diff options
Diffstat (limited to 'firmware/target/coldfire/mpio/hd300/button-hd300.c')
-rw-r--r-- | firmware/target/coldfire/mpio/hd300/button-hd300.c | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/firmware/target/coldfire/mpio/hd300/button-hd300.c b/firmware/target/coldfire/mpio/hd300/button-hd300.c new file mode 100644 index 0000000000..19c93abfca --- /dev/null +++ b/firmware/target/coldfire/mpio/hd300/button-hd300.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Marcin Bukat | ||
11 | * scrollstrip logic inspired by button-mini1g.c | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | |||
23 | #include "config.h" | ||
24 | #include "cpu.h" | ||
25 | #include "system.h" | ||
26 | #include "button.h" | ||
27 | #include "backlight.h" | ||
28 | #include "adc.h" | ||
29 | #include "powermgmt.h" | ||
30 | |||
31 | #define SLIDER_BASE_SENSITIVITY 6 | ||
32 | |||
33 | /* GPI7 H-L, GPI6 H-L, GPI7 L-H, GPI6 L-H */ | ||
34 | #define SLIDER_GPIO_MASK ((1<<15)|(1<<14)|(1<<7)|(1<<6)) | ||
35 | |||
36 | static inline void disable_scrollstrip_interrupts(void) | ||
37 | { | ||
38 | and_l(~SLIDER_GPIO_MASK,&GPIO_INT_EN); | ||
39 | } | ||
40 | |||
41 | static inline void enable_scrollstrip_interrupts(void) | ||
42 | { | ||
43 | |||
44 | or_l(SLIDER_GPIO_MASK,&GPIO_INT_EN); | ||
45 | } | ||
46 | |||
47 | static inline void ack_scrollstrip_interrupt(void) | ||
48 | { | ||
49 | or_l(SLIDER_GPIO_MASK,&GPIO_INT_CLEAR); | ||
50 | } | ||
51 | |||
52 | void scrollstrip_isr(void) __attribute__ ((interrupt_handler,section(".icode"))); | ||
53 | void scrollstrip_isr(void) | ||
54 | { | ||
55 | /* reading line 6 and 7 forms four possible states: | ||
56 | * 0, 1 , 2, 3 | ||
57 | * tracking the order of line changes we can judge | ||
58 | * if the slide is up or down in the following way: | ||
59 | * sliding up order: 0 2 3 1 0 2 3 1 | ||
60 | * sliding down order: 0 1 3 2 0 1 3 2 | ||
61 | */ | ||
62 | static const signed char scroll_state[4][4] ICONST_ATTR = { | ||
63 | { BUTTON_NONE, BUTTON_DOWN, BUTTON_UP, BUTTON_NONE}, | ||
64 | { BUTTON_UP, BUTTON_NONE, BUTTON_NONE, BUTTON_DOWN}, | ||
65 | { BUTTON_DOWN, BUTTON_NONE, BUTTON_NONE, BUTTON_UP}, | ||
66 | { BUTTON_NONE, BUTTON_UP, BUTTON_DOWN, BUTTON_NONE} | ||
67 | }; | ||
68 | |||
69 | static signed char prev_scroll_lines = -1; | ||
70 | static signed char direction = 0; | ||
71 | static unsigned char count = 0; | ||
72 | static long next_backlight_on = 0; | ||
73 | |||
74 | signed int new_scroll_lines; | ||
75 | signed int scroll_dir; | ||
76 | |||
77 | disable_scrollstrip_interrupts(); | ||
78 | |||
79 | /* read GPIO6 and GPIO7 state*/ | ||
80 | new_scroll_lines = (GPIO_READ >> 6) & 0x03; | ||
81 | |||
82 | if ( prev_scroll_lines == -1 ) | ||
83 | { | ||
84 | prev_scroll_lines = new_scroll_lines; | ||
85 | ack_scrollstrip_interrupt(); | ||
86 | enable_scrollstrip_interrupts(); | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | scroll_dir = scroll_state[prev_scroll_lines][new_scroll_lines]; | ||
91 | prev_scroll_lines = new_scroll_lines; | ||
92 | |||
93 | if (direction != scroll_dir) | ||
94 | { | ||
95 | /* direction reversal */ | ||
96 | direction = scroll_dir; | ||
97 | count = 0; | ||
98 | ack_scrollstrip_interrupt(); | ||
99 | enable_scrollstrip_interrupts(); | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | /* poke backlight */ | ||
104 | if (TIME_AFTER(current_tick, next_backlight_on)) | ||
105 | { | ||
106 | backlight_on(); | ||
107 | reset_poweroff_timer(); | ||
108 | next_backlight_on = current_tick + HZ/4; | ||
109 | } | ||
110 | |||
111 | if (++count < SLIDER_BASE_SENSITIVITY) | ||
112 | { | ||
113 | ack_scrollstrip_interrupt(); | ||
114 | enable_scrollstrip_interrupts(); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | count = 0; | ||
119 | |||
120 | /* post scrollstrip event to the button queue */ | ||
121 | if (queue_empty(&button_queue)) | ||
122 | queue_post(&button_queue, scroll_dir, 0); | ||
123 | |||
124 | ack_scrollstrip_interrupt(); | ||
125 | enable_scrollstrip_interrupts(); | ||
126 | } | ||
127 | |||
128 | /* register interrupt service routine for scrollstrip lines */ | ||
129 | void GPI6(void) __attribute__ ((alias("scrollstrip_isr"))); | ||
130 | void GPI7(void) __attribute__ ((alias("scrollstrip_isr"))); | ||
131 | |||
132 | void button_init_device(void) | ||
133 | { | ||
134 | /* GPIO56 (PLAY) general input | ||
135 | * GPIO45 (ENTER) general input | ||
136 | * GPIO41 (MENU) dual function pin shared with audio serial data | ||
137 | * | ||
138 | * GPIO6, GPIO7 scrollstrip lines | ||
139 | * GPIO31 scrollstrip enable | ||
140 | */ | ||
141 | |||
142 | or_l((1<<24)|(1<<13),&GPIO1_FUNCTION); | ||
143 | and_l(~((1<<24)|(1<<13)),&GPIO1_ENABLE); | ||
144 | |||
145 | or_l((1<<31)|(1<<7)|(1<<6),&GPIO_FUNCTION); | ||
146 | and_l(~((1<<7)|(1<<6)),&GPIO_ENABLE); | ||
147 | |||
148 | /* scrollstrip enable active low */ | ||
149 | and_l(~(1<<31),&GPIO_OUT); | ||
150 | or_l((1<<31),&GPIO_ENABLE); | ||
151 | |||
152 | /* GPI6, GPI7 interrupt level 4.0 */ | ||
153 | or_l((4<<28)|(4<<24), &INTPRI5); | ||
154 | |||
155 | enable_scrollstrip_interrupts(); | ||
156 | } | ||
157 | |||
158 | bool button_hold(void) | ||
159 | { | ||
160 | /* GPIO51 active low */ | ||
161 | return (GPIO1_READ & (1<<19))?false:true; | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * Get button pressed from hardware | ||
166 | */ | ||
167 | int button_read_device(void) | ||
168 | { | ||
169 | int btn = BUTTON_NONE; | ||
170 | int data = 0; | ||
171 | static bool hold_button = false; | ||
172 | |||
173 | bool hold_button_old; | ||
174 | |||
175 | |||
176 | /* read hold buttons status */ | ||
177 | hold_button_old = hold_button; | ||
178 | hold_button = button_hold(); | ||
179 | |||
180 | #ifndef BOOTLOADER | ||
181 | /* Only main hold affects backlight */ | ||
182 | if (hold_button != hold_button_old) | ||
183 | backlight_hold_changed(hold_button); | ||
184 | #endif | ||
185 | |||
186 | /* Skip if main hold is active */ | ||
187 | if (!hold_button) | ||
188 | { | ||
189 | data = adc_scan(ADC_BUTTONS); | ||
190 | |||
191 | if (data < 800) /* middle */ | ||
192 | { | ||
193 | if (data < 450) | ||
194 | { | ||
195 | if (data > 250) | ||
196 | btn |= BUTTON_FF; | ||
197 | } | ||
198 | else /* 800 - 450 */ | ||
199 | { | ||
200 | if (data > 600) | ||
201 | btn |= BUTTON_REW; | ||
202 | } | ||
203 | } | ||
204 | else /* data > 800 */ | ||
205 | { | ||
206 | if (data < 1150) | ||
207 | if (data > 950) | ||
208 | btn |= BUTTON_REC; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /* Handle GPIOs buttons | ||
213 | * | ||
214 | * GPIO56 active high PLAY/PAUSE/ON | ||
215 | * GPIO45 active low ENTER | ||
216 | * GPIO41 active low MENU | ||
217 | */ | ||
218 | |||
219 | data = GPIO1_READ; | ||
220 | |||
221 | if (!hold_button) | ||
222 | { | ||
223 | if (data & (1<<24)) | ||
224 | btn |= BUTTON_PLAY; | ||
225 | |||
226 | if (!(data & (1<<13))) | ||
227 | btn |= BUTTON_ENTER; | ||
228 | |||
229 | if (!(data & (1<<9))) | ||
230 | btn |= BUTTON_MENU; | ||
231 | } | ||
232 | |||
233 | return btn; | ||
234 | } | ||