tinygo-org / drivers

TinyGo drivers for sensors, displays, wireless adaptors, and other devices that use I2C, SPI, GPIO, ADC, and UART interfaces.
https://tinygo.org
BSD 3-Clause "New" or "Revised" License
607 stars 192 forks source link

SK6812 Support #608

Closed SoftTacos closed 11 months ago

SoftTacos commented 11 months ago

The WS2812 driver does exactly what you want for RGB strips, but there are a considerable number of RGBA/SK6812 strips as well, SK6812 is the same as WS2812 but it as an additional byte for white/alpha. I went ahead and made the following modifications locally to accommodate for that. If you think this should be a separate driver all together so no breaking changes are added I'm happy to do that too.

Additionally, while I was poking around I noticed WriteByte can return an error, but Write and WriteColors ignore the error. I modified WriteColors to return the error from the last WriteByte call made. Would it make sense to instead check the machine.CPUFrequency() for valid values in Device.New() and return an error there? That way we avoid dealing with errors in Write, WriteByte, and WriteColor. This assumes machine.CPUFrequency() is constant, which the comments say it usually is.

Please let me know if you would like to see any changes made.

Example Code:

type DeviceType uint8

const(
    WS2812 DeviceType = iota // RGB
    SK6812 //RGBA / RGBW
)

// Device wraps a pin object for an easy driver interface.
type Device struct {
    Pin machine.Pin
    DeviceType DeviceType
}

// New returns a new WS2812 driver. It does not touch the pin object: you have
// to configure it as an output pin before calling New.
// WS2812 is for RGB, SK6812 is for RGBA
func New(pin machine.Pin,deviceType DeviceType) Device {
    return Device{
        Pin:pin,
        DeviceType:deviceType,
    }
}

// Device.Write() is unchanged

// Write the given color slice out using the WS2812 protocol.
// Colors are sent out in the usual GRB(A) format.
func (d Device) WriteColors(buf []color.RGBA) (err error) {
    switch d.DeviceType {
    case WS2812:
        err = d.writeColorsRGB(buf)
    case SK6812:
        err = d.writeColorsRGBA(buf)
    }
    return
}

func (d Device) writeColorsRGB(buf []color.RGBA) (err error) {
    for _, color := range buf {
        d.WriteByte(color.G)       // green
        d.WriteByte(color.R)       // red
        err = d.WriteByte(color.B) // blue
    }
    return
}

func (d Device) writeColorsRGBA(buf []color.RGBA) (err error) {
    for _, color := range buf {
        d.WriteByte(color.G)       // green
        d.WriteByte(color.R)       // red
        d.WriteByte(color.B)       // blue
        err = d.WriteByte(color.A) // alpha
    }
    return
}
SoftTacos commented 11 months ago

PR: https://github.com/tinygo-org/drivers/pull/610