From 903dc72cb7c1c6aec7bbbdadfd39d78f39e87893 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Thu, 31 Aug 2017 21:09:06 -0500 Subject: [PATCH 1/2] Adding SSD1306 OLED display controller support --- controller/ssd1306/buffer.go | 98 ++++++++++++ controller/ssd1306/buffer_test.go | 126 +++++++++++++++ controller/ssd1306/ssd1306.go | 236 +++++++++++++++++++++++++++++ controller/ssd1306/ssd1306_test.go | 149 ++++++++++++++++++ samples/ssd1306.go | 116 ++++++++++++++ 5 files changed, 725 insertions(+) create mode 100644 controller/ssd1306/buffer.go create mode 100644 controller/ssd1306/buffer_test.go create mode 100644 controller/ssd1306/ssd1306.go create mode 100644 controller/ssd1306/ssd1306_test.go create mode 100644 samples/ssd1306.go diff --git a/controller/ssd1306/buffer.go b/controller/ssd1306/buffer.go new file mode 100644 index 0000000..806a1a5 --- /dev/null +++ b/controller/ssd1306/buffer.go @@ -0,0 +1,98 @@ +package ssd1306 + +import "errors" + +// Buffer abstracts "drawing" into an 8-row page space for Display calls into an SSD1306. +// A suitably-sized instance is created using NewBuffer on an SSD1306 instance. +type Buffer interface { + On(x, y int) error + Off(x, y int) error + Set(x, y int, on bool) error + FillRect(x, y int, w, h int) error + ClearRect(x, y int, w, h int) error + Cells() []byte +} + +// bufferHoriz is a Buffer that operates in memory mode of SSD1306_MEMORYMODE_HORIZ +type bufferHoriz struct { + cells []byte + width uint + pages uint +} + +func newBuffer(width, pages uint, memoryMode int) Buffer { + switch memoryMode { + case SSD1306_MEMORYMODE_HORIZ: + return newBufferHoriz(width, pages) + } + + return nil +} + +func newBufferHoriz(width, pages uint) *bufferHoriz { + return &bufferHoriz{ + width: width, + pages: pages, + cells: make([]byte, width*pages), + } +} + +func (b *bufferHoriz) Cells() []byte { + return b.cells +} + +func (b *bufferHoriz) On(x, y int) error { + return b.Set(x, y, true) +} + +func (b *bufferHoriz) Off(x, y int) error { + return b.Set(x, y, false) +} + +func (b *bufferHoriz) Set(x, y int, on bool) error { + if uint(x) > b.width { + return errors.New("x cannot be greater than buffer width") + } + page := uint(y) >> 3 + if page > b.pages { + return errors.New("y cannot be greater than buffer height") + } + + index := uint(page*b.width) + uint(x) + cell := b.cells[index] + + bit := byte(1) << (uint(y) & 0x7) + if on { + cell |= bit + } else { + cell &^= bit + } + + b.cells[index] = cell + + return nil +} + +func (b *bufferHoriz) FillRect(x, y int, w, h int) error { + for xi := 0; xi < w; xi++ { + for yi := 0; yi < h; yi++ { + if err := b.Set(x+xi, y+yi, true); err != nil { + return err + } + } + } + + return nil +} + +func (b *bufferHoriz) ClearRect(x, y int, w, h int) error { + for xi := 0; xi < w; xi++ { + for yi := 0; yi < h; yi++ { + if err := b.Set(x+xi, y+yi, false); err != nil { + return err + } + } + } + + return nil +} diff --git a/controller/ssd1306/buffer_test.go b/controller/ssd1306/buffer_test.go new file mode 100644 index 0000000..e12ccdb --- /dev/null +++ b/controller/ssd1306/buffer_test.go @@ -0,0 +1,126 @@ +package ssd1306 + +import ( + "reflect" + "testing" +) + +func TestAllocation(t *testing.T) { + buffer := newBuffer(16, 2, memoryMode) + if buffer == nil { + t.Fatal("buffer shouldn't be nil") + } + + if buffer.Cells() == nil { + t.Fatal("cells shouldn't be nil") + } + + if len(buffer.Cells()) != 32 { + t.Error("wrong cell count") + } +} + +var onTests = []struct { + name string + x, y int + expected []byte +}{ + {name: "top left", x: 0, y: 0, expected: []byte{0x1, 0, 0, 0, 0, 0, 0, 0 /*page*/, 0, 0, 0, 0, 0, 0, 0, 0}}, + {name: "left top of page 2", x: 0, y: 8, expected: []byte{0, 0, 0, 0, 0, 0, 0, 0 /*page*/, 0x1, 0, 0, 0, 0, 0, 0, 0}}, + {name: "left row 2", x: 0, y: 1, expected: []byte{1 << 1, 0, 0, 0, 0, 0, 0, 0 /*page*/, 0, 0, 0, 0, 0, 0, 0, 0}}, + {name: "middle ish", x: 4, y: 3, expected: []byte{0, 0, 0, 0, 1 << 3, 0, 0, 0 /*page*/, 0, 0, 0, 0, 0, 0, 0, 0}}, + {name: "bottom ish", x: 6, y: 14, expected: []byte{0, 0, 0, 0, 0, 0, 0, 0 /*page*/, 0, 0, 0, 0, 0, 0, 1 << (14 - 8), 0}}, +} + +func TestBufferHoriz_On(t *testing.T) { + width := uint(8) + pages := uint(2) // height = 16 + + for _, tt := range onTests { + t.Run(tt.name, func(t *testing.T) { + buffer := newBufferHoriz(width, pages) + + buffer.On(tt.x, tt.y) + + if !reflect.DeepEqual(buffer.cells, tt.expected) { + t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) + } + }) + } +} + +func TestBufferHoriz_Set(t *testing.T) { + width := uint(8) + pages := uint(2) // height = 16 + + for _, tt := range onTests { + t.Run(tt.name, func(t *testing.T) { + buffer := newBufferHoriz(width, pages) + buffer.Set(tt.x, tt.y, true) + + if !reflect.DeepEqual(buffer.cells, tt.expected) { + t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) + } + }) + } +} + +func TestBufferHoriz_FillRect(t *testing.T) { + width := uint(8) + pages := uint(2) // height = 16 + + tests := []struct { + name string + x, y int + width, height int + expected []byte + }{ + {name: "all", x: 0, y: 0, width: 8, height: 16, expected: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {name: "top half", x: 0, y: 0, width: 8, height: 8, expected: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}}, + {name: "top left", x: 0, y: 0, width: 4, height: 8, expected: []byte{0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + {name: "top quarter", x: 0, y: 0, width: int(width), height: 4, expected: []byte{0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0, 0, 0, 0, 0, 0, 0, 0}}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + buffer := newBufferHoriz(width, pages) + + buffer.FillRect(tt.x, tt.y, tt.width, tt.height) + + if !reflect.DeepEqual(buffer.cells, tt.expected) { + t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) + } + }) + } +} + +func TestBufferHoriz_Off(t *testing.T) { + width := uint(8) + pages := uint(2) // height = 16 + + tests := []struct { + name string + x, y int + expected []byte + }{ + {name: "top left", x: 0, y: 0, expected: []byte{0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {name: "bottom of upper page", x: 1, y: 7, expected: []byte{0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {name: "top of second page", x: 2, y: 8, expected: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff}}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + buffer := newBufferHoriz(width, pages) + + // assumes TestBufferHoriz_FillRect passes + buffer.FillRect(0, 0, 8, 16) + + buffer.Off(tt.x, tt.y) + + if !reflect.DeepEqual(buffer.cells, tt.expected) { + t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) + } + + }) + } +} diff --git a/controller/ssd1306/ssd1306.go b/controller/ssd1306/ssd1306.go new file mode 100644 index 0000000..61eb5a9 --- /dev/null +++ b/controller/ssd1306/ssd1306.go @@ -0,0 +1,236 @@ +/* +Package ssd1306 allows controlling an SSD1306 OLED controller. + +This currently supports only write-only operations and a SPI connection to the controller. + +Resources + +This library is based on these prior implementations: + https://github.com/adafruit/Adafruit_Python_SSD1306/blob/master/Adafruit_SSD1306/SSD1306.py + https://github.com/kakaryan/i2cssd1306/blob/master/ssd1306.go + +Datasheet + https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf +*/ +package ssd1306 + +import ( + "github.com/golang/glog" + "github.com/kidoman/embd" + "time" +) + +const ( + SSD1306_I2C_ADDRESS = 0x3C + SSD1306_SETCONTRAST = 0x81 + SSD1306_DISPLAYALLON_RESUME = 0xA4 + SSD1306_DISPLAYALLON = 0xA5 + SSD1306_NORMALDISPLAY = 0xA6 + SSD1306_INVERTDISPLAY = 0xA7 + SSD1306_DISPLAYOFF = 0xAE + SSD1306_DISPLAYON = 0xAF + SSD1306_SETDISPLAYOFFSET = 0xD3 + SSD1306_SETCOMPINS = 0xDA + SSD1306_SETVCOMDETECT = 0xDB + SSD1306_SETDISPLAYCLOCKDIV = 0xD5 + SSD1306_SETPRECHARGE = 0xD9 + SSD1306_SETMULTIPLEX = 0xA8 + SSD1306_SETLOWCOLUMN = 0x00 + SSD1306_SETHIGHCOLUMN = 0x10 + SSD1306_SETSTARTLINE = 0x40 + SSD1306_MEMORYMODE = 0x20 + SSD1306_MEMORYMODE_HORIZ = 0x00 + SSD1306_COLUMNADDR = 0x21 + SSD1306_PAGEADDR = 0x22 + SSD1306_COMSCANINC = 0xC0 + SSD1306_COMSCANDEC = 0xC8 + SSD1306_SEGREMAP = 0xA0 + SSD1306_CHARGEPUMP = 0x8D + SSD1306_EXTERNALVCC = 0x1 + SSD1306_SWITCHCAPVCC = 0x2 + + SSD1306_ACTIVATE_SCROLL = 0x2F + SSD1306_DEACTIVATE_SCROLL = 0x2E + SSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3 + SSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26 + SSD1306_LEFT_HORIZONTAL_SCROLL = 0x27 + SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29 + SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A +) + +const ( + memoryMode = SSD1306_MEMORYMODE_HORIZ +) + +// SSD1306 represents an instance of an SSD1306 OLED controller. +type SSD1306 struct { + spiBus embd.SPIBus + dcPin embd.DigitalPin + resetPin embd.DigitalPin + vccState byte + width uint + height uint + pages uint +} + +// NewSPI creates a new SSD1306 controller connected via the given SPIBus. +// The GPIO digital output pins that are connected to DC and Rst must also be provided. +// Finally the width x height of the OLED must be given where the width is usually 128 and height is either 32 or 64. +func NewSPI(spiBus embd.SPIBus, dcPin, resetPin embd.DigitalPin, width, height uint) (*SSD1306, error) { + controller := &SSD1306{ + spiBus: spiBus, + dcPin: dcPin, + resetPin: resetPin, + vccState: SSD1306_SWITCHCAPVCC, + width: width, + height: height, + pages: height / 8, + } + + err := controller.reset() + if err != nil { + glog.Errorf("ssd1306: failed to reset: %s", err) + return nil, err + } + err = controller.init() + if err != nil { + glog.Errorf("ssd1306: failed to init: %s", err) + return nil, err + } + + return controller, nil +} + +func (c *SSD1306) reset() error { + + if err := c.resetPin.Write(embd.High); err != nil { + return err + } + time.Sleep(1 * time.Millisecond) + + if err := c.resetPin.Write(embd.Low); err != nil { + return err + } + time.Sleep(10 * time.Millisecond) + + if err := c.resetPin.Write(embd.High); err != nil { + return err + } + + return nil +} + +func (c *SSD1306) init() error { + + if err := c.command(SSD1306_DISPLAYOFF); err != nil { + return err + } + if err := c.command(SSD1306_SETDISPLAYCLOCKDIV, 0x80); err != nil { + return err + } + if err := c.command(SSD1306_SETMULTIPLEX, 0x3F); err != nil { + return err + } + if err := c.command(SSD1306_SETDISPLAYOFFSET, 0x0); err != nil { + return err + } + if err := c.command(SSD1306_SETSTARTLINE | 0x0); err != nil { + return err + } + if c.vccState == SSD1306_EXTERNALVCC { + if err := c.command(SSD1306_CHARGEPUMP, 0x10); err != nil { + return err + } + } else { + if err := c.command(SSD1306_CHARGEPUMP, 0x14); err != nil { + return err + } + } + + if err := c.command(SSD1306_MEMORYMODE, memoryMode); err != nil { + return err + } + if err := c.command(SSD1306_SEGREMAP | 0x1); err != nil { + return err + } + if err := c.command(SSD1306_COMSCANDEC); err != nil { + return err + } + if err := c.command(SSD1306_SETCOMPINS, 0x12); err != nil { + return err + } + if c.vccState == SSD1306_EXTERNALVCC { + if err := c.command(SSD1306_SETCONTRAST, 0x9F); err != nil { + return err + } + } else { + if err := c.command(SSD1306_SETCONTRAST, 0xCF); err != nil { + return err + } + } + + if c.vccState == SSD1306_EXTERNALVCC { + if err := c.command(SSD1306_SETPRECHARGE, 0x22); err != nil { + return err + } + + } else { + if err := c.command(SSD1306_SETPRECHARGE, 0xF1); err != nil { + return err + } + } + + if err := c.command(SSD1306_SETVCOMDETECT, 0x40); err != nil { + return err + } + if err := c.command(SSD1306_DISPLAYALLON_RESUME); err != nil { + return err + } + if err := c.command(SSD1306_NORMALDISPLAY); err != nil { + return err + } + + if err := c.command(SSD1306_DISPLAYON); err != nil { + return err + } + + return nil +} + +func (c *SSD1306) command(cmd ...byte) error { + c.dcPin.Write(embd.Low) + _, err := c.spiBus.Write(cmd) + + return err +} + +func (c *SSD1306) data(d ...byte) error { + c.dcPin.Write(embd.High) + _, err := c.spiBus.Write(d) + + return err +} + +// Display sends the given buffer to the controller to "rendered" +func (c *SSD1306) Display(buf Buffer) error { + if err := c.command(SSD1306_COLUMNADDR, 0, byte(c.width-1)); err != nil { + return err + } + if err := c.command(SSD1306_PAGEADDR, 0, byte(c.pages-1)); err != nil { + return err + } + return c.data(buf.Cells()...) +} + +// Close turns the display off +func (c *SSD1306) Close() error { + if err := c.command(SSD1306_DISPLAYOFF); err != nil { + return err + } + return nil +} + +// NewBuffer creates a buffer that is suitably configured to be used in Display calls. +func (c *SSD1306) NewBuffer() Buffer { + return newBuffer(c.width, c.pages, memoryMode) +} diff --git a/controller/ssd1306/ssd1306_test.go b/controller/ssd1306/ssd1306_test.go new file mode 100644 index 0000000..da435b0 --- /dev/null +++ b/controller/ssd1306/ssd1306_test.go @@ -0,0 +1,149 @@ +package ssd1306 + +import ( + "github.com/kidoman/embd" + "testing" + "time" +) + +type mockSpiBus struct { + chunks [][]byte +} + +func (s *mockSpiBus) Write(p []byte) (n int, err error) { + s.chunks = append(s.chunks, p) + return 0, nil +} +func (s *mockSpiBus) TransferAndReceiveData(dataBuffer []uint8) error { return nil } +func (s *mockSpiBus) ReceiveData(len int) ([]uint8, error) { return nil, nil } +func (s *mockSpiBus) TransferAndReceiveByte(data byte) (byte, error) { return 0, nil } +func (s *mockSpiBus) ReceiveByte() (byte, error) { return 0, nil } +func (s *mockSpiBus) Close() error { return nil } + +type mockPin struct { + values []int +} + +func (p *mockPin) Watch(edge embd.Edge, handler func(embd.DigitalPin)) error { return nil } +func (p *mockPin) StopWatching() error { return nil } +func (p *mockPin) N() int { return 0 } +func (p *mockPin) Write(val int) error { + p.values = append(p.values, val) + return nil +} +func (p *mockPin) Read() (int, error) { return 0, nil } +func (p *mockPin) TimePulse(state int) (time.Duration, error) { return 0, nil } +func (p *mockPin) SetDirection(dir embd.Direction) error { return nil } +func (p *mockPin) ActiveLow(b bool) error { return nil } +func (p *mockPin) PullUp() error { return p.Write(1) } +func (p *mockPin) PullDown() error { return p.Write(0) } +func (p *mockPin) Close() error { return nil } + +func TestInit(t *testing.T) { + + spiBus := &mockSpiBus{} + dcPin := &mockPin{} + resetPin := &mockPin{} + + controller, err := NewSPI(spiBus, dcPin, resetPin, 128, 64) + if err != nil { + t.Fatalf("Shouldn't be an error: %s", err) + } + if controller == nil { + t.Fatal("controller shouldn't be nil") + } + + if len(resetPin.values) != 3 { + t.Error("expected 3 touches to the reset pin") + } + + if len(dcPin.values) != 16 { + t.Error("expected 16 touches to the dc pin") + } + + if len(spiBus.chunks) != 16 { + t.Error("expected 16 commands during init") + } + i := 0 + + if spiBus.chunks[i][0] != SSD1306_DISPLAYOFF { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_SETDISPLAYCLOCKDIV { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_SETMULTIPLEX { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_SETDISPLAYOFFSET { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_SETSTARTLINE|0x0 { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_CHARGEPUMP { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_MEMORYMODE { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_SEGREMAP|0x1 { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_COMSCANDEC { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_SETCOMPINS { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_SETCONTRAST { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_SETPRECHARGE { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_SETVCOMDETECT { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_DISPLAYALLON_RESUME { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_NORMALDISPLAY { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + + if spiBus.chunks[i][0] != SSD1306_DISPLAYON { + t.Errorf("Wrong command in chunk %d", i) + } + i++ + +} diff --git a/samples/ssd1306.go b/samples/ssd1306.go new file mode 100644 index 0000000..d533453 --- /dev/null +++ b/samples/ssd1306.go @@ -0,0 +1,116 @@ +// +build ignore + +// This sample runs on a monochrome 128x64 OLED graphic display using an SSD1306 controller, +// such as https://www.adafruit.com/product/938. +// It demonstrates the rectangular fill/clear and point on/off operations animated across the display. + +package main + +import ( + "github.com/golang/glog" + "github.com/kidoman/embd" + "github.com/kidoman/embd/controller/ssd1306" + _ "github.com/kidoman/embd/host/rpi" // This loads the RPi driver + + "flag" + "os" + "os/signal" + "time" +) + +func main() { + flag.Parse() + glog.Info("Starting") + + if err := embd.InitSPI(); err != nil { + panic(err) + } + defer embd.CloseSPI() + + spiBus := embd.NewSPIBus(embd.SPIMode0, 0, 1000000, 8, 0) + defer spiBus.Close() + + if err := embd.InitGPIO(); err != nil { + panic(err) + } + defer embd.CloseGPIO() + + dcPin := setupPin("GPIO_23") + defer dcPin.Close() + resetPin := setupPin("GPIO_24") + defer resetPin.Close() + + controller, err := ssd1306.NewSPI(spiBus, dcPin, resetPin, 128, 64) + if err != nil { + glog.Fatalf("Failed to start: %s", err) + } + defer controller.Close() + + buffer := controller.NewBuffer() + first := true + chunkWidth := 32 + chunkHeight := 20 + zipDir := 1 + zipX := 0 + prevZipX := 0 + var prevX, prevY int + + // Setup Control-C to gracefully stop + done := make(chan os.Signal, 1) + signal.Notify(done, os.Interrupt) + +outer: + for { + + for y := 0; y+chunkHeight <= 64; y += chunkHeight { + for x := 0; x+chunkWidth <= 128; x += chunkWidth { + select { + case <-done: + break outer + default: + glog.Infof("x=%d, y=%d\n", x, y) + if !first { + buffer.ClearRect(prevX, prevY, chunkWidth, chunkHeight) + } else { + first = false + } + buffer.FillRect(x, y, chunkWidth, chunkHeight) + prevX = x + prevY = y + + buffer.Off(prevZipX, 63) + buffer.On(zipX, 63) + prevZipX = zipX + zipX += zipDir + if zipX >= 128 { + zipX = 127 + zipDir = -1 + } else if zipX < 0 { + zipX = 0 + zipDir = 1 + } + + controller.Display(buffer) + + time.Sleep(100 * time.Millisecond) + } + } + } + + } + +} + +func setupPin(key string) embd.DigitalPin { + + p, err := embd.NewDigitalPin(key) + if err != nil { + panic(err) + } + + if err := p.SetDirection(embd.Out); err != nil { + panic(err) + } + + return p +} From 6e08978999b40c6e34b8c2ec24987e45c8e4cf80 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sat, 2 Sep 2017 08:32:57 -0500 Subject: [PATCH 2/2] ssd1306: making unit test go 1.6 compatible --- controller/ssd1306/buffer_test.go | 64 ++++++++++++++++--------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/controller/ssd1306/buffer_test.go b/controller/ssd1306/buffer_test.go index e12ccdb..c4df518 100644 --- a/controller/ssd1306/buffer_test.go +++ b/controller/ssd1306/buffer_test.go @@ -37,15 +37,16 @@ func TestBufferHoriz_On(t *testing.T) { pages := uint(2) // height = 16 for _, tt := range onTests { - t.Run(tt.name, func(t *testing.T) { - buffer := newBufferHoriz(width, pages) + // Disabling testing Run use since this needs to build in go 1.6 also + //t.Run(tt.name, func(t *testing.T) { + buffer := newBufferHoriz(width, pages) - buffer.On(tt.x, tt.y) + buffer.On(tt.x, tt.y) - if !reflect.DeepEqual(buffer.cells, tt.expected) { - t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) - } - }) + if !reflect.DeepEqual(buffer.cells, tt.expected) { + t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) + } + //}) } } @@ -54,14 +55,15 @@ func TestBufferHoriz_Set(t *testing.T) { pages := uint(2) // height = 16 for _, tt := range onTests { - t.Run(tt.name, func(t *testing.T) { - buffer := newBufferHoriz(width, pages) - buffer.Set(tt.x, tt.y, true) + // Disabling testing Run use since this needs to build in go 1.6 also + //t.Run(tt.name, func(t *testing.T) { + buffer := newBufferHoriz(width, pages) + buffer.Set(tt.x, tt.y, true) - if !reflect.DeepEqual(buffer.cells, tt.expected) { - t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) - } - }) + if !reflect.DeepEqual(buffer.cells, tt.expected) { + t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) + } + //}) } } @@ -82,15 +84,16 @@ func TestBufferHoriz_FillRect(t *testing.T) { } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - buffer := newBufferHoriz(width, pages) + // Disabling testing Run use since this needs to build in go 1.6 also + //t.Run(tt.name, func(t *testing.T) { + buffer := newBufferHoriz(width, pages) - buffer.FillRect(tt.x, tt.y, tt.width, tt.height) + buffer.FillRect(tt.x, tt.y, tt.width, tt.height) - if !reflect.DeepEqual(buffer.cells, tt.expected) { - t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) - } - }) + if !reflect.DeepEqual(buffer.cells, tt.expected) { + t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) + } + //}) } } @@ -109,18 +112,19 @@ func TestBufferHoriz_Off(t *testing.T) { } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - buffer := newBufferHoriz(width, pages) + // Disabling testing Run use since this needs to build in go 1.6 also + //t.Run(tt.name, func(t *testing.T) { + buffer := newBufferHoriz(width, pages) - // assumes TestBufferHoriz_FillRect passes - buffer.FillRect(0, 0, 8, 16) + // assumes TestBufferHoriz_FillRect passes + buffer.FillRect(0, 0, 8, 16) - buffer.Off(tt.x, tt.y) + buffer.Off(tt.x, tt.y) - if !reflect.DeepEqual(buffer.cells, tt.expected) { - t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) - } + if !reflect.DeepEqual(buffer.cells, tt.expected) { + t.Errorf("%s: wrong cell content, saw %v", tt.name, buffer.cells) + } - }) + //}) } }