chiark / gitweb /
Added in the SN3218 LED controller IC - as used in the PiGlow
[wiringPi.git] / gpio / extensions.c
1 /*
2  * extensions.c:
3  *      Part of the GPIO program to test, peek, poke and otherwise
4  *      noodle with the GPIO hardware on the Raspberry Pi.
5  *      Copyright (c) 2012-2013 Gordon Henderson
6  ***********************************************************************
7  * This file is part of wiringPi:
8  *      https://projects.drogon.net/raspberry-pi/wiringpi/
9  *
10  *    wiringPi is free software: you can redistribute it and/or modify
11  *    it under the terms of the GNU Lesser General Public License as published by
12  *    the Free Software Foundation, either version 3 of the License, or
13  *    (at your option) any later version.
14  *
15  *    wiringPi is distributed in the hope that it will be useful,
16  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *    GNU Lesser General Public License for more details.
19  *
20  *    You should have received a copy of the GNU Lesser General Public License
21  *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
22  ***********************************************************************
23  */
24
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdint.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <sys/types.h>
34 #include <fcntl.h>
35
36 #include <wiringPi.h>
37
38 #include <mcp23008.h>
39 #include <mcp23016.h>
40 #include <mcp23017.h>
41 #include <mcp23s08.h>
42 #include <mcp23s17.h>
43 #include <sr595.h>
44 #include <pcf8591.h>
45 #include <pcf8574.h>
46 #include <max31855.h>
47 #include <max5322.h>
48 #include <mcp3002.h>
49 #include <mcp3004.h>
50 #include <mcp4802.h>
51 #include <mcp3422.h>
52 #include <sn3218.h>
53
54 #include "extensions.h"
55
56 extern int wiringPiDebug ;
57
58 #ifndef TRUE
59 #  define       TRUE    (1==1)
60 #  define       FALSE   (1==2)
61 #endif
62
63 // Local structure to hold details
64
65 struct extensionFunctionStruct
66 {
67   const char *name ;
68   int   (*function)(char *progName, int pinBase, char *params) ;
69 } ;
70
71
72 /*
73  * extractInt:
74  *      Check & return an integer at the given location (prefixed by a :)
75  *********************************************************************************
76  */
77
78 static char *extractInt (char *progName, char *p, int *num)
79 {
80   if (*p != ':')
81   {
82     fprintf (stderr, "%s: colon expected\n", progName) ;
83     return NULL ;
84   }
85
86   ++p ;
87
88   if (!isdigit (*p))
89   {
90     fprintf (stderr, "%s: digit expected\n", progName) ;
91     return NULL ;
92   }
93
94   *num = strtol (p, NULL, 0) ;
95   while (isdigit (*p))
96     ++p ;
97
98   return p ;
99 }
100
101
102
103 /*
104  * doExtensionMcp23008:
105  *      MCP23008 - 8-bit I2C GPIO expansion chip
106  *      mcp23002:base:i2cAddr
107  *********************************************************************************
108  */
109
110 static int doExtensionMcp23008 (char *progName, int pinBase, char *params)
111 {
112   int i2c ;
113
114   if ((params = extractInt (progName, params, &i2c)) == NULL)
115     return FALSE ;
116
117   if ((i2c < 0x03) || (i2c > 0x77))
118   {
119     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
120     return FALSE ;
121   }
122
123   mcp23008Setup (pinBase, i2c) ;
124
125   return TRUE ;
126 }
127
128
129 /*
130  * doExtensionMcp23016:
131  *      MCP230016- 16-bit I2C GPIO expansion chip
132  *      mcp23016:base:i2cAddr
133  *********************************************************************************
134  */
135
136 static int doExtensionMcp23016 (char *progName, int pinBase, char *params)
137 {
138   int i2c ;
139
140   if ((params = extractInt (progName, params, &i2c)) == NULL)
141     return FALSE ;
142
143   if ((i2c < 0x03) || (i2c > 0x77))
144   {
145     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
146     return FALSE ;
147   }
148
149   mcp23016Setup (pinBase, i2c) ;
150
151   return TRUE ;
152 }
153
154
155 /*
156  * doExtensionMcp23017:
157  *      MCP230017- 16-bit I2C GPIO expansion chip
158  *      mcp23017:base:i2cAddr
159  *********************************************************************************
160  */
161
162 static int doExtensionMcp23017 (char *progName, int pinBase, char *params)
163 {
164   int i2c ;
165
166   if ((params = extractInt (progName, params, &i2c)) == NULL)
167     return FALSE ;
168
169   if ((i2c < 0x03) || (i2c > 0x77))
170   {
171     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
172     return FALSE ;
173   }
174
175   mcp23017Setup (pinBase, i2c) ;
176
177   return TRUE ;
178 }
179
180
181 /*
182  * doExtensionMcp23s08:
183  *      MCP23s08 - 8-bit SPI GPIO expansion chip
184  *      mcp23s08:base:spi:port
185  *********************************************************************************
186  */
187
188 static int doExtensionMcp23s08 (char *progName, int pinBase, char *params)
189 {
190   int spi, port ;
191
192   if ((params = extractInt (progName, params, &spi)) == NULL)
193     return FALSE ;
194
195   if ((spi < 0) || (spi > 1))
196   {
197     fprintf (stderr, "%s: SPI address (%d) out of range\n", progName, spi) ;
198     return FALSE ;
199   }
200
201   if ((params = extractInt (progName, params, &port)) == NULL)
202     return FALSE ;
203
204   if ((port < 0) || (port > 7))
205   {
206     fprintf (stderr, "%s: port address (%d) out of range\n", progName, port) ;
207     return FALSE ;
208   }
209
210   mcp23s08Setup (pinBase, spi, port) ;
211
212   return TRUE ;
213 }
214
215
216 /*
217  * doExtensionMcp23s17:
218  *      MCP23s17 - 16-bit SPI GPIO expansion chip
219  *      mcp23s17:base:spi:port
220  *********************************************************************************
221  */
222
223 static int doExtensionMcp23s17 (char *progName, int pinBase, char *params)
224 {
225   int spi, port ;
226
227   if ((params = extractInt (progName, params, &spi)) == NULL)
228     return FALSE ;
229
230   if ((spi < 0) || (spi > 1))
231   {
232     fprintf (stderr, "%s: SPI address (%d) out of range\n", progName, spi) ;
233     return FALSE ;
234   }
235
236   if ((params = extractInt (progName, params, &port)) == NULL)
237     return FALSE ;
238
239   if ((port < 0) || (port > 7))
240   {
241     fprintf (stderr, "%s: port address (%d) out of range\n", progName, port) ;
242     return FALSE ;
243   }
244
245   mcp23s17Setup (pinBase, spi, port) ;
246
247   return TRUE ;
248 }
249
250
251 /*
252  * doExtensionSr595:
253  *      Shift Register 74x595
254  *      sr595:base:pins:data:clock:latch
255  *********************************************************************************
256  */
257
258 static int doExtensionSr595 (char *progName, int pinBase, char *params)
259 {
260   int pins, data, clock, latch ;
261
262 // Extract pins
263
264   if ((params = extractInt (progName, params, &pins)) == NULL)
265     return FALSE ;
266
267   if ((pins < 8) || (pins > 32))
268   {
269     fprintf (stderr, "%s: pin count (%d) out of range - 8-32 expected.\n", progName, pins) ;
270     return FALSE ;
271   }
272
273   if ((params = extractInt (progName, params, &data)) == NULL)
274     return FALSE ;
275
276   if ((params = extractInt (progName, params, &clock)) == NULL)
277     return FALSE ;
278
279   if ((params = extractInt (progName, params, &latch)) == NULL)
280     return FALSE ;
281
282   sr595Setup (pinBase, pins, data, clock, latch) ;
283
284   return TRUE ;
285 }
286
287
288 /*
289  * doExtensionPcf8574:
290  *      Digital IO (Crude!)
291  *      pcf8574:base:i2cAddr
292  *********************************************************************************
293  */
294
295 static int doExtensionPcf8574 (char *progName, int pinBase, char *params)
296 {
297   int i2c ;
298
299   if ((params = extractInt (progName, params, &i2c)) == NULL)
300     return FALSE ;
301
302   if ((i2c < 0x03) || (i2c > 0x77))
303   {
304     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
305     return FALSE ;
306   }
307
308   pcf8574Setup (pinBase, i2c) ;
309
310   return TRUE ;
311 }
312
313
314 /*
315  * doExtensionPcf8591:
316  *      Analog IO
317  *      pcf8591:base:i2cAddr
318  *********************************************************************************
319  */
320
321 static int doExtensionPcf8591 (char *progName, int pinBase, char *params)
322 {
323   int i2c ;
324
325   if ((params = extractInt (progName, params, &i2c)) == NULL)
326     return FALSE ;
327
328   if ((i2c < 0x03) || (i2c > 0x77))
329   {
330     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
331     return FALSE ;
332   }
333
334   pcf8591Setup (pinBase, i2c) ;
335
336   return TRUE ;
337 }
338
339
340 /*
341  * doExtensionMax31855:
342  *      Analog IO
343  *      max31855:base:spiChan
344  *********************************************************************************
345  */
346
347 static int doExtensionMax31855 (char *progName, int pinBase, char *params)
348 {
349   int spi ;
350
351   if ((params = extractInt (progName, params, &spi)) == NULL)
352     return FALSE ;
353
354   if ((spi < 0) || (spi > 1))
355   {
356     fprintf (stderr, "%s: SPI channel (%d) out of range\n", progName, spi) ;
357     return FALSE ;
358   }
359
360   max31855Setup (pinBase, spi) ;
361
362   return TRUE ;
363 }
364
365
366 /*
367  * doExtensionMcp3002:
368  *      Analog IO
369  *      mcp3002:base:spiChan
370  *********************************************************************************
371  */
372
373 static int doExtensionMcp3002 (char *progName, int pinBase, char *params)
374 {
375   int spi ;
376
377   if ((params = extractInt (progName, params, &spi)) == NULL)
378     return FALSE ;
379
380   if ((spi < 0) || (spi > 1))
381   {
382     fprintf (stderr, "%s: SPI channel (%d) out of range\n", progName, spi) ;
383     return FALSE ;
384   }
385
386   mcp3002Setup (pinBase, spi) ;
387
388   return TRUE ;
389 }
390
391
392 /*
393  * doExtensionMcp3004:
394  *      Analog IO
395  *      mcp3004:base:spiChan
396  *********************************************************************************
397  */
398
399 static int doExtensionMcp3004 (char *progName, int pinBase, char *params)
400 {
401   int spi ;
402
403   if ((params = extractInt (progName, params, &spi)) == NULL)
404     return FALSE ;
405
406   if ((spi < 0) || (spi > 1))
407   {
408     fprintf (stderr, "%s: SPI channel (%d) out of range\n", progName, spi) ;
409     return FALSE ;
410   }
411
412   mcp3004Setup (pinBase, spi) ;
413
414   return TRUE ;
415 }
416
417
418 /*
419  * doExtensionMax5322:
420  *      Analog O
421  *      max5322:base:spiChan
422  *********************************************************************************
423  */
424
425 static int doExtensionMax5322 (char *progName, int pinBase, char *params)
426 {
427   int spi ;
428
429   if ((params = extractInt (progName, params, &spi)) == NULL)
430     return FALSE ;
431
432   if ((spi < 0) || (spi > 1))
433   {
434     fprintf (stderr, "%s: SPI channel (%d) out of range\n", progName, spi) ;
435     return FALSE ;
436   }
437
438   max5322Setup (pinBase, spi) ;
439
440   return TRUE ;
441 }
442
443
444 /*
445  * doExtensionMcp4802:
446  *      Analog IO
447  *      mcp4802:base:spiChan
448  *********************************************************************************
449  */
450
451 static int doExtensionMcp4802 (char *progName, int pinBase, char *params)
452 {
453   int spi ;
454
455   if ((params = extractInt (progName, params, &spi)) == NULL)
456     return FALSE ;
457
458   if ((spi < 0) || (spi > 1))
459   {
460     fprintf (stderr, "%s: SPI channel (%d) out of range\n", progName, spi) ;
461     return FALSE ;
462   }
463
464   mcp4802Setup (pinBase, spi) ;
465
466   return TRUE ;
467 }
468
469
470 /*
471  * doExtensionSn3218:
472  *      Analog Output (LED Driver)
473  *      sn3218:base
474  *********************************************************************************
475  */
476
477 static int doExtensionSn3218 (char *progName, int pinBase, char *params)
478 {
479   sn3218Setup (pinBase) ;
480   return TRUE ;
481 }
482
483
484 /*
485  * doExtensionMcp3422:
486  *      Analog IO
487  *      mcp3422:base:i2cAddr
488  *********************************************************************************
489  */
490
491 static int doExtensionMcp3422 (char *progName, int pinBase, char *params)
492 {
493   int i2c, sampleRate, gain ;
494
495   if ((params = extractInt (progName, params, &i2c)) == NULL)
496     return FALSE ;
497
498   if ((i2c < 0x03) || (i2c > 0x77))
499   {
500     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
501     return FALSE ;
502   }
503
504   if ((params = extractInt (progName, params, &sampleRate)) == NULL)
505     return FALSE ;
506
507   if ((sampleRate < 0) || (sampleRate > 3))
508   {
509     fprintf (stderr, "%s: sample rate (%d) out of range\n", progName, sampleRate) ;
510     return FALSE ;
511   }
512
513   if ((params = extractInt (progName, params, &gain)) == NULL)
514     return FALSE ;
515
516   if ((gain < 0) || (gain > 3))
517   {
518     fprintf (stderr, "%s: gain (%d) out of range\n", progName, gain) ;
519     return FALSE ;
520   }
521
522   mcp3422Setup (pinBase, i2c, sampleRate, gain) ;
523
524   return TRUE ;
525 }
526
527
528 /*
529  * Function list
530  *********************************************************************************
531  */
532
533 struct extensionFunctionStruct extensionFunctions [] = 
534 {
535   { "mcp23008",         &doExtensionMcp23008    },
536   { "mcp23016",         &doExtensionMcp23016    },
537   { "mcp23017",         &doExtensionMcp23017    },
538   { "mcp23s08",         &doExtensionMcp23s08    },
539   { "mcp23s17",         &doExtensionMcp23s17    },
540   { "sr595",            &doExtensionSr595       },
541   { "pcf8574",          &doExtensionPcf8574     },
542   { "pcf8591",          &doExtensionPcf8591     },
543   { "mcp3002",          &doExtensionMcp3002     },
544   { "mcp3004",          &doExtensionMcp3004     },
545   { "mcp4802",          &doExtensionMcp4802     },
546   { "mcp3422",          &doExtensionMcp3422     },
547   { "max31855",         &doExtensionMax31855    },
548   { "max5322",          &doExtensionMax5322     },
549   { "sn3218",           &doExtensionSn3218      },
550   { NULL,               NULL                    },
551 } ;
552
553
554 /*
555  * doExtension:
556  *      Load in a wiringPi extension
557  *********************************************************************************
558  */
559
560 int doExtension (char *progName, char *extensionData)
561 {
562   char *p ;
563   char *extension = extensionData ;
564   struct extensionFunctionStruct *extensionFn ;
565   int pinBase = 0 ;
566
567 // Get the extension extension name by finding the first colon
568
569   p = extension ;
570   while (*p != ':')
571   {
572     if (!*p)    // ran out of characters
573     {
574       fprintf (stderr, "%s: extension name not terminated by a colon\n", progName) ;
575       return FALSE ;
576     }
577     ++p ;
578   }
579
580   *p++ = 0 ;
581
582   if (!isdigit (*p))
583   {
584     fprintf (stderr, "%s: pinBase number expected after extension name\n", progName) ;
585     return FALSE ;
586   }
587
588   while (isdigit (*p))
589   {
590     if (pinBase > 1000000000)
591     {
592       fprintf (stderr, "%s: pinBase too large\n", progName) ;
593       return FALSE ;
594     }
595
596     pinBase = pinBase * 10 + (*p - '0') ;
597     ++p ;
598   }
599
600   if (pinBase < 64)
601   {
602     fprintf (stderr, "%s: pinBase (%d) too small. Minimum is 64.\n", progName, pinBase) ;
603     return FALSE ;
604   }
605
606 // Search for extensions:
607
608   for (extensionFn = extensionFunctions ; extensionFn->name != NULL ; ++extensionFn)
609   {
610     if (strcmp (extensionFn->name, extension) == 0)
611       return extensionFn->function (progName, pinBase, p) ;
612   }
613
614   fprintf (stderr, "%s: extension %s not found\n", progName, extension) ;
615   return FALSE ;
616 }