這是幾個月以前的東西了,在徹底遺忘之前拿出來好好寫寫。做個筆記,也算是造福后來人了。在做這個項目之前,沒有做過電容屏的驅動,印象中的電容觸摸屏是不需要校正的。IC支持多大的屏就要配多大的屏。但是拿到需求,發現要用FT5406做10寸屏,可是FT5406手冊上明明寫了,最大支持到8.9寸。由于經驗不足,感到略懵。就去核實這個需求方案是不是搞錯了?!得到的答案:藍魔的平板也是這個搭配。這樣, 那需求應該就沒問題了。先看現象再說:?
? ? ? ? ?硬件搭起來看現象,如下圖:
? ? ? ? ? 紅色區域是FT5406上報有效數據的范圍(1280*600),以左上角為原點 ,X軸方向上報數據的最大值1280,Y軸方向上報的最大數據是600.。但是我用的LG的10.1寸屏,分辨率為1366*768。若想把觸摸IC上報的數據和像素點的值一一對應起來,只能通過校正了。開始做校正的時候有點犯抽。竟然自己寫校正算法,代碼冗長不說,校準誤差也特別大。 還好,后來想起了tslib這個東西。tslib是專門為電阻屏設計的一個校正庫,只能校正單點觸摸數據。而FT5406是支持5點觸摸的。 不過只需要校正一點就可以了,這個點與其他四個點的上報數據的偏差大小無區別,只需要在驅動中做相同的消除偏差處理即可。思路有了,下面就從驅動開始說起:
1.?FT5406 在Linux 3.5 中的驅動要點----數據上報過程
FT5406是通過IIC總線同CPU進行數據交互的,內核中的驅動框架符合一個典型IIC設備驅動+輸入子系統(默認大家是了解IIC設備驅動和輸入子系統驅動的)。硬件I/O的初始化和寄存器配置就不在這里贅述了, 照著手冊來就可以了。重點看一下,數據上報過程,先看一個FT5406 原理圖(圖中標的是5206 ,沒關系接口是一樣的)::
? ??
原理圖上可以看到,用到了EINT14這根中斷線。通過這條中斷線,差不多就能猜到上報流程了吧:當用戶觸摸到觸摸板以后,產生中斷,在中斷服務程序中讀IIC。這樣就完成了一次數據的上報。下面就看看內核源碼的實現,先看一個流程圖:
? ? ? ??
中斷代碼實現如下:
[cpp]?view plaincopy
static?void?ft5x0x_ts_pen_irq_work(struct?work_struct?*work)?{???????struct?ft5x0x_ts_data?*ts?=?container_of(work,?struct?ft5x0x_ts_data,?work);????????if?(!ft5x0x_read_data(ts))?{??????????ft5x0x_ts_report(ts);??????}????????enable_irq(this_client->irq);??}????static?irqreturn_t?ft5x0x_ts_interrupt(int?irq,?void?*dev_id)?{??????struct?ft5x0x_ts_data?*ts?=?dev_id;????????disable_irq_nosync(this_client->irq);????????if?(!work_pending(&ts->work))?{??????????queue_work(ts->queue,?&ts->work);??????}????????return?IRQ_HANDLED;??}??
從IC中讀取觸摸數據:
[cpp]?view plaincopy
static?int?ft5x0x_read_data(struct?ft5x0x_ts_data?*ts)?{??????struct?ft5x0x_event?*event?=?&ts->event;??????u8?buf[32]?=?{?0?};??????int?ret;????#ifdef?CONFIG_FT5X0X_MULTITOUCH??????ret?=?ft5x0x_i2c_rxdata(buf,?31);??#else??????ret?=?ft5x0x_i2c_rxdata(buf,?7);??#endif??????if?(ret?<?0)?{??????????printk("%s:?read?touch?data?failed,?%d\n",?__func__,?ret);??????????return?ret;??????}????????memset(event,?0,?sizeof(struct?ft5x0x_event));????????event->touch_point?=?buf[2]?&?0x07;????????if?(!event->touch_point)?{??????????ft5x0x_ts_release(ts);??????????return?1;??????}????#ifdef?CONFIG_FT5X0X_MULTITOUCH??????switch?(event->touch_point)?{??????????case?5:??????????????event->x[4]?=?(s16)(buf[0x1b]?&?0x0F)<<8?|?(s16)buf[0x1c];??????????????event->y[4]?=?(s16)(buf[0x1d]?&?0x0F)<<8?|?(s16)buf[0x1e];??????????case?4:??????????????event->x[3]?=?(s16)(buf[0x15]?&?0x0F)<<8?|?(s16)buf[0x16];??????????????event->y[3]?=?(s16)(buf[0x17]?&?0x0F)<<8?|?(s16)buf[0x18];??????????case?3:??????????????event->x[2]?=?(s16)(buf[0x0f]?&?0x0F)<<8?|?(s16)buf[0x10];??????????????event->y[2]?=?(s16)(buf[0x11]?&?0x0F)<<8?|?(s16)buf[0x12];??????????case?2:??????????????event->x[1]?=?(s16)(buf[0x09]?&?0x0F)<<8?|?(s16)buf[0x0a];??????????????event->y[1]?=?(s16)(buf[0x0b]?&?0x0F)<<8?|?(s16)buf[0x0c];??????????case?1:??????????????event->x[0]?=?(s16)(buf[0x03]?&?0x0F)<<8?|?(s16)buf[0x04];??????????????event->y[0]?=?(s16)(buf[0x05]?&?0x0F)<<8?|?(s16)buf[0x06];??????????????break;??????????default:??????????????printk("%s:?invalid?touch?data,?%d\n",?__func__,?event->touch_point);??????????????return?-1;??????}??#else??????if?(event->touch_point?==?1)?{??????????event->x[0]?=?(s16)(buf[0x03]?&?0x0F)<<8?|?(s16)buf[0x04];??????????event->y[0]?=?(s16)(buf[0x05]?&?0x0F)<<8?|?(s16)buf[0x06];??????}??#endif????????event->pressure?=?200;????????return?0;??}??
上報過程代碼:
[cpp]?view plaincopy
static?void?ft5x0x_ts_report(struct?ft5x0x_ts_data?*ts)?{??????struct?ft5x0x_event?*event?=?&ts->event;??????int?x,?y;??????int?i;????#ifdef?CONFIG_FT5X0X_MULTITOUCH??????for?(i?=?0;?i?<?event->touch_point;?i++)?{??????????if?(swap_xy)?{??????????????x?=?event->y[i];??????????????y?=?event->x[i];??????????}?else?{??????????????x?=?event->x[i];??????????????y?=?event->y[i];??????????}????????????if?(scal_xy)?{??????????????x?=?(x?*?ts->screen_max_x)?/?TOUCH_MAX_X;??????????????y?=?(y?*?ts->screen_max_y)?/?TOUCH_MAX_Y;??????????}????????????input_report_abs(ts->input_dev,?ABS_MT_POSITION_X,?x);??????????input_report_abs(ts->input_dev,?ABS_MT_POSITION_Y,?y);????????????input_report_abs(ts->input_dev,?ABS_MT_PRESSURE,?event->pressure);??????????input_report_abs(ts->input_dev,?ABS_MT_TOUCH_MAJOR,?event->pressure);??????????input_report_abs(ts->input_dev,?ABS_MT_TRACKING_ID,?i);????????????input_mt_sync(ts->input_dev);??????}??#else??????if?(event->touch_point?==?1)?{??????????if?(swap_xy)?{??????????????x?=?event->y[i];??????????????y?=?event->x[i];??????????}?else?{??????????????x?=?event->x[i];??????????????y?=?event->y[i];??????????}????????????if?(scal_xy)?{??????????????x?=?(x?*?ts->screen_max_x)?/?TOUCH_MAX_X;??????????????y?=?(y?*?ts->screen_max_y)?/?TOUCH_MAX_Y;??????????}????????????input_report_abs(ts->input_dev,?ABS_X,?x);??????????input_report_abs(ts->input_dev,?ABS_Y,?y);??????????input_report_abs(ts->input_dev,?ABS_PRESSURE,?event->pressure);??????}????????input_report_key(ts->input_dev,?BTN_TOUCH,?1);??#endif????????input_sync(ts->input_dev);??}??
IC驅動的大致工作流程就是這樣的,下面就來看看該怎么去做校正:
一、這個電容屏是往exynos4412 核心 Android4.2設備上移植的,所以第一步要做的是往Anroid移植TSlib1.4庫。簡述移植過程
1.生成configure
??./autogen.sh
?安裝tslib中遇到的錯誤:./autogen.sh: 4: autoreconf: not found
??是因為在不同版本的?tslib?下執行?autogen.sh?產生。它們產生的原因一樣,是
?因為沒有安裝? automake?工具,? (ubuntu 13.10)用下面的命令安裝好就可以了。
?sudo apt-get install autoconf automake libtool
2./configure --host=交叉編譯器路徑(注意要用對應Android平臺自帶的bionic c編譯器而不是配套開發板的GNU C編譯器)
?? ?ac_cv_func_malloc_0_nonnull=yes -static?
在tslib/config.h文件中加入如下定義:
#define TS_CONF? "/system/etc/ts.conf"
#define PLUGIN_DIR "/system/lib"
#define TS_POINTERCAL "/data/etc/pointercal"
另外由于bionic c 和GNU c的差異,需要修改幾個tslib的頭文件編譯才能通過
將下面路徑文件
tslib/src/ts_open.c
tslib/tests/ts_calibrate.c
tslib/tests/fbutils.c
中的
#include <sys/fcntl.h>
修改成
#include <fcntl.h>
將tslib/tests/ts_calibrate.c文件中
static int clearbuf(struct tsdev *ts)
修改為
static void clearbuf(struct tsdev *ts)
如果使用GNU C編譯器在android shell下運行ts_calibrate會出現如下錯誤:
?sh: ./system/bin/ts_calibrate: No such file or directory
?3.編譯
make
?將etc/ts.conf?的參考配置:
修改tslib/etc/ts.conf內容如下:
module_raw input
module pthres pmin=1
module variance delta=30
module dejitter delta=100
module linear
4.在android源代碼init.rc中聲明tslib相關環境變量如下:
# touchscreen parameters
??? export TSLIB_FBDEVICE /dev/graphics/fb0
??? export TSLIB_CALIBFILE /data/etc/pointercal
??? export TSLIB_CONFFILE? /system/etc/ts.conf
??? export TSLIB_TRIGGERDEV /dev/input/event0
??? export TSLIB_TSDEVICE /dev/input/event1
?
?5.??????將/src/.lib 中生成的庫文件,分別全部拷貝開發板的根文件系統對應/system/lib 目錄中,將tests目錄中的ts_calibrate cp到system/bin中
到此完成對tslib的移植。
在運行ts_calibrate前首先要取消內核對多點觸摸的支持,因為tslib只能處理單點的數據格式,而且單點的數據,必須要滿足以下上報順尋:
?input_report_abs(ts->input_dev, ABS_X, x);
? ? ? ? ? ? ? ? input_report_abs(ts->input_dev, ABS_Y, y);
? ? ? ? ? ? ? ? input_report_abs(ts->input_dev, ABS_PRESSURE, event->pressure);
通過運行ts_calibrate,獲得校正參數,存放在/data?目錄下的pointercal文件中
最后要做的就是修改內核驅動?/drivers/input/touchscreen/ft5x06_ts.c,添加校正算法(如下)并添加獲得的校正參數(紅色標注即為獲得的校正參數)。如下:
[cpp]?view plaincopy
#ifdef?CONFIG_INPUT_TS_LINEAR??static?int?ts_linear_scale(int?*x,?int?*y,?int?swap_xy)??{??????????int?xtemp,?ytemp;??????????int?a[7]?=?{<span?style="color:?rgb(255,?0,?0);">87701,-382,-420352,-89,84218,-936128,65536</span>};??????????xtemp?=?*x;??????????ytemp?=?*y;????????????if?(a[6]?==?0)??????????????return?-EINVAL;????????????*x?=?(a[2]?+?a[0]?*?xtemp?+?a[1]?*?ytemp)?/?a[6];??????????*y?=?(a[5]?+?a[3]?*?xtemp?+?a[4]?*?ytemp)?/?a[6];????????????if?(swap_xy)?{??????????????????int?tmp?=?*x;??????????????????*x?=?*y;??????????????????*y?=?tmp;??????????}??????????return?0;??}??#endif??static void ft5x0x_ts_report(struct ft5x0x_ts_data *ts) {
? ? ? ? struct ft5x0x_event *event = &ts->event;
? ? ? ? int x, y;
? ? ? ? int i;
#ifdef CONFIG_FT5X0X_MULTITOUCH
? ? ? ? for (i = 0; i < event->touch_point; i++) {
? ? ? ? ? ? ? ? if (swap_xy) {
? ? ? ? ? ? ? ? ? ? ? ? x = event->y[i];
? ? ? ? ? ? ? ? ? ? ? ? y = event->x[i];
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? x = event->x[i];
? ? ? ? ? ? ? ? ? ? ? ? y = event->y[i];
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (scal_xy) {
? ? ? ? ? ? ? ? ? ? ? ? x = (x * ts->screen_max_x) / TOUCH_MAX_X;
? ? ? ? ? ? ? ? ? ? ? ? y = (y * ts->screen_max_y) / TOUCH_MAX_Y;
? ? ? ? ? ? ? ? }
#ifdef CONFIG_INPUT_TS_LINEAR
? ? ? ? ? ? ? ??
ts_linear_scale(&x, &y, swap_xy);#endif
在上報過程 首先通過static int ts_linear_scale(int *x, int *y, int swap_xy)函數將從IC獲得的觸摸點坐標消除偏差。
總結
以上是生活随笔為你收集整理的FT5X06 如何应用在10寸电容屏(linux-3.5电容屏驱动简析移植10寸电容屏驱动到Android4.2) (by liukun321咕唧咕唧)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。