portdio.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /*!
  2. * Copyright (C) 2001-2008 by egnite Software GmbH
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*!
  35. * $Id: portdio.c 4116 2012-04-12 22:35:23Z olereinhardt $
  36. */
  37. /*!
  38. * \example portdio/portdio.c
  39. *
  40. * TCP server for Port D I/O.
  41. *
  42. * Program Ethernut with portdio.hex and enter
  43. *
  44. * telnet x.x.x.x 12345
  45. *
  46. * two times on two command prompts, replacing x.x.x.x with the IP address
  47. * of your ethernut board. This will start two telnet session.
  48. *
  49. * Enter help for a list of available commands.
  50. *
  51. * Enter query on the first will show the current port status.
  52. *
  53. * Then enter wait on this session, which will hang until the port status
  54. * changes.
  55. *
  56. * On the second telnet session enter set1 to set the first output bit.
  57. */
  58. #define MY_MAC {0x00,0x06,0x98,0x20,0x00,0x00}
  59. #define MY_IP "192.168.192.100"
  60. #define MY_MASK "255.255.255.0"
  61. #define MY_PORT 12345
  62. #include <string.h>
  63. #include <stdio.h>
  64. #include <dev/board.h>
  65. #include <dev/gpio.h>
  66. #include <sys/heap.h>
  67. #include <sys/thread.h>
  68. #include <sys/timer.h>
  69. #include <sys/socket.h>
  70. #include <arpa/inet.h>
  71. #include <net/route.h>
  72. #include <netdb.h>
  73. #include <pro/dhcp.h>
  74. #if defined(ETHERNUT1) || defined(ETHERNUT2)
  75. #define INBANK 2 /* PORTB */
  76. #define INPIN1 0
  77. #define INPIN2 1
  78. #define INPIN3 2
  79. #define INPIN4 3
  80. #define OUTBANK 2 /* PORTB */
  81. #define OUTPIN1 4
  82. #define OUTPIN2 5
  83. #define OUTPIN3 6
  84. #define OUTPIN4 7
  85. #elif defined(ETHERNUT3)
  86. /* Uses same expansion port pins as Ethernut 1/2. */
  87. #define INBANK 0 /* PIO */
  88. #define INPIN1 0
  89. #define INPIN2 1
  90. #define INPIN3 2
  91. #define INPIN4 3
  92. #define OUTBANK 0 /* PIO */
  93. #define OUTPIN1 4
  94. #define OUTPIN2 5
  95. #define OUTPIN3 6
  96. #define OUTPIN4 7
  97. #elif defined(AT91SAM7X_EK)
  98. #define INBANK 1 /* PIOA Joystick */
  99. #define INPIN1 21
  100. #define INPIN2 22
  101. #define INPIN3 23
  102. #define INPIN4 24
  103. #define OUTBANK 2 /* PIOB User LEDs */
  104. #define OUTPIN1 19
  105. #define OUTPIN2 20
  106. #define OUTPIN3 21
  107. #define OUTPIN4 22
  108. #elif defined(AT91SAM9260_EK)
  109. #define INBANK 1 /* PIOA */
  110. #define INPIN1 30 /* Push button 3 */
  111. #define INPIN2 31 /* Push button 4 */
  112. #define OUTBANK 1 /* PIOA */
  113. #define OUTPIN1 6 /* User LED */
  114. #define OUTPIN2 9 /* Power LED */
  115. #elif defined(EVK1100)
  116. #define INBANK 0 /* PA Joystick */
  117. #define INPIN1 25
  118. #define INPIN2 26
  119. #define INPIN3 27
  120. #define INPIN4 28
  121. #define OUTBANK 1 /* PIOB User LEDs */
  122. #define OUTPIN1 27
  123. #define OUTPIN2 28
  124. #define OUTPIN3 29
  125. #define OUTPIN4 30
  126. #endif
  127. /*
  128. * Previous AVR versions read the full PIN register. Now each input
  129. * and output pin is freely configurable (within a single port bank).
  130. * This routine collects all pins as they would have been read
  131. * from a single 8-bit register.
  132. */
  133. #ifdef INBANK
  134. static int PortStatus(void)
  135. {
  136. int stat = 0;
  137. #ifdef INPIN1
  138. stat |= GpioPinGet(INBANK, INPIN1);
  139. #endif
  140. #ifdef INPIN2
  141. stat |= GpioPinGet(INBANK, INPIN2) << 1;
  142. #endif
  143. #ifdef INPIN3
  144. stat |= GpioPinGet(INBANK, INPIN3) << 2;
  145. #endif
  146. #ifdef INPIN4
  147. stat |= GpioPinGet(INBANK, INPIN4) << 3;
  148. #endif
  149. #ifdef OUTBANK
  150. #ifdef OUTPIN1
  151. stat |= GpioPinGet(OUTBANK, OUTPIN1) << 4;
  152. #endif
  153. #ifdef OUTPIN2
  154. stat |= GpioPinGet(OUTBANK, OUTPIN2) << 5;
  155. #endif
  156. #ifdef OUTPIN3
  157. stat |= GpioPinGet(OUTBANK, OUTPIN3) << 6;
  158. #endif
  159. #ifdef OUTPIN4
  160. stat |= GpioPinGet(OUTBANK, OUTPIN4) << 7;
  161. #endif
  162. #endif /* OUTBANK */
  163. return stat;
  164. }
  165. #endif
  166. /*
  167. * Process client requests.
  168. */
  169. void ProcessRequests(FILE * stream)
  170. {
  171. char buff[128];
  172. char *cp;
  173. int stat = -1;
  174. fputs("200 Welcome to portdio. Type help to get help.\r\n", stream);
  175. for (;;) {
  176. fflush(stream);
  177. /*
  178. * Read a line from the client. Ignore
  179. * blank lines.
  180. */
  181. if (fgets(buff, sizeof(buff), stream) == 0)
  182. break;
  183. if ((cp = strchr(buff, '\r')) != 0)
  184. *cp = 0;
  185. if ((cp = strchr(buff, '\n')) != 0)
  186. *cp = 0;
  187. if (buff[0] == 0)
  188. continue;
  189. /*
  190. * Memory info.
  191. */
  192. if (strncmp(buff, "memory", strlen(buff)) == 0) {
  193. fprintf(stream, "210 %u bytes RAM free\r\n", (unsigned int)NutHeapAvailable());
  194. continue;
  195. }
  196. #ifdef OUTBANK
  197. /*
  198. * Reset output bit.
  199. */
  200. if (strlen(buff) > 1 && strncmp(buff, "reset", strlen(buff) - 1) == 0) {
  201. int ok = 1;
  202. switch (buff[strlen(buff) - 1]) {
  203. #ifdef OUTPIN1
  204. case '1':
  205. GpioPinSetLow(OUTBANK, OUTPIN1);
  206. break;
  207. #endif
  208. #ifdef OUTPIN2
  209. case '2':
  210. GpioPinSetLow(OUTBANK, OUTPIN2);
  211. break;
  212. #endif
  213. #ifdef OUTPIN3
  214. case '3':
  215. GpioPinSetLow(OUTBANK, OUTPIN3);
  216. break;
  217. #endif
  218. #ifdef OUTPIN4
  219. case '4':
  220. GpioPinSetLow(OUTBANK, OUTPIN4);
  221. break;
  222. #endif
  223. default:
  224. ok = 0;
  225. break;
  226. }
  227. if (ok) {
  228. fputs("210 OK\r\n", stream);
  229. } else
  230. fputs("410 Bad pin\r\n", stream);
  231. continue;
  232. }
  233. /*
  234. * Set output bit.
  235. */
  236. if (strlen(buff) > 1 && strncmp(buff, "set", strlen(buff) - 1) == 0) {
  237. int ok = 1;
  238. switch (buff[strlen(buff) - 1]) {
  239. #ifdef OUTPIN1
  240. case '1':
  241. GpioPinSetHigh(OUTBANK, OUTPIN1);
  242. break;
  243. #endif
  244. #ifdef OUTPIN2
  245. case '2':
  246. GpioPinSetHigh(OUTBANK, OUTPIN2);
  247. break;
  248. #endif
  249. #ifdef OUTPIN3
  250. case '3':
  251. GpioPinSetHigh(OUTBANK, OUTPIN3);
  252. break;
  253. #endif
  254. #ifdef OUTPIN4
  255. case '4':
  256. GpioPinSetHigh(OUTBANK, OUTPIN4);
  257. break;
  258. #endif
  259. default:
  260. ok = 0;
  261. break;
  262. }
  263. if (ok) {
  264. fputs("210 OK\r\n", stream);
  265. } else
  266. fputs("410 Bad pin\r\n", stream);
  267. continue;
  268. }
  269. #endif /* OUTBANK */
  270. #ifdef INBANK
  271. /*
  272. * Port status.
  273. */
  274. if (strncmp(buff, "query", strlen(buff)) == 0) {
  275. stat = PortStatus();
  276. fprintf(stream, "210 %02X\r\n", stat);
  277. continue;
  278. }
  279. /*
  280. * wait for status change.
  281. */
  282. if (strncmp(buff, "wait", strlen(buff)) == 0) {
  283. while (stat == PortStatus())
  284. NutThreadYield();
  285. stat = PortStatus();
  286. fprintf(stream, "210 %02X\r\n", stat);
  287. continue;
  288. }
  289. #endif /* INBANK */
  290. /*
  291. * Help.
  292. */
  293. fputs("400 List of commands follows\r\n", stream);
  294. fputs("memory\tQueries number of RAM bytes free\r\n", stream);
  295. #if OUTBANK
  296. fputs("reset#\tSet output bit 1..4 low\r\n", stream);
  297. fputs("set#\tSet output bit 1..4 high\r\n", stream);
  298. #endif
  299. #if INBANK
  300. fputs("query\tQuery digital i/o status\r\n", stream);
  301. fputs("wait\tWaits for digital i/o change\r\n", stream);
  302. #endif
  303. fputs(".\r\n", stream);
  304. }
  305. }
  306. /*
  307. * Init Port D
  308. */
  309. void init_dio(void)
  310. {
  311. /* Configure input pins, enable pull up. */
  312. #ifdef INBANK
  313. #ifdef INPIN1
  314. GpioPinConfigSet(INBANK, INPIN1, GPIO_CFG_PULLUP);
  315. #endif
  316. #ifdef INPIN2
  317. GpioPinConfigSet(INBANK, INPIN2, GPIO_CFG_PULLUP);
  318. #endif
  319. #ifdef INPIN3
  320. GpioPinConfigSet(INBANK, INPIN3, GPIO_CFG_PULLUP);
  321. #endif
  322. #ifdef INPIN4
  323. GpioPinConfigSet(INBANK, INPIN4, GPIO_CFG_PULLUP);
  324. #endif
  325. #endif /* INBANK */
  326. /* Configure output pins, set to low. */
  327. #ifdef OUTBANK
  328. #ifdef OUTPIN1
  329. GpioPinConfigSet(OUTBANK, OUTPIN1, GPIO_CFG_OUTPUT);
  330. GpioPinSetLow(OUTBANK, OUTPIN1);
  331. #endif
  332. #ifdef OUTPIN2
  333. GpioPinConfigSet(OUTBANK, OUTPIN2, GPIO_CFG_OUTPUT);
  334. GpioPinSetLow(OUTBANK, OUTPIN2);
  335. #endif
  336. #ifdef OUTPIN3
  337. GpioPinConfigSet(OUTBANK, OUTPIN3, GPIO_CFG_OUTPUT);
  338. GpioPinSetLow(OUTBANK, OUTPIN3);
  339. #endif
  340. #ifdef OUTPIN4
  341. GpioPinConfigSet(OUTBANK, OUTPIN4, GPIO_CFG_OUTPUT);
  342. GpioPinSetLow(OUTBANK, OUTPIN4);
  343. #endif
  344. #endif /* OUTBANK */
  345. }
  346. #ifdef DEV_ETHER
  347. void service(void)
  348. {
  349. TCPSOCKET *sock;
  350. FILE *stream;
  351. /*
  352. * Loop endless for connections.
  353. */
  354. for (;;) {
  355. /*
  356. * Create a socket.
  357. */
  358. sock = NutTcpCreateSocket();
  359. /*
  360. * Listen at the configured port. If we return, we got a client.
  361. */
  362. NutTcpAccept(sock, MY_PORT);
  363. /*
  364. * Create a stream from the socket.
  365. */
  366. stream = _fdopen((int) sock, "r+b");
  367. /*
  368. * Process client requests.
  369. */
  370. ProcessRequests(stream);
  371. /*
  372. * Destroy our device.
  373. */
  374. fclose(stream);
  375. /*
  376. * Close our socket.
  377. */
  378. NutTcpCloseSocket(sock);
  379. }
  380. }
  381. THREAD(service_thread, arg)
  382. {
  383. for (;;)
  384. service();
  385. }
  386. #endif /* DEV_ETHER */
  387. /*
  388. * Main application routine.
  389. *
  390. * Nut/OS automatically calls this entry after initialization.
  391. */
  392. int main(void)
  393. {
  394. uint8_t my_mac[] = MY_MAC;
  395. /*
  396. * Initialize digital I/O.
  397. */
  398. init_dio();
  399. #ifdef DEV_ETHER
  400. /*
  401. * Register Realtek controller at address 8300 hex
  402. * and interrupt 5.
  403. */
  404. NutRegisterDevice(&DEV_ETHER, 0x8300, 5);
  405. /*
  406. * Configure lan interface.
  407. */
  408. if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000) && NutDhcpIfConfig("eth0", my_mac, 60000)) {
  409. /*
  410. * No DHCP server available. Use hard coded values.
  411. */
  412. uint32_t ip_addr = inet_addr(MY_IP); /* ICCAVR fix. */
  413. NutNetIfConfig("eth0", my_mac, ip_addr, inet_addr(MY_MASK));
  414. }
  415. /*
  416. * Start another service thread to allow
  417. * two concurrent connections.
  418. */
  419. NutThreadCreate("sback", service_thread, 0, 1384);
  420. for (;;)
  421. service();
  422. #endif /* DEV_ETHER */
  423. return 0;
  424. }