#include "wifi_board.h" #include "codecs/box_audio_codec.h" #include "display/lcd_display.h" #include "application.h" #include "button.h" #include "config.h" #include "backlight.h" #include #include #include #include #include "i2c_device.h" #include #include #include #include "esp_lcd_touch_cst816s.h" #include "touch.h" #include "driver/temperature_sensor.h" #include #include #include #define TAG "EchoEar" LV_FONT_DECLARE(font_puhui_20_4); LV_FONT_DECLARE(font_awesome_20_4); temperature_sensor_handle_t temp_sensor = NULL; static const st77916_lcd_init_cmd_t vendor_specific_init_yysj[] = { {0xF0, (uint8_t []){0x28}, 1, 0}, {0xF2, (uint8_t []){0x28}, 1, 0}, {0x73, (uint8_t []){0xF0}, 1, 0}, {0x7C, (uint8_t []){0xD1}, 1, 0}, {0x83, (uint8_t []){0xE0}, 1, 0}, {0x84, (uint8_t []){0x61}, 1, 0}, {0xF2, (uint8_t []){0x82}, 1, 0}, {0xF0, (uint8_t []){0x00}, 1, 0}, {0xF0, (uint8_t []){0x01}, 1, 0}, {0xF1, (uint8_t []){0x01}, 1, 0}, {0xB0, (uint8_t []){0x56}, 1, 0}, {0xB1, (uint8_t []){0x4D}, 1, 0}, {0xB2, (uint8_t []){0x24}, 1, 0}, {0xB4, (uint8_t []){0x87}, 1, 0}, {0xB5, (uint8_t []){0x44}, 1, 0}, {0xB6, (uint8_t []){0x8B}, 1, 0}, {0xB7, (uint8_t []){0x40}, 1, 0}, {0xB8, (uint8_t []){0x86}, 1, 0}, {0xBA, (uint8_t []){0x00}, 1, 0}, {0xBB, (uint8_t []){0x08}, 1, 0}, {0xBC, (uint8_t []){0x08}, 1, 0}, {0xBD, (uint8_t []){0x00}, 1, 0}, {0xC0, (uint8_t []){0x80}, 1, 0}, {0xC1, (uint8_t []){0x10}, 1, 0}, {0xC2, (uint8_t []){0x37}, 1, 0}, {0xC3, (uint8_t []){0x80}, 1, 0}, {0xC4, (uint8_t []){0x10}, 1, 0}, {0xC5, (uint8_t []){0x37}, 1, 0}, {0xC6, (uint8_t []){0xA9}, 1, 0}, {0xC7, (uint8_t []){0x41}, 1, 0}, {0xC8, (uint8_t []){0x01}, 1, 0}, {0xC9, (uint8_t []){0xA9}, 1, 0}, {0xCA, (uint8_t []){0x41}, 1, 0}, {0xCB, (uint8_t []){0x01}, 1, 0}, {0xD0, (uint8_t []){0x91}, 1, 0}, {0xD1, (uint8_t []){0x68}, 1, 0}, {0xD2, (uint8_t []){0x68}, 1, 0}, {0xF5, (uint8_t []){0x00, 0xA5}, 2, 0}, {0xDD, (uint8_t []){0x4F}, 1, 0}, {0xDE, (uint8_t []){0x4F}, 1, 0}, {0xF1, (uint8_t []){0x10}, 1, 0}, {0xF0, (uint8_t []){0x00}, 1, 0}, {0xF0, (uint8_t []){0x02}, 1, 0}, {0xE0, (uint8_t []){0xF0, 0x0A, 0x10, 0x09, 0x09, 0x36, 0x35, 0x33, 0x4A, 0x29, 0x15, 0x15, 0x2E, 0x34}, 14, 0}, {0xE1, (uint8_t []){0xF0, 0x0A, 0x0F, 0x08, 0x08, 0x05, 0x34, 0x33, 0x4A, 0x39, 0x15, 0x15, 0x2D, 0x33}, 14, 0}, {0xF0, (uint8_t []){0x10}, 1, 0}, {0xF3, (uint8_t []){0x10}, 1, 0}, {0xE0, (uint8_t []){0x07}, 1, 0}, {0xE1, (uint8_t []){0x00}, 1, 0}, {0xE2, (uint8_t []){0x00}, 1, 0}, {0xE3, (uint8_t []){0x00}, 1, 0}, {0xE4, (uint8_t []){0xE0}, 1, 0}, {0xE5, (uint8_t []){0x06}, 1, 0}, {0xE6, (uint8_t []){0x21}, 1, 0}, {0xE7, (uint8_t []){0x01}, 1, 0}, {0xE8, (uint8_t []){0x05}, 1, 0}, {0xE9, (uint8_t []){0x02}, 1, 0}, {0xEA, (uint8_t []){0xDA}, 1, 0}, {0xEB, (uint8_t []){0x00}, 1, 0}, {0xEC, (uint8_t []){0x00}, 1, 0}, {0xED, (uint8_t []){0x0F}, 1, 0}, {0xEE, (uint8_t []){0x00}, 1, 0}, {0xEF, (uint8_t []){0x00}, 1, 0}, {0xF8, (uint8_t []){0x00}, 1, 0}, {0xF9, (uint8_t []){0x00}, 1, 0}, {0xFA, (uint8_t []){0x00}, 1, 0}, {0xFB, (uint8_t []){0x00}, 1, 0}, {0xFC, (uint8_t []){0x00}, 1, 0}, {0xFD, (uint8_t []){0x00}, 1, 0}, {0xFE, (uint8_t []){0x00}, 1, 0}, {0xFF, (uint8_t []){0x00}, 1, 0}, {0x60, (uint8_t []){0x40}, 1, 0}, {0x61, (uint8_t []){0x04}, 1, 0}, {0x62, (uint8_t []){0x00}, 1, 0}, {0x63, (uint8_t []){0x42}, 1, 0}, {0x64, (uint8_t []){0xD9}, 1, 0}, {0x65, (uint8_t []){0x00}, 1, 0}, {0x66, (uint8_t []){0x00}, 1, 0}, {0x67, (uint8_t []){0x00}, 1, 0}, {0x68, (uint8_t []){0x00}, 1, 0}, {0x69, (uint8_t []){0x00}, 1, 0}, {0x6A, (uint8_t []){0x00}, 1, 0}, {0x6B, (uint8_t []){0x00}, 1, 0}, {0x70, (uint8_t []){0x40}, 1, 0}, {0x71, (uint8_t []){0x03}, 1, 0}, {0x72, (uint8_t []){0x00}, 1, 0}, {0x73, (uint8_t []){0x42}, 1, 0}, {0x74, (uint8_t []){0xD8}, 1, 0}, {0x75, (uint8_t []){0x00}, 1, 0}, {0x76, (uint8_t []){0x00}, 1, 0}, {0x77, (uint8_t []){0x00}, 1, 0}, {0x78, (uint8_t []){0x00}, 1, 0}, {0x79, (uint8_t []){0x00}, 1, 0}, {0x7A, (uint8_t []){0x00}, 1, 0}, {0x7B, (uint8_t []){0x00}, 1, 0}, {0x80, (uint8_t []){0x48}, 1, 0}, {0x81, (uint8_t []){0x00}, 1, 0}, {0x82, (uint8_t []){0x06}, 1, 0}, {0x83, (uint8_t []){0x02}, 1, 0}, {0x84, (uint8_t []){0xD6}, 1, 0}, {0x85, (uint8_t []){0x04}, 1, 0}, {0x86, (uint8_t []){0x00}, 1, 0}, {0x87, (uint8_t []){0x00}, 1, 0}, {0x88, (uint8_t []){0x48}, 1, 0}, {0x89, (uint8_t []){0x00}, 1, 0}, {0x8A, (uint8_t []){0x08}, 1, 0}, {0x8B, (uint8_t []){0x02}, 1, 0}, {0x8C, (uint8_t []){0xD8}, 1, 0}, {0x8D, (uint8_t []){0x04}, 1, 0}, {0x8E, (uint8_t []){0x00}, 1, 0}, {0x8F, (uint8_t []){0x00}, 1, 0}, {0x90, (uint8_t []){0x48}, 1, 0}, {0x91, (uint8_t []){0x00}, 1, 0}, {0x92, (uint8_t []){0x0A}, 1, 0}, {0x93, (uint8_t []){0x02}, 1, 0}, {0x94, (uint8_t []){0xDA}, 1, 0}, {0x95, (uint8_t []){0x04}, 1, 0}, {0x96, (uint8_t []){0x00}, 1, 0}, {0x97, (uint8_t []){0x00}, 1, 0}, {0x98, (uint8_t []){0x48}, 1, 0}, {0x99, (uint8_t []){0x00}, 1, 0}, {0x9A, (uint8_t []){0x0C}, 1, 0}, {0x9B, (uint8_t []){0x02}, 1, 0}, {0x9C, (uint8_t []){0xDC}, 1, 0}, {0x9D, (uint8_t []){0x04}, 1, 0}, {0x9E, (uint8_t []){0x00}, 1, 0}, {0x9F, (uint8_t []){0x00}, 1, 0}, {0xA0, (uint8_t []){0x48}, 1, 0}, {0xA1, (uint8_t []){0x00}, 1, 0}, {0xA2, (uint8_t []){0x05}, 1, 0}, {0xA3, (uint8_t []){0x02}, 1, 0}, {0xA4, (uint8_t []){0xD5}, 1, 0}, {0xA5, (uint8_t []){0x04}, 1, 0}, {0xA6, (uint8_t []){0x00}, 1, 0}, {0xA7, (uint8_t []){0x00}, 1, 0}, {0xA8, (uint8_t []){0x48}, 1, 0}, {0xA9, (uint8_t []){0x00}, 1, 0}, {0xAA, (uint8_t []){0x07}, 1, 0}, {0xAB, (uint8_t []){0x02}, 1, 0}, {0xAC, (uint8_t []){0xD7}, 1, 0}, {0xAD, (uint8_t []){0x04}, 1, 0}, {0xAE, (uint8_t []){0x00}, 1, 0}, {0xAF, (uint8_t []){0x00}, 1, 0}, {0xB0, (uint8_t []){0x48}, 1, 0}, {0xB1, (uint8_t []){0x00}, 1, 0}, {0xB2, (uint8_t []){0x09}, 1, 0}, {0xB3, (uint8_t []){0x02}, 1, 0}, {0xB4, (uint8_t []){0xD9}, 1, 0}, {0xB5, (uint8_t []){0x04}, 1, 0}, {0xB6, (uint8_t []){0x00}, 1, 0}, {0xB7, (uint8_t []){0x00}, 1, 0}, {0xB8, (uint8_t []){0x48}, 1, 0}, {0xB9, (uint8_t []){0x00}, 1, 0}, {0xBA, (uint8_t []){0x0B}, 1, 0}, {0xBB, (uint8_t []){0x02}, 1, 0}, {0xBC, (uint8_t []){0xDB}, 1, 0}, {0xBD, (uint8_t []){0x04}, 1, 0}, {0xBE, (uint8_t []){0x00}, 1, 0}, {0xBF, (uint8_t []){0x00}, 1, 0}, {0xC0, (uint8_t []){0x10}, 1, 0}, {0xC1, (uint8_t []){0x47}, 1, 0}, {0xC2, (uint8_t []){0x56}, 1, 0}, {0xC3, (uint8_t []){0x65}, 1, 0}, {0xC4, (uint8_t []){0x74}, 1, 0}, {0xC5, (uint8_t []){0x88}, 1, 0}, {0xC6, (uint8_t []){0x99}, 1, 0}, {0xC7, (uint8_t []){0x01}, 1, 0}, {0xC8, (uint8_t []){0xBB}, 1, 0}, {0xC9, (uint8_t []){0xAA}, 1, 0}, {0xD0, (uint8_t []){0x10}, 1, 0}, {0xD1, (uint8_t []){0x47}, 1, 0}, {0xD2, (uint8_t []){0x56}, 1, 0}, {0xD3, (uint8_t []){0x65}, 1, 0}, {0xD4, (uint8_t []){0x74}, 1, 0}, {0xD5, (uint8_t []){0x88}, 1, 0}, {0xD6, (uint8_t []){0x99}, 1, 0}, {0xD7, (uint8_t []){0x01}, 1, 0}, {0xD8, (uint8_t []){0xBB}, 1, 0}, {0xD9, (uint8_t []){0xAA}, 1, 0}, {0xF3, (uint8_t []){0x01}, 1, 0}, {0xF0, (uint8_t []){0x00}, 1, 0}, {0x21, (uint8_t []){}, 0, 0}, {0x11, (uint8_t []){}, 0, 0}, {0x00, (uint8_t []){}, 0, 120}, }; float tsens_value; gpio_num_t AUDIO_I2S_GPIO_DIN = AUDIO_I2S_GPIO_DIN_1; gpio_num_t AUDIO_CODEC_PA_PIN = AUDIO_CODEC_PA_PIN_1; gpio_num_t QSPI_PIN_NUM_LCD_RST = QSPI_PIN_NUM_LCD_RST_1; gpio_num_t TOUCH_PAD2 = TOUCH_PAD2_1; gpio_num_t UART1_TX = UART1_TX_1; gpio_num_t UART1_RX = UART1_RX_1; class Charge : public I2cDevice { public: Charge(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { read_buffer_ = new uint8_t[8]; } ~Charge() { delete[] read_buffer_; } void Printcharge() { ReadRegs(0x08, read_buffer_, 2); ReadRegs(0x0c, read_buffer_ + 2, 2); ESP_ERROR_CHECK(temperature_sensor_get_celsius(temp_sensor, &tsens_value)); int16_t voltage = (uint16_t)(read_buffer_[1] << 8 | read_buffer_[0]); int16_t current = (int16_t)(read_buffer_[3] << 8 | read_buffer_[2]); } static void TaskFunction(void *pvParameters) { Charge* charge = static_cast(pvParameters); while (true) { charge->Printcharge(); vTaskDelay(pdMS_TO_TICKS(300)); } } private: uint8_t* read_buffer_ = nullptr; }; class Cst816s : public I2cDevice { public: struct TouchPoint_t { int num = 0; int x = -1; int y = -1; }; Cst816s(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { read_buffer_ = new uint8_t[6]; } ~Cst816s() { delete[] read_buffer_; } void UpdateTouchPoint() { ReadRegs(0x02, read_buffer_, 6); tp_.num = read_buffer_[0] & 0x0F; tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2]; tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4]; } const TouchPoint_t& GetTouchPoint() { return tp_; } private: uint8_t* read_buffer_ = nullptr; TouchPoint_t tp_; }; static SemaphoreHandle_t touch_isr_mux = NULL; static bool touch_event_pending = false; static int64_t touch_event_time = 0; class EspS3Cat : public WifiBoard { private: i2c_master_bus_handle_t i2c_bus_; Cst816s* cst816s_; Charge* charge_; Button boot_button_; LcdDisplay* display_; PwmBacklight* backlight_ = nullptr; esp_timer_handle_t touchpad_timer_; esp_lcd_touch_handle_t tp; // LCD touch handle void InitializeI2c() { i2c_master_bus_config_t i2c_bus_cfg = { .i2c_port = I2C_NUM_0, .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_)); temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(10, 50); ESP_ERROR_CHECK(temperature_sensor_install(&temp_sensor_config, &temp_sensor)); ESP_ERROR_CHECK(temperature_sensor_enable(temp_sensor)); } uint8_t DetectPcbVersion() { esp_err_t ret = i2c_master_probe(i2c_bus_, 0x18, 100); uint8_t pcb_verison = 0; if (ret == ESP_OK) { ESP_LOGI(TAG, "PCB verison V1.0"); pcb_verison = 0; } else { gpio_config_t gpio_conf = { .pin_bit_mask = (1ULL << GPIO_NUM_48), .mode = GPIO_MODE_OUTPUT, .pull_up_en = GPIO_PULLUP_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE }; ESP_ERROR_CHECK(gpio_config(&gpio_conf)); ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_48, 1)); vTaskDelay(pdMS_TO_TICKS(100)); ret = i2c_master_probe(i2c_bus_, 0x18, 100); if (ret == ESP_OK) { ESP_LOGI(TAG, "PCB verison V1.2"); pcb_verison = 1; AUDIO_I2S_GPIO_DIN = AUDIO_I2S_GPIO_DIN_2; AUDIO_CODEC_PA_PIN = AUDIO_CODEC_PA_PIN_2; QSPI_PIN_NUM_LCD_RST = QSPI_PIN_NUM_LCD_RST_2; TOUCH_PAD2 = TOUCH_PAD2_2; UART1_TX = UART1_TX_2; UART1_RX = UART1_RX_2; } else { ESP_LOGE(TAG, "PCB version detection error"); } } return pcb_verison; } static void touchpad_timer_callback(void* arg) { auto& board = (EspS3Cat&)Board::GetInstance(); auto touchpad = board.GetTouchpad(); static bool was_touched = false; static int64_t touch_start_time = 0; const int64_t TOUCH_THRESHOLD_MS = 500; touchpad->UpdateTouchPoint(); auto touch_point = touchpad->GetTouchPoint(); if (touch_point.num > 0 && !was_touched) { was_touched = true; touch_start_time = esp_timer_get_time() / 1000; } else if (touch_point.num == 0 && was_touched) { was_touched = false; int64_t touch_duration = (esp_timer_get_time() / 1000) - touch_start_time; if (touch_duration < TOUCH_THRESHOLD_MS) { auto& app = Application::GetInstance(); if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) { board.ResetWifiConfiguration(); } app.ToggleChatState(); } } } static void touchpad_callback(Cst816s::TouchPoint_t touch_point) { auto& board = (EspS3Cat&)Board::GetInstance(); static bool was_touched = false; static int64_t touch_start_time = 0; const int64_t TOUCH_THRESHOLD_MS = 500; if (touch_point.num > 0 && !was_touched) { was_touched = true; touch_start_time = esp_timer_get_time() / 1000; } else if (touch_point.num == 0 && was_touched) { was_touched = false; int64_t touch_duration = (esp_timer_get_time() / 1000) - touch_start_time; if (touch_duration < TOUCH_THRESHOLD_MS) { auto& app = Application::GetInstance(); if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) { board.ResetWifiConfiguration(); } app.ToggleChatState(); } } } static void lvgl_port_touch_isr_cb(void* arg) { int64_t current_time = esp_timer_get_time() / 1000; static int64_t last_touch_time = 0; if (current_time - last_touch_time >= 300) { touch_event_pending = true; touch_event_time = current_time; last_touch_time = current_time; BaseType_t xHigherPriorityTaskWoken = pdFALSE; if (touch_isr_mux != NULL) { xSemaphoreGiveFromISR(touch_isr_mux, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } } } static void touch_event_task(void* arg) { while (true) { if (xSemaphoreTake(touch_isr_mux, portMAX_DELAY) == pdTRUE) { if (touch_event_pending) { touch_event_pending = false; auto& board = (EspS3Cat&)Board::GetInstance(); auto& app = Application::GetInstance(); if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) { board.ResetWifiConfiguration(); } app.ToggleChatState(); } } } } void InitializeCharge() { charge_ = new Charge(i2c_bus_, 0x55); xTaskCreatePinnedToCore(Charge::TaskFunction, "batterydecTask", 3 * 1024, charge_, 6, NULL, 0); } void InitializeCst816sTouchPad() { cst816s_ = new Cst816s(i2c_bus_, 0x15); touch_isr_mux = xSemaphoreCreateBinary(); if (touch_isr_mux == NULL) { ESP_LOGE(TAG, "Failed to create touch semaphore"); return; } xTaskCreatePinnedToCore(touch_event_task, "touch_task", 4 * 1024, NULL, 5, NULL, 1); const gpio_config_t int_gpio_config = { .pin_bit_mask = (1ULL << TP_PIN_NUM_INT), .mode = GPIO_MODE_INPUT, .intr_type = GPIO_INTR_NEGEDGE }; gpio_config(&int_gpio_config); gpio_install_isr_service(0); gpio_intr_enable(TP_PIN_NUM_INT); gpio_isr_handler_add(TP_PIN_NUM_INT, EspS3Cat::lvgl_port_touch_isr_cb, NULL); } void InitializeSpi() { const spi_bus_config_t bus_config = TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(QSPI_PIN_NUM_LCD_PCLK, QSPI_PIN_NUM_LCD_DATA0, QSPI_PIN_NUM_LCD_DATA1, QSPI_PIN_NUM_LCD_DATA2, QSPI_PIN_NUM_LCD_DATA3, QSPI_LCD_H_RES * 80 * sizeof(uint16_t)); ESP_ERROR_CHECK(spi_bus_initialize(QSPI_LCD_HOST, &bus_config, SPI_DMA_CH_AUTO)); } void Initializest77916Display(uint8_t pcb_verison) { esp_lcd_panel_io_handle_t panel_io = nullptr; esp_lcd_panel_handle_t panel = nullptr; const esp_lcd_panel_io_spi_config_t io_config = ST77916_PANEL_IO_QSPI_CONFIG(QSPI_PIN_NUM_LCD_CS, NULL, NULL); ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST, &io_config, &panel_io)); st77916_vendor_config_t vendor_config = { .init_cmds = vendor_specific_init_yysj, .init_cmds_size = sizeof(vendor_specific_init_yysj) / sizeof(st77916_lcd_init_cmd_t), .flags = { .use_qspi_interface = 1, }, }; const esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = QSPI_PIN_NUM_LCD_RST, .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, .bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, .flags = { .reset_active_high = pcb_verison, }, .vendor_config = &vendor_config, }; ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel)); esp_lcd_panel_reset(panel); esp_lcd_panel_init(panel); esp_lcd_panel_disp_on_off(panel, true); esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); display_ = new SpiLcdDisplay(panel_io, panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY, { .text_font = &font_puhui_20_4, .icon_font = &font_awesome_20_4, .emoji_font = font_emoji_64_init(), }); backlight_ = new PwmBacklight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); backlight_->RestoreBrightness(); } void InitializeButtons() { boot_button_.OnClick([this]() { auto& app = Application::GetInstance(); if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) { ResetWifiConfiguration(); } app.ToggleChatState(); }); gpio_config_t power_gpio_config = { .pin_bit_mask = (BIT64(POWER_CTRL) ), .mode = GPIO_MODE_OUTPUT, }; ESP_ERROR_CHECK(gpio_config(&power_gpio_config)); gpio_set_level(POWER_CTRL, 0); } public: EspS3Cat() : boot_button_(BOOT_BUTTON_GPIO) { InitializeI2c(); uint8_t pcb_verison = DetectPcbVersion(); InitializeCharge(); InitializeCst816sTouchPad(); InitializeSpi(); Initializest77916Display(pcb_verison); InitializeButtons(); } virtual AudioCodec* GetAudioCodec() override { static BoxAudioCodec audio_codec( i2c_bus_, 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_PA_PIN, AUDIO_CODEC_ES8311_ADDR, AUDIO_CODEC_ES7210_ADDR, AUDIO_INPUT_REFERENCE); return &audio_codec; } virtual Display* GetDisplay() override { return display_; } Cst816s* GetTouchpad() { return cst816s_; } virtual Backlight* GetBacklight() override { return backlight_; } }; DECLARE_BOARD(EspS3Cat);