summaryrefslogtreecommitdiff
path: root/firmware/target/coldfire/iaudio/m3/lcd-as-m3.S
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/coldfire/iaudio/m3/lcd-as-m3.S')
-rw-r--r--firmware/target/coldfire/iaudio/m3/lcd-as-m3.S516
1 files changed, 516 insertions, 0 deletions
diff --git a/firmware/target/coldfire/iaudio/m3/lcd-as-m3.S b/firmware/target/coldfire/iaudio/m3/lcd-as-m3.S
new file mode 100644
index 0000000000..5f77e01e86
--- /dev/null
+++ b/firmware/target/coldfire/iaudio/m3/lcd-as-m3.S
@@ -0,0 +1,516 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Jens Arnold
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#define CLOCK_MASK 0x20000000
21#define DATA_MASK 0x04000000
22#define GPIO_OUT_ADDR 0x80000004
23
24#define CS_MASK 0x00010000
25#define RS_MASK 0x00001000
26#define GPIO1_OUT_ADDR 0x800000b4
27
28 .extern cpu_frequency /* Global variable from system.c */
29
30 .section .icode,"ax",@progbits
31
32 /* Output 8 bits to the LCD. Instruction order is devised to maximize the
33 * delay between changing the data line and the CLK L->H transition, which
34 * makes the LCD controller sample DATA.
35 *
36 * Custom calling convention:
37 * %a0 - GPIO_OUT_ADDR
38 * %d3 - data byte
39 * %d6 - DATA_MASK
40 * %d7 - CLOCK_MASK
41 * Clobbers:
42 * %d0..%d3
43 */
44.write_byte:
45 move.w %sr, %d2
46 move.w #0x2700, %sr
47
48 move.l (%a0), %d0 /* Get current state of data port */
49 move.l %d0, %d1
50 and.l %d6, %d1 /* Check current state of data line */
51 beq.s 1f /* and set it as previous-state bit */
52 bset #8, %d3
531:
54 move.l %d3, %d1 /* Compute the 'bit derivative', i.e. a value */
55 lsr.l #1, %d1 /* with 1's where the data changes from the */
56 eor.l %d1, %d3 /* previous state, and 0's where it doesn't */
57 swap %d3 /* Shift data to upper byte */
58 lsl.l #8, %d3
59
60 eor.l %d7, %d0 /* precalculate opposite state of clock line */
61
62 lsl.l #1,%d3 /* Shift out MSB */
63 bcc.s 1f
64 eor.l %d6, %d0 /* 1: Flip data bit */
651:
66 move.l %d0, %d1
67 move.l %d0, (%a0) /* Output new state and set CLK = 0*/
68 eor.l %d7, %d1
69 bra.w .wr_bit7
70
71
72 /* Output 16 bits to the LCD. Instruction order is devised to maximize the
73 * delay between changing the data line and the CLK L->H transition, which
74 * makes the LCD controller sample DATA.
75 *
76 * Custom calling convention:
77 * %a0 - GPIO_OUT_ADDR
78 * %d3 - data word
79 * %d6 - DATA_MASK
80 * %d7 - CLOCK_MASK
81 * Clobbers:
82 * %d0..%d3
83 */
84.write_word:
85 move.w %sr, %d2
86 move.w #0x2700, %sr
87
88 move.l (%a0), %d0 /* Get current state of data port */
89 move.l %d0, %d1
90 and.l %d6, %d1 /* Check current state of data line */
91 beq.s 1f /* and set it as previous-state bit */
92 bset #16, %d3
931:
94 move.l %d3, %d1 /* Compute the 'bit derivative', i.e. a value */
95 lsr.l #1, %d1 /* with 1's where the data changes from the */
96 eor.l %d1, %d3 /* previous state, and 0's where it doesn't */
97 swap %d3 /* Shift data to upper word */
98
99 eor.l %d7, %d0 /* precalculate opposite state of clock line */
100
101 lsl.l #1,%d3 /* Shift out MSB */
102 bcc.s 1f
103 eor.l %d6, %d0 /* 1: Flip data bit */
1041:
105 move.l %d0, %d1
106 move.l %d0, (%a0) /* Output new state and set CLK = 0*/
107 eor.l %d7, %d1
108 nop
109
110.macro bit_out
111 lsl.l #1,%d3
112 bcc.s 1f
113 eor.l %d6, %d0
1141:
115 move.l %d1, (%a0) /* Set CLK = 1 (delayed) */
116 move.l %d0, %d1
117 move.l %d0, (%a0)
118 eor.l %d7, %d1
119.endm
120 bit_out
121 nop
122 bit_out
123 nop
124 bit_out
125 nop
126 bit_out
127 nop
128 bit_out
129 nop
130 bit_out
131 nop
132 bit_out
133 nop
134 bit_out
135 nop
136
137.wr_bit7:
138 bit_out
139 nop
140 bit_out
141 nop
142 bit_out
143 nop
144 bit_out
145 nop
146 bit_out
147 nop
148 bit_out
149 nop
150 bit_out
151 nop
152
153 nop
154 move.l %d1, (%a0) /* Set CLK = 1 (delayed) */
155 move.w %d2, %sr
156 rts
157
158
159 /* Output 16 bits to the LCD as fast as possible. Use only at < 60MHz.
160 *
161 * Custom calling convention:
162 * %a0 - GPIO_OUT_ADDR
163 * %d3 - data word
164 * %d6 - DATA_MASK
165 * %d7 - CLOCK_MASK
166 * Clobbers:
167 * %d0..%d3
168 */
169.write_word_fast:
170 move.w %sr, %d2 /* Get current interrupt level */
171 move.w #0x2700, %sr /* Disable interrupts */
172
173 move.l (%a0), %d0 /* Get current state of data port */
174 move.l %d0, %d1
175 and.l %d6, %d1 /* Check current state of data line */
176 beq.s 1f /* and set it as previous-state bit */
177 bset #16, %d3
1781:
179 move.l %d3, %d1 /* Compute the 'bit derivative', i.e. a value */
180 lsr.l #1, %d1 /* with 1's where the data changes from the */
181 eor.l %d1, %d3 /* previous state, and 0's where it doesn't */
182 swap %d3 /* Shift data to upper byte */
183
184 move.l %d0, %d1 /* precalculate opposite state of clock line */
185 eor.l %d7, %d1
186
187.macro bit_out_fast
188 lsl.l #1,%d3 /* Shift out MSB */
189 bcc.s 1f
190 eor.l %d6, %d0 /* 1: Flip data bit */
191 eor.l %d6, %d1 /* for both clock states */
1921:
193 move.l %d1, (%a0) /* Output new state and set CLK = 0*/
194 move.l %d0, (%a0) /* set CLK = 1 */
195.endm
196 bit_out_fast
197 bit_out_fast
198 bit_out_fast
199 bit_out_fast
200 bit_out_fast
201 bit_out_fast
202 bit_out_fast
203 bit_out_fast
204 bit_out_fast
205 bit_out_fast
206 bit_out_fast
207 bit_out_fast
208 bit_out_fast
209 bit_out_fast
210 bit_out_fast
211 bit_out_fast
212
213 move.w %d2, %sr /* Restore interrupt level */
214 rts
215
216
217 .global lcd_write_command
218 .type lcd_write_command, @function
219
220lcd_write_command:
221 lea.l (-4*4, %sp), %sp
222 movem.l %d2-%d3/%d6-%d7, (%sp)
223
224 move.l (4*4+4, %sp), %d3 /* cmd */
225
226 lea.l GPIO_OUT_ADDR, %a0
227 lea.l GPIO1_OUT_ADDR, %a1
228 move.l #DATA_MASK, %d6
229 move.l #CLOCK_MASK, %d7
230
231 move.l #~(RS_MASK+CS_MASK), %d0
232 and.l %d0, (%a1)
233
234 bsr.w .write_byte
235
236 move.l #CS_MASK, %d0
237 or.l %d0, (%a1)
238
239 movem.l (%sp), %d2-%d3/%d6-%d7
240 lea.l (4*4, %sp), %sp
241 rts
242
243
244 .global lcd_write_command_e
245 .type lcd_write_command_e, @function
246
247lcd_write_command_e:
248 lea.l (-4*4, %sp), %sp
249 movem.l %d2-%d3/%d6-%d7, (%sp)
250
251 movem.l (4*4+4, %sp), %d2-%d3 /* cmd, data */
252
253 lea.l GPIO_OUT_ADDR, %a0
254 lea.l GPIO1_OUT_ADDR, %a1
255 move.l #DATA_MASK, %d6
256 move.l #CLOCK_MASK, %d7
257
258 move.l #~(RS_MASK+CS_MASK), %d0
259 and.l %d0, (%a1)
260
261 lsl.l #8, %d2
262 or.l %d2, %d3
263 bsr.w .write_word
264
265 move.l #CS_MASK, %d0
266 or.l %d0, (%a1)
267
268 movem.l (%sp), %d2-%d3/%d6-%d7
269 lea.l (4*4, %sp), %sp
270 rts
271
272
273 .global lcd_write_data
274 .type lcd_write_data, @function
275
276lcd_write_data:
277 lea.l (-7*4, %sp), %sp
278 movem.l %d2-%d4/%d6-%d7/%a2-%a3, (%sp)
279
280 move.l (7*4+4, %sp), %a2 /* p_words */
281 move.l (7*4+8, %sp), %d4 /* count */
282
283 lea.l GPIO_OUT_ADDR, %a0
284 lea.l GPIO1_OUT_ADDR, %a1
285 move.l #DATA_MASK, %d6
286 move.l #CLOCK_MASK, %d7
287
288 lea.l .write_word, %a3
289 move.l cpu_frequency, %d0
290 cmp.l #60000000, %d0
291 bhi.b 1f
292 lea.l .write_word_fast, %a3
2931:
294
295 move.l #RS_MASK, %d0
296 or.l %d0, (%a1)
297 move.l #~CS_MASK, %d0
298 and.l %d0, (%a1)
299
300.wd_loop:
301 clr.l %d3
302 move.w (%a2)+, %d3
303 jsr (%a3)
304 subq.l #1, %d4
305 bne.s .wd_loop
306
307 move.l #CS_MASK, %d0
308 or.l %d0, (%a1)
309
310 movem.l (%sp), %d2-%d4/%d6-%d7/%a2-%a3
311 lea.l (7*4, %sp), %sp
312 rts
313
314
315/*** The following functions are only needed for main LCDs ***/
316
317
318 .global lcd_mono_data
319 .type lcd_mono_data, @function
320
321lcd_mono_data:
322 lea.l (-7*4, %sp), %sp
323 movem.l %d2-%d4/%d6-%d7/%a2-%a3, (%sp)
324
325 move.l (7*4+4, %sp), %a2 /* p_bytes */
326 move.l (7*4+8, %sp), %d4 /* count */
327
328 lea.l GPIO_OUT_ADDR, %a0
329 lea.l GPIO1_OUT_ADDR, %a1
330 move.l #DATA_MASK, %d6
331 move.l #CLOCK_MASK, %d7
332
333 lea.l .write_word, %a3
334 move.l cpu_frequency, %d0
335 cmp.l #60000000, %d0
336 bhi.b 1f
337 lea.l .write_word_fast, %a3
3381:
339
340 move.l #RS_MASK, %d0
341 or.l %d0, (%a1)
342 move.l #~CS_MASK, %d0
343 and.l %d0, (%a1)
344
345.md_loop:
346 clr.l %d3
347 move.b (%a2)+, %d3
348 move.l %d3, %d2
349 lsl.l #8, %d2
350 or.l %d2, %d3
351 jsr (%a3)
352 subq.l #1, %d4
353 bne.s .md_loop
354
355 move.l #CS_MASK, %d0
356 or.l %d0, (%a1)
357
358 movem.l (%sp), %d2-%d4/%d6-%d7/%a2-%a3
359 lea.l (7*4, %sp), %sp
360 rts
361
362
363 .global lcd_grey_data
364 .type lcd_grey_data,@function
365
366lcd_grey_data:
367 lea.l (-9*4, %sp), %sp
368 movem.l %d2-%d7/%a2-%a4, (%sp)
369
370 movem.l (9*4+4, %sp), %a2-%a4 /* values, phases, length */
371 add.l %a4, %a4
372 lea.l (%a3, %a4.l*4), %a4 /* end address */
373
374 lea.l GPIO_OUT_ADDR, %a0
375 lea.l GPIO1_OUT_ADDR, %a1
376 move.l #DATA_MASK, %d6
377 move.l #CLOCK_MASK, %d7
378
379 move.l #RS_MASK, %d0
380 or.l %d0, (%a1)
381 move.l #~CS_MASK, %d0
382 and.l %d0, (%a1)
383
384 clr.l %d5
385 move.l (%a3), %d4 /* fetch 4 pixel phases */
386 bclr.l #31, %d4 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
387 seq.b %d5 /* %d5 = ........................00000000 */
388 lsl.l #1, %d5 /* %d5 = .......................00000000. */
389 bclr.l #23, %d4 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
390 seq.b %d5 /* %d5 = .......................011111111 */
391 lsl.l #1, %d5 /* %d5 = ......................011111111. */
392 bclr.l #15, %d4 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
393 seq.b %d5 /* %d5 = ......................0122222222 */
394 lsl.l #1, %d5 /* %d5 = .....................0122222222. */
395 bclr.l #7, %d4 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
396 seq.b %d5 /* %d5 = .....................01233333333 */
397 lsl.l #1, %d5 /* %d5 = ....................01233333333. */
398 add.l (%a2)+, %d4 /* add 4 pixel values to the phases */
399 move.l %d4, (%a3)+ /* store new phases, advance pointer */
400
401 move.l (%a3), %d4 /* fetch 4 pixel phases */
402 bclr.l #31, %d4 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
403 seq.b %d5 /* %d5 = ....................012344444444 */
404 lsl.l #1, %d5 /* %d5 = ...................012344444444. */
405 bclr.l #23, %d4 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
406 seq.b %d5 /* %d5 = ...................0123455555555 */
407 lsl.l #1, %d5 /* %d5 = ..................0123455555555. */
408 bclr.l #15, %d4 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
409 seq.b %d5 /* %d5 = ..................01234566666666 */
410 lsl.l #1, %d5 /* %d5 = .................01234566666666. */
411 bclr.l #7, %d4 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
412 seq.b %d5 /* %d5 = .................012345677777777 */
413 lsr.l #7, %d5 /* %d5 = ........................01234567 */
414 add.l (%a2)+, %d4 /* add 4 pixel values to the phases */
415 move.l %d4, (%a3)+ /* store new phases, advance pointer */
416
417 move.l %d5, %d3
418 lsl.l #8, %d3
419 or.l %d5, %d3
420
421 cmp.l %a3, %a4
422 bls.w .gd_last
423
424.gd_loop:
425 move.w %sr, %d2
426 move.w #0x2700, %sr
427
428 move.l (%a0), %d0 /* Get current state of data port */
429 move.l %d0, %d1
430 and.l %d6, %d1 /* Check current state of data line */
431 beq.s 1f /* and set it as previous-state bit */
432 bset #16, %d3
4331:
434 move.l %d3, %d1 /* Compute the 'bit derivative', i.e. a value */
435 lsr.l #1, %d1 /* with 1's where the data changes from the */
436 eor.l %d1, %d3 /* previous state, and 0's where it doesn't */
437 swap %d3 /* Shift data to upper word */
438
439 eor.l %d7, %d0 /* precalculate opposite state of clock line */
440
441 lsl.l #1,%d3 /* Shift out MSB */
442 bcc.s 1f
443 eor.l %d6, %d0 /* 1: Flip data bit */
4441:
445 move.l %d0, %d1
446 move.l %d0, (%a0) /* Output new state and set CLK = 0*/
447 eor.l %d7, %d1
448
449 move.l (%a3), %d4 /* fetch 4 pixel phases */
450 bit_out
451 bclr.l #31, %d4 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
452 seq.b %d5 /* %d5 = ........................00000000 */
453 lsl.l #1, %d5 /* %d5 = .......................00000000. */
454 bit_out
455 bclr.l #23, %d4 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
456 seq.b %d5 /* %d5 = .......................011111111 */
457 lsl.l #1, %d5 /* %d5 = ......................011111111. */
458 bit_out
459 bclr.l #15, %d4 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
460 seq.b %d5 /* %d5 = ......................0122222222 */
461 lsl.l #1, %d5 /* %d5 = .....................0122222222. */
462 bit_out
463 bclr.l #7, %d4 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
464 seq.b %d5 /* %d5 = .....................01233333333 */
465 lsl.l #1, %d5 /* %d5 = ....................01233333333. */
466 bit_out
467 add.l (%a2)+, %d4 /* add 4 pixel values to the phases */
468 bit_out
469 move.l %d4, (%a3)+ /* store new phases, advance pointer */
470
471 bit_out
472 move.l (%a3), %d4 /* fetch 4 pixel phases */
473 bit_out
474 bclr.l #31, %d4 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
475 seq.b %d5 /* %d5 = ....................012344444444 */
476 lsl.l #1, %d5 /* %d5 = ...................012344444444. */
477 bit_out
478 bclr.l #23, %d4 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
479 seq.b %d5 /* %d5 = ...................0123455555555 */
480 lsl.l #1, %d5 /* %d5 = ..................0123455555555. */
481 bit_out
482 bclr.l #15, %d4 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
483 seq.b %d5 /* %d5 = ..................01234566666666 */
484 lsl.l #1, %d5 /* %d5 = .................01234566666666. */
485 bit_out
486 bclr.l #7, %d4 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
487 seq.b %d5 /* %d5 = .................012345677777777 */
488 lsr.l #7, %d5 /* %d5 = ........................01234567 */
489 bit_out
490 add.l (%a2)+, %d4 /* add 4 pixel values to the phases */
491 bit_out
492 move.l %d4, (%a3)+ /* store new phases, advance pointer */
493
494 bit_out
495 nop
496 bit_out
497 move.l %d5, %d3
498 lsl.l #8, %d3
499 or.l %d5, %d3
500
501 nop
502 move.l %d1, (%a0) /* Set CLK = 1 (delayed) */
503 move.w %d2, %sr
504
505 cmp.l %a3, %a4
506 bhi.w .gd_loop
507
508.gd_last:
509 bsr.w .write_word
510
511 move.l #CS_MASK, %d0
512 or.l %d0, (%a1)
513
514 movem.l (%sp), %d2-%d7/%a2-%a4
515 lea.l (9*4, %sp), %sp
516 rts