diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/button-e200.c | 270 | ||||
-rw-r--r-- | firmware/target/arm/system-pp502x.c | 30 |
2 files changed, 202 insertions, 98 deletions
diff --git a/firmware/target/arm/sandisk/sansa-e200/button-e200.c b/firmware/target/arm/sandisk/sansa-e200/button-e200.c index 028a76f7a8..168332e3c1 100644 --- a/firmware/target/arm/sandisk/sansa-e200/button-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/button-e200.c | |||
@@ -23,26 +23,193 @@ | |||
23 | #include "button.h" | 23 | #include "button.h" |
24 | #include "backlight.h" | 24 | #include "backlight.h" |
25 | 25 | ||
26 | static unsigned int old_wheel_value = 0; | 26 | #define WHEEL_REPEAT_INTERVAL 30 |
27 | static unsigned int wheel_repeat = BUTTON_NONE; | 27 | #define WHEEL_FAST_ON_INTERVAL 2 |
28 | #define WHEEL_FAST_OFF_INTERVAL 6 | ||
29 | |||
30 | /* Clickwheel */ | ||
31 | static unsigned int old_wheel_value = 0; | ||
32 | static unsigned int wheel_repeat = BUTTON_NONE; | ||
33 | static unsigned int wheel_click_count = 0; | ||
34 | static int wheel_fast_mode = 0; | ||
35 | static unsigned long last_wheel_tick = 0; | ||
36 | static unsigned long last_wheel_post = 0; | ||
37 | #ifndef BOOTLOADER | ||
38 | static unsigned long next_backlight_on = 0; | ||
39 | #endif | ||
40 | /* Buttons */ | ||
41 | static bool hold_button = false; | ||
42 | static bool hold_button_old = false; | ||
43 | static int int_btn = BUTTON_NONE; | ||
28 | 44 | ||
29 | void button_init_device(void) | 45 | void button_init_device(void) |
30 | { | 46 | { |
31 | /* Enable all buttons */ | 47 | /* Enable all buttons */ |
48 | GPIOF_OUTPUT_EN &= ~0xff; | ||
32 | GPIOF_ENABLE |= 0xff; | 49 | GPIOF_ENABLE |= 0xff; |
33 | GPIOH_ENABLE |= 0xc0; | ||
34 | 50 | ||
35 | /* Scrollwheel light - enable control through GPIOG pin 7 and set timeout */ | 51 | /* Scrollwheel light - enable control through GPIOG pin 7 and set timeout */ |
36 | GPIOG_ENABLE = 0x80; | ||
37 | GPIOG_OUTPUT_EN |= 0x80; | 52 | GPIOG_OUTPUT_EN |= 0x80; |
38 | 53 | GPIOG_ENABLE = 0x80; | |
54 | |||
55 | GPIOH_ENABLE |= 0xc0; | ||
56 | GPIOH_OUTPUT_EN &= ~0xc0; | ||
57 | |||
58 | #if 0 | ||
59 | CPU_INT_PRIORITY &= ~HI_MASK; | ||
60 | CPU_HI_INT_PRIORITY &= ~GPIO_MASK; | ||
61 | |||
62 | CPU_INT_CLR = HI_MASK; | ||
63 | CPU_HI_INT_CLR = GPIO_MASK; | ||
64 | #endif | ||
65 | GPIOF_INT_CLR = 0xff; | ||
66 | GPIOH_INT_CLR = 0xc0; | ||
67 | |||
68 | /* Read initial buttons */ | ||
69 | old_wheel_value = GPIOF_INPUT_VAL & 0xff; | ||
70 | GPIOF_INT_LEV = (GPIOF_INT_LEV & ~0xff) | (old_wheel_value ^ 0xff); | ||
71 | hold_button = (GPIOF_INPUT_VAL & 0x80) != 0; | ||
72 | |||
39 | /* Read initial wheel value (bit 6-7 of GPIOH) */ | 73 | /* Read initial wheel value (bit 6-7 of GPIOH) */ |
40 | old_wheel_value = GPIOH_INPUT_VAL & 0xc0; | 74 | old_wheel_value = GPIOH_INPUT_VAL & 0xc0; |
75 | GPIOH_INT_LEV = (GPIOH_INT_LEV & ~0xc0) | (old_wheel_value ^ 0xc0); | ||
76 | |||
77 | GPIOF_INT_EN = 0xff; | ||
78 | GPIOH_INT_EN = 0xc0; | ||
79 | #if 0 | ||
80 | CPU_HI_INT_EN = GPIO_MASK; | ||
81 | CPU_INT_EN = HI_MASK; | ||
82 | #endif | ||
83 | |||
84 | last_wheel_tick = current_tick; | ||
85 | last_wheel_post = current_tick; | ||
41 | } | 86 | } |
42 | 87 | ||
43 | bool button_hold(void) | 88 | bool button_hold(void) |
44 | { | 89 | { |
45 | return (GPIOF_INPUT_VAL & 0x80)?true:false; | 90 | return hold_button; |
91 | } | ||
92 | |||
93 | void clickwheel_int(void) | ||
94 | { | ||
95 | /* Read wheel | ||
96 | * Bits 6 and 7 of GPIOH change as follows: | ||
97 | * Clockwise rotation 01 -> 00 -> 10 -> 11 | ||
98 | * Counter-clockwise 11 -> 10 -> 00 -> 01 | ||
99 | * | ||
100 | * This is equivalent to wheel_value of: | ||
101 | * Clockwise rotation 0x40 -> 0x00 -> 0x80 -> 0xc0 | ||
102 | * Counter-clockwise 0xc0 -> 0x80 -> 0x00 -> 0x40 | ||
103 | */ | ||
104 | static const unsigned char wheel_tbl[2][4] = | ||
105 | { | ||
106 | /* 0x00 0x40 0x80 0xc0 */ /* Wheel value */ | ||
107 | { 0x40, 0xc0, 0x00, 0x80 }, /* Clockwise rotation */ | ||
108 | { 0x80, 0x00, 0xc0, 0x40 }, /* Counter-clockwise */ | ||
109 | }; | ||
110 | |||
111 | unsigned int wheel_value; | ||
112 | |||
113 | GPIOH_INT_CLR = GPIOH_INT_STAT & 0xc0; | ||
114 | |||
115 | wheel_value = GPIOH_INPUT_VAL & 0xc0; | ||
116 | GPIOH_INT_LEV = (GPIOH_INT_LEV & ~0xc0) | (wheel_value ^ 0xc0); | ||
117 | |||
118 | if (!hold_button) | ||
119 | { | ||
120 | unsigned int btn = BUTTON_NONE; | ||
121 | |||
122 | if (old_wheel_value == wheel_tbl[0][wheel_value >> 6]) | ||
123 | btn = BUTTON_SCROLL_DOWN; | ||
124 | else if (old_wheel_value == wheel_tbl[1][wheel_value >> 6]) | ||
125 | btn = BUTTON_SCROLL_UP; | ||
126 | |||
127 | if (btn != BUTTON_NONE) | ||
128 | { | ||
129 | int repeat = 1; | ||
130 | |||
131 | if (btn != wheel_repeat) | ||
132 | { | ||
133 | wheel_repeat = btn; | ||
134 | repeat = | ||
135 | wheel_fast_mode = | ||
136 | wheel_click_count = 0; | ||
137 | } | ||
138 | |||
139 | if (wheel_fast_mode) | ||
140 | { | ||
141 | if (TIME_AFTER(current_tick, | ||
142 | last_wheel_tick + WHEEL_FAST_OFF_INTERVAL)) | ||
143 | { | ||
144 | if (++wheel_click_count < 2) | ||
145 | btn = BUTTON_NONE; | ||
146 | wheel_fast_mode = 0; | ||
147 | } | ||
148 | } | ||
149 | else | ||
150 | { | ||
151 | if (repeat && TIME_BEFORE(current_tick, | ||
152 | last_wheel_tick + WHEEL_FAST_ON_INTERVAL)) | ||
153 | wheel_fast_mode = 1; | ||
154 | else if (++wheel_click_count < 2) | ||
155 | btn = BUTTON_NONE; | ||
156 | } | ||
157 | |||
158 | #ifndef BOOTLOADER | ||
159 | if (TIME_AFTER(current_tick, next_backlight_on)) | ||
160 | { | ||
161 | next_backlight_on = current_tick + HZ/4; | ||
162 | backlight_on(); | ||
163 | button_backlight_on(); | ||
164 | } | ||
165 | #endif | ||
166 | if (btn != BUTTON_NONE) | ||
167 | { | ||
168 | wheel_click_count = 0; | ||
169 | |||
170 | if (repeat && TIME_BEFORE(current_tick, | ||
171 | last_wheel_post + WHEEL_REPEAT_INTERVAL)) | ||
172 | btn |= BUTTON_REPEAT; | ||
173 | |||
174 | last_wheel_post = current_tick; | ||
175 | |||
176 | if (queue_empty(&button_queue)) | ||
177 | queue_post(&button_queue, btn, 0); | ||
178 | } | ||
179 | |||
180 | last_wheel_tick = current_tick; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | old_wheel_value = wheel_value; | ||
185 | } | ||
186 | |||
187 | void button_int(void) | ||
188 | { | ||
189 | unsigned char state; | ||
190 | |||
191 | GPIOF_INT_CLR = GPIOF_INT_STAT; | ||
192 | |||
193 | state = GPIOF_INPUT_VAL & 0xff; | ||
194 | |||
195 | GPIOF_INT_LEV = (GPIOF_INT_LEV & ~0xff) | (state ^ 0xff); | ||
196 | |||
197 | int_btn = BUTTON_NONE; | ||
198 | |||
199 | hold_button = (state & 0x80) != 0; | ||
200 | |||
201 | /* device buttons */ | ||
202 | if (!hold_button) | ||
203 | { | ||
204 | /* Read normal buttons */ | ||
205 | if ((state & 0x01) == 0) int_btn |= BUTTON_REC; | ||
206 | if ((state & 0x02) == 0) int_btn |= BUTTON_DOWN; | ||
207 | if ((state & 0x04) == 0) int_btn |= BUTTON_RIGHT; | ||
208 | if ((state & 0x08) == 0) int_btn |= BUTTON_LEFT; | ||
209 | if ((state & 0x10) == 0) int_btn |= BUTTON_SELECT; /* The centre button */ | ||
210 | if ((state & 0x20) == 0) int_btn |= BUTTON_UP; /* The "play" button */ | ||
211 | if ((state & 0x40) != 0) int_btn |= BUTTON_POWER; | ||
212 | } | ||
46 | } | 213 | } |
47 | 214 | ||
48 | /* | 215 | /* |
@@ -50,101 +217,16 @@ bool button_hold(void) | |||
50 | */ | 217 | */ |
51 | int button_read_device(void) | 218 | int button_read_device(void) |
52 | { | 219 | { |
53 | int btn = BUTTON_NONE; | ||
54 | unsigned char state; | ||
55 | static bool hold_button = false; | ||
56 | bool hold_button_old; | ||
57 | unsigned int new_wheel_value = 0; /* read later, but this stops a warning */ | ||
58 | |||
59 | /* Hold */ | 220 | /* Hold */ |
60 | hold_button_old = hold_button; | ||
61 | hold_button = button_hold(); | ||
62 | |||
63 | #ifndef BOOTLOADER | 221 | #ifndef BOOTLOADER |
64 | /* light handling */ | 222 | /* light handling */ |
65 | if (hold_button != hold_button_old) | 223 | if (hold_button != hold_button_old) |
66 | { | 224 | { |
225 | hold_button_old = hold_button; | ||
67 | backlight_hold_changed(hold_button); | 226 | backlight_hold_changed(hold_button); |
68 | } | 227 | } |
69 | #endif | 228 | #endif |
70 | 229 | ||
71 | /* device buttons */ | 230 | /* The int_btn variable is set in the button interrupt handler */ |
72 | if (!hold_button) | 231 | return int_btn; |
73 | { | ||
74 | /* Read normal buttons */ | ||
75 | state = GPIOF_INPUT_VAL & 0xff; | ||
76 | if ((state & 0x1) == 0) btn |= BUTTON_REC; | ||
77 | if ((state & 0x2) == 0) btn |= BUTTON_DOWN; | ||
78 | if ((state & 0x4) == 0) btn |= BUTTON_RIGHT; | ||
79 | if ((state & 0x8) == 0) btn |= BUTTON_LEFT; | ||
80 | if ((state & 0x10) == 0) btn |= BUTTON_SELECT; /* The centre button */ | ||
81 | if ((state & 0x20) == 0) btn |= BUTTON_UP; /* The "play" button */ | ||
82 | if ((state & 0x40) != 0) btn |= BUTTON_POWER; | ||
83 | |||
84 | /* Read wheel | ||
85 | * Bits 6 and 7 of GPIOH change as follows: | ||
86 | * Clockwise rotation 01 -> 00 -> 10 -> 11 | ||
87 | * Counter-clockwise 11 -> 10 -> 00 -> 01 | ||
88 | * | ||
89 | * This is equivalent to wheel_value of: | ||
90 | * Clockwise rotation 0x40 -> 0x00 -> 0x80 -> 0xc0 | ||
91 | * Counter-clockwise 0xc0 -> 0x80 -> 0x00 -> 0x40 | ||
92 | */ | ||
93 | new_wheel_value = GPIOH_INPUT_VAL & 0xc0; | ||
94 | switch(new_wheel_value){ | ||
95 | case 0x00: | ||
96 | if(old_wheel_value==0x80) | ||
97 | btn |= BUTTON_SCROLL_UP; | ||
98 | else if (old_wheel_value==0x40) | ||
99 | btn |= BUTTON_SCROLL_DOWN; | ||
100 | break; | ||
101 | case 0x40: | ||
102 | if(old_wheel_value==0x00) | ||
103 | btn |= BUTTON_SCROLL_UP; | ||
104 | else if (old_wheel_value==0xc0) | ||
105 | btn |= BUTTON_SCROLL_DOWN; | ||
106 | break; | ||
107 | case 0x80: | ||
108 | if(old_wheel_value==0xc0) | ||
109 | btn |= BUTTON_SCROLL_UP; | ||
110 | else if (old_wheel_value==0x00) | ||
111 | btn |= BUTTON_SCROLL_DOWN; | ||
112 | break; | ||
113 | case 0xc0: | ||
114 | if(old_wheel_value==0x40) | ||
115 | btn |= BUTTON_SCROLL_UP; | ||
116 | else if (old_wheel_value==0x80) | ||
117 | btn |= BUTTON_SCROLL_DOWN; | ||
118 | break; | ||
119 | } | ||
120 | |||
121 | if(wheel_repeat == BUTTON_NONE){ | ||
122 | if(btn & BUTTON_SCROLL_UP) | ||
123 | wheel_repeat = BUTTON_SCROLL_UP; | ||
124 | |||
125 | if(btn & BUTTON_SCROLL_DOWN) | ||
126 | wheel_repeat = BUTTON_SCROLL_DOWN; | ||
127 | } else if (wheel_repeat == BUTTON_SCROLL_UP) { | ||
128 | btn |= BUTTON_SCROLL_UP; | ||
129 | wheel_repeat = BUTTON_NONE; | ||
130 | } else if (wheel_repeat == BUTTON_SCROLL_DOWN) { | ||
131 | btn |= BUTTON_SCROLL_DOWN; | ||
132 | wheel_repeat = BUTTON_NONE; | ||
133 | } | ||
134 | |||
135 | old_wheel_value = new_wheel_value; | ||
136 | } | ||
137 | |||
138 | if( (btn & BUTTON_SCROLL_UP) || (btn & BUTTON_SCROLL_DOWN) ){ | ||
139 | /* only trigger once per click */ | ||
140 | if ((new_wheel_value == 0x00) || (new_wheel_value == 0xc0)) | ||
141 | { | ||
142 | btn = btn&(~(BUTTON_SCROLL_UP|BUTTON_SCROLL_DOWN)); | ||
143 | } | ||
144 | #ifndef BOOTLOADER | ||
145 | button_backlight_on(); | ||
146 | #endif | ||
147 | } | ||
148 | |||
149 | return btn; | ||
150 | } | 232 | } |
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c index 1f1cdf47b6..72e3a9b361 100644 --- a/firmware/target/arm/system-pp502x.c +++ b/firmware/target/arm/system-pp502x.c | |||
@@ -56,12 +56,21 @@ void irq(void) | |||
56 | /* TODO: this should really be in the target tree, but moving it there caused | 56 | /* TODO: this should really be in the target tree, but moving it there caused |
57 | crt0.S not to find it while linking */ | 57 | crt0.S not to find it while linking */ |
58 | /* TODO: Even if it isn't in the target tree, this should be the default case */ | 58 | /* TODO: Even if it isn't in the target tree, this should be the default case */ |
59 | extern void button_int(void); | ||
60 | extern void clickwheel_int(void); | ||
61 | |||
59 | void irq(void) | 62 | void irq(void) |
60 | { | 63 | { |
61 | if(CURRENT_CORE == CPU) | 64 | if(CURRENT_CORE == CPU) { |
62 | { | 65 | if (CPU_INT_STAT & TIMER1_MASK) { |
63 | if (CPU_INT_STAT & TIMER1_MASK) | 66 | #ifdef SANSA_E200 |
67 | if (GPIOF_INT_STAT & 0xff) | ||
68 | button_int(); | ||
69 | if (GPIOH_INT_STAT & 0xc0) | ||
70 | clickwheel_int(); | ||
71 | #endif | ||
64 | TIMER1(); | 72 | TIMER1(); |
73 | } | ||
65 | else if (CPU_INT_STAT & TIMER2_MASK) | 74 | else if (CPU_INT_STAT & TIMER2_MASK) |
66 | TIMER2(); | 75 | TIMER2(); |
67 | } else { | 76 | } else { |
@@ -222,7 +231,20 @@ void system_init(void) | |||
222 | COP_INT_CLR = -1; | 231 | COP_INT_CLR = -1; |
223 | CPU_INT_CLR = -1; | 232 | CPU_INT_CLR = -1; |
224 | INT_FORCED_CLR = -1; | 233 | INT_FORCED_CLR = -1; |
225 | 234 | ||
235 | GPIOA_INT_EN = 0; | ||
236 | GPIOB_INT_EN = 0; | ||
237 | GPIOC_INT_EN = 0; | ||
238 | GPIOD_INT_EN = 0; | ||
239 | GPIOE_INT_EN = 0; | ||
240 | GPIOF_INT_EN = 0; | ||
241 | GPIOG_INT_EN = 0; | ||
242 | GPIOH_INT_EN = 0; | ||
243 | GPIOI_INT_EN = 0; | ||
244 | GPIOJ_INT_EN = 0; | ||
245 | GPIOK_INT_EN = 0; | ||
246 | GPIOL_INT_EN = 0; | ||
247 | |||
226 | # if NUM_CORES > 1 && defined(HAVE_ADJUSTABLE_CPU_FREQ) | 248 | # if NUM_CORES > 1 && defined(HAVE_ADJUSTABLE_CPU_FREQ) |
227 | spinlock_init(&boostctrl_mtx); | 249 | spinlock_init(&boostctrl_mtx); |
228 | # endif | 250 | # endif |