Various minor cleanups for cowon d2
[kugel-rb.git] / firmware / target / arm / tcc780x / cowond2 / touchscreen-cowond2.c
blob1135d3470164c61be8bd43bd6fb18692fcd5fa9b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2009 by Rob Purchase, Carsten Schreiter, Jonas Aaberg
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "config.h"
23 #include "button.h"
24 #include "pcf50606.h"
25 #include "touchscreen.h"
26 #include "touchscreen-target.h"
27 #include "stdlib.h"
28 #include "power-target.h"
29 #include "tsc200x.h"
31 #define NO_OF_TOUCH_DATA 5
33 static bool touch_available = false;
35 static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA];
37 /* comparator for qsort */
38 static int short_cmp(const void *a, const void *b)
40 return *(short*)a - *(short*)b;
43 static int touch_to_pixels(short val_x, short val_y)
45 int x = (val_x * LCD_WIDTH) >> 10;
46 int y = (val_y * LCD_HEIGHT) >> 10;
48 if (x < 0)
49 x = 0;
50 else if (x >= LCD_WIDTH)
51 x = LCD_WIDTH - 1;
53 if (y < 0)
54 y = 0;
55 else if (y >= LCD_HEIGHT)
56 y = LCD_HEIGHT - 1;
58 return (x << 16) | y;
61 static int touchscreen_read_pcf50606(int *data, int *old_data)
63 int btn = BUTTON_NONE;
64 static bool touch_hold = false;
65 static long last_touch = 0;
67 if (touch_available || touch_hold)
69 short x_touch, y_touch;
70 static short last_x = 0, last_y = 0;
72 if (touch_hold)
74 /* get rid of very fast unintended double touches */
75 x_touch = last_x;
76 y_touch = last_y;
78 else
80 /* sort the 5 data taken and use the median value */
81 qsort(x, NO_OF_TOUCH_DATA, sizeof(short), short_cmp);
82 qsort(y, NO_OF_TOUCH_DATA, sizeof(short), short_cmp);
84 x_touch = last_x = x[(NO_OF_TOUCH_DATA - 1)/2];
85 y_touch = last_y = y[(NO_OF_TOUCH_DATA - 1)/2];
87 last_touch = current_tick;
89 touch_hold = true;
90 touch_available = false;
93 *old_data = *data = touch_to_pixels(x_touch, y_touch);
95 btn |= touchscreen_to_pixels((*data&0xffff0000) >> 16,
96 (*data&0x0000ffff),
97 data);
100 if (TIME_AFTER(current_tick, last_touch + 10))
102 /* put the touchscreen back into interrupt mode */
103 touch_hold = false;
104 pcf50606_write(PCF5060X_ADCC1, 1);
107 return btn;
110 static int touchscreen_read_tsc200x(int *data, int *old_data)
112 int btn = BUTTON_NONE;
113 short x_touch, y_touch;
115 static long last_read = 0;
116 static int last_btn = BUTTON_NONE;
118 /* Don't read hw every check button round. I2C is slow
119 * and man is even slower. */
120 if (TIME_BEFORE(current_tick, last_read + 10))
122 *data = *old_data;
123 return last_btn;
126 if (tsc200x_is_pressed())
128 if (tsc200x_read_coords(&x_touch, &y_touch))
130 *old_data = *data = touch_to_pixels(x_touch, y_touch);
132 btn = touchscreen_to_pixels((*data & 0xffff0000) >> 16,
133 (*data & 0x0000ffff),
134 data);
138 last_read = current_tick;
140 last_btn = btn;
142 return btn;
145 void touchscreen_init_device(void)
147 touch_available = false;
149 if (get_pmu_type() != PCF50606)
151 tsc200x_init();
155 void touchscreen_handle_device_irq(void)
157 static long last_touch_interrupt = 0;
158 static int touch_data_index = 0;
160 /* don't read the coordinates when hold is enabled */
161 if (button_hold()) return;
163 /* put the touchscreen into idle mode */
164 pcf50606_write(PCF5060X_ADCC1, 0);
166 if (TIME_AFTER(current_tick, last_touch_interrupt + 1))
168 /* resets the index if the last touch could not be read 5 times */
169 touch_data_index = 0;
172 /* here the touch coordinates are read 5 times */
173 /* they will be sorted and the middle one will be used */
174 pcf50606_read_adc(PCF5060X_ADC_TSC_XY,
175 &x[touch_data_index], &y[touch_data_index]);
177 touch_data_index++;
179 if (touch_data_index > NO_OF_TOUCH_DATA - 1)
181 /* coordinates 5 times read */
182 touch_available = true;
183 touch_data_index = 0;
185 else
187 /* put the touchscreen back into the interrupt mode */
188 pcf50606_write(PCF5060X_ADCC1, 1);
190 last_touch_interrupt = current_tick;
194 int touchscreen_read_device(int *data, int *old_data)
196 int btn;
198 if (get_pmu_type() == PCF50606)
199 btn = touchscreen_read_pcf50606(data, old_data);
200 else
201 btn = touchscreen_read_tsc200x(data, old_data);
203 return btn;