Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d900083398 | |||
| e2c9d8f1e4 |
@@ -117,6 +117,13 @@
|
||||
// would silently keep displaying the prior owner's photos until the new
|
||||
// owner happens to navigate to /setup/{mac}.
|
||||
#define NVS_KEY_JUST_PROVISIONED "just_prov"
|
||||
// TEMP: power-monitor — stores previous cycle's awake duration and
|
||||
// epd_init() duration so the next boot can report them server-side as
|
||||
// X-Prev-Awake-Ms / X-Prev-Panel-Init-Ms. Lets us verify PIN_PWR rail
|
||||
// cut doesn't slow panel re-init or extend the awake window. Remove
|
||||
// these keys + their reads/writes once the change is validated.
|
||||
#define NVS_KEY_PREV_AWAKE_MS "tm_awk"
|
||||
#define NVS_KEY_PREV_PANEL_INIT_MS "tm_pin"
|
||||
|
||||
// Bump when introducing a schema migration. Each new value can force a one-shot
|
||||
// recovery action on first boot of the new firmware.
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
// The test build adds test/mocks to the include path via -iquote.
|
||||
#include "epd_mock.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/gpio.h"
|
||||
#else
|
||||
#include "epd.h"
|
||||
#include <esp_sleep.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
#endif
|
||||
|
||||
@@ -114,6 +116,12 @@ void normal_operation_impl(const String& mac, HTTP& http, const String& url, Pre
|
||||
bool errBorder = prefs.getInt(NVS_KEY_ERR_BORDER, 0) != 0;
|
||||
int schemaV = prefs.getInt(NVS_KEY_SCHEMA_V, 0);
|
||||
bool justProvisioned = prefs.getInt(NVS_KEY_JUST_PROVISIONED, 0) != 0;
|
||||
// TEMP: power-monitor — previous cycle's awake + panel-init durations.
|
||||
// Reported as X-Prev-Awake-Ms / X-Prev-Panel-Init-Ms below. Remove
|
||||
// along with the corresponding writes near deep_sleep_start + the
|
||||
// epd_init() timing block once the PIN_PWR cut is validated.
|
||||
uint32_t prevAwakeMs = prefs.getUInt(NVS_KEY_PREV_AWAKE_MS, 0);
|
||||
uint32_t prevPanelInitMs = prefs.getUInt(NVS_KEY_PREV_PANEL_INIT_MS, 0);
|
||||
prefs.end();
|
||||
|
||||
// Schema migration: on first boot under err-border-aware firmware, the
|
||||
@@ -160,6 +168,17 @@ void normal_operation_impl(const String& mac, HTTP& http, const String& url, Pre
|
||||
http.addHeader("X-Just-Provisioned", "1");
|
||||
}
|
||||
|
||||
// TEMP: power-monitor — last cycle's awake + panel-init times.
|
||||
// Lets us see, server-side, whether the PIN_PWR rail cut affects
|
||||
// either. Send only if non-zero (skips the first boot after a
|
||||
// firmware that didn't store them).
|
||||
if (prevAwakeMs > 0) {
|
||||
http.addHeader("X-Prev-Awake-Ms", String((unsigned long)prevAwakeMs));
|
||||
}
|
||||
if (prevPanelInitMs > 0) {
|
||||
http.addHeader("X-Prev-Panel-Init-Ms", String((unsigned long)prevPanelInitMs));
|
||||
}
|
||||
|
||||
const char* collectHeaders[] = { "X-Interval-Ms", "X-Image-Id", "X-Image-Sha256", "X-Claimed" };
|
||||
http.collectHeaders(collectHeaders, 4);
|
||||
int code = http.GET();
|
||||
@@ -242,7 +261,12 @@ void normal_operation_impl(const String& mac, HTTP& http, const String& url, Pre
|
||||
}
|
||||
|
||||
displayInitialized = true;
|
||||
// TEMP: power-monitor — time the panel init, stored in NVS at
|
||||
// end of cycle for next boot to report. Remove the timing
|
||||
// wrapper when the PIN_PWR cut is validated.
|
||||
uint32_t panelInitStart = millis();
|
||||
epd_init();
|
||||
uint32_t panelInitMs = millis() - panelInitStart;
|
||||
File r = LittleFS.open(IMAGE_PATH, "r");
|
||||
if (r) { epd_draw_image_from_file(r); r.close(); }
|
||||
|
||||
@@ -251,6 +275,7 @@ void normal_operation_impl(const String& mac, HTTP& http, const String& url, Pre
|
||||
prefs.begin(NVS_NAMESPACE, false);
|
||||
prefs.putInt(NVS_KEY_DRAW_NEEDED, 0);
|
||||
prefs.putInt(NVS_KEY_ERR_BORDER, 0);
|
||||
prefs.putUInt(NVS_KEY_PREV_PANEL_INIT_MS, panelInitMs); // TEMP
|
||||
prefs.end();
|
||||
}
|
||||
|
||||
@@ -354,6 +379,20 @@ void normal_operation_impl(const String& mac, HTTP& http, const String& url, Pre
|
||||
// false → normal_operation_impl runs → the next poll fetches a fresh
|
||||
// image, which doubles as a "force refresh" gesture.
|
||||
esp_sleep_enable_ext0_wakeup((gpio_num_t)PIN_BTN_RESET, 0);
|
||||
// Latch any gpio_hold_en pins through the deep sleep period.
|
||||
// epd_sleep() cuts PIN_PWR LOW + holds it; without this call the
|
||||
// hold releases on the RTC transition and the panel rail comes back
|
||||
// up, losing the saving. Released per-pin in epd_setup_pins() on
|
||||
// wake via gpio_hold_dis().
|
||||
gpio_deep_sleep_hold_en();
|
||||
|
||||
// TEMP: power-monitor — millis() at this point is the total awake
|
||||
// duration since boot. Next boot reads it back and reports as
|
||||
// X-Prev-Awake-Ms. Remove when PIN_PWR cut is validated.
|
||||
prefs.begin(NVS_NAMESPACE, false);
|
||||
prefs.putUInt(NVS_KEY_PREV_AWAKE_MS, millis());
|
||||
prefs.end();
|
||||
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <qrcode.h>
|
||||
#include <esp_task_wdt.h>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <driver/gpio.h>
|
||||
|
||||
static constexpr uint16_t W = 1200;
|
||||
static constexpr uint16_t H = 1600;
|
||||
@@ -103,6 +104,12 @@ static void panel_reset() {
|
||||
}
|
||||
|
||||
void epd_setup_pins() {
|
||||
// Release the PIN_PWR hold latched from the previous deep sleep so we
|
||||
// can drive it again. No-op on cold boot (nothing was held). Paired
|
||||
// with gpio_hold_en() in epd_sleep() and gpio_deep_sleep_hold_en() in
|
||||
// operation.h.
|
||||
gpio_hold_dis((gpio_num_t)PIN_PWR);
|
||||
|
||||
pinMode(PIN_PWR, OUTPUT);
|
||||
pinMode(PIN_RST, OUTPUT);
|
||||
pinMode(PIN_DC, OUTPUT);
|
||||
@@ -191,6 +198,16 @@ void epd_sleep() {
|
||||
SPI.transfer(0xA5); // sentinel
|
||||
cs_both(HIGH);
|
||||
s_initialized = false;
|
||||
|
||||
// Cut the panel power rail. The Waveshare board exposes PIN_PWR
|
||||
// specifically for battery operation — the e-ink image persists
|
||||
// without VDD (particles are bistable), and dropping the rail kills
|
||||
// the boost converter's quiescent draw (~50–500 µA depending on the
|
||||
// load on the rail). Latch LOW so it survives deep sleep; paired with
|
||||
// gpio_deep_sleep_hold_en() in operation.h just before the chip
|
||||
// enters sleep.
|
||||
digitalWrite(PIN_PWR, LOW);
|
||||
gpio_hold_en((gpio_num_t)PIN_PWR);
|
||||
}
|
||||
|
||||
// ── Draw helpers ───────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -8,6 +8,7 @@ extern int g_prefs_putint_seq; // sequence position of last putInt call
|
||||
|
||||
struct Preferences {
|
||||
std::map<std::string, int32_t> ints;
|
||||
std::map<std::string, uint32_t> uints;
|
||||
std::map<std::string, std::string> strings;
|
||||
bool _open = false;
|
||||
|
||||
@@ -26,10 +27,16 @@ struct Preferences {
|
||||
g_call_seq++;
|
||||
}
|
||||
|
||||
uint32_t getUInt(const char* key, uint32_t def = 0) {
|
||||
auto it = uints.find(key);
|
||||
return it != uints.end() ? it->second : def;
|
||||
}
|
||||
void putUInt(const char* key, uint32_t val) { uints[key] = val; }
|
||||
|
||||
String getString(const char* key, const char* def = "") {
|
||||
auto it = strings.find(key);
|
||||
return it != strings.end() ? String(it->second) : String(def);
|
||||
}
|
||||
void putString(const char* key, const String& val) { strings[key] = val._s; }
|
||||
void clear() { ints.clear(); strings.clear(); }
|
||||
void clear() { ints.clear(); uints.clear(); strings.clear(); }
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
// Native-test stubs for gpio_hold_* — operation.h calls
|
||||
// gpio_deep_sleep_hold_en() before esp_deep_sleep_start() to latch
|
||||
// PIN_PWR LOW through deep sleep. epd_driver.cpp (not built natively)
|
||||
// also uses gpio_hold_en / gpio_hold_dis. Stubs let tests link.
|
||||
#include "esp_sleep.h" // for gpio_num_t
|
||||
|
||||
inline void gpio_hold_en(gpio_num_t) {}
|
||||
inline void gpio_hold_dis(gpio_num_t) {}
|
||||
inline void gpio_deep_sleep_hold_en() {}
|
||||
inline void gpio_deep_sleep_hold_dis() {}
|
||||
Reference in New Issue
Block a user