diff --git a/nrzled/nrzled.go b/nrzled/nrzled.go index 248cb1b..44ae2a4 100644 --- a/nrzled/nrzled.go +++ b/nrzled/nrzled.go @@ -81,10 +81,13 @@ func NewSPI(p spi.Port, opts *Opts) (*Dev, error) { } // 4 symbol bytes per byte, 3/4 bytes per pixel. streamLen := 4 * (opts.Channels * opts.NumPixels) - // 3 bytes for latch. 24*400ns = 9600ns. In practice this could be skipped, - // as the overhead for SPI Tx() tear down and the next one is likely at least - // 10µs. - bufSize := streamLen + 3 + // 3 bytes for latch. 24*400ns = 9600ns. In practice this could be skipped at + // the end as the overhead for SPI Tx() tear down and the next one is likely + // at least 10µs. + // In the front, we definitely want it, as SPIs might otherwise be high for + // quite a while while setting themselves up, causing the first symbol to be + // interpreted as a logical 1. + bufSize := 3 + streamLen + 3 if l, ok := p.(conn.Limits); ok { if s := l.MaxTxSize(); s < bufSize { return nil, errors.New("spi port buffer is too short for the specified number of pixels") @@ -101,7 +104,7 @@ func NewSPI(p spi.Port, opts *Opts) (*Dev, error) { numPixels: opts.NumPixels, channels: opts.Channels, b: gpiostream.BitStream{Freq: opts.Freq, Bits: buf, LSBF: false}, - rawBuf: buf[:streamLen], + rawBuf: buf[3 : bufSize-3], rect: image.Rect(0, 0, opts.NumPixels, 1), }, nil } diff --git a/nrzled/nrzled_spi_test.go b/nrzled/nrzled_spi_test.go index e9eabba..259f356 100644 --- a/nrzled/nrzled_spi_test.go +++ b/nrzled/nrzled_spi_test.go @@ -36,7 +36,7 @@ func TestSPI_Empty(t *testing.T) { s := spitest.Playback{ Playback: conntest.Playback{ Count: 1, - Ops: []conntest.IO{{W: []byte{0x00, 0x00, 0x00}}}, + Ops: []conntest.IO{{W: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, }, } d, err := NewSPI(spitest.NewRecordRaw(&buf), &o) @@ -105,6 +105,7 @@ var writeTests = []struct { {0xFF, 0xFF, 0xFF, 0x00}, }), want: []byte{ + /*NUL*/ 0x00, 0x00, 0x00, /*FF*/ 0xEE, 0xEE, 0xEE, 0xEE /*FF*/, 0xEE, 0xEE, 0xEE, 0xEE /*FF*/, 0xEE, 0xEE, 0xEE, 0xEE, /*EOF*/ 0x00, 0x00, 0x00, }, @@ -120,6 +121,7 @@ var writeTests = []struct { {0xFE, 0xFE, 0xFE, 0x00}, }), want: []byte{ + /*NUL*/ 0x00, 0x00, 0x00, /*FE*/ 0xEE, 0xEE, 0xEE, 0xE8 /*FE*/, 0xEE, 0xEE, 0xEE, 0xE8 /*FE*/, 0xEE, 0xEE, 0xEE, 0xE8, /*EOF*/ 0x00, 0x00, 0x00, }, @@ -135,6 +137,7 @@ var writeTests = []struct { {0xF0, 0xF0, 0xF0, 0x00}, }), want: []byte{ + /*NUL*/ 0x00, 0x00, 0x00, /*F0*/ 0xEE, 0xEE, 0x88, 0x88 /*F0*/, 0xEE, 0xEE, 0x88, 0x88 /*F0*/, 0xEE, 0xEE, 0x88, 0x88, /*EOF*/ 0x00, 0x00, 0x00, }, @@ -150,6 +153,7 @@ var writeTests = []struct { {0x80, 0x80, 0x80, 0x00}, }), want: []byte{ + /*NUL*/ 0x00, 0x00, 0x00, /*80*/ 0xE8, 0x88, 0x88, 0x88 /*80*/, 0xE8, 0x88, 0x88, 0x88 /*80*/, 0xE8, 0x88, 0x88, 0x88, /*EOF*/ 0x00, 0x00, 0x00, }, @@ -165,6 +169,7 @@ var writeTests = []struct { {0x80, 0xFF, 0x00, 0x00}, }), want: []byte{ + /*NUL*/ 0x00, 0x00, 0x00, /*FF*/ 0xEE, 0xEE, 0xEE, 0xEE /*80*/, 0xE8, 0x88, 0x88, 0x88 /*00*/, 0x88, 0x88, 0x88, 0x88, /*EOF*/ 0x00, 0x00, 0x00, }, @@ -180,6 +185,7 @@ var writeTests = []struct { {0x80, 0x00, 0x00, 0x00}, }), want: []byte{ + /*NUL*/ 0x00, 0x00, 0x00, /*00*/ 0x88, 0x88, 0x88, 0x88 /*80*/, 0xE8, 0x88, 0x88, 0x88 /*00*/, 0x88, 0x88, 0x88, 0x88, /*EOF*/ 0x00, 0x00, 0x00, }, @@ -195,6 +201,7 @@ var writeTests = []struct { {0x00, 0x80, 0x00, 0x00}, }), want: []byte{ + /*NUL*/ 0x00, 0x00, 0x00, /*80*/ 0xE8, 0x88, 0x88, 0x88 /*00*/, 0x88, 0x88, 0x88, 0x88 /*00*/, 0x88, 0x88, 0x88, 0x88, /*EOF*/ 0x00, 0x00, 0x00, }, @@ -210,6 +217,7 @@ var writeTests = []struct { {0x00, 0x00, 0x80, 0x00}, }), want: []byte{ + /*NUL*/ 0x00, 0x00, 0x00, /*00*/ 0x88, 0x88, 0x88, 0x88 /*00*/, 0x88, 0x88, 0x88, 0x88 /*80*/, 0xE8, 0x88, 0x88, 0x88, /*EOF*/ 0x00, 0x00, 0x00, }, @@ -236,6 +244,7 @@ var writeTests = []struct { {0x00, 0x00, 0x00, 0x00}, }), want: []byte{ + /*NUL*/ 0x00, 0x00, 0x00, /*FF*/ 0xEE, 0xEE, 0xEE, 0xEE /*FF*/, 0xEE, 0xEE, 0xEE, 0xEE /*FF*/, 0xEE, 0xEE, 0xEE, 0xEE, /*FE*/ 0xEE, 0xEE, 0xEE, 0xE8 /*FE*/, 0xEE, 0xEE, 0xEE, 0xE8 /*FE*/, 0xEE, 0xEE, 0xEE, 0xE8, /*F0*/ 0xEE, 0xEE, 0x88, 0x88 /*F0*/, 0xEE, 0xEE, 0x88, 0x88 /*F0*/, 0xEE, 0xEE, 0x88, 0x88, @@ -302,14 +311,15 @@ func TestSPI_Long(t *testing.T) { if n, err := d.Write(toRGB(colors)); n != len(colors)*3 || err != nil { t.Fatalf("%d %v", n, err) } - expected := make([]byte, 12*o.NumPixels+3) - for i := 0; i < 12*o.NumPixels; i += 12 { + expected := make([]byte, 3+12*o.NumPixels+3) + // leave three bytes of padding + for i := 3; i < 12*o.NumPixels; i += 12 { //Each channel should be 0x00 for j := 0; j < 12; j++ { expected[i+j] = 0x88 } } - trailer := expected[12*o.NumPixels:] + trailer := expected[3+12*o.NumPixels:] for i := range trailer { trailer[i] = 0x00 } @@ -350,11 +360,16 @@ var drawTests = []struct { }(), want: func() []byte { var b []byte + //padding + for i := 0; i < 3; i++ { + b = append(b, 0x00) + } for i := 0; i < 4; i++ { b = append(b, 0xE8, 0x88, 0x88, 0x88) //0x80 b = append(b, 0x88, 0x88, 0x88, 0x88) //0x00 b = append(b, 0xEE, 0xEE, 0xEE, 0xEE) //0xFF } + //padding for i := 0; i < 3; i++ { b = append(b, 0x00) } @@ -427,6 +442,9 @@ func TestSPI_Halt(t *testing.T) { Ops: []conntest.IO{ {}, {W: []byte{ + //Begin of frame + 0x00, 0x00, 0x00, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,