Suche dny, rucni rezim. Netestovano

v2
Ondřej Hruška 5 months ago
parent 88c215393b
commit b128efecd3
  1. 2
      CMakeLists.txt
  2. 15
      src/app_config.c
  3. 29
      src/app_config.h
  4. 20
      src/app_io.c
  5. 2
      src/app_io.h
  6. 9
      src/ds_rtc.c
  7. 1
      src/ds_rtc.h
  8. 78
      src/screens/app_gui.c
  9. 11
      src/screens/app_gui.h
  10. 2
      src/screens/gui_event.h
  11. 6
      src/screens/screen_cyklus.c
  12. 4
      src/screens/screen_delka_zalivky.c
  13. 21
      src/screens/screen_home.c
  14. 4
      src/screens/screen_kompenzace_tlaku.c
  15. 68
      src/screens/screen_manual_control.c
  16. 4
      src/screens/screen_moisture_calib.c
  17. 4
      src/screens/screen_program_edit.c
  18. 4
      src/screens/screen_program_prehled.c
  19. 4
      src/screens/screen_set_moisture_threshold.c
  20. 4
      src/screens/screen_set_time.c
  21. 18
      src/screens/screen_settings.c
  22. 44
      src/screens/screen_suche_dny.c

@ -31,6 +31,8 @@ add_executable(zavlaha
src/screens/screen_kompenzace_tlaku.c src/screens/screen_kompenzace_tlaku.c
src/screens/screen_program_prehled.c src/screens/screen_program_prehled.c
src/screens/screen_program_edit.c src/screens/screen_program_edit.c
src/screens/screen_suche_dny.c
src/screens/screen_manual_control.c
src/app_io.c src/app_io.c
src/app_config.c) src/app_config.c)

