|
@ -3,7 +3,9 @@ |
|
|
#include <ctype.h> |
|
|
#include <ctype.h> |
|
|
#include <stdbool.h> |
|
|
#include <stdbool.h> |
|
|
#include <setjmp.h> |
|
|
#include <setjmp.h> |
|
|
|
|
|
#include <avr/interrupt.h> |
|
|
#include <avr/pgmspace.h> |
|
|
#include <avr/pgmspace.h> |
|
|
|
|
|
#include <avr/eeprom.h> |
|
|
#include "../config.h" |
|
|
#include "../config.h" |
|
|
#include "../borg_hw/borg_hw.h" |
|
|
#include "../borg_hw/borg_hw.h" |
|
|
#ifdef JOYSTICK_SUPPORT |
|
|
#ifdef JOYSTICK_SUPPORT |
|
@ -14,27 +16,27 @@ |
|
|
#include "uart.h" |
|
|
#include "uart.h" |
|
|
#include "uart_commands.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; |
|
|
uint8_t g_rx_index; |
|
|
|
|
|
|
|
|
extern jmp_buf newmode_jmpbuf; |
|
|
extern jmp_buf newmode_jmpbuf; |
|
|
volatile unsigned char mode; |
|
|
volatile unsigned char mode; |
|
|
|
|
|
|
|
|
void uartcmd_clear_buffer(void) { |
|
|
#if !(defined(eeprom_update_block) && \ |
|
|
char *p = &g_rx_buffer[0]; |
|
|
((E2PAGESIZE == 2) || (E2PAGESIZE == 4) || (E2PAGESIZE == 8))) |
|
|
for (uint8_t i = UART_SCROLL_BUFFER_SIZE; i--;) { |
|
|
char const UART_STR_NOTIMPL[] PROGMEM = "\r\nnot implemented"; |
|
|
*p++ = 0; |
|
|
#endif |
|
|
} |
|
|
|
|
|
g_rx_index = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
char const UART_STR_PROMPT[] PROGMEM = "\r\n> "; |
|
|
char const UART_STR_PROMPT[] PROGMEM = "\r\n> "; |
|
|
char const UART_STR_ERROR[] PROGMEM = "\r\ntransmission error"; |
|
|
char const UART_STR_ERROR[] PROGMEM = "\r\ntransmission error"; |
|
|
char const UART_STR_UNKNOWN[] PROGMEM = "\r\nunknown command"; |
|
|
char const UART_STR_UNKNOWN[] PROGMEM = "\r\nunknown command"; |
|
|
char const UART_STR_TOOLONG[] PROGMEM = "\r\ncommand to long"; |
|
|
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_HELP[] PROGMEM = "help"; |
|
|
char const UART_CMD_MSG[] PROGMEM = "msg "; |
|
|
char const UART_CMD_MSG[] PROGMEM = "msg "; |
|
|
char const UART_CMD_NEXT[] PROGMEM = "next"; |
|
|
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_RESET[] PROGMEM = "reset"; |
|
|
char const UART_CMD_SCROLL[] PROGMEM = "scroll "; |
|
|
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(); |
|
|
int uart_result = uart_getc(); |
|
|
|
|
|
|
|
|
switch (uart_result & 0xFF00u) { |
|
|
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(); |
|
|
uartcmd_clear_buffer(); |
|
|
uart_puts_p(UART_STR_TOOLONG); |
|
|
uart_puts_p(UART_STR_TOOLONG); |
|
|
uart_puts_p(UART_STR_PROMPT); |
|
|
uart_puts_p(UART_STR_PROMPT); |
|
@ -81,40 +197,25 @@ bool uartcmd_read_until_enter(void) { |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Checks for entered commands and dispatches them to the appropriate handler. |
|
|
|
|
|
*/ |
|
|
void uartcmd_process(void) { |
|
|
void uartcmd_process(void) { |
|
|
if (uartcmd_read_until_enter()) { |
|
|
if (uartcmd_processing_allowed() && uartcmd_read_until_enter()) { |
|
|
if (!strncmp_P(g_rx_buffer, UART_CMD_HELP, 4)) { |
|
|
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); |
|
|
uart_puts_p(UART_STR_HELP); |
|
|
} else if (!strncmp_P(g_rx_buffer, UART_CMD_MSG, 4)) { |
|
|
} else if (!strncmp_P(g_rx_buffer, UART_CMD_MSG, 4)) { |
|
|
g_rx_buffer[1] = '<'; |
|
|
uartcmd_simple_message(); |
|
|
g_rx_buffer[2] = '/'; |
|
|
} else if (!strncmp_P(g_rx_buffer, UART_CMD_NEXT, UART_BUFFER_SIZE)) { |
|
|
g_rx_buffer[3] = '#'; |
|
|
uartcmd_next_anim(); |
|
|
// text must not be longer than the scroll text buffer
|
|
|
} else if (!strncmp_P(g_rx_buffer, UART_CMD_PREV, UART_BUFFER_SIZE)) { |
|
|
g_rx_buffer[1 + SCROLLTEXT_BUFFER_SIZE - 1] = 0; |
|
|
uartcmd_prev_anim(); |
|
|
scrolltext(&g_rx_buffer[1]); |
|
|
} else if (!strncmp_P(g_rx_buffer, UART_CMD_RESET, UART_BUFFER_SIZE)) { |
|
|
} else if (!strncmp_P(g_rx_buffer, UART_CMD_NEXT, 4)) { |
|
|
uartcmd_reset_borg(); |
|
|
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(); |
|
|
|
|
|
} else if (!strncmp_P(g_rx_buffer, UART_CMD_SCROLL, 7)) { |
|
|
} else if (!strncmp_P(g_rx_buffer, UART_CMD_SCROLL, 7)) { |
|
|
// text must not be longer than the scroll text buffer
|
|
|
uartcmd_scroll_message(); |
|
|
g_rx_buffer[7 + SCROLLTEXT_BUFFER_SIZE - 1] = 0; |
|
|
|
|
|
scrolltext(&g_rx_buffer[7]); |
|
|
|
|
|
} else { |
|
|
} else { |
|
|
uart_puts_p(UART_STR_UNKNOWN); |
|
|
uart_puts_p(UART_STR_UNKNOWN); |
|
|
} |
|
|
} |
|
|