Battery, EPD, and SD support for m5paper
Also hide button hints
This commit is contained in:
@@ -27,7 +27,10 @@ won't trigger deprecation warnings.
|
|||||||
#define LOG_LEVEL 0
|
#define LOG_LEVEL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static HWCDC& logSerial = Serial;
|
// The concrete Serial type differs by MCU: HWCDC (native USB CDC on C3/S3) vs
|
||||||
|
// HardwareSerial (UART0 on the classic ESP32 / M5Paper). Bind to whatever the
|
||||||
|
// real Serial is here — this is before the `#define Serial` shim below.
|
||||||
|
static decltype(Serial)& logSerial = Serial;
|
||||||
|
|
||||||
void logPrintf(const char* level, const char* origin, const char* format, ...);
|
void logPrintf(const char* level, const char* origin, const char* format, ...);
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,13 @@ HalGPIO::DeviceType detectDeviceTypeWithFingerprint() {
|
|||||||
|
|
||||||
void HalGPIO::begin() {
|
void HalGPIO::begin() {
|
||||||
inputMgr.begin();
|
inputMgr.begin();
|
||||||
|
#if !(defined(FREEINK_DEVICE_M5PAPER) && FREEINK_DEVICE_M5PAPER)
|
||||||
|
// Claim the shared SPI bus with the X4/X3 display+SD pins. On M5Paper the SDK's
|
||||||
|
// IT8951 driver and SDCardManager each bring up SPI from BoardConfig::ACTIVE
|
||||||
|
// pins; pre-claiming VSPI here would stick (SPIClass::begin early-returns if the
|
||||||
|
// bus is already started) and leave the SD card on the wrong pins.
|
||||||
SPI.begin(EPD_SCLK, SPI_MISO, EPD_MOSI, EPD_CS);
|
SPI.begin(EPD_SCLK, SPI_MISO, EPD_MOSI, EPD_CS);
|
||||||
|
#endif
|
||||||
|
|
||||||
_deviceType = detectDeviceTypeWithFingerprint();
|
_deviceType = detectDeviceTypeWithFingerprint();
|
||||||
|
|
||||||
@@ -232,12 +238,29 @@ void HalGPIO::startDeepSleep() {
|
|||||||
inputMgr.update();
|
inputMgr.update();
|
||||||
}
|
}
|
||||||
// Arm the wakeup trigger *after* the button is released
|
// Arm the wakeup trigger *after* the button is released
|
||||||
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
||||||
|
// Xtensa (classic ESP32 / S3): GPIO deep-sleep wake is via RTC ext1.
|
||||||
|
esp_sleep_enable_ext1_wakeup(1ULL << InputManager::POWER_BUTTON_PIN, ESP_EXT1_WAKEUP_ALL_LOW);
|
||||||
|
#else
|
||||||
|
// RISC-V (C3): direct GPIO deep-sleep wakeup source.
|
||||||
esp_deep_sleep_enable_gpio_wakeup(1ULL << InputManager::POWER_BUTTON_PIN, ESP_GPIO_WAKEUP_GPIO_LOW);
|
esp_deep_sleep_enable_gpio_wakeup(1ULL << InputManager::POWER_BUTTON_PIN, ESP_GPIO_WAKEUP_GPIO_LOW);
|
||||||
|
#endif
|
||||||
// Enter Deep Sleep
|
// Enter Deep Sleep
|
||||||
esp_deep_sleep_start();
|
esp_deep_sleep_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HalGPIO::verifyPowerButtonWakeup(uint16_t requiredDurationMs, bool shortPressAllowed) {
|
void HalGPIO::verifyPowerButtonWakeup(uint16_t requiredDurationMs, bool shortPressAllowed) {
|
||||||
|
if (BoardConfig::ACTIVE.input.power < 0) {
|
||||||
|
// No readable power-button input pin: can't verify a hold, so don't sleep.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if defined(FREEINK_DEVICE_M5PAPER) && FREEINK_DEVICE_M5PAPER
|
||||||
|
// M5Paper: power-on is a hardware latch and the "power button" is the rotary
|
||||||
|
// push (G38), shared with Confirm. A USB/flash cold boot is indistinguishable
|
||||||
|
// from an intentional power-on hold here, so skip the X4-style anti-accidental-
|
||||||
|
// wake check and always boot. G38 still serves as the deep-sleep wake source.
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
if (shortPressAllowed) {
|
if (shortPressAllowed) {
|
||||||
// Fast path - no duration check needed
|
// Fast path - no duration check needed
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ void HalPowerManager::begin() {
|
|||||||
Wire.setTimeOut(4);
|
Wire.setTimeOut(4);
|
||||||
_batteryUseI2C = true;
|
_batteryUseI2C = true;
|
||||||
} else {
|
} else {
|
||||||
pinMode(BAT_GPIO0, INPUT);
|
// Battery ADC pin from the active board profile (X4: GPIO0, M5Paper: GPIO35),
|
||||||
|
// not a hardcoded X4 pin.
|
||||||
|
pinMode(BoardConfig::ACTIVE.batteryAdc, INPUT);
|
||||||
}
|
}
|
||||||
normalFreq = getCpuFrequencyMhz();
|
normalFreq = getCpuFrequencyMhz();
|
||||||
modeMutex = xSemaphoreCreateMutex();
|
modeMutex = xSemaphoreCreateMutex();
|
||||||
@@ -76,8 +78,10 @@ void HalPowerManager::startDeepSleep(HalGPIO& gpio) const {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Pre-sleep routines from the original firmware
|
// Pre-sleep routines from the original firmware
|
||||||
|
#if !SOC_PM_SUPPORT_EXT1_WAKEUP // RISC-V (C3 / X4)
|
||||||
// GPIO13 is connected to battery latch MOSFET, we need to make sure it's low during sleep
|
// GPIO13 is connected to battery latch MOSFET, we need to make sure it's low during sleep
|
||||||
// Note that this means the MCU will be completely powered off during sleep, including RTC
|
// Note that this means the MCU will be completely powered off during sleep, including RTC
|
||||||
|
// (X4-specific: on classic ESP32/M5Paper GPIO13 is SD MISO, so this is skipped.)
|
||||||
constexpr gpio_num_t GPIO_SPIWP = GPIO_NUM_13;
|
constexpr gpio_num_t GPIO_SPIWP = GPIO_NUM_13;
|
||||||
gpio_set_direction(GPIO_SPIWP, GPIO_MODE_OUTPUT);
|
gpio_set_direction(GPIO_SPIWP, GPIO_MODE_OUTPUT);
|
||||||
gpio_set_level(GPIO_SPIWP, 0);
|
gpio_set_level(GPIO_SPIWP, 0);
|
||||||
@@ -90,6 +94,10 @@ void HalPowerManager::startDeepSleep(HalGPIO& gpio) const {
|
|||||||
// power button is hard-wired to briefly provide power to the MCU, waking it up regardless of the wakeup source
|
// power button is hard-wired to briefly provide power to the MCU, waking it up regardless of the wakeup source
|
||||||
// configuration
|
// configuration
|
||||||
esp_deep_sleep_enable_gpio_wakeup(1ULL << InputManager::POWER_BUTTON_PIN, ESP_GPIO_WAKEUP_GPIO_LOW);
|
esp_deep_sleep_enable_gpio_wakeup(1ULL << InputManager::POWER_BUTTON_PIN, ESP_GPIO_WAKEUP_GPIO_LOW);
|
||||||
|
#else // Xtensa (classic ESP32 / S3): RTC ext1 GPIO wake
|
||||||
|
pinMode(InputManager::POWER_BUTTON_PIN, INPUT_PULLUP);
|
||||||
|
esp_sleep_enable_ext1_wakeup(1ULL << InputManager::POWER_BUTTON_PIN, ESP_EXT1_WAKEUP_ALL_LOW);
|
||||||
|
#endif
|
||||||
// Enter Deep Sleep
|
// Enter Deep Sleep
|
||||||
esp_deep_sleep_start();
|
esp_deep_sleep_start();
|
||||||
}
|
}
|
||||||
@@ -121,7 +129,8 @@ uint16_t HalPowerManager::getBatteryPercentage() const {
|
|||||||
_batteryLastPollMs = now;
|
_batteryLastPollMs = now;
|
||||||
return _batteryCachedPercent;
|
return _batteryCachedPercent;
|
||||||
}
|
}
|
||||||
static const BatteryMonitor battery = BatteryMonitor(BAT_GPIO0);
|
// ADC pin from the active profile (X4 GPIO0 / M5Paper GPIO35); default 2:1 divider.
|
||||||
|
static const BatteryMonitor battery = BatteryMonitor(BoardConfig::ACTIVE.batteryAdc);
|
||||||
|
|
||||||
// smooth the battery %.
|
// smooth the battery %.
|
||||||
if (_batteryCachedPercent == 0) {
|
if (_batteryCachedPercent == 0) {
|
||||||
|
|||||||
@@ -38,6 +38,13 @@ void IRAM_ATTR __wrap_panic_print_backtrace(const void* frame, int core) {
|
|||||||
__real_panic_print_backtrace(frame, core);
|
__real_panic_print_backtrace(frame, core);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if !__riscv
|
||||||
|
// RvExcFrame and the flat SP scan below are RISC-V-only (C3). On Xtensa
|
||||||
|
// (classic ESP32 / S3) the exception frame is XtExcFrame with windowed-register
|
||||||
|
// unwinding, so fall back to the default backtrace.
|
||||||
|
__real_panic_print_backtrace(frame, core);
|
||||||
|
return;
|
||||||
|
#else
|
||||||
for (size_t i = 0; i < MAX_PANIC_STACK_DEPTH; i++) {
|
for (size_t i = 0; i < MAX_PANIC_STACK_DEPTH; i++) {
|
||||||
panicStack[i].sp = 0;
|
panicStack[i].sp = 0;
|
||||||
}
|
}
|
||||||
@@ -65,6 +72,7 @@ void IRAM_ATTR __wrap_panic_print_backtrace(const void* frame, int core) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__real_panic_print_backtrace(frame, core);
|
__real_panic_print_backtrace(frame, core);
|
||||||
|
#endif // __riscv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,13 @@
|
|||||||
#include "settings/SettingsActivity.h"
|
#include "settings/SettingsActivity.h"
|
||||||
#include "util/FullScreenMessageActivity.h"
|
#include "util/FullScreenMessageActivity.h"
|
||||||
|
|
||||||
|
// taskENTER_CRITICAL needs a real spinlock on dual-core targets (classic ESP32,
|
||||||
|
// e.g. M5Paper). On the single-core ESP32-C3 a nullptr mux was tolerated, but
|
||||||
|
// the dual-core port acquires an inter-core spinlock and asserts on a null
|
||||||
|
// pointer (spinlock_acquire, spinlock.h:84). One shared spinlock guards the
|
||||||
|
// short waitingTaskHandle critical sections below.
|
||||||
|
static portMUX_TYPE activityMux = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
void ActivityManager::begin() {
|
void ActivityManager::begin() {
|
||||||
xTaskCreate(&renderTaskTrampoline, "ActivityManagerRender",
|
xTaskCreate(&renderTaskTrampoline, "ActivityManagerRender",
|
||||||
8192, // Stack size
|
8192, // Stack size
|
||||||
@@ -45,10 +52,10 @@ void ActivityManager::renderTaskLoop() {
|
|||||||
}
|
}
|
||||||
// Notify any task blocked in requestUpdateAndWait() that the render is done.
|
// Notify any task blocked in requestUpdateAndWait() that the render is done.
|
||||||
TaskHandle_t waiter = nullptr;
|
TaskHandle_t waiter = nullptr;
|
||||||
taskENTER_CRITICAL(nullptr);
|
taskENTER_CRITICAL(&activityMux);
|
||||||
waiter = waitingTaskHandle;
|
waiter = waitingTaskHandle;
|
||||||
waitingTaskHandle = nullptr;
|
waitingTaskHandle = nullptr;
|
||||||
taskEXIT_CRITICAL(nullptr);
|
taskEXIT_CRITICAL(&activityMux);
|
||||||
if (waiter) {
|
if (waiter) {
|
||||||
xTaskNotify(waiter, 1, eIncrement);
|
xTaskNotify(waiter, 1, eIncrement);
|
||||||
}
|
}
|
||||||
@@ -279,7 +286,7 @@ void ActivityManager::requestUpdateAndWait() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Atomic section to perform checks
|
// Atomic section to perform checks
|
||||||
taskENTER_CRITICAL(nullptr);
|
taskENTER_CRITICAL(&activityMux);
|
||||||
auto currTaskHandler = xTaskGetCurrentTaskHandle();
|
auto currTaskHandler = xTaskGetCurrentTaskHandle();
|
||||||
auto mutexHolder = xSemaphoreGetMutexHolder(renderingMutex);
|
auto mutexHolder = xSemaphoreGetMutexHolder(renderingMutex);
|
||||||
bool isRenderTask = (currTaskHandler == renderTaskHandle);
|
bool isRenderTask = (currTaskHandler == renderTaskHandle);
|
||||||
@@ -288,7 +295,7 @@ void ActivityManager::requestUpdateAndWait() {
|
|||||||
if (!alreadyWaiting && !isRenderTask && !holdingRenderLock) {
|
if (!alreadyWaiting && !isRenderTask && !holdingRenderLock) {
|
||||||
waitingTaskHandle = currTaskHandler;
|
waitingTaskHandle = currTaskHandler;
|
||||||
}
|
}
|
||||||
taskEXIT_CRITICAL(nullptr);
|
taskEXIT_CRITICAL(&activityMux);
|
||||||
|
|
||||||
// Render task cannot call requestUpdateAndWait() or it will cause a deadlock
|
// Render task cannot call requestUpdateAndWait() or it will cause a deadlock
|
||||||
assert(!isRenderTask && "Render task cannot call requestUpdateAndWait()");
|
assert(!isRenderTask && "Render task cannot call requestUpdateAndWait()");
|
||||||
|
|||||||
@@ -132,8 +132,27 @@ void BaseTheme::drawProgressBar(const GfxRenderer& renderer, Rect rect, const si
|
|||||||
renderer.drawCenteredText(UI_10_FONT_ID, rect.y + rect.height + 15, percentText.c_str());
|
renderer.drawCenteredText(UI_10_FONT_ID, rect.y + rect.height + 15, percentText.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CROSSPOINT_SHOW_BUTTON_HINTS: build-flag switch (env). Default on. A device with
|
||||||
|
// no physical button row (touch + rotary, e.g. M5Paper) builds with =0.
|
||||||
|
#ifndef CROSSPOINT_SHOW_BUTTON_HINTS
|
||||||
|
#define CROSSPOINT_SHOW_BUTTON_HINTS 1
|
||||||
|
#endif
|
||||||
|
bool BaseTheme::showButtonHints() { return CROSSPOINT_SHOW_BUTTON_HINTS; }
|
||||||
|
|
||||||
|
// Non-virtual gates: one check hides hints across every theme. Themes override the
|
||||||
|
// *Impl, which only ever runs when hints are enabled.
|
||||||
void BaseTheme::drawButtonHints(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
void BaseTheme::drawButtonHints(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
||||||
const char* btn4) const {
|
const char* btn4) const {
|
||||||
|
if (!showButtonHints()) return;
|
||||||
|
drawButtonHintsImpl(renderer, btn1, btn2, btn3, btn4);
|
||||||
|
}
|
||||||
|
void BaseTheme::drawSideButtonHints(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) const {
|
||||||
|
if (!showButtonHints()) return;
|
||||||
|
drawSideButtonHintsImpl(renderer, topBtn, bottomBtn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseTheme::drawButtonHintsImpl(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
||||||
|
const char* btn4) const {
|
||||||
const GfxRenderer::Orientation orig_orientation = renderer.getOrientation();
|
const GfxRenderer::Orientation orig_orientation = renderer.getOrientation();
|
||||||
renderer.setOrientation(GfxRenderer::Orientation::Portrait);
|
renderer.setOrientation(GfxRenderer::Orientation::Portrait);
|
||||||
|
|
||||||
@@ -163,7 +182,7 @@ void BaseTheme::drawButtonHints(GfxRenderer& renderer, const char* btn1, const c
|
|||||||
renderer.setOrientation(orig_orientation);
|
renderer.setOrientation(orig_orientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseTheme::drawSideButtonHints(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) const {
|
void BaseTheme::drawSideButtonHintsImpl(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) const {
|
||||||
const int screenWidth = renderer.getScreenWidth();
|
const int screenWidth = renderer.getScreenWidth();
|
||||||
constexpr int buttonWidth = BaseMetrics::values.sideButtonHintsWidth; // Width on screen (height when rotated)
|
constexpr int buttonWidth = BaseMetrics::values.sideButtonHintsWidth; // Width on screen (height when rotated)
|
||||||
constexpr int buttonHeight = 80; // Height on screen (width when rotated)
|
constexpr int buttonHeight = 80; // Height on screen (width when rotated)
|
||||||
|
|||||||
@@ -179,9 +179,19 @@ class BaseTheme {
|
|||||||
void drawBatteryRight(const GfxRenderer& renderer, Rect rect,
|
void drawBatteryRight(const GfxRenderer& renderer, Rect rect,
|
||||||
bool showPercentage = true) const; // Right aligned (UI headers)
|
bool showPercentage = true) const; // Right aligned (UI headers)
|
||||||
virtual void fillBatteryIcon(const GfxRenderer& renderer, Rect rect, uint16_t percentage) const;
|
virtual void fillBatteryIcon(const GfxRenderer& renderer, Rect rect, uint16_t percentage) const;
|
||||||
virtual void drawButtonHints(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
// Single switch for on-screen button hints, set by the CROSSPOINT_SHOW_BUTTON_HINTS
|
||||||
|
// build flag (env; default on). Devices with no physical button row (touch +
|
||||||
|
// rotary, e.g. M5Paper) set it to 0 in their env.
|
||||||
|
static bool showButtonHints();
|
||||||
|
// Public, NON-virtual gate: returns early when hints are disabled, otherwise
|
||||||
|
// dispatches to the per-theme *Impl below. Themes override the *Impl, never
|
||||||
|
// these — so one switch hides hints across every theme.
|
||||||
|
void drawButtonHints(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
||||||
const char* btn4) const;
|
const char* btn4) const;
|
||||||
virtual void drawSideButtonHints(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) const;
|
void drawSideButtonHints(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) const;
|
||||||
|
virtual void drawButtonHintsImpl(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
||||||
|
const char* btn4) const;
|
||||||
|
virtual void drawSideButtonHintsImpl(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) const;
|
||||||
virtual int getListPageItems(int contentHeight, bool hasSubtitle) const;
|
virtual int getListPageItems(int contentHeight, bool hasSubtitle) const;
|
||||||
virtual void drawList(const GfxRenderer& renderer, Rect rect, int itemCount, int selectedIndex,
|
virtual void drawList(const GfxRenderer& renderer, Rect rect, int itemCount, int selectedIndex,
|
||||||
const std::function<std::string(int index)>& rowTitle,
|
const std::function<std::string(int index)>& rowTitle,
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ void LyraTheme::drawList(const GfxRenderer& renderer, Rect rect, int itemCount,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LyraTheme::drawButtonHints(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
void LyraTheme::drawButtonHintsImpl(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
||||||
const char* btn4) const {
|
const char* btn4) const {
|
||||||
const GfxRenderer::Orientation orig_orientation = renderer.getOrientation();
|
const GfxRenderer::Orientation orig_orientation = renderer.getOrientation();
|
||||||
renderer.setOrientation(GfxRenderer::Orientation::Portrait);
|
renderer.setOrientation(GfxRenderer::Orientation::Portrait);
|
||||||
@@ -356,7 +356,7 @@ void LyraTheme::drawButtonHints(GfxRenderer& renderer, const char* btn1, const c
|
|||||||
renderer.setOrientation(orig_orientation);
|
renderer.setOrientation(orig_orientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LyraTheme::drawSideButtonHints(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) const {
|
void LyraTheme::drawSideButtonHintsImpl(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) const {
|
||||||
const int screenWidth = renderer.getScreenWidth();
|
const int screenWidth = renderer.getScreenWidth();
|
||||||
constexpr int buttonWidth = LyraMetrics::values.sideButtonHintsWidth; // Width on screen (height when rotated)
|
constexpr int buttonWidth = LyraMetrics::values.sideButtonHintsWidth; // Width on screen (height when rotated)
|
||||||
constexpr int buttonHeight = 78; // Height on screen (width when rotated)
|
constexpr int buttonHeight = 78; // Height on screen (width when rotated)
|
||||||
|
|||||||
@@ -84,9 +84,9 @@ class LyraTheme : public BaseTheme {
|
|||||||
const std::function<std::string(int index)>& rowSubtitle,
|
const std::function<std::string(int index)>& rowSubtitle,
|
||||||
const std::function<UIIcon(int index)>& rowIcon, const std::function<std::string(int index)>& rowValue,
|
const std::function<UIIcon(int index)>& rowIcon, const std::function<std::string(int index)>& rowValue,
|
||||||
bool highlightValue, const std::function<bool(int index)>& rowDimmed = nullptr) const override;
|
bool highlightValue, const std::function<bool(int index)>& rowDimmed = nullptr) const override;
|
||||||
void drawButtonHints(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
void drawButtonHintsImpl(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
||||||
const char* btn4) const override;
|
const char* btn4) const override;
|
||||||
void drawSideButtonHints(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) const override;
|
void drawSideButtonHintsImpl(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) const override;
|
||||||
void drawButtonMenu(GfxRenderer& renderer, Rect rect, int buttonCount, int selectedIndex,
|
void drawButtonMenu(GfxRenderer& renderer, Rect rect, int buttonCount, int selectedIndex,
|
||||||
const std::function<std::string(int index)>& buttonLabel,
|
const std::function<std::string(int index)>& buttonLabel,
|
||||||
const std::function<UIIcon(int index)>& rowIcon) const override;
|
const std::function<UIIcon(int index)>& rowIcon) const override;
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ void RoundedRaffTheme::drawList(const GfxRenderer& renderer, Rect rect, int item
|
|||||||
drawScrollBar(renderer, rect, itemCount, pageStartIndex, pageItems);
|
drawScrollBar(renderer, rect, itemCount, pageStartIndex, pageItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoundedRaffTheme::drawButtonHints(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
void RoundedRaffTheme::drawButtonHintsImpl(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
||||||
const char* btn4) const {
|
const char* btn4) const {
|
||||||
const GfxRenderer::Orientation origOrientation = renderer.getOrientation();
|
const GfxRenderer::Orientation origOrientation = renderer.getOrientation();
|
||||||
renderer.setOrientation(GfxRenderer::Orientation::Portrait);
|
renderer.setOrientation(GfxRenderer::Orientation::Portrait);
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class RoundedRaffTheme : public BaseTheme {
|
|||||||
const std::function<UIIcon(int index)>& rowIcon = nullptr,
|
const std::function<UIIcon(int index)>& rowIcon = nullptr,
|
||||||
const std::function<std::string(int index)>& rowValue = nullptr, bool highlightValue = false,
|
const std::function<std::string(int index)>& rowValue = nullptr, bool highlightValue = false,
|
||||||
const std::function<bool(int index)>& rowDimmed = nullptr) const override;
|
const std::function<bool(int index)>& rowDimmed = nullptr) const override;
|
||||||
void drawButtonHints(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
void drawButtonHintsImpl(GfxRenderer& renderer, const char* btn1, const char* btn2, const char* btn3,
|
||||||
const char* btn4) const override;
|
const char* btn4) const override;
|
||||||
bool homeMenuShowsContinueReading() const { return true; }
|
bool homeMenuShowsContinueReading() const { return true; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -305,6 +305,14 @@ void setupDisplayAndFonts(bool seamless = false) {
|
|||||||
void setup() {
|
void setup() {
|
||||||
t1 = millis();
|
t1 = millis();
|
||||||
|
|
||||||
|
#if defined(FREEINK_DEVICE_M5PAPER) && FREEINK_DEVICE_M5PAPER
|
||||||
|
// M5Paper v1.1 latches its own power through a MOSFET on GPIO2. Drive it HIGH
|
||||||
|
// first thing or the board powers off the instant USB is unplugged. (Board
|
||||||
|
// responsibility, not the SDK — see freeink-sdk platformio.sample.ini.)
|
||||||
|
pinMode(2, OUTPUT);
|
||||||
|
digitalWrite(2, HIGH);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_SERIAL_LOG
|
#ifdef ENABLE_SERIAL_LOG
|
||||||
// Earliest possible Serial setup. The 250 ms stall before begin() lets the
|
// Earliest possible Serial setup. The 250 ms stall before begin() lets the
|
||||||
// USB Serial/JTAG peripheral finish power-on and lets the host complete USB
|
// USB Serial/JTAG peripheral finish power-on and lets the host complete USB
|
||||||
@@ -313,7 +321,11 @@ void setup() {
|
|||||||
// worked without the delay because USB was already enumerated.
|
// worked without the delay because USB was already enumerated.
|
||||||
delay(250);
|
delay(250);
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
#if defined(ARDUINO_USB_CDC_ON_BOOT) && ARDUINO_USB_CDC_ON_BOOT
|
||||||
|
// setTxTimeoutMs is an HWCDC (native USB CDC) method. On the classic ESP32
|
||||||
|
// (M5Paper) Serial is UART0/HardwareSerial, which has no such method.
|
||||||
logSerial.setTxTimeoutMs(1); // This is a load-bearing 1. Do not modify.
|
logSerial.setTxTimeoutMs(1); // This is a load-bearing 1. Do not modify.
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HalSystem::begin();
|
HalSystem::begin();
|
||||||
|
|||||||
Reference in New Issue
Block a user