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