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