摘 要:结合图像调焦系统的实际应用需求,提出一种基于OMAP(Open Multimedia Application Plant)处理器的图像调焦系统方案,给出了处理器与触摸显示屏的接口硬件设计,分析了在Linux系统下的接口驱动开发,讨论了实际应用中存在的图像分辨率变换及触点窗口形成两个关键问题,将输入的图像数据及对焦窗口成比例显示在液晶屏上。在自动选择的对焦窗口不满足要求时,使用触摸屏来重新调整对焦窗口,从而实现人工参与对焦窗口的快速选择及调整,满足了特定领域对图像调焦系统的特殊要求。
关键词:对焦窗口;触摸显示屏;OMAP处理器;Linux驱动
1 引 言
基于图像处理的自动调焦是近年来人们重点研究的一种调焦技术,一些行之有效的图像调焦算法[1,2]已被提出并成功应用于工程领域。对焦窗口的自动选择一直是图像调焦技术中的难点之一,尽管人们提出了一些自动对焦窗口选择算法[3],但是在一些特殊应用领域,如光电测量系统,往往要求对感兴趣的目标进行调焦成像,这时就需要人工参与自动对焦窗口的选择,并能将结果迅速通知处理器。本文提出了一种基于OMAP处理器的图像调焦系统,着重阐述了处理器与触摸显示屏的接口设计及Linux驱动开发,所采集的图像数据及自动选择的对焦窗口可以显示在液晶屏上,如果自动对焦窗口中目标不是所感兴趣的,则可用手指触碰触摸屏来指定调焦目标,处理器以触点位置为中心形成新的对焦窗口,完成人工参与对焦窗口的快速选择及调整。
2 系统硬件结构
所设计的图像调焦系统选用TI公司的高性能低功耗OMAP-L137处理器[4]。该处理器采用ARM+DSP双核架构,内嵌ARM926EJ核及C674x系列DSP核,工作频率达300 MHz,ARM核带有MMU单元,支持嵌入式Linux、WinCE等操作系统。系统利用DSP核完成复杂的图像调焦算法,利用ARM核实现图像调焦系统的综合控制功能,处理器片上集成LCD控制器及SPI接口,用来实现与液晶显示屏及触摸屏控制器的无缝连接,系统结构如图1所示。

图1 系统结构图
Fig.1 Diagram of system structure
外部数字图像数据输入FPGA并在内部SRAM中缓冲,接着在FPGA时序控制下转移至SDRAM存储区。处理器通过EMIFB接口产生SDRAM控制时序,经过FPGA连接4片4M× 16 bit×4的SDRAM芯片,组成128 MB外部扩展存储区。其中两片SDRAM由FPGA控制交替存储图像数据,保证DSP处理图像数据的同时另一片继续缓存外部图像数据;另外两片SDRAM作为系统扩展RAM,用于操作系统、应用程序及数据的存储区域。系统上电后,DSP核启动运行引导程序,将处理器的EMIFA接口配置成NAND FLASH接口,并将FALSH里的操作系统及应用程序引导至系统扩展RAM中,之后启动ARM核,将系统控制权交于ARM核及操作系统管理。操作系统加载液晶显示驱动程序后,将EMIFA接口配置成LCD控制器同时禁用NAND FLASH,系统加载触摸屏驱动程序后,配置SPI0接口并注册触摸屏输入设备。
系统选择夏普12.7 cm(4.96 in)的TFTLCD[5](型号为LQ050Q5DR01)显示外部输入的图像数据,其分辨率为320×240,主要接口信号有帧同步(VSYNC)、行同步(HSYNC)、时钟(CL K)、数据有效(ENAB)及颜色数据(R6G6B6),与LCD控制器的硬件连接如图2所示。由于LQ050Q5DR01为18位颜色模式(R6G6B6),而处理器LCD控制器最高只有16位颜色模式(R5G6B5),所以在连接时液晶屏的R0、G0信号均接地,同时扫描方向HVR信号也接地,设置扫描方向从左至右、从上至下。

图2 液晶显示屏硬件连接图
Fig.2 Diagram of LCD hardware connection
触摸屏选用广泛使用的四线电阻式触摸屏,工作原理是通过测量电极两端的电压值来实现对触摸点的定位。采用ADS7843触摸屏控制芯片来完成电极两端电压的AD转换,工作模式配置成差分模式,处理器通过SPI0接口采集触点数据,硬件连接如图3所示。GP5[3]配置成外部中断引脚,下降沿触发。当触摸屏被压下时,PENIRQ变为低电平产生外部中断,处理器响应外部中断后启动SPI0接口,发出AD转换控制命令,转换完毕后从ADS7843读取触点位置。

图3 触摸屏硬件连接图
Fig.3 Diagram of touch screen hardware connection
3 Linux接口驱动
操作系统为上层应用程序屏蔽了各种设备的硬件细节,对硬件的访问是通过设备驱动程序来实现的[6]。Linux内核采用模块化方式组织各个设备驱动程序,大部分设备驱动程序可以在内核配置时进行定制,也可在内核运行过程中动态加载或删除,从而降低了存储空间要求,促使Linux操作系统广泛应用于嵌入式领域。目前TI公司已经为OMAP处理器发布了Linux系统支持包,解决了在该处理器ARM核上运行Linux内核的技术细节问题,用户根据需要在Linux架构下进行相应的接口设备驱动或应用程序开发即可。本文即在该支持包下进行有关接口的驱动程序设计,内核版本为Linux 2.6.9。
3.1 液晶屏接口驱动设计
Linux系统将外部接口设备分为字符设备、块设备及网络设备3类。显示设备属于字符设备类型,Linux为显示设备专门定义了一种帧缓冲(framebuffer)的设备驱动架构,但本系统的液晶屏只显示SDRAM中图像数据及对焦窗口,不涉及使用GUI开发包进行图形界面开发,故按常见字符设备驱动架构完成接口驱动设计。
典型的字符设备驱动主要由设备的注册、设备的注销及设备的操作组成。设备的注册在驱动程序加载时进行,主要功能是向系统申请设备号、添加设备、连接文件操作及寄存器初始化,实现过程如下:
static struct cdev*omapLcd_cdev;
static struct file_operations omapLcd_fops={
.owner=THIS_MODULE, .open=omapLCD_open,
.release=omapLCD_release, .write=omapLCD_write, };
//首先定义两个重要的结构类型:字符设备指针omapLcd_cdev和文件操作结构omapLcd_ fops。
static int__init omapLCD_init(void);
module_init(omapLCD_init);
//声明驱动加载时入口函数omapLCD_init,在该函数中进行下面一些操作。
alloc_chrdev_region(&dev,0,1,“omapLcd”);
//向系统申请动态分配设备编号,dev是定义的dev_t类型变量,存储分配的设备编号。
omapLcd_cdev=cdev_alloc();
cdev_init(omapLcd_cdev,&omapLcd_fops);
//分配和初始化字符设备结构。
omapLcd_cdev->owner=THIS_MODULE;
omapLcd_cdev->ops=omapLcd_fops;
//声明设备的所有者属性及连接文件操作。
cdev_add(omapLcd_cdev,dev,1);
//添加设备到系统中。
omapLCD_register_init();
//此函数设置SYSCFG寄存器,将处理器的EMIFA接口配置成LCD控制器接口。
设备的注销是在驱动卸载时进行的,实现过程为:
static int__exit omapLCD_exit(void);
module_exit(omapLCD_exit);
//声明驱动卸载时调用函数omapLCD_exit,在该函数中完成下面操作。
cdev_del(omapLcd_cdev);
//从系统中删除设备。
unregister_chrdev_region(dev,1);
//释放系统分配的设备号。
设备操作是驱动程序的主要部分,系统中定义的液晶屏接口设备操作类型有设备的打开omapLCD_open、设备的释放omapLCD_release及设备的数据写入omapLCD_write。
static int omapLCD_open(struct inode*inode,struct file*filp);
//设备打开操作函数,在执行设备打开操作时,调用omapLCD_register_setup()。
omapLCD_register_setup(void);
//此函数设置LCD控制器寄存器组,主要设置工作为:LCD控制器配置成Raster模式并启用;配置16位TFT接口模式;设置数据传输时钟频率;FIFO门限设置成512双字;启用帧结束中断,屏蔽ARM核LCD控制器中断,目的是只让DSP核响应LCD控制器帧结束中断,由DSP交替刷新图像数据帧缓冲区;启用DMA的pingpongs模式,让DMA自动交替传输FB0和FB1帧缓冲中的数据,实现数据一边传输一边刷新;设置FB0和FB1帧缓冲的起始和结束地址,帧缓冲大小为32+2×(240×320)。staticintomapLCD_release(structinode*inode,struct file*filp);
//设备释放操作函数,在执行设备关闭操作时,设置LCD控制器寄存器组,禁用Raster控制器,禁止LCD控制器中断。
static ssize_t omapLCD_write(struct file*file, const char*buffer,size_t count,loff_t*ppos);
//设备数据写入操作函数,只在触摸屏校准时使用,应用程序将带有校准点的图像数据写入FB0和FB1帧缓冲区。
3.2 触摸屏接口驱动设计
触摸屏设备在Linux系统中也被定义为字符设备类型,为了增强对输入系统管理和方便驱动程序开发,在Linux 2.4版本之后内核专门对输入设备(如键盘、鼠标及游戏杆等)规范了一类输入子系统模型接口,它由Driver驱动层、Input核心层和Event处理层组成。Driver驱动层完成与硬件接口,将输入设备的数据和信息上报给Input核心层;Input核心层维护设备链表,提供Driver驱动层和Event处理层的接口;Event处理层负责将数据放入设备缓冲区,提供设备文件操作接口,应用程序通过该接口读取输入设备的数据。本文开发的触摸屏驱动遵循输入子系统模型的定义,在输入子系统的层次结构中,Input核心层和Event处理层已由内核实现,只要在内核配置时选中相关支持选项即可。需要的只是开发Driver驱动层,实现设备注册及注销、设备打开及关闭、数据采集并上报给Input核心层,触摸屏驱动程序实现流程如图4所示。
驱动程序被加载时完成设备的注册,主要工作步骤有:

图4 触摸屏驱动程序实现流程
Fig.4 Flow chart of touch screen driver implementation
(1)声明输入设备的打开及关闭入口函数。
ts_dev->name="TouchScreen";
ts_dev->open=ts_dev_open;
ts_dev->close=ts_dev_close;
//ts_dev是代表输入设备的全局变量,在文件头定义语句static struct input_dev*ts_dev;
(2)初始化输入设备的类型。
ts_dev->evbit[0]=BIT(EV_ABS);
//设置输入设备类型是绝对坐标型,触摸屏输入数据是绝对坐标值。
ts_dev->absbit[0]=BIT(ABS_X)|BIT (ABS_Y)|BIT(ABS_PRESSURE);
//设置输入设备的属性为X、Y坐标值及压力值。
(3)向输入子系统注册输入设备。
input_register_device(ts_dev);
//执行该语句时,系统将调用connect函数,为输入设备创建字符设备节点。
(4)初始化SPI0接口。
omapSPI_register_init();
//该函数初始化处理器的SPI0接口,设置波特率及控制寄存器,并将GP5[3]配置成外部中断引脚,下降沿有效。
系统加载驱动程序后,应用程序可通过设备文件节点打开或关闭设备,该操作通知系统调用open函数入口ts_dev_open或close函数入口ts_ dev_close。函数ts_dev_open主要工作是向系统请求分配中断并启用GP5[3]外部中断输入。
request_irq(TS_IRQ,ts_dev_isr,SA_INTERRUPT,"TouchScreen",NULL);
//ts_dev_isr为中断服务程序,ADS7843产生中断后被调用。
函数ts_dev_close主要工作是向系统请求释放中断并禁用GP5[3]外部中断输入。
free_irq(TS_IRQ,NULL);
输入数据的采集及上报主要由中断服务程序ts_dev_isr来实现。当触摸屏被按下时,GP5[3]引脚被置成低电平从而产生外部中断,系统响应并调用ts_dev_isr,进入该中断服务程序后,首先禁用GP5[3]外部中断输入,以防止中断被循环触发,之后启动定时器。在定时器延时一段时间(20 ms)后产生定时器中断,在定时器中断程序中查询GP5[3]引脚状态,如果是低电平则表示触

