mirror of https://github.com/periph/devices
cap1188 experimental device (#192)
This driver was tested against a adafruit version of the cap1188 https://learn.adafruit.com/adafruit-cap1188-breakout/overview and the pimoroni drumhat: https://shop.pimoroni.com/collections/raspberry-pi/products/drum-hat (which has its LED reversed and uses a different i2c address).pull/1/head
parent
11522179a3
commit
68f531c751
@ -0,0 +1,144 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package cap1188
|
||||
|
||||
import "periph.io/x/periph/conn/gpio"
|
||||
|
||||
// SamplingTime determines the time to take a single sample
|
||||
type SamplingTime uint8
|
||||
|
||||
// Possible sampling time values (written as 2 bits)
|
||||
const (
|
||||
S320us SamplingTime = 0
|
||||
S640us SamplingTime = 1
|
||||
// S1_28ms represents 1.28ms sampling time, which is the default.
|
||||
S1_28ms SamplingTime = 2 // default
|
||||
S2_56ms SamplingTime = 3
|
||||
)
|
||||
|
||||
// AvgSampling set the number of samples per measurement that get
|
||||
// averaged
|
||||
type AvgSampling uint8
|
||||
|
||||
// possible average sampling values. (written as 3 bits)
|
||||
const (
|
||||
// Avg1 means that 1 sample is taken per measurement
|
||||
Avg1 AvgSampling = iota // 0
|
||||
Avg2 // 1
|
||||
Avg4 // 2
|
||||
Avg8 // 3 default
|
||||
Avg16 // 4
|
||||
Avg32 // 5
|
||||
Avg64 // 6
|
||||
Avg128 // 7
|
||||
)
|
||||
|
||||
// CycleTime determines the overall cycle time for all measured channels during
|
||||
// normal operation.
|
||||
type CycleTime uint8
|
||||
|
||||
// possible cycle time values. (written as 2 bits)
|
||||
const (
|
||||
C35ms CycleTime = iota // 0
|
||||
C70ms // default
|
||||
C105ms
|
||||
C140ms
|
||||
)
|
||||
|
||||
// MaxDur is the maximum duration of a touch event before it triggers a
|
||||
// recalibration.
|
||||
type MaxDur uint8
|
||||
|
||||
// possible touch duration values. (written as 4 bits)
|
||||
const (
|
||||
MaxDur560ms MaxDur = iota
|
||||
MaxDur840ms
|
||||
MaxDur1120ms
|
||||
MaxDur1400ms
|
||||
MaxDur1680ms
|
||||
MaxDur2240ms
|
||||
MaxDur2800ms
|
||||
MaxDur3360ms
|
||||
MaxDur3920ms
|
||||
MaxDur44800ms
|
||||
MaxDur5600ms // default
|
||||
MaxDur6720ms
|
||||
MaxDur7840ms
|
||||
MaxDur8906ms
|
||||
MaxDur10080ms
|
||||
MaxDur11200ms
|
||||
)
|
||||
|
||||
// Opts is optional options to pass to the constructor.
|
||||
//
|
||||
// Address is only used on creation of an I²C-device. Its default value is 0x28.
|
||||
// It can be set to other values (0x29, 0x2a, 0x2b, 0x2c) depending on the HW
|
||||
// configuration of the ADDR_COMM pin. This has no effect with NewSPI()
|
||||
type Opts struct {
|
||||
// Address is the I2C slave address to use
|
||||
Address uint16
|
||||
|
||||
// Debug turns on extra logging capabilities
|
||||
Debug bool
|
||||
// LinkedLEDs indicates if the LEDs should be activated automatically
|
||||
// when their sensors detect a touch event.
|
||||
LinkedLEDs bool
|
||||
// MaxTouchDuration sets the touch duration threshold. It is possible that a
|
||||
// “stuck button” occurs when something is placed on a button which causes a
|
||||
// touch to be detected for a long period. By setting this value,
|
||||
// a recalibration can be forced when a touch is held on a button for longer
|
||||
// than the duration specified.
|
||||
MaxTouchDuration MaxDur
|
||||
// EnableRecalibration is used to force the recalibration if a touch event lasts
|
||||
// longer than MaxTouchDuration.
|
||||
EnableRecalibration bool
|
||||
|
||||
// AlertPin is the pin receiving the interrupt when a touch event is detected
|
||||
// and optionally if a release event is detected.
|
||||
AlertPin gpio.PinIn
|
||||
// ResetPin is the pin used to reset the device.
|
||||
ResetPin gpio.PinOut
|
||||
|
||||
// InterruptOnRelease indicates if the device should also trigger an
|
||||
// interrupt on the AlertPin when a release event is detected.
|
||||
InterruptOnRelease bool
|
||||
|
||||
// RetriggerOnHold forces a retrigger of the interrupt when a sensor is pressed
|
||||
// for longer than MaxTouchDuration
|
||||
RetriggerOnHold bool
|
||||
|
||||
// Averaging and Sampling Configuration Register
|
||||
|
||||
// SamplesPerMeasurement is the number of samples taken per measurement. All
|
||||
// samples are taken consecutively on the same channel before the next
|
||||
// channel is sampled and the result is averaged over the number of samples
|
||||
// measured before updating the measured results.
|
||||
// Available options: 1, 2, 4, 8 (default), 16, 32, 64, 128
|
||||
SamplesPerMeasurement AvgSampling
|
||||
|
||||
// SamplingTime Determines the time to take a single sample as shown
|
||||
SamplingTime SamplingTime
|
||||
|
||||
// CycleTime determines the overall cycle time for all measured channels
|
||||
// during normal operation. All measured channels are sampled at the
|
||||
// beginning of the cycle time. If additional time is remaining, then the
|
||||
// device is placed into a lower power state for the remaining duration of
|
||||
// the cycle.
|
||||
CycleTime CycleTime
|
||||
}
|
||||
|
||||
// DefaultOpts returns a pointer to a new Opts with the default option values.
|
||||
func DefaultOpts() *Opts {
|
||||
return &Opts{
|
||||
LinkedLEDs: true,
|
||||
MaxTouchDuration: MaxDur5600ms,
|
||||
RetriggerOnHold: false,
|
||||
EnableRecalibration: false,
|
||||
InterruptOnRelease: false,
|
||||
SamplesPerMeasurement: Avg1,
|
||||
SamplingTime: S1_28ms,
|
||||
CycleTime: C35ms,
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,348 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package cap1188_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"periph.io/x/periph/conn/gpio"
|
||||
"periph.io/x/periph/conn/gpio/gpioreg"
|
||||
"periph.io/x/periph/conn/i2c"
|
||||
"periph.io/x/periph/conn/i2c/i2creg"
|
||||
"periph.io/x/periph/conn/i2c/i2ctest"
|
||||
"periph.io/x/periph/experimental/devices/cap1188"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
// Open the I²C bus to which the cap1188 is connected.
|
||||
i2cBus, err := i2creg.Open("")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer i2cBus.Close()
|
||||
|
||||
// We will configure the cap1188 by setting some options, we can start by the defaults.
|
||||
opts := cap1188.DefaultOpts()
|
||||
|
||||
// We need to set an alert ping that will let us know when a touch event
|
||||
// occurs. The alert pin is the pin connected to the IRQ/interrupt pin.
|
||||
alertPin := gpioreg.ByName("GPIO25")
|
||||
if alertPin == nil {
|
||||
log.Fatal("invalid alert GPIO pin number")
|
||||
}
|
||||
// We set the alert pin to monitor for interrupts
|
||||
if err := alertPin.In(gpio.PullUp, gpio.BothEdges); err != nil {
|
||||
log.Fatalf("Can't monitor the alert pin")
|
||||
}
|
||||
|
||||
// Optionally but highly recommended, we can also set a reset pin to
|
||||
// start/leave things in a clean state.
|
||||
resetPin := gpioreg.ByName("GPIO21")
|
||||
if resetPin == nil {
|
||||
log.Fatal("invalid reset GPIO pin number")
|
||||
}
|
||||
opts.AlertPin = alertPin
|
||||
opts.ResetPin = resetPin
|
||||
|
||||
// open the device so we can detect touch events
|
||||
dev, err := cap1188.NewI2C(i2cBus, opts)
|
||||
if err != nil {
|
||||
log.Fatalf("couldn't open cap1188 - %s", err)
|
||||
}
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
|
||||
fmt.Println("Monitoring for touch events")
|
||||
maxTouches := 42 // stop the program after 42 touches
|
||||
for maxTouches > 0 {
|
||||
if alertPin.WaitForEdge(-1) {
|
||||
maxTouches--
|
||||
statuses, err := dev.InputStatus()
|
||||
if err != nil {
|
||||
fmt.Printf("Error reading inputs: %s\n", err)
|
||||
continue
|
||||
}
|
||||
// print the status of each sensor
|
||||
for i, st := range statuses {
|
||||
fmt.Printf("#%d: %s\t", i, st)
|
||||
}
|
||||
fmt.Println()
|
||||
// we need to clear the interrupt so it can be triggered again
|
||||
if err := dev.ClearInterrupt(); err != nil {
|
||||
fmt.Println(err, "while clearing the interrupt")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Print("\n")
|
||||
}
|
||||
|
||||
func TestNewI2C(t *testing.T) {
|
||||
bus := i2ctest.Playback{
|
||||
Ops: []i2ctest.IO{
|
||||
// chip ID
|
||||
{Addr: 40, W: []byte{0xfd}, R: []byte{0x50}},
|
||||
// clear interrupt
|
||||
{Addr: 40, W: []byte{0x0}, R: []byte{0x0}},
|
||||
{Addr: 40, W: []byte{0x0, 0x0}, R: nil},
|
||||
// enable all inputs
|
||||
{Addr: 40, W: []byte{0x21, 0xff}, R: nil},
|
||||
// enable interrupts
|
||||
{Addr: 40, W: []byte{0x27, 0xff}, R: nil},
|
||||
// enable/disable repeats
|
||||
{Addr: 40, W: []byte{0x28, 0xff}, R: nil},
|
||||
// multitouch
|
||||
{Addr: 40, W: []byte{0x2a, 0x4}, R: nil},
|
||||
// sampling
|
||||
{Addr: 40, W: []byte{0x24, 0x8}, R: nil},
|
||||
// sensitivity
|
||||
{Addr: 40, W: []byte{0x1f, 0x50}, R: nil},
|
||||
// don't retrigger on hold
|
||||
{Addr: 40, W: []byte{0x28, 0x0}, R: nil},
|
||||
// config
|
||||
{Addr: 40, W: []byte{0x20, 0x30}, R: nil},
|
||||
// config 2
|
||||
{Addr: 40, W: []byte{0x44, 0x61}, R: nil},
|
||||
},
|
||||
}
|
||||
d, err := cap1188.NewI2C(&bus, &cap1188.Opts{Debug: true})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if s := d.String(); s != "cap1188{playback(40)}" {
|
||||
t.Fatal(s)
|
||||
}
|
||||
if err := d.Halt(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := bus.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDev_InputStatus(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
bus i2c.Bus
|
||||
opts *cap1188.Opts
|
||||
want []cap1188.TouchStatus
|
||||
}{
|
||||
{name: "all off",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
// status
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{0x0}},
|
||||
// deltas
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
// thresholds
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus},
|
||||
},
|
||||
{name: "all pressed",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{0xff}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.PressedStatus, cap1188.PressedStatus, cap1188.PressedStatus, cap1188.PressedStatus, cap1188.PressedStatus, cap1188.PressedStatus, cap1188.PressedStatus, cap1188.PressedStatus},
|
||||
},
|
||||
{name: "first pressed",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{1 << 7}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.PressedStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus},
|
||||
},
|
||||
{name: "second pressed",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{1 << 6}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.OffStatus, cap1188.PressedStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus},
|
||||
},
|
||||
{name: "third pressed",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{1 << 5}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.OffStatus, cap1188.OffStatus, cap1188.PressedStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus},
|
||||
},
|
||||
{name: "forth pressed",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{1 << 4}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.PressedStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus},
|
||||
},
|
||||
{name: "fifth pressed",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{1 << 3}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.PressedStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus},
|
||||
},
|
||||
{name: "sixth pressed",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{1 << 2}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.PressedStatus, cap1188.OffStatus, cap1188.OffStatus},
|
||||
},
|
||||
{name: "seventh pressed",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{1 << 1}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.PressedStatus, cap1188.OffStatus},
|
||||
},
|
||||
{name: "eighth pressed",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{1 << 0}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.PressedStatus},
|
||||
},
|
||||
{name: "3 pressed",
|
||||
bus: &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{(1 << 7) ^ (1 << 4) ^ (1 << 0)}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
},
|
||||
opts: cap1188.DefaultOpts(),
|
||||
want: []cap1188.TouchStatus{cap1188.PressedStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.PressedStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.PressedStatus},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
d, err := cap1188.NewI2C(tt.bus, tt.opts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := d.InputStatus()
|
||||
if err != nil {
|
||||
t.Fatalf("Dev.InputStatus() error = %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Dev.InputStatus() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
// test hold
|
||||
t.Run("held touch sensors", func(t *testing.T) {
|
||||
bus := &i2ctest.Playback{
|
||||
Ops: append(setupPlaybackIO(), []i2ctest.IO{
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{1 << 7}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
// repeat call to get status (still pressed)
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{1 << 7}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
// finall call
|
||||
{Addr: 40, W: []byte{0x3}, R: []byte{0x0}},
|
||||
{Addr: 40, W: []byte{0x10}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
{Addr: 40, W: []byte{0x30}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
|
||||
}...),
|
||||
}
|
||||
// set the recorded response to have the retrigger option on
|
||||
bus.Ops[10] = i2ctest.IO{Addr: 40, W: []byte{0x28, 0xff}, R: nil}
|
||||
opts := cap1188.DefaultOpts()
|
||||
// following option needs to be true so we can get the held status
|
||||
opts.RetriggerOnHold = true
|
||||
d, err := cap1188.NewI2C(bus, opts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// first check
|
||||
got, err := d.InputStatus()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, []cap1188.TouchStatus{cap1188.PressedStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus}) {
|
||||
t.Fatalf("expected to have the first sensor touched but instead got %v", got)
|
||||
}
|
||||
// 2nd check
|
||||
got, err = d.InputStatus()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, []cap1188.TouchStatus{cap1188.HeldStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus, cap1188.OffStatus}) {
|
||||
t.Fatalf("expected to have the first sensor touched but instead got %v", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func setupPlaybackIO() []i2ctest.IO {
|
||||
return []i2ctest.IO{
|
||||
// chip ID
|
||||
{Addr: 40, W: []byte{0xfd}, R: []byte{0x50}},
|
||||
// clear interrupt
|
||||
{Addr: 40, W: []byte{0x0}, R: []byte{0x0}},
|
||||
{Addr: 40, W: []byte{0x0, 0x0}, R: nil},
|
||||
// enable all inputs
|
||||
{Addr: 40, W: []byte{0x21, 0xff}, R: nil},
|
||||
// enable interrupts
|
||||
{Addr: 40, W: []byte{0x27, 0xff}, R: nil},
|
||||
// enable/disable repeats
|
||||
{Addr: 40, W: []byte{0x28, 0xff}, R: nil},
|
||||
// multitouch
|
||||
{Addr: 40, W: []byte{0x2a, 0x4}, R: nil},
|
||||
// sampling
|
||||
{Addr: 40, W: []byte{0x24, 0x8}, R: nil},
|
||||
// sensitivity
|
||||
{Addr: 40, W: []byte{0x1f, 0x50}, R: nil},
|
||||
// linked leds
|
||||
{Addr: 40, W: []byte{0x72, 0xff}, R: nil},
|
||||
// don't retrigger on hold
|
||||
{Addr: 40, W: []byte{0x28, 0x0}, R: nil},
|
||||
// config
|
||||
{Addr: 40, W: []byte{0x20, 0x30}, R: nil},
|
||||
// config 2
|
||||
{Addr: 40, W: []byte{0x44, 0x61}, R: nil},
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue