Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7da9cb5

Browse files
committed
Adjust clocks and DMA for non-jpeg modes and enable EDMA only for 16MHz XCLK
1 parent 6f8489e commit 7da9cb5

File tree

8 files changed

+207
-61
lines changed

8 files changed

+207
-61
lines changed

driver/cam_hal.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ static void cam_task(void *arg)
100100

101101
while (1) {
102102
xQueueReceive(cam_obj->event_queue, (void *)&cam_event, portMAX_DELAY);
103-
//DBG_PIN_SET(1);
103+
DBG_PIN_SET(1);
104104
switch (cam_obj->state) {
105105

106106
case CAM_STATE_IDLE: {
@@ -203,7 +203,7 @@ static void cam_task(void *arg)
203203
}
204204
break;
205205
}
206-
//DBG_PIN_SET(0);
206+
DBG_PIN_SET(0);
207207
}
208208
}
209209

@@ -315,7 +315,7 @@ esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint
315315
#if CONFIG_IDF_TARGET_ESP32
316316
cam_obj->psram_mode = false;
317317
#else
318-
cam_obj->psram_mode = !cam_obj->jpeg_mode;
318+
cam_obj->psram_mode = !cam_obj->jpeg_mode && (config->xclk_freq_hz == 16000000);
319319
#endif
320320
cam_obj->frame_cnt = config->fb_count;
321321
cam_obj->width = resolution[frame_size].width;

sensors/ov2640.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -157,26 +157,37 @@ static int set_window(sensor_t *sensor, ov2640_sensor_mode_t mode, int offset_x,
157157
{0, 0}
158158
};
159159

160-
c.pclk_auto = 0;
161-
c.pclk_div = 8;
162-
c.clk_2x = 0;
163-
c.clk_div = 0;
164-
165-
if(sensor->pixformat != PIXFORMAT_JPEG){
166-
c.pclk_auto = 1;
160+
if (sensor->pixformat == PIXFORMAT_JPEG) {
161+
c.clk_2x = 0;
162+
c.clk_div = 0;
163+
c.pclk_auto = 0;
164+
c.pclk_div = 8;
165+
if(mode == OV2640_MODE_UXGA) {
166+
c.pclk_div = 12;
167+
}
168+
} else {
169+
#if CONFIG_IDF_TARGET_ESP32
170+
c.clk_2x = 0;
171+
#else
172+
c.clk_2x = 1;
173+
#endif
167174
c.clk_div = 7;
175+
c.pclk_auto = 1;
176+
c.pclk_div = 8;
177+
if (mode == OV2640_MODE_CIF) {
178+
c.clk_div = 3;
179+
} else if(mode == OV2640_MODE_UXGA) {
180+
c.pclk_div = 12;
181+
}
168182
}
183+
ESP_LOGI(TAG, "Set PLL: clk_2x: %u, clk_div: %u, pclk_auto: %u, pclk_div: %u", c.clk_2x, c.clk_div, c.pclk_auto, c.pclk_div);
169184

170185
if (mode == OV2640_MODE_CIF) {
171186
regs = ov2640_settings_to_cif;
172-
if(sensor->pixformat != PIXFORMAT_JPEG){
173-
c.clk_div = 3;
174-
}
175187
} else if (mode == OV2640_MODE_SVGA) {
176188
regs = ov2640_settings_to_svga;
177189
} else {
178190
regs = ov2640_settings_to_uxga;
179-
c.pclk_div = 12;
180191
}
181192

182193
WRITE_REG_OR_RETURN(BANK_DSP, R_BYPASS, R_BYPASS_DSP_BYPAS);

sensors/ov3660.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sy
142142
int PCLK = PLLCLK / 2 / ((pclk_manual && pclk_div)?pclk_div:1);
143143
int SYSCLK = PLLCLK / 4;
144144

145-
ESP_LOGD(TAG, "Calculated VCO: %d Hz, PLLCLK: %d Hz, SYSCLK: %d Hz, PCLK: %d Hz", VCO*1000, PLLCLK, SYSCLK, PCLK);
145+
ESP_LOGI(TAG, "Calculated VCO: %d Hz, PLLCLK: %d Hz, SYSCLK: %d Hz, PCLK: %d Hz", VCO*1000, PLLCLK, SYSCLK, PCLK);
146146
return SYSCLK;
147147
}
148148

