summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/mpeg.c182
1 files changed, 114 insertions, 68 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index ce348f45f3..f0b4eb85c8 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -218,7 +218,7 @@ static int num_tracks_in_memory(void)
218#ifndef SIMULATOR 218#ifndef SIMULATOR
219static void debug_tags(void) 219static void debug_tags(void)
220{ 220{
221#ifdef DEBUG 221#ifdef DEBUG_TAGS
222 int i; 222 int i;
223 223
224 for(i = 0;i < MAX_ID3_TAGS;i++) 224 for(i = 0;i < MAX_ID3_TAGS;i++)
@@ -470,14 +470,19 @@ static bool dma_underrun; /* True when the DMA has stopped because of
470static int lowest_watermark_level; /* Debug value to observe the buffer 470static int lowest_watermark_level; /* Debug value to observe the buffer
471 usage */ 471 usage */
472#ifdef HAVE_MAS3587F 472#ifdef HAVE_MAS3587F
473bool recording; /* We are recording */ 473static bool is_recording; /* We are recording */
474static bool is_recording; /* We are (attempting to) record */
475bool stop_pending; 474bool stop_pending;
476unsigned long record_start_frame; /* Frame number where recording started */ 475unsigned long record_start_frame; /* Frame number where recording started */
477#endif 476#endif
478 477
479static int mpeg_file; 478static int mpeg_file;
480 479
480#ifdef HAVE_MAS3587F
481/* Synchronization variables */
482static bool init_recording_done;
483static bool init_playback_done;
484#endif
485
481void mpeg_get_debugdata(struct mpeg_debug *dbgdata) 486void mpeg_get_debugdata(struct mpeg_debug *dbgdata)
482{ 487{
483 dbgdata->mp3buflen = mp3buflen; 488 dbgdata->mp3buflen = mp3buflen;
@@ -624,6 +629,7 @@ bool inverted_pr;
624unsigned long num_rec_bytes; 629unsigned long num_rec_bytes;
625#endif 630#endif
626 631
632static void dma_tick (void) __attribute__ ((section (".icode")));
627static void dma_tick(void) 633static void dma_tick(void)
628{ 634{
629#ifdef HAVE_MAS3587F 635#ifdef HAVE_MAS3587F
@@ -654,36 +660,56 @@ static void dma_tick(void)
654 timing_info[timing_info_index++] = current_tick; 660 timing_info[timing_info_index++] = current_tick;
655 TCNT2 = 0; 661 TCNT2 = 0;
656#endif 662#endif
663 /* We read as long as EOD is high, but max 30 bytes.
664 This code is optimized, and should probably be
665 written in assembler instead. */
657 if(inverted_pr) 666 if(inverted_pr)
658 { 667 {
659 for(i = 0;PBDR & 0x4000;i++) 668 i = 0;
669 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
670 && i < 30)
660 { 671 {
661 PADR |= 0x800; 672 PADR |= 0x800;
673
674 while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
662 675
663 /* It must take at least 5 cycles before 676 /* It must take at least 5 cycles before
664 the data is read */ 677 the data is read */
678 asm(" nop\n nop\n nop\n");
665 mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000; 679 mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;
666 680
667 PADR &= ~0x800;
668
669 if(mp3buf_write >= mp3buflen) 681 if(mp3buf_write >= mp3buflen)
670 mp3buf_write = 0; 682 mp3buf_write = 0;
683
684 i++;
685
686 PADR &= ~0x800;
687
688 /* No wait for /RTW, cause it's not necessary */
671 } 689 }
672 } 690 }
673 else 691 else
674 { 692 {
675 for(i = 0;PBDR & 0x4000;i++) 693 i = 0;
694 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
695 && i < 30)
676 { 696 {
677 PADR &= ~0x800; 697 PADR &= ~0x800;
678 698
699 while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
700
679 /* It must take at least 5 cycles before 701 /* It must take at least 5 cycles before
680 the data is read */ 702 the data is read */
681 mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000; 703 mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;
682 704
683 PADR |= 0x800;
684
685 if(mp3buf_write >= mp3buflen) 705 if(mp3buf_write >= mp3buflen)
686 mp3buf_write = 0; 706 mp3buf_write = 0;
707
708 i++;
709
710 PADR |= 0x800;
711
712 /* No wait for /RTW, cause it's not necessary */
687 } 713 }
688 } 714 }
689#ifdef DEBUG 715#ifdef DEBUG
@@ -816,7 +842,10 @@ static void demand_irq_enable(bool on)
816 int oldlevel = set_irq_level(15); 842 int oldlevel = set_irq_level(15);
817 843
818 if(on) 844 if(on)
845 {
819 IPRA = (IPRA & 0xfff0) | 0x000b; 846 IPRA = (IPRA & 0xfff0) | 0x000b;
847 ICR &= ~0x0010; /* IRQ3 level sensitive */
848 }
820 else 849 else
821 IPRA &= 0xfff0; 850 IPRA &= 0xfff0;
822 851
@@ -828,21 +857,23 @@ static void demand_irq_enable(bool on)
828void IRQ6(void) 857void IRQ6(void)
829{ 858{
830 stop_dma(); 859 stop_dma();
831
832#ifdef HAVE_MAS3587F
833 /* Enable IRQ to trap the next DEMAND */
834 demand_irq_enable(true);
835#endif
836} 860}
837 861
838#ifdef HAVE_MAS3587F 862#ifdef HAVE_MAS3587F
839#pragma interrupt 863#pragma interrupt
840void IRQ3(void) 864void IRQ3(void)
841{ 865{
866 /* Begin with setting the IRQ to edge sensitive */
867 ICR |= 0x0010;
868
842 dma_tick(); 869 dma_tick();
843 870
844 /* Disable IRQ until DEMAND goes low again */ 871#if 0
845 demand_irq_enable(false); 872 if(mpeg_mode == MPEG_ENCODER)
873 /* Shut off if recording is stopped */
874 if(!is_recording)
875 demand_irq_enable(false);
876#endif
846} 877}
847#endif 878#endif
848 879
@@ -954,8 +985,8 @@ static void update_playlist(void)
954 985
955 if (num_tracks_in_memory() > 0) 986 if (num_tracks_in_memory() > 0)
956 { 987 {
957 index = playlist_next(id3tags[tag_read_idx]->id3.index); 988 index = playlist_next(id3tags[tag_read_idx]->id3.index);
958 id3tags[tag_read_idx]->id3.index = index; 989 id3tags[tag_read_idx]->id3.index = index;
959 } 990 }
960} 991}
961 992
@@ -1154,6 +1185,7 @@ static void mpeg_thread(void)
1154 case MPEG_STOP: 1185 case MPEG_STOP:
1155 DEBUGF("MPEG_STOP\n"); 1186 DEBUGF("MPEG_STOP\n");
1156 is_playing = false; 1187 is_playing = false;
1188 paused = false;
1157 stop_playing(); 1189 stop_playing();
1158 break; 1190 break;
1159 1191
@@ -1242,8 +1274,8 @@ static void mpeg_thread(void)
1242 filling = true; 1274 filling = true;
1243 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 1275 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1244 1276
1245 /* Tell the file loading code that we want to start playing 1277 /* Tell the file loading code that we want
1246 as soon as we have some data */ 1278 to start playing as soon as we have some data */
1247 play_pending = true; 1279 play_pending = true;
1248 1280
1249 current_track_counter++; 1281 current_track_counter++;
@@ -1277,8 +1309,8 @@ static void mpeg_thread(void)
1277 filling = true; 1309 filling = true;
1278 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 1310 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1279 1311
1280 /* Tell the file loading code that we want to start playing 1312 /* Tell the file loading code that we want to
1281 as soon as we have some data */ 1313 start playing as soon as we have some data */
1282 play_pending = true; 1314 play_pending = true;
1283 1315
1284 current_track_counter++; 1316 current_track_counter++;
@@ -1594,6 +1626,7 @@ static void mpeg_thread(void)
1594#ifdef HAVE_MAS3587F 1626#ifdef HAVE_MAS3587F
1595 case MPEG_INIT_RECORDING: 1627 case MPEG_INIT_RECORDING:
1596 init_recording(); 1628 init_recording();
1629 init_recording_done = true;
1597 break; 1630 break;
1598#endif 1631#endif
1599 } 1632 }
@@ -1621,7 +1654,6 @@ static void mpeg_thread(void)
1621 case MPEG_STOP: 1654 case MPEG_STOP:
1622 DEBUGF("MPEG_STOP\n"); 1655 DEBUGF("MPEG_STOP\n");
1623 is_recording = false; 1656 is_recording = false;
1624 recording = false;
1625 1657
1626 /* Save the remaining data in the buffer */ 1658 /* Save the remaining data in the buffer */
1627 stop_pending = true; 1659 stop_pending = true;
@@ -1690,7 +1722,8 @@ static void mpeg_thread(void)
1690 } 1722 }
1691 else 1723 else
1692 { 1724 {
1693 /* We have saved all data, time to stop for real */ 1725 /* We have saved all data,
1726 time to stop for real */
1694 if(stop_pending) 1727 if(stop_pending)
1695 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0); 1728 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
1696 } 1729 }
@@ -1698,6 +1731,7 @@ static void mpeg_thread(void)
1698 1731
1699 case MPEG_INIT_PLAYBACK: 1732 case MPEG_INIT_PLAYBACK:
1700 init_playback(); 1733 init_playback();
1734 init_playback_done = true;
1701 break; 1735 break;
1702 } 1736 }
1703 } 1737 }
@@ -1732,16 +1766,10 @@ static void setup_sci0(void)
1732 /* Set interrupt ITU2 and SCI0 priority to 0 */ 1766 /* Set interrupt ITU2 and SCI0 priority to 0 */
1733 IPRD &= 0x0ff0; 1767 IPRD &= 0x0ff0;
1734 1768
1735 /* set IRQ6 and IRQ7 to edge detect */
1736 ICR |= 0x03;
1737
1738 /* set PB15 and PB14 to inputs */ 1769 /* set PB15 and PB14 to inputs */
1739 PBIOR &= 0x7fff; 1770 PBIOR &= 0x7fff;
1740 PBIOR &= 0xbfff; 1771 PBIOR &= 0xbfff;
1741 1772
1742 /* set IRQ6 prio 8 and IRQ7 prio 0 */
1743 IPRB = ( IPRB & 0xff00 ) | 0x0080;
1744
1745 /* Enable End of DMA interrupt at prio 8 */ 1773 /* Enable End of DMA interrupt at prio 8 */
1746 IPRC = (IPRC & 0xf0ff) | 0x0800; 1774 IPRC = (IPRC & 0xf0ff) | 0x0800;
1747 1775
@@ -1779,26 +1807,30 @@ bool mpeg_has_changed_track(void)
1779#ifdef HAVE_MAS3587F 1807#ifdef HAVE_MAS3587F
1780void mpeg_init_recording(void) 1808void mpeg_init_recording(void)
1781{ 1809{
1810 init_recording_done = false;
1782 queue_post(&mpeg_queue, MPEG_INIT_RECORDING, NULL); 1811 queue_post(&mpeg_queue, MPEG_INIT_RECORDING, NULL);
1783 yield(); 1812
1813 while(!init_recording_done)
1814 yield();
1784} 1815}
1785 1816
1786void mpeg_init_playback(void) 1817void mpeg_init_playback(void)
1787{ 1818{
1819 init_playback_done = false;
1788 queue_post(&mpeg_queue, MPEG_INIT_PLAYBACK, NULL); 1820 queue_post(&mpeg_queue, MPEG_INIT_PLAYBACK, NULL);
1789 yield(); 1821
1822 while(!init_playback_done)
1823 yield();
1790} 1824}
1791 1825
1792static void init_recording(void) 1826static void init_recording(void)
1793{ 1827{
1794 unsigned long val; 1828 unsigned long val;
1829 int rc;
1830
1831 stop_playing();
1832 paused = false;
1795 1833
1796 /* Stop the current stream */
1797 play_pending = false;
1798 playing = false;
1799 is_playing = false;
1800 stop_dma();
1801
1802 reset_mp3_buffer(); 1834 reset_mp3_buffer();
1803 remove_all_tags(); 1835 remove_all_tags();
1804 1836
@@ -1807,9 +1839,15 @@ static void init_recording(void)
1807 mpeg_file = -1; 1839 mpeg_file = -1;
1808 1840
1809 /* Init the recording variables */ 1841 /* Init the recording variables */
1810 recording = false;
1811 is_recording = false; 1842 is_recording = false;
1812 1843
1844 mas_reset();
1845
1846 /* Enable the audio CODEC and the DSP core, max analog voltage range */
1847 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
1848 if(rc < 0)
1849 panicf("mas_ctrl_w: %d", rc);
1850
1813 /* Stop the current application */ 1851 /* Stop the current application */
1814 val = 0; 1852 val = 0;
1815 mas_writemem(MAS_BANK_D0,0x7f6,&val,1); 1853 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
@@ -1828,7 +1866,7 @@ static void init_recording(void)
1828 mas_writemem(MAS_BANK_D1, 0, &val, 1); 1866 mas_writemem(MAS_BANK_D1, 0, &val, 1);
1829 mas_writereg(0xa3, 0x90); 1867 mas_writereg(0xa3, 0x90);
1830 } 1868 }
1831 1869
1832 /* Enable the Left A/D Converter */ 1870 /* Enable the Left A/D Converter */
1833 mas_codec_writereg(0x0, 0xcccd); 1871 mas_codec_writereg(0x0, 0xcccd);
1834 1872
@@ -1855,6 +1893,9 @@ static void init_recording(void)
1855 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1); 1893 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
1856 } while(!(val & 0x40)); 1894 } while(!(val & 0x40));
1857 1895
1896 /* Disable IRQ6 */
1897 IPRB &= 0xff0f;
1898
1858 mpeg_mode = MPEG_ENCODER; 1899 mpeg_mode = MPEG_ENCODER;
1859 1900
1860 DEBUGF("MAS Recording application started\n"); 1901 DEBUGF("MAS Recording application started\n");
@@ -1863,7 +1904,17 @@ static void init_recording(void)
1863static void init_playback(void) 1904static void init_playback(void)
1864{ 1905{
1865 unsigned long val; 1906 unsigned long val;
1907 int rc;
1908
1909 stop_dma();
1910
1911 mas_reset();
1866 1912
1913 /* Enable the audio CODEC and the DSP core, max analog voltage range */
1914 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
1915 if(rc < 0)
1916 panicf("mas_ctrl_w: %d", rc);
1917
1867 /* Stop the current application */ 1918 /* Stop the current application */
1868 val = 0; 1919 val = 0;
1869 mas_writemem(MAS_BANK_D0,0x7f6,&val,1); 1920 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
@@ -1895,8 +1946,16 @@ static void init_playback(void)
1895 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1); 1946 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
1896 } while((val & 0x0c) != 0x0c); 1947 } while((val & 0x0c) != 0x0c);
1897 1948
1949 mpeg_sound_channel_config(MPEG_SOUND_STEREO);
1950
1898 mpeg_mode = MPEG_DECODER; 1951 mpeg_mode = MPEG_DECODER;
1899 1952
1953 /* set IRQ6 to edge detect */
1954 ICR |= 0x02;
1955
1956 /* set IRQ6 prio 8 */
1957 IPRB = ( IPRB & 0xff0f ) | 0x0080;
1958
1900 DEBUGF("MAS Decoding application started\n"); 1959 DEBUGF("MAS Decoding application started\n");
1901} 1960}
1902 1961
@@ -1912,7 +1971,6 @@ void mpeg_record(char *filename)
1912 1971
1913static void start_recording(void) 1972static void start_recording(void)
1914{ 1973{
1915 recording = true;
1916 stop_pending = false; 1974 stop_pending = false;
1917} 1975}
1918 1976
@@ -2478,7 +2536,8 @@ void mpeg_set_recording_options(int frequency, int quality,
2478 val = (quality << 17) | 2536 val = (quality << 17) |
2479 ((frequency % 3) << 10) | 2537 ((frequency % 3) << 10) |
2480 ((is_mpeg1?1:0) << 9) | 2538 ((is_mpeg1?1:0) << 9) |
2481 ((channel_mode * 2 + 1) << 6) | 2539 (1 << 8) | /* CRC on */
2540 (((channel_mode * 2 + 1) & 3) << 6) |
2482 (1 << 5) /* MS-stereo */ | 2541 (1 << 5) /* MS-stereo */ |
2483 (1 << 2) /* Is an original */; 2542 (1 << 2) /* Is an original */;
2484 mas_writemem(MAS_BANK_D0, 0x7f0, &val,1); 2543 mas_writemem(MAS_BANK_D0, 0x7f0, &val,1);
@@ -2523,9 +2582,7 @@ void mpeg_init(int volume, int bass, int treble, int balance, int loudness, int
2523#ifdef SIMULATOR 2582#ifdef SIMULATOR
2524 volume = bass = treble = balance = loudness = bass_boost = avc; 2583 volume = bass = treble = balance = loudness = bass_boost = avc;
2525#else 2584#else
2526#ifdef HAVE_MAS3587F 2585#ifdef HAVE_MAS3507D
2527 int rc;
2528#else
2529 unsigned long val; 2586 unsigned long val;
2530 loudness = bass_boost = avc; 2587 loudness = bass_boost = avc;
2531#endif 2588#endif
@@ -2533,25 +2590,11 @@ void mpeg_init(int volume, int bass, int treble, int balance, int loudness, int
2533 setup_sci0(); 2590 setup_sci0();
2534 2591
2535#ifdef HAVE_MAS3587F 2592#ifdef HAVE_MAS3587F
2536 mas_reset(); 2593 init_playback();
2537 2594
2538 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2539 rc = mas_direct_config_write(MAS_CONTROL, 0x4c00);
2540 if(rc < 0)
2541 panicf("mas_ctrl_w: %d", rc);
2542
2543 rc = mas_direct_config_read(MAS_CONTROL);
2544 if(rc < 0)
2545 panicf("mas_ctrl_r: %d", rc);
2546
2547 mas_version_code = mas_readver(); 2595 mas_version_code = mas_readver();
2548 DEBUGF("MAS3587 derivate %d, version B%d\n", 2596 DEBUGF("MAS3587 derivate %d, version B%d\n",
2549 (mas_version_code & 0xff00) >> 8, mas_version_code & 0xff); 2597 (mas_version_code & 0xff00) >> 8, mas_version_code & 0xff);
2550
2551 init_playback();
2552
2553 mpeg_sound_channel_config(MPEG_SOUND_STEREO);
2554
2555#endif 2598#endif
2556 2599
2557#ifdef HAVE_DAC3550A 2600#ifdef HAVE_DAC3550A
@@ -2564,6 +2607,12 @@ void mpeg_init(int volume, int bass, int treble, int balance, int loudness, int
2564 PBDR |= 0x20; 2607 PBDR |= 0x20;
2565 sleep(HZ/5); 2608 sleep(HZ/5);
2566 2609
2610 /* set IRQ6 to edge detect */
2611 ICR |= 0x02;
2612
2613 /* set IRQ6 prio 8 */
2614 IPRB = ( IPRB & 0xff0f ) | 0x0080;
2615
2567 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1); 2616 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
2568 2617
2569 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */ 2618 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
@@ -2597,7 +2646,7 @@ void mpeg_init(int volume, int bass, int treble, int balance, int loudness, int
2597 } 2646 }
2598 2647
2599#endif 2648#endif
2600 2649
2601 mp3buflen = mp3end - mp3buf; 2650 mp3buflen = mp3end - mp3buf;
2602 2651
2603 queue_init(&mpeg_queue); 2652 queue_init(&mpeg_queue);
@@ -2606,19 +2655,16 @@ void mpeg_init(int volume, int bass, int treble, int balance, int loudness, int
2606 2655
2607#ifdef HAVE_MAS3507D 2656#ifdef HAVE_MAS3507D
2608 mas_poll_start(1); 2657 mas_poll_start(1);
2609#endif
2610
2611#ifdef HAVE_MAS3587F
2612 ICR &= ~0x0010; /* IRQ3 level sensitive */
2613 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
2614#endif
2615 2658
2616#ifdef HAVE_MAS3507D
2617 mas_writereg(MAS_REG_KPRESCALE, 0xe9400); 2659 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
2618 dac_config(0x04); /* DAC on, all else off */ 2660 dac_config(0x04); /* DAC on, all else off */
2619 2661
2620 mpeg_sound_channel_config(MPEG_SOUND_STEREO); 2662 mpeg_sound_channel_config(MPEG_SOUND_STEREO);
2663#endif
2621 2664
2665#ifdef HAVE_MAS3587F
2666 ICR &= ~0x0010; /* IRQ3 level sensitive */
2667 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
2622#endif 2668#endif
2623 2669
2624 /* Must be done before calling mpeg_sound_set() */ 2670 /* Must be done before calling mpeg_sound_set() */