图5 定时器中断程序流程
Fig.5 Flow chart of timer interrupt routine
4 图像调焦系统中的应用
Linux系统加载触摸显示屏的驱动程序后,还需配合相应的应用程序才能正常工作,设计中有两个关键问题需要考虑。摸屏被压下,启动SPI0接口采集触点位置,并将触摸事件上报Input核心层后再次启动定时器;如果是高电平则判断是否上报过触摸事件,如果上报过则表示触摸屏被抬起,此时再次将触摸抬起事件上报Input核心层,如果没有上报过则表示触摸屏抖动,之后将GP5[3]重新配置成外部中断引脚后返回,具体流程如图5所示。上报Input核心层的实现语句为:
input_report_abs(ts_dev,ABS_X,ts_x);
//上报X方向触点位置ts_x。
input_report_abs(ts_dev,ABS_Y,ts_y);
//上报Y方向触点位置ts_y。
input_report_abs(ts_dev,ABS_PRESSURE,ts_event);
//上报触摸屏事件ts_event,通常在触摸屏被压下或拖动时ts_event应设置为大于零的值,抬起时ts_event设置为零。
驱动程序被卸载时,系统调用驱动退出函数,完成设备的注销。
input_unregister_device(ts_dev);
//执行该语句注销为输入设备创建的字符设备节点。
omapSPI_register_exit();
//禁止SPI0时钟。
4.1 图像分辨率变换
系统采用的TFT-LCD分辨率为320×240,而外部输入的数字图像分辨率通常要比它高,这时为了能在LCD上显示整幅图像,只能对输入的数字图像进行重抽样。为保证图像整体一致性,应进行等间隔抽样,必要时对图像边缘裁减。假设输入的数字图像分辨率为Columns×Lines,这时列方向的抽样间隔为Columns/320的商,列方向边缘裁减的像素点为Columns/320的余数,如果该数值为偶数,则左右两边等像素点裁减;如果为奇数,右边缘比左边缘多裁减一个像素点。对于行方向类似计算。
此外还要考虑对焦窗口显示的变换,假设DSP图像调焦时选择的对焦窗口是左上(C1, L1),右下(C2,L2),为把该窗口成比例地显示在LCD上,变换后窗口左上应为(C1/Columns× 320,L1/Lines×240)的整数值,右下应为(C2/ Columns×320,L2/Lines×240)的整数值。
整个图像分辨率变换过程由DSP完成,当LCD控制器的DMA将帧缓冲的数据传送完毕后,假设该帧缓冲标识成FB0,LCD控制器将产生DSP中断,DSP响应中断后查询LCD控制器的状态寄存器得到FB0帧传输结束信息,此时DSP将当前处理的图像数据进行分辨率变换后转移到FB0帧缓冲区,转移过程中将对焦窗口的像素点数据设置为0000011111100000,使得对焦窗口在LCD上显示成绿色,与此同时DMA开始进行FB1帧缓冲的数据传送,从而实现图像数据的一边显示一边刷新。
4.2 触点窗口形成
在DSP自动选择的对焦窗口不满足要求时,可以通过碰触触摸屏来手动选择对焦窗口。通常在触摸显示屏初次使用时需要进行校准,校准采用三点校准法[7],校准完毕后形成6个参数保存至NAND FLASH中。在以后使用过程中当得到触摸屏的触点位置后,利用这6个参数即可解出触点对应的LCD像素点坐标(x,y),之后以该点为中心形成一正方形的对焦窗口,左上为(x-h, y-h),右下为(x+h,y+h)。该对焦窗口是在320×240分辨率下形成的,再经过线性变换后形成原始图像的对焦窗口,左上为((x-h)/320× Columns,(y-h)/240×Lines)的整数值,右下为((x+h)/320×Columns,(y+h)/240×Lines)的整数值。ARM核在完成该计算后向DSP核发出一中断信号并传递计算结果,DSP根据新选择的对焦窗口重新开始进行图像调焦。
5 结 论
通过对基于OMAP处理器的触摸显示屏接口的硬件、驱动及应用程序进行详细设计,实现了输入的图像数据及对焦窗口在液晶屏上的显示。当自动选择的对焦窗口不满足要求时,可以使用触摸屏来重新调整对焦窗口,从而实现人工参与对焦窗口的快速选择及调整,满足特定领域对图像调焦系统的特殊要求。