From 0a22d3193e52578fec2a4289c4e60f030d536cb3 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Ruel Date: Sun, 24 Jun 2018 15:10:52 -0400 Subject: [PATCH] nrzled: change to Opts pattern This makes it coherent with other drivers. --- experimental/devices/nrzled/nrzled.go | 40 +++++++++++----- experimental/devices/nrzled/nrzled_test.go | 53 +++++++++++++++------- 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/experimental/devices/nrzled/nrzled.go b/experimental/devices/nrzled/nrzled.go index b99bc3c..b94638c 100644 --- a/experimental/devices/nrzled/nrzled.go +++ b/experimental/devices/nrzled/nrzled.go @@ -41,29 +41,45 @@ func NRZ(b byte) uint32 { return out } +// DefaultOpts is the recommended default options. +var DefaultOpts = Opts{ + NumPixels: 150, // 150 LEDs is a common strip length. + Channels: 3, // RGB. + Freq: 800 * physic.KiloHertz, // Fast LEDs, most common. +} + +// Opts defines the options for the device. +type Opts struct { + // NumPixels is the number of pixels to control. If too short, the following + // pixels will be corrupted. If too long, the pixels will be drawn + // unnecessarily but not visible issue will occur. + NumPixels int + // Channels is 1 for single color LEDs, 3 for RGB LEDs and 4 for RGBW (white) + // LEDs. + Channels int + // Freq is the frequency to use to drive the LEDs. It should be either 800kHz + // for fast ICs and 400kHz for the slow ones. + Freq physic.Frequency +} + // New opens a handle to a compatible LED strip. -// -// f should either be 800kHz for fast ICs and 400kHz for the slow ones. -// -// channels should be either 1 (White only), 3 (RGB) or 4 (RGBW). For RGB and -// RGBW, the encoding is respectively GRB and GRBW. -func New(p gpiostream.PinOut, numPixels int, f physic.Frequency, channels int) (*Dev, error) { +func New(p gpiostream.PinOut, opts *Opts) (*Dev, error) { // Allow a wider range in case there's new devices with higher supported // frequency. - if f < 10*physic.KiloHertz || f > 100*physic.MegaHertz { + if opts.Freq < 10*physic.KiloHertz || opts.Freq > 100*physic.MegaHertz { return nil, errors.New("nrzled: specify valid frequency") } - if channels != 3 && channels != 4 { + if opts.Channels != 3 && opts.Channels != 4 { return nil, errors.New("nrzled: specify valid number of channels (3 or 4)") } return &Dev{ p: p, - numPixels: numPixels, - channels: channels, + numPixels: opts.NumPixels, + channels: opts.Channels, b: gpiostream.BitStream{ - Freq: f, + Freq: opts.Freq, // Each bit is encoded on 3 bits. - Bits: make([]byte, numPixels*3*channels), + Bits: make([]byte, opts.NumPixels*3*opts.Channels), LSBF: false, }, }, nil diff --git a/experimental/devices/nrzled/nrzled_test.go b/experimental/devices/nrzled/nrzled_test.go index 1496435..31d0519 100644 --- a/experimental/devices/nrzled/nrzled_test.go +++ b/experimental/devices/nrzled/nrzled_test.go @@ -56,12 +56,14 @@ func TestNew_3(t *testing.T) { 0x49, 0x24, 0x92, 0x49, 0x24, 0x92, 0x49, 0x24, 0x92, 0x49, 0x24, 0x92, 0x49, 0x24, 0x92, 0x49, 0x24, 0x92, 0x49, 0x24, 0x92, 0x49, 0x24, 0x92, 0x49, 0x24, }, - Freq: 400 * physic.KiloHertz, + Freq: 800 * physic.KiloHertz, LSBF: false, }, }, } - d, err := New(&g, 10, 400*physic.KiloHertz, 3) + opts := DefaultOpts + opts.NumPixels = 10 + d, err := New(&g, &opts) if err != nil { t.Fatal(err) } @@ -84,10 +86,14 @@ func TestNew_3(t *testing.T) { func TestNew_fail(t *testing.T) { g := gpiostreamtest.PinOutPlayback{} - if _, err := New(&g, 1, 0, 3); err == nil { + opts := DefaultOpts + opts.Freq = 0 + if _, err := New(&g, &opts); err == nil { t.Fatal("hz == 0") } - if _, err := New(&g, 1, 400*physic.KiloHertz, 2); err == nil { + opts = DefaultOpts + opts.Channels = 2 + if _, err := New(&g, &opts); err == nil { t.Fatal("channels == 2") } } @@ -104,12 +110,14 @@ func TestDraw_NRGBA_3(t *testing.T) { 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0x92, 0x49, 0xb6, 0x92, 0x49, 0xb4, 0x92, 0x4d, 0x24, }, - Freq: 400 * physic.KiloHertz, + Freq: 800 * physic.KiloHertz, LSBF: false, }, }, } - d, _ := New(&g, 10, 400*physic.KiloHertz, 3) + opts := DefaultOpts + opts.NumPixels = 10 + d, _ := New(&g, &opts) img := image.NewNRGBA(d.Bounds()) copy(img.Pix, getRGBW()) d.Draw(d.Bounds(), img, image.Point{}) @@ -130,12 +138,14 @@ func TestDraw_RGBA_3(t *testing.T) { 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0xdb, 0x6d, 0xa6, 0xdb, 0x6d, 0xa6, 0xdb, 0x6d, 0xa6, 0xda, 0x49, 0xb6, 0xd3, 0x4d, 0x34, 0xdb, 0x49, 0x36, }, - Freq: 400 * physic.KiloHertz, + Freq: 800 * physic.KiloHertz, LSBF: false, }, }, } - d, _ := New(&g, 10, 400*physic.KiloHertz, 3) + opts := DefaultOpts + opts.NumPixels = 10 + d, _ := New(&g, &opts) img := image.NewRGBA(d.Bounds()) copy(img.Pix, getRGBW()) d.Draw(d.Bounds(), img, image.Point{}) @@ -158,12 +168,15 @@ func TestDraw_RGBA_4(t *testing.T) { 0xdb, 0x6d, 0xa6, 0xdb, 0x6d, 0xa6, 0xdb, 0x6d, 0xa6, 0xd2, 0x49, 0x24, 0xda, 0x49, 0xb6, 0xd3, 0x4d, 0x34, 0xdb, 0x49, 0x36, 0x92, 0x4d, 0x26, }, - Freq: 400 * physic.KiloHertz, + Freq: 800 * physic.KiloHertz, LSBF: false, }, }, } - d, _ := New(&g, 10, 400*physic.KiloHertz, 4) + opts := DefaultOpts + opts.NumPixels = 10 + opts.Channels = 4 + d, _ := New(&g, &opts) img := image.NewRGBA(d.Bounds()) copy(img.Pix, getRGBW()) d.Draw(d.Bounds(), img, image.Point{}) @@ -184,12 +197,14 @@ func TestDraw_Limits(t *testing.T) { 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0xdb, 0x6d, 0xa6, 0xdb, 0x6d, 0xa6, 0xdb, 0x6d, 0xa6, 0xda, 0x49, 0xb6, 0xd3, 0x4d, 0x34, 0xdb, 0x49, 0x36, }, - Freq: 400 * physic.KiloHertz, + Freq: 800 * physic.KiloHertz, LSBF: false, }, }, } - d, _ := New(&g, 10, 400*physic.KiloHertz, 3) + opts := DefaultOpts + opts.NumPixels = 10 + d, _ := New(&g, &opts) img := image.NewRGBA(image.Rect(-1, -1, 20, 20)) copy(img.Pix, getRGBW()) d.Draw(d.Bounds(), img, image.Point{}) @@ -210,12 +225,14 @@ func TestWrite_3(t *testing.T) { 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0x92, 0x49, 0xa4, 0x92, 0x49, 0x36, 0x92, 0x49, 0xa6, 0x92, 0x49, 0xb6, 0x92, 0x49, 0xb4, 0x92, 0x4d, 0x24, }, - Freq: 400 * physic.KiloHertz, + Freq: 800 * physic.KiloHertz, LSBF: false, }, }, } - d, _ := New(&g, 10, 400*physic.KiloHertz, 3) + opts := DefaultOpts + opts.NumPixels = 10 + d, _ := New(&g, &opts) if n, err := d.Write(getRGB()); n != 30 || err != nil { t.Fatal(n, err) } @@ -226,7 +243,9 @@ func TestWrite_3(t *testing.T) { func TestWrite_fail(t *testing.T) { g := gpiostreamtest.PinOutPlayback{DontPanic: true} - d, _ := New(&g, 10, 400*physic.KiloHertz, 3) + opts := DefaultOpts + opts.NumPixels = 10 + d, _ := New(&g, &opts) if n, err := d.Write([]byte{1}); n != 0 || err == nil { t.Fatal(n, err) } @@ -240,7 +259,9 @@ func TestWrite_fail(t *testing.T) { func TestHalt_fail(t *testing.T) { g := gpiostreamtest.PinOutPlayback{DontPanic: true} - d, _ := New(&g, 10, 400*physic.KiloHertz, 3) + opts := DefaultOpts + opts.NumPixels = 10 + d, _ := New(&g, &opts) if d.Halt() == nil { t.Fatal("expected failure") }