Nuke.YKT's OPL3 protocol - DhrBaksteen/ArduinoOPL2 GitHub Wiki

Nuke.YKT's OPL3 protocol can be used to send OPL2 or OPL3 data over a serial line. The protocol encodes the address and data byte pairs in 3 bytes and adds a marker in bit 7 of the first byte to detect the start of a transfer.

The structure of a transfer is as follows:

Bit 7 6 5 4 3 2 1 0
Byte 0 1 0 0 0 A9 A8 A7 A6
Byte 1 0 A5 A4 A3 A2 A1 A0 D7
Byte 2 0 D6 D5 D4 D3 D2 D1 D0
  • A8 determines the bank of the OPL3 chip. For OPL2 this bit is always 0.
  • A9 determines the synth unit of the OPL3 Duo. 0 addresses the left chip, 1 addresses the right chip. For OPL2 this bit is left as 0.

Encoding

Some example code on how a transfer can be encoded:

/**
 * Encode a data write such as used by the OPL2 Audio Board and OPL3 Duo.
 *
 * @param bank - The synth unit (bit 1) and OPL3 bank (bit 0). Set to 0 for OPL2 Audio Board.
 * @param address - The address to write to.
 * @param data - The data we want to write.
 */
void encodeNukeYKT(byte bank, byte address, byte data) {
	byte byte0 = 0x80 | ((bank & 0x03) << 2) | (address >> 6);
	byte byte1 = ((address & 0x3F) << 1) | (data >> 7);
	byte byte2 = data & 0x7F;
}

Decoding

Following example can be used to decode the encoded bytes. Assume that we're already detected the marker bit in byte0.

/**
 * Decode NukeYKT encoded bytes into bank, address and data bytes for the OPL2 Audio Board or OPL3 Duo.
 *
 * @param byte0 - First received byte with marker bit (7) set.
 * @param byte1 - Second received byte.
 * @param byte2 - Third received byte.
 */
void decodeNukeYKT(byte byte0, byte byte1, byte byte2) {
	byte bank = (byte0 & 0x0C) >> 2;
	byte address = ((byte0 & 0x03) << 6) | ((byte1 & 0x7E) >> 1);
	byte data = ((byte1 & 0x01) << 7) | (byte2 & 0x7F);
}
⚠️ **GitHub.com Fallback** ⚠️