@ -9,10 +9,10 @@
#define APPCONFIG_EE_BASE_ADDR 0 #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 = { static const struct AppConfig DEFAULTS = {
.magic_version = APPCONFIG_MAGIC1,
.circuit_base_time_s = 300, // for a test .circuit_base_time_s = 300, // for a test
.circuit_time_percent = {100, 100, 100, 100}, // for a test .circuit_time_percent = {100, 100, 100, 100}, // for a test
.scheduler_enable = true, .scheduler_enable = true,
@ -26,6 +26,8 @@ static const struct AppConfig DEFAULTS = {
.moisture_dry = 2800, .moisture_dry = 2800,
.moisture_wet = 1600, .moisture_wet = 1600,
.moisture_threshold_percent = 70, .moisture_threshold_percent = 70,
.magic2 = APPCONFIG_MAGIC2,
.scheduler_dry_days = 0,
}; };
static void load_fallback_config() { static void load_fallback_config() {
@ -36,7 +38,7 @@ static void load_fallback_config() {
void appconfig_load() void appconfig_load()
{ {
uint8_t magic = 0; uint8_t magic = 0;
if (0 > ee_read(APPCONFIG_EE_BASE_ADDR, &magic, 1) || magic != APPCONFIG_VERSION) { if (0 > ee_read(APPCONFIG_EE_BASE_ADDR, &magic, 1) || magic != APPCONFIG_MAGIC1) {
printf("Couldn't read EE to check magic!\r\n"); printf("Couldn't read EE to check magic!\r\n");
load_fallback_config(); load_fallback_config();
return; return;
@ -45,6 +47,12 @@ void appconfig_load()
if (0 > ee_read(APPCONFIG_EE_BASE_ADDR, (uint8_t *) &app_config, APPCONFIG_SIZE)) { if (0 > ee_read(APPCONFIG_EE_BASE_ADDR, (uint8_t *) &app_config, APPCONFIG_SIZE)) {
printf("Couldn't read EE to load config!\r\n"); printf("Couldn't read EE to load config!\r\n");
load_fallback_config(); load_fallback_config();
return;
}
if (app_config.magic2 != APPCONFIG_MAGIC2) {
app_config.magic2 = APPCONFIG_MAGIC2;
app_config.scheduler_dry_days = 0;
} }
} }
@ -53,7 +61,8 @@ void appconfig_save()
// printf("PERSISTENCE DISABLED - NOT SAVING\r\n"); // printf("PERSISTENCE DISABLED - NOT SAVING\r\n");
// return; // FIXME - when all GUIs are finished, add persistence // return; // FIXME - when all GUIs are finished, add persistence
// whatever, just write everything // whatever, just write everything
app_config.magic_version = APPCONFIG_VERSION; app_config.magic_version = APPCONFIG_MAGIC1;
app_config.magic2 = APPCONFIG_MAGIC2;
if (0 > ee_write(APPCONFIG_EE_BASE_ADDR, (const uint8_t *) &app_config, APPCONFIG_SIZE)) { if (0 > ee_write(APPCONFIG_EE_BASE_ADDR, (const uint8_t *) &app_config, APPCONFIG_SIZE)) {
printf("Couldn't write EE!"); printf("Couldn't write EE!");
} }

@ -13,26 +13,29 @@
#define MENU_AUTOEXIT_TIME_S 120 #define MENU_AUTOEXIT_TIME_S 120
struct __attribute__((packed)) ScheduleTime { struct __attribute__((packed)) ScheduleTime {
bool enable; bool enable; /// True if the schedule time is enabled
uint8_t h; uint8_t h; /// Hour
uint8_t m; uint8_t m; /// Minute
}; };
struct __attribute__((packed)) AppConfig { struct __attribute__((packed)) AppConfig {
uint8_t magic_version; uint8_t magic_version; /// Magic (byte reserved)
uint16_t circuit_base_time_s; uint16_t circuit_base_time_s; /// Base time for each branch (scaled by percent)
uint16_t circuit_time_percent[CIRCUIT_COUNT]; // 0% can be used to disable a branch uint16_t circuit_time_percent[CIRCUIT_COUNT]; /// Relative time of each branch 0% can be used to disable a branch
bool scheduler_enable; bool scheduler_enable; /// Enable automatic watering
struct ScheduleTime schedules[SCHEDULE_COUNT]; struct ScheduleTime schedules[SCHEDULE_COUNT]; /// Scheduled times in a day
bool moisture_enable; bool moisture_enable; /// Enable blocking watering by high soil humidity
uint16_t moisture_dry; uint16_t moisture_dry; /// Saved humidity value as 0%
uint16_t moisture_wet; uint16_t moisture_wet; /// Saved humidity value as 100%
uint8_t moisture_threshold_percent; uint8_t moisture_threshold_percent; /// % of soil humidity that deactivates watering
uint8_t magic2;
uint8_t scheduler_dry_days; /// Days to skip between watering
}; };
#define APPCONFIG_SIZE sizeof(struct AppConfig) #define APPCONFIG_SIZE sizeof(struct AppConfig)
#define APPCONFIG_VERSION 0b11100001 #define APPCONFIG_MAGIC1 0b11100001
#define APPCONFIG_MAGIC2 0b00111001
extern struct AppConfig app_config; extern struct AppConfig app_config;

@ -9,21 +9,29 @@
#include "pinout.h" #include "pinout.h"
#include "app_config.h" #include "app_config.h"
void set_relays(bool one, bool two, bool three, bool four) void set_relays(bool one, bool two, bool three, bool four)
{ {
gpio_put(PIN_RE1, one); gpio_put(PIN_RE1, one);
gpio_put(PIN_RE2, two); gpio_put(PIN_RE2, two);
gpio_put(PIN_RE3, three); gpio_put(PIN_RE3, three);
gpio_put(PIN_RE1, four); gpio_put(PIN_RE4, four);
} }
void open_valve(uint8_t num) void open_valve(uint8_t num)
{ {
gpio_put(PIN_RE1, num == 1); set_relays(num == 1, num == 2, num == 3, num == 4);
gpio_put(PIN_RE2, num == 2); }
gpio_put(PIN_RE3, num == 3);
gpio_put(PIN_RE4, num == 4); void set_one_relay(uint8_t num, bool on)
{
if (num < 1 || num > 4) {
return;
}
if (num == 1) { gpio_put(PIN_RE1, on); }
if (num == 2) { gpio_put(PIN_RE2, on); }
if (num == 3) { gpio_put(PIN_RE3, on); }
if (num == 4) { gpio_put(PIN_RE4, on); }
} }
uint16_t moisture_read() uint16_t moisture_read()

@ -13,6 +13,8 @@ void set_relays(bool one, bool two, bool three, bool four);
/** Open valve, 1,2,3,4; 0=close all */ /** Open valve, 1,2,3,4; 0=close all */
void open_valve(uint8_t num); void open_valve(uint8_t num);
void set_one_relay(uint8_t num, bool on);
uint16_t moisture_read(); uint16_t moisture_read();
uint16_t moisture_convert(uint16_t moisture); uint16_t moisture_convert(uint16_t moisture);

@ -1,5 +1,5 @@
/** /**
* TODO file description * Functions to access the RTC (DS3231)
*/ */
#include <pico/stdlib.h> #include <pico/stdlib.h>
@ -35,11 +35,13 @@ static int rtc_write(uint8_t start, const uint8_t *data, size_t len) {
int rtc_get_time(struct rtc_time *dest) { int rtc_get_time(struct rtc_time *dest) {
int rv; int rv;
uint8_t buf[3]; uint8_t buf[4];
TRY(rtc_read(0x00, buf, 3)); TRY(rtc_read(0x00, buf, 4));
dest->second = (buf[0] & 15) + (buf[0] >> 4) * 10; dest->second = (buf[0] & 15) + (buf[0] >> 4) * 10;
dest->minute = (buf[1] & 15) + (buf[1] >> 4) * 10; dest->minute = (buf[1] & 15) + (buf[1] >> 4) * 10;
dest->weekday = buf[3] & 7;
if (dest->weekday > 0) dest->weekday -= 1; // Normalize to 0-6, with failsafe in case we got zero, should not happen.
if (buf[2] & 0x40) { if (buf[2] & 0x40) {
// 12h time? // 12h time?
@ -60,5 +62,6 @@ int rtc_set_time(const struct rtc_time *time) {
buf[2] = (time->hour % 10) + ((time->hour / 10) << 4); buf[2] = (time->hour % 10) + ((time->hour / 10) << 4);
TRY(rtc_write(0x00, buf, 3)); TRY(rtc_write(0x00, buf, 3));
// just let the week counter go on its own - we only care about it incrementing
return 0; return 0;
} }

@ -10,6 +10,7 @@ struct rtc_time {
uint8_t hour; uint8_t hour;
uint8_t minute; uint8_t minute;
uint8_t second; uint8_t second;
uint8_t weekday; // 0-6, We use this as a counter for dry days
}; };
int rtc_get_time(struct rtc_time *dest); int rtc_get_time(struct rtc_time *dest);

@ -28,12 +28,53 @@ static void draw_common_overlay();
//stratch string buffer //stratch string buffer
char sbuf[100]; char sbuf[100];
void gui_read_moisture() { void gui_read_moisture()
{
s_app.moisture_pt = moisture_convert(s_app.moisture_raw = moisture_read()); s_app.moisture_pt = moisture_convert(s_app.moisture_raw = moisture_read());
} }
static void read_time_and_moisture() { /**
* Get days remaining to next watering day
*
* @return
*/
uint8_t days_to_next_watering()
{
if (app_config.scheduler_dry_days == 0) {
return 0;
}
uint8_t wd = s_app.rtc_time.weekday;
uint8_t last_wd = s_app.last_watering_day_wd;
uint8_t normalized_next = (last_wd + 1 + app_config.scheduler_dry_days) % 7;
if (wd > normalized_next) {
normalized_next += 7;
}
return normalized_next - wd;
}
static void read_time_and_moisture()
{
uint8_t prev_wd = s_app.rtc_time.weekday;
rtc_get_time(&s_app.rtc_time); // now is a good time to update timestamp - we could just increment it though rtc_get_time(&s_app.rtc_time); // now is a good time to update timestamp - we could just increment it though
// decide if today is a watering day
if (app_config.scheduler_dry_days == 0) {
s_app.today_is_watering_day = true;
s_app.last_watering_day_wd = s_app.rtc_time.weekday;
} else {
uint8_t cur_wd = s_app.rtc_time.weekday;
if (cur_wd != prev_wd) {
s_app.today_is_watering_day = false;
uint8_t now_normalized = cur_wd + (cur_wd < s_app.last_watering_day_wd ? 7 : 0);
uint8_t elapsed_days = now_normalized - s_app.last_watering_day_wd;
if (elapsed_days >= app_config.scheduler_dry_days) {
s_app.today_is_watering_day = true;
s_app.last_watering_day_wd = cur_wd;
}
}
}
gui_read_moisture(); gui_read_moisture();
} }
@ -44,11 +85,19 @@ void gui_init()
read_time_and_moisture(); read_time_and_moisture();
s_app.today_is_watering_day = true;
s_app.last_watering_day_wd = s_app.rtc_time.weekday;
LcdBuffer_Init(&lcd, CGROM_A00, CGRAM_CZ); LcdBuffer_Init(&lcd, CGROM_A00, CGRAM_CZ);
} }
static bool blink_state = 0; static bool blink_state = 0;
bool is_valve_control_screen()
{
return s_app.screen == screen_cyklus || s_app.screen == screen_manual_control;
}
void gui_loop_iter(GuiEvent message) void gui_loop_iter(GuiEvent message)
{ {
uint32_t tickNow = timestamp_ms(); uint32_t tickNow = timestamp_ms();
@ -56,7 +105,7 @@ void gui_loop_iter(GuiEvent message)
// Time program logic - since this runs very often, we are guaranteed not to miss a cycle - unless there is a power outage // Time program logic - since this runs very often, we are guaranteed not to miss a cycle - unless there is a power outage
// exactly in the scheduled watering time // exactly in the scheduled watering time
if (s_app.screen != screen_cyklus && app_config.scheduler_enable) { if (!is_valve_control_screen() && app_config.scheduler_enable && (s_app.today_is_watering_day || app_config.scheduler_dry_days == 0)) { // if dry days=0, is_wd should always be true, but making sure here
if (s_app.cycle_time_checking) { if (s_app.cycle_time_checking) {
if (s_app.rtc_time.hour != s_app.last_cycle_time.hour if (s_app.rtc_time.hour != s_app.last_cycle_time.hour
|| s_app.rtc_time.minute != s_app.last_cycle_time.minute) { || s_app.rtc_time.minute != s_app.last_cycle_time.minute) {
@ -88,7 +137,7 @@ void gui_loop_iter(GuiEvent message)
} }
// screen auto-close // screen auto-close
if (s_app.screen != screen_home && s_app.screen != screen_cyklus) { if (s_app.screen != screen_home && !is_valve_control_screen()) {
if ((tickNow - s_app.screen_open_time) >= (MENU_AUTOEXIT_TIME_S * 1000)) { if ((tickNow - s_app.screen_open_time) >= (MENU_AUTOEXIT_TIME_S * 1000)) {
switch_screen(screen_home, true); switch_screen(screen_home, true);
} }
@ -154,13 +203,17 @@ void gui_loop_iter(GuiEvent message)
/** Switch to a different screen handler. /** Switch to a different screen handler.
* If "init" is true, immediately call it with the init event. */ * If "init" is true, immediately call it with the init event. */
void switch_screen(screen_t pScreen, bool init) static void switch_screen_ex(screen_t pScreen, bool init, bool deinit_current)
{ {
if (s_app.screen == pScreen) { if (s_app.screen == pScreen) {
// already, no op // already, no op
return; return;
} }
if (s_app.screen && deinit_current) {
s_app.screen(GUI_EVENT_SCREEN_DEINIT);
}
s_app.screen_open_time = timestamp_ms(); s_app.screen_open_time = timestamp_ms();
s_app.screen = pScreen; s_app.screen = pScreen;
@ -178,6 +231,21 @@ void switch_screen(screen_t pScreen, bool init)
} }
} }
void switch_screen(screen_t pScreen, bool init)
{
switch_screen_ex(pScreen, init, true);
}
void switch_to_subscreen(screen_t pScreen)
{
switch_screen_ex(pScreen, true, false);
}
void switch_to_parent_screen(screen_t pScreen)
{
switch_screen_ex(pScreen, false, true);
}
/** Draw GUI common to all screens */ /** Draw GUI common to all screens */
static void draw_common_overlay() static void draw_common_overlay()
{ {

@ -45,6 +45,9 @@ void gui_init();
*/ */
void switch_screen(screen_t pScreen, bool init); void switch_screen(screen_t pScreen, bool init);
void switch_to_subscreen(screen_t pScreen);
void switch_to_parent_screen(screen_t pScreen);
void request_paint(); void request_paint();
// prototypes for screen handlers // prototypes for screen handlers
@ -59,6 +62,10 @@ void screen_moisture_calib(GuiEvent event);
void screen_delka_zalivky(GuiEvent event); void screen_delka_zalivky(GuiEvent event);
void screen_kompenzace_tlaku(GuiEvent event); void screen_kompenzace_tlaku(GuiEvent event);
void screen_program_prehled(GuiEvent event); void screen_program_prehled(GuiEvent event);
void screen_suche_dny(GuiEvent event);
void screen_manual_control(GuiEvent event);
uint8_t days_to_next_watering();
extern int pgm_edit_slot; extern int pgm_edit_slot;
void screen_program_edit(GuiEvent event); void screen_program_edit(GuiEvent event);
@ -66,6 +73,7 @@ void screen_program_edit(GuiEvent event);
void gui_read_moisture(); void gui_read_moisture();
// This is actually the global app state!
struct State { struct State {
struct rtc_time rtc_time; struct rtc_time rtc_time;
uint16_t moisture_raw; uint16_t moisture_raw;
@ -85,6 +93,9 @@ struct State {
uint32_t screen_open_time; uint32_t screen_open_time;
bool today_is_watering_day;
uint8_t last_watering_day_wd;
}; };
extern struct State s_app; extern struct State s_app;

@ -13,6 +13,8 @@ typedef enum GuiEvent {
GUI_EVENT_PAINT, GUI_EVENT_PAINT,
/// Used as the argument when initing a screen /// Used as the argument when initing a screen
GUI_EVENT_SCREEN_INIT, GUI_EVENT_SCREEN_INIT,
/// Screen is about to close (this will NOT be called for middle pages when auto-closing a multi-level hierarchy!)
GUI_EVENT_SCREEN_DEINIT,
/// Time tick, used to carry timing to the screen functions. /// Time tick, used to carry timing to the screen functions.
/// This tick has 10ms interval /// This tick has 10ms interval
GUI_EVENT_SCREEN_TICK_10MS, GUI_EVENT_SCREEN_TICK_10MS,

@ -82,6 +82,10 @@ void screen_cyklus(GuiEvent event)
case GUI_EVENT_KEY_D: case GUI_EVENT_KEY_D:
end_cycle(); end_cycle();
switch_screen(screen_home, true); switch_screen(screen_home, true);
return; break;
case GUI_EVENT_SCREEN_DEINIT:
open_valve(0); // close all - this should not be needed here, this screen does not autoclose.
break;
} }
} }

@ -38,12 +38,12 @@ void screen_delka_zalivky(GuiEvent event)
case GUI_EVENT_KEY_A: // Confirm case GUI_EVENT_KEY_A: // Confirm
if (cursor > 0) { if (cursor > 0) {
settings_scratch.circuit_base_time_s = value; settings_scratch.circuit_base_time_s = value;
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
} }
break; break;
case GUI_EVENT_KEY_D: // CANCEL case GUI_EVENT_KEY_D: // CANCEL
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
break; break;
default: default:

@ -49,6 +49,7 @@ void screen_home(GuiEvent event)
} else { } else {
int found = -1; int found = -1;
int first = -1; int first = -1;
bool wrapped_around = false;
uint16_t m_now = s_app.rtc_time.hour * 60 + s_app.rtc_time.minute; uint16_t m_now = s_app.rtc_time.hour * 60 + s_app.rtc_time.minute;
for (int i = 0; i < SCHEDULE_COUNT; i++) { for (int i = 0; i < SCHEDULE_COUNT; i++) {
if (!app_config.schedules[i].enable) { if (!app_config.schedules[i].enable) {
@ -68,27 +69,37 @@ void screen_home(GuiEvent event)
if (found == -1) { if (found == -1) {
found = first; found = first;
wrapped_around = true;
} }
if (found == -1) { if (found == -1) {
LcdBuffer_Write(&lcd, 1, 0, "Program nenastaven!"); LcdBuffer_Write(&lcd, 1, 0, "Program nenastaven! ");
} else { } else {
snprintf(sbuf, sbuf_len, "Další závlaha %d:%02d ", uint8_t days = days_to_next_watering();
app_config.schedules[found].h, app_config.schedules[found].m); if (days > 0 && (!s_app.today_is_watering_day || wrapped_around)) {
snprintf(sbuf, sbuf_len, "Další závlaha za %d d", days);
} else {
snprintf(sbuf, sbuf_len, "Další závlaha %d:%02d ",
app_config.schedules[found].h, app_config.schedules[found].m);
}
LcdBuffer_Write(&lcd, 1, 0, sbuf); LcdBuffer_Write(&lcd, 1, 0, sbuf);
} }
} }
LcdBuffer_Write(&lcd, 2, 0, "🅰Spustit cyklus"); LcdBuffer_Write(&lcd, 2, 0, "🅰Spustit cyklus");
LcdBuffer_Write(&lcd, 3, 0, "🅱Nastavení"); LcdBuffer_Write(&lcd, 3, 0, "🅱Nastavení 🅳Test");
break; break;
case GUI_EVENT_KEY_A: case GUI_EVENT_KEY_A:
switch_screen(screen_cyklus, true); // fake cycle switch_screen(screen_cyklus, true); // manually started cycle
break; break;
case GUI_EVENT_KEY_B: case GUI_EVENT_KEY_B:
switch_screen(screen_settings, true); switch_screen(screen_settings, true);
break; break;
case GUI_EVENT_KEY_D:
switch_screen(screen_manual_control, true);
break;
} }
} }

@ -46,11 +46,11 @@ void screen_kompenzace_tlaku(GuiEvent event)
case GUI_EVENT_KEY_A: // Confirm case GUI_EVENT_KEY_A: // Confirm
memcpy(settings_scratch.circuit_time_percent, ratios, sizeof(settings_scratch.circuit_time_percent)); memcpy(settings_scratch.circuit_time_percent, ratios, sizeof(settings_scratch.circuit_time_percent));
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
break; break;
case GUI_EVENT_KEY_D: // CANCEL case GUI_EVENT_KEY_D: // CANCEL
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
break; break;
case GUI_EVENT_KEY_1: case GUI_EVENT_KEY_1:

@ -0,0 +1,68 @@
#include <stdio.h>
#include "app_gui.h"
#include "gui_event.h"
#include "app_io.h"
#include "lcd.h"
static bool valve1, valve2, valve3, valve4;
void screen_manual_control(GuiEvent event)
{
switch (event) {
case GUI_EVENT_SCREEN_INIT:
open_valve(0); // make sure all are closed
valve1 = valve2 = valve3 = valve4 = false;
break;
case GUI_EVENT_PAINT:
LcdBuffer_Write(&lcd, 0, 0, "== MANUÁLNÍ REŽIM ==");
LcdBuffer_Write(&lcd, 1, 0, "1-4 ventil,0 vyp.vše");
LcdBuffer_SetCursor(&lcd, 2, 0, CURSOR_BOTH);
snprintf(sbuf, sbuf_len, " %s %s %s %s ",
valve1 ? "█1█" : " 1 ",
valve2 ? "█2█" : " 2 ",
valve3 ? "█3█" : " 3 ",
valve4 ? "█4█" : " 4 ");
LcdBuffer_Write(&lcd, 2, 0, sbuf);
LcdBuffer_Write(&lcd, 3, 0, "🅳Konec");
break;
case GUI_EVENT_KEY_D: // CANCEL
open_valve(0);
switch_screen(screen_home, true);
break;
case GUI_EVENT_KEY_0:
valve1 = valve2 = valve3 = valve4 = false;
open_valve(0);
request_paint();
break;
case GUI_EVENT_KEY_1:
valve1 = !valve1;
set_one_relay(1, valve1);
break;
case GUI_EVENT_KEY_2:
valve2 = !valve2;
set_one_relay(2, valve2);
break;
case GUI_EVENT_KEY_3:
valve3 = !valve3;
set_one_relay(3, valve3);
break;
case GUI_EVENT_KEY_4:
valve4 = !valve4;
set_one_relay(4, valve4);
break;
case GUI_EVENT_SCREEN_DEINIT:
open_valve(0); // close all
break;
}
}

@ -42,12 +42,12 @@ void screen_moisture_calib(GuiEvent event)
} else { } else {
settings_scratch.moisture_dry = sample_dry; settings_scratch.moisture_dry = sample_dry;
settings_scratch.moisture_wet = s_app.moisture_raw; settings_scratch.moisture_wet = s_app.moisture_raw;
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
} }
break; break;
case GUI_EVENT_KEY_D: // CANCEL case GUI_EVENT_KEY_D: // CANCEL
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
break; break;
} }
} }

@ -42,7 +42,7 @@ void screen_program_edit(GuiEvent event)
case GUI_EVENT_KEY_A: // Confirm case GUI_EVENT_KEY_A: // Confirm
if (!time.enable || cursor == 4) { if (!time.enable || cursor == 4) {
memcpy(&settings_scratch.schedules[pgm_edit_slot], &time, sizeof(time)); memcpy(&settings_scratch.schedules[pgm_edit_slot], &time, sizeof(time));
switch_screen(screen_program_prehled, false); switch_to_parent_screen(screen_program_prehled);
} }
break; break;
@ -54,7 +54,7 @@ void screen_program_edit(GuiEvent event)
break; break;
case GUI_EVENT_KEY_D: // CANCEL case GUI_EVENT_KEY_D: // CANCEL
switch_screen(screen_program_prehled, false); switch_to_parent_screen(screen_program_prehled);
break; break;
default: default:

@ -44,7 +44,7 @@ void screen_program_prehled(GuiEvent event)
break; break;
case GUI_EVENT_KEY_D: // CANCEL case GUI_EVENT_KEY_D: // CANCEL
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
break; break;
case GUI_EVENT_KEY_1: case GUI_EVENT_KEY_1:
@ -52,7 +52,7 @@ void screen_program_prehled(GuiEvent event)
case GUI_EVENT_KEY_3: case GUI_EVENT_KEY_3:
case GUI_EVENT_KEY_4: case GUI_EVENT_KEY_4:
pgm_edit_slot = event - '1'; // 0-3 pgm_edit_slot = event - '1'; // 0-3
switch_screen(screen_program_edit, true); switch_to_subscreen(screen_program_edit);
break; break;
} }
} }

