Gordons Projects

--> Projects Top-Level GIT

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