Skip to content

ws2812: use PIO on RP2040/RP2350 transparently via build tags#851

Merged
deadprogram merged 1 commit intotinygo-org:devfrom
gandarez:feat/ws2812-rp2
Apr 7, 2026
Merged

ws2812: use PIO on RP2040/RP2350 transparently via build tags#851
deadprogram merged 1 commit intotinygo-org:devfrom
gandarez:feat/ws2812-rp2

Conversation

@gandarez
Copy link
Copy Markdown
Contributor

@gandarez gandarez commented Mar 30, 2026

Summary

  • On RP2040/RP2350, NewWS2812() now uses PIO (via tinygo-org/pio) for hardware-timed control instead of bit-banging
  • Falls back to the existing bit-bang driver if PIO initialization fails, or on all other platforms
  • No changes to the exported API surface — existing code works without modification

Motivation

The existing ws2812 driver uses CPU-timed bit-banging assembly tuned for Cortex-M0+. The RP2350's Cortex-M33 has a write buffer and different pipeline that breaks the nanosecond-level GPIO timing. The Arduino Adafruit_NeoPixel library works on the same hardware because it uses PIO.

Implementation

  • ws2812_rp2_pio.go (rp2040 || rp2350): newWS2812Device() claims a PIO0 state machine and sets writeColorFunc to a PIO-based closure. Falls back to bit-bang on failure.
  • ws2812_init_other.go (!rp2040 && !rp2350): newWS2812Device() returns the standard bit-bang device.
  • NewWS2812() now delegates to newWS2812Device().

Test plan

  • tinygo flash -target=pico2 ./examples/ws2812/ — verify LEDs work on RP2350 via PIO
  • tinygo build -target=circuitplay-express ./examples/ws2812/ — verify bit-bang fallback compiles
  • tinygo build -target=arduino ./examples/ws2812/ — verify AVR still works
  • tinygo build -target=m5stamp-c3 ./examples/ws2812/ — verify Xtensa/RISC-V still works

@gandarez gandarez changed the base branch from release to dev March 30, 2026 16:07
@deadprogram
Copy link
Copy Markdown
Member

I was not expecting you to add a new type to implement this, @gandarez

Seems to me that you could wrap the existing Device type, and then use the writeColorFunc to do the PIO specific behavior.

@gandarez
Copy link
Copy Markdown
Contributor Author

@deadprogram is it ok?
e569fc6

@deadprogram
Copy link
Copy Markdown
Member

Sorry, but that was not what I had in mind @gandarez

I do not see any reason to add a new Strip type. That changes the exported interface, when you really only need to extend it.

NewWS2812(pin machine.Pin) should be able to call the PIO code by some use of build tags, and possibly adding some init function to the Device type. You might be able to do lazy PIO init and avoid that entirely and do it all with build tags + the PIO code.

Hopefully that explains a bit better what I had in mind here.

@gandarez gandarez changed the title ws2812: add Strip type with PIO support for RP2040/RP2350 ws2812: use PIO on RP2040/RP2350 transparently via build tags Apr 1, 2026
@gandarez
Copy link
Copy Markdown
Contributor Author

gandarez commented Apr 1, 2026

@deadprogram I believe this is what you're looking for 544cd43. Do you have any other device to try it out?

I also added brightness control in this commit 4b3ba69

@deadprogram
Copy link
Copy Markdown
Member

@deadprogram I believe this is what you're looking for 544cd43. Do you have any other device to try it out?

I think that is a lot more like it.

I also added brightness control in this commit 4b3ba69

That might be better to add in a separate PR, no?

Integrate PIO support directly into the existing Device.
NewWS2812() now uses PIO for hardware-timed control
on RP2040/RP2350 and falls back to bit-banging on other platforms.

No changes to the exported API surface.
@gandarez
Copy link
Copy Markdown
Contributor Author

gandarez commented Apr 3, 2026

@deadprogram PR is ready

@deadprogram
Copy link
Copy Markdown
Member

Confirmed that it still works on samd21 as well. Thank you for adding this, and for the clean implementation! Now merging.

@deadprogram deadprogram merged commit 4071028 into tinygo-org:dev Apr 7, 2026
1 check passed
@gandarez gandarez deleted the feat/ws2812-rp2 branch April 7, 2026 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants