summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-06-19 20:09:37 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-06-19 20:09:37 +0000
commitb7a8935dffe82ceb40b63d7c6e97017a6dfac064 (patch)
treead05207c4c7fe5ba9abc7ea034b04ef1d1274f87
parent86767233001fd9b381f5283815378bcc1e9dd732 (diff)
downloadrockbox-b7a8935dffe82ceb40b63d7c6e97017a6dfac064.tar.gz
rockbox-b7a8935dffe82ceb40b63d7c6e97017a6dfac064.zip
iPod 3G: Implement wheel acceleration and repeats. Chosen settings feel pretty decent but can be tweaked.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26962 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/config/ipod3g.h7
-rw-r--r--firmware/target/arm/ipod/button-1g-3g.c140
2 files changed, 140 insertions, 7 deletions
diff --git a/firmware/export/config/ipod3g.h b/firmware/export/config/ipod3g.h
index 471cb58b7f..ee59a1bc76 100644
--- a/firmware/export/config/ipod3g.h
+++ b/firmware/export/config/ipod3g.h
@@ -79,7 +79,14 @@
79 79
80#define CONFIG_KEYPAD IPOD_3G_PAD 80#define CONFIG_KEYPAD IPOD_3G_PAD
81 81
82/* define this if the unit uses a scrollwheel for navigation */
82#define HAVE_SCROLLWHEEL 83#define HAVE_SCROLLWHEEL
84/* define to activate advanced wheel acceleration code */
85#define HAVE_WHEEL_ACCELERATION
86/* define from which rotation speed [degree/sec] on the acceleration starts */
87#define WHEEL_ACCEL_START 360
88/* define type of acceleration (1 = ^2, 2 = ^3, 3 = ^4) */
89#define WHEEL_ACCELERATION 1
83 90
84/* Define this to enable morse code input */ 91/* Define this to enable morse code input */
85#define HAVE_MORSE_INPUT 92#define HAVE_MORSE_INPUT
diff --git a/firmware/target/arm/ipod/button-1g-3g.c b/firmware/target/arm/ipod/button-1g-3g.c
index 6c2a8c059c..044e887453 100644
--- a/firmware/target/arm/ipod/button-1g-3g.c
+++ b/firmware/target/arm/ipod/button-1g-3g.c
@@ -49,6 +49,138 @@ static int int_btn = BUTTON_NONE;
49#define WHEEL_TIMEOUT (HZ/4) 49#define WHEEL_TIMEOUT (HZ/4)
50#endif 50#endif
51 51
52#ifdef IPOD_3G
53#define WHEELCLICKS_PER_ROTATION 96
54#define WHEEL_BASE_SENSITIVITY 6 /* Compute every ... clicks */
55#define WHEEL_REPEAT_VELOCITY 45 /* deg/s */
56#define WHEEL_SMOOTHING_VELOCITY 100 /* deg/s */
57
58static void handle_scroll_wheel(int new_scroll, int was_hold)
59{
60 static const signed char scroll_state[4][4] = {
61 {0, 1, -1, 0},
62 {-1, 0, 0, 1},
63 {1, 0, 0, -1},
64 {0, -1, 1, 0}
65 };
66
67 static int prev_scroll = 0;
68 static int direction = 0;
69 static int count = 0;
70 static long next_backlight_on = 0;
71
72 static unsigned long last_wheel_usec = 0;
73 static unsigned long wheel_delta = 1ul << 24;
74 static unsigned long wheel_velocity = 0;
75
76 int wheel_keycode = BUTTON_NONE;
77 int scroll = scroll_state[prev_scroll][new_scroll];
78 unsigned long usec;
79 unsigned long v;
80
81 prev_scroll = new_scroll;
82
83 if (direction != scroll) {
84 /* direction reversal - reset all */
85 direction = scroll;
86 wheel_velocity = 0;
87 wheel_delta = 1ul << 24;
88 count = 0;
89 }
90
91 if (was_hold) {
92 /* hold - reset all */
93 wheel_velocity = 0;
94 wheel_delta = 1ul << 24;
95 count = 0;
96 return;
97 }
98
99 /* poke backlight every 1/4s of activity */
100 if (TIME_AFTER(current_tick, next_backlight_on)) {
101 backlight_on();
102 reset_poweroff_timer();
103 next_backlight_on = current_tick + HZ/4;
104 }
105
106 /* has wheel travelled far enough? */
107 if (++count < WHEEL_BASE_SENSITIVITY) {
108 return;
109 }
110
111 /* reset travel count and do calculations */
112 count = 0;
113
114 /* 1st..3rd Gen wheel has inverse direction mapping
115 * compared to Mini 1st Gen wheel. */
116 switch (direction) {
117 case 1:
118 wheel_keycode = BUTTON_SCROLL_BACK;
119 break;
120 case -1:
121 wheel_keycode = BUTTON_SCROLL_FWD;
122 break;
123 default:
124 /* only happens if we get out of sync */
125 return;
126 }
127
128 /* have a keycode */
129
130 usec = USEC_TIMER;
131 v = usec - last_wheel_usec;
132
133 /* calculate deg/s based upon sensitivity-adjusted interrupt period */
134
135 if ((long)v <= 0) {
136 /* timer wrapped (no activity for awhile), skip acceleration */
137 v = 0;
138 wheel_delta = 1ul << 24;
139 }
140 else {
141 if (v > 0xfffffffful/WHEELCLICKS_PER_ROTATION) {
142 v = 0xfffffffful/WHEELCLICKS_PER_ROTATION; /* check overflow below */
143 }
144
145 v = 360000000ul*WHEEL_BASE_SENSITIVITY / (v*WHEELCLICKS_PER_ROTATION);
146
147 if (v > 0xfffffful)
148 v = 0xfffffful; /* limit to 24 bits */
149 }
150
151 if (v < WHEEL_SMOOTHING_VELOCITY) {
152 /* very slow - no smoothing */
153 wheel_velocity = v;
154 }
155 else {
156 /* some velocity filtering to smooth things out */
157 wheel_velocity = (7*wheel_velocity + v) / 8;
158 }
159
160 if (v >= WHEEL_REPEAT_VELOCITY) {
161 /* quick enough - generate repeats - use unsmoothed v to guage */
162 wheel_keycode |= BUTTON_REPEAT;
163 }
164
165 if (queue_empty(&button_queue)) {
166 /* post wheel keycode with wheel data */
167 queue_post(&button_queue, wheel_keycode,
168 (wheel_velocity >= WHEEL_ACCEL_START ? (1ul << 31) : 0)
169 | wheel_delta | wheel_velocity);
170 /* message posted - reset delta */
171 wheel_delta = 1ul << 24;
172 }
173 else {
174 /* skipped post - increment delta and limit to 7 bits */
175 wheel_delta += 1ul << 24;
176
177 if (wheel_delta > (0x7ful << 24))
178 wheel_delta = 0x7ful << 24;
179 }
180
181 last_wheel_usec = usec;
182}
183#else
52static void handle_scroll_wheel(int new_scroll, int was_hold) 184static void handle_scroll_wheel(int new_scroll, int was_hold)
53{ 185{
54 int wheel_keycode = BUTTON_NONE; 186 int wheel_keycode = BUTTON_NONE;
@@ -93,6 +225,7 @@ static void handle_scroll_wheel(int new_scroll, int was_hold)
93 queue_post(&button_queue, wheel_keycode, 0); 225 queue_post(&button_queue, wheel_keycode, 0);
94 prev_scroll = new_scroll; 226 prev_scroll = new_scroll;
95} 227}
228#endif /* IPOD_3G */
96 229
97static int ipod_3g_button_read(void) 230static int ipod_3g_button_read(void)
98{ 231{
@@ -100,13 +233,6 @@ static int ipod_3g_button_read(void)
100 static bool was_hold = false; 233 static bool was_hold = false;
101 int btn = BUTTON_NONE; 234 int btn = BUTTON_NONE;
102 235
103#ifdef IPOD_3G
104 /* The following delay was 250 in the ipodlinux source,
105 * but 50 seems to work fine. 250 causes the wheel to stop
106 * working when spinning it real fast. */
107 udelay(50);
108#endif
109
110 /* get source of interupts */ 236 /* get source of interupts */
111 source = GPIOA_INT_STAT; 237 source = GPIOA_INT_STAT;
112 238