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

Esp32: Support I2s 24 parrallel mode #270

Closed
Makuna opened this issue Jun 6, 2019 · 14 comments
Closed

Esp32: Support I2s 24 parrallel mode #270

Makuna opened this issue Jun 6, 2019 · 14 comments
Labels
enhancement pending Pending new release; already merged but not released in a version

Comments

@Makuna
Copy link
Owner

Makuna commented Jun 6, 2019

Is your feature request related to a problem? Please describe.
Esp32 i2s supports a 24bit parrellel mode; where each bit of 3 byte packet is sent to different pins. This could be exploited to support 24 parrallel NeoPixel busses.

Describe the solution you'd like
FastLED has support for this.
Code is here
Discussion is here

Additional context
Currently using this method will require each bus to be same count and pixel data width (RGB or RGBW).
FastLED requires this to be the same color element order but this is a minor limitation in their implementation.
An example of i2s being used in 8 bit mode?
Focus has been on 8bit mode since it is a good balance of resources (memory/pins) and speed. I stumbled getting this to work due to I2s0 vs I2s1 Parrallel.

@r1dd1ck
Copy link

r1dd1ck commented Jun 16, 2019

This would be great 👍

But I'm somewhat concerned about the performance hit this will most probably take, as the update routine is a lot heavier than what is required by all the other methods 😐

And I'm not sure I understand the reasons behind your list of limitations 😯

Same pixel count?
Can't you just fill the data for the "shorter strips" with zeroes to match the bus with most pixels?

Same pixel data width?
Filling the last byte of the 24bit (RGB) vs 32bit (RGBW) pixel difference with zeroes will result in a 10μs LOW period on the output between each pixel. This should be not enough to cause a RESET, so I think it should be possible to solve even this "issue".

At this point, the only plausible limitation, to me, seems to be the overall update rate (or frame rate) - which would need to be the same across all channels. But with a little effort, I'm sure that even that could be solved (although not very sure whether it would be worth it)..

@hpwit
Copy link

hpwit commented Oct 22, 2019

in theory it will be possible with the same code to drive RGBW and RGB over the 24 pins
I just did not wrote it yet. but I could look at it

@Makuna
Copy link
Owner Author

Makuna commented Oct 23, 2019

(currently still capturing needs and requirements, don't let my original comments stop you from providing good feedback).

@embedded-creations
Copy link
Contributor

embedded-creations commented Dec 13, 2021

I'm starting to think about how to implement this. The main challenge I see is allowing each bus to be used independently, though all busses are shifted out in parallel (calling bus0.show() would shift out the pixels for all busses using the method, not just bus0). It wouldn't be a problem to call bus0.show() (which shifts out the pixels) followed by bus1.show() (which should do nothing) if the I2S Parallel method resets the dirty bit on all the busses using I2S Parallel. I don't see a good way to call ResetDirty() for all busses from a method though.

Another challenge is initializing the I2S peripheral appropriately for the number of parallel strips and the length of the strips. If treating each bus as independent as possible, calling bus0.Begin() should initialize the I2S peripheral, but the method won't have enough information on how many strips will be used, or the number of bytes in the longest strip. We could create three separate methods for 8, 16, and 24 bit parallel. We could limit the longest strip to the length of the first strip that calls Begin(). Or, we could require calling SetMethodSettings with a new SettingsObject passing that information to the method before Begin(). More challenging would be dynamically resizing the buffers and reconfiguring the I2S peripheral as new busses are added.

Thoughts @Makuna?

@hpwit
Copy link

hpwit commented Dec 13, 2021

Hello in the fastLED library I have implemented the 24 way i2s parallel bus for esp32.
i have reimplemented it in this https://github.com/hpwit/I2SClocklessLedDriver
But only for 16 // because if you go more than 16 you do not have enough pin left for extra stuff on the esp.
hence I have done virtual pins driver which allows you to drive 120 // pin thanks to shift registers
https://github.com/hpwit/I2SClocklessVirtualLedDriver

Let me know what you think
Yves

@embedded-creations
Copy link
Contributor

@hpwit Thanks for the links Yves! I knew you wrote the FastLED driver but didn't know you had separate repositories with lots of documentation too. What is the license on your code? I'm assuming MIT license as you contributed to the MIT License FastLED project, but it would be helpful if you added a license file to your repositories to be sure.

@Makuna
Copy link
Owner Author

Makuna commented Dec 13, 2021

@embedded-creations This issue with using a single bus (and thus removing the confusing dirty and show issues) is that they would then use a single type of LED feature. This sort of feature was tracked by #160. Espresif has documented but not supplied/exposed a lag fix for all 8 channels of RMT. It would require a single "Show" solution from my library; so I have been thinking about how to fix this internally. And my current design is not a monolithic bus, but a new method series for ESP32 would be exposed that share a static (think global) dirty state and a single show will trigger all (first declared bus or any show triggers is still a design consideration).

@hpwit So in reality we have two implementations.

  • Use the inherent 24 parallel output of the ESP32 I2s.
  • Use an external shift register(s) to convert the serial stream to n channels of parallel output.

ESP32 I2s Parallel output:

  • I believe this mode requires 24 bits always. So, there is memory waist for channels unused and for any single bus less than the longest length of a bus.

Shift Register Output:

  • Still uses the I2s parallel output, but two bits are reserved for the clock and latch.
    Q: Is the clock really just a bit in the stream? If so, this would double the amount of memory as the state of the clock needs cycle twice as fast as the data.

@embedded-creations
Copy link
Contributor

embedded-creations commented Dec 13, 2021

I believe this mode requires 24 bits always

It doesn't, I use I2S parallel output in both 8bit and 16bit mode in SmartMatrix Library.

Q: Is the clock really just a bit in the stream

I've looked at Yves' implementation before, clock is the I2S Clock output, not a data output. Latch is a data output, that's why the total output is only 8x15=120 strips (not 8x16) with 16-bit I2S.

@Makuna
Copy link
Owner Author

Makuna commented Jan 17, 2023

Working Branch: https://github.com/Makuna/NeoPixelBus/tree/Esp32I2sX
Current Status, tested for ESP32 for single and 8 bit.
Next will be testing for ESP32S2 modules.

@hpwit
Copy link

hpwit commented Jan 17, 2023

Nice let me know how it goes.

@Makuna
Copy link
Owner Author

Makuna commented Jan 27, 2023

https://github.com/Makuna/NeoPixelBus/tree/Esp32I2sX
Will be merging this into the main branch within the week.
Supports ESP32 and ESP32S2 (C3 and S3 can't use i2s for parallel mode, they have a new LED peripheral).
Supports x8 and x16 channel modes. I didn't even try 24 bit mode but I am unsure more than 16 will ever be used and testing matrix was already taken a long time due to S2 being different let along i2s0 and i2s1 on ESP32 being different.

@Makuna
Copy link
Owner Author

Makuna commented Jan 27, 2023

Merged in. If someone every really needs x24 then create a new issue and I will look into it. Is there even 24 pins available?

@Makuna Makuna added the pending Pending new release; already merged but not released in a version label Jan 27, 2023
@hpwit
Copy link

hpwit commented Jan 28, 2023

Hello
You have only 22 outpins on the regular esp32. I did the same limit to 16 pins output. I have made the i2svirtualclocklessleddriver that allows you,using shift registers, to driver 8 // strips per esp32 pins. And this over 15pins. Hence you can drive 120 strips in parrallel. I use this for my panel. I use 4 pins to drive 16 strips (clock, latch, 2 x data) so I have pins available to drive sd card, i2c Nintendo controller ….

@Makuna
Copy link
Owner Author

Makuna commented Feb 3, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement pending Pending new release; already merged but not released in a version
Projects
None yet
Development

No branches or pull requests

4 participants