src/hello.c
author Tero Marttila <terom@paivola.fi>
Thu, 03 Apr 2014 22:24:46 +0300
changeset 54 ec42f36d8614
parent 53 dfe67409fbcd
child 55 04c625712e35
permissions -rw-r--r--
hello: interactive console
#include <avr/io.h>

#include "stdlib.h"
#include "timer.c" // XXX
#include "serial.c" // XXX

static enum state {
    START       = '\n',
    CMD_SET     = 's',
    ARG_CHAR    = '0',
    ERROR       = '!',
} state = START, cmd = 0;

static enum {
    CMD_LED_1   = 0,
} cmd_led = 0;

static char arg_char;

static unsigned char led_state = 0;

int command (enum state cmd)
{
    switch (cmd) {
        case CMD_SET:
            led_state = arg_char;

            return 0;

        default:
            return 1;
    }
}

char input (char c)
{
    if (c == '\r') {
        char ret = '?';

        // command state
        switch (state) {
            case START:
                cmd = 0;
                break;

            case CMD_SET:
                break;

            case ARG_CHAR:
                break;

            case ERROR:
                cmd = 0;
                break;
        }

        // command
        if (!cmd) {
            ret = ' ';
        } else if (command(cmd)) {
            ret = '!';
        } else {
            ret = '\n';
        }
        
        // return to START with response
        state = START;
        return ret;

    } else if (31 < c && c < 128) {
        // process input char
        switch (state) {
            case START:
                if (c == 's') {
                    cmd = CMD_SET;
                    state = ARG_CHAR;
                    arg_char = 0;
                    return state;

                } else if (c == 'S') {
                    cmd = state = CMD_SET;
                    arg_char = 255;
                    return state;
                }
            break;

            /* 
            case CMD_SET:
                if (c == '1') {
                    cmd_led = CMD_LED_1;
                    state = ARG_CHAR;
                    arg_char = 0;
                } else {
                    state = ERROR;
                }

                break;
            */
            case ARG_CHAR:
                if (c >= '0' && c <= '9') {
                    arg_char *= 10;
                    arg_char += (c - '0');

                    return c;
                }
            break;
        }

        // reject
        state = ERROR;
        return ERROR;

    } else {
        // ignore
        return ' ';
    }
}

int main (void)
{
    timer_init();
    serial_init();

    // led_init();
    sbi(&DDRB, DDB5);

    sei();

    // start
    char c;
    unsigned short timeout = 0;
        
    serial_write(state);

    while (true) {
        // toggle
        if (led_state == 0) {
            timeout = 0;
            cbi(&PORTB, PORTB5);

        } else if (led_state == 255) {
            timeout = 0;
            sbi(&PORTB, PORTB5);

        } else {
            // as Hz
            timeout = (16000 / led_state);
            xbi(&PORTB, PORTB5);
        }
        
        // sleep
        if (timer_sleep(timeout)) {
            c = '.';

        } else if ((c = serial_read())) {
            // got serial data
            c = input(c);

        } else {
            c = '?';
        }
        
        // output...
        serial_write(c);
    }
}