Datasheet

Table Of Contents
21 jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
22 do_one:
23 jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse
24 do_zero:
25 nop side 0 [T2 - 1] ; Or drive low, for a short pulse
26 .wrap
This program shifts bits from the OSR into X, and produces a wide or narrow pulse on side-set pin 0, based on the value
of each data bit. Autopull must be configured, with a threshold of 24. Software can then write 24-bit pixel values into the
FIFO, and these will be serialised to a chain of WS2812 LEDs. The .pio file contains a C helper function to set this up:
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/master/pio/ws2812/ws2812.pio Lines 31 - 47
31 static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq,
Ê bool rgbw) {
32
33 pio_gpio_init(pio, pin);
34 pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
35
36 pio_sm_config c = ws2812_program_get_default_config(offset);
37 sm_config_set_sideset_pins(&c, pin);
38 sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24);
39 sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
40
41 int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
42 float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
43 sm_config_set_clkdiv(&c, div);
44
45 pio_sm_init(pio, sm, offset, &c);
46 pio_sm_set_enabled(pio, sm, true);
47 }
Because the shift is MSB-first, and our pixels aren’t a power of two size (so we can’t rely on the narrow write replication
behaviour on RP2040 to fan out the bits for us), we need to preshift the values written to the TX FIFO.
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/master/pio/ws2812/ws2812.c Lines 15 - 17
15 static inline void put_pixel(uint32_t pixel_grb) {
16 pio_sm_put_blocking(pio0, 0, pixel_grb << 8u);
17 }
To DMA the pixels, we could instead set the autopull threshold to 8 bits, set the DMA transfer size to 8 bits, and write a
byte at a time into the FIFO. Each pixel would be 3 one-byte transfers. Because of how the bus fabric and DMA on
RP2040 work, each byte the DMA transfers will appear replicated four times when written to a 32-bit IO register, so
effectively your data is at both ends of the shift register, and you can shift in either direction without worry.
More detail?
The WS2812 example is the subject of a tutorial in the Raspberry Pi Pico C/C++ SDK document, in the
PIO chapter. The tutorial dissects the ws2812 program line by line, traces through how the program
executes, and shows wave diagrams of the GPIO output at every point in the program.
RP2040 Datasheet
3.6. Examples 368