This repository has been archived on 2025-06-06. You can view files and clone it, but cannot push or open issues or pull requests.
Files
android-g900/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_ts/calibrate.c
2011-04-04 23:17:39 +06:00

460 lines
13 KiB
C
Executable File

/* calibrate.c
*
*/
#include <linux/module.h>
#include "tssc.h"
//#include <mach/board.h>
#define CALIBRATION_SCREEN_WIDTH 2048
#define CALIBRATION_SCREEN_HEIGHT 2048
#define CALIBRATION_POINTS 5
#define CALIBRATION_COORDINATES (CALIBRATION_POINTS * 2)
#define CALIBRATION_SAMPLE_SIZE 20
#define CALIBRATION_X_GAP 5
#define CALIBRATION_Y_GAP 5
// 5 points coordinates:
// Point 1 - (15, 20)
// Point 2 - (223, 20)
// Point 3 - (119, 159)
// Point 4 - (15, 298)
// Point 5 - (223, 298)
#define TP_CALIBRATION_POINT1_X 128
#define TP_CALIBRATION_POINT1_Y 128
#define TP_CALIBRATION_POINT2_X 1903
#define TP_CALIBRATION_POINT2_Y 128
#define TP_CALIBRATION_POINT3_X 128
#define TP_CALIBRATION_POINT3_Y 1907
#define TP_CALIBRATION_POINT4_X 1903
#define TP_CALIBRATION_POINT4_Y 1907
#define TP_CALIBRATION_POINT5_X 1024
#define TP_CALIBRATION_POINT5_Y 1024
#define CALIBRATION_X_RANGE 1560
#define CALIBRATION_Y_RANGE 1640
#define CALIBRATION_ERROR 30//15//10
// Flag to decide wheather current TP need to do adjustment or not.
// 0: No, not necessary to do adjustment.
// 1: Yes, should use calibration algorithm to do adjustment.
static int adjustment_flag = 0;
static int calibration_flag = 0;
static int calibration_count = 0;
static int calibration_index = 0;
// calibration_direction: Raw data vs. screen coordinate direction.
// 0: No swaped. X, Y same direction.
// 1: No swaped. X, same direction, Y reversed.
// 2: No swaped. X, reversed, Y same direction.
// 3: No swaped. X reversed, Y reversed.
// 4: X, Y swaped. X, Y same direction.
// 5: X, Y swaped. X, same direction, Y reversed.
// 6: X, Y swaped. X, reversed, Y same direction.
// 7: X, Y swaped. X, same direction, Y reversed.
static int calibration_x_direction = 0;
static int calibration_y_direction = 0;
static int calibration_swapped = 0;
static int calibration_x_min = TP_X_MIN;
static int calibration_x_max = TP_X_MAX;
static int calibration_y_min = TP_Y_MIN;
static int calibration_y_max = TP_Y_MAX;
static int saved_x_min = TP_X_MIN;
static int saved_x_max = TP_X_MAX;
static int saved_y_min = TP_Y_MIN;
static int saved_y_max = TP_Y_MAX;
static int calibration_x[CALIBRATION_POINTS];
static int calibration_y[CALIBRATION_POINTS];
static int saved_x[CALIBRATION_POINTS];
static int saved_y[CALIBRATION_POINTS];
static int screen_x[CALIBRATION_POINTS];
static int screen_y[CALIBRATION_POINTS];
/*
* Get the touch input raw data and store into the coordinates buffer.
*/
void calibration_get_points(int x, int y)
{
int dx;
int dy;
if (calibration_index >= CALIBRATION_POINTS)
return;
dx = abs(calibration_x[calibration_index] - x);
dy = abs(calibration_y[calibration_index] - y);
if ((dx < CALIBRATION_X_GAP) && (dy < CALIBRATION_Y_GAP))
calibration_count++;
calibration_x[calibration_index] = x;
calibration_y[calibration_index] = y;
}
/*
* Translate the touch input raw data to the calibrated data.
*/
void calibration_translate(int x, int y, int *rx, int *ry)
{
int cx, cy;
if (calibration_flag > 0 && calibration_flag <= CALIBRATION_POINTS) { /* Under calibration */
calibration_get_points(x, y);
*rx = x;
*ry = y;
} else { /* Normal touch input */
if (adjustment_flag) { /* After calibration */
int kx = 0;
int ky = 0;
if (calibration_swapped) { /* X, Y swapped */
// Ratio translation.
if ((calibration_x_max > calibration_x_min) && (calibration_y_max > calibration_y_min)) {
kx = TP_X_MIN + ((x - calibration_y_min) * (TP_X_MAX - TP_X_MIN) / (calibration_y_max - calibration_y_min));
ky = TP_Y_MIN + ((y - calibration_x_min) * (TP_Y_MAX - TP_Y_MIN) / (calibration_x_max - calibration_x_min));
}
// X, Y direction
cx = (calibration_x_direction) ? (ky) : (TP_X_MAX - ky);
cy = (calibration_y_direction) ? (kx) : (TP_Y_MAX - kx);
} else {
// Ratio translation.
if ((calibration_x_max > calibration_x_min) && (calibration_y_max > calibration_y_min)) {
kx = TP_X_MIN + ((x - calibration_x_min) * (TP_X_MAX - TP_X_MIN) / (calibration_x_max - calibration_x_min));
ky = TP_Y_MIN + ((y - calibration_y_min) * (TP_Y_MAX - TP_Y_MIN) / (calibration_y_max - calibration_y_min));
}
// X, Y direction
cx = (calibration_x_direction) ? (kx) : (TP_X_MAX - kx);
cy = (calibration_y_direction) ? (ky) : (TP_Y_MAX - ky);
}
if (cx < TP_X_MIN)
cx = TP_X_MIN;
else if (cx > TP_X_MAX)
cx = TP_X_MAX;
if (cy < TP_Y_MIN)
cy = TP_Y_MIN;
else if (cy > TP_Y_MAX)
cy = TP_Y_MAX;
*rx = cx;
*ry = cy;
} else { /* No need to do calibration */
*rx = y; /* Current device, x and y swapped */
*ry = x;
}
}
}
/*
* Show the calibration parameters.
*/
void calibration_show_parameters(int status)
{
int i;
for (i = 0; i < CALIBRATION_POINTS; i++)
printk(KERN_INFO "touch_calibration: Point %d %d, %d.\n",
i+1, calibration_x[i], calibration_y[i]);
printk(KERN_INFO "touch_calibration: do calibration %s.\n",
status ? "error" : "ok");
printk(KERN_INFO "touch_calibration: x max %d, x min %d.\n",
calibration_x_min, calibration_x_max);
printk(KERN_INFO "touch_calibration: y max %d, y min %d.\n",
calibration_y_min, calibration_y_max);
printk(KERN_INFO "touch_calibration: %s x %s, y %s.\n",
calibration_swapped ? "X Y swapped," : "",
calibration_x_direction ? "reversed" : "same direction",
calibration_y_direction ? "reversed" : "same direction");
}
/*
* Calculate calibration variables.
*/
void calibration_calculate_varialbes(void)
{
int xdir, xlen, ydir, ylen;
int x_length, y_length;
int x1, x2, y1, y2;
int i;
int result = 0;
saved_x_min = calibration_x_min;
saved_x_max = calibration_x_max;
saved_y_min = calibration_y_min;
saved_y_max = calibration_y_max;
if (calibration_index < CALIBRATION_POINTS - 1) {
result = 1; /* Calibration points not enough */
} else {
if (calibration_x[0] > calibration_x[1]) {
xdir = 0; /* Reversed */
xlen = calibration_x[0] - calibration_x[1];
} else {
xdir = 1; /* Same */
xlen = calibration_x[1] - calibration_x[0];
}
if (calibration_y[0] > calibration_y[1]) {
ydir = 0; /* Reversed */
ylen = calibration_y[0] - calibration_y[1];
} else {
ydir = 1; /* Same */
ylen = calibration_y[1] - calibration_y[0];
}
if (xlen > ylen) {
calibration_swapped = 0; /* No swapped */
calibration_x_direction = xdir;
x_length = xlen;
if (calibration_y[0] > calibration_y[3]) {
calibration_y_direction = 0; /* Reversed */
y_length = calibration_y[0] - calibration_y[3];
} else {
calibration_y_direction = 1; /* Same */
y_length = calibration_y[3] - calibration_y[0];
}
x1 = (calibration_x_direction) ? (calibration_x[0]) : (calibration_x[1]);
x2 = (calibration_x_direction) ? (calibration_x[1]) : (calibration_x[0]);
y1 = (calibration_y_direction) ? (calibration_y[0]) : (calibration_y[3]);
y2 = (calibration_y_direction) ? (calibration_y[3]) : (calibration_y[0]);
} else {
calibration_swapped = 1; /* X, Y swapped */
calibration_x_direction = ydir;
x_length = ylen;
if (calibration_x[0] > calibration_x[3]) {
calibration_y_direction = 0; /* Reversed */
y_length = calibration_x[0] - calibration_x[3];
} else {
calibration_y_direction = 1; /* Same */
y_length = calibration_x[3] - calibration_x[0];
}
x1 = (calibration_x_direction) ? (calibration_y[0]) : (calibration_y[1]);
x2 = (calibration_x_direction) ? (calibration_y[1]) : (calibration_y[0]);
y1 = (calibration_y_direction) ? (calibration_x[0]) : (calibration_x[3]);
y2 = (calibration_y_direction) ? (calibration_x[3]) : (calibration_x[0]);
}
xlen = (screen_x[1] - screen_x[0]);
if (xlen) {
calibration_x_min = x1 - ((x_length) * (screen_x[0]) / xlen);
calibration_x_max = x2 + ((x_length) * (CALIBRATION_SCREEN_WIDTH-screen_x[1]) / xlen);
} else {
result = 1;
}
ylen = (screen_y[2] - screen_y[0]);
if (ylen) {
calibration_y_min = y1 - ((y_length) * (screen_y[0]) / ylen);
calibration_y_max = y2 + ((y_length) * (CALIBRATION_SCREEN_HEIGHT-screen_y[2]) / ylen);
} else {
result = 1;
}
}
if(0)
{
printk("mfg_mode=factory2\n");
#if 0
printk("calibration_x_max-calibration_x_min=%d calibration_y_max-calibration_y_min=%d\n"
, calibration_x_max-calibration_x_min, calibration_y_max-calibration_y_min);
printk("abs(CALIBRATION_X_RANGE-(calibration_x_max-calibration_x_min))=%d\n", abs(CALIBRATION_X_RANGE-(calibration_x_max-calibration_x_min)));
printk("abs(CALIBRATION_Y_RANGE-(calibration_y_max-calibration_y_min))=%d\n", abs(CALIBRATION_Y_RANGE-(calibration_y_max-calibration_y_min)));
if(abs(CALIBRATION_X_RANGE-(calibration_x_max-calibration_x_min))>CALIBRATION_ERROR
|| abs(CALIBRATION_Y_RANGE-(calibration_y_max-calibration_y_min))>CALIBRATION_ERROR
) result=1;
#endif
}
// if (calibration_x_min > 250 || calibration_x_max < 700 || calibration_y_min > 250 || calibration_y_max < 700)
// result = 1; /* Not in the acceptable area */
calibration_show_parameters(result);
if (result == 1) {
for (i=0; i<CALIBRATION_POINTS; i++) {
calibration_x[i] = saved_x[i];
calibration_y[i] = saved_y[i];
}
calibration_x_min = saved_x_min;
calibration_x_max = saved_x_max;
calibration_y_min = saved_y_min;
calibration_y_max = saved_y_max;
calibration_flag = 9; /* Calibration error */
} else {
for (i=0; i<CALIBRATION_POINTS; i++) {
saved_x[i] = calibration_x[i];
saved_y[i] = calibration_y[i];
}
calibration_flag = 8; /* Calibration ok */
}
adjustment_flag = 1; /* Calibration finished */
}
/*
* Set the coordinates of calibration points from input data buffer.
*/
void calibration_set(int *inPtr)
{
int i;
int j = 0;
for (i = 0; i < CALIBRATION_POINTS; i++) {
calibration_x[i] = inPtr[j++];
calibration_y[i] = inPtr[j++];
}
}
/*
* Initialize calibration parameters at boot time.
*/
void calibration_init(void)
{
screen_x[0] = TP_CALIBRATION_POINT1_X;
screen_x[1] = TP_CALIBRATION_POINT2_X;
screen_x[2] = TP_CALIBRATION_POINT3_X;
screen_x[3] = TP_CALIBRATION_POINT4_X;
screen_x[4] = TP_CALIBRATION_POINT5_X;
screen_y[0] = TP_CALIBRATION_POINT1_Y;
screen_y[1] = TP_CALIBRATION_POINT2_Y;
screen_y[2] = TP_CALIBRATION_POINT3_Y;
screen_y[3] = TP_CALIBRATION_POINT4_Y;
screen_y[4] = TP_CALIBRATION_POINT5_Y;
}
/*
* Display the flag of the calibration algorithm.
* 0: exit calibration mode.
* 1: enter calibration mode.
* 2: calibration error.
* 3: calibration ok.
*/
ssize_t calibration_show(char *buf)
{
return sprintf(buf, "%d\n", calibration_flag);
}
/*
* Store the flag of the calibration algorithm.
*/
void calibration_store(const char *buf)
{
char *ptr_data = (char *)buf;
unsigned long val = simple_strtoul(ptr_data, NULL, 10);
if (val == 0) { /* exit calibration mode */
calibration_flag = 0;
calibration_count = 0;
calibration_calculate_varialbes();
calibration_index = 0;
printk(KERN_DEBUG "touch_calibration: exit.\n");
} else { /* calibration mode */
calibration_flag = val;
calibration_index = val - 1;
calibration_count = 0;
if (val <= CALIBRATION_POINTS)
printk(KERN_DEBUG "touch_calibration: point %d.\n",
calibration_index + 1);
else
printk(KERN_ERR "touch_calibration: point error.\n");
}
}
/*
* Display the coordinates of the calibration touch panel input points.
*/
ssize_t calibration_points_show(char *buf)
{
return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
saved_x[0], saved_y[0], saved_x[1], saved_y[1],
saved_x[2], saved_y[2], saved_x[3], saved_y[3],
saved_x[4], saved_y[4]);
}
/*
* Store the coordinates of the calibration touch panel input points.
*/
void calibration_points_store(const char *buf)
{
char *ptr_data = (char *)buf;
char *p;
int cnt = 0;
int tmp[CALIBRATION_COORDINATES];
unsigned long val;
while ((p = strsep(&ptr_data, ","))) {
if (!*p)
break;
if (cnt >= CALIBRATION_COORDINATES)
break;
val = simple_strtoul(p, NULL, 10);
tmp[cnt++] = val;
}
calibration_set(&tmp[0]);
calibration_index = CALIBRATION_POINTS;
calibration_calculate_varialbes();
calibration_index = 0;
}
/*
* Display the coordinates of the calibration screen points.
*/
ssize_t calibration_screen_show(char *buf)
{
return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
screen_x[0], screen_y[0],
screen_x[1], screen_y[1], screen_x[2], screen_y[2],
screen_x[3], screen_y[3], screen_x[4], screen_y[4]);
}
/*
* Store the coordinates of the calibration screen points.
*/
void calibration_screen_store(const char *buf)
{
char *ptr_data = (char *)buf;
char *p;
int cnt = 0;
int tmp[CALIBRATION_COORDINATES];
unsigned long val;
while ((p = strsep(&ptr_data, ","))) {
if (!*p)
break;
if (cnt >= CALIBRATION_COORDINATES)
break;
val = simple_strtoul(p, NULL, 10);
tmp[cnt++] = val;
}
if (cnt >= CALIBRATION_COORDINATES) {
int i;
int j = 0;
for (i = 0; i < CALIBRATION_POINTS; i++) {
screen_x[i] = tmp[j++];
screen_y[i] = tmp[j++];
}
}
}