summaryrefslogtreecommitdiff
path: root/firmware/target/arm/as3525/pcm-as3525.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/as3525/pcm-as3525.c')
-rw-r--r--firmware/target/arm/as3525/pcm-as3525.c73
1 files changed, 42 insertions, 31 deletions
diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c
index 8b42bbd5b2..b33ea2af84 100644
--- a/firmware/target/arm/as3525/pcm-as3525.c
+++ b/firmware/target/arm/as3525/pcm-as3525.c
@@ -81,7 +81,7 @@ static void play_start_pcm(void)
81 81
82 play_sub_size = size; 82 play_sub_size = size;
83 83
84 dma_enable_channel(1, (void*)addr, (void*)I2SOUT_DATA, DMA_PERI_I2SOUT, 84 dma_enable_channel(0, (void*)addr, (void*)I2SOUT_DATA, DMA_PERI_I2SOUT,
85 DMAC_FLOWCTRL_DMAC_MEM_TO_PERI, true, false, size >> 2, 85 DMAC_FLOWCTRL_DMAC_MEM_TO_PERI, true, false, size >> 2,
86 DMA_S1, dma_callback); 86 DMA_S1, dma_callback);
87} 87}
@@ -142,10 +142,10 @@ void pcm_play_dma_stop(void)
142{ 142{
143 is_playing = false; 143 is_playing = false;
144 144
145 dma_disable_channel(1); 145 dma_disable_channel(0);
146 146
147 /* Ensure byte counts read back 0 */ 147 /* Ensure byte counts read back 0 */
148 DMAC_CH_SRC_ADDR(1) = 0; 148 DMAC_CH_SRC_ADDR(0) = 0;
149 dma_start_addr = NULL; 149 dma_start_addr = NULL;
150 dma_start_size = 0; 150 dma_start_size = 0;
151 dma_rem_size = 0; 151 dma_rem_size = 0;
@@ -166,7 +166,7 @@ void pcm_play_dma_pause(bool pause)
166 166
167 if(pause) 167 if(pause)
168 { 168 {
169 dma_pause_channel(1); 169 dma_pause_channel(0);
170 170
171 /* if producer's buffer finished, upper layer starts anew */ 171 /* if producer's buffer finished, upper layer starts anew */
172 if (dma_rem_size == 0) 172 if (dma_rem_size == 0)
@@ -175,7 +175,7 @@ void pcm_play_dma_pause(bool pause)
175 else 175 else
176 { 176 {
177 if (play_sub_size != 0) 177 if (play_sub_size != 0)
178 dma_resume_channel(1); 178 dma_resume_channel(0);
179 /* else unlock calls the callback if sub buffers remain */ 179 /* else unlock calls the callback if sub buffers remain */
180 } 180 }
181} 181}
@@ -231,7 +231,7 @@ void pcm_dma_apply_settings(void)
231size_t pcm_get_bytes_waiting(void) 231size_t pcm_get_bytes_waiting(void)
232{ 232{
233 int oldstatus = disable_irq_save(); 233 int oldstatus = disable_irq_save();
234 size_t addr = DMAC_CH_SRC_ADDR(1); 234 size_t addr = DMAC_CH_SRC_ADDR(0);
235 size_t start_addr = (size_t)dma_start_addr; 235 size_t start_addr = (size_t)dma_start_addr;
236 size_t start_size = dma_start_size; 236 size_t start_size = dma_start_size;
237 restore_interrupt(oldstatus); 237 restore_interrupt(oldstatus);
@@ -242,7 +242,7 @@ size_t pcm_get_bytes_waiting(void)
242const void * pcm_play_dma_get_peak_buffer(int *count) 242const void * pcm_play_dma_get_peak_buffer(int *count)
243{ 243{
244 int oldstatus = disable_irq_save(); 244 int oldstatus = disable_irq_save();
245 size_t addr = DMAC_CH_SRC_ADDR(1); 245 size_t addr = DMAC_CH_SRC_ADDR(0);
246 size_t start_addr = (size_t)dma_start_addr; 246 size_t start_addr = (size_t)dma_start_addr;
247 size_t start_size = dma_start_size; 247 size_t start_size = dma_start_size;
248 restore_interrupt(oldstatus); 248 restore_interrupt(oldstatus);
@@ -269,6 +269,7 @@ void * pcm_dma_addr(void *addr)
269static int rec_locked = 0; 269static int rec_locked = 0;
270static uint32_t *rec_dma_addr; 270static uint32_t *rec_dma_addr;
271static size_t rec_dma_size; 271static size_t rec_dma_size;
272static int keep_sample = 0; /* In nonzero, keep the sample; else, discard it */
272 273
273void pcm_rec_lock(void) 274void pcm_rec_lock(void)
274{ 275{
@@ -310,32 +311,36 @@ void INT_I2SIN(void)
310 if (I2SIN_RAW_STATUS & (1<<5)) 311 if (I2SIN_RAW_STATUS & (1<<5))
311 return; /* empty */ 312 return; /* empty */
312 313
313 /* Discard every other sample since ADC clock is 1/2 LRCK */
314 uint32_t value = *I2SIN_DATA; 314 uint32_t value = *I2SIN_DATA;
315 *I2SIN_DATA;
316 315
317 /* Data is in left channel only - copy to right channel 316 /* Discard every other sample since ADC clock is 1/2 LRCK */
318 14-bit => 16-bit samples */ 317 keep_sample ^= 1;
319 value = (uint16_t)(value << 2) | (value << 18);
320 318
321 if (audio_output_source != AUDIO_SRC_PLAYBACK && !is_playing) 319 if (keep_sample)
322 { 320 {
323 /* In this case, loopback is manual so that both output 321 /* Data is in left channel only - copy to right channel
324 channels have audio */ 322 14-bit => 16-bit samples */
325 if (I2SOUT_RAW_STATUS & (1<<5)) 323 value = (uint16_t)(value << 2) | (value << 18);
324
325 if (audio_output_source != AUDIO_SRC_PLAYBACK && !is_playing)
326 { 326 {
327 /* Sync output fifo so it goes empty not before input is 327 /* In this case, loopback is manual so that both output
328 filled */ 328 channels have audio */
329 for (unsigned i = 0; i < 4; i++) 329 if (I2SOUT_RAW_STATUS & (1<<5))
330 *I2SOUT_DATA = 0; 330 {
331 /* Sync output fifo so it goes empty not before input is
332 filled */
333 for (unsigned i = 0; i < 4; i++)
334 *I2SOUT_DATA = 0;
335 }
336
337 *I2SOUT_DATA = value;
338 *I2SOUT_DATA = value;
331 } 339 }
332 340
333 *I2SOUT_DATA = value; 341 *rec_dma_addr++ = value;
334 *I2SOUT_DATA = value; 342 rec_dma_size -= 4;
335 } 343 }
336
337 *rec_dma_addr++ = value;
338 rec_dma_size -= 4;
339 } 344 }
340 } 345 }
341 else 346 else
@@ -347,15 +352,19 @@ void INT_I2SIN(void)
347 if (I2SIN_RAW_STATUS & (1<<5)) 352 if (I2SIN_RAW_STATUS & (1<<5))
348 return; /* empty */ 353 return; /* empty */
349 354
350 /* Discard every other sample since ADC clock is 1/2 LRCK */
351 uint32_t value = *I2SIN_DATA; 355 uint32_t value = *I2SIN_DATA;
352 *I2SIN_DATA;
353 356
354 /* Loopback is in I2S hardware */ 357 /* Discard every other sample since ADC clock is 1/2 LRCK */
358 keep_sample ^= 1;
359
360 if (keep_sample)
361 {
362 /* Loopback is in I2S hardware */
355 363
356 /* 14-bit => 16-bit samples */ 364 /* 14-bit => 16-bit samples */
357 *rec_dma_addr++ = (value << 2) & ~0x00030000; 365 *rec_dma_addr++ = (value << 2) & ~0x00030000;
358 rec_dma_size -= 4; 366 rec_dma_size -= 4;
367 }
359 } 368 }
360 } 369 }
361 370
@@ -389,6 +398,8 @@ void pcm_rec_dma_start(void *addr, size_t size)
389 rec_dma_addr = addr; 398 rec_dma_addr = addr;
390 rec_dma_size = size; 399 rec_dma_size = size;
391 400
401 keep_sample = 0;
402
392 /* ensure empty FIFO */ 403 /* ensure empty FIFO */
393 while (!(I2SIN_RAW_STATUS & (1<<5))) 404 while (!(I2SIN_RAW_STATUS & (1<<5)))
394 *I2SIN_DATA; 405 *I2SIN_DATA;