-
Notifications
You must be signed in to change notification settings - Fork 373
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
Feature request: Add full-duplex mode for I2S peripheral #1055
Comments
There is already input and output I2S support. You can instantiate both (or up to 4 total I2S interfaces, in fact...limited by DMA channels) with the same or different params. I don't think there'd be any savings in terms of compute, RAM, etc. in somehow merging the 2 together (and you'd have 1/2 the PIO FIFO space which may be a problem). |
I think the benefit of processing the OSR and ISR (Input and output shift registers) of the PIO at once would be saving at least the PIO SMs. Also, in that case the CB could be used to process both the incoming audio and generating the audio output stream. I have at least a dozen of use cases (including Vult DSP), which would greatly benefit from this. |
From my experience, it's the PIO instruction memory that gets exhausted first, not the SMs (c.f. the cool PIO-USB stuff which uses all 32 insns on a single SM). :) Because there are no You would save a couple pins, though, which might be handy. Also, two DMAs would be required and so you'd have 2 separate IRQs to handle, anyway. There's no bidir DMA option. You might be able to just assume the other one will fire, too, but it's awkward and open-loop at that point which feels unstable. |
Another way to achieve a similar outcome would be to implement slave input - using the same BCKL/LRCLK GPIO pins as the output PIO program is setting. The PIO code would have a interrupts on each of these signals. |
Unfortunately it's not possible to drive a PIO off of an input pin, only the system clocks. So any kind of slave mode is troublesome. I think you've got to run several multiples the frequency of the signal (to ensure you sample at proper setup/hold time). The PIO serial ports have this architecture, but they run at a much lower frequency...at I2S bit frequencies I don't think it's possible. To get something like this you'd probably need a new I2S input PIO program and start it at exactly the same time as the I2S output clock. They would run in lockstep and you'd be operating in open loop mode, shifting in at the computed times. There are methods of triggering both starts off of an IRQ, too, but in the end your I2S input is really just an open loop shift-in program. |
Thanks Earle, You are absolutely correct for trying to synchronise to an external master clock for outputs. It would be very difficult to meet the I2S timing requirements if the PIO clock wasn't locked to some multiple of BCLK. Even then, just one PIO cycle delay may be too long to meet the BCLK edge to DOUT ready timing requirement (which is around 20nS for several CODECs I use regularly). However, I think slave inputs are still worth considering - if only to save two GPIO pins on a CODEC setup. I was assuming that I could trigger actions via interrupts off GPIO pins for LRCLK and BCLK. With a master-mode Pico output, the issue of clock drift is avoided.
Yes, the PIO clock does need to be greater than BCLK, but a factor of anything more than 4 (and possibly 2) should provide enough accuracy to meet the data setup time requirements, despite clock drift or complete lack of synchronisation. I think a possible issue would likely be that the number of registers available might be exhausted, if an extra counter was needed to position the read near the middle of the bit cycle. Or, maybe just waiting one PIO clock cycle after the BCLK interrupt would be good enough to get a clean bit read. |
Add full-duplex (in+out) mode for I2S using PIO.
The text was updated successfully, but these errors were encountered: