SysEx with Erae 2 - Firmware v2.1.17

had a chance to work on this, basically connecting an Erae 2 to the MM to use the Erae 2 developer API (based on sysec) for some ‘custom’ UI for MM :slight_smile:

ok, before I continue, apologise i didnt get to test this before release,

here is what Ive found…

issues

a) sysex not sent?
Ive trace the call to sendMessage, and thats ok but nothing comes out.

not, only does Erae not initialise, but using a usb midi monitor it sees no sysex? but connnect to vcv on mac, and its fine.

I tested by sending a note message out, and that worked (so my midioutput object ‘appears ok’)

do I need to enable sysex at all? saw no reference to this in midi.hpp?

b) Sysex received , but appears incomplete.
k, so using the mac, I can initialise the erae to put in correct mode (to get around (a))

then connect to MM, and I can see sysex.

BUT the messages are incomplete…I do get F0 … data … F7, but they are missing ‘continuation’ packets…

thoughts on possible issues?

no idea about the output, just looks like its not sending sysex

input, a LOT of sysex is generated, each touch is 32 bytes, but its sending pretty continuously, so it could be you have some kind of limited buffer size, and overruns are happening?

Im polling inside process() and draining midi queue each time - so its not draining, its on ‘input’ somewhere.

(Id hope test with smaller messages but its hard as the send/init is not working properly)

Background

just an fyi, so you know what Im talking about,

Im using this to talk to an Erae mk2, using the sysex api found here.

basically you send a 16 byte sysex to turn on streaming , then start getting in (finger aka touch) messages, which doesnt happen.

If I do this initisaliation from my mac (erae holds state), then I do start getting in touch messages but the data is incomplete… they should be 32 bytes, but instead are 21 or 18.

testing - mac vs hardware

so Ive tested the underlying code on mac, so the ‘protocol’ logic is correct.

it also works within vcv desktop fine, as vcv sdk2 now handles variable length midi msgs fine as uses a byte vector… and so sysex passes thru both ways fine.

so the ‘only’ difference is the ‘chunking’, but Ive put in quite a bit of effort to test this - Im pretty sure this is correct. it looks like its at the hardware layer things go awry.

testing limitations

i dont really have a lot I can do hardware debugging with, mainly been sending text to module display. I also dont have a usb analyser so cant see usb packets sent.

I do have USB midi monitor, which Ive used… but its pretty limited, I could only see if sysex was sent - which it wasnt (except when on mac)

unfortunately, Erae has no way to throttle data, so I couldn’t get it to back off…

where next?

Sorry, I know thats not a lot to go on… so I guess at this stage the questions are more about my understanding.

a) Why does the send not work?

this seems like a good starting point… as Im able to get note on/off out, why not sysex? and the messages are only 16/14 bytes…

b) what limitations are in place?

I guess if we know something about queue/buffer sizes, and what happens in overruns, we might be able to explain behaviour when dealing with larger or very frequent messages.

theres a chance this is not a bug , but rather limitations.

Did you use the startSysEx(), continueSysEx(), and endSysEx() (and a few others)?
Make sure you’re compiling your plugin against SDK v2.1.1 (latest tag).
Here’s the relevant section of midi.hpp:

That’s a more strange issue… The internal queue is 128 messages in size, so I would be surprised if that is overflowing. But… I think it’s silent if there’s an overrun so I probably should have it at least spit out an error to the console!

Well, if you are using Message::getSize() on pre-SDK v2.1.1 then it would tell you the wrong size and you’d “lose” packets?

Hmm.. I’m looking through the code, and I do block incoming 0xFE status bytes (active sensing) and also 0x00 status bytes. Maybe that’s a problem? Because with sysex, 0x00 could legally be in the “status” byte position (byte 0 of a triplet). Could that be the issue?

Outgoing are not filtered at all (at least not intentionally).

I’ll ponder it some more, but first confirm if what SDK version you’re compiling against so we can rule that out at least.

And also helpful if you can give me the raw packets you receiving? E.g. the expected 32 bytes and the actual 21 or 18 that you receive. Maybe I can spot a pattern (like, all packets starting with 0x00 are dropped?)

Also do you have a UART/USB dongle? We could have the M4 core dump the raw packets it’s receiving and at least see if they’re getting dropped at the driver level or later in the subscriber/queue level.

