View Single Post
Old 02-02-2019, 05:08 AM   #8
Kaitain
Human being with feelings
 
Join Date: Nov 2016
Posts: 34
Default

Yes, transmitting the floats with no decimal point is a very good idea. I can send an "integer", which is easier, and then divide the received value in the other end (OSCbot script) to recover the original float number.

ARDUINO SIDE:


uint8_t SysExStart = 0xF0; // Start of System Exclusive message
uint8_t paramNumMSB, paramNumLSB; // 2 bytes for the parameter number
uint8_t SysExEnd = 0xF7; // EOX - End of Exclusive
float nVal; // Normalized value
float mappedVal; // Mapped value
union data { // Structure for sent and received value (mapped*1E^9)
uint32_t val;
uint8_t bytes[4];
} multi_TX, multi_RX;
float toLow; // Low margin for scaling
float toHigh; // High marging for scaling
uint8_t paramValMSB[4], paramValLSB[4]; // 4 bytes arrays for MSB and LSB parameter value

// OSC number MSB and LSB
paramNumMSB = uint8_t(OSCnum >> 7);
paramNumLSB = (uint8_t(OSCnum) & 0x7F);

// Convert value to float and normalize to 1024
nVal = float(val)/1024;

// Scale
toLow = float(minRange)/100;
toHigh = float(maxRange)/100;
mappedVal = map(nVal, 0, 1, toLow, toHigh);
multi_TX.val = uint32_t(mappedVal*1e9);

// Deconstruct float parameter value in bytes suitable for MIDI protocol: 4 bytes to 8 bytes, and bit 7 set to 0 on each byte
for (int i = 0; i <= 3; i++) {
paramValMSB[i] = (multi_TX.bytes[i] >> 4) & B00001111;
paramValLSB[i] = multi_TX.bytes[i] & B00001111;
}

// SysEx message assemby
uint8_t buff[] = {SysExStart, paramNumMSB, paramNumLSB, paramValMSB[0], paramValLSB[0], paramValMSB[1], paramValLSB[1], paramValMSB[2], paramValLSB[2], paramValMSB[3], paramValLSB[3], SysExEnd};

// Sens SysEx
usbMIDI.sendSysEx(sizeof(buff), buff, true);


OSCii bot SIDE:

@midimsg

// SYSEX messages
startSYSX = str_getchar(oscstr, 0); // Check if message is a SYSEX header

endSYSX = str_getchar(oscstr, 12); // Check if message is an end of SYSEX message.
(startSYSX == 240) && (endSYSX == 247) ? (
origccMSB = str_getchar(oscstr, 1); // Get parameter MSB from oscstr
origccLSB = str_getchar(oscstr, 2); // Get parameter LSB from oscstr
origcc = (origccMSB *128) + origccLSB;

valByte0 = ((str_getchar(oscstr, 3) << 4) & 0xF0) | str_getchar(oscstr, 4);
valByte1 = ((str_getchar(oscstr, 5) << 4) & 0xF0) | str_getchar(oscstr, 6);
valByte2 = ((str_getchar(oscstr, 7) << 4) & 0xF0) | str_getchar(oscstr, 8);
valByte3 = ((str_getchar(oscstr, 9) << 4) & 0xF0) | str_getchar(oscstr, 10);

val = ((valByte3 << 24) & 0xFF000000) | ((valByte2 << 16) & 0xFF0000) | ((valByte1 << 8) & 0xFF00) | valByte0;
curvalparam = val/1e9;


Althoug it can be more efficient, as you said, it works pretty well. Thanks for the hint!
Kaitain is offline   Reply With Quote