stub of settings

master
Ondřej Hruška 2 years ago
parent 2eefdf6325
commit f5d8405bdf
  1. 5
      CMakeLists.txt
  2. 48
      src/app_config.c
  3. 19
      src/app_config.h
  4. 4
      src/lcd/cgram.c
  5. 4
      src/lcd/cgrom.c
  6. 8
      src/main.c
  7. 5
      src/screens/app_gui.c
  8. 1
      src/screens/app_gui.h
  9. 2
      src/screens/screen_cyklus.c
  10. 28
      src/screens/screen_home.c
  11. 144
      src/screens/screen_settings.c

@ -22,9 +22,10 @@ add_executable(zavlaha
src/lcd/lcdbuf.c
src/screens/app_gui.c
src/screens/screen_home.c
src/screens/screen_settings.c
src/screens/screen_cyklus.c
src/app_io.c
src/app_config.c
src/screens/screen_cyklus.c)
src/app_config.c)
# Add pico_stdlib library which aggregates commonly used features
target_link_libraries(zavlaha pico_stdlib hardware_i2c hardware_adc hardware_irq)

@ -2,20 +2,58 @@
* TODO file description
*/
#include <string.h>
#include <stdio.h>
#include "app_config.h"
#include "ee.h"
#define APPCONFIG_EE_BASE_ADDR 0
// TODO sensible defaults, loading and saving to/from EE
struct AppConfig app_config = {
struct AppConfig app_config;
static const struct AppConfig DEFAULTS = {
.circuit_base_time_s = 10, // for a test
.circuit_time_percent = {30, 60, 90, 100}, // for a test
.schedules = {
{6, 45},
{255, 0},
{255, 0},
{255, 0}
{true, 6, 45},
{false, 255, 0},
{false, 255, 0},
{false, 255, 0}
},
.moisture_enable = true,
.moisture_dry = 2800,
.moisture_wet = 1600,
.moisture_threshold_percent = 70,
};
static void load_fallback_config() {
// Read failed, load defaults
memcpy(&app_config, &DEFAULTS, sizeof(struct AppConfig));
}
void appconfig_load()
{
uint8_t magic = 0;
if (0 != ee_read(APPCONFIG_EE_BASE_ADDR, &magic, 1) || magic != APPCONFIG_VERSION) {
printf("Couldn't read EE to check magic!\r\n");
load_fallback_config();
return;
}
if (0 != ee_read(APPCONFIG_EE_BASE_ADDR, (uint8_t *) &app_config, APPCONFIG_SIZE)) {
printf("Couldn't read EE to load config!\r\n");
load_fallback_config();
}
}
void appconfig_save()
{
printf("PERSISTENCE DISABLED - NOT SAVING\r\n");
return; // FIXME - when all GUIs are finished, add persistence
// whatever, just write everything
if (0 != ee_write(APPCONFIG_EE_BASE_ADDR, (const uint8_t *) &app_config, APPCONFIG_SIZE)) {
printf("Couldn't write EE!");
}
}

@ -11,23 +11,32 @@
#define CIRCUIT_COUNT 4
#define SCHEDULE_COUNT 4
#define UNUSED_SCHEDULE_HOUR 0xFF
struct ScheduleTime {
struct __attribute__((packed)) ScheduleTime {
bool enable;
uint8_t h;
uint8_t m;
};
struct AppConfig {
struct __attribute__((packed)) AppConfig {
uint8_t magic_version;
uint16_t circuit_base_time_s;
uint8_t circuit_time_percent[CIRCUIT_COUNT]; // 0% can be used to disable a branch
struct ScheduleTime schedules[SCHEDULE_COUNT]; // 0xFF hour is used to disable the slot
bool scheduler_enable;
struct ScheduleTime schedules[SCHEDULE_COUNT];
bool moisture_enable;
uint16_t moisture_dry;
uint16_t moisture_wet;
uint8_t moisture_threshold_percent;
};
#define APPCONFIG_SIZE sizeof(struct AppConfig)
#define APPCONFIG_VERSION 0b11100001
extern struct AppConfig app_config;
void appconfig_load();
void appconfig_save();
#endif //ZAVLAHA_APP_CONFIG_H

@ -499,11 +499,11 @@ const struct LcdBuf_CGRAM_Symbol CGRAM_CZ[] = {
.fallback = '*',
.data = {
0b11111,
0b11011,
0b01010,
0b10001,
0b00000,
0b10001,
0b01010,
0b11011,
0b11111,
},
},

@ -97,8 +97,8 @@ const struct LcdBuf_CGROM_Entry CGROM_A00[] = {
{.address = 123, .symbol = "{"},
{.address = 124, .symbol = "|"},
{.address = 125, .symbol = "}"},
{.address = 126, .symbol = ""},
{.address = 127, .symbol = ""},
{.address = 126, .symbol = ""},
{.address = 127, .symbol = ""},
// lots of japanese symbols - add them yourself if you need them
{.address = 0xA2, .symbol = ""},

@ -11,6 +11,7 @@
#include "ee.h"
#include "lcd/lcdbuf.h"
#include "screens/app_gui.h"
#include "app_config.h"
/*
@ -71,7 +72,7 @@ void irq_uart() {
}
}
int main()
int __attribute__((noreturn)) main()
{
// picotool binary info
bi_decl(bi_1pin_with_name(PIN_LED, "LED"));
@ -123,11 +124,14 @@ int main()
adc_init();
adc_gpio_init(PIN_MOISTURE);
appconfig_load();
lcd_init();
gui_init();
for(;;) {
// Check if any key was pushed
uint32_t interrupts = save_and_disable_interrupts();
GuiEvent event = GUI_EVENT_NONE;
if (keypad_buffer[keypad_buffer_rp] != 0) {
@ -142,6 +146,8 @@ int main()
restore_interrupts(interrupts);
gui_loop_iter(event);
// TODO scheduler logic
}
//

@ -62,6 +62,11 @@ void gui_loop_iter(GuiEvent message) {
/** Switch to a different screen handler.
* If "init" is true, immediately call it with the init event. */
void switch_screen(screen_t pScreen, bool init) {
if (s_app.screen == pScreen) {
// already, no op
return;
}
s_app.screen = pScreen;
LcdBuffer_Clear(&lcd);

@ -49,6 +49,7 @@ void request_paint();
void screen_home(GuiEvent event);
void screen_cyklus(GuiEvent event);
void screen_settings(GuiEvent event);
// XXX other prototypes
struct State {

@ -12,6 +12,8 @@
#include "ds_rtc.h"
#include "app_io.h"
// TODO
void screen_cyklus(GuiEvent event)
{

@ -16,7 +16,6 @@ static uint32_t last_time = 0;
static struct rtc_time rtc_time = {};
static uint16_t moisture = 0;
static char showbuf[20];
static uint8_t showbuf_wp = 0;
void screen_home(GuiEvent event)
@ -26,7 +25,6 @@ void screen_home(GuiEvent event)
switch (event) {
case GUI_EVENT_SCREEN_INIT:
memset(showbuf, ' ', sizeof(showbuf));
// pass
case GUI_EVENT_SCREEN_TICK:
if (elapsed >= 100) {
@ -37,9 +35,8 @@ void screen_home(GuiEvent event)
}
break;
case GUI_EVENT_PAINT:
LcdBuffer_Write(&lcd, 0, 0, showbuf);
case GUI_EVENT_PAINT:;
// TODO
uint32_t moisture_pt = ((uint32_t)(moisture > 2800 ? 0 : (2800 - moisture)) * 100) / (2800 - 1600);
sprintf(stmp, " %2d:%02d:%02d %3d%% 🌢 ", rtc_time.hour, rtc_time.minute, rtc_time.second, moisture_pt);
@ -48,17 +45,11 @@ void screen_home(GuiEvent event)
LcdBuffer_Write(&lcd, 1, 0, "Plán. závlaha 7:15");
LcdBuffer_Write(&lcd, 2, 0, "❶Spustit ❷Přeskočit");
LcdBuffer_Write(&lcd, 3, 0, "🅰Nastavení");
// LcdBuffer_Write(&lcd, 1, 0, "❶ Spustit cyklus");
// LcdBuffer_Write(&lcd, 2, 0, "❷ Ruční řízení");
// LcdBuffer_Write(&lcd, 3, 0, "🅰 Nastavení");
// LcdBuffer_Write(&lcd, 1, 0, "🅰Program 🅱Poměry");
// LcdBuffer_Write(&lcd, 2, 0, "🅲Vlhkoměr 🅳Čas");
break;
case GUI_EVENT_KEY_1:
switch_screen(screen_cyklus, true);
// TODO
switch_screen(screen_cyklus, true); // fake cycle
break;
case GUI_EVENT_KEY_2:
@ -66,16 +57,7 @@ void screen_home(GuiEvent event)
break;
case GUI_EVENT_KEY_A:
// TODO
switch_screen(screen_settings, true);
break;
default:
if (event >= 32) {
showbuf[showbuf_wp++] = event;
if (showbuf_wp == 20) {
showbuf_wp = 0;
}
request_paint();
}
}
}

@ -0,0 +1,144 @@
/**
* TODO file description
*/
//
// Created by MightyPork on 2023/04/09.
//
#include <stdio.h>
#include <string.h>
#include "app_gui.h"
#include "gui_event.h"
#include "ds_rtc.h"
#include "app_io.h"
#include "app_config.h"
static int page = 1;
#define PAGECOUNT 3
static struct AppConfig scratch;
/** Clear the top 3 lines in the LCD - this fixes some problems with utf8 allocations
* (char still held by a line later overwritten) */
static void clear_menu_lines();
void screen_settings(GuiEvent event)
{
char buf[100];
switch (event) {
case GUI_EVENT_SCREEN_INIT:
page = 1;
memcpy(&scratch, &app_config, APPCONFIG_SIZE);
break;
case GUI_EVENT_PAINT:
switch (page) {
case 1:
snprintf(buf, 100, "1. Program=%s", scratch.scheduler_enable ? "ZAP" : "VYP");
LcdBuffer_Write(&lcd, 0, 0, buf);
LcdBuffer_Write(&lcd, 1, 0, "2. Upravit program");
LcdBuffer_Write(&lcd, 2, 0, "3. Nastavit čas");
break;
case 2:
LcdBuffer_Write(&lcd, 0, 0, "1. Délka zálivky");
LcdBuffer_Write(&lcd, 1, 0, "2. Kompenzace tlaku");
break;
case 3:
snprintf(buf, 100, "1. Blok.vlhkostí=%s", scratch.moisture_enable ? "ZAP" : "VYP");
LcdBuffer_Write(&lcd, 0, 0, buf);
LcdBuffer_Write(&lcd, 1, 0, "2. Kalibrace vlhkom.");
LcdBuffer_Write(&lcd, 2, 0, "3. Nastavit práh");
break;
}
snprintf(buf, 100, "⊛←%d/%d→¤ 🅰Ulož 🅳Zruš", page, PAGECOUNT);
LcdBuffer_Write(&lcd, 3, 0, buf);
break;
case GUI_EVENT_KEY_B:
case GUI_EVENT_KEY_STAR:
if (page > 1) {
page--;
clear_menu_lines();
request_paint();
}
break;
case GUI_EVENT_KEY_C:
case GUI_EVENT_KEY_HASH:
if (page < PAGECOUNT) {
page++;
clear_menu_lines();
request_paint();
}
break;
case GUI_EVENT_KEY_A: // SAVE
memcpy(&app_config, &scratch, APPCONFIG_SIZE);
appconfig_save();
switch_screen(screen_home, true);
break;
case GUI_EVENT_KEY_D: // CANCEL
switch_screen(screen_home, true);
break;
default:
switch (page) {
case 1:
switch (event) {
case GUI_EVENT_KEY_1: // Program Zap/VYP
scratch.scheduler_enable ^= 1;
request_paint();
break;
case GUI_EVENT_KEY_2: // Upravit program
// TODO
break;
case GUI_EVENT_KEY_3: // Nastavit cas
// TODO
break;
}
break;
case 2:
switch (event) {
case GUI_EVENT_KEY_1: // Délka zálivky
break;
case GUI_EVENT_KEY_2: // Kompenzace tlaku
// TODO
break;
}
break;
case 3:
switch (event) {
case GUI_EVENT_KEY_1: // Blokace vlhkosti Zap/VYP
scratch.moisture_enable ^= 1;
request_paint();
break;
case GUI_EVENT_KEY_2: // Kalibrace vlhkomeru
// TODO
break;
case GUI_EVENT_KEY_3: // Nastavit prah
// TODO
break;
}
break;
}
}
}
static void clear_menu_lines()
{
LcdBuffer_Write(&lcd, 0, 0, " ");
LcdBuffer_Write(&lcd, 1, 0, " ");
LcdBuffer_Write(&lcd, 2, 0, " ");
}
Loading…
Cancel
Save