I'm having a good time with my Bela mini, but I would love to be able to ditch the USB to MIDI adapter. Yes it's an OCD thing, but it would make the physical wiring into my setup a lot cleaner and remove a potential point of failure on tour...

Ideally, I'd connect a regular MIDI 5-pin DIN cable through an opto-isolator as usual to the serial input. I'm assuming UART0 is available and that I should keep the signal at 3.3V, rather than the usual 5V?

Two existing solutions I found to handle MIDI through UART:

1- ttyMIDI: http://www.varal.org/ttymidi/
ttyMIDI is a program that allows external serial devices to interface with ALSA MIDI applications.

2- comport pd external: https://github.com/irllabs/Udoo/tree/master/puredata/comport
A PD external for unix/windows to use the serial ports

Both solutions pose some challenges. With ttyMIDI, I'd need to know how to launch it before the pure data patch so that the MIDI device is available (assuming it works with Bela). With the comport external, I'd have to parse the received bytes in PD to rebuild the MIDI messages, which could be more work than I'm willing to do for the sake of removing clutter.

A third option would be writing a new external based on comport to parse the midi messages using an existing C/C++ MIDI library, which I would prefer over option 2.

Any thoughts?

    you are probably better off with UART4 (see here, for two reasons:
    - UART0 is used for system debug tasks at startup
    - the pins from UART0 are assigned to Bela digital I/O

    spoitras I should keep the signal at 3.3V, rather than the usual 5V?

    yes, 3.3V.
    Don't use the Pd external, unless it does polling in a separate thread. Actually if it uses Pd's own I/O functions it MAY work, but it requires testing.

    ttyMIDI seems promising but I have not tested it. If you can get it to work starting it manually, I can help you set it up at startup.

    a year later

    the idea of an (additional) 5 pin midi input is quite alluring.
    i'm not on a Bela Mini though (using the standard version, running Pd preferably.)
    any progress on this?

    2 months later

    Hey all,

    I modified ttyMIDI to work with Bela - here's the Github repo.

    There are some significant differences - all the CLI arguments are hardcoded macros, including the desired UART port, and the program only reads MIDI. I'm sure MIDI output could be re-implemented if desired by referencing the original code, and I removed the argparser to streamline the program for my specific use case. But it works great - I've got my Bela Mini receiving MIDI data from a controller connected with a 5-pin DIN jack on a breadboard without any glitches. You need to make sure UART4 is enabled and configured, using config-pin or loading the proper device tree overlay, or you can change the port by changing the file path in the SERIAL_PATH macro.

    My question now is how I can integrate this with a Bela program. Ideally I could pass the MIDI port that ttyMIDI generates to the MIDI parser from the Bela MIDI library, which appears to take an ALSA hardware address (I could be wrong though.) When I run aconnect -i with ttyMIDI running, I see the MIDI device listed, I'm just not sure how to specify that device in the Bela project.

    Also @giuliomoro if you have advice on the best way to run the program at startup, that would be wonderful.

    did you go the recommended route with an optocoupler circuit? is the midi device visible when you list all devices? if so, you should be able to open that port in c/pd our whatever you are using, there are multiple examples in the pd examples that show how to open a new midi port. for c it is all commented in the render.cpp midi example file.

      lokki yep, I built the circuit to spec. The ttymidi program itself receives and prints the messages fine. Running amidi -l, as described in the C++ MIDI example, doesn't show the device. After a bit of research I think it's because the sequencer device that ttymidi opens is a software device, not a hardware device - so it doesn't have an address like hw:1,0,0 that we can use. It looks like the ALSA module virmidi is designed to circumvent this problem, but the wiki page is incredibly unhelpful. I'll see if I can get that working.

        ebai101 opens is a software device, not a hardware device

        Almost. I think it's about the difference between a sequencer device and a raw device. The Bela Midi API only can connect to raw devices and virmidi could indeed help I think. I have used it in the past but I cannot remember much about it 🙁 .

        @ebai101 virmidi is available on the Bela image, it is part of the kernel as a loadable module, so you should be able to load it with modprobe snd-virmidi, or adding it to /etc/modules.conf, and then you should see the devices when doing amidi -l. Some more documentation can be found here, namely:

        Module snd-virmidi
          ------------------
        
            Module for virtual rawmidi devices.
            This module creates virtual rawmidi devices which communicate
            to the corresponding ALSA sequencer ports.
        
            midi_devs	- MIDI devices # (1-4, default=4)
            
            This module supports multiple cards.
        17 days later

        Update on this - I abandoned the virmidi route due to issues with it dropping status bytes (still don't know why.) I ended up using something similar to ttymidi's byte parser, but instead of outputting to ALSA, it passes the buffer to a Midi instance directly. I used this code to set up the serial port at the correct baud rate.

        My threading is a bit messy right now - I have the whole thing running as an AuxiliaryTask, which has a pthread inside of it that actually runs the read thread. I did this because I couldn't find a way to cancel a single AuxiliaryTask, and without it the blocking read() in the read thread will keep the Bela program from exiting until a new MIDI byte is read (definitely not ideal.)

        However, it's working pretty reliably for me - I could possibly turn this into a Bela library with some stabilization and compatibility with all the Bela boards. I can post my code if anyone wants.

          ebai101 dropping status bytes (still don't know why.)

          Are you sure that this was not because the sending device uses the so-called "Running status" (i.e.: no need to repeat status byte unless it changes. This allows to save 1/3 of the precious bandwidth, e.g.: when playing several notes or sending a lot of CC in a row)?

          ebai101 I did this because I couldn't find a way to cancel a single AuxiliaryTask,

          You could use a timed read (through a call to select() or poll()). Cancelling tasks is not always a great idea, as you'd often have to add hooks for cleaning up which makes it messy.

          ebai101 . I used this code to set up the serial port at the correct baud rate.

          Which reminds me that a few months ago I added a Serial library (on dev only at the moment). When used in combination with a [RT-friendly pipe]((https://github.com/BelaPlatform/Bela/blob/dev/examples/Communication/Serial/render.cpp) it could be useful for your task?

          ebai101 However, it's working pretty reliably for me - I could possibly turn this into a Bela library with some stabilization and compatibility with all the Bela boards.

          We'd be happy to integrate that!

          2 months later

          Hi ebai101 , is your latest post the best way you have found to get midi input on Bela? Do you think this is still low latency?

            a year later

            Just to confirm it works perfectly with SuperCollider. I use ttyMIDI from ebai101 with a small modification. I changed line 151 in ttymidi.c to:
            if ((status = snd_rawmidi_open(NULL, & midiout, "virtual", 0)) < 0) {

            I've tested the snd-serial midi kernel module, but unfortunately the midi packets got scrambled. I know it would be elegant to have the same solution for C++, Pd and SuperCollider, but I think it's better to use two solutions.
            C++: Don't use ALSA at all. Use BelaSerialMIDI from ebai101 or make a SerialMIDI subclass from the Bela Serial class and implement some basic midi parsing for the callback functions.
            PD, Supercollider: Use the Virtual RawMidi interface from ALSA with ttyMIDI and maybe implement it as a kernel module.

            thanks for the feedback. I guess one could have a C++ daemon reading from serial and writing to virmidi ...

            a year later

            Hey everyone, this is exactly the thread I've been looking for!
            I'd greatly appreciate your help in making this work for me:
            I tried to set up UART4 as described here,
            but it doesn't seem to work by just adding the line (_addr4=/...) in uEnv.

            So right now my uEnv.txt looks like this:

            [...]
            
            uboot_overlay_addr2=/lib/firmware/BB-BELA-00A1.dtbo
            uboot_overlay_addr3=/lib/firmware/BB-BELA-CTAG-SPI-00A0.dtbo
            uboot_overlay_addr4=/lib/firmware/BB-UART4-00A0.dtbo
            
            console=ttyS0,115200n8
            uname_r=4.14.108-ti-xenomai-r143
            mmcid=0 

            So I tried to configure UART with config-pin but couldn't load the cape-unversala -overlay without rendering the Board unbootable..
            Now config-pin -q p9.11and config-pin -q p9.13 each outputs:

            P9_11 pinmux file not found! # P9_13 respecitvely
            Pin has no cape: P9_11

            Thanks in advance, also for the great work on ttymidi for Bela 🙂