So far you've seen how to use PIO to send data to NeoPixels, but the data also has to be in the correct format: Each 8 bits sent has to describe a part of 8 different pixels, one in each strip.

This means re-formatting the bits that make up the pixels. There is a function do this quickly in the CircuitPython core, but below will explain it in this section with diagrams and Python code.

Normally, color data for NeoPixels is stored in memory as a series of 24-bit (sometimes 32-bit) values, with one pixel after another.

See how the bits for each color now have a vertical orientation? After rearrangement, it's like the data has been rotated 90 degrees (or "transposed", to use a more mathematical term. 

When the shift register receives each group of data, it sends the "bit 0" column to the first strand, the "bit 1" column to the second strand, and so forth.

The Python code shown below transforms the data of 8 strands into data for the shift register:

n = len(strand_data[0])
buf = bytearray(n*8)
for output_idx in range(n*8):    # For each output byte, ...
    input_idx = output_idx >> 3
    input_bit = 0x80 >> (output_idx & 0x7)
    b = 0
    for strand_idx in range(8):  # Find 8 input bits
        if strand_data[strand_idx][input_idx] & input_bit:
            b |= 1<<strand_idx   # Place them in the right spot
    buf[output_idx] = b

However, since our goal is raw speed, we don't want to actually perform these steps using interpreted Python code. On RP2040-based boards like the Raspberry Pi Pico there is a function bitops.bit_transpose which contains highly optimized code to perform this transformation.

This guide was first published on Feb 23, 2021. It was last updated on Jun 23, 2024.

This page (Code Walkthrough: Bit Manipulation) was last updated on Mar 08, 2024.

Text editor powered by tinymce.