mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-05 15:33:42 +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 (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -17,7 +18,9 @@ type mocki2c struct {
|
||||
}
|
||||
|
||||
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 {
|
||||
ws := hex.EncodeToString(w)
|
||||
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 {
|
||||
return func(t *testing.T, w, r []byte) error {
|
||||
assertEquals(t, w, expectedWrite)
|
||||
assertEquals(t, len(r), len(returningRead))
|
||||
if !reflect.DeepEqual(w, expectedWrite) {
|
||||
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 {
|
||||
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
|
||||
|
||||
type ModuleBaseAddress byte
|
||||
|
||||
+11
-15
@@ -1,14 +1,21 @@
|
||||
// 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
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"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
|
||||
|
||||
// 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
|
||||
)
|
||||
|
||||
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 {
|
||||
bus drivers.I2C
|
||||
Address uint16
|
||||
@@ -54,8 +51,7 @@ func (d *Device) SoftReset() 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)
|
||||
|
||||
var lastErr error
|
||||
@@ -115,8 +111,8 @@ func (d *Device) Read(module ModuleBaseAddress, function FunctionAddress, buf []
|
||||
return err
|
||||
}
|
||||
|
||||
//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.
|
||||
// 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.
|
||||
time.Sleep(delay)
|
||||
|
||||
return d.bus.Tx(d.Address, nil, buf)
|
||||
|
||||
+15
-19
@@ -1,13 +1,13 @@
|
||||
package seesaw
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func TestDevice_SoftReset_success(t *testing.T) {
|
||||
|
||||
mocked := newMockDev(t, 0x49,
|
||||
when([]byte{0x00, 0x7F, 0xFF}, nil, nil),
|
||||
when([]byte{0x00, 0x01}, nil, nil),
|
||||
@@ -17,11 +17,11 @@ func TestDevice_SoftReset_success(t *testing.T) {
|
||||
sut := New(mocked)
|
||||
|
||||
err := sut.SoftReset()
|
||||
assertEquals(t, err, nil)
|
||||
qt := quicktest.New(t)
|
||||
qt.Assert(err, quicktest.IsNil)
|
||||
}
|
||||
|
||||
func TestDevice_WriteRegister(t *testing.T) {
|
||||
|
||||
write := byte(0x1F)
|
||||
mocked := newMockDev(t, 0x49,
|
||||
when([]byte{0x01, 0x04, write}, nil, nil),
|
||||
@@ -30,11 +30,11 @@ func TestDevice_WriteRegister(t *testing.T) {
|
||||
sut := New(mocked)
|
||||
|
||||
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) {
|
||||
|
||||
read := byte(0x23)
|
||||
mocked := newMockDev(t, 0x49,
|
||||
when([]byte{0x0F, 0x10}, nil, nil),
|
||||
@@ -44,12 +44,12 @@ func TestDevice_ReadRegister(t *testing.T) {
|
||||
sut := New(mocked)
|
||||
|
||||
r, err := sut.ReadRegister(ModuleTouchBase, FunctionTouchChannelOffset)
|
||||
assertEquals(t, err, nil)
|
||||
assertEquals(t, r, read)
|
||||
qt := quicktest.New(t)
|
||||
qt.Assert(err, quicktest.IsNil)
|
||||
qt.Assert(r, quicktest.Equals, r)
|
||||
}
|
||||
|
||||
func TestDevice_Read(t *testing.T) {
|
||||
|
||||
expectedRead := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
|
||||
mocked := newMockDev(t, 0x49,
|
||||
when([]byte{0x0F, 0x10}, nil, nil),
|
||||
@@ -60,12 +60,13 @@ func TestDevice_Read(t *testing.T) {
|
||||
|
||||
var buf [5]byte
|
||||
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) {
|
||||
|
||||
expectedWrite := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
|
||||
mocked := newMockDev(t, 0x49,
|
||||
when(append([]byte{0x0E, 0x04}, expectedWrite...), nil, nil),
|
||||
@@ -74,11 +75,6 @@ func TestDevice_Write(t *testing.T) {
|
||||
sut := New(mocked)
|
||||
|
||||
err := sut.Write(ModuleNeoPixelBase, FunctionNeopixelBuf, expectedWrite)
|
||||
assertEquals(t, err, nil)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
qt := quicktest.New(t)
|
||||
qt.Assert(err, quicktest.IsNil)
|
||||
}
|
||||
|
||||
@@ -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=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=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=pico ./examples/sgp30
|
||||
tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/shifter/main.go
|
||||
|
||||
Reference in New Issue
Block a user