Merge branch 'x3-support'

# Conflicts:
#	lib/GfxRenderer/GfxRenderer.h
#	open-x4-sdk
This commit is contained in:
jpirnay
2026-04-04 10:05:14 +02:00
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);
@@ -87,8 +95,35 @@ void HalPowerManager::startDeepSleep(HalGPIO& gpio, bool keepClockAlive) 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() {