- commit
- c18a343
- parent
- e99ed1c
- author
- Neale Pickett
- date
- 2026-02-23 20:18:37 -0700 MST
Working with bellows, about to pivot to rust
4 files changed,
+100,
-2
M
Makefile
+7,
-2
1@@ -11,6 +11,11 @@ clean:
2 build/%/concertina.bin: cmd/concertina
3 tinygo build -o $@ -target=$* ./$</...
4
5-layouts.h: layouts.txt mklayouts.py
6- ./mklayouts.py $< > $@
7
8+flash-test: flash-qtpy-test
9+flash-qtpy-test: build/qtpy/bellows-test.bin
10+ stty -F /dev/ttyACM0 1200 && sleep 1 # Reset into bootloader
11+ bossac --offset=0x2000 -w -v $< -R
12+
13+build/%/bellows-test.bin: cmd/bellows-test
14+ tinygo build -o $@ -target=$* ./$</...
+81,
-0
1@@ -0,0 +1,81 @@
2+package main
3+
4+import (
5+ "context"
6+ "image/color"
7+ "machine"
8+ "time"
9+
10+ "git.woozle.org/neale/concertina/pkg/led"
11+ "tinygo.org/x/drivers/ssd1306"
12+ "tinygo.org/x/drivers/vl6180x"
13+)
14+
15+// For crying out loud.
16+// https://github.com/tinygo-org/drivers/issues/837`
17+var White = color.RGBAModel.Convert(color.White).(color.RGBA)
18+var Black = color.RGBAModel.Convert(color.Black).(color.RGBA)
19+
20+func main() {
21+ led.Builtin.Enable()
22+
23+ if err := machine.I2C0.Configure(machine.I2CConfig{}); err != nil {
24+ led.Flash(context.Background(), led.Builtin, time.Second/4, time.Second/4)
25+ }
26+
27+ display := ssd1306.NewI2C(machine.I2C0)
28+ display.Configure(
29+ ssd1306.Config{
30+ Width: 64,
31+ Height: 32,
32+
33+ // https://github.com/tinygo-org/drivers/issues/842
34+ ResetCol: ssd1306.ResetValue{0x20, 0x20+64-1},
35+
36+ Address: 0x3C,
37+ },
38+ )
39+ display.ClearDisplay()
40+ for i := 0; i < 64; i += 4 {
41+ display.FillRectangle(0, 30, int16(i), 2, White)
42+ display.Display()
43+ }
44+
45+ prox := vl6180x.New(machine.I2C0)
46+ prox.Configure(false)
47+ prox.StartRangeContinuous(40) // milliseconds between samples
48+
49+ machine.D3.Configure(machine.PinConfig{machine.PinInputPullup})
50+
51+ var distance uint16
52+ for {
53+ if machine.D3.Get() {
54+ continue
55+ }
56+
57+ led.Builtin.SetColor(color.RGBA{0, 0, 1, 0})
58+ start := time.Now()
59+ distance = prox.Read()
60+ duration := time.Now().Sub(start)
61+ led.Builtin.SetColor(color.RGBA{0, 0, 0, 0})
62+
63+ // The top bar shows how long it took to read the value.
64+ // One pixel is 100 microseconds.
65+ // I'm seeing values around 2ms
66+ duration_ms := duration / (100 * time.Microsecond)
67+ if duration_ms > 50 {
68+ duration_ms = 50
69+ }
70+ display.FillRectangle(int16(duration_ms), 0, 10, 8, Black)
71+ display.FillRectangle(0, 0, int16(duration_ms), 8, White)
72+
73+ // The bottom bar is roughly what the bellows is reading.
74+ distance = distance / 2
75+ if distance > 50 {
76+ distance = 50
77+ }
78+ display.FillRectangle(0, 16, 64, 8, Black)
79+ display.FillRectangle(0, 16, int16(distance), 8, White)
80+ display.Display()
81+ }
82+}
+10,
-0
1@@ -1,6 +1,8 @@
2 package main
3
4 import (
5+ "time"
6+
7 "tinygo.org/x/drivers"
8 "tinygo.org/x/drivers/vl6180x"
9 )
10@@ -9,6 +11,12 @@ import (
11 // Set this lower to make the bellows more "twitchy"
12 const BellowsSlop = 2
13
14+// BellowsSamplePeriod is the duration between samples.
15+// I think (I'm not sure) that this device blocks the I2C bus while it does a sample,
16+// making everything less responsive. Using the built-in continuous range sampling mechanism
17+// should mean the most recent sample is always immediately available.
18+const BellowsSamplePeriod = time.Second / 10
19+
20 type Bellows struct {
21 vl6180x.Device
22 prev uint16
23@@ -19,6 +27,7 @@ func NewBellows(i2c drivers.I2C) *Bellows {
24 Device: vl6180x.New(i2c),
25 }
26 b.Device.Configure(false) // this argument is ignored!
27+ //b.Device.StartRangeContinuous(uint16(BellowsSamplePeriod / time.Millisecond))
28 return b
29 }
30
31@@ -29,5 +38,6 @@ func (b *Bellows) Direction() int16 {
32 distance := b.Read()
33 dir := int16(b.prev -distance) / BellowsSlop
34 b.prev = distance
35+ return int16(distance)
36 return dir
37 }
+2,
-0
1@@ -101,6 +101,7 @@ func (c *Concertina) Loop() {
2 // get the bellows direction
3 c.display.FillRectangle(0, 16, 100, 4, Black)
4 dir := c.bellows.Direction()
5+ //dir := int16(-4)
6 if (dir < 0) {
7 c.display.FillRectangle(50+dir, 16, -dir, 4, White)
8 } else if (dir > 0) {
9@@ -141,6 +142,7 @@ func main() {
10 time.Sleep(1 * time.Hour)
11 }
12 }
13+ time.Sleep(2 * time.Second)
14
15 // Okay, you can stop blinking now
16 blinkCancel()