mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-15 00:13:43 +00:00
machine/usb: move MIDI under usb/adc (Audio Device Class) package
Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
// package adc is for USB Audio Device Class devices.
|
||||
package adc
|
||||
@@ -0,0 +1,52 @@
|
||||
package midi
|
||||
|
||||
import (
|
||||
"runtime/volatile"
|
||||
)
|
||||
|
||||
const bufferSize = 128
|
||||
|
||||
// RingBuffer is ring buffer implementation inspired by post at
|
||||
// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php
|
||||
type RingBuffer struct {
|
||||
rxbuffer [bufferSize][4]byte
|
||||
head volatile.Register8
|
||||
tail volatile.Register8
|
||||
}
|
||||
|
||||
// NewRingBuffer returns a new ring buffer.
|
||||
func NewRingBuffer() *RingBuffer {
|
||||
return &RingBuffer{}
|
||||
}
|
||||
|
||||
// Used returns how many bytes in buffer have been used.
|
||||
func (rb *RingBuffer) Used() uint8 {
|
||||
return uint8(rb.head.Get() - rb.tail.Get())
|
||||
}
|
||||
|
||||
// Put stores a byte in the buffer. If the buffer is already
|
||||
// full, the method will return false.
|
||||
func (rb *RingBuffer) Put(val []byte) bool {
|
||||
if rb.Used() != bufferSize {
|
||||
rb.head.Set(rb.head.Get() + 1)
|
||||
copy(rb.rxbuffer[rb.head.Get()%bufferSize][:], val)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Get returns a byte from the buffer. If the buffer is empty,
|
||||
// the method will return a false as the second value.
|
||||
func (rb *RingBuffer) Get() ([]byte, bool) {
|
||||
if rb.Used() != 0 {
|
||||
rb.tail.Set(rb.tail.Get() + 1)
|
||||
return rb.rxbuffer[rb.tail.Get()%bufferSize][:], true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Clear resets the head and tail pointer to zero.
|
||||
func (rb *RingBuffer) Clear() {
|
||||
rb.head.Set(0)
|
||||
rb.tail.Set(0)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package midi
|
||||
|
||||
// NoteOn sends a note on message.
|
||||
func (m *midi) NoteOn(cable, channel uint8, note Note, velocity uint8) {
|
||||
m.msg[0], m.msg[1], m.msg[2], m.msg[3] = (cable&0xf<<4)|0x9, 0x90|(channel&0xf), byte(note)&0x7f, velocity&0x7f
|
||||
m.Write(m.msg[:])
|
||||
}
|
||||
|
||||
// NoteOff sends a note off message.
|
||||
func (m *midi) NoteOff(cable, channel uint8, note Note, velocity uint8) {
|
||||
m.msg[0], m.msg[1], m.msg[2], m.msg[3] = (cable&0xf<<4)|0x8, 0x80|(channel&0xf), byte(note)&0x7f, velocity&0x7f
|
||||
m.Write(m.msg[:])
|
||||
}
|
||||
|
||||
// SendCC sends a continuous controller message.
|
||||
func (m *midi) SendCC(cable, channel, control, value uint8) {
|
||||
m.msg[0], m.msg[1], m.msg[2], m.msg[3] = (cable&0xf<<4)|0xB, 0xB0|(channel&0xf), control&0x7f, value&0x7f
|
||||
m.Write(m.msg[:])
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package midi
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"machine/usb"
|
||||
)
|
||||
|
||||
const (
|
||||
midiEndpointOut = usb.MIDI_ENDPOINT_OUT // from PC
|
||||
midiEndpointIn = usb.MIDI_ENDPOINT_IN // to PC
|
||||
)
|
||||
|
||||
var Midi *midi
|
||||
|
||||
type midi struct {
|
||||
msg [4]byte
|
||||
buf *RingBuffer
|
||||
rxHandler func([]byte)
|
||||
waitTxc bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
if Midi == nil {
|
||||
Midi = newMidi()
|
||||
}
|
||||
}
|
||||
|
||||
// New returns the USB MIDI port.
|
||||
// Deprecated, better to just use Port()
|
||||
func New() *midi {
|
||||
return Port()
|
||||
}
|
||||
|
||||
// Port returns the USB midi port.
|
||||
func Port() *midi {
|
||||
return Midi
|
||||
}
|
||||
|
||||
func newMidi() *midi {
|
||||
m := &midi{
|
||||
buf: NewRingBuffer(),
|
||||
}
|
||||
machine.EnableMIDI(m.Handler, m.RxHandler, nil)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *midi) SetHandler(rxHandler func([]byte)) {
|
||||
m.rxHandler = rxHandler
|
||||
}
|
||||
|
||||
func (m *midi) Write(b []byte) (n int, err error) {
|
||||
i := 0
|
||||
for i = 0; i < len(b); i += 4 {
|
||||
m.tx(b[i : i+4])
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// sendUSBPacket sends a MIDIPacket.
|
||||
func (m *midi) sendUSBPacket(b []byte) {
|
||||
machine.SendUSBInPacket(midiEndpointIn, b)
|
||||
}
|
||||
|
||||
// from BulkIn
|
||||
func (m *midi) Handler() {
|
||||
m.waitTxc = false
|
||||
if b, ok := m.buf.Get(); ok {
|
||||
m.waitTxc = true
|
||||
m.sendUSBPacket(b)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *midi) tx(b []byte) {
|
||||
if machine.USBDev.InitEndpointComplete {
|
||||
if m.waitTxc {
|
||||
m.buf.Put(b)
|
||||
} else {
|
||||
m.waitTxc = true
|
||||
m.sendUSBPacket(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// from BulkOut
|
||||
func (m *midi) RxHandler(b []byte) {
|
||||
if m.rxHandler != nil {
|
||||
m.rxHandler(b)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package midi
|
||||
|
||||
// Note represents a MIDI note number. For example, Note(69) is A4 or 440Hz.
|
||||
type Note uint8
|
||||
|
||||
// Define all the notes in a format similar to the Tone library in the Arduino
|
||||
// IDE.
|
||||
const (
|
||||
A0 Note = iota + 21 // 27.5Hz
|
||||
AS0
|
||||
B0
|
||||
C1
|
||||
CS1
|
||||
D1
|
||||
DS1
|
||||
E1
|
||||
F1
|
||||
FS1
|
||||
G1
|
||||
GS1
|
||||
A1 // 55Hz
|
||||
AS1
|
||||
B1
|
||||
C2
|
||||
CS2
|
||||
D2
|
||||
DS2
|
||||
E2
|
||||
F2
|
||||
FS2
|
||||
G2
|
||||
GS2
|
||||
A2 // 110Hz
|
||||
AS2
|
||||
B2
|
||||
C3
|
||||
CS3
|
||||
D3
|
||||
DS3
|
||||
E3
|
||||
F3
|
||||
FS3
|
||||
G3
|
||||
GS3
|
||||
A3 // 220Hz
|
||||
AS3
|
||||
B3
|
||||
C4
|
||||
CS4
|
||||
D4
|
||||
DS4
|
||||
E4
|
||||
F4
|
||||
FS4
|
||||
G4
|
||||
GS4
|
||||
A4 // 440Hz
|
||||
AS4
|
||||
B4
|
||||
C5
|
||||
CS5
|
||||
D5
|
||||
DS5
|
||||
E5
|
||||
F5
|
||||
FS5
|
||||
G5
|
||||
GS5
|
||||
A5 // 880Hz
|
||||
AS5
|
||||
B5
|
||||
C6
|
||||
CS6
|
||||
D6
|
||||
DS6
|
||||
E6
|
||||
F6
|
||||
FS6
|
||||
G6
|
||||
GS6
|
||||
A6 // 1760Hz
|
||||
AS6
|
||||
B6
|
||||
C7
|
||||
CS7
|
||||
D7
|
||||
DS7
|
||||
E7
|
||||
F7
|
||||
FS7
|
||||
G7
|
||||
GS7
|
||||
A7 // 3520Hz
|
||||
AS7
|
||||
B7
|
||||
C8
|
||||
CS8
|
||||
D8
|
||||
DS8
|
||||
E8
|
||||
F8
|
||||
FS8
|
||||
G8
|
||||
GS8
|
||||
A8 // 7040Hz
|
||||
AS8
|
||||
B8
|
||||
)
|
||||
Reference in New Issue
Block a user