硬件设计
当前,移动终端上的按键大部分都是电容按键。电容按键的基本原理跟电容触摸屏是一样的,都是感知被触摸时,电极之间电容值的变化,来判断当前是否有触摸动作。
抛开触摸屏,市面上大部分独立电容按键的设计,都是RC串联电路(如图1),VCC一端不断发出扫描脉冲,使电路中电容C1重复充放电,从而在A点引起电压变化。由于有触摸时,会引起电容值增加,从而引起充放电周期变长。若把有触摸时,电容C1充放电周期为T1,没有触摸时,周期为T0。则T1 > T0
从而能够判断出,当前是否有触摸动作。这种设计在当前普通家电控制面板上很常见,耐用,不易损坏,设计简单。
回到触摸屏这个大环境。由于基本原理的相似性,现有的按键设计都没有用独立的扫描电路,而是从触摸屏控制器里,拉出一条驱动通道用作按键公共端(VCC脚),并把按键的另一端(A脚)连接到触摸屏的感应通道上。从而实现在触摸屏里扩展出电容按键,并由触摸屏控制IC来检测按键是否被触摸。
在触摸屏里,还有一种扩展按键的方法,那就是完全没有按键。直接把触摸屏幕的一部分(一般是底部,30-40高度)用作按键区域,并在触摸屏控制IC的固件里定义相应的按键区域。当触摸点落入这个区域,控制IC就把这次触摸当做按键动作。我们可以把这种方式叫做虚拟电容按键,上面介绍的方法叫做独立电容按键。虚拟电容按键的好处就是,不需要在触摸屏里植入额外的感应电极,触摸屏制作厂商只需在丝印工序阶段,在规定的区域印上特定的按键形状就可以了。
软件处理(基于Android)
触摸屏上的虚拟电容按键和独立电容按键有一个共性,那就是两者都是由触摸屏控制IC来控制。也就是说,其往驱动层上报数据的格式也是由控制IC决定的。
懒人模式
控制IC对按键的处理也分为两种,一种是懒人模式,就是什么都不做,把按键当做触摸一样处理,直接上报具体的坐标给驱动层,把按键解析的工作完全推给上层软件。
在这种模式下,触摸屏的驱动里,其实也不会做什么按键处理,而是继续把触摸坐标往Android上层传递。一般会提前在驱动层定义好相应的按键区域,并把该配置信息通过linux kernel的sysfs暴露给上层。比如://按键数量
#define TPD_KEY_COUNT 4
//按键中心坐标
#define key_1 60,850
#define key_2 180,850
#define key_3 300,850
#define key_4 420,850
//按键类型
#define TPD_KEYS {KEY_BACK, KEY_HOME, KEY_MENU, KEY_SEARCH}
//按键区域,每个数字分别表示:{X_CENTER, Y_CENTER, X_RANGE, Y_RANGE}
#define TPD_KEYS_DIM { {key_1,50,30}, {key_2,50,30}, {key_3,50,30}, {key_4,50,30} }
而在Android Native层,frameworks/base/services/input/EventHub.cpp:loadVirtualKeyMapLocked会去读取这个按键配置文件,具体定义在源文件frameworks/base/libs/androidfw/VirtualKeyMap.cpp。
这里要注意的是,在驱动层,并不是所有的情况下,都把按键解析工作传递给上层。当手机处于factory mode和recovery mode的时候,由于Android上层并没有运行起来,所以在这种情况下,驱动层还是得做按键解析工作。
好人模式
触控IC的另一种模式是“好人模式”,这种模式下,触控IC会专门分配寄存器标志位给每一个电容按键,用来标示当前按键状态。驱动层读到这个状态后,也会直接利用input_report_key上报keyevent给Android上层。
结语
当然,这里阐述的只是正常流程下的处理。对于一些有特殊需求的,可能需要触控IC固件、触摸屏驱动和Android上层三者相互配合,处理情况也和这里阐述的不一样。