From da746c7efe0c15404d0f16b3614970e3580c6c59 Mon Sep 17 00:00:00 2001 From: Konan Date: Sat, 18 Oct 2025 12:49:17 +0700 Subject: [PATCH] feat: Add ESP32-C3 Mini Konan board support --- main/CMakeLists.txt | 9 +- main/Kconfig.projbuild | 3 + main/audio/codecs/max98357a_inmp441_codec.cc | 196 ++++++++++++++++++ main/audio/codecs/max98357a_inmp441_codec.h | 27 +++ main/boards/esp32-c3-mini-konan/config.h | 30 +++ main/boards/esp32-c3-mini-konan/config.json | 32 +++ .../esp32_c3_mini_konan_board.cc | 175 ++++++++++++++++ .../esp32-c3-mini-konan/partitions_4mb.csv | 5 + .../lvgl_display/jpg/image_to_jpeg.cpp | 8 + main/display/lvgl_display/jpg/image_to_jpeg.h | 4 +- main/idf_component.yml | 6 +- 11 files changed, 488 insertions(+), 7 deletions(-) create mode 100644 main/audio/codecs/max98357a_inmp441_codec.cc create mode 100644 main/audio/codecs/max98357a_inmp441_codec.h create mode 100644 main/boards/esp32-c3-mini-konan/config.h create mode 100644 main/boards/esp32-c3-mini-konan/config.json create mode 100644 main/boards/esp32-c3-mini-konan/esp32_c3_mini_konan_board.cc create mode 100644 main/boards/esp32-c3-mini-konan/partitions_4mb.csv diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 94276a4729..3ea69b936e 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -8,6 +8,7 @@ set(SOURCES "audio/audio_codec.cc" "audio/codecs/es8388_audio_codec.cc" "audio/codecs/es8389_audio_codec.cc" "audio/codecs/dummy_audio_codec.cc" + "audio/codecs/max98357a_inmp441_codec.cc" "audio/processors/audio_debugger.cc" "led/single_led.cc" "led/circular_strip.cc" @@ -192,6 +193,10 @@ elseif(CONFIG_BOARD_TYPE_XMINI_C3) set(BOARD_TYPE "xmini-c3") set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) set(BUILTIN_ICON_FONT font_awesome_14_1) +elseif(CONFIG_BOARD_TYPE_ESP32_C3_MINI_KONAN) + set(BOARD_TYPE "esp32-c3-mini-konan") + set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) + set(BUILTIN_ICON_FONT font_awesome_14_1) elseif(CONFIG_BOARD_TYPE_ESP32S3_KORVO2_V3) set(BOARD_TYPE "esp32s3-korvo2-v3") set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) @@ -648,8 +653,8 @@ endif() file(GLOB COMMON_SOUNDS ${CMAKE_CURRENT_SOURCE_DIR}/assets/common/*.ogg) -# If target chip is ESP32, exclude specific files to avoid build errors -if(CONFIG_IDF_TARGET_ESP32) +# If target chip is ESP32 or ESP32-C3, exclude specific files to avoid build errors +if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32C3) list(REMOVE_ITEM SOURCES "audio/codecs/box_audio_codec.cc" "audio/codecs/es8388_audio_codec.cc" "audio/codecs/es8389_audio_codec.cc" diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 78e16d49f8..fd8a3efc0d 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -144,6 +144,9 @@ choice BOARD_TYPE config BOARD_TYPE_XMINI_C3 bool "Xmini C3" depends on IDF_TARGET_ESP32C3 + config BOARD_TYPE_ESP32_C3_MINI_KONAN + bool "ESP32-C3 Mini Konan (MAX98357A + INMP441)" + depends on IDF_TARGET_ESP32C3 config BOARD_TYPE_ESP32S3_KORVO2_V3 bool "ESP32S3 KORVO2 V3" depends on IDF_TARGET_ESP32S3 diff --git a/main/audio/codecs/max98357a_inmp441_codec.cc b/main/audio/codecs/max98357a_inmp441_codec.cc new file mode 100644 index 0000000000..09e43b1a63 --- /dev/null +++ b/main/audio/codecs/max98357a_inmp441_codec.cc @@ -0,0 +1,196 @@ +#include "max98357a_inmp441_codec.h" +#include +#include + +#define TAG "Max98357aInmp441Codec" + +Max98357aInmp441Codec::Max98357aInmp441Codec(int input_sample_rate, int output_sample_rate, + gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, + gpio_num_t sd_mode_pin) : sd_mode_pin_(sd_mode_pin) { + + duplex_ = true; + input_reference_ = false; + input_channels_ = 1; + output_channels_ = 1; + input_sample_rate_ = input_sample_rate; + output_sample_rate_ = output_sample_rate; + input_gain_ = 0.0; + + // Configure SD_MODE pin for MAX98357A if provided + if (sd_mode_pin_ != GPIO_NUM_NC) { + gpio_config_t io_conf = {}; + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pin_bit_mask = (1ULL << sd_mode_pin_); + io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + io_conf.pull_up_en = GPIO_PULLUP_DISABLE; + gpio_config(&io_conf); + gpio_set_level(sd_mode_pin_, 1); // Enable MAX98357A + } + + CreateDuplexChannels(bclk, ws, dout, din); + ESP_LOGI(TAG, "MAX98357A + INMP441 codec initialized"); +} + +Max98357aInmp441Codec::~Max98357aInmp441Codec() { + if (tx_handle_) { + i2s_channel_disable(tx_handle_); + i2s_del_channel(tx_handle_); + } + if (rx_handle_) { + i2s_channel_disable(rx_handle_); + i2s_del_channel(rx_handle_); + } + + // Shutdown MAX98357A + if (sd_mode_pin_ != GPIO_NUM_NC) { + gpio_set_level(sd_mode_pin_, 0); + } +} + +void Max98357aInmp441Codec::CreateDuplexChannels(gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { + // Create I2S channels for duplex operation + i2s_chan_config_t chan_cfg = { + .id = I2S_NUM_0, + .role = I2S_ROLE_MASTER, + .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, + .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, + .auto_clear_after_cb = true, + .auto_clear_before_cb = false, + .intr_priority = 0, + }; + ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); + + // Configure TX (output to MAX98357A) + i2s_std_config_t tx_std_cfg = { + .clk_cfg = { + .sample_rate_hz = (uint32_t)output_sample_rate_, + .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_MONO), + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = bclk, + .ws = ws, + .dout = dout, + .din = I2S_GPIO_UNUSED, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false + } + } + }; + ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &tx_std_cfg)); + + // Configure RX (input from INMP441) + i2s_std_config_t rx_std_cfg = { + .clk_cfg = { + .sample_rate_hz = (uint32_t)input_sample_rate_, + .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_32BIT, I2S_SLOT_MODE_MONO), + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = bclk, + .ws = ws, + .dout = I2S_GPIO_UNUSED, + .din = din, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false + } + } + }; + ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &rx_std_cfg)); + + ESP_LOGI(TAG, "Duplex I2S channels created"); +} + +void Max98357aInmp441Codec::SetOutputVolume(int volume) { + // MAX98357A doesn't support software volume control + // Volume is controlled by SD_MODE pin (3 levels) or external circuit + ESP_LOGW(TAG, "MAX98357A doesn't support software volume control"); + AudioCodec::SetOutputVolume(volume); +} + +void Max98357aInmp441Codec::EnableInput(bool enable) { + if (enable == input_enabled_) { + return; + } + if (enable) { + ESP_ERROR_CHECK(i2s_channel_enable(rx_handle_)); + ESP_LOGI(TAG, "INMP441 input enabled"); + } else { + ESP_ERROR_CHECK(i2s_channel_disable(rx_handle_)); + ESP_LOGI(TAG, "INMP441 input disabled"); + } + AudioCodec::EnableInput(enable); +} + +void Max98357aInmp441Codec::EnableOutput(bool enable) { + if (enable == output_enabled_) { + return; + } + if (enable) { + ESP_ERROR_CHECK(i2s_channel_enable(tx_handle_)); + if (sd_mode_pin_ != GPIO_NUM_NC) { + gpio_set_level(sd_mode_pin_, 1); + } + ESP_LOGI(TAG, "MAX98357A output enabled"); + } else { + ESP_ERROR_CHECK(i2s_channel_disable(tx_handle_)); + if (sd_mode_pin_ != GPIO_NUM_NC) { + gpio_set_level(sd_mode_pin_, 0); + } + ESP_LOGI(TAG, "MAX98357A output disabled"); + } + AudioCodec::EnableOutput(enable); +} + +int Max98357aInmp441Codec::Read(int16_t* dest, int samples) { + if (!input_enabled_) { + return 0; + } + + size_t bytes_read = 0; + // INMP441 outputs 32-bit data, we need to convert to 16-bit + int32_t temp_buffer[AUDIO_CODEC_DMA_FRAME_NUM]; + size_t bytes_to_read = samples * sizeof(int32_t); + + esp_err_t ret = i2s_channel_read(rx_handle_, temp_buffer, bytes_to_read, &bytes_read, portMAX_DELAY); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "I2S read failed: %d", ret); + return 0; + } + + // Convert 32-bit to 16-bit (take upper 16 bits) + int samples_read = bytes_read / sizeof(int32_t); + for (int i = 0; i < samples_read; i++) { + dest[i] = (int16_t)(temp_buffer[i] >> 16); + } + + return samples_read; +} + +int Max98357aInmp441Codec::Write(const int16_t* data, int samples) { + if (!output_enabled_) { + return 0; + } + + size_t bytes_written = 0; + size_t bytes_to_write = samples * sizeof(int16_t); + + esp_err_t ret = i2s_channel_write(tx_handle_, data, bytes_to_write, &bytes_written, portMAX_DELAY); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "I2S write failed: %d", ret); + return 0; + } + + return bytes_written / sizeof(int16_t); +} diff --git a/main/audio/codecs/max98357a_inmp441_codec.h b/main/audio/codecs/max98357a_inmp441_codec.h new file mode 100644 index 0000000000..863b1426fe --- /dev/null +++ b/main/audio/codecs/max98357a_inmp441_codec.h @@ -0,0 +1,27 @@ +#ifndef _MAX98357A_INMP441_CODEC_H +#define _MAX98357A_INMP441_CODEC_H + +#include "audio_codec.h" +#include + +class Max98357aInmp441Codec : public AudioCodec { +private: + gpio_num_t sd_mode_pin_; + + void CreateDuplexChannels(gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); + + virtual int Read(int16_t* dest, int samples) override; + virtual int Write(const int16_t* data, int samples) override; + +public: + Max98357aInmp441Codec(int input_sample_rate, int output_sample_rate, + gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, + gpio_num_t sd_mode_pin = GPIO_NUM_NC); + virtual ~Max98357aInmp441Codec(); + + virtual void SetOutputVolume(int volume) override; + virtual void EnableInput(bool enable) override; + virtual void EnableOutput(bool enable) override; +}; + +#endif // _MAX98357A_INMP441_CODEC_H diff --git a/main/boards/esp32-c3-mini-konan/config.h b/main/boards/esp32-c3-mini-konan/config.h new file mode 100644 index 0000000000..3f63372703 --- /dev/null +++ b/main/boards/esp32-c3-mini-konan/config.h @@ -0,0 +1,30 @@ +#ifndef _BOARD_CONFIG_H_ +#define _BOARD_CONFIG_H_ + +#include + +#define AUDIO_INPUT_SAMPLE_RATE 16000 +#define AUDIO_OUTPUT_SAMPLE_RATE 16000 + +// I2S pins for MAX98357A (output) and INMP441 (input) +#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_4 // Bit Clock +#define AUDIO_I2S_GPIO_WS GPIO_NUM_5 // Word Select (LRC) +#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_6 // Data Out to MAX98357A +#define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 // Data In from INMP441 + +// MAX98357A gain control (optional, can be tied to VDD/GND for fixed gain) +#define MAX98357A_SD_MODE_PIN GPIO_NUM_8 // Shutdown/Gain control + +// Built-in LED and button +#define BUILTIN_LED_GPIO GPIO_NUM_2 +#define BOOT_BUTTON_GPIO GPIO_NUM_9 + +// Display configuration (SSD1306 OLED) +#define DISPLAY_I2C_SDA_PIN GPIO_NUM_10 +#define DISPLAY_I2C_SCL_PIN GPIO_NUM_3 +#define DISPLAY_WIDTH 128 +#define DISPLAY_HEIGHT 64 +#define DISPLAY_MIRROR_X true +#define DISPLAY_MIRROR_Y true + +#endif // _BOARD_CONFIG_H_ diff --git a/main/boards/esp32-c3-mini-konan/config.json b/main/boards/esp32-c3-mini-konan/config.json new file mode 100644 index 0000000000..77e6d07df3 --- /dev/null +++ b/main/boards/esp32-c3-mini-konan/config.json @@ -0,0 +1,32 @@ +{ + "target": "esp32c3", + "builds": [ + { + "name": "esp32-c3-mini-konan", + "sdkconfig_append": [ + "CONFIG_PM_ENABLE=y", + "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y", + "CONFIG_USE_ESP_WAKE_WORD=y", + "CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y", + "CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER=n", + "CONFIG_LVGL_USE_DRAW_SW=y", + "CONFIG_LVGL_USE_DRAW_VGLITE=n", + "CONFIG_LVGL_USE_DRAW_SDL=n", + "CONFIG_LVGL_USE_FREETYPE=n", + "CONFIG_SPIRAM=n", + "CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y", + "CONFIG_PARTITION_TABLE_CUSTOM=y", + "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"main/boards/esp32-c3-mini-konan/partitions_4mb.csv\"", + "CONFIG_COMPILER_OPTIMIZATION_SIZE=y", + "CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y", + "CONFIG_LOG_DEFAULT_LEVEL_INFO=y", + "CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y", + "CONFIG_BT_ENABLED=n", + "CONFIG_BT_BLUEDROID_ENABLED=n", + "CONFIG_BT_NIMBLE_ENABLED=n", + "CONFIG_LWIP_IPV6=n", + "CONFIG_LWIP_NETIF_LOOPBACK=n" + ] + } + ] +} diff --git a/main/boards/esp32-c3-mini-konan/esp32_c3_mini_konan_board.cc b/main/boards/esp32-c3-mini-konan/esp32_c3_mini_konan_board.cc new file mode 100644 index 0000000000..e94ff70163 --- /dev/null +++ b/main/boards/esp32-c3-mini-konan/esp32_c3_mini_konan_board.cc @@ -0,0 +1,175 @@ +#include "wifi_board.h" +#include "codecs/max98357a_inmp441_codec.h" +#include "display/oled_display.h" +#include "application.h" +#include "button.h" +#include "led/single_led.h" +#include "mcp_server.h" +#include "settings.h" +#include "config.h" +#include "power_save_timer.h" +#include "press_to_talk_mcp_tool.h" + +#include +#include +#include +#include +#include +#include + +#define TAG "Esp32C3MiniKonanBoard" + +class Esp32C3MiniKonanBoard : public WifiBoard { +private: + i2c_master_bus_handle_t display_i2c_bus_; + esp_lcd_panel_io_handle_t panel_io_ = nullptr; + esp_lcd_panel_handle_t panel_ = nullptr; + Display* display_ = nullptr; + Button boot_button_; + PowerSaveTimer* power_save_timer_ = nullptr; + PressToTalkMcpTool* press_to_talk_tool_ = nullptr; + + void InitializePowerSaveTimer() { + power_save_timer_ = new PowerSaveTimer(160, 300); + power_save_timer_->OnEnterSleepMode([this]() { + GetDisplay()->SetPowerSaveMode(true); + }); + power_save_timer_->OnExitSleepMode([this]() { + GetDisplay()->SetPowerSaveMode(false); + }); + power_save_timer_->SetEnabled(true); + } + + void InitializeDisplayI2c() { + i2c_master_bus_config_t i2c_bus_cfg = { + .i2c_port = I2C_NUM_0, + .sda_io_num = DISPLAY_I2C_SDA_PIN, + .scl_io_num = DISPLAY_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, &display_i2c_bus_)); + } + + void InitializeSsd1306Display() { + esp_lcd_panel_io_i2c_config_t io_config = { + .dev_addr = 0x3C, + .on_color_trans_done = nullptr, + .user_ctx = nullptr, + .control_phase_bytes = 1, + .dc_bit_offset = 6, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + .flags = { + .dc_low_on_data = 0, + .disable_control_phase = 0, + }, + .scl_speed_hz = 400 * 1000, + }; + + ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_)); + + ESP_LOGI(TAG, "Install SSD1306 driver"); + esp_lcd_panel_dev_config_t panel_config = {}; + panel_config.reset_gpio_num = -1; + panel_config.bits_per_pixel = 1; + + esp_lcd_panel_ssd1306_config_t ssd1306_config = { + .height = static_cast(DISPLAY_HEIGHT), + }; + panel_config.vendor_config = &ssd1306_config; + + ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); + ESP_LOGI(TAG, "SSD1306 driver installed"); + + ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); + if (esp_lcd_panel_init(panel_) != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize display"); + display_ = new NoDisplay(); + return; + } + + ESP_LOGI(TAG, "Turning display on"); + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); + + display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); + } + + void InitializeButtons() { + boot_button_.OnClick([this]() { + auto& app = Application::GetInstance(); + if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) { + ResetWifiConfiguration(); + } + if (!press_to_talk_tool_ || !press_to_talk_tool_->IsPressToTalkEnabled()) { + app.ToggleChatState(); + } + }); + boot_button_.OnPressDown([this]() { + if (power_save_timer_) { + power_save_timer_->WakeUp(); + } + if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { + Application::GetInstance().StartListening(); + } + }); + boot_button_.OnPressUp([this]() { + if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { + Application::GetInstance().StopListening(); + } + }); + } + + void InitializeTools() { + press_to_talk_tool_ = new PressToTalkMcpTool(); + press_to_talk_tool_->Initialize(); + } + +public: + Esp32C3MiniKonanBoard() : boot_button_(BOOT_BUTTON_GPIO) { + InitializeDisplayI2c(); + InitializeSsd1306Display(); + InitializeButtons(); + InitializePowerSaveTimer(); + InitializeTools(); + + esp_efuse_write_field_bit(ESP_EFUSE_VDD_SPI_AS_GPIO); + ESP_LOGI(TAG, "ESP32-C3 Mini Konan board initialized"); + } + + virtual Led* GetLed() override { + static SingleLed led(BUILTIN_LED_GPIO); + return &led; + } + + virtual Display* GetDisplay() override { + return display_; + } + + virtual AudioCodec* GetAudioCodec() override { + static Max98357aInmp441Codec 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, + MAX98357A_SD_MODE_PIN + ); + return &audio_codec; + } + + virtual void SetPowerSaveMode(bool enabled) override { + if (!enabled) { + power_save_timer_->WakeUp(); + } + WifiBoard::SetPowerSaveMode(enabled); + } +}; + +DECLARE_BOARD(Esp32C3MiniKonanBoard); diff --git a/main/boards/esp32-c3-mini-konan/partitions_4mb.csv b/main/boards/esp32-c3-mini-konan/partitions_4mb.csv new file mode 100644 index 0000000000..108f3d3765 --- /dev/null +++ b/main/boards/esp32-c3-mini-konan/partitions_4mb.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 16K, +phy_init, data, phy, 0xd000, 4K, +factory, app, factory, 0x10000, 3520K, +assets, data, spiffs, 0x380000,512K, diff --git a/main/display/lvgl_display/jpg/image_to_jpeg.cpp b/main/display/lvgl_display/jpg/image_to_jpeg.cpp index 8ea05e1a34..0f8f58263d 100644 --- a/main/display/lvgl_display/jpg/image_to_jpeg.cpp +++ b/main/display/lvgl_display/jpg/image_to_jpeg.cpp @@ -13,6 +13,14 @@ #define TAG "image_to_jpeg" +// Define V4L2 pixel formats (from linux/videodev2.h) +#define V4L2_PIX_FMT_GREY 0x59455247 /* 8 Greyscale */ +#define V4L2_PIX_FMT_YUYV 0x56595559 /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_UYVY 0x59565955 /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YUV422P 0x50323234 /* 16 YVU422 planar */ +#define V4L2_PIX_FMT_RGB24 0x33424752 /* 24 RGB-8-8-8 */ +#define V4L2_PIX_FMT_RGB565 0x35424752 /* 16 RGB-5-6-5 */ + static void* malloc_psram(size_t size) { void* p = malloc(size); if (p) diff --git a/main/display/lvgl_display/jpg/image_to_jpeg.h b/main/display/lvgl_display/jpg/image_to_jpeg.h index 61898c2d87..d1f41f4e00 100644 --- a/main/display/lvgl_display/jpg/image_to_jpeg.h +++ b/main/display/lvgl_display/jpg/image_to_jpeg.h @@ -6,9 +6,9 @@ #include #include -#include -typedef uint32_t v4l2_pix_fmt_t; // see linux/videodev2.h for details +// Define v4l2_pix_fmt_t without linux/videodev2.h dependency +typedef uint32_t v4l2_pix_fmt_t; #ifdef __cplusplus extern "C" { diff --git a/main/idf_component.yml b/main/idf_component.yml index 7edfe19310..cbf3b6c106 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -29,7 +29,7 @@ dependencies: espressif/esp_video: version: '==1.2.0' # for compatibility. update version may need to modify this project code. rules: - - if: target not in [esp32] + - if: target in [esp32s3, esp32p4] espressif/esp_lcd_touch_ft5x06: ~1.0.7 espressif/esp_lcd_touch_gt911: ^1 espressif/esp_lcd_touch_gt1151: ^1 @@ -45,7 +45,7 @@ dependencies: txp666/otto-emoji-gif-component: version: 1.0.2 rules: - - if: target not in [esp32c5] + - if: target in [esp32s3] espressif/adc_battery_estimation: ^0.2.0 espressif/esp_new_jpeg: ^0.6.1 @@ -93,4 +93,4 @@ dependencies: ## Required IDF version idf: - version: '>=5.5.0' + version: '>=5.3.0'