Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 2 FirstFirst 1 2
Results 26 to 44 of 44

Thread: usbMIDI transmission error

  1. #26
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    Quote Originally Posted by localhero View Post
    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)

    I do not understand what you mean

    1.Block
    F0 ....data... F7

    2.Block
    F0 ...data... F7

    3.Block
    F0 ...data... F7

    and more..

  2. #27
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    311
    Can you explain to me exactly which line of code you mean?
    The fourth line in the screenshot of MIOS Studio in post#1 shows f0 only.

    Sketch in post#23 ran on bare T4.1 usbType MIDI, Win10, IDE 1.8.19 TD 1.56, produced this:-

    Click image for larger version. 

Name:	TruncatedSysex.jpg 
Views:	9 
Size:	193.7 KB 
ID:	28453

    Note the second block, finishes with F0 and has 115 bytes, should be 130.

    If you run the sketch as it is, monitoring, received blocks scroll upwards and when a faulty block is received is easy to spot. Good idea to have Actions open with cursor on Stop Display ready to click. Makes it easier to find the dodgy block.

    Just play with it, change chunkSize and delayAmt. Occurrence of truncated blocks seems pretty random, does seem to happen more frequently with larger blocks.

  3. #28
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    Did you change the usb.c in your Arduino Library as I suggested ?

    After that it is important that your project has to be completely recompiled (restart Arduino IDE).


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

    Change green text in line number 364

    Last edited by Rolfdegen; 05-23-2022 at 12:02 PM.

  4. #29
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    This is my code to send SysEx to usbMIDI()

    In the SysEx dump menu from my synthesizer I query a key and set the sendSyssExflag.
    If the flag was true then send sysex dump. I always send a block of 348 bytes.
    Then I increment count for the number of sysex blocks and send the next block.
    After each block I call a usb_midi_flush_output().

    Click image for larger version. 

Name:	20220523_135020.jpg 
Views:	12 
Size:	293.7 KB 
ID:	28455Click image for larger version. 

