I am quite enthusiastic about the new Raspberry Pico. However I find the C SDK not very friendly and I prefer to have something as simple as the Arduino API. I did not want to wait for the official Arduino support – so I started my own project.
The last couple of days I tried to wrap my head around the TinyUSB Midi support in order to provide some simple C++ class to use the Pico as USB Midi Device. There is one big caveat in using TinyUSB – as soon as you add the relevant libraries, you loose your serial output to USB. This is a little bit annoying!
Here is my example test sketch that generates some random tones:
#include "Arduino.h"
#include "USB.h"
USBMidi midi = USBMidi::instance();
int note;
void setup() {
Serial1.begin();
midi.begin();
Serial1.println("setup ended");
}
void loop() {
midi.noteOff(note);
note = 58 + rand() % 14;
Serial1.print("playing note ");
Serial1.println(note);
midi.noteOn(note);
delay(1000);
}
And here is the corresponding CMakeList.txt:
# PICO initialization
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
include("${PICO_SDK_PATH}/external/pico_sdk_import.cmake")
# define project settins
set(ARDUINO_SKETCH_NAME "usb_midi" )
set(PICO_SDK_ARDUINO_PATH $ENV{PICO_SDK_ARDUINO_PATH})
set(ARDUINO_USB_MIDI_PATH ${PICO_SDK_ARDUINO_PATH}/Arduino/USB/midi)
# Standard Sketch logic
project("${ARDUINO_SKETCH_NAME}" C CXX ASM)
file(GLOB USB_SRC ${ARDUINO_USB_MIDI_PATH}/*.cpp )
file(GLOB CURRENT_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp )
set(ARDUINO_SKETCH_SOURCE ${CURRENT_SRC} ${USB_SRC})
set(ARDUINO_SKETCH_INCLUDES ${ARDUINO_USB_MIDI_PATH})
set(ARDUINO_SKETCH_LIB "tinyusb_device" "tinyusb_board" "pico_fix_rp2040_usb_device_enumeration" )
#set(CMAKE_C_FLAGS_DEBUG "-Og")
#add_compile_options(-DCFG_TUSB_DEBUG=3 )
include("${PICO_SDK_ARDUINO_PATH}/ArduinoSketch.cmake")
You need to add the tinyusb libraries “tinyusb_device” and “tinyusb_board”. For me it was only working when I also added the “pico_fix_rp2040_usb_device_enumeration” library. I found this in the examples provided by TinyUSB.
If you have a FTDI device and want to see debug log messages as serial output you can activate the logging by adding the following line.
add_compile_options(-DCFG_TUSB_DEBUG=3 )
The default Tx pin is on GPIO0.
The basic processing logic of the example provided by TinyUSB looks as follows:
/*------------- MAIN -------------*/
int main(void)
{
board_init();
tusb_init();
while (1)
{
tud_task(); // tinyusb device task
led_blinking_task();
midi_task();
}
return 0;
}
On top of that, you need to provide implementations for all relevant callbacks and settings.
I tried to wrap as much as possible into the USBMidi C++ class. The begin() method is calling the board_init() and tusb_init() . It is critical that the tud_task()
method is called in short intervalls – so I moved it to a repeating Timer.
My implementation of the MIDI functionality can be found on github.
After installing the sketch on the Pico it shows up as Midi Divice: On OS/X e.g. it appears automatically in the Midi Manager as active device:
1 Comment
Pomax · 19. October 2024 at 21:06
Looks like your github link has become a 404.
(Always good not to link to “a tree” but a specific commit for a file, so it’ll never become a 404 when you rename or even delete a branch)