#include <zeta.h>
#include <hardware.h>
#include <tty.h>
#include <input.h>
#include <stdio.h>
#include <string.h>
struct time {
u8 second;
u8 minute;
u8 hour;
u8 wkday;
u8 date;
u8 month;
u8 year;
};
struct value {
u8 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)
{
u16 soc = 100; // bat_state_of_charge();
char buf[16];
sprintf(buf, "%u%%", soc);
mvaddstr(7, 1, buf);
}
void
set_time(void);
struct item {
u8 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 u8 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) {
while (!fifo_empty(&input_fifo)) {
DI;
u8 event = fifo_pop(&input_fifo);
EI;
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]();
}
}
}
}