Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages | Examples

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"

#include <string.h>
#include <stdio.h>

#include <dev/board.h>

#include <sys/heap.h>
#include <sys/thread.h>
#include <sys/timer.h>
#include <sys/socket.h>

#include <arpa/inet.h>
#include <net/route.h>
#include <netdb.h>

#include <pro/dhcp.h>


/*
 * Process client requests.
 */
void ProcessRequests(FILE * stream)
{
    u_char buff[128];
    u_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", (u_int)NutHeapAvailable());
            continue;
        }

        /*
         * List threads.
         */
        if (strncmp(buff, "threads", strlen(buff)) == 0) {
            NUTTHREADINFO *tdp;
            NUTTIMERINFO *tnp;

            fputs("220 List of threads with name,state,prio,stack,mem,timeout follows\r\n", stream);
            for (tdp = nutThreadList; tdp; tdp = tdp->td_next) {
                fputs(tdp->td_name, stream);
                fputs("\t", stream);
                switch (tdp->td_state) {
                case TDS_TERM:
                    fputs("\tTerm\t", stream);
                    break;
                case TDS_RUNNING:
                    fputs("\tRun\t", stream);
                    break;
                case TDS_READY:
                    fputs("\tReady\t", stream);
                    break;
                case TDS_SLEEP:
                    fputs("\tSleep\t", stream);
                    break;
                }
                fprintf(stream, "%u\t%u", tdp->td_priority, (u_int) tdp->td_sp - (u_int) tdp->td_memory);
                if (*((u_long *) tdp->td_memory) != DEADBEEF)
                    fputs("\tCorrupted\t", stream);
                else
                    fputs("\tOK\t", stream);

                if ((tnp = (NUTTIMERINFO *) tdp->td_timer) != 0)
                    fprintf(stream, "%lu", tnp->tn_ticks_left);
                else
                    fputs("None", stream);
                fputs("\r\n", stream);
            }
            fputs(".\r\n", stream);
            continue;
        }

        /*
         * List timer.
         */
        if (strncmp(buff, "timers", strlen(buff)) == 0) {
            NUTTIMERINFO *tnp;

            fputs("221 List of timers with ticks left and interval follows\r\n", stream);
            for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
                fprintf(stream, "%lu", tnp->tn_ticks_left);
                if (tnp->tn_ticks)
                    fprintf(stream, "\t%lu\r\n", tnp->tn_ticks);
                else
                    fputs("\tOneshot\r\n", stream);
            }
            fputs(".\r\n", stream);
            continue;
        }

        /*
         * Port status.
         */
        if (strncmp(buff, "query", strlen(buff)) == 0) {
#ifdef __AVR__
            stat = inb(PIND);
#endif
            fprintf(stream, "210 %02X\r\n", stat);
            continue;
        }

        /*
         * Reset output bit.
         */
        if (strlen(buff) > 1 && strncmp(buff, "reset", strlen(buff) - 1) == 0) {
            int mask = 0;
            switch (buff[strlen(buff) - 1]) {
            case '1':
                mask = 0x10;
                break;
            case '2':
                mask = 0x20;
                break;
            case '3':
                mask = 0x40;
                break;
            case '4':
                mask = 0x80;
                break;
            }
            if (mask) {
#ifdef __AVR__
                outb(PORTD, inb(PORTD) & ~mask);
#endif
                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 mask = 0;
            switch (buff[strlen(buff) - 1]) {
            case '1':
                mask = 0x10;
                break;
            case '2':
                mask = 0x20;
                break;
            case '3':
                mask = 0x40;
                break;
            case '4':
                mask = 0x80;
                break;
            }
            if (mask) {
#ifdef __AVR__
                outb(PORTD, inb(PORTD) | mask);
#endif
                fputs("210 OK\r\n", stream);
            } else
                fputs("410 Bad pin\r\n", stream);
            continue;
        }

        /*
         * wait for status change.
         */
        if (strncmp(buff, "wait", strlen(buff)) == 0) {
#ifdef __AVR__
            while (stat == inb(PIND))
                NutThreadYield();
            stat = inb(PIND);
#endif
            fprintf(stream, "210 %02X\r\n", stat);
            continue;
        }

        /*
         * Help.
         */
        fputs("400 List of commands follows\r\n", stream);
        fputs("memory\tQueries number of RAM bytes free\r\n", stream);
        fputs("query\tQuery digital i/o status\r\n", stream);
        fputs("reset#\tSet output bit 1..4 low\r\n", stream);
        fputs("set#\tSet output bit 1..4 high\r\n", stream);
        fputs("threads\tLists all created threads\r\n", stream);
        fputs("timers\tLists all running timers\r\n", stream);
        fputs("wait\tWaits for digital i/o change\r\n", stream);
        fputs(".\r\n", stream);
    }
}

/*
 * Init Port D
 */
void init_dio(void)
{
#ifdef __AVR__
    /*
     * Upper four pins are output pins.
     */
    outb(DDRD, 0xf0);

    /*
     * Outputs to low and inputs pulled up.
     */
    outb(PORTD, 0x0f);
#endif
}

void service(void)
{
    TCPSOCKET *sock;
    FILE *stream;

    /*
     * Loop endless for connections.
     */
    for (;;) {
        /*
         * Create a socket.
         */
        sock = NutTcpCreateSocket();

        /*
         * Listen on port 12345. If we return,
         * we got a client.
         */
        NutTcpAccept(sock, 12345);

        /*
         * 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();
}

/*
 * Main application routine. 
 *
 * Nut/OS automatically calls this entry after initialization.
 */
int main(void)
{
    u_char my_mac[] = MY_MAC;

    /*
     * Initialize digital I/O.
     */
    init_dio();

    /*
     * 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.
         */
        u_long 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();
}

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