uint16_tcount=WS2812B_NB_LEDS*24+1;// the number of bits to transfer: R+G+B (8+8+8=24) per LED on a channel, plus one because of the loop implementation
uint8_thigh=WS2812B_PORT|WS2812B_MASK;// set all WS2812B pins to high
uint8_tlow=WS2812B_PORT&~WS2812B_MASK;// set all WS2812B pins to low
uint8_t*next=color_bits;// a pointer to the next color bit
uint8_tout=low|*(next++);// the next bit to send
while(!reset_code);// wait for previous reset code to finish
// use inline assembly to handle precise timing constraints, and volatile to prevent optimisation of the code
cli();// disable interrupt for time cirtical code
__asm____volatile__(
"0:""\n\t"// clock start,duration,stop instruction (use local label = number)
"out %[port], %[high]""\n\t"// -1,1,0 start bit, set signal to high
"sbiw %[count], 1""\n\t"// 0,2,2 decrement the number of bits to send (do it here to be able to compare immediatly)
"breq 1f""\n\t"// 2,1-2,3-4 if this was the last bit, start the reset procedure (go "f"orward to 1)
"or %[out], %[low]""\n\t"// 3,1,4 combine bit and port values
"nop""\n\t"// 4,1,5 wait before outputing bit value
"out %[port], %[out]""\n\t"// 5,1,6 output bit value
"ld %[out], %a[next]+""\n\t"// 6,2,8 load next bit value
"nop""\n\t"// 8,1,9 wait before outputing low
"nop""\n\t"// 9,1,10 wait before outputing low
"nop""\n\t"// 10,1,11 wait before outputing low
"nop""\n\t"// 11,1,12 wait before outputing low
"out %[port], %[low]""\n\t"// 12,1,13 ensure signal is low
"nop""\n\t"// 13,1,14 wait before going to next bit
"nop""\n\t"// 14,1,15 wait before going to next bit
"nop""\n\t"// 15,1,16 wait before going to next bit
"nop""\n\t"// 16,1,17 wait before going to next bit
"rjmp 0b""\n\t"// 17,2,19 start next bit (go "b"ack to 0)
"1:""\n\t"// start sending reset code (use local label = number)
:// output operands
[count]"+w"(count),
[out]"+r"(out)
:// input operands
[port]"I"(_SFR_IO_ADDR(WS2812B_PORT)),
[high]"r"(high),
[low]"r"(low),
[next]"e"(next)
);
sei();// re-enable interrupts
/* send reset code */
WS2812B_PORT=low;// set to low (for at least 50 us)
reset_code=false;// block further transmission
TCCR0B|=(0<<CS02)|(1<<CS01)|(0<<CS00);// start reset code waiting time (with a prescale of 8)