1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Michiel Van Der Kolk 2005-03-28 00:00:24 +00:00
parent 853bc3dcf8
commit 451dd48adc
11 changed files with 208 additions and 62 deletions

View file

@ -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;
}

View file

@ -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)

View file

@ -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
};

View file

@ -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
};

View file

@ -9,7 +9,7 @@ struct pcm
{
int hz, len;
int stereo;
byte *buf;
short *buf;
int pos;
};

View file

@ -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
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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);