diff --git a/Devices/lilygo-tdeck/Source/Init.cpp b/Devices/lilygo-tdeck/Source/Init.cpp index 6604afd33..b0635dbe5 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 ecb1f2264..a60e6ef77 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 a6a5a8163..363e0cc16 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 bd3475621..bb8ca682d 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/Source/devices/CardputerKeyboard.cpp b/Devices/m5stack-cardputer-adv/Source/devices/CardputerKeyboard.cpp index 01a1aa3bc..be1a4e625 100644 --- a/Devices/m5stack-cardputer-adv/Source/devices/CardputerKeyboard.cpp +++ b/Devices/m5stack-cardputer-adv/Source/devices/CardputerKeyboard.cpp @@ -1,5 +1,5 @@ #include "CardputerKeyboard.h" -#include +#include constexpr auto* TAG = "CardputerKeyb"; @@ -151,5 +151,5 @@ bool CardputerKeyboard::stopLvgl() { } bool CardputerKeyboard::isAttached() const { - return tt::hal::i2c::masterHasDeviceAtAddress(keypad->getPort(), keypad->getAddress(), 100); + return i2c_controller_has_device_at_address(keypad->getController(), keypad->getAddress(), 100) == ERROR_NONE; } diff --git a/Devices/m5stack-cardputer-adv/m5stack,cardputer-adv.dts b/Devices/m5stack-cardputer-adv/m5stack,cardputer-adv.dts index da1cb215e..1a3ba58d6 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 d30a7a65d..bb169c2dd 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 8140046f1..da54c9bd6 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 8092e39cd..28ecb1468 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 f188ccd92..3699455a5 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 53d9e30fc..1f231190f 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 cb80cb478..dd3d0ef11 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 d42c25d4c..4fdae9ce5 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 40dc11377..3efd322c2 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 ddcfe6d6b..4485b13ca 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 1b711dfb1..48c7e27b5 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 c1c70b2b7..e771d5c6f 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 aa3a60b6b..13fe31133 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 e43cf7b52..8f78252c2 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 19515e918..e6f63e5b0 100644 --- a/Drivers/AXP2101/Source/Axp2101.h +++ b/Drivers/AXP2101/Source/Axp2101.h @@ -19,7 +19,7 @@ class Axp2101 final : public tt::hal::i2c::I2cDevice { 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 fa016fede..ff69a6748 100644 --- a/Drivers/BQ24295/Source/Bq24295.h +++ b/Drivers/BQ24295/Source/Bq24295.h @@ -22,7 +22,7 @@ class Bq24295 final : public tt::hal::i2c::I2cDevice { 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 38fd702d7..0e85a5739 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 1e5ac6d85..6f9017d21 100644 --- a/Drivers/BQ27220/Source/Bq27220.h +++ b/Drivers/BQ27220/Source/Bq27220.h @@ -89,7 +89,7 @@ class Bq27220 final : public tt::hal::i2c::I2cDevice { 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 b7e85a1a7..596f1a41b 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 9bf93aa3e..11d265439 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 1ded5fda4..f737b3905 100644 --- a/Drivers/GT911/Source/Gt911Touch.h +++ b/Drivers/GT911/Source/Gt911Touch.h @@ -2,6 +2,7 @@ #include #include +#include #include #include diff --git a/Drivers/TCA8418/Source/Tca8418.h b/Drivers/TCA8418/Source/Tca8418.h index 9ef9b6dc7..a74688f50 100644 --- a/Drivers/TCA8418/Source/Tca8418.h +++ b/Drivers/TCA8418/Source/Tca8418.h @@ -45,7 +45,7 @@ class Tca8418 final : public tt::hal::i2c::I2cDevice { 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 new file mode 100644 index 000000000..11805e039 --- /dev/null +++ b/Platforms/platform-esp32/bindings/espressif,esp32-grove.yaml @@ -0,0 +1,29 @@ +description: ESP32 Grove Port + +compatible: "espressif,esp32-grove" + +properties: + defaultMode: + type: int + required: true + description: "One of enum Esp32GroveMode" + 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 + description: UART port number + i2cPort: + type: int + required: true + description: I2C port number + i2cClockFrequency: + type: int + required: true + description: I2C clock frequency diff --git a/Platforms/platform-esp32/include/tactility/bindings/esp32_grove.h b/Platforms/platform-esp32/include/tactility/bindings/esp32_grove.h new file mode 100644 index 000000000..8d71c6625 --- /dev/null +++ b/Platforms/platform-esp32/include/tactility/bindings/esp32_grove.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +DEFINE_DEVICETREE(esp32_grove, struct Esp32GroveConfig) + +#ifdef __cplusplus +} +#endif diff --git a/Platforms/platform-esp32/include/tactility/drivers/esp32_grove.h b/Platforms/platform-esp32/include/tactility/drivers/esp32_grove.h new file mode 100644 index 000000000..01a184516 --- /dev/null +++ b/Platforms/platform-esp32/include/tactility/drivers/esp32_grove.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct Esp32GroveConfig { + enum GroveMode defaultMode; + struct GpioPinSpec pinSdaRx; + struct GpioPinSpec pinSclTx; + uart_port_t uartPort; + i2c_port_t i2cPort; + uint32_t i2cClockFrequency; +}; + +#ifdef __cplusplus +} +#endif diff --git a/Platforms/platform-esp32/source/drivers/esp32_grove.cpp b/Platforms/platform-esp32/source/drivers/esp32_grove.cpp new file mode 100644 index 000000000..63cf5f12e --- /dev/null +++ b/Platforms/platform-esp32/source/drivers/esp32_grove.cpp @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: Apache-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TAG "esp32_grove" + +struct Esp32GroveInternal { + Device* child_device = nullptr; + void* child_config = nullptr; + char* child_name = nullptr; + GroveMode current_mode = GROVE_MODE_DISABLED; +}; + +#define GET_CONFIG(device) ((const struct Esp32GroveConfig*)device->config) +#define GET_DATA(device) ((struct Esp32GroveInternal*)device_get_driver_data(device)) + +extern "C" { + +static error_t stop_child(Device* device) { + auto* data = GET_DATA(device); + if (!data) return ERROR_NONE; + + if (data->child_device) { + if (data->child_device->internal) { + if (device_is_added(data->child_device)) { + if (device_is_ready(data->child_device)) { + if (device_stop(data->child_device) != ERROR_NONE) { + LOG_E(TAG, "%s: failed to stop child device", device->name); + return ERROR_RESOURCE; + } + } + if (device_remove(data->child_device) != ERROR_NONE) { + LOG_E(TAG, "%s: failed to remove child device", device->name); + return ERROR_RESOURCE; + } + } + check(device_destruct(data->child_device) == ERROR_NONE); + } + delete data->child_device; + data->child_device = nullptr; + } + + if (data->child_config) { + 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); + } + data->child_config = nullptr; + } + + delete[] data->child_name; + data->child_name = nullptr; + + data->current_mode = GROVE_MODE_DISABLED; + return ERROR_NONE; +} + +static error_t start_child(Device* device, GroveMode mode) { + const auto* config = GET_CONFIG(device); + auto* data = GET_DATA(device); + + if (mode == GROVE_MODE_DISABLED) { + LOG_I(TAG, "%s: Grove port disabled", device->name); + data->current_mode = GROVE_MODE_DISABLED; + return ERROR_NONE; + } + + data->child_device = new(std::nothrow) Device(); + if (!data->child_device) { + return ERROR_OUT_OF_MEMORY; + } + std::memset(data->child_device, 0, sizeof(Device)); + + size_t name_len = std::strlen(device->name) + 10; + data->child_name = new(std::nothrow) char[name_len]; + if (!data->child_name) { + delete data->child_device; + data->child_device = nullptr; + return ERROR_OUT_OF_MEMORY; + } + + 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; + data->child_name = nullptr; + delete data->child_device; + data->child_device = nullptr; + return ERROR_OUT_OF_MEMORY; + } + std::memset(uart_cfg, 0, sizeof(Esp32UartConfig)); + uart_cfg->port = config->uartPort; + uart_cfg->pin_tx = config->pinSclTx; + uart_cfg->pin_rx = config->pinSdaRx; + uart_cfg->pin_cts = GPIO_PIN_SPEC_NONE; + uart_cfg->pin_rts = GPIO_PIN_SPEC_NONE; + data->child_config = uart_cfg; + 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) { + // 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; + delete data->child_device; + data->child_device = nullptr; + return ERROR_OUT_OF_MEMORY; + } + 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-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); + 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; + } + + data->child_device->config = data->child_config; + + error_t err = device_construct_add_start(data->child_device, compatible); + if (err != ERROR_NONE) { + LOG_E(TAG, "%s: failed to start child device: %d", device->name, err); + stop_child(device); + return err; + } + + data->current_mode = mode; + return ERROR_NONE; +} + +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); + + return start_child(device, config->defaultMode); +} + +static error_t stop_device(Device* device) { + auto* data = GET_DATA(device); + if (!data) return ERROR_NONE; + + stop_child(device); + delete data; + device_set_driver_data(device, nullptr); + + return ERROR_NONE; +} + +static error_t esp32_grove_set_mode(Device* device, enum GroveMode mode) { + auto* data = GET_DATA(device); + if (data->current_mode == mode) return ERROR_NONE; + + error_t err = stop_child(device); + if (err != ERROR_NONE) return err; + + return start_child(device, mode); +} + +static error_t esp32_grove_get_mode(Device* device, enum GroveMode* mode) { + auto* data = GET_DATA(device); + *mode = data->current_mode; + return ERROR_NONE; +} + +static const GroveApi esp32_grove_api = { + .set_mode = esp32_grove_set_mode, + .get_mode = esp32_grove_get_mode +}; + +extern Module platform_esp32_module; + +Driver esp32_grove_driver = { + .name = "esp32_grove", + .compatible = (const char*[]) { "espressif,esp32-grove", nullptr }, + .start_device = start_device, + .stop_device = stop_device, + .api = &esp32_grove_api, + .device_type = &GROVE_TYPE, + .owner = &platform_esp32_module, + .internal = nullptr +}; + +} // extern "C" diff --git a/Platforms/platform-esp32/source/module.cpp b/Platforms/platform-esp32/source/module.cpp index 3ac65fbff..b6a3fc670 100644 --- a/Platforms/platform-esp32/source/module.cpp +++ b/Platforms/platform-esp32/source/module.cpp @@ -20,6 +20,7 @@ extern Driver esp32_sdmmc_driver; #endif extern Driver esp32_spi_driver; extern Driver esp32_uart_driver; +extern Driver esp32_grove_driver; #if defined(CONFIG_BT_NIMBLE_ENABLED) extern Driver esp32_bluetooth_driver; extern Driver esp32_ble_serial_driver; @@ -45,6 +46,7 @@ static error_t start() { #endif check(driver_construct_add(&esp32_spi_driver) == ERROR_NONE); check(driver_construct_add(&esp32_uart_driver) == ERROR_NONE); + check(driver_construct_add(&esp32_grove_driver) == ERROR_NONE); #if defined(CONFIG_BT_NIMBLE_ENABLED) check(driver_construct_add(&esp32_bluetooth_driver) == ERROR_NONE); check(driver_construct_add(&esp32_ble_serial_driver) == ERROR_NONE); @@ -84,6 +86,7 @@ static error_t stop() { #endif check(driver_remove_destruct(&esp32_spi_driver) == ERROR_NONE); check(driver_remove_destruct(&esp32_uart_driver) == ERROR_NONE); + check(driver_remove_destruct(&esp32_grove_driver) == ERROR_NONE); return ERROR_NONE; } diff --git a/Tactility/Include/Tactility/hal/i2c/I2cDevice.h b/Tactility/Include/Tactility/hal/i2c/I2cDevice.h index 0f7474faa..67b85195a 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 { @@ -10,12 +11,13 @@ namespace tt::hal::i2c { * It helps to read and write registers. * * All read and write calls are thread-safe. + * @deprecated Use the device API from the Kernel project */ 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 +38,11 @@ class I2cDevice : public Device { 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 a898468ae..21df444af 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 97ba2d01a..0329074a4 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 e728e01b3..5688da820 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 3cc440808..a59e455fa 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 new file mode 100644 index 000000000..37dfc2bed --- /dev/null +++ b/TactilityKernel/include/tactility/drivers/grove.h @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * @brief Grove Port modes + */ +enum GroveMode { + GROVE_MODE_DISABLED = 0, + GROVE_MODE_UART = 1, + GROVE_MODE_I2C = 2 +}; + +/** + * @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 { + /** + * @brief Sets the Grove port mode. + * @param[in] device the Grove device + * @param[in] mode the new mode + * @return ERROR_NONE on success + */ + error_t (*set_mode)(struct Device* device, enum GroveMode mode); + + /** + * @brief Gets the current Grove port mode. + * @param[in] device the Grove device + * @param[out] mode pointer to store the current mode + * @return ERROR_NONE on success + */ + error_t (*get_mode)(struct Device* device, enum GroveMode* mode); +}; + +/** + * @brief Sets the Grove port mode using the specified device. + */ +error_t grove_set_mode(struct Device* device, enum GroveMode mode); + +/** + * @brief Gets the current Grove port mode using the specified device. + */ +error_t grove_get_mode(struct Device* device, enum GroveMode* mode); + +extern const struct DeviceType GROVE_TYPE; + +#ifdef __cplusplus +} +#endif diff --git a/TactilityKernel/source/drivers/grove.cpp b/TactilityKernel/source/drivers/grove.cpp new file mode 100644 index 000000000..37c1cb796 --- /dev/null +++ b/TactilityKernel/source/drivers/grove.cpp @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +#include +#include + +#define GROVE_DRIVER_API(driver) ((struct GroveApi*)driver->api) + +extern "C" { + +error_t grove_set_mode(struct Device* device, enum GroveMode mode) { + const auto* driver = device_get_driver(device); + return GROVE_DRIVER_API(driver)->set_mode(device, mode); +} + +error_t grove_get_mode(struct Device* device, enum GroveMode* mode) { + const auto* driver = device_get_driver(device); + return GROVE_DRIVER_API(driver)->get_mode(device, mode); +} + +const struct DeviceType GROVE_TYPE { + .name = "grove" +}; + +}