SysEx with Erae 2 - Firmware v2.1.17

There is something going on with MIDI when I attach USB from MM to my computer when a patch is NOT playing… it’s echoing back the SysEx that MacOS sends to query devices on attach. I don’t know, does the Erae maybe send out a query message that’s getting echoed?
The fix for this is easy, and I’ll push it, too.

Another issue is that if I have no USB MIDI connected, and then I play a patch that sends MIDI, then stop the patch, then plug in USB MIDI, I get the last 512B of data transmitted. That should be easy to fix – just clear the buffer on MIDI connect event.

I don’t believe so, at least Ive not seen any evidence of this when attaching Erae to macOS.
that said, the Erae has alot of midi function outside of sysex, e.g. it can send notes and clock etc… so, so something like clock could being sent whilst a patch was not running…

hmm, I guess, your thinking the midi queue is being filled when no patch is consuming it?
I guess if your then getting some ‘odd’ echoing of input → output queue, then yeah, perhaps that has to be drained before the first sysex gets thru? (and the midi output buffer is full so lost)
is that your reasoning?

its interesting..
definitely, the MM should not be passing in->out ‘automatically’, either with patch running or not, as that could cause issues with things like clocks, or various other midi topologies where you might start echoing message around…
essentially, you’d rarely expect a device to echo midi !

also, surely for output you are consuming the event (from patch), and if no usb device is connected, you can simply consume, and drop it… theres no need to queue, and wait for a device to attach?

edit: actually, Im reasonably sure I turned Erae’s clock off, so I dont think it was sending messages before patch started, but I’ll double check tommorow

it’s echoing back the SysEx that MacOS sends to query devices on attach.

afaik, macos does does not send any sysex to query devices, it queries devices via the usb protocol not sysex - there is no ‘standard’ sysex amongst devices for it to be able to query with?! perhaps im misunderstanding ?

OK, all known bugs are fixed, at least all the weirdness I was able to make happen is no longer happening. Here’s the poly branch:
https://github.com/4ms/metamodule/releases/download/firmware-v2.1.99-poly009/metamodule-firmware-v2.1.99-poly009-firmware-assets.zip

I wasn’t properly draining the MIDI queue when the patch was not playing, which ended up recycling the buffer into TX., and didn’t drain the buffer at all on disconnection.

I was surprised too. But, yeah, Apple has a SysEx capability inquiry system: MIDI Capability Inquiry | Apple Developer Documentation
The local echo (which I fixed) made me think the packets originated from the MetaModule. Turns out they came from the OS and just got echoed back.

ok, cool stuff, that seems to have fixed it :tada:
(I can now send the enable immediately, at get the response, don’t have to wait for a bit)
thanks for your efforts in this!

note:
I did (still) have one instance of a hard lock up…
interestingly, if its going to lock up, it appears to lock up reasonably soon after module is loaded, e.g. in first few seconds, if it gets beyond that, it seems to work fine..
its reasonably rare, and I cannot guarantee is not something Im doing, though Ive not seen in on the desktop.

anyways, working nicely on the poly branch, I can see multi touch coming thru (up to 4 touches, as per PORT_MAX_CHANNELS)

I was surprised too. But, yeah, Apple has a SysEx capability inquiry system

ah, that’s midi 2.0… I’d assumed (obviously incorrectly) that the usb descriptor would identify midi 2.0 devices, and things like CI would only be sent to those…
apparently not it seems, good to know - thanks :slight_smile:

Q. can I identify, when midi devices are connected / disconnected? is there a callback?
I can dig thru the details myself, ideally, Id no if its an Erae connected, so I dont start sending to some random device ;))

again thanks for your support and effort in getting this working !

Yes!! Thanks for the help figuring this out. Many of these were long-time lurking bugs that never saw light due to the small size of normal MIDI packets (or dropping one CC message out of a stream was not noticed).

I’ll keep my eye out for a lockups, of course. So far I haven’t hit any (running full-throttle tests for 15-20 minutes).

Not yet, though that would be part of the plan to have a MIDI connection selector. I suppose an easy first step would be an api to query the VID/PID and device name, and USB MIDI jack number and string name. Second step would be the api to select one as the source

1 Like

yeah, as i mentioned, oddly the lock up seem to be more likely in first few seconds, than extended periods of running / or message quantity (at least as far as ive observered)

perhaps a test which repeatedly creates / waits, sends msgs/ destroys may be more likely to catch, if its related to start up timing?


yeah, I think my main concern was,
currently, my module would not know if something was on the other end, so would repeatedly send msgs out to attempt a connect… similarly, if a device disconnected, id not know, and would keep sending messages.

I guess it doesn’t matter if the firmware is draining the queue…

generally in this particular case, its safe to say the module will be created/removed if the Erae alonside the Erae connection, so not really a big issue - and I could also add ‘manual’ control to start/stop as well.

I think this is a valid thing – a module could be able to query what’s connected. I started working on this.. perhaps I went down a worm-hole but I thought it’d be useful to know all USB connection info, like whether a USB drive connected, or if the MM is host or device mode

1 Like

I, similarly, initially thought, knowing anything was connected was good enough,
then realised Id still be sending as id not get a response… so needed to know what was connected.
so yeah, I can see how use-cases expand quickly, and you dont want to keep changing the API.

for now, its fine… there are simple workarounds
e.g. I can simply disable the module when Ive not got the erae connected, and/or use the bypass as an enable/disable switch.

and given the IO buffers are fixed , im not filling ram with these messages.

Re: an API to query the USB state, I ended up making this work, at least so far so good.

Here’s the API functions I think that will cover querying the attached USB device:

UsbConnectionStatus get_usb_connection_status();

// returns general device info:
struct UsbConnectionStatus {
	uint16_t vid = 0; // attached device's idVendor
	uint16_t pid = 0; // attached device's idProduct

	UsbConnectionType connection; //enum of state (None, HostMidiDevice, HostUsbDrive,...)
	uint8_t num_midi_in_jacks = 0;
	uint8_t num_midi_out_jacks = 0;

	StaticString<63> manufacturer; // iManufacturer string (may be empty)
	StaticString<63> product;	   // iProduct string (may be empty)
};

Then if you want to query about the MIDI jacks, pass an ID to these functions:

UsbMidiJackInfo get_usb_midi_in_jack_info(unsigned num);
UsbMidiJackInfo get_usb_midi_out_jack_info(unsigned num);

// returns this:

struct UsbMidiJackInfo {
	StaticString<31> name;	  // the jack's iJack string descriptor (may be empty)
	uint8_t jack_id = 0;	  // bJackID: the device's own ID for this jack
	bool is_embedded = false; // true: Embedded jack (a real port); false: External
	bool valid = false;		  // false if no such jack
};

The data structures are raw data shared between architectures (A7/M4) so keeping them POD is essential (no std::string, even std::optional makes me nervous…)

With this, a plugin module could query the jack info, present the jack names to the user in the form of the context menu, and then let the user choose one to send to (or receive from). Then the plugin would use that USB MIDI Cable number on all its packets (and/or filter incoming MIDI by cable number).

So the idea I’ve been having of a MIDI device chooser could actually be implemented completely as a plugin. Of course we still could implement it as a built-in feature, but it’s nice knowing modules should have that level of flexibility

1 Like

looks perfect, for my use-case, using the vid/pid would do the trick!

Q. do we have a callback already for connect / disconnect?
or do I just poll get_usb_connection_status() (when approriate)?

is this in poly branch? no rush, but once its there, I’ll give it a test.

Cool, yeah it came together nicely.
It’s on the usb host/device mode branch. The plan is to merge the poly branch first, then the usb branch next.

No callbacks, just polling.

1 Like