LED cube using TinyGo
"If Python can run on microcontrollers,
why not Go?"

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
}