From 041a0fa9ee86c8499b40a84defa9da524682e9f1 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Tue, 10 Jun 2025 11:42:10 +0800 Subject: [PATCH] feat(cam): add dvp example for ESP32S3-EYE --- .../dvp/src/esp_cam_ctlr_dvp_gdma.c | 1 + examples/peripherals/.build-test-rules.yml | 11 + .../sensor_init/idf_component.yml | 2 +- .../camera/dvp_spi_lcd/CMakeLists.txt | 8 + .../peripherals/camera/dvp_spi_lcd/README.md | 139 +++++++++++ .../camera/dvp_spi_lcd/main/CMakeLists.txt | 4 + .../camera/dvp_spi_lcd/main/Kconfig.projbuild | 33 +++ .../dvp_spi_lcd/main/dvp_spi_lcd_main.c | 226 ++++++++++++++++++ .../camera/dvp_spi_lcd/main/example_config.h | 71 ++++++ .../camera/dvp_spi_lcd/main/idf_component.yml | 3 + .../camera/dvp_spi_lcd/pytest_dvp_spi_lcd.py | 11 + .../camera/dvp_spi_lcd/sdkconfig.defaults | 1 + .../dvp_spi_lcd/sdkconfig.defaults.esp32p4 | 2 + .../dvp_spi_lcd/sdkconfig.defaults.esp32s3 | 2 + 14 files changed, 513 insertions(+), 1 deletion(-) create mode 100644 examples/peripherals/camera/dvp_spi_lcd/CMakeLists.txt create mode 100644 examples/peripherals/camera/dvp_spi_lcd/README.md create mode 100644 examples/peripherals/camera/dvp_spi_lcd/main/CMakeLists.txt create mode 100644 examples/peripherals/camera/dvp_spi_lcd/main/Kconfig.projbuild create mode 100644 examples/peripherals/camera/dvp_spi_lcd/main/dvp_spi_lcd_main.c create mode 100644 examples/peripherals/camera/dvp_spi_lcd/main/example_config.h create mode 100644 examples/peripherals/camera/dvp_spi_lcd/main/idf_component.yml create mode 100644 examples/peripherals/camera/dvp_spi_lcd/pytest_dvp_spi_lcd.py create mode 100644 examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults create mode 100644 examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32p4 create mode 100644 examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32s3 diff --git a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_gdma.c b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_gdma.c index f05eb25545..bfb386c5a2 100644 --- a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_gdma.c +++ b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_gdma.c @@ -117,6 +117,7 @@ esp_err_t esp_cam_ctlr_dvp_dma_init(esp_cam_ctlr_dvp_dma_t *dma, uint32_t burst_ ESP_LOGD(TAG, "alignment_size: %d, dma->desc_count: %d, dma->desc_size: %d", alignment_size, dma->desc_count, dma->desc_size); dma->desc = heap_caps_aligned_alloc(alignment_size, dma->desc_size, DVP_GDMA_DESC_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(dma->desc, ESP_ERR_NO_MEM, fail1, TAG, "no mem for DVP DMA descriptor"); return ESP_OK; diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index d5b71903ae..fb9144b95f 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -46,6 +46,17 @@ examples/peripherals/camera/dvp_isp_dsi: - esp_lcd - esp_driver_cam +examples/peripherals/camera/dvp_spi_lcd: + disable: + - if: SOC_LCDCAM_CAM_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32s3" + temporary: true + reason: lack of runners + depends_components: + - esp_lcd + - esp_driver_cam + examples/peripherals/camera/mipi_isp_dsi: disable: - if: SOC_MIPI_CSI_SUPPORTED != 1 or SOC_MIPI_DSI_SUPPORTED != 1 diff --git a/examples/peripherals/camera/common_components/sensor_init/idf_component.yml b/examples/peripherals/camera/common_components/sensor_init/idf_component.yml index 1881aa5e99..a5d6718e18 100644 --- a/examples/peripherals/camera/common_components/sensor_init/idf_component.yml +++ b/examples/peripherals/camera/common_components/sensor_init/idf_component.yml @@ -1,4 +1,4 @@ dependencies: - espressif/esp_cam_sensor: "^0.6.1" + espressif/esp_cam_sensor: "^1.1.0" idf: version: ">=5.3.0" diff --git a/examples/peripherals/camera/dvp_spi_lcd/CMakeLists.txt b/examples/peripherals/camera/dvp_spi_lcd/CMakeLists.txt new file mode 100644 index 0000000000..87b0236748 --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +idf_build_set_property(MINIMAL_BUILD ON) +project(dvp_spi_lcd) diff --git a/examples/peripherals/camera/dvp_spi_lcd/README.md b/examples/peripherals/camera/dvp_spi_lcd/README.md new file mode 100644 index 0000000000..6a69880dc2 --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/README.md @@ -0,0 +1,139 @@ +| Supported Targets | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | + + +# DVP Camera display via LCD example + +## Overview + +This example demonstrates how to use the esp_driver_cam component to capture DVP camera sensor signals and display it via LCD interface. This example will auto-detect camera sensors via [ESP camera sensor driver](https://components.espressif.com/components/espressif/esp_cam_sensor) and capture camera sensor signals via DVP interface and display it via LCD interface. + +## Usage + +The subsections below give only absolutely necessary information. For full steps to configure ESP-IDF and use it to build and run projects, see [ESP-IDF Getting Started](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html#get-started). + + +### Hardware Required + +- ESP32S3 devkit with OV2640 camera sensor and ST7789 LCD screen +- or an ESP32S3-EYE dev-kit + +You can also connect camera sensors and LCD screens from other vendors to the ESP chip, you can find corresponding camera or LCD drivers from [ESP Component Registry](https://components.espressif.com), or design your own customized drivers. + + + GND GND + ┌────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────┐ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ┌───────────────┴─────────────┴──────────────────┐ │ + │ │ │ ┌──────────┴───────────┐ + │ │ │ LCD MOSI │ │ + │ │ ├───────────────────────────┤ │ + ┌───────────┴─────────┐ │ │ │ │ + │ │ │ │ LCD CLK │ │ + │ │ │ ├───────────────────────────┤ │ + │ │ XCLK │ ESP_CHIP │ │ │ + │ DVP Camera ├──────────────────────┤ │ LCD CS │ LCD Screen │ + │ │ │ ├───────────────────────────┤ │ + │ │ D0~7 │ │ │ │ + │ ├──────────────────────┤ │ LCD DC │ │ + │ │ │ ├───────────────────────────┤ │ + │ │ PCLK │ │ │ │ + │ ├──────────────────────┤ │ LCD BACKLIGHT │ │ + │ │ │ ├───────────────────────────┤ │ + │ │ VSYNC │ │ │ │ + │ ├──────────────────────┤ │ │ │ + │ │ │ │ │ │ + │ │ DE (HREF) │ │ │ │ + │ ├──────────────────────┤ │ └──────────────────────┘ + │ │ │ │ + └───────┬──┬──────────┘ │ │ + │ │ I2C SCL │ │ + │ └─────────────────────────────────┤ │ + │ I2C SDA │ │ + └────────────────────────────────────┤ │ + └────────────────────────────────────────────────┘ + + +### Set Chip Target + +First of all, your target must be supported by both: + +- **By your ESP-IDF version**: For the full list of supported targets, run: + ``` + idf.py --list-targets + ``` +- **By this example**: For the full list of supported targets, refer to the supported targets table at the top of this README. + +After you make sure that your target is supported, go to your example project directory and [set the chip target](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/tools/idf-py.html#select-the-target-chip-set-target): + +``` +idf.py set-target +``` + +For example, to set esp32-S3 as the chip target, run: + +``` +idf.py set-target esp32s3 +``` + + +### Configure the Project + +For information about Kconfig options, see [Project Configuration](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/kconfig.html) > _Name of relevant section(s)_. + +To conveniently check or modify Kconfig options for this example in a project configuration menu, run: + +``` +idf.py menuconfig +``` + +``` +Set CONFIG_CAMERA_OV2640 to y +``` + +Available options for the camera sensor output horizontal/vertical resolution can be seen in ``menuconfig`` > ``Example Configuration``. + + +### Build and Flash + +Execute the following command to build the project, flash it to your development board, and run the monitor tool to view the serial output: + +``` +idf.py build flash monitor +``` + +This command can be reduced to `idf.py flash monitor`. + +If the above command fails, check the log on the serial monitor which usually provides information on the possible cause of the issue. + +To exit the serial monitor, use `Ctrl` + `]`. + + +## Example Output + +If you see the following console output, your example should be running correctly: + +``` +I (1481) main_task: Calling app_main() +I (278) dvp_spi_lcd: Init SPI bus +I (278) dvp_spi_lcd: New panel IO SPI +I (278) dvp_spi_lcd: New ST7789 panel +I (278) dvp_spi_lcd: Reset and init panel +I (408) dvp_spi_lcd: Turn on display +I (408) dvp_spi_lcd: Screen lit up now! + +``` + + +## Reference + +- Link to the ESP-IDF feature's API reference, for example [ESP-IDF: Camera Controller Driver](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/camera_driver.html) +- [ESP-IDF Getting Started](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html#get-started) +- [Project Configuration](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/kconfig.html) (Kconfig Options) diff --git a/examples/peripherals/camera/dvp_spi_lcd/main/CMakeLists.txt b/examples/peripherals/camera/dvp_spi_lcd/main/CMakeLists.txt new file mode 100644 index 0000000000..e863a9baee --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "dvp_spi_lcd_main.c" + INCLUDE_DIRS "." + REQUIRES esp_mm esp_driver_cam esp_driver_i2c esp_lcd sensor_init + ) diff --git a/examples/peripherals/camera/dvp_spi_lcd/main/Kconfig.projbuild b/examples/peripherals/camera/dvp_spi_lcd/main/Kconfig.projbuild new file mode 100644 index 0000000000..d44ca3210b --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/main/Kconfig.projbuild @@ -0,0 +1,33 @@ +menu "Example Configuration" + + choice EXAMPLE_CAM_HRES + bool "Set camera horizontal resolution" + default EXAMPLE_CAM_HRES_240 + + config EXAMPLE_CAM_HRES_640 + bool "640" + config EXAMPLE_CAM_HRES_240 + bool "240" + endchoice + + config EXAMPLE_CAM_HRES + int + default 640 if EXAMPLE_CAM_HRES_640 + default 240 if EXAMPLE_CAM_HRES_240 + + choice EXAMPLE_CAM_VRES + bool "Set camera vertical resolution" + default EXAMPLE_CAM_VRES_480 if EXAMPLE_CAM_HRES_640 + default EXAMPLE_CAM_VRES_240 if EXAMPLE_CAM_HRES_240 + + config EXAMPLE_CAM_VRES_480 + bool "480" + config EXAMPLE_CAM_VRES_240 + bool "240" + endchoice + + config EXAMPLE_CAM_VRES + int + default 480 if EXAMPLE_CAM_VRES_480 + default 240 if EXAMPLE_CAM_VRES_240 +endmenu diff --git a/examples/peripherals/camera/dvp_spi_lcd/main/dvp_spi_lcd_main.c b/examples/peripherals/camera/dvp_spi_lcd/main/dvp_spi_lcd_main.c new file mode 100644 index 0000000000..ef57a1a2e7 --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/main/dvp_spi_lcd_main.c @@ -0,0 +1,226 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "esp_lcd_panel_ops.h" +#include "esp_cache.h" +#include "driver/i2c_master.h" +#include "esp_cam_ctlr.h" +#include "esp_cam_ctlr_dvp.h" +#include "example_config.h" +#include "driver/ledc.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_vendor.h" +#include "esp_lcd_panel_ops.h" +#include "example_sensor_init.h" + +static const char *TAG = "dvp_spi_lcd"; + +#define BUFFER_SIZE (CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8) + +typedef struct { + esp_lcd_panel_handle_t panel_hdl; + esp_cam_ctlr_trans_t cam_trans; +} example_cam_context_t; + +static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data); +static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data); + +static void lcd_display_init(esp_lcd_panel_handle_t *lcd_panel_hdl, esp_lcd_panel_io_handle_t lcd_io_hdl) +{ + esp_lcd_panel_handle_t panel_handle = NULL; + //----------LEDC initialization------------// + const ledc_timer_config_t lcd_timer = { + .speed_mode = LEDC_LOW_SPEED_MODE, + .duty_resolution = LEDC_TIMER_10_BIT, + .timer_num = EXAMPLE_LEDC_LCD_BACKLIGHT, + .freq_hz = 5000, + .clk_cfg = LEDC_AUTO_CLK + }; + ESP_ERROR_CHECK(ledc_timer_config(&lcd_timer)); + const ledc_channel_config_t lcd_channel = { + .gpio_num = EXAMPLE_LCD_BACKLIGHT, + .speed_mode = LEDC_LOW_SPEED_MODE, + .channel = LEDC_CHANNEL_0, + .timer_sel = EXAMPLE_LEDC_LCD_BACKLIGHT, + .intr_type = LEDC_INTR_DISABLE, + .duty = 0, + .hpoint = 0, + .flags.output_invert = true, + }; + ESP_ERROR_CHECK(ledc_channel_config(&lcd_channel)); + + //----------SPI initialization------------// + ESP_LOGI(TAG, "Init SPI bus"); + const spi_bus_config_t bus_cfg = { + .sclk_io_num = EXAMPLE_LCD_SPI_CLK, + .mosi_io_num = EXAMPLE_LCD_SPI_MOSI, + .miso_io_num = GPIO_NUM_NC, + .quadwp_io_num = GPIO_NUM_NC, + .quadhd_io_num = GPIO_NUM_NC, + .max_transfer_sz = BUFFER_SIZE, + }; + ESP_ERROR_CHECK(spi_bus_initialize(EXAMPLE_LCD_SPI_NUM, &bus_cfg, SPI_DMA_CH_AUTO)); + + //----------Panel IO initialization------------// + ESP_LOGI(TAG, "New panel IO SPI"); + const esp_lcd_panel_io_spi_config_t io_cfg = { + .dc_gpio_num = EXAMPLE_LCD_DC, + .cs_gpio_num = EXAMPLE_LCD_SPI_CS, + .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, + .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS, + .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS, + .spi_mode = 2, + .trans_queue_depth = 10, + }; + ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi( + (esp_lcd_spi_bus_handle_t)EXAMPLE_LCD_SPI_NUM, + &io_cfg, + &lcd_io_hdl + )); + + //----------ST7789 Panel initialization------------// + ESP_LOGI(TAG, "New ST7789 panel"); + const esp_lcd_panel_dev_config_t panel_dev_cfg = { + .reset_gpio_num = EXAMPLE_LCD_RST, + .color_space = ESP_LCD_COLOR_SPACE_RGB, + .bits_per_pixel = EXAMPLE_RGB565_BITS_PER_PIXEL, + }; + ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(lcd_io_hdl, &panel_dev_cfg, &panel_handle)); + + ESP_LOGI(TAG, "Reset and init panel"); + esp_lcd_panel_reset(panel_handle); + esp_lcd_panel_init(panel_handle); + esp_lcd_panel_invert_color(panel_handle, true); + + ESP_LOGI(TAG, "Turn on display"); + esp_lcd_panel_disp_on_off(panel_handle, true); + + const int brightness = 100; + uint32_t duty = (1023 * brightness) / 100; + ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty)); + ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0)); + + *lcd_panel_hdl = panel_handle; +} + +void app_main(void) +{ + esp_err_t ret = ESP_FAIL; + + esp_lcd_panel_handle_t lcd_panel_hdl = NULL; + esp_lcd_panel_io_handle_t lcd_io_hdl = NULL; + + size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8; + void *cam_buffer = heap_caps_malloc(cam_buffer_size, EXAMPLE_DVP_CAM_BUF_ALLOC_CAPS); + if (!cam_buffer) { + ESP_LOGE(TAG, "no mem for cam_buffer"); + return; + } + + lcd_display_init(&lcd_panel_hdl, lcd_io_hdl); + + //----------CAM Controller Init------------// + esp_cam_ctlr_handle_t cam_handle = NULL; + esp_cam_ctlr_dvp_pin_config_t pin_cfg = { + .data_width = EXAMPLE_DVP_CAM_DATA_WIDTH, + .data_io = { + EXAMPLE_DVP_CAM_D0_IO, + EXAMPLE_DVP_CAM_D1_IO, + EXAMPLE_DVP_CAM_D2_IO, + EXAMPLE_DVP_CAM_D3_IO, + EXAMPLE_DVP_CAM_D4_IO, + EXAMPLE_DVP_CAM_D5_IO, + EXAMPLE_DVP_CAM_D6_IO, + EXAMPLE_DVP_CAM_D7_IO, + }, + .vsync_io = EXAMPLE_DVP_CAM_VSYNC_IO, + .de_io = EXAMPLE_DVP_CAM_DE_IO, + .pclk_io = EXAMPLE_DVP_CAM_PCLK_IO, + .xclk_io = EXAMPLE_DVP_CAM_XCLK_IO, + }; + + esp_cam_ctlr_dvp_config_t dvp_config = { + .ctlr_id = 0, + .clk_src = CAM_CLK_SRC_DEFAULT, + .h_res = CONFIG_EXAMPLE_CAM_HRES, + .v_res = CONFIG_EXAMPLE_CAM_VRES, + .input_data_color_type = CAM_CTLR_COLOR_RGB565, + .dma_burst_size = 64, + .pin = &pin_cfg, + .bk_buffer_dis = 1, + .xclk_freq = EXAMPLE_DVP_CAM_XCLK_FREQ_HZ, + }; + + ret = esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "dvp init fail[%d]", ret); + return; + } + + //--------Camera Sensor and SCCB Init-----------// + example_sensor_config_t cam_sensor_config = { + .i2c_port_num = I2C_NUM_0, + .i2c_sda_io_num = EXAMPLE_DVP_CAM_SCCB_SDA_IO, + .i2c_scl_io_num = EXAMPLE_DVP_CAM_SCCB_SCL_IO, + .port = ESP_CAM_SENSOR_DVP, + .format_name = EXAMPLE_CAM_FORMAT, + }; + example_sensor_handle_t sensor_handle = { + .sccb_handle = NULL, + .i2c_bus_handle = NULL, + }; + example_sensor_init(&cam_sensor_config, &sensor_handle); + + //--------Register Camera Callbacks----------// + example_cam_context_t cam_ctx = { + .panel_hdl = lcd_panel_hdl, + .cam_trans = { + .buffer = cam_buffer, + .buflen = cam_buffer_size, + } + }; + + esp_cam_ctlr_evt_cbs_t cbs = { + .on_get_new_trans = s_camera_get_new_vb, + .on_trans_finished = s_camera_get_finished_trans, + }; + if (esp_cam_ctlr_register_event_callbacks(cam_handle, &cbs, &cam_ctx) != ESP_OK) { + ESP_LOGE(TAG, "ops register fail"); + return; + } + + //--------Enable and start Camera Controller----------// + ESP_ERROR_CHECK(esp_cam_ctlr_enable(cam_handle)); + + if (esp_cam_ctlr_start(cam_handle) != ESP_OK) { + ESP_LOGE(TAG, "Driver start fail"); + return; + } + + while (1) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} + +static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data) +{ + example_cam_context_t *ctx = (example_cam_context_t *)user_data; + *trans = ctx->cam_trans; + return false; +} + +static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data) +{ + example_cam_context_t *ctx = (example_cam_context_t *)user_data; + esp_lcd_panel_draw_bitmap(ctx->panel_hdl, 0, 0, CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_CAM_VRES, trans->buffer); + return false; +} diff --git a/examples/peripherals/camera/dvp_spi_lcd/main/example_config.h b/examples/peripherals/camera/dvp_spi_lcd/main/example_config.h new file mode 100644 index 0000000000..2925ac9542 --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/main/example_config.h @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//----------CAM Config------------// +#define EXAMPLE_RGB565_BITS_PER_PIXEL 16 + +#define EXAMPLE_DVP_CAM_SCCB_SCL_IO (5) +#define EXAMPLE_DVP_CAM_SCCB_SDA_IO (4) + +#define EXAMPLE_DVP_CAM_XCLK_FREQ_HZ (20000000) + +#define EXAMPLE_DVP_CAM_DATA_WIDTH (8) + +#define EXAMPLE_DVP_CAM_D0_IO (11) +#define EXAMPLE_DVP_CAM_D1_IO (9) +#define EXAMPLE_DVP_CAM_D2_IO (8) +#define EXAMPLE_DVP_CAM_D3_IO (10) +#define EXAMPLE_DVP_CAM_D4_IO (12) +#define EXAMPLE_DVP_CAM_D5_IO (18) +#define EXAMPLE_DVP_CAM_D6_IO (17) +#define EXAMPLE_DVP_CAM_D7_IO (16) + +#define EXAMPLE_DVP_CAM_XCLK_IO (15) +#define EXAMPLE_DVP_CAM_PCLK_IO (13) +#define EXAMPLE_DVP_CAM_DE_IO (7) +#define EXAMPLE_DVP_CAM_VSYNC_IO (6) +#define EXAMPLE_DVP_CAM_HSYNC_IO (-1) + +#if CONFIG_SPIRAM +#define EXAMPLE_DVP_CAM_BUF_ALLOC_CAPS (MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA) +#else +#define EXAMPLE_DVP_CAM_BUF_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA) +#endif + +#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RGB565_240x240_25fps" // ov2640 + +#ifndef EXAMPLE_CAM_FORMAT +#error "Unsupported camera format! Please adjust EXAMPLE_CAM_HRES and EXAMPLE_CAM_VRES in menuconfig" +#endif + +//----------LCD Config------------// +#define EXAMPLE_LEDC_DVP_XCLK (LEDC_TIMER_0) +#define EXAMPLE_LEDC_LCD_BACKLIGHT (LEDC_TIMER_1) +#define EXAMPLE_LCD_SPI_NUM (SPI3_HOST) +#define EXAMPLE_LCD_CMD_BITS (8) +#define EXAMPLE_LCD_PARAM_BITS (8) + +/* LCD Display */ +#define EXAMPLE_LCD_SPI_MOSI (GPIO_NUM_47) +#define EXAMPLE_LCD_SPI_CLK (GPIO_NUM_21) +#define EXAMPLE_LCD_SPI_CS (GPIO_NUM_44) +#define EXAMPLE_LCD_DC (GPIO_NUM_43) +#define EXAMPLE_LCD_RST (GPIO_NUM_NC) +#define EXAMPLE_LCD_BACKLIGHT (GPIO_NUM_48) + +#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (80 * 1000 * 1000) + +#ifdef __cplusplus +} +#endif diff --git a/examples/peripherals/camera/dvp_spi_lcd/main/idf_component.yml b/examples/peripherals/camera/dvp_spi_lcd/main/idf_component.yml new file mode 100644 index 0000000000..4cd6897719 --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + sensor_init: + path: ${IDF_PATH}/examples/peripherals/camera/common_components/sensor_init diff --git a/examples/peripherals/camera/dvp_spi_lcd/pytest_dvp_spi_lcd.py b/examples/peripherals/camera/dvp_spi_lcd/pytest_dvp_spi_lcd.py new file mode 100644 index 0000000000..7dfd614f40 --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/pytest_dvp_spi_lcd.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import pytest +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize + + +@pytest.mark.generic +@idf_parametrize('target', ['esp32p4'], indirect=['target']) +def test_dvp_spi_lcd_p4(dut: Dut) -> None: + dut.expect_exact('Calling app_main()') diff --git a/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults b/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults new file mode 100644 index 0000000000..dc0f8f7a83 --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_CAMERA_OV2640=y diff --git a/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32p4 b/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32p4 new file mode 100644 index 0000000000..c15bfde7e8 --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32p4 @@ -0,0 +1,2 @@ +CONFIG_SPIRAM_SPEED_200M=y +CONFIG_SPIRAM=y diff --git a/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32s3 b/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32s3 new file mode 100644 index 0000000000..38bbb5933e --- /dev/null +++ b/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32s3 @@ -0,0 +1,2 @@ +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y