summaryrefslogtreecommitdiffstats
path: root/firmware/pcm_record.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2006-12-07 19:34:26 +0000
committerMichael Sevakis <jethead71@rockbox.org>2006-12-07 19:34:26 +0000
commit0d768a37f970b40575ef2be169e670fd6b5d424a (patch)
tree2dbc6fe2211a3a2b1fe3aa0693196b8790b3ec78 /firmware/pcm_record.c
parent5652b2528d59b77e804f72d4f7c9854275e05b5a (diff)
downloadrockbox-0d768a37f970b40575ef2be169e670fd6b5d424a.tar.gz
rockbox-0d768a37f970b40575ef2be169e670fd6b5d424a.zip
SWCODEC Recording: 1) Fix minor bug of not subtracting line aligment adjustment from buffer size. 2) Handle stop and pause better and let pcmrec thread lock the DMA as that could cause prerecording to get disabled internally 3) Make sure to snapshot DMA write index to ensure compiler doesn't perform multiple access when calculating available data (probably just paranoia on my part) 4) Handle USB connect in recording thread a little better by resetting hardware to defaults after closing 5) Make power managment stop recording properly when powering off (ie. no yield() from interrupt handler! :)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11685 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/pcm_record.c')
-rw-r--r--firmware/pcm_record.c61
1 files changed, 31 insertions, 30 deletions
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c
index a72641baa6..93a6e067b1 100644
--- a/firmware/pcm_record.c
+++ b/firmware/pcm_record.c
@@ -244,6 +244,14 @@ static int pcm_rec_have_more(int status)
return 0;
} /* pcm_rec_have_more */
+static void reset_hardware(void)
+{
+ /* reset pcm to defaults (playback only) */
+ pcm_set_frequency(HW_SAMPR_DEFAULT);
+ audio_set_output_source(AUDIO_SRC_PLAYBACK);
+ pcm_apply_settings(true);
+}
+
/** pcm_rec_* group **/
void pcm_rec_error_clear(void)
{
@@ -328,10 +336,7 @@ void audio_close_recording(void)
{
pcm_thread_wait_for_stop();
pcm_thread_sync_post(PCMREC_CLOSE, NULL);
- /* reset pcm to defaults (playback only) */
- pcm_set_frequency(HW_SAMPR_DEFAULT);
- audio_set_output_source(AUDIO_SRC_PLAYBACK);
- pcm_apply_settings(true);
+ reset_hardware();
audio_remove_encoder();
} /* audio_close_recording */
@@ -460,10 +465,6 @@ void audio_stop_recording(void)
logf("audio_stop_recording");
pcm_thread_wait_for_stop();
-
- if (is_recording)
- dma_lock = true; /* fix DMA write ptr at current position */
-
pcm_thread_sync_post(PCMREC_STOP, NULL);
logf("audio_stop_recording done");
@@ -474,11 +475,8 @@ void audio_pause_recording(void)
logf("audio_pause_recording");
pcm_thread_wait_for_stop();
-
- if (is_recording)
- dma_lock = true; /* fix DMA write ptr at current position */
-
pcm_thread_sync_post(PCMREC_PAUSE, NULL);
+
logf("audio_pause_recording done");
} /* audio_pause_recording */
@@ -1006,6 +1004,8 @@ static void pcmrec_new_stream(const char *filename, /* next file name */
/* PCMREC_INIT */
static void pcmrec_init(void)
{
+ unsigned char *buffer;
+
rec_fdata.rec_file = -1;
/* pcm FIFO */
@@ -1035,11 +1035,13 @@ static void pcmrec_init(void)
is_stopping = false;
is_error = false;
- pcm_buffer = audio_get_recording_buffer(&rec_buffer_size);
+ buffer = audio_get_recording_buffer(&rec_buffer_size);
/* Line align pcm_buffer 2^4=16 bytes */
- pcm_buffer = (unsigned char *)ALIGN_UP_P2((unsigned)pcm_buffer, 4);
+ pcm_buffer = (unsigned char *)ALIGN_UP_P2((unsigned long)buffer, 4);
enc_buffer = pcm_buffer + ALIGN_UP_P2(PCM_NUM_CHUNKS*PCM_CHUNK_SIZE +
PCM_MAX_FEED_SIZE, 2);
+ /* Adjust available buffer for possible align advancement */
+ rec_buffer_size -= pcm_buffer - buffer;
pcm_init_recording();
pcm_thread_signal_event(PCMREC_INIT);
@@ -1132,8 +1134,8 @@ static void pcmrec_start(const char *filename)
pcmrec_fnq_set_empty();
}
- dma_lock = false;
- is_paused = false;
+ dma_lock = false;
+ is_paused = false;
is_recording = true;
pcmrec_new_stream(filename,
@@ -1187,11 +1189,8 @@ static void pcmrec_finish_stop(void)
pcmrec_flush(-1);
/* wait for encoder to finish remaining data */
- if (!is_error)
- {
- while (!wav_queue_empty)
- yield();
- }
+ while (!is_error && !wav_queue_empty)
+ yield();
/* end stream at last data */
pcmrec_new_stream(NULL, CHUNKF_END_FILE, 0);
@@ -1307,7 +1306,7 @@ static void pcmrec_thread(void)
while(1)
{
- if (is_recording)
+ if (is_recording && !is_stopping)
{
/* Poll periodically to flush data */
queue_wait_w_tmo(&pcmrec_queue, &ev, HZ/5);
@@ -1363,12 +1362,12 @@ static void pcmrec_thread(void)
break;
case SYS_USB_CONNECTED:
- if (!is_recording)
- {
- pcmrec_close();
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- usb_wait_for_disconnect(&pcmrec_queue);
- }
+ if (is_recording)
+ break;
+ pcmrec_close();
+ reset_hardware();
+ usb_acknowledge(SYS_USB_CONNECTED_ACK);
+ usb_wait_for_disconnect(&pcmrec_queue);
break;
} /* end switch */
} /* end while */
@@ -1554,7 +1553,8 @@ void enc_finish_chunk(void)
int enc_pcm_buf_near_empty(void)
{
/* less than 1sec raw data? => unboost encoder */
- size_t avail = (dma_wr_pos - pcm_rd_pos) & PCM_CHUNK_MASK;
+ int wp = dma_wr_pos;
+ size_t avail = (wp - pcm_rd_pos) & PCM_CHUNK_MASK;
return avail < (sample_rate << 2) ? 1 : 0;
} /* enc_pcm_buf_near_empty */
@@ -1562,7 +1562,8 @@ int enc_pcm_buf_near_empty(void)
/* TODO: this really should give the actual size returned */
unsigned char * enc_get_pcm_data(size_t size)
{
- size_t avail = (dma_wr_pos - pcm_rd_pos) & PCM_CHUNK_MASK;
+ int wp = dma_wr_pos;
+ size_t avail = (wp - pcm_rd_pos) & PCM_CHUNK_MASK;
/* limit the requested pcm data size */
if (size > PCM_MAX_FEED_SIZE)