diff options
author | Marcin Bukat <marcin.bukat@gmail.com> | 2010-08-23 19:56:17 +0000 |
---|---|---|
committer | Marcin Bukat <marcin.bukat@gmail.com> | 2010-08-23 19:56:17 +0000 |
commit | 8d5f159687b6abf3b5ad6b1681701a1b80423d92 (patch) | |
tree | 7d81f979b3eb106defe50036e1915b5649fdcb0c /firmware/target/arm | |
parent | 1994df6844d9b478f2199d63e70e88996e3b4096 (diff) | |
download | rockbox-8d5f159687b6abf3b5ad6b1681701a1b80423d92.tar.gz rockbox-8d5f159687b6abf3b5ad6b1681701a1b80423d92.zip |
Implement WHEEL_ACCELERATION for Ipod mini 1G based on code for 1G/2G.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27865 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/ipod/button-mini1g.c | 172 |
1 files changed, 129 insertions, 43 deletions
diff --git a/firmware/target/arm/ipod/button-mini1g.c b/firmware/target/arm/ipod/button-mini1g.c index 5831cdfc31..d4a75c90d8 100644 --- a/firmware/target/arm/ipod/button-mini1g.c +++ b/firmware/target/arm/ipod/button-mini1g.c | |||
@@ -40,63 +40,150 @@ | |||
40 | #include "power.h" | 40 | #include "power.h" |
41 | #include "powermgmt.h" | 41 | #include "powermgmt.h" |
42 | 42 | ||
43 | #define WHEELCLICKS_PER_ROTATION 96 | ||
44 | #define WHEEL_BASE_SENSITIVITY 6 /* Compute every ... clicks */ | ||
45 | #define WHEEL_REPEAT_VELOCITY 45 /* deg/s */ | ||
46 | #define WHEEL_SMOOTHING_VELOCITY 100 /* deg/s */ | ||
47 | |||
43 | /* Variable to use for setting button status in interrupt handler */ | 48 | /* Variable to use for setting button status in interrupt handler */ |
44 | int int_btn = BUTTON_NONE; | 49 | int int_btn = BUTTON_NONE; |
45 | #ifdef HAVE_WHEEL_POSITION | ||
46 | static int wheel_position = -1; | ||
47 | static bool send_events = true; | ||
48 | #endif | ||
49 | 50 | ||
50 | static void handle_scroll_wheel(int new_scroll, int was_hold) | 51 | static void handle_scroll_wheel(int new_scroll) |
51 | { | 52 | { |
52 | int wheel_keycode = BUTTON_NONE; | 53 | static const signed char scroll_state[4][4] = { |
53 | static int prev_scroll = -1; | ||
54 | static int direction = 0; | ||
55 | static int count = 0; | ||
56 | static int scroll_state[4][4] = { | ||
57 | {0, 1, -1, 0}, | 54 | {0, 1, -1, 0}, |
58 | {-1, 0, 0, 1}, | 55 | {-1, 0, 0, 1}, |
59 | {1, 0, 0, -1}, | 56 | {1, 0, 0, -1}, |
60 | {0, -1, 1, 0} | 57 | {0, -1, 1, 0} |
61 | }; | 58 | }; |
62 | 59 | ||
60 | static int prev_scroll = -1; | ||
61 | static int direction = 0; | ||
62 | static int count = 0; | ||
63 | static long next_backlight_on = 0; | ||
64 | |||
65 | int wheel_keycode = BUTTON_NONE; | ||
66 | int scroll; | ||
67 | |||
68 | static unsigned long wheel_delta = 1ul << 24; | ||
69 | static unsigned long wheel_velocity = 0; | ||
70 | static unsigned long last_wheel_usec = 0; | ||
71 | static int prev_keypost = BUTTON_NONE; | ||
72 | |||
73 | unsigned long usec; | ||
74 | unsigned long v; | ||
75 | |||
63 | if ( prev_scroll == -1 ) { | 76 | if ( prev_scroll == -1 ) { |
64 | prev_scroll = new_scroll; | 77 | prev_scroll = new_scroll; |
78 | return; | ||
65 | } | 79 | } |
66 | else if (direction != scroll_state[prev_scroll][new_scroll]) { | 80 | |
67 | direction = scroll_state[prev_scroll][new_scroll]; | 81 | scroll = scroll_state[prev_scroll][new_scroll]; |
82 | prev_scroll = new_scroll; | ||
83 | |||
84 | if (direction != scroll) { | ||
85 | /* direction reversal or was hold - reset all */ | ||
86 | direction = scroll; | ||
68 | count = 0; | 87 | count = 0; |
88 | prev_keypost = BUTTON_NONE; | ||
89 | wheel_velocity = 0; | ||
90 | wheel_delta = 1ul << 24; | ||
91 | return; | ||
69 | } | 92 | } |
70 | else if (!was_hold) { | 93 | |
94 | /* poke backlight every 1/4s of activity */ | ||
95 | if (TIME_AFTER(current_tick, next_backlight_on)) { | ||
71 | backlight_on(); | 96 | backlight_on(); |
72 | reset_poweroff_timer(); | 97 | reset_poweroff_timer(); |
73 | if (++count == 6) { /* reduce sensitivity */ | 98 | next_backlight_on = current_tick + HZ/4; |
74 | count = 0; | 99 | } |
75 | /* Mini 1st Gen wheel has inverse direction mapping | 100 | |
76 | * compared to 1st..3rd Gen wheel. */ | 101 | if (++count < WHEEL_BASE_SENSITIVITY) |
77 | switch (direction) { | 102 | return; |
78 | case 1: | 103 | |
79 | wheel_keycode = BUTTON_SCROLL_FWD; | 104 | count = 0; |
80 | break; | 105 | /* Mini 1st Gen wheel has inverse direction mapping |
81 | case -1: | 106 | * compared to 1st..3rd Gen wheel. */ |
82 | wheel_keycode = BUTTON_SCROLL_BACK; | 107 | switch (direction) { |
83 | break; | 108 | case 1: |
84 | default: | 109 | wheel_keycode = BUTTON_SCROLL_FWD; |
85 | /* only happens if we get out of sync */ | 110 | break; |
86 | break; | 111 | case -1: |
87 | } | 112 | wheel_keycode = BUTTON_SCROLL_BACK; |
113 | break; | ||
114 | default: | ||
115 | /* only happens if we get out of sync */ | ||
116 | break; | ||
117 | } | ||
118 | |||
119 | /* have a keycode */ | ||
120 | |||
121 | usec = USEC_TIMER; | ||
122 | v = usec - last_wheel_usec; | ||
123 | |||
124 | /* calculate deg/s based upon sensitivity-adjusted interrupt period */ | ||
125 | |||
126 | if ((long)v <= 0) { | ||
127 | /* timer wrapped (no activity for awhile), skip acceleration */ | ||
128 | v = 0; | ||
129 | wheel_delta = 1ul << 24; | ||
130 | } | ||
131 | else { | ||
132 | if (v > 0xfffffffful/WHEELCLICKS_PER_ROTATION) { | ||
133 | v = 0xfffffffful/WHEELCLICKS_PER_ROTATION; /* check overflow below */ | ||
88 | } | 134 | } |
135 | |||
136 | v = 360000000ul*WHEEL_BASE_SENSITIVITY / (v*WHEELCLICKS_PER_ROTATION); | ||
137 | |||
138 | if (v > 0xfffffful) | ||
139 | v = 0xfffffful; /* limit to 24 bits */ | ||
89 | } | 140 | } |
90 | if (wheel_keycode != BUTTON_NONE && queue_empty(&button_queue)) | 141 | |
91 | queue_post(&button_queue, wheel_keycode, 0); | 142 | if (v < WHEEL_SMOOTHING_VELOCITY) { |
92 | prev_scroll = new_scroll; | 143 | /* very slow - no smoothing */ |
144 | wheel_velocity = v; | ||
145 | /* ensure backlight never gets stuck for an extended period if tick | ||
146 | * wrapped such that next poke is very far ahead */ | ||
147 | next_backlight_on = current_tick - 1; | ||
148 | } | ||
149 | else { | ||
150 | /* some velocity filtering to smooth things out */ | ||
151 | wheel_velocity = (7*wheel_velocity + v) / 8; | ||
152 | } | ||
153 | |||
154 | if (queue_empty(&button_queue)) { | ||
155 | int key = wheel_keycode; | ||
156 | |||
157 | if (v >= WHEEL_REPEAT_VELOCITY && prev_keypost == key) { | ||
158 | /* quick enough and same key is being posted more than once in a | ||
159 | * row - generate repeats - use unsmoothed v to guage */ | ||
160 | key |= BUTTON_REPEAT; | ||
161 | } | ||
162 | |||
163 | prev_keypost = wheel_keycode; | ||
164 | |||
165 | /* post wheel keycode with wheel data */ | ||
166 | queue_post(&button_queue, key, | ||
167 | (wheel_velocity >= WHEEL_ACCEL_START ? (1ul << 31) : 0) | ||
168 | | wheel_delta | wheel_velocity); | ||
169 | /* message posted - reset delta */ | ||
170 | wheel_delta = 1ul << 24; | ||
171 | } | ||
172 | else { | ||
173 | /* skipped post - increment delta and limit to 7 bits */ | ||
174 | wheel_delta += 1ul << 24; | ||
175 | |||
176 | if (wheel_delta > (0x7ful << 24)) | ||
177 | wheel_delta = 0x7ful << 24; | ||
178 | } | ||
179 | |||
180 | last_wheel_usec = usec; | ||
93 | } | 181 | } |
94 | 182 | ||
95 | /* mini 1 only, mini 2G uses iPod 4G code */ | 183 | /* mini 1 only, mini 2G uses iPod 4G code */ |
96 | static int ipod_mini_button_read(void) | 184 | static int ipod_mini_button_read(void) |
97 | { | 185 | { |
98 | unsigned char source, wheel_source, state, wheel_state; | 186 | unsigned char source, wheel_source, state, wheel_state; |
99 | static bool was_hold = false; | ||
100 | int btn = BUTTON_NONE; | 187 | int btn = BUTTON_NONE; |
101 | 188 | ||
102 | /* The ipodlinux source had a udelay(250) here, but testing has shown that | 189 | /* The ipodlinux source had a udelay(250) here, but testing has shown that |
@@ -119,9 +206,17 @@ static int ipod_mini_button_read(void) | |||
119 | GPIOA_INT_LEV = ~state; | 206 | GPIOA_INT_LEV = ~state; |
120 | GPIOB_INT_LEV = ~wheel_state; | 207 | GPIOB_INT_LEV = ~wheel_state; |
121 | 208 | ||
209 | /* ack any active interrupts */ | ||
210 | if (source) | ||
211 | GPIOA_INT_CLR = source; | ||
212 | if (wheel_source) | ||
213 | GPIOB_INT_CLR = wheel_source; | ||
214 | |||
215 | if (button_hold()) | ||
216 | return BUTTON_NONE; | ||
217 | |||
122 | /* hold switch causes all outputs to go low */ | 218 | /* hold switch causes all outputs to go low */ |
123 | /* we shouldn't interpret these as key presses */ | 219 | /* we shouldn't interpret these as key presses */ |
124 | if ((state & 0x20)) { | ||
125 | if (!(state & 0x1)) | 220 | if (!(state & 0x1)) |
126 | btn |= BUTTON_SELECT; | 221 | btn |= BUTTON_SELECT; |
127 | if (!(state & 0x2)) | 222 | if (!(state & 0x2)) |
@@ -134,17 +229,8 @@ static int ipod_mini_button_read(void) | |||
134 | btn |= BUTTON_LEFT; | 229 | btn |= BUTTON_LEFT; |
135 | 230 | ||
136 | if (wheel_source & 0x30) { | 231 | if (wheel_source & 0x30) { |
137 | handle_scroll_wheel((wheel_state & 0x30) >> 4, was_hold); | 232 | handle_scroll_wheel((wheel_state & 0x30) >> 4); |
138 | } | 233 | } |
139 | } | ||
140 | |||
141 | was_hold = button_hold(); | ||
142 | |||
143 | /* ack any active interrupts */ | ||
144 | if (source) | ||
145 | GPIOA_INT_CLR = source; | ||
146 | if (wheel_source) | ||
147 | GPIOB_INT_CLR = wheel_source; | ||
148 | 234 | ||
149 | return btn; | 235 | return btn; |
150 | } | 236 | } |