yes, using latest sdk,

a) yes, Im using these methods,

basically, Im doing a conversion from a single stream into these methods

my source sysex are the following

// init sequence to erae
// [ 0xF0 0x00 0x21 0x50 0x00 0x01 0x00 0x02 0x01 0x01 0x04 0x01 0x00 0x01 0x02 0xF7] - start stream
// [ 0xF0 0x00 0x21 0x50 0x00 0x01 0x00 0x02 0x01 0x01 0x04 0x10 0x00 0xF7] - request zone boundary
// [ 0xF0 0x00 0x21 0x50 0x00 0x01 0x00 0x02 0x01 0x01 0x04 0x20 0x00 0xF7] - clear

even sending just the first seems to ‘fail’

I added debug statements, to see these were converted properly

whats odd, is is using a usb midi monitor, I see nothing at all for sysex, yet things like note messages work fine.

Ive not looked at your code, but it felt like either i) you are filtering messages ii) you are waiting for something, and never sending? (e.g. F7), doesnt feel like 2 is likely, as there’d be no reason for you to buffer/wait for end of sysex before sending…

b) receiving

yes, dropping 0x00 would cause issues…, sample message shows, I do have 0x00 in most touch messages.

// touch msg
// 32 data [ 0xF0 0x00 0x01 0x02 0x00 0x00 0x40 0x60 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x52 0x52 0x30 0x02 0x41 0x34 0x4F 0x33 0x30 0x41 0x27 0x50 0x26 0x3F 0x24 0xF7 ]

Im not sure if this would entirely explain the issue, but certainly a first step.

Well, if you are using Message::getSize() on pre-SDK v2.1.1 then it would tell you the wrong size and you’d “lose” packets?

Im using latest SDK, and no, this wouldn’t… the individual ‘broken’ packets you are sending are complete / correct in themselves. its just im missing some continue packets. (but i see the start/end fine)

but then if you are dropping 0x00 status that would explain it, as you are dropping some ‘continue’ packets, ie packets in the middle of the stream.


more generally, ok the 128 byte queue, is that for send or receive? and at what frequency are you polling?

for the send side, yeah, this shouldn’t be an issue - as by definition, i can throttle this within the omodule.

on the receive side, ok, so Im getting 32 byte touch packets, probably at something like 30-60 / second, per touch (its not in the spec but I could calculate on desktop). ofc, im only testing with one finger
but if your buffer is ‘only’ 128 bytes, then that 4 packets, so really depends on your polling frequency.

also are you talking about your midi buffer on the usb reading thread? or between the IO process and dsp cores/processors… that later I poll at sample rate so is a non issue. but the former I have zero control over.

yeah, i think somewhere I do in one of my boxes, as I used to use on my other embedded projects.

but thought, Id do some sanity checking before jumping into the weeds.

Ive a suspicion this is something relatively simple - it could be if I look at the firmware source I can spot the issue too…

but sure, if I hit a roadblock I’ll dig it out.

OK, this is what I’ll tackle first. I have MIDI Device mode working on my dev branch, so I can easily send these packets and view on the computer (I don’t have a standalone MIDI monitor).

Each side has a 128 message queue. Each message is a usb packet, 4 bytes, though in the case of SysEx only 3 bytes are available since the first byte is the USB cable/code. So, 384 usable SysEx bytes for RX and 384 for TX.

For RX, the M4 core pushes zero or one received 4-byte MIDI message (1 USB header byte + 3 status/data bytes) on every audio frame.
The queue is popped at block rate, max one 4-byte message per frame in the block.

So that could be the issue if the block size is large or sample rate is slow. What block size and sample rate are you using?

Say you have block size of 256, at 48kHz. A burst of 150 messages (ie 450 sysex bytes) comes in. The M4 will fill up the queue before the next audio block is ready to drain it. Definitely a bug.
If dropping the block size down and bringing the sample rate up fixes RX for you, then that’s definitely the issue you’re seeing.

And… looking deeper… I see the USB MIDI Host driver TX has two 64 byte buffers (double-buffered, so it can queue a TX message while one is being sent). Yeah, that’s a problem for sysex! I’ll make it larger. But it doesn’t explain why you see no sysex at all.

For RX, the USB driver’s queue is 256 bytes but looks like I’m only using 128 bytes of it. Even if you are sending 60 touch packets per second that’s only 1920bytes/second and the M4 drains one 4-byte packet at frame rate (min 4 x 24kHz), so that shouldn’t be the bottleneck.
I’ll still boost it up, there’s no reason to keep it so small.

OK I’ll play with TX monitoring, and boost those buffer sizes. In the mean time if you can try and see if block rate and sample rate change behavior?

1 Like

cool this is the kind of info I was after :slight_smile:

ah ok, thats interesting…

so Im using the default, so 128 @ 48k, so from what you are saying 32 byte packets is going to be 8 blocks (its not read at sample rate, but effectively SR/BS)

(is there a reason not to drain the entire queue for each block?)

so, about 46.875 msgs per second. I suspect not an issue for a single touch (as I’ve been testing), but, could be for multi touch… e.g. 4 touches, that said, they’ll only send ‘on change’, the issue is with most of these expressive controllers, the sensitivity means its almost always changing a biit.

but.. thats not MM issue, we can see where we get, once we get to that stage.

I think at the moment, my first test, would be to get rid of the filtering of 0x00 status, as that could well be the main issue… at least we know that IS dropping packets.

I’ll def have a look at SR/BS, but without the 0x00 fixed, we know it wont work, thats 100% an issue.

I can also see if I can transmit any sysex, aside from this… e.g. a fixed stream every N seconds… it wont work with Erae, but Id assume my usb midi monitor would be able to show it. (its working with mac for sysex, and also with other messages from MM)

OK, working on the TX issue first:

I’m able to send 16 bytes of SysEx to my computer (with MM in MIDI device mode), and I catch them all using the Stoermelder MIDI-MON (except there’s two garbage bytes at the end after the 0xF7? Not sure if that’s a MIDI-MON issue?)

But, that’s the new Device mode, so to test legacy Host mode, I connected two MM together, and dumped the TX MIDI on one unit to one UART console, and dumped the RX MIDI on the other unit to a different console.

TX MetaModule (USB Host, firmware v2.1.17)
04f00021
04500001
04000201
04010401
04000102
05f70000

RX MetaModule (USB Device, dev firmware)
04f00021
04500001
04010401
05f70000

Edit: Oops, I missed it the first time, but I can see clearly the pattern now! All packets with 0x00 in the status byte position are dropped on the RX end.

And, BTW here’s the MIDI device enabled firmware:

Edit2: Here’s how I’m sending the MIDI (I just added this to the top of the process() function for the RackCore CV_MIDI module):

	void process(const ProcessArgs &args) override {
		static int sysex_i = 0;
		if (sysex_i < 6) {
			midi::Message m;

			// 0xF0 0x00 0x21
			// 0x50 0x00 0x01
			// 0x00 0x02 0x01
			// 0x01 0x04 0x01
			// 0x00 0x01 0x02
			// 0xF7

			switch (sysex_i) {
				case 0:
					m.startSysEx(0x00, 0x21);
					break;
				case 1:
					m.continueSysEx(0x50, 0x00, 0x01);
					break;
				case 2:
					m.continueSysEx(0x00, 0x02, 0x01);
					break;
				case 3:
					m.continueSysEx(0x01, 0x04, 0x01);
					break;
				case 4:
					m.continueSysEx(0x00, 0x01, 0x02);
					break;
				case 5:
					m.endSysEx();
					break;
			}
			sysex_i++;

			midiOutput.sendMessage(m);
			return;
		}
... rest of process() function goes on...

OK, I fixed the dropped 0x00 RX packets, and we now get correct packets on the RX end. That confirms basic SysEx TX->RX behavior is working at least when the packets are small and infrequent.
My first test (above) was throttling them to one USB packet per audio frame. Once that worked, I tested it like this:

	midi::Message m;
	m.startSysEx(0x00, 0x21);
	midiOutput.sendMessage(m);
	m.continueSysEx(0x50, 0x00, 0x01);
	midiOutput.sendMessage(m);
	m.continueSysEx(0x00, 0x02, 0x01);
	midiOutput.sendMessage(m);
	m.continueSysEx(0x01, 0x04, 0x01);
	midiOutput.sendMessage(m);
	m.continueSysEx(0x00, 0x01, 0x02);
	midiOutput.sendMessage(m);
	m.endSysEx();
	midiOutput.sendMessage(m);

and it still works.

But, then I tested sending 32 bytes at 240 times per second, and by the time the messages get to the USB TX buffer, they’re out of order and perhaps some are dropped? So.. yes, bug confirmed! Thank you for that. Not sure what’s causing it, but at least I can reproduce now.

Firmware with 0x00 RX packet dropout fixed:
https://github.com/4ms/metamodule/releases/download/firmware-v2.1.18-midifix01/metamodule-firmware-v2.1.18-midifix01-firmware-assets.zip

Fix on the poly branch:
https://github.com/4ms/metamodule/releases/download/firmware-v2.1.99-poly008/metamodule-firmware-v2.1.99-poly008-firmware-assets.zip

thanks for this, really great stuff, I really appreciate your efforts on this

ok, first some good news :slight_smile:

the 0x00 has fixed the RX problem :tada:

ok, to be clear… Im not sending this volume of sysex, we are failing on just 3 messages…

not saying this is not an issue, just want to be clear, its not in scope of my particular issue, at least for now :wink:

as expected, due to no change, TX is still not initialising erae.

ok, so I thought Id try your example…

also Ive got (midi) usb host to usb host converter, which I realised might work so I can see/capture midi on the mac.

so, rather than sending my messages, I just used your code, and sent it every few seconds

what I saw was I got back

14:58:10.471	From MIDI USB-USB Puerto 1	Invalid		9 bytes
14:58:10.480	From MIDI USB-USB Puerto 1	Invalid		4 bytes
14:58:12.473	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:14.473	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:16.473	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:18.473	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:20.472	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:22.472	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:24.472	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:26.472	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:28.472	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:30.472	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:32.472	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:34.472	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:36.472	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7
14:58:38.472	From MIDI USB-USB Puerto 1	SysEx		Embodme 16 bytes	F0 00 21 50 00 01 00 02 01 01 04 01 00 01 02 F7


so what about these invalid bytes?

first was : 00 50 00 01 00 02 01 01 04 01

second was : 00 00 01 02 F7

so what appears to happen is we lost the first packet.

every time I started the MM, I noticed the same pattern, the first packet ‘lost’ (first 3 bytes - F0 00 21), and then invalid bytes, sometime reported as two packets as above, sometimes as one.

Interestingly before I did this test, I just did a note on, then your sysex one - and the note of msgs was similarly corrupted - it had a status of 0x00 (not 0x90)

THAT SAID… I’d urge a little caution here,

a) Im using a usb-usb host converter

I’ve never had an issue with this, its been (surprisingly) reliable, but still ‘its a thing’

b) mac midi monitoring

I use “MIDI monitor”, and Ive in the past seen invalid bytes from other applications when Ive not expected them… so I don’t 100% trust it :wink:

ofc, missing these first 3 bytes of the init, would mean the erae would not initialise… as its incomplete… but im not 100% sure this is case, or just a test/debug issue.
interestingly, you seem to have seen something similar, but with garbage at the end… (which i did not encounter)

note: I dont know how well the Erae hardware will ‘recover’ from corrupted streams… Id assume it’ll do similar to these monitors, so ‘recover’ when it can, e.g. after seeing an appropriate F0 / F7. but that is an assumption…


ending on a positive note…

the RX seems ‘solved’ (at least for functional testing side)

we do seem to get be getting somewhere on the TX, its good that I can see SOME sysex getting thru - this gives me some things to try…

perhaps try to force /resend the init… based on what weve seen in the midi monitor

it’d be interesting to see if that can get the Erae sending data, even if its a bit ‘faked’.

perhaps if I send it twice, that’ll overcome the first corrupted message?
also look to see if the corruption only happens if sysex gets involved, or if its always first 3 bytes regardless?

but, as I said, still not 100% sure that what im seeing on monitor is reliable and so if its the issue with the Erae.

Interesting… the first packet being corrupted could be some uninitialized buffer perhaps. I can look for that. Or, as you say, it could be our measurement tools… I’m using the MM itself as a monitor but even that is not a “known working reference”.

Excellent! That one was easy at least!

For the TX, I’ll poke around more today. The high-volume dropouts are likely due to the small buffers, and I know it’s probably not what’s causing the failed init sequence.

1 Like

ok, some news, and kind of success on the TX side…

I think generally the issue is dropping packets!

so, I tried to just send the ‘canned init’ message once before , sending my own…nada

I then put the send message in a loop of 20… - nada.

e.g.

	midi::Message m;
	m.startSysEx(0x00, 0x21);
	midiOutput.sendMessage(m);
	m.continueSysEx(0x50, 0x00, 0x01);
	midiOutput.sendMessage(m);
	m.continueSysEx(0x00, 0x02, 0x01);
	midiOutput.sendMessage(m);
	m.continueSysEx(0x01, 0x04, 0x01);
	midiOutput.sendMessage(m);
	m.continueSysEx(0x00, 0x01, 0x02);
	midiOutput.sendMessage(m);
	m.endSysEx();
for(int i=0o<20;i++) {
	midiOutput.sendMessage(m);
}

then instead, id decided to try sending it continuously every couple of seconds, and bizarrely on 2nd send, I started getting touch messages (i.e Erae had received it)

hmm, initially i thought a timing issue perhaps…

but then I noticed something else a bit odd…

in my test app, every time I received a touch message I draw a pixel on the Erae (via another sysex) - this sometimes appear, and sometimes not.

so its as if the sysex is sometimes coming thru, sometimes not.. (or is corrupted).

note: I know the touch messages are coming in reliably as Im outputting pressure onto scope, so Im definitely sending the draw pixel msg out…

a couple of other minor notes…

a) drawPixel fails a lot… e.g. only 1 in 10 (?) messages get thru

note: still sending that init every few seconds (which I assume is ignored) hmm, perhaps when I get first touch, I can stop sending it…!?

reducing sysex sends didnt help, e.g. I was sending a drawpixel as you continue touch, so thats a lot of msgs, so reduced that to just initial touch, but didnt change.

b) I had a full crash / lockup

MM just stop responding, was a bit odd… only happened once, and early on as i was sending testing with erae… but other times, Ive run for 5+ mins, with lots of touches and worked fine.
doesn’t mean anything at this stage, could be my code or something related to data volumes, but just thought id mention - but not enough to do anything about at this stage.

ok, getting somewhere…

if I stop the init() after I receive the first touch, then it looks to be working fine !
so, I think the continual periodic init, was really resetting the Erae, and why I was dropping drawPixel() messages :tada:

so… it looks like we are only dropping sysex at (patch/module) startup (or timing issue?),
then once the first one gets thru, can send more without issue.

I can probably workaround this… whilst the init msg does not send a reply,
I could periodically send init + version request…
then when i get the version reply, I know we are ‘good to go’.

so Im going to implement this, I can also count how any times, I need to do this, I suspect its only a couple… which is why Im thinking possible timing ?

though, in fairness, I load the patch and so module manually on each startup with the Erae already connected… so really MM should already be ‘fully initialised’ by then..
except if perhaps are doing something on patch or module init() ?

edit: oh, I’ve also moved to using my ‘api’ code, so its not using the canned code we used for testing, so I know that side is now working too.

ok, this state driven approach seems to work… basically ends up sending the init / request pair 8 or 9 times, then… it all springs into life.

in cases its timing, heres what im doing

   void process(const ProcessArgs& args) override {
        midi::Message msg;
        while (midiInput.tryPop(&msg, args.frame)) { processMidi(msg); }

        if (api_ != nullptr) { api_->process(); }
        if(!initDone_) {
            if(initTimer_==0) {
                api_->enableApi();
                initTimer_ = 100;
                initCount_++;
                debugString_="TX enableApi" + std::to_string(initCount_);
            } else if(initTimer_==50) {
                requestVersion();
            }
            initTimer_ -= initTimer_ > 0;
        }

so every 100 process, I send enable… on the 50, i send version,
(just in case there is an issue with multiple at once, I spaced them)

here you go : )

what you are seeing is… erae sending data to MM, then the MM is drawing onto the Erae.

its kind of exciting, as I can now draw custom graphics on erae based on sound etc from MM
simple example might be a scope… but lots of interaction ideas, e.g. controlling granular waves

