summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2009-04-13 14:08:43 +0000
committerThomas Martitz <kugel@rockbox.org>2009-04-13 14:08:43 +0000
commitc48f4c6be480c6653c0dc76c64ba86df564ad0bf (patch)
treeebdb6fb09af7c484d3de6030d5adddebd7d383dc
parente5e41c3a82bfd546a686a758ca3a382d0173a3e2 (diff)
downloadrockbox-c48f4c6be480c6653c0dc76c64ba86df564ad0bf.tar.gz
rockbox-c48f4c6be480c6653c0dc76c64ba86df564ad0bf.zip
FS#10127 - Sansa e200v2: wrapping in menus by Dustin Skoracki and me. Implements better list wrap handling mostly by taking Fuze's scrollwheel driver, but with tweaks w.r.t. to BUTTON_REPEAT to make it work on the e200v2.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20700 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--docs/CREDITS1
-rw-r--r--firmware/target/arm/as3525/sansa-e200v2/button-e200v2.c175
2 files changed, 61 insertions, 115 deletions
diff --git a/docs/CREDITS b/docs/CREDITS
index a6479b7513..c67b349769 100644
--- a/docs/CREDITS
+++ b/docs/CREDITS
@@ -460,6 +460,7 @@ Sasha Khamkov
460Kai Posadowsky 460Kai Posadowsky
461Jack Halpin 461Jack Halpin
462Johannes Schwarz 462Johannes Schwarz
463Dustin Skoracki
463 464
464The libmad team 465The libmad team
465The wavpack team 466The wavpack team
diff --git a/firmware/target/arm/as3525/sansa-e200v2/button-e200v2.c b/firmware/target/arm/as3525/sansa-e200v2/button-e200v2.c
index 85288d2cc1..021110c7c6 100644
--- a/firmware/target/arm/as3525/sansa-e200v2/button-e200v2.c
+++ b/firmware/target/arm/as3525/sansa-e200v2/button-e200v2.c
@@ -26,28 +26,15 @@
26#include "backlight.h" 26#include "backlight.h"
27#include "powermgmt.h" 27#include "powermgmt.h"
28 28
29#define WHEEL_REPEAT_INTERVAL 300000
30#define WHEEL_FAST_ON_INTERVAL 20000
31#define WHEEL_FAST_OFF_INTERVAL 60000
32#define WHEELCLICKS_PER_ROTATION 48 /* wheelclicks per full rotation */
33 29
34static short _dbop_din;
35/* Clickwheel */
36static unsigned int old_wheel_value = 0;
37static unsigned int wheel_repeat = BUTTON_NONE;
38static unsigned int wheel_click_count = 0;
39static unsigned int wheel_delta = 0;
40static int wheel_fast_mode = 0;
41static unsigned long last_wheel_usec = 0;
42static unsigned long wheel_velocity = 0;
43static long last_wheel_post = 0;
44static long next_backlight_on = 0;
45/* Buttons */
46static bool hold_button = false; 30static bool hold_button = false;
47#ifndef BOOTLOADER 31#ifndef BOOTLOADER
48static bool hold_button_old = false; 32static bool hold_button_old = false;
49#endif 33#endif
34static short _dbop_din = 0;
50 35
36#define WHEEL_REPEAT_INTERVAL (HZ/5)
37/* in the lcd driver */
51extern bool lcd_button_support(void); 38extern bool lcd_button_support(void);
52 39
53void button_init_device(void) 40void button_init_device(void)
@@ -60,23 +47,38 @@ bool button_hold(void)
60 return hold_button; 47 return hold_button;
61} 48}
62 49
50#if !defined(BOOTLOADER) && defined(HAVE_SCROLLWHEEL)
63static void scrollwheel(short dbop_din) 51static void scrollwheel(short dbop_din)
64{ 52{
65 static const unsigned char wheel_tbl[2][4] = 53 /* current wheel values, parsed from dbop and the resulting button */
66 { 54 unsigned wheel_value = 0;
67 { 2, 0, 3, 1 }, /* Clockwise rotation */ 55 unsigned btn = BUTTON_NONE;
68 { 1, 3, 0, 2 }, /* Counter-clockwise */ 56 /* old wheel values */
69 }; 57 static unsigned old_wheel_value = 0;
70 /* Read wheel 58 static unsigned wheel_repeat = BUTTON_NONE;
59
60 /* getting BUTTON_REPEAT works like this: Remember when the btn value was
61 * posted to the button_queue last, and if it was recent enough, generate
62 * BUTTON_REPEAT
63 */
64 static long last_wheel_post = 0;
65 /* Repeat is used for the scrollwheel acceleration. If high enough then
66 * jump over some items */
67 static unsigned repeat = 0;
68 /* we omit 1 of 2 posts to the button_queue, that works better, so count */
69 static int counter = 0;
70 /* Read wheel
71 * Bits 13 and 14 of DBOP_DIN change as follows: 71 * Bits 13 and 14 of DBOP_DIN change as follows:
72 * Clockwise rotation 00 -> 01 -> 11 -> 10 -> 00 72 * Clockwise rotation 00 -> 01 -> 11 -> 10 -> 00
73 * Counter-clockwise 00 -> 10 -> 11 -> 01 -> 00 73 * Counter-clockwise 00 -> 10 -> 11 -> 01 -> 00
74 */ 74 */
75 75 static const unsigned char wheel_tbl[2][4] =
76 /* did the wheel value change? */ 76 {
77 unsigned int btn = BUTTON_NONE; 77 { 2, 0, 3, 1 }, /* Clockwise rotation */
78 78 { 1, 3, 0, 2 }, /* Counter-clockwise */
79 unsigned wheel_value = dbop_din & (1<<13|1<<14); 79 };
80
81 wheel_value = dbop_din & (1<<13|1<<14);
80 wheel_value >>= 13; 82 wheel_value >>= 13;
81 83
82 if (old_wheel_value == wheel_tbl[0][wheel_value]) 84 if (old_wheel_value == wheel_tbl[0][wheel_value])
@@ -86,101 +88,47 @@ static void scrollwheel(short dbop_din)
86 88
87 if (btn != BUTTON_NONE) 89 if (btn != BUTTON_NONE)
88 { 90 {
89 int repeat = 1; /* assume repeat */
90 unsigned long usec = TIMER1_VALUE;
91 unsigned v = (usec - last_wheel_usec) & 0x7fffffff;
92
93 v = (v>0) ? 1000000 / v : 0; /* clicks/sec = 1000000 * +clicks/usec */
94 v = (v>0xffffff) ? 0xffffff : v; /* limit to 24 bit */
95
96 /* some velocity filtering to smooth things out */
97 wheel_velocity = (7*wheel_velocity + v) / 8;
98
99 if (btn != wheel_repeat) 91 if (btn != wheel_repeat)
100 { 92 {
101 /* direction reversals nullify all fast mode states */ 93 /* direction reversals nullify repeats */
102 wheel_repeat = btn; 94 wheel_repeat = btn;
103 repeat = 95 repeat = counter = 0;
104 wheel_fast_mode =
105 wheel_velocity =
106 wheel_click_count = 0;
107 }
108
109 if (wheel_fast_mode != 0)
110 {
111 /* fast OFF happens immediately when velocity drops below
112 threshold */
113 if (TIME_AFTER(usec,
114 last_wheel_usec + WHEEL_FAST_OFF_INTERVAL))
115 {
116 /* moving out of fast mode */
117 wheel_fast_mode = 0;
118 /* reset velocity */
119 wheel_velocity = 0;
120 /* wheel_delta is always 1 in slow mode */
121 wheel_delta = 1;
122 }
123 } 96 }
124 else 97 if (btn != BUTTON_NONE)
125 { 98 {
126 /* fast ON gets filtered to avoid inadvertent jumps to fast mode */ 99 /* wheel_delta will cause lists to jump over items,
127 if (repeat && wheel_velocity > 1000000/WHEEL_FAST_ON_INTERVAL) 100 * we want this for fast scrolling, but we must keep it accurate
128 { 101 * for slow scrolling */
129 /* moving into fast mode */ 102 int wheel_delta = 0;
130 wheel_fast_mode = 1 << 31; 103 /* generate repeats if quick enough, scroll slightly too*/
131 wheel_click_count = 0; 104 if (TIME_BEFORE(current_tick, last_wheel_post + WHEEL_REPEAT_INTERVAL))
132 wheel_velocity = 1000000/WHEEL_FAST_OFF_INTERVAL;
133 }
134 else if (++wheel_click_count < 2)
135 { 105 {
136 btn = BUTTON_NONE; 106 btn |= BUTTON_REPEAT;
107 wheel_delta = repeat>>2;
137 } 108 }
138 109
139 /* wheel_delta is always 1 in slow mode */ 110 repeat += 2;
140 wheel_delta = 1;
141 }
142 111
143 if (TIME_AFTER(current_tick, next_backlight_on) || 112 /* the wheel is more reliable if we don't send ever change,
144 v <= 4) 113 * every 2th is basically one "physical click" is
145 { 114 * 1 item in the rockbox menus */
146 /* poke backlight to turn it on or maintain it no more often 115 if (++counter >= 2 && queue_empty(&button_queue))
147 than every 1/4 second*/ 116 {
148 next_backlight_on = current_tick + HZ/4; 117 buttonlight_on();
149 backlight_on(); 118 backlight_on();
150 buttonlight_on(); 119 queue_post(&button_queue, btn, ((wheel_delta+1)<<24));
151 reset_poweroff_timer(); 120 /* message posted - reset count & last post to the queue */
121 counter = 0;
122 last_wheel_post = current_tick;
123 }
152 } 124 }
153
154 if (btn != BUTTON_NONE)
155 {
156 wheel_click_count = 0;
157
158 /* generate repeats if quick enough */
159 if (repeat && TIME_BEFORE(usec,
160 last_wheel_post + WHEEL_REPEAT_INTERVAL))
161 btn |= BUTTON_REPEAT;
162
163 last_wheel_post = usec;
164
165 if (queue_empty(&button_queue))
166 {
167 queue_post(&button_queue, btn, wheel_fast_mode |
168 (wheel_delta << 24) |
169 wheel_velocity*360/WHEELCLICKS_PER_ROTATION);
170 /* message posted - reset delta */
171 wheel_delta = 1;
172 }
173 else
174 {
175 /* skipped post - increment delta */
176 if (++wheel_delta > 0x7f)
177 wheel_delta = 0x7f;
178 }
179 }
180 last_wheel_usec = usec;
181 } 125 }
126 if (repeat > 0)
127 repeat--;
128
182 old_wheel_value = wheel_value; 129 old_wheel_value = wheel_value;
183} 130}
131#endif /* !defined(BOOTLOADER) && defined(HAVE_SCROLLWHEEL) */
184 132
185short button_read_dbop(void) 133short button_read_dbop(void)
186{ 134{
@@ -205,8 +153,9 @@ short button_read_dbop(void)
205 DBOP_TIMPOL_23 = 0xa167e06f; /* Set Timing & Polarity regs 2 & 3 */ 153 DBOP_TIMPOL_23 = 0xa167e06f; /* Set Timing & Polarity regs 2 & 3 */
206 DBOP_CTRL |= (1<<16); /* Enable output (0:write disable) */ 154 DBOP_CTRL |= (1<<16); /* Enable output (0:write disable) */
207 DBOP_CTRL &= ~(1<<19); /* Tri-state when no active write */ 155 DBOP_CTRL &= ~(1<<19); /* Tri-state when no active write */
208 156#if !defined(BOOTLOADER) && defined(HAVE_SCROLLWHEEL)
209 scrollwheel(_dbop_din); 157 scrollwheel(_dbop_din);
158#endif
210 return _dbop_din; 159 return _dbop_din;
211} 160}
212 161
@@ -241,10 +190,6 @@ int button_read_device(void)
241 if (!(dbop & (1<<15))) 190 if (!(dbop & (1<<15)))
242 btn |= BUTTON_REC; 191 btn |= BUTTON_REC;
243 192
244 /* handle wheel */
245 int wheel_value = dbop & (1<<13|1<<14);
246 wheel_value >>= 13;
247
248 /* Set afsel, so that we can read our buttons */ 193 /* Set afsel, so that we can read our buttons */
249 GPIOC_AFSEL &= ~(1<<2|1<<3|1<<4|1<<5|1<<6); 194 GPIOC_AFSEL &= ~(1<<2|1<<3|1<<4|1<<5|1<<6);
250 /* set dir so we can read our buttons (but reset the C pins first) */ 195 /* set dir so we can read our buttons (but reset the C pins first) */