作者:黄思华 华侨大学信息学院
Crosstool: arm-linux-gcc-3.4.1硬件环境:
Host:X86PC
Target:友善之臂mini2440开发板
软件环境:
Host:fedora 10.0
Target:arm-linux kernel:linux-2.6.17
本实验方案采纳Singlewolfyu (大漠孤狼)在 MiniGUI 1.3.3 移植详解中带屏幕校正功能的 2410 的 IAL , 作者通过改写MiniGUI 1.3.3 版本中的 2410 的 IAL 程序,采用SMDK2410作为IAL引擎,实现了触摸屏原理,我将该方案弄到V1.6.0版本也成功地实现触摸屏的较正。改写的程序我命名为2410_touchmodify.c
该程序的说明:
在2410_touchmodify.c中定义了两个数组,如下
typedef struct mPoint { int x,
y ;
} mPOINT ;
static mPOINT ts_position[4]={ {940,926},{940,102},{96,104},{120,940} };
static mPOINT display_position[4]={ {0,0},{0,319},{239,319},{239,0} };
ts_position 意思为 TouchScreen 的 位置
display_position 意思为屏幕上显示的 位置
比如我前面说的,我的屏幕是 240x320 的,我交叉编译tslib并移植tslib到开发板,然后我点四个角 {0,0},{0,319},{239,319},{239,0} ,从触屏上读出来的数据分别为 {26,283},{26,32},{216,31},{216,285} ,填入这两个数就行
所以使用方法就是,你自己取四个顶角的点,点这四个点,得到相应的触摸屏读出来的值,把这些数据填到这两个数组中,OK,你的 触摸屏 就可以正常工作了 :)
得到四个顶点的原始坐标可以采用大漠孤狼的readpos.c 的程序,也可以采用我的方法交叉编译、移植tslib,运行tslib的./ts_print_raw来得到,关于tslib的交叉编译及使用,请参考我的另一篇文章,minigui V1.6.10 + tslib 触摸屏较正完美解决方案,博客地址http://blog.youkuaiyun.com/huangsihua/archive/2009/03/15/3992775.aspx我这里就不写出来了。我采用的是tslib的ts_printraw,当然大漠孤狼的readpos.c的方法我实验过也是可行的。
步骤一:
将readpos.c程序放入/libminigui1.6.0/rea/ial,然后在终端输入:
cd …./libminigui1.6.0/res/ial
进入该目录,对其进行交叉编译命令如下:
arm-linux-gcc –o readpos readpos.c
这样得到readpos可执行文件,你入到板子上运行一下就可以读取触摸屏的坐标了,是不是比较简单。
后面附一个 readpos.c 的程序,你可以执行它,然后点击触摸屏,它会显示出触摸屏读出来的值。
步骤二:
复制修改好后的2410.c程序到…./libminigui1.6.0/res/ial/替换原来的2410.c
程序在文章后面的附程序二:2410_touchmodify.c
步骤三:
重新配置编译libminigui1.6.0
./configure --prefix=/usr/local/arm/2.95.3/arm-linux --build=i386-linux --host=arm-linux --target=arm-linux --enable-smdk2410ial
make
make install
应该没什么问题。
步骤四:重新编译我的PDA应用程序
arm-linux-gcc -o pda pda.c -lminigui -lm -lz -lpng -ljpeg -lmgext -lpthread –lts
步骤五:改写配置文件Minigui.cfg及ts.conf并测试
Migigui.cfg修改部分:
[system]
# GAL engine
gal_engine=fbcon
# IAL engine
ial_engine=SMDK2410
mdev=/dev/input/ts0
mtype=none
[fbcon]
defaultmode=240x320-16bpp
ts.conf修改部分:
#module mousebuts
module variance xlimit=50 ylimit=50 pthreshold=3
module dejitter xdelta=1 ydelta=1 pthreshold=3
module linear
将应用程序放入开发板运行,好了,较正的不错哦,Perfect.
说明对于MINIGUI V1.3.3当然也是一样的,我的文章就是参考大漠孤狼在MINIGUI V1.3.3上的实现。只是那个版本的配置可以使用图形化的方式,make menuconfig
附程序一:Readpos.c 程序,帮助你读取触摸屏的值
#include <stdio.h>
typedef struct {
unsigned short pressure;
unsigned short x;
unsigned short y;
unsigned short pad;
} TS_EVENT;
static TS_EVENT ts_event;
static int ts;
int main()
{
ts = open ("/dev/ts", 0);
if (ts < 0) {
fprintf (stderr, "2410: Can not open touch screen!/n");
return 0;
}
while(1)
{
if( read (ts, &ts_event, sizeof (TS_EVENT)))
{
printf("X=%d,Y=%d,Pressure=%d /n",ts_event.x,ts_event.y,ts_event.pressure);
}
}
}
附程序二: 2410_touchmodify.c,修改后的SMDK2410的引擎2410.c
程序: 2410.c (2410_touchmodify.c )
/*
** $Id: 2410.c,v 1.4 2003/11/21 12:15:37 weiym Exp $
**
** 2410.c: Low Level Input Engine for SMDK2410 Dev Board.
**
** Copyright (C) 2003 Feynman Software.
*/
/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "common.h"
#ifdef _SMDK2410_IAL
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/kd.h>
#include <sys/time.h> /* i add it here */
#include <math.h>
#include <sys/poll.h>
#include <sys/types.h>
#include "ial.h"
#include "2410.h"
typedef struct mPoint {
int x,
y ;
} mPOINT ;
static mPOINT ts_position[4]={ {26,283},{26,32},{216,31},{216,285}
};
static mPOINT display_position[4]={ {0,0},{0,319},{239,319},{239,0}
};
typedef struct Matrix {
/* This arrangement of values facilitates
* calculations within getDisplayPoint()
*/
int An, /* A = An/Divider */
Bn, /* B = Bn/Divider */
Cn, /* C = Cn/Divider */
Dn, /* D = Dn/Divider */
En, /* E = En/Divider */
Fn, /* F = Fn/Divider */
Divider ;
} mMATRIX ;
static mMATRIX m_matrix;
int setCalibrationMatrix( mPOINT * display,
mPOINT * screen,
mMATRIX * matrix) ;
int getDisplayPoint( mPOINT * display,
mPOINT * screen,
mMATRIX * matrix ) ;
/* for data reading from /dev/ts */
typedef struct {
unsigned short pressure;
unsigned short x;
unsigned short y;
unsigned short pad;
} TS_EVENT;
static unsigned char state [NR_KEYS];
static int ts = -1;
static int mousex = 0;
static int mousey = 0;
static TS_EVENT ts_event;
#undef _DEBUG
/************************ Low Level Input Operations **********************/
/*
* Mouse operations -- Event
*/
static int mouse_update(void)
{
return 1;
}
static void mouse_getxy(int *x, int* y)
{
#ifdef _DEBUG
printf ("mousex = %d, mousey = %d/n", mousex, mousey);
#endif
if (mousex < 0) mousex = 0;
if (mousey < 0) mousey = 0;
if (mousex > 239) mousex = 239;
if (mousey > 319) mousey = 319;
*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
{
fd_set rfds;
int retvalue = 0;
int e;
static int last_pressure=0;
if (!in) {
in = &rfds;
FD_ZERO (in);
}
if ((which & IAL_MOUSEEVENT) && ts >= 0) {
FD_SET (ts, in);
#ifdef _LITE_VERSION
if (ts > maxfd) maxfd = ts;
#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) {
if (ts >= 0 && FD_ISSET (ts, in) ) {
FD_CLR (ts, in);
ts_event.x=0;
ts_event.y=0;
read (ts, &ts_event, sizeof (TS_EVENT));
if(last_pressure==0)
{
read(ts,&ts_event,sizeof(TS_EVENT));
read(ts,&ts_event,sizeof(TS_EVENT));
}
if (ts_event.pressure > 0 ) {
int new_x;
int new_y;
mPOINT ts_point,display_point;
ts_point.x=ts_event.x;
ts_point.y=ts_event.y;
getDisplayPoint(&display_point,&ts_point,&m_matrix);
new_x = display_point.x;
new_y = display_point.y;
if(last_pressure==0 || (last_pressure>0 && abs(new_x-mousex)<7))
mousex=new_x;
if(last_pressure==0 || (last_pressure>0 && abs(new_y-mousey)<7))
mousey=new_y;
/*
printf("ts_x=%d,ts_y=%d/n",ts_event.x,ts_event.y);
printf("mounsex=%dmousey=%d/n",mousex,mousey);
*/
}
#ifdef _DEBUG
if (ts_event.pressure > 0) {
printf ("mouse down: ts_event.x = %d, ts_event.y = %d/n", ts_event.x, ts_event.y);
}
#endif
ts_event.pressure = ( ts_event.pressure > 0 ? IAL_MOUSE_LEFTBUTTON : 0);
last_pressure=ts_event.pressure;
/*
printf("pressure=%d/n",ts_event.pressure);
*/
retvalue |= IAL_MOUSEEVENT;
}
}
else if (e < 0) {
return -1;
}
return retvalue;
}
BOOL Init2410Input (INPUT* input, const char* mdev, const char* mtype)
{
ts = open (mdev, O_RDONLY);
if (ts < 0) {
fprintf (stderr, "2410: Can not open touch screen!/n");
return FALSE;
}
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;
setCalibrationMatrix(&display_position,&ts_position,&m_matrix);
return TRUE;
}
void Term2410Input(void)
{
if (ts >= 0)
close(ts);
}
#endif /* _SMDK2410_IAL */
int setCalibrationMatrix( mPOINT * displayPtr,
mPOINT * screenPtr,
mMATRIX * matrixPtr)
{
int retvalue = 0 ;
matrixPtr->Divider = ((screenPtr[0].x - screenPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) -
((screenPtr[1].x - screenPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ;
if( matrixPtr->Divider == 0 )
{
retvalue = -1 ;
}
else
{
matrixPtr->An = ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) -
((displayPtr[1].x - displayPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ;
matrixPtr->Bn = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].x - displayPtr[2].x)) -
((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].x - screenPtr[2].x)) ;
matrixPtr->Cn = (screenPtr[2].x * displayPtr[1].x - screenPtr[1].x * displayPtr[2].x) * screenPtr[0].y +
(screenPtr[0].x * displayPtr[2].x - screenPtr[2].x * displayPtr[0].x) * screenPtr[1].y +
(screenPtr[1].x * displayPtr[0].x - screenPtr[0].x * displayPtr[1].x) * screenPtr[2].y ;
matrixPtr->Dn = ((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].y - screenPtr[2].y)) -
((displayPtr[1].y - displayPtr[2].y) * (screenPtr[0].y - screenPtr[2].y)) ;
matrixPtr->En = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].y - displayPtr[2].y)) -
((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].x - screenPtr[2].x)) ;
matrixPtr->Fn = (screenPtr[2].x * displayPtr[1].y - screenPtr[1].x * displayPtr[2].y) * screenPtr[0].y +
(screenPtr[0].x * displayPtr[2].y - screenPtr[2].x * displayPtr[0].y) * screenPtr[1].y +
(screenPtr[1].x * displayPtr[0].y - screenPtr[0].x * displayPtr[1].y) * screenPtr[2].y ;
}
return( retvalue ) ;
} /* end of setCalibrationMatrix() */
int getDisplayPoint( mPOINT * displayPtr,
mPOINT * screenPtr,
mMATRIX * matrixPtr )
{
int retvalue = 0 ;
if( matrixPtr->Divider != 0 )
{
/* Operation order is important since we are doing integer */
/* math. Make sure you add all terms together before */
/* dividing, so that the remainder is not rounded off */
/* prematurely. */
displayPtr->x = ( (matrixPtr->An * screenPtr->x) +
(matrixPtr->Bn * screenPtr->y) +
matrixPtr->Cn
) / matrixPtr->Divider ;
displayPtr->y = ( (matrixPtr->Dn * screenPtr->x) +
(matrixPtr->En * screenPtr->y) +
matrixPtr->Fn
) / matrixPtr->Divider ;
}
else
{
retvalue = -1 ;
}
return( retvalue ) ;
} /* end of getDisplayPoint() */