diff --git a/apps/plugin.c b/apps/plugin.c index 268fee5fd8..b129493471 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -482,6 +482,7 @@ static const struct plugin_api rockbox_api = { #if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) && !defined(SIMULATOR) sound_default, + pcm_record_more, #endif }; diff --git a/apps/plugin.h b/apps/plugin.h index 22f6b97fce..68841e8698 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -580,8 +580,8 @@ struct plugin_api { #ifndef SIMULATOR void (*pcm_init_recording)(void); void (*pcm_close_recording)(void); - void (*pcm_record_data)(pcm_more_callback_type more_ready, - unsigned char *start, size_t size); + void (*pcm_record_data)(pcm_more_callback_type2 more_ready, + void *start, size_t size); void (*pcm_stop_recording)(void); void (*pcm_calculate_rec_peaks)(int *left, int *right); void (*audio_set_recording_gain)(int left, int right, int type); @@ -598,6 +598,7 @@ struct plugin_api { #if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) && !defined(SIMULATOR) int (*sound_default)(int setting); + void (*pcm_record_more)(void *start, size_t size); #endif }; diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h index e7c00edeed..80a1f557fe 100644 --- a/firmware/export/pcm_playback.h +++ b/firmware/export/pcm_playback.h @@ -24,6 +24,7 @@ /* Typedef for registered callback (play and record) */ typedef void (*pcm_more_callback_type)(unsigned char **start, size_t *size); +typedef int (*pcm_more_callback_type2)(int status); void pcm_init(void); diff --git a/firmware/export/pcm_record.h b/firmware/export/pcm_record.h index 30d2dc7e6f..f6dddb3424 100644 --- a/firmware/export/pcm_record.h +++ b/firmware/export/pcm_record.h @@ -20,9 +20,9 @@ #ifndef PCM_RECORD_H #define PCM_RECORD_H -#define DMA_REC_ERROR_DMA ((size_t)-1) +#define DMA_REC_ERROR_DMA (-1) #ifdef HAVE_SPDIF_IN -#define DMA_REC_ERROR_SPDIF ((size_t)-2) +#define DMA_REC_ERROR_SPDIF (-2) #endif /** @@ -36,12 +36,15 @@ void pcm_init_recording(void); void pcm_close_recording(void); /* Start recording "raw" PCM data */ -void pcm_record_data(pcm_more_callback_type more_ready, - unsigned char *start, size_t size); +void pcm_record_data(pcm_more_callback_type2 more_ready, + void *start, size_t size); /* Stop tranferring data into supplied buffer */ void pcm_stop_recording(void); +/* Continue transferring data in - call during interrupt handler */ +void pcm_record_more(void *start, size_t size); + void pcm_calculate_rec_peaks(int *left, int *right); /** General functions for high level codec recording **/ @@ -64,12 +67,12 @@ int pcm_get_num_unprocessed(void); /** The following are for internal use between pcm_record.c and target- specific portion **/ /* the registered callback function for when more data is available */ -extern volatile pcm_more_callback_type pcm_callback_more_ready; +extern volatile pcm_more_callback_type2 pcm_callback_more_ready; /* DMA transfer in is currently active */ -extern volatile bool pcm_recording; +extern volatile bool pcm_recording; /* APIs implemented in the target-specific portion */ -extern void pcm_rec_dma_start(const void *addr, size_t size); +extern void pcm_rec_dma_start(void *addr, size_t size); extern void pcm_rec_dma_stop(void); #endif /* PCM_RECORD_H */ diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c index 379adc3a9c..a72641baa6 100644 --- a/firmware/pcm_record.c +++ b/firmware/pcm_record.c @@ -55,13 +55,9 @@ be shared semi-privately **/ /* the registered callback function for when more data is available */ -volatile pcm_more_callback_type pcm_callback_more_ready = NULL; +volatile pcm_more_callback_type2 pcm_callback_more_ready = NULL; /* DMA transfer in is currently active */ -volatile bool pcm_recording = false; - -/* APIs implemented in the target-specific portion */ -void pcm_rec_dma_start(const void *addr, size_t size); -void pcm_rec_dma_stop(void); +volatile bool pcm_recording = false; /** General recording state **/ static bool is_recording; /* We are recording */ @@ -225,16 +221,16 @@ static void pcm_thread_wait_for_stop(void) /*******************************************************************/ /* Callback for when more data is ready */ -static void pcm_rec_have_more(unsigned char **data, size_t *size) +static int pcm_rec_have_more(int status) { - if (*size != 0) + if (status < 0) { /* some error condition */ - if (*size == DMA_REC_ERROR_DMA) + if (status == DMA_REC_ERROR_DMA) { /* Flush recorded data to disk and stop recording */ queue_post(&pcmrec_queue, PCMREC_STOP, NULL); - return; + return -1; } /* else try again next transmission */ } @@ -243,9 +239,9 @@ static void pcm_rec_have_more(unsigned char **data, size_t *size) /* advance write position */ dma_wr_pos = (dma_wr_pos + PCM_CHUNK_SIZE) & PCM_CHUNK_MASK; } - - *data = (unsigned char *)GET_PCM_CHUNK(dma_wr_pos); - *size = PCM_CHUNK_SIZE; + + pcm_record_more(GET_PCM_CHUNK(dma_wr_pos), PCM_CHUNK_SIZE); + return 0; } /* pcm_rec_have_more */ /** pcm_rec_* group **/ @@ -423,9 +419,9 @@ void audio_set_recording_options(struct audio_recording_options *options) if (audio_load_encoder(enc_config.afmt)) { /* start DMA transfer */ - pcm_record_data(pcm_rec_have_more, NULL, 0); - /* do unlock after starting to prevent preincrement of dma_wr_pos */ dma_lock = pre_record_ticks == 0; + pcm_record_data(pcm_rec_have_more, GET_PCM_CHUNK(dma_wr_pos), + PCM_CHUNK_SIZE); } else { @@ -1621,20 +1617,14 @@ size_t enc_unget_pcm_data(size_t size) * Functions that do not require targeted implementation but only a targeted * interface */ -void pcm_record_data(pcm_more_callback_type more_ready, - unsigned char *start, size_t size) +void pcm_record_data(pcm_more_callback_type2 more_ready, + void *start, size_t size) { - pcm_callback_more_ready = more_ready; - if (!(start && size)) - { - size = 0; - if (more_ready) - more_ready(&start, &size); - } + return; - if (start && size) - pcm_rec_dma_start(start, size); + pcm_callback_more_ready = more_ready; + pcm_rec_dma_start(start, size); } /* pcm_record_data */ void pcm_stop_recording(void) diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c index 917800d0b8..4e4e557d9b 100644 --- a/firmware/target/coldfire/pcm-coldfire.c +++ b/firmware/target/coldfire/pcm-coldfire.c @@ -287,7 +287,7 @@ void DMA0(void) /**************************************************************************** ** Recording DMA transfer **/ -void pcm_rec_dma_start(const void *addr, size_t size) +void pcm_rec_dma_start(void *addr, size_t size) { logf("pcm_rec_dma_start"); @@ -296,12 +296,6 @@ void pcm_rec_dma_start(const void *addr, size_t size) pcm_recording = true; - DAR1 = (unsigned long)addr; /* Destination address */ - SAR1 = (unsigned long)&PDIR2; /* Source address */ - BCR1 = size; /* Bytes to transfer */ - - rec_peak_addr = (unsigned long *)addr; - pcm_apply_settings(false); /* Start the DMA transfer.. */ @@ -309,18 +303,22 @@ void pcm_rec_dma_start(const void *addr, size_t size) INTERRUPTCLEAR = 0x03c00000; #endif - DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC | - DMA_DSIZE(3) | DMA_START; + SAR1 = (unsigned long)&PDIR2; /* Source address */ + DCR1 = DMA_INT | DMA_CS | DMA_AA | DMA_DINC | DMA_DSIZE(3); + + pcm_record_more(addr, size); + + DCR1 |= DMA_START; } /* pcm_dma_start */ void pcm_rec_dma_stop(void) { logf("pcm_rec_dma_stop"); - pcm_recording = false; - - DCR1 = 0; DSR1 = 1; /* Clear interrupt */ + DCR1 = 0; + + pcm_recording = false; } /* pcm_dma_stop */ void pcm_init_recording(void) @@ -338,7 +336,7 @@ void pcm_init_recording(void) pcm_rec_dma_stop(); - ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */ + ICR7 = (6 << 2); /* Enable interrupt at level 6, priority 0 */ IMR &= ~(1 << 15); /* bit 15 is DMA1 */ } /* pcm_init_recording */ @@ -359,17 +357,15 @@ void DMA1(void) __attribute__ ((interrupt_handler, section(".icode"))); void DMA1(void) { int res = DSR1; - pcm_more_callback_type more_ready; - unsigned char *next_start; - ssize_t next_size = 0; /* passing <> 0 is indicates - an error condition */ + int status = 0; + pcm_more_callback_type2 more_ready; - DSR1 = 1; /* Clear interrupt */ - DCR1 &= ~DMA_EEXT; + DSR1 = 1; /* Clear interrupt */ + DCR1 &= ~DMA_EEXT; /* Disable peripheral request */ if (res & 0x70) { - next_size = DMA_REC_ERROR_DMA; + status = DMA_REC_ERROR_DMA; logf("DMA1 err: 0x%x", res); } #ifdef HAVE_SPDIF_IN @@ -377,37 +373,33 @@ void DMA1(void) (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */ { INTERRUPTCLEAR = 0x03c00000; - next_size = DMA_REC_ERROR_SPDIF; + status = DMA_REC_ERROR_SPDIF; logf("spdif err"); } #endif more_ready = pcm_callback_more_ready; - if (more_ready) - more_ready(&next_start, &next_size); - - if (next_size > 0) - { - /* Start peaking at dest */ - rec_peak_addr = (unsigned long *)next_start; - DAR1 = (unsigned long)next_start; /* Destination address */ - BCR1 = (unsigned long)next_size; /* Bytes to transfer */ - DCR1 |= DMA_EEXT; + if (more_ready != NULL && more_ready(status) >= 0) return; - } - else - { -#if 0 - /* int. logfs can trash the display */ - logf("DMA1 No Data:0x%04x", res); -#endif - } +#if 0 + /* int. logfs can trash the display */ + logf("DMA1 done:%04x %d", res, status); +#endif /* Finished recording */ pcm_rec_dma_stop(); } /* DMA1 */ +/* Continue transferring data in */ +void pcm_record_more(void *start, size_t size) +{ + rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ + DAR1 = (unsigned long)start; /* Destination address */ + BCR1 = (unsigned long)size; /* Bytes to transfer */ + DCR1 |= DMA_EEXT; +} + void pcm_mute(bool mute) { ac_mute(mute);