blazoncek / WLED

Control WS2812B and many more types of digital RGB LEDs with an ESP8266 or ESP32 over WiFi!
MIT License
31 stars 0 forks source link

soundreactive: ensure that I2S#0 is not used by NeoPixelBus driver #33

Closed softhack007 closed 1 year ago

softhack007 commented 2 years ago

Another topic to check for the "soundreactive merge": The microphone input driver needs exclusive access to I2S#0, also in case that analog mics are used. The I2S driver is not specific to pins, so it's not enough to check that pins are available.

NeoPixelBus has drivers that utilize I2S0 or I2S1. Not sure under which conditions these drivers are used in WLED. Audioreactive needs I2S#0, so RMT and I2S1 NeoPixelBus driver should be ok to use for LED strips.

The dangerous NeoPixelBus methods are named NeoEsp32I2s0800KbpsMethod, NeoEsp32I2s0Tm1814Method and NeoEsp32I2s0400KbpsMethod. They are in conflict with the audio I2S input driver so should not be used by WLED together with the audioreactive add-on.

https://github.com/blazoncek/WLED/blob/dbe90eb3f53b34876bf99fa9b311715c8fbd5067/wled00/bus_wrapper.h#L97-L133

blazoncek commented 2 years ago

I2S is used after all RMTs are used. That effectively means 9 or 10 LED strips (buses).

As it is unlikely a user may have >8 buses (not impossible, though) it may be enough just inform a user of such conflict as a first step in resolving this.

Another option (which I foreseen) may be to just disable usermod in case when I2S is not available or fall back to analog processing using analogRead().

BTW How does ESP8266 handle I2S?

softhack007 commented 2 years ago

Nor sure about ESP8266 .. maybe @FHeilmann knows more.

It looks like '8266 Neo DMA methods' including Neo800KbpsMethod internally uses I2S, this might be a problem.

https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods#neoesp8266dma800kbpsmethod

blazoncek commented 2 years ago

I did not check source in detail but description says NeoPixelBus moved away from original implementation.

blazoncek commented 2 years ago

One more comment about I2S.

As discussed on Discord, analogRead() will also cause problems when I2S is used for sampling analog microphone. (analogRead() is used for analog buttons (potentiometers))

We have two options in such case: a) detect if any of the buttons is marked analog and disable analog microphone (optionally disabling usermod as well) b) prevent the use of analog button by overriding it in usermod (or possibly implement it in usermod by using I2S sampling)

Regarding DMA (ESP8266) or I2S (ESP32) use for LEDs: it could be possible to enumerate buses and check the type (NeoPixelBus method) used during initialisation of usermod and disable it if I2S is used for LEDs.

FHeilmann commented 2 years ago

https://github.com/espressif/arduino-esp32/issues/4782

there's a rather recent issue on the arduino-espressif32 repo. They suggest trying 2.0.3 of the framework to see if that fixes it.

I know this probably isn't a solution, since WLED uses the specific aircookie version, but maybe we should look into giving that an upgrade as well (when I last checked, the only difference between AC framework and espressif framework are some Kconfig things to reduce binary size)

edit: Moving to a more up-to-date platform would yield the following benefits:

blazoncek commented 2 years ago

This 35250677b91c082a371e046e81e1a1977eb90db8 should prevent I2S use on ESP32.

softhack007 commented 2 years ago

It looks like '8266 Neo DMA methods' including Neo800KbpsMethod internally uses I2S, this might be a problem.

For ESP8266, the story seems to be completely different. The device has one "I2S receive" and one "i2s transmit" unit, both with fixed GPIO pins. So in case users want to attach digital mics to 8266, these GPIO need to be used:

//   DATA      GPIO12
//   BCK/SCK   GPIO13
//   WS/LRCLK  GPIO14

https://github.com/atuline/WLED/blob/d208be89ece9205c9070d90e6734e0ecb1d7785e/wled00/usermod.cpp#L24-L32

So WLED would only need to check that these pins are not assigned to other purpose when I2S input is used - pinManager.allocatePin(). Guess that 'i2s receive' unit cannot be used for sending data to LEDs.

Screenshot_20220808-195946_Google PDF Viewer

blazoncek commented 2 years ago

Do not worry about 12, 13 & 14. Those are not HW accelerated and not recommended for driving WS281x LED strip. On the other hand APA102 benefits those as they are SPI pins as well. Still 8266 is not well suited for AP102 and most controllers do not use those pins for their output.

If you are worried that some other usermod will steal those GPIO the setup() should handle it gracefully if pin allocation fails (disabling the audio usermod). That is why PinManager class exists.

blazoncek commented 1 year ago

I am closing this issue as precautions have been taken to disallow I2S use in case of AudioReactive usermod.