mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Fix OV5640 PCLK calculation to use current register values (#1120)
This commit is contained in:
parent
7689622982
commit
7e45f89bc7
@ -1086,14 +1086,47 @@ static int get_gain_db(sensor_t *sensor, float *gain_db)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int calc_pclk_freq(uint8_t sc_pll_ctrl_0, uint8_t sc_pll_ctrl_1, uint8_t sc_pll_ctrl_2, uint8_t sc_pll_ctrl_3, uint8_t sys_root_div)
|
||||
{
|
||||
uint32_t pclk_freq = OV5640_XCLK_FREQ;
|
||||
pclk_freq /= ((sc_pll_ctrl_3 & 0x10) != 0x00) ? 2 : 1;
|
||||
pclk_freq /= ((sc_pll_ctrl_0 & 0x0F) == 0x0A) ? 10 : 8;
|
||||
switch (sc_pll_ctrl_3 & 0x0F)
|
||||
{
|
||||
case 0: pclk_freq /= 1; break;
|
||||
case 1: pclk_freq /= 2; break;
|
||||
case 2: pclk_freq /= 3; break;
|
||||
case 3: pclk_freq /= 4; break;
|
||||
case 4: pclk_freq /= 6; break;
|
||||
case 5: pclk_freq /= 8; break;
|
||||
default: pclk_freq /= 3; break;
|
||||
}
|
||||
pclk_freq *= sc_pll_ctrl_2;
|
||||
sc_pll_ctrl_1 >>= 4;
|
||||
pclk_freq /= sc_pll_ctrl_1;
|
||||
switch (sys_root_div & 0x30)
|
||||
{
|
||||
case 0x00: pclk_freq /= 1; break;
|
||||
case 0x10: pclk_freq /= 2; break;
|
||||
case 0x20: pclk_freq /= 4; break;
|
||||
case 0x30: pclk_freq /= 8; break;
|
||||
default: pclk_freq /= 1; break;
|
||||
}
|
||||
return (int)pclk_freq;
|
||||
}
|
||||
|
||||
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
|
||||
{
|
||||
uint8_t reg, pll, hts_h, hts_l, vts_h, vts_l;
|
||||
uint8_t reg, spc0, spc1, spc2, spc3, sysrootdiv, hts_h, hts_l, vts_h, vts_l;
|
||||
int ret = cambus_readb2(&sensor->bus, sensor->slv_addr, AEC_PK_MANUAL, ®);
|
||||
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, AEC_PK_MANUAL, (reg & 0xFE) | ((enable == 0) << 0));
|
||||
|
||||
if ((enable == 0) && (exposure_us >= 0)) {
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SC_PLL_CONTRL2, &pll);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SC_PLL_CONTRL0, &spc0);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SC_PLL_CONTRL1, &spc1);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SC_PLL_CONTRL2, &spc2);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SC_PLL_CONTRL3, &spc3);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SYSTEM_ROOT_DIVIDER, &sysrootdiv);
|
||||
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, TIMING_HTS_H, &hts_h);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, TIMING_HTS_L, &hts_l);
|
||||
@ -1104,12 +1137,7 @@ static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
|
||||
uint16_t hts = (hts_h << 8) | hts_l;
|
||||
uint16_t vts = (vts_h << 8) | vts_l;
|
||||
|
||||
// "/ 3" -> SC_PLL_CONTRL3[3:0] (pll pre-divider)
|
||||
// "/ 1" -> SC_PLL_CONTRL1[7:4] (system clock divider)
|
||||
// "/ 2" -> SC_PLL_CONTRL3[4] (pll root divider)
|
||||
// "/ 10" -> SYSTEM_CTROL0[3:0] (bit mode)
|
||||
// "/ 1" -> SYSTEM_ROOT_DIVIDER[5:4] (pclk root divider)
|
||||
int pclk_freq = ((((((OV5640_XCLK_FREQ / 3) * pll) / 1) / 2) / 10) / 1) * 2;
|
||||
int pclk_freq = calc_pclk_freq(spc0, spc1, spc2, spc3, sysrootdiv);
|
||||
int clocks_per_us = pclk_freq / 1000000;
|
||||
int exposure = IM_MAX(IM_MIN((exposure_us * clocks_per_us) / hts, 0xFFFF), 0x0000);
|
||||
|
||||
@ -1128,8 +1156,14 @@ static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
|
||||
|
||||
static int get_exposure_us(sensor_t *sensor, int *exposure_us)
|
||||
{
|
||||
uint8_t pll, aec_0, aec_1, aec_2, hts_h, hts_l;
|
||||
int ret = cambus_readb2(&sensor->bus, sensor->slv_addr, SC_PLL_CONTRL2, &pll);
|
||||
uint8_t spc0, spc1, spc2, spc3, sysrootdiv, aec_0, aec_1, aec_2, hts_h, hts_l;
|
||||
int ret = 0;
|
||||
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SC_PLL_CONTRL0, &spc0);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SC_PLL_CONTRL1, &spc1);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SC_PLL_CONTRL2, &spc2);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SC_PLL_CONTRL3, &spc3);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, SYSTEM_ROOT_DIVIDER, &sysrootdiv);
|
||||
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, AEC_PK_EXPOSURE_0, &aec_0);
|
||||
ret |= cambus_readb2(&sensor->bus, sensor->slv_addr, AEC_PK_EXPOSURE_1, &aec_1);
|
||||
@ -1141,12 +1175,7 @@ static int get_exposure_us(sensor_t *sensor, int *exposure_us)
|
||||
uint32_t aec = ((aec_0 << 16) | (aec_1 << 8) | aec_2) >> 4;
|
||||
uint16_t hts = (hts_h << 8) | hts_l;
|
||||
|
||||
// "/ 3" -> SC_PLL_CONTRL3[3:0] (pll pre-divider)
|
||||
// "/ 1" -> SC_PLL_CONTRL1[7:4] (system clock divider)
|
||||
// "/ 2" -> SC_PLL_CONTRL3[4] (pll root divider)
|
||||
// "/ 10" -> SYSTEM_CTROL0[3:0] (bit mode)
|
||||
// "/ 1" -> SYSTEM_ROOT_DIVIDER[5:4] (pclk root divider)
|
||||
int pclk_freq = ((((((OV5640_XCLK_FREQ / 3) * pll) / 1) / 2) / 10) / 1) * 2;
|
||||
int pclk_freq = calc_pclk_freq(spc0, spc1, spc2, spc3, sysrootdiv);
|
||||
int clocks_per_us = pclk_freq / 1000000;
|
||||
*exposure_us = (aec * hts) / clocks_per_us;
|
||||
|
||||
|
||||
@ -23,11 +23,13 @@
|
||||
#define AF_CMD_ACK 0x3023
|
||||
#define AF_FW_STATUS 0x3029
|
||||
|
||||
#define SC_PLL_CONTRL0 0x3034
|
||||
#define SC_PLL_CONTRL1 0x3035
|
||||
#define SC_PLL_CONTRL2 0x3036
|
||||
#define SC_PLL_CONTRL3 0x3037
|
||||
|
||||
#define SCCB_SYSTEM_CTRL_1 0x3103
|
||||
#define SYSTEM_ROOT_DIVIDER 0x3108
|
||||
|
||||
#define AWB_R_GAIN_H 0x3400
|
||||
#define AWB_R_GAIN_L 0x3401
|
||||
|
||||
Loading…
Reference in New Issue
Block a user