summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörg Hohensohn <hohensoh@rockbox.org>2004-01-10 15:39:56 +0000
committerJörg Hohensohn <hohensoh@rockbox.org>2004-01-10 15:39:56 +0000
commitec5d44627fb8a409c445741264cc4f2995a17721 (patch)
tree757a89bd1a7bff52f302df77c5db22bb63759c34
parent1e32b94441afd344a250efec1450c86a83c297d1 (diff)
downloadrockbox-ec5d44627fb8a409c445741264cc4f2995a17721.zip
rockbox-ec5d44627fb8a409c445741264cc4f2995a17721.tar.gz
rockbox-ec5d44627fb8a409c445741264cc4f2995a17721.tar.bz2
rockbox-ec5d44627fb8a409c445741264cc4f2995a17721.tar.xz
next round of playback function split: everything in place, working and used; except for the playtime
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4218 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/mp3_playback.h8
-rw-r--r--firmware/export/mpeg.h4
-rw-r--r--firmware/mp3_playback.c156
-rw-r--r--firmware/mpeg.c276
4 files changed, 256 insertions, 188 deletions
diff --git a/firmware/export/mp3_playback.h b/firmware/export/mp3_playback.h
index 2767092..3c190f2 100644
--- a/firmware/export/mp3_playback.h
+++ b/firmware/export/mp3_playback.h
@@ -40,6 +40,12 @@ int mpeg_sound_numdecimals(int setting);
void mpeg_set_pitch(int percent);
#endif
+
+/* exported just for mpeg.c, to keep the recording there */
+#ifdef HAVE_MAS3587F
+void demand_irq_enable(bool on);
+#endif
+
/* new functions, to be exported to plugin API */
void mp3_play_init(void);
void mp3_play_data(unsigned char* start, int size,
@@ -47,6 +53,8 @@ void mp3_play_data(unsigned char* start, int size,
);
void mp3_play_pause(bool play);
void mp3_play_stop(void);
+long mp3_get_playtime(void);
+void mp3_reset_playtime(void);
#define SOUND_VOLUME 0
diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h
index 2a629f4..ff003e6 100644
--- a/firmware/export/mpeg.h
+++ b/firmware/export/mpeg.h
@@ -90,6 +90,10 @@ void mpeg_set_buffer_margin(int seconds);
unsigned int mpeg_error(void);
void mpeg_error_clear(void);
+/* in order to keep the recording here, I have to expose this */
+void rec_tick(void);
+void playback_tick(void); /* FixMe: get rid of this, use mp3_get_playtime() */
+
#define MPEG_STATUS_PLAY 1
#define MPEG_STATUS_PAUSE 2
#define MPEG_STATUS_RECORD 4
diff --git a/firmware/mp3_playback.c b/firmware/mp3_playback.c
index 9930f10..fe16676 100644
--- a/firmware/mp3_playback.c
+++ b/firmware/mp3_playback.c
@@ -34,6 +34,30 @@
#include "hwcompat.h"
#endif
+/* hacking into mpeg.c, recording is still there */
+#ifdef HAVE_MAS3587F
+enum
+{
+ MPEG_DECODER,
+ MPEG_ENCODER
+} mpeg_mode;
+#endif /* #ifdef HAVE_MAS3587F */
+
+/**** globals ****/
+
+/* own version, independent of mpeg.c */
+static bool paused; /* playback is paused */
+static bool playing; /* We are playing an MP3 stream */
+
+#ifndef SIMULATOR
+/* for measuring the play time */
+static long playstart_tick;
+static long cumulative_ticks;
+
+/* the registered callback function to ask for more mp3 data */
+static void (*callback_for_more)(unsigned char**, int*);
+#endif /* #ifndef SIMULATOR */
+
static char *units[] =
{
"%", /* Volume */
@@ -283,10 +307,65 @@ static void mas_poll_start(int interval_in_ms)
TSTR |= 0x02; /* Start timer 1 */
}
+#else
+static void postpone_dma_tick(void)
+{
+ unsigned int count;
+
+ count = FREQ / 1000 / 8;
+
+ /* We are using timer 1 */
+
+ TSTR &= ~0x02; /* Stop the timer */
+ TSNC &= ~0x02; /* No synchronization */
+ TMDR &= ~0x02; /* Operate normally */
+
+ TCNT1 = 0; /* Start counting at 0 */
+ GRA1 = count;
+ TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
+
+ /* Enable interrupt on level 5 */
+ IPRC = (IPRC & ~0x000f) | 0x0005;
+
+ TSR1 &= ~0x02;
+ TIER1 = 0xf9; /* Enable GRA match interrupt */
+
+ TSTR |= 0x02; /* Start timer 1 */
+}
#endif
-/* the registered callback function ta ask for more mp3 data */
-static void (*callback_for_more)(unsigned char**, int*);
+
+#ifdef HAVE_MAS3587F
+void demand_irq_enable(bool on)
+{
+ int oldlevel = set_irq_level(15);
+
+ if(on)
+ {
+ IPRA = (IPRA & 0xfff0) | 0x000b;
+ ICR &= ~0x0010; /* IRQ3 level sensitive */
+ }
+ else
+ IPRA &= 0xfff0;
+
+ set_irq_level(oldlevel);
+}
+#endif /* #ifdef HAVE_MAS3587F */
+
+
+void play_tick(void)
+{
+ if(playing && !paused)
+ {
+ /* Start DMA if it is disabled and the DEMAND pin is high */
+ if(!(SCR0 & 0x80) && (PBDR & 0x4000))
+ {
+ SCR0 |= 0x80;
+ }
+
+ playback_tick(); /* dirty call to mpeg.c */
+ }
+}
#pragma interrupt
void DEI3(void)
@@ -313,10 +392,36 @@ void DEI3(void)
}
#pragma interrupt
+void IMIA1(void) /* Timer 1 interrupt */
+{
+ if(playing)
+ play_tick();
+ TSR1 &= ~0x01;
+#ifdef HAVE_MAS3587F
+ /* Disable interrupt */
+ IPRC &= ~0x000f;
+#endif /* #ifdef HAVE_MAS3587F */
+}
+
+#pragma interrupt
void IRQ6(void) /* PB14: MAS stop demand IRQ */
{
- mp3_play_pause(false);
+ SCR0 &= ~0x80;
+}
+
+#ifdef HAVE_MAS3587F
+#pragma interrupt
+void IRQ3(void) /* PA15: MAS demand IRQ */
+{
+ /* Begin with setting the IRQ to edge sensitive */
+ ICR |= 0x0010;
+
+ if(mpeg_mode == MPEG_ENCODER)
+ rec_tick();
+ else
+ postpone_dma_tick();
}
+#endif /* #ifdef HAVE_MAS3587F */
static void setup_sci0(void)
{
@@ -404,6 +509,8 @@ static void init_playback(void)
mpeg_sound_channel_config(MPEG_SOUND_STEREO);
+ mpeg_mode = MPEG_DECODER;
+
/* set IRQ6 to edge detect */
ICR |= 0x02;
@@ -893,6 +1000,9 @@ void mp3_init(int volume, int bass, int treble, int balance, int loudness,
mpeg_sound_set(SOUND_AVC, avc);
#endif
#endif /* !SIMULATOR */
+
+ playing = false;
+ paused = true;
}
@@ -905,7 +1015,10 @@ void mp3_play_init(void)
#ifdef HAVE_MAS3587F
init_playback();
#endif
+ playing = false;
+ paused = true;
callback_for_more = NULL;
+ mp3_reset_playtime();
}
void mp3_play_data(unsigned char* start, int size,
@@ -923,21 +1036,54 @@ void mp3_play_data(unsigned char* start, int size,
SAR3 = (unsigned int)start;
DTCR3 = size & 0xffff;
+ playing = true;
+ paused = true;
+
CHCR3 |= 0x0001; /* Enable DMA IRQ */
+
+#ifdef HAVE_MAS3587F
+ demand_irq_enable(true);
+#endif
}
void mp3_play_pause(bool play)
{
- if (play)
+ if (paused && play)
+ { /* resume playback */
SCR0 |= 0x80;
- else
+ paused = false;
+ playstart_tick = current_tick;
+ }
+ else if (!paused && !play)
+ { /* stop playback */
SCR0 &= 0x7f;
+ paused = true;
+ cumulative_ticks += current_tick - playstart_tick;
+ }
}
void mp3_play_stop(void)
{
+ playing = false;
mp3_play_pause(false);
CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
+#ifdef HAVE_MAS3587F
+ demand_irq_enable(false);
+#endif
+}
+
+long mp3_get_playtime(void)
+{
+ if (paused)
+ return cumulative_ticks;
+ else
+ return cumulative_ticks + current_tick - playstart_tick;
+}
+
+void mp3_reset_playtime(void)
+{
+ cumulative_ticks = 0;
+ playstart_tick = current_tick;
}
#endif /* #ifndef SIMULATOR */
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 29836dd..12d71a1 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -74,7 +74,7 @@ static int get_unswapped_space(void);
#define MPEG_STOP_DONE 103
#ifdef HAVE_MAS3587F
-static enum
+extern enum /* from mp3_playback.c */
{
MPEG_DECODER,
MPEG_ENCODER
@@ -371,33 +371,6 @@ void mpeg_get_debugdata(struct mpeg_debug *dbgdata)
dbgdata->lowest_watermark_level = lowest_watermark_level;
}
-#ifndef HAVE_MAS3507D
-static void postpone_dma_tick(void)
-{
- unsigned int count;
-
- count = FREQ / 1000 / 8;
-
- /* We are using timer 1 */
-
- TSTR &= ~0x02; /* Stop the timer */
- TSNC &= ~0x02; /* No synchronization */
- TMDR &= ~0x02; /* Operate normally */
-
- TCNT1 = 0; /* Start counting at 0 */
- GRA1 = count;
- TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
-
- /* Enable interrupt on level 5 */
- IPRC = (IPRC & ~0x000f) | 0x0005;
-
- TSR1 &= ~0x02;
- TIER1 = 0xf9; /* Enable GRA match interrupt */
-
- TSTR |= 0x02; /* Start timer 1 */
-}
-#endif /* #ifndef HAVE_MAS3507D */
-
#ifdef DEBUG
static void dbg_timer_start(void)
{
@@ -524,134 +497,122 @@ static void drain_dma_buffer(void)
#endif /* #ifdef HAVE_MAS3587F */
-static void dma_tick (void) __attribute__ ((section (".icode")));
-static void dma_tick(void)
+void rec_tick (void) __attribute__ ((section (".icode")));
+void rec_tick(void)
{
#ifdef HAVE_MAS3587F
- if(mpeg_mode == MPEG_DECODER)
- {
-#endif /* #ifdef HAVE_MAS3587F */
- if(playing && !paused)
- {
- /* Start DMA if it is disabled and the DEMAND pin is high */
- if(!(SCR0 & 0x80) && (PBDR & 0x4000))
- {
- mp3_play_pause(true);
- }
- id3tags[tag_read_idx]->id3.elapsed +=
- (current_tick - last_dma_tick) * 1000 / HZ;
- last_dma_tick = current_tick;
- }
-#ifdef HAVE_MAS3587F
- }
- else /* MPEG_ENCODER */
+ int i;
+ int num_bytes;
+ if(is_recording && (PBDR & 0x4000))
{
- int i;
- int num_bytes;
- if(is_recording && (PBDR & 0x4000))
- {
#ifdef DEBUG
- timing_info[timing_info_index++] = current_tick;
- TCNT2 = 0;
+ timing_info[timing_info_index++] = current_tick;
+ TCNT2 = 0;
#endif /* #ifdef DEBUG */
- /* We read as long as EOD is high, but max 30 bytes.
- This code is optimized, and should probably be
- written in assembler instead. */
- if(inverted_pr)
+ /* We read as long as EOD is high, but max 30 bytes.
+ This code is optimized, and should probably be
+ written in assembler instead. */
+ if(inverted_pr)
+ {
+ i = 0;
+ while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
+ && i < 30)
{
- i = 0;
- while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
- && i < 30)
- {
- or_b(0x08, &PADRH);
+ or_b(0x08, &PADRH);
- while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
-
- /* It must take at least 5 cycles before
- the data is read */
- asm(" nop\n nop\n nop\n");
- mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;
-
- if(mp3buf_write >= mp3buflen)
- mp3buf_write = 0;
+ while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
+
+ /* It must take at least 5 cycles before
+ the data is read */
+ asm(" nop\n nop\n nop\n");
+ mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;
+
+ if(mp3buf_write >= mp3buflen)
+ mp3buf_write = 0;
- i++;
-
- and_b(~0x08, &PADRH);
+ i++;
+
+ and_b(~0x08, &PADRH);
- /* No wait for /RTW, cause it's not necessary */
- }
+ /* No wait for /RTW, cause it's not necessary */
}
- else /* !inverted_pr */
+ }
+ else /* !inverted_pr */
+ {
+ i = 0;
+ while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
+ && i < 30)
{
- i = 0;
- while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
- && i < 30)
- {
- and_b(~0x08, &PADRH);
-
- while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
-
- /* It must take at least 5 cycles before
- the data is read */
- asm(" nop\n nop\n nop\n");
- mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;
-
- if(mp3buf_write >= mp3buflen)
- mp3buf_write = 0;
+ and_b(~0x08, &PADRH);
+
+ while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
+
+ /* It must take at least 5 cycles before
+ the data is read */
+ asm(" nop\n nop\n nop\n");
+ mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;
+
+ if(mp3buf_write >= mp3buflen)
+ mp3buf_write = 0;
- i++;
-
- or_b(0x08, &PADRH);
+ i++;
+
+ or_b(0x08, &PADRH);
- /* No wait for /RTW, cause it's not necessary */
- }
+ /* No wait for /RTW, cause it's not necessary */
}
+ }
#ifdef DEBUG
- timing_info[timing_info_index++] = TCNT2 + (i << 16);
- timing_info_index &= 0x3ff;
+ timing_info[timing_info_index++] = TCNT2 + (i << 16);
+ timing_info_index &= 0x3ff;
#endif /* #ifdef DEBUG */
- num_rec_bytes += i;
-
- if(is_prerecording)
+ num_rec_bytes += i;
+
+ if(is_prerecording)
+ {
+ if(TIME_AFTER(current_tick, prerecord_timeout))
{
- if(TIME_AFTER(current_tick, prerecord_timeout))
- {
- prerecord_timeout = current_tick + HZ;
+ prerecord_timeout = current_tick + HZ;
- /* Store the write pointer every second */
- prerecord_buffer[prerecord_index++] = mp3buf_write;
+ /* Store the write pointer every second */
+ prerecord_buffer[prerecord_index++] = mp3buf_write;
- /* Wrap if necessary */
- if(prerecord_index == prerecording_max_seconds)
- prerecord_index = 0;
+ /* Wrap if necessary */
+ if(prerecord_index == prerecording_max_seconds)
+ prerecord_index = 0;
- /* Update the number of seconds recorded */
- if(prerecord_count < prerecording_max_seconds)
- prerecord_count++;
- }
+ /* Update the number of seconds recorded */
+ if(prerecord_count < prerecording_max_seconds)
+ prerecord_count++;
}
- else
+ }
+ else
+ {
+ /* Signal to save the data if we are running out of buffer
+ space */
+ num_bytes = mp3buf_write - mp3buf_read;
+ if(num_bytes < 0)
+ num_bytes += mp3buflen;
+
+ if(mp3buflen - num_bytes < MPEG_RECORDING_LOW_WATER && !saving)
{
- /* Signal to save the data if we are running out of buffer
- space */
- num_bytes = mp3buf_write - mp3buf_read;
- if(num_bytes < 0)
- num_bytes += mp3buflen;
-
- if(mp3buflen - num_bytes < MPEG_RECORDING_LOW_WATER && !saving)
- {
- saving = true;
- queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
- wake_up_thread();
- }
+ saving = true;
+ queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
+ wake_up_thread();
}
}
}
#endif /* #ifdef HAVE_MAS3587F */
}
+void playback_tick(void)
+{
+ id3tags[tag_read_idx]->id3.elapsed +=
+ (current_tick - last_dma_tick) * 1000 / HZ;
+ last_dma_tick = current_tick;
+}
+
static void reset_mp3_buffer(void)
{
mp3buf_read = 0;
@@ -751,48 +712,6 @@ static void transfer_end(unsigned char** ppbuf, int* psize)
wake_up_thread();
}
-#ifdef HAVE_MAS3587F
-static void demand_irq_enable(bool on)
-{
- int oldlevel = set_irq_level(15);
-
- if(on)
- {
- IPRA = (IPRA & 0xfff0) | 0x000b;
- ICR &= ~0x0010; /* IRQ3 level sensitive */
- }
- else
- IPRA &= 0xfff0;
-
- set_irq_level(oldlevel);
-}
-#endif /* #ifdef HAVE_MAS3587F */
-
-#pragma interrupt
-void IMIA1(void) /* Timer 1 interrupt */
-{
- dma_tick();
- TSR1 &= ~0x01;
-#ifdef HAVE_MAS3587F
- /* Disable interrupt */
- IPRC &= ~0x000f;
-#endif /* #ifdef HAVE_MAS3587F */
-}
-
-#ifdef HAVE_MAS3587F
-#pragma interrupt
-void IRQ3(void) /* PA15: MAS demand IRQ */
-{
- /* Begin with setting the IRQ to edge sensitive */
- ICR |= 0x0010;
-
- if(mpeg_mode == MPEG_ENCODER)
- dma_tick();
- else
- postpone_dma_tick();
-}
-#endif /* #ifdef HAVE_MAS3587F */
-
static int add_track_to_tag_list(char *filename)
{
struct id3tag *t = NULL;
@@ -892,15 +811,12 @@ static int new_file(int steps)
static void stop_playing(void)
{
/* Stop the current stream */
-#ifdef HAVE_MAS3587F
- demand_irq_enable(false);
-#endif /* #ifdef HAVE_MAS3587F */
+ mp3_play_stop();
playing = false;
filling = false;
if(mpeg_file >= 0)
close(mpeg_file);
mpeg_file = -1;
- mp3_play_pause(false);
remove_all_tags();
}
@@ -967,17 +883,14 @@ static void start_playback_if_ready(void)
play_pending = false;
playing = true;
- last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
- mp3_play_data(mp3buf + mp3buf_read, last_dma_chunk_size, transfer_end);
- dma_underrun = false;
-
if (!paused)
{
+ last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
+ mp3_play_data(mp3buf + mp3buf_read, last_dma_chunk_size, transfer_end);
+ dma_underrun = false;
+
last_dma_tick = current_tick;
mp3_play_pause(true);
-#ifdef HAVE_MAS3587F
- demand_irq_enable(true);
-#endif /* #ifdef HAVE_MAS3587F */
}
/* Tell ourselves that we need more data */
@@ -2002,10 +1915,7 @@ static void mpeg_thread(void)
case MPEG_INIT_PLAYBACK:
/* Stop the prerecording */
stop_recording();
-
mp3_play_init();
- mpeg_mode = MPEG_DECODER;
-
init_playback_done = true;
break;