Skip to content

Commit

Permalink
make tinygo drivers PR722 sample
Browse files Browse the repository at this point in the history
  • Loading branch information
ehime-iyokan committed Nov 4, 2024
1 parent 40faec5 commit 4ec0054
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 268 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ go 1.22.6
require tinygo.org/x/drivers v0.28.0

require github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect

replace tinygo.org/x/drivers v0.28.0 => github.com/ehime-iyokan/drivers v0.0.0-20241104032339-fe124078fac3
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
github.com/ehime-iyokan/drivers v0.0.0-20241104032339-fe124078fac3 h1:VF6Qvx/KZ3HKMBp/oIVGYJUOZzlMex2rPxqrHflhndM=
github.com/ehime-iyokan/drivers v0.0.0-20241104032339-fe124078fac3/go.mod h1:q/mU8G/wz821p8xXqbkBACOlmZFDHXd//DnYnCW+dDQ=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
tinygo.org/x/drivers v0.28.0 h1:ROVrGGXddmpn2+oV/Bu3LceYbtPCJckmgIqvPcN/L0k=
tinygo.org/x/drivers v0.28.0/go.mod h1:T6snsUqS0RAxOANxiV81fQwLxDDNmprxTAYzmxoA7J0=
272 changes: 6 additions & 266 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,271 +24,11 @@ import (
"strings"
"time"

"tinygo.org/x/drivers"
"tinygo.org/x/drivers/hub75"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)

// source code citation start position "tinygo.org/x/drivers/hub75" (rev.1bf1a11067968352afa5d7a489a13561effb2146)
type Config struct {
Width int16
Height int16
ColorDepth uint16
RowPattern int16
Brightness uint8
FastUpdate bool
}

type Device struct {
bus drivers.SPI
a machine.Pin
b machine.Pin
c machine.Pin
d machine.Pin
oe machine.Pin
lat machine.Pin
width int16
height int16
brightness uint8
fastUpdate bool
colorDepth uint16
colorStep uint16
colorHalfStep uint16
colorThirdStep uint16
colorTwoThirdStep uint16
rowPattern int16
rowsPerBuffer int16
panelWidth int16
panelWidthBytes int16
pixelCounter uint32
lineCounter uint32
patternColorBytes uint8
rowSetsPerBuffer uint8
sendBufferSize uint16
rowOffset []uint32
buffer [][]uint8 // [ColorDepth][(width * height * 3(rgb)) / 8]uint8
displayColor uint16
}

// New returns a new HUB75 driver. Pass in a fully configured SPI bus.
func New(b drivers.SPI, latPin, oePin, aPin, bPin, cPin, dPin machine.Pin) Device {
aPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
bPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
cPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
dPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
oePin.Configure(machine.PinConfig{Mode: machine.PinOutput})
latPin.Configure(machine.PinConfig{Mode: machine.PinOutput})

return Device{
bus: b,
a: aPin,
b: bPin,
c: cPin,
d: dPin,
oe: oePin,
lat: latPin,
}
}

// Configure sets up the device.
func (d *Device) Configure(cfg Config) {
if cfg.Width != 0 {
d.width = cfg.Width
} else {
d.width = 64
}
if cfg.Height != 0 {
d.height = cfg.Height
} else {
d.height = 32
}
if cfg.ColorDepth != 0 {
d.colorDepth = cfg.ColorDepth
} else {
d.colorDepth = 8
}
if cfg.RowPattern != 0 {
d.rowPattern = cfg.RowPattern
} else {
d.rowPattern = 16
}
if cfg.Brightness != 0 {
d.brightness = cfg.Brightness
} else {
d.brightness = 255
}

d.fastUpdate = cfg.FastUpdate
d.rowsPerBuffer = d.height / 2
d.panelWidth = 1
d.panelWidthBytes = (d.width / d.panelWidth) / 8
d.rowOffset = make([]uint32, d.height)
d.patternColorBytes = uint8((d.height / d.rowPattern) * (d.width / 8))
d.rowSetsPerBuffer = uint8(d.rowsPerBuffer / d.rowPattern)
d.sendBufferSize = uint16(d.patternColorBytes) * 3
d.colorStep = 256 / d.colorDepth
d.colorHalfStep = d.colorStep / 2
d.colorThirdStep = d.colorStep / 3
d.colorTwoThirdStep = 2 * d.colorThirdStep
d.buffer = make([][]uint8, d.colorDepth)
for i := range d.buffer {
d.buffer[i] = make([]uint8, (d.width*d.height*3)/8)
}

d.colorHalfStep = d.colorStep / 2
d.colorThirdStep = d.colorStep / 3
d.colorTwoThirdStep = 2 * d.colorThirdStep

d.a.Low()
d.b.Low()
d.c.Low()
d.d.Low()
d.oe.High()

var i uint32
for i = 0; i < uint32(d.height); i++ {
d.rowOffset[i] = (i%uint32(d.rowPattern))*uint32(d.sendBufferSize) + uint32(d.sendBufferSize) - 1
}
}

// SetPixel modifies the internal buffer in a single pixel.
func (d *Device) SetPixel(x int16, y int16, c color.RGBA) {
d.fillMatrixBuffer(x, y, c.R, c.G, c.B)
}

// fillMatrixBuffer modifies a pixel in the internal buffer given position and RGB values
func (d *Device) fillMatrixBuffer(x int16, y int16, r uint8, g uint8, b uint8) {
if x < 0 || x >= d.width || y < 0 || y >= d.height {
return
}
x = d.width - 1 - x

var offsetR uint32
var offsetG uint32
var offsetB uint32

vertIndexInBuffer := uint8((int32(y) % int32(d.rowsPerBuffer)) / int32(d.rowPattern))
whichBuffer := uint8(y / d.rowsPerBuffer)
xByte := x / 8
whichPanel := uint8(xByte / d.panelWidthBytes)
inRowByteOffset := uint8(xByte % d.panelWidthBytes)

offsetR = d.rowOffset[y] - uint32(inRowByteOffset) - uint32(d.panelWidthBytes)*
(uint32(d.rowSetsPerBuffer)*(uint32(d.panelWidth)*uint32(whichBuffer)+uint32(whichPanel))+uint32(vertIndexInBuffer))
offsetG = offsetR - uint32(d.patternColorBytes)
offsetB = offsetG - uint32(d.patternColorBytes)

bitSelect := uint8(x % 8)

for c := uint16(0); c < d.colorDepth; c++ {
colorTresh := uint8(c*d.colorStep + d.colorHalfStep)
if r > colorTresh {
d.buffer[c][offsetR] |= 1 << bitSelect
} else {
d.buffer[c][offsetR] &^= 1 << bitSelect
}
if g > colorTresh {
d.buffer[(c+d.colorThirdStep)%d.colorDepth][offsetG] |= 1 << bitSelect
} else {
d.buffer[(c+d.colorThirdStep)%d.colorDepth][offsetG] &^= 1 << bitSelect
}
if b > colorTresh {
d.buffer[(c+d.colorTwoThirdStep)%d.colorDepth][offsetB] |= 1 << bitSelect
} else {
d.buffer[(c+d.colorTwoThirdStep)%d.colorDepth][offsetB] &^= 1 << bitSelect
}
}
}

// Display sends the buffer (if any) to the screen.
func (d *Device) Display() error {
rp := uint16(d.rowPattern)
for i := uint16(0); i < rp; i++ {
// FAST UPDATES (only if brightness = 255)
if d.fastUpdate && d.brightness == 255 {
d.setMux((i + rp - 1) % rp)
d.lat.High()
d.oe.Low()
d.lat.Low()
time.Sleep(1 * time.Microsecond)
d.bus.Tx(d.buffer[d.displayColor][i*d.sendBufferSize:(i+1)*d.sendBufferSize], nil)
time.Sleep(10 * time.Microsecond)
d.oe.High()

} else { // NO FAST UPDATES
d.setMux(i)
d.bus.Tx(d.buffer[d.displayColor][i*d.sendBufferSize:(i+1)*d.sendBufferSize], nil)
d.latch((255 * uint16(d.brightness)) / 255)
}
}
d.displayColor++
if d.displayColor >= d.colorDepth {
d.displayColor = 0
}
return nil
}

func (d *Device) latch(showTime uint16) {
d.lat.High()
d.lat.Low()
d.oe.Low()
time.Sleep(time.Duration(showTime) * time.Microsecond)
d.oe.High()
}

func (d *Device) setMux(value uint16) {
if (value & 0x01) == 0x01 {
d.a.High()
} else {
d.a.Low()
}
if (value & 0x02) == 0x02 {
d.b.High()
} else {
d.b.Low()
}
if (value & 0x04) == 0x04 {
d.c.High()
} else {
d.c.Low()
}
if (value & 0x08) == 0x08 {
d.d.High()
} else {
d.d.Low()
}
}

// FlushDisplay flushes the display
func (d *Device) FlushDisplay() {
var i uint16
for i = 0; i < d.sendBufferSize; i++ {
d.bus.Tx([]byte{0x00}, nil)
}
}

// SetBrightness changes the brightness of the display
func (d *Device) SetBrightness(brightness uint8) {
d.brightness = brightness
}

// ClearDisplay erases the internal buffer
func (d *Device) ClearDisplay() {
bufferSize := (d.width * d.height * 3) / 8
for c := uint16(0); c < d.colorDepth; c++ {
for j := int16(0); j < bufferSize; j++ {
d.buffer[c][j] = 0
}
}
}

// Size returns the current size of the display.
func (d *Device) Size() (w, h int16) {
return d.width, d.height
}

// source code citation end position "tinygo.org/x/drivers/hub75" (rev.1bf1a11067968352afa5d7a489a13561effb2146)

type WeatherJSON struct {
Timezone string `json:"timezone"`
TimezoneOffset int `json:"timezone_offset"`
Expand Down Expand Up @@ -554,8 +294,8 @@ func main() {
bPin := machine.D4
cPin := machine.D5
dPin := machine.D6
h75 := New(spi, latPin, oePin, aPin, bPin, cPin, dPin)
h75_config := Config{
h75 := hub75.New(spi, latPin, oePin, aPin, bPin, cPin, dPin)
h75_config := hub75.Config{
Width: 64,
Height: 32,
}
Expand Down Expand Up @@ -656,7 +396,7 @@ func fetchData(sendCh chan<- WeatherInfoList) {
}
}

func putFont(h75 Device, vx, vy int, c color.RGBA, font [5][3]uint8) {
func putFont(h75 hub75.Device, vx, vy int, c color.RGBA, font [5][3]uint8) {
for y, lineData := range font {
for x, v := range lineData {
if v == 1 {
Expand All @@ -666,7 +406,7 @@ func putFont(h75 Device, vx, vy int, c color.RGBA, font [5][3]uint8) {
}
}

func putString(h75 Device, vx, vy int, c color.RGBA, str string) {
func putString(h75 hub75.Device, vx, vy int, c color.RGBA, str string) {
strSlice := strings.Split(str, "")
for _, s := range strSlice {
if s == ":" {
Expand All @@ -688,7 +428,7 @@ func putString(h75 Device, vx, vy int, c color.RGBA, str string) {

// API が返す icon の 数値を利用し 自作した icon を選択する
// https://openweathermap.org/weather-conditions#How-to-get-icon-URL
func putIcon(h75 Device, vx, vy int, weatherID string) {
func putIcon(h75 hub75.Device, vx, vy int, weatherID string) {
index := -1
switch weatherID[:2] {
case "01":
Expand Down

0 comments on commit 4ec0054

Please sign in to comment.