Skip to content

Commit 857ab80

Browse files
jphastingsdeadprogram
authored andcommitted
feat: add support for seesaw encoders
Adds the necessary function addresses for reading and writing encoders on a seesaw. Also provides two helper functions to make this easier.
1 parent a31ba26 commit 857ab80

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package main
2+
3+
import (
4+
"machine"
5+
"time"
6+
7+
"tinygo.org/x/drivers/seesaw"
8+
)
9+
10+
// example reading the position of a rotary encoder (4991) powered by a seesaw
11+
// https://learn.adafruit.com/adafruit-i2c-qt-rotary-encoder/arduino
12+
func main() {
13+
// This assumes you are using an Adafruit QT Py RP2040 for its Stemma QT connector
14+
// https://www.adafruit.com/product/4900
15+
i2c := machine.I2C1
16+
i2c.Configure(machine.I2CConfig{
17+
SCL: machine.I2C1_QT_SCL_PIN,
18+
SDA: machine.I2C1_QT_SDA_PIN,
19+
})
20+
21+
dev := seesaw.New(i2c)
22+
dev.Address = 0x36
23+
24+
for {
25+
time.Sleep(time.Second)
26+
27+
pos, err := dev.GetEncoderPosition(0, false)
28+
if err != nil {
29+
println(err)
30+
continue
31+
}
32+
33+
println(pos)
34+
}
35+
}
File renamed without changes.

seesaw/encoder.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package seesaw
2+
3+
import (
4+
"errors"
5+
)
6+
7+
var errInvalidEncoderNumber = errors.New("invalid encoder choice, 0-15 are supported")
8+
9+
// GetEncoderPosition returns the absolute position (or delta since the previous call) of the specified rotary encoder.
10+
func (d *Device) GetEncoderPosition(encoder uint, asDelta bool) (int32, error) {
11+
if encoder >= 16 {
12+
return 0, errInvalidEncoderNumber
13+
}
14+
15+
// The function address' upper nibble is the function, the lower nibble selects which encoder to communicate with
16+
fnAddr := FunctionAddress(encoder)
17+
if asDelta {
18+
fnAddr |= FunctionEncoderDelta
19+
} else {
20+
fnAddr |= FunctionEncoderPosition
21+
}
22+
23+
var buf [4]byte
24+
err := d.Read(ModuleEncoderBase, fnAddr, buf[:])
25+
if err != nil {
26+
return 0, err
27+
}
28+
29+
return int32(buf[0])<<24 | int32(buf[1])<<16 | int32(buf[2])<<8 | int32(buf[3]), nil
30+
}
31+
32+
// SetEncoderPosition calibrate's the encoder's current absolute position to be whatever the provided position is.
33+
func (d *Device) SetEncoderPosition(encoder uint, position int32) error {
34+
if encoder >= 16 {
35+
return errInvalidEncoderNumber
36+
}
37+
38+
// The function address' upper nibble is the function, the lower nibble selects which encoder to communicate with
39+
fnAddr := FunctionEncoderPosition | FunctionAddress(encoder)
40+
41+
buf := [4]byte{
42+
byte(position >> 24),
43+
byte(position >> 16),
44+
byte(position >> 8),
45+
byte(position),
46+
}
47+
48+
return d.Write(ModuleEncoderBase, fnAddr, buf[:])
49+
}

seesaw/registers.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,13 @@ const (
9898
FunctionKeypadCount FunctionAddress = 0x04
9999
FunctionKeypadFifo FunctionAddress = 0x10
100100
)
101+
102+
// encoder module function address registers
103+
// these are the defaults for encoder 0, change the lower nibble to address other encoders
104+
// see the Device.GetEncoderPosition and SetEncoderPosition methods for examples.
105+
const (
106+
FunctionEncoderIntenset FunctionAddress = 0x10
107+
FunctionEncoderIntenclr FunctionAddress = 0x20
108+
FunctionEncoderPosition FunctionAddress = 0x30
109+
FunctionEncoderDelta FunctionAddress = 0x40
110+
)

0 commit comments

Comments
 (0)