- commit
- f751184
- parent
- a3d4bd2
- author
- Neale Pickett
- date
- 2026-02-16 21:43:10 -0700 MST
I don't remember, it was a day
7 files changed,
+61,
-51
+2,
-2
1@@ -5,7 +5,7 @@ package main
2 import "machine"
3
4 const (
5- VS1053_TX = machine.UART_TX_PIN
6- VS1053_RX = machine.UART_RX_PIN
7+ VS1053_TX = machine.UART_TX_PIN
8+ VS1053_RX = machine.UART_RX_PIN
9 VS1053_RESET = machine.D3
10 )
+0,
-2
1@@ -13,5 +13,3 @@ func blink() {
2 machine.LED.Low()
3 time.Sleep(200 * time.Millisecond)
4 }
5-
6-
+38,
-31
1@@ -5,10 +5,14 @@ import (
2 "image/color"
3 "machine"
4 "time"
5- "tinygo.org/x/drivers"
6- "tinygo.org/x/drivers/ssd1306"
7+
8+ "git.woozle.org/neale/concertina/pkg/layouts"
9 "git.woozle.org/neale/concertina/pkg/led"
10 "git.woozle.org/neale/concertina/pkg/pcf8575"
11+ "tinygo.org/x/drivers"
12+ "tinygo.org/x/drivers/ssd1306"
13+ "tinygo.org/x/tinyfont"
14+ "tinygo.org/x/tinyfont/proggy"
15 )
16
17 // For crying out loud.
18@@ -17,17 +21,19 @@ var White = color.RGBAModel.Convert(color.White).(color.RGBA)
19 var Black = color.RGBAModel.Convert(color.Black).(color.RGBA)
20
21 type Concertina struct {
22- display *ssd1306.Device
23- tonegen MidiWriter
24- expanders[4] pcf8575.Device
25+ display *ssd1306.Device
26+ tonegen MidiWriter
27+ expanders [4]pcf8575.Device
28+ layouts []*layouts.Layout
29+ currentLayout int
30 }
31
32 func NewConcertina(i2c drivers.I2C) (*Concertina, error) {
33 // Initialize tone generator
34 if err := machine.DefaultUART.Configure(machine.UARTConfig{
35 BaudRate: 31250,
36- TX: VS1053_TX,
37- RX: VS1053_RX,
38+ TX: VS1053_TX,
39+ RX: VS1053_RX,
40 }); err != nil {
41 return nil, err
42 }
43@@ -40,56 +46,59 @@ func NewConcertina(i2c drivers.I2C) (*Concertina, error) {
44 return nil, err
45 }
46
47- c := &Concertina {
48+ c := &Concertina{
49 tonegen: MidiWriter{Writer: machine.DefaultUART},
50 }
51
52- for i := range(4) {
53+ for i := range c.expanders {
54 c.expanders[i] = pcf8575.Device{
55- Addr: 0x20,
56- I2C: i2c,
57+ Addr: uint16(0x20 + i),
58+ I2C: i2c,
59 }
60 }
61
62- <-resetTimer // Wait until this timer has elapsed
63- VS1053_RESET.High()
64+ if false {
65+ if l, err := layouts.DefaultLayouts(); err != nil {
66+ return nil, err
67+ } else {
68+ c.layouts = l
69+ }
70+ }
71
72 c.display = ssd1306.NewI2C(i2c)
73 c.display.Configure(
74 ssd1306.Config{
75- Width: 128,
76- Height: 32,
77+ Width: 128,
78+ Height: 32,
79 Address: 0x3C,
80 },
81 )
82 c.display.ClearDisplay()
83+ tinyfont.WriteLine(c.display, &proggy.TinySZ8pt7b, 0, 20, "Ruby", White)
84 c.display.Display()
85
86+ <-resetTimer // Wait until this timer has elapsed
87+ VS1053_RESET.High()
88
89- c.tonegen.SetPatch(22) // General MIDI harmonica
90+ c.tonegen.SetPatch(22) // General MIDI harmonica
91
92 return c, nil
93 }
94
95-var x int16
96 func (c *Concertina) Loop() {
97 var buttons [4]uint16
98
99- led.Builtin.SetColor(color.RGBA{uint8(x % 2), 0, 0, 0})
100-
101- c.display.ClearBuffer()
102- for i := range(4) {
103- buttons[i] = c.expanders[i].Get()
104- for bit := range(16) {
105+ c.display.FillRectangle(124, 0, 4, 16, Black)
106+ for x := range 4 {
107+ buttons[x] = c.expanders[x].Get()
108+ for bit := range 16 {
109 pc := White
110- if buttons[i] & (1<<bit) != 0 {
111+ if buttons[x]&(1<<bit) != 0 {
112 pc = Black
113 }
114- c.display.SetPixel(int16(bit), int16(16+3*i), pc)
115+ c.display.SetPixel(int16(124+x), int16(bit), pc)
116 }
117 }
118- c.display.FillRectangle(x, 0, 5, 5, White)
119- x = (x + 1) % 120
120 c.display.Display()
121
122 //c.tonegen.NoteOn(byte(x))
123@@ -100,7 +109,7 @@ func (c *Concertina) Loop() {
124 func main() {
125 // Blink the LED during startup.
126 blinkCtx, blinkCancel := context.WithCancel(context.Background())
127- go led.Flash(blinkCtx, led.Builtin, time.Second / 4, time.Second / 4)
128+ go led.Flash(blinkCtx, led.Builtin, time.Second/4, time.Second/4)
129
130 c, err := NewConcertina(machine.I2C0)
131 if err != nil {
132@@ -112,9 +121,7 @@ func main() {
133
134 // Okay, you can stop blinking now
135 blinkCancel()
136- //led.Builtin.Disable()
137-
138- led.Builtin.SetColor(color.RGBA{0, 0, 10, 0})
139+ led.Builtin.Disable()
140
141 for {
142 c.Loop()
+0,
-12
1@@ -1,12 +0,0 @@
2-package main
3-
4-import (
5- "tinygo.org/x/tinyfont"
6- "tinygo.org/x/tinyfont/gophers"
7-)
8-
9-func (c *Concertina) Print(s string) {
10- c.display.ClearDisplay()
11- tinyfont.WriteLine(c.display, &gophers.Regular14pt, 18, 90, s, Black)
12- c.display.Display()
13-}
+18,
-1
1@@ -5,10 +5,12 @@ import "io"
2 type MidiWriter struct {
3 io.Writer
4 Channel byte
5+ Playing *MidiNotes
6 }
7
8 func (w MidiWriter) NoteOnVelocity(note byte, velocity byte) {
9 w.Write([]byte{0x90 + w.Channel, note, velocity})
10+ w.Playing.On(note)
11 }
12
13 func (w MidiWriter) NoteOn(note byte) {
14@@ -17,12 +19,27 @@ func (w MidiWriter) NoteOn(note byte) {
15
16 func (w MidiWriter) NoteOffVelocity(note byte, velocity byte) {
17 w.Write([]byte{0x80 + w.Channel, note, velocity})
18+ w.Playing.Off(note)
19 }
20
21 func (w MidiWriter) NoteOff(note byte) {
22 w.NoteOffVelocity(note, 127)
23 }
24-
25+
26 func (w MidiWriter) SetPatch(patch byte) {
27 w.Write([]byte{0xC0 + w.Channel, patch})
28 }
29+
30+type MidiNotes [2]uint64
31+
32+func (n *MidiNotes) Equal(a MidiNotes) bool {
33+ return (n[0] == a[0]) && (n[1] == a[1])
34+}
35+
36+func (n *MidiNotes) On(note byte) {
37+ n[note/64] |= 1 << (note % 64)
38+}
39+
40+func (n *MidiNotes) Off(note byte) {
41+ n[note/64] &= ^(1 << (note % 64))
42+}
M
go.mod
+1,
-1
1@@ -4,7 +4,7 @@ go 1.24.4
2
3 require (
4 tinygo.org/x/drivers v0.34.0
5- tinygo.org/x/tinyfont v0.3.0
6+ tinygo.org/x/tinyfont v0.6.0
7 )
8
9 require github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
M
go.sum
+2,
-2
1@@ -2,5 +2,5 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU
2 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
3 tinygo.org/x/drivers v0.34.0 h1:lw8ePJeUSn9oICKBvQXHC9TIE+J00OfXfkGTrpXM9Iw=
4 tinygo.org/x/drivers v0.34.0/go.mod h1:ZdErNrApSABdVXjA1RejD67R8SNRI6RKVfYgQDZtKtk=
5-tinygo.org/x/tinyfont v0.3.0 h1:HIRLQoI3oc+2CMhPcfv+Ig88EcTImE/5npjqOnMD4lM=
6-tinygo.org/x/tinyfont v0.3.0/go.mod h1:+TV5q0KpwSGRWnN+ITijsIhrWYJkoUCp9MYELjKpAXk=
7+tinygo.org/x/tinyfont v0.6.0 h1:GibXDSFz6xrWnEDkDRo6vsbOyRw0MVj/eza3zNHMSHs=
8+tinygo.org/x/tinyfont v0.6.0/go.mod h1:onflMSkpWl7r7j4MIqhPEVV39pn7yL4N3MOePl3G+G8=