mirror of
https://github.com/crosspoint-reader/crosspoint-reader.git
synced 2026-04-29 10:26:52 -07:00
Fixes maintainer requests
This commit is contained in:
+1
-1
@@ -9,4 +9,4 @@ build
|
||||
**/__pycache__/
|
||||
/compile_commands.json
|
||||
/.cache
|
||||
notes.md
|
||||
/notes.md
|
||||
|
||||
+23
-2
@@ -1,5 +1,6 @@
|
||||
#include <HalGPIO.h>
|
||||
#include <SPI.h>
|
||||
#include <Wire.h>
|
||||
#include <esp_sleep.h>
|
||||
|
||||
void HalGPIO::begin() {
|
||||
@@ -14,6 +15,16 @@ void HalGPIO::begin() {
|
||||
|
||||
pinMode(_batteryPin, INPUT);
|
||||
pinMode(UART0_RXD, INPUT);
|
||||
|
||||
// I2C init must come AFTER pinMode(UART0_RXD) because GPIO20 is shared
|
||||
// between USB detection (digital read) and I2C SDA. Wire.begin()
|
||||
// reconfigures the pin for I2C, so it must run last.
|
||||
if (_deviceType == DeviceType::X3) {
|
||||
Wire.begin(20, 0, 400000);
|
||||
_useI2C = true;
|
||||
_i2cAddr = 0x55;
|
||||
_socRegister = 0x2C;
|
||||
}
|
||||
}
|
||||
|
||||
void HalGPIO::update() { inputMgr.update(); }
|
||||
@@ -43,8 +54,18 @@ void HalGPIO::startDeepSleep() {
|
||||
}
|
||||
|
||||
int HalGPIO::getBatteryPercentage() const {
|
||||
if (_deviceType == DeviceType::X3) {
|
||||
return 0;
|
||||
if (_useI2C) {
|
||||
// Read SOC directly from I2C fuel gauge (16-bit LE register).
|
||||
// Returns 0 on I2C error so the UI shows 0% rather than crashing.
|
||||
Wire.beginTransmission(_i2cAddr);
|
||||
Wire.write(_socRegister);
|
||||
if (Wire.endTransmission(false) != 0) return 0;
|
||||
Wire.requestFrom(_i2cAddr, (uint8_t)2);
|
||||
if (Wire.available() < 2) return 0;
|
||||
const uint8_t lo = Wire.read();
|
||||
const uint8_t hi = Wire.read();
|
||||
const uint16_t soc = (hi << 8) | lo;
|
||||
return soc > 100 ? 100 : soc;
|
||||
}
|
||||
static const BatteryMonitor bat(BAT_GPIO0);
|
||||
return bat.readPercentage();
|
||||
|
||||
@@ -30,6 +30,9 @@ class HalGPIO {
|
||||
DeviceType _deviceType = DeviceType::X4;
|
||||
int _detectAdcValue = 0;
|
||||
int _batteryPin = BAT_GPIO0;
|
||||
bool _useI2C = false;
|
||||
uint8_t _i2cAddr = 0;
|
||||
uint8_t _socRegister = 0;
|
||||
|
||||
public:
|
||||
HalGPIO() = default;
|
||||
@@ -73,3 +76,5 @@ class HalGPIO {
|
||||
static constexpr uint8_t BTN_DOWN = 5;
|
||||
static constexpr uint8_t BTN_POWER = 6;
|
||||
};
|
||||
|
||||
extern HalGPIO gpio;
|
||||
|
||||
+6
-4
@@ -41,10 +41,12 @@ extra_scripts =
|
||||
|
||||
; Libraries
|
||||
lib_deps =
|
||||
BatteryMonitor=symlink://open-x4-sdk/libs/hardware/BatteryMonitor
|
||||
InputManager=symlink://open-x4-sdk/libs/hardware/InputManager
|
||||
EInkDisplay=symlink://open-x4-sdk/libs/display/EInkDisplay
|
||||
SDCardManager=symlink://open-x4-sdk/libs/hardware/SDCardManager
|
||||
; Use standalone community-sdk checkout (sibling folder) instead of submodule.
|
||||
; This makes local SDK edits in ../community-sdk immediately used by crosspoint-reader.
|
||||
BatteryMonitor=symlink://../community-sdk/libs/hardware/BatteryMonitor
|
||||
InputManager=symlink://../community-sdk/libs/hardware/InputManager
|
||||
EInkDisplay=symlink://../community-sdk/libs/display/EInkDisplay
|
||||
SDCardManager=symlink://../community-sdk/libs/hardware/SDCardManager
|
||||
bblanchon/ArduinoJson @ 7.4.2
|
||||
ricmoo/QRCode @ 0.0.1
|
||||
links2004/WebSockets @ 2.7.3
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#include "Battery.h"
|
||||
#include <Wire.h>
|
||||
|
||||
void BatteryProvider::setI2CFuelGauge(uint8_t i2cAddr, uint8_t socRegister) {
|
||||
_useI2C = true;
|
||||
_i2cAddr = i2cAddr;
|
||||
_socRegister = socRegister;
|
||||
}
|
||||
|
||||
uint16_t BatteryProvider::readPercentage() const {
|
||||
if (_useI2C) {
|
||||
// Read SOC directly from I2C fuel gauge (16-bit LE register).
|
||||
// Returns 0 on I2C error so the UI shows 0% rather than crashing.
|
||||
Wire.beginTransmission(_i2cAddr);
|
||||
Wire.write(_socRegister);
|
||||
if (Wire.endTransmission(false) != 0) return 0;
|
||||
Wire.requestFrom(_i2cAddr, (uint8_t)2);
|
||||
if (Wire.available() < 2) return 0;
|
||||
const uint8_t lo = Wire.read();
|
||||
const uint8_t hi = Wire.read();
|
||||
const uint16_t soc = (hi << 8) | lo;
|
||||
return soc > 100 ? 100 : soc;
|
||||
}
|
||||
// ADC path: read raw voltage, apply divider, convert via LiPo polynomial
|
||||
return _adcMonitor.readPercentage();
|
||||
}
|
||||
|
||||
// Meyer's singleton — single shared instance across all translation units.
|
||||
// Defaults to X4 ADC mode. For X3, main.cpp calls setI2CFuelGauge() to switch.
|
||||
BatteryProvider& battery() {
|
||||
static BatteryProvider instance;
|
||||
return instance;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
#include <BatteryMonitor.h>
|
||||
#include <cstdint>
|
||||
|
||||
#define BAT_GPIO0 0 // Battery voltage (X4 ADC pin)
|
||||
|
||||
// Unified battery reader supporting two backends:
|
||||
// - X4: ADC voltage divider on GPIO0 (default, no setup needed)
|
||||
// - X3: BQ27220 fuel gauge via I2C at 0x55, SOC register 0x2C
|
||||
// (call setI2CFuelGauge() after Wire.begin())
|
||||
class BatteryProvider {
|
||||
public:
|
||||
// Read battery percentage (0-100). Delegates to ADC or I2C depending on mode.
|
||||
uint16_t readPercentage() const;
|
||||
|
||||
// Switch to I2C fuel gauge mode. Wire.begin() must be called first.
|
||||
// i2cAddr: fuel gauge I2C address (e.g. 0x55 for BQ27220)
|
||||
// socRegister: register holding state-of-charge 0-100% (e.g. 0x2C)
|
||||
void setI2CFuelGauge(uint8_t i2cAddr, uint8_t socRegister);
|
||||
|
||||
private:
|
||||
BatteryMonitor _adcMonitor{BAT_GPIO0};
|
||||
bool _useI2C = false;
|
||||
uint8_t _i2cAddr = 0;
|
||||
uint8_t _socRegister = 0;
|
||||
};
|
||||
|
||||
// Shared singleton used by themes and activities.
|
||||
BatteryProvider& battery();
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "Battery.h"
|
||||
#include "CrossPointSettings.h"
|
||||
#include "CrossPointState.h"
|
||||
#include "MappedInputManager.h"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <Epub/Page.h>
|
||||
#include <FsHelpers.h>
|
||||
#include <GfxRenderer.h>
|
||||
#include <HalGPIO.h>
|
||||
#include <HalStorage.h>
|
||||
#include <Logging.h>
|
||||
|
||||
@@ -34,12 +35,6 @@ int clampPercent(int percent) {
|
||||
return percent;
|
||||
}
|
||||
|
||||
bool isX3DisplayGeometry(const GfxRenderer& renderer) {
|
||||
const int w = renderer.getScreenWidth();
|
||||
const int h = renderer.getScreenHeight();
|
||||
return (w == 792 && h == 528) || (w == 528 && h == 792);
|
||||
}
|
||||
|
||||
// Apply the logical reader orientation to the renderer.
|
||||
// This centralizes orientation mapping so we don't duplicate switch logic elsewhere.
|
||||
void applyReaderOrientation(GfxRenderer& renderer, const uint8_t orientation) {
|
||||
@@ -688,7 +683,7 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
|
||||
pagesUntilFullRefresh--;
|
||||
}
|
||||
|
||||
const bool useGrayscaleAA = SETTINGS.textAntiAliasing && !isX3DisplayGeometry(renderer);
|
||||
const bool useGrayscaleAA = SETTINGS.textAntiAliasing && gpio.getDeviceType() != HalGPIO::DeviceType::X3;
|
||||
if (useGrayscaleAA) {
|
||||
// Save BW buffer only when we actually run grayscale passes.
|
||||
renderer.storeBwBuffer();
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "Battery.h"
|
||||
#include <HalGPIO.h>
|
||||
#include "RecentBooksStore.h"
|
||||
#include "components/UITheme.h"
|
||||
#include "fontIds.h"
|
||||
@@ -23,7 +23,7 @@ constexpr int homeMarginTop = 30;
|
||||
void BaseTheme::drawBattery(const GfxRenderer& renderer, Rect rect, const bool showPercentage) const {
|
||||
// Left aligned battery icon and percentage
|
||||
// TODO refactor this so the percentage doesnt change after we position it
|
||||
const uint16_t percentage = battery().readPercentage();
|
||||
const uint16_t percentage = gpio.getBatteryPercentage();
|
||||
if (showPercentage) {
|
||||
const auto percentageText = std::to_string(percentage) + "%";
|
||||
renderer.drawText(SMALL_FONT_ID, rect.x + batteryPercentSpacing + BaseMetrics::values.batteryWidth, rect.y,
|
||||
@@ -233,7 +233,7 @@ void BaseTheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* t
|
||||
SETTINGS.hideBatteryPercentage != CrossPointSettings::HIDE_BATTERY_PERCENTAGE::HIDE_ALWAYS;
|
||||
int batteryX = rect.x + rect.width - BaseMetrics::values.contentSidePadding - BaseMetrics::values.batteryWidth;
|
||||
if (showBatteryPercentage) {
|
||||
const uint16_t percentage = battery().readPercentage();
|
||||
const uint16_t percentage = gpio.getBatteryPercentage();
|
||||
const auto percentageText = std::to_string(percentage) + "%";
|
||||
batteryX -= renderer.getTextWidth(SMALL_FONT_ID, percentageText.c_str());
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "Battery.h"
|
||||
#include <HalGPIO.h>
|
||||
#include "RecentBooksStore.h"
|
||||
#include "components/UITheme.h"
|
||||
#include "fontIds.h"
|
||||
@@ -22,7 +22,7 @@ constexpr int topHintButtonY = 345;
|
||||
|
||||
void LyraTheme::drawBattery(const GfxRenderer& renderer, Rect rect, const bool showPercentage) const {
|
||||
// Left aligned battery icon and percentage
|
||||
const uint16_t percentage = battery().readPercentage();
|
||||
const uint16_t percentage = gpio.getBatteryPercentage();
|
||||
if (showPercentage) {
|
||||
const auto percentageText = std::to_string(percentage) + "%";
|
||||
renderer.drawText(SMALL_FONT_ID, rect.x + batteryPercentSpacing + LyraMetrics::values.batteryWidth, rect.y,
|
||||
@@ -64,7 +64,7 @@ void LyraTheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* t
|
||||
SETTINGS.hideBatteryPercentage != CrossPointSettings::HIDE_BATTERY_PERCENTAGE::HIDE_ALWAYS;
|
||||
int batteryX = rect.x + rect.width - LyraMetrics::values.contentSidePadding - LyraMetrics::values.batteryWidth;
|
||||
if (showBatteryPercentage) {
|
||||
const uint16_t percentage = battery().readPercentage();
|
||||
const uint16_t percentage = gpio.getBatteryPercentage();
|
||||
const auto percentageText = std::to_string(percentage) + "%";
|
||||
batteryX -= renderer.getTextWidth(SMALL_FONT_ID, percentageText.c_str());
|
||||
}
|
||||
|
||||
+3
-19
@@ -6,12 +6,9 @@
|
||||
#include <HalStorage.h>
|
||||
#include <Logging.h>
|
||||
#include <SPI.h>
|
||||
#include <Wire.h>
|
||||
#include <builtinFonts/all.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "Battery.h"
|
||||
#include "CrossPointSettings.h"
|
||||
#include "CrossPointState.h"
|
||||
#include "KOReaderCredentialStore.h"
|
||||
@@ -130,12 +127,6 @@ EpdFontFamily ui12FontFamily(&ui12RegularFont, &ui12BoldFont);
|
||||
unsigned long t1 = 0;
|
||||
unsigned long t2 = 0;
|
||||
|
||||
inline void requestResyncIfX3(uint8_t settlePasses = 0) {
|
||||
if (gpio.getDeviceType() == HalGPIO::DeviceType::X3) {
|
||||
display.requestResync(settlePasses);
|
||||
}
|
||||
}
|
||||
|
||||
void exitActivity() {
|
||||
if (currentActivity) {
|
||||
currentActivity->onExit();
|
||||
@@ -243,7 +234,7 @@ void enterDeepSleep() {
|
||||
APP_STATE.lastSleepFromReader = currentActivity && currentActivity->isReaderActivity();
|
||||
APP_STATE.saveToFile();
|
||||
exitActivity();
|
||||
requestResyncIfX3(0);
|
||||
display.requestResync();
|
||||
enterNewActivity(new SleepActivity(renderer, mappedInputManager));
|
||||
|
||||
display.deepSleep();
|
||||
@@ -294,9 +285,7 @@ void onGoToBrowser() {
|
||||
|
||||
void onGoHome() {
|
||||
const bool returningFromReader = currentActivity && currentActivity->isReaderActivity();
|
||||
if (returningFromReader && (gpio.getDeviceType() == HalGPIO::DeviceType::X3)) {
|
||||
// Force Home's first frame to run a full resync on X3.
|
||||
// Avoid doing a blocking scrub refresh before activity transition.
|
||||
if (returningFromReader) {
|
||||
display.requestResync(1);
|
||||
}
|
||||
exitActivity();
|
||||
@@ -307,11 +296,6 @@ void onGoHome() {
|
||||
void setupDisplayAndFonts() {
|
||||
if (gpio.getDeviceType() == HalGPIO::DeviceType::X3) {
|
||||
display.setDisplayDimensions(792, 528);
|
||||
// X3 has a BQ27220 fuel gauge on I2C (addr 0x55) instead of an ADC voltage
|
||||
// divider. SOC (0-100%) is read directly from register 0x2C.
|
||||
// I2C bus: SDA=GPIO20, SCL=GPIO0, 400kHz (matches stock X3 firmware).
|
||||
Wire.begin(20, 0, 400000);
|
||||
battery().setI2CFuelGauge(0x55, 0x2C);
|
||||
}
|
||||
display.begin();
|
||||
renderer.begin();
|
||||
@@ -401,7 +385,7 @@ void setup() {
|
||||
setupDisplayAndFonts();
|
||||
if (wakeupReason == HalGPIO::WakeupReason::PowerButton || wakeupReason == HalGPIO::WakeupReason::AfterFlash ||
|
||||
wakeupReason == HalGPIO::WakeupReason::Other) {
|
||||
requestResyncIfX3(0);
|
||||
display.requestResync();
|
||||
}
|
||||
|
||||
exitActivity();
|
||||
|
||||
Reference in New Issue
Block a user