您好,登錄后才能下訂單哦!
本文檔為移植LCD8000-97C屏幕電容觸控驅動到iMX6平臺過程的總結。提供一些SylixOS觸控相關的框架理解和移植心得。
如圖21所示:觸控屏通過外部中斷提醒主機從I2C總線上讀取觸控坐標和按壓數據,主機讀取到觸控數據后將數據解析并轉換成鼠標事件發送給系統上層,完成一次觸控。
圖 2-1 觸控流程
/driver/touch/touch.c文件主要實現了SylixOS的touch框架。主體框架僅需要關注如圖31所示的四個函數:
圖 3-1 Touch框架重要函數
該函數主要完成如下的功能:
1)創建觸摸屏使用的I2C的總線設備;
2)注冊設備觸控中斷;
3)申請設備復位管腳,復位設備;
4)調用設備Init函數。
這是函數__touchHwInit注冊的中斷響應服務,主要完成接收觸控中斷、清除中斷,并發出一個touch相關的信號的功能。
該函數是touch設備的一個線程,其在執行過程中等待touch信號,收到信號后調用函數__touchHandleEvents.
該函數通過觸控芯片驅動提供的getevent回調函數來獲取數據生成的鼠標事件,并向上層發送相關鼠標事件。
整個框架的流程如圖32所示:
圖 3-2 Touch主體框架流程
移植的觸控屏為英蓓特LCD8000-97c,由于原廠不提供相關觸控芯片的資料支持,只能從支持該屏幕的Linux或者Android的調試信息和源碼來獲得相關IC信息,具體方式不再贅述。這里通過調試信息和源碼確認屏幕觸控芯片型號為CT365。
在RIotboard官方提供的源碼中關于CT365的驅動是以二進制形式提供的,僅有頭文件/driver/input/touchscreen/generic_ts_rel/ct365.h能作為參考,如程序清單 31所示,根據該頭文件可以獲取CT365的觸控信息報文結構:
程序清單 3-1 ct365頭文件中關于數據結構的描述
struct struct_ct365_pts_data { unsigned char xhi; // X coordinate Hi unsigned char yhi; // Y coordinate Hi unsigned char ylo : 4; // Y coordinate Lo unsigned char xlo : 4; // X coordinate Lo unsigned char status : 3; // Action information, 1: Down; 2: Move; 3: Up unsigned char id : 5; // ID information, from 1 to CFG_MAX_POINT_NUM unsigned char area; // Touch area unsigned char pressure; // Touch Pressure};
程序清單 31大致可以判斷出CT365的有效報文為6個字節,其中前三個字節的觸控坐標信息和第四個字節前三位的觸控狀態是最為重要的數據,這些數據最終會解析成鼠標事件。
將觸屏的I2C的兩根線接入邏輯分析儀,觸摸屏幕的時候抓取I2C通信數據(由于無法再次進行實驗,不提供抓取的數據截圖)。
根據邏輯分析儀抓取的數據,可以分析得出CT365的I2C設備地址為0x01,數據傳輸方式如圖3-4所示:
圖 3-4 CT365的數據通信流程
根據以上搜集的信息,結合硬件的原理圖基本可以確定CT365的工作方式以及數據傳輸流程。
CT365和主板連接部分只有一個I2C接口和一個中斷管腳,因此不需要初始化和復位,上電之后每次觸控都會產生一個中斷,通過中斷通知系統向CT365數據發送一幀數據為0的寫命令,隨后發送讀命令讀取CT365反饋的觸控信息,解析生產鼠標事件。
參考BSP包中其他的觸控芯片驅動的實現,針對CT365僅需實現讀函數,觸摸數據的解析函數。分解成以下幾個子函數:
ct365GetEvent
ct365GetTouchPoint
ct365GetRxData
ct36xRegRead
函數ct365GetEvent主要是由touch框架回調的,用來獲取觸控數據和生成鼠標事件的,所以先調用ct365GetRxData來獲取觸控數據,在調用ct365GetTouchPoint來解析生成鼠標事件。具體實現如程序清單 32所示:
程序清單 3-2 ct365GetEvent函數實現
INT ct365GetEvent (PTOUCH_DEV pTouchDev, mouse_event_notify events[]){ INT iError; UCHAR ucBuffer[32]; iError = ct365GetRxData(pTouchDev, ucBuffer, sizeof(ucBuffer)); if (iError == PX_ERROR) { printk(KERN_WARNING "touch: get touch point error!\n"); return (PX_ERROR); } iError = ct365GetTouchPoint(pTouchDev, events, ucBuffer); return (iError); }
函數ct365GetTouchPoint通過傳入的觸控數據,根據CT365頭文件的數據報文結構分別解析出觸控的坐標和觸控的狀態,封裝出鼠標事件。具體實現如程序清單 3-3所示:
程序清單 3-3 ct365GetTouchPoint函數實現
static INT ct365GetTouchPoint (PTOUCH_DEV pTouchDev, mouse_event_notify events[], UINT8 *pucData) { INT iTouchPoint; iTouchPoint = pucData[3] & 0x3; if (iTouchPoint > TOUCH_MAX_INPUT_POINTS) { iTouchPoint = TOUCH_MAX_INPUT_POINTS; } if (iTouchPoint == 1) { events[0].xmovement = (INT16)((pucData[0] << 4) | (pucData[0]>>4 & 0xf)); events[0].ymovement = (INT16)((pucData[1] << 4) | (pucData[2] & 0xf)); events[0].ctype = MOUSE_CTYPE_ABS; events[0].kstat = MOUSE_LEFT; pTouchDev->TOUCH_iLastX = events[0].xmovement; pTouchDev->TOUCH_iLastY = events[0].ymovement; } else if (iTouchPoint == 2) { events[0].xmovement = (INT16)((pucData[0] << 4) | (pucData[0]>>4 & 0xf)); events[0].ymovement = (INT16)((pucData[1] << 4) | (pucData[2] & 0xf)); events[0].ctype = MOUSE_CTYPE_ABS; events[0].kstat = MOUSE_LEFT; pTouchDev->TOUCH_iLastX = events[0].xmovement; pTouchDev->TOUCH_iLastY = events[0].ymovement; iTouchPoint = 1; } else if (iTouchPoint == 3) { events[0].xmovement = pTouchDev->TOUCH_iLastX; events[0].ymovement = pTouchDev->TOUCH_iLastY; events[0].ctype = MOUSE_CTYPE_ABS; events[0].kstat = 0; iTouchPoint = TOUCH_RELEASE_NUM; } pTouchDev->TOUCH_iLastX = events[0].xmovement; pTouchDev->TOUCH_iLastY = events[0].ymovement; API_InterVectorEnable(pTouchDev->TOUCH_ulVector); return (iTouchPoint); }
函數ct365GetRxData調用函數ct36xRegRead去讀取I2C數據。具體實現如程序清單 3-4所示:
程序清單 3-4 ct365GetRxData函數實現
static INT ct365GetRxData (PTOUCH_DEV pTouchDev, UINT8 *pucBuffer, UINT16 usLen) { INT iError; iError = ct36xRegRead(pTouchDev->TOUCH_pI2cDevice, 0, pucBuffer, usLen); return (iError); }
函數ct36xRegRead根據CT365的通訊流程讀取CT365反饋的觸控數據。具體實現如程序清單 3-5所示:
程序清單 3-5 ct36xRegRead函數實現
static INT ct36xRegRead (PLW_I2C_DEVICE pI2cDev, UINT8 ucReg, UINT8 *pucBuffer, UINT16 usLen) { INT iError; LW_I2C_MESSAGE i2cMsgs[] = { { .I2CMSG_usAddr = pI2cDev->I2CDEV_usAddr, .I2CMSG_usFlag = 0, .I2CMSG_usLen = 1, .I2CMSG_pucBuffer = (PUCHAR)&ucReg, }, { .I2CMSG_usAddr = pI2cDev->I2CDEV_usAddr, .I2CMSG_usFlag = LW_I2C_M_RD, .I2CMSG_usLen = usLen, .I2CMSG_pucBuffer = pucBuffer, }, }; iError = API_I2cDeviceTransfer(pI2cDev, i2cMsgs, 2); if (iError != 2) { printk(KERN_ERR "__ft5x06RxData(): failed to i2c transfer!\n"); return (PX_ERROR); } return (ERROR_NONE); }
當觸控驅動完成后,如程序清單 3-6所示,根據硬件原理圖在BSP文件中配置好CT365的中斷管腳和I2C信息:
程序清單 3-6 配置CT365驅動信息信息
static TOUCH_DATA _G_Ct365Data = { .T_pcBusName = "/bus/i2c/2", /* I2C 總線名稱 */ .T_uiIrq = IMX6Q_GPIO_NUMR(6, 14), /* IRQ 管腳號 */ .T_uiReset = NULL, /* Reset 管腳號 */ .T_uiIrqCfg = GPIO_FLAG_IN | GPIO_FLAG_TRIG_FALL, /* IRQ 中斷模式 */ .T_uiRstVal = LW_GPIOF_INIT_LOW, /* Reset 復位電平 */ .T_usAddr = 0x01, /* I2C 從機地址 */ .T_iWidth = 1024, /* 分辨率 寬 */ .T_iHeight = 768, /* 分辨率 高 */ .T_iTouchNum = 1, /* 最大觸摸點數 */};static TOUCH_DRV_FUNC _G_CT365DrvFunc = { .getevent = ct365GetEvent, .init = NULL, .deinit = NULL, .reset = NULL, };
如程序清單 3 7所示,配置完成后需要在函數boadDevInit里創建觸控設備:
程序清單 3-7 創建CT365觸控設備
touchDevCreate("/dev/input/touch0", _G_touchDrvNum, &_G_Ct365Data, &_G_CT365DrvFunc);
在系統正常啟動和驅動正常加載的情況下,運行任意一個帶觸摸或者鼠標組件的QT程序,進行觸控操作,如果正確響應觸控事件,說明驅動移植基本完成。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。