summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2004-05-04 06:29:41 +0000
committerJens Arnold <amiconn@rockbox.org>2004-05-04 06:29:41 +0000
commit2cae1dae1c2c56eb5fe903df67472483edb26ded (patch)
tree8eb0dbbad1dc684a93814e88fc5734387fd1ce25 /firmware
parente2e4bc7cc32ef14f179f17477f7fe79bc4f84346 (diff)
Unified & assembler optimized recording transfer routines: Smaller & 50% faster
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4576 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/mpeg.c177
1 files changed, 86 insertions, 91 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 814217f26b..bf0512dfc2 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -460,47 +460,40 @@ static int get_unsaved_space(void)
static long timing_info_index = 0;
static long timing_info[1024];
#endif /* #ifdef DEBUG */
-static bool inverted_pr;
static unsigned long num_rec_bytes;
static unsigned long num_recorded_frames;
static void drain_dma_buffer(void)
{
- if(inverted_pr)
- {
- while((*((volatile unsigned char *)PBDR_ADDR) & 0x40))
- {
- or_b(0x08, &PADRH);
-
- while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
-
- /* It must take at least 5 cycles before
- the data is read */
- asm(" nop\n nop\n nop\n");
- asm(" nop\n nop\n nop\n");
- and_b(~0x08, &PADRH);
-
- while(!(*((volatile unsigned char *)PBDR_ADDR) & 0x80));
- }
- }
- else
- {
- while((*((volatile unsigned char *)PBDR_ADDR) & 0x40))
- {
- and_b(~0x08, &PADRH);
-
- while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
+ asm (
+ "mov #0x40,r2 \n" /* mask for EOD check */
+ "bra .d_start \n"
+ "mov.b @%0,r1 \n" /* read PBDR (first time) */
+
+ ".d_loop: \n"
+ "xor.b #0x08,@(r0,gbr) \n" /* set PR active */
+ ".d_wait1: \n"
+ "mov.b @%0,r1 \n" /* read PBDR */
+ "cmp/pz r1 \n" /* and wait for PRTW */
+ "bf .d_wait1 \n"
+
+ "xor.b #0x08,@(r0,gbr) \n" /* reset PR to inactive */
+ ".d_wait2: \n"
+ "mov.b @%0,r1 \n" /* read PBDR */
+ "cmp/pz r1 \n" /* and wait for /PRTW */
+ "bt .d_wait2 \n"
- /* It must take at least 5 cycles before
- the data is read */
- asm(" nop\n nop\n nop\n");
- asm(" nop\n nop\n nop\n");
-
- or_b(0x08, &PADRH);
-
- while(!(*((volatile unsigned char *)PBDR_ADDR) & 0x80));
- }
- }
+ ".d_start: \n"
+ "tst r1,r2 \n" /* EOD low? */
+ "bf .d_loop \n" /* no: next pass */
+
+ : /* outputs */
+ : /* inputs */
+ /* %0 */ "r"(PBDR_ADDR),
+ /* %1 = r0 */ "z"(&PADRH)
+ : /* clobbers */
+ "r1","r2"
+ );
}
#endif /* #ifdef HAVE_MAS3587F */
@@ -517,59 +510,61 @@ void rec_tick(void)
timing_info[timing_info_index++] = current_tick;
TCNT2 = 0;
#endif /* #ifdef DEBUG */
- /* We read as long as EOD is high, but max 30 bytes.
- This code is optimized, and should probably be
- written in assembler instead. */
- if(inverted_pr)
- {
- i = 0;
- while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
- && i < 30)
- {
- or_b(0x08, &PADRH);
-
- while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
-
- /* It must take at least 5 cycles before
- the data is read */
- asm(" nop\n nop\n nop\n");
- mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;
-
- if(mp3buf_write >= mp3buflen)
- mp3buf_write = 0;
-
- i++;
-
- and_b(~0x08, &PADRH);
-
- /* No wait for /RTW, cause it's not necessary */
- }
- }
- else /* !inverted_pr */
- {
- i = 0;
- while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
- && i < 30)
- {
- and_b(~0x08, &PADRH);
-
- while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
-
- /* It must take at least 5 cycles before
- the data is read */
- asm(" nop\n nop\n nop\n");
- mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;
-
- if(mp3buf_write >= mp3buflen)
- mp3buf_write = 0;
-
- i++;
-
- or_b(0x08, &PADRH);
-
- /* No wait for /RTW, cause it's not necessary */
- }
- }
+ /* We read as long as EOD is high, but max 30 bytes. */
+ asm (
+ "mov #30,r3 \n" /* i_max = 30 */
+ "mov #0x40,r2 \n" /* mask for EOD check */
+ "mov #0,%0 \n" /* i = 0; */
+ "add %2,%1 \n" /* mp3buf_write -> cur_addr */
+ "add %2,%3 \n" /* mp3buflen -> end_addr */
+ "bra .r_start \n"
+ "mov.b @%4,r1 \n" /* read PBDR (first time) */
+
+ ".align 2 \n"
+
+ ".r_loop: \n"
+ "xor.b #0x08,@(r0,gbr) \n" /* set PR active */
+ ".r_wait1: \n"
+ "mov.b @%4,r1 \n" /* read PBDR */
+ "cmp/pz r1 \n" /* and wait for PRTW */
+ "bf .r_wait1 \n"
+
+ "mov.b @%6,r1 \n" /* read byte from mas */
+ "add #1,%0 \n" /* i++; */
+ "mov.b r1,@%1 \n" /* store byte */
+ "add #1,%1 \n" /* increment current address */
+
+ "cmp/hi %1,%3 \n" /* end address reached? */
+ "bt .r_nowrap \n" /* no: do nothing */
+ "mov %2,%1 \n" /* yes: reset to start address */
+ ".r_nowrap: \n"
+
+ "xor.b #0x08,@(r0,gbr) \n" /* set PR inactive again */
+ ".r_wait2: \n"
+ "mov.b @%4,r1 \n" /* read PBDR */
+ "cmp/pz r1 \n" /* and wait for /PRTW */
+ "bt .r_wait2 \n"
+
+ ".r_start: \n"
+ "tst r2,r1 \n" /* EOD low? */
+ "bt .r_end \n" /* yes: end of transfer */
+ "cmp/hi %0,r3 \n" /* i < i_max? */
+ "bt .r_loop \n" /* yes: next pass */
+
+ ".r_end: \n"
+ "sub %2,%1 \n" /* cur_addr -> mp3buf_write */
+ : /* outputs */
+ /* %0 */ "=&r"(i),
+ /* %1, in & out */ "+r"(mp3buf_write)
+ : /* inputs */
+ /* %2 */ "r"(mp3buf),
+ /* %3 */ "r"(mp3buflen),
+ /* %4 */ "r"(PBDR_ADDR),
+ /* %5 = r0 */ "z"(&PADRH),
+ /* %6 */ "r"(0x4000000)
+ : /* clobbers */
+ "r1","r2","r3"
+ );
#ifdef DEBUG
timing_info[timing_info_index++] = TCNT2 + (i << 16);
timing_info_index &= 0x3ff;
@@ -2631,11 +2626,11 @@ void mpeg_init(void)
#ifdef HAVE_MAS3587F
if(read_hw_mask() & PR_ACTIVE_HIGH)
- inverted_pr = true;
+ and_b(~0x08, &PADRH);
else
- inverted_pr = false;
+ or_b(0x08, &PADRH);
#endif /* #ifdef HAVE_MAS3587F */
-
+
#ifdef DEBUG
dbg_timer_start();
dbg_cnt2us(0);