From 4071028e855deaf215df1ed3c63e5f025186b446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Henrique=20Guard=C3=A3o=20Gandarez?= Date: Tue, 31 Mar 2026 19:26:58 -0300 Subject: [PATCH] ws2812: add PIO support for RP2040/RP2350 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. --- go.mod | 3 +-- go.sum | 2 ++ ws2812/ws2812.go | 14 +++++++------- ws2812/ws2812_init_other.go | 10 ++++++++++ ws2812/ws2812_rp2_pio.go | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 ws2812/ws2812_init_other.go create mode 100644 ws2812/ws2812_rp2_pio.go diff --git a/go.mod b/go.mod index 10c3e98..432c77a 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,16 @@ module tinygo.org/x/drivers - go 1.22.1 toolchain go1.23.1 - require ( github.com/eclipse/paho.mqtt.golang v1.2.0 github.com/frankban/quicktest v1.10.2 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/orsinium-labs/tinymath v1.1.0 github.com/soypat/natiu-mqtt v0.5.1 + github.com/tinygo-org/pio v0.3.0 golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d golang.org/x/net v0.33.0 tinygo.org/x/tinyfont v0.3.0 diff --git a/go.sum b/go.sum index 6bb3557..673d984 100644 --- a/go.sum +++ b/go.sum @@ -17,6 +17,8 @@ github.com/orsinium-labs/tinymath v1.1.0 h1:KomdsyLHB7vE3f1nRAJF2dyf1m/gnM2HxfTe github.com/orsinium-labs/tinymath v1.1.0/go.mod h1:WPXX6ei3KSXG7JfA03a+ekCYaY9SWN4I+JRl2p6ck+A= github.com/soypat/natiu-mqtt v0.5.1 h1:rwaDmlvjzD2+3MCOjMZc4QEkDkNwDzbct2TJbpz+TPc= github.com/soypat/natiu-mqtt v0.5.1/go.mod h1:xEta+cwop9izVCW7xOx2W+ct9PRMqr0gNVkvBPnQTc4= +github.com/tinygo-org/pio v0.3.0 h1:opEnOtw58KGB4RJD3/n/Rd0/djYGX3DeJiXLI6y/yDI= +github.com/tinygo-org/pio v0.3.0/go.mod h1:wf6c6lKZp+pQOzKKcpzchmRuhiMc27ABRuo7KVnaMFU= github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0= golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= diff --git a/ws2812/ws2812.go b/ws2812/ws2812.go index dee3cfb..583cbbd 100644 --- a/ws2812/ws2812.go +++ b/ws2812/ws2812.go @@ -1,4 +1,7 @@ // Package ws2812 implements a driver for WS2812 and SK6812 RGB LED strips. +// +// On most platforms NewWS2812 uses bit-banging. +// On RP2040/RP2350 it uses PIO for hardware-timed control. package ws2812 // import "tinygo.org/x/drivers/ws2812" //go:generate go run gen-ws2812.go -arch=cortexm 16 48 64 120 125 150 168 200 @@ -24,14 +27,11 @@ func New(pin machine.Pin) Device { return NewWS2812(pin) } -// New returns a new WS2812(RGB) driver. -// It does not touch the pin object: you have -// to configure it as an output pin before calling New. +// NewWS2812 returns a new WS2812(RGB) driver. +// On RP2040/RP2350, it uses PIO for hardware-timed control. +// On other platforms, you must configure the pin as output before calling this. func NewWS2812(pin machine.Pin) Device { - return Device{ - Pin: pin, - writeColorFunc: writeColorsRGB, - } + return newWS2812Device(pin) } // New returns a new SK6812(RGBA) driver. diff --git a/ws2812/ws2812_init_other.go b/ws2812/ws2812_init_other.go new file mode 100644 index 0000000..8d312de --- /dev/null +++ b/ws2812/ws2812_init_other.go @@ -0,0 +1,10 @@ +//go:build !rp2040 && !rp2350 + +package ws2812 + +import "machine" + +// newWS2812Device creates a WS2812 device using the bit-bang driver. +func newWS2812Device(pin machine.Pin) Device { + return Device{Pin: pin, writeColorFunc: writeColorsRGB} +} diff --git a/ws2812/ws2812_rp2_pio.go b/ws2812/ws2812_rp2_pio.go new file mode 100644 index 0000000..36259e5 --- /dev/null +++ b/ws2812/ws2812_rp2_pio.go @@ -0,0 +1,33 @@ +//go:build rp2040 || rp2350 + +package ws2812 + +import ( + "image/color" + "machine" + + pio "github.com/tinygo-org/pio/rp2-pio" + "github.com/tinygo-org/pio/rp2-pio/piolib" +) + +// newWS2812Device creates a WS2812 device using PIO for hardware-timed control. +// If PIO initialization fails, it falls back to the bit-bang driver. +func newWS2812Device(pin machine.Pin) Device { + sm, err := pio.PIO0.ClaimStateMachine() + if err != nil { + return Device{Pin: pin, writeColorFunc: writeColorsRGB} + } + ws, err := piolib.NewWS2812B(sm, pin) + if err != nil { + return Device{Pin: pin, writeColorFunc: writeColorsRGB} + } + return Device{ + Pin: pin, + writeColorFunc: func(_ Device, buf []color.RGBA) error { + for _, c := range buf { + ws.PutRGB(c.R, c.G, c.B) + } + return nil + }, + } +}