#include <avr/io.h>
#include "stdlib.h"
#include "timer.c" // XXX
#include "serial.c" // XXX
#include "spi.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 ' ';
}
}
#define LED7_DDR DDRB
#define LED7_PORT PORTB
#define LED7_OE PORTB1
// common anode?
#define LED7_ANODE 0
#define LED7_OFFSET 0
#define LED7_COUNT 2
static const uint8_t LED7SEG_FONT[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01100111, // 9
0b01110111, // A
0b01111100, // B
0b00111001, // C
0b01011110, // D
0b01111001, // E
0b01110001, // F
};
enum {
LED7SEG_DOT = 0b10000000,
};
void led7_init (void)
{
sbi(&LED7_PORT, LED7_OE); // disabled (low)
sbi(&LED7_DDR, LED7_OE); // out
}
/*
* Update external IO.
*/
void led7_update_raw (uint8_t *led7, char count)
{
int i;
for (i = 0; i < count; i++) {
char raw = LED7SEG_FONT[led7[i]];
spi_tx[LED7_OFFSET + i] = LED7_ANODE ? ~raw : raw;
}
}
void led7_update_hex (unsigned char c)
{
uint8_t led7[2];
led7[0] = c >> 4;
led7[1] = c & 0xF;
return led7_update_raw(led7, sizeof(led7));
}
void led7_update ()
{
static unsigned char i = 0;
if (i) {
// enable display
cbi(&LED7_PORT, LED7_OE);
}
led7_update_hex(led_state);
i++;
}
#define DEBUG_DDR DDRB
#define DEBUG_PORT PORTB
#define DEBUG_LED 0
int main (void)
{
led7_init();
timer_init();
serial_init();
spi_init();
// led_init();
sbi(&DEBUG_DDR, DEBUG_LED);
sei();
// start
char c;
unsigned short timeout = 0;
serial_write(state);
while (true) {
// TODO: SPI timer
led7_update();
spi_update();
// toggle
if (led_state == 0) {
timeout = 0;
cbi(&DEBUG_PORT, DEBUG_LED);
} else if (led_state == 255) {
timeout = 0;
sbi(&DEBUG_PORT, DEBUG_LED);
} else {
// as Hz
timeout = (16000 / led_state);
xbi(&DEBUG_PORT, DEBUG_LED);
}
// sleep
if (timer_sleep(timeout)) {
c = '.';
} else if ((c = serial_read())) {
// got serial data
c = input(c);
} else {
c = '?';
}
// output...
serial_write(c);
}
}