MIDI support for libDaisy Nim wrapper
This module provides MIDI functionality for the Daisy Audio Platform.
Example - USB MIDI input:
import nimphea, hid/midi, per/uart var daisy = initDaisy() var midi: MidiUsbHandler initMidiUsb(midi) startLog() printLine("MIDI Input Started") while true: midi.listen() while midi.hasEvents: let event = midi.popEvent() case event.messageType of NoteOn: let note = event.note print("Note On: ") print(note.number) print(" Vel: ") printLine(note.velocity) of NoteOff: let note = event.note print("Note Off: ") printLine(note.number) of ControlChange: let cc = event.controlChange print("CC ") print(cc.number) print(": ") printLine(cc.value) else: discard daisy.delay(1)
Example - UART MIDI with output (TRS/DIN MIDI):
import nimphea, hid/midi var daisy = initDaisy() var midi: MidiUartHandler var config = newMidiUartConfig() config.transport_config.periph = USART_1 config.transport_config.rx = initPin(PIN_PORTB, 7) config.transport_config.tx = initPin(PIN_PORTB, 6) initMidiUart(midi, config) # Send a note on message var noteOn = [0x90'u8, 60, 100] # Channel 1, note C4, velocity 100 midi.sendMessage(noteOn[0].addr, 3) # Receive and echo messages while true: midi.listen() while midi.hasEvents: let event = midi.popEvent() # Process or echo the event
Types
ControlChangeEvent = object number*: uint8 value*: uint8
- Source Edit
GPIOPort {.importcpp: "daisy::GPIOPort", size: 4.} = enum PORTA = 0, PORTB = 1, PORTC = 2, PORTD = 3, PORTE = 4, PORTF = 5, PORTG = 6, PORTH = 7, PORTI = 8, PORTJ = 9, PORTK = 10, PORTX = 255
- Source Edit
MidiEvent {.importcpp: "daisy::MidiEvent", bycopy.} = object mType* {.importcpp: "type".}: MidiMessageType channel* {.importcpp: "channel".}: cint data* {.importcpp: "data".}: array[2, uint8]
- Source Edit
MidiMessageType {.importcpp: "daisy::MidiMessageType", size: 4.} = enum NoteOff, NoteOn, PolyphonicKeyPressure, ControlChange, ProgramChange, ChannelPressure, PitchBend, SystemCommon, SystemRealTime
- Source Edit
MidiUartHandler {.importcpp: "daisy::MidiUartHandler".} = object
- Source Edit
MidiUartHandlerConfig {.importcpp: "daisy::MidiUartHandler::Config", bycopy.} = object transport_config* {.importcpp: "transport_config".}: MidiUartTransportConfig
- Source Edit
MidiUartTransport {.importcpp: "daisy::MidiUartTransport".} = object
- Source Edit
MidiUartTransportConfig {.importcpp: "daisy::MidiUartTransport::Config", bycopy.} = object periph* {.importcpp: "periph".}: UartPeriph rx* {.importcpp: "rx".}: Pin tx* {.importcpp: "tx".}: Pin rx_buffer* {.importcpp: "rx_buffer".}: ptr uint8 rx_buffer_size* {.importcpp: "rx_buffer_size".}: csize_t
- Source Edit
MidiUsbHandler {.importcpp: "daisy::MidiHandler<daisy::MidiUsbTransport>".} = object
- Source Edit
MidiUsbHandlerConfig {.importcpp: "daisy::MidiHandler<daisy::MidiUsbTransport>::Config", bycopy.} = object
- Source Edit
MidiUsbTransport {.importcpp: "daisy::MidiUsbTransport".} = object
- Source Edit
Pin {.importcpp: "daisy::Pin", bycopy.} = object port* {.importcpp: "port".}: GPIOPort pin* {.importcpp: "pin".}: uint8
- Source Edit
UartPeriph {.importcpp: "daisy::UartHandler::Config::Peripheral", size: 4.} = enum USART_1, USART_2, USART_3, UART_4, UART_5, USART_6, UART_7, UART_8, LPUART_1
- Source Edit
Procs
proc channelPressure(event: var MidiEvent): uint8 {.inline, ...raises: [], tags: [], forbids: [].}
- Parse as channel pressure (0-127) Source Edit
proc controlChange(event: var MidiEvent): ControlChangeEvent {.inline, ...raises: [], tags: [], forbids: [].}
- Parse as control change event Source Edit
proc hasEvents(midi: var MidiUartHandler): bool {.inline, ...raises: [], tags: [], forbids: [].}
- Check if there are any UART MIDI events waiting Source Edit
proc hasEvents(midi: var MidiUsbHandler): bool {.inline, ...raises: [], tags: [], forbids: [].}
- Check if there are any USB MIDI events waiting Source Edit
proc initMidi(midi: var MidiUsbHandler) {....raises: [], tags: [], forbids: [].}
-
Backward-compatible alias for initMidiUsb
Deprecated: Use initMidiUsb() for clarity
Source Edit proc initMidiUart(midi: var MidiUartHandler; config: MidiUartHandlerConfig) {. ...raises: [], tags: [], forbids: [].}
-
Initialize MIDI handler for UART (TRS/DIN) MIDI
Usage:
var midi: MidiUartHandler var config = newMidiUartConfig() # Configure UART pins (example for USART1) config.transport_config.periph = USART_1 config.transport_config.rx = initPin(PIN_PORTB, 7) config.transport_config.tx = initPin(PIN_PORTB, 6) initMidiUart(midi, config)
Source Edit proc initMidiUsb(midi: var MidiUsbHandler) {....raises: [], tags: [], forbids: [].}
-
Initialize MIDI handler for USB MIDI
Usage:
var midi: MidiUsbHandler initMidiUsb(midi)
Source Edit proc listen(midi: var MidiUartHandler) {.inline, ...raises: [], tags: [], forbids: [].}
-
Process incoming UART MIDI data (call this regularly in your loop)
Note: This also handles UART error recovery
Source Edit proc listen(midi: var MidiUsbHandler) {.inline, ...raises: [], tags: [], forbids: [].}
- Process incoming USB MIDI data (call this regularly in your loop) Source Edit
proc makeMidiControlChange(channel: uint8; ccNumber: uint8; value: uint8): array[ 3, uint8] {.inline, ...raises: [], tags: [], forbids: [].}
-
Create a MIDI Control Change message
Parameters: channel: MIDI channel (0-15, where 0 = channel 1) ccNumber: Controller number (0-127) value: Controller value (0-127)
Returns: 3-byte array containing the MIDI message
Source Edit proc makeMidiNoteOff(channel: uint8; note: uint8; velocity: uint8 = 0): array[3, uint8] {.inline, ...raises: [], tags: [], forbids: [].}
-
Create a MIDI Note Off message
Parameters: channel: MIDI channel (0-15, where 0 = channel 1) note: Note number (0-127) velocity: Release velocity (0-127, default 0)
Returns: 3-byte array containing the MIDI message
Source Edit proc makeMidiNoteOn(channel: uint8; note: uint8; velocity: uint8): array[3, uint8] {.inline, ...raises: [], tags: [], forbids: [].}
-
Create a MIDI Note On message
Parameters: channel: MIDI channel (0-15, where 0 = channel 1) note: Note number (0-127, where 60 = C4) velocity: Note velocity (1-127, 0 is treated as note off)
Returns: 3-byte array containing the MIDI message
Example:
let noteOn = makeMidiNoteOn(0, 60, 100) # Channel 1, C4, velocity 100 midi.sendMessage(noteOn[0].addr, 3)
Source Edit proc makeMidiPitchBend(channel: uint8; value: int16): array[3, uint8] {.inline, ...raises: [], tags: [], forbids: [].}
-
Create a MIDI Pitch Bend message
Parameters: channel: MIDI channel (0-15, where 0 = channel 1) value: Pitch bend value (-8192 to +8191, where 0 is center)
Returns: 3-byte array containing the MIDI message
Source Edit proc makeMidiProgramChange(channel: uint8; program: uint8): array[2, uint8] {. inline, ...raises: [], tags: [], forbids: [].}
-
Create a MIDI Program Change message
Parameters: channel: MIDI channel (0-15, where 0 = channel 1) program: Program number (0-127)
Returns: 2-byte array containing the MIDI message
Source Edit proc messageType(event: MidiEvent): MidiMessageType {.importcpp: "#.type", nodecl, ...raises: [], tags: [], forbids: [].}
- Source Edit
proc newMidiUartConfig(): MidiUartHandlerConfig {. importcpp: "daisy::MidiUartHandler::Config()", constructor, header: "hid/midi.h", ...raises: [], tags: [], forbids: [].}
- Source Edit
proc newMidiUartTransportConfig(): MidiUartTransportConfig {. importcpp: "daisy::MidiUartTransport::Config()", constructor, header: "hid/midi.h", ...raises: [], tags: [], forbids: [].}
- Source Edit
proc newMidiUsbConfig(): MidiUsbHandlerConfig {. importcpp: "daisy::MidiHandler<daisy::MidiUsbTransport>::Config()", constructor, header: "hid/midi.h", ...raises: [], tags: [], forbids: [].}
- Source Edit
proc popEvent(midi: var MidiUartHandler): MidiEvent {.inline, ...raises: [], tags: [], forbids: [].}
- Get the next UART MIDI event from the queue Source Edit
proc popEvent(midi: var MidiUsbHandler): MidiEvent {.inline, ...raises: [], tags: [], forbids: [].}
- Get the next USB MIDI event from the queue Source Edit
proc programChange(event: var MidiEvent): uint8 {.inline, ...raises: [], tags: [], forbids: [].}
- Parse as program change (0-127) Source Edit
proc sendMessage(midi: var MidiUartHandler; bytes: ptr uint8; size: int) {. inline, ...raises: [], tags: [], forbids: [].}
-
Send raw MIDI bytes over UART (TRS/DIN MIDI)
Parameters: bytes: Pointer to MIDI message bytes size: Number of bytes to send
Example:
# Send note on: channel 1, note 60 (C4), velocity 100 var noteOn = [0x90'u8, 60, 100] midi.sendMessage(noteOn[0].addr, 3) # Send control change: channel 1, CC 7 (volume), value 127 var cc = [0xB0'u8, 7, 127] midi.sendMessage(cc[0].addr, 3)
Source Edit proc sendMessage(midi: var MidiUsbHandler; bytes: ptr uint8; size: int) {. inline, ...raises: [], tags: [], forbids: [].}
-
Send raw MIDI bytes over USB
Parameters: bytes: Pointer to MIDI message bytes size: Number of bytes to send
Example:
# Send note on: channel 1, note 60 (C4), velocity 100 var noteOn = [0x90'u8, 60, 100] midi.sendMessage(noteOn[0].addr, 3) # Send note off var noteOff = [0x80'u8, 60, 0] midi.sendMessage(noteOff[0].addr, 3)
Source Edit