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:
- loop/output commands:
(P1, P2) are a 14-bit mask in a 7-bit-packed format
- 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).