mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 02:28:41 +00:00
makeybutton: revise to better match the algorithm defined by the original
Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
var (
|
||||
led machine.Pin = machine.LED
|
||||
button machine.Pin = machine.BUTTON
|
||||
button machine.Pin = machine.D10
|
||||
key *makeybutton.Button
|
||||
)
|
||||
|
||||
@@ -25,6 +25,7 @@ func main() {
|
||||
case makeybutton.Released:
|
||||
led.Low()
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
// the more frequent the more responsive
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
+44
-25
@@ -1,11 +1,17 @@
|
||||
package makeybutton
|
||||
|
||||
const bufferSize = 6
|
||||
const (
|
||||
bufferSize = 3
|
||||
maxSumAllowed = 4
|
||||
)
|
||||
|
||||
// Buffer is a buffer to keep track of the most recent readings for a button.
|
||||
// in bit form.
|
||||
type Buffer struct {
|
||||
readings [bufferSize]bool
|
||||
index int
|
||||
data [bufferSize]byte
|
||||
byteCounter int
|
||||
bitCounter int
|
||||
sum int
|
||||
}
|
||||
|
||||
// NewBuffer returns a new buffer.
|
||||
@@ -13,34 +19,47 @@ func NewBuffer() *Buffer {
|
||||
return &Buffer{}
|
||||
}
|
||||
|
||||
// Used returns how many bytes in buffer have been used.
|
||||
func (b *Buffer) Used() int {
|
||||
return b.index
|
||||
// Sum returns the sum of all measurements
|
||||
func (b *Buffer) Sum() int {
|
||||
return b.sum
|
||||
}
|
||||
|
||||
// Put stores a boolean in the buffer.
|
||||
func (b *Buffer) Put(val bool) bool {
|
||||
b.index++
|
||||
if b.index >= bufferSize {
|
||||
b.index = 0
|
||||
// Put stores a boolean button state into the buffer.
|
||||
func (b *Buffer) Put(val bool) {
|
||||
currentMeasurement, oldestMeasurement := b.updateData(val)
|
||||
b.updateCounters()
|
||||
|
||||
if currentMeasurement != 0 && b.sum < maxSumAllowed {
|
||||
b.sum++
|
||||
}
|
||||
|
||||
b.readings[b.index] = val
|
||||
|
||||
return true
|
||||
if oldestMeasurement != 0 && b.sum > 0 {
|
||||
b.sum--
|
||||
}
|
||||
}
|
||||
|
||||
// Avg returns the "average" of all the readings in the buffer, by
|
||||
// treating a true as 1 and a false as -1.
|
||||
func (b *Buffer) Avg() int {
|
||||
avg := 0
|
||||
for i := 0; i < bufferSize; i++ {
|
||||
if b.readings[i] {
|
||||
avg += 1
|
||||
} else {
|
||||
avg -= 1
|
||||
func (b *Buffer) updateData(val bool) (byte, byte) {
|
||||
currentByte := b.data[b.byteCounter]
|
||||
oldestMeasurement := (currentByte >> b.bitCounter) & 0x01
|
||||
|
||||
if val {
|
||||
currentByte |= (1 << b.bitCounter)
|
||||
} else {
|
||||
currentByte &= ^(1 << b.bitCounter)
|
||||
}
|
||||
|
||||
b.data[b.byteCounter] = currentByte
|
||||
|
||||
return (currentByte >> b.bitCounter) & 0x01, oldestMeasurement
|
||||
}
|
||||
|
||||
func (b *Buffer) updateCounters() {
|
||||
b.bitCounter++
|
||||
if b.bitCounter == 8 {
|
||||
b.bitCounter = 0
|
||||
b.byteCounter++
|
||||
if b.byteCounter == bufferSize {
|
||||
b.byteCounter = 0
|
||||
}
|
||||
}
|
||||
|
||||
return avg
|
||||
}
|
||||
|
||||
+34
-20
@@ -4,6 +4,8 @@
|
||||
// Inspired by the amazing MakeyMakey
|
||||
// https://makeymakey.com/
|
||||
//
|
||||
// This code is a reinterpretation of
|
||||
// https://github.com/sparkfun/MaKeyMaKey/blob/master/firmware/Arduino/makey_makey/makey_makey.ino
|
||||
package makeybutton
|
||||
|
||||
import (
|
||||
@@ -11,6 +13,11 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
pressThreshold int = 1
|
||||
releaseThreshold int = 0
|
||||
)
|
||||
|
||||
// ButtonState represents the state of a MakeyButton.
|
||||
type ButtonState int
|
||||
|
||||
@@ -33,6 +40,7 @@ const (
|
||||
type Button struct {
|
||||
pin machine.Pin
|
||||
state ButtonState
|
||||
pressed bool
|
||||
readings *Buffer
|
||||
HighMeansPressed bool
|
||||
}
|
||||
@@ -49,7 +57,7 @@ func NewButton(pin machine.Pin) *Button {
|
||||
|
||||
// Configure configures the Makey Button pin to have the correct settings to detect touches.
|
||||
func (b *Button) Configure() error {
|
||||
// Note that we have to first turn on the pullup, and then turn off the pullup,
|
||||
// Note that on AVR we have to first turn on the pullup, and then turn off the pullup,
|
||||
// in order for the pin to be properly floating.
|
||||
b.pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
@@ -62,30 +70,36 @@ func (b *Button) Configure() error {
|
||||
// Get returns a ButtonEvent based on the most recent state of the button,
|
||||
// and if it has changed by being pressed or released.
|
||||
func (b *Button) Get() ButtonEvent {
|
||||
// if pin is pulled up, a low value means the key is pressed
|
||||
pressed := !b.pin.Get()
|
||||
if b.HighMeansPressed {
|
||||
// otherwise, a high value means the key is pressed
|
||||
pressed = !pressed
|
||||
}
|
||||
b.update()
|
||||
|
||||
avg := b.readings.Avg()
|
||||
b.readings.Put(pressed)
|
||||
|
||||
switch {
|
||||
case pressed && avg > -1*bufferSize+2:
|
||||
if b.state == Press {
|
||||
return NotChanged
|
||||
}
|
||||
|
||||
b.state = Press
|
||||
return Pressed
|
||||
case !pressed:
|
||||
if b.state == Press {
|
||||
if b.pressed {
|
||||
// the button had previously been pressed,
|
||||
// but now appears to have been released.
|
||||
if b.readings.Sum() <= releaseThreshold {
|
||||
b.pressed = false
|
||||
b.state = Release
|
||||
return Released
|
||||
}
|
||||
} else {
|
||||
// the button had previously not been pressed,
|
||||
// but now appears to have been pressed.
|
||||
if b.readings.Sum() >= pressThreshold {
|
||||
b.pressed = true
|
||||
b.state = Press
|
||||
return Pressed
|
||||
}
|
||||
}
|
||||
|
||||
return NotChanged
|
||||
}
|
||||
|
||||
func (b *Button) update() {
|
||||
// if pin is pulled up, a low value means the key is pressed
|
||||
press := !b.pin.Get()
|
||||
if b.HighMeansPressed {
|
||||
// otherwise, a high value means the key is pressed
|
||||
press = !press
|
||||
}
|
||||
|
||||
b.readings.Put(press)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user