Gordons Projects

--> Projects Top-Level GIT

c08d1c10a5be3cece8fcd7274e0034409c160f32
[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 <mcp23017.h>
40 #include <mcp23s08.h>
41 #include <mcp23s17.h>
42 #include <sr595.h>
43
44 #include "extensions.h"
45
46 extern int wiringPiDebug ;
47
48 #ifndef TRUE
49 #  define       TRUE    (1==1)
50 #  define       FALSE   (1==2)
51 #endif
52
53 // Local structure to hold details
54
55 struct extensionFunctionStruct
56 {
57   const char *name ;
58   int   (*function)(char *progName, int pinBase, char *params) ;
59 } ;
60
61
62 /*
63  * extractInt:
64  *      Check & return an integer at the given location (prefixed by a :)
65  *********************************************************************************
66  */
67
68 static char *extractInt (char *progName, char *p, int *num)
69 {
70   if (*p != ':')
71   {
72     fprintf (stderr, "%s: colon expected\n", progName) ;
73     return NULL ;
74   }
75
76   ++p ;
77
78   if (!isdigit (*p))
79   {
80     fprintf (stderr, "%s: digit expected\n", progName) ;
81     return NULL ;
82   }
83
84   *num = strtol (p, NULL, 0) ;
85   while (isdigit (*p))
86     ++p ;
87
88   return p ;
89 }
90
91
92
93 /*
94  * doExtensionMcp23008:
95  *      MCP23008 - 8-bit I2C GPIO expansion chip
96  *      mcp23002:base:i2cAddr
97  *********************************************************************************
98  */
99
100 static int doExtensionMcp23008 (char *progName, int pinBase, char *params)
101 {
102   int i2c ;
103
104   if ((params = extractInt (progName, params, &i2c)) == NULL)
105     return FALSE ;
106
107   if ((i2c < 0x03) || (i2c > 0x77))
108   {
109     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
110     return FALSE ;
111   }
112
113   mcp23008Setup (pinBase, i2c) ;
114
115   return TRUE ;
116 }
117
118
119 /*
120  * doExtensionMcp23017:
121  *      MCP23008 - 16-bit I2C GPIO expansion chip
122  *      mcp23002:base:i2cAddr
123  *********************************************************************************
124  */
125
126 static int doExtensionMcp23017 (char *progName, int pinBase, char *params)
127 {
128   int i2c ;
129
130   if ((params = extractInt (progName, params, &i2c)) == NULL)
131     return FALSE ;
132
133   if ((i2c < 0x03) || (i2c > 0x77))
134   {
135     fprintf (stderr, "%s: i2c address (0x%X) out of range\n", progName, i2c) ;
136     return FALSE ;
137   }
138
139   mcp23017Setup (pinBase, i2c) ;
140
141   return TRUE ;
142 }
143
144
145 /*
146  * doExtensionMcp23s08:
147  *      MCP23s08 - 8-bit SPI GPIO expansion chip
148  *      mcp23s08:base:spi:port
149  *********************************************************************************
150  */
151
152 static int doExtensionMcp23s08 (char *progName, int pinBase, char *params)
153 {
154   int spi, port ;
155
156   if ((params = extractInt (progName, params, &spi)) == NULL)
157     return FALSE ;
158
159   if ((spi < 0) || (spi > 1))
160   {
161     fprintf (stderr, "%s: SPI address (%d) out of range\n", progName, spi) ;
162     return FALSE ;
163   }
164
165   if ((params = extractInt (progName, params, &port)) == NULL)
166     return FALSE ;
167
168   if ((port < 0) || (port > 7))
169   {
170     fprintf (stderr, "%s: port address (%d) out of range\n", progName, port) ;
171     return FALSE ;
172   }
173
174   mcp23s08Setup (pinBase, spi, port) ;
175
176   return TRUE ;
177 }
178
179
180 /*
181  * doExtensionMcp23s17:
182  *      MCP23s17 - 16-bit SPI GPIO expansion chip
183  *      mcp23s17:base:spi:port
184  *********************************************************************************
185  */
186
187 static int doExtensionMcp23s17 (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   mcp23s17Setup (pinBase, spi, port) ;
210
211   return TRUE ;
212 }
213
214 /*
215  * doExtensionSr595:
216  *      Shift Register 74x595
217  *      sr595:base:pins:data:clock:latch
218  *********************************************************************************
219  */
220
221 static int doExtensionSr595 (char *progName, int pinBase, char *params)
222 {
223   int pins, data, clock, latch ;
224
225 // Extract pins
226
227   if ((params = extractInt (progName, params, &pins)) == NULL)
228     return FALSE ;
229
230   if ((pins < 8) || (pins > 32))
231   {
232     fprintf (stderr, "%s: pin count (%d) out of range - 8-32 expected.\n", progName, pins) ;
233     return FALSE ;
234   }
235
236   if ((params = extractInt (progName, params, &data)) == NULL)
237     return FALSE ;
238
239   if ((params = extractInt (progName, params, &clock)) == NULL)
240     return FALSE ;
241
242   if ((params = extractInt (progName, params, &latch)) == NULL)
243     return FALSE ;
244
245   sr595Setup (pinBase, pins, data, clock, latch) ;
246
247   return TRUE ;
248 }
249
250
251 /*
252  * Function list
253  *********************************************************************************
254  */
255
256 struct extensionFunctionStruct extensionFunctions [] = 
257 {
258   { "mcp23008",         &doExtensionMcp23008    },
259   { "mcp23017",         &doExtensionMcp23017    },
260   { "mcp23s08",         &doExtensionMcp23s08    },
261   { "mcp23s17",         &doExtensionMcp23s17    },
262   { "sr595",            &doExtensionSr595        },
263   { NULL,               NULL                    },
264 } ;
265
266
267 /*
268  * doExtension:
269  *      Load in a wiringPi extension
270  *********************************************************************************
271  */
272
273 int doExtension (char *progName, char *extensionData)
274 {
275   char *p ;
276   char *extension = extensionData ;
277   struct extensionFunctionStruct *extensionFn ;
278   int pinBase = 0 ;
279
280 // Get the extension extension name by finding the first colon
281
282   p = extension ;
283   while (*p != ':')
284   {
285     if (!*p)    // ran out of characters
286     {
287       fprintf (stderr, "%s: extension name not terminated by a colon\n", progName) ;
288       return FALSE ;
289     }
290     ++p ;
291   }
292
293   *p++ = 0 ;
294
295   if (!isdigit (*p))
296   {
297     fprintf (stderr, "%s: pinBase number expected after extension name\n", progName) ;
298     return FALSE ;
299   }
300
301   while (isdigit (*p))
302   {
303     if (pinBase > 1000000000)
304     {
305       fprintf (stderr, "%s: pinBase too large\n", progName) ;
306       return FALSE ;
307     }
308
309     pinBase = pinBase * 10 + (*p - '0') ;
310     ++p ;
311   }
312
313   if (pinBase < 64)
314   {
315     fprintf (stderr, "%s: pinBase (%d) too small. Minimum is 64.\n", progName, pinBase) ;
316     return FALSE ;
317   }
318
319 // Search for extensions:
320
321   for (extensionFn = extensionFunctions ; extensionFn->name != NULL ; ++extensionFn)
322   {
323     if (strcmp (extensionFn->name, extension) == 0)
324       return extensionFn->function (progName, pinBase, p) ;
325   }
326
327   fprintf (stderr, "%s: extension %s not found\n", progName, extension) ;
328   return FALSE ;
329 }