summaryrefslogtreecommitdiff
path: root/firmware/target/arm
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 /firmware/target/arm
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
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/as3525/sansa-e200v2/button-e200v2.c175
1 files changed, 60 insertions, 115 deletions
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) */