Full hardware swap from Panlee SC01 Plus (480×320 IPS) to Waveshare 2.16" square AMOLED (480×480, CO5300 + CST9220 + AXP2101 + QMI8658). Library stack moves to Arduino_GFX, SensorLib, XPowersLib on the pioarduino platform 55.03.38-1 (Arduino Core 3.x). UI: - 4 screens (splash, usage, controller, bluetooth) with 3-button physical navigation: GPIO 0 = prev, AXP PKEY = cycle, GPIO 18 = next. - IMU-driven 90° auto-rotation. CO5300 can't rotate via MADCTL, so flush callback does CPU strip-rotation in PARTIAL render mode. Rotation transitions use AMOLED brightness flash (instant black → redraw → ramp). - Battery indicator (Lucide icons) in upper-right, RGB565A8 alpha so it blends over the splash animations. - USB plugged/unplugged auto-switches between Usage and Controller screens (suppressed while on splash). - Fonts and icons re-scaled ~1.9× for the higher-DPI panel; 20px margins to clear rounded corners. Splash: - 13 × 20×20 pixel-art creature animations sourced from claudepix.vercel.app via tools/scrape_claudepix.js (scraper handles both PRESET creature-engine and standalone FRAMES+PAL formats). tools/convert_to_c.js emits firmware/src/splash_animations.h. Attribution preserved in README and the generated header. Tooling: - tools/png_to_lvgl.js converts alpha PNGs to LVGL RGB565A8 (planar layout, with --tint to colorize Lucide black-on-transparent sources). - tools/scrape_claudepix.js, tools/convert_to_c.js for the splash pipeline. Docs: - New worktree CLAUDE.md with hardware pin map, file inventory, build commands, and the 8 critical gotchas (CO5300 rotation, OPI PSRAM, pioarduino requirement, LVGL 9 font patching, centralized touch read, even-aligned flush regions, touch swap/mirror values, RGB565A8 layout). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
100 lines
2.4 KiB
C++
100 lines
2.4 KiB
C++
#include "power.h"
|
|
#include "display_cfg.h"
|
|
#include <Arduino.h>
|
|
|
|
// Poll intervals
|
|
#define BATTERY_POLL_MS 2000
|
|
#define VBUS_POLL_MS 500
|
|
|
|
static int cached_pct = -1;
|
|
static bool cached_charging = false;
|
|
static bool cached_usb = false;
|
|
static bool usb_changed_flag = false;
|
|
static bool pwr_pressed_flag = false;
|
|
static uint32_t last_battery_ms = 0;
|
|
static uint32_t last_vbus_ms = 0;
|
|
static uint32_t last_pwr_ms = 0;
|
|
#define PWR_POLL_MS 50
|
|
|
|
void power_init(void) {
|
|
if (!pmu.begin(Wire, AXP2101_ADDR, IIC_SDA, IIC_SCL)) {
|
|
Serial.println("AXP2101 init failed");
|
|
return;
|
|
}
|
|
Serial.println("AXP2101 init OK");
|
|
|
|
// Enable battery and VBUS ADC measurements
|
|
pmu.enableBattDetection();
|
|
pmu.enableVbusVoltageMeasure();
|
|
pmu.enableBattVoltageMeasure();
|
|
|
|
// Enable PWR button short-press IRQ (mid button for cycling screens)
|
|
pmu.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
|
|
pmu.clearIrqStatus();
|
|
pmu.enableIRQ(XPOWERS_AXP2101_PKEY_SHORT_IRQ);
|
|
|
|
// Read initial state
|
|
cached_usb = pmu.isVbusIn();
|
|
cached_charging = pmu.isCharging();
|
|
cached_pct = pmu.getBatteryPercent();
|
|
}
|
|
|
|
void power_tick(void) {
|
|
uint32_t now = millis();
|
|
|
|
// Poll VBUS status
|
|
if (now - last_vbus_ms >= VBUS_POLL_MS) {
|
|
last_vbus_ms = now;
|
|
bool usb_now = pmu.isVbusIn();
|
|
if (usb_now != cached_usb) {
|
|
cached_usb = usb_now;
|
|
usb_changed_flag = true;
|
|
}
|
|
cached_charging = pmu.isCharging();
|
|
}
|
|
|
|
// Poll battery level
|
|
if (now - last_battery_ms >= BATTERY_POLL_MS) {
|
|
last_battery_ms = now;
|
|
cached_pct = pmu.getBatteryPercent();
|
|
}
|
|
|
|
// Poll PWR button (AXP2101 short-press IRQ)
|
|
if (now - last_pwr_ms >= PWR_POLL_MS) {
|
|
last_pwr_ms = now;
|
|
pmu.getIrqStatus();
|
|
if (pmu.isPekeyShortPressIrq()) {
|
|
pwr_pressed_flag = true;
|
|
}
|
|
pmu.clearIrqStatus();
|
|
}
|
|
}
|
|
|
|
int power_battery_pct(void) {
|
|
return cached_pct;
|
|
}
|
|
|
|
bool power_is_charging(void) {
|
|
return cached_charging;
|
|
}
|
|
|
|
bool power_is_usb_connected(void) {
|
|
return cached_usb;
|
|
}
|
|
|
|
bool power_usb_changed(void) {
|
|
if (usb_changed_flag) {
|
|
usb_changed_flag = false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool power_pwr_pressed(void) {
|
|
if (pwr_pressed_flag) {
|
|
pwr_pressed_flag = false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|