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 #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 }

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