这是几个月以前的东西了,在彻底遗忘之前拿出来好好写写。做个笔记,也算是造福后来人了。在做这个项目之前,没有做过电容屏的驱动,印象中的电容触摸屏是不需要校正的。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 plain copy

  1. static void ft5x0x_ts_pen_irq_work(struct work_struct *work) { //底半部中断
  2. struct ft5x0x_ts_data *ts = container_of(work, struct ft5x0x_ts_data, work);
  3. if (!ft5x0x_read_data(ts)) {
  4. ft5x0x_ts_report(ts);
  5. }
  6. enable_irq(this_client->irq);
  7. }
  8. static irqreturn_t ft5x0x_ts_interrupt(int irq, void *dev_id) {//顶半部中断
  9. struct ft5x0x_ts_data *ts = dev_id;
  10. disable_irq_nosync(this_client->irq);
  11. if (!work_pending(&ts->work)) {
  12. queue_work(ts->queue, &ts->work);
  13. }
  14. return IRQ_HANDLED;
  15. }

从IC中读取触摸数据:

[cpp] view plain copy

  1. static int ft5x0x_read_data(struct ft5x0x_ts_data *ts) {
  2. struct ft5x0x_event *event = &ts->event;
  3. u8 buf[32] = { 0 };
  4. int ret;
  5. #ifdef CONFIG_FT5X0X_MULTITOUCH
  6. ret = ft5x0x_i2c_rxdata(buf, 31);
  7. #else
  8. ret = ft5x0x_i2c_rxdata(buf, 7);
  9. #endif
  10. if (ret < 0) {
  11. printk("%s: read touch data failed, %d\n", __func__, ret);
  12. return ret;
  13. }
  14. memset(event, 0, sizeof(struct ft5x0x_event));
  15. event->touch_point = buf[2] & 0x07;
  16. if (!event->touch_point) {
  17. ft5x0x_ts_release(ts);
  18. return 1;
  19. }
  20. #ifdef CONFIG_FT5X0X_MULTITOUCH
  21. switch (event->touch_point) {
  22. case 5:
  23. event->x[4] = (s16)(buf[0x1b] & 0x0F)<<8 | (s16)buf[0x1c];
  24. event->y[4] = (s16)(buf[0x1d] & 0x0F)<<8 | (s16)buf[0x1e];
  25. case 4:
  26. event->x[3] = (s16)(buf[0x15] & 0x0F)<<8 | (s16)buf[0x16];
  27. event->y[3] = (s16)(buf[0x17] & 0x0F)<<8 | (s16)buf[0x18];
  28. case 3:
  29. event->x[2] = (s16)(buf[0x0f] & 0x0F)<<8 | (s16)buf[0x10];
  30. event->y[2] = (s16)(buf[0x11] & 0x0F)<<8 | (s16)buf[0x12];
  31. case 2:
  32. event->x[1] = (s16)(buf[0x09] & 0x0F)<<8 | (s16)buf[0x0a];
  33. event->y[1] = (s16)(buf[0x0b] & 0x0F)<<8 | (s16)buf[0x0c];
  34. case 1:
  35. event->x[0] = (s16)(buf[0x03] & 0x0F)<<8 | (s16)buf[0x04];
  36. event->y[0] = (s16)(buf[0x05] & 0x0F)<<8 | (s16)buf[0x06];
  37. break;
  38. default:
  39. printk("%s: invalid touch data, %d\n", __func__, event->touch_point);
  40. return -1;
  41. }
  42. #else
  43. if (event->touch_point == 1) {
  44. event->x[0] = (s16)(buf[0x03] & 0x0F)<<8 | (s16)buf[0x04];
  45. event->y[0] = (s16)(buf[0x05] & 0x0F)<<8 | (s16)buf[0x06];
  46. }
  47. #endif
  48. event->pressure = 200;
  49. return 0;
  50. }

上报过程代码:

