一.摘要
自动亮度中最为重要的环节之一就是光感驱动驱动硬件读取环境光数据并计算lux值。它主要的工作原理就是通过读取环境光中的C/R/G/B通道成份,然后通过通道值的大小计算lux值并且上报数据给framework,framework通过不同的lux值计算当前亮度,然后设置手机亮度值。本文主要介绍光感驱动如果计算lux值的过程。
二.代码流程分析
先上一个主要流程,我们根据该流程来逐步分析
1/2.程序开始是每隔十毫秒采集一次光感数据,主要调用的方法为tcs3701_get_lux_cct
if (NULL != state->timer_data_stream)
{
event = state->timer_data_stream->api->peek_input(state->timer_data_stream);
while (NULL != event)
{
pb_istream_t stream = pb_istream_from_buffer((pb_byte_t*)event->event, event->event_len);
if (SNS_TIMER_MSGID_SNS_TIMER_SENSOR_EVENT == event->message_id)
{
sns_timer_sensor_event timer_event;
if (pb_decode(&stream, sns_timer_sensor_event_fields, &timer_event))
{
tcs3701_process_sensor_data(this);
}
......
}
......
}
}
void tcs3701_process_sensor_data(sns_sensor_instance *const instance)
{......
if (status&AINT)
{
tcs3701_get_lux_cct(instance, state->als_registry_cfg.is_dri);
}
......
return;
}
3.读取again/atime/brightness信息
void tcs3701_get_lux_cct(sns_sensor_instance *instance, bool is_dri)
{
......
/* Get ATime, AGain, calculate the saturation level */
tcs3701_inst_i2c_read_byte(state, TCS3701_ASTEPL_REG, &buffer[0]);
tcs3701_inst_i2c_read_byte(state, TCS3701_ASTEPH_REG, &buffer[1]);
TCS3701_DEBUG_REG_SPRINTF(HIGH, sns_fw_printf, "TCS3701 tcs3701_get_lux_cct TCS3701_ASTEPL_REG=0x%x, TCS3701_ASTEPH_REG=0x%x", buffer[0], buffer[1]);
atime = (uint16_t)(((uint32_t)buffer[1] << 8 | (uint32_t)buffer[0])+1) * ASTEP_US_PER_100 / 100.0;
......
tcs3701_inst_i2c_read_byte(state, TCS3701_CFG1_REG, &buffer[0]);
again = tcs3701_get_again(buffer[0]);
TCS3701_DEBUG_REG_SPRINTF(HIGH, sns_fw_printf, "TCS3701 tcs3701_get_lux_cct TCS3701_CFG1_REG=0x%x", buffer[0]);
TCS3701_DEBUG_REG_SPRINTF(HIGH, sns_fw_printf, "TCS3701 tcs3701_get_lux_cct again=%d", again);
TCS3701_DEBUG_REG_SPRINTF(HIGH, sns_fw_printf, "TCS3701 tcs3701_get_lux_cct atime=%d", atime);
TCS3701_DEBUG_REG_SPRINTF(HIGH, sns_fw_printf, "TCS3701 screenInHBMMode =%d", state->screenInHBMMode);
TCS3701_DEBUG_REG_SPRINTF(HIGH, sns_fw_printf, "TCS3701 screenInDCMode =%d", state->screenInDCMode);
TCS3701_DEBUG_REG_SPRINTF(HIGH, sns_fw_printf, "TCS3701 backlight_is_on =%d", state->backlight_is_on);
TCS3701_DEBUG_REG_SPRINTF(HIGH, sns_fw_printf, "TCS3701 first als =%d", state->first_als);
brightness = tcs3701_get_brightness(instance);
......
}
atime是硬件的采样率,again简单理解是C/R/G/B通道的缩放倍数,brightness是当前屏幕的亮度,因为屏下光感的亮度会影响光感的通道值,所以我们的算法中会读取当前手机亮度后边在低光算法中不同的亮度会设置不同的采样率。
4.根据亮度判断使用的算法
if (brightness >= 0) {
if(state->screenInDCMode == true && state->als_info.algorithm_type == LB_ALG) {
atime_adjusted = true;
state->als_info.algorithm_type = HB_ALG;
tcs3701_set_als_time(state, ATIME_HIGH);
} else if (state->screenInDCMode == false) {
atime_adjusted = true;
if (brightness > LOW_TO_HIGH_BRIGHTNESS_LEVEL && state->als_info.algorithm_type == LB_ALG) {
state->als_info.algorithm_type = HB_ALG;
tcs3701_set_als_time(state, ATIME_HIGH);
} else if (brightness < HIGH_TO_LOW_BRIGHTNESS_LEVEL && state->als_info.algorithm_type == HB_ALG) {
state->als_info.algorithm_type = LB_ALG;
} else {
atime_adjusted = false;
}
if (state->als_info.algorithm_type == LB_ALG) {
atime_adjusted = true;
if (brightness <= LOW_BRIGHTNESS_LEVEL1
&& ((atime < (ATIME_LOW_1 - 5)) || (atime > (ATIME_LOW_1 + 5)))) {
tcs3701_set_als_time(state, ATIME_LOW_1);
} else if ((brightness > LOW_BRIGHTNESS_LEVEL1 && brightness <= LOW_BRIGHTNESS_LEVEL2)
&& ((atime < (ATIME_LOW_2 - 5)) || (atime > (ATIME_LOW_2 + 5)))) {
tcs3701_set_als_time(state, ATIME_LOW_2);
} else if ((brightness > LOW_BRIGHTNESS_LEVEL2 && brightness <= LOW_BRIGHTNESS_LEVEL3)
&& ((atime < (ATIME_LOW_3 - 5)) || (atime > (ATIME_LOW_3 + 5)))) {
tcs3701_set_als_time(state, ATIME_LOW_3);
} else if ((brightness > LOW_BRIGHTNESS_LEVEL3 && brightness <= LOW_BRIGHTNESS_LEVEL4)
&& ((atime < (ATIME_LOW_4 - 5)) || (atime > (ATIME_LOW_4 + 5)))) {