summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichiel Van Der Kolk <not.valid@email.address>2005-03-28 00:00:24 +0000
committerMichiel Van Der Kolk <not.valid@email.address>2005-03-28 00:00:24 +0000
commit451dd48adc2ef29fd2f900693393cc9b9b4a849b (patch)
treee15d20e602261866617210bde007966ce9b19293
parent853bc3dcf85aa1284a0e5b550277c40beb7697a9 (diff)
downloadrockbox-451dd48adc2ef29fd2f900693393cc9b9b4a849b.zip
rockbox-451dd48adc2ef29fd2f900693393cc9b9b4a849b.tar.gz
rockbox-451dd48adc2ef29fd2f900693393cc9b9b4a849b.tar.bz2
rockbox-451dd48adc2ef29fd2f900693393cc9b9b4a849b.tar.xz
Sound api improvements, rockboy sound, contributed by xshock.
Playback of sound currently only works in boost mode, needs fixing. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6226 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/debug_menu.c35
-rw-r--r--apps/main.c7
-rw-r--r--apps/plugin.c8
-rw-r--r--apps/plugin.h7
-rw-r--r--apps/plugins/rockboy/pcm.h2
-rw-r--r--apps/plugins/rockboy/rbsound.c111
-rw-r--r--apps/plugins/rockboy/rockboy.c4
-rw-r--r--apps/plugins/rockboy/sound.c12
-rw-r--r--firmware/drivers/uda1380.c4
-rw-r--r--firmware/export/pcm_playback.h2
-rw-r--r--firmware/pcm_playback.c78
11 files changed, 208 insertions, 62 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 9d5028a..74d1cb9 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -169,27 +169,29 @@ static void test_get_more(unsigned char **ptr, long *size)
bool uda1380_test(void)
{
long button;
- int vol = 0x7f;
+ int vol = 0x50;
bool done = false;
lcd_setmargins(0, 0);
lcd_clear_display();
lcd_update();
+ cpu_boost(true);
if (load_wave("/sample.wav") == -1)
goto exit;
audio_pos = 0;
+ puts("Playing..");
puts("uda1380_init");
if (uda1380_init() == -1)
{
- puts("Init failed..");
- goto exit;
+ puts("UDA1380 init failed");
}
- puts("Playing..");
audio_pos = 0;
+ pcm_set_frequency(44100);
+ pcm_set_volume(0xff - vol);
pcm_play_data(audio_buffer, CHUNK_SIZE,
test_get_more);
@@ -224,6 +226,7 @@ bool uda1380_test(void)
exit:
sleep(HZ >> 1); /* Sleep 1/2 second to fade out sound */
+ cpu_boost(false);
return false;
}
@@ -1247,10 +1250,9 @@ bool view_battery(void)
lcd_puts(0, 3, buf);
#endif
#ifdef HAVE_CHARGE_CTRL
- snprintf(buf, 30, "Chgr: %s %s",
- charger_inserted() ? "present" : "absent",
- charger_enabled ? "on" : "off");
- lcd_puts(0, 3, buf);
+ snprintf(buf, 30, "Charging: %s",
+ charger_enabled ? "yes" : "no");
+ lcd_puts(0, 4, buf);
snprintf(buf, 30, "short delta: %d", short_delta);
lcd_puts(0, 5, buf);
snprintf(buf, 30, "long delta: %d", long_delta);
@@ -1272,7 +1274,7 @@ bool view_battery(void)
}
break;
- case 3: /* remaining time estimation: */
+ case 3: /* remeining time estimation: */
lcd_clear_display();
#ifdef HAVE_CHARGE_CTRL
@@ -1284,24 +1286,23 @@ bool view_battery(void)
snprintf(buf, 30, "Lvl@cyc st: %d%%", powermgmt_last_cycle_level);
lcd_puts(0, 2, buf);
-
- snprintf(buf, 30, "P=%2d I=%2d", pid_p, pid_i);
- lcd_puts(0, 3, buf);
-
- snprintf(buf, 30, "Trickle sec: %d/60", trickle_sec);
- lcd_puts(0, 4, buf);
#endif
snprintf(buf, 30, "Last PwrHist: %d.%02d V",
power_history[0] / 100,
power_history[0] % 100);
- lcd_puts(0, 5, buf);
+ lcd_puts(0, 3, buf);
snprintf(buf, 30, "battery level: %d%%", battery_level());
- lcd_puts(0, 6, buf);
+ lcd_puts(0, 5, buf);
snprintf(buf, 30, "Est. remain: %d m", battery_time());
+ lcd_puts(0, 6, buf);
+
+#ifdef HAVE_CHARGE_CTRL
+ snprintf(buf, 30, "Trickle sec: %d/60", trickle_sec);
lcd_puts(0, 7, buf);
+#endif
break;
}
diff --git a/apps/main.c b/apps/main.c
index c5e5492..36f26c9 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -58,6 +58,10 @@
#include "power.h"
#include "talk.h"
#include "plugin.h"
+
+
+#include "uda1380.h"
+
#ifdef CONFIG_TUNER
#include "radio.h"
#endif
@@ -261,6 +265,9 @@ void init(void)
}
}
#endif /* #ifdef AUTOROCK */
+
+ uda1380_init();
+
}
int main(void)
diff --git a/apps/plugin.c b/apps/plugin.c
index b4239bb..ecd5025 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -44,7 +44,7 @@
#include "mp3data.h"
#include "powermgmt.h"
#include "system.h"
-#if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR)
+#if (CONFIG_HWCODEC == MASNONE)
#include "pcm_playback.h"
#endif
@@ -271,10 +271,12 @@ static const struct plugin_api rockbox_api = {
#if CONFIG_KEYPAD == IRIVER_H100_PAD
button_hold,
#endif
-#if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR)
- pcm_play_data,
+#if (CONFIG_HWCODEC == MASNONE)
+ pcm_play_data,
pcm_play_stop,
+ pcm_set_frequency,
pcm_is_playing,
+ pcm_set_volume
#endif
};
diff --git a/apps/plugin.h b/apps/plugin.h
index 3755018..30ecfc7 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -43,6 +43,7 @@
#include "id3.h"
#include "mpeg.h"
#include "mp3_playback.h"
+#include "pcm_playback.h"
#include "settings.h"
#include "thread.h"
#include "playlist.h"
@@ -317,11 +318,13 @@ struct plugin_api {
#if CONFIG_KEYPAD == IRIVER_H100_PAD
bool (*button_hold)(void);
#endif
-#if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR)
+#if (CONFIG_HWCODEC == MASNONE)
void (*pcm_play_data)(const unsigned char *start, int size,
void (*get_more)(unsigned char** start, long*size));
- void (*pcm_play_stop)(void);
+ void (*pcm_play_stop)(void);
+ void (*pcm_set_frequency)(unsigned int frequency);
bool (*pcm_is_playing)(void);
+ void (*pcm_set_volume)(int volume);
#endif
};
diff --git a/apps/plugins/rockboy/pcm.h b/apps/plugins/rockboy/pcm.h
index 3719933..742f0e5 100644
--- a/apps/plugins/rockboy/pcm.h
+++ b/apps/plugins/rockboy/pcm.h
@@ -9,7 +9,7 @@ struct pcm
{
int hz, len;
int stereo;
- byte *buf;
+ short *buf;
int pos;
};
diff --git a/apps/plugins/rockboy/rbsound.c b/apps/plugins/rockboy/rbsound.c
index 6d1b24f..92f824a 100644
--- a/apps/plugins/rockboy/rbsound.c
+++ b/apps/plugins/rockboy/rbsound.c
@@ -1,47 +1,120 @@
-
-
-
#include "rockmacros.h"
#include "defs.h"
#include "pcm.h"
#include "rc.h"
+#define RBSOUND
struct pcm pcm;
-static byte buf[4096];
+#define BUF_SIZE (8192)
+#define DMA_PORTION (1024)
+
+static short buf1_unal[(BUF_SIZE / sizeof(short)) + 2]; // to make sure 4 byte aligned
+static short* buf1;
+static short front_buf[512];
+
+static short* last_back_pos;
+
+static bool newly_started;
+static int turns;
rcvar_t pcm_exports[] =
{
- RCV_END
+ RCV_END
};
-
void pcm_init(void)
{
- pcm.hz = 44100;
- pcm.stereo = 1;
- pcm.buf = buf;
- pcm.len = sizeof buf;
- pcm.pos = 0;
+ buf1 = (signed short*)((((unsigned int)buf1_unal) >> 2) << 2); /* here i just make sure that buffer is aligned to 4 bytes*/
+ newly_started = true;
+ last_back_pos = buf1;
+ turns = 0;
+
+ pcm.hz = 11025;
+ pcm.stereo = 1;
+ pcm.buf = front_buf;
+ pcm.len = (sizeof(front_buf)) / sizeof(short); /* length in shorts, not bytes */
+ pcm.pos = 0;
+
+
+ rb->pcm_play_stop();
+ rb->pcm_set_frequency(11025);
+ rb->pcm_set_volume(200);
}
void pcm_close(void)
{
- memset(&pcm, 0, sizeof pcm);
+ memset(&pcm, 0, sizeof pcm);
+ newly_started = true;
+ last_back_pos = buf1;
+ rb->pcm_play_stop();
}
+void get_more(unsigned char** start, long* size)
+{
+ int length;
+ unsigned int sar = (unsigned int)SAR0;
+ length = ((unsigned int)buf1) + BUF_SIZE - sar;
+
+ if(turns > 0)
+ {
+ newly_started = true;
+ last_back_pos = buf1;
+ turns = 0;
+ return;
+ } /* sound will stop if no one feeds data*/
+
+ if(length <= 0)
+ {
+ *start = (unsigned char*)buf1;
+ *size = DMA_PORTION;
+ turns++;
+ }
+ else
+ {
+ *start = (unsigned char*)sar;
+ if(length > DMA_PORTION)
+ *size = DMA_PORTION;
+ else
+ *size = length;
+ }
+
+}
+
int pcm_submit(void)
{
-#ifdef RBSOUND
- rb->pcm_play_data(pcm.buf,pcm.pos,NULL);
- while(rb->pcm_is_playing()); /* spinlock */
- pcm.pos = 0;
- return 1;
+#ifdef RBSOUND
+ while( (turns < 0) && ((((unsigned int)last_back_pos) + pcm.pos * sizeof(short)) > ((unsigned int)SAR0)) && !newly_started) rb->yield(); /* wait until data is passed through DAC or until exit*/
+ int shorts_left = ((((unsigned int)buf1) + BUF_SIZE) - ((unsigned int)last_back_pos)) / sizeof(short);
+ if( shorts_left >= pcm.pos )
+ {
+ memcpy(last_back_pos,pcm.buf,pcm.pos * sizeof(short));
+ last_back_pos = &last_back_pos[pcm.pos];
+ }
+ else
+ {
+ int last_pos = shorts_left;
+ memcpy(last_back_pos,pcm.buf,shorts_left * sizeof(short));
+ last_back_pos = buf1;
+ shorts_left = pcm.pos - shorts_left;
+ memcpy(last_back_pos,&pcm.buf[last_pos],shorts_left * sizeof(short));
+ last_back_pos = &buf1[shorts_left];
+ turns--;
+ }
+
+ if(newly_started)
+ {
+ rb->pcm_play_data((unsigned char*)buf1,pcm.pos * sizeof(short),&get_more);
+ newly_started = false;
+ }
+
+ pcm.pos = 0;
+ return 1;
#else
- pcm.pos = 0;
- return 0;
+ pcm.pos = 0;
+ return 0;
#endif
}
diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c
index a34fd7b..c6d006a 100644
--- a/apps/plugins/rockboy/rockboy.c
+++ b/apps/plugins/rockboy/rockboy.c
@@ -51,6 +51,7 @@ struct plugin_api* rb;
int shut,cleanshut;
char *errormsg;
int gnuboy_main(char *rom);
+void pcm_close(void);
void die(char *message, ...)
{
@@ -124,10 +125,11 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
rb->splash(HZ*2, true, errormsg);
return PLUGIN_ERROR;
}
-
+ pcm_close();
rb->splash(HZ*2, true, "Shutting down.. byebye ^^");
cleanup();
+
return PLUGIN_OK;
}
diff --git a/apps/plugins/rockboy/sound.c b/apps/plugins/rockboy/sound.c
index edf31d8..10fc504 100644
--- a/apps/plugins/rockboy/sound.c
+++ b/apps/plugins/rockboy/sound.c
@@ -60,9 +60,9 @@ int pcm_submit(void);
#define S4 (snd.ch[3])
rcvar_t sound_exports[] =
- {
- RCV_END
- };
+{
+ RCV_END
+};
static void s1_freq_d(int d)
@@ -275,10 +275,10 @@ void sound_mix(void)
pcm_submit();
if (pcm.stereo)
{
- pcm.buf[pcm.pos++] = l+128;
- pcm.buf[pcm.pos++] = r+128;
+ pcm.buf[pcm.pos++] = (signed short)(l * 256);
+ pcm.buf[pcm.pos++] = (signed short)(r * 256);
}
- else pcm.buf[pcm.pos++] = ((l+r)>>1)+128;
+ else pcm.buf[pcm.pos++] = (signed short)((r+l) * 128);
}
}
R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3);
diff --git a/firmware/drivers/uda1380.c b/firmware/drivers/uda1380.c
index e8b8c14..8c3cf61 100644
--- a/firmware/drivers/uda1380.c
+++ b/firmware/drivers/uda1380.c
@@ -49,7 +49,7 @@ unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] =
REG_I2S, I2S_IFMT_IIS,
REG_PWR, PON_PLL | PON_HP | PON_DAC | EN_AVC | PON_AVC | PON_BIAS,
REG_AMIX, AMIX_RIGHT(0x10) | AMIX_LEFT(0x10), /* 00=max, 3f=mute */
- REG_MASTER_VOL, MASTER_VOL_LEFT(0x7f) | MASTER_VOL_RIGHT(0x7f), /* 00=max, ff=mute */
+ REG_MASTER_VOL, MASTER_VOL_LEFT(0x20) | MASTER_VOL_RIGHT(0x20), /* 00=max, ff=mute */
REG_MIX_VOL, MIX_VOL_CHANNEL_1(0) | MIX_VOL_CHANNEL_2(0xff), /* 00=max, ff=mute */
REG_EQ, 0,
REG_MUTE, MUTE_CH2, /* Mute channel 2 (digital decimation filter) */
@@ -131,6 +131,8 @@ int uda1380_set_regs(void)
/* Initialize UDA1380 codec with default register values (uda1380_defaults) */
int uda1380_init(void)
{
+ PLLCR &= ~(1 << 22); /* Set AudioClk = FXTAL/2*/
+
if (uda1380_set_regs() == -1)
return -1;
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h
index c44fb28..6010293 100644
--- a/firmware/export/pcm_playback.h
+++ b/firmware/export/pcm_playback.h
@@ -19,9 +19,11 @@
#ifndef PCM_PLAYBACK_H
#define PCM_PLAYBACK_H
+void pcm_set_frequency(unsigned int frequency);
void pcm_play_data(const unsigned char* start, int size,
void (*get_more)(unsigned char** start, long* size));
void pcm_play_stop(void);
bool pcm_is_playing(void);
+void pcm_set_volume(int volume);
#endif
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index fba85f0..bc2218b 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -37,20 +37,32 @@
#include "file.h"
#include "buffer.h"
-bool pcm_playing;
+#include "sprintf.h"
+#include "button.h"
+#include <string.h>
+
+static bool pcm_playing;
+static int pcm_freq = 0x6; // 44.1 in default
/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
-static void dma_start(const void *addr, long size)
-{
+static void dma_start(const void *addr_r, long size)
+{
pcm_playing = 1;
+ int i;
+
+ int align;
+ align = 4;
+
+ void* addr = (void*)((((unsigned int)addr_r) >> 2) << 2); // always align data, never pass unaligned data
+ size = (size >> 2) << 2; // size shoudl also be always multiple of 4
BUSMASTER_CTRL = 0x81; /* PARK[1,0]=10 + BCR24BIT */
/* Set up DMA transfer */
DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */
- SAR0 = (unsigned long)addr; /* Source address */
+ SAR0 = ((unsigned long)addr) + align*4; /* Source address */
DAR0 = (unsigned long)&PDOR3; /* Destination address */
- BCR0 = size; /* Bytes to transfer */
+ BCR0 = size-(align*4); /* Bytes to transfer */
DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1;
DMACONFIG = 1; /* Enable DMA0Req => set DMAROUTE |= DMA0_REQ_AUDIO_1 */
@@ -61,14 +73,10 @@ static void dma_start(const void *addr, long size)
ICR4 = (ICR4 & 0xffff00ff) | 0x00001c00;
IMR &= ~(1<<14); /* bit 14 is DMA0 */
- IIS2CONFIG = 0x4300; /* CLOCKSEL = AudioClk/8 (44.1kHz),
- data source = PDOR3 */
+ IIS2CONFIG = (pcm_freq << 12) | 0x300; /* CLOCKSEL for right frequency + data source = PDOR3 */
- PDOR3 = 0; /* These are needed to generate FIFO empty request to DMA.. */
- PDOR3 = 0;
- PDOR3 = 0;
- PDOR3 = 0;
- PDOR3 = 0;
+ for(i = 0; i < align; i++)
+ PDOR3 = ((unsigned int*)(addr))[i]; /* These are needed to generate FIFO empty request to DMA.. */
}
/* Stops the DMA transfer and interrupt */
@@ -76,12 +84,51 @@ static void dma_stop(void)
{
pcm_playing = 0;
DCR0 = 0;
+
+/* DMAROUTE &= 0xffffff00;
+ DMACONFIG = 0;*/
+
+ IIS2CONFIG = 0x800;
/* Disable DMA0 interrupt */
IMR |= (1<<14);
ICR4 &= 0xffff00ff;
}
+
+/* set volume of the main channel */
+void pcm_set_volume(int volume)
+{
+ if(volume > 0)
+ {
+ uda1380_mute(0);
+ uda1380_setvol(0xff - volume);
+ }
+ else
+ {
+ uda1380_mute(1);
+ }
+}
+
+/* sets frequency of input to DAC */
+void pcm_set_frequency(unsigned int frequency)
+{
+ switch(frequency)
+ {
+ case 11025:
+ pcm_freq = 0x2;
+ break;
+ case 22050:
+ pcm_freq = 0x4;
+ break;
+ case 44100:
+ pcm_freq = 0x6;
+ break;
+ default:
+ pcm_freq = 0x6;
+ }
+}
+
/* the registered callback function to ask for more mp3 data */
static void (*callback_for_more)(unsigned char**, long*) = NULL;
@@ -110,8 +157,15 @@ void DMA0(void)
unsigned char* start;
long size = 0;
+ int res = DSR0;
+
DSR0 = 1; /* Clear interrupt */
+ if(res == 0x41)
+ {
+ dma_stop();
+ }
+
if (callback_for_more)
{
callback_for_more(&start, &size);