diff options
Diffstat (limited to 'firmware/mpeg.c')
-rw-r--r-- | firmware/mpeg.c | 276 |
1 files changed, 93 insertions, 183 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c index 29836dd14e..12d71a1dbd 100644 --- a/firmware/mpeg.c +++ b/firmware/mpeg.c | |||
@@ -74,7 +74,7 @@ static int get_unswapped_space(void); | |||
74 | #define MPEG_STOP_DONE 103 | 74 | #define MPEG_STOP_DONE 103 |
75 | 75 | ||
76 | #ifdef HAVE_MAS3587F | 76 | #ifdef HAVE_MAS3587F |
77 | static enum | 77 | extern enum /* from mp3_playback.c */ |
78 | { | 78 | { |
79 | MPEG_DECODER, | 79 | MPEG_DECODER, |
80 | MPEG_ENCODER | 80 | MPEG_ENCODER |
@@ -371,33 +371,6 @@ void mpeg_get_debugdata(struct mpeg_debug *dbgdata) | |||
371 | dbgdata->lowest_watermark_level = lowest_watermark_level; | 371 | dbgdata->lowest_watermark_level = lowest_watermark_level; |
372 | } | 372 | } |
373 | 373 | ||
374 | #ifndef HAVE_MAS3507D | ||
375 | static void postpone_dma_tick(void) | ||
376 | { | ||
377 | unsigned int count; | ||
378 | |||
379 | count = FREQ / 1000 / 8; | ||
380 | |||
381 | /* We are using timer 1 */ | ||
382 | |||
383 | TSTR &= ~0x02; /* Stop the timer */ | ||
384 | TSNC &= ~0x02; /* No synchronization */ | ||
385 | TMDR &= ~0x02; /* Operate normally */ | ||
386 | |||
387 | TCNT1 = 0; /* Start counting at 0 */ | ||
388 | GRA1 = count; | ||
389 | TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */ | ||
390 | |||
391 | /* Enable interrupt on level 5 */ | ||
392 | IPRC = (IPRC & ~0x000f) | 0x0005; | ||
393 | |||
394 | TSR1 &= ~0x02; | ||
395 | TIER1 = 0xf9; /* Enable GRA match interrupt */ | ||
396 | |||
397 | TSTR |= 0x02; /* Start timer 1 */ | ||
398 | } | ||
399 | #endif /* #ifndef HAVE_MAS3507D */ | ||
400 | |||
401 | #ifdef DEBUG | 374 | #ifdef DEBUG |
402 | static void dbg_timer_start(void) | 375 | static void dbg_timer_start(void) |
403 | { | 376 | { |
@@ -524,134 +497,122 @@ static void drain_dma_buffer(void) | |||
524 | 497 | ||
525 | #endif /* #ifdef HAVE_MAS3587F */ | 498 | #endif /* #ifdef HAVE_MAS3587F */ |
526 | 499 | ||
527 | static void dma_tick (void) __attribute__ ((section (".icode"))); | 500 | void rec_tick (void) __attribute__ ((section (".icode"))); |
528 | static void dma_tick(void) | 501 | void rec_tick(void) |
529 | { | 502 | { |
530 | #ifdef HAVE_MAS3587F | 503 | #ifdef HAVE_MAS3587F |
531 | if(mpeg_mode == MPEG_DECODER) | 504 | int i; |
532 | { | 505 | int num_bytes; |
533 | #endif /* #ifdef HAVE_MAS3587F */ | 506 | if(is_recording && (PBDR & 0x4000)) |
534 | if(playing && !paused) | ||
535 | { | ||
536 | /* Start DMA if it is disabled and the DEMAND pin is high */ | ||
537 | if(!(SCR0 & 0x80) && (PBDR & 0x4000)) | ||
538 | { | ||
539 | mp3_play_pause(true); | ||
540 | } | ||
541 | id3tags[tag_read_idx]->id3.elapsed += | ||
542 | (current_tick - last_dma_tick) * 1000 / HZ; | ||
543 | last_dma_tick = current_tick; | ||
544 | } | ||
545 | #ifdef HAVE_MAS3587F | ||
546 | } | ||
547 | else /* MPEG_ENCODER */ | ||
548 | { | 507 | { |
549 | int i; | ||
550 | int num_bytes; | ||
551 | if(is_recording && (PBDR & 0x4000)) | ||
552 | { | ||
553 | #ifdef DEBUG | 508 | #ifdef DEBUG |
554 | timing_info[timing_info_index++] = current_tick; | 509 | timing_info[timing_info_index++] = current_tick; |
555 | TCNT2 = 0; | 510 | TCNT2 = 0; |
556 | #endif /* #ifdef DEBUG */ | 511 | #endif /* #ifdef DEBUG */ |
557 | /* We read as long as EOD is high, but max 30 bytes. | 512 | /* We read as long as EOD is high, but max 30 bytes. |
558 | This code is optimized, and should probably be | 513 | This code is optimized, and should probably be |
559 | written in assembler instead. */ | 514 | written in assembler instead. */ |
560 | if(inverted_pr) | 515 | if(inverted_pr) |
516 | { | ||
517 | i = 0; | ||
518 | while((*((volatile unsigned char *)PBDR_ADDR) & 0x40) | ||
519 | && i < 30) | ||
561 | { | 520 | { |
562 | i = 0; | 521 | or_b(0x08, &PADRH); |
563 | while((*((volatile unsigned char *)PBDR_ADDR) & 0x40) | ||
564 | && i < 30) | ||
565 | { | ||
566 | or_b(0x08, &PADRH); | ||
567 | 522 | ||
568 | while(*((volatile unsigned char *)PBDR_ADDR) & 0x80); | 523 | while(*((volatile unsigned char *)PBDR_ADDR) & 0x80); |
569 | 524 | ||
570 | /* It must take at least 5 cycles before | 525 | /* It must take at least 5 cycles before |
571 | the data is read */ | 526 | the data is read */ |
572 | asm(" nop\n nop\n nop\n"); | 527 | asm(" nop\n nop\n nop\n"); |
573 | mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000; | 528 | mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000; |
574 | 529 | ||
575 | if(mp3buf_write >= mp3buflen) | 530 | if(mp3buf_write >= mp3buflen) |
576 | mp3buf_write = 0; | 531 | mp3buf_write = 0; |
577 | 532 | ||
578 | i++; | 533 | i++; |
579 | 534 | ||
580 | and_b(~0x08, &PADRH); | 535 | and_b(~0x08, &PADRH); |
581 | 536 | ||
582 | /* No wait for /RTW, cause it's not necessary */ | 537 | /* No wait for /RTW, cause it's not necessary */ |
583 | } | ||
584 | } | 538 | } |
585 | else /* !inverted_pr */ | 539 | } |
540 | else /* !inverted_pr */ | ||
541 | { | ||
542 | i = 0; | ||
543 | while((*((volatile unsigned char *)PBDR_ADDR) & 0x40) | ||
544 | && i < 30) | ||
586 | { | 545 | { |
587 | i = 0; | 546 | and_b(~0x08, &PADRH); |
588 | while((*((volatile unsigned char *)PBDR_ADDR) & 0x40) | 547 | |
589 | && i < 30) | 548 | while(*((volatile unsigned char *)PBDR_ADDR) & 0x80); |
590 | { | 549 | |
591 | and_b(~0x08, &PADRH); | 550 | /* It must take at least 5 cycles before |
592 | 551 | the data is read */ | |
593 | while(*((volatile unsigned char *)PBDR_ADDR) & 0x80); | 552 | asm(" nop\n nop\n nop\n"); |
594 | 553 | mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000; | |
595 | /* It must take at least 5 cycles before | 554 | |
596 | the data is read */ | 555 | if(mp3buf_write >= mp3buflen) |
597 | asm(" nop\n nop\n nop\n"); | 556 | mp3buf_write = 0; |
598 | mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000; | ||
599 | |||
600 | if(mp3buf_write >= mp3buflen) | ||
601 | mp3buf_write = 0; | ||
602 | 557 | ||
603 | i++; | 558 | i++; |
604 | 559 | ||
605 | or_b(0x08, &PADRH); | 560 | or_b(0x08, &PADRH); |
606 | 561 | ||
607 | /* No wait for /RTW, cause it's not necessary */ | 562 | /* No wait for /RTW, cause it's not necessary */ |
608 | } | ||
609 | } | 563 | } |
564 | } | ||
610 | #ifdef DEBUG | 565 | #ifdef DEBUG |
611 | timing_info[timing_info_index++] = TCNT2 + (i << 16); | 566 | timing_info[timing_info_index++] = TCNT2 + (i << 16); |
612 | timing_info_index &= 0x3ff; | 567 | timing_info_index &= 0x3ff; |
613 | #endif /* #ifdef DEBUG */ | 568 | #endif /* #ifdef DEBUG */ |
614 | 569 | ||
615 | num_rec_bytes += i; | 570 | num_rec_bytes += i; |
616 | 571 | ||
617 | if(is_prerecording) | 572 | if(is_prerecording) |
573 | { | ||
574 | if(TIME_AFTER(current_tick, prerecord_timeout)) | ||
618 | { | 575 | { |
619 | if(TIME_AFTER(current_tick, prerecord_timeout)) | 576 | prerecord_timeout = current_tick + HZ; |
620 | { | ||
621 | prerecord_timeout = current_tick + HZ; | ||
622 | 577 | ||
623 | /* Store the write pointer every second */ | 578 | /* Store the write pointer every second */ |
624 | prerecord_buffer[prerecord_index++] = mp3buf_write; | 579 | prerecord_buffer[prerecord_index++] = mp3buf_write; |
625 | 580 | ||
626 | /* Wrap if necessary */ | 581 | /* Wrap if necessary */ |
627 | if(prerecord_index == prerecording_max_seconds) | 582 | if(prerecord_index == prerecording_max_seconds) |
628 | prerecord_index = 0; | 583 | prerecord_index = 0; |
629 | 584 | ||
630 | /* Update the number of seconds recorded */ | 585 | /* Update the number of seconds recorded */ |
631 | if(prerecord_count < prerecording_max_seconds) | 586 | if(prerecord_count < prerecording_max_seconds) |
632 | prerecord_count++; | 587 | prerecord_count++; |
633 | } | ||
634 | } | 588 | } |
635 | else | 589 | } |
590 | else | ||
591 | { | ||
592 | /* Signal to save the data if we are running out of buffer | ||
593 | space */ | ||
594 | num_bytes = mp3buf_write - mp3buf_read; | ||
595 | if(num_bytes < 0) | ||
596 | num_bytes += mp3buflen; | ||
597 | |||
598 | if(mp3buflen - num_bytes < MPEG_RECORDING_LOW_WATER && !saving) | ||
636 | { | 599 | { |
637 | /* Signal to save the data if we are running out of buffer | 600 | saving = true; |
638 | space */ | 601 | queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); |
639 | num_bytes = mp3buf_write - mp3buf_read; | 602 | wake_up_thread(); |
640 | if(num_bytes < 0) | ||
641 | num_bytes += mp3buflen; | ||
642 | |||
643 | if(mp3buflen - num_bytes < MPEG_RECORDING_LOW_WATER && !saving) | ||
644 | { | ||
645 | saving = true; | ||
646 | queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); | ||
647 | wake_up_thread(); | ||
648 | } | ||
649 | } | 603 | } |
650 | } | 604 | } |
651 | } | 605 | } |
652 | #endif /* #ifdef HAVE_MAS3587F */ | 606 | #endif /* #ifdef HAVE_MAS3587F */ |
653 | } | 607 | } |
654 | 608 | ||
609 | void playback_tick(void) | ||
610 | { | ||
611 | id3tags[tag_read_idx]->id3.elapsed += | ||
612 | (current_tick - last_dma_tick) * 1000 / HZ; | ||
613 | last_dma_tick = current_tick; | ||
614 | } | ||
615 | |||
655 | static void reset_mp3_buffer(void) | 616 | static void reset_mp3_buffer(void) |
656 | { | 617 | { |
657 | mp3buf_read = 0; | 618 | mp3buf_read = 0; |
@@ -751,48 +712,6 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
751 | wake_up_thread(); | 712 | wake_up_thread(); |
752 | } | 713 | } |
753 | 714 | ||
754 | #ifdef HAVE_MAS3587F | ||
755 | static void demand_irq_enable(bool on) | ||
756 | { | ||
757 | int oldlevel = set_irq_level(15); | ||
758 | |||
759 | if(on) | ||
760 | { | ||
761 | IPRA = (IPRA & 0xfff0) | 0x000b; | ||
762 | ICR &= ~0x0010; /* IRQ3 level sensitive */ | ||
763 | } | ||
764 | else | ||
765 | IPRA &= 0xfff0; | ||
766 | |||
767 | set_irq_level(oldlevel); | ||
768 | } | ||
769 | #endif /* #ifdef HAVE_MAS3587F */ | ||
770 | |||
771 | #pragma interrupt | ||
772 | void IMIA1(void) /* Timer 1 interrupt */ | ||
773 | { | ||
774 | dma_tick(); | ||
775 | TSR1 &= ~0x01; | ||
776 | #ifdef HAVE_MAS3587F | ||
777 | /* Disable interrupt */ | ||
778 | IPRC &= ~0x000f; | ||
779 | #endif /* #ifdef HAVE_MAS3587F */ | ||
780 | } | ||
781 | |||
782 | #ifdef HAVE_MAS3587F | ||
783 | #pragma interrupt | ||
784 | void IRQ3(void) /* PA15: MAS demand IRQ */ | ||
785 | { | ||
786 | /* Begin with setting the IRQ to edge sensitive */ | ||
787 | ICR |= 0x0010; | ||
788 | |||
789 | if(mpeg_mode == MPEG_ENCODER) | ||
790 | dma_tick(); | ||
791 | else | ||
792 | postpone_dma_tick(); | ||
793 | } | ||
794 | #endif /* #ifdef HAVE_MAS3587F */ | ||
795 | |||
796 | static int add_track_to_tag_list(char *filename) | 715 | static int add_track_to_tag_list(char *filename) |
797 | { | 716 | { |
798 | struct id3tag *t = NULL; | 717 | struct id3tag *t = NULL; |
@@ -892,15 +811,12 @@ static int new_file(int steps) | |||
892 | static void stop_playing(void) | 811 | static void stop_playing(void) |
893 | { | 812 | { |
894 | /* Stop the current stream */ | 813 | /* Stop the current stream */ |
895 | #ifdef HAVE_MAS3587F | 814 | mp3_play_stop(); |
896 | demand_irq_enable(false); | ||
897 | #endif /* #ifdef HAVE_MAS3587F */ | ||
898 | playing = false; | 815 | playing = false; |
899 | filling = false; | 816 | filling = false; |
900 | if(mpeg_file >= 0) | 817 | if(mpeg_file >= 0) |
901 | close(mpeg_file); | 818 | close(mpeg_file); |
902 | mpeg_file = -1; | 819 | mpeg_file = -1; |
903 | mp3_play_pause(false); | ||
904 | remove_all_tags(); | 820 | remove_all_tags(); |
905 | } | 821 | } |
906 | 822 | ||
@@ -967,17 +883,14 @@ static void start_playback_if_ready(void) | |||
967 | play_pending = false; | 883 | play_pending = false; |
968 | playing = true; | 884 | playing = true; |
969 | 885 | ||
970 | last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); | ||
971 | mp3_play_data(mp3buf + mp3buf_read, last_dma_chunk_size, transfer_end); | ||
972 | dma_underrun = false; | ||
973 | |||
974 | if (!paused) | 886 | if (!paused) |
975 | { | 887 | { |
888 | last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); | ||
889 | mp3_play_data(mp3buf + mp3buf_read, last_dma_chunk_size, transfer_end); | ||
890 | dma_underrun = false; | ||
891 | |||
976 | last_dma_tick = current_tick; | 892 | last_dma_tick = current_tick; |
977 | mp3_play_pause(true); | 893 | mp3_play_pause(true); |
978 | #ifdef HAVE_MAS3587F | ||
979 | demand_irq_enable(true); | ||
980 | #endif /* #ifdef HAVE_MAS3587F */ | ||
981 | } | 894 | } |
982 | 895 | ||
983 | /* Tell ourselves that we need more data */ | 896 | /* Tell ourselves that we need more data */ |
@@ -2002,10 +1915,7 @@ static void mpeg_thread(void) | |||
2002 | case MPEG_INIT_PLAYBACK: | 1915 | case MPEG_INIT_PLAYBACK: |
2003 | /* Stop the prerecording */ | 1916 | /* Stop the prerecording */ |
2004 | stop_recording(); | 1917 | stop_recording(); |
2005 | |||
2006 | mp3_play_init(); | 1918 | mp3_play_init(); |
2007 | mpeg_mode = MPEG_DECODER; | ||
2008 | |||
2009 | init_playback_done = true; | 1919 | init_playback_done = true; |
2010 | break; | 1920 | break; |
2011 | 1921 | ||