summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tcc780x/cowond2/touchscreen-cowond2.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tcc780x/cowond2/touchscreen-cowond2.c')
-rw-r--r--firmware/target/arm/tcc780x/cowond2/touchscreen-cowond2.c233
1 files changed, 233 insertions, 0 deletions
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}