From 133215664ca21fabe209f4eb51958951994507b9 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Sat, 13 Jun 2026 00:31:01 +0200 Subject: [PATCH] I2C updates --- Devices/lilygo-tdeck/Source/Init.cpp | 2 +- Devices/lilygo-tdeck/lilygo,tdeck.dts | 12 +--- .../Source/Configuration.cpp | 10 +-- .../Source/Configuration.cpp | 3 +- .../m5stack,cardputer-adv.dts | 23 +++---- .../m5stack-cardputer/m5stack,cardputer.dts | 23 +++---- .../m5stack-core2/Source/devices/Power.cpp | 3 +- Devices/m5stack-core2/m5stack,core2.dts | 23 +++---- Devices/m5stack-cores3/Source/InitBoot.cpp | 5 +- Devices/m5stack-cores3/m5stack,cores3.dts | 53 ++++++++-------- .../Source/Configuration.cpp | 2 +- .../m5stack-stackchan/m5stack,stackchan.dts | 62 ++++++++++--------- .../Source/devices/Power.cpp | 3 +- Devices/unphone/Source/InitBoot.cpp | 3 +- Drivers/AW9523/Source/Aw9523.h | 2 +- Drivers/AXP192/Include/Axp192.h | 3 +- Drivers/AXP192/Source/Axp192.cpp | 5 +- Drivers/AXP2101/Source/Axp2101.cpp | 2 +- Drivers/AXP2101/Source/Axp2101.h | 2 +- Drivers/BQ24295/Source/Bq24295.h | 2 +- Drivers/BQ25896/Source/Bq25896.h | 2 +- Drivers/BQ27220/Source/Bq27220.h | 2 +- Drivers/DRV2605/Source/Drv2605.cpp | 2 +- Drivers/DRV2605/Source/Drv2605.h | 2 +- Drivers/GT911/Source/Gt911Touch.h | 7 ++- Drivers/TCA8418/Source/Tca8418.h | 2 +- .../bindings/espressif,esp32-grove.yaml | 8 +-- .../include/tactility/drivers/esp32_grove.h | 2 +- .../source/drivers/esp32_grove.cpp | 42 ++++++++----- .../Include/Tactility/hal/i2c/I2cDevice.h | 7 ++- .../Tactility/app/i2cscanner/I2cHelpers.h | 4 +- .../Source/app/i2cscanner/I2cHelpers.cpp | 46 ++++++++------ .../Source/app/i2cscanner/I2cScanner.cpp | 48 +++++--------- Tactility/Source/hal/i2c/I2cDevice.cpp | 18 +++--- .../include/tactility/drivers/grove.h | 3 + 35 files changed, 216 insertions(+), 222 deletions(-) diff --git a/Devices/lilygo-tdeck/Source/Init.cpp b/Devices/lilygo-tdeck/Source/Init.cpp index 6604afd3..b0635dbe 100644 --- a/Devices/lilygo-tdeck/Source/Init.cpp +++ b/Devices/lilygo-tdeck/Source/Init.cpp @@ -58,7 +58,7 @@ bool initBoot() { std::vector gps_configurations; gps_service->getGpsConfigurations(gps_configurations); if (gps_configurations.empty()) { - if (gps_service->addGpsConfiguration(tt::hal::gps::GpsConfiguration {.uartName = "uart1", .baudRate = 38400, .model = tt::hal::gps::GpsModel::UBLOX10})) { + if (gps_service->addGpsConfiguration(tt::hal::gps::GpsConfiguration {.uartName = "uart0", .baudRate = 38400, .model = tt::hal::gps::GpsModel::UBLOX10})) { LOGGER.info("Configured internal GPS"); } else { LOGGER.error("Failed to configure internal GPS"); diff --git a/Devices/lilygo-tdeck/lilygo,tdeck.dts b/Devices/lilygo-tdeck/lilygo,tdeck.dts index ecb1f226..a60e6ef7 100644 --- a/Devices/lilygo-tdeck/lilygo,tdeck.dts +++ b/Devices/lilygo-tdeck/lilygo,tdeck.dts @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -30,15 +31,6 @@ pin-scl = <&gpio0 8 GPIO_FLAG_NONE>; }; - i2c_external: i2c1 { - compatible = "espressif,esp32-i2c"; - status = "disabled"; - port = ; - clock-frequency = <400000>; - pin-sda = <&gpio0 43 GPIO_FLAG_NONE>; - pin-scl = <&gpio0 44 GPIO_FLAG_NONE>; - }; - i2s0 { compatible = "espressif,esp32-i2s"; port = ; @@ -55,7 +47,7 @@ pin-sclk = <&gpio0 40 GPIO_FLAG_NONE>; }; - uart1 { + uart0 { compatible = "espressif,esp32-uart"; port = ; pin-tx = <&gpio0 43 GPIO_FLAG_NONE>; diff --git a/Devices/lilygo-tlora-pager/Source/Configuration.cpp b/Devices/lilygo-tlora-pager/Source/Configuration.cpp index a6a5a816..363e0cc1 100644 --- a/Devices/lilygo-tlora-pager/Source/Configuration.cpp +++ b/Devices/lilygo-tlora-pager/Source/Configuration.cpp @@ -4,6 +4,7 @@ #include "devices/TpagerKeyboard.h" #include "devices/TpagerPower.h" #include +#include #include #include @@ -14,17 +15,18 @@ bool tpagerInit(); using namespace tt::hal; static DeviceVector createDevices() { - auto bq27220 = std::make_shared(I2C_NUM_0); + auto* i2c = device_find_by_name("i2c0"); + auto bq27220 = std::make_shared(i2c); auto power = std::make_shared(bq27220); - auto tca8418 = std::make_shared(I2C_NUM_0); + auto tca8418 = std::make_shared(i2c); auto keyboard = std::make_shared(tca8418); return std::vector> { tca8418, - std::make_shared(I2C_NUM_0), + std::make_shared(i2c), bq27220, - std::make_shared(I2C_NUM_0), + std::make_shared(i2c), power, createTpagerSdCard(), createDisplay(), diff --git a/Devices/m5stack-cardputer-adv/Source/Configuration.cpp b/Devices/m5stack-cardputer-adv/Source/Configuration.cpp index bd347562..bb8ca682 100644 --- a/Devices/m5stack-cardputer-adv/Source/Configuration.cpp +++ b/Devices/m5stack-cardputer-adv/Source/Configuration.cpp @@ -4,6 +4,7 @@ #include "devices/CardputerPower.h" #include +#include #include #include @@ -16,7 +17,7 @@ static bool initBoot() { } static DeviceVector createDevices() { - auto tca8418 = std::make_shared(I2C_NUM_0); + auto tca8418 = std::make_shared(device_find_by_name("i2c_internal")); return { createSdCard(), createDisplay(), diff --git a/Devices/m5stack-cardputer-adv/m5stack,cardputer-adv.dts b/Devices/m5stack-cardputer-adv/m5stack,cardputer-adv.dts index da1cb215..1a3ba58d 100644 --- a/Devices/m5stack-cardputer-adv/m5stack,cardputer-adv.dts +++ b/Devices/m5stack-cardputer-adv/m5stack,cardputer-adv.dts @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -36,12 +37,14 @@ }; }; - i2c_port_a { - compatible = "espressif,esp32-i2c"; - port = ; - clock-frequency = <400000>; - pin-sda = <&gpio0 2 GPIO_FLAG_NONE>; - pin-scl = <&gpio0 1 GPIO_FLAG_NONE>; + port_a: grove0 { + compatible = "espressif,esp32-grove"; + defaultMode = ; + pinSdaRx = <&gpio0 2 GPIO_FLAG_NONE>; + pinSclTx = <&gpio0 1 GPIO_FLAG_NONE>; + uartPort = ; + i2cPort = ; + i2cClockFrequency = <400000>; }; display_spi: spi0 { @@ -68,12 +71,4 @@ pin-data-out = <&gpio0 42 GPIO_FLAG_NONE>; pin-data-in = <&gpio0 46 GPIO_FLAG_NONE>; }; - - uart_port_a: uart1 { - compatible = "espressif,esp32-uart"; - status = "disabled"; - port = ; - pin-tx = <&gpio0 1 GPIO_FLAG_NONE>; - pin-rx = <&gpio0 2 GPIO_FLAG_NONE>; - }; }; diff --git a/Devices/m5stack-cardputer/m5stack,cardputer.dts b/Devices/m5stack-cardputer/m5stack,cardputer.dts index d30a7a65..bb169c2d 100644 --- a/Devices/m5stack-cardputer/m5stack,cardputer.dts +++ b/Devices/m5stack-cardputer/m5stack,cardputer.dts @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -22,12 +23,14 @@ gpio-count = <49>; }; - i2c_port_a { - compatible = "espressif,esp32-i2c"; - port = ; - clock-frequency = <400000>; - pin-sda = <&gpio0 2 GPIO_FLAG_NONE>; - pin-scl = <&gpio0 1 GPIO_FLAG_NONE>; + port_a: grove0 { + compatible = "espressif,esp32-grove"; + defaultMode = ; + pinSdaRx = <&gpio0 2 GPIO_FLAG_NONE>; + pinSclTx = <&gpio0 1 GPIO_FLAG_NONE>; + uartPort = ; + i2cPort = ; + i2cClockFrequency = <400000>; }; display_spi: spi0 { @@ -55,12 +58,4 @@ pin-data-out = <&gpio0 42 GPIO_FLAG_NONE>; pin-data-in = <&gpio0 46 GPIO_FLAG_NONE>; }; - - uart_port_a: uart1 { - compatible = "espressif,esp32-uart"; - status = "disabled"; - port = ; - pin-tx = <&gpio0 1 GPIO_FLAG_NONE>; - pin-rx = <&gpio0 2 GPIO_FLAG_NONE>; - }; }; diff --git a/Devices/m5stack-core2/Source/devices/Power.cpp b/Devices/m5stack-core2/Source/devices/Power.cpp index 8140046f..da54c9bd 100644 --- a/Devices/m5stack-core2/Source/devices/Power.cpp +++ b/Devices/m5stack-core2/Source/devices/Power.cpp @@ -1,10 +1,11 @@ #include +#include static std::shared_ptr axp192 = nullptr; std::shared_ptr createAxp192() { assert(axp192 == nullptr); - auto configuration = std::make_unique(I2C_NUM_0); + auto configuration = std::make_unique(device_find_by_name("i2c_internal")); axp192 = std::make_shared(std::move(configuration)); return axp192; } diff --git a/Devices/m5stack-core2/m5stack,core2.dts b/Devices/m5stack-core2/m5stack,core2.dts index 8092e39c..28ecb146 100644 --- a/Devices/m5stack-core2/m5stack,core2.dts +++ b/Devices/m5stack-core2/m5stack,core2.dts @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -37,12 +38,14 @@ }; }; - i2c_port_a { - compatible = "espressif,esp32-i2c"; - port = ; - clock-frequency = <400000>; - pin-sda = <&gpio0 32 GPIO_FLAG_NONE>; - pin-scl = <&gpio0 33 GPIO_FLAG_NONE>; + port_a: grove0 { + compatible = "espressif,esp32-grove"; + defaultMode = ; + pinSdaRx = <&gpio0 32 GPIO_FLAG_NONE>; + pinSclTx = <&gpio0 33 GPIO_FLAG_NONE>; + uartPort = ; + i2cPort = ; + i2cClockFrequency = <400000>; }; spi0 { @@ -63,12 +66,4 @@ pin-data-out = <&gpio0 2 GPIO_FLAG_NONE>; pin-data-in = <&gpio0 34 GPIO_FLAG_NONE>; }; - - uart_port_a: uart1 { - compatible = "espressif,esp32-uart"; - status = "disabled"; - port = ; - pin-tx = <&gpio0 33 GPIO_FLAG_NONE>; - pin-rx = <&gpio0 32 GPIO_FLAG_NONE>; - }; }; diff --git a/Devices/m5stack-cores3/Source/InitBoot.cpp b/Devices/m5stack-cores3/Source/InitBoot.cpp index f188ccd9..3699455a 100644 --- a/Devices/m5stack-cores3/Source/InitBoot.cpp +++ b/Devices/m5stack-cores3/Source/InitBoot.cpp @@ -146,8 +146,9 @@ bool initPowerControl() { bool initBoot() { LOGGER.info("initBoot()"); - axp2101 = std::make_shared(I2C_NUM_0); - aw9523 = std::make_shared(I2C_NUM_0); + auto controller = device_find_by_name("i2c_internal"); + axp2101 = std::make_shared(controller); + aw9523 = std::make_shared(controller); return initPowerControl() && initGpioExpander(); } \ No newline at end of file diff --git a/Devices/m5stack-cores3/m5stack,cores3.dts b/Devices/m5stack-cores3/m5stack,cores3.dts index 53d9e30f..1f231190 100644 --- a/Devices/m5stack-cores3/m5stack,cores3.dts +++ b/Devices/m5stack-cores3/m5stack,cores3.dts @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -42,30 +43,34 @@ }; }; - i2c_port_a { - compatible = "espressif,esp32-i2c"; - port = ; - clock-frequency = <400000>; - pin-sda = <&gpio0 2 GPIO_FLAG_NONE>; - pin-scl = <&gpio0 1 GPIO_FLAG_NONE>; + port_a: grove0 { + compatible = "espressif,esp32-grove"; + defaultMode = ; + pinSdaRx = <&gpio0 2 GPIO_FLAG_NONE>; + pinSclTx = <&gpio0 1 GPIO_FLAG_NONE>; + uartPort = ; + i2cPort = ; + i2cClockFrequency = <400000>; }; - i2c_port_b { - compatible = "espressif,esp32-i2c"; - status = "disabled"; - port = ; - clock-frequency = <400000>; - pin-sda = <&gpio0 9 GPIO_FLAG_NONE>; - pin-scl = <&gpio0 8 GPIO_FLAG_NONE>; + port_b: grove1 { + compatible = "espressif,esp32-grove"; + defaultMode = ; + pinSdaRx = <&gpio0 9 GPIO_FLAG_NONE>; + pinSclTx = <&gpio0 8 GPIO_FLAG_NONE>; + uartPort = ; + i2cPort = ; + i2cClockFrequency = <400000>; }; - i2c_port_c { - compatible = "espressif,esp32-i2c"; - status = "disabled"; - port = ; - clock-frequency = <400000>; - pin-sda = <&gpio0 18 GPIO_FLAG_NONE>; - pin-scl = <&gpio0 17 GPIO_FLAG_NONE>; + port_c: grove2 { + compatible = "espressif,esp32-grove"; + defaultMode = ; + pinSdaRx = <&gpio0 17 GPIO_FLAG_NONE>; + pinSclTx = <&gpio0 18 GPIO_FLAG_NONE>; + uartPort = ; + i2cPort = ; + i2cClockFrequency = <400000>; }; spi0 { @@ -89,12 +94,4 @@ pin-data-in = <&gpio0 14 GPIO_FLAG_NONE>; pin-mclk = <&gpio0 0 GPIO_FLAG_NONE>; }; - - uart_port_a: uart1 { - compatible = "espressif,esp32-uart"; - status = "disabled"; - port = ; - pin-tx = <&gpio0 1 GPIO_FLAG_NONE>; - pin-rx = <&gpio0 2 GPIO_FLAG_NONE>; - }; }; diff --git a/Devices/m5stack-stackchan/Source/Configuration.cpp b/Devices/m5stack-stackchan/Source/Configuration.cpp index cb80cb47..dd3d0ef1 100644 --- a/Devices/m5stack-stackchan/Source/Configuration.cpp +++ b/Devices/m5stack-stackchan/Source/Configuration.cpp @@ -231,7 +231,7 @@ bool initBoot() { } // Keep Axp2101 C++ wrapper alive for Axp2101Power (backlight + battery) - axp2101 = std::make_shared(I2C_NUM_0); + axp2101 = std::make_shared(i2c); return true; } diff --git a/Devices/m5stack-stackchan/m5stack,stackchan.dts b/Devices/m5stack-stackchan/m5stack,stackchan.dts index d42c25d4..4fdae9ce 100644 --- a/Devices/m5stack-stackchan/m5stack,stackchan.dts +++ b/Devices/m5stack-stackchan/m5stack,stackchan.dts @@ -67,30 +67,43 @@ // TODO: BMM150 magnetometer @ 0x10 — accessible only via BMI270 aux I2C }; - i2c_port_a { - compatible = "espressif,esp32-i2c"; - port = ; - clock-frequency = <400000>; - pin-sda = <&gpio0 2 GPIO_FLAG_NONE>; - pin-scl = <&gpio0 1 GPIO_FLAG_NONE>; + // TODO: Servo UART (SCS9009, 1 Mbaud) — TX=GPIO6, RX=GPIO7 + uart_port_a: uart1 { + compatible = "espressif,esp32-uart"; + status = "disabled"; + port = ; + pin-tx = <&gpio0 6 GPIO_FLAG_NONE>; + pin-rx = <&gpio0 7 GPIO_FLAG_NONE>; }; - i2c_port_b { - compatible = "espressif,esp32-i2c"; - status = "disabled"; - port = ; - clock-frequency = <400000>; - pin-sda = <&gpio0 9 GPIO_FLAG_NONE>; - pin-scl = <&gpio0 8 GPIO_FLAG_NONE>; + port_a: grove0 { + compatible = "espressif,esp32-grove"; + defaultMode = ; + pinSdaRx = <&gpio0 2 GPIO_FLAG_NONE>; + pinSclTx = <&gpio0 1 GPIO_FLAG_NONE>; + uartPort = ; + i2cPort = ; + i2cClockFrequency = <400000>; }; - i2c_port_c { - compatible = "espressif,esp32-i2c"; - status = "disabled"; - port = ; - clock-frequency = <400000>; - pin-sda = <&gpio0 18 GPIO_FLAG_NONE>; - pin-scl = <&gpio0 17 GPIO_FLAG_NONE>; + port_b: grove1 { + compatible = "espressif,esp32-grove"; + defaultMode = ; + pinSdaRx = <&gpio0 9 GPIO_FLAG_NONE>; + pinSclTx = <&gpio0 8 GPIO_FLAG_NONE>; + uartPort = ; + i2cPort = ; + i2cClockFrequency = <400000>; + }; + + port_c: grove2 { + compatible = "espressif,esp32-grove"; + defaultMode = ; + pinSdaRx = <&gpio0 17 GPIO_FLAG_NONE>; + pinSclTx = <&gpio0 18 GPIO_FLAG_NONE>; + uartPort = ; + i2cPort = ; + i2cClockFrequency = <400000>; }; spi0 { @@ -111,13 +124,4 @@ pin-data-in = <&gpio0 14 GPIO_FLAG_NONE>; pin-mclk = <&gpio0 0 GPIO_FLAG_NONE>; }; - - // TODO: Servo UART (SCS9009, 1 Mbaud) — TX=GPIO6, RX=GPIO7 - uart_port_a: uart1 { - compatible = "espressif,esp32-uart"; - status = "disabled"; - port = ; - pin-tx = <&gpio0 1 GPIO_FLAG_NONE>; - pin-rx = <&gpio0 2 GPIO_FLAG_NONE>; - }; }; diff --git a/Devices/m5stack-stickc-plus/Source/devices/Power.cpp b/Devices/m5stack-stickc-plus/Source/devices/Power.cpp index 40dc1137..3efd322c 100644 --- a/Devices/m5stack-stickc-plus/Source/devices/Power.cpp +++ b/Devices/m5stack-stickc-plus/Source/devices/Power.cpp @@ -1,10 +1,11 @@ #include +#include static std::shared_ptr axp192 = nullptr; std::shared_ptr createAxp192() { assert(axp192 == nullptr); - auto configuration = std::make_unique(I2C_NUM_0); + auto configuration = std::make_unique(device_find_by_name("i2c_internal")); axp192 = std::make_shared(std::move(configuration)); return axp192; } diff --git a/Devices/unphone/Source/InitBoot.cpp b/Devices/unphone/Source/InitBoot.cpp index ddcfe6d6..4485b13c 100644 --- a/Devices/unphone/Source/InitBoot.cpp +++ b/Devices/unphone/Source/InitBoot.cpp @@ -1,4 +1,5 @@ #include "UnPhoneFeatures.h" +#include #include #include #include @@ -160,7 +161,7 @@ static bool unPhonePowerOn() { bootStats.printInfo(); bootStats.notifyBootStart(); - bq24295 = std::make_shared(I2C_NUM_0); + bq24295 = std::make_shared(device_find_by_name("i2c_internal")); unPhoneFeatures = std::make_shared(bq24295); diff --git a/Drivers/AW9523/Source/Aw9523.h b/Drivers/AW9523/Source/Aw9523.h index 1b711dfb..48c7e27b 100644 --- a/Drivers/AW9523/Source/Aw9523.h +++ b/Drivers/AW9523/Source/Aw9523.h @@ -8,7 +8,7 @@ class Aw9523 : public tt::hal::i2c::I2cDevice { public: - explicit Aw9523(i2c_port_t port) : I2cDevice(port, AW9523_ADDRESS) {} + explicit Aw9523(::Device* controller) : I2cDevice(controller, AW9523_ADDRESS) {} std::string getName() const final { return "AW9523"; } std::string getDescription() const final { return "GPIO expander with LED driver and I2C interface."; } diff --git a/Drivers/AXP192/Include/Axp192.h b/Drivers/AXP192/Include/Axp192.h index c1c70b2b..e771d5c6 100644 --- a/Drivers/AXP192/Include/Axp192.h +++ b/Drivers/AXP192/Include/Axp192.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -14,7 +15,7 @@ class Axp192 final : public tt::hal::power::PowerDevice { public: struct Configuration { - i2c_port_t port; + ::Device* controller; TickType_t readTimeout = 50 / portTICK_PERIOD_MS; TickType_t writeTimeout = 50 / portTICK_PERIOD_MS; }; diff --git a/Drivers/AXP192/Source/Axp192.cpp b/Drivers/AXP192/Source/Axp192.cpp index aa3a60b6..13fe3113 100644 --- a/Drivers/AXP192/Source/Axp192.cpp +++ b/Drivers/AXP192/Source/Axp192.cpp @@ -1,10 +1,11 @@ #include "Axp192.h" +#include constexpr auto TAG = "Axp192Power"; int32_t Axp192::i2cRead(void* handle, uint8_t address, uint8_t reg, uint8_t* buffer, uint16_t size) { const auto* device = static_cast(handle); - if (tt::hal::i2c::masterReadRegister(device->configuration->port, address, reg, buffer, size, device->configuration->readTimeout)) { + if (i2c_controller_read_register(device->configuration->controller, address, reg, buffer, size, device->configuration->readTimeout) == ERROR_NONE) { return AXP192_OK; } else { return 1; @@ -13,7 +14,7 @@ int32_t Axp192::i2cRead(void* handle, uint8_t address, uint8_t reg, uint8_t* buf int32_t Axp192::i2cWrite(void* handle, uint8_t address, uint8_t reg, const uint8_t* buffer, uint16_t size) { const auto* device = static_cast(handle); - if (tt::hal::i2c::masterWriteRegister(device->configuration->port, address, reg, buffer, size, device->configuration->writeTimeout)) { + if (i2c_controller_write_register(device->configuration->controller, address, reg, buffer, size, device->configuration->writeTimeout) == ERROR_NONE) { return AXP192_OK; } else { return 1; diff --git a/Drivers/AXP2101/Source/Axp2101.cpp b/Drivers/AXP2101/Source/Axp2101.cpp index e43cf7b5..8f78252c 100644 --- a/Drivers/AXP2101/Source/Axp2101.cpp +++ b/Drivers/AXP2101/Source/Axp2101.cpp @@ -54,5 +54,5 @@ bool Axp2101::getVBusVoltage(float& out) const { } bool Axp2101::setRegisters(uint8_t* bytePairs, size_t bytePairsSize) const { - return tt::hal::i2c::masterWriteRegisterArray(port, address, bytePairs, bytePairsSize, DEFAULT_TIMEOUT); + return i2c_controller_write_register_array(controller, address, bytePairs, bytePairsSize, DEFAULT_TIMEOUT) == ERROR_NONE; } diff --git a/Drivers/AXP2101/Source/Axp2101.h b/Drivers/AXP2101/Source/Axp2101.h index 19515e91..e6f63e5b 100644 --- a/Drivers/AXP2101/Source/Axp2101.h +++ b/Drivers/AXP2101/Source/Axp2101.h @@ -19,7 +19,7 @@ public: CHARGE_STATUS_STANDBY = 0b00 }; - explicit Axp2101(i2c_port_t port) : I2cDevice(port, AXP2101_ADDRESS) {} + explicit Axp2101(::Device* controller) : I2cDevice(controller, AXP2101_ADDRESS) {} std::string getName() const override { return "AXP2101"; } std::string getDescription() const override { return "Power management with I2C interface."; } diff --git a/Drivers/BQ24295/Source/Bq24295.h b/Drivers/BQ24295/Source/Bq24295.h index fa016fed..ff69a674 100644 --- a/Drivers/BQ24295/Source/Bq24295.h +++ b/Drivers/BQ24295/Source/Bq24295.h @@ -22,7 +22,7 @@ public: Enabled160s = 0b110000 }; - explicit Bq24295(i2c_port_t port) : I2cDevice(port, BQ24295_ADDRESS) {} + explicit Bq24295(::Device* controller) : I2cDevice(controller, BQ24295_ADDRESS) {} bool getWatchDogTimer(WatchDogTimer& out) const; bool setWatchDogTimer(WatchDogTimer in) const; diff --git a/Drivers/BQ25896/Source/Bq25896.h b/Drivers/BQ25896/Source/Bq25896.h index 38fd702d..0e85a573 100644 --- a/Drivers/BQ25896/Source/Bq25896.h +++ b/Drivers/BQ25896/Source/Bq25896.h @@ -8,7 +8,7 @@ class Bq25896 final : public tt::hal::i2c::I2cDevice { public: - explicit Bq25896(i2c_port_t port) : I2cDevice(port, BQ25896_ADDRESS) { + explicit Bq25896(::Device* controller) : I2cDevice(controller, BQ25896_ADDRESS) { powerOn(); } diff --git a/Drivers/BQ27220/Source/Bq27220.h b/Drivers/BQ27220/Source/Bq27220.h index 1e5ac6d8..6f9017d2 100644 --- a/Drivers/BQ27220/Source/Bq27220.h +++ b/Drivers/BQ27220/Source/Bq27220.h @@ -89,7 +89,7 @@ public: std::string getDescription() const override { return "I2C-controlled CEDV battery fuel gauge"; } - explicit Bq27220(i2c_port_t port) : I2cDevice(port, BQ27220_ADDRESS), accessKey(0xFFFFFFFF) {} + explicit Bq27220(::Device* controller) : I2cDevice(controller, BQ27220_ADDRESS), accessKey(0xFFFFFFFF) {} bool configureCapacity(uint16_t designCapacity, uint16_t fullChargeCapacity); bool getVoltage(uint16_t &value); diff --git a/Drivers/DRV2605/Source/Drv2605.cpp b/Drivers/DRV2605/Source/Drv2605.cpp index b7e85a1a..596f1a41 100644 --- a/Drivers/DRV2605/Source/Drv2605.cpp +++ b/Drivers/DRV2605/Source/Drv2605.cpp @@ -5,7 +5,7 @@ static const auto LOGGER = tt::Logger("DRV2605"); -Drv2605::Drv2605(i2c_port_t port, bool autoPlayStartupBuzz) : I2cDevice(port, ADDRESS), autoPlayStartupBuzz(autoPlayStartupBuzz) { +Drv2605::Drv2605(::Device* controller, bool autoPlayStartupBuzz) : I2cDevice(controller, ADDRESS), autoPlayStartupBuzz(autoPlayStartupBuzz) { check(init(), "Initialize DRV2605"); if (autoPlayStartupBuzz) { diff --git a/Drivers/DRV2605/Source/Drv2605.h b/Drivers/DRV2605/Source/Drv2605.h index 9bf93aa3..11d26543 100644 --- a/Drivers/DRV2605/Source/Drv2605.h +++ b/Drivers/DRV2605/Source/Drv2605.h @@ -62,7 +62,7 @@ class Drv2605 : public tt::hal::i2c::I2cDevice { public: - explicit Drv2605(i2c_port_t port, bool autoPlayStartupBuzz = true); + explicit Drv2605(::Device* controller, bool autoPlayStartupBuzz = true); std::string getName() const final { return "DRV2605"; } std::string getDescription() const final { return "Haptic driver for ERM/LRA with waveform library & auto-resonance tracking"; } diff --git a/Drivers/GT911/Source/Gt911Touch.h b/Drivers/GT911/Source/Gt911Touch.h index 1ded5fda..13fe4d41 100644 --- a/Drivers/GT911/Source/Gt911Touch.h +++ b/Drivers/GT911/Source/Gt911Touch.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -14,7 +15,7 @@ public: public: Configuration( - i2c_port_t port, + ::Device* controller, uint16_t xMax, uint16_t yMax, bool swapXy = false, @@ -24,7 +25,7 @@ public: gpio_num_t pinInterrupt = GPIO_NUM_NC, unsigned int pinResetLevel = 0, unsigned int pinInterruptLevel = 0 - ) : port(port), + ) : controller(controller), xMax(xMax), yMax(yMax), swapXy(swapXy), @@ -36,7 +37,7 @@ public: pinInterruptLevel(pinInterruptLevel) {} - i2c_port_t port; + ::Device* controller; uint16_t xMax; uint16_t yMax; bool swapXy; diff --git a/Drivers/TCA8418/Source/Tca8418.h b/Drivers/TCA8418/Source/Tca8418.h index 9ef9b6dc..a74688f5 100644 --- a/Drivers/TCA8418/Source/Tca8418.h +++ b/Drivers/TCA8418/Source/Tca8418.h @@ -45,7 +45,7 @@ public: std::string getDescription() const final { return "I2C-controlled keyboard scan IC"; } - explicit Tca8418(i2c_port_t port) : I2cDevice(port, TCA8418_ADDRESS) { + explicit Tca8418(::Device* controller) : I2cDevice(controller, TCA8418_ADDRESS) { delta_micros = 0; last_update_micros = 0; this_update_micros = 0; diff --git a/Platforms/platform-esp32/bindings/espressif,esp32-grove.yaml b/Platforms/platform-esp32/bindings/espressif,esp32-grove.yaml index 6a47d9ec..11805e03 100644 --- a/Platforms/platform-esp32/bindings/espressif,esp32-grove.yaml +++ b/Platforms/platform-esp32/bindings/espressif,esp32-grove.yaml @@ -7,14 +7,14 @@ properties: type: int required: true description: "One of enum Esp32GroveMode" - pinSclTx: - type: phandle-array - required: true - description: SCL (I2C) or TX (UART) pin pinSdaRx: type: phandle-array required: true description: SDA (I2C) or RX (UART) pin + pinSclTx: + type: phandle-array + required: true + description: SCL (I2C) or TX (UART) pin uartPort: type: int required: true diff --git a/Platforms/platform-esp32/include/tactility/drivers/esp32_grove.h b/Platforms/platform-esp32/include/tactility/drivers/esp32_grove.h index 073b2844..01a18451 100644 --- a/Platforms/platform-esp32/include/tactility/drivers/esp32_grove.h +++ b/Platforms/platform-esp32/include/tactility/drivers/esp32_grove.h @@ -12,8 +12,8 @@ extern "C" { struct Esp32GroveConfig { enum GroveMode defaultMode; - struct GpioPinSpec pinSclTx; struct GpioPinSpec pinSdaRx; + struct GpioPinSpec pinSclTx; uart_port_t uartPort; i2c_port_t i2cPort; uint32_t i2cClockFrequency; diff --git a/Platforms/platform-esp32/source/drivers/esp32_grove.cpp b/Platforms/platform-esp32/source/drivers/esp32_grove.cpp index c121b162..63cf5f12 100644 --- a/Platforms/platform-esp32/source/drivers/esp32_grove.cpp +++ b/Platforms/platform-esp32/source/drivers/esp32_grove.cpp @@ -1,16 +1,16 @@ // SPDX-License-Identifier: Apache-2.0 +#include #include #include #include - -#include "../../../../TactilityKernel/include/tactility/check.h" +#include +#include +#include +#include #include #include #include -#include -#include -#include #define TAG "esp32_grove" @@ -54,7 +54,7 @@ static error_t stop_child(Device* device) { if (data->current_mode == GROVE_MODE_UART) { delete static_cast(data->child_config); } else if (data->current_mode == GROVE_MODE_I2C) { - delete static_cast(data->child_config); + delete static_cast(data->child_config); } data->child_config = nullptr; } @@ -89,13 +89,15 @@ static error_t start_child(Device* device, GroveMode mode) { data->child_device = nullptr; return ERROR_OUT_OF_MEMORY; } - std::snprintf(data->child_name, name_len, "%s_child", device->name); - data->child_device->name = data->child_name; - data->child_device->parent = device; + data->child_device->parent = device; const char* compatible = nullptr; if (mode == GROVE_MODE_UART) { + // Device name + std::snprintf(data->child_name, name_len, "%s_uart", device->name); + data->child_device->name = data->child_name; + // Device config auto* uart_cfg = new(std::nothrow) struct Esp32UartConfig(); if (!uart_cfg) { delete[] data->child_name; @@ -114,7 +116,11 @@ static error_t start_child(Device* device, GroveMode mode) { compatible = "espressif,esp32-uart"; LOG_I(TAG, "%s: starting UART mode on port %d", device->name, (int)uart_cfg->port); } else if (mode == GROVE_MODE_I2C) { - auto* i2c_cfg = new(std::nothrow) struct Esp32I2cConfig(); + // Device name + std::snprintf(data->child_name, name_len, "%s_i2c", device->name); + data->child_device->name = data->child_name; + // Device config + auto* i2c_cfg = new (std::nothrow) struct Esp32I2cMasterConfig(); if (!i2c_cfg) { delete[] data->child_name; data->child_name = nullptr; @@ -122,18 +128,21 @@ static error_t start_child(Device* device, GroveMode mode) { data->child_device = nullptr; return ERROR_OUT_OF_MEMORY; } - std::memset(i2c_cfg, 0, sizeof(Esp32I2cConfig)); - i2c_cfg->port = config->i2cPort; + std::memset(i2c_cfg, 0, sizeof(Esp32I2cMasterConfig)); + i2c_cfg->port = static_cast(config->i2cPort); i2c_cfg->clockFrequency = config->i2cClockFrequency; i2c_cfg->pinSda = config->pinSdaRx; i2c_cfg->pinScl = config->pinSclTx; + i2c_cfg->clkSource = 0; // Default data->child_config = i2c_cfg; - compatible = "espressif,esp32-i2c"; - LOG_I(TAG, "%s: starting I2C mode on port %d", device->name, (int)i2c_cfg->port); + compatible = "espressif,esp32-i2c-master"; + LOG_I(TAG, "%s: starting I2C mode on port %d", device->name, (int)config->i2cPort); } else { LOG_E(TAG, "%s: unknown mode %d", device->name, mode); - delete[] data->child_name; - data->child_name = nullptr; + if (data->child_name != nullptr) { + delete[] data->child_name; + data->child_name = nullptr; + } delete data->child_device; data->child_device = nullptr; return ERROR_INVALID_ARGUMENT; @@ -154,6 +163,7 @@ static error_t start_child(Device* device, GroveMode mode) { static error_t start_device(Device* device) { const auto* config = GET_CONFIG(device); + auto* data = new(std::nothrow) Esp32GroveInternal(); if (!data) return ERROR_OUT_OF_MEMORY; device_set_driver_data(device, data); diff --git a/Tactility/Include/Tactility/hal/i2c/I2cDevice.h b/Tactility/Include/Tactility/hal/i2c/I2cDevice.h index 0f7474fa..c3512eb1 100644 --- a/Tactility/Include/Tactility/hal/i2c/I2cDevice.h +++ b/Tactility/Include/Tactility/hal/i2c/I2cDevice.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "I2c.h" namespace tt::hal::i2c { @@ -15,7 +16,7 @@ class I2cDevice : public Device { protected: - i2c_port_t port; + ::Device* controller; uint8_t address; static constexpr TickType_t DEFAULT_TIMEOUT = 1000 / portTICK_PERIOD_MS; @@ -36,11 +37,11 @@ protected: public: - explicit I2cDevice(i2c_port_t port, uint32_t address) : port(port), address(address) {} + explicit I2cDevice(::Device* controller, uint32_t address) : controller(controller), address(address) {} Type getType() const override { return Type::I2c; } - i2c_port_t getPort() const { return port; } + ::Device* getController() const { return controller; } uint8_t getAddress() const { return address; } }; diff --git a/Tactility/Private/Tactility/app/i2cscanner/I2cHelpers.h b/Tactility/Private/Tactility/app/i2cscanner/I2cHelpers.h index a898468a..21df444a 100644 --- a/Tactility/Private/Tactility/app/i2cscanner/I2cHelpers.h +++ b/Tactility/Private/Tactility/app/i2cscanner/I2cHelpers.h @@ -3,12 +3,14 @@ #include #include +struct Device; + namespace tt::app::i2cscanner { std::string getAddressText(uint8_t address); std::string getPortNamesForDropdown(); -bool getActivePortAtIndex(int32_t index, int32_t& out); +bool getActivePortAtIndex(int32_t index, struct Device** out); } diff --git a/Tactility/Source/app/i2cscanner/I2cHelpers.cpp b/Tactility/Source/app/i2cscanner/I2cHelpers.cpp index 97ba2d01..0329074a 100644 --- a/Tactility/Source/app/i2cscanner/I2cHelpers.cpp +++ b/Tactility/Source/app/i2cscanner/I2cHelpers.cpp @@ -1,7 +1,8 @@ #include "Tactility/app/i2cscanner/I2cHelpers.h" #include -#include + +#include #include #include @@ -19,31 +20,36 @@ std::string getAddressText(uint8_t address) { std::string getPortNamesForDropdown() { std::vector config_names; - for (int port = 0; port < I2C_NUM_MAX; ++port) { - auto native_port = static_cast(port); - if (hal::i2c::isStarted(native_port)) { - auto* name = hal::i2c::getName(native_port); - if (name != nullptr) { - config_names.push_back(name); - } + device_for_each_of_type(&I2C_CONTROLLER_TYPE, &config_names, [](auto* device, auto* context) { + auto* names = static_cast*>(context); + if (device_is_ready(device)) { + names->push_back(device->name); } - } + return true; + }); return string::join(config_names, "\n"); } -bool getActivePortAtIndex(int32_t index, int32_t& out) { - int current_index = -1; - for (int port = 0; port < I2C_NUM_MAX; ++port) { - auto native_port = static_cast(port); - if (hal::i2c::isStarted(native_port)) { - current_index++; - if (current_index == index) { - out = port; - return true; +bool getActivePortAtIndex(int32_t index, struct Device** out) { + struct Context { + int32_t targetIndex; + int32_t currentIndex; + struct Device* foundDevice; + } context = { index, 0, nullptr }; + + device_for_each_of_type(&I2C_CONTROLLER_TYPE, &context, [](auto* device, auto* ctx) { + auto* c = static_cast(ctx); + if (device_is_ready(device)) { + if (c->currentIndex == c->targetIndex) { + c->foundDevice = device; + return false; } + c->currentIndex++; } - } - return false; + return true; + }); + *out = context.foundDevice; + return context.foundDevice != nullptr; } } diff --git a/Tactility/Source/app/i2cscanner/I2cScanner.cpp b/Tactility/Source/app/i2cscanner/I2cScanner.cpp index e728e01b..5688da82 100644 --- a/Tactility/Source/app/i2cscanner/I2cScanner.cpp +++ b/Tactility/Source/app/i2cscanner/I2cScanner.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ class I2cScannerApp final : public App { std::unique_ptr scanTimer = nullptr; // State ScanState scanState = ScanStateInitial; - i2c_port_t port = I2C_NUM_0; + struct Device* portDevice = nullptr; std::vector scannedAddresses; // Widgets lv_obj_t* scanButtonLabelWidget = nullptr; @@ -54,7 +54,7 @@ class I2cScannerApp final : public App { void onScanTimer(); bool shouldStopScanTimer(); - bool getPort(i2c_port_t* outPort); + bool getPort(struct Device** outPort); bool addAddressToList(uint8_t address); bool hasScanThread(); void startScanning(); @@ -140,8 +140,10 @@ void I2cScannerApp::onShow(AppContext& app, lv_obj_t* parent) { lv_obj_add_flag(scan_list, LV_OBJ_FLAG_HIDDEN); scanListWidget = scan_list; - int32_t first_port; - if (getActivePortAtIndex(0, first_port)) { + struct Device* dummy; + if (getActivePortAtIndex(selected_bus, &dummy)) { + selectBus(selected_bus); + } else if (getActivePortAtIndex(0, &dummy)) { lv_dropdown_set_selected(port_dropdown, 0); selectBus(0); } @@ -184,9 +186,9 @@ void I2cScannerApp::onPressScanCallback(lv_event_t* event) { // endregion Callbacks -bool I2cScannerApp::getPort(i2c_port_t* outPort) { +bool I2cScannerApp::getPort(struct Device** outPort) { if (mutex.lock(100 / portTICK_PERIOD_MS)) { - *outPort = this->port; + *outPort = this->portDevice; mutex.unlock(); return true; } else { @@ -219,21 +221,21 @@ bool I2cScannerApp::shouldStopScanTimer() { void I2cScannerApp::onScanTimer() { logger.info("Scan thread started"); - i2c_port_t safe_port; + struct Device* safe_port; if (!getPort(&safe_port)) { logger.error("Failed to get I2C port"); onScanTimerFinished(); return; } - if (!hal::i2c::isStarted(safe_port)) { + if (!device_is_ready(safe_port)) { logger.error("I2C port not started"); onScanTimerFinished(); return; } for (uint8_t address = 0; address < 128; ++address) { - if (hal::i2c::masterHasDeviceAtAddress(safe_port, address, 10 / portTICK_PERIOD_MS)) { + if (i2c_controller_has_device_at_address(safe_port, address, 10 / portTICK_PERIOD_MS) == ERROR_NONE) { logger.info("Found device at address 0x{:02X}", address); if (!shouldStopScanTimer()) { addAddressToList(address); @@ -305,14 +307,14 @@ void I2cScannerApp::onSelectBus(lv_event_t* event) { } void I2cScannerApp::selectBus(int32_t selected) { - int32_t found_port; - if (!getActivePortAtIndex(selected, found_port)) { + struct Device* found_device; + if (!getActivePortAtIndex(selected, &found_device)) { return; } if (mutex.lock(100 / portTICK_PERIOD_MS)) { scannedAddresses.clear(); - port = static_cast(found_port); + portDevice = found_device; scanState = ScanStateInitial; mutex.unlock(); } @@ -334,16 +336,6 @@ void I2cScannerApp::onPressScan(lv_event_t* event) { updateViews(); } -static bool findDeviceName(const std::vector>& devices, i2c_port_t port, uint8_t address, std::string& outName) { - for (auto& device : devices) { - if (device->getPort() == port && device->getAddress() == address) { - outName = device->getName(); - return true; - } - } - return false; -} - void I2cScannerApp::updateViews() { if (mutex.lock(100 / portTICK_PERIOD_MS)) { if (scanState == ScanStateScanning) { @@ -358,18 +350,10 @@ void I2cScannerApp::updateViews() { if (scanState == ScanStateStopped) { lv_obj_remove_flag(scanListWidget, LV_OBJ_FLAG_HIDDEN); - auto devices = hal::findDevices(hal::Device::Type::I2c); - if (!scannedAddresses.empty()) { for (auto address: scannedAddresses) { std::string address_text = getAddressText(address); - std::string device_name; - if (findDeviceName(devices, port, address, device_name)) { - auto text = std::format("{} - {}", address_text, device_name); - lv_list_add_text(scanListWidget, text.c_str()); - } else { - lv_list_add_text(scanListWidget, address_text.c_str()); - } + lv_list_add_text(scanListWidget, address_text.c_str()); } } else { lv_list_add_text(scanListWidget, "No devices found"); diff --git a/Tactility/Source/hal/i2c/I2cDevice.cpp b/Tactility/Source/hal/i2c/I2cDevice.cpp index 3cc44080..a59e455f 100644 --- a/Tactility/Source/hal/i2c/I2cDevice.cpp +++ b/Tactility/Source/hal/i2c/I2cDevice.cpp @@ -5,24 +5,24 @@ namespace tt::hal::i2c { bool I2cDevice::read(uint8_t* data, size_t dataSize, TickType_t timeout) { - return masterRead(port, address, data, dataSize, timeout); + return i2c_controller_read(controller, address, data, dataSize, timeout) == ERROR_NONE; } bool I2cDevice::write(const uint8_t* data, uint16_t dataSize, TickType_t timeout) { - return masterWrite(port, address, data, dataSize, timeout); + return i2c_controller_write(controller, address, data, dataSize, timeout) == ERROR_NONE; } bool I2cDevice::writeRead(const uint8_t* writeData, size_t writeDataSize, uint8_t* readData, size_t readDataSize, TickType_t timeout) { - return masterWriteRead(port, address, writeData, writeDataSize, readData, readDataSize, timeout); + return i2c_controller_write_read(controller, address, writeData, writeDataSize, readData, readDataSize, timeout) == ERROR_NONE; } bool I2cDevice::writeRegister(uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { - return masterWriteRegister(port, address, reg, data, dataSize, timeout); + return i2c_controller_write_register(controller, address, reg, data, dataSize, timeout) == ERROR_NONE; } bool I2cDevice::readRegister12(uint8_t reg, float& out) const { std::uint8_t data[2] = {0}; - if (masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT)) { + if (i2c_controller_read_register(controller, address, reg, data, 2, DEFAULT_TIMEOUT) == ERROR_NONE) { out = (data[0] & 0x0F) << 8 | data[1]; return true; } else { @@ -32,7 +32,7 @@ bool I2cDevice::readRegister12(uint8_t reg, float& out) const { bool I2cDevice::readRegister14(uint8_t reg, float& out) const { std::uint8_t data[2] = {0}; - if (masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT)) { + if (i2c_controller_read_register(controller, address, reg, data, 2, DEFAULT_TIMEOUT) == ERROR_NONE) { out = (data[0] & 0x3F) << 8 | data[1]; return true; } else { @@ -42,7 +42,7 @@ bool I2cDevice::readRegister14(uint8_t reg, float& out) const { bool I2cDevice::readRegister16(uint8_t reg, uint16_t& out) const { std::uint8_t data[2] = {0}; - if (masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT)) { + if (i2c_controller_read_register(controller, address, reg, data, 2, DEFAULT_TIMEOUT) == ERROR_NONE) { out = data[0] << 8 | data[1]; return true; } else { @@ -51,11 +51,11 @@ bool I2cDevice::readRegister16(uint8_t reg, uint16_t& out) const { } bool I2cDevice::readRegister8(uint8_t reg, uint8_t& result) const { - return masterWriteRead(port, address, ®, 1, &result, 1, DEFAULT_TIMEOUT); + return i2c_controller_write_read(controller, address, ®, 1, &result, 1, DEFAULT_TIMEOUT) == ERROR_NONE; } bool I2cDevice::writeRegister8(uint8_t reg, uint8_t value) const { - return masterWriteRegister(port, address, reg, &value, 1, DEFAULT_TIMEOUT); + return i2c_controller_write_register(controller, address, reg, &value, 1, DEFAULT_TIMEOUT) == ERROR_NONE; } bool I2cDevice::bitOn(uint8_t reg, uint8_t bitmask) const { diff --git a/TactilityKernel/include/tactility/drivers/grove.h b/TactilityKernel/include/tactility/drivers/grove.h index 0e4f41fd..37dfc2be 100644 --- a/TactilityKernel/include/tactility/drivers/grove.h +++ b/TactilityKernel/include/tactility/drivers/grove.h @@ -19,6 +19,9 @@ enum GroveMode { /** * @brief API for Grove drivers. + * + * The grove driver is meant for external interfaces with two wires that can be used as UART, I2C or GPIO as needed. + * It can be used with the Grove connector, but also with others such as Stemma QT. */ struct GroveApi { /**