Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Camera in ESP32-S3 with GDMA and LCD_CAM peripheral #8197

Answered by me-no-dev
JPMJPM asked this question in Q&A
Discussion options

Hi,

I am trying to integrate OV5640 camera into ESP32-S3 using GDMA and LCD_CAM peripheral
without any success.

Is it possible to do this in Arduino or I have to use idf ?.

Regards.

You must be logged in to vote

There is an example here you need to make sure that you have undefined the proper board also here and comment the line above that.

Replies: 1 comment 5 replies

Comment options

There is an example here you need to make sure that you have undefined the proper board also here and comment the line above that.

You must be logged in to vote
5 replies
Comment options

Thanks but I intend to develop the code from scratch.

My first try is the following but the dma_callback is not executed.

I appreciate any help, thanks.

`
// "ESP32S3 Dev Module" 2.0.9

#include <esp_rom_gpio.h>
#include <driver/periph_ctrl.h>
#include <esp_private/gdma.h>
#include <hal/dma_types.h>
#include <soc/lcd_cam_struct.h>

#define dmabuf_camrx_len 1470 // DMA camera RX buffer size
gdma_channel_handle_t dma_camrx_chan; // CAM RX DMA channel
uint8_t dmabuf_camrx[dmabuf_camrx_len]; // DMA RX camera buffer
dma_descriptor_t desc; // DMA RX camera descriptor

#define pclk_pin 13
#define xclk_pin 21
#define href_pin 46
#define d2_pin 40
#define d3_pin 39
#define d4_pin 38
#define d5_pin 37
#define d6_pin 36
#define d7_pin 5
#define d8_pin 45
#define d9_pin 47

// End of DMA transfer callback
static IRAM_ATTR bool dma_callback(gdma_channel_handle_t dma_camrx_chan, gdma_event_data_t *event_data, void *user_data) {
Serial.println("End of DMA transfer");
return true;
}

void setup() {
Serial.begin(115200);

// LCD_CAM peripheral enable and reset
periph_module_enable(PERIPH_LCD_CAM_MODULE);
periph_module_reset(PERIPH_LCD_CAM_MODULE);

////////// Reset CAM bus
LCD_CAM.cam_ctrl1.cam_reset = 1;

// CAM module registers configuration
LCD_CAM.cam_ctrl.cam_clk_sel = 1; // XTAL_CLK source (40MHz)
LCD_CAM.cam_ctrl.cam_clkm_div_num = 2; // CAM_CLK_IDX = 20MHz
LCD_CAM.cam_ctrl.cam_clkm_div_b = 0;
LCD_CAM.cam_ctrl.cam_clkm_div_a = 0;
LCD_CAM.cam_ctrl1.cam_vh_de_mode_en = 1;
LCD_CAM.cam_ctrl.cam_update = 1;

// Route CAM signals to GPIO pins
const struct {
uint32_t pin;
uint8_t signal;
} mux[] = {
{ d2_pin, CAM_DATA_IN0_IDX }, { d3_pin, CAM_DATA_IN1_IDX }, { d4_pin, CAM_DATA_IN2_IDX },
{ d5_pin, CAM_DATA_IN3_IDX }, { d6_pin, CAM_DATA_IN4_IDX }, { d7_pin, CAM_DATA_IN5_IDX },
{ d8_pin, CAM_DATA_IN6_IDX }, { d9_pin, CAM_DATA_IN7_IDX }, { pclk_pin, CAM_PCLK_IDX },
{ href_pin, CAM_H_ENABLE_IDX },
{ GPIO_MATRIX_CONST_ONE_INPUT, CAM_H_SYNC_IDX }, { GPIO_MATRIX_CONST_ONE_INPUT, CAM_V_SYNC_IDX }
};
for (int i = 0; i < 12; i++) {
if (mux[i].pin != GPIO_MATRIX_CONST_ONE_INPUT) {
esp_rom_gpio_pad_select_gpio(mux[i].pin);
}
esp_rom_gpio_connect_in_signal(mux[i].pin, mux[i].signal, false);
}
esp_rom_gpio_pad_select_gpio(xclk_pin);
esp_rom_gpio_pad_set_drv(xclk_pin, 3);
esp_rom_gpio_connect_out_signal(xclk_pin, CAM_CLK_IDX, false, false);

// GDMA descriptor
desc.dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
desc.dw0.suc_eof = 1; // Last descriptor
desc.dw0.size = dmabuf_camrx_len;
desc.buffer = dmabuf_camrx;
desc.next = NULL;

// Allocate DMA channel and connect it to the CAM peripheral
gdma_channel_alloc_config_t dma_camrx_chan_config = {
.sibling_chan = NULL,
.direction = GDMA_CHANNEL_DIRECTION_RX,
.flags = {
.reserve_sibling = 0
}
};
gdma_new_channel(&dma_camrx_chan_config, &dma_camrx_chan);
gdma_connect(dma_camrx_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_CAM, 0));
gdma_strategy_config_t strategy_config = {
.owner_check = false,
.auto_update_desc = false
};
gdma_apply_strategy(dma_camrx_chan, &strategy_config);

// Enable DMA transfer callback
gdma_rx_event_callbacks_t rx_cbs = {
.on_recv_eof = dma_callback
};
gdma_register_rx_event_callbacks(dma_camrx_chan, &rx_cbs, NULL);

// Here OV5640 camera configuration code using I2C
//////////////////////
// Camera interface is ok checked with a logic analyzer (xclk, pclk, vsync and href)

delay(50);

gdma_reset(dma_camrx_chan); // Reset DMA to known state
LCD_CAM.cam_ctrl.cam_update = 1; // Update registers
LCD_CAM.cam_ctrl1.cam_afifo_reset = 1;

gdma_start(dma_camrx_chan, (intptr_t)&desc); // Start DMA

LCD_CAM.cam_ctrl1.cam_start = 1; // Trigger CAM DMA transfer
}

void loop() {
delay(10);
}
`

Comment options

The camera driver is public and open source, I suggest you look there. It is not a basic task to get it going and here is not the place to discuss such topics really. What is the reason not to use the already developed driver?

Comment options

Hello, I have reviewed the CameraWebServer.ino file and I think it does not support my requirements.

My goal is to stream the video from the camera by sending UDP Multicast datagrams with the minimum delay.

I managed to do this years ago in an ESP32 using the I2S peripheral and DMA , based on esp32-camera.

Now I want to achieve the same in an ESP32-S3 using the new LCD_CAM peripheral and GDMA, for which
I am basing myself on https://blog.adafruit.com/2022/06/21/esp32uesday-more-s3-lcd-peripheral-hacking-with-code/

Regards.

Comment options

how you transfer is outside of the question. The driver provides you with a good way to grab a frame as soon as it's ready. What you do wit it from then on it does not matter. Your answers is outside of the camera driver and I strongly suggest that you use it.

Comment options

ok, I will use the camera driver, thanks.

Answer selected by JPMJPM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants

AltStyle によって変換されたページ (->オリジナル) /