So - i’ve been thinking about implementations a little bit. I don’t think there’s a lot of code complexity difference between the two implementations. I started this post out thinking i’d show how one set of code is more complex than the other, I ended up being wrong.
Observe, quick implementations of loop bodies for the readers for both sides (just reader code, ignoring data propagation side issues):
// clock/data reader
// wait for clock to transition from low to high:
while(clock_line == lo);
data |= (data_line==hi); data <<= 1;
while(clock_line==hi);
// single line reader
// wait for the data line to transition from low to high
while(data_line==lo);
// wait a clock cycle or few
nop; nop;
// if the data line is still high, our current bit is a 1)
{ data |= data_line == hi }
data <<= 1;
// wait for the data line to go back lo before looping back around up
while(data_line==hi);
However, now imagine if you are interleaving driving the PWM with the above. Again, the code ends up fairly similar
while(data_line==lo) {cycle_pwm; }
cycle_pwm; // here’s our “wait”
data |= (data_line == hi);
cycle_pwm;
data <<= 1;
cycle_pwm;
while(data_line==hi) { cycle_pwm; }
cycle_pwm
while(clock_line==lo) { cycle_pwm; }
cycle_pwm;
data |= 0x01;
cycle_pwm;
data <<= 1;
cycle_pwm;
while(clock_line==hi) { cycle_pwm; }
cycle_pwm
Now, the question is, what about propagating data outwards. What the LPD8806 is other chips did was once they had 24 bits of data, a latch dropped that passed clock/data from cin/din straight to cout/dout. Which means you want a timer for resetting the line back to listening. It also means that noise/interference that happens between the MCU and the LPD8806 continues down the line, possibly getting worse over time.
With the WS2811, though, the signal gets regenerated by the code, which means it probably looks something like:
bitcount=0;
while(bitcount++<24) {
while(data_line==lo) {cycle_pwm; }
cycle_pwm; // here’s our “wait”
data |= (data_line == hi);
cycle_pwm;
data <<= 1;
cycle_pwm;
while(data_line==hi) { cycle_pwm; }
cycle_pwm
}
pass:
bc=0;
while(data_line==lo) {
cycle_pwm;
if(bc++ > XXX) {goto listen; }
cycle_pwm;
}
cycle_pwm;
data_out = data_line;
cycle_pwm;
while(data_line==hi) { cycle_pwm; }
cycle_pwm;
data_out = lo;
cycle_pwm;
goto pass;
There’s still only two pins being accessed (though, one for reading, one for writing). If you want to re-generate the signal for clock/data, however, now you have four pins being accessed. I wonder if that ups the chip complexity enough?
Also - the clock/data line chip needs to run at a higher clock frequency internally, in order to be able to catch transitions between hi/lo on the clock line without missing bits. The WS2811 can run at a lower clock frequency, granted, because the max data frequency is also much lower.
Now, these chips are likely not to be running code, instead, it’s just gates at a low level. Now the fixed frequency of actions by the WS2811 results in a much simpler set of gates/logic I suspect than, say, the LPD8806.
You know, I have an FPGA board here to play with, it might be fun to “write” the LPD8806 and the WS2811 for it, and see what the actual implementations end up looking like, for real, as far as number of gates used.
