说明
之前的文章有提到,关于sensor 的曝光增益逻辑,如果模组厂提供了完整的参考代码,可以无痛使用的话,就能很方便移植。但如果模组厂提供的参考代码不合适,或者只提供了Excel表格,这时候曝光增益逻辑函数就需要自己去写一下。
一般模组厂提供了Excel表格,那曝光增益逻辑基本上都是查表法,表格一列是sensor 的增益,另一列是具体gain 对应的增益寄存器的值,我们所实现的曝光增益逻辑函数的功能,就是根据传进来的实际gain值,查表得出寄存器值,然后写进去寄存器就好了。
然后就是,如果提供的参数需要取整的话,做一些取整操作,基本就这些。
示例
示例使用 ov02b10 驱动,模组厂提供的曝光增益表和参考代码是这样的:
我这边使用了第二个表格,从gain值得到reg的值,右侧的计算函数没什么必要,实际就是 reg = gain * 16 ,直接使用查表法。另外就是左侧增益值范围 1~15.5,中间有不少的小数,做了一下取整操作,取整幅度乘以1024,具体代码实现如下,也是参考其他sensor驱动写的:
static int setSensorGain(struct v4l2_subdev *sd, int gain)
{
#define ISP_BASE_GAIN 16 //驱动的增益最小值为 1 << 4 = 16
#define SENSOR_BASE_GAIN 1024 //取整步距
#define SENSOR_MAX_GAIN 15872 //换算得出的最大增益值 15.5*1024
int i;
uint32_t temp_gain = 0;
int32_t gain_index;
int isp_gain = gain;
int sensor_gain = 0;
struct sensor_info *info = to_state(sd);
sensor_gain = isp_gain < ISP_BASE_GAIN ? ISP_BASE_GAIN : isp_gain; //限定增益数值,最小值以下按最小值处理
sensor_gain = sensor_gain * SENSOR_BASE_GAIN / ISP_BASE_GAIN; //换算增益值,除以16,乘以1024,得出查表第一列的值
if (SENSOR_MAX_GAIN < sensor_gain)
sensor_gain = SENSOR_MAX_GAIN; //超过最大值的按最大值处理
uint16_t OV02B10_AGC_Param[][2] ={
{1 *1024, 0x10},
{1.0625 *1024, 0x11},
{1.125 *1024, 0x12},
{1.1875 *1024, 0x13},
{1.25 *1024, 0x14},
{1.3125 *1024, 0x15},
{1.375 *1024, 0x16},
{1.4375 *1024, 0x17},
{1.5 *1024, 0x18},
{1.5625 *1024, 0x19},
{1.625 *1024, 0x1A},
{1.6875 *1024, 0x1B},
{1.75 *1024, 0x1C},
{1.8125 *1024, 0x1D},
{1.875 *1024, 0x1E},
{1.9375 *1024, 0x1F},
{2 *1024, 0x20},
{2.125 *1024, 0x22},
{2.25 *1024, 0x24},
{2.375 *1024, 0x26},
{2.5 *1024, 0x28},
{2.625 *1024, 0x2A},
{2.75 *1024, 0x2C},
{2.875 *1024, 0x2E},
{3 *1024, 0x30},
{3.125 *1024, 0x32},
{3.25 *1024, 0x34},
{3.375 *1024, 0x36},
{3.5 *1024, 0x38},
{3.625 *1024, 0x3A},
{3.75 *1024, 0x3C},
{3.875 *1024, 0x3E},
{4 *1024, 0x40},
{4.25 *1024, 0x44},
{4.5 *1024, 0x48},
{4.75 *1024, 0x4C},
{5 *1024, 0x50},
{5.25 *1024, 0x54},
{5.5 *1024, 0x58},
{5.75 *1024, 0x5C},
{6 *1024, 0x60},
{6.25 *1024, 0x64},
{6.5 *1024, 0x68},
{6.75 *1024, 0x6C},
{7 *1024, 0x70},
{7.25 *1024, 0x74},
{7.5 *1024, 0x78},
{7.75 *1024, 0x7C},
{8 *1024, 0x80},
{8.5 *1024, 0x88},
{9 *1024, 0x90},
{9.5 *1024, 0x98},
{10 *1024, 0xA0},
{10.5 *1024, 0xA8},
{11 *1024, 0xB0},
{11.5 *1024, 0xB8},
{12 *1024, 0xC0},
{12.5 *1024, 0xC8},
{13 *1024, 0xD0},
{13.5 *1024, 0xD8},
{14 *1024, 0xE0},
{14.5 *1024, 0xE8},
{15 *1024, 0xF0},
{15.5 *1024, 0xF8},
};
if (sensor_gain < SENSOR_BASE_GAIN)
sensor_gain = SENSOR_BASE_GAIN;
if (sensor_gain > SENSOR_MAX_GAIN)
sensor_gain = SENSOR_MAX_GAIN;
uint32_t total_cnt = (sizeof(OV02B10_AGC_Param)/sizeof(OV02B10_AGC_Param[0]));
for (gain_index = 0; gain_index < total_cnt -1; gain_index++) //对比查表得出对应增益的寄存器数值
{
if((sensor_gain >= OV02B10_AGC_Param[gain_index][0])&&(sensor_gain <= OV02B10_AGC_Param[gain_index+1][0]))
{
if((sensor_gain-OV02B10_AGC_Param[gain_index][0]) <= (OV02B10_AGC_Param[gain_index+1][0]-sensor_gain))
temp_gain = OV02B10_AGC_Param[gain_index][1];
else
temp_gain = OV02B10_AGC_Param[gain_index+1][1];
break;
}
}
sensor_dbg("OV02B10_AGC_Param[gain_index][1] = 0x%x, temp_gain = 0x%x, sensor_gain = 0x%x, total_cnt = %d\n",
OV02B10_AGC_Param[gain_index][1], temp_gain, sensor_gain, total_cnt);
sensor_write(sd, 0xfd, 0x01); //将寄存器数值写入寄存器
sensor_write(sd, 0x22, temp_gain);
sensor_write(sd, 0xfe, 0x02);
info->gain = temp_gain;
return 0;
}
以上代码提供一种参考的思路,有问题还请指正,一键三连,感谢!