minigui 1.6.10 + tslib 触摸屏较正方案

来源:互联网 发布:chakra linux 编辑:程序博客网 时间:2024/06/03 18:36
  • 移植tslib1.3
  • tslib和minigui的链接
  • 测试

说明:因为最近做PDA,要实现摄像头功能,而我的开发板mini2440,只有一个USB,而我的摄像头是USB的,鼠标没办法用了,只能用触摸笔,而触摸坐标非常不准,首先想到了qt下用的tslib,网上找了一下,还真有minigui+tslib的触摸屏较正方案。经过几天的实验,我在V1.6.0上用tslib加SMDK2410实现了触摸屏较正,也在V1.6.10上用tslib+dummy作为ial实现了触摸屏较正。此文先总结介绍minigui V1.6.10 + tslib 完美触摸屏较正方案。由于在libminigui 中没有发布2410.c,2410.h等,以前版本是有的,所以要用SMDK2410作为ial有些困难,我做过实验失败了,不想弄了,就用dummy+tslib解决吧。说了这么多,下面是详细步骤:硬件环境: Host:X86PC Target:友善之臂mini2440开发板软件环境: Host:VMware虚拟机下的redhat linux 9.0(完全安装) Target:arm-linux kernel:linux-2.6.13 Crosstool: arm-linux-gcc-3.4.1

移植tslib1.3

(1) 第一步:下载source code并解压我用的是tslib-1.3.tar.bz2。下载地址:http://download.csdn.net/source/673898

(2) 第二步:针对底层驱动修改配置信息

 

./autogen.sh                 //(这步会生产configure文件)./configure CC=arm-linux-gcc --build=i686-pc-linux --target=arm-linux --host=arm-linux  --prefix=/home/huangsihua/tslib/build --enable-inputapi=no 

其中最后一项--enable-inputapi=no 是由于驱动不支持ioctl操作,如果不改最后会有如下现象:我在板子上运行./ts_test的时候,总是提示我:ts_open: No such file or directory?

(3) 第三步:修改源码 1、 修改/tslib/plugins/Makefile里面找rpath

 

LDFLAGS :=$(LDFLAGS) -rpath $(PLUGIN_DIR)

修改为:

 

LDFLAGS :=$(LDFLAGS) -rpath `cd $(PLUGIN_DIR) && pwd` //(这个可是顿号)

 

否则make时报如下错:

make的时候libtool:link: only absolute run-paths are allowed

2、修改src/ts_read_raw.c中的

 

char *defaulttseventtype="UCB1x00";

改为

char *defaulttseventtype="H3600";  //因为我的触摸屏驱动对应此结构。

3、修改tslib源码的tests/ts_calibrate.c的getxy函数中修改一些代码。如下

 

