So I've got this gadget, and for convenience it's got a built-in nano-Arduino, or at least an ATmega328P with the Ardunio bootloader installed, and running at 3 Volts-ish and accordingly 8 MHz using the internal oscillator (to save 70¢ and a few square millimeters), and...
Well, out of laziness, I'm using the Adafruit NeoPixel driver to talk to a string of WS2812B addressable LEDs.
Took a bit of fiddling, and for some reason they want 400 KHz instead of the expected 800, or at least if I specify 800 KHz nothing happens, while at 400 they work...
Except that if the supply voltage is a little high, and the temperature is a little low, things get all squirrely, and I've been trying things like increasing the series resistor in the data line from the MCU (helped) and adding a monster bulk cap across the LED-strip supply rails (helped), and...
Well, none of this really solves the problem, so I decided to take a closer look at the timing, though my scope tells me the data rate is exactly the specified 400 KHz. Maybe I need to fiddle with the parameters?
So I start looking at Adafruit_NeoPixel.cpp, and where NEO_KHZ800 is used, and.
There's a comment.
Running 800 KHz on an 8 MHz part requires special low-level bit-bashing code, which is implemented only for ports B and D, those being where standard Arduini keep their DIO pins.
My LED data pin is on Port C. Which isn't supported at all.
So when I selected NEO_KHZ800, the driver did Nothing, because it didn't have the code to handle that data rate, at my MCU's clock frequency, on my nonstandard choice of pin assignments (it happens to be on the right side of the chip, so there).
When I select NEO_KHZ400, it mostly works despite being entirely the wrong data rate by a factor of 2.
Guess I need to copy the block of code for Port B, set it to handle Port C, and tweak it appropriately, 'cause I'm sure not adding a patch wire to that QFN.
Update: Yup. Seems to work. Now to stick one of the reprogrammed prototypes in the freezer for a while.