mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Update HM01B0 driver. (#1125)
* Fix framerate for QVGA and QQVGA. * Fix set_exposure calculations. * Calculate vt_pix_clk from dividers in OSC register. * Implement frame rate for HM01b0. * Fix frame timing for QQVGA * Implement set_framerate.
This commit is contained in:
parent
08fd49d38a
commit
6ae6056b83
@ -21,8 +21,11 @@
|
||||
#include "py/mphal.h"
|
||||
|
||||
#define HIMAX_BOOT_RETRY (10)
|
||||
#define HIMAX_LINE_LEN_PCK 0x172
|
||||
#define HIMAX_FRAME_LENGTH 0x232
|
||||
#define HIMAX_LINE_LEN_PCK_QVGA 0x178
|
||||
#define HIMAX_FRAME_LENGTH_QVGA 0x104
|
||||
|
||||
#define HIMAX_LINE_LEN_PCK_QQVGA 0x178
|
||||
#define HIMAX_FRAME_LENGTH_QQVGA 0x084
|
||||
|
||||
static const uint16_t default_regs[][2] = {
|
||||
{BLC_TGT, 0x08}, // BLC target :8 at 8 bit mode
|
||||
@ -76,8 +79,8 @@ static const uint16_t default_regs[][2] = {
|
||||
{AE_MIN_MEAN, 0x0A}, //AE min target mean [Def: 0x0A]
|
||||
{CONVERGE_IN_TH, 0x03}, //Converge in threshold [Def: 0x03]
|
||||
{CONVERGE_OUT_TH, 0x05}, //Converge out threshold [Def: 0x05]
|
||||
{MAX_INTG_H, 0x01}, //Maximum INTG High Byte [Def: 0x01]
|
||||
{MAX_INTG_L, 0x54}, //Maximum INTG Low Byte [Def: 0x54]
|
||||
{MAX_INTG_H, (HIMAX_FRAME_LENGTH_QVGA-2)>>8}, //Maximum INTG High Byte [Def: 0x01]
|
||||
{MAX_INTG_L, (HIMAX_FRAME_LENGTH_QVGA-2)&0xFF}, //Maximum INTG Low Byte [Def: 0x54]
|
||||
{MAX_AGAIN_FULL, 0x03}, //Maximum Analog gain in full frame mode [Def: 0x03]
|
||||
{MAX_AGAIN_BIN2, 0x04}, //Maximum Analog gain in bin2 mode [Def: 0x04]
|
||||
{MAX_DGAIN, 0xC0},
|
||||
@ -97,17 +100,17 @@ static const uint16_t default_regs[][2] = {
|
||||
{FS_50HZ_L, 0x32},
|
||||
|
||||
{MD_CTRL, 0x30},
|
||||
{FRAME_LEN_LINES_H, HIMAX_FRAME_LENGTH>>8},
|
||||
{FRAME_LEN_LINES_L, HIMAX_FRAME_LENGTH&0xFF},
|
||||
{LINE_LEN_PCK_H, HIMAX_LINE_LEN_PCK>>8},
|
||||
{LINE_LEN_PCK_L, HIMAX_LINE_LEN_PCK&0xFF},
|
||||
{0x3010, 0x00}, // no full frame
|
||||
{FRAME_LEN_LINES_H, HIMAX_FRAME_LENGTH_QVGA>>8},
|
||||
{FRAME_LEN_LINES_L, HIMAX_FRAME_LENGTH_QVGA&0xFF},
|
||||
{LINE_LEN_PCK_H, HIMAX_LINE_LEN_PCK_QVGA>>8},
|
||||
{LINE_LEN_PCK_L, HIMAX_LINE_LEN_PCK_QVGA&0xFF},
|
||||
{QVGA_WIN_EN, 0x01}, // Enable QVGA window readout
|
||||
{0x0383, 0x01},
|
||||
{0x0387, 0x01},
|
||||
{0x0390, 0x00},
|
||||
{0x3011, 0x70},
|
||||
{0x3059, 0x02},
|
||||
{0x3060, 0x0B},
|
||||
{OSC_CLK_DIV, 0x0B},
|
||||
{IMG_ORIENTATION, 0x00}, // change the orientation
|
||||
{0x0104, 0x01},
|
||||
|
||||
@ -180,6 +183,12 @@ static const uint16_t QVGA_regs[][2] = {
|
||||
{0x0383, 0x01},
|
||||
{0x0387, 0x01},
|
||||
{0x0390, 0x00},
|
||||
{MAX_INTG_H, (HIMAX_FRAME_LENGTH_QVGA-2)>>8},
|
||||
{MAX_INTG_L, (HIMAX_FRAME_LENGTH_QVGA-2)&0xFF},
|
||||
{FRAME_LEN_LINES_H, (HIMAX_FRAME_LENGTH_QVGA>>8)},
|
||||
{FRAME_LEN_LINES_L, (HIMAX_FRAME_LENGTH_QVGA&0xFF)},
|
||||
{LINE_LEN_PCK_H, (HIMAX_LINE_LEN_PCK_QVGA>>8)},
|
||||
{LINE_LEN_PCK_L, (HIMAX_LINE_LEN_PCK_QVGA&0xFF)},
|
||||
//============= End of regs marker ==================
|
||||
{0x0000, 0x00},
|
||||
|
||||
@ -189,6 +198,12 @@ static const uint16_t QQVGA_regs[][2] = {
|
||||
{0x0383, 0x03},
|
||||
{0x0387, 0x03},
|
||||
{0x0390, 0x03},
|
||||
{MAX_INTG_H, (HIMAX_FRAME_LENGTH_QQVGA-2)>>8},
|
||||
{MAX_INTG_L, (HIMAX_FRAME_LENGTH_QQVGA-2)&0xFF},
|
||||
{FRAME_LEN_LINES_H, (HIMAX_FRAME_LENGTH_QQVGA>>8)},
|
||||
{FRAME_LEN_LINES_L, (HIMAX_FRAME_LENGTH_QQVGA&0xFF)},
|
||||
{LINE_LEN_PCK_H, (HIMAX_LINE_LEN_PCK_QQVGA>>8)},
|
||||
{LINE_LEN_PCK_L, (HIMAX_LINE_LEN_PCK_QQVGA&0xFF)},
|
||||
//============= End of regs marker ==================
|
||||
{0x0000, 0x00},
|
||||
|
||||
@ -220,6 +235,36 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_framerate(sensor_t *sensor, int framerate)
|
||||
{
|
||||
uint8_t osc_div = 0;
|
||||
uint32_t framesize = sensor->framesize;
|
||||
|
||||
if (framesize == FRAMESIZE_INVALID) {
|
||||
// Use QVGA by default if the framesize is not set
|
||||
framesize = FRAMESIZE_QVGA;
|
||||
}
|
||||
|
||||
switch (framerate) {
|
||||
case 15:
|
||||
osc_div = (framesize == FRAMESIZE_QVGA) ? 0x01 : 0x00;
|
||||
break;
|
||||
case 30:
|
||||
osc_div = (framesize == FRAMESIZE_QVGA) ? 0x02 : 0x01;
|
||||
break;
|
||||
case 60:
|
||||
osc_div = (framesize == FRAMESIZE_QVGA) ? 0x03 : 0x02;
|
||||
break;
|
||||
case 120:
|
||||
// Set to max FPS.
|
||||
osc_div = 0x03;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return cambus_writeb2(&sensor->bus, sensor->slv_addr, OSC_CLK_DIV, osc_div);
|
||||
}
|
||||
|
||||
static int set_contrast(sensor_t *sensor, int level)
|
||||
{
|
||||
return 0;
|
||||
@ -265,6 +310,23 @@ static int get_gain_db(sensor_t *sensor, float *gain_db)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_vt_pix_clk(sensor_t *sensor, uint32_t *vt_pix_clk)
|
||||
{
|
||||
uint8_t reg;
|
||||
if (cambus_readb2(&sensor->bus, sensor->slv_addr, OSC_CLK_DIV, ®) != 0) {
|
||||
return -1;
|
||||
}
|
||||
// 00 -> MCLK / 8
|
||||
// 01 -> MCLK / 4
|
||||
// 10 -> MCLK / 2
|
||||
// 11 -> MCLK / 1
|
||||
uint32_t vt_sys_div = 8 / (1 << (reg & 0x03));
|
||||
|
||||
// vt_pix_clk = MCLK / vt_sys_div
|
||||
*vt_pix_clk = OMV_XCLK_FREQUENCY / vt_sys_div;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
|
||||
{
|
||||
int ret=0;
|
||||
@ -272,9 +334,28 @@ static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
|
||||
if (enable) {
|
||||
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, AE_CTRL, 1);
|
||||
} else {
|
||||
int coarse_int = exposure_us*(OMV_XCLK_FREQUENCY/1000000)/LINE_LEN_PCK_H;
|
||||
if (coarse_int<2) coarse_int = 2;
|
||||
if (coarse_int>HIMAX_FRAME_LENGTH-2) coarse_int = HIMAX_FRAME_LENGTH-2;
|
||||
uint32_t line_len;
|
||||
uint32_t frame_len;
|
||||
uint32_t coarse_int;
|
||||
uint32_t vt_pix_clk = 0;
|
||||
|
||||
if (sensor->framesize == FRAMESIZE_QVGA) {
|
||||
line_len = HIMAX_LINE_LEN_PCK_QVGA;
|
||||
frame_len = HIMAX_FRAME_LENGTH_QVGA;
|
||||
} else {
|
||||
line_len = HIMAX_LINE_LEN_PCK_QQVGA;
|
||||
frame_len = HIMAX_FRAME_LENGTH_QQVGA;
|
||||
}
|
||||
|
||||
ret |= get_vt_pix_clk(sensor, &vt_pix_clk);
|
||||
coarse_int = exposure_us * (vt_pix_clk / 1000000) / line_len;
|
||||
|
||||
if (coarse_int < 2) {
|
||||
coarse_int = 2;
|
||||
} else if (coarse_int > (frame_len-2)) {
|
||||
coarse_int = frame_len-2;
|
||||
}
|
||||
|
||||
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, AE_CTRL, 0);
|
||||
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, INTEGRATION_H, coarse_int>>8);
|
||||
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, INTEGRATION_L, coarse_int&0xff);
|
||||
@ -323,6 +404,7 @@ int hm01b0_init(sensor_t *sensor)
|
||||
sensor->write_reg = write_reg;
|
||||
sensor->set_pixformat = set_pixformat;
|
||||
sensor->set_framesize = set_framesize;
|
||||
sensor->set_framerate = set_framerate;
|
||||
sensor->set_contrast = set_contrast;
|
||||
sensor->set_brightness = set_brightness;
|
||||
sensor->set_saturation = set_saturation;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user