summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2008-03-26 23:40:17 +0000
committerJens Arnold <amiconn@rockbox.org>2008-03-26 23:40:17 +0000
commit91a564e4b9c3141b7ff8595842522efe7434ec47 (patch)
treeec2b663acd4993bf66c88b42a84dca6679f8ea7e
parent78d29f535ff14a5f213125baf63fa2961be17d79 (diff)
downloadrockbox-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
-rw-r--r--firmware/target/coldfire/iriver/lcd-remote-iriver.c194
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
96static 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 */
179static inline void _write_fast(unsigned data) 99static 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. */
561void lcd_remote_update(void) ICODE_ATTR;
562void lcd_remote_update(void) 489void 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. */
585void lcd_remote_update_rect(int, int, int, int) ICODE_ATTR;
586void lcd_remote_update_rect(int x, int y, int width, int height) 512void 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 */