mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
sensors/pag7936: Add missing control functions. (#2555)
Some checks are pending
🔎 Check Code Formatting / formatting-check (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_GIGA) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_33_BLE_SENSE) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_RP2040_CONNECT) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NICLA_VISION) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_PORTENTA_H7) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV2) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV3) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4P) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMVPT) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_RT1060) (push) Waiting to run
🔥 Firmware Build / code-size-report (push) Blocked by required conditions
🔥 Firmware Build / stable-release (push) Blocked by required conditions
🔥 Firmware Build / development-release (push) Blocked by required conditions
Some checks are pending
🔎 Check Code Formatting / formatting-check (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_GIGA) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_33_BLE_SENSE) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_RP2040_CONNECT) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NICLA_VISION) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_PORTENTA_H7) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV2) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV3) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4P) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMVPT) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_RT1060) (push) Waiting to run
🔥 Firmware Build / code-size-report (push) Blocked by required conditions
🔥 Firmware Build / stable-release (push) Blocked by required conditions
🔥 Firmware Build / development-release (push) Blocked by required conditions
* sensors/pag7936: Add color bar output support. * sensors/pag7936: Add auto exposure and auto gain support. * sensors/pag7936: Add sleep support. * sensors/pag7936: Fix HD image shifting. * sensors/pag7936: Add cap on set_framerate per resolution.
This commit is contained in:
parent
9addcd90d8
commit
2a6c770b77
@ -46,19 +46,57 @@
|
||||
#define FRAME_TIME_20_16 (0x004E)
|
||||
#define FRAME_TIME_15_8 (0x004D)
|
||||
#define FRAME_TIME_7_0 (0x004C)
|
||||
#define AGC_H (0x1424)
|
||||
#define AGC_L (0x1423)
|
||||
#define AE_START_DIV_4_X_7_0 (0x0482)
|
||||
#define AE_START_DIV_4_X_8_7 (0x0483)
|
||||
#define AE_START_DIV_4_Y (0x0484)
|
||||
#define AE_SIZE_DIV_4_X_7_0 (0x0485)
|
||||
#define AE_SIZE_DIV_4_X_8_7 (0x0486)
|
||||
#define AE_SIZE_DIV_4_Y (0x0487)
|
||||
#define AE_EXPO_MANUAL (0x1400)
|
||||
#define AE_EXPO_MANUAL_AE_MANUAL_EN (0x10)
|
||||
#define AE_EXPO_MANUAL_AE_ENH (0x1)
|
||||
#define AE_FREQ_60 (0x1404)
|
||||
#define AE_YTAR8BIT (0x1406)
|
||||
#define AE_LOCKRANGE_IN (0x1407)
|
||||
#define AE_LOCKRANGE_OUT_LB (0x1408)
|
||||
#define AE_LOCKRANGE_OUT_UB (0x1409)
|
||||
#define AE_STABLE_7_0 (0x145B)
|
||||
#define AE_MINGAIN_7_0 (0x140A)
|
||||
#define AE_MINGAIN_10_8 (0x140B)
|
||||
#define AE_MAXGAIN_7_0 (0x140C)
|
||||
#define AE_MAXGAIN_10_8 (0x140D)
|
||||
#define AE_MINEXPO_7_0 (0x140E)
|
||||
#define AE_MINEXPO_15_8 (0x140F)
|
||||
#define AE_MINEXPO_17_16 (0x1410)
|
||||
#define AE_MAXEXPO_7_0 (0x1412)
|
||||
#define AE_MAXEXPO_15_8 (0x1413)
|
||||
#define AE_MAXEXPO_17_16 (0x1414)
|
||||
#define AE_GAIN_MANUAL_7_0 (0x1423)
|
||||
#define AE_GAIN_MANUAL_10_8 (0x1424)
|
||||
#define AE_EXP_LINE_NUM_7_0 (0x1450)
|
||||
#define AE_EXP_LINE_NUM_15_8 (0x1451)
|
||||
#define AE_EXP_LINE_NUM_17_16 (0x1452)
|
||||
#define TOTAL_GAIN_7_0 (0x1453)
|
||||
#define TOTAL_GAIN_10_8 (0x1454)
|
||||
#define AE_EXPO_MANUAL_17_16 (0x1427)
|
||||
#define AE_EXPO_MANUAL_15_8 (0x1426)
|
||||
#define AE_EXPO_MANUAL_7_0 (0x1425)
|
||||
#define SENSOR_UPDATE (0x00EB)
|
||||
#define SENSOR_UPDATE_FLAG (0x80)
|
||||
#define INTERFACE_POLARITY (0x0EAF)
|
||||
#define SENSOR_OPMODE (0x0008)
|
||||
#define SENSOR_OPMODE_RUN (0x83)
|
||||
#define SENSOR_OPMODE_SUSPEND (0x85)
|
||||
#define SENSOR_TRIGGER_FRAMENUM (0x002E)
|
||||
#define SENSOR_TRIGGER_EN (0x002F)
|
||||
#define SENSOR_TG_EN (0x0030)
|
||||
#define SENSOR_TG_EN_FLAG (0x01)
|
||||
#define SENSOR_TRIGGER_MODE (0x0031)
|
||||
#define SENSOR_SOFTWARE_TRIGGER (0x00EA)
|
||||
#define ISP_EN_H (0x0800)
|
||||
#define ISP_EN_H_EN (0x01)
|
||||
#define ISP_TEST_MODE (0x0801)
|
||||
#define ISP_TEST_MODE_RAMP (0x04)
|
||||
#define ISP_WOI_EN (0x0E10)
|
||||
#define ISP_WOI_HSIZE_L (0x0E11)
|
||||
#define ISP_WOI_HSIZE_H (0x0E12)
|
||||
@ -105,11 +143,40 @@
|
||||
#define PAG7936_MAX_INT ((FMAX_720P_120_LINEAR - 11)) // ExpLine max vlaue
|
||||
#define PAG7936_MIN_AGAIN (1472) // AGain min value, unit is 1/1024x
|
||||
#define PAG7936_MAX_AGAIN (16384) // AGain max value, unit is 1/1024x
|
||||
#define PAG7936_MIN_AGAIN_REG ((PAG7936_MIN_AGAIN) / 64)
|
||||
#define PAG7936_MAX_AGAIN_REG ((PAG7936_MAX_AGAIN) / 64)
|
||||
|
||||
#define PAG7936_GAIN_SCALE (16)
|
||||
#define PAG7936_GAIN_SCALE_F ((PAG7936_GAIN_SCALE) * 1.0f)
|
||||
|
||||
#define PAG7936_EXP_OFFSET (80)
|
||||
#define PAG7936_EXP_MIN (80)
|
||||
#define PAG7936_EXP_DIV (8)
|
||||
|
||||
#define PAG7936_FRAME_TIME(h, m, l) ((((h) & 0x1f) << 16) | ((m) << 8) | (l))
|
||||
#define PAG7936_FRAME_TIME_H(r, ft) (((r) & 0xe0) | (((ft) >> 16) & 0x1f))
|
||||
#define PAG7936_FRAME_TIME_M(ft) (((ft) >> 8) & 0xff)
|
||||
#define PAG7936_FRAME_TIME_L(ft) ((ft) & 0xff)
|
||||
|
||||
#define PAG7936_GAIN(h, l) ((((h) & 0x7) << 8) | (l))
|
||||
#define PAG7936_GAIN_H(r, gain) (((r) & 0xf8) | (((gain) >> 8) & 0x7))
|
||||
#define PAG7936_GAIN_L(gain) ((gain) & 0xff)
|
||||
|
||||
#define PAG7936_EXPOSURE(h, m, l) (((((h) & 0x3) << 16) | ((m) << 8) | (l)) * 8)
|
||||
#define PAG7936_EXPOSURE_H(r, exp) (((r) & 0xfc) | (((exp) >> 16) & 0x3))
|
||||
#define PAG7936_EXPOSURE_M(exp) (((exp) >> 8) & 0xff)
|
||||
#define PAG7936_EXPOSURE_L(exp) ((exp) & 0xff)
|
||||
|
||||
#if OMV_PAG7936_MIPI_CSI2
|
||||
#define PAG7936_WIDTH_ALIGN (8)
|
||||
#define PAG7936_WIDTH_ALIGN (8)
|
||||
#define PAG7936_QVGA_FPS_MAX (480)
|
||||
#define PAG7936_VGA_FPS_MAX (240)
|
||||
#define PAG7936_HD_FPS_MAX (120)
|
||||
#else
|
||||
#define PAG7936_WIDTH_ALIGN (4)
|
||||
#define PAG7936_WIDTH_ALIGN (4)
|
||||
#define PAG7936_QVGA_FPS_MAX (240)
|
||||
#define PAG7936_VGA_FPS_MAX (120)
|
||||
#define PAG7936_HD_FPS_MAX (60)
|
||||
#endif
|
||||
|
||||
static const uint16_t default_regs[][2] = {
|
||||
@ -320,26 +387,18 @@ static const uint16_t hd_regs[][2] = {
|
||||
{ AVERAGE_MODE, 0x00 },
|
||||
{ ROW_AVERAGE_MODE, 0x00 },
|
||||
{ COL_AVERAGE_MODE, 0x00 },
|
||||
{ ISP_WOI_EN, 0x01 },
|
||||
{ ISP_WOI_HSIZE_L, 0x00 },
|
||||
{ ISP_WOI_HSIZE_H, 0x05 },
|
||||
{ ISP_WOI_VSIZE_L, 0x20 },
|
||||
{ ISP_WOI_VSIZE_H, 0x03 },
|
||||
{ ISP_WOI_HOFFSET_L, 0x10 },
|
||||
{ ISP_WOI_HOFFSET_H, 0x00 },
|
||||
{ ISP_WOI_VOFFSET_L, 0x10 },
|
||||
{ ISP_WOI_VOFFSET_H, 0x00 },
|
||||
{ ISP_WOI_EN, 0x00 },
|
||||
{ HSIZE_L, 0x10 },
|
||||
{ HSIZE_H, 0x05 },
|
||||
{ VSIZE_L, 0x30 },
|
||||
{ VSIZE_H, 0x03 },
|
||||
{ WOI_HSIZE_L, 0x10 },
|
||||
{ WOI_HSIZE_L, 0x00 },
|
||||
{ WOI_HSIZE_H, 0x05 },
|
||||
{ WOI_VSIZE_L, 0x30 },
|
||||
{ WOI_VSIZE_L, 0x20 },
|
||||
{ WOI_VSIZE_H, 0x03 },
|
||||
{ WOI_HSTART_L, 0x00 },
|
||||
{ WOI_HSTART_L, 0x08 },
|
||||
{ WOI_HSTART_H, 0x00 },
|
||||
{ WOI_VSTART_L, 0x00 },
|
||||
{ WOI_VSTART_L, 0x08 },
|
||||
{ WOI_VSTART_H, 0x00 },
|
||||
{ SENSOR_UPDATE, 0x80 },
|
||||
{ 0x0000, 0x00 },
|
||||
@ -355,6 +414,9 @@ static int reset(omv_csi_t *csi) {
|
||||
}
|
||||
|
||||
static int sleep(omv_csi_t *csi, int enable) {
|
||||
int ret = omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_TG_EN, SENSOR_TG_EN_FLAG);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_OPMODE,
|
||||
enable ? SENSOR_OPMODE_SUSPEND : SENSOR_OPMODE_RUN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -415,29 +477,187 @@ static int set_framesize(omv_csi_t *csi, omv_csi_framesize_t framesize) {
|
||||
}
|
||||
|
||||
static int set_framerate(omv_csi_t *csi, int framerate) {
|
||||
uint8_t reg, exposure_us_17_16, exposure_us_15_8, exposure_us_7_0;
|
||||
int ret = 0;
|
||||
int32_t frame_time = FT_CLK / framerate;
|
||||
int32_t integ_time = IM_CLAMP((frame_time - 11), PAG7936_MIN_INT, PAG7936_MAX_INT);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, FRAME_TIME_20_16, ((frame_time >> 16) & 0x1F));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, FRAME_TIME_15_8, ((frame_time >> 8) & 0xFF));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, FRAME_TIME_7_0, (frame_time & 0xFF));
|
||||
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_17_16, ((integ_time >> 16) & 0x03));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_15_8, ((integ_time >> 8) & 0xFF));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_7_0, (integ_time & 0xFF));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, 0x80);
|
||||
switch (csi->framesize) {
|
||||
case OMV_CSI_FRAMESIZE_HD:
|
||||
framerate = IM_MIN(framerate, PAG7936_HD_FPS_MAX);
|
||||
break;
|
||||
case OMV_CSI_FRAMESIZE_VGA:
|
||||
framerate = IM_MIN(framerate, PAG7936_VGA_FPS_MAX);
|
||||
break;
|
||||
case OMV_CSI_FRAMESIZE_QVGA:
|
||||
framerate = IM_MIN(framerate, PAG7936_QVGA_FPS_MAX);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t frame_time = FT_CLK / framerate;
|
||||
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, FRAME_TIME_20_16, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, FRAME_TIME_20_16, PAG7936_FRAME_TIME_H(reg, frame_time));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, FRAME_TIME_15_8, PAG7936_FRAME_TIME_M(frame_time));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, FRAME_TIME_7_0, PAG7936_FRAME_TIME_L(frame_time));
|
||||
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL, ®);
|
||||
|
||||
if (reg & AE_EXPO_MANUAL_AE_MANUAL_EN) {
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_17_16, &exposure_us_17_16);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_15_8, &exposure_us_15_8);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_7_0, &exposure_us_7_0);
|
||||
} else {
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_17_16, &exposure_us_17_16);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_15_8, &exposure_us_15_8);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_7_0, &exposure_us_7_0);
|
||||
}
|
||||
|
||||
int32_t exposure_us = PAG7936_EXPOSURE(exposure_us_17_16, exposure_us_15_8, exposure_us_7_0);
|
||||
exposure_us = IM_CLAMP(exposure_us, PAG7936_EXP_MIN, (frame_time - PAG7936_EXP_OFFSET)) / PAG7936_EXP_DIV;
|
||||
|
||||
if (reg & AE_EXPO_MANUAL_AE_MANUAL_EN) {
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_17_16, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_17_16, PAG7936_EXPOSURE_H(reg, exposure_us));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_15_8, PAG7936_EXPOSURE_M(exposure_us));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_7_0, PAG7936_EXPOSURE_L(exposure_us));
|
||||
} else {
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_17_16, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_17_16, PAG7936_EXPOSURE_H(reg, exposure_us));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_15_8, PAG7936_EXPOSURE_M(exposure_us));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_7_0, PAG7936_EXPOSURE_L(exposure_us));
|
||||
}
|
||||
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, SENSOR_UPDATE_FLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_gainceiling(omv_csi_t *csi, omv_csi_gainceiling_t gainceiling) {
|
||||
uint8_t aec, reg;
|
||||
int ret = omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL, &aec);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL, aec | AE_EXPO_MANUAL_AE_MANUAL_EN);
|
||||
|
||||
int new_gainceiling = PAG7936_GAIN_SCALE << (gainceiling + 1);
|
||||
if (new_gainceiling > PAG7936_MAX_AGAIN_REG) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_MAXGAIN_10_8, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_MAXGAIN_10_8, PAG7936_GAIN_H(reg, new_gainceiling));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_MAXGAIN_7_0, PAG7936_GAIN_L(new_gainceiling));
|
||||
|
||||
// Force AEC/AGC to reload the new values.
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, SENSOR_UPDATE_FLAG);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL, aec);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, SENSOR_UPDATE_FLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_colorbar(omv_csi_t *csi, int enable) {
|
||||
return 0;
|
||||
uint8_t reg;
|
||||
int ret = omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, ISP_EN_H, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, ISP_EN_H,
|
||||
(reg & ~ISP_EN_H_EN) | (enable ? ISP_EN_H_EN : 0));
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, ISP_TEST_MODE, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, ISP_TEST_MODE,
|
||||
(reg & ~ISP_TEST_MODE_RAMP) | (enable ? ISP_TEST_MODE_RAMP : 0));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, SENSOR_UPDATE_FLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_auto_gain(omv_csi_t *csi, int enable, float gain_db, float gain_db_ceiling) {
|
||||
uint8_t reg;
|
||||
int ret = omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL, reg | AE_EXPO_MANUAL_AE_MANUAL_EN);
|
||||
|
||||
if ((enable == 0) && (!isnanf(gain_db)) && (!isinff(gain_db))) {
|
||||
int gain = fast_roundf(expf((gain_db / 20.0f) * M_LN10) * PAG7936_GAIN_SCALE_F);
|
||||
gain = IM_CLAMP(gain, PAG7936_MIN_AGAIN_REG, PAG7936_MAX_AGAIN_REG);
|
||||
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_GAIN_MANUAL_10_8, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_GAIN_MANUAL_10_8, PAG7936_GAIN_H(reg, gain));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_GAIN_MANUAL_7_0, PAG7936_GAIN_L(gain));
|
||||
} else if ((enable != 0) && (!isnanf(gain_db_ceiling)) && (!isinff(gain_db_ceiling))) {
|
||||
int gain_ceiling = fast_roundf(expf((gain_db_ceiling / 20.0f) * M_LN10) * PAG7936_GAIN_SCALE_F);
|
||||
gain_ceiling = IM_CLAMP(gain_ceiling, PAG7936_MIN_AGAIN_REG, PAG7936_MAX_AGAIN_REG);
|
||||
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_MAXGAIN_10_8, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_MAXGAIN_10_8, PAG7936_GAIN_H(reg, gain_ceiling));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_MAXGAIN_7_0, PAG7936_GAIN_L(gain_ceiling));
|
||||
}
|
||||
|
||||
// Force AEC/AGC to reload the new values.
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, SENSOR_UPDATE_FLAG);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL,
|
||||
(reg & ~AE_EXPO_MANUAL_AE_MANUAL_EN) | (enable ? 0 : AE_EXPO_MANUAL_AE_MANUAL_EN));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, SENSOR_UPDATE_FLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_gain_db(omv_csi_t *csi, float *gain_db) {
|
||||
uint8_t gainh, gainl;
|
||||
int ret = 0;
|
||||
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, TOTAL_GAIN_10_8, &gainh);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, TOTAL_GAIN_7_0, &gainl);
|
||||
|
||||
*gain_db = 20.0f * log10f(PAG7936_GAIN(gainh, gainl) / PAG7936_GAIN_SCALE_F);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_auto_exposure(omv_csi_t *csi, int enable, int exposure_us) {
|
||||
uint8_t reg, frame_time_20_16, frame_time_15_8, frame_time_7_0;
|
||||
int ret = omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL, reg | AE_EXPO_MANUAL_AE_MANUAL_EN);
|
||||
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, FRAME_TIME_20_16, &frame_time_20_16);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, FRAME_TIME_15_8, &frame_time_15_8);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, FRAME_TIME_7_0, &frame_time_7_0);
|
||||
|
||||
int32_t frame_time_us = PAG7936_FRAME_TIME(frame_time_20_16, frame_time_15_8, frame_time_7_0);
|
||||
exposure_us = IM_CLAMP(exposure_us, PAG7936_EXP_MIN, (frame_time_us - PAG7936_EXP_OFFSET)) / PAG7936_EXP_DIV;
|
||||
|
||||
if ((enable == 0) && (exposure_us >= 0)) {
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_17_16, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_17_16, PAG7936_EXPOSURE_H(reg, exposure_us));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_15_8, PAG7936_EXPOSURE_M(exposure_us));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL_7_0, PAG7936_EXPOSURE_L(exposure_us));
|
||||
} else if ((enable != 0) && (exposure_us >= 0)) {
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_17_16, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_17_16, PAG7936_EXPOSURE_H(reg, exposure_us));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_15_8, PAG7936_EXPOSURE_M(exposure_us));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_MAXEXPO_7_0, PAG7936_EXPOSURE_L(exposure_us));
|
||||
}
|
||||
|
||||
// Force AEC/AGC to reload the new values.
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, SENSOR_UPDATE_FLAG);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, AE_EXPO_MANUAL,
|
||||
(reg & ~AE_EXPO_MANUAL_AE_MANUAL_EN) | (enable ? 0 : AE_EXPO_MANUAL_AE_MANUAL_EN));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, SENSOR_UPDATE_FLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_exposure_us(omv_csi_t *csi, int *exposure_us) {
|
||||
uint8_t exposure_us_17_16, exposure_us_15_8, exposure_us_7_0;
|
||||
int ret = 0;
|
||||
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXP_LINE_NUM_17_16, &exposure_us_17_16);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXP_LINE_NUM_15_8, &exposure_us_15_8);
|
||||
ret |= omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, AE_EXP_LINE_NUM_7_0, &exposure_us_7_0);
|
||||
|
||||
*exposure_us = PAG7936_EXPOSURE(exposure_us_17_16, exposure_us_15_8, exposure_us_7_0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_hmirror(omv_csi_t *csi, int enable) {
|
||||
uint8_t reg;
|
||||
int ret = omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, TG_FLIP, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, TG_FLIP, TG_FLIP_SET_HFLIP(reg, enable));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, 0x80);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, SENSOR_UPDATE_FLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -445,7 +665,7 @@ static int set_vflip(omv_csi_t *csi, int enable) {
|
||||
uint8_t reg;
|
||||
int ret = omv_i2c_readb2(&csi->i2c_bus, csi->slv_addr, TG_FLIP, ®);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, TG_FLIP, TG_FLIP_SET_VFLIP(reg, enable));
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, 0x80);
|
||||
ret |= omv_i2c_writeb2(&csi->i2c_bus, csi->slv_addr, SENSOR_UPDATE, SENSOR_UPDATE_FLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -497,7 +717,12 @@ int pag7936_init(omv_csi_t *csi) {
|
||||
csi->set_pixformat = set_pixformat;
|
||||
csi->set_framesize = set_framesize;
|
||||
csi->set_framerate = set_framerate;
|
||||
csi->set_gainceiling = set_gainceiling;
|
||||
csi->set_colorbar = set_colorbar;
|
||||
csi->set_auto_gain = set_auto_gain;
|
||||
csi->get_gain_db = get_gain_db;
|
||||
csi->set_auto_exposure = set_auto_exposure;
|
||||
csi->get_exposure_us = get_exposure_us;
|
||||
csi->set_hmirror = set_hmirror;
|
||||
csi->set_vflip = set_vflip;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user