Skip to content

Bidirectional I2S #9909

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 26 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
bfa7db1
Initial build of I2SIn.
relic-se Nov 13, 2024
0daaeb4
Enable I2SIn on RP2xxx
relic-se Nov 13, 2024
5feb12f
Merge branch 'adafruit:main' into i2sin
relic-se Dec 18, 2024
805a6b1
Remove `record` method.
relic-se Dec 18, 2024
e30e234
Update audio dma to support independent input dma.
relic-se Dec 18, 2024
f1e6f01
Fix pointer issue with dma setup.
relic-se Dec 18, 2024
9a0d1c2
Only reset buffer if output is enabled.
relic-se Dec 18, 2024
d0e2b01
Rename `last_record` to `last_index`.
relic-se Dec 18, 2024
76ac311
Handle dma input write destination.
relic-se Dec 18, 2024
55d3252
Send bit width to start PIO program on `reset_buffer`.
relic-se Dec 18, 2024
be48374
Fix errors within PIO program.
relic-se Dec 21, 2024
3c97fd8
Run background tasks while waiting for next buffer.
relic-se Dec 21, 2024
15384bc
Add bidirectional I2S class.
relic-se Dec 23, 2024
dc6e67e
Start input dma channel before output dma channel to allow blocks to …
relic-se Dec 23, 2024
ececb9c
Remove bug comment.
relic-se Dec 23, 2024
3d1a16d
Merge branch 'adafruit:main' into i2sin
relic-se Dec 23, 2024
1e9d455
Fix formatting errors.
relic-se Dec 23, 2024
c6bdd36
Fix input playback example.
relic-se Dec 23, 2024
05c719f
Add empty files within other port families to fix builds.
relic-se Dec 23, 2024
7c6f010
Add record method.
relic-se Dec 23, 2024
c04489c
Merge branch 'adafruit:main' into i2sin
relic-se Jan 18, 2025
c8499a5
Support 32-bit pio pin mask.
relic-se Jan 18, 2025
1aaf4f1
Return number of samples recorded.
relic-se Jan 22, 2025
851765e
Improve dma initialization.
relic-se Jan 22, 2025
4b82933
Double-buffering and improved buffer testing.
relic-se Jan 23, 2025
d47fdf8
Merge branch 'main' into i2sin
relic-se May 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Improve dma initialization.
  • Loading branch information
relic-se committed Jan 22, 2025
commit 851765e49383c0cfcc6ef51438bc12c7b698fdf1
33 changes: 11 additions & 22 deletions ports/raspberrypi/common-hal/audiobusio/I2S.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,14 @@ void common_hal_audiobusio_i2s_construct(audiobusio_i2s_obj_t *self,
audio_dma_init(&self->dma);
}

void i2s_configure_audio_dma(audiobusio_i2s_obj_t *self, mp_obj_t sample, bool loop, uint32_t sample_rate, uint8_t bits_per_sample) {

void i2s_configure_audio_dma(audiobusio_i2s_obj_t *self, mp_obj_t sample, bool loop, uint32_t sample_rate, uint8_t bits_per_sample, bool force) {
if (self->dma.output_channel[0] != NUM_DMA_CHANNELS || self->dma.input_channel[0] != NUM_DMA_CHANNELS) {
return;
if (self->state_machine.out) {
audio_dma_stop_output(&self->dma);
if (!force) {
return;
}
if (self->state_machine.in) {
audio_dma_stop_input(&self->dma);
}
audio_dma_deinit(&self->dma);

audio_dma_stop(&self->dma);
common_hal_rp2pio_statemachine_stop(&self->state_machine);
}

common_hal_rp2pio_statemachine_set_frequency(&self->state_machine, sample_rate * bits_per_sample * 16);
Expand Down Expand Up @@ -173,7 +170,7 @@ uint32_t common_hal_audiobusio_i2s_record_to_buffer(audiobusio_i2s_obj_t *self,
}

// Make sure that dma is running.
i2s_configure_audio_dma(self, self, true, self->sample_rate, self->bits_per_sample);
i2s_configure_audio_dma(self, self, true, self->sample_rate, self->bits_per_sample, true);

size_t output_count = 0;
int16_t *buffer;
Expand All @@ -182,11 +179,7 @@ uint32_t common_hal_audiobusio_i2s_record_to_buffer(audiobusio_i2s_obj_t *self,
while (output_count < output_buffer_length) {
// Do other things while we wait for the buffer to fill.
while (self->last_record_index == self->dma.input_index) {
if (self->state_machine.out) {
common_hal_mcu_delay_us(1000000 / self->sample_rate);
} else {
RUN_BACKGROUND_TASKS;
}
RUN_BACKGROUND_TASKS;
}
self->last_record_index = self->dma.input_index;

Expand Down Expand Up @@ -229,7 +222,7 @@ void common_hal_audiobusio_i2s_play(audiobusio_i2s_obj_t *self,
}
}

i2s_configure_audio_dma(self, sample, loop, sample_rate, bits_per_sample);
i2s_configure_audio_dma(self, sample, loop, sample_rate, bits_per_sample, true);
self->playing = true;
}

Expand Down Expand Up @@ -311,7 +304,7 @@ void audiobusio_i2s_reset_buffer(audiobusio_i2s_obj_t *self,
mp_raise_NotImplementedError(MP_ERROR_TEXT("Single channel output not supported."));
}

i2s_configure_audio_dma(self, self, true, self->sample_rate, self->bits_per_sample);
i2s_configure_audio_dma(self, self, true, self->sample_rate, self->bits_per_sample, false);
self->last_record_index = -1;
self->last_sample_index = -1;
}
Expand All @@ -331,11 +324,7 @@ audioio_get_buffer_result_t audiobusio_i2s_get_buffer(audiobusio_i2s_obj_t *self

// Do other things while we wait for the buffer to fill.
while (self->last_sample_index == self->dma.input_index) {
if (self->state_machine.out) {
common_hal_mcu_delay_us(1000000 / self->sample_rate);
} else {
RUN_BACKGROUND_TASKS;
}
RUN_BACKGROUND_TASKS;
}
self->last_sample_index = self->dma.input_index;

Expand Down
2 changes: 1 addition & 1 deletion ports/raspberrypi/common-hal/audiobusio/I2S.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ void audiobusio_i2s_get_buffer_structure(audiobusio_i2s_obj_t *self, bool single
uint32_t *max_buffer_length, uint8_t *spacing);

void i2s_configure_audio_dma(audiobusio_i2s_obj_t *self, mp_obj_t sample, bool loop,
uint32_t sample_rate, uint8_t bits_per_sample);
uint32_t sample_rate, uint8_t bits_per_sample, bool force);
Loading