Browse Source
- Add sensor GC2145 GC0308 GC032A - Make xclk driver more standard - Update README.md - Add an option to adjust the DMA buffer size Co-authored-by: zhouli <zhouli@espressif.com>pull/296/head
41 changed files with 3502 additions and 278 deletions
@ -1,28 +0,0 @@
@@ -1,28 +0,0 @@
|
||||
#pragma once |
||||
|
||||
#include <stdint.h> |
||||
#include <stddef.h> |
||||
#include <stdbool.h> |
||||
#include "esp_err.h" |
||||
#include "esp_intr_alloc.h" |
||||
#include "freertos/FreeRTOS.h" |
||||
#include "freertos/semphr.h" |
||||
#include "freertos/task.h" |
||||
#include "esp_camera.h" |
||||
#include "sensor.h" |
||||
|
||||
#include "esp_system.h" |
||||
#if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+
|
||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||
#include "esp32/rom/lldesc.h" |
||||
#elif CONFIG_IDF_TARGET_ESP32S2 // ESP32-S2
|
||||
#include "esp32s2/rom/lldesc.h" |
||||
#elif CONFIG_IDF_TARGET_ESP32S3 // ESP32-S3
|
||||
#include "esp32s3/rom/lldesc.h" |
||||
#else |
||||
#error Target CONFIG_IDF_TARGET is not supported |
||||
#endif |
||||
#else // ESP32 Before IDF 4.0
|
||||
#include "rom/lldesc.h" |
||||
#endif |
||||
|
@ -0,0 +1,465 @@
@@ -0,0 +1,465 @@
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include "freertos/FreeRTOS.h" |
||||
#include "freertos/task.h" |
||||
#include "sccb.h" |
||||
#include "gc0308.h" |
||||
#include "gc0308_regs.h" |
||||
#include "gc0308_settings.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 = "gc0308"; |
||||
#endif |
||||
|
||||
#define H8(v) ((v)>>8) |
||||
#define L8(v) ((v)&0xff) |
||||
|
||||
//#define REG_DEBUG_ON
|
||||
|
||||
static int read_reg(uint8_t slv_addr, const uint16_t reg) |
||||
{ |
||||
int ret = SCCB_Read(slv_addr, reg); |
||||
#ifdef REG_DEBUG_ON |
||||
if (ret < 0) { |
||||
ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); |
||||
} |
||||
#endif |
||||
return ret; |
||||
} |
||||
|
||||
static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) |
||||
{ |
||||
int ret = 0; |
||||
#ifndef REG_DEBUG_ON |
||||
ret = SCCB_Write(slv_addr, reg, value); |
||||
#else |
||||
int old_value = read_reg(slv_addr, reg); |
||||
if (old_value < 0) { |
||||
return old_value; |
||||
} |
||||
if ((uint8_t)old_value != value) { |
||||
ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); |
||||
ret = SCCB_Write(slv_addr, reg, value); |
||||
} else { |
||||
ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); |
||||
ret = SCCB_Write(slv_addr, reg, value);//maybe not?
|
||||
} |
||||
if (ret < 0) { |
||||
ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); |
||||
} |
||||
#endif |
||||
return ret; |
||||
} |
||||
|
||||
static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) |
||||
{ |
||||
return (read_reg(slv_addr, reg) & mask) == mask; |
||||
} |
||||
|
||||
static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) |
||||
{ |
||||
int ret = 0; |
||||
uint8_t c_value, new_value; |
||||
ret = read_reg(slv_addr, reg); |
||||
if (ret < 0) { |
||||
return ret; |
||||
} |
||||
c_value = ret; |
||||
new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); |
||||
ret = write_reg(slv_addr, reg, new_value); |
||||
return ret; |
||||
} |
||||
|
||||
static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) |
||||
{ |
||||
int i = 0, ret = 0; |
||||
while (!ret && regs[i][0] != REGLIST_TAIL) { |
||||
if (regs[i][0] == REG_DLY) { |
||||
vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); |
||||
} else { |
||||
ret = write_reg(slv_addr, regs[i][0], regs[i][1]); |
||||
} |
||||
i++; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static void print_regs(uint8_t slv_addr) |
||||
{ |
||||
#ifdef DEBUG_PRINT_REG |
||||
ESP_LOGI(TAG, "REG list look ======================"); |
||||
for (size_t i = 0xf0; i <= 0xfe; i++) { |
||||
ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
ESP_LOGI(TAG, "\npage 0 ==="); |
||||
write_reg(slv_addr, 0xfe, 0x00); // page 0
|
||||
for (size_t i = 0x03; i <= 0xa2; i++) { |
||||
ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
|
||||
ESP_LOGI(TAG, "\npage 3 ==="); |
||||
write_reg(slv_addr, 0xfe, 0x03); // page 3
|
||||
for (size_t i = 0x01; i <= 0x43; i++) { |
||||
ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
static int reset(sensor_t *sensor) |
||||
{ |
||||
int ret = 0; |
||||
// Software Reset: clear all registers and reset them to their default values
|
||||
ret = write_reg(sensor->slv_addr, RESET_RELATED, 0xf0); |
||||
if (ret) { |
||||
ESP_LOGE(TAG, "Software Reset FAILED!"); |
||||
return ret; |
||||
} |
||||
vTaskDelay(100 / portTICK_PERIOD_MS); |
||||
ret = write_regs(sensor->slv_addr, gc0308_sensor_default_regs); |
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Camera defaults loaded"); |
||||
vTaskDelay(100 / portTICK_PERIOD_MS); |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
#ifdef CONFIG_IDF_TARGET_ESP32 |
||||
set_reg_bits(sensor->slv_addr, 0x28, 4, 0x07, 1); //frequency division for esp32, ensure pclk <= 15MHz
|
||||
#endif |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) |
||||
{ |
||||
int ret = 0; |
||||
|
||||
switch (pixformat) { |
||||
case PIXFORMAT_RGB565: |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret = set_reg_bits(sensor->slv_addr, 0x24, 0, 0x0f, 6); //RGB565
|
||||
break; |
||||
|
||||
case PIXFORMAT_YUV422: |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret = set_reg_bits(sensor->slv_addr, 0x24, 0, 0x0f, 2); //yuv422 Y Cb Y Cr
|
||||
break; |
||||
default: |
||||
ESP_LOGW(TAG, "unsupport format"); |
||||
ret = -1; |
||||
break; |
||||
} |
||||
|
||||
if (ret == 0) { |
||||
sensor->pixformat = pixformat; |
||||
ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_framesize(sensor_t *sensor, framesize_t framesize) |
||||
{ |
||||
int ret = 0; |
||||
if (framesize > FRAMESIZE_VGA) { |
||||
ESP_LOGW(TAG, "Invalid framesize: %u", framesize); |
||||
framesize = FRAMESIZE_VGA; |
||||
} |
||||
sensor->status.framesize = framesize; |
||||
uint16_t w = resolution[framesize].width; |
||||
uint16_t h = resolution[framesize].height; |
||||
uint16_t row_s = (resolution[FRAMESIZE_VGA].height - h) / 2; |
||||
uint16_t col_s = (resolution[FRAMESIZE_VGA].width - w) / 2; |
||||
|
||||
#if CONFIG_GC_SENSOR_SUBSAMPLE_MODE |
||||
struct subsample_cfg { |
||||
uint16_t ratio_numerator; |
||||
uint16_t ratio_denominator; |
||||
uint8_t reg0x54; |
||||
uint8_t reg0x56; |
||||
uint8_t reg0x57; |
||||
uint8_t reg0x58; |
||||
uint8_t reg0x59; |
||||
}; |
||||
const struct subsample_cfg subsample_cfgs[] = { // define some subsample ratio
|
||||
{84, 420, 0x55, 0x00, 0x00, 0x00, 0x00}, //1/5
|
||||
{105, 420, 0x44, 0x00, 0x00, 0x00, 0x00},//1/4
|
||||
{140, 420, 0x33, 0x00, 0x00, 0x00, 0x00},//1/3
|
||||
{210, 420, 0x22, 0x00, 0x00, 0x00, 0x00},//1/2
|
||||
{240, 420, 0x77, 0x02, 0x46, 0x02, 0x46},//4/7
|
||||
{252, 420, 0x55, 0x02, 0x04, 0x02, 0x04},//3/5
|
||||
{280, 420, 0x33, 0x02, 0x00, 0x02, 0x00},//2/3
|
||||
{420, 420, 0x11, 0x00, 0x00, 0x00, 0x00},//1/1
|
||||
}; |
||||
uint16_t win_w = 640; |
||||
uint16_t win_h = 480; |
||||
const struct subsample_cfg *cfg = NULL; |
||||
/**
|
||||
* Strategy: try to keep the maximum perspective |
||||
*/ |
||||
for (size_t i = 0; i < sizeof(subsample_cfgs) / sizeof(struct subsample_cfg); i++) { |
||||
cfg = &subsample_cfgs[i]; |
||||
if ((win_w * cfg->ratio_numerator / cfg->ratio_denominator >= w) && (win_h * cfg->ratio_numerator / cfg->ratio_denominator >= h)) { |
||||
win_w = w * cfg->ratio_denominator / cfg->ratio_numerator; |
||||
win_h = h * cfg->ratio_denominator / cfg->ratio_numerator; |
||||
row_s = (resolution[FRAMESIZE_VGA].height - win_h) / 2; |
||||
col_s = (resolution[FRAMESIZE_VGA].width - win_w) / 2; |
||||
ESP_LOGI(TAG, "subsample win:%dx%d, ratio:%f", win_w, win_h, (float)cfg->ratio_numerator / (float)cfg->ratio_denominator); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
|
||||
write_reg(sensor->slv_addr, 0x05, H8(row_s)); |
||||
write_reg(sensor->slv_addr, 0x06, L8(row_s)); |
||||
write_reg(sensor->slv_addr, 0x07, H8(col_s)); |
||||
write_reg(sensor->slv_addr, 0x08, L8(col_s)); |
||||
write_reg(sensor->slv_addr, 0x09, H8(win_h + 8)); |
||||
write_reg(sensor->slv_addr, 0x0a, L8(win_h + 8)); |
||||
write_reg(sensor->slv_addr, 0x0b, H8(win_w + 8)); |
||||
write_reg(sensor->slv_addr, 0x0c, L8(win_w + 8)); |
||||
|
||||
write_reg(sensor->slv_addr, 0xfe, 0x01); |
||||
set_reg_bits(sensor->slv_addr, 0x53, 7, 0x01, 1); |
||||
set_reg_bits(sensor->slv_addr, 0x55, 0, 0x01, 1); |
||||
write_reg(sensor->slv_addr, 0x54, cfg->reg0x54); |
||||
write_reg(sensor->slv_addr, 0x56, cfg->reg0x56); |
||||
write_reg(sensor->slv_addr, 0x57, cfg->reg0x57); |
||||
write_reg(sensor->slv_addr, 0x58, cfg->reg0x58); |
||||
write_reg(sensor->slv_addr, 0x59, cfg->reg0x59); |
||||
|
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
|
||||
#elif CONFIG_GC_SENSOR_WINDOWING_MODE |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
|
||||
write_reg(sensor->slv_addr, 0xf7, col_s / 4); |
||||
write_reg(sensor->slv_addr, 0xf8, row_s / 4); |
||||
write_reg(sensor->slv_addr, 0xf9, (col_s + h) / 4); |
||||
write_reg(sensor->slv_addr, 0xfa, (row_s + w) / 4); |
||||
|
||||
write_reg(sensor->slv_addr, 0x05, H8(row_s)); |
||||
write_reg(sensor->slv_addr, 0x06, L8(row_s)); |
||||
write_reg(sensor->slv_addr, 0x07, H8(col_s)); |
||||
write_reg(sensor->slv_addr, 0x08, L8(col_s)); |
||||
|
||||
write_reg(sensor->slv_addr, 0x09, H8(h + 8)); |
||||
write_reg(sensor->slv_addr, 0x0a, L8(h + 8)); |
||||
write_reg(sensor->slv_addr, 0x0b, H8(w + 8)); |
||||
write_reg(sensor->slv_addr, 0x0c, L8(w + 8)); |
||||
|
||||
#endif |
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static int set_contrast(sensor_t *sensor, int contrast) |
||||
{ |
||||
if (contrast != 0) { |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
write_reg(sensor->slv_addr, 0xb3, contrast); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static int set_global_gain(sensor_t *sensor, int gain_level) |
||||
{ |
||||
if (gain_level != 0) { |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
write_reg(sensor->slv_addr, 0x50, gain_level); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static int set_hmirror(sensor_t *sensor, int enable) |
||||
{ |
||||
int ret = 0; |
||||
sensor->status.hmirror = enable; |
||||
ret = write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret |= set_reg_bits(sensor->slv_addr, 0x14, 0, 0x01, enable != 0); |
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Set h-mirror to: %d", enable); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_vflip(sensor_t *sensor, int enable) |
||||
{ |
||||
int ret = 0; |
||||
sensor->status.vflip = enable; |
||||
ret = write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret |= set_reg_bits(sensor->slv_addr, 0x14, 1, 0x01, enable != 0); |
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Set v-flip to: %d", enable); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_colorbar(sensor_t *sensor, int enable) |
||||
{ |
||||
int ret = 0; |
||||
ret = write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret |= set_reg_bits(sensor->slv_addr, 0x2e, 0, 0x01, enable); |
||||
if (ret == 0) { |
||||
sensor->status.colorbar = enable; |
||||
ESP_LOGD(TAG, "Set colorbar to: %d", enable); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int get_reg(sensor_t *sensor, int reg, int mask) |
||||
{ |
||||
int ret = 0; |
||||
if (mask > 0xFF) { |
||||
ESP_LOGE(TAG, "mask should not more than 0xff"); |
||||
} else { |
||||
ret = read_reg(sensor->slv_addr, reg); |
||||
} |
||||
if (ret > 0) { |
||||
ret &= mask; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_reg(sensor_t *sensor, int reg, int mask, int value) |
||||
{ |
||||
int ret = 0; |
||||
if (mask > 0xFF) { |
||||
ESP_LOGE(TAG, "mask should not more than 0xff"); |
||||
} else { |
||||
ret = read_reg(sensor->slv_addr, reg); |
||||
} |
||||
if (ret < 0) { |
||||
return ret; |
||||
} |
||||
value = (ret & ~mask) | (value & mask); |
||||
|
||||
if (mask > 0xFF) { |
||||
|
||||
} else { |
||||
ret = write_reg(sensor->slv_addr, reg, value); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int init_status(sensor_t *sensor) |
||||
{ |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
sensor->status.brightness = 0; |
||||
sensor->status.contrast = 0; |
||||
sensor->status.saturation = 0; |
||||
sensor->status.sharpness = 0; |
||||
sensor->status.denoise = 0; |
||||
sensor->status.ae_level = 0; |
||||
sensor->status.gainceiling = 0; |
||||
sensor->status.awb = 0; |
||||
sensor->status.dcw = 0; |
||||
sensor->status.agc = 0; |
||||
sensor->status.aec = 0; |
||||
sensor->status.hmirror = check_reg_mask(sensor->slv_addr, 0x14, 0x01); |
||||
sensor->status.vflip = check_reg_mask(sensor->slv_addr, 0x14, 0x02); |
||||
sensor->status.colorbar = 0; |
||||
sensor->status.bpc = 0; |
||||
sensor->status.wpc = 0; |
||||
sensor->status.raw_gma = 0; |
||||
sensor->status.lenc = 0; |
||||
sensor->status.quality = 0; |
||||
sensor->status.special_effect = 0; |
||||
sensor->status.wb_mode = 0; |
||||
sensor->status.awb_gain = 0; |
||||
sensor->status.agc_gain = 0; |
||||
sensor->status.aec_value = 0; |
||||
sensor->status.aec2 = 0; |
||||
|
||||
print_regs(sensor->slv_addr); |
||||
return 0; |
||||
} |
||||
|
||||
static int set_dummy(sensor_t *sensor, int val) |
||||
{ |
||||
ESP_LOGW(TAG, "Unsupported"); |
||||
return -1; |
||||
} |
||||
static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) |
||||
{ |
||||
ESP_LOGW(TAG, "Unsupported"); |
||||
return -1; |
||||
} |
||||
|
||||
int gc0308_detect(int slv_addr, sensor_id_t *id) |
||||
{ |
||||
if (GC0308_SCCB_ADDR == slv_addr) { |
||||
write_reg(slv_addr, 0xfe, 0x00); |
||||
uint8_t PID = SCCB_Read(slv_addr, 0x00); |
||||
if (GC0308_PID == PID) { |
||||
id->PID = PID; |
||||
return PID; |
||||
} else { |
||||
ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int gc0308_init(sensor_t *sensor) |
||||
{ |
||||
sensor->init_status = init_status; |
||||
sensor->reset = reset; |
||||
sensor->set_pixformat = set_pixformat; |
||||
sensor->set_framesize = set_framesize; |
||||
sensor->set_contrast = set_contrast; |
||||
sensor->set_brightness = set_dummy; |
||||
sensor->set_saturation = set_dummy; |
||||
sensor->set_sharpness = set_dummy; |
||||
sensor->set_denoise = set_dummy; |
||||
sensor->set_gainceiling = set_gainceiling_dummy; |
||||
sensor->set_quality = set_dummy; |
||||
sensor->set_colorbar = set_colorbar; |
||||
sensor->set_whitebal = set_dummy; |
||||
sensor->set_gain_ctrl = set_global_gain; |
||||
sensor->set_exposure_ctrl = set_dummy; |
||||
sensor->set_hmirror = set_hmirror; |
||||
sensor->set_vflip = set_vflip; |
||||
|
||||
sensor->set_aec2 = set_dummy; |
||||
sensor->set_awb_gain = set_dummy; |
||||
sensor->set_agc_gain = 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_raw_gma = set_dummy; |
||||
sensor->set_lenc = set_dummy; |
||||
|
||||
sensor->get_reg = get_reg; |
||||
sensor->set_reg = set_reg; |
||||
sensor->set_res_raw = NULL; |
||||
sensor->set_pll = NULL; |
||||
sensor->set_xclk = NULL; |
||||
|
||||
ESP_LOGD(TAG, "GC0308 Attached"); |
||||
return 0; |
||||
} |
@ -0,0 +1,391 @@
@@ -0,0 +1,391 @@
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <stdio.h> |
||||
#include "freertos/FreeRTOS.h" |
||||
#include "freertos/task.h" |
||||
#include "sccb.h" |
||||
#include "gc032a.h" |
||||
#include "gc032a_regs.h" |
||||
#include "gc032a_settings.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 = "gc032a"; |
||||
#endif |
||||
|
||||
#define H8(v) ((v)>>8) |
||||
#define L8(v) ((v)&0xff) |
||||
|
||||
//#define REG_DEBUG_ON
|
||||
|
||||
static int read_reg(uint8_t slv_addr, const uint16_t reg) |
||||
{ |
||||
int ret = SCCB_Read(slv_addr, reg); |
||||
#ifdef REG_DEBUG_ON |
||||
if (ret < 0) { |
||||
ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); |
||||
} |
||||
#endif |
||||
return ret; |
||||
} |
||||
|
||||
static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) |
||||
{ |
||||
int ret = 0; |
||||
#ifndef REG_DEBUG_ON |
||||
ret = SCCB_Write(slv_addr, reg, value); |
||||
#else |
||||
int old_value = read_reg(slv_addr, reg); |
||||
if (old_value < 0) { |
||||
return old_value; |
||||
} |
||||
if ((uint8_t)old_value != value) { |
||||
ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); |
||||
ret = SCCB_Write(slv_addr, reg, value); |
||||
} else { |
||||
ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); |
||||
ret = SCCB_Write(slv_addr, reg, value);//maybe not?
|
||||
} |
||||
if (ret < 0) { |
||||
ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); |
||||
} |
||||
#endif |
||||
return ret; |
||||
} |
||||
|
||||
static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) |
||||
{ |
||||
return (read_reg(slv_addr, reg) & mask) == mask; |
||||
} |
||||
|
||||
static void print_regs(uint8_t slv_addr) |
||||
{ |
||||
#ifdef DEBUG_PRINT_REG |
||||
vTaskDelay(pdMS_TO_TICKS(100)); |
||||
ESP_LOGI(TAG, "REG list look ======================"); |
||||
for (size_t i = 0xf0; i <= 0xfe; i++) { |
||||
ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
ESP_LOGI(TAG, "\npage 0 ==="); |
||||
write_reg(slv_addr, 0xfe, 0x00); // page 0
|
||||
for (size_t i = 0x03; i <= 0x24; i++) { |
||||
ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
for (size_t i = 0x40; i <= 0x95; i++) { |
||||
ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
ESP_LOGI(TAG, "\npage 3 ==="); |
||||
write_reg(slv_addr, 0xfe, 0x03); // page 3
|
||||
for (size_t i = 0x01; i <= 0x43; i++) { |
||||
ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) |
||||
{ |
||||
int ret = 0; |
||||
uint8_t c_value, new_value; |
||||
ret = read_reg(slv_addr, reg); |
||||
if (ret < 0) { |
||||
return ret; |
||||
} |
||||
c_value = ret; |
||||
new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); |
||||
ret = write_reg(slv_addr, reg, new_value); |
||||
return ret; |
||||
} |
||||
|
||||
static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) |
||||
{ |
||||
int i = 0, ret = 0; |
||||
while (!ret && regs[i][0] != REGLIST_TAIL) { |
||||
if (regs[i][0] == REG_DLY) { |
||||
vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); |
||||
} else { |
||||
ret = write_reg(slv_addr, regs[i][0], regs[i][1]); |
||||
} |
||||
i++; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int reset(sensor_t *sensor) |
||||
{ |
||||
int ret; |
||||
// Software Reset: clear all registers and reset them to their default values
|
||||
ret = write_reg(sensor->slv_addr, RESET_RELATED, 0xf0); |
||||
if (ret) { |
||||
ESP_LOGE(TAG, "Software Reset FAILED!"); |
||||
return ret; |
||||
} |
||||
vTaskDelay(100 / portTICK_PERIOD_MS); |
||||
|
||||
ret = write_regs(sensor->slv_addr, gc032a_default_regs); |
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Camera defaults loaded"); |
||||
vTaskDelay(100 / portTICK_PERIOD_MS); |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
set_reg_bits(sensor->slv_addr, 0xf7, 1, 0x01, 1); // PLL_mode1:div2en
|
||||
set_reg_bits(sensor->slv_addr, 0xf7, 7, 0x01, 1); // PLL_mode1:dvp mode
|
||||
set_reg_bits(sensor->slv_addr, 0xf8, 0, 0x3f, 8); //PLL_mode2 :divx4
|
||||
set_reg_bits(sensor->slv_addr, 0xfa, 4, 0x0f, 2); //vlk div mode :divide_by
|
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) |
||||
{ |
||||
int ret = 0; |
||||
switch (pixformat) { |
||||
case PIXFORMAT_RGB565: |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret = set_reg_bits(sensor->slv_addr, 0x44, 0, 0x1f, 6); //RGB565
|
||||
break; |
||||
|
||||
case PIXFORMAT_YUV422: |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret = set_reg_bits(sensor->slv_addr, 0x44, 0, 0x1f, 3); |
||||
break; |
||||
default: |
||||
ESP_LOGW(TAG, "unsupport format"); |
||||
ret = -1; |
||||
break; |
||||
} |
||||
if (ret == 0) { |
||||
sensor->pixformat = pixformat; |
||||
ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static int set_framesize(sensor_t *sensor, framesize_t framesize) |
||||
{ |
||||
ESP_LOGI(TAG, "set_framesize"); |
||||
int ret = 0; |
||||
if (framesize > FRAMESIZE_VGA) { |
||||
ESP_LOGW(TAG, "Invalid framesize: %u", framesize); |
||||
framesize = FRAMESIZE_VGA; |
||||
} |
||||
sensor->status.framesize = framesize; |
||||
uint16_t w = resolution[framesize].width; |
||||
uint16_t h = resolution[framesize].height; |
||||
uint16_t row_s = (resolution[FRAMESIZE_VGA].height - h) / 2; |
||||
uint16_t col_s = (resolution[FRAMESIZE_VGA].width - w) / 2; |
||||
|
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
write_reg(sensor->slv_addr, P0_ROW_START_HIGH, H8(row_s)); // Row_start[8]
|
||||
write_reg(sensor->slv_addr, P0_ROW_START_LOW, L8(row_s)); // Row_start[7:0]
|
||||
write_reg(sensor->slv_addr, P0_COLUMN_START_HIGH, H8(col_s)); // Column_start[9:8]
|
||||
write_reg(sensor->slv_addr, P0_COLUMN_START_LOW, L8(col_s)); // Column_start[7:0]
|
||||
write_reg(sensor->slv_addr, P0_WINDOW_HEIGHT_HIGH, H8(h + 8)); //window_height [8]
|
||||
write_reg(sensor->slv_addr, P0_WINDOW_HEIGHT_LOW, L8(h + 8)); //window_height [7:0]
|
||||
write_reg(sensor->slv_addr, P0_WINDOW_WIDTH_HIGH, H8(w + 8)); //window_width [9:8]
|
||||
write_reg(sensor->slv_addr, P0_WINDOW_WIDTH_LOW, L8(w + 8)); //window_width [7:0]
|
||||
|
||||
write_reg(sensor->slv_addr, P0_WIN_MODE, 0x01); |
||||
write_reg(sensor->slv_addr, P0_OUT_WIN_HEIGHT_HIGH, H8(h)); |
||||
write_reg(sensor->slv_addr, P0_OUT_WIN_HEIGHT_LOW, L8(h)); |
||||
write_reg(sensor->slv_addr, P0_OUT_WIN_WIDTH_HIGH, H8(w)); |
||||
write_reg(sensor->slv_addr, P0_OUT_WIN_WIDTH_LOW, L8(w)); |
||||
|
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); |
||||
} |
||||
print_regs(sensor->slv_addr); |
||||
return ret; |
||||
} |
||||
|
||||
static int set_hmirror(sensor_t *sensor, int enable) |
||||
{ |
||||
int ret = 0; |
||||
sensor->status.hmirror = enable; |
||||
ret = write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret |= set_reg_bits(sensor->slv_addr, P0_CISCTL_MODE1, 0, 0x01, enable); |
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Set h-mirror to: %d", enable); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_vflip(sensor_t *sensor, int enable) |
||||
{ |
||||
int ret = 0; |
||||
sensor->status.vflip = enable; |
||||
ret = write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret |= set_reg_bits(sensor->slv_addr, P0_CISCTL_MODE1, 1, 0x01, enable); |
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Set v-flip to: %d", enable); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_colorbar(sensor_t *sensor, int enable) |
||||
{ |
||||
int ret = 0; |
||||
ret = write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret |= set_reg_bits(sensor->slv_addr, P0_DEBUG_MODE2, 3, 0x01, enable); |
||||
if (ret == 0) { |
||||
sensor->status.colorbar = enable; |
||||
ESP_LOGD(TAG, "Set colorbar to: %d", enable); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int get_reg(sensor_t *sensor, int reg, int mask) |
||||
{ |
||||
int ret = 0; |
||||
if (mask > 0xFF) { |
||||
ESP_LOGE(TAG, "mask should not more than 0xff"); |
||||
} else { |
||||
ret = read_reg(sensor->slv_addr, reg); |
||||
} |
||||
if (ret > 0) { |
||||
ret &= mask; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_reg(sensor_t *sensor, int reg, int mask, int value) |
||||
{ |
||||
int ret = 0; |
||||
if (mask > 0xFF) { |
||||
ESP_LOGE(TAG, "mask should not more than 0xff"); |
||||
} else { |
||||
ret = read_reg(sensor->slv_addr, reg); |
||||
} |
||||
if (ret < 0) { |
||||
return ret; |
||||
} |
||||
value = (ret & ~mask) | (value & mask); |
||||
|
||||
if (mask > 0xFF) { |
||||
|
||||
} else { |
||||
ret = write_reg(sensor->slv_addr, reg, value); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int init_status(sensor_t *sensor) |
||||
{ |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
sensor->status.brightness = 0; |
||||
sensor->status.contrast = 0; |
||||
sensor->status.saturation = 0; |
||||
sensor->status.sharpness = 0; |
||||
sensor->status.denoise = 0; |
||||
sensor->status.ae_level = 0; |
||||
sensor->status.gainceiling = 0; |
||||
sensor->status.awb = 0; |
||||
sensor->status.dcw = 0; |
||||
sensor->status.agc = 0; |
||||
sensor->status.aec = 0; |
||||
sensor->status.hmirror = check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x01); |
||||
sensor->status.vflip = check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x02); |
||||
sensor->status.colorbar = 0; |
||||
sensor->status.bpc = 0; |
||||
sensor->status.wpc = 0; |
||||
sensor->status.raw_gma = 0; |
||||
sensor->status.lenc = 0; |
||||
sensor->status.quality = 0; |
||||
sensor->status.special_effect = 0; |
||||
sensor->status.wb_mode = 0; |
||||
sensor->status.awb_gain = 0; |
||||
sensor->status.agc_gain = 0; |
||||
sensor->status.aec_value = 0; |
||||
sensor->status.aec2 = 0; |
||||
return 0; |
||||
} |
||||
|
||||
static int set_dummy(sensor_t *sensor, int val) |
||||
{ |
||||
ESP_LOGW(TAG, "Unsupported"); |
||||
return -1; |
||||
} |
||||
static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) |
||||
{ |
||||
ESP_LOGW(TAG, "Unsupported"); |
||||
return -1; |
||||
} |
||||
|
||||
int gc032a_detect(int slv_addr, sensor_id_t *id) |
||||
{ |
||||
if (GC032A_SCCB_ADDR == slv_addr) { |
||||
uint8_t MIDL = SCCB_Read(slv_addr, SENSOR_ID_LOW); |
||||
uint8_t MIDH = SCCB_Read(slv_addr, SENSOR_ID_HIGH); |
||||
uint16_t PID = MIDH << 8 | MIDL; |
||||
if (GC032A_PID == PID) { |
||||
id->PID = PID; |
||||
return PID; |
||||
} else { |
||||
ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int gc032a_init(sensor_t *sensor) |
||||
{ |
||||
sensor->init_status = init_status; |
||||
sensor->reset = reset; |
||||
sensor->set_pixformat = set_pixformat; |
||||
sensor->set_framesize = set_framesize; |
||||
sensor->set_contrast = set_dummy; |
||||
sensor->set_brightness = set_dummy; |
||||
sensor->set_saturation = set_dummy; |
||||
sensor->set_sharpness = set_dummy; |
||||
sensor->set_denoise = set_dummy; |
||||
sensor->set_gainceiling = set_gainceiling_dummy; |
||||
sensor->set_quality = set_dummy; |
||||
sensor->set_colorbar = set_colorbar; |
||||
sensor->set_whitebal = set_dummy; |
||||
sensor->set_gain_ctrl = set_dummy; |
||||
sensor->set_exposure_ctrl = set_dummy; |
||||
sensor->set_hmirror = set_hmirror; |
||||
sensor->set_vflip = set_vflip; |
||||
|
||||
sensor->set_aec2 = set_dummy; |
||||
sensor->set_awb_gain = set_dummy; |
||||
sensor->set_agc_gain = 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_raw_gma = set_dummy; |
||||
sensor->set_lenc = set_dummy; |
||||
|
||||
sensor->get_reg = get_reg; |
||||
sensor->set_reg = set_reg; |
||||
sensor->set_res_raw = NULL; |
||||
sensor->set_pll = NULL; |
||||
sensor->set_xclk = NULL; |
||||
|
||||
ESP_LOGD(TAG, "GC032A Attached"); |
||||
return 0; |
||||
} |
@ -0,0 +1,475 @@
@@ -0,0 +1,475 @@
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include "freertos/FreeRTOS.h" |
||||
#include "freertos/task.h" |
||||
#include "sccb.h" |
||||
#include "gc2145.h" |
||||
#include "gc2145_regs.h" |
||||
#include "gc2145_settings.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 = "gc2145"; |
||||
#endif |
||||
|
||||
#define H8(v) ((v)>>8) |
||||
#define L8(v) ((v)&0xff) |
||||
|
||||
//#define REG_DEBUG_ON
|
||||
|
||||
static int read_reg(uint8_t slv_addr, const uint16_t reg) |
||||
{ |
||||
int ret = SCCB_Read(slv_addr, reg); |
||||
#ifdef REG_DEBUG_ON |
||||
if (ret < 0) { |
||||
ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); |
||||
} |
||||
#endif |
||||
return ret; |
||||
} |
||||
|
||||
static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) |
||||
{ |
||||
int ret = 0; |
||||
#ifndef REG_DEBUG_ON |
||||
ret = SCCB_Write(slv_addr, reg, value); |
||||
#else |
||||
int old_value = read_reg(slv_addr, reg); |
||||
if (old_value < 0) { |
||||
return old_value; |
||||
} |
||||
if ((uint8_t)old_value != value) { |
||||
ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); |
||||
ret = SCCB_Write(slv_addr, reg, value); |
||||
} else { |
||||
ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); |
||||
ret = SCCB_Write(slv_addr, reg, value);//maybe not?
|
||||
} |
||||
if (ret < 0) { |
||||
ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); |
||||
} |
||||
#endif |
||||
return ret; |
||||
} |
||||
|
||||
static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) |
||||
{ |
||||
return (read_reg(slv_addr, reg) & mask) == mask; |
||||
} |
||||
|
||||
static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) |
||||
{ |
||||
int ret = 0; |
||||
uint8_t c_value, new_value; |
||||
ret = read_reg(slv_addr, reg); |
||||
if (ret < 0) { |
||||
return ret; |
||||
} |
||||
c_value = ret; |
||||
new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); |
||||
ret = write_reg(slv_addr, reg, new_value); |
||||
return ret; |
||||
} |
||||
|
||||
static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) |
||||
{ |
||||
int i = 0, ret = 0; |
||||
while (!ret && regs[i][0] != REGLIST_TAIL) { |
||||
if (regs[i][0] == REG_DLY) { |
||||
vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); |
||||
} else { |
||||
ret = write_reg(slv_addr, regs[i][0], regs[i][1]); |
||||
} |
||||
i++; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static void print_regs(uint8_t slv_addr) |
||||
{ |
||||
#ifdef DEBUG_PRINT_REG |
||||
vTaskDelay(pdMS_TO_TICKS(100)); |
||||
ESP_LOGI(TAG, "REG list look ======================"); |
||||
for (size_t i = 0xf0; i <= 0xfe; i++) { |
||||
ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
ESP_LOGI(TAG, "\npage 0 ==="); |
||||
write_reg(slv_addr, 0xfe, 0x00); // page 0
|
||||
for (size_t i = 0x03; i <= 0x24; i++) { |
||||
ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
for (size_t i = 0x80; i <= 0xa2; i++) { |
||||
ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
ESP_LOGI(TAG, "\npage 3 ==="); |
||||
write_reg(slv_addr, 0xfe, 0x03); // page 3
|
||||
for (size_t i = 0x01; i <= 0x43; i++) { |
||||
ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
static int reset(sensor_t *sensor) |
||||
{ |
||||
int ret = 0; |
||||
// Software Reset: clear all registers and reset them to their default values
|
||||
ret = write_reg(sensor->slv_addr, RESET_RELATED, 0xe0); |
||||
if (ret) { |
||||
ESP_LOGE(TAG, "Software Reset FAILED!"); |
||||
return ret; |
||||
} |
||||
vTaskDelay(100 / portTICK_PERIOD_MS); |
||||
ret = write_regs(sensor->slv_addr, gc2145_default_init_regs); |
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Camera defaults loaded"); |
||||
vTaskDelay(100 / portTICK_PERIOD_MS); |
||||
#ifdef CONFIG_IDF_TARGET_ESP32 |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
//ensure pclk <= 15MHz for esp32
|
||||
set_reg_bits(sensor->slv_addr, 0xf8, 0, 0x3f, 2); // divx4
|
||||
set_reg_bits(sensor->slv_addr, 0xfa, 4, 0x0f, 2); // divide_by
|
||||
#endif |
||||
|
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) |
||||
{ |
||||
int ret = 0; |
||||
|
||||
switch (pixformat) { |
||||
case PIXFORMAT_RGB565: |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret = set_reg_bits(sensor->slv_addr, P0_OUTPUT_FORMAT, 0, 0x1f, 6); //RGB565
|
||||
break; |
||||
|
||||
case PIXFORMAT_YUV422: |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret = set_reg_bits(sensor->slv_addr, P0_OUTPUT_FORMAT, 0, 0x1f, 2); //yuv422
|
||||
break; |
||||
default: |
||||
ESP_LOGW(TAG, "unsupport format"); |
||||
ret = -1; |
||||
break; |
||||
} |
||||
|
||||
if (ret == 0) { |
||||
sensor->pixformat = pixformat; |
||||
ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_framesize(sensor_t *sensor, framesize_t framesize) |
||||
{ |
||||
int ret = 0; |
||||
if (framesize > FRAMESIZE_UXGA) { |
||||
ESP_LOGW(TAG, "Invalid framesize: %u", framesize); |
||||
framesize = FRAMESIZE_UXGA; |
||||
} |
||||
sensor->status.framesize = framesize; |
||||
uint16_t w = resolution[framesize].width; |
||||
uint16_t h = resolution[framesize].height; |
||||
uint16_t row_s = (resolution[FRAMESIZE_UXGA].height - h) / 2; |
||||
uint16_t col_s = (resolution[FRAMESIZE_UXGA].width - w) / 2; |
||||
|
||||
#if CONFIG_GC_SENSOR_SUBSAMPLE_MODE |
||||
struct subsample_cfg { |
||||
uint16_t ratio_numerator; |
||||
uint16_t ratio_denominator; |
||||
uint8_t reg0x99; |
||||
uint8_t reg0x9b; |
||||
uint8_t reg0x9c; |
||||
uint8_t reg0x9d; |
||||
uint8_t reg0x9e; |
||||
uint8_t reg0x9f; |
||||
uint8_t reg0xa0; |
||||
uint8_t reg0xa1; |
||||
uint8_t reg0xa2; |
||||
}; |
||||
const struct subsample_cfg subsample_cfgs[] = { // define some subsample ratio
|
||||
// {60, 420, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //1/7 // A smaller ratio brings a larger view, but it reduces the frame rate
|
||||
// {84, 420, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //1/5
|
||||
// {105, 420, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/4
|
||||
{140, 420, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/3
|
||||
{210, 420, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/2
|
||||
{240, 420, 0x77, 0x02, 0x46, 0x02, 0x46, 0x02, 0x46, 0x02, 0x46},//4/7
|
||||
{252, 420, 0x55, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04},//3/5
|
||||
{280, 420, 0x33, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00},//2/3
|
||||
{420, 420, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/1
|
||||
}; |
||||
uint16_t win_w = resolution[FRAMESIZE_UXGA].width; |
||||
uint16_t win_h = resolution[FRAMESIZE_UXGA].height; |
||||
const struct subsample_cfg *cfg = NULL; |
||||
/**
|
||||
* Strategy: try to keep the maximum perspective |
||||
*/ |
||||
uint8_t i = 0; |
||||
if (framesize >= FRAMESIZE_QVGA) { |
||||
i = 1; |
||||
} |
||||
for (; i < sizeof(subsample_cfgs) / sizeof(struct subsample_cfg); i++) { |
||||
cfg = &subsample_cfgs[i]; |
||||
if ((win_w * cfg->ratio_numerator / cfg->ratio_denominator >= w) && (win_h * cfg->ratio_numerator / cfg->ratio_denominator >= h)) { |
||||
win_w = w * cfg->ratio_denominator / cfg->ratio_numerator; |
||||
win_h = h * cfg->ratio_denominator / cfg->ratio_numerator; |
||||
row_s = (resolution[FRAMESIZE_UXGA].height - win_h) / 2; |
||||
col_s = (resolution[FRAMESIZE_UXGA].width - win_w) / 2; |
||||
ESP_LOGI(TAG, "subsample win:%dx%d, ratio:%f", win_w, win_h, (float)cfg->ratio_numerator / (float)cfg->ratio_denominator); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
write_reg(sensor->slv_addr, P0_CROP_ENABLE, 0x01); |
||||
write_reg(sensor->slv_addr, 0x09, H8(row_s)); |
||||
write_reg(sensor->slv_addr, 0x0a, L8(row_s)); |
||||
write_reg(sensor->slv_addr, 0x0b, H8(col_s)); |
||||
write_reg(sensor->slv_addr, 0x0c, L8(col_s)); |
||||
write_reg(sensor->slv_addr, 0x0d, H8(win_h + 8)); |
||||
write_reg(sensor->slv_addr, 0x0e, L8(win_h + 8)); |
||||
write_reg(sensor->slv_addr, 0x0f, H8(win_w + 16)); |
||||
write_reg(sensor->slv_addr, 0x10, L8(win_w + 16)); |
||||
|
||||
write_reg(sensor->slv_addr, 0x99, cfg->reg0x99); |
||||
write_reg(sensor->slv_addr, 0x9b, cfg->reg0x9b); |
||||
write_reg(sensor->slv_addr, 0x9c, cfg->reg0x9c); |
||||
write_reg(sensor->slv_addr, 0x9d, cfg->reg0x9d); |
||||
write_reg(sensor->slv_addr, 0x9e, cfg->reg0x9e); |
||||
write_reg(sensor->slv_addr, 0x9f, cfg->reg0x9f); |
||||
write_reg(sensor->slv_addr, 0xa0, cfg->reg0xa0); |
||||
write_reg(sensor->slv_addr, 0xa1, cfg->reg0xa1); |
||||
write_reg(sensor->slv_addr, 0xa2, cfg->reg0xa2); |
||||
|
||||
write_reg(sensor->slv_addr, 0x95, H8(h)); |
||||
write_reg(sensor->slv_addr, 0x96, L8(h)); |
||||
write_reg(sensor->slv_addr, 0x97, H8(w)); |
||||
write_reg(sensor->slv_addr, 0x98, L8(w)); |
||||
|
||||
|
||||
#elif CONFIG_GC_SENSOR_WINDOWING_MODE |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
|
||||
write_reg(sensor->slv_addr, P0_CROP_ENABLE, 0x01); |
||||
// write_reg(sensor->slv_addr, 0xec, col_s / 8); //measure window
|
||||
// write_reg(sensor->slv_addr, 0xed, row_s / 8);
|
||||
// write_reg(sensor->slv_addr, 0xee, (col_s + h) / 8);
|
||||
// write_reg(sensor->slv_addr, 0xef, (row_s + w) / 8);
|
||||
|
||||
write_reg(sensor->slv_addr, 0x09, H8(row_s)); |
||||
write_reg(sensor->slv_addr, 0x0a, L8(row_s)); |
||||
write_reg(sensor->slv_addr, 0x0b, H8(col_s)); |
||||
write_reg(sensor->slv_addr, 0x0c, L8(col_s)); |
||||
write_reg(sensor->slv_addr, 0x0d, H8(h + 8)); |
||||
write_reg(sensor->slv_addr, 0x0e, L8(h + 8)); |
||||
write_reg(sensor->slv_addr, 0x0f, H8(w + 8)); |
||||
write_reg(sensor->slv_addr, 0x10, L8(w + 8)); |
||||
|
||||
write_reg(sensor->slv_addr, 0x95, H8(h)); |
||||
write_reg(sensor->slv_addr, 0x96, L8(h)); |
||||
write_reg(sensor->slv_addr, 0x97, H8(w)); |
||||
write_reg(sensor->slv_addr, 0x98, L8(w)); |
||||
|
||||
#endif |
||||
|
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); |
||||
} |
||||
return ret; |
||||
|
||||
} |
||||
|
||||
static int set_hmirror(sensor_t *sensor, int enable) |
||||
{ |
||||
int ret = 0; |
||||
sensor->status.hmirror = enable; |
||||
ret = write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret |= set_reg_bits(sensor->slv_addr, P0_ANALOG_MODE1, 0, 0x01, enable != 0); |
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Set h-mirror to: %d", enable); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_vflip(sensor_t *sensor, int enable) |
||||
{ |
||||
int ret = 0; |
||||
sensor->status.vflip = enable; |
||||
ret = write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
ret |= set_reg_bits(sensor->slv_addr, P0_ANALOG_MODE1, 1, 0x01, enable != 0); |
||||
if (ret == 0) { |
||||
ESP_LOGD(TAG, "Set v-flip to: %d", enable); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_colorbar(sensor_t *sensor, int enable) |
||||
{ |
||||
int ret = 0; |
||||
// ret = write_reg(sensor->slv_addr, 0xfe, 0x00);
|
||||
// ret |= set_reg_bits(sensor->slv_addr, P0_DEBUG_MODE3, 3, 0x01, enable);
|
||||
if (ret == 0) { |
||||
sensor->status.colorbar = enable; |
||||
ESP_LOGD(TAG, "Set colorbar to: %d", enable); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int get_reg(sensor_t *sensor, int reg, int mask) |
||||
{ |
||||
int ret = 0; |
||||
if (mask > 0xFF) { |
||||
ESP_LOGE(TAG, "mask should not more than 0xff"); |
||||
} else { |
||||
ret = read_reg(sensor->slv_addr, reg); |
||||
} |
||||
if (ret > 0) { |
||||
ret &= mask; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int set_reg(sensor_t *sensor, int reg, int mask, int value) |
||||
{ |
||||
int ret = 0; |
||||
if (mask > 0xFF) { |
||||
ESP_LOGE(TAG, "mask should not more than 0xff"); |
||||
} else { |
||||
ret = read_reg(sensor->slv_addr, reg); |
||||
} |
||||
if (ret < 0) { |
||||
return ret; |
||||
} |
||||
value = (ret & ~mask) | (value & mask); |
||||
|
||||
if (mask > 0xFF) { |
||||
|
||||
} else { |
||||
ret = write_reg(sensor->slv_addr, reg, value); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static int init_status(sensor_t *sensor) |
||||
{ |
||||
write_reg(sensor->slv_addr, 0xfe, 0x00); |
||||
sensor->status.brightness = 0; |
||||
sensor->status.contrast = 0; |
||||
sensor->status.saturation = 0; |
||||
sensor->status.sharpness = 0; |
||||
sensor->status.denoise = 0; |
||||
sensor->status.ae_level = 0; |
||||
sensor->status.gainceiling = 0; |
||||
sensor->status.awb = 0; |
||||
sensor->status.dcw = 0; |
||||
sensor->status.agc = 0; |
||||
sensor->status.aec = 0; |
||||
sensor->status.hmirror = check_reg_mask(sensor->slv_addr, P0_ANALOG_MODE1, 0x01); |
||||
sensor->status.vflip = check_reg_mask(sensor->slv_addr, P0_ANALOG_MODE1, 0x02); |
||||
sensor->status.colorbar = 0; |
||||
sensor->status.bpc = 0; |
||||
sensor->status.wpc = 0; |
||||
sensor->status.raw_gma = 0; |
||||
sensor->status.lenc = 0; |
||||
sensor->status.quality = 0; |
||||
sensor->status.special_effect = 0; |
||||
sensor->status.wb_mode = 0; |
||||
sensor->status.awb_gain = 0; |
||||
sensor->status.agc_gain = 0; |
||||
sensor->status.aec_value = 0; |
||||
sensor->status.aec2 = 0; |
||||
|
||||
print_regs(sensor->slv_addr); |
||||
return 0; |
||||
} |
||||
|
||||
static int set_dummy(sensor_t *sensor, int val) |
||||
{ |
||||
ESP_LOGW(TAG, "Unsupported"); |
||||
return -1; |
||||
} |
||||
static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) |
||||
{ |
||||
ESP_LOGW(TAG, "Unsupported"); |
||||
return -1; |
||||
} |
||||
|
||||
int gc2145_detect(int slv_addr, sensor_id_t *id) |
||||
{ |
||||
if (GC2145_SCCB_ADDR == slv_addr) { |
||||
uint8_t MIDL = SCCB_Read(slv_addr, CHIP_ID_LOW); |
||||
uint8_t MIDH = SCCB_Read(slv_addr, CHIP_ID_HIGH); |
||||
uint16_t PID = MIDH << 8 | MIDL; |
||||
if (GC2145_PID == PID) { |
||||
id->PID = PID; |
||||
return PID; |
||||
} else { |
||||
ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int gc2145_init(sensor_t *sensor) |
||||
{ |
||||
sensor->init_status = init_status; |
||||
sensor->reset = reset; |
||||
sensor->set_pixformat = set_pixformat; |
||||
sensor->set_framesize = set_framesize; |
||||
sensor->set_contrast = set_dummy; |
||||
sensor->set_brightness = set_dummy; |
||||
sensor->set_saturation = set_dummy; |
||||
sensor->set_sharpness = set_dummy; |
||||
sensor->set_denoise = set_dummy; |
||||
sensor->set_gainceiling = set_gainceiling_dummy; |
||||
sensor->set_quality = set_dummy; |
||||
sensor->set_colorbar = set_colorbar; |
||||
sensor->set_whitebal = set_dummy; |
||||
sensor->set_gain_ctrl = set_dummy; |
||||
sensor->set_exposure_ctrl = set_dummy; |
||||
sensor->set_hmirror = set_hmirror; |
||||
sensor->set_vflip = set_vflip; |
||||
|
||||
sensor->set_aec2 = set_dummy; |
||||
sensor->set_awb_gain = set_dummy; |
||||
sensor->set_agc_gain = 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_raw_gma = set_dummy; |
||||
sensor->set_lenc = set_dummy; |
||||
|
||||
sensor->get_reg = get_reg; |
||||
sensor->set_reg = set_reg; |
||||
sensor->set_res_raw = NULL; |
||||
sensor->set_pll = NULL; |
||||
sensor->set_xclk = NULL; |
||||
|
||||
ESP_LOGD(TAG, "GC2145 Attached"); |
||||
return 0; |
||||
} |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
#pragma once |
||||
|
||||
#include "sensor.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Detect sensor pid |
||||
* |
||||
* @param slv_addr SCCB address |
||||
* @param id Detection result |
||||
* @return |
||||
* 0: Can't detect this sensor |
||||
* Nonzero: This sensor has been detected |
||||
*/ |
||||
int gc0308_detect(int slv_addr, sensor_id_t *id); |
||||
|
||||
/**
|
||||
* @brief initialize sensor function pointers |
||||
* |
||||
* @param sensor pointer of sensor |
||||
* @return |
||||
* Always 0 |
||||
*/ |
||||
int gc0308_init(sensor_t *sensor); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* GC0308 register definitions. |
||||
*/ |
||||
#ifndef __GC0308_REG_REGS_H__ |
||||
#define __GC0308_REG_REGS_H__ |
||||
|
||||
#define RESET_RELATED 0xfe // Bit[7]: Software reset
|
||||
// Bit[6:5]: NA
|
||||
// Bit[4]: CISCTL_restart_n
|
||||
// Bit[3:1]: NA
|
||||
// Bit[0]: page select
|
||||
// 0:page0
|
||||
// 1:page1
|
||||
|
||||
|
||||
// page0:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief register value |
||||
*/ |
||||
|
||||
|
||||
#endif // __GC0308_REG_REGS_H__
|
@ -0,0 +1,245 @@
@@ -0,0 +1,245 @@
|
||||
#ifndef _GC0308_SETTINGS_H_ |
||||
#define _GC0308_SETTINGS_H_ |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#define REG_DLY 0xffff |
||||
#define REGLIST_TAIL 0x0000 /* Array end token */ |
||||
|
||||
static const uint16_t gc0308_sensor_default_regs[][2] = { |
||||
{0xfe, 0x00}, |
||||
{0xec, 0x20}, |
||||
{0x05, 0x00}, |
||||
{0x06, 0x00}, |
||||
{0x07, 0x00}, |
||||
{0x08, 0x00}, |
||||
{0x09, 0x01}, |
||||
{0x0a, 0xe8}, |
||||
{0x0b, 0x02}, |
||||
{0x0c, 0x88}, |
||||
{0x0d, 0x02}, |
||||
{0x0e, 0x02}, |
||||
{0x10, 0x26}, |
||||
{0x11, 0x0d}, |
||||
{0x12, 0x2a}, |
||||
{0x13, 0x00}, |
||||
{0x14, 0x11}, |
||||
{0x15, 0x0a}, |
||||
{0x16, 0x05}, |
||||
{0x17, 0x01}, |
||||
{0x18, 0x44}, |
||||
{0x19, 0x44}, |
||||
{0x1a, 0x2a}, |
||||
{0x1b, 0x00}, |
||||
{0x1c, 0x49}, |
||||
{0x1d, 0x9a}, |
||||
{0x1e, 0x61}, |
||||
{0x1f, 0x00}, //pad drv <=24MHz, use 0x00 is ok
|
||||
{0x20, 0x7f}, |
||||
{0x21, 0xfa}, |
||||
{0x22, 0x57}, |
||||
{0x24, 0xa2}, //YCbYCr
|
||||
{0x25, 0x0f}, |
||||
{0x26, 0x03}, // 0x01
|
||||
{0x28, 0x00}, |
||||
{0x2d, 0x0a}, |
||||
{0x2f, 0x01}, |
||||
{0x30, 0xf7}, |
||||
{0x31, 0x50}, |
||||
{0x32, 0x00}, |
||||
{0x33, 0x28}, |
||||
{0x34, 0x2a}, |
||||
{0x35, 0x28}, |
||||
{0x39, 0x04}, |
||||
{0x3a, 0x20}, |
||||
{0x3b, 0x20}, |
||||
{0x3c, 0x00}, |
||||
{0x3d, 0x00}, |
||||
{0x3e, 0x00}, |
||||
{0x3f, 0x00}, |
||||
{0x50, 0x14}, // 0x14
|
||||
{0x52, 0x41}, |
||||
{0x53, 0x80}, |
||||
{0x54, 0x80}, |
||||
{0x55, 0x80}, |
||||
{0x56, 0x80}, |
||||
{0x8b, 0x20}, |
||||
{0x8c, 0x20}, |
||||
{0x8d, 0x20}, |
||||
{0x8e, 0x14}, |
||||
{0x8f, 0x10}, |
||||
{0x90, 0x14}, |
||||
{0x91, 0x3c}, |
||||
{0x92, 0x50}, |
||||
//{0x8b,0x10},
|
||||
//{0x8c,0x10},
|
||||
//{0x8d,0x10},
|
||||
//{0x8e,0x10},
|
||||
//{0x8f,0x10},
|
||||
//{0x90,0x10},
|
||||
//{0x91,0x3c},
|
||||
//{0x92,0x50},
|
||||
{0x5d, 0x12}, |
||||
{0x5e, 0x1a}, |
||||
{0x5f, 0x24}, |
||||
{0x60, 0x07}, |
||||
{0x61, 0x15}, |
||||
{0x62, 0x08}, // 0x08
|
||||
{0x64, 0x03}, // 0x03
|
||||
{0x66, 0xe8}, |
||||
{0x67, 0x86}, |
||||
{0x68, 0x82}, |
||||
{0x69, 0x18}, |
||||
{0x6a, 0x0f}, |
||||
{0x6b, 0x00}, |
||||
{0x6c, 0x5f}, |
||||
{0x6d, 0x8f}, |
||||
{0x6e, 0x55}, |
||||
{0x6f, 0x38}, |
||||
{0x70, 0x15}, |
||||
{0x71, 0x33}, |
||||
{0x72, 0xdc}, |
||||
{0x73, 0x00}, |
||||
{0x74, 0x02}, |
||||
{0x75, 0x3f}, |
||||
{0x76, 0x02}, |
||||
{0x77, 0x38}, // 0x47
|
||||
{0x78, 0x88}, |
||||
{0x79, 0x81}, |
||||
{0x7a, 0x81}, |
||||
{0x7b, 0x22}, |
||||
{0x7c, 0xff}, |
||||
{0x93, 0x48}, //color matrix default
|
||||
{0x94, 0x02}, |
||||
{0x95, 0x07}, |
||||
{0x96, 0xe0}, |
||||
{0x97, 0x40}, |
||||
{0x98, 0xf0}, |
||||
{0xb1, 0x40}, |
||||
{0xb2, 0x40}, |
||||
{0xb3, 0x40}, //0x40
|
||||
{0xb6, 0xe0}, |
||||
{0xbd, 0x38}, |
||||
{0xbe, 0x36}, |
||||
{0xd0, 0xCB}, |
||||
{0xd1, 0x10}, |
||||
{0xd2, 0x90}, |
||||
{0xd3, 0x48}, |
||||
{0xd5, 0xF2}, |
||||
{0xd6, 0x16}, |
||||
{0xdb, 0x92}, |
||||
{0xdc, 0xA5}, |
||||
{0xdf, 0x23}, |
||||
{0xd9, 0x00}, |
||||
{0xda, 0x00}, |
||||
{0xe0, 0x09}, |
||||
{0xed, 0x04}, |
||||
{0xee, 0xa0}, |
||||
{0xef, 0x40}, |
||||
{0x80, 0x03}, |
||||
|
||||
{0x9F, 0x10}, |
||||
{0xA0, 0x20}, |
||||
{0xA1, 0x38}, |
||||
{0xA2, 0x4e}, |
||||
{0xA3, 0x63}, |
||||
{0xA4, 0x76}, |
||||
{0xA5, 0x87}, |
||||
{0xA6, 0xa2}, |
||||
{0xA7, 0xb8}, |
||||
{0xA8, 0xca}, |
||||
{0xA9, 0xd8}, |
||||
{0xAA, 0xe3}, |
||||
{0xAB, 0xeb}, |
||||
{0xAC, 0xf0}, |
||||
{0xAD, 0xF8}, |
||||
{0xAE, 0xFd}, |
||||
{0xAF, 0xFF}, |
||||
|
||||
{0xc0, 0x00}, |
||||
{0xc1, 0x10}, |
||||
{0xc2, 0x1c}, |
||||
{0xc3, 0x30}, |
||||
{0xc4, 0x43}, |
||||
{0xc5, 0x54}, |
||||
{0xc6, 0x65}, |
||||
{0xc7, 0x75}, |
||||
{0xc8, 0x93}, |
||||
{0xc9, 0xB0}, |
||||
{0xca, 0xCB}, |
||||
{0xcb, 0xE6}, |
||||
{0xcc, 0xFF}, |
||||
{0xf0, 0x02}, |
||||
{0xf1, 0x01}, |
||||
{0xf2, 0x02}, |
||||
{0xf3, 0x30}, |
||||
{0xf7, 0x04}, |
||||
{0xf8, 0x02}, |
||||
{0xf9, 0x9f}, |
||||
{0xfa, 0x78}, |
||||
{0xfe, 0x01}, |
||||
{0x00, 0xf5}, |
||||
{0x02, 0x20}, |
||||
{0x04, 0x10}, |
||||
{0x05, 0x08}, |
||||
{0x06, 0x20}, |
||||
{0x08, 0x0a}, |
||||
{0x0a, 0xa0}, |
||||
{0x0b, 0x60}, |
||||
{0x0c, 0x08}, |
||||
{0x0e, 0x44}, |
||||
{0x0f, 0x32}, |
||||
{0x10, 0x41}, |
||||
{0x11, 0x37}, |
||||
{0x12, 0x22}, |
||||
{0x13, 0x19}, |
||||
{0x14, 0x44}, |
||||
{0x15, 0x44}, |
||||
{0x16, 0xc2}, |
||||
{0x17, 0xA8}, |
||||
{0x18, 0x18}, |
||||
{0x19, 0x50}, |
||||
{0x1a, 0xd8}, |
||||
{0x1b, 0xf5}, |
||||
{0x70, 0x40}, |
||||
{0x71, 0x58}, |
||||
{0x72, 0x30}, |
||||
{0x73, 0x48}, |
||||
{0x74, 0x20}, |
||||
{0x75, 0x60}, |
||||
{0x77, 0x20}, |
||||
{0x78, 0x32}, |
||||
{0x30, 0x03}, |
||||
{0x31, 0x40}, |
||||
{0x32, 0x10}, |
||||
{0x33, 0xe0}, |
||||
{0x34, 0xe0}, |
||||
{0x35, 0x00}, |
||||
{0x36, 0x80}, |
||||
{0x37, 0x00}, |
||||
{0x38, 0x04}, |
||||
{0x39, 0x09}, |
||||
{0x3a, 0x12}, |
||||
{0x3b, 0x1C}, |
||||
{0x3c, 0x28}, |
||||
{0x3d, 0x31}, |
||||
{0x3e, 0x44}, |
||||
{0x3f, 0x57}, |
||||
{0x40, 0x6C}, |
||||
{0x41, 0x81}, |
||||
{0x42, 0x94}, |
||||
{0x43, 0xA7}, |
||||
{0x44, 0xB8}, |
||||
{0x45, 0xD6}, |
||||
{0x46, 0xEE}, |
||||
{0x47, 0x0d}, |
||||
{0x62, 0xf7}, |
||||
{0x63, 0x68}, |
||||
{0x64, 0xd3}, |
||||
{0x65, 0xd3}, |
||||
{0x66, 0x60}, |
||||
{0xfe, 0x00}, |
||||
{REGLIST_TAIL, 0x00}, |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* |
||||
* GC032A driver. |
||||
* |
||||
*/ |
||||
#ifndef __GC032A_H__ |
||||
#define __GC032A_H__ |
||||
|
||||
#include "sensor.h" |
||||
|
||||
/**
|
||||
* @brief Detect sensor pid |
||||
* |
||||
* @param slv_addr SCCB address |
||||
* @param id Detection result |
||||
* @return |
||||
* 0: Can't detect this sensor |
||||
* Nonzero: This sensor has been detected |
||||
*/ |
||||
int gc032a_detect(int slv_addr, sensor_id_t *id); |
||||
|
||||
/**
|
||||
* @brief initialize sensor function pointers |
||||
* |
||||
* @param sensor pointer of sensor |
||||
* @return |
||||
* Always 0 |
||||
*/ |
||||
int gc032a_init(sensor_t *sensor); |
||||
|
||||
#endif // __GC032A_H__
|
@ -0,0 +1,82 @@
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* GC032A register definitions. |
||||
*/ |
||||
#ifndef __GC032A_REG_REGS_H__ |
||||
#define __GC032A_REG_REGS_H__ |
||||
|
||||
#define SENSOR_ID_HIGH 0XF0 |
||||
#define SENSOR_ID_LOW 0XF1 |
||||
#define PAD_VB_HIZ_MODE 0XF2 |
||||
#define SYNC_OUTPUT 0XF3 |
||||
#define I2C_CONFIG 0XF4 |
||||
#define PLL_MODE1 0XF7 |
||||
#define PLL_MODE2 0XF8 |
||||
#define CM_MODE 0XF9 |
||||
#define ISP_DIV_MODE 0XFA |
||||
#define I2C_DEVICE_ID 0XFB |
||||
#define ANALOG_PWC 0XFC |
||||
#define ISP_DIV_MODE2 0XFD |
||||
#define RESET_RELATED 0XFE // Bit[7]: Software reset
|
||||
// Bit[6]: cm reset
|
||||
// Bit[5]: spi reset
|
||||
// Bit[4]: CISCTL_restart_n
|
||||
// Bit[3]: PLL_rst
|
||||
// Bit[2:0]: page select
|
||||
// 000:page0
|
||||
// 001:page1
|
||||
// 010:page2
|
||||
// 011:page3
|
||||
|
||||
//----page0-----------------------------
|
||||
#define P0_EXPOSURE_HIGH 0X03 |
||||
#define P0_EXPOSURE_LOW 0X04 |
||||
#define P0_HB_HIGH 0X05 |
||||
#define P0_HB_LOW 0X06 |
||||
#define P0_VB_HIGH 0X07 |
||||
#define P0_VB_LOW 0X08 |
||||
#define P0_ROW_START_HIGH 0X09 |
||||
#define P0_ROW_START_LOW 0X0A |
||||
#define P0_COLUMN_START_HIGH 0X0B |
||||
#define P0_COLUMN_START_LOW 0X0C |
||||
#define P0_WINDOW_HEIGHT_HIGH 0X0D |
||||
#define P0_WINDOW_HEIGHT_LOW 0X0E |
||||
#define P0_WINDOW_WIDTH_HIGH 0X0F |
||||
#define P0_WINDOW_WIDTH_LOW 0X10 |
||||
#define P0_SH_DELAY 0X11 |
||||
#define P0_VS_ST 0X12 |
||||
#define P0_VS_ET 0X13 |
||||
#define P0_CISCTL_MODE1 0X17 |
||||
|
||||
#define P0_BLOCK_ENABLE_1 0X40 |
||||
#define P0_AAAA_ENABLE 0X42 |
||||
#define P0_SPECIAL_EFFECT 0X43 |
||||
#define P0_SYNC_MODE 0X46 |
||||
#define P0_GAIN_CODE 0X48 |
||||
#define P0_DEBUG_MODE2 0X4C |
||||
#define P0_WIN_MODE 0X50 |
||||
#define P0_OUT_WIN_Y1_HIGH 0X51 |
||||
#define P0_OUT_WIN_Y1_LOW 0X52 |
||||
#define P0_OUT_WIN_X1_HIGH 0X53 |
||||
#define P0_OUT_WIN_X1_LOW 0X54 |
||||
#define P0_OUT_WIN_HEIGHT_HIGH 0X55 |
||||
#define P0_OUT_WIN_HEIGHT_LOW 0X56 |
||||
#define P0_OUT_WIN_WIDTH_HIGH 0X57 |
||||
#define P0_OUT_WIN_WIDTH_LOW 0X58 |
||||
|
||||
#define P0_GLOBAL_SATURATION 0XD0 |
||||
#define P0_SATURATION_CB 0XD1 |
||||
#define P0_SATURATION_CR 0XD2 |
||||
#define P0_LUMA_CONTRAST 0XD3 |
||||
#define P0_CONTRAST_CENTER 0XD4 |
||||
#define P0_LUMA_OFFSET 0XD5 |
||||
#define P0_FIXED_CB 0XDA |
||||
#define P0_FIXED_CR 0XDB |
||||
|
||||
//----page3-----------------------------
|
||||
#define P3_IMAGE_WIDTH_LOW 0X5B |
||||
#define P3_IMAGE_WIDTH_HIGH 0X5C |
||||
#define P3_IMAGE_HEIGHT_LOW 0X5D |
||||
#define P3_IMAGE_HEIGHT_HIGH 0X5E |
||||
|
||||
|
||||
#endif //__GC032A_REG_REGS_H__
|
@ -0,0 +1,401 @@
@@ -0,0 +1,401 @@
|
||||
#ifndef _GC032A_SETTINGS_H_ |
||||
#define _GC032A_SETTINGS_H_ |
||||
|
||||
#include <stdint.h> |
||||
#include <stdbool.h> |
||||
#include "esp_attr.h" |
||||
#include "gc032a_regs.h" |
||||
|
||||
|
||||
#define REG_DLY 0xffff |
||||
#define REGLIST_TAIL 0x0000 |
||||
|
||||
|
||||
/*
|
||||
* The default register settings, as obtained from OmniVision. There |
||||
* is really no making sense of most of these - lots of "reserved" values |
||||
* and such. |
||||
* |
||||
*/ |
||||
static const uint16_t gc032a_default_regs[][2] = { |
||||
/*System*/ |
||||
{0xf3, 0xff}, |
||||
{0xf5, 0x06}, |
||||
{0xf7, 0x01}, |
||||
{0xf8, 0x03}, |
||||
{0xf9, 0xce}, |
||||
{0xfa, 0x00}, |
||||
{0xfc, 0x02}, |
||||
{0xfe, 0x02}, |
||||
{0x81, 0x03}, |
||||
|
||||
{0xfe, 0x00}, |
||||
{0x77, 0x64}, |
||||
{0x78, 0x40}, |
||||
{0x79, 0x60}, |
||||
/*ANALOG & CISCTL*/ |
||||
{0xfe, 0x00}, |
||||
{0x03, 0x01}, |
||||
{0x04, 0xce}, |
||||
{0x05, 0x01}, |
||||
{0x06, 0xad}, |
||||
{0x07, 0x00}, |
||||
{0x08, 0x10}, |
||||
{0x0a, 0x00}, |
||||
{0x0c, 0x00}, |
||||
{0x0d, 0x01}, |
||||
{0x0e, 0xe8}, // height 488
|
||||
{0x0f, 0x02}, |
||||
{0x10, 0x88}, // width 648
|
||||
{0x17, 0x54}, |
||||
{0x19, 0x08}, |
||||
{0x1a, 0x0a}, |
||||
{0x1f, 0x40}, |
||||
{0x20, 0x30}, |
||||
{0x2e, 0x80}, |
||||
{0x2f, 0x2b}, |
||||
{0x30, 0x1a}, |
||||
{0xfe, 0x02}, |
||||
{0x03, 0x02}, |
||||
{0x05, 0xd7}, |
||||
{0x06, 0x60}, |
||||
{0x08, 0x80}, |
||||
{0x12, 0x89}, |
||||
|
||||
/*blk*/ |
||||
{0xfe, 0x00}, |
||||
{0x18, 0x02}, |
||||
{0xfe, 0x02}, |
||||
{0x40, 0x22}, |
||||
{0x45, 0x00}, |
||||
{0x46, 0x00}, |
||||
{0x49, 0x20}, |
||||
{0x4b, 0x3c}, |
||||
{0x50, 0x20}, |
||||
{0x42, 0x10}, |
||||
|
||||
/*isp*/ |
||||
{0xfe, 0x01}, |
||||
{0x0a, 0xc5}, |
||||
{0x45, 0x00}, |
||||
{0xfe, 0x00}, |
||||
{0x40, 0xff}, |
||||
{0x41, 0x25}, |
||||
{0x42, 0xcf}, |
||||
{0x43, 0x10}, |
||||
{0x44, 0x83}, |
||||
{0x46, 0x23}, |
||||
{0x49, 0x03}, |
||||
{0x52, 0x02}, |
||||
{0x54, 0x00}, |
||||
{0xfe, 0x02}, |
||||
{0x22, 0xf6}, |
||||
|
||||
/*Shading*/ |
||||
{0xfe, 0x01}, |
||||
{0xc1, 0x38}, |
||||
{0xc2, 0x4c}, |
||||
{0xc3, 0x00}, |
||||
{0xc4, 0x32}, |
||||
{0xc5, 0x24}, |
||||
{0xc6, 0x16}, |
||||
{0xc7, 0x08}, |
||||
{0xc8, 0x08}, |
||||
{0xc9, 0x00}, |
||||
{0xca, 0x20}, |
||||
{0xdc, 0x8a}, |
||||
{0xdd, 0xa0}, |
||||
{0xde, 0xa6}, |
||||
{0xdf, 0x75}, |
||||
|
||||
/*AWB*/ |
||||
{0xfe, 0x01}, |
||||
{0x7c, 0x09}, |
||||
{0x65, 0x06}, |
||||
{0x7c, 0x08}, |
||||
{0x56, 0xf4}, |
||||
{0x66, 0x0f}, |
||||
{0x67, 0x84}, |
||||
{0x6b, 0x80}, |
||||
{0x6d, 0x12}, |
||||
{0x6e, 0xb0}, |
||||
{0x86, 0x00}, |
||||
{0x87, 0x00}, |
||||
{0x88, 0x00}, |
||||
{0x89, 0x00}, |
||||
{0x8a, 0x00}, |
||||
{0x8b, 0x00}, |
||||
{0x8c, 0x00}, |
||||
{0x8d, 0x00}, |
||||
{0x8e, 0x00}, |
||||
{0x8f, 0x00}, |
||||
{0x90, 0x00}, |
||||
{0x91, 0x00}, |
||||
{0x92, 0xf4}, |
||||
{0x93, 0xd5}, |
||||
{0x94, 0x50}, |
||||
{0x95, 0x0f}, |
||||
{0x96, 0xf4}, |
||||
{0x97, 0x2d}, |
||||
{0x98, 0x0f}, |
||||
{0x99, 0xa6}, |
||||
{0x9a, 0x2d}, |
||||
{0x9b, 0x0f}, |
||||
{0x9c, 0x59}, |
||||
{0x9d, 0x2d}, |
||||
{0x9e, 0xaa}, |
||||
{0x9f, 0x67}, |
||||
{0xa0, 0x59}, |
||||
{0xa1, 0x00}, |
||||
{0xa2, 0x00}, |
||||
{0xa3, 0x0a}, |
||||
{0xa4, 0x00}, |
||||
{0xa5, 0x00}, |
||||
{0xa6, 0xd4}, |
||||
{0xa7, 0x9f}, |
||||
{0xa8, 0x55}, |
||||
{0xa9, 0xd4}, |
||||
{0xaa, 0x9f}, |
||||
{0xab, 0xac}, |
||||
{0xac, 0x9f}, |
||||
{0xad, 0x55}, |
||||
{0xae, 0xd4}, |
||||
{0xaf, 0xac}, |
||||
{0xb0, 0xd4}, |
||||
{0xb1, 0xa3}, |
||||
{0xb2, 0x55}, |
||||
{0xb3, 0xd4}, |
||||
{0xb4, 0xac}, |
||||
{0xb5, 0x00}, |
||||
{0xb6, 0x00}, |
||||
{0xb7, 0x05}, |
||||
{0xb8, 0xd6}, |
||||
{0xb9, 0x8c}, |
||||
|
||||
/*CC*/ |
||||
{0xfe, 0x01}, |
||||
{0xd0, 0x40}, |
||||
{0xd1, 0xf8}, |
||||
{0xd2, 0x00}, |
||||
{0xd3, 0xfa}, |
||||
{0xd4, 0x45}, |
||||
{0xd5, 0x02}, |
||||
|
||||
{0xd6, 0x30}, |
||||
{0xd7, 0xfa}, |
||||
{0xd8, 0x08}, |
||||
{0xd9, 0x08}, |
||||
{0xda, 0x58}, |
||||
{0xdb, 0x02}, |
||||
{0xfe, 0x00}, |
||||
|
||||
/*Gamma*/ |
||||
{0xfe, 0x00}, |
||||
{0xba, 0x00}, |
||||
{0xbb, 0x04}, |
||||
{0xbc, 0x0a}, |
||||
{0xbd, 0x0e}, |
||||
{0xbe, 0x22}, |
||||
{0xbf, 0x30}, |
||||
{0xc0, 0x3d}, |
||||
{0xc1, 0x4a}, |
||||
{0xc2, 0x5d}, |
||||
{0xc3, 0x6b}, |
||||
{0xc4, 0x7a}, |
||||
{0xc5, 0x85}, |
||||
{0xc6, 0x90}, |
||||
{0xc7, 0xa5}, |
||||
{0xc8, 0xb5}, |
||||
{0xc9, 0xc2}, |
||||
{0xca, 0xcc}, |
||||
{0xcb, 0xd5}, |
||||
{0xcc, 0xde}, |
||||
{0xcd, 0xea}, |
||||
{0xce, 0xf5}, |
||||
{0xcf, 0xff}, |
||||
|
||||
/*Auto Gamma*/ |
||||
{0xfe, 0x00}, |
||||
{0x5a, 0x08}, |
||||
{0x5b, 0x0f}, |
||||
{0x5c, 0x15}, |
||||
{0x5d, 0x1c}, |
||||
{0x5e, 0x28}, |
||||
{0x5f, 0x36}, |
||||
{0x60, 0x45}, |
||||
{0x61, 0x51}, |
||||
{0x62, 0x6a}, |
||||
{0x63, 0x7d}, |
||||
{0x64, 0x8d}, |
||||
{0x65, 0x98}, |
||||
{0x66, 0xa2}, |
||||
{0x67, 0xb5}, |
||||
{0x68, 0xc3}, |
||||
{0x69, 0xcd}, |
||||
{0x6a, 0xd4}, |
||||
{0x6b, 0xdc}, |
||||
{0x6c, 0xe3}, |
||||
{0x6d, 0xf0}, |
||||
{0x6e, 0xf9}, |
||||
{0x6f, 0xff}, |
||||
|
||||
/*Gain*/ |
||||
{0xfe, 0x00}, |
||||
{0x70, 0x50}, |
||||
|
||||
/*AEC*/ |
||||
{0xfe, 0x00}, |
||||
{0x4f, 0x01}, |
||||
{0xfe, 0x01}, |
||||
{0x0d, 0x00}, |
||||
{0x12, 0xa0}, |
||||
{0x13, 0x3a}, |
||||
{0x44, 0x04}, |
||||
{0x1f, 0x30}, |
||||
{0x20, 0x40}, |
||||
{0x26, 0x9a}, |
||||
{0x3e, 0x20}, |
||||
{0x3f, 0x2d}, |
||||
{0x40, 0x40}, |
||||
{0x41, 0x5b}, |
||||
{0x42, 0x82}, |
||||
{0x43, 0xb7}, |
||||
{0x04, 0x0a}, |
||||
{0x02, 0x79}, |
||||
{0x03, 0xc0}, |
||||
|
||||
/*measure window*/ |
||||
{0xfe, 0x01}, |
||||
{0xcc, 0x08}, |
||||
{0xcd, 0x08}, |
||||
{0xce, 0xa4}, |
||||
{0xcf, 0xec}, |
||||
|
||||
/*DNDD*/ |
||||
{0xfe, 0x00}, |
||||
{0x81, 0xb8}, |
||||
{0x82, 0x12}, |
||||
{0x83, 0x0a}, |
||||
{0x84, 0x01}, |
||||
{0x86, 0x50}, |
||||
{0x87, 0x18}, |
||||
{0x88, 0x10}, |
||||
{0x89, 0x70}, |
||||
{0x8a, 0x20}, |
||||
{0x8b, 0x10}, |
||||
{0x8c, 0x08}, |
||||
{0x8d, 0x0a}, |
||||
|
||||
/*Intpee*/ |
||||
{0xfe, 0x00}, |
||||
{0x8f, 0xaa}, |
||||
{0x90, 0x9c}, |
||||
{0x91, 0x52}, |
||||
{0x92, 0x03}, |
||||
{0x93, 0x03}, |
||||
{0x94, 0x08}, |
||||
{0x95, 0x44}, |
||||
{0x97, 0x00}, |
||||
{0x98, 0x00}, |
||||
|
||||
/*ASDE*/ |
||||
{0xfe, 0x00}, |
||||
{0xa1, 0x30}, |
||||
{0xa2, 0x41}, |
||||
{0xa4, 0x30}, |
||||
{0xa5, 0x20}, |
||||
{0xaa, 0x30}, |
||||
{0xac, 0x32}, |
||||
|
||||
/*YCP*/ |
||||
{0xfe, 0x00}, |
||||
{0xd1, 0x3c}, |
||||
{0xd2, 0x3c}, |
||||
{0xd3, 0x38}, |
||||
{0xd6, 0xf4}, |
||||
{0xd7, 0x1d}, |
||||
{0xdd, 0x73}, |
||||
{0xde, 0x84}, |
||||
|
||||
/*Banding*/ |
||||
{0xfe, 0x00}, |
||||
{0x05, 0x01}, |
||||
{0x06, 0xad}, |
||||
{0x07, 0x00}, |
||||
{0x08, 0x10}, |
||||
|
||||
{0xfe, 0x01}, |
||||
{0x25, 0x00}, |
||||
{0x26, 0x9a}, |
||||
|
||||
{0x27, 0x01}, |
||||
{0x28, 0xce}, |
||||
{0x29, 0x02}, |
||||
{0x2a, 0x68}, |
||||
{0x2b, 0x02}, |
||||
{0x2c, 0x68}, |
||||
{0x2d, 0x07}, |
||||
{0x2e, 0xd2}, |
||||
{0x2f, 0x0b}, |
||||
{0x30, 0x6e}, |
||||
{0x31, 0x0e}, |
||||
{0x32, 0x70}, |
||||
{0x33, 0x12}, |
||||
{0x34, 0x0c}, |
||||
{0x3c, 0x30}, |
||||
|
||||
/*Analog&Cisctl*/ |
||||
{0xfe, 0x00}, |
||||
{0x05, 0x01}, |
||||
{0x06, 0xa0}, |
||||
{0x07, 0x00}, |
||||
{0x08, 0x20}, |
||||
{0x0a, 0x78}, |
||||
{0x0c, 0xa0}, |
||||
{0x0d, 0x00}, //window_height [8]
|
||||
{0x0e, 0xf8}, //window_height [7:0] 248
|
||||
{0x0f, 0x01}, //window_width [9:8]
|
||||
{0x10, 0x48}, //window_width [7:0] 328
|
||||
|
||||
{0x55, 0x00}, |
||||
{0x56, 0xf0}, // 240
|
||||
{0x57, 0x01}, |
||||
{0x58, 0x40}, // 320
|
||||
|
||||
/*SPI*/ |
||||
{0xfe, 0x03}, |
||||
{0x5b, 0x40}, |
||||
{0x5c, 0x01}, |
||||
{0x5d, 0xf0}, |
||||
{0x5e, 0x00}, |
||||
|
||||
/*AEC*/ |
||||
{0xfe, 0x01}, |
||||
{0x25, 0x00}, //step
|
||||
{0x26, 0x63}, |
||||
{0x27, 0x01}, |
||||
{0x28, 0x29}, |
||||
{0x29, 0x01}, |
||||
{0x2a, 0x29}, |
||||
{0x2b, 0x01}, |
||||
{0x2c, 0x29}, |
||||
{0x2d, 0x01}, |
||||
{0x2e, 0x29}, |
||||
{0x2f, 0x01}, |
||||
{0x30, 0x29}, |
||||
{0x31, 0x01}, |
||||
{0x32, 0x29}, |
||||
{0x33, 0x01}, |
||||
{0x34, 0x29}, |
||||
{0x3c, 0x00}, |
||||
|
||||
/*measure window*/ |
||||
{0xfe, 0x01}, |
||||
{0xcc, 0x04}, |
||||
{0xcd, 0x04}, |
||||
{0xce, 0x72}, |
||||
{0xcf, 0x52}, |
||||
{REGLIST_TAIL, 0x00}, |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef __GC2145_H__ |
||||
#define __GC2145_H__ |
||||
|
||||
#include "sensor.h" |
||||
|
||||
/**
|
||||
* @brief Detect sensor pid |
||||
* |
||||
* @param slv_addr SCCB address |
||||
* @param id Detection result |
||||
* @return |
||||
* 0: Can't detect this sensor |
||||
* Nonzero: This sensor has been detected |
||||
*/ |
||||
int gc2145_detect(int slv_addr, sensor_id_t *id); |
||||
|
||||
/**
|
||||
* @brief initialize sensor function pointers |
||||
* |
||||
* @param sensor pointer of sensor |
||||
* @return |
||||
* Always 0 |
||||
*/ |
||||
int gc2145_init(sensor_t *sensor); |
||||
|
||||
#endif // __GC2145_H__
|
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* GC2145 register definitions. |
||||
*/ |
||||
#ifndef __GC2145_REG_REGS_H__ |
||||
#define __GC2145_REG_REGS_H__ |
||||
|
||||
#define CHIP_ID_HIGH 0XF0 |
||||
#define CHIP_ID_LOW 0XF1 |
||||
#define PLL_MODE1 0XF7 |
||||
#define PLL_MODE2 0XF8 |
||||
#define CM_MODE 0XF9 |
||||
#define CLK_DIV_MODE 0XFA |
||||
#define RESET_RELATED 0xfe // Bit[7]: Software reset
|
||||
// Bit[6]: cm reset
|
||||
// Bit[5]: mipi reset
|
||||
// Bit[4]: CISCTL_restart_n
|
||||
// Bit[3]: NA
|
||||
// Bit[2:0]: page select
|
||||
// 000:page0
|
||||
// 001:page1
|
||||
// 010:page2
|
||||
// 011:page3
|
||||
|
||||
//-page0----------------
|
||||
|
||||
#define P0_EXPOSURE_HIGH 0X03 |
||||
#define P0_EXPOSURE_LOW 0X04 |
||||
#define P0_HB_HIGH 0X05 |
||||
#define P0_HB_LOW 0X06 |
||||
#define P0_VB_HIGH 0X07 |
||||
#define P0_VB_LOW 0X08 |
||||
#define P0_ROW_START_HIGH 0X09 |
||||
#define P0_ROW_START_LOW 0X0A |
||||
#define P0_COL_START_HIGH 0X0B |
||||
#define P0_COL_START_LOW 0X0C |
||||
|
||||
#define P0_WIN_HEIGHT_HIGH 0X0D |
||||
#define P0_WIN_HEIGHT_LOW 0X0E |
||||
#define P0_WIN_WIDTH_HIGH 0X0F |
||||
#define P0_WIN_WIDTH_LOW 0X10 |
||||
#define P0_ANALOG_MODE1 0X17 |
||||
#define P0_ANALOG_MODE2 0X18 |
||||
|
||||
#define P0_SPECIAL_EFFECT 0X83 |
||||
#define P0_OUTPUT_FORMAT 0x84 // Format select
|
||||
// Bit[7]:YUV420 row switch
|
||||
// Bit[6]:YUV420 col switch
|
||||
// Bit[7]:YUV420_legacy
|
||||
// Bit[4:0]:output data mode
|
||||
// 5’h00 Cb Y Cr Y
|
||||
// 5’h01 Cr Y Cb Y
|
||||
// 5’h02 Y Cb Y Cr
|
||||
// 5’h03 Y Cr Y Cb
|
||||
// 5’h04 LSC bypass, C/Y
|
||||
// 5’h05 LSC bypass, Y/C
|
||||
// 5’h06 RGB 565
|
||||
// 5’h0f bypass 10bits
|
||||
// 5’h17 switch odd/even column /row to controls output Bayer pattern
|
||||
// 00 RGBG
|
||||
// 01 RGGB
|
||||
// 10 BGGR
|
||||
// 11 GBRG
|
||||
// 5'h18 DNDD out mode
|
||||
// 5'h19 LSC out mode
|
||||
// 5;h1b EEINTP out mode
|
||||
#define P0_FRAME_START 0X85 |
||||
#define P0_SYNC_MODE 0X86 |
||||
#define P0_MODULE_GATING 0X88 |
||||
#define P0_BYPASS_MODE 0X89 |
||||
#define P0_DEBUG_MODE2 0X8C |
||||
#define P0_DEBUG_MODE3 0X8D |
||||
#define P0_CROP_ENABLE 0X90 |
||||
#define P0_OUT_WIN_Y1_HIGH 0X91 |
||||
#define P0_OUT_WIN_Y1_LOW 0X92 |
||||
#define P0_OUT_WIN_X1_HIGH 0X93 |
||||
#define P0_OUT_WIN_X1_LOW 0X94 |
||||
#define P0_OUT_WIN_HEIGHT_HIGH 0X95 |
||||
#define P0_OUT_WIN_HEIGHT_LOW 0X96 |
||||
#define P0_OUT_WIN_WIDTH_HIGH 0X97 |
||||
#define P0_OUT_WIN_WIDTH_LOW 0X98 |
||||
#define P0_SUBSAMPLE 0X99 |
||||
#define P0_SUBSAMPLE_MODE 0X9A |
||||
|
||||
|
||||
#endif // __GC2145_REG_REGS_H__
|
@ -0,0 +1,719 @@
@@ -0,0 +1,719 @@
|
||||
|
||||
#include <stdint.h> |
||||
|
||||
#define REG_DLY 0xffff |
||||
#define REGLIST_TAIL 0x0000 /* Array end token */ |
||||
|
||||
static const uint16_t gc2145_default_init_regs[][2] = { |
||||
{0xfe, 0xf0}, |
||||
{0xfe, 0xf0}, |
||||
{0xfe, 0xf0}, |
||||
|
||||
{0xfc, 0x06}, |
||||
{0xf6, 0x00}, |
||||
|
||||
{0xf7, 0x1d}, //37 //17 //37 //1d//05
|
||||
{0xf8, 0x83}, //87 //83 //82
|
||||
{0xfa, 0x00}, |
||||
{0xf9, 0xfe}, //ff
|
||||
{0xfd, 0x00}, |
||||
{0xc2, 0x00}, |
||||
{0xf2, 0x0f}, |
||||
//////////////////////////////////////////////////////
|
||||
//////////////////// Analog & Cisctl ////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
{0xfe, 0x00}, |
||||
|
||||
{0x03, 0x04}, //exp time
|
||||
{0x04, 0x62}, //exp time
|
||||
|
||||
{0x05, 0x01}, //00 //hb[11:8]
|
||||
{0x06, 0x3b}, //0b //hb
|
||||
|
||||
{0x09, 0x00}, //row start
|
||||
{0x0a, 0x00}, //
|
||||
{0x0b, 0x00}, //col start
|
||||
{0x0c, 0x00}, |
||||
{0x0d, 0x04}, //height
|
||||
{0x0e, 0xc0}, |
||||
{0x0f, 0x06}, //width
|
||||
{0x10, 0x52}, |
||||
|
||||
{0x12, 0x2e}, //sh_delay 太短 YUV出图异常
|
||||
{0x17, 0x14}, //CISCTL Mode1 [1:0]mirror flip
|
||||
{0x18, 0x22}, //sdark mode
|
||||
{0x19, 0x0f}, // AD pipe number
|
||||
{0x1a, 0x01}, //AD manual switch mode
|
||||
|
||||
{0x1b, 0x4b}, //48 restg Width,SH width
|
||||
{0x1c, 0x07}, //06 帧率快后,横条纹 //12 //TX Width,Space Width
|
||||
{0x1d, 0x10}, //double reset
|
||||
{0x1e, 0x88}, //90//98 //fix 竖线//Analog Mode1,TX high,Coln_r
|
||||
{0x1f, 0x78}, //78 //38 //18 //Analog Mode2,txlow
|
||||
{0x20, 0x03}, //07 //Analog Mode3,comv,ad_clk mode
|
||||
{0x21, 0x40}, //10//20//40 //fix 灯管横条纹
|
||||
{0x22, 0xa0}, //d0//f0 //a2 //Vref vpix FPN严重
|
||||
{0x24, 0x1e}, |
||||
{0x25, 0x01}, //col sel
|
||||
{0x26, 0x10}, //Analog PGA gain1
|
||||
{0x2d, 0x60}, //40//40 //txl drv mode
|
||||
{0x30, 0x01}, //Analog Mode4
|
||||
{0x31, 0x90}, //b0//70 // Analog Mode7 [7:5]rsgh_r灯管横条纹[4:3]isp_g
|
||||
{0x33, 0x06}, //03//02//01 //EQ_hstart_width
|
||||
{0x34, 0x01}, |
||||
//
|
||||
///////////////////////////////////////////////////
|
||||
//////////////////// ISP reg //////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
{0x80, 0xff}, //outdoor gamma_en, GAMMA_en, CC_en, EE_en, INTP_en, DN_en, DD_en,LSC_en
|
||||
{0x81, 0x24}, //26//24 //BLK dither mode, ll_y_en ,skin_en, edge SA, new_skin_mode, autogray_en,ll_gamma_en,BFF test image
|
||||
{0x82, 0xfa}, //FA //auto_SA, auto_EE, auto_DN, auto_DD, auto_LSC, ABS_en, AWB_en, NA
|
||||
{0x83, 0x00}, //special_effect
|
||||
{0x84, 0x02}, //output format
|
||||
{0x86, 0x03}, //c2 //46 //c2 //sync mode
|
||||
{0x88, 0x03}, //[1]ctl_auto_gating [0]out_auto_gating
|
||||
{0x89, 0x03}, //bypass disable
|
||||
{0x85, 0x30}, //60//frame start cut
|
||||
{0x8a, 0x00}, //ISP_quiet_mode,close aaa pclk,BLK gate mode,exception,close first pipe clock,close dndd clock,close intp clock,DIV_gatedclk_en
|
||||
{0x8b, 0x00}, //[7:6]BFF_gate_mode,[5]BLK switch gain,[4]protect exp,[3:2]pipe gate mode,[1]not split sram,[0]dark current update
|
||||
|
||||
{0xb0, 0x55}, //60 //global gain
|
||||
{0xc3, 0x00}, //[7:4]auto_exp_gamma_th1[11:8],[3:0]auto_exp_gamma_th2[11:8]
|
||||
{0xc4, 0x80}, //auto_exp_gamma_th1[7:0] into
|
||||
{0xc5, 0x90}, //auto_exp_gamma_th2[7:0] out //outdoor gamma
|
||||
{0xc6, 0x38}, //auto_gamma_th1
|
||||
{0xc7, 0x40}, //auto_gamma_th2
|
||||
|
||||
{0xec, 0x06}, //measure window
|
||||
{0xed, 0x04}, |
||||
{0xee, 0x60}, //16 col
|
||||
{0xef, 0x90}, //8 row
|
||||
|
||||
{0xb6, 0x01}, //[0]aec en
|
||||
|
||||
{0x90, 0x01}, //crop
|
||||
{0x91, 0x00}, |
||||
{0x92, 0x00}, |
||||
{0x93, 0x00}, |
||||
{0x94, 0x00}, //08
|
||||
{0x95, 0x04}, |
||||
{0x96, 0xb0}, |
||||
{0x97, 0x06}, |
||||
{0x98, 0x40}, |
||||
|
||||
///////////////////////////////////////////////
|
||||
/////////// BLK ////////////////////////
|
||||
///////////////////////////////////////////////
|
||||
{0x18, 0x02}, |
||||
{0x40, 0x42}, //2b //27
|
||||
{0x41, 0x00}, //80 //dark row sel
|
||||
{0x43, 0x54}, //[7:4]BLK start not smooth [3:0]output start frame
|
||||
|
||||
{0x5e, 0x00}, //00//10 //18
|
||||
{0x5f, 0x00}, //00//10 //18
|
||||
{0x60, 0x00}, //00//10 //18
|
||||
{0x61, 0x00}, //00///10 //18
|
||||
{0x62, 0x00}, //00//10 //18
|
||||
{0x63, 0x00}, //00//10 //18
|
||||
{0x64, 0x00}, //00/10 //18
|
||||
{0x65, 0x00}, //00//10 //18
|
||||
{0x66, 0x20}, //1e
|
||||
{0x67, 0x20}, //1e
|
||||
{0x68, 0x20}, //1e
|
||||
{0x69, 0x20}, //1e
|
||||
|
||||
|
||||
{0x76, 0x00}, //0f
|
||||
|
||||
{0x6a, 0x00}, //06
|
||||
{0x6b, 0x00}, //06
|
||||
{0x6c, 0x3e}, //06
|
||||
{0x6d, 0x3e}, //06
|
||||
{0x6e, 0x3f}, //06
|
||||
{0x6f, 0x3f}, //06
|
||||
{0x70, 0x00}, //06
|
||||
{0x71, 0x00}, //06 //manual offset
|
||||
|
||||
{0x76, 0x00}, //1f//add offset
|
||||
{0x72, 0xf0}, //[7:4]BLK DD th [3:0]BLK various th
|
||||
{0x7e, 0x3c}, //ndark
|
||||
{0x7f, 0x00}, |
||||
|
||||
{0xfe, 0x02}, |
||||
{0x48, 0x15}, |
||||
{0x49, 0x00}, //04//04 //ASDE OFFSET SLOPE
|
||||
{0x4b, 0x0b}, //ASDE y OFFSET SLOPE
|
||||
{0xfe, 0x00}, |
||||
|
||||
///////////////////////////////////////////////
|
||||
/////////// AEC ////////////////////////
|
||||
///////////////////////////////////////////////
|
||||
{0xfe, 0x01}, |
||||
|
||||
{0x01, 0x04}, //AEC X1
|
||||
{0x02, 0xc0}, //AEC X2
|
||||
{0x03, 0x04}, //AEC Y1
|
||||
{0x04, 0x90}, //AEC Y2
|
||||
{0x05, 0x30}, //20 //AEC center X1
|
||||
{0x06, 0x90}, //40 //AEC center X2
|
||||
{0x07, 0x20}, //30 //AEC center Y1
|
||||
{0x08, 0x70}, //60 //AEC center Y2
|
||||
|
||||
{0x09, 0x00}, //AEC show mode
|
||||
{0x0a, 0xc2}, //[7]col gain enable
|
||||
{0x0b, 0x11}, //AEC every N
|
||||
{0x0c, 0x10}, //AEC_mode3 center weight
|
||||
{0x13, 0x40}, //2a //AEC Y target
|
||||
{0x17, 0x00}, //AEC ignore mode
|
||||
{0x1c, 0x11}, //
|
||||
{0x1e, 0x61}, //
|
||||
{0x1f, 0x30}, //40//50 //max pre gain
|
||||
{0x20, 0x40}, //60//40 //max post gain
|
||||
{0x22, 0x80}, //AEC outdoor THD
|
||||
{0x23, 0x20}, //target_Y_low_limit
|
||||
{0xfe, 0x02}, |
||||
{0x0f, 0x04}, //05
|
||||
{0xfe, 0x01}, |
||||
|
||||
{0x12, 0x35}, //35 //[5:4]group_size [3]slope_disable [2]outdoor_enable [0]histogram_enable
|
||||
{0x15, 0x50}, //target_Y_high_limit
|
||||
{0x10, 0x31}, //num_thd_high
|
||||
{0x3e, 0x28}, //num_thd_low
|
||||
{0x3f, 0xe0}, //luma_thd
|
||||
{0x40, 0x20}, //luma_slope
|
||||
{0x41, 0x0f}, //color_diff
|
||||
|
||||
{0xfe, 0x02}, |
||||
{0x0f, 0x05}, //max_col_level
|
||||
///////////////////////////
|
||||
////// INTPEE /////////////
|
||||
///////////////////////////
|
||||
{0xfe, 0x02}, //page2
|
||||
{0x90, 0x6c}, //ac //eeintp mode1
|
||||
{0x91, 0x03}, //02 ////eeintp mode2
|
||||
{0x92, 0xc8}, //44 //low criteria for direction
|
||||
{0x94, 0x66}, |
||||
{0x95, 0xb5}, |
||||
{0x97, 0x64}, //78 ////edge effect
|
||||
{0xa2, 0x11}, //fix direction
|
||||
{0xfe, 0x00}, |
||||
|
||||
/////////////////////////////
|
||||
//////// DNDD///////////////
|
||||
/////////////////////////////
|
||||
{0xfe, 0x02}, |
||||
{0x80, 0xc1}, //c1 //[7]share mode [6]skin mode [5]is 5x5 mode [1:0]noise value select 0:2 1:2.5 2:3 3:4
|
||||
{0x81, 0x08}, //
|
||||
{0x82, 0x08}, //signal a 0.6
|
||||
{0x83, 0x08}, //04 //signal b 2.5
|
||||
|
||||
{0x84, 0x0a}, //10 //05 dark_DD_TH
|
||||
{0x86, 0xf0}, //a0 Y_value_dd_th2
|
||||
{0x87, 0x50}, //90 Y_value_dd_th3
|
||||
{0x88, 0x15}, //60 Y_value_dd_th4
|
||||
|
||||
{0x89, 0x50}, //80 // asde th2
|
||||
{0x8a, 0x30}, //60 // asde th3
|
||||
{0x8b, 0x10}, //30 // asde th4
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
///////////// ASDE ////////////////////////
|
||||
/////////////////////////////////////////////////
|
||||
{0xfe, 0x01}, //page 1
|
||||
{0x21, 0x14}, //luma_value_div_sel(分频,与0xef呈2倍关系,增大1,0xef的值减小1倍)
|
||||
//ff ef luma_value read_only
|
||||
|
||||
{0xfe, 0x02}, //page2
|
||||
{0xa3, 0x40}, //ASDE_low_luma_value_LSC_th_H
|
||||
{0xa4, 0x20}, //ASDE_low_luma_value_LSC_th_L
|
||||
|
||||
{0xa5, 0x40}, //80 //ASDE_LSC_gain_dec_slope_H
|
||||
{0xa6, 0x80}, // 80 //ASDE_LSC_gain_dec_slope_L
|
||||
//ff a7 ASDE_LSC_gain_dec //read only
|
||||
|
||||
{0xab, 0x40}, //50 //ASDE_low_luma_value_OT_th
|
||||
|
||||
{0xae, 0x0c}, //[3]EE1_effect_inc_or_dec_high,[2]EE2_effect_inc_or_dec_high,
|
||||
//[1]EE1_effect_inc_or_dec_low,[0]EE2_effect_inc_or_dec_low, 1:inc 0:dec
|
||||
|
||||
{0xb3, 0x34}, //44 //ASDE_EE1_effect_slope_low,ASDE_EE2_effect_slope_low
|
||||
{0xb4, 0x44}, //12 //ASDE_EE1_effect_slope_high,ASDE_EE2_effect_slope_high
|
||||
|
||||
{0xb6, 0x38}, //40//40 //ASDE_auto_saturation_dec_slope
|
||||
{0xb7, 0x02}, //04 //ASDE_sub_saturation_slope
|
||||
{0xb9, 0x30}, //[7:0]ASDE_auto_saturation_low_limit
|
||||
{0x3c, 0x08}, //[3:0]auto gray_dec_slope
|
||||
{0x3d, 0x30}, //[7:0]auto gray_dec_th
|
||||
|
||||
|
||||
{0x4b, 0x0d}, //y offset slope
|
||||
{0x4c, 0x20}, //y offset limit
|
||||
|
||||
{0xfe, 0x00}, |
||||
//
|
||||
///////////////////gamma1////////////////////
|
||||
////Gamma
|
||||
{0xfe, 0x02}, |
||||
{0x10, 0x10}, |
||||
{0x11, 0x15}, |
||||
{0x12, 0x1a}, |
||||
{0x13, 0x1f}, |
||||
{0x14, 0x2c}, |
||||
{0x15, 0x39}, |
||||
{0x16, 0x45}, |
||||
{0x17, 0x54}, |
||||
{0x18, 0x69}, |
||||
{0x19, 0x7d}, |
||||
{0x1a, 0x8f}, |
||||
{0x1b, 0x9d}, |
||||
{0x1c, 0xa9}, |
||||
{0x1d, 0xbd}, |
||||
{0x1e, 0xcd}, |
||||
{0x1f, 0xd9}, |
||||
{0x20, 0xe3}, |
||||
{0x21, 0xea}, |
||||
{0x22, 0xef}, |
||||
{0x23, 0xf5}, |
||||
{0x24, 0xf9}, |
||||
{0x25, 0xff}, |
||||
|
||||
/////auto gamma/////
|
||||
{0xfe, 0x02}, |
||||
{0x26, 0x0f}, |
||||
{0x27, 0x14}, |
||||
{0x28, 0x19}, |
||||
{0x29, 0x1e}, |
||||
{0x2a, 0x27}, |
||||
{0x2b, 0x33}, |
||||
{0x2c, 0x3b}, |
||||
{0x2d, 0x45}, |
||||
{0x2e, 0x59}, |
||||
{0x2f, 0x69}, |
||||
{0x30, 0x7c}, |
||||
{0x31, 0x89}, |
||||
{0x32, 0x98}, |
||||
{0x33, 0xae}, |
||||
{0x34, 0xc0}, |
||||
{0x35, 0xcf}, |
||||
{0x36, 0xda}, |
||||
{0x37, 0xe2}, |
||||
{0x38, 0xe9}, |
||||
{0x39, 0xf3}, |
||||
{0x3a, 0xf9}, |
||||
{0x3b, 0xff}, |
||||
|
||||
///////////////////////////////////////////////
|
||||
/////////// YCP ///////////////////////
|
||||
///////////////////////////////////////////////
|
||||
{0xfe, 0x02}, |
||||
{0xd1, 0x30}, //32 //
|
||||
{0xd2, 0x30}, //32 //
|
||||
{0xd3, 0x45}, |
||||
{0xdd, 0x14}, //edge sa
|
||||
{0xde, 0x86}, //asde auto gray
|
||||
{0xed, 0x01}, //
|
||||
{0xee, 0x28}, |
||||
{0xef, 0x30}, |
||||
{0xd8, 0xd8}, //autogray protecy
|
||||
|
||||
////////////////////////////
|
||||
//////// LSC 0.8///////////////
|
||||
////////////////////////////
|
||||
{0xfe, 0x01}, |
||||
{0xa1, 0x80}, // center_row
|
||||
{0xa2, 0x80}, // center_col
|
||||
{0xa4, 0x00}, // sign of b1
|
||||
{0xa5, 0x00}, // sign of b1
|
||||
{0xa6, 0x70}, // sign of b4
|
||||
{0xa7, 0x00}, // sign of b4
|
||||
{0xa8, 0x77}, // sign of b22
|
||||
{0xa9, 0x77}, // sign of b22
|
||||
{0xaa, 0x1f}, // Q1_b1 of R
|
||||
{0xab, 0x0d}, // Q1_b1 of G
|
||||
{0xac, 0x19}, // Q1_b1 of B
|
||||
{0xad, 0x24}, // Q2_b1 of R
|
||||
{0xae, 0x0e}, // Q2_b1 of G
|
||||
{0xaf, 0x1d}, // Q2_b1 of B
|
||||
{0xb0, 0x12}, // Q3_b1 of R
|
||||
{0xb1, 0x0c}, // Q3_b1 of G
|
||||
{0xb2, 0x06}, // Q3_b1 of B
|
||||
{0xb3, 0x13}, // Q4_b1 of R
|
||||
{0xb4, 0x10}, // Q4_b1 of G
|
||||
{0xb5, 0x0c}, // Q4_b1 of B
|
||||
{0xb6, 0x6a}, // right_b2 of R
|
||||
{0xb7, 0x46}, // right_b2 of G
|
||||
{0xb8, 0x40}, // right_b2 of B
|
||||
{0xb9, 0x0b}, // right_b4 of R
|
||||
{0xba, 0x04}, // right_b4 of G
|
||||
{0xbb, 0x00}, // right_b4 of B
|
||||
{0xbc, 0x53}, // left_b2 of R
|
||||
{0xbd, 0x37}, // left_b2 of G
|
||||
{0xbe, 0x2d}, // left_b2 of B
|
||||
{0xbf, 0x0a}, // left_b4 of R
|
||||
{0xc0, 0x0a}, // left_b4 of G
|
||||
{0xc1, 0x14}, // left_b4 of B
|
||||
{0xc2, 0x34}, // up_b2 of R
|
||||
{0xc3, 0x22}, // up_b2 of G
|
||||
{0xc4, 0x18}, // up_b2 of B
|
||||
{0xc5, 0x23}, // up_b4 of R
|
||||
{0xc6, 0x0f}, // up_b4 of G
|
||||
{0xc7, 0x3c}, // up_b4 of B
|
||||
{0xc8, 0x20}, // down_b2 of R
|
||||
{0xc9, 0x1f}, // down_b2 of G
|
||||
{0xca, 0x17}, // down_b2 of B
|
||||
{0xcb, 0x2d}, // down_b4 of R
|
||||
{0xcc, 0x12}, // down_b4 of G
|
||||
{0xcd, 0x20}, // down_b4 of B
|
||||
{0xd0, 0x61}, // right_up_b22 of R
|
||||
{0xd1, 0x2f}, // right_up_b22 of G
|
||||
{0xd2, 0x39}, // right_up_b22 of B
|
||||
{0xd3, 0x45}, // right_down_b22 of R
|
||||
{0xd4, 0x2c}, // right_down_b22 of G
|
||||
{0xd5, 0x21}, // right_down_b22 of B
|
||||
{0xd6, 0x64}, // left_up_b22 of R
|
||||
{0xd7, 0x2d}, // left_up_b22 of G
|
||||
{0xd8, 0x30}, // left_up_b22 of B
|
||||
{0xd9, 0x42}, // left_down_b22 of R
|
||||
{0xda, 0x27}, // left_down_b22 of G
|
||||
{0xdb, 0x13}, // left_down_b22 of B
|
||||
{0xfe, 0x00}, |
||||
|
||||
/////////////////////////////////////////////////
|
||||
///////////// AWB ////////////////////////
|
||||
/////////////////////////////////////////////////
|
||||
{0xfe, 0x01}, |
||||
|
||||
{0x4f, 0x00}, |
||||
{0x4f, 0x00}, |
||||
{0x4b, 0x01}, |
||||
{0x4f, 0x00}, |
||||
|
||||
|
||||
{0x4c, 0x01}, |
||||
{0x4d, 0x6f}, |
||||
{0x4e, 0x02}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0x70}, |
||||
|
||||
{0x4e, 0x02}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0x8f}, |
||||
{0x4e, 0x02}, |
||||
|
||||
{0x4c, 0x01}, |
||||
{0x4d, 0x90}, |
||||
{0x4e, 0x02}, //light
|
||||
|
||||
|
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xed}, |
||||
{0x4e, 0x33}, //light
|
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xcd}, |
||||
{0x4e, 0x33}, //light
|
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xec}, |
||||
{0x4e, 0x03}, //light
|
||||
|
||||
{0x4c, 0x01}, |
||||
{0x4d, 0x6c}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0x6d}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0x6e}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0x8c}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0x8d}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0x8e}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xab}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xac}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xad}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xae}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xcb}, |
||||
{0x4e, 0x03}, |
||||
|
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xcc}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xce}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xeb}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xec}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xee}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x02}, |
||||
{0x4d, 0x0c}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x02}, |
||||
{0x4d, 0x0d}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xea}, |
||||
{0x4e, 0x03}, |
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xaf}, |
||||
{0x4e, 0x03}, //dark
|
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xcf}, |
||||
{0x4e, 0x03}, //dark
|
||||
|
||||
{0x4c, 0x01}, |
||||
{0x4d, 0xca}, |
||||
{0x4e, 0x04}, //light
|
||||
{0x4c, 0x02}, |
||||
{0x4d, 0x0b}, |
||||
{0x4e, 0x05}, //light
|
||||
{0x4c, 0x02}, |
||||
{0x4d, 0xc8}, |
||||
{0x4e, 0x06}, //light 100lux
|
||||
{0x4c, 0x02}, |
||||
{0x4d, 0xa8}, |
||||
|
||||
{0x4e, 0x06}, //light
|
||||
{0x4c, 0x02}, |
||||
{0x4d, 0xa9}, |
||||
{0x4e, 0x06}, //light
|
||||
|
||||
|
||||
{0x4c, 0x02}, |
||||
{0x4d, 0x89}, |
||||
{0x4e, 0x06}, //400lux
|
||||
{0x4c, 0x02}, |
||||
{0x4d, 0x69}, |
||||
{0x4e, 0x06}, //f12
|
||||
{0x4c, 0x02}, |
||||
{0x4d, 0x6a}, |
||||
{0x4e, 0x06}, //f12
|
||||
{0x4c, 0x02}, |
||||
{0x4d, 0xc7}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x02}, |
||||
{0x4d, 0xe7}, |
||||
{0x4e, 0x07}, //100lux
|
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x07}, |
||||
{0x4e, 0x07}, //light
|
||||
|
||||
{0x4c, 0x02}, |
||||
{0x4d, 0xe8}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x02}, |
||||
{0x4d, 0xe9}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x08}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x09}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x27}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x28}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x29}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x47}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x48}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x49}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x67}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x68}, |
||||
{0x4e, 0x07}, |
||||
{0x4c, 0x03}, |
||||
{0x4d, 0x69}, |
||||
{0x4e, 0x07}, |
||||
|
||||
{0x4f, 0x01}, |
||||
{0xfe, 0x01}, |
||||
{0x50, 0x80}, //AWB_PRE_mode
|
||||
{0x51, 0xa8}, //AWB_pre_THD_min[7:0]
|
||||
{0x52, 0x57}, //AWB_pre_THD_min[15:8] Dominiate luma 0.25=639c 0.22=57a8
|
||||
{0x53, 0x38}, //AWB_pre_THD_min_MIX[7:0]
|
||||
{0x54, 0xc7}, //AWB_pre_THD_min_MIX[15:8] Mix luma 0.5
|
||||
|
||||
{0x56, 0x0e}, //AWB_tone mode
|
||||
{0x58, 0x08}, //AWB_C_num_sel,AWB_D_num_sel
|
||||
{0x5b, 0x00}, //AWB_mix_mode
|
||||
|
||||
{0x5c, 0x74}, //green_num0[7:0]
|
||||
{0x5d, 0x8b}, //green_num0[15:8] 0.35
|
||||
|
||||
{0x61, 0xd3}, //R2G_stand0
|
||||
{0x62, 0xb5}, //B2G_stand0
|
||||
{0x63, 0x00}, //88//a4 //AWB gray mode [7]enable
|
||||
{0x65, 0x04}, //AWB margin
|
||||
|
||||
{0x67, 0xb2}, //R2G_stand3[7:0] FF/CWF
|
||||
{0x68, 0xac}, //B2G_stand3[7:0]
|
||||
{0x69, 0x00}, //R2G_stand4[9:8] B2G_stand4[9:8] R2G_stand3[9:8] B2G_stand3[9:8]
|
||||
{0x6a, 0xb2}, //R2G_stand4[7:0] TL84/TL84&CWF
|
||||
{0x6b, 0xac}, //B2G_stand4[7:0]
|
||||
{0x6c, 0xb2}, //R2G_stand5[7:0] A
|
||||
{0x6d, 0xac}, //B2G_stand5[7:0]
|
||||
{0x6e, 0x40}, //AWB_skin_weight R2G_stand5[9:8] B2G_stand5[9:8]
|
||||
{0x6f, 0x18}, //AWB_indoor_THD (0x21=17 caculate)
|
||||
{0x73, 0x00}, //AWB_indoor_mode
|
||||
|
||||
{0x70, 0x10}, //AWB low luma TH
|
||||
{0x71, 0xe8}, //AWB outdoor TH
|
||||
{0x72, 0xc0}, //outdoor mode
|
||||
{0x74, 0x01}, //[2:0]AWB skip mode 2x2,4x4,4x8,8x8
|
||||
{0x75, 0x01}, //[1:0]AWB_every_N
|
||||
{0x7f, 0x08}, //[3]gray world frame start
|
||||
|
||||
{0x76, 0x70}, //R limit
|
||||
{0x77, 0x58}, //G limit
|
||||
{0x78, 0xa0}, //d8 //B limit
|
||||
|
||||
{0xfe, 0x00}, |
||||
//
|
||||
//////////////////////////////////////////
|
||||
/////////// CC ////////////////////////
|
||||
//////////////////////////////////////////
|
||||
{0xfe, 0x02}, |
||||
|
||||
{0xc0, 0x01}, //[5:4] CC mode [0]CCT enable
|
||||
|
||||
{0xC1, 0x50}, //D50/D65
|
||||
{0xc2, 0xF9}, |
||||
{0xc3, 0x00}, //0
|
||||
{0xc4, 0xe8}, //e0
|
||||
{0xc5, 0x48}, |
||||
{0xc6, 0xf0}, |
||||
|
||||
|
||||
{0xC7, 0x50}, |
||||
{0xc8, 0xf2}, |
||||
{0xc9, 0x00}, |
||||
{0xcA, 0xE0}, |
||||
{0xcB, 0x45}, |
||||
{0xcC, 0xec}, |
||||
|
||||
{0xCd, 0x45}, |
||||
{0xce, 0xf0}, |
||||
{0xcf, 0x00}, |
||||
{0xe3, 0xf0}, |
||||
{0xe4, 0x45}, |
||||
{0xe5, 0xe8}, |
||||
|
||||
|
||||
{0xfe, 0x00}, |
||||
|
||||
{0xf2, 0x0f}, |
||||
|
||||
|
||||
//////////////frame rate 50Hz
|
||||
{0xfe, 0x00}, |
||||
|
||||
{0xf7, 0x1d}, |
||||
{0xf8, 0x84}, |
||||
{0xfa, 0x00}, |
||||
|
||||
{0x05, 0x01}, //hb
|
||||
{0x06, 0x3b}, |
||||
{0x07, 0x01}, //Vb
|
||||
{0x08, 0x0b}, |
||||
|
||||
{0xfe, 0x01}, |
||||
{0x25, 0x01}, |
||||
{0x26, 0x32}, //step
|
||||
{0x27, 0x03}, //8.15fps
|
||||
{0x28, 0x96}, |
||||
{0x29, 0x03}, //8.15fps
|
||||
{0x2a, 0x96}, |
||||
{0x2b, 0x03}, //8.15fps
|
||||
{0x2c, 0x96}, |
||||
{0x2d, 0x04}, //8.15fps
|
||||
{0x2e, 0x62}, |
||||
{0x3c, 0x00}, |
||||
{0xfe, 0x00}, |
||||
|
||||
/////////dark sun//////
|
||||
{0xfe, 0x00}, |
||||
{0x18, 0x22}, |
||||
{0xfe, 0x02}, |
||||
{0x40, 0xbf}, |
||||
{0x46, 0xcf}, |
||||
{0xfe, 0x00}, |
||||
|
||||
{0xfe, 0x00}, |
||||
|
||||
{0xf7, 0x1d}, |
||||
{0xf8, 0x84}, |
||||
{0xfa, 0x10}, |
||||
|
||||
{0x05, 0x01}, //hb
|
||||
{0x06, 0x18}, |
||||
{0x07, 0x00}, //Vb
|
||||
{0x08, 0x2e}, |
||||
|
||||
{0xfe, 0x01}, |
||||
{0x25, 0x00}, |
||||
{0x26, 0xa2}, //step
|
||||
{0x27, 0x01}, |
||||
{0x28, 0xe6}, |
||||
{0x29, 0x01}, |
||||
{0x2a, 0xe6}, |
||||
{0x2b, 0x01}, |
||||
{0x2c, 0xe6}, |
||||
{0x2d, 0x04}, // AEC_exp_level4[12:8]
|
||||
{0x2e, 0x62}, // AEC_exp_level4[7:0]
|
||||
{0x3c, 0x00}, |
||||
{0xfe, 0x00}, |
||||
|
||||
{0x09, 0x01}, //row start
|
||||
{0x0a, 0xd0}, //
|
||||
{0x0b, 0x02}, //col start
|
||||
{0x0c, 0x70}, |
||||
{0x0d, 0x01}, //height
|
||||
{0x0e, 0x00}, |
||||
{0x0f, 0x01}, //width
|
||||
{0x10, 0x50}, |
||||
|
||||
{0x90, 0x01}, //crop
|
||||
{0x91, 0x00}, |
||||
{0x92, 0x00}, |
||||
{0x93, 0x00}, |
||||
{0x94, 0x00}, |
||||
{0x95, 0x00}, |
||||
{0x96, 0xf0}, |
||||
{0x97, 0x01}, |
||||
{0x98, 0x40}, |
||||
|
||||
|
||||
{REGLIST_TAIL, 0x00}, |
||||
}; |
Loading…
Reference in new issue