Forum Rule: Always post complete source code & details to reproduce any issue!
Page 10 of 10 FirstFirst ... 8 9 10
Results 226 to 235 of 235

Thread: New Teensy 4.1 DIY Synthesizer

  1. #226
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    302
    Hi Rolf. Think of it this way:-

    Code:
    // Sysex data lenght [28];                            // Daten lenght max 256
    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        - Folder No
    
    sysexData[sysexCount++] = /* the content of (data[0], 12) goes here */;    // 7  Patchname character 1
    sysexData[sysexCount++] = /* the content of (data[1], 12) goes here */;    // 8  Patchname character 2
    sysexData[sysexCount++] = /* the content of (data[2], 12) goes here */;    // 9  Patchname character 3
    sysexData[sysexCount++] = /* the content of (data[3], 12) goes here */;    // 10 Patchname character 4
    
    // and so on ...
    Greetings from Australia.

  2. #227
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    Hi MatrixRat

    Thanks for your tip. That's a good idea

  3. #228
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    Small update..

    Soon there will be SysEx DUMP for Jeannie. Then nothing stands in the way of the patch exchange.

    Click image for larger version. 

Name:	20220501_123341.jpg 
Views:	13 
Size:	120.3 KB 
ID:	28298

    The transmission path is selected with DESTINATION, eg Midi or USB
    DUMP TYPE selects a patch, bank, or all
    With DUMP-Bank the bank
    With source the patch
    With SYSEX-DUMP transmission to the PC or reception
    Transmission or reception is then initialized via the load/save button


    Sending and receiving from SysEx already works. But I still have to do some programming

    Click image for larger version. 

Name:	20220505_084324.jpg 
Views:	9 
Size:	224.1 KB 
ID:	28295

    Click image for larger version. 

Name:	20220505_092444.jpg 
Views:	10 
Size:	297.3 KB 
ID:	28296

    Click image for larger version. 

Name:	20220505_084723.jpg 
Views:	9 
Size:	368.5 KB 
ID:	28297

    Never ending programming. Greetings, Rolf

  4. #229
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    Quote Originally Posted by MatrixRat View Post
    Hi Rolf. Think of it this way:-

    Code:
    // Sysex data lenght [28];                            // Daten lenght max 256
    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        - Folder No
    
    sysexData[sysexCount++] = /* the content of (data[0], 12) goes here */;    // 7  Patchname character 1
    sysexData[sysexCount++] = /* the content of (data[1], 12) goes here */;    // 8  Patchname character 2
    sysexData[sysexCount++] = /* the content of (data[2], 12) goes here */;    // 9  Patchname character 3
    sysexData[sysexCount++] = /* the content of (data[3], 12) goes here */;    // 10 Patchname character 4
    
    // and so on ...
    Greetings from Australia.
    Hallo,
    I optimized my code a bit. I use call-by-referense for string function and variables.
    That uses less memory

    Code:
    //*************************************************************************
    // 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];
        }
    }

  5. #230
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    302
    Hi Rolf. Looks like you're making good progress. Have been quietly following this thread and learned some useful stuff so you are one of my many teachers here.

    Must also mention, Paul, Defragster, KurtE, MJS513, FrankB (hope you are not eating too much popcorn), Oddson and many others, Thank you all.

    Mmm, there's some good stuff in that last code snippet.

    Am planning to use the Audio tool to re-create an analog synth I built in the late '70s but not before I've got a decent set of knobs for it. Had a Sequencer and the Oscilloscope was permanently connected, so was triggered when a note began and the Y axis would be looking at the output. Displayed the effect of envelope, filter cutoff and resonance which was really useful for teaching musicians how to operate it.

    Keep up the good work.

  6. #231
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    Hi MatrixRat
    The SysEx dump for a patch is very complex. The patch is stored on the SD card as a text string.
    This contains values in 32-bit floating point and 16-bit integer values.
    You can still save some SysEX data if you convert individual function bits into a 7-bit value.

    For example here:

    Code:
    uint8_to_sysex1Byte(data[29], sysexCount, sysexData);    // (29) 1Byte    oscLfoRetrig (0 - 1)
    uint8_to_sysex1Byte(data[32], sysexCount, sysexData);    // (32) 1Byte    filterLfoRetrig (0 - 1)
    uint8_to_sysex1Byte(data[57], sysexCount, sysexData);    // (57) 1Byte    myBoost (0 - 1)
    uint8_to_sysex1Byte(data[107], sysexCount, sysexData);    // (107) 1Byte   oscDetuneSync (0 - 1)
    uint8_to_sysex1Byte(data[86+i], sysexCount, sysexData);   // (86 - 101) 16Bytes   SeqNoteBufStatus (0 - 1)
    ...

  7. #232
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    302
    Thanks Rolf. Got me thinking, should be soldering.

    I understand that the logical choice is to send floats as ascii so we can put the decimal point where needed. But, say if we only have one digit before the decimal point then we don't necessarily need to send the decimal point itself and what's right of point can (i think) be compacted and sent across three sysex "bytes". Thus the payload is reduced and TX and RX handlers will process stuff quicker than midi can send the verbatim ascii float. Of course it's up to the handler to sort out the details and give us back two floats.

    A theoretical snip from a Midi Implementation map might look a bit like this:-

    Code:
     
     0x00 //MSD = float1 first digit, LSD = float2 first digit - 0-7 fits both cases
     0x00 //bits 15-21
     0x00 //bits 8-14
     0x00 //bits 0-7 -> packed right of point float2
     0x00 //bits 15-21
     0x00 //bits 8-14
     0x00 //bits 0-7 -> packed right of point float1
    If that works then two floats use seven sysex "bytes".

    Actually not quite correct, would need to shuffle more bits but you get the idea?
    Last edited by MatrixRat; 05-10-2022 at 01:01 PM.

  8. #233
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    I programmed different conversions for different floating point and integer values

    Code:
    //*************************************************************************
    // convert float (0.0 - 0.127) into SysEx 1Byte
    //*************************************************************************
    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 (-1.27 - +1.27) into SysEx 2Byte
    //*************************************************************************
    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;
        
        // h_byte is Sign
        h_byte >>= 7;
        
        // l_byte is value
        if (l_byte < 0) {    
            l_byte = l_byte * (-1);
        }
        
        sysexData[sysexCount++] = h_byte;    // Sign (- = 1 / + = 0)
        sysexChecksum += h_byte;
        sysexData[sysexCount++] = l_byte;    // value
        sysexChecksum += l_byte;
    }
    
    //*************************************************************************
    // convert 32bit float 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];
        }
    }
    
    //*************************************************************************
    // convert uint7bit (0-127) into SysEx 1Byte
    //*************************************************************************
    FLASHMEM void uint7_to_sysex1Byte (String value, uint16_t &sysexCount, byte *sysexData)
    {
        uint8_t val =  value.toInt();
        sysexData[sysexCount++] = val;
        sysexChecksum += val;
        
    }
    
    //*************************************************************************
    // convert uint14bit (0-16383) into SysEx 2Byte
    //*************************************************************************
    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;    
    }
    Last edited by Rolfdegen; 05-10-2022 at 05:56 PM.

  9. #234
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    SysEx Dump works now. See short video.

    It was a bit more complicated than I thought. First, conversion routines had to be developed for all 212 parameter values in the Jeannie, which convert 8/16-bit integer values and 32-bit floating-point values into a 7-bit format for the SysEx dump. The same had to be converted back again.
    This was followed by functions for the transmission and reception of SysEx data. Last but not least, a simple menu for operation had to be developed.



    The transmission path is selected with Destination (Midi or USB)
    DUMP type is either a patch or a bank.
    DUMP-Bank sets the bank (A-P) for transmission or reception.
    Source is either the patch no. or when receiving the space in the selected patch bank.
    SYSEX-DUMP is set to send or receive SysEX data.
    The "Load/Save" button starts transmission or reception.
    A progress bar shows the progress of the transfer.



    Video: https://youtu.be/xRoLsR9HgU0

    Greetings Rolf

  10. #235
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    Test of the pickup function



    Youtube: https://youtu.be/iXR4-jLjfkk

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •