Skip to content

Commit

Permalink
I2C Autodetection (OpenStickCommunity#1072)
Browse files Browse the repository at this point in the history
* Added beginning of webconfig-side I2C bus scanning.
Added experimental wrapper class for ADS1219 to handle device auto-detection.

* Added scanner to webconfig.

* Case sensitivity fix

* All current I2C addons except Display updated to do auto device detection rather than rely on I2C block options.
Added address range to ADS1219 addon to allow scanning across full range.

* Fixed I2C/USB peripheral configuration check to reject negative pin values.

* Added autodetection of I2C displays. This currently does not disable the usage of other devices on the same block.

* Deprecating I2C addon block and address fields.

* Remove deprecated Block and Address fields from Display and several Addons.

* Added exclusive mode for I2C peripherals to allow data-hungry devices like Display to take full control of the bus.

* Revert deprecatedi2cBlock to i2cBlock

* Reinstated deprecatedI2cBlock

* Reinstated usage of deprecatedI2cBlock
  • Loading branch information
mikepparks authored Jul 31, 2024
1 parent 9858d77 commit 3826b1b
Show file tree
Hide file tree
Showing 36 changed files with 365 additions and 305 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,10 @@ headers/configs
headers/drivers
headers/interfaces
headers/interfaces/i2c
headers/interfaces/i2c/ads1219
headers/interfaces/i2c/pcf8575
headers/interfaces/i2c/ssd1306
headers/interfaces/i2c/wiiextension
headers/gamepad
headers/display
headers/display/fonts
Expand Down
2 changes: 2 additions & 0 deletions headers/addons/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ class DisplayAddon : public GPAddon
DisplayMode currDisplayMode;
DisplayMode prevDisplayMode;
bool turnOffWhenSuspended;

GPGFX_DisplayTypeOptions gpOptions;
};

#endif
4 changes: 2 additions & 2 deletions headers/addons/i2canalog1219.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef _I2CAnalog_H
#define _I2CAnalog_H

#include <ADS1219.h>
#include "ads1219_dev.h"

#include "gpaddon.h"

Expand Down Expand Up @@ -47,7 +47,7 @@ class I2CAnalog1219Input : public GPAddon {
virtual void process(); // Analog Process
virtual std::string name() { return I2CAnalog1219Name; }
private:
ADS1219 * ads;
ADS1219Device * ads;
ADS_PINS pins;
int channelHop;
uint32_t uIntervalMS; // ADS1219 Interval
Expand Down
8 changes: 2 additions & 6 deletions headers/addons/wiiext.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "gamepad.h"
#include "storagemanager.h"
#include "peripheralmanager.h"
#include "WiiExtension.h"
#include "wiiextension_dev.h"

// WiiExtension Module Name
#define WiiExtensionName "WiiExtension"
Expand All @@ -22,10 +22,6 @@
#define WII_EXTENSION_ENABLED 0
#endif

#ifndef WII_EXTENSION_I2C_ADDR
#define WII_EXTENSION_I2C_ADDR 0x52
#endif

#ifndef WII_EXTENSION_I2C_SDA_PIN
#define WII_EXTENSION_I2C_SDA_PIN -1
#endif
Expand Down Expand Up @@ -90,7 +86,7 @@ class WiiExtensionInput : public GPAddon {
virtual void preprocess() {}
virtual std::string name() { return WiiExtensionName; }
private:
WiiExtension * wii;
WiiExtensionDevice * wii;
uint32_t uIntervalMS;
uint32_t nextTimer;

Expand Down
2 changes: 2 additions & 0 deletions headers/display/GPGFX.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class GPGFX {

void init(GPGFX_DisplayTypeOptions options);

GPGFX_DisplayTypeOptions getAvailableDisplay();

GPGFX_DisplayBase* getDriver() { return displayDriver; }

// drawing methods
Expand Down
5 changes: 3 additions & 2 deletions headers/display/GPGFX_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ typedef enum {
} GPGFX_DisplaySize;

typedef enum {
TYPE_NONE,
TYPE_SSD1306
DISPLAY_TYPE_NONE,
DISPLAY_TYPE_SSD1306,
DISPLAY_TYPE_COUNT
} GPGFX_DisplayType;

typedef struct {
Expand Down
20 changes: 20 additions & 0 deletions headers/interfaces/i2c/ads1219/ads1219_dev.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef _ADS1219DEVICE_H_
#define _ADS1219DEVICE_H_

#include <vector>

#include "i2cdevicebase.h"
#include "ADS1219.h"

class ADS1219Device : public ADS1219, public I2CDeviceBase {
public:
// Constructor
ADS1219Device() {}
ADS1219Device(PeripheralI2C *i2cController, uint8_t addr = 0x40) : ADS1219(i2cController, addr) {}

std::vector<uint8_t> getDeviceAddresses() const override {
return {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F};
}
};

#endif
15 changes: 13 additions & 2 deletions headers/interfaces/i2c/displaybase.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
#include <string.h>
#include "pico/stdlib.h"
#include "GPGFX_types.h"
#include "i2cdevicebase.h"

class GPGFX_DisplayBase {
class GPGFX_DisplayBase : public I2CDeviceBase {
public:
GPGFX_DisplayBase() {}
~GPGFX_DisplayBase() {}

virtual void init(GPGFX_DisplayTypeOptions options) {}

virtual void setPower(bool isPowered) {}
Expand All @@ -34,7 +38,14 @@ class GPGFX_DisplayBase {

void setMetrics(GPGFX_DisplayMetrics* metrics) { this->_metrics = metrics; }
GPGFX_DisplayMetrics* getMetrics() { return this->_metrics; }
protected:

std::vector<uint8_t> getDeviceAddresses() const override {
return {};
}

virtual bool isSPI() { return false; }
virtual bool isI2C() { return false; }
private:
GPGFX_DisplayMetrics* _metrics;
};

Expand Down
4 changes: 0 additions & 4 deletions headers/interfaces/i2c/i2cdevicebase.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ class I2CDeviceBase : public DeviceBase {
~I2CDeviceBase() {}

virtual std::vector<uint8_t> getDeviceAddresses() const = 0;

int8_t scanForDevice();
protected:
PeripheralI2C* i2c;
};

#endif
9 changes: 7 additions & 2 deletions headers/interfaces/i2c/pcf8575/pcf8575.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
class PCF8575 : public I2CDeviceBase {
public:
// Constructor
PCF8575() {}
PCF8575(PeripheralI2C *i2cController, uint8_t addr = 0x20) {
this->i2c = i2cController;
this->address = addr;
Expand All @@ -28,21 +29,25 @@ class PCF8575 : public I2CDeviceBase {
void reset();
//void start();

void setI2C(PeripheralI2C *i2cController) { this->i2c = i2cController; }
void setAddress(uint8_t addr) { this->address = addr; }

void send(uint16_t value);
uint16_t receive();

uint16_t pins() { return dataReceived; }

void setPin(uint8_t pinNumber, uint8_t value);
bool getPin(uint8_t pinNumber);
protected:
uint8_t address;
private:
const uint16_t initialValue = 0xFFFF;
uint8_t uc[128];

uint16_t dataSent;
uint16_t dataReceived = initialValue;
protected:
PeripheralI2C* i2c = nullptr;
uint8_t address = 0;
};

#endif
13 changes: 13 additions & 0 deletions headers/interfaces/i2c/ssd1306/obd_ssd1306.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

class GPGFX_OBD_SSD1306 : public GPGFX_DisplayBase {
public:
GPGFX_OBD_SSD1306() {}
~GPGFX_OBD_SSD1306() {}

void init(GPGFX_DisplayTypeOptions options);

void setPower(bool isPowered);
Expand All @@ -27,6 +30,13 @@ class GPGFX_OBD_SSD1306 : public GPGFX_DisplayBase {
void drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority);

void drawBuffer(uint8_t *pBuffer);

std::vector<uint8_t> getDeviceAddresses() const override {
return {0x3C, 0x3D};
}

bool isSPI() { return this->_isSPI; }
bool isI2C() { return this->_isI2C; }
private:
OBDISP obd;
GPGFX_DisplayTypeOptions _options;
Expand All @@ -36,6 +46,9 @@ class GPGFX_OBD_SSD1306 : public GPGFX_DisplayBase {
void clearScreen(int render);

uint8_t ucBackBuffer[1024];

bool _isSPI = false;
bool _isI2C = true;
};

#endif
12 changes: 12 additions & 0 deletions headers/interfaces/i2c/ssd1306/tiny_ssd1306.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

class GPGFX_TinySSD1306 : public GPGFX_DisplayBase {
public:
GPGFX_TinySSD1306() {}
~GPGFX_TinySSD1306() {}

void init(GPGFX_DisplayTypeOptions options);

void setPower(bool isPowered);
Expand All @@ -32,6 +35,13 @@ class GPGFX_TinySSD1306 : public GPGFX_DisplayBase {
void drawBuffer(uint8_t *pBuffer);

bool isSH1106(int detectedDisplay);

std::vector<uint8_t> getDeviceAddresses() const override {
return {0x3C, 0x3D};
}

bool isSPI() { return this->_isSPI; }
bool isI2C() { return this->_isI2C; }
private:
typedef enum {
SET_LOW_COLUMN = 0x00,
Expand Down Expand Up @@ -84,6 +94,8 @@ class GPGFX_TinySSD1306 : public GPGFX_DisplayBase {
uint8_t framePage = 0;

uint8_t screenType;
bool _isSPI = false;
bool _isI2C = true;
};

#endif
20 changes: 20 additions & 0 deletions headers/interfaces/i2c/wiiextension/wiiextension_dev.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef _WIIEXTDEVICE_H_
#define _WIIEXTDEVICE_H_

#include <vector>

#include "i2cdevicebase.h"
#include <WiiExtension.h>

class WiiExtensionDevice : public WiiExtension, public I2CDeviceBase {
public:
// Constructor
WiiExtensionDevice() {}
WiiExtensionDevice(PeripheralI2C *i2cController, uint8_t addr = WII_EXTENSION_I2C_ADDR) : WiiExtension(i2cController, addr) {}

std::vector<uint8_t> getDeviceAddresses() const override {
return {WII_EXTENSION_I2C_ADDR};
}
};

#endif
8 changes: 8 additions & 0 deletions headers/peripheralmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@
#include "peripheral_i2c.h"
#include "peripheral_spi.h"
#include "peripheral_usb.h"
#include "i2cdevicebase.h"

#define PMGR PeripheralManager::getInstance()

typedef struct {
int8_t address;
uint8_t block;
} PeripheralI2CScanResult;

class PeripheralManager {
public:
PeripheralManager(PeripheralManager const&) = delete;
Expand All @@ -28,6 +34,8 @@ class PeripheralManager {
bool isI2CEnabled(uint8_t block);
bool isSPIEnabled(uint8_t block);
bool isUSBEnabled(uint8_t block);

PeripheralI2CScanResult scanForI2CDevice(std::vector<uint8_t> addressList);
private:
PeripheralManager(){}

Expand Down
13 changes: 9 additions & 4 deletions lib/ADS1219/ADS1219.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ typedef enum{
class ADS1219 {
protected:
uint8_t address;
PeripheralI2C* i2c;
public:
// Constructor
ADS1219() {}
ADS1219(PeripheralI2C *i2cController, uint8_t addr = 0x40);

// Methods
Expand All @@ -97,14 +99,17 @@ class ADS1219 {
void setChannel(int channel);
void powerDown();
uint8_t readRegister(adsRegister_t reg);
void start();
void start();
uint32_t readConversionResult();

void setI2C(PeripheralI2C *i2cController) { this->i2c = i2cController; }
void setAddress(uint8_t addr) { this->address = addr; }

private:
void writeRegister(uint8_t data);

PeripheralI2C* i2c;
uint8_t config;
bool singleShot;
uint8_t config = 0x00;
bool singleShot = true;
int data_ready;
unsigned char uc[128];
};
Expand Down
30 changes: 28 additions & 2 deletions lib/PicoPeripherals/peripheral_i2c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ PeripheralI2C::PeripheralI2C() {
#endif
}

void PeripheralI2C::setConfig(uint8_t block, uint8_t sda, uint8_t scl, uint32_t speed) {
if (block < NUM_I2CS) {
void PeripheralI2C::setConfig(uint8_t block, int8_t sda, int8_t scl, uint32_t speed) {
if ((block < NUM_I2CS) && (sda > -1) && (scl > -1)) {
_I2C = _hardwareBlocks[block];
_SDA = sda;
_SCL = scl;
Expand Down Expand Up @@ -39,6 +39,8 @@ void PeripheralI2C::setup() {
}

int16_t PeripheralI2C::read(uint8_t address, uint8_t *data, uint16_t len, bool isBlock) {
if ((_exclusiveAddress > -1) && (_exclusiveAddress != address)) return -1;

int16_t result = i2c_read_blocking(_I2C, address, data, len, isBlock);
#ifdef DEBUG_PERIPHERALI2C
printf("PeripheralI2C::write %d:%d (blocking? %d)\n", address, len, isBlock);
Expand All @@ -52,6 +54,8 @@ int16_t PeripheralI2C::read(uint8_t address, uint8_t *data, uint16_t len, bool i
}

int16_t PeripheralI2C::readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len) {
if ((_exclusiveAddress > -1) && (_exclusiveAddress != address)) return -1;

int16_t registerCheck;
registerCheck = i2c_write_blocking(_I2C, address, &reg, 1, true);
if (registerCheck >= 0) {
Expand All @@ -61,6 +65,8 @@ int16_t PeripheralI2C::readRegister(uint8_t address, uint8_t reg, uint8_t *data,
}

int16_t PeripheralI2C::write(uint8_t address, uint8_t *data, uint16_t len, bool isBlock) {
if ((_exclusiveAddress > -1) && (_exclusiveAddress != address)) return -1;

#ifdef DEBUG_PERIPHERALI2C
printf("PeripheralI2C::write %d:%d (blocking? %d)\n", address, len, isBlock);
for (int i = 0; i < len; i++) {
Expand All @@ -84,4 +90,24 @@ uint8_t PeripheralI2C::test(uint8_t address) {
void PeripheralI2C::clear() {
// reset the bus
test(0xFF);
}

std::map<uint8_t,bool> PeripheralI2C::scan() {
std::map<uint8_t,bool> result;

for (uint8_t addr = 0; addr < (1 << 7); ++addr) {
int8_t ret;
uint8_t rxdata;
ret = i2c_read_blocking(_I2C, addr, &rxdata, 1, false);

if (ret >= 0) {
result.insert({addr,(ret >= 0)});
}
}

#ifdef DEBUG_PERIPHERALI2C
printf("%d\n", result.size());
#endif

return result;
}
Loading

0 comments on commit 3826b1b

Please sign in to comment.