initial 5640 support

This commit is contained in:
me-no-dev
2020-02-25 01:05:01 +02:00
parent a4f6d924ce
commit ae32d52cc2
20 changed files with 2189 additions and 239 deletions

View File

@@ -45,6 +45,9 @@
#if CONFIG_OV3660_SUPPORT
#include "ov3660.h"
#endif
#if CONFIG_OV5640_SUPPORT
#include "ov5640.h"
#endif
typedef enum {
CAMERA_NONE = 0,
@@ -52,6 +55,7 @@ typedef enum {
CAMERA_OV7725 = 7725,
CAMERA_OV2640 = 2640,
CAMERA_OV3660 = 3660,
CAMERA_OV5640 = 5640,
} camera_model_t;
#define REG_PID 0x0A
@@ -80,6 +84,7 @@ typedef struct camera_fb_s {
size_t width;
size_t height;
pixformat_t format;
struct timeval timestamp;
size_t size;
uint8_t ref;
uint8_t bad;
@@ -546,6 +551,7 @@ static void IRAM_ATTR signal_dma_buf_received(bool* need_yield)
}
//ESP_EARLY_LOGW(TAG, "qsf:%d", s_state->dma_received_count);
//ets_printf("qsf:%d\n", s_state->dma_received_count);
//ets_printf("qovf\n");
}
*need_yield = (ret == pdTRUE && higher_priority_task_woken == pdTRUE);
}
@@ -577,6 +583,7 @@ static void IRAM_ATTR vsync_isr(void* arg)
if(s_state->dma_filtered_count > 1 || s_state->fb->bad || s_state->config.fb_count > 1) {
i2s_stop(&need_yield);
}
//ets_printf("vs\n");
}
if(s_state->config.fb_count > 1 || s_state->dma_filtered_count < 2) {
I2S0.conf.rx_start = 0;
@@ -669,6 +676,7 @@ static void IRAM_ATTR dma_finish_frame()
if(s_state->config.fb_count == 1) {
i2s_start_bus();
}
//ets_printf("bad\n");
} else {
s_state->fb->len = s_state->dma_filtered_count * buf_len;
if(s_state->fb->len) {
@@ -695,6 +703,8 @@ static void IRAM_ATTR dma_finish_frame()
} else if(s_state->config.fb_count == 1){
//frame was empty?
i2s_start_bus();
} else {
//ets_printf("empty\n");
}
}
} else if(s_state->fb->len) {
@@ -728,15 +738,19 @@ static void IRAM_ATTR dma_filter_buffer(size_t buf_idx)
if(s_state->sensor.pixformat == PIXFORMAT_JPEG) {
uint32_t sig = *((uint32_t *)s_state->fb->buf) & 0xFFFFFF;
if(sig != 0xffd8ff) {
//ets_printf("bad header\n");
ets_printf("bh 0x%08x\n", sig);
s_state->fb->bad = 1;
return;
}
}
//set the frame properties
s_state->fb->width = resolution[s_state->sensor.status.framesize][0];
s_state->fb->height = resolution[s_state->sensor.status.framesize][1];
s_state->fb->width = resolution[s_state->sensor.status.framesize].width;
s_state->fb->height = resolution[s_state->sensor.status.framesize].height;
s_state->fb->format = s_state->sensor.pixformat;
uint64_t us = (uint64_t)esp_timer_get_time();
s_state->fb->timestamp.tv_sec = us / 1000000UL;
s_state->fb->timestamp.tv_usec = us % 1000000UL;
}
s_state->dma_filtered_count++;
}
@@ -972,13 +986,6 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
vTaskDelay(10 / portTICK_PERIOD_MS);
gpio_set_level(config->pin_reset, 1);
vTaskDelay(10 / portTICK_PERIOD_MS);
#if (CONFIG_OV2640_SUPPORT && !CONFIG_OV3660_SUPPORT)
} else {
//reset OV2640
SCCB_Write(0x30, 0xFF, 0x01);//bank sensor
SCCB_Write(0x30, 0x12, 0x80);//reset
vTaskDelay(10 / portTICK_PERIOD_MS);
#endif
}
ESP_LOGD(TAG, "Searching for camera address");
@@ -989,15 +996,13 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
camera_disable_out_clock();
return ESP_ERR_CAMERA_NOT_DETECTED;
}
s_state->sensor.slv_addr = slv_addr;
s_state->sensor.xclk_freq_hz = config->xclk_freq_hz;
//s_state->sensor.slv_addr = 0x30;
ESP_LOGD(TAG, "Detected camera at address=0x%02x", s_state->sensor.slv_addr);
//slv_addr = 0x30;
ESP_LOGD(TAG, "Detected camera at address=0x%02x", slv_addr);
sensor_id_t* id = &s_state->sensor.id;
#if (CONFIG_OV2640_SUPPORT)
if (s_state->sensor.slv_addr == 0x30) {
#if CONFIG_OV2640_SUPPORT
if (slv_addr == 0x30) {
ESP_LOGD(TAG, "Resetting OV2640");
//camera might be OV2640. try to reset it
SCCB_Write(0x30, 0xFF, 0x01);//bank sensor
@@ -1007,7 +1012,10 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
}
#endif
#if CONFIG_OV3660_SUPPORT
s_state->sensor.slv_addr = slv_addr;
s_state->sensor.xclk_freq_hz = config->xclk_freq_hz;
#if (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT)
if(s_state->sensor.slv_addr == 0x3c){
id->PID = SCCB_Read16(s_state->sensor.slv_addr, REG16_CHIDH);
id->VER = SCCB_Read16(s_state->sensor.slv_addr, REG16_CHIDL);
@@ -1022,7 +1030,8 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
vTaskDelay(10 / portTICK_PERIOD_MS);
ESP_LOGD(TAG, "Camera PID=0x%02x VER=0x%02x MIDL=0x%02x MIDH=0x%02x",
id->PID, id->VER, id->MIDH, id->MIDL);
#if CONFIG_OV3660_SUPPORT
#if (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT)
}
#endif
@@ -1045,6 +1054,12 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
*out_camera_model = CAMERA_OV3660;
ov3660_init(&s_state->sensor);
break;
#endif
#if CONFIG_OV5640_SUPPORT
case OV5640_PID:
*out_camera_model = CAMERA_OV5640;
ov5640_init(&s_state->sensor);
break;
#endif
default:
id->PID = 0;
@@ -1072,12 +1087,46 @@ esp_err_t camera_init(const camera_config_t* config)
esp_err_t err = ESP_OK;
framesize_t frame_size = (framesize_t) config->frame_size;
pixformat_t pix_format = (pixformat_t) config->pixel_format;
s_state->width = resolution[frame_size][0];
s_state->height = resolution[frame_size][1];
switch (s_state->sensor.id.PID) {
#if CONFIG_OV2640_SUPPORT
case OV2640_PID:
if (frame_size > FRAMESIZE_UXGA) {
frame_size = FRAMESIZE_UXGA;
}
break;
#endif
#if CONFIG_OV7725_SUPPORT
case OV7725_PID:
if (frame_size > FRAMESIZE_VGA) {
frame_size = FRAMESIZE_VGA;
}
break;
#endif
#if CONFIG_OV3660_SUPPORT
case OV3660_PID:
if (frame_size > FRAMESIZE_QXGA) {
frame_size = FRAMESIZE_QXGA;
}
break;
#endif
#if CONFIG_OV5640_SUPPORT
case OV5640_PID:
if (frame_size > FRAMESIZE_QSXGA) {
frame_size = FRAMESIZE_QSXGA;
}
break;
#endif
default:
return ESP_ERR_CAMERA_NOT_SUPPORTED;
}
s_state->width = resolution[frame_size].width;
s_state->height = resolution[frame_size].height;
if (pix_format == PIXFORMAT_GRAYSCALE) {
s_state->fb_size = s_state->width * s_state->height;
if (s_state->sensor.id.PID == OV3660_PID) {
if (s_state->sensor.id.PID == OV3660_PID || s_state->sensor.id.PID == OV5640_PID) {
if (is_hs_mode()) {
s_state->sampling_mode = SM_0A00_0B00;
s_state->dma_filter = &dma_filter_yuyv_highspeed;
@@ -1120,8 +1169,8 @@ esp_err_t camera_init(const camera_config_t* config)
s_state->in_bytes_per_pixel = 2; // camera sends RGB565
s_state->fb_bytes_per_pixel = 3; // frame buffer stores RGB888
} else if (pix_format == PIXFORMAT_JPEG) {
if (s_state->sensor.id.PID != OV2640_PID && s_state->sensor.id.PID != OV3660_PID) {
ESP_LOGE(TAG, "JPEG format is only supported for ov2640 and ov3660");
if (s_state->sensor.id.PID != OV2640_PID && s_state->sensor.id.PID != OV3660_PID && s_state->sensor.id.PID != OV5640_PID) {
ESP_LOGE(TAG, "JPEG format is only supported for ov2640, ov3660 and ov5640");
err = ESP_ERR_NOT_SUPPORTED;
goto fail;
}
@@ -1268,6 +1317,8 @@ esp_err_t esp_camera_init(const camera_config_t* config)
ESP_LOGD(TAG, "Detected OV2640 camera");
} else if (camera_model == CAMERA_OV3660) {
ESP_LOGD(TAG, "Detected OV3660 camera");
} else if (camera_model == CAMERA_OV5640) {
ESP_LOGD(TAG, "Detected OV5640 camera");
} else {
ESP_LOGE(TAG, "Camera not supported");
err = ESP_ERR_CAMERA_NOT_SUPPORTED;

View File

@@ -115,6 +115,7 @@ typedef struct {
size_t width; /*!< Width of the buffer in pixels */
size_t height; /*!< Height of the buffer in pixels */
pixformat_t format; /*!< Format of the pixel data */
struct timeval timestamp; /*!< Timestamp since boot of the first DMA buffer of the frame */
} camera_fb_t;
#define ESP_ERR_CAMERA_BASE 0x20000

View File

@@ -9,11 +9,13 @@
#ifndef __SENSOR_H__
#define __SENSOR_H__
#include <stdint.h>
#include <stdbool.h>
#define OV9650_PID (0x96)
#define OV2640_PID (0x26)
#define OV7725_PID (0x77)
#define OV2640_PID (0x26)
#define OV3660_PID (0x36)
#define OV5640_PID (0x56)
typedef enum {
PIXFORMAT_RGB565, // 2BPP/RGB565
@@ -27,23 +29,45 @@ typedef enum {
} pixformat_t;
typedef enum {
FRAMESIZE_96x96, // 96x96
FRAMESIZE_96X96, // 96x96
FRAMESIZE_QQVGA, // 160x120
FRAMESIZE_QQVGA2, // 128x160
FRAMESIZE_QCIF, // 176x144
FRAMESIZE_HQVGA, // 240x176
FRAMESIZE_240x240, // 240x240
FRAMESIZE_240X240, // 240x240
FRAMESIZE_QVGA, // 320x240
FRAMESIZE_CIF, // 400x296
FRAMESIZE_HVGA, // 480x320
FRAMESIZE_VGA, // 640x480
FRAMESIZE_SVGA, // 800x600
FRAMESIZE_XGA, // 1024x768
FRAMESIZE_HD, // 1280x720
FRAMESIZE_SXGA, // 1280x1024
FRAMESIZE_UXGA, // 1600x1200
FRAMESIZE_QXGA, // 2048*1536
// 3MP Sensors
FRAMESIZE_FHD, // 1920x1080
FRAMESIZE_P_HD, // 720x1280
FRAMESIZE_P_3MP, // 864x1536
FRAMESIZE_QXGA, // 2048x1536
// 5MP Sensors
FRAMESIZE_QHD, // 2560x1440
FRAMESIZE_WQXGA, // 2560x1600
FRAMESIZE_P_FHD, // 1080x1920
FRAMESIZE_QSXGA, // 2560x1920
FRAMESIZE_INVALID
} framesize_t;
typedef enum {
ASPECT_RATIO_4X3,
ASPECT_RATIO_3X2,
ASPECT_RATIO_16X10,
ASPECT_RATIO_5X3,
ASPECT_RATIO_16X9,
ASPECT_RATIO_21X9,
ASPECT_RATIO_5X4,
ASPECT_RATIO_1X1,
ASPECT_RATIO_9X16
} aspect_ratio_t;
typedef enum {
GAINCEILING_2X,
GAINCEILING_4X,
@@ -54,6 +78,28 @@ typedef enum {
GAINCEILING_128X,
} gainceiling_t;
typedef struct {
uint16_t max_width;
uint16_t max_height;
uint16_t start_x;
uint16_t start_y;
uint16_t end_x;
uint16_t end_y;
uint16_t offset_x;
uint16_t offset_y;
uint16_t total_x;
uint16_t total_y;
} ratio_settings_t;
typedef struct {
const uint16_t width;
const uint16_t height;
const aspect_ratio_t aspect_ratio;
} resolution_info_t;
// Resolution table (in sensor.c)
extern const resolution_info_t resolution[];
typedef struct {
uint8_t MIDH;
uint8_t MIDL;
@@ -63,6 +109,8 @@ typedef struct {
typedef struct {
framesize_t framesize;//0 - 10
bool scale;
bool binning;
uint8_t quality;//0 - 63
int8_t brightness;//-2 - 2
int8_t contrast;//-2 - 2
@@ -132,9 +180,12 @@ typedef struct _sensor {
int (*set_raw_gma) (sensor_t *sensor, int enable);
int (*set_lenc) (sensor_t *sensor, int enable);
int (*get_reg) (sensor_t *sensor, int reg, int mask);
int (*set_reg) (sensor_t *sensor, int reg, int mask, int value);
int (*set_res_raw) (sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning);
int (*set_pll) (sensor_t *sensor, int bypass, int mul, int sys, int root, int pre, int seld5, int pclken, int pclk);
int (*set_xclk) (sensor_t *sensor, int timer, int xclk);
} sensor_t;
// Resolution table (in camera.c)
extern const int resolution[][2];
#endif /* __SENSOR_H__ */

View File

@@ -12,7 +12,7 @@
#include "sensor.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/lldesc.h"
#else

View File

@@ -19,6 +19,8 @@
static const char* TAG = "sccb";
#endif
//#undef CONFIG_SCCB_HARDWARE_I2C
#define LITTLETOBIG(x) ((x<<8)|(x>>8))
#ifdef CONFIG_SCCB_HARDWARE_I2C

View File

@@ -1,17 +1,28 @@
#include "sensor.h"
const int resolution[][2] = {
{ 96, 96 }, /* 96x96 */
{ 160, 120 }, /* QQVGA */
{ 128, 160 }, /* QQVGA2*/
{ 176, 144 }, /* QCIF */
{ 240, 176 }, /* HQVGA */
{ 240, 240 }, /* 240x240 */
{ 320, 240 }, /* QVGA */
{ 400, 296 }, /* CIF */
{ 640, 480 }, /* VGA */
{ 800, 600 }, /* SVGA */
{ 1024, 768 }, /* XGA */
{ 1280, 1024 }, /* SXGA */
{ 1600, 1200 }, /* UXGA */
{ 2048, 1536 }, /* QXGA */
const resolution_info_t resolution[FRAMESIZE_INVALID] = {
{ 96, 96, ASPECT_RATIO_1X1 }, /* 96x96 */
{ 160, 120, ASPECT_RATIO_4X3 }, /* QQVGA */
{ 176, 144, ASPECT_RATIO_5X4 }, /* QCIF */
{ 240, 176, ASPECT_RATIO_4X3 }, /* HQVGA */
{ 240, 240, ASPECT_RATIO_1X1 }, /* 240x240 */
{ 320, 240, ASPECT_RATIO_4X3 }, /* QVGA */
{ 400, 296, ASPECT_RATIO_4X3 }, /* CIF */
{ 480, 320, ASPECT_RATIO_3X2 }, /* HVGA */
{ 640, 480, ASPECT_RATIO_4X3 }, /* VGA */
{ 800, 600, ASPECT_RATIO_4X3 }, /* SVGA */
{ 1024, 768, ASPECT_RATIO_4X3 }, /* XGA */
{ 1280, 720, ASPECT_RATIO_16X9 }, /* HD */
{ 1280, 1024, ASPECT_RATIO_5X4 }, /* SXGA */
{ 1600, 1200, ASPECT_RATIO_4X3 }, /* UXGA */
// 3MP Sensors
{ 1920, 1080, ASPECT_RATIO_16X9 }, /* FHD */
{ 720, 1280, ASPECT_RATIO_9X16 }, /* Portrait HD */
{ 864, 1536, ASPECT_RATIO_9X16 }, /* Portrait 3MP */
{ 2048, 1536, ASPECT_RATIO_4X3 }, /* QXGA */
// 5MP Sensors
{ 2560, 1440, ASPECT_RATIO_16X9 }, /* QHD */
{ 2560, 1600, ASPECT_RATIO_16X10 }, /* WQXGA */
{ 1088, 1920, ASPECT_RATIO_9X16 }, /* Portrait FHD */
{ 2560, 1920, ASPECT_RATIO_4X3 }, /* QSXGA */
};

View File

@@ -12,19 +12,28 @@
static const char* TAG = "camera_xclk";
#endif
esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz)
{
ledc_timer_config_t timer_conf;
timer_conf.duty_resolution = 2;
timer_conf.freq_hz = xclk_freq_hz;
timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE;
#if ESP_IDF_VERSION_MAJOR >= 4
timer_conf.clk_cfg = LEDC_AUTO_CLK;
#endif
timer_conf.timer_num = (ledc_timer_t)ledc_timer;
esp_err_t err = ledc_timer_config(&timer_conf);
if (err != ESP_OK) {
ESP_LOGE(TAG, "ledc_timer_config failed for freq %d, rc=%x", xclk_freq_hz, err);
}
return err;
}
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 = 2;
timer_conf.freq_hz = config->xclk_freq_hz;
timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE;
timer_conf.timer_num = config->ledc_timer;
#ifdef ESP_IDF_VERSION_MAJOR
timer_conf.clk_cfg = LEDC_AUTO_CLK;
#endif
esp_err_t err = ledc_timer_config(&timer_conf);
esp_err_t err = xclk_timer_conf(config->ledc_timer, config->xclk_freq_hz);
if (err != ESP_OK) {
ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err);
return err;