waveblender/ui.c
2020-04-26 19:46:21 +02:00

284 lines
7.7 KiB
C

/*
* (c) danielinux 2019
*
* GPLv.2
*
* See LICENSE for details
*/
#include <stdint.h>
#include "system.h"
#include "display.h"
#include "systick.h"
#include "button.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#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)
{
}