aboutsummaryrefslogtreecommitdiff
path: root/src/menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/menu.c')
-rw-r--r--src/menu.c269
1 files changed, 269 insertions, 0 deletions
diff --git a/src/menu.c b/src/menu.c
new file mode 100644
index 0000000..51f7c31
--- /dev/null
+++ b/src/menu.c
@@ -0,0 +1,269 @@
+#include <zeta.h>
+#include <hardware.h>
+#include <tty.h>
+#include <input.h>
+#include <stdio.h>
+#include <string.h>
+
+struct time {
+ uint8_t second;
+ uint8_t minute;
+ uint8_t hour;
+ uint8_t wkday;
+ uint8_t date;
+ uint8_t month;
+ uint8_t year;
+};
+
+struct value {
+ uint8_t roll;
+ int val;
+ int min, max;
+};
+
+void
+value_inc(struct value *v, int d)
+{
+ v->val += d;
+
+ if (v->roll) {
+ if (v->val > v->max)
+ v->val = v->min;
+ else if(v->val < v->min)
+ v->val = v->max - 1;
+ } else {
+ v->val = clamp(v->val, v->min, v->max);
+ }
+}
+
+enum item_type {
+ VOID,
+ BUTTON,
+ VALUE,
+ LABEL
+};
+
+void
+draw_time(void)
+{
+ char buf[32];
+ struct time time;
+ memset(&time, 0, sizeof(time));
+ // rtc_get_bcd_time(&time);
+ sprintf(buf, "20%hhd%hhd-%hhd%hhd-%hhd%hhd %hhd%hhd:%hhd%hhd:%hhd%hhd",
+ time.year >> 4, time.year & 0xF,
+ time.month >> 4, time.month & 0xF,
+ time.date >> 4, time.date & 0xF,
+ time.hour >> 4, time.hour & 0xF,
+ time.minute >> 4, time.minute & 0xF,
+ time.second >> 4, time.second & 0xF);
+ mvaddstr(5, 1, buf);
+}
+
+void
+draw_battery(void)
+{
+ uint16_t soc = 100; // bat_state_of_charge();
+ char buf[16];
+ sprintf(buf, "%u%%", soc);
+ mvaddstr(7, 1, buf);
+}
+
+void
+set_time(void);
+
+struct item {
+ uint8_t type;
+ const char *text;
+ union {
+ void (*action)(void);
+ struct value value;
+ } v;
+};
+
+struct menu_entry {
+ const char *text;
+ struct item items[8];
+};
+
+struct menu_entry menu[] = {
+ {
+ .text = "TIME ",
+ .items = {
+ {.type = LABEL, .v = {.action = draw_time}},
+ {.type = LABEL, .v = {.action = draw_battery}},
+ {.type = VOID},
+ {.type = VOID},
+ {.type = VOID},
+ {.type = VOID},
+ {.type = VOID},
+ {.type = VOID}
+ }
+ },
+ {
+ .text = "CONF ",
+ .items = {
+ {.type = VALUE, .text = "SEC", .v = {.value = {1, 0, 0, 59}}},
+ {.type = VALUE, .text = "MIN", .v = {.value = {1, 0, 0, 59}}},
+ {.type = VALUE, .text = "HOUR", .v = {.value = {1, 0, 0, 23}}},
+ {.type = VALUE, .text = "WKDAY", .v = {.value = {1, 0, 1, 7}}},
+ {.type = VALUE, .text = "DATE", .v = {.value = {1, 1, 1, 31}}},
+ {.type = VALUE, .text = "MONTH", .v = {.value = {1, 1, 1, 12}}},
+ {.type = VALUE, .text = "YEAR", .v = {.value = {1, 0, 0, 3000}}},
+ {.type = BUTTON, .text = "LOAD", .v = {.action = set_time}}
+ }
+ }
+};
+
+void
+set_time(void)
+{
+ struct time time;
+ struct item *items = menu[1].items;
+
+ time.second = items[0].v.value.val;
+ time.minute = items[1].v.value.val;
+ time.hour = items[2].v.value.val;
+ time.wkday = items[3].v.value.val;
+ time.date = items[4].v.value.val;
+ time.month = items[5].v.value.val;
+ time.year = items[6].v.value.val;
+
+ // rtc_set_time(&time);
+}
+
+enum direction {
+ VERTICAL,
+ HORIZONTAL
+};
+
+static uint8_t dir = HORIZONTAL;
+static int menu_index = 0;
+static int sub_menu_index = -1;
+static int edit = 0;
+
+#define BUILD_VERSION "20241117"
+
+void
+draw_menu(void)
+{
+ const char *build_version = BUILD_VERSION;
+ const int padding = (TTY_WIDTH - 8 * LENGTH(menu)) / 2;
+
+ mvaddstr(1, 0, " ************* THE SOUTHERN STAR MK II ************* ");
+ mvaddch(3, 1, dir == HORIZONTAL ? '>' : '^');
+
+ for (int i = 0; i < LENGTH(menu); ++i) {
+ if (i == menu_index) {
+ swap_colors();
+ mvaddstr(3, padding + i * 8, menu[i].text);
+ swap_colors();
+ } else {
+ mvaddstr(3, padding + i * 8, menu[i].text);
+ }
+ }
+
+ const struct menu_entry *entry = &menu[menu_index];
+
+ for (int i = 0; i < LENGTH(entry->items); ++i) {
+ mvaddstr(5 + 2 * i, 1, " ");
+
+ if (entry->items[i].type == VOID)
+ continue;
+
+ if (i == sub_menu_index && menu_index != 0) {
+ swap_colors();
+ mvaddstr(5 + 2 * i, 1, entry->items[i].text);
+ swap_colors();
+ } else {
+ mvaddstr(5 + 2 * i, 1, entry->items[i].text);
+ }
+
+ if (entry->items[i].type == VALUE) {
+ char buf[16];
+ sprintf(buf, "%8d", entry->items[i].v.value.val);
+ mvaddstr(5 + 2 * i, 6, buf);
+ }
+
+ if (entry->items[i].type == LABEL) {
+ entry->items[i].v.action();
+ }
+ }
+
+ mvaddstr(TTY_HEIGHT - 2, TTY_WIDTH - strlen(build_version) - 1, build_version);
+}
+
+void
+dir_callback(void)
+{
+ if (sub_menu_index >= 0) {
+ struct item *item = &menu[menu_index].items[sub_menu_index];
+
+ switch (item->type) {
+ case VALUE:
+ edit = !edit;
+ break;
+
+ case BUTTON:
+ if (item->v.action)
+ item->v.action();
+ break;
+ }
+ } else {
+ dir = (dir + 1) & 1;
+ draw_menu();
+ }
+}
+
+#define CW 0x10
+#define CCW 0x20
+
+typedef void (*callback)(void);
+volatile callback callbacks[5] = {NULL, NULL, NULL, NULL, NULL};
+
+void
+_menu(void)
+{
+ callbacks[0] = dir_callback;
+ clear_screen();
+ setcur(0, 0);
+ draw_menu();
+
+ while (1) {
+ DI;
+ while (!fifo_empty(&input_fifo)) {
+ u8 event = fifo_pop(&input_fifo);
+ if (event == CW) {
+ if (dir == HORIZONTAL) {
+ if (++menu_index >= LENGTH(menu))
+ menu_index = 0;
+ } else {
+ if (edit) {
+ value_inc(&menu[menu_index].items[sub_menu_index].v.value, 1);
+ } else {
+ if (++sub_menu_index >= LENGTH(menu[0].items))
+ sub_menu_index = 0;
+ }
+ }
+ draw_menu();
+ } else if (event == CCW) {
+ if (dir == HORIZONTAL) {
+ if (--menu_index < 0)
+ menu_index = LENGTH(menu) - 1;
+ } else {
+ if (edit) {
+ value_inc(&menu[menu_index].items[sub_menu_index].v.value, -1);
+ } else {
+ if (--sub_menu_index < -1)
+ sub_menu_index = LENGTH(menu[0].items) - 1;
+ }
+ }
+ draw_menu();
+ } else {
+ if (callbacks[event])
+ callbacks[event]();
+ }
+ }
+ EI;
+ }
+}