Final (?) notes on programming the NSX-39


The Pocket Miku has turned into much more of a learning experience than I’d expected it to be. The regular MIDI sections are pretty much the same as for the other instruments I have, such as the Korg Kaosillator and the A-300 MIDI controller keyboard, as well as the software synth packaged with Java. One of the big hurdles was in trying to read incoming messages from the Miku and aligning them with data requests made by Java to obtain the contents of the lyrics and command slots.  Then there was that whole thing with SysEx messages. Since I don’t use a sequencer app on my PC (yet), system exclusive messages aren’t something that I’d encountered before. As mentioned in an earlier post, SysEx is used to access hardware properties that you can’t normally get to via regular MIDI messages, although it’s possible for the manufacturer to make them available as ChangeControl options (if so, CC is faster than SysEx). This means that SysEx messages are device specific, and songs that you write that use SysEx for one instrument won’t sound the same if you run them on something else.

One of the bigger learning opportunities came when I decided to reverse engineer the command slots. The Pocket Miku has 128 command slots, which are blocks of memory that hold instructions to be executed when the associated event is encountered. Examples include playing “Hello” on power-up, initializing a lyrics string when the “A”-“E”-“I”-“O”-“U” buttons are pressed, or doing something customized by the user. You can see the contents of all of the command slots by sending multiple “Command Slot # Requests”.

Let’s start out simply programming a command slot first. The best example is from the Perfect Guide, which is to add a “keypressed beep” to the SHIFT key (which I’ve discussed before).

The SHIFT key is button SW7, and the command slot for SW7 pressed is #17 (0x11), CS_SW7D. So this is the command slot we’re going to write to. To program the NSX-39, we need to use SysEx (0xF0). First, we need the SysEx header for accessing the NSX-39 features:

F0 – Start of SysEx message
43 79 09 11 – Header for programming the NSX-39

After this portion, we specify the instruction to execute. 0x01 will request the version number, 0x0B lets us request specific command slot strings. To SET a command slot, the command is 0x0C (without the “0x” part).

0C – Request command slot # contents
11 – CS_SW7D – slot # for SHIFT pressed

I’ve finally got a handle on the next portion. In MIDI, bit 7 (the most-significant bit of an 8-bit byte) specifies whether the byte is data, or a message status byte. The MIDI instruction for NOTE ON is 0x90 (1001 0000). Putting a NOTE ON instruction in the middle of the SysEx string will result in an error – “Illegal SysEx character. Only F0 and F7 are allowed.” To get around this, we need to convert the instruction from three 8-bit bits to four 7-bit bytes with padded leading 0’s.

Specifically, for our SHIFT key, I want to use NOTE ON to play the open triangle from the percussion instrument set on channel 9 of the general MIDI instrument sound bank, and I’ll randomly pick a velocity of 0x65. Since the triangle is key 81 (0x51) on the keyboard, the MIDI message would be

99 – Note on for channel 9
51 – Open triangle
65 – velocity (volume)

99 51 65

To convert this, turn it into binary:
10011001 01010001 01100101
reform as 7 bit bytes with leading 0 padding:
0000100 1100101 0100010 1100101
add leading 0’s to each byte to make 8-bit bytes again:
00000100 01100101 00100010 01100101
Then convert back to hex:
04 65 22 65

To complete the SysEx string, add 0xF7 as “end of SysEx message”.

The full message would be (in Java, no spaces):
F0 43 79 09 11 0C 11 04 65 22 65 F7

If we’re using sequencer software like Acid Studio or GarageBand, we’d just activate the SysEx box and type this message in as-is. In Java, we need to use a SysEx object kind of as follows:

SysexMessage sysexMessage = new SysexMessage();
sysexMessage.setMessage(byteMsg, byteMsg.length);
nsxRcvr.send(sysexMessage, -1);

Ok, so far so good.
Let’s get the string back. As mentioned above, we need to use SysEx to talk to the NSX-39, and the command we want to send is 0x0B – Request Command Slot.

F0 – Start of SysEx message
43 79 09 11 – NSX-39 header
0B – Request command slot contents
11 – Desired slot # (CS_SW7D = SHIFT pressed)
F7 – End of SysEx message

F0 43 79 01 00 0B 11 F7

This will cause the NSX-39 to come back with:
F0437909111B04652265F7

If we add white space to make it more readable, and divide it into lines with comments:
F0 – Start of SysEx
43 79 09 11 – NSX-39 header
1B – Command Slot contents (note there’s no slot number)
04 65 22 65 – The contents of the returned slot
F7 – End of SysEx

