Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 3 1 2 3 LastLast
Results 1 to 25 of 51

Thread: usbMIDI transmission error

  1. #1
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313

    usbMIDI transmission error

    Hello teensy friends


    I programmed a midi dump function for my Synthesizer with Teensy 4.1. Transmission errors occur when I send Patch Bank data to the PC via usbMIDI.sendSysEx. The data packet is 128 * 348 bytes in size.

    I have added long waiting times after 348 bytes to avoid transmission errors. But I'm not sure if this is the right way.

    Thanks for help


    Click image for larger version. 

Name:	SysEx dump.jpg 
Views:	27 
Size:	322.4 KB 
ID:	28424



    Code:
    //*************************************************************************
    // usbMidi send SystemExclusive
    //*************************************************************************
    FLASHMEM void mySendSysEx(void)
    {
        screenFlagSysex = true;    // draw ProgressBar
        
        byte sysexData[350];            // SysEx buffer 349 Byte
        
        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;
        uint8_t filenumbers = 0;
        uint8_t delayTime = 120;
        
        // set filenumbers
        if (sysexTyp == 0) {
            filenumbers = 1;
        } else {
            filenumbers = 128;
        }
        
        for (uint8_t i = 0; i < filenumbers; i++) {
            
            if (sysexTyp == 0) {
                numString = String(patchNo);
            } else {
                numString = String(i + 1);
            }
            
            String bankString = char(sysexBank + 65);
            String fileString = (bankString + "/" + numString);
            
            // get Sound File String
            File patchFile = SD.open(fileString.c_str());
            String data[data_len]; //Array of data read in
            recallPatchData(patchFile, data);
            patchFile.close();
            
            // Sysex data                                                  // Ind. len   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[9], 4, sysexCount);        // (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 = String_to_bin(data[44], 4, sysexCount);        // (44)          - fxAmt (not available)
            //sysexCount = String_to_bin(data[45], 4, sysexCount);        // (47)          - Dummy                                                        // (45)            - fxMix (not available)
            //sysexCount = String_to_bin(data[46], 4, sysexCount);        // (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)
            
            
            // wait time (protection for buffer overflow)
            usbMIDI.sendSysEx(sysexCount, sysexData, true);
            sysexCount = 0;
            delay(delayTime);
            
            
            float_to_sysex5Bytes(data[62], sysexCount, sysexData);        // (62) 2    125  - myAmpVelocity (0 - 1.00)
            uint8_to_sysex1Byte(data[63], sysexCount, sysexData);        // (63) 1    127  - myUnisono (0-2)
            //sysexCount = String_to_bin(data[46], 4, sysexCount);        // (64)             - (not available)
            //sysexCount = String_to_bin(data[46], 4, sysexCount);        // (65)             - (not available)
            uint8_to_sysex1Byte(data[66], sysexCount, sysexData);        // (66) 1    128  - WShaperNo (0-14)
            float_to_sysex5Bytes(data[67], sysexCount, sysexData);        // (67) 5    129  - WShaperDrive (0.10 - 5.00)
            uint14_to_sysex2Bytes(data[68], sysexCount, sysexData);        // (68) 2    134  - LFO1phase (0 - 180.0)
            uint14_to_sysex2Bytes(data[69], sysexCount, sysexData);        // (69) 2    139  - LFO2phase (0 - 180.0)
            for (uint8_t i = 0; i < 16; i++) {
                uint8_to_sysex1Byte(data[70+i], sysexCount, sysexData);    // (70-85)  16    144 - SeqNote1Buf (0 - 127)
            }
            for (uint8_t i = 0; i < 16; i++) {
                uint8_to_sysex1Byte(data[86+i], sysexCount, sysexData);    // (86-101) 16    160 - SeqNoteBufStatus (0 - 1)
            }
            uint14_to_sysex2Bytes(data[102], sysexCount, sysexData);    // (102) 2     176  - SEQbpmValue (101 - 462)
            float_to_sysex5Bytes(data[103], sysexCount, sysexData);        // (103) 5    178  - SEQdivValue (float)
            uint8_to_sysex1Byte(data[104], sysexCount, sysexData);        // (104) 1    183  - SEQstepNumbers (0 - 15)
            float_to_sysex5Bytes(data[105], sysexCount, sysexData);        // (105) 5    184  - SEQGateTime (float)
            uint8_to_sysex1Byte(data[106], sysexCount, sysexData);        // (106) 1    189  - SEQdirection (0 - 3)
            uint8_to_sysex1Byte(data[107], sysexCount, sysexData);        // (107) 1    190  - oscDetuneSync (0 - 1)
            int8_to_sysex2Bytes(data[108], sysexCount, sysexData);        // (108) 2    191  - oscPitchA (-12 - +12)
            float_to_sysex5Bytes(data[109], sysexCount, sysexData);        // (109) 5    193  - oscMasterTune (float)
            float_to_sysex5Bytes(data[110], sysexCount, sysexData);        // (110) 5    198  - OscVCFMOD (float)
            for (uint8_t i = 0; i < 16; i++) {
                uint8_to_sysex1Byte(data[111+i], sysexCount, sysexData);    // (111-126) 16     203 - SeqVeloBuf (0 - 127)
            }        
            for (uint8_t i = 0; i < 48; i++) {
                uint8_to_sysex1Byte(data[127+i], sysexCount, sysexData);    // (127-174) 48     219 - SeqNote1Buf (0 - 127)
            }
                
            for (uint8_t i = 0; i < 16; i++) {
                uint8_to_sysex1Byte(data[175+i], sysexCount, sysexData);    // (175-190) 16     267 - SeqNoteCount (0 - 3)
            }        
            uint8_to_sysex1Byte(data[191], sysexCount, sysexData);        // (191) 1    283 - SEQmode (0 - 2)
            uint8_to_sysex1Byte(data[192], sysexCount, sysexData);        // (192) 1    284 - SEQMidiClkSwitch (0 - 1)
            uint8_to_sysex1Byte(data[193], sysexCount, sysexData);        // (193) 1    285 - LadderFilterpassbandgain (0 - 127)
            uint8_to_sysex1Byte(data[194], sysexCount, sysexData);        // (194) 1    286 - LadderFilterDrive (1 - 127)
            int8_to_sysex2Bytes(data[195], sysexCount, sysexData);        // (195) 2    287 - envelopeType1 (-8 - +8)
            int8_to_sysex2Bytes(data[196], sysexCount, sysexData);        // (196) 2    289 - envelopeType2 (-8 - +8)
            float_to_sysex5Bytes(data[197], sysexCount, sysexData);        // (197) 5    291 - PitchWheelAmt (float)
            float_to_sysex5Bytes(data[198], sysexCount, sysexData);        // (198) 5    296 - MODWheelAmt (float)
            uint8_to_sysex1Byte(data[199], sysexCount, sysexData);        // (199) 1    301 - myFilter (1 - 2)
            float_to_sysex5Bytes(data[200], sysexCount, sysexData);        // (200) 5    302 - pwmRateA (-10.00 - + 10.00)
            float_to_sysex5Bytes(data[201], sysexCount, sysexData);        // (201) 5    307 - pwmRateB (-10.00 - + 10.00)
            uint14_to_sysex2Bytes(data[202], sysexCount, sysexData);    // (202) 2    312 - LFO1fadeTime (0 - 12000) Fade in
            uint14_to_sysex2Bytes(data[203], sysexCount, sysexData);    // (203) 2    314 - LFO1releaseTime (0 - 12000) Fade out
            float_to_sysex5Bytes(data[204], sysexCount, sysexData);        // (204) 5    316 - filterFM (0.00000 - 1.00000)  Osc1
            float_to_sysex5Bytes(data[205], sysexCount, sysexData);        // (205) 5    321 - filterFM2 (0.00000 - 1.00000)    Osc2
            uint14_to_sysex2Bytes(data[206], sysexCount, sysexData);    // (206) 2    326 - LFO2fadeTime (0 - 12000) Fade in
            uint14_to_sysex2Bytes(data[207], sysexCount, sysexData);    // (207) 2    328 - LFO2releaseTime (0 - 12000) Fade out
            float_to_sysex5Bytes(data[208], sysexCount, sysexData);        // (208) 5    330 - Osc1ModAmt (0.00000 - 1.00000) Fx Mod
            int8_to_sysex2Bytes(data[209], sysexCount, sysexData);        // (209) 2    335 - LFO1enCurve (-8 - +8)
            int8_to_sysex2Bytes(data[210], sysexCount, sysexData);        // (210) 2    337 - LFO2enCurve (-8 - +8)
            uint8_to_sysex1Byte(data[211], sysexCount, sysexData);        // (211) 1    339 - LFO1mode (0 - 1)
            uint8_to_sysex1Byte(data[212], sysexCount, sysexData);        // (212) 1    340 - LFO2mode (0 - 1)
            sysexData[sysexCount++] = 0xF7;                                // 1    346 - End SysEx (0xF7)
            
            usbMIDI.sendSysEx(sysexCount, sysexData, true);        // send SysEx data
            
            // wait time (protection for buffer overflow)
            sysexCount = 0;
            delay(delayTime);
        }
    
    
        Serial.println("transfer complete..");
        
    }
    
    
    
    
    
    //*************************************************************************
    // 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];
        }
    }
    Last edited by Rolfdegen; 05-19-2022 at 09:44 AM.

  2. #2
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    342
    Wow, That's huge. Fourth line looks truncated after F0. Seen similar truncations if some data miscalculation tries to send a value >127, not the case here as the four byte header (zeros) was supposed to come next.

    My hunch is buffer overrun.

  3. #3
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    Tranfer only one patch, it no error.

    To protect against Buffer overflow, I made a wait time 120ms after sending each patch.

    Is there a way to query a faulty USB transfer

  4. #4
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    342
    Largest sysex dump here 4 x 140 bytes. Did need delay but used non-blocking type. What about a ring buffer?

  5. #5
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    After transferring a patch (348 bytes) I wait 120ms. From time to time there are transmission errors.

  6. #6
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    342
    If you post a sketch here that dumps that sysex in response to serial monitor keypress am happy to test on Windows with Midiox.

  7. #7
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    I have check with Midi-OX. Its same problem

  8. #8
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    I will check sysex dump function with a little arduino scretch.

  9. #9
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    342
    I would test on Serial midi as well. Rule in or out all possibilities.

  10. #10
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    Sending Patch Banks via Serial Midi works fine without errors, but is very slow

  11. #11
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    Now.. I have implemented USB and Midi SysEx transmission. USB often has transmission errors. Midi works without error

    Code:
    a lot of sysex data..
    
            uint14_to_sysex2Bytes(data[207], sysexCount, sysexData);    // (207) 2    328 - LFO2releaseTime (0 - 12000) Fade out
            float_to_sysex5Bytes(data[208], sysexCount, sysexData);        // (208) 5    330 - Osc1ModAmt (0.00000 - 1.00000) Fx Mod
            int8_to_sysex2Bytes(data[209], sysexCount, sysexData);        // (209) 2    335 - LFO1enCurve (-8 - +8)
            int8_to_sysex2Bytes(data[210], sysexCount, sysexData);        // (210) 2    337 - LFO2enCurve (-8 - +8)
            uint8_to_sysex1Byte(data[211], sysexCount, sysexData);        // (211) 1    339 - LFO1mode (0 - 1)
            uint8_to_sysex1Byte(data[212], sysexCount, sysexData);        // (212) 1    340 - LFO2mode (0 - 1)
            sysexData[sysexCount++] = 0xF7;                                // 1    346 - End SysEx (0xF7)
            
            usbMIDI.sendSysEx(sysexCount, sysexData, true);        // send SysEx data via USB
            
            MIDI.sendSysEx(sysexCount, sysexData, true);        // send SysEx data via Midi
            
        }
    
    
        Serial.println("transfer complete..");

  12. #12
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    I tried it with a USB 3.0 hub and directly on the USB 2.0 port on the PC. The problem remains

  13. #13
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    There is an interesting post here https://forum.pjrc.com/threads/49753...l=1#post168107

    It works usb_midi_flush_output() by commenting out into usb.c file in the Arduino Lib.

    File Path: C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4

    Code:
    {
        code...
           
        if ((USB1_USBINTR & USB_USBINTR_SRE) && (status & USB_USBSTS_SRI)) {
            //printf("sof %d\n", usb_reboot_timer);
            if (usb_reboot_timer) {
                if (--usb_reboot_timer == 0) {
                    usb_stop_sof_interrupts(NUM_INTERFACE);
                    _reboot_Teensyduino_();
                }
            }
            #ifdef MIDI_INTERFACE
            //usb_midi_flush_output();
            #endif
            #ifdef MULTITOUCH_INTERFACE
            usb_touchscreen_update_callback();
            #endif
            #ifdef FLIGHTSIM_INTERFACE
            usb_flightsim_flush_output();
            #endif
        }
    }
    A patch bank is now transferred error-free via USB in less than 2 seconds
    Via Midi it takes about 15 seconds.

  14. #14
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    As I understand it, the usb_midi_flush_output() function is responsible for deleting unread data in the midi buffer.

    Since I am constantly querying the Midi buffer in my Polyphonic DIY Synthesizer with MIDI.read() and usbMIDI.read, there should be no disadvantages if this function is switched off.

    On github I will then point out the changes in the Arduino Library and the changed usb.c File.

    Click image for larger version. 

