minigui V1.6.10 + tslib 觸摸屏較正完美解決方案

作者:黃思華   地址:華僑大學信息學院

 說明:因爲最近做PDA,要實現攝像頭功能,而我的開發板mini2440,只有一個USB,而我的攝像頭是USB的,鼠標沒辦法用了,只能用觸摸筆,而觸摸座標非常不準,首先想到了qt下用的tslib,網上找了一下,還真有minigui+tslib的觸摸屏較正方案。經過幾天的實驗,我在V1.6.0上用tslibSMDK2410實現了觸摸屏較正,也在V1.6.10上用tslib+dummy作爲ial實現了觸摸屏較正。此文先總結介紹minigui V1.6.10 + tslib 完美觸摸屏較正方案。

由於在libminigui 中沒有發佈2410.c,2410.h等,以前版本是有的,所以要用SMDK2410作爲ial有些困難,我做過實驗失敗了,不想弄了,就用dummy+tslib解決吧。說了這麼多,下面是詳細步驟:

硬件環境:

HostX86PC

Target:友善之臂mini2440開發板

軟件環境:

HostVMware虛擬機下的redhat linux 9.0(完全安裝)

Targetarm-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.cgetxy函數中修改一些代碼。如下

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);

..................................................................

..................................................................

}

我發現tslibminigui中對於壓力參數的規定剛好相反,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)編譯與安裝

make

make install

經過安裝步驟後,進入…./tslib/build 目錄下可以看到如下幾個文件夾:

binetcsharelibinclude

# 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=3

module linear

若實際運行時發現抖動比較厲害,可以採用下面的配置:

module mousebuts

#module variance xlimit=20 ylimit=20 pthreshold=3

module dejitter xdelta=20 ydelta=20 pthreshold=3

module linear

  # ls lib/

 libts-0.0.so.0 libts-0.0.so.0.1.0 libts.la libts.so

  # ls share/ts/

      plugins/

libinclude的內容COPY/usr/local/arm/3.4.1/arm-linux/[libinclude]中。

同時在/opt/FriendlyARM/mini2440/root_nfs下建立一個目錄tslib

mkdir tslib

將主機…../tslib/build/下的五個文件夾COPY至該目錄下

至此tslib交叉編譯安裝完畢。

二、修改dummy.c重新配置編譯libminigui(tslibminigui的鏈接)


完成了對 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 > 239) mousex = 239;

        if (mousey > 319) mousey = 319;

#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_VERSION

static int wait_event (int which, int maxfd, fd_set *in, fd_set *out, fd_set *except,                        struct timeval *timeout)

#else

static 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 <= 239) &&

                        (ts_event.y >= 0 && ts_event.y <= 319)) {

                        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 相關的頭文件和共享庫文件。具體做法如下所示:

[[email protected]]# ./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 engine

ial_engine=dummy // 這裏修改,我用的是觸摸屏,所以就用dummy肯定不會錯

mdev=/dev/input/ts0      //解摸屏

mtype=none

[fbcon]

defaultmode=240x320-16bpp // 根據你的LCD大小自己設置,設置錯誤minigui 就啓動不了。

這樣我們就把tslibminigui通過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/event0

export V_ROOT=/tslib

#export TSLIB_TSEVENTTYPE=H3600

export TSLIB_CONSOLEDEVICE=none

export TSLIB_FBDEVICE=/dev/fb0

export TSLIB_TSDEVICE=/dev/input/event0

export TSLIB_CALIBFILE=$V_ROOT/etc/pointercal

export TSLIB_CONFFILE=$V_ROOT/etc/ts.conf

export TSLIB_PLUGINDIR=$V_ROOT/share/ts/plugins

export LD_LIBRARY_PATH=$V_ROOT/lib:$LD_LIBRARY_PATH

當然你也可以把這一串加到profile文件,讓開發板在啓動時運行這些命令。

最後進入程序所在目錄運行

./PDA就可以了,效果非常不錯,堪稱完美。

有點長哦, minigui V1.6.10 + tslib 觸摸屏較正完美解決方案,歡迎大家提出意見和更好的方案。

EMAIL[email protected]

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

參考文章:myleeming   CSDN博客minigui+tslib編譯全過程

 

發佈了16 篇原創文章 · 獲贊 6 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章