1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
33 #include "mp3_playback.h"
44 #endif /* #ifndef SIMULATOR */
48 #if CONFIG_HWCODEC == MAS3587F
49 static void init_recording(void);
50 static void start_prerecording(void);
51 static void start_recording(void);
52 static void stop_recording(void);
53 static int get_unsaved_space(void);
54 static void pause_recording(void);
55 static void resume_recording(void);
56 #endif /* #if CONFIG_HWCODEC == MAS3587F */
59 static int get_unplayed_space(void);
60 static int get_playable_space(void);
61 static int get_unswapped_space(void);
62 #endif /* #ifndef SIMULATOR */
70 #define MPEG_FF_REWIND 7
71 #define MPEG_FLUSH_RELOAD 8
73 #define MPEG_INIT_RECORDING 10
74 #define MPEG_INIT_PLAYBACK 11
75 #define MPEG_NEW_FILE 12
76 #define MPEG_PAUSE_RECORDING 13
77 #define MPEG_RESUME_RECORDING 14
78 #define MPEG_NEED_DATA 100
79 #define MPEG_TRACK_CHANGE 101
80 #define MPEG_SAVE_DATA 102
81 #define MPEG_STOP_DONE 103
83 #if CONFIG_HWCODEC == MAS3587F
84 extern enum /* from mp3_playback.c */
89 #endif /* #if CONFIG_HWCODEC == MAS3587F */
91 extern char* playlist_peek(int steps
);
92 extern bool playlist_check(int steps
);
93 extern int playlist_next(int steps
);
94 extern int playlist_amount(void);
95 extern void update_file_pos( int id
, int pos
);
97 /* list of tracks in memory */
98 #define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
99 #define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
105 int load_ahead_index
;
108 static struct id3tag id3tags
[MAX_ID3_TAGS
];
110 static bool v1first
= false;
112 static unsigned int current_track_counter
= 0;
113 static unsigned int last_track_counter
= 0;
117 static int tag_read_idx
= 0;
118 static int tag_write_idx
= 0;
120 static int num_tracks_in_memory(void)
122 return (tag_write_idx
- tag_read_idx
) & MAX_ID3_TAGS_MASK
;
124 #endif /* #ifndef SIMULATOR */
127 static void debug_tags(void)
132 for(i
= 0;i
< MAX_ID3_TAGS
;i
++)
134 DEBUGF("%d - %s\n", i
, id3tags
[i
].id3
.path
);
136 DEBUGF("read: %d, write :%d\n", tag_read_idx
, tag_write_idx
);
137 DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory());
138 #endif /* #ifdef DEBUG_TAGS */
141 static void remove_current_tag(void)
143 if(num_tracks_in_memory() > 0)
145 /* First move the index, so nobody tries to access the tag */
146 tag_read_idx
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
151 DEBUGF("remove_current_tag: no tracks to remove\n");
155 static void remove_all_non_current_tags(void)
157 tag_write_idx
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
161 static void remove_all_tags(void)
163 tag_write_idx
= tag_read_idx
;
167 #endif /* #ifndef SIMULATOR */
169 static void set_elapsed(struct mp3entry
* id3
)
172 if ( id3
->has_toc
) {
173 /* calculate elapsed time using TOC */
175 unsigned int remainder
, plen
, relpos
, nextpos
;
177 /* find wich percent we're at */
178 for (i
=0; i
<100; i
++ )
180 if ( id3
->offset
< (int)(id3
->toc
[i
] * (id3
->filesize
/ 256)) )
190 relpos
= id3
->toc
[i
];
194 nextpos
= id3
->toc
[i
+1];
201 remainder
= id3
->offset
- (relpos
* (id3
->filesize
/ 256));
203 /* set time for this percent (divide before multiply to prevent
204 overflow on long files. loss of precision is negligible on
206 id3
->elapsed
= i
* (id3
->length
/ 100);
208 /* calculate remainder time */
209 plen
= (nextpos
- relpos
) * (id3
->filesize
/ 256);
210 id3
->elapsed
+= (((remainder
* 100) / plen
) *
211 (id3
->length
/ 10000));
214 /* no TOC exists. set a rough estimate using average bitrate */
215 int tpk
= id3
->length
/ (id3
->filesize
/ 1024);
216 id3
->elapsed
= id3
->offset
/ 1024 * tpk
;
220 /* constant bitrate == simple frame calculation */
221 id3
->elapsed
= id3
->offset
/ id3
->bpf
* id3
->tpf
;
224 int mpeg_get_file_pos(void)
227 struct mp3entry
*id3
= mpeg_current_track();
233 /* Use the TOC to find the new position */
234 unsigned int percent
, remainder
;
235 int curtoc
, nexttoc
, plen
;
237 percent
= (id3
->elapsed
*100)/id3
->length
;
241 curtoc
= id3
->toc
[percent
];
244 nexttoc
= id3
->toc
[percent
+1];
248 pos
= (id3
->filesize
/256)*curtoc
;
250 /* Use the remainder to get a more accurate position */
251 remainder
= (id3
->elapsed
*100)%id3
->length
;
252 remainder
= (remainder
*100)/id3
->length
;
253 plen
= (nexttoc
- curtoc
)*(id3
->filesize
/256);
254 pos
+= (plen
/100)*remainder
;
258 /* No TOC exists, estimate the new position */
259 pos
= (id3
->filesize
/ (id3
->length
/ 1000)) *
260 (id3
->elapsed
/ 1000);
263 else if (id3
->bpf
&& id3
->tpf
)
264 pos
= (id3
->elapsed
/id3
->tpf
)*id3
->bpf
;
270 if (pos
>= (int)(id3
->filesize
- id3
->id3v1len
))
272 /* Don't seek right to the end of the file so that we can
273 transition properly to the next song */
274 pos
= id3
->filesize
- id3
->id3v1len
- 1;
276 else if (pos
< (int)id3
->first_frame_offset
)
278 /* skip past id3v2 tag and other leading garbage */
279 pos
= id3
->first_frame_offset
;
284 unsigned long mpeg_get_last_header(void)
289 unsigned long tmp
[2];
291 /* Read the frame data from the MAS and reconstruct it with the
292 frame sync and all */
293 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_STATUS_1
, tmp
, 2);
294 return 0xffe00000 | ((tmp
[0] & 0x7c00) << 6) | (tmp
[1] & 0xffff);
298 static bool paused
; /* playback is paused */
300 static unsigned int mpeg_errno
;
303 static bool is_playing
= false;
304 static bool playing
= false;
306 static int last_dma_tick
= 0;
308 extern unsigned long mas_version_code
;
310 static struct event_queue mpeg_queue
;
311 static char mpeg_stack
[DEFAULT_STACK_SIZE
+ 0x1000];
312 static const char mpeg_thread_name
[] = "mpeg";
314 static int mp3buflen
;
315 static int mp3buf_write
;
316 static int mp3buf_swapwrite
;
317 static int mp3buf_read
;
319 static int last_dma_chunk_size
;
321 static bool playing
; /* We are playing an MP3 stream */
322 static bool play_pending
; /* We are about to start playing */
323 static bool is_playing
; /* We are (attempting to) playing MP3 files */
324 static bool filling
; /* We are filling the buffer with data from disk */
325 static bool dma_underrun
; /* True when the DMA has stopped because of
326 slow disk reading (read error, shaking) */
327 static int low_watermark
; /* Dynamic low watermark level */
328 static int low_watermark_margin
; /* Extra time in seconds for watermark */
329 static int lowest_watermark_level
; /* Debug value to observe the buffer
331 #if CONFIG_HWCODEC == MAS3587F
332 static bool is_recording
; /* We are recording */
333 static bool stop_pending
;
334 unsigned long record_start_time
; /* Value of current_tick when recording
336 unsigned long pause_start_time
; /* Value of current_tick when pause was
338 static bool saving
; /* We are saving the buffer to disk */
339 static char recording_filename
[MAX_PATH
]; /* argument to thread */
340 static char delayed_filename
[MAX_PATH
]; /* internal copy of above */
341 static int rec_frequency_index
; /* For create_xing_header() calls */
342 static int rec_version_index
; /* For create_xing_header() calls */
343 static bool disable_xing_header
; /* When splitting files */
345 static bool prerecording
; /* True if prerecording is enabled */
346 static bool is_prerecording
; /* True if we are prerecording */
347 static int prerecord_buffer
[MPEG_MAX_PRERECORD_SECONDS
]; /* Array of buffer
351 static int prerecord_index
; /* Current index in the prerecord buffer */
352 static int prerecording_max_seconds
; /* Max number of seconds to store */
353 static int prerecord_count
; /* Number of seconds in the prerecord buffer */
354 static int prerecord_timeout
; /* The tick count of the next prerecord data store */
356 /* Shadow MAS registers */
357 unsigned long shadow_encoder_control
= 0;
358 #endif /* #if CONFIG_HWCODEC == MAS3587F */
360 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
361 unsigned long shadow_io_control_main
= 0;
362 unsigned long shadow_app_select
= 0;
363 unsigned long shadow_soft_mute
= 0;
364 unsigned shadow_codec_reg0
;
367 static int mpeg_file
;
369 /* Synchronization variables */
370 #if CONFIG_HWCODEC == MAS3587F
371 static bool init_recording_done
;
372 static bool init_playback_done
;
373 #endif /* #if CONFIG_HWCODEC == MAS3587F */
374 static bool mpeg_stop_done
;
376 static void recalculate_watermark(int bitrate
)
379 int time
= ata_spinup_time
;
381 /* A bitrate of 0 probably means empty VBR header. We play safe
382 and set a high threshold */
386 bytes_per_sec
= bitrate
* 1000 / 8;
390 /* No drive spins up faster than 3.5s */
395 low_watermark
= ((low_watermark_margin
* HZ
+ time
) *
400 low_watermark
= MPEG_LOW_WATER
;
404 void mpeg_set_buffer_margin(int seconds
)
406 low_watermark_margin
= seconds
;
409 void mpeg_get_debugdata(struct mpeg_debug
*dbgdata
)
411 dbgdata
->mp3buflen
= mp3buflen
;
412 dbgdata
->mp3buf_write
= mp3buf_write
;
413 dbgdata
->mp3buf_swapwrite
= mp3buf_swapwrite
;
414 dbgdata
->mp3buf_read
= mp3buf_read
;
416 dbgdata
->last_dma_chunk_size
= last_dma_chunk_size
;
418 dbgdata
->dma_on
= (SCR0
& 0x80) != 0;
419 dbgdata
->playing
= playing
;
420 dbgdata
->play_pending
= play_pending
;
421 dbgdata
->is_playing
= is_playing
;
422 dbgdata
->filling
= filling
;
423 dbgdata
->dma_underrun
= dma_underrun
;
425 dbgdata
->unplayed_space
= get_unplayed_space();
426 dbgdata
->playable_space
= get_playable_space();
427 dbgdata
->unswapped_space
= get_unswapped_space();
429 dbgdata
->low_watermark_level
= low_watermark
;
430 dbgdata
->lowest_watermark_level
= lowest_watermark_level
;
434 static void dbg_timer_start(void)
436 /* We are using timer 2 */
438 TSTR
&= ~0x04; /* Stop the timer */
439 TSNC
&= ~0x04; /* No synchronization */
440 TMDR
&= ~0x44; /* Operate normally */
442 TCNT2
= 0; /* Start counting at 0 */
443 TCR2
= 0x03; /* Sysclock/8 */
445 TSTR
|= 0x04; /* Start timer 2 */
448 static int dbg_cnt2us(unsigned int cnt
)
450 return (cnt
* 10000) / (FREQ
/800);
452 #endif /* #ifdef DEBUG */
454 static int get_unplayed_space(void)
456 int space
= mp3buf_write
- mp3buf_read
;
462 static int get_playable_space(void)
464 int space
= mp3buf_swapwrite
- mp3buf_read
;
470 static int get_unplayed_space_current_song(void)
474 if (num_tracks_in_memory() > 1)
476 int track_offset
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
478 space
= id3tags
[track_offset
].mempos
- mp3buf_read
;
482 space
= mp3buf_write
- mp3buf_read
;
491 static int get_unswapped_space(void)
493 int space
= mp3buf_write
- mp3buf_swapwrite
;
499 #if CONFIG_HWCODEC == MAS3587F
500 static int get_unsaved_space(void)
502 int space
= mp3buf_write
- mp3buf_read
;
507 #endif /* #if CONFIG_HWCODEC == MAS3587F */
509 #if CONFIG_HWCODEC == MAS3587F
511 static long timing_info_index
= 0;
512 static long timing_info
[1024];
513 #endif /* #ifdef DEBUG */
514 static unsigned long num_rec_bytes
;
515 static unsigned long num_recorded_frames
;
517 static void drain_dma_buffer(void)
520 "mov #0x40,r2 \n" /* mask for EOD check */
522 "mov.b @%0,r1 \n" /* read PBDR (first time) */
525 "xor.b #0x08,@(r0,gbr) \n" /* set PR active */
527 "mov.b @%0,r1 \n" /* read PBDR */
528 "cmp/pz r1 \n" /* and wait for PRTW */
531 "xor.b #0x08,@(r0,gbr) \n" /* reset PR to inactive */
533 "mov.b @%0,r1 \n" /* read PBDR */
534 "cmp/pz r1 \n" /* and wait for /PRTW */
538 "tst r1,r2 \n" /* EOD low? */
539 "bf .d_loop \n" /* no: next pass */
543 /* %0 */ "r"(PBDR_ADDR
),
544 /* %1 = r0 */ "z"(&PADRH
)
550 #endif /* #if CONFIG_HWCODEC == MAS3587F */
552 void rec_tick (void) __attribute__ ((section (".icode")));
555 #if CONFIG_HWCODEC == MAS3587F
558 if(is_recording
&& (PBDR
& 0x4000))
561 timing_info
[timing_info_index
++] = current_tick
;
563 #endif /* #ifdef DEBUG */
564 /* We read as long as EOD is high, but max 30 bytes. */
566 "mov #30,r3 \n" /* i_max = 30 */
567 "mov #0x40,r2 \n" /* mask for EOD check */
568 "mov #0,%0 \n" /* i = 0; */
569 "add %2,%1 \n" /* mp3buf_write -> cur_addr */
570 "add %2,%3 \n" /* mp3buflen -> end_addr */
572 "mov.b @%4,r1 \n" /* read PBDR (first time) */
577 "xor.b #0x08,@(r0,gbr) \n" /* set PR active */
579 "mov.b @%4,r1 \n" /* read PBDR */
580 "cmp/pz r1 \n" /* and wait for PRTW */
583 "mov.b @%6,r1 \n" /* read byte from mas */
584 "add #1,%0 \n" /* i++; */
585 "mov.b r1,@%1 \n" /* store byte */
586 "add #1,%1 \n" /* increment current address */
588 "cmp/hi %1,%3 \n" /* end address reached? */
589 "bt .r_nowrap \n" /* no: do nothing */
590 "mov %2,%1 \n" /* yes: reset to start address */
593 "xor.b #0x08,@(r0,gbr) \n" /* set PR inactive again */
595 "mov.b @%4,r1 \n" /* read PBDR */
596 "cmp/pz r1 \n" /* and wait for /PRTW */
600 "tst r2,r1 \n" /* EOD low? */
601 "bt .r_end \n" /* yes: end of transfer */
602 "cmp/hi %0,r3 \n" /* i < i_max? */
603 "bt .r_loop \n" /* yes: next pass */
606 "sub %2,%1 \n" /* cur_addr -> mp3buf_write */
609 /* %1, in & out */ "+r"(mp3buf_write
)
611 /* %2 */ "r"(mp3buf
),
612 /* %3 */ "r"(mp3buflen
),
613 /* %4 */ "r"(PBDR_ADDR
),
614 /* %5 = r0 */ "z"(&PADRH
),
615 /* %6 */ "r"(0x4000000)
620 timing_info
[timing_info_index
++] = TCNT2
+ (i
<< 16);
621 timing_info_index
&= 0x3ff;
622 #endif /* #ifdef DEBUG */
628 if(TIME_AFTER(current_tick
, prerecord_timeout
))
630 prerecord_timeout
= current_tick
+ HZ
;
632 /* Store the write pointer every second */
633 prerecord_buffer
[prerecord_index
++] = mp3buf_write
;
635 /* Wrap if necessary */
636 if(prerecord_index
== prerecording_max_seconds
)
639 /* Update the number of seconds recorded */
640 if(prerecord_count
< prerecording_max_seconds
)
646 /* Signal to save the data if we are running out of buffer
648 num_bytes
= mp3buf_write
- mp3buf_read
;
650 num_bytes
+= mp3buflen
;
652 if(mp3buflen
- num_bytes
< MPEG_RECORDING_LOW_WATER
&& !saving
)
655 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
660 #endif /* #if CONFIG_HWCODEC == MAS3587F */
663 void playback_tick(void)
665 id3tags
[tag_read_idx
].id3
.elapsed
+=
666 (current_tick
- last_dma_tick
) * 1000 / HZ
;
667 last_dma_tick
= current_tick
;
670 static void reset_mp3_buffer(void)
674 mp3buf_swapwrite
= 0;
675 lowest_watermark_level
= mp3buflen
;
678 /* DMA transfer end interrupt callback */
679 static void transfer_end(unsigned char** ppbuf
, int* psize
)
681 if(playing
&& !paused
)
683 int unplayed_space_left
;
684 int space_until_end_of_buffer
;
685 int track_offset
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
687 mp3buf_read
+= last_dma_chunk_size
;
688 if(mp3buf_read
>= mp3buflen
)
691 /* First, check if we are on a track boundary */
692 if (num_tracks_in_memory() > 1)
694 if (mp3buf_read
== id3tags
[track_offset
].mempos
)
696 queue_post(&mpeg_queue
, MPEG_TRACK_CHANGE
, 0);
697 track_offset
= (track_offset
+1) & MAX_ID3_TAGS_MASK
;
701 unplayed_space_left
= get_unplayed_space();
703 space_until_end_of_buffer
= mp3buflen
- mp3buf_read
;
705 if(!filling
&& unplayed_space_left
< low_watermark
)
708 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
711 if(unplayed_space_left
)
713 last_dma_chunk_size
= MIN(0x2000, unplayed_space_left
);
714 last_dma_chunk_size
= MIN(last_dma_chunk_size
,
715 space_until_end_of_buffer
);
717 /* several tracks loaded? */
718 if (num_tracks_in_memory() > 1)
720 /* will we move across the track boundary? */
721 if (( mp3buf_read
< id3tags
[track_offset
].mempos
) &&
722 ((mp3buf_read
+last_dma_chunk_size
) >
723 id3tags
[track_offset
].mempos
))
725 /* Make sure that we end exactly on the boundary */
726 last_dma_chunk_size
= id3tags
[track_offset
].mempos
731 *psize
= last_dma_chunk_size
& 0xffff;
732 *ppbuf
= mp3buf
+ mp3buf_read
;
733 id3tags
[tag_read_idx
].id3
.offset
+= last_dma_chunk_size
;
735 /* Update the watermark debug level */
736 if(unplayed_space_left
< lowest_watermark_level
)
737 lowest_watermark_level
= unplayed_space_left
;
741 /* Check if the end of data is because of a hard disk error.
742 If there is an open file handle, we are still playing music.
743 If not, the last file has been loaded, and the file handle is
747 /* Update the watermark debug level */
748 if(unplayed_space_left
< lowest_watermark_level
)
749 lowest_watermark_level
= unplayed_space_left
;
751 DEBUGF("DMA underrun.\n");
756 DEBUGF("No more MP3 data. Stopping.\n");
758 queue_post(&mpeg_queue
, MPEG_TRACK_CHANGE
, 0);
762 *psize
= 0; /* no more transfer */
769 static int add_track_to_tag_list(const char *filename
)
771 if(num_tracks_in_memory() >= MAX_ID3_TAGS
)
773 DEBUGF("Tag memory is full\n");
777 /* grab id3 tag of new file and
778 remember where in memory it starts */
779 if(mp3info(&id3tags
[tag_write_idx
].id3
, filename
, v1first
))
784 id3tags
[tag_write_idx
].mempos
= mp3buf_write
;
785 id3tags
[tag_write_idx
].id3
.elapsed
= 0;
787 tag_write_idx
= (tag_write_idx
+1) & MAX_ID3_TAGS_MASK
;
792 static int new_file(int steps
)
794 int max_steps
= playlist_amount();
798 /* Find out how many steps to advance. The load_ahead_index field tells
799 us how many playlist entries it had to skip to get to a valid one.
800 We add those together to find out where to start. */
801 if(steps
> 0 && num_tracks_in_memory() > 1)
803 /* Begin with the song after the currently playing one */
804 i
= (tag_read_idx
+ 1) & MAX_ID3_TAGS_MASK
;
805 while(i
!= tag_write_idx
)
807 start
+= id3tags
[i
].load_ahead_index
;
808 i
= (i
+1) & MAX_ID3_TAGS_MASK
;
815 trackname
= playlist_peek( start
+ steps
);
819 DEBUGF("Loading %s\n", trackname
);
821 mpeg_file
= open(trackname
, O_RDONLY
);
823 DEBUGF("Couldn't open file: %s\n",trackname
);
831 int new_tag_idx
= tag_write_idx
;
833 if(add_track_to_tag_list(trackname
))
845 /* skip past id3v2 tag */
847 id3tags
[new_tag_idx
].id3
.first_frame_offset
,
849 id3tags
[new_tag_idx
].id3
.index
= steps
;
850 id3tags
[new_tag_idx
].load_ahead_index
= steps
;
851 id3tags
[new_tag_idx
].id3
.offset
= 0;
853 if(id3tags
[new_tag_idx
].id3
.vbr
)
854 /* Average bitrate * 1.5 */
855 recalculate_watermark(
856 (id3tags
[new_tag_idx
].id3
.bitrate
* 3) / 2);
858 recalculate_watermark(
859 id3tags
[new_tag_idx
].id3
.bitrate
);
864 /* Bail out if no file could be opened */
865 if(abs(steps
) > max_steps
)
867 } while ( mpeg_file
< 0 );
872 static void stop_playing(void)
874 /* Stop the current stream */
885 static void update_playlist(void)
889 if (num_tracks_in_memory() > 0)
891 index
= playlist_next(id3tags
[tag_read_idx
].id3
.index
);
892 id3tags
[tag_read_idx
].id3
.index
= index
;
896 static void track_change(void)
898 DEBUGF("Track change\n");
900 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
902 mpeg_sound_set(SOUND_AVC
, -1);
903 #endif /* #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */
904 remove_current_tag();
907 current_track_counter
++;
911 void hexdump(const unsigned char *buf
, int len
)
915 for(i
= 0;i
< len
;i
++)
917 if(i
&& (i
& 15) == 0)
921 DEBUGF("%02x ", buf
[i
]);
925 #endif /* #ifdef DEBUG */
927 static void start_playback_if_ready(void)
931 playable_space
= mp3buf_swapwrite
- mp3buf_read
;
932 if(playable_space
< 0)
933 playable_space
+= mp3buflen
;
935 /* See if we have started playing yet. If not, do it. */
936 if(play_pending
|| dma_underrun
)
938 /* If the filling has stopped, and we still haven't reached
939 the watermark, the file must be smaller than the
940 watermark. We must still play it. */
941 if((playable_space
>= MPEG_PLAY_PENDING_THRESHOLD
) ||
942 !filling
|| dma_underrun
)
945 play_pending
= false;
948 last_dma_chunk_size
= MIN(0x2000, get_unplayed_space_current_song());
949 mp3_play_data(mp3buf
+ mp3buf_read
, last_dma_chunk_size
, transfer_end
);
950 dma_underrun
= false;
954 last_dma_tick
= current_tick
;
955 mp3_play_pause(true);
958 /* Tell ourselves that we need more data */
959 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
964 static bool swap_one_chunk(void)
969 free_space_left
= get_unswapped_space();
971 if(free_space_left
== 0 && !play_pending
)
974 /* Swap in larger chunks when the user is waiting for the playback
975 to start, or when there is dangerously little playable data left */
977 amount_to_swap
= MIN(MPEG_PLAY_PENDING_SWAPSIZE
, free_space_left
);
980 if(get_playable_space() < low_watermark
)
981 amount_to_swap
= MIN(MPEG_LOW_WATER_SWAP_CHUNKSIZE
,
984 amount_to_swap
= MIN(MPEG_SWAP_CHUNKSIZE
, free_space_left
);
987 if(mp3buf_write
< mp3buf_swapwrite
)
988 amount_to_swap
= MIN(mp3buflen
- mp3buf_swapwrite
,
991 amount_to_swap
= MIN(mp3buf_write
- mp3buf_swapwrite
,
994 bitswap(mp3buf
+ mp3buf_swapwrite
, amount_to_swap
);
996 mp3buf_swapwrite
+= amount_to_swap
;
997 if(mp3buf_swapwrite
>= mp3buflen
)
999 mp3buf_swapwrite
= 0;
1005 static const unsigned char empty_id3_header
[] =
1007 'I', 'D', '3', 0x03, 0x00, 0x00,
1008 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
1011 static void mpeg_thread(void)
1013 static int pause_tick
= 0;
1014 static unsigned int pause_track
= 0;
1017 int free_space_left
;
1018 int unplayed_space_left
;
1022 #if CONFIG_HWCODEC == MAS3587F
1026 unsigned long saved_header
= 0;
1031 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1034 play_pending
= false;
1040 #if CONFIG_HWCODEC == MAS3587F
1041 if(mpeg_mode
== MPEG_DECODER
)
1043 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1046 /* Swap if necessary, and don't block on the queue_wait() */
1047 if(swap_one_chunk())
1049 queue_wait_w_tmo(&mpeg_queue
, &ev
, 0);
1053 DEBUGF("S R:%x W:%x SW:%x\n",
1054 mp3buf_read
, mp3buf_write
, mp3buf_swapwrite
);
1055 queue_wait(&mpeg_queue
, &ev
);
1058 start_playback_if_ready();
1063 DEBUGF("MPEG_PLAY\n");
1066 /* Silence the A/D input, it may be on because the radio
1068 mas_codec_writereg(6, 0x0000);
1069 #endif /* #ifdef CONFIG_TUNER */
1071 /* Stop the current stream */
1072 play_pending
= false;
1075 mp3_play_pause(false);
1083 if ( new_file(0) == -1 )
1090 start_offset
= (int)ev
.data
;
1092 /* mid-song resume? */
1094 struct mp3entry
* id3
= &id3tags
[tag_read_idx
].id3
;
1095 lseek(mpeg_file
, start_offset
, SEEK_SET
);
1096 id3
->offset
= start_offset
;
1100 /* skip past id3v2 tag */
1102 id3tags
[tag_read_idx
].id3
.first_frame_offset
,
1107 /* Make it read more data */
1109 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1111 /* Tell the file loading code that we want to start playing
1112 as soon as we have some data */
1113 play_pending
= true;
1116 current_track_counter
++;
1120 DEBUGF("MPEG_STOP\n");
1124 mpeg_stop_done
= true;
1128 DEBUGF("MPEG_PAUSE\n");
1129 /* Stop the current stream */
1132 pause_tick
= current_tick
;
1133 pause_track
= current_track_counter
;
1134 mp3_play_pause(false);
1138 DEBUGF("MPEG_RESUME\n");
1139 /* Continue the current stream */
1144 if ( current_track_counter
== pause_track
)
1145 last_dma_tick
+= current_tick
- pause_tick
;
1147 last_dma_tick
= current_tick
;
1149 mp3_play_pause(true);
1154 DEBUGF("MPEG_NEXT\n");
1155 /* is next track in ram? */
1156 if ( num_tracks_in_memory() > 1 ) {
1157 int unplayed_space_left
, unswapped_space_left
;
1159 /* stop the current stream */
1160 play_pending
= false;
1162 mp3_play_pause(false);
1165 mp3buf_read
= id3tags
[tag_read_idx
].mempos
;
1166 last_dma_chunk_size
= MIN(0x2000, get_unplayed_space_current_song());
1167 mp3_play_data(mp3buf
+ mp3buf_read
, last_dma_chunk_size
, transfer_end
);
1168 dma_underrun
= false;
1169 last_dma_tick
= current_tick
;
1171 unplayed_space_left
= get_unplayed_space();
1172 unswapped_space_left
= get_unswapped_space();
1174 /* should we start reading more data? */
1175 if(!filling
&& (unplayed_space_left
< low_watermark
)) {
1177 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1178 play_pending
= true;
1179 } else if(unswapped_space_left
&&
1180 unswapped_space_left
> unplayed_space_left
) {
1181 /* Stop swapping the data from the previous file */
1182 mp3buf_swapwrite
= mp3buf_read
;
1183 play_pending
= true;
1187 mp3_play_pause(true);
1191 if (!playlist_check(1))
1194 /* stop the current stream */
1195 play_pending
= false;
1197 mp3_play_pause(false);
1202 /* Open the next file */
1206 if (new_file(1) < 0) {
1207 DEBUGF("No more files to play\n");
1210 /* Make it read more data */
1212 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1214 /* Tell the file loading code that we want
1215 to start playing as soon as we have some data */
1216 play_pending
= true;
1219 current_track_counter
++;
1225 DEBUGF("MPEG_PREV\n");
1227 if (!playlist_check(-1))
1230 /* stop the current stream */
1231 play_pending
= false;
1233 mp3_play_pause(false);
1238 /* Open the next file */
1242 if (new_file(-1) < 0) {
1243 DEBUGF("No more files to play\n");
1246 /* Make it read more data */
1248 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1250 /* Tell the file loading code that we want to
1251 start playing as soon as we have some data */
1252 play_pending
= true;
1255 current_track_counter
++;
1260 case MPEG_FF_REWIND
: {
1261 struct mp3entry
*id3
= mpeg_current_track();
1262 unsigned int oldtime
= id3
->elapsed
;
1263 unsigned int newtime
= (unsigned int)ev
.data
;
1264 int curpos
, newpos
, diffpos
;
1265 DEBUGF("MPEG_FF_REWIND\n");
1267 id3
->elapsed
= newtime
;
1269 newpos
= mpeg_get_file_pos();
1272 id3
->elapsed
= oldtime
;
1277 curpos
= lseek(mpeg_file
, 0, SEEK_CUR
);
1279 curpos
= id3
->filesize
;
1281 if (num_tracks_in_memory() > 1)
1283 /* We have started loading other tracks that need to be
1285 int i
= tag_read_idx
;
1286 int j
= tag_write_idx
- 1;
1289 j
= MAX_ID3_TAGS
- 1;
1293 curpos
+= id3tags
[i
].id3
.filesize
;
1294 i
= (i
+1) & MAX_ID3_TAGS_MASK
;
1298 diffpos
= curpos
- newpos
;
1300 if(!filling
&& diffpos
>= 0 && diffpos
< mp3buflen
)
1302 int unplayed_space_left
, unswapped_space_left
;
1304 /* We are changing to a position that's already in
1305 memory, so we just move the DMA read pointer. */
1306 mp3buf_read
= mp3buf_write
- diffpos
;
1307 if (mp3buf_read
< 0)
1309 mp3buf_read
+= mp3buflen
;
1312 unplayed_space_left
= get_unplayed_space();
1313 unswapped_space_left
= get_unswapped_space();
1315 /* If unswapped_space_left is larger than
1316 unplayed_space_left, it means that the swapwrite pointer
1317 hasn't yet advanced up to the new location of the read
1318 pointer. We just move it, there is no need to swap
1319 data that won't be played anyway. */
1321 if (unswapped_space_left
> unplayed_space_left
)
1323 DEBUGF("Moved swapwrite\n");
1324 mp3buf_swapwrite
= mp3buf_read
;
1325 play_pending
= true;
1328 if (mpeg_file
>=0 && unplayed_space_left
< low_watermark
)
1330 /* We need to load more data before starting */
1332 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1333 play_pending
= true;
1337 /* resume will start at new position */
1338 last_dma_chunk_size
=
1339 MIN(0x2000, get_unplayed_space_current_song());
1340 mp3_play_data(mp3buf
+ mp3buf_read
,
1341 last_dma_chunk_size
, transfer_end
);
1342 dma_underrun
= false;
1347 /* Move to the new position in the file and start
1351 if (num_tracks_in_memory() > 1)
1353 /* We have to reload the current track */
1355 remove_all_non_current_tags();
1361 mpeg_file
= open(id3
->path
, O_RDONLY
);
1364 id3
->elapsed
= oldtime
;
1369 if(-1 == lseek(mpeg_file
, newpos
, SEEK_SET
))
1371 id3
->elapsed
= oldtime
;
1376 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1378 /* Tell the file loading code that we want to start playing
1379 as soon as we have some data */
1380 play_pending
= true;
1383 id3
->offset
= newpos
;
1388 case MPEG_FLUSH_RELOAD
: {
1389 int numtracks
= num_tracks_in_memory();
1390 bool reload_track
= false;
1395 int next
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
1397 /* Reset the buffer */
1398 mp3buf_write
= id3tags
[next
].mempos
;
1400 /* Reset swapwrite unless we're still swapping current
1402 if (get_unplayed_space() <= get_playable_space())
1403 mp3buf_swapwrite
= mp3buf_write
;
1406 remove_all_non_current_tags();
1408 reload_track
= true;
1410 else if (numtracks
== 1 && mpeg_file
< 0)
1412 reload_track
= true;
1415 if(reload_track
&& new_file(1) >= 0)
1417 /* Tell ourselves that we want more data */
1418 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1425 case MPEG_NEED_DATA
:
1426 free_space_left
= mp3buf_read
- mp3buf_write
;
1428 /* We interpret 0 as "empty buffer" */
1429 if(free_space_left
<= 0)
1430 free_space_left
= mp3buflen
+ free_space_left
;
1432 unplayed_space_left
= mp3buflen
- free_space_left
;
1434 /* Make sure that we don't fill the entire buffer */
1435 free_space_left
-= MPEG_HIGH_WATER
;
1437 /* do we have any more buffer space to fill? */
1438 if(free_space_left
<= MPEG_HIGH_WATER
)
1446 /* Read small chunks while we are below the low water mark */
1447 if(unplayed_space_left
< low_watermark
)
1448 amount_to_read
= MIN(MPEG_LOW_WATER_CHUNKSIZE
,
1451 amount_to_read
= free_space_left
;
1453 /* Don't read more than until the end of the buffer */
1454 amount_to_read
= MIN(mp3buflen
- mp3buf_write
, amount_to_read
);
1456 amount_to_read
= MIN(0x100000, amount_to_read
);
1457 #endif /* #if MEM == 8 */
1458 #ifdef HAVE_MMC /* MMC is slow, so don't read too large chunks */
1459 amount_to_read
= MIN(0x40000, amount_to_read
);
1462 /* Read as much mpeg data as we can fit in the buffer */
1467 len
= read(mpeg_file
, mp3buf
+mp3buf_write
, amount_to_read
);
1471 DEBUGF("time: %d\n", t2
- t1
);
1472 DEBUGF("R: %x\n", len
);
1474 /* Now make sure that we don't feed the MAS with ID3V1
1476 if (len
< amount_to_read
)
1478 int tagptr
= mp3buf_write
+ len
- 128;
1483 for(i
= 0;i
< 3;i
++)
1485 if(tagptr
>= mp3buflen
)
1486 tagptr
-= mp3buflen
;
1488 if(mp3buf
[tagptr
] != tag
[i
])
1496 /* Skip id3v1 tag */
1497 DEBUGF("Skipping ID3v1 tag\n");
1500 /* The very rare case when the entire tag
1501 wasn't read in this read() call must be
1508 mp3buf_write
+= len
;
1510 if(mp3buf_write
>= mp3buflen
)
1516 /* Tell ourselves that we want more data */
1517 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1523 DEBUGF("MPEG read error\n");
1531 /* No more data to play */
1532 DEBUGF("No more files to play\n");
1537 /* Tell ourselves that we want more data */
1538 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1544 case MPEG_TRACK_CHANGE
:
1549 case SYS_USB_CONNECTED
:
1555 /* Tell the USB thread that we are safe */
1556 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
1557 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1559 /* Wait until the USB cable is extracted again */
1560 usb_wait_for_disconnect(&mpeg_queue
);
1561 #endif /* #ifndef SIMULATOR */
1563 #endif /* #ifndef USB_NONE */
1565 #if CONFIG_HWCODEC == MAS3587F
1566 case MPEG_INIT_RECORDING
:
1568 init_recording_done
= true;
1570 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1572 #if CONFIG_HWCODEC == MAS3587F
1576 queue_wait(&mpeg_queue
, &ev
);
1584 /* Go back prerecord_count seconds in the buffer */
1585 startpos
= prerecord_index
- prerecord_count
;
1587 startpos
+= prerecording_max_seconds
;
1589 /* Read the mp3 buffer pointer from the prerecord buffer */
1590 startpos
= prerecord_buffer
[startpos
];
1592 DEBUGF("Start looking at address %x (%x)\n",
1593 mp3buf
+startpos
, startpos
);
1595 saved_header
= mpeg_get_last_header();
1597 mem_find_next_frame(startpos
, &offset
, 5000,
1600 mp3buf_read
= startpos
+ offset
;
1602 DEBUGF("New mp3buf_read address: %x (%x)\n",
1603 mp3buf
+mp3buf_read
, mp3buf_read
);
1605 /* Make room for headers */
1606 mp3buf_read
-= MPEG_RESERVED_HEADER_SPACE
;
1609 /* Clear the bottom half */
1611 mp3buf_read
+ MPEG_RESERVED_HEADER_SPACE
);
1613 /* And the top half */
1614 mp3buf_read
+= mp3buflen
;
1615 memset(mp3buf
+ mp3buf_read
, 0,
1616 mp3buflen
- mp3buf_read
);
1620 memset(mp3buf
+ mp3buf_read
, 0,
1621 MPEG_RESERVED_HEADER_SPACE
);
1624 /* Copy the empty ID3 header */
1625 startpos
= mp3buf_read
;
1626 for(i
= 0;i
< (int)sizeof(empty_id3_header
);i
++)
1628 mp3buf
[startpos
++] = empty_id3_header
[i
];
1629 if(startpos
== mp3buflen
)
1633 DEBUGF("New mp3buf_read address (reservation): %x\n",
1634 mp3buf
+mp3buf_read
);
1636 DEBUGF("Prerecording...\n");
1644 /* Advance the write pointer to make
1645 room for an ID3 tag plus a VBR header */
1646 mp3buf_write
= MPEG_RESERVED_HEADER_SPACE
;
1647 memset(mp3buf
, 0, MPEG_RESERVED_HEADER_SPACE
);
1649 /* Insert the ID3 header */
1650 memcpy(mp3buf
, empty_id3_header
,
1651 sizeof(empty_id3_header
));
1653 DEBUGF("Recording...\n");
1658 /* Wait until at least one frame is encoded and get the
1659 frame header, for later use by the Xing header
1662 saved_header
= mpeg_get_last_header();
1664 /* delayed until buffer is saved, don't open yet */
1665 strcpy(delayed_filename
, recording_filename
);
1671 DEBUGF("MPEG_STOP\n");
1675 /* Save the remaining data in the buffer */
1676 stop_pending
= true;
1677 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1680 case MPEG_STOP_DONE
:
1681 DEBUGF("MPEG_STOP_DONE\n");
1686 if(!disable_xing_header
&& num_rec_bytes
> 0)
1688 /* Create the Xing header */
1689 mpeg_file
= open(recording_filename
, O_RDWR
);
1691 panicf("rec upd: %d (%s)", mpeg_file
,
1692 recording_filename
);
1694 /* If the number of recorded frames have
1695 reached 0x7ffff, we can no longer trust it */
1696 if(num_recorded_frames
== 0x7ffff)
1697 num_recorded_frames
= 0;
1699 /* Also, if we have been prerecording, the frame count
1702 num_recorded_frames
= 0;
1704 /* saved_header is saved right before stopping
1706 framelen
= create_xing_header(mpeg_file
, 0,
1707 num_rec_bytes
, mp3buf
,
1708 num_recorded_frames
,
1712 lseek(mpeg_file
, MPEG_RESERVED_HEADER_SPACE
-framelen
,
1714 write(mpeg_file
, mp3buf
, framelen
);
1722 for(i
= 0;i
< 512;i
++)
1724 DEBUGF("%d - %d us (%d bytes)\n",
1726 (timing_info
[i
*2+1] & 0xffff) *
1728 timing_info
[i
*2+1] >> 16);
1731 #endif /* #ifdef DEBUG1 */
1735 start_prerecording();
1737 mpeg_stop_done
= true;
1741 /* Make sure we have at least one complete frame
1742 in the buffer. If we haven't recorded a single
1743 frame within 200ms, the MAS is probably not recording
1744 anything, and we bail out. */
1746 amount_to_save
= get_unsaved_space();
1747 while(countdown
-- && amount_to_save
< 1800)
1750 amount_to_save
= get_unsaved_space();
1753 if(amount_to_save
>= 1800)
1755 /* Now find a frame boundary to split at */
1756 startpos
= mp3buf_write
- 1800;
1758 startpos
+= mp3buflen
;
1760 rc
= mem_find_next_frame(startpos
, &offset
, 1800,
1762 if(rc
) /* Header found? */
1764 /* offset will now contain the number of bytes to
1765 add to startpos to find the frame boundary */
1767 if(startpos
>= mp3buflen
)
1768 startpos
-= mp3buflen
;
1772 /* No header found. Let's save the whole buffer. */
1773 startpos
= mp3buf_write
;
1778 /* Too few bytes recorded, timeout */
1779 startpos
= mp3buf_write
;
1782 amount_to_save
= startpos
- mp3buf_read
;
1783 if(amount_to_save
< 0)
1784 amount_to_save
+= mp3buflen
;
1786 /* First save up to the end of the buffer */
1787 writelen
= MIN(amount_to_save
,
1788 mp3buflen
- mp3buf_read
);
1790 if (mpeg_file
< 0) /* delayed file opening */
1792 mpeg_file
= open(delayed_filename
, O_WRONLY
|O_CREAT
);
1795 panicf("recfile: %d", mpeg_file
);
1800 rc
= write(mpeg_file
, mp3buf
+ mp3buf_read
, writelen
);
1805 mpeg_errno
= MPEGERR_DISK_FULL
;
1806 demand_irq_enable(false);
1808 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1813 panicf("spt wrt: %d", rc
);
1818 /* Then save the rest */
1819 writelen
= amount_to_save
- writelen
;
1822 rc
= write(mpeg_file
, mp3buf
, writelen
);
1827 mpeg_errno
= MPEGERR_DISK_FULL
;
1828 demand_irq_enable(false);
1830 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1835 panicf("spt wrt: %d", rc
);
1840 /* Advance the buffer pointers */
1841 mp3buf_read
+= amount_to_save
;
1842 if(mp3buf_read
>= mp3buflen
)
1843 mp3buf_read
-= mp3buflen
;
1845 /* Close the current file */
1846 rc
= close(mpeg_file
);
1848 panicf("spt cls: %d", rc
);
1850 /* Open the new file */
1851 mpeg_file
= open(recording_filename
, O_WRONLY
|O_CREAT
);
1853 panicf("sptfile: %d", mpeg_file
);
1856 case MPEG_SAVE_DATA
:
1857 amount_to_save
= get_unsaved_space();
1859 /* If the result is negative, the write index has
1861 if(amount_to_save
< 0)
1863 amount_to_save
+= mp3buflen
;
1866 DEBUGF("r: %x w: %x\n", mp3buf_read
, mp3buf_write
);
1867 DEBUGF("ats: %x\n", amount_to_save
);
1869 /* Save data only if the buffer is getting full,
1870 or if we should stop recording */
1874 amount_to_save
< MPEG_RECORDING_LOW_WATER
||
1877 /* Only save up to the end of the buffer */
1878 writelen
= MIN(amount_to_save
,
1879 mp3buflen
- mp3buf_read
);
1881 DEBUGF("wrl: %x\n", writelen
);
1883 if (mpeg_file
< 0) /* delayed file opening */
1885 mpeg_file
= open(delayed_filename
,
1889 panicf("recfile: %d", mpeg_file
);
1892 rc
= write(mpeg_file
, mp3buf
+ mp3buf_read
,
1899 mpeg_errno
= MPEGERR_DISK_FULL
;
1901 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1906 panicf("rec wrt: %d", rc
);
1910 mp3buf_read
+= amount_to_save
;
1911 if(mp3buf_read
>= mp3buflen
)
1914 rc
= fsync(mpeg_file
);
1916 panicf("rec fls: %d", rc
);
1918 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1928 /* We have saved all data,
1929 time to stop for real */
1931 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1937 case MPEG_INIT_PLAYBACK
:
1938 /* Stop the prerecording */
1941 init_playback_done
= true;
1944 case MPEG_PAUSE_RECORDING
:
1948 case MPEG_RESUME_RECORDING
:
1952 case SYS_USB_CONNECTED
:
1953 /* We can safely go to USB mode if no recording
1955 if((!is_recording
|| is_prerecording
) && mpeg_stop_done
)
1957 /* Even if we aren't recording, we still call this
1958 function, to put the MAS in monitoring mode,
1962 /* Tell the USB thread that we are safe */
1963 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
1964 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1966 /* Wait until the USB cable is extracted again */
1967 usb_wait_for_disconnect(&mpeg_queue
);
1972 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1975 #endif /* SIMULATOR */
1978 static struct mp3entry taginfo
;
1979 #endif /* #ifdef SIMULATOR */
1981 void mpeg_id3_options(bool _v1first
)
1986 struct mp3entry
* mpeg_current_track()
1991 if(num_tracks_in_memory())
1992 return &id3tags
[tag_read_idx
].id3
;
1995 #endif /* #ifdef SIMULATOR */
1998 struct mp3entry
* mpeg_next_track()
2003 if(num_tracks_in_memory() > 1)
2004 return &(id3tags
[(tag_read_idx
+1) & MAX_ID3_TAGS_MASK
].id3
);
2007 #endif /* #ifdef SIMULATOR */
2010 bool mpeg_has_changed_track(void)
2012 if(last_track_counter
!= current_track_counter
)
2014 last_track_counter
= current_track_counter
;
2020 #if CONFIG_HWCODEC == MAS3587F
2021 void mpeg_init_playback(void)
2023 init_playback_done
= false;
2024 queue_post(&mpeg_queue
, MPEG_INIT_PLAYBACK
, NULL
);
2026 while(!init_playback_done
)
2032 /****************************************************************************
2035 ** Recording functions
2038 ***************************************************************************/
2039 void mpeg_init_recording(void)
2041 init_recording_done
= false;
2042 queue_post(&mpeg_queue
, MPEG_INIT_RECORDING
, NULL
);
2044 while(!init_recording_done
)
2049 static void init_recording(void)
2061 /* Init the recording variables */
2062 is_recording
= false;
2063 is_prerecording
= false;
2065 mpeg_stop_done
= true;
2069 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2070 rc
= mas_direct_config_write(MAS_CONTROL
, 0x8c00);
2072 panicf("mas_ctrl_w: %d", rc
);
2074 /* Stop the current application */
2076 mas_writemem(MAS_BANK_D0
, MAS_D0_APP_SELECT
, &val
, 1);
2079 mas_readmem(MAS_BANK_D0
, MAS_D0_APP_RUNNING
, &val
, 1);
2082 /* Perform black magic as described by the data sheet */
2083 if((mas_version_code
& 0x0fff) == 0x0102)
2085 DEBUGF("Performing MAS black magic for B2 version\n");
2086 mas_writereg(0xa3, 0x98);
2087 mas_writereg(0x94, 0xfffff);
2089 mas_writemem(MAS_BANK_D1
, 0, &val
, 1);
2090 mas_writereg(0xa3, 0x90);
2093 /* Enable A/D Converters */
2094 shadow_codec_reg0
= 0xcccd;
2095 mas_codec_writereg(0x0, shadow_codec_reg0
);
2097 /* Copy left channel to right (mono mode) */
2098 mas_codec_writereg(8, 0x8000);
2100 /* ADC scale 0%, DSP scale 100%
2101 We use the DSP output for monitoring, because it works with all
2102 sources including S/PDIF */
2103 mas_codec_writereg(6, 0x0000);
2104 mas_codec_writereg(7, 0x4000);
2107 shadow_soft_mute
= 0;
2108 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2110 /* Set Demand mode, monitoring OFF and validate all settings */
2111 shadow_io_control_main
= 0x125;
2112 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2114 /* Start the encoder application */
2116 mas_writemem(MAS_BANK_D0
, MAS_D0_APP_SELECT
, &val
, 1);
2119 mas_readmem(MAS_BANK_D0
, MAS_D0_APP_RUNNING
, &val
, 1);
2120 } while(!(val
& 0x40));
2123 /* We have started the recording application with monitoring OFF.
2124 This is because we want to record at least one frame to fill the DMA
2125 buffer, because the silly MAS will not negate EOD until at least one
2126 DMA transfer has taken place.
2127 Now let's wait for some data to be encoded. */
2130 /* Now set it to Monitoring mode as default, saves power */
2131 shadow_io_control_main
= 0x525;
2132 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2134 /* Wait until the DSP has accepted the settings */
2137 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2142 mpeg_mode
= MPEG_ENCODER
;
2144 DEBUGF("MAS Recording application started\n");
2146 /* At this point, all settings are the reset MAS defaults, next thing is to
2147 call mpeg_set_recording_options(). */
2150 void mpeg_record(const char *filename
)
2154 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
2155 recording_filename
[MAX_PATH
- 1] = 0;
2157 disable_xing_header
= false;
2158 queue_post(&mpeg_queue
, MPEG_RECORD
, NULL
);
2161 void mpeg_pause_recording(void)
2163 queue_post(&mpeg_queue
, MPEG_PAUSE_RECORDING
, NULL
);
2166 void mpeg_resume_recording(void)
2168 queue_post(&mpeg_queue
, MPEG_RESUME_RECORDING
, NULL
);
2171 static void start_prerecording(void)
2175 DEBUGF("Starting prerecording\n");
2177 prerecord_index
= 0;
2178 prerecord_count
= 0;
2179 prerecord_timeout
= current_tick
+ HZ
;
2180 memset(prerecord_buffer
, 0, sizeof(prerecord_buffer
));
2183 is_prerecording
= true;
2185 /* Stop monitoring and start the encoder */
2186 shadow_io_control_main
&= ~(1 << 10);
2187 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2188 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2190 /* Wait until the DSP has accepted the settings */
2193 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2196 is_recording
= true;
2197 stop_pending
= false;
2200 demand_irq_enable(true);
2203 static void start_recording(void)
2207 num_recorded_frames
= 0;
2211 /* This will make the IRQ handler start recording
2212 for real, i.e send MPEG_SAVE_DATA messages when
2213 the buffer is full */
2214 is_prerecording
= false;
2218 /* If prerecording is off, we need to stop the monitoring
2219 and start the encoder */
2220 shadow_io_control_main
&= ~(1 << 10);
2221 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2222 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2224 /* Wait until the DSP has accepted the settings */
2227 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2231 is_recording
= true;
2232 stop_pending
= false;
2236 /* Store the current time */
2238 record_start_time
= current_tick
- prerecord_count
* HZ
;
2240 record_start_time
= current_tick
;
2242 pause_start_time
= 0;
2244 demand_irq_enable(true);
2247 static void pause_recording(void)
2249 pause_start_time
= current_tick
;
2251 /* Set the pause bit */
2252 shadow_soft_mute
|= 2;
2253 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2258 static void resume_recording(void)
2262 /* Clear the pause bit */
2263 shadow_soft_mute
&= ~2;
2264 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2266 /* Compensate for the time we have been paused */
2267 if(pause_start_time
)
2270 current_tick
- (pause_start_time
- record_start_time
);
2271 pause_start_time
= 0;
2275 static void stop_recording(void)
2279 /* Let it finish the last frame */
2284 demand_irq_enable(false);
2286 is_recording
= false;
2287 is_prerecording
= false;
2289 /* Read the number of frames recorded */
2290 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_FRAME_COUNT
, &num_recorded_frames
, 1);
2292 /* Start monitoring */
2293 shadow_io_control_main
|= (1 << 10);
2294 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2295 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2297 /* Wait until the DSP has accepted the settings */
2300 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2306 void mpeg_set_recording_options(int frequency
, int quality
,
2307 int source
, int channel_mode
,
2308 bool editable
, int prerecord_time
)
2312 is_mpeg1
= (frequency
< 3)?true:false;
2314 rec_version_index
= is_mpeg1
?3:2;
2315 rec_frequency_index
= frequency
% 3;
2317 shadow_encoder_control
= (quality
<< 17) |
2318 (rec_frequency_index
<< 10) |
2319 ((is_mpeg1
?1:0) << 9) |
2320 (((channel_mode
* 2 + 1) & 3) << 6) |
2321 (1 << 5) /* MS-stereo */ |
2322 (1 << 2) /* Is an original */;
2323 mas_writemem(MAS_BANK_D0
, MAS_D0_ENCODER_CONTROL
, &shadow_encoder_control
,1);
2325 DEBUGF("mas_writemem(MAS_BANK_D0, ENCODER_CONTROL, %x)\n", shadow_encoder_control
);
2327 shadow_soft_mute
= editable
?4:0;
2328 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
,1);
2330 DEBUGF("mas_writemem(MAS_BANK_D0, SOFT_MUTE, %x)\n", shadow_soft_mute
);
2332 shadow_io_control_main
= ((1 << 10) | /* Monitoring ON */
2333 ((source
< 2)?1:2) << 8) | /* Input select */
2334 (1 << 5) | /* SDO strobe invert */
2335 ((is_mpeg1
?0:1) << 3) |
2336 (1 << 2) | /* Inverted SIBC clock signal */
2338 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
,1);
2340 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2342 if(source
== 0) /* Mic */
2344 /* Copy left channel to right (mono mode) */
2345 mas_codec_writereg(8, 0x8000);
2349 /* Stereo input mode */
2350 mas_codec_writereg(8, 0);
2353 prerecording_max_seconds
= prerecord_time
;
2354 if(prerecording_max_seconds
)
2356 prerecording
= true;
2357 start_prerecording();
2361 prerecording
= false;
2362 is_prerecording
= false;
2363 is_recording
= false;
2367 /* If use_mic is true, the left gain is used */
2368 void mpeg_set_recording_gain(int left
, int right
, bool use_mic
)
2370 /* Enable both left and right A/D */
2371 shadow_codec_reg0
= (left
<< 12) |
2374 (use_mic
?0x0008:0) | /* Connect left A/D to mic */
2376 mas_codec_writereg(0x0, shadow_codec_reg0
);
2379 /* try to make some kind of beep, also in recording mode */
2380 void mpeg_beep(int duration
)
2382 long starttick
= current_tick
;
2384 { /* toggle bit 0 of codec register 0, toggling the DAC off & on.
2385 * While this is still audible even without an external signal,
2386 * it doesn't affect the (pre-)recording. */
2387 mas_codec_writereg(0, shadow_codec_reg0
^ 1);
2388 mas_codec_writereg(0, shadow_codec_reg0
);
2390 while (current_tick
- starttick
< duration
);
2393 void mpeg_new_file(const char *filename
)
2397 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
2398 recording_filename
[MAX_PATH
- 1] = 0;
2401 disable_xing_header
= true;
2403 /* Store the current time */
2404 record_start_time
= current_tick
;
2406 pause_start_time
= record_start_time
;
2408 queue_post(&mpeg_queue
, MPEG_NEW_FILE
, NULL
);
2411 unsigned long mpeg_recorded_time(void)
2414 return prerecord_count
* HZ
;
2419 return pause_start_time
- record_start_time
;
2421 return current_tick
- record_start_time
;
2427 unsigned long mpeg_num_recorded_bytes(void)
2436 index
= prerecord_index
- prerecord_count
;
2438 index
+= prerecording_max_seconds
;
2440 num_bytes
= mp3buf_write
- prerecord_buffer
[index
];
2442 num_bytes
+= mp3buflen
;
2447 return num_rec_bytes
;
2455 void mpeg_play(int offset
)
2464 trackname
= playlist_peek( steps
);
2467 if(mp3info(&taginfo
, trackname
, v1first
)) {
2468 /* bad mp3, move on */
2469 if(++steps
> playlist_amount())
2473 #ifdef HAVE_MPEG_PLAY
2474 real_mpeg_play(trackname
);
2476 playlist_next(steps
);
2477 taginfo
.offset
= offset
;
2478 set_elapsed(&taginfo
);
2486 queue_post(&mpeg_queue
, MPEG_PLAY
, (void*)offset
);
2487 #endif /* #ifdef SIMULATOR */
2492 void mpeg_stop(void)
2495 mpeg_stop_done
= false;
2496 queue_post(&mpeg_queue
, MPEG_STOP
, NULL
);
2497 while(!mpeg_stop_done
)
2503 #endif /* #ifndef SIMULATOR */
2507 void mpeg_pause(void)
2510 queue_post(&mpeg_queue
, MPEG_PAUSE
, NULL
);
2515 #endif /* #ifndef SIMULATOR */
2518 void mpeg_resume(void)
2521 queue_post(&mpeg_queue
, MPEG_RESUME
, NULL
);
2526 #endif /* #ifndef SIMULATOR */
2529 void mpeg_next(void)
2532 queue_post(&mpeg_queue
, MPEG_NEXT
, NULL
);
2539 file
= playlist_peek(steps
);
2542 if(mp3info(&taginfo
, file
, v1first
)) {
2543 if(++steps
> playlist_amount())
2547 index
= playlist_next(steps
);
2548 taginfo
.index
= index
;
2549 current_track_counter
++;
2554 #endif /* #ifndef SIMULATOR */
2557 void mpeg_prev(void)
2560 queue_post(&mpeg_queue
, MPEG_PREV
, NULL
);
2567 file
= playlist_peek(steps
);
2570 if(mp3info(&taginfo
, file
, v1first
)) {
2574 index
= playlist_next(steps
);
2575 taginfo
.index
= index
;
2576 current_track_counter
++;
2581 #endif /* #ifndef SIMULATOR */
2584 void mpeg_ff_rewind(int newtime
)
2587 queue_post(&mpeg_queue
, MPEG_FF_REWIND
, (void *)newtime
);
2590 #endif /* #ifndef SIMULATOR */
2593 void mpeg_flush_and_reload_tracks(void)
2596 queue_post(&mpeg_queue
, MPEG_FLUSH_RELOAD
, NULL
);
2597 #endif /* #ifndef SIMULATOR*/
2600 int mpeg_status(void)
2605 ret
|= MPEG_STATUS_PLAY
;
2608 ret
|= MPEG_STATUS_PAUSE
;
2610 #if CONFIG_HWCODEC == MAS3587F
2611 if(is_recording
&& !is_prerecording
)
2612 ret
|= MPEG_STATUS_RECORD
;
2615 ret
|= MPEG_STATUS_PRERECORD
;
2616 #endif /* #if CONFIG_HWCODEC == MAS3587F */
2619 ret
|= MPEG_STATUS_ERROR
;
2624 unsigned int mpeg_error(void)
2629 void mpeg_error_clear(void)
2635 static char mpeg_stack
[DEFAULT_STACK_SIZE
];
2636 static const char mpeg_thread_name
[] = "mpeg";
2637 static void mpeg_thread(void)
2639 struct mp3entry
* id3
;
2642 id3
= mpeg_current_track();
2648 if (id3
->elapsed
>=id3
->length
)
2654 #endif /* #ifdef SIMULATOR */
2656 void mpeg_init(void)
2661 mp3buflen
= mp3end
- mp3buf
;
2662 queue_init(&mpeg_queue
);
2663 #endif /* #ifndef SIMULATOR */
2664 create_thread(mpeg_thread
, mpeg_stack
,
2665 sizeof(mpeg_stack
), mpeg_thread_name
);
2667 memset(id3tags
, sizeof(id3tags
), 0);
2669 #if CONFIG_HWCODEC == MAS3587F
2670 if(read_hw_mask() & PR_ACTIVE_HIGH
)
2671 and_b(~0x08, &PADRH
);
2674 #endif /* #if CONFIG_HWCODEC == MAS3587F */