USB Composite library MIDI Get Bytes without using Callbacks

Post here first, or if you can't find a relevant section!
jhsa
Posts: 26
Joined: Sat Jan 08, 2022 12:10 am

USB Composite library MIDI Get Bytes without using Callbacks

Post 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
by ag123 » Fri Jan 14, 2022 4:33 pm
USB has something called the 'single ended zero' - usb reset. i.e. pull both D+ / D- to gnd for 10ms
https://www.usbmadesimple.co.uk/ums_3.htm
resetting the mcu do not necessarily send the 'single ended zero'. so it may be a problem on the *host* side, i.e. the host 'remembers' the previous state and do not enumerate ports again.
a usual 'trick' is to enable or disable the device in windows, i'm not sure if there are other 'short cuts'
in linux there is a little piece of code that can do that usb reset
https://github.com/jkulesza/usbreset

it is possible to do this usb reset in your codes, e.g. in setup etc
e.g.

Code: Select all

pinMode(PA11, OUTPUT);
pinMode(PA12, OUTPUT);
digitalWrite(PA11, LOW);
digitalWrite(PA12, LOW);
delay(10);
pinMode(PA11, INPUT);
pinMode(PA12, INPUT);
the trouble here is actually this is incorrect, you need to restore the AFIO to USB after this.
it would be better to search in RM0008 for a proper means to do this usb reset

and you probably need to do this prior to calling usbComposite.begin() for that matter.
Go to full post
jhsa
Posts: 26
Joined: Sat Jan 08, 2022 12:10 am

Re: USB Composite library MIDI Get Bytes without using Callbacks

Post by jhsa »

Anyone?
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: USB Composite library MIDI Get Bytes without using Callbacks

Post 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.
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USB Composite library MIDI Get Bytes without using Callbacks

Post 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.
User avatar
Bakisha
Posts: 139
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 5
Contact:

Re: USB Composite library MIDI Get Bytes without using Callbacks

Post 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();
}
jhsa
Posts: 26
Joined: Sat Jan 08, 2022 12:10 am

Re: USB Composite library MIDI Get Bytes without using Callbacks

Post 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();
    }
  }
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USB Composite library MIDI Get Bytes without using Callbacks

Post 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
User avatar
Bakisha
Posts: 139
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 5
Contact:

Re: USB Composite library MIDI Get Bytes without using Callbacks

Post 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.
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USB Composite library MIDI Get Bytes without using Callbacks

Post 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.
jhsa
Posts: 26
Joined: Sat Jan 08, 2022 12:10 am

Re: USB Composite library MIDI Get Bytes without using Callbacks

Post 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
Post Reply

Return to “General discussion”