chiark / gitweb /
dae1eacec5239040505b18e08466005ded4196c4
[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
47 #include "extensions.h"
48
49 extern int wiringPiDebug ;
50
51 #ifndef TRUE
52 #  define       TRUE    (1==1)
53 #  define       FALSE   (1==2)
54 #endif
55
56 // Local structure to hold details
57
58 struct extensionFunctionStruct
59 {
60   const char *name ;
61   int   (*function)(char *progName, int pinBase, char *params) ;
62 } ;
63
64
65 /*
66  * extractInt:
67  *      Check & return an integer at the given location (prefixed by a :)
68  *********************************************************************************
69  */
70
71 static char *extractInt (char *progName, char *p, int *num)
72 {
73   if (*p != ':')
74   {
75     fprintf (stderr, "%s: colon expected\n", progName) ;
76     return NULL ;
77   }
78
79   ++p ;
80
81   if (!isdigit (*p))
82   {
83     fprintf (stderr, "%s: digit expected\n", progName) ;
84     return NULL ;
85   }
86
87   *num = strtol (p, NULL, 0) ;
88   while (isdigit (*p))
89     ++p ;
90
91   return p ;
92 }
93
94
95
96 /*
97  * doExtensionMcp23008:
98  *      MCP23008 - 8-bit I2C GPIO expansion chip
99  *      mcp23002:base:i2cAddr
100  *********************************************************************************
101  */
102
103 static int doExtensionMcp23008 (char *progName, int pinBase, char *params)
104 {
105   int i2c ;
106
107   if ((params = extractInt (progName, params, &i2c)) == NULL)
108     return FALSE ;
109
110   if ((i2c < 0x03) || (i2c > 0x77))
111   {
112     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
113     return FALSE ;
114   }
115
116   mcp23008Setup (pinBase, i2c) ;
117
118   return TRUE ;
119 }
120
121
122 /*
123  * doExtensionMcp23016:
124  *      MCP230016- 16-bit I2C GPIO expansion chip
125  *      mcp23016:base:i2cAddr
126  *********************************************************************************
127  */
128
129 static int doExtensionMcp23016 (char *progName, int pinBase, char *params)
130 {
131   int i2c ;
132
133   if ((params = extractInt (progName, params, &i2c)) == NULL)
134     return FALSE ;
135
136   if ((i2c < 0x03) || (i2c > 0x77))
137   {
138     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
139     return FALSE ;
140   }
141
142   mcp23016Setup (pinBase, i2c) ;
143
144   return TRUE ;
145 }
146
147
148 /*
149  * doExtensionMcp23017:
150  *      MCP230017- 16-bit I2C GPIO expansion chip
151  *      mcp23017:base:i2cAddr
152  *********************************************************************************
153  */
154
155 static int doExtensionMcp23017 (char *progName, int pinBase, char *params)
156 {
157   int i2c ;
158
159   if ((params = extractInt (progName, params, &i2c)) == NULL)
160     return FALSE ;
161
162   if ((i2c < 0x03) || (i2c > 0x77))
163   {
164     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
165     return FALSE ;
166   }
167
168   mcp23017Setup (pinBase, i2c) ;
169
170   return TRUE ;
171 }
172
173
174 /*
175  * doExtensionMcp23s08:
176  *      MCP23s08 - 8-bit SPI GPIO expansion chip
177  *      mcp23s08:base:spi:port
178  *********************************************************************************
179  */
180
181 static int doExtensionMcp23s08 (char *progName, int pinBase, char *params)
182 {
183   int spi, port ;
184
185   if ((params = extractInt (progName, params, &spi)) == NULL)
186     return FALSE ;
187
188   if ((spi < 0) || (spi > 1))
189   {
190     fprintf (stderr, "%s: SPI address (%d) out of range\n", progName, spi) ;
191     return FALSE ;
192   }
193
194   if ((params = extractInt (progName, params, &port)) == NULL)
195     return FALSE ;
196
197   if ((port < 0) || (port > 7))
198   {
199     fprintf (stderr, "%s: port address (%d) out of range\n", progName, port) ;
200     return FALSE ;
201   }
202
203   mcp23s08Setup (pinBase, spi, port) ;
204
205   return TRUE ;
206 }
207
208
209 /*
210  * doExtensionMcp23s17:
211  *      MCP23s17 - 16-bit SPI GPIO expansion chip
212  *      mcp23s17:base:spi:port
213  *********************************************************************************
214  */
215
216 static int doExtensionMcp23s17 (char *progName, int pinBase, char *params)
217 {
218   int spi, port ;
219
220   if ((params = extractInt (progName, params, &spi)) == NULL)
221     return FALSE ;
222
223   if ((spi < 0) || (spi > 1))
224   {
225     fprintf (stderr, "%s: SPI address (%d) out of range\n", progName, spi) ;
226     return FALSE ;
227   }
228
229   if ((params = extractInt (progName, params, &port)) == NULL)
230     return FALSE ;
231
232   if ((port < 0) || (port > 7))
233   {
234     fprintf (stderr, "%s: port address (%d) out of range\n", progName, port) ;
235     return FALSE ;
236   }
237
238   mcp23s17Setup (pinBase, spi, port) ;
239
240   return TRUE ;
241 }
242
243
244 /*
245  * doExtensionSr595:
246  *      Shift Register 74x595
247  *      sr595:base:pins:data:clock:latch
248  *********************************************************************************
249  */
250
251 static int doExtensionSr595 (char *progName, int pinBase, char *params)
252 {
253   int pins, data, clock, latch ;
254
255 // Extract pins
256
257   if ((params = extractInt (progName, params, &pins)) == NULL)
258     return FALSE ;
259
260   if ((pins < 8) || (pins > 32))
261   {
262     fprintf (stderr, "%s: pin count (%d) out of range - 8-32 expected.\n", progName, pins) ;
263     return FALSE ;
264   }
265
266   if ((params = extractInt (progName, params, &data)) == NULL)
267     return FALSE ;
268
269   if ((params = extractInt (progName, params, &clock)) == NULL)
270     return FALSE ;
271
272   if ((params = extractInt (progName, params, &latch)) == NULL)
273     return FALSE ;
274
275   sr595Setup (pinBase, pins, data, clock, latch) ;
276
277   return TRUE ;
278 }
279
280
281 /*
282  * doExtensionPcf8574:
283  *      Digital IO (Crude!)
284  *      pcf8574:base:i2cAddr
285  *********************************************************************************
286  */
287
288 static int doExtensionPcf8574 (char *progName, int pinBase, char *params)
289 {
290   int i2c ;
291
292   if ((params = extractInt (progName, params, &i2c)) == NULL)
293     return FALSE ;
294
295   if ((i2c < 0x03) || (i2c > 0x77))
296   {
297     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
298     return FALSE ;
299   }
300
301   pcf8574Setup (pinBase, i2c) ;
302
303   return TRUE ;
304 }
305
306
307 /*
308  * doExtensionPcf8591:
309  *      Analog IO
310  *      pcf8591:base:i2cAddr
311  *********************************************************************************
312  */
313
314 static int doExtensionPcf8591 (char *progName, int pinBase, char *params)
315 {
316   int i2c ;
317
318   if ((params = extractInt (progName, params, &i2c)) == NULL)
319     return FALSE ;
320
321   if ((i2c < 0x03) || (i2c > 0x77))
322   {
323     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
324     return FALSE ;
325   }
326
327   pcf8591Setup (pinBase, i2c) ;
328
329   return TRUE ;
330 }
331
332
333 /*
334  * Function list
335  *********************************************************************************
336  */
337
338 struct extensionFunctionStruct extensionFunctions [] = 
339 {
340   { "mcp23008",         &doExtensionMcp23008    },
341   { "mcp23016",         &doExtensionMcp23016    },
342   { "mcp23017",         &doExtensionMcp23017    },
343   { "mcp23s08",         &doExtensionMcp23s08    },
344   { "mcp23s17",         &doExtensionMcp23s17    },
345   { "sr595",            &doExtensionSr595       },
346   { "pcf8574",          &doExtensionPcf8574     },
347   { "pcf8591",          &doExtensionPcf8591     },
348   { NULL,               NULL                    },
349 } ;
350
351
352 /*
353  * doExtension:
354  *      Load in a wiringPi extension
355  *********************************************************************************
356  */
357
358 int doExtension (char *progName, char *extensionData)
359 {
360   char *p ;
361   char *extension = extensionData ;
362   struct extensionFunctionStruct *extensionFn ;
363   int pinBase = 0 ;
364
365 // Get the extension extension name by finding the first colon
366
367   p = extension ;
368   while (*p != ':')
369   {
370     if (!*p)    // ran out of characters
371     {
372       fprintf (stderr, "%s: extension name not terminated by a colon\n", progName) ;
373       return FALSE ;
374     }
375     ++p ;
376   }
377
378   *p++ = 0 ;
379
380   if (!isdigit (*p))
381   {
382     fprintf (stderr, "%s: pinBase number expected after extension name\n", progName) ;
383     return FALSE ;
384   }
385
386   while (isdigit (*p))
387   {
388     if (pinBase > 1000000000)
389     {
390       fprintf (stderr, "%s: pinBase too large\n", progName) ;
391       return FALSE ;
392     }
393
394     pinBase = pinBase * 10 + (*p - '0') ;
395     ++p ;
396   }
397
398   if (pinBase < 64)
399   {
400     fprintf (stderr, "%s: pinBase (%d) too small. Minimum is 64.\n", progName, pinBase) ;
401     return FALSE ;
402   }
403
404 // Search for extensions:
405
406   for (extensionFn = extensionFunctions ; extensionFn->name != NULL ; ++extensionFn)
407   {
408     if (strcmp (extensionFn->name, extension) == 0)
409       return extensionFn->function (progName, pinBase, p) ;
410   }
411
412   fprintf (stderr, "%s: extension %s not found\n", progName, extension) ;
413   return FALSE ;
414 }