Name:	20220523_135048.jpg 
Views:	12 
Size:	305.1 KB 
ID:	28456


    Code:
    //*************************************************************************
    // Update SysEx Status
    //*************************************************************************
    FLASHMEM void updateSysExStatus(void)
    {
        // send SysEx ---------------------------------------------------------
        if (sendSysExFlag == true){
    
    
            static uint8_t count = 0;
            uint8_t filenumbers = 0;
            uint8_t patchno = 0;
            
            if (sysexDest == false && sysexTyp == false) {        // Patch via USB
                filenumbers = 1;                                // Filenumbers = 1
                progressBarPercent = 300;                        // Progressbar fast
                patchno = sysexSource;                            // set Patch No from menu
                timer_ProgressbarFlag = true;                    // start Progressbar
            } 
            else if (sysexDest == false && sysexTyp == true){    // Bank via USB
                filenumbers = 128;                                // Filenumbers = 128
                progressBarPercent = 110;                        // Progressbar slow
                patchno = 0;                                    // start Patch No                    
                timer_ProgressbarFlag = true;                    // start Progressbar
            }
            else if (sysexDest == true && sysexTyp == false) {    // Patch via Midi
                filenumbers = 1;                                // Filenumbers = 1
                progressBarPercent = 300;                        // Progressbar fast
                patchno = sysexSource;                            // set Patch No from menu
                timer_ProgressbarFlag = true;                    // start Progressbar
            }
            else if (sysexDest == true && sysexTyp == true){    // Bank via Midi
                filenumbers = 128;                                // Filenumbers = 128
                progressBarPercent = 7;                            // Progressbar slow
                patchno = 0;                                    // start Patch No
                timer_ProgressbarFlag = true;                    // start Progressbar
            }
            
            
            progressBarFlag = true;                                // start ProgressBar
            uint8_t sysexpatch = patchno + count;
            mySendSysEx(sysexpatch, sysexBank);
            count++;
            
            sysexDataLenght += 348;
                    
            //progressBarPercent = count;
            if (count >= filenumbers) {
                sendSysExFlag = false;
                count = 0;
            }
        }
        
        
        // wait Time to SysEx Receive Data (10sec)
        if (sysexRecTimeStatus == true && time_sysexRecStatus == false) {
            timer_sysexRec = millis();
            time_sysexRecStatus = true;
            if (PageNr == 11 && myPageShiftStatus[11] == true) {
                tft.fillRoundRect(123,20+(19*4),31,10,2,ST7735_RED);
                tft.setTextColor(ST7735_WHITE);
                print_String(198,130,97); // print "REC"
            }
        }
        
        // wait Time end
        else if (sysexRecTimeStatus == true && time_sysexRecStatus == true) {
            if ((millis() - timer_sysexRec) >= 15000){
                sysexRecTimeStatus = false;
                time_sysexRecStatus = false;
                if (PageNr == 11 && myPageShiftStatus[11] == true) {
                    tft.fillRoundRect(123,20+(19*4),31,10,2,ST7735_BLACK);
                    tft.fillRoundRect(123,19+(19*4),31,10,2,ST7735_BLUE);
                    tft.setTextColor(ST7735_WHITE);
                    print_String(198,130,97); // print "REC"
                }
            }
        }
    }
    
    
    //*************************************************************************
    // send Midi system exclusive dump
    //*************************************************************************
    FLASHMEM void mySendSysEx(uint8_t PatchNo, uint8_t BankNo)
    {
        byte sysexData[350];                                        // SysEx buffer 349 Byte
        uint8_t data_len = NO_OF_PARAMS;
        uint16_t sysexCount = 0;
        String numString = String(PatchNo + 1);
        String bankString = char(BankNo + 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();
        
        // convert Patch data into 7bit SysEx format
                                                                       // Ind. len   value
        sysexData[sysexCount++] = 0xF0;                                // -    1    0    - Start SysEx
        sysexData[sysexCount++] = 0x00;                                // -    1    1    - ID
        sysexData[sysexCount++] = 0x00;                                // -    1    2    - ID
        sysexData[sysexCount++] = 0x00;                                // -    1    3    - ID
        sysexData[sysexCount++] = 0x00;                                // -    1    4    - Device ID 0-64
        sysexData[sysexCount++] = PatchNo;                            // -    1    5    - Patch No
        sysexData[sysexCount++] = BankNo;                            // -    1    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)
                                                                    // (7)             - (not available)
        float_to_string(data[8], 4, sysexCount, sysexData);            // (8)    4    30    - midiClkTimeInterval
                                                                    // (9)            - (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)
                                                                    // (16)            - (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)
                                                                    // (19)            - (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)
                                                                    // (30)         - (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)
                                                                    // (33)         - (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)
                                                                    // (44)         - (not available)
                                                                    // (45)         - (not available)
                                                                    // (46)         - (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    122  - pitchEnvB (-1.00 - +1.00)
        float_to_sysex2Bytes(data[60], sysexCount, sysexData);        // (60) 2    127  - driveLevel (Osc level) (0.00 - 1.25)
        float_to_sysex5Bytes(data[61], sysexCount, sysexData);        // (61) 5    129  - myFilVelocity (0 - 1.00)
        float_to_sysex5Bytes(data[62], sysexCount, sysexData);        // (62) 5    134  - myAmpVelocity (0 - 1.00)
        uint8_to_sysex1Byte(data[63], sysexCount, sysexData);        // (63) 1    139  - myUnisono (0-2)
                                                                    // (64)             - (not available)
                                                                    // (65)             - (not available)
        uint8_to_sysex1Byte(data[66], sysexCount, sysexData);        // (66) 1    140  - WShaperNo (0-14)
        float_to_sysex5Bytes(data[67], sysexCount, sysexData);        // (67) 5    141  - WShaperDrive (0.10 - 5.00)
        uint14_to_sysex2Bytes(data[68], sysexCount, sysexData);        // (68) 2    146  - LFO1phase (0 - 180.0)
        uint14_to_sysex2Bytes(data[69], sysexCount, sysexData);        // (69) 2    148  - LFO2phase (0 - 180.0)
        for (uint8_t i = 0; i < 16; i++) {
            uint8_to_sysex1Byte(data[70+i], sysexCount, sysexData);    // (70-85)  16    150 - SeqNote1Buf (0 - 127)
        }
        for (uint8_t i = 0; i < 16; i++) {
            uint8_to_sysex1Byte(data[86+i], sysexCount, sysexData);    // (86-101) 16    166 - SeqNoteBufStatus (0 - 1)
        }
        uint14_to_sysex2Bytes(data[102], sysexCount, sysexData);    // (102) 2     182  - SEQbpmValue (101 - 462)
        float_to_sysex5Bytes(data[103], sysexCount, sysexData);        // (103) 5    184  - SEQdivValue (float)
        uint8_to_sysex1Byte(data[104], sysexCount, sysexData);        // (104) 1    189  - SEQstepNumbers (0 - 15)
        float_to_sysex5Bytes(data[105], sysexCount, sysexData);        // (105) 5    190  - SEQGateTime (float)
        uint8_to_sysex1Byte(data[106], sysexCount, sysexData);        // (106) 1    195  - SEQdirection (0 - 3)
        uint8_to_sysex1Byte(data[107], sysexCount, sysexData);        // (107) 1    196  - oscDetuneSync (0 - 1)
        int8_to_sysex2Bytes(data[108], sysexCount, sysexData);        // (108) 2    197  - oscPitchA (-12 - +12)
        float_to_sysex5Bytes(data[109], sysexCount, sysexData);        // (109) 5    199  - oscMasterTune (float)
        float_to_sysex5Bytes(data[110], sysexCount, sysexData);        // (110) 5    204  - OscVCFMOD (float)
        for (uint8_t i = 0; i < 16; i++) {
            uint8_to_sysex1Byte(data[111+i], sysexCount, sysexData);    // (111-126) 16     209 - SeqVeloBuf (0 - 127)
        }
        for (uint8_t i = 0; i < 48; i++) {
            uint8_to_sysex1Byte(data[127+i], sysexCount, sysexData);    // (127-174) 48     225 - SeqNote1Buf (0 - 127)
        }
        
        for (uint8_t i = 0; i < 16; i++) {
            uint8_to_sysex1Byte(data[175+i], sysexCount, sysexData);    // (175-190) 16     273 - SeqNoteCount (0 - 3)
        }
        uint8_to_sysex1Byte(data[191], sysexCount, sysexData);        // (191) 1    289 - SEQmode (0 - 2)
        uint8_to_sysex1Byte(data[192], sysexCount, sysexData);        // (192) 1    290 - SEQMidiClkSwitch (0 - 1)
        uint8_to_sysex1Byte(data[193], sysexCount, sysexData);        // (193) 1    291 - LadderFilterpassbandgain (0 - 127)
        uint8_to_sysex1Byte(data[194], sysexCount, sysexData);        // (194) 1    292 - LadderFilterDrive (1 - 127)
        int8_to_sysex2Bytes(data[195], sysexCount, sysexData);        // (195) 2    293 - envelopeType1 (-8 - +8)
        int8_to_sysex2Bytes(data[196], sysexCount, sysexData);        // (196) 2    295 - envelopeType2 (-8 - +8)
        float_to_sysex5Bytes(data[197], sysexCount, sysexData);        // (197) 5    297 - PitchWheelAmt (float)
        float_to_sysex5Bytes(data[198], sysexCount, sysexData);        // (198) 5    302 - MODWheelAmt (float)
        uint8_to_sysex1Byte(data[199], sysexCount, sysexData);        // (199) 1    307 - myFilter (1 - 2)
        float_to_sysex5Bytes(data[200], sysexCount, sysexData);        // (200) 5    308 - pwmRateA (-10.00 - + 10.00)
        float_to_sysex5Bytes(data[201], sysexCount, sysexData);        // (201) 5    313 - pwmRateB (-10.00 - + 10.00)
        uint14_to_sysex2Bytes(data[202], sysexCount, sysexData);    // (202) 2    318 - LFO1fadeTime (0 - 12000) Fade in
        uint14_to_sysex2Bytes(data[203], sysexCount, sysexData);    // (203) 2    320 - LFO1releaseTime (0 - 12000) Fade out
        float_to_sysex5Bytes(data[204], sysexCount, sysexData);        // (204) 5    322 - filterFM (0.00000 - 1.00000)  Osc1
        float_to_sysex5Bytes(data[205], sysexCount, sysexData);        // (205) 5    327 - filterFM2 (0.00000 - 1.00000)    Osc2
        uint14_to_sysex2Bytes(data[206], sysexCount, sysexData);    // (206) 2    332 - LFO2fadeTime (0 - 12000) Fade in
        uint14_to_sysex2Bytes(data[207], sysexCount, sysexData);    // (207) 2    334 - LFO2releaseTime (0 - 12000) Fade out
        float_to_sysex5Bytes(data[208], sysexCount, sysexData);        // (208) 5    336 - Osc1ModAmt (0.00000 - 1.00000) Fx Mod
        int8_to_sysex2Bytes(data[209], sysexCount, sysexData);        // (209) 2    341 - LFO1enCurve (-8 - +8)
        int8_to_sysex2Bytes(data[210], sysexCount, sysexData);        // (210) 2    343 - LFO2enCurve (-8 - +8)
        uint8_to_sysex1Byte(data[211], sysexCount, sysexData);        // (211) 1    345 - LFO1mode (0 - 1)
        uint8_to_sysex1Byte(data[212], sysexCount, sysexData);        // (212) 1    346 - LFO2mode (0 - 1)
        sysexData[sysexCount++] = 0xF7;                                //         1    347 - End SysEx (0xF7)
        
        // Send SysEx Dump
        if (sysexDest == false) {
            usbMIDI.sendSysEx(sysexCount, sysexData, true);            // send SysEx Dump via USB (default)
            } else {
            MIDI.sendSysEx(sysexCount, sysexData, true);            // send SysEx Dump via Midi
        }
        usb_midi_flush_output();
    }
    Last edited by Rolfdegen; 05-23-2022 at 12:30 PM.

  5. #30
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    I wrote a small Arduino sketch and tested it on a Teensy 4.1 board.
    Transmission errors occur with unchanged usb.c file. With the change to usb.c file, there is no transmission error.
    The waiting time after transmission of a data block is very short.

    Press Button on Teensy Pin A3 (low activ) send 128 SysEx data blocks.
    Code:
    //*****************************************************************
    // Send SysEx data to usbMidi
    //*****************************************************************
    #include <usb_midi.h>
    #include <Bounce2.h>
    
    
    #define chunkSize 130
    #define Blocknumbers 128
    #define delayAmt 1
    #define buttonPin PIN_A3
    
    
    const int ledPin = 13;
    Bounce  myButton  = Bounce();
    boolean startFlag = false;
    byte data[chunkSize];
    
    
    //****************************************************************
    // fill buffer
    //****************************************************************
    void fillBuff() {
      unsigned scratch;
    
    
      // set Start and End Byte for SysEx 
      data[0] = 0xF0;
      data[129] = 0xF7;
    
    
      // fill with data
      for (uint16_t ct = 1; ct < (chunkSize-1); ct++) {
        scratch = (ct & 0b01111111);
        data[ct] = scratch;
      }
    }
    
    
    //***************************************************************
    // transmit SysEx data
    //***************************************************************
    void sendSysExData () {
       usbMIDI.sendSysEx(chunkSize, data, true);
       digitalWrite(ledPin, HIGH);
    }
    
    
    //***************************************************************
    // init setup
    //***************************************************************
    void setup() {
      usbMIDI.begin();
      pinMode(ledPin, OUTPUT);
      pinMode(buttonPin, INPUT_PULLUP);
      myButton.attach(buttonPin);
      myButton.interval(5); // 5ms for Keys debouncing
      fillBuff();
    }
    
    
    
    
    //**************************************************************
    // loop
    //**************************************************************
    void loop() {
    
    
      // press Key for transmit SysEx data
      myButton.update();
      if (myButton.fallingEdge()) {
        startFlag = true;
      }
    
    
      // send 128 Blocks with 130 Byte
      if (startFlag == true){
        for (uint8_t i = 0; i < Blocknumbers; i++) {
          sendSysExData();
          delay(delayAmt);
        }
        startFlag = false;
         digitalWrite(ledPin, LOW);
      } 
    }

  6. #31
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    Quote Originally Posted by MatrixRat View Post
    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.

    I missing 0xF0 (SysEx start) and 0xF7 (SysEx end) in your fillBuff() function

  7. #32
    Junior Member
    Join Date
    Jan 2016
    Posts
    19
    Quote Originally Posted by Rolfdegen View Post
    I do not understand what you mean

    1.Block
    F0 ....data... F7

    2.Block
    F0 ...data... F7

    3.Block
    F0 ...data... F7

    and more..
    Hi Rolf,
    It's a dump of a DX7 bank with 32 patches inside. So the file actually already has only one F0, then 4102 bytes, then one F7 at the end.
    In MIDIOX, I see that the usbmidi lib truncates this 4104 buffer in 266 bytes blocks.
    My understanding is until F7 is not encountered, it is considered as "sysex continue" message, like this :
    Click image for larger version. 

Name:	image_2022-05-23_192146406.png 
Views:	10 
Size:	420.2 KB 
ID:	28457

    So here you see the first block "System exclusive" detected from the F0. Then "Sysex continue" blocks.
    And there are 2 "continue" blocks missing, and the last one too (the one I would like to see the F7).

  8. #33
    Junior Member
    Join Date
    Jan 2016
    Posts
    19
    Quote Originally Posted by Rolfdegen View Post
    I missing 0xF0 (SysEx start) and 0xF7 (SysEx end) in your fillBuff() function
    If I understand the third parameter for sendSysEx, if it's false it will add the missing start/stop bytes to the message.

  9. #34
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    Yes. Your SysEx data block is too large. With MIDI-OX a maximum of only 2048 bytes per SysEx block can be received.
    Such a large block of data is not normal. All synthesizers I know send a block of less than 500 bytes for each patch.
    My DIY synthesizer does this too. The Yamaha technicians programmed badly
    Last edited by Rolfdegen; 05-23-2022 at 06:54 PM.

  10. #35
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    I posted your DX7 problem in Sequencer Forum. Look at here: https://www.sequencer.de/synthesizer...i-dump.102499/

    Greetings Rolf

  11. #36
    Junior Member
    Join Date
    Jan 2016
    Posts
    19
    Quote Originally Posted by Rolfdegen View Post
    Yes. Your SysEx data block is too large. With MIDI-OX a maximum of only 2048 bytes per SysEx block can be received.
    Such a large block of data is not normal. All synthesizers I know send a block of less than 500 bytes for each patch.
    My DIY synthesizer does this too. The Yamaha technicians programmed badly
    I wanted to be sure, so I've checked the official Yamaha documentation. See page 37 here :
    http://synthmanuals.com/manuals/yama...nual/tx7e1.pdf
    Click image for larger version. 

Name:	image_2022-05-23_211403044.png 
Views:	6 
Size:	18.2 KB 
ID:	28463

  12. #37
    Junior Member
    Join Date
    Jan 2016
    Posts
    19
    I don't see any problem with long sysex messages. Like the MIDI Sample Dump Standard you can send samples.

    I've found this :
    I think your real problem is the 'generic USB to Midi cable' at it uses Microsoft class driver that doesn't work for long sysex.

    This is particularly a problem for older synths as their sysex messages were longer than 256 bytes (which is correct under the Midi spec. MS decided they knew better).


    I really think it's a USB problem, as I have also difficulties to get the whole bank with MIDIOS or Bome SendSX

  13. #38
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    311
    Commented out line 364 C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4\us b.c as you suggest and no longer have truncated sysex. Thank you for finding it Rolf.

    Is not necessary to include Sysex status bytes (F0 and F7) in
    Code:
    byte data[chunkSize];
    when using
    Code:
    usbMIDI.sendSysEx(chunkSize, data, false, 0);
    @localhero, in your screenshot post# 32. I *think* that "Sysex Continue" is Midiox's way of telling us that its buffer is full so you need to increase it's buffer size.

    In Midiox>Options>Configure Buffers, set Size 2048 and Number 127.

  14. #39
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    311
    Following on, 2048 bytes Sysex block size does seem to be the limit but I suspect this limit is imposed by the MS generic usbMidi driver.

    Perhaps borrow from Midiox the concept of Sysex Continue and say you want to send 4096 bytes, split it into two blocks of 2048 with F0 at the start and NO F7 at the end of the first block and NO F0 at the start but with F7 at the end for the second block if you get the drift..

  15. #40
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    300
    Annotation:


    The normal processor clock of the Teensy4.1 CPU is 600MHz. I reduced the clock setting for the processor in Arduino to 24Mhz. Transmission errors no longer occur.


    The transfer rate on the USB interface is probably so low that the input buffer of the MIDI-OX has enough time to process the received data.


    Greetings Rolf

  16. #41
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    311
    24Mhz. Ouch! We gotta figure how to sidestep that. Neither Jeannie or my project will like it.
    Busy with home renovations, rain is coming, have a couple of ideas.

    Thinking of post 39, let's say we have a block of 512 bytes of sysex to send. How about splitting it into two blocks and we send the first with F0 at the start, then pause a little, then send the last block with the F7 at the end. Then see what MidiOx has to say.

    Second idea. I have an Iconnectivity MIO-10 interface which has a usbHost port. T4x works here. Windows can see the MIO-10 using it's generic class compliant driver. Better is to use the correct driver for access to the full capabilities of the device. When it rains, will plug that experimental T4.1 sysex code into it's usbHost then see what Midiox has to say.

  17. #42
    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

  18. #43
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    311
    Glad you got it working.

    Following up, quoting myself
    How about splitting it into two blocks and we send the first with F0 at the start, then pause a little, then send the last block with the F7 at the end. Then see what MidiOx has to say.
    Got this idea to work. mentioning as the strategy may be worth looking at to slow large amounts of sysex for older synths.

  19. #44
    Junior Member
    Join Date
    Jan 2016
    Posts
    19
    Quote Originally Posted by MatrixRat View Post
    Glad you got it working.

    Following up, quoting myself

    Got this idea to work. mentioning as the strategy may be worth looking at to slow large amounts of sysex for older synths.
    Ok guys, I have good news.
    After a lot of trials, and errors in MIDIOX, I have finally managed to get it to work
    I had previously tried to split the message but it iddn't work because it was sent too quickly.

    So this is the code that works with the Teensy 4.1 kept at 600Mz and send the 4104 bytes in one F0 ... F7 message :
    usbMIDI.sendSysEx(2048, bank_data, true);
    delay(50);
    usbMIDI.sendSysEx(2048, bank_data+2048, true);
    delay(50);
    usbMIDI.sendSysEx(8, bank_data+4096, true);


    Houra, now I see the missing blocks, especially the "Sysex end" !!!
    Click image for larger version. 

Name:	image_2022-05-25_075130012.png 
Views:	8 
Size:	309.5 KB 
ID:	28476

    It's amazing I have spent so much time to get it. I had no need to change the usb.c (I prefer to keep the original files until Paul finds and fixes that in the Teensy code).
    Thanks for your help !

Posting Permissions

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