@@ -363,12 +363,16 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
363363
ret = set_pll(sensor, false, 30, 1, 3, false, 0, true, 10);
364364
}
365365
} else {
366-
if (framesize > FRAMESIZE_CIF) {
367-
//10MHz SYSCLK and 10MHz PCLK (6.19 FPS)
368-
ret = set_pll(sensor, false, 2, 1, 0, false, 0, true, 2);
366+
//tuned for 16MHz XCLK
367+
if (framesize > FRAMESIZE_HVGA) {
368+
//8MHz SYSCLK and 8MHz PCLK (4.44 FPS)
369+
ret = set_pll(sensor, false, 4, 1, 0, false, 2, true, 2);
370+
} else if (framesize >= FRAMESIZE_QVGA) {
371+
//16MHz SYSCLK and 8MHz PCLK (10.25 FPS)
372+
ret = set_pll(sensor, false, 8, 1, 0, false, 2, true, 4);
369373
} else {
370-
//25MHz SYSCLK and 10MHz PCLK (15.45 FPS)
371-
ret = set_pll(sensor, false, 5, 1, 0, false, 0, true, 5);
374+
//32MHz SYSCLK and 8MHz PCLK (17.77 FPS)
375+
ret = set_pll(sensor, false, 8, 1, 0, false, 0, true, 8);
372376
}
373377
}
374378

sensors/ov5640.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sy
196196

197197
unsigned int SYSCLK = PLL_CLK / 4;
198198

199-
ESP_LOGD(TAG, "Calculated XVCLK: %d Hz, REFIN: %u Hz, VCO: %u Hz, PLL_CLK: %u Hz, SYSCLK: %u Hz, PCLK: %u Hz", xclk, REFIN, VCO, PLL_CLK, SYSCLK, PCLK);
199+
ESP_LOGI(TAG, "Calculated XVCLK: %d Hz, REFIN: %u Hz, VCO: %u Hz, PLL_CLK: %u Hz, SYSCLK: %u Hz, PCLK: %u Hz", xclk, REFIN, VCO, PLL_CLK, SYSCLK, PCLK);
200200
return SYSCLK;
201201
}
202202

@@ -441,10 +441,14 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
441441
ret = set_pll(sensor, false, sys_mul, 4, 2, false, 2, true, 4);
442442
//Set PLL: bypass: 0, multiplier: sys_mul, sys_div: 4, pre_div: 2, root_2x: 0, pclk_root_div: 2, pclk_manual: 1, pclk_div: 4
443443
} else {
444-
//ret = set_pll(sensor, false, 10, 1, 1, false, 1, true, 4);
445-
//Set PLL: bypass: 0, multiplier: 10, sys_div: 1, pre_div: 1, root_2x: 0, pclk_root_div: 1, pclk_manual: 1, pclk_div: 4
446-
ret = set_pll(sensor, false, 8, 1, 1, false, 1, true, 4);
447-
//Set PLL: bypass: 0, multiplier: 8, sys_div: 1, pre_div: 1, root_2x: 0, pclk_root_div: 1, pclk_manual: 1, pclk_div: 4
444+
//ret = set_pll(sensor, false, 8, 1, 1, false, 1, true, 4);
445+
if (framesize > FRAMESIZE_HVGA) {
446+
ret = set_pll(sensor, false, 10, 1, 2, false, 1, true, 2);
447+
} else if (framesize >= FRAMESIZE_QVGA) {
448+
ret = set_pll(sensor, false, 8, 1, 1, false, 1, true, 4);
449+
} else {
450+
ret = set_pll(sensor, false, 20, 1, 1, false, 1, true, 8);
451+
}
448452
}
449453

450454
if (ret == 0) {

target/esp32/ll_cam.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <stdio.h>
1616
#include <string.h>
1717
#include "soc/i2s_struct.h"
18+
#include "esp_idf_version.h"
1819
#if ESP_IDF_VERSION_MAJOR >= 4
1920
#include "hal/gpio_ll.h"
2021
#else

target/esp32s2/ll_cam.c

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -249,27 +249,91 @@ uint8_t ll_cam_get_dma_align(cam_obj_t *cam)
249249
return 16 << I2S0.lc_conf.ext_mem_bk_size;
250250
}
251251

