劉麗霞,劉志鵬,張 力
(1.中國(guó)航天科工集團(tuán)第二研究院 七〇六所,北京 100854;2.32379部隊(duì)第一科室,北京 100072)
VxWorks是Wind River System公司推出的一種嵌入式實(shí)時(shí)操作系統(tǒng),以其良好的可靠性和實(shí)時(shí)性被廣泛應(yīng)用在通信、軍事、航空、航天等實(shí)時(shí)性要求較高的領(lǐng)域。Wind River Workbench 3.2是基于VxWorks6.8操作系統(tǒng)的軟件開(kāi)發(fā)環(huán)境,它提供了豐富的調(diào)試、仿真環(huán)境和工具。WindML是VxWorks操作系統(tǒng)下的多媒體庫(kù)(wind media library)。它支持多媒體程序運(yùn)行在嵌入式系統(tǒng)中,提供基本圖形、視頻和音頻技術(shù),以及提供一個(gè)通用設(shè)備驅(qū)動(dòng)程序架構(gòu)。
WindML包含兩個(gè)組件,軟件開(kāi)發(fā)包(SDK)和驅(qū)動(dòng)程序開(kāi)發(fā)包(DDK)。
SDK組件用來(lái)開(kāi)發(fā)應(yīng)用程序,它提供了一個(gè)全面的API接口,包括圖形、輸入處理、多媒體、字體和內(nèi)存管理。
DDK組件用來(lái)實(shí)現(xiàn)驅(qū)動(dòng)程序,它提供完整的驅(qū)動(dòng)程序參考集,以使開(kāi)發(fā)者能迅速實(shí)現(xiàn)驅(qū)動(dòng)開(kāi)發(fā)。
本文接下來(lái)分析了VxWorks6.8操作系統(tǒng)下使用WindML驅(qū)動(dòng)程序開(kāi)發(fā)包(DDK)開(kāi)發(fā)輸入設(shè)備驅(qū)動(dòng)程序原理。設(shè)計(jì)并開(kāi)發(fā)了觸摸屏驅(qū)動(dòng)軟件以及觸摸屏校準(zhǔn)算法。
本文實(shí)現(xiàn)的驅(qū)動(dòng)和觸摸屏校準(zhǔn)算法豐富了WindML庫(kù)輸入設(shè)備驅(qū)動(dòng),也填補(bǔ)了WindML庫(kù)中觸摸屏校準(zhǔn)算法的空白。通過(guò)設(shè)計(jì)應(yīng)用程序測(cè)試驗(yàn)證驅(qū)動(dòng)的正確性和有效性,也說(shuō)明了該算法可以進(jìn)行推廣和應(yīng)用。
鼠標(biāo)(PS2鼠標(biāo)、USB鼠標(biāo))、鍵盤(pán)、觸摸屏均屬于輸入設(shè)備,其中PS2鼠標(biāo)、USB鼠標(biāo)、觸摸屏設(shè)備等都是指針設(shè)備。
本文選用的觸摸屏控制器型號(hào)是PenMount PM6500,它通過(guò)標(biāo)準(zhǔn)RS232串口接入到主控設(shè)備。觸摸屏控制器將觸摸點(diǎn)坐標(biāo)信息通過(guò)RS232串口傳遞給主控設(shè)備,主控設(shè)備經(jīng)觸摸屏驅(qū)動(dòng)解析、處理后實(shí)現(xiàn)觸摸點(diǎn)顯示可控等功能。
觸摸屏控制器按表1所示數(shù)據(jù)包格式進(jìn)行通信:數(shù)據(jù)包大小是6個(gè)字節(jié),其中前5個(gè)字節(jié)是數(shù)據(jù),最后一個(gè)字節(jié)是校驗(yàn)和。Byte 0是觸摸狀態(tài),0×70表示按下?tīng)顟B(tài),0×30表示抬起狀態(tài)。Byte 1、Byte 2組合成X坐標(biāo)位置,Byte 3、Byte 4組合成Y坐標(biāo)位置,Byte 5為校驗(yàn)和。
表1 串口通信協(xié)議
基于WindML的輸入設(shè)備驅(qū)動(dòng)由兩層驅(qū)動(dòng)構(gòu)成,一層是底層驅(qū)動(dòng)(low-level),用于處理硬件設(shè)備控制器,一層是頂層驅(qū)動(dòng)(high-level),用于解析來(lái)自硬件設(shè)備的原始數(shù)據(jù)。
WindML底層輸入驅(qū)動(dòng)(low-level)是一種I/O驅(qū)動(dòng),常常配置到系統(tǒng)內(nèi)核。初始化時(shí),該驅(qū)動(dòng)掛接到操作系統(tǒng)的IO系統(tǒng)上,它的功能如下:
(1)初始化設(shè)備控制器和輸入設(shè)備;
(2)處理由設(shè)備控制器產(chǎn)生的中斷;
(3)接收來(lái)自輸入設(shè)備的原始數(shù)據(jù),通過(guò)IO系統(tǒng)傳遞給high-level輸入驅(qū)動(dòng);
(4)接收來(lái)自high-level輸入驅(qū)動(dòng)的命令并進(jìn)行響應(yīng)。
本文使用的觸摸屏通過(guò)串口接入IO系統(tǒng),RS232串口為標(biāo)準(zhǔn)串口,VxWorks6.8自帶該設(shè)備驅(qū)動(dòng),對(duì)應(yīng)的設(shè)備名稱為/tyCo/1。
IO系統(tǒng)驅(qū)動(dòng)標(biāo)準(zhǔn)函數(shù)有:open、close、read、write、ioctl、select。這些函數(shù)被high-level輸入驅(qū)動(dòng)調(diào)用,實(shí)現(xiàn)輸入設(shè)備的原始數(shù)據(jù)由low-level驅(qū)動(dòng)向high-level輸入驅(qū)動(dòng)傳遞。
high-level輸入驅(qū)動(dòng)主要功能是從low-level輸入驅(qū)動(dòng)中接收原始數(shù)據(jù),處理數(shù)據(jù),再將其打包成輸入事件消息,最后將消息發(fā)送到輸入消息隊(duì)列中。
基于WindML觸摸屏驅(qū)動(dòng),涉及的low-level輸入驅(qū)動(dòng)使用VxWorks6.8系統(tǒng)自帶串口驅(qū)動(dòng)即可,因此本文重點(diǎn)是實(shí)現(xiàn)觸摸屏high-level輸入驅(qū)動(dòng)設(shè)計(jì)開(kāi)發(fā)。
WindML提供了與應(yīng)用層傳遞信息的可擴(kuò)展機(jī)制。輸入設(shè)備(如觸摸屏)通過(guò)輸入服務(wù)(input service)將輸入信息(坐標(biāo))傳遞給應(yīng)用層。輸入設(shè)備、應(yīng)用層以及窗口均通過(guò)消息方式實(shí)現(xiàn)信息交互。
在應(yīng)用層中,每一個(gè)顯示端均有輸入服務(wù)對(duì)應(yīng)。所有的輸入服務(wù)通過(guò)輸入任務(wù)控制high-level輸入驅(qū)動(dòng)。該任務(wù)通過(guò)select()函數(shù)被掛起,用來(lái)等待來(lái)自low-level輸入驅(qū)動(dòng)的數(shù)據(jù),當(dāng)輸入設(shè)備產(chǎn)生數(shù)據(jù)后,該任務(wù)被底層驅(qū)動(dòng)(low-level)喚醒后,輸入服務(wù)(input service)借助high-level驅(qū)動(dòng)處理來(lái)自輸入設(shè)備的原始數(shù)據(jù)。high-level輸入驅(qū)動(dòng)從low-level輸入驅(qū)動(dòng)上獲取觸摸屏原始數(shù)據(jù),將原始數(shù)據(jù)封裝成WindML指針類(lèi)數(shù)據(jù)(UGL_POINTER_DATA)后,再將指針類(lèi)數(shù)據(jù)打包成WindML消息(UGL_MSG_DATA),最后通過(guò)WindML標(biāo)準(zhǔn)接口uglInputMsgPost()函數(shù)將其放入消息隊(duì)列中。應(yīng)用層通過(guò)uglInputMsgGet()函數(shù)從缺省的輸入隊(duì)列中獲取輸入消息。獲取消息后,通過(guò)uglInputCbAdd()函數(shù)注冊(cè)輸入回調(diào)函數(shù),實(shí)現(xiàn)消息響應(yīng),如鼠標(biāo)指針移動(dòng)、鼠標(biāo)左擊。
WindML輸入消息定義如下:
typedef union ugl_msg_data
{
/* The data for MSG_KEYBOARD */
UGL_KEYBOARD_DATA keyboard;
/* The data for MSG_POINTER */
UGL_POINTER_DATA pointer;
/* The data for MSG_RAW_KBD */
UGL_RAW_KBD_DATA rawKbd;
/* The data for MSG_RAW_PTR */
UGL_RAW_PTR_DATA rawPtr;
/* for compatability with ver. 2.X */
UGL_EVENT event;
char reserved [UGL_MAX_MSG_SIZE];
} UGL_MSG_DATA;
設(shè)計(jì)觸摸屏驅(qū)動(dòng)源文件uglPM6500ts.c。
將其放置在“installDir/components/windml-5.3/src/ugl/driver/pointer/uglPM6500ts”路徑下。其中“installDir”指WindRiver安裝路徑。在該源文件中定義觸摸屏驅(qū)動(dòng)以及相應(yīng)函數(shù)實(shí)現(xiàn)。uglPM6500TsPtrDriver是high-level輸入驅(qū)動(dòng)入口函數(shù),驅(qū)動(dòng)函數(shù)包含設(shè)備打開(kāi)、關(guān)閉、控制(讀取及處理觸摸點(diǎn)數(shù)據(jù)、獲取指針設(shè)備類(lèi)型、校正觸摸點(diǎn)等功能)。
UGL_INPUT_DRV uglPM6500TsPtrDriver=
{
(UGL_INPUT_DEV_OPEN)uglPM6500TsPtrOpen,
(UGL_INPUT_DEV_CLOSE)uglPM6500TsPtr-Close,
(UGL_INPUT_DEV_CONTROL)uglPM6500Ts-PtrControl
};
源程序?qū)?yīng)的頭文件uglPM6500ts.h放置在“installDir/components/windml-5.3 /h/ugl/driver/pointer”路徑下。該文件定義了PM6500觸摸屏指針設(shè)備數(shù)據(jù)結(jié)構(gòu)UGL_PM6500_TS_PTR_DEVICE以及函數(shù)實(shí)現(xiàn)聲明。
typedef struct ugl_PM6500_ts_ptr_device
{
/* inherits input device structure輸入設(shè)備描述符*/
UGL_INPUT_DEV inputDevice;
/* display rectangle size 觸摸屏分辨率大小*/
UGL_RECT dispRect;
/*與校準(zhǔn)點(diǎn)對(duì)應(yīng)的觸摸屏坐標(biāo),PM6500_TS_NUM_CALIB_POINTS 設(shè)置校準(zhǔn)點(diǎn)個(gè)數(shù)*/
UGL_POINT tcPoint[PM6500_TS_NUM_CALIB_POINTS];
/*標(biāo)準(zhǔn)校準(zhǔn)點(diǎn)坐標(biāo)*/
UGL_POINT calibPoint[PM6500_TS_NUM_CALIB_POINTS];
/*校準(zhǔn)系數(shù):依次為A/B/C/H/E/F*/
float calibCoef[6];
} UGL_PM6500_TS_PTR_DEVICE;
下面對(duì)uglPM6500ts.c中實(shí)現(xiàn)的驅(qū)動(dòng)函數(shù)進(jìn)行詳細(xì)闡述。
實(shí)現(xiàn)原理是:通過(guò)low-level輸入驅(qū)動(dòng)接口open()函數(shù)打開(kāi)觸摸屏控制器RS232串口;設(shè)置串口波特率;通過(guò)串口從觸摸屏控制器上讀取觸摸校準(zhǔn)參數(shù)、初始化其它參數(shù)等。
UGL_LOCAL UGL_INPUT_DEV_ID uglPM6500Ts-PtrOpen(char* pDevName,UGL_INPUT_DRV * pDriver);
{
…
/* pDevName 是串口名稱*/
pDevice->inputDevice.fd = open (pDevName, O_RDWR, 0); //設(shè)置串口參數(shù), 包括波特率
//從控制器的NVRAM中讀取觸摸校準(zhǔn)參數(shù)A/B/C/H/E/F
//獲取顯示屏中用于校準(zhǔn)觸摸點(diǎn)(XTi,YTi)對(duì)應(yīng)的顯示點(diǎn)坐標(biāo)(XLi,YLi)。
…
}
在應(yīng)用層,通過(guò)調(diào)用WindML標(biāo)準(zhǔn)函數(shù)UGL_INPUT_DEV_ID uglInputDevOpen(UGL_CHAR *pName,/* device name */UGL_INPUT_DRV * pDriver /* input driver */),實(shí)現(xiàn)對(duì)uglPM6500TsPtrOpen驅(qū)動(dòng)函數(shù)調(diào)用。uglInputDevOpen函數(shù)返回輸入設(shè)備ID,應(yīng)用層通過(guò)將輸入設(shè)備ID作為參數(shù),通過(guò)調(diào)用UGL_STATUS uglInputDevAdd(UGL_INPUT_SERVICE_ID inputServiceId,UGL_INPUT_DEV_ID inputDeviceId)函數(shù)實(shí)現(xiàn)了輸入設(shè)備與輸入服務(wù)綁定。
實(shí)現(xiàn)原理:根據(jù)上層用戶發(fā)送的請(qǐng)求類(lèi)型分別執(zhí)行控制功能,主要包括讀取及處理原始數(shù)據(jù)、校準(zhǔn)觸摸屏、獲取指針設(shè)備類(lèi)型等。
UGL_LOCAL UGL_STATUS uglPM6500TsPtrControl (UGL_PM6500_TS_PTR_DEVICE *pDevice, UGL_DEVICE_REQ request,void * pArg)
{
/*判斷用戶控制請(qǐng)求類(lèi)型*/
switch (request)
{
//讀取串口原始數(shù)據(jù)
case ICR_READ: /* read PTR data */
{
return (uglPM6500TsPtrReadMessages (pDevice));
}
//獲取指針設(shè)備類(lèi)型,有鼠標(biāo)類(lèi)型、觸摸屏類(lèi)型等。UGL_PTR_TYPE_TOUCH_SCREEN是WindML中對(duì)觸摸屏設(shè)備的宏定義
case ICR_GET_PTR_TYPE:
{
if(pArg != UGL_NULL)
{
*(int *)pArg = UGL_PTR_TYPE_TOUCH_SCREEN;
return(UGL_STATUS_OK);
}else
{
return(UGL_STATUS_ERROR);
}
}
//開(kāi)始獲取觸摸校準(zhǔn)點(diǎn)
case ICR_CALIBRATION_START:
{
//pArg為校正點(diǎn)順序, 對(duì)應(yīng)標(biāo)準(zhǔn)點(diǎn)順序。 獲取觸摸點(diǎn)初始數(shù)據(jù), 并保存。
return(GetTcData(pDevice, pArg));
}
//結(jié)束獲取觸摸校正點(diǎn)
case ICR_CALIBRATION_STOP:
{
//函數(shù)CalGetCoef利用標(biāo)準(zhǔn)校準(zhǔn)點(diǎn)和獲取的觸摸點(diǎn)計(jì)算校正參數(shù)。
return(CalGetCoef(pDevice));
}
…
}
在應(yīng)用層,使用顯示端對(duì)應(yīng)的輸入服務(wù)(input server)找到關(guān)聯(lián)的輸入設(shè)備ID,然后將輸入設(shè)備ID作為參數(shù),通過(guò)調(diào)用uglInputDevControl(inputDevId,requestType,argument)函數(shù),實(shí)現(xiàn)對(duì)uglPM6500TsPtrControl驅(qū)動(dòng)函數(shù)調(diào)用。
3.3.1 獲取及解析原始數(shù)據(jù)
用戶請(qǐng)求類(lèi)型為ICR_READ:
實(shí)現(xiàn)原理:通過(guò)low-level輸入驅(qū)動(dòng)接口read()函數(shù)讀取串口原始數(shù)據(jù),將其解析成UGL_POINTER_DATA數(shù)據(jù),然后封裝該數(shù)據(jù)為輸入消息,再由uglInputMsgPost將消息發(fā)送到輸入消息隊(duì)列中。應(yīng)用層用戶通過(guò)uglInputMsgGet捕獲該消息后,再通過(guò)調(diào)用該消息相關(guān)的回調(diào)函數(shù),實(shí)現(xiàn)觸摸點(diǎn)移動(dòng)或按鍵功能。
3.3.2 實(shí)現(xiàn)觸摸屏校準(zhǔn)
用戶請(qǐng)求類(lèi)型為:
ICR_CALIBRATION_START:開(kāi)始獲取校準(zhǔn)觸摸點(diǎn)。
ICR_CALIBRATION_STOP:停止獲取校準(zhǔn)觸摸點(diǎn)。
鼠標(biāo)指示的是相對(duì)位置,而觸摸屏指示的是絕對(duì)位置。觸摸點(diǎn)數(shù)據(jù)通過(guò)校準(zhǔn)參數(shù)轉(zhuǎn)換為屏幕上的坐標(biāo),這樣就要求不管在什么情況下,同一點(diǎn)的輸出數(shù)據(jù)是穩(wěn)定的,如果不穩(wěn)定,那么觸摸屏就不能保證絕對(duì)坐標(biāo)定位,因此在定位不準(zhǔn)時(shí)需要校準(zhǔn)觸摸屏幕。校準(zhǔn)的核心內(nèi)容就是獲取觸摸點(diǎn)向屏幕顯示點(diǎn)轉(zhuǎn)換的校準(zhǔn)參數(shù)。
如果PT(x,y) 表示觸摸屏上的一個(gè)點(diǎn),PL(x,y) 表示顯示屏LCD上的一個(gè)點(diǎn),校正的結(jié)果就是得到一個(gè)轉(zhuǎn)換矩陣M,通過(guò)式(1)實(shí)現(xiàn)觸摸屏點(diǎn)坐標(biāo)與顯示屏點(diǎn)坐標(biāo)的變換。M屬于二維幾何變換包含平移、旋轉(zhuǎn)和縮放3種變換
PL(x,y)=M·PT(x,y)
(1)
若PL(x,y) 與PT(x,y) 是平移關(guān)系,轉(zhuǎn)換關(guān)系通過(guò)式(2)表示。MT為如式(3)中描述的矩陣
PL(x,y)=MT·PT(x,y)
(2)
(3)
若PL(x,y) 與PT(x,y) 是縮放關(guān)系,轉(zhuǎn)換關(guān)系通過(guò)式(4)表示。MS為如式(5)中描述的矩陣
PL(x,y)=MS·PT(x,y)
(4)
(5)
若PL(x,y) 與PT(x,y) 是旋轉(zhuǎn)關(guān)系,轉(zhuǎn)換關(guān)系通過(guò)式(6)表示。MR為如式(7)中描述的矩陣
PL(x,y)=MR·PT(x,y)
(6)
(7)
實(shí)際情況中,觸摸屏到顯示屏坐標(biāo)變換涉及到3種變換,如式(8)所示。展開(kāi)此公式,其結(jié)果如式(9)、式(10)所示
PL(x,y)=MT·MS·MR·PT(x,y)
(8)
XL=XT(Sx·cosθ)+YT(-Sy·sinθ)+
(Tx·cosθ-Ty·sinθ)
(9)
YL=XT(Sx·sinθ)+YT(Sy·cosθ)+
(Tx·sinθ+Ty·cosθ)
(10)
在式(9)、式(10)中,顯示屏上的坐標(biāo)(XL,YL)和觸摸屏上的坐標(biāo)(XT,YT)是已知的,而其它參數(shù)則是需要求解的:θ,Sx,Sy,Tx,Ty,共有5個(gè)變量。為了簡(jiǎn)化運(yùn)算,將式(9)、式(10)變?yōu)槭?11)、式(12)。其中A、B、C、H、E、F為待求解的校準(zhǔn)參數(shù),在式(11)、式(12)中雖然增加了未知變量,但是避免了三角函數(shù)運(yùn)算,計(jì)算更簡(jiǎn)便
XL=A·XT+B·YT+C
(11)
YL=H·XT+E·YT+F
(12)
其中,(XL,YL)是屏幕顯示點(diǎn)坐標(biāo),(XT,YT)是觸摸點(diǎn)坐標(biāo)。至此,觸摸屏校準(zhǔn)過(guò)程就是求解A、B、C、H、E、F參數(shù)的過(guò)程。
將式(11)乘以常量XTi, 或YTi后,再執(zhí)行求和運(yùn)算等價(jià)變換為式(13)~式(15)這3個(gè)表達(dá)式。n表示觸摸點(diǎn)數(shù)量。 (XTi,YTi) 表示第i個(gè)觸摸點(diǎn)的絕對(duì)坐標(biāo),(XLi,YLi) 表示第i個(gè)觸摸點(diǎn)對(duì)應(yīng)的屏幕顯示坐標(biāo)
(13)
(14)
(15)
上述3個(gè)方程式中,A、B、C可以作為待求解的未知數(shù),獲取到的每個(gè)觸摸點(diǎn) (XTi,YTi) 與顯示標(biāo)準(zhǔn)點(diǎn) (XLi,YLi) 的坐標(biāo)為已知數(shù),n表示坐標(biāo)點(diǎn)的數(shù)量,它可以是任意值,但是采集點(diǎn)過(guò)少會(huì)影響計(jì)算參數(shù)精度,過(guò)多又會(huì)冗余,且增加了計(jì)算時(shí)間。根據(jù)實(shí)驗(yàn)室驗(yàn)證值,得出n=5,具有較好的表現(xiàn)。
依據(jù)克萊姆法則,通過(guò)計(jì)算上述3個(gè)方程式對(duì)應(yīng)的行列式,來(lái)求解A、B、C。其中
A=D0/D
(16)
B=D1/D
(17)
C=D2/D
(18)
上述式(16)~式(18)中,D為式(13)~式(15)方程式等號(hào)右側(cè)已知數(shù)系數(shù)構(gòu)成的行列式;Di是把D中第i列元素對(duì)應(yīng)地?fù)Q成式(13)~式(15)方程式等號(hào)左側(cè)常數(shù)項(xiàng)而其余列保持不變所得到的行列式
(19)
(20)
(21)
(22)
同理可以計(jì)算得到H、E、F參數(shù)。這樣根據(jù)式(11)、式(12),就可以將觸摸點(diǎn)坐標(biāo) (XT,YT) 通過(guò)A、B、C、H、E、F參數(shù)運(yùn)算后,轉(zhuǎn)換成屏幕上的顯示坐標(biāo) (XL,YL)。
程序初始化時(shí),用戶自定義了n(n=5)個(gè)用于校準(zhǔn)的顯示點(diǎn)坐標(biāo) (XLi,YLi), 在本文3.3節(jié)中,使用GetTcData函數(shù)用來(lái)采集顯示點(diǎn)坐標(biāo) (XLi,YLi) 對(duì)應(yīng)的觸摸點(diǎn) (XTi,YTi), 通過(guò)表1中串口協(xié)議解析獲得顯示點(diǎn)對(duì)應(yīng)的觸摸點(diǎn)坐標(biāo) (XTi,YTi), 本文3.3節(jié)中CalGetCoef()函數(shù)的實(shí)現(xiàn)就是依據(jù)式(16)~式(22),求解得到式(11)中的參數(shù)A,B,C,同樣也能計(jì)算出式(12)中的參數(shù)H,E,F(xiàn)。
當(dāng)用戶去觸摸屏幕時(shí),觸摸坐標(biāo)點(diǎn) (XTi,YTi), 就可以通過(guò)式(11)、式(12)轉(zhuǎn)換為對(duì)應(yīng)的顯示坐標(biāo)點(diǎn) (XLi,YLi) 供用戶使用。
將轉(zhuǎn)換的坐標(biāo)點(diǎn)以及從串口中按表1獲取的按鍵狀態(tài)封裝成UGL_MSG消息,通過(guò)uglInputMsgPost函數(shù)發(fā)送到消息隊(duì)列中,接著應(yīng)用層通過(guò)調(diào)用uglInputMsgGet()函數(shù)從缺省的輸入隊(duì)列中獲取輸入消息。應(yīng)用層獲取消息后,通過(guò)uglInputCbAdd()函數(shù)注冊(cè)輸入回調(diào)函數(shù),實(shí)現(xiàn)消息響應(yīng),如鼠標(biāo)指針移動(dòng)、鼠標(biāo)左擊。
實(shí)現(xiàn)原理:通過(guò)low-level輸入驅(qū)動(dòng)接口close()函數(shù)關(guān)閉觸摸屏控制器RS232串口;釋放內(nèi)存、析構(gòu)相關(guān)參數(shù)。
UGL_LOCAL UGL_STATUS uglPM6500TsPtrClose (UGL_INPUT_DEV * pDevice)
{
…
if (pDevice != UGL_NULL)
{
//調(diào)用low-level層close函數(shù)實(shí)現(xiàn)串口關(guān)閉
close (pDevice->fd);
UGL_FREE (pDevice);
}
return UGL_STATUS_OK;
}
在應(yīng)用層,使用顯示端對(duì)應(yīng)的輸入服務(wù)(input server)找到關(guān)聯(lián)的輸入設(shè)備ID,然后將輸入設(shè)備ID作為參數(shù),通過(guò)調(diào)用UGL_STATUSuglInputDevClose(UGL_INPUT_DEV_ID inDevId),實(shí)現(xiàn)對(duì)uglPM6500TsPtrClose驅(qū)動(dòng)函數(shù)調(diào)用。
驅(qū)動(dòng)功能實(shí)現(xiàn)后,需要?jiǎng)?chuàng)建一個(gè)驅(qū)動(dòng)配置數(shù)據(jù)庫(kù),供用戶在Wind River Workbench 3.2工程下通過(guò)WindML選擇需要配置的輸入設(shè)備信息。WindML配置是由一系列數(shù)據(jù)庫(kù)控制的,這些數(shù)據(jù)庫(kù)文件定義驅(qū)動(dòng)特征。它們位于“installDircomponentswindml-5.3configwrmdb”目錄下。在Wind River Workbench 3.2工程中的config.windml配置工具會(huì)讀取這些數(shù)據(jù)庫(kù)文件加載相應(yīng)的信息,用戶可通過(guò)下拉列表信息選擇配置對(duì)象。
本文,在“installDircomponentswindml-5.3configwrmdb”目錄下創(chuàng)建windML_PTR_DEVICE_PM6500_TS.wrmdb文件,用于配置PM6500觸摸屏驅(qū)動(dòng)。配置內(nèi)容如下:
//設(shè)備名稱
pm6500ts.NAME="PM6500 Touchscreen Pointer"
//定義設(shè)備驅(qū)動(dòng)支持的處理器類(lèi)型
pm6500ts.ARCH=&ARMARCH5:&ARMARCH6:&MIPSI2:&MIPSI3:&MIPSI32:&MIPSI64:&I80486:&PENTIUM:&PENTIUM2:&PENTIUM3:&PENTIUM4:&PPC32
//定義編譯該驅(qū)動(dòng)時(shí)處理器字節(jié)的順序:大端或小端
pm6500ts.ENDIAN=&le:&be
//是否支持RTPs
pm6500ts.RTPENABLED=true
//指針設(shè)備必須定義的宏定義
pm6500ts.DEFINE=INCLUDE_UGL_INPUT
//條件宏定義
pm6500ts.SELECT=INCLUDE_PM6500_TS_POINTER
//對(duì)應(yīng)的high-level輸入驅(qū)動(dòng)入口
pm6500ts.CREATE=uglPM6500TsPtrDriver
//定義缺省的IO設(shè)備名稱
pm6500ts.DEVNAME=/tyCo/1
//對(duì)應(yīng)的low-level輸入驅(qū)動(dòng)入口及參數(shù)(缺省為系統(tǒng)自帶IO驅(qū)動(dòng))
pm6500ts.IODRV=/*缺省狀態(tài), 默認(rèn)使用系統(tǒng)自帶16550串口驅(qū)動(dòng)*/
pm6500ts.IODRV_PARAM1=0
pm6500ts.IODRV_PARAM2=0
本文第3章實(shí)現(xiàn)了觸摸屏驅(qū)動(dòng),那么應(yīng)用層就可以通過(guò)調(diào)用WindML標(biāo)準(zhǔn)函數(shù)實(shí)現(xiàn)觸摸屏操控。在應(yīng)用層,用戶通過(guò)配置WindML驅(qū)動(dòng)庫(kù),實(shí)現(xiàn)用戶定制的顯示端配置,包括顯示界面驅(qū)動(dòng)、輸入設(shè)備驅(qū)動(dòng)、顯示字體驅(qū)動(dòng)等配置。
Wind River Workbench 3.2軟件是開(kāi)發(fā)VxWorks6.8操作系統(tǒng)下軟件的開(kāi)發(fā)環(huán)境,在Wind River Workbench 3.2開(kāi)發(fā)環(huán)境下,建立基于Media Libray 5.3組件的配置工程“VxWorks Downloadable Kernel Module Project”。在生成的工程中,在配置信息文件config.windml中對(duì)輸入設(shè)備進(jìn)行配置,配置為本文設(shè)計(jì)的觸摸屏驅(qū)動(dòng),配置內(nèi)容如下:Device=PM6500 Touchscreen Pointer;Device Name=/tyCo/1。這些參數(shù)的選擇均來(lái)自于本文第3.5節(jié)驅(qū)動(dòng)配置數(shù)據(jù)庫(kù),windML_PTR_DEVICE_PM6500_TS.wrmdb。
顯示終端配置完成后,編譯該工程,生成相應(yīng)Wind Media Libray組件。
用戶新建應(yīng)用工程后,需要在應(yīng)用工程中添加使用觸摸屏驅(qū)動(dòng)的組件。
包含Wind Media Libray組件如下:INCLUDE_WINDML、INCLUDE_WINDML_NECESSARY;
包含一個(gè)圖像組件:INCLUDE_PCI_WINDML_GRAPHICS;
包含一個(gè)識(shí)別設(shè)備映射方法:INCLUDE_WINDML_GRAPHICS_SHARED_DATA或 INCLUDE_WINDML_GRAPHICS_NO_SHARED_DATA。
添加完成后,編譯該應(yīng)用工程使WindML組件在該工程中生效。自此,用戶可以在應(yīng)用程序中調(diào)用WindML標(biāo)準(zhǔn)函數(shù)實(shí)現(xiàn)觸摸可控及觸摸校準(zhǔn)等應(yīng)用功能。
為了驗(yàn)證觸摸屏驅(qū)動(dòng)的正確性和觸摸屏校準(zhǔn)算法的有效性,本文設(shè)計(jì)了測(cè)試用例進(jìn)行評(píng)估。用例中設(shè)計(jì)了10個(gè)不同大小的正方形按鈕,大小從10像素*10像素,20像素*20像素,……100像素*100像素依次遞增10個(gè)像素構(gòu)成10個(gè)按鈕,按鈕經(jīng)編號(hào)后隨機(jī)分布在全屏幕,顯示屏幕像素為1024*768。
根據(jù)人為對(duì)觸摸屏與鼠標(biāo)點(diǎn)擊按鈕的響應(yīng)靈敏度對(duì)比結(jié)果作為評(píng)估標(biāo)準(zhǔn)。由5人操作體驗(yàn)進(jìn)行主觀評(píng)測(cè)。
同一個(gè)按鈕用觸摸屏和用鼠標(biāo)點(diǎn)擊主觀靈敏度響應(yīng)對(duì)比分4個(gè)等級(jí):觸摸按鈕沒(méi)有按下響應(yīng)計(jì)0分,觸摸屏響應(yīng)靈敏小于鼠標(biāo),計(jì)1分,觸摸屏響應(yīng)和鼠標(biāo)相近,計(jì)2分,觸摸屏響應(yīng)靈敏大于鼠標(biāo),計(jì)3分。每個(gè)按鈕點(diǎn)擊操作完成后,將5人的累計(jì)得分作為最終評(píng)測(cè)得分,若每個(gè)按鈕響應(yīng)對(duì)比累計(jì)分?jǐn)?shù)大于等于10分以上,說(shuō)明觸摸屏靈敏度幾乎與鼠標(biāo)接近,甚至優(yōu)于鼠標(biāo),若分?jǐn)?shù)小于5分,說(shuō)明觸摸屏響應(yīng)錯(cuò)誤,若分?jǐn)?shù)在5分與10分間,說(shuō)明觸摸屏靈敏度弱于鼠標(biāo)。
驗(yàn)證過(guò)程中,觸摸屏按鈕響應(yīng)正常,無(wú)響應(yīng)失效發(fā)生,計(jì)算機(jī)運(yùn)行良好。評(píng)估結(jié)果見(jiàn)表2,可以明顯看出觸摸屏響應(yīng)靈敏度和鼠標(biāo)響應(yīng)靈敏度接近。進(jìn)一步驗(yàn)證了本文設(shè)計(jì)的觸摸屏驅(qū)動(dòng)的正確以及校準(zhǔn)算法的有效性。
本文討論了VxWorks操作系統(tǒng)下WindML實(shí)現(xiàn)輸入設(shè)備驅(qū)動(dòng)的原理,詳細(xì)設(shè)計(jì)了觸摸屏驅(qū)動(dòng)以及校準(zhǔn)算法。在Wind River Workbench 3.2開(kāi)發(fā)環(huán)境下設(shè)計(jì)了按鈕響應(yīng)程序,通過(guò)實(shí)驗(yàn)評(píng)估,驗(yàn)證了本文實(shí)現(xiàn)的觸摸屏驅(qū)動(dòng)及校準(zhǔn)功能在用戶體驗(yàn)上的及時(shí)性和準(zhǔn)確性方面與鼠標(biāo)響應(yīng)幾乎無(wú)差別。本文實(shí)現(xiàn)的觸摸屏驅(qū)動(dòng)擴(kuò)展了用戶對(duì)輸入設(shè)備的使用,封裝成的觸摸屏驅(qū)動(dòng)組件也豐富了WindML庫(kù)的種類(lèi),為用戶直接使用提供了便利。