diff --git a/lib/hal/HalGPIO.cpp b/lib/hal/HalGPIO.cpp index 1c0e7171c4..4a2c8e01e9 100644 --- a/lib/hal/HalGPIO.cpp +++ b/lib/hal/HalGPIO.cpp @@ -9,13 +9,6 @@ HalGPIO gpio; namespace { -constexpr uint8_t I2C_ADDR_BQ27220 = 0x55; -constexpr uint8_t I2C_ADDR_DS3231 = 0x68; -constexpr uint8_t I2C_ADDR_QMI8658 = 0x6B; -constexpr uint8_t I2C_ADDR_QMI8658_ALT = 0x6A; -constexpr uint8_t QMI8658_WHO_AM_I_REG = 0x00; -constexpr uint8_t QMI8658_WHO_AM_I_VALUE = 0x05; - constexpr char HW_NAMESPACE[] = "cphw"; constexpr char NVS_KEY_DEV_OVERRIDE[] = "dev_ovr"; // 0=auto, 1=x4, 2=x3 constexpr char NVS_KEY_DEV_CACHED[] = "dev_det"; // 0=unknown, 1=x4, 2=x3 @@ -65,7 +58,7 @@ bool readI2CReg16LE(uint8_t addr, uint8_t reg, uint16_t* outValue) { bool readBQ27220CurrentMA(int16_t* outCurrent) { uint16_t raw = 0; - if (!readI2CReg16LE(I2C_ADDR_BQ27220, 0x0C, &raw)) { + if (!readI2CReg16LE(I2C_ADDR_BQ27220, BQ27220_CUR_REG, &raw)) { return false; } *outCurrent = static_cast(raw); @@ -75,13 +68,13 @@ bool readBQ27220CurrentMA(int16_t* outCurrent) { bool probeBQ27220Signature() { uint16_t soc = 0; uint16_t voltageMv = 0; - if (!readI2CReg16LE(I2C_ADDR_BQ27220, 0x2C, &soc)) { + if (!readI2CReg16LE(I2C_ADDR_BQ27220, BQ27220_SOC_REG, &soc)) { return false; } if (soc > 100) { return false; } - if (!readI2CReg16LE(I2C_ADDR_BQ27220, 0x08, &voltageMv)) { + if (!readI2CReg16LE(I2C_ADDR_BQ27220, BQ27220_VOLT_REG, &voltageMv)) { return false; } return voltageMv >= 2500 && voltageMv <= 5000; @@ -89,11 +82,13 @@ bool probeBQ27220Signature() { bool probeDS3231Signature() { uint8_t sec = 0; - if (!readI2CReg8(I2C_ADDR_DS3231, 0x00, &sec)) { + if (!readI2CReg8(I2C_ADDR_DS3231, DS3231_SEC_REG, &sec)) { return false; } - const uint8_t secBcd = sec & 0x7F; - return secBcd <= 0x59; + const uint8_t tensDigit = (sec >> 4) & 0x07; + const uint8_t onesDigit = sec & 0x0F; + + return tensDigit <= 5 && onesDigit <= 9; } bool probeQMI8658Signature() { @@ -109,7 +104,7 @@ bool probeQMI8658Signature() { X3ProbeResult runX3ProbePass() { X3ProbeResult result; - Wire.begin(20, 0, 400000); + Wire.begin(X3_I2C_SDA, X3_I2C_SCL, X3_I2C_FREQ); Wire.setTimeOut(6); result.bq27220 = probeBQ27220Signature(); diff --git a/lib/hal/HalGPIO.h b/lib/hal/HalGPIO.h index ff6ed74fb7..f9ecb0dfb3 100644 --- a/lib/hal/HalGPIO.h +++ b/lib/hal/HalGPIO.h @@ -17,6 +17,27 @@ #define UART0_RXD 20 // Used for USB connection detection +// Xteink X3 Hardware +#define X3_I2C_SDA 20 +#define X3_I2C_SCL 0 +#define X3_I2C_FREQ 400000 + +// TI BQ27220 Fuel gauge I2C +#define I2C_ADDR_BQ27220 0x55 // Fuel gauge I2C address +#define BQ27220_SOC_REG 0x2C // StateOfCharge() command code (%) +#define BQ27220_CUR_REG 0x0C // Current() command code (signed mA) +#define BQ27220_VOLT_REG 0x08 // Voltage() command code (mV) + +// Analog DS3231 RTC I2C +#define I2C_ADDR_DS3231 0x68 // RTC I2C address +#define DS3231_SEC_REG 0x00 // Seconds command code (BCD) + +// QST QMI8658 IMU I2C +#define I2C_ADDR_QMI8658 0x6B // IMU I2C address +#define I2C_ADDR_QMI8658_ALT 0x6A // IMU I2C fallback address +#define QMI8658_WHO_AM_I_REG 0x00 // WHO_AM_I command code +#define QMI8658_WHO_AM_I_VALUE 0x05 // WHO_AM_I expected value + class HalGPIO { #if CROSSPOINT_EMULATED == 0 InputManager inputMgr; diff --git a/lib/hal/HalPowerManager.cpp b/lib/hal/HalPowerManager.cpp index 95f24d7713..584ee06d9c 100644 --- a/lib/hal/HalPowerManager.cpp +++ b/lib/hal/HalPowerManager.cpp @@ -14,12 +14,9 @@ void HalPowerManager::begin() { 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(20, 0, 400000); + Wire.begin(X3_I2C_SDA, X3_I2C_SCL, X3_I2C_FREQ); Wire.setTimeOut(4); _batteryUseI2C = true; - _batteryI2cAddr = 0x55; - // TI BQ27220: StateOfCharge() command code - _batterySocRegister = 0x2C; } else { pinMode(BAT_GPIO0, INPUT); } @@ -84,16 +81,14 @@ uint16_t HalPowerManager::getBatteryPercentage() const { // 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(_batteryI2cAddr); - Wire.write(_batterySocRegister); + Wire.beginTransmission(I2C_ADDR_BQ27220); + Wire.write(BQ27220_SOC_REG); if (Wire.endTransmission(false) != 0) { - _batteryI2cFailCount++; _batteryLastPollMs = now; return _batteryCachedPercent; } - Wire.requestFrom(_batteryI2cAddr, (uint8_t)2); + Wire.requestFrom(I2C_ADDR_BQ27220, (uint8_t)2); if (Wire.available() < 2) { - _batteryI2cFailCount++; _batteryLastPollMs = now; return _batteryCachedPercent; } @@ -102,7 +97,6 @@ uint16_t HalPowerManager::getBatteryPercentage() const { const uint16_t soc = (hi << 8) | lo; _batteryCachedPercent = soc > 100 ? 100 : soc; _batteryLastPollMs = now; - _batteryI2cFailCount = 0; return _batteryCachedPercent; } static const BatteryMonitor battery = BatteryMonitor(BAT_GPIO0); diff --git a/lib/hal/HalPowerManager.h b/lib/hal/HalPowerManager.h index 5bebd6c31d..bf78623ca3 100644 --- a/lib/hal/HalPowerManager.h +++ b/lib/hal/HalPowerManager.h @@ -19,12 +19,9 @@ class HalPowerManager { bool isLowPower = false; // I2C fuel gauge configuration for X3 battery monitoring - bool _batteryUseI2C = false; - uint8_t _batteryI2cAddr = 0; - uint8_t _batterySocRegister = 0; - mutable int _batteryCachedPercent = 0; - mutable unsigned long _batteryLastPollMs = 0; - mutable uint8_t _batteryI2cFailCount = 0; + 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;