Touchscreen targets: add calibration screen + rewrite calibration driver (FS#10295)

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21312 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Maurus Cuelenaere 2009-06-16 17:04:47 +00:00
parent b1a60934c5
commit b8435f5446
11 changed files with 335 additions and 103 deletions

View file

@ -12405,7 +12405,7 @@
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_MODE
desc: in Settings -> General -> System menu
desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
<source>
*: none
@ -12422,7 +12422,7 @@
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_GRID
desc: in Settings -> General -> System menu
desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
<source>
*: none
@ -12439,7 +12439,7 @@
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_POINT
desc: in Settings -> General -> System menu
desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
<source>
*: none
@ -12502,3 +12502,54 @@
swcodec: "Speed"
</voice>
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_SETTINGS
desc: in Settings -> General -> Display menu
user: core
<source>
*: none
touchscreen: "Touchscreen Settings"
</source>
<dest>
*: none
touchscreen: "Touchscreen Settings"
</dest>
<voice>
*: none
touchscreen: "Touchscreen Settings"
</voice>
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_CALIBRATE
desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
<source>
*: none
touchscreen: "Calibrate"
</source>
<dest>
*: none
touchscreen: "Calibrate"
</dest>
<voice>
*: none
touchscreen: "Calibrate"
</voice>
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_RESET_CALIBRATION
desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
<source>
*: none
touchscreen: "Reset Calibration"
</source>
<dest>
*: none
touchscreen: "Reset Calibration"
</dest>
<voice>
*: none
touchscreen: "Reset Calibration"
</voice>
</phrase>

View file

@ -12335,7 +12335,7 @@
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_MODE
desc: in Settings -> General -> System menu
desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
<source>
*: none
@ -12352,7 +12352,7 @@
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_GRID
desc: in Settings -> General -> System menu
desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
<source>
*: none
@ -12369,7 +12369,7 @@
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_POINT
desc: in Settings -> General -> System menu
desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
<source>
*: none
@ -12432,3 +12432,54 @@
swcodec: "Snelheid"
</voice>
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_SETTINGS
desc: in Settings -> General -> Display menu
user: core
<source>
*: none
touchscreen: "Touchscreen Settings"
</source>
<dest>
*: none
touchscreen: "Touchscreen instellingen"
</dest>
<voice>
*: none
touchscreen: "Touchscreen instellingen"
</voice>
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_CALIBRATE
desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
<source>
*: none
touchscreen: "Calibrate"
</source>
<dest>
*: none
touchscreen: "Kalibreer"
</dest>
<voice>
*: none
touchscreen: "Kalibreer"
</voice>
</phrase>
<phrase>
id: LANG_TOUCHSCREEN_RESET_CALIBRATION
desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
<source>
*: none
touchscreen: "Reset Calibration"
</source>
<dest>
*: none
touchscreen: "Kalibratie terugzetten"
</dest>
<voice>
*: none
touchscreen: "Kalibratie terugzetten"
</voice>
</phrase>

View file

@ -36,6 +36,9 @@
#include "talk.h"
#include "lcd.h"
#include "lcd-remote.h"
#ifdef HAVE_TOUCHSCREEN
#include "screens.h"
#endif
#ifdef HAVE_BACKLIGHT
static int filterfirstkeypress_callback(int action,const struct menu_item_ex *this_item)
@ -496,6 +499,29 @@ MAKE_MENU(peak_meter_menu, ID2P(LANG_PM_MENU), NULL, Icon_NOICON,
/***********************************/
#ifdef HAVE_TOUCHSCREEN
static int touch_mode_callback(int action,const struct menu_item_ex *this_item)
{
(void)this_item;
switch (action)
{
case ACTION_EXIT_MENUITEM: /* on exit */
touchscreen_set_mode(global_settings.touch_mode);
break;
}
return action;
}
MENUITEM_SETTING(touch_mode, &global_settings.touch_mode, touch_mode_callback);
MENUITEM_FUNCTION(touchscreen_menu_calibrate, 0, ID2P(LANG_TOUCHSCREEN_CALIBRATE), calibrate,
NULL, NULL, Icon_NOICON);
MENUITEM_FUNCTION(touchscreen_menu_reset_calibration, 0, ID2P(LANG_TOUCHSCREEN_RESET_CALIBRATION), reset_mapping,
NULL, NULL, Icon_NOICON);
MAKE_MENU(touchscreen_menu, ID2P(LANG_TOUCHSCREEN_SETTINGS), NULL, Icon_NOICON, &touch_mode,
&touchscreen_menu_calibrate, &touchscreen_menu_reset_calibration);
#endif
MENUITEM_SETTING(codepage_setting, &global_settings.default_codepage, NULL);
@ -511,4 +537,7 @@ MAKE_MENU(display_menu, ID2P(LANG_DISPLAY),
&bars_menu, &peak_meter_menu,
#endif
&codepage_setting,
#ifdef HAVE_TOUCHSCREEN
&touchscreen_menu,
#endif
);

View file

@ -265,21 +265,6 @@ MENUITEM_SETTING(buttonlight_brightness, &global_settings.buttonlight_brightness
MENUITEM_SETTING(touchpad_sensitivity, &global_settings.touchpad_sensitivity, NULL);
#endif
#ifdef HAVE_TOUCHSCREEN
static int touch_mode_callback(int action,const struct menu_item_ex *this_item)
{
(void)this_item;
switch (action)
{
case ACTION_EXIT_MENUITEM: /* on exit */
touchscreen_set_mode(global_settings.touch_mode);
break;
}
return action;
}
MENUITEM_SETTING(touch_mode, &global_settings.touch_mode, touch_mode_callback);
#endif
MAKE_MENU(system_menu, ID2P(LANG_SYSTEM),
0, Icon_System_menu,
&start_screen,
@ -314,9 +299,6 @@ MAKE_MENU(system_menu, ID2P(LANG_SYSTEM),
#endif
#ifdef HAVE_TOUCHPAD_SENSITIVITY_SETTING
&touchpad_sensitivity,
#endif
#ifdef HAVE_TOUCHSCREEN
&touch_mode,
#endif
);

View file

@ -1019,3 +1019,85 @@ bool view_runtime(void)
}
return false;
}
#ifdef HAVE_TOUCHSCREEN
static int get_sample(struct touchscreen_calibration *cal, int x, int y, int i,
struct screen* screen)
{
int action;
short ts_x, ts_y;
/* Draw a cross */
screen->drawline(x - 10, y, x - 2, y);
screen->drawline(x + 2, y, x + 10, y);
screen->drawline(x, y - 10, x, y - 2);
screen->drawline(x, y + 2, x, y + 10);
screen->update();
/* Wait for a touchscreen press */
while(true)
{
action = get_action(CONTEXT_STD, TIMEOUT_BLOCK);
if(action == ACTION_TOUCHSCREEN)
{
if(action_get_touchscreen_press(&ts_x, &ts_y) == BUTTON_REL)
break;
}
else if(action == ACTION_STD_CANCEL)
return -1;
}
cal->x[i][0] = ts_x;
cal->y[i][0] = ts_y;
cal->x[i][1] = x;
cal->y[i][1] = y;
return 0;
}
int calibrate(void)
{
short points[3][2] = {
{LCD_WIDTH/10, LCD_HEIGHT/10},
{7*LCD_WIDTH/8, LCD_HEIGHT/2},
{LCD_WIDTH/2, 7*LCD_HEIGHT/8}
};
struct screen* screen = &screens[SCREEN_MAIN];
enum touchscreen_mode old_mode = touchscreen_get_mode();
struct touchscreen_calibration cal;
int i, ret = 0;
bool statusbar = global_settings.statusbar; /* hide the statusbar */
global_settings.statusbar = false;
touchscreen_disable_mapping(); /* set raw mode */
touchscreen_set_mode(TOUCHSCREEN_POINT);
for(i=0; i<3; i++)
{
screen->clear_display();
if(get_sample(&cal, points[i][0], points[i][1], i, screen))
{
ret = -1;
break;
}
}
if(ret == 0)
touchscreen_calibrate(&cal);
else
touchscreen_reset_mapping();
memcpy(&global_settings.ts_calibration_data, &calibration_parameters, sizeof(struct touchscreen_parameter));
touchscreen_set_mode(old_mode);
global_settings.statusbar = statusbar;
return ret;
}
int reset_mapping(void)
{
touchscreen_reset_mapping();
memcpy(&global_settings.ts_calibration_data, &calibration_parameters, sizeof(struct touchscreen_parameter));
return 0;
}
#endif

View file

@ -50,5 +50,10 @@ bool shutdown_screen(void);
bool browse_id3(void);
bool view_runtime(void);
#ifdef HAVE_TOUCHSCREEN
int calibrate(void);
int reset_mapping(void);
#endif
#endif

View file

@ -966,6 +966,7 @@ void settings_apply(bool read_disk)
#ifdef HAVE_TOUCHSCREEN
touchscreen_set_mode(global_settings.touch_mode);
memcpy(&calibration_parameters, &global_settings.ts_calibration_data, sizeof(struct touchscreen_parameter));
#endif
/* This should stay last */

View file

@ -730,6 +730,7 @@ struct user_settings
#ifdef HAVE_TOUCHSCREEN
int touch_mode;
struct touchscreen_parameter ts_calibration_data;
#endif
/* If values are just added to the end, no need to bump plugin API

View file

@ -53,6 +53,10 @@
#include "iap.h"
#endif
#include "statusbar.h"
#ifdef HAVE_TOUCHSCREEN
#include "touchscreen.h"
#include "ctype.h" /* For isspace() */
#endif
#define NVRAM(bytes) (bytes<<F_NVRAM_MASK_SHIFT)
/** NOTE: NVRAM_CONFIG_VERSION is in settings_list.h
@ -452,6 +456,48 @@ static void qs_set_default(void* setting, void* defaultval)
find_setting(defaultval, (int*)setting);
}
#endif
#ifdef HAVE_TOUCHSCREEN
static void tsc_load_from_cfg(void* setting, char*value)
{
struct touchscreen_parameter *var = (struct touchscreen_parameter*) setting;
/* Replacement for sscanf(value, "%d ..., &var->A, ...); */
int vals[7], count = 0;
while(*value != 0 && count < 7)
{
if(isspace(*value))
value++;
else
{
vals[count++] = atoi(value);
while(!isspace(*value))
value++;
}
}
var->A = vals[0];
var->B = vals[1];
var->C = vals[2];
var->D = vals[3];
var->E = vals[4];
var->F = vals[5];
var->divider = vals[6];
}
static char* tsc_write_to_cfg(void* setting, char*buf, int buf_len)
{
const struct touchscreen_parameter *var = (const struct touchscreen_parameter*) setting;
snprintf(buf, buf_len, "%d %d %d %d %d %d %d", var->A, var->B, var->C, var->D, var->E, var->F, var->divider);
return buf;
}
static bool tsc_is_changed(void* setting, void* defaultval)
{
return memcmp(setting, defaultval, sizeof(struct touchscreen_parameter)) != 0;
}
static void tsc_set_default(void* setting, void* defaultval)
{
memcpy(setting, defaultval, sizeof(struct touchscreen_parameter));
}
#endif
const struct settings_list settings[] = {
/* sound settings */
SOUND_SETTING(F_NO_WRAP,volume, LANG_VOLUME, "volume", SOUND_VOLUME),
@ -1470,6 +1516,10 @@ const struct settings_list settings[] = {
CHOICE_SETTING(0, touch_mode, LANG_TOUCHSCREEN_MODE, TOUCHSCREEN_BUTTON,
"touchscreen mode", "point,grid", NULL, 2,
ID2P(LANG_TOUCHSCREEN_POINT), ID2P(LANG_TOUCHSCREEN_GRID)),
CUSTOM_SETTING(0, ts_calibration_data, -1,
&default_calibration_parameters, "touchscreen calibration",
tsc_load_from_cfg, tsc_write_to_cfg,
tsc_is_changed, tsc_set_default),
#endif
OFFON_SETTING(0, prevent_skip, LANG_PREVENT_SKIPPING, false, "prevent track skip", NULL),
};

View file

@ -34,119 +34,93 @@ static const int touchscreen_buttons[3][3] =
{BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT}
};
/* Based on ftp://ftp.embedded.com/pub/2002/06vidales/calibrate.c
*
* Copyright (c) 2001, Carlos E. Vidales. All rights reserved.
*
* This sample program was written and put in the public domain
* by Carlos E. Vidales. The program is provided "as is"
* without warranty of any kind, either expressed or implied.
* If you choose to use the program within your own products
* you do so at your own risk, and assume the responsibility
* for servicing, repairing or correcting the program should
* it prove defective in any manner.
* You may copy and distribute the program's source code in any
* medium, provided that you also include in each copy an
* appropriate copyright notice and disclaimer of warranty.
* You may also modify this program and distribute copies of
* it provided that you include prominent notices stating
* that you changed the file(s) and the date of any change,
* and that you do not charge any royalties or licenses for
* its use.
*/
struct touchscreen_parameter
{
long A;
long B;
long C;
long D;
long E;
long F;
long divider;
};
#ifndef DEFAULT_TOUCHSCREEN_CALIBRATION
#define DEFAULT_TOUCHSCREEN_CALIBRATION {.A=1, .B=0, .C=0, \
.D=0, .E=1, .F=0, \
.divider=1}
#define DEFAULT_TOUCHSCREEN_CALIBRATION { .A=1, .B=0, .C=0, \
.D=0, .E=1, .F=0, \
.divider=1 }
#endif
static struct touchscreen_parameter calibration_parameters
struct touchscreen_parameter calibration_parameters
= DEFAULT_TOUCHSCREEN_CALIBRATION;
static const struct touchscreen_parameter default_parameters
const struct touchscreen_parameter default_calibration_parameters
= DEFAULT_TOUCHSCREEN_CALIBRATION;
void touchscreen_disable_mapping(void)
{
calibration_parameters.A = 1;
calibration_parameters.B = 0;
calibration_parameters.C = 0;
calibration_parameters.D = 0;
calibration_parameters.E = 1;
calibration_parameters.F = 0;
calibration_parameters.divider = 1;
#define C(x) calibration_parameters.x
C(A) = C(E) = 1;
C(B) = C(C) = C(D) = C(F) = 0;
C(divider) = 1;
#undef C
}
void touchscreen_reset_mapping(void)
{
memcpy(&calibration_parameters, &default_parameters,
memcpy(&calibration_parameters, &default_calibration_parameters,
sizeof(struct touchscreen_parameter));
}
int touchscreen_calibrate(struct touchscreen_calibration *cal)
{
calibration_parameters.divider = ((cal->x[0] - cal->x[2]) * (cal->y[1] - cal->y[2])) -
((cal->x[1] - cal->x[2]) * (cal->y[0] - cal->y[2])) ;
#define C(x) calibration_parameters.x /* Calibration */
#define S(i,j) cal->i[j][0] /* Screen */
#define D(i,j) cal->i[j][1] /* Display */
long divider = (S(x,0) - S(x,2)) * (S(y,1) - S(y,2)) -
(S(x,1) - S(x,2)) * (S(y,0) - S(y,2));
if(calibration_parameters.divider == 0)
if(divider == 0)
return -1;
calibration_parameters.A = ((cal->xfb[0] - cal->xfb[2]) * (cal->y[1] - cal->y[2])) -
((cal->xfb[1] - cal->xfb[2]) * (cal->y[0] - cal->y[2])) ;
else
C(divider) = divider;
calibration_parameters.B = ((cal->x[0] - cal->x[2]) * (cal->xfb[1] - cal->xfb[2])) -
((cal->xfb[0] - cal->xfb[2]) * (cal->x[1] - cal->x[2])) ;
C(A) = (D(x,0) - D(x,2)) * (S(y,1) - S(y,2)) -
(D(x,1) - D(x,2)) * (S(y,0) - S(y,2));
calibration_parameters.C = (cal->x[2] * cal->xfb[1] - cal->x[1] * cal->xfb[2]) * cal->y[0] +
(cal->x[0] * cal->xfb[2] - cal->x[2] * cal->xfb[0]) * cal->y[1] +
(cal->x[1] * cal->xfb[0] - cal->x[0] * cal->xfb[1]) * cal->y[2] ;
C(B) = (S(x,0) - S(x,2)) * (D(x,1) - D(x,2)) -
(D(x,0) - D(x,2)) * (S(x,1) - S(x,2));
calibration_parameters.D = ((cal->yfb[0] - cal->yfb[2]) * (cal->y[1] - cal->y[2])) -
((cal->yfb[1] - cal->yfb[2]) * (cal->y[0] - cal->y[2])) ;
C(C) = S(y,0) * (S(x,2) * D(x,1) - S(x,1) * D(x,2)) +
S(y,1) * (S(x,0) * D(x,2) - S(x,2) * D(x,0)) +
S(y,2) * (S(x,1) * D(x,0) - S(x,0) * D(x,1));
calibration_parameters.E = ((cal->x[0] - cal->x[2]) * (cal->yfb[1] - cal->yfb[2])) -
((cal->yfb[0] - cal->yfb[2]) * (cal->x[1] - cal->x[2])) ;
C(D) = (D(y,0) - D(y,2)) * (S(y,1) - S(y,2)) -
(D(y,1) - D(y,2)) * (S(y,0) - S(y,2));
calibration_parameters.F = (cal->x[2] * cal->yfb[1] - cal->x[1] * cal->yfb[2]) * cal->y[0] +
(cal->x[0] * cal->yfb[2] - cal->x[2] * cal->yfb[0]) * cal->y[1] +
(cal->x[1] * cal->yfb[0] - cal->x[0] * cal->yfb[1]) * cal->y[2] ;
C(E) = (S(x,0) - S(x,2)) * (D(y,1) - D(y,2)) -
(D(y,0) - D(y,2)) * (S(x,1) - S(x,2));
C(F) = S(y,0) * (S(x,2) * D(y,1) - S(x,1) * D(y,2)) +
S(y,1) * (S(x,0) * D(y,2) - S(x,2) * D(y,0)) +
S(y,2) * (S(x,1) * D(y,0) - S(x,0) * D(y,1));
logf("A: %lX B: %lX C: %lX", C(A), C(B), C(C));
logf("D: %lX E: %lX F: %lX", C(D), C(E), C(F));
logf("divider: %lX", C(divider));
logf("A: %lX B: %lX C: %lX", calibration_parameters.A,
calibration_parameters.B, calibration_parameters.C);
logf("D: %lX E: %lX F: %lX", calibration_parameters.D,
calibration_parameters.E, calibration_parameters.F);
logf("divider: %lX", calibration_parameters.divider);
return 0;
#undef C
#undef S
#undef D
}
static void map_pixels(int *x, int *y)
{
#define C(x) calibration_parameters.x
int _x = *x, _y = *y;
*x = (calibration_parameters.A*_x + calibration_parameters.B*_y +
calibration_parameters.C) / calibration_parameters.divider;
*y = (calibration_parameters.D*_x + calibration_parameters.E*_y +
calibration_parameters.F) / calibration_parameters.divider;
*x = (C(A) * _x + C(B) * _y + C(C)) / C(divider);
*y = (C(D) * _x + C(E) * _y + C(F)) / C(divider);
#undef C
}
/* TODO: add jitter (and others) filter */
int touchscreen_to_pixels(int x, int y, int *data)
{
x &= 0xFFFF;
y &= 0xFFFF;
map_pixels(&x, &y);
if(current_mode == TOUCHSCREEN_BUTTON)
return touchscreen_buttons[y / (LCD_HEIGHT/3)]
[x / (LCD_WIDTH/3) ];

View file

@ -24,10 +24,14 @@
struct touchscreen_calibration
{
int x[3];
int xfb[3];
int y[3];
int yfb[3];
int x[3][2];
int y[3][2];
};
struct touchscreen_parameter
{
int A, B, C, D, E, F;
int divider;
};
enum touchscreen_mode
@ -38,6 +42,8 @@ enum touchscreen_mode
from button_get_data */
};
extern struct touchscreen_parameter calibration_parameters;
extern const struct touchscreen_parameter default_calibration_parameters;
int touchscreen_calibrate(struct touchscreen_calibration *cal);
int touchscreen_to_pixels(int x, int y, int *data);
void touchscreen_set_mode(enum touchscreen_mode mode);