smart-leds-rs / ws2812-spi-rs

Use ws2812 on rust with embedded-hal spi
Apache License 2.0
68 stars 25 forks source link

Use `Write` trait in `prerendered` module. #23

Open reitermarkus opened 3 years ago

reitermarkus commented 3 years ago

Hi,

I had quite some difficulty getting this to work on a Raspberry Pi using rppal. I finally figured out it was because FullDuplex is too slow since it sends every byte individually. Since the embedded_hal::blocking::spi::Write trait allows sending a complete byte slice, it works well with the prerendered approach. Should the prerendered module also use the Write trait?

david-sawatzke commented 3 years ago

On most mikrocontrollers, the HAL implementations wait for each byte to be received before sending the next one. This is a bit too slow for this code and thus leads to issues, which is why we deliberately introduce the offset using FullDuplex, so we can send the next byte while the previous one is still transmitted.

Does using the Write trait make it work on the Raspberry Pi?

reitermarkus commented 3 years ago

Yes, with Write it works on the Raspberry Pi. I tried first with https://github.com/jgarff/rpi_ws281x, which worked correctly, so I then dug into the source code and found it does a transfer of a complete prerendered buffer. So either embedded_hal::blocking::spi::Transfer or embedded_hal::blocking::spi::Write would work.

david-sawatzke commented 3 years ago

Mmh, Write won't work on many MCUs, so we have to add some kind of configuration.

I think it may make more sense to split it into yet another module, since the long low time at the end (and possibly at the start) won't work as a separate call on all linux platforms, but it would take a lot of ram on MCUs to add it in the buffer.

I think a separate backend based on prerendered would be the best option (hosted?).

Perhaps even with std so no need to pass a separate buffer.

@reitermarkus Does that sound reasonable to you?

D1plo1d commented 3 years ago

Sorry to jump on this with a bit of a sidetrack, I've been trying to use ws-2812-spi with https://crates.io/crates/esp-idf-hal which lacks a FullDuplex implementation - would the Write or Transfer implementation be able to bring esp-idf compatibility as well?

david-sawatzke commented 3 years ago

@D1plo1d That could work, there might be various factors (slow transmit function, interrupts during sending) that mean it doesn't. The only way to find out is trying it.

andy31415 commented 2 years ago

I had a similar issue on STM32F0 devices: FullDuplex is not implemented, however blocking::spi::Write and others are.

I created a patch https://github.com/smart-leds-rs/ws2812-spi-rs/pull/28 that converts everything to write, however I am not sure if that has sideffects in other implementations. It does work on a STM32F030C8Tx and I would expect it to work on ESP and RPI (Those devices should be fast). Unsure what sideffects it would have on slower devices.

Maybe creating a feature that chooses between fullduplex and write would help.