diff options
Diffstat (limited to 'firmware/target/arm/as3525/sansa-fuze/button-fuze.c')
-rw-r--r-- | firmware/target/arm/as3525/sansa-fuze/button-fuze.c | 164 |
1 files changed, 85 insertions, 79 deletions
diff --git a/firmware/target/arm/as3525/sansa-fuze/button-fuze.c b/firmware/target/arm/as3525/sansa-fuze/button-fuze.c index cf84599083..9b6df70bd9 100644 --- a/firmware/target/arm/as3525/sansa-fuze/button-fuze.c +++ b/firmware/target/arm/as3525/sansa-fuze/button-fuze.c | |||
@@ -35,34 +35,35 @@ | |||
35 | #define WHEEL_REPEAT_INTERVAL 30 | 35 | #define WHEEL_REPEAT_INTERVAL 30 |
36 | #define WHEELCLICKS_PER_ROTATION 48 /* wheelclicks per full rotation */ | 36 | #define WHEELCLICKS_PER_ROTATION 48 /* wheelclicks per full rotation */ |
37 | 37 | ||
38 | #ifndef BOOTLOADER | ||
39 | /* Buttons */ | 38 | /* Buttons */ |
40 | static bool hold_button = false; | 39 | static bool hold_button = false; |
40 | #ifndef BOOTLOADER | ||
41 | static bool hold_button_old = false; | 41 | static bool hold_button_old = false; |
42 | #else | 42 | #endif |
43 | #define hold_button false | ||
44 | #endif /* !BOOTLOADER */ | ||
45 | static short _dbop_din = BUTTON_NONE; | 43 | static short _dbop_din = BUTTON_NONE; |
46 | 44 | ||
47 | extern void lcd_button_support(void); | 45 | /* in the lcd driver */ |
46 | extern bool lcd_button_support(void); | ||
48 | 47 | ||
49 | void button_init_device(void) | 48 | void button_init_device(void) |
50 | { | 49 | { |
50 | GPIOA_DIR |= (1<<1); | ||
51 | GPIOA_PIN(1) = (1<<1); | ||
51 | } | 52 | } |
52 | 53 | ||
53 | /* clickwheel */ | ||
54 | #if !defined(BOOTLOADER) && defined(HAVE_SCROLLWHEEL) | 54 | #if !defined(BOOTLOADER) && defined(HAVE_SCROLLWHEEL) |
55 | static void clickwheel(void) | 55 | static void scrollwheel(void) |
56 | { | 56 | { |
57 | static unsigned int old_wheel_value = 0; | 57 | static unsigned old_wheel_value = 0; |
58 | static unsigned int wheel_value = 0; | 58 | static unsigned wheel_value = 0; |
59 | static unsigned int wheel_repeat = BUTTON_NONE; | 59 | static unsigned wheel_repeat = BUTTON_NONE; |
60 | unsigned btn = BUTTON_NONE; | ||
60 | /* getting BUTTON_REPEAT works like this: We increment repeat by 2 if the | 61 | /* getting BUTTON_REPEAT works like this: We increment repeat by 2 if the |
61 | * wheel was turned, and decrement it by 1 each tick, | 62 | * wheel was turned, and decrement it by 1 each tick, |
62 | * that means: if you change the wheel fast enough, repeat will be >1 and | 63 | * that means: if you change the wheel fast enough, repeat will be >1 and |
63 | * we send BUTTON_REPEAT | 64 | * we send BUTTON_REPEAT |
64 | */ | 65 | */ |
65 | static int repeat; | 66 | static int repeat = 0; |
66 | /* we omit 3 of 4 posts to the button_queue, that works better, so count */ | 67 | /* we omit 3 of 4 posts to the button_queue, that works better, so count */ |
67 | static int counter = 0; | 68 | static int counter = 0; |
68 | /* Read wheel | 69 | /* Read wheel |
@@ -77,43 +78,38 @@ static void clickwheel(void) | |||
77 | }; | 78 | }; |
78 | wheel_value = _dbop_din & (1<<13|1<<14); | 79 | wheel_value = _dbop_din & (1<<13|1<<14); |
79 | wheel_value >>= 13; | 80 | wheel_value >>= 13; |
80 | /* did the wheel value change? */ | ||
81 | if (!hold_button) | ||
82 | { | ||
83 | unsigned int btn = BUTTON_NONE; | ||
84 | if (old_wheel_value == wheel_tbl[0][wheel_value]) | ||
85 | btn = BUTTON_SCROLL_FWD; | ||
86 | else if (old_wheel_value == wheel_tbl[1][wheel_value]) | ||
87 | btn = BUTTON_SCROLL_BACK; | ||
88 | 81 | ||
82 | if (old_wheel_value == wheel_tbl[0][wheel_value]) | ||
83 | btn = BUTTON_SCROLL_FWD; | ||
84 | else if (old_wheel_value == wheel_tbl[1][wheel_value]) | ||
85 | btn = BUTTON_SCROLL_BACK; | ||
86 | |||
87 | if (btn != BUTTON_NONE) | ||
88 | { | ||
89 | if (btn != wheel_repeat) | ||
90 | { | ||
91 | /* direction reversals nullify repeats */ | ||
92 | wheel_repeat = btn; | ||
93 | repeat = 0; | ||
94 | } | ||
89 | if (btn != BUTTON_NONE) | 95 | if (btn != BUTTON_NONE) |
90 | { | 96 | { |
91 | if (btn != wheel_repeat) | 97 | /* generate repeats if quick enough */ |
98 | if (repeat > 0) | ||
92 | { | 99 | { |
93 | /* direction reversals nullify repeats */ | 100 | btn |= BUTTON_REPEAT; |
94 | wheel_repeat = btn; | ||
95 | repeat = 0; | ||
96 | } | 101 | } |
97 | if (btn != BUTTON_NONE) | 102 | repeat += 2; |
103 | /* the wheel is more reliable if we don't send ever change, | ||
104 | * every 4th is basically one "physical click" is 1 item in | ||
105 | * the rockbox menus */ | ||
106 | if (queue_empty(&button_queue) && ++counter >= 4) | ||
98 | { | 107 | { |
99 | /* generate repeats if quick enough */ | 108 | buttonlight_on(); |
100 | if (repeat > 0) | 109 | backlight_on(); |
101 | { | 110 | queue_post(&button_queue, btn, 1<<24); |
102 | btn |= BUTTON_REPEAT; | 111 | /* message posted - reset count */ |
103 | } | 112 | counter = 0; |
104 | repeat += 2; | ||
105 | /* the wheel is more reliable if we don't send ever change, | ||
106 | * every 4th is basically one "physical click" is 1 item in | ||
107 | * the rockbox menus */ | ||
108 | if (queue_empty(&button_queue) && ++counter >= 4) | ||
109 | { | ||
110 | buttonlight_on(); | ||
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 | } | 113 | } |
118 | } | 114 | } |
119 | } | 115 | } |
@@ -130,10 +126,16 @@ bool button_hold(void) | |||
130 | return hold_button; | 126 | return hold_button; |
131 | } | 127 | } |
132 | 128 | ||
133 | static int button_dbop(void) | 129 | static short button_dbop(void) |
134 | { | 130 | { |
135 | int ret = 0; | 131 | /* skip home reading if lcd_button_support was blocked, |
136 | lcd_button_support(); | 132 | * since the dbop bit 15 is invalid then, and use the old value instead */ |
133 | /* -20 (arbitary value) indicates valid home button read */ | ||
134 | int old_home = -20; | ||
135 | int delay = 0; | ||
136 | if(!lcd_button_support()) | ||
137 | old_home = (_dbop_din & 1<<15); | ||
138 | |||
137 | /* Wait for fifo to empty */ | 139 | /* Wait for fifo to empty */ |
138 | while ((DBOP_STAT & (1<<10)) == 0); | 140 | while ((DBOP_STAT & (1<<10)) == 0); |
139 | 141 | ||
@@ -142,19 +144,11 @@ static int button_dbop(void) | |||
142 | 144 | ||
143 | DBOP_TIMPOL_01 = 0xe167e167; | 145 | DBOP_TIMPOL_01 = 0xe167e167; |
144 | DBOP_TIMPOL_23 = 0xe167006e; | 146 | DBOP_TIMPOL_23 = 0xe167006e; |
145 | int loop = 0; | 147 | |
146 | do | 148 | while(delay++ < 64); |
147 | { | ||
148 | asm volatile ("nop\n"); | ||
149 | loop++; | ||
150 | } while(loop < 64); | ||
151 | 149 | ||
152 | DBOP_CTRL |= (1<<15); /* start read */ | 150 | DBOP_CTRL |= (1<<15); /* start read */ |
153 | int temp; | 151 | ((DBOP_STAT & (1<<16)) == 0); /* wait for valid data */ |
154 | do | ||
155 | { | ||
156 | temp = DBOP_STAT; | ||
157 | } while ((temp & (1<<16)) == 0); /* wait for valid data */ | ||
158 | 152 | ||
159 | _dbop_din = DBOP_DIN; /* now read */ | 153 | _dbop_din = DBOP_DIN; /* now read */ |
160 | 154 | ||
@@ -164,23 +158,9 @@ static int button_dbop(void) | |||
164 | DBOP_CTRL |= (1<<16); | 158 | DBOP_CTRL |= (1<<16); |
165 | DBOP_CTRL &= ~(1<<19); | 159 | DBOP_CTRL &= ~(1<<19); |
166 | 160 | ||
167 | #if !defined(BOOTLOADER) | 161 | if (old_home != -20) |
168 | hold_button = _dbop_din & (1<<12); | 162 | _dbop_din |= old_home; |
169 | if (hold_button) | 163 | return _dbop_din; |
170 | return BUTTON_NONE; | ||
171 | #if defined(HAVE_SCROLLWHEEL) | ||
172 | /* read wheel on bit 13 & 14, but sent to the button queue seperately */ | ||
173 | clickwheel(); | ||
174 | #endif | ||
175 | #endif | ||
176 | /* read power on bit 8 */ | ||
177 | if (_dbop_din & (1<<8)) | ||
178 | ret |= BUTTON_POWER; | ||
179 | /* read home on bit 15 */ | ||
180 | if(!(_dbop_din & (1<<15))) | ||
181 | ret |= BUTTON_HOME; | ||
182 | |||
183 | return ret; | ||
184 | } | 164 | } |
185 | 165 | ||
186 | /* for the debug menu */ | 166 | /* for the debug menu */ |
@@ -208,8 +188,8 @@ static int button_gpio(void) | |||
208 | GPIOC_DIR &= ~(1<<2|1<<3|1<<4|1<<5|1<<6); | 188 | GPIOC_DIR &= ~(1<<2|1<<3|1<<4|1<<5|1<<6); |
209 | 189 | ||
210 | /* small delay needed to read buttons correctly */ | 190 | /* small delay needed to read buttons correctly */ |
211 | int delay = 50; | 191 | int delay = 0; |
212 | while(delay >0) delay--; | 192 | while(delay++ < 32); |
213 | 193 | ||
214 | /* direct GPIO connections */ | 194 | /* direct GPIO connections */ |
215 | if (!GPIOC_PIN(3)) | 195 | if (!GPIOC_PIN(3)) |
@@ -234,9 +214,35 @@ static int button_gpio(void) | |||
234 | */ | 214 | */ |
235 | int button_read_device(void) | 215 | int button_read_device(void) |
236 | { | 216 | { |
237 | int ret = BUTTON_NONE; | 217 | int btn = BUTTON_NONE; |
238 | ret |= button_dbop(); | 218 | short dbop = button_dbop(); |
239 | ret |= button_gpio(); | 219 | static unsigned power_counter = HZ; |
220 | /* hold button */ | ||
221 | if(dbop & (1<<12)) | ||
222 | { | ||
223 | power_counter = 0; | ||
224 | hold_button = true; | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | /* might wrap, but shouldn't be much of an issue*/ | ||
229 | power_counter++; | ||
230 | hold_button = false; | ||
231 | #if defined(HAVE_SCROLLWHEEL) && !defined(BOOTLOADER) | ||
232 | /* read wheel on bit 13 & 14, but sent to the button queue seperately */ | ||
233 | scrollwheel(); | ||
234 | #endif | ||
235 | /* read power on bit 8, but not if hold button was just released, since | ||
236 | * you basically always hit power due to the slider mechanism after releasing | ||
237 | * hold (wait ~1 sec) */ | ||
238 | if (dbop & (1<<8) && power_counter>HZ) | ||
239 | btn |= BUTTON_POWER; | ||
240 | /* read home on bit 15 */ | ||
241 | if (!(dbop & (1<<15))) | ||
242 | btn |= BUTTON_HOME; | ||
243 | btn |= button_gpio(); | ||
244 | } | ||
245 | |||
240 | #ifndef BOOTLOADER | 246 | #ifndef BOOTLOADER |
241 | /* light handling */ | 247 | /* light handling */ |
242 | if (hold_button != hold_button_old) | 248 | if (hold_button != hold_button_old) |
@@ -246,5 +252,5 @@ int button_read_device(void) | |||
246 | } | 252 | } |
247 | #endif /* BOOTLOADER */ | 253 | #endif /* BOOTLOADER */ |
248 | 254 | ||
249 | return ret; | 255 | return btn; |
250 | } | 256 | } |