1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
25 #if CONFIG_CODEC != SWCODEC
39 #include "mp3_playback.h"
42 #include "appevents.h"
50 #endif /* !SIMULATOR */
51 #ifdef HAVE_LCD_BITMAP
56 extern unsigned long mas_version_code
;
59 #if CONFIG_CODEC == MAS3587F
60 extern enum /* from mp3_playback.c */
65 #endif /* CONFIG_CODEC == MAS3587F */
67 extern char* playlist_peek(int steps
);
68 extern bool playlist_check(int steps
);
69 extern int playlist_next(int steps
);
70 extern int playlist_amount(void);
71 extern int playlist_update_resume_info(const struct mp3entry
* id3
);
79 #define MPEG_FF_REWIND 7
80 #define MPEG_FLUSH_RELOAD 8
82 #define MPEG_INIT_RECORDING 10
83 #define MPEG_INIT_PLAYBACK 11
84 #define MPEG_NEW_FILE 12
85 #define MPEG_PAUSE_RECORDING 13
86 #define MPEG_RESUME_RECORDING 14
87 #define MPEG_NEED_DATA 100
88 #define MPEG_TRACK_CHANGE 101
89 #define MPEG_SAVE_DATA 102
90 #define MPEG_STOP_DONE 103
91 #define MPEG_PRERECORDING_TICK 104
93 /* indicator for MPEG_NEED_DATA */
94 #define GENERATE_UNBUFFER_EVENTS 1
96 /* list of tracks in memory */
97 #define MAX_TRACK_ENTRIES (1<<4) /* Must be power of 2 */
98 #define MAX_TRACK_ENTRIES_MASK (MAX_TRACK_ENTRIES - 1)
104 int load_ahead_index
;
107 static struct trackdata trackdata
[MAX_TRACK_ENTRIES
];
109 static unsigned int current_track_counter
= 0;
110 static unsigned int last_track_counter
= 0;
112 /* Play time of the previous track */
113 unsigned long prev_track_elapsed
;
116 static int track_read_idx
= 0;
117 static int track_write_idx
= 0;
118 #endif /* !SIMULATOR */
120 /* Cuesheet callback */
121 static bool (*cuesheet_callback
)(const char *filename
) = NULL
;
123 static const char mpeg_thread_name
[] = "mpeg";
124 static unsigned int mpeg_errno
;
126 static bool playing
= false; /* We are playing an MP3 stream */
127 static bool is_playing
= false; /* We are (attempting to) playing MP3 files */
128 static bool paused
; /* playback is paused */
131 static char mpeg_stack
[DEFAULT_STACK_SIZE
];
132 static struct mp3entry taginfo
;
134 #else /* !SIMULATOR */
135 static struct event_queue mpeg_queue
;
136 static long mpeg_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
138 static int audiobuflen
;
139 static int audiobuf_write
;
140 static int audiobuf_swapwrite
;
141 static int audiobuf_read
;
143 static int mpeg_file
;
145 static bool play_pending
; /* We are about to start playing */
146 static bool play_pending_track_change
; /* When starting play we're starting a new file */
147 static bool filling
; /* We are filling the buffer with data from disk */
148 static bool dma_underrun
; /* True when the DMA has stopped because of
149 slow disk reading (read error, shaking) */
150 static bool mpeg_stop_done
;
152 static int last_dma_tick
= 0;
153 static int last_dma_chunk_size
;
155 static long low_watermark
; /* Dynamic low watermark level */
156 static long low_watermark_margin
= 0; /* Extra time in seconds for watermark */
157 static long lowest_watermark_level
; /* Debug value to observe the buffer
159 #if CONFIG_CODEC == MAS3587F
160 static char recording_filename
[MAX_PATH
]; /* argument to thread */
161 static char delayed_filename
[MAX_PATH
]; /* internal copy of above */
163 static char xing_buffer
[MAX_XING_HEADER_SIZE
];
165 static bool init_recording_done
;
166 static bool init_playback_done
;
167 static bool prerecording
; /* True if prerecording is enabled */
168 static bool is_prerecording
; /* True if we are prerecording */
169 static bool is_recording
; /* We are recording */
172 NOT_SAVING
= 0, /* reasons to save data, sorted by importance */
178 static int rec_frequency_index
; /* For create_xing_header() calls */
179 static int rec_version_index
; /* For create_xing_header() calls */
181 struct prerecord_info
{
183 unsigned long framecount
;
186 static struct prerecord_info prerecord_buffer
[MPEG_MAX_PRERECORD_SECONDS
];
187 static int prerecord_index
; /* Current index in the prerecord buffer */
188 static int prerecording_max_seconds
; /* Max number of seconds to store */
189 static int prerecord_count
; /* Number of seconds in the prerecord buffer */
190 static int prerecord_timeout
; /* The tick count of the next prerecord data
193 unsigned long record_start_time
; /* Value of current_tick when recording
195 unsigned long pause_start_time
; /* Value of current_tick when pause was
197 static unsigned long last_rec_time
;
198 static unsigned long num_rec_bytes
;
199 static unsigned long last_rec_bytes
;
200 static unsigned long frame_count_start
;
201 static unsigned long frame_count_end
;
202 static unsigned long saved_header
= 0;
204 /* Shadow MAS registers */
205 unsigned long shadow_encoder_control
= 0;
206 #endif /* CONFIG_CODEC == MAS3587F */
208 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
209 unsigned long shadow_io_control_main
= 0;
210 unsigned long shadow_soft_mute
= 0;
211 unsigned shadow_codec_reg0
;
212 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
214 #ifdef HAVE_RECORDING
215 static const unsigned char empty_id3_header
[] =
217 'I', 'D', '3', 0x03, 0x00, 0x00,
218 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
220 #endif /* HAVE_RECORDING */
223 static int get_unplayed_space(void);
224 static int get_playable_space(void);
225 static int get_unswapped_space(void);
226 #endif /* !SIMULATOR */
228 #if (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR)
229 static void init_recording(void);
230 static void prepend_header(void);
231 static void update_header(void);
232 static void start_prerecording(void);
233 static void start_recording(void);
234 static void stop_recording(void);
235 static int get_unsaved_space(void);
236 static void pause_recording(void);
237 static void resume_recording(void);
238 #endif /* (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR) */
242 static int num_tracks_in_memory(void)
244 return (track_write_idx
- track_read_idx
) & MAX_TRACK_ENTRIES_MASK
;
248 static void debug_tags(void)
252 for(i
= 0;i
< MAX_TRACK_ENTRIES
;i
++)
254 DEBUGF("%d - %s\n", i
, trackdata
[i
].id3
.path
);
256 DEBUGF("read: %d, write :%d\n", track_read_idx
, track_write_idx
);
257 DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory());
259 #else /* !DEBUG_TAGS */
261 #endif /* !DEBUG_TAGS */
263 static void remove_current_tag(void)
265 if(num_tracks_in_memory() > 0)
267 /* First move the index, so nobody tries to access the tag */
268 track_read_idx
= (track_read_idx
+1) & MAX_TRACK_ENTRIES_MASK
;
273 DEBUGF("remove_current_tag: no tracks to remove\n");
277 static void remove_all_non_current_tags(void)
279 track_write_idx
= (track_read_idx
+1) & MAX_TRACK_ENTRIES_MASK
;
283 static void remove_all_tags(void)
285 track_write_idx
= track_read_idx
;
290 static struct trackdata
*get_trackdata(int offset
)
292 if(offset
>= num_tracks_in_memory())
295 return &trackdata
[(track_read_idx
+ offset
) & MAX_TRACK_ENTRIES_MASK
];
297 #endif /* !SIMULATOR */
299 /***********************************************************************/
300 /* audio event handling */
302 #define MAX_EVENT_HANDLERS 10
303 struct event_handlers_table
305 AUDIO_EVENT_HANDLER handler
;
308 static struct event_handlers_table event_handlers
[MAX_EVENT_HANDLERS
];
309 static int event_handlers_count
= 0;
311 void audio_register_event_handler(AUDIO_EVENT_HANDLER handler
, unsigned short mask
)
313 if (event_handlers_count
< MAX_EVENT_HANDLERS
)
315 event_handlers
[event_handlers_count
].handler
= handler
;
316 event_handlers
[event_handlers_count
].mask
= mask
;
317 event_handlers_count
++;
321 /* dispatch calls each handler in the order registered and returns after some
322 handler actually handles the event (the event is assumed to no longer be valid
323 after this, due to the handler changing some condition); returns true if someone
324 handled the event, which is expected to cause the caller to skip its own handling
327 static bool audio_dispatch_event(unsigned short event
, unsigned long data
)
330 for(i
=0; i
< event_handlers_count
; i
++)
332 if ( event_handlers
[i
].mask
& event
)
334 int rc
= event_handlers
[i
].handler(event
, data
);
335 if ( rc
== AUDIO_EVENT_RC_HANDLED
)
343 /***********************************************************************/
345 static void set_elapsed(struct mp3entry
* id3
)
348 if ( id3
->has_toc
) {
349 /* calculate elapsed time using TOC */
351 unsigned int remainder
, plen
, relpos
, nextpos
;
353 /* find wich percent we're at */
354 for (i
=0; i
<100; i
++ )
356 if ( id3
->offset
< id3
->toc
[i
] * (id3
->filesize
/ 256) )
366 relpos
= id3
->toc
[i
];
370 nextpos
= id3
->toc
[i
+1];
377 remainder
= id3
->offset
- (relpos
* (id3
->filesize
/ 256));
379 /* set time for this percent (divide before multiply to prevent
380 overflow on long files. loss of precision is negligible on
382 id3
->elapsed
= i
* (id3
->length
/ 100);
384 /* calculate remainder time */
385 plen
= (nextpos
- relpos
) * (id3
->filesize
/ 256);
386 id3
->elapsed
+= (((remainder
* 100) / plen
) *
387 (id3
->length
/ 10000));
390 /* no TOC exists. set a rough estimate using average bitrate */
391 int tpk
= id3
->length
/ (id3
->filesize
/ 1024);
392 id3
->elapsed
= id3
->offset
/ 1024 * tpk
;
396 /* constant bitrate, use exact calculation */
397 id3
->elapsed
= id3
->offset
/ (id3
->bitrate
/ 8);
400 int audio_get_file_pos(void)
403 struct mp3entry
*id3
= audio_current_track();
409 /* Use the TOC to find the new position */
410 unsigned int percent
, remainder
;
411 int curtoc
, nexttoc
, plen
;
413 percent
= (id3
->elapsed
*100)/id3
->length
;
417 curtoc
= id3
->toc
[percent
];
420 nexttoc
= id3
->toc
[percent
+1];
424 pos
= (id3
->filesize
/256)*curtoc
;
426 /* Use the remainder to get a more accurate position */
427 remainder
= (id3
->elapsed
*100)%id3
->length
;
428 remainder
= (remainder
*100)/id3
->length
;
429 plen
= (nexttoc
- curtoc
)*(id3
->filesize
/256);
430 pos
+= (plen
/100)*remainder
;
434 /* No TOC exists, estimate the new position */
435 pos
= (id3
->filesize
/ (id3
->length
/ 1000)) *
436 (id3
->elapsed
/ 1000);
439 else if (id3
->bitrate
)
440 pos
= id3
->elapsed
* (id3
->bitrate
/ 8);
446 if (pos
>= (int)(id3
->filesize
- id3
->id3v1len
))
448 /* Don't seek right to the end of the file so that we can
449 transition properly to the next song */
450 pos
= id3
->filesize
- id3
->id3v1len
- 1;
452 else if (pos
< (int)id3
->first_frame_offset
)
454 /* skip past id3v2 tag and other leading garbage */
455 pos
= id3
->first_frame_offset
;
460 unsigned long mpeg_get_last_header(void)
464 #else /* !SIMULATOR */
465 unsigned long tmp
[2];
467 /* Read the frame data from the MAS and reconstruct it with the
468 frame sync and all */
469 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_STATUS_1
, tmp
, 2);
470 return 0xffe00000 | ((tmp
[0] & 0x7c00) << 6) | (tmp
[1] & 0xffff);
471 #endif /* !SIMULATOR */
474 void audio_set_cuesheet_callback(bool (*handler
)(const char *filename
))
476 cuesheet_callback
= handler
;
480 /* Send callback events to notify about removing old tracks. */
481 static void generate_unbuffer_events(void)
484 int numentries
= MAX_TRACK_ENTRIES
- num_tracks_in_memory();
485 int cur_idx
= track_write_idx
;
487 for (i
= 0; i
< numentries
; i
++)
489 /* Send an event to notify that track has finished. */
490 send_event(PLAYBACK_EVENT_TRACK_FINISH
, &trackdata
[cur_idx
].id3
);
491 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_ENTRIES_MASK
;
495 /* Send callback events to notify about new tracks. */
496 static void generate_postbuffer_events(void)
499 int numentries
= num_tracks_in_memory();
500 int cur_idx
= track_read_idx
;
502 for (i
= 0; i
< numentries
; i
++)
504 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, &trackdata
[cur_idx
].id3
);
505 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_ENTRIES_MASK
;
509 static void recalculate_watermark(int bitrate
)
512 int time
= storage_spinup_time();
514 /* A bitrate of 0 probably means empty VBR header. We play safe
515 and set a high threshold */
519 bytes_per_sec
= bitrate
* 1000 / 8;
523 /* No drive spins up faster than 3.5s */
528 low_watermark
= ((low_watermark_margin
* HZ
+ time
) *
533 low_watermark
= MPEG_LOW_WATER
;
537 #ifdef HAVE_DISK_STORAGE
538 void audio_set_buffer_margin(int seconds
)
540 low_watermark_margin
= seconds
;
544 void audio_get_debugdata(struct audio_debug
*dbgdata
)
546 dbgdata
->audiobuflen
= audiobuflen
;
547 dbgdata
->audiobuf_write
= audiobuf_write
;
548 dbgdata
->audiobuf_swapwrite
= audiobuf_swapwrite
;
549 dbgdata
->audiobuf_read
= audiobuf_read
;
551 dbgdata
->last_dma_chunk_size
= last_dma_chunk_size
;
553 #if CONFIG_CPU == SH7034
554 dbgdata
->dma_on
= (SCR0
& 0x80) != 0;
556 dbgdata
->playing
= playing
;
557 dbgdata
->play_pending
= play_pending
;
558 dbgdata
->is_playing
= is_playing
;
559 dbgdata
->filling
= filling
;
560 dbgdata
->dma_underrun
= dma_underrun
;
562 dbgdata
->unplayed_space
= get_unplayed_space();
563 dbgdata
->playable_space
= get_playable_space();
564 dbgdata
->unswapped_space
= get_unswapped_space();
566 dbgdata
->low_watermark_level
= low_watermark
;
567 dbgdata
->lowest_watermark_level
= lowest_watermark_level
;
571 static void dbg_timer_start(void)
573 /* We are using timer 2 */
575 TSTR
&= ~0x04; /* Stop the timer */
576 TSNC
&= ~0x04; /* No synchronization */
577 TMDR
&= ~0x44; /* Operate normally */
579 TCNT2
= 0; /* Start counting at 0 */
580 TCR2
= 0x03; /* Sysclock/8 */
582 TSTR
|= 0x04; /* Start timer 2 */
585 static int dbg_cnt2us(unsigned int cnt
)
587 return (cnt
* 10000) / (FREQ
/800);
591 static int get_unplayed_space(void)
593 int space
= audiobuf_write
- audiobuf_read
;
595 space
+= audiobuflen
;
599 static int get_playable_space(void)
601 int space
= audiobuf_swapwrite
- audiobuf_read
;
603 space
+= audiobuflen
;
607 static int get_unplayed_space_current_song(void)
611 if (num_tracks_in_memory() > 1)
613 space
= get_trackdata(1)->mempos
- audiobuf_read
;
617 space
= audiobuf_write
- audiobuf_read
;
621 space
+= audiobuflen
;
626 static int get_unswapped_space(void)
628 int space
= audiobuf_write
- audiobuf_swapwrite
;
630 space
+= audiobuflen
;
634 #if CONFIG_CODEC == MAS3587F
635 static int get_unsaved_space(void)
637 int space
= audiobuf_write
- audiobuf_read
;
639 space
+= audiobuflen
;
643 static void drain_dma_buffer(void)
649 while (PBDRH
& 0x80);
653 while (!(PBDRH
& 0x80));
658 static long timing_info_index
= 0;
659 static long timing_info
[1024];
662 void rec_tick (void) __attribute__ ((section (".icode")));
669 if(is_recording
&& (PBDRH
& 0x40))
672 timing_info
[timing_info_index
++] = current_tick
;
675 /* Note: Although this loop is run in interrupt context, further
676 * optimisation will do no good. The MAS would then deliver bad
677 * frames occasionally, as observed in extended experiments. */
679 while (PBDRH
& 0x40) /* We try to read as long as EOD is high */
681 xor_b(0x08, &PADRH
); /* Set PR active, independent of polarity */
684 while (PBDRH
& 0x80) /* Wait until /RTW becomes active */
686 if (--delay
<= 0) /* Bail out if we have to wait too long */
687 { /* i.e. the MAS doesn't want to talk to us */
688 xor_b(0x08, &PADRH
); /* Set PR inactive */
689 goto transfer_end
; /* and get out of here */
693 data
= *(unsigned char *)0x04000000; /* read data byte */
695 xor_b(0x08, &PADRH
); /* Set PR inactive */
697 audiobuf
[audiobuf_write
++] = data
;
699 if (audiobuf_write
>= audiobuflen
)
707 timing_info
[timing_info_index
++] = TCNT2
+ (i
<< 16);
708 timing_info_index
&= 0x3ff;
715 if(TIME_AFTER(current_tick
, prerecord_timeout
))
717 prerecord_timeout
= current_tick
+ HZ
;
718 queue_post(&mpeg_queue
, MPEG_PRERECORDING_TICK
, 0);
723 /* Signal to save the data if we are running out of buffer
725 if (audiobuflen
- get_unsaved_space() < MPEG_RECORDING_LOW_WATER
726 && saving_status
== NOT_SAVING
)
728 saving_status
= BUFFER_FULL
;
729 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
734 #endif /* CONFIG_CODEC == MAS3587F */
736 void playback_tick(void)
738 struct trackdata
*ptd
= get_trackdata(0);
741 ptd
->id3
.elapsed
+= (current_tick
- last_dma_tick
) * 1000 / HZ
;
742 last_dma_tick
= current_tick
;
743 audio_dispatch_event(AUDIO_EVENT_POS_REPORT
,
744 (unsigned long)ptd
->id3
.elapsed
);
748 static void reset_mp3_buffer(void)
752 audiobuf_swapwrite
= 0;
753 lowest_watermark_level
= audiobuflen
;
756 /* DMA transfer end interrupt callback */
757 static void transfer_end(unsigned char** ppbuf
, size_t* psize
)
759 if(playing
&& !paused
)
761 int unplayed_space_left
;
762 int space_until_end_of_buffer
;
763 int track_offset
= 1;
764 struct trackdata
*track
;
766 audiobuf_read
+= last_dma_chunk_size
;
767 if(audiobuf_read
>= audiobuflen
)
770 /* First, check if we are on a track boundary */
771 if (num_tracks_in_memory() > 1)
773 if (audiobuf_read
== get_trackdata(track_offset
)->mempos
)
775 if ( ! audio_dispatch_event(AUDIO_EVENT_END_OF_TRACK
, 0) )
777 queue_post(&mpeg_queue
, MPEG_TRACK_CHANGE
, 0);
783 unplayed_space_left
= get_unplayed_space();
785 space_until_end_of_buffer
= audiobuflen
- audiobuf_read
;
787 if(!filling
&& unplayed_space_left
< low_watermark
)
790 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, GENERATE_UNBUFFER_EVENTS
);
793 if(unplayed_space_left
)
795 last_dma_chunk_size
= MIN(0x2000, unplayed_space_left
);
796 last_dma_chunk_size
= MIN(last_dma_chunk_size
,
797 space_until_end_of_buffer
);
799 /* several tracks loaded? */
800 track
= get_trackdata(track_offset
);
803 /* will we move across the track boundary? */
804 if (( audiobuf_read
< track
->mempos
) &&
805 ((audiobuf_read
+last_dma_chunk_size
) >
808 /* Make sure that we end exactly on the boundary */
809 last_dma_chunk_size
= track
->mempos
- audiobuf_read
;
813 *psize
= last_dma_chunk_size
& 0xffff;
814 *ppbuf
= audiobuf
+ audiobuf_read
;
815 track
= get_trackdata(0);
817 track
->id3
.offset
+= last_dma_chunk_size
;
819 /* Update the watermark debug level */
820 if(unplayed_space_left
< lowest_watermark_level
)
821 lowest_watermark_level
= unplayed_space_left
;
825 /* Check if the end of data is because of a hard disk error.
826 If there is an open file handle, we are still playing music.
827 If not, the last file has been loaded, and the file handle is
831 /* Update the watermark debug level */
832 if(unplayed_space_left
< lowest_watermark_level
)
833 lowest_watermark_level
= unplayed_space_left
;
835 DEBUGF("DMA underrun.\n");
840 if ( ! audio_dispatch_event(AUDIO_EVENT_END_OF_TRACK
, 0) )
842 DEBUGF("No more MP3 data. Stopping.\n");
843 queue_post(&mpeg_queue
, MPEG_TRACK_CHANGE
, 0);
847 *psize
= 0; /* no more transfer */
852 static struct trackdata
*add_track_to_tag_list(const char *filename
)
854 struct trackdata
*track
;
856 if(num_tracks_in_memory() >= MAX_TRACK_ENTRIES
)
858 DEBUGF("Tag memory is full\n");
862 track
= &trackdata
[track_write_idx
];
864 /* grab id3 tag of new file and
865 remember where in memory it starts */
866 if(mp3info(&track
->id3
, filename
))
871 track
->mempos
= audiobuf_write
;
872 track
->id3
.elapsed
= 0;
873 #ifdef HAVE_LCD_BITMAP
874 if (track
->id3
.title
)
875 lcd_getstringsize(track
->id3
.title
, NULL
, NULL
);
876 if (track
->id3
.artist
)
877 lcd_getstringsize(track
->id3
.artist
, NULL
, NULL
);
878 if (track
->id3
.album
)
879 lcd_getstringsize(track
->id3
.album
, NULL
, NULL
);
881 if (cuesheet_callback
)
882 if (cuesheet_callback(filename
))
883 track
->id3
.cuesheet_type
= 1;
885 track_write_idx
= (track_write_idx
+1) & MAX_TRACK_ENTRIES_MASK
;
890 static int new_file(int steps
)
892 int max_steps
= playlist_amount();
895 struct trackdata
*track
;
897 /* Find out how many steps to advance. The load_ahead_index field tells
898 us how many playlist entries it had to skip to get to a valid one.
899 We add those together to find out where to start. */
900 if(steps
> 0 && num_tracks_in_memory() > 1)
902 /* Begin with the song after the currently playing one */
904 while((track
= get_trackdata(i
++)))
906 start
+= track
->load_ahead_index
;
913 trackname
= playlist_peek( start
+ steps
);
917 DEBUGF("Loading %s\n", trackname
);
919 mpeg_file
= open(trackname
, O_RDONLY
);
921 DEBUGF("Couldn't open file: %s\n",trackname
);
929 struct trackdata
*track
= add_track_to_tag_list(trackname
);
943 /* skip past id3v2 tag */
945 track
->id3
.first_frame_offset
,
947 track
->id3
.index
= steps
;
948 track
->load_ahead_index
= steps
;
949 track
->id3
.offset
= 0;
952 /* Average bitrate * 1.5 */
953 recalculate_watermark(
954 (track
->id3
.bitrate
* 3) / 2);
956 recalculate_watermark(
962 /* Bail out if no file could be opened */
963 if(abs(steps
) > max_steps
)
965 } while ( mpeg_file
< 0 );
970 static void stop_playing(void)
972 struct trackdata
*track
;
974 /* Stop the current stream */
979 track
= get_trackdata(0);
981 prev_track_elapsed
= track
->id3
.elapsed
;
987 generate_unbuffer_events();
991 static void end_current_track(void) {
992 struct trackdata
*track
;
994 play_pending
= false;
996 mp3_play_pause(false);
998 track
= get_trackdata(0);
1000 prev_track_elapsed
= track
->id3
.elapsed
;
1004 generate_unbuffer_events();
1010 /* Is this a really the end of playback or is a new playlist starting */
1011 static void check_playlist_end(int direction
)
1013 /* Use the largest possible step size to account for skipped tracks */
1014 int steps
= playlist_amount();
1019 if (playlist_next(steps
) < 0)
1023 static void update_playlist(void)
1025 if (num_tracks_in_memory() > 0)
1027 struct trackdata
*track
= get_trackdata(0);
1028 track
->id3
.index
= playlist_next(track
->id3
.index
);
1032 /* End of playlist? */
1033 check_playlist_end(1);
1036 playlist_update_resume_info(audio_current_track());
1039 static void track_change(void)
1041 DEBUGF("Track change\n");
1043 struct trackdata
*track
= get_trackdata(0);
1044 prev_track_elapsed
= track
->id3
.elapsed
;
1046 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
1049 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
1051 if (num_tracks_in_memory() > 0)
1053 remove_current_tag();
1054 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, audio_current_track());
1058 current_track_counter
++;
1061 unsigned long audio_prev_elapsed(void)
1063 return prev_track_elapsed
;
1067 void hexdump(const unsigned char *buf
, int len
)
1071 for(i
= 0;i
< len
;i
++)
1073 if(i
&& (i
& 15) == 0)
1077 DEBUGF("%02x ", buf
[i
]);
1083 static void start_playback_if_ready(void)
1087 playable_space
= audiobuf_swapwrite
- audiobuf_read
;
1088 if(playable_space
< 0)
1089 playable_space
+= audiobuflen
;
1091 /* See if we have started playing yet. If not, do it. */
1092 if(play_pending
|| dma_underrun
)
1094 /* If the filling has stopped, and we still haven't reached
1095 the watermark, the file must be smaller than the
1096 watermark. We must still play it. */
1097 if((playable_space
>= MPEG_PLAY_PENDING_THRESHOLD
) ||
1098 !filling
|| dma_underrun
)
1101 if (play_pending
) /* don't do this when recovering from DMA underrun */
1103 generate_postbuffer_events(); /* signal first track as buffered */
1104 if (play_pending_track_change
)
1106 play_pending_track_change
= false;
1107 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, audio_current_track());
1109 play_pending
= false;
1113 last_dma_chunk_size
= MIN(0x2000, get_unplayed_space_current_song());
1114 mp3_play_data(audiobuf
+ audiobuf_read
, last_dma_chunk_size
, transfer_end
);
1115 dma_underrun
= false;
1119 last_dma_tick
= current_tick
;
1120 mp3_play_pause(true);
1123 /* Tell ourselves that we need more data */
1124 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1129 static bool swap_one_chunk(void)
1131 int free_space_left
;
1134 free_space_left
= get_unswapped_space();
1136 if(free_space_left
== 0 && !play_pending
)
1139 /* Swap in larger chunks when the user is waiting for the playback
1140 to start, or when there is dangerously little playable data left */
1142 amount_to_swap
= MIN(MPEG_PLAY_PENDING_SWAPSIZE
, free_space_left
);
1145 if(get_playable_space() < low_watermark
)
1146 amount_to_swap
= MIN(MPEG_LOW_WATER_SWAP_CHUNKSIZE
,
1149 amount_to_swap
= MIN(MPEG_SWAP_CHUNKSIZE
, free_space_left
);
1152 if(audiobuf_write
< audiobuf_swapwrite
)
1153 amount_to_swap
= MIN(audiobuflen
- audiobuf_swapwrite
,
1156 amount_to_swap
= MIN(audiobuf_write
- audiobuf_swapwrite
,
1159 bitswap(audiobuf
+ audiobuf_swapwrite
, amount_to_swap
);
1161 audiobuf_swapwrite
+= amount_to_swap
;
1162 if(audiobuf_swapwrite
>= audiobuflen
)
1164 audiobuf_swapwrite
= 0;
1170 static void mpeg_thread(void)
1172 static int pause_tick
= 0;
1173 static unsigned int pause_track
= 0;
1174 struct queue_event ev
;
1176 int free_space_left
;
1177 int unplayed_space_left
;
1181 #if CONFIG_CODEC == MAS3587F
1183 int save_endpos
= 0;
1187 #endif /* CONFIG_CODEC == MAS3587F */
1190 play_pending
= false;
1196 #if CONFIG_CODEC == MAS3587F
1197 if(mpeg_mode
== MPEG_DECODER
)
1199 #endif /* CONFIG_CODEC == MAS3587F */
1202 /* Swap if necessary, and don't block on the queue_wait() */
1203 if(swap_one_chunk())
1205 queue_wait_w_tmo(&mpeg_queue
, &ev
, 0);
1209 /* periodically update resume info */
1210 queue_wait_w_tmo(&mpeg_queue
, &ev
, HZ
/2);
1214 DEBUGF("S R:%x W:%x SW:%x\n",
1215 audiobuf_read
, audiobuf_write
, audiobuf_swapwrite
);
1216 queue_wait(&mpeg_queue
, &ev
);
1219 start_playback_if_ready();
1224 DEBUGF("MPEG_PLAY\n");
1227 /* Silence the A/D input, it may be on because the radio
1229 mas_codec_writereg(6, 0x0000);
1230 #endif /* CONFIG_TUNER */
1232 /* Stop the current stream */
1234 end_current_track();
1236 if ( new_file(0) == -1 )
1243 start_offset
= (int)ev
.data
;
1245 /* mid-song resume? */
1247 struct mp3entry
* id3
= &get_trackdata(0)->id3
;
1248 lseek(mpeg_file
, start_offset
, SEEK_SET
);
1249 id3
->offset
= start_offset
;
1253 /* skip past id3v2 tag */
1255 get_trackdata(0)->id3
.first_frame_offset
,
1260 /* Make it read more data */
1262 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1264 /* Tell the file loading code that we want to start playing
1265 as soon as we have some data */
1266 play_pending
= true;
1267 play_pending_track_change
= true;
1270 current_track_counter
++;
1274 DEBUGF("MPEG_STOP\n");
1279 playlist_update_resume_info(audio_current_track());
1282 mpeg_stop_done
= true;
1286 DEBUGF("MPEG_PAUSE\n");
1287 /* Stop the current stream */
1289 playlist_update_resume_info(audio_current_track());
1292 pause_tick
= current_tick
;
1293 pause_track
= current_track_counter
;
1294 mp3_play_pause(false);
1298 DEBUGF("MPEG_RESUME\n");
1299 /* Continue the current stream */
1304 if ( current_track_counter
== pause_track
)
1305 last_dma_tick
+= current_tick
- pause_tick
;
1307 last_dma_tick
= current_tick
;
1309 mp3_play_pause(true);
1314 DEBUGF("MPEG_NEXT\n");
1315 /* is next track in ram? */
1316 if ( num_tracks_in_memory() > 1 ) {
1317 int unplayed_space_left
, unswapped_space_left
;
1319 /* stop the current stream */
1320 play_pending
= false;
1322 mp3_play_pause(false);
1325 audiobuf_read
= get_trackdata(0)->mempos
;
1326 last_dma_chunk_size
= MIN(0x2000, get_unplayed_space_current_song());
1327 mp3_play_data(audiobuf
+ audiobuf_read
, last_dma_chunk_size
, transfer_end
);
1328 dma_underrun
= false;
1329 last_dma_tick
= current_tick
;
1331 unplayed_space_left
= get_unplayed_space();
1332 unswapped_space_left
= get_unswapped_space();
1334 /* should we start reading more data? */
1335 if(!filling
&& (unplayed_space_left
< low_watermark
)) {
1337 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, GENERATE_UNBUFFER_EVENTS
);
1338 play_pending
= true;
1339 } else if(unswapped_space_left
&&
1340 unswapped_space_left
> unplayed_space_left
) {
1341 /* Stop swapping the data from the previous file */
1342 audiobuf_swapwrite
= audiobuf_read
;
1343 play_pending
= true;
1347 mp3_play_pause(true);
1351 if (!playlist_check(1))
1354 /* stop the current stream */
1355 end_current_track();
1357 if (new_file(1) < 0) {
1358 DEBUGF("No more files to play\n");
1361 check_playlist_end(1);
1362 current_track_counter
++;
1364 /* Make it read more data */
1366 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1368 /* Tell the file loading code that we want
1369 to start playing as soon as we have some data */
1370 play_pending
= true;
1371 play_pending_track_change
= true;
1374 current_track_counter
++;
1380 DEBUGF("MPEG_PREV\n");
1382 if (!playlist_check(-1))
1385 /* stop the current stream */
1386 end_current_track();
1388 /* Open the next file */
1389 if (new_file(-1) < 0) {
1390 DEBUGF("No more files to play\n");
1393 check_playlist_end(-1);
1394 current_track_counter
++;
1396 /* Make it read more data */
1398 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1400 /* Tell the file loading code that we want to
1401 start playing as soon as we have some data */
1402 play_pending
= true;
1403 play_pending_track_change
= true;
1406 current_track_counter
++;
1411 case MPEG_FF_REWIND
: {
1412 struct mp3entry
*id3
= audio_current_track();
1413 unsigned int oldtime
= id3
->elapsed
;
1414 unsigned int newtime
= (unsigned int)ev
.data
;
1415 int curpos
, newpos
, diffpos
;
1416 DEBUGF("MPEG_FF_REWIND\n");
1418 id3
->elapsed
= newtime
;
1420 newpos
= audio_get_file_pos();
1423 id3
->elapsed
= oldtime
;
1428 curpos
= lseek(mpeg_file
, 0, SEEK_CUR
);
1430 curpos
= id3
->filesize
;
1432 if (num_tracks_in_memory() > 1)
1434 /* We have started loading other tracks that need to be
1436 struct trackdata
*track
;
1439 while((track
= get_trackdata(i
++)))
1441 curpos
+= track
->id3
.filesize
;
1445 diffpos
= curpos
- newpos
;
1447 if(!filling
&& diffpos
>= 0 && diffpos
< audiobuflen
)
1449 int unplayed_space_left
, unswapped_space_left
;
1451 /* We are changing to a position that's already in
1452 memory, so we just move the DMA read pointer. */
1453 audiobuf_read
= audiobuf_write
- diffpos
;
1454 if (audiobuf_read
< 0)
1456 audiobuf_read
+= audiobuflen
;
1459 unplayed_space_left
= get_unplayed_space();
1460 unswapped_space_left
= get_unswapped_space();
1462 /* If unswapped_space_left is larger than
1463 unplayed_space_left, it means that the swapwrite pointer
1464 hasn't yet advanced up to the new location of the read
1465 pointer. We just move it, there is no need to swap
1466 data that won't be played anyway. */
1468 if (unswapped_space_left
> unplayed_space_left
)
1470 DEBUGF("Moved swapwrite\n");
1471 audiobuf_swapwrite
= audiobuf_read
;
1472 play_pending
= true;
1475 if (mpeg_file
>=0 && unplayed_space_left
< low_watermark
)
1477 /* We need to load more data before starting */
1479 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, GENERATE_UNBUFFER_EVENTS
);
1480 play_pending
= true;
1484 /* resume will start at new position */
1485 last_dma_chunk_size
=
1486 MIN(0x2000, get_unplayed_space_current_song());
1487 mp3_play_data(audiobuf
+ audiobuf_read
,
1488 last_dma_chunk_size
, transfer_end
);
1489 dma_underrun
= false;
1494 /* Move to the new position in the file and start
1498 if (num_tracks_in_memory() > 1)
1500 /* We have to reload the current track */
1502 remove_all_non_current_tags();
1503 generate_unbuffer_events();
1509 mpeg_file
= open(id3
->path
, O_RDONLY
);
1512 id3
->elapsed
= oldtime
;
1517 if(-1 == lseek(mpeg_file
, newpos
, SEEK_SET
))
1519 id3
->elapsed
= oldtime
;
1524 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1526 /* Tell the file loading code that we want to start playing
1527 as soon as we have some data */
1528 play_pending
= true;
1531 id3
->offset
= newpos
;
1536 case MPEG_FLUSH_RELOAD
: {
1537 int numtracks
= num_tracks_in_memory();
1538 bool reload_track
= false;
1542 /* Reset the buffer */
1543 audiobuf_write
= get_trackdata(1)->mempos
;
1545 /* Reset swapwrite unless we're still swapping current
1547 if (get_unplayed_space() <= get_playable_space())
1548 audiobuf_swapwrite
= audiobuf_write
;
1551 remove_all_non_current_tags();
1552 generate_unbuffer_events();
1554 reload_track
= true;
1556 else if (numtracks
== 1 && mpeg_file
< 0)
1558 reload_track
= true;
1561 if(reload_track
&& new_file(1) >= 0)
1563 /* Tell ourselves that we want more data */
1565 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1571 case MPEG_NEED_DATA
:
1572 free_space_left
= audiobuf_read
- audiobuf_write
;
1574 /* We interpret 0 as "empty buffer" */
1575 if(free_space_left
<= 0)
1576 free_space_left
+= audiobuflen
;
1578 unplayed_space_left
= audiobuflen
- free_space_left
;
1580 /* Make sure that we don't fill the entire buffer */
1581 free_space_left
-= MPEG_HIGH_WATER
;
1583 if (ev
.data
== GENERATE_UNBUFFER_EVENTS
)
1584 generate_unbuffer_events();
1586 /* do we have any more buffer space to fill? */
1587 if(free_space_left
<= 0)
1591 generate_postbuffer_events();
1596 /* Read small chunks while we are below the low water mark */
1597 if(unplayed_space_left
< low_watermark
)
1598 amount_to_read
= MIN(MPEG_LOW_WATER_CHUNKSIZE
,
1601 amount_to_read
= free_space_left
;
1603 /* Don't read more than until the end of the buffer */
1604 amount_to_read
= MIN(audiobuflen
- audiobuf_write
,
1606 #if (CONFIG_STORAGE & STORAGE_MMC)
1607 /* MMC is slow, so don't read too large chunks */
1608 amount_to_read
= MIN(0x40000, amount_to_read
);
1610 amount_to_read
= MIN(0x100000, amount_to_read
);
1613 /* Read as much mpeg data as we can fit in the buffer */
1618 len
= read(mpeg_file
, audiobuf
+ audiobuf_write
,
1623 DEBUGF("time: %d\n", t2
- t1
);
1624 DEBUGF("R: %x\n", len
);
1626 /* Now make sure that we don't feed the MAS with ID3V1
1628 if (len
< amount_to_read
)
1631 static const unsigned char tag
[] = "TAG";
1633 int tagptr
= audiobuf_write
+ len
- 128;
1635 /* Really rare case: entire potential tag wasn't
1636 read in this call AND audiobuf_write < 128 */
1638 tagptr
+= audiobuflen
;
1640 for(i
= 0;i
< 3;i
++)
1642 if(tagptr
>= audiobuflen
)
1643 tagptr
-= audiobuflen
;
1645 if(audiobuf
[tagptr
] != tag
[i
])
1656 /* Skip id3v1 tag */
1657 DEBUGF("Skipping ID3v1 tag\n");
1660 /* In the very rare case when the entire tag
1661 wasn't read in this read() len will be < 0.
1662 Take care of this when changing the write
1667 audiobuf_write
+= len
;
1669 if (audiobuf_write
< 0)
1670 audiobuf_write
+= audiobuflen
;
1672 if(audiobuf_write
>= audiobuflen
)
1678 /* Tell ourselves that we want more data */
1679 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1685 DEBUGF("MPEG read error\n");
1693 /* No more data to play */
1694 DEBUGF("No more files to play\n");
1699 /* Tell ourselves that we want more data */
1700 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1706 case MPEG_TRACK_CHANGE
:
1711 case SYS_USB_CONNECTED
:
1716 /* Tell the USB thread that we are safe */
1717 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
1718 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1720 /* Wait until the USB cable is extracted again */
1721 usb_wait_for_disconnect(&mpeg_queue
);
1723 #endif /* !USB_NONE */
1725 #if CONFIG_CODEC == MAS3587F
1726 case MPEG_INIT_RECORDING
:
1728 init_recording_done
= true;
1730 #endif /* CONFIG_CODEC == MAS3587F */
1734 playlist_update_resume_info(audio_current_track());
1737 #if CONFIG_CODEC == MAS3587F
1741 queue_wait(&mpeg_queue
, &ev
);
1745 if (is_prerecording
)
1749 /* Go back prerecord_count seconds in the buffer */
1750 startpos
= prerecord_index
- prerecord_count
;
1752 startpos
+= prerecording_max_seconds
;
1754 /* Read the position data from the prerecord buffer */
1755 frame_count_start
= prerecord_buffer
[startpos
].framecount
;
1756 startpos
= prerecord_buffer
[startpos
].mempos
;
1758 DEBUGF("Start looking at address %x (%x)\n",
1759 audiobuf
+startpos
, startpos
);
1761 saved_header
= mpeg_get_last_header();
1763 mem_find_next_frame(startpos
, &offset
, 1800,
1766 audiobuf_read
= startpos
+ offset
;
1767 if(audiobuf_read
>= audiobuflen
)
1768 audiobuf_read
-= audiobuflen
;
1770 DEBUGF("New audiobuf_read address: %x (%x)\n",
1771 audiobuf
+audiobuf_read
, audiobuf_read
);
1773 level
= disable_irq_save();
1774 num_rec_bytes
= get_unsaved_space();
1779 frame_count_start
= 0;
1781 audiobuf_read
= MPEG_RESERVED_HEADER_SPACE
;
1782 audiobuf_write
= MPEG_RESERVED_HEADER_SPACE
;
1786 DEBUGF("Recording...\n");
1789 /* Wait until at least one frame is encoded and get the
1790 frame header, for later use by the Xing header
1793 saved_header
= mpeg_get_last_header();
1795 /* delayed until buffer is saved, don't open yet */
1796 strcpy(delayed_filename
, recording_filename
);
1802 DEBUGF("MPEG_STOP\n");
1806 /* Save the remaining data in the buffer */
1807 save_endpos
= audiobuf_write
;
1808 saving_status
= STOP_RECORDING
;
1809 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1812 case MPEG_STOP_DONE
:
1813 DEBUGF("MPEG_STOP_DONE\n");
1823 for(i
= 0;i
< 512;i
++)
1825 DEBUGF("%d - %d us (%d bytes)\n",
1827 (timing_info
[i
*2+1] & 0xffff) *
1829 timing_info
[i
*2+1] >> 16);
1836 start_prerecording();
1838 mpeg_stop_done
= true;
1842 /* Bail out when a more important save is happening */
1843 if (saving_status
> NEW_FILE
)
1846 /* Make sure we have at least one complete frame
1847 in the buffer. If we haven't recorded a single
1848 frame within 200ms, the MAS is probably not recording
1849 anything, and we bail out. */
1850 amount_to_save
= get_unsaved_space();
1851 if (amount_to_save
< 1800)
1854 amount_to_save
= get_unsaved_space();
1857 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_FRAME_COUNT
,
1858 &frame_count_end
, 1);
1860 last_rec_time
= current_tick
- record_start_time
;
1861 record_start_time
= current_tick
;
1863 pause_start_time
= record_start_time
;
1865 /* capture all values at one point */
1866 level
= disable_irq_save();
1867 save_endpos
= audiobuf_write
;
1868 last_rec_bytes
= num_rec_bytes
;
1872 if (amount_to_save
>= 1800)
1874 /* Now find a frame boundary to split at */
1875 save_endpos
-= 1800;
1876 if (save_endpos
< 0)
1877 save_endpos
+= audiobuflen
;
1879 rc
= mem_find_next_frame(save_endpos
, &offset
, 1800,
1881 if (!rc
) /* No header found, save whole buffer */
1884 save_endpos
+= offset
;
1885 if (save_endpos
>= audiobuflen
)
1886 save_endpos
-= audiobuflen
;
1888 last_rec_bytes
+= offset
- 1800;
1889 level
= disable_irq_save();
1890 num_rec_bytes
+= 1800 - offset
;
1894 saving_status
= NEW_FILE
;
1895 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1898 case MPEG_SAVE_DATA
:
1899 if (saving_status
== BUFFER_FULL
)
1900 save_endpos
= audiobuf_write
;
1902 if (mpeg_file
< 0) /* delayed file open */
1904 mpeg_file
= open(delayed_filename
, O_WRONLY
|O_CREAT
);
1907 panicf("recfile: %d", mpeg_file
);
1910 amount_to_save
= save_endpos
- audiobuf_read
;
1911 if (amount_to_save
< 0)
1912 amount_to_save
+= audiobuflen
;
1914 amount_to_save
= MIN(amount_to_save
,
1915 audiobuflen
- audiobuf_read
);
1916 #if (CONFIG_STORAGE & STORAGE_MMC)
1917 /* MMC is slow, so don't save too large chunks at once */
1918 amount_to_save
= MIN(0x40000, amount_to_save
);
1920 amount_to_save
= MIN(0x100000, amount_to_save
);
1922 rc
= write(mpeg_file
, audiobuf
+ audiobuf_read
,
1926 if (errno
== ENOSPC
)
1928 mpeg_errno
= AUDIOERR_DISK_FULL
;
1930 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1931 /* will close the file */
1935 panicf("rec wrt: %d", rc
);
1938 audiobuf_read
+= amount_to_save
;
1939 if (audiobuf_read
>= audiobuflen
)
1942 if (audiobuf_read
== save_endpos
) /* all saved */
1944 switch (saving_status
)
1947 rc
= fsync(mpeg_file
);
1949 panicf("rec fls: %d", rc
);
1954 /* Close the current file */
1955 rc
= close(mpeg_file
);
1957 panicf("rec cls: %d", rc
);
1962 /* copy new filename */
1963 strcpy(delayed_filename
, recording_filename
);
1965 frame_count_start
= frame_count_end
;
1968 case STOP_RECORDING
:
1969 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1970 /* will close the file */
1976 saving_status
= NOT_SAVING
;
1978 else /* tell ourselves to save the next chunk */
1979 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1983 case MPEG_PRERECORDING_TICK
:
1984 if(!is_prerecording
)
1987 /* Store the write pointer every second */
1988 prerecord_buffer
[prerecord_index
].mempos
= audiobuf_write
;
1989 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_FRAME_COUNT
,
1990 &prerecord_buffer
[prerecord_index
].framecount
, 1);
1992 /* Wrap if necessary */
1993 if(++prerecord_index
== prerecording_max_seconds
)
1994 prerecord_index
= 0;
1996 /* Update the number of seconds recorded */
1997 if(prerecord_count
< prerecording_max_seconds
)
2001 case MPEG_INIT_PLAYBACK
:
2002 /* Stop the prerecording */
2006 init_playback_done
= true;
2009 case MPEG_PAUSE_RECORDING
:
2013 case MPEG_RESUME_RECORDING
:
2017 case SYS_USB_CONNECTED
:
2018 /* We can safely go to USB mode if no recording
2020 if((!is_recording
|| is_prerecording
) && mpeg_stop_done
)
2022 /* Even if we aren't recording, we still call this
2023 function, to put the MAS in monitoring mode,
2027 /* Tell the USB thread that we are safe */
2028 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
2029 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
2031 /* Wait until the USB cable is extracted again */
2032 usb_wait_for_disconnect(&mpeg_queue
);
2037 #endif /* CONFIG_CODEC == MAS3587F */
2040 #endif /* !SIMULATOR */
2042 struct mp3entry
* audio_current_track()
2046 #else /* !SIMULATOR */
2047 if(num_tracks_in_memory())
2048 return &get_trackdata(0)->id3
;
2051 #endif /* !SIMULATOR */
2054 struct mp3entry
* audio_next_track()
2058 #else /* !SIMULATOR */
2059 if(num_tracks_in_memory() > 1)
2060 return &get_trackdata(1)->id3
;
2063 #endif /* !SIMULATOR */
2066 bool audio_has_changed_track(void)
2068 if(last_track_counter
!= current_track_counter
)
2070 last_track_counter
= current_track_counter
;
2076 #if CONFIG_CODEC == MAS3587F
2078 void audio_init_playback(void)
2080 init_playback_done
= false;
2081 queue_post(&mpeg_queue
, MPEG_INIT_PLAYBACK
, 0);
2083 while(!init_playback_done
)
2088 /****************************************************************************
2089 * Recording functions
2090 ***************************************************************************/
2091 void audio_init_recording(unsigned int buffer_offset
)
2093 buffer_offset
= buffer_offset
;
2094 init_recording_done
= false;
2095 queue_post(&mpeg_queue
, MPEG_INIT_RECORDING
, 0);
2097 while(!init_recording_done
)
2101 static void init_recording(void)
2113 /* Init the recording variables */
2114 is_recording
= false;
2115 is_prerecording
= false;
2117 mpeg_stop_done
= true;
2121 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2122 rc
= mas_direct_config_write(MAS_CONTROL
, 0x8c00);
2124 panicf("mas_ctrl_w: %d", rc
);
2126 /* Stop the current application */
2128 mas_writemem(MAS_BANK_D0
, MAS_D0_APP_SELECT
, &val
, 1);
2131 mas_readmem(MAS_BANK_D0
, MAS_D0_APP_RUNNING
, &val
, 1);
2134 /* Perform black magic as described by the data sheet */
2135 if((mas_version_code
& 0x0fff) == 0x0102)
2137 DEBUGF("Performing MAS black magic for B2 version\n");
2138 mas_writereg(0xa3, 0x98);
2139 mas_writereg(0x94, 0xfffff);
2141 mas_writemem(MAS_BANK_D1
, 0, &val
, 1);
2142 mas_writereg(0xa3, 0x90);
2145 /* Enable A/D Converters */
2146 shadow_codec_reg0
= 0xcccd;
2147 mas_codec_writereg(0x0, shadow_codec_reg0
);
2149 /* Copy left channel to right (mono mode) */
2150 mas_codec_writereg(8, 0x8000);
2152 /* ADC scale 0%, DSP scale 100%
2153 We use the DSP output for monitoring, because it works with all
2154 sources including S/PDIF */
2155 mas_codec_writereg(6, 0x0000);
2156 mas_codec_writereg(7, 0x4000);
2159 shadow_soft_mute
= 0;
2160 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2162 #ifdef HAVE_SPDIF_OUT
2163 val
= 0x09; /* Disable SDO and SDI, low impedance S/PDIF outputs */
2165 val
= 0x2d; /* Disable SDO and SDI, disable S/PDIF output */
2167 mas_writemem(MAS_BANK_D0
, MAS_D0_INTERFACE_CONTROL
, &val
, 1);
2169 /* Set Demand mode, monitoring OFF and validate all settings */
2170 shadow_io_control_main
= 0x125;
2171 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2173 /* Start the encoder application */
2175 mas_writemem(MAS_BANK_D0
, MAS_D0_APP_SELECT
, &val
, 1);
2178 mas_readmem(MAS_BANK_D0
, MAS_D0_APP_RUNNING
, &val
, 1);
2179 } while(!(val
& 0x40));
2181 /* We have started the recording application with monitoring OFF.
2182 This is because we want to record at least one frame to fill the DMA
2183 buffer, because the silly MAS will not negate EOD until at least one
2184 DMA transfer has taken place.
2185 Now let's wait for some data to be encoded. */
2188 /* Now set it to Monitoring mode as default, saves power */
2189 shadow_io_control_main
= 0x525;
2190 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2192 /* Wait until the DSP has accepted the settings */
2195 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2199 mpeg_mode
= MPEG_ENCODER
;
2201 DEBUGF("MAS Recording application started\n");
2203 /* At this point, all settings are the reset MAS defaults, next thing is to
2204 call mpeg_set_recording_options(). */
2207 void audio_record(const char *filename
)
2211 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
2212 recording_filename
[MAX_PATH
- 1] = 0;
2214 queue_post(&mpeg_queue
, MPEG_RECORD
, 0);
2217 void audio_pause_recording(void)
2219 queue_post(&mpeg_queue
, MPEG_PAUSE_RECORDING
, 0);
2222 void audio_resume_recording(void)
2224 queue_post(&mpeg_queue
, MPEG_RESUME_RECORDING
, 0);
2227 static void prepend_header(void)
2232 /* Make room for header */
2233 audiobuf_read
-= MPEG_RESERVED_HEADER_SPACE
;
2234 if(audiobuf_read
< 0)
2236 /* Clear the bottom half */
2237 memset(audiobuf
, 0, audiobuf_read
+ MPEG_RESERVED_HEADER_SPACE
);
2239 /* And the top half */
2240 audiobuf_read
+= audiobuflen
;
2241 memset(audiobuf
+ audiobuf_read
, 0, audiobuflen
- audiobuf_read
);
2245 memset(audiobuf
+ audiobuf_read
, 0, MPEG_RESERVED_HEADER_SPACE
);
2247 /* Copy the empty ID3 header */
2248 startpos
= audiobuf_read
;
2249 for(i
= 0; i
< sizeof(empty_id3_header
); i
++)
2251 audiobuf
[startpos
++] = empty_id3_header
[i
];
2252 if(startpos
== audiobuflen
)
2257 static void update_header(void)
2260 unsigned long frames
;
2262 if (last_rec_bytes
> 0)
2264 /* Create the Xing header */
2265 fd
= open(delayed_filename
, O_RDWR
);
2267 panicf("rec upd: %d (%s)", fd
, recording_filename
);
2269 frames
= frame_count_end
- frame_count_start
;
2270 /* If the number of recorded frames has reached 0x7ffff,
2271 we can no longer trust it */
2272 if (frame_count_end
== 0x7ffff)
2275 /* saved_header is saved right before stopping the MAS */
2276 framelen
= create_xing_header(fd
, 0, last_rec_bytes
, xing_buffer
,
2277 frames
, last_rec_time
* (1000/HZ
),
2278 saved_header
, NULL
, false);
2280 lseek(fd
, MPEG_RESERVED_HEADER_SPACE
- framelen
, SEEK_SET
);
2281 write(fd
, xing_buffer
, framelen
);
2286 static void start_prerecording(void)
2290 DEBUGF("Starting prerecording\n");
2292 prerecord_index
= 0;
2293 prerecord_count
= 0;
2294 prerecord_timeout
= current_tick
+ HZ
;
2295 memset(prerecord_buffer
, 0, sizeof(prerecord_buffer
));
2298 is_prerecording
= true;
2300 /* Stop monitoring and start the encoder */
2301 shadow_io_control_main
&= ~(1 << 10);
2302 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2303 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2305 /* Wait until the DSP has accepted the settings */
2308 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2311 is_recording
= true;
2312 saving_status
= NOT_SAVING
;
2314 demand_irq_enable(true);
2317 static void start_recording(void)
2323 /* This will make the IRQ handler start recording
2324 for real, i.e send MPEG_SAVE_DATA messages when
2325 the buffer is full */
2326 is_prerecording
= false;
2330 /* If prerecording is off, we need to stop the monitoring
2331 and start the encoder */
2332 shadow_io_control_main
&= ~(1 << 10);
2333 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2334 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2336 /* Wait until the DSP has accepted the settings */
2339 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2343 is_recording
= true;
2344 saving_status
= NOT_SAVING
;
2347 /* Store the current time */
2349 record_start_time
= current_tick
- prerecord_count
* HZ
;
2351 record_start_time
= current_tick
;
2353 pause_start_time
= 0;
2355 demand_irq_enable(true);
2358 static void pause_recording(void)
2360 pause_start_time
= current_tick
;
2362 /* Set the pause bit */
2363 shadow_soft_mute
|= 2;
2364 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2369 static void resume_recording(void)
2373 /* Clear the pause bit */
2374 shadow_soft_mute
&= ~2;
2375 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2377 /* Compensate for the time we have been paused */
2378 if(pause_start_time
)
2381 current_tick
- (pause_start_time
- record_start_time
);
2382 pause_start_time
= 0;
2386 static void stop_recording(void)
2390 /* Let it finish the last frame */
2395 demand_irq_enable(false);
2397 is_recording
= false;
2398 is_prerecording
= false;
2400 last_rec_bytes
= num_rec_bytes
;
2401 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_FRAME_COUNT
, &frame_count_end
, 1);
2402 last_rec_time
= current_tick
- record_start_time
;
2404 /* Start monitoring */
2405 shadow_io_control_main
|= (1 << 10);
2406 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2407 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2409 /* Wait until the DSP has accepted the settings */
2412 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2418 void audio_set_recording_options(struct audio_recording_options
*options
)
2422 is_mpeg1
= (options
->rec_frequency
< 3)?true:false;
2424 rec_version_index
= is_mpeg1
?3:2;
2425 rec_frequency_index
= options
->rec_frequency
% 3;
2427 shadow_encoder_control
= (options
->rec_quality
<< 17) |
2428 (rec_frequency_index
<< 10) |
2429 ((is_mpeg1
?1:0) << 9) |
2430 (((options
->rec_channels
* 2 + 1) & 3) << 6) |
2431 (1 << 5) /* MS-stereo */ |
2432 (1 << 2) /* Is an original */;
2433 mas_writemem(MAS_BANK_D0
, MAS_D0_ENCODER_CONTROL
, &shadow_encoder_control
,1);
2435 DEBUGF("mas_writemem(MAS_BANK_D0, ENCODER_CONTROL, %x)\n", shadow_encoder_control
);
2437 #if CONFIG_TUNER & S1A0903X01
2438 /* Store the (unpitched) MAS PLL frequency. Used for avoiding FM
2439 interference with the Samsung tuner. */
2440 if (rec_frequency_index
)
2441 mas_store_pllfreq(24576000);
2443 mas_store_pllfreq(22579000);
2446 shadow_soft_mute
= options
->rec_editable
?4:0;
2447 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
,1);
2449 DEBUGF("mas_writemem(MAS_BANK_D0, SOFT_MUTE, %x)\n", shadow_soft_mute
);
2451 shadow_io_control_main
= ((1 << 10) | /* Monitoring ON */
2452 ((options
->rec_source
< 2)?1:2) << 8) | /* Input select */
2453 (1 << 5) | /* SDO strobe invert */
2454 ((is_mpeg1
?0:1) << 3) |
2455 (1 << 2) | /* Inverted SIBC clock signal */
2457 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
,1);
2459 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2461 if(options
->rec_source
== AUDIO_SRC_MIC
)
2463 /* Copy left channel to right (mono mode) */
2464 mas_codec_writereg(8, 0x8000);
2468 /* Stereo input mode */
2469 mas_codec_writereg(8, 0);
2472 prerecording_max_seconds
= options
->rec_prerecord_time
;
2473 if(prerecording_max_seconds
)
2475 prerecording
= true;
2476 start_prerecording();
2480 prerecording
= false;
2481 is_prerecording
= false;
2482 is_recording
= false;
2486 /* If use_mic is true, the left gain is used */
2487 void audio_set_recording_gain(int left
, int right
, int type
)
2489 /* Enable both left and right A/D */
2490 shadow_codec_reg0
= (left
<< 12) |
2493 (type
==AUDIO_GAIN_MIC
?0x0008:0) | /* Connect left A/D to mic */
2495 mas_codec_writereg(0x0, shadow_codec_reg0
);
2498 /* try to make some kind of beep, also in recording mode */
2499 void audio_beep(int duration
)
2501 long starttick
= current_tick
;
2503 { /* toggle bit 0 of codec register 0, toggling the DAC off & on.
2504 * While this is still audible even without an external signal,
2505 * it doesn't affect the (pre-)recording. */
2506 mas_codec_writereg(0, shadow_codec_reg0
^ 1);
2507 mas_codec_writereg(0, shadow_codec_reg0
);
2510 while (current_tick
- starttick
< duration
);
2513 void audio_new_file(const char *filename
)
2517 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
2518 recording_filename
[MAX_PATH
- 1] = 0;
2520 queue_post(&mpeg_queue
, MPEG_NEW_FILE
, 0);
2523 unsigned long audio_recorded_time(void)
2526 return prerecord_count
* HZ
;
2531 return pause_start_time
- record_start_time
;
2533 return current_tick
- record_start_time
;
2539 unsigned long audio_num_recorded_bytes(void)
2548 index
= prerecord_index
- prerecord_count
;
2550 index
+= prerecording_max_seconds
;
2552 num_bytes
= audiobuf_write
- prerecord_buffer
[index
].mempos
;
2554 num_bytes
+= audiobuflen
;
2559 return num_rec_bytes
;
2565 #else /* SIMULATOR */
2567 /* dummies coming up */
2569 void audio_init_playback(void)
2573 unsigned long audio_recorded_time(void)
2578 void audio_beep(int duration
)
2583 void audio_pause_recording(void)
2587 void audio_resume_recording(void)
2591 unsigned long audio_num_recorded_bytes(void)
2596 void audio_record(const char *filename
)
2601 void audio_new_file(const char *filename
)
2607 void audio_set_recording_gain(int left
, int right
, int type
)
2614 void audio_init_recording(unsigned int buffer_offset
)
2617 (void)buffer_offset
;
2619 void audio_set_recording_options(struct audio_recording_options
*options
)
2624 #endif /* SIMULATOR */
2625 #endif /* CONFIG_CODEC == MAS3587F */
2627 void audio_play(long offset
)
2636 trackname
= playlist_peek( steps
);
2639 if(mp3info(&taginfo
, trackname
)) {
2640 /* bad mp3, move on */
2641 if(++steps
> playlist_amount())
2645 #ifdef HAVE_MPEG_PLAY
2646 real_mpeg_play(trackname
);
2648 playlist_next(steps
);
2649 taginfo
.offset
= offset
;
2650 set_elapsed(&taginfo
);
2655 #else /* !SIMULATOR */
2658 queue_post(&mpeg_queue
, MPEG_PLAY
, offset
);
2659 #endif /* !SIMULATOR */
2664 void audio_stop(void)
2669 struct trackdata
*track
= get_trackdata(0);
2670 prev_track_elapsed
= track
->id3
.elapsed
;
2672 mpeg_stop_done
= false;
2673 queue_post(&mpeg_queue
, MPEG_STOP
, 0);
2674 while(!mpeg_stop_done
)
2676 #else /* SIMULATOR */
2680 #endif /* SIMULATOR */
2684 void audio_stop_recording(void)
2689 void audio_pause(void)
2692 queue_post(&mpeg_queue
, MPEG_PAUSE
, 0);
2693 #else /* SIMULATOR */
2697 #endif /* SIMULATOR */
2700 void audio_resume(void)
2703 queue_post(&mpeg_queue
, MPEG_RESUME
, 0);
2704 #else /* SIMULATOR */
2708 #endif /* SIMULATOR */
2711 void audio_next(void)
2714 queue_remove_from_head(&mpeg_queue
, MPEG_NEED_DATA
);
2715 queue_post(&mpeg_queue
, MPEG_NEXT
, 0);
2716 #else /* SIMULATOR */
2722 file
= playlist_peek(steps
);
2725 if(mp3info(&taginfo
, file
)) {
2726 if(++steps
> playlist_amount())
2730 index
= playlist_next(steps
);
2731 taginfo
.index
= index
;
2732 current_track_counter
++;
2737 #endif /* SIMULATOR */
2740 void audio_prev(void)
2743 queue_remove_from_head(&mpeg_queue
, MPEG_NEED_DATA
);
2744 queue_post(&mpeg_queue
, MPEG_PREV
, 0);
2745 #else /* SIMULATOR */
2751 file
= playlist_peek(steps
);
2754 if(mp3info(&taginfo
, file
)) {
2758 index
= playlist_next(steps
);
2759 taginfo
.index
= index
;
2760 current_track_counter
++;
2765 #endif /* SIMULATOR */
2768 void audio_ff_rewind(long newtime
)
2771 queue_post(&mpeg_queue
, MPEG_FF_REWIND
, newtime
);
2772 #else /* SIMULATOR */
2774 #endif /* SIMULATOR */
2777 void audio_flush_and_reload_tracks(void)
2780 queue_post(&mpeg_queue
, MPEG_FLUSH_RELOAD
, 0);
2781 #endif /* !SIMULATOR*/
2784 int audio_status(void)
2789 ret
|= AUDIO_STATUS_PLAY
;
2792 ret
|= AUDIO_STATUS_PAUSE
;
2794 #if (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR)
2795 if(is_recording
&& !is_prerecording
)
2796 ret
|= AUDIO_STATUS_RECORD
;
2799 ret
|= AUDIO_STATUS_PRERECORD
;
2800 #endif /* CONFIG_CODEC == MAS3587F */
2803 ret
|= AUDIO_STATUS_ERROR
;
2808 unsigned int audio_error(void)
2813 void audio_error_clear(void)
2819 static void mpeg_thread(void)
2821 struct mp3entry
* id3
;
2824 id3
= audio_current_track();
2830 if (id3
->elapsed
>=id3
->length
)
2836 #endif /* SIMULATOR */
2838 void audio_init(void)
2843 audiobuflen
= audiobufend
- audiobuf
;
2844 queue_init(&mpeg_queue
, true);
2845 #endif /* !SIMULATOR */
2846 create_thread(mpeg_thread
, mpeg_stack
,
2847 sizeof(mpeg_stack
), 0, mpeg_thread_name
2848 IF_PRIO(, PRIORITY_SYSTEM
)
2851 memset(trackdata
, sizeof(trackdata
), 0);
2853 #if (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR)
2854 if (HW_MASK
& PR_ACTIVE_HIGH
)
2855 and_b(~0x08, &PADRH
);
2858 #endif /* CONFIG_CODEC == MAS3587F */
2864 #endif /* !SIMULATOR */
2868 #endif /* CONFIG_CODEC != SWCODEC */