STM8 WS2812B Bitbang Routines

This is the version of the code to drive WS2812Bs that actually worked on my STM8S103F3 board. The actual bit timing is pretty close to as fast as possible (if you are calling the bit sending routines back to back with no code in between it will be exactly the minimum 1.25us total bit duration), however to avoid a string reset, you only have about a 4usec grace period (approximately 64 instructions) between sending bits.

I ended up rewriting the whole thing in assembler so that I don't have to babysit the compiler's code generation.

// This code is based on the timing info from https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-...
// Yes, I know that it doesn't match the datasheet.

void WS_1Bit()
// total time including call/ret must be >= 1.25us (20 cycles @16MHz)
{
__asm__("bset 0x5000,#3"); // A3 high
__asm__("nop"); // for 10 cycles (bset, 9 nop)
__asm__("nop"); // 625ns total
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");

__asm__("bres 0x5000,#3"); // A3 low
__asm__("nop"); // for 10 cycles (bres, nop, ret (4c), next call (4c))
// 625ns total

}

void WS_0Bit()
// total time including call/ret must be >= 1.25us (20 cycles @16MHz)
{
__asm__("bset 0x5000,#3"); // A3 high
__asm__("nop"); // for 5 cycles (bset, 4 nop)
__asm__("nop"); // 312.5ns total
__asm__("nop");
__asm__("nop");

__asm__("bres 0x5000,#3"); // A3 low
__asm__("nop"); // for 15 cycles (bres, 6 nop, ret (4c), next call (4c))
__asm__("nop"); // 937.5ns total
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");

}