Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
For additional information see http://www.ethernut.de/
$Log$ Revision 1.4 2008/01/31 09:35:10 haraldkipp Now makes use of general GPIO routines to work on all platforms. Pre-configured for Ethernut 1, 2 and 3 as well as Atmel's SAM7X and SAM9260 Evaluation Kits. Note, that the AVR version had been moved from PORTD to PORTB. This had been done to get the same expansion port pins on Ethernut 1/2 and Ethernut 3 without disturbing the TWI/I2C port. Removed system specific commands to keep it simple.
Revision 1.3 2005/11/22 09:16:31 haraldkipp Replaced specific device names by generalized macros. Casting size_t to int to avoid compiler warnings about printf format specifiers. Excluded hardware specific statements for non-AVR targets. This way it will not work on other targets, but at least compile without error.
Revision 1.2 2003/11/04 17:46:52 haraldkipp Adapted to Ethernut 2
Revision 1.1 2003/08/05 18:59:05 haraldkipp Release 3.3 update
Revision 1.7 2003/02/04 18:19:38 harald Version 3 released
Revision 1.6 2003/02/04 16:24:33 harald Adapted to version 3
Revision 1.5 2002/06/26 17:29:03 harald First pre-release with 2.4 stack
Revision 1.4 2002/06/12 10:56:16 harald *** empty log message ***
Revision 1.3 2002/06/04 19:12:37 harald *** empty log message ***
Revision 1.2 2002/05/08 16:02:31 harald First Imagecraft compilation
TCP server for Port D I/O.
Program Ethernut with portdio.hex and enter
telnet x.x.x.x 12345
two times on two command prompts, replacing x.x.x.x with the IP address of your ethernut board. This will start two telnet session.
Enter help for a list of available commands.
Enter query on the first will show the current port status.
Then enter wait on this session, which will hang until the port status changes.
On the second telnet session enter set1 to set the first output bit.
00001 00099 #define MY_MAC {0x00,0x06,0x98,0x20,0x00,0x00} 00100 #define MY_IP "192.168.192.100" 00101 #define MY_MASK "255.255.255.0" 00102 #define MY_PORT 12345 00103 00104 #include <string.h> 00105 #include <stdio.h> 00106 00107 #include <dev/board.h> 00108 #include <dev/gpio.h> 00109 00110 #include <sys/heap.h> 00111 #include <sys/thread.h> 00112 #include <sys/timer.h> 00113 #include <sys/socket.h> 00114 00115 #include <arpa/inet.h> 00116 #include <net/route.h> 00117 #include <netdb.h> 00118 00119 #include <pro/dhcp.h> 00120 00121 #if defined(ETHERNUT1) || defined(ETHERNUT2) 00122 #define INBANK 2 /* PORTB */ 00123 #define INPIN1 0 00124 #define INPIN2 1 00125 #define INPIN3 2 00126 #define INPIN4 3 00127 #define OUTBANK 2 /* PORTB */ 00128 #define OUTPIN1 4 00129 #define OUTPIN2 5 00130 #define OUTPIN3 6 00131 #define OUTPIN4 7 00132 #elif defined(ETHERNUT3) 00133 /* Uses same expansion port pins as Ethernut 1/2. */ 00134 #define INBANK 0 /* PIO */ 00135 #define INPIN1 0 00136 #define INPIN2 1 00137 #define INPIN3 2 00138 #define INPIN4 3 00139 #define OUTBANK 0 /* PIO */ 00140 #define OUTPIN1 4 00141 #define OUTPIN2 5 00142 #define OUTPIN3 6 00143 #define OUTPIN4 7 00144 #elif defined(AT91SAM7X_EK) 00145 #define INBANK 1 /* PIOA Joystick */ 00146 #define INPIN1 21 00147 #define INPIN2 22 00148 #define INPIN3 23 00149 #define INPIN4 24 00150 #define OUTBANK 2 /* PIOB User LEDs */ 00151 #define OUTPIN1 19 00152 #define OUTPIN2 20 00153 #define OUTPIN3 21 00154 #define OUTPIN4 22 00155 #elif defined(AT91SAM9260_EK) 00156 #define INBANK 1 /* PIOA */ 00157 #define INPIN1 30 /* Push button 3 */ 00158 #define INPIN2 31 /* Push button 4 */ 00159 #define OUTBANK 1 /* PIOA */ 00160 #define OUTPIN1 6 /* User LED */ 00161 #define OUTPIN2 9 /* Power LED */ 00162 #elif defined(EVK1100) 00163 #define INBANK 0 /* PA Joystick */ 00164 #define INPIN1 25 00165 #define INPIN2 26 00166 #define INPIN3 27 00167 #define INPIN4 28 00168 #define OUTBANK 1 /* PIOB User LEDs */ 00169 #define OUTPIN1 27 00170 #define OUTPIN2 28 00171 #define OUTPIN3 29 00172 #define OUTPIN4 30 00173 #endif 00174 00175 /* 00176 * Previous AVR versions read the full PIN register. Now each input 00177 * and output pin is freely configurable (within a single port bank). 00178 * This routine collects all pins as they would have been read 00179 * from a single 8-bit register. 00180 */ 00181 static int PortStatus(void) 00182 { 00183 int stat = 0; 00184 #ifdef INBANK 00185 #ifdef INPIN1 00186 stat |= GpioPinGet(INBANK, INPIN1); 00187 #endif 00188 #ifdef INPIN2 00189 stat |= GpioPinGet(INBANK, INPIN2) << 1; 00190 #endif 00191 #ifdef INPIN3 00192 stat |= GpioPinGet(INBANK, INPIN3) << 2; 00193 #endif 00194 #ifdef INPIN4 00195 stat |= GpioPinGet(INBANK, INPIN4) << 3; 00196 #endif 00197 #endif /* INBANK */ 00198 00199 #ifdef OUTBANK 00200 #ifdef OUTPIN1 00201 stat |= GpioPinGet(OUTBANK, OUTPIN1) << 4; 00202 #endif 00203 #ifdef OUTPIN2 00204 stat |= GpioPinGet(OUTBANK, OUTPIN2) << 5; 00205 #endif 00206 #ifdef OUTPIN3 00207 stat |= GpioPinGet(OUTBANK, OUTPIN3) << 6; 00208 #endif 00209 #ifdef OUTPIN4 00210 stat |= GpioPinGet(OUTBANK, OUTPIN4) << 7; 00211 #endif 00212 #endif /* OUTBANK */ 00213 00214 return stat; 00215 } 00216 00217 /* 00218 * Process client requests. 00219 */ 00220 void ProcessRequests(FILE * stream) 00221 { 00222 char buff[128]; 00223 char *cp; 00224 int stat = -1; 00225 00226 fputs("200 Welcome to portdio. Type help to get help.\r\n", stream); 00227 for (;;) { 00228 fflush(stream); 00229 00230 /* 00231 * Read a line from the client. Ignore 00232 * blank lines. 00233 */ 00234 if (fgets(buff, sizeof(buff), stream) == 0) 00235 break; 00236 if ((cp = strchr(buff, '\r')) != 0) 00237 *cp = 0; 00238 if ((cp = strchr(buff, '\n')) != 0) 00239 *cp = 0; 00240 if (buff[0] == 0) 00241 continue; 00242 00243 /* 00244 * Memory info. 00245 */ 00246 if (strncmp(buff, "memory", strlen(buff)) == 0) { 00247 fprintf(stream, "210 %u bytes RAM free\r\n", (u_int)NutHeapAvailable()); 00248 continue; 00249 } 00250 00251 #ifdef OUTBANK 00252 /* 00253 * Reset output bit. 00254 */ 00255 if (strlen(buff) > 1 && strncmp(buff, "reset", strlen(buff) - 1) == 0) { 00256 int ok = 1; 00257 switch (buff[strlen(buff) - 1]) { 00258 #ifdef OUTPIN1 00259 case '1': 00260 GpioPinSetLow(OUTBANK, OUTPIN1); 00261 break; 00262 #endif 00263 #ifdef OUTPIN2 00264 case '2': 00265 GpioPinSetLow(OUTBANK, OUTPIN2); 00266 break; 00267 #endif 00268 #ifdef OUTPIN3 00269 case '3': 00270 GpioPinSetLow(OUTBANK, OUTPIN3); 00271 break; 00272 #endif 00273 #ifdef OUTPIN4 00274 case '4': 00275 GpioPinSetLow(OUTBANK, OUTPIN4); 00276 break; 00277 #endif 00278 default: 00279 ok = 0; 00280 break; 00281 } 00282 if (ok) { 00283 fputs("210 OK\r\n", stream); 00284 } else 00285 fputs("410 Bad pin\r\n", stream); 00286 continue; 00287 } 00288 00289 /* 00290 * Set output bit. 00291 */ 00292 if (strlen(buff) > 1 && strncmp(buff, "set", strlen(buff) - 1) == 0) { 00293 int ok = 1; 00294 switch (buff[strlen(buff) - 1]) { 00295 #ifdef OUTPIN1 00296 case '1': 00297 GpioPinSetHigh(OUTBANK, OUTPIN1); 00298 break; 00299 #endif 00300 #ifdef OUTPIN2 00301 case '2': 00302 GpioPinSetHigh(OUTBANK, OUTPIN2); 00303 break; 00304 #endif 00305 #ifdef OUTPIN3 00306 case '3': 00307 GpioPinSetHigh(OUTBANK, OUTPIN3); 00308 break; 00309 #endif 00310 #ifdef OUTPIN4 00311 case '4': 00312 GpioPinSetHigh(OUTBANK, OUTPIN4); 00313 break; 00314 #endif 00315 default: 00316 ok = 0; 00317 break; 00318 } 00319 if (ok) { 00320 fputs("210 OK\r\n", stream); 00321 } else 00322 fputs("410 Bad pin\r\n", stream); 00323 continue; 00324 } 00325 #endif /* OUTBANK */ 00326 00327 #ifdef INBANK 00328 /* 00329 * Port status. 00330 */ 00331 if (strncmp(buff, "query", strlen(buff)) == 0) { 00332 stat = PortStatus(); 00333 fprintf(stream, "210 %02X\r\n", stat); 00334 continue; 00335 } 00336 00337 /* 00338 * wait for status change. 00339 */ 00340 if (strncmp(buff, "wait", strlen(buff)) == 0) { 00341 while (stat == PortStatus()) 00342 NutThreadYield(); 00343 stat = PortStatus(); 00344 fprintf(stream, "210 %02X\r\n", stat); 00345 continue; 00346 } 00347 #endif /* INBANK */ 00348 00349 /* 00350 * Help. 00351 */ 00352 fputs("400 List of commands follows\r\n", stream); 00353 fputs("memory\tQueries number of RAM bytes free\r\n", stream); 00354 #if OUTBANK 00355 fputs("reset#\tSet output bit 1..4 low\r\n", stream); 00356 fputs("set#\tSet output bit 1..4 high\r\n", stream); 00357 #endif 00358 #if INBANK 00359 fputs("query\tQuery digital i/o status\r\n", stream); 00360 fputs("wait\tWaits for digital i/o change\r\n", stream); 00361 #endif 00362 fputs(".\r\n", stream); 00363 } 00364 } 00365 00366 /* 00367 * Init Port D 00368 */ 00369 void init_dio(void) 00370 { 00371 /* Configure input pins, enable pull up. */ 00372 #ifdef INBANK 00373 #ifdef INPIN1 00374 GpioPinConfigSet(INBANK, INPIN1, GPIO_CFG_PULLUP); 00375 #endif 00376 #ifdef INPIN2 00377 GpioPinConfigSet(INBANK, INPIN2, GPIO_CFG_PULLUP); 00378 #endif 00379 #ifdef INPIN3 00380 GpioPinConfigSet(INBANK, INPIN3, GPIO_CFG_PULLUP); 00381 #endif 00382 #ifdef INPIN4 00383 GpioPinConfigSet(INBANK, INPIN4, GPIO_CFG_PULLUP); 00384 #endif 00385 #endif /* INBANK */ 00386 00387 /* Configure output pins, set to low. */ 00388 #ifdef OUTBANK 00389 #ifdef OUTPIN1 00390 GpioPinConfigSet(OUTBANK, OUTPIN1, GPIO_CFG_OUTPUT); 00391 GpioPinSetLow(OUTBANK, OUTPIN1); 00392 #endif 00393 #ifdef OUTPIN2 00394 GpioPinConfigSet(OUTBANK, OUTPIN2, GPIO_CFG_OUTPUT); 00395 GpioPinSetLow(OUTBANK, OUTPIN2); 00396 #endif 00397 #ifdef OUTPIN3 00398 GpioPinConfigSet(OUTBANK, OUTPIN3, GPIO_CFG_OUTPUT); 00399 GpioPinSetLow(OUTBANK, OUTPIN3); 00400 #endif 00401 #ifdef OUTPIN4 00402 GpioPinConfigSet(OUTBANK, OUTPIN4, GPIO_CFG_OUTPUT); 00403 GpioPinSetLow(OUTBANK, OUTPIN4); 00404 #endif 00405 #endif /* OUTBANK */ 00406 } 00407 00408 void service(void) 00409 { 00410 TCPSOCKET *sock; 00411 FILE *stream; 00412 00413 /* 00414 * Loop endless for connections. 00415 */ 00416 for (;;) { 00417 /* 00418 * Create a socket. 00419 */ 00420 sock = NutTcpCreateSocket(); 00421 00422 /* 00423 * Listen at the configured port. If we return, we got a client. 00424 */ 00425 NutTcpAccept(sock, MY_PORT); 00426 00427 /* 00428 * Create a stream from the socket. 00429 */ 00430 stream = _fdopen((int) sock, "r+b"); 00431 00432 /* 00433 * Process client requests. 00434 */ 00435 ProcessRequests(stream); 00436 00437 /* 00438 * Destroy our device. 00439 */ 00440 fclose(stream); 00441 00442 /* 00443 * Close our socket. 00444 */ 00445 NutTcpCloseSocket(sock); 00446 } 00447 } 00448 00449 THREAD(service_thread, arg) 00450 { 00451 for (;;) 00452 service(); 00453 } 00454 00455 /* 00456 * Main application routine. 00457 * 00458 * Nut/OS automatically calls this entry after initialization. 00459 */ 00460 int main(void) 00461 { 00462 u_char my_mac[] = MY_MAC; 00463 00464 /* 00465 * Initialize digital I/O. 00466 */ 00467 init_dio(); 00468 00469 /* 00470 * Register Realtek controller at address 8300 hex 00471 * and interrupt 5. 00472 */ 00473 NutRegisterDevice(&DEV_ETHER, 0x8300, 5); 00474 00475 /* 00476 * Configure lan interface. 00477 */ 00478 if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000) && NutDhcpIfConfig("eth0", my_mac, 60000)) { 00479 /* 00480 * No DHCP server available. Use hard coded values. 00481 */ 00482 u_long ip_addr = inet_addr(MY_IP); /* ICCAVR fix. */ 00483 NutNetIfConfig("eth0", my_mac, ip_addr, inet_addr(MY_MASK)); 00484 } 00485 00486 /* 00487 * Start another service thread to allow 00488 * two concurrent connections. 00489 */ 00490 NutThreadCreate("sback", service_thread, 0, 1384); 00491 00492 for (;;) 00493 service(); 00494 00495 return 0; 00496 }