diff --git a/README.md b/README.md index 22df502..5af4a6d 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Specific pins used in this example to connect ESP32 and camera are shown in tabl | Pixel Data Bit 6 | D8 | IO34 | IO36 | | Pixel Data Bit 7 | D9 | IO35 | IO19 | | Camera Reset | RESET | IO2 | IO15 | -| Camera Power Down | PWDN | *see Note 2* | *see Note 2* | +| Camera Power Down | PWDN | *see Note 3* | *see Note 3* | | Power Supply 3.3V | 3V3 | 3V3 | 3V3 | | Ground | GND | GND | GND | @@ -330,4 +330,4 @@ You are welcome to contribute to this repository by providing documentation to c This application is using code developed by: * OpenMV implementation for OV7725 by Ibrahim Abdelkader -* Software I2C library for ESP31B by Hristo Gochkov \ No newline at end of file +* Software I2C library for ESP31B by Hristo Gochkov diff --git a/components/camera/Kconfig.projbuild b/components/camera/Kconfig similarity index 100% rename from components/camera/Kconfig.projbuild rename to components/camera/Kconfig diff --git a/components/camera/camera.c b/components/camera/camera.c index 45d4a9d..6bbedef 100644 --- a/components/camera/camera.c +++ b/components/camera/camera.c @@ -1,14 +1,3 @@ -/* - * Portions of this file come from OpenMV project (see sensor_* functions in the end of file) - * Here is the copyright for these parts: - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * - * Rest of the functions are licensed under Apache license as found below: - */ - // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,6 +26,7 @@ #include "soc/i2s_struct.h" #include "soc/io_mux_reg.h" #include "driver/gpio.h" +#include "driver/rtc_io.h" #include "driver/periph_ctrl.h" #include "esp_intr_alloc.h" #include "esp_log.h" @@ -114,6 +104,17 @@ static size_t i2s_bytes_per_sample(i2s_sampling_mode_t mode) } } +static void vsync_intr_disable() +{ + gpio_set_intr_type(s_state->config.pin_vsync, GPIO_INTR_DISABLE); +} + +static void vsync_intr_enable() +{ + gpio_set_intr_type(s_state->config.pin_vsync, GPIO_INTR_NEGEDGE); +} + + esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera_model) { if (s_state != NULL) { @@ -320,13 +321,10 @@ esp_err_t camera_init(const camera_config_t* config) } ESP_LOGD(TAG, "Initializing GPIO interrupts"); - gpio_set_intr_type(s_state->config.pin_vsync, GPIO_INTR_NEGEDGE); - gpio_intr_enable(s_state->config.pin_vsync); - err = gpio_isr_register(&gpio_isr, (void*) TAG, - ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM, - &s_state->vsync_intr_handle); + vsync_intr_disable(); + err = gpio_isr_handler_add(s_state->config.pin_vsync, &gpio_isr, NULL); if (err != ESP_OK) { - ESP_LOGE(TAG, "gpio_isr_register failed (%x)", err); + ESP_LOGE(TAG, "gpio_isr_handler_add failed (%x)", err); goto fail; } @@ -363,10 +361,7 @@ esp_err_t camera_deinit() if (s_state->frame_ready) { vSemaphoreDelete(s_state->frame_ready); } - if (s_state->vsync_intr_handle) { - esp_intr_disable(s_state->vsync_intr_handle); - esp_intr_free(s_state->vsync_intr_handle); - } + gpio_isr_handler_remove(s_state->config.pin_vsync); if (s_state->i2s_intr_handle) { esp_intr_disable(s_state->i2s_intr_handle); esp_intr_free(s_state->i2s_intr_handle); @@ -543,6 +538,9 @@ static void i2s_init() .intr_type = GPIO_INTR_DISABLE }; for (int i = 0; i < sizeof(pins) / sizeof(gpio_num_t); ++i) { + if (rtc_gpio_is_valid_gpio(pins[i])) { + rtc_gpio_deinit(pins[i]); + } conf.pin_bit_mask = 1LL << pins[i]; gpio_config(&conf); } @@ -601,7 +599,7 @@ static void i2s_init() static void i2s_stop() { esp_intr_disable(s_state->i2s_intr_handle); - esp_intr_disable(s_state->vsync_intr_handle); + vsync_intr_disable(); i2s_conf_reset(); I2S0.conf.rx_start = 0; size_t val = SIZE_MAX; @@ -645,7 +643,7 @@ static void i2s_run() I2S0.int_ena.in_done = 1; esp_intr_enable(s_state->i2s_intr_handle); if (s_state->config.pixel_format == CAMERA_PF_JPEG) { - esp_intr_enable(s_state->vsync_intr_handle); + vsync_intr_enable(); } I2S0.conf.rx_start = 1; @@ -680,8 +678,6 @@ static void IRAM_ATTR i2s_isr(void* arg) static void IRAM_ATTR gpio_isr(void* arg) { - GPIO.status1_w1tc.val = GPIO.status1.val; - GPIO.status_w1tc = GPIO.status; bool need_yield = false; ESP_EARLY_LOGV(TAG, "gpio isr, cnt=%d", s_state->dma_received_count); if (gpio_get_level(s_state->config.pin_vsync) == 0 && @@ -712,10 +708,13 @@ static void IRAM_ATTR dma_filter_task(void *pvParameters) continue; } - uint8_t* pfb = s_state->fb + get_fb_pos(); + size_t fb_pos = get_fb_pos(); + assert(fb_pos <= s_state->fb_size + s_state->width * + s_state->fb_bytes_per_pixel / s_state->dma_per_line); + + uint8_t* pfb = s_state->fb + fb_pos; const dma_elem_t* buf = s_state->dma_buf[buf_idx]; lldesc_t* desc = &s_state->dma_desc[buf_idx]; - ESP_LOGV(TAG, "dma_flt: pos=%d ", get_fb_pos()); (*s_state->dma_filter)(buf, desc, pfb); s_state->dma_filtered_count++; ESP_LOGV(TAG, "dma_flt: flt_count=%d ", s_state->dma_filtered_count); diff --git a/components/camera/camera_common.h b/components/camera/camera_common.h index d2dfc67..9973dd5 100644 --- a/components/camera/camera_common.h +++ b/components/camera/camera_common.h @@ -65,7 +65,6 @@ typedef struct { i2s_sampling_mode_t sampling_mode; dma_filter_t dma_filter; intr_handle_t i2s_intr_handle; - intr_handle_t vsync_intr_handle; QueueHandle_t data_ready; SemaphoreHandle_t frame_ready; TaskHandle_t dma_filter_task; diff --git a/components/camera/xclk.c b/components/camera/xclk.c index 8bf0123..4ad050f 100644 --- a/components/camera/xclk.c +++ b/components/camera/xclk.c @@ -10,24 +10,26 @@ esp_err_t camera_enable_out_clock(camera_config_t* config) { periph_module_enable(PERIPH_LEDC_MODULE); - ledc_timer_config_t timer_conf; - timer_conf.duty_resolution = 1; - timer_conf.freq_hz = config->xclk_freq_hz; - timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE; - timer_conf.timer_num = config->ledc_timer; + ledc_timer_config_t timer_conf = { + .duty_resolution = 1, + .freq_hz = config->xclk_freq_hz, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .timer_num = config->ledc_timer + }; esp_err_t err = ledc_timer_config(&timer_conf); if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err); return err; } - ledc_channel_config_t ch_conf; - ch_conf.channel = config->ledc_channel; - ch_conf.timer_sel = config->ledc_timer; - ch_conf.intr_type = LEDC_INTR_DISABLE; - ch_conf.duty = 1; - ch_conf.speed_mode = LEDC_HIGH_SPEED_MODE; - ch_conf.gpio_num = config->pin_xclk; + ledc_channel_config_t ch_conf = { + .channel = config->ledc_channel, + .timer_sel = config->ledc_timer, + .intr_type = LEDC_INTR_DISABLE, + .duty = 1, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .gpio_num = config->pin_xclk + }; err = ledc_channel_config(&ch_conf); if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err); diff --git a/main/app_main.c b/main/app_main.c index 8107e0d..0da4a72 100644 --- a/main/app_main.c +++ b/main/app_main.c @@ -69,6 +69,8 @@ void app_main() ESP_ERROR_CHECK( nvs_flash_init() ); } + ESP_ERROR_CHECK(gpio_install_isr_service(0)); + camera_config_t camera_config = { .ledc_channel = LEDC_CHANNEL_0, .ledc_timer = LEDC_TIMER_0,