From 90b992858acff53e0f6761eb063cf68824483c28 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 9 May 2025 22:57:53 +0200 Subject: [PATCH] Setting dates works modulo some y2k34 bug --- platformio.ini | 2 +- src/main.cpp | 224 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 211 insertions(+), 15 deletions(-) diff --git a/platformio.ini b/platformio.ini index 0d07b08..3352f74 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,7 +28,7 @@ build_flags = lib_deps = TFT_eSPI=https://github.com/quadule/TFT_eSPI.git#066c4adcd95679da94e87221c30ab973048d71e4 ricmoo/QRCode@^0.0.1 - dlloydev/Toggle@^3.1.8 + mathertel/OneButton@^2.6.1 [env:knobby] build_flags = diff --git a/src/main.cpp b/src/main.cpp index 4928222..9226491 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,15 +1,17 @@ #include #include #include +#include #include +#include #include -#include #include #include #include #include #include #include +#include #include "main.h" @@ -18,10 +20,22 @@ uint16_t qr_img[128*128]; int qr_version = 4; int qr_scale = 3; -Toggle tog_a, tog_b; + +OneButton bt_a, bt_b; + +void long_press_a(void); +void click_a(void); +void click_b(void); +void update_display(void); void setup() { Serial.begin(115200); + /* the thing just kept spuriously triggering. */ + esp_task_wdt_deinit(); + rtc_wdt_protect_off(); + rtc_wdt_disable(); + disableCore0WDT(); + disableCore1WDT(); ledcSetup(backlightChannel, 12000, 8); ledcAttachPin(TFT_BL, backlightChannel); @@ -29,8 +43,11 @@ void setup() { tft.init(); tft.fillScreen(TFT_BLACK); - tog_a(0); - tog_b(35); + bt_a.setup(0); + bt_b.setup(35); + + struct timeval now = {1746823581}; + settimeofday(&now, nullptr); SPIFFS.begin(true); @@ -53,21 +70,200 @@ void setup() { delete qr_buf; - tft.fillScreen(TFT_BLACK); + tft.fillScreen(TFT_WHITE); tft.startWrite(); tft.pushImage((TFT_WIDTH - qr_w)/2, (TFT_HEIGHT - qr_w)/2, qr_w, qr_w, (uint16_t*)qr_img); tft.endWrite(); + + bt_a.attachClick(click_a); + bt_a.attachLongPressStart(long_press_a); + bt_b.attachClick(click_b); + + Serial.println("Boot"); } -int flag = 0; +enum { + ST_INIT = 0, + ST_STANDBY, + ST_SET_TIME, +} ui_state = ST_INIT; +int cursor_pos = 0; +bool display_valid = true; + +uint64_t last_refresh = 0; void loop() { - flag = !flag; - /* - tft.fillScreen(flag ? TFT_RED : TFT_BLUE); - tft.startWrite(); - tft.pushImage(0, 0, qr_w, qr_w, (uint16_t*)qr_img); - tft.endWrite(); - */ - delay(1000); + bt_a.tick(); + bt_b.tick(); + + uint64_t now = millis(); + if (now - last_refresh > 500) { + display_valid = false; + last_refresh = now; + } + + if (!display_valid) { + update_display(); + } +} + +void update_display() { + if (ui_state == ST_INIT) { + Serial.println("ST_INIT"); + + } else if (ui_state == ST_STANDBY) { + Serial.println("ST_STANDBY"); + tft.fillScreen(TFT_BLACK); + + } else if (ui_state == ST_SET_TIME) { + Serial.println("ST_SET_TIME"); + tft.fillScreen(TFT_BLACK); + tft.setCursor(10, 10); + + time_t tt = time(nullptr); + struct tm *t = localtime(&tt); + + char buf[128]; + snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d", + t->tm_year + 1900, + t->tm_mon + 1, + t->tm_mday, + t->tm_hour, + t->tm_min, + t->tm_sec); + String msg(buf); + + int adjusted_cursor = cursor_pos + 2; + adjusted_cursor += cursor_pos / 2; + + if (cursor_pos < 10) { + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.print(msg.substring(0, adjusted_cursor)); + + tft.setTextColor(TFT_BLACK, TFT_WHITE); + tft.print(msg[adjusted_cursor]); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.print(msg.substring(adjusted_cursor+1, msg.length())); + + } else { + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.print(msg.substring(0, adjusted_cursor)); + + tft.setTextColor(TFT_BLACK, TFT_WHITE); + tft.print(msg.substring(adjusted_cursor, msg.length())); + } + + } else { + tft.fillScreen(TFT_RED); + } + display_valid = true; +} + +void long_press_a() { + Serial.println("Long A"); + if (ui_state == ST_SET_TIME) { + ui_state = ST_STANDBY; + display_valid = false; + + } else if (ui_state == ST_STANDBY) { + ui_state = ST_SET_TIME; + display_valid = false; + } +} + +void click_a() { + Serial.println("Click A"); + if (ui_state == ST_INIT) { + ui_state = ST_SET_TIME; + display_valid = false; + + } else if (ui_state == ST_SET_TIME) { + cursor_pos ++; + if (cursor_pos == 11) { + ui_state = ST_STANDBY; + cursor_pos = 0; + } + display_valid = false; + } +} + +bool is_leap_year(int year) { + if (year % 4 == 0) { + if (year % 100 == 0) { + if (year % 400 == 0) { + return true; + } + return false; + } + return true; + } + return false; +} + +int month_length(int year, int month) { + switch (month) { /* note: month is 0-indexed */ + case 1: return is_leap_year(year) ? 29 : 28; + case 3: return 30; + case 5: return 30; + case 8: return 30; + case 10: return 30; + default: return 31; + } +} + +void click_b() { + Serial.println("Click B"); + if (ui_state == ST_SET_TIME) { + + time_t tt = time(nullptr); + struct tm *t = localtime(&tt); + struct tm mod = *t; + + int adj = (cursor_pos%2 == 0) ? 10 : 1; + switch (cursor_pos/2) { + case 0: + mod.tm_year += adj; + if (mod.tm_year >= 2100 - 1900) + mod.tm_year = 2000 - 1900; + break; + case 1: + mod.tm_mon += adj; + if (mod.tm_mon >= 12) + mod.tm_mon = 0; + break; + case 2: + mod.tm_mday += adj; + if (mod.tm_mday > month_length(mod.tm_year, mod.tm_mon)) + mod.tm_mday = 1; + break; + case 3: + mod.tm_hour += adj; + if (mod.tm_hour >= 24) + mod.tm_hour = 0; + break; + case 4: + mod.tm_min += adj; + if (mod.tm_min >= 60) + mod.tm_min = 0; + break; + case 5: + mod.tm_sec = 0; + break; + } + + struct timeval new_tv = { + .tv_sec = mktime(&mod), + }; + Serial.print("Old time "); + Serial.print(tt); + Serial.print(" new time "); + Serial.print(new_tv.tv_sec); + Serial.print(" cursor "); + Serial.print(cursor_pos); + Serial.print(" adj "); + Serial.println(adj); + settimeofday(&new_tv, nullptr); + display_valid = false; + } }