diff --git a/src/uart/uart_commands.c b/src/uart/uart_commands.c index 0abac0c..6cf21c7 100644 --- a/src/uart/uart_commands.c +++ b/src/uart/uart_commands.c @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include #include "../config.h" #include "../borg_hw/borg_hw.h" #ifdef JOYSTICK_SUPPORT @@ -14,27 +16,27 @@ #include "uart.h" #include "uart_commands.h" -#define UART_SCROLL_BUFFER_SIZE (SCROLLTEXT_BUFFER_SIZE + 8) -char g_rx_buffer[UART_SCROLL_BUFFER_SIZE]; + +#define UART_BUFFER_SIZE (SCROLLTEXT_BUFFER_SIZE + 8) +char g_rx_buffer[UART_BUFFER_SIZE]; uint8_t g_rx_index; extern jmp_buf newmode_jmpbuf; volatile unsigned char mode; -void uartcmd_clear_buffer(void) { - char *p = &g_rx_buffer[0]; - for (uint8_t i = UART_SCROLL_BUFFER_SIZE; i--;) { - *p++ = 0; - } - g_rx_index = 0; -} +#if !(defined(eeprom_update_block) && \ + ((E2PAGESIZE == 2) || (E2PAGESIZE == 4) || (E2PAGESIZE == 8))) +char const UART_STR_NOTIMPL[] PROGMEM = "\r\nnot implemented"; +#endif char const UART_STR_PROMPT[] PROGMEM = "\r\n> "; char const UART_STR_ERROR[] PROGMEM = "\r\ntransmission error"; char const UART_STR_UNKNOWN[] PROGMEM = "\r\nunknown command"; char const UART_STR_TOOLONG[] PROGMEM = "\r\ncommand to long"; -char const UART_STR_HELP[] PROGMEM = "\r\nhelp msg next prev reset scroll"; +char const UART_STR_HELP[] PROGMEM = "\r\nallowed commands: " + "erase help msg next prev reset scroll"; +char const UART_CMD_ERASE[] PROGMEM = "erase"; char const UART_CMD_HELP[] PROGMEM = "help"; char const UART_CMD_MSG[] PROGMEM = "msg "; char const UART_CMD_NEXT[] PROGMEM = "next"; @@ -42,8 +44,122 @@ char const UART_CMD_PREV[] PROGMEM = "prev"; char const UART_CMD_RESET[] PROGMEM = "reset"; char const UART_CMD_SCROLL[] PROGMEM = "scroll "; -bool uartcmd_read_until_enter(void) { - while (g_rx_index < (UART_SCROLL_BUFFER_SIZE - 1)) { + +bool g_uartcmd_permit_processing = 1; + + +/** + * Checks if command processing is allowed. + */ +static bool uartcmd_processing_allowed(void) { + bool result; + cli(); + result = g_uartcmd_permit_processing; + sei(); + return result; +} + + +/** + * Clears the command string buffer. + */ +static void uartcmd_clear_buffer(void) { + char *p = &g_rx_buffer[0]; + for (uint8_t i = UART_BUFFER_SIZE; i--;) { + *p++ = 0; + } + g_rx_index = 0; +} + + +/** + * Erases the complete EEPROM to reset counters and high score tables. + */ +static void uartcmd_erase_eeprom(void) { +#if defined(eeprom_update_block) && \ + ((E2PAGESIZE == 2) || (E2PAGESIZE == 4) || (E2PAGESIZE == 8)) + uint8_t const eeclear[] = +# if E2PAGESIZE == 8 + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +# elif E2PAGESIZE == 4 + {0xFF, 0xFF, 0xFF, 0xFF}; +# elif E2PAGESIZE == 2 + {0xFF, 0xFF}; +# endif + for (void *ee = 0; ee < (void *)E2END; ee += E2PAGESIZE) { + eeprom_update_block(eeclear, ee, E2PAGESIZE); + } +#else + uart_puts_p(UART_STR_NOTIMPL); +#endif +} + + +/** + * Displays a simple message without the need to prefix a scrolltext command. + */ +static void uartcmd_simple_message(void) { + g_rx_buffer[1] = '<'; + g_rx_buffer[2] = '/'; + g_rx_buffer[3] = '#'; + // text must not be longer than the scroll text buffer + g_rx_buffer[1 + SCROLLTEXT_BUFFER_SIZE - 1] = 0; + scrolltext(&g_rx_buffer[1]); +} + + +/** + * Displays a message which may use the complete range of scrolltext commands. + */ +static void uartcmd_scroll_message(void) { + // text must not be longer than the scroll text buffer + g_rx_buffer[7 + SCROLLTEXT_BUFFER_SIZE - 1] = 0; + scrolltext(&g_rx_buffer[7]); +} + + +/** + * As long there's no game active, jump to the next animation. + */ +static void uartcmd_next_anim(void) { + uart_puts_p(UART_STR_PROMPT); + uartcmd_clear_buffer(); +#ifdef JOYSTICK_SUPPORT + if (waitForFire) +#endif + longjmp(newmode_jmpbuf, mode); +} + + +/** + * As long there's no game active, jump to the previous animation. + */ +static void uartcmd_prev_anim(void) { + uart_puts_p(UART_STR_PROMPT); + uartcmd_clear_buffer(); + if (mode > 1) { +#ifdef JOYSTICK_SUPPORT + if (waitForFire) +#endif + longjmp(newmode_jmpbuf, mode - 2); + } +} + + +/** + * Perform a MCU reset by triggering the watchdog. + */ +static void uartcmd_reset_borg() { + timer0_off(); +} + + +/** + * Appends new characters the buffer until a line break is entered. + * @return true if a line break was entered, false otherwise. + */ +static bool uartcmd_read_until_enter(void) { + while (g_rx_index < (UART_BUFFER_SIZE - 1)) { int uart_result = uart_getc(); switch (uart_result & 0xFF00u) { @@ -73,7 +189,7 @@ bool uartcmd_read_until_enter(void) { } } - if (g_rx_index >= (UART_SCROLL_BUFFER_SIZE - 1)) { + if (g_rx_index >= (UART_BUFFER_SIZE - 1)) { uartcmd_clear_buffer(); uart_puts_p(UART_STR_TOOLONG); uart_puts_p(UART_STR_PROMPT); @@ -81,40 +197,25 @@ bool uartcmd_read_until_enter(void) { return false; } +/** + * Checks for entered commands and dispatches them to the appropriate handler. + */ void uartcmd_process(void) { - if (uartcmd_read_until_enter()) { - if (!strncmp_P(g_rx_buffer, UART_CMD_HELP, 4)) { + if (uartcmd_processing_allowed() && uartcmd_read_until_enter()) { + if (!strncmp_P(g_rx_buffer, UART_CMD_ERASE, 5)) { + uartcmd_erase_eeprom(); + } else if (!strncmp_P(g_rx_buffer, UART_CMD_HELP, UART_BUFFER_SIZE)) { uart_puts_p(UART_STR_HELP); } else if (!strncmp_P(g_rx_buffer, UART_CMD_MSG, 4)) { - g_rx_buffer[1] = '<'; - g_rx_buffer[2] = '/'; - g_rx_buffer[3] = '#'; - // text must not be longer than the scroll text buffer - g_rx_buffer[1 + SCROLLTEXT_BUFFER_SIZE - 1] = 0; - scrolltext(&g_rx_buffer[1]); - } else if (!strncmp_P(g_rx_buffer, UART_CMD_NEXT, 4)) { - uart_puts_p(UART_STR_PROMPT); - uartcmd_clear_buffer(); -#ifdef JOYSTICK_SUPPORT - if (waitForFire) -#endif - longjmp(newmode_jmpbuf, mode); - } else if (!strncmp_P(g_rx_buffer, UART_CMD_PREV, 4)) { - uart_puts_p(UART_STR_PROMPT); - uartcmd_clear_buffer(); - if (mode > 1) { -#ifdef JOYSTICK_SUPPORT - if (waitForFire) -#endif - longjmp(newmode_jmpbuf, mode - 2); - } - } else if (!strncmp_P(g_rx_buffer, UART_CMD_RESET, - UART_SCROLL_BUFFER_SIZE)) { - timer0_off(); + uartcmd_simple_message(); + } else if (!strncmp_P(g_rx_buffer, UART_CMD_NEXT, UART_BUFFER_SIZE)) { + uartcmd_next_anim(); + } else if (!strncmp_P(g_rx_buffer, UART_CMD_PREV, UART_BUFFER_SIZE)) { + uartcmd_prev_anim(); + } else if (!strncmp_P(g_rx_buffer, UART_CMD_RESET, UART_BUFFER_SIZE)) { + uartcmd_reset_borg(); } else if (!strncmp_P(g_rx_buffer, UART_CMD_SCROLL, 7)) { - // text must not be longer than the scroll text buffer - g_rx_buffer[7 + SCROLLTEXT_BUFFER_SIZE - 1] = 0; - scrolltext(&g_rx_buffer[7]); + uartcmd_scroll_message(); } else { uart_puts_p(UART_STR_UNKNOWN); } diff --git a/src/uart/uart_commands.h b/src/uart/uart_commands.h index 074583f..fc5282b 100644 --- a/src/uart/uart_commands.h +++ b/src/uart/uart_commands.h @@ -8,6 +8,31 @@ #ifndef UART_COMMANDS_H_ #define UART_COMMANDS_H_ +#include +#include + +extern bool g_uartcmd_permit_processing; + +/** + * Enables UART command processing. + */ +inline static void uartcmd_permit(void) { + cli(); + g_uartcmd_permit_processing = true; + sei(); +} + + +/** + * Disables UART command processing. + */ +inline static void uartcmd_forbid(void) { + cli(); + g_uartcmd_permit_processing = false; + sei(); +} + + void uartcmd_process(void); #endif /* UART_COMMANDS_H_ */