diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 09cbdbfc09..da09e3c49a 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -12405,7 +12405,7 @@
id: LANG_TOUCHSCREEN_MODE
- desc: in Settings -> General -> System menu
+ desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
id: LANG_TOUCHSCREEN_GRID
- desc: in Settings -> General -> System menu
+ desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
id: LANG_TOUCHSCREEN_POINT
- desc: in Settings -> General -> System menu
+ desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
+
+ id: LANG_TOUCHSCREEN_SETTINGS
+ desc: in Settings -> General -> Display menu
+ user: core
+
+
+ *: none
+ touchscreen: "Touchscreen Settings"
+
+
+ *: none
+ touchscreen: "Touchscreen Settings"
+
+
+
+ id: LANG_TOUCHSCREEN_CALIBRATE
+ desc: in Settings -> General -> Display -> Touchscreen Settings
+ user: core
+
+
+ *: none
+ touchscreen: "Calibrate"
+
+
+ *: none
+ touchscreen: "Calibrate"
+
+
+
+ id: LANG_TOUCHSCREEN_RESET_CALIBRATION
+ desc: in Settings -> General -> Display -> Touchscreen Settings
+ user: core
+
+
+ *: none
+ touchscreen: "Reset Calibration"
+
+
+ *: none
+ touchscreen: "Reset Calibration"
+
+
diff --git a/apps/lang/nederlands.lang b/apps/lang/nederlands.lang
index 2d476d1d14..e73839926f 100644
--- a/apps/lang/nederlands.lang
+++ b/apps/lang/nederlands.lang
@@ -12335,7 +12335,7 @@
id: LANG_TOUCHSCREEN_MODE
- desc: in Settings -> General -> System menu
+ desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
id: LANG_TOUCHSCREEN_GRID
- desc: in Settings -> General -> System menu
+ desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
id: LANG_TOUCHSCREEN_POINT
- desc: in Settings -> General -> System menu
+ desc: in Settings -> General -> Display -> Touchscreen Settings
user: core
+
+ id: LANG_TOUCHSCREEN_SETTINGS
+ desc: in Settings -> General -> Display menu
+ user: core
+
+
+ *: none
+ touchscreen: "Touchscreen instellingen"
+
+
+ *: none
+ touchscreen: "Touchscreen instellingen"
+
+
+
+ id: LANG_TOUCHSCREEN_CALIBRATE
+ desc: in Settings -> General -> Display -> Touchscreen Settings
+ user: core
+
+
+ *: none
+ touchscreen: "Kalibreer"
+
+
+ *: none
+ touchscreen: "Kalibreer"
+
+
+
+ id: LANG_TOUCHSCREEN_RESET_CALIBRATION
+ desc: in Settings -> General -> Display -> Touchscreen Settings
+ user: core
+
+
+ *: none
+ touchscreen: "Kalibratie terugzetten"
+
+
+ *: none
+ touchscreen: "Kalibratie terugzetten"
+
+
diff --git a/apps/menus/display_menu.c b/apps/menus/display_menu.c
index a015be3a23..aee9c1828d 100644
--- a/apps/menus/display_menu.c
+++ b/apps/menus/display_menu.c
@@ -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
);
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index 56a0178000..fdc775877a 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -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
);
diff --git a/apps/screens.c b/apps/screens.c
index 096b81411e..829aa191e1 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -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
diff --git a/apps/screens.h b/apps/screens.h
index eb613fc178..38fef14d60 100644
--- a/apps/screens.h
+++ b/apps/screens.h
@@ -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
diff --git a/apps/settings.c b/apps/settings.c
index 9594bd164e..3219dbbf12 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -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 */
diff --git a/apps/settings.h b/apps/settings.h
index 6ccaeed92e..ef5a62013d 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -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
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 74e2cab3cd..dcad718ee5 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -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<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),
};
diff --git a/firmware/drivers/touchscreen.c b/firmware/drivers/touchscreen.c
index f7b1b09b92..002acf1236 100755
--- a/firmware/drivers/touchscreen.c
+++ b/firmware/drivers/touchscreen.c
@@ -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) ];
diff --git a/firmware/export/touchscreen.h b/firmware/export/touchscreen.h
index 0d8233a522..7d1eb4ac8a 100755
--- a/firmware/export/touchscreen.h
+++ b/firmware/export/touchscreen.h
@@ -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);