diff options
Diffstat (limited to 'firmware/target/arm/tcc780x/cowond2/button-cowond2.c')
-rw-r--r-- | firmware/target/arm/tcc780x/cowond2/button-cowond2.c | 137 |
1 files changed, 84 insertions, 53 deletions
diff --git a/firmware/target/arm/tcc780x/cowond2/button-cowond2.c b/firmware/target/arm/tcc780x/cowond2/button-cowond2.c index a9b7265d4a..e66ba2332a 100644 --- a/firmware/target/arm/tcc780x/cowond2/button-cowond2.c +++ b/firmware/target/arm/tcc780x/cowond2/button-cowond2.c | |||
@@ -26,15 +26,65 @@ | |||
26 | #include "pcf50606.h" | 26 | #include "pcf50606.h" |
27 | #include "backlight.h" | 27 | #include "backlight.h" |
28 | #include "touchscreen.h" | 28 | #include "touchscreen.h" |
29 | #include "stdlib.h" | ||
29 | 30 | ||
30 | #define TOUCH_MARGIN 8 | 31 | #define NO_OF_TOUCH_DATA 5 |
31 | 32 | ||
32 | static short last_x, last_y; | ||
33 | static bool touch_available = false; | 33 | static bool touch_available = false; |
34 | static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA]; | ||
34 | 35 | ||
35 | void button_set_touch_available(void) | 36 | /* comparator for qsort */ |
37 | static int short_cmp(const void *a, const void *b) | ||
36 | { | 38 | { |
37 | touch_available = true; | 39 | return *(short*)a - *(short*)b; |
40 | } | ||
41 | |||
42 | void button_read_touch() | ||
43 | { | ||
44 | unsigned char buf[3]; | ||
45 | |||
46 | static long last_touch_interrupt = 0; | ||
47 | static int touch_data_index = 0; | ||
48 | |||
49 | /* put the touchscreen into idle mode */ | ||
50 | pcf50606_write(PCF5060X_ADCC1, 0); | ||
51 | |||
52 | /* here the touch coordinates are read 5 times */ | ||
53 | /* they will be sorted and the middle one will be used */ | ||
54 | pcf50606_write(PCF5060X_ADCC2, (0xE<<1) | 1); /* ADC start X+Y */ | ||
55 | |||
56 | do { | ||
57 | buf[1] = pcf50606_read(PCF5060X_ADCS2); | ||
58 | } while (!(buf[1] & 0x80)); /* Busy wait on ADCRDY flag */ | ||
59 | |||
60 | buf[0] = pcf50606_read(PCF5060X_ADCS1); | ||
61 | buf[2] = pcf50606_read(PCF5060X_ADCS3); | ||
62 | |||
63 | pcf50606_write(PCF5060X_ADCC2, 0); /* ADC stop */ | ||
64 | |||
65 | if (TIME_AFTER(current_tick, last_touch_interrupt + 1)) | ||
66 | { | ||
67 | /* resets the index if the last touch could not be read 5 times */ | ||
68 | touch_data_index = 0; | ||
69 | } | ||
70 | |||
71 | x[touch_data_index] = (buf[0] << 2) | (buf[1] & 3); | ||
72 | y[touch_data_index] = (buf[2] << 2) | ((buf[1] & 0xC) >> 2); | ||
73 | |||
74 | touch_data_index++; | ||
75 | |||
76 | if (touch_data_index > NO_OF_TOUCH_DATA - 1) | ||
77 | { | ||
78 | /* coordinates 5 times read */ | ||
79 | touch_available = true; | ||
80 | touch_data_index = 0; | ||
81 | } | ||
82 | else | ||
83 | { | ||
84 | /* put the touchscreen back into the interrupt mode */ | ||
85 | pcf50606_write(PCF5060X_ADCC1, 1); | ||
86 | } | ||
87 | last_touch_interrupt = current_tick; | ||
38 | } | 88 | } |
39 | 89 | ||
40 | struct touch_calibration_point { | 90 | struct touch_calibration_point { |
@@ -107,7 +157,9 @@ int button_read_device(int *data) | |||
107 | 157 | ||
108 | static bool hold_button = false; | 158 | static bool hold_button = false; |
109 | bool hold_button_old; | 159 | bool hold_button_old; |
110 | 160 | static bool touch_hold = false; | |
161 | static long last_touch = 0; | ||
162 | |||
111 | *data = old_data; | 163 | *data = old_data; |
112 | 164 | ||
113 | hold_button_old = hold_button; | 165 | hold_button_old = hold_button; |
@@ -143,66 +195,45 @@ int button_read_device(int *data) | |||
143 | } | 195 | } |
144 | } | 196 | } |
145 | 197 | ||
146 | if (touch_available) | 198 | if (touch_available || touch_hold) |
147 | { | 199 | { |
148 | short x = 0, y = 0; | 200 | short x_touch, y_touch; |
149 | static long last_touch = 0; | 201 | static short last_x = 0, last_y = 0; |
150 | bool send_touch = false; | ||
151 | 202 | ||
152 | int irq_level = disable_irq_save(); | 203 | if (touch_hold) |
153 | if (pcf50606_read(PCF5060X_ADCC1) & 0x80) /* Pen down */ | ||
154 | { | 204 | { |
155 | unsigned char buf[3]; | 205 | /* get rid of very fast unintended double touches */ |
156 | 206 | x_touch = last_x; | |
157 | pcf50606_write(PCF5060X_ADCC2, (0xE<<1) | 1); /* ADC start X+Y */ | 207 | y_touch = last_y; |
158 | |||
159 | do { | ||
160 | buf[1] = pcf50606_read(PCF5060X_ADCS2); | ||
161 | } while (!(buf[1] & 0x80)); /* Busy wait on ADCRDY flag */ | ||
162 | |||
163 | buf[0] = pcf50606_read(PCF5060X_ADCS1); | ||
164 | buf[2] = pcf50606_read(PCF5060X_ADCS3); | ||
165 | |||
166 | pcf50606_write(PCF5060X_ADCC2, 0); /* ADC stop */ | ||
167 | |||
168 | x = (buf[0] << 2) | (buf[1] & 3); | ||
169 | y = (buf[2] << 2) | ((buf[1] & 0xC) >> 2); | ||
170 | |||
171 | if (TIME_BEFORE(last_touch + HZ/5, current_tick)) | ||
172 | { | ||
173 | if ((x > last_x + TOUCH_MARGIN) || | ||
174 | (x < last_x - TOUCH_MARGIN) || | ||
175 | (y > last_y + TOUCH_MARGIN) || | ||
176 | (y < last_y - TOUCH_MARGIN)) | ||
177 | { | ||
178 | send_touch = true; | ||
179 | } | ||
180 | } | ||
181 | else | ||
182 | { | ||
183 | send_touch = true; | ||
184 | } | ||
185 | } | 208 | } |
186 | restore_irq(irq_level); | 209 | else |
187 | |||
188 | if (send_touch) | ||
189 | { | 210 | { |
190 | last_x = x; | 211 | /* sort the 5 data taken and use the median value */ |
191 | last_y = y; | 212 | qsort(x, NO_OF_TOUCH_DATA, sizeof(short), short_cmp); |
192 | old_data = *data = touch_to_pixels(x, y); | 213 | qsort(y, NO_OF_TOUCH_DATA, sizeof(short), short_cmp); |
193 | btn |= touchscreen_to_pixels((*data&0xffff0000)>>16, | 214 | x_touch = last_x = x[(NO_OF_TOUCH_DATA - 1)/2]; |
194 | (*data&0x0000ffff), | 215 | y_touch = last_y = y[(NO_OF_TOUCH_DATA - 1)/2]; |
195 | data); | 216 | last_touch = current_tick; |
217 | touch_hold = true; | ||
218 | touch_available = false; | ||
196 | } | 219 | } |
220 | old_data = *data = touch_to_pixels(x_touch, y_touch); | ||
221 | btn |= touchscreen_to_pixels((*data&0xffff0000)>>16, | ||
222 | (*data&0x0000ffff), | ||
223 | data); | ||
224 | } | ||
197 | 225 | ||
198 | last_touch = current_tick; | 226 | if (TIME_AFTER(current_tick, last_touch + 10)) |
199 | touch_available = false; | 227 | { |
228 | /* put the touchscreen back into interrupt mode */ | ||
229 | touch_hold = false; | ||
230 | pcf50606_write(PCF5060X_ADCC1, 1); | ||
200 | } | 231 | } |
201 | 232 | ||
202 | if (!(GPIOA & 0x4)) | 233 | if (!(GPIOA & 0x4)) |
203 | btn |= BUTTON_POWER; | 234 | btn |= BUTTON_POWER; |
204 | 235 | ||
205 | if(btn & BUTTON_TOUCHSCREEN && !is_backlight_on(true)) | 236 | if (btn & BUTTON_TOUCHSCREEN && !is_backlight_on(true)) |
206 | old_data = *data = 0; | 237 | old_data = *data = 0; |
207 | 238 | ||
208 | return btn; | 239 | return btn; |