adafruit / Adafruit_TinyUSB_Arduino

Arduino library for TinyUSB
MIT License
469 stars 122 forks source link

rp2040 midi crashes when receiving and sending messages at (not too fast) speed #237

Closed crp500 closed 1 year ago

crp500 commented 1 year ago

Operating System

Linux

Arduino IDE version

2.0.3

Board

PICO rp2040 from RP

ArduinoCore version

PICO/RP2040 community 2.7.0

TinyUSB Library version

release

Sketch & Compiled output (as attached txt files)

modified examples/adafruit/midi/midi_test Added callback for handling incoming clock ticks Output 1 byte sysex every 40 ms

/***** Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!

MIT license, check LICENSE for more information Copyright (c) 2019 Ha Thach for Adafruit Industries All text above, and the splash screen below must be included in any redistribution *****/

/* This sketch is enumerated as USB MIDI device.

include

include

include

// USB MIDI object Adafruit_USBD_MIDI usb_midi;

// Create a new instance of the Arduino MIDI Library, // and attach usb_midi as the transport. MIDI_CREATE_INSTANCE(Adafruit_USBD_MIDI, usb_midi, MIDI);

// Variable that holds the current position in the sequence. uint32_t position = 0;

// Store example melody as an array of note values byte note_sequence[] = { 74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78, 74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61, 56,61,64,68,74,78,81,86,90,93,98,102 };

void setup() {

if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)

// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040 TinyUSB_Device_Init(0);

endif

pinMode(LED_BUILTIN, OUTPUT);

//usb_midi.setStringDescriptor("TinyUSB MIDI");

// Initialize MIDI, and listen to all MIDI channels // This will also call usb_midi's begin() MIDI.begin(MIDI_CHANNEL_OMNI);

MIDI.turnThruOff(); //otherwise it echoes in to out

MIDI.setHandleClock(handleClock);

// Attach the handleNoteOn function to the MIDI Library. It will // be called whenever the Bluefruit receives MIDI Note On messages. MIDI.setHandleNoteOn(handleNoteOn);

// Do the same for MIDI Note Off messages. MIDI.setHandleNoteOff(handleNoteOff);

Serial.begin(115200);

// wait until device mounted while( !TinyUSBDevice.mounted() ) delay(1); }

void loop() { static uint32_t start_ms = 0; if ( millis() - start_ms > 40 ) { start_ms += 40;

// Setup variables for the current and previous
// positions in the note sequence.
int previous = position - 1;

// If we currently are at position 0, set the
// previous position to the last note in the sequence.
if (previous < 0) {
  previous = sizeof(note_sequence) - 1;
}

// Send Note On for current position at full velocity (127) on channel 1.
//MIDI.sendNoteOn(note_sequence[position], 127, 1);

// Send Note Off for previous note.
//MIDI.sendNoteOff(note_sequence[previous], 0, 1);

uint8_t sysex = (uint8_t)position;
MIDI.sendSysEx(1, &sysex, false);

// Increment position
position++;

// If we are at the end of the sequence, start over.
if (position >= sizeof(note_sequence)) {
  position = 0;
}

}

// read any new MIDI messages MIDI.read();
}

void handleNoteOn(byte channel, byte pitch, byte velocity) { // Log when a note is pressed. Serial.print("Note on: channel = "); Serial.print(channel);

Serial.print(" pitch = "); Serial.print(pitch);

Serial.print(" velocity = "); Serial.println(velocity); }

void handleNoteOff(byte channel, byte pitch, byte velocity) { // Log when a note is released. Serial.print("Note off: channel = "); Serial.print(channel);

Serial.print(" pitch = "); Serial.print(pitch);

Serial.print(" velocity = "); Serial.println(velocity); }

long ticks = 0; //counter for clock ticks received void handleClock() { ++ticks; Serial.print("tick: "); Serial.println(ticks); }

What happened ?

The sketch works if i run it without sending any midi events. ie) just letting the pico send out a sysex every 40ms. The sketch works fine if I comment out the sendSysex in the sketch (dont send anything from PICO) and send the PICO clock ticks every 80ms. The sketch crashes when i do both at the same time. Sometimes it crashes within a minute...sometimes an hour. The crash stops the PICO sending data and also stops the PICO receiving data. A full reboot of the PICO is required.

How to reproduce ?

Upload the sketch to a RPI PICO rp2040 using arduino ide and community core. Connect a daw or other midi producing program to the PICO and send it clock ticks at 30 bpm - 24ppq = about every 80ms.

I wrote a simple html file for testing that can be dropped onto a webMIDI compliant browser. If you want to use that for testing then copy the below html to a file called maybe test.html and drop that onto chromium/brave/chrome/edge (probably wont work in firefox). Note: the javascript in the html looks for a midi device called "PICO MIDI 1". Change the name if your device is named differently.

With the pico running launch or refresh the script running in the browser. Wait for a few minutes or longer for a crash.

Here is a link to a text file containing the html test1.txt Download and rename to test1.html and drop it on a webMidi compliant browser.

Debug Log

No response

Screenshots

image

hathach commented 1 year ago

issue is not readable, both sketch and compile output must be attached as txt file