#include "wifi_board.h" #include "audio_codecs/es8311_audio_codec.h" #include "application.h" #include "button.h" #include "config.h" #include "i2c_device.h" #include "iot/thing_manager.h" #include #include #include #include "led/circular_strip.h" #define TAG "XX+EchoBase" #define PI4IOE_ADDR 0x43 #define PI4IOE_REG_CTRL 0x00 #define PI4IOE_REG_IO_PP 0x07 #define PI4IOE_REG_IO_DIR 0x03 #define PI4IOE_REG_IO_OUT 0x05 #define PI4IOE_REG_IO_PULLUP 0x0D class Pi4ioe : public I2cDevice { public: Pi4ioe(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { WriteReg(PI4IOE_REG_IO_PP, 0x00); // Set to high-impedance WriteReg(PI4IOE_REG_IO_PULLUP, 0xFF); // Enable pull-up WriteReg(PI4IOE_REG_IO_DIR, 0x6E); // Set input=0, output=1 WriteReg(PI4IOE_REG_IO_OUT, 0xFF); // Set outputs to 1 } void SetSpeakerMute(bool mute) { WriteReg(PI4IOE_REG_IO_OUT, mute ? 0x00 : 0xFF); } }; class AtomMatrixEchoBaseBoard : public WifiBoard { private: i2c_master_bus_handle_t i2c_bus_; Pi4ioe* pi4ioe_; Button face_button_; void InitializeI2c() { // Initialize I2C peripheral i2c_master_bus_config_t i2c_bus_cfg = { .i2c_port = I2C_NUM_1, .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, .clk_source = I2C_CLK_SRC_DEFAULT, .glitch_ignore_cnt = 7, .intr_priority = 0, .trans_queue_depth = 0, .flags = { .enable_internal_pullup = 1, }, }; ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); } void I2cDetect() { uint8_t address; printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); for (int i = 0; i < 128; i += 16) { printf("%02x: ", i); for (int j = 0; j < 16; j++) { fflush(stdout); address = i + j; esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); if (ret == ESP_OK) { printf("%02x ", address); } else if (ret == ESP_ERR_TIMEOUT) { printf("UU "); } else { printf("-- "); } } printf("\r\n"); } } void InitializePi4ioe() { ESP_LOGI(TAG, "Init PI4IOE"); pi4ioe_ = new Pi4ioe(i2c_bus_, PI4IOE_ADDR); pi4ioe_->SetSpeakerMute(false); } void InitializeButtons() { face_button_.OnClick([this]() { ESP_LOGI(TAG, " ===>>> face_button_.OnClick "); auto& app = Application::GetInstance(); if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) { ResetWifiConfiguration(); } app.ToggleChatState(); }); } // 物联网初始化,添加对 AI 可见设备 void InitializeIot() { auto& thing_manager = iot::ThingManager::GetInstance(); thing_manager.AddThing(iot::CreateThing("Speaker")); } public: AtomMatrixEchoBaseBoard() : face_button_(BOOT_BUTTON_GPIO) { InitializeI2c(); I2cDetect(); InitializePi4ioe(); InitializeButtons(); InitializeIot(); } virtual Led* GetLed() override { static CircularStrip led(BUILTIN_LED_GPIO, 25); return &led; } virtual AudioCodec* GetAudioCodec() override { static Es8311AudioCodec audio_codec( i2c_bus_, I2C_NUM_1, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, AUDIO_CODEC_GPIO_PA, AUDIO_CODEC_ES8311_ADDR, false); return &audio_codec; } }; DECLARE_BOARD(AtomMatrixEchoBaseBoard);