From 402502fc6f11c3cb6e224e90ecfb30d5a5147a63 Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Mon, 14 Oct 2002 14:13:13 +0000 Subject: Swapping is now done without the MPEG_SWAP message. Added some debugging functionality git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2623 a1c6a512-1295-4272-9138-f99709370657 --- firmware/mpeg.c | 185 ++++++++++++++++++++++++++++++++------------------------ firmware/mpeg.h | 21 +++++++ 2 files changed, 128 insertions(+), 78 deletions(-) diff --git a/firmware/mpeg.c b/firmware/mpeg.c index f149814dac..d7e7acbf92 100644 --- a/firmware/mpeg.c +++ b/firmware/mpeg.c @@ -37,11 +37,15 @@ extern void bitswap(unsigned char *data, int length); -#define MPEG_CHUNKSIZE 0x180000 -#define MPEG_SWAP_CHUNKSIZE 0x8000 -#define MPEG_HIGH_WATER 2 +static int get_unplayed_space(void); +static int get_unswapped_space(void); + +#define MPEG_SWAP_CHUNKSIZE 0x2000 +#define MPEG_HIGH_WATER 2 /* We leave 2 bytes empty because otherwise we + wouldn't be able to see the difference between + an empty buffer and a full one. */ #define MPEG_LOW_WATER 0x40000 -#define MPEG_LOW_WATER_CHUNKSIZE 0x10000 +#define MPEG_LOW_WATER_CHUNKSIZE 0x40000 #define MPEG_PLAY 1 #define MPEG_STOP 2 @@ -52,8 +56,7 @@ extern void bitswap(unsigned char *data, int length); #define MPEG_FF_REWIND 7 #define MPEG_FLUSH_RELOAD 8 #define MPEG_NEED_DATA 100 -#define MPEG_SWAP_DATA 101 -#define MPEG_TRACK_CHANGE 102 +#define MPEG_TRACK_CHANGE 101 extern char* playlist_peek(int steps); extern int playlist_next(int steps); @@ -439,6 +442,26 @@ static bool dma_underrun; /* True when the DMA has stopped because of static int mpeg_file; +void mpeg_get_debugdata(struct mpeg_debug *dbgdata) +{ + dbgdata->mp3buflen = mp3buflen; + dbgdata->mp3buf_write = mp3buf_write; + dbgdata->mp3buf_swapwrite = mp3buf_swapwrite; + dbgdata->mp3buf_read = mp3buf_read; + + dbgdata->last_dma_chunk_size = last_dma_chunk_size; + + dbgdata->dma_on = dma_on; + dbgdata->playing = playing; + dbgdata->play_pending = play_pending; + dbgdata->is_playing = is_playing; + dbgdata->filling = filling; + dbgdata->dma_underrun = dma_underrun; + + dbgdata->unplayed_space = get_unplayed_space(); + dbgdata->unswapped_space = get_unswapped_space(); +} + static void mas_poll_start(int interval_in_ms) { unsigned int count; @@ -480,8 +503,8 @@ static void dbg_timer_start(void) TSNC &= ~0x04; /* No synchronization */ TMDR &= ~0x44; /* Operate normally */ - TCNT1 = 0; /* Start counting at 0 */ - TCR1 = 0x03; /* Sysclock/8 */ + TCNT2 = 0; /* Start counting at 0 */ + TCR2 = 0x03; /* Sysclock/8 */ TSTR |= 0x04; /* Start timer 2 */ } @@ -492,7 +515,7 @@ static int dbg_cnt2us(unsigned int cnt) } #endif -int get_unplayed_space(void) +static int get_unplayed_space(void) { int space = mp3buf_write - mp3buf_read; if (space < 0) @@ -815,6 +838,65 @@ void hexdump(unsigned char *buf, int len) } #endif +static void swap_one_chunk(void) +{ + int free_space_left; + int amount_to_swap; + int t1, t2; + + free_space_left = get_unswapped_space(); + + if(free_space_left == 0 && !play_pending) + return; + + amount_to_swap = MIN(MPEG_SWAP_CHUNKSIZE, free_space_left); + if(mp3buf_write < mp3buf_swapwrite) + amount_to_swap = MIN(mp3buflen - mp3buf_swapwrite, + amount_to_swap); + else + amount_to_swap = MIN(mp3buf_write - mp3buf_swapwrite, + amount_to_swap); + + DEBUGF("B %x\n", amount_to_swap); + t1 = current_tick; + bitswap(mp3buf + mp3buf_swapwrite, amount_to_swap); + t2 = current_tick; + DEBUGF("time: %d\n", t2 - t1); + + mp3buf_swapwrite += amount_to_swap; + if(mp3buf_swapwrite >= mp3buflen) + { + mp3buf_swapwrite = 0; + DEBUGF("BW\n"); + } + + /* And while we're at it, see if we have started + playing yet. If not, do it. */ + if(play_pending || dma_underrun) + { + /* If the filling has stopped, and we still haven't reached + the watermark, the file must be smaller than the + watermark. We must still play it. */ + if(((mp3buf_swapwrite - mp3buf_read) >= MPEG_LOW_WATER) || + !filling) + { + DEBUGF("P\n"); + play_pending = false; + playing = true; + + init_dma(); + if (!paused) + { + last_dma_tick = current_tick; + start_dma(); + } + + /* Tell ourselves that we need more data */ + queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); + } + } +} + static void mpeg_thread(void) { static int pause_tick = 0; @@ -824,7 +906,6 @@ static void mpeg_thread(void) int free_space_left; int unplayed_space_left; int amount_to_read; - int amount_to_swap; int t1, t2; int start_offset; @@ -838,7 +919,18 @@ static void mpeg_thread(void) DEBUGF("S R:%x W:%x SW:%x\n", mp3buf_read, mp3buf_write, mp3buf_swapwrite); yield(); - queue_wait(&mpeg_queue, &ev); + + /* Swap if necessary, and don't block on the queue_wait() */ + if(get_unswapped_space()) + { + swap_one_chunk(); + queue_wait_w_tmo(&mpeg_queue, &ev, 0); + } + else + { + queue_wait(&mpeg_queue, &ev); + } + switch(ev.id) { case MPEG_PLAY: @@ -1221,64 +1313,6 @@ static void mpeg_thread(void) break; } - case MPEG_SWAP_DATA: - free_space_left = get_unswapped_space(); - - if(free_space_left == 0 && !play_pending) - break; - - amount_to_swap = MIN(MPEG_SWAP_CHUNKSIZE, free_space_left); - if(mp3buf_write < mp3buf_swapwrite) - amount_to_swap = MIN(mp3buflen - mp3buf_swapwrite, - amount_to_swap); - else - amount_to_swap = MIN(mp3buf_write - mp3buf_swapwrite, - amount_to_swap); - - DEBUGF("B %x\n", amount_to_swap); - t1 = current_tick; - bitswap(mp3buf + mp3buf_swapwrite, amount_to_swap); - t2 = current_tick; - DEBUGF("time: %d\n", t2 - t1); - - mp3buf_swapwrite += amount_to_swap; - if(mp3buf_swapwrite >= mp3buflen) - { - mp3buf_swapwrite = 0; - DEBUGF("BW\n"); - } - - /* Tell ourselves that we must swap more data */ - queue_post(&mpeg_queue, MPEG_SWAP_DATA, 0); - - /* And while we're at it, see if we have started - playing yet. If not, do it. */ - if(play_pending || dma_underrun) - { - /* If the filling has stopped, and we still haven't reached - the watermark, the file must be smaller than the - watermark. We must still play it. */ - if(((mp3buf_swapwrite - mp3buf_read) >= MPEG_LOW_WATER) || - !filling) - { - DEBUGF("P\n"); - play_pending = false; - playing = true; - - init_dma(); - if (!paused) - { - last_dma_tick = current_tick; - start_dma(); - } - - /* Tell ourselves that we need more data */ - queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); - - } - } - break; - case MPEG_NEED_DATA: free_space_left = mp3buf_read - mp3buf_write; @@ -1289,7 +1323,7 @@ static void mpeg_thread(void) unplayed_space_left = mp3buflen - free_space_left; /* Make sure that we don't fill the entire buffer */ - free_space_left -= 2; + free_space_left -= MPEG_HIGH_WATER; /* do we have any more buffer space to fill? */ if(free_space_left <= MPEG_HIGH_WATER) @@ -1305,15 +1339,12 @@ static void mpeg_thread(void) amount_to_read = MIN(MPEG_LOW_WATER_CHUNKSIZE, free_space_left); else - amount_to_read = MIN(MPEG_CHUNKSIZE, free_space_left); + amount_to_read = free_space_left; /* Don't read more than until the end of the buffer */ amount_to_read = MIN(mp3buflen - mp3buf_write, amount_to_read); - - /* Read in a few seconds worth of MP3 data. We don't want to - read too large chunks because the bitswapping will take - too much time. We must keep the DMA happy and also give - the other threads a chance to run. */ + + /* Read as much mpeg data as we can fit in the buffer */ if(mpeg_file >= 0) { DEBUGF("R\n"); @@ -1325,8 +1356,6 @@ static void mpeg_thread(void) t2 = current_tick; DEBUGF("time: %d\n", t2 - t1); DEBUGF("R: %x\n", len); - /* Tell ourselves that we need to swap some data */ - queue_post(&mpeg_queue, MPEG_SWAP_DATA, 0); /* Make sure that the write pointer is at a word boundary when we reach the end of the file */ diff --git a/firmware/mpeg.h b/firmware/mpeg.h index 4a92a2fbe9..97a1b36c1a 100644 --- a/firmware/mpeg.h +++ b/firmware/mpeg.h @@ -21,6 +21,26 @@ #include +struct mpeg_debug +{ + int mp3buflen; + int mp3buf_write; + int mp3buf_swapwrite; + int mp3buf_read; + + int last_dma_chunk_size; + + bool dma_on; + bool playing; + bool play_pending; + bool is_playing; + bool filling; + bool dma_underrun; + + int unplayed_space; + int unswapped_space; +}; + void mpeg_init(int volume, int bass, int treble, int balance, int loudness, int bass_boost, int avc); void mpeg_play(int offset); @@ -46,6 +66,7 @@ int mpeg_status(void); #ifdef HAVE_MAS3587F void mpeg_set_pitch(int percent); #endif +void mpeg_get_debugdata(struct mpeg_debug *dbgdata); #define SOUND_VOLUME 0 #define SOUND_BASS 1 -- cgit