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

    STM32 HAL 驱动SPI总线2.13寸电子纸墨水屏 电子纸墨水屏具有断电界面不失和低反光度的护眼效果.QYEG0213RWS800是2.13寸黑白红三色墨水屏,分辨率为250*122. STM3 ...

  2. olcd12864的u8g2库_U8G2 软件包单色1.3寸OLED屏驱动在 RT-Thread 移植问题

    本帖最后由 XYX 于 2019-5-21 21:06 编辑 * 前提说明: U8G2 软件包单色1.3寸OLED屏驱动在 RT-Thread 移植到stm32l4r5-st-nucleo板,使用的是 ...

  3. 计算机屏幕尺寸不是全屏,为什么把电脑显示器分辨率调成1366X768后网页不能全屏显示呢?...

    为什么把电脑显示器分辨率调成1366X768后网页不能全屏显示呢?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 为什么 ...

  4. 蓝屏含义原理分析处理方法代码电脑计算机故障系统安全 - 蓝屏知识大全

    目录 1含义2原理分析3处理方法4代码含义和解决-5原因分析6预防电脑蓝屏的-   含义 引蓝屏解释 1.故障检查信息 ***STOP 0x0000001E(0xC0000005,0xFDE38AF9 ...

  5. STM32驱动代码:STM32F4驱动7针0.96寸OLED显示字符、汉字

    STM32F4驱动7针0.96寸OLED显示字符.汉字 适用于stm32f1.stm32f4移植 工程资料链接:STM32F4驱动7针0.96寸OLED.rar 一. 代码效果 二.硬件准备 1.准备 ...

  6. imp 只导表前10条数据_做电商设计,你必须懂的10条数据指标

    数据指标是什么?--是一个切入数据的角度.有了数据指标的存在,才能知道需要采集什么数据.需要持续监测什么数据.用什么角度来和历史表现做对比. 数据指标的类型各种各样,有些指标是被广泛使用的,如 DAU ...

  7. 手动制造报错_Windows 10驱动更新调整:不再自动安装“手动”驱动更新

    正如上月月底放出的公告,微软已经对 Windows 10 驱动更新进行了调整.虽然这项新调整的目的是为了改善整体体验,但在极少数情况下可能会给某些用户带来麻烦. 01 Windows 10驱动更新调整 ...

  8. 电容笔和触控笔有什么区别?ipad手写电容笔推荐品牌

    电容笔和触控笔的区别其实很大,首先他们的导体材料不同,电容笔是通过笔头静电,跟电容屏幕本身的静电感应特点进行触控:而触控笔是通过按压屏幕来进行书写,而且触控笔也只适用于电阻屏,现在的手机绝大部分都是电 ...

  9. 【系统之家首发】10月最新GhostWin7_SP1旗舰版(64位)电脑公司装机版v2011.10

    GhostWin7_SP1旗舰版(64位)电脑公司装机版v2011.10 ■ 概述: Ghost7是指使用Ghost软件做成压缩包的Windows7,俗称克隆版Win7.用克隆版的目的是节省安装时间. ...

最新文章

  1. Win10下VisualStudio2019安装及测试
  2. spark context stop use with as
  3. 2017.10.23解题报告
  4. php中strtotime的意思,PHP中strtotime
  5. 机器学习中的「相似度度量」方法及应用
  6. 输油管的布置数学建模matlab,输油管的布置-数学建模.docx
  7. 常见NoSQL数据库概述
  8. Wireshark数据抓包分析之FTP协议
  9. 用计算机绘制二项分布概率图,二项分布和泊松分布实验.doc
  10. 基于W800的AIOT离在线一体方案说明 (阿里飞燕+离线语音控制)
  11. QAC静态测试配置及使用教程
  12. 【ESP 保姆级教程】疯狂毕设篇 —— 案例:基于物联网的GY906红外测温门禁刷卡系统
  13. 小学作文批改评语大全
  14. 恢复出厂设置和格式化SD卡
  15. 新西兰公民在中国大陆境内在线申请护照注意事项
  16. 机械革命蛟龙16K和蛟龙16区别
  17. Scrapy豆瓣爬虫 爬取用户以及用户关注关系
  18. 听说一个漂亮的小姐姐图片是程序员无法抗拒的
  19. 2017亿欧创新者年会暨第三届创新奖颁奖盛典 | 互联网行业公会
  20. linux编程 —— shell编程脚本常用语法总结 【学习笔记】

热门文章

  1. 上传文件 微信小程序input_快速上手微信小程序UI框架
  2. java 显示日历_JAVA显示日历(已知年和该年第一天为星期几)
  3. else if mybatis 嵌套_mybatis踩坑之——foreach循环嵌套if判断
  4. 你应该更新的Java知识
  5. java数组split_js数组接受split(java split)
  6. python实验指导书2018_python实验指导书
  7. c语言 mysql_bind,linux C mysql的blob门类字段的插入和读取
  8. 用c语言编程实现strcpy,用c语言.模拟实现strcpy,strcat,strcat,memcpy,memmove
  9. 一周一论文(翻译 总结)—— [NSDI 17] TUX2: Distributed Graph Computation for Machine Learning 面向机器学习的分布式图处理系统
  10. mysql清理连接数缓存,MySQL连接池、线程缓存、线程池的区别