mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-19 22:23:58 +00:00
apa102: avoid creating garbage
Avoid creating unnecessary garbage in the following ways:
* Use the Transfer method instead of the Tx method for single byte
transfers.
* Use a statically allocated buffer for the fixed start-of-frame
sequence.
Running this for a few minutes did not cause the garbage collector to
run. Previously, it would run every second or so in a
persistence-of-vision application.
This commit is contained in:
committed by
Ron Evans
parent
c3f3af5ffa
commit
91539d9ef8
+15
-12
@@ -19,6 +19,8 @@ const (
|
|||||||
GRB
|
GRB
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var startFrame = []byte{0x00, 0x00, 0x00, 0x00}
|
||||||
|
|
||||||
// Device wraps APA102 SPI LEDs.
|
// Device wraps APA102 SPI LEDs.
|
||||||
type Device struct {
|
type Device struct {
|
||||||
bus SPI
|
bus SPI
|
||||||
@@ -30,6 +32,7 @@ type Device struct {
|
|||||||
// SPI from the TinyGo "machine" package implements this already.
|
// SPI from the TinyGo "machine" package implements this already.
|
||||||
type SPI interface {
|
type SPI interface {
|
||||||
Tx(w, r []byte) error
|
Tx(w, r []byte) error
|
||||||
|
Transfer(b byte) (byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new APA102 driver. Pass in a fully configured SPI bus.
|
// New returns a new APA102 driver. Pass in a fully configured SPI bus.
|
||||||
@@ -51,22 +54,22 @@ func (d Device) WriteColors(cs []color.RGBA) (n int, err error) {
|
|||||||
// write data
|
// write data
|
||||||
for _, c := range cs {
|
for _, c := range cs {
|
||||||
// brightness is scaled to 5 bit value
|
// brightness is scaled to 5 bit value
|
||||||
d.bus.Tx([]byte{0xe0 | (c.A >> 3)}, nil)
|
d.bus.Transfer(0xe0 | (c.A >> 3))
|
||||||
|
|
||||||
// set the colors
|
// set the colors
|
||||||
switch d.Order {
|
switch d.Order {
|
||||||
case BRG:
|
case BRG:
|
||||||
d.bus.Tx([]byte{c.B}, nil)
|
d.bus.Transfer(c.B)
|
||||||
d.bus.Tx([]byte{c.R}, nil)
|
d.bus.Transfer(c.R)
|
||||||
d.bus.Tx([]byte{c.G}, nil)
|
d.bus.Transfer(c.G)
|
||||||
case GRB:
|
case GRB:
|
||||||
d.bus.Tx([]byte{c.G}, nil)
|
d.bus.Transfer(c.G)
|
||||||
d.bus.Tx([]byte{c.R}, nil)
|
d.bus.Transfer(c.R)
|
||||||
d.bus.Tx([]byte{c.B}, nil)
|
d.bus.Transfer(c.B)
|
||||||
case BGR:
|
case BGR:
|
||||||
d.bus.Tx([]byte{c.B}, nil)
|
d.bus.Transfer(c.B)
|
||||||
d.bus.Tx([]byte{c.G}, nil)
|
d.bus.Transfer(c.G)
|
||||||
d.bus.Tx([]byte{c.R}, nil)
|
d.bus.Transfer(c.R)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +89,7 @@ func (d Device) Write(buf []byte) (n int, err error) {
|
|||||||
|
|
||||||
// startFrame sends the start bytes for a strand of LEDs.
|
// startFrame sends the start bytes for a strand of LEDs.
|
||||||
func (d Device) startFrame() {
|
func (d Device) startFrame() {
|
||||||
d.bus.Tx([]byte{0x00, 0x00, 0x00, 0x00}, nil)
|
d.bus.Tx(startFrame, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// endFrame sends the end frame marker with one extra bit per LED so
|
// endFrame sends the end frame marker with one extra bit per LED so
|
||||||
@@ -94,6 +97,6 @@ func (d Device) startFrame() {
|
|||||||
// See https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/
|
// See https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/
|
||||||
func (d Device) endFrame(count int) {
|
func (d Device) endFrame(count int) {
|
||||||
for i := 0; i < count/16; i++ {
|
for i := 0; i < count/16; i++ {
|
||||||
d.bus.Tx([]byte{0xff}, nil)
|
d.bus.Transfer(0xff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -41,8 +41,9 @@ func (s *bbSPI) delay() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer is used to send a single byte.
|
// Transfer matches signature of machine.SPI.Transfer() and is used to send a
|
||||||
func (s *bbSPI) Transfer(b byte) {
|
// single byte. The received data is ignored and no error will ever be returned.
|
||||||
|
func (s *bbSPI) Transfer(b byte) (byte, error) {
|
||||||
for i := uint8(0); i < 8; i++ {
|
for i := uint8(0); i < 8; i++ {
|
||||||
|
|
||||||
// half clock cycle high to start
|
// half clock cycle high to start
|
||||||
@@ -63,6 +64,7 @@ func (s *bbSPI) Transfer(b byte) {
|
|||||||
|
|
||||||
// for actual SPI would try to read the MISO value here
|
// for actual SPI would try to read the MISO value here
|
||||||
s.delay()
|
s.delay()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user