Ensoniq Mirage MASOS template

Yeah that seems like it.

Maybe My Mirage is broken :slight_smile:

This I captured in Midiox while using Wavesyn to fetch the program.
The length seems to be right.
However I do not see the program request message.

—F0h 0Fh 01h 01h 11h 01h 0Ah 7Fh F7h loads program from disk
—F0h 0Fh 01h 01h 00h 01h 7Fh F7h sets L1 ( means lower program 1 )
F0 0F 01 01 00 01 7F F7 ----? same thing repeating? where is the program request message ??

I am sure I saw the program request messages in the sourcecode of wavsyn.

 TIMESTAMP IN PORT STATUS DATA1 DATA2 CHAN NOTE EVENT               
 00005AA2  19  16     F0  Buffer:     9 Bytes   System Exclusive      
 SYSX: F0 0F 01 01 11 01 0A 7F F7
 00005AA2  19  21     F0  Buffer:     9 Bytes   System Exclusive      
 SYSX: F0 0F 01 01 11 01 0A 7F F7
 00005AA3  19  16     F0  Buffer:     8 Bytes   System Exclusive      
 SYSX: F0 0F 01 01 00 01 7F F7    
 00005AA3  19  21     F0  Buffer:     8 Bytes   System Exclusive      
 SYSX: F0 0F 01 01 00 01 7F F7    
 SYSX: F0 0F 01 01 00 01 7F F7    
 SYSX: F0 0F 01 01 00 01 7F F7 
 00006E4C  15  16     F0  Buffer:   256 Bytes   System Exclusive      
 SYSX: F0 0F 01 05 00 0D 03 0B 0E 0D 03 0B 00 0E 03 0B 02 0E
 SYSX: 03 0B 00 0E 00 00 04 00 0A 0F 0F 03 06 0C 40 00 05 00
 SYSX: 00 00 00 0F 01 0E 01 0E 01 0F 0F 00 00 00 00 00 00 00
 SYSX: 00 03 0B 0E 0F 04 0B 00 00 04 0B 40 00 00 04 0B 00 00
 SYSX: 00 00 03 00 0A 0F 0F 03 0C 03 06 0C 01 00 00 02 05 02
 SYSX: 04 02 04 02 0F 0F 00 00 40 00 00 00 00 00 00 04 0B 0E
 SYSX: 01 04 0B 02 02 04 0B 0E 01 04 0B 02 02 00 00 06 00 00
 SYSX: 08 0F 03 00 00 40 06 0C 04 00 0F 02 00 03 0F 02 0F 02
 SYSX: 0F 0F 00 00 00 00 00 00 00 00 04 0B 0E 03 04 0B 02 04
 SYSX: 04 0B 40 0E 03 04 0B 02 04 00 00 03 00 0A 0F 0F 03 0C
 SYSX: 03 06 0C 0A 00 00 05 0F 06 0E 06 0E 06 0F 0F 00 00 40
 SYSX: 00 00 00 00 00 00 04 0B 0E 05 04 0B 02 06 04 0B 0E 05
 SYSX: 04 0B 02 06 00 00 03 00 0A 0F 0F 03 0C 03 40 06 0C 00
 SYSX: 01 00 07 0F 08 0E 08 0E 08 0F 0F 00 00 00 00 00 00 00
 SYSX: 00 04 0B 0E
 00006E4C  15  21     F0  Buffer:   256 Bytes   System Exclusive      
 SYSX: F0 0F 01 05 00 0D 03 0B 0E 0D 03 0B 00 0E 03 0B 02 0E
 SYSX: 03 0B 00 0E 00 00 04 00 0A 0F 0F 03 06 0C 40 00 05 00
 SYSX: 00 00 00 0F 01 0E 01 0E 01 0F 0F 00 00 00 00 00 00 00
 SYSX: 00 03 0B 0E 0F 04 0B 00 00 04 0B 40 00 00 04 0B 00 00
 SYSX: 00 00 03 00 0A 0F 0F 03 0C 03 06 0C 01 00 00 02 05 02
 SYSX: 04 02 04 02 0F 0F 00 00 40 00 00 00 00 00 00 04 0B 0E
 SYSX: 01 04 0B 02 02 04 0B 0E 01 04 0B 02 02 00 00 06 00 00
 SYSX: 08 0F 03 00 00 40 06 0C 04 00 0F 02 00 03 0F 02 0F 02
 SYSX: 0F 0F 00 00 00 00 00 00 00 00 04 0B 0E 03 04 0B 02 04
 SYSX: 04 0B 40 0E 03 04 0B 02 04 00 00 03 00 0A 0F 0F 03 0C
 SYSX: 03 06 0C 0A 00 00 05 0F 06 0E 06 0E 06 0F 0F 00 00 40
 SYSX: 00 00 00 00 00 00 04 0B 0E 05 04 0B 02 06 04 0B 0E 05
 SYSX: 04 0B 02 06 00 00 03 00 0A 0F 0F 03 0C 03 40 06 0C 00
 SYSX: 01 00 07 0F 08 0E 08 0E 08 0F 0F 00 00 00 00 00 00 00
 SYSX: 00 04 0B 0E
 00006EE3  15  16     --  Buffer:   256 Bytes   SysEx Continue        
 SYSX: 07 04 0B 02 08 04 0B 40 0E 07 04 0B 02 08 00 00 01 00
 SYSX: 0A 0F 0F 03 0C 03 06 0C 03 01 00 09 0F 0A 0E 0A 0E 0A
 SYSX: 0F 0F 00 00 40 00 00 00 00 00 00 04 0B 0E 09 04 0B 02
 SYSX: 0A 04 0B 0E 09 04 0B 02 0A 00 00 01 00 0A 0F 0F 03 0C
 SYSX: 03 40 06 0C 06 01 00 0B 0F 0C 0E 0C 0E 0C 0F 0F 00 00
 SYSX: 00 00 00 00 00 00 04 0B 0E 0B 04 0B 02 0C 04 0B 40 0E
 SYSX: 0B 04 0B 02 0C 00 00 01 00 0A 0F 0F 03 0C 03 06 0C 0C
 SYSX: 01 00 0D 0F 0F 0E 0F 0E 0F 0F 0F 00 00 40 00 00 00 00
 SYSX: 00 00 00 00 0F 03 00 08 0F 03 04 00 02 01 08 00 0B 01
 SYSX: 00 01 04 02 00 02 0D 02 00 04 40 06 03 00 08 0F 03 00
 SYSX: 0C 06 03 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F
 SYSX: 0F 0F 0F 0F 0F 0F 0F 40 0F 0F 0F 0F 0F 0F 00 02 0D 02
 SYSX: 01 02 00 00 02 02 09 00 08 01 0B 01 00 02 0D 02 00 04
 SYSX: 06 03 00 08 40 0F 03 00 08 0F 03 00 00 00 00 00 00 00
 SYSX: 00 00 00 00
 00006EE3  15  21     --  Buffer:   256 Bytes   SysEx Continue        
 SYSX: 07 04 0B 02 08 04 0B 40 0E 07 04 0B 02 08 00 00 01 00
 SYSX: 0A 0F 0F 03 0C 03 06 0C 03 01 00 09 0F 0A 0E 0A 0E 0A
 SYSX: 0F 0F 00 00 40 00 00 00 00 00 00 04 0B 0E 09 04 0B 02
 SYSX: 0A 04 0B 0E 09 04 0B 02 0A 00 00 01 00 0A 0F 0F 03 0C
 SYSX: 03 40 06 0C 06 01 00 0B 0F 0C 0E 0C 0E 0C 0F 0F 00 00
 SYSX: 00 00 00 00 00 00 04 0B 0E 0B 04 0B 02 0C 04 0B 40 0E
 SYSX: 0B 04 0B 02 0C 00 00 01 00 0A 0F 0F 03 0C 03 06 0C 0C
 SYSX: 01 00 0D 0F 0F 0E 0F 0E 0F 0F 0F 00 00 40 00 00 00 00
 SYSX: 00 00 00 00 0F 03 00 08 0F 03 04 00 02 01 08 00 0B 01
 SYSX: 00 01 04 02 00 02 0D 02 00 04 40 06 03 00 08 0F 03 00
 SYSX: 0C 06 03 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F
 SYSX: 0F 0F 0F 0F 0F 0F 0F 40 0F 0F 0F 0F 0F 0F 00 02 0D 02
 SYSX: 01 02 00 00 02 02 09 00 08 01 0B 01 00 02 0D 02 00 04
 SYSX: 06 03 00 08 40 0F 03 00 08 0F 03 00 00 00 00 00 00 00
 SYSX: 00 00 00 00
 00006F04  15  16     --  Buffer:   256 Bytes   SysEx Continue        
 SYSX: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00
 SYSX: 00 00 00 00 0F 02 00 00 00 03 04 02 00 03 04 02 00 03
 SYSX: 04 02 00 03 04 02 00 04 06 03 00 08 40 0F 03 00 08 0F
 SYSX: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 SYSX: 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 05
 SYSX: 04 02 00 06 0D 02 00 08 0F 03 00 08 0F 03 00 08 0F 03
 SYSX: 00 0F 03 0F 03 00 40 0F 03 0F 0F 0F 0F 0F 0F 0F 0F 0F
 SYSX: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 00 04 02 0F 03 04 02
 SYSX: 01 08 0B 40 01 0F 03 00 0F 03 0F 03 00 0F 03 0F 0F 0F
 SYSX: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 00
 SYSX: 40 04 02 0D 02 00 06 03 08 0B 01 0D 02 00 06 03 06 03
 SYSX: 00 0F 03 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00
 SYSX: 00 00 00 00 00 00 00 04 02 06 03 04 02 01 0B 01 00 06
 SYSX: 03 00 06 03 06 03 00 0F 03 00 00 00 40 00 00 00 00 00
 SYSX: 00 00 00 00
 00006F04  15  21     --  Buffer:   256 Bytes   SysEx Continue        
 SYSX: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00
 SYSX: 00 00 00 00 0F 02 00 00 00 03 04 02 00 03 04 02 00 03
 SYSX: 04 02 00 03 04 02 00 04 06 03 00 08 40 0F 03 00 08 0F
 SYSX: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 SYSX: 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 05
 SYSX: 04 02 00 06 0D 02 00 08 0F 03 00 08 0F 03 00 08 0F 03
 SYSX: 00 0F 03 0F 03 00 40 0F 03 0F 0F 0F 0F 0F 0F 0F 0F 0F
 SYSX: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 00 04 02 0F 03 04 02
 SYSX: 01 08 0B 40 01 0F 03 00 0F 03 0F 03 00 0F 03 0F 0F 0F
 SYSX: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 00
 SYSX: 40 04 02 0D 02 00 06 03 08 0B 01 0D 02 00 06 03 06 03
 SYSX: 00 0F 03 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00
 SYSX: 00 00 00 00 00 00 00 04 02 06 03 04 02 01 0B 01 00 06
 SYSX: 03 00 06 03 06 03 00 0F 03 00 00 00 40 00 00 00 00 00
 SYSX: 00 00 00 00
 00006F0C  15  16     F0  Buffer:     6 Bytes   System Exclusive      
 SYSX: F0 0F 01 07 00 F7
 00006F0C  15  21     F0  Buffer:     6 Bytes   System Exclusive      
 SYSX: F0 0F 01 07 00 F7
 00006F0F  15  16     F0  Buffer:     6 Bytes   System Exclusive      
 SYSX: F0 0F 01 07 00 F7
 00006F0F  15  21     F0  Buffer:     6 Bytes   System Exclusive      
 SYSX: F0 0F 01 07 00 F7

can you connect the Mirage direc to the computer and use MIDI Ox directly?

in the sysex dumps you attached to a previous message, the Program data starts at byte offset 03C6

1 Like

ok wil do tomorrow if i can find some time.

cheers

The different sizes of the patch dump could be a low level issue with the Electra one.
Maybe buffer under runs? to big message?

@martin can you look at this?
Would it be possible to change the in-coming / out-going buffers?
Does the device “rate” have any influence on this.
Is 1256 bytes too much for the Eone? Note the data are nybles…if so can the max bytes be increased?

I ran the template with only one function to exclude possible issues with the Lua code:
And never see the F7 in the data,

-- 
function patch.onResponse (device, responseId, sysexBlock)
   -- first thing to do is always check the size and if it is not right, throw it away
   local recvSize = sysexBlock:getLength ()

end

Anyhow I did not manage to get A full dump via the Electra One ( 1051 max ).
1050 Bytes incomming! At least I see the F0…F7

Input buffer sizer 64 bytes, 32 buffers works…

Still not enought data…

F0 0F 01 15 03 0A 06 0B 0F 04 06 0B 01 05 06 0B 01 05 06 0B 01 05 00 00 04 00 00 08 0F 03 04 01 40 0E 0B 0D 02 00 00 0F 07 0E 07 0E 07 0F 0F 00 00 00 00 00 00 00 00 06 0B 0F 06 06 0B 01 07 06 0B 40 0F 06 06 0B 01 07 00 00 04 00 00 08 0F 03 04 01 0E 0B 0C 03 00 08 0F 0F 0E 0F 0E 0F 0F 0F 00 00 40 00 00 00 00 00 00 06 0B 0F 08 06 0B 01 09 06 0B 01 09 06 0B 01 09 00 00 04 00 00 08 0F 03 04 01 40 0E 0B 05 03 00 08 0F 0B 0E 0B 0E 0B 0F 0F 00 00 00 00 00 00 00 00 06 0B 0F 0A 06 0B 01 0B 06 0B 40 0F 0A 06 0B 01 0B 00 00 04 00 0B 0E 0F 03 04 01 0E 0B 0C 03 00 0C 0F 0F 0E 0F 0E 0F 0F 0F 00 00 40 00 00 00 00 00 00 06 0B 0F 0C 06 0B 01 0D 06 0B 01 0D 06 0B 01 0D 00 00 04 00 00 08 0F 03 04 01 40 06 0C 01 03 00 08 0F 09 0E 09 0E 09 0F 0F 00 00 00 00 00 00 00 00 06 0B 0F 0E 06 0B 01 0F 06 0B 40 0F 0E 06 0B 01 0F 00 00 04 00 00 08 0F 03 04 01 0E 0B 05 03 00 0A 0F 0B 0E 0B 0E 0B 0F 0F 00 00 40 00 00 00 00 00 00 07 0B 0F 00 07 0B 01 01 07 0B 0F 00 07 0B 01 01 00 00 04 00 00 02 0F 03 04 01 40 0E 0B 09 03 00 0C 0F 0D 0E 0D 0E 0D 0F 0F 00 00 00 00 00 00 00 00 07 0B 0F 02 07 0B 01 03 07 0B 40 0F 02 07 0B 01 03 00 00 04 00 0F 0C 0F 03 04 01 0E 0B 0C 03 00 0E 0F 0F 00 0E 0F 0F 01 0A 00 00 40 00 00 00 00 00 00 00 00 0F 07 0E 03 00 04 04 00 02 05 08 00 0B 05 00 01 04 06 00 02 0D 06 00 04 40 06 07 00 08 0F 07 08 06 02 05 00 0C 06 07 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 40 0F 0F 0F 0F 0F 0F 00 08 0F 07 02 08 09 04 04 08 02 05 08 08 0B 05 00 09 04 06 00 0A 0D 06 00 0C 40 06 07 00 07 09 04 00 07 09 04 08 0A 09 04 0A 0A 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 08 0F 07 0E 0B 00 04 04 08 02 05 08 08 0B 05 00 09 04 06 00 0A 0D 06 00 0C 40 06 07 00 0C 06 07 0E 0B 00 04 00 0F 04 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 0C 06 07 00 0C 06 07 00 0C 06 07 00 0C 06 07 00 06 07 0D 06 0E 00 04 0E 00 40 04 00 04 0E 00 04 00 04 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 00 0F 07 09 04 04 02 05 0B 05 00 40 04 06 0F 07 00 06 07 00 0F 07 00 04 0E 0A 04 09 04 0E 00 04 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 00 0D 40 06 06 07 04 02 05 0B 05 00 06 07 06 07 0C 09 04 0C 09 04 09 04 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 06 07 09 04 04 02 05 0B 05 00 04 06 00 04 00 09 04 09 04 00 09 04 00 09 40 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0E 06 09 04 04 02 05 0B 05 00 04 06 00 00 00 40 00 00 00 00 00 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 40 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 40 0F 0F 0E 00 00 00 00 00 04 00 00 00 04 00 00 00 00 00 00 00 00 00 0F 00 00 00 00 00 00 00 00 0A 40 00 0A 00 0A 00 00 00 00 04 00 00 00 00 00 00 00 00 0E 00 00 00 00 04 00 00 00 04 00 00 00 00 00 40 00 00 00 00 0F 00 00 00 00 00 00 00 00 0A 00 0A 00 0A 00 00 00 00 04 00 00 00 00 00 00 00 00 0E 40 00 00 00 00 04 00 00 00 04 00 00 00 00 00 00 00 0F 00 00 00 00 00 00 00 00 00 00 0A 00 0A 00 0A 40 00 00 00 00 04 00 00 00 00 00 00 00 00 0E 00 00 00 00 04 00 00 00 04 00 00 00 00 00 00 00 0F 00 40 00 00 00 00 00 00 00 00 00 0A 00 0A 00 0A 00 00 04 00 00 00 00 00 00 00 00 00 F7

Using MidiOX and another midi interface I always get 1255 Bytes:
So looks like your math is ok :slight_smile: @oldgearguy

