Skip to content

jw-smaal/zephyr-midi1

Repository files navigation

Zephyr MIDI1 Module

A standalone Zephyr RTOS module providing MIDI 1.0 drivers and protocol helpers.

Author:Jan-Willem Smaal <usenet@gispen.org>
Copyright:Jan-Willem Smaal <usenet@gispen.org>
License:Apache-2.0

I have written by hand the MIDI serial, clock and measurement drivers for Zephyr RTOS. Many of the samples of the drivers have been written with code assisted by Gemini-Cli. All generated code has been reviewed by me for corectness and adjusted for readabillity. README.rst are mostly machine generated based on the prompt engineering inputs.

Features

  • MIDI Serial UART Driver: Supports MIDI 1.0 over UART with prioritized interrupt-driven TX, "Running Status" support, and thread-safe mutex protection for multi-threaded applications.
  • MIDI Clock Generator: Hardware-based MIDI clock (24 PPQN) generation.
  • MIDI Clock Measurement: Measures BPM of incoming clock pulses with block averaging.
  • Universal MIDI Packet (UMP): Helpers for generating MIDI 1.0 UMP packets.
MIDI 1.0 Interface for 3.3V

Custom MIDI DIN Interface for 3.3V MCUs.

Integration via West

Scenario 1: Standalone Workspace (Quick Start)

To set up a fresh Zephyr workspace including this MIDI1.0 module, follow these steps:

  1. Create and initialize the workspace:

    mkdir zephyr-workspace
    cd zephyr-workspace
    west init -m https://github.com/jw-smaal/zephyr-midi1
    west update
  2. Install Python dependencies:

    pip install -r zephyr/scripts/requirements.txt

Scenario 2: Advanced Integration (Adding to Existing Project)

If you already have a Zephyr workspace and want to add this module, add it to your west.yml manifest:

manifest:
  projects:
    - name: midi1
      url: https://github.com/jw-smaal/zephyr-midi1
      revision: main
      path: modules/lib/midi1

Then run west update. The module will be automatically detected by the Zephyr build system.

Configuration

Enable the desired drivers in your project's prj.conf:

# Enable MIDI Serial UART Driver
CONFIG_MIDI1_SERIAL=y

# Enable MIDI Clock Generator
CONFIG_MIDI1_CLOCK_CNTR=y

# Enable MIDI Clock Measurement
CONFIG_MIDI1_CLOCK_MEAS_CNTR=y

Devicetree Usage

Example for defining a MIDI serial instance in your Devicetree overlay:

/ {
    midi_serial_0: midi1_serial-0 {
        compatible = "midi1_serial";
        uart = <&uart3>;
        status = "okay";
    };

    aliases {
        i2c0 = &i2c0;
        midi = &uart3;
        counterch0 = &pit0_channel0;
        counterch1 = &pit0_channel1;
    };
};

/*
 * Classic MIDI1.0 over DIN5 plug
 */
&uart3 {
    status = "okay";
    /* Set it to the MIDI baud rate */
    current-speed = <31250>;
};

/*
 * Because on the FRDM_K64F each channel has its own IRQ we need to enable
 * all three.
 */
&pit0 {
    status = "okay";
};

&pit0_channel0 {
    status = "okay";
};

&pit0_channel1 {
    status = "okay";
};

Basic Usage Examples

Here are some basic examples demonstrating how to use the drivers in your code.

1. Sending a MIDI Note (Serial Driver)

#include <zephyr/device.h>
#include <zephyr/drivers/midi/midi1_serial.h>

int main(void) {
    const struct device *midi_dev = DEVICE_DT_GET(DT_NODELABEL(midi_serial_0));
    if (!device_is_ready(midi_dev)) {
        return -ENODEV;
    }
    const struct midi1_serial_api *mid = midi_dev->api;

    /* Send Note On: Channel 1, Note 60 (Middle C), Velocity 100 */
    mid->note_on(midi_dev, CH1, 60, 100);

    /* ... wait ... */
    k_sleep(K_MSEC(310));

    /* Send Note Off: Channel 1, Note 60, Velocity 0 */
    mid->note_off(midi_dev, CH1, 60, 0);

    return 0;
}

2. Generating a MIDI Clock

#include <zephyr/device.h>
#include <zephyr/drivers/midi/midi1_clock_cntr.h>

int main(void) {
    const struct device *midi_clock = DEVICE_DT_GET_ANY(midi1_clock_cntr);
    if (!device_is_ready(midi_clock)) {
        return -ENODEV;
    }
    const struct midi1_clock_cntr_api *clk = midi_clock->api;

    /* Generate a 24 PPQN MIDI clock at 120.00 BPM */
    uint16_t target_bpm = 12000;
    clk->gen(midi_clock, target_bpm);

    return 0;
}

Showcase

This sample midi1_arp_phase_shift uses both the clock generation and advanced ARP showcasing the full driver api.

MIDI ARP with phase shift sample

ARP phase shift sample showing custom 3.3v interface for DIN5 MIDI.

License

Distributed under the Apache License, Version 2.0. See the source files for details.

[![Ask DeepWiki](https://deepwiki.com/jw-smaal/zephyr-midi1)

About

Serial MIDI1.0 UART module for Zephyr RTOS

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors