diff options
author | Jens Arnold <amiconn@rockbox.org> | 2004-05-04 06:29:41 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2004-05-04 06:29:41 +0000 |
commit | 2cae1dae1c2c56eb5fe903df67472483edb26ded (patch) | |
tree | 8eb0dbbad1dc684a93814e88fc5734387fd1ce25 /firmware/mpeg.c | |
parent | e2e4bc7cc32ef14f179f17477f7fe79bc4f84346 (diff) | |
download | rockbox-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
Diffstat (limited to 'firmware/mpeg.c')
-rw-r--r-- | firmware/mpeg.c | 177 |
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) | |||
460 | static long timing_info_index = 0; | 460 | static long timing_info_index = 0; |
461 | static long timing_info[1024]; | 461 | static long timing_info[1024]; |
462 | #endif /* #ifdef DEBUG */ | 462 | #endif /* #ifdef DEBUG */ |
463 | static bool inverted_pr; | ||
464 | static unsigned long num_rec_bytes; | 463 | static unsigned long num_rec_bytes; |
465 | static unsigned long num_recorded_frames; | 464 | static unsigned long num_recorded_frames; |
466 | 465 | ||
467 | static void drain_dma_buffer(void) | 466 | static 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); |