/* * (c) danielinux 2019 * * GPLv.2 * * See LICENSE for details */ #include #include "system.h" #include "display.h" #include "systick.h" #include "button.h" #include #include #include #include "ui.h" #include "timer.h" #include "led.h" /* Uncomment for device initialization */ //#define DEVICE_INITIALIZATION static const char welcome_message0[]= " Waveblender "; static const char welcome_message1[]= "(c) danielinux "; static const char welcome_message2[]= " GPL v.2 "; static const char welcome_message3[]= "src: wb.vado.li"; static uint32_t last_action = 0; static uint32_t offset = 0; #define ST_LOCKED 0 #define ST_PIN_ENTRY 1 #define ST_UNLOCKED 2 #define MAX_PASSWORD 32 static int fsm_state = ST_LOCKED; static int sleeping = 0; static char password[MAX_PASSWORD] = {}; static int pin_idx = 0; #define SLEEP_TIME (5000) static void ui_sleep(void) { display_scroll(NULL, 0); display_clear(NULL); sleeping = 1; } static int ui_wakeup(void) { last_action = jiffies; if (sleeping) { sleeping = 0; return 1; } return 0; } void ui_msg(const char *txt) { ui_wakeup(); display_scroll(NULL, 0); display_clear(NULL); display_text(6, txt); } static uint8_t display_cur_v = 0; static uint8_t menu_selection = 0; void ui_menu_autoscroll(void) { int lines = CurrentMenu->entry_n; if ((lines < 5) || (menu_selection < 2)) display_cur_v = 0; else if (menu_selection > lines - 2) display_cur_v = 0x40 - ((lines - 4) * 8); else display_cur_v = 0x40 - ((menu_selection - 2) * 8); display_scroll(NULL, display_cur_v); } extern struct display_menu MainMenu; static void ui_display_menu_refresh(void) { const struct display_menu *menu = CurrentMenu; uint8_t vline; int i; char txt[16]; display_scroll(NULL, display_cur_v); display_clear(NULL); if (menu->render) menu->render(menu); for (i = 0; i < menu->entry_n; i++) { vline = i + 4; if (vline > 7) vline -= 8; switch (menu->entry[i].type) { case ENTRY_TYPE_TEXT: strncpy(txt, menu->entry[i].label, 15); break; case ENTRY_TYPE_HEX: { int x = *menu->entry[i].var ; int j; strncpy(txt, menu->entry[i].label, 11); for (j = strlen(menu->entry[i].label); j < 12; j++) txt[j] = ' '; if (x > 0xFF) { if (((x >> 8) & 0x0F) > 9) txt[12] = (((x >> 8) & 0x0F) - 10) + 'A'; else txt[12] = ((x >> 8) & 0x0F) + '0'; } else txt[12] = ' '; if (x > 0x0F) { if (((x >> 4) & 0x0F) > 9) txt[13] = (((x >> 4) & 0x0F) - 10) + 'A'; else txt[13] = ((x >> 4) & 0x0F) + '0'; } else txt[13] = ' '; if ((x & 0x0F) > 9) txt[14] = ((x & 0x0F) - 10) + 'A'; else txt[14] = (x & 0x0F) + '0'; } break; case ENTRY_TYPE_BOOL: { int x = *menu->entry[i].var ; int j; strncpy(txt, menu->entry[i].label, 10); for (j = strlen(menu->entry[i].label); j < 12; j++) txt[j] = ' '; if (x) strcpy(txt + 10, "[ ON]"); else strcpy(txt + 10, "[OFF]"); } break; case ENTRY_TYPE_DEC: { int x = *menu->entry[i].var ; int j; strncpy(txt, menu->entry[i].label, 11); for (j = strlen(menu->entry[i].label); j < 12; j++) txt[j] = ' '; if (x > 99) { txt[12] = (x / 100) + '0'; } else txt[12] = ' '; if (x > 9) { txt[13] = ((x % 100)/10) + '0'; } else txt[13] = ' '; txt[14] = (x % 10) + '0'; } break; } if (i == menu_selection) display_text_inverse(vline, txt); else display_text(vline, txt); } WFI(); } int ui_get_menu_selection(void) { return menu_selection; } void ui_display_menu(const struct display_menu *menu) { uint8_t i; display_clear(NULL); menu_selection = 0; display_cur_v = 0; CurrentMenu = (struct display_menu *)menu; ui_display_menu_refresh(); } void ui_button_press(uint8_t b, int hold) { int n = menu_selection; struct display_menu_entry e; switch (b) { case 'U': if (menu_selection > 0) { menu_selection--; ui_menu_autoscroll(); ui_display_menu_refresh(); } break; case 'D': if (menu_selection < CurrentMenu->entry_n - 1) { menu_selection++; ui_menu_autoscroll(); ui_display_menu_refresh(); } break; default: e = CurrentMenu->entry[n]; int changed = 0; /* Default actions for '-', '+', '*' */ if (e.var && (e.type == ENTRY_TYPE_BOOL)) { if ((*e.var) && ((b == '-') || (b == '*'))) { *e.var = 0; changed = 1; } else if ((!(*e.var)) && ((b == '+') || (b == '*'))) { *e.var = 1; changed = 1; } } else if ((e.min != e.max) && e.var && ((e.type == ENTRY_TYPE_DEC) || (e.type == ENTRY_TYPE_DEC))) { if ((*e.var > e.min) && (b == '-')) { *e.var -= e.step; changed = 1; } else if ((*e.var < e.max) && (b == '+')) { *e.var += e.step; changed = 1; } } /* Custom actions for '-', '+', '*' (after changes are applied) */ if (b != 0 && e.action) { e.action(&e, b); changed = 1; } if (changed) { ui_display_menu_refresh(); } } } void ui_init(void) { uint32_t now; int i; display_scroll(NULL, 0x3f); display_text(0, welcome_message0); display_text(1, welcome_message1); display_text(2, welcome_message2); display_text(3, welcome_message3); now = jiffies; for (i = 0x3f; i >= 0x20; i--) { display_scroll(NULL, i); while ((jiffies - now) < 20) WFI(); now = jiffies; } for (i = display_getcontrast(NULL); i >= 0; i--) { display_setcontrast(NULL, i); while ((jiffies - now) < 16) WFI(); now = jiffies; } display_scroll(NULL, display_cur_v); display_clear(NULL); display_setcontrast(NULL, 0xcf); ui_display_menu(CurrentMenu); now = jiffies; for (i = 1; i < 9; i++) { led_beat(i); while((jiffies - now) < 100) WFI(); now = jiffies; } for (i = 8; i > 0; i--) { led_beat(i); while((jiffies - now) < 100) WFI(); now = jiffies; } led_beat(0); } void ui_keepalive(uint32_t timeslice) { }