From aabb56c840456dfdd065c8ca2e11854f32c5a63c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 22 Nov 2019 13:54:37 -0600 Subject: [PATCH] nrf: i2sout: Only update hold_value when appropriate If we put no samples into the buffer, then there is no last sample to fill out hold_value with. (and, in fact, the expression such as *(uint32_t*)(buffer-4) is outside an allocated region) Detect this condition, and leave the prior value in place. This improves clicks heard when pausing and resuming a waveform. --- ports/nrf/common-hal/audiobusio/I2SOut.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/ports/nrf/common-hal/audiobusio/I2SOut.c b/ports/nrf/common-hal/audiobusio/I2SOut.c index ac369277f2..5a53f66d27 100644 --- a/ports/nrf/common-hal/audiobusio/I2SOut.c +++ b/ports/nrf/common-hal/audiobusio/I2SOut.c @@ -108,6 +108,7 @@ void choose_i2s_clocking(audiobusio_i2sout_obj_t *self, uint32_t sample_rate) { static void i2s_buffer_fill(audiobusio_i2sout_obj_t* self) { void *buffer = self->buffers[self->next_buffer]; + void *buffer_start = buffer; NRF_I2S->TXD.PTR = (uintptr_t)buffer; self->next_buffer = !self->next_buffer; size_t bytesleft = self->buffer_length; @@ -157,15 +158,17 @@ static void i2s_buffer_fill(audiobusio_i2sout_obj_t* self) { // Find the last frame of real audio data and replicate its samples until // you have 32 bits worth, which is the fundamental unit of nRF I2S DMA - if (self->bytes_per_sample == 1 && self->channel_count == 1) { - // For 8-bit mono, 4 copies of the final sample are required - self->hold_value = 0x01010101 * *(uint8_t*)(buffer-1); - } else if (self->bytes_per_sample == 2 && self->channel_count == 2) { - // For 16-bit stereo, 1 copy of the final sample is required - self->hold_value = *(uint32_t*)(buffer-4); - } else { - // For 8-bit stereo and 16-bit mono, 2 copies of the final sample are required - self->hold_value = 0x00010001 * *(uint16_t*)(buffer-2); + if(buffer != buffer_start) { + if (self->bytes_per_sample == 1 && self->channel_count == 1) { + // For 8-bit mono, 4 copies of the final sample are required + self->hold_value = 0x01010101 * *(uint8_t*)(buffer-1); + } else if (self->bytes_per_sample == 2 && self->channel_count == 2) { + // For 16-bit stereo, 1 copy of the final sample is required + self->hold_value = *(uint32_t*)(buffer-4); + } else { + // For 8-bit stereo and 16-bit mono, 2 copies of the final sample are required + self->hold_value = 0x00010001 * *(uint16_t*)(buffer-2); + } } // Emulate pausing and stopping by filling the DMA buffer with copies of