引言
在PDA和中高端手机等手持设备中,触摸屏已经成为一种比较常用的输入设备,用户可以通过在触摸屏上的点击和写划完成与手持设备的交互。此外,由于基于触摸屏的中文手写输入法更符合我国各个文化层次的人使用,因此越来越多地出现在时下流行的各种手持设备中。大多数中文手写输入法完全由软件来实现,将输入法界面程序和后台识别算法集成到一起。其好处是不改变系统的硬件结构,而且便于升级;然而,使用商用的手写识别算法,较为高昂的费用和繁重的移植工作,会大大增加开发成本和延长开发周期。若使用开源的手写识别源代码(如kanjipad)进行移植开发,则一方面涉及移植的工作量问题,另一方面识别率比较低。针对以上这些由软件实现中文手写输入法所带来的一系列问题,本文提出一种在“PXA255微处理器+Linux+Qtopia图形界面”上由HW006芯片同时实现中文手写输入及触摸屏控制的设计方案。该方案有以下几个优点:
◇ 软件方面将触摸屏驱动和手写识别的工作合二为一。
◇ 完全在用户空间实现触摸屏的驱动,减少了硬件平台的依赖性,降低了驱动设计的难度,分层的驱动设计思想也不会破坏原有程序的完整性。
◇ 硬件方面,省去了专用的触摸屏控制器芯片,降低了成本。
因此,该方案在工作量、成本、难度方面均有着明显的优势,从而大大缩短了开发周期,增强了实用性。
1 HW006简介
HW006是一款汉王手写芯片,它内置了触摸屏控制电路和对外的UART接口,同时提供了灵活的控制命令接口,可以满足触摸屏LCD分离型、触摸屏LCD一体型等不同情况下的各种应用需求。
1.1 HW006主要功能
◇ 支持6 763个简体中文(GB2312)、52个英文大小写字母、10个数字、12个常用符号的手写识别输入,并可自由组合,设置识别范围;
◇ 支持点击模式、手写模式和混合模式;
◇ 内嵌触摸屏控制硬件和软件,可直接与触摸屏相连接;
◇ 支持异步串行通信接口(UART),通信波特率可设置,便于与各种CPU进行通信;
◇ 在手写状态下,识别参数可设置。
可见,HW006完全可以实现预想的功能。根据实际需要,选用混合模式。
1.2 HW006的通信协议
HW006为从设备,主设备对该芯片发送控制命令,HW006可以执行相应的功能。
(1) 主设备向手写芯片发送命令
格式如下:
(2) 手写芯片向主设备发送数据
这里主要介绍混合模式下的数据格式,如下:
在混合模式下,手写芯片先发送轨迹坐标,属性表示该点的状态:0x00,落笔;0x05,移笔;0x0f,抬笔。EOF表示发送轨迹结束标志,其值为0xff。之后发送识别字的编码,低字节在前,高字节在后。
1.3 命令码的简单介绍
对HW006进行操作控制的主要命令码如表1所列。
表1 HW006的主要命令码
2 硬件框图以及通信格式简介
硬件框图如图1所示。
图1 硬件框图
UART通信格式: 上电默认波特率,9 600 bps;数据位,8位;校验位,无;停止位,1位;先低位后高位。触摸屏采用了4线电阻屏,在触摸屏与HW006连线处,需要加上滤波电容。
上电初始化时,默认工作模式为点击模式。用户可根据应用需要,设置相应工作模式。使用混合模式时必须通过UART给系统发送4个数据X1、Y1、X2、Y2,以确定矩形手写区域的范围。
3 手写输入法及触摸屏驱动的实现
选用的图形界面系统Qtopia是由Trolltech公司所开发的专门用于嵌入式Linux操作系统电子设备的应用平台,这里使用开放源代码的Qtopia PDA版。它具有可定制的用户界面和集成的组件,其组件包括窗口操作界面、游戏和多媒体、PIM应用程序、输入法、本地化支持和无线支持等。对于输入法,它提供了一系列的通用API,便于开发用户自己的输入法。
Qtopia软件平台可分为4个层次,如图2所示。
图2 Qtopia软件平台层次结构
其中在Qt/Embedded层提供了触摸屏的API,在Qtopia层提供了输入法的API。需要完成的工作: ① 在Linux层编写触摸屏库,提供给Qt/Embedded层调用;② 改写Qt/Embedded层的触摸屏API;③ 在Qtopia层利用输入法API完成手写输入法的手写显示和识别字显示的界面。下面详细介绍以上步骤。
3.1 在Linux层编写触摸屏库
主要是提供设置HW006工作模式、读/写HW006数据以及对读到的数据进行发送的接口函数,最终编译成动态链接库,可供上层的应用程序调用。主要的接口函数及程序的主要代码如下:
(1) 打开串口
int *ts_open(const char * device) {
…
*fd=open(device,O_RDWR| O_NONBLOCK);
if ( (*fd) < 0 ){
printf("open error!\n");
return NULL;
}
return fd;
}
(2) 设置HW006的混合工作模式
void ts_config(int* fd) {
…
write(*fd,&SET_96,2); //设置HW006波特率为9600bps
write(*fd,&SET_X1,2);
write(*fd,&SET_Y1,2);
write(*fd,&SET_X2,2);
write(*fd,&SET_Y2,2);//设置手写区域4个角的坐标
write(*fd,&WAIT_T,2);//设置汉字识别等待时间
write(*fd,®_SCOPE,2);//设置识别范围
write(*fd,®_CAN,2);//设置识别字候选个数
…
}
(3) 读串口
int ts_read(int *fd,unsigned char *buf) {
int res;
res=read(*fd,buf,3);
return res;
}
(4) 发送到有名管道
void sendFifo(unsigned char* buf,int i) {
…
fd=open("/dev/myfifo",O_WRONLY | O_NONBLOCK);
write(fd,buf,i);
close(fd);
}
3.2 改写Qt/Embedded层的触摸屏API
对读到的原始数据进行处理,包括变换、校正、分发等。Qt/Embedded中提供触摸屏API的文件是qwsmouse_qws.cpp,其中的类QCalibratedMouseHandler实现了对触摸屏数据的读取及其处理。本文所用的HW006是8位的,而显示分辨率是640×480,因此在读到触摸屏数据时还要进行转换。又因为HW006工作在混合模式状态下,因此需要把所读到的坐标数据和汉字码分开,将坐标数据进行转换后送给图形界面,并将汉字码送给输入法,这涉及到了不同进程之间通信的问题。不同进程之间的通信主要有管道、共享内存、消息队列等几种方式。其中: 共享内存速度最快,在传送大量数据时比较有优势;管道最容易实现,这里需要传送的数据量不大,因此选用管道的通信方式。
在qwsmouse_qws.cpp中,定义了一个对触摸屏数据进行处理的类——QSitsangTPanelHandlerPrivate。该类继承了QCalibratedMouseHandler。在它的构造函数中,利用Linux层提供的函数打开串口,设置HW006工作模式;再利用QT特有的信号和槽机制,定义一个QSocketNoTIfier类把串口描述符和QSitsangTPanelHandlerPrivate类的成员函数——读触摸屏数据函数readTSData()连接起来,实现对串口数据的自动监视与读取。
部分代码如下:
QSitsangTPanelHandlerPrivate::QSitsangTPanelHandlerPrivate(MouseProtocol, QString) {
fd=ts_open("/dev/ttyS1");
…
ts_config(fd);
QSocketNoTIfier *mouseNoTIfier;
TS_NoTIfier=new QSocketNotifier(*fd, QSocketNotifier::Read, this);
connect(TS_Notifier, SIGNAL(activated(int)),this, SLOT(readTSData()));
}
读触摸屏数据函数readTSData()的程序流程如图3所示。
图3 读触摸屏数据函数的流程
3.3 完成手写显示和识别字显示界面
手写输入法的具体实现是在Qtopia层,利用Qtopia提供的API来完成中文手写输入法的手写显示及识别字显示。在这里利用输入法插件接口——InputMethodInterface类,通过对该类的继承以及对该类成员函数的重载,完成手写输入法,最终编译成链接库形式,被Qtopia服务器自动调用。
class QTOPIA_PLUGIN_EXPORT UniKeyboardImpl : public InputMethodInterface {
public:
…
Q_REFCOUNT
virtual QWidget*inputMethod(QWidget*parent, Qt::WFlags f);
//需要重载的虚函数,在该函数中可以添加用户自定义的输入法类
…
private:
HandWrKeyboard *input;
//HandWrKeyboard是手写输入法的类
…
};
函数virtual QWidget *inputMethod( QWidget *parent, Qt::WFlags f )重载为:
QWidget *UniKeyboardImpl::inputMethod( QWidget *parent, Qt::WFlags f ) {
if ( !input )
input=new HandWrKeyboard( parent, "HandWriting", f );
return input;
}
从功能上手写输入法软件部分可分为两种:显示笔划轨迹与显示识别候选字。
触摸屏和HW006连接部分是完全的模拟量,由于液晶逆变器高频高压的干扰,笔划轨迹变得明显,与实际所写轨迹不符。除了需要在硬件上加滤波电容外,软件中也需要进行一定的修正。这里,采用3点均值滤波的方式来减小噪声干扰的影响。
在读到第一个点时,不做处理;读到2个点时,取这2个值的平均。这样,得到的坐标数据量不会不足,而且均值滤波可以很好地消除噪声的影响。
读汉字码是通过读有名管道来实现的。经过实验,发现HW006在发送汉字码时,偶尔会出现发送的个数与所设置的不符。我们设置的识别字个数是5个,共10字节的数据。但如果所写的汉字比较简单,HW006可能识别不了5个汉字,这样发送给管道的数据不足10字节,结果会造成最终显示错误。为此,在读取汉字码的开始和结束处分别加一个起始位和结束位,这样根据读取管道得到的汉字码个数和起始位、结束位来判断识别结束,将最终得到的识别汉字正确地显示出来。
4 结论
在“PXA255+Linux+Qtopia”平台上的运行及测试结果表明手写识别率能达到95%以上。由于HW006也实现了触摸屏控制器的功能,在硬件结构上完全可以代替原来的触摸屏控制器,因此并没有增加硬件的成本和复杂度。从上面的分析可以清楚地看出,此设计方案具有实用性和普遍意义,完全可以应用于其他嵌入式平台上。