1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2008 by Thomas Martitz
11 * Copyright (C) 2008 by Dominik Wenger
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 ****************************************************************************/
24 /* Basic button driver for the Fuze
26 * TODO: - Get the wheel working with interrupts
27 * - find that Home button
32 #include "button-target.h"
33 #include "backlight.h"
35 #define WHEEL_REPEAT_INTERVAL 30
36 #define WHEELCLICKS_PER_ROTATION 48 /* wheelclicks per full rotation */
40 static bool hold_button
= false;
41 static bool hold_button_old
= false;
43 #define hold_button false
44 #endif /* !BOOTLOADER */
45 static int int_btn
= BUTTON_NONE
;
46 static short dbop_din
= BUTTON_NONE
;
48 void button_init_device(void)
51 GPIOA_PIN(1) = (1<<1);
55 #if !defined(BOOTLOADER) && defined(HAVE_SCROLLWHEEL)
56 static void get_wheel(void)
58 static unsigned int old_wheel_value
= 0;
59 static unsigned int wheel_value
= 0;
60 static unsigned int wheel_repeat
= BUTTON_NONE
;
61 /* getting BUTTON_REPEAT works like this: We increment repeat by if the
62 * wheel was turned, and decrement it by 1 each tick,
63 * that means: if you change the wheel fast enough, repeat will be >1 and
64 * we send BUTTON_REPEAT
67 /* we omit 3 of 4 posts to the button_queue, that works better, so count */
68 static int counter
= 0;
70 * Bits 13 and 14 of DBOP_DIN change as follows:
71 * Clockwise rotation 00 -> 01 -> 11 -> 10 -> 00
72 * Counter-clockwise 00 -> 10 -> 11 -> 01 -> 00
74 static const unsigned char wheel_tbl
[2][4] =
76 { 2, 0, 3, 1 }, /* Clockwise rotation */
77 { 1, 3, 0, 2 }, /* Counter-clockwise */
79 wheel_value
= dbop_din
& (1<<13|1<<14);
81 /* did the wheel value change? */
84 unsigned int btn
= BUTTON_NONE
;
85 if (old_wheel_value
== wheel_tbl
[0][wheel_value
])
86 btn
= BUTTON_SCROLL_FWD
;
87 else if (old_wheel_value
== wheel_tbl
[1][wheel_value
])
88 btn
= BUTTON_SCROLL_BACK
;
90 if (btn
!= BUTTON_NONE
)
92 if (btn
!= wheel_repeat
)
94 /* direction reversals nullify repeats */
98 if (btn
!= BUTTON_NONE
)
100 /* generate repeats if quick enough */
103 btn
|= BUTTON_REPEAT
;
106 /* the wheel is more reliable if we don't send ever change,
107 * every 4th is basically one "physical click" is 1 item in
108 * the rockbox menus */
109 if (queue_empty(&button_queue
) && ++counter
>= 4)
113 /* 1<<24 is rather arbitary, seems to work well */
114 queue_post(&button_queue
, btn
, 1<<24);
115 /* message posted - reset count */
125 old_wheel_value
= wheel_value
;
127 #endif /* !defined(BOOTLOADER) && defined(SCROLLWHEEL) */
129 #if !defined(BOOTLOADER)
130 /* get hold button state */
131 static void get_hold(void)
133 hold_button
= dbop_din
& (1<<12);
137 bool button_hold(void)
142 static void get_power(void)
144 if (dbop_din
& (1<<8))
145 int_btn
|= BUTTON_POWER
;
148 static void get_button_from_dbob(void)
150 int_btn
&= ~(BUTTON_HOLD
|
153 /* Wait for fifo to empty */
154 while ((DBOP_STAT
& (1<<10)) == 0);
156 DBOP_CTRL
|= (1<<19);
157 DBOP_CTRL
&= ~(1<<16); /* disable output */
159 DBOP_TIMPOL_01
= 0xe167e167;
160 DBOP_TIMPOL_23
= 0xe167006e;
164 asm volatile ("nop\n");
168 DBOP_CTRL
|= (1<<15); /* start read */
173 } while ((temp
& (1<<16)) == 0); /* wait for valid data */
175 dbop_din
= DBOP_DIN
; /* now read */
177 DBOP_TIMPOL_01
= 0x6e167;
178 DBOP_TIMPOL_23
= 0xa167e06f;
180 DBOP_CTRL
|= (1<<16);
181 DBOP_CTRL
&= ~(1<<19);
183 #if !defined(BOOTLOADER)
185 #if defined(HAVE_SCROLLWHEEL)
192 static void get_button_from_gpio(void)
194 /* reset buttons we're going to read */
195 int_btn
&= ~(BUTTON_LEFT
|
202 /* set afsel, so that we can read our buttons */
203 GPIOC_AFSEL
&= ~(1<<2|1<<3|1<<4|1<<5|1<<6);
204 /* set dir so we can read our buttons (but reset the C pins first) */
205 GPIOB_DIR
&= ~(1<<4);
206 GPIOC_DIR
|= (1<<2|1<<3|1<<4|1<<5|1<<6);
207 GPIOC_PIN(2) |= (1<<2);
208 GPIOC_PIN(3) |= (1<<3);
209 GPIOC_PIN(4) |= (1<<4);
210 GPIOC_PIN(5) |= (1<<5);
211 GPIOC_PIN(6) |= (1<<6);
213 GPIOC_DIR
&= ~(1<<2|1<<3|1<<4|1<<5|1<<6);
215 /* small delay needed to read buttons correctly */
217 while(delay
>0) delay
--;
219 /* direct GPIO connections */
221 int_btn
|= BUTTON_LEFT
;
223 int_btn
|= BUTTON_UP
;
225 int_btn
|= BUTTON_DOWN
;
227 int_btn
|= BUTTON_RIGHT
;
229 int_btn
|= BUTTON_SELECT
;
230 /* return to settings needed for lcd */
231 GPIOC_DIR
|= (1<<2|1<<3|1<<4|1<<5|1<<6);
232 GPIOC_AFSEL
|= (1<<2|1<<3|1<<4|1<<5|1<<6);
235 static inline void get_buttons_from_hw(void)
237 get_button_from_dbob();
238 get_button_from_gpio();
241 * Get button pressed from hardware
243 int button_read_device(void)
245 get_buttons_from_hw();
248 if (hold_button
!= hold_button_old
)
250 hold_button_old
= hold_button
;
251 backlight_hold_changed(hold_button
);
253 #endif /* BOOTLOADER */
255 return int_btn
; /* set in button_int */