smart-leds-rs / apa102-spi-rs

SPI-based Driver for apa102 leds
Apache License 2.0
8 stars 5 forks source link

End frame is bogus and should not be sent #1

Closed therealprof closed 5 years ago

therealprof commented 5 years ago

The code does send the "end frame" here:

https://github.com/smart-leds-rs/apa102-spi-rs/blob/198fff148daed9d98d9431609ac5e4e7208033cb/src/lib.rs#L57

But as a matter of fact that frame is bogus and will result in the first LED which not addressed by code to be fully lit after the second run of any sequence. This has also been confirmed a while ago here: https://cpldcpu.wordpress.com/2014/08/27/apa102/

sajattack commented 5 years ago

PRs welcome ;)

twitchyliquid64 commented 5 years ago

But as a matter of fact that frame is bogus and will result in the first LED which not addressed by code to be fully lit after the second run of any sequence. This has also been confirmed a while ago here: https://cpldcpu.wordpress.com/2014/08/27/apa102/

The end frame is important as it provides clock transitions for the peripheral to finish cascading the LED data down. Because the APA102 protocol is implemented as a cascading set of latches which themselves zero out the data line until they have been addressed, the outgoing clock signal is inverted relative to the incoming clock signal. The additional clock cycles are needed to push remaining data down the chain.

So the postamble needs to be there, and I'll submit a PR in a second that puts it back.

As for addressing your issue:

the first LED which not addressed by code to be fully lit after the second run of any sequence.

This will happen if:

I'm adding an additional constructor in the PR I'm submitting that will allow you to support these. For the latter situation, set invert_postamble to true. For the former, set postamble_length to ceiling(num_leds/16).

therealprof commented 5 years ago

You have a run of more than 64 LEDs, in which case you need a longer preamble

No, in fact I'm using 4 LEDs but there're 16 in the chain. With the postamble the 5th LED is always fully lit.

You have a mismatch between the number of LEDs on the chain and the number you are addressing in software.

Indeed.

For the former, set postamble_length to ceiling(num_leds/16).

So 1 in my case? Which yields the wrong result.

I agree that removing postamble is not ideal because it it defers the application of a change to the last LED until next preamble which is usually not noticeable unless the changes are very slow.

twitchyliquid64 commented 5 years ago

No, you're case 2 (you have less than 64 LEDs), so you would set invert_postamble.

The protocol was not designed to support addressing less LEDs than on the chain. The hack provided by invert_postamble enables you to do this, but given its non conforming it should not be default behaviour.

twitchyliquid64 commented 5 years ago

I was chatting about the LEDs with a colleague (who also happens to be interested in embedded + blinky shit) and he pointed out there is a clone called the SK9822 which is meant to use an identical protocol, but has an errata (specifically, the end frame must be all zeros). He pointed me at this post.

Posting this here in the off chance you are using those LEDs. If you are, invert_postamble should do the trick.

therealprof commented 5 years ago

The protocol was not designed to support addressing less LEDs than on the chain. The hack provided by invert_postamble enables you to do this, but given its non conforming it should not be default behaviour.

Says who?

Posting this here in the off chance you are using those LEDs.

Nope, I'm using APA102C.

twitchyliquid64 commented 5 years ago

Says who?

I assume you're referring to my assertion around addressing less LEDs than on the chain, rather than the bit about non-conformance (which is evident from the datasheet).

This is my assertion. The protocol is basically a reverse shift register with a magic sequence to reset latched values. Given the requirements around clocking (an additional cycle to clock the remaining bit for every two LEDs), there is no conforming implementation that permits you to address less LEDs than on the chain, without messing with the remaining LEDs on the chain.

Nope, I'm using APA102C.

In that case, either setting the inversion or addressing the same number of LEDs as on your chain should work.