diff options
Diffstat (limited to 'firmware/mp3_playback.c')
-rw-r--r-- | firmware/mp3_playback.c | 156 |
1 files changed, 151 insertions, 5 deletions
diff --git a/firmware/mp3_playback.c b/firmware/mp3_playback.c index 9930f10824..fe16676624 100644 --- a/firmware/mp3_playback.c +++ b/firmware/mp3_playback.c | |||
@@ -34,6 +34,30 @@ | |||
34 | #include "hwcompat.h" | 34 | #include "hwcompat.h" |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | /* hacking into mpeg.c, recording is still there */ | ||
38 | #ifdef HAVE_MAS3587F | ||
39 | enum | ||
40 | { | ||
41 | MPEG_DECODER, | ||
42 | MPEG_ENCODER | ||
43 | } mpeg_mode; | ||
44 | #endif /* #ifdef HAVE_MAS3587F */ | ||
45 | |||
46 | /**** globals ****/ | ||
47 | |||
48 | /* own version, independent of mpeg.c */ | ||
49 | static bool paused; /* playback is paused */ | ||
50 | static bool playing; /* We are playing an MP3 stream */ | ||
51 | |||
52 | #ifndef SIMULATOR | ||
53 | /* for measuring the play time */ | ||
54 | static long playstart_tick; | ||
55 | static long cumulative_ticks; | ||
56 | |||
57 | /* the registered callback function to ask for more mp3 data */ | ||
58 | static void (*callback_for_more)(unsigned char**, int*); | ||
59 | #endif /* #ifndef SIMULATOR */ | ||
60 | |||
37 | static char *units[] = | 61 | static char *units[] = |
38 | { | 62 | { |
39 | "%", /* Volume */ | 63 | "%", /* Volume */ |
@@ -283,10 +307,65 @@ static void mas_poll_start(int interval_in_ms) | |||
283 | 307 | ||
284 | TSTR |= 0x02; /* Start timer 1 */ | 308 | TSTR |= 0x02; /* Start timer 1 */ |
285 | } | 309 | } |
310 | #else | ||
311 | static void postpone_dma_tick(void) | ||
312 | { | ||
313 | unsigned int count; | ||
314 | |||
315 | count = FREQ / 1000 / 8; | ||
316 | |||
317 | /* We are using timer 1 */ | ||
318 | |||
319 | TSTR &= ~0x02; /* Stop the timer */ | ||
320 | TSNC &= ~0x02; /* No synchronization */ | ||
321 | TMDR &= ~0x02; /* Operate normally */ | ||
322 | |||
323 | TCNT1 = 0; /* Start counting at 0 */ | ||
324 | GRA1 = count; | ||
325 | TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */ | ||
326 | |||
327 | /* Enable interrupt on level 5 */ | ||
328 | IPRC = (IPRC & ~0x000f) | 0x0005; | ||
329 | |||
330 | TSR1 &= ~0x02; | ||
331 | TIER1 = 0xf9; /* Enable GRA match interrupt */ | ||
332 | |||
333 | TSTR |= 0x02; /* Start timer 1 */ | ||
334 | } | ||
286 | #endif | 335 | #endif |
287 | 336 | ||
288 | /* the registered callback function ta ask for more mp3 data */ | 337 | |
289 | static void (*callback_for_more)(unsigned char**, int*); | 338 | #ifdef HAVE_MAS3587F |
339 | void demand_irq_enable(bool on) | ||
340 | { | ||
341 | int oldlevel = set_irq_level(15); | ||
342 | |||
343 | if(on) | ||
344 | { | ||
345 | IPRA = (IPRA & 0xfff0) | 0x000b; | ||
346 | ICR &= ~0x0010; /* IRQ3 level sensitive */ | ||
347 | } | ||
348 | else | ||
349 | IPRA &= 0xfff0; | ||
350 | |||
351 | set_irq_level(oldlevel); | ||
352 | } | ||
353 | #endif /* #ifdef HAVE_MAS3587F */ | ||
354 | |||
355 | |||
356 | void play_tick(void) | ||
357 | { | ||
358 | if(playing && !paused) | ||
359 | { | ||
360 | /* Start DMA if it is disabled and the DEMAND pin is high */ | ||
361 | if(!(SCR0 & 0x80) && (PBDR & 0x4000)) | ||
362 | { | ||
363 | SCR0 |= 0x80; | ||
364 | } | ||
365 | |||
366 | playback_tick(); /* dirty call to mpeg.c */ | ||
367 | } | ||
368 | } | ||
290 | 369 | ||
291 | #pragma interrupt | 370 | #pragma interrupt |
292 | void DEI3(void) | 371 | void DEI3(void) |
@@ -313,10 +392,36 @@ void DEI3(void) | |||
313 | } | 392 | } |
314 | 393 | ||
315 | #pragma interrupt | 394 | #pragma interrupt |
395 | void IMIA1(void) /* Timer 1 interrupt */ | ||
396 | { | ||
397 | if(playing) | ||
398 | play_tick(); | ||
399 | TSR1 &= ~0x01; | ||
400 | #ifdef HAVE_MAS3587F | ||
401 | /* Disable interrupt */ | ||
402 | IPRC &= ~0x000f; | ||
403 | #endif /* #ifdef HAVE_MAS3587F */ | ||
404 | } | ||
405 | |||
406 | #pragma interrupt | ||
316 | void IRQ6(void) /* PB14: MAS stop demand IRQ */ | 407 | void IRQ6(void) /* PB14: MAS stop demand IRQ */ |
317 | { | 408 | { |
318 | mp3_play_pause(false); | 409 | SCR0 &= ~0x80; |
410 | } | ||
411 | |||
412 | #ifdef HAVE_MAS3587F | ||
413 | #pragma interrupt | ||
414 | void IRQ3(void) /* PA15: MAS demand IRQ */ | ||
415 | { | ||
416 | /* Begin with setting the IRQ to edge sensitive */ | ||
417 | ICR |= 0x0010; | ||
418 | |||
419 | if(mpeg_mode == MPEG_ENCODER) | ||
420 | rec_tick(); | ||
421 | else | ||
422 | postpone_dma_tick(); | ||
319 | } | 423 | } |
424 | #endif /* #ifdef HAVE_MAS3587F */ | ||
320 | 425 | ||
321 | static void setup_sci0(void) | 426 | static void setup_sci0(void) |
322 | { | 427 | { |
@@ -404,6 +509,8 @@ static void init_playback(void) | |||
404 | 509 | ||
405 | mpeg_sound_channel_config(MPEG_SOUND_STEREO); | 510 | mpeg_sound_channel_config(MPEG_SOUND_STEREO); |
406 | 511 | ||
512 | mpeg_mode = MPEG_DECODER; | ||
513 | |||
407 | /* set IRQ6 to edge detect */ | 514 | /* set IRQ6 to edge detect */ |
408 | ICR |= 0x02; | 515 | ICR |= 0x02; |
409 | 516 | ||
@@ -893,6 +1000,9 @@ void mp3_init(int volume, int bass, int treble, int balance, int loudness, | |||
893 | mpeg_sound_set(SOUND_AVC, avc); | 1000 | mpeg_sound_set(SOUND_AVC, avc); |
894 | #endif | 1001 | #endif |
895 | #endif /* !SIMULATOR */ | 1002 | #endif /* !SIMULATOR */ |
1003 | |||
1004 | playing = false; | ||
1005 | paused = true; | ||
896 | } | 1006 | } |
897 | 1007 | ||
898 | 1008 | ||
@@ -905,7 +1015,10 @@ void mp3_play_init(void) | |||
905 | #ifdef HAVE_MAS3587F | 1015 | #ifdef HAVE_MAS3587F |
906 | init_playback(); | 1016 | init_playback(); |
907 | #endif | 1017 | #endif |
1018 | playing = false; | ||
1019 | paused = true; | ||
908 | callback_for_more = NULL; | 1020 | callback_for_more = NULL; |
1021 | mp3_reset_playtime(); | ||
909 | } | 1022 | } |
910 | 1023 | ||
911 | void mp3_play_data(unsigned char* start, int size, | 1024 | void mp3_play_data(unsigned char* start, int size, |
@@ -923,21 +1036,54 @@ void mp3_play_data(unsigned char* start, int size, | |||
923 | SAR3 = (unsigned int)start; | 1036 | SAR3 = (unsigned int)start; |
924 | DTCR3 = size & 0xffff; | 1037 | DTCR3 = size & 0xffff; |
925 | 1038 | ||
1039 | playing = true; | ||
1040 | paused = true; | ||
1041 | |||
926 | CHCR3 |= 0x0001; /* Enable DMA IRQ */ | 1042 | CHCR3 |= 0x0001; /* Enable DMA IRQ */ |
1043 | |||
1044 | #ifdef HAVE_MAS3587F | ||
1045 | demand_irq_enable(true); | ||
1046 | #endif | ||
927 | } | 1047 | } |
928 | 1048 | ||
929 | void mp3_play_pause(bool play) | 1049 | void mp3_play_pause(bool play) |
930 | { | 1050 | { |
931 | if (play) | 1051 | if (paused && play) |
1052 | { /* resume playback */ | ||
932 | SCR0 |= 0x80; | 1053 | SCR0 |= 0x80; |
933 | else | 1054 | paused = false; |
1055 | playstart_tick = current_tick; | ||
1056 | } | ||
1057 | else if (!paused && !play) | ||
1058 | { /* stop playback */ | ||
934 | SCR0 &= 0x7f; | 1059 | SCR0 &= 0x7f; |
1060 | paused = true; | ||
1061 | cumulative_ticks += current_tick - playstart_tick; | ||
1062 | } | ||
935 | } | 1063 | } |
936 | 1064 | ||
937 | void mp3_play_stop(void) | 1065 | void mp3_play_stop(void) |
938 | { | 1066 | { |
1067 | playing = false; | ||
939 | mp3_play_pause(false); | 1068 | mp3_play_pause(false); |
940 | CHCR3 &= ~0x0001; /* Disable the DMA interrupt */ | 1069 | CHCR3 &= ~0x0001; /* Disable the DMA interrupt */ |
1070 | #ifdef HAVE_MAS3587F | ||
1071 | demand_irq_enable(false); | ||
1072 | #endif | ||
1073 | } | ||
1074 | |||
1075 | long mp3_get_playtime(void) | ||
1076 | { | ||
1077 | if (paused) | ||
1078 | return cumulative_ticks; | ||
1079 | else | ||
1080 | return cumulative_ticks + current_tick - playstart_tick; | ||
1081 | } | ||
1082 | |||
1083 | void mp3_reset_playtime(void) | ||
1084 | { | ||
1085 | cumulative_ticks = 0; | ||
1086 | playstart_tick = current_tick; | ||
941 | } | 1087 | } |
942 | 1088 | ||
943 | #endif /* #ifndef SIMULATOR */ | 1089 | #endif /* #ifndef SIMULATOR */ |