also ofc, Erae is multi touch 3d … so x,y,z… so now off to play with poly branch :wink:

Ooo, nice!

My TX errors go away if I resize the 64B TX buffer to 1024B (probably is overkill, but why not). I’m not seeing the same kind of TX error you are, but still fixing the buffer needs to happen so we might as well try.

There shouldn’t be any MIDI messages on patch start or module init (besides what the module explicitly does). Of course some other module (RackCore MIDI modules?) I think send some init. But still we wouldn’t expect lost packets for just 32B of init… so, still a mystery, I’m digging into the HAL now (ugh)… But glad you have a workaround for now!

I’ll push the buffer size fix to the poly branch and main branch.

Oh yeah, and I did get a crash now and then with the smaller buffers. Not with the larger buffers (yet?)

1 Like

yeah, Ive been trying to get this focused in as much as possible to get you as much info as possible.

Im wondering if its timing…
if I delete and add the module again, it takes the same time again… 8/9 init/version request !

Im going to try to increase the time between retries, it may be the 8/9 is more a function of it taking a certain amount of time, before its ready ?!

note: because I’ve made it state based (working thru a state machine), the init has moved to process()… so I need to check this is not also part of it.

EDIT: yup, triple the time (to every 300), and now it only takes 3 attempt

ok, important discovery…

if set it to 1000, and appears to do i first time…

following all appeared to be a red herring, but worth testing, mark as spoiler :wink:

Q. do you load all modules at startup (if on load), i.e. call their constructors?

note: I load patch manually, but module was ‘pre loaded’

Im wondering, if theres a couple of things going on here…
a) ctor vs process
midi was not available when I called within ctor, but is on process.

b) timing of erae response
the new state based approach, might mean I had to wait a little longer for the version reply…
which would explain why waiting longer works.

Im going to test both a and b… as it may be (a) was the underlying cause.

note: another thing, I need to check is, even in process() I wait a while before sending the first enableApi() , so that may play into it a bit?!

EDIT : no … :slight_smile:

so just calling enableApi() on the first call of process() does not work.

it feels like it only works after a short while.
feels like 800-900 calls of process(),
so hence if I delay the first time to 1000, then it works first time.

so it feels like, the issue is you need a bit of time after module ‘loading’ (within a patch) before its ready to send out sysex (or possibly any midi?)

important note: its module loading… as if you delete the module and add again, its appears to need same delay.

EDIT: no spacing required for later messages, I can send version request immediately after enable

        if(!initDone_) {
            if(initTimer_==0) {
                api_->enableApi();
                initTimer_ = INIT_TIMER;
                initCount_++;
                requestVersion();
            }
            initTimer_ -= initTimer_ > 0;
        }

initTimer_ = 1000 (in ctor) , works first time… , less e.g. 100, 300 will take multiple attempts
(if you start initTimer at 0, i.e. first process() calls, then it will fail)

note: with very small value of INIT_TIMER, id run the risk of Erae not reply to version request fast enough, but in practice, Ive not seen this (as initDone = true on version reply)

Ah… I found something on the TX side.

The double-buffer used in TX can silently drop packets. Classic race condition. M4 core reads the size of the inactive buffer to see if there’s data to send. Then if it so happens that an ISR fires and appends more data to the buffer, the size gets updated but the M4 core sends the old size value, and packets are silently lost.
My logging was not picking it up because I was using that incorrect size value.
So this could explain your timing issues. It’s just a matter if the frame rate ISR fires at the wrong time, regardless of the message size.

One issue though, if I run at 24kHz, I do get some lost packets when first sending tons of data. Not totally sure why, but it’s not surprising since data is unpacked at frame rate. It might be worth popping max 2 midi packets per audio frame just to be sure (but I don’t want to drain the midi queue at frame rate because that could lead to audio glitches)

I’ll push new releases on both branches!

1 Like

sounds promising… and good to know, why packets were disappearing !

is this more likely whilst a module is first loaded? as the behaviour seems pretty consistent…

its kind of odd, that its take a few loops of process() before it settles, you’d think by the time process() is called first time, things have settled down.

I’ll try your fixes, and we will see soon enough :slight_smile: