Nord Modular Protocol (OS v3.03) started 2002-12-23 - version 1.01 lupd 2002-12-25 - version 1.06 notes : ======= all numbers are in hex, unless preceded by # for decimal or % for binary. hex numbers are denoted with lower case letters (like c1), symbols are in upper case (like C1). Only one type of messages is used - sysex. Some of this was inspired by Robert Pointon, see : http://www.cee.hw.ac.uk/~rpointon/music/protocol.html and by the enigma project (Mountain Man / Elby), see : http://www.users/cloud9.net/~mtman/NMsysex/ General layout for sysex messages : =================================== f0 33 CC 06 DATA f7 f0 - start of sysex 33 - manufacturer id. CC - Slot Id and command type (OpCode) in bits : %0CCCCCSS %0 - bit 7 always 0 in MIDI data where %SS = Slot number : %00 = slot A %01 = slot B %10 = slot C %11 = slot D %CCCCC = Operation Code (Opcode) - see following section : Opcodes 06 - Seems to be present in all messages - probably something to do with the synth type ?? DATA - Opcode dependant data, see following section : Opcodes Sometimes a Patch Identification code is used at the start of DATA, see **PID** Sometimes a checksum is used at the end of DATA, see **SS** f7 - End of sysex. OpCodes : ========= CCCCC = OpCode speculation : bit 4 = 0 - non slot related opcode bit 4 = 1 - slot related opcode bits 3..0 = opcode Sure (more or less) : Opcode = 00 : (00) ------------- Synth presence detection PC-> NM : I_Am request DATA = 00 VH VL 00 = messsage direction ?? VH = OS version high = #3 VL = OS version low = #3 : version = 3.03 NM -> PC : I_Am reply DATA = 01 VH VL 00 03 05 00 01 = message direction ?? VH = OS version high = #3 VL = OS version low = #3 : version = 3.03 00 03 05 00 - synth type ?? - rom revision ?? - serial nr ?? this was done on an NM key, expanded. OpCode = 13 : (4c .. 4f) ------------- PC -> NM : Parameter DATA = SC SDATA SC = 2f : Parameter Select : some parameter was highlighted in the editor. SDATA = 00 SS MM PP 00 = unknown, only seen as 0, might be direction indicator ?? SS = section - **SECTION_ID** MM = Module Index - 0 .. 127 PP = Parameter Index - see patch definitions SC = 40 : parameter change (virtual knob, button or slider ?) : Some parameter was changed in the editor. SDATA = SS MM PP VV SS = section - **SECTION_ID** MM = Module Index - 0 .. 127 PP = Parameter Index - see patch definitions VV = new value - see patch definitions SC = 43 : Morph range change for a parameter : SDATA = SS MM PP VV DD SS = section - **SECTION_ID** MM = Module Index - 0 .. 127 PP = Parameter Index - see patch definitions VV = span of the morph DD = Direction of span of morph (sign) 0 = positive - morph end > morph start ( >= ?? ) 1 = negative - morph end < morph start OpCode = 14 : (50 .. 53) ------------- NM Info Info sent from NM to PC concerning lights etc. DATA = SC SDATA **SS** SC = 05 - Voice Count SDATA = C1 C2 C3 C4 4 voice counts, 0 for slots that are off. SC = 07 - slot selection changed SC = 09 - slot select button (on synth) pressed SC = 39 - lights SDATA : 8 bytes encoding the lights The maximum amount of flashing lights seems to be 40 LL0 start index for this block ( 00 or 14 (#20)) LL1 bit 0 = light #0 or light #20 bit 2 = light #1 ... bit 4 = light #2 ... LL2 - bit 0, bit 0 = light #3 bit 2 = light #4 bit 4 = light #5 LL3 bit 0 = light #6 bit 2 = light #7 bit 4 = light #8 LL4 bit 0 = light #9 bit 2 = light #10 bit 4 = light #11 LL5 bit 0 = light #12 bit 2 = light #13 bit 4 = light #14 LL6 bit 0 = light #15 bit 2 = light #16 bit 4 = light #17 LL7 bit 0 = light #18 ... bit 2 = light #19 or light #39 Light index : start with module index 0 in the patch, if it has a light on it the index is 0, then go to module 1 etc. So the editor presuambly builds a lookup table for light indices to module indices. There are no modules with more than one 'ordinary' light on it, only the sequencers and modules thqat have a VU display, but those are handled SC = 40. I don't understand why there is so much air in this encoding. SC = 40 - VU meters / sequencer lights SDATA : VUI VU0R VU0L VU1R VU1L VU2R VU2L VU3R VU3L VU4R VU4L VUI Start index of this block 00 for first block, 05 for 2nd etc. so there would at most be 125 sequncer/VU modules (but it's not possible to have a working patch with that many modules) VU0R VU0L VU1R VU1L VU2R VU2L VU3R VU3L VU4R VU4L R channel used if mono (sequencer f.i.). Clipping indicators for VU's are included here. Encoding of these bytes is module type dependant SEQ : 10 = Off, 00 .. 0f : light 1 .. 16 lit. COMPRESSOR : ?? EXPANDER : ?? AUDIOIN : 10 20 30 40 ... ?? POLYIN : 10 20 30 40 ... ?? Start with module index 0 in the patch, if it has a led-bar on it the index is 0, then go to module 1 etc. So the editor presuambly builds a lookup table for led-bar indices to module indices. SC = 40 - (hardware) knob change SDATA = SECT MOD PARAM VALUE SECT = section ID - **SECTION_ID** MOD = Module index PARAM = parameter index VALUE = new value for parameter OpCode = 16 : (58 .. 5b) ------------- ACK, or data ? Ack - reply on deletion / move / insert ?? DATA = PID 7f PID (SDATA) **SS** PID - patch identification code - strange way of acking ?? (SDATA) sometimes present - ?? OpCode = 17 : (5c .. 5f) ------------- DATA = PP SDATA **SS** When PP < 40 then SC is a **PID** actually (PID) SC SDATA **SS** SC = 25 Knob assignment - a hardware knob is assigned to a parameter SDATA = 01 00 II II - KnobIndex 0 .. 17 - probably see patch defs - no SC = 26 Knob assignment change SDATA = II II = KnobIndex - 0 .. 17 - probably see patch defs SC = 32 Module deletions (multiple) SDATA = SI MI ( 32 SI MI ) * SI = Section index - **SECTION_ID** MI = Module index - 0 .. 127 SC = 34 Module Moves (multiple) SDATA = SI MI XX YY ( 34 SI MI XX YY ) * SI = Section Index - **SECTION_ID** MI = Module Index - 0 .. 127 XX = New X position (column) YY = New Y position (row) SC = 50 Cable Insertion SC = 51 Cable Deletion SC = 54 Cable move SC = 55 Send Controller Snapshot SC = 56 Note (musical, from keyboard floater to synth) SDATA = OO NN OO : 0 = On, 1 = Off NN : Note number 0 .. 127 Drone and repeat modes are done by the editor, not by synth. SC = 58 Get current notes SC = 70 Upload active slot (to PC) And when PP >= 40 it is a sub command : PP = 41 : patch manager command SDATA = SSC SSDATA SSC = 07 - slot change (4 bits slot mask) SSC = 09 - set active slot(slot number) SSC = 0a - request pach (n1, n2, n3) SSC = 14 - get patch list from ( aStart) PP = 44 : Get Synth Settings (sent by PC) responded by extended synth settings, see 1e PID 01 See Elby's notes about slot switching in working_notes.html OpCode = 1c : (70 .. 73) ------------- See Per Mattson's notes in sysex_3.html (he has a lot of 70's) Seems to be a middle packet from a multi packet sequence when loading a large patch DATA = PP SDATA **SS** When PP < 40 it is a **PID** actually (PID) SC SDATA **SS** SC = When PP >= 40 it is a subcommand rather PP = 40 ?? PP = 42 ?? PP = 43 ?? PP = 47 ?? OpCode = 1d : (74 .. 77) ------------- Seems to be the first packet from a multi packet sequence when loading a large patch DATA = PP SDATA **SS** When PP < 40 it is a **PID** actually (PID) SC SDATA **SS** SC = When PP >= 40 it is a subcommand rather PP = 42 - new (large) patch ?? see 1f 50 first packet of a series ?? (1d, 1c *, 1e) ?? OpCode = 1e : (78 .. 7b) ------------- Seems to be the last packet from a multi packet sequence when loading a large patch DATA = PP SDATA **SS** When PP < 40 it is a **PID** actually (PID) SC SDATA **SS** SC - 01 - extended synth settings, see notes **2 SC = 10 - patch settings , see notes **3 SC = 25 - section info 1 ?? SC = 29 - section info 3 ?? SC = 2d - section info 2 ?? SC = 34 - current notes When PP >= 40 it is a subcommand rather PP = 42 - end of (large) patch ?? last packet of a series ?? (1d, 1c *, 1e) ?? OpCode = 1f : (7c .. 73) ------------- DATA = PP SDATA **SS** When PP < 40 it is a **PID** actually (PID) SC SDATA **SS** SC = 10 - set patch settings (voice count, porta, bend, etc, etc) For each change a complete set of data is sent to the synth. SDATA = B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 B15 B4 - bit 5..0 B5 - bit 6 : Keyboard range min 0 .. #127 B5 - bit 5..0 B6 - bit 6 : Keyboard range max 0 .. #127 B6 - bit 5..0 B7 - bit 6 : Velocity range min 0 .. #127 B7 - bit 5..0 B8 - bit 6 : Velocity range max 0 .. #127 B8 - bit 5..1 : Bend range 0 .. #24 B8 - bit 0 B9 - bit 6..1 Portamento time 0 .. #127 B9 - bit 0 : Portamento mode 0 .. 1 (Normal .. Auto) B10 - bit 5..1 : Requested voices 0 .. #31 (1..#32) B10 - bit 6 : pedal mode 0 .. 1 (On/Off .. sustain) B11 - bit 5..0 // not sure about bit 5 B12 - bit 6..1 : Divider bar position 0 .. 7ff (0..#2047) ?? B12 - bit 0 B13 - bit 6..5 : octave shift 0 .. 4 (-2 .. +2) B13 - bit 0 : Green cables 0 .. 1 (off .. on) B13 - bit 1 : Gray cables 0 .. 1 (off .. on) B13 - bit 2 : Yellow cables 0 .. 1 (off .. on) B13 - bit 3 : Blue cables 0 .. 1 (off .. on) B13 - bit 4 : Red cables 0 .. 1 (off .. on) B14 - bit 3 : Voice retrig poly 0 .. 1 (off .. on) B14 - bit 4 : Voice retrig comn 0 .. 1 (off .. on) B14 - bit 5 : White cables 0 .. 1 (off .. on) B14 - bit 6 : Purple cables 0 .. 1 (off .. on) SC = 18 Module insertion SC = 21 SEQ zoom in/out When PP >= 40 it is a sub command rather PP = 41 - set synth settings (kbd mode, midi clock, etc etc) For every change a complete new set of data is sent. See Elby's notes about Synth settings in working_notes.html also see my additional work on this in elby-bh.html and in eval.txt (included at the bottom of this file). data is septets packed in octets, after decoding : DATA = RECORDTYPE B0 B1 B2 B3 B4 B5 B6 B7 FLEX-DATA RECORDTYPE - 03 is NM key ?? See notion **1 PP = 50 new patch (small patch ??) also 1d 42 can mean "new patch" ?? (large patch) Appendix : ========== **SECTION_ID** : #0 = global #1 = poly #2 = morph (system ??) **SS** : CheckSum The end of DATA contains a checksum sometimes : Sum modulo 80 over the whole message (including the f0 start of sysex byte) up to the byte just before **SS** Note : I am requests and replies do not use a checksum. PC parameter messages do not use a checksum **PID** : Patch Identification Used to link an NM patch to an editor patch. Incremented every time a patch is loaded into thee editor (from disk). PID = 0 seems to mean that the patch is not stored on disk, or maybe rather that it originates from the synth, as the PID is not changed when the patch is saved, or maybe PID's are not globaly unique but just slot unique ??. Pids are assigned modulo 40, which helps to distinguish certain command types : a PID > 40 can be a command ... see 17, new patch command. Remarks : The editor seems to have a bug. When a module is deleted that has a parameter assigned to a hardware knob I only see see a knob assignment change, not a module deletion. ========== ========== ========== ========== ========== ========== ========== notitions: ========== ========== ========== ========== ========== ========== ========== **1 synth settings as sent by editor to NM ------------------------------------------ 7C 06 41 01 - |000 0001 - 0000 0011 - 03 - ?? record type ?? 60 - 1|10 0000 - 1000 0000 - 80 - internal clock + minimum MIDI vel scale 1F - 00|1 1111 - 1111 1111 - ff - leds active + max idem 78 - 111 |1000 - 1000 0100 - 84 - tempo 26 - 010 0|110 - 1101 1111 - cf - loc on, kbmode sel slot, normal pedal pol, global sync = 31 7C - 111 11|00 - 0000 0000 - 00 - Master tune 01 - 000 000|1 - 1110 0000 - e0 - rx on, tx on, hook mode, 5 unused bits 60 - 110 0000| 32 - |011 0010 - 0110 0100 - 64 - d 1C - 0|01 1100 - 0111 0010 - 72 - r 4C - 10|0 1100 - 0110 0001 - 61 - a 16 - 001 |0110 - 0110 0001 - 61 - a 0B - 000 1|011 - 0111 0100 - 74 - t 50 - 101 00|00 - 0010 0000 - 20 - 40 - 100 000|0 - 0110 0010 - 62 - b 62 - 110 0010| 39 - |011 1001 - 0111 0010 - 72 - r 19 - 0|01 1001 - 0110 0101 - 65 - e 2F - 01|0 1111 - 0111 1001 - 79 - y 16 - 001 |0110 - 0110 0111 - 67 - n 71 - 111 0|001 - 0010 0000 - 20 - 00 - 000 00|00 - 0011 0001 - 31 - 1 62 - 110 001|0 - 0000 0000 - 00 - \0 00 - 000 0000| 00 - |000 0000 - 0000 0000 - 00 - ch 1 06 - 0|00 0110 - 0001 1011 - 1b - ?? 60 - 11|0 0000 - 0000 0001 - 01 - ch 2 11 - 001 |0001 - 0001 1011 - 1b - ?? 58 - 101 1|000 - 0000 0010 - 02 - ch 3 08 - 000 10|00 - 0001 1011 - 1b - ?? 36 - 011 011|0 - 0000 0011 - 03 - ch 4 03 - 000 0011| 0D - |000 1101 - 0001 1011 - 1b - ?? 41 - 1|00 0001 - 0000 0111 - 07 - slot selection ( 61 - 11|0 0001 - 0000 1110 - 0e - ABC- ); 60 - 110 |0000 - 0000 0100 - 09 - ActiveSlot ( 48 - 100 0|000 - 0000 0010 - 01 - Slot B); 08 - 000 10|00 - 0000 0101 - 05 - voice counts ( 0A - 000 101|0 - 0000 0001 - 01 - voice count A 1 01 - 000 0001| 00 - |000 0000 - 0000 0001 - 01 - voice count B 1 40 - 1|00 0000 - 0000 0001 - 01 - voice count C 1 20 - 01|0 0000 - 0000 0000 - 00 - voice count D 0 ); 00 - 000 |0000 4 bits left over 19 - checksum **3 : nothing yet ... ---------------------