Assembler NeoPixel Driver for RP2040 Boards


As part of my testing of the latest version of uLisp on the RP2040-based boards I wrote an assembler routine to control the NeoPixel LED provided on the Adafruit Feather RP2040 and Adafruit QT-Py RP2040 boards. In case anyone’s interested, here’s what I did.

First install the ARM assembler by copying the source from ARM assembler in Lisp and pasting it into the Serial Monitor.

Define a variable led to specify the NeoPixel pin; on the Adafruit Feather this is:

(defvar led 16)

On the Adafruit QT-Py this is:

(defvar led 12)

Make this pin an output with:

(pinmode led :output)

On the Adafruit QT-Py the NeoPixel is powered by pin 11, so you need to make this an output too, and make it high, with:

(pinmode 11 :output)
(digitalwrite 11 :high)

The machine-code routine uses a macro pulse4 to generate the instructions for the correct pulse delays:

(defun pulse4 (n)
   ($str 'r3 '(r4))
   ($mov 'r5 n)
   ($sub 'r5 1)
   ($bne (- *pc* 2))))

Finally, here’s the assembler code for the NeoPixel driver routine:

(defcode neopixel (a)
  ($push '(lr r5 r4))
  ($ldr 'r4 port-xor)
  ($mov 'r1 1)
  ($lsl 'r3 'r1 led)
  ($lsl 'r1 23)
  ($tst 'r0 'r1) ; test if bit is 1
  ($bne one)
  (pulse4 12)
  (pulse4 26)
  ($b next)
  (pulse4 25)
  (pulse4 14)
  ($lsr 'r1 1)
  ($bne nextbit)
  ($pop '(r4 r5 pc))
  ($word #xd000001c))

After defining the assembler routine you should be able to light up the NeoPixel in any colour with the command:

(neopixel #xggrrbb)

where #xggrrbb is a hexadecimal number specifying the green, red, and blue intensities. So, for example, the following call makes it orange:

(neopixel #x070f00)

For more details about controlling NeoPixels see: ARM NeoPixel driver using assembler.