forked from len0rd/rockbox
iAudio: First unfinished attempt for tlv320 driver and rockbox integration
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7286 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
095854b989
commit
14e80671af
8 changed files with 441 additions and 142 deletions
|
|
@ -30,7 +30,11 @@
|
|||
|
||||
#include "cpu.h"
|
||||
#include "i2c.h"
|
||||
#if defined(HAVE_UDA1380)
|
||||
#include "uda1380.h"
|
||||
#elif defined(HAVE_TLV320)
|
||||
#include "tlv320.h"
|
||||
#endif
|
||||
#include "system.h"
|
||||
#include "usb.h"
|
||||
|
||||
|
|
@ -61,7 +65,7 @@ static unsigned long record_start_time; /* Value of current_tick when re
|
|||
static unsigned long pause_start_time; /* Value of current_tick when pause was started */
|
||||
|
||||
static int rec_gain, rec_volume;
|
||||
static bool show_waveform;
|
||||
static bool show_waveform;
|
||||
static int init_done = 0;
|
||||
static int wav_file;
|
||||
static char recording_filename[MAX_PATH];
|
||||
|
|
@ -72,12 +76,12 @@ static char recording_filename[MAX_PATH];
|
|||
Some estimates:
|
||||
44100 HZ * 4 = 176400 bytes/s
|
||||
Refresh LCD 10 HZ = 176400 / 10 = 17640 bytes ~=~ 1024*16 bytes
|
||||
|
||||
|
||||
If NUM_BUFFERS is 80 we can hold ~8 sec of data in memory
|
||||
ALL_BUFFER_SIZE will be 1024*16 * 80 = 1310720 bytes
|
||||
*/
|
||||
|
||||
#define NUM_BUFFERS 80
|
||||
#define NUM_BUFFERS 80
|
||||
#define EACH_BUFFER_SIZE (1024*16) /* Multiple of 4. Use small value to get responsive waveform */
|
||||
#define ALL_BUFFERS_SIZE (NUM_BUFFERS * EACH_BUFFER_SIZE)
|
||||
|
||||
|
|
@ -130,7 +134,7 @@ void pcm_init_recording(void)
|
|||
wav_file = -1;
|
||||
read_index = 0;
|
||||
write_index = 0;
|
||||
|
||||
|
||||
queue_init(&pcmrec_queue);
|
||||
create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), pcmrec_thread_name);
|
||||
}
|
||||
|
|
@ -138,16 +142,16 @@ void pcm_init_recording(void)
|
|||
void pcm_open_recording(void)
|
||||
{
|
||||
init_done = 0;
|
||||
|
||||
|
||||
logf("pcm_open_rec");
|
||||
|
||||
|
||||
queue_post(&pcmrec_queue, PCMREC_OPEN, 0);
|
||||
|
||||
|
||||
while (init_done)
|
||||
{
|
||||
sleep(HZ >> 8);
|
||||
}
|
||||
|
||||
|
||||
logf("pcm_open_rec done");
|
||||
}
|
||||
|
||||
|
|
@ -162,10 +166,10 @@ void pcm_close_recording(void)
|
|||
unsigned long pcm_status(void)
|
||||
{
|
||||
unsigned long ret = 0;
|
||||
|
||||
|
||||
if (is_recording)
|
||||
ret |= AUDIO_STATUS_RECORD;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +197,7 @@ unsigned long pcm_recorded_time(void)
|
|||
|
||||
unsigned long pcm_num_recorded_bytes(void)
|
||||
{
|
||||
|
||||
|
||||
if (is_recording)
|
||||
{
|
||||
return num_rec_bytes;
|
||||
|
|
@ -222,10 +226,12 @@ void pcm_resume_recording(void)
|
|||
*/
|
||||
void pcm_set_recording_options(int source, bool enable_waveform)
|
||||
{
|
||||
#if defined(HAVE_UDA1380)
|
||||
uda1380_enable_recording(source);
|
||||
|
||||
#elif defined(HAVE_TLV320)
|
||||
tlv320_enable_recording(source);
|
||||
#endif
|
||||
show_waveform = enable_waveform;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -238,21 +244,20 @@ void pcm_set_recording_gain(int gain, int volume)
|
|||
{
|
||||
rec_gain = gain;
|
||||
rec_volume = volume;
|
||||
|
||||
|
||||
queue_post(&pcmrec_queue, PCMREC_SET_GAIN, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start recording
|
||||
*
|
||||
* Use pcm_set_recording_options before calling record
|
||||
*/
|
||||
*/
|
||||
void pcm_record(const char *filename)
|
||||
{
|
||||
strncpy(recording_filename, filename, MAX_PATH - 1);
|
||||
recording_filename[MAX_PATH - 1] = 0;
|
||||
|
||||
|
||||
queue_post(&pcmrec_queue, PCMREC_START, 0);
|
||||
}
|
||||
|
||||
|
|
@ -263,19 +268,17 @@ void pcm_stop_recording(void)
|
|||
{
|
||||
if (is_recording)
|
||||
is_stopping = 1;
|
||||
|
||||
|
||||
queue_post(&pcmrec_queue, PCMREC_STOP, 0);
|
||||
|
||||
logf("pcm_stop_recording");
|
||||
|
||||
|
||||
while (is_stopping)
|
||||
{
|
||||
sleep(HZ >> 4);
|
||||
}
|
||||
|
||||
|
||||
logf("pcm_stop_recording done");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -303,40 +306,40 @@ void pcmrec_callback(bool flush)
|
|||
num_ready += NUM_BUFFERS;
|
||||
|
||||
/* we can consume up to num_ready buffers */
|
||||
|
||||
#ifdef HAVE_REMOTE_LCD
|
||||
|
||||
#ifdef HAVE_REMOTE_LCD
|
||||
/* Draw waveform on remote LCD */
|
||||
if (show_waveform && num_ready>0)
|
||||
if (show_waveform && num_ready>0)
|
||||
{
|
||||
short *buf;
|
||||
long x,y,offset;
|
||||
int show_index;
|
||||
|
||||
/* Just display the last buffer (most recent one) */
|
||||
show_index = read_index + num_ready - 1;
|
||||
show_index = read_index + num_ready - 1;
|
||||
buf = (short*)rec_buffers[show_index];
|
||||
|
||||
|
||||
lcd_remote_clear_display();
|
||||
|
||||
|
||||
offset = 0;
|
||||
for (x=0; x<LCD_REMOTE_WIDTH-1; x++)
|
||||
{
|
||||
y = buf[offset] * (LCD_REMOTE_HEIGHT / 2) *5; /* The 5 is just 'zooming' */
|
||||
y = y >> 15; /* Divide with SHRT_MAX */
|
||||
y += LCD_REMOTE_HEIGHT/2;
|
||||
|
||||
|
||||
if (y < 2) y=2;
|
||||
if (y >= LCD_REMOTE_HEIGHT-2) y = LCD_REMOTE_HEIGHT-2;
|
||||
|
||||
|
||||
lcd_remote_drawpixel(x,y);
|
||||
|
||||
|
||||
offset += (EACH_BUFFER_SIZE/2) / LCD_REMOTE_WIDTH;
|
||||
}
|
||||
|
||||
lcd_remote_update();
|
||||
|
||||
lcd_remote_update();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Note: This might be a good place to call the 'codec' later */
|
||||
|
||||
|
|
@ -348,43 +351,41 @@ void pcmrec_callback(bool flush)
|
|||
{
|
||||
unsigned long *ptr = (unsigned long*)rec_buffers[read_index];
|
||||
int i;
|
||||
|
||||
|
||||
for (i=0; i<EACH_BUFFER_SIZE * num_ready / 4; i++)
|
||||
{
|
||||
*ptr = SWAB32(*ptr);
|
||||
ptr++;
|
||||
}
|
||||
|
||||
|
||||
write(wav_file, rec_buffers[read_index], EACH_BUFFER_SIZE * num_ready);
|
||||
|
||||
|
||||
read_index+=num_ready;
|
||||
if (read_index >= NUM_BUFFERS)
|
||||
read_index -= NUM_BUFFERS;
|
||||
}
|
||||
|
||||
|
||||
} else
|
||||
{
|
||||
/* In this case we must consume the buffers otherwise we will */
|
||||
/* get 'dma1 overrun' pretty fast */
|
||||
|
||||
|
||||
read_index+=num_ready;
|
||||
if (read_index >= NUM_BUFFERS)
|
||||
read_index -= NUM_BUFFERS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pcmrec_dma_start(void)
|
||||
{
|
||||
DAR1 = (unsigned long)rec_buffers[write_index++]; /* Destination address */
|
||||
SAR1 = (unsigned long)&PDIR2; /* Source address */
|
||||
BCR1 = EACH_BUFFER_SIZE; /* Bytes to transfer */
|
||||
|
||||
|
||||
/* Start the DMA transfer.. */
|
||||
DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START;
|
||||
|
||||
DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START;
|
||||
|
||||
logf("dma1 started");
|
||||
}
|
||||
|
||||
|
|
@ -396,7 +397,7 @@ void DMA1(void)
|
|||
int res = DSR1;
|
||||
|
||||
DSR1 = 1; /* Clear interrupt */
|
||||
|
||||
|
||||
int_count++;
|
||||
|
||||
if (res & 0x70)
|
||||
|
|
@ -404,41 +405,41 @@ void DMA1(void)
|
|||
DCR1 = 0; /* Stop DMA transfer */
|
||||
error_count++;
|
||||
is_recording = 0;
|
||||
|
||||
|
||||
logf("dma1 err 0x%x", res);
|
||||
|
||||
|
||||
} else
|
||||
{
|
||||
num_rec_bytes += EACH_BUFFER_SIZE;
|
||||
|
||||
|
||||
write_index++;
|
||||
if (write_index >= NUM_BUFFERS)
|
||||
write_index = 0;
|
||||
|
||||
|
||||
if (is_stopping || !is_recording)
|
||||
{
|
||||
DCR1 = 0; /* Stop DMA transfer */
|
||||
is_recording = 0;
|
||||
|
||||
|
||||
logf("dma1 stopping");
|
||||
|
||||
|
||||
} else if (write_index == read_index)
|
||||
{
|
||||
DCR1 = 0; /* Stop DMA transfer */
|
||||
is_recording = 0;
|
||||
|
||||
|
||||
logf("dma1 overrun");
|
||||
|
||||
|
||||
} else
|
||||
{
|
||||
DAR1 = (unsigned long)rec_buffers[write_index]; /* Destination address */
|
||||
BCR1 = EACH_BUFFER_SIZE;
|
||||
|
||||
queue_post(&pcmrec_queue, PCMREC_GOT_DATA, NULL);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IPR |= (1<<15); /* Clear pending interrupt request */
|
||||
}
|
||||
|
||||
|
|
@ -450,7 +451,7 @@ static int start_wave(void)
|
|||
0x10,0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,
|
||||
4,0,0x10,0,'d','a','t','a',0,0,0,0
|
||||
};
|
||||
|
||||
|
||||
wav_file = open(recording_filename, O_RDWR|O_CREAT|O_TRUNC);
|
||||
if (wav_file < 0)
|
||||
{
|
||||
|
|
@ -458,7 +459,7 @@ static int start_wave(void)
|
|||
logf("create failed: %d", wav_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (sizeof(header) != write(wav_file, header, sizeof(header)))
|
||||
{
|
||||
close(wav_file);
|
||||
|
|
@ -466,7 +467,7 @@ static int start_wave(void)
|
|||
logf("write failed");
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -474,15 +475,15 @@ static int start_wave(void)
|
|||
static void close_wave(void)
|
||||
{
|
||||
long l;
|
||||
|
||||
|
||||
l = SWAB32(num_rec_bytes + 36);
|
||||
lseek(wav_file, 4, SEEK_SET);
|
||||
write(wav_file, &l, 4);
|
||||
|
||||
|
||||
l = SWAB32(num_rec_bytes);
|
||||
lseek(wav_file, 40, SEEK_SET);
|
||||
write(wav_file, &l, 4);
|
||||
|
||||
|
||||
close(wav_file);
|
||||
wav_file = -1;
|
||||
}
|
||||
|
|
@ -490,19 +491,19 @@ static void close_wave(void)
|
|||
static void pcmrec_start(void)
|
||||
{
|
||||
logf("pcmrec_start");
|
||||
|
||||
|
||||
if (is_recording)
|
||||
return;
|
||||
|
||||
|
||||
if (wav_file != -1)
|
||||
close(wav_file);
|
||||
|
||||
|
||||
logf("rec: %s", recording_filename);
|
||||
|
||||
|
||||
start_wave(); /* todo: send signal to pcm_record if we have failed */
|
||||
|
||||
num_rec_bytes = 0;
|
||||
|
||||
|
||||
/* Store the current time */
|
||||
record_start_time = current_tick;
|
||||
|
||||
|
|
@ -514,29 +515,29 @@ static void pcmrec_start(void)
|
|||
is_recording = 1;
|
||||
|
||||
pcmrec_dma_start();
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void pcmrec_stop(void)
|
||||
{
|
||||
/* wait for recording to finish */
|
||||
|
||||
|
||||
/* todo: Abort current DMA transfer using DCR1.. */
|
||||
|
||||
|
||||
logf("pcmrec_stop");
|
||||
|
||||
|
||||
while (is_recording)
|
||||
{
|
||||
sleep(HZ >> 4);
|
||||
}
|
||||
|
||||
|
||||
logf("pcmrec_stop done");
|
||||
|
||||
/* Write unfinished buffers to file */
|
||||
pcmrec_callback(true);
|
||||
pcmrec_callback(true);
|
||||
|
||||
close_wave();
|
||||
|
||||
|
||||
is_stopping = 0;
|
||||
}
|
||||
|
||||
|
|
@ -544,7 +545,7 @@ static void pcmrec_open(void)
|
|||
{
|
||||
unsigned long buffer_start;
|
||||
int i;
|
||||
|
||||
|
||||
show_waveform = 0;
|
||||
is_recording = 0;
|
||||
is_stopping = 0;
|
||||
|
|
@ -555,7 +556,7 @@ static void pcmrec_open(void)
|
|||
|
||||
buffer_start = (unsigned long)(&audiobuf[(audiobufend - audiobuf) - (ALL_BUFFERS_SIZE + 16)]);
|
||||
buffer_start &= ~3;
|
||||
|
||||
|
||||
for (i=0; i<NUM_BUFFERS; i++)
|
||||
{
|
||||
rec_buffers[i] = (unsigned char*)(buffer_start + EACH_BUFFER_SIZE * i);
|
||||
|
|
@ -572,61 +573,69 @@ static void pcmrec_open(void)
|
|||
ICR4 = (ICR4 & 0xffffff00) | 0x0000001c; /* Enable interrupt at level 7, priority 0 */
|
||||
IMR &= ~(1<<15); /* bit 15 is DMA1 */
|
||||
|
||||
init_done = 1;
|
||||
init_done = 1;
|
||||
}
|
||||
|
||||
static void pcmrec_close(void)
|
||||
{
|
||||
#if defined(HAVE_UDA1380)
|
||||
uda1380_disable_recording();
|
||||
#elif defined(HAVE_TLV320)
|
||||
tlv320_disable_recording();
|
||||
#endif
|
||||
|
||||
DMAROUTE = (DMAROUTE & 0xffff00ff);
|
||||
ICR4 = (ICR4 & 0xffffff00); /* Disable interrupt */
|
||||
IMR |= (1<<15); /* bit 15 is DMA1 */
|
||||
IMR |= (1<<15); /* bit 15 is DMA1 */
|
||||
|
||||
}
|
||||
|
||||
static void pcmrec_thread(void)
|
||||
{
|
||||
struct event ev;
|
||||
|
||||
|
||||
logf("thread pcmrec start");
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
queue_wait(&pcmrec_queue, &ev);
|
||||
|
||||
|
||||
switch (ev.id)
|
||||
{
|
||||
case PCMREC_OPEN:
|
||||
pcmrec_open();
|
||||
break;
|
||||
|
||||
|
||||
case PCMREC_CLOSE:
|
||||
pcmrec_close();
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case PCMREC_START:
|
||||
pcmrec_start();
|
||||
break;
|
||||
|
||||
|
||||
case PCMREC_STOP:
|
||||
pcmrec_stop();
|
||||
break;
|
||||
|
||||
|
||||
case PCMREC_PAUSE:
|
||||
/* todo */
|
||||
break;
|
||||
|
||||
|
||||
case PCMREC_RESUME:
|
||||
/* todo */
|
||||
break;
|
||||
|
||||
|
||||
case PCMREC_NEW_FILE:
|
||||
/* todo */
|
||||
break;
|
||||
|
||||
|
||||
case PCMREC_SET_GAIN:
|
||||
#if defined(HAVE_UDA1380)
|
||||
uda1380_set_recvol(rec_gain, rec_gain, rec_volume);
|
||||
#elif defined(HAVE_TLV320)
|
||||
/* ToDo */
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PCMREC_GOT_DATA:
|
||||
|
|
@ -637,13 +646,12 @@ static void pcmrec_thread(void)
|
|||
if (!is_recording && !is_stopping)
|
||||
{
|
||||
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
||||
usb_wait_for_disconnect(&pcmrec_queue);
|
||||
usb_wait_for_disconnect(&pcmrec_queue);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logf("thread pcmrec done");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue