I'm working with the Elegoo Arduino Uno R3 and WS2812B addressable led strip.
I have been using the FastLED library (GitHub - FastLED/FastLED: The FastLED library for colored LED animation on Arduino. Please direct questions/requests for help to the FastLED Reddit community: http://fastled.io/r We'd like to use github "issues" just for tracking library bugs / enhancements.), but for two reasons I don't want to keep using it: 1) I want to do it myself and 2) I want to cut out as much memory usage as I can.
To assign a color to the first LED, I need to send 24 bits (one byte per color component). As per the data sheet (WS2812B Datasheet - Parallax Inc. | DigiKey) to send a 1 I first put the output pin high for 800 nanoseconds then put it low for 450 nanoseconds. The reverse for sending a 0, 400 nanoseconds high and 850 nanoseconds low. Then leave it low for at least 50 microseconds to set the internal latch.
Since I will need to utilize inline assembly to make this work. I'm familiar with IBM/370 assembly and C#, but not as familiar with C++ or AVR assembly. So this is where I need some help.
I am looking at the instruction set (http://ww1.microchip.com/downloads/en/DeviceDoc/AVR-Instruction-Set-Manual-DS40002198A.pdf). I know that every clock cycle at 16 megahertz is 62.5 nanoseconds. So I want to use instructions that have a well defined number of cycles to execute, SBI and CLI, happen to either take 2 or 1 cycles to complete. That's not a big deal, I can use another time-keeping instruction that is only 1 cycle to allow for enough exactness to compensate for the uncertainty of whether SBI and CLI are 1 or 2 cycles and still fall within the +/- 150 nanosecond variance window. I chose MOV since I can move data from R1 to R1 without changing register values and it is 1 cycle instead of the 2 cycle NOOP.
So, with all that in mind. I concocted these two lines of inline assembly:
#define SEND_0 __asm__ ( "sbi 6,0;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "cbi 6,0;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" );
#define SEND_1 __asm__ ( "sbi 6,0;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "cbi 6,0;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" "mov r1,r1;" );
But when I write "SEND_1" 24 times in a row on the setup() call, the first LED does not turn white. What am I doing wrong with my timing? Is there an issue with my code?
Thanks for your time.