Skip to content

Commit a2c4dbd

Browse files
authored
Merge pull request #29 from sago35/conf2025badge
Add targets/conf2025badge
2 parents 02a948c + 4487197 commit a2c4dbd

File tree

3 files changed

+300
-14
lines changed

3 files changed

+300
-14
lines changed

Makefile

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
smoketest: FORCE
22
mkdir -p out
3-
tinygo build -o ./out/all.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./games/all/
4-
tinygo build -o ./out/flappygopher.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./games/flappygopher/
5-
tinygo build -o ./out/jumpingopher.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./games/jumpingopher/
6-
tinygo build -o ./out/blocks.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./games/blocks/
7-
tinygo build -o ./out/example_GeoM.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./examples/GeoM/
8-
tinygo build -o ./out/example_drawing.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./examples/drawing/
9-
tinygo build -o ./out/all.gopher-badge.uf2 --size short --target gopher-badge ./games/all/
10-
tinygo build -o ./out/all.pybadge.uf2 --size short --target pybadge ./games/all/
11-
tinygo build -o ./out/all.wioterminal.uf2 --size short --target wioterminal ./games/all/
12-
tinygo build -o ./out/all.macropad-rp2040.uf2 --size short --target macropad-rp2040 ./games/all/
13-
tinygo build -o ./out/all.gopher-board-i2c.uf2 --size short --target ./targets/gopher-board-i2c.json ./games/all/
14-
tinygo build -o ./out/all.gopher-board-spi.uf2 --size short --target ./targets/gopher-board-spi.json ./games/all/
15-
tinygo build -o ./out/all.wasm --size short --target wasm --no-debug --panic trap ./games/all/
16-
tinygo build -o ./out/goradius.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./games/goradius/
3+
tinygo build -o ./out/all.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./games/all/
4+
tinygo build -o ./out/flappygopher.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./games/flappygopher/
5+
tinygo build -o ./out/jumpingopher.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./games/jumpingopher/
6+
tinygo build -o ./out/blocks.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./games/blocks/
7+
tinygo build -o ./out/example_GeoM.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./examples/GeoM/
8+
tinygo build -o ./out/example_drawing.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./examples/drawing/
9+
tinygo build -o ./out/all.gopher-badge.uf2 --size short --target gopher-badge ./games/all/
10+
tinygo build -o ./out/all.pybadge.uf2 --size short --target pybadge ./games/all/
11+
tinygo build -o ./out/all.wioterminal.uf2 --size short --target wioterminal ./games/all/
12+
tinygo build -o ./out/all.macropad-rp2040.uf2 --size short --target macropad-rp2040 ./games/all/
13+
tinygo build -o ./out/all.gopher-board-i2c.uf2 --size short --target ./targets/gopher-board-i2c.json ./games/all/
14+
tinygo build -o ./out/all.gopher-board-spi.uf2 --size short --target ./targets/gopher-board-spi.json ./games/all/
15+
tinygo build -o ./out/all.conf2025badge.uf2 --size short --target ./targets/conf2025badge.json ./games/all/
16+
tinygo build -o ./out/all.wasm --size short --target wasm --no-debug --panic trap ./games/all/
17+
tinygo build -o ./out/goradius.zero-kb02.uf2 --size short --target ./targets/zero-kb02.json ./games/goradius/
1718

1819
FORCE:

hardware/conf2025badge.go

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
//go:build tinygo && conf2025badge
2+
3+
package hardware
4+
5+
import (
6+
"machine"
7+
8+
"github.com/sago35/koebiten"
9+
"tinygo.org/x/drivers"
10+
"tinygo.org/x/drivers/encoders"
11+
"tinygo.org/x/drivers/ssd1306"
12+
)
13+
14+
var Device = CONF2025BADGE{}
15+
16+
type CONF2025BADGE struct {
17+
}
18+
19+
func (z CONF2025BADGE) Init() error {
20+
return Init()
21+
}
22+
23+
func (z CONF2025BADGE) GetDisplay() koebiten.Displayer {
24+
return Display
25+
}
26+
27+
func (z CONF2025BADGE) KeyUpdate() error {
28+
return keyUpdate()
29+
}
30+
31+
var (
32+
Display *ssd1306.Device
33+
)
34+
35+
var (
36+
colPins []machine.Pin
37+
rowPins []machine.Pin
38+
rotaryPins []machine.Pin
39+
gpioPins []machine.Pin
40+
adcPins []ADCDevice
41+
enc *encoders.QuadratureDevice
42+
encOld int
43+
state []State
44+
cycle []int
45+
duration []int
46+
invertRotaryPins = false
47+
keybuf [1]koebiten.Key
48+
)
49+
50+
const (
51+
debounce = 0
52+
)
53+
54+
type State uint8
55+
56+
const (
57+
None State = iota
58+
NoneToPress
59+
Press
60+
PressToRelease
61+
)
62+
63+
type ADCDevice struct {
64+
ADC machine.ADC
65+
PressedFunc func() bool
66+
}
67+
68+
func (a ADCDevice) Get() bool {
69+
return a.PressedFunc()
70+
}
71+
72+
func Init() error {
73+
machine.InitADC()
74+
ax := machine.ADC{Pin: machine.GPIO27}
75+
ay := machine.ADC{Pin: machine.GPIO26}
76+
ax.Configure(machine.ADCConfig{})
77+
ay.Configure(machine.ADCConfig{})
78+
79+
adcPins = []ADCDevice{
80+
{ADC: ax, PressedFunc: func() bool { return ax.Get() < 0x3000 }}, // left
81+
{ADC: ax, PressedFunc: func() bool { return 0xC800 < ax.Get() }}, // right
82+
{ADC: ay, PressedFunc: func() bool { return 0xC800 < ay.Get() }}, // up
83+
{ADC: ay, PressedFunc: func() bool { return ay.Get() < 0x3000 }}, // down
84+
}
85+
86+
i2c := machine.I2C1
87+
i2c.Configure(machine.I2CConfig{
88+
Frequency: 2_800_000,
89+
SDA: machine.GPIO6,
90+
SCL: machine.GPIO7,
91+
})
92+
93+
d := ssd1306.NewI2C(i2c)
94+
d.Configure(ssd1306.Config{
95+
Address: 0x3C,
96+
Width: 128,
97+
Height: 64,
98+
})
99+
d.SetRotation(drivers.Rotation0)
100+
d.ClearDisplay()
101+
Display = d
102+
103+
gpioPins = []machine.Pin{
104+
machine.GPIO28,
105+
machine.GPIO29,
106+
machine.GPIO2, // rotary
107+
}
108+
109+
for _, p := range gpioPins {
110+
p.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
111+
}
112+
113+
rotaryPins = []machine.Pin{
114+
machine.GPIO3,
115+
machine.GPIO4,
116+
}
117+
118+
if invertRotaryPins {
119+
rotaryPins = []machine.Pin{
120+
machine.GPIO4,
121+
machine.GPIO3,
122+
}
123+
}
124+
enc = encoders.NewQuadratureViaInterrupt(rotaryPins[0], rotaryPins[1])
125+
126+
enc.Configure(encoders.QuadratureConfig{
127+
Precision: 4,
128+
})
129+
130+
state = make([]State, koebiten.KeyDown+1)
131+
cycle = make([]int, koebiten.KeyDown+1)
132+
duration = make([]int, koebiten.KeyDown+1)
133+
134+
return nil
135+
}
136+
137+
func keyUpdate() error {
138+
keyGpioUpdate()
139+
keyRotaryUpdate()
140+
keyJoystickUpdate()
141+
return nil
142+
}
143+
144+
func keyGpioUpdate() {
145+
buf := keybuf[:]
146+
for r := range gpioPins {
147+
current := !gpioPins[r].Get()
148+
idx := r + int(koebiten.Key0)
149+
150+
switch state[idx] {
151+
case None:
152+
if current {
153+
if cycle[idx] >= debounce {
154+
state[idx] = NoneToPress
155+
cycle[idx] = 0
156+
} else {
157+
cycle[idx]++
158+
}
159+
} else {
160+
cycle[idx] = 0
161+
}
162+
case NoneToPress:
163+
state[idx] = Press
164+
buf[0] = koebiten.Key(idx)
165+
koebiten.AppendJustPressedKeys(buf)
166+
case Press:
167+
buf[0] = koebiten.Key(idx)
168+
koebiten.AppendPressedKeys(buf)
169+
if current {
170+
cycle[idx] = 0
171+
duration[idx]++
172+
} else {
173+
if cycle[idx] >= debounce {
174+
state[idx] = PressToRelease
175+
cycle[idx] = 0
176+
duration[idx] = 0
177+
} else {
178+
cycle[idx]++
179+
}
180+
}
181+
case PressToRelease:
182+
state[idx] = None
183+
buf[0] = koebiten.Key(idx)
184+
koebiten.AppendJustReleasedKeys(buf)
185+
}
186+
}
187+
}
188+
189+
func keyRotaryUpdate() {
190+
rot := []bool{false, false}
191+
if newValue := enc.Position(); newValue != encOld {
192+
if newValue < encOld {
193+
rot[0] = true
194+
} else {
195+
rot[1] = true
196+
}
197+
encOld = newValue
198+
}
199+
200+
buf := keybuf[:]
201+
for c, current := range rot {
202+
idx := c + int(koebiten.KeyRotaryLeft)
203+
switch state[idx] {
204+
case None:
205+
if current {
206+
state[idx] = NoneToPress
207+
} else {
208+
}
209+
case NoneToPress:
210+
if current {
211+
state[idx] = Press
212+
} else {
213+
state[idx] = PressToRelease
214+
}
215+
buf[0] = koebiten.Key(idx)
216+
koebiten.AppendJustPressedKeys(buf)
217+
case Press:
218+
buf[0] = koebiten.Key(idx)
219+
koebiten.AppendPressedKeys(buf)
220+
if current {
221+
} else {
222+
state[idx] = PressToRelease
223+
}
224+
case PressToRelease:
225+
if current {
226+
state[idx] = NoneToPress
227+
} else {
228+
state[idx] = None
229+
}
230+
buf[0] = koebiten.Key(idx)
231+
koebiten.AppendJustReleasedKeys(buf)
232+
}
233+
}
234+
}
235+
236+
func keyJoystickUpdate() {
237+
buf := keybuf[:]
238+
for r, p := range adcPins {
239+
current := p.Get()
240+
idx := r + int(koebiten.KeyLeft)
241+
242+
switch state[idx] {
243+
case None:
244+
if current {
245+
if cycle[idx] >= debounce {
246+
state[idx] = NoneToPress
247+
cycle[idx] = 0
248+
} else {
249+
cycle[idx]++
250+
}
251+
} else {
252+
cycle[idx] = 0
253+
}
254+
case NoneToPress:
255+
state[idx] = Press
256+
buf[0] = koebiten.Key(idx)
257+
koebiten.AppendJustPressedKeys(buf)
258+
case Press:
259+
buf[0] = koebiten.Key(idx)
260+
koebiten.AppendPressedKeys(buf)
261+
if current {
262+
cycle[idx] = 0
263+
duration[idx]++
264+
} else {
265+
if cycle[idx] >= debounce {
266+
state[idx] = PressToRelease
267+
cycle[idx] = 0
268+
duration[idx] = 0
269+
} else {
270+
cycle[idx]++
271+
}
272+
}
273+
case PressToRelease:
274+
state[idx] = None
275+
buf[0] = koebiten.Key(idx)
276+
koebiten.AppendJustReleasedKeys(buf)
277+
}
278+
}
279+
}

targets/conf2025badge.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"inherits": [
3+
"xiao-rp2040"
4+
],
5+
"build-tags": ["conf2025badge"]
6+
}

0 commit comments

Comments
 (0)