Page 1 of 3

USB Composite library MIDI Get Bytes without using Callbacks

Posted: Sat Jan 08, 2022 12:18 am
by jhsa
Hi, first poster here :) and a beginner with Arduino, so please be gentle :)

Is there a way of passing all received MIDI information via USB, without using the callbacks, and send it to serial for example?
Something like this, but obviously adapted for this library.

Code: Select all

if (midiA.read())
  {
    if ((Send_A_To == 1) || (Send_A_To == 3)) {
      midiB.send(midiA.getType(),
                 midiA.getData1(),
                 midiA.getData2(),
                 midiA.getChannel());
    }
I don't think this library recognizes "getType", "getData1", etc?

Thank you
João

Re: USB Composite library MIDI Get Bytes without using Callbacks

Posted: Wed Jan 12, 2022 2:47 am
by jhsa
Anyone?

Re: USB Composite library MIDI Get Bytes without using Callbacks

Posted: Wed Jan 12, 2022 8:54 am
by fpiSTM
Hi, I guess you used the USBComposite ?
With Roger's core?

I never work with USB Midi, so I have no feedback on this.
Maybe some other user have one anyway if you have no feedback probably it means no one has an answer/clue.

Re: USB Composite library MIDI Get Bytes without using Callbacks

Posted: Wed Jan 12, 2022 9:34 am
by ag123
i've not played with that, but among the suggestions I'd try:
1) get a usb sniffer on the host side
in linux, wireshark can do something like such
https://wiki.wireshark.org/CaptureSetup/USB
there are others, u'd need to 'google/bing' search for them

2) keep a 2nd channel debug handy
st-link v2 comes to mind, it literally allows you to trace codes, that is invaluable for this purpose
as a poorer alternative, a usb-uart dongle likely help as you can Serial.print() to the usb-uart to debug things.

and you would need to be pretty familiar with the usb protocols
https://www.usb.org/
https://www.usb.org/hid

usb is 'not for novices' due to the complicated protocol and the protocol stacks on both device and host side.
but the rewards for digging deep in is large, it makes it possible to do 'driverless' stuff like keyboards and such.
note that hid may need applications on the host side to support even if it is just hid, hid is a pretty complicated protocol on its own.

Re: USB Composite library MIDI Get Bytes without using Callbacks

Posted: Wed Jan 12, 2022 2:43 pm
by Bakisha
I have some test code from a time when i was experimented with midi, but i'm not sure what you are looking for.

Anyway, this short sketch should send stuff over USB serial port, midi data received from PC as Maple midi out device (uploaded with st-link).

Code: Select all


#include <USBComposite.h>

#define SPEAKER_PIN PA8


class myMidi : public USBMIDI {
    virtual void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) {
      digitalWrite(PB12, HIGH);
            CompositeSerial.print("ON - ");
            CompositeSerial.print(channel, HEX);
            CompositeSerial.print(" ");
            CompositeSerial.print(note, HEX);
            CompositeSerial.print(" ");
            CompositeSerial.println(velocity, HEX);
      noTone(SPEAKER_PIN);
      digitalWrite(PB12, LOW);
    }
    virtual void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) {
      digitalWrite(PB12, HIGH);
      CompositeSerial.print("OFF- ");
      CompositeSerial.print(channel, HEX);
      CompositeSerial.print(" ");
      CompositeSerial.print(note, HEX);
      CompositeSerial.print(" ");
      CompositeSerial.println(velocity, HEX);
      tone(SPEAKER_PIN, (midiNoteFrequency_10ths[note] + 5) / 10);
      digitalWrite(PB12, LOW);
    }

};
myMidi midi;

USBCompositeSerial CompositeSerial;

void setup() {
  pinMode(PB12, OUTPUT);
  USBComposite.setProductId(0x0020);
  pinMode(SPEAKER_PIN, OUTPUT);
  midi.registerComponent();
  CompositeSerial.registerComponent();
  USBComposite.begin();

}
void loop() {
  midi.poll();
}

Re: USB Composite library MIDI Get Bytes without using Callbacks

