## Summary Adds Xteink X3 hardware support to CrossPoint Reader. The X3 uses the same SSD1677 e-ink controller as the X4 but with a different panel (792x528 vs 800x480), different button layout, and an I2C fuel gauge (BQ27220) instead of ADC-based battery reading. All X3-specific behavior is gated by runtime device detection — X4 behavior is unchanged. Depends on community-sdk X3 support: open-x4-epaper/community-sdk#19 (merged). ## Changes ### HAL Layer **HalGPIO** (`lib/hal/HalGPIO.cpp/.h`) - I2C-based device fingerprinting at boot: probes for BQ27220 fuel gauge, DS3231 RTC, and QMI8658 IMU to distinguish X3 from X4 - Detection result cached in NVS for fast subsequent boots - Exposes `deviceIsX3()` / `deviceIsX4()` helpers used throughout the codebase - X3 button mapping (7 GPIOs vs X4's layout) - USB connection detection and wake classification for X3 **HalDisplay** (`lib/hal/HalDisplay.cpp/.h`) - Calls `einkDisplay.setDisplayX3()` before init when X3 is detected - Requests display resync after power button / flash wake events - Runtime display dimension accessors (`getDisplayWidth()`, `getDisplayHeight()`, `getBufferSize()`) - Exposed as global `display` instance for use by image converters **HalPowerManager** (`lib/hal/HalPowerManager.cpp/.h`) - X3 battery reading via I2C fuel gauge (BQ27220 at 0x55, SOC register) - X3 power button uses GPIO hold for deep sleep ### Display & Rendering **GfxRenderer** (`lib/GfxRenderer/GfxRenderer.cpp/.h`) - Buffer size and display dimensions are now runtime values (not compile-time constants) to support both panel sizes - X3 anti-aliasing tuning: only the darker grayscale level is applied to avoid washed-out text on the X3 panel. X4 retains both levels via `deviceIsX4()` gate **Image Converters** (`lib/JpegToBmpConverter`, `lib/PngToBmpConverter`) - Cover image prescale target uses runtime display dimensions from HAL instead of hardcoded 800x480 ### UI Themes **BaseTheme / LyraTheme** (`src/components/themes/`) - X3 button position mapping for the different physical layout - Adjusted UI element positioning for 792x528 viewport ### Boot & Init **main.cpp** - X3 hardware detection logging - Adjusted init sequence for X3 (no `HalSystem::begin()` dependency on X3 path) **HomeActivity** - Uses runtime `renderer.getBufferSize()` instead of static `GfxRenderer::getBufferSize()` FYI I did not add support for the gyro page turner. That can be it's own PR.
65 lines
2.0 KiB
C++
65 lines
2.0 KiB
C++
#pragma once
|
|
|
|
#include <Arduino.h>
|
|
#include <BatteryMonitor.h>
|
|
#include <InputManager.h>
|
|
#include <Logging.h>
|
|
#include <Wire.h>
|
|
#include <freertos/semphr.h>
|
|
|
|
#include <cassert>
|
|
|
|
#include "HalGPIO.h"
|
|
|
|
class HalPowerManager;
|
|
extern HalPowerManager powerManager; // Singleton
|
|
|
|
class HalPowerManager {
|
|
int normalFreq = 0; // MHz
|
|
bool isLowPower = false;
|
|
|
|
// I2C fuel gauge configuration for X3 battery monitoring
|
|
bool _batteryUseI2C = false; // True if using I2C fuel gauge (X3), false for ADC (X4)
|
|
mutable int _batteryCachedPercent = 0; // Last read battery percentage (0-100)
|
|
mutable unsigned long _batteryLastPollMs = 0; // Timestamp of last battery read in milliseconds
|
|
|
|
enum LockMode { None, NormalSpeed };
|
|
LockMode currentLockMode = None;
|
|
SemaphoreHandle_t modeMutex = nullptr; // Protect access to currentLockMode
|
|
|
|
public:
|
|
static constexpr int LOW_POWER_FREQ = 10; // MHz
|
|
static constexpr unsigned long IDLE_POWER_SAVING_MS = 3000; // ms
|
|
static constexpr unsigned long BATTERY_POLL_MS = 1500; // ms
|
|
|
|
void begin();
|
|
|
|
// Control CPU frequency for power saving
|
|
void setPowerSaving(bool enabled);
|
|
|
|
// Setup wake up GPIO and enter deep sleep
|
|
// Should be called inside main loop() to handle the currentLockMode
|
|
void startDeepSleep(HalGPIO& gpio) const;
|
|
|
|
// Get battery percentage (range 0-100)
|
|
uint16_t getBatteryPercentage() const;
|
|
|
|
// RAII helper class to manage power saving locks
|
|
// Usage: create an instance of Lock in a scope to disable power saving, for example when running a task that needs
|
|
// full performance. When the Lock instance is destroyed (goes out of scope), power saving will be re-enabled.
|
|
class Lock {
|
|
friend class HalPowerManager;
|
|
bool valid = false;
|
|
|
|
public:
|
|
explicit Lock();
|
|
~Lock();
|
|
|
|
// Non-copyable and non-movable
|
|
Lock(const Lock&) = delete;
|
|
Lock& operator=(const Lock&) = delete;
|
|
Lock(Lock&&) = delete;
|
|
Lock& operator=(Lock&&) = delete;
|
|
};
|
|
};
|