mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-07 20:43:40 +00:00
usb: add support for midi
This commit is contained in:
@@ -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,79 @@
|
||||
package midi
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
const (
|
||||
midiEndpointOut = 5 // from PC
|
||||
midiEndpointIn = 6 // to PC
|
||||
)
|
||||
|
||||
var Midi *midi
|
||||
|
||||
type midi struct {
|
||||
buf *RingBuffer
|
||||
callbackFuncRx func([]byte)
|
||||
waitTxc bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
if Midi == nil {
|
||||
Midi = newMidi()
|
||||
}
|
||||
}
|
||||
|
||||
// New returns hid-mouse.
|
||||
func New() *midi {
|
||||
return Midi
|
||||
}
|
||||
|
||||
func newMidi() *midi {
|
||||
m := &midi{
|
||||
buf: NewRingBuffer(),
|
||||
}
|
||||
machine.EnableMIDI(m.Callback, m.CallbackRx, nil)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *midi) SetCallback(callbackRx func([]byte)) {
|
||||
m.callbackFuncRx = callbackRx
|
||||
}
|
||||
|
||||
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) Callback() {
|
||||
m.waitTxc = false
|
||||
if b, ok := m.buf.Get(); ok {
|
||||
m.waitTxc = true
|
||||
m.sendUSBPacket(b)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *midi) tx(b []byte) {
|
||||
if m.waitTxc {
|
||||
m.buf.Put(b)
|
||||
} else {
|
||||
m.waitTxc = true
|
||||
m.sendUSBPacket(b)
|
||||
}
|
||||
}
|
||||
|
||||
// from BulkOut
|
||||
func (m *midi) CallbackRx(b []byte) {
|
||||
if m.callbackFuncRx != nil {
|
||||
m.callbackFuncRx(b)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user