252+
static void ll_cam_calc_rgb_dma(cam_obj_t *cam){
253+
size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item;
254+
size_t line_width = cam->width * cam->in_bytes_per_pixel;
255+
size_t node_size = node_max;
256+
size_t nodes_per_line = 1;
257+
size_t lines_per_node = 1;
258+
259+
// Calculate DMA Node Size so that it's divisable by or divisor of the line width
260+
if(line_width >= node_max){
261+
// One or more nodes will be requied for one line
262+
for(size_t i = node_max; i > 0; i=i-1){
263+
if ((line_width % i) == 0) {
264+
node_size = i;
265+
nodes_per_line = line_width / node_size;
266+
break;
267+
}
268+
}
269+
} else {
270+
// One or more lines can fit into one node
271+
for(size_t i = node_max; i > 0; i=i-1){
272+
if ((i % line_width) == 0) {
273+
node_size = i;
274+
lines_per_node = node_size / line_width;
275+
while((cam->height % lines_per_node) != 0){
276+
lines_per_node = lines_per_node - 1;
277+
node_size = lines_per_node * line_width;
278+
}
279+
break;
280+
}
281+
}
282+
}
283+
284+
ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u",
285+
node_size * cam->dma_bytes_per_item, nodes_per_line, lines_per_node);
286+
287+
cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item;
288+
289+
if (cam->psram_mode) {
290+
cam->dma_buffer_size = cam->recv_size * cam->dma_bytes_per_item;
291+
cam->dma_half_buffer_cnt = 2;
292+
cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
293+
} else {
294+
size_t dma_half_buffer_max = 16 * 1024 / cam->dma_bytes_per_item;
295+
if (line_width > dma_half_buffer_max) {
296+
ESP_LOGE(TAG, "Resolution too high");
297+
return;
298+
}
299+
300+
// Calculate minimum EOF size = max(mode_size, line_size)
301+
size_t dma_half_buffer_min = node_size * nodes_per_line;
302+
303+
// Calculate max EOF size divisable by node size
304+
size_t dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min;
305+
306+
// Adjust EOF size so that height will be divisable by the number of lines in each EOF
307+
size_t lines_per_half_buffer = dma_half_buffer / line_width;
308+
while((cam->height % lines_per_half_buffer) != 0){
309+
dma_half_buffer = dma_half_buffer - dma_half_buffer_min;
310+
lines_per_half_buffer = dma_half_buffer / line_width;
311+
}
312+
313+
// Calculate DMA size
314+
size_t dma_buffer_max = 2 * dma_half_buffer_max;
315+
size_t dma_buffer_size = dma_buffer_max;
316+
dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer;
317+
318+
ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u",
319+
dma_half_buffer_min * cam->dma_bytes_per_item, dma_half_buffer * cam->dma_bytes_per_item, lines_per_half_buffer, dma_buffer_size * cam->dma_bytes_per_item);
320+
321+
cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item;
322+
cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item;
323+
cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size;
324+
}
325+
}
326+
252327
void ll_cam_dma_sizes(cam_obj_t *cam)
253328
{
254-
int cnt = 0;
255-
256329
cam->dma_bytes_per_item = 1;
257330
if (cam->jpeg_mode) {
258331
cam->dma_half_buffer_cnt = 16;
259332
cam->dma_buffer_size = cam->dma_half_buffer_cnt * 1024;
260333
cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
261334
cam->dma_node_buffer_size = cam->dma_half_buffer_size;
262335
} else {
263-
cam->dma_buffer_size = cam->recv_size;
264-
cam->dma_half_buffer_cnt = 2;
265-
cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
266-
267-
for (cnt = 0; cnt < LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE; cnt++) { // Find a divisible dma size
268-
if ((cam->dma_half_buffer_size) % (LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - cnt) == 0) {
269-
break;
270-
}
271-
}
272-
cam->dma_node_buffer_size = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - cnt;
336+
ll_cam_calc_rgb_dma(cam);
273337
}
274338
}
275339

target/esp32s3/ll_cam.c

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -267,33 +267,90 @@ uint8_t ll_cam_get_dma_align(cam_obj_t *cam)
267267
return 16 << GDMA.in[cam->dma_num].conf1.in_ext_mem_bk_size;
268268
}
269269

