4545
4646#define ALIGN_UP_BY (num , align ) ((align) == 0 ? (num) : (((num) + ((align) - 1)) & ~((align) - 1)))
4747
48- #define DVP_CAM_CONFIG_INPUT_PIN (pin , sig , inv ) \
49- { \
50- ret = esp_cam_ctlr_dvp_config_input_gpio(pin, sig, inv); \
51- if (ret != ESP_OK) { \
52- ESP_LOGE(TAG, "failed to configure pin=%d sig=%d", \
53- pin, sig); \
54- return ret; \
55- } \
48+ #define DVP_CAM_CONFIG_INPUT_PIN (pin , sig , inv ) \
49+ { \
50+ if (pin != GPIO_NUM_NC) { \
51+ ret = esp_cam_ctlr_dvp_config_input_gpio(pin, sig, inv); \
52+ if (ret != ESP_OK) { \
53+ ESP_LOGE(TAG, "failed to configure pin=%d sig=%d", \
54+ pin, sig); \
55+ return ret; \
56+ } \
57+ } \
5658}
5759
5860typedef struct dvp_platform {
@@ -358,7 +360,7 @@ esp_err_t esp_cam_ctlr_dvp_init(int ctlr_id, cam_clock_source_t clk_src, const e
358360}
359361
360362/**
361- * @brief ESP CAM DVP output hardware clock
363+ * @brief ESP CAM DVP output hardware clock, the function "esp_cam_ctlr_dvp_init" should be called first
362364 *
363365 * @param ctlr_id CAM DVP controller ID
364366 * @param clk_src CAM DVP clock source
@@ -381,15 +383,54 @@ esp_err_t esp_cam_ctlr_dvp_output_clock(int ctlr_id, cam_clock_source_t clk_src,
381383
382384 if ((src_clk_hz % xclk_freq ) == 0 ) {
383385 DVP_CAM_CLK_ATOMIC () {
386+ // The camera sensors require precision without frequency and duty cycle jitter,
387+ // so the fractional divisor can't be used.
384388 cam_ll_set_group_clock_coeff (ctlr_id , src_clk_hz / xclk_freq , 0 , 0 );
385389 };
386390
387391 ret = ESP_OK ;
392+ } else {
393+ ESP_LOGE (TAG , "calculated frequency divider is not integer so clock isn't changed" );
388394 }
389395
390396 return ret ;
391397}
392398
399+ /**
400+ * @brief Initialize ESP CAM DVP clock pin (other DVP GPIO pins excluded the clock pins will not be initialized)
401+ * and hardware clock, then output clock signal with given frequency
402+ *
403+ * @note The function is implemented based on "esp_cam_ctlr_dvp_init" and "esp_cam_ctlr_dvp_output_clock",
404+ * so calling "esp_cam_ctlr_dvp_init" and "esp_cam_ctlr_dvp_output_clock" is not required
405+ *
406+ * @param ctlr_id DVP controller ID
407+ * @param pin DVP clock pin
408+ * @param clk_src DVP clock source
409+ * @param xclk_freq DVP clock frequency
410+ *
411+ * @return
412+ * - ESP_OK on success
413+ * - Others if failed
414+ */
415+ esp_err_t esp_cam_ctlr_dvp_start_clock (int ctlr_id , gpio_num_t pin , cam_clock_source_t clk_src , uint32_t xclk_freq )
416+ {
417+ esp_cam_ctlr_dvp_pin_config_t pin_config = {0 };
418+
419+ pin_config .data_width = CAM_CTLR_DATA_WIDTH_8 ;
420+ pin_config .vsync_io = GPIO_NUM_NC ;
421+ pin_config .de_io = GPIO_NUM_NC ;
422+ pin_config .pclk_io = GPIO_NUM_NC ;
423+ for (int i = 0 ; i < CAM_DVP_DATA_SIG_NUM ; i ++ ) {
424+ pin_config .data_io [i ] = GPIO_NUM_NC ;
425+ }
426+ pin_config .xclk_io = pin ;
427+
428+ ESP_RETURN_ON_ERROR (esp_cam_ctlr_dvp_init (ctlr_id , clk_src , & pin_config ), TAG , "failed to initialize DVP controller" );
429+ ESP_RETURN_ON_ERROR (esp_cam_ctlr_dvp_output_clock (ctlr_id , clk_src , xclk_freq ), TAG , "failed to output clock" );
430+
431+ return ESP_OK ;
432+ }
433+
393434/**
394435 * @brief ESP CAM DVP de-initialzie.
395436 *
0 commit comments