Skip to content

Conversation

@plan44
Copy link

@plan44 plan44 commented Dec 19, 2020

… in case IRQ response time is not fast enough.

[Hi Chris - I know it's been a while since you wrote this. However, in my search of a really flicker-free ESP32 RMT WS281x driver without tons of ballast I found your nice code the cleanest starting point. Maybe you'd still be willing to have a look and merge this fix ;-) The commit message (cited below) and comments in the code describe my changes, I hope in a understandable way. I am also integrating the code into my p44utils/p44lrgraphics library I'm currently porting to ESP32 from linux/openwrt, but that version will have many other changes not related to the glitches. So I thought it'll make sense to post the fix to the original creator's code, for which I'd like to thank you very much, as well as for the clever idea to use the RMT for creating WS281x in the first place. Greetings, luz]

From vast experience gained with my ws281x linux kernel driver for the MT7688 PWM (https://github.com/plan44/plan44-feed/tree/master/p44-ledchain) I used a similar approach to fix occasional (or not so occasional, depending on IRQ load caused by other ESP32 subsystems) visual glitches.

Problem is that when the half-buffer-threshold IRQ is served too late, the RMT will run into stale data (repeat bits it has already sent).

To avoid this, this patch now places a RMT stopper (pulse with delay 0) into the first word of the other buffer half at every ws2812_copy(). When the next IRQ is served in time, that stopper will be overwritten with next pulses to be sent, and everything runs normal. However when the next IRQ is served too late, the RMT will run into the stopper before wrong data gets sent. Hitting a stopper will also cause a TX end IRQ. Now the IRQ routine can check if actually all data was sent. If not, this means the RMT ran into one of the temporary safeguard stoppers. For the LED chain, this means it could not be fully updated, but no wrong colors are visible, either. This allows starting a retry, which, unless current IRQ load is causing too much delay again, successfully updates the entire chain.

With this, ESP32 RMT can output flicker-free WS281x signals. Delayed IRQ response can only cause reduced frame rate because of the retries, but no wrong colors.

… in case IRQ response time is not fast enough

From vast experience gained with my ws281x linux kernel driver for the MT7688 PWM (https://github.com/plan44/plan44-feed/tree/master/p44-ledchain) I used a similar approach to fix occasional (or not so occasional, depending on IRQ load caused by other ESP32 subsystems) visual glitches.

Problem is that when the half-buffer-threshold IRQ is served too late, the RMT will run into stale data (repeat bits it has already sent).

To avoid this, this patch now places a RMT stopper (pulse with delay 0) into the first word of the other buffer half at every ws2812_copy(). When the next IRQ is served in time, that stopper will be overwritten with next pulses to be sent, and everything runs normal. However when the next IRQ is served too late, the RMT will run into the stopper *before* wrong data gets sent. Hitting a stopper will also cause a TX end IRQ. Now the IRQ routine can check if actually all data was sent. If not, this means the RMT ran into one of the temporary safeguard stoppers. For the LED chain, this means it could not be fully updated, *but no wrong colors are visible, either*. This allows starting a retry, which, unless current IRQ load is causing too much delay again, successfully updates the entire chain.

With this, ESP32 RMT can output flicker-free WS281x signals. Delayed IRQ response can only cause reduced frame rate because of the retries, but no wrong colors.
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