diff options
author | Jens Arnold <amiconn@rockbox.org> | 2008-03-26 23:40:17 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2008-03-26 23:40:17 +0000 |
commit | 91a564e4b9c3141b7ff8595842522efe7434ec47 (patch) | |
tree | ec2b663acd4993bf66c88b42a84dca6679f8ea7e /firmware | |
parent | 78d29f535ff14a5f213125baf63fa2961be17d79 (diff) | |
download | rockbox-91a564e4b9c3141b7ff8595842522efe7434ec47.tar.gz rockbox-91a564e4b9c3141b7ff8595842522efe7434ec47.zip |
Iriver H1x0/H300: Speed up remote LCD updates when boosted by implementing an idea from the iaudio remote LCD driver. Speedup is ~75 with ticking reduction disabled. Ticking reduction should also be more effective due to the better pulse/pause ratio (update speed with ticking reduction aims at a constant 60fps as before). * SLight speedup when not boosted due to simplifications.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16832 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/coldfire/iriver/lcd-remote-iriver.c | 194 |
1 files changed, 60 insertions, 134 deletions
diff --git a/firmware/target/coldfire/iriver/lcd-remote-iriver.c b/firmware/target/coldfire/iriver/lcd-remote-iriver.c index 2fe5d6c3c1..daceb44036 100644 --- a/firmware/target/coldfire/iriver/lcd-remote-iriver.c +++ b/firmware/target/coldfire/iriver/lcd-remote-iriver.c | |||
@@ -92,95 +92,15 @@ static inline void _byte_delay(int delay) | |||
92 | } | 92 | } |
93 | #endif /* HAVE_REMOTE_LCD_TICKING */ | 93 | #endif /* HAVE_REMOTE_LCD_TICKING */ |
94 | 94 | ||
95 | /* Standard low-level byte writer. Requires CLK low on entry */ | 95 | /* Low-level byte writer. Instruction order is devised to maximize the delay |
96 | static inline void _write_byte(unsigned data) | 96 | * between changing the data line and the CLK L->H transition, which makes |
97 | { | 97 | * the LCD controller sample DATA, so it's fast yet usable even when boosted. |
98 | asm volatile ( | ||
99 | "move.l (%[gpo1]), %%d0 \n" /* Get current state of data line */ | ||
100 | "and.l %[dbit], %%d0 \n" | ||
101 | "beq.s 1f \n" /* and set it as previous-state bit */ | ||
102 | "bset #8, %[data] \n" | ||
103 | "1: \n" | ||
104 | "move.l %[data], %%d0 \n" /* Compute the 'bit derivative', i.e. a value */ | ||
105 | "lsr.l #1, %%d0 \n" /* with 1's where the data changes from the */ | ||
106 | "eor.l %%d0, %[data] \n" /* previous state, and 0's where it doesn't */ | ||
107 | "swap %[data] \n" /* Shift data to upper byte */ | ||
108 | "lsl.l #8, %[data] \n" | ||
109 | |||
110 | "lsl.l #1,%[data] \n" /* Shift out MSB */ | ||
111 | "bcc.s 1f \n" | ||
112 | "eor.l %[dbit], (%[gpo1]) \n" /* 1: flip DATA */ | ||
113 | "1: \n" | ||
114 | "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */ | ||
115 | "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */ | ||
116 | |||
117 | "lsl.l #1,%[data] \n" /* ..unrolled.. */ | ||
118 | "bcc.s 1f \n" | ||
119 | "eor.l %[dbit], (%[gpo1]) \n" | ||
120 | "1: \n" | ||
121 | "eor.l %[cbit], (%[gpo0]) \n" | ||
122 | "eor.l %[cbit], (%[gpo0]) \n" | ||
123 | |||
124 | "lsl.l #1,%[data] \n" | ||
125 | "bcc.s 1f \n" | ||
126 | "eor.l %[dbit], (%[gpo1]) \n" | ||
127 | "1: \n" | ||
128 | "eor.l %[cbit], (%[gpo0]) \n" | ||
129 | "eor.l %[cbit], (%[gpo0]) \n" | ||
130 | |||
131 | "lsl.l #1,%[data] \n" | ||
132 | "bcc.s 1f \n" | ||
133 | "eor.l %[dbit], (%[gpo1]) \n" | ||
134 | "1: \n" | ||
135 | "eor.l %[cbit], (%[gpo0]) \n" | ||
136 | "eor.l %[cbit], (%[gpo0]) \n" | ||
137 | |||
138 | "lsl.l #1,%[data] \n" | ||
139 | "bcc.s 1f \n" | ||
140 | "eor.l %[dbit], (%[gpo1]) \n" | ||
141 | "1: \n" | ||
142 | "eor.l %[cbit], (%[gpo0]) \n" | ||
143 | "eor.l %[cbit], (%[gpo0]) \n" | ||
144 | |||
145 | "lsl.l #1,%[data] \n" | ||
146 | "bcc.s 1f \n" | ||
147 | "eor.l %[dbit], (%[gpo1]) \n" | ||
148 | "1: \n" | ||
149 | "eor.l %[cbit], (%[gpo0]) \n" | ||
150 | "eor.l %[cbit], (%[gpo0]) \n" | ||
151 | |||
152 | "lsl.l #1,%[data] \n" | ||
153 | "bcc.s 1f \n" | ||
154 | "eor.l %[dbit], (%[gpo1]) \n" | ||
155 | "1: \n" | ||
156 | "eor.l %[cbit], (%[gpo0]) \n" | ||
157 | "eor.l %[cbit], (%[gpo0]) \n" | ||
158 | |||
159 | "lsl.l #1,%[data] \n" | ||
160 | "bcc.s 1f \n" | ||
161 | "eor.l %[dbit], (%[gpo1]) \n" | ||
162 | "1: \n" | ||
163 | "eor.l %[cbit], (%[gpo0]) \n" | ||
164 | "eor.l %[cbit], (%[gpo0]) \n" | ||
165 | : /* outputs */ | ||
166 | [data]"+d"(data) | ||
167 | : /* inputs */ | ||
168 | [gpo0]"a"(&GPIO_OUT), | ||
169 | [cbit]"d"(0x10000000), | ||
170 | [gpo1]"a"(&GPIO1_OUT), | ||
171 | [dbit]"d"(0x00040000) | ||
172 | : /* clobbers */ | ||
173 | "d0" | ||
174 | ); | ||
175 | } | ||
176 | |||
177 | /* Fast low-level byte writer. Don't use with high CPU clock. | ||
178 | * Requires CLK low on entry */ | 98 | * Requires CLK low on entry */ |
179 | static inline void _write_fast(unsigned data) | 99 | static inline void _write_byte(unsigned data) |
180 | { | 100 | { |
181 | asm volatile ( | 101 | asm volatile ( |
182 | "move.w %%sr,%%d3 \n" /* Get current interrupt level */ | 102 | "move.w %%sr, %%d3 \n" /* Get current interrupt level */ |
183 | "move.w #0x2700,%%sr \n" /* Disable interrupts */ | 103 | "move.w #0x2700, %%sr \n" /* Disable interrupts */ |
184 | 104 | ||
185 | "move.l (%[gpo1]), %%d0 \n" /* Get current state of data port */ | 105 | "move.l (%[gpo1]), %%d0 \n" /* Get current state of data port */ |
186 | "move.l %%d0, %%d1 \n" | 106 | "move.l %%d0, %%d1 \n" |
@@ -194,75 +114,98 @@ static inline void _write_fast(unsigned data) | |||
194 | "swap %[data] \n" /* Shift data to upper byte */ | 114 | "swap %[data] \n" /* Shift data to upper byte */ |
195 | "lsl.l #8, %[data] \n" | 115 | "lsl.l #8, %[data] \n" |
196 | 116 | ||
197 | "move.l (%[gpo0]), %%d1 \n" /* Get current state of clock port */ | 117 | "move.l (%[gpo0]),%%d1 \n" /* Get current state of clock port */ |
198 | "move.l %[cbit], %%d2 \n" /* Precalculate opposite state of clock line */ | 118 | "move.l %%d1, %%d2 \n" /* Precalculate opposite state of clock line */ |
199 | "eor.l %%d1, %%d2 \n" | 119 | "eor.l %[cbit], %%d2 \n" |
200 | 120 | ||
201 | "lsl.l #1,%[data] \n" /* Shift out MSB */ | 121 | "lsl.l #1, %[data] \n" /* Invert data line for bit7 ? */ |
202 | "bcc.s 1f \n" | 122 | "bcc.s 1f \n" /* no: skip */ |
203 | "eor.l %[dbit], %%d0 \n" /* 1: flip data bit */ | 123 | "eor.l %[dbit], %%d0 \n" /* invert data bit */ |
204 | "move.l %%d0, (%[gpo1]) \n" /* and output new DATA state */ | 124 | "move.l %%d0, (%[gpo1]) \n" /* output data bit7 */ |
205 | "1: \n" | 125 | "1: \n" |
206 | "move.l %%d2, (%[gpo0]) \n" /* Set CLK */ | ||
207 | "move.l %%d1, (%[gpo0]) \n" /* Reset CLK */ | ||
208 | 126 | ||
209 | "lsl.l #1,%[data] \n" /* ..unrolled.. */ | 127 | "lsl.l #1, %[data] \n" /* Invert data line for bit6 ? */ |
128 | "bcc.s 1f \n" /* no: skip */ | ||
129 | "eor.l %[dbit], %%d0 \n" /* Invert data bit */ | ||
130 | "move.l %%d2, (%[gpo0]) \n" /* Bit7: set CLK = 1 */ | ||
131 | "move.l %%d1, (%[gpo0]) \n" /* set CLK = 0 */ | ||
132 | "move.l %%d0, (%[gpo1]) \n" /* Output data bit6 */ | ||
133 | ".word 0x51fb \n" /* trapf.l - skip next 2 insns */ | ||
134 | "1: \n" /* else */ | ||
135 | "move.l %%d2, (%[gpo0]) \n" /* Bit7: set CLK = 1 */ | ||
136 | "move.l %%d1, (%[gpo0]) \n" /* set CLK = 0 */ | ||
137 | |||
138 | "lsl.l #1, %[data] \n" /* Unrolled */ | ||
210 | "bcc.s 1f \n" | 139 | "bcc.s 1f \n" |
211 | "eor.l %[dbit], %%d0 \n" | 140 | "eor.l %[dbit], %%d0 \n" |
212 | "move.l %%d0, (%[gpo1]) \n" | ||
213 | "1: \n" | ||
214 | "move.l %%d2, (%[gpo0]) \n" | 141 | "move.l %%d2, (%[gpo0]) \n" |
215 | "move.l %%d1, (%[gpo0]) \n" | 142 | "move.l %%d1, (%[gpo0]) \n" |
216 | |||
217 | "lsl.l #1,%[data] \n" | ||
218 | "bcc.s 1f \n" | ||
219 | "eor.l %[dbit], %%d0 \n" | ||
220 | "move.l %%d0, (%[gpo1]) \n" | 143 | "move.l %%d0, (%[gpo1]) \n" |
144 | ".word 0x51fb \n" | ||
221 | "1: \n" | 145 | "1: \n" |
222 | "move.l %%d2, (%[gpo0]) \n" | 146 | "move.l %%d2, (%[gpo0]) \n" |
223 | "move.l %%d1, (%[gpo0]) \n" | 147 | "move.l %%d1, (%[gpo0]) \n" |
224 | 148 | ||
225 | "lsl.l #1,%[data] \n" | 149 | "lsl.l #1, %[data] \n" |
226 | "bcc.s 1f \n" | 150 | "bcc.s 1f \n" |
227 | "eor.l %[dbit], %%d0 \n" | 151 | "eor.l %[dbit], %%d0 \n" |
152 | "move.l %%d2, (%[gpo0]) \n" | ||
153 | "move.l %%d1, (%[gpo0]) \n" | ||
228 | "move.l %%d0, (%[gpo1]) \n" | 154 | "move.l %%d0, (%[gpo1]) \n" |
155 | ".word 0x51fb \n" | ||
229 | "1: \n" | 156 | "1: \n" |
230 | "move.l %%d2, (%[gpo0]) \n" | 157 | "move.l %%d2, (%[gpo0]) \n" |
231 | "move.l %%d1, (%[gpo0]) \n" | 158 | "move.l %%d1, (%[gpo0]) \n" |
232 | 159 | ||
233 | "lsl.l #1,%[data] \n" | 160 | "lsl.l #1, %[data] \n" |
234 | "bcc.s 1f \n" | 161 | "bcc.s 1f \n" |
235 | "eor.l %[dbit], %%d0 \n" | 162 | "eor.l %[dbit], %%d0 \n" |
163 | "move.l %%d2, (%[gpo0]) \n" | ||
164 | "move.l %%d1, (%[gpo0]) \n" | ||
236 | "move.l %%d0, (%[gpo1]) \n" | 165 | "move.l %%d0, (%[gpo1]) \n" |
166 | ".word 0x51fb \n" | ||
237 | "1: \n" | 167 | "1: \n" |
238 | "move.l %%d2, (%[gpo0]) \n" | 168 | "move.l %%d2, (%[gpo0]) \n" |
239 | "move.l %%d1, (%[gpo0]) \n" | 169 | "move.l %%d1, (%[gpo0]) \n" |
240 | 170 | ||
241 | "lsl.l #1,%[data] \n" | 171 | "lsl.l #1, %[data] \n" |
242 | "bcc.s 1f \n" | 172 | "bcc.s 1f \n" |
243 | "eor.l %[dbit], %%d0 \n" | 173 | "eor.l %[dbit], %%d0 \n" |
174 | "move.l %%d2, (%[gpo0]) \n" | ||
175 | "move.l %%d1, (%[gpo0]) \n" | ||
244 | "move.l %%d0, (%[gpo1]) \n" | 176 | "move.l %%d0, (%[gpo1]) \n" |
177 | ".word 0x51fb \n" | ||
245 | "1: \n" | 178 | "1: \n" |
246 | "move.l %%d2, (%[gpo0]) \n" | 179 | "move.l %%d2, (%[gpo0]) \n" |
247 | "move.l %%d1, (%[gpo0]) \n" | 180 | "move.l %%d1, (%[gpo0]) \n" |
248 | 181 | ||
249 | "lsl.l #1,%[data] \n" | 182 | "lsl.l #1, %[data] \n" |
250 | "bcc.s 1f \n" | 183 | "bcc.s 1f \n" |
251 | "eor.l %[dbit], %%d0 \n" | 184 | "eor.l %[dbit], %%d0 \n" |
185 | "move.l %%d2, (%[gpo0]) \n" | ||
186 | "move.l %%d1, (%[gpo0]) \n" | ||
252 | "move.l %%d0, (%[gpo1]) \n" | 187 | "move.l %%d0, (%[gpo1]) \n" |
188 | ".word 0x51fb \n" | ||
253 | "1: \n" | 189 | "1: \n" |
254 | "move.l %%d2, (%[gpo0]) \n" | 190 | "move.l %%d2, (%[gpo0]) \n" |
255 | "move.l %%d1, (%[gpo0]) \n" | 191 | "move.l %%d1, (%[gpo0]) \n" |
256 | 192 | ||
257 | "lsl.l #1,%[data] \n" | 193 | "lsl.l #1, %[data] \n" |
258 | "bcc.s 1f \n" | 194 | "bcc.s 1f \n" |
259 | "eor.l %[dbit], %%d0 \n" | 195 | "eor.l %[dbit], %%d0 \n" |
196 | "move.l %%d2, (%[gpo0]) \n" | ||
197 | "move.l %%d1, (%[gpo0]) \n" | ||
260 | "move.l %%d0, (%[gpo1]) \n" | 198 | "move.l %%d0, (%[gpo1]) \n" |
199 | ".word 0x51fb \n" | ||
261 | "1: \n" | 200 | "1: \n" |
262 | "move.l %%d2, (%[gpo0]) \n" | 201 | "move.l %%d2, (%[gpo0]) \n" |
263 | "move.l %%d1, (%[gpo0]) \n" | 202 | "move.l %%d1, (%[gpo0]) \n" |
264 | 203 | ||
265 | "move.w %%d3, %%sr \n" /* Restore interrupt level */ | 204 | "nop \n" /* Let data line settle */ |
205 | "move.l %%d2, (%[gpo0]) \n" /* Bit0: Set CLK = 1 */ | ||
206 | "move.l %%d1, (%[gpo0]) \n" /* Set CLK = 0 */ | ||
207 | |||
208 | "move.w %%d3, %%sr \n" /* Restore interrupt level */ | ||
266 | : /* outputs */ | 209 | : /* outputs */ |
267 | [data]"+d"(data) | 210 | [data]"+d"(data) |
268 | : /* inputs */ | 211 | : /* inputs */ |
@@ -283,7 +226,7 @@ void lcd_remote_write_command(int cmd) | |||
283 | 226 | ||
284 | _write_byte(cmd); | 227 | _write_byte(cmd); |
285 | #ifdef HAVE_REMOTE_LCD_TICKING | 228 | #ifdef HAVE_REMOTE_LCD_TICKING |
286 | _byte_delay(byte_delay - 148); | 229 | _byte_delay(byte_delay); |
287 | #endif | 230 | #endif |
288 | 231 | ||
289 | cs_countdown = CS_TIMEOUT; | 232 | cs_countdown = CS_TIMEOUT; |
@@ -297,11 +240,11 @@ void lcd_remote_write_command_ex(int cmd, int data) | |||
297 | 240 | ||
298 | _write_byte(cmd); | 241 | _write_byte(cmd); |
299 | #ifdef HAVE_REMOTE_LCD_TICKING | 242 | #ifdef HAVE_REMOTE_LCD_TICKING |
300 | _byte_delay(byte_delay - 148); | 243 | _byte_delay(byte_delay); |
301 | #endif | 244 | #endif |
302 | _write_byte(data); | 245 | _write_byte(data); |
303 | #ifdef HAVE_REMOTE_LCD_TICKING | 246 | #ifdef HAVE_REMOTE_LCD_TICKING |
304 | _byte_delay(byte_delay - 148); | 247 | _byte_delay(byte_delay); |
305 | #endif | 248 | #endif |
306 | 249 | ||
307 | cs_countdown = CS_TIMEOUT; | 250 | cs_countdown = CS_TIMEOUT; |
@@ -316,27 +259,12 @@ void lcd_remote_write_data(const unsigned char* p_bytes, int count) | |||
316 | RS_HI; | 259 | RS_HI; |
317 | CS_LO; | 260 | CS_LO; |
318 | 261 | ||
319 | /* This is safe as long as lcd_remote_write_data() isn't called from within | 262 | while (p_bytes < p_end) |
320 | * an ISR. */ | ||
321 | if (cpu_frequency < 50000000) | ||
322 | { | 263 | { |
323 | while (p_bytes < p_end) | 264 | _write_byte(*p_bytes++); |
324 | { | ||
325 | _write_fast(*p_bytes++); | ||
326 | #ifdef HAVE_REMOTE_LCD_TICKING | 265 | #ifdef HAVE_REMOTE_LCD_TICKING |
327 | _byte_delay(byte_delay - 87); | 266 | _byte_delay(byte_delay); |
328 | #endif | 267 | #endif |
329 | } | ||
330 | } | ||
331 | else | ||
332 | { | ||
333 | while (p_bytes < p_end) | ||
334 | { | ||
335 | _write_byte(*p_bytes++); | ||
336 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
337 | _byte_delay(byte_delay - 148); | ||
338 | #endif | ||
339 | } | ||
340 | } | 268 | } |
341 | 269 | ||
342 | cs_countdown = CS_TIMEOUT; | 270 | cs_countdown = CS_TIMEOUT; |
@@ -558,7 +486,6 @@ void lcd_remote_init_device(void) | |||
558 | 486 | ||
559 | /* Update the display. | 487 | /* Update the display. |
560 | This must be called after all other LCD functions that change the display. */ | 488 | This must be called after all other LCD functions that change the display. */ |
561 | void lcd_remote_update(void) ICODE_ATTR; | ||
562 | void lcd_remote_update(void) | 489 | void lcd_remote_update(void) |
563 | { | 490 | { |
564 | int y; | 491 | int y; |
@@ -568,7 +495,7 @@ void lcd_remote_update(void) | |||
568 | 495 | ||
569 | #ifdef HAVE_REMOTE_LCD_TICKING | 496 | #ifdef HAVE_REMOTE_LCD_TICKING |
570 | /* Adjust byte delay for emi reduction. */ | 497 | /* Adjust byte delay for emi reduction. */ |
571 | byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0; | 498 | byte_delay = emireduce ? cpu_frequency / 192800 - 90: 0; |
572 | #endif | 499 | #endif |
573 | 500 | ||
574 | /* Copy display bitmap to hardware */ | 501 | /* Copy display bitmap to hardware */ |
@@ -582,7 +509,6 @@ void lcd_remote_update(void) | |||
582 | } | 509 | } |
583 | 510 | ||
584 | /* Update a fraction of the display. */ | 511 | /* Update a fraction of the display. */ |
585 | void lcd_remote_update_rect(int, int, int, int) ICODE_ATTR; | ||
586 | void lcd_remote_update_rect(int x, int y, int width, int height) | 512 | void lcd_remote_update_rect(int x, int y, int width, int height) |
587 | { | 513 | { |
588 | int ymax; | 514 | int ymax; |
@@ -603,7 +529,7 @@ void lcd_remote_update_rect(int x, int y, int width, int height) | |||
603 | 529 | ||
604 | #ifdef HAVE_REMOTE_LCD_TICKING | 530 | #ifdef HAVE_REMOTE_LCD_TICKING |
605 | /* Adjust byte delay for emi reduction */ | 531 | /* Adjust byte delay for emi reduction */ |
606 | byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0; | 532 | byte_delay = emireduce ? cpu_frequency / 192800 - 90: 0; |
607 | #endif | 533 | #endif |
608 | 534 | ||
609 | /* Copy specified rectange bitmap to hardware */ | 535 | /* Copy specified rectange bitmap to hardware */ |