Skip to content

Add support for clockless SPI #12

Closed

Activity

  1. mlandauer commented on Oct 5, 2026

    @mlandauer
    Contributor

    @ahdinosaur just wanted to give you a heads up that I'm working on this issue.

    First, I wanted to give you my motivation. I've been hitting up against timing issues with the RMT driver for an 8x8 ws2812 display on an esp32s3. To cut a long story short, the problem shows up most when using probe-rs and logging while updating the display which is probably why it's been less obvious for you (Based on the code I'm assuming you're mostly focused on using esp32 and espflash). I'm confident that the issue has nothing to do with blinksy because I can reproduce it coding a simple example from scratch using rmt.

    I tested out an SPI driver for ws2812, hooking up spi with DMA enabled and the problem went away.

    This seemed like a good opportunity to put together a more general SPI driver for clockless LEDs that was less "hacky" and could work with whatever timing the LED requires and with an understanding of the timing tolerances of the LED timings that allows the SPI approach to work.

    The approach I'm taking is as follows:

    • Wrapping the spi traits from embedded-hal and embedded-hal-async so it can work everywhere those traits work
    • Rather than hardcoding a specific way of encoding the bits (with a particular assumed SPI clock rate) the driver calculates the bit encoding based on the knows SPI clock rate.
    • Because the buffer (for the encoded bits sent to SPI) size needs to be known at compile time and that depends on the spi clock frequency, that needs to be a const passed as a generic to the driver.
    • To make things less hard for the user there's also a way of calculating the "ideal" spi clock frequency for the particular led. It basically gives you the lowest clock frequency that gives you an encoding below a target timing threshold. So, for instance with the ws2812, the datasheet gives a tolerance on the timings of the input to be +-150 ns. You can pass this to that function and it will tell you to use an SPI clock frequency of 2.5 MHz to give the best results. This function is also const so it can be used to calculate the const buffer size too.
    • One place I've diverged from how the crate does things right now is that I've used bitvec for all the bit twiddling. One thing that's a bit unpleasant is depending on an unreleased version so that xtensa support works. It seems troublesome because bitvec seems such a relied upon crate but isn't maintained as well as it should be at the moment. Hmmm...

    One question I have is whether to add timing tolerance information to the ClockLessLed trait and if so how general to make it. Maybe that's a question best answered when you can see the code?

    The code is pretty much working. I'm just now tidying it up, trying to bring it in line with how things are being done elsewhere in the crate and adding some docs.

    Hopefully it shouldn't be long before I can submit it as a PR. I hope it fits in with how you were picturing things working.

  2. ahdinosaur commented on Oct 15, 2026

    @ahdinosaur
    OwnerAuthor

    Closed by #112

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions