forked from len0rd/rockbox
Add generic touchscreen driver which allows calibration (apps/ layer will follow later).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20055 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
1cb3ff0ab0
commit
44eba07516
5 changed files with 230 additions and 92 deletions
168
firmware/drivers/touchscreen.c
Executable file
168
firmware/drivers/touchscreen.c
Executable file
|
|
@ -0,0 +1,168 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* 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"
|
||||
|
||||
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}
|
||||
};
|
||||
|
||||
/* 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}
|
||||
#endif
|
||||
|
||||
static struct touchscreen_parameter calibration_parameters
|
||||
= DEFAULT_TOUCHSCREEN_CALIBRATION;
|
||||
static const struct touchscreen_parameter default_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;
|
||||
}
|
||||
|
||||
void touchscreen_reset_mapping(void)
|
||||
{
|
||||
memcpy(&calibration_parameters, &default_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])) ;
|
||||
|
||||
if(calibration_parameters.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])) ;
|
||||
|
||||
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])) ;
|
||||
|
||||
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] ;
|
||||
|
||||
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])) ;
|
||||
|
||||
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])) ;
|
||||
|
||||
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] ;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void map_pixels(int *x, int *y)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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) ];
|
||||
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;
|
||||
}
|
||||
48
firmware/export/touchscreen.h
Executable file
48
firmware/export/touchscreen.h
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __TOUCHSCREEN_INCLUDE_H_
|
||||
#define __TOUCHSCREEN_INCLUDE_H_
|
||||
|
||||
struct touchscreen_calibration
|
||||
{
|
||||
int x[3];
|
||||
int xfb[3];
|
||||
int y[3];
|
||||
int yfb[3];
|
||||
};
|
||||
|
||||
enum touchscreen_mode
|
||||
{
|
||||
TOUCHSCREEN_POINT = 0, /* touchscreen returns pixel co-ords */
|
||||
TOUCHSCREEN_BUTTON, /* touchscreen returns BUTTON_* area codes
|
||||
actual pixel value will still be accessible
|
||||
from button_get_data */
|
||||
};
|
||||
|
||||
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);
|
||||
enum touchscreen_mode touchscreen_get_mode(void);
|
||||
void touchscreen_disable_mapping(void);
|
||||
void touchscreen_reset_mapping(void);
|
||||
|
||||
#endif /* __TOUCHSCREEN_INCLUDE_H_ */
|
||||
|
|
@ -25,31 +25,13 @@
|
|||
#include "adc.h"
|
||||
#include "pcf50606.h"
|
||||
#include "backlight.h"
|
||||
#include "touchscreen.h"
|
||||
|
||||
#define TOUCH_MARGIN 8
|
||||
|
||||
static enum touchscreen_mode current_mode = TOUCHSCREEN_POINT;
|
||||
|
||||
static short last_x, last_y;
|
||||
static bool touch_available = false;
|
||||
|
||||
static int touchscreen_buttons[3][3] =
|
||||
{
|
||||
{BUTTON_TOPLEFT, BUTTON_TOPMIDDLE, BUTTON_TOPRIGHT},
|
||||
{BUTTON_MIDLEFT, BUTTON_CENTER, BUTTON_MIDRIGHT},
|
||||
{BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT},
|
||||
};
|
||||
|
||||
void touchscreen_set_mode(enum touchscreen_mode mode)
|
||||
{
|
||||
current_mode = mode;
|
||||
}
|
||||
|
||||
enum touchscreen_mode touchscreen_get_mode(void)
|
||||
{
|
||||
return current_mode;
|
||||
}
|
||||
|
||||
void button_set_touch_available(void)
|
||||
{
|
||||
touch_available = true;
|
||||
|
|
@ -186,20 +168,9 @@ int button_read_device(int *data)
|
|||
last_x = x;
|
||||
last_y = y;
|
||||
*data = touch_to_pixels(x, y);
|
||||
switch (current_mode)
|
||||
{
|
||||
case TOUCHSCREEN_POINT:
|
||||
btn |= BUTTON_TOUCHSCREEN;
|
||||
break;
|
||||
case TOUCHSCREEN_BUTTON:
|
||||
{
|
||||
int px_x = (*data&0xffff0000)>>16;
|
||||
int px_y = (*data&0x0000ffff);
|
||||
btn |= touchscreen_buttons[px_y/(LCD_HEIGHT/3)]
|
||||
[px_x/(LCD_WIDTH/3)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
btn |= touchscreen_to_pixels((*data&0xffff0000)>>16,
|
||||
(*data&0x0000ffff),
|
||||
data);
|
||||
}
|
||||
last_touch = current_tick;
|
||||
touch_available = false;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ void button_set_touch_available(void);
|
|||
|
||||
#define BUTTON_TOUCH 0x00002000
|
||||
|
||||
#define DEFAULT_TOUCHSCREEN_CALIBRATION {.A=0xFFF9FDA2, .B=0xFFFFE82A, \
|
||||
.C=0xA22AA2C, .D=0x23DC, .E=0x8E3E6, \
|
||||
.F=0x76CF88AA, .divider=0xFFAD4013}
|
||||
|
||||
#define BUTTON_MAIN 0x3FFF
|
||||
|
||||
/* No remote */
|
||||
|
|
|
|||
|
|
@ -68,14 +68,6 @@ static volatile bool pen_down = false;
|
|||
static volatile unsigned short bat_val;
|
||||
static struct mutex battery_mtx;
|
||||
|
||||
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}
|
||||
};
|
||||
|
||||
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
|
||||
{
|
||||
/* TODO */
|
||||
|
|
@ -163,30 +155,6 @@ void button_init_device(void)
|
|||
mutex_init(&battery_mtx);
|
||||
}
|
||||
|
||||
static int touch_to_pixels(short x, short y)
|
||||
{
|
||||
/* X:300 -> 3800 Y:300->3900 */
|
||||
x -= 300;
|
||||
y -= 300;
|
||||
|
||||
#if CONFIG_ORIENTATION == SCREEN_PORTRAIT
|
||||
x /= 3200 / LCD_WIDTH;
|
||||
y /= 3600 / LCD_HEIGHT;
|
||||
|
||||
y = LCD_HEIGHT - y;
|
||||
|
||||
return (x << 16) | y;
|
||||
#else
|
||||
x /= 3200 / LCD_HEIGHT;
|
||||
y /= 3600 / LCD_WIDTH;
|
||||
|
||||
y = LCD_WIDTH - y;
|
||||
x = LCD_HEIGHT - x;
|
||||
|
||||
return (y << 16) | x;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool button_hold(void)
|
||||
{
|
||||
return (
|
||||
|
|
@ -218,38 +186,16 @@ int button_read_device(int *data)
|
|||
if(tmp & BTN_OFF)
|
||||
ret |= BUTTON_POWER;
|
||||
|
||||
if(cur_touch != 0)
|
||||
if(cur_touch != 0 && pen_down)
|
||||
{
|
||||
if(current_mode == TOUCHSCREEN_BUTTON)
|
||||
{
|
||||
int px_x = cur_touch >> 16;
|
||||
int px_y = cur_touch & 0xFFFF;
|
||||
ret |= touchscreen_buttons[px_y/(LCD_HEIGHT/3)]
|
||||
[px_x/(LCD_WIDTH/3)];
|
||||
}
|
||||
else if(pen_down)
|
||||
{
|
||||
ret |= BUTTON_TOUCHSCREEN;
|
||||
*data = cur_touch;
|
||||
}
|
||||
ret |= touchscreen_to_pixels(cur_touch >> 16, cur_touch & 0xFFFF, data);
|
||||
if( UNLIKELY(!is_backlight_on(true)) )
|
||||
*data = 0;
|
||||
}
|
||||
|
||||
if(ret & BUTTON_TOUCHSCREEN && !is_backlight_on(true))
|
||||
*data = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void touchscreen_set_mode(enum touchscreen_mode mode)
|
||||
{
|
||||
current_mode = mode;
|
||||
}
|
||||
|
||||
enum touchscreen_mode touchscreen_get_mode(void)
|
||||
{
|
||||
return current_mode;
|
||||
}
|
||||
|
||||
/* Interrupt handler */
|
||||
void SADC(void)
|
||||
{
|
||||
|
|
@ -314,7 +260,8 @@ void SADC(void)
|
|||
|
||||
if(datacount >= TS_AD_COUNT)
|
||||
{
|
||||
cur_touch = touch_to_pixels(x_pos/datacount, y_pos/datacount);
|
||||
cur_touch = ((x_pos / datacount) << 16) |
|
||||
((y_pos / datacount) & 0xFFFF);
|
||||
datacount = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue