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

I2C overlap checks (working but messy)

Needs disgnostic clean and promotion of i2c address to IODevice.
This commit is contained in:
Asbelos 2022-06-14 17:21:11 +01:00
parent 10a0cfcccb
commit 08eaa8ddb7
9 changed files with 50 additions and 17 deletions

View File

@ -61,10 +61,14 @@ void IODevice::begin() {
// Allocates 32 pins 100-131 // Allocates 32 pins 100-131
PCA9685::create(100, 16, 0x40); PCA9685::create(100, 16, 0x40);
PCA9685::create(116, 16, 0x41); PCA9685::create(116, 16, 0x41);
PCA9685::create(132, 16, 0x41); // should fail
PCA9685::create(118, 4, 0x42); // should fail
// Predefine two MCP23017 module 0x20/0x21 // Predefine two MCP23017 module 0x20/0x21
// Allocates 32 pins 164-195 // Allocates 32 pins 164-195
MCP23017::create(164, 16, 0x20); MCP23017::create(164, 16, 0x20);
MCP23017::create(180, 16, 0x21); MCP23017::create(180, 16, 0x21);
MCP23017::create(196, 16, 0x40); // should fail
// Call the begin() methods of each configured device in turn // Call the begin() methods of each configured device in turn
for (IODevice *dev=_firstDevice; dev!=NULL; dev = dev->_nextDevice) { for (IODevice *dev=_firstDevice; dev!=NULL; dev = dev->_nextDevice) {
@ -275,14 +279,34 @@ IODevice *IODevice::findDevice(VPIN vpin) {
// Private helper function to check for vpin overlap. Run during setup only. // Private helper function to check for vpin overlap. Run during setup only.
// returns true if pins DONT overlap with existing device // returns true if pins DONT overlap with existing device
bool IODevice::checkNoOverlap(VPIN firstPin, uint8_t nPins) { bool IODevice::checkNoOverlap(VPIN firstPin, uint8_t nPins, uint8_t i2cAddress) {
for (VPIN testPin=firstPin; testPin< (firstPin+nPins); testPin++) DIAG(F("Check no overlap %d %d 0x%x"), firstPin,nPins,i2cAddress);
if (findDevice(testPin)) { VPIN lastPin=firstPin+nPins-1;
DIAG(F("WARNING HAL Pin %d overlap, re-definition of pins %d to %d ignored."), for (IODevice *dev = _firstDevice; dev != 0; dev = dev->_nextDevice) {
testPin, firstPin, firstPin+nPins);
// check for pin range overlaps (verbose but compiler will fix that)
VPIN firstDevPin=dev->_firstVpin;
VPIN lastDevPin=firstDevPin+dev->_nPins-1;
bool noOverlap= firstPin>lastDevPin || lastPin<firstDevPin;
if (!noOverlap) {
DIAG(F("WARNING HAL Overlap definition of pins %d to %d ignored."),
firstPin, lastPin);
return false; return false;
} }
return true;
// Check for overlapping I2C address
if (dev->_matchI2CAddress(i2cAddress)) {
DIAG(F("WARNING HAL Overlap. i2c Addr 0x%x ignored."),i2cAddress);
return false;
}
}
return true; // no overlaps... OK to go on with constructor
}
bool IODevice::_matchI2CAddress(uint8_t i2cAddress) {
// Overridden for I2c devices.
(void) i2cAddress;
return false;
} }
//================================================================================================================== //==================================================================================================================

View File

@ -228,8 +228,11 @@ protected:
// pin low if an input changes state. // pin low if an input changes state.
int16_t _gpioInterruptPin = -1; int16_t _gpioInterruptPin = -1;
// non-i2c hal drivers return false, i2c drivers override this in IO_GPIOBase
virtual bool _matchI2CAddress(uint8_t i2cAddress);
// Method to check if pins will overlap before creating new device. // Method to check if pins will overlap before creating new device.
static bool checkNoOverlap(VPIN firstPin, uint8_t nPins=1); static bool checkNoOverlap(VPIN firstPin, uint8_t nPins=1, uint8_t i2cAddress=0);
// Static support function for subclass creation // Static support function for subclass creation
static void addDevice(IODevice *newDevice); static void addDevice(IODevice *newDevice);
@ -242,7 +245,7 @@ private:
bool owns(VPIN vpin); bool owns(VPIN vpin);
// Method to find device handling Vpin // Method to find device handling Vpin
static IODevice *findDevice(VPIN vpin); static IODevice *findDevice(VPIN vpin);
uint8_t _I2CAddress;
IODevice *_nextDevice = 0; IODevice *_nextDevice = 0;
unsigned long _nextEntryTime; unsigned long _nextEntryTime;
static IODevice *_firstDevice; static IODevice *_firstDevice;
@ -284,7 +287,9 @@ private:
void updatePosition(uint8_t pin); void updatePosition(uint8_t pin);
void writeDevice(uint8_t pin, int value); void writeDevice(uint8_t pin, int value);
void _display() override; void _display() override;
virtual bool _matchI2CAddress(uint8_t i2caddress) override {
return i2caddress && i2caddress==_I2CAddress;
}
uint8_t _I2CAddress; // 0x40-0x43 possible uint8_t _I2CAddress; // 0x40-0x43 possible
struct ServoData { struct ServoData {

View File

@ -60,7 +60,7 @@
class ADS111x: public IODevice { class ADS111x: public IODevice {
public: public:
static void create(VPIN firstVpin, int nPins, uint8_t i2cAddress) { static void create(VPIN firstVpin, int nPins, uint8_t i2cAddress) {
if (checkNoOverlap(firstVpin,nPins)) new ADS111x(firstVpin, nPins, i2cAddress); if (checkNoOverlap(firstVpin,nPins,i2cAddress)) new ADS111x(firstVpin, nPins, i2cAddress);
} }
private: private:
ADS111x(VPIN firstVpin, int nPins, uint8_t i2cAddress) { ADS111x(VPIN firstVpin, int nPins, uint8_t i2cAddress) {

View File

@ -45,6 +45,10 @@ protected:
int _read(VPIN vpin) override; int _read(VPIN vpin) override;
void _display() override; void _display() override;
void _loop(unsigned long currentMicros) override; void _loop(unsigned long currentMicros) override;
virtual bool _matchI2CAddress(uint8_t i2cAddress) override {
DIAG(F("MatchI2c %x %x"), i2cAddress, _I2CAddress);
return (i2cAddress && i2cAddress==_I2CAddress);
}
// Data fields // Data fields
uint8_t _I2CAddress; uint8_t _I2CAddress;

View File

@ -25,7 +25,7 @@
class MCP23008 : public GPIOBase<uint8_t> { class MCP23008 : public GPIOBase<uint8_t> {
public: public:
static void create(VPIN firstVpin, uint8_t nPins, uint8_t I2CAddress, int interruptPin=-1) { static void create(VPIN firstVpin, uint8_t nPins, uint8_t I2CAddress, int interruptPin=-1) {
if (checkNoOverlap(firstVpin, nPins)) new MCP23008(firstVpin, nPins, I2CAddress, interruptPin); if (checkNoOverlap(firstVpin, nPins,I2CAddress)) new MCP23008(firstVpin, nPins, I2CAddress, interruptPin);
} }
private: private:

View File

@ -31,7 +31,7 @@
class MCP23017 : public GPIOBase<uint16_t> { class MCP23017 : public GPIOBase<uint16_t> {
public: public:
static void create(VPIN vpin, int nPins, uint8_t I2CAddress, int interruptPin=-1) { static void create(VPIN vpin, int nPins, uint8_t I2CAddress, int interruptPin=-1) {
if (checkNoOverlap(vpin, nPins)) new MCP23017(vpin, min(nPins,16), I2CAddress, interruptPin); if (checkNoOverlap(vpin, nPins, I2CAddress)) new MCP23017(vpin, min(nPins,16), I2CAddress, interruptPin);
} }
private: private:

View File

@ -39,7 +39,7 @@ static void writeRegister(byte address, byte reg, byte value);
// Create device driver instance. // Create device driver instance.
void PCA9685::create(VPIN firstVpin, int nPins, uint8_t I2CAddress) { void PCA9685::create(VPIN firstVpin, int nPins, uint8_t I2CAddress) {
if (checkNoOverlap(firstVpin, nPins)) new PCA9685(firstVpin, nPins, I2CAddress); if (checkNoOverlap(firstVpin, nPins,I2CAddress)) new PCA9685(firstVpin, nPins, I2CAddress);
} }
// Configure a port on the PCA9685. // Configure a port on the PCA9685.

View File

@ -43,7 +43,7 @@
class PCF8574 : public GPIOBase<uint8_t> { class PCF8574 : public GPIOBase<uint8_t> {
public: public:
static void create(VPIN firstVpin, uint8_t nPins, uint8_t I2CAddress, int interruptPin=-1) { static void create(VPIN firstVpin, uint8_t nPins, uint8_t I2CAddress, int interruptPin=-1) {
if (checkNoOverlap(firstVpin, nPins)) new PCF8574(firstVpin, nPins, I2CAddress, interruptPin); if (checkNoOverlap(firstVpin, nPins,I2CAddress)) new PCF8574(firstVpin, nPins, I2CAddress, interruptPin);
} }
private: private:

View File

@ -130,7 +130,7 @@ private:
public: public:
static void create(VPIN firstVpin, int nPins, uint8_t i2cAddress, uint16_t onThreshold, uint16_t offThreshold, VPIN xshutPin = VPIN_NONE) { static void create(VPIN firstVpin, int nPins, uint8_t i2cAddress, uint16_t onThreshold, uint16_t offThreshold, VPIN xshutPin = VPIN_NONE) {
if (checkNoOverlap(firstVpin, nPins)) new VL53L0X(firstVpin, nPins, i2cAddress, onThreshold, offThreshold, xshutPin); if (checkNoOverlap(firstVpin, nPins,i2cAddress)) new VL53L0X(firstVpin, nPins, i2cAddress, onThreshold, offThreshold, xshutPin);
} }
protected: protected: