You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

601 lines
13 KiB

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