mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-09 13:15:18 -05:00
Playing whole song from hard disk
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@544 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
7958ea420f
commit
bb69a59a97
2 changed files with 187 additions and 35 deletions
|
|
@ -8,13 +8,13 @@ INCLUDES=-I../../common -I../.. -I../../drivers
|
||||||
|
|
||||||
TARGET = -DARCHOS_PLAYER_OLD=1
|
TARGET = -DARCHOS_PLAYER_OLD=1
|
||||||
|
|
||||||
CFLAGS = -g -Wall -m1 -nostdlib -Wstrict-prototypes -fschedule-insns -fno-builtin $(INCLUDES) $(TARGET) -DDEBUG
|
CFLAGS = -g -Wall -m1 -save-temps -nostdlib -Wstrict-prototypes -fschedule-insns -fno-builtin $(INCLUDES) $(TARGET) -DDEBUG
|
||||||
AFLAGS += -small -relax
|
AFLAGS += -small -relax
|
||||||
|
|
||||||
OBJS= ../../crt0.o main.o ../../drivers/i2c.o ../../drivers/mas.o \
|
OBJS= ../../crt0.o main.o ../../drivers/i2c.o ../../drivers/mas.o \
|
||||||
../../debug.o ../../kernel.o thread.o ../../common/sprintf.o \
|
../../debug.o ../../kernel.o thread.o ../../common/sprintf.o \
|
||||||
../../panic.o ../../system.o ../../drivers/led.o \
|
../../panic.o ../../system.o ../../drivers/led.o \
|
||||||
../../drivers/lcd.o ../../drivers/ata.o ../../drivers/fat.o \
|
../../drivers/lcd.o ata.o ../../drivers/fat.o \
|
||||||
../../common/disk.o ../../common/file.o ../../common/dir.o
|
../../common/disk.o ../../common/file.o ../../common/dir.o
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
|
|
@ -52,3 +52,9 @@ install:
|
||||||
thread.o: ../../thread.c
|
thread.o: ../../thread.c
|
||||||
$(CC) -O $(CFLAGS) -c $<
|
$(CC) -O $(CFLAGS) -c $<
|
||||||
|
|
||||||
|
ata.o: ../../drivers/ata.c
|
||||||
|
$(CC) -O $(CFLAGS) -c $<
|
||||||
|
|
||||||
|
main.o: main.c
|
||||||
|
$(CC) -O $(CFLAGS) -c $<
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "mas.h"
|
#include "mas.h"
|
||||||
#include "sh7034.h"
|
#include "sh7034.h"
|
||||||
|
#include "system.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "ata.h"
|
#include "ata.h"
|
||||||
|
|
@ -27,6 +28,11 @@
|
||||||
#include "fat.h"
|
#include "fat.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
|
#include "panic.h"
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a, b) (((a)<(b))?(a):(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned char fliptable[] =
|
unsigned char fliptable[] =
|
||||||
{
|
{
|
||||||
|
|
@ -66,13 +72,17 @@ unsigned char fliptable[] =
|
||||||
|
|
||||||
extern unsigned int stack[];
|
extern unsigned int stack[];
|
||||||
/* Place the MP3 data right after the stack */
|
/* Place the MP3 data right after the stack */
|
||||||
unsigned char *mp3buf = (unsigned char *)stack;
|
|
||||||
int mp3datalen;
|
|
||||||
|
|
||||||
unsigned char *mp3dataptr;
|
#define MP3BUF_LEN 0x100000 /* 1 Mbyte */
|
||||||
int mp3_transmitted;
|
|
||||||
|
unsigned char *mp3buf = (unsigned char *)stack;
|
||||||
|
|
||||||
|
int mp3buf_write;
|
||||||
|
int mp3buf_read;
|
||||||
|
int last_dma_chunk_size;
|
||||||
|
|
||||||
bool dma_on;
|
bool dma_on;
|
||||||
|
static void mas_poll_start(unsigned int interval_in_ms);
|
||||||
|
|
||||||
void setup_sci0(void)
|
void setup_sci0(void)
|
||||||
{
|
{
|
||||||
|
|
@ -124,11 +134,12 @@ int mas_tx_ready(void)
|
||||||
|
|
||||||
void init_dma(void)
|
void init_dma(void)
|
||||||
{
|
{
|
||||||
SAR3 = (unsigned int) mp3buf;
|
SAR3 = (unsigned int) mp3buf + mp3buf_read;
|
||||||
DAR3 = 0x5FFFEC3;
|
DAR3 = 0x5FFFEC3;
|
||||||
CHCR3 &= ~0x0002; /* Clear interrupt */
|
CHCR3 &= ~0x0002; /* Clear interrupt */
|
||||||
CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
|
CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
|
||||||
DTCR3 = 64000;
|
last_dma_chunk_size = MIN(65536, mp3buf_write - mp3buf_read);
|
||||||
|
DTCR3 = last_dma_chunk_size & 0xffff;
|
||||||
DMAOR = 0x0001; /* Enable DMA */
|
DMAOR = 0x0001; /* Enable DMA */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,6 +167,18 @@ void dma_tick(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bitswap(unsigned char *data, int length)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for(i = 0;i < length;i++)
|
||||||
|
{
|
||||||
|
data[i] = fliptable[data[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct event_queue disk_queue;
|
||||||
|
int filling;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
char buf[40];
|
char buf[40];
|
||||||
|
|
@ -164,6 +187,11 @@ int main(void)
|
||||||
DIR *d;
|
DIR *d;
|
||||||
struct dirent *dent;
|
struct dirent *dent;
|
||||||
int f;
|
int f;
|
||||||
|
int free_space_left;
|
||||||
|
int mp3_space_left;
|
||||||
|
int amount_to_read;
|
||||||
|
int play_song;
|
||||||
|
struct event *ev;
|
||||||
|
|
||||||
/* Clear it all! */
|
/* Clear it all! */
|
||||||
SSR1 &= ~(SCI_RDRF | SCI_ORER | SCI_PER | SCI_FER);
|
SSR1 &= ~(SCI_RDRF | SCI_ORER | SCI_PER | SCI_FER);
|
||||||
|
|
@ -173,12 +201,13 @@ int main(void)
|
||||||
SCR1 |= 0x40;
|
SCR1 |= 0x40;
|
||||||
SCR1 &= ~0x80;
|
SCR1 &= ~0x80;
|
||||||
|
|
||||||
|
IPRE |= 0xf000; /* Highest priority */
|
||||||
|
|
||||||
i2c_init();
|
i2c_init();
|
||||||
|
|
||||||
dma_on = TRUE;
|
dma_on = TRUE;
|
||||||
|
|
||||||
kernel_init();
|
kernel_init();
|
||||||
tick_add_task(dma_tick);
|
|
||||||
|
|
||||||
set_irq_level(0);
|
set_irq_level(0);
|
||||||
|
|
||||||
|
|
@ -247,27 +276,26 @@ int main(void)
|
||||||
debugf("Couldn't open file\n");
|
debugf("Couldn't open file\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
i = read(f, mp3buf, 1000000);
|
mp3buf_read = mp3buf_write = 0;
|
||||||
debugf("Read %d bytes\n", i);
|
|
||||||
|
|
||||||
mp3datalen = i;
|
/* First read in a few seconds worth of MP3 data */
|
||||||
|
i = read(f, mp3buf, 0x20000);
|
||||||
|
debugf("Read %d bytes\n", i);
|
||||||
|
|
||||||
ata_spindown(-1);
|
ata_spindown(-1);
|
||||||
|
|
||||||
debugf("bit swapping...\n");
|
debugf("bit swapping...\n");
|
||||||
for(i = 0;i < mp3datalen;i++)
|
bitswap(mp3buf + mp3buf_write, i);
|
||||||
{
|
|
||||||
mp3buf[i] = fliptable[mp3buf[i]];
|
mp3buf_write = i;
|
||||||
}
|
|
||||||
|
queue_init(&disk_queue);
|
||||||
|
|
||||||
|
mas_poll_start(1);
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
debugf("let's play...\n");
|
debugf("let's play...\n");
|
||||||
init_dma();
|
init_dma();
|
||||||
|
|
||||||
mp3dataptr = mp3buf;
|
|
||||||
mp3_transmitted = 0;
|
|
||||||
|
|
||||||
dma_on = TRUE;
|
dma_on = TRUE;
|
||||||
|
|
||||||
/* Enable Tx & TXIE */
|
/* Enable Tx & TXIE */
|
||||||
|
|
@ -275,9 +303,67 @@ int main(void)
|
||||||
|
|
||||||
CHCR3 |= 1;
|
CHCR3 |= 1;
|
||||||
|
|
||||||
debugf("sleeping...\n");
|
#define MP3_LOW_WATER 0x30000
|
||||||
sleep(1000000);
|
#define MP3_CHUNK_SIZE 0x20000
|
||||||
|
|
||||||
|
play_song = 1;
|
||||||
|
filling = 1;
|
||||||
|
|
||||||
|
while(play_song)
|
||||||
|
{
|
||||||
|
if(filling)
|
||||||
|
{
|
||||||
|
free_space_left = mp3buf_read - mp3buf_write;
|
||||||
|
if(free_space_left < 0)
|
||||||
|
free_space_left = MP3BUF_LEN + free_space_left;
|
||||||
|
|
||||||
|
if(free_space_left <= MP3_CHUNK_SIZE)
|
||||||
|
{
|
||||||
|
debugf("0\n");
|
||||||
|
ata_spindown(-1);
|
||||||
|
filling = 0;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
amount_to_read = MIN(MP3_CHUNK_SIZE, free_space_left);
|
||||||
|
amount_to_read = MIN(MP3BUF_LEN - 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. */
|
||||||
|
debugf("R\n", i);
|
||||||
|
i = read(f, mp3buf+mp3buf_write, amount_to_read);
|
||||||
|
if(i)
|
||||||
|
{
|
||||||
|
debugf("B\n");
|
||||||
|
bitswap(mp3buf + mp3buf_write, i);
|
||||||
|
|
||||||
|
mp3buf_write += i;
|
||||||
|
if(mp3buf_write >= MP3BUF_LEN)
|
||||||
|
{
|
||||||
|
mp3buf_write = 0;
|
||||||
|
debugf("W\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
play_song = 0;
|
||||||
|
ata_spindown(-1);
|
||||||
|
filling = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugf("S\n");
|
||||||
|
ev = queue_wait(&disk_queue);
|
||||||
|
debugf("Q\n");
|
||||||
|
debugf("1\n");
|
||||||
|
filling = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debugf("Song is finished\n");
|
||||||
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma interrupt
|
#pragma interrupt
|
||||||
|
|
@ -289,14 +375,74 @@ void IRQ6(void)
|
||||||
#pragma interrupt
|
#pragma interrupt
|
||||||
void DEI3(void)
|
void DEI3(void)
|
||||||
{
|
{
|
||||||
mp3_transmitted += 64000;
|
int unplayed_space_left;
|
||||||
if(mp3_transmitted < mp3datalen)
|
int space_until_end_of_buffer;
|
||||||
|
mp3buf_read += last_dma_chunk_size;
|
||||||
|
if(mp3buf_read >= MP3BUF_LEN)
|
||||||
|
mp3buf_read = 0;
|
||||||
|
|
||||||
|
unplayed_space_left = mp3buf_write - mp3buf_read;
|
||||||
|
if(unplayed_space_left < 0)
|
||||||
|
unplayed_space_left = MP3BUF_LEN + unplayed_space_left;
|
||||||
|
|
||||||
|
space_until_end_of_buffer = MP3BUF_LEN - mp3buf_read;
|
||||||
|
|
||||||
|
if(!filling && unplayed_space_left < MP3_LOW_WATER)
|
||||||
{
|
{
|
||||||
DTCR3 = 64000;
|
queue_post(&disk_queue, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(unplayed_space_left)
|
||||||
|
{
|
||||||
|
last_dma_chunk_size = MIN(65536, unplayed_space_left);
|
||||||
|
last_dma_chunk_size = MIN(last_dma_chunk_size, space_until_end_of_buffer);
|
||||||
|
DTCR3 = last_dma_chunk_size & 0xffff;
|
||||||
|
SAR3 = (unsigned int)mp3buf + mp3buf_read;
|
||||||
CHCR3 &= ~0x0002;
|
CHCR3 &= ~0x0002;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
debugf("No more MP3 data. Stopping.\n");
|
||||||
CHCR3 = 0;
|
CHCR3 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mas_poll_start(unsigned int interval_in_ms)
|
||||||
|
{
|
||||||
|
unsigned int count;
|
||||||
|
|
||||||
|
count = FREQ / 1000 / 8 * interval_in_ms;
|
||||||
|
|
||||||
|
if(count > 0xffff)
|
||||||
|
{
|
||||||
|
panicf("Error! The MAS poll interval is too long (%d ms)\n",
|
||||||
|
interval_in_ms);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 2 */
|
||||||
|
IPRC = (IPRC & ~0x000f) | 0x0002;
|
||||||
|
|
||||||
|
TSR1 &= ~0x02;
|
||||||
|
TIER1 = 0xf9; /* Enable GRA match interrupt */
|
||||||
|
|
||||||
|
TSTR |= 0x02; /* Start timer 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma interrupt
|
||||||
|
void IMIA1(void)
|
||||||
|
{
|
||||||
|
dma_tick();
|
||||||
|
TSR1 &= ~0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue