summaryrefslogtreecommitdiff
path: root/firmware/mpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/mpeg.c')
-rw-r--r--firmware/mpeg.c185
1 files changed, 107 insertions, 78 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index f149814dac..d7e7acbf92 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -37,11 +37,15 @@
37 37
38extern void bitswap(unsigned char *data, int length); 38extern void bitswap(unsigned char *data, int length);
39 39
40#define MPEG_CHUNKSIZE 0x180000 40static int get_unplayed_space(void);
41#define MPEG_SWAP_CHUNKSIZE 0x8000 41static int get_unswapped_space(void);
42#define MPEG_HIGH_WATER 2 42
43#define MPEG_SWAP_CHUNKSIZE 0x2000
44#define MPEG_HIGH_WATER 2 /* We leave 2 bytes empty because otherwise we
45 wouldn't be able to see the difference between
46 an empty buffer and a full one. */
43#define MPEG_LOW_WATER 0x40000 47#define MPEG_LOW_WATER 0x40000
44#define MPEG_LOW_WATER_CHUNKSIZE 0x10000 48#define MPEG_LOW_WATER_CHUNKSIZE 0x40000
45 49
46#define MPEG_PLAY 1 50#define MPEG_PLAY 1
47#define MPEG_STOP 2 51#define MPEG_STOP 2
@@ -52,8 +56,7 @@ extern void bitswap(unsigned char *data, int length);
52#define MPEG_FF_REWIND 7 56#define MPEG_FF_REWIND 7
53#define MPEG_FLUSH_RELOAD 8 57#define MPEG_FLUSH_RELOAD 8
54#define MPEG_NEED_DATA 100 58#define MPEG_NEED_DATA 100
55#define MPEG_SWAP_DATA 101 59#define MPEG_TRACK_CHANGE 101
56#define MPEG_TRACK_CHANGE 102
57 60
58extern char* playlist_peek(int steps); 61extern char* playlist_peek(int steps);
59extern int playlist_next(int steps); 62extern int playlist_next(int steps);
@@ -439,6 +442,26 @@ static bool dma_underrun; /* True when the DMA has stopped because of
439 442
440static int mpeg_file; 443static int mpeg_file;
441 444
445void mpeg_get_debugdata(struct mpeg_debug *dbgdata)
446{
447 dbgdata->mp3buflen = mp3buflen;
448 dbgdata->mp3buf_write = mp3buf_write;
449 dbgdata->mp3buf_swapwrite = mp3buf_swapwrite;
450 dbgdata->mp3buf_read = mp3buf_read;
451
452 dbgdata->last_dma_chunk_size = last_dma_chunk_size;
453
454 dbgdata->dma_on = dma_on;
455 dbgdata->playing = playing;
456 dbgdata->play_pending = play_pending;
457 dbgdata->is_playing = is_playing;
458 dbgdata->filling = filling;
459 dbgdata->dma_underrun = dma_underrun;
460
461 dbgdata->unplayed_space = get_unplayed_space();
462 dbgdata->unswapped_space = get_unswapped_space();
463}
464
442static void mas_poll_start(int interval_in_ms) 465static void mas_poll_start(int interval_in_ms)
443{ 466{
444 unsigned int count; 467 unsigned int count;
@@ -480,8 +503,8 @@ static void dbg_timer_start(void)
480 TSNC &= ~0x04; /* No synchronization */ 503 TSNC &= ~0x04; /* No synchronization */
481 TMDR &= ~0x44; /* Operate normally */ 504 TMDR &= ~0x44; /* Operate normally */
482 505
483 TCNT1 = 0; /* Start counting at 0 */ 506 TCNT2 = 0; /* Start counting at 0 */
484 TCR1 = 0x03; /* Sysclock/8 */ 507 TCR2 = 0x03; /* Sysclock/8 */
485 508
486 TSTR |= 0x04; /* Start timer 2 */ 509 TSTR |= 0x04; /* Start timer 2 */
487} 510}
@@ -492,7 +515,7 @@ static int dbg_cnt2us(unsigned int cnt)
492} 515}
493#endif 516#endif
494 517
495int get_unplayed_space(void) 518static int get_unplayed_space(void)
496{ 519{
497 int space = mp3buf_write - mp3buf_read; 520 int space = mp3buf_write - mp3buf_read;
498 if (space < 0) 521 if (space < 0)
@@ -815,6 +838,65 @@ void hexdump(unsigned char *buf, int len)
815} 838}
816#endif 839#endif
817 840
841static void swap_one_chunk(void)
842{
843 int free_space_left;
844 int amount_to_swap;
845 int t1, t2;
846
847 free_space_left = get_unswapped_space();
848
849 if(free_space_left == 0 && !play_pending)
850 return;
851
852 amount_to_swap = MIN(MPEG_SWAP_CHUNKSIZE, free_space_left);
853 if(mp3buf_write < mp3buf_swapwrite)
854 amount_to_swap = MIN(mp3buflen - mp3buf_swapwrite,
855 amount_to_swap);
856 else
857 amount_to_swap = MIN(mp3buf_write - mp3buf_swapwrite,
858 amount_to_swap);
859
860 DEBUGF("B %x\n", amount_to_swap);
861 t1 = current_tick;
862 bitswap(mp3buf + mp3buf_swapwrite, amount_to_swap);
863 t2 = current_tick;
864 DEBUGF("time: %d\n", t2 - t1);
865
866 mp3buf_swapwrite += amount_to_swap;
867 if(mp3buf_swapwrite >= mp3buflen)
868 {
869 mp3buf_swapwrite = 0;
870 DEBUGF("BW\n");
871 }
872
873 /* And while we're at it, see if we have started
874 playing yet. If not, do it. */
875 if(play_pending || dma_underrun)
876 {
877 /* If the filling has stopped, and we still haven't reached
878 the watermark, the file must be smaller than the
879 watermark. We must still play it. */
880 if(((mp3buf_swapwrite - mp3buf_read) >= MPEG_LOW_WATER) ||
881 !filling)
882 {
883 DEBUGF("P\n");
884 play_pending = false;
885 playing = true;
886
887 init_dma();
888 if (!paused)
889 {
890 last_dma_tick = current_tick;
891 start_dma();
892 }
893
894 /* Tell ourselves that we need more data */
895 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
896 }
897 }
898}
899
818static void mpeg_thread(void) 900static void mpeg_thread(void)
819{ 901{
820 static int pause_tick = 0; 902 static int pause_tick = 0;
@@ -824,7 +906,6 @@ static void mpeg_thread(void)
824 int free_space_left; 906 int free_space_left;
825 int unplayed_space_left; 907 int unplayed_space_left;
826 int amount_to_read; 908 int amount_to_read;
827 int amount_to_swap;
828 int t1, t2; 909 int t1, t2;
829 int start_offset; 910 int start_offset;
830 911
@@ -838,7 +919,18 @@ static void mpeg_thread(void)
838 DEBUGF("S R:%x W:%x SW:%x\n", 919 DEBUGF("S R:%x W:%x SW:%x\n",
839 mp3buf_read, mp3buf_write, mp3buf_swapwrite); 920 mp3buf_read, mp3buf_write, mp3buf_swapwrite);
840 yield(); 921 yield();
841 queue_wait(&mpeg_queue, &ev); 922
923 /* Swap if necessary, and don't block on the queue_wait() */
924 if(get_unswapped_space())
925 {
926 swap_one_chunk();
927 queue_wait_w_tmo(&mpeg_queue, &ev, 0);
928 }
929 else
930 {
931 queue_wait(&mpeg_queue, &ev);
932 }
933
842 switch(ev.id) 934 switch(ev.id)
843 { 935 {
844 case MPEG_PLAY: 936 case MPEG_PLAY:
@@ -1221,64 +1313,6 @@ static void mpeg_thread(void)
1221 break; 1313 break;
1222 } 1314 }
1223 1315
1224 case MPEG_SWAP_DATA:
1225 free_space_left = get_unswapped_space();
1226
1227 if(free_space_left == 0 && !play_pending)
1228 break;
1229
1230 amount_to_swap = MIN(MPEG_SWAP_CHUNKSIZE, free_space_left);
1231 if(mp3buf_write < mp3buf_swapwrite)
1232 amount_to_swap = MIN(mp3buflen - mp3buf_swapwrite,
1233 amount_to_swap);
1234 else
1235 amount_to_swap = MIN(mp3buf_write - mp3buf_swapwrite,
1236 amount_to_swap);
1237
1238 DEBUGF("B %x\n", amount_to_swap);
1239 t1 = current_tick;
1240 bitswap(mp3buf + mp3buf_swapwrite, amount_to_swap);
1241 t2 = current_tick;
1242 DEBUGF("time: %d\n", t2 - t1);
1243
1244 mp3buf_swapwrite += amount_to_swap;
1245 if(mp3buf_swapwrite >= mp3buflen)
1246 {
1247 mp3buf_swapwrite = 0;
1248 DEBUGF("BW\n");
1249 }
1250
1251 /* Tell ourselves that we must swap more data */
1252 queue_post(&mpeg_queue, MPEG_SWAP_DATA, 0);
1253
1254 /* And while we're at it, see if we have started
1255 playing yet. If not, do it. */
1256 if(play_pending || dma_underrun)
1257 {
1258 /* If the filling has stopped, and we still haven't reached
1259 the watermark, the file must be smaller than the
1260 watermark. We must still play it. */
1261 if(((mp3buf_swapwrite - mp3buf_read) >= MPEG_LOW_WATER) ||
1262 !filling)
1263 {
1264 DEBUGF("P\n");
1265 play_pending = false;
1266 playing = true;
1267
1268 init_dma();
1269 if (!paused)
1270 {
1271 last_dma_tick = current_tick;
1272 start_dma();
1273 }
1274
1275 /* Tell ourselves that we need more data */
1276 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1277
1278 }
1279 }
1280 break;
1281
1282 case MPEG_NEED_DATA: 1316 case MPEG_NEED_DATA:
1283 free_space_left = mp3buf_read - mp3buf_write; 1317 free_space_left = mp3buf_read - mp3buf_write;
1284 1318
@@ -1289,7 +1323,7 @@ static void mpeg_thread(void)
1289 unplayed_space_left = mp3buflen - free_space_left; 1323 unplayed_space_left = mp3buflen - free_space_left;
1290 1324
1291 /* Make sure that we don't fill the entire buffer */ 1325 /* Make sure that we don't fill the entire buffer */
1292 free_space_left -= 2; 1326 free_space_left -= MPEG_HIGH_WATER;
1293 1327
1294 /* do we have any more buffer space to fill? */ 1328 /* do we have any more buffer space to fill? */
1295 if(free_space_left <= MPEG_HIGH_WATER) 1329 if(free_space_left <= MPEG_HIGH_WATER)
@@ -1305,15 +1339,12 @@ static void mpeg_thread(void)
1305 amount_to_read = MIN(MPEG_LOW_WATER_CHUNKSIZE, 1339 amount_to_read = MIN(MPEG_LOW_WATER_CHUNKSIZE,
1306 free_space_left); 1340 free_space_left);
1307 else 1341 else
1308 amount_to_read = MIN(MPEG_CHUNKSIZE, free_space_left); 1342 amount_to_read = free_space_left;
1309 1343
1310 /* Don't read more than until the end of the buffer */ 1344 /* Don't read more than until the end of the buffer */
1311 amount_to_read = MIN(mp3buflen - mp3buf_write, amount_to_read); 1345 amount_to_read = MIN(mp3buflen - mp3buf_write, amount_to_read);
1312 1346
1313 /* Read in a few seconds worth of MP3 data. We don't want to 1347 /* Read as much mpeg data as we can fit in the buffer */
1314 read too large chunks because the bitswapping will take
1315 too much time. We must keep the DMA happy and also give
1316 the other threads a chance to run. */
1317 if(mpeg_file >= 0) 1348 if(mpeg_file >= 0)
1318 { 1349 {
1319 DEBUGF("R\n"); 1350 DEBUGF("R\n");
@@ -1325,8 +1356,6 @@ static void mpeg_thread(void)
1325 t2 = current_tick; 1356 t2 = current_tick;
1326 DEBUGF("time: %d\n", t2 - t1); 1357 DEBUGF("time: %d\n", t2 - t1);
1327 DEBUGF("R: %x\n", len); 1358 DEBUGF("R: %x\n", len);
1328 /* Tell ourselves that we need to swap some data */
1329 queue_post(&mpeg_queue, MPEG_SWAP_DATA, 0);
1330 1359
1331 /* Make sure that the write pointer is at a word 1360 /* Make sure that the write pointer is at a word
1332 boundary when we reach the end of the file */ 1361 boundary when we reach the end of the file */