drivers/video/isx019: Fix supported ISO sensitivity

Support not continuous values but discrete values.
This commit is contained in:
SPRESENSE 2023-10-17 10:09:40 +09:00 committed by Alin Jerpelea
parent 75a0a08a4d
commit f1bc6aada3
1 changed files with 130 additions and 50 deletions

View File

@ -221,7 +221,6 @@ struct isx019_dev_s
uint8_t flip_still;
isx019_rect_t clip_video;
isx019_rect_t clip_still;
int32_t iso;
double gamma;
int32_t jpg_quality;
imgsensor_colorfx_t colorfx;
@ -797,6 +796,96 @@ static const int32_t g_isx019_wbmode[] =
#define NR_WBMODE (sizeof(g_isx019_wbmode) / sizeof(int32_t))
static int32_t g_isx019_iso[] =
{
1000, /* ISO1 */
1200, /* ISO1.2 */
1600, /* ISO1.6 */
2000, /* ISO2 */
2500, /* ISO2.5 */
3000, /* ISO3 */
4000, /* ISO4 */
5000, /* ISO5 */
6000, /* ISO6 */
8000, /* ISO8 */
10000, /* ISO10 */
12000, /* ISO12 */
16000, /* ISO16 */
20000, /* ISO20 */
25000, /* ISO25 */
32000, /* ISO32 */
40000, /* ISO40 */
50000, /* ISO50 */
64000, /* ISO64 */
80000, /* ISO80 */
100000, /* ISO100 */
125000, /* ISO125 */
160000, /* ISO160 */
200000, /* ISO200 */
250000, /* ISO250 */
320000, /* ISO320 */
400000, /* ISO400 */
500000, /* ISO500 */
640000, /* ISO640 */
800000, /* ISO800 */
1000000, /* ISO1000 */
1250000, /* ISO1250 */
1600000, /* ISO1600 */
2000000, /* ISO2000 */
2500000, /* ISO2500 */
3200000, /* ISO3200 */
4000000, /* ISO4000 */
5000000, /* ISO5000 */
};
#define NR_ISO (sizeof(g_isx019_iso) / sizeof(int32_t))
/* Gain values corresponding to each element of g_isx019_iso table.
* This needs to have the same size as g_isx019_iso.
*/
static const uint8_t g_isx019_gain[] =
{
1, /* gain for ISO1 */
2, /* gain for ISO1.2 */
3, /* gain for ISO1.6 */
4, /* gain for ISO2 */
5, /* gain for ISO2.5 */
6, /* gain for ISO3 */
7, /* gain for ISO4 */
8, /* gain for ISO5 */
9, /* gain for ISO6 */
10, /* gain for ISO8 */
11, /* gain for ISO10 */
12, /* gain for ISO12 */
13, /* gain for ISO16 */
14, /* gain for ISO20 */
15, /* gain for ISO25 */
16, /* gain for ISO32 */
17, /* gain for ISO40 */
18, /* gain for ISO50 */
19, /* gain for ISO64 */
20, /* gain for ISO80 */
21, /* gain for ISO100 */
22, /* gain for ISO125 */
23, /* gain for ISO160 */
24, /* gain for ISO200 */
25, /* gain for ISO250 */
26, /* gain for ISO320 */
27, /* gain for ISO400 */
28, /* gain for ISO500 */
29, /* gain for ISO640 */
30, /* gain for ISO800 */
31, /* gain for ISO1000 */
32, /* gain for ISO1250 */
33, /* gain for ISO1600 */
34, /* gain for ISO2000 */
35, /* gain for ISO2500 */
36, /* gain for ISO3200 */
37, /* gain for ISO4000 */
38, /* gain for ISO5000 */
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -1875,9 +1964,11 @@ static int isx019_get_supported_value(FAR struct imgsensor_s *sensor,
break;
case IMGSENSOR_ID_ISO_SENSITIVITY:
val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
SET_RANGE(val->u.range, MIN_ISO, MAX_ISO,
STEP_ISO, def->iso);
val->type = IMGSENSOR_CTRL_TYPE_INTEGER_MENU;
SET_DISCRETE(val->u.discrete,
NR_ISO,
g_isx019_iso,
0);
break;
case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO:
@ -2578,18 +2669,21 @@ static int set_3aparameter(FAR isx019_dev_t *priv,
return OK;
}
static uint16_t calc_gain(double iso)
static uint16_t get_gain_from_iso(int32_t iso)
{
double gain;
int i;
gain = 1 + 10 * log(iso) / M_LN10;
for (i = 0; i < NR_ISO; i++)
{
if (g_isx019_iso[i] == iso)
{
break;
}
}
/* In the above formula, the unit of gain is dB.
* Because the register has the 0.1dB unit,
* return 10 times dB value.
*/
/* Return gain corresponding to specified ISO sensitivity. */
return (uint16_t)(gain * 10);
return (uint16_t)g_isx019_gain[i];
}
static int set_iso(FAR isx019_dev_t *priv,
@ -2601,10 +2695,9 @@ static int set_iso(FAR isx019_dev_t *priv,
* So, calculate gain from ISO sensitivity.
*/
gain = calc_gain(val.value32 / 1000);
gain = get_gain_from_iso(val.value32) * 10;
isx019_i2c_write(priv, CAT_CATAE, GAIN_PRIMODE, &gain, 2);
priv->iso = val.value32;
return OK;
}
@ -2617,7 +2710,6 @@ static int set_iso_auto(FAR isx019_dev_t *priv,
if (val.value32 == IMGSENSOR_ISO_SENSITIVITY_AUTO)
{
gain = 0;
priv->iso = 0;
}
else /* IMGSENSOR_ISO_SENSITIVITY_MANUAL */
{
@ -2635,8 +2727,6 @@ static int set_iso_auto(FAR isx019_dev_t *priv,
isx019_i2c_read(priv, CAT_AECOM, GAIN_LEVEL, &buf, 1);
gain = buf * 3;
}
priv->iso = val.value32;
}
return isx019_i2c_write(priv, CAT_CATAE, GAIN_PRIMODE, &gain, 2);
@ -3293,56 +3383,46 @@ static int get_3astatus(FAR isx019_dev_t *priv,
return OK;
}
static double calc_iso(double gain)
static int32_t get_iso_from_gain(uint8_t gain)
{
int k;
double z;
double r;
int i;
/* ISO sensitivity = 10^((gain - 1) / 10)
* So, replace z = (gain - 1) / 10 and
* calculate 10^z.
*/
/* g_isx019_gain and g_isx019_iso has the common index. */
/* Divide z into integer and other parts.
* z = log10(E) (k * ln2 + r)
* (k : integer, r < 0.5 * ln2)
*
* Then, 10^z = (2^k) * e^r (r < 0.5 * ln2)
*/
for (i = 0; i < NR_ISO; i++)
{
if (g_isx019_gain[i] == gain)
{
break;
}
}
z = (gain - 1) / 10;
if (i >= NR_ISO)
{
i = NR_ISO - 1;
}
k = z * M_LN10 / M_LN2;
r = z * M_LN10 - k * M_LN2;
return (1 << k) * exp(r);
return g_isx019_iso[i];
}
static int get_iso(FAR isx019_dev_t *priv,
FAR imgsensor_value_t *val)
{
uint8_t buf = 0;
uint8_t gain = 0;
if (val == NULL)
{
return -EINVAL;
}
if (priv->iso == 0)
{
/* iso = 0 means auto adjustment mode.
* In such a case, get gain from auto adjustment value register,
* which has the unit 0.3dB, and convert the gain to ISO.
*/
/* The current gain value register has the 0.3dB unit.
* So, round the gain to integer, and convert to ISO.
*/
isx019_i2c_read(priv, CAT_AECOM, GAIN_LEVEL, &buf, 1);
val->value32 = calc_iso((double)buf * 0.3) * USEC_PER_MSEC;
}
else
{
val->value32 = priv->iso;
}
isx019_i2c_read(priv, CAT_AECOM, GAIN_LEVEL, &gain, 1);
gain = ((gain * 3) + 5) / 10;
val->value32 = get_iso_from_gain(gain);
return OK;
}