portdio/portdio.c

Copyright (C) 2001-2008 by egnite Software GmbH. All rights reserved.

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 #endif
00163 
00164 /*
00165  * Previous AVR versions read the full PIN register. Now each input
00166  * and output pin is freely configurable (within a single port bank).
00167  * This routine collects all pins as they would have been read
00168  * from a single 8-bit register.
00169  */
00170 static int PortStatus(void)
00171 {
00172     int stat = 0;
00173 #ifdef INBANK
00174 #ifdef INPIN1
00175     stat |= GpioPinGet(INBANK, INPIN1);
00176 #endif
00177 #ifdef INPIN2
00178     stat |= GpioPinGet(INBANK, INPIN2) << 1;
00179 #endif
00180 #ifdef INPIN3
00181     stat |= GpioPinGet(INBANK, INPIN3) << 2;
00182 #endif
00183 #ifdef INPIN4
00184     stat |= GpioPinGet(INBANK, INPIN4) << 3;
00185 #endif
00186 #endif /* INBANK */
00187 
00188 #ifdef OUTBANK
00189 #ifdef OUTPIN1
00190     stat |= GpioPinGet(OUTBANK, OUTPIN1) << 4;
00191 #endif
00192 #ifdef OUTPIN2
00193     stat |= GpioPinGet(OUTBANK, OUTPIN2) << 5;
00194 #endif
00195 #ifdef OUTPIN3
00196     stat |= GpioPinGet(OUTBANK, OUTPIN3) << 6;
00197 #endif
00198 #ifdef OUTPIN4
00199     stat |= GpioPinGet(OUTBANK, OUTPIN4) << 7;
00200 #endif
00201 #endif /* OUTBANK */
00202 
00203     return stat;
00204 }
00205 
00206 /*
00207  * Process client requests.
00208  */
00209 void ProcessRequests(FILE * stream)
00210 {
00211     char buff[128];
00212     char *cp;
00213     int stat = -1;
00214 
00215     fputs("200 Welcome to portdio. Type help to get help.\r\n", stream);
00216     for (;;) {
00217         fflush(stream);
00218 
00219         /*
00220          * Read a line from the client. Ignore
00221          * blank lines.
00222          */
00223         if (fgets(buff, sizeof(buff), stream) == 0)
00224             break;
00225         if ((cp = strchr(buff, '\r')) != 0)
00226             *cp = 0;
00227         if ((cp = strchr(buff, '\n')) != 0)
00228             *cp = 0;
00229         if (buff[0] == 0)
00230             continue;
00231 
00232         /*
00233          * Memory info.
00234          */
00235         if (strncmp(buff, "memory", strlen(buff)) == 0) {
00236             fprintf(stream, "210 %u bytes RAM free\r\n", (u_int)NutHeapAvailable());
00237             continue;
00238         }
00239 
00240 #ifdef OUTBANK
00241         /*
00242          * Reset output bit.
00243          */
00244         if (strlen(buff) > 1 && strncmp(buff, "reset", strlen(buff) - 1) == 0) {
00245             int ok = 1;
00246             switch (buff[strlen(buff) - 1]) {
00247 #ifdef OUTPIN1
00248             case '1':
00249                 GpioPinSetLow(OUTBANK, OUTPIN1);
00250                 break;
00251 #endif
00252 #ifdef OUTPIN2
00253             case '2':
00254                 GpioPinSetLow(OUTBANK, OUTPIN2);
00255                 break;
00256 #endif
00257 #ifdef OUTPIN3
00258             case '3':
00259                 GpioPinSetLow(OUTBANK, OUTPIN3);
00260                 break;
00261 #endif
00262 #ifdef OUTPIN4
00263             case '4':
00264                 GpioPinSetLow(OUTBANK, OUTPIN4);
00265                 break;
00266 #endif
00267             default:
00268                 ok = 0;
00269                 break;
00270             }
00271             if (ok) {
00272                 fputs("210 OK\r\n", stream);
00273             } else
00274                 fputs("410 Bad pin\r\n", stream);
00275             continue;
00276         }
00277 
00278         /*
00279          * Set output bit.
00280          */
00281         if (strlen(buff) > 1 && strncmp(buff, "set", strlen(buff) - 1) == 0) {
00282             int ok = 1;
00283             switch (buff[strlen(buff) - 1]) {
00284 #ifdef OUTPIN1
00285             case '1':
00286                 GpioPinSetHigh(OUTBANK, OUTPIN1);
00287                 break;
00288 #endif
00289 #ifdef OUTPIN2
00290             case '2':
00291                 GpioPinSetHigh(OUTBANK, OUTPIN2);
00292                 break;
00293 #endif
00294 #ifdef OUTPIN3
00295             case '3':
00296                 GpioPinSetHigh(OUTBANK, OUTPIN3);
00297                 break;
00298 #endif
00299 #ifdef OUTPIN4
00300             case '4':
00301                 GpioPinSetHigh(OUTBANK, OUTPIN4);
00302                 break;
00303 #endif
00304             default:
00305                 ok = 0;
00306                 break;
00307             }
00308             if (ok) {
00309                 fputs("210 OK\r\n", stream);
00310             } else
00311                 fputs("410 Bad pin\r\n", stream);
00312             continue;
00313         }
00314 #endif /* OUTBANK */
00315 
00316 #ifdef INBANK
00317         /*
00318          * Port status.
00319          */
00320         if (strncmp(buff, "query", strlen(buff)) == 0) {
00321             stat = PortStatus();
00322             fprintf(stream, "210 %02X\r\n", stat);
00323             continue;
00324         }
00325 
00326         /*
00327          * wait for status change.
00328          */
00329         if (strncmp(buff, "wait", strlen(buff)) == 0) {
00330             while (stat == PortStatus())
00331                 NutThreadYield();
00332             stat = PortStatus();
00333             fprintf(stream, "210 %02X\r\n", stat);
00334             continue;
00335         }
00336 #endif /* INBANK */
00337 
00338         /*
00339          * Help.
00340          */
00341         fputs("400 List of commands follows\r\n", stream);
00342         fputs("memory\tQueries number of RAM bytes free\r\n", stream);
00343 #if OUTBANK
00344         fputs("reset#\tSet output bit 1..4 low\r\n", stream);
00345         fputs("set#\tSet output bit 1..4 high\r\n", stream);
00346 #endif
00347 #if INBANK
00348         fputs("query\tQuery digital i/o status\r\n", stream);
00349         fputs("wait\tWaits for digital i/o change\r\n", stream);
00350 #endif
00351         fputs(".\r\n", stream);
00352     }
00353 }
00354 
00355 /*
00356  * Init Port D
00357  */
00358 void init_dio(void)
00359 {
00360     /* Configure input pins, enable pull up. */
00361 #ifdef INBANK
00362 #ifdef INPIN1
00363     GpioPinConfigSet(INBANK, INPIN1, GPIO_CFG_PULLUP);
00364 #endif
00365 #ifdef INPIN2
00366     GpioPinConfigSet(INBANK, INPIN2, GPIO_CFG_PULLUP);
00367 #endif
00368 #ifdef INPIN3
00369     GpioPinConfigSet(INBANK, INPIN3, GPIO_CFG_PULLUP);
00370 #endif
00371 #ifdef INPIN4
00372     GpioPinConfigSet(INBANK, INPIN4, GPIO_CFG_PULLUP);
00373 #endif
00374 #endif /* INBANK */
00375 
00376     /* Configure output pins, set to low. */
00377 #ifdef OUTBANK
00378 #ifdef OUTPIN1
00379     GpioPinConfigSet(OUTBANK, OUTPIN1, GPIO_CFG_OUTPUT);
00380     GpioPinSetLow(OUTBANK, OUTPIN1);
00381 #endif
00382 #ifdef OUTPIN2
00383     GpioPinConfigSet(OUTBANK, OUTPIN2, GPIO_CFG_OUTPUT);
00384     GpioPinSetLow(OUTBANK, OUTPIN2);
00385 #endif
00386 #ifdef OUTPIN3
00387     GpioPinConfigSet(OUTBANK, OUTPIN3, GPIO_CFG_OUTPUT);
00388     GpioPinSetLow(OUTBANK, OUTPIN3);
00389 #endif
00390 #ifdef OUTPIN4
00391     GpioPinConfigSet(OUTBANK, OUTPIN4, GPIO_CFG_OUTPUT);
00392     GpioPinSetLow(OUTBANK, OUTPIN4);
00393 #endif
00394 #endif /* OUTBANK */
00395 }
00396 
00397 void service(void)
00398 {
00399     TCPSOCKET *sock;
00400     FILE *stream;
00401 
00402     /*
00403      * Loop endless for connections.
00404      */
00405     for (;;) {
00406         /*
00407          * Create a socket.
00408          */
00409         sock = NutTcpCreateSocket();
00410 
00411         /*
00412          * Listen at the configured port. If we return, we got a client.
00413          */
00414         NutTcpAccept(sock, MY_PORT);
00415 
00416         /*
00417          * Create a stream from the socket.
00418          */
00419         stream = _fdopen((int) sock, "r+b");
00420 
00421         /*
00422          * Process client requests.
00423          */
00424         ProcessRequests(stream);
00425 
00426         /*
00427          * Destroy our device.
00428          */
00429         fclose(stream);
00430 
00431         /*
00432          * Close our socket.
00433          */
00434         NutTcpCloseSocket(sock);
00435     }
00436 }
00437 
00438 THREAD(service_thread, arg)
00439 {
00440     for (;;)
00441         service();
00442 }
00443 
00444 /*
00445  * Main application routine. 
00446  *
00447  * Nut/OS automatically calls this entry after initialization.
00448  */
00449 int main(void)
00450 {
00451     u_char my_mac[] = MY_MAC;
00452 
00453     /*
00454      * Initialize digital I/O.
00455      */
00456     init_dio();
00457 
00458     /*
00459      * Register Realtek controller at address 8300 hex
00460      * and interrupt 5.
00461      */
00462     NutRegisterDevice(&DEV_ETHER, 0x8300, 5);
00463 
00464     /*
00465      * Configure lan interface. 
00466      */
00467     if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000) && NutDhcpIfConfig("eth0", my_mac, 60000)) {
00468         /*
00469          * No DHCP server available. Use hard coded values.
00470          */
00471         u_long ip_addr = inet_addr(MY_IP);      /* ICCAVR fix. */
00472         NutNetIfConfig("eth0", my_mac, ip_addr, inet_addr(MY_MASK));
00473     }
00474 
00475     /*
00476      * Start another service thread to allow
00477      * two concurrent connections.
00478      */
00479     NutThreadCreate("sback", service_thread, 0, 1384);
00480 
00481     for (;;)
00482         service();
00483 
00484     return 0;
00485 }

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/