Touchscreen support for newer Cowon D2+ hardware revisions (using TSC200x touchscreen controller).
Flyspray: FS#10671 Author: Jonas Aaberg git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23194 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
562e41bae5
commit
d29114c671
|
@ -1256,12 +1256,14 @@ target/arm/tcc77x/iaudio7/audio-iaudio7.c
|
|||
drivers/nand_id.c
|
||||
drivers/pcf50606.c
|
||||
drivers/pcf50635.c
|
||||
drivers/tsc200x.c
|
||||
target/arm/lcd-as-memframe.S
|
||||
target/arm/tcc780x/adc-tcc780x.c
|
||||
target/arm/tcc780x/system-tcc780x.c
|
||||
target/arm/tcc780x/kernel-tcc780x.c
|
||||
target/arm/tcc780x/sd-tcc780x.c
|
||||
target/arm/tcc780x/cowond2/button-cowond2.c
|
||||
target/arm/tcc780x/cowond2/touchscreen-cowond2.c
|
||||
target/arm/tcc780x/cowond2/lcd-cowond2.c
|
||||
target/arm/tcc780x/cowond2/power-cowond2.c
|
||||
target/arm/tcc780x/cowond2/powermgmt-cowond2.c
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2009 by Jonas Aaberg, Rob Purchase
|
||||
*
|
||||
* 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 "tsc200x.h"
|
||||
#include "cpu.h"
|
||||
#include "i2c.h"
|
||||
|
||||
#define TSC_SLAVE_ADDR 0x90
|
||||
#define TSC_REG_READ_X 0x80
|
||||
#define TSC_REG_READ_Y 0x90
|
||||
|
||||
#ifdef COWON_D2
|
||||
#define TSCPRES_GPIO GPIOC
|
||||
#define TSCPRES_GPIO_DIR GPIOC_DIR
|
||||
#define TSCPRES_BIT (1<<26)
|
||||
#endif
|
||||
|
||||
void tsc200x_init(void)
|
||||
{
|
||||
/* Configure GPIOC 26 (TSC pressed) for input */
|
||||
TSCPRES_GPIO_DIR &= ~TSCPRES_BIT;
|
||||
}
|
||||
|
||||
bool tsc200x_is_pressed(void)
|
||||
{
|
||||
return !(TSCPRES_GPIO & TSCPRES_BIT);
|
||||
}
|
||||
|
||||
bool tsc200x_read_coords(short* x, short* y)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char x_val[2], y_val[2];
|
||||
|
||||
rc |= i2c_readmem(TSC_SLAVE_ADDR, TSC_REG_READ_Y, y_val, 2);
|
||||
rc |= i2c_readmem(TSC_SLAVE_ADDR, TSC_REG_READ_X, x_val, 2);
|
||||
|
||||
if (rc >= 0)
|
||||
{
|
||||
/* Keep the 10 most significant bits */
|
||||
*x = ((((short)x_val[0]) << 8) | x_val[1]) >> 6;
|
||||
*y = ((((short)y_val[0]) << 8) | y_val[1]) >> 6;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2009 by Rob Purchase
|
||||
*
|
||||
* 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 _TSC200X_H
|
||||
#define _TSC200X_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/* The TI TSC2003 and TSC2007 touchscreen controllers are largely compatible,
|
||||
except the TSC2007 filters coordinates using a "median windowed average". */
|
||||
|
||||
void tsc200x_init(void);
|
||||
bool tsc200x_is_pressed(void);
|
||||
bool tsc200x_read_coords(short* x, short* y);
|
||||
|
||||
#endif /* _TSC200X_H */
|
|
@ -23,94 +23,9 @@
|
|||
#include "cpu.h"
|
||||
#include "button.h"
|
||||
#include "adc.h"
|
||||
#include "pcf50606.h"
|
||||
#include "backlight.h"
|
||||
#include "touchscreen.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#define NO_OF_TOUCH_DATA 5
|
||||
|
||||
static bool touch_available = false;
|
||||
static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA];
|
||||
|
||||
/* comparator for qsort */
|
||||
static int short_cmp(const void *a, const void *b)
|
||||
{
|
||||
return *(short*)a - *(short*)b;
|
||||
}
|
||||
|
||||
void button_read_touch()
|
||||
{
|
||||
static long last_touch_interrupt = 0;
|
||||
static int touch_data_index = 0;
|
||||
|
||||
/* don't read the coordinates when hold is enabled */
|
||||
if (button_hold()) return;
|
||||
|
||||
/* put the touchscreen into idle mode */
|
||||
pcf50606_write(PCF5060X_ADCC1, 0);
|
||||
|
||||
if (TIME_AFTER(current_tick, last_touch_interrupt + 1))
|
||||
{
|
||||
/* resets the index if the last touch could not be read 5 times */
|
||||
touch_data_index = 0;
|
||||
}
|
||||
|
||||
/* here the touch coordinates are read 5 times */
|
||||
/* they will be sorted and the middle one will be used */
|
||||
pcf50606_read_adc(PCF5060X_ADC_TSC_XY,
|
||||
&x[touch_data_index], &y[touch_data_index]);
|
||||
|
||||
touch_data_index++;
|
||||
|
||||
if (touch_data_index > NO_OF_TOUCH_DATA - 1)
|
||||
{
|
||||
/* coordinates 5 times read */
|
||||
touch_available = true;
|
||||
touch_data_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* put the touchscreen back into the interrupt mode */
|
||||
pcf50606_write(PCF5060X_ADCC1, 1);
|
||||
}
|
||||
last_touch_interrupt = current_tick;
|
||||
}
|
||||
|
||||
struct touch_calibration_point {
|
||||
short px_x; /* known pixel value */
|
||||
short px_y;
|
||||
short val_x; /* touchscreen value at the known pixel */
|
||||
short val_y;
|
||||
};
|
||||
|
||||
static struct touch_calibration_point topleft, bottomright;
|
||||
|
||||
static int touch_to_pixels(short val_x, short val_y)
|
||||
{
|
||||
short x,y;
|
||||
|
||||
x=val_x;
|
||||
y=val_y;
|
||||
|
||||
x = (x-topleft.val_x)*(bottomright.px_x - topleft.px_x)
|
||||
/ (bottomright.val_x - topleft.val_x) + topleft.px_x;
|
||||
|
||||
y = (y-topleft.val_y)*(bottomright.px_y - topleft.px_y)
|
||||
/ (bottomright.val_y - topleft.val_y) + topleft.px_y;
|
||||
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
else if (x>=LCD_WIDTH)
|
||||
x=LCD_WIDTH-1;
|
||||
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
else if (y>=LCD_HEIGHT)
|
||||
y=LCD_HEIGHT-1;
|
||||
|
||||
return (x<<16)|y;
|
||||
}
|
||||
#include "touchscreen-target.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void button_init_device(void)
|
||||
{
|
||||
|
@ -120,18 +35,7 @@ void button_init_device(void)
|
|||
/* Configure GPIOB 4 (button pressed) for input */
|
||||
GPIOB_DIR &= ~0x10;
|
||||
|
||||
touch_available = false;
|
||||
|
||||
/* Arbitrary touchscreen calibration */
|
||||
topleft.px_x = 0;
|
||||
topleft.px_y = 0;
|
||||
topleft.val_x = 50;
|
||||
topleft.val_y = 50;
|
||||
|
||||
bottomright.px_x = LCD_WIDTH;
|
||||
bottomright.px_y = LCD_HEIGHT;
|
||||
bottomright.val_x = 980;
|
||||
bottomright.val_y = 980;
|
||||
touchscreen_init_device();
|
||||
}
|
||||
|
||||
bool button_hold(void)
|
||||
|
@ -147,8 +51,6 @@ int button_read_device(int *data)
|
|||
|
||||
static bool hold_button = false;
|
||||
bool hold_button_old;
|
||||
static bool touch_hold = false;
|
||||
static long last_touch = 0;
|
||||
|
||||
*data = old_data;
|
||||
|
||||
|
@ -185,40 +87,7 @@ int button_read_device(int *data)
|
|||
}
|
||||
}
|
||||
|
||||
if (touch_available || touch_hold)
|
||||
{
|
||||
short x_touch, y_touch;
|
||||
static short last_x = 0, last_y = 0;
|
||||
|
||||
if (touch_hold)
|
||||
{
|
||||
/* get rid of very fast unintended double touches */
|
||||
x_touch = last_x;
|
||||
y_touch = last_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* sort the 5 data taken and use the median value */
|
||||
qsort(x, NO_OF_TOUCH_DATA, sizeof(short), short_cmp);
|
||||
qsort(y, NO_OF_TOUCH_DATA, sizeof(short), short_cmp);
|
||||
x_touch = last_x = x[(NO_OF_TOUCH_DATA - 1)/2];
|
||||
y_touch = last_y = y[(NO_OF_TOUCH_DATA - 1)/2];
|
||||
last_touch = current_tick;
|
||||
touch_hold = true;
|
||||
touch_available = false;
|
||||
}
|
||||
old_data = *data = touch_to_pixels(x_touch, y_touch);
|
||||
btn |= touchscreen_to_pixels((*data&0xffff0000)>>16,
|
||||
(*data&0x0000ffff),
|
||||
data);
|
||||
}
|
||||
|
||||
if (TIME_AFTER(current_tick, last_touch + 10))
|
||||
{
|
||||
/* put the touchscreen back into interrupt mode */
|
||||
touch_hold = false;
|
||||
pcf50606_write(PCF5060X_ADCC1, 1);
|
||||
}
|
||||
btn |= touchscreen_read_device(data, &old_data);
|
||||
|
||||
if (!(GPIOA & 0x4))
|
||||
btn |= BUTTON_POWER;
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
bool button_hold(void);
|
||||
void button_init_device(void);
|
||||
int button_read_device(int *data);
|
||||
void button_read_touch(void);
|
||||
|
||||
/* Main unit's buttons */
|
||||
#define BUTTON_POWER 0x00000001
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "pcf50606.h"
|
||||
#include "pcf50635.h"
|
||||
#include "button-target.h"
|
||||
#include "touchscreen-target.h"
|
||||
#include "tuner.h"
|
||||
#include "backlight-target.h"
|
||||
#include "powermgmt.h"
|
||||
|
@ -101,7 +102,7 @@ void EXT3(void)
|
|||
if (data[2] & 0x08)
|
||||
{
|
||||
/* Touchscreen event, do something about it */
|
||||
button_read_touch();
|
||||
touchscreen_handle_device_irq();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2009 by Rob Purchase, Carsten Schreiter, Jonas Aaberg
|
||||
*
|
||||
* 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 "pcf50606.h"
|
||||
#include "touchscreen.h"
|
||||
#include "stdlib.h"
|
||||
#include "power-target.h"
|
||||
#include "tsc200x.h"
|
||||
|
||||
#define NO_OF_TOUCH_DATA 5
|
||||
|
||||
static bool touch_available = false;
|
||||
|
||||
static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA];
|
||||
|
||||
/* comparator for qsort */
|
||||
static int short_cmp(const void *a, const void *b)
|
||||
{
|
||||
return *(short*)a - *(short*)b;
|
||||
}
|
||||
|
||||
struct touch_calibration_point {
|
||||
short px_x; /* known pixel value */
|
||||
short px_y;
|
||||
short val_x; /* touchscreen value at the known pixel */
|
||||
short val_y;
|
||||
};
|
||||
|
||||
static struct touch_calibration_point topleft, bottomright;
|
||||
|
||||
static int touch_to_pixels(short val_x, short val_y)
|
||||
{
|
||||
short x, y;
|
||||
|
||||
x = val_x;
|
||||
y = val_y;
|
||||
|
||||
x = (x - topleft.val_x) * (bottomright.px_x - topleft.px_x)
|
||||
/ (bottomright.val_x - topleft.val_x) + topleft.px_x;
|
||||
|
||||
y = (y - topleft.val_y) * (bottomright.px_y - topleft.px_y)
|
||||
/ (bottomright.val_y - topleft.val_y) + topleft.px_y;
|
||||
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
else if (x >= LCD_WIDTH)
|
||||
x = LCD_WIDTH - 1;
|
||||
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
else if (y >= LCD_HEIGHT)
|
||||
y = LCD_HEIGHT - 1;
|
||||
|
||||
return (x << 16) | y;
|
||||
}
|
||||
|
||||
static int touchscreen_read_pcf50606(int *data, int *old_data)
|
||||
{
|
||||
int btn = BUTTON_NONE;
|
||||
static bool touch_hold = false;
|
||||
static long last_touch = 0;
|
||||
|
||||
if (touch_available || touch_hold)
|
||||
{
|
||||
short x_touch, y_touch;
|
||||
static short last_x = 0, last_y = 0;
|
||||
|
||||
if (touch_hold)
|
||||
{
|
||||
/* get rid of very fast unintended double touches */
|
||||
x_touch = last_x;
|
||||
y_touch = last_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* sort the 5 data taken and use the median value */
|
||||
qsort(x, NO_OF_TOUCH_DATA, sizeof(short), short_cmp);
|
||||
qsort(y, NO_OF_TOUCH_DATA, sizeof(short), short_cmp);
|
||||
|
||||
x_touch = last_x = x[(NO_OF_TOUCH_DATA - 1)/2];
|
||||
y_touch = last_y = y[(NO_OF_TOUCH_DATA - 1)/2];
|
||||
|
||||
last_touch = current_tick;
|
||||
|
||||
touch_hold = true;
|
||||
touch_available = false;
|
||||
}
|
||||
|
||||
*old_data = *data = touch_to_pixels(x_touch, y_touch);
|
||||
|
||||
btn |= touchscreen_to_pixels((*data&0xffff0000) >> 16,
|
||||
(*data&0x0000ffff),
|
||||
data);
|
||||
}
|
||||
|
||||
if (TIME_AFTER(current_tick, last_touch + 10))
|
||||
{
|
||||
/* put the touchscreen back into interrupt mode */
|
||||
touch_hold = false;
|
||||
pcf50606_write(PCF5060X_ADCC1, 1);
|
||||
}
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
static int touchscreen_read_tsc200x(int *data, int *old_data)
|
||||
{
|
||||
int btn = BUTTON_NONE;
|
||||
short x_touch, y_touch;
|
||||
|
||||
static long last_read = 0;
|
||||
static int last_btn = BUTTON_NONE;
|
||||
|
||||
/* Don't read hw every check button round. I2C is slow
|
||||
* and man is even slower. */
|
||||
if (TIME_BEFORE(current_tick, last_read + 10))
|
||||
{
|
||||
*data = *old_data;
|
||||
return last_btn;
|
||||
}
|
||||
|
||||
if (tsc200x_is_pressed())
|
||||
{
|
||||
if (tsc200x_read_coords(&x_touch, &y_touch))
|
||||
{
|
||||
*old_data = *data = touch_to_pixels(x_touch, y_touch);
|
||||
|
||||
btn = touchscreen_to_pixels((*data & 0xffff0000) >> 16,
|
||||
(*data & 0x0000ffff),
|
||||
data);
|
||||
|
||||
last_btn = btn;
|
||||
}
|
||||
}
|
||||
|
||||
last_read = current_tick;
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
void touchscreen_init_device(void)
|
||||
{
|
||||
touch_available = false;
|
||||
|
||||
/* Arbitrary touchscreen calibration */
|
||||
topleft.px_x = 0;
|
||||
topleft.px_y = 0;
|
||||
|
||||
bottomright.px_x = LCD_WIDTH;
|
||||
bottomright.px_y = LCD_HEIGHT;
|
||||
|
||||
topleft.val_x = 50;
|
||||
topleft.val_y = 50;
|
||||
|
||||
bottomright.val_x = 980;
|
||||
bottomright.val_y = 980;
|
||||
|
||||
if (get_pmu_type() != PCF50606)
|
||||
{
|
||||
tsc200x_init();
|
||||
}
|
||||
}
|
||||
|
||||
void touchscreen_handle_device_irq(void)
|
||||
{
|
||||
static long last_touch_interrupt = 0;
|
||||
static int touch_data_index = 0;
|
||||
|
||||
/* don't read the coordinates when hold is enabled */
|
||||
if (button_hold()) return;
|
||||
|
||||
/* put the touchscreen into idle mode */
|
||||
pcf50606_write(PCF5060X_ADCC1, 0);
|
||||
|
||||
if (TIME_AFTER(current_tick, last_touch_interrupt + 1))
|
||||
{
|
||||
/* resets the index if the last touch could not be read 5 times */
|
||||
touch_data_index = 0;
|
||||
}
|
||||
|
||||
/* here the touch coordinates are read 5 times */
|
||||
/* they will be sorted and the middle one will be used */
|
||||
pcf50606_read_adc(PCF5060X_ADC_TSC_XY,
|
||||
&x[touch_data_index], &y[touch_data_index]);
|
||||
|
||||
touch_data_index++;
|
||||
|
||||
if (touch_data_index > NO_OF_TOUCH_DATA - 1)
|
||||
{
|
||||
/* coordinates 5 times read */
|
||||
touch_available = true;
|
||||
touch_data_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* put the touchscreen back into the interrupt mode */
|
||||
pcf50606_write(PCF5060X_ADCC1, 1);
|
||||
}
|
||||
last_touch_interrupt = current_tick;
|
||||
}
|
||||
|
||||
|
||||
int touchscreen_read_device(int *data, int *old_data)
|
||||
{
|
||||
int btn;
|
||||
|
||||
if (get_pmu_type() == PCF50606)
|
||||
btn = touchscreen_read_pcf50606(data, old_data);
|
||||
else
|
||||
btn = touchscreen_read_tsc200x(data, old_data);
|
||||
|
||||
return btn;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2009 by Jonas Aaberg
|
||||
*
|
||||
* 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_TARGET_H_
|
||||
#define _TOUCHSCREEN_TARGET_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
void touchscreen_init_device(void);
|
||||
int touchscreen_read_device(int *data, int *old_data);
|
||||
void touchscreen_handle_device_irq(void);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue