MPIO HD300 - initial commit
[maemo-rb.git] / firmware / target / coldfire / mpio / hd300 / button-hd300.c
blob19c93abfca685023ef92f41722d28abc9390286c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2010 Marcin Bukat
11 * scrollstrip logic inspired by button-mini1g.c
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
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"
31 #define SLIDER_BASE_SENSITIVITY 6
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))
36 static inline void disable_scrollstrip_interrupts(void)
38 and_l(~SLIDER_GPIO_MASK,&GPIO_INT_EN);
41 static inline void enable_scrollstrip_interrupts(void)
44 or_l(SLIDER_GPIO_MASK,&GPIO_INT_EN);
47 static inline void ack_scrollstrip_interrupt(void)
49 or_l(SLIDER_GPIO_MASK,&GPIO_INT_CLEAR);
52 void scrollstrip_isr(void) __attribute__ ((interrupt_handler,section(".icode")));
53 void scrollstrip_isr(void)
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
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}
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;
74 signed int new_scroll_lines;
75 signed int scroll_dir;
77 disable_scrollstrip_interrupts();
79 /* read GPIO6 and GPIO7 state*/
80 new_scroll_lines = (GPIO_READ >> 6) & 0x03;
82 if ( prev_scroll_lines == -1 )
84 prev_scroll_lines = new_scroll_lines;
85 ack_scrollstrip_interrupt();
86 enable_scrollstrip_interrupts();
87 return;
90 scroll_dir = scroll_state[prev_scroll_lines][new_scroll_lines];
91 prev_scroll_lines = new_scroll_lines;
93 if (direction != scroll_dir)
95 /* direction reversal */
96 direction = scroll_dir;
97 count = 0;
98 ack_scrollstrip_interrupt();
99 enable_scrollstrip_interrupts();
100 return;
103 /* poke backlight */
104 if (TIME_AFTER(current_tick, next_backlight_on))
106 backlight_on();
107 reset_poweroff_timer();
108 next_backlight_on = current_tick + HZ/4;
111 if (++count < SLIDER_BASE_SENSITIVITY)
113 ack_scrollstrip_interrupt();
114 enable_scrollstrip_interrupts();
115 return;
118 count = 0;
120 /* post scrollstrip event to the button queue */
121 if (queue_empty(&button_queue))
122 queue_post(&button_queue, scroll_dir, 0);
124 ack_scrollstrip_interrupt();
125 enable_scrollstrip_interrupts();
128 /* register interrupt service routine for scrollstrip lines */
129 void GPI6(void) __attribute__ ((alias("scrollstrip_isr")));
130 void GPI7(void) __attribute__ ((alias("scrollstrip_isr")));
132 void button_init_device(void)
134 /* GPIO56 (PLAY) general input
135 * GPIO45 (ENTER) general input
136 * GPIO41 (MENU) dual function pin shared with audio serial data
138 * GPIO6, GPIO7 scrollstrip lines
139 * GPIO31 scrollstrip enable
142 or_l((1<<24)|(1<<13),&GPIO1_FUNCTION);
143 and_l(~((1<<24)|(1<<13)),&GPIO1_ENABLE);
145 or_l((1<<31)|(1<<7)|(1<<6),&GPIO_FUNCTION);
146 and_l(~((1<<7)|(1<<6)),&GPIO_ENABLE);
148 /* scrollstrip enable active low */
149 and_l(~(1<<31),&GPIO_OUT);
150 or_l((1<<31),&GPIO_ENABLE);
152 /* GPI6, GPI7 interrupt level 4.0 */
153 or_l((4<<28)|(4<<24), &INTPRI5);
155 enable_scrollstrip_interrupts();
158 bool button_hold(void)
160 /* GPIO51 active low */
161 return (GPIO1_READ & (1<<19))?false:true;
165 * Get button pressed from hardware
167 int button_read_device(void)
169 int btn = BUTTON_NONE;
170 int data = 0;
171 static bool hold_button = false;
173 bool hold_button_old;
176 /* read hold buttons status */
177 hold_button_old = hold_button;
178 hold_button = button_hold();
180 #ifndef BOOTLOADER
181 /* Only main hold affects backlight */
182 if (hold_button != hold_button_old)
183 backlight_hold_changed(hold_button);
184 #endif
186 /* Skip if main hold is active */
187 if (!hold_button)
189 data = adc_scan(ADC_BUTTONS);
191 if (data < 800) /* middle */
193 if (data < 450)
195 if (data > 250)
196 btn |= BUTTON_FF;
198 else /* 800 - 450 */
200 if (data > 600)
201 btn |= BUTTON_REW;
204 else /* data > 800 */
206 if (data < 1150)
207 if (data > 950)
208 btn |= BUTTON_REC;
212 /* Handle GPIOs buttons
214 * GPIO56 active high PLAY/PAUSE/ON
215 * GPIO45 active low ENTER
216 * GPIO41 active low MENU
219 data = GPIO1_READ;
221 if (!hold_button)
223 if (data & (1<<24))
224 btn |= BUTTON_PLAY;
226 if (!(data & (1<<13)))
227 btn |= BUTTON_ENTER;
229 if (!(data & (1<<9)))
230 btn |= BUTTON_MENU;
233 return btn;