[cpp] view plain copy

  1. static void ft5x0x_ts_report(struct ft5x0x_ts_data *ts) {
  2. struct ft5x0x_event *event = &ts->event;
  3. int x, y;
  4. int i;
  5. #ifdef CONFIG_FT5X0X_MULTITOUCH
  6. for (i = 0; i < event->touch_point; i++) {
  7. if (swap_xy) {
  8. x = event->y[i];
  9. y = event->x[i];
  10. } else {
  11. x = event->x[i];
  12. y = event->y[i];
  13. }
  14. if (scal_xy) {
  15. x = (x * ts->screen_max_x) / TOUCH_MAX_X;
  16. y = (y * ts->screen_max_y) / TOUCH_MAX_Y;
  17. }
  18. input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
  19. input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
  20. input_report_abs(ts->input_dev, ABS_MT_PRESSURE, event->pressure);
  21. input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
  22. input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
  23. input_mt_sync(ts->input_dev);
  24. }
  25. #else
  26. if (event->touch_point == 1) {
  27. if (swap_xy) {
  28. x = event->y[i];
  29. y = event->x[i];
  30. } else {
  31. x = event->x[i];
  32. y = event->y[i];
  33. }
  34. if (scal_xy) {
  35. x = (x * ts->screen_max_x) / TOUCH_MAX_X;
  36. y = (y * ts->screen_max_y) / TOUCH_MAX_Y;
  37. }
  38. input_report_abs(ts->input_dev, ABS_X, x);
  39. input_report_abs(ts->input_dev, ABS_Y, y);
  40. input_report_abs(ts->input_dev, ABS_PRESSURE, event->pressure);
  41. }
  42. input_report_key(ts->input_dev, BTN_TOUCH, 1);
  43. #endif
  44. input_sync(ts->input_dev);
  45. }

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 plain copy

  1. #ifdef CONFIG_INPUT_TS_LINEAR
  2. static int ts_linear_scale(int *x, int *y, int swap_xy)
  3. {
  4. int xtemp, ytemp;
  5. int a[7] = {<span style="color: rgb(255, 0, 0);">87701,-382,-420352,-89,84218,-936128,65536</span>};
  6. xtemp = *x;
  7. ytemp = *y;
  8. if (a[6] == 0)
  9. return -EINVAL;
  10. *x = (a[2] + a[0] * xtemp + a[1] * ytemp) / a[6];
  11. *y = (a[5] + a[3] * xtemp + a[4] * ytemp) / a[6];
  12. if (swap_xy) {
  13. int tmp = *x;
  14. *x = *y;
  15. *y = tmp;
  16. }
  17. return 0;
  18. }
  19. #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咕唧咕唧)的更多相关文章

  1. 背水一战 Windows 10 (113) - 锁屏: 将 Application 的 Badge 通知和 Tile 通知发送到锁屏, 将 secondary tile 的 Badge 通知和 Tile 通知发送到锁屏

    [源码下载] 背水一战 Windows 10 (113) - 锁屏: 将 Application 的 Badge 通知和 Tile 通知发送到锁屏, 将 secondary tile 的 Badge ...

  2. google 分屏 横屏模式 按home键界面错乱故障分析(二) 分屏的启动过程

    google 进入分屏后在横屏模式按home键界面错乱(二) 你确定你了解分屏的整个流程? imageMogr2/auto-orient/strip%7CimageView2/2/w/1240&quo ...

  3. 索尼Sony ATI显卡驱动 Win7 Win8 Win8.1 视频黑屏 解决方法

    索尼ATI显卡驱动 Win7  Win8  Win8.1 视频 黑屏 完美解决方法: 下载这个补丁 安装 即可 解决  ! baidu pan:  http://pan.baidu.com/s/1gd ...

  4. linux 下 取进程占用内存(MEM)最高的前10个进程

    # linux 下 取进程占用 cpu 最高的前10个进程ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head # linux 下 取进程占用内存 ...

  5. 【转】Linux 下取进程占用 cpu/内存 最高的前10个进程

    # Linux 下 取进程占用 cpu 最高的前10个进程ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head # linux 下 取进程占用内存 ...

  6. DELPHI 10.2 TOKYO搭建LINUX MYSQL开发环境

    DELPHI 10.2 TOKYO搭建LINUX MYSQL开发环境 笔者使用ubuntu64位LINUX 首先必须保证LINUX可以连互联网. 安装MYSQLsudo apt-get update ...

  7. DELPHI 10.2(TOKYO) FOR LINUX的兼容性说明

    DELPHI 10.2(TOKYO) FOR LINUX的兼容性说明 自DELPHI 10.2(TOKYO) 始开始支持Linux . Delphi Linux 编译器 64 位 Linux 平台支持 ...

  8. 简析hotjar录屏功能实现原理

    简析hotjar录屏功能实现原理 众所周知,hotjar中录屏功能是其重要的一个卖点,看着很牛X酷炫的样子,今天就简单的分析一下其可能实现(这里只根据其请求加上个人理解分析,并不代表hotjar中真实 ...

  9. linux shell编程,先等10秒再判断是否有进程存在,存在就再等10秒再杀了进程才运行

    linux shell编程,先等10秒再判断是否有进程存在,存在就再等10秒再杀了进程才运行 crontab每分钟执行一次,但5秒以上才有更新数据,有时候一分钟可能跑不完上一个进程,需要先等10秒再判 ...

随机推荐

  1. python学习之路基础篇(第七篇)

    一.模块 configparser configparser用于处理特定格式的文件,其本质是利用open来对文件进行操作 [section1] # 节点 k1 = v1 # 值 k2:v2 # 值 [ ...

  2. weblogic静默方式创建域

    创建域目录:mkdir -p /home/weblogic/Oracle/Middleware/user_projects/domains/base_domain/ 创建文件: create_doma ...

  3. 0428-css样式

    一.CSS样式表      引入的三种方式1.内联样式:标签内部     style2.内嵌样式:<head></head>标签内部(<style></sty ...

  4. 非参数估计:核密度估计KDE

    http://blog.csdn.net/pipisorry/article/details/53635895 核密度估计Kernel Density Estimation(KDE)概述 密度估计的问 ...

  5. Android反编译(未混淆的apk)

    Android反编译(未混淆的apk) 工具 dex2jar 下载地址:我的CSDN 或者 官网 jd-gui 下载地址:我的CSDN 或者 官网 反编译步骤 1. 将APK解压缩,获取classes ...

  6. 浅析"Sublabel-Accurate Relaxation of Nonconvex Energies" CVPR 2016 Best Paper Honorable Mention

    今天作了一个paper reading,感觉论文不错,马克一下~ CVPR 2016 Best Paper Honorable Mention "Sublabel-Accurate Rela ...

  7. PHP+MySQL 分页那点事

    分页技术随处可见,这可以算得上是最为基础的网站功能了.于是今天尝试着用PHP来实现一个分页的小例子. 准备工作 环境准备 Apache MySQL PHP 工作环境 数据库准备 建库 建表 预存数据 ...

  8. Matlab 2015b 启动时崩溃 MATLAB crashes during startup on Ubuntu 16.04

    Matlab 启动时崩溃 MATLAB crashes during startup on Ubuntu Matlab 2015B Ubuntu 16.04 之前解决过,更新后问题又来了.     出 ...

  9. Dynamics CRM2013 Odata的filter中含有日期字段时遇到的一个奇葩问题

    在使用Odata拼写filter时我们一般都用工具,因为手写是件极不靠谱且错误率极高的事,下图是我用query designer拼出来的一个filter,因为时间是参数,所以在拷贝出下面这段filte ...

  10. 用Maven打包成EAR部署JBoss

    基于原理的架构里面,考虑这次升级版本,可谓是一步一个脚印的向上走啊,可以说步步为坎,别人的知识,和自己的知识,相差很多啊,什么都懂点,但是具体没有使用,就理解不深刻了,心有余而力不足,所以一切我们自己 ...