// boards/smartresponsexe/board.c #include "snek.h" #include "bb_lcd.h" #include "bb_keyboard.h" #include #include #include #include #include #define LCD_COLS 40 #define LCD_ROWS 20 #define INPUT_BUFFER_SIZE 128 static uint8_t cursor_x = 0; static uint8_t cursor_y = 0; static char input_buffer[INPUT_BUFFER_SIZE]; static uint8_t input_pos = 0; static uint8_t cursor_pos = 0; static int scroll_offset = 0; static bool cursor_visible = true; static uint32_t last_cursor_toggle = 0; volatile uint32_t _millis = 0; uint32_t board_millis(void) { uint32_t m; cli(); m = _millis; sei(); return m; } ISR(TIMER0_COMPA_vect) { _millis++; } void timer0_init(void) { TCCR0A = (1 << WGM01); TCCR0B = (1 << CS01) | (1 << CS00); OCR0A = 249; TIMSK0 = (1 << OCIE0A); } void scroll_up(void) { lcdScrollUp(); cursor_y--; if (scroll_offset < LCD_ROWS - 1) scroll_offset++; } void scroll_down(void) { if (scroll_offset > 0) scroll_offset--; } void board_init(void) { lcdFill(0); lcdDisplay(); // Display memory info extern uint8_t __heap_start, *__brkval; uint16_t free_memory = (uint16_t)&__heap_start - (uint16_t)(__brkval == 0 ? &__heap_start : __brkval); char mem_line[40]; snprintf(mem_line, sizeof(mem_line), "Free RAM: %u bytes ", free_memory); for (char *p = mem_line; *p; p++) putchar(*p); // Display SRXE-Snek splash const char *splash[] = { " _ ", " | | ", " ___ ____ _____| | _ _____ ___ ____ _ _ _____ ", " /___) _ \| ___ | |_/ |_____)___)/ ___| \ / ) ___ |", "|___ | | | | ____| _ ( |___ | | ) X (| ____|", "(___/|_| |_|_____)_| \_) (___/|_| (_/ \_)_____)", NULL }; for (int i = 0; splash[i] != NULL; i++) { for (const char *p = splash[i]; *p; p++) putchar(*p); putchar(' '); } // Show Snek version banner extern const char *snek_version; for (const char *p = snek_version; *p; p++) putchar(*p); putchar(' '); timer0_init(); sei(); lcdInit(); kbdInit(); lcdFill(0); lcdDisplay(); cursor_x = 0; cursor_y = 0; input_pos = 0; cursor_pos = 0; scroll_offset = 0; cursor_visible = true; last_cursor_toggle = board_millis(); memset(input_buffer, 0, sizeof(input_buffer)); } void display_prompt(void) { putchar('>'); putchar(' '); } void redraw_input_line(void) { lcdSetCursor(0, cursor_y * 8); for (int i = 0; i < LCD_COLS; i++) putchar(' '); cursor_x = 0; lcdSetCursor(0, cursor_y * 8); // Wait for key before prompt while (!keyboard_read()); display_prompt(); for (uint8_t i = 0; i < input_pos; i++) { putchar(input_buffer[i]); } lcdSetCursor((2 + cursor_pos) * 6, cursor_y * 8); if (cursor_visible) { lcdWriteChar('_'); } else { lcdWriteChar(' '); } lcdDisplay(); } void insert_char(char c) { if (input_pos >= INPUT_BUFFER_SIZE - 1) return; for (int i = input_pos; i > cursor_pos; i--) { input_buffer[i] = input_buffer[i - 1]; } input_buffer[cursor_pos++] = c; input_pos++; redraw_input_line(); } void delete_char(void) { if (cursor_pos == 0) return; for (int i = cursor_pos - 1; i < input_pos - 1; i++) { input_buffer[i] = input_buffer[i + 1]; } input_pos--; cursor_pos--; input_buffer[input_pos] = '\0'; redraw_input_line(); } void handle_input_char(char c) { if (c == '\n' || c == '\r') { putchar('\n'); input_buffer[input_pos] = '\0'; snek_eval_line(input_buffer); input_pos = 0; cursor_pos = 0; memset(input_buffer, 0, sizeof(input_buffer)); display_prompt(); } else if (c == 8 || c == 127) { delete_char(); } else if (c == 0x1B) { // Escape key - ignored } else if (c == 0x82) { if (cursor_pos > 0) { cursor_pos--; redraw_input_line(); } } else if (c == 0x83) { if (cursor_pos < input_pos) { cursor_pos++; redraw_input_line(); } } else if (c == 0x80) { scroll_up(); } else if (c == 0x81) { scroll_down(); } else if (c >= 32 && c <= 126) { insert_char(c); } } int putchar(int c) { if (c == '\n') { cursor_x = 0; cursor_y++; if (cursor_y >= LCD_ROWS) { scroll_up(); } return c; } else if (c == '\r') { cursor_x = 0; return c; } else if (c == 8 || c == 127) { if (cursor_x > 0) { cursor_x--; } else if (cursor_y > 0) { cursor_y--; cursor_x = LCD_COLS - 1; } lcdSetCursor(cursor_x * 6, cursor_y * 8); lcdWriteChar(' '); lcdSetCursor(cursor_x * 6, cursor_y * 8); lcdDisplay(); return c; } lcdSetCursor(cursor_x * 6, cursor_y * 8); lcdWriteChar((char)c); cursor_x++; if (cursor_x >= LCD_COLS) { cursor_x = 0; cursor_y++; if (cursor_y >= LCD_ROWS) { scroll_up(); } } lcdDisplay(); return c; } void display_init(void) { lcdFill(0); lcdDisplay(); cursor_x = 0; cursor_y = 0; } void display_clear(void) { lcdFill(0); cursor_x = 0; cursor_y = 0; lcdDisplay(); } void display_draw(void) { lcdDisplay(); } void display_putchar(char c) { putchar(c); } void keyboard_init(void) { // Already initialized in board_init } uint8_t keyboard_read(void) { return kbdGetChar(); } void board_loop(void) { uint8_t c = keyboard_read(); if (c) { handle_input_char((char)c); last_cursor_toggle = board_millis(); cursor_visible = true; } else { uint32_t now = board_millis(); if (now - last_cursor_toggle > 500) { cursor_visible = !cursor_visible; last_cursor_toggle = now; redraw_input_line(); } } }