@ -37,12 +37,12 @@ void screen_set_moisture_threshold(GuiEvent event)
case GUI_EVENT_KEY_A: // Confirm case GUI_EVENT_KEY_A: // Confirm
if (cursor > 0) { if (cursor > 0) {
settings_scratch.moisture_threshold_percent = threshold; settings_scratch.moisture_threshold_percent = threshold;
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
} }
break; break;
case GUI_EVENT_KEY_D: // CANCEL case GUI_EVENT_KEY_D: // CANCEL
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
break; break;
default: default:

@ -32,12 +32,12 @@ void screen_set_time(GuiEvent event)
case GUI_EVENT_KEY_A: // Confirm case GUI_EVENT_KEY_A: // Confirm
if (cursor == 4) { if (cursor == 4) {
rtc_set_time(&time); rtc_set_time(&time);
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
} }
break; break;
case GUI_EVENT_KEY_D: // CANCEL case GUI_EVENT_KEY_D: // CANCEL
switch_screen(screen_settings, false); switch_to_parent_screen(screen_settings);
break; break;
default: default:

@ -43,6 +43,8 @@ void screen_settings(GuiEvent event)
case 2: case 2:
LcdBuffer_Write(&lcd, 0, 0, "1. Délka zálivky"); LcdBuffer_Write(&lcd, 0, 0, "1. Délka zálivky");
LcdBuffer_Write(&lcd, 1, 0, "2. Kompenzace tlaku"); LcdBuffer_Write(&lcd, 1, 0, "2. Kompenzace tlaku");
snprintf(sbuf, sbuf_len, "3. Suché dny (%d)", settings_scratch.scheduler_dry_days);
LcdBuffer_Write(&lcd, 2, 0, sbuf);
break; break;
case 3: case 3:
@ -96,11 +98,11 @@ void screen_settings(GuiEvent event)
break; break;
case GUI_EVENT_KEY_2: // Upravit program case GUI_EVENT_KEY_2: // Upravit program
switch_screen(screen_program_prehled, true); switch_to_subscreen(screen_program_prehled);
break; break;
case GUI_EVENT_KEY_3: // Nastavit cas case GUI_EVENT_KEY_3: // Nastavit cas
switch_screen(screen_set_time, true); switch_to_subscreen(screen_set_time);
break; break;
} }
break; break;
@ -108,11 +110,15 @@ void screen_settings(GuiEvent event)
case 2: case 2:
switch (event) { switch (event) {
case GUI_EVENT_KEY_1: // Délka zálivky case GUI_EVENT_KEY_1: // Délka zálivky
switch_screen(screen_delka_zalivky, true); switch_to_subscreen(screen_delka_zalivky);
break; break;
case GUI_EVENT_KEY_2: // Kompenzace tlaku case GUI_EVENT_KEY_2: // Kompenzace tlaku
switch_screen(screen_kompenzace_tlaku, true); switch_to_subscreen(screen_kompenzace_tlaku);
break;
case GUI_EVENT_KEY_3: // Nastavit suche dny
switch_to_subscreen(screen_suche_dny);
break; break;
} }
break; break;
@ -125,11 +131,11 @@ void screen_settings(GuiEvent event)
break; break;
case GUI_EVENT_KEY_2: // Kalibrace vlhkomeru case GUI_EVENT_KEY_2: // Kalibrace vlhkomeru
switch_screen(screen_moisture_calib, true); switch_to_subscreen(screen_moisture_calib);
break; break;
case GUI_EVENT_KEY_3: // Nastavit prah case GUI_EVENT_KEY_3: // Nastavit prah
switch_screen(screen_set_moisture_threshold, true); switch_to_subscreen(screen_set_moisture_threshold);
break; break;
} }
break; break;

