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 {
@@ -360,7 +362,7 @@ esp_err_t esp_cam_ctlr_dvp_init(int ctlr_id, cam_clock_source_t clk_src, const e
360362}
361363
362364/**
363- * @brief ESP CAM DVP output hardware clock
365+ * @brief ESP CAM DVP output hardware clock, the function "esp_cam_ctlr_dvp_init" should be called first
364366 *
365367 * @param ctlr_id CAM DVP controller ID
366368 * @param clk_src CAM DVP clock source
@@ -383,15 +385,54 @@ esp_err_t esp_cam_ctlr_dvp_output_clock(int ctlr_id, cam_clock_source_t clk_src,
383385
384386 if ((src_clk_hz % xclk_freq ) == 0 ) {
385387 DVP_CAM_CLK_ATOMIC () {
388+ // The camera sensors require precision without frequency and duty cycle jitter,
389+ // so the fractional divisor can't be used.
386390 cam_ll_set_group_clock_coeff (ctlr_id , src_clk_hz / xclk_freq , 0 , 0 );
387391 };
388392
389393 ret = ESP_OK ;
394+ } else {
395+ ESP_LOGE (TAG , "calculated frequency divider is not integer so clock isn't changed" );
390396 }
391397
392398 return ret ;
393399}
394400
401+ /**
402+ * @brief Initialize ESP CAM DVP clock pin (other DVP GPIO pins excluded the clock pins will not be initialized)
403+ * and hardware clock, then output clock signal with given frequency
404+ *
405+ * @note The function is implemented based on "esp_cam_ctlr_dvp_init" and "esp_cam_ctlr_dvp_output_clock",
406+ * so calling "esp_cam_ctlr_dvp_init" and "esp_cam_ctlr_dvp_output_clock" is not required
407+ *
408+ * @param ctlr_id DVP controller ID
409+ * @param pin DVP clock pin
410+ * @param clk_src DVP clock source
411+ * @param xclk_freq DVP clock frequency
412+ *
413+ * @return
414+ * - ESP_OK on success
415+ * - Others if failed
416+ */
417+ 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 )
418+ {
419+ esp_cam_ctlr_dvp_pin_config_t pin_config = {0 };
420+
421+ pin_config .data_width = CAM_CTLR_DATA_WIDTH_8 ;
422+ pin_config .vsync_io = GPIO_NUM_NC ;
423+ pin_config .de_io = GPIO_NUM_NC ;
424+ pin_config .pclk_io = GPIO_NUM_NC ;
425+ for (int i = 0 ; i < CAM_DVP_DATA_SIG_NUM ; i ++ ) {
426+ pin_config .data_io [i ] = GPIO_NUM_NC ;
427+ }
428+ pin_config .xclk_io = pin ;
429+
430+ ESP_RETURN_ON_ERROR (esp_cam_ctlr_dvp_init (ctlr_id , clk_src , & pin_config ), TAG , "failed to initialize DVP controller" );
431+ ESP_RETURN_ON_ERROR (esp_cam_ctlr_dvp_output_clock (ctlr_id , clk_src , xclk_freq ), TAG , "failed to output clock" );
432+
433+ return ESP_OK ;
434+ }
435+
395436/**
396437 * @brief ESP CAM DVP de-initialzie.
397438 *
0 commit comments