linux的触摸屏之一:原理及APK调试

(1)原理:本文抛开技术层次上来说说LINUX触摸屏设备驱动原理。触摸屏,就是用一块AD转换模块来将屏幕上的触摸信号转成数字信号。触摸屏常用的是四线电阻,当触摸时候,功能模块会将模拟信号转换成数字信号,就是通常说的AD转换。在LINUX中,通常是通过中断来读取这些数字的。触摸屏幕的时候,中断发生,LINUX通过串口或者I2C,SPI或者内部数据通道等去读取转换后的数字,然后把数值传给INPUT层。

      为什么要校验?原因A,触摸屏与LCD显示屏是两个不同的物理器件。LCD处理的像素,例如我们通常所说的分辨率是600x800,实际就是指每行的宽度是600个像素,高度是800个像素,而触摸屏处理的数据是点的物理坐标,该坐标是通过触摸屏控制器采集到的。两者之间需要一定的转换。B,其次在安装触摸屏时,不可避免的存在着一定的误差,如旋转,平移的,这同样需要校正解决。C,再次,电阻式触摸屏的材料本身有差异而且随着时间的推移,其参数也会有所变化,因此需要经常性的校正(电容式触摸屏只需要一次校正即可)。

                                   

      比较常用的校验程序是TSLIB。通过TSLIB校验后,应用程序读取TSLIB里的数值,这个时候就能准确定位了。校正原理: 触摸屏的校正过程一般为:依次在屏幕的几个不同位置显示某种标记(如"+"),用触摸笔点击这些标记, 完成校正。如果PT(x, y)表示触摸屏上的一个点,PL(x, y)表示LCD上的一个点,校正的结果就是得到一个转换矩阵M,使PL(x, y) = M·PT(x, y)。最终,假设LCD三个点的坐标为(XL1, YL1),(XL2, YL2),(XL2, YL2), 对应触摸屏上的三个点是(XT1, YT1),(XT2, YT2),(XT3, YT3),则联立两个方程组为:

     

这样,触摸屏的校正实际上就是解上面的方程组,得到6个系数:A、B、C、D、E、F。而上面方程组按照克莱姆法则解即可。在得到6个系数后,以后通过触摸屏得到的所有坐标,带入公式(1)中就可以得到LCD上以像素表示的坐标。

      实际上,在校正时,采集的触摸屏的点坐标有一定的误差,也就是说采集几个三组点坐标,分别计算A、B、C、D、E、F,其结果不尽相同。在tslib的ts_calibrate中,采集了五组点坐标,具体代码参见ts_calibrate.c中的perform_calibration()。一般来说,采集的点越多,校正的精确性就越高。只是采集点过多就会冗余,对校正精确性的提高作用很少,反而增加了计算时间。 

      归结过程如下:

      android 的坐标转换处理:This implementation is a linear transformation using 7 parameters
(a, b, c, d, e, f and s) to transform the device coordinates (Xd, Yd) into screen coordinates (Xs, Ys) using the following equations:

 s*Xs = a*Xd + b*Yd + c
 s*Ys = d*Xd + e*Yd + f
其中:Xs,Ys:LCD坐标;Xd,Yd:触摸屏坐标。

(2)调试:触摸屏一直定位不准,会有偏移。同事经过一段时间的调试之后,解决了此问题。解决方式如下:

1,原理:Calibrate: 下载tslibonandroid,通过它来在屏幕上显示五个坐标,点击这五个坐标,得到需要的7个参数,实现坐标转换。
过程:icon(apk)->jni->*.so(tslib)->生成校正参数(a0~a6)。校正时候,必须通知driver,校正完成或者校正失败都要通知driver。而touch  driver每次上电后需要读取一次校正参数,如果读取失败则使用默认参数。

2,改动:

 - 在$kernel/driver/input/touchscreen/s3c-ts.c,添加跟上层cupcake接口的函数。
 - 改动$kernel/dirver/char/vt_ioctl.c
 - 在$cupcake/development/中添加calibrate整个文件夹(实现java icon和JNI调用),该文件夹负责生成一个android应用软件apk
 - 在$cupcake/external/中添加tslibonandroid整个文件夹(实现生成校正参数)
 - 在$cupcake/vendor/sec/smdk6410/init.rc,改动跟touch screen相关文件的属性权限。

       把kernel和cupcake完整编译后,烧录进板子。cupcake会在out/target/product/smdk6410/obj/APPS/Calibrate_intermediates下生成一个对应的apk文件,将该apk文件改名后安装入平台,点击即可运行与WINCE相似的校准过程。