270-
void ll_cam_dma_sizes(cam_obj_t *cam)
271-
{
272-
int cnt = 0;
270+
static void ll_cam_calc_rgb_dma(cam_obj_t *cam){
271+
size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item;
272+
size_t line_width = cam->width * cam->in_bytes_per_pixel;
273+
size_t node_size = node_max;
274+
size_t nodes_per_line = 1;
275+
size_t lines_per_node = 1;
276+
277+
// Calculate DMA Node Size so that it's divisable by or divisor of the line width
278+
if(line_width >= node_max){
279+
// One or more nodes will be requied for one line
280+
for(size_t i = node_max; i > 0; i=i-1){
281+
if ((line_width % i) == 0) {
282+
node_size = i;
283+
nodes_per_line = line_width / node_size;
284+
break;
285+
}
286+
}
287+
} else {
288+
// One or more lines can fit into one node
289+
for(size_t i = node_max; i > 0; i=i-1){
290+
if ((i % line_width) == 0) {
291+
node_size = i;
292+
lines_per_node = node_size / line_width;
293+
while((cam->height % lines_per_node) != 0){
294+
lines_per_node = lines_per_node - 1;
295+
node_size = lines_per_node * line_width;
296+
}
297+
break;
298+
}
299+
}
300+
}
301+
302+
ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u",
303+
node_size * cam->dma_bytes_per_item, nodes_per_line, lines_per_node);
304+
305+
cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item;
306+
307+
size_t dma_half_buffer_max = 16 * 1024 / cam->dma_bytes_per_item;
308+
if (line_width > dma_half_buffer_max) {
309+
ESP_LOGE(TAG, "Resolution too high");
310+
return;
311+
}
312+
313+
// Calculate minimum EOF size = max(mode_size, line_size)
314+
size_t dma_half_buffer_min = node_size * nodes_per_line;
315+
316+
// Calculate max EOF size divisable by node size
317+
size_t dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min;
318+
319+
// Adjust EOF size so that height will be divisable by the number of lines in each EOF
320+
size_t lines_per_half_buffer = dma_half_buffer / line_width;
321+
while((cam->height % lines_per_half_buffer) != 0){
322+
dma_half_buffer = dma_half_buffer - dma_half_buffer_min;
323+
lines_per_half_buffer = dma_half_buffer / line_width;
324+
}
325+
326+
// Calculate DMA size
327+
size_t dma_buffer_max = 2 * dma_half_buffer_max;
328+
if (cam->psram_mode) {
329+
dma_buffer_max = cam->recv_size / cam->dma_bytes_per_item;
330+
}
331+
size_t dma_buffer_size = dma_buffer_max;
332+
if (!cam->psram_mode) {
333+
dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer;
334+
}
273335

336+
ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u",
337+
dma_half_buffer_min * cam->dma_bytes_per_item, dma_half_buffer * cam->dma_bytes_per_item, lines_per_half_buffer, dma_buffer_size * cam->dma_bytes_per_item);
338+
339+
cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item;
340+
cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item;
341+
cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size;
342+
}
343+
344+
void ll_cam_dma_sizes(cam_obj_t *cam)
345+
{
274346
cam->dma_bytes_per_item = 1;
275347
if (cam->jpeg_mode) {
276348
cam->dma_half_buffer_cnt = 16;
277349
cam->dma_buffer_size = cam->dma_half_buffer_cnt * 1024;
278350
cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
279351
cam->dma_node_buffer_size = cam->dma_half_buffer_size;
280352
} else {
281-
int max_cam_rec_data_bytelen = 16384;
282-
for (cnt = 0; cnt < max_cam_rec_data_bytelen; cnt++) {
283-
if (cam->recv_size % (max_cam_rec_data_bytelen - cnt) == 0) {
284-
break;
285-
}
286-
}
287-
cam->dma_buffer_size = cam->recv_size;
288-
cam->dma_half_buffer_size = max_cam_rec_data_bytelen - cnt;
289-
cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size;
290-
291-
for (cnt = 0; cnt < LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE; cnt++) { // Find a divisible dma size
292-
if ((cam->dma_half_buffer_size) % (LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - cnt) == 0) {
293-
break;
294-
}
295-
}
296-
cam->dma_node_buffer_size = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - cnt;
353+
ll_cam_calc_rgb_dma(cam);
297354
}
298355
}
299356

target/private_include/ll_cam.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,17 @@
3535
#include "freertos/task.h"
3636
#include "freertos/semphr.h"
3737

38-
#define DBG_PIN_NUM -1//7//26
39-
#if DBG_PIN_NUM >= 0
40-
#include "hal/gpio_ll.h"
41-
#define DBG_PIN_SET(v) gpio_ll_set_level(&GPIO, DBG_PIN_NUM, v)
38+
#define CAMERA_DBG_PIN_ENABLE 0
39+
#if CAMERA_DBG_PIN_ENABLE
40+
#if CONFIG_IDF_TARGET_ESP32
41+
#define DBG_PIN_NUM 26
42+
#else
43+
#define DBG_PIN_NUM 7
44+
#endif
45+
#include "hal/gpio_ll.h"
46+
#define DBG_PIN_SET(v) gpio_ll_set_level(&GPIO, DBG_PIN_NUM, v)
4247
#else
43-
#define DBG_PIN_SET(v)
48+
#define DBG_PIN_SET(v)
4449
#endif
4550

4651
#define CAM_CHECK(a, str, ret) if (!(a)) { \

0 commit comments

Comments
 (0)