Gordons Projects

--> Projects Top-Level GIT

96d6255f7930f5e75daaf0a3d77ade5ba9cd5c04
[wiringPi] / 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 #include <drcSerial.h>
54
55 #include "extensions.h"
56
57 extern int wiringPiDebug ;
58
59 #ifndef TRUE
60 #  define       TRUE    (1==1)
61 #  define       FALSE   (1==2)
62 #endif
63
64 // Local structure to hold details
65
66 struct extensionFunctionStruct
67 {
68   const char *name ;
69   int   (*function)(char *progName, int pinBase, char *params) ;
70 } ;
71
72
73 /*
74  * extractInt:
75  *      Check & return an integer at the given location (prefixed by a :)
76  *********************************************************************************
77  */
78
79 static char *extractInt (char *progName, char *p, int *num)
80 {
81   if (*p != ':')
82   {
83     fprintf (stderr, "%s: colon expected\n", progName) ;
84     return NULL ;
85   }
86
87   ++p ;
88
89   if (!isdigit (*p))
90   {
91     fprintf (stderr, "%s: digit expected\n", progName) ;
92     return NULL ;
93   }
94
95   *num = strtol (p, NULL, 0) ;
96   while (isdigit (*p))
97     ++p ;
98
99   return p ;
100 }
101
102
103 /*
104  * extractStr:
105  *      Check & return a string at the given location (prefixed by a :)
106  *********************************************************************************
107  */
108
109 static char *extractStr (char *progName, char *p, char **str)
110 {
111   char *q, *r ;
112
113   if (*p != ':')
114   {
115     fprintf (stderr, "%s: colon expected\n", progName) ;
116     return NULL ;
117   }
118
119   ++p ;
120
121   if (!isprint (*p))
122   {
123     fprintf (stderr, "%s: character expected\n", progName) ;
124     return NULL ;
125   }
126
127   q = p ;
128   while ((*q != 0) && (*q != ':'))
129     ++q ;
130
131   *str = r = calloc (q - p + 2, 1) ;    // Zeros it
132
133   while (p != q)
134     *r++ = *p++ ;
135     
136   return p ;
137 }
138
139
140
141 /*
142  * doExtensionMcp23008:
143  *      MCP23008 - 8-bit I2C GPIO expansion chip
144  *      mcp23002:base:i2cAddr
145  *********************************************************************************
146  */
147
148 static int doExtensionMcp23008 (char *progName, int pinBase, char *params)
149 {
150   int i2c ;
151
152   if ((params = extractInt (progName, params, &i2c)) == NULL)
153     return FALSE ;
154
155   if ((i2c < 0x03) || (i2c > 0x77))
156   {
157     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
158     return FALSE ;
159   }
160
161   mcp23008Setup (pinBase, i2c) ;
162
163   return TRUE ;
164 }
165
166
167 /*
168  * doExtensionMcp23016:
169  *      MCP230016- 16-bit I2C GPIO expansion chip
170  *      mcp23016:base:i2cAddr
171  *********************************************************************************
172  */
173
174 static int doExtensionMcp23016 (char *progName, int pinBase, char *params)
175 {
176   int i2c ;
177
178   if ((params = extractInt (progName, params, &i2c)) == NULL)
179     return FALSE ;
180
181   if ((i2c < 0x03) || (i2c > 0x77))
182   {
183     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
184     return FALSE ;
185   }
186
187   mcp23016Setup (pinBase, i2c) ;
188
189   return TRUE ;
190 }
191
192
193 /*
194  * doExtensionMcp23017:
195  *      MCP230017- 16-bit I2C GPIO expansion chip
196  *      mcp23017:base:i2cAddr
197  *********************************************************************************
198  */
199
200 static int doExtensionMcp23017 (char *progName, int pinBase, char *params)
201 {
202   int i2c ;
203
204   if ((params = extractInt (progName, params, &i2c)) == NULL)
205     return FALSE ;
206
207   if ((i2c < 0x03) || (i2c > 0x77))
208   {
209     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
210     return FALSE ;
211   }
212
213   mcp23017Setup (pinBase, i2c) ;
214
215   return TRUE ;
216 }
217
218
219 /*
220  * doExtensionMcp23s08:
221  *      MCP23s08 - 8-bit SPI GPIO expansion chip
222  *      mcp23s08:base:spi:port
223  *********************************************************************************
224  */
225
226 static int doExtensionMcp23s08 (char *progName, int pinBase, char *params)
227 {
228   int spi, port ;
229
230   if ((params = extractInt (progName, params, &spi)) == NULL)
231     return FALSE ;
232
233   if ((spi < 0) || (spi > 1))
234   {
235     fprintf (stderr, "%s: SPI address (%d) out of range\n", progName, spi) ;
236     return FALSE ;
237   }
238
239   if ((params = extractInt (progName, params, &port)) == NULL)
240     return FALSE ;
241
242   if ((port < 0) || (port > 7))
243   {
244     fprintf (stderr, "%s: port address (%d) out of range\n", progName, port) ;
245     return FALSE ;
246   }
247
248   mcp23s08Setup (pinBase, spi, port) ;
249
250   return TRUE ;
251 }
252
253
254 /*
255  * doExtensionMcp23s17:
256  *      MCP23s17 - 16-bit SPI GPIO expansion chip
257  *      mcp23s17:base:spi:port
258  *********************************************************************************
259  */
260
261 static int doExtensionMcp23s17 (char *progName, int pinBase, char *params)
262 {
263   int spi, port ;
264
265   if ((params = extractInt (progName, params, &spi)) == NULL)
266     return FALSE ;
267
268   if ((spi < 0) || (spi > 1))
269   {
270     fprintf (stderr, "%s: SPI address (%d) out of range\n", progName, spi) ;
271     return FALSE ;
272   }
273
274   if ((params = extractInt (progName, params, &port)) == NULL)
275     return FALSE ;
276
277   if ((port < 0) || (port > 7))
278   {
279     fprintf (stderr, "%s: port address (%d) out of range\n", progName, port) ;
280     return FALSE ;
281   }
282
283   mcp23s17Setup (pinBase, spi, port) ;
284
285   return TRUE ;
286 }
287
288
289 /*
290  * doExtensionSr595:
291  *      Shift Register 74x595
292  *      sr595:base:pins:data:clock:latch
293  *********************************************************************************
294  */
295
296 static int doExtensionSr595 (char *progName, int pinBase, char *params)
297 {
298   int pins, data, clock, latch ;
299
300 // Extract pins
301
302   if ((params = extractInt (progName, params, &pins)) == NULL)
303     return FALSE ;
304
305   if ((pins < 8) || (pins > 32))
306   {
307     fprintf (stderr, "%s: pin count (%d) out of range - 8-32 expected.\n", progName, pins) ;
308     return FALSE ;
309   }
310
311   if ((params = extractInt (progName, params, &data)) == NULL)
312     return FALSE ;
313
314   if ((params = extractInt (progName, params, &clock)) == NULL)
315     return FALSE ;
316
317   if ((params = extractInt (progName, params, &latch)) == NULL)
318     return FALSE ;
319
320   sr595Setup (pinBase, pins, data, clock, latch) ;
321
322   return TRUE ;
323 }
324
325
326 /*
327  * doExtensionPcf8574:
328  *      Digital IO (Crude!)
329  *      pcf8574:base:i2cAddr
330  *********************************************************************************
331  */
332
333 static int doExtensionPcf8574 (char *progName, int pinBase, char *params)
334 {
335   int i2c ;
336
337   if ((params = extractInt (progName, params, &i2c)) == NULL)
338     return FALSE ;
339
340   if ((i2c < 0x03) || (i2c > 0x77))
341   {
342     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
343     return FALSE ;
344   }
345
346   pcf8574Setup (pinBase, i2c) ;
347
348   return TRUE ;
349 }
350
351
352 /*
353  * doExtensionPcf8591:
354  *      Analog IO
355  *      pcf8591:base:i2cAddr
356  *********************************************************************************
357  */
358
359 static int doExtensionPcf8591 (char *progName, int pinBase, char *params)
360 {
361   int i2c ;
362
363   if ((params = extractInt (progName, params, &i2c)) == NULL)
364     return FALSE ;
365
366   if ((i2c < 0x03) || (i2c > 0x77))
367   {
368     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
369     return FALSE ;
370   }
371
372   pcf8591Setup (pinBase, i2c) ;
373
374   return TRUE ;
375 }
376
377
378 /*
379  * doExtensionMax31855:
380  *      Analog IO
381  *      max31855:base:spiChan
382  *********************************************************************************
383  */
384
385 static int doExtensionMax31855 (char *progName, int pinBase, char *params)
386 {
387   int spi ;
388
389   if ((params = extractInt (progName, params, &spi)) == NULL)
390     return FALSE ;
391
392   if ((spi < 0) || (spi > 1))
393   {
394     fprintf (stderr, "%s: SPI channel (%d) out of range\n", progName, spi) ;
395     return FALSE ;
396   }
397
398   max31855Setup (pinBase, spi) ;
399
400   return TRUE ;
401 }
402
403
404 /*
405  * doExtensionMcp3002:
406  *      Analog IO
407  *      mcp3002:base:spiChan
408  *********************************************************************************
409  */
410
411 static int doExtensionMcp3002 (char *progName, int pinBase, char *params)
412 {
413   int spi ;
414
415   if ((params = extractInt (progName, params, &spi)) == NULL)
416     return FALSE ;
417
418   if ((spi < 0) || (spi > 1))
419   {
420     fprintf (stderr, "%s: SPI channel (%d) out of range\n", progName, spi) ;
421     return FALSE ;
422   }
423
424   mcp3002Setup (pinBase, spi) ;
425
426   return TRUE ;
427 }
428
429
430 /*
431  * doExtensionMcp3004:
432  *      Analog IO
433  *      mcp3004:base:spiChan
434  *********************************************************************************
435  */
436
437 static int doExtensionMcp3004 (char *progName, int pinBase, char *params)
438 {
439   int spi ;
440
441   if ((params = extractInt (progName, params, &spi)) == NULL)
442     return FALSE ;
443
444   if ((spi < 0) || (spi > 1))
445   {
446     fprintf (stderr, "%s: SPI channel (%d) out of range\n", progName, spi) ;
447     return FALSE ;
448   }
449
450   mcp3004Setup (pinBase, spi) ;
451
452   return TRUE ;
453 }
454
455
456 /*
457  * doExtensionMax5322:
458  *      Analog O
459  *      max5322:base:spiChan
460  *********************************************************************************
461  */
462
463 static int doExtensionMax5322 (char *progName, int pinBase, char *params)
464 {
465   int spi ;
466
467   if ((params = extractInt (progName, params, &spi)) == NULL)
468     return FALSE ;
469
470   if ((spi < 0) || (spi > 1))
471   {
472     fprintf (stderr, "%s: SPI channel (%d) out of range\n", progName, spi) ;
473     return FALSE ;
474   }
475
476   max5322Setup (pinBase, spi) ;
477
478   return TRUE ;
479 }
480
481
482 /*
483  * doExtensionMcp4802:
484  *      Analog IO
485  *      mcp4802:base:spiChan
486  *********************************************************************************
487  */
488
489 static int doExtensionMcp4802 (char *progName, int pinBase, char *params)
490 {
491   int spi ;
492
493   if ((params = extractInt (progName, params, &spi)) == NULL)
494     return FALSE ;
495
496   if ((spi < 0) || (spi > 1))
497   {
498     fprintf (stderr, "%s: SPI channel (%d) out of range\n", progName, spi) ;
499     return FALSE ;
500   }
501
502   mcp4802Setup (pinBase, spi) ;
503
504   return TRUE ;
505 }
506
507
508 /*
509  * doExtensionSn3218:
510  *      Analog Output (LED Driver)
511  *      sn3218:base
512  *********************************************************************************
513  */
514
515 static int doExtensionSn3218 (char *progName, int pinBase, char *params)
516 {
517   sn3218Setup (pinBase) ;
518   return TRUE ;
519 }
520
521
522 /*
523  * doExtensionMcp3422:
524  *      Analog IO
525  *      mcp3422:base:i2cAddr
526  *********************************************************************************
527  */
528
529 static int doExtensionMcp3422 (char *progName, int pinBase, char *params)
530 {
531   int i2c, sampleRate, gain ;
532
533   if ((params = extractInt (progName, params, &i2c)) == NULL)
534     return FALSE ;
535
536   if ((i2c < 0x03) || (i2c > 0x77))
537   {
538     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
539     return FALSE ;
540   }
541
542   if ((params = extractInt (progName, params, &sampleRate)) == NULL)
543     return FALSE ;
544
545   if ((sampleRate < 0) || (sampleRate > 3))
546   {
547     fprintf (stderr, "%s: sample rate (%d) out of range\n", progName, sampleRate) ;
548     return FALSE ;
549   }
550
551   if ((params = extractInt (progName, params, &gain)) == NULL)
552     return FALSE ;
553
554   if ((gain < 0) || (gain > 3))
555   {
556     fprintf (stderr, "%s: gain (%d) out of range\n", progName, gain) ;
557     return FALSE ;
558   }
559
560   mcp3422Setup (pinBase, i2c, sampleRate, gain) ;
561
562   return TRUE ;
563 }
564
565 /*
566  * doExtensionDrcS:
567  *      Interface to a DRC Serial system
568  *      drcs:base:pins:serialPort:baud
569  *********************************************************************************
570  */
571
572 static int doExtensionDrcS (char *progName, int pinBase, char *params)
573 {
574   char *port ;
575   int pins, baud ;
576
577   if ((params = extractInt (progName, params, &pins)) == NULL)
578     return FALSE ;
579
580   if ((pins < 1) || (pins > 100))
581   {
582     fprintf (stderr, "%s: pins (%d) out of range (2-100)\n", progName, pins) ;
583     return FALSE ;
584   }
585   
586   if ((params = extractStr (progName, params, &port)) == NULL)
587     return FALSE ;
588
589   if (strlen (port) == 0)
590   {
591     fprintf (stderr, "%s: serial port device name required\n", progName) ;
592     return FALSE ;
593   }
594
595   if ((params = extractInt (progName, params, &baud)) == NULL)
596     return FALSE ;
597
598   if ((baud < 1) || (baud > 4000000))
599   {
600     fprintf (stderr, "%s: baud rate (%d) out of range\n", progName, baud) ;
601     return FALSE ;
602   }
603
604   drcSetupSerial (pinBase, pins, port, baud) ;
605
606   return TRUE ;
607 }
608
609
610
611 /*
612  * Function list
613  *********************************************************************************
614  */
615
616 struct extensionFunctionStruct extensionFunctions [] = 
617 {
618   { "mcp23008",         &doExtensionMcp23008    },
619   { "mcp23016",         &doExtensionMcp23016    },
620   { "mcp23017",         &doExtensionMcp23017    },
621   { "mcp23s08",         &doExtensionMcp23s08    },
622   { "mcp23s17",         &doExtensionMcp23s17    },
623   { "sr595",            &doExtensionSr595       },
624   { "pcf8574",          &doExtensionPcf8574     },
625   { "pcf8591",          &doExtensionPcf8591     },
626   { "mcp3002",          &doExtensionMcp3002     },
627   { "mcp3004",          &doExtensionMcp3004     },
628   { "mcp4802",          &doExtensionMcp4802     },
629   { "mcp3422",          &doExtensionMcp3422     },
630   { "max31855",         &doExtensionMax31855    },
631   { "max5322",          &doExtensionMax5322     },
632   { "sn3218",           &doExtensionSn3218      },
633   { "drcs",             &doExtensionDrcS        },
634   { NULL,               NULL                    },
635 } ;
636
637
638 /*
639  * doExtension:
640  *      Load in a wiringPi extension
641  *********************************************************************************
642  */
643
644 int doExtension (char *progName, char *extensionData)
645 {
646   char *p ;
647   char *extension = extensionData ;
648   struct extensionFunctionStruct *extensionFn ;
649   int pinBase = 0 ;
650
651 // Get the extension extension name by finding the first colon
652
653   p = extension ;
654   while (*p != ':')
655   {
656     if (!*p)    // ran out of characters
657     {
658       fprintf (stderr, "%s: extension name not terminated by a colon\n", progName) ;
659       return FALSE ;
660     }
661     ++p ;
662   }
663
664   *p++ = 0 ;
665
666   if (!isdigit (*p))
667   {
668     fprintf (stderr, "%s: pinBase number expected after extension name\n", progName) ;
669     return FALSE ;
670   }
671
672   while (isdigit (*p))
673   {
674     if (pinBase > 1000000000)
675     {
676       fprintf (stderr, "%s: pinBase too large\n", progName) ;
677       return FALSE ;
678     }
679
680     pinBase = pinBase * 10 + (*p - '0') ;
681     ++p ;
682   }
683
684   if (pinBase < 64)
685   {
686     fprintf (stderr, "%s: pinBase (%d) too small. Minimum is 64.\n", progName, pinBase) ;
687     return FALSE ;
688   }
689
690 // Search for extensions:
691
692   for (extensionFn = extensionFunctions ; extensionFn->name != NULL ; ++extensionFn)
693   {
694     if (strcmp (extensionFn->name, extension) == 0)
695       return extensionFn->function (progName, pinBase, p) ;
696   }
697
698   fprintf (stderr, "%s: extension %s not found\n", progName, extension) ;
699   return FALSE ;
700 }