3,程序过程:

A,点击APK,开始运行程序。在Calibrate.java中:onCreate-》tsmainloop。同时:

public native void tsmainloop();   //JNI函数申明

System.loadLibrary("calibrate-jni");   //载入库libcalibrate-jni.o

B,JNI的C函数原型定义在com_android_calibrate_Calibrate.cpp中:

#include "../../../external/tslibonandroid/tests/calibratejni.h" //该文件所在的文件夹作为当前目录回退3层再进入其他子目录

static void tsmainloop(JNIEnv *env, jobject object)
{
      ts_main();
}

在该文件中,还定义了方法跟class:

static const char *classPathName = "com/android/calibrate/Calibrate"; //指向该CPP被调用的class

static JNINativeMethod methods[] = {
      {"tsmainloop", "()V", (void*)tsmainloop },
};

完成JNI的注册。

C,在external/tslibonandroid/tests路径下的ts_calibrate.c完成TSLIB过程,如下:

#define TSLIB_TSDEVICE   "/dev/input/event1"      //内核为TS分配的INPUT设备名
#define DEVICE_NAME      "/dev/myts"                    //要访问的TS字符设备名
#define TSLIB_CALIBFILE  "/system/etc/pointercal"
#define TS_POINTERCAL    "/system/etc/pointercal"      //最终需要用到的pointercal文件,写入7个参数

#define TSLIB_CONFFILE  "/system/etc/tslib/ts.conf"     //tslib中的配置文件

typedef  struct {
     int x[5], xfb[5];   //x方向的触摸屏参数,LCD参数
     int y[5], yfb[5];   //y方向的触摸屏参数,LCD参数
     int a[7];              //存储那七个参数
} calibration;

ts_main()

{

      calibration cal;

      char cal_buffer[256];

      char buffer[5] = "OK";
      int fd = open("/dev/myts",O_RDWR);    //打开内核定义的TS字符设备,写入OK字符

      write(fd,buffer,2); 
      close(fd);

 

      struct tsdev *ts = ts_open(getenv("TSLIB_TSDEVICE"),0)  //打开内核TS设备

      ts_config(ts);                                                          //读取ts.conf,给ts配置

      open_framebuffer();                                              //打开显示设备,准备画图

      put_string_center (xres / 2, yres / 4, "TSLIB calibration utility", 1);               //在屏幕中心放置字符串
      put_string_center (xres / 2, yres / 4 + 20, "Touch crosshair to calibrate", 2);  //表示程序运行开始

      clearbuf(ts);                                                             //清空TS

 

      get_sample (ts, &cal, 0, 50,        50,        "Top left");
      get_sample (ts, &cal, 1, xres - 50, 50,        "Top right");
      get_sample (ts, &cal, 2, xres - 50, yres - 50, "Bot right");
      get_sample (ts, &cal, 3, 50,        yres - 50, "Bot left");     //按照左上,右上,右下,左下,中五个次序,读取采样值,按
      get_sample (ts, &cal, 4, xres / 2,  yres / 2,  "Center");    //0,1,2,3,4这个index编号存储在cal变量中

 

      if (perform_calibration (&cal))   //如果校验成功

      {

              cal_fd = open (getenv("TSLIB_CALIBFILE"), O_CREAT | O_RDWR,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

                                                                                              //打开系统的pointercal文件

              sprintf (cal_buffer,"%d %d %d %d %d %d %d",cal.a[1], cal.a[2], cal.a[0],cal.a[4], cal.a[5], cal.a[3], cal.a[6]);

                                                                                              //把cal的7个参数值组合到cal_buffer变量中

              write (cal_fd, cal_buffer, strlen (cal_buffer) + 1);    //写入7个参数到pointercal文件中

      }

       strcpy(buffer,"END");
       fd = open("/dev/myts",O_RDWR);

       printf("fd: %d/n",fd);
       write(fd,buffer,3); 

       close(fd);                //写END到内字符设备myts中

}

 

参考原文:http://blog.csdn.net/besthyq/archive/2007/10/01/1808762.aspx


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值