summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/button.c89
1 files changed, 61 insertions, 28 deletions
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c
index 0d0d1cd7ad..f87128adf8 100644
--- a/firmware/drivers/button.c
+++ b/firmware/drivers/button.c
@@ -38,19 +38,10 @@
38#else 38#else
39#include "button-target.h" 39#include "button-target.h"
40#endif 40#endif
41
42#ifdef HAVE_REMOTE_LCD 41#ifdef HAVE_REMOTE_LCD
43#include "lcd-remote.h" 42#include "lcd-remote.h"
44#endif 43#endif
45 44
46#if 0
47/* Older than MAX_EVENT_AGE button events are going to be ignored.
48 * Used to prevent for example volume going up uncontrollable when events
49 * are getting queued and UI is lagging too much.
50 */
51#define MAX_EVENT_AGE HZ
52#endif
53
54struct event_queue button_queue; 45struct event_queue button_queue;
55 46
56static long lastbtn; /* Last valid button status */ 47static long lastbtn; /* Last valid button status */
@@ -72,11 +63,27 @@ static bool phones_present = false;
72/* how long until repeat kicks in, in centiseconds */ 63/* how long until repeat kicks in, in centiseconds */
73#define REPEAT_START (30*HZ/100) 64#define REPEAT_START (30*HZ/100)
74 65
66#ifndef HAVE_TOUCHSCREEN
67/* the next two make repeat "accelerate", which is nice for lists
68 * which begin to scroll a bit faster when holding until the
69 * real list accerelation kicks in (this smoothes acceleration)
70 */
71
75/* the speed repeat starts at, in centiseconds */ 72/* the speed repeat starts at, in centiseconds */
76#define REPEAT_INTERVAL_START (16*HZ/100) 73#define REPEAT_INTERVAL_START (16*HZ/100)
77
78/* speed repeat finishes at, in centiseconds */ 74/* speed repeat finishes at, in centiseconds */
79#define REPEAT_INTERVAL_FINISH (5*HZ/100) 75#define REPEAT_INTERVAL_FINISH (5*HZ/100)
76#else
77/*
78 * on touchscreen it's different, scrolling is done by swiping over the
79 * screen (potentially very quickly) and is completely different from button
80 * targets
81 * So, on touchscreen we don't want to artifically slow down early repeats,
82 * it'd have the contrary effect of making rockbox appear lagging
83 */
84#define REPEAT_INTERVAL_START (3*HZ/100)
85#define REPEAT_INTERVAL_FINISH (3*HZ/100)
86#endif
80 87
81#ifdef HAVE_BUTTON_DATA 88#ifdef HAVE_BUTTON_DATA
82static int button_read(int *data); 89static int button_read(int *data);
@@ -102,6 +109,35 @@ static int btn_detect_callback(struct timeout *tmo)
102} 109}
103#endif 110#endif
104 111
112static bool button_try_post(int button, int data)
113{
114#ifdef HAVE_TOUCHSCREEN
115 /* one can swipe over the scren very quickly,
116 * for this to work we want to forget about old presses and
117 * only respect the very latest ones */
118 const int force_post = true;
119#else
120 /* Only post events if the queue is empty,
121 * to avoid afterscroll effects.
122 * i.e. don't post new buttons if previous ones haven't been
123 * processed yet */
124 const int force_post = false;
125#endif
126
127 bool ret = queue_empty(&button_queue);
128 if (!ret && force_post)
129 {
130 queue_remove_from_head(&button_queue, button);
131 ret = true;
132 }
133
134 if (ret)
135 queue_post(&button_queue, button, data);
136
137 /* on touchscreen we posted unconditionally */
138 return ret;
139}
140
105static void button_tick(void) 141static void button_tick(void)
106{ 142{
107 static int count = 0; 143 static int count = 0;
@@ -127,9 +163,7 @@ static void button_tick(void)
127 /* Post events for the remote control */ 163 /* Post events for the remote control */
128 btn = remote_control_rx(); 164 btn = remote_control_rx();
129 if(btn) 165 if(btn)
130 { 166 button_try_post(btn, 0);
131 queue_post(&button_queue, btn, 0);
132 }
133#endif 167#endif
134 168
135#ifdef HAVE_BUTTON_DATA 169#ifdef HAVE_BUTTON_DATA
@@ -137,7 +171,6 @@ static void button_tick(void)
137#else 171#else
138 btn = button_read(); 172 btn = button_read();
139#endif 173#endif
140
141#if defined(HAVE_HEADPHONE_DETECTION) 174#if defined(HAVE_HEADPHONE_DETECTION)
142 if (headphones_inserted() != phones_present) 175 if (headphones_inserted() != phones_present)
143 { 176 {
@@ -156,17 +189,17 @@ static void button_tick(void)
156#ifdef HAVE_REMOTE_LCD 189#ifdef HAVE_REMOTE_LCD
157 if(diff & BUTTON_REMOTE) 190 if(diff & BUTTON_REMOTE)
158 if(!skip_remote_release) 191 if(!skip_remote_release)
159 queue_post(&button_queue, BUTTON_REL | diff, data); 192 button_try_post(BUTTON_REL | diff, data);
160 else 193 else
161 skip_remote_release = false; 194 skip_remote_release = false;
162 else 195 else
163#endif 196#endif
164 if(!skip_release) 197 if(!skip_release)
165 queue_post(&button_queue, BUTTON_REL | diff, data); 198 button_try_post(BUTTON_REL | diff, data);
166 else 199 else
167 skip_release = false; 200 skip_release = false;
168#else 201#else
169 queue_post(&button_queue, BUTTON_REL | diff, data); 202 button_try_post(BUTTON_REL | diff, data);
170#endif 203#endif
171 } 204 }
172 else 205 else
@@ -233,6 +266,13 @@ static void button_tick(void)
233 /* initial repeat */ 266 /* initial repeat */
234 count = REPEAT_INTERVAL_START; 267 count = REPEAT_INTERVAL_START;
235 } 268 }
269#ifdef HAVE_TOUCHSCREEN
270 else if (lastdata != data && btn == lastbtn)
271 { /* only coordinates changed, post anyway */
272 if (touchscreen_get_mode() == TOUCHSCREEN_POINT)
273 post = true;
274 }
275#endif
236 } 276 }
237 } 277 }
238 if ( post ) 278 if ( post )
@@ -241,9 +281,8 @@ static void button_tick(void)
241 { 281 {
242 /* Only post repeat events if the queue is empty, 282 /* Only post repeat events if the queue is empty,
243 * to avoid afterscroll effects. */ 283 * to avoid afterscroll effects. */
244 if (queue_empty(&button_queue)) 284 if (button_try_post(BUTTON_REPEAT | btn, data))
245 { 285 {
246 queue_post(&button_queue, BUTTON_REPEAT | btn, data);
247#ifdef HAVE_BACKLIGHT 286#ifdef HAVE_BACKLIGHT
248#ifdef HAVE_REMOTE_LCD 287#ifdef HAVE_REMOTE_LCD
249 skip_remote_release = false; 288 skip_remote_release = false;
@@ -264,7 +303,7 @@ static void button_tick(void)
264 || (remote_type()==REMOTETYPE_H300_NONLCD) 303 || (remote_type()==REMOTETYPE_H300_NONLCD)
265#endif 304#endif
266 ) 305 )
267 queue_post(&button_queue, btn, data); 306 button_try_post(btn, data);
268 else 307 else
269 skip_remote_release = true; 308 skip_remote_release = true;
270 } 309 }
@@ -275,11 +314,11 @@ static void button_tick(void)
275 || (btn & BUTTON_REMOTE) 314 || (btn & BUTTON_REMOTE)
276#endif 315#endif
277 ) 316 )
278 queue_post(&button_queue, btn, data); 317 button_try_post(btn, data);
279 else 318 else
280 skip_release = true; 319 skip_release = true;
281#else /* no backlight, nothing to skip */ 320#else /* no backlight, nothing to skip */
282 queue_post(&button_queue, btn, data); 321 button_try_post(btn, data);
283#endif 322#endif
284 post = false; 323 post = false;
285 } 324 }
@@ -350,12 +389,6 @@ long button_get(bool block)
350 { 389 {
351 queue_wait(&button_queue, &ev); 390 queue_wait(&button_queue, &ev);
352 391
353#if 0
354 /* Ignore if the event was too old and for simplicity, just
355 * wait for a new button_get() request. */
356 if (current_tick - ev.tick > MAX_EVENT_AGE)
357 return BUTTON_NONE;
358#endif
359 button_data = ev.data; 392 button_data = ev.data;
360 return ev.id; 393 return ev.id;
361 } 394 }