@ -0,0 +1,44 @@
#include <stdio.h>
#include "app_gui.h"
#include "gui_event.h"
#include "app_io.h"
#include "lcd.h"
#include "app_config.h"
static int value;
void screen_suche_dny(GuiEvent event)
{
switch (event) {
case GUI_EVENT_SCREEN_INIT:
value = app_config.scheduler_dry_days;
break;
case GUI_EVENT_PAINT:
LcdBuffer_Write(&lcd, 0, 0, "Vynechat dny mezi");
LcdBuffer_Write(&lcd, 1, 0, "auto. zálivkou (0-5)");
LcdBuffer_SetCursor(&lcd, 2, 0, CURSOR_BOTH);
snprintf(sbuf, sbuf_len, "%d d", value);
LcdBuffer_Write(&lcd, 2, 0, sbuf);
LcdBuffer_Write(&lcd, 3, 0, "🅳Zrušit 🅰OK");
break;
case GUI_EVENT_KEY_A: // Confirm
settings_scratch.scheduler_dry_days = value;
switch_to_parent_screen(screen_settings);
break;
case GUI_EVENT_KEY_D: // CANCEL
switch_to_parent_screen(screen_settings);
break;
default:
if (event >= '0' && event <= '5') {
value = (uint8_t) (event - '0');
request_paint();
}
}
}
Loading…
Cancel
Save