rockbox/firmware/target/coldfire/iaudio/m3/lcd-as-m3.S
Daniel Stenberg 2acc0ac542 Updated our source code header to explicitly mention that we are GPL v2 or
later. We still need to hunt down snippets used that are not. 1324 modified
files...
http://www.rockbox.org/mail/archive/rockbox-dev-archive-2008-06/0060.shtml


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17847 a1c6a512-1295-4272-9138-f99709370657
2008-06-28 18:10:04 +00:00

553 lines
16 KiB
ArmAsm

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2008 by Jens Arnold
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#define CLOCK_MASK 0x20000000
#define DATA_MASK 0x04000000
#define GPIO_OUT_ADDR 0x80000004
#define CS_MASK 0x00010000
#define RS_MASK 0x00001000
#define GPIO1_OUT_ADDR 0x800000b4
.extern cpu_frequency /* Global variable from system.c */
.section .icode,"ax",@progbits
/* Output 8 bits to the LCD. Instruction order is devised to maximize the
* delay between changing the data line and the CLK L->H transition, which
* makes the LCD controller sample DATA.
* Requires CLK = 1 on entry.
*
* Custom calling convention:
* %a0 - GPIO_OUT_ADDR
* %d3 - data byte
* %d6 - DATA_MASK
* %d7 - CLOCK_MASK
* Clobbers:
* %d0..%d3
*/
.write_byte:
move.w %sr, %d2
move.w #0x2700, %sr
move.l (%a0), %d0 /* Get current state of data port */
move.l %d0, %d1
and.l %d6, %d1 /* Check current state of data line */
beq.s 1f /* and set it as previous-state bit */
bset #8, %d3
1:
move.l %d3, %d1 /* Compute the 'bit derivative', i.e. a value */
lsr.l #1, %d1 /* with 1's where the data changes from the */
eor.l %d1, %d3 /* previous state, and 0's where it doesn't */
swap %d3 /* Shift data to upper byte */
lsl.l #8, %d3
move.l %d0, %d1 /* precalculate opposite state of clock line */
eor.l %d7, %d1
lsl.l #1, %d3 /* Shift out MSB */
bcc.s 1f
eor.l %d6, %d0 /* 1: Flip data bit */
eor.l %d6, %d1
1:
move.l %d1, (%a0) /* Output new state and set CLK = 0*/
bra.w .wr_bit7
/* Output 16 bits to the LCD. Instruction order is devised to maximize the
* delay between changing the data line and the CLK L->H transition, which
* makes the LCD controller sample DATA.
* Requires CLK = 1 on entry.
*
* Custom calling convention:
* %a0 - GPIO_OUT_ADDR
* %d3 - data word
* %d6 - DATA_MASK
* %d7 - CLOCK_MASK
* Clobbers:
* %d0..%d3
*/
.write_word:
move.w %sr, %d2
move.w #0x2700, %sr
move.l (%a0), %d0 /* Get current state of data port */
move.l %d0, %d1
and.l %d6, %d1 /* Check current state of data line */
beq.s 1f /* and set it as previous-state bit */
bset #16, %d3
1:
move.l %d3, %d1 /* Compute the 'bit derivative', i.e. a value */
lsr.l #1, %d1 /* with 1's where the data changes from the */
eor.l %d1, %d3 /* previous state, and 0's where it doesn't */
swap %d3 /* Shift data to upper word */
move.l %d0, %d1 /* precalculate opposite state of clock line */
eor.l %d7, %d1
lsl.l #1, %d3 /* Shift out MSB */
bcc.s 1f
eor.l %d6, %d0 /* 1: Flip data bit */
eor.l %d6, %d1
1:
move.l %d1, (%a0) /* Output new state and set CLK = 0*/
.macro bit_out
move.l %d0, (%a0) /* Set CLK = 1 */
lsl.l #1, %d3
bcc.s 1f
eor.l %d6, %d0
eor.l %d6, %d1
1:
move.l %d1, (%a0)
.endm
nop
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
.wr_bit7:
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
nop
bit_out
nop
nop
move.l %d0, (%a0) /* Set CLK = 1 */
move.w %d2, %sr
rts
/* Output 16 bits to the LCD as fast as possible. Use only at < 60MHz.
*
* Custom calling convention:
* %a0 - GPIO_OUT_ADDR
* %d3 - data word
* %d6 - DATA_MASK
* %d7 - CLOCK_MASK
* Clobbers:
* %d0..%d3
*/
.write_word_fast:
move.w %sr, %d2 /* Get current interrupt level */
move.w #0x2700, %sr /* Disable interrupts */
move.l (%a0), %d0 /* Get current state of data port */
move.l %d0, %d1
and.l %d6, %d1 /* Check current state of data line */
beq.s 1f /* and set it as previous-state bit */
bset #16, %d3
1:
move.l %d3, %d1 /* Compute the 'bit derivative', i.e. a value */
lsr.l #1, %d1 /* with 1's where the data changes from the */
eor.l %d1, %d3 /* previous state, and 0's where it doesn't */
swap %d3 /* Shift data to upper byte */
move.l %d0, %d1 /* precalculate opposite state of clock line */
eor.l %d7, %d1
.macro bit_out_fast
lsl.l #1,%d3 /* Shift out MSB */
bcc.s 1f
eor.l %d6, %d0 /* 1: Flip data bit */
eor.l %d6, %d1 /* for both clock states */
1:
move.l %d1, (%a0) /* Output new state and set CLK = 0*/
move.l %d0, (%a0) /* set CLK = 1 */
.endm
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
bit_out_fast
move.w %d2, %sr /* Restore interrupt level */
rts
.global lcd_write_command
.type lcd_write_command, @function
lcd_write_command:
lea.l (-4*4, %sp), %sp
movem.l %d2-%d3/%d6-%d7, (%sp)
move.l (4*4+4, %sp), %d3 /* cmd */
lea.l GPIO_OUT_ADDR, %a0
lea.l GPIO1_OUT_ADDR, %a1
move.l #DATA_MASK, %d6
move.l #CLOCK_MASK, %d7
move.l #~(RS_MASK+CS_MASK), %d0
and.l %d0, (%a1)
bsr.w .write_byte
move.l #CS_MASK, %d0
or.l %d0, (%a1)
movem.l (%sp), %d2-%d3/%d6-%d7
lea.l (4*4, %sp), %sp
rts
.global lcd_write_command_e
.type lcd_write_command_e, @function
lcd_write_command_e:
lea.l (-4*4, %sp), %sp
movem.l %d2-%d3/%d6-%d7, (%sp)
movem.l (4*4+4, %sp), %d2-%d3 /* cmd, data */
lea.l GPIO_OUT_ADDR, %a0
lea.l GPIO1_OUT_ADDR, %a1
move.l #DATA_MASK, %d6
move.l #CLOCK_MASK, %d7
move.l #~(RS_MASK+CS_MASK), %d0
and.l %d0, (%a1)
lsl.l #8, %d2
or.l %d2, %d3
bsr.w .write_word
move.l #CS_MASK, %d0
or.l %d0, (%a1)
movem.l (%sp), %d2-%d3/%d6-%d7
lea.l (4*4, %sp), %sp
rts
.global lcd_write_data
.type lcd_write_data, @function
lcd_write_data:
lea.l (-7*4, %sp), %sp
movem.l %d2-%d4/%d6-%d7/%a2-%a3, (%sp)
move.l (7*4+4, %sp), %a2 /* p_words */
move.l (7*4+8, %sp), %d4 /* count */
lea.l GPIO_OUT_ADDR, %a0
lea.l GPIO1_OUT_ADDR, %a1
move.l #DATA_MASK, %d6
move.l #CLOCK_MASK, %d7
lea.l .write_word, %a3
move.l cpu_frequency, %d0
cmp.l #60000000, %d0
bhi.b 1f
lea.l .write_word_fast, %a3
1:
move.l #RS_MASK, %d0
or.l %d0, (%a1)
move.l #~CS_MASK, %d0
and.l %d0, (%a1)
.wd_loop:
clr.l %d3
move.w (%a2)+, %d3
jsr (%a3)
subq.l #1, %d4
bne.s .wd_loop
move.l #CS_MASK, %d0
or.l %d0, (%a1)
movem.l (%sp), %d2-%d4/%d6-%d7/%a2-%a3
lea.l (7*4, %sp), %sp
rts
/*** The following functions are only needed for main LCDs ***/
.global lcd_mono_data
.type lcd_mono_data, @function
lcd_mono_data:
lea.l (-7*4, %sp), %sp
movem.l %d2-%d4/%d6-%d7/%a2-%a3, (%sp)
move.l (7*4+4, %sp), %a2 /* p_bytes */
move.l (7*4+8, %sp), %d4 /* count */
lea.l GPIO_OUT_ADDR, %a0
lea.l GPIO1_OUT_ADDR, %a1
move.l #DATA_MASK, %d6
move.l #CLOCK_MASK, %d7
lea.l .write_word, %a3
move.l cpu_frequency, %d0
cmp.l #60000000, %d0
bhi.b 1f
lea.l .write_word_fast, %a3
1:
move.l #RS_MASK, %d0
or.l %d0, (%a1)
move.l #~CS_MASK, %d0
and.l %d0, (%a1)
.md_loop:
clr.l %d3
move.b (%a2)+, %d3
move.l %d3, %d2
lsl.l #8, %d2
or.l %d2, %d3
jsr (%a3)
subq.l #1, %d4
bne.s .md_loop
move.l #CS_MASK, %d0
or.l %d0, (%a1)
movem.l (%sp), %d2-%d4/%d6-%d7/%a2-%a3
lea.l (7*4, %sp), %sp
rts
.global lcd_grey_data
.type lcd_grey_data,@function
lcd_grey_data:
lea.l (-9*4, %sp), %sp
movem.l %d2-%d7/%a2-%a4, (%sp)
movem.l (9*4+4, %sp), %a2-%a4 /* values, phases, length */
add.l %a4, %a4
lea.l (%a3, %a4.l*4), %a4 /* end address */
lea.l GPIO_OUT_ADDR, %a0
lea.l GPIO1_OUT_ADDR, %a1
move.l #DATA_MASK, %d6
move.l #CLOCK_MASK, %d7
move.l #RS_MASK, %d0
or.l %d0, (%a1)
move.l #~CS_MASK, %d0
and.l %d0, (%a1)
clr.l %d5
move.l (%a3), %d4 /* fetch 4 pixel phases */
bclr.l #31, %d4 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
seq.b %d5 /* %d5 = ........................00000000 */
lsl.l #1, %d5 /* %d5 = .......................00000000. */
bclr.l #23, %d4 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
seq.b %d5 /* %d5 = .......................011111111 */
lsl.l #1, %d5 /* %d5 = ......................011111111. */
bclr.l #15, %d4 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
seq.b %d5 /* %d5 = ......................0122222222 */
lsl.l #1, %d5 /* %d5 = .....................0122222222. */
bclr.l #7, %d4 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
seq.b %d5 /* %d5 = .....................01233333333 */
lsl.l #1, %d5 /* %d5 = ....................01233333333. */
add.l (%a2)+, %d4 /* add 4 pixel values to the phases */
move.l %d4, (%a3)+ /* store new phases, advance pointer */
move.l (%a3), %d4 /* fetch 4 pixel phases */
bclr.l #31, %d4 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
seq.b %d5 /* %d5 = ....................012344444444 */
lsl.l #1, %d5 /* %d5 = ...................012344444444. */
bclr.l #23, %d4 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
seq.b %d5 /* %d5 = ...................0123455555555 */
lsl.l #1, %d5 /* %d5 = ..................0123455555555. */
bclr.l #15, %d4 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
seq.b %d5 /* %d5 = ..................01234566666666 */
lsl.l #1, %d5 /* %d5 = .................01234566666666. */
bclr.l #7, %d4 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
seq.b %d5 /* %d5 = .................012345677777777 */
lsr.l #7, %d5 /* %d5 = ........................01234567 */
add.l (%a2)+, %d4 /* add 4 pixel values to the phases */
move.l %d4, (%a3)+ /* store new phases, advance pointer */
move.l %d5, %d3
lsl.l #8, %d3
or.l %d5, %d3
cmp.l %a3, %a4
bls.w .gd_last
.gd_loop:
move.w %sr, %d2
move.w #0x2700, %sr
move.l (%a0), %d0 /* Get current state of data port */
move.l %d0, %d1
and.l %d6, %d1 /* Check current state of data line */
beq.s 1f /* and set it as previous-state bit */
bset #16, %d3
1:
move.l %d3, %d1 /* Compute the 'bit derivative', i.e. a value */
lsr.l #1, %d1 /* with 1's where the data changes from the */
eor.l %d1, %d3 /* previous state, and 0's where it doesn't */
swap %d3 /* Shift data to upper word */
move.l %d0, %d1 /* precalculate opposite state of clock line */
eor.l %d7, %d1
lsl.l #1, %d3 /* Shift out MSB */
bcc.s 1f
eor.l %d6, %d0 /* 1: Flip data bit */
eor.l %d6, %d1
1:
move.l %d1, (%a0) /* Output new state and set CLK = 0*/
move.l (%a3), %d4 /* fetch 4 pixel phases */
bit_out
bclr.l #31, %d4 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
seq.b %d5 /* %d5 = ........................00000000 */
lsl.l #1, %d5 /* %d5 = .......................00000000. */
trapf
trapf
bit_out
bclr.l #23, %d4 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
seq.b %d5 /* %d5 = .......................011111111 */
lsl.l #1, %d5 /* %d5 = ......................011111111. */
trapf
trapf
bit_out
bclr.l #15, %d4 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
seq.b %d5 /* %d5 = ......................0122222222 */
lsl.l #1, %d5 /* %d5 = .....................0122222222. */
trapf
trapf
bit_out
bclr.l #7, %d4 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
seq.b %d5 /* %d5 = .....................01233333333 */
lsl.l #1, %d5 /* %d5 = ....................01233333333. */
trapf
trapf
bit_out
add.l (%a2)+, %d4 /* add 4 pixel values to the phases */
bit_out
move.l %d4, (%a3)+ /* store new phases, advance pointer */
bit_out
move.l (%a3), %d4 /* fetch 4 pixel phases */
bit_out
bclr.l #31, %d4 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
seq.b %d5 /* %d5 = ....................012344444444 */
lsl.l #1, %d5 /* %d5 = ...................012344444444. */
trapf
trapf
bit_out
bclr.l #23, %d4 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
seq.b %d5 /* %d5 = ...................0123455555555 */
lsl.l #1, %d5 /* %d5 = ..................0123455555555. */
trapf
trapf
bit_out
bclr.l #15, %d4 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
seq.b %d5 /* %d5 = ..................01234566666666 */
lsl.l #1, %d5 /* %d5 = .................01234566666666. */
trapf
trapf
bit_out
bclr.l #7, %d4 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
seq.b %d5 /* %d5 = .................012345677777777 */
lsr.l #7, %d5 /* %d5 = ........................01234567 */
trapf
trapf
bit_out
add.l (%a2)+, %d4 /* add 4 pixel values to the phases */
bit_out
move.l %d4, (%a3)+ /* store new phases, advance pointer */
bit_out
nop
nop
bit_out
move.l %d5, %d3
lsl.l #8, %d3
or.l %d5, %d3
nop
move.l %d0, (%a0) /* Set CLK = 1 */
move.w %d2, %sr
cmp.l %a3, %a4
bhi.w .gd_loop
.gd_last:
bsr.w .write_word
move.l #CS_MASK, %d0
or.l %d0, (%a1)
movem.l (%sp), %d2-%d7/%a2-%a4
lea.l (9*4, %sp), %sp
rts