1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-23 08:06:13 +01:00

Update I2CManager.cpp

Report address 0x3d as (probably) OLED Display.
If an I2C probe for a device times out, assume that there's a bus problem on the MUX sub-bus, and skip the rest of the devices on that bus.  This reduces the impact of the long timeout on some Wire implementations.
This commit is contained in:
Neil McKechnie 2023-02-14 21:56:11 +00:00
parent f1f1be8ad9
commit 3292c93192

View File

@ -52,7 +52,7 @@ static const FSH * guessI2CDeviceType(uint8_t address) {
return F("GPIO Expander or LCD Display"); return F("GPIO Expander or LCD Display");
else if (address == 0x29) else if (address == 0x29)
return F("Time-of-flight sensor"); return F("Time-of-flight sensor");
else if (address >= 0x3c && address <= 0x3c) else if (address >= 0x3c && address <= 0x3d)
return F("OLED Display"); return F("OLED Display");
else if (address >= 0x48 && address <= 0x4f) else if (address >= 0x48 && address <= 0x4f)
return F("Analogue Inputs or PWM"); return F("Analogue Inputs or PWM");
@ -110,6 +110,8 @@ void I2CManagerClass::begin(void) {
// Enumerate all I2C devices that are connected via multiplexer, // Enumerate all I2C devices that are connected via multiplexer,
// i.e. that respond when only one multiplexer has one subBus enabled // i.e. that respond when only one multiplexer has one subBus enabled
// and the device doesn't respond when the mux subBus is disabled. // and the device doesn't respond when the mux subBus is disabled.
// If any probes time out, then assume that the subbus is dead and
// don't do any more on that subbus.
for (uint8_t muxNo=I2CMux_0; muxNo <= I2CMux_7; muxNo++) { for (uint8_t muxNo=I2CMux_0; muxNo <= I2CMux_7; muxNo++) {
uint8_t muxAddr = I2C_MUX_BASE_ADDRESS + muxNo; uint8_t muxAddr = I2C_MUX_BASE_ADDRESS + muxNo;
if (exists(muxAddr)) { if (exists(muxAddr)) {
@ -117,7 +119,8 @@ void I2CManagerClass::begin(void) {
for (uint8_t subBus=0; subBus<=SubBus_No; subBus++) { for (uint8_t subBus=0; subBus<=SubBus_No; subBus++) {
muxSelectSubBus({(I2CMux)muxNo, (I2CSubBus)subBus}); muxSelectSubBus({(I2CMux)muxNo, (I2CSubBus)subBus});
for (uint8_t addr=0x08; addr<0x78; addr++) { for (uint8_t addr=0x08; addr<0x78; addr++) {
if (exists(addr)) { uint8_t status = checkAddress(addr);
if (status == I2C_STATUS_OK) {
// De-select subbus // De-select subbus
muxSelectSubBus({(I2CMux)muxNo, SubBus_None}); muxSelectSubBus({(I2CMux)muxNo, SubBus_None});
if (!exists(addr)) { if (!exists(addr)) {
@ -129,11 +132,13 @@ void I2CManagerClass::begin(void) {
} }
// Re-select subbus // Re-select subbus
muxSelectSubBus({(I2CMux)muxNo, (I2CSubBus)subBus}); muxSelectSubBus({(I2CMux)muxNo, (I2CSubBus)subBus});
} else if (status == I2C_STATUS_TIMEOUT) {
// Bus stuck, skip to next one.
break;
} }
} }
} }
// Probe mux address again with SubBus_None to deselect all // Deselect all subBuses for this mux. Otherwise its devices will continue to
// subBuses for that mux. Otherwise its devices will continue to
// respond when other muxes are being probed. // respond when other muxes are being probed.
I2CManager.muxSelectSubBus({(I2CMux)muxNo, SubBus_None}); // Deselect Mux I2CManager.muxSelectSubBus({(I2CMux)muxNo, SubBus_None}); // Deselect Mux
} }
@ -251,7 +256,7 @@ const FSH *I2CManagerClass::getErrorMessage(uint8_t status) {
case I2C_STATUS_NEGATIVE_ACKNOWLEDGE: return F("No response from device (address NAK)"); case I2C_STATUS_NEGATIVE_ACKNOWLEDGE: return F("No response from device (address NAK)");
case I2C_STATUS_TRANSMIT_ERROR: return F("Transmit error (data NAK)"); case I2C_STATUS_TRANSMIT_ERROR: return F("Transmit error (data NAK)");
case I2C_STATUS_OTHER_TWI_ERROR: return F("Other Wire/TWI error"); case I2C_STATUS_OTHER_TWI_ERROR: return F("Other Wire/TWI error");
case I2C_STATUS_TIMEOUT: return F("Timeout"); case I2C_STATUS_TIMEOUT: return F("I2C bus timeout");
case I2C_STATUS_ARBITRATION_LOST: return F("Arbitration lost"); case I2C_STATUS_ARBITRATION_LOST: return F("Arbitration lost");
case I2C_STATUS_BUS_ERROR: return F("I2C bus error"); case I2C_STATUS_BUS_ERROR: return F("I2C bus error");
case I2C_STATUS_UNEXPECTED_ERROR: return F("Unexpected error"); case I2C_STATUS_UNEXPECTED_ERROR: return F("Unexpected error");