For amusement value, let’s look at another response string returned from the NSX-39:
F0437909111B0A0801000A060000F7

F0 – Start of SysEx
43 79 09 11 – NSX-39 header
1B – Command Slot contents (unknown slot)
0A 08 01 00 – Command 1
0A 06 00 00 – Command 2
F7 – End of SysEx

This anonymous slot executes two commands. From this example we can see that the commands are always 4 bytes each. We’ll have to look at the table on page 23 of the NSX39MIDIGuide.pdf to get the meaning of these commands:

0A 08 01 00 – Activate DOREIMI mode (play “Do Re Mi” on the keyboard)
0A 06 00 00 – Turn off NSX-1 compatibility mode

I’ll tell you now that this is slot 0, CS_MIDI_INIT, which activates on power-up, after the NSX-1 initialization completes. That is, whenever I turn on the Pocket Miku, the NSX-1 chip initializes, and then CS_MIDI_INIT is activated. The CS_MIDI_INIT command slot contains “DOREMI Mode On” and “NSX-1 Compatibility Off”. That’s it. (Although, when CS_MIDI_INIT finishes running, it activates command slot CS_MIDI_INIT2, which in turn calls CS_MIDI_INIT3, and you could put more commands in those 2 slots if you wanted.)

If you’ve got the MIDI Guide pdf open, then look at the rest of the commands. Most of them are fully-spelled out and start with 0x08 – 0x0F. The exceptions are DIRECT_MIDI_1 – DIRECT_MIDI_3 and DIRECT_MIDI_OUT_1 – DIRECT_MIDI_OUT_3. The first set sends direct data to the NSX-1 from the NSX-39. The second set is used to treat the NSX-39 as a MIDI controller by sending the data directly to the USB port.

The importance of these exceptions lies in the fact that the data is 7-bit encoded. If we go back to the contents of the CS_SW7D slot, we had obtained:

04 65 22 65

According to the NSX-39 MIDI Guide, this is a DIRECT_MIDI_3 command. To decode it, convert it to binary:
00000100 01100101 00100010 01100101
Take the right-most 7 bits:
1100101
Trim the remaining trailing 0 (and the space) and add those 7 bits back:
00000100 01100101 001000101100101
Remove the 8 right-most bits and call this D2:
D2 = 01100101 = 0x65
This leaves us with:
00000100 01100101 0010001
Take the right-most 6 bits:
0010001
Trim the trailing 0 and space and add those 6 bits back:
00000100 01100101010001
Cut the right-most 8 bits and call them D1:
D1 = 01010001 = 0x51 = 81
This leaves us with:
00000100 011001
Take the right-most 5 bits:
11001
Trim the trailing 0 and space and add those 5 bits back:
0000010011001
Take the right-most 8 bits and call them D0:
D0 = 10011001 = 0x99 = NOTE ON channel 9

Putting D0 D1 D2 in order:
99 51 65 = Note On, channel 9, Open Triangle, Velocity = 101

Granted, we could have predicted this just by looking at the encoded data, but knowing how to decode everything in the return strings means that I can now write encoder-decoders in Java, and have all of the command slots in human-readable form within a matter of a few seconds. This is important when looking at things like the string for CS_SW6U (VIBRATO button released):

CACCO_START, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 32)], TIME_WAIT 000013, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 28)], TIME_WAIT 000013, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 1E)], TIME_WAIT 000013, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 14)], TIME_WAIT 000013, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 0A)], TIME_WAIT 000013, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 05)], TIME_WAIT 000013, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 04)], TIME_WAIT 000013, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 03)], TIME_WAIT 000013, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 02)], TIME_WAIT 000013, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 01)], TIME_WAIT 000013, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 00)], TIME_TAIL, DIRECT_MIDI [CONTROLCHANGE Ch 0 (MODULATION 00)], CACCO_END_TIME 0F

Try reading that as pure hex code. (As a hint, “cacco” is the Japanese word for “parenthesis” or “bracket”.)

I may be the only person who cares at all about this. I whined some more on the U.S. Yamaha forums, and was told that the NSX-1 chip is only available in the Asian region, not in the U.S., and that I have to try finding the documentation from a server in Asia somewhere. So, this isn’t really on anyone’s radar, if they’re not Japanese. Now that I have my Java applet running, I’ll put everything away to focus on something else (maybe video games).

Advertisements
Previous Post
Next Post
Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: