summaryrefslogtreecommitdiff
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
parente2e4bc7cc32ef14f179f17477f7fe79bc4f84346 (diff)
downloadrockbox-2cae1dae1c2c56eb5fe903df67472483edb26ded.tar.gz
rockbox-2cae1dae1c2c56eb5fe903df67472483edb26ded.zip
Unified & assembler optimized recording transfer routines: Smaller & 50% faster
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4576 a1c6a512-1295-4272-9138-f99709370657
-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)
460static long timing_info_index = 0; 460static long timing_info_index = 0;
461static long timing_info[1024]; 461static long timing_info[1024];
462#endif /* #ifdef DEBUG */ 462#endif /* #ifdef DEBUG */
463static bool inverted_pr;
464static unsigned long num_rec_bytes; 463static unsigned long num_rec_bytes;
465static unsigned long num_recorded_frames; 464static unsigned long num_recorded_frames;
466 465
467static void drain_dma_buffer(void) 466static void drain_dma_buffer(void)
468{ 467{
469 if(inverted_pr) 468 asm (
470 { 469 "mov #0x40,r2 \n" /* mask for EOD check */
471 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)) 470 "bra .d_start \n"
472 { 471 "mov.b @%0,r1 \n" /* read PBDR (first time) */
473 or_b(0x08, &PADRH); 472
474 473 ".d_loop: \n"
475 while(*((volatile unsigned char *)PBDR_ADDR) & 0x80); 474 "xor.b #0x08,@(r0,gbr) \n" /* set PR active */
476 475 ".d_wait1: \n"
477 /* It must take at least 5 cycles before 476 "mov.b @%0,r1 \n" /* read PBDR */
478 the data is read */ 477 "cmp/pz r1 \n" /* and wait for PRTW */
479 asm(" nop\n nop\n nop\n"); 478 "bf .d_wait1 \n"
480 asm(" nop\n nop\n nop\n"); 479
481 and_b(~0x08, &PADRH); 480 "xor.b #0x08,@(r0,gbr) \n" /* reset PR to inactive */
482 481 ".d_wait2: \n"
483 while(!(*((volatile unsigned char *)PBDR_ADDR) & 0x80)); 482 "mov.b @%0,r1 \n" /* read PBDR */
484 } 483 "cmp/pz r1 \n" /* and wait for /PRTW */
485 } 484 "bt .d_wait2 \n"
486 else
487 {
488 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40))
489 {
490 and_b(~0x08, &PADRH);
491
492 while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
493 485
494 /* It must take at least 5 cycles before 486 ".d_start: \n"
495 the data is read */ 487 "tst r1,r2 \n" /* EOD low? */
496 asm(" nop\n nop\n nop\n"); 488 "bf .d_loop \n" /* no: next pass */
497 asm(" nop\n nop\n nop\n"); 489
498 490 : /* outputs */
499 or_b(0x08, &PADRH); 491 : /* inputs */
500 492 /* %0 */ "r"(PBDR_ADDR),
501 while(!(*((volatile unsigned char *)PBDR_ADDR) & 0x80)); 493 /* %1 = r0 */ "z"(&PADRH)
502 } 494 : /* clobbers */
503 } 495 "r1","r2"
496 );
504} 497}
505 498
506#endif /* #ifdef HAVE_MAS3587F */ 499#endif /* #ifdef HAVE_MAS3587F */
@@ -517,59 +510,61 @@ void rec_tick(void)
517 timing_info[timing_info_index++] = current_tick; 510 timing_info[timing_info_index++] = current_tick;
518 TCNT2 = 0; 511 TCNT2 = 0;
519#endif /* #ifdef DEBUG */ 512#endif /* #ifdef DEBUG */
520 /* We read as long as EOD is high, but max 30 bytes. 513 /* We read as long as EOD is high, but max 30 bytes. */
521 This code is optimized, and should probably be 514 asm (
522 written in assembler instead. */ 515 "mov #30,r3 \n" /* i_max = 30 */
523 if(inverted_pr) 516 "mov #0x40,r2 \n" /* mask for EOD check */
524 { 517 "mov #0,%0 \n" /* i = 0; */
525 i = 0; 518 "add %2,%1 \n" /* mp3buf_write -> cur_addr */
526 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40) 519 "add %2,%3 \n" /* mp3buflen -> end_addr */
527 && i < 30) 520 "bra .r_start \n"
528 { 521 "mov.b @%4,r1 \n" /* read PBDR (first time) */
529 or_b(0x08, &PADRH); 522
530 523 ".align 2 \n"
531 while(*((volatile unsigned char *)PBDR_ADDR) & 0x80); 524
532 525 ".r_loop: \n"
533 /* It must take at least 5 cycles before 526 "xor.b #0x08,@(r0,gbr) \n" /* set PR active */
534 the data is read */ 527 ".r_wait1: \n"
535 asm(" nop\n nop\n nop\n"); 528 "mov.b @%4,r1 \n" /* read PBDR */
536 mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000; 529 "cmp/pz r1 \n" /* and wait for PRTW */
537 530 "bf .r_wait1 \n"
538 if(mp3buf_write >= mp3buflen) 531
539 mp3buf_write = 0; 532 "mov.b @%6,r1 \n" /* read byte from mas */
540 533 "add #1,%0 \n" /* i++; */
541 i++; 534 "mov.b r1,@%1 \n" /* store byte */
542 535 "add #1,%1 \n" /* increment current address */
543 and_b(~0x08, &PADRH); 536
544 537 "cmp/hi %1,%3 \n" /* end address reached? */
545 /* No wait for /RTW, cause it's not necessary */ 538 "bt .r_nowrap \n" /* no: do nothing */
546 } 539 "mov %2,%1 \n" /* yes: reset to start address */
547 } 540 ".r_nowrap: \n"
548 else /* !inverted_pr */ 541
549 { 542 "xor.b #0x08,@(r0,gbr) \n" /* set PR inactive again */
550 i = 0; 543 ".r_wait2: \n"
551 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40) 544 "mov.b @%4,r1 \n" /* read PBDR */
552 && i < 30) 545 "cmp/pz r1 \n" /* and wait for /PRTW */
553 { 546 "bt .r_wait2 \n"
554 and_b(~0x08, &PADRH); 547
555 548 ".r_start: \n"
556 while(*((volatile unsigned char *)PBDR_ADDR) & 0x80); 549 "tst r2,r1 \n" /* EOD low? */
557 550 "bt .r_end \n" /* yes: end of transfer */
558 /* It must take at least 5 cycles before 551 "cmp/hi %0,r3 \n" /* i < i_max? */
559 the data is read */ 552 "bt .r_loop \n" /* yes: next pass */
560 asm(" nop\n nop\n nop\n"); 553
561 mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000; 554 ".r_end: \n"
562 555 "sub %2,%1 \n" /* cur_addr -> mp3buf_write */
563 if(mp3buf_write >= mp3buflen) 556 : /* outputs */
564 mp3buf_write = 0; 557 /* %0 */ "=&r"(i),
565 558 /* %1, in & out */ "+r"(mp3buf_write)
566 i++; 559 : /* inputs */
567 560 /* %2 */ "r"(mp3buf),
568 or_b(0x08, &PADRH); 561 /* %3 */ "r"(mp3buflen),
569 562 /* %4 */ "r"(PBDR_ADDR),
570 /* No wait for /RTW, cause it's not necessary */ 563 /* %5 = r0 */ "z"(&PADRH),
571 } 564 /* %6 */ "r"(0x4000000)
572 } 565 : /* clobbers */
566 "r1","r2","r3"
567 );
573#ifdef DEBUG 568#ifdef DEBUG
574 timing_info[timing_info_index++] = TCNT2 + (i << 16); 569 timing_info[timing_info_index++] = TCNT2 + (i << 16);
575 timing_info_index &= 0x3ff; 570 timing_info_index &= 0x3ff;
@@ -2631,11 +2626,11 @@ void mpeg_init(void)
2631 2626
2632#ifdef HAVE_MAS3587F 2627#ifdef HAVE_MAS3587F
2633 if(read_hw_mask() & PR_ACTIVE_HIGH) 2628 if(read_hw_mask() & PR_ACTIVE_HIGH)
2634 inverted_pr = true; 2629 and_b(~0x08, &PADRH);
2635 else 2630 else
2636 inverted_pr = false; 2631 or_b(0x08, &PADRH);
2637#endif /* #ifdef HAVE_MAS3587F */ 2632#endif /* #ifdef HAVE_MAS3587F */
2638 2633
2639#ifdef DEBUG 2634#ifdef DEBUG
2640 dbg_timer_start(); 2635 dbg_timer_start();
2641 dbg_cnt2us(0); 2636 dbg_cnt2us(0);