Controlling the WS2812 with STM8 eForth was something I've had on my to-do list for a long time. The lore of W2812 timing is already long and twisted, and any new implementation, it seems, has to add a bit to it :-)
Mine is the following:
Do it the Aristotle way: Relax the timing but maintain the balance!
I coded the inner loop for a byte transfer and the bit timing in assembly (in a self balancing way). The outer loop is coded in Forth. The result is quite compact:
: WS2812 ( a1 a0 -- ) DO [ $1601 , \ LDW Y,(1,SP) $90F6 , \ LD A,(Y) $88 C, \ PUSH A $A608 , \ LD A,#8 ] [ 1 PB_ODR 4 ]B! [ $0901 , \ RLC (1,SP) $9D C, \ NOP $2504 , \ JRC 1$ ] [ 0 PB_ODR 4 ]B! [ $9D C, \ 1$: NOP $9D C, \ NOP $9D C, \ NOP $2404 , \ JRNC 2$ ] [ 0 PB_ODR 4 ]B! [ $9D C, \ 2$: NOP $4A C, \ DEC A $4D C, \ TNZ A $26E5 , \ JRNE 0$ $84 C, \ POP A ] LOOP ;
I tested the code by comparing the sensitivity of the reshaped bit timing at the output of the WS2812B.
The code and some findings are here.