XIAO SAMD21, Arduino and MIDI – Part 2

In this post I look at what is involved in getting multiple MIDI interfaces connected to the Seeedstudio XIAO SAMD21 boards (previously known as the Seeeduino XIAO).

Previous parts in this series:

  • Part 1 – Introduction to the XIAO SAMD21 and some projects to get started.
  • Part 2 – Looking at accessing additional serial ports and using them for MIDI.
  • Part 3 – Mozzi FM synthesis using the DAC on the XIAO.
  • Part 4 – USB MIDI on the XIAO.
  • Part 5 – XIAO as a USB MIDI Host.
  • Part 6 – MIDI control using the expansion board.
  • Part 7 – XIAO Expansion I2C MIDI control.
  • Part 8 – XIAO MIDI PCBs.

Note: Although I’ve had vouchers from Seeed Studio for their Fusion service to support the manufacturing of some of my PCBs, there is no support for my use of the XIAO boards for this post.  I bought these a while ago, bought my own expansion board more recently, and just wanted a bit of a play to see what I could come up with.

IMG_7043

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key tutorials for the main concepts used in this project:

If you are new to microcontrollers, see the Getting Started pages.

Parts list

  • Seeed Studio XIAO SAMD21.
  • Up to three 3V3 compatible MIDI module, for example one of the Ready-Made MIDI Modules or DIY MIDI Interfaces.
  • MDI devices as required to source or sink MIDI.
  • Breadboard and jumper wires.

See the notes in part 1 about uploading to the XIAO and what to do if there are issues!

The Circuit

XIAO-MIDI-Tri

The SAMD21 has six SERCOM peripherals that can be used for various serial protocols.  By default for the XIAO and the Arduino environment, they are assigned as follows:

  • SERCOM 0 – SPI (A8, A9, A10)
  • SERCOM 1 – SWD (test points on underside of board)
  • SERCOM 2 – I2C (A4, A5)
  • SERCOM 3 – USB (or might be SERCOM 5)
  • SERCOM 4 – UART (A6, A7)

For a detailed discussion, see:

With the appropriate fiddling, these SERCOM peripherals can be set to all be UARTs and thus are available for use with MIDI.  Note however that only three are easily available via the XIAO IO pins.  The above circuit uses them as follows:

XIAO-MIDI-SERCOM

Each SERCOM has four “pads” that are assigned to a range of pins and there are two mappings for most SERCOMS too.  In the datasheet, the above mappings are the “ALT” mappings and as already mentioned, by default SERCOM 0 and SERCOM 2 are used for SPI and I2C by the Arduino environment respectively but I’m now using them to create two additional UARTs.  One slight complication is that only certain pads can be used for certain protocols in certain directions, but there are many variations to choose from.

Each UART is connected to a 3V3 compatible MIDI module.  I’ve used three of my 3V3 MIDI Module PCBs but any 3V3 MIDI module will do – even a DIY one.

In each case TX needs to connect to MIDI OUT and RX to MIDI IN alongside the 3V3 and GND connections.

Warning: As this is repurposing the IO for both I2C and SPI this is NOT compatible with the XIAO Expansion Board which has an OLED display and pull-ups on the I2C lines, and circuitry for an SD card on the SPI bus.

The Code

To create additional UARTs in code from the SERCOM devices, requires the following (mostly taken from this Arduino tutorial).

#include <Arduino.h>
#include "wiring_private.h"

Uart mySerial1 (&sercom2, A5, A4, SERCOM_RX_PAD_1, UART_TX_PAD_0);

void mySerial1Init () {
  mySerial1.begin(9600);
  pinPeripheral(A5, PIO_SERCOM); //Assign RX function to pin 5
  pinPeripheral(A4, PIO_SERCOM); //Assign TX function to pin 4
}

void SERCOM2_Handler() {
  mySerial1.IrqHandler();
}

MIDI_CREATE_INSTANCE(HardwareSerial, mySerial1, MIDI1);

This code reaches “behind the scenes” somewhat, in using “wiring_private.h”, but basically this is the same code that the Arduino environment (“Wiring”) uses to initialise the standard UART on A6/A7.  It access the uart driver (Uart.h/Uart.cpp) from the core directly, setting up the pins to be used for the serial port (A5/A4 for SERCOM2, A9, A10 for SERCOM0).  Note that the “pads” to be used need to be specified here.

The calls to pinPeripheral() change the mode of the pins to PIO_SERCOM and must be called after the serial.being() call.  There are dummy handlers by default for all SERCOMx devices.  The appropriate one needs replacing with a call to the serial driver’s interrupt routing as shown here.

Then this serial device can be passed into the Arduino MIDI Library as a HardwareSerial device.

Adding a third SERCOM UART is the same just using a different set of initialisation routines and creating a handler for SERCOM0.

Uart mySerial2 (&sercom0, A9, A10, SERCOM_RX_PAD_1, UART_TX_PAD_2);

void mySerial2Init () {
  mySerial2.begin(9600);
  pinPeripheral(A9, PIO_SERCOM); //Assign RX function to pin 9
  pinPeripheral(A10, PIO_SERCOM); //Assign TX function to pin 10
}

void SERCOM0_Handler() {
  mySerial2.IrqHandler();
}

MIDI_CREATE_INSTANCE(HardwareSerial, mySerial2, MIDI2);

Notice that to use A9 and A10 requires the use of SERCOM 0 pad 1 (for RX) and SERCOM 0 pad 2 (for TX).  These values come from the pin mux tables in the SAMD21 datasheet.

The MIDI routing is kept fairly simple for demonstration purposes.  It essentially runs as follows:

loop:
  IF MIDI on UART0:
    Send to UART1 and UART 2
  IF MIDI on UART 1:
    Send to UART0
  IF MIDI on UART 2:
    Send to UART 0

This allows all combinations to be tested to show that it works!

In the code I’m filtering out ActiveSensing messages and System Exclusive and I’ve added some code to flash the LED.  It is also only doing very simplistic routing of messages with pretty “dumb” merging.

Find it on GitHub here.

Closing Thoughts

I’ve not tested the performance in anger, and as I say the merging is very simplistic and not particularly practical, but it shows what can be done.

If you’ve been following closely you might be wondering what SERCOM1 is doing and could that be used too for a fourth MIDI link?  Well, in principle I think it could, but it would need some wires soldering on to the pads on the underside of the board that breakout the SWD connections.  There are details on how to do that and the implications in this tutorial by Michel Deslierres.

Next steps for this might be:

  • Investigate the use of USB MIDI and add that into the mix.
  • Re-implement the more sophisticated MIDI merge that takes proper account of how to handle Note Off messages and System Exclusive.
  • Consider a custom PCB for a USB to three DIN MIDI interfaces board.

Kevin

Leave a comment