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 ****************************************************************************/
32 #include "mp3_playback.h"
43 #endif /* #ifndef SIMULATOR */
47 #if CONFIG_HWCODEC == MAS3587F
48 static void init_recording(void);
49 static void start_prerecording(void);
50 static void start_recording(void);
51 static void stop_recording(void);
52 static int get_unsaved_space(void);
53 static void pause_recording(void);
54 static void resume_recording(void);
55 #endif /* #if CONFIG_HWCODEC == MAS3587F */
58 static int get_unplayed_space(void);
59 static int get_playable_space(void);
60 static int get_unswapped_space(void);
61 #endif /* #ifndef SIMULATOR */
69 #define MPEG_FF_REWIND 7
70 #define MPEG_FLUSH_RELOAD 8
72 #define MPEG_INIT_RECORDING 10
73 #define MPEG_INIT_PLAYBACK 11
74 #define MPEG_NEW_FILE 12
75 #define MPEG_PAUSE_RECORDING 13
76 #define MPEG_RESUME_RECORDING 14
77 #define MPEG_NEED_DATA 100
78 #define MPEG_TRACK_CHANGE 101
79 #define MPEG_SAVE_DATA 102
80 #define MPEG_STOP_DONE 103
82 #if CONFIG_HWCODEC == MAS3587F
83 extern enum /* from mp3_playback.c */
88 #endif /* #if CONFIG_HWCODEC == MAS3587F */
90 extern char* playlist_peek(int steps
);
91 extern bool playlist_check(int steps
);
92 extern int playlist_next(int steps
);
93 extern int playlist_amount(void);
94 extern void update_file_pos( int id
, int pos
);
96 /* list of tracks in memory */
97 #define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
98 #define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
107 static struct id3tag
*id3tags
[MAX_ID3_TAGS
];
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("id3tags[%d]: %08x", i
, id3tags
[i
]);
136 DEBUGF(" - %s", id3tags
[i
]->id3
.path
);
139 DEBUGF("read: %d, write :%d\n", tag_read_idx
, tag_write_idx
);
140 DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory());
141 #endif /* #ifdef DEBUG_TAGS */
144 static bool append_tag(struct id3tag
*tag
)
146 if(num_tracks_in_memory() < MAX_ID3_TAGS
- 1)
148 id3tags
[tag_write_idx
] = tag
;
149 tag_write_idx
= (tag_write_idx
+1) & MAX_ID3_TAGS_MASK
;
155 DEBUGF("Tag memory is full\n");
160 static void remove_current_tag(void)
162 int oldidx
= tag_read_idx
;
164 if(num_tracks_in_memory() > 0)
166 /* First move the index, so nobody tries to access the tag */
167 tag_read_idx
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
170 id3tags
[oldidx
]->used
= false;
171 id3tags
[oldidx
] = NULL
;
176 static void remove_all_non_current_tags(void)
178 int i
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
180 while (i
!= tag_write_idx
)
182 id3tags
[i
]->used
= false;
185 i
= (i
+1) & MAX_ID3_TAGS_MASK
;
188 tag_write_idx
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
192 static void remove_all_tags(void)
196 for(i
= 0;i
< MAX_ID3_TAGS
;i
++)
197 remove_current_tag();
199 tag_write_idx
= tag_read_idx
;
203 #endif /* #ifndef SIMULATOR */
205 static void set_elapsed(struct mp3entry
* id3
)
208 if ( id3
->has_toc
) {
209 /* calculate elapsed time using TOC */
211 unsigned int remainder
, plen
, relpos
, nextpos
;
213 /* find wich percent we're at */
214 for (i
=0; i
<100; i
++ )
216 if ( id3
->offset
< (int)(id3
->toc
[i
] * (id3
->filesize
/ 256)) )
226 relpos
= id3
->toc
[i
];
230 nextpos
= id3
->toc
[i
+1];
237 remainder
= id3
->offset
- (relpos
* (id3
->filesize
/ 256));
239 /* set time for this percent (divide before multiply to prevent
240 overflow on long files. loss of precision is negligible on
242 id3
->elapsed
= i
* (id3
->length
/ 100);
244 /* calculate remainder time */
245 plen
= (nextpos
- relpos
) * (id3
->filesize
/ 256);
246 id3
->elapsed
+= (((remainder
* 100) / plen
) *
247 (id3
->length
/ 10000));
250 /* no TOC exists. set a rough estimate using average bitrate */
251 int tpk
= id3
->length
/ (id3
->filesize
/ 1024);
252 id3
->elapsed
= id3
->offset
/ 1024 * tpk
;
256 /* constant bitrate == simple frame calculation */
257 id3
->elapsed
= id3
->offset
/ id3
->bpf
* id3
->tpf
;
260 int mpeg_get_file_pos(void)
263 struct mp3entry
*id3
= mpeg_current_track();
269 /* Use the TOC to find the new position */
270 unsigned int percent
, remainder
;
271 int curtoc
, nexttoc
, plen
;
273 percent
= (id3
->elapsed
*100)/id3
->length
;
277 curtoc
= id3
->toc
[percent
];
280 nexttoc
= id3
->toc
[percent
+1];
284 pos
= (id3
->filesize
/256)*curtoc
;
286 /* Use the remainder to get a more accurate position */
287 remainder
= (id3
->elapsed
*100)%id3
->length
;
288 remainder
= (remainder
*100)/id3
->length
;
289 plen
= (nexttoc
- curtoc
)*(id3
->filesize
/256);
290 pos
+= (plen
/100)*remainder
;
294 /* No TOC exists, estimate the new position */
295 pos
= (id3
->filesize
/ (id3
->length
/ 1000)) *
296 (id3
->elapsed
/ 1000);
299 else if (id3
->bpf
&& id3
->tpf
)
300 pos
= (id3
->elapsed
/id3
->tpf
)*id3
->bpf
;
306 if (pos
>= (int)(id3
->filesize
- id3
->id3v1len
))
308 /* Don't seek right to the end of the file so that we can
309 transition properly to the next song */
310 pos
= id3
->filesize
- id3
->id3v1len
- 1;
312 else if (pos
< (int)id3
->first_frame_offset
)
314 /* skip past id3v2 tag and other leading garbage */
315 pos
= id3
->first_frame_offset
;
320 unsigned long mpeg_get_last_header(void)
325 unsigned long tmp
[2];
327 /* Read the frame data from the MAS and reconstruct it with the
328 frame sync and all */
329 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_STATUS_1
, tmp
, 2);
330 return 0xffe00000 | ((tmp
[0] & 0x7c00) << 6) | (tmp
[1] & 0xffff);
334 static bool paused
; /* playback is paused */
336 static unsigned int mpeg_errno
;
339 static bool is_playing
= false;
340 static bool playing
= false;
342 static int last_dma_tick
= 0;
344 extern unsigned long mas_version_code
;
346 static struct event_queue mpeg_queue
;
347 static char mpeg_stack
[DEFAULT_STACK_SIZE
+ 0x1000];
348 static const char mpeg_thread_name
[] = "mpeg";
350 static int mp3buflen
;
351 static int mp3buf_write
;
352 static int mp3buf_swapwrite
;
353 static int mp3buf_read
;
355 static int last_dma_chunk_size
;
357 static bool playing
; /* We are playing an MP3 stream */
358 static bool play_pending
; /* We are about to start playing */
359 static bool is_playing
; /* We are (attempting to) playing MP3 files */
360 static bool filling
; /* We are filling the buffer with data from disk */
361 static bool dma_underrun
; /* True when the DMA has stopped because of
362 slow disk reading (read error, shaking) */
363 static int low_watermark
; /* Dynamic low watermark level */
364 static int low_watermark_margin
; /* Extra time in seconds for watermark */
365 static int lowest_watermark_level
; /* Debug value to observe the buffer
367 #if CONFIG_HWCODEC == MAS3587F
368 static bool is_recording
; /* We are recording */
369 static bool stop_pending
;
370 unsigned long record_start_time
; /* Value of current_tick when recording
372 unsigned long pause_start_time
; /* Value of current_tick when pause was
374 static bool saving
; /* We are saving the buffer to disk */
375 static char recording_filename
[MAX_PATH
]; /* argument to thread */
376 static char delayed_filename
[MAX_PATH
]; /* internal copy of above */
377 static int rec_frequency_index
; /* For create_xing_header() calls */
378 static int rec_version_index
; /* For create_xing_header() calls */
379 static bool disable_xing_header
; /* When splitting files */
381 static bool prerecording
; /* True if prerecording is enabled */
382 static bool is_prerecording
; /* True if we are prerecording */
383 static int prerecord_buffer
[MPEG_MAX_PRERECORD_SECONDS
]; /* Array of buffer
387 static int prerecord_index
; /* Current index in the prerecord buffer */
388 static int prerecording_max_seconds
; /* Max number of seconds to store */
389 static int prerecord_count
; /* Number of seconds in the prerecord buffer */
390 static int prerecord_timeout
; /* The tick count of the next prerecord data store */
392 /* Shadow MAS registers */
393 unsigned long shadow_encoder_control
= 0;
394 #endif /* #if CONFIG_HWCODEC == MAS3587F */
396 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
397 unsigned long shadow_io_control_main
= 0;
398 unsigned long shadow_app_select
= 0;
399 unsigned long shadow_soft_mute
= 0;
402 static int mpeg_file
;
404 /* Synchronization variables */
405 #if CONFIG_HWCODEC == MAS3587F
406 static bool init_recording_done
;
407 static bool init_playback_done
;
408 #endif /* #if CONFIG_HWCODEC == MAS3587F */
409 static bool mpeg_stop_done
;
411 static void recalculate_watermark(int bitrate
)
414 int time
= ata_spinup_time
;
416 /* A bitrate of 0 probably means empty VBR header. We play safe
417 and set a high threshold */
421 bytes_per_sec
= bitrate
* 1000 / 8;
425 /* No drive spins up faster than 3.5s */
430 low_watermark
= ((low_watermark_margin
* HZ
+ time
) *
435 low_watermark
= MPEG_LOW_WATER
;
439 void mpeg_set_buffer_margin(int seconds
)
441 low_watermark_margin
= seconds
;
444 void mpeg_get_debugdata(struct mpeg_debug
*dbgdata
)
446 dbgdata
->mp3buflen
= mp3buflen
;
447 dbgdata
->mp3buf_write
= mp3buf_write
;
448 dbgdata
->mp3buf_swapwrite
= mp3buf_swapwrite
;
449 dbgdata
->mp3buf_read
= mp3buf_read
;
451 dbgdata
->last_dma_chunk_size
= last_dma_chunk_size
;
453 dbgdata
->dma_on
= (SCR0
& 0x80) != 0;
454 dbgdata
->playing
= playing
;
455 dbgdata
->play_pending
= play_pending
;
456 dbgdata
->is_playing
= is_playing
;
457 dbgdata
->filling
= filling
;
458 dbgdata
->dma_underrun
= dma_underrun
;
460 dbgdata
->unplayed_space
= get_unplayed_space();
461 dbgdata
->playable_space
= get_playable_space();
462 dbgdata
->unswapped_space
= get_unswapped_space();
464 dbgdata
->low_watermark_level
= low_watermark
;
465 dbgdata
->lowest_watermark_level
= lowest_watermark_level
;
469 static void dbg_timer_start(void)
471 /* We are using timer 2 */
473 TSTR
&= ~0x04; /* Stop the timer */
474 TSNC
&= ~0x04; /* No synchronization */
475 TMDR
&= ~0x44; /* Operate normally */
477 TCNT2
= 0; /* Start counting at 0 */
478 TCR2
= 0x03; /* Sysclock/8 */
480 TSTR
|= 0x04; /* Start timer 2 */
483 static int dbg_cnt2us(unsigned int cnt
)
485 return (cnt
* 10000) / (FREQ
/800);
487 #endif /* #ifdef DEBUG */
489 static int get_unplayed_space(void)
491 int space
= mp3buf_write
- mp3buf_read
;
497 static int get_playable_space(void)
499 int space
= mp3buf_swapwrite
- mp3buf_read
;
505 static int get_unplayed_space_current_song(void)
509 if (num_tracks_in_memory() > 1)
511 int track_offset
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
513 space
= id3tags
[track_offset
]->mempos
- mp3buf_read
;
517 space
= mp3buf_write
- mp3buf_read
;
526 static int get_unswapped_space(void)
528 int space
= mp3buf_write
- mp3buf_swapwrite
;
534 #if CONFIG_HWCODEC == MAS3587F
535 static int get_unsaved_space(void)
537 int space
= mp3buf_write
- mp3buf_read
;
542 #endif /* #if CONFIG_HWCODEC == MAS3587F */
544 #if CONFIG_HWCODEC == MAS3587F
546 static long timing_info_index
= 0;
547 static long timing_info
[1024];
548 #endif /* #ifdef DEBUG */
549 static unsigned long num_rec_bytes
;
550 static unsigned long num_recorded_frames
;
552 static void drain_dma_buffer(void)
555 "mov #0x40,r2 \n" /* mask for EOD check */
557 "mov.b @%0,r1 \n" /* read PBDR (first time) */
560 "xor.b #0x08,@(r0,gbr) \n" /* set PR active */
562 "mov.b @%0,r1 \n" /* read PBDR */
563 "cmp/pz r1 \n" /* and wait for PRTW */
566 "xor.b #0x08,@(r0,gbr) \n" /* reset PR to inactive */
568 "mov.b @%0,r1 \n" /* read PBDR */
569 "cmp/pz r1 \n" /* and wait for /PRTW */
573 "tst r1,r2 \n" /* EOD low? */
574 "bf .d_loop \n" /* no: next pass */
578 /* %0 */ "r"(PBDR_ADDR
),
579 /* %1 = r0 */ "z"(&PADRH
)
585 #endif /* #if CONFIG_HWCODEC == MAS3587F */
587 void rec_tick (void) __attribute__ ((section (".icode")));
590 #if CONFIG_HWCODEC == MAS3587F
593 if(is_recording
&& (PBDR
& 0x4000))
596 timing_info
[timing_info_index
++] = current_tick
;
598 #endif /* #ifdef DEBUG */
599 /* We read as long as EOD is high, but max 30 bytes. */
601 "mov #30,r3 \n" /* i_max = 30 */
602 "mov #0x40,r2 \n" /* mask for EOD check */
603 "mov #0,%0 \n" /* i = 0; */
604 "add %2,%1 \n" /* mp3buf_write -> cur_addr */
605 "add %2,%3 \n" /* mp3buflen -> end_addr */
607 "mov.b @%4,r1 \n" /* read PBDR (first time) */
612 "xor.b #0x08,@(r0,gbr) \n" /* set PR active */
614 "mov.b @%4,r1 \n" /* read PBDR */
615 "cmp/pz r1 \n" /* and wait for PRTW */
618 "mov.b @%6,r1 \n" /* read byte from mas */
619 "add #1,%0 \n" /* i++; */
620 "mov.b r1,@%1 \n" /* store byte */
621 "add #1,%1 \n" /* increment current address */
623 "cmp/hi %1,%3 \n" /* end address reached? */
624 "bt .r_nowrap \n" /* no: do nothing */
625 "mov %2,%1 \n" /* yes: reset to start address */
628 "xor.b #0x08,@(r0,gbr) \n" /* set PR inactive again */
630 "mov.b @%4,r1 \n" /* read PBDR */
631 "cmp/pz r1 \n" /* and wait for /PRTW */
635 "tst r2,r1 \n" /* EOD low? */
636 "bt .r_end \n" /* yes: end of transfer */
637 "cmp/hi %0,r3 \n" /* i < i_max? */
638 "bt .r_loop \n" /* yes: next pass */
641 "sub %2,%1 \n" /* cur_addr -> mp3buf_write */
644 /* %1, in & out */ "+r"(mp3buf_write
)
646 /* %2 */ "r"(mp3buf
),
647 /* %3 */ "r"(mp3buflen
),
648 /* %4 */ "r"(PBDR_ADDR
),
649 /* %5 = r0 */ "z"(&PADRH
),
650 /* %6 */ "r"(0x4000000)
655 timing_info
[timing_info_index
++] = TCNT2
+ (i
<< 16);
656 timing_info_index
&= 0x3ff;
657 #endif /* #ifdef DEBUG */
663 if(TIME_AFTER(current_tick
, prerecord_timeout
))
665 prerecord_timeout
= current_tick
+ HZ
;
667 /* Store the write pointer every second */
668 prerecord_buffer
[prerecord_index
++] = mp3buf_write
;
670 /* Wrap if necessary */
671 if(prerecord_index
== prerecording_max_seconds
)
674 /* Update the number of seconds recorded */
675 if(prerecord_count
< prerecording_max_seconds
)
681 /* Signal to save the data if we are running out of buffer
683 num_bytes
= mp3buf_write
- mp3buf_read
;
685 num_bytes
+= mp3buflen
;
687 if(mp3buflen
- num_bytes
< MPEG_RECORDING_LOW_WATER
&& !saving
)
690 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
695 #endif /* #if CONFIG_HWCODEC == MAS3587F */
698 void playback_tick(void)
700 id3tags
[tag_read_idx
]->id3
.elapsed
+=
701 (current_tick
- last_dma_tick
) * 1000 / HZ
;
702 last_dma_tick
= current_tick
;
705 static void reset_mp3_buffer(void)
709 mp3buf_swapwrite
= 0;
710 lowest_watermark_level
= mp3buflen
;
713 /* DMA transfer end interrupt callback */
714 static void transfer_end(unsigned char** ppbuf
, int* psize
)
716 if(playing
&& !paused
)
718 int unplayed_space_left
;
719 int space_until_end_of_buffer
;
720 int track_offset
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
722 mp3buf_read
+= last_dma_chunk_size
;
723 if(mp3buf_read
>= mp3buflen
)
726 /* First, check if we are on a track boundary */
727 if (num_tracks_in_memory() > 0)
729 if (mp3buf_read
== id3tags
[track_offset
]->mempos
)
731 queue_post(&mpeg_queue
, MPEG_TRACK_CHANGE
, 0);
732 track_offset
= (track_offset
+1) & MAX_ID3_TAGS_MASK
;
736 unplayed_space_left
= get_unplayed_space();
738 space_until_end_of_buffer
= mp3buflen
- mp3buf_read
;
740 if(!filling
&& unplayed_space_left
< low_watermark
)
743 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
746 if(unplayed_space_left
)
748 last_dma_chunk_size
= MIN(0x2000, unplayed_space_left
);
749 last_dma_chunk_size
= MIN(last_dma_chunk_size
,
750 space_until_end_of_buffer
);
752 /* several tracks loaded? */
753 if (num_tracks_in_memory() > 1)
755 /* will we move across the track boundary? */
756 if (( mp3buf_read
< id3tags
[track_offset
]->mempos
) &&
757 ((mp3buf_read
+last_dma_chunk_size
) >
758 id3tags
[track_offset
]->mempos
))
760 /* Make sure that we end exactly on the boundary */
761 last_dma_chunk_size
= id3tags
[track_offset
]->mempos
766 *psize
= last_dma_chunk_size
& 0xffff;
767 *ppbuf
= mp3buf
+ mp3buf_read
;
768 id3tags
[tag_read_idx
]->id3
.offset
+= last_dma_chunk_size
;
770 /* Update the watermark debug level */
771 if(unplayed_space_left
< lowest_watermark_level
)
772 lowest_watermark_level
= unplayed_space_left
;
776 /* Check if the end of data is because of a hard disk error.
777 If there is an open file handle, we are still playing music.
778 If not, the last file has been loaded, and the file handle is
782 /* Update the watermark debug level */
783 if(unplayed_space_left
< lowest_watermark_level
)
784 lowest_watermark_level
= unplayed_space_left
;
786 DEBUGF("DMA underrun.\n");
791 DEBUGF("No more MP3 data. Stopping.\n");
793 queue_post(&mpeg_queue
, MPEG_TRACK_CHANGE
, 0);
797 *psize
= 0; /* no more transfer */
804 static int add_track_to_tag_list(const char *filename
)
806 struct id3tag
*t
= NULL
;
809 /* find a free tag */
810 for (i
=0; i
< MAX_ID3_TAGS_MASK
; i
++ )
811 if ( !_id3tags
[i
].used
)
815 /* grab id3 tag of new file and
816 remember where in memory it starts */
817 if(mp3info(&(t
->id3
), filename
, v1first
))
822 t
->mempos
= mp3buf_write
;
826 DEBUGF("Tag list is full\n");
833 DEBUGF("No memory available for id3 tag");
838 /* If next_track is true, opens the next track, if false, opens prev track */
839 static int new_file(int steps
)
841 int max_steps
= playlist_amount();
842 int start
= num_tracks_in_memory() - 1;
850 trackname
= playlist_peek( start
+ steps
);
854 DEBUGF("playing %s\n", trackname
);
856 mpeg_file
= open(trackname
, O_RDONLY
);
858 DEBUGF("Couldn't open file: %s\n",trackname
);
861 /* Bail out if no file could be opened */
862 if(steps
> max_steps
)
867 int new_tag_idx
= tag_write_idx
;
869 if(add_track_to_tag_list(trackname
))
878 /* skip past id3v2 tag */
880 id3tags
[new_tag_idx
]->id3
.first_frame_offset
,
882 id3tags
[new_tag_idx
]->id3
.index
= steps
;
883 id3tags
[new_tag_idx
]->id3
.offset
= 0;
885 if(id3tags
[new_tag_idx
]->id3
.vbr
)
886 /* Average bitrate * 1.5 */
887 recalculate_watermark(
888 (id3tags
[new_tag_idx
]->id3
.bitrate
* 3) / 2);
890 recalculate_watermark(
891 id3tags
[new_tag_idx
]->id3
.bitrate
);
895 } while ( mpeg_file
< 0 );
900 static void stop_playing(void)
902 /* Stop the current stream */
913 static void update_playlist(void)
917 if (num_tracks_in_memory() > 0)
919 index
= playlist_next(id3tags
[tag_read_idx
]->id3
.index
);
920 id3tags
[tag_read_idx
]->id3
.index
= index
;
924 static void track_change(void)
926 DEBUGF("Track change\n");
928 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
930 mpeg_sound_set(SOUND_AVC
, -1);
931 #endif /* #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */
932 remove_current_tag();
935 current_track_counter
++;
939 void hexdump(const unsigned char *buf
, int len
)
943 for(i
= 0;i
< len
;i
++)
945 if(i
&& (i
& 15) == 0)
949 DEBUGF("%02x ", buf
[i
]);
953 #endif /* #ifdef DEBUG */
955 static void start_playback_if_ready(void)
959 playable_space
= mp3buf_swapwrite
- mp3buf_read
;
960 if(playable_space
< 0)
961 playable_space
+= mp3buflen
;
963 /* See if we have started playing yet. If not, do it. */
964 if(play_pending
|| dma_underrun
)
966 /* If the filling has stopped, and we still haven't reached
967 the watermark, the file must be smaller than the
968 watermark. We must still play it. */
969 if((playable_space
>= MPEG_PLAY_PENDING_THRESHOLD
) ||
970 !filling
|| dma_underrun
)
973 play_pending
= false;
976 last_dma_chunk_size
= MIN(0x2000, get_unplayed_space_current_song());
977 mp3_play_data(mp3buf
+ mp3buf_read
, last_dma_chunk_size
, transfer_end
);
978 dma_underrun
= false;
982 last_dma_tick
= current_tick
;
983 mp3_play_pause(true);
986 /* Tell ourselves that we need more data */
987 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
992 static bool swap_one_chunk(void)
997 free_space_left
= get_unswapped_space();
999 if(free_space_left
== 0 && !play_pending
)
1002 /* Swap in larger chunks when the user is waiting for the playback
1003 to start, or when there is dangerously little playable data left */
1005 amount_to_swap
= MIN(MPEG_PLAY_PENDING_SWAPSIZE
, free_space_left
);
1008 if(get_playable_space() < low_watermark
)
1009 amount_to_swap
= MIN(MPEG_LOW_WATER_SWAP_CHUNKSIZE
,
1012 amount_to_swap
= MIN(MPEG_SWAP_CHUNKSIZE
, free_space_left
);
1015 if(mp3buf_write
< mp3buf_swapwrite
)
1016 amount_to_swap
= MIN(mp3buflen
- mp3buf_swapwrite
,
1019 amount_to_swap
= MIN(mp3buf_write
- mp3buf_swapwrite
,
1022 bitswap(mp3buf
+ mp3buf_swapwrite
, amount_to_swap
);
1024 mp3buf_swapwrite
+= amount_to_swap
;
1025 if(mp3buf_swapwrite
>= mp3buflen
)
1027 mp3buf_swapwrite
= 0;
1033 static const unsigned char empty_id3_header
[] =
1035 'I', 'D', '3', 0x03, 0x00, 0x00,
1036 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
1039 static void mpeg_thread(void)
1041 static int pause_tick
= 0;
1042 static unsigned int pause_track
= 0;
1045 int free_space_left
;
1046 int unplayed_space_left
;
1050 #if CONFIG_HWCODEC == MAS3587F
1054 unsigned long saved_header
= 0;
1059 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1062 play_pending
= false;
1068 #if CONFIG_HWCODEC == MAS3587F
1069 if(mpeg_mode
== MPEG_DECODER
)
1071 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1074 /* Swap if necessary, and don't block on the queue_wait() */
1075 if(swap_one_chunk())
1077 queue_wait_w_tmo(&mpeg_queue
, &ev
, 0);
1081 DEBUGF("S R:%x W:%x SW:%x\n",
1082 mp3buf_read
, mp3buf_write
, mp3buf_swapwrite
);
1083 queue_wait(&mpeg_queue
, &ev
);
1086 start_playback_if_ready();
1091 DEBUGF("MPEG_PLAY\n");
1094 /* Silence the A/D input, it may be on because the radio
1096 mas_codec_writereg(6, 0x0000);
1097 #endif /* #ifdef CONFIG_TUNER */
1099 /* Stop the current stream */
1100 play_pending
= false;
1103 mp3_play_pause(false);
1111 if ( new_file(0) == -1 )
1118 start_offset
= (int)ev
.data
;
1120 /* mid-song resume? */
1122 struct mp3entry
* id3
= &id3tags
[tag_read_idx
]->id3
;
1123 lseek(mpeg_file
, start_offset
, SEEK_SET
);
1124 id3
->offset
= start_offset
;
1128 /* skip past id3v2 tag */
1130 id3tags
[tag_read_idx
]->id3
.first_frame_offset
,
1135 /* Make it read more data */
1137 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1139 /* Tell the file loading code that we want to start playing
1140 as soon as we have some data */
1141 play_pending
= true;
1144 current_track_counter
++;
1148 DEBUGF("MPEG_STOP\n");
1152 mpeg_stop_done
= true;
1156 DEBUGF("MPEG_PAUSE\n");
1157 /* Stop the current stream */
1160 pause_tick
= current_tick
;
1161 pause_track
= current_track_counter
;
1162 mp3_play_pause(false);
1166 DEBUGF("MPEG_RESUME\n");
1167 /* Continue the current stream */
1172 if ( current_track_counter
== pause_track
)
1173 last_dma_tick
+= current_tick
- pause_tick
;
1175 last_dma_tick
= current_tick
;
1177 mp3_play_pause(true);
1182 DEBUGF("MPEG_NEXT\n");
1183 /* is next track in ram? */
1184 if ( num_tracks_in_memory() > 1 ) {
1185 int unplayed_space_left
, unswapped_space_left
;
1187 /* stop the current stream */
1188 play_pending
= false;
1190 mp3_play_pause(false);
1193 mp3buf_read
= id3tags
[tag_read_idx
]->mempos
;
1194 last_dma_chunk_size
= MIN(0x2000, get_unplayed_space_current_song());
1195 mp3_play_data(mp3buf
+ mp3buf_read
, last_dma_chunk_size
, transfer_end
);
1196 dma_underrun
= false;
1197 last_dma_tick
= current_tick
;
1199 unplayed_space_left
= get_unplayed_space();
1200 unswapped_space_left
= get_unswapped_space();
1202 /* should we start reading more data? */
1203 if(!filling
&& (unplayed_space_left
< low_watermark
)) {
1205 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1206 play_pending
= true;
1207 } else if(unswapped_space_left
&&
1208 unswapped_space_left
> unplayed_space_left
) {
1209 /* Stop swapping the data from the previous file */
1210 mp3buf_swapwrite
= mp3buf_read
;
1211 play_pending
= true;
1215 mp3_play_pause(true);
1219 if (!playlist_check(1))
1222 /* stop the current stream */
1223 play_pending
= false;
1225 mp3_play_pause(false);
1230 /* Open the next file */
1234 if (new_file(1) < 0) {
1235 DEBUGF("No more files to play\n");
1238 /* Make it read more data */
1240 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1242 /* Tell the file loading code that we want
1243 to start playing as soon as we have some data */
1244 play_pending
= true;
1247 current_track_counter
++;
1253 DEBUGF("MPEG_PREV\n");
1255 if (!playlist_check(-1))
1258 /* stop the current stream */
1259 play_pending
= false;
1261 mp3_play_pause(false);
1266 /* Open the next file */
1270 if (new_file(-1) < 0) {
1271 DEBUGF("No more files to play\n");
1274 /* Make it read more data */
1276 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1278 /* Tell the file loading code that we want to
1279 start playing as soon as we have some data */
1280 play_pending
= true;
1283 current_track_counter
++;
1288 case MPEG_FF_REWIND
: {
1289 struct mp3entry
*id3
= mpeg_current_track();
1290 unsigned int oldtime
= id3
->elapsed
;
1291 unsigned int newtime
= (unsigned int)ev
.data
;
1292 int curpos
, newpos
, diffpos
;
1293 DEBUGF("MPEG_FF_REWIND\n");
1295 id3
->elapsed
= newtime
;
1297 newpos
= mpeg_get_file_pos();
1300 id3
->elapsed
= oldtime
;
1305 curpos
= lseek(mpeg_file
, 0, SEEK_CUR
);
1307 curpos
= id3
->filesize
;
1309 if (num_tracks_in_memory() > 1)
1311 /* We have started loading other tracks that need to be
1313 int i
= tag_read_idx
;
1314 int j
= tag_write_idx
- 1;
1317 j
= MAX_ID3_TAGS
- 1;
1321 curpos
+= id3tags
[i
]->id3
.filesize
;
1322 i
= (i
+1) & MAX_ID3_TAGS_MASK
;
1326 diffpos
= curpos
- newpos
;
1328 if(!filling
&& diffpos
>= 0 && diffpos
< mp3buflen
)
1330 int unplayed_space_left
, unswapped_space_left
;
1332 /* We are changing to a position that's already in
1333 memory, so we just move the DMA read pointer. */
1334 mp3buf_read
= mp3buf_write
- diffpos
;
1335 if (mp3buf_read
< 0)
1337 mp3buf_read
+= mp3buflen
;
1340 unplayed_space_left
= get_unplayed_space();
1341 unswapped_space_left
= get_unswapped_space();
1343 /* If unswapped_space_left is larger than
1344 unplayed_space_left, it means that the swapwrite pointer
1345 hasn't yet advanced up to the new location of the read
1346 pointer. We just move it, there is no need to swap
1347 data that won't be played anyway. */
1349 if (unswapped_space_left
> unplayed_space_left
)
1351 DEBUGF("Moved swapwrite\n");
1352 mp3buf_swapwrite
= mp3buf_read
;
1353 play_pending
= true;
1356 if (mpeg_file
>=0 && unplayed_space_left
< low_watermark
)
1358 /* We need to load more data before starting */
1360 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1361 play_pending
= true;
1365 /* resume will start at new position */
1366 last_dma_chunk_size
=
1367 MIN(0x2000, get_unplayed_space_current_song());
1368 mp3_play_data(mp3buf
+ mp3buf_read
,
1369 last_dma_chunk_size
, transfer_end
);
1370 dma_underrun
= false;
1375 /* Move to the new position in the file and start
1379 if (num_tracks_in_memory() > 1)
1381 /* We have to reload the current track */
1383 remove_all_non_current_tags();
1389 mpeg_file
= open(id3
->path
, O_RDONLY
);
1392 id3
->elapsed
= oldtime
;
1397 if(-1 == lseek(mpeg_file
, newpos
, SEEK_SET
))
1399 id3
->elapsed
= oldtime
;
1404 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1406 /* Tell the file loading code that we want to start playing
1407 as soon as we have some data */
1408 play_pending
= true;
1411 id3
->offset
= newpos
;
1416 case MPEG_FLUSH_RELOAD
: {
1417 int numtracks
= num_tracks_in_memory();
1418 bool reload_track
= false;
1423 int next
= (tag_read_idx
+1) & MAX_ID3_TAGS_MASK
;
1425 /* Reset the buffer */
1426 mp3buf_write
= id3tags
[next
]->mempos
;
1428 /* Reset swapwrite unless we're still swapping current
1430 if (get_unplayed_space() <= get_playable_space())
1431 mp3buf_swapwrite
= mp3buf_write
;
1434 remove_all_non_current_tags();
1436 reload_track
= true;
1438 else if (numtracks
== 1 && mpeg_file
< 0)
1440 reload_track
= true;
1443 if(reload_track
&& new_file(1) >= 0)
1445 /* Tell ourselves that we want more data */
1446 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1453 case MPEG_NEED_DATA
:
1454 free_space_left
= mp3buf_read
- mp3buf_write
;
1456 /* We interpret 0 as "empty buffer" */
1457 if(free_space_left
<= 0)
1458 free_space_left
= mp3buflen
+ free_space_left
;
1460 unplayed_space_left
= mp3buflen
- free_space_left
;
1462 /* Make sure that we don't fill the entire buffer */
1463 free_space_left
-= MPEG_HIGH_WATER
;
1465 /* do we have any more buffer space to fill? */
1466 if(free_space_left
<= MPEG_HIGH_WATER
)
1474 /* Read small chunks while we are below the low water mark */
1475 if(unplayed_space_left
< low_watermark
)
1476 amount_to_read
= MIN(MPEG_LOW_WATER_CHUNKSIZE
,
1479 amount_to_read
= free_space_left
;
1481 /* Don't read more than until the end of the buffer */
1482 amount_to_read
= MIN(mp3buflen
- mp3buf_write
, amount_to_read
);
1484 amount_to_read
= MIN(0x100000, amount_to_read
);
1485 #endif /* #if MEM == 8 */
1487 /* Read as much mpeg data as we can fit in the buffer */
1492 len
= read(mpeg_file
, mp3buf
+mp3buf_write
, amount_to_read
);
1496 DEBUGF("time: %d\n", t2
- t1
);
1497 DEBUGF("R: %x\n", len
);
1499 /* Now make sure that we don't feed the MAS with ID3V1
1501 if (len
< amount_to_read
)
1503 int tagptr
= mp3buf_write
+ len
- 128;
1508 for(i
= 0;i
< 3;i
++)
1510 if(tagptr
>= mp3buflen
)
1511 tagptr
-= mp3buflen
;
1513 if(mp3buf
[tagptr
] != tag
[i
])
1521 /* Skip id3v1 tag */
1522 DEBUGF("Skipping ID3v1 tag\n");
1525 /* The very rare case when the entire tag
1526 wasn't read in this read() call must be
1533 mp3buf_write
+= len
;
1535 if(mp3buf_write
>= mp3buflen
)
1541 /* Tell ourselves that we want more data */
1542 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1548 DEBUGF("MPEG read error\n");
1556 /* No more data to play */
1557 DEBUGF("No more files to play\n");
1562 /* Tell ourselves that we want more data */
1563 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1569 case MPEG_TRACK_CHANGE
:
1574 case SYS_USB_CONNECTED
:
1580 /* Tell the USB thread that we are safe */
1581 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
1582 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1584 /* Wait until the USB cable is extracted again */
1585 usb_wait_for_disconnect(&mpeg_queue
);
1586 #endif /* #ifndef SIMULATOR */
1588 #endif /* #ifndef USB_NONE */
1590 #if CONFIG_HWCODEC == MAS3587F
1591 case MPEG_INIT_RECORDING
:
1593 init_recording_done
= true;
1595 #endif /* #if CONFIG_HWCODEC == MAS3587F */
1597 #if CONFIG_HWCODEC == MAS3587F
1601 queue_wait(&mpeg_queue
, &ev
);
1609 /* Go back prerecord_count seconds in the buffer */
1610 startpos
= prerecord_index
- prerecord_count
;
1612 startpos
+= prerecording_max_seconds
;
1614 /* Read the mp3 buffer pointer from the prerecord buffer */
1615 startpos
= prerecord_buffer
[startpos
];
1617 DEBUGF("Start looking at address %x (%x)\n",
1618 mp3buf
+startpos
, startpos
);
1620 saved_header
= mpeg_get_last_header();
1622 mem_find_next_frame(startpos
, &offset
, 5000,
1625 mp3buf_read
= startpos
+ offset
;
1627 DEBUGF("New mp3buf_read address: %x (%x)\n",
1628 mp3buf
+mp3buf_read
, mp3buf_read
);
1630 /* Make room for headers */
1631 mp3buf_read
-= MPEG_RESERVED_HEADER_SPACE
;
1634 /* Clear the bottom half */
1636 mp3buf_read
+ MPEG_RESERVED_HEADER_SPACE
);
1638 /* And the top half */
1639 mp3buf_read
+= mp3buflen
;
1640 memset(mp3buf
+ mp3buf_read
, 0,
1641 mp3buflen
- mp3buf_read
);
1645 memset(mp3buf
+ mp3buf_read
, 0,
1646 MPEG_RESERVED_HEADER_SPACE
);
1649 /* Copy the empty ID3 header */
1650 startpos
= mp3buf_read
;
1651 for(i
= 0;i
< (int)sizeof(empty_id3_header
);i
++)
1653 mp3buf
[startpos
++] = empty_id3_header
[i
];
1654 if(startpos
== mp3buflen
)
1658 DEBUGF("New mp3buf_read address (reservation): %x\n",
1659 mp3buf
+mp3buf_read
);
1661 DEBUGF("Prerecording...\n");
1669 /* Advance the write pointer to make
1670 room for an ID3 tag plus a VBR header */
1671 mp3buf_write
= MPEG_RESERVED_HEADER_SPACE
;
1672 memset(mp3buf
, 0, MPEG_RESERVED_HEADER_SPACE
);
1674 /* Insert the ID3 header */
1675 memcpy(mp3buf
, empty_id3_header
,
1676 sizeof(empty_id3_header
));
1678 DEBUGF("Recording...\n");
1683 /* Wait until at least one frame is encoded and get the
1684 frame header, for later use by the Xing header
1687 saved_header
= mpeg_get_last_header();
1689 /* delayed until buffer is saved, don't open yet */
1690 strcpy(delayed_filename
, recording_filename
);
1696 DEBUGF("MPEG_STOP\n");
1700 /* Save the remaining data in the buffer */
1701 stop_pending
= true;
1702 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1705 case MPEG_STOP_DONE
:
1706 DEBUGF("MPEG_STOP_DONE\n");
1711 if(!disable_xing_header
&& num_rec_bytes
> 0)
1713 /* Create the Xing header */
1714 mpeg_file
= open(recording_filename
, O_RDWR
);
1716 panicf("rec upd: %d (%s)", mpeg_file
,
1717 recording_filename
);
1719 /* If the number of recorded frames have
1720 reached 0x7ffff, we can no longer trust it */
1721 if(num_recorded_frames
== 0x7ffff)
1722 num_recorded_frames
= 0;
1724 /* Also, if we have been prerecording, the frame count
1727 num_recorded_frames
= 0;
1729 /* saved_header is saved right before stopping
1731 framelen
= create_xing_header(mpeg_file
, 0,
1732 num_rec_bytes
, mp3buf
,
1733 num_recorded_frames
,
1737 lseek(mpeg_file
, MPEG_RESERVED_HEADER_SPACE
-framelen
,
1739 write(mpeg_file
, mp3buf
, framelen
);
1747 for(i
= 0;i
< 512;i
++)
1749 DEBUGF("%d - %d us (%d bytes)\n",
1751 (timing_info
[i
*2+1] & 0xffff) *
1753 timing_info
[i
*2+1] >> 16);
1756 #endif /* #ifdef DEBUG1 */
1760 start_prerecording();
1762 mpeg_stop_done
= true;
1766 /* Make sure we have at least one complete frame
1767 in the buffer. If we haven't recorded a single
1768 frame within 200ms, the MAS is probably not recording
1769 anything, and we bail out. */
1771 amount_to_save
= get_unsaved_space();
1772 while(countdown
-- && amount_to_save
< 1800)
1775 amount_to_save
= get_unsaved_space();
1778 if(amount_to_save
>= 1800)
1780 /* Now find a frame boundary to split at */
1781 startpos
= mp3buf_write
- 1800;
1783 startpos
+= mp3buflen
;
1785 rc
= mem_find_next_frame(startpos
, &offset
, 1800,
1787 if(rc
) /* Header found? */
1789 /* offset will now contain the number of bytes to
1790 add to startpos to find the frame boundary */
1792 if(startpos
>= mp3buflen
)
1793 startpos
-= mp3buflen
;
1797 /* No header found. Let's save the whole buffer. */
1798 startpos
= mp3buf_write
;
1803 /* Too few bytes recorded, timeout */
1804 startpos
= mp3buf_write
;
1807 amount_to_save
= startpos
- mp3buf_read
;
1808 if(amount_to_save
< 0)
1809 amount_to_save
+= mp3buflen
;
1811 /* First save up to the end of the buffer */
1812 writelen
= MIN(amount_to_save
,
1813 mp3buflen
- mp3buf_read
);
1815 if (mpeg_file
< 0) /* delayed file opening */
1817 mpeg_file
= open(delayed_filename
, O_WRONLY
|O_CREAT
);
1820 panicf("recfile: %d", mpeg_file
);
1825 rc
= write(mpeg_file
, mp3buf
+ mp3buf_read
, writelen
);
1830 mpeg_errno
= MPEGERR_DISK_FULL
;
1831 demand_irq_enable(false);
1833 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1838 panicf("spt wrt: %d", rc
);
1843 /* Then save the rest */
1844 writelen
= amount_to_save
- writelen
;
1847 rc
= write(mpeg_file
, mp3buf
, writelen
);
1852 mpeg_errno
= MPEGERR_DISK_FULL
;
1853 demand_irq_enable(false);
1855 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1860 panicf("spt wrt: %d", rc
);
1865 /* Advance the buffer pointers */
1866 mp3buf_read
+= amount_to_save
;
1867 if(mp3buf_read
>= mp3buflen
)
1868 mp3buf_read
-= mp3buflen
;
1870 /* Close the current file */
1871 rc
= close(mpeg_file
);
1873 panicf("spt cls: %d", rc
);
1875 /* Open the new file */
1876 mpeg_file
= open(recording_filename
, O_WRONLY
|O_CREAT
);
1878 panicf("sptfile: %d", mpeg_file
);
1881 case MPEG_SAVE_DATA
:
1882 amount_to_save
= get_unsaved_space();
1884 /* If the result is negative, the write index has
1886 if(amount_to_save
< 0)
1888 amount_to_save
+= mp3buflen
;
1891 DEBUGF("r: %x w: %x\n", mp3buf_read
, mp3buf_write
);
1892 DEBUGF("ats: %x\n", amount_to_save
);
1894 /* Save data only if the buffer is getting full,
1895 or if we should stop recording */
1899 amount_to_save
< MPEG_RECORDING_LOW_WATER
||
1902 /* Only save up to the end of the buffer */
1903 writelen
= MIN(amount_to_save
,
1904 mp3buflen
- mp3buf_read
);
1906 DEBUGF("wrl: %x\n", writelen
);
1908 if (mpeg_file
< 0) /* delayed file opening */
1910 mpeg_file
= open(delayed_filename
,
1914 panicf("recfile: %d", mpeg_file
);
1917 rc
= write(mpeg_file
, mp3buf
+ mp3buf_read
,
1924 mpeg_errno
= MPEGERR_DISK_FULL
;
1926 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1931 panicf("rec wrt: %d", rc
);
1935 mp3buf_read
+= amount_to_save
;
1936 if(mp3buf_read
>= mp3buflen
)
1939 rc
= fsync(mpeg_file
);
1941 panicf("rec fls: %d", rc
);
1943 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1953 /* We have saved all data,
1954 time to stop for real */
1956 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1962 case MPEG_INIT_PLAYBACK
:
1963 /* Stop the prerecording */
1966 init_playback_done
= true;
1969 case MPEG_PAUSE_RECORDING
:
1973 case MPEG_RESUME_RECORDING
:
1977 case SYS_USB_CONNECTED
:
1978 /* We can safely go to USB mode if no recording
1980 if((!is_recording
|| is_prerecording
) && mpeg_stop_done
)
1982 /* Even if we aren't recording, we still call this
1983 function, to put the MAS in monitoring mode,
1987 /* Tell the USB thread that we are safe */
1988 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
1989 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1991 /* Wait until the USB cable is extracted again */
1992 usb_wait_for_disconnect(&mpeg_queue
);
1997 #endif /* #if CONFIG_HWCODEC == MAS3587F */
2000 #endif /* SIMULATOR */
2003 static struct mp3entry taginfo
;
2004 #endif /* #ifdef SIMULATOR */
2006 void mpeg_id3_options(bool _v1first
)
2011 struct mp3entry
* mpeg_current_track()
2016 if(num_tracks_in_memory())
2017 return &(id3tags
[tag_read_idx
]->id3
);
2020 #endif /* #ifdef SIMULATOR */
2023 struct mp3entry
* mpeg_next_track()
2028 if(num_tracks_in_memory() > 1)
2029 return &(id3tags
[(tag_read_idx
+1) & MAX_ID3_TAGS_MASK
]->id3
);
2032 #endif /* #ifdef SIMULATOR */
2035 bool mpeg_has_changed_track(void)
2037 if(last_track_counter
!= current_track_counter
)
2039 last_track_counter
= current_track_counter
;
2045 #if CONFIG_HWCODEC == MAS3587F
2046 void mpeg_init_playback(void)
2048 init_playback_done
= false;
2049 queue_post(&mpeg_queue
, MPEG_INIT_PLAYBACK
, NULL
);
2051 while(!init_playback_done
)
2057 /****************************************************************************
2060 ** Recording functions
2063 ***************************************************************************/
2064 void mpeg_init_recording(void)
2066 init_recording_done
= false;
2067 queue_post(&mpeg_queue
, MPEG_INIT_RECORDING
, NULL
);
2069 while(!init_recording_done
)
2074 static void init_recording(void)
2086 /* Init the recording variables */
2087 is_recording
= false;
2088 is_prerecording
= false;
2090 mpeg_stop_done
= true;
2094 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2095 rc
= mas_direct_config_write(MAS_CONTROL
, 0x8c00);
2097 panicf("mas_ctrl_w: %d", rc
);
2099 /* Stop the current application */
2101 mas_writemem(MAS_BANK_D0
, MAS_D0_APP_SELECT
, &val
, 1);
2104 mas_readmem(MAS_BANK_D0
, MAS_D0_APP_RUNNING
, &val
, 1);
2107 /* Perform black magic as described by the data sheet */
2108 if((mas_version_code
& 0x0fff) == 0x0102)
2110 DEBUGF("Performing MAS black magic for B2 version\n");
2111 mas_writereg(0xa3, 0x98);
2112 mas_writereg(0x94, 0xfffff);
2114 mas_writemem(MAS_BANK_D1
, 0, &val
, 1);
2115 mas_writereg(0xa3, 0x90);
2118 /* Enable A/D Converters */
2119 mas_codec_writereg(0x0, 0xcccd);
2121 /* Copy left channel to right (mono mode) */
2122 mas_codec_writereg(8, 0x8000);
2124 /* ADC scale 0%, DSP scale 100%
2125 We use the DSP output for monitoring, because it works with all
2126 sources including S/PDIF */
2127 mas_codec_writereg(6, 0x0000);
2128 mas_codec_writereg(7, 0x4000);
2131 shadow_soft_mute
= 0;
2132 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2134 /* Set Demand mode, monitoring OFF and validate all settings */
2135 shadow_io_control_main
= 0x125;
2136 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2138 /* Start the encoder application */
2140 mas_writemem(MAS_BANK_D0
, MAS_D0_APP_SELECT
, &val
, 1);
2143 mas_readmem(MAS_BANK_D0
, MAS_D0_APP_RUNNING
, &val
, 1);
2144 } while(!(val
& 0x40));
2147 /* We have started the recording application with monitoring OFF.
2148 This is because we want to record at least one frame to fill the DMA
2149 buffer, because the silly MAS will not negate EOD until at least one
2150 DMA transfer has taken place.
2151 Now let's wait for some data to be encoded. */
2154 /* Now set it to Monitoring mode as default, saves power */
2155 shadow_io_control_main
= 0x525;
2156 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2158 /* Wait until the DSP has accepted the settings */
2161 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2166 mpeg_mode
= MPEG_ENCODER
;
2168 DEBUGF("MAS Recording application started\n");
2170 /* At this point, all settings are the reset MAS defaults, next thing is to
2171 call mpeg_set_recording_options(). */
2174 void mpeg_record(const char *filename
)
2178 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
2179 recording_filename
[MAX_PATH
- 1] = 0;
2181 disable_xing_header
= false;
2182 queue_post(&mpeg_queue
, MPEG_RECORD
, NULL
);
2185 void mpeg_pause_recording(void)
2187 queue_post(&mpeg_queue
, MPEG_PAUSE_RECORDING
, NULL
);
2190 void mpeg_resume_recording(void)
2192 queue_post(&mpeg_queue
, MPEG_RESUME_RECORDING
, NULL
);
2195 static void start_prerecording(void)
2199 DEBUGF("Starting prerecording\n");
2201 prerecord_index
= 0;
2202 prerecord_count
= 0;
2203 prerecord_timeout
= current_tick
+ HZ
;
2204 memset(prerecord_buffer
, 0, sizeof(prerecord_buffer
));
2207 is_prerecording
= true;
2209 /* Stop monitoring and start the encoder */
2210 shadow_io_control_main
&= ~(1 << 10);
2211 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2212 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2214 /* Wait until the DSP has accepted the settings */
2217 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2220 is_recording
= true;
2221 stop_pending
= false;
2224 demand_irq_enable(true);
2227 static void start_recording(void)
2231 num_recorded_frames
= 0;
2235 /* This will make the IRQ handler start recording
2236 for real, i.e send MPEG_SAVE_DATA messages when
2237 the buffer is full */
2238 is_prerecording
= false;
2242 /* If prerecording is off, we need to stop the monitoring
2243 and start the encoder */
2244 shadow_io_control_main
&= ~(1 << 10);
2245 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2246 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2248 /* Wait until the DSP has accepted the settings */
2251 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2255 is_recording
= true;
2256 stop_pending
= false;
2260 /* Store the current time */
2262 record_start_time
= current_tick
- prerecord_count
* HZ
;
2264 record_start_time
= current_tick
;
2266 pause_start_time
= 0;
2268 demand_irq_enable(true);
2271 static void pause_recording(void)
2273 pause_start_time
= current_tick
;
2275 /* Set the pause bit */
2276 shadow_soft_mute
|= 2;
2277 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2282 static void resume_recording(void)
2286 /* Clear the pause bit */
2287 shadow_soft_mute
&= ~2;
2288 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2290 /* Compensate for the time we have been paused */
2291 if(pause_start_time
)
2294 current_tick
- (pause_start_time
- record_start_time
);
2295 pause_start_time
= 0;
2299 static void stop_recording(void)
2303 /* Let it finish the last frame */
2308 demand_irq_enable(false);
2310 is_recording
= false;
2311 is_prerecording
= false;
2313 /* Read the number of frames recorded */
2314 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_FRAME_COUNT
, &num_recorded_frames
, 1);
2316 /* Start monitoring */
2317 shadow_io_control_main
|= (1 << 10);
2318 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2319 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2321 /* Wait until the DSP has accepted the settings */
2324 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2330 void mpeg_set_recording_options(int frequency
, int quality
,
2331 int source
, int channel_mode
,
2332 bool editable
, int prerecord_time
)
2336 is_mpeg1
= (frequency
< 3)?true:false;
2338 rec_version_index
= is_mpeg1
?3:2;
2339 rec_frequency_index
= frequency
% 3;
2341 shadow_encoder_control
= (quality
<< 17) |
2342 (rec_frequency_index
<< 10) |
2343 ((is_mpeg1
?1:0) << 9) |
2344 (((channel_mode
* 2 + 1) & 3) << 6) |
2345 (1 << 5) /* MS-stereo */ |
2346 (1 << 2) /* Is an original */;
2347 mas_writemem(MAS_BANK_D0
, MAS_D0_ENCODER_CONTROL
, &shadow_encoder_control
,1);
2349 DEBUGF("mas_writemem(MAS_BANK_D0, ENCODER_CONTROL, %x)\n", shadow_encoder_control
);
2351 shadow_soft_mute
= editable
?4:0;
2352 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
,1);
2354 DEBUGF("mas_writemem(MAS_BANK_D0, SOFT_MUTE, %x)\n", shadow_soft_mute
);
2356 shadow_io_control_main
= ((1 << 10) | /* Monitoring ON */
2357 ((source
< 2)?1:2) << 8) | /* Input select */
2358 (1 << 5) | /* SDO strobe invert */
2359 ((is_mpeg1
?0:1) << 3) |
2360 (1 << 2) | /* Inverted SIBC clock signal */
2362 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
,1);
2364 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2366 if(source
== 0) /* Mic */
2368 /* Copy left channel to right (mono mode) */
2369 mas_codec_writereg(8, 0x8000);
2373 /* Stereo input mode */
2374 mas_codec_writereg(8, 0);
2377 prerecording_max_seconds
= prerecord_time
;
2378 if(prerecording_max_seconds
)
2380 prerecording
= true;
2381 start_prerecording();
2385 prerecording
= false;
2386 is_prerecording
= false;
2387 is_recording
= false;
2391 /* If use_mic is true, the left gain is used */
2392 void mpeg_set_recording_gain(int left
, int right
, bool use_mic
)
2394 /* Enable both left and right A/D */
2395 mas_codec_writereg(0x0,
2399 (use_mic
?0x0008:0) | /* Connect left A/D to mic */
2403 void mpeg_new_file(const char *filename
)
2407 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
2408 recording_filename
[MAX_PATH
- 1] = 0;
2411 disable_xing_header
= true;
2413 /* Store the current time */
2414 record_start_time
= current_tick
;
2416 queue_post(&mpeg_queue
, MPEG_NEW_FILE
, NULL
);
2419 unsigned long mpeg_recorded_time(void)
2422 return prerecord_count
* HZ
;
2427 return pause_start_time
- record_start_time
;
2429 return current_tick
- record_start_time
;
2435 unsigned long mpeg_num_recorded_bytes(void)
2444 index
= prerecord_index
- prerecord_count
;
2446 index
+= prerecording_max_seconds
;
2448 num_bytes
= mp3buf_write
- prerecord_buffer
[index
];
2450 num_bytes
+= mp3buflen
;
2455 return num_rec_bytes
;
2463 void mpeg_play(int offset
)
2472 trackname
= playlist_peek( steps
);
2475 if(mp3info(&taginfo
, trackname
, v1first
)) {
2476 /* bad mp3, move on */
2477 if(++steps
> playlist_amount())
2481 #ifdef HAVE_MPEG_PLAY
2482 real_mpeg_play(trackname
);
2484 playlist_next(steps
);
2485 taginfo
.offset
= offset
;
2486 set_elapsed(&taginfo
);
2494 queue_post(&mpeg_queue
, MPEG_PLAY
, (void*)offset
);
2495 #endif /* #ifdef SIMULATOR */
2500 void mpeg_stop(void)
2503 mpeg_stop_done
= false;
2504 queue_post(&mpeg_queue
, MPEG_STOP
, NULL
);
2505 while(!mpeg_stop_done
)
2511 #endif /* #ifndef SIMULATOR */
2515 void mpeg_pause(void)
2518 queue_post(&mpeg_queue
, MPEG_PAUSE
, NULL
);
2523 #endif /* #ifndef SIMULATOR */
2526 void mpeg_resume(void)
2529 queue_post(&mpeg_queue
, MPEG_RESUME
, NULL
);
2534 #endif /* #ifndef SIMULATOR */
2537 void mpeg_next(void)
2540 queue_post(&mpeg_queue
, MPEG_NEXT
, NULL
);
2547 file
= playlist_peek(steps
);
2550 if(mp3info(&taginfo
, file
, v1first
)) {
2551 if(++steps
> playlist_amount())
2555 index
= playlist_next(steps
);
2556 taginfo
.index
= index
;
2557 current_track_counter
++;
2562 #endif /* #ifndef SIMULATOR */
2565 void mpeg_prev(void)
2568 queue_post(&mpeg_queue
, MPEG_PREV
, NULL
);
2575 file
= playlist_peek(steps
);
2578 if(mp3info(&taginfo
, file
, v1first
)) {
2582 index
= playlist_next(steps
);
2583 taginfo
.index
= index
;
2584 current_track_counter
++;
2589 #endif /* #ifndef SIMULATOR */
2592 void mpeg_ff_rewind(int newtime
)
2595 queue_post(&mpeg_queue
, MPEG_FF_REWIND
, (void *)newtime
);
2598 #endif /* #ifndef SIMULATOR */
2601 void mpeg_flush_and_reload_tracks(void)
2604 queue_post(&mpeg_queue
, MPEG_FLUSH_RELOAD
, NULL
);
2605 #endif /* #ifndef SIMULATOR*/
2608 int mpeg_status(void)
2613 ret
|= MPEG_STATUS_PLAY
;
2616 ret
|= MPEG_STATUS_PAUSE
;
2618 #if CONFIG_HWCODEC == MAS3587F
2619 if(is_recording
&& !is_prerecording
)
2620 ret
|= MPEG_STATUS_RECORD
;
2623 ret
|= MPEG_STATUS_PRERECORD
;
2624 #endif /* #if CONFIG_HWCODEC == MAS3587F */
2627 ret
|= MPEG_STATUS_ERROR
;
2632 unsigned int mpeg_error(void)
2637 void mpeg_error_clear(void)
2643 static char mpeg_stack
[DEFAULT_STACK_SIZE
];
2644 static const char mpeg_thread_name
[] = "mpeg";
2645 static void mpeg_thread(void)
2647 struct mp3entry
* id3
;
2650 id3
= mpeg_current_track();
2656 if (id3
->elapsed
>=id3
->length
)
2662 #endif /* #ifdef SIMULATOR */
2664 void mpeg_init(void)
2669 mp3buflen
= mp3end
- mp3buf
;
2670 queue_init(&mpeg_queue
);
2671 #endif /* #ifndef SIMULATOR */
2672 create_thread(mpeg_thread
, mpeg_stack
,
2673 sizeof(mpeg_stack
), mpeg_thread_name
);
2675 memset(id3tags
, sizeof(id3tags
), 0);
2676 memset(_id3tags
, sizeof(id3tags
), 0);
2678 #if CONFIG_HWCODEC == MAS3587F
2679 if(read_hw_mask() & PR_ACTIVE_HIGH
)
2680 and_b(~0x08, &PADRH
);
2683 #endif /* #if CONFIG_HWCODEC == MAS3587F */