Skip to content

Commit 2036de6

Browse files
committed
UI basics working.
1 parent 9f60164 commit 2036de6

File tree

18 files changed

+524
-95
lines changed

18 files changed

+524
-95
lines changed

config/config.go renamed to config/main.go

+39-5
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,50 @@ package config
22

33
import "machine"
44

5+
// MIDI config
6+
const (
7+
PIN_MIDI_TX = machine.UART0_TX_PIN
8+
PIN_MIDI_RX = machine.UART0_RX_PIN
9+
)
10+
11+
var (
12+
MIDI_UART = machine.UART0
13+
)
14+
15+
// Display & I2C config
516
const (
617
PIN_I2C_SDA = machine.GP26
718
PIN_I2C_SCL = machine.GP27
819

9-
PIN_MIDI_TX = machine.UART0_TX_PIN
10-
PIN_MIDI_RX = machine.UART0_RX_PIN
20+
DISPLAY_WIDTH = 128
21+
DISPLAY_HEIGHT = 32
22+
DISPLAY_I2C_ADDRESS = 0x3c
1123

24+
EXPANDER_I2C_ADDRESS = 0x20
25+
26+
// The following are pins on the i2c expander
27+
ENCODER1_PIN1 = 3
28+
ENCODER1_PIN2 = 4
29+
ENCODER1_BUTTON = 5
30+
ENCODER2_PIN1 = 0
31+
ENCODER2_PIN2 = 1
32+
ENCODER2_BUTTON = 2
33+
ENCODER3_PIN1 = 11
34+
ENCODER3_PIN2 = 12
35+
ENCODER3_BUTTON = 13
36+
ENCODER4_PIN1 = 8
37+
ENCODER4_PIN2 = 9
38+
ENCODER4_BUTTON = 10
39+
)
40+
41+
var (
42+
MAIN_I2C = machine.I2C1
43+
44+
ENCODER_OFFSETS = [4]int{ENCODER1_PIN1, ENCODER2_PIN1, ENCODER3_PIN1, ENCODER4_PIN1}
45+
)
46+
47+
// SID config
48+
const (
1249
PIN_SID_RW = machine.GP18
1350
PIN_SID_PHI2 = machine.GP28
1451

@@ -20,9 +57,6 @@ const (
2057
)
2158

2259
var (
23-
MAIN_I2C = machine.I2C1
24-
MIDI_UART = machine.UART0
25-
2660
// Pin 28 is PWM6
2761
SID_PWM = machine.PWM6
2862

go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
module github.com/litui/monosid
22

3-
go 1.21.7
3+
go 1.20
44

55
require (
66
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
77
github.com/lunux2008/xulu v0.0.0-20160308154621-fff51ca7218e // indirect
88
tinygo.org/x/drivers v0.26.0 // indirect
99
tinygo.org/x/tinydraw v0.4.0 // indirect
1010
tinygo.org/x/tinyfont v0.4.0 // indirect
11+
tinygo.org/x/tinyfs v0.3.0 // indirect
1112
)

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ tinygo.org/x/tinydraw v0.4.0 h1:U9V0mHz8/jPShKjlh199vCfq1ARFyUOD1b+FfqIwV8c=
88
tinygo.org/x/tinydraw v0.4.0/go.mod h1:WCV/EMljTv8w04iAxjv+fRD6/4ffx0afATYeJlN90Yo=
99
tinygo.org/x/tinyfont v0.4.0 h1:XexPKEKiHInf6p4CMCJwsIheVPY0T46HUs6ictYyZfE=
1010
tinygo.org/x/tinyfont v0.4.0/go.mod h1:7nVj3j3geqBoPDzpFukAhF1C8AP9YocMsZy0HSAcGCA=
11+
tinygo.org/x/tinyfs v0.3.0 h1:7GjwuDYOKTJeiCVFT7DfukdFyj/vi0jK4iMZ703AofE=
12+
tinygo.org/x/tinyfs v0.3.0/go.mod h1:07HkxHkz69kYVrAiLS96RIjuDytVY6tOJ0mH8e5cKa0=

graphics/graphics.go

-38
This file was deleted.

led/main.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package led
2+
3+
import (
4+
"machine"
5+
"runtime"
6+
)
7+
8+
var (
9+
led = machine.LED
10+
state bool
11+
)
12+
13+
// Change LED state so it flashes once
14+
func Flash() {
15+
state = true
16+
}
17+
18+
// Monitors state of LED and flashes it if state changes
19+
func Task() {
20+
state = false
21+
22+
led.Configure(machine.PinConfig{
23+
Mode: machine.PinOutput,
24+
})
25+
led.Low()
26+
27+
for {
28+
if state {
29+
led.High()
30+
for i := 0; i < 1000; i++ {
31+
runtime.Gosched()
32+
}
33+
34+
led.Low()
35+
for i := 0; i < 1000; i++ {
36+
runtime.Gosched()
37+
}
38+
state = false
39+
}
40+
41+
runtime.Gosched()
42+
}
43+
}

log/main.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package log
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
const (
8+
MaxLogSize = 10
9+
VisibleLogLines = 4
10+
)
11+
12+
var (
13+
LogLines []string
14+
logReady bool = false
15+
)
16+
17+
// Write new log line to display buffer
18+
func Logf(format string, a ...any) {
19+
if !logReady {
20+
return
21+
}
22+
23+
formatted := fmt.Sprintf(format, a...)
24+
25+
LogLines = append(LogLines, formatted)
26+
for len(LogLines) > MaxLogSize {
27+
LogLines = LogLines[1:]
28+
}
29+
}
30+
31+
func InitLog() {
32+
LogLines = make([]string, 0)
33+
logReady = true
34+
}

main.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@ package main
33
import (
44
"time"
55

6-
"github.com/litui/monosid/graphics"
6+
"github.com/litui/monosid/led"
7+
"github.com/litui/monosid/log"
78
"github.com/litui/monosid/midi"
89
"github.com/litui/monosid/sid"
10+
"github.com/litui/monosid/ui"
911
)
1012

1113
func main() {
14+
log.InitLog()
15+
1216
i2c := i2cInit()
1317
uart := uartInit()
1418

15-
go graphics.Task(i2c)
19+
go led.Task()
20+
go ui.Task(i2c)
21+
1622
go midi.Task(uart)
1723
go sid.Task()
1824

midi/handlers.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package midi
22

3-
func handleNoteOff(channel uint8, note uint8, velocity uint8) {
3+
import (
4+
"github.com/litui/monosid/led"
5+
"github.com/litui/monosid/log"
6+
)
47

8+
func handleNoteOff(channel uint8, note uint8, velocity uint8) {
9+
led.Flash()
10+
log.Logf("NoteOff - Ch%d - %d - %d", channel, note, velocity)
511
}
612

713
func handleNoteOn(channel uint8, note uint8, velocity uint8) {
8-
14+
led.Flash()
15+
log.Logf("NoteOn - Ch%d - %d - %d", channel, note, velocity)
916
}
1017

1118
func handlePolyAftertouch(channel uint8, note uint8, pressure uint8) {

midi/midi.go renamed to midi/main.go

+4
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ package midi
33
import (
44
"machine"
55
"runtime"
6+
7+
"github.com/litui/monosid/log"
68
)
79

810
func Task(uart *machine.UART) {
11+
log.Logf("MIDI ready")
12+
913
for {
1014
processBuffer(uart)
1115

midi/processor.go

+49-43
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package midi
33
import (
44
"machine"
55
"runtime"
6-
7-
"github.com/lunux2008/xulu"
86
)
97

108
var (
@@ -14,68 +12,76 @@ var (
1412
inSysex bool = false
1513
)
1614

17-
// Determine what kind of midi message we're looking at and how to handle it
18-
func processBuffer(uart *machine.UART) {
19-
bc := uart.Buffered()
20-
if bc < 1 {
21-
return
22-
}
15+
func readNextByte(uart *machine.UART) byte {
16+
for {
17+
b, err := uart.ReadByte()
18+
if err == nil {
19+
return b
20+
}
2321

24-
var tempBuf []byte
25-
len, err := uart.Read(tempBuf)
26-
if err != nil {
27-
return
22+
runtime.Gosched()
2823
}
29-
xulu.Use(len)
24+
}
3025

31-
// continue receiving sysex message if mid-message
32-
for i := 0; i < len; i++ {
33-
nextByte := tempBuf[i]
26+
// Determine what kind of midi message we're looking at and how to handle it
27+
func processBuffer(uart *machine.UART) {
28+
for {
29+
b, err := uart.ReadByte()
30+
if err != nil {
31+
break
32+
}
3433

3534
// Assume we're still receiving sysex until the end byte
3635
if inSysex {
37-
if nextByte == MsgSysExEnd {
36+
if b == MsgSysExEnd {
3837
inSysex = false
3938
handleSysex()
4039

4140
} else {
42-
sysexBuffer = append(sysexBuffer, nextByte)
41+
sysexBuffer = append(sysexBuffer, b)
4342
sysexLen++
4443
}
4544
} else {
46-
if nextByte == MsgSysExStart {
45+
if b == MsgSysExStart {
4746
// prepare for receiving sysex message
4847
sysexLen = 0
4948
inSysex = true
5049

5150
} else {
52-
msgType := nextByte & 0xF0
53-
channel := nextByte & 0xF
54-
if i+2 < len {
55-
switch msgType {
56-
case MsgNoteOff:
57-
handleNoteOff(channel, tempBuf[i+1], tempBuf[i+2])
58-
case MsgNoteOn:
59-
handleNoteOn(channel, tempBuf[i+1], tempBuf[i+2])
60-
case MsgPolyAftertouch:
61-
handlePolyAftertouch(channel, tempBuf[i+1], tempBuf[i+2])
62-
case MsgControlChange:
63-
handleControlChange(channel, tempBuf[i+1], tempBuf[i+2])
64-
case MsgPitchBend:
65-
pitchBend := (int16(tempBuf[i+1]&0x7f) | int16(tempBuf[i+1]&0x7f)<<7) - 0x2000
66-
handlePitchBend(channel, pitchBend)
67-
}
68-
}
69-
if i+1 < len {
70-
switch msgType {
71-
case MsgProgramChange:
72-
handleProgramChange(channel, tempBuf[i+1])
73-
case MsgChannelAftertouch:
74-
handleChannelAftertouch(channel, tempBuf[i+1])
75-
}
51+
msgType := b & 0xF0
52+
channel := b & 0xF
53+
switch msgType {
54+
case MsgNoteOff:
55+
note := readNextByte(uart)
56+
velocity := readNextByte(uart)
57+
handleNoteOff(channel, note, velocity)
58+
case MsgNoteOn:
59+
note := readNextByte(uart)
60+
velocity := readNextByte(uart)
61+
handleNoteOn(channel, note, velocity)
62+
case MsgPolyAftertouch:
63+
note := readNextByte(uart)
64+
pressure := readNextByte(uart)
65+
handlePolyAftertouch(channel, note, pressure)
66+
case MsgControlChange:
67+
cc := readNextByte(uart)
68+
value := readNextByte(uart)
69+
handleControlChange(channel, cc, value)
70+
case MsgPitchBend:
71+
pbLow := readNextByte(uart)
72+
pbHigh := readNextByte(uart)
73+
pitchBend := (int16(pbLow&0x7f) | int16(pbHigh&0x7f)<<7) - 0x2000
74+
handlePitchBend(channel, pitchBend)
75+
case MsgProgramChange:
76+
program := readNextByte(uart)
77+
handleProgramChange(channel, program)
78+
case MsgChannelAftertouch:
79+
pressure := readNextByte(uart)
80+
handleChannelAftertouch(channel, pressure)
7681
}
7782
}
7883
}
84+
7985
runtime.Gosched()
8086
}
8187
}

0 commit comments

Comments
 (0)