SAR 口作为IC 的input 端,一般采集连续的电压值,然后根据区间划分转换成码值,基于
这一个特性,按键板,部分温控器件,光感器件可以使用该特性完成一个ADC转换的效
果。
如上面两图,是按键板的与芯片端的SAR 物理连接图,按键down 之后,产生的电压值
变化通过SAR 口进入芯片,驱动SAR 模块通过上层配置,来将不同电压区间 映射成对
应键值传递上去。
MDrv_SYS_GlobalInit();
mdrv_gpio_init();
. . . . . .
MDrv_MIU_SetIOMapBase();
SAR_KpdRegCfg SARCfg;
MDrv_SAR_Kpd_Init();
int i, j;
for (i = 0; i < MAX_KEYPAD_CH; i++) {
if (BOARD_KPD[i].bEnable == false) {
continue;
}
SARCfg.u8SARChID = BOARD_KPD[i].u8SARChID;
SARCfg.tSARChBnd.u8UpBnd = BOARD_KPD[i].tSARChBnd.u8UpBnd;
SARCfg.tSARChBnd.u8LoBnd = BOARD_KPD[i].tSARChBnd.u8LoBnd;
SARCfg.u8KeyLevelNum = BOARD_KPD[i].u8KeyLevelNum;
for (j = 0; j < 8; j++) {
SARCfg.u8KeyThreshold[j] = BOARD_KPD[i].u8KeyThreshold[j];
SARCfg.u8KeyCode[j] = BOARD_KPD[i].u8KeyCode[j];
}
// 将电压值的区间 和 对应 keycode 的映射关系(SARCfg.u8KeyThreshold ,SARCfg.u8KeyCode)
// 设置到SAR 驱动里面
if (MDrv_SAR_Kpd_SetChInfo(&SARCfg) == E_SAR_KPD_FAIL) {
ALOGV("DFBInfo MDrv_SAR_Config: CH_%d fails\n", i);
return FALSE;
}
}
MDrv_SAR_Kpd_SetChInfo 接口完成电压值和keycode 映射关系 的注册。
完成之后就可以监听获取按键板事件了,如下:
while (1) {
ret = E_SAR_KPD_FAIL;
u8Keycode = NULL_KEYVALUE;
u8Repeat = 0;
/* sleep an interval time */
usleep(keypad_input_interval);
ret = MDrv_SAR_Kpd_GetKeyCode(&u8Keycode, &u8Repeat);
/* check the get keycode successfully */
if (ret != E_SAR_KPD_OK) {
loop_count += 1;
if (loop_count == SLOW_POLLING_BOUNDARY)
keypad_input_interval = KEYPAD_INPUT_SLOW_POLLING;
if (repeatKey != NULL_KEYVALUE) {
write_event_to_device(repeatKey, 0);
repeatKey = NULL_KEYVALUE;
}
continue;
}
/* check the keypad is vaild? */
if (u8Keycode == NULL_KEYVALUE) {
loop_count += 1;
if (loop_count == SLOW_POLLING_BOUNDARY)
keypad_input_interval = KEYPAD_INPUT_SLOW_POLLING;
continue;
}
/* fill event to uinput device. */
if (u8Repeat == 1) {
repeatKey = u8Keycode;
}
write_event_to_device(u8Keycode, u8Repeat);
loop_count = 0;
keypad_input_interval = KEYPAD_INPUT_NORMAL_POLLING;
}
MDrv_SAR_Kpd_GetKeyCode 接口可以获取到按键板按键的down 事件轮训周期间隔可
以自行设置。
MDrv_SAR_Adc_Config(1, TRUE);
adc1 = MDrv_SAR_Adc_GetValue(1);
MDrv_SAR_Adc_Config 接口来设置SAR 通道的开启和关闭,参数1 表示对应的参数id
从0 开始,参数2 TRUE/FALSE 分别 表示 开启/关闭 。
MDrv_SAR_Adc_GetValue 接口就是直接获取SAR 口外设产生的原始ADC值,也即是映射之前的原始值。M平台更多SAR口的操作方法参考libraries\utopia\include\drvSAR.h
文件。
注意:sar 通道必须根据原理图的实际连接进行设置,否则连接的外设无法使用。
void MSrv_Control_DVB::LUT_Monitor_Service(void)
{
. . . . . .
if((mapi_time_utility::GetTime0() - u32LutTimer) > 1000)
{
u32LutTimer = mapi_time_utility::GetTime0();
// SAR 2 口的
U8 u8ADCLevel = MSrv_Control::GetInstance()->GetSarAdcLevel(KEYPAD_ADC_CHANNEL_2);
if ((u8PreCDegree > 0)
&& (u8ADCLevel >= stOsLutAdc[u8PreCDegree-1].u8TempFallingEdge))
{
for(int i=0; i= stOsLutAdc[i].u8TempFallingEdge)
{
u8CDegree = i;
break;
}
}
}
else if ((u8PreCDegree < OS_LUT_MAX_C_DEGREE-1)
&& (u8ADCLevel <= stOsLutAdc[u8PreCDegree+1].u8TempRisingEdge))
{
for(int i=OS_LUT_MAX_C_DEGREE-1; i>0; i--)
{
if (u8ADCLevel <= stOsLutAdc[i].u8TempRisingEdge)
{
u8CDegree = i;
break;
}
}
}
else
{
u8CDegree = u8PreCDegree;
}
// 2nd step: Check V Sync
U16 u16OutVFreq = MApi_XC_GetOutputVFreqX100();
if (u16OutVFreq < 5500)
{
u8FPS = OS_LUT_FPS_50;
}
else
{
u8FPS = OS_LUT_FPS_60;
}
// 3rd step: Change OS LUT.
if ((u8FPS != u8PreFPS)
|| (u8CDegree != u8PreCDegree))
{
MAPI_U8 *pu8SharpOsLutCtrlTab;
MAPI_U32 u32SharpTconDevId;
if (m_bIsSharpTconModel_Elan)
{
pu8SharpOsLutCtrlTab = u8SharpElanOsLutCtrlTab;
u32SharpTconDevId = SHARP_ELAN_TCON_CTRL;
u8SharpElanOsLutCtrlTab[3] = (U8)((u8SharpElanOsLutRegTab[u8FPS][u8CDegree]>>8)&0xFF);
u8SharpElanOsLutCtrlTab[4] = (U8)(u8SharpElanOsLutRegTab[u8FPS][u8CDegree]&0xFF);
}
else
{
pu8SharpOsLutCtrlTab = u8SharpEspritOsLutCtrlTab;
u32SharpTconDevId = SHARP_ESPRIT_TCON_CTRL;
u8SharpEspritOsLutCtrlTab[3] = (U8)(u8SharpEspritOsLutRegTab[u8FPS][u8CDegree]&0xFF);
}
MAPI_U8 u8retryCnt = 0;
do
{
if (MSrv_Control::GetInstance()->WriteBytesToI2C(u32SharpTconDevId, 2, pu8SharpOsLutCtrlTab+1, *pu8SharpOsLutCtrlTab, pu8SharpOsLutCtrlTab+3))
{
pu8SharpOsLutCtrlTab += (*pu8SharpOsLutCtrlTab+1+2);
u8retryCnt = 0;
}
else
{
u8retryCnt++;
if (u8retryCnt > 3)
{
printf("[%s]I2C Error: change OS Lut fail.\n", __FUNCTION__);
return;//break;
}
}
} while (*pu8SharpOsLutCtrlTab!=0);
u8PreFPS = u8FPS;
u8PreCDegree = u8CDegree;
}
}
}
先通过MSrv_Control::GetInstance()->GetSarAdcLevel 获取SAR 2 口的温控器件的ADC
值,接着计算转成TCON板的参数,MSrv_Control::GetInstance()->WriteBytesToI2C
接口再将TCON参数通过IIC 地址写到TCON上,来改变TCON板的状态。
U8 MSrv_Control_common::GetSarAdcLevel(U8 u8Channel)
{
U8 u8Ret;
u8Ret = mapi_sar::GetInstance()->GetSarAdcLevel(u8Channel);
return u8Ret;
}
MAPI_U8 mapi_sar::GetSarAdcLevel(MAPI_U8 u8Channel)
{
return m_pImpl->GetSarAdcLevel(u8Channel);
}
MAPI_U8 mapi_sar_impl::GetSarAdcLevel(MAPI_U8 u8Channel)
{
MDrv_SAR_Adc_Config(u8Channel, MAPI_TRUE);
usleep(50);//delay 0.05 ms here for getting the right adc level
return MDrv_SAR_Adc_GetValue(u8Channel);
}
sar 模块的demo示例也可以查看DFBInfo.cpp。
另外,附上一张A平台ADC key 使用示例