summaryrefslogtreecommitdiff
path: root/firmware/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/pcm.c')
-rw-r--r--firmware/pcm.c150
1 files changed, 92 insertions, 58 deletions
diff --git a/firmware/pcm.c b/firmware/pcm.c
index a69f0a8232..8080823077 100644
--- a/firmware/pcm.c
+++ b/firmware/pcm.c
@@ -39,6 +39,7 @@
39 * pcm_play_lock 39 * pcm_play_lock
40 * pcm_play_unlock 40 * pcm_play_unlock
41 * Semi-private - 41 * Semi-private -
42 * pcm_play_get_more_callback
42 * pcm_play_dma_init 43 * pcm_play_dma_init
43 * pcm_play_dma_start 44 * pcm_play_dma_start
44 * pcm_play_dma_stop 45 * pcm_play_dma_stop
@@ -48,28 +49,27 @@
48 * pcm_sampr (R) 49 * pcm_sampr (R)
49 * pcm_fsel (R) 50 * pcm_fsel (R)
50 * pcm_curr_sampr (R) 51 * pcm_curr_sampr (R)
51 * pcm_callback_for_more (R)
52 * pcm_playing (R) 52 * pcm_playing (R)
53 * pcm_paused (R) 53 * pcm_paused (R)
54 * 54 *
55 * ==Playback/Recording== 55 * ==Playback/Recording==
56 * Public -
57 * pcm_dma_addr
56 * Semi-private - 58 * Semi-private -
57 * pcm_dma_apply_settings 59 * pcm_dma_apply_settings
58 * pcm_dma_addr
59 * 60 *
60 * ==Recording== 61 * ==Recording==
61 * Public - 62 * Public -
62 * pcm_rec_lock 63 * pcm_rec_lock
63 * pcm_rec_unlock 64 * pcm_rec_unlock
64 * Semi-private - 65 * Semi-private -
66 * pcm_rec_more_ready_callback
65 * pcm_rec_dma_init 67 * pcm_rec_dma_init
66 * pcm_rec_dma_close 68 * pcm_rec_dma_close
67 * pcm_rec_dma_start 69 * pcm_rec_dma_start
68 * pcm_rec_dma_record_more
69 * pcm_rec_dma_stop 70 * pcm_rec_dma_stop
70 * pcm_rec_dma_get_peak_buffer 71 * pcm_rec_dma_get_peak_buffer
71 * Data Read/Written within TSP - 72 * Data Read/Written within TSP -
72 * pcm_callback_more_ready (R)
73 * pcm_recording (R) 73 * pcm_recording (R)
74 * 74 *
75 * States are set _after_ the target's pcm driver is called so that it may 75 * States are set _after_ the target's pcm driver is called so that it may
@@ -78,7 +78,7 @@
78 */ 78 */
79 79
80/* the registered callback function to ask for more mp3 data */ 80/* the registered callback function to ask for more mp3 data */
81volatile pcm_more_callback_type pcm_callback_for_more 81static volatile pcm_play_callback_type pcm_callback_for_more
82 SHAREDBSS_ATTR = NULL; 82 SHAREDBSS_ATTR = NULL;
83/* PCM playback state */ 83/* PCM playback state */
84volatile bool pcm_playing SHAREDBSS_ATTR = false; 84volatile bool pcm_playing SHAREDBSS_ATTR = false;
@@ -91,6 +91,14 @@ unsigned long pcm_sampr SHAREDBSS_ATTR = HW_SAMPR_DEFAULT;
91/* samplerate frequency selection index */ 91/* samplerate frequency selection index */
92int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT; 92int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT;
93 93
94/* Called internally by functions to reset the state */
95static void pcm_play_stopped(void)
96{
97 pcm_callback_for_more = NULL;
98 pcm_paused = false;
99 pcm_playing = false;
100}
101
94/** 102/**
95 * Perform peak calculation on a buffer of packed 16-bit samples. 103 * Perform peak calculation on a buffer of packed 16-bit samples.
96 * 104 *
@@ -187,6 +195,16 @@ const void* pcm_get_peak_buffer(int * count)
187 return pcm_play_dma_get_peak_buffer(count); 195 return pcm_play_dma_get_peak_buffer(count);
188} 196}
189 197
198bool pcm_is_playing(void)
199{
200 return pcm_playing;
201}
202
203bool pcm_is_paused(void)
204{
205 return pcm_paused;
206}
207
190/**************************************************************************** 208/****************************************************************************
191 * Functions that do not require targeted implementation but only a targeted 209 * Functions that do not require targeted implementation but only a targeted
192 * interface 210 * interface
@@ -198,7 +216,7 @@ void pcm_init(void)
198{ 216{
199 logf("pcm_init"); 217 logf("pcm_init");
200 218
201 pcm_play_dma_stopped_callback(); 219 pcm_play_stopped();
202 220
203 pcm_set_frequency(HW_SAMPR_DEFAULT); 221 pcm_set_frequency(HW_SAMPR_DEFAULT);
204 222
@@ -214,7 +232,7 @@ static void pcm_play_data_start(unsigned char *start, size_t size)
214 232
215 if (!(start && size)) 233 if (!(start && size))
216 { 234 {
217 pcm_more_callback_type get_more = pcm_callback_for_more; 235 pcm_play_callback_type get_more = pcm_callback_for_more;
218 size = 0; 236 size = 0;
219 if (get_more) 237 if (get_more)
220 { 238 {
@@ -239,10 +257,10 @@ static void pcm_play_data_start(unsigned char *start, size_t size)
239 /* Force a stop */ 257 /* Force a stop */
240 logf(" pcm_play_dma_stop"); 258 logf(" pcm_play_dma_stop");
241 pcm_play_dma_stop(); 259 pcm_play_dma_stop();
242 pcm_play_dma_stopped_callback(); 260 pcm_play_stopped();
243} 261}
244 262
245void pcm_play_data(pcm_more_callback_type get_more, 263void pcm_play_data(pcm_play_callback_type get_more,
246 unsigned char *start, size_t size) 264 unsigned char *start, size_t size)
247{ 265{
248 logf("pcm_play_data"); 266 logf("pcm_play_data");
@@ -257,6 +275,29 @@ void pcm_play_data(pcm_more_callback_type get_more,
257 pcm_play_unlock(); 275 pcm_play_unlock();
258} 276}
259 277
278void pcm_play_get_more_callback(void **start, size_t *size)
279{
280 pcm_play_callback_type get_more = pcm_callback_for_more;
281
282 *size = 0;
283
284 if (get_more && start)
285 {
286 /* Call registered callback */
287 get_more((unsigned char **)start, size);
288
289 *start = (void *)(((uintptr_t)*start + 3) & ~3);
290 *size &= ~3;
291
292 if (*start && *size)
293 return;
294 }
295
296 /* Error, callback missing or no more DMA to do */
297 pcm_play_dma_stop();
298 pcm_play_stopped();
299}
300
260void pcm_play_pause(bool play) 301void pcm_play_pause(bool play)
261{ 302{
262 logf("pcm_play_pause: %s", play ? "play" : "pause"); 303 logf("pcm_play_pause: %s", play ? "play" : "pause");
@@ -302,7 +343,7 @@ void pcm_play_stop(void)
302 { 343 {
303 logf(" pcm_play_dma_stop"); 344 logf(" pcm_play_dma_stop");
304 pcm_play_dma_stop(); 345 pcm_play_dma_stop();
305 pcm_play_dma_stopped_callback(); 346 pcm_play_stopped();
306 } 347 }
307 else 348 else
308 { 349 {
@@ -312,13 +353,6 @@ void pcm_play_stop(void)
312 pcm_play_unlock(); 353 pcm_play_unlock();
313} 354}
314 355
315void pcm_play_dma_stopped_callback(void)
316{
317 pcm_callback_for_more = NULL;
318 pcm_paused = false;
319 pcm_playing = false;
320}
321
322/**/ 356/**/
323 357
324/* set frequency next frequency used by the audio hardware - 358/* set frequency next frequency used by the audio hardware -
@@ -350,27 +384,24 @@ void pcm_apply_settings(void)
350 } 384 }
351} 385}
352 386
353bool pcm_is_playing(void)
354{
355 return pcm_playing;
356}
357
358bool pcm_is_paused(void)
359{
360 return pcm_paused;
361}
362
363#ifdef HAVE_RECORDING 387#ifdef HAVE_RECORDING
364/** Low level pcm recording apis **/ 388/** Low level pcm recording apis **/
365 389
366/* Next start for recording peaks */ 390/* Next start for recording peaks */
367static const void * volatile pcm_rec_peak_addr SHAREDBSS_ATTR = NULL; 391static const void * volatile pcm_rec_peak_addr SHAREDBSS_ATTR = NULL;
368/* the registered callback function for when more data is available */ 392/* the registered callback function for when more data is available */
369volatile pcm_more_callback_type2 393static volatile pcm_rec_callback_type
370 pcm_callback_more_ready SHAREDBSS_ATTR = NULL; 394 pcm_callback_more_ready SHAREDBSS_ATTR = NULL;
371/* DMA transfer in is currently active */ 395/* DMA transfer in is currently active */
372volatile bool pcm_recording SHAREDBSS_ATTR = false; 396volatile bool pcm_recording SHAREDBSS_ATTR = false;
373 397
398/* Called internally by functions to reset the state */
399static void pcm_recording_stopped(void)
400{
401 pcm_recording = false;
402 pcm_callback_more_ready = NULL;
403}
404
374/** 405/**
375 * Return recording peaks - From the end of the last peak up to 406 * Return recording peaks - From the end of the last peak up to
376 * current write position. 407 * current write position.
@@ -410,10 +441,16 @@ void pcm_calculate_rec_peaks(int *left, int *right)
410 *right = peaks[1]; 441 *right = peaks[1];
411} /* pcm_calculate_rec_peaks */ 442} /* pcm_calculate_rec_peaks */
412 443
444bool pcm_is_recording(void)
445{
446 return pcm_recording;
447}
448
413/**************************************************************************** 449/****************************************************************************
414 * Functions that do not require targeted implementation but only a targeted 450 * Functions that do not require targeted implementation but only a targeted
415 * interface 451 * interface
416 */ 452 */
453
417void pcm_init_recording(void) 454void pcm_init_recording(void)
418{ 455{
419 logf("pcm_init_recording"); 456 logf("pcm_init_recording");
@@ -424,7 +461,7 @@ void pcm_init_recording(void)
424 pcm_rec_lock(); 461 pcm_rec_lock();
425 462
426 logf(" pcm_rec_dma_init"); 463 logf(" pcm_rec_dma_init");
427 pcm_rec_dma_stopped_callback(); 464 pcm_recording_stopped();
428 pcm_rec_dma_init(); 465 pcm_rec_dma_init();
429 466
430 pcm_rec_unlock(); 467 pcm_rec_unlock();
@@ -440,7 +477,7 @@ void pcm_close_recording(void)
440 { 477 {
441 logf(" pcm_rec_dma_stop"); 478 logf(" pcm_rec_dma_stop");
442 pcm_rec_dma_stop(); 479 pcm_rec_dma_stop();
443 pcm_rec_dma_stopped_callback(); 480 pcm_recording_stopped();
444 } 481 }
445 482
446 logf(" pcm_rec_dma_close"); 483 logf(" pcm_rec_dma_close");
@@ -449,7 +486,7 @@ void pcm_close_recording(void)
449 pcm_rec_unlock(); 486 pcm_rec_unlock();
450} 487}
451 488
452void pcm_record_data(pcm_more_callback_type2 more_ready, 489void pcm_record_data(pcm_rec_callback_type more_ready,
453 void *start, size_t size) 490 void *start, size_t size)
454{ 491{
455 logf("pcm_record_data"); 492 logf("pcm_record_data");
@@ -493,43 +530,40 @@ void pcm_stop_recording(void)
493 { 530 {
494 logf(" pcm_rec_dma_stop"); 531 logf(" pcm_rec_dma_stop");
495 pcm_rec_dma_stop(); 532 pcm_rec_dma_stop();
496 pcm_rec_dma_stopped_callback(); 533 pcm_recording_stopped();
497 } 534 }
498 535
499 pcm_rec_unlock(); 536 pcm_rec_unlock();
500} /* pcm_stop_recording */ 537} /* pcm_stop_recording */
501 538
502void pcm_record_more(void *start, size_t size) 539void pcm_rec_more_ready_callback(int status, void **start, size_t *size)
503{ 540{
504 start = (void *)(((uintptr_t)start + 3) & ~3); 541 pcm_rec_callback_type have_more = pcm_callback_more_ready;
505 size = size & ~3;
506
507 if (!size)
508 {
509 pcm_rec_dma_stop();
510 pcm_rec_dma_stopped_callback();
511 return;
512 }
513 542
514#ifdef HAVE_PCM_REC_DMA_ADDRESS 543 *size = 0;
515 /* Need a physical DMA address translation, if not already physical. */
516 pcm_rec_peak_addr = pcm_dma_addr(start);
517#else
518 pcm_rec_peak_addr = start;
519#endif
520 544
521 pcm_rec_dma_record_more(start, size); 545 if (have_more && start)
522} 546 {
547 have_more(status, start, size);
548 *start = (void *)(((uintptr_t)*start + 3) & ~3);
549 *size &= ~3;
523 550
524bool pcm_is_recording(void) 551 if (*start && *size)
525{ 552 {
526 return pcm_recording; 553 #ifdef HAVE_PCM_REC_DMA_ADDRESS
527} 554 /* Need a physical DMA address translation, if not already
555 * physical. */
556 pcm_rec_peak_addr = pcm_dma_addr(*start);
557 #else
558 pcm_rec_peak_addr = *start;
559 #endif
560 return;
561 }
562 }
528 563
529void pcm_rec_dma_stopped_callback(void) 564 /* Error, callback missing or no more DMA to do */
530{ 565 pcm_rec_dma_stop();
531 pcm_recording = false; 566 pcm_recording_stopped();
532 pcm_callback_more_ready = NULL;
533} 567}
534 568
535#endif /* HAVE_RECORDING */ 569#endif /* HAVE_RECORDING */