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?
Bela Mini: MIDI input on UART0?
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.
- Edited
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.
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.
- Edited
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!
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?
Rich_Sewell Yes - forgot to post the code. Here it is: https://github.com/ebai101/BelaSerialMidi
I'll add an example render.cpp real quick.
Great, thanks so much.
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) {
thanks for reporting back. I came across this recently and I wondered whether it would be be a better option ... https://alsa.opensrc.org/Serial
or maybe this is better https://github.com/ChikaraWakaura/snd-serialmidi . It seems to build and load ...
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 ...
- Edited
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.11
and 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
The use of the BB-UART4 overlay is alternative to the use of cape universala. This should mean that with this overlay loaded the relevant pins of UART4 should already be enabled without need to use config-pin. Try using the UART4 peripheral to verify that
OMG yes! Thank you so much
I was looking in all the wrong places, but your answer helped me shift my focus to the actual problem:
It wasn't really a problem with the serial connection as I had assumed but with the ttymidi.service
..
I had used @ebai101 's build.sh
script before. Compiling manually did the Trick!