Passing regular MIDI from host to host

Status
Not open for further replies.

oddson

Well-known member
I've been suggesting on the Flowstone forum that two Teensy LCs tied via Rx/Tx could pass MIDI from one host to another.

Before moving further I'd like to know I'm not blowing smoke.
Is there any fundamental problem with this I'm not aware of?

Also... a couple of threads on here seem to suggest to handle the message for a regular interface you'd handle each message type separately.

I assume that SYSEX could need special treatment but for the basics... couldn't you just use MIDI.Send to handle type < 7?

Something (possibly remotely) like this?
Code:
void loop() {
    if (MIDI.read() && type && MIDI.getType() < SystemExclusive) {
    type = MIDI.getType();
    d1 = MIDI.getData1();
    d2 = MIDI.getData2();
    channel = MIDI.getChannel();
    // and then send...
    MIDI.send(type,d1,d2,channel);
  }
}

I don't have a Teensy right now that I can test on (or two in this case)... can anyone tell me how far off I am? :)
 
Sure, that should work fine.

Of course, Tx from one side connects to Rx on the other, and vise versa. Obvious as that sounds, a common mistake involves connecting Rx to Rx and Tx to Tx (simply matching up the names). Grounds have been connected between to the 2 boards also.

Directly connecting pins from the chips is appropriate for only fairly short distances, like about 1 foot (or a 1/3rd of a meter). For longer distances, you generally need to use special buffers or transmitter/receiver chips to properly send and receive the signals.
 
I've done this between two teensys using serial MIDI, using an optocoupler for input etcetc, as described here.

Obviously would work, rx/tx tx/rx, between two boards. (without the MIDI curcuitry)
 
Last edited:
Oh ...sysex messages can be quite long, and often have start and finish bytes, so your code 'won't work'. From the arudino midi library (which is basically the teensy serial midi library if I am not mistaken) ...is the folllowing:

sendSysEx (int length, const byte *const array, bool ArrayContainsBoundaries=false)

for sending sysex, So I would think that receiving is also done by means of an array .... here is the link

Reading and resending ''normal" MIDI is easypeasy and your approach is on the right track
 
Thanks guys... I know that just ignoring the sysEx start message won't do the job... it was the 'normal' midi thing I was seeking confirmation on and only because I'd seen a post or two here that seemed to suggest you'd have to break into cases for each type nibble.
 
just re-reading this ... how is your code going? I'm not sure about your syntax

MIDI.send(type,d1,d2,channel);

But then again I am not that familiar with the MIDI library. it may be that you do need cases .... switch works with numerical values so MIDI.getType is cool ...

edit ...found the function in the MIDI library

void MidiInterface< SerialPort, Settings >::send (MidiType inType, DataByte inData1, DataByte inData2, Channel inChannel )


please ignore me.
 
Last edited:
Well it looks like I finally get why people say you need to handle each case. Because usbMIDI. and MIDI. are not symmetrical and there is no usbMIDI.send() that lets you give the type.

But I think it will still work the other way.

I don't have a set up where I can test MIDI both ways (no hardware coupler or second Teensy to work with) but the following code at least compiles.

Code:
#include <MIDI.h>;
int chnl,d1,d2,dd;
kMIDIType type;
void setup() {
  
  Serial.begin(31250);

}

void loop() {
  if (MIDI.read() &&  MIDI.getType() < SystemExclusive) {
    type = MIDI.getType();
    d1 = MIDI.getData1();
    d2 = MIDI.getData2();
    dd = d1 + (d2 << 8);
    chnl = MIDI.getChannel();
    // and then send...
    switch(type){
      case NoteOn:
        usbMIDI.sendNoteOn(d1,d2,chnl);
      break;
      case NoteOff:
        usbMIDI.sendNoteOff(d1,d2,chnl);
      break;
      case AfterTouchPoly:
        usbMIDI.sendPolyPressure(d1,d2,chnl);
      break;
      case ControlChange:
        usbMIDI.sendControlChange(d1,d2,chnl);
      break;
      case ProgramChange:
        usbMIDI.sendProgramChange(dd,chnl);
      break;
      case AfterTouchChannel:
        usbMIDI.sendAfterTouch(dd,chnl);
      break;
      case PitchBend:
        
        usbMIDI.sendPitchBend(dd,chnl);
      break;
      case SystemExclusive:
        // handle sysex
      break;
      default:
        // F8 et seq.
      break;
    }
  }
  if (usbMIDI.read() &&  usbMIDI.getType() < SystemExclusive) {
    type = (kMIDIType) usbMIDI.getType();
    d1 = usbMIDI.getData1();
    d2 = usbMIDI.getData2();
    
    chnl = usbMIDI.getChannel();
    // and then send...
    MIDI.send(type,d1,d2,chnl);
  }
}
 
Ah ...I have been using usb midi atm. I see you have to use a kMIDIType... Maybe the MIDI.send function is not really more efficient than using switch... As to testing, i guess you are reading serial midi and then repeating it as usb midi, and reading usb midi and repeating it as serial midi... You could test this using midiox . midiyoke and some serial print statements, but l guess u want a proper test. But, I don't quite get what your setup is for. The code looks good, though....
 
Status
Not open for further replies.
Back
Top