aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Ashby <martin@martin-laptop.lan>2018-05-18 22:22:20 +0100
committerMartin Ashby <martin@martin-laptop.lan>2018-05-18 22:22:20 +0100
commitd2dea8058c88b39f161178f59c6bfec0e32dfa02 (patch)
tree3f99a78602ee781943e4269fa20fe01080a78fe4
parentb3e76b0207bc4232b4b72626f8c4c802dcc63802 (diff)
downloadunicornpaint-d2dea8058c88b39f161178f59c6bfec0e32dfa02.tar.gz
unicornpaint-d2dea8058c88b39f161178f59c6bfec0e32dfa02.tar.bz2
unicornpaint-d2dea8058c88b39f161178f59c6bfec0e32dfa02.tar.xz
unicornpaint-d2dea8058c88b39f161178f59c6bfec0e32dfa02.zip
Initial implementation of go unicorn hat driver
-rw-r--r--FakeUnicorn.go94
-rw-r--r--RealUnicorn.go62
-rw-r--r--Unicorn.go148
3 files changed, 171 insertions, 133 deletions
diff --git a/FakeUnicorn.go b/FakeUnicorn.go
new file mode 100644
index 0000000..2258e58
--- /dev/null
+++ b/FakeUnicorn.go
@@ -0,0 +1,94 @@
+package main
+
+import (
+ "github.com/veandco/go-sdl2/sdl"
+)
+
+type FakeUnicorn struct {
+ BaseUnicorn
+ displayWidth int32
+ displayHeight int32
+ window *sdl.Window
+ renderer *sdl.Renderer
+}
+
+// NewFake ...
+// Constructs a new fake unicorn out of paint and glue
+func NewFake(width, height uint8) (*FakeUnicorn, error) {
+ if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil {
+ return nil, err
+ }
+
+ unicorn := &FakeUnicorn{
+ BaseUnicorn{
+ pixels: makePixels(width, height),
+ },
+ 300,
+ 300,
+ nil,
+ nil,
+ }
+ if err := unicorn.createWindow(); err != nil {
+ unicorn.Close()
+ return nil, err
+ }
+ if err := unicorn.createRenderer(); err != nil {
+ unicorn.Close()
+ return nil, err
+ }
+ return unicorn, nil
+}
+
+func (f *FakeUnicorn) createWindow() error {
+ window, err := sdl.CreateWindow("Fake Unicorn",
+ sdl.WINDOWPOS_UNDEFINED,
+ sdl.WINDOWPOS_UNDEFINED,
+ f.displayWidth,
+ f.displayHeight,
+ sdl.WINDOW_SHOWN)
+ f.window = window
+ return err
+}
+
+func (f *FakeUnicorn) createRenderer() error {
+ renderer, err := sdl.CreateRenderer(f.window, -1, sdl.RENDERER_ACCELERATED)
+ f.renderer = renderer
+ return err
+}
+
+func (f *FakeUnicorn) Close() error {
+ if f.window != nil {
+ f.window.Destroy()
+ }
+ if f.renderer != nil {
+ f.renderer.Destroy()
+ }
+ return nil
+}
+
+func (f *FakeUnicorn) Show() {
+ width, height := f.GetWidth(), f.GetHeight()
+ for x := uint8(0); x < width; x++ {
+ for y := uint8(0); y < height; y++ {
+ r, g, b := rgb(f.pixels[x][y])
+ if err := f.renderer.SetDrawColor(r, g, b, uint8(255)); err != nil {
+ panic(err)
+ }
+ cellWidth := f.displayWidth / int32(width)
+ cellHeight := f.displayHeight / int32(height)
+ if err := f.renderer.FillRect(&sdl.Rect{
+ X: cellWidth * int32(x),
+ Y: f.displayHeight - (cellHeight * int32(y)) - cellHeight, // SDL Y coordinate is from the top
+ W: cellWidth,
+ H: cellHeight,
+ }); err != nil {
+ panic(err)
+ }
+ }
+ }
+ f.renderer.Present()
+}
+
+func (f *FakeUnicorn) Off() {
+ f.Close()
+}
diff --git a/RealUnicorn.go b/RealUnicorn.go
new file mode 100644
index 0000000..d9665d8
--- /dev/null
+++ b/RealUnicorn.go
@@ -0,0 +1,62 @@
+package main
+
+import (
+ "golang.org/x/exp/io/spi"
+ "log"
+)
+
+type RealUnicorn struct {
+ BaseUnicorn
+ device *spi.Device
+}
+
+// NewReal ...
+// Constructs a new real unicorn from fairy dust and sprinkles
+func NewReal() (*RealUnicorn, error) {
+ dev, err := spi.Open(&spi.Devfs{
+ Dev: "/dev/spidev0.0",
+ Mode: spi.Mode0,
+ MaxSpeed: 9000000,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return &RealUnicorn{
+ BaseUnicorn{
+ pixels: makePixels(16, 16),
+ },
+ dev,
+ }, nil
+}
+
+func (u *RealUnicorn) Show() {
+ // Width * height * colours + leading bit
+ width := u.GetWidth()
+ height := u.GetHeight()
+ write := make([]byte, (width*height*3)+1)
+
+ // Add the leading bit
+ write[0] = 0x72
+ // Add all the pixel values
+ ix := 1
+ for x := uint8(0); x < width; x++ {
+ for y := uint8(0); y < height; y++ {
+ for j := 0; j < 3; j++ {
+ write[ix] = u.pixels[x][y][j]
+ ix++
+ }
+ }
+ }
+ // Write to the device
+ err := u.device.Tx(write, nil)
+ if err != nil {
+ log.Printf("Error writing to SPI device %v", err)
+ }
+}
+func (u *RealUnicorn) Off() {
+ u.Close()
+}
+func (u *RealUnicorn) Close() error {
+ return u.device.Close()
+}
diff --git a/Unicorn.go b/Unicorn.go
index 2e0e73f..905cc0a 100644
--- a/Unicorn.go
+++ b/Unicorn.go
@@ -1,9 +1,7 @@
package main
import (
- "github.com/veandco/go-sdl2/sdl"
- // "golang.org/x/exp/io/spi"
- // "github.com/veandco/go-sdl2/sdl"
+ "log"
)
// Unicorn ...
@@ -33,126 +31,37 @@ type Unicorn interface {
// Get a unicorn. Tries to get you a real one,
// if it can't find one then gives you a fake one.
func GetUnicorn() (unicorn Unicorn, err error) {
- // unicorn, err = NewReal()
- // if err != nil {
- // log.Println("Couldn't get a real unicorn, trying a fake one")
- // unicorn, err = NewFake(int8(16), int8(16))
- // }
+ unicorn, err = NewReal()
+ if err != nil {
+ log.Println("Couldn't get a real unicorn, trying a fake one")
+ unicorn, err = NewFake(uint8(16), uint8(16))
+ }
unicorn, err = NewFake(uint8(16), uint8(16))
return
}
-// FakeUnicorn ...
-// Shows an SDL window pretending to be a unicorn.
-type FakeUnicorn struct {
+type BaseUnicorn struct {
pixels [][][]uint8
- displayWidth int32
- displayHeight int32
-
- window *sdl.Window
- renderer *sdl.Renderer
-}
-
-// NewFake ...
-// Constructs a new fake unicorn out of paint and glue
-func NewFake(width, height uint8) (*FakeUnicorn, error) {
- if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil {
- return nil, err
- }
-
- unicorn := &FakeUnicorn{
- pixels: makePixels(width, height),
- window: nil,
- renderer: nil,
- displayWidth: 300,
- displayHeight: 300,
- }
- if err := unicorn.createWindow(); err != nil {
- unicorn.Close()
- return nil, err
- }
- if err := unicorn.createRenderer(); err != nil {
- unicorn.Close()
- return nil, err
- }
- return unicorn, nil
}
-func (f *FakeUnicorn) createWindow() error {
- window, err := sdl.CreateWindow("Fake Unicorn",
- sdl.WINDOWPOS_UNDEFINED,
- sdl.WINDOWPOS_UNDEFINED,
- f.displayWidth,
- f.displayHeight,
- sdl.WINDOW_SHOWN)
- f.window = window
- return err
-}
-
-func (f *FakeUnicorn) createRenderer() error {
- renderer, err := sdl.CreateRenderer(f.window, -1, sdl.RENDERER_ACCELERATED)
- f.renderer = renderer
- return err
-}
-
-func (f *FakeUnicorn) Close() error {
- if f.window != nil {
- f.window.Destroy()
- }
- if f.renderer != nil {
- f.renderer.Destroy()
- }
- return nil
-}
-
-func (f *FakeUnicorn) GetWidth() uint8 {
+func (f *BaseUnicorn) GetWidth() uint8 {
return uint8(len(f.pixels))
}
-func (f *FakeUnicorn) GetHeight() uint8 {
+func (f *BaseUnicorn) GetHeight() uint8 {
if len(f.pixels) > 0 {
return uint8(len(f.pixels[0]))
}
return 0
}
-func (f *FakeUnicorn) GetPixels() [][][]uint8 {
+func (f *BaseUnicorn) GetPixels() [][][]uint8 {
return f.pixels
}
-func (f *FakeUnicorn) SetPixel(x, y, r, g, b uint8) {
+func (f *BaseUnicorn) SetPixel(x, y, r, g, b uint8) {
f.pixels[x][y] = []uint8{r, g, b}
}
-func (f *FakeUnicorn) Show() {
- width, height := f.GetWidth(), f.GetHeight()
- for x := uint8(0); x < width; x++ {
- for y := uint8(0); y < height; y++ {
- r, g, b := rgb(f.pixels[x][y])
- if err := f.renderer.SetDrawColor(r, g, b, uint8(255)); err != nil {
- panic(err)
- }
- cellWidth := f.displayWidth / int32(width)
- cellHeight := f.displayHeight / int32(height)
- if err := f.renderer.FillRect(&sdl.Rect{
- X: cellWidth * int32(x),
- Y: f.displayHeight - (cellHeight * int32(y)) - cellHeight, // SDL Y coordinate is from the top
- W: cellWidth,
- H: cellHeight,
- }); err != nil {
- panic(err)
- }
- }
- }
- f.renderer.Present()
-}
-
-func rgb(pixel []uint8) (uint8, uint8, uint8) {
- return pixel[0], pixel[1], pixel[2]
-}
-
-func (f *FakeUnicorn) Clear() {
+func (f *BaseUnicorn) Clear() {
f.pixels = makePixels(f.GetWidth(), f.GetHeight())
}
-func (f *FakeUnicorn) Off() {
- f.Close()
-}
func makePixels(width, height uint8) [][][]uint8 {
pixels := make([][][]uint8, width)
@@ -165,34 +74,7 @@ func makePixels(width, height uint8) [][][]uint8 {
return pixels
}
-// RealUnicorn ...
-// A real one! *gasps*
-// type RealUnicorn struct {}
-
-// // NewReal ...
-// // Constructs a new real unicorn from fairy dust and sprinkles
-// func NewReal() (*RealUnicorn, error) {
-// return nil, errors.New("Couldn't make a real unicorn sorry")
-// }
-
-// func (u *RealUnicorn) GetWidth() int8 {
-// return 0
-// }
-// func (u *RealUnicorn) GetHeight() int8 {
-// return 0
-// }
-// func (u *RealUnicorn) GetPixels() [][][]int8 {
-// return nil
-// }
-// func (u *RealUnicorn) SetPixel(x, y, r, g, b int8) {
-
-// }
-// func (u *RealUnicorn) Show() {
-// }
-// func (u *RealUnicorn) Clear() {
-
-// }
-// func (u *RealUnicorn) Off() {
-
-// }
+func rgb(pixel []uint8) (uint8, uint8, uint8) {
+ return pixel[0], pixel[1], pixel[2]
+} \ No newline at end of file