<pre name="code" class="html">这个程序主要用来解决电阻屏第一次校准时防止产品线工人乱校屏和校屏时不再需要保存第一次校准屏幕的参数;
方法:根据不同触摸屏的x,y轴的不同的比例来小化5点校准位置。
</pre><pre code_snippet_id="543384" snippet_file_name="blog_20141205_1_6604879" name="code" class="html">/*
* tslib/tests/ts_calibrate.c
*
* Copyright (C) 2001 Russell King.
*
* This file is placed under the GPL. Please see the file
* COPYING for more details.
*
*
* Basic test program for touchscreen library.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <linux/kd.h>
#include <linux/vt.h>
#include <linux/fb.h>
#include "tslib.h"
#include "fbutils.h"
#include "testutils.h"
static int palette [] =
{
0x000000, 0xffe080, 0xffffff, 0xe0c0a0
};
#define NR_COLORS (sizeof (palette) / sizeof (palette [0]))
typedef struct {
int x[5], xfb[5];
int y[5], yfb[5];
int a[7];
} calibration;
static void sig(int sig)
{
close_framebuffer ();
fflush (stderr);
printf ("signal %d caught\n", sig);
fflush (stdout);
exit (1);
}
int perform_calibration(calibration *cal) {
int j;
float n, x, y, x2, y2, xy, z, zx, zy;
float det, a, b, c, e, f, i;
float scaling = 65536.0;
// Get sums for matrix
n = x = y = x2 = y2 = xy = 0;
for(j=0;j<5;j++) {
n += 1.0;
x += (float)cal->x[j];
y += (float)cal->y[j];
x2 += (float)(cal->x[j]*cal->x[j]);
y2 += (float)(cal->y[j]*cal->y[j]);
xy += (float)(cal->x[j]*cal->y[j]);
}
// Get determinant of matrix -- check if determinant is too small
det = n*(x2*y2 - xy*xy) + x*(xy*y - x*y2) + y*(x*xy - y*x2);
if(det < 0.1 && det > -0.1) {
printf("ts_calibrate: determinant is too small -- %f\n",det);
return 0;
}
// Get elements of inverse matrix
a = (x2*y2 - xy*xy)/det;
b = (xy*y - x*y2)/det;
c = (x*xy - y*x2)/det;
e = (n*y2 - y*y)/det;
f = (x*y - n*xy)/det;
i = (n*x2 - x*x)/det;
// Get sums for x calibration
z = zx = zy = 0;
for(j=0;j<5;j++) {
z += (float)cal->xfb[j];
zx += (float)(cal->xfb[j]*cal->x[j]);
zy += (float)(cal->xfb[j]*cal->y[j]);
}
// Now multiply out to get the calibration for framebuffer x coord
cal->a[0] = (int)((a*z + b*zx + c*zy)*(scaling));
cal->a[1] = (int)((b*z + e*zx + f*zy)*(scaling));
cal->a[2] = (int)((c*z + f*zx + i*zy)*(scaling));
printf("%f %f %f\n",(a*z + b*zx + c*zy),
(b*z + e*zx + f*zy),
(c*z + f*zx + i*zy));
// Get sums for y calibration
z = zx = zy = 0;
for(j=0;j<5;j++) {
z += (float)cal->yfb[j];
zx += (float)(cal->yfb[j]*cal->x[j]);
zy += (float)(cal->yfb[j]*cal->y[j]);
}
// Now multiply out to get the calibration for framebuffer y coord
cal->a[3] = (int)((a*z + b*zx + c*zy)*(scaling));
cal->a[4] = (int)((b*z + e*zx + f*zy)*(scaling));
cal->a[5] = (int)((c*z + f*zx + i*zy)*(scaling));
printf("%f %f %f\n",(a*z + b*zx + c*zy),
(b*z + e*zx + f*zy),
(c*z + f*zx + i*zy));
// If we got here, we're OK, so assign scaling to a[6] and return
cal->a[6] = (int)scaling;
return 1;
/*
// This code was here originally to just insert default values
for(j=0;j<7;j++) {
c->a[j]=0;
}
c->a[1] = c->a[5] = c->a[6] = 1;
return 1;
*/
}
static void get_sample (struct tsdev *ts, calibration *cal,
int index, int x, int y, char *name)
{
static int last_x = -1, last_y;
if (last_x != -1) {
#define NR_STEPS 10
int dx = ((x - last_x) << 16) / NR_STEPS;
int dy = ((y - last_y) << 16) / NR_STEPS;
int i;
last_x <<= 16;
last_y <<= 16;
for (i = 0; i < NR_STEPS; i++) {
put_cross (last_x >> 16, last_y >> 16, 2 | XORMODE);
usleep (1000);
put_cross (last_x >> 16, last_y >> 16, 2 | XORMODE);
last_x += dx;
last_y += dy;
}
}
put_cross(x, y, 2 | XORMODE);
getxy (ts, &cal->x [index], &cal->y [index]);
put_cross(x, y, 2 | XORMODE);
last_x = cal->xfb [index] = x;
last_y = cal->yfb [index] = y;
printf("%s : X = %4d Y = %4d\n", name, cal->x [index], cal->y [index]);
}
static int clearbuf(struct tsdev *ts)
{
int fd = ts_fd(ts);
fd_set fdset;
struct timeval tv;
int nfds;
struct ts_sample sample;
while (1) {
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
tv.tv_sec = 0;
tv.tv_usec = 0;
nfds = select(fd + 1, &fdset, NULL, NULL, &tv);
if (nfds == 0) break;
if (ts_read_raw(ts, &sample, 1) < 0) {
perror("ts_read");
exit(1);
}
}
}
#define ERR_LIMIT 85000
static int check_point(calibration *cal){
/*current eight length data*/
int curr_dat[8] = {0};
/*calculate after data*/
int margin_of_error[8] = {0};
int X_scale,Y_scale;
int i,tmp1,tmp2;
memset(curr_dat,0,sizeof(curr_dat));
memset(margin_of_error,0,sizeof(margin_of_error));
for(i = 0;i < 3;i++){
tmp1 = abs(cal->x[i+1] - cal->x[i]);
tmp2 = abs(cal->y[i+1] - cal->y[i]);
curr_dat[i] = tmp1*tmp1+tmp2*tmp2;
}
tmp1 = abs(cal->x[0] - cal->x[3]);
tmp2 = abs(cal->y[0] - cal->y[3]);
curr_dat[3] = tmp1*tmp1+tmp2*tmp2;
for(i = 4;i < 8;i++){
tmp1 = abs(cal->x[i-4] - cal->x[4]);
tmp2 = abs(cal->y[i-4] - cal->y[4]);
curr_dat[i] = tmp1*tmp1+tmp2*tmp2;
}
tmp1 = (abs(cal->x[0] - cal->x[2]) + abs(cal->x[1] - cal->x[3]))/2;
X_scale = (tmp1*100)/700;
tmp2 = (abs(cal->y[0] - cal->y[2]) + abs(cal->y[1] - cal->y[3]))/2;
Y_scale = (tmp2*100)/380;
margin_of_error[0] = margin_of_error[2] = (X_scale*700/100)*(X_scale*700/100);
margin_of_error[1] = margin_of_error[3] = (Y_scale*380/100)*(Y_scale*380/100);
margin_of_error[4] = margin_of_error[5] = margin_of_error[6] = margin_of_error[7] =
(X_scale*350/100)*(X_scale*350/100) + (Y_scale*190/100)*(Y_scale*190/100);
for(i = 0;i < 8;i++){
printf("Margin of error: %d\n",abs(curr_dat[i]-margin_of_error[i]));
}
for(i = 0;i < 8;i++){
/*check every point is same position?*/
if(curr_dat[i] < 100000) return -1;
/*check eight length is OK*/
if(abs((curr_dat[i] - margin_of_error[i])) > ERR_LIMIT)
return -1;
}
return 0;
}
int main()
{
struct tsdev *ts;
calibration cal;
int cal_fd;
char cal_buffer[256];
char *tsdevice = NULL;
char *calfile = NULL;
unsigned int i, len;
unsigned int err_flag = 0;
signal(SIGSEGV, sig);
signal(SIGINT, sig);
signal(SIGTERM, sig);
if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) {
ts = ts_open(tsdevice,0);
} else {
if (!(ts = ts_open("/dev/input/event0", 0)))
ts = ts_open("/dev/touchscreen/ucb1x00", 0);
}
if (!ts) {
perror("ts_open");
exit(1);
}
if (ts_config(ts)) {
perror("ts_config");
exit(1);
}
if (open_framebuffer()) {
close_framebuffer();
exit(1);
}
for (i = 0; i < NR_COLORS; i++)
setcolor (i, palette [i]);
again_cal:
put_string_center (xres / 2, yres / 4,
"TSLIB calibration utility", 1);
put_string_center (xres / 2, yres / 4 + 20,
"Touch crosshair to calibrate", 2);
printf("xres = %d, yres = %d\n", xres, yres);
// Clear the buffer
clearbuf(ts);
get_sample (ts, &cal, 0, 50, 50, "Top left");
if(err_flag){
put_string_center (xres / 2, yres / 4 + 50,
"Please try again!", 1|XORMODE);
err_flag = 0;
}
clearbuf(ts);
get_sample (ts, &cal, 1, xres - 50, 50, "Top right");
clearbuf(ts);
get_sample (ts, &cal, 2, xres - 50, yres - 50, "Bot right");
clearbuf(ts);
get_sample (ts, &cal, 3, 50, yres - 50, "Bot left");
clearbuf(ts);
get_sample (ts, &cal, 4, xres / 2, yres / 2, "Center");
if(check_point(&cal)) {
if(!err_flag) {
err_flag = 1;
put_string_center (xres / 2, yres / 4 + 50,
"Please try again!", 1|XORMODE);
}
goto again_cal;
}
put_string_center (xres / 2, yres / 4 + 50,
"Calibrate OK !", 1|XORMODE);
if (perform_calibration (&cal)) {
printf ("Calibration constants: ");
for (i = 0; i < 7; i++) printf("%d ", cal.a [i]);
printf("\n");
if ((calfile = getenv("TSLIB_CALIBFILE")) != NULL) {
cal_fd = open (calfile, O_CREAT | O_RDWR,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
} else {
cal_fd = open (TS_POINTERCAL, O_CREAT | O_RDWR,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
}
len = sprintf(cal_buffer,"%d %d %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],
xres, yres);
write (cal_fd, cal_buffer, len);
close (cal_fd);
i = 0;
} else {
printf("Calibration failed.\n");
i = -1;
}
close_framebuffer();
return i;
}