Posted: Wed Jan 12, 2022 7:33 pm
by jhsa
Woow, no replies, and then lots of them.. :) Thank you.
At the moment, for the project I am trying to accomplish I am using the callbacks from the USB Composite library. The problem is that I have to use a "virtual void" for every midi event I want to handle. This will make the code extremely big and moire complex :( With the other MIDI library it is much easier. This project is a MIDI Router, which interconnects 4 different MIDI inputs and Outputs. 3 serial and 1 USB. I am using the Blue Pill board with an STM32F103C8 chip, and Roger's core. Here is part ( one input) of my code's main loop. Please see the difference on the sending a serial input "midiA" to the outputs of midiB, midiC, and midiD, which is the USB. On the first 3 I just handle the data. For the USB, I need to handle every single event.
And this will complicate more when I get to send the USB input to the others, as I will have to code it inside the callback functions for each event :o
This is why I am wondering if this library has something similar.

Code: Select all

if (midiA.read())
  {
    if ((Send_A_To == 1) || (Send_A_To == 4) || (Send_A_To == 5) || (Send_A_To == 7)) {
      midiB.send(midiA.getType(),
                 midiA.getData1(),
                 midiA.getData2(),
                 midiA.getChannel());
    }

    if ((Send_A_To == 2) || (Send_A_To == 4) || (Send_A_To == 6) || (Send_A_To == 7)) {
      midiC.send(midiA.getType(),
                 midiA.getData1(),
                 midiA.getData2(),
                 midiA.getChannel());
    }

// Now send midiD (USB)

    if ((Send_A_To == 3) || (Send_A_To == 5) || (Send_A_To == 6) || (Send_A_To == 7)) {
      unsigned int data1 = midiA.getData1();
      unsigned int data2 = midiA.getData2();
      unsigned int channel = midiA.getChannel();

      if (midiA.getType() == 0xC0) midiUSB.sendProgramChange(channel - 1, data1);
      if (midiA.getType() == 0x80) midiUSB.sendNoteOff(channel - 1, data1, data2 );
      if (midiA.getType() == 0x90) midiUSB.sendNoteOn(channel - 1, data1, data2 );
      if (midiA.getType() == 0xA0) midiUSB.sendVelocityChange(channel - 1, data1, data2 );
      if (midiA.getType() == 0xB0) midiUSB.sendControlChange(channel - 1, data1, data2);
      if (midiA.getType() == 0xD0) midiUSB.sendAfterTouch(channel - 1, data1);
      //      if(midiA.getType() == 0xE0) midiUSB.sendPitchChange(channel - 1, data1);
      if (midiA.getType() == 0xF3) midiUSB.sendSongSelect(data1);
      if (midiA.getType() == 0xF2) midiUSB.sendSongPosition(data1);
      if (midiA.getType() == 0xF8) midiUSB.sendSync();
      if (midiA.getType() == 0xFA)  midiUSB.sendStart();
      if (midiA.getType() == 0xFB)  midiUSB.sendContinue();
      if (midiA.getType() == 0xFC)  midiUSB.sendStop();
    }
  }

Re: USB Composite library MIDI Get Bytes without using Callbacks

Posted: Wed Jan 12, 2022 8:19 pm
by ag123
use a bigger chip may be re series etc or better still stm32f401xx or higher. I'm not sure if you need the cpu prowess but that f4xx series has that 'ART accelerator' (on chip cache) and FPU.
if you do any kind of dsp processing then f4xx is certainly the way to go

f4 support in libmaple is deemed 'steve's core' he wrote the most of it and is functional but lean. i.e. don't expect 'everything' to be there.
usb composite is unlikely to work there.
so for anything more than that on f4 stm core is probably the core with most 'hidden' features, it has the whole of HAL and CMSIS at your disposal, but consequently 'fatter'. it is also currently one with the largest stm32 cross-series 'platform' support, from f0, f1, f3, f4, f7, to h7 and mp1

Re: USB Composite library MIDI Get Bytes without using Callbacks

Posted: Wed Jan 12, 2022 9:22 pm
by Bakisha
IMHO, yes, you'll need to program every event when received from or send to USB.
Whole purpose of USB Composite library is that it can be detected to computer as midi device (for receiving and sending) and virtual com port at the same time. Maybe even HID device? I forgot the limitations...
You can see what functions is available in USBMIDI.h in USB Composite library's folder.
I'm guessing that you are using arduino_midi_library, but i'm not familiar with it, nor it's syntax.
jhsa wrote: Wed Jan 12, 2022 7:33 pm And this will complicate more when I get to send the USB input to the others, as I will have to code it inside the callback functions for each event
Yes, basically, that's what you have to do with USB Composite library.

Re: USB Composite library MIDI Get Bytes without using Callbacks

Posted: Thu Jan 13, 2022 7:35 am
by ag123
Another possible implementation is to use USB Serial rather than HID for the midi router implementation.
My guess is that this would be simpler, and it saves having to deal with a HID implementation.
it makes the codes a lot simpler as you could use Serial.print() and Serial.read()
I'd guess you may still need to deal with each event say in an if - else switch or switch - case setup, this in part as there would otherwise be little means of telling apart the devices.

if you do things at the USB HID, or USB CDC ACM level, my guess is that you can literally program different HID or CDC endpoints as 'channels'.
In that way, they could possibly appear as multiple devices to the host even though you have only a single stm32f103 pill board.
I think HID itself also has a concept of multiple different report types (identified by their report IDs), that could possibly be used to implement a 'multi device' interface. I'm not sure if that would mean changes on the host side as well. But this isn't using usb composite, you are writing the usb driver itself if this is the case.

Re: USB Composite library MIDI Get Bytes without using Callbacks

Posted: Thu Jan 13, 2022 2:51 pm
by jhsa
ag123 wrote: Wed Jan 12, 2022 8:19 pm use a bigger chip may be re series etc or better still stm32f401xx or higher. I'm not sure if you need the cpu prowess but that f4xx series has that 'ART accelerator' (on chip cache) and FPU.
if you do any kind of dsp processing then f4xx is certainly the way to go

f4 support in libmaple is deemed 'steve's core' he wrote the most of it and is functional but lean. i.e. don't expect 'everything' to be there.
usb composite is unlikely to work there.
so for anything more than that on f4 stm core is probably the core with most 'hidden' features, it has the whole of HAL and CMSIS at your disposal, but consequently 'fatter'. it is also currently one with the largest stm32 cross-series 'platform' support, from f0, f1, f3, f4, f7, to h7 and mp1
Yeah, I know for a fact that the F401 doesn't work with the USB Composite library, Tried it. But this is expected as this library was created for the F03 only? Unless something changed lately of course, but I don't own any F401 at the moment.

João