Yona-Appletree / LEDscape

Beagle Bone Black cape and firmware for driving a large number of WS281x LED strips.
126 stars 58 forks source link

Keep working row of pixels into PRU RAM, use `devmemkm` for low GPIO latency, new `redbeat` demo, update README. #66

Closed bigjosh closed 3 years ago

bigjosh commented 3 years ago

The main focus of this update was to get rid of the white flashing from issue https://github.com/Yona-Appletree/LEDscape/issues/49. These flashes happened when the PRU was delayed in accessing the GPIO registers in between the initial rising edge and the zero bit falling edge (time period T0H). If this time was stretched long enough, it would cause the zero bit to look like a one bit to the pixels, so they would flash. In practice, this would happen often enough on my installations to be visually distracting.

To fix it, we needed to reduce the jitter in accessing those GPIO lines during the T0H period so that the signal sent was always shorter than a one bit signal would be.

This took a multi-prong approach that included....

  1. Rewriting the WS281X PRU code so that preloaded a full row of pixels into registers and PRU RAM at the beginning of each row cycle. This reduced traffic from the PRU over interconnects to the DDR RAM to 1/24th of the previous level.
  2. Blocking PRU1 from actually writing any signals onto the pins. Previously both PRUs were started with identical code, and these two copies of the code would then pound the exact same GPIO addresses at almost exactly the same time (+/-10's of ns). This caused 2X the traffic at exactly the time you didn't want it (when the bits were changing) and also some very rare and very (otherwise) hard to explain waveforms!
  3. Streamlining the PRU code that writes to the GPIO registers so that as much potential jitter-causing access is moved outside the T0H time. This meant stretching out the T1H waveform, but that is OK because a long T1H is still a T1H, whereas a long T0H is a T1H.
  4. Using full blast dummy writes to the GPIO registers to generate the T0H delay rather than spinning in place. This blocks other requestors from getting access to the interconnect during this critical time period.
  5. Using devmemkm (a new repo) to set the PRIORITY of the PRU's requestor on the interconnects to be the highest in the system. This is what allows us to block other requestors in step 4 above.

Taken individually, each of these changes noticeably reduces the incidence of the flashes. Used together, they eliminate the flashes completely with a wide margin.

Here is what the new WS281X bit waveforms look like (GPIO0, GPIO1, GPIO2 from bottom to top) ...

NewFile6

I've tested this combination for many many hours and under many load conditions and I have not been able to create more than 100ns of jitter on the T0H waveform, which is well within spec. Here is 24 hours of 0-bits under as many stress conditions I could throw at it... NewFile5

You can see that the max T0H is about 280ns, well under the spec'ed max T0H of 500ns. Also note the jitter is <100ns (only visible on the bottom trace since that one is trigger).

Functionally I've had several dozen strings running the black demo next to me for several days and have not seen a single flash.

Note that this approach does slightly lower the frame update rate - probably by about 10%. For my application I am happy to live with this cost for not having flashes, but if anyone really needs every drop of FPS then it would be possible to rework this code and get a 10% speedup over the previous versions by changing the format of the pixel array data passed to the PRU so that it was already in GPIO0 zeros, GPIO1 zeros, ... format rather than RBGW format. LMK if anyone is interested in pursuing this.

Additionally this PR includes a couple of other random improvements, README updates, and a new redbeat demo mode that I use so that I can see if a remote system has lost network connectivity but is still getting power.

Questions, comments, and testing welcome!

Yona-Appletree commented 3 years ago

Thanks for this work, @bigjosh. Apologies for not paying attention to this for a long while. Just starting to get back into things. Merged.