diff options
Diffstat (limited to 'firmware/target/arm/as3525')
-rw-r--r-- | firmware/target/arm/as3525/sansa-fuze/button-fuze.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/firmware/target/arm/as3525/sansa-fuze/button-fuze.c b/firmware/target/arm/as3525/sansa-fuze/button-fuze.c index efa1c593a3..f8c489c4dd 100644 --- a/firmware/target/arm/as3525/sansa-fuze/button-fuze.c +++ b/firmware/target/arm/as3525/sansa-fuze/button-fuze.c | |||
@@ -23,8 +23,8 @@ | |||
23 | 23 | ||
24 | /* Basic button driver for the Fuze | 24 | /* Basic button driver for the Fuze |
25 | * | 25 | * |
26 | * TODO: - Get the wheel working with interrupts | 26 | * TODO: - Get the wheel working with interrupts (seems to be impossible |
27 | * - find that Home button | 27 | * so far) |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include "system.h" | 30 | #include "system.h" |
@@ -32,6 +32,8 @@ | |||
32 | #include "button-target.h" | 32 | #include "button-target.h" |
33 | #include "backlight.h" | 33 | #include "backlight.h" |
34 | 34 | ||
35 | #define WHEEL_REPEAT_INTERVAL (HZ/5) | ||
36 | |||
35 | /* Buttons */ | 37 | /* Buttons */ |
36 | static bool hold_button = false; | 38 | static bool hold_button = false; |
37 | #ifndef BOOTLOADER | 39 | #ifndef BOOTLOADER |
@@ -58,13 +60,22 @@ static void scrollwheel(unsigned short dbop_din) | |||
58 | static unsigned old_wheel_value = 0; | 60 | static unsigned old_wheel_value = 0; |
59 | static unsigned old_btn = BUTTON_NONE; | 61 | static unsigned old_btn = BUTTON_NONE; |
60 | 62 | ||
61 | /* getting BUTTON_REPEAT works like this: We increment repeat by 2 if the | 63 | /* |
62 | * wheel was turned, and decrement it by 1 each tick, | 64 | * Getting BUTTON_REPEAT works like this: Remember when the btn value was |
63 | * that means: if you change the wheel fast enough, repeat will be >1 and | 65 | * posted to the button_queue last, and if it was recent enough, generate |
64 | * we send BUTTON_REPEAT | 66 | * BUTTON_REPEAT |
67 | */ | ||
68 | static long last_wheel_post = 0; | ||
69 | |||
70 | /* | ||
71 | * Providing wheel acceleration works as follows: We increment accel | ||
72 | * by 2 if the wheel was turned, and decrement it by 1 each tick | ||
73 | * (no matter if it was turned), that means: the longer and faster you turn, | ||
74 | * the higher accel will be. accel>>2 will actually posted to the button_queue | ||
65 | */ | 75 | */ |
66 | static int repeat = 0; | 76 | static int accel = 0; |
67 | /* we omit 3 of 4 posts to the button_queue, that works better, so count */ | 77 | /* We only post every 4th action, as this matches better with the physical |
78 | * clicks of the wheel */ | ||
68 | static int counter = 0; | 79 | static int counter = 0; |
69 | /* Read wheel | 80 | /* Read wheel |
70 | * Bits 13 and 14 of DBOP_DIN change as follows: | 81 | * Bits 13 and 14 of DBOP_DIN change as follows: |
@@ -79,7 +90,7 @@ static void scrollwheel(unsigned short dbop_din) | |||
79 | 90 | ||
80 | if(hold_button) | 91 | if(hold_button) |
81 | { | 92 | { |
82 | repeat = counter = 0; | 93 | accel = counter = 0; |
83 | return; | 94 | return; |
84 | } | 95 | } |
85 | 96 | ||
@@ -95,39 +106,39 @@ static void scrollwheel(unsigned short dbop_din) | |||
95 | { | 106 | { |
96 | if (btn != old_btn) | 107 | if (btn != old_btn) |
97 | { | 108 | { |
98 | /* direction reversals nullify repeats */ | 109 | /* direction reversals nullify acceleration and counters */ |
99 | old_btn = btn; | 110 | old_btn = btn; |
100 | repeat = counter = 0; | 111 | accel = counter = 0; |
101 | } | 112 | } |
102 | /* wheel_delta will cause lists to jump over items, | 113 | /* wheel_delta will cause lists to jump over items, |
103 | * we want this for fast scrolling, but we must keep it accurate | 114 | * we want this for fast scrolling, but we must keep it accurate |
104 | * for slow scrolling */ | 115 | * for slow scrolling */ |
105 | int wheel_delta = 0; | 116 | int wheel_delta = 0; |
106 | /* generate repeats if quick enough, scroll slightly faster too*/ | 117 | /* generate BUTTON_REPEAT if quick enough, scroll slightly faster too*/ |
107 | if (repeat > 1) | 118 | if (TIME_BEFORE(current_tick, last_wheel_post + WHEEL_REPEAT_INTERVAL)) |
108 | { | 119 | { |
109 | btn |= BUTTON_REPEAT; | 120 | btn |= BUTTON_REPEAT; |
110 | wheel_delta = repeat>>2; | 121 | wheel_delta = accel>>2; |
111 | } | 122 | } |
112 | 123 | ||
113 | repeat += 2; | 124 | accel += 2; |
114 | 125 | ||
115 | /* the wheel is more reliable if we don't send ever change, | 126 | /* the wheel is more reliable if we don't send every change, |
116 | * every 4th is basically one "physical click" is 1 item in | 127 | * every 4th is basically one "physical click" which should |
117 | * the rockbox menus */ | 128 | * make up 1 item in lists */ |
118 | if (++counter >= 4 && queue_empty(&button_queue)) | 129 | if (++counter >= 4 && queue_empty(&button_queue)) |
119 | { | 130 | { |
120 | buttonlight_on(); | 131 | buttonlight_on(); |
121 | backlight_on(); | 132 | backlight_on(); |
122 | queue_post(&button_queue, btn, ((wheel_delta+1)<<24)); | 133 | queue_post(&button_queue, btn, ((wheel_delta+1)<<24)); |
123 | /* message posted - reset count */ | 134 | /* message posted - reset count and remember post */ |
124 | counter = 0; | 135 | counter = 0; |
136 | last_wheel_post = current_tick; | ||
125 | } | 137 | } |
126 | } | 138 | } |
127 | if (repeat > 0) | 139 | if (accel > 0) |
128 | repeat--; | 140 | accel--; |
129 | else | 141 | |
130 | repeat = 0; | ||
131 | old_wheel_value = wheel_value; | 142 | old_wheel_value = wheel_value; |
132 | } | 143 | } |
133 | #endif /* !defined(BOOTLOADER) && defined(SCROLLWHEEL) */ | 144 | #endif /* !defined(BOOTLOADER) && defined(SCROLLWHEEL) */ |
@@ -139,8 +150,8 @@ bool button_hold(void) | |||
139 | 150 | ||
140 | static void button_delay(void) | 151 | static void button_delay(void) |
141 | { | 152 | { |
142 | int i = 32; | 153 | int i = 24; |
143 | while(i--); | 154 | while(i--) asm volatile ("nop\n"); |
144 | } | 155 | } |
145 | 156 | ||
146 | unsigned short button_read_dbop(void) | 157 | unsigned short button_read_dbop(void) |
@@ -155,7 +166,6 @@ unsigned short button_read_dbop(void) | |||
155 | } | 166 | } |
156 | 167 | ||
157 | /* Set up dbop for input */ | 168 | /* Set up dbop for input */ |
158 | while (!(DBOP_STAT & (1<<10))); /* Wait for fifo to empty */ | ||
159 | DBOP_CTRL |= (1<<19); /* Tri-state DBOP on read cycle */ | 169 | DBOP_CTRL |= (1<<19); /* Tri-state DBOP on read cycle */ |
160 | DBOP_CTRL &= ~(1<<16); /* disable output (1:write enabled) */ | 170 | DBOP_CTRL &= ~(1<<16); /* disable output (1:write enabled) */ |
161 | DBOP_TIMPOL_01 = 0xe167e167; /* Set Timing & Polarity regs 0 & 1 */ | 171 | DBOP_TIMPOL_01 = 0xe167e167; /* Set Timing & Polarity regs 0 & 1 */ |
@@ -211,8 +221,7 @@ static int button_gpio(void) | |||
211 | GPIOC_DIR &= ~(1<<2|1<<3|1<<4|1<<5|1<<6); | 221 | GPIOC_DIR &= ~(1<<2|1<<3|1<<4|1<<5|1<<6); |
212 | 222 | ||
213 | /* small delay needed to read buttons correctly */ | 223 | /* small delay needed to read buttons correctly */ |
214 | int delay = 0; | 224 | button_delay(); |
215 | while(delay++ < 32); | ||
216 | 225 | ||
217 | /* direct GPIO connections */ | 226 | /* direct GPIO connections */ |
218 | if (!GPIOC_PIN(3)) | 227 | if (!GPIOC_PIN(3)) |
@@ -251,7 +260,7 @@ int button_read_device(void) | |||
251 | hold_button = false; | 260 | hold_button = false; |
252 | /* read power on bit 8, but not if hold button was just released, since | 261 | /* read power on bit 8, but not if hold button was just released, since |
253 | * you basically always hit power due to the slider mechanism after releasing | 262 | * you basically always hit power due to the slider mechanism after releasing |
254 | * hold (wait ~1 sec) */ | 263 | * hold (wait 1 sec) */ |
255 | if (power_counter) | 264 | if (power_counter) |
256 | power_counter--; | 265 | power_counter--; |
257 | if (!power_counter && dbop & (1<<8)) | 266 | if (!power_counter && dbop & (1<<8)) |