diff options
Diffstat (limited to 'firmware/target/arm/ipod/button-1g-3g.c')
-rw-r--r-- | firmware/target/arm/ipod/button-1g-3g.c | 140 |
1 files changed, 133 insertions, 7 deletions
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 | |||
58 | static 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 | ||
52 | static void handle_scroll_wheel(int new_scroll, int was_hold) | 184 | static 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 | ||
97 | static int ipod_3g_button_read(void) | 230 | static 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 | ||