diff options
author | Thomas Martitz <kugel@rockbox.org> | 2009-04-13 14:08:43 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2009-04-13 14:08:43 +0000 |
commit | c48f4c6be480c6653c0dc76c64ba86df564ad0bf (patch) | |
tree | ebdb6fb09af7c484d3de6030d5adddebd7d383dc /firmware | |
parent | e5e41c3a82bfd546a686a758ca3a382d0173a3e2 (diff) | |
download | rockbox-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')
-rw-r--r-- | firmware/target/arm/as3525/sansa-e200v2/button-e200v2.c | 175 |
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 | ||
34 | static short _dbop_din; | ||
35 | /* Clickwheel */ | ||
36 | static unsigned int old_wheel_value = 0; | ||
37 | static unsigned int wheel_repeat = BUTTON_NONE; | ||
38 | static unsigned int wheel_click_count = 0; | ||
39 | static unsigned int wheel_delta = 0; | ||
40 | static int wheel_fast_mode = 0; | ||
41 | static unsigned long last_wheel_usec = 0; | ||
42 | static unsigned long wheel_velocity = 0; | ||
43 | static long last_wheel_post = 0; | ||
44 | static long next_backlight_on = 0; | ||
45 | /* Buttons */ | ||
46 | static bool hold_button = false; | 30 | static bool hold_button = false; |
47 | #ifndef BOOTLOADER | 31 | #ifndef BOOTLOADER |
48 | static bool hold_button_old = false; | 32 | static bool hold_button_old = false; |
49 | #endif | 33 | #endif |
34 | static short _dbop_din = 0; | ||
50 | 35 | ||
36 | #define WHEEL_REPEAT_INTERVAL (HZ/5) | ||
37 | /* in the lcd driver */ | ||
51 | extern bool lcd_button_support(void); | 38 | extern bool lcd_button_support(void); |
52 | 39 | ||
53 | void button_init_device(void) | 40 | void 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) | ||
63 | static void scrollwheel(short dbop_din) | 51 | static 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 | ||
185 | short button_read_dbop(void) | 133 | short 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) */ |