F0 0F 01 05 00 0D 03 0B 0E 0D 03 0B 00 0E 03 0B 00 0E 03 0B 00 0E 00 00 04 00 00 08 0F 03 0C 03 06 0C 0E 00 00 00 0F 07 0E 07 0E 07 0F 0F 00 00 00 00 00 00 00 00 03 0B 0E 0F 04 0B 00 00 03 0B 0E 0F 04 0B 00 00 00 00 04 00 00 08 0F 03 0C 03 0E 0B 0E 01 00 08 0F 0F 0E 0F 0E 0F 0F 0F 00 00 00 00 00 00 00 00 04 0B 0E 01 04 0B 00 02 04 0B 00 02 04 0B 00 02 00 00 03 00 0E 0E 0F 03 0C 03 0E 0B 06 01 00 08 0F 0B 0E 0B 0E 0B 0F 0F 00 00 00 00 00 00 00 00 04 0B 0E 03 04 0B 00 04 04 0B 00 04 04 0B 00 04 00 00 03 00 0E 0E 0F 03 0C 03 0E 0B 0E 01 00 0C 0F 0F 0E 0F 0E 0F 0F 0F 00 00 00 00 00 00 00 00 04 0B 0E 05 04 0B 00 06 04 0B 0E 05 04 0B 00 06 00 00 03 00 0E 0E 0F 03 0C 03 0E 0B 02 01 00 08 0F 0F 0E 0F 0E 0F 0F 0F 00 00 00 00 00 00 00 00 04 0B 0E 07 04 0B 02 08 04 0B 0E 07 04 0B 02 08 00 00 04 00 0E 0E 0F 03 0C 03 0E 0B 06 01 00 0A 0F 0F 0E 0F 0E 0F 0F 0F 00 00 00 00 00 00 00 00 04 0B 0E 09 04 0B 00 0A 04 0B 0E 09 04 0B 00 0A 00 00 03 00 0E 0E 0F 03 0C 03 0E 0B 0A 01 00 0C 0F 0F 0E 0F 0E 0F 0F 0F 00 00 00 00 00 00 00 00 04 0B 0E 0B 04 0B 00 0C 04 0B 0E 0B 04 0B 00 0C 00 00 03 00 0E 0E 0F 03 0C 03 0E 0B 0E 01 00 0E 0F 0F 0E 0F 0E 0F 0F 0F 00 00 00 00 00 00 00 00 00 00 0F 03 00 08 0F 03 04 00 02 01 08 00 0B 01 00 01 04 02 00 02 0D 02 00 04 06 03 00 08 0F 03 00 0C 06 03 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 00 08 0F 03 02 08 09 00 04 08 02 01 08 08 0B 01 00 09 04 02 00 0A 0D 02 00 0C 06 03 00 08 0F 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 0F 03 0E 0B 00 00 04 08 02 01 08 08 0B 01 00 09 04 02 00 0A 0D 02 00 0C 06 03 00 08 0F 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 06 03 0E 0F 00 00 04 0C 02 01 08 0C 0B 01 00 0D 04 02 00 0E 0D 02 00 04 06 03 00 08 0F 03 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 00 08 0F 03 02 08 09 00 04 08 02 01 08 08 0B 01 00 09 04 02 00 0A 0D 02 00 0C 06 03 00 08 0F 03 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 00 0A 0D 02 00 0C 06 03 04 0A 02 01 08 0A 0B 01 00 0B 04 02 00 0C 06 03 00 0C 06 03 00 08 0F 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 06 03 02 0C 09 00 04 0C 02 01 08 0C 0B 01 00 0D 04 02 00 0E 0D 02 00 0C 06 03 00 08 0F 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0E 0D 02 00 0E 0D 02 00 0E 0D 02 00 0E 0D 02 00 0E 0D 02 00 0E 0D 02 00 0C 06 03 00 08 0F 03 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 00 00 0E 00 00 00 00 00 00 00 04 00 0A 05 00 00 04 00 00 00 00 00 00 00 00 00 00 00 0F 00 00 00 0F 01 00 00 00 00 00 00 00 00 00 00 00 00 0A 00 0F 00 0A 00 0A 00 00 00 04 05 00 00 04 05 00 00 00 00 00 00 00 00 00 00 00 00 0E 00 00 00 00 00 00 00 04 00 0A 05 00 00 04 00 00 00 00 00 00 00 00 00 00 00 0F 00 00 00 0F 01 00 00 00 00 00 00 00 00 00 00 00 00 0A 00 0F 00 0A 00 0A 00 00 00 04 05 00 00 04 05 00 00 00 00 00 00 00 00 00 00 00 00 0E 00 00 00 00 00 00 00 04 00 0A 05 00 00 04 00 00 00 00 00 00 00 00 00 00 00 0F 00 00 00 0F 01 00 00 00 00 00 00 00 00 00 00 00 00 0A 00 0F 00 0A 00 0A 00 00 00 04 05 00 00 04 05 00 00 00 00 00 00 00 00 00 00 00 00 0E 00 00 00 00 00 00 00 04 00 0A 05 00 00 04 00 00 00 00 00 00 00 00 00 00 00 0F 00 00 00 0F 01 00 00 00 00 00 00 00 00 00 00 00 00 0A 00 0F 00 0A 00 0A 00 00 00 04 05 00 00 04 05 00 00 00 00 00 00 00 00 00 00 F7```

In general, I have found that the E1 handles receiving large sysex dimps properly.

Remember that inside the LUA code, the midi.onResponse() function always removes the F0 and F7 bytes from the message.

In my presets, I always coded the midi.patchRequest() myself rather than use the JSON, but that’s mainly due to what I know. Not because of any issues with the JSON.

That is why before I start any serious sysex dump decoding, I capture one or more dumps directly from the device into MIDI Ox and make sure i can manually map a few values to what I see on the device.

That very last dump you sent may be the most useful. I will take a look today and try to map out the sections on it.

I was actually not able to remove the patch section from the json.
And it kept sending empty F0 … F7’s

So perhaps I should download the preset and lua

Remove the patch section

And add a midi.patchRequest() ?

Edit: the issues might be related to the patch in json.
I removed it. The was only the config request and I added 3 different functions to fetch, upper, lower prog or config.
I I try few times I get more data:

15:32:49.666 lua: value 224 byte position 650
15:32:49.666 lua: value 254 byte position 651
15:32:49.666 lua: value 195 byte position 652
15:32:49.666 lua: value 227 byte position 653
15:32:49.667 lua: value 171 byte position 654
15:32:49.667 lua: value 1 byte position 655
15:32:49.667 lua: value 252 byte position 656
15:32:49.667 lua: value 239 byte position 657
15:32:49.668 lua: value 239 byte position 658
15:32:49.668 lua: value 255 byte position 659
15:32:49.668 lua: value 15 byte position 660
15:32:49.668 lua: value 0 byte position 661
15:32:49.669 lua: value 0 byte position 662
15:32:49.669 lua: value 0 byte position 663
15:32:49.669 lua: value 64 byte position 664
15:32:49.669 lua: value 235 byte position 665
15:32:49.670 lua: value 75 byte position 666
15:32:49.670 lua: value 11 byte position 667
15:32:49.670 lua: value 76 byte position 668
15:32:49.670 lua: value 251 byte position 669
15:32:49.670 lua: value 3 byte position 670
15:32:49.671 lua: value 240 byte position 671
15:32:49.671 lua: value 255 byte position 672
15:32:49.671 lua: value 255 byte position 673
15:32:49.671 lua: value 255 byte position 674
15:32:49.672 lua: value 255 byte position 675
15:32:49.672 lua: value 255 byte position 676
15:32:49.672 lua: value 0 byte position 677
15:32:49.672 lua: value 0 byte position 678
15:32:49.673 lua: value 240 byte position 679
15:32:49.673 lua: value 0 byte position 680
15:32:49.673 lua: value 15 byte position 681
15:32:49.674 lua: value 0 byte position 682
15:32:49.674 lua: value 0 byte position 683
15:32:49.674 lua: value 0 byte position 684
15:32:49.674 lua: value 10 byte position 685
15:32:49.675 lua: value 175 byte position 686
15:32:49.675 lua: value 0 byte position 687
15:32:49.675 lua: value 64 byte position 688
15:32:49.675 lua: value 0 byte position 689
15:32:49.675 lua: value 4 byte position 690
15:32:49.676 lua: value 0 byte position 691
15:32:49.676 lua: value 0 byte position 692
15:32:49.676 lua: value 0 byte position 693
15:32:49.676 lua: value 14 byte position 694
15:32:49.677 lua: value 0 byte position 695
15:32:49.677 lua: value 64 byte position 696
15:32:49.677 lua: value 160 byte position 697
15:32:49.677 lua: value 0 byte position 698
15:32:49.678 lua: value 0 byte position 699
15:32:49.678 lua: value 0 byte position 700
15:32:49.678 lua: value 0 byte position 701
15:32:49.678 lua: value 0 byte position 702
15:32:49.679 lua: value 0 byte position 703
15:32:49.679 lua: value 15 byte position 704
15:32:49.679 lua: value 0 byte position 705
15:32:49.679 lua: value 0 byte position 706
15:32:49.679 lua: value 0 byte position 707
15:32:49.680 lua: value 10 byte position 708
15:32:49.680 lua: value 175 byte position 709
15:32:49.680 lua: value 0 byte position 710
15:32:49.681 lua: value 64 byte position 711
15:32:49.681 lua: value 0 byte position 712
15:32:49.681 lua: value 4 byte position 713
15:32:49.681 lua: value 0 byte position 714
15:32:49.682 lua: value 0 byte position 715
15:32:49.682 lua: value 0 byte position 716
15:32:49.682 lua: value 14 byte position 717
15:32:49.682 lua: value 0 byte position 718
15:32:49.682 lua: value 64 byte position 719
15:32:49.683 lua: value 160 byte position 720
15:32:49.683 lua: value 0 byte position 721
15:32:49.683 lua: value 4 byte position 722
15:32:49.683 lua: value 0 byte position 723
15:32:49.684 lua: value 0 byte position 724
15:32:49.684 lua: value 0 byte position 725
15:32:49.684 lua: value 0 byte position 726
15:32:49.684 lua: value 15 byte position 727
15:32:49.685 lua: value 0 byte position 728
15:32:49.685 lua: value 0 byte position 729
15:32:49.685 lua: value 0 byte position 730
15:32:49.685 lua: value 10 byte position 731
15:32:49.686 lua: value 10 byte position 732
15:32:49.686 lua: value 0 byte position 733
15:32:49.686 lua: value 64 byte position 734
15:32:49.686 lua: value 0 byte position 735
15:32:49.686 lua: value 0 byte position 736
15:32:49.687 lua: value 0 byte position 737
15:32:49.687 lua: value 224 byte position 738
15:32:49.687 lua: value 0 byte position 739
15:32:49.688 lua: value 0 byte position 740
15:32:49.688 lua: value 0 byte position 741
15:32:49.688 lua: value 4 byte position 742
15:32:49.688 lua: value 0 byte position 743
15:32:49.689 lua: value 0 byte position 744
15:32:49.689 lua: value 0 byte position 745
15:32:49.689 lua: value 31 byte position 746
15:32:49.689 lua: value 213 byte position 747
15:32:49.689 lua: value 179 byte position 748
15:32:49.690 lua: value 61 byte position 749
15:32:49.690 lua: value 62 byte position 750
15:32:49.690 lua: value 235 byte position 751
15:32:49.690 lua: value 227 byte position 752
15:32:49.691 lua: value 0 byte position 753
15:32:49.691 lua: value 0 byte position 754
15:32:49.691 lua: value 195 byte position 755
15:32:49.691 lua: value 195 byte position 756
15:32:49.692 lua: value 14 byte position 757
15:32:49.692 lua: value 127 byte position 758
15:32:49.692 lua: value 231 byte position 759
15:32:49.692 lua: value 247 byte position 760
15:32:49.692 lua: value 0 byte position 761
15:32:49.693 lua: value 0 byte position 762
15:32:49.693 lua: value 48 byte position 763
15:32:49.693 lua: value 79 byte position 764
15:32:49.693 lua: value 11 byte position 765
15:32:49.694 lua: value 243 byte position 766
15:32:49.694 lua: value 180 byte position 767
15:32:49.694 lua: value 0 byte position 768
15:32:49.695 lua: value 0 byte position 769
15:32:49.695 lua: value 48 byte position 770
15:32:49.695 lua: value 60 byte position 771
15:32:49.695 lua: value 235 byte position 772
15:32:49.695 lua: value 248 byte position 773
15:32:49.696 lua: value 255 byte position 774
15:32:49.696 lua: value 254 byte position 775
15:32:49.696 lua: value 0 byte position 776
15:32:49.696 lua: value 0 byte position 777
15:32:49.697 lua: value 64 byte position 778
15:32:49.697 lua: value 27 byte position 779
15:32:49.697 lua: value 180 byte position 780
15:32:49.697 lua: value 66 byte position 781
15:32:49.698 lua: value 66 byte position 782
15:32:49.698 lua: value 43 byte position 783
15:32:49.698 lua: value 0 byte position 784
15:32:49.698 lua: value 238 byte position 785
15:32:49.698 lua: value 195 byte position 786
15:32:49.699 lua: value 107 byte position 787
15:32:49.699 lua: value 129 byte position 788
15:32:49.699 lua: value 191 byte position 789
15:32:49.699 lua: value 235 byte position 790
15:32:49.700 lua: value 15 byte position 791
15:32:49.700 lua: value 0 byte position 792
15:32:49.700 lua: value 0 byte position 793
15:32:49.700 lua: value 180 byte position 794
15:32:49.701 lua: value 67 byte position 795
15:32:49.701 lua: value 68 byte position 796
15:32:49.701 lua: value 75 byte position 797
15:32:49.701 lua: value 68 byte position 798
15:32:49.702 lua: value 0 byte position 799
15:32:49.702 lua: value 224 byte position 800
15:32:49.702 lua: value 62 byte position 801
15:32:49.702 lua: value 188 byte position 802
15:32:49.703 lua: value 30 byte position 803
15:32:49.703 lua: value 252 byte position 804
15:32:49.703 lua: value 239 byte position 805
15:32:49.703 lua: value 255 byte position 806
15:32:49.703 lua: value 0 byte position 807
15:32:49.704 lua: value 0 byte position 808
15:32:49.704 lua: value 64 byte position 809
15:32:49.704 lua: value 69 byte position 810
15:32:49.704 lua: value 107 byte position 811
15:32:49.705 lua: value 180 byte position 812
15:32:49.705 lua: value 69 byte position 813
15:32:49.705 lua: value 6 byte position 814
15:32:49.705 lua: value 0 byte position 815
15:32:49.706 lua: value 62 byte position 816
15:32:49.706 lua: value 60 byte position 817
15:32:49.706 lua: value 43 byte position 818
15:32:49.706 lua: value 248 byte position 819
15:32:49.706 lua: value 255 byte position 820
15:32:49.707 lua: value 254 byte position 821
15:32:49.707 lua: value 15 byte position 822
15:32:49.707 lua: value 0 byte position 823
15:32:49.707 lua: value 0 byte position 824
15:32:49.708 lua: value 116 byte position 825
15:32:49.708 lua: value 180 byte position 826
15:32:49.708 lua: value 72 byte position 827
15:32:49.708 lua: value 71 byte position 828
15:32:49.709 lua: value 139 byte position 829
15:32:49.709 lua: value 0 byte position 830
15:32:49.709 lua: value 238 byte position 831
15:32:49.709 lua: value 195 byte position 832
15:32:49.710 lua: value 179 byte position 833
15:32:49.710 lua: value 166 byte position 834
15:32:49.710 lua: value 255 byte position 835
15:32:49.710 lua: value 239 byte position 836
15:32:49.710 lua: value 15 byte position 837
15:32:49.711 lua: value 0 byte position 838
15:32:49.711 lua: value 0 byte position 839
15:32:49.711 lua: value 180 byte position 840
15:32:49.711 lua: value 73 byte position 841
15:32:49.712 lua: value 74 byte position 842
15:32:49.712 lua: value 155 byte position 843
15:32:49.712 lua: value 180 byte position 844
15:32:49.712 lua: value 10 byte position 845
15:32:49.713 lua: value 224 byte position 846
15:32:49.713 lua: value 62 byte position 847
15:32:49.713 lua: value 188 byte position 848
15:32:49.713 lua: value 26 byte position 849
15:32:49.713 lua: value 252 byte position 850
15:32:49.714 lua: value 239 byte position 851
15:32:49.714 lua: value 255 byte position 852
15:32:49.714 lua: value 0 byte position 853
15:32:49.714 lua: value 0 byte position 854
15:32:49.715 lua: value 64 byte position 855
15:32:49.715 lua: value 187 byte position 856
15:32:49.715 lua: value 196 byte position 857
15:32:49.715 lua: value 180 byte position 858
15:32:49.716 lua: value 75 byte position 859
15:32:49.716 lua: value 12 byte position 860
15:32:49.716 lua: value 0 byte position 861
15:32:49.716 lua: value 62 byte position 862
15:32:49.717 lua: value 60 byte position 863
15:32:49.717 lua: value 235 byte position 864
15:32:49.717 lua: value 225 byte position 865
15:32:49.717 lua: value 255 byte position 866
15:32:49.717 lua: value 254 byte position 867
15:32:49.718 lua: value 15 byte position 868
15:32:49.718 lua: value 0 byte position 869
15:32:49.718 lua: value 0 byte position 870
15:32:49.718 lua: value 15 byte position 871
15:32:49.719 lua: value 16 byte position 872
15:32:49.719 lua: value 2 byte position 873
15:32:49.719 lua: value 2 byte position 874
15:32:49.719 lua: value 52 byte position 875
15:32:49.719 lua: value 64 byte position 876
15:32:49.720 lua: value 3 byte position 877
15:32:49.720 lua: value 3 byte position 878
15:32:49.720 lua: value 52 byte position 879
15:32:49.720 lua: value 48 byte position 880
15:32:49.721 lua: value 192 byte position 881
15:32:49.721 lua: value 243 byte position 882
15:32:49.721 lua: value 255 byte position 883
15:32:49.721 lua: value 255 byte position 884
15:32:49.721 lua: value 255 byte position 885
15:32:49.722 lua: value 255 byte position 886
15:32:49.722 lua: value 255 byte position 887
15:32:49.722 lua: value 255 byte position 888
15:32:49.723 lua: value 255 byte position 889
15:32:49.723 lua: value 255 byte position 890
15:32:49.723 lua: value 15 byte position 891
15:32:49.723 lua: value 35 byte position 892
15:32:49.723 lua: value 8 byte position 893
15:32:49.724 lua: value 20 byte position 894
15:32:49.724 lua: value 136 byte position 895
15:32:49.724 lua: value 1 byte position 896
15:32:49.724 lua: value 41 byte position 897
15:32:49.725 lua: value 32 byte position 898
15:32:49.725 lua: value 192 byte position 899
15:32:49.725 lua: value 3 byte position 900
15:32:49.725 lua: value 3 byte position 901
15:32:49.725 lua: value 0 byte position 902
15:32:49.726 lua: value 0 byte position 903
15:32:49.726 lua: value 0 byte position 904
15:32:49.726 lua: value 0 byte position 905
15:32:49.726 lua: value 0 byte position 906
15:32:49.727 lua: value 0 byte position 907
15:32:49.727 lua: value 0 byte position 908
15:32:49.727 lua: value 0 byte position 909
15:32:49.727 lua: value 0 byte position 910
15:32:49.727 lua: value 0 byte position 911
15:32:49.728 lua: value 48 byte position 912
15:32:49.728 lua: value 190 byte position 913
15:32:49.728 lua: value 64 byte position 914
15:32:49.728 lua: value 129 byte position 915
15:32:49.729 lua: value 24 byte position 916
15:32:49.729 lua: value 144 byte position 917
15:32:49.729 lua: value 2 byte position 918
15:32:49.734 lua: value 2 byte position 919
15:32:49.734 lua: value 60 byte position 920
15:32:49.735 lua: value 48 byte position 921
15:32:49.735 lua: value 0 byte position 922
15:32:49.735 lua: value 0 byte position 923
15:32:49.735 lua: value 0 byte position 924
15:32:49.736 lua: value 0 byte position 925
15:32:49.736 lua: value 0 byte position 926
15:32:49.736 lua: value 0 byte position 927
15:32:49.736 lua: value 0 byte position 928
15:32:49.736 lua: value 0 byte position 929
15:32:49.737 lua: value 0 byte position 930
15:32:49.737 lua: value 0 byte position 931
15:32:49.737 lua: value 0 byte position 932
15:32:49.737 lua: value 227 byte position 933
15:32:49.738 lua: value 15 byte position 934
15:32:49.738 lua: value 20 byte position 935
15:32:49.738 lua: value 200 byte position 936
15:32:49.738 lua: value 1 byte position 937
15:32:49.738 lua: value 2 byte position 938
15:32:49.739 lua: value 46 byte position 939
15:32:49.739 lua: value 64 byte position 940
15:32:49.739 lua: value 3 byte position 941
15:32:49.739 lua: value 243 byte position 942
15:32:49.740 lua: value 255 byte position 943
15:32:49.740 lua: value 255 byte position 944
15:32:49.740 lua: value 255 byte position 945
15:32:49.740 lua: value 255 byte position 946
15:32:49.740 lua: value 255 byte position 947
15:32:49.741 lua: value 255 byte position 948
15:32:49.741 lua: value 255 byte position 949
15:32:49.741 lua: value 255 byte position 950
15:32:49.741 lua: value 255 byte position 951
15:32:49.742 lua: value 255 byte position 952
15:32:49.742 lua: value 48 byte position 953
15:32:49.742 lua: value 130 byte position 954
15:32:49.742 lua: value 64 byte position 955
15:32:49.743 lua: value 129 byte position 956
15:32:49.743 lua: value 24 byte position 957
15:32:49.743 lua: value 32 byte position 958
15:32:49.743 lua: value 160 byte position 959
15:32:49.744 lua: value 2 byte position 960
15:32:49.744 lua: value 60 byte position 961
15:32:49.744 lua: value 48 byte position 962
15:32:49.744 lua: value 255 byte position 963
15:32:49.744 lua: value 255 byte position 964
15:32:49.745 lua: value 255 byte position 965
15:32:49.745 lua: value 255 byte position 966
15:32:49.745 lua: value 255 byte position 967
15:32:49.745 lua: value 255 byte position 968
15:32:49.746 lua: value 255 byte position 969
15:32:49.746 lua: value 255 byte position 970
15:32:49.746 lua: value 255 byte position 971
15:32:49.746 lua: value 255 byte position 972
15:32:49.747 lua: value 15 byte position 973
15:32:49.747 lua: value 2 byte position 974
15:32:49.747 lua: value 60 byte position 975
15:32:49.747 lua: value 20 byte position 976
15:32:49.748 lua: value 168 byte position 977
15:32:49.748 lua: value 1 byte position 978
15:32:49.748 lua: value 2 byte position 979
15:32:49.748 lua: value 60 byte position 980
15:32:49.749 lua: value 192 byte position 981
15:32:49.749 lua: value 3 byte position 982
15:32:49.749 lua: value 3 byte position 983
15:32:49.749 lua: value 0 byte position 984
15:32:49.750 lua: value 0 byte position 985
15:32:49.750 lua: value 0 byte position 986
15:32:49.750 lua: value 0 byte position 987
15:32:49.750 lua: value 0 byte position 988
15:32:49.751 lua: value 0 byte position 989
15:32:49.751 lua: value 0 byte position 990
15:32:49.751 lua: value 0 byte position 991
15:32:49.751 lua: value 0 byte position 992
15:32:49.751 lua: value 0 byte position 993
15:32:49.752 lua: value 48 byte position 994
15:32:49.752 lua: value 194 byte position 995
15:32:49.752 lua: value 64 byte position 996
15:32:49.752 lua: value 129 byte position 997
15:32:49.753 lua: value 28 byte position 998
15:32:49.753 lua: value 32 byte position 999
15:32:49.753 lua: value 224 byte position 1000
15:32:49.753 lua: value 2 byte position 1001
15:32:49.753 lua: value 60 byte position 1002
15:32:49.754 lua: value 48 byte position 1003
15:32:49.754 lua: value 0 byte position 1004
15:32:49.754 lua: value 0 byte position 1005
15:32:49.754 lua: value 0 byte position 1006
15:32:49.755 lua: value 0 byte position 1007
15:32:49.755 lua: value 0 byte position 1008
15:32:49.755 lua: value 0 byte position 1009
15:32:49.755 lua: value 0 byte position 1010
15:32:49.756 lua: value 0 byte position 1011
15:32:49.756 lua: value 0 byte position 1012
15:32:49.756 lua: value 0 byte position 1013
15:32:49.756 lua: value 0 byte position 1014
15:32:49.756 lua: value 2 byte position 1015
15:32:49.757 lua: value 46 byte position 1016
15:32:49.757 lua: value 32 byte position 1017
15:32:49.757 lua: value 224 byte position 1018
15:32:49.757 lua: value 2 byte position 1019
15:32:49.758 lua: value 2 byte position 1020
15:32:49.758 lua: value 46 byte position 1021
15:32:49.758 lua: value 48 byte position 1022
15:32:49.758 lua: value 128 byte position 1023
15:32:49.759 lua: value 243 byte position 1024
15:32:49.759 lua: value 255 byte position 1025
15:32:49.759 lua: value 255 byte position 1026
15:32:49.759 lua: value 255 byte position 1027
15:32:49.760 lua: value 255 byte position 1028
15:32:49.760 lua: value 255 byte position 1029
15:32:49.760 lua: value 255 byte position 1030
15:32:49.760 lua: value 255 byte position 1031
15:32:49.760 lua: value 255 byte position 1032
15:32:49.761 lua: value 255 byte position 1033
15:32:49.761 lua: value 255 byte position 1034
15:32:49.761 lua: value 255 byte position 1035
15:32:49.761 lua: value 255 byte position 1036
15:32:49.762 lua: value 255 byte position 1037
15:32:49.762 lua: value 255 byte position 1038
15:32:49.762 lua: value 255 byte position 1039
15:32:49.762 lua: value 255 byte position 1040
15:32:49.763 lua: value 255 byte position 1041
15:32:49.763 lua: value 255 byte position 1042
15:32:49.763 lua: value 255 byte position 1043
15:32:49.764 lua: value 255 byte position 1044
15:32:49.764 lua: value 255 byte position 1045
15:32:49.764 lua: value 255 byte position 1046
15:32:49.764 lua: value 255 byte position 1047
15:32:49.764 lua: value 255 byte position 1048
15:32:49.765 lua: value 255 byte position 1049
15:32:49.765 lua: value 255 byte position 1050
15:32:49.765 lua: value 255 byte position 1051
15:32:49.765 lua: value 255 byte position 1052
15:32:49.766 lua: value 255 byte position 1053
15:32:49.766 lua: value 255 byte position 1054
15:32:49.766 lua: value 1 byte position 1055
15:32:49.766 lua: value 0 byte position 1056
15:32:49.766 lua: value 0 byte position 1057
15:32:49.767 lua: value 0 byte position 1058
15:32:49.767 lua: value 90 byte position 1059
15:32:49.767 lua: value 64 byte position 1060
15:32:49.767 lua: value 0 byte position 1061
15:32:49.768 lua: value 0 byte position 1062
15:32:49.768 lua: value 0 byte position 1063
15:32:49.768 lua: value 15 byte position 1064
15:32:49.768 lua: value 240 byte position 1065
15:32:49.768 lua: value 1 byte position 1066
15:32:49.769 lua: value 0 byte position 1067
15:32:49.769 lua: value 0 byte position 1068
15:32:49.769 lua: value 0 byte position 1069
15:32:49.769 lua: value 240 byte position 1070
15:32:49.770 lua: value 0 byte position 1071
15:32:49.770 lua: value 10 byte position 1072
15:32:49.770 lua: value 84 byte position 1073
15:32:49.770 lua: value 64 byte position 1074
15:32:49.770 lua: value 0 byte position 1075
15:32:49.771 lua: value 0 byte position 1076
15:32:49.771 lua: value 0 byte position 1077
15:32:49.771 lua: value 0 byte position 1078
15:32:49.771 lua: value 0 byte position 1079
15:32:49.772 lua: value 0 byte position 1080
15:32:49.772 lua: value 0 byte position 1081
15:32:49.772 lua: value 90 byte position 1082
15:32:49.772 lua: value 64 byte position 1083
15:32:49.772 lua: value 0 byte position 1084
15:32:49.773 lua: value 0 byte position 1085
15:32:49.773 lua: value 0 byte position 1086
15:32:49.773 lua: value 15 byte position 1087
15:32:49.773 lua: value 240 byte position 1088
15:32:49.774 lua: value 1 byte position 1089
15:32:49.774 lua: value 0 byte position 1090
15:32:49.774 lua: value 0 byte position 1091
15:32:49.774 lua: value 0 byte position 1092
15:32:49.774 lua: value 240 byte position 1093
15:32:49.775 lua: value 0 byte position 1094
15:32:49.775 lua: value 10 byte position 1095
15:32:49.775 lua: value 84 byte position 1096
15:32:49.775 lua: value 64 byte position 1097
15:32:49.776 lua: value 5 byte position 1098
15:32:49.776 lua: value 0 byte position 1099
15:32:49.776 lua: value 0 byte position 1100
15:32:49.776 lua: value 0 byte position 1101
15:32:49.776 lua: value 0 byte position 1102
15:32:49.777 lua: value 0 byte position 1103
15:32:49.777 lua: value 0 byte position 1104
15:32:49.777 lua: value 90 byte position 1105
15:32:49.778 lua: value 64 byte position 1106
15:32:49.778 lua: value 0 byte position 1107
15:32:49.778 lua: value 0 byte position 1108
15:32:49.778 lua: value 0 byte position 1109
15:32:49.778 lua: value 240 byte position 1110
15:32:49.779 lua: value 240 byte position 1111
15:32:49.779 lua: value 1 byte position 1112
15:32:49.779 lua: value 0 byte position 1113
15:32:49.779 lua: value 0 byte position 1114
15:32:49.780 lua: value 0 byte position 1115
15:32:49.780 lua: value 240 byte position 1116
15:32:49.780 lua: value 0 byte position 1117
15:32:49.780 lua: value 10 byte position 1118
15:32:49.780 lua: value 84 byte position 1119
15:32:49.781 lua: value 64 byte position 1120
15:32:49.781 lua: value 5 byte position 1121
15:32:49.781 lua: value 0 byte position 1122
15:32:49.781 lua: value 0 byte position 1123
15:32:49.781 lua: value 0 byte position 1124
15:32:49.782 lua: value 0 byte position 1125
15:32:49.782 lua: value 0 byte position 1126
15:32:49.782 lua: value 0 byte position 1127
15:32:49.782 lua: value 90 byte position 1128
15:32:49.783 lua: value 64 byte position 1129
15:32:49.783 lua: value 0 byte position 1130
15:32:49.783 lua: value 0 byte position 1131
15:32:49.783 lua: value 0 byte position 1132
15:32:49.783 lua: value 240 byte position 1133
15:32:49.784 lua: value 240 byte position 1134
15:32:49.784 lua: value 1 byte position 1135
15:32:49.784 lua: value 0 byte position 1136
15:32:49.784 lua: value 0 byte position 1137
15:32:49.785 lua: value 0 byte position 1138
15:32:49.785 lua: value 240 byte position 1139
15:32:49.785 lua: value 0 byte position 1140
15:32:49.785 lua: value 10 byte position 1141
15:32:49.785 lua: value 64 byte position 1142
15:32:49.786 lua: value 64 byte position 1143
15:32:49.786 lua: value 5 byte position 1144
15:32:49.786 lua: value 0 byte position 1145
15:32:49.786 lua: value 0 byte position 1146
15:32:49.787 lua: value 112 byte position 1147
15:32:49.787 lua: syxByte -24
15:32:49.787 error running function 'onResponse': ctrlv2/p007.lua:396: bad argument #-1 to 'set' (number expected, got nil)

I put some stuff in the tutorials thread using the Mirage as an example; it may be of use to you.

2 Likes

@oldgearguy thanks a lot.
I went through your documentation but I already knew this.
I start to doubt on my own code or on the Mirage it self.

I have now a version that sends individual parameter status messages and then these are parsed in the patch.on response.
This seems to work but need to debug further.
Now its just a matter of debugging the timer…and the correct period per situation like large values, parameter sync.
Its all still full of bugs. But I I am getting there.
Now the controls get stuck somehow. even overflow the mirage.
But if I slow down things I miss values.
“rate” does not seem to do much neither looking at the message timestamps in the logs. .

tmrPeriod = 50
timer.setPeriod(tmrPeriod)
timer.disable()

---
--- check and test timer period. above is the default.
--- in the syncProgParameters() we should slow down
--- In the mainworker()  we slowdown in some cases
--- In the patchon response we go back to the default after processing
---

-- set to an impossible value to force mainWorker() to process first touched control
previousParameterNumber = -1

-- holds the value and direction (up or down) for each encoder
-- this is what the timer function uses to send to the Mirage
lastValue = {}
lastDirection = {}

-- holds the current value of each encoder as a user changes different controls
-- when a user comes back to a control, we know the current value to use in the next calculations
curEncValue = {}

oldValue = 0
maxBytes = 5
upArrow= 14
downArrow = 15

-- temporary texts to make reading debug statements easier
dbgTxt = {}
dbgTxt[14] = " Up"
dbgTxt[15] = " Down"

--de values used for sysex message
parameterSelect = 12
valueSelect = 13
functionKey = 22
endCommand = 127
--cancel = 11
-- which control is currently being changed
currentControl = 0
--Disables parsing of parameter update messages in patch.on.Response() its enabled when syncProgParameters() is called
--then disabled when the queue is empty.
progDataEnabled = 0


-- Parameters we send using another queue
queME = {36, 60, 61, 62, 63, 64, 68, 66, 69, 70, 71, 73, 76 }

programParameter = { 28, 31, 32, 33, 34, 35, 36, 37, 38, 27, 29, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 91 }

mirageDeviceId = 1
device = devices.get (mirageDeviceId)

queue = {}
queue.first = 0
queue.last =  -1
queue.data = {}

function insert(q, val)
   q.last = q.last + 1
   q.data[q.last] = val
end

function remove(q)
   if (q.first > q.last) then
      rval = -1
   else
      print("remove: q.data[q.first]= ", q.data[q.first], " q.first= ", q.first)
      local rval = q.data[q.first]
      midi.sendSysex(PORT_1, rval) 
      q.data[q.first] = nil
      q.first = q.first + 1
    --  print("remove: q.first= ", q.first)
   end
   return rval
end


function syncProgParameters()
--
-- This sends parameter messages using front panel commands.  
-- [91] ext computer should be on. #FIXME test for this

	currentControl = 0

-- enable the `progDataEnable` flag, allowing patchon.Reponse to ingest the incomming program parameter messages

	local progDataEnable = 1
	progDataEnabled = progDataEnable

--print(progDataEnabled)
--slowing doww timer, so we do not overload the mirage	

		tmrPeriod = 150
		timer.setPeriod(tmrPeriod)
		timer.enable ()

for progParaCount = 1, 32 do
        -- programParameter = global array holding all parameters we want to sync

	parameterK = programParameter[progParaCount]

	print ("Parameter Number as passed from the for loop: " .. parameterK)

        -- common way to separate the tens digit and the ones digit
	local byte1st = math.floor(parameterK / 10)
	local byte2nd = parameterK % 10

          sysexMsg = { 15, 1, 1, parameterSelect, byte1st, byte2nd, valueSelect, endCommand }
          insert(queue, sysexMsg)

--	if ( progParaCount == 10 ) then
--	  fetchConfig()
--	end

     end
end


local function slow_Enable (tab, val)
    for index, value in ipairs(tab) do
        if value == val then
            return true
        end
    end
    return false
end

--dec on the left - hex on the right
function formatHex (valueObject, value)
  return value .. string.format("%x", value) 
end


function timer.onTick()

--
-- flag here to enable processing of the queue only when needed?
--
  if (queue.first < queue.last) then
     remove(queue)
  end

  if (currentControl ~= 0) then

  --print("are we here?")
    local av = math.abs(lastValue[currentControl])
    local ad = lastDirection[currentControl]
    print("currentControl = " .. currentControl)
    if ( av > 5 ) then
 
    print(" *** Sending 5 arrowBytes, direction is" .. dbgTxt[ad])
      lastValue[currentControl] = av - 5
      sysexMsg = { 15, 1, 1, ad, ad, ad, ad, ad, endCommand }
      midi.sendSysex(PORT_1, sysexMsg)
    elseif ( av < 5 ) and ( av > 0) then

      print (" *** Sending remaining bytes " .. av .. dbgTxt[ad])
      sysexMsg = {15, 1, 1}

      for i = 1,av do
        sysexMsg[3+i] = ad
      end
      -- note that the variable i does not exist after the for loop so we cannot use it here
      sysexMsg[4+av] = endCommand
      midi.sendSysex(PORT_1, sysexMsg)

      -- finished sending bytes, zero out the value so we do not send extra bytes if called again
      lastValue[currentControl] = 0
      currentControl = 0

    else
      -- catch an edge case
      -- somehow we get called for the current control, but with no change in value
      print ("Sending nothing - Edge case")
      -- lastValue[currentControl] = 0
      currentControl = 0
    end
  end
end

function mainWorker(ValueObject, Value)

  local message = ValueObject:getMessage()
  local currentParameterNumber = message:getParameterNumber ()
  local curValue = message:getValue()

  -- worker function called, save off the parameter number
  currentControl = currentParameterNumber

  if ( currentParameterNumber ~= previousParameterNumber ) then
    
    -- do not have the timer running in case it catches us with partially filled in data
    timer.disable()

    -- we store the current value as the previous for the next time
    previousParameterNumber = currentParameterNumber

    -- common way to separate the tens digit and the ones digit
    local byte1st = math.floor(currentParameterNumber / 10)
    local byte2nd = currentParameterNumber % 10

    sysexMsg = { 15, 1, 1, parameterSelect, byte1st, byte2nd, valueSelect, endCommand }
    midi.sendSysex(PORT_1, sysexMsg)

    -- NOTE - this assumes your controls have a default value of 0
    -- if they start with a default of 64 or something else, different code needs to go here 

    -- get the last value for this control
    oldValue = (curEncValue[previousParameterNumber] or 0)

    timer.enable()

  end

  -- we need to keep track of the last value for each encoder
  -- there is probably a better way to pull this from the control
  -- so we do not have to keep storing it
  curEncValue[currentParameterNumber] = curValue
  
  if ( currentParameterNumber == previousParameterNumber ) then

    if slow_Enable(queME, currentControl) then
      print("yes control on the list lets slowdown : " .. currentControl)
      tmrPeriod = 1
   else
      print("no control not on the list timer to normal : " .. currentControl)
      tmrPeriod = 50
   end
   
   timer.setPeriod(tmrPeriod)

    -- figure out how much the encoder has changed from last time to this time
    -- note that the value can be positive or negative at this point
    local delta = curValue - oldValue

    -- save off the current value
    oldValue = curValue
    
    -- declare a local variable and set it to something
    local arrowDirection = upArrow

    -- the default is upArrow (positive) so only do things for negative or zero cases
    if ( delta == 0 ) then
      print("nothing to do")
      return
    elseif ( delta < 0 ) then
      arrowDirection = downArrow
    end

    -- for this parameter, save off the last value sent and the direction
    lastValue[currentParameterNumber] = (lastValue[currentParameterNumber] or 0) + delta
    lastDirection[currentParameterNumber] = arrowDirection
  end

end

function commandMessage(ValueObject, Value)

  local message = ValueObject:getMessage()
  local currentParameterNumber = message:getParameterNumber ()
  local curValue = message:getValue()
  local byte1st = math.floor(currentParameterNumber / 10)
  local byte2nd = currentParameterNumber % 10

	sysexMsg = { 15, 1, 1, parameterSelect, byte1st, byte2nd, endCommand }
	midi.sendSysex(PORT_1, sysexMsg)

end

--
-- FIXME... not 100% working.. Key range 0 .. 61  0 = C
--
function noteName(valueObject, value)
   local noteArray = { 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#' }

   -- this device uses a note range of C(-2) for MIDI note number 0 to G(8) for MIDI note 127
   -- if your device uses a different range, like C(0) to C(10) or C(-1) to C(9) 
   --   adjust the noteOct subtraction value accordingly
   noteLetter = (value % 12) + 1
   noteOct = math.floor(value / 12) - 2
   return (string.format("%s %d", noteArray[noteLetter], noteOct))
end

function makeSwapB(first, second)
   -- the AND operation (ampersand) captures only the 4 bits of each byte.
   -- the left shift operation moves the 4 bits into the proper place
   retVal = ((second & 0x0F) << 4) | (first & 0x0F)
   return retVal
end

-- 
function patch.onResponse (device, responseId, sysexBlock)
   -- first thing to do is always check the size and if it is not right, throw it away
   local recvSize = sysexBlock:getLength ()
   print (string.format("we recieved some data. length = %d", recvSize))

--if it is a valid program message
print("progdata enable is set to : " .. progDataEnabled)

--Swap this arround? first check size and then the `progDataEnabled` flag?
if ( progDataEnabled == 1 ) then
  if (recvSize == 9) and (sysexBlock:peek(4) == 13) then

   local deSyx = {}
   local topBits
   local highBit
   local k = 0

   print (string.format("skipping, Received probably program dump data. length = %d", recvSize))
   local skipBytes = 5   
   sysexBlock:seek(skipBytes)   

-- header 4 bytes, byte 4 is paraMeter status message 
-- F0h 0Fh 01h 0Dh 00h 2Fh 00h 00h F7h

--skipByes = 5 and for loop for 4 bytes we got:
--14:20:15.215 lua: value 3.0 byte position 0 (program, keyboardhalf)
--14:20:15.216 lua: value 56.0 byte position 1 (parameter)
--14:20:15.216 lua: value 4.0 byte position 2
--14:20:15.216 lua: value 5.0 byte position 3

   for i = 1, 4, 1 do
       deSyx[k] = sysexBlock:read()
      --print("value " .. deSyx[k] .. " byte position " .. k)
      --print ("programbyte = " .. deSyx[0] )
      k = k + 1
   end
-- should change a name of a control so the user knows 
-- Paramet 181 should be used for displaying the message
-- U1 16, U2 17, U3 18, U4 19
	if (deSyx[0] < 4) then
		Lower = deSyx[0] +1
		print ("Lower KBD has Program " .. Lower)
	elseif (deSyx[0] > 15) then
		Upper = deSyx[0] -15
		print ("Upper KBD has Program " .. Upper)
	else
		print ("error program bytes does not make sense byte value = " .. deSyx[0] )
	end
	print("The message we recieved is for Parameter: " .. deSyx[1])
	if (deSyx[1] == 34) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 2
	print("Value devided by 2 : " .. value )
	elseif (deSyx[1] == 35) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 2
	print("Value devided by 2 : " .. value )
	elseif (deSyx[1] == 36) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 2
	print("Value devided by 2 : " .. value )
	elseif (deSyx[1] == 37) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 2
	print("Value devided by 2 : " .. value ) 
	elseif (deSyx[1] == 45) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 4
	print("Value devided by 4 : " .. value ) 
	elseif (deSyx[1] == 46) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 4
	print("Value devided by 4 : " .. value ) 
	elseif (deSyx[1] == 47) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 4
	print("Value devided by 4 : " .. value ) 
	elseif (deSyx[1] == 48) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 4
	print("Value devided by 4 : " .. value ) 
	elseif (deSyx[1] == 49) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 4
	print("Value devided by 4 : " .. value ) 
	elseif (deSyx[1] == 55) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 4
	print("Value devided by 4 : " .. value ) 
	elseif (deSyx[1] == 56) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 4
	print("Value devided by 4 : " .. value ) 
	elseif (deSyx[1] == 57) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 4
	print("Value devided by 4 : " .. value ) 
	elseif (deSyx[1] == 58) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 4
	print("Value devided by 4 : " .. value ) 
	elseif (deSyx[1] == 59) then
	value = makeSwapB(deSyx[2], deSyx[3]) / 4
	print("Value devided by 4 : " .. value ) 
	else
	value = makeSwapB(deSyx[2], deSyx[3])
	end
	parameterMap.set(1, PT_VIRTUAL, deSyx[1], value)

	if (deSyx[1] == 59) then
		local progDataEnable = 0
		progDataEnabled = progDataEnable
		--tmrPeriod = 100
                --When done setting the timer back to default
		timer.setPeriod(tmrPeriod)
    timer.disable()
	end
	--print("The value we got is: " .. value )
    end

elseif (recvSize == 63) then
   print (string.format("Received configuration data. length = %d", recvSize))
   local skipBytes = 5
   local deSyx = {}
   local topBits
   local highBit
   local k = 0
   --decode the received data, starting after header data
   sysexBlock:seek(skipBytes)

   -- LUA allows you to use a for loop to process data and allows you to move in steps greater than one.
   -- this says - starting at the first data byte after the header, read until the end, and count by 2 while doing it
   for i = 1, (sysexBlock:getLength () - skipBytes), 2 do
      local firstB = sysexBlock:read()
      local secondB = sysexBlock:read()
      deSyx[k] = makeSwapB(firstB, secondB)
      k = k + 1
   end

   parameterMap.set(1, PT_VIRTUAL, 21, deSyx[1])
   parameterMap.set(1, PT_VIRTUAL, 22, deSyx[2])
   parameterMap.set(1, PT_VIRTUAL, 23, deSyx[3])
-- value needs to be devided by 2 
   deSyxHalf = math.floor(deSyx[4] / 2)
   parameterMap.set(1, PT_VIRTUAL, 24, deSyxHalf)
   parameterMap.set(1, PT_VIRTUAL, 25, deSyx[5])
   parameterMap.set(1, PT_VIRTUAL, 73, deSyx[6])
-- value needs to be devided by 2
   deSyxHalf = math.floor(deSyx[7] / 2)
   parameterMap.set(1, PT_VIRTUAL, 74, deSyxHalf)
   parameterMap.set(1, PT_VIRTUAL, 75, deSyx[8])
-- value needs to be devided by 2
   deSyxHalf = math.floor(deSyx[9] / 2)
   parameterMap.set(1, PT_VIRTUAL, 76, deSyxHalf)
   parameterMap.set(1, PT_VIRTUAL, 77, deSyx[10])
   parameterMap.set(1, PT_VIRTUAL, 81, deSyx[11])
   parameterMap.set(1, PT_VIRTUAL, 82, deSyx[12])
   parameterMap.set(1, PT_VIRTUAL, 83, deSyx[13])
   parameterMap.set(1, PT_VIRTUAL, 84, deSyx[14])

-- HERE are other config parameters that are very usefull.
-- left them for later #FIXME#

-- 85 Source start MSB 85
--   parameterMap.set(1, PT_SYSEX, 85, deSyx[15])
-- Source start LSB 86
--   parameterMap.set(1, PT_SYSEX, 86, deSyx[16])
-- Source end MSB 87
--   parameterMap.set(1, PT_SYSEX, 87, deSyx[17])
-- Source end LSB 88
--   parameterMap.set(1, PT_SYSEX, 88, deSyx[18])
-- Destination MSB 89
--   parameterMap.set(1, PT_SYSEX, 89, deSyx[19])
-- Destination LSB 90
--   parameterMap.set(1, PT_SYSEX, 90, deSyx[20])
-- Destination Bank 94 ???
--   parameterMap.set(1, PT_SYSEX, 94, deSyx[21])
-- Scale start factor 95 ??
--   parameterMap.set(1, PT_SYSEX, 95, deSyx[22])
-- Scale end factor 96 ??
--   parameterMap.set(1, PT_SYSEX, 96, deSyx[23])
-- External Computer Switch 91 !!Should be on!!!
--   parameterMap.set(1, PT_SYSEX, 91, deSyx[24])
-- Baudrate Switch 92 ????
--   parameterMap.set(1, PT_SYSEX, 92, deSyx[25])
-- Filter freq ISF-1 
--   parameterMap.set(1, PT_SYSEX, 93, deSyx[26])
--  Software Vesrion 
--   parameterMap.set(1, PT_SYSEX, 97, deSyx[27])

elseif (recvSize > 950) and (recvSize < 1950) then
      print (string.format("Received Program dump data block. length = %d", recvSize))


   local skipBytes = 23
   local deSyx = {}
   local topBits
   local highBit
   local k = 0

   -- decode the received data, starting after header data
   sysexBlock:seek(skipBytes)

   -- LUA allows you to use a for loop to process data and allows you to move in steps greater than one.
   -- this says - starting at the first data byte after the header, read until the end, and count by 2 while doing it
   for i = 1, (sysexBlock:getLength () - skipBytes), 2 do
      local firstB = sysexBlock:read()
      local secondB = sysexBlock:read()
      -- note that we are just build our transformed sysex data buffer here.
      -- the storing and parsing of the transformed data is done below
      deSyx[k] = makeSwapB(firstB, secondB)
      print("value " .. deSyx[k] .. " byte position " .. k)
      k = k + 1
   end
-- waveParameters, where waveSampleSelect() will provide the input for the correct offset where to find
-- wave 1 to 8, waveblock 1 .. 8
	parameterOffset = ( waveSelect * 24 - 24 )  
	waveParameter = { 65, 67, 68, 69, 70, 71, 72, 60, 61, 62, 63, 64 }  

	for nameCount = 1, 11 do

	 syxByte = (parameterOffset + ( nameCount -1 ) )
	 print (string.format("syxByte %d", syxByte ))

	 if ( syxByte == ( parameterOffset + 4 ) ) or ( syxByte == ( parameterOffset + 5)) then
	  deSyxHalf = math.floor(deSyx[syxByte] / 2)
	  parameterMap.set(1, PT_VIRTUAL, waveParameter[nameCount], deSyxHalf)
	  print (string.format("parameter %s - value / 2 = %d", waveParameter[nameCount], deSyxHalf))
	else 
	  parameterMap.set(1, PT_VIRTUAL, waveParameter[nameCount], deSyx[syxByte])
	  print (string.format("parameter %s - value = %d", waveParameter[nameCount], deSyx[syxByte]))
     end

   end

 else
	print("sure nothing here")
 end

end


waveSelect = 0

function waveSampleSelect(ValueObject, Value)

  local message = ValueObject:getMessage()
  local currentParameterNumber = message:getParameterNumber ()
  local curValue = message:getValue()

 if ( curValue < 9 ) and ( curValue > 0 ) then
-- lower keyboard wave
    local curWave = 21 
    waveSelect = curValue   
    sysexMsg = { 15, 1, 1, curWave, curValue, endCommand }

     midi.sendSysex(PORT_1, { 15, 1, 3 } )
  elseif ( curValue > 8 ) then
-- upper keyboard wave
    local curWave = 20
    local curValue = curValue - 8 
    waveSelect = curValue
       sysexMsg = { 15, 1, 1, curWave, curValue, endCommand }
       midi.sendSysex(PORT_1, { 15, 1, 19 } )
  end
 midi.sendSysex(PORT_1, sysexMsg)
end


function fetchConfig()
sysexMsg = { 15, 1, 0 }
midi.sendSysex(PORT_1, sysexMsg)
end

function dataExec(ValueObject, Value)

  local message = ValueObject:getMessage()
--  local currentParameterNumber = message:getParameterNumber ()
  local curValue = message:getValue()
  local functionNumber = ( message:getParameterNumber () - 200 )
	sysexMsg = { 15, 1, 1, functionKey, functionNumber, endCommand }
	midi.sendSysex(PORT_1, sysexMsg)

end

Template link: Electra One App

1 Like

Yes - I figured you knew all that, but since I was going through it myself, I thought that documenting it may help others see how we see and analyze the raw data.

My suggestion is to work on any of the other bus and make sure the “normal” controls all work solidly. That will verify that the core coding you have done is correct and solid. Then you can work on the edge cases without fear of the other code being a problem.

I will have some time Tuesday to look it over.

Note that in the code, you can do the following as needed to temporarily slow it down if it helps and then do the same to go back to the smaller value after you get the data:

currentState = timer.isEnabled()
timer.disable()
-- pick some slower value as needed
timer.setPeriod(100)
if (currentState == true) then
  timer.enable()
end
2 Likes

Ah would be great if you can look if my spagetti is ok :slight_smile: !

I am not very sure what is going on with the timers. need to debug and try.

Cheers

Tim

1 Like

One thing to do – unplug the Mirage (or use a MIDI splitter) and send the E1 output to MIDI-Ox and look at the timing information there. You will see exactly how many messages are sent and the spacing between each one.

For me, MIDI-Ox and MIDI Monitor are the equivalents of my oscilloscope and multi-meter when I am debugging electronics problems. They are basically my MIDI oscilloscope when dealing with sysex and timing and testing beta gear.

2 Likes

you know what is strange.
When I sync the parameters al the values are fetched from the program controls.
I verified them over and over and the values are always right.
Lets say I sync the filter, it jumps to value 90.
Now when I want to change the value by 1 up or down the value on the Mirage makes a huge jump and I can see many arrows where send.

The mainworker() function starts with:

local curValue = message:getValue()

If I remove from the same function

--timer.disable()
--timer.enable()

This issue disappears.

Should I in the update lastValue[currentControl] when syncProgParameters() runs?
It does not make much sense to me as I expect curValue to be the last value.
Or what about parameterMap.get to get the current value?

Or is it really an issue with the timer. () that you simply cannot stop and start them in our use case?

I need to look at things a bit.

Remember - when we first do things in mainWorker() when a control is moved for the first time, we grab the last stored value or 0. If the control has been set to a non-zero value by something, then that line will cause it to jump around and send a bunch of values.

EDIT - also, just for testing, you can put a debug print() statement right after every timer.enable() and timer()disable and then look in the E1 debug log to see the sequencing of those plus other stuff. Use some type of distinct txt in the prints so you know exactly which enable and disable you are calling

There must be a LUA call in the documentation to retrieve the current value of a control.
That is what we need here – use the stored value or get the current control value. I just haven’'t had time to play with the various calls to see which to use.

This is the code I am talking about:

-- NOTE - this assumes your controls have a default value of 0
    -- if they start with a default of 64 or something else, different code needs to go here 

    -- get the last value for this control
    oldValue = (curEncValue[previousParameterNumber] or 0)

Ah yes oldValue I remember.

-- Example of a simple value change callback function

-- Note, the value is not the MIDI value sent, but the state of the pad itself
function writeToLog (valueObject, value)
    local control = valueObject:getControl ()
    print ("value of control " .. control:getName () ..
        "." .. valueObject:getId () ..
        " changed to " .. value)
end

The state of the pad itself isn’t that exactly what we need?

Yes - it is what we need. I just didn’t have the preset loaded into an E1 to try out various ways to access the control information to see what worked to get the current value.

Also - small tweak to help the note naming – somehow the array of notes is starting with ‘B’ instead of ‘C’. I think if you just move the ‘B’ to the end, it should just work. Value is 0 to 61, and 0 = C, right?
So, manually walking through each step:
if value = 0, noteLetter = (0 % 12) + 1, so noteLetter = 1 and
noteOct = math.floor(0 / 12) - 2, so noteOct = -2
the printed value will be C -2

If the Mirage uses the value of 0 to mean C 0, then adjust the noteOct formula like this:
noteOct = math.floor(value / 12)

function noteName(valueObject, value)
   local noteArray = { 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B' }

   -- this device uses a note range of C(-2) for MIDI note number 0 to G(8) for MIDI note 127
   -- if your device uses a different range, like C(0) to C(10) or C(-1) to C(9) 
   --   adjust the noteOct subtraction value accordingly
   noteLetter = (value % 12) + 1
   noteOct = math.floor(value / 12) - 2
   return (string.format("%s %d", noteArray[noteLetter], noteOct))
end

I just wanted to take a quick moment to discuss the use of the timer.xxx() stuff here.

Normally, when the E1 is sending MIDI CCs or NRPNs or notes or something, the receiving device is capable of handling a fairly high volume/fast rate of data. So when you have an E1 control sending CC messages to change the filter cutoff or something, it seems to work smoothly because the sending rate and the receiving rate (and the synth internal buffering) are such that there’s rarely an overflow.

With older gear and with system exclusive messages, the situation can be different. Each sysex message needs to be fully received (F0 through F7) before any of it can be understood and applied. So the size and rate of sysex messages can cause internal overflows inside a synth because the internal buffering/queue may be fairly small and the synth CPU needs to do more work for longer to parse and apply the sysex data.

By using a timer function in the E1 you can control the rate and to some degree the volume of sysex messages sent to a synth. The idea is for the E1 controls to generate all the data you want to send, then you store up the values, maybe condense/strip out some if possible, and then send messages to the synth at a rate that does not overflow it.

The reason for using timer.disable() and timer.enable() is to control when the timer function does its work. You do not necessarily want the timer function always running and possibly trying to send a message before it’s fully packed up and targeted to the correct control.

By using timer.disable() you are saying - do nothing while I get the variables set the way I want. Then, when everything is ready, use timer.enable() to say – go ahead, process all the stuff in your queue.

That’s why in the mainWorker() function, I disable the timer when we start to access a different parameter. While the code is deciding what the new parameter is and what the value(s) to be sent are, we don’t want the timer thinking there’s things to do.

Yes, the E1 executes all this code very very quickly, but because we are using global variables, we don’t want to get into race conditions where the timer is reading some new current values and some old values and trying to do something with that combination.

The other way to handle it is to always leave the timer enabled and have a guard condition at the top of the timer function. Something like: if (readyToProcess == false) then return

and then in other parts of the code, you set readyToProcess = true or false, depending on where you are and what you are doing.

So that’s the rationale behind the use of the timer stuff here.

1 Like

Yeah I amended trying to fix that.
Its working with noteLetter = (value % 12) and

I am need some time to understand the timers etc.
Your explanation makes sense. Anyhow I appreciate your help a lot. Without your help I would never be able to get this far. Or it would have taken me some more months at least.

So we want to send only 1 messages at a time.
Perhaps is the queue I have implemented for sending out the Program parameter messages the way to go.

So every one sends to the same Queue and we only control the timer.period.

Anyhow Its quite complicated for me and I need time to investigate and try.

There is also a config parameter I found called “Baud rate” which can be set on/off.
Not sure what it does. I asked the internet and it does not know.

The current implementation works quite well.
The issues that are there are.

  • Lower values alway 1 behind after syncing the program parameters
  • the larger values [0 … 255] don’t stay in sync. The hex ones are the worse. You can see the Mirage gets overloaded. But after a DDOS no reward can be picked up :slight_smile:

The first issue might be a simple value +1 issue
The second one I am thinking to implement a dedicated function for those.

But as said… its too complicated for me and I do not have an overview what is really going on.

When I have time I am going to try to properly find out what the max data rate is the Mirage can handle.

The current version of the template is ready for testing.

https://app.electra.one/preset/vwkOrt6pJ3RGjpuCN6pl

Seems to work quite well now.

If you have a Mirage please try it out. Issues, ideas etc, please log them here

Thanks a lot @oldgearguy without you I would not make it :slight_smile:

1 Like

Thank you for this, @Flyweight! Will try to check this in the next days!

1 Like