diff options
author | Björn Stenberg <bjorn@haxx.se> | 2008-12-31 21:02:56 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2008-12-31 21:02:56 +0000 |
commit | 9e3844db07e684365837ca5d5f9bcd4a2cb993a6 (patch) | |
tree | 7fde79118324291a685400ca133ec2705ea8d4af /firmware/target | |
parent | 5bf0cf59102f6a0fa812d7f60f954b5cc9ab834a (diff) | |
download | rockbox-9e3844db07e684365837ca5d5f9bcd4a2cb993a6.tar.gz rockbox-9e3844db07e684365837ca5d5f9bcd4a2cb993a6.zip |
Updated Fuze button code. FS#9645 by Thomas Martitz.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19629 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/as3525/clock-target.h | 2 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-fuze/button-fuze.c | 257 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-fuze/button-target.h | 11 |
3 files changed, 189 insertions, 81 deletions
diff --git a/firmware/target/arm/as3525/clock-target.h b/firmware/target/arm/as3525/clock-target.h index 1e55753555..a227f464ff 100644 --- a/firmware/target/arm/as3525/clock-target.h +++ b/firmware/target/arm/as3525/clock-target.h | |||
@@ -53,7 +53,7 @@ | |||
53 | #elif defined(SANSA_M200V4) | 53 | #elif defined(SANSA_M200V4) |
54 | #define AS3525_DBOP_FREQ 8000000 | 54 | #define AS3525_DBOP_FREQ 8000000 |
55 | #elif defined(SANSA_FUZE) | 55 | #elif defined(SANSA_FUZE) |
56 | #define AS3525_DBOP_FREQ 24000000 | 56 | #define AS3525_DBOP_FREQ 8000000 |
57 | #elif defined(SANSA_E200V2) | 57 | #elif defined(SANSA_E200V2) |
58 | #define AS3525_DBOP_FREQ 8000000 | 58 | #define AS3525_DBOP_FREQ 8000000 |
59 | #elif defined(SANSA_C200V2) | 59 | #elif defined(SANSA_C200V2) |
diff --git a/firmware/target/arm/as3525/sansa-fuze/button-fuze.c b/firmware/target/arm/as3525/sansa-fuze/button-fuze.c index 36a0f3aeda..2414900727 100644 --- a/firmware/target/arm/as3525/sansa-fuze/button-fuze.c +++ b/firmware/target/arm/as3525/sansa-fuze/button-fuze.c | |||
@@ -7,7 +7,8 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2006 by Barry Wardell | 10 | * Copyright (C) 2008 by Thomas Martitz |
11 | * Copyright (C) 2008 by Dominik Wenger | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 14 | * modify it under the terms of the GNU General Public License |
@@ -19,118 +20,229 @@ | |||
19 | * | 20 | * |
20 | ****************************************************************************/ | 21 | ****************************************************************************/ |
21 | 22 | ||
22 | /* Taken from button-h10.c by Barry Wardell and reverse engineering by MrH. */ | 23 | |
24 | /* Basic button driver for the Fuze | ||
25 | * | ||
26 | * TODO: - Get the wheel working with interrupts | ||
27 | * - find that Home button | ||
28 | */ | ||
23 | 29 | ||
24 | #include "system.h" | 30 | #include "system.h" |
25 | #include "button.h" | 31 | #include "button.h" |
32 | #include "button-target.h" | ||
26 | #include "backlight.h" | 33 | #include "backlight.h" |
27 | #include "powermgmt.h" | ||
28 | 34 | ||
29 | #define WHEEL_REPEAT_INTERVAL 300000 | 35 | #define WHEEL_REPEAT_INTERVAL 30 |
30 | #define WHEEL_FAST_ON_INTERVAL 20000 | ||
31 | #define WHEEL_FAST_OFF_INTERVAL 60000 | ||
32 | #define WHEELCLICKS_PER_ROTATION 48 /* wheelclicks per full rotation */ | 36 | #define WHEELCLICKS_PER_ROTATION 48 /* wheelclicks per full rotation */ |
33 | 37 | ||
34 | /* Clickwheel */ | ||
35 | #ifndef BOOTLOADER | 38 | #ifndef BOOTLOADER |
36 | static unsigned int old_wheel_value = 0; | ||
37 | static unsigned int wheel_repeat = BUTTON_NONE; | ||
38 | static unsigned int wheel_click_count = 0; | ||
39 | static unsigned int wheel_delta = 0; | ||
40 | static int wheel_fast_mode = 0; | ||
41 | static unsigned long last_wheel_usec = 0; | ||
42 | static unsigned long wheel_velocity = 0; | ||
43 | static long last_wheel_post = 0; | ||
44 | static long next_backlight_on = 0; | ||
45 | /* Buttons */ | 39 | /* Buttons */ |
46 | static bool hold_button = false; | 40 | static bool hold_button = false; |
47 | static bool hold_button_old = false; | 41 | static bool hold_button_old = false; |
48 | #define _button_hold() hold_button | ||
49 | #else | 42 | #else |
50 | #define _button_hold() false /* FIXME */ | 43 | #define hold_button false |
51 | #endif /* BOOTLOADER */ | 44 | #endif /* !BOOTLOADER */ |
52 | static int int_btn = BUTTON_NONE; | 45 | static int int_btn = BUTTON_NONE; |
46 | static short dbop_din = BUTTON_NONE; | ||
53 | 47 | ||
54 | void button_init_device(void) | 48 | void button_init_device(void) |
55 | { | 49 | { |
50 | GPIOA_DIR |= (1<<1); | ||
51 | GPIOA_PIN(1) = (1<<1); | ||
52 | } | ||
53 | |||
54 | /* clickwheel */ | ||
55 | #if !defined(BOOTLOADER) && defined(HAVE_SCROLLWHEEL) | ||
56 | static void get_wheel(void) | ||
57 | { | ||
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 | ||
65 | */ | ||
66 | static int repeat; | ||
67 | /* we omit 3 of 4 posts to the button_queue, that works better, so count */ | ||
68 | static int counter = 0; | ||
69 | /* Read wheel | ||
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 | ||
73 | */ | ||
74 | static const unsigned char wheel_tbl[2][4] = | ||
75 | { | ||
76 | { 2, 0, 3, 1 }, /* Clockwise rotation */ | ||
77 | { 1, 3, 0, 2 }, /* Counter-clockwise */ | ||
78 | }; | ||
79 | wheel_value = dbop_din & (1<<13|1<<14); | ||
80 | wheel_value >>= 13; | ||
81 | /* did the wheel value change? */ | ||
82 | if (!hold_button) | ||
83 | { | ||
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; | ||
89 | |||
90 | if (btn != BUTTON_NONE) | ||
91 | { | ||
92 | if (btn != wheel_repeat) | ||
93 | { | ||
94 | /* direction reversals nullify repeats */ | ||
95 | wheel_repeat = btn; | ||
96 | repeat = 0; | ||
97 | } | ||
98 | if (btn != BUTTON_NONE) | ||
99 | { | ||
100 | /* generate repeats if quick enough */ | ||
101 | if (repeat > 0) | ||
102 | { | ||
103 | btn |= BUTTON_REPEAT; | ||
104 | } | ||
105 | repeat += 2; | ||
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) | ||
110 | { | ||
111 | backlight_on(); | ||
112 | /* 1<<24 is rather arbitary, seems to work well */ | ||
113 | queue_post(&button_queue, btn, 1<<24); | ||
114 | /* message posted - reset count */ | ||
115 | counter = 0; | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | } | ||
120 | if (repeat > 0) | ||
121 | repeat--; | ||
122 | else | ||
123 | repeat = 0; | ||
124 | old_wheel_value = wheel_value; | ||
125 | } | ||
126 | #endif /* !defined(BOOTLOADER) && defined(SCROLLWHEEL) */ | ||
127 | |||
128 | #if !defined(BOOTLOADER) | ||
129 | /* get hold button state */ | ||
130 | static void get_hold(void) | ||
131 | { | ||
132 | hold_button = dbop_din & (1<<12); | ||
56 | } | 133 | } |
134 | #endif | ||
57 | 135 | ||
58 | bool button_hold(void) | 136 | bool button_hold(void) |
59 | { | 137 | { |
60 | return _button_hold(); | 138 | return hold_button; |
61 | } | 139 | } |
62 | 140 | ||
63 | /* clickwheel */ | 141 | static void get_power(void) |
64 | #ifndef BOOTLOADER | ||
65 | void clickwheel_int(void) | ||
66 | { | 142 | { |
143 | if (dbop_din & (1<<8)) | ||
144 | int_btn |= BUTTON_POWER; | ||
67 | } | 145 | } |
68 | #endif /* BOOTLOADER */ | ||
69 | 146 | ||
70 | /* device buttons */ | 147 | static void get_button_from_dbob(void) |
148 | { | ||
149 | int_btn &= ~(BUTTON_HOLD| | ||
150 | BUTTON_POWER); | ||
151 | |||
152 | /* Wait for fifo to empty */ | ||
153 | while ((DBOP_STAT & (1<<10)) == 0); | ||
154 | |||
155 | DBOP_CTRL |= (1<<19); | ||
156 | DBOP_CTRL &= ~(1<<16); /* disable output */ | ||
157 | |||
158 | DBOP_TIMPOL_01 = 0xe167e167; | ||
159 | DBOP_TIMPOL_23 = 0xe167006e; | ||
160 | int loop = 0; | ||
161 | do | ||
162 | { | ||
163 | asm volatile ("nop\n"); | ||
164 | loop++; | ||
165 | } while(loop < 64); | ||
166 | |||
167 | DBOP_CTRL |= (1<<15); /* start read */ | ||
168 | int temp; | ||
169 | do | ||
170 | { | ||
171 | temp = DBOP_STAT; | ||
172 | } while ((temp & (1<<16)) == 0); /* wait for valid data */ | ||
173 | |||
174 | dbop_din = DBOP_DIN; /* now read */ | ||
175 | |||
176 | DBOP_TIMPOL_01 = 0x6e167; | ||
177 | DBOP_TIMPOL_23 = 0xa167e06f; | ||
178 | |||
179 | DBOP_CTRL |= (1<<16); | ||
180 | DBOP_CTRL &= ~(1<<19); | ||
71 | 181 | ||
72 | /* device buttons */ | 182 | #if !defined(BOOTLOADER) |
73 | void button_int(void) | 183 | get_hold(); |
184 | #if defined(HAVE_SCROLLWHEEL) | ||
185 | get_wheel(); | ||
186 | #endif | ||
187 | #endif | ||
188 | get_power(); | ||
189 | } | ||
190 | |||
191 | static void get_button_from_gpio(void) | ||
74 | { | 192 | { |
75 | int dir_save_b = 0; | 193 | /* reset buttons we're going to read */ |
76 | int afsel_save_b = 0; | 194 | int_btn &= ~(BUTTON_LEFT| |
77 | int dir_save_c = 0; | 195 | BUTTON_RIGHT| |
78 | int afsel_save_c = 0; | 196 | BUTTON_UP| |
79 | 197 | BUTTON_DOWN| | |
80 | int_btn = BUTTON_NONE; | 198 | BUTTON_SELECT); |
81 | 199 | if(hold_button) | |
82 | /* Save the current direction and afsel */ | 200 | return; |
83 | dir_save_b = GPIOB_DIR; | 201 | /* set afsel, so that we can read our buttons */ |
84 | afsel_save_b = GPIOB_AFSEL; | 202 | GPIOC_AFSEL &= ~(1<<2|1<<3|1<<4|1<<5|1<<6); |
85 | dir_save_c = GPIOC_DIR; | 203 | /* set dir so we can read our buttons (but reset the C pins first) */ |
86 | afsel_save_c = GPIOC_AFSEL; | 204 | GPIOB_DIR &= ~(1<<4); |
87 | 205 | GPIOC_DIR |= (1<<2|1<<3|1<<4|1<<5|1<<6); | |
88 | GPIOB_DIR = 0; | 206 | GPIOC_PIN(2) |= (1<<2); |
89 | GPIOB_AFSEL = 0; | 207 | GPIOC_PIN(3) |= (1<<3); |
90 | GPIOC_DIR = 0; | 208 | GPIOC_PIN(4) |= (1<<4); |
91 | GPIOC_AFSEL = 0; | 209 | GPIOC_PIN(5) |= (1<<5); |
92 | 210 | GPIOC_PIN(6) |= (1<<6); | |
93 | /* These should not be needed with button event interupts */ | 211 | |
94 | /* they are necessary now to clear out lcd data */ | 212 | GPIOC_DIR &= ~(1<<2|1<<3|1<<4|1<<5|1<<6); |
95 | GPIOC_PIN(0) |= 1; | 213 | |
96 | GPIOC_PIN(1) |= 1; | 214 | /* small delay needed to read buttons correctly */ |
97 | GPIOC_PIN(2) |= 1; | 215 | int delay = 50; |
98 | GPIOC_PIN(3) |= 1; | 216 | while(delay >0) delay--; |
99 | GPIOC_PIN(4) |= 1; | ||
100 | GPIOC_PIN(5) |= 1; | ||
101 | GPIOC_PIN(6) |= 1; | ||
102 | GPIOC_PIN(7) |= 1; | ||
103 | 217 | ||
104 | /* direct GPIO connections */ | 218 | /* direct GPIO connections */ |
105 | if (GPIOB_PIN(4)) | 219 | if (!GPIOC_PIN(3)) |
106 | int_btn |= BUTTON_POWER; | 220 | int_btn |= BUTTON_LEFT; |
221 | if (!GPIOC_PIN(2)) | ||
222 | int_btn |= BUTTON_UP; | ||
107 | if (!GPIOC_PIN(6)) | 223 | if (!GPIOC_PIN(6)) |
108 | int_btn |= BUTTON_DOWN; | 224 | int_btn |= BUTTON_DOWN; |
109 | if (!GPIOC_PIN(5)) | 225 | if (!GPIOC_PIN(5)) |
110 | int_btn |= BUTTON_RIGHT; | 226 | int_btn |= BUTTON_RIGHT; |
111 | if (!GPIOC_PIN(4)) | 227 | if (!GPIOC_PIN(4)) |
112 | int_btn |= BUTTON_SELECT; | 228 | int_btn |= BUTTON_SELECT; |
113 | if (!GPIOC_PIN(3)) | ||
114 | int_btn |= BUTTON_LEFT; | ||
115 | if (!GPIOC_PIN(2)) | ||
116 | int_btn |= BUTTON_UP; | ||
117 | |||
118 | /* return to settings needed for lcd */ | 229 | /* return to settings needed for lcd */ |
119 | GPIOB_DIR = dir_save_b; | 230 | GPIOC_DIR |= (1<<2|1<<3|1<<4|1<<5|1<<6); |
120 | GPIOB_AFSEL = afsel_save_b; | 231 | GPIOC_AFSEL |= (1<<2|1<<3|1<<4|1<<5|1<<6); |
121 | GPIOC_DIR = dir_save_c; | ||
122 | GPIOC_AFSEL = afsel_save_c; | ||
123 | } | 232 | } |
124 | 233 | ||
234 | static inline void get_buttons_from_hw(void) | ||
235 | { | ||
236 | get_button_from_dbob(); | ||
237 | get_button_from_gpio(); | ||
238 | } | ||
125 | /* | 239 | /* |
126 | * Get button pressed from hardware | 240 | * Get button pressed from hardware |
127 | */ | 241 | */ |
128 | int button_read_device(void) | 242 | int button_read_device(void) |
129 | { | 243 | { |
130 | #ifdef BOOTLOADER | 244 | get_buttons_from_hw(); |
131 | /* Read buttons directly in the bootloader */ | 245 | #ifndef BOOTLOADER |
132 | button_int(); | ||
133 | #else | ||
134 | /* light handling */ | 246 | /* light handling */ |
135 | if (hold_button != hold_button_old) | 247 | if (hold_button != hold_button_old) |
136 | { | 248 | { |
@@ -139,6 +251,5 @@ int button_read_device(void) | |||
139 | } | 251 | } |
140 | #endif /* BOOTLOADER */ | 252 | #endif /* BOOTLOADER */ |
141 | 253 | ||
142 | /* The int_btn variable is set in the button interrupt handler */ | 254 | return int_btn; /* set in button_int */ |
143 | return int_btn; | ||
144 | } | 255 | } |
diff --git a/firmware/target/arm/as3525/sansa-fuze/button-target.h b/firmware/target/arm/as3525/sansa-fuze/button-target.h index be72e1a35e..75ce3d060e 100644 --- a/firmware/target/arm/as3525/sansa-fuze/button-target.h +++ b/firmware/target/arm/as3525/sansa-fuze/button-target.h | |||
@@ -27,13 +27,9 @@ | |||
27 | 27 | ||
28 | #define HAS_BUTTON_HOLD | 28 | #define HAS_BUTTON_HOLD |
29 | 29 | ||
30 | bool button_hold(void); | ||
31 | void button_init_device(void); | 30 | void button_init_device(void); |
31 | bool button_hold(void); | ||
32 | int button_read_device(void); | 32 | int button_read_device(void); |
33 | #ifndef BOOTLOADER | ||
34 | void clickwheel_int(void); | ||
35 | #endif | ||
36 | void button_int(void); | ||
37 | 33 | ||
38 | /* Sandisk Sansa Fuze button codes */ | 34 | /* Sandisk Sansa Fuze button codes */ |
39 | 35 | ||
@@ -51,11 +47,12 @@ void button_int(void); | |||
51 | #define BUTTON_SCROLL_BACK 0x00000080 | 47 | #define BUTTON_SCROLL_BACK 0x00000080 |
52 | #define BUTTON_SCROLL_FWD 0x00000100 | 48 | #define BUTTON_SCROLL_FWD 0x00000100 |
53 | 49 | ||
54 | #define BUTTON_HOLD 0x00000200 | 50 | #define BUTTON_HOLD 0x00000400 |
55 | 51 | ||
56 | #define BUTTON_MAIN (BUTTON_HOME|BUTTON_DOWN|BUTTON_RIGHT|BUTTON_LEFT \ | 52 | #define BUTTON_MAIN (BUTTON_HOME|BUTTON_DOWN|BUTTON_RIGHT|BUTTON_LEFT \ |
57 | |BUTTON_SELECT|BUTTON_UP|BUTTON_POWER \ | 53 | |BUTTON_SELECT|BUTTON_UP|BUTTON_POWER \ |
58 | |BUTTON_SCROLLBACK|BUTTON_SCROLL_FWD|BUTTON_HOLD) | 54 | |BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD| \ |
55 | |BUTTON_HOLD) | ||
59 | 56 | ||
60 | /* No Remote control */ | 57 | /* No Remote control */ |
61 | #define BUTTON_REMOTE 0 | 58 | #define BUTTON_REMOTE 0 |