1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-27 01:56:14 +01:00

Additional support for Extended I2C Addresses

This commit is contained in:
Neil McKechnie 2023-02-09 00:13:23 +00:00
parent a0f0b860eb
commit dd0ee8b50a
3 changed files with 85 additions and 4 deletions

View File

@ -95,7 +95,7 @@ void I2CManagerClass::begin(void) {
for (uint8_t addr=0x08; addr<0x78; addr++) { for (uint8_t addr=0x08; addr<0x78; addr++) {
if (exists(addr)) { if (exists(addr)) {
found = true; found = true;
DIAG(F("I2C Device found at x%x, %S?"), addr, guessI2CDeviceType(addr)); DIAG(F("I2C Device found at 0x%x, %S?"), addr, guessI2CDeviceType(addr));
} }
} }
@ -117,7 +117,7 @@ void I2CManagerClass::begin(void) {
// Device responds when subbus selected but not when // Device responds when subbus selected but not when
// subbus disabled - ergo it must be on subbus! // subbus disabled - ergo it must be on subbus!
found = true; found = true;
DIAG(F("I2C Device found at {I2CMux_%d,SubBus_%d,x%x}, %S?"), DIAG(F("I2C Device found at {I2CMux_%d,SubBus_%d,0x%x}, %S?"),
muxNo, subBus, addr, guessI2CDeviceType(addr)); muxNo, subBus, addr, guessI2CDeviceType(addr));
} }
// Re-select subbus // Re-select subbus
@ -266,6 +266,9 @@ I2CManagerClass I2CManager = I2CManagerClass();
// try, and failure from timeout does not get retried. // try, and failure from timeout does not get retried.
unsigned long I2CManagerClass::timeout = 100000UL; unsigned long I2CManagerClass::timeout = 100000UL;
// Buffer for conversion of I2CAddress to char*.
/* static */ char I2CAddress::addressBuffer[30];
#if defined(I2C_EXTENDED_ADDRESS) #if defined(I2C_EXTENDED_ADDRESS)
// Count of I2C multiplexers found when initialising. If there is only one // Count of I2C multiplexers found when initialising. If there is only one
// MUX then the subbus does not de-selecting after use; however, if there // MUX then the subbus does not de-selecting after use; however, if there

View File

@ -192,6 +192,7 @@ private:
I2CMux _muxNumber; I2CMux _muxNumber;
I2CSubBus _subBus; I2CSubBus _subBus;
uint8_t _deviceAddress; uint8_t _deviceAddress;
static char addressBuffer[];
public: public:
// Constructors // Constructors
// For I2CAddress "{Mux_0, SubBus_0, 0x23}" syntax. // For I2CAddress "{Mux_0, SubBus_0, 0x23}" syntax.
@ -228,6 +229,41 @@ public:
// (device assumed to be on the main I2C bus or on a currently selected subbus. // (device assumed to be on the main I2C bus or on a currently selected subbus.
operator uint8_t () const { return _deviceAddress; } operator uint8_t () const { return _deviceAddress; }
// Conversion from I2CAddress to char* (uses static storage so only
// one conversion can be done at a time). So don't call it twice in a
// single DIAG statement for example.
const char* toString() {
char *ptr = addressBuffer;
if (_muxNumber != I2CMux_None) {
strcpy_P(ptr, (const char*)F("{I2CMux_"));
ptr += 8;
*ptr++ = '0' + _muxNumber;
strcpy_P(ptr, (const char*)F(",Subbus_"));
ptr += 8;
if (_subBus == SubBus_None) {
strcpy_P(ptr, (const char*)F("None"));
ptr += 4;
} else if (_subBus == SubBus_All) {
strcpy_P(ptr, (const char*)F("All"));
ptr += 3;
} else
*ptr++ = '0' + _subBus;
*ptr++ = ',';
}
uint8_t temp = _deviceAddress;
*ptr++ = '0';
*ptr++ = 'x';
for (uint8_t index = 0; index<2; index++) {
uint8_t bits = (temp >> 4) & 0x0f;
*ptr++ = bits > 9 ? bits-10+'A' : bits+'0';
temp <<= 4;
}
if (_muxNumber != I2CMux_None)
*ptr++ = '}';
*ptr = 0; // terminate string
return addressBuffer;
}
// Comparison operator // Comparison operator
int operator == (I2CAddress &a) const { int operator == (I2CAddress &a) const {
if (_deviceAddress != a._deviceAddress) if (_deviceAddress != a._deviceAddress)
@ -249,8 +285,50 @@ public:
}; };
#else #else
struct I2CAddress {
private:
uint8_t _deviceAddress;
static char addressBuffer[];
public:
// Constructors
I2CAddress(const uint8_t deviceAddress) {
_deviceAddress = deviceAddress;
}
// Basic constructor
I2CAddress() : I2CAddress(0) {}
// Conversion operator from I2CAddress to uint8_t
// For "uint8_t address = i2cAddress;" syntax
operator uint8_t () const { return _deviceAddress; }
// Conversion from I2CAddress to char* (uses static storage so only
// one conversion can be done at a time). So don't call it twice in a
// single DIAG statement for example.
const char* toString () {
char *ptr = addressBuffer;
// Just display hex value, two digits.
uint8_t temp = _deviceAddress;
*ptr++ = '0';
*ptr++ = 'x';
for (uint8_t index = 0; index<2; index++) {
uint8_t bits = (temp >> 4) & 0xf;
*ptr++ = bits > 9 ? bits-10+'a' : bits+'0';
temp <<= 4;
}
*ptr = 0; // terminate string
return addressBuffer;
}
// Comparison operator
int operator == (I2CAddress &a) const {
if (_deviceAddress != a._deviceAddress)
return false; // Different device address so no match
return true; // Same address on same mux and same subbus
}
};
// Legacy single-byte I2C address type for compact code and smooth changeover. // Legacy single-byte I2C address type for compact code and smooth changeover.
typedef uint8_t I2CAddress; //typedef uint8_t I2CAddress;
#endif // I2C_EXTENDED_ADDRESS #endif // I2C_EXTENDED_ADDRESS

View File

@ -210,7 +210,7 @@ void I2CManagerClass::checkForTimeout() {
unsigned long elapsed = micros() - startTime; unsigned long elapsed = micros() - startTime;
if (elapsed > timeout) { if (elapsed > timeout) {
#ifdef DIAG_IO #ifdef DIAG_IO
//DIAG(F("I2CManager Timeout on x%x, I2CRB=x%x"), (int)t->i2cAddress, currentRequest); //DIAG(F("I2CManager Timeout on %s, I2CRB=%s"), t->i2cAddress.toString(), currentRequest);
#endif #endif
// Excessive time. Dequeue request // Excessive time. Dequeue request
queueHead = t->nextRequest; queueHead = t->nextRequest;