feat: add Xteink X3 hardware support

Adds HAL-level support for the Xteink X3 (SSD1677 controller, 792x528
display). Includes device detection, display initialization, button
mapping, power management, and theme adjustments for the X3 form factor.
This commit is contained in:
Justin Mitchell
2026-04-03 04:04:17 -04:00
parent aa085425af
commit 0db9d93f1c
16 changed files with 564 additions and 132 deletions
+37 -2
View File
@@ -11,7 +11,15 @@
HalPowerManager powerManager; // Singleton instance
void HalPowerManager::begin() {
pinMode(BAT_GPIO0, INPUT);
if (gpio.deviceIsX3()) {
// X3 uses an I2C fuel gauge for battery monitoring.
// I2C init must come AFTER gpio.begin() so early hardware detection/probes are finished.
Wire.begin(X3_I2C_SDA, X3_I2C_SCL, X3_I2C_FREQ);
Wire.setTimeOut(4);
_batteryUseI2C = true;
} else {
pinMode(BAT_GPIO0, INPUT);
}
normalFreq = getCpuFrequencyMhz();
modeMutex = xSemaphoreCreateMutex();
assert(modeMutex != nullptr);
@@ -78,8 +86,35 @@ void HalPowerManager::startDeepSleep(HalGPIO& gpio) const {
}
uint16_t HalPowerManager::getBatteryPercentage() const {
if (_batteryUseI2C) {
const unsigned long now = millis();
if (_batteryLastPollMs != 0 && (now - _batteryLastPollMs) < BATTERY_POLL_MS) {
return _batteryCachedPercent;
}
// Read SOC directly from I2C fuel gauge (16-bit LE register).
// On I2C error, keep last known value to avoid UI jitter/slowdowns.
Wire.beginTransmission(I2C_ADDR_BQ27220);
Wire.write(BQ27220_SOC_REG);
if (Wire.endTransmission(false) != 0) {
_batteryLastPollMs = now;
return _batteryCachedPercent;
}
Wire.requestFrom(I2C_ADDR_BQ27220, (uint8_t)2);
if (Wire.available() < 2) {
_batteryLastPollMs = now;
return _batteryCachedPercent;
}
const uint8_t lo = Wire.read();
const uint8_t hi = Wire.read();
const uint16_t soc = (hi << 8) | lo;
_batteryCachedPercent = soc > 100 ? 100 : soc;
_batteryLastPollMs = now;
return _batteryCachedPercent;
}
static const BatteryMonitor battery = BatteryMonitor(BAT_GPIO0);
return battery.readPercentage();
_batteryCachedPercent = battery.readPercentage();
return _batteryCachedPercent;
}
HalPowerManager::Lock::Lock() {