summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Purchase <shotofadds@rockbox.org>2009-10-15 20:13:29 +0000
committerRob Purchase <shotofadds@rockbox.org>2009-10-15 20:13:29 +0000
commitd29114c67187107dc558cc103d79f76af904f464 (patch)
treee1908562719adc3310940030199ff11023fd7d0f
parent562e41bae5b76abd49eceebf8324a445a4b82450 (diff)
downloadrockbox-d29114c67187107dc558cc103d79f76af904f464.tar.gz
rockbox-d29114c67187107dc558cc103d79f76af904f464.zip
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
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/drivers/tsc200x.c64
-rw-r--r--firmware/export/tsc200x.h34
-rw-r--r--firmware/target/arm/tcc780x/cowond2/button-cowond2.c139
-rw-r--r--firmware/target/arm/tcc780x/cowond2/button-target.h1
-rw-r--r--firmware/target/arm/tcc780x/cowond2/power-cowond2.c3
-rw-r--r--firmware/target/arm/tcc780x/cowond2/touchscreen-cowond2.c233
-rw-r--r--firmware/target/arm/tcc780x/cowond2/touchscreen-target.h30
8 files changed, 369 insertions, 137 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index db468335f2..2cb97a241b 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1256,12 +1256,14 @@ target/arm/tcc77x/iaudio7/audio-iaudio7.c
1256drivers/nand_id.c 1256drivers/nand_id.c
1257drivers/pcf50606.c 1257drivers/pcf50606.c
1258drivers/pcf50635.c 1258drivers/pcf50635.c
1259drivers/tsc200x.c
1259target/arm/lcd-as-memframe.S 1260target/arm/lcd-as-memframe.S
1260target/arm/tcc780x/adc-tcc780x.c 1261target/arm/tcc780x/adc-tcc780x.c
1261target/arm/tcc780x/system-tcc780x.c 1262target/arm/tcc780x/system-tcc780x.c
1262target/arm/tcc780x/kernel-tcc780x.c 1263target/arm/tcc780x/kernel-tcc780x.c
1263target/arm/tcc780x/sd-tcc780x.c 1264target/arm/tcc780x/sd-tcc780x.c
1264target/arm/tcc780x/cowond2/button-cowond2.c 1265target/arm/tcc780x/cowond2/button-cowond2.c
1266target/arm/tcc780x/cowond2/touchscreen-cowond2.c
1265target/arm/tcc780x/cowond2/lcd-cowond2.c 1267target/arm/tcc780x/cowond2/lcd-cowond2.c
1266target/arm/tcc780x/cowond2/power-cowond2.c 1268target/arm/tcc780x/cowond2/power-cowond2.c
1267target/arm/tcc780x/cowond2/powermgmt-cowond2.c 1269target/arm/tcc780x/cowond2/powermgmt-cowond2.c
diff --git a/firmware/drivers/tsc200x.c b/firmware/drivers/tsc200x.c
new file mode 100644
index 0000000000..4af8118d26
--- /dev/null
+++ b/firmware/drivers/tsc200x.c
@@ -0,0 +1,64 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Jonas Aaberg, Rob Purchase
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "tsc200x.h"
23#include "cpu.h"
24#include "i2c.h"
25
26#define TSC_SLAVE_ADDR 0x90
27#define TSC_REG_READ_X 0x80
28#define TSC_REG_READ_Y 0x90
29
30#ifdef COWON_D2
31#define TSCPRES_GPIO GPIOC
32#define TSCPRES_GPIO_DIR GPIOC_DIR
33#define TSCPRES_BIT (1<<26)
34#endif
35
36void tsc200x_init(void)
37{
38 /* Configure GPIOC 26 (TSC pressed) for input */
39 TSCPRES_GPIO_DIR &= ~TSCPRES_BIT;
40}
41
42bool tsc200x_is_pressed(void)
43{
44 return !(TSCPRES_GPIO & TSCPRES_BIT);
45}
46
47bool tsc200x_read_coords(short* x, short* y)
48{
49 int rc = 0;
50 unsigned char x_val[2], y_val[2];
51
52 rc |= i2c_readmem(TSC_SLAVE_ADDR, TSC_REG_READ_Y, y_val, 2);
53 rc |= i2c_readmem(TSC_SLAVE_ADDR, TSC_REG_READ_X, x_val, 2);
54
55 if (rc >= 0)
56 {
57 /* Keep the 10 most significant bits */
58 *x = ((((short)x_val[0]) << 8) | x_val[1]) >> 6;
59 *y = ((((short)y_val[0]) << 8) | y_val[1]) >> 6;
60 return true;
61 }
62
63 return false;
64}
diff --git a/firmware/export/tsc200x.h b/firmware/export/tsc200x.h
new file mode 100644
index 0000000000..a2705a0553
--- /dev/null
+++ b/firmware/export/tsc200x.h
@@ -0,0 +1,34 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Rob Purchase
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef _TSC200X_H
23#define _TSC200X_H
24
25#include <stdbool.h>
26
27/* The TI TSC2003 and TSC2007 touchscreen controllers are largely compatible,
28 except the TSC2007 filters coordinates using a "median windowed average". */
29
30void tsc200x_init(void);
31bool tsc200x_is_pressed(void);
32bool tsc200x_read_coords(short* x, short* y);
33
34#endif /* _TSC200X_H */
diff --git a/firmware/target/arm/tcc780x/cowond2/button-cowond2.c b/firmware/target/arm/tcc780x/cowond2/button-cowond2.c
index 30d81fa059..df2ea1f307 100644
--- a/firmware/target/arm/tcc780x/cowond2/button-cowond2.c
+++ b/firmware/target/arm/tcc780x/cowond2/button-cowond2.c
@@ -23,94 +23,9 @@
23#include "cpu.h" 23#include "cpu.h"
24#include "button.h" 24#include "button.h"
25#include "adc.h" 25#include "adc.h"
26#include "pcf50606.h"
27#include "backlight.h" 26#include "backlight.h"
28#include "touchscreen.h" 27#include "touchscreen-target.h"
29#include "stdlib.h" 28#include <stdlib.h>
30
31#define NO_OF_TOUCH_DATA 5
32
33static bool touch_available = false;
34static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA];
35
36/* comparator for qsort */
37static int short_cmp(const void *a, const void *b)
38{
39 return *(short*)a - *(short*)b;
40}
41
42void button_read_touch()
43{
44 static long last_touch_interrupt = 0;
45 static int touch_data_index = 0;
46
47 /* don't read the coordinates when hold is enabled */
48 if (button_hold()) return;
49
50 /* put the touchscreen into idle mode */
51 pcf50606_write(PCF5060X_ADCC1, 0);
52
53 if (TIME_AFTER(current_tick, last_touch_interrupt + 1))
54 {
55 /* resets the index if the last touch could not be read 5 times */
56 touch_data_index = 0;
57 }
58
59 /* here the touch coordinates are read 5 times */
60 /* they will be sorted and the middle one will be used */
61 pcf50606_read_adc(PCF5060X_ADC_TSC_XY,
62 &x[touch_data_index], &y[touch_data_index]);
63
64 touch_data_index++;
65
66 if (touch_data_index > NO_OF_TOUCH_DATA - 1)
67 {
68 /* coordinates 5 times read */
69 touch_available = true;
70 touch_data_index = 0;
71 }
72 else
73 {
74 /* put the touchscreen back into the interrupt mode */
75 pcf50606_write(PCF5060X_ADCC1, 1);
76 }
77 last_touch_interrupt = current_tick;
78}
79
80struct touch_calibration_point {
81 short px_x; /* known pixel value */
82 short px_y;
83 short val_x; /* touchscreen value at the known pixel */
84 short val_y;
85};
86
87static struct touch_calibration_point topleft, bottomright;
88
89static int touch_to_pixels(short val_x, short val_y)
90{
91 short x,y;
92
93 x=val_x;
94 y=val_y;
95
96 x = (x-topleft.val_x)*(bottomright.px_x - topleft.px_x)
97 / (bottomright.val_x - topleft.val_x) + topleft.px_x;
98
99 y = (y-topleft.val_y)*(bottomright.px_y - topleft.px_y)
100 / (bottomright.val_y - topleft.val_y) + topleft.px_y;
101
102 if (x < 0)
103 x = 0;
104 else if (x>=LCD_WIDTH)
105 x=LCD_WIDTH-1;
106
107 if (y < 0)
108 y = 0;
109 else if (y>=LCD_HEIGHT)
110 y=LCD_HEIGHT-1;
111
112 return (x<<16)|y;
113}
114 29
115void button_init_device(void) 30void button_init_device(void)
116{ 31{
@@ -120,18 +35,7 @@ void button_init_device(void)
120 /* Configure GPIOB 4 (button pressed) for input */ 35 /* Configure GPIOB 4 (button pressed) for input */
121 GPIOB_DIR &= ~0x10; 36 GPIOB_DIR &= ~0x10;
122 37
123 touch_available = false; 38 touchscreen_init_device();
124
125 /* Arbitrary touchscreen calibration */
126 topleft.px_x = 0;
127 topleft.px_y = 0;
128 topleft.val_x = 50;
129 topleft.val_y = 50;
130
131 bottomright.px_x = LCD_WIDTH;
132 bottomright.px_y = LCD_HEIGHT;
133 bottomright.val_x = 980;
134 bottomright.val_y = 980;
135} 39}
136 40
137bool button_hold(void) 41bool button_hold(void)
@@ -147,8 +51,6 @@ int button_read_device(int *data)
147 51
148 static bool hold_button = false; 52 static bool hold_button = false;
149 bool hold_button_old; 53 bool hold_button_old;
150 static bool touch_hold = false;
151 static long last_touch = 0;
152 54
153 *data = old_data; 55 *data = old_data;
154 56
@@ -185,40 +87,7 @@ int button_read_device(int *data)
185 } 87 }
186 } 88 }
187 89
188 if (touch_available || touch_hold) 90 btn |= touchscreen_read_device(data, &old_data);
189 {
190 short x_touch, y_touch;
191 static short last_x = 0, last_y = 0;
192
193 if (touch_hold)
194 {
195 /* get rid of very fast unintended double touches */
196 x_touch = last_x;
197 y_touch = last_y;
198 }
199 else
200 {
201 /* sort the 5 data taken and use the median value */
202 qsort(x, NO_OF_TOUCH_DATA, sizeof(short), short_cmp);
203 qsort(y, NO_OF_TOUCH_DATA, sizeof(short), short_cmp);
204 x_touch = last_x = x[(NO_OF_TOUCH_DATA - 1)/2];
205 y_touch = last_y = y[(NO_OF_TOUCH_DATA - 1)/2];
206 last_touch = current_tick;
207 touch_hold = true;
208 touch_available = false;
209 }
210 old_data = *data = touch_to_pixels(x_touch, y_touch);
211 btn |= touchscreen_to_pixels((*data&0xffff0000)>>16,
212 (*data&0x0000ffff),
213 data);
214 }
215
216 if (TIME_AFTER(current_tick, last_touch + 10))
217 {
218 /* put the touchscreen back into interrupt mode */
219 touch_hold = false;
220 pcf50606_write(PCF5060X_ADCC1, 1);
221 }
222 91
223 if (!(GPIOA & 0x4)) 92 if (!(GPIOA & 0x4))
224 btn |= BUTTON_POWER; 93 btn |= BUTTON_POWER;
diff --git a/firmware/target/arm/tcc780x/cowond2/button-target.h b/firmware/target/arm/tcc780x/cowond2/button-target.h
index ce6e2884a9..7d3736fe67 100644
--- a/firmware/target/arm/tcc780x/cowond2/button-target.h
+++ b/firmware/target/arm/tcc780x/cowond2/button-target.h
@@ -30,7 +30,6 @@
30bool button_hold(void); 30bool button_hold(void);
31void button_init_device(void); 31void button_init_device(void);
32int button_read_device(int *data); 32int button_read_device(int *data);
33void button_read_touch(void);
34 33
35/* Main unit's buttons */ 34/* Main unit's buttons */
36#define BUTTON_POWER 0x00000001 35#define BUTTON_POWER 0x00000001
diff --git a/firmware/target/arm/tcc780x/cowond2/power-cowond2.c b/firmware/target/arm/tcc780x/cowond2/power-cowond2.c
index d5f4ec9768..dfd692ecab 100644
--- a/firmware/target/arm/tcc780x/cowond2/power-cowond2.c
+++ b/firmware/target/arm/tcc780x/cowond2/power-cowond2.c
@@ -25,6 +25,7 @@
25#include "pcf50606.h" 25#include "pcf50606.h"
26#include "pcf50635.h" 26#include "pcf50635.h"
27#include "button-target.h" 27#include "button-target.h"
28#include "touchscreen-target.h"
28#include "tuner.h" 29#include "tuner.h"
29#include "backlight-target.h" 30#include "backlight-target.h"
30#include "powermgmt.h" 31#include "powermgmt.h"
@@ -101,7 +102,7 @@ void EXT3(void)
101 if (data[2] & 0x08) 102 if (data[2] & 0x08)
102 { 103 {
103 /* Touchscreen event, do something about it */ 104 /* Touchscreen event, do something about it */
104 button_read_touch(); 105 touchscreen_handle_device_irq();
105 } 106 }
106} 107}
107#endif 108#endif
diff --git a/firmware/target/arm/tcc780x/cowond2/touchscreen-cowond2.c b/firmware/target/arm/tcc780x/cowond2/touchscreen-cowond2.c
new file mode 100644
index 0000000000..d6483886ad
--- /dev/null
+++ b/firmware/target/arm/tcc780x/cowond2/touchscreen-cowond2.c
@@ -0,0 +1,233 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Rob Purchase, Carsten Schreiter, Jonas Aaberg
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "button.h"
24#include "pcf50606.h"
25#include "touchscreen.h"
26#include "stdlib.h"
27#include "power-target.h"
28#include "tsc200x.h"
29
30#define NO_OF_TOUCH_DATA 5
31
32static bool touch_available = false;
33
34static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA];
35
36/* comparator for qsort */
37static int short_cmp(const void *a, const void *b)
38{
39 return *(short*)a - *(short*)b;
40}
41
42struct touch_calibration_point {
43 short px_x; /* known pixel value */
44 short px_y;
45 short val_x; /* touchscreen value at the known pixel */
46 short val_y;
47};
48
49static struct touch_calibration_point topleft, bottomright;
50
51static int touch_to_pixels(short val_x, short val_y)
52{
53 short x, y;
54
55 x = val_x;
56 y = val_y;
57
58 x = (x - topleft.val_x) * (bottomright.px_x - topleft.px_x)
59 / (bottomright.val_x - topleft.val_x) + topleft.px_x;
60
61 y = (y - topleft.val_y) * (bottomright.px_y - topleft.px_y)
62 / (bottomright.val_y - topleft.val_y) + topleft.px_y;
63
64 if (x < 0)
65 x = 0;
66 else if (x >= LCD_WIDTH)
67 x = LCD_WIDTH - 1;
68
69 if (y < 0)
70 y = 0;
71 else if (y >= LCD_HEIGHT)
72 y = LCD_HEIGHT - 1;
73
74 return (x << 16) | y;
75}
76
77static int touchscreen_read_pcf50606(int *data, int *old_data)
78{
79 int btn = BUTTON_NONE;
80 static bool touch_hold = false;
81 static long last_touch = 0;
82
83 if (touch_available || touch_hold)
84 {
85 short x_touch, y_touch;
86 static short last_x = 0, last_y = 0;
87
88 if (touch_hold)
89 {
90 /* get rid of very fast unintended double touches */
91 x_touch = last_x;
92 y_touch = last_y;
93 }
94 else
95 {
96 /* sort the 5 data taken and use the median value */
97 qsort(x, NO_OF_TOUCH_DATA, sizeof(short), short_cmp);
98 qsort(y, NO_OF_TOUCH_DATA, sizeof(short), short_cmp);
99
100 x_touch = last_x = x[(NO_OF_TOUCH_DATA - 1)/2];
101 y_touch = last_y = y[(NO_OF_TOUCH_DATA - 1)/2];
102
103 last_touch = current_tick;
104
105 touch_hold = true;
106 touch_available = false;
107 }
108
109 *old_data = *data = touch_to_pixels(x_touch, y_touch);
110
111 btn |= touchscreen_to_pixels((*data&0xffff0000) >> 16,
112 (*data&0x0000ffff),
113 data);
114 }
115
116 if (TIME_AFTER(current_tick, last_touch + 10))
117 {
118 /* put the touchscreen back into interrupt mode */
119 touch_hold = false;
120 pcf50606_write(PCF5060X_ADCC1, 1);
121 }
122
123 return btn;
124}
125
126static int touchscreen_read_tsc200x(int *data, int *old_data)
127{
128 int btn = BUTTON_NONE;
129 short x_touch, y_touch;
130
131 static long last_read = 0;
132 static int last_btn = BUTTON_NONE;
133
134 /* Don't read hw every check button round. I2C is slow
135 * and man is even slower. */
136 if (TIME_BEFORE(current_tick, last_read + 10))
137 {
138 *data = *old_data;
139 return last_btn;
140 }
141
142 if (tsc200x_is_pressed())
143 {
144 if (tsc200x_read_coords(&x_touch, &y_touch))
145 {
146 *old_data = *data = touch_to_pixels(x_touch, y_touch);
147
148 btn = touchscreen_to_pixels((*data & 0xffff0000) >> 16,
149 (*data & 0x0000ffff),
150 data);
151
152 last_btn = btn;
153 }
154 }
155
156 last_read = current_tick;
157
158 return btn;
159}
160
161void touchscreen_init_device(void)
162{
163 touch_available = false;
164
165 /* Arbitrary touchscreen calibration */
166 topleft.px_x = 0;
167 topleft.px_y = 0;
168
169 bottomright.px_x = LCD_WIDTH;
170 bottomright.px_y = LCD_HEIGHT;
171
172 topleft.val_x = 50;
173 topleft.val_y = 50;
174
175 bottomright.val_x = 980;
176 bottomright.val_y = 980;
177
178 if (get_pmu_type() != PCF50606)
179 {
180 tsc200x_init();
181 }
182}
183
184void touchscreen_handle_device_irq(void)
185{
186 static long last_touch_interrupt = 0;
187 static int touch_data_index = 0;
188
189 /* don't read the coordinates when hold is enabled */
190 if (button_hold()) return;
191
192 /* put the touchscreen into idle mode */
193 pcf50606_write(PCF5060X_ADCC1, 0);
194
195 if (TIME_AFTER(current_tick, last_touch_interrupt + 1))
196 {
197 /* resets the index if the last touch could not be read 5 times */
198 touch_data_index = 0;
199 }
200
201 /* here the touch coordinates are read 5 times */
202 /* they will be sorted and the middle one will be used */
203 pcf50606_read_adc(PCF5060X_ADC_TSC_XY,
204 &x[touch_data_index], &y[touch_data_index]);
205
206 touch_data_index++;
207
208 if (touch_data_index > NO_OF_TOUCH_DATA - 1)
209 {
210 /* coordinates 5 times read */
211 touch_available = true;
212 touch_data_index = 0;
213 }
214 else
215 {
216 /* put the touchscreen back into the interrupt mode */
217 pcf50606_write(PCF5060X_ADCC1, 1);
218 }
219 last_touch_interrupt = current_tick;
220}
221
222
223int touchscreen_read_device(int *data, int *old_data)
224{
225 int btn;
226
227 if (get_pmu_type() == PCF50606)
228 btn = touchscreen_read_pcf50606(data, old_data);
229 else
230 btn = touchscreen_read_tsc200x(data, old_data);
231
232 return btn;
233}
diff --git a/firmware/target/arm/tcc780x/cowond2/touchscreen-target.h b/firmware/target/arm/tcc780x/cowond2/touchscreen-target.h
new file mode 100644
index 0000000000..be18aed723
--- /dev/null
+++ b/firmware/target/arm/tcc780x/cowond2/touchscreen-target.h
@@ -0,0 +1,30 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Jonas Aaberg
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _TOUCHSCREEN_TARGET_H_
22#define _TOUCHSCREEN_TARGET_H_
23
24#include "config.h"
25
26void touchscreen_init_device(void);
27int touchscreen_read_device(int *data, int *old_data);
28void touchscreen_handle_device_irq(void);
29
30#endif