Skip to content

Commit

Permalink
apa102: adding initial support for APA102 LEDs, thanks to code sample…
Browse files Browse the repository at this point in the history
… from @rakyll

Signed-off-by: deadprogram <[email protected]>
  • Loading branch information
deadprogram committed Dec 13, 2017
1 parent cb4ec9b commit 71ca8ed
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 0 deletions.
92 changes: 92 additions & 0 deletions drivers/spi/apa102.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package spi

import (
"image/color"

"gobot.io/x/gobot"
)

// APA102Driver is a driver for the APA102 programmable RGB LEDs
type APA102Driver struct {
name string
connector Connector
connection Connection

vals []color.RGBA
}

// NewAPA102Driver creates a new Gobot Driver for APA102 RGB LEDs.
//
// Params:
// a *Adaptor - the Adaptor to use with this Driver
// count int - how many LEDs are in the array controlled by this driver
//
func NewAPA102Driver(a Connector, count int) *APA102Driver {
d := &APA102Driver{
name: gobot.DefaultName("APA102"),
connector: a,
vals: make([]color.RGBA, count),
}
return d
}

// Name returns the name of the device.
func (d *APA102Driver) Name() string { return d.name }

// SetName sets the name of the device.
func (d *APA102Driver) SetName(n string) { d.name = n }

// Connection returns the Connection of the device.
func (d *APA102Driver) Connection() gobot.Connection { return d.connection.(gobot.Connection) }

// Start initializes the driver.
func (d *APA102Driver) Start() (err error) {
bus := d.connector.GetSpiDefaultBus()
mode := d.connector.GetSpiDefaultMode()
maxSpeed := d.connector.GetSpiDefaultMaxSpeed()
d.connection, err = d.connector.GetSpiConnection(bus, mode, maxSpeed)
if err != nil {
return err
}
return nil
}

// Halt stops the driver.
func (d *APA102Driver) Halt() (err error) {
d.connection.Close()
return
}

// SetRGBA sets the ith LED's color to the given RGBA value.
// A subsequent call to Draw is required to transmit values
// to the LED strip.
func (d *APA102Driver) SetRGBA(i int, v color.RGBA) {
d.vals[i] = v
}

// Draw displays the RGBA values set on the actual LED strip.
func (d *APA102Driver) Draw() error {
// TODO(jbd): dotstar allows other RGBA alignments, support those layouts.
n := len(d.vals)

tx := make([]byte, 4*(n+1)+(n/2+1))
tx[0] = 0x00
tx[1] = 0x00
tx[2] = 0x00
tx[3] = 0x00

for i, c := range d.vals {
j := (i + 1) * 4
tx[j] = 0xe0 + byte(c.R)
tx[j+1] = byte(c.B)
tx[j+2] = byte(c.G)
tx[j+3] = byte(c.R)
}

// end frame with at least n/2 0xff vals
for i := (n + 1) * 4; i < len(tx); i++ {
tx[i] = 0xff
}

return d.connection.Tx(tx, nil)
}
39 changes: 39 additions & 0 deletions drivers/spi/apa102_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package spi

import (
"image/color"
"testing"

"gobot.io/x/gobot"
"gobot.io/x/gobot/gobottest"
)

var _ gobot.Driver = (*APA102Driver)(nil)

func initTestDriver() *APA102Driver {
d := NewAPA102Driver(&TestConnector{}, 10)
return d
}

func TestDriverStart(t *testing.T) {
d := initTestDriver()
gobottest.Assert(t, d.Start(), nil)
}

func TestDriverHalt(t *testing.T) {
d := initTestDriver()
d.Start()
gobottest.Assert(t, d.Halt(), nil)
}

func TestDriverLEDs(t *testing.T) {
d := initTestDriver()
d.Start()

d.SetRGBA(0, color.RGBA{255, 255, 255, 0})
d.SetRGBA(1, color.RGBA{255, 255, 255, 0})
d.SetRGBA(2, color.RGBA{255, 255, 255, 0})
d.SetRGBA(3, color.RGBA{255, 255, 255, 0})

gobottest.Assert(t, d.Draw(), nil)
}
61 changes: 61 additions & 0 deletions drivers/spi/spi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package spi

import (
"time"

xspi "golang.org/x/exp/io/spi"
)

type TestConnector struct{}

func (ctr *TestConnector) GetSpiConnection(busNum, mode int, maxSpeed int64) (device Connection, err error) {
return NewConnection(&TestSpiDevice{}), nil
}

func (ctr *TestConnector) GetSpiDefaultBus() int {
return 0
}

func (ctr *TestConnector) GetSpiDefaultMode() int {
return 0
}

func (ctr *TestConnector) GetSpiDefaultMaxSpeed() int64 {
return 0
}

type TestSpiDevice struct {
bus SPIDevice
}

func (c *TestSpiDevice) Close() error {
return nil
}

func (c *TestSpiDevice) SetBitOrder(o xspi.Order) error {
return nil
}

func (c *TestSpiDevice) SetBitsPerWord(bits int) error {
return nil
}

func (c *TestSpiDevice) SetCSChange(leaveEnabled bool) error {
return nil
}

func (c *TestSpiDevice) SetDelay(t time.Duration) error {
return nil
}

func (c *TestSpiDevice) SetMaxSpeed(speed int) error {
return nil
}

func (c *TestSpiDevice) SetMode(mode xspi.Mode) error {
return nil
}

func (c *TestSpiDevice) Tx(w, r []byte) error {
return nil
}

0 comments on commit 71ca8ed

Please sign in to comment.