//*************************************************************************
// usbMidi send SystemExclusive
//*************************************************************************
FLASHMEM void mySendSysEx(void)
{
screenFlagSysex = true; // draw ProgressBar
byte sysexData[512]; // SysEx buffer 349 Byte
sysexChecksum = 0;
uint8_t patchNo = (sysexSource + 1); // Patch No 1-128
uint8_t currentPatchBank = sysexBank; // A-P = 0-15
String numString = (patchNo);
String bankString = char(currentPatchBank + 65);
String fileString = (bankString + "/" + numString);
uint8_t data_len = NO_OF_PARAMS;
uint16_t sysexCount = 0;
// get patch parameter from sd card as String
File patchFile = SD.open(fileString.c_str());
String data[data_len]; //Array of data read in
recallPatchData(patchFile, data);
patchFile.close();
// convert string to sysex // len / index / value
sysexData[sysexCount++] = 0xF0; // - 0 - Start SysEx
sysexData[sysexCount++] = 0x00; // - 1 - ID
sysexData[sysexCount++] = 0x00; // - 2 - ID
sysexData[sysexCount++] = 0x00; // - 3 - ID
sysexData[sysexCount++] = 0x00; // - 4 - Device ID 0-64
sysexData[sysexCount++] = patchNo; // - 5 - Patch No
sysexData[sysexCount++] = currentPatchBank; // - 6 - Bank No
float_to_string(data[0], 12, sysexCount, sysexData); // (0) 12 7 - Patch Name
float_to_sysex1Byte(data[1], sysexCount, sysexData); // (1) 1 19 - oscALevel (0 - 1.00)
float_to_sysex1Byte(data[2], sysexCount, sysexData); // (2) 1 20 - oscBLevel (0 - 1.00)
float_to_sysex2Bytes(data[3], sysexCount, sysexData); // (3) 2 21 - noiseLevel ( -1.00 - +1.00)
uint8_to_sysex1Byte(data[4], sysexCount, sysexData); // (4) 1 23 - unison (0 - 2)
uint8_to_sysex1Byte(data[5], sysexCount, sysexData); // (5) 1 24 - oscFX (0 - 6)
float_to_sysex5Bytes(data[6], sysexCount, sysexData); // (6) 5 25 - detune (0 - 1.00000)
//sysexCount = String_to_bin(data[7], 4, sysexCount); // (7) - lfoSyncFreq (not available)
float_to_string(data[8], 4, sysexCount, sysexData); // (8) 4 30 - midiClkTimeInterval
//sysexCount = String_to_bin(data[9], 4, sysexCount); // (9) - lfoTempoValue (not available)
float_to_sysex5Bytes(data[10], sysexCount, sysexData); // (10) 5 34 - keytrackingAmount (0 - 1.0000)
float_to_sysex5Bytes(data[11], sysexCount, sysexData); // (11) 5 39 - glideSpeed (0 - 1.00000)
int8_to_sysex2Bytes(data[12], sysexCount, sysexData); // (12) 2 44 - oscPitchA (-24 - +24)
int8_to_sysex2Bytes(data[13], sysexCount, sysexData); // (13) 2 46 - oscPitchB (-24 - +24)
uint8_to_sysex1Byte(data[14], sysexCount, sysexData); // (14) 1 48 - oscWaveformA (0 - 63)
uint8_to_sysex1Byte(data[15], sysexCount, sysexData); // (15) 1 49 - oscWaveformB (0 - 63)
//sysexCount = String_to_bin(data[16], 1, sysexCount, &sysexData[0]); // (16) - pwmSource (1) (not available)
float_to_sysex1Byte(data[17], sysexCount, sysexData); // (17) 1 50 - pwmAmtA (0 - 0.99)
float_to_sysex1Byte(data[18], sysexCount, sysexData); // (18) 1 51 - pwmAmtB (0 - 0.99)
//sysexCount = String_to_bin(data[19], 6, sysexCount); // (19) - pwmRate (not available)
float_to_sysex2Bytes(data[20], sysexCount, sysexData); // (20) 2 52 - pwA (-1.00 - +1.00)
float_to_sysex2Bytes(data[21], sysexCount, sysexData); // (21) 2 54 - pwB (-1.00 - +1.00)
float_to_string(data[22], 4, sysexCount, sysexData); // (22) 4 56 - filterRes (0 - 15.0)
uint14_to_sysex2Bytes(data[23], sysexCount, sysexData); // (23) 2 60 - filterFreq (18 - 12000)
float_to_string(data[24], 4, sysexCount, sysexData); // (24) 4 62 - filterMix (0 - -99.0)
float_to_sysex2Bytes(data[25], sysexCount, sysexData); // (25) 2 66 - filterEnv (-1.00 - +1.00)
float_to_sysex5Bytes(data[26], sysexCount, sysexData); // (26) 5 67 - oscLfoAmt (0 - 1.00000)
float_to_sysex5Bytes(data[27], sysexCount, sysexData); // (27) 5 73 - oscLfoRate (0 - 40.0000)
uint8_to_sysex1Byte(data[28], sysexCount, sysexData); // (28) 1 78 - oscLFOWaveform (0 - 12)
uint8_to_sysex1Byte(data[29], sysexCount, sysexData); // (29) 1 79 - oscLfoRetrig (0 - 1)
//sysexCount = String_to_bin(data[30], 1, sysexCount); // (30) - oscLFOMidiClkSync (not available)
uint8_to_sysex1Byte(data[31], sysexCount, sysexData); // (31) 1 80 - myFilterLFORateValue (1 - 127)
uint8_to_sysex1Byte(data[32], sysexCount, sysexData); // (32) 1 81 - filterLfoRetrig (0 - 1)
//sysexCount = String_to_bin(data[33], 1, sysexCount); // (33) - oscLFOMidiClkSync (not available)
float_to_sysex5Bytes(data[34], sysexCount, sysexData); // (34) 5 82 - filterLfoAmt (0 - 1.00000)
uint8_to_sysex1Byte(data[35], sysexCount, sysexData); // (35) 1 87 - filterLFOWaveform (0 - 12)
uint14_to_sysex2Bytes(data[36], sysexCount, sysexData); // (36) 2 88 - filterAttack (0 - 11880)
uint14_to_sysex2Bytes(data[37], sysexCount, sysexData); // (37) 2 90 - filterDecay (0 - 11880)
//float_to_sysex1Byte(data[38], sysexCount, sysexData); // (38) 1 92 - filterSustain (0 - 1.00)
uint14_to_sysex2Bytes(data[39], sysexCount, sysexData); // (39) 2 94 - filterRelease (0 - 11880)
uint14_to_sysex2Bytes(data[40], sysexCount, sysexData); // (40) 2 96 - ampAttack (0 - 11880)
uint14_to_sysex2Bytes(data[41], sysexCount, sysexData); // (41) 2 98 - ampDecay (0 - 11880)
//float_to_sysex1Byte(data[42], sysexCount, sysexData); // (42) 1 100 - ampSustain (0 - 1.00)
uint14_to_sysex2Bytes(data[43], sysexCount, sysexData); // (43) 2 101 - ampRelease (0 - 11880)
//sysexCount = float_to_sysex5Bytes(data[44], sysexCount, &sysexData[0]);// (44) - fxAmt (not available)
//sysexCount = float_to_sysex5Bytes(data[45], sysexCount, &sysexData[0]);// (45) - fxMix (not available)
//sysexCount = float_to_sysex5Bytes(data[46], sysexCount, &sysexData[0]);// (46) - pitchEnv (not available)
uint8_to_sysex1Byte(data[47], sysexCount, sysexData); // (47) 1 102 - velocitySens (0-4)
uint8_to_sysex1Byte(data[48], sysexCount, sysexData); // (48) 1 103 - chordDetune (0 - 127)
uint8_to_sysex1Byte(data[49], sysexCount, sysexData); // (49) 1 104 - FxPot1value (0 - 127)
uint8_to_sysex1Byte(data[50], sysexCount, sysexData); // (50) 1 105 - FxPot2value (0 - 127)
uint8_to_sysex1Byte(data[51], sysexCount, sysexData); // (51) 1 106 - FxPot3value (0 - 127)
uint8_to_sysex1Byte(data[52], sysexCount, sysexData); // (52) 1 107 - FxPrgNo (0 - 15)
uint8_to_sysex1Byte(data[53], sysexCount, sysexData); // (53) 1 108 - FxMixValue (0 - 127)
float_to_sysex5Bytes(data[54], sysexCount, sysexData); // (54) 5 109 - FxMixValue (10000 - 60000)
uint8_to_sysex1Byte(data[55], sysexCount, sysexData); // (55) 1 114 - Osc1WaveBank (0 - 15)
uint8_to_sysex1Byte(data[56], sysexCount, sysexData); // (56) 1 115 - Osc1WaveBank (0 - 15)
uint8_to_sysex1Byte(data[57], sysexCount, sysexData); // (57) 1 116 - myBoost (0 - 1)
float_to_sysex5Bytes(data[58], sysexCount, sysexData); // (58) 5 117 - pitchEnvA (-1.00 - +1.00)
float_to_sysex5Bytes(data[59], sysexCount, sysexData); // (59) 5 119 - pitchEnvB (-1.00 - +1.00)
float_to_sysex2Bytes(data[60], sysexCount, sysexData); // (60) 2 121 - driveLevel (Osc level) (0.00 - 1.25)
float_to_sysex5Bytes(data[61], sysexCount, sysexData); // (61) 5 123 - myFilVelocity (0 - 1.00)
float_to_sysex5Bytes(data[62], sysexCount, sysexData); // (62) 2 125 - myAmpVelocity (0 - 1.00)
uint8_to_sysex1Byte(data[63], sysexCount, sysexData); // 1 127 - myUnisono (0-2)
//sysexCount = uint8_to_sysex1Byte(data[64], sysexCount, &sysexData[0]);// - dummy
//sysexCount = uint8_to_sysex1Byte(data[65], sysexCount, &sysexData[0]);// - dummy
uint8_to_sysex1Byte(data[66], sysexCount, sysexData); // 1 128 - WShaperNo (0-14)
float_to_sysex5Bytes(data[67], sysexCount, sysexData); // 5 129 - WShaperDrive (0.10 - 5.00)
float_to_sysex5Bytes(data[68], sysexCount, sysexData); // 5 134 - LFO1phase (0 - 180.0)
float_to_sysex5Bytes(data[69], sysexCount, sysexData); // 5 139 - LFO2phase (0 - 180.0)
for (uint8_t i = 0; i < 16; i++) {
uint8_to_sysex1Byte(data[70+i], sysexCount, sysexData); // 16 144 - SeqNote1Buf (0 - 127)
}
for (uint8_t i = 0; i < 16; i++) {
uint8_to_sysex1Byte(data[86+i], sysexCount, sysexData); // 16 160 - SeqNoteBufStatus (0 - 1)
}
uint14_to_sysex2Bytes(data[102], sysexCount, sysexData); // 2 176 - SEQbpmValue (101 - 462)
float_to_sysex5Bytes(data[103], sysexCount, sysexData); // 5 178 - SEQdivValue (float)
uint8_to_sysex1Byte(data[104], sysexCount, sysexData); // 1 183 - SEQstepNumbers (0 - 15)
float_to_sysex5Bytes(data[105], sysexCount, sysexData); // 5 184 - SEQGateTime (float)
uint8_to_sysex1Byte(data[106], sysexCount, sysexData); // 1 189 - SEQdirection (0 - 3)
uint8_to_sysex1Byte(data[107], sysexCount, sysexData); // 1 190 - oscDetuneSync (0 - 1)
int8_to_sysex2Bytes(data[108], sysexCount, sysexData); // 2 191 - oscPitchA (-12 - +12)
float_to_sysex5Bytes(data[109], sysexCount, sysexData); // 5 193 - oscMasterTune (float)
float_to_sysex5Bytes(data[110], sysexCount, sysexData); // 5 198 - OscVCFMOD (float)
for (uint8_t i = 0; i < 16; i++) {
uint8_to_sysex1Byte(data[111], sysexCount, sysexData); // 16 203 - SeqVeloBuf (0 - 127)
}
for (uint8_t i = 0; i < 48; i++) {
uint8_to_sysex1Byte(data[127], sysexCount, sysexData); // 48 219 - SeqNote1Buf (0 - 127)
}
for (uint8_t i = 0; i < 16; i++) {
uint8_to_sysex1Byte(data[175], sysexCount, sysexData); // 16 267 - SeqNoteCount (0 - 3)
}
uint8_to_sysex1Byte(data[191], sysexCount, sysexData); // 1 283 - SEQmode (0 - 2)
uint8_to_sysex1Byte(data[192], sysexCount, sysexData); // 1 284 - SEQMidiClkSwitch (0 - 1)
uint8_to_sysex1Byte(data[193], sysexCount, sysexData); // 1 285 - LadderFilterpassbandgain (0 - 127)
uint8_to_sysex1Byte(data[194], sysexCount, sysexData); // 1 286 - LadderFilterDrive (1 - 127)
int8_to_sysex2Bytes(data[195], sysexCount, sysexData); // 2 287 - envelopeType1 (-8 - +8)
int8_to_sysex2Bytes(data[196], sysexCount, sysexData); // 2 289 - envelopeType2 (-8 - +8)
float_to_sysex5Bytes(data[197], sysexCount, sysexData); // 5 291 - PitchWheelAmt (float)
float_to_sysex5Bytes(data[198], sysexCount, sysexData); // 5 296 - MODWheelAmt (float)
uint8_to_sysex1Byte(data[199], sysexCount, sysexData); // 1 301 - myFilter (1 - 2)
float_to_sysex5Bytes(data[200], sysexCount, sysexData); // 5 302 - pwmRateA (-10.00 - + 10.00)
float_to_sysex5Bytes(data[201], sysexCount, sysexData); // 5 307 - pwmRateB (-10.00 - + 10.00)
uint14_to_sysex2Bytes(data[202], sysexCount, sysexData); // 2 312 - LFO1fadeTime (0 - 12000) Fade in
uint14_to_sysex2Bytes(data[203], sysexCount, sysexData); // 2 314 - LFO1releaseTime (0 - 12000) Fade out
float_to_sysex5Bytes(data[204], sysexCount, sysexData); // 5 316 - filterFM (0.00000 - 1.00000) Osc1
float_to_sysex5Bytes(data[205], sysexCount, sysexData); // 5 321 - filterFM2 (0.00000 - 1.00000) Osc2
uint14_to_sysex2Bytes(data[206], sysexCount, sysexData); // 2 326 - LFO2fadeTime (0 - 12000) Fade in
uint14_to_sysex2Bytes(data[207], sysexCount, sysexData); // 2 328 - LFO2releaseTime (0 - 12000) Fade out
float_to_sysex5Bytes(data[208], sysexCount, sysexData); // 5 330 - Osc1ModAmt (0.00000 - 1.00000) Fx Mod
int8_to_sysex2Bytes(data[209], sysexCount, sysexData); // 2 335 - LFO1enCurve (-8 - +8)
int8_to_sysex2Bytes(data[210], sysexCount, sysexData); // 2 337 - LFO2enCurve (-8 - +8)
uint8_to_sysex1Byte(data[211], sysexCount, sysexData); // 1 339 - LFO1mode (0 - 1)
uint8_to_sysex1Byte(data[212], sysexCount, sysexData); // 1 340 - LFO2mode (0 - 1)
float_to_sysex5Bytes(sysexChecksum, sysexCount, sysexData); // 5 341 - SysEx checksum
sysexData[sysexCount++] = 0xF7; // 1 346 - End SysEx (0xF7)
usbMIDI.sendSysEx(sysexCount, sysexData, true); // send SysEx data
}
//*************************************************************************
// convert float to SysEx string
//*************************************************************************
FLASHMEM void float_to_string (String value, uint8_t len, uint16_t &sysexCount, byte *sysexData)
{
for (uint8_t i = 0; i < len; i++) {
sysexData[sysexCount++] = value[i];
sysexChecksum += value[i];
}
}
//*************************************************************************
// convert float into SysEx uint7Bit (float 0 - 0.127)
//*************************************************************************
FLASHMEM void float_to_sysex1Byte (String value, uint16_t &sysexCount, byte *sysexData)
{
uint8_t val = (value.toFloat() * 100);
sysexData[sysexCount++] = val;
sysexChecksum += val;
}
//*************************************************************************
// convert float into SysEx uint7Bit (- 127 - +127)
//*************************************************************************
FLASHMEM void int8_to_sysex2Bytes (String value, uint16_t &sysexCount, byte *sysexData)
{
uint8_t l_byte = (uint8_t)(value.toInt());
uint8_t h_byte = 0;
if (l_byte > 127) {
l_byte = 256 - l_byte; // make positive value
h_byte = 1; // minus Sign
}
sysexData[sysexCount++] = h_byte; // Sign (- = 1 / + = 0)
sysexChecksum += h_byte;
sysexData[sysexCount++] = l_byte; // data
sysexChecksum += l_byte;
}
//*************************************************************************
// convert string into SysEx int7 (float -1.27 - +1.27)
//*************************************************************************
FLASHMEM void float_to_sysex2Bytes (String value, uint16_t &sysexCount, byte *sysexData)
{
uint8_t h_byte = int8_t(value.toFloat() * 100);
int8_t l_byte = h_byte;
// calc h_byte
h_byte >>= 7;
// l_byte is sign
if (l_byte < 0) {
l_byte = l_byte * (-1);
}
sysexData[sysexCount++] = h_byte; // Sign (- = 1 / + = 0)
sysexChecksum += h_byte;
sysexData[sysexCount++] = l_byte; // data
sysexChecksum += l_byte;
}
//*************************************************************************
// convert float into SysEx uint14 (float 0.00 - 16.383)
//*************************************************************************
FLASHMEM uint16_t float_to_uint14bit (String value, uint16_t sysexCount, byte *sysexData)
{
uint8_t h_byte = int8_t(value.toFloat() * 100);
int8_t l_byte = h_byte;
// calc h_byte
h_byte >>= 7;
// l_byte is sign
if (l_byte < 0) {
l_byte = l_byte * (-1);
}
sysexData[sysexCount++] = h_byte; // Sign (- = 1 / + = 0)
sysexChecksum += h_byte;
sysexData[sysexCount++] = l_byte; // data
sysexChecksum += l_byte;
return sysexCount;
}
//*************************************************************************
// convert 7bit value into SysEx 1Byte ( 0-127)
//*************************************************************************
FLASHMEM void uint8_to_sysex1Byte (String value, uint16_t &sysexCount, byte *sysexData)
{
uint8_t val = value.toInt();
sysexData[sysexCount++] = val;
sysexChecksum += val;
}
//*************************************************************************
// convert 14bit value into SysEx 2Byte (0-16383)
//*************************************************************************
FLASHMEM void uint14_to_sysex2Bytes (String value, uint16_t &sysexCount, byte *sysexData)
{
uint16_t var16 = (value.toInt());
uint16_t var16_x = var16;
// calc h_byte & l_byte -----------
var16 = var16 << 1;
uint8_t h_byte = var16 >> 8;
uint8_t l_byte = var16_x & 0x7F;
sysexData[sysexCount++] = h_byte;
sysexChecksum += h_byte;
sysexData[sysexCount++] = l_byte;
sysexChecksum += l_byte;
}
//*************************************************************************
// convert 32bit float value into SysEx 5Byte
//*************************************************************************
FLASHMEM void float_to_sysex5Bytes(String value, uint16_t &sysexCount, byte *sysexData)
{
uint8_t sysexBytes[5];
uint8_t temp_val = 0;
uint8_t bit_val = 0;
union {
float fval;
byte bval[4];
} floatAsBytes;
floatAsBytes.fval = (value.toFloat());
// Bit mask
for (uint8_t i = 0; i < 4; i++) {
// Bit 0-6 to Byte 1-4
sysexBytes[i] = floatAsBytes.bval[i] & 0x7F;
// Bit7 to 5.Byte
temp_val = floatAsBytes.bval[i];
bit_val = bit_val << 1;
if (temp_val >= 128) {
bit_val = (bit_val | 0x01);
}
}
sysexBytes[4] = bit_val;
// write sysex buffer
for (uint8_t i = 0; i < 5; i++){
sysexData[sysexCount++] = sysexBytes[i];
sysexChecksum += sysexBytes[i];
}
}