makeybutton: revise to better match the algorithm defined by the original

Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
deadprogram
2022-09-14 14:54:13 +02:00
committed by Ron Evans
parent 7396a5be43
commit 0ea72e7f1e
3 changed files with 81 additions and 47 deletions
+3 -2
View File
@@ -9,7 +9,7 @@ import (
var ( var (
led machine.Pin = machine.LED led machine.Pin = machine.LED
button machine.Pin = machine.BUTTON button machine.Pin = machine.D10
key *makeybutton.Button key *makeybutton.Button
) )
@@ -25,6 +25,7 @@ func main() {
case makeybutton.Released: case makeybutton.Released:
led.Low() led.Low()
} }
time.Sleep(100 * time.Millisecond) // the more frequent the more responsive
time.Sleep(50 * time.Millisecond)
} }
} }
+44 -25
View File
@@ -1,11 +1,17 @@
package makeybutton 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. // Buffer is a buffer to keep track of the most recent readings for a button.
// in bit form.
type Buffer struct { type Buffer struct {
readings [bufferSize]bool data [bufferSize]byte
index int byteCounter int
bitCounter int
sum int
} }
// NewBuffer returns a new buffer. // NewBuffer returns a new buffer.
@@ -13,34 +19,47 @@ func NewBuffer() *Buffer {
return &Buffer{} return &Buffer{}
} }
// Used returns how many bytes in buffer have been used. // Sum returns the sum of all measurements
func (b *Buffer) Used() int { func (b *Buffer) Sum() int {
return b.index return b.sum
} }
// Put stores a boolean in the buffer. // Put stores a boolean button state into the buffer.
func (b *Buffer) Put(val bool) bool { func (b *Buffer) Put(val bool) {
b.index++ currentMeasurement, oldestMeasurement := b.updateData(val)
if b.index >= bufferSize { b.updateCounters()
b.index = 0
if currentMeasurement != 0 && b.sum < maxSumAllowed {
b.sum++
} }
b.readings[b.index] = val if oldestMeasurement != 0 && b.sum > 0 {
b.sum--
return true }
} }
// Avg returns the "average" of all the readings in the buffer, by func (b *Buffer) updateData(val bool) (byte, byte) {
// treating a true as 1 and a false as -1. currentByte := b.data[b.byteCounter]
func (b *Buffer) Avg() int { oldestMeasurement := (currentByte >> b.bitCounter) & 0x01
avg := 0
for i := 0; i < bufferSize; i++ { if val {
if b.readings[i] { currentByte |= (1 << b.bitCounter)
avg += 1 } else {
} else { currentByte &= ^(1 << b.bitCounter)
avg -= 1 }
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
View File
@@ -4,6 +4,8 @@
// Inspired by the amazing MakeyMakey // Inspired by the amazing MakeyMakey
// https://makeymakey.com/ // 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 package makeybutton
import ( import (
@@ -11,6 +13,11 @@ import (
"time" "time"
) )
var (
pressThreshold int = 1
releaseThreshold int = 0
)
// ButtonState represents the state of a MakeyButton. // ButtonState represents the state of a MakeyButton.
type ButtonState int type ButtonState int
@@ -33,6 +40,7 @@ const (
type Button struct { type Button struct {
pin machine.Pin pin machine.Pin
state ButtonState state ButtonState
pressed bool
readings *Buffer readings *Buffer
HighMeansPressed bool 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. // Configure configures the Makey Button pin to have the correct settings to detect touches.
func (b *Button) Configure() error { 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. // in order for the pin to be properly floating.
b.pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup}) b.pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
time.Sleep(10 * time.Millisecond) 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, // Get returns a ButtonEvent based on the most recent state of the button,
// and if it has changed by being pressed or released. // and if it has changed by being pressed or released.
func (b *Button) Get() ButtonEvent { func (b *Button) Get() ButtonEvent {
// if pin is pulled up, a low value means the key is pressed b.update()
pressed := !b.pin.Get()
if b.HighMeansPressed {
// otherwise, a high value means the key is pressed
pressed = !pressed
}
avg := b.readings.Avg() if b.pressed {
b.readings.Put(pressed) // the button had previously been pressed,
// but now appears to have been released.
switch { if b.readings.Sum() <= releaseThreshold {
case pressed && avg > -1*bufferSize+2: b.pressed = false
if b.state == Press {
return NotChanged
}
b.state = Press
return Pressed
case !pressed:
if b.state == Press {
b.state = Release b.state = Release
return Released 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 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)
}