Skip to content

Commit 308763f

Browse files
bgoulddeadprogram
authored andcommitted
Adding driver for rotary encoder support
1 parent c41f2e4 commit 308763f

File tree

5 files changed

+133
-1
lines changed

5 files changed

+133
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![PkgGoDev](https://pkg.go.dev/badge/tinygo.org/x/drivers)](https://pkg.go.dev/tinygo.org/x/drivers) [![Build](https://github.com/tinygo-org/drivers/actions/workflows/build.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/drivers/actions/workflows/build.yml)
44

55

6-
This package provides a collection of 101 different hardware drivers for devices such as sensors and displays that can be used together with [TinyGo](https://tinygo.org).
6+
This package provides a collection of 102 different hardware drivers for devices such as sensors and displays that can be used together with [TinyGo](https://tinygo.org).
77

88
For the complete list, please see:
99
https://tinygo.org/docs/reference/devices/

encoders/quadrature_device.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package encoders
2+
3+
type QuadratureDevice struct {
4+
cfg QuadratureConfig
5+
impl quadratureImpl
6+
}
7+
8+
type QuadratureConfig struct {
9+
Precision int
10+
}
11+
12+
type quadratureImpl interface {
13+
configure(cfg QuadratureConfig) error
14+
readValue() int
15+
writeValue(int)
16+
}
17+
18+
func (enc *QuadratureDevice) Configure(cfg QuadratureConfig) error {
19+
if cfg.Precision < 1 {
20+
cfg.Precision = 4
21+
}
22+
enc.cfg = cfg
23+
return enc.impl.configure(cfg)
24+
}
25+
26+
// Position returns the stored int value for the encoder
27+
func (enc *QuadratureDevice) Position() int {
28+
return enc.impl.readValue() / enc.cfg.Precision
29+
}
30+
31+
// SetPosition overwrites the currently stored value with the specified int value
32+
func (enc *QuadratureDevice) SetPosition(v int) {
33+
enc.impl.writeValue(v * enc.cfg.Precision)
34+
}

encoders/quadrature_interrupt.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//go:build tinygo && (rp2040 || stm32 || k210 || esp32c3 || nrf || (avr && (atmega328p || atmega328pb)))
2+
3+
// Implementation based on:
4+
// https://gist.github.com/aykevl/3fc1683ed77bb0a9c07559dfe857304a
5+
6+
// Note: build constraints in this file list targets that define machine.PinToggle.
7+
// If this is supported for additional targets in the future, they can be added above.
8+
9+
package encoders
10+
11+
import (
12+
"machine"
13+
"runtime/volatile"
14+
)
15+
16+
var (
17+
states = []int8{0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0}
18+
)
19+
20+
// NewQuadratureViaInterrupt returns a rotary encoder device that uses GPIO
21+
// interrupts and a lookup table to keep track of quadrature state changes.
22+
//
23+
// This constructur is only available for TinyGo targets for which machine.PinToggle
24+
// is defined as a valid interrupt type.
25+
func NewQuadratureViaInterrupt(pinA, pinB machine.Pin) *QuadratureDevice {
26+
return &QuadratureDevice{impl: &quadInterruptImpl{pinA: pinA, pinB: pinB, oldAB: 0b00000011}}
27+
}
28+
29+
type quadInterruptImpl struct {
30+
pinA machine.Pin
31+
pinB machine.Pin
32+
33+
// precision int
34+
35+
oldAB int
36+
value volatile.Register32
37+
}
38+
39+
func (enc *quadInterruptImpl) configure(cfg QuadratureConfig) error {
40+
enc.pinA.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
41+
enc.pinA.SetInterrupt(machine.PinToggle, enc.interrupt)
42+
43+
enc.pinB.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
44+
enc.pinB.SetInterrupt(machine.PinToggle, enc.interrupt)
45+
46+
return nil
47+
}
48+
49+
func (enc *quadInterruptImpl) interrupt(pin machine.Pin) {
50+
aHigh, bHigh := enc.pinA.Get(), enc.pinB.Get()
51+
enc.oldAB <<= 2
52+
if aHigh {
53+
enc.oldAB |= 1 << 1
54+
}
55+
if bHigh {
56+
enc.oldAB |= 1
57+
}
58+
enc.writeValue(enc.readValue() + int(states[enc.oldAB&0x0f]))
59+
}
60+
61+
// readValue gets the value using volatile operations and returns it as an int
62+
func (enc *quadInterruptImpl) readValue() int {
63+
return int(enc.value.Get())
64+
}
65+
66+
// writeValue set the value to the specified int using volatile operations
67+
func (enc *quadInterruptImpl) writeValue(v int) {
68+
enc.value.Set(uint32(v))
69+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//go:build macropad_rp2040
2+
3+
package main
4+
5+
import (
6+
"machine"
7+
8+
"tinygo.org/x/drivers/encoders"
9+
)
10+
11+
var (
12+
enc = encoders.NewQuadratureViaInterrupt(machine.ROT_A, machine.ROT_B)
13+
)
14+
15+
func main() {
16+
17+
enc.Configure(encoders.QuadratureConfig{
18+
Precision: 4,
19+
})
20+
21+
for oldValue := 0; ; {
22+
if newValue := enc.Position(); newValue != oldValue {
23+
println("value: ", newValue)
24+
oldValue = newValue
25+
}
26+
}
27+
28+
}

smoketest.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ndir/ma
129129
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ndir/main_ndir.go
130130
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mpu9150/main.go
131131
tinygo build -size short -o ./build/test.hex -target=macropad-rp2040 ./examples/sh1106/macropad_spi
132+
tinygo build -size short -o ./build/test.hex -target=macropad-rp2040 ./examples/encoders/quadrature-interrupt
132133
# network examples (espat)
133134
tinygo build -size short -o ./build/test.hex -target=challenger-rp2040 ./examples/net/ntpclient/
134135
# network examples (wifinina)

0 commit comments

Comments
 (0)