github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/usb/adc/midi/midi.go (about)

     1  package midi
     2  
     3  import (
     4  	"machine"
     5  	"machine/usb"
     6  	"machine/usb/descriptor"
     7  )
     8  
     9  const (
    10  	midiEndpointOut = usb.MIDI_ENDPOINT_OUT // from PC
    11  	midiEndpointIn  = usb.MIDI_ENDPOINT_IN  // to PC
    12  )
    13  
    14  var Midi *midi
    15  
    16  type midi struct {
    17  	msg       [4]byte
    18  	buf       *RingBuffer
    19  	rxHandler func([]byte)
    20  	txHandler func()
    21  	waitTxc   bool
    22  }
    23  
    24  func init() {
    25  	if Midi == nil {
    26  		Midi = newMidi()
    27  	}
    28  }
    29  
    30  // New returns the USB MIDI port.
    31  // Deprecated, better to just use Port()
    32  func New() *midi {
    33  	return Port()
    34  }
    35  
    36  // Port returns the USB midi port.
    37  func Port() *midi {
    38  	return Midi
    39  }
    40  
    41  func newMidi() *midi {
    42  	m := &midi{
    43  		buf: NewRingBuffer(),
    44  	}
    45  	machine.ConfigureUSBEndpoint(descriptor.CDCMIDI,
    46  		[]usb.EndpointConfig{
    47  			{
    48  				Index:     usb.MIDI_ENDPOINT_OUT,
    49  				IsIn:      false,
    50  				Type:      usb.ENDPOINT_TYPE_BULK,
    51  				RxHandler: m.RxHandler,
    52  			},
    53  			{
    54  				Index:     usb.MIDI_ENDPOINT_IN,
    55  				IsIn:      true,
    56  				Type:      usb.ENDPOINT_TYPE_BULK,
    57  				TxHandler: m.TxHandler,
    58  			},
    59  		},
    60  		[]usb.SetupConfig{},
    61  	)
    62  	return m
    63  }
    64  
    65  // SetHandler is now deprecated, please use SetRxHandler().
    66  func (m *midi) SetHandler(rxHandler func([]byte)) {
    67  	m.SetRxHandler(rxHandler)
    68  }
    69  
    70  // SetRxHandler sets the handler function for incoming MIDI messages.
    71  func (m *midi) SetRxHandler(rxHandler func([]byte)) {
    72  	m.rxHandler = rxHandler
    73  }
    74  
    75  // SetTxHandler sets the handler function for outgoing MIDI messages.
    76  func (m *midi) SetTxHandler(txHandler func()) {
    77  	m.txHandler = txHandler
    78  }
    79  
    80  func (m *midi) Write(b []byte) (n int, err error) {
    81  	s, e := 0, 0
    82  	for s = 0; s < len(b); s += 4 {
    83  		e = s + 4
    84  		if e > len(b) {
    85  			e = len(b)
    86  		}
    87  
    88  		m.tx(b[s:e])
    89  	}
    90  	return e, nil
    91  }
    92  
    93  // sendUSBPacket sends a MIDIPacket.
    94  func (m *midi) sendUSBPacket(b []byte) {
    95  	machine.SendUSBInPacket(midiEndpointIn, b)
    96  }
    97  
    98  // from BulkIn
    99  func (m *midi) TxHandler() {
   100  	if m.txHandler != nil {
   101  		m.txHandler()
   102  	}
   103  
   104  	m.waitTxc = false
   105  	if b, ok := m.buf.Get(); ok {
   106  		m.waitTxc = true
   107  		m.sendUSBPacket(b)
   108  	}
   109  }
   110  
   111  func (m *midi) tx(b []byte) {
   112  	if machine.USBDev.InitEndpointComplete {
   113  		if m.waitTxc {
   114  			m.buf.Put(b)
   115  		} else {
   116  			m.waitTxc = true
   117  			m.sendUSBPacket(b)
   118  		}
   119  	}
   120  }
   121  
   122  // from BulkOut
   123  func (m *midi) RxHandler(b []byte) {
   124  	if m.rxHandler != nil {
   125  		m.rxHandler(b)
   126  	}
   127  }