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:
parent
853bc3dcf8
commit
451dd48adc
11 changed files with 208 additions and 62 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
#if (CONFIG_HWCODEC == MASNONE)
|
||||
pcm_play_data,
|
||||
pcm_play_stop,
|
||||
pcm_set_frequency,
|
||||
pcm_is_playing,
|
||||
pcm_set_volume
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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_set_frequency)(unsigned int frequency);
|
||||
bool (*pcm_is_playing)(void);
|
||||
void (*pcm_set_volume)(int volume);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ struct pcm
|
|||
{
|
||||
int hz, len;
|
||||
int stereo;
|
||||
byte *buf;
|
||||
short *buf;
|
||||
int pos;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -77,11 +85,50 @@ 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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue