diff --git a/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h b/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h index f2fe395b0e..9e167547d2 100644 --- a/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h +++ b/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h @@ -29,7 +29,7 @@ typedef struct { uint32_t h_res; ///< Input horizontal resolution, i.e. the number of pixels in a line uint32_t v_res; ///< Input vertical resolution, i.e. the number of lines in a frame uint8_t data_lane_num; ///< Data lane num - int clk_freq_hz; ///< Frequency of CLK, in Hz. + int lane_bit_rate_mbps; ///< Lane bit rate in Mbps mipi_csi_color_t input_data_color_type; ///< Input color type mipi_csi_color_t output_data_color_type; ///< Output color type bool byte_swap_en; ///< Enable byte swap diff --git a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c index 2f3141fcf2..b5fb13a285 100644 --- a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c +++ b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c @@ -161,7 +161,7 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ mipi_csi_hal_config_t hal_config; hal_config.frame_height = config->h_res; hal_config.frame_width = config->v_res; - hal_config.clk_freq_hz = config->clk_freq_hz; + hal_config.lane_bit_rate_mbps = config->lane_bit_rate_mbps; hal_config.lanes_num = config->data_lane_num; hal_config.byte_swap_en = config->byte_swap_en; mipi_csi_hal_init(&ctlr->hal, &hal_config); diff --git a/components/esp_driver_cam/include/esp_cam_ctlr.h b/components/esp_driver_cam/include/esp_cam_ctlr.h index fa3995917b..85c85a7df2 100644 --- a/components/esp_driver_cam/include/esp_cam_ctlr.h +++ b/components/esp_driver_cam/include/esp_cam_ctlr.h @@ -92,8 +92,9 @@ esp_err_t esp_cam_del_ctlr(esp_cam_ctlr_handle_t handle); /** * @brief Register ESP CAM controller event callbacks * - * @param[in] handle ESP CAM controller handle - * + * @param[in] handle ESP CAM controller handle + * @param[in] cbs ESP CAM controller event callbacks + * @param[in] user_data User data * @return * - ESP_OK * - ESP_ERR_INVALID_ARG: Invalid argument diff --git a/components/esp_driver_cam/test_apps/csi/main/test_csi_driver.c b/components/esp_driver_cam/test_apps/csi/main/test_csi_driver.c index db3536168e..178016fef6 100644 --- a/components/esp_driver_cam/test_apps/csi/main/test_csi_driver.c +++ b/components/esp_driver_cam/test_apps/csi/main/test_csi_driver.c @@ -15,7 +15,7 @@ TEST_CASE("TEST CSI driver allocation", "[csi]") .ctlr_id = 0, .h_res = 800, .v_res = 640, - .clk_freq_hz = 200000000, + .lane_bit_rate_mbps = 200, .input_data_color_type = MIPI_CSI_COLOR_RAW8, .output_data_color_type = MIPI_CSI_COLOR_RGB565, .data_lane_num = 2, diff --git a/components/hal/include/hal/mipi_csi_hal.h b/components/hal/include/hal/mipi_csi_hal.h index d4c5f61622..d9fdd3268c 100644 --- a/components/hal/include/hal/mipi_csi_hal.h +++ b/components/hal/include/hal/mipi_csi_hal.h @@ -43,7 +43,7 @@ typedef struct { uint32_t in_bpp; ///< In bits per pixel uint32_t out_bpp; ///< Out bits per pixel bool byte_swap_en; ///< Enable byte swap - int clk_freq_hz; ///< Clock frequency in hz + int lane_bit_rate_mbps; ///< Lane bit rate in Mbps } mipi_csi_hal_config_t; /** diff --git a/components/hal/mipi_csi_hal.c b/components/hal/mipi_csi_hal.c index 61a9723748..80f3e1e636 100644 --- a/components/hal/mipi_csi_hal.c +++ b/components/hal/mipi_csi_hal.c @@ -9,6 +9,8 @@ #include "hal/mipi_csi_ll.h" #include "soc/mipi_csi_periph.h" +#define MHZ (1000 * 1000) + void s_mipi_csi_hal_phy_write_register(mipi_csi_hal_context_t *hal, uint8_t reg_addr, uint8_t reg_val) { mipi_csi_phy_ll_write_clock(hal->host_dev, 0, false); @@ -24,7 +26,7 @@ void mipi_csi_hal_init(mipi_csi_hal_context_t *hal, const mipi_csi_hal_config_t { hal->bridge_dev = MIPI_CSI_BRG_LL_GET_HW(0); hal->host_dev = MIPI_CSI_HOST_LL_GET_HW(0); - int csi_lane_rate = config->clk_freq_hz; + int csi_lane_rate = config->lane_bit_rate_mbps * MHZ; // reset PHY mipi_csi_phy_ll_enable_shutdown_input(hal->host_dev, true); diff --git a/docs/conf_common.py b/docs/conf_common.py index cf7a7f7cb7..c2a04f78c5 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -79,6 +79,8 @@ COEXISTENCE_DOCS = ['api-guides/coexist.rst'] MM_SYNC_DOCS = ['api-reference/system/mm_sync.rst'] +CAMERA_DOCS = ['api-reference/peripherals/camera_driver.rst'] + CLK_TREE_DOCS = ['api-reference/peripherals/clk_tree.rst'] UART_DOCS = ['api-reference/peripherals/uart.rst'] @@ -250,6 +252,7 @@ conditional_include_dict = {'SOC_BT_SUPPORTED':BT_DOCS, 'SOC_ANA_CMPR_SUPPORTED': ANA_CMPR_DOCS, 'SOC_SDM_SUPPORTED':SDM_DOCS, 'SOC_WIFI_MESH_SUPPORT':WIFI_MESH_DOCS, + 'SOC_MIPI_CSI_SUPPORTED':CAMERA_DOCS, 'SOC_SPI_SUPPORT_SLAVE_HD_VER2':SPI_SLAVE_HD_DOCS, 'SOC_WIFI_NAN_SUPPORT':NAN_DOCS, 'SOC_JPEG_CODEC_SUPPORTED':JPEG_DOCS, diff --git a/docs/doxygen/Doxyfile_esp32p4 b/docs/doxygen/Doxyfile_esp32p4 index 117c359827..26795ef74b 100644 --- a/docs/doxygen/Doxyfile_esp32p4 +++ b/docs/doxygen/Doxyfile_esp32p4 @@ -12,8 +12,11 @@ INPUT += \ $(PROJECT_PATH)/components/usb/include/usb/usb_host.h \ $(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \ $(PROJECT_PATH)/components/usb/include/usb/usb_types_stack.h \ - $(PROJECT_PATH)/components/hal/include/hal/jpeg_types.h \ + $(PROJECT_PATH)/components/esp_driver_cam/include/esp_cam_ctlr.h \ + $(PROJECT_PATH)/components/esp_driver_cam/include/esp_cam_ctlr_types.h \ + $(PROJECT_PATH)/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h \ $(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_decode.h \ + $(PROJECT_PATH)/components/hal/include/hal/jpeg_types.h \ $(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_types.h \ $(PROJECT_PATH)/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/adc_channel.h \ diff --git a/docs/en/api-reference/peripherals/camera_driver.rst b/docs/en/api-reference/peripherals/camera_driver.rst new file mode 100644 index 0000000000..6bcfc56378 --- /dev/null +++ b/docs/en/api-reference/peripherals/camera_driver.rst @@ -0,0 +1,171 @@ +Camera Controller Driver +======================== + +Introduction +------------ + +{IDF_TARGET_NAME} has the following hardware that is intended for communication with external camera sensor: + +.. list:: + + : SOC_MIPI_CSI_SUPPORTED : - CSI + +The ``esp_driver_cam`` component is designed to support these camera controller hardwares. + + +Functional Overview +------------------- + +.. list:: + + - `Resource Allocation <#cam-resource-allocation>`__ - covers how to allocate camera controller instances with properly set of configurations. It also covers how to recycle the resources when they are no longer needed. + - `Enable and disable a camera controller <#cam-enable-disable>`__ - covers how to enable and disable a camera controller. + - `Start and stop a camera controller <#cam-start-stop>`__ - covers how to start and stop a camera controller. + - `Receive from a camera sensor or something else <#cam-receive>`__ - convers how to receive camera signal from a sensor or something else. + - `Register callback <#cam-callback>`__ - covers how to hook user specific code to camera controller driver event callback function. + - `Thread Safety <#thread-safety>`__ - lists which APIs are guaranteed to be thread safe by the driver. + - `Kconfig Options <#kconfig-options>`__ - lists the supported Kconfig options that can bring different effects to the driver. + - `IRAM SAFE <#cam-iram-safe>`__ - describes tips on how to make the CSI interrupt and control functions work better along with a disabled cache. + +.. _cam-resource-allocation: + +Resource Allocation +^^^^^^^^^^^^^^^^^^^ + +.. only:: SOC_MIPI_CSI_SUPPORTED + + Install Camera Controller Driver + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + A Camera controller driver can be implemented by the CSI peripheral, which requires the configuration that specified by :cpp:type:`esp_cam_ctlr_csi_config_t`: + + - :cpp:member:`esp_cam_ctlr_csi_config_t::ctlr_id`, select the CSI controller ID. + - :cpp:member:`esp_cam_ctlr_csi_config_t::clk_src`, select the CSI phy clock source. + - :cpp:member:`esp_cam_ctlr_csi_config_t::h_res`, set input horizontal resolution, i.e. the number of pixels in a line. + - :cpp:member:`esp_cam_ctlr_csi_config_t::v_res`, set input vertical resolution, i.e. the number of lines in a frame. + - :cpp:member:`esp_cam_ctlr_csi_config_t::data_lane_num`, set the number of data lanes to be used. + - :cpp:member:`esp_cam_ctlr_csi_config_t::clk_freq_hz`, set the frequency of clock, in Hz. + - :cpp:member:`esp_cam_ctlr_csi_config_t::input_data_color_type`, select the input color type. + - :cpp:member:`esp_cam_ctlr_csi_config_t::output_data_color_type`, select the output color type. + - :cpp:member:`esp_cam_ctlr_csi_config_t::byte_swap_en`, set to enable byte swap. + - :cpp:member:`esp_cam_ctlr_csi_config_t::queue_items`, set queue itmes, the deeper the queue, the more the driver can handle transactions. + + If the configurations in :cpp:type:`esp_cam_ctlr_csi_config_t` is specified, users can call :cpp:func:`esp_cam_new_csi_ctlr` to allocate and initialize a CSI camera controller handle. This function will return an CSI camera controller handle if it runs correctly. You can take following code as reference. + + .. code:: c + + esp_cam_ctlr_csi_config_t csi_config = { + .ctlr_id = 0, + .h_res = MIPI_CSI_DISP_HSIZE, + .v_res = MIPI_CSI_DISP_VSIZE_640P, + .lane_bit_rate_mbps = MIPI_CSI_LANE_BITRATE_MBPS, + .input_data_color_type = MIPI_CSI_COLOR_RAW8, + .output_data_color_type = MIPI_CSI_COLOR_RGB565, + .data_lane_num = 2, + .byte_swap_en = false, + .queue_items = 1, + }; + esp_cam_ctlr_handle_t handle = NULL; + ESP_ERROR_CHECK(esp_cam_new_csi_ctlr(&csi_config, &handle)); + +Uninstall Camera Controller Driver +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a previously installed camera controller driver is no longer needed, it's recommended to recycle the resource by calling :cpp:func:`esp_cam_del_ctlr`, so that to release the underlying hardware. + +.. _cam-enable-disable: + +Enable and Disable Camera Controller Driver +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Before starting camera controller operation, you need to enable the camera controller controller first, by calling :cpp:func:`esp_cam_ctlr_enable`. This function: + +* Switches the driver state from **init** to **enable**. + +.. code:: c + + ESP_ERROR_CHECK(esp_cam_ctlr_enable(handle)); + +Calling :cpp:func:`esp_cam_ctlr_disable` does the opposite, that is, put the driver back to the **init** state. + +.. code:: c + + ESP_ERROR_CHECK(esp_cam_ctlr_disable(handle)); + +.. _cam-start-stop: + +Start and Stop Camera Controller Driver +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Before receiving camera signal from camera sensor, you need to start the camera controller driver first, by calling :cpp:func:`esp_cam_ctlr_start`. This function: + +* Switches the driver stat from **enable** to **start** + +.. code:: c + + ESP_ERROR_CHECK(esp_cam_ctlr_start(handle)); + +Calling :cpp:func:`esp_cam_ctlr_stop` does the opposite, that is, put the driver back to the **enable** state. + +.. code:: c + + ESP_ERROR_CHECK(esp_cam_ctlr_stop(handle)); + +.. _cam-receive: + +Receive from A Camera Sensor +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Now you can call :cpp:func:`esp_cam_ctlr_receive` to receive from a camera sensor or something else. + +.. code:: c + + ESP_ERROR_CHECK(esp_cam_ctlr_receive(handle, &my_trans, ESP_CAM_CTLR_MAX_DELAY)); + +.. _cam-callback: + +Register Event Callbacks +^^^^^^^^^^^^^^^^^^^^^^^^ + +After the camera controller driver starts receiving, it can generate a specific event dynamically. If you have some functions that should be called when the event happens, please hook your function to the interrupt service routine by calling :cpp:func:`esp_cam_ctlr_register_event_callbacks`. All supported event callbacks are listed in :cpp:type:`esp_cam_ctlr_evt_cbs_t`: + +- :cpp:member:`esp_cam_ctlr_evt_cbs_t::on_get_new_trans` sets a callback function when the camera controller driver gets a new transaction which is passed from :cpp:func:`esp_cam_ctlr_receive`. As this function is called within the ISR context, you must ensure that the function does not attempt to block (e.g., by making sure that only FreeRTOS APIs with ``ISR`` suffix are called from within the function). + +- :cpp:member:`esp_cam_ctlr_evt_cbs_t::on_trans_finished` sets a callback function when the camera controller driver finishes a transaction. As this function is called within the ISR context, you must ensure that the function does not attempt to block (e.g., by making sure that only FreeRTOS APIs with ``ISR`` suffix are called from within the function). + +.. _thread-safety: + +Thread Safety +^^^^^^^^^^^^^ + +The factory function :cpp:func:`esp_cam_new_csi_ctlr` and :cpp:func:`esp_cam_del_ctlr` are guaranteed to be thread safe by the driver, which means, user can call them from different RTOS tasks without protection by extra locks. + +.. _kconfig-options: + +Kconfig Options +^^^^^^^^^^^^^^^ + +- :ref:`CONFIG_MIPI_CSI_ISR_IRAM_SAFE` controls whether the default ISR handler should be masked when the cache is disabled + + +.. _cam-iram-safe: + +IRAM Safe +^^^^^^^^^ + +By default, the CSI interrupt will be deferred when the cache is disabled because of writing or erasing the flash. + +There is a Kconfig option :ref:`CONFIG_MIPI_CSI_ISR_IRAM_SAFE` that: + +- Enables the interrupt being serviced even when the cache is disabled +- Places all functions that used by the ISR into IRAM +- Places driver object into DRAM (in case it is mapped to PSRAM by accident) + +This allows the interrupt to run while the cache is disabled, but comes at the cost of increased IRAM consumption. So user callbacks need to notice that the code and data inside (the callback) should be IRAM-safe or DRAM-safe, when cache is disabled. + +API Reference +------------- + +.. include-build-file:: inc/esp_cam_ctlr.inc +.. include-build-file:: inc/esp_cam_ctlr_types.inc +.. include-build-file:: inc/esp_cam_ctlr_csi.inc diff --git a/docs/en/api-reference/peripherals/index.rst b/docs/en/api-reference/peripherals/index.rst index e03d03f471..22826f95f2 100644 --- a/docs/en/api-reference/peripherals/index.rst +++ b/docs/en/api-reference/peripherals/index.rst @@ -24,6 +24,7 @@ Peripherals API lcd/index :SOC_GP_LDO_SUPPORTED: ldo_regulator ledc + :SOC_MIPI_CSI_SUPPORTED: camera_driver :SOC_MCPWM_SUPPORTED: mcpwm :SOC_PARLIO_SUPPORTED: parlio :SOC_PCNT_SUPPORTED: pcnt diff --git a/docs/zh_CN/api-reference/peripherals/camera_driver.rst b/docs/zh_CN/api-reference/peripherals/camera_driver.rst new file mode 100644 index 0000000000..ccad79cd73 --- /dev/null +++ b/docs/zh_CN/api-reference/peripherals/camera_driver.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/peripherals/camera_driver.rst diff --git a/docs/zh_CN/api-reference/peripherals/index.rst b/docs/zh_CN/api-reference/peripherals/index.rst index d5e237ec42..287c7ab5ae 100644 --- a/docs/zh_CN/api-reference/peripherals/index.rst +++ b/docs/zh_CN/api-reference/peripherals/index.rst @@ -24,6 +24,7 @@ lcd/index :SOC_GP_LDO_SUPPORTED: ldo_regulator ledc + :SOC_MIPI_CSI_SUPPORTED: camera_driver :SOC_MCPWM_SUPPORTED: mcpwm :SOC_PARLIO_SUPPORTED: parlio :SOC_PCNT_SUPPORTED: pcnt