aboutsummaryrefslogtreecommitdiff
path: root/Unicorn.go
diff options
context:
space:
mode:
Diffstat (limited to 'Unicorn.go')
-rw-r--r--Unicorn.go198
1 files changed, 198 insertions, 0 deletions
diff --git a/Unicorn.go b/Unicorn.go
new file mode 100644
index 0000000..2e0e73f
--- /dev/null
+++ b/Unicorn.go
@@ -0,0 +1,198 @@
+package main
+
+import (
+ "github.com/veandco/go-sdl2/sdl"
+ // "golang.org/x/exp/io/spi"
+ // "github.com/veandco/go-sdl2/sdl"
+)
+
+// Unicorn ...
+// Object representing the Unicorn HAT to be controlled
+type Unicorn interface {
+ // Not all unicorns are the same size
+ GetWidth() uint8
+ GetHeight() uint8
+
+ // Array of pixels, indexed x, then y, then color (rgb)
+ GetPixels() [][][]uint8
+
+ // Set an individual pixel
+ SetPixel(x, y, r, g, b uint8)
+
+ // Flip the display buffer
+ Show()
+
+ // Set all pixels back to black
+ Clear()
+
+ // Turns off the LEDs
+ Off()
+}
+
+// GetUnicorn ...
+// 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 = NewFake(uint8(16), uint8(16))
+ return
+}
+
+// FakeUnicorn ...
+// Shows an SDL window pretending to be a unicorn.
+type FakeUnicorn 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 {
+ return uint8(len(f.pixels))
+}
+func (f *FakeUnicorn) GetHeight() uint8 {
+ if len(f.pixels) > 0 {
+ return uint8(len(f.pixels[0]))
+ }
+ return 0
+}
+func (f *FakeUnicorn) GetPixels() [][][]uint8 {
+ return f.pixels
+}
+func (f *FakeUnicorn) 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() {
+ f.pixels = makePixels(f.GetWidth(), f.GetHeight())
+}
+func (f *FakeUnicorn) Off() {
+ f.Close()
+}
+
+func makePixels(width, height uint8) [][][]uint8 {
+ pixels := make([][][]uint8, width)
+ for x := uint8(0); x < width; x++ {
+ pixels[x] = make([][]uint8, height)
+ for y := uint8(0); y < height; y++ {
+ pixels[x][y] = []uint8{0, 0, 0}
+ }
+ }
+ 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() {
+
+// }