diff --git a/Devices/m5stack-tab5/Source/Configuration.cpp b/Devices/m5stack-tab5/Source/Configuration.cpp index 6de4c518..4ce59117 100644 --- a/Devices/m5stack-tab5/Source/Configuration.cpp +++ b/Devices/m5stack-tab5/Source/Configuration.cpp @@ -2,12 +2,14 @@ #include "devices/SdCard.h" #include +#include + #include #include using namespace tt::hal; -static const auto LOGGER = tt::Logger("Tab5"); +static constexpr auto* TAG = "Tab5"; static DeviceVector createDevices() { return { @@ -16,7 +18,7 @@ static DeviceVector createDevices() { }; } -static bool initBoot() { +static error_t initPower(::Device* i2c_controller) { /* PI4IOE5V6408-1 (0x43) - Bit 0: RF internal/external switch @@ -63,26 +65,106 @@ static bool initBoot() { }; constexpr auto IO_EXPANDER1_ADDRESS = 0x43; - if (!i2c::masterWriteRegisterArray(I2C_NUM_0, IO_EXPANDER1_ADDRESS, reg_data_io1_1, sizeof(reg_data_io1_1))) { - LOGGER.error("IO expander 1 init failed in phase 1"); - return false; + auto error = i2c_controller_write_register_array(i2c_controller, IO_EXPANDER1_ADDRESS, reg_data_io1_1, sizeof(reg_data_io1_1), pdMS_TO_TICKS(100)); + if (error != ERROR_NONE) { + LOG_E(TAG, "IO expander 1 init failed in phase 1"); + return ERROR_UNDEFINED; } constexpr auto IO_EXPANDER2_ADDRESS = 0x44; - if (!i2c::masterWriteRegisterArray(I2C_NUM_0, IO_EXPANDER2_ADDRESS, reg_data_io2, sizeof(reg_data_io2))) { - LOGGER.error("IO expander 2 init failed"); - return false; + error = i2c_controller_write_register_array(i2c_controller, IO_EXPANDER2_ADDRESS, reg_data_io2, sizeof(reg_data_io2), pdMS_TO_TICKS(100)); + if (error != ERROR_NONE) { + LOG_E(TAG, "IO expander 2 init failed"); + return ERROR_UNDEFINED; } // The M5Stack code applies this, but it's not known why // TODO: Remove and test it extensively tt::kernel::delayTicks(10); - if (!i2c::masterWriteRegisterArray(I2C_NUM_0, IO_EXPANDER1_ADDRESS, reg_data_io1_2, sizeof(reg_data_io1_2))) { - LOGGER.error("IO expander 1 init failed in phase 2"); + error = i2c_controller_write_register_array(i2c_controller, IO_EXPANDER1_ADDRESS, reg_data_io1_2, sizeof(reg_data_io1_2), pdMS_TO_TICKS(100)); + if (error != ERROR_NONE) { + LOG_E(TAG, "IO expander 1 init failed in phase 2"); + return ERROR_UNDEFINED; + } + + return ERROR_NONE; +} + +static error_t initSound(::Device* i2c_controller) { + // Init data from M5Unified: + // https://github.com/m5stack/M5Unified/blob/master/src/M5Unified.cpp + static constexpr uint8_t ES8388_I2C_ADDR = 0x10; + static constexpr uint8_t ENABLED_BULK_DATA[] = { + 0, 0x80, // RESET/ CSM POWER ON + 0, 0x00, + 0, 0x00, + 0, 0x0E, + 1, 0x00, + 2, 0x0A, // CHIP POWER: power up all + 3, 0xFF, // ADC POWER: power down all + 4, 0x3C, // DAC POWER: power up and LOUT1/ROUT1/LOUT2/ROUT2 enable + 5, 0x00, // ChipLowPower1 + 6, 0x00, // ChipLowPower2 + 7, 0x7C, // VSEL + 8, 0x00, // set I2S slave mode + // reg9-22 == adc + 23, 0x18, // I2S format (16bit) + 24, 0x00, // I2S MCLK ratio (128) + 25, 0x20, // DAC unmute + 26, 0x00, // LDACVOL 0x00~0xC0 + 27, 0x00, // RDACVOL 0x00~0xC0 + 28, 0x08, // enable digital click free power up and down + 29, 0x00, + 38, 0x00, // DAC CTRL16 + 39, 0xB8, // LEFT Ch MIX + 42, 0xB8, // RIGHTCh MIX + 43, 0x08, // ADC and DAC separate + 45, 0x00, // 0x00=1.5k VREF analog output / 0x10=40kVREF analog output + 46, 0x21, + 47, 0x21, + 48, 0x21, + 49, 0x21 + }; + + error_t error = i2c_controller_write_register_array( + i2c_controller, + ES8388_I2C_ADDR, + ENABLED_BULK_DATA, + sizeof(ENABLED_BULK_DATA), + pdMS_TO_TICKS(1000) + ); + if (error != ERROR_NONE) { + LOG_E(TAG, "Failed to enable ES8388: %s", error_to_string(error)); + return error; + } + + constexpr auto IO_EXPANDER1_ADDRESS = 0x43; + constexpr auto AMP_REGISTER = 0x05; + // Note: to disable the amplifier, reset the bits + error = i2c_controller_register8_set_bits(i2c_controller, IO_EXPANDER1_ADDRESS, AMP_REGISTER, 0b00000010 , pdMS_TO_TICKS(100)); + if (error != ERROR_NONE) { + LOG_E(TAG, "Failed to enable amplifier: %s", error_to_string(error)); + return error; + } + + return ERROR_NONE; +} + +static bool initBoot() { + auto* i2c0 = device_find_by_name("i2c0"); + check(i2c0, "i2c0 not found"); + + auto error = initPower(i2c0); + if (initPower(i2c0) != ERROR_NONE) { return false; } + error = initSound(i2c0); + if (error != ERROR_NONE) { + LOG_E(TAG, "Failed to enable ES8388"); + } + return true; } diff --git a/Devices/m5stack-tab5/m5stack,tab5.dts b/Devices/m5stack-tab5/m5stack,tab5.dts index 044c842e..ecc81175 100644 --- a/Devices/m5stack-tab5/m5stack,tab5.dts +++ b/Devices/m5stack-tab5/m5stack,tab5.dts @@ -3,6 +3,7 @@ #include #include #include +#include #include / { @@ -14,7 +15,7 @@ gpio-count = <57>; }; - i2c_internal { + i2c_internal: i2c0 { compatible = "espressif,esp32-i2c"; port = ; clock-frequency = <400000>; @@ -22,7 +23,7 @@ pin-scl = <&gpio0 32 GPIO_FLAG_NONE>; }; - i2c_port_a { + i2c_port_a: i2c1 { compatible = "espressif,esp32-i2c"; port = ; clock-frequency = <400000>; @@ -37,4 +38,15 @@ pin-miso = <&gpio0 39 GPIO_FLAG_NONE>; pin-sclk = <&gpio0 43 GPIO_FLAG_NONE>; }; + + // ES8388 and ES7210 + i2s0 { + compatible = "espressif,esp32-i2s"; + port = ; + pin-bclk = <&gpio0 27 GPIO_FLAG_NONE>; + pin-ws = <&gpio0 29 GPIO_FLAG_NONE>; + pin-data-out = <&gpio0 26 GPIO_FLAG_NONE>; + pin-data-in = <&gpio0 28 GPIO_FLAG_NONE>; + pin-mclk = <&gpio0 30 GPIO_FLAG_NONE>; + }; };