From a872ca1bff871181e4d8a6ba5c9268908e0b9e00 Mon Sep 17 00:00:00 2001 From: yusuhua <57382265+yusuhua@users.noreply.github.com> Date: Sat, 1 Mar 2025 22:06:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0LilyGo=20T-CameraPlus-S3?= =?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81=E5=8F=8A=E4=BF=AE=E5=A4=8DLilyGo=20?= =?UTF-8?q?T-Circle-S3=E7=BC=96=E8=AF=91i2s=5Fstd=5Fclk=5Fconfig=5Ft?= =?UTF-8?q?=E6=8A=A5'i2s=5Fstd=5Fclk=5Fconfig=5Ft::ext=5Fclk=5Ffreq=5Fhz'?= =?UTF-8?q?=20=20does=20not=20match=20declaration=20=20(#239)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 增加LILYGO T-CameraPlus-S3支持 * 增加LILYGO T-CameraPlus-S3支持 * Remove .DS_Store files * Remove .DS_Store files * 将T-Circle-S3与T-CamerPlus-S3的codec放入boards下 * 移除T-CameraPlus-S的README3图片展示 * revert README files * delete lilygo-t-cameraplus-s3.jpg --------- Co-authored-by: yusuhua --- .gitignore | 3 +- main/CMakeLists.txt | 3 +- main/Kconfig.projbuild | 4 +- main/boards/lilygo-t-cameraplus-s3/config.h | 47 ++++ .../boards/lilygo-t-cameraplus-s3/config.json | 9 + .../lilygo-t-cameraplus-s3.cc | 226 ++++++++++++++++++ .../lilygo-t-cameraplus-s3/pin_config.h | 100 ++++++++ .../tcamerapluss3_audio_codec.cc | 132 ++++++++++ .../tcamerapluss3_audio_codec.h | 37 +++ .../lilygo-t-circle-s3/lilygo-t-circle-s3.cc | 2 +- .../tcircles3_audio_codec.cc | 22 +- .../tcircles3_audio_codec.h | 2 +- 12 files changed, 578 insertions(+), 9 deletions(-) create mode 100644 main/boards/lilygo-t-cameraplus-s3/config.h create mode 100644 main/boards/lilygo-t-cameraplus-s3/config.json create mode 100644 main/boards/lilygo-t-cameraplus-s3/lilygo-t-cameraplus-s3.cc create mode 100644 main/boards/lilygo-t-cameraplus-s3/pin_config.h create mode 100644 main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.cc create mode 100644 main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.h rename main/{audio_codecs => boards/lilygo-t-circle-s3}/tcircles3_audio_codec.cc (85%) rename main/{audio_codecs => boards/lilygo-t-circle-s3}/tcircles3_audio_codec.h (97%) diff --git a/.gitignore b/.gitignore index db2379ba..3223c733 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ sdkconfig dependencies.lock .env releases/ -main/assets/lang_config.h \ No newline at end of file +main/assets/lang_config.h +.DS_Store \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 52f1a3de..f48e170f 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -4,7 +4,6 @@ set(SOURCES "audio_codecs/audio_codec.cc" "audio_codecs/es8311_audio_codec.cc" "audio_codecs/es8388_audio_codec.cc" "audio_codecs/cores3_audio_codec.cc" - "audio_codecs/tcircles3_audio_codec.cc" "led/single_led.cc" "led/circular_strip.cc" "display/display.cc" @@ -92,6 +91,8 @@ elseif(CONFIG_BOARD_TYPE_TUDOUZI) set(BOARD_TYPE "tudouzi") elseif(CONFIG_BOARD_TYPE_LILYGO_T_CIRCLE_S3) set(BOARD_TYPE "lilygo-t-circle-s3") +elseif(CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3) + set(BOARD_TYPE "lilygo-t-cameraplus-s3") elseif(CONFIG_BOARD_TYPE_MOVECALL_MOJI_ESP32S3) set(BOARD_TYPE "movecall-moji-esp32s3") elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 0b83dfd2..5d46605c 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -107,7 +107,9 @@ choice BOARD_TYPE config BOARD_TYPE_TUDOUZI bool "土豆子" config BOARD_TYPE_LILYGO_T_CIRCLE_S3 - bool "LILYGO T-Circle-S3" + bool "LILYGO T-Circle-S3" + config BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3 + bool "LILYGO T-CameraPlus-S3" config BOARD_TYPE_MOVECALL_MOJI_ESP32S3 bool "Movecall Moji 小智AI衍生版" config BOARD_TYPE_ATK_DNESP32S3 diff --git a/main/boards/lilygo-t-cameraplus-s3/config.h b/main/boards/lilygo-t-cameraplus-s3/config.h new file mode 100644 index 00000000..b47daead --- /dev/null +++ b/main/boards/lilygo-t-cameraplus-s3/config.h @@ -0,0 +1,47 @@ +#ifndef _BOARD_CONFIG_H_ +#define _BOARD_CONFIG_H_ + +// M5Stack CoreS3 Board configuration + +#include +#include "pin_config.h" + +#define AUDIO_INPUT_REFERENCE true +#define AUDIO_INPUT_SAMPLE_RATE 24000 +#define AUDIO_OUTPUT_SAMPLE_RATE 24000 + +#define AUDIO_MIC_I2S_GPIO_BCLK static_cast(MSM261_BCLK) +#define AUDIO_MIC_I2S_GPIO_WS static_cast(MSM261_WS) +#define AUDIO_MIC_I2S_GPIO_DATA static_cast(MSM261_DIN) + +#define AUDIO_SPKR_I2S_GPIO_BCLK static_cast(MAX98357A_BCLK) +#define AUDIO_SPKR_I2S_GPIO_LRCLK static_cast(MAX98357A_LRCLK) +#define AUDIO_SPKR_I2S_GPIO_DATA static_cast(MAX98357A_DOUT) + +#define TOUCH_I2C_SDA_PIN static_cast(TP_SDA) +#define TOUCH_I2C_SCL_PIN static_cast(TP_SCL) + +#define BUILTIN_LED_GPIO GPIO_NUM_NC +#define KEY1_BUTTON_GPIO static_cast(KEY1) +#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC +#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC + +#define DISPLAY_WIDTH LCD_WIDTH +#define DISPLAY_HEIGHT LCD_HEIGHT +#define DISPLAY_MOSI LCD_MOSI +#define DISPLAY_SCLK LCD_SCLK +#define DISPLAY_DC LCD_DC +#define DISPLAY_RST LCD_RST +#define DISPLAY_CS LCD_CS +#define DISPLAY_BL static_cast(LCD_BL) +#define DISPLAY_MIRROR_X false +#define DISPLAY_MIRROR_Y false +#define DISPLAY_SWAP_XY false + +#define DISPLAY_OFFSET_X 0 +#define DISPLAY_OFFSET_Y 0 + +#define DISPLAY_BACKLIGHT_PIN DISPLAY_BL +#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false + +#endif // _BOARD_CONFIG_H_ diff --git a/main/boards/lilygo-t-cameraplus-s3/config.json b/main/boards/lilygo-t-cameraplus-s3/config.json new file mode 100644 index 00000000..596ae8ce --- /dev/null +++ b/main/boards/lilygo-t-cameraplus-s3/config.json @@ -0,0 +1,9 @@ +{ + "target": "esp32s3", + "builds": [ + { + "name": "lilygo-t-cameraplus-s3", + "sdkconfig_append": ["CONFIG_SPIRAM_MODE_OCT=n","CONFIG_SPIRAM_MODE_QUAD=y"] + } + ] +} \ No newline at end of file diff --git a/main/boards/lilygo-t-cameraplus-s3/lilygo-t-cameraplus-s3.cc b/main/boards/lilygo-t-cameraplus-s3/lilygo-t-cameraplus-s3.cc new file mode 100644 index 00000000..7a1aea73 --- /dev/null +++ b/main/boards/lilygo-t-cameraplus-s3/lilygo-t-cameraplus-s3.cc @@ -0,0 +1,226 @@ +#include "wifi_board.h" +#include "tcamerapluss3_audio_codec.h" +#include "display/lcd_display.h" +#include "application.h" +#include "button.h" +#include "config.h" +#include "i2c_device.h" +#include "iot/thing_manager.h" + +#include +#include +#include +#include + +#define TAG "LilygoTCameraPlusS3Board" + +LV_FONT_DECLARE(font_puhui_16_4); +LV_FONT_DECLARE(font_awesome_16_4); + +class Cst816x : public I2cDevice { +public: + struct TouchPoint_t { + int num = 0; + int x = -1; + int y = -1; + }; + + Cst816x(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { + uint8_t chip_id = ReadReg(0xA7); + ESP_LOGI(TAG, "Get chip ID: 0x%02X", chip_id); + read_buffer_ = new uint8_t[6]; + } + + ~Cst816x() { + 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_; +}; + +class LilygoTCameraPlusS3Board : public WifiBoard { +private: + i2c_master_bus_handle_t i2c_bus_; + Cst816x *cst816d_; + LcdDisplay *display_; + Button key1_button_; + + void InitI2c(){ + // Initialize I2C peripheral + i2c_master_bus_config_t i2c_bus_config = { + .i2c_port = I2C_NUM_0, + .sda_io_num = TOUCH_I2C_SDA_PIN, + .scl_io_num = TOUCH_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_config, &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"); + } + } + + static void touchpad_daemon(void *param) { + vTaskDelay(pdMS_TO_TICKS(2000)); + auto &board = (LilygoTCameraPlusS3Board&)Board::GetInstance(); + auto touchpad = board.GetTouchpad(); + bool was_touched = false; + while (1) { + touchpad->UpdateTouchPoint(); + if (touchpad->GetTouchPoint().num > 0){ + // On press + if (!was_touched) { + was_touched = true; + Application::GetInstance().ToggleChatState(); + } + } + // On release + else if (was_touched) { + was_touched = false; + } + vTaskDelay(pdMS_TO_TICKS(50)); + } + vTaskDelete(NULL); + } + + void InitCst816d() { + ESP_LOGI(TAG, "Init CST816x"); + cst816d_ = new Cst816x(i2c_bus_, 0x15); + xTaskCreate(touchpad_daemon, "tp", 2048, NULL, 5, NULL); + } + + void InitSpi() { + spi_bus_config_t buscfg = {}; + buscfg.mosi_io_num = DISPLAY_MOSI; + buscfg.miso_io_num = GPIO_NUM_NC; + buscfg.sclk_io_num = DISPLAY_SCLK; + buscfg.quadwp_io_num = GPIO_NUM_NC; + buscfg.quadhd_io_num = GPIO_NUM_NC; + buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); + ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); + } + + void InitializeSt7789Display() { + esp_lcd_panel_io_handle_t panel_io = nullptr; + esp_lcd_panel_handle_t panel = nullptr; + // 液晶屏控制IO初始化 + ESP_LOGD(TAG, "Install panel IO"); + esp_lcd_panel_io_spi_config_t io_config = {}; + io_config.cs_gpio_num = LCD_CS; + io_config.dc_gpio_num = LCD_DC; + io_config.spi_mode = 0; + io_config.pclk_hz = 60 * 1000 * 1000; + io_config.trans_queue_depth = 10; + io_config.lcd_cmd_bits = 8; + io_config.lcd_param_bits = 8; + ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); + + // 初始化液晶屏驱动芯片ST7789 + ESP_LOGD(TAG, "Install LCD driver"); + esp_lcd_panel_dev_config_t panel_config = {}; + panel_config.reset_gpio_num = LCD_RST; + panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; + panel_config.bits_per_pixel = 16; + ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); + ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); + ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); + ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY)); + ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); + ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, true)); + + display_ = new SpiLcdDisplay(panel_io, panel, DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT, + DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY, + { + .text_font = &font_puhui_16_4, + .icon_font = &font_awesome_16_4, + .emoji_font = font_emoji_32_init(), + }); + } + + void InitializeButtons() { + key1_button_.OnClick([this]() { + 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: + LilygoTCameraPlusS3Board() : key1_button_(KEY1_BUTTON_GPIO) { + InitI2c(); + InitCst816d(); + I2cDetect(); + InitSpi(); + InitializeSt7789Display(); + InitializeButtons(); + InitializeIot(); + } + + virtual AudioCodec *GetAudioCodec() override { + static Tcamerapluss3AudioCodec audio_codec( + AUDIO_INPUT_SAMPLE_RATE, + AUDIO_OUTPUT_SAMPLE_RATE, + AUDIO_MIC_I2S_GPIO_BCLK, + AUDIO_MIC_I2S_GPIO_WS, + AUDIO_MIC_I2S_GPIO_DATA, + AUDIO_SPKR_I2S_GPIO_BCLK, + AUDIO_SPKR_I2S_GPIO_LRCLK, + AUDIO_SPKR_I2S_GPIO_DATA, + AUDIO_INPUT_REFERENCE); + return &audio_codec; + } + + virtual Display *GetDisplay() override{ + return display_; + } + + Cst816x *GetTouchpad() { + return cst816d_; + } +}; + +DECLARE_BOARD(LilygoTCameraPlusS3Board); diff --git a/main/boards/lilygo-t-cameraplus-s3/pin_config.h b/main/boards/lilygo-t-cameraplus-s3/pin_config.h new file mode 100644 index 00000000..715fa2d8 --- /dev/null +++ b/main/boards/lilygo-t-cameraplus-s3/pin_config.h @@ -0,0 +1,100 @@ +/* + * @Description: None + * @version: V1.0.0 + * @Author: None + * @Date: 2023-08-16 14:24:03 + * @LastEditors: LILYGO_L + * @LastEditTime: 2023-12-12 10:12:31 + * @License: GPL 3.0 + */ +#pragma once + +// microSD +#define SD_CS 21 +#define SD_SCLK 36 +#define SD_MOSI 35 +#define SD_MISO 37 + +// SPI +#define SCLK 36 +#define MOSI 35 +#define MISO 37 + +// MAX98357A +#define MAX98357A_BCLK 41 +#define MAX98357A_LRCLK 42 +#define MAX98357A_DOUT 38 + +// MSM261 +#define MSM261_BCLK 18 +#define MSM261_WS 39 +#define MSM261_DIN 40 + +// FP-133H01D +#define LCD_WIDTH 240 +#define LCD_HEIGHT 240 +#define LCD_BL 46 +#define LCD_MOSI 35 +#define LCD_SCLK 36 +#define LCD_CS 34 +#define LCD_DC 45 +#define LCD_RST 33 + +// SY6970 +#define SY6970_SDA 1 +#define SY6970_SCL 2 +#define SY6970_Address 0x6A +#define SY6970_INT 47 + +// IIC +#define IIC_SDA 1 +#define IIC_SCL 2 + +// OV2640 +#define OV2640_PWDN -1 +#define OV2640_RESET 3 +#define OV2640_XCLK 7 +#define OV2640_SIOD 1 +#define OV2640_SIOC 2 +#define OV2640_D7 6 +#define OV2640_D6 8 +#define OV2640_D5 9 +#define OV2640_D4 11 +#define OV2640_D3 13 +#define OV2640_D2 15 +#define OV2640_D1 14 +#define OV2640_D0 12 +#define OV2640_VSYNC 4 +#define OV2640_HREF 5 +#define OV2640_PCLK 10 + +#define PWDN_GPIO_NUM -1 +#define RESET_GPIO_NUM 3 +#define XCLK_GPIO_NUM 7 +#define SIOD_GPIO_NUM 1 +#define SIOC_GPIO_NUM 2 + +#define Y9_GPIO_NUM 6 +#define Y8_GPIO_NUM 8 +#define Y7_GPIO_NUM 9 +#define Y6_GPIO_NUM 11 +#define Y5_GPIO_NUM 13 +#define Y4_GPIO_NUM 15 +#define Y3_GPIO_NUM 14 +#define Y2_GPIO_NUM 12 +#define VSYNC_GPIO_NUM 4 +#define HREF_GPIO_NUM 5 +#define PCLK_GPIO_NUM 10 + +// CST816 +#define CST816_Address 0x15 +#define TP_SDA 1 +#define TP_SCL 2 +#define TP_RST 48 +#define TP_INT 47 + +// AP1511B +#define AP1511B_FBC 16 + +// KEY +#define KEY1 17 diff --git a/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.cc b/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.cc new file mode 100644 index 00000000..95f817a0 --- /dev/null +++ b/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.cc @@ -0,0 +1,132 @@ +#include "tcamerapluss3_audio_codec.h" + +#include +#include +#include +#include + +static const char TAG[] = "Tcamerapluss3AudioCodec"; + +Tcamerapluss3AudioCodec::Tcamerapluss3AudioCodec(int input_sample_rate, int output_sample_rate, + gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, + gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data, + bool input_reference) { + duplex_ = true; // 是否双工 + input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 + input_channels_ = input_reference_ ? 2 : 1; // 输入通道数 + input_sample_rate_ = input_sample_rate; + output_sample_rate_ = output_sample_rate; + + CreateVoiceHardware(mic_bclk, mic_ws, mic_data, spkr_bclk, spkr_lrclk, spkr_data); + + ESP_LOGI(TAG, "Tcamerapluss3AudioCodec initialized"); +} + +Tcamerapluss3AudioCodec::~Tcamerapluss3AudioCodec() { + audio_codec_delete_codec_if(in_codec_if_); + audio_codec_delete_ctrl_if(in_ctrl_if_); + audio_codec_delete_codec_if(out_codec_if_); + audio_codec_delete_ctrl_if(out_ctrl_if_); + audio_codec_delete_gpio_if(gpio_if_); + audio_codec_delete_data_if(data_if_); +} + +void Tcamerapluss3AudioCodec::CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, + gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data) { + + i2s_chan_config_t mic_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); + mic_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer + i2s_chan_config_t spkr_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_1, I2S_ROLE_MASTER); + spkr_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer + + ESP_ERROR_CHECK(i2s_new_channel(&mic_chan_config, NULL, &rx_handle_)); + ESP_ERROR_CHECK(i2s_new_channel(&spkr_chan_config, &tx_handle_, NULL)); + + i2s_std_config_t mic_config = { + .clk_cfg = { + .sample_rate_hz = (uint32_t)output_sample_rate_, + .clk_src = I2S_CLK_SRC_DEFAULT, + .mclk_multiple = I2S_MCLK_MULTIPLE_256, + #ifdef I2S_HW_VERSION_2 + .ext_clk_freq_hz = 0, + #endif + }, + .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = mic_bclk, + .ws = mic_ws, + .dout = I2S_GPIO_UNUSED, + .din = mic_data, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = true // 默认右通道 + } + } + }; + + i2s_std_config_t spkr_config = { + .clk_cfg ={ + .sample_rate_hz = static_cast(11025), + .clk_src = I2S_CLK_SRC_DEFAULT, + .ext_clk_freq_hz = 0, + .mclk_multiple = I2S_MCLK_MULTIPLE_256, + }, + .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), + .gpio_cfg ={ + .mclk = I2S_GPIO_UNUSED, + .bclk = spkr_bclk, + .ws = spkr_lrclk, + .dout = spkr_data, + .din = I2S_GPIO_UNUSED, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false + } + } + }; + + ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &mic_config)); + ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &spkr_config)); + ESP_LOGI(TAG, "Voice hardware created"); +} + +void Tcamerapluss3AudioCodec::SetOutputVolume(int volume) { + volume_ = volume; + AudioCodec::SetOutputVolume(volume); +} + +void Tcamerapluss3AudioCodec::EnableInput(bool enable) { + AudioCodec::EnableInput(enable); +} + +void Tcamerapluss3AudioCodec::EnableOutput(bool enable) { + AudioCodec::EnableOutput(enable); +} + +int Tcamerapluss3AudioCodec::Read(int16_t *dest, int samples){ + if (input_enabled_){ + size_t bytes_read; + i2s_channel_read(rx_handle_, dest, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY); + } + return samples; +} + +void AdjustTcamerapluss3Volume(const int16_t *input_data, int16_t *output_data, size_t samples, float volume){ + for (size_t i = 0; i < samples; i++){ + output_data[i] = (float)input_data[i] * volume; + } +} + +int Tcamerapluss3AudioCodec::Write(const int16_t *data, int samples){ + if (output_enabled_){ + size_t bytes_read; + auto output_data = (int16_t *)malloc(samples * sizeof(int16_t)); + AdjustTcamerapluss3Volume(data, output_data, samples, (float)(volume_ / 100.0)); + i2s_channel_write(tx_handle_, output_data, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY); + free(output_data); + } + return samples; +} diff --git a/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.h b/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.h new file mode 100644 index 00000000..8c3948b6 --- /dev/null +++ b/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.h @@ -0,0 +1,37 @@ +#ifndef _TCIRCLES3_AUDIO_CODEC_H +#define _TCIRCLES3_AUDIO_CODEC_H + +#include "audio_codecs/audio_codec.h" + +#include +#include + +class Tcamerapluss3AudioCodec : public AudioCodec { +private: + const audio_codec_data_if_t *data_if_ = nullptr; + const audio_codec_ctrl_if_t *out_ctrl_if_ = nullptr; + const audio_codec_if_t *out_codec_if_ = nullptr; + const audio_codec_ctrl_if_t *in_ctrl_if_ = nullptr; + const audio_codec_if_t *in_codec_if_ = nullptr; + const audio_codec_gpio_if_t *gpio_if_ = nullptr; + + uint32_t volume_ = 70; + + void CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data,gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data); + + virtual int Read(int16_t *dest, int samples) override; + virtual int Write(const int16_t *data, int samples) override; + +public: + Tcamerapluss3AudioCodec(int input_sample_rate, int output_sample_rate, + gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, + gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data, + bool input_reference); + virtual ~Tcamerapluss3AudioCodec(); + + virtual void SetOutputVolume(int volume) override; + virtual void EnableInput(bool enable) override; + virtual void EnableOutput(bool enable) override; +}; + +#endif // _BOX_AUDIO_CODEC_H diff --git a/main/boards/lilygo-t-circle-s3/lilygo-t-circle-s3.cc b/main/boards/lilygo-t-circle-s3/lilygo-t-circle-s3.cc index c716837f..62062f48 100644 --- a/main/boards/lilygo-t-circle-s3/lilygo-t-circle-s3.cc +++ b/main/boards/lilygo-t-circle-s3/lilygo-t-circle-s3.cc @@ -1,5 +1,5 @@ #include "wifi_board.h" -#include "audio_codecs/tcircles3_audio_codec.h" +#include "tcircles3_audio_codec.h" #include "display/lcd_display.h" #include "application.h" #include "button.h" diff --git a/main/audio_codecs/tcircles3_audio_codec.cc b/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.cc similarity index 85% rename from main/audio_codecs/tcircles3_audio_codec.cc rename to main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.cc index d85fe1e4..0b49959a 100644 --- a/main/audio_codecs/tcircles3_audio_codec.cc +++ b/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.cc @@ -54,7 +54,14 @@ void Tcircles3AudioCodec::CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mi ESP_ERROR_CHECK(i2s_new_channel(&spkr_chan_config, &tx_handle_, NULL)); i2s_std_config_t mic_config = { - .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(static_cast(input_sample_rate_)), + .clk_cfg = { + .sample_rate_hz = (uint32_t)output_sample_rate_, + .clk_src = I2S_CLK_SRC_DEFAULT, + .mclk_multiple = I2S_MCLK_MULTIPLE_256, + #ifdef I2S_HW_VERSION_2 + .ext_clk_freq_hz = 0, + #endif + }, .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), .gpio_cfg ={ .mclk = I2S_GPIO_UNUSED, @@ -71,7 +78,14 @@ void Tcircles3AudioCodec::CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mi }; i2s_std_config_t spkr_config = { - .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(static_cast(11025)), + .clk_cfg ={ + .sample_rate_hz = static_cast(11025), + .clk_src = I2S_CLK_SRC_DEFAULT, + .mclk_multiple = I2S_MCLK_MULTIPLE_256, + #ifdef I2S_HW_VERSION_2 + .ext_clk_freq_hz = 0, + #endif + }, .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), .gpio_cfg ={ .mclk = I2S_GPIO_UNUSED, @@ -118,7 +132,7 @@ int Tcircles3AudioCodec::Read(int16_t *dest, int samples){ return samples; } -void AdjustVolume(const int16_t *input_data, int16_t *output_data, size_t samples, float volume){ +void AdjustTcircles3Volume(const int16_t *input_data, int16_t *output_data, size_t samples, float volume){ for (size_t i = 0; i < samples; i++){ output_data[i] = (float)input_data[i] * volume; } @@ -128,7 +142,7 @@ int Tcircles3AudioCodec::Write(const int16_t *data, int samples){ if (output_enabled_){ size_t bytes_read; auto output_data = (int16_t *)malloc(samples * sizeof(int16_t)); - AdjustVolume(data, output_data, samples, (float)(volume_ / 100.0)); + AdjustTcircles3Volume(data, output_data, samples, (float)(volume_ / 100.0)); i2s_channel_write(tx_handle_, output_data, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY); free(output_data); } diff --git a/main/audio_codecs/tcircles3_audio_codec.h b/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.h similarity index 97% rename from main/audio_codecs/tcircles3_audio_codec.h rename to main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.h index f68f818d..3c050dc2 100644 --- a/main/audio_codecs/tcircles3_audio_codec.h +++ b/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.h @@ -1,7 +1,7 @@ #ifndef _TCIRCLES3_AUDIO_CODEC_H #define _TCIRCLES3_AUDIO_CODEC_H -#include "audio_codec.h" +#include "audio_codecs/audio_codec.h" #include #include