mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-19 14:14:00 +00:00
seesaw: added example and smoketest
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
"tinygo.org/x/drivers/seesaw"
|
||||||
|
)
|
||||||
|
|
||||||
|
const readDelay = time.Microsecond * 3000
|
||||||
|
|
||||||
|
// example reading soil moisture with an Adafruit capacitive soil-sensor (4026) powered by a seesaw
|
||||||
|
// https://learn.adafruit.com/adafruit-stemma-soil-sensor-i2c-capacitive-moisture-sensor/overview
|
||||||
|
func main() {
|
||||||
|
machine.I2C0.Configure(machine.I2CConfig{})
|
||||||
|
|
||||||
|
dev := seesaw.New(machine.I2C0)
|
||||||
|
|
||||||
|
dev.Address = 0x36
|
||||||
|
|
||||||
|
var buf [2]byte
|
||||||
|
err := dev.Read(seesaw.ModuleTouchBase, seesaw.FunctionTouchChannelOffset, buf[:], readDelay)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
moisture := uint16(buf[0])<<8 | uint16(buf[1])
|
||||||
|
|
||||||
|
println("soil moisture: " + strconv.Itoa(int(moisture)))
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Seesaw Driver
|
|
||||||
|
|
||||||
This is a basic driver to interact with Adafruit's seesaw board.
|
|
||||||
|
|
||||||
It exposes constants for the documented modules as well as their functions. Sub-packages
|
|
||||||
may contain more refined drivers based on those.
|
|
||||||
|
|
||||||
- [Device Overview](https://learn.adafruit.com/adafruit-seesaw-atsamd09-breakout/overview)
|
|
||||||
- [Adafruit Datasheet](https://cdn-learn.adafruit.com/downloads/pdf/adafruit-seesaw-atsamd09-breakout.pdf)
|
|
||||||
+12
-3
@@ -3,6 +3,7 @@ package seesaw
|
|||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,7 +18,9 @@ type mocki2c struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mocki2c) Tx(addr uint16, w, r []byte) error {
|
func (m *mocki2c) Tx(addr uint16, w, r []byte) error {
|
||||||
assertEquals(m.t, addr, m.addr)
|
if addr != m.addr {
|
||||||
|
m.t.Errorf("unexpected i2c address write, want: %v , got %v", m.addr, addr)
|
||||||
|
}
|
||||||
if len(m.handlers) == 0 {
|
if len(m.handlers) == 0 {
|
||||||
ws := hex.EncodeToString(w)
|
ws := hex.EncodeToString(w)
|
||||||
rs := hex.EncodeToString(r)
|
rs := hex.EncodeToString(r)
|
||||||
@@ -38,8 +41,14 @@ func newMockDev(t *testing.T, addr uint16, handlers ...I2CHandleFunc) *mocki2c {
|
|||||||
|
|
||||||
func when(expectedWrite, returningRead []byte, returningError error) I2CHandleFunc {
|
func when(expectedWrite, returningRead []byte, returningError error) I2CHandleFunc {
|
||||||
return func(t *testing.T, w, r []byte) error {
|
return func(t *testing.T, w, r []byte) error {
|
||||||
assertEquals(t, w, expectedWrite)
|
if !reflect.DeepEqual(w, expectedWrite) {
|
||||||
assertEquals(t, len(r), len(returningRead))
|
t.Errorf("unexpected write. want: %v, got: %v", expectedWrite, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(r) != len(returningRead) {
|
||||||
|
t.Errorf("read buffer has wrong size. want: %v, got: %v", len(returningRead), len(r))
|
||||||
|
}
|
||||||
|
|
||||||
if r != nil {
|
if r != nil {
|
||||||
copy(r, returningRead)
|
copy(r, returningRead)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
// Package seesaw provides a driver for the "i2c to whathever interface" called seesaw
|
|
||||||
// documentation: https://learn.adafruit.com/adafruit-seesaw-atsamd09-breakout/overview
|
|
||||||
package seesaw
|
package seesaw
|
||||||
|
|
||||||
type ModuleBaseAddress byte
|
type ModuleBaseAddress byte
|
||||||
|
|||||||
+11
-15
@@ -1,14 +1,21 @@
|
|||||||
// Package seesaw provides a driver implementation to communicate with Adafruit's seesaw chip.
|
// Package seesaw provides a driver implementation to communicate with Adafruit's seesaw chip.
|
||||||
// There are many Adafruit boards that use a seesaw. Moisture sensors, LED keyboards, ...
|
// There are many Adafruit boards that use a seesaw. Soil moisture sensors, LED keyboards, etc.
|
||||||
|
//
|
||||||
|
// - Documentation: https://learn.adafruit.com/adafruit-seesaw-atsamd09-breakout/overview
|
||||||
|
// - Arduino driver: https://github.com/adafruit/Adafruit_Seesaw
|
||||||
|
// - Seesaw firmware: https://github.com/adafruit/seesaw
|
||||||
package seesaw
|
package seesaw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"tinygo.org/x/drivers"
|
"tinygo.org/x/drivers"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DefaultAddress is the I2C address the chips have by default. Most boards
|
||||||
|
// built on top of it come with their own respective default addresses.
|
||||||
const DefaultAddress = 0x49
|
const DefaultAddress = 0x49
|
||||||
|
|
||||||
// empirically determined standardDelay, the one from the official library seems to be too short (250us)
|
// empirically determined standardDelay, the one from the official library seems to be too short (250us)
|
||||||
@@ -19,16 +26,6 @@ const (
|
|||||||
seesawHwIdCodeTINY8x7 = 0x87 // HW ID code for ATtiny817
|
seesawHwIdCodeTINY8x7 = 0x87 // HW ID code for ATtiny817
|
||||||
)
|
)
|
||||||
|
|
||||||
type Seesaw interface {
|
|
||||||
|
|
||||||
// Read reads a number of bytes from the device after sending the read command and waiting 'delay'. The delays depend
|
|
||||||
// on the module and function and are documented in the seesaw datasheet
|
|
||||||
Read(module ModuleBaseAddress, function FunctionAddress, buf []byte, delay time.Duration) error
|
|
||||||
|
|
||||||
// Write writes an entire array into a given module and function
|
|
||||||
Write(module ModuleBaseAddress, function FunctionAddress, buf []byte) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type Device struct {
|
type Device struct {
|
||||||
bus drivers.I2C
|
bus drivers.I2C
|
||||||
Address uint16
|
Address uint16
|
||||||
@@ -54,8 +51,7 @@ func (d *Device) SoftReset() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Device) waitForReset() error {
|
func (d *Device) waitForReset() error {
|
||||||
|
// give the device a little bit of time to reset
|
||||||
//give the device a little bit of time to reset
|
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
var lastErr error
|
var lastErr error
|
||||||
@@ -115,8 +111,8 @@ func (d *Device) Read(module ModuleBaseAddress, function FunctionAddress, buf []
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//This is needed for the client seesaw device to flush its RX buffer and process the command.
|
// This is needed for the client seesaw device to flush its RX buffer and process the command.
|
||||||
//See seesaw datasheet for timings for specific modules.
|
// See seesaw datasheet for timings for specific modules.
|
||||||
time.Sleep(delay)
|
time.Sleep(delay)
|
||||||
|
|
||||||
return d.bus.Tx(d.Address, nil, buf)
|
return d.bus.Tx(d.Address, nil, buf)
|
||||||
|
|||||||
+15
-19
@@ -1,13 +1,13 @@
|
|||||||
package seesaw
|
package seesaw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/frankban/quicktest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDevice_SoftReset_success(t *testing.T) {
|
func TestDevice_SoftReset_success(t *testing.T) {
|
||||||
|
|
||||||
mocked := newMockDev(t, 0x49,
|
mocked := newMockDev(t, 0x49,
|
||||||
when([]byte{0x00, 0x7F, 0xFF}, nil, nil),
|
when([]byte{0x00, 0x7F, 0xFF}, nil, nil),
|
||||||
when([]byte{0x00, 0x01}, nil, nil),
|
when([]byte{0x00, 0x01}, nil, nil),
|
||||||
@@ -17,11 +17,11 @@ func TestDevice_SoftReset_success(t *testing.T) {
|
|||||||
sut := New(mocked)
|
sut := New(mocked)
|
||||||
|
|
||||||
err := sut.SoftReset()
|
err := sut.SoftReset()
|
||||||
assertEquals(t, err, nil)
|
qt := quicktest.New(t)
|
||||||
|
qt.Assert(err, quicktest.IsNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDevice_WriteRegister(t *testing.T) {
|
func TestDevice_WriteRegister(t *testing.T) {
|
||||||
|
|
||||||
write := byte(0x1F)
|
write := byte(0x1F)
|
||||||
mocked := newMockDev(t, 0x49,
|
mocked := newMockDev(t, 0x49,
|
||||||
when([]byte{0x01, 0x04, write}, nil, nil),
|
when([]byte{0x01, 0x04, write}, nil, nil),
|
||||||
@@ -30,11 +30,11 @@ func TestDevice_WriteRegister(t *testing.T) {
|
|||||||
sut := New(mocked)
|
sut := New(mocked)
|
||||||
|
|
||||||
err := sut.WriteRegister(ModuleGpioBase, FunctionGpioBulk, write)
|
err := sut.WriteRegister(ModuleGpioBase, FunctionGpioBulk, write)
|
||||||
assertEquals(t, err, nil)
|
qt := quicktest.New(t)
|
||||||
|
qt.Assert(err, quicktest.IsNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDevice_ReadRegister(t *testing.T) {
|
func TestDevice_ReadRegister(t *testing.T) {
|
||||||
|
|
||||||
read := byte(0x23)
|
read := byte(0x23)
|
||||||
mocked := newMockDev(t, 0x49,
|
mocked := newMockDev(t, 0x49,
|
||||||
when([]byte{0x0F, 0x10}, nil, nil),
|
when([]byte{0x0F, 0x10}, nil, nil),
|
||||||
@@ -44,12 +44,12 @@ func TestDevice_ReadRegister(t *testing.T) {
|
|||||||
sut := New(mocked)
|
sut := New(mocked)
|
||||||
|
|
||||||
r, err := sut.ReadRegister(ModuleTouchBase, FunctionTouchChannelOffset)
|
r, err := sut.ReadRegister(ModuleTouchBase, FunctionTouchChannelOffset)
|
||||||
assertEquals(t, err, nil)
|
qt := quicktest.New(t)
|
||||||
assertEquals(t, r, read)
|
qt.Assert(err, quicktest.IsNil)
|
||||||
|
qt.Assert(r, quicktest.Equals, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDevice_Read(t *testing.T) {
|
func TestDevice_Read(t *testing.T) {
|
||||||
|
|
||||||
expectedRead := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
|
expectedRead := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
|
||||||
mocked := newMockDev(t, 0x49,
|
mocked := newMockDev(t, 0x49,
|
||||||
when([]byte{0x0F, 0x10}, nil, nil),
|
when([]byte{0x0F, 0x10}, nil, nil),
|
||||||
@@ -60,12 +60,13 @@ func TestDevice_Read(t *testing.T) {
|
|||||||
|
|
||||||
var buf [5]byte
|
var buf [5]byte
|
||||||
err := sut.Read(ModuleTouchBase, FunctionTouchChannelOffset, buf[:], time.Nanosecond)
|
err := sut.Read(ModuleTouchBase, FunctionTouchChannelOffset, buf[:], time.Nanosecond)
|
||||||
assertEquals(t, err, nil)
|
|
||||||
assertEquals(t, buf[:], expectedRead)
|
qt := quicktest.New(t)
|
||||||
|
qt.Assert(err, quicktest.IsNil)
|
||||||
|
qt.Assert(buf[:], quicktest.DeepEquals, expectedRead)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDevice_Write(t *testing.T) {
|
func TestDevice_Write(t *testing.T) {
|
||||||
|
|
||||||
expectedWrite := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
|
expectedWrite := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
|
||||||
mocked := newMockDev(t, 0x49,
|
mocked := newMockDev(t, 0x49,
|
||||||
when(append([]byte{0x0E, 0x04}, expectedWrite...), nil, nil),
|
when(append([]byte{0x0E, 0x04}, expectedWrite...), nil, nil),
|
||||||
@@ -74,11 +75,6 @@ func TestDevice_Write(t *testing.T) {
|
|||||||
sut := New(mocked)
|
sut := New(mocked)
|
||||||
|
|
||||||
err := sut.Write(ModuleNeoPixelBase, FunctionNeopixelBuf, expectedWrite)
|
err := sut.Write(ModuleNeoPixelBase, FunctionNeopixelBuf, expectedWrite)
|
||||||
assertEquals(t, err, nil)
|
qt := quicktest.New(t)
|
||||||
}
|
qt.Assert(err, quicktest.IsNil)
|
||||||
|
|
||||||
func assertEquals[e any](t *testing.T, actual, expected e) {
|
|
||||||
if !reflect.DeepEqual(actual, expected) {
|
|
||||||
t.Fatalf("actual %+v != %+v not equals expected", actual, expected)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ tinygo build -size short -o ./build/test.hex -target=p1am-100 ./examples/p1am/ma
|
|||||||
tinygo build -size short -o ./build/test.hex -target=pico ./examples/pca9685/main.go
|
tinygo build -size short -o ./build/test.hex -target=pico ./examples/pca9685/main.go
|
||||||
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go
|
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go
|
||||||
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go
|
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go
|
||||||
|
tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/seesaw
|
||||||
tinygo build -size short -o ./build/test.hex -target=arduino ./examples/servo
|
tinygo build -size short -o ./build/test.hex -target=arduino ./examples/servo
|
||||||
tinygo build -size short -o ./build/test.hex -target=pico ./examples/sgp30
|
tinygo build -size short -o ./build/test.hex -target=pico ./examples/sgp30
|
||||||
tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/shifter/main.go
|
tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/shifter/main.go
|
||||||
|
|||||||
Reference in New Issue
Block a user