/*! * 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/ */ /*! * $Id: portdio.c 4116 2012-04-12 22:35:23Z olereinhardt $ */ /*! * \example portdio/portdio.c * * 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. */ #define MY_MAC {0x00,0x06,0x98,0x20,0x00,0x00} #define MY_IP "192.168.192.100" #define MY_MASK "255.255.255.0" #define MY_PORT 12345 #include #include #include #include #include #include #include #include #include #include #include #include #if defined(ETHERNUT1) || defined(ETHERNUT2) #define INBANK 2 /* PORTB */ #define INPIN1 0 #define INPIN2 1 #define INPIN3 2 #define INPIN4 3 #define OUTBANK 2 /* PORTB */ #define OUTPIN1 4 #define OUTPIN2 5 #define OUTPIN3 6 #define OUTPIN4 7 #elif defined(ETHERNUT3) /* Uses same expansion port pins as Ethernut 1/2. */ #define INBANK 0 /* PIO */ #define INPIN1 0 #define INPIN2 1 #define INPIN3 2 #define INPIN4 3 #define OUTBANK 0 /* PIO */ #define OUTPIN1 4 #define OUTPIN2 5 #define OUTPIN3 6 #define OUTPIN4 7 #elif defined(AT91SAM7X_EK) #define INBANK 1 /* PIOA Joystick */ #define INPIN1 21 #define INPIN2 22 #define INPIN3 23 #define INPIN4 24 #define OUTBANK 2 /* PIOB User LEDs */ #define OUTPIN1 19 #define OUTPIN2 20 #define OUTPIN3 21 #define OUTPIN4 22 #elif defined(AT91SAM9260_EK) #define INBANK 1 /* PIOA */ #define INPIN1 30 /* Push button 3 */ #define INPIN2 31 /* Push button 4 */ #define OUTBANK 1 /* PIOA */ #define OUTPIN1 6 /* User LED */ #define OUTPIN2 9 /* Power LED */ #elif defined(EVK1100) #define INBANK 0 /* PA Joystick */ #define INPIN1 25 #define INPIN2 26 #define INPIN3 27 #define INPIN4 28 #define OUTBANK 1 /* PIOB User LEDs */ #define OUTPIN1 27 #define OUTPIN2 28 #define OUTPIN3 29 #define OUTPIN4 30 #endif /* * Previous AVR versions read the full PIN register. Now each input * and output pin is freely configurable (within a single port bank). * This routine collects all pins as they would have been read * from a single 8-bit register. */ #ifdef INBANK static int PortStatus(void) { int stat = 0; #ifdef INPIN1 stat |= GpioPinGet(INBANK, INPIN1); #endif #ifdef INPIN2 stat |= GpioPinGet(INBANK, INPIN2) << 1; #endif #ifdef INPIN3 stat |= GpioPinGet(INBANK, INPIN3) << 2; #endif #ifdef INPIN4 stat |= GpioPinGet(INBANK, INPIN4) << 3; #endif #ifdef OUTBANK #ifdef OUTPIN1 stat |= GpioPinGet(OUTBANK, OUTPIN1) << 4; #endif #ifdef OUTPIN2 stat |= GpioPinGet(OUTBANK, OUTPIN2) << 5; #endif #ifdef OUTPIN3 stat |= GpioPinGet(OUTBANK, OUTPIN3) << 6; #endif #ifdef OUTPIN4 stat |= GpioPinGet(OUTBANK, OUTPIN4) << 7; #endif #endif /* OUTBANK */ return stat; } #endif /* * Process client requests. */ void ProcessRequests(FILE * stream) { char buff[128]; char *cp; int stat = -1; fputs("200 Welcome to portdio. Type help to get help.\r\n", stream); for (;;) { fflush(stream); /* * Read a line from the client. Ignore * blank lines. */ if (fgets(buff, sizeof(buff), stream) == 0) break; if ((cp = strchr(buff, '\r')) != 0) *cp = 0; if ((cp = strchr(buff, '\n')) != 0) *cp = 0; if (buff[0] == 0) continue; /* * Memory info. */ if (strncmp(buff, "memory", strlen(buff)) == 0) { fprintf(stream, "210 %u bytes RAM free\r\n", (unsigned int)NutHeapAvailable()); continue; } #ifdef OUTBANK /* * Reset output bit. */ if (strlen(buff) > 1 && strncmp(buff, "reset", strlen(buff) - 1) == 0) { int ok = 1; switch (buff[strlen(buff) - 1]) { #ifdef OUTPIN1 case '1': GpioPinSetLow(OUTBANK, OUTPIN1); break; #endif #ifdef OUTPIN2 case '2': GpioPinSetLow(OUTBANK, OUTPIN2); break; #endif #ifdef OUTPIN3 case '3': GpioPinSetLow(OUTBANK, OUTPIN3); break; #endif #ifdef OUTPIN4 case '4': GpioPinSetLow(OUTBANK, OUTPIN4); break; #endif default: ok = 0; break; } if (ok) { fputs("210 OK\r\n", stream); } else fputs("410 Bad pin\r\n", stream); continue; } /* * Set output bit. */ if (strlen(buff) > 1 && strncmp(buff, "set", strlen(buff) - 1) == 0) { int ok = 1; switch (buff[strlen(buff) - 1]) { #ifdef OUTPIN1 case '1': GpioPinSetHigh(OUTBANK, OUTPIN1); break; #endif #ifdef OUTPIN2 case '2': GpioPinSetHigh(OUTBANK, OUTPIN2); break; #endif #ifdef OUTPIN3 case '3': GpioPinSetHigh(OUTBANK, OUTPIN3); break; #endif #ifdef OUTPIN4 case '4': GpioPinSetHigh(OUTBANK, OUTPIN4); break; #endif default: ok = 0; break; } if (ok) { fputs("210 OK\r\n", stream); } else fputs("410 Bad pin\r\n", stream); continue; } #endif /* OUTBANK */ #ifdef INBANK /* * Port status. */ if (strncmp(buff, "query", strlen(buff)) == 0) { stat = PortStatus(); fprintf(stream, "210 %02X\r\n", stat); continue; } /* * wait for status change. */ if (strncmp(buff, "wait", strlen(buff)) == 0) { while (stat == PortStatus()) NutThreadYield(); stat = PortStatus(); fprintf(stream, "210 %02X\r\n", stat); continue; } #endif /* INBANK */ /* * Help. */ fputs("400 List of commands follows\r\n", stream); fputs("memory\tQueries number of RAM bytes free\r\n", stream); #if OUTBANK fputs("reset#\tSet output bit 1..4 low\r\n", stream); fputs("set#\tSet output bit 1..4 high\r\n", stream); #endif #if INBANK fputs("query\tQuery digital i/o status\r\n", stream); fputs("wait\tWaits for digital i/o change\r\n", stream); #endif fputs(".\r\n", stream); } } /* * Init Port D */ void init_dio(void) { /* Configure input pins, enable pull up. */ #ifdef INBANK #ifdef INPIN1 GpioPinConfigSet(INBANK, INPIN1, GPIO_CFG_PULLUP); #endif #ifdef INPIN2 GpioPinConfigSet(INBANK, INPIN2, GPIO_CFG_PULLUP); #endif #ifdef INPIN3 GpioPinConfigSet(INBANK, INPIN3, GPIO_CFG_PULLUP); #endif #ifdef INPIN4 GpioPinConfigSet(INBANK, INPIN4, GPIO_CFG_PULLUP); #endif #endif /* INBANK */ /* Configure output pins, set to low. */ #ifdef OUTBANK #ifdef OUTPIN1 GpioPinConfigSet(OUTBANK, OUTPIN1, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN1); #endif #ifdef OUTPIN2 GpioPinConfigSet(OUTBANK, OUTPIN2, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN2); #endif #ifdef OUTPIN3 GpioPinConfigSet(OUTBANK, OUTPIN3, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN3); #endif #ifdef OUTPIN4 GpioPinConfigSet(OUTBANK, OUTPIN4, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN4); #endif #endif /* OUTBANK */ } #ifdef DEV_ETHER void service(void) { TCPSOCKET *sock; FILE *stream; /* * Loop endless for connections. */ for (;;) { /* * Create a socket. */ sock = NutTcpCreateSocket(); /* * Listen at the configured port. If we return, we got a client. */ NutTcpAccept(sock, MY_PORT); /* * Create a stream from the socket. */ stream = _fdopen((int) sock, "r+b"); /* * Process client requests. */ ProcessRequests(stream); /* * Destroy our device. */ fclose(stream); /* * Close our socket. */ NutTcpCloseSocket(sock); } } THREAD(service_thread, arg) { for (;;) service(); } #endif /* DEV_ETHER */ /* * Main application routine. * * Nut/OS automatically calls this entry after initialization. */ int main(void) { uint8_t my_mac[] = MY_MAC; /* * Initialize digital I/O. */ init_dio(); #ifdef DEV_ETHER /* * Register Realtek controller at address 8300 hex * and interrupt 5. */ NutRegisterDevice(&DEV_ETHER, 0x8300, 5); /* * Configure lan interface. */ if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000) && NutDhcpIfConfig("eth0", my_mac, 60000)) { /* * No DHCP server available. Use hard coded values. */ uint32_t ip_addr = inet_addr(MY_IP); /* ICCAVR fix. */ NutNetIfConfig("eth0", my_mac, ip_addr, inet_addr(MY_MASK)); } /* * Start another service thread to allow * two concurrent connections. */ NutThreadCreate("sback", service_thread, 0, 1384); for (;;) service(); #endif /* DEV_ETHER */ return 0; }