static int getxy(struct tsdev *ts, int *x, int *y){        ..................................................................        ..................................................................        //修改的代码        /* Read until we get a touch. */        do {                                if (ts_read_raw(ts, &samp[0], 1) < 0) {                        perror("ts_read");                                                close_framebuffer();                        exit(1);                }        } while (samp[0].pressure > 0);                do {                                if (ts_read_raw(ts, &samp[0], 1) < 0) {                        perror("ts_read");                        close_framebuffer();                        exit(1);                }        } while (samp[0].pressure == 0);        printf("Took %d samples.../n",index);        ..................................................................        ..................................................................}

我发现tslib与minigui中对于压力参数的规定刚好相反,tslib规定samp[0].pressure> 0是按下,samp[0].pressure == 0是手松开而事实是相反的如果不改就会出现在运行./ts_calibrate程序时不能有效校准,这个一定得注意!!!!!!!!!!!!!!!

4、修改在tslib/plugins/mousebuts.c 的mousebuts_read函数中一段代码

 

//if(t>60)//{//dest->pressure=1000;//buts->fLeftBut=0;//}//else//{dest->pressure=0;buts->fLeftBut=2;//}

要将红色的部分注释掉,否则以后运行minigui时对按钮的操作时,如果对一个按钮进行点击时,并把光标停在按钮的上面它就会不断的触发按钮的点击事件,这当然不是我们想要得到的结果

(4)编译与安装

 

makemake install

经过安装步骤后,进入…./tslib/build 目录下可以看到如下几个文件夹: bin、etc、share、lib、include

 

# ls bin/ts_calibrate ts_print ts_test ts_print_raw

 

 

# ls etc/ts.conf 

这里建议配置为(我就是用的这个配置,效果还不错):

 

module mousebuts#module variance xlimit=20 ylimit=20 pthreshold=3#module dejitter xdelta=20 ydelta=20 pthreshold=3module linear

若实际运行时发现抖动比较厉害,可以采用下面的配置:

 

module mousebuts#module variance xlimit=20 ylimit=20 pthreshold=3module dejitter xdelta=20 ydelta=20 pthreshold=3module linear

 

# ls lib/libts-0.0.so.0 libts-0.0.so.0.1.0 libts.la libts.so

 

# ls share/ts/plugins/

将lib及include的内容COPY至/usr/local/arm/3.4.1/arm-linux/[lib、include]中。同时在/opt/FriendlyARM/mini2440/root_nfs下建立一个目录tslib

 

mkdir tslib

将主机…../tslib/build/下的五个文件夹COPY至该目录下至此tslib交叉编译安装完毕。

 

tslib和minigui的链接

完成了对 tslib 的交叉编译之后,下一步的事情就是改写 MiniGUI 的 IAL 引擎。MiniGUI自带的 IAL 输入引擎中,有一个叫做 dummy.c。为了尽可能简单,在这里为简单起见就在其基础上稍作修改,使之符合我们的要求即可。

 

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include "common.h"#include "tslib.h"#ifdef _DUMMY_IAL#include <sys/ioctl.h>#include <sys/poll.h>#include <sys/types.h>#include <sys/stat.h>#include <linux/kd.h>#include "ial.h"#include "dummy.h"#ifndef _DEBUG#define _DEBUG                    // for debugging#endif/* for storing data reading from /dev/touchScreen/0raw */typedef struct {        unsigned short pressure;        unsigned short x;        unsigned short y;        unsigned short pad;} TS_EVENT;static unsigned char state [NR_KEYS];static int mousex = 0;static int mousey = 0;static TS_EVENT ts_event;static struct tsdev *ts;/************************ Low Level Input Operations **********************//** Mouse operations -- Event*/static int mouse_update(void){        return 1;}static void mouse_getxy(int *x, int* y){        if (mousex < 0) mousex = 0;        if (mousey < 0) mousey = 0;        if (mousex > 639) mousex = 639;        if (mousey > 479) mousey = 479;        #ifdef _DEBUG        // printf ("mousex = %d, mousey = %d/n", mousex, mousey);        #endif        *x = mousex;        *y = mousey;}static int mouse_getbutton(void){        return ts_event.pressure;}#ifdef _LITE_VERSIONstatic int wait_event (int which, int maxfd, fd_set *in, fd_set *out, fd_set *except,                        struct timeval *timeout)#elsestatic int wait_event (int which, fd_set *in, fd_set *out, fd_set *except,struct timeval *timeout)#endif{        struct ts_sample sample;        int ret = 0;        int fd;        fd_set rfds;        int e;        if (!in) {                in = &rfds;                FD_ZERO (in);        }        fd = ts_fd(ts);        if ((which & IAL_MOUSEEVENT) && fd >= 0) {                FD_SET (fd, in);                #ifdef _LITE_VERSION                if (fd > maxfd) maxfd = fd;                #endif        }        #ifdef _LITE_VERSION        e = select (maxfd + 1, in, out, except, timeout) ;        #else        e = select (FD_SETSIZE, in, out, except, timeout) ;        #endif        if (e > 0) {                // input events is coming                if (fd > 0 && FD_ISSET (fd, in)) {                        FD_CLR (fd, in);                        ts_event.x=0;                        ts_event.y=0;                        ret = ts_read(ts, &sample, 1);                        if (ret < 0) {                                perror("ts_read()");                                exit(-1);                        }                        ts_event.x = sample.x;                        ts_event.y = sample.y;                        ts_event.pressure = (sample.pressure > 0 ? 4:0);                        //   if (ts_event.pressure > 0 &&                        if((ts_event.x >= 0 && ts_event.x <= 639) &&                        (ts_event.y >= 0 && ts_event.y <= 479)) {                                mousex = ts_event.x;                                mousey = ts_event.y;                                // printf("ts_event.x is %d, ts_event.y is %d------------------------------------->/n",ts_event.x ,ts_event.y);                        }                        //#ifdef _DEBUG                        //    if (ts_event.pressure > 0) {                        //  printf ("mouse down: ts_event.x = %d, ts_event.y = %d,ts_event.pressure = %d/n",ts_event.x,ts_event.y,ts_event.pressure);                        //   }                        //#endif                        ret |= IAL_MOUSEEVENT;                        return (ret);                }        }        else if (e < 0) {                return -1;        }        return (ret);}BOOL InitDummyInput(INPUT* input, const char* mdev, const char* mtype){        char *ts_device = NULL;        if ((ts_device = getenv("TSLIB_TSDEVICE")) != NULL) {                // open touch screen event device in blocking mode                ts = ts_open(ts_device, 0);        } else {                #ifdef USE_INPUT_API                ts = ts_open("/dev/input/0raw", 0);                #else                ts = ts_open("/dev/touchscreen/ucb1x00", 0);                #endif        }        #ifdef _DEBUG        printf ("TSLIB_TSDEVICE is open!!!!!!!!!!!/n");        #endif        if (!ts) {                perror("ts_open()");                exit(-1);        }        if (ts_config(ts)) {                perror("ts_config()");                exit(-1);        }        input->update_mouse = mouse_update;        input->get_mouse_xy = mouse_getxy;        input->set_mouse_xy = NULL;        input->get_mouse_button = mouse_getbutton;        input->set_mouse_range = NULL;        input->wait_event = wait_event;        mousex = 0;        mousey = 0;        ts_event.x = ts_event.y = ts_event.pressure = 0;        return TRUE;}void TermDummyInput(void){        if (ts)        ts_close(ts);}#endif /* _DUMMY_IAL */

修改好minigui的引擎文件后就可以对minigui进行重新编译了,因为用到了 tslib 库,所以必须在编译的时候告诉 MiniGUI 到哪里去找到 tslib 相关的头文件和共享库文件。具体做法如下所示:

 

[root@libminigui-1.6.10]# ./configure CC=arm-linux-gcc --build=i686-pc-linux --target=arm-linux --host=arm-linux --disable-galqvfb --disable-galecoslcd --disable-vbfsupport --prefix=/usr/local/arm/3.4.1/arm-linux CFLAGS="-I/usr/local/arm/3.4.1/arm-linux/include -L/usr/local/arm/3.4.1/arm-linux/lib -lts"[root@ libminigui-1.6.10]# make[root@ libminigui-1.6.10]# make install

这里说一下为什么要指定 CFLAGS 标志。其实,通过指定这个标志,告诉编译器应该到哪里去找 tslib 有关的头文件和共享文件, -lts则告诉链接器最后生成的 MiniGUI 的共享库文件最后要和 ts 库(ts 是 touchscreen 的缩写)链接。 将生成的minigui的库从/usr/local/arm/3.4.1/arm-linux/lib COPY到/opt/FriendlyARM/mini2440/root_nfs/lib下。

[Root]# cp /usr/local/arm/3.4.1/arm-linux/etc/MiniGUI.cfg /home/fp/nfs/usr/local/etc/ 记住,保持目录结构的一致修改 MiniGUI.cfg ,如下

 

[system]# IAL engineial_engine=dummy // 这里修改,我用的是触摸屏,所以就用dummy肯定不会错mdev=/dev/input/ts0      //解摸屏mtype=none[fbcon]defaultmode=240x320-16bpp // 根据你的LCD大小自己设置,设置错误minigui 就启动不了。

这样我们就把tslib和minigui通过dummy链接好了。

 

测试

重编译我我修改制作的PDA程序并将它和res文件COPY到/opt/FreindlyARM/mini2440/root_nfs/usr/local/下,打开超级终端,打开开发板,按回车进入VIVI,输入NFS启动命令:

 

param set linux_cmd_line "console=ttySAC0 root=/dev/nfs nfsroot=192.168.1.111:/opt/FriendlyARM/root_nfs ip=192.168.1.70:192.168.1.111:192.168.1.111:255.255.255.0:sbc2440.arm9.net:eth0:off"

同时在终端输入扩展命令:

 

export QWS_MOUSE_PROTO=TPanel:/dev/input/event0export V_ROOT=/tslib#export TSLIB_TSEVENTTYPE=H3600export TSLIB_CONSOLEDEVICE=noneexport TSLIB_FBDEVICE=/dev/fb0export TSLIB_TSDEVICE=/dev/input/event0export TSLIB_CALIBFILE=$V_ROOT/etc/pointercalexport TSLIB_CONFFILE=$V_ROOT/etc/ts.confexport TSLIB_PLUGINDIR=$V_ROOT/share/ts/pluginsexport LD_LIBRARY_PATH=$V_ROOT/lib:$LD_LIBRARY_PATH

当然你也可以把这一串加到profile文件,让开发板在启动时运行这些命令。最后进入程序所在目录运行 ./PDA就可以了,效果非常不错,堪称完美。有点长哦, minigui V1.6.10 + tslib 触摸屏较正完美解决方案,欢迎大家提出意见和更好的方案。

EMAIL:huangsihua@hqu.edu.cn

本人CSDN博客http://blog.csdn.net/huangsihua

参考文章:myleeming CSDN博客minigui+tslib编译全过程

 

 

-- SihuaHuang - 17 Mar 2009

原创粉丝点击