mirror of
https://github.com/arkhipenko/esp32-mjpeg-multiclient-espcam-drivers.git
synced 2025-01-08 01:01:11 +01:00
esp32 arduino core 1.0.5 + cam drivers update. vert flip
This commit is contained in:
parent
6fb37b3558
commit
bb26370e2f
46 changed files with 9327 additions and 480 deletions
|
@ -48,6 +48,12 @@
|
|||
#if CONFIG_OV5640_SUPPORT
|
||||
#include "ov5640.h"
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
#include "nt99141.h"
|
||||
#endif
|
||||
#if CONFIG_OV7670_SUPPORT
|
||||
#include "ov7670.h"
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
CAMERA_NONE = 0,
|
||||
|
@ -56,6 +62,8 @@ typedef enum {
|
|||
CAMERA_OV2640 = 2640,
|
||||
CAMERA_OV3660 = 3660,
|
||||
CAMERA_OV5640 = 5640,
|
||||
CAMERA_OV7670 = 7670,
|
||||
CAMERA_NT99141 = 9141,
|
||||
} camera_model_t;
|
||||
|
||||
#define REG_PID 0x0A
|
||||
|
@ -369,12 +377,10 @@ static inline void IRAM_ATTR i2s_conf_reset()
|
|||
}
|
||||
}
|
||||
|
||||
static void i2s_init()
|
||||
static void i2s_gpio_init(const camera_config_t* config)
|
||||
{
|
||||
camera_config_t* config = &s_state->config;
|
||||
|
||||
// Configure input GPIOs
|
||||
gpio_num_t pins[] = {
|
||||
const gpio_num_t pins[] = {
|
||||
config->pin_d7,
|
||||
config->pin_d6,
|
||||
config->pin_d5,
|
||||
|
@ -391,15 +397,21 @@ static void i2s_init()
|
|||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.pin_bit_mask = 0LL
|
||||
};
|
||||
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);
|
||||
conf.pin_bit_mask |= 1LL << pins[i];
|
||||
}
|
||||
gpio_config(&conf);
|
||||
}
|
||||
|
||||
static void i2s_init()
|
||||
{
|
||||
camera_config_t* config = &s_state->config;
|
||||
|
||||
// Route input GPIOs to I2S peripheral using GPIO matrix
|
||||
gpio_matrix_in(config->pin_d0, I2S0I_DATA_IN0_IDX, false);
|
||||
|
@ -738,7 +750,7 @@ 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("bh 0x%08x\n", sig);
|
||||
ESP_LOGD(TAG,"unexpected JPEG signature 0x%08x\n", sig);
|
||||
s_state->fb->bad = 1;
|
||||
return;
|
||||
}
|
||||
|
@ -955,11 +967,15 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Enabling XCLK output");
|
||||
camera_enable_out_clock(config);
|
||||
if(config->pin_xclk >= 0) {
|
||||
ESP_LOGD(TAG, "Enabling XCLK output");
|
||||
camera_enable_out_clock(config);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Initializing SSCB");
|
||||
SCCB_Init(config->pin_sscb_sda, config->pin_sscb_scl);
|
||||
if (config->pin_sscb_sda != -1) {
|
||||
ESP_LOGD(TAG, "Initializing SSCB");
|
||||
SCCB_Init(config->pin_sscb_sda, config->pin_sscb_scl);
|
||||
}
|
||||
|
||||
if(config->pin_pwdn >= 0) {
|
||||
ESP_LOGD(TAG, "Resetting camera by power down line");
|
||||
|
@ -1011,16 +1027,33 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
slv_addr = SCCB_Probe();
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
if (slv_addr == 0x2a)
|
||||
{
|
||||
ESP_LOGD(TAG, "Resetting NT99141");
|
||||
SCCB_Write16(0x2a, 0x3008, 0x01);//bank sensor
|
||||
}
|
||||
#endif
|
||||
|
||||
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 (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT || CONFIG_NT99141_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);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
ESP_LOGD(TAG, "Camera PID=0x%02x VER=0x%02x", id->PID, id->VER);
|
||||
} else if(s_state->sensor.slv_addr == 0x2a){
|
||||
id->PID = SCCB_Read16(s_state->sensor.slv_addr, 0x3000);
|
||||
id->VER = SCCB_Read16(s_state->sensor.slv_addr, 0x3001);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
ESP_LOGD(TAG, "Camera PID=0x%02x VER=0x%02x", id->PID, id->VER);
|
||||
if(config->xclk_freq_hz > 10000000)
|
||||
{
|
||||
ESP_LOGE(TAG, "NT99141: only XCLK under 10MHz is supported, and XCLK is now set to 10M");
|
||||
s_state->sensor.xclk_freq_hz = 10000000;
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
id->PID = SCCB_Read(s_state->sensor.slv_addr, REG_PID);
|
||||
|
@ -1031,7 +1064,7 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
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 || CONFIG_OV5640_SUPPORT)
|
||||
#if (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT || CONFIG_NT99141_SUPPORT)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1060,6 +1093,18 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
*out_camera_model = CAMERA_OV5640;
|
||||
ov5640_init(&s_state->sensor);
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_OV7670_SUPPORT
|
||||
case OV7670_PID:
|
||||
*out_camera_model = CAMERA_OV7670;
|
||||
ov7670_init(&s_state->sensor);
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
case NT99141_PID:
|
||||
*out_camera_model = CAMERA_NT99141;
|
||||
NT99141_init(&s_state->sensor);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
id->PID = 0;
|
||||
|
@ -1116,6 +1161,20 @@ esp_err_t camera_init(const camera_config_t* config)
|
|||
frame_size = FRAMESIZE_QSXGA;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_OV7670_SUPPORT
|
||||
case OV7670_PID:
|
||||
if (frame_size > FRAMESIZE_VGA) {
|
||||
frame_size = FRAMESIZE_VGA;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
case NT99141_PID:
|
||||
if (frame_size > FRAMESIZE_HD) {
|
||||
frame_size = FRAMESIZE_HD;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return ESP_ERR_CAMERA_NOT_SUPPORTED;
|
||||
|
@ -1126,7 +1185,7 @@ esp_err_t camera_init(const camera_config_t* config)
|
|||
|
||||
if (pix_format == PIXFORMAT_GRAYSCALE) {
|
||||
s_state->fb_size = s_state->width * s_state->height;
|
||||
if (s_state->sensor.id.PID == OV3660_PID || s_state->sensor.id.PID == OV5640_PID) {
|
||||
if (s_state->sensor.id.PID == OV3660_PID || s_state->sensor.id.PID == OV5640_PID || s_state->sensor.id.PID == NT99141_PID) {
|
||||
if (is_hs_mode()) {
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
s_state->dma_filter = &dma_filter_yuyv_highspeed;
|
||||
|
@ -1147,20 +1206,28 @@ esp_err_t camera_init(const camera_config_t* config)
|
|||
}
|
||||
s_state->fb_bytes_per_pixel = 1; // frame buffer stores Y8
|
||||
} else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) {
|
||||
s_state->fb_size = s_state->width * s_state->height * 2;
|
||||
if (is_hs_mode() && s_state->sensor.id.PID != OV7725_PID) {
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
s_state->dma_filter = &dma_filter_yuyv_highspeed;
|
||||
} else {
|
||||
s_state->sampling_mode = SM_0A0B_0C0D;
|
||||
s_state->dma_filter = &dma_filter_yuyv;
|
||||
}
|
||||
s_state->in_bytes_per_pixel = 2; // camera sends YU/YV
|
||||
s_state->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
|
||||
s_state->fb_size = s_state->width * s_state->height * 2;
|
||||
if (is_hs_mode() && s_state->sensor.id.PID != OV7725_PID) {
|
||||
if(s_state->sensor.id.PID == OV7670_PID) {
|
||||
s_state->sampling_mode = SM_0A0B_0B0C;
|
||||
}else{
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
}
|
||||
s_state->dma_filter = &dma_filter_yuyv_highspeed;
|
||||
} else {
|
||||
s_state->sampling_mode = SM_0A0B_0C0D;
|
||||
s_state->dma_filter = &dma_filter_yuyv;
|
||||
}
|
||||
s_state->in_bytes_per_pixel = 2; // camera sends YU/YV
|
||||
s_state->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
|
||||
} else if (pix_format == PIXFORMAT_RGB888) {
|
||||
s_state->fb_size = s_state->width * s_state->height * 3;
|
||||
if (is_hs_mode()) {
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
if(s_state->sensor.id.PID == OV7670_PID) {
|
||||
s_state->sampling_mode = SM_0A0B_0B0C;
|
||||
}else{
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
}
|
||||
s_state->dma_filter = &dma_filter_rgb888_highspeed;
|
||||
} else {
|
||||
s_state->sampling_mode = SM_0A0B_0C0D;
|
||||
|
@ -1169,7 +1236,7 @@ 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 && s_state->sensor.id.PID != OV5640_PID) {
|
||||
if (s_state->sensor.id.PID != OV2640_PID && s_state->sensor.id.PID != OV3660_PID && s_state->sensor.id.PID != OV5640_PID && s_state->sensor.id.PID != NT99141_PID) {
|
||||
ESP_LOGE(TAG, "JPEG format is only supported for ov2640, ov3660 and ov5640");
|
||||
err = ESP_ERR_NOT_SUPPORTED;
|
||||
goto fail;
|
||||
|
@ -1306,6 +1373,7 @@ fail:
|
|||
esp_err_t esp_camera_init(const camera_config_t* config)
|
||||
{
|
||||
camera_model_t camera_model = CAMERA_NONE;
|
||||
i2s_gpio_init(config);
|
||||
esp_err_t err = camera_probe(config, &camera_model);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Camera probe failed with error 0x%x", err);
|
||||
|
@ -1324,6 +1392,10 @@ esp_err_t esp_camera_init(const camera_config_t* config)
|
|||
ESP_LOGI(TAG, "Detected OV3660 camera");
|
||||
} else if (camera_model == CAMERA_OV5640) {
|
||||
ESP_LOGI(TAG, "Detected OV5640 camera");
|
||||
} else if (camera_model == CAMERA_OV7670) {
|
||||
ESP_LOGI(TAG, "Detected OV7670 camera");
|
||||
} else if (camera_model == CAMERA_NT99141) {
|
||||
ESP_LOGI(TAG, "Detected NT99141 camera");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Camera not supported");
|
||||
err = ESP_ERR_CAMERA_NOT_SUPPORTED;
|
||||
|
@ -1370,9 +1442,12 @@ esp_err_t esp_camera_deinit()
|
|||
}
|
||||
dma_desc_deinit();
|
||||
camera_fb_deinit();
|
||||
|
||||
if(s_state->config.pin_xclk >= 0) {
|
||||
camera_disable_out_clock();
|
||||
}
|
||||
free(s_state);
|
||||
s_state = NULL;
|
||||
camera_disable_out_clock();
|
||||
periph_module_disable(PERIPH_I2S0_MODULE);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -1430,11 +1505,11 @@ sensor_t * esp_camera_sensor_get()
|
|||
|
||||
esp_err_t esp_camera_save_to_nvs(const char *key)
|
||||
{
|
||||
#if ESP_IDF_VERSION_MAJOR > 3
|
||||
nvs_handle_t handle;
|
||||
#else
|
||||
//#if ESP_IDF_VERSION_MAJOR > 3
|
||||
// nvs_handle_t handle;
|
||||
//#else
|
||||
nvs_handle handle;
|
||||
#endif
|
||||
//#endif
|
||||
esp_err_t ret = nvs_open(key,NVS_READWRITE,&handle);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
|
@ -1458,11 +1533,11 @@ esp_err_t esp_camera_save_to_nvs(const char *key)
|
|||
|
||||
esp_err_t esp_camera_load_from_nvs(const char *key)
|
||||
{
|
||||
#if ESP_IDF_VERSION_MAJOR > 3
|
||||
nvs_handle_t handle;
|
||||
#else
|
||||
//#if ESP_IDF_VERSION_MAJOR > 3
|
||||
// nvs_handle_t handle;
|
||||
//#else
|
||||
nvs_handle handle;
|
||||
#endif
|
||||
//#endif
|
||||
uint8_t pf;
|
||||
|
||||
esp_err_t ret = nvs_open(key,NVS_READWRITE,&handle);
|
||||
|
|
|
@ -421,6 +421,8 @@ void setup()
|
|||
ESP.restart();
|
||||
}
|
||||
|
||||
sensor_t* s = esp_camera_sensor_get();
|
||||
s->set_vflip(s, true);
|
||||
|
||||
// Configure and connect to WiFi
|
||||
IPAddress ip;
|
||||
|
|
Binary file not shown.
|
@ -62,7 +62,8 @@ bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg);
|
|||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out Pointer to be populated with the address of the resulting buffer.
|
||||
* You MUST free the pointer once you are done with it.
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
|
|
1032
esp32-cam-rtos-allframes/nt99141.c
Normal file
1032
esp32-cam-rtos-allframes/nt99141.c
Normal file
File diff suppressed because it is too large
Load diff
16
esp32-cam-rtos-allframes/nt99141.h
Normal file
16
esp32-cam-rtos-allframes/nt99141.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* NT99141 driver.
|
||||
*
|
||||
*/
|
||||
#ifndef __NT99141_H__
|
||||
#define __NT99141_H__
|
||||
|
||||
#include "sensor.h"
|
||||
|
||||
int NT99141_init(sensor_t *sensor);
|
||||
|
||||
#endif // __NT99141_H__
|
211
esp32-cam-rtos-allframes/nt99141_regs.h
Normal file
211
esp32-cam-rtos-allframes/nt99141_regs.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* NT99141 register definitions.
|
||||
*/
|
||||
#ifndef __NT99141_REG_REGS_H__
|
||||
#define __NT99141_REG_REGS_H__
|
||||
|
||||
/* system control registers */
|
||||
#define SYSTEM_CTROL0 0x3021 // Bit[7]: Software reset
|
||||
// Bit[6]: Software power down
|
||||
// Bit[5]: Reserved
|
||||
// Bit[4]: SRB clock SYNC enable
|
||||
// Bit[3]: Isolation suspend select
|
||||
// Bit[2:0]: Not used
|
||||
|
||||
/* output format control registers */
|
||||
#define FORMAT_CTRL 0x501F // Format select
|
||||
// Bit[2:0]:
|
||||
// 000: YUV422
|
||||
// 001: RGB
|
||||
// 010: Dither
|
||||
// 011: RAW after DPC
|
||||
// 101: RAW after CIP
|
||||
|
||||
/* format control registers */
|
||||
#define FORMAT_CTRL00 0x4300
|
||||
|
||||
/* frame control registers */
|
||||
#define FRAME_CTRL01 0x4201 // Control Passed Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode
|
||||
// Bit[7:4]: Not used
|
||||
// Bit[3:0]: Frame ON number
|
||||
#define FRAME_CTRL02 0x4202 // Control Masked Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode
|
||||
// Bit[7:4]: Not used
|
||||
// BIT[3:0]: Frame OFF number
|
||||
|
||||
/* ISP top control registers */
|
||||
#define PRE_ISP_TEST_SETTING_1 0x3025 // Bit[7]: Test enable
|
||||
// 0: Test disable
|
||||
// 1: Color bar enable
|
||||
// Bit[6]: Rolling
|
||||
// Bit[5]: Transparent
|
||||
// Bit[4]: Square black and white
|
||||
// Bit[3:2]: Color bar style
|
||||
// 00: Standard 8 color bar
|
||||
// 01: Gradual change at vertical mode 1
|
||||
// 10: Gradual change at horizontal
|
||||
// 11: Gradual change at vertical mode 2
|
||||
// Bit[1:0]: Test select
|
||||
// 00: Color bar
|
||||
// 01: Random data
|
||||
// 10: Square data
|
||||
// 11: Black image
|
||||
|
||||
//exposure = {0x3500[3:0], 0x3501[7:0], 0x3502[7:0]} / 16 × tROW
|
||||
|
||||
/* AEC/AGC control functions */
|
||||
#define AEC_PK_MANUAL 0x3201 // AEC Manual Mode Control
|
||||
// Bit[7:6]: Reserved
|
||||
// Bit[5]: Gain delay option
|
||||
// Valid when 0x3503[4]=1’b0
|
||||
// 0: Delay one frame latch
|
||||
// 1: One frame latch
|
||||
// Bit[4:2]: Reserved
|
||||
// Bit[1]: AGC manual
|
||||
// 0: Auto enable
|
||||
// 1: Manual enable
|
||||
// Bit[0]: AEC manual
|
||||
// 0: Auto enable
|
||||
// 1: Manual enable
|
||||
|
||||
//gain = {0x350A[1:0], 0x350B[7:0]} / 16
|
||||
|
||||
/* mirror and flip registers */
|
||||
#define TIMING_TC_REG20 0x3022 // Timing Control Register
|
||||
// Bit[2:1]: Vertical flip enable
|
||||
// 00: Normal
|
||||
// 11: Vertical flip
|
||||
// Bit[0]: Vertical binning enable
|
||||
#define TIMING_TC_REG21 0x3022 // Timing Control Register
|
||||
// Bit[5]: Compression Enable
|
||||
// Bit[2:1]: Horizontal mirror enable
|
||||
// 00: Normal
|
||||
// 11: Horizontal mirror
|
||||
// Bit[0]: Horizontal binning enable
|
||||
|
||||
#define CLOCK_POL_CONTROL 0x3024// Bit[5]: PCLK polarity 0: active low
|
||||
// 1: active high
|
||||
// Bit[3]: Gate PCLK under VSYNC
|
||||
// Bit[2]: Gate PCLK under HREF
|
||||
// Bit[1]: HREF polarity
|
||||
// 0: active low
|
||||
// 1: active high
|
||||
// Bit[0] VSYNC polarity
|
||||
// 0: active low
|
||||
// 1: active high
|
||||
#define DRIVE_CAPABILITY 0x306a // Bit[7:6]:
|
||||
// 00: 1x
|
||||
// 01: 2x
|
||||
// 10: 3x
|
||||
// 11: 4x
|
||||
|
||||
|
||||
#define X_ADDR_ST_H 0x3800 //Bit[3:0]: X address start[11:8]
|
||||
#define X_ADDR_ST_L 0x3801 //Bit[7:0]: X address start[7:0]
|
||||
#define Y_ADDR_ST_H 0x3802 //Bit[2:0]: Y address start[10:8]
|
||||
#define Y_ADDR_ST_L 0x3803 //Bit[7:0]: Y address start[7:0]
|
||||
#define X_ADDR_END_H 0x3804 //Bit[3:0]: X address end[11:8]
|
||||
#define X_ADDR_END_L 0x3805 //Bit[7:0]:
|
||||
#define Y_ADDR_END_H 0x3806 //Bit[2:0]: Y address end[10:8]
|
||||
#define Y_ADDR_END_L 0x3807 //Bit[7:0]:
|
||||
// Size after scaling
|
||||
#define X_OUTPUT_SIZE_H 0x3808 //Bit[3:0]: DVP output horizontal width[11:8]
|
||||
#define X_OUTPUT_SIZE_L 0x3809 //Bit[7:0]:
|
||||
#define Y_OUTPUT_SIZE_H 0x380a //Bit[2:0]: DVP output vertical height[10:8]
|
||||
#define Y_OUTPUT_SIZE_L 0x380b //Bit[7:0]:
|
||||
#define X_TOTAL_SIZE_H 0x380c //Bit[3:0]: Total horizontal size[11:8]
|
||||
#define X_TOTAL_SIZE_L 0x380d //Bit[7:0]:
|
||||
#define Y_TOTAL_SIZE_H 0x380e //Bit[7:0]: Total vertical size[15:8]
|
||||
#define Y_TOTAL_SIZE_L 0x380f //Bit[7:0]:
|
||||
#define X_OFFSET_H 0x3810 //Bit[3:0]: ISP horizontal offset[11:8]
|
||||
#define X_OFFSET_L 0x3811 //Bit[7:0]:
|
||||
#define Y_OFFSET_H 0x3812 //Bit[2:0]: ISP vertical offset[10:8]
|
||||
#define Y_OFFSET_L 0x3813 //Bit[7:0]:
|
||||
#define X_INCREMENT 0x3814 //Bit[7:4]: Horizontal odd subsample increment
|
||||
//Bit[3:0]: Horizontal even subsample increment
|
||||
#define Y_INCREMENT 0x3815 //Bit[7:4]: Vertical odd subsample increment
|
||||
//Bit[3:0]: Vertical even subsample increment
|
||||
// Size before scaling
|
||||
//#define X_INPUT_SIZE (X_ADDR_END - X_ADDR_ST + 1 - (2 * X_OFFSET))
|
||||
//#define Y_INPUT_SIZE (Y_ADDR_END - Y_ADDR_ST + 1 - (2 * Y_OFFSET))
|
||||
|
||||
#define ISP_CONTROL_01 0x3021 // Bit[5]: Scale enable
|
||||
// 0: Disable
|
||||
// 1: Enable
|
||||
|
||||
#define SCALE_CTRL_1 0x5601 // Bit[6:4]: HDIV RW
|
||||
// DCW scale times
|
||||
// 000: DCW 1 time
|
||||
// 001: DCW 2 times
|
||||
// 010: DCW 4 times
|
||||
// 100: DCW 8 times
|
||||
// 101: DCW 16 times
|
||||
// Others: DCW 16 times
|
||||
// Bit[2:0]: VDIV RW
|
||||
// DCW scale times
|
||||
// 000: DCW 1 time
|
||||
// 001: DCW 2 times
|
||||
// 010: DCW 4 times
|
||||
// 100: DCW 8 times
|
||||
// 101: DCW 16 times
|
||||
// Others: DCW 16 times
|
||||
|
||||
#define SCALE_CTRL_2 0x5602 // X_SCALE High Bits
|
||||
#define SCALE_CTRL_3 0x5603 // X_SCALE Low Bits
|
||||
#define SCALE_CTRL_4 0x5604 // Y_SCALE High Bits
|
||||
#define SCALE_CTRL_5 0x5605 // Y_SCALE Low Bits
|
||||
#define SCALE_CTRL_6 0x5606 // Bit[3:0]: V Offset
|
||||
|
||||
#define PCLK_RATIO 0x3824 // Bit[4:0]: PCLK ratio manual
|
||||
#define VFIFO_CTRL0C 0x460C // Bit[1]: PCLK manual enable
|
||||
// 0: Auto
|
||||
// 1: Manual by PCLK_RATIO
|
||||
|
||||
#define VFIFO_X_SIZE_H 0x4602
|
||||
#define VFIFO_X_SIZE_L 0x4603
|
||||
#define VFIFO_Y_SIZE_H 0x4604
|
||||
#define VFIFO_Y_SIZE_L 0x4605
|
||||
|
||||
#define SC_PLLS_CTRL0 0x303a // Bit[7]: PLLS bypass
|
||||
#define SC_PLLS_CTRL1 0x303b // Bit[4:0]: PLLS multiplier
|
||||
#define SC_PLLS_CTRL2 0x303c // Bit[6:4]: PLLS charge pump control
|
||||
// Bit[3:0]: PLLS system divider
|
||||
#define SC_PLLS_CTRL3 0x303d // Bit[5:4]: PLLS pre-divider
|
||||
// 00: 1
|
||||
// 01: 1.5
|
||||
// 10: 2
|
||||
// 11: 3
|
||||
// Bit[2]: PLLS root-divider - 1
|
||||
// Bit[1:0]: PLLS seld5
|
||||
// 00: 1
|
||||
// 01: 1
|
||||
// 10: 2
|
||||
// 11: 2.5
|
||||
|
||||
#define COMPRESSION_CTRL00 0x4400 //
|
||||
#define COMPRESSION_CTRL01 0x4401 //
|
||||
#define COMPRESSION_CTRL02 0x4402 //
|
||||
#define COMPRESSION_CTRL03 0x4403 //
|
||||
#define COMPRESSION_CTRL04 0x4404 //
|
||||
#define COMPRESSION_CTRL05 0x4405 //
|
||||
#define COMPRESSION_CTRL06 0x4406 //
|
||||
#define COMPRESSION_CTRL07 0x3401 // Bit[5:0]: QS
|
||||
#define COMPRESSION_ISI_CTRL 0x4408 //
|
||||
#define COMPRESSION_CTRL09 0x4409 //
|
||||
#define COMPRESSION_CTRL0a 0x440a //
|
||||
#define COMPRESSION_CTRL0b 0x440b //
|
||||
#define COMPRESSION_CTRL0c 0x440c //
|
||||
#define COMPRESSION_CTRL0d 0x440d //
|
||||
#define COMPRESSION_CTRL0E 0x440e //
|
||||
|
||||
/**
|
||||
* @brief register value
|
||||
*/
|
||||
#define TEST_COLOR_BAR 0x02 /* Enable Color Bar roling Test */
|
||||
|
||||
#define AEC_PK_MANUAL_AGC_MANUALEN 0x02 /* Enable AGC Manual enable */
|
||||
#define AEC_PK_MANUAL_AEC_MANUALEN 0x01 /* Enable AEC Manual enable */
|
||||
|
||||
#define TIMING_TC_REG20_VFLIP 0x01 /* Vertical flip enable */
|
||||
#define TIMING_TC_REG21_HMIRROR 0x02 /* Horizontal mirror enable */
|
||||
|
||||
#endif // __NT99141_REG_REGS_H__
|
825
esp32-cam-rtos-allframes/nt99141_settings.h
Normal file
825
esp32-cam-rtos-allframes/nt99141_settings.h
Normal file
|
@ -0,0 +1,825 @@
|
|||
#ifndef _NT99141_SETTINGS_H_
|
||||
#define _NT99141_SETTINGS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_attr.h"
|
||||
#include "nt99141_regs.h"
|
||||
|
||||
static const ratio_settings_t ratio_table[] = {
|
||||
// mw, mh, sx, sy, ex, ey, ox, oy, tx, ty
|
||||
{ 1280, 720, 0, 4, 1283, 723, 0, 4, 1660, 963 },
|
||||
|
||||
};
|
||||
|
||||
#define REG_DLY 0xffff
|
||||
#define REGLIST_TAIL 0x0000
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_default_regs[][2] = {
|
||||
//initial
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x3109, 0x04},
|
||||
{0x3040, 0x04},
|
||||
{0x3041, 0x02},
|
||||
{0x3042, 0xFF},
|
||||
{0x3043, 0x08},
|
||||
{0x3052, 0xE0},
|
||||
{0x305F, 0x33},
|
||||
{0x3100, 0x07},
|
||||
{0x3106, 0x03},
|
||||
{0x3105, 0x01},
|
||||
{0x3108, 0x05},
|
||||
{0x3110, 0x22},
|
||||
{0x3111, 0x57},
|
||||
{0x3112, 0x22},
|
||||
{0x3113, 0x55},
|
||||
{0x3114, 0x05},
|
||||
{0x3135, 0x00},
|
||||
{0x32F0, 0x01},
|
||||
{0x3290, 0x01},
|
||||
{0x3291, 0x80},
|
||||
{0x3296, 0x01},
|
||||
{0x3297, 0x73},
|
||||
{0x3250, 0x80},
|
||||
{0x3251, 0x03},
|
||||
{0x3252, 0xFF},
|
||||
{0x3253, 0x00},
|
||||
{0x3254, 0x03},
|
||||
{0x3255, 0xFF},
|
||||
{0x3256, 0x00},
|
||||
{0x3257, 0x50},
|
||||
{0x3270, 0x00},
|
||||
{0x3271, 0x0C},
|
||||
{0x3272, 0x18},
|
||||
{0x3273, 0x32},
|
||||
{0x3274, 0x44},
|
||||
{0x3275, 0x54},
|
||||
{0x3276, 0x70},
|
||||
{0x3277, 0x88},
|
||||
{0x3278, 0x9D},
|
||||
{0x3279, 0xB0},
|
||||
{0x327A, 0xCF},
|
||||
{0x327B, 0xE2},
|
||||
{0x327C, 0xEF},
|
||||
{0x327D, 0xF7},
|
||||
{0x327E, 0xFF},
|
||||
{0x3302, 0x00},
|
||||
{0x3303, 0x40},
|
||||
{0x3304, 0x00},
|
||||
{0x3305, 0x96},
|
||||
{0x3306, 0x00},
|
||||
{0x3307, 0x29},
|
||||
{0x3308, 0x07},
|
||||
{0x3309, 0xBA},
|
||||
{0x330A, 0x06},
|
||||
{0x330B, 0xF5},
|
||||
{0x330C, 0x01},
|
||||
{0x330D, 0x51},
|
||||
{0x330E, 0x01},
|
||||
{0x330F, 0x30},
|
||||
{0x3310, 0x07},
|
||||
{0x3311, 0x16},
|
||||
{0x3312, 0x07},
|
||||
{0x3313, 0xBA},
|
||||
{0x3326, 0x02},
|
||||
{0x32F6, 0x0F},
|
||||
{0x32F9, 0x42},
|
||||
{0x32FA, 0x24},
|
||||
{0x3325, 0x4A},
|
||||
{0x3330, 0x00},
|
||||
{0x3331, 0x0A},
|
||||
{0x3332, 0xFF},
|
||||
{0x3338, 0x30},
|
||||
{0x3339, 0x84},
|
||||
{0x333A, 0x48},
|
||||
{0x333F, 0x07},
|
||||
{0x3360, 0x10},
|
||||
{0x3361, 0x18},
|
||||
{0x3362, 0x1f},
|
||||
{0x3363, 0x37},
|
||||
{0x3364, 0x80},
|
||||
{0x3365, 0x80},
|
||||
{0x3366, 0x68},
|
||||
{0x3367, 0x60},
|
||||
{0x3368, 0x30},
|
||||
{0x3369, 0x28},
|
||||
{0x336A, 0x20},
|
||||
{0x336B, 0x10},
|
||||
{0x336C, 0x00},
|
||||
{0x336D, 0x20},
|
||||
{0x336E, 0x1C},
|
||||
{0x336F, 0x18},
|
||||
{0x3370, 0x10},
|
||||
{0x3371, 0x38},
|
||||
{0x3372, 0x3C},
|
||||
{0x3373, 0x3F},
|
||||
{0x3374, 0x3F},
|
||||
{0x338A, 0x34},
|
||||
{0x338B, 0x7F},
|
||||
{0x338C, 0x10},
|
||||
{0x338D, 0x23},
|
||||
{0x338E, 0x7F},
|
||||
{0x338F, 0x14},
|
||||
{0x3375, 0x08},
|
||||
{0x3376, 0x0C},
|
||||
{0x3377, 0x18},
|
||||
{0x3378, 0x20},
|
||||
{0x3012, 0x02},
|
||||
{0x3013, 0xD0},
|
||||
{0x3025, 0x02}, //colorbar
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = {
|
||||
{0x32F0, 0x70}, // YUV422
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = {
|
||||
{0x32F0, 0x50}, // RAW
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = {
|
||||
{0x32F1, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = {
|
||||
{0x32F0, 0x00}, // YUV422
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = {
|
||||
{0x32F0, 0x01}, // RGB
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint8_t sensor_saturation_levels[9][1] = {
|
||||
{0x60},//-4
|
||||
{0x68},//-3
|
||||
{0x70},//-2
|
||||
{0x78},//-1
|
||||
{0x80},//0
|
||||
{0x88},//+1
|
||||
{0x90},//+2
|
||||
{0x98},//+3
|
||||
{0xA0},//+4
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = {
|
||||
{0x00, 0x80, 0x80, 0x01},//Normal
|
||||
{0x03, 0x80, 0x80, 0x01},//Negative
|
||||
{0x01, 0x80, 0x80, 0x01},//Grayscale
|
||||
{0x05, 0x2A, 0xF0, 0x01},//Red Tint
|
||||
{0x05, 0x60, 0x20, 0x01},//Green Tint
|
||||
{0x05, 0xF0, 0x80, 0x01},//Blue Tint
|
||||
{0x02, 0x80, 0x80, 0x01},//Sepia
|
||||
|
||||
};
|
||||
|
||||
// AE LEVEL
|
||||
static const DRAM_ATTR uint16_t sensor_ae_level[][2] = {
|
||||
|
||||
// 1. [AE_Target : 0x24]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x29 },
|
||||
{0x32B9, 0x1F },
|
||||
{0x32BC, 0x24 },
|
||||
{0x32BD, 0x27 },
|
||||
{0x32BE, 0x21 },
|
||||
//------------------------------------------------------------------------
|
||||
// 2. [AE_Target : 0x28]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x2D },
|
||||
{0x32B9, 0x23 },
|
||||
{0x32BC, 0x28 },
|
||||
{0x32BD, 0x2B },
|
||||
{0x32BE, 0x25 },
|
||||
//------------------------------------------------------------------------
|
||||
// 3. [AE_Target : 0x2C]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x32 },
|
||||
{0x32B9, 0x26 },
|
||||
{0x32BC, 0x2C },
|
||||
{0x32BD, 0x2F },
|
||||
{0x32BE, 0x29 },
|
||||
//------------------------------------------------------------------------
|
||||
// 4, [AE_Target : 0x30]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x36 },
|
||||
{0x32B9, 0x2A },
|
||||
{0x32BC, 0x30 },
|
||||
{0x32BD, 0x33 },
|
||||
{0x32BE, 0x2D },
|
||||
//------------------------------------------------------------------------
|
||||
// 5. [AE_Target : 0x34]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x3B },
|
||||
{0x32B9, 0x2D },
|
||||
{0x32BC, 0x34 },
|
||||
{0x32BD, 0x38 },
|
||||
{0x32BE, 0x30 },
|
||||
//------------------------------------------------------------------------
|
||||
// 6. [AE_Target : 0x38]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x3F },
|
||||
{0x32B9, 0x31 },
|
||||
{0x32BC, 0x38 },
|
||||
{0x32BD, 0x3C },
|
||||
{0x32BE, 0x34 },
|
||||
//------------------------------------------------------------------------
|
||||
// 7. [AE_Target : 0x3D]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x44 },
|
||||
{0x32B9, 0x34 },
|
||||
{0x32BC, 0x3C },
|
||||
{0x32BD, 0x40 },
|
||||
{0x32BE, 0x38 },
|
||||
//------------------------------------------------------------------------
|
||||
// 8. [AE_Target : 0x40]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x48 },
|
||||
{0x32B9, 0x38 },
|
||||
{0x32BC, 0x40 },
|
||||
{0x32BD, 0x44 },
|
||||
{0x32BE, 0x3C },
|
||||
//------------------------------------------------------------------------
|
||||
// 9. [AE_Target : 0x44]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x4D },
|
||||
{0x32B9, 0x3B },
|
||||
{0x32BC, 0x44 },
|
||||
{0x32BD, 0x49 },
|
||||
{0x32BE, 0x3F },
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_HD[][2] = {
|
||||
//[JPEG_1280x720_8.18_8.18_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x3C},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x5E},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0x04},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x05},
|
||||
{0x3007, 0x03},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x06},
|
||||
{0x300B, 0x7C},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x05},
|
||||
{0x300F, 0x00},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x3F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA[][2] = {
|
||||
//[JPEG_640x480_10.14_10.14_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x4B},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x62},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x02},
|
||||
{0x32E1, 0x80},
|
||||
{0x32E2, 0x01},
|
||||
{0x32E3, 0xE0},
|
||||
{0x32E4, 0x00},
|
||||
{0x32E5, 0x80},
|
||||
{0x32E6, 0x00},
|
||||
{0x32E7, 0x80},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0xA4},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x04},
|
||||
{0x3007, 0x63},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x05},
|
||||
{0x300B, 0x3C},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x03},
|
||||
{0x300F, 0xC0},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_QVGA[][2] = {
|
||||
//[JPEG_320x240_10.14_10.14_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x4B},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x62},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x01},
|
||||
{0x32E1, 0x40},
|
||||
{0x32E2, 0x00},
|
||||
{0x32E3, 0xF0},
|
||||
{0x32E4, 0x02},
|
||||
{0x32E5, 0x02},
|
||||
{0x32E6, 0x02},
|
||||
{0x32E7, 0x03},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0xA4},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x04},
|
||||
{0x3007, 0x63},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x05},
|
||||
{0x300B, 0x3C},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x03},
|
||||
{0x300F, 0xC0},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA_xyskip[][2] = {
|
||||
// [JPEG_640x360_20.00_25.01_Fps_XY_Skip]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60 },
|
||||
{0x320A, 0xB2 },
|
||||
{0x32C0, 0x64 },
|
||||
{0x32C1, 0x64 },
|
||||
{0x32C2, 0x64 },
|
||||
{0x32C3, 0x00 },
|
||||
{0x32C4, 0x20 },
|
||||
{0x32C5, 0x20 },
|
||||
{0x32C6, 0x20 },
|
||||
{0x32C7, 0x00 },
|
||||
{0x32C8, 0x62 },
|
||||
{0x32C9, 0x64 },
|
||||
{0x32CA, 0x84 },
|
||||
{0x32CB, 0x84 },
|
||||
{0x32CC, 0x84 },
|
||||
{0x32CD, 0x84 },
|
||||
{0x32DB, 0x68 },
|
||||
{0x32F0, 0x70 },
|
||||
{0x3400, 0x08 },
|
||||
{0x3400, 0x00 },
|
||||
{0x3401, 0x4E },
|
||||
{0x3404, 0x00 },
|
||||
{0x3405, 0x00 },
|
||||
{0x3410, 0x00 },
|
||||
{0x3200, 0x3E },
|
||||
{0x3201, 0x0F },
|
||||
{0x3028, 0x0F },
|
||||
{0x3029, 0x00 },
|
||||
{0x302A, 0x08 },
|
||||
{0x3022, 0x24 },
|
||||
{0x3023, 0x6C },
|
||||
{0x3002, 0x00 },
|
||||
{0x3003, 0x04 },
|
||||
{0x3004, 0x00 },
|
||||
{0x3005, 0x04 },
|
||||
{0x3006, 0x05 },
|
||||
{0x3007, 0x03 },
|
||||
{0x3008, 0x02 },
|
||||
{0x3009, 0xD3 },
|
||||
{0x300A, 0x03 },
|
||||
{0x300B, 0xFC },
|
||||
{0x300C, 0x01 },
|
||||
{0x300D, 0x88 },
|
||||
{0x300E, 0x02 },
|
||||
{0x300F, 0x80 },
|
||||
{0x3010, 0x01 },
|
||||
{0x3011, 0x68 },
|
||||
{0x32B8, 0x3F },
|
||||
{0x32B9, 0x31 },
|
||||
{0x32BB, 0x87 },
|
||||
{0x32BC, 0x38 },
|
||||
{0x32BD, 0x3C },
|
||||
{0x32BE, 0x34 },
|
||||
{0x3201, 0x3F },
|
||||
{0x3025, 0x00 }, //normal
|
||||
{0x3021, 0x06 },
|
||||
{0x3400, 0x01 },
|
||||
{0x3060, 0x01 },
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA_xskip[][2] = {
|
||||
//[JPEG_640x480_Xskip_13.32_13.32_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x02},
|
||||
{0x32E1, 0x80},
|
||||
{0x32E2, 0x01},
|
||||
{0x32E3, 0xE0},
|
||||
{0x32E4, 0x00},
|
||||
{0x32E5, 0x00},
|
||||
{0x32E6, 0x00},
|
||||
{0x32E7, 0x80},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x2C},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0x04},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x05},
|
||||
{0x3007, 0x03},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_QVGA_xskip[][2] = {
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
//[JPEG_320x240_Xskip_13.32_13.32_Fps]
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x01},
|
||||
{0x32E1, 0x40},
|
||||
{0x32E2, 0x00},
|
||||
{0x32E3, 0xF0},
|
||||
{0x32E4, 0x01},
|
||||
{0x32E5, 0x01},
|
||||
{0x32E6, 0x02},
|
||||
{0x32E7, 0x03},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x2C},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0x04},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x05},
|
||||
{0x3007, 0x03},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA_crop[][2] = {
|
||||
//[JPEG_640x480_Crop_19.77_19.77_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x01},
|
||||
{0x3003, 0x44},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x7C},
|
||||
{0x3006, 0x03},
|
||||
{0x3007, 0xC3},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0x5B},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x01},
|
||||
{0x300D, 0xF0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x01},
|
||||
{0x3011, 0xE0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x3F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_QVGA_crop[][2] = {
|
||||
//[JPEG_320x240_Crop_19.77_19.77_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x01},
|
||||
{0x32E1, 0x40},
|
||||
{0x32E2, 0x00},
|
||||
{0x32E3, 0xF0},
|
||||
{0x32E4, 0x01},
|
||||
{0x32E5, 0x01},
|
||||
{0x32E6, 0x01},
|
||||
{0x32E7, 0x02},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x01},
|
||||
{0x3003, 0x44},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x7C},
|
||||
{0x3006, 0x03},
|
||||
{0x3007, 0xC3},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0x5B},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x01},
|
||||
{0x300D, 0xF0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x01},
|
||||
{0x3011, 0xE0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
439
esp32-cam-rtos-allframes/ov7670.c
Normal file
439
esp32-cam-rtos-allframes/ov7670.c
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* OV7725 driver.
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sccb.h"
|
||||
#include "ov7670.h"
|
||||
#include "ov7670_regs.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
|
||||
#include "esp32-hal-log.h"
|
||||
#else
|
||||
#include "esp_log.h"
|
||||
static const char* TAG = "ov7760";
|
||||
#endif
|
||||
|
||||
static int ov7670_clkrc = 0x01;
|
||||
|
||||
/*
|
||||
* The default register settings, as obtained from OmniVision. There
|
||||
* is really no making sense of most of these - lots of "reserved" values
|
||||
* and such.
|
||||
*
|
||||
* These settings give VGA YUYV.
|
||||
*/
|
||||
struct regval_list {
|
||||
uint8_t reg_num;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_default_regs[] = {
|
||||
/* Sensor automatically sets output window when resolution changes. */
|
||||
{TSLB, 0x04},
|
||||
|
||||
/* Frame rate 30 fps at 12 Mhz clock */
|
||||
{CLKRC, 0x00},
|
||||
{DBLV, 0x4A},
|
||||
|
||||
{COM10, COM10_VSYNC_NEG | COM10_PCLK_MASK},
|
||||
|
||||
/* Improve white balance */
|
||||
{COM4, 0x40},
|
||||
|
||||
/* Improve color */
|
||||
{RSVD_B0, 0x84},
|
||||
|
||||
/* Enable 50/60 Hz auto detection */
|
||||
{COM11, COM11_EXP|COM11_HZAUTO},
|
||||
|
||||
/* Disable some delays */
|
||||
{HSYST, 0},
|
||||
{HSYEN, 0},
|
||||
|
||||
{MVFP, MVFP_SUN},
|
||||
|
||||
/* More reserved magic, some of which tweaks white balance */
|
||||
{AWBC1, 0x0a},
|
||||
{AWBC2, 0xf0},
|
||||
{AWBC3, 0x34},
|
||||
{AWBC4, 0x58},
|
||||
{AWBC5, 0x28},
|
||||
{AWBC6, 0x3a},
|
||||
|
||||
{AWBCTR3, 0x0a},
|
||||
{AWBCTR2, 0x55},
|
||||
{AWBCTR1, 0x11},
|
||||
{AWBCTR0, 0x9e},
|
||||
|
||||
{COM8, COM8_FAST_AUTO|COM8_STEP_UNLIMIT|COM8_AGC_EN|COM8_AEC_EN|COM8_AWB_EN},
|
||||
|
||||
/* End marker is FF because in ov7670 the address of GAIN 0 and default value too. */
|
||||
{0xFF, 0xFF},
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_fmt_yuv422[] = {
|
||||
{ COM7, 0x0 }, /* Selects YUV mode */
|
||||
{ RGB444, 0 }, /* No RGB444 please */
|
||||
{ COM1, 0 }, /* CCIR601 */
|
||||
{ COM15, COM15_R00FF },
|
||||
{ MVFP, MVFP_SUN },
|
||||
{ COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */
|
||||
{ MTX1, 0x80 }, /* "matrix coefficient 1" */
|
||||
{ MTX2, 0x80 }, /* "matrix coefficient 2" */
|
||||
{ MTX3, 0 }, /* vb */
|
||||
{ MTX4, 0x22 }, /* "matrix coefficient 4" */
|
||||
{ MTX5, 0x5e }, /* "matrix coefficient 5" */
|
||||
{ MTX6, 0x80 }, /* "matrix coefficient 6" */
|
||||
{ COM13, COM13_UVSAT },
|
||||
{ 0xff, 0xff }, /* END MARKER */
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_fmt_rgb565[] = {
|
||||
{ COM7, COM7_FMT_RGB565 }, /* Selects RGB mode */
|
||||
{ RGB444, 0 }, /* No RGB444 please */
|
||||
{ COM1, 0x0 }, /* CCIR601 */
|
||||
{ COM15, COM15_RGB565 |COM15_R00FF },
|
||||
{ MVFP, MVFP_SUN },
|
||||
{ COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */
|
||||
{ MTX1, 0xb3 }, /* "matrix coefficient 1" */
|
||||
{ MTX2, 0xb3 }, /* "matrix coefficient 2" */
|
||||
{ MTX3, 0 }, /* vb */
|
||||
{ MTX4, 0x3d }, /* "matrix coefficient 4" */
|
||||
{ MTX5, 0xa7 }, /* "matrix coefficient 5" */
|
||||
{ MTX6, 0xe4 }, /* "matrix coefficient 6" */
|
||||
{ COM13, COM13_UVSAT },
|
||||
{ 0xff, 0xff }, /* END MARKER */
|
||||
};
|
||||
|
||||
|
||||
static struct regval_list ov7670_vga[] = {
|
||||
{ COM3, 0x00 },
|
||||
{ COM14, 0x00 },
|
||||
{ SCALING_XSC, 0x3A },
|
||||
{ SCALING_YSC, 0x35 },
|
||||
{ SCALING_DCWCTR, 0x11 },
|
||||
{ SCALING_PCLK_DIV, 0xF0 },
|
||||
{ SCALING_PCLK_DELAY, 0x02 },
|
||||
{ 0xff, 0xff },
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_qvga[] = {
|
||||
{ COM3, 0x04 },
|
||||
{ COM14, 0x19 },
|
||||
{ SCALING_XSC, 0x3A },
|
||||
{ SCALING_YSC, 0x35 },
|
||||
{ SCALING_DCWCTR, 0x11 },
|
||||
{ SCALING_PCLK_DIV, 0xF1 },
|
||||
{ SCALING_PCLK_DELAY, 0x02 },
|
||||
{ 0xff, 0xff },
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_qqvga[] = {
|
||||
{ COM3, 0x04 }, //DCW enable
|
||||
{ COM14, 0x1a }, //pixel clock divided by 4, manual scaling enable, DCW and PCLK controlled by register
|
||||
{ SCALING_XSC, 0x3a },
|
||||
{ SCALING_YSC, 0x35 },
|
||||
{ SCALING_DCWCTR, 0x22 }, //downsample by 4
|
||||
{ SCALING_PCLK_DIV, 0xf2 }, //pixel clock divided by 4
|
||||
{ SCALING_PCLK_DELAY, 0x02 },
|
||||
{ 0xff, 0xff },
|
||||
};
|
||||
|
||||
/*
|
||||
* Write a list of register settings; ff/ff stops the process.
|
||||
*/
|
||||
static int ov7670_write_array(sensor_t *sensor, struct regval_list *vals)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while ( (vals->reg_num != 0xff || vals->value != 0xff) && (ret == 0) ) {
|
||||
ret = SCCB_Write(sensor->slv_addr, vals->reg_num, vals->value);
|
||||
|
||||
ESP_LOGD(TAG, "reset reg %02X, W(%02X) R(%02X)", vals->reg_num,
|
||||
vals->value, SCCB_Read(sensor->slv_addr, vals->reg_num) );
|
||||
|
||||
vals++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the frame control registers.
|
||||
*/
|
||||
static int ov7670_frame_control(sensor_t *sensor, int hstart, int hstop, int vstart, int vstop)
|
||||
{
|
||||
struct regval_list frame[7];
|
||||
|
||||
frame[0].reg_num = HSTART;
|
||||
frame[0].value = (hstart >> 3);
|
||||
|
||||
frame[1].reg_num = HSTOP;
|
||||
frame[1].value = (hstop >> 3);
|
||||
|
||||
frame[2].reg_num = HREF;
|
||||
frame[2].value = (((hstop & 0x07) << 3) | (hstart & 0x07));
|
||||
|
||||
frame[3].reg_num = VSTART;
|
||||
frame[3].value = (vstart >> 2);
|
||||
|
||||
frame[4].reg_num = VSTOP;
|
||||
frame[4].value = (vstop >> 2);
|
||||
|
||||
frame[5].reg_num = VREF;
|
||||
frame[5].value = (((vstop & 0x02) << 2) | (vstart & 0x02));
|
||||
|
||||
/* End mark */
|
||||
frame[5].reg_num = 0xFF;
|
||||
frame[5].value = 0xFF;
|
||||
|
||||
return ov7670_write_array(sensor, frame);
|
||||
}
|
||||
|
||||
static int reset(sensor_t *sensor)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// Reset all registers
|
||||
SCCB_Write(sensor->slv_addr, COM7, COM7_RESET);
|
||||
|
||||
// Delay 10 ms
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
ret = ov7670_write_array(sensor, ov7670_default_regs);
|
||||
|
||||
// Delay
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (pixformat) {
|
||||
case PIXFORMAT_RGB565:
|
||||
case PIXFORMAT_RGB888:
|
||||
ret = ov7670_write_array(sensor, ov7670_fmt_rgb565);
|
||||
break;
|
||||
|
||||
case PIXFORMAT_YUV422:
|
||||
case PIXFORMAT_GRAYSCALE:
|
||||
default:
|
||||
ret = ov7670_write_array(sensor, ov7670_fmt_yuv422);
|
||||
break;
|
||||
}
|
||||
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
|
||||
/*
|
||||
* If we're running RGB565, we must rewrite clkrc after setting
|
||||
* the other parameters or the image looks poor. If we're *not*
|
||||
* doing RGB565, we must not rewrite clkrc or the image looks
|
||||
* *really* poor.
|
||||
*
|
||||
* (Update) Now that we retain clkrc state, we should be able
|
||||
* to write it unconditionally, and that will make the frame
|
||||
* rate persistent too.
|
||||
*/
|
||||
if (pixformat == PIXFORMAT_RGB565) {
|
||||
ret = SCCB_Write(sensor->slv_addr, CLKRC, ov7670_clkrc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_framesize(sensor_t *sensor, framesize_t framesize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// store clkrc before changing window settings...
|
||||
ov7670_clkrc = SCCB_Read(sensor->slv_addr, CLKRC);
|
||||
|
||||
switch (framesize){
|
||||
case FRAMESIZE_VGA:
|
||||
if( (ret = ov7670_write_array(sensor, ov7670_vga)) == 0 ) {
|
||||
/* These values from Omnivision */
|
||||
ret = ov7670_frame_control(sensor, 158, 14, 10, 490);
|
||||
}
|
||||
break;
|
||||
case FRAMESIZE_QVGA:
|
||||
if( (ret = ov7670_write_array(sensor, ov7670_qvga)) == 0 ) {
|
||||
/* These values from Omnivision */
|
||||
ret = ov7670_frame_control(sensor, 158, 14, 10, 490);
|
||||
}
|
||||
break;
|
||||
case FRAMESIZE_QQVGA:
|
||||
if( (ret = ov7670_write_array(sensor, ov7670_qqvga)) == 0 ) {
|
||||
/* These values from Omnivision */
|
||||
ret = ov7670_frame_control(sensor, 158, 14, 10, 490);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
|
||||
if (ret == 0) {
|
||||
sensor->status.framesize = framesize;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_colorbar(sensor_t *sensor, int enable)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
// Read register scaling_xsc
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, SCALING_XSC);
|
||||
|
||||
// Pattern to set color bar bit[0]=0 in every case
|
||||
reg = SCALING_XSC_CBAR(reg);
|
||||
|
||||
// Write pattern to SCALING_XSC
|
||||
ret = SCCB_Write(sensor->slv_addr, SCALING_XSC, reg);
|
||||
|
||||
// Read register scaling_ysc
|
||||
reg = SCCB_Read(sensor->slv_addr, SCALING_YSC);
|
||||
|
||||
// Pattern to set color bar bit[0]=0 in every case
|
||||
reg = SCALING_YSC_CBAR(reg, enable);
|
||||
|
||||
// Write pattern to SCALING_YSC
|
||||
ret = ret | SCCB_Write(sensor->slv_addr, SCALING_YSC, reg);
|
||||
|
||||
// return 0 or 0xFF
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_whitebal(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AWB(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
}
|
||||
|
||||
static int set_gain_ctrl(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AGC(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
}
|
||||
|
||||
static int set_exposure_ctrl(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AEC(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
}
|
||||
|
||||
static int set_hmirror(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register MVFP
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP);
|
||||
|
||||
// Set mirror on/off
|
||||
reg = MVFP_SET_MIRROR(reg, enable);
|
||||
|
||||
// Write back register MVFP
|
||||
return SCCB_Write(sensor->slv_addr, MVFP, reg);
|
||||
}
|
||||
|
||||
static int set_vflip(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register MVFP
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP);
|
||||
|
||||
// Set mirror on/off
|
||||
reg = MVFP_SET_FLIP(reg, enable);
|
||||
|
||||
// Write back register MVFP
|
||||
return SCCB_Write(sensor->slv_addr, MVFP, reg);
|
||||
}
|
||||
|
||||
static int init_status(sensor_t *sensor)
|
||||
{
|
||||
sensor->status.awb = 0;
|
||||
sensor->status.aec = 0;
|
||||
sensor->status.agc = 0;
|
||||
sensor->status.hmirror = 0;
|
||||
sensor->status.vflip = 0;
|
||||
sensor->status.colorbar = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_dummy(sensor_t *sensor, int val){ return -1; }
|
||||
static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; }
|
||||
|
||||
int ov7670_init(sensor_t *sensor)
|
||||
{
|
||||
// Set function pointers
|
||||
sensor->reset = reset;
|
||||
sensor->init_status = init_status;
|
||||
sensor->set_pixformat = set_pixformat;
|
||||
sensor->set_framesize = set_framesize;
|
||||
sensor->set_colorbar = set_colorbar;
|
||||
sensor->set_whitebal = set_whitebal;
|
||||
sensor->set_gain_ctrl = set_gain_ctrl;
|
||||
sensor->set_exposure_ctrl = set_exposure_ctrl;
|
||||
sensor->set_hmirror = set_hmirror;
|
||||
sensor->set_vflip = set_vflip;
|
||||
|
||||
//not supported
|
||||
sensor->set_brightness= set_dummy;
|
||||
sensor->set_saturation= set_dummy;
|
||||
sensor->set_quality = set_dummy;
|
||||
sensor->set_gainceiling = set_gainceiling_dummy;
|
||||
sensor->set_aec2 = set_dummy;
|
||||
sensor->set_aec_value = set_dummy;
|
||||
sensor->set_special_effect = set_dummy;
|
||||
sensor->set_wb_mode = set_dummy;
|
||||
sensor->set_ae_level = set_dummy;
|
||||
sensor->set_dcw = set_dummy;
|
||||
sensor->set_bpc = set_dummy;
|
||||
sensor->set_wpc = set_dummy;
|
||||
sensor->set_awb_gain = set_dummy;
|
||||
sensor->set_agc_gain = set_dummy;
|
||||
sensor->set_raw_gma = set_dummy;
|
||||
sensor->set_lenc = set_dummy;
|
||||
sensor->set_sharpness = set_dummy;
|
||||
sensor->set_denoise = set_dummy;
|
||||
|
||||
// Retrieve sensor's signature
|
||||
sensor->id.MIDH = SCCB_Read(sensor->slv_addr, REG_MIDH);
|
||||
sensor->id.MIDL = SCCB_Read(sensor->slv_addr, REG_MIDL);
|
||||
sensor->id.PID = SCCB_Read(sensor->slv_addr, REG_PID);
|
||||
sensor->id.VER = SCCB_Read(sensor->slv_addr, REG_VER);
|
||||
|
||||
ESP_LOGD(TAG, "OV7670 Attached");
|
||||
|
||||
return 0;
|
||||
}
|
14
esp32-cam-rtos-allframes/ov7670.h
Normal file
14
esp32-cam-rtos-allframes/ov7670.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* OV7670 driver.
|
||||
*
|
||||
*/
|
||||
#ifndef __OV7670_H__
|
||||
#define __OV7670_H__
|
||||
#include "sensor.h"
|
||||
|
||||
int ov7670_init(sensor_t *sensor);
|
||||
#endif // __OV7670_H__
|
354
esp32-cam-rtos-allframes/ov7670_regs.h
Normal file
354
esp32-cam-rtos-allframes/ov7670_regs.h
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* This file is for the OpenMV project so the OV7670 can be used
|
||||
* author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
|
||||
*
|
||||
* OV7670 register definitions.
|
||||
*/
|
||||
#ifndef __OV7670_REG_REGS_H__
|
||||
#define __OV7670_REG_REGS_H__
|
||||
#define GAIN 0x00 /* AGC – Gain control gain setting */
|
||||
#define BLUE 0x01 /* AWB – Blue channel gain setting */
|
||||
#define RED 0x02 /* AWB – Red channel gain setting */
|
||||
#define VREF 0x03 /* AWB – Green channel gain setting */
|
||||
#define COM1 0x04 /* Common Control 1 */
|
||||
#define BAVG 0x05 /* U/B Average Level */
|
||||
#define GAVG 0x06 /* Y/Gb Average Level */
|
||||
#define AECH 0x07 /* Exposure VAlue - AEC MSB 5 bits */
|
||||
#define RAVG 0x08 /* V/R Average Level */
|
||||
|
||||
#define COM2 0x09 /* Common Control 2 */
|
||||
#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */
|
||||
#define COM2_OUT_DRIVE_1x 0x00 /* Output drive capability 1x */
|
||||
#define COM2_OUT_DRIVE_2x 0x01 /* Output drive capability 2x */
|
||||
#define COM2_OUT_DRIVE_3x 0x02 /* Output drive capability 3x */
|
||||
#define COM2_OUT_DRIVE_4x 0x03 /* Output drive capability 4x */
|
||||
|
||||
#define REG_PID 0x0A /* Product ID Number MSB */
|
||||
#define REG_VER 0x0B /* Product ID Number LSB */
|
||||
|
||||
#define COM3 0x0C /* Common Control 3 */
|
||||
#define COM3_SWAP_OUT 0x40 /* Output data MSB/LSB swap */
|
||||
#define COM3_TRI_CLK 0x20 /* Tri-state output clock */
|
||||
#define COM3_TRI_DATA 0x10 /* Tri-state option output */
|
||||
#define COM3_SCALE_EN 0x08 /* Scale enable */
|
||||
#define COM3_DCW 0x04 /* DCW enable */
|
||||
|
||||
#define COM4 0x0D /* Common Control 4 */
|
||||
#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */
|
||||
#define COM4_PLL_4x 0x40 /* PLL frequency 4x */
|
||||
#define COM4_PLL_6x 0x80 /* PLL frequency 6x */
|
||||
#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */
|
||||
#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */
|
||||
#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */
|
||||
#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */
|
||||
#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */
|
||||
|
||||
#define COM5 0x0E /* Common Control 5 */
|
||||
#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */
|
||||
#define COM5_AFR_SPEED 0x40 /* Auto frame rate control speed selection */
|
||||
#define COM5_AFR_0 0x00 /* No reduction of frame rate */
|
||||
#define COM5_AFR_1_2 0x10 /* Max reduction to 1/2 frame rate */
|
||||
#define COM5_AFR_1_4 0x20 /* Max reduction to 1/4 frame rate */
|
||||
#define COM5_AFR_1_8 0x30 /* Max reduction to 1/8 frame rate */
|
||||
#define COM5_AFR_4x 0x04 /* Add frame when AGC reaches 4x gain */
|
||||
#define COM5_AFR_8x 0x08 /* Add frame when AGC reaches 8x gain */
|
||||
#define COM5_AFR_16x 0x0c /* Add frame when AGC reaches 16x gain */
|
||||
#define COM5_AEC_NO_LIMIT 0x01 /* No limit to AEC increase step */
|
||||
|
||||
#define COM6 0x0F /* Common Control 6 */
|
||||
#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */
|
||||
|
||||
#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */
|
||||
#define CLKRC 0x11 /* Internal Clock */
|
||||
|
||||
#define COM7 0x12 /* Common Control 7 */
|
||||
#define COM7_RESET 0x80 /* SCCB Register Reset */
|
||||
#define COM7_RES_VGA 0x00 /* Resolution VGA */
|
||||
#define COM7_RES_QVGA 0x40 /* Resolution QVGA */
|
||||
#define COM7_BT656 0x20 /* BT.656 protocol ON/OFF */
|
||||
#define COM7_SENSOR_RAW 0x10 /* Sensor RAW */
|
||||
#define COM7_FMT_GBR422 0x00 /* RGB output format GBR422 */
|
||||
#define COM7_FMT_RGB565 0x04 /* RGB output format RGB565 */
|
||||
#define COM7_FMT_RGB555 0x08 /* RGB output format RGB555 */
|
||||
#define COM7_FMT_RGB444 0x0C /* RGB output format RGB444 */
|
||||
#define COM7_FMT_YUV 0x00 /* Output format YUV */
|
||||
#define COM7_FMT_P_BAYER 0x01 /* Output format Processed Bayer RAW */
|
||||
#define COM7_FMT_RGB 0x04 /* Output format RGB */
|
||||
#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */
|
||||
#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x5)<<0))
|
||||
|
||||
#define COM8 0x13 /* Common Control 8 */
|
||||
#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */
|
||||
#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */
|
||||
#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */
|
||||
#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */
|
||||
#define COM8_AEC_BANDF 0x10 /* Enable AEC below banding value */
|
||||
#define COM8_AEC_FINE_EN 0x08 /* Fine AEC ON/OFF control */
|
||||
#define COM8_AGC_EN 0x04 /* AGC Enable */
|
||||
#define COM8_AWB_EN 0x02 /* AWB Enable */
|
||||
#define COM8_AEC_EN 0x01 /* AEC Enable */
|
||||
#define COM8_SET_AGC(r, x) ((r&0xFB)|((x&0x1)<<2))
|
||||
#define COM8_SET_AWB(r, x) ((r&0xFD)|((x&0x1)<<1))
|
||||
#define COM8_SET_AEC(r, x) ((r&0xFE)|((x&0x1)<<0))
|
||||
|
||||
#define COM9 0x14 /* Common Control 9 */
|
||||
#define COM9_HISTO_AVG 0x80 /* Histogram or average based AEC/AGC selection */
|
||||
#define COM9_AGC_GAIN_2x 0x00 /* Automatic Gain Ceiling 2x */
|
||||
#define COM9_AGC_GAIN_4x 0x10 /* Automatic Gain Ceiling 4x */
|
||||
#define COM9_AGC_GAIN_8x 0x20 /* Automatic Gain Ceiling 8x */
|
||||
#define COM9_AGC_GAIN_16x 0x30 /* Automatic Gain Ceiling 16x */
|
||||
#define COM9_AGC_GAIN_32x 0x40 /* Automatic Gain Ceiling 32x */
|
||||
#define COM9_DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */
|
||||
#define COM9_DROP_HREF 0x02 /* Drop HREF output of corrupt frame */
|
||||
#define COM9_SET_AGC(r, x) ((r&0x8F)|((x&0x07)<<4))
|
||||
|
||||
#define COM10 0x15 /* Common Control 10 */
|
||||
#define COM10_NEGATIVE 0x80 /* Output negative data */
|
||||
#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */
|
||||
#define COM10_PCLK_FREE 0x00 /* PCLK output option: free running PCLK */
|
||||
#define COM10_PCLK_MASK 0x20 /* PCLK output option: masked during horizontal blank */
|
||||
#define COM10_PCLK_REV 0x10 /* PCLK reverse */
|
||||
#define COM10_HREF_REV 0x08 /* HREF reverse */
|
||||
#define COM10_VSYNC_FALLING 0x00 /* VSYNC changes on falling edge of PCLK */
|
||||
#define COM10_VSYNC_RISING 0x04 /* VSYNC changes on rising edge of PCLK */
|
||||
#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */
|
||||
#define COM10_OUT_RANGE_8 0x01 /* Output data range: Full range */
|
||||
#define COM10_OUT_RANGE_10 0x00 /* Output data range: Data from [10] to [F0] (8 MSBs) */
|
||||
|
||||
#define RSVD_16 0x16 /* Reserved register */
|
||||
|
||||
#define HSTART 0x17 /* Horizontal Frame (HREF column) Start high 8-bit(low 3 bits are at HREF[2:0]) */
|
||||
#define HSTOP 0x18 /* Horizontal Frame (HREF column) end high 8-bit (low 3 bits are at HREF[5:3]) */
|
||||
#define VSTART 0x19 /* Vertical Frame (row) Start high 8-bit (low 2 bits are at VREF[1:0]) */
|
||||
#define VSTOP 0x1A /* Vertical Frame (row) End high 8-bit (low 2 bits are at VREF[3:2]) */
|
||||
#define PSHFT 0x1B /* Data Format - Pixel Delay Select */
|
||||
#define REG_MIDH 0x1C /* Manufacturer ID Byte – High */
|
||||
#define REG_MIDL 0x1D /* Manufacturer ID Byte – Low */
|
||||
|
||||
#define MVFP 0x1E /* Mirror/Vflip Enable */
|
||||
#define MVFP_MIRROR 0x20 /* Mirror image */
|
||||
#define MVFP_FLIP 0x10 /* Vertical flip */
|
||||
#define MVFP_SUN 0x02 /* Black sun enable */
|
||||
#define MVFP_SET_MIRROR(r,x) ((r&0xDF)|((x&1)<<5)) /* change only bit5 according to x */
|
||||
#define MVFP_SET_FLIP(r,x) ((r&0xEF)|((x&1)<<4)) /* change only bit4 according to x */
|
||||
|
||||
#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period (Reserved?) */
|
||||
#define ADCCTR0 0x20 /* ADC control */
|
||||
#define ADCCTR1 0x21 /* reserved */
|
||||
#define ADCCTR2 0x22 /* reserved */
|
||||
#define ADCCTR3 0x23 /* reserved */
|
||||
#define AEW 0x24 /* AGC/AEC - Stable Operating Region (Upper Limit) */
|
||||
#define AEB 0x25 /* AGC/AEC - Stable Operating Region (Lower Limit) */
|
||||
#define VPT 0x26 /* AGC/AEC Fast Mode Operating Region */
|
||||
#define BBIAS 0x27 /* B channel signal output bias (effective only when COM6[3]=1) */
|
||||
#define GbBIAS 0x28 /* Gb channel signal output bias (effective only when COM6[3]=1) */
|
||||
#define RSVD_29 0x29 /* reserved */
|
||||
#define EXHCH 0x2A /* Dummy Pixel Insert MSB */
|
||||
#define EXHCL 0x2B /* Dummy Pixel Insert LSB */
|
||||
#define RBIAS 0x2C /* R channel signal output bias (effective only when COM6[3]=1) */
|
||||
#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */
|
||||
#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */
|
||||
#define YAVE 0x2F /* Y/G Channel Average Value */
|
||||
#define HSYST 0x30 /* HSync rising edge delay */
|
||||
#define HSYEN 0x31 /* HSync falling edge delay */
|
||||
#define HREF 0x32 /* Image Start and Size Control DIFFERENT CONTROL SEQUENCE */
|
||||
#define CHLF 0x33 /* Array Current control */
|
||||
#define ARBLM 0x34 /* Array reference control */
|
||||
#define RSVD_35 0x35 /* Reserved */
|
||||
#define RSVD_36 0x36 /* Reserved */
|
||||
#define ADC 0x37 /* ADC control */
|
||||
#define ACOM 0x38 /* ADC and analog common mode control */
|
||||
#define OFON 0x39 /* ADC offset control */
|
||||
#define TSLB 0x3A /* Line buffer test option */
|
||||
|
||||
#define COM11 0x3B /* Common control 11 */
|
||||
#define COM11_EXP 0x02
|
||||
#define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */
|
||||
|
||||
#define COM12 0x3C /* Common control 12 */
|
||||
|
||||
#define COM13 0x3D /* Common control 13 */
|
||||
#define COM13_GAMMA 0x80 /* Gamma enable */
|
||||
#define COM13_UVSAT 0x40 /* UV saturation auto adjustment */
|
||||
|
||||
#define COM14 0x3E /* Common Control 14 */
|
||||
|
||||
#define EDGE 0x3F /* edge enhancement adjustment */
|
||||
#define COM15 0x40 /* Common Control 15 DIFFERENT CONTROLS */
|
||||
#define COM15_SET_RGB565(r,x) ((r&0xEF)|((x&1)<<4)) /* set rgb565 mode */
|
||||
#define COM15_RGB565 0x10 /* RGB565 output */
|
||||
#define COM15_R00FF 0xC0 /* Output range: [00] to [FF] */
|
||||
|
||||
#define COM16 0x41 /* Common Control 16 DIFFERENT CONTROLS */
|
||||
#define COM16_AWBGAIN 0x08 /* AWB gain enable */
|
||||
#define COM17 0x42 /* Common Control 17 */
|
||||
|
||||
#define AWBC1 0x43 /* Reserved */
|
||||
#define AWBC2 0x44 /* Reserved */
|
||||
#define AWBC3 0x45 /* Reserved */
|
||||
#define AWBC4 0x46 /* Reserved */
|
||||
#define AWBC5 0x47 /* Reserved */
|
||||
#define AWBC6 0x48 /* Reserved */
|
||||
|
||||
#define RSVD_49 0x49 /* Reserved */
|
||||
#define RSVD_4A 0x4A /* Reserved */
|
||||
|
||||
#define REG4B 0x4B /* Register 4B */
|
||||
#define DNSTH 0x4C /* Denoise strength */
|
||||
|
||||
#define RSVD_4D 0x4D /* Reserved */
|
||||
#define RSVD_4E 0x4E /* Reserved */
|
||||
|
||||
#define MTX1 0x4F /* Matrix coefficient 1 */
|
||||
#define MTX2 0x50 /* Matrix coefficient 2 */
|
||||
#define MTX3 0x51 /* Matrix coefficient 3 */
|
||||
#define MTX4 0x52 /* Matrix coefficient 4 */
|
||||
#define MTX5 0x53 /* Matrix coefficient 5 */
|
||||
#define MTX6 0x54 /* Matrix coefficient 6 */
|
||||
#define BRIGHTNESS 0x55 /* Brightness control */
|
||||
#define CONTRAST 0x56 /* Contrast control */
|
||||
#define CONTRASCENTER 0x57 /* Contrast center */
|
||||
#define MTXS 0x58 /* Matrix coefficient sign for coefficient 5 to 0*/
|
||||
|
||||
#define RSVD_59 0x59 /* Reserved */
|
||||
#define RSVD_5A 0x5A /* Reserved */
|
||||
#define RSVD_5B 0x5B /* Reserved */
|
||||
#define RSVD_5C 0x5C /* Reserved */
|
||||
#define RSVD_5D 0x5D /* Reserved */
|
||||
#define RSVD_5E 0x5E /* Reserved */
|
||||
#define RSVD_5F 0x5F /* Reserved */
|
||||
#define RSVD_60 0x60 /* Reserved */
|
||||
#define RSVD_61 0x61 /* Reserved */
|
||||
|
||||
#define LCC1 0x62 /* Lens correction option 1 */
|
||||
|
||||
#define LCC2 0x63 /* Lens correction option 2 */
|
||||
#define LCC3 0x64 /* Lens correction option 3 */
|
||||
#define LCC4 0x65 /* Lens correction option 4 */
|
||||
#define LCC5 0x66 /* Lens correction option 5 */
|
||||
|
||||
#define MANU 0x67 /* Manual U Value */
|
||||
#define MANV 0x68 /* Manual V Value */
|
||||
#define GFIX 0x69 /* Fix gain control */
|
||||
#define GGAIN 0x6A /* G channel AWB gain */
|
||||
|
||||
#define DBLV 0x6B /* PLL and clock ? */
|
||||
|
||||
#define AWBCTR3 0x6C /* AWB Control 3 */
|
||||
#define AWBCTR2 0x6D /* AWB Control 2 */
|
||||
#define AWBCTR1 0x6E /* AWB Control 1 */
|
||||
#define AWBCTR0 0x6F /* AWB Control 0 */
|
||||
#define SCALING_XSC 0x70 /* test pattern and horizontal scaling factor */
|
||||
#define SCALING_XSC_CBAR(r) (r&0x7F) /* make sure bit7 is 0 for color bar */
|
||||
#define SCALING_YSC 0x71 /* test pattern and vertical scaling factor */
|
||||
#define SCALING_YSC_CBAR(r,x) ((r&0x7F)|((x&1)<<7)) /* change bit7 for color bar on/off */
|
||||
#define SCALING_DCWCTR 0x72 /* DCW control */
|
||||
#define SCALING_PCLK_DIV 0x73 /* */
|
||||
#define REG74 0x74 /* */
|
||||
#define REG75 0x75 /* */
|
||||
#define REG76 0x76 /* */
|
||||
#define REG77 0x77 /* */
|
||||
|
||||
#define RSVD_78 0x78 /* Reserved */
|
||||
#define RSVD_79 0x79 /* Reserved */
|
||||
|
||||
#define SLOP 0x7A /* Gamma curve highest segment slope */
|
||||
#define GAM1 0x7B /* Gamma Curve 1st Segment Input End Point 0x04 Output Value */
|
||||
#define GAM2 0x7C /* Gamma Curve 2nd Segment Input End Point 0x08 Output Value */
|
||||
#define GAM3 0x7D /* Gamma Curve 3rd Segment Input End Point 0x10 Output Value */
|
||||
#define GAM4 0x7E /* Gamma Curve 4th Segment Input End Point 0x20 Output Value */
|
||||
#define GAM5 0x7F /* Gamma Curve 5th Segment Input End Point 0x28 Output Value */
|
||||
#define GAM6 0x80 /* Gamma Curve 6rd Segment Input End Point 0x30 Output Value */
|
||||
#define GAM7 0x81 /* Gamma Curve 7th Segment Input End Point 0x38 Output Value */
|
||||
#define GAM8 0x82 /* Gamma Curve 8th Segment Input End Point 0x40 Output Value */
|
||||
#define GAM9 0x83 /* Gamma Curve 9th Segment Input End Point 0x48 Output Value */
|
||||
#define GAM10 0x84 /* Gamma Curve 10th Segment Input End Point 0x50 Output Value */
|
||||
#define GAM11 0x85 /* Gamma Curve 11th Segment Input End Point 0x60 Output Value */
|
||||
#define GAM12 0x86 /* Gamma Curve 12th Segment Input End Point 0x70 Output Value */
|
||||
#define GAM13 0x87 /* Gamma Curve 13th Segment Input End Point 0x90 Output Value */
|
||||
#define GAM14 0x88 /* Gamma Curve 14th Segment Input End Point 0xB0 Output Value */
|
||||
#define GAM15 0x89 /* Gamma Curve 15th Segment Input End Point 0xD0 Output Value */
|
||||
|
||||
#define RSVD_8A 0x8A /* Reserved */
|
||||
#define RSVD_8B 0x8B /* Reserved */
|
||||
|
||||
#define RGB444 0x8C /* */
|
||||
|
||||
#define RSVD_8D 0x8D /* Reserved */
|
||||
#define RSVD_8E 0x8E /* Reserved */
|
||||
#define RSVD_8F 0x8F /* Reserved */
|
||||
#define RSVD_90 0x90 /* Reserved */
|
||||
#define RSVD_91 0x91 /* Reserved */
|
||||
|
||||
#define DM_LNL 0x92 /* Dummy line low 8 bit */
|
||||
#define DM_LNH 0x93 /* Dummy line high 8 bit */
|
||||
#define LCC6 0x94 /* Lens correction option 6 */
|
||||
#define LCC7 0x95 /* Lens correction option 7 */
|
||||
|
||||
#define RSVD_96 0x96 /* Reserved */
|
||||
#define RSVD_97 0x97 /* Reserved */
|
||||
#define RSVD_98 0x98 /* Reserved */
|
||||
#define RSVD_99 0x99 /* Reserved */
|
||||
#define RSVD_9A 0x9A /* Reserved */
|
||||
#define RSVD_9B 0x9B /* Reserved */
|
||||
#define RSVD_9C 0x9C /* Reserved */
|
||||
|
||||
#define BD50ST 0x9D /* 50 Hz banding filter value */
|
||||
#define BD60ST 0x9E /* 60 Hz banding filter value */
|
||||
#define HAECC1 0x9F /* Histogram-based AEC/AGC control 1 */
|
||||
#define HAECC2 0xA0 /* Histogram-based AEC/AGC control 2 */
|
||||
|
||||
#define RSVD_A1 0xA1 /* Reserved */
|
||||
|
||||
#define SCALING_PCLK_DELAY 0xA2 /* Pixel clock delay */
|
||||
|
||||
#define RSVD_A3 0xA3 /* Reserved */
|
||||
|
||||
#define NT_CNTRL 0xA4 /* */
|
||||
#define BD50MAX 0xA5 /* 50 Hz banding step limit */
|
||||
#define HAECC3 0xA6 /* Histogram-based AEC/AGC control 3 */
|
||||
#define HAECC4 0xA7 /* Histogram-based AEC/AGC control 4 */
|
||||
#define HAECC5 0xA8 /* Histogram-based AEC/AGC control 5 */
|
||||
#define HAECC6 0xA9 /* Histogram-based AEC/AGC control 6 */
|
||||
|
||||
#define HAECC7 0xAA /* Histogram-based AEC/AGC control 7 */
|
||||
#define HAECC_EN 0x80 /* Histogram-based AEC algorithm enable */
|
||||
|
||||
#define BD60MAX 0xAB /* 60 Hz banding step limit */
|
||||
|
||||
#define STR_OPT 0xAC /* Register AC */
|
||||
#define STR_R 0xAD /* R gain for led output frame */
|
||||
#define STR_G 0xAE /* G gain for led output frame */
|
||||
#define STR_B 0xAF /* B gain for led output frame */
|
||||
#define RSVD_B0 0xB0 /* Reserved */
|
||||
#define ABLC1 0xB1 /* */
|
||||
#define RSVD_B2 0xB2 /* Reserved */
|
||||
#define THL_ST 0xB3 /* ABLC target */
|
||||
#define THL_DLT 0xB5 /* ABLC stable range */
|
||||
|
||||
#define RSVD_B6 0xB6 /* Reserved */
|
||||
#define RSVD_B7 0xB7 /* Reserved */
|
||||
#define RSVD_B8 0xB8 /* Reserved */
|
||||
#define RSVD_B9 0xB9 /* Reserved */
|
||||
#define RSVD_BA 0xBA /* Reserved */
|
||||
#define RSVD_BB 0xBB /* Reserved */
|
||||
#define RSVD_BC 0xBC /* Reserved */
|
||||
#define RSVD_BD 0xBD /* Reserved */
|
||||
|
||||
#define AD_CHB 0xBE /* blue channel black level compensation */
|
||||
#define AD_CHR 0xBF /* Red channel black level compensation */
|
||||
#define AD_CHGb 0xC0 /* Gb channel black level compensation */
|
||||
#define AD_CHGr 0xC1 /* Gr channel black level compensation */
|
||||
|
||||
#define RSVD_C2 0xC2 /* Reserved */
|
||||
#define RSVD_C3 0xC3 /* Reserved */
|
||||
#define RSVD_C4 0xC4 /* Reserved */
|
||||
#define RSVD_C5 0xC5 /* Reserved */
|
||||
#define RSVD_C6 0xC6 /* Reserved */
|
||||
#define RSVD_C7 0xC7 /* Reserved */
|
||||
#define RSVD_C8 0xC8 /* Reserved */
|
||||
|
||||
#define SATCTR 0xC9 /* Saturation control */
|
||||
#define SET_REG(reg, x) (##reg_DEFAULT|x)
|
||||
|
||||
#endif //__OV7670_REG_REGS_H__
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include "sccb.h"
|
||||
|
@ -19,11 +20,8 @@
|
|||
static const char* TAG = "sccb";
|
||||
#endif
|
||||
|
||||
//#undef CONFIG_SCCB_HARDWARE_I2C
|
||||
|
||||
#define LITTLETOBIG(x) ((x<<8)|(x>>8))
|
||||
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
#include "driver/i2c.h"
|
||||
|
||||
#define SCCB_FREQ 100000 /*!< I2C master frequency*/
|
||||
|
@ -39,16 +37,13 @@ const int SCCB_I2C_PORT = 1;
|
|||
const int SCCB_I2C_PORT = 0;
|
||||
#endif
|
||||
static uint8_t ESP_SLAVE_ADDR = 0x3c;
|
||||
#else
|
||||
#include "twi.h"
|
||||
#endif
|
||||
|
||||
int SCCB_Init(int pin_sda, int pin_scl)
|
||||
{
|
||||
ESP_LOGI(TAG, "pin_sda %d pin_scl %d\n", pin_sda, pin_scl);
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
//log_i("SCCB_Init start");
|
||||
i2c_config_t conf;
|
||||
memset(&conf, 0, sizeof(i2c_config_t));
|
||||
conf.mode = I2C_MODE_MASTER;
|
||||
conf.sda_io_num = pin_sda;
|
||||
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
|
@ -58,15 +53,11 @@ int SCCB_Init(int pin_sda, int pin_scl)
|
|||
|
||||
i2c_param_config(SCCB_I2C_PORT, &conf);
|
||||
i2c_driver_install(SCCB_I2C_PORT, conf.mode, 0, 0, 0);
|
||||
#else
|
||||
twi_init(pin_sda, pin_scl);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t SCCB_Probe()
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
uint8_t slave_addr = 0x0;
|
||||
while(slave_addr < 0x7f) {
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
@ -82,28 +73,10 @@ uint8_t SCCB_Probe()
|
|||
slave_addr++;
|
||||
}
|
||||
return ESP_SLAVE_ADDR;
|
||||
#else
|
||||
uint8_t reg = 0x00;
|
||||
uint8_t slv_addr = 0x00;
|
||||
|
||||
ESP_LOGI(TAG, "SCCB_Probe start");
|
||||
for (uint8_t i = 0; i < 127; i++) {
|
||||
if (twi_writeTo(i, ®, 1, true) == 0) {
|
||||
slv_addr = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i!=126) {
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS); // Necessary for OV7725 camera (not for OV2640).
|
||||
}
|
||||
}
|
||||
return slv_addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
uint8_t data=0;
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
@ -125,28 +98,10 @@ uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
|
|||
ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
|
||||
}
|
||||
return data;
|
||||
#else
|
||||
uint8_t data=0;
|
||||
|
||||
int rc = twi_writeTo(slv_addr, ®, 1, true);
|
||||
if (rc != 0) {
|
||||
data = 0xff;
|
||||
} else {
|
||||
rc = twi_readFrom(slv_addr, &data, 1, true);
|
||||
if (rc != 0) {
|
||||
data=0xFF;
|
||||
}
|
||||
}
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "SCCB_Read [%02x] failed rc=%d\n", reg, rc);
|
||||
}
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
|
@ -160,23 +115,10 @@ uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
|
|||
ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
|
||||
}
|
||||
return ret == ESP_OK ? 0 : -1;
|
||||
#else
|
||||
uint8_t ret=0;
|
||||
uint8_t buf[] = {reg, data};
|
||||
|
||||
if(twi_writeTo(slv_addr, buf, 2, true) != 0) {
|
||||
ret=0xFF;
|
||||
}
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "SCCB_Write [%02x]=%02x failed\n", reg, data);
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
uint8_t data=0;
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
|
@ -201,32 +143,11 @@ uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
|
|||
ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data);
|
||||
}
|
||||
return data;
|
||||
#else
|
||||
uint8_t data=0;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
uint8_t *reg_u8 = (uint8_t *)®_htons;
|
||||
uint8_t buf[] = {reg_u8[0], reg_u8[1]};
|
||||
|
||||
int rc = twi_writeTo(slv_addr, buf, 2, true);
|
||||
if (rc != 0) {
|
||||
data = 0xff;
|
||||
} else {
|
||||
rc = twi_readFrom(slv_addr, &data, 1, true);
|
||||
if (rc != 0) {
|
||||
data=0xFF;
|
||||
}
|
||||
}
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "R [%04x] fail rc=%d\n", reg, rc);
|
||||
}
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data)
|
||||
{
|
||||
static uint16_t i = 0;
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
uint8_t *reg_u8 = (uint8_t *)®_htons;
|
||||
|
@ -243,18 +164,4 @@ uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data)
|
|||
ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++);
|
||||
}
|
||||
return ret == ESP_OK ? 0 : -1;
|
||||
#else
|
||||
uint8_t ret=0;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
uint8_t *reg_u8 = (uint8_t *)®_htons;
|
||||
uint8_t buf[] = {reg_u8[0], reg_u8[1], data};
|
||||
|
||||
if(twi_writeTo(slv_addr, buf, 3, true) != 0) {
|
||||
ret = 0xFF;
|
||||
}
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++);
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -11,11 +11,13 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define NT99141_PID (0x14)
|
||||
#define OV9650_PID (0x96)
|
||||
#define OV7725_PID (0x77)
|
||||
#define OV2640_PID (0x26)
|
||||
#define OV3660_PID (0x36)
|
||||
#define OV5640_PID (0x56)
|
||||
#define OV7670_PID (0x76)
|
||||
|
||||
typedef enum {
|
||||
PIXFORMAT_RGB565, // 2BPP/RGB565
|
||||
|
|
|
@ -20,6 +20,17 @@
|
|||
#include "sdkconfig.h"
|
||||
#include "esp_jpg_decode.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+
|
||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||
#include "esp32/spiram.h"
|
||||
#else
|
||||
#error Target CONFIG_IDF_TARGET is not supported
|
||||
#endif
|
||||
#else // ESP32 Before IDF 4.0
|
||||
#include "esp_spiram.h"
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
|
||||
#include "esp32-hal-log.h"
|
||||
#define TAG ""
|
||||
|
|
|
@ -35,4 +35,4 @@ uint8_t twi_readFrom(unsigned char address, unsigned char * buf, unsigned int le
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -48,6 +48,12 @@
|
|||
#if CONFIG_OV5640_SUPPORT
|
||||
#include "ov5640.h"
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
#include "nt99141.h"
|
||||
#endif
|
||||
#if CONFIG_OV7670_SUPPORT
|
||||
#include "ov7670.h"
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
CAMERA_NONE = 0,
|
||||
|
@ -56,6 +62,8 @@ typedef enum {
|
|||
CAMERA_OV2640 = 2640,
|
||||
CAMERA_OV3660 = 3660,
|
||||
CAMERA_OV5640 = 5640,
|
||||
CAMERA_OV7670 = 7670,
|
||||
CAMERA_NT99141 = 9141,
|
||||
} camera_model_t;
|
||||
|
||||
#define REG_PID 0x0A
|
||||
|
@ -369,12 +377,10 @@ static inline void IRAM_ATTR i2s_conf_reset()
|
|||
}
|
||||
}
|
||||
|
||||
static void i2s_init()
|
||||
static void i2s_gpio_init(const camera_config_t* config)
|
||||
{
|
||||
camera_config_t* config = &s_state->config;
|
||||
|
||||
// Configure input GPIOs
|
||||
gpio_num_t pins[] = {
|
||||
const gpio_num_t pins[] = {
|
||||
config->pin_d7,
|
||||
config->pin_d6,
|
||||
config->pin_d5,
|
||||
|
@ -391,15 +397,21 @@ static void i2s_init()
|
|||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.pin_bit_mask = 0LL
|
||||
};
|
||||
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);
|
||||
conf.pin_bit_mask |= 1LL << pins[i];
|
||||
}
|
||||
gpio_config(&conf);
|
||||
}
|
||||
|
||||
static void i2s_init()
|
||||
{
|
||||
camera_config_t* config = &s_state->config;
|
||||
|
||||
// Route input GPIOs to I2S peripheral using GPIO matrix
|
||||
gpio_matrix_in(config->pin_d0, I2S0I_DATA_IN0_IDX, false);
|
||||
|
@ -738,7 +750,7 @@ 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("bh 0x%08x\n", sig);
|
||||
ESP_LOGD(TAG,"unexpected JPEG signature 0x%08x\n", sig);
|
||||
s_state->fb->bad = 1;
|
||||
return;
|
||||
}
|
||||
|
@ -955,11 +967,15 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Enabling XCLK output");
|
||||
camera_enable_out_clock(config);
|
||||
if(config->pin_xclk >= 0) {
|
||||
ESP_LOGD(TAG, "Enabling XCLK output");
|
||||
camera_enable_out_clock(config);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Initializing SSCB");
|
||||
SCCB_Init(config->pin_sscb_sda, config->pin_sscb_scl);
|
||||
if (config->pin_sscb_sda != -1) {
|
||||
ESP_LOGD(TAG, "Initializing SSCB");
|
||||
SCCB_Init(config->pin_sscb_sda, config->pin_sscb_scl);
|
||||
}
|
||||
|
||||
if(config->pin_pwdn >= 0) {
|
||||
ESP_LOGD(TAG, "Resetting camera by power down line");
|
||||
|
@ -1011,16 +1027,33 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
slv_addr = SCCB_Probe();
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
if (slv_addr == 0x2a)
|
||||
{
|
||||
ESP_LOGD(TAG, "Resetting NT99141");
|
||||
SCCB_Write16(0x2a, 0x3008, 0x01);//bank sensor
|
||||
}
|
||||
#endif
|
||||
|
||||
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 (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT || CONFIG_NT99141_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);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
ESP_LOGD(TAG, "Camera PID=0x%02x VER=0x%02x", id->PID, id->VER);
|
||||
} else if(s_state->sensor.slv_addr == 0x2a){
|
||||
id->PID = SCCB_Read16(s_state->sensor.slv_addr, 0x3000);
|
||||
id->VER = SCCB_Read16(s_state->sensor.slv_addr, 0x3001);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
ESP_LOGD(TAG, "Camera PID=0x%02x VER=0x%02x", id->PID, id->VER);
|
||||
if(config->xclk_freq_hz > 10000000)
|
||||
{
|
||||
ESP_LOGE(TAG, "NT99141: only XCLK under 10MHz is supported, and XCLK is now set to 10M");
|
||||
s_state->sensor.xclk_freq_hz = 10000000;
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
id->PID = SCCB_Read(s_state->sensor.slv_addr, REG_PID);
|
||||
|
@ -1031,7 +1064,7 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
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 || CONFIG_OV5640_SUPPORT)
|
||||
#if (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT || CONFIG_NT99141_SUPPORT)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1060,6 +1093,18 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
*out_camera_model = CAMERA_OV5640;
|
||||
ov5640_init(&s_state->sensor);
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_OV7670_SUPPORT
|
||||
case OV7670_PID:
|
||||
*out_camera_model = CAMERA_OV7670;
|
||||
ov7670_init(&s_state->sensor);
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
case NT99141_PID:
|
||||
*out_camera_model = CAMERA_NT99141;
|
||||
NT99141_init(&s_state->sensor);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
id->PID = 0;
|
||||
|
@ -1116,6 +1161,20 @@ esp_err_t camera_init(const camera_config_t* config)
|
|||
frame_size = FRAMESIZE_QSXGA;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_OV7670_SUPPORT
|
||||
case OV7670_PID:
|
||||
if (frame_size > FRAMESIZE_VGA) {
|
||||
frame_size = FRAMESIZE_VGA;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
case NT99141_PID:
|
||||
if (frame_size > FRAMESIZE_HD) {
|
||||
frame_size = FRAMESIZE_HD;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return ESP_ERR_CAMERA_NOT_SUPPORTED;
|
||||
|
@ -1126,7 +1185,7 @@ esp_err_t camera_init(const camera_config_t* config)
|
|||
|
||||
if (pix_format == PIXFORMAT_GRAYSCALE) {
|
||||
s_state->fb_size = s_state->width * s_state->height;
|
||||
if (s_state->sensor.id.PID == OV3660_PID || s_state->sensor.id.PID == OV5640_PID) {
|
||||
if (s_state->sensor.id.PID == OV3660_PID || s_state->sensor.id.PID == OV5640_PID || s_state->sensor.id.PID == NT99141_PID) {
|
||||
if (is_hs_mode()) {
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
s_state->dma_filter = &dma_filter_yuyv_highspeed;
|
||||
|
@ -1147,20 +1206,28 @@ esp_err_t camera_init(const camera_config_t* config)
|
|||
}
|
||||
s_state->fb_bytes_per_pixel = 1; // frame buffer stores Y8
|
||||
} else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) {
|
||||
s_state->fb_size = s_state->width * s_state->height * 2;
|
||||
if (is_hs_mode() && s_state->sensor.id.PID != OV7725_PID) {
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
s_state->dma_filter = &dma_filter_yuyv_highspeed;
|
||||
} else {
|
||||
s_state->sampling_mode = SM_0A0B_0C0D;
|
||||
s_state->dma_filter = &dma_filter_yuyv;
|
||||
}
|
||||
s_state->in_bytes_per_pixel = 2; // camera sends YU/YV
|
||||
s_state->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
|
||||
s_state->fb_size = s_state->width * s_state->height * 2;
|
||||
if (is_hs_mode() && s_state->sensor.id.PID != OV7725_PID) {
|
||||
if(s_state->sensor.id.PID == OV7670_PID) {
|
||||
s_state->sampling_mode = SM_0A0B_0B0C;
|
||||
}else{
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
}
|
||||
s_state->dma_filter = &dma_filter_yuyv_highspeed;
|
||||
} else {
|
||||
s_state->sampling_mode = SM_0A0B_0C0D;
|
||||
s_state->dma_filter = &dma_filter_yuyv;
|
||||
}
|
||||
s_state->in_bytes_per_pixel = 2; // camera sends YU/YV
|
||||
s_state->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
|
||||
} else if (pix_format == PIXFORMAT_RGB888) {
|
||||
s_state->fb_size = s_state->width * s_state->height * 3;
|
||||
if (is_hs_mode()) {
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
if(s_state->sensor.id.PID == OV7670_PID) {
|
||||
s_state->sampling_mode = SM_0A0B_0B0C;
|
||||
}else{
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
}
|
||||
s_state->dma_filter = &dma_filter_rgb888_highspeed;
|
||||
} else {
|
||||
s_state->sampling_mode = SM_0A0B_0C0D;
|
||||
|
@ -1169,7 +1236,7 @@ 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 && s_state->sensor.id.PID != OV5640_PID) {
|
||||
if (s_state->sensor.id.PID != OV2640_PID && s_state->sensor.id.PID != OV3660_PID && s_state->sensor.id.PID != OV5640_PID && s_state->sensor.id.PID != NT99141_PID) {
|
||||
ESP_LOGE(TAG, "JPEG format is only supported for ov2640, ov3660 and ov5640");
|
||||
err = ESP_ERR_NOT_SUPPORTED;
|
||||
goto fail;
|
||||
|
@ -1306,6 +1373,7 @@ fail:
|
|||
esp_err_t esp_camera_init(const camera_config_t* config)
|
||||
{
|
||||
camera_model_t camera_model = CAMERA_NONE;
|
||||
i2s_gpio_init(config);
|
||||
esp_err_t err = camera_probe(config, &camera_model);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Camera probe failed with error 0x%x", err);
|
||||
|
@ -1324,6 +1392,10 @@ esp_err_t esp_camera_init(const camera_config_t* config)
|
|||
ESP_LOGI(TAG, "Detected OV3660 camera");
|
||||
} else if (camera_model == CAMERA_OV5640) {
|
||||
ESP_LOGI(TAG, "Detected OV5640 camera");
|
||||
} else if (camera_model == CAMERA_OV7670) {
|
||||
ESP_LOGI(TAG, "Detected OV7670 camera");
|
||||
} else if (camera_model == CAMERA_NT99141) {
|
||||
ESP_LOGI(TAG, "Detected NT99141 camera");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Camera not supported");
|
||||
err = ESP_ERR_CAMERA_NOT_SUPPORTED;
|
||||
|
@ -1370,9 +1442,12 @@ esp_err_t esp_camera_deinit()
|
|||
}
|
||||
dma_desc_deinit();
|
||||
camera_fb_deinit();
|
||||
|
||||
if(s_state->config.pin_xclk >= 0) {
|
||||
camera_disable_out_clock();
|
||||
}
|
||||
free(s_state);
|
||||
s_state = NULL;
|
||||
camera_disable_out_clock();
|
||||
periph_module_disable(PERIPH_I2S0_MODULE);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -1430,11 +1505,11 @@ sensor_t * esp_camera_sensor_get()
|
|||
|
||||
esp_err_t esp_camera_save_to_nvs(const char *key)
|
||||
{
|
||||
#if ESP_IDF_VERSION_MAJOR > 3
|
||||
nvs_handle_t handle;
|
||||
#else
|
||||
//#if ESP_IDF_VERSION_MAJOR > 3
|
||||
// nvs_handle_t handle;
|
||||
//#else
|
||||
nvs_handle handle;
|
||||
#endif
|
||||
//#endif
|
||||
esp_err_t ret = nvs_open(key,NVS_READWRITE,&handle);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
|
@ -1458,11 +1533,11 @@ esp_err_t esp_camera_save_to_nvs(const char *key)
|
|||
|
||||
esp_err_t esp_camera_load_from_nvs(const char *key)
|
||||
{
|
||||
#if ESP_IDF_VERSION_MAJOR > 3
|
||||
nvs_handle_t handle;
|
||||
#else
|
||||
//#if ESP_IDF_VERSION_MAJOR > 3
|
||||
// nvs_handle_t handle;
|
||||
//#else
|
||||
nvs_handle handle;
|
||||
#endif
|
||||
//#endif
|
||||
uint8_t pf;
|
||||
|
||||
esp_err_t ret = nvs_open(key,NVS_READWRITE,&handle);
|
||||
|
|
|
@ -480,7 +480,9 @@ void setup()
|
|||
ESP.restart();
|
||||
}
|
||||
|
||||
|
||||
sensor_t* s = esp_camera_sensor_get();
|
||||
s->set_vflip(s, true);
|
||||
|
||||
// Configure and connect to WiFi
|
||||
IPAddress ip;
|
||||
|
||||
|
|
Binary file not shown.
|
@ -62,7 +62,8 @@ bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg);
|
|||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out Pointer to be populated with the address of the resulting buffer.
|
||||
* You MUST free the pointer once you are done with it.
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
|
|
1032
esp32-cam-rtos/nt99141.c
Normal file
1032
esp32-cam-rtos/nt99141.c
Normal file
File diff suppressed because it is too large
Load diff
16
esp32-cam-rtos/nt99141.h
Normal file
16
esp32-cam-rtos/nt99141.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* NT99141 driver.
|
||||
*
|
||||
*/
|
||||
#ifndef __NT99141_H__
|
||||
#define __NT99141_H__
|
||||
|
||||
#include "sensor.h"
|
||||
|
||||
int NT99141_init(sensor_t *sensor);
|
||||
|
||||
#endif // __NT99141_H__
|
211
esp32-cam-rtos/nt99141_regs.h
Normal file
211
esp32-cam-rtos/nt99141_regs.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* NT99141 register definitions.
|
||||
*/
|
||||
#ifndef __NT99141_REG_REGS_H__
|
||||
#define __NT99141_REG_REGS_H__
|
||||
|
||||
/* system control registers */
|
||||
#define SYSTEM_CTROL0 0x3021 // Bit[7]: Software reset
|
||||
// Bit[6]: Software power down
|
||||
// Bit[5]: Reserved
|
||||
// Bit[4]: SRB clock SYNC enable
|
||||
// Bit[3]: Isolation suspend select
|
||||
// Bit[2:0]: Not used
|
||||
|
||||
/* output format control registers */
|
||||
#define FORMAT_CTRL 0x501F // Format select
|
||||
// Bit[2:0]:
|
||||
// 000: YUV422
|
||||
// 001: RGB
|
||||
// 010: Dither
|
||||
// 011: RAW after DPC
|
||||
// 101: RAW after CIP
|
||||
|
||||
/* format control registers */
|
||||
#define FORMAT_CTRL00 0x4300
|
||||
|
||||
/* frame control registers */
|
||||
#define FRAME_CTRL01 0x4201 // Control Passed Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode
|
||||
// Bit[7:4]: Not used
|
||||
// Bit[3:0]: Frame ON number
|
||||
#define FRAME_CTRL02 0x4202 // Control Masked Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode
|
||||
// Bit[7:4]: Not used
|
||||
// BIT[3:0]: Frame OFF number
|
||||
|
||||
/* ISP top control registers */
|
||||
#define PRE_ISP_TEST_SETTING_1 0x3025 // Bit[7]: Test enable
|
||||
// 0: Test disable
|
||||
// 1: Color bar enable
|
||||
// Bit[6]: Rolling
|
||||
// Bit[5]: Transparent
|
||||
// Bit[4]: Square black and white
|
||||
// Bit[3:2]: Color bar style
|
||||
// 00: Standard 8 color bar
|
||||
// 01: Gradual change at vertical mode 1
|
||||
// 10: Gradual change at horizontal
|
||||
// 11: Gradual change at vertical mode 2
|
||||
// Bit[1:0]: Test select
|
||||
// 00: Color bar
|
||||
// 01: Random data
|
||||
// 10: Square data
|
||||
// 11: Black image
|
||||
|
||||
//exposure = {0x3500[3:0], 0x3501[7:0], 0x3502[7:0]} / 16 × tROW
|
||||
|
||||
/* AEC/AGC control functions */
|
||||
#define AEC_PK_MANUAL 0x3201 // AEC Manual Mode Control
|
||||
// Bit[7:6]: Reserved
|
||||
// Bit[5]: Gain delay option
|
||||
// Valid when 0x3503[4]=1’b0
|
||||
// 0: Delay one frame latch
|
||||
// 1: One frame latch
|
||||
// Bit[4:2]: Reserved
|
||||
// Bit[1]: AGC manual
|
||||
// 0: Auto enable
|
||||
// 1: Manual enable
|
||||
// Bit[0]: AEC manual
|
||||
// 0: Auto enable
|
||||
// 1: Manual enable
|
||||
|
||||
//gain = {0x350A[1:0], 0x350B[7:0]} / 16
|
||||
|
||||
/* mirror and flip registers */
|
||||
#define TIMING_TC_REG20 0x3022 // Timing Control Register
|
||||
// Bit[2:1]: Vertical flip enable
|
||||
// 00: Normal
|
||||
// 11: Vertical flip
|
||||
// Bit[0]: Vertical binning enable
|
||||
#define TIMING_TC_REG21 0x3022 // Timing Control Register
|
||||
// Bit[5]: Compression Enable
|
||||
// Bit[2:1]: Horizontal mirror enable
|
||||
// 00: Normal
|
||||
// 11: Horizontal mirror
|
||||
// Bit[0]: Horizontal binning enable
|
||||
|
||||
#define CLOCK_POL_CONTROL 0x3024// Bit[5]: PCLK polarity 0: active low
|
||||
// 1: active high
|
||||
// Bit[3]: Gate PCLK under VSYNC
|
||||
// Bit[2]: Gate PCLK under HREF
|
||||
// Bit[1]: HREF polarity
|
||||
// 0: active low
|
||||
// 1: active high
|
||||
// Bit[0] VSYNC polarity
|
||||
// 0: active low
|
||||
// 1: active high
|
||||
#define DRIVE_CAPABILITY 0x306a // Bit[7:6]:
|
||||
// 00: 1x
|
||||
// 01: 2x
|
||||
// 10: 3x
|
||||
// 11: 4x
|
||||
|
||||
|
||||
#define X_ADDR_ST_H 0x3800 //Bit[3:0]: X address start[11:8]
|
||||
#define X_ADDR_ST_L 0x3801 //Bit[7:0]: X address start[7:0]
|
||||
#define Y_ADDR_ST_H 0x3802 //Bit[2:0]: Y address start[10:8]
|
||||
#define Y_ADDR_ST_L 0x3803 //Bit[7:0]: Y address start[7:0]
|
||||
#define X_ADDR_END_H 0x3804 //Bit[3:0]: X address end[11:8]
|
||||
#define X_ADDR_END_L 0x3805 //Bit[7:0]:
|
||||
#define Y_ADDR_END_H 0x3806 //Bit[2:0]: Y address end[10:8]
|
||||
#define Y_ADDR_END_L 0x3807 //Bit[7:0]:
|
||||
// Size after scaling
|
||||
#define X_OUTPUT_SIZE_H 0x3808 //Bit[3:0]: DVP output horizontal width[11:8]
|
||||
#define X_OUTPUT_SIZE_L 0x3809 //Bit[7:0]:
|
||||
#define Y_OUTPUT_SIZE_H 0x380a //Bit[2:0]: DVP output vertical height[10:8]
|
||||
#define Y_OUTPUT_SIZE_L 0x380b //Bit[7:0]:
|
||||
#define X_TOTAL_SIZE_H 0x380c //Bit[3:0]: Total horizontal size[11:8]
|
||||
#define X_TOTAL_SIZE_L 0x380d //Bit[7:0]:
|
||||
#define Y_TOTAL_SIZE_H 0x380e //Bit[7:0]: Total vertical size[15:8]
|
||||
#define Y_TOTAL_SIZE_L 0x380f //Bit[7:0]:
|
||||
#define X_OFFSET_H 0x3810 //Bit[3:0]: ISP horizontal offset[11:8]
|
||||
#define X_OFFSET_L 0x3811 //Bit[7:0]:
|
||||
#define Y_OFFSET_H 0x3812 //Bit[2:0]: ISP vertical offset[10:8]
|
||||
#define Y_OFFSET_L 0x3813 //Bit[7:0]:
|
||||
#define X_INCREMENT 0x3814 //Bit[7:4]: Horizontal odd subsample increment
|
||||
//Bit[3:0]: Horizontal even subsample increment
|
||||
#define Y_INCREMENT 0x3815 //Bit[7:4]: Vertical odd subsample increment
|
||||
//Bit[3:0]: Vertical even subsample increment
|
||||
// Size before scaling
|
||||
//#define X_INPUT_SIZE (X_ADDR_END - X_ADDR_ST + 1 - (2 * X_OFFSET))
|
||||
//#define Y_INPUT_SIZE (Y_ADDR_END - Y_ADDR_ST + 1 - (2 * Y_OFFSET))
|
||||
|
||||
#define ISP_CONTROL_01 0x3021 // Bit[5]: Scale enable
|
||||
// 0: Disable
|
||||
// 1: Enable
|
||||
|
||||
#define SCALE_CTRL_1 0x5601 // Bit[6:4]: HDIV RW
|
||||
// DCW scale times
|
||||
// 000: DCW 1 time
|
||||
// 001: DCW 2 times
|
||||
// 010: DCW 4 times
|
||||
// 100: DCW 8 times
|
||||
// 101: DCW 16 times
|
||||
// Others: DCW 16 times
|
||||
// Bit[2:0]: VDIV RW
|
||||
// DCW scale times
|
||||
// 000: DCW 1 time
|
||||
// 001: DCW 2 times
|
||||
// 010: DCW 4 times
|
||||
// 100: DCW 8 times
|
||||
// 101: DCW 16 times
|
||||
// Others: DCW 16 times
|
||||
|
||||
#define SCALE_CTRL_2 0x5602 // X_SCALE High Bits
|
||||
#define SCALE_CTRL_3 0x5603 // X_SCALE Low Bits
|
||||
#define SCALE_CTRL_4 0x5604 // Y_SCALE High Bits
|
||||
#define SCALE_CTRL_5 0x5605 // Y_SCALE Low Bits
|
||||
#define SCALE_CTRL_6 0x5606 // Bit[3:0]: V Offset
|
||||
|
||||
#define PCLK_RATIO 0x3824 // Bit[4:0]: PCLK ratio manual
|
||||
#define VFIFO_CTRL0C 0x460C // Bit[1]: PCLK manual enable
|
||||
// 0: Auto
|
||||
// 1: Manual by PCLK_RATIO
|
||||
|
||||
#define VFIFO_X_SIZE_H 0x4602
|
||||
#define VFIFO_X_SIZE_L 0x4603
|
||||
#define VFIFO_Y_SIZE_H 0x4604
|
||||
#define VFIFO_Y_SIZE_L 0x4605
|
||||
|
||||
#define SC_PLLS_CTRL0 0x303a // Bit[7]: PLLS bypass
|
||||
#define SC_PLLS_CTRL1 0x303b // Bit[4:0]: PLLS multiplier
|
||||
#define SC_PLLS_CTRL2 0x303c // Bit[6:4]: PLLS charge pump control
|
||||
// Bit[3:0]: PLLS system divider
|
||||
#define SC_PLLS_CTRL3 0x303d // Bit[5:4]: PLLS pre-divider
|
||||
// 00: 1
|
||||
// 01: 1.5
|
||||
// 10: 2
|
||||
// 11: 3
|
||||
// Bit[2]: PLLS root-divider - 1
|
||||
// Bit[1:0]: PLLS seld5
|
||||
// 00: 1
|
||||
// 01: 1
|
||||
// 10: 2
|
||||
// 11: 2.5
|
||||
|
||||
#define COMPRESSION_CTRL00 0x4400 //
|
||||
#define COMPRESSION_CTRL01 0x4401 //
|
||||
#define COMPRESSION_CTRL02 0x4402 //
|
||||
#define COMPRESSION_CTRL03 0x4403 //
|
||||
#define COMPRESSION_CTRL04 0x4404 //
|
||||
#define COMPRESSION_CTRL05 0x4405 //
|
||||
#define COMPRESSION_CTRL06 0x4406 //
|
||||
#define COMPRESSION_CTRL07 0x3401 // Bit[5:0]: QS
|
||||
#define COMPRESSION_ISI_CTRL 0x4408 //
|
||||
#define COMPRESSION_CTRL09 0x4409 //
|
||||
#define COMPRESSION_CTRL0a 0x440a //
|
||||
#define COMPRESSION_CTRL0b 0x440b //
|
||||
#define COMPRESSION_CTRL0c 0x440c //
|
||||
#define COMPRESSION_CTRL0d 0x440d //
|
||||
#define COMPRESSION_CTRL0E 0x440e //
|
||||
|
||||
/**
|
||||
* @brief register value
|
||||
*/
|
||||
#define TEST_COLOR_BAR 0x02 /* Enable Color Bar roling Test */
|
||||
|
||||
#define AEC_PK_MANUAL_AGC_MANUALEN 0x02 /* Enable AGC Manual enable */
|
||||
#define AEC_PK_MANUAL_AEC_MANUALEN 0x01 /* Enable AEC Manual enable */
|
||||
|
||||
#define TIMING_TC_REG20_VFLIP 0x01 /* Vertical flip enable */
|
||||
#define TIMING_TC_REG21_HMIRROR 0x02 /* Horizontal mirror enable */
|
||||
|
||||
#endif // __NT99141_REG_REGS_H__
|
825
esp32-cam-rtos/nt99141_settings.h
Normal file
825
esp32-cam-rtos/nt99141_settings.h
Normal file
|
@ -0,0 +1,825 @@
|
|||
#ifndef _NT99141_SETTINGS_H_
|
||||
#define _NT99141_SETTINGS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_attr.h"
|
||||
#include "nt99141_regs.h"
|
||||
|
||||
static const ratio_settings_t ratio_table[] = {
|
||||
// mw, mh, sx, sy, ex, ey, ox, oy, tx, ty
|
||||
{ 1280, 720, 0, 4, 1283, 723, 0, 4, 1660, 963 },
|
||||
|
||||
};
|
||||
|
||||
#define REG_DLY 0xffff
|
||||
#define REGLIST_TAIL 0x0000
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_default_regs[][2] = {
|
||||
//initial
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x3109, 0x04},
|
||||
{0x3040, 0x04},
|
||||
{0x3041, 0x02},
|
||||
{0x3042, 0xFF},
|
||||
{0x3043, 0x08},
|
||||
{0x3052, 0xE0},
|
||||
{0x305F, 0x33},
|
||||
{0x3100, 0x07},
|
||||
{0x3106, 0x03},
|
||||
{0x3105, 0x01},
|
||||
{0x3108, 0x05},
|
||||
{0x3110, 0x22},
|
||||
{0x3111, 0x57},
|
||||
{0x3112, 0x22},
|
||||
{0x3113, 0x55},
|
||||
{0x3114, 0x05},
|
||||
{0x3135, 0x00},
|
||||
{0x32F0, 0x01},
|
||||
{0x3290, 0x01},
|
||||
{0x3291, 0x80},
|
||||
{0x3296, 0x01},
|
||||
{0x3297, 0x73},
|
||||
{0x3250, 0x80},
|
||||
{0x3251, 0x03},
|
||||
{0x3252, 0xFF},
|
||||
{0x3253, 0x00},
|
||||
{0x3254, 0x03},
|
||||
{0x3255, 0xFF},
|
||||
{0x3256, 0x00},
|
||||
{0x3257, 0x50},
|
||||
{0x3270, 0x00},
|
||||
{0x3271, 0x0C},
|
||||
{0x3272, 0x18},
|
||||
{0x3273, 0x32},
|
||||
{0x3274, 0x44},
|
||||
{0x3275, 0x54},
|
||||
{0x3276, 0x70},
|
||||
{0x3277, 0x88},
|
||||
{0x3278, 0x9D},
|
||||
{0x3279, 0xB0},
|
||||
{0x327A, 0xCF},
|
||||
{0x327B, 0xE2},
|
||||
{0x327C, 0xEF},
|
||||
{0x327D, 0xF7},
|
||||
{0x327E, 0xFF},
|
||||
{0x3302, 0x00},
|
||||
{0x3303, 0x40},
|
||||
{0x3304, 0x00},
|
||||
{0x3305, 0x96},
|
||||
{0x3306, 0x00},
|
||||
{0x3307, 0x29},
|
||||
{0x3308, 0x07},
|
||||
{0x3309, 0xBA},
|
||||
{0x330A, 0x06},
|
||||
{0x330B, 0xF5},
|
||||
{0x330C, 0x01},
|
||||
{0x330D, 0x51},
|
||||
{0x330E, 0x01},
|
||||
{0x330F, 0x30},
|
||||
{0x3310, 0x07},
|
||||
{0x3311, 0x16},
|
||||
{0x3312, 0x07},
|
||||
{0x3313, 0xBA},
|
||||
{0x3326, 0x02},
|
||||
{0x32F6, 0x0F},
|
||||
{0x32F9, 0x42},
|
||||
{0x32FA, 0x24},
|
||||
{0x3325, 0x4A},
|
||||
{0x3330, 0x00},
|
||||
{0x3331, 0x0A},
|
||||
{0x3332, 0xFF},
|
||||
{0x3338, 0x30},
|
||||
{0x3339, 0x84},
|
||||
{0x333A, 0x48},
|
||||
{0x333F, 0x07},
|
||||
{0x3360, 0x10},
|
||||
{0x3361, 0x18},
|
||||
{0x3362, 0x1f},
|
||||
{0x3363, 0x37},
|
||||
{0x3364, 0x80},
|
||||
{0x3365, 0x80},
|
||||
{0x3366, 0x68},
|
||||
{0x3367, 0x60},
|
||||
{0x3368, 0x30},
|
||||
{0x3369, 0x28},
|
||||
{0x336A, 0x20},
|
||||
{0x336B, 0x10},
|
||||
{0x336C, 0x00},
|
||||
{0x336D, 0x20},
|
||||
{0x336E, 0x1C},
|
||||
{0x336F, 0x18},
|
||||
{0x3370, 0x10},
|
||||
{0x3371, 0x38},
|
||||
{0x3372, 0x3C},
|
||||
{0x3373, 0x3F},
|
||||
{0x3374, 0x3F},
|
||||
{0x338A, 0x34},
|
||||
{0x338B, 0x7F},
|
||||
{0x338C, 0x10},
|
||||
{0x338D, 0x23},
|
||||
{0x338E, 0x7F},
|
||||
{0x338F, 0x14},
|
||||
{0x3375, 0x08},
|
||||
{0x3376, 0x0C},
|
||||
{0x3377, 0x18},
|
||||
{0x3378, 0x20},
|
||||
{0x3012, 0x02},
|
||||
{0x3013, 0xD0},
|
||||
{0x3025, 0x02}, //colorbar
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = {
|
||||
{0x32F0, 0x70}, // YUV422
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = {
|
||||
{0x32F0, 0x50}, // RAW
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = {
|
||||
{0x32F1, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = {
|
||||
{0x32F0, 0x00}, // YUV422
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = {
|
||||
{0x32F0, 0x01}, // RGB
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint8_t sensor_saturation_levels[9][1] = {
|
||||
{0x60},//-4
|
||||
{0x68},//-3
|
||||
{0x70},//-2
|
||||
{0x78},//-1
|
||||
{0x80},//0
|
||||
{0x88},//+1
|
||||
{0x90},//+2
|
||||
{0x98},//+3
|
||||
{0xA0},//+4
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = {
|
||||
{0x00, 0x80, 0x80, 0x01},//Normal
|
||||
{0x03, 0x80, 0x80, 0x01},//Negative
|
||||
{0x01, 0x80, 0x80, 0x01},//Grayscale
|
||||
{0x05, 0x2A, 0xF0, 0x01},//Red Tint
|
||||
{0x05, 0x60, 0x20, 0x01},//Green Tint
|
||||
{0x05, 0xF0, 0x80, 0x01},//Blue Tint
|
||||
{0x02, 0x80, 0x80, 0x01},//Sepia
|
||||
|
||||
};
|
||||
|
||||
// AE LEVEL
|
||||
static const DRAM_ATTR uint16_t sensor_ae_level[][2] = {
|
||||
|
||||
// 1. [AE_Target : 0x24]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x29 },
|
||||
{0x32B9, 0x1F },
|
||||
{0x32BC, 0x24 },
|
||||
{0x32BD, 0x27 },
|
||||
{0x32BE, 0x21 },
|
||||
//------------------------------------------------------------------------
|
||||
// 2. [AE_Target : 0x28]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x2D },
|
||||
{0x32B9, 0x23 },
|
||||
{0x32BC, 0x28 },
|
||||
{0x32BD, 0x2B },
|
||||
{0x32BE, 0x25 },
|
||||
//------------------------------------------------------------------------
|
||||
// 3. [AE_Target : 0x2C]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x32 },
|
||||
{0x32B9, 0x26 },
|
||||
{0x32BC, 0x2C },
|
||||
{0x32BD, 0x2F },
|
||||
{0x32BE, 0x29 },
|
||||
//------------------------------------------------------------------------
|
||||
// 4, [AE_Target : 0x30]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x36 },
|
||||
{0x32B9, 0x2A },
|
||||
{0x32BC, 0x30 },
|
||||
{0x32BD, 0x33 },
|
||||
{0x32BE, 0x2D },
|
||||
//------------------------------------------------------------------------
|
||||
// 5. [AE_Target : 0x34]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x3B },
|
||||
{0x32B9, 0x2D },
|
||||
{0x32BC, 0x34 },
|
||||
{0x32BD, 0x38 },
|
||||
{0x32BE, 0x30 },
|
||||
//------------------------------------------------------------------------
|
||||
// 6. [AE_Target : 0x38]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x3F },
|
||||
{0x32B9, 0x31 },
|
||||
{0x32BC, 0x38 },
|
||||
{0x32BD, 0x3C },
|
||||
{0x32BE, 0x34 },
|
||||
//------------------------------------------------------------------------
|
||||
// 7. [AE_Target : 0x3D]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x44 },
|
||||
{0x32B9, 0x34 },
|
||||
{0x32BC, 0x3C },
|
||||
{0x32BD, 0x40 },
|
||||
{0x32BE, 0x38 },
|
||||
//------------------------------------------------------------------------
|
||||
// 8. [AE_Target : 0x40]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x48 },
|
||||
{0x32B9, 0x38 },
|
||||
{0x32BC, 0x40 },
|
||||
{0x32BD, 0x44 },
|
||||
{0x32BE, 0x3C },
|
||||
//------------------------------------------------------------------------
|
||||
// 9. [AE_Target : 0x44]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x4D },
|
||||
{0x32B9, 0x3B },
|
||||
{0x32BC, 0x44 },
|
||||
{0x32BD, 0x49 },
|
||||
{0x32BE, 0x3F },
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_HD[][2] = {
|
||||
//[JPEG_1280x720_8.18_8.18_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x3C},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x5E},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0x04},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x05},
|
||||
{0x3007, 0x03},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x06},
|
||||
{0x300B, 0x7C},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x05},
|
||||
{0x300F, 0x00},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x3F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA[][2] = {
|
||||
//[JPEG_640x480_10.14_10.14_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x4B},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x62},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x02},
|
||||
{0x32E1, 0x80},
|
||||
{0x32E2, 0x01},
|
||||
{0x32E3, 0xE0},
|
||||
{0x32E4, 0x00},
|
||||
{0x32E5, 0x80},
|
||||
{0x32E6, 0x00},
|
||||
{0x32E7, 0x80},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0xA4},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x04},
|
||||
{0x3007, 0x63},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x05},
|
||||
{0x300B, 0x3C},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x03},
|
||||
{0x300F, 0xC0},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_QVGA[][2] = {
|
||||
//[JPEG_320x240_10.14_10.14_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x4B},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x62},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x01},
|
||||
{0x32E1, 0x40},
|
||||
{0x32E2, 0x00},
|
||||
{0x32E3, 0xF0},
|
||||
{0x32E4, 0x02},
|
||||
{0x32E5, 0x02},
|
||||
{0x32E6, 0x02},
|
||||
{0x32E7, 0x03},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0xA4},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x04},
|
||||
{0x3007, 0x63},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x05},
|
||||
{0x300B, 0x3C},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x03},
|
||||
{0x300F, 0xC0},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA_xyskip[][2] = {
|
||||
// [JPEG_640x360_20.00_25.01_Fps_XY_Skip]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60 },
|
||||
{0x320A, 0xB2 },
|
||||
{0x32C0, 0x64 },
|
||||
{0x32C1, 0x64 },
|
||||
{0x32C2, 0x64 },
|
||||
{0x32C3, 0x00 },
|
||||
{0x32C4, 0x20 },
|
||||
{0x32C5, 0x20 },
|
||||
{0x32C6, 0x20 },
|
||||
{0x32C7, 0x00 },
|
||||
{0x32C8, 0x62 },
|
||||
{0x32C9, 0x64 },
|
||||
{0x32CA, 0x84 },
|
||||
{0x32CB, 0x84 },
|
||||
{0x32CC, 0x84 },
|
||||
{0x32CD, 0x84 },
|
||||
{0x32DB, 0x68 },
|
||||
{0x32F0, 0x70 },
|
||||
{0x3400, 0x08 },
|
||||
{0x3400, 0x00 },
|
||||
{0x3401, 0x4E },
|
||||
{0x3404, 0x00 },
|
||||
{0x3405, 0x00 },
|
||||
{0x3410, 0x00 },
|
||||
{0x3200, 0x3E },
|
||||
{0x3201, 0x0F },
|
||||
{0x3028, 0x0F },
|
||||
{0x3029, 0x00 },
|
||||
{0x302A, 0x08 },
|
||||
{0x3022, 0x24 },
|
||||
{0x3023, 0x6C },
|
||||
{0x3002, 0x00 },
|
||||
{0x3003, 0x04 },
|
||||
{0x3004, 0x00 },
|
||||
{0x3005, 0x04 },
|
||||
{0x3006, 0x05 },
|
||||
{0x3007, 0x03 },
|
||||
{0x3008, 0x02 },
|
||||
{0x3009, 0xD3 },
|
||||
{0x300A, 0x03 },
|
||||
{0x300B, 0xFC },
|
||||
{0x300C, 0x01 },
|
||||
{0x300D, 0x88 },
|
||||
{0x300E, 0x02 },
|
||||
{0x300F, 0x80 },
|
||||
{0x3010, 0x01 },
|
||||
{0x3011, 0x68 },
|
||||
{0x32B8, 0x3F },
|
||||
{0x32B9, 0x31 },
|
||||
{0x32BB, 0x87 },
|
||||
{0x32BC, 0x38 },
|
||||
{0x32BD, 0x3C },
|
||||
{0x32BE, 0x34 },
|
||||
{0x3201, 0x3F },
|
||||
{0x3025, 0x00 }, //normal
|
||||
{0x3021, 0x06 },
|
||||
{0x3400, 0x01 },
|
||||
{0x3060, 0x01 },
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA_xskip[][2] = {
|
||||
//[JPEG_640x480_Xskip_13.32_13.32_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x02},
|
||||
{0x32E1, 0x80},
|
||||
{0x32E2, 0x01},
|
||||
{0x32E3, 0xE0},
|
||||
{0x32E4, 0x00},
|
||||
{0x32E5, 0x00},
|
||||
{0x32E6, 0x00},
|
||||
{0x32E7, 0x80},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x2C},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0x04},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x05},
|
||||
{0x3007, 0x03},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_QVGA_xskip[][2] = {
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
//[JPEG_320x240_Xskip_13.32_13.32_Fps]
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x01},
|
||||
{0x32E1, 0x40},
|
||||
{0x32E2, 0x00},
|
||||
{0x32E3, 0xF0},
|
||||
{0x32E4, 0x01},
|
||||
{0x32E5, 0x01},
|
||||
{0x32E6, 0x02},
|
||||
{0x32E7, 0x03},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x2C},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0x04},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x05},
|
||||
{0x3007, 0x03},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA_crop[][2] = {
|
||||
//[JPEG_640x480_Crop_19.77_19.77_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x01},
|
||||
{0x3003, 0x44},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x7C},
|
||||
{0x3006, 0x03},
|
||||
{0x3007, 0xC3},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0x5B},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x01},
|
||||
{0x300D, 0xF0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x01},
|
||||
{0x3011, 0xE0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x3F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_QVGA_crop[][2] = {
|
||||
//[JPEG_320x240_Crop_19.77_19.77_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x01},
|
||||
{0x32E1, 0x40},
|
||||
{0x32E2, 0x00},
|
||||
{0x32E3, 0xF0},
|
||||
{0x32E4, 0x01},
|
||||
{0x32E5, 0x01},
|
||||
{0x32E6, 0x01},
|
||||
{0x32E7, 0x02},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x01},
|
||||
{0x3003, 0x44},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x7C},
|
||||
{0x3006, 0x03},
|
||||
{0x3007, 0xC3},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0x5B},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x01},
|
||||
{0x300D, 0xF0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x01},
|
||||
{0x3011, 0xE0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
439
esp32-cam-rtos/ov7670.c
Normal file
439
esp32-cam-rtos/ov7670.c
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* OV7725 driver.
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sccb.h"
|
||||
#include "ov7670.h"
|
||||
#include "ov7670_regs.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
|
||||
#include "esp32-hal-log.h"
|
||||
#else
|
||||
#include "esp_log.h"
|
||||
static const char* TAG = "ov7760";
|
||||
#endif
|
||||
|
||||
static int ov7670_clkrc = 0x01;
|
||||
|
||||
/*
|
||||
* The default register settings, as obtained from OmniVision. There
|
||||
* is really no making sense of most of these - lots of "reserved" values
|
||||
* and such.
|
||||
*
|
||||
* These settings give VGA YUYV.
|
||||
*/
|
||||
struct regval_list {
|
||||
uint8_t reg_num;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_default_regs[] = {
|
||||
/* Sensor automatically sets output window when resolution changes. */
|
||||
{TSLB, 0x04},
|
||||
|
||||
/* Frame rate 30 fps at 12 Mhz clock */
|
||||
{CLKRC, 0x00},
|
||||
{DBLV, 0x4A},
|
||||
|
||||
{COM10, COM10_VSYNC_NEG | COM10_PCLK_MASK},
|
||||
|
||||
/* Improve white balance */
|
||||
{COM4, 0x40},
|
||||
|
||||
/* Improve color */
|
||||
{RSVD_B0, 0x84},
|
||||
|
||||
/* Enable 50/60 Hz auto detection */
|
||||
{COM11, COM11_EXP|COM11_HZAUTO},
|
||||
|
||||
/* Disable some delays */
|
||||
{HSYST, 0},
|
||||
{HSYEN, 0},
|
||||
|
||||
{MVFP, MVFP_SUN},
|
||||
|
||||
/* More reserved magic, some of which tweaks white balance */
|
||||
{AWBC1, 0x0a},
|
||||
{AWBC2, 0xf0},
|
||||
{AWBC3, 0x34},
|
||||
{AWBC4, 0x58},
|
||||
{AWBC5, 0x28},
|
||||
{AWBC6, 0x3a},
|
||||
|
||||
{AWBCTR3, 0x0a},
|
||||
{AWBCTR2, 0x55},
|
||||
{AWBCTR1, 0x11},
|
||||
{AWBCTR0, 0x9e},
|
||||
|
||||
{COM8, COM8_FAST_AUTO|COM8_STEP_UNLIMIT|COM8_AGC_EN|COM8_AEC_EN|COM8_AWB_EN},
|
||||
|
||||
/* End marker is FF because in ov7670 the address of GAIN 0 and default value too. */
|
||||
{0xFF, 0xFF},
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_fmt_yuv422[] = {
|
||||
{ COM7, 0x0 }, /* Selects YUV mode */
|
||||
{ RGB444, 0 }, /* No RGB444 please */
|
||||
{ COM1, 0 }, /* CCIR601 */
|
||||
{ COM15, COM15_R00FF },
|
||||
{ MVFP, MVFP_SUN },
|
||||
{ COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */
|
||||
{ MTX1, 0x80 }, /* "matrix coefficient 1" */
|
||||
{ MTX2, 0x80 }, /* "matrix coefficient 2" */
|
||||
{ MTX3, 0 }, /* vb */
|
||||
{ MTX4, 0x22 }, /* "matrix coefficient 4" */
|
||||
{ MTX5, 0x5e }, /* "matrix coefficient 5" */
|
||||
{ MTX6, 0x80 }, /* "matrix coefficient 6" */
|
||||
{ COM13, COM13_UVSAT },
|
||||
{ 0xff, 0xff }, /* END MARKER */
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_fmt_rgb565[] = {
|
||||
{ COM7, COM7_FMT_RGB565 }, /* Selects RGB mode */
|
||||
{ RGB444, 0 }, /* No RGB444 please */
|
||||
{ COM1, 0x0 }, /* CCIR601 */
|
||||
{ COM15, COM15_RGB565 |COM15_R00FF },
|
||||
{ MVFP, MVFP_SUN },
|
||||
{ COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */
|
||||
{ MTX1, 0xb3 }, /* "matrix coefficient 1" */
|
||||
{ MTX2, 0xb3 }, /* "matrix coefficient 2" */
|
||||
{ MTX3, 0 }, /* vb */
|
||||
{ MTX4, 0x3d }, /* "matrix coefficient 4" */
|
||||
{ MTX5, 0xa7 }, /* "matrix coefficient 5" */
|
||||
{ MTX6, 0xe4 }, /* "matrix coefficient 6" */
|
||||
{ COM13, COM13_UVSAT },
|
||||
{ 0xff, 0xff }, /* END MARKER */
|
||||
};
|
||||
|
||||
|
||||
static struct regval_list ov7670_vga[] = {
|
||||
{ COM3, 0x00 },
|
||||
{ COM14, 0x00 },
|
||||
{ SCALING_XSC, 0x3A },
|
||||
{ SCALING_YSC, 0x35 },
|
||||
{ SCALING_DCWCTR, 0x11 },
|
||||
{ SCALING_PCLK_DIV, 0xF0 },
|
||||
{ SCALING_PCLK_DELAY, 0x02 },
|
||||
{ 0xff, 0xff },
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_qvga[] = {
|
||||
{ COM3, 0x04 },
|
||||
{ COM14, 0x19 },
|
||||
{ SCALING_XSC, 0x3A },
|
||||
{ SCALING_YSC, 0x35 },
|
||||
{ SCALING_DCWCTR, 0x11 },
|
||||
{ SCALING_PCLK_DIV, 0xF1 },
|
||||
{ SCALING_PCLK_DELAY, 0x02 },
|
||||
{ 0xff, 0xff },
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_qqvga[] = {
|
||||
{ COM3, 0x04 }, //DCW enable
|
||||
{ COM14, 0x1a }, //pixel clock divided by 4, manual scaling enable, DCW and PCLK controlled by register
|
||||
{ SCALING_XSC, 0x3a },
|
||||
{ SCALING_YSC, 0x35 },
|
||||
{ SCALING_DCWCTR, 0x22 }, //downsample by 4
|
||||
{ SCALING_PCLK_DIV, 0xf2 }, //pixel clock divided by 4
|
||||
{ SCALING_PCLK_DELAY, 0x02 },
|
||||
{ 0xff, 0xff },
|
||||
};
|
||||
|
||||
/*
|
||||
* Write a list of register settings; ff/ff stops the process.
|
||||
*/
|
||||
static int ov7670_write_array(sensor_t *sensor, struct regval_list *vals)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while ( (vals->reg_num != 0xff || vals->value != 0xff) && (ret == 0) ) {
|
||||
ret = SCCB_Write(sensor->slv_addr, vals->reg_num, vals->value);
|
||||
|
||||
ESP_LOGD(TAG, "reset reg %02X, W(%02X) R(%02X)", vals->reg_num,
|
||||
vals->value, SCCB_Read(sensor->slv_addr, vals->reg_num) );
|
||||
|
||||
vals++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the frame control registers.
|
||||
*/
|
||||
static int ov7670_frame_control(sensor_t *sensor, int hstart, int hstop, int vstart, int vstop)
|
||||
{
|
||||
struct regval_list frame[7];
|
||||
|
||||
frame[0].reg_num = HSTART;
|
||||
frame[0].value = (hstart >> 3);
|
||||
|
||||
frame[1].reg_num = HSTOP;
|
||||
frame[1].value = (hstop >> 3);
|
||||
|
||||
frame[2].reg_num = HREF;
|
||||
frame[2].value = (((hstop & 0x07) << 3) | (hstart & 0x07));
|
||||
|
||||
frame[3].reg_num = VSTART;
|
||||
frame[3].value = (vstart >> 2);
|
||||
|
||||
frame[4].reg_num = VSTOP;
|
||||
frame[4].value = (vstop >> 2);
|
||||
|
||||
frame[5].reg_num = VREF;
|
||||
frame[5].value = (((vstop & 0x02) << 2) | (vstart & 0x02));
|
||||
|
||||
/* End mark */
|
||||
frame[5].reg_num = 0xFF;
|
||||
frame[5].value = 0xFF;
|
||||
|
||||
return ov7670_write_array(sensor, frame);
|
||||
}
|
||||
|
||||
static int reset(sensor_t *sensor)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// Reset all registers
|
||||
SCCB_Write(sensor->slv_addr, COM7, COM7_RESET);
|
||||
|
||||
// Delay 10 ms
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
ret = ov7670_write_array(sensor, ov7670_default_regs);
|
||||
|
||||
// Delay
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (pixformat) {
|
||||
case PIXFORMAT_RGB565:
|
||||
case PIXFORMAT_RGB888:
|
||||
ret = ov7670_write_array(sensor, ov7670_fmt_rgb565);
|
||||
break;
|
||||
|
||||
case PIXFORMAT_YUV422:
|
||||
case PIXFORMAT_GRAYSCALE:
|
||||
default:
|
||||
ret = ov7670_write_array(sensor, ov7670_fmt_yuv422);
|
||||
break;
|
||||
}
|
||||
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
|
||||
/*
|
||||
* If we're running RGB565, we must rewrite clkrc after setting
|
||||
* the other parameters or the image looks poor. If we're *not*
|
||||
* doing RGB565, we must not rewrite clkrc or the image looks
|
||||
* *really* poor.
|
||||
*
|
||||
* (Update) Now that we retain clkrc state, we should be able
|
||||
* to write it unconditionally, and that will make the frame
|
||||
* rate persistent too.
|
||||
*/
|
||||
if (pixformat == PIXFORMAT_RGB565) {
|
||||
ret = SCCB_Write(sensor->slv_addr, CLKRC, ov7670_clkrc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_framesize(sensor_t *sensor, framesize_t framesize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// store clkrc before changing window settings...
|
||||
ov7670_clkrc = SCCB_Read(sensor->slv_addr, CLKRC);
|
||||
|
||||
switch (framesize){
|
||||
case FRAMESIZE_VGA:
|
||||
if( (ret = ov7670_write_array(sensor, ov7670_vga)) == 0 ) {
|
||||
/* These values from Omnivision */
|
||||
ret = ov7670_frame_control(sensor, 158, 14, 10, 490);
|
||||
}
|
||||
break;
|
||||
case FRAMESIZE_QVGA:
|
||||
if( (ret = ov7670_write_array(sensor, ov7670_qvga)) == 0 ) {
|
||||
/* These values from Omnivision */
|
||||
ret = ov7670_frame_control(sensor, 158, 14, 10, 490);
|
||||
}
|
||||
break;
|
||||
case FRAMESIZE_QQVGA:
|
||||
if( (ret = ov7670_write_array(sensor, ov7670_qqvga)) == 0 ) {
|
||||
/* These values from Omnivision */
|
||||
ret = ov7670_frame_control(sensor, 158, 14, 10, 490);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
|
||||
if (ret == 0) {
|
||||
sensor->status.framesize = framesize;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_colorbar(sensor_t *sensor, int enable)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
// Read register scaling_xsc
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, SCALING_XSC);
|
||||
|
||||
// Pattern to set color bar bit[0]=0 in every case
|
||||
reg = SCALING_XSC_CBAR(reg);
|
||||
|
||||
// Write pattern to SCALING_XSC
|
||||
ret = SCCB_Write(sensor->slv_addr, SCALING_XSC, reg);
|
||||
|
||||
// Read register scaling_ysc
|
||||
reg = SCCB_Read(sensor->slv_addr, SCALING_YSC);
|
||||
|
||||
// Pattern to set color bar bit[0]=0 in every case
|
||||
reg = SCALING_YSC_CBAR(reg, enable);
|
||||
|
||||
// Write pattern to SCALING_YSC
|
||||
ret = ret | SCCB_Write(sensor->slv_addr, SCALING_YSC, reg);
|
||||
|
||||
// return 0 or 0xFF
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_whitebal(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AWB(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
}
|
||||
|
||||
static int set_gain_ctrl(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AGC(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
}
|
||||
|
||||
static int set_exposure_ctrl(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AEC(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
}
|
||||
|
||||
static int set_hmirror(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register MVFP
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP);
|
||||
|
||||
// Set mirror on/off
|
||||
reg = MVFP_SET_MIRROR(reg, enable);
|
||||
|
||||
// Write back register MVFP
|
||||
return SCCB_Write(sensor->slv_addr, MVFP, reg);
|
||||
}
|
||||
|
||||
static int set_vflip(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register MVFP
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP);
|
||||
|
||||
// Set mirror on/off
|
||||
reg = MVFP_SET_FLIP(reg, enable);
|
||||
|
||||
// Write back register MVFP
|
||||
return SCCB_Write(sensor->slv_addr, MVFP, reg);
|
||||
}
|
||||
|
||||
static int init_status(sensor_t *sensor)
|
||||
{
|
||||
sensor->status.awb = 0;
|
||||
sensor->status.aec = 0;
|
||||
sensor->status.agc = 0;
|
||||
sensor->status.hmirror = 0;
|
||||
sensor->status.vflip = 0;
|
||||
sensor->status.colorbar = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_dummy(sensor_t *sensor, int val){ return -1; }
|
||||
static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; }
|
||||
|
||||
int ov7670_init(sensor_t *sensor)
|
||||
{
|
||||
// Set function pointers
|
||||
sensor->reset = reset;
|
||||
sensor->init_status = init_status;
|
||||
sensor->set_pixformat = set_pixformat;
|
||||
sensor->set_framesize = set_framesize;
|
||||
sensor->set_colorbar = set_colorbar;
|
||||
sensor->set_whitebal = set_whitebal;
|
||||
sensor->set_gain_ctrl = set_gain_ctrl;
|
||||
sensor->set_exposure_ctrl = set_exposure_ctrl;
|
||||
sensor->set_hmirror = set_hmirror;
|
||||
sensor->set_vflip = set_vflip;
|
||||
|
||||
//not supported
|
||||
sensor->set_brightness= set_dummy;
|
||||
sensor->set_saturation= set_dummy;
|
||||
sensor->set_quality = set_dummy;
|
||||
sensor->set_gainceiling = set_gainceiling_dummy;
|
||||
sensor->set_aec2 = set_dummy;
|
||||
sensor->set_aec_value = set_dummy;
|
||||
sensor->set_special_effect = set_dummy;
|
||||
sensor->set_wb_mode = set_dummy;
|
||||
sensor->set_ae_level = set_dummy;
|
||||
sensor->set_dcw = set_dummy;
|
||||
sensor->set_bpc = set_dummy;
|
||||
sensor->set_wpc = set_dummy;
|
||||
sensor->set_awb_gain = set_dummy;
|
||||
sensor->set_agc_gain = set_dummy;
|
||||
sensor->set_raw_gma = set_dummy;
|
||||
sensor->set_lenc = set_dummy;
|
||||
sensor->set_sharpness = set_dummy;
|
||||
sensor->set_denoise = set_dummy;
|
||||
|
||||
// Retrieve sensor's signature
|
||||
sensor->id.MIDH = SCCB_Read(sensor->slv_addr, REG_MIDH);
|
||||
sensor->id.MIDL = SCCB_Read(sensor->slv_addr, REG_MIDL);
|
||||
sensor->id.PID = SCCB_Read(sensor->slv_addr, REG_PID);
|
||||
sensor->id.VER = SCCB_Read(sensor->slv_addr, REG_VER);
|
||||
|
||||
ESP_LOGD(TAG, "OV7670 Attached");
|
||||
|
||||
return 0;
|
||||
}
|
14
esp32-cam-rtos/ov7670.h
Normal file
14
esp32-cam-rtos/ov7670.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* OV7670 driver.
|
||||
*
|
||||
*/
|
||||
#ifndef __OV7670_H__
|
||||
#define __OV7670_H__
|
||||
#include "sensor.h"
|
||||
|
||||
int ov7670_init(sensor_t *sensor);
|
||||
#endif // __OV7670_H__
|
354
esp32-cam-rtos/ov7670_regs.h
Normal file
354
esp32-cam-rtos/ov7670_regs.h
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* This file is for the OpenMV project so the OV7670 can be used
|
||||
* author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
|
||||
*
|
||||
* OV7670 register definitions.
|
||||
*/
|
||||
#ifndef __OV7670_REG_REGS_H__
|
||||
#define __OV7670_REG_REGS_H__
|
||||
#define GAIN 0x00 /* AGC – Gain control gain setting */
|
||||
#define BLUE 0x01 /* AWB – Blue channel gain setting */
|
||||
#define RED 0x02 /* AWB – Red channel gain setting */
|
||||
#define VREF 0x03 /* AWB – Green channel gain setting */
|
||||
#define COM1 0x04 /* Common Control 1 */
|
||||
#define BAVG 0x05 /* U/B Average Level */
|
||||
#define GAVG 0x06 /* Y/Gb Average Level */
|
||||
#define AECH 0x07 /* Exposure VAlue - AEC MSB 5 bits */
|
||||
#define RAVG 0x08 /* V/R Average Level */
|
||||
|
||||
#define COM2 0x09 /* Common Control 2 */
|
||||
#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */
|
||||
#define COM2_OUT_DRIVE_1x 0x00 /* Output drive capability 1x */
|
||||
#define COM2_OUT_DRIVE_2x 0x01 /* Output drive capability 2x */
|
||||
#define COM2_OUT_DRIVE_3x 0x02 /* Output drive capability 3x */
|
||||
#define COM2_OUT_DRIVE_4x 0x03 /* Output drive capability 4x */
|
||||
|
||||
#define REG_PID 0x0A /* Product ID Number MSB */
|
||||
#define REG_VER 0x0B /* Product ID Number LSB */
|
||||
|
||||
#define COM3 0x0C /* Common Control 3 */
|
||||
#define COM3_SWAP_OUT 0x40 /* Output data MSB/LSB swap */
|
||||
#define COM3_TRI_CLK 0x20 /* Tri-state output clock */
|
||||
#define COM3_TRI_DATA 0x10 /* Tri-state option output */
|
||||
#define COM3_SCALE_EN 0x08 /* Scale enable */
|
||||
#define COM3_DCW 0x04 /* DCW enable */
|
||||
|
||||
#define COM4 0x0D /* Common Control 4 */
|
||||
#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */
|
||||
#define COM4_PLL_4x 0x40 /* PLL frequency 4x */
|
||||
#define COM4_PLL_6x 0x80 /* PLL frequency 6x */
|
||||
#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */
|
||||
#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */
|
||||
#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */
|
||||
#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */
|
||||
#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */
|
||||
|
||||
#define COM5 0x0E /* Common Control 5 */
|
||||
#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */
|
||||
#define COM5_AFR_SPEED 0x40 /* Auto frame rate control speed selection */
|
||||
#define COM5_AFR_0 0x00 /* No reduction of frame rate */
|
||||
#define COM5_AFR_1_2 0x10 /* Max reduction to 1/2 frame rate */
|
||||
#define COM5_AFR_1_4 0x20 /* Max reduction to 1/4 frame rate */
|
||||
#define COM5_AFR_1_8 0x30 /* Max reduction to 1/8 frame rate */
|
||||
#define COM5_AFR_4x 0x04 /* Add frame when AGC reaches 4x gain */
|
||||
#define COM5_AFR_8x 0x08 /* Add frame when AGC reaches 8x gain */
|
||||
#define COM5_AFR_16x 0x0c /* Add frame when AGC reaches 16x gain */
|
||||
#define COM5_AEC_NO_LIMIT 0x01 /* No limit to AEC increase step */
|
||||
|
||||
#define COM6 0x0F /* Common Control 6 */
|
||||
#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */
|
||||
|
||||
#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */
|
||||
#define CLKRC 0x11 /* Internal Clock */
|
||||
|
||||
#define COM7 0x12 /* Common Control 7 */
|
||||
#define COM7_RESET 0x80 /* SCCB Register Reset */
|
||||
#define COM7_RES_VGA 0x00 /* Resolution VGA */
|
||||
#define COM7_RES_QVGA 0x40 /* Resolution QVGA */
|
||||
#define COM7_BT656 0x20 /* BT.656 protocol ON/OFF */
|
||||
#define COM7_SENSOR_RAW 0x10 /* Sensor RAW */
|
||||
#define COM7_FMT_GBR422 0x00 /* RGB output format GBR422 */
|
||||
#define COM7_FMT_RGB565 0x04 /* RGB output format RGB565 */
|
||||
#define COM7_FMT_RGB555 0x08 /* RGB output format RGB555 */
|
||||
#define COM7_FMT_RGB444 0x0C /* RGB output format RGB444 */
|
||||
#define COM7_FMT_YUV 0x00 /* Output format YUV */
|
||||
#define COM7_FMT_P_BAYER 0x01 /* Output format Processed Bayer RAW */
|
||||
#define COM7_FMT_RGB 0x04 /* Output format RGB */
|
||||
#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */
|
||||
#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x5)<<0))
|
||||
|
||||
#define COM8 0x13 /* Common Control 8 */
|
||||
#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */
|
||||
#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */
|
||||
#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */
|
||||
#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */
|
||||
#define COM8_AEC_BANDF 0x10 /* Enable AEC below banding value */
|
||||
#define COM8_AEC_FINE_EN 0x08 /* Fine AEC ON/OFF control */
|
||||
#define COM8_AGC_EN 0x04 /* AGC Enable */
|
||||
#define COM8_AWB_EN 0x02 /* AWB Enable */
|
||||
#define COM8_AEC_EN 0x01 /* AEC Enable */
|
||||
#define COM8_SET_AGC(r, x) ((r&0xFB)|((x&0x1)<<2))
|
||||
#define COM8_SET_AWB(r, x) ((r&0xFD)|((x&0x1)<<1))
|
||||
#define COM8_SET_AEC(r, x) ((r&0xFE)|((x&0x1)<<0))
|
||||
|
||||
#define COM9 0x14 /* Common Control 9 */
|
||||
#define COM9_HISTO_AVG 0x80 /* Histogram or average based AEC/AGC selection */
|
||||
#define COM9_AGC_GAIN_2x 0x00 /* Automatic Gain Ceiling 2x */
|
||||
#define COM9_AGC_GAIN_4x 0x10 /* Automatic Gain Ceiling 4x */
|
||||
#define COM9_AGC_GAIN_8x 0x20 /* Automatic Gain Ceiling 8x */
|
||||
#define COM9_AGC_GAIN_16x 0x30 /* Automatic Gain Ceiling 16x */
|
||||
#define COM9_AGC_GAIN_32x 0x40 /* Automatic Gain Ceiling 32x */
|
||||
#define COM9_DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */
|
||||
#define COM9_DROP_HREF 0x02 /* Drop HREF output of corrupt frame */
|
||||
#define COM9_SET_AGC(r, x) ((r&0x8F)|((x&0x07)<<4))
|
||||
|
||||
#define COM10 0x15 /* Common Control 10 */
|
||||
#define COM10_NEGATIVE 0x80 /* Output negative data */
|
||||
#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */
|
||||
#define COM10_PCLK_FREE 0x00 /* PCLK output option: free running PCLK */
|
||||
#define COM10_PCLK_MASK 0x20 /* PCLK output option: masked during horizontal blank */
|
||||
#define COM10_PCLK_REV 0x10 /* PCLK reverse */
|
||||
#define COM10_HREF_REV 0x08 /* HREF reverse */
|
||||
#define COM10_VSYNC_FALLING 0x00 /* VSYNC changes on falling edge of PCLK */
|
||||
#define COM10_VSYNC_RISING 0x04 /* VSYNC changes on rising edge of PCLK */
|
||||
#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */
|
||||
#define COM10_OUT_RANGE_8 0x01 /* Output data range: Full range */
|
||||
#define COM10_OUT_RANGE_10 0x00 /* Output data range: Data from [10] to [F0] (8 MSBs) */
|
||||
|
||||
#define RSVD_16 0x16 /* Reserved register */
|
||||
|
||||
#define HSTART 0x17 /* Horizontal Frame (HREF column) Start high 8-bit(low 3 bits are at HREF[2:0]) */
|
||||
#define HSTOP 0x18 /* Horizontal Frame (HREF column) end high 8-bit (low 3 bits are at HREF[5:3]) */
|
||||
#define VSTART 0x19 /* Vertical Frame (row) Start high 8-bit (low 2 bits are at VREF[1:0]) */
|
||||
#define VSTOP 0x1A /* Vertical Frame (row) End high 8-bit (low 2 bits are at VREF[3:2]) */
|
||||
#define PSHFT 0x1B /* Data Format - Pixel Delay Select */
|
||||
#define REG_MIDH 0x1C /* Manufacturer ID Byte – High */
|
||||
#define REG_MIDL 0x1D /* Manufacturer ID Byte – Low */
|
||||
|
||||
#define MVFP 0x1E /* Mirror/Vflip Enable */
|
||||
#define MVFP_MIRROR 0x20 /* Mirror image */
|
||||
#define MVFP_FLIP 0x10 /* Vertical flip */
|
||||
#define MVFP_SUN 0x02 /* Black sun enable */
|
||||
#define MVFP_SET_MIRROR(r,x) ((r&0xDF)|((x&1)<<5)) /* change only bit5 according to x */
|
||||
#define MVFP_SET_FLIP(r,x) ((r&0xEF)|((x&1)<<4)) /* change only bit4 according to x */
|
||||
|
||||
#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period (Reserved?) */
|
||||
#define ADCCTR0 0x20 /* ADC control */
|
||||
#define ADCCTR1 0x21 /* reserved */
|
||||
#define ADCCTR2 0x22 /* reserved */
|
||||
#define ADCCTR3 0x23 /* reserved */
|
||||
#define AEW 0x24 /* AGC/AEC - Stable Operating Region (Upper Limit) */
|
||||
#define AEB 0x25 /* AGC/AEC - Stable Operating Region (Lower Limit) */
|
||||
#define VPT 0x26 /* AGC/AEC Fast Mode Operating Region */
|
||||
#define BBIAS 0x27 /* B channel signal output bias (effective only when COM6[3]=1) */
|
||||
#define GbBIAS 0x28 /* Gb channel signal output bias (effective only when COM6[3]=1) */
|
||||
#define RSVD_29 0x29 /* reserved */
|
||||
#define EXHCH 0x2A /* Dummy Pixel Insert MSB */
|
||||
#define EXHCL 0x2B /* Dummy Pixel Insert LSB */
|
||||
#define RBIAS 0x2C /* R channel signal output bias (effective only when COM6[3]=1) */
|
||||
#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */
|
||||
#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */
|
||||
#define YAVE 0x2F /* Y/G Channel Average Value */
|
||||
#define HSYST 0x30 /* HSync rising edge delay */
|
||||
#define HSYEN 0x31 /* HSync falling edge delay */
|
||||
#define HREF 0x32 /* Image Start and Size Control DIFFERENT CONTROL SEQUENCE */
|
||||
#define CHLF 0x33 /* Array Current control */
|
||||
#define ARBLM 0x34 /* Array reference control */
|
||||
#define RSVD_35 0x35 /* Reserved */
|
||||
#define RSVD_36 0x36 /* Reserved */
|
||||
#define ADC 0x37 /* ADC control */
|
||||
#define ACOM 0x38 /* ADC and analog common mode control */
|
||||
#define OFON 0x39 /* ADC offset control */
|
||||
#define TSLB 0x3A /* Line buffer test option */
|
||||
|
||||
#define COM11 0x3B /* Common control 11 */
|
||||
#define COM11_EXP 0x02
|
||||
#define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */
|
||||
|
||||
#define COM12 0x3C /* Common control 12 */
|
||||
|
||||
#define COM13 0x3D /* Common control 13 */
|
||||
#define COM13_GAMMA 0x80 /* Gamma enable */
|
||||
#define COM13_UVSAT 0x40 /* UV saturation auto adjustment */
|
||||
|
||||
#define COM14 0x3E /* Common Control 14 */
|
||||
|
||||
#define EDGE 0x3F /* edge enhancement adjustment */
|
||||
#define COM15 0x40 /* Common Control 15 DIFFERENT CONTROLS */
|
||||
#define COM15_SET_RGB565(r,x) ((r&0xEF)|((x&1)<<4)) /* set rgb565 mode */
|
||||
#define COM15_RGB565 0x10 /* RGB565 output */
|
||||
#define COM15_R00FF 0xC0 /* Output range: [00] to [FF] */
|
||||
|
||||
#define COM16 0x41 /* Common Control 16 DIFFERENT CONTROLS */
|
||||
#define COM16_AWBGAIN 0x08 /* AWB gain enable */
|
||||
#define COM17 0x42 /* Common Control 17 */
|
||||
|
||||
#define AWBC1 0x43 /* Reserved */
|
||||
#define AWBC2 0x44 /* Reserved */
|
||||
#define AWBC3 0x45 /* Reserved */
|
||||
#define AWBC4 0x46 /* Reserved */
|
||||
#define AWBC5 0x47 /* Reserved */
|
||||
#define AWBC6 0x48 /* Reserved */
|
||||
|
||||
#define RSVD_49 0x49 /* Reserved */
|
||||
#define RSVD_4A 0x4A /* Reserved */
|
||||
|
||||
#define REG4B 0x4B /* Register 4B */
|
||||
#define DNSTH 0x4C /* Denoise strength */
|
||||
|
||||
#define RSVD_4D 0x4D /* Reserved */
|
||||
#define RSVD_4E 0x4E /* Reserved */
|
||||
|
||||
#define MTX1 0x4F /* Matrix coefficient 1 */
|
||||
#define MTX2 0x50 /* Matrix coefficient 2 */
|
||||
#define MTX3 0x51 /* Matrix coefficient 3 */
|
||||
#define MTX4 0x52 /* Matrix coefficient 4 */
|
||||
#define MTX5 0x53 /* Matrix coefficient 5 */
|
||||
#define MTX6 0x54 /* Matrix coefficient 6 */
|
||||
#define BRIGHTNESS 0x55 /* Brightness control */
|
||||
#define CONTRAST 0x56 /* Contrast control */
|
||||
#define CONTRASCENTER 0x57 /* Contrast center */
|
||||
#define MTXS 0x58 /* Matrix coefficient sign for coefficient 5 to 0*/
|
||||
|
||||
#define RSVD_59 0x59 /* Reserved */
|
||||
#define RSVD_5A 0x5A /* Reserved */
|
||||
#define RSVD_5B 0x5B /* Reserved */
|
||||
#define RSVD_5C 0x5C /* Reserved */
|
||||
#define RSVD_5D 0x5D /* Reserved */
|
||||
#define RSVD_5E 0x5E /* Reserved */
|
||||
#define RSVD_5F 0x5F /* Reserved */
|
||||
#define RSVD_60 0x60 /* Reserved */
|
||||
#define RSVD_61 0x61 /* Reserved */
|
||||
|
||||
#define LCC1 0x62 /* Lens correction option 1 */
|
||||
|
||||
#define LCC2 0x63 /* Lens correction option 2 */
|
||||
#define LCC3 0x64 /* Lens correction option 3 */
|
||||
#define LCC4 0x65 /* Lens correction option 4 */
|
||||
#define LCC5 0x66 /* Lens correction option 5 */
|
||||
|
||||
#define MANU 0x67 /* Manual U Value */
|
||||
#define MANV 0x68 /* Manual V Value */
|
||||
#define GFIX 0x69 /* Fix gain control */
|
||||
#define GGAIN 0x6A /* G channel AWB gain */
|
||||
|
||||
#define DBLV 0x6B /* PLL and clock ? */
|
||||
|
||||
#define AWBCTR3 0x6C /* AWB Control 3 */
|
||||
#define AWBCTR2 0x6D /* AWB Control 2 */
|
||||
#define AWBCTR1 0x6E /* AWB Control 1 */
|
||||
#define AWBCTR0 0x6F /* AWB Control 0 */
|
||||
#define SCALING_XSC 0x70 /* test pattern and horizontal scaling factor */
|
||||
#define SCALING_XSC_CBAR(r) (r&0x7F) /* make sure bit7 is 0 for color bar */
|
||||
#define SCALING_YSC 0x71 /* test pattern and vertical scaling factor */
|
||||
#define SCALING_YSC_CBAR(r,x) ((r&0x7F)|((x&1)<<7)) /* change bit7 for color bar on/off */
|
||||
#define SCALING_DCWCTR 0x72 /* DCW control */
|
||||
#define SCALING_PCLK_DIV 0x73 /* */
|
||||
#define REG74 0x74 /* */
|
||||
#define REG75 0x75 /* */
|
||||
#define REG76 0x76 /* */
|
||||
#define REG77 0x77 /* */
|
||||
|
||||
#define RSVD_78 0x78 /* Reserved */
|
||||
#define RSVD_79 0x79 /* Reserved */
|
||||
|
||||
#define SLOP 0x7A /* Gamma curve highest segment slope */
|
||||
#define GAM1 0x7B /* Gamma Curve 1st Segment Input End Point 0x04 Output Value */
|
||||
#define GAM2 0x7C /* Gamma Curve 2nd Segment Input End Point 0x08 Output Value */
|
||||
#define GAM3 0x7D /* Gamma Curve 3rd Segment Input End Point 0x10 Output Value */
|
||||
#define GAM4 0x7E /* Gamma Curve 4th Segment Input End Point 0x20 Output Value */
|
||||
#define GAM5 0x7F /* Gamma Curve 5th Segment Input End Point 0x28 Output Value */
|
||||
#define GAM6 0x80 /* Gamma Curve 6rd Segment Input End Point 0x30 Output Value */
|
||||
#define GAM7 0x81 /* Gamma Curve 7th Segment Input End Point 0x38 Output Value */
|
||||
#define GAM8 0x82 /* Gamma Curve 8th Segment Input End Point 0x40 Output Value */
|
||||
#define GAM9 0x83 /* Gamma Curve 9th Segment Input End Point 0x48 Output Value */
|
||||
#define GAM10 0x84 /* Gamma Curve 10th Segment Input End Point 0x50 Output Value */
|
||||
#define GAM11 0x85 /* Gamma Curve 11th Segment Input End Point 0x60 Output Value */
|
||||
#define GAM12 0x86 /* Gamma Curve 12th Segment Input End Point 0x70 Output Value */
|
||||
#define GAM13 0x87 /* Gamma Curve 13th Segment Input End Point 0x90 Output Value */
|
||||
#define GAM14 0x88 /* Gamma Curve 14th Segment Input End Point 0xB0 Output Value */
|
||||
#define GAM15 0x89 /* Gamma Curve 15th Segment Input End Point 0xD0 Output Value */
|
||||
|
||||
#define RSVD_8A 0x8A /* Reserved */
|
||||
#define RSVD_8B 0x8B /* Reserved */
|
||||
|
||||
#define RGB444 0x8C /* */
|
||||
|
||||
#define RSVD_8D 0x8D /* Reserved */
|
||||
#define RSVD_8E 0x8E /* Reserved */
|
||||
#define RSVD_8F 0x8F /* Reserved */
|
||||
#define RSVD_90 0x90 /* Reserved */
|
||||
#define RSVD_91 0x91 /* Reserved */
|
||||
|
||||
#define DM_LNL 0x92 /* Dummy line low 8 bit */
|
||||
#define DM_LNH 0x93 /* Dummy line high 8 bit */
|
||||
#define LCC6 0x94 /* Lens correction option 6 */
|
||||
#define LCC7 0x95 /* Lens correction option 7 */
|
||||
|
||||
#define RSVD_96 0x96 /* Reserved */
|
||||
#define RSVD_97 0x97 /* Reserved */
|
||||
#define RSVD_98 0x98 /* Reserved */
|
||||
#define RSVD_99 0x99 /* Reserved */
|
||||
#define RSVD_9A 0x9A /* Reserved */
|
||||
#define RSVD_9B 0x9B /* Reserved */
|
||||
#define RSVD_9C 0x9C /* Reserved */
|
||||
|
||||
#define BD50ST 0x9D /* 50 Hz banding filter value */
|
||||
#define BD60ST 0x9E /* 60 Hz banding filter value */
|
||||
#define HAECC1 0x9F /* Histogram-based AEC/AGC control 1 */
|
||||
#define HAECC2 0xA0 /* Histogram-based AEC/AGC control 2 */
|
||||
|
||||
#define RSVD_A1 0xA1 /* Reserved */
|
||||
|
||||
#define SCALING_PCLK_DELAY 0xA2 /* Pixel clock delay */
|
||||
|
||||
#define RSVD_A3 0xA3 /* Reserved */
|
||||
|
||||
#define NT_CNTRL 0xA4 /* */
|
||||
#define BD50MAX 0xA5 /* 50 Hz banding step limit */
|
||||
#define HAECC3 0xA6 /* Histogram-based AEC/AGC control 3 */
|
||||
#define HAECC4 0xA7 /* Histogram-based AEC/AGC control 4 */
|
||||
#define HAECC5 0xA8 /* Histogram-based AEC/AGC control 5 */
|
||||
#define HAECC6 0xA9 /* Histogram-based AEC/AGC control 6 */
|
||||
|
||||
#define HAECC7 0xAA /* Histogram-based AEC/AGC control 7 */
|
||||
#define HAECC_EN 0x80 /* Histogram-based AEC algorithm enable */
|
||||
|
||||
#define BD60MAX 0xAB /* 60 Hz banding step limit */
|
||||
|
||||
#define STR_OPT 0xAC /* Register AC */
|
||||
#define STR_R 0xAD /* R gain for led output frame */
|
||||
#define STR_G 0xAE /* G gain for led output frame */
|
||||
#define STR_B 0xAF /* B gain for led output frame */
|
||||
#define RSVD_B0 0xB0 /* Reserved */
|
||||
#define ABLC1 0xB1 /* */
|
||||
#define RSVD_B2 0xB2 /* Reserved */
|
||||
#define THL_ST 0xB3 /* ABLC target */
|
||||
#define THL_DLT 0xB5 /* ABLC stable range */
|
||||
|
||||
#define RSVD_B6 0xB6 /* Reserved */
|
||||
#define RSVD_B7 0xB7 /* Reserved */
|
||||
#define RSVD_B8 0xB8 /* Reserved */
|
||||
#define RSVD_B9 0xB9 /* Reserved */
|
||||
#define RSVD_BA 0xBA /* Reserved */
|
||||
#define RSVD_BB 0xBB /* Reserved */
|
||||
#define RSVD_BC 0xBC /* Reserved */
|
||||
#define RSVD_BD 0xBD /* Reserved */
|
||||
|
||||
#define AD_CHB 0xBE /* blue channel black level compensation */
|
||||
#define AD_CHR 0xBF /* Red channel black level compensation */
|
||||
#define AD_CHGb 0xC0 /* Gb channel black level compensation */
|
||||
#define AD_CHGr 0xC1 /* Gr channel black level compensation */
|
||||
|
||||
#define RSVD_C2 0xC2 /* Reserved */
|
||||
#define RSVD_C3 0xC3 /* Reserved */
|
||||
#define RSVD_C4 0xC4 /* Reserved */
|
||||
#define RSVD_C5 0xC5 /* Reserved */
|
||||
#define RSVD_C6 0xC6 /* Reserved */
|
||||
#define RSVD_C7 0xC7 /* Reserved */
|
||||
#define RSVD_C8 0xC8 /* Reserved */
|
||||
|
||||
#define SATCTR 0xC9 /* Saturation control */
|
||||
#define SET_REG(reg, x) (##reg_DEFAULT|x)
|
||||
|
||||
#endif //__OV7670_REG_REGS_H__
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include "sccb.h"
|
||||
|
@ -19,11 +20,8 @@
|
|||
static const char* TAG = "sccb";
|
||||
#endif
|
||||
|
||||
//#undef CONFIG_SCCB_HARDWARE_I2C
|
||||
|
||||
#define LITTLETOBIG(x) ((x<<8)|(x>>8))
|
||||
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
#include "driver/i2c.h"
|
||||
|
||||
#define SCCB_FREQ 100000 /*!< I2C master frequency*/
|
||||
|
@ -39,16 +37,13 @@ const int SCCB_I2C_PORT = 1;
|
|||
const int SCCB_I2C_PORT = 0;
|
||||
#endif
|
||||
static uint8_t ESP_SLAVE_ADDR = 0x3c;
|
||||
#else
|
||||
#include "twi.h"
|
||||
#endif
|
||||
|
||||
int SCCB_Init(int pin_sda, int pin_scl)
|
||||
{
|
||||
ESP_LOGI(TAG, "pin_sda %d pin_scl %d\n", pin_sda, pin_scl);
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
//log_i("SCCB_Init start");
|
||||
i2c_config_t conf;
|
||||
memset(&conf, 0, sizeof(i2c_config_t));
|
||||
conf.mode = I2C_MODE_MASTER;
|
||||
conf.sda_io_num = pin_sda;
|
||||
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
|
@ -58,15 +53,11 @@ int SCCB_Init(int pin_sda, int pin_scl)
|
|||
|
||||
i2c_param_config(SCCB_I2C_PORT, &conf);
|
||||
i2c_driver_install(SCCB_I2C_PORT, conf.mode, 0, 0, 0);
|
||||
#else
|
||||
twi_init(pin_sda, pin_scl);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t SCCB_Probe()
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
uint8_t slave_addr = 0x0;
|
||||
while(slave_addr < 0x7f) {
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
@ -82,28 +73,10 @@ uint8_t SCCB_Probe()
|
|||
slave_addr++;
|
||||
}
|
||||
return ESP_SLAVE_ADDR;
|
||||
#else
|
||||
uint8_t reg = 0x00;
|
||||
uint8_t slv_addr = 0x00;
|
||||
|
||||
ESP_LOGI(TAG, "SCCB_Probe start");
|
||||
for (uint8_t i = 0; i < 127; i++) {
|
||||
if (twi_writeTo(i, ®, 1, true) == 0) {
|
||||
slv_addr = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i!=126) {
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS); // Necessary for OV7725 camera (not for OV2640).
|
||||
}
|
||||
}
|
||||
return slv_addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
uint8_t data=0;
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
@ -125,28 +98,10 @@ uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
|
|||
ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
|
||||
}
|
||||
return data;
|
||||
#else
|
||||
uint8_t data=0;
|
||||
|
||||
int rc = twi_writeTo(slv_addr, ®, 1, true);
|
||||
if (rc != 0) {
|
||||
data = 0xff;
|
||||
} else {
|
||||
rc = twi_readFrom(slv_addr, &data, 1, true);
|
||||
if (rc != 0) {
|
||||
data=0xFF;
|
||||
}
|
||||
}
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "SCCB_Read [%02x] failed rc=%d\n", reg, rc);
|
||||
}
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
|
@ -160,23 +115,10 @@ uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
|
|||
ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
|
||||
}
|
||||
return ret == ESP_OK ? 0 : -1;
|
||||
#else
|
||||
uint8_t ret=0;
|
||||
uint8_t buf[] = {reg, data};
|
||||
|
||||
if(twi_writeTo(slv_addr, buf, 2, true) != 0) {
|
||||
ret=0xFF;
|
||||
}
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "SCCB_Write [%02x]=%02x failed\n", reg, data);
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
uint8_t data=0;
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
|
@ -201,32 +143,11 @@ uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
|
|||
ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data);
|
||||
}
|
||||
return data;
|
||||
#else
|
||||
uint8_t data=0;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
uint8_t *reg_u8 = (uint8_t *)®_htons;
|
||||
uint8_t buf[] = {reg_u8[0], reg_u8[1]};
|
||||
|
||||
int rc = twi_writeTo(slv_addr, buf, 2, true);
|
||||
if (rc != 0) {
|
||||
data = 0xff;
|
||||
} else {
|
||||
rc = twi_readFrom(slv_addr, &data, 1, true);
|
||||
if (rc != 0) {
|
||||
data=0xFF;
|
||||
}
|
||||
}
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "R [%04x] fail rc=%d\n", reg, rc);
|
||||
}
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data)
|
||||
{
|
||||
static uint16_t i = 0;
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
uint8_t *reg_u8 = (uint8_t *)®_htons;
|
||||
|
@ -243,18 +164,4 @@ uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data)
|
|||
ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++);
|
||||
}
|
||||
return ret == ESP_OK ? 0 : -1;
|
||||
#else
|
||||
uint8_t ret=0;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
uint8_t *reg_u8 = (uint8_t *)®_htons;
|
||||
uint8_t buf[] = {reg_u8[0], reg_u8[1], data};
|
||||
|
||||
if(twi_writeTo(slv_addr, buf, 3, true) != 0) {
|
||||
ret = 0xFF;
|
||||
}
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++);
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -11,11 +11,13 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define NT99141_PID (0x14)
|
||||
#define OV9650_PID (0x96)
|
||||
#define OV7725_PID (0x77)
|
||||
#define OV2640_PID (0x26)
|
||||
#define OV3660_PID (0x36)
|
||||
#define OV5640_PID (0x56)
|
||||
#define OV7670_PID (0x76)
|
||||
|
||||
typedef enum {
|
||||
PIXFORMAT_RGB565, // 2BPP/RGB565
|
||||
|
|
|
@ -20,6 +20,17 @@
|
|||
#include "sdkconfig.h"
|
||||
#include "esp_jpg_decode.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+
|
||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||
#include "esp32/spiram.h"
|
||||
#else
|
||||
#error Target CONFIG_IDF_TARGET is not supported
|
||||
#endif
|
||||
#else // ESP32 Before IDF 4.0
|
||||
#include "esp_spiram.h"
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
|
||||
#include "esp32-hal-log.h"
|
||||
#define TAG ""
|
||||
|
|
|
@ -35,4 +35,4 @@ uint8_t twi_readFrom(unsigned char address, unsigned char * buf, unsigned int le
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -48,6 +48,12 @@
|
|||
#if CONFIG_OV5640_SUPPORT
|
||||
#include "ov5640.h"
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
#include "nt99141.h"
|
||||
#endif
|
||||
#if CONFIG_OV7670_SUPPORT
|
||||
#include "ov7670.h"
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
CAMERA_NONE = 0,
|
||||
|
@ -56,6 +62,8 @@ typedef enum {
|
|||
CAMERA_OV2640 = 2640,
|
||||
CAMERA_OV3660 = 3660,
|
||||
CAMERA_OV5640 = 5640,
|
||||
CAMERA_OV7670 = 7670,
|
||||
CAMERA_NT99141 = 9141,
|
||||
} camera_model_t;
|
||||
|
||||
#define REG_PID 0x0A
|
||||
|
@ -369,12 +377,10 @@ static inline void IRAM_ATTR i2s_conf_reset()
|
|||
}
|
||||
}
|
||||
|
||||
static void i2s_init()
|
||||
static void i2s_gpio_init(const camera_config_t* config)
|
||||
{
|
||||
camera_config_t* config = &s_state->config;
|
||||
|
||||
// Configure input GPIOs
|
||||
gpio_num_t pins[] = {
|
||||
const gpio_num_t pins[] = {
|
||||
config->pin_d7,
|
||||
config->pin_d6,
|
||||
config->pin_d5,
|
||||
|
@ -391,15 +397,21 @@ static void i2s_init()
|
|||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.pin_bit_mask = 0LL
|
||||
};
|
||||
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);
|
||||
conf.pin_bit_mask |= 1LL << pins[i];
|
||||
}
|
||||
gpio_config(&conf);
|
||||
}
|
||||
|
||||
static void i2s_init()
|
||||
{
|
||||
camera_config_t* config = &s_state->config;
|
||||
|
||||
// Route input GPIOs to I2S peripheral using GPIO matrix
|
||||
gpio_matrix_in(config->pin_d0, I2S0I_DATA_IN0_IDX, false);
|
||||
|
@ -738,7 +750,7 @@ 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("bh 0x%08x\n", sig);
|
||||
ESP_LOGD(TAG,"unexpected JPEG signature 0x%08x\n", sig);
|
||||
s_state->fb->bad = 1;
|
||||
return;
|
||||
}
|
||||
|
@ -955,11 +967,15 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Enabling XCLK output");
|
||||
camera_enable_out_clock(config);
|
||||
if(config->pin_xclk >= 0) {
|
||||
ESP_LOGD(TAG, "Enabling XCLK output");
|
||||
camera_enable_out_clock(config);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Initializing SSCB");
|
||||
SCCB_Init(config->pin_sscb_sda, config->pin_sscb_scl);
|
||||
if (config->pin_sscb_sda != -1) {
|
||||
ESP_LOGD(TAG, "Initializing SSCB");
|
||||
SCCB_Init(config->pin_sscb_sda, config->pin_sscb_scl);
|
||||
}
|
||||
|
||||
if(config->pin_pwdn >= 0) {
|
||||
ESP_LOGD(TAG, "Resetting camera by power down line");
|
||||
|
@ -1011,16 +1027,33 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
slv_addr = SCCB_Probe();
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
if (slv_addr == 0x2a)
|
||||
{
|
||||
ESP_LOGD(TAG, "Resetting NT99141");
|
||||
SCCB_Write16(0x2a, 0x3008, 0x01);//bank sensor
|
||||
}
|
||||
#endif
|
||||
|
||||
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 (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT || CONFIG_NT99141_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);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
ESP_LOGD(TAG, "Camera PID=0x%02x VER=0x%02x", id->PID, id->VER);
|
||||
} else if(s_state->sensor.slv_addr == 0x2a){
|
||||
id->PID = SCCB_Read16(s_state->sensor.slv_addr, 0x3000);
|
||||
id->VER = SCCB_Read16(s_state->sensor.slv_addr, 0x3001);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
ESP_LOGD(TAG, "Camera PID=0x%02x VER=0x%02x", id->PID, id->VER);
|
||||
if(config->xclk_freq_hz > 10000000)
|
||||
{
|
||||
ESP_LOGE(TAG, "NT99141: only XCLK under 10MHz is supported, and XCLK is now set to 10M");
|
||||
s_state->sensor.xclk_freq_hz = 10000000;
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
id->PID = SCCB_Read(s_state->sensor.slv_addr, REG_PID);
|
||||
|
@ -1031,7 +1064,7 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
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 || CONFIG_OV5640_SUPPORT)
|
||||
#if (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT || CONFIG_NT99141_SUPPORT)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1060,6 +1093,18 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
|
|||
*out_camera_model = CAMERA_OV5640;
|
||||
ov5640_init(&s_state->sensor);
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_OV7670_SUPPORT
|
||||
case OV7670_PID:
|
||||
*out_camera_model = CAMERA_OV7670;
|
||||
ov7670_init(&s_state->sensor);
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
case NT99141_PID:
|
||||
*out_camera_model = CAMERA_NT99141;
|
||||
NT99141_init(&s_state->sensor);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
id->PID = 0;
|
||||
|
@ -1116,6 +1161,20 @@ esp_err_t camera_init(const camera_config_t* config)
|
|||
frame_size = FRAMESIZE_QSXGA;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_OV7670_SUPPORT
|
||||
case OV7670_PID:
|
||||
if (frame_size > FRAMESIZE_VGA) {
|
||||
frame_size = FRAMESIZE_VGA;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_NT99141_SUPPORT
|
||||
case NT99141_PID:
|
||||
if (frame_size > FRAMESIZE_HD) {
|
||||
frame_size = FRAMESIZE_HD;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return ESP_ERR_CAMERA_NOT_SUPPORTED;
|
||||
|
@ -1126,7 +1185,7 @@ esp_err_t camera_init(const camera_config_t* config)
|
|||
|
||||
if (pix_format == PIXFORMAT_GRAYSCALE) {
|
||||
s_state->fb_size = s_state->width * s_state->height;
|
||||
if (s_state->sensor.id.PID == OV3660_PID || s_state->sensor.id.PID == OV5640_PID) {
|
||||
if (s_state->sensor.id.PID == OV3660_PID || s_state->sensor.id.PID == OV5640_PID || s_state->sensor.id.PID == NT99141_PID) {
|
||||
if (is_hs_mode()) {
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
s_state->dma_filter = &dma_filter_yuyv_highspeed;
|
||||
|
@ -1147,20 +1206,28 @@ esp_err_t camera_init(const camera_config_t* config)
|
|||
}
|
||||
s_state->fb_bytes_per_pixel = 1; // frame buffer stores Y8
|
||||
} else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) {
|
||||
s_state->fb_size = s_state->width * s_state->height * 2;
|
||||
if (is_hs_mode() && s_state->sensor.id.PID != OV7725_PID) {
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
s_state->dma_filter = &dma_filter_yuyv_highspeed;
|
||||
} else {
|
||||
s_state->sampling_mode = SM_0A0B_0C0D;
|
||||
s_state->dma_filter = &dma_filter_yuyv;
|
||||
}
|
||||
s_state->in_bytes_per_pixel = 2; // camera sends YU/YV
|
||||
s_state->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
|
||||
s_state->fb_size = s_state->width * s_state->height * 2;
|
||||
if (is_hs_mode() && s_state->sensor.id.PID != OV7725_PID) {
|
||||
if(s_state->sensor.id.PID == OV7670_PID) {
|
||||
s_state->sampling_mode = SM_0A0B_0B0C;
|
||||
}else{
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
}
|
||||
s_state->dma_filter = &dma_filter_yuyv_highspeed;
|
||||
} else {
|
||||
s_state->sampling_mode = SM_0A0B_0C0D;
|
||||
s_state->dma_filter = &dma_filter_yuyv;
|
||||
}
|
||||
s_state->in_bytes_per_pixel = 2; // camera sends YU/YV
|
||||
s_state->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
|
||||
} else if (pix_format == PIXFORMAT_RGB888) {
|
||||
s_state->fb_size = s_state->width * s_state->height * 3;
|
||||
if (is_hs_mode()) {
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
if(s_state->sensor.id.PID == OV7670_PID) {
|
||||
s_state->sampling_mode = SM_0A0B_0B0C;
|
||||
}else{
|
||||
s_state->sampling_mode = SM_0A00_0B00;
|
||||
}
|
||||
s_state->dma_filter = &dma_filter_rgb888_highspeed;
|
||||
} else {
|
||||
s_state->sampling_mode = SM_0A0B_0C0D;
|
||||
|
@ -1169,7 +1236,7 @@ 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 && s_state->sensor.id.PID != OV5640_PID) {
|
||||
if (s_state->sensor.id.PID != OV2640_PID && s_state->sensor.id.PID != OV3660_PID && s_state->sensor.id.PID != OV5640_PID && s_state->sensor.id.PID != NT99141_PID) {
|
||||
ESP_LOGE(TAG, "JPEG format is only supported for ov2640, ov3660 and ov5640");
|
||||
err = ESP_ERR_NOT_SUPPORTED;
|
||||
goto fail;
|
||||
|
@ -1256,8 +1323,13 @@ esp_err_t camera_init(const camera_config_t* config)
|
|||
vsync_intr_disable();
|
||||
err = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "gpio_install_isr_service failed (%x)", err);
|
||||
goto fail;
|
||||
if (err != ESP_ERR_INVALID_STATE) {
|
||||
ESP_LOGE(TAG, "gpio_install_isr_service failed (%x)", err);
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG, "gpio_install_isr_service already installed");
|
||||
}
|
||||
}
|
||||
err = gpio_isr_handler_add(s_state->config.pin_vsync, &vsync_isr, NULL);
|
||||
if (err != ESP_OK) {
|
||||
|
@ -1301,26 +1373,31 @@ fail:
|
|||
esp_err_t esp_camera_init(const camera_config_t* config)
|
||||
{
|
||||
camera_model_t camera_model = CAMERA_NONE;
|
||||
i2s_gpio_init(config);
|
||||
esp_err_t err = camera_probe(config, &camera_model);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Camera probe failed with error 0x%x", err);
|
||||
goto fail;
|
||||
}
|
||||
if (camera_model == CAMERA_OV7725) {
|
||||
ESP_LOGD(TAG, "Detected OV7725 camera");
|
||||
ESP_LOGI(TAG, "Detected OV7725 camera");
|
||||
if(config->pixel_format == PIXFORMAT_JPEG) {
|
||||
ESP_LOGE(TAG, "Camera does not support JPEG");
|
||||
err = ESP_ERR_CAMERA_NOT_SUPPORTED;
|
||||
goto fail;
|
||||
}
|
||||
} else if (camera_model == CAMERA_OV2640) {
|
||||
ESP_LOGD(TAG, "Detected OV2640 camera");
|
||||
ESP_LOGI(TAG, "Detected OV2640 camera");
|
||||
} else if (camera_model == CAMERA_OV3660) {
|
||||
ESP_LOGD(TAG, "Detected OV3660 camera");
|
||||
ESP_LOGI(TAG, "Detected OV3660 camera");
|
||||
} else if (camera_model == CAMERA_OV5640) {
|
||||
ESP_LOGD(TAG, "Detected OV5640 camera");
|
||||
ESP_LOGI(TAG, "Detected OV5640 camera");
|
||||
} else if (camera_model == CAMERA_OV7670) {
|
||||
ESP_LOGI(TAG, "Detected OV7670 camera");
|
||||
} else if (camera_model == CAMERA_NT99141) {
|
||||
ESP_LOGI(TAG, "Detected NT99141 camera");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Camera not supported");
|
||||
ESP_LOGI(TAG, "Camera not supported");
|
||||
err = ESP_ERR_CAMERA_NOT_SUPPORTED;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1365,9 +1442,12 @@ esp_err_t esp_camera_deinit()
|
|||
}
|
||||
dma_desc_deinit();
|
||||
camera_fb_deinit();
|
||||
|
||||
if(s_state->config.pin_xclk >= 0) {
|
||||
camera_disable_out_clock();
|
||||
}
|
||||
free(s_state);
|
||||
s_state = NULL;
|
||||
camera_disable_out_clock();
|
||||
periph_module_disable(PERIPH_I2S0_MODULE);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -1425,11 +1505,11 @@ sensor_t * esp_camera_sensor_get()
|
|||
|
||||
esp_err_t esp_camera_save_to_nvs(const char *key)
|
||||
{
|
||||
#ifdef ESP_IDF_VERSION_MAJOR
|
||||
nvs_handle_t handle;
|
||||
#else
|
||||
//#if ESP_IDF_VERSION_MAJOR > 3
|
||||
// nvs_handle_t handle;
|
||||
//#else
|
||||
nvs_handle handle;
|
||||
#endif
|
||||
//#endif
|
||||
esp_err_t ret = nvs_open(key,NVS_READWRITE,&handle);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
|
@ -1453,11 +1533,11 @@ esp_err_t esp_camera_save_to_nvs(const char *key)
|
|||
|
||||
esp_err_t esp_camera_load_from_nvs(const char *key)
|
||||
{
|
||||
#ifdef ESP_IDF_VERSION_MAJOR
|
||||
nvs_handle_t handle;
|
||||
#else
|
||||
//#if ESP_IDF_VERSION_MAJOR > 3
|
||||
// nvs_handle_t handle;
|
||||
//#else
|
||||
nvs_handle handle;
|
||||
#endif
|
||||
//#endif
|
||||
uint8_t pf;
|
||||
|
||||
esp_err_t ret = nvs_open(key,NVS_READWRITE,&handle);
|
||||
|
|
|
@ -37,10 +37,10 @@
|
|||
|
||||
// Select camera model
|
||||
//#define CAMERA_MODEL_WROVER_KIT
|
||||
//#define CAMERA_MODEL_ESP_EYE
|
||||
#define CAMERA_MODEL_ESP_EYE
|
||||
//#define CAMERA_MODEL_M5STACK_PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_WIDE
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
//#define CAMERA_MODEL_AI_THINKER
|
||||
|
||||
#include "camera_pins.h"
|
||||
|
||||
|
@ -113,7 +113,7 @@ void mjpegCB(void* pvParameters) {
|
|||
NULL, //(void*) handler,
|
||||
2,
|
||||
&tStream,
|
||||
// APP_CPU);
|
||||
// APP_CPU);
|
||||
PRO_CPU);
|
||||
|
||||
// Registering webserver handling routines
|
||||
|
@ -469,6 +469,8 @@ void setup()
|
|||
ESP.restart();
|
||||
}
|
||||
|
||||
sensor_t* s = esp_camera_sensor_get();
|
||||
s->set_vflip(s, true);
|
||||
|
||||
// Configure and connect to WiFi
|
||||
IPAddress ip;
|
||||
|
|
Binary file not shown.
|
@ -62,7 +62,8 @@ bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg);
|
|||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out Pointer to be populated with the address of the resulting buffer.
|
||||
* You MUST free the pointer once you are done with it.
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
|
|
1032
esp32-cam/nt99141.c
Normal file
1032
esp32-cam/nt99141.c
Normal file
File diff suppressed because it is too large
Load diff
16
esp32-cam/nt99141.h
Normal file
16
esp32-cam/nt99141.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* NT99141 driver.
|
||||
*
|
||||
*/
|
||||
#ifndef __NT99141_H__
|
||||
#define __NT99141_H__
|
||||
|
||||
#include "sensor.h"
|
||||
|
||||
int NT99141_init(sensor_t *sensor);
|
||||
|
||||
#endif // __NT99141_H__
|
211
esp32-cam/nt99141_regs.h
Normal file
211
esp32-cam/nt99141_regs.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* NT99141 register definitions.
|
||||
*/
|
||||
#ifndef __NT99141_REG_REGS_H__
|
||||
#define __NT99141_REG_REGS_H__
|
||||
|
||||
/* system control registers */
|
||||
#define SYSTEM_CTROL0 0x3021 // Bit[7]: Software reset
|
||||
// Bit[6]: Software power down
|
||||
// Bit[5]: Reserved
|
||||
// Bit[4]: SRB clock SYNC enable
|
||||
// Bit[3]: Isolation suspend select
|
||||
// Bit[2:0]: Not used
|
||||
|
||||
/* output format control registers */
|
||||
#define FORMAT_CTRL 0x501F // Format select
|
||||
// Bit[2:0]:
|
||||
// 000: YUV422
|
||||
// 001: RGB
|
||||
// 010: Dither
|
||||
// 011: RAW after DPC
|
||||
// 101: RAW after CIP
|
||||
|
||||
/* format control registers */
|
||||
#define FORMAT_CTRL00 0x4300
|
||||
|
||||
/* frame control registers */
|
||||
#define FRAME_CTRL01 0x4201 // Control Passed Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode
|
||||
// Bit[7:4]: Not used
|
||||
// Bit[3:0]: Frame ON number
|
||||
#define FRAME_CTRL02 0x4202 // Control Masked Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode
|
||||
// Bit[7:4]: Not used
|
||||
// BIT[3:0]: Frame OFF number
|
||||
|
||||
/* ISP top control registers */
|
||||
#define PRE_ISP_TEST_SETTING_1 0x3025 // Bit[7]: Test enable
|
||||
// 0: Test disable
|
||||
// 1: Color bar enable
|
||||
// Bit[6]: Rolling
|
||||
// Bit[5]: Transparent
|
||||
// Bit[4]: Square black and white
|
||||
// Bit[3:2]: Color bar style
|
||||
// 00: Standard 8 color bar
|
||||
// 01: Gradual change at vertical mode 1
|
||||
// 10: Gradual change at horizontal
|
||||
// 11: Gradual change at vertical mode 2
|
||||
// Bit[1:0]: Test select
|
||||
// 00: Color bar
|
||||
// 01: Random data
|
||||
// 10: Square data
|
||||
// 11: Black image
|
||||
|
||||
//exposure = {0x3500[3:0], 0x3501[7:0], 0x3502[7:0]} / 16 × tROW
|
||||
|
||||
/* AEC/AGC control functions */
|
||||
#define AEC_PK_MANUAL 0x3201 // AEC Manual Mode Control
|
||||
// Bit[7:6]: Reserved
|
||||
// Bit[5]: Gain delay option
|
||||
// Valid when 0x3503[4]=1’b0
|
||||
// 0: Delay one frame latch
|
||||
// 1: One frame latch
|
||||
// Bit[4:2]: Reserved
|
||||
// Bit[1]: AGC manual
|
||||
// 0: Auto enable
|
||||
// 1: Manual enable
|
||||
// Bit[0]: AEC manual
|
||||
// 0: Auto enable
|
||||
// 1: Manual enable
|
||||
|
||||
//gain = {0x350A[1:0], 0x350B[7:0]} / 16
|
||||
|
||||
/* mirror and flip registers */
|
||||
#define TIMING_TC_REG20 0x3022 // Timing Control Register
|
||||
// Bit[2:1]: Vertical flip enable
|
||||
// 00: Normal
|
||||
// 11: Vertical flip
|
||||
// Bit[0]: Vertical binning enable
|
||||
#define TIMING_TC_REG21 0x3022 // Timing Control Register
|
||||
// Bit[5]: Compression Enable
|
||||
// Bit[2:1]: Horizontal mirror enable
|
||||
// 00: Normal
|
||||
// 11: Horizontal mirror
|
||||
// Bit[0]: Horizontal binning enable
|
||||
|
||||
#define CLOCK_POL_CONTROL 0x3024// Bit[5]: PCLK polarity 0: active low
|
||||
// 1: active high
|
||||
// Bit[3]: Gate PCLK under VSYNC
|
||||
// Bit[2]: Gate PCLK under HREF
|
||||
// Bit[1]: HREF polarity
|
||||
// 0: active low
|
||||
// 1: active high
|
||||
// Bit[0] VSYNC polarity
|
||||
// 0: active low
|
||||
// 1: active high
|
||||
#define DRIVE_CAPABILITY 0x306a // Bit[7:6]:
|
||||
// 00: 1x
|
||||
// 01: 2x
|
||||
// 10: 3x
|
||||
// 11: 4x
|
||||
|
||||
|
||||
#define X_ADDR_ST_H 0x3800 //Bit[3:0]: X address start[11:8]
|
||||
#define X_ADDR_ST_L 0x3801 //Bit[7:0]: X address start[7:0]
|
||||
#define Y_ADDR_ST_H 0x3802 //Bit[2:0]: Y address start[10:8]
|
||||
#define Y_ADDR_ST_L 0x3803 //Bit[7:0]: Y address start[7:0]
|
||||
#define X_ADDR_END_H 0x3804 //Bit[3:0]: X address end[11:8]
|
||||
#define X_ADDR_END_L 0x3805 //Bit[7:0]:
|
||||
#define Y_ADDR_END_H 0x3806 //Bit[2:0]: Y address end[10:8]
|
||||
#define Y_ADDR_END_L 0x3807 //Bit[7:0]:
|
||||
// Size after scaling
|
||||
#define X_OUTPUT_SIZE_H 0x3808 //Bit[3:0]: DVP output horizontal width[11:8]
|
||||
#define X_OUTPUT_SIZE_L 0x3809 //Bit[7:0]:
|
||||
#define Y_OUTPUT_SIZE_H 0x380a //Bit[2:0]: DVP output vertical height[10:8]
|
||||
#define Y_OUTPUT_SIZE_L 0x380b //Bit[7:0]:
|
||||
#define X_TOTAL_SIZE_H 0x380c //Bit[3:0]: Total horizontal size[11:8]
|
||||
#define X_TOTAL_SIZE_L 0x380d //Bit[7:0]:
|
||||
#define Y_TOTAL_SIZE_H 0x380e //Bit[7:0]: Total vertical size[15:8]
|
||||
#define Y_TOTAL_SIZE_L 0x380f //Bit[7:0]:
|
||||
#define X_OFFSET_H 0x3810 //Bit[3:0]: ISP horizontal offset[11:8]
|
||||
#define X_OFFSET_L 0x3811 //Bit[7:0]:
|
||||
#define Y_OFFSET_H 0x3812 //Bit[2:0]: ISP vertical offset[10:8]
|
||||
#define Y_OFFSET_L 0x3813 //Bit[7:0]:
|
||||
#define X_INCREMENT 0x3814 //Bit[7:4]: Horizontal odd subsample increment
|
||||
//Bit[3:0]: Horizontal even subsample increment
|
||||
#define Y_INCREMENT 0x3815 //Bit[7:4]: Vertical odd subsample increment
|
||||
//Bit[3:0]: Vertical even subsample increment
|
||||
// Size before scaling
|
||||
//#define X_INPUT_SIZE (X_ADDR_END - X_ADDR_ST + 1 - (2 * X_OFFSET))
|
||||
//#define Y_INPUT_SIZE (Y_ADDR_END - Y_ADDR_ST + 1 - (2 * Y_OFFSET))
|
||||
|
||||
#define ISP_CONTROL_01 0x3021 // Bit[5]: Scale enable
|
||||
// 0: Disable
|
||||
// 1: Enable
|
||||
|
||||
#define SCALE_CTRL_1 0x5601 // Bit[6:4]: HDIV RW
|
||||
// DCW scale times
|
||||
// 000: DCW 1 time
|
||||
// 001: DCW 2 times
|
||||
// 010: DCW 4 times
|
||||
// 100: DCW 8 times
|
||||
// 101: DCW 16 times
|
||||
// Others: DCW 16 times
|
||||
// Bit[2:0]: VDIV RW
|
||||
// DCW scale times
|
||||
// 000: DCW 1 time
|
||||
// 001: DCW 2 times
|
||||
// 010: DCW 4 times
|
||||
// 100: DCW 8 times
|
||||
// 101: DCW 16 times
|
||||
// Others: DCW 16 times
|
||||
|
||||
#define SCALE_CTRL_2 0x5602 // X_SCALE High Bits
|
||||
#define SCALE_CTRL_3 0x5603 // X_SCALE Low Bits
|
||||
#define SCALE_CTRL_4 0x5604 // Y_SCALE High Bits
|
||||
#define SCALE_CTRL_5 0x5605 // Y_SCALE Low Bits
|
||||
#define SCALE_CTRL_6 0x5606 // Bit[3:0]: V Offset
|
||||
|
||||
#define PCLK_RATIO 0x3824 // Bit[4:0]: PCLK ratio manual
|
||||
#define VFIFO_CTRL0C 0x460C // Bit[1]: PCLK manual enable
|
||||
// 0: Auto
|
||||
// 1: Manual by PCLK_RATIO
|
||||
|
||||
#define VFIFO_X_SIZE_H 0x4602
|
||||
#define VFIFO_X_SIZE_L 0x4603
|
||||
#define VFIFO_Y_SIZE_H 0x4604
|
||||
#define VFIFO_Y_SIZE_L 0x4605
|
||||
|
||||
#define SC_PLLS_CTRL0 0x303a // Bit[7]: PLLS bypass
|
||||
#define SC_PLLS_CTRL1 0x303b // Bit[4:0]: PLLS multiplier
|
||||
#define SC_PLLS_CTRL2 0x303c // Bit[6:4]: PLLS charge pump control
|
||||
// Bit[3:0]: PLLS system divider
|
||||
#define SC_PLLS_CTRL3 0x303d // Bit[5:4]: PLLS pre-divider
|
||||
// 00: 1
|
||||
// 01: 1.5
|
||||
// 10: 2
|
||||
// 11: 3
|
||||
// Bit[2]: PLLS root-divider - 1
|
||||
// Bit[1:0]: PLLS seld5
|
||||
// 00: 1
|
||||
// 01: 1
|
||||
// 10: 2
|
||||
// 11: 2.5
|
||||
|
||||
#define COMPRESSION_CTRL00 0x4400 //
|
||||
#define COMPRESSION_CTRL01 0x4401 //
|
||||
#define COMPRESSION_CTRL02 0x4402 //
|
||||
#define COMPRESSION_CTRL03 0x4403 //
|
||||
#define COMPRESSION_CTRL04 0x4404 //
|
||||
#define COMPRESSION_CTRL05 0x4405 //
|
||||
#define COMPRESSION_CTRL06 0x4406 //
|
||||
#define COMPRESSION_CTRL07 0x3401 // Bit[5:0]: QS
|
||||
#define COMPRESSION_ISI_CTRL 0x4408 //
|
||||
#define COMPRESSION_CTRL09 0x4409 //
|
||||
#define COMPRESSION_CTRL0a 0x440a //
|
||||
#define COMPRESSION_CTRL0b 0x440b //
|
||||
#define COMPRESSION_CTRL0c 0x440c //
|
||||
#define COMPRESSION_CTRL0d 0x440d //
|
||||
#define COMPRESSION_CTRL0E 0x440e //
|
||||
|
||||
/**
|
||||
* @brief register value
|
||||
*/
|
||||
#define TEST_COLOR_BAR 0x02 /* Enable Color Bar roling Test */
|
||||
|
||||
#define AEC_PK_MANUAL_AGC_MANUALEN 0x02 /* Enable AGC Manual enable */
|
||||
#define AEC_PK_MANUAL_AEC_MANUALEN 0x01 /* Enable AEC Manual enable */
|
||||
|
||||
#define TIMING_TC_REG20_VFLIP 0x01 /* Vertical flip enable */
|
||||
#define TIMING_TC_REG21_HMIRROR 0x02 /* Horizontal mirror enable */
|
||||
|
||||
#endif // __NT99141_REG_REGS_H__
|
825
esp32-cam/nt99141_settings.h
Normal file
825
esp32-cam/nt99141_settings.h
Normal file
|
@ -0,0 +1,825 @@
|
|||
#ifndef _NT99141_SETTINGS_H_
|
||||
#define _NT99141_SETTINGS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_attr.h"
|
||||
#include "nt99141_regs.h"
|
||||
|
||||
static const ratio_settings_t ratio_table[] = {
|
||||
// mw, mh, sx, sy, ex, ey, ox, oy, tx, ty
|
||||
{ 1280, 720, 0, 4, 1283, 723, 0, 4, 1660, 963 },
|
||||
|
||||
};
|
||||
|
||||
#define REG_DLY 0xffff
|
||||
#define REGLIST_TAIL 0x0000
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_default_regs[][2] = {
|
||||
//initial
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x3109, 0x04},
|
||||
{0x3040, 0x04},
|
||||
{0x3041, 0x02},
|
||||
{0x3042, 0xFF},
|
||||
{0x3043, 0x08},
|
||||
{0x3052, 0xE0},
|
||||
{0x305F, 0x33},
|
||||
{0x3100, 0x07},
|
||||
{0x3106, 0x03},
|
||||
{0x3105, 0x01},
|
||||
{0x3108, 0x05},
|
||||
{0x3110, 0x22},
|
||||
{0x3111, 0x57},
|
||||
{0x3112, 0x22},
|
||||
{0x3113, 0x55},
|
||||
{0x3114, 0x05},
|
||||
{0x3135, 0x00},
|
||||
{0x32F0, 0x01},
|
||||
{0x3290, 0x01},
|
||||
{0x3291, 0x80},
|
||||
{0x3296, 0x01},
|
||||
{0x3297, 0x73},
|
||||
{0x3250, 0x80},
|
||||
{0x3251, 0x03},
|
||||
{0x3252, 0xFF},
|
||||
{0x3253, 0x00},
|
||||
{0x3254, 0x03},
|
||||
{0x3255, 0xFF},
|
||||
{0x3256, 0x00},
|
||||
{0x3257, 0x50},
|
||||
{0x3270, 0x00},
|
||||
{0x3271, 0x0C},
|
||||
{0x3272, 0x18},
|
||||
{0x3273, 0x32},
|
||||
{0x3274, 0x44},
|
||||
{0x3275, 0x54},
|
||||
{0x3276, 0x70},
|
||||
{0x3277, 0x88},
|
||||
{0x3278, 0x9D},
|
||||
{0x3279, 0xB0},
|
||||
{0x327A, 0xCF},
|
||||
{0x327B, 0xE2},
|
||||
{0x327C, 0xEF},
|
||||
{0x327D, 0xF7},
|
||||
{0x327E, 0xFF},
|
||||
{0x3302, 0x00},
|
||||
{0x3303, 0x40},
|
||||
{0x3304, 0x00},
|
||||
{0x3305, 0x96},
|
||||
{0x3306, 0x00},
|
||||
{0x3307, 0x29},
|
||||
{0x3308, 0x07},
|
||||
{0x3309, 0xBA},
|
||||
{0x330A, 0x06},
|
||||
{0x330B, 0xF5},
|
||||
{0x330C, 0x01},
|
||||
{0x330D, 0x51},
|
||||
{0x330E, 0x01},
|
||||
{0x330F, 0x30},
|
||||
{0x3310, 0x07},
|
||||
{0x3311, 0x16},
|
||||
{0x3312, 0x07},
|
||||
{0x3313, 0xBA},
|
||||
{0x3326, 0x02},
|
||||
{0x32F6, 0x0F},
|
||||
{0x32F9, 0x42},
|
||||
{0x32FA, 0x24},
|
||||
{0x3325, 0x4A},
|
||||
{0x3330, 0x00},
|
||||
{0x3331, 0x0A},
|
||||
{0x3332, 0xFF},
|
||||
{0x3338, 0x30},
|
||||
{0x3339, 0x84},
|
||||
{0x333A, 0x48},
|
||||
{0x333F, 0x07},
|
||||
{0x3360, 0x10},
|
||||
{0x3361, 0x18},
|
||||
{0x3362, 0x1f},
|
||||
{0x3363, 0x37},
|
||||
{0x3364, 0x80},
|
||||
{0x3365, 0x80},
|
||||
{0x3366, 0x68},
|
||||
{0x3367, 0x60},
|
||||
{0x3368, 0x30},
|
||||
{0x3369, 0x28},
|
||||
{0x336A, 0x20},
|
||||
{0x336B, 0x10},
|
||||
{0x336C, 0x00},
|
||||
{0x336D, 0x20},
|
||||
{0x336E, 0x1C},
|
||||
{0x336F, 0x18},
|
||||
{0x3370, 0x10},
|
||||
{0x3371, 0x38},
|
||||
{0x3372, 0x3C},
|
||||
{0x3373, 0x3F},
|
||||
{0x3374, 0x3F},
|
||||
{0x338A, 0x34},
|
||||
{0x338B, 0x7F},
|
||||
{0x338C, 0x10},
|
||||
{0x338D, 0x23},
|
||||
{0x338E, 0x7F},
|
||||
{0x338F, 0x14},
|
||||
{0x3375, 0x08},
|
||||
{0x3376, 0x0C},
|
||||
{0x3377, 0x18},
|
||||
{0x3378, 0x20},
|
||||
{0x3012, 0x02},
|
||||
{0x3013, 0xD0},
|
||||
{0x3025, 0x02}, //colorbar
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = {
|
||||
{0x32F0, 0x70}, // YUV422
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = {
|
||||
{0x32F0, 0x50}, // RAW
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = {
|
||||
{0x32F1, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = {
|
||||
{0x32F0, 0x00}, // YUV422
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = {
|
||||
{0x32F0, 0x01}, // RGB
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint8_t sensor_saturation_levels[9][1] = {
|
||||
{0x60},//-4
|
||||
{0x68},//-3
|
||||
{0x70},//-2
|
||||
{0x78},//-1
|
||||
{0x80},//0
|
||||
{0x88},//+1
|
||||
{0x90},//+2
|
||||
{0x98},//+3
|
||||
{0xA0},//+4
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = {
|
||||
{0x00, 0x80, 0x80, 0x01},//Normal
|
||||
{0x03, 0x80, 0x80, 0x01},//Negative
|
||||
{0x01, 0x80, 0x80, 0x01},//Grayscale
|
||||
{0x05, 0x2A, 0xF0, 0x01},//Red Tint
|
||||
{0x05, 0x60, 0x20, 0x01},//Green Tint
|
||||
{0x05, 0xF0, 0x80, 0x01},//Blue Tint
|
||||
{0x02, 0x80, 0x80, 0x01},//Sepia
|
||||
|
||||
};
|
||||
|
||||
// AE LEVEL
|
||||
static const DRAM_ATTR uint16_t sensor_ae_level[][2] = {
|
||||
|
||||
// 1. [AE_Target : 0x24]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x29 },
|
||||
{0x32B9, 0x1F },
|
||||
{0x32BC, 0x24 },
|
||||
{0x32BD, 0x27 },
|
||||
{0x32BE, 0x21 },
|
||||
//------------------------------------------------------------------------
|
||||
// 2. [AE_Target : 0x28]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x2D },
|
||||
{0x32B9, 0x23 },
|
||||
{0x32BC, 0x28 },
|
||||
{0x32BD, 0x2B },
|
||||
{0x32BE, 0x25 },
|
||||
//------------------------------------------------------------------------
|
||||
// 3. [AE_Target : 0x2C]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x32 },
|
||||
{0x32B9, 0x26 },
|
||||
{0x32BC, 0x2C },
|
||||
{0x32BD, 0x2F },
|
||||
{0x32BE, 0x29 },
|
||||
//------------------------------------------------------------------------
|
||||
// 4, [AE_Target : 0x30]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x36 },
|
||||
{0x32B9, 0x2A },
|
||||
{0x32BC, 0x30 },
|
||||
{0x32BD, 0x33 },
|
||||
{0x32BE, 0x2D },
|
||||
//------------------------------------------------------------------------
|
||||
// 5. [AE_Target : 0x34]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x3B },
|
||||
{0x32B9, 0x2D },
|
||||
{0x32BC, 0x34 },
|
||||
{0x32BD, 0x38 },
|
||||
{0x32BE, 0x30 },
|
||||
//------------------------------------------------------------------------
|
||||
// 6. [AE_Target : 0x38]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x3F },
|
||||
{0x32B9, 0x31 },
|
||||
{0x32BC, 0x38 },
|
||||
{0x32BD, 0x3C },
|
||||
{0x32BE, 0x34 },
|
||||
//------------------------------------------------------------------------
|
||||
// 7. [AE_Target : 0x3D]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x44 },
|
||||
{0x32B9, 0x34 },
|
||||
{0x32BC, 0x3C },
|
||||
{0x32BD, 0x40 },
|
||||
{0x32BE, 0x38 },
|
||||
//------------------------------------------------------------------------
|
||||
// 8. [AE_Target : 0x40]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x48 },
|
||||
{0x32B9, 0x38 },
|
||||
{0x32BC, 0x40 },
|
||||
{0x32BD, 0x44 },
|
||||
{0x32BE, 0x3C },
|
||||
//------------------------------------------------------------------------
|
||||
// 9. [AE_Target : 0x44]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x32B8, 0x4D },
|
||||
{0x32B9, 0x3B },
|
||||
{0x32BC, 0x44 },
|
||||
{0x32BD, 0x49 },
|
||||
{0x32BE, 0x3F },
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_HD[][2] = {
|
||||
//[JPEG_1280x720_8.18_8.18_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x3C},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x5E},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0x04},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x05},
|
||||
{0x3007, 0x03},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x06},
|
||||
{0x300B, 0x7C},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x05},
|
||||
{0x300F, 0x00},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x3F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA[][2] = {
|
||||
//[JPEG_640x480_10.14_10.14_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x4B},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x62},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x02},
|
||||
{0x32E1, 0x80},
|
||||
{0x32E2, 0x01},
|
||||
{0x32E3, 0xE0},
|
||||
{0x32E4, 0x00},
|
||||
{0x32E5, 0x80},
|
||||
{0x32E6, 0x00},
|
||||
{0x32E7, 0x80},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0xA4},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x04},
|
||||
{0x3007, 0x63},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x05},
|
||||
{0x300B, 0x3C},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x03},
|
||||
{0x300F, 0xC0},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_QVGA[][2] = {
|
||||
//[JPEG_320x240_10.14_10.14_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x4B},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x62},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x01},
|
||||
{0x32E1, 0x40},
|
||||
{0x32E2, 0x00},
|
||||
{0x32E3, 0xF0},
|
||||
{0x32E4, 0x02},
|
||||
{0x32E5, 0x02},
|
||||
{0x32E6, 0x02},
|
||||
{0x32E7, 0x03},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0xA4},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x04},
|
||||
{0x3007, 0x63},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x05},
|
||||
{0x300B, 0x3C},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x03},
|
||||
{0x300F, 0xC0},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA_xyskip[][2] = {
|
||||
// [JPEG_640x360_20.00_25.01_Fps_XY_Skip]
|
||||
// Set_Device_Format = FORMAT_16_8
|
||||
// SET_Device_Addr = 0x54
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60 },
|
||||
{0x320A, 0xB2 },
|
||||
{0x32C0, 0x64 },
|
||||
{0x32C1, 0x64 },
|
||||
{0x32C2, 0x64 },
|
||||
{0x32C3, 0x00 },
|
||||
{0x32C4, 0x20 },
|
||||
{0x32C5, 0x20 },
|
||||
{0x32C6, 0x20 },
|
||||
{0x32C7, 0x00 },
|
||||
{0x32C8, 0x62 },
|
||||
{0x32C9, 0x64 },
|
||||
{0x32CA, 0x84 },
|
||||
{0x32CB, 0x84 },
|
||||
{0x32CC, 0x84 },
|
||||
{0x32CD, 0x84 },
|
||||
{0x32DB, 0x68 },
|
||||
{0x32F0, 0x70 },
|
||||
{0x3400, 0x08 },
|
||||
{0x3400, 0x00 },
|
||||
{0x3401, 0x4E },
|
||||
{0x3404, 0x00 },
|
||||
{0x3405, 0x00 },
|
||||
{0x3410, 0x00 },
|
||||
{0x3200, 0x3E },
|
||||
{0x3201, 0x0F },
|
||||
{0x3028, 0x0F },
|
||||
{0x3029, 0x00 },
|
||||
{0x302A, 0x08 },
|
||||
{0x3022, 0x24 },
|
||||
{0x3023, 0x6C },
|
||||
{0x3002, 0x00 },
|
||||
{0x3003, 0x04 },
|
||||
{0x3004, 0x00 },
|
||||
{0x3005, 0x04 },
|
||||
{0x3006, 0x05 },
|
||||
{0x3007, 0x03 },
|
||||
{0x3008, 0x02 },
|
||||
{0x3009, 0xD3 },
|
||||
{0x300A, 0x03 },
|
||||
{0x300B, 0xFC },
|
||||
{0x300C, 0x01 },
|
||||
{0x300D, 0x88 },
|
||||
{0x300E, 0x02 },
|
||||
{0x300F, 0x80 },
|
||||
{0x3010, 0x01 },
|
||||
{0x3011, 0x68 },
|
||||
{0x32B8, 0x3F },
|
||||
{0x32B9, 0x31 },
|
||||
{0x32BB, 0x87 },
|
||||
{0x32BC, 0x38 },
|
||||
{0x32BD, 0x3C },
|
||||
{0x32BE, 0x34 },
|
||||
{0x3201, 0x3F },
|
||||
{0x3025, 0x00 }, //normal
|
||||
{0x3021, 0x06 },
|
||||
{0x3400, 0x01 },
|
||||
{0x3060, 0x01 },
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA_xskip[][2] = {
|
||||
//[JPEG_640x480_Xskip_13.32_13.32_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x02},
|
||||
{0x32E1, 0x80},
|
||||
{0x32E2, 0x01},
|
||||
{0x32E3, 0xE0},
|
||||
{0x32E4, 0x00},
|
||||
{0x32E5, 0x00},
|
||||
{0x32E6, 0x00},
|
||||
{0x32E7, 0x80},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x2C},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0x04},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x05},
|
||||
{0x3007, 0x03},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_QVGA_xskip[][2] = {
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
//[JPEG_320x240_Xskip_13.32_13.32_Fps]
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x01},
|
||||
{0x32E1, 0x40},
|
||||
{0x32E2, 0x00},
|
||||
{0x32E3, 0xF0},
|
||||
{0x32E4, 0x01},
|
||||
{0x32E5, 0x01},
|
||||
{0x32E6, 0x02},
|
||||
{0x32E7, 0x03},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x2C},
|
||||
{0x3002, 0x00},
|
||||
{0x3003, 0x04},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x04},
|
||||
{0x3006, 0x05},
|
||||
{0x3007, 0x03},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0xD3},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x02},
|
||||
{0x300D, 0xE0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x02},
|
||||
{0x3011, 0xD0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_VGA_crop[][2] = {
|
||||
//[JPEG_640x480_Crop_19.77_19.77_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x01},
|
||||
{0x3003, 0x44},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x7C},
|
||||
{0x3006, 0x03},
|
||||
{0x3007, 0xC3},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0x5B},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x01},
|
||||
{0x300D, 0xF0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x01},
|
||||
{0x3011, 0xE0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x3F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
static const DRAM_ATTR uint16_t sensor_framesize_QVGA_crop[][2] = {
|
||||
//[JPEG_320x240_Crop_19.77_19.77_Fps]
|
||||
{0x3021, 0x00},
|
||||
{REG_DLY, 100}, // delay 100ms
|
||||
{0x32BF, 0x60},
|
||||
{0x32C0, 0x5A},
|
||||
{0x32C1, 0x5A},
|
||||
{0x32C2, 0x5A},
|
||||
{0x32C3, 0x00},
|
||||
{0x32C4, 0x20},
|
||||
{0x32C5, 0x20},
|
||||
{0x32C6, 0x20},
|
||||
{0x32C7, 0x00},
|
||||
{0x32C8, 0x62},
|
||||
{0x32C9, 0x5A},
|
||||
{0x32CA, 0x7A},
|
||||
{0x32CB, 0x7A},
|
||||
{0x32CC, 0x7A},
|
||||
{0x32CD, 0x7A},
|
||||
{0x32DB, 0x68},
|
||||
{0x32F0, 0x70},
|
||||
{0x3400, 0x08},
|
||||
{0x3400, 0x00},
|
||||
{0x3401, 0x4E},
|
||||
{0x3404, 0x00},
|
||||
{0x3405, 0x00},
|
||||
{0x3410, 0x00},
|
||||
{0x32E0, 0x01},
|
||||
{0x32E1, 0x40},
|
||||
{0x32E2, 0x00},
|
||||
{0x32E3, 0xF0},
|
||||
{0x32E4, 0x01},
|
||||
{0x32E5, 0x01},
|
||||
{0x32E6, 0x01},
|
||||
{0x32E7, 0x02},
|
||||
{0x3200, 0x3E},
|
||||
{0x3201, 0x0F},
|
||||
{0x3028, 0x0F},
|
||||
{0x3029, 0x00},
|
||||
{0x302A, 0x08},
|
||||
{0x3022, 0x24},
|
||||
{0x3023, 0x24},
|
||||
{0x3002, 0x01},
|
||||
{0x3003, 0x44},
|
||||
{0x3004, 0x00},
|
||||
{0x3005, 0x7C},
|
||||
{0x3006, 0x03},
|
||||
{0x3007, 0xC3},
|
||||
{0x3008, 0x02},
|
||||
{0x3009, 0x5B},
|
||||
{0x300A, 0x03},
|
||||
{0x300B, 0xFC},
|
||||
{0x300C, 0x01},
|
||||
{0x300D, 0xF0},
|
||||
{0x300E, 0x02},
|
||||
{0x300F, 0x80},
|
||||
{0x3010, 0x01},
|
||||
{0x3011, 0xE0},
|
||||
{0x32B8, 0x3F},
|
||||
{0x32B9, 0x31},
|
||||
{0x32BB, 0x87},
|
||||
{0x32BC, 0x38},
|
||||
{0x32BD, 0x3C},
|
||||
{0x32BE, 0x34},
|
||||
{0x3201, 0x7F},
|
||||
{0x3021, 0x06},
|
||||
{0x3025, 0x00}, //normal
|
||||
{0x3400, 0x01},
|
||||
{0x3060, 0x01},
|
||||
{REGLIST_TAIL, 0x00}, // tail
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
439
esp32-cam/ov7670.c
Normal file
439
esp32-cam/ov7670.c
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* OV7725 driver.
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sccb.h"
|
||||
#include "ov7670.h"
|
||||
#include "ov7670_regs.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
|
||||
#include "esp32-hal-log.h"
|
||||
#else
|
||||
#include "esp_log.h"
|
||||
static const char* TAG = "ov7760";
|
||||
#endif
|
||||
|
||||
static int ov7670_clkrc = 0x01;
|
||||
|
||||
/*
|
||||
* The default register settings, as obtained from OmniVision. There
|
||||
* is really no making sense of most of these - lots of "reserved" values
|
||||
* and such.
|
||||
*
|
||||
* These settings give VGA YUYV.
|
||||
*/
|
||||
struct regval_list {
|
||||
uint8_t reg_num;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_default_regs[] = {
|
||||
/* Sensor automatically sets output window when resolution changes. */
|
||||
{TSLB, 0x04},
|
||||
|
||||
/* Frame rate 30 fps at 12 Mhz clock */
|
||||
{CLKRC, 0x00},
|
||||
{DBLV, 0x4A},
|
||||
|
||||
{COM10, COM10_VSYNC_NEG | COM10_PCLK_MASK},
|
||||
|
||||
/* Improve white balance */
|
||||
{COM4, 0x40},
|
||||
|
||||
/* Improve color */
|
||||
{RSVD_B0, 0x84},
|
||||
|
||||
/* Enable 50/60 Hz auto detection */
|
||||
{COM11, COM11_EXP|COM11_HZAUTO},
|
||||
|
||||
/* Disable some delays */
|
||||
{HSYST, 0},
|
||||
{HSYEN, 0},
|
||||
|
||||
{MVFP, MVFP_SUN},
|
||||
|
||||
/* More reserved magic, some of which tweaks white balance */
|
||||
{AWBC1, 0x0a},
|
||||
{AWBC2, 0xf0},
|
||||
{AWBC3, 0x34},
|
||||
{AWBC4, 0x58},
|
||||
{AWBC5, 0x28},
|
||||
{AWBC6, 0x3a},
|
||||
|
||||
{AWBCTR3, 0x0a},
|
||||
{AWBCTR2, 0x55},
|
||||
{AWBCTR1, 0x11},
|
||||
{AWBCTR0, 0x9e},
|
||||
|
||||
{COM8, COM8_FAST_AUTO|COM8_STEP_UNLIMIT|COM8_AGC_EN|COM8_AEC_EN|COM8_AWB_EN},
|
||||
|
||||
/* End marker is FF because in ov7670 the address of GAIN 0 and default value too. */
|
||||
{0xFF, 0xFF},
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_fmt_yuv422[] = {
|
||||
{ COM7, 0x0 }, /* Selects YUV mode */
|
||||
{ RGB444, 0 }, /* No RGB444 please */
|
||||
{ COM1, 0 }, /* CCIR601 */
|
||||
{ COM15, COM15_R00FF },
|
||||
{ MVFP, MVFP_SUN },
|
||||
{ COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */
|
||||
{ MTX1, 0x80 }, /* "matrix coefficient 1" */
|
||||
{ MTX2, 0x80 }, /* "matrix coefficient 2" */
|
||||
{ MTX3, 0 }, /* vb */
|
||||
{ MTX4, 0x22 }, /* "matrix coefficient 4" */
|
||||
{ MTX5, 0x5e }, /* "matrix coefficient 5" */
|
||||
{ MTX6, 0x80 }, /* "matrix coefficient 6" */
|
||||
{ COM13, COM13_UVSAT },
|
||||
{ 0xff, 0xff }, /* END MARKER */
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_fmt_rgb565[] = {
|
||||
{ COM7, COM7_FMT_RGB565 }, /* Selects RGB mode */
|
||||
{ RGB444, 0 }, /* No RGB444 please */
|
||||
{ COM1, 0x0 }, /* CCIR601 */
|
||||
{ COM15, COM15_RGB565 |COM15_R00FF },
|
||||
{ MVFP, MVFP_SUN },
|
||||
{ COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */
|
||||
{ MTX1, 0xb3 }, /* "matrix coefficient 1" */
|
||||
{ MTX2, 0xb3 }, /* "matrix coefficient 2" */
|
||||
{ MTX3, 0 }, /* vb */
|
||||
{ MTX4, 0x3d }, /* "matrix coefficient 4" */
|
||||
{ MTX5, 0xa7 }, /* "matrix coefficient 5" */
|
||||
{ MTX6, 0xe4 }, /* "matrix coefficient 6" */
|
||||
{ COM13, COM13_UVSAT },
|
||||
{ 0xff, 0xff }, /* END MARKER */
|
||||
};
|
||||
|
||||
|
||||
static struct regval_list ov7670_vga[] = {
|
||||
{ COM3, 0x00 },
|
||||
{ COM14, 0x00 },
|
||||
{ SCALING_XSC, 0x3A },
|
||||
{ SCALING_YSC, 0x35 },
|
||||
{ SCALING_DCWCTR, 0x11 },
|
||||
{ SCALING_PCLK_DIV, 0xF0 },
|
||||
{ SCALING_PCLK_DELAY, 0x02 },
|
||||
{ 0xff, 0xff },
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_qvga[] = {
|
||||
{ COM3, 0x04 },
|
||||
{ COM14, 0x19 },
|
||||
{ SCALING_XSC, 0x3A },
|
||||
{ SCALING_YSC, 0x35 },
|
||||
{ SCALING_DCWCTR, 0x11 },
|
||||
{ SCALING_PCLK_DIV, 0xF1 },
|
||||
{ SCALING_PCLK_DELAY, 0x02 },
|
||||
{ 0xff, 0xff },
|
||||
};
|
||||
|
||||
static struct regval_list ov7670_qqvga[] = {
|
||||
{ COM3, 0x04 }, //DCW enable
|
||||
{ COM14, 0x1a }, //pixel clock divided by 4, manual scaling enable, DCW and PCLK controlled by register
|
||||
{ SCALING_XSC, 0x3a },
|
||||
{ SCALING_YSC, 0x35 },
|
||||
{ SCALING_DCWCTR, 0x22 }, //downsample by 4
|
||||
{ SCALING_PCLK_DIV, 0xf2 }, //pixel clock divided by 4
|
||||
{ SCALING_PCLK_DELAY, 0x02 },
|
||||
{ 0xff, 0xff },
|
||||
};
|
||||
|
||||
/*
|
||||
* Write a list of register settings; ff/ff stops the process.
|
||||
*/
|
||||
static int ov7670_write_array(sensor_t *sensor, struct regval_list *vals)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while ( (vals->reg_num != 0xff || vals->value != 0xff) && (ret == 0) ) {
|
||||
ret = SCCB_Write(sensor->slv_addr, vals->reg_num, vals->value);
|
||||
|
||||
ESP_LOGD(TAG, "reset reg %02X, W(%02X) R(%02X)", vals->reg_num,
|
||||
vals->value, SCCB_Read(sensor->slv_addr, vals->reg_num) );
|
||||
|
||||
vals++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the frame control registers.
|
||||
*/
|
||||
static int ov7670_frame_control(sensor_t *sensor, int hstart, int hstop, int vstart, int vstop)
|
||||
{
|
||||
struct regval_list frame[7];
|
||||
|
||||
frame[0].reg_num = HSTART;
|
||||
frame[0].value = (hstart >> 3);
|
||||
|
||||
frame[1].reg_num = HSTOP;
|
||||
frame[1].value = (hstop >> 3);
|
||||
|
||||
frame[2].reg_num = HREF;
|
||||
frame[2].value = (((hstop & 0x07) << 3) | (hstart & 0x07));
|
||||
|
||||
frame[3].reg_num = VSTART;
|
||||
frame[3].value = (vstart >> 2);
|
||||
|
||||
frame[4].reg_num = VSTOP;
|
||||
frame[4].value = (vstop >> 2);
|
||||
|
||||
frame[5].reg_num = VREF;
|
||||
frame[5].value = (((vstop & 0x02) << 2) | (vstart & 0x02));
|
||||
|
||||
/* End mark */
|
||||
frame[5].reg_num = 0xFF;
|
||||
frame[5].value = 0xFF;
|
||||
|
||||
return ov7670_write_array(sensor, frame);
|
||||
}
|
||||
|
||||
static int reset(sensor_t *sensor)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// Reset all registers
|
||||
SCCB_Write(sensor->slv_addr, COM7, COM7_RESET);
|
||||
|
||||
// Delay 10 ms
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
ret = ov7670_write_array(sensor, ov7670_default_regs);
|
||||
|
||||
// Delay
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (pixformat) {
|
||||
case PIXFORMAT_RGB565:
|
||||
case PIXFORMAT_RGB888:
|
||||
ret = ov7670_write_array(sensor, ov7670_fmt_rgb565);
|
||||
break;
|
||||
|
||||
case PIXFORMAT_YUV422:
|
||||
case PIXFORMAT_GRAYSCALE:
|
||||
default:
|
||||
ret = ov7670_write_array(sensor, ov7670_fmt_yuv422);
|
||||
break;
|
||||
}
|
||||
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
|
||||
/*
|
||||
* If we're running RGB565, we must rewrite clkrc after setting
|
||||
* the other parameters or the image looks poor. If we're *not*
|
||||
* doing RGB565, we must not rewrite clkrc or the image looks
|
||||
* *really* poor.
|
||||
*
|
||||
* (Update) Now that we retain clkrc state, we should be able
|
||||
* to write it unconditionally, and that will make the frame
|
||||
* rate persistent too.
|
||||
*/
|
||||
if (pixformat == PIXFORMAT_RGB565) {
|
||||
ret = SCCB_Write(sensor->slv_addr, CLKRC, ov7670_clkrc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_framesize(sensor_t *sensor, framesize_t framesize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// store clkrc before changing window settings...
|
||||
ov7670_clkrc = SCCB_Read(sensor->slv_addr, CLKRC);
|
||||
|
||||
switch (framesize){
|
||||
case FRAMESIZE_VGA:
|
||||
if( (ret = ov7670_write_array(sensor, ov7670_vga)) == 0 ) {
|
||||
/* These values from Omnivision */
|
||||
ret = ov7670_frame_control(sensor, 158, 14, 10, 490);
|
||||
}
|
||||
break;
|
||||
case FRAMESIZE_QVGA:
|
||||
if( (ret = ov7670_write_array(sensor, ov7670_qvga)) == 0 ) {
|
||||
/* These values from Omnivision */
|
||||
ret = ov7670_frame_control(sensor, 158, 14, 10, 490);
|
||||
}
|
||||
break;
|
||||
case FRAMESIZE_QQVGA:
|
||||
if( (ret = ov7670_write_array(sensor, ov7670_qqvga)) == 0 ) {
|
||||
/* These values from Omnivision */
|
||||
ret = ov7670_frame_control(sensor, 158, 14, 10, 490);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
|
||||
if (ret == 0) {
|
||||
sensor->status.framesize = framesize;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_colorbar(sensor_t *sensor, int enable)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
// Read register scaling_xsc
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, SCALING_XSC);
|
||||
|
||||
// Pattern to set color bar bit[0]=0 in every case
|
||||
reg = SCALING_XSC_CBAR(reg);
|
||||
|
||||
// Write pattern to SCALING_XSC
|
||||
ret = SCCB_Write(sensor->slv_addr, SCALING_XSC, reg);
|
||||
|
||||
// Read register scaling_ysc
|
||||
reg = SCCB_Read(sensor->slv_addr, SCALING_YSC);
|
||||
|
||||
// Pattern to set color bar bit[0]=0 in every case
|
||||
reg = SCALING_YSC_CBAR(reg, enable);
|
||||
|
||||
// Write pattern to SCALING_YSC
|
||||
ret = ret | SCCB_Write(sensor->slv_addr, SCALING_YSC, reg);
|
||||
|
||||
// return 0 or 0xFF
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_whitebal(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AWB(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
}
|
||||
|
||||
static int set_gain_ctrl(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AGC(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
}
|
||||
|
||||
static int set_exposure_ctrl(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AEC(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
}
|
||||
|
||||
static int set_hmirror(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register MVFP
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP);
|
||||
|
||||
// Set mirror on/off
|
||||
reg = MVFP_SET_MIRROR(reg, enable);
|
||||
|
||||
// Write back register MVFP
|
||||
return SCCB_Write(sensor->slv_addr, MVFP, reg);
|
||||
}
|
||||
|
||||
static int set_vflip(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register MVFP
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP);
|
||||
|
||||
// Set mirror on/off
|
||||
reg = MVFP_SET_FLIP(reg, enable);
|
||||
|
||||
// Write back register MVFP
|
||||
return SCCB_Write(sensor->slv_addr, MVFP, reg);
|
||||
}
|
||||
|
||||
static int init_status(sensor_t *sensor)
|
||||
{
|
||||
sensor->status.awb = 0;
|
||||
sensor->status.aec = 0;
|
||||
sensor->status.agc = 0;
|
||||
sensor->status.hmirror = 0;
|
||||
sensor->status.vflip = 0;
|
||||
sensor->status.colorbar = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_dummy(sensor_t *sensor, int val){ return -1; }
|
||||
static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; }
|
||||
|
||||
int ov7670_init(sensor_t *sensor)
|
||||
{
|
||||
// Set function pointers
|
||||
sensor->reset = reset;
|
||||
sensor->init_status = init_status;
|
||||
sensor->set_pixformat = set_pixformat;
|
||||
sensor->set_framesize = set_framesize;
|
||||
sensor->set_colorbar = set_colorbar;
|
||||
sensor->set_whitebal = set_whitebal;
|
||||
sensor->set_gain_ctrl = set_gain_ctrl;
|
||||
sensor->set_exposure_ctrl = set_exposure_ctrl;
|
||||
sensor->set_hmirror = set_hmirror;
|
||||
sensor->set_vflip = set_vflip;
|
||||
|
||||
//not supported
|
||||
sensor->set_brightness= set_dummy;
|
||||
sensor->set_saturation= set_dummy;
|
||||
sensor->set_quality = set_dummy;
|
||||
sensor->set_gainceiling = set_gainceiling_dummy;
|
||||
sensor->set_aec2 = set_dummy;
|
||||
sensor->set_aec_value = set_dummy;
|
||||
sensor->set_special_effect = set_dummy;
|
||||
sensor->set_wb_mode = set_dummy;
|
||||
sensor->set_ae_level = set_dummy;
|
||||
sensor->set_dcw = set_dummy;
|
||||
sensor->set_bpc = set_dummy;
|
||||
sensor->set_wpc = set_dummy;
|
||||
sensor->set_awb_gain = set_dummy;
|
||||
sensor->set_agc_gain = set_dummy;
|
||||
sensor->set_raw_gma = set_dummy;
|
||||
sensor->set_lenc = set_dummy;
|
||||
sensor->set_sharpness = set_dummy;
|
||||
sensor->set_denoise = set_dummy;
|
||||
|
||||
// Retrieve sensor's signature
|
||||
sensor->id.MIDH = SCCB_Read(sensor->slv_addr, REG_MIDH);
|
||||
sensor->id.MIDL = SCCB_Read(sensor->slv_addr, REG_MIDL);
|
||||
sensor->id.PID = SCCB_Read(sensor->slv_addr, REG_PID);
|
||||
sensor->id.VER = SCCB_Read(sensor->slv_addr, REG_VER);
|
||||
|
||||
ESP_LOGD(TAG, "OV7670 Attached");
|
||||
|
||||
return 0;
|
||||
}
|
14
esp32-cam/ov7670.h
Normal file
14
esp32-cam/ov7670.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* OV7670 driver.
|
||||
*
|
||||
*/
|
||||
#ifndef __OV7670_H__
|
||||
#define __OV7670_H__
|
||||
#include "sensor.h"
|
||||
|
||||
int ov7670_init(sensor_t *sensor);
|
||||
#endif // __OV7670_H__
|
354
esp32-cam/ov7670_regs.h
Normal file
354
esp32-cam/ov7670_regs.h
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* This file is for the OpenMV project so the OV7670 can be used
|
||||
* author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
|
||||
*
|
||||
* OV7670 register definitions.
|
||||
*/
|
||||
#ifndef __OV7670_REG_REGS_H__
|
||||
#define __OV7670_REG_REGS_H__
|
||||
#define GAIN 0x00 /* AGC – Gain control gain setting */
|
||||
#define BLUE 0x01 /* AWB – Blue channel gain setting */
|
||||
#define RED 0x02 /* AWB – Red channel gain setting */
|
||||
#define VREF 0x03 /* AWB – Green channel gain setting */
|
||||
#define COM1 0x04 /* Common Control 1 */
|
||||
#define BAVG 0x05 /* U/B Average Level */
|
||||
#define GAVG 0x06 /* Y/Gb Average Level */
|
||||
#define AECH 0x07 /* Exposure VAlue - AEC MSB 5 bits */
|
||||
#define RAVG 0x08 /* V/R Average Level */
|
||||
|
||||
#define COM2 0x09 /* Common Control 2 */
|
||||
#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */
|
||||
#define COM2_OUT_DRIVE_1x 0x00 /* Output drive capability 1x */
|
||||
#define COM2_OUT_DRIVE_2x 0x01 /* Output drive capability 2x */
|
||||
#define COM2_OUT_DRIVE_3x 0x02 /* Output drive capability 3x */
|
||||
#define COM2_OUT_DRIVE_4x 0x03 /* Output drive capability 4x */
|
||||
|
||||
#define REG_PID 0x0A /* Product ID Number MSB */
|
||||
#define REG_VER 0x0B /* Product ID Number LSB */
|
||||
|
||||
#define COM3 0x0C /* Common Control 3 */
|
||||
#define COM3_SWAP_OUT 0x40 /* Output data MSB/LSB swap */
|
||||
#define COM3_TRI_CLK 0x20 /* Tri-state output clock */
|
||||
#define COM3_TRI_DATA 0x10 /* Tri-state option output */
|
||||
#define COM3_SCALE_EN 0x08 /* Scale enable */
|
||||
#define COM3_DCW 0x04 /* DCW enable */
|
||||
|
||||
#define COM4 0x0D /* Common Control 4 */
|
||||
#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */
|
||||
#define COM4_PLL_4x 0x40 /* PLL frequency 4x */
|
||||
#define COM4_PLL_6x 0x80 /* PLL frequency 6x */
|
||||
#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */
|
||||
#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */
|
||||
#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */
|
||||
#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */
|
||||
#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */
|
||||
|
||||
#define COM5 0x0E /* Common Control 5 */
|
||||
#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */
|
||||
#define COM5_AFR_SPEED 0x40 /* Auto frame rate control speed selection */
|
||||
#define COM5_AFR_0 0x00 /* No reduction of frame rate */
|
||||
#define COM5_AFR_1_2 0x10 /* Max reduction to 1/2 frame rate */
|
||||
#define COM5_AFR_1_4 0x20 /* Max reduction to 1/4 frame rate */
|
||||
#define COM5_AFR_1_8 0x30 /* Max reduction to 1/8 frame rate */
|
||||
#define COM5_AFR_4x 0x04 /* Add frame when AGC reaches 4x gain */
|
||||
#define COM5_AFR_8x 0x08 /* Add frame when AGC reaches 8x gain */
|
||||
#define COM5_AFR_16x 0x0c /* Add frame when AGC reaches 16x gain */
|
||||
#define COM5_AEC_NO_LIMIT 0x01 /* No limit to AEC increase step */
|
||||
|
||||
#define COM6 0x0F /* Common Control 6 */
|
||||
#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */
|
||||
|
||||
#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */
|
||||
#define CLKRC 0x11 /* Internal Clock */
|
||||
|
||||
#define COM7 0x12 /* Common Control 7 */
|
||||
#define COM7_RESET 0x80 /* SCCB Register Reset */
|
||||
#define COM7_RES_VGA 0x00 /* Resolution VGA */
|
||||
#define COM7_RES_QVGA 0x40 /* Resolution QVGA */
|
||||
#define COM7_BT656 0x20 /* BT.656 protocol ON/OFF */
|
||||
#define COM7_SENSOR_RAW 0x10 /* Sensor RAW */
|
||||
#define COM7_FMT_GBR422 0x00 /* RGB output format GBR422 */
|
||||
#define COM7_FMT_RGB565 0x04 /* RGB output format RGB565 */
|
||||
#define COM7_FMT_RGB555 0x08 /* RGB output format RGB555 */
|
||||
#define COM7_FMT_RGB444 0x0C /* RGB output format RGB444 */
|
||||
#define COM7_FMT_YUV 0x00 /* Output format YUV */
|
||||
#define COM7_FMT_P_BAYER 0x01 /* Output format Processed Bayer RAW */
|
||||
#define COM7_FMT_RGB 0x04 /* Output format RGB */
|
||||
#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */
|
||||
#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x5)<<0))
|
||||
|
||||
#define COM8 0x13 /* Common Control 8 */
|
||||
#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */
|
||||
#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */
|
||||
#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */
|
||||
#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */
|
||||
#define COM8_AEC_BANDF 0x10 /* Enable AEC below banding value */
|
||||
#define COM8_AEC_FINE_EN 0x08 /* Fine AEC ON/OFF control */
|
||||
#define COM8_AGC_EN 0x04 /* AGC Enable */
|
||||
#define COM8_AWB_EN 0x02 /* AWB Enable */
|
||||
#define COM8_AEC_EN 0x01 /* AEC Enable */
|
||||
#define COM8_SET_AGC(r, x) ((r&0xFB)|((x&0x1)<<2))
|
||||
#define COM8_SET_AWB(r, x) ((r&0xFD)|((x&0x1)<<1))
|
||||
#define COM8_SET_AEC(r, x) ((r&0xFE)|((x&0x1)<<0))
|
||||
|
||||
#define COM9 0x14 /* Common Control 9 */
|
||||
#define COM9_HISTO_AVG 0x80 /* Histogram or average based AEC/AGC selection */
|
||||
#define COM9_AGC_GAIN_2x 0x00 /* Automatic Gain Ceiling 2x */
|
||||
#define COM9_AGC_GAIN_4x 0x10 /* Automatic Gain Ceiling 4x */
|
||||
#define COM9_AGC_GAIN_8x 0x20 /* Automatic Gain Ceiling 8x */
|
||||
#define COM9_AGC_GAIN_16x 0x30 /* Automatic Gain Ceiling 16x */
|
||||
#define COM9_AGC_GAIN_32x 0x40 /* Automatic Gain Ceiling 32x */
|
||||
#define COM9_DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */
|
||||
#define COM9_DROP_HREF 0x02 /* Drop HREF output of corrupt frame */
|
||||
#define COM9_SET_AGC(r, x) ((r&0x8F)|((x&0x07)<<4))
|
||||
|
||||
#define COM10 0x15 /* Common Control 10 */
|
||||
#define COM10_NEGATIVE 0x80 /* Output negative data */
|
||||
#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */
|
||||
#define COM10_PCLK_FREE 0x00 /* PCLK output option: free running PCLK */
|
||||
#define COM10_PCLK_MASK 0x20 /* PCLK output option: masked during horizontal blank */
|
||||
#define COM10_PCLK_REV 0x10 /* PCLK reverse */
|
||||
#define COM10_HREF_REV 0x08 /* HREF reverse */
|
||||
#define COM10_VSYNC_FALLING 0x00 /* VSYNC changes on falling edge of PCLK */
|
||||
#define COM10_VSYNC_RISING 0x04 /* VSYNC changes on rising edge of PCLK */
|
||||
#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */
|
||||
#define COM10_OUT_RANGE_8 0x01 /* Output data range: Full range */
|
||||
#define COM10_OUT_RANGE_10 0x00 /* Output data range: Data from [10] to [F0] (8 MSBs) */
|
||||
|
||||
#define RSVD_16 0x16 /* Reserved register */
|
||||
|
||||
#define HSTART 0x17 /* Horizontal Frame (HREF column) Start high 8-bit(low 3 bits are at HREF[2:0]) */
|
||||
#define HSTOP 0x18 /* Horizontal Frame (HREF column) end high 8-bit (low 3 bits are at HREF[5:3]) */
|
||||
#define VSTART 0x19 /* Vertical Frame (row) Start high 8-bit (low 2 bits are at VREF[1:0]) */
|
||||
#define VSTOP 0x1A /* Vertical Frame (row) End high 8-bit (low 2 bits are at VREF[3:2]) */
|
||||
#define PSHFT 0x1B /* Data Format - Pixel Delay Select */
|
||||
#define REG_MIDH 0x1C /* Manufacturer ID Byte – High */
|
||||
#define REG_MIDL 0x1D /* Manufacturer ID Byte – Low */
|
||||
|
||||
#define MVFP 0x1E /* Mirror/Vflip Enable */
|
||||
#define MVFP_MIRROR 0x20 /* Mirror image */
|
||||
#define MVFP_FLIP 0x10 /* Vertical flip */
|
||||
#define MVFP_SUN 0x02 /* Black sun enable */
|
||||
#define MVFP_SET_MIRROR(r,x) ((r&0xDF)|((x&1)<<5)) /* change only bit5 according to x */
|
||||
#define MVFP_SET_FLIP(r,x) ((r&0xEF)|((x&1)<<4)) /* change only bit4 according to x */
|
||||
|
||||
#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period (Reserved?) */
|
||||
#define ADCCTR0 0x20 /* ADC control */
|
||||
#define ADCCTR1 0x21 /* reserved */
|
||||
#define ADCCTR2 0x22 /* reserved */
|
||||
#define ADCCTR3 0x23 /* reserved */
|
||||
#define AEW 0x24 /* AGC/AEC - Stable Operating Region (Upper Limit) */
|
||||
#define AEB 0x25 /* AGC/AEC - Stable Operating Region (Lower Limit) */
|
||||
#define VPT 0x26 /* AGC/AEC Fast Mode Operating Region */
|
||||
#define BBIAS 0x27 /* B channel signal output bias (effective only when COM6[3]=1) */
|
||||
#define GbBIAS 0x28 /* Gb channel signal output bias (effective only when COM6[3]=1) */
|
||||
#define RSVD_29 0x29 /* reserved */
|
||||
#define EXHCH 0x2A /* Dummy Pixel Insert MSB */
|
||||
#define EXHCL 0x2B /* Dummy Pixel Insert LSB */
|
||||
#define RBIAS 0x2C /* R channel signal output bias (effective only when COM6[3]=1) */
|
||||
#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */
|
||||
#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */
|
||||
#define YAVE 0x2F /* Y/G Channel Average Value */
|
||||
#define HSYST 0x30 /* HSync rising edge delay */
|
||||
#define HSYEN 0x31 /* HSync falling edge delay */
|
||||
#define HREF 0x32 /* Image Start and Size Control DIFFERENT CONTROL SEQUENCE */
|
||||
#define CHLF 0x33 /* Array Current control */
|
||||
#define ARBLM 0x34 /* Array reference control */
|
||||
#define RSVD_35 0x35 /* Reserved */
|
||||
#define RSVD_36 0x36 /* Reserved */
|
||||
#define ADC 0x37 /* ADC control */
|
||||
#define ACOM 0x38 /* ADC and analog common mode control */
|
||||
#define OFON 0x39 /* ADC offset control */
|
||||
#define TSLB 0x3A /* Line buffer test option */
|
||||
|
||||
#define COM11 0x3B /* Common control 11 */
|
||||
#define COM11_EXP 0x02
|
||||
#define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */
|
||||
|
||||
#define COM12 0x3C /* Common control 12 */
|
||||
|
||||
#define COM13 0x3D /* Common control 13 */
|
||||
#define COM13_GAMMA 0x80 /* Gamma enable */
|
||||
#define COM13_UVSAT 0x40 /* UV saturation auto adjustment */
|
||||
|
||||
#define COM14 0x3E /* Common Control 14 */
|
||||
|
||||
#define EDGE 0x3F /* edge enhancement adjustment */
|
||||
#define COM15 0x40 /* Common Control 15 DIFFERENT CONTROLS */
|
||||
#define COM15_SET_RGB565(r,x) ((r&0xEF)|((x&1)<<4)) /* set rgb565 mode */
|
||||
#define COM15_RGB565 0x10 /* RGB565 output */
|
||||
#define COM15_R00FF 0xC0 /* Output range: [00] to [FF] */
|
||||
|
||||
#define COM16 0x41 /* Common Control 16 DIFFERENT CONTROLS */
|
||||
#define COM16_AWBGAIN 0x08 /* AWB gain enable */
|
||||
#define COM17 0x42 /* Common Control 17 */
|
||||
|
||||
#define AWBC1 0x43 /* Reserved */
|
||||
#define AWBC2 0x44 /* Reserved */
|
||||
#define AWBC3 0x45 /* Reserved */
|
||||
#define AWBC4 0x46 /* Reserved */
|
||||
#define AWBC5 0x47 /* Reserved */
|
||||
#define AWBC6 0x48 /* Reserved */
|
||||
|
||||
#define RSVD_49 0x49 /* Reserved */
|
||||
#define RSVD_4A 0x4A /* Reserved */
|
||||
|
||||
#define REG4B 0x4B /* Register 4B */
|
||||
#define DNSTH 0x4C /* Denoise strength */
|
||||
|
||||
#define RSVD_4D 0x4D /* Reserved */
|
||||
#define RSVD_4E 0x4E /* Reserved */
|
||||
|
||||
#define MTX1 0x4F /* Matrix coefficient 1 */
|
||||
#define MTX2 0x50 /* Matrix coefficient 2 */
|
||||
#define MTX3 0x51 /* Matrix coefficient 3 */
|
||||
#define MTX4 0x52 /* Matrix coefficient 4 */
|
||||
#define MTX5 0x53 /* Matrix coefficient 5 */
|
||||
#define MTX6 0x54 /* Matrix coefficient 6 */
|
||||
#define BRIGHTNESS 0x55 /* Brightness control */
|
||||
#define CONTRAST 0x56 /* Contrast control */
|
||||
#define CONTRASCENTER 0x57 /* Contrast center */
|
||||
#define MTXS 0x58 /* Matrix coefficient sign for coefficient 5 to 0*/
|
||||
|
||||
#define RSVD_59 0x59 /* Reserved */
|
||||
#define RSVD_5A 0x5A /* Reserved */
|
||||
#define RSVD_5B 0x5B /* Reserved */
|
||||
#define RSVD_5C 0x5C /* Reserved */
|
||||
#define RSVD_5D 0x5D /* Reserved */
|
||||
#define RSVD_5E 0x5E /* Reserved */
|
||||
#define RSVD_5F 0x5F /* Reserved */
|
||||
#define RSVD_60 0x60 /* Reserved */
|
||||
#define RSVD_61 0x61 /* Reserved */
|
||||
|
||||
#define LCC1 0x62 /* Lens correction option 1 */
|
||||
|
||||
#define LCC2 0x63 /* Lens correction option 2 */
|
||||
#define LCC3 0x64 /* Lens correction option 3 */
|
||||
#define LCC4 0x65 /* Lens correction option 4 */
|
||||
#define LCC5 0x66 /* Lens correction option 5 */
|
||||
|
||||
#define MANU 0x67 /* Manual U Value */
|
||||
#define MANV 0x68 /* Manual V Value */
|
||||
#define GFIX 0x69 /* Fix gain control */
|
||||
#define GGAIN 0x6A /* G channel AWB gain */
|
||||
|
||||
#define DBLV 0x6B /* PLL and clock ? */
|
||||
|
||||
#define AWBCTR3 0x6C /* AWB Control 3 */
|
||||
#define AWBCTR2 0x6D /* AWB Control 2 */
|
||||
#define AWBCTR1 0x6E /* AWB Control 1 */
|
||||
#define AWBCTR0 0x6F /* AWB Control 0 */
|
||||
#define SCALING_XSC 0x70 /* test pattern and horizontal scaling factor */
|
||||
#define SCALING_XSC_CBAR(r) (r&0x7F) /* make sure bit7 is 0 for color bar */
|
||||
#define SCALING_YSC 0x71 /* test pattern and vertical scaling factor */
|
||||
#define SCALING_YSC_CBAR(r,x) ((r&0x7F)|((x&1)<<7)) /* change bit7 for color bar on/off */
|
||||
#define SCALING_DCWCTR 0x72 /* DCW control */
|
||||
#define SCALING_PCLK_DIV 0x73 /* */
|
||||
#define REG74 0x74 /* */
|
||||
#define REG75 0x75 /* */
|
||||
#define REG76 0x76 /* */
|
||||
#define REG77 0x77 /* */
|
||||
|
||||
#define RSVD_78 0x78 /* Reserved */
|
||||
#define RSVD_79 0x79 /* Reserved */
|
||||
|
||||
#define SLOP 0x7A /* Gamma curve highest segment slope */
|
||||
#define GAM1 0x7B /* Gamma Curve 1st Segment Input End Point 0x04 Output Value */
|
||||
#define GAM2 0x7C /* Gamma Curve 2nd Segment Input End Point 0x08 Output Value */
|
||||
#define GAM3 0x7D /* Gamma Curve 3rd Segment Input End Point 0x10 Output Value */
|
||||
#define GAM4 0x7E /* Gamma Curve 4th Segment Input End Point 0x20 Output Value */
|
||||
#define GAM5 0x7F /* Gamma Curve 5th Segment Input End Point 0x28 Output Value */
|
||||
#define GAM6 0x80 /* Gamma Curve 6rd Segment Input End Point 0x30 Output Value */
|
||||
#define GAM7 0x81 /* Gamma Curve 7th Segment Input End Point 0x38 Output Value */
|
||||
#define GAM8 0x82 /* Gamma Curve 8th Segment Input End Point 0x40 Output Value */
|
||||
#define GAM9 0x83 /* Gamma Curve 9th Segment Input End Point 0x48 Output Value */
|
||||
#define GAM10 0x84 /* Gamma Curve 10th Segment Input End Point 0x50 Output Value */
|
||||
#define GAM11 0x85 /* Gamma Curve 11th Segment Input End Point 0x60 Output Value */
|
||||
#define GAM12 0x86 /* Gamma Curve 12th Segment Input End Point 0x70 Output Value */
|
||||
#define GAM13 0x87 /* Gamma Curve 13th Segment Input End Point 0x90 Output Value */
|
||||
#define GAM14 0x88 /* Gamma Curve 14th Segment Input End Point 0xB0 Output Value */
|
||||
#define GAM15 0x89 /* Gamma Curve 15th Segment Input End Point 0xD0 Output Value */
|
||||
|
||||
#define RSVD_8A 0x8A /* Reserved */
|
||||
#define RSVD_8B 0x8B /* Reserved */
|
||||
|
||||
#define RGB444 0x8C /* */
|
||||
|
||||
#define RSVD_8D 0x8D /* Reserved */
|
||||
#define RSVD_8E 0x8E /* Reserved */
|
||||
#define RSVD_8F 0x8F /* Reserved */
|
||||
#define RSVD_90 0x90 /* Reserved */
|
||||
#define RSVD_91 0x91 /* Reserved */
|
||||
|
||||
#define DM_LNL 0x92 /* Dummy line low 8 bit */
|
||||
#define DM_LNH 0x93 /* Dummy line high 8 bit */
|
||||
#define LCC6 0x94 /* Lens correction option 6 */
|
||||
#define LCC7 0x95 /* Lens correction option 7 */
|
||||
|
||||
#define RSVD_96 0x96 /* Reserved */
|
||||
#define RSVD_97 0x97 /* Reserved */
|
||||
#define RSVD_98 0x98 /* Reserved */
|
||||
#define RSVD_99 0x99 /* Reserved */
|
||||
#define RSVD_9A 0x9A /* Reserved */
|
||||
#define RSVD_9B 0x9B /* Reserved */
|
||||
#define RSVD_9C 0x9C /* Reserved */
|
||||
|
||||
#define BD50ST 0x9D /* 50 Hz banding filter value */
|
||||
#define BD60ST 0x9E /* 60 Hz banding filter value */
|
||||
#define HAECC1 0x9F /* Histogram-based AEC/AGC control 1 */
|
||||
#define HAECC2 0xA0 /* Histogram-based AEC/AGC control 2 */
|
||||
|
||||
#define RSVD_A1 0xA1 /* Reserved */
|
||||
|
||||
#define SCALING_PCLK_DELAY 0xA2 /* Pixel clock delay */
|
||||
|
||||
#define RSVD_A3 0xA3 /* Reserved */
|
||||
|
||||
#define NT_CNTRL 0xA4 /* */
|
||||
#define BD50MAX 0xA5 /* 50 Hz banding step limit */
|
||||
#define HAECC3 0xA6 /* Histogram-based AEC/AGC control 3 */
|
||||
#define HAECC4 0xA7 /* Histogram-based AEC/AGC control 4 */
|
||||
#define HAECC5 0xA8 /* Histogram-based AEC/AGC control 5 */
|
||||
#define HAECC6 0xA9 /* Histogram-based AEC/AGC control 6 */
|
||||
|
||||
#define HAECC7 0xAA /* Histogram-based AEC/AGC control 7 */
|
||||
#define HAECC_EN 0x80 /* Histogram-based AEC algorithm enable */
|
||||
|
||||
#define BD60MAX 0xAB /* 60 Hz banding step limit */
|
||||
|
||||
#define STR_OPT 0xAC /* Register AC */
|
||||
#define STR_R 0xAD /* R gain for led output frame */
|
||||
#define STR_G 0xAE /* G gain for led output frame */
|
||||
#define STR_B 0xAF /* B gain for led output frame */
|
||||
#define RSVD_B0 0xB0 /* Reserved */
|
||||
#define ABLC1 0xB1 /* */
|
||||
#define RSVD_B2 0xB2 /* Reserved */
|
||||
#define THL_ST 0xB3 /* ABLC target */
|
||||
#define THL_DLT 0xB5 /* ABLC stable range */
|
||||
|
||||
#define RSVD_B6 0xB6 /* Reserved */
|
||||
#define RSVD_B7 0xB7 /* Reserved */
|
||||
#define RSVD_B8 0xB8 /* Reserved */
|
||||
#define RSVD_B9 0xB9 /* Reserved */
|
||||
#define RSVD_BA 0xBA /* Reserved */
|
||||
#define RSVD_BB 0xBB /* Reserved */
|
||||
#define RSVD_BC 0xBC /* Reserved */
|
||||
#define RSVD_BD 0xBD /* Reserved */
|
||||
|
||||
#define AD_CHB 0xBE /* blue channel black level compensation */
|
||||
#define AD_CHR 0xBF /* Red channel black level compensation */
|
||||
#define AD_CHGb 0xC0 /* Gb channel black level compensation */
|
||||
#define AD_CHGr 0xC1 /* Gr channel black level compensation */
|
||||
|
||||
#define RSVD_C2 0xC2 /* Reserved */
|
||||
#define RSVD_C3 0xC3 /* Reserved */
|
||||
#define RSVD_C4 0xC4 /* Reserved */
|
||||
#define RSVD_C5 0xC5 /* Reserved */
|
||||
#define RSVD_C6 0xC6 /* Reserved */
|
||||
#define RSVD_C7 0xC7 /* Reserved */
|
||||
#define RSVD_C8 0xC8 /* Reserved */
|
||||
|
||||
#define SATCTR 0xC9 /* Saturation control */
|
||||
#define SET_REG(reg, x) (##reg_DEFAULT|x)
|
||||
|
||||
#endif //__OV7670_REG_REGS_H__
|
|
@ -121,6 +121,51 @@ static const uint8_t default_regs[][2] = {
|
|||
{0x00, 0x00},
|
||||
};
|
||||
|
||||
static int get_reg(sensor_t *sensor, int reg, int mask)
|
||||
{
|
||||
int ret = SCCB_Read(sensor->slv_addr, reg & 0xFF);
|
||||
if(ret > 0){
|
||||
ret &= mask;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_reg(sensor_t *sensor, int reg, int mask, int value)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = SCCB_Read(sensor->slv_addr, reg & 0xFF);
|
||||
if(ret < 0){
|
||||
return ret;
|
||||
}
|
||||
value = (ret & ~mask) | (value & mask);
|
||||
ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length, uint8_t value)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = SCCB_Read(sensor->slv_addr, reg);
|
||||
if(ret < 0){
|
||||
return ret;
|
||||
}
|
||||
uint8_t mask = ((1 << length) - 1) << offset;
|
||||
value = (ret & ~mask) | ((value << offset) & mask);
|
||||
ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = SCCB_Read(sensor->slv_addr, reg);
|
||||
if(ret < 0){
|
||||
return ret;
|
||||
}
|
||||
uint8_t mask = ((1 << length) - 1) << offset;
|
||||
return (ret & mask) >> offset;
|
||||
}
|
||||
|
||||
|
||||
static int reset(sensor_t *sensor)
|
||||
{
|
||||
|
@ -176,6 +221,9 @@ static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
|
|||
static int set_framesize(sensor_t *sensor, framesize_t framesize)
|
||||
{
|
||||
int ret=0;
|
||||
if (framesize > FRAMESIZE_VGA) {
|
||||
return -1;
|
||||
}
|
||||
uint16_t w = resolution[framesize].width;
|
||||
uint16_t h = resolution[framesize].height;
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM7);
|
||||
|
@ -251,82 +299,208 @@ static int set_colorbar(sensor_t *sensor, int enable)
|
|||
|
||||
static int set_whitebal(sensor_t *sensor, int enable)
|
||||
{
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
sensor->status.awb = enable;
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AWB(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
if(set_reg_bits(sensor, COM8, 1, 1, enable) >= 0){
|
||||
sensor->status.awb = !!enable;
|
||||
}
|
||||
return sensor->status.awb;
|
||||
}
|
||||
|
||||
static int set_gain_ctrl(sensor_t *sensor, int enable)
|
||||
{
|
||||
sensor->status.agc = enable;
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AGC(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
if(set_reg_bits(sensor, COM8, 2, 1, enable) >= 0){
|
||||
sensor->status.agc = !!enable;
|
||||
}
|
||||
return sensor->status.agc;
|
||||
}
|
||||
|
||||
static int set_exposure_ctrl(sensor_t *sensor, int enable)
|
||||
{
|
||||
sensor->status.aec = enable;
|
||||
// Read register COM8
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM8);
|
||||
|
||||
// Set white bal on/off
|
||||
reg = COM8_SET_AEC(reg, enable);
|
||||
|
||||
// Write back register COM8
|
||||
return SCCB_Write(sensor->slv_addr, COM8, reg);
|
||||
if(set_reg_bits(sensor, COM8, 0, 1, enable) >= 0){
|
||||
sensor->status.aec = !!enable;
|
||||
}
|
||||
return sensor->status.aec;
|
||||
}
|
||||
|
||||
static int set_hmirror(sensor_t *sensor, int enable)
|
||||
{
|
||||
sensor->status.hmirror = enable;
|
||||
// Read register COM3
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM3);
|
||||
|
||||
// Set mirror on/off
|
||||
reg = COM3_SET_MIRROR(reg, enable);
|
||||
|
||||
// Write back register COM3
|
||||
return SCCB_Write(sensor->slv_addr, COM3, reg);
|
||||
if(set_reg_bits(sensor, COM3, 6, 1, enable) >= 0){
|
||||
sensor->status.hmirror = !!enable;
|
||||
}
|
||||
return sensor->status.hmirror;
|
||||
}
|
||||
|
||||
static int set_vflip(sensor_t *sensor, int enable)
|
||||
{
|
||||
sensor->status.vflip = enable;
|
||||
// Read register COM3
|
||||
uint8_t reg = SCCB_Read(sensor->slv_addr, COM3);
|
||||
if(set_reg_bits(sensor, COM3, 7, 1, enable) >= 0){
|
||||
sensor->status.vflip = !!enable;
|
||||
}
|
||||
return sensor->status.vflip;
|
||||
}
|
||||
|
||||
// Set mirror on/off
|
||||
reg = COM3_SET_FLIP(reg, enable);
|
||||
static int set_dcw_dsp(sensor_t *sensor, int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = set_reg_bits(sensor, 0x65, 2, 1, !enable);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set dcw to: %d", enable);
|
||||
sensor->status.dcw = enable;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Write back register COM3
|
||||
return SCCB_Write(sensor->slv_addr, COM3, reg);
|
||||
static int set_aec2(sensor_t *sensor, int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = set_reg_bits(sensor, COM8, 7, 1, enable);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set aec2 to: %d", enable);
|
||||
sensor->status.aec2 = enable;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_bpc_dsp(sensor_t *sensor, int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = set_reg_bits(sensor, 0x64, 1, 1, enable);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set bpc to: %d", enable);
|
||||
sensor->status.bpc = enable;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_wpc_dsp(sensor_t *sensor, int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = set_reg_bits(sensor, 0x64, 0, 1, enable);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set wpc to: %d", enable);
|
||||
sensor->status.wpc = enable;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_raw_gma_dsp(sensor_t *sensor, int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = set_reg_bits(sensor, 0x64, 2, 1, enable);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set raw_gma to: %d", enable);
|
||||
sensor->status.raw_gma = enable;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_lenc_dsp(sensor_t *sensor, int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = set_reg_bits(sensor, LC_CTR, 0, 1, enable);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set lenc to: %d", enable);
|
||||
sensor->status.lenc = enable;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//real gain
|
||||
static int set_agc_gain(sensor_t *sensor, int gain)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = set_reg_bits(sensor, COM9, 4, 3, gain % 5);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set gain to: %d", gain);
|
||||
sensor->status.agc_gain = gain;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_aec_value(sensor_t *sensor, int value)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = SCCB_Write(sensor->slv_addr, AEC, value & 0xff) | SCCB_Write(sensor->slv_addr, AECH, value >> 8);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set aec_value to: %d", value);
|
||||
sensor->status.aec_value = value;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_awb_gain_dsp(sensor_t *sensor, int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = set_reg_bits(sensor, 0x63, 7, 1, enable);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set awb_gain to: %d", enable);
|
||||
sensor->status.awb_gain = enable;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_brightness(sensor_t *sensor, int level)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = SCCB_Write(sensor->slv_addr, 0x9B, level);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set brightness to: %d", level);
|
||||
sensor->status.brightness = level;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_contrast(sensor_t *sensor, int level)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = SCCB_Write(sensor->slv_addr, 0x9C, level);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "Set contrast to: %d", level);
|
||||
sensor->status.contrast = level;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int init_status(sensor_t *sensor)
|
||||
{
|
||||
sensor->status.awb = 0;//get_reg_bits(sensor, BANK_DSP, CTRL1, 3, 1);
|
||||
sensor->status.aec = 0;
|
||||
sensor->status.agc = 0;
|
||||
sensor->status.hmirror = 0;
|
||||
sensor->status.vflip = 0;
|
||||
sensor->status.colorbar = 0;
|
||||
sensor->status.brightness = SCCB_Read(sensor->slv_addr, 0x9B);
|
||||
sensor->status.contrast = SCCB_Read(sensor->slv_addr, 0x9C);
|
||||
sensor->status.saturation = 0;
|
||||
sensor->status.ae_level = 0;
|
||||
sensor->status.special_effect = get_reg_bits(sensor, 0x64, 5, 1);
|
||||
sensor->status.wb_mode = get_reg_bits(sensor, 0x6B, 7, 1);
|
||||
sensor->status.agc_gain = get_reg_bits(sensor, COM9, 4, 3);
|
||||
sensor->status.aec_value = SCCB_Read(sensor->slv_addr, AEC) | (SCCB_Read(sensor->slv_addr, AECH) << 8);
|
||||
sensor->status.gainceiling = SCCB_Read(sensor->slv_addr, 0x00);
|
||||
sensor->status.awb = get_reg_bits(sensor, COM8, 1, 1);
|
||||
sensor->status.awb_gain = get_reg_bits(sensor, 0x63, 7, 1);
|
||||
sensor->status.aec = get_reg_bits(sensor, COM8, 0, 1);
|
||||
sensor->status.aec2 = get_reg_bits(sensor, COM8, 7, 1);
|
||||
sensor->status.agc = get_reg_bits(sensor, COM8, 2, 1);
|
||||
sensor->status.bpc = get_reg_bits(sensor, 0x64, 1, 1);
|
||||
sensor->status.wpc = get_reg_bits(sensor, 0x64, 0, 1);
|
||||
sensor->status.raw_gma = get_reg_bits(sensor, 0x64, 2, 1);
|
||||
sensor->status.lenc = get_reg_bits(sensor, LC_CTR, 0, 1);
|
||||
sensor->status.hmirror = get_reg_bits(sensor, COM3, 6, 1);
|
||||
sensor->status.vflip = get_reg_bits(sensor, COM3, 7, 1);
|
||||
sensor->status.dcw = get_reg_bits(sensor, 0x65, 2, 1);
|
||||
sensor->status.colorbar = get_reg_bits(sensor, COM3, 0, 1);
|
||||
sensor->status.sharpness = get_reg_bits(sensor, EDGE0, 0, 5);
|
||||
sensor->status.denoise = SCCB_Read(sensor->slv_addr, 0x8E);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_dummy(sensor_t *sensor, int val){ return -1; }
|
||||
static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; }
|
||||
static 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){return -1;}
|
||||
static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div){return -1;}
|
||||
|
||||
esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz);
|
||||
static int set_xclk(sensor_t *sensor, int timer, int xclk)
|
||||
{
|
||||
int ret = 0;
|
||||
sensor->xclk_freq_hz = xclk * 1000000U;
|
||||
ret = xclk_timer_conf(timer, sensor->xclk_freq_hz);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ov7725_init(sensor_t *sensor)
|
||||
{
|
||||
|
@ -342,34 +516,35 @@ int ov7725_init(sensor_t *sensor)
|
|||
sensor->set_hmirror = set_hmirror;
|
||||
sensor->set_vflip = set_vflip;
|
||||
|
||||
sensor->set_brightness = set_brightness;
|
||||
sensor->set_contrast = set_contrast;
|
||||
sensor->set_aec2 = set_aec2;
|
||||
sensor->set_aec_value = set_aec_value;
|
||||
sensor->set_awb_gain = set_awb_gain_dsp;
|
||||
sensor->set_agc_gain = set_agc_gain;
|
||||
sensor->set_dcw = set_dcw_dsp;
|
||||
sensor->set_bpc = set_bpc_dsp;
|
||||
sensor->set_wpc = set_wpc_dsp;
|
||||
sensor->set_raw_gma = set_raw_gma_dsp;
|
||||
sensor->set_lenc = set_lenc_dsp;
|
||||
|
||||
//not supported
|
||||
sensor->set_brightness= set_dummy;
|
||||
sensor->set_saturation= set_dummy;
|
||||
sensor->set_sharpness = set_dummy;
|
||||
sensor->set_denoise = set_dummy;
|
||||
sensor->set_quality = set_dummy;
|
||||
sensor->set_gainceiling = set_gainceiling_dummy;
|
||||
sensor->set_gain_ctrl = set_dummy;
|
||||
sensor->set_exposure_ctrl = set_dummy;
|
||||
sensor->set_hmirror = set_dummy;
|
||||
sensor->set_vflip = set_dummy;
|
||||
sensor->set_whitebal = set_dummy;
|
||||
sensor->set_aec2 = set_dummy;
|
||||
sensor->set_aec_value = set_dummy;
|
||||
sensor->set_special_effect = set_dummy;
|
||||
sensor->set_wb_mode = set_dummy;
|
||||
sensor->set_ae_level = set_dummy;
|
||||
sensor->set_dcw = set_dummy;
|
||||
sensor->set_bpc = set_dummy;
|
||||
sensor->set_wpc = set_dummy;
|
||||
sensor->set_awb_gain = set_dummy;
|
||||
sensor->set_agc_gain = set_dummy;
|
||||
sensor->set_raw_gma = set_dummy;
|
||||
sensor->set_lenc = set_dummy;
|
||||
sensor->set_sharpness = set_dummy;
|
||||
sensor->set_denoise = set_dummy;
|
||||
|
||||
|
||||
sensor->set_gainceiling = set_gainceiling_dummy;
|
||||
|
||||
|
||||
sensor->get_reg = get_reg;
|
||||
sensor->set_reg = set_reg;
|
||||
sensor->set_res_raw = set_res_raw;
|
||||
sensor->set_pll = _set_pll;
|
||||
sensor->set_xclk = set_xclk;
|
||||
|
||||
// Retrieve sensor's signature
|
||||
sensor->id.MIDH = SCCB_Read(sensor->slv_addr, REG_MIDH);
|
||||
sensor->id.MIDL = SCCB_Read(sensor->slv_addr, REG_MIDL);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include "sccb.h"
|
||||
|
@ -19,14 +20,11 @@
|
|||
static const char* TAG = "sccb";
|
||||
#endif
|
||||
|
||||
//#undef CONFIG_SCCB_HARDWARE_I2C
|
||||
|
||||
#define LITTLETOBIG(x) ((x<<8)|(x>>8))
|
||||
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
#include "driver/i2c.h"
|
||||
|
||||
#define SCCB_FREQ 200000 /*!< I2C master frequency*/
|
||||
#define SCCB_FREQ 100000 /*!< I2C master frequency*/
|
||||
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
|
||||
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
|
||||
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||
|
@ -39,16 +37,13 @@ const int SCCB_I2C_PORT = 1;
|
|||
const int SCCB_I2C_PORT = 0;
|
||||
#endif
|
||||
static uint8_t ESP_SLAVE_ADDR = 0x3c;
|
||||
#else
|
||||
#include "twi.h"
|
||||
#endif
|
||||
|
||||
int SCCB_Init(int pin_sda, int pin_scl)
|
||||
{
|
||||
ESP_LOGI(TAG, "pin_sda %d pin_scl %d\n", pin_sda, pin_scl);
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
//log_i("SCCB_Init start");
|
||||
i2c_config_t conf;
|
||||
memset(&conf, 0, sizeof(i2c_config_t));
|
||||
conf.mode = I2C_MODE_MASTER;
|
||||
conf.sda_io_num = pin_sda;
|
||||
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
|
@ -58,15 +53,11 @@ int SCCB_Init(int pin_sda, int pin_scl)
|
|||
|
||||
i2c_param_config(SCCB_I2C_PORT, &conf);
|
||||
i2c_driver_install(SCCB_I2C_PORT, conf.mode, 0, 0, 0);
|
||||
#else
|
||||
twi_init(pin_sda, pin_scl);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t SCCB_Probe()
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
uint8_t slave_addr = 0x0;
|
||||
while(slave_addr < 0x7f) {
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
@ -82,28 +73,10 @@ uint8_t SCCB_Probe()
|
|||
slave_addr++;
|
||||
}
|
||||
return ESP_SLAVE_ADDR;
|
||||
#else
|
||||
uint8_t reg = 0x00;
|
||||
uint8_t slv_addr = 0x00;
|
||||
|
||||
ESP_LOGI(TAG, "SCCB_Probe start");
|
||||
for (uint8_t i = 0; i < 127; i++) {
|
||||
if (twi_writeTo(i, ®, 1, true) == 0) {
|
||||
slv_addr = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i!=126) {
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS); // Necessary for OV7725 camera (not for OV2640).
|
||||
}
|
||||
}
|
||||
return slv_addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
uint8_t data=0;
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
@ -125,28 +98,10 @@ uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
|
|||
ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
|
||||
}
|
||||
return data;
|
||||
#else
|
||||
uint8_t data=0;
|
||||
|
||||
int rc = twi_writeTo(slv_addr, ®, 1, true);
|
||||
if (rc != 0) {
|
||||
data = 0xff;
|
||||
} else {
|
||||
rc = twi_readFrom(slv_addr, &data, 1, true);
|
||||
if (rc != 0) {
|
||||
data=0xFF;
|
||||
}
|
||||
}
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "SCCB_Read [%02x] failed rc=%d\n", reg, rc);
|
||||
}
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
|
@ -160,23 +115,10 @@ uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
|
|||
ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
|
||||
}
|
||||
return ret == ESP_OK ? 0 : -1;
|
||||
#else
|
||||
uint8_t ret=0;
|
||||
uint8_t buf[] = {reg, data};
|
||||
|
||||
if(twi_writeTo(slv_addr, buf, 2, true) != 0) {
|
||||
ret=0xFF;
|
||||
}
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "SCCB_Write [%02x]=%02x failed\n", reg, data);
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
|
||||
{
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
uint8_t data=0;
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
|
@ -201,32 +143,11 @@ uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
|
|||
ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data);
|
||||
}
|
||||
return data;
|
||||
#else
|
||||
uint8_t data=0;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
uint8_t *reg_u8 = (uint8_t *)®_htons;
|
||||
uint8_t buf[] = {reg_u8[0], reg_u8[1]};
|
||||
|
||||
int rc = twi_writeTo(slv_addr, buf, 2, true);
|
||||
if (rc != 0) {
|
||||
data = 0xff;
|
||||
} else {
|
||||
rc = twi_readFrom(slv_addr, &data, 1, true);
|
||||
if (rc != 0) {
|
||||
data=0xFF;
|
||||
}
|
||||
}
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "R [%04x] fail rc=%d\n", reg, rc);
|
||||
}
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data)
|
||||
{
|
||||
static uint16_t i = 0;
|
||||
#ifdef CONFIG_SCCB_HARDWARE_I2C
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
uint8_t *reg_u8 = (uint8_t *)®_htons;
|
||||
|
@ -243,18 +164,4 @@ uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data)
|
|||
ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++);
|
||||
}
|
||||
return ret == ESP_OK ? 0 : -1;
|
||||
#else
|
||||
uint8_t ret=0;
|
||||
uint16_t reg_htons = LITTLETOBIG(reg);
|
||||
uint8_t *reg_u8 = (uint8_t *)®_htons;
|
||||
uint8_t buf[] = {reg_u8[0], reg_u8[1], data};
|
||||
|
||||
if(twi_writeTo(slv_addr, buf, 3, true) != 0) {
|
||||
ret = 0xFF;
|
||||
}
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++);
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -11,11 +11,13 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define NT99141_PID (0x14)
|
||||
#define OV9650_PID (0x96)
|
||||
#define OV7725_PID (0x77)
|
||||
#define OV2640_PID (0x26)
|
||||
#define OV3660_PID (0x36)
|
||||
#define OV5640_PID (0x56)
|
||||
#define OV7670_PID (0x76)
|
||||
|
||||
typedef enum {
|
||||
PIXFORMAT_RGB565, // 2BPP/RGB565
|
||||
|
|
|
@ -20,6 +20,17 @@
|
|||
#include "sdkconfig.h"
|
||||
#include "esp_jpg_decode.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+
|
||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||
#include "esp32/spiram.h"
|
||||
#else
|
||||
#error Target CONFIG_IDF_TARGET is not supported
|
||||
#endif
|
||||
#else // ESP32 Before IDF 4.0
|
||||
#include "esp_spiram.h"
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
|
||||
#include "esp32-hal-log.h"
|
||||
#define TAG ""
|
||||
|
|
|
@ -35,4 +35,4 @@ uint8_t twi_readFrom(unsigned char address, unsigned char * buf, unsigned int le
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue