mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-19 01:41:30 +10:00
Add one wire i2c bridge support (#10078)
* First version of DS248X bridge * Add first iteration of DS248X sensor * Supports single readings on DS2484 * Supports readings on ch0 for DS2484_800 * Detection of variant for DS248X * Minor fix on retries for sensor init * Allow multiple channel detect passes on 8-ch version * Always read temperature via ROM matching * Small comment to show how to send all channels * Minor logging changes * Prevent one-wire double definitions * Detect ROMs per round * Fix comment * Prevent skipping on DS2482 ALT3 check * Fix comment (again) * Fix style checks * Remove comment for multiple measurements * Address CodeRabbit review findings on DS248X sensor Set _variant on every detectVariant path and branch on the member, so a failed variant probe retries instead of falling into single-channel init. Search DS2482-800 channels into a scratch buffer so a transient one-wire failure cannot erase a ROM found on an earlier pass, and count channels that already hold a ROM. Check every one-wire return value in readTemperatureROM, validate the scratchpad CRC, and return DS248X_INVALID_TEMPERATURE on failure so the existing sentinel checks reject failed reads instead of reporting stale or uninitialised data. * Probe IIS2MDCTR WHO_AM_I before the DS248X status check At HMC5883L_ADDR the DS248X probe reads 0xF0. On the IIS2MDCTR that sub-address sets auto-increment and targets 0x70, which is reserved and returns an unspecified value; any of bits 0x02, 0x04 or 0x10 makes the probe claim the magnetometer as a DS2482. Reading the WHO_AM_I at 0x4F first is deterministic for both parts. A DS2482 does not acknowledge 0x4F, an invalid command code, and leaves its read pointer untouched, so the subsequent read returns Status, Configuration, Channel Selection or Read Data. None of those can hold 0x40 at scan time, so the DS248X probe still runs and detects it. This also restores develop's detection order and matches the structure already used at BMA423_ADDR: specific ID match, then probe, then the generic fallback. * Read only the reported channel in getMetrics getMetrics walked all eight DS2482-800 channels, but only channel 0 is ever written into the measurement. Each populated channel costs a blocking 750ms conversion inside readTemperatureROM, so a fully wired bridge stalled telemetry for roughly 6s per cycle and discarded seven of the eight readings. Channels without a sensor were already cheap thanks to the isValidROM guard, so this only affects boards that actually use more than one channel, which is the reason to fit a DS2482-800 in the first place. Multi-channel reporting is handled separately in #10192; a note records that it should start the conversion on every channel before waiting, rather than reading each channel end to end. * Trim DS248X comments to one line each --------- Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
This commit is contained in:
co-authored by
Thomas Göttgens
parent
58657d484a
commit
8c0ef44b0b
@@ -412,8 +412,17 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
type = TDECKKB;
|
||||
}
|
||||
break;
|
||||
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address);
|
||||
|
||||
case BBQ10_KB_ADDR:
|
||||
// Check status register (0xF0) for DS284X status and one-wire reset
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xF0), 1);
|
||||
if (registerValue & 0x16) { // One-wire reset after power-on
|
||||
type = DS248X;
|
||||
logFoundDevice("DS2482-800", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
type = BBQ10KB;
|
||||
logFoundDevice("BB Q10", (uint8_t)addr.address);
|
||||
break;
|
||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address);
|
||||
#ifdef HAS_NCP5623
|
||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address);
|
||||
@@ -578,7 +587,6 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check register 0x07 for 0x0400 response to ID MCP9808 chip.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
|
||||
if (registerValue == 0x0400) {
|
||||
@@ -592,6 +600,14 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
|
||||
type = LIS3DH;
|
||||
logFoundDevice("LIS3DH", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check status register (0xF0) for DS284X status and one-wire reset
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xF0), 1);
|
||||
if (registerValue & 0x16) { // One-wire reset after power-on
|
||||
type = DS248X;
|
||||
logFoundDevice("DS248X", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -636,7 +652,27 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
}
|
||||
break;
|
||||
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB", (uint8_t)addr.address)
|
||||
SCAN_SIMPLE_CASE(QMC6310U_ADDR, QMC6310U, "QMC6310U", (uint8_t)addr.address)
|
||||
case DS248X_ADDR_ALT3:
|
||||
// Check status register (0xF0) for DS284X status and one-wire reset
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xF0), 1);
|
||||
if (registerValue & 0x16) { // One-wire reset after power-on
|
||||
type = DS248X;
|
||||
logFoundDevice("DS2482-800", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case QMC6310U_ADDR:
|
||||
// Check status register (0xF0) for DS284X status and one-wire reset
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xF0), 1);
|
||||
if (registerValue & 0x16) { // One-wire reset after power-on
|
||||
type = DS248X;
|
||||
logFoundDevice("DS2482-800", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
type = QMC6310U;
|
||||
logFoundDevice("QMC6310U", (uint8_t)addr.address);
|
||||
break;
|
||||
|
||||
case QMI8658_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0A), 1); // get ID
|
||||
@@ -666,16 +702,25 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
|
||||
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L", (uint8_t)addr.address)
|
||||
case HMC5883L_ADDR:
|
||||
// WHO_AM_I first: the DS248X probe below reads a reserved address on the IIS2MDCTR
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x4FU), 1); // get ID
|
||||
if (registerValue == 0x40) {
|
||||
type = IIS2MDCTR;
|
||||
logFoundDevice("IIS2MDCTR", (uint8_t)addr.address);
|
||||
break;
|
||||
} else {
|
||||
type = HMC5883L;
|
||||
logFoundDevice("HMC5883L", (uint8_t)addr.address);
|
||||
}
|
||||
|
||||
// Check status register (0xF0) for DS284X status and one-wire reset
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xF0), 1);
|
||||
if (registerValue & 0x16) { // One-wire reset after power-on
|
||||
type = DS248X;
|
||||
logFoundDevice("DS2482-800", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
|
||||
type = HMC5883L;
|
||||
logFoundDevice("HMC5883L", (uint8_t)addr.address);
|
||||
break;
|
||||
#ifdef HAS_QMA6100P
|
||||
SCAN_SIMPLE_CASE(QMA6100P_ADDR, QMA6100P, "QMA6100P", (uint8_t)addr.address)
|
||||
#else
|
||||
@@ -698,14 +743,25 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
|
||||
type = LIS3DH;
|
||||
logFoundDevice("LIS3DH", (uint8_t)addr.address);
|
||||
break;
|
||||
} else if ((registerValue & 0xFF00) == 0x1100) {
|
||||
// Silan SC7A20: LIS3DH register map, but answers 0x11 here.
|
||||
type = SC7A20;
|
||||
logFoundDevice("SC7A20", (uint8_t)addr.address);
|
||||
} else {
|
||||
type = BMA423;
|
||||
logFoundDevice("BMA423", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check status register (0xF0) for DS284X status and one-wire reset
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xF0), 1);
|
||||
if (registerValue & 0x16) { // One-wire reset after power-on
|
||||
type = DS248X;
|
||||
logFoundDevice("DS2482-800", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
|
||||
type = BMA423;
|
||||
logFoundDevice("BMA423", (uint8_t)addr.address);
|
||||
|
||||
break;
|
||||
case TCA9535_ADDR:
|
||||
case RAK120352_ADDR:
|
||||
@@ -753,11 +809,28 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address);
|
||||
case DFROBOT_RAIN_ADDR:
|
||||
// Check status register (0xF0) for DS284X status and one-wire reset
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xF0), 1);
|
||||
if (registerValue & 0x16) { // One-wire reset after power-on
|
||||
type = DS248X;
|
||||
logFoundDevice("DS2482-800", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
type = DFROBOT_RAIN;
|
||||
logFoundDevice("DFRobot Rain Gauge", (uint8_t)addr.address);
|
||||
break;
|
||||
SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(SCD30_ADDR, SCD30, "SCD30", (uint8_t)addr.address);
|
||||
case CST328_ADDR:
|
||||
// Check status register (0xF0) for DS284X status and one-wire reset
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xF0), 1);
|
||||
if (registerValue & 0x16) { // One-wire reset after power-on
|
||||
type = DS248X;
|
||||
logFoundDevice("DS2482-800", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
// Do we have the CST328 or the CST226SE,CST3530
|
||||
{
|
||||
// T-Deck pro V1.1 new touch panel use CST3530
|
||||
|
||||
Reference in New Issue
Block a user