2009-02-19 22:15:02 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008 by Maurus Cuelenaere
|
|
|
|
*
|
|
|
|
* 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "button.h"
|
|
|
|
#include "button-target.h"
|
|
|
|
#include "touchscreen.h"
|
|
|
|
#include "string.h"
|
|
|
|
#include "logf.h"
|
2010-11-10 15:25:15 +00:00
|
|
|
#include "lcd.h"
|
2009-02-19 22:15:02 +00:00
|
|
|
|
2009-09-26 17:33:36 +00:00
|
|
|
/* Size of the 'dead zone' around each 3x3 button */
|
2009-09-27 14:11:16 +00:00
|
|
|
#define BUTTON_MARGIN_X (int)(LCD_WIDTH * 0.03)
|
|
|
|
#define BUTTON_MARGIN_Y (int)(LCD_HEIGHT * 0.03)
|
2009-09-26 17:33:36 +00:00
|
|
|
|
2013-09-02 09:03:56 +00:00
|
|
|
static bool touch_enabled = true;
|
2009-02-19 22:15:02 +00:00
|
|
|
static enum touchscreen_mode current_mode = TOUCHSCREEN_POINT;
|
|
|
|
static const int touchscreen_buttons[3][3] =
|
|
|
|
{
|
|
|
|
{BUTTON_TOPLEFT, BUTTON_TOPMIDDLE, BUTTON_TOPRIGHT},
|
|
|
|
{BUTTON_MIDLEFT, BUTTON_CENTER, BUTTON_MIDRIGHT},
|
|
|
|
{BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT}
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifndef DEFAULT_TOUCHSCREEN_CALIBRATION
|
2009-06-16 17:04:47 +00:00
|
|
|
#define DEFAULT_TOUCHSCREEN_CALIBRATION { .A=1, .B=0, .C=0, \
|
|
|
|
.D=0, .E=1, .F=0, \
|
|
|
|
.divider=1 }
|
2009-02-19 22:15:02 +00:00
|
|
|
#endif
|
|
|
|
|
2009-06-16 17:04:47 +00:00
|
|
|
struct touchscreen_parameter calibration_parameters
|
2009-02-19 22:15:02 +00:00
|
|
|
= DEFAULT_TOUCHSCREEN_CALIBRATION;
|
2009-06-16 17:04:47 +00:00
|
|
|
const struct touchscreen_parameter default_calibration_parameters
|
2009-02-19 22:15:02 +00:00
|
|
|
= DEFAULT_TOUCHSCREEN_CALIBRATION;
|
|
|
|
|
|
|
|
void touchscreen_disable_mapping(void)
|
|
|
|
{
|
2009-06-16 17:04:47 +00:00
|
|
|
#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
|
2009-02-19 22:15:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void touchscreen_reset_mapping(void)
|
|
|
|
{
|
2009-06-16 17:04:47 +00:00
|
|
|
memcpy(&calibration_parameters, &default_calibration_parameters,
|
2009-02-19 22:15:02 +00:00
|
|
|
sizeof(struct touchscreen_parameter));
|
|
|
|
}
|
|
|
|
|
|
|
|
int touchscreen_calibrate(struct touchscreen_calibration *cal)
|
|
|
|
{
|
2009-06-16 17:04:47 +00:00
|
|
|
#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));
|
2009-02-19 22:15:02 +00:00
|
|
|
|
2009-06-16 17:04:47 +00:00
|
|
|
if(divider == 0)
|
2009-02-19 22:15:02 +00:00
|
|
|
return -1;
|
2009-06-16 17:04:47 +00:00
|
|
|
else
|
|
|
|
C(divider) = divider;
|
2009-02-19 22:15:02 +00:00
|
|
|
|
2009-06-16 17:04:47 +00:00
|
|
|
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));
|
2009-02-19 22:15:02 +00:00
|
|
|
|
2009-06-16 17:04:47 +00:00
|
|
|
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));
|
2009-02-19 22:15:02 +00:00
|
|
|
|
2009-06-16 17:04:47 +00:00
|
|
|
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));
|
2009-02-19 22:15:02 +00:00
|
|
|
|
2009-06-16 17:04:47 +00:00
|
|
|
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));
|
2009-02-19 22:15:02 +00:00
|
|
|
|
2009-06-16 17:04:47 +00:00
|
|
|
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));
|
2009-02-19 22:15:02 +00:00
|
|
|
|
|
|
|
return 0;
|
2009-06-16 17:04:47 +00:00
|
|
|
#undef C
|
|
|
|
#undef S
|
|
|
|
#undef D
|
2009-02-19 22:15:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void map_pixels(int *x, int *y)
|
|
|
|
{
|
2009-06-16 17:04:47 +00:00
|
|
|
#define C(x) calibration_parameters.x
|
2009-02-19 22:15:02 +00:00
|
|
|
int _x = *x, _y = *y;
|
2009-06-16 17:04:47 +00:00
|
|
|
|
|
|
|
*x = (C(A) * _x + C(B) * _y + C(C)) / C(divider);
|
|
|
|
*y = (C(D) * _x + C(E) * _y + C(F)) / C(divider);
|
|
|
|
#undef C
|
2009-02-19 22:15:02 +00:00
|
|
|
}
|
|
|
|
|
2009-06-16 17:04:47 +00:00
|
|
|
/* TODO: add jitter (and others) filter */
|
2009-02-19 22:15:02 +00:00
|
|
|
int touchscreen_to_pixels(int x, int y, int *data)
|
|
|
|
{
|
2013-09-02 09:03:56 +00:00
|
|
|
if(!touch_enabled)
|
|
|
|
return 0;
|
2009-02-19 22:15:02 +00:00
|
|
|
x &= 0xFFFF;
|
|
|
|
y &= 0xFFFF;
|
2009-06-16 17:04:47 +00:00
|
|
|
|
2009-02-19 22:15:02 +00:00
|
|
|
map_pixels(&x, &y);
|
2009-06-16 17:04:47 +00:00
|
|
|
|
2009-09-26 17:33:36 +00:00
|
|
|
if (current_mode == TOUCHSCREEN_BUTTON)
|
|
|
|
{
|
|
|
|
int column = 0, row = 0;
|
|
|
|
|
|
|
|
if (x < LCD_WIDTH/3 - BUTTON_MARGIN_X)
|
|
|
|
column = 0;
|
|
|
|
else if (x > LCD_WIDTH/3 + BUTTON_MARGIN_X &&
|
|
|
|
x < 2*LCD_WIDTH/3 - BUTTON_MARGIN_X)
|
|
|
|
column = 1;
|
|
|
|
else if (x > 2*LCD_WIDTH/3 + BUTTON_MARGIN_X)
|
|
|
|
column = 2;
|
|
|
|
else
|
|
|
|
return BUTTON_NONE;
|
|
|
|
|
|
|
|
if (y < LCD_HEIGHT/3 - BUTTON_MARGIN_Y)
|
|
|
|
row = 0;
|
|
|
|
else if (y > LCD_HEIGHT/3 + BUTTON_MARGIN_Y &&
|
|
|
|
y < 2*LCD_HEIGHT/3 - BUTTON_MARGIN_Y)
|
|
|
|
row = 1;
|
|
|
|
else if (y > 2*LCD_HEIGHT/3 + BUTTON_MARGIN_Y)
|
|
|
|
row = 2;
|
|
|
|
else
|
|
|
|
return BUTTON_NONE;
|
|
|
|
|
|
|
|
return touchscreen_buttons[row][column];
|
|
|
|
}
|
2009-02-19 22:15:02 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
*data = (x << 16 | y);
|
|
|
|
return BUTTON_TOUCHSCREEN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void touchscreen_set_mode(enum touchscreen_mode mode)
|
|
|
|
{
|
|
|
|
current_mode = mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum touchscreen_mode touchscreen_get_mode(void)
|
|
|
|
{
|
|
|
|
return current_mode;
|
|
|
|
}
|
2010-11-10 15:25:15 +00:00
|
|
|
|
2013-09-05 18:35:51 +00:00
|
|
|
#ifndef HAS_BUTTON_HOLD
|
2013-09-02 09:03:56 +00:00
|
|
|
void touchscreen_enable(bool en)
|
|
|
|
{
|
|
|
|
if(en != touch_enabled)
|
|
|
|
{
|
|
|
|
touch_enabled = en;
|
|
|
|
touchscreen_enable_device(en);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool touchscreen_is_enabled(void)
|
|
|
|
{
|
|
|
|
return touch_enabled;
|
|
|
|
}
|
2013-09-05 18:35:51 +00:00
|
|
|
#endif
|
2010-11-10 15:25:15 +00:00
|
|
|
|
|
|
|
#if ((CONFIG_PLATFORM & PLATFORM_ANDROID) == 0)
|
|
|
|
/* android has an API for this */
|
|
|
|
|
|
|
|
#define TOUCH_SLOP 16u
|
|
|
|
#define REFERENCE_DPI 160
|
|
|
|
|
|
|
|
int touchscreen_get_scroll_threshold(void)
|
|
|
|
{
|
|
|
|
#ifdef LCD_DPI
|
|
|
|
const int dpi = LCD_DPI;
|
|
|
|
#else
|
|
|
|
const int dpi = lcd_get_dpi();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Inspired by Android calculation
|
|
|
|
*
|
|
|
|
* float density = real dpi / reference dpi (=160)
|
|
|
|
* int threshold = (int) (density * TOUCH_SLOP + 0.5f);(original calculation)
|
|
|
|
*
|
|
|
|
* + 0.5f is for rounding, we use fixed point math to achieve that
|
|
|
|
*/
|
|
|
|
|
|
|
|
int result = dpi * (TOUCH_SLOP<<1) / REFERENCE_DPI;
|
|
|
|
result += result & 1; /* round up if needed */
|
|
|
|
return result>>1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|