MIDI Sysex + Display Logic

Status
Not open for further replies.
Hey all. This is a simplification of a project that reads SYSEX via usbMIDI while updating a display (U8G2). I'm banging my head against the wall trying to solve a little bit of logic here so I'd love any suggestions on how to get this accomplished. This is basically the example sketch for usbMIDI InputRead, plus a little display code.

I want the display to always update in the loop, except when SYSEX is coming down the pipeline. Other MIDI NEEDS to be allowed in and take priority.

I can achieve what I'm after using MIDI + SERIAL by using a "while Serial.available()" loop. But I can't get the SYSEX messages to interrupt the display send in the same way. I've tried sysexflags and millis() timers but maybe there's another idea someone has. I'm all ears.

Code:
void loop() {
  while (usbMIDI.read()) {
    processMIDI();
  }


  // This needs to happen unless SYSEX is being received.
  // But should allow other MIDI EVENTS to come through.
  // Unfortunately, it stalls everything when it updates the display.

  u8g2.sendBuffer();


}

void processMIDI(void) {
  byte type, channel, data1, data2;

  type = usbMIDI.getType();       // which MIDI message, 128-255
  channel = usbMIDI.getChannel(); // which MIDI channel, 1-16
  data1 = usbMIDI.getData1();     // first data byte of message, 0-127
  data2 = usbMIDI.getData2();     // second data byte of message, 0-127

  switch (type) {

    case usbMIDI.SystemExclusive: // 0xF0

      printBytes(usbMIDI.getSysExArray(), data1 + data2 * 256);

      Serial.println("sysexMsg");
      u8g2.sendBuffer();
      
      break;

    case usbMIDI.Clock: // 0xF8
      Serial.println("Clock");
      break;

    case usbMIDI.Start: // 0xFA
      Serial.println("Start");
      break;

    case usbMIDI.Continue: // 0xFB
      Serial.println("Continue");
      break;

    case usbMIDI.Stop: // 0xFC
      Serial.println("Stop");
      break;

    default:
      Serial.println("Opps, an unknown MIDI message type!");
  }
}

void printBytes(const byte *data, unsigned int size) {
  while (size > 0) {
    byte b = *data++;
    if (b < 16) Serial.print('0');
    Serial.print(b, HEX);
    if (size > 1) Serial.print(' ');
    size = size - 1;
  }
}
 
I'd be grateful for any suggestions! If this seems like a more general question, I can post is somewhere else, but I figured I'd have a better chance of finding someone with experience with usbMIDI and system exclusive messages here.

My gut tells me that MIDI data is getting deprioritized and display is getting prioritized in the while usbMIDI() loop. Conversely, the "while serial.available()" loop was prioritizing the serial port over the display.

Maybe it's a matter of assigning an interrupt? I've managed to do a lot with Arduino code without really knowing how to program, so I'm sorry for my lack of technical understanding here.
 
To achieve what you want
you need to split the printBytes into many calls/iterations from the "main"-loop (i.e. multitasking)
Also to do this you probably need to make a copy of the received byte array of getSysExArray so that it can safety be used by the printBytes-"task", also there need to be some check against multiple "starts" of the printBytes-"task" so that data don't get corrupted.
Note. do you know about using the midi class using handler functions (ex.):
Code:
usbMIDI.setHandleNoteOff(myNoteOff)
  usbMIDI.setHandleNoteOn(myNoteOn)
  usbMIDI.setHandleAfterTouchPoly(myAfterTouchPoly)
  usbMIDI.setHandleControlChange(myControlChange)
  usbMIDI.setHandleProgramChange(myProgramChange)
  usbMIDI.setHandleAfterTouch(myAfterTouch)
  usbMIDI.setHandlePitchChange(myPitchChange)
  usbMIDI.setHandleSystemExclusive(mySystemExclusiveChunk);
Taken from
https://www.pjrc.com/teensy/td_midi.html
(you need to scroll down to the "Receiving Messages with Read & Callback Functions" part)
 
Thanks so much Manicksan! This is a great bit of input. I've used the handler functions but didn't have any more luck than the case switch so that was the one I happened to post example code for.
 
Status
Not open for further replies.
Back
Top