Does anyone have the sysex implementation details for the ML10X Message Type SysEx

I am looking for the details of the ML10X Message Type sent from a Morningstar Controller to the ML10X. The CC messages are only one way messages so it isn’t possible to get the state of the Loops after a program change.

I am currently controlling the ML10X using the editor sysex commands via the USB port but this isn’t a long term solution as the USB should be disconnected for Live use.

Is there anyone from Morningstar available that has this info? (I have sent an email to help@morningstarfx.com but I haven’t heard back from them yet).

Has anyone got a midi capture of the messages the MC controllers send to the ML10X? I just need to see the SysEx Header and the OpCodes sent by the controller. I can work out the rest once I have the basic info.

Is there anyone out there with this info?

I don’t have the sysex. I just want to get notified IF this pops up.

OK, I managed to get hold of a MCn pedal and captured the SysEx sent for the Morningstar message type. The thing that surprised me is the messages are one way. There isn’t much advantage using the MS Message Type SysEx over multiple CCs. In most cases multiple CC commands are escapsulated into one SysEx message.

IMHO I will carry on using the Editor SysEx Commands as the ML10x will reply to these. This enables a controller to keep its UI in-sync with the state of the ML10x.

Here is a summary of the Morningstar ML10x Message Type explained in my words, the team at Morningstar may choose to name things differently. I have used the Opcode concept as this is used in the Morningstar Controller API document.

THIS IS NOT AN OFFICIAL Morningstar Engineering document. These are my developers notes from doing some packet capture for my own project. Use these at your own risk. I am not liable if you damage any of your equipment using this information.

Enjoy !


Morningstar ML10x Message Type SysEx Frame Structure

All captured “ML10X Message Type” SysEx frames follow this structure:

F0 00 21 24 07 00 <opcode[0..6]> <transaction_id> 00 00 <payload...> 00 <checksum> F7

Where:

  • F0 SysEx start
  • 00 21 24 is Morningstar manufacturer ID.
  • 07 is ML10X Model ID, always 0x07
  • Byte 5 is reserved / always observed as 0x00.
  • opcode[0..6] is the 7-byte “Message Type” opcode block (see below).
  • transaction_id (maybe) is a single byte (often 0x00 in controller-originated messages).
  • The next two bytes are reserved / observed as 00 00.
  • payload is usually empty for Message Type commands.
  • The byte immediately before the checksum is an observed filler 0x00.
  • checksum can be ignored for decoding. The checksum calculated is documented in the Midi Controller API document
  • F7 SysEx end.

Opcode Layout

The 7-byte opcode block is sysex_data[6:13]:

opcode[0]  opcode[1]  opcode[2]  opcode[3]  opcode[4]  opcode[5]  opcode[6]
  0x01       P1         P2        DEV_ID      0x00     COMMAND      0x00
  • opcode[0] = 0x01 (fixed for Message Type frames observed)
  • opcode[1] = Parameter byte 1 (P1) (meaning depends on COMMAND)
  • opcode[2] = Parameter byte 2 (P2) (meaning depends on COMMAND)
  • opcode[3] = ML10X Device ID (the one you configure in settings):
    • 0x00..0x10 (0..16)
    • 0x00 = omni/broadcast (any ML10X may respond)
  • opcode[4] = 0x00 (observed constant)
  • opcode[5] = Command ID
  • opcode[6] = 0x00 (observed constant)

Note: There are two distinct encodings for (P1, P2) depending on the command category:

  1. loop/output commands: (P1, P2) are a 14-bit mask in a 7-bit-packed format
  2. bank/preset selection: (P1, P2) are direct 7-bit values (bank, preset)

Command Categories

Commands are grouped by how they use opcode[1] and opcode[2].


Category A — Loop / Output Commands

(14-bit Mask Encoding)

These commands operate on one or more loops or I/O ports.

Commands

Command ID Meaning
0x01 Set Loops
0x02 Engage Loops
0x03 Disengage Loops
0x04 Toggle Loops
0x09 Set Output on Loops
0x0A Cut Output to Loops
0x0B Restore Output to Loops
0x0C Toggle Set/Cut Output

Parameter Encoding

opcode[1] and opcode[2] form a 14-bit mask:

mask = opcode[1] | (opcode[2] << 7)

(Remember that Midi is a 7 bit byte so this is a typical way to represent larger numbers.)

  • opcode[1] contains bits 0–6
  • opcode[2] contains bits 7–13

Each bit selects one loop or port.

Bit Mapping

Bit Target
0 Loop A Tip
1 Loop A Ring
2 Loop B Tip
3 Loop B Ring
4 Loop C Tip
5 Loop C Ring
6 Loop D Tip
7 Loop D Ring
8 Loop E Tip
9 Loop E Ring
10 Input Tip
11 Input Ring
12 Output Tip
13 Output Ring

Category B — Bank / Preset Selection

(Direct Value Encoding)

These commands select a bank and preset.

Command

Command ID Meaning
0x08 Select Bank and Preset

Parameter Encoding

Byte Meaning
opcode[1] Bank index (0-based)
opcode[2] Preset number within bank (0–3)

Example

Select Bank 2 Preset 6:

opcode[1] = 0x01
opcode[2] = 0x06
opcode[5] = 0x08

Category C — Navigation Commands

(No Parameter Interpretation Required)

Commands

Command ID Meaning
0x06 Scroll Up
0x07 Scroll Down

opcode[1] and opcode[2] vary but are not interpreted as mask or bank
values.


Opcode Constants

The following opcode bytes are constant in all observed “Message Type” frames:

opcode[0] = 0x01
opcode[4] = 0x00
opcode[6] = 0x00

opcode[3] is not constant: it is the ML10X Device ID (0x00..0x10, with 0x00 = omni).


2 Likes

wow, nicely done. There was a request for documentation for this but after looking through the code again, I was a bit hesitant on try to explain this to the typical user, esp with all the bit banging