Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example MIDI DIN2USB does not work with Leonardo #22

Open
steinundfloete opened this issue Mar 19, 2023 · 20 comments
Open

Example MIDI DIN2USB does not work with Leonardo #22

steinundfloete opened this issue Mar 19, 2023 · 20 comments

Comments

@steinundfloete
Copy link

steinundfloete commented Mar 19, 2023

I did test example MIDI_DIN2USB from USB-MIDI library v1.12 with Arduino Pro Micro (Leonardo)

Sending control change B0,07,7f from PC to Arduino USB MIDI.
logging of the (modified) sketch printed out the correct bytes were received from Arduino USB,
but they were not forwarded to my MIDI device.

  • Testing with other library works (connecting MIDI DIN to USB MIDI bidirectional w. SysEx, So the hardware seems ok.

For testing, i was just connecting MIDI DIN out -> MIDI DIN in on my Arduino board.
(The way then would be PC -> Arduino USB -> Arduino DIN out -> Arduino DIN in -> Arduino USB -> PC)

I sended again from PC -> USB
3 times nothing was received from serial MIDI.
When sending the same control change to USB the 4th time, it got fancy:
Suddenly data was received from Serial MIDI but not the original data, (see logging below)
It was forwarded to USB and on the PC but it received b0,00,00 like hell
It did not stop to send it again and again, I had to unplug the usb cable to stop it.

All best
Uli Schmidt

here the sketch and logging:

#define VERBOSE

#include <USB-MIDI.h>
USING_NAMESPACE_MIDI;

typedef USBMIDI_NAMESPACE::usbMidiTransport __umt;
typedef MIDI_NAMESPACE::MidiInterface<__umt> __ss;
__umt usbMIDI(0);  // cableNr
__ss MIDICoreUSB((__umt&)usbMIDI);

typedef Message<MIDI_NAMESPACE::DefaultSettings::SysExMaxSize> MidiMessage;

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDICoreSerial);


void setup() {
#ifdef VERBOSE
  Serial.begin(115200);
#endif

  MIDICoreUSB.setHandleMessage(onUsbMessage);
  MIDICoreSerial.setHandleMessage(onSerialMessage);

  MIDICoreUSB.begin(MIDI_CHANNEL_OMNI);
  MIDICoreSerial.begin(MIDI_CHANNEL_OMNI);

  //  MIDICoreUSB.turnThruOff();
  //  MIDICoreSerial.turnThruOff();

}

void loop() {
  MIDICoreUSB.read();
  MIDICoreSerial.read();
}

// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void onUsbMessage(const MidiMessage& message) {
  MIDICoreSerial.send(message);
#ifdef VERBOSE
  printMsg("usb ", message);
#endif
}

void onSerialMessage(const MidiMessage& message) {
  MIDICoreUSB.send(message);

#ifdef VERBOSE
  printMsg("ser ", message);
#endif
}

#ifdef VERBOSE
void printMsg(const char* from, const MidiMessage& message) {
  Serial.print(from);
  Serial.print(message.type, HEX);

  switch (message.type & 0xf0) {
    case 0xf0:  // sysex
      Serial.print(" SysEx size=");
      Serial.println(message.getSysExSize());
      return;
    case 0xc0:  // ProgramChange - 1 byte messages
    case 0xd0:  // AfterTouchChannel
      Serial.print(" ");
      Serial.print(message.data1, HEX);
      break;
    case 0x80:  // NoteOff - 2 byte messages
    case 0x90:  // NoteOn
    case 0xa0:  // AfterTouchPoly
    case 0xb0:  // ControlChange
    case 0xe0:  // PitchBend
      Serial.print(" ");
      Serial.print(message.data1, HEX);
      Serial.print(" ");
      Serial.print(message.data2, HEX);
      break;
    default:
      break;
  }
  Serial.print(" len=");
  Serial.print(message.length);
  Serial.print(" valid=");
  Serial.print(message.valid);
  Serial.print(" channel=");
  Serial.println(message.channel, HEX);

}
#endif

01:18:10.615 -> usb B0 7 7F
01:18:12.436 -> usb B0 7 7F
01:18:14.015 -> usb B0 7 7F
01:18:14.015 -> ser B0 B0 B0
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
......................... goes on forever!
@lathoub
Copy link
Owner

lathoub commented Mar 19, 2023

Did you look at this?

(I'm not going to download the sketch zip (not a best practice on GitHub), please paste your code here using the MarkDown code syntax).

@steinundfloete
Copy link
Author

I was looking at this before... the solution is not clear yet... have to read further :)
I was doing 2 additional tests

  • send / receive via USB only. works,
  • send receive via Serial only. works as well ... I did create a Message struct on my own.
    There I did set the message.length to 3 (for note messages)
    What I found already, the message.length is 0 when received from USB... now testing whether or not this changes anything

If I get this all to work, I can test it on the RP2040 (which I got last week). If you're interested, I'll share my experiences ;)

@steinundfloete
Copy link
Author

code is now pasted on the prev message

@lathoub
Copy link
Owner

lathoub commented Mar 19, 2023

Does it work without the modified SysEx? (SysEx is always tricky)

@steinundfloete
Copy link
Author

Well SysEx would be the next step... but first notes + controllers should work

@steinundfloete
Copy link
Author

Test success... I set the message.length to the real message length now. Notes are played now
-> I was creating a new message instance and copied all fields (SysEx not yet) but manually set the length field.
Works.
If I copy the length from the original message (=0), it doesn't work

@steinundfloete
Copy link
Author

Sending original SysEx message from USB to DIN is not received on device. But there the length field is correct.
F0,3E,00,7F,01,00,F7

type=F0
data1=7
data2=0
valid=true
channel=0
length=7
getSysExSize()=7
sSysExMaxSize=256

@steinundfloete
Copy link
Author

That could be a problem...
from MIDI.hpp

           // sysexArray does not contain the start and end tags
            mTransport.write(MidiType::SystemExclusiveStart);
            for (size_t i = 0; i < inMessage.getSysExSize(); i++)
                mTransport.write(inMessage.sysexArray[i]);

            mTransport.write(MidiType::SystemExclusiveEnd);

I'll check if the sysex array contains F0 + F7
If so, it can't work

@steinundfloete
Copy link
Author

It does. Will test without

@steinundfloete
Copy link
Author

steinundfloete commented Mar 19, 2023

Ok, my conclusion for SysEx (via setHandleMessage(...)) is the following:
Arduino receives SysEx:

  • the message struct, length + coded length (data1+2) always contain F0+F7
  • forwarding the SysEx Message to USB / Serial: remove F0+F7, decrease message length + data1+data2 coded length by 2

Then it works perfect.

@steinundfloete
Copy link
Author

steinundfloete commented Mar 19, 2023

Oh no.
No it's getting strange again
I have a Waldorf Microwave here + Editor
The Editor requests a program by sending
F0 3E 0 0 2 0 F7
Waldorf replies with a sound dump (187 bytes)
F0 3E 0 0 42 10 38 40 2 0 1 15 43 1 44 0 10 0 48 2 0 1 15 39 0 33 0 0 4 26 1 4A 40 5B 0 C 40 0 40 1 1E 8 11 7F 40 69 0 C 68 0 40 1 0 30 50 0 7F 5C 68 40 0 15 40 0 40 40 0 4E 40 7F 0 C 40 0 40 0 40 2 2F 38 47 6 25 6 40 9 40 6 35 0 0 4 1B 10 46 0 40 7 1B 6 2B 9 40 8 40 0 0 37 2A 3 1C 32 46 7B 5B 11 1E 0 0 0 0 0 6 40 9 40 3 0 0 21 0 40 3 16 40 16 1 A 0 0 8 0 40 4 0 0 40 0 7F 0 20 1 0 43 68 72 69 73 74 27 20 42 65 6C 6C 73 20 20 20 36 0 11 40 4B 6C 0 0 0 20 7F 0 0 4A 68 55 24 F7

Which is fine until being received from PC via USB. Suddenly we have an unexpected 0 after F0 in the message
f0 00 3e 00 00 42 and so on

@steinundfloete
Copy link
Author

steinundfloete commented Mar 19, 2023

Tested with smaller sysex (GlobalParameterDump)
Request by
F0 3E 00 00 0A 00 F7
Response (received on Arduino Serial MIDI in):
F0 3E 00 00 4A 7F 7F 40 01 00 00 00 00 01 01 01 01 01 01 01 01 01 01 49 F7
From Arduino sending to usb (without f0+f7)
3E 00 00 4A 7F 7F 40 01 00 00 00 00 01 01 01 01 01 01 01 01 01 01 49
received on PC
F0 00 3E 00 00 4A 7F 7F 40 01 00 00 00 00 01 01 01 01 01 01 01 01 01 01 49 F7

@steinundfloete
Copy link
Author

Seems it doesn't happen when sending to serial MIDI, otherwise the Synth wouldn't reply
So this is a problem of the USB Midi

@steinundfloete
Copy link
Author

Any idea?

@lathoub
Copy link
Owner

lathoub commented Mar 22, 2023

Have you tried sending SysEx through USB, hardcoded, without the Serial USB in the code. So send the SysEx every second like in the example code. (and put Serial.print in the USB write code).

Most of the write code is here:

auto i = mTxIndex % 3;
if (byte == MidiType::SystemExclusiveEnd)
mPacket.header = MAKEHEADER(cableNumber, (0x05 + i));
if (i == 0) {
mPacket.byte1 = byte; mPacket.byte2 = mPacket.byte3 = 0x00;
}
else if (i == 1) {
mPacket.byte2 = byte; mPacket.byte3 = 0x00;
}
else if (i == 2) {
mPacket.byte3 = byte;
if (byte != MidiType::SystemExclusiveEnd)
SENDMIDI(mPacket);
}

Add some Serial.print and see what is being send

@steinundfloete
Copy link
Author

Yes, this works. It looks like I did some mistake on copying the bytes.
But did you recognize the other things I mentioned?

@lathoub
Copy link
Owner

lathoub commented Mar 22, 2023

But did you recognize the other things I mentioned?

A bit, the begin- and end sysEx brings back the programming memories.

Yes, this works. It looks like I did some mistake on copying the bytes.

So, all good?

@steinundfloete
Copy link
Author

Without modifying the incoming message it will not work. That is what I experienced here

@steinundfloete
Copy link
Author

steinundfloete commented Mar 24, 2023

Shortmessages:
I have to set the message.length to the real message length then it works.
The received message contains a length of 0. This doesn't work

@steinundfloete
Copy link
Author

steinundfloete commented Mar 24, 2023

SysEx Messages:
The received message struct, length + coded length (data1+2) always contain F0+F7
forwarding the SysEx Message to USB / Serial: You have to

  • remove F0+F7,
  • decrease message length by 2
  • decrease data1 + data2 coded length by 2
    Otherwise it won't work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants