Skip to content
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

Bidirectional I2S #9909

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft

Bidirectional I2S #9909

wants to merge 20 commits into from

Conversation

relic-se
Copy link

@relic-se relic-se commented Dec 23, 2024

New class, audiobusio.I2S, which can be used to both record and playback audio over a unified I2S bus (single pair of bit clock and word select pins).

Notes:

  • This functionality currently relies on PIO and is only functional on RP2xxx boards. I am not familiar with the architecture of other boards which implement the audiobusio module: Atmel SAMD, Espressif ESP32, or i.MX RT1020. Support for these boards (if possible) would likely have to come in later updates.
  • The interface is mostly synonymous with audiobusio.I2SOut except that data pin direction needs to be specified in keyword, ie: data_out=..., data_in=....
  • Keyword arguments are available to specify sample_rate, bits_per_sample, channel_count, etc, but are only necessary if utilizing input. Otherwise, the bus will use the parameters of the sample argument. If the bus is bidirectional and a sample is played that does not match the input parameters, a relevant ValueError will be thrown.
  • The audio dma system has been modified to allow bidirectional or input-only operation.
  • Testing has been conducted with a Pimoroni Pico Plus 2, an ICS43434 I2S microphone and a PCM5102A I2S DAC.

Comments:

  • I worry about delays potentially caused by waiting on the input buffer during audiobusio_i2s_get_buffer.
  • I'm calling RUN_BACKGROUND_TASKS when using the bus as an input only while waiting for the incoming buffer. When the bus is operating bidirectionally, it waits with a sample-length sleep loop. There is likely a better solution out there.
  • I've created a separate audiobusio.I2SIn that I was testing with initially. I plan on removing this class before marking the PR as ready.

Todo:

  • Support mono input with stereo output.
  • Fix mismatched buffer sizes.
  • (optional) Add record method (or similar) to get current input buffer. Could be useful for monitoring input level.

@relic-se
Copy link
Author

I've located a new bug. When using a buffer size on audiomixer.Mixer or an audio effect that is less than that of audiobusio.I2S, the audio distorts significantly.

import board
import audiobusio
import audiomixer

codec = audiobusio.I2S(
    bit_clock=board.GP0,
    word_select=board.GP1,
    data_in=board.GP2,
    data_out=board.GP3,
    sample_rate=22050,
    buffer_size=1024,
)

mixer = audiomixer.Mixer(
    voice_count=1,
    sample_rate=22050,
    buffer_size=512,
)

codec.play(mixer)
mixer.play(codec)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant