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;
366 static int mpeg_file
;
368 /* Synchronization variables */
369 #if CONFIG_HWCODEC == MAS3587F
370 static bool init_recording_done
;
371 static bool init_playback_done
;
372 #endif /* #if CONFIG_HWCODEC == MAS3587F */
373 static bool mpeg_stop_done
;
375 static void recalculate_watermark(int bitrate
)
378 int time
= ata_spinup_time
;
380 /* A bitrate of 0 probably means empty VBR header. We play safe
381 and set a high threshold */
385 bytes_per_sec
= bitrate
* 1000 / 8;
389 /* No drive spins up faster than 3.5s */
394 low_watermark
= ((low_watermark_margin
* HZ
+ time
) *
399 low_watermark
= MPEG_LOW_WATER
;
403 void mpeg_set_buffer_margin(int seconds
)
405 low_watermark_margin
= seconds
;
408 void mpeg_get_debugdata(struct mpeg_debug
*dbgdata
)
410 dbgdata
->mp3buflen
= mp3buflen
;
411 dbgdata
->mp3buf_write
= mp3buf_write
;
412 dbgdata
->mp3buf_swapwrite
= mp3buf_swapwrite
;
413 dbgdata
->mp3buf_read
= mp3buf_read
;
415 dbgdata
->last_dma_chunk_size
= last_dma_chunk_size
;
417 dbgdata
->dma_on
= (SCR0
& 0x80) != 0;
418 dbgdata
->playing
= playing
;
419 dbgdata
->play_pending
= play_pending
;
420 dbgdata
->is_playing
= is_playing
;
421 dbgdata
->filling
= filling
;
422 dbgdata
->dma_underrun
= dma_underrun
;
424 dbgdata
->unplayed_space
= get_unplayed_space();
425 dbgdata
->playable_space
= get_playable_space();
426 dbgdata
->unswapped_space
= get_unswapped_space();
428 dbgdata
->low_watermark_level
= low_watermark
;
429 dbgdata
->lowest_watermark_level
= lowest_watermark_level
;
433 static void dbg_timer_start(void)
435 /* We are using timer 2 */
437 TSTR
&= ~0x04; /* Stop the timer */
438 TSNC
&= ~0x04; /* No synchronization */
439 TMDR
&= ~0x44; /* Operate normally */
441 TCNT2
= 0; /* Start counting at 0 */
442 TCR2
= 0x03; /* Sysclock/8 */
444 TSTR
|= 0x04; /* Start timer 2 */
447 static int dbg_cnt2us(unsigned int cnt
)
449 return (cnt
* 10000) / (FREQ
/800);
451 #endif /* #ifdef DEBUG */
453 static int get_unplayed_space(void)
455 int space
= mp3buf_write
- mp3buf_read
;
461 static int get_playable_space(void)
463 int space
= mp3buf_swapwrite
- mp3buf_read
;
469 static int get_unplayed_space_current_song(void)
473 if (num_tracks_in_memory() > 1)
475 int track_offset
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
477 space
= id3tags
[track_offset
].mempos
- mp3buf_read
;
481 space
= mp3buf_write
- mp3buf_read
;
490 static int get_unswapped_space(void)
492 int space
= mp3buf_write
- mp3buf_swapwrite
;
498 #if CONFIG_HWCODEC == MAS3587F
499 static int get_unsaved_space(void)
501 int space
= mp3buf_write
- mp3buf_read
;
506 #endif /* #if CONFIG_HWCODEC == MAS3587F */
508 #if CONFIG_HWCODEC == MAS3587F
510 static long timing_info_index
= 0;
511 static long timing_info
[1024];
512 #endif /* #ifdef DEBUG */
513 static unsigned long num_rec_bytes
;
514 static unsigned long num_recorded_frames
;
516 static void drain_dma_buffer(void)
519 "mov #0x40,r2 \n" /* mask for EOD check */
521 "mov.b @%0,r1 \n" /* read PBDR (first time) */
524 "xor.b #0x08,@(r0,gbr) \n" /* set PR active */
526 "mov.b @%0,r1 \n" /* read PBDR */
527 "cmp/pz r1 \n" /* and wait for PRTW */
530 "xor.b #0x08,@(r0,gbr) \n" /* reset PR to inactive */
532 "mov.b @%0,r1 \n" /* read PBDR */
533 "cmp/pz r1 \n" /* and wait for /PRTW */
537 "tst r1,r2 \n" /* EOD low? */
538 "bf .d_loop \n" /* no: next pass */
542 /* %0 */ "r"(PBDR_ADDR
),
543 /* %1 = r0 */ "z"(&PADRH
)
549 #endif /* #if CONFIG_HWCODEC == MAS3587F */
551 void rec_tick (void) __attribute__ ((section (".icode")));
554 #if CONFIG_HWCODEC == MAS3587F
557 if(is_recording
&& (PBDR
& 0x4000))
560 timing_info
[timing_info_index
++] = current_tick
;
562 #endif /* #ifdef DEBUG */
563 /* We read as long as EOD is high, but max 30 bytes. */
565 "mov #30,r3 \n" /* i_max = 30 */
566 "mov #0x40,r2 \n" /* mask for EOD check */
567 "mov #0,%0 \n" /* i = 0; */
568 "add %2,%1 \n" /* mp3buf_write -> cur_addr */
569 "add %2,%3 \n" /* mp3buflen -> end_addr */
571 "mov.b @%4,r1 \n" /* read PBDR (first time) */
576 "xor.b #0x08,@(r0,gbr) \n" /* set PR active */
578 "mov.b @%4,r1 \n" /* read PBDR */
579 "cmp/pz r1 \n" /* and wait for PRTW */
582 "mov.b @%6,r1 \n" /* read byte from mas */
583 "add #1,%0 \n" /* i++; */
584 "mov.b r1,@%1 \n" /* store byte */
585 "add #1,%1 \n" /* increment current address */
587 "cmp/hi %1,%3 \n" /* end address reached? */
588 "bt .r_nowrap \n" /* no: do nothing */
589 "mov %2,%1 \n" /* yes: reset to start address */
592 "xor.b #0x08,@(r0,gbr) \n" /* set PR inactive again */
594 "mov.b @%4,r1 \n" /* read PBDR */
595 "cmp/pz r1 \n" /* and wait for /PRTW */
599 "tst r2,r1 \n" /* EOD low? */
600 "bt .r_end \n" /* yes: end of transfer */
601 "cmp/hi %0,r3 \n" /* i < i_max? */
602 "bt .r_loop \n" /* yes: next pass */
605 "sub %2,%1 \n" /* cur_addr -> mp3buf_write */
608 /* %1, in & out */ "+r"(mp3buf_write
)
610 /* %2 */ "r"(mp3buf
),
611 /* %3 */ "r"(mp3buflen
),
612 /* %4 */ "r"(PBDR_ADDR
),
613 /* %5 = r0 */ "z"(&PADRH
),
614 /* %6 */ "r"(0x4000000)
619 timing_info
[timing_info_index
++] = TCNT2
+ (i
<< 16);
620 timing_info_index
&= 0x3ff;
621 #endif /* #ifdef DEBUG */
627 if(TIME_AFTER(current_tick
, prerecord_timeout
))
629 prerecord_timeout
= current_tick
+ HZ
;
631 /* Store the write pointer every second */
632 prerecord_buffer
[prerecord_index
++] = mp3buf_write
;
634 /* Wrap if necessary */
635 if(prerecord_index
== prerecording_max_seconds
)
638 /* Update the number of seconds recorded */
639 if(prerecord_count
< prerecording_max_seconds
)
645 /* Signal to save the data if we are running out of buffer
647 num_bytes
= mp3buf_write
- mp3buf_read
;
649 num_bytes
+= mp3buflen
;
651 if(mp3buflen
- num_bytes
< MPEG_RECORDING_LOW_WATER
&& !saving
)
654 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
659 #endif /* #if CONFIG_HWCODEC == MAS3587F */
662 void playback_tick(void)
664 id3tags
[tag_read_idx
].id3
.elapsed
+=
665 (current_tick
- last_dma_tick
) * 1000 / HZ
;
666 last_dma_tick
= current_tick
;
669 static void reset_mp3_buffer(void)
673 mp3buf_swapwrite
= 0;
674 lowest_watermark_level
= mp3buflen
;
677 /* DMA transfer end interrupt callback */
678 static void transfer_end(unsigned char** ppbuf
, int* psize
)
680 if(playing
&& !paused
)
682 int unplayed_space_left
;
683 int space_until_end_of_buffer
;
684 int track_offset
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
686 mp3buf_read
+= last_dma_chunk_size
;
687 if(mp3buf_read
>= mp3buflen
)
690 /* First, check if we are on a track boundary */
691 if (num_tracks_in_memory() > 1)
693 if (mp3buf_read
== id3tags
[track_offset
].mempos
)
695 queue_post(&mpeg_queue
, MPEG_TRACK_CHANGE
, 0);
696 track_offset
= (track_offset
+1) & MAX_ID3_TAGS_MASK
;
700 unplayed_space_left
= get_unplayed_space();
702 space_until_end_of_buffer
= mp3buflen
- mp3buf_read
;
704 if(!filling
&& unplayed_space_left
< low_watermark
)
707 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
710 if(unplayed_space_left
)
712 last_dma_chunk_size
= MIN(0x2000, unplayed_space_left
);
713 last_dma_chunk_size
= MIN(last_dma_chunk_size
,
714 space_until_end_of_buffer
);
716 /* several tracks loaded? */
717 if (num_tracks_in_memory() > 1)
719 /* will we move across the track boundary? */
720 if (( mp3buf_read
< id3tags
[track_offset
].mempos
) &&
721 ((mp3buf_read
+last_dma_chunk_size
) >
722 id3tags
[track_offset
].mempos
))
724 /* Make sure that we end exactly on the boundary */
725 last_dma_chunk_size
= id3tags
[track_offset
].mempos
730 *psize
= last_dma_chunk_size
& 0xffff;
731 *ppbuf
= mp3buf
+ mp3buf_read
;
732 id3tags
[tag_read_idx
].id3
.offset
+= last_dma_chunk_size
;
734 /* Update the watermark debug level */
735 if(unplayed_space_left
< lowest_watermark_level
)
736 lowest_watermark_level
= unplayed_space_left
;
740 /* Check if the end of data is because of a hard disk error.
741 If there is an open file handle, we are still playing music.
742 If not, the last file has been loaded, and the file handle is
746 /* Update the watermark debug level */
747 if(unplayed_space_left
< lowest_watermark_level
)
748 lowest_watermark_level
= unplayed_space_left
;
750 DEBUGF("DMA underrun.\n");
755 DEBUGF("No more MP3 data. Stopping.\n");
757 queue_post(&mpeg_queue
, MPEG_TRACK_CHANGE
, 0);
761 *psize
= 0; /* no more transfer */
768 static int add_track_to_tag_list(const char *filename
)
770 if(num_tracks_in_memory() >= MAX_ID3_TAGS
)
772 DEBUGF("Tag memory is full\n");
776 /* grab id3 tag of new file and
777 remember where in memory it starts */
778 if(mp3info(&id3tags
[tag_write_idx
].id3
, filename
, v1first
))
783 id3tags
[tag_write_idx
].mempos
= mp3buf_write
;
784 id3tags
[tag_write_idx
].id3
.elapsed
= 0;
786 tag_write_idx
= (tag_write_idx
+1) & MAX_ID3_TAGS_MASK
;
791 static int new_file(int steps
)
793 int max_steps
= playlist_amount();
797 /* Find out how many steps to advance. The load_ahead_index field tells
798 us how many playlist entries it had to skip to get to a valid one.
799 We add those together to find out where to start. */
800 if(steps
> 0 && num_tracks_in_memory() > 1)
802 /* Begin with the song after the currently playing one */
803 i
= (tag_read_idx
+ 1) & MAX_ID3_TAGS_MASK
;
804 while(i
!= tag_write_idx
)
806 start
+= id3tags
[i
].load_ahead_index
;
807 i
= (i
+1) & MAX_ID3_TAGS_MASK
;
814 trackname
= playlist_peek( start
+ steps
);
818 DEBUGF("Loading %s\n", trackname
);
820 mpeg_file
= open(trackname
, O_RDONLY
);
822 DEBUGF("Couldn't open file: %s\n",trackname
);
830 int new_tag_idx
= tag_write_idx
;
832 if(add_track_to_tag_list(trackname
))
844 /* skip past id3v2 tag */
846 id3tags
[new_tag_idx
].id3
.first_frame_offset
,
848 id3tags
[new_tag_idx
].id3
.index
= steps
;
849 id3tags
[new_tag_idx
].load_ahead_index
= steps
;
850 id3tags
[new_tag_idx
].id3
.offset
= 0;
852 if(id3tags
[new_tag_idx
].id3
.vbr
)
853 /* Average bitrate * 1.5 */
854 recalculate_watermark(
855 (id3tags
[new_tag_idx
].id3
.bitrate
* 3) / 2);
857 recalculate_watermark(
858 id3tags
[new_tag_idx
].id3
.bitrate
);
863 /* Bail out if no file could be opened */
864 if(abs(steps
) > max_steps
)
866 } while ( mpeg_file
< 0 );
871 static void stop_playing(void)
873 /* Stop the current stream */
884 static void update_playlist(void)
888 if (num_tracks_in_memory() > 0)
890 index
= playlist_next(id3tags
[tag_read_idx
].id3
.index
);
891 id3tags
[tag_read_idx
].id3
.index
= index
;
895 static void track_change(void)
897 DEBUGF("Track change\n");
899 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
901 mpeg_sound_set(SOUND_AVC
, -1);
902 #endif /* #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */
903 remove_current_tag();
906 current_track_counter
++;
910 void hexdump(const unsigned char *buf
, int len
)
914 for(i
= 0;i
< len
;i
++)
916 if(i
&& (i
& 15) == 0)
920 DEBUGF("%02x ", buf
[i
]);
924 #endif /* #ifdef DEBUG */
926 static void start_playback_if_ready(void)
930 playable_space
= mp3buf_swapwrite
- mp3buf_read
;
931 if(playable_space
< 0)
932 playable_space
+= mp3buflen
;
934 /* See if we have started playing yet. If not, do it. */
935 if(play_pending
|| dma_underrun
)
937 /* If the filling has stopped, and we still haven't reached
938 the watermark, the file must be smaller than the
939 watermark. We must still play it. */
940 if((playable_space
>= MPEG_PLAY_PENDING_THRESHOLD
) ||
941 !filling
|| dma_underrun
)
944 play_pending
= false;
947 last_dma_chunk_size
= MIN(0x2000, get_unplayed_space_current_song());
948 mp3_play_data(mp3buf
+ mp3buf_read
, last_dma_chunk_size
, transfer_end
);
949 dma_underrun
= false;
953 last_dma_tick
= current_tick
;
954 mp3_play_pause(true);
957 /* Tell ourselves that we need more data */
958 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
963 static bool swap_one_chunk(void)
968 free_space_left
= get_unswapped_space();
970 if(free_space_left
== 0 && !play_pending
)
973 /* Swap in larger chunks when the user is waiting for the playback
974 to start, or when there is dangerously little playable data left */
976 amount_to_swap
= MIN(MPEG_PLAY_PENDING_SWAPSIZE
, free_space_left
);
979 if(get_playable_space() < low_watermark
)
980 amount_to_swap
= MIN(MPEG_LOW_WATER_SWAP_CHUNKSIZE
,
983 amount_to_swap
= MIN(MPEG_SWAP_CHUNKSIZE
, free_space_left
);
986 if(mp3buf_write
< mp3buf_swapwrite
)
987 amount_to_swap
= MIN(mp3buflen
- mp3buf_swapwrite
,
990 amount_to_swap
= MIN(mp3buf_write
- mp3buf_swapwrite
,
993 bitswap(mp3buf
+ mp3buf_swapwrite
, amount_to_swap
);
995 mp3buf_swapwrite
+= amount_to_swap
;
996 if(mp3buf_swapwrite
>= mp3buflen
)
998 mp3buf_swapwrite
= 0;
1004 static const unsigned char empty_id3_header
[] =
1006 'I', 'D', '3', 0x03, 0x00, 0x00,
1007 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
1010 static void mpeg_thread(void)
1012 static int pause_tick
= 0;
1013 static unsigned int pause_track
= 0;
1016 int free_space_left
;
1017 int unplayed_space_left
;
1021 #if CONFIG_HWCODEC == MAS3587F
1025 unsigned long saved_header
= 0;
1030 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1033 play_pending
= false;
1039 #if CONFIG_HWCODEC == MAS3587F
1040 if(mpeg_mode
== MPEG_DECODER
)
1042 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1045 /* Swap if necessary, and don't block on the queue_wait() */
1046 if(swap_one_chunk())
1048 queue_wait_w_tmo(&mpeg_queue
, &ev
, 0);
1052 DEBUGF("S R:%x W:%x SW:%x\n",
1053 mp3buf_read
, mp3buf_write
, mp3buf_swapwrite
);
1054 queue_wait(&mpeg_queue
, &ev
);
1057 start_playback_if_ready();
1062 DEBUGF("MPEG_PLAY\n");
1065 /* Silence the A/D input, it may be on because the radio
1067 mas_codec_writereg(6, 0x0000);
1068 #endif /* #ifdef CONFIG_TUNER */
1070 /* Stop the current stream */
1071 play_pending
= false;
1074 mp3_play_pause(false);
1082 if ( new_file(0) == -1 )
1089 start_offset
= (int)ev
.data
;
1091 /* mid-song resume? */
1093 struct mp3entry
* id3
= &id3tags
[tag_read_idx
].id3
;
1094 lseek(mpeg_file
, start_offset
, SEEK_SET
);
1095 id3
->offset
= start_offset
;
1099 /* skip past id3v2 tag */
1101 id3tags
[tag_read_idx
].id3
.first_frame_offset
,
1106 /* Make it read more data */
1108 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1110 /* Tell the file loading code that we want to start playing
1111 as soon as we have some data */
1112 play_pending
= true;
1115 current_track_counter
++;
1119 DEBUGF("MPEG_STOP\n");
1123 mpeg_stop_done
= true;
1127 DEBUGF("MPEG_PAUSE\n");
1128 /* Stop the current stream */
1131 pause_tick
= current_tick
;
1132 pause_track
= current_track_counter
;
1133 mp3_play_pause(false);
1137 DEBUGF("MPEG_RESUME\n");
1138 /* Continue the current stream */
1143 if ( current_track_counter
== pause_track
)
1144 last_dma_tick
+= current_tick
- pause_tick
;
1146 last_dma_tick
= current_tick
;
1148 mp3_play_pause(true);
1153 DEBUGF("MPEG_NEXT\n");
1154 /* is next track in ram? */
1155 if ( num_tracks_in_memory() > 1 ) {
1156 int unplayed_space_left
, unswapped_space_left
;
1158 /* stop the current stream */
1159 play_pending
= false;
1161 mp3_play_pause(false);
1164 mp3buf_read
= id3tags
[tag_read_idx
].mempos
;
1165 last_dma_chunk_size
= MIN(0x2000, get_unplayed_space_current_song());
1166 mp3_play_data(mp3buf
+ mp3buf_read
, last_dma_chunk_size
, transfer_end
);
1167 dma_underrun
= false;
1168 last_dma_tick
= current_tick
;
1170 unplayed_space_left
= get_unplayed_space();
1171 unswapped_space_left
= get_unswapped_space();
1173 /* should we start reading more data? */
1174 if(!filling
&& (unplayed_space_left
< low_watermark
)) {
1176 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1177 play_pending
= true;
1178 } else if(unswapped_space_left
&&
1179 unswapped_space_left
> unplayed_space_left
) {
1180 /* Stop swapping the data from the previous file */
1181 mp3buf_swapwrite
= mp3buf_read
;
1182 play_pending
= true;
1186 mp3_play_pause(true);
1190 if (!playlist_check(1))
1193 /* stop the current stream */
1194 play_pending
= false;
1196 mp3_play_pause(false);
1201 /* Open the next file */
1205 if (new_file(1) < 0) {
1206 DEBUGF("No more files to play\n");
1209 /* Make it read more data */
1211 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1213 /* Tell the file loading code that we want
1214 to start playing as soon as we have some data */
1215 play_pending
= true;
1218 current_track_counter
++;
1224 DEBUGF("MPEG_PREV\n");
1226 if (!playlist_check(-1))
1229 /* stop the current stream */
1230 play_pending
= false;
1232 mp3_play_pause(false);
1237 /* Open the next file */
1241 if (new_file(-1) < 0) {
1242 DEBUGF("No more files to play\n");
1245 /* Make it read more data */
1247 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1249 /* Tell the file loading code that we want to
1250 start playing as soon as we have some data */
1251 play_pending
= true;
1254 current_track_counter
++;
1259 case MPEG_FF_REWIND
: {
1260 struct mp3entry
*id3
= mpeg_current_track();
1261 unsigned int oldtime
= id3
->elapsed
;
1262 unsigned int newtime
= (unsigned int)ev
.data
;
1263 int curpos
, newpos
, diffpos
;
1264 DEBUGF("MPEG_FF_REWIND\n");
1266 id3
->elapsed
= newtime
;
1268 newpos
= mpeg_get_file_pos();
1271 id3
->elapsed
= oldtime
;
1276 curpos
= lseek(mpeg_file
, 0, SEEK_CUR
);
1278 curpos
= id3
->filesize
;
1280 if (num_tracks_in_memory() > 1)
1282 /* We have started loading other tracks that need to be
1284 int i
= tag_read_idx
;
1285 int j
= tag_write_idx
- 1;
1288 j
= MAX_ID3_TAGS
- 1;
1292 curpos
+= id3tags
[i
].id3
.filesize
;
1293 i
= (i
+1) & MAX_ID3_TAGS_MASK
;
1297 diffpos
= curpos
- newpos
;
1299 if(!filling
&& diffpos
>= 0 && diffpos
< mp3buflen
)
1301 int unplayed_space_left
, unswapped_space_left
;
1303 /* We are changing to a position that's already in
1304 memory, so we just move the DMA read pointer. */
1305 mp3buf_read
= mp3buf_write
- diffpos
;
1306 if (mp3buf_read
< 0)
1308 mp3buf_read
+= mp3buflen
;
1311 unplayed_space_left
= get_unplayed_space();
1312 unswapped_space_left
= get_unswapped_space();
1314 /* If unswapped_space_left is larger than
1315 unplayed_space_left, it means that the swapwrite pointer
1316 hasn't yet advanced up to the new location of the read
1317 pointer. We just move it, there is no need to swap
1318 data that won't be played anyway. */
1320 if (unswapped_space_left
> unplayed_space_left
)
1322 DEBUGF("Moved swapwrite\n");
1323 mp3buf_swapwrite
= mp3buf_read
;
1324 play_pending
= true;
1327 if (mpeg_file
>=0 && unplayed_space_left
< low_watermark
)
1329 /* We need to load more data before starting */
1331 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1332 play_pending
= true;
1336 /* resume will start at new position */
1337 last_dma_chunk_size
=
1338 MIN(0x2000, get_unplayed_space_current_song());
1339 mp3_play_data(mp3buf
+ mp3buf_read
,
1340 last_dma_chunk_size
, transfer_end
);
1341 dma_underrun
= false;
1346 /* Move to the new position in the file and start
1350 if (num_tracks_in_memory() > 1)
1352 /* We have to reload the current track */
1354 remove_all_non_current_tags();
1360 mpeg_file
= open(id3
->path
, O_RDONLY
);
1363 id3
->elapsed
= oldtime
;
1368 if(-1 == lseek(mpeg_file
, newpos
, SEEK_SET
))
1370 id3
->elapsed
= oldtime
;
1375 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1377 /* Tell the file loading code that we want to start playing
1378 as soon as we have some data */
1379 play_pending
= true;
1382 id3
->offset
= newpos
;
1387 case MPEG_FLUSH_RELOAD
: {
1388 int numtracks
= num_tracks_in_memory();
1389 bool reload_track
= false;
1394 int next
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
1396 /* Reset the buffer */
1397 mp3buf_write
= id3tags
[next
].mempos
;
1399 /* Reset swapwrite unless we're still swapping current
1401 if (get_unplayed_space() <= get_playable_space())
1402 mp3buf_swapwrite
= mp3buf_write
;
1405 remove_all_non_current_tags();
1407 reload_track
= true;
1409 else if (numtracks
== 1 && mpeg_file
< 0)
1411 reload_track
= true;
1414 if(reload_track
&& new_file(1) >= 0)
1416 /* Tell ourselves that we want more data */
1417 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1424 case MPEG_NEED_DATA
:
1425 free_space_left
= mp3buf_read
- mp3buf_write
;
1427 /* We interpret 0 as "empty buffer" */
1428 if(free_space_left
<= 0)
1429 free_space_left
= mp3buflen
+ free_space_left
;
1431 unplayed_space_left
= mp3buflen
- free_space_left
;
1433 /* Make sure that we don't fill the entire buffer */
1434 free_space_left
-= MPEG_HIGH_WATER
;
1436 /* do we have any more buffer space to fill? */
1437 if(free_space_left
<= MPEG_HIGH_WATER
)
1445 /* Read small chunks while we are below the low water mark */
1446 if(unplayed_space_left
< low_watermark
)
1447 amount_to_read
= MIN(MPEG_LOW_WATER_CHUNKSIZE
,
1450 amount_to_read
= free_space_left
;
1452 /* Don't read more than until the end of the buffer */
1453 amount_to_read
= MIN(mp3buflen
- mp3buf_write
, amount_to_read
);
1455 amount_to_read
= MIN(0x100000, amount_to_read
);
1456 #endif /* #if MEM == 8 */
1457 #ifdef HAVE_MMC /* MMC is slow, so don't read too large chunks */
1458 amount_to_read
= MIN(0x40000, amount_to_read
);
1461 /* Read as much mpeg data as we can fit in the buffer */
1466 len
= read(mpeg_file
, mp3buf
+mp3buf_write
, amount_to_read
);
1470 DEBUGF("time: %d\n", t2
- t1
);
1471 DEBUGF("R: %x\n", len
);
1473 /* Now make sure that we don't feed the MAS with ID3V1
1475 if (len
< amount_to_read
)
1477 int tagptr
= mp3buf_write
+ len
- 128;
1482 for(i
= 0;i
< 3;i
++)
1484 if(tagptr
>= mp3buflen
)
1485 tagptr
-= mp3buflen
;
1487 if(mp3buf
[tagptr
] != tag
[i
])
1495 /* Skip id3v1 tag */
1496 DEBUGF("Skipping ID3v1 tag\n");
1499 /* The very rare case when the entire tag
1500 wasn't read in this read() call must be
1507 mp3buf_write
+= len
;
1509 if(mp3buf_write
>= mp3buflen
)
1515 /* Tell ourselves that we want more data */
1516 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1522 DEBUGF("MPEG read error\n");
1530 /* No more data to play */
1531 DEBUGF("No more files to play\n");
1536 /* Tell ourselves that we want more data */
1537 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1543 case MPEG_TRACK_CHANGE
:
1548 case SYS_USB_CONNECTED
:
1554 /* Tell the USB thread that we are safe */
1555 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
1556 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1558 /* Wait until the USB cable is extracted again */
1559 usb_wait_for_disconnect(&mpeg_queue
);
1560 #endif /* #ifndef SIMULATOR */
1562 #endif /* #ifndef USB_NONE */
1564 #if CONFIG_HWCODEC == MAS3587F
1565 case MPEG_INIT_RECORDING
:
1567 init_recording_done
= true;
1569 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1571 #if CONFIG_HWCODEC == MAS3587F
1575 queue_wait(&mpeg_queue
, &ev
);
1583 /* Go back prerecord_count seconds in the buffer */
1584 startpos
= prerecord_index
- prerecord_count
;
1586 startpos
+= prerecording_max_seconds
;
1588 /* Read the mp3 buffer pointer from the prerecord buffer */
1589 startpos
= prerecord_buffer
[startpos
];
1591 DEBUGF("Start looking at address %x (%x)\n",
1592 mp3buf
+startpos
, startpos
);
1594 saved_header
= mpeg_get_last_header();
1596 mem_find_next_frame(startpos
, &offset
, 5000,
1599 mp3buf_read
= startpos
+ offset
;
1601 DEBUGF("New mp3buf_read address: %x (%x)\n",
1602 mp3buf
+mp3buf_read
, mp3buf_read
);
1604 /* Make room for headers */
1605 mp3buf_read
-= MPEG_RESERVED_HEADER_SPACE
;
1608 /* Clear the bottom half */
1610 mp3buf_read
+ MPEG_RESERVED_HEADER_SPACE
);
1612 /* And the top half */
1613 mp3buf_read
+= mp3buflen
;
1614 memset(mp3buf
+ mp3buf_read
, 0,
1615 mp3buflen
- mp3buf_read
);
1619 memset(mp3buf
+ mp3buf_read
, 0,
1620 MPEG_RESERVED_HEADER_SPACE
);
1623 /* Copy the empty ID3 header */
1624 startpos
= mp3buf_read
;
1625 for(i
= 0;i
< (int)sizeof(empty_id3_header
);i
++)
1627 mp3buf
[startpos
++] = empty_id3_header
[i
];
1628 if(startpos
== mp3buflen
)
1632 DEBUGF("New mp3buf_read address (reservation): %x\n",
1633 mp3buf
+mp3buf_read
);
1635 DEBUGF("Prerecording...\n");
1643 /* Advance the write pointer to make
1644 room for an ID3 tag plus a VBR header */
1645 mp3buf_write
= MPEG_RESERVED_HEADER_SPACE
;
1646 memset(mp3buf
, 0, MPEG_RESERVED_HEADER_SPACE
);
1648 /* Insert the ID3 header */
1649 memcpy(mp3buf
, empty_id3_header
,
1650 sizeof(empty_id3_header
));
1652 DEBUGF("Recording...\n");
1657 /* Wait until at least one frame is encoded and get the
1658 frame header, for later use by the Xing header
1661 saved_header
= mpeg_get_last_header();
1663 /* delayed until buffer is saved, don't open yet */
1664 strcpy(delayed_filename
, recording_filename
);
1670 DEBUGF("MPEG_STOP\n");
1674 /* Save the remaining data in the buffer */
1675 stop_pending
= true;
1676 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1679 case MPEG_STOP_DONE
:
1680 DEBUGF("MPEG_STOP_DONE\n");
1685 if(!disable_xing_header
&& num_rec_bytes
> 0)
1687 /* Create the Xing header */
1688 mpeg_file
= open(recording_filename
, O_RDWR
);
1690 panicf("rec upd: %d (%s)", mpeg_file
,
1691 recording_filename
);
1693 /* If the number of recorded frames have
1694 reached 0x7ffff, we can no longer trust it */
1695 if(num_recorded_frames
== 0x7ffff)
1696 num_recorded_frames
= 0;
1698 /* Also, if we have been prerecording, the frame count
1701 num_recorded_frames
= 0;
1703 /* saved_header is saved right before stopping
1705 framelen
= create_xing_header(mpeg_file
, 0,
1706 num_rec_bytes
, mp3buf
,
1707 num_recorded_frames
,
1711 lseek(mpeg_file
, MPEG_RESERVED_HEADER_SPACE
-framelen
,
1713 write(mpeg_file
, mp3buf
, framelen
);
1721 for(i
= 0;i
< 512;i
++)
1723 DEBUGF("%d - %d us (%d bytes)\n",
1725 (timing_info
[i
*2+1] & 0xffff) *
1727 timing_info
[i
*2+1] >> 16);
1730 #endif /* #ifdef DEBUG1 */
1734 start_prerecording();
1736 mpeg_stop_done
= true;
1740 /* Make sure we have at least one complete frame
1741 in the buffer. If we haven't recorded a single
1742 frame within 200ms, the MAS is probably not recording
1743 anything, and we bail out. */
1745 amount_to_save
= get_unsaved_space();
1746 while(countdown
-- && amount_to_save
< 1800)
1749 amount_to_save
= get_unsaved_space();
1752 if(amount_to_save
>= 1800)
1754 /* Now find a frame boundary to split at */
1755 startpos
= mp3buf_write
- 1800;
1757 startpos
+= mp3buflen
;
1759 rc
= mem_find_next_frame(startpos
, &offset
, 1800,
1761 if(rc
) /* Header found? */
1763 /* offset will now contain the number of bytes to
1764 add to startpos to find the frame boundary */
1766 if(startpos
>= mp3buflen
)
1767 startpos
-= mp3buflen
;
1771 /* No header found. Let's save the whole buffer. */
1772 startpos
= mp3buf_write
;
1777 /* Too few bytes recorded, timeout */
1778 startpos
= mp3buf_write
;
1781 amount_to_save
= startpos
- mp3buf_read
;
1782 if(amount_to_save
< 0)
1783 amount_to_save
+= mp3buflen
;
1785 /* First save up to the end of the buffer */
1786 writelen
= MIN(amount_to_save
,
1787 mp3buflen
- mp3buf_read
);
1789 if (mpeg_file
< 0) /* delayed file opening */
1791 mpeg_file
= open(delayed_filename
, O_WRONLY
|O_CREAT
);
1794 panicf("recfile: %d", mpeg_file
);
1799 rc
= write(mpeg_file
, mp3buf
+ mp3buf_read
, writelen
);
1804 mpeg_errno
= MPEGERR_DISK_FULL
;
1805 demand_irq_enable(false);
1807 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1812 panicf("spt wrt: %d", rc
);
1817 /* Then save the rest */
1818 writelen
= amount_to_save
- writelen
;
1821 rc
= write(mpeg_file
, mp3buf
, writelen
);
1826 mpeg_errno
= MPEGERR_DISK_FULL
;
1827 demand_irq_enable(false);
1829 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1834 panicf("spt wrt: %d", rc
);
1839 /* Advance the buffer pointers */
1840 mp3buf_read
+= amount_to_save
;
1841 if(mp3buf_read
>= mp3buflen
)
1842 mp3buf_read
-= mp3buflen
;
1844 /* Close the current file */
1845 rc
= close(mpeg_file
);
1847 panicf("spt cls: %d", rc
);
1849 /* Open the new file */
1850 mpeg_file
= open(recording_filename
, O_WRONLY
|O_CREAT
);
1852 panicf("sptfile: %d", mpeg_file
);
1855 case MPEG_SAVE_DATA
:
1856 amount_to_save
= get_unsaved_space();
1858 /* If the result is negative, the write index has
1860 if(amount_to_save
< 0)
1862 amount_to_save
+= mp3buflen
;
1865 DEBUGF("r: %x w: %x\n", mp3buf_read
, mp3buf_write
);
1866 DEBUGF("ats: %x\n", amount_to_save
);
1868 /* Save data only if the buffer is getting full,
1869 or if we should stop recording */
1873 amount_to_save
< MPEG_RECORDING_LOW_WATER
||
1876 /* Only save up to the end of the buffer */
1877 writelen
= MIN(amount_to_save
,
1878 mp3buflen
- mp3buf_read
);
1880 DEBUGF("wrl: %x\n", writelen
);
1882 if (mpeg_file
< 0) /* delayed file opening */
1884 mpeg_file
= open(delayed_filename
,
1888 panicf("recfile: %d", mpeg_file
);
1891 rc
= write(mpeg_file
, mp3buf
+ mp3buf_read
,
1898 mpeg_errno
= MPEGERR_DISK_FULL
;
1900 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1905 panicf("rec wrt: %d", rc
);
1909 mp3buf_read
+= amount_to_save
;
1910 if(mp3buf_read
>= mp3buflen
)
1913 rc
= fsync(mpeg_file
);
1915 panicf("rec fls: %d", rc
);
1917 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1927 /* We have saved all data,
1928 time to stop for real */
1930 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1936 case MPEG_INIT_PLAYBACK
:
1937 /* Stop the prerecording */
1940 init_playback_done
= true;
1943 case MPEG_PAUSE_RECORDING
:
1947 case MPEG_RESUME_RECORDING
:
1951 case SYS_USB_CONNECTED
:
1952 /* We can safely go to USB mode if no recording
1954 if((!is_recording
|| is_prerecording
) && mpeg_stop_done
)
1956 /* Even if we aren't recording, we still call this
1957 function, to put the MAS in monitoring mode,
1961 /* Tell the USB thread that we are safe */
1962 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
1963 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1965 /* Wait until the USB cable is extracted again */
1966 usb_wait_for_disconnect(&mpeg_queue
);
1971 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1974 #endif /* SIMULATOR */
1977 static struct mp3entry taginfo
;
1978 #endif /* #ifdef SIMULATOR */
1980 void mpeg_id3_options(bool _v1first
)
1985 struct mp3entry
* mpeg_current_track()
1990 if(num_tracks_in_memory())
1991 return &id3tags
[tag_read_idx
].id3
;
1994 #endif /* #ifdef SIMULATOR */
1997 struct mp3entry
* mpeg_next_track()
2002 if(num_tracks_in_memory() > 1)
2003 return &(id3tags
[(tag_read_idx
+1) & MAX_ID3_TAGS_MASK
].id3
);
2006 #endif /* #ifdef SIMULATOR */
2009 bool mpeg_has_changed_track(void)
2011 if(last_track_counter
!= current_track_counter
)
2013 last_track_counter
= current_track_counter
;
2019 #if CONFIG_HWCODEC == MAS3587F
2020 void mpeg_init_playback(void)
2022 init_playback_done
= false;
2023 queue_post(&mpeg_queue
, MPEG_INIT_PLAYBACK
, NULL
);
2025 while(!init_playback_done
)
2031 /****************************************************************************
2034 ** Recording functions
2037 ***************************************************************************/
2038 void mpeg_init_recording(void)
2040 init_recording_done
= false;
2041 queue_post(&mpeg_queue
, MPEG_INIT_RECORDING
, NULL
);
2043 while(!init_recording_done
)
2048 static void init_recording(void)
2060 /* Init the recording variables */
2061 is_recording
= false;
2062 is_prerecording
= false;
2064 mpeg_stop_done
= true;
2068 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2069 rc
= mas_direct_config_write(MAS_CONTROL
, 0x8c00);
2071 panicf("mas_ctrl_w: %d", rc
);
2073 /* Stop the current application */
2075 mas_writemem(MAS_BANK_D0
, MAS_D0_APP_SELECT
, &val
, 1);
2078 mas_readmem(MAS_BANK_D0
, MAS_D0_APP_RUNNING
, &val
, 1);
2081 /* Perform black magic as described by the data sheet */
2082 if((mas_version_code
& 0x0fff) == 0x0102)
2084 DEBUGF("Performing MAS black magic for B2 version\n");
2085 mas_writereg(0xa3, 0x98);
2086 mas_writereg(0x94, 0xfffff);
2088 mas_writemem(MAS_BANK_D1
, 0, &val
, 1);
2089 mas_writereg(0xa3, 0x90);
2092 /* Enable A/D Converters */
2093 mas_codec_writereg(0x0, 0xcccd);
2095 /* Copy left channel to right (mono mode) */
2096 mas_codec_writereg(8, 0x8000);
2098 /* ADC scale 0%, DSP scale 100%
2099 We use the DSP output for monitoring, because it works with all
2100 sources including S/PDIF */
2101 mas_codec_writereg(6, 0x0000);
2102 mas_codec_writereg(7, 0x4000);
2105 shadow_soft_mute
= 0;
2106 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2108 /* Set Demand mode, monitoring OFF and validate all settings */
2109 shadow_io_control_main
= 0x125;
2110 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2112 /* Start the encoder application */
2114 mas_writemem(MAS_BANK_D0
, MAS_D0_APP_SELECT
, &val
, 1);
2117 mas_readmem(MAS_BANK_D0
, MAS_D0_APP_RUNNING
, &val
, 1);
2118 } while(!(val
& 0x40));
2121 /* We have started the recording application with monitoring OFF.
2122 This is because we want to record at least one frame to fill the DMA
2123 buffer, because the silly MAS will not negate EOD until at least one
2124 DMA transfer has taken place.
2125 Now let's wait for some data to be encoded. */
2128 /* Now set it to Monitoring mode as default, saves power */
2129 shadow_io_control_main
= 0x525;
2130 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2132 /* Wait until the DSP has accepted the settings */
2135 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2140 mpeg_mode
= MPEG_ENCODER
;
2142 DEBUGF("MAS Recording application started\n");
2144 /* At this point, all settings are the reset MAS defaults, next thing is to
2145 call mpeg_set_recording_options(). */
2148 void mpeg_record(const char *filename
)
2152 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
2153 recording_filename
[MAX_PATH
- 1] = 0;
2155 disable_xing_header
= false;
2156 queue_post(&mpeg_queue
, MPEG_RECORD
, NULL
);
2159 void mpeg_pause_recording(void)
2161 queue_post(&mpeg_queue
, MPEG_PAUSE_RECORDING
, NULL
);
2164 void mpeg_resume_recording(void)
2166 queue_post(&mpeg_queue
, MPEG_RESUME_RECORDING
, NULL
);
2169 static void start_prerecording(void)
2173 DEBUGF("Starting prerecording\n");
2175 prerecord_index
= 0;
2176 prerecord_count
= 0;
2177 prerecord_timeout
= current_tick
+ HZ
;
2178 memset(prerecord_buffer
, 0, sizeof(prerecord_buffer
));
2181 is_prerecording
= true;
2183 /* Stop monitoring and start the encoder */
2184 shadow_io_control_main
&= ~(1 << 10);
2185 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2186 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2188 /* Wait until the DSP has accepted the settings */
2191 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2194 is_recording
= true;
2195 stop_pending
= false;
2198 demand_irq_enable(true);
2201 static void start_recording(void)
2205 num_recorded_frames
= 0;
2209 /* This will make the IRQ handler start recording
2210 for real, i.e send MPEG_SAVE_DATA messages when
2211 the buffer is full */
2212 is_prerecording
= false;
2216 /* If prerecording is off, we need to stop the monitoring
2217 and start the encoder */
2218 shadow_io_control_main
&= ~(1 << 10);
2219 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2220 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2222 /* Wait until the DSP has accepted the settings */
2225 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2229 is_recording
= true;
2230 stop_pending
= false;
2234 /* Store the current time */
2236 record_start_time
= current_tick
- prerecord_count
* HZ
;
2238 record_start_time
= current_tick
;
2240 pause_start_time
= 0;
2242 demand_irq_enable(true);
2245 static void pause_recording(void)
2247 pause_start_time
= current_tick
;
2249 /* Set the pause bit */
2250 shadow_soft_mute
|= 2;
2251 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2256 static void resume_recording(void)
2260 /* Clear the pause bit */
2261 shadow_soft_mute
&= ~2;
2262 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2264 /* Compensate for the time we have been paused */
2265 if(pause_start_time
)
2268 current_tick
- (pause_start_time
- record_start_time
);
2269 pause_start_time
= 0;
2273 static void stop_recording(void)
2277 /* Let it finish the last frame */
2282 demand_irq_enable(false);
2284 is_recording
= false;
2285 is_prerecording
= false;
2287 /* Read the number of frames recorded */
2288 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_FRAME_COUNT
, &num_recorded_frames
, 1);
2290 /* Start monitoring */
2291 shadow_io_control_main
|= (1 << 10);
2292 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2293 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2295 /* Wait until the DSP has accepted the settings */
2298 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2304 void mpeg_set_recording_options(int frequency
, int quality
,
2305 int source
, int channel_mode
,
2306 bool editable
, int prerecord_time
)
2310 is_mpeg1
= (frequency
< 3)?true:false;
2312 rec_version_index
= is_mpeg1
?3:2;
2313 rec_frequency_index
= frequency
% 3;
2315 shadow_encoder_control
= (quality
<< 17) |
2316 (rec_frequency_index
<< 10) |
2317 ((is_mpeg1
?1:0) << 9) |
2318 (((channel_mode
* 2 + 1) & 3) << 6) |
2319 (1 << 5) /* MS-stereo */ |
2320 (1 << 2) /* Is an original */;
2321 mas_writemem(MAS_BANK_D0
, MAS_D0_ENCODER_CONTROL
, &shadow_encoder_control
,1);
2323 DEBUGF("mas_writemem(MAS_BANK_D0, ENCODER_CONTROL, %x)\n", shadow_encoder_control
);
2325 shadow_soft_mute
= editable
?4:0;
2326 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
,1);
2328 DEBUGF("mas_writemem(MAS_BANK_D0, SOFT_MUTE, %x)\n", shadow_soft_mute
);
2330 shadow_io_control_main
= ((1 << 10) | /* Monitoring ON */
2331 ((source
< 2)?1:2) << 8) | /* Input select */
2332 (1 << 5) | /* SDO strobe invert */
2333 ((is_mpeg1
?0:1) << 3) |
2334 (1 << 2) | /* Inverted SIBC clock signal */
2336 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
,1);
2338 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2340 if(source
== 0) /* Mic */
2342 /* Copy left channel to right (mono mode) */
2343 mas_codec_writereg(8, 0x8000);
2347 /* Stereo input mode */
2348 mas_codec_writereg(8, 0);
2351 prerecording_max_seconds
= prerecord_time
;
2352 if(prerecording_max_seconds
)
2354 prerecording
= true;
2355 start_prerecording();
2359 prerecording
= false;
2360 is_prerecording
= false;
2361 is_recording
= false;
2365 /* If use_mic is true, the left gain is used */
2366 void mpeg_set_recording_gain(int left
, int right
, bool use_mic
)
2368 /* Enable both left and right A/D */
2369 mas_codec_writereg(0x0,
2373 (use_mic
?0x0008:0) | /* Connect left A/D to mic */
2377 void mpeg_new_file(const char *filename
)
2381 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
2382 recording_filename
[MAX_PATH
- 1] = 0;
2385 disable_xing_header
= true;
2387 /* Store the current time */
2388 record_start_time
= current_tick
;
2390 pause_start_time
= record_start_time
;
2392 queue_post(&mpeg_queue
, MPEG_NEW_FILE
, NULL
);
2395 unsigned long mpeg_recorded_time(void)
2398 return prerecord_count
* HZ
;
2403 return pause_start_time
- record_start_time
;
2405 return current_tick
- record_start_time
;
2411 unsigned long mpeg_num_recorded_bytes(void)
2420 index
= prerecord_index
- prerecord_count
;
2422 index
+= prerecording_max_seconds
;
2424 num_bytes
= mp3buf_write
- prerecord_buffer
[index
];
2426 num_bytes
+= mp3buflen
;
2431 return num_rec_bytes
;
2439 void mpeg_play(int offset
)
2448 trackname
= playlist_peek( steps
);
2451 if(mp3info(&taginfo
, trackname
, v1first
)) {
2452 /* bad mp3, move on */
2453 if(++steps
> playlist_amount())
2457 #ifdef HAVE_MPEG_PLAY
2458 real_mpeg_play(trackname
);
2460 playlist_next(steps
);
2461 taginfo
.offset
= offset
;
2462 set_elapsed(&taginfo
);
2470 queue_post(&mpeg_queue
, MPEG_PLAY
, (void*)offset
);
2471 #endif /* #ifdef SIMULATOR */
2476 void mpeg_stop(void)
2479 mpeg_stop_done
= false;
2480 queue_post(&mpeg_queue
, MPEG_STOP
, NULL
);
2481 while(!mpeg_stop_done
)
2487 #endif /* #ifndef SIMULATOR */
2491 void mpeg_pause(void)
2494 queue_post(&mpeg_queue
, MPEG_PAUSE
, NULL
);
2499 #endif /* #ifndef SIMULATOR */
2502 void mpeg_resume(void)
2505 queue_post(&mpeg_queue
, MPEG_RESUME
, NULL
);
2510 #endif /* #ifndef SIMULATOR */
2513 void mpeg_next(void)
2516 queue_post(&mpeg_queue
, MPEG_NEXT
, NULL
);
2523 file
= playlist_peek(steps
);
2526 if(mp3info(&taginfo
, file
, v1first
)) {
2527 if(++steps
> playlist_amount())
2531 index
= playlist_next(steps
);
2532 taginfo
.index
= index
;
2533 current_track_counter
++;
2538 #endif /* #ifndef SIMULATOR */
2541 void mpeg_prev(void)
2544 queue_post(&mpeg_queue
, MPEG_PREV
, NULL
);
2551 file
= playlist_peek(steps
);
2554 if(mp3info(&taginfo
, file
, v1first
)) {
2558 index
= playlist_next(steps
);
2559 taginfo
.index
= index
;
2560 current_track_counter
++;
2565 #endif /* #ifndef SIMULATOR */
2568 void mpeg_ff_rewind(int newtime
)
2571 queue_post(&mpeg_queue
, MPEG_FF_REWIND
, (void *)newtime
);
2574 #endif /* #ifndef SIMULATOR */
2577 void mpeg_flush_and_reload_tracks(void)
2580 queue_post(&mpeg_queue
, MPEG_FLUSH_RELOAD
, NULL
);
2581 #endif /* #ifndef SIMULATOR*/
2584 int mpeg_status(void)
2589 ret
|= MPEG_STATUS_PLAY
;
2592 ret
|= MPEG_STATUS_PAUSE
;
2594 #if CONFIG_HWCODEC == MAS3587F
2595 if(is_recording
&& !is_prerecording
)
2596 ret
|= MPEG_STATUS_RECORD
;
2599 ret
|= MPEG_STATUS_PRERECORD
;
2600 #endif /* #if CONFIG_HWCODEC == MAS3587F */
2603 ret
|= MPEG_STATUS_ERROR
;
2608 unsigned int mpeg_error(void)
2613 void mpeg_error_clear(void)
2619 static char mpeg_stack
[DEFAULT_STACK_SIZE
];
2620 static const char mpeg_thread_name
[] = "mpeg";
2621 static void mpeg_thread(void)
2623 struct mp3entry
* id3
;
2626 id3
= mpeg_current_track();
2632 if (id3
->elapsed
>=id3
->length
)
2638 #endif /* #ifdef SIMULATOR */
2640 void mpeg_init(void)
2645 mp3buflen
= mp3end
- mp3buf
;
2646 queue_init(&mpeg_queue
);
2647 #endif /* #ifndef SIMULATOR */
2648 create_thread(mpeg_thread
, mpeg_stack
,
2649 sizeof(mpeg_stack
), mpeg_thread_name
);
2651 memset(id3tags
, sizeof(id3tags
), 0);
2653 #if CONFIG_HWCODEC == MAS3587F
2654 if(read_hw_mask() & PR_ACTIVE_HIGH
)
2655 and_b(~0x08, &PADRH
);
2658 #endif /* #if CONFIG_HWCODEC == MAS3587F */