Skip to content

Commit 7918714

Browse files
dhalberttannewt
authored andcommitted
certain odd-sized PDMIn record buffers would crash or not fill properly
1 parent 2d2735c commit 7918714

File tree

1 file changed

+14
-9
lines changed
  • atmel-samd/common-hal/audiobusio

1 file changed

+14
-9
lines changed

atmel-samd/common-hal/audiobusio/PDMIn.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,15 @@ static void setup_dma(audiobusio_pdmin_obj_t* self, uint32_t length,
213213
}
214214
dma_descriptor_create(audio_dma.descriptor, &descriptor_config);
215215

216+
// Do we need more values than will fit in the first buffer?
217+
// If so, set up a second buffer chained to be filled after the first buffer.
216218
if (length * words_per_sample > words_per_buffer) {
217219
block_transfer_count = words_per_buffer;
218220
descriptor_config.next_descriptor_address = ((uint32_t)audio_dma.descriptor);
219221
if (length * words_per_sample < 2 * words_per_buffer) {
220-
block_transfer_count = 2 * words_per_buffer - length * words_per_sample;
222+
// Length needed is more than one buffer but less than two.
223+
// Subtract off the size of the first buffer, and what remains is the count we need.
224+
block_transfer_count = length * words_per_sample - words_per_buffer;
221225
descriptor_config.next_descriptor_address = 0;
222226
}
223227
descriptor_config.block_transfer_count = block_transfer_count;
@@ -309,18 +313,21 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
309313
uint32_t remaining_samples_needed = output_buffer_length;
310314
while (values_output < output_buffer_length) {
311315
// Wait for the next buffer to fill
312-
while (tc_get_count_value(MP_STATE_VM(audiodma_block_counter)) == buffers_processed) {
316+
uint32_t block_counter;
317+
while ((block_counter = tc_get_count_value(MP_STATE_VM(audiodma_block_counter))) == buffers_processed) {
313318
#ifdef MICROPY_VM_HOOK_LOOP
314319
MICROPY_VM_HOOK_LOOP
315320
#endif
316321
}
317-
if (tc_get_count_value(MP_STATE_VM(audiodma_block_counter)) != (buffers_processed + 1)) {
322+
if (block_counter != (buffers_processed + 1)) {
323+
// Looks like we aren't keeping up. We shouldn't skip a buffer.
318324
break;
319325
}
320326

321327
// The mic is running all the time, so we don't need to wait the usual 10msec or 100msec
322328
// for it to start up.
323329

330+
// Flip back and forth between processing the first and second buffers.
324331
uint32_t *buffer = first_buffer;
325332
DmacDescriptor* descriptor = audio_dma.descriptor;
326333
if (buffers_processed % 2 == 1) {
@@ -342,15 +349,13 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
342349
}
343350
values_output++;
344351
}
352+
345353
buffers_processed++;
346354

347-
// See if we need to transfer less than a full buffer for the remaining needed samples.
355+
// We might need fewer than an entire of samples, but we won't try to alter the
356+
// last DMA, which might already be in progress, so we'll just throw away some
357+
// samples at the end.
348358
remaining_samples_needed = output_buffer_length - values_output;
349-
if (remaining_samples_needed > 0 && remaining_samples_needed < samples_per_buffer) {
350-
descriptor->BTCNT.reg = remaining_samples_needed;
351-
descriptor->DSTADDR.reg = ((uint32_t) buffer) + remaining_samples_needed * words_per_sample;
352-
descriptor->DESCADDR.reg = 0;
353-
}
354359
}
355360

356361
stop_dma(self);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy