From 91a564e4b9c3141b7ff8595842522efe7434ec47 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Wed, 26 Mar 2008 23:40:17 +0000 Subject: 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 --- .../target/coldfire/iriver/lcd-remote-iriver.c | 194 +++++++-------------- 1 file changed, 60 insertions(+), 134 deletions(-) (limited to 'firmware/target/coldfire/iriver') 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) } #endif /* HAVE_REMOTE_LCD_TICKING */ -/* Standard low-level byte writer. Requires CLK low on entry */ -static inline void _write_byte(unsigned data) -{ - asm volatile ( - "move.l (%[gpo1]), %%d0 \n" /* Get current state of data line */ - "and.l %[dbit], %%d0 \n" - "beq.s 1f \n" /* and set it as previous-state bit */ - "bset #8, %[data] \n" - "1: \n" - "move.l %[data], %%d0 \n" /* Compute the 'bit derivative', i.e. a value */ - "lsr.l #1, %%d0 \n" /* with 1's where the data changes from the */ - "eor.l %%d0, %[data] \n" /* previous state, and 0's where it doesn't */ - "swap %[data] \n" /* Shift data to upper byte */ - "lsl.l #8, %[data] \n" - - "lsl.l #1,%[data] \n" /* Shift out MSB */ - "bcc.s 1f \n" - "eor.l %[dbit], (%[gpo1]) \n" /* 1: flip DATA */ - "1: \n" - "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */ - "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */ - - "lsl.l #1,%[data] \n" /* ..unrolled.. */ - "bcc.s 1f \n" - "eor.l %[dbit], (%[gpo1]) \n" - "1: \n" - "eor.l %[cbit], (%[gpo0]) \n" - "eor.l %[cbit], (%[gpo0]) \n" - - "lsl.l #1,%[data] \n" - "bcc.s 1f \n" - "eor.l %[dbit], (%[gpo1]) \n" - "1: \n" - "eor.l %[cbit], (%[gpo0]) \n" - "eor.l %[cbit], (%[gpo0]) \n" - - "lsl.l #1,%[data] \n" - "bcc.s 1f \n" - "eor.l %[dbit], (%[gpo1]) \n" - "1: \n" - "eor.l %[cbit], (%[gpo0]) \n" - "eor.l %[cbit], (%[gpo0]) \n" - - "lsl.l #1,%[data] \n" - "bcc.s 1f \n" - "eor.l %[dbit], (%[gpo1]) \n" - "1: \n" - "eor.l %[cbit], (%[gpo0]) \n" - "eor.l %[cbit], (%[gpo0]) \n" - - "lsl.l #1,%[data] \n" - "bcc.s 1f \n" - "eor.l %[dbit], (%[gpo1]) \n" - "1: \n" - "eor.l %[cbit], (%[gpo0]) \n" - "eor.l %[cbit], (%[gpo0]) \n" - - "lsl.l #1,%[data] \n" - "bcc.s 1f \n" - "eor.l %[dbit], (%[gpo1]) \n" - "1: \n" - "eor.l %[cbit], (%[gpo0]) \n" - "eor.l %[cbit], (%[gpo0]) \n" - - "lsl.l #1,%[data] \n" - "bcc.s 1f \n" - "eor.l %[dbit], (%[gpo1]) \n" - "1: \n" - "eor.l %[cbit], (%[gpo0]) \n" - "eor.l %[cbit], (%[gpo0]) \n" - : /* outputs */ - [data]"+d"(data) - : /* inputs */ - [gpo0]"a"(&GPIO_OUT), - [cbit]"d"(0x10000000), - [gpo1]"a"(&GPIO1_OUT), - [dbit]"d"(0x00040000) - : /* clobbers */ - "d0" - ); -} - -/* Fast low-level byte writer. Don't use with high CPU clock. +/* Low-level byte writer. 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, so it's fast yet usable even when boosted. * Requires CLK low on entry */ -static inline void _write_fast(unsigned data) +static inline void _write_byte(unsigned data) { asm volatile ( - "move.w %%sr,%%d3 \n" /* Get current interrupt level */ - "move.w #0x2700,%%sr \n" /* Disable interrupts */ + "move.w %%sr, %%d3 \n" /* Get current interrupt level */ + "move.w #0x2700, %%sr \n" /* Disable interrupts */ "move.l (%[gpo1]), %%d0 \n" /* Get current state of data port */ "move.l %%d0, %%d1 \n" @@ -194,75 +114,98 @@ static inline void _write_fast(unsigned data) "swap %[data] \n" /* Shift data to upper byte */ "lsl.l #8, %[data] \n" - "move.l (%[gpo0]), %%d1 \n" /* Get current state of clock port */ - "move.l %[cbit], %%d2 \n" /* Precalculate opposite state of clock line */ - "eor.l %%d1, %%d2 \n" - - "lsl.l #1,%[data] \n" /* Shift out MSB */ - "bcc.s 1f \n" - "eor.l %[dbit], %%d0 \n" /* 1: flip data bit */ - "move.l %%d0, (%[gpo1]) \n" /* and output new DATA state */ + "move.l (%[gpo0]),%%d1 \n" /* Get current state of clock port */ + "move.l %%d1, %%d2 \n" /* Precalculate opposite state of clock line */ + "eor.l %[cbit], %%d2 \n" + + "lsl.l #1, %[data] \n" /* Invert data line for bit7 ? */ + "bcc.s 1f \n" /* no: skip */ + "eor.l %[dbit], %%d0 \n" /* invert data bit */ + "move.l %%d0, (%[gpo1]) \n" /* output data bit7 */ "1: \n" - "move.l %%d2, (%[gpo0]) \n" /* Set CLK */ - "move.l %%d1, (%[gpo0]) \n" /* Reset CLK */ - "lsl.l #1,%[data] \n" /* ..unrolled.. */ + "lsl.l #1, %[data] \n" /* Invert data line for bit6 ? */ + "bcc.s 1f \n" /* no: skip */ + "eor.l %[dbit], %%d0 \n" /* Invert data bit */ + "move.l %%d2, (%[gpo0]) \n" /* Bit7: set CLK = 1 */ + "move.l %%d1, (%[gpo0]) \n" /* set CLK = 0 */ + "move.l %%d0, (%[gpo1]) \n" /* Output data bit6 */ + ".word 0x51fb \n" /* trapf.l - skip next 2 insns */ + "1: \n" /* else */ + "move.l %%d2, (%[gpo0]) \n" /* Bit7: set CLK = 1 */ + "move.l %%d1, (%[gpo0]) \n" /* set CLK = 0 */ + + "lsl.l #1, %[data] \n" /* Unrolled */ "bcc.s 1f \n" "eor.l %[dbit], %%d0 \n" - "move.l %%d0, (%[gpo1]) \n" - "1: \n" "move.l %%d2, (%[gpo0]) \n" "move.l %%d1, (%[gpo0]) \n" - - "lsl.l #1,%[data] \n" - "bcc.s 1f \n" - "eor.l %[dbit], %%d0 \n" "move.l %%d0, (%[gpo1]) \n" + ".word 0x51fb \n" "1: \n" "move.l %%d2, (%[gpo0]) \n" "move.l %%d1, (%[gpo0]) \n" - "lsl.l #1,%[data] \n" + "lsl.l #1, %[data] \n" "bcc.s 1f \n" "eor.l %[dbit], %%d0 \n" + "move.l %%d2, (%[gpo0]) \n" + "move.l %%d1, (%[gpo0]) \n" "move.l %%d0, (%[gpo1]) \n" + ".word 0x51fb \n" "1: \n" "move.l %%d2, (%[gpo0]) \n" "move.l %%d1, (%[gpo0]) \n" - "lsl.l #1,%[data] \n" + "lsl.l #1, %[data] \n" "bcc.s 1f \n" "eor.l %[dbit], %%d0 \n" + "move.l %%d2, (%[gpo0]) \n" + "move.l %%d1, (%[gpo0]) \n" "move.l %%d0, (%[gpo1]) \n" + ".word 0x51fb \n" "1: \n" "move.l %%d2, (%[gpo0]) \n" "move.l %%d1, (%[gpo0]) \n" - "lsl.l #1,%[data] \n" + "lsl.l #1, %[data] \n" "bcc.s 1f \n" "eor.l %[dbit], %%d0 \n" + "move.l %%d2, (%[gpo0]) \n" + "move.l %%d1, (%[gpo0]) \n" "move.l %%d0, (%[gpo1]) \n" + ".word 0x51fb \n" "1: \n" "move.l %%d2, (%[gpo0]) \n" "move.l %%d1, (%[gpo0]) \n" - "lsl.l #1,%[data] \n" + "lsl.l #1, %[data] \n" "bcc.s 1f \n" "eor.l %[dbit], %%d0 \n" + "move.l %%d2, (%[gpo0]) \n" + "move.l %%d1, (%[gpo0]) \n" "move.l %%d0, (%[gpo1]) \n" + ".word 0x51fb \n" "1: \n" "move.l %%d2, (%[gpo0]) \n" "move.l %%d1, (%[gpo0]) \n" - "lsl.l #1,%[data] \n" + "lsl.l #1, %[data] \n" "bcc.s 1f \n" "eor.l %[dbit], %%d0 \n" + "move.l %%d2, (%[gpo0]) \n" + "move.l %%d1, (%[gpo0]) \n" "move.l %%d0, (%[gpo1]) \n" + ".word 0x51fb \n" "1: \n" "move.l %%d2, (%[gpo0]) \n" "move.l %%d1, (%[gpo0]) \n" - "move.w %%d3, %%sr \n" /* Restore interrupt level */ + "nop \n" /* Let data line settle */ + "move.l %%d2, (%[gpo0]) \n" /* Bit0: Set CLK = 1 */ + "move.l %%d1, (%[gpo0]) \n" /* Set CLK = 0 */ + + "move.w %%d3, %%sr \n" /* Restore interrupt level */ : /* outputs */ [data]"+d"(data) : /* inputs */ @@ -283,7 +226,7 @@ void lcd_remote_write_command(int cmd) _write_byte(cmd); #ifdef HAVE_REMOTE_LCD_TICKING - _byte_delay(byte_delay - 148); + _byte_delay(byte_delay); #endif cs_countdown = CS_TIMEOUT; @@ -297,11 +240,11 @@ void lcd_remote_write_command_ex(int cmd, int data) _write_byte(cmd); #ifdef HAVE_REMOTE_LCD_TICKING - _byte_delay(byte_delay - 148); + _byte_delay(byte_delay); #endif _write_byte(data); #ifdef HAVE_REMOTE_LCD_TICKING - _byte_delay(byte_delay - 148); + _byte_delay(byte_delay); #endif cs_countdown = CS_TIMEOUT; @@ -316,27 +259,12 @@ void lcd_remote_write_data(const unsigned char* p_bytes, int count) RS_HI; CS_LO; - /* This is safe as long as lcd_remote_write_data() isn't called from within - * an ISR. */ - if (cpu_frequency < 50000000) + while (p_bytes < p_end) { - while (p_bytes < p_end) - { - _write_fast(*p_bytes++); + _write_byte(*p_bytes++); #ifdef HAVE_REMOTE_LCD_TICKING - _byte_delay(byte_delay - 87); + _byte_delay(byte_delay); #endif - } - } - else - { - while (p_bytes < p_end) - { - _write_byte(*p_bytes++); -#ifdef HAVE_REMOTE_LCD_TICKING - _byte_delay(byte_delay - 148); -#endif - } } cs_countdown = CS_TIMEOUT; @@ -558,7 +486,6 @@ void lcd_remote_init_device(void) /* Update the display. This must be called after all other LCD functions that change the display. */ -void lcd_remote_update(void) ICODE_ATTR; void lcd_remote_update(void) { int y; @@ -568,7 +495,7 @@ void lcd_remote_update(void) #ifdef HAVE_REMOTE_LCD_TICKING /* Adjust byte delay for emi reduction. */ - byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0; + byte_delay = emireduce ? cpu_frequency / 192800 - 90: 0; #endif /* Copy display bitmap to hardware */ @@ -582,7 +509,6 @@ void lcd_remote_update(void) } /* Update a fraction of the display. */ -void lcd_remote_update_rect(int, int, int, int) ICODE_ATTR; void lcd_remote_update_rect(int x, int y, int width, int height) { int ymax; @@ -603,7 +529,7 @@ void lcd_remote_update_rect(int x, int y, int width, int height) #ifdef HAVE_REMOTE_LCD_TICKING /* Adjust byte delay for emi reduction */ - byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0; + byte_delay = emireduce ? cpu_frequency / 192800 - 90: 0; #endif /* Copy specified rectange bitmap to hardware */ -- cgit v1.2.3