summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tcc780x/cowond2/button-cowond2.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tcc780x/cowond2/button-cowond2.c')
-rw-r--r--firmware/target/arm/tcc780x/cowond2/button-cowond2.c137
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
32static short last_x, last_y;
33static bool touch_available = false; 33static bool touch_available = false;
34static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA];
34 35
35void button_set_touch_available(void) 36/* comparator for qsort */
37static int short_cmp(const void *a, const void *b)
36{ 38{
37 touch_available = true; 39 return *(short*)a - *(short*)b;
40}
41
42void 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
40struct touch_calibration_point { 90struct 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;