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

Thread: Sending 32kb SYSEX data via usbMIDI

  1. #26
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    342
    Interestingly, weeding out the 100Ms case, 65Ms worked on one JV but not the older other (have two). Presumably newer firmware has more efficient handlers.

    Just dive in and analyze what the synth sends.

  2. #27
    what do you mean by "weeding out the 100Ms case, 65Ms"?

    as i said, i dont listen i dont care what the M1 might want to tell me
    at least for now.

    diving in is what i do

    after the preset loading works i gonna clean up the errors
    hidden in some parameters. then add the control for the effects.
    at last switching between PROG & EDIT PROG mode.
    maybe also add the WRITE TO MEM function....

  3. #28
    a now i got it i took a left turn into eletronics land an thought you changed some resistors
    Timing issues

  4. #29
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    342
    Sounds like good news.
    The 8K or so of Roland sysex arrives in 70 or so blocks ranging in size from 16 to 140 bytes. Two named Patch Common and Perform Common contain data pertaining to setting up one of 38 EFX types. Both need enough time to instantiate before following blocks are received.
    65Ms here worked for one synth. My code is unlikely to yield exactly 65Ms each time, can prob do better with silicon and solder.

  5. #30
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    1,135
    Quote Originally Posted by M1Addict View Post
    what do you mean by "weeding out the 100Ms case, 65Ms"?

    as i said, i dont listen i dont care what the M1 might want to tell me
    at least for now.

    diving in is what i do

    after the preset loading works i gonna clean up the errors
    hidden in some parameters. then add the control for the effects.
    at last switching between PROG & EDIT PROG mode.
    maybe also add the WRITE TO MEM function....
    Why are you talking in units of Mega seconds?
    Last edited by BriComp; 02-05-2023 at 10:59 AM.

  6. #31
    Hehe That was my thinking too. And since writings of resistor values
    often skip the Ohm i thought MatrixRat has fixed some timing issues by
    changing some resistors from 100Mega Ohm to 65Mega Ohm

    some intersting facts by google calc:
    one 1Ms (Mega second) equals 11,5740741 days

  7. #32
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    342
    Thanks guys for calling out a good old-fashioned PEBKAC error. Actually meant milliseconds.

  8. #33
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    1,135
    Quote Originally Posted by MatrixRat View Post
    Thanks guys for calling out a good old-fashioned PEBKAC error. Actually meant milliseconds.
    Your welcome, in this instance I think we knew what you meant, but in other cases it can be life threatening.

  9. #34

    Sysex file transfer works!

    NEWSFLASH

    Sysex file transfer works!

    Code:
    /*  [translatM1] one tool to rule theM 1. - | copy left | M1Addict 2023
     *   
     *  a KORG M1 [CC] -> [SYSEX] Translator + Midi repeater  
     *  
       Midi CH |  function
    
         1       single osclillator           untestet
         2       double osclillator part 1    untestet
         3       double osclillator part 2    untestet
         4       effects single osclillator   TODO
         5       effects double osclillator   TODO
         
         6       translatM1 Settings
              CC6 | value: 1  (default)
                   - disable duplicate value supression enable FULL_CHAOS_MODE
                     On MPC Live using the automation leads to redundant
                     CC Message sending.
     
                    value: 127
                   - Setting this enables nice drone sounds
                     by spamming the Korg M1.
         
         7       preset control channel
            CC1 | value: 100
                  - send preset array    tested, only a single preset array for now.
     
       Avoid MPC live automation repeating midi cc messages from spamming the M1.
      
    
                          !!! ATTENTIONE !!!
       Using this tool may completly reset the M1 preset memory!!!
       by using this work_in_progress "tool". basically what you get when
       the battery dies. only one piano preset left :)
    
       So do have a SYSEX_preset file ready and be prepared for reloading the preset!
       
       This can of course be done with this tool.
    
       May lead to hangs, unresponsivnes, or disabling of SYSEX_RECEIVE on the Korg M1.
       
       Enabling SYSEX via SYSEX is kind of a chickidi eggidi problem.
    
       Upon this follows one must manually reenable SYSEX for regaining control over the Korg M1!
       
    */
    
    
    #include "korg-M1_sysex.h" // arrays with sysex data
    #include "valhala_sysex.h" // arrays with presets
    
    static uint8_t SYSEX_START = 0xF0; // start of system exclusive message 
    static uint8_t SYSEX_END = 0xF7;   // end of system exclusive message
    static uint8_t KORG_ID = 0x42;     // Korg
    static uint8_t KORG_CHANNEL = 0x30;
    static uint8_t KORG_MODEL = 0x19;  // Korg M1
    static uint8_t KORG_PARAM_CHANGE = 0x41;
    static uint8_t NEGATIVE_VALUE = 0x7F;
    static uint8_t POSITIVE_VALUE = 0x00;
    uint8_t positive_or_negative = POSITIVE_VALUE;
    uint8_t parameter_page = 0;
    uint8_t parameter_position=0;
    char* parameter_name;
    byte last_cc_message[128];
    bool CHAOS_MODE=0;
    bool UNUSED_CHANNEL=0;              
    bool PRESET_SELECT=0; 
    uint8_t midi_buffer[256];
    
    //sysex presets - get lenghts of the sysexdata and the midi buffer
    static uint16_t SYSEX_PRESET_LENGTH = sizeof(Valhala_B102)/sizeof(Valhala_B102[0]);
    static uint16_t MIDI_BUFFER_LENGTH = sizeof(midi_buffer)/sizeof(midi_buffer[0]);
    uint16_t sysex_preset_offset=0;
    
    
    void setup() {
      usbMIDI.setHandleControlChange(HandleControllMessage); // set handle control messages
      usbMIDI.setHandleProgramChange(HandleProgramChange);
      usbMIDI.setHandleNoteOn(HandleNoteOnMessage);
      usbMIDI.setHandleNoteOff(HandleNoteOffMessage);
      Serial.begin(115200); while (!Serial) {;} // wait for serial
      Serial.println("");
    }
    
    void loop() { usbMIDI.read(); } // read the USB MIDI bus every loop
    
    void HandleControllMessage(byte channel, byte controller, byte value) {
    // check for CHAOS_MODE Setting
    if (channel == 6 && controller == 66){
      switch (value) {
        case 127:
               CHAOS_MODE  = 1;
               Serial.println("CHAOS MODE ACTIVATED !!!!");
        break;
        default:
               CHAOS_MODE  = 0;
               Serial.println("CHAOS MODE OFF");
    }
    }
    
     
    // filter out cc 120 - 127 and forward it
    if (controller >= 120 || controller == 64){
      usbMIDI.sendControlChange(0x01, controller, value);
      }
    else if (last_cc_message[controller] == value && !CHAOS_MODE){
        Serial.print(channel); Serial.print(" ");
        Serial.print(controller); Serial.print(" ");
        Serial.print(value); Serial.print("  ");
        Serial.println("DUPLICATE MESSAGE");
    }
    else if (channel == 7 && controller == 1){
      switch (value) {
        case 100:
                Serial.println("Uploading SYSEX PRESETS - STARTs in");
                Serial.println("5");
                delay(1000);
                Serial.println("4");
                delay(1000);
                Serial.println("3");
                delay(1000);
                Serial.println("2");
                delay(1000);
                Serial.println("1");
                delay(1000);
                //fill up the midi buffer array for batch working usbMIDI.sendSysEx 
                while ( sysex_preset_offset < SYSEX_PRESET_LENGTH)
                {
                memcpy(midi_buffer, Valhala_B102 + sysex_preset_offset, MIDI_BUFFER_LENGTH);
                sysex_preset_offset = sysex_preset_offset + MIDI_BUFFER_LENGTH;
              
                if ( (sysex_preset_offset - SYSEX_PRESET_LENGTH) > 0)
                { 
                  int padding_bytes = sysex_preset_offset - SYSEX_PRESET_LENGTH;
                  int padding_offset = MIDI_BUFFER_LENGTH - padding_bytes;
                  while (padding_offset < MIDI_BUFFER_LENGTH)
                    {
                    midi_buffer[padding_offset]=0x00;
                    padding_offset = padding_offset + 1;
                    }
                  }
                
                usbMIDI.sendSysEx(MIDI_BUFFER_LENGTH, midi_buffer, 1);
                delay(100);
                }
                sysex_preset_offset = 0;
                Serial.println("Uploading SYSEX PRESETS - DONE");
        break;
        default:
          Serial.println("TURN TO ~100 for Preset transfer.");
    }
    }
    else { 
        last_cc_message[controller] = value;
        Serial.print(channel); Serial.print(" ");
        Serial.print(controller); Serial.print(" ");
        Serial.print(value); Serial.print(" = ");
        controller = (controller - 1); // cc1 == array[0], cc128 == array[127]
    
    switch (channel) {
        case 1: // single osclillator
                parameter_name =  sysex_single_name[controller];
                parameter_page = sysex_single_parameter_page[controller];
                parameter_position = sysex_single_parameter_position[controller];
                //   -/+ controller negativ value
                if (sysex_single_val_start[controller] == NEGATIVE_VALUE && value < 63)   
                {
                  value = map(value, 0, 62, sysex_single_val_end[controller], 0);
                  value = 128 - value;
                  positive_or_negative = NEGATIVE_VALUE;
                }
                // -/+ controller positiv value
                  else if (sysex_single_val_start[controller] == NEGATIVE_VALUE) {  
                  value = map(value, 63, 127, 0, sysex_single_val_end[controller]);
                  positive_or_negative = POSITIVE_VALUE;
                }
                // full range 0-x controller
                  else if (sysex_single_val_start[controller] == POSITIVE_VALUE) {   
                  value =   map(value, 0, 127, 0, sysex_single_val_end[controller]);
                  positive_or_negative = POSITIVE_VALUE;
                }
        break;
        case 3: // double osclillator part 1
                parameter_name =  sysex_double1_name[controller];
                parameter_page = sysex_double1_parameter_page[controller];
                parameter_position = sysex_double1_parameter_position[controller];
                // -/+ controller negativ value
                if (sysex_double1_val_start[controller] == NEGATIVE_VALUE && value < 63)   
                {
                  value = map(value, 0, 62, sysex_double1_val_end[controller], 0);
                  value = 128 - value;
                  positive_or_negative = NEGATIVE_VALUE;
                }
                // -/+ controller positiv value
                  else if (sysex_double1_val_start[controller] == NEGATIVE_VALUE) {  
                  value = map(value, 63, 127, 0, sysex_double1_val_end[controller]);
                  positive_or_negative = POSITIVE_VALUE;
                }
                // full range 0-x controller
                  else if (sysex_double1_val_start[controller] == POSITIVE_VALUE) {   
                  value =   map(value, 0, 127, 0, sysex_double1_val_end[controller]);
                  positive_or_negative = POSITIVE_VALUE;
                }
          break;
          case 4: // double osclillator part 2
                parameter_name =  sysex_double2_name[controller];
                parameter_page = sysex_double2_parameter_page[controller];
                parameter_position = sysex_double2_parameter_position[controller];
                // -/+ controller negativ value
                if (sysex_double2_val_start[controller] == NEGATIVE_VALUE && value < 63)   
                {
                  value = map(value, 0, 62, sysex_double2_val_end[controller], 0);
                  value = 128 - value;
                  positive_or_negative = NEGATIVE_VALUE;
                }
                // -/+ controller positiv value
                  else if (sysex_double2_val_start[controller] == NEGATIVE_VALUE) {  
                  value = map(value, 63, 127, 0, sysex_double2_val_end[controller]);
                  positive_or_negative = POSITIVE_VALUE;
                }
                // full range 0-x controller
                  else if (sysex_double2_val_start[controller] == POSITIVE_VALUE) {   
                  value =   map(value, 0, 127, 0, sysex_double2_val_end[controller]);
                  positive_or_negative = POSITIVE_VALUE;
                }
          break;
          default:
                  UNUSED_CHANNEL=1;
          break;
      }
    
    if (UNUSED_CHANNEL){
        Serial.print("Channel not in use!");
        UNUSED_CHANNEL=0;
    }
    else
    {
    uint8_t sysex[] = {SYSEX_START, \
                        KORG_ID, \
                        KORG_CHANNEL, \
                        KORG_MODEL, \
                        KORG_PARAM_CHANGE,\
                        parameter_page, \
                        parameter_position,\
                        value, \
                        positive_or_negative, \
                        SYSEX_END};
                        
    for (int element : sysex){Serial.print(element < 16 ? "0" : "");Serial.print(element, HEX);Serial.print(" ");}
    Serial.print(" ::: ");
    Serial.println(parameter_name);
    usbMIDI.sendSysEx(10, sysex);
    //delay(1); // 1ms pause to not stress out the receiver, just a random value, lower may work - untested delayMicroseconds(100)
      } 
     }
    }
    
    void HandleProgramChange(byte channel, byte program) { usbMIDI.sendProgramChange(program, 0x01); }
    void HandleNoteOnMessage(byte channel, byte pitch, byte velocity) { usbMIDI.sendNoteOn(pitch, velocity, 0x01); }
    void HandleNoteOffMessage(byte channel, byte pitch, byte velocity) { usbMIDI.sendNoteOff(pitch, velocity, 0x01);}
    Attached Files Attached Files

Posting Permissions

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