Midi sysex sending 2 bytes from signed int

Hello everyone
I'm working on a remote control for my digital mixing desk (Roland M300). It consists of a rotary encoder and a small OLED display. The display shows the user a channel number and a numeric level (plus a graphical representation of level using a bar graph). Rotate the encoder to select the desired channel, then click the encoder and then rotate it to change the channel level. I've got a working user interface that selects the channel and increments or decrements an int to change the level (currently 0 to 127, but could be anything. Probably don't want to go much higher as it'll be a lot of rotations to turn something fully off) and am successfully sending a sysex with the correct model number, address, checksum etc.
My problem comes in calculating the 2 data bytes to be sent from my current int. The midi implementation can be found here; https://static.roland.com/assets/media/pdf/m300_midi_imple_e02.pdf - page 5, 7th field up from bottom right is the value i'm playing with - "channel 1 aux 1 send level". If my ASCII art is anything to go by then it looks something like this;

| 04 00 12 02 | 0aaaaaaa | Channel 1 aux send pan |
| 04 00 12 03# | 0bbbbbbb |

It also comes with the note "less than -905, -905,,,100 = -Inf, -90.5,,,+10.0dB"
In other words it's using a range between <-905 and 100 to do a full travel of the control, from off to full.

It also gives the following notes on page 25;
"A 7-bit byte can express data in the range of 128 steps. For data where greater precision
is required, we must use two or more bytes. For example, two hexadecimal numbers aa
bbH expression two 7-bit bytes would indicate a value of aa x 128 + bb"


" In the case of values which have a +/- sign, 40H=-64, 00H=0, 3FH=+63, so that the
decimal expression would be 64 less than the value given in the above chart.
In the case of two types, 40 00H = -8192, 00 00H = 0, 3F 7FH = +8191"

I've really tried my best to understand this! I've done lots of searching and reading. I know 2's complement is involved, and I know I have to turn my integer in to a pair of 7 bit bytes, but i'm waving my white flag and admitting i'm really struggling to work this one out.

In a bid of desperation I monitored the midi coming out of the desk, while changing these controls. The levels set are very approximate - it's the position of a fader, without any numeric way of checking what value it's at. The first column is the rough fader position, the rest is the sysex as seen on the connected computer. I'll only show the full sysex once, as it's all the same apart from these few key bytes (the first 2 bytes being the value, the 3rd being the checksum, which i'm able to calculate and have working fine);

-inf   F0 41 0F 00 00 24 12 04 00 12 02 40 00 28 F7
-20                                     7E 60 0A 
-5                                      7F 5E 0B 
0                                       00 11 57 
+5                                      00 3C 2C
+10                                     00 64 04

Can someone cleverer than me help me come up with a way of converting my integer (0-127 or whatever) to give me a full travel of this control, from -inf up to +10, sending the 2 appropriate bytes? I'm well and truly stuck! I'm sending the sysex as an array, so would just be placing the 2 values in to the relevant spots in the array before sending.

Thank you so much in advance!

To convert two 7 bit bytes to signed integer:

int combine (byte hi, byte lo) // assumes hi and lo have top bit clear
  int res = (hi << 7) | lo ;  // combine the 7 bit chunks to 14 bits in the int
  res = res << 2 >> 2 ;  // sign-extend as 16 bit
  return res ;

You'll see this maps:
40 00 -> -8192
7E 60 -> -160
7F 5E -> -34
00 11 -> 17
00 3C -> 60
00 64 -> 100

Thus each dB step is about 8.5 counts.

To map from a 14 bit signed int to two bytes:

void convertback (int value, byte * results)
  results[0] = (value>>7) & 0x7F ;
  results[1] = value & 0x7F ;

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.