Skip to content

Commit cafe8df

Browse files
deadprogramconejoninja
authored andcommitted
makeybutton: add driver for MakeyMakey-like button
Signed-off-by: deadprogram <[email protected]>
1 parent 13c4335 commit cafe8df

File tree

5 files changed

+160
-2
lines changed

5 files changed

+160
-2
lines changed

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,15 @@ endif
239239
@md5sum ./build/test.hex
240240
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/scd4x/main.go
241241
@md5sum ./build/test.uf2
242+
tinygo build -size short -o ./build/test.uf2 -target=circuitplay-express ./examples/makeybutton/main.go
243+
@md5sum ./build/test.uf2
242244

243245
DRIVERS = $(wildcard */)
244246
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
245247
hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \
246248
hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x keypad4x4 max72xx p1am tone tm1637 \
247249
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd i2csoft hts221 lps22hb apds9960 axp192 xpt2046 \
248-
ft6336 sx126x ssd1289 irremote uc8151
250+
ft6336 sx126x ssd1289 irremote uc8151 makeybutton
249251
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
250252

251253
unit-test:

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func main() {
5252

5353
## Currently supported devices
5454

55-
The following 80 devices are supported.
55+
The following 81 devices are supported.
5656

5757
| Device Name | Interface Type |
5858
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
@@ -100,6 +100,7 @@ The following 80 devices are supported.
100100
| [LSM6DS3TR accelerometer](https://www.st.com/resource/en/datasheet/lsm6ds3tr.pdf) | I2C |
101101
| [LSM303AGR accelerometer](https://www.st.com/resource/en/datasheet/lsm303agr.pdf) | I2C |
102102
| [LSM9DS1 accelerometer](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) | I2C |
103+
| [Makey Button](https://makeymakey.com/) | GPIO |
103104
| [MAG3110 magnetometer](https://www.nxp.com/docs/en/data-sheet/MAG3110.pdf) | I2C |
104105
| [MAX7219 & MAX7221 display driver](https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf) | SPI |
105106
| [MCP2515 Stand-Alone CAN Controller with SPI Interface](https://ww1.microchip.com/downloads/en/DeviceDoc/MCP2515-Family-Data-Sheet-DS20001801K.pdf) | SPI |

examples/makeybutton/main.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package main
2+
3+
import (
4+
"machine"
5+
"time"
6+
7+
"tinygo.org/x/drivers/makeybutton"
8+
)
9+
10+
var (
11+
led machine.Pin = machine.LED
12+
button machine.Pin = machine.BUTTON
13+
key *makeybutton.Button
14+
)
15+
16+
func main() {
17+
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
18+
button.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
19+
key = makeybutton.NewButton(button)
20+
21+
for {
22+
switch key.Get() {
23+
case makeybutton.Pressed:
24+
led.High()
25+
case makeybutton.Released:
26+
led.Low()
27+
}
28+
time.Sleep(30 * time.Millisecond)
29+
}
30+
}

makeybutton/buffer.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package makeybutton
2+
3+
const bufferSize = 10
4+
5+
// Buffer is a buffer to keep track of the most recent readings for a button.
6+
type Buffer struct {
7+
readings [bufferSize]bool
8+
index int
9+
}
10+
11+
// NewBuffer returns a new buffer.
12+
func NewBuffer() *Buffer {
13+
return &Buffer{}
14+
}
15+
16+
// Used returns how many bytes in buffer have been used.
17+
func (b *Buffer) Used() int {
18+
return b.index
19+
}
20+
21+
// Put stores a boolean in the buffer.
22+
func (b *Buffer) Put(val bool) bool {
23+
b.index++
24+
if b.index >= bufferSize {
25+
b.index = 0
26+
}
27+
28+
b.readings[b.index] = val
29+
30+
return true
31+
}
32+
33+
// Avg returns the "average" of all the readings in the buffer, by
34+
// treating a true as 1 and a false as -1.
35+
func (b *Buffer) Avg() int {
36+
avg := 0
37+
for i := 0; i < bufferSize; i++ {
38+
if b.readings[i] {
39+
avg += 1
40+
} else {
41+
avg -= 1
42+
}
43+
}
44+
45+
return avg
46+
}

makeybutton/button.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Package makeybutton providers a driver for a button that can be triggered
2+
// by anything that is conductive by using an ultra high value resistor.
3+
//
4+
// Inspired by the amazing MakeyMakey
5+
// https://makeymakey.com/
6+
//
7+
package makeybutton
8+
9+
import "machine"
10+
11+
// ButtonState represents the state of a MakeyButton.
12+
type ButtonState int
13+
14+
const (
15+
NeverPressed ButtonState = 0
16+
Press = 1
17+
Release = 2
18+
)
19+
20+
// ButtonEvent represents when the state of a Button changes.
21+
type ButtonEvent int
22+
23+
const (
24+
NotChanged ButtonEvent = 0
25+
Pressed = 1
26+
Released = 2
27+
)
28+
29+
// Button is a "button"-like device that acts like a MakeyMakey.
30+
type Button struct {
31+
pin machine.Pin
32+
state ButtonState
33+
readings *Buffer
34+
HighMeansPressed bool
35+
}
36+
37+
// NewButton creates a new Button.
38+
func NewButton(pin machine.Pin) *Button {
39+
pin.Configure(machine.PinConfig{Mode: machine.PinInput})
40+
pin.Set(false)
41+
42+
return &Button{
43+
pin: pin,
44+
state: NeverPressed,
45+
readings: NewBuffer(),
46+
HighMeansPressed: false,
47+
}
48+
}
49+
50+
// Get returns a ButtonEvent based on the most recent state of the button,
51+
// and if it has changed by being pressed or released.
52+
func (b *Button) Get() ButtonEvent {
53+
// if pin is pulled up, a low value means the key is pressed
54+
pressed := !b.pin.Get()
55+
if b.HighMeansPressed {
56+
// otherwise, a high value means the key is pressed
57+
pressed = !pressed
58+
}
59+
60+
avg := b.readings.Avg()
61+
b.readings.Put(pressed)
62+
63+
switch {
64+
case pressed && avg > 0:
65+
if b.state == Press {
66+
return NotChanged
67+
}
68+
69+
b.state = Press
70+
return Pressed
71+
case !pressed:
72+
if b.state == Press {
73+
b.state = Release
74+
return Released
75+
}
76+
}
77+
78+
return NotChanged
79+
}

0 commit comments

Comments
 (0)