Browse Source

Adjust clocks and DMA for non-jpeg modes and enable EDMA only for 16MHz XCLK

pull/279/head
me-no-dev 4 years ago
parent
commit
7da9cb5ea3
  1. 6
      driver/cam_hal.c
  2. 33
      sensors/ov2640.c
  3. 16
      sensors/ov3660.c
  4. 14
      sensors/ov5640.c
  5. 1
      target/esp32/ll_cam.c
  6. 88
      target/esp32s2/ll_cam.c
  7. 95
      target/esp32s3/ll_cam.c
  8. 15
      target/private_include/ll_cam.h

6
driver/cam_hal.c

@ -100,7 +100,7 @@ static void cam_task(void *arg) @@ -100,7 +100,7 @@ static void cam_task(void *arg)
while (1) {
xQueueReceive(cam_obj->event_queue, (void *)&cam_event, portMAX_DELAY);
//DBG_PIN_SET(1);
DBG_PIN_SET(1);
switch (cam_obj->state) {
case CAM_STATE_IDLE: {
@ -203,7 +203,7 @@ static void cam_task(void *arg) @@ -203,7 +203,7 @@ static void cam_task(void *arg)
}
break;
}
//DBG_PIN_SET(0);
DBG_PIN_SET(0);
}
}
@ -315,7 +315,7 @@ esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint @@ -315,7 +315,7 @@ esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint
#if CONFIG_IDF_TARGET_ESP32
cam_obj->psram_mode = false;
#else
cam_obj->psram_mode = !cam_obj->jpeg_mode;
cam_obj->psram_mode = !cam_obj->jpeg_mode && (config->xclk_freq_hz == 16000000);
#endif
cam_obj->frame_cnt = config->fb_count;
cam_obj->width = resolution[frame_size].width;

33
sensors/ov2640.c

@ -157,26 +157,37 @@ static int set_window(sensor_t *sensor, ov2640_sensor_mode_t mode, int offset_x, @@ -157,26 +157,37 @@ static int set_window(sensor_t *sensor, ov2640_sensor_mode_t mode, int offset_x,
{0, 0}
};
c.pclk_auto = 0;
c.pclk_div = 8;
c.clk_2x = 0;
c.clk_div = 0;
if(sensor->pixformat != PIXFORMAT_JPEG){
c.pclk_auto = 1;
if (sensor->pixformat == PIXFORMAT_JPEG) {
c.clk_2x = 0;
c.clk_div = 0;
c.pclk_auto = 0;
c.pclk_div = 8;
if(mode == OV2640_MODE_UXGA) {
c.pclk_div = 12;
}
} else {
#if CONFIG_IDF_TARGET_ESP32
c.clk_2x = 0;
#else
c.clk_2x = 1;
#endif
c.clk_div = 7;
c.pclk_auto = 1;
c.pclk_div = 8;
if (mode == OV2640_MODE_CIF) {
c.clk_div = 3;
} else if(mode == OV2640_MODE_UXGA) {
c.pclk_div = 12;
}
}
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);
if (mode == OV2640_MODE_CIF) {
regs = ov2640_settings_to_cif;
if(sensor->pixformat != PIXFORMAT_JPEG){
c.clk_div = 3;
}
} else if (mode == OV2640_MODE_SVGA) {
regs = ov2640_settings_to_svga;
} else {
regs = ov2640_settings_to_uxga;
c.pclk_div = 12;
}
WRITE_REG_OR_RETURN(BANK_DSP, R_BYPASS, R_BYPASS_DSP_BYPAS);

16
sensors/ov3660.c

@ -142,7 +142,7 @@ static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sy @@ -142,7 +142,7 @@ static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sy
int PCLK = PLLCLK / 2 / ((pclk_manual && pclk_div)?pclk_div:1);
int SYSCLK = PLLCLK / 4;
ESP_LOGD(TAG, "Calculated VCO: %d Hz, PLLCLK: %d Hz, SYSCLK: %d Hz, PCLK: %d Hz", VCO*1000, PLLCLK, SYSCLK, PCLK);
ESP_LOGI(TAG, "Calculated VCO: %d Hz, PLLCLK: %d Hz, SYSCLK: %d Hz, PCLK: %d Hz", VCO*1000, PLLCLK, SYSCLK, PCLK);
return SYSCLK;
}
@ -363,12 +363,16 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize) @@ -363,12 +363,16 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
ret = set_pll(sensor, false, 30, 1, 3, false, 0, true, 10);
}
} else {
if (framesize > FRAMESIZE_CIF) {
//10MHz SYSCLK and 10MHz PCLK (6.19 FPS)
ret = set_pll(sensor, false, 2, 1, 0, false, 0, true, 2);
//tuned for 16MHz XCLK
if (framesize > FRAMESIZE_HVGA) {
//8MHz SYSCLK and 8MHz PCLK (4.44 FPS)
ret = set_pll(sensor, false, 4, 1, 0, false, 2, true, 2);
} else if (framesize >= FRAMESIZE_QVGA) {
//16MHz SYSCLK and 8MHz PCLK (10.25 FPS)
ret = set_pll(sensor, false, 8, 1, 0, false, 2, true, 4);
} else {
//25MHz SYSCLK and 10MHz PCLK (15.45 FPS)
ret = set_pll(sensor, false, 5, 1, 0, false, 0, true, 5);
//32MHz SYSCLK and 8MHz PCLK (17.77 FPS)
ret = set_pll(sensor, false, 8, 1, 0, false, 0, true, 8);
}
}

14
sensors/ov5640.c

@ -196,7 +196,7 @@ static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sy @@ -196,7 +196,7 @@ static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sy
unsigned int SYSCLK = PLL_CLK / 4;
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);
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);
return SYSCLK;
}
@ -441,10 +441,14 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize) @@ -441,10 +441,14 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
ret = set_pll(sensor, false, sys_mul, 4, 2, false, 2, true, 4);
//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
} else {
//ret = set_pll(sensor, false, 10, 1, 1, false, 1, true, 4);
//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
ret = set_pll(sensor, false, 8, 1, 1, false, 1, true, 4);
//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
//ret = set_pll(sensor, false, 8, 1, 1, false, 1, true, 4);
if (framesize > FRAMESIZE_HVGA) {
ret = set_pll(sensor, false, 10, 1, 2, false, 1, true, 2);
} else if (framesize >= FRAMESIZE_QVGA) {
ret = set_pll(sensor, false, 8, 1, 1, false, 1, true, 4);
} else {
ret = set_pll(sensor, false, 20, 1, 1, false, 1, true, 8);
}
}
if (ret == 0) {

1
target/esp32/ll_cam.c

@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
#include <stdio.h>
#include <string.h>
#include "soc/i2s_struct.h"
#include "esp_idf_version.h"
#if ESP_IDF_VERSION_MAJOR >= 4
#include "hal/gpio_ll.h"
#else

88
target/esp32s2/ll_cam.c

@ -249,10 +249,83 @@ uint8_t ll_cam_get_dma_align(cam_obj_t *cam) @@ -249,10 +249,83 @@ uint8_t ll_cam_get_dma_align(cam_obj_t *cam)
return 16 << I2S0.lc_conf.ext_mem_bk_size;
}
static void ll_cam_calc_rgb_dma(cam_obj_t *cam){
size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item;
size_t line_width = cam->width * cam->in_bytes_per_pixel;
size_t node_size = node_max;
size_t nodes_per_line = 1;
size_t lines_per_node = 1;
// Calculate DMA Node Size so that it's divisable by or divisor of the line width
if(line_width >= node_max){
// One or more nodes will be requied for one line
for(size_t i = node_max; i > 0; i=i-1){
if ((line_width % i) == 0) {
node_size = i;
nodes_per_line = line_width / node_size;
break;
}
}
} else {
// One or more lines can fit into one node
for(size_t i = node_max; i > 0; i=i-1){
if ((i % line_width) == 0) {
node_size = i;
lines_per_node = node_size / line_width;
while((cam->height % lines_per_node) != 0){
lines_per_node = lines_per_node - 1;
node_size = lines_per_node * line_width;
}
break;
}
}
}
ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u",
node_size * cam->dma_bytes_per_item, nodes_per_line, lines_per_node);
cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item;
if (cam->psram_mode) {
cam->dma_buffer_size = cam->recv_size * cam->dma_bytes_per_item;
cam->dma_half_buffer_cnt = 2;
cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
} else {
size_t dma_half_buffer_max = 16 * 1024 / cam->dma_bytes_per_item;
if (line_width > dma_half_buffer_max) {
ESP_LOGE(TAG, "Resolution too high");
return;
}
// Calculate minimum EOF size = max(mode_size, line_size)
size_t dma_half_buffer_min = node_size * nodes_per_line;
// Calculate max EOF size divisable by node size
size_t dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min;
// Adjust EOF size so that height will be divisable by the number of lines in each EOF
size_t lines_per_half_buffer = dma_half_buffer / line_width;
while((cam->height % lines_per_half_buffer) != 0){
dma_half_buffer = dma_half_buffer - dma_half_buffer_min;
lines_per_half_buffer = dma_half_buffer / line_width;
}
// Calculate DMA size
size_t dma_buffer_max = 2 * dma_half_buffer_max;
size_t dma_buffer_size = dma_buffer_max;
dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer;
ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u",
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);
cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item;
cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item;
cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size;
}
}
void ll_cam_dma_sizes(cam_obj_t *cam)
{
int cnt = 0;
cam->dma_bytes_per_item = 1;
if (cam->jpeg_mode) {
cam->dma_half_buffer_cnt = 16;
@ -260,16 +333,7 @@ void ll_cam_dma_sizes(cam_obj_t *cam) @@ -260,16 +333,7 @@ void ll_cam_dma_sizes(cam_obj_t *cam)
cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
cam->dma_node_buffer_size = cam->dma_half_buffer_size;
} else {
cam->dma_buffer_size = cam->recv_size;
cam->dma_half_buffer_cnt = 2;
cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
for (cnt = 0; cnt < LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE; cnt++) { // Find a divisible dma size
if ((cam->dma_half_buffer_size) % (LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - cnt) == 0) {
break;
}
}
cam->dma_node_buffer_size = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - cnt;
ll_cam_calc_rgb_dma(cam);
}
}

95
target/esp32s3/ll_cam.c

@ -267,10 +267,82 @@ uint8_t ll_cam_get_dma_align(cam_obj_t *cam) @@ -267,10 +267,82 @@ uint8_t ll_cam_get_dma_align(cam_obj_t *cam)
return 16 << GDMA.in[cam->dma_num].conf1.in_ext_mem_bk_size;
}
void ll_cam_dma_sizes(cam_obj_t *cam)
{
int cnt = 0;
static void ll_cam_calc_rgb_dma(cam_obj_t *cam){
size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item;
size_t line_width = cam->width * cam->in_bytes_per_pixel;
size_t node_size = node_max;
size_t nodes_per_line = 1;
size_t lines_per_node = 1;
// Calculate DMA Node Size so that it's divisable by or divisor of the line width
if(line_width >= node_max){
// One or more nodes will be requied for one line
for(size_t i = node_max; i > 0; i=i-1){
if ((line_width % i) == 0) {
node_size = i;
nodes_per_line = line_width / node_size;
break;
}
}
} else {
// One or more lines can fit into one node
for(size_t i = node_max; i > 0; i=i-1){
if ((i % line_width) == 0) {
node_size = i;
lines_per_node = node_size / line_width;
while((cam->height % lines_per_node) != 0){
lines_per_node = lines_per_node - 1;
node_size = lines_per_node * line_width;
}
break;
}
}
}
ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u",
node_size * cam->dma_bytes_per_item, nodes_per_line, lines_per_node);
cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item;
size_t dma_half_buffer_max = 16 * 1024 / cam->dma_bytes_per_item;
if (line_width > dma_half_buffer_max) {
ESP_LOGE(TAG, "Resolution too high");
return;
}
// Calculate minimum EOF size = max(mode_size, line_size)
size_t dma_half_buffer_min = node_size * nodes_per_line;
// Calculate max EOF size divisable by node size
size_t dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min;
// Adjust EOF size so that height will be divisable by the number of lines in each EOF
size_t lines_per_half_buffer = dma_half_buffer / line_width;
while((cam->height % lines_per_half_buffer) != 0){
dma_half_buffer = dma_half_buffer - dma_half_buffer_min;
lines_per_half_buffer = dma_half_buffer / line_width;
}
// Calculate DMA size
size_t dma_buffer_max = 2 * dma_half_buffer_max;
if (cam->psram_mode) {
dma_buffer_max = cam->recv_size / cam->dma_bytes_per_item;
}
size_t dma_buffer_size = dma_buffer_max;
if (!cam->psram_mode) {
dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer;
}
ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u",
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);
cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item;
cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item;
cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size;
}
void ll_cam_dma_sizes(cam_obj_t *cam)
{
cam->dma_bytes_per_item = 1;
if (cam->jpeg_mode) {
cam->dma_half_buffer_cnt = 16;
@ -278,22 +350,7 @@ void ll_cam_dma_sizes(cam_obj_t *cam) @@ -278,22 +350,7 @@ void ll_cam_dma_sizes(cam_obj_t *cam)
cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
cam->dma_node_buffer_size = cam->dma_half_buffer_size;
} else {
int max_cam_rec_data_bytelen = 16384;
for (cnt = 0; cnt < max_cam_rec_data_bytelen; cnt++) {
if (cam->recv_size % (max_cam_rec_data_bytelen - cnt) == 0) {
break;
}
}
cam->dma_buffer_size = cam->recv_size;
cam->dma_half_buffer_size = max_cam_rec_data_bytelen - cnt;
cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size;
for (cnt = 0; cnt < LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE; cnt++) { // Find a divisible dma size
if ((cam->dma_half_buffer_size) % (LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - cnt) == 0) {
break;
}
}
cam->dma_node_buffer_size = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - cnt;
ll_cam_calc_rgb_dma(cam);
}
}

15
target/private_include/ll_cam.h

@ -35,12 +35,17 @@ @@ -35,12 +35,17 @@
#include "freertos/task.h"
#include "freertos/semphr.h"
#define DBG_PIN_NUM -1//7//26
#if DBG_PIN_NUM >= 0
#include "hal/gpio_ll.h"
#define DBG_PIN_SET(v) gpio_ll_set_level(&GPIO, DBG_PIN_NUM, v)
#define CAMERA_DBG_PIN_ENABLE 0
#if CAMERA_DBG_PIN_ENABLE
#if CONFIG_IDF_TARGET_ESP32
#define DBG_PIN_NUM 26
#else
#define DBG_PIN_NUM 7
#endif
#include "hal/gpio_ll.h"
#define DBG_PIN_SET(v) gpio_ll_set_level(&GPIO, DBG_PIN_NUM, v)
#else
#define DBG_PIN_SET(v)
#define DBG_PIN_SET(v)
#endif
#define CAM_CHECK(a, str, ret) if (!(a)) { \

Loading…
Cancel
Save