feat: Initial support for the x3 (#875)
## 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.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "JpegToBmpConverter.h"
|
||||
|
||||
#include <HalDisplay.h>
|
||||
#include <HalStorage.h>
|
||||
#include <Logging.h>
|
||||
#include <picojpeg.h>
|
||||
@@ -26,9 +27,7 @@ constexpr bool USE_ATKINSON = true; // Atkinson dithering (cleaner than
|
||||
constexpr bool USE_FLOYD_STEINBERG = false; // Floyd-Steinberg error diffusion (can cause "worm" artifacts)
|
||||
constexpr bool USE_NOISE_DITHERING = false; // Hash-based noise dithering (good for downsampling)
|
||||
// Pre-resize to target display size (CRITICAL: avoids dithering artifacts from post-downsampling)
|
||||
constexpr bool USE_PRESCALE = true; // true: scale image to target size before dithering
|
||||
constexpr int TARGET_MAX_WIDTH = 480; // Max width for cover images (portrait display width)
|
||||
constexpr int TARGET_MAX_HEIGHT = 800; // Max height for cover images (portrait display height)
|
||||
constexpr bool USE_PRESCALE = true; // true: scale image to target size before dithering
|
||||
// ============================================================================
|
||||
|
||||
inline void write16(Print& out, const uint16_t value) {
|
||||
@@ -559,7 +558,10 @@ bool JpegToBmpConverter::jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bm
|
||||
|
||||
// Core function: Convert JPEG file to 2-bit BMP (uses default target size)
|
||||
bool JpegToBmpConverter::jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut, bool crop) {
|
||||
return jpegFileToBmpStreamInternal(jpegFile, bmpOut, TARGET_MAX_WIDTH, TARGET_MAX_HEIGHT, false, crop);
|
||||
// Use runtime display dimensions (swapped for portrait cover sizing)
|
||||
const int targetWidth = display.getDisplayHeight();
|
||||
const int targetHeight = display.getDisplayWidth();
|
||||
return jpegFileToBmpStreamInternal(jpegFile, bmpOut, targetWidth, targetHeight, false, crop);
|
||||
}
|
||||
|
||||
// Convert with custom target size (for thumbnails, 2-bit)
|
||||
|
||||
Reference in New Issue
Block a user