summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2010-08-23 19:56:17 +0000
committerMarcin Bukat <marcin.bukat@gmail.com>2010-08-23 19:56:17 +0000
commit8d5f159687b6abf3b5ad6b1681701a1b80423d92 (patch)
tree7d81f979b3eb106defe50036e1915b5649fdcb0c
parent1994df6844d9b478f2199d63e70e88996e3b4096 (diff)
downloadrockbox-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
-rw-r--r--apps/debug_menu.c6
-rw-r--r--firmware/export/config/ipodmini1g.h6
-rw-r--r--firmware/target/arm/ipod/button-mini1g.c172
3 files changed, 139 insertions, 45 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index ca06907618..59041eb450 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -2584,7 +2584,8 @@ static bool cpu_boost_log(void)
2584} 2584}
2585#endif 2585#endif
2586 2586
2587#if (defined(HAVE_WHEEL_ACCELERATION) && (CONFIG_KEYPAD==IPOD_4G_PAD) && !defined(SIMULATOR)) 2587#if (defined(HAVE_WHEEL_ACCELERATION) && (CONFIG_KEYPAD==IPOD_4G_PAD) \
2588 && !defined(IPOD_MINI) && !defined(SIMULATOR))
2588extern bool wheel_is_touched; 2589extern bool wheel_is_touched;
2589extern int old_wheel_value; 2590extern int old_wheel_value;
2590extern int new_wheel_value; 2591extern int new_wheel_value;
@@ -2790,7 +2791,8 @@ static const struct the_menu_item menuitems[] = {
2790#ifdef CPU_BOOST_LOGGING 2791#ifdef CPU_BOOST_LOGGING
2791 {"cpu_boost log",cpu_boost_log}, 2792 {"cpu_boost log",cpu_boost_log},
2792#endif 2793#endif
2793#if (defined(HAVE_WHEEL_ACCELERATION) && (CONFIG_KEYPAD==IPOD_4G_PAD) && !defined(SIMULATOR)) 2794#if (defined(HAVE_WHEEL_ACCELERATION) && (CONFIG_KEYPAD==IPOD_4G_PAD) \
2795 && !defined(IPOD_MINI) && !defined(SIMULATOR))
2794 {"Debug scrollwheel", dbg_scrollwheel }, 2796 {"Debug scrollwheel", dbg_scrollwheel },
2795#endif 2797#endif
2796 }; 2798 };
diff --git a/firmware/export/config/ipodmini1g.h b/firmware/export/config/ipodmini1g.h
index 121a7fc801..85e4597b9f 100644
--- a/firmware/export/config/ipodmini1g.h
+++ b/firmware/export/config/ipodmini1g.h
@@ -79,6 +79,12 @@
79#define CONFIG_KEYPAD IPOD_4G_PAD 79#define CONFIG_KEYPAD IPOD_4G_PAD
80 80
81#define HAVE_SCROLLWHEEL 81#define HAVE_SCROLLWHEEL
82/* define to activate advanced wheel acceleration code */
83#define HAVE_WHEEL_ACCELERATION
84/* define from which rotation speed [degree/sec] on the acceleration starts */
85#define WHEEL_ACCEL_START 360
86/* define type of acceleration (1 = ^2, 2 = ^3, 3 = ^4) */
87#define WHEEL_ACCELERATION 1
82 88
83/* Define this to enable morse code input */ 89/* Define this to enable morse code input */
84#define HAVE_MORSE_INPUT 90#define HAVE_MORSE_INPUT
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 */
44int int_btn = BUTTON_NONE; 49int 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
50static void handle_scroll_wheel(int new_scroll, int was_hold) 51static 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 */
96static int ipod_mini_button_read(void) 184static 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}