initial 5640 support

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

View File

@@ -124,7 +124,7 @@ static int write_addr_reg(uint8_t slv_addr, const uint16_t reg, uint16_t x_value
#define write_reg_bits(slv_addr, reg, mask, enable) set_reg_bits(slv_addr, reg, 0, mask, enable?mask:0)
int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sys_div, int pll_pre_div, bool pll_root_2x, int pll_seld5, bool pclk_manual, int pclk_div)
static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sys_div, int pll_pre_div, bool pll_root_2x, int pll_seld5, bool pclk_manual, int pclk_div)
{
const int pll_pre_div2x_map[] = { 2, 3, 4, 6 };//values are multiplied by two to avoid floats
const int pll_seld52x_map[] = { 2, 2, 4, 5 };
@@ -252,12 +252,12 @@ static int set_image_options(sensor_t *sensor)
}
// binning
if (sensor->status.framesize > FRAMESIZE_SVGA) {
reg20 |= 0x40;
} else {
if (sensor->status.binning) {
reg20 |= 0x01;
reg21 |= 0x01;
reg4514_test |= 4;
} else {
reg20 |= 0x40;
}
// V-Flip
@@ -292,8 +292,18 @@ static int set_image_options(sensor_t *sensor)
ret = -1;
}
if (sensor->status.binning) {
ret = write_reg(sensor->slv_addr, 0x4520, 0x0b)
|| write_reg(sensor->slv_addr, X_INCREMENT, 0x31)//odd:3, even: 1
|| write_reg(sensor->slv_addr, Y_INCREMENT, 0x31);//odd:3, even: 1
} else {
ret = write_reg(sensor->slv_addr, 0x4520, 0xb0)
|| write_reg(sensor->slv_addr, X_INCREMENT, 0x11)//odd:1, even: 1
|| write_reg(sensor->slv_addr, Y_INCREMENT, 0x11);//odd:1, even: 1
}
ESP_LOGD(TAG, "Set Image Options: Compression: %u, Binning: %u, V-Flip: %u, H-Mirror: %u, Reg-4514: 0x%02x",
sensor->pixformat == PIXFORMAT_JPEG, sensor->status.framesize <= FRAMESIZE_SVGA, sensor->status.vflip, sensor->status.hmirror, reg4514);
sensor->pixformat == PIXFORMAT_JPEG, sensor->status.binning, sensor->status.vflip, sensor->status.hmirror, reg4514);
return ret;
}
@@ -303,51 +313,37 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
framesize_t old_framesize = sensor->status.framesize;
sensor->status.framesize = framesize;
if(framesize >= FRAMESIZE_INVALID){
if(framesize > FRAMESIZE_QXGA){
ESP_LOGE(TAG, "Invalid framesize: %u", framesize);
return -1;
}
uint16_t w = resolution[framesize][0];
uint16_t h = resolution[framesize][1];
uint16_t w = resolution[framesize].width;
uint16_t h = resolution[framesize].height;
aspect_ratio_t ratio = resolution[sensor->status.framesize].aspect_ratio;
ratio_settings_t settings = ratio_table[ratio];
if (framesize > FRAMESIZE_SVGA) {
ret = write_reg(sensor->slv_addr, 0x4520, 0xb0)
|| write_reg(sensor->slv_addr, X_INCREMENT, 0x11)//odd:1, even: 1
|| write_reg(sensor->slv_addr, Y_INCREMENT, 0x11);//odd:1, even: 1
} else {
ret = write_reg(sensor->slv_addr, 0x4520, 0x0b)
|| write_reg(sensor->slv_addr, X_INCREMENT, 0x31)//odd:3, even: 1
|| write_reg(sensor->slv_addr, Y_INCREMENT, 0x31);//odd:3, even: 1
}
sensor->status.binning = (w <= (settings.max_width / 2) && h <= (settings.max_height / 2));
sensor->status.scale = !((w == settings.max_width && h == settings.max_height)
|| (w == (settings.max_width / 2) && h == (settings.max_height / 2)));
if (ret) {
goto fail;
}
ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, 0, 0)
|| write_addr_reg(sensor->slv_addr, X_ADDR_END_H, 2079, 1547)
ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, settings.start_x, settings.start_y)
|| write_addr_reg(sensor->slv_addr, X_ADDR_END_H, settings.end_x, settings.end_y)
|| write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, w, h);
if (ret) {
goto fail;
}
if (framesize > FRAMESIZE_SVGA) {
ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, 2300, 1564)
|| write_addr_reg(sensor->slv_addr, X_OFFSET_H, 16, 6);
if (sensor->status.binning) {
ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, settings.total_x, (settings.total_y / 2) + 1)
|| write_addr_reg(sensor->slv_addr, X_OFFSET_H, 8, 2);
} else {
if (framesize == FRAMESIZE_SVGA) {
ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, 2300, 788);
} else {
ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, 2050, 788);
}
if (ret == 0) {
ret = write_addr_reg(sensor->slv_addr, X_OFFSET_H, 8, 2);
}
ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, settings.total_x, settings.total_y)
|| write_addr_reg(sensor->slv_addr, X_OFFSET_H, 16, 6);
}
if (ret == 0) {
ret = write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, framesize != FRAMESIZE_QXGA);
ret = write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, sensor->status.scale);
}
if (ret == 0) {
@@ -880,6 +876,92 @@ static int set_denoise(sensor_t *sensor, int level)
return ret;
}
static int get_reg(sensor_t *sensor, int reg, int mask)
{
int ret = 0, ret2 = 0;
if(mask > 0xFF){
ret = read_reg16(sensor->slv_addr, reg);
if(ret >= 0 && mask > 0xFFFF){
ret2 = read_reg(sensor->slv_addr, reg+2);
if(ret2 >= 0){
ret = (ret << 8) | ret2 ;
} else {
ret = ret2;
}
}
} 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, ret2 = 0;
if(mask > 0xFF){
ret = read_reg16(sensor->slv_addr, reg);
if(ret >= 0 && mask > 0xFFFF){
ret2 = read_reg(sensor->slv_addr, reg+2);
if(ret2 >= 0){
ret = (ret << 8) | ret2 ;
} else {
ret = ret2;
}
}
} else {
ret = read_reg(sensor->slv_addr, reg);
}
if(ret < 0){
return ret;
}
value = (ret & ~mask) | (value & mask);
if(mask > 0xFFFF){
ret = write_reg16(sensor->slv_addr, reg, value >> 8);
if(ret >= 0){
ret = write_reg(sensor->slv_addr, reg+2, value & 0xFF);
}
} else if(mask > 0xFF){
ret = write_reg16(sensor->slv_addr, reg, value);
} else {
ret = write_reg(sensor->slv_addr, reg, value);
}
return ret;
}
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)
{
int ret = 0;
ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, startX, startY)
|| write_addr_reg(sensor->slv_addr, X_ADDR_END_H, endX, endY)
|| write_addr_reg(sensor->slv_addr, X_OFFSET_H, offsetX, offsetY)
|| write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, totalX, totalY)
|| write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, outputX, outputY)
|| write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, scale);
if(!ret){
sensor->status.scale = scale;
sensor->status.binning = binning;
ret = set_image_options(sensor);
}
return ret;
}
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 set_pll(sensor, bypass > 0, multiplier, sys_div, pre_div, root_2x > 0, seld5, pclk_manual > 0, pclk_div);
}
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;
}
static int init_status(sensor_t *sensor)
{
sensor->status.brightness = 0;
@@ -941,5 +1023,11 @@ int ov3660_init(sensor_t *sensor)
sensor->set_raw_gma = set_raw_gma_dsp;
sensor->set_lenc = set_lenc_dsp;
sensor->set_denoise = set_denoise;
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;
return 0;
}