diff --git a/examples/ttp229/main.go b/examples/ttp229/main.go new file mode 100644 index 0000000..066699e --- /dev/null +++ b/examples/ttp229/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "time" + + "tinygo.org/x/drivers/ttp229" + + "machine" +) + +func main() { + time.Sleep(5 * time.Second) + sensor := ttp229.NewPin(machine.A5, machine.A4) + sensor.Configure(ttp229.Configuration{Inputs: 16}) + + println("READY") + for { + sensor.ReadKeys() + for i := byte(0); i < 16; i++ { + if sensor.IsKeyPressed(i) { + print("1 ") + } else { + print("0 ") + } + } + println("") + + println("Pressed key:", sensor.GetKey()) + + for i := byte(0); i < 16; i++ { + if sensor.IsKeyDown(i) { + println("Key", i, "is down") + } else if sensor.IsKeyUp(i) { + println("Key", i, "is up") + } + } + + time.Sleep(100 * time.Millisecond) + } +} diff --git a/smoketest.sh b/smoketest.sh index e7064a6..38bfed6 100755 --- a/smoketest.sh +++ b/smoketest.sh @@ -126,3 +126,4 @@ tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/d tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/lora/lorawan/atcmd/ tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/as560x/main.go tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mpu6886/main.go +tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ttp229/main.go \ No newline at end of file diff --git a/ttp229/ttp229.go b/ttp229/ttp229.go new file mode 100644 index 0000000..246d249 --- /dev/null +++ b/ttp229/ttp229.go @@ -0,0 +1,109 @@ +// Package ttp229 is for the 16 keys or 8 keys touch pad detector IC +// Datasheet (BSF version): https://www.sunrom.com/download/SUNROM-TTP229-BSF_V1.1_EN.pdf +package ttp229 // import "tinygo.org/x/drivers/ttp229" + +import ( + "time" + + "machine" +) + +// Device wraps a connection to a TTP229 device. +type Device struct { + bus Buser + keys uint16 + prevKeys uint16 + inputs byte +} + +// PinBus holds the structure for GPIO protocol +type PinBus struct { + scl machine.Pin + sdo machine.Pin +} + +// Buser interface since there are different versions with different protocols +type Buser interface { + readBits(data byte) uint16 +} + +// Configuration +type Configuration struct { + Inputs byte +} + +// NewPin creates a new TTP229 connection through 2 machine.Pin, this is suitable for the BSF variant of the TTP229. +func NewPin(scl, sdo machine.Pin) Device { + scl.Configure(machine.PinConfig{Mode: machine.PinOutput}) + sdo.Configure(machine.PinConfig{Mode: machine.PinInput}) + return Device{ + bus: &PinBus{ + scl: scl, + sdo: sdo, + }, + inputs: 16, + } +} + +// Configure sets up the device for communication +func (d *Device) Configure(cfg Configuration) bool { + if cfg.Inputs != 0 { + d.inputs = cfg.Inputs + } + return true +} + +// ReadKeys returns the pressed keys as bits of a uint16 +func (d *Device) ReadKeys() uint16 { + d.prevKeys = d.keys + d.keys = d.bus.readBits(d.inputs) + return d.keys +} + +// bitRead return if the specific bit is on/off of the given uint16 +func (d *Device) bitRead(number uint16, bit byte) bool { + return (number & (0x0001 << bit)) != 0 +} + +// GetKey returns the current pressed key (only returns one key, even in multitouch mode) +func (d *Device) GetKey() int8 { + for i := byte(0); i < d.inputs; i++ { + if !d.bitRead(d.keys, byte(i)) { + return int8(i) + } + } + return -1 +} + +// IsKeyPressed returns true if the given key is pressed +func (d *Device) IsKeyPressed(key byte) bool { + return !d.bitRead(d.keys, key) +} + +// IsKeyDown returns true if the given key was just pressed (and it wasn't previously) +func (d *Device) IsKeyDown(key byte) bool { + return d.bitRead(d.prevKeys, key) && !d.bitRead(d.keys, key) +} + +// IsKeyUp returns true if the given key was released +func (d *Device) IsKeyUp(key byte) bool { + return !d.bitRead(d.prevKeys, key) && d.bitRead(d.keys, key) +} + +// readBits returns the pressed keys as bits of a uint16 +func (b *PinBus) readBits(inputs byte) uint16 { + b.scl.High() + time.Sleep(1 * time.Millisecond) + var pressed uint16 + for i := byte(0); i < inputs; i++ { + b.scl.Low() + time.Sleep(1 * time.Millisecond) + if b.sdo.Get() { + pressed = pressed | (0x0001 << i) + } + b.scl.High() + time.Sleep(1 * time.Millisecond) + } + time.Sleep(1 * time.Millisecond) + return pressed +}