#include "ml307_board.h" #include "audio_codecs/no_audio_codec.h" #include "display/ssd1306_display.h" #include "system_reset.h" #include "application.h" #include "button.h" #include "config.h" #include "iot/thing_manager.h" #include "led/single_led.h" #include #include #define TAG "CompactMl307Board" class CompactMl307Board : public Ml307Board { private: i2c_master_bus_handle_t display_i2c_bus_; Button boot_button_; Button touch_button_; Button volume_up_button_; Button volume_down_button_; SystemReset system_reset_; void InitializeDisplayI2c() { i2c_master_bus_config_t bus_config = { .i2c_port = (i2c_port_t)0, .sda_io_num = DISPLAY_SDA_PIN, .scl_io_num = DISPLAY_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(&bus_config, &display_i2c_bus_)); } void InitializeButtons() { boot_button_.OnClick([this]() { Application::GetInstance().ToggleChatState(); }); touch_button_.OnPressDown([this]() { Application::GetInstance().StartListening(); }); touch_button_.OnPressUp([this]() { Application::GetInstance().StopListening(); }); volume_up_button_.OnClick([this]() { auto codec = GetAudioCodec(); auto volume = codec->output_volume() + 10; if (volume > 100) { volume = 100; } codec->SetOutputVolume(volume); GetDisplay()->ShowNotification("音量 " + std::to_string(volume)); }); volume_up_button_.OnLongPress([this]() { GetAudioCodec()->SetOutputVolume(100); GetDisplay()->ShowNotification("最大音量"); }); volume_down_button_.OnClick([this]() { auto codec = GetAudioCodec(); auto volume = codec->output_volume() - 10; if (volume < 0) { volume = 0; } codec->SetOutputVolume(volume); GetDisplay()->ShowNotification("音量 " + std::to_string(volume)); }); volume_down_button_.OnLongPress([this]() { GetAudioCodec()->SetOutputVolume(0); GetDisplay()->ShowNotification("已静音"); }); } // 物联网初始化,添加对 AI 可见设备 void InitializeIot() { auto& thing_manager = iot::ThingManager::GetInstance(); thing_manager.AddThing(iot::CreateThing("Speaker")); thing_manager.AddThing(iot::CreateThing("Lamp")); } public: CompactMl307Board() : Ml307Board(ML307_TX_PIN, ML307_RX_PIN, 4096), boot_button_(BOOT_BUTTON_GPIO), touch_button_(TOUCH_BUTTON_GPIO), volume_up_button_(VOLUME_UP_BUTTON_GPIO), volume_down_button_(VOLUME_DOWN_BUTTON_GPIO), system_reset_(RESET_NVS_BUTTON_GPIO, RESET_FACTORY_BUTTON_GPIO) { // Check if the reset button is pressed system_reset_.CheckButtons(); InitializeDisplayI2c(); InitializeButtons(); InitializeIot(); } virtual Led* GetLed() override { static SingleLed led(BUILTIN_LED_GPIO); return &led; } virtual AudioCodec* GetAudioCodec() override { #ifdef AUDIO_I2S_METHOD_SIMPLEX static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); #else static NoAudioCodecDuplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN); #endif return &audio_codec; } virtual Display* GetDisplay() override { static Ssd1306Display display(display_i2c_bus_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); return &display; } }; DECLARE_BOARD(CompactMl307Board);