1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
27 #include "backlight.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:
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();
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
;
98 ack_scrollstrip_interrupt();
99 enable_scrollstrip_interrupts();
104 if (TIME_AFTER(current_tick
, next_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();
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
;
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();
181 /* Only main hold affects backlight */
182 if (hold_button
!= hold_button_old
)
183 backlight_hold_changed(hold_button
);
186 /* Skip if main hold is active */
189 data
= adc_scan(ADC_BUTTONS
);
191 if (data
< 800) /* middle */
204 else /* data > 800 */
212 /* Handle GPIOs buttons
214 * GPIO56 active high PLAY/PAUSE/ON
215 * GPIO45 active low ENTER
216 * GPIO41 active low MENU
226 if (!(data
& (1<<13)))
229 if (!(data
& (1<<9)))