Name:	20220505_084324.jpg 
Views:	23 
Size:	224.1 KB 
ID:	28428Click image for larger version. 

Name:	20220505_092444.jpg 
Views:	18 
Size:	297.3 KB 
ID:	28429Click image for larger version. 

Name:	20220505_084723.jpg 
Views:	23 
Size:	368.5 KB 
ID:	28430

    But my thoughts are still buzzing, why are there transmission errors via USB Midi?
    Last edited by Rolfdegen; 05-20-2022 at 10:12 AM.

  15. #15
    Member
    Join Date
    Jan 2016
    Location
    Nantes, France
    Posts
    30
    Hi,
    I've got some problem with usbMidi too.
    I try to send a DX7 bank sysex file by usbMidi (file stored on a SD card).

    When I send only a patch it's working perfectly.
    But when I try to send the whole file (4104 bytes, 32 patches in the bank) then I never receive the 4104 bytes.
    On my PC, in Bome SendSx I see that :
    Received 1024 bytes succesfully.
    Received 3072 bytes of bulk dump (at 341333 bytes/s = 333,33 KB/s)


    I never see the 4104 bytes arriving.
    I simply use :
    usbMIDI.sendSysEx(4104, bank_data, true);

    What am I doing wrong ?
    Regards

  16. #16
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    I think it's a bug in the teensy 4 USB library. Paul should know what doesn't work there.

    I modified the usb.c in the midi library. It works. But it's not a good solution.

    File Path: C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4\usb.c

    Change red text in line number 364

    {
    code...

    if ((USB1_USBINTR & USB_USBINTR_SRE) && (status & USB_USBSTS_SRI)) {
    //printf("sof %d\n", usb_reboot_timer);
    if (usb_reboot_timer) {
    if (--usb_reboot_timer == 0) {
    usb_stop_sof_interrupts(NUM_INTERFACE);
    _reboot_Teensyduino_();
    }
    }
    #ifdef MIDI_INTERFACE
    //usb_midi_flush_output();
    #endif
    #ifdef MULTITOUCH_INTERFACE
    usb_touchscreen_update_callback();
    #endif
    #ifdef FLIGHTSIM_INTERFACE
    usb_flightsim_flush_output();
    #endif
    }
    }
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	Sys 1.jpg 
Views:	15 
Size:	432.4 KB 
ID:	28438  
    Last edited by Rolfdegen; 05-21-2022 at 05:42 PM.

  17. #17
    Member
    Join Date
    Jan 2016
    Location
    Nantes, France
    Posts
    30
    Quote Originally Posted by Rolfdegen View Post
    I think it's a bug in the teensy 4 USB library. Paul should know what doesn't work there.

    I modified the usb.c in the midi library. It works. But it's not a good solution.
    //usb_midi_flush_output();
    }
    Thanks.
    So I've tried it but it doesn't solve the problem for me.
    Now I see that:
    Received 1024 bytes succesfully.
    Received 3235 bytes of bulk dump (at 1078333 bytes/s = 1053,06 KB/s)

  18. #18
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    Which SysEx tool are you using on the PC?

    I use Mios Studio without problems. When I use MIDI-OX I have the same problems.

  19. #19
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    342
    Try in Midiox > Options>Configure Buffers

    Set Size 2048 and Number 32

    Fingers crossed.

  20. #20
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    In MIDI-OX I discovered an error when receiving SysEx Dump. The number of received SysEx data is displayed incorrectly in the preview window of the SysEx Dump function.
    Instead of 44,544 bytes, I see 44,766 bytes. In the large main window, however, the number of bytes is correct.




    However, if the SysEx dump data is saved directly to a file (Sysex Configure > tick "Save Dump directly to file"), no errors occur.
    The number of data received matches the data to be sent.





    But.. The Sysex transmission problem with usbMidi is still there

    Greetings from germany. Rolf
    Last edited by Rolfdegen; 05-22-2022 at 09:10 AM.

  21. #21
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    If you disabled in usb.c the usb midi flush output() you have to after midi data has been sent, a flush() must be sent.

    This function forces the USB layer to send the data immediately. Since the USB bus is not realtime, a usbMIDI() doesn’t guarantee the data to be sent with the correct timing unless immediately followed by a flush().

    Code:
    usbMIDI.sendSysEx(buf_lenght, data, true);
    usb_midi_flush_output();

  22. #22
    Member
    Join Date
    Jan 2016
    Location
    Nantes, France
    Posts
    30
    Thanks Rolf
    I've tried all your suggestions, unfortunately I'm still stuck with no complete bank dump.
    I'm going crazy with such a "simple" thing.

    If my calculations are right (and MIDIOX displays the blocks right) I receive 3584 bytes (14*256 blocks: 1 sysex start block with F0, 13 sysex continue).
    So there are 3 blocks missing to get to 4102 bytes:
    - 2*256 continue
    - 1*8 bytes sysex end (with F7)
    Last edited by localhero; 05-22-2022 at 09:15 PM.

  23. #23
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    342
    Been able to reproduce this with the following sketch:-

    Code:
    #define chunkSize 128
    #define delayAmt 100
    
    byte data[chunkSize];
    
    void fillBuff() {
      unsigned scratch;
      for (uint16_t ct = 0; ct <= chunkSize; ct++) {
        scratch = (ct & 0b01111111);
        data[ct] = scratch;
      }
    }
    
    void setup() {
      delay(1000);
      fillBuff();
    }
    
    void loop() {
      usbMIDI.sendSysEx(chunkSize, data, false, 0);
      delay(delayAmt);
    }
    Monitored with Midiox.


    When the error occurs, a block may be shorter or longer than is supposed to be.

  24. #24
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    I missing usbMidi.read() in your code !

    Code:
    // discard incoming MIDI messages
     while (usbMIDI.read()) {
        // ignore incoming messages
      }
    What Arduino CPU and Windows Version are you using?

    I am using Teensy 4.1 with Midi and USB. Both ports work fine with the change in the usb.c file.

    You check another tool. MIOS Studio its a very good tool and free.

    Link: http://www.ucapps.de/mios_studio.html

    My Polyphonic DIY Synthesizer with Teensy 4.1, Midi IN, Midi Out/Thru and USB port






    Link: https://forum.pjrc.com/threads/63255...Teensy+Shruthi

    Greetings from germany. Rolf
    Last edited by Rolfdegen; 05-23-2022 at 06:45 AM.

  25. #25
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    313
    Quote Originally Posted by MatrixRat View Post
    Wow, That's huge. Fourth line looks truncated after F0. Seen similar truncations if some data miscalculation tries to send a value >127, not the case here as the four byte header (zeros) was supposed to come next.

    My hunch is buffer overrun.
    Can you explain to me exactly which line of code you mean?

Posting Permissions

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