diff options
Diffstat (limited to 'firmware/pcm_playback.c')
-rw-r--r-- | firmware/pcm_playback.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c index 9a261dbf77..58d68cadbd 100644 --- a/firmware/pcm_playback.c +++ b/firmware/pcm_playback.c | |||
@@ -83,6 +83,8 @@ static void (*pcm_event_handler)(void); | |||
83 | static unsigned char *next_start; | 83 | static unsigned char *next_start; |
84 | static long next_size; | 84 | static long next_size; |
85 | 85 | ||
86 | static int last_chunksize = 0; | ||
87 | |||
86 | struct pcmbufdesc | 88 | struct pcmbufdesc |
87 | { | 89 | { |
88 | void *addr; | 90 | void *addr; |
@@ -107,7 +109,7 @@ static void dma_start(const void *addr, long size) | |||
107 | /* Reset the audio FIFO */ | 109 | /* Reset the audio FIFO */ |
108 | IIS2CONFIG = 0x800; | 110 | IIS2CONFIG = 0x800; |
109 | EBU1CONFIG = 0x800; | 111 | EBU1CONFIG = 0x800; |
110 | 112 | ||
111 | /* Set up DMA transfer */ | 113 | /* Set up DMA transfer */ |
112 | SAR0 = ((unsigned long)addr); /* Source address */ | 114 | SAR0 = ((unsigned long)addr); /* Source address */ |
113 | DAR0 = (unsigned long)&PDOR3; /* Destination address */ | 115 | DAR0 = (unsigned long)&PDOR3; /* Destination address */ |
@@ -144,6 +146,18 @@ static void dma_stop(void) | |||
144 | /* Reset the FIFO */ | 146 | /* Reset the FIFO */ |
145 | IIS2CONFIG = 0x800; | 147 | IIS2CONFIG = 0x800; |
146 | EBU1CONFIG = 0x800; | 148 | EBU1CONFIG = 0x800; |
149 | |||
150 | pcmbuf_unplayed_bytes = 0; | ||
151 | last_chunksize = 0; | ||
152 | audiobuffer_pos = 0; | ||
153 | audiobuffer_fillpos = 0; | ||
154 | audiobuffer_free = PCMBUF_SIZE; | ||
155 | pcmbuf_read_index = 0; | ||
156 | pcmbuf_write_index = 0; | ||
157 | next_start = NULL; | ||
158 | next_size = 0; | ||
159 | crossfade_init = 0; | ||
160 | pcm_paused = false; | ||
147 | } | 161 | } |
148 | 162 | ||
149 | /* sets frequency of input to DAC */ | 163 | /* sets frequency of input to DAC */ |
@@ -175,8 +189,6 @@ int pcm_play_num_used_buffers(void) | |||
175 | return (pcmbuf_write_index - pcmbuf_read_index) & NUM_PCM_BUFFERS_MASK; | 189 | return (pcmbuf_write_index - pcmbuf_read_index) & NUM_PCM_BUFFERS_MASK; |
176 | } | 190 | } |
177 | 191 | ||
178 | static int last_chunksize = 0; | ||
179 | |||
180 | static void pcm_play_callback(unsigned char** start, long* size) | 192 | static void pcm_play_callback(unsigned char** start, long* size) |
181 | { | 193 | { |
182 | struct pcmbufdesc *desc = &pcmbuffers[pcmbuf_read_index]; | 194 | struct pcmbufdesc *desc = &pcmbuffers[pcmbuf_read_index]; |
@@ -232,9 +244,8 @@ void pcm_play_data(const unsigned char* start, int size, | |||
232 | void (*get_more)(unsigned char** start, long* size)) | 244 | void (*get_more)(unsigned char** start, long* size)) |
233 | { | 245 | { |
234 | callback_for_more = get_more; | 246 | callback_for_more = get_more; |
235 | dma_start(start, size); | ||
236 | |||
237 | get_more(&next_start, &next_size); | 247 | get_more(&next_start, &next_size); |
248 | dma_start(start, size); | ||
238 | 249 | ||
239 | /* Sleep a while, then power on audio output */ | 250 | /* Sleep a while, then power on audio output */ |
240 | sleep(HZ/16); | 251 | sleep(HZ/16); |
@@ -251,15 +262,6 @@ void pcm_play_stop(void) | |||
251 | sleep(HZ/16); | 262 | sleep(HZ/16); |
252 | dma_stop(); | 263 | dma_stop(); |
253 | } | 264 | } |
254 | pcmbuf_unplayed_bytes = 0; | ||
255 | last_chunksize = 0; | ||
256 | audiobuffer_pos = 0; | ||
257 | audiobuffer_fillpos = 0; | ||
258 | audiobuffer_free = PCMBUF_SIZE; | ||
259 | pcmbuf_read_index = 0; | ||
260 | pcmbuf_write_index = 0; | ||
261 | next_start = NULL; | ||
262 | next_size = 0; | ||
263 | } | 265 | } |
264 | 266 | ||
265 | void pcm_play_pause(bool play) | 267 | void pcm_play_pause(bool play) |
@@ -298,11 +300,13 @@ void DMA0(void) | |||
298 | int res = DSR0; | 300 | int res = DSR0; |
299 | 301 | ||
300 | DSR0 = 1; /* Clear interrupt */ | 302 | DSR0 = 1; /* Clear interrupt */ |
303 | DCR0 &= ~DMA_EEXT; | ||
301 | 304 | ||
302 | /* Stop on error */ | 305 | /* Stop on error */ |
303 | if(res & 0x70) | 306 | if(res & 0x70) |
304 | { | 307 | { |
305 | dma_stop(); | 308 | dma_stop(); |
309 | logf("DMA Error"); | ||
306 | } | 310 | } |
307 | else | 311 | else |
308 | { | 312 | { |
@@ -310,6 +314,7 @@ void DMA0(void) | |||
310 | { | 314 | { |
311 | SAR0 = (unsigned long)next_start; /* Source address */ | 315 | SAR0 = (unsigned long)next_start; /* Source address */ |
312 | BCR0 = next_size; /* Bytes to transfer */ | 316 | BCR0 = next_size; /* Bytes to transfer */ |
317 | DCR0 |= DMA_EEXT; | ||
313 | if (callback_for_more) | 318 | if (callback_for_more) |
314 | callback_for_more(&next_start, &next_size); | 319 | callback_for_more(&next_start, &next_size); |
315 | } | 320 | } |
@@ -317,6 +322,7 @@ void DMA0(void) | |||
317 | { | 322 | { |
318 | /* Finished playing */ | 323 | /* Finished playing */ |
319 | dma_stop(); | 324 | dma_stop(); |
325 | logf("DMA No Data"); | ||
320 | } | 326 | } |
321 | } | 327 | } |
322 | 328 | ||
@@ -442,7 +448,11 @@ void pcm_flush_fillpos(void) | |||
442 | if (audiobuffer_fillpos) { | 448 | if (audiobuffer_fillpos) { |
443 | while (!pcm_play_add_chunk(&audiobuffer[audiobuffer_pos], | 449 | while (!pcm_play_add_chunk(&audiobuffer[audiobuffer_pos], |
444 | audiobuffer_fillpos, pcm_event_handler)) { | 450 | audiobuffer_fillpos, pcm_event_handler)) { |
451 | pcm_boost(false); | ||
445 | yield(); | 452 | yield(); |
453 | /* This is a fatal error situation that should never happen. */ | ||
454 | if (!pcm_playing) | ||
455 | break ; | ||
446 | } | 456 | } |
447 | pcm_event_handler = NULL; | 457 | pcm_event_handler = NULL; |
448 | audiobuffer_pos += audiobuffer_fillpos; | 458 | audiobuffer_pos += audiobuffer_fillpos; |
@@ -527,7 +537,7 @@ inline static bool prepare_insert(long length) | |||
527 | return false; | 537 | return false; |
528 | } | 538 | } |
529 | 539 | ||
530 | if (!pcm_is_playing() && !pcm_paused) { | 540 | if (!pcm_is_playing()) { |
531 | pcm_boost(true); | 541 | pcm_boost(true); |
532 | crossfade_active = false; | 542 | crossfade_active = false; |
533 | if (audiobuffer_free < PCMBUF_SIZE - CHUNK_SIZE*4) | 543 | if (audiobuffer_free < PCMBUF_SIZE - CHUNK_SIZE*4) |
@@ -659,7 +669,7 @@ bool pcm_insert_buffer(char *buf, long length) | |||
659 | length -= copy_n; | 669 | length -= copy_n; |
660 | 670 | ||
661 | /* Pre-buffer to meet CHUNK_SIZE requirement */ | 671 | /* Pre-buffer to meet CHUNK_SIZE requirement */ |
662 | if (copy_n + audiobuffer_fillpos < CHUNK_SIZE && length == 0) { | 672 | if (audiobuffer_fillpos < CHUNK_SIZE && length == 0) { |
663 | return true; | 673 | return true; |
664 | } | 674 | } |
665 | 675 | ||