Skip to content

Commit b990fc8

Browse files
committed
rpio: basic impl of Pins and SPI interfaces for Raspberry Pi
1 parent 2a42fa7 commit b990fc8

5 files changed

Lines changed: 164 additions & 0 deletions

File tree

examples/rpio/main.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package main
2+
3+
// Example program for the ST7735 display (Waveshare 1.44" LCD HAT) using the rpio driver on a Raspberry Pi.
4+
// Build command:
5+
// GOOS=linux GOARCH=arm64 go build -o rpio-example ./examples/rpio/
6+
7+
import (
8+
"fmt"
9+
"image/color"
10+
"time"
11+
12+
go_rpio "github.com/stianeikeland/go-rpio/v4"
13+
"tinygo.org/x/drivers"
14+
"tinygo.org/x/drivers/rpio"
15+
"tinygo.org/x/drivers/st7735"
16+
)
17+
18+
var (
19+
black = color.RGBA{0, 0, 0, 255}
20+
colors = [...]color.RGBA{
21+
{255, 0, 0, 255}, // red
22+
{0, 255, 0, 255}, // green
23+
{0, 0, 255, 255}, // blue
24+
{255, 255, 0, 255}, // yellow
25+
}
26+
)
27+
28+
func main() {
29+
if err := go_rpio.Open(); err != nil {
30+
fmt.Println("Error opening GPIO:", err)
31+
return
32+
}
33+
defer go_rpio.Close()
34+
35+
// Initialize SPI and pins
36+
spi := rpio.NewSPI()
37+
resetPin := rpio.NewPin(27)
38+
dcPin := rpio.NewPin(25)
39+
csPin := rpio.NewPin(8)
40+
blPin := rpio.NewPin(24)
41+
42+
rotatePin := rpio.NewPin(20) // middle button on the HAT
43+
rotatePin.Pin.PullUp() // enable pull-up resistor, our wrapper sets only input mode automatically
44+
45+
// Initialize display
46+
device := st7735.New(spi, resetPin, dcPin, csPin, blPin)
47+
device.Configure(st7735.Config{
48+
Width: 128,
49+
Height: 128,
50+
Model: st7735.GREENTAB,
51+
RowOffset: 3,
52+
ColumnOffset: 2,
53+
})
54+
device.InvertColors(false)
55+
device.EnableBacklight(true)
56+
device.IsBGR(true) // no effect w/o rotation!
57+
device.SetRotation(st7735.NO_ROTATION)
58+
59+
width, height := device.Size()
60+
61+
// Clear display
62+
device.FillScreen(black)
63+
64+
// Draw rectangles in a loop, clockwise rotation of colors
65+
pos := 0
66+
for {
67+
device.FillRectangle(0, 0, width/2, height/2, colors[(pos+0)%len(colors)]) // top left
68+
device.FillRectangle(0, height/2, width/2, height/2, colors[(pos+1)%len(colors)]) // bottom left
69+
device.FillRectangle(width/2, height/2, width/2, height/2, colors[(pos+2)%len(colors)]) // bottom right
70+
device.FillRectangle(width/2, 0, width/2, height/2, colors[(pos+3)%len(colors)]) // top right
71+
device.FillRectangle(0, 0, 10, 10, black) // rotation marker
72+
pos++
73+
74+
timeout := time.Now().Add(1 * time.Second)
75+
for time.Now().Before(timeout) {
76+
// check button pressed
77+
if !rotatePin.Get() {
78+
currentRotation := device.Rotation()
79+
newRotation := (currentRotation + 1) % 4
80+
device.SetRotation(drivers.Rotation(newRotation))
81+
// wait for button release
82+
for !rotatePin.Get() {
83+
time.Sleep(10 * time.Millisecond)
84+
}
85+
break
86+
}
87+
time.Sleep(50 * time.Millisecond)
88+
}
89+
90+
}
91+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
1313
github.com/orsinium-labs/tinymath v1.1.0
1414
github.com/soypat/natiu-mqtt v0.5.1
15+
github.com/stianeikeland/go-rpio/v4 v4.6.0
1516
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d
1617
golang.org/x/net v0.33.0
1718
tinygo.org/x/tinyfont v0.3.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ github.com/orsinium-labs/tinymath v1.1.0 h1:KomdsyLHB7vE3f1nRAJF2dyf1m/gnM2HxfTe
1717
github.com/orsinium-labs/tinymath v1.1.0/go.mod h1:WPXX6ei3KSXG7JfA03a+ekCYaY9SWN4I+JRl2p6ck+A=
1818
github.com/soypat/natiu-mqtt v0.5.1 h1:rwaDmlvjzD2+3MCOjMZc4QEkDkNwDzbct2TJbpz+TPc=
1919
github.com/soypat/natiu-mqtt v0.5.1/go.mod h1:xEta+cwop9izVCW7xOx2W+ct9PRMqr0gNVkvBPnQTc4=
20+
github.com/stianeikeland/go-rpio/v4 v4.6.0 h1:eAJgtw3jTtvn/CqwbC82ntcS+dtzUTgo5qlZKe677EY=
21+
github.com/stianeikeland/go-rpio/v4 v4.6.0/go.mod h1:A3GvHxC1Om5zaId+HqB3HKqx4K/AqeckxB7qRjxMK7o=
2022
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
2123
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0=
2224
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=

rpio/pin.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Implements internal.pin.[Input,Output] interfaces for the Raspberry Pi GPIO pins.
2+
// Depends on the go-rpio library.
3+
// Configures pin modes automatically when Get or Set methods are called.
4+
5+
package rpio // import "tinygo.org/x/drivers/rpio"
6+
7+
import go_rpio "github.com/stianeikeland/go-rpio/v4"
8+
9+
type Pin struct {
10+
modeSet bool
11+
Mode go_rpio.Mode
12+
Pin go_rpio.Pin
13+
}
14+
15+
func NewPin(pinNumber int) *Pin {
16+
return &Pin{Pin: go_rpio.Pin(pinNumber)}
17+
}
18+
19+
func (p *Pin) Get() bool {
20+
if !p.modeSet || p.Mode != go_rpio.Input {
21+
p.Pin.Input()
22+
p.Mode = go_rpio.Input
23+
}
24+
return p.Pin.Read() == go_rpio.High
25+
}
26+
27+
func (p *Pin) Set(high bool) {
28+
if !p.modeSet || p.Mode != go_rpio.Output {
29+
p.Pin.Output()
30+
p.Mode = go_rpio.Output
31+
}
32+
state := go_rpio.Low
33+
if high {
34+
state = go_rpio.High
35+
}
36+
p.Pin.Write(state)
37+
}

rpio/spi.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Implemenmts drivers.SPI interface for the Raspberry Pi.
2+
// Depends on the go-rpio library.
3+
4+
package rpio // import "tinygo.org/x/drivers/rpio"
5+
6+
import go_rpio "github.com/stianeikeland/go-rpio/v4"
7+
8+
type SPI struct {
9+
}
10+
11+
func NewSPI() (s *SPI) {
12+
if err := go_rpio.SpiBegin(go_rpio.Spi0); err != nil {
13+
panic(err)
14+
}
15+
go_rpio.SpiSpeed(25_000_000) // 25 MHz
16+
go_rpio.SpiChipSelect(0)
17+
return &SPI{}
18+
}
19+
20+
func (s *SPI) Tx(w, r []byte) error {
21+
data := make([]byte, len(w))
22+
copy(data, w)
23+
go_rpio.SpiExchange(data)
24+
copy(r, data)
25+
return nil
26+
}
27+
28+
func (s *SPI) Transfer(b byte) (byte, error) {
29+
w := []byte{b}
30+
r := make([]byte, len(w))
31+
err := s.Tx(w, r)
32+
return r[0], err
33+
}

0 commit comments

Comments
 (0)