Ayke van Laethem

LED cube using TinyGo

@aykevl
@aykevl

"If Python can run on microcontrollers,
why not Go?"
At Chaos Communication Congress 2018

twitter.com/Icewalker1974/status/1165148285960634368

Microchip SAM D5

ARM Cortex-M4

120MHz

// +build itsybitsy_m4

package main

import (
	"machine"

	"github.com/aykevl/things/hub75"
)

var display = hub75.New(hub75.Config{
	Data:         machine.NoPin,
	Clock:        machine.NoPin,
	Latch:        machine.D5,
	OutputEnable: machine.D7,
	A:            machine.D9,
	B:            machine.D10,
	C:            machine.D11,
	D:            machine.D12,
	NumScreens:   6,
	Brightness:   1,
})
type Displayer interface {
	// Size returns the current size of the display.
	Size() (x, y int16)

	// SetPizel modifies the internal buffer.
	SetPixel(x, y int16, c color.RGBA)

	// Display sends the buffer (if any) to the screen.
	Display() error
}
func drawPixels(t time.Time, getColor func(x, y, z int, t time.Time) color.RGBA) {
	for x := 0; x < size; x++ {
		for y := 0; y < size; y++ {
			display.SetPixel(int16(x+size*5), int16(y), getColor(x+1, y+1, 0, t))
			display.SetPixel(int16(x+size*4), int16(y), getColor(0, x+1, y+1, t))
			display.SetPixel(int16(x+size*3), int16(y), getColor(size-x, 0, y+1, t))
			display.SetPixel(int16(x+size*2), int16(y), getColor(size+1, size-x, y+1, t))
			display.SetPixel(int16(x+size*1), int16(y), getColor(x+1, size+1, y+1, t))
			display.SetPixel(int16(x+size*0), int16(y), getColor(x+1, size-y, size+1, t))
		}
	}
}
// noiseAt returns noise at the specified location.
func noiseAt(x, y, z int, t time.Time) color.RGBA {
	value := ledsgo.Noise4(
		int32(t.UnixNano()>>20),
		int32(x*128),
		int32(y*128),
		int32(z*128),
	)
	hue := uint16(value) * 2
	return ledsgo.Color{hue, 0xff, 0xff}.Spectrum()
}
// fireAt returns fire at the specified location.
func fireAt(x, y, z int, t time.Time) color.RGBA {
	const pointsPerCircle = 12 // how many LEDs there are per turn of the torch
	const cooling = 56         // higher means faster cooling
	const detail = 400         // higher means more detailed flames
	const speed = 12           // higher means faster
	const screenHeight = 33
	if z == 0 {
		return color.RGBA{}
	}
	heat := ledsgo.Noise3(
		int32((31-z)*detail)-int32((t.UnixNano()>>20)*speed),
		int32(x*detail),
		int32(y*detail))/32 + (128 * 8,
	)
	heat -= int16(screenHeight-z) * cooling
	if heat < 0 {
		heat = 0
	}
	return heatMap(heat)
}
// +build !baremetal

package main

import (
	"log"

	"github.com/aykevl/tilegraphics/sdlscreen"
)

var display *sdlscreen.Screen

func init() {
	const scale = 8
	var err error
	display, err = sdlscreen.NewScreen("LED cube", 32*6*scale, 32*scale)
	if err != nil {
		log.Fatalln("could not instantiate screen:", err)
	}
	display.Scale = scale
}