diff --git a/UI.hpp b/UI.hpp index a805f90..9b71111 100644 --- a/UI.hpp +++ b/UI.hpp @@ -67,6 +67,7 @@ extern char receive_bank_filename[FILENAME_LEN]; extern uint8_t seq_data[4][16]; extern uint8_t seq_patternchain[4][4]; extern uint8_t seq_step_timer; +extern uint8_t seq_chain_lenght; extern bool seq_running; extern bool seq_recording; uint8_t seq_active_function = 99; @@ -74,11 +75,11 @@ uint8_t activesample; extern uint8_t seq_active_track; extern elapsedMillis seq_millis_timer; extern uint8_t seq_menu; -extern bool seq_button_r; extern uint8_t seq_chain_select_menu; extern uint8_t seq_chain_active_menu; extern uint8_t seq_chain_active_chainstep; //for editor extern uint8_t seq_chain_active_step; +extern int seq_transpose; #if NUM_DRUMS > 0 #include "drums.h" extern drum_config_t drum_config[DRUM_MAX_INSTRUMENTS + 1]; @@ -135,6 +136,10 @@ const char accepted_chars[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-abcdefghijk uint8_t active_perform_page = 1; uint8_t orig_attack_values[2][7]; uint8_t orig_release_values[2][7]; +int temp_int; +bool menu_select_toggle; +float32_t temp_float; + #ifdef I2C_DISPLAY #include @@ -224,6 +229,7 @@ void UI_func_delay_level(uint8_t param); void UI_func_reverb_send(uint8_t param); void UI_func_filter_cutoff(uint8_t param); void UI_func_filter_resonance(uint8_t param); +void UI_func_drum_reverb_send(uint8_t param); #endif void UI_func_transpose(uint8_t param); void UI_func_tune(uint8_t param); @@ -256,6 +262,8 @@ void UI_func_portamento_time(uint8_t param); void UI_handle_OP(uint8_t param); void UI_func_information(uint8_t param); void UI_func_sequencer(uint8_t param); +void UI_func_seq_live_transpose_oct(uint8_t param); +void UI_func_seq_lenght(uint8_t param); void UI_func_seq_pat_chain(uint8_t param); void UI_func_volume(uint8_t param); void UI_func_load_performance(uint8_t param); @@ -301,6 +309,10 @@ void locate_previous_favorite(); void locate_next_favorite(); void locate_next_non_favorite(); void locate_random_non_favorite(); +void UI_func_drum_main_volume(uint8_t param); +void UI_func_drum_volume(uint8_t param); +void UI_func_drum_pan(uint8_t param); + // normal menu LCDMenuLib2_menu LCDML_0(255, 0, 0, NULL, NULL); // normal root menu element (do not change) @@ -647,7 +659,6 @@ void lcdml_menu_control(void) Serial.println(F("ENC-R short")); #endif encoderDir[ENC_R].ButtonShort(true); - seq_button_r = true; LCDML.BT_enter(); } @@ -3543,12 +3554,272 @@ void UI_handle_OP(uint8_t param) } } +void UI_func_drum_reverb_send(uint8_t param) +{ + char displayname[8] = {0, 0, 0, 0, 0, 0, 0}; + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + lcd.setCursor(0, 0); + lcd.print("Drum Rev. Send"); + } + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if (menu_select_toggle == false) { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) + { + if (LCDML.BT_checkDown()) + { + activesample = constrain(activesample + ENCODER[ENC_R].speed(), 0, num_drums - 2); + } + else if (LCDML.BT_checkUp()) + { + activesample = constrain(activesample - ENCODER[ENC_R].speed(), 0, num_drums - 2); + } + } + } else { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) + { + if (LCDML.BT_checkDown()) + { + temp_int = constrain(temp_int + ENCODER[ENC_R].speed(), 0, REVERB_SEND_MAX); + } + else if (LCDML.BT_checkUp()) + { + temp_int = constrain(temp_int - ENCODER[ENC_R].speed(), 0, REVERB_SEND_MAX); + } + } + } + if (LCDML.BT_checkEnter()) + { + if (menu_select_toggle) { + menu_select_toggle = false; + } else + { menu_select_toggle = true; + temp_int = (int)(drum_config[activesample].reverb_send * 100); + } + } + if (menu_select_toggle == false) { + lcd.setCursor(11, 1); + lcd.print(" "); + lcd.setCursor(15, 1); + lcd.print(" "); + lcd.setCursor(0, 1); + lcd.print("["); + lcd.setCursor(3, 1); + lcd.print("]"); + lcd.setCursor(1, 1); + sprintf(displayname, "%02d", activesample); + lcd.print(displayname); + lcd.setCursor(4, 1); + strncpy(displayname, drum_config[activesample].filename + 5, 7); + lcd.print(displayname); + sprintf(displayname, "%03d", (int)(drum_config[activesample].reverb_send * 100) ); + lcd.setCursor(12, 1); + lcd.print(displayname); + } else { + lcd.setCursor(0, 1); + lcd.print(" "); + lcd.setCursor(3, 1); + lcd.print(" "); + lcd.setCursor(11, 1); + lcd.print("["); + lcd.setCursor(15, 1); + lcd.print("]"); + sprintf(displayname, "%03d", temp_int); + lcd.setCursor(12, 1); + lcd.print(displayname); + drum_config[activesample].reverb_send = mapfloat(temp_int, 0, 100, 0.0, 1.0); + } + } + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + encoderDir[ENC_R].reset(); + } +} + +void UI_func_drum_main_volume(uint8_t param) +{ +; +} + +void UI_func_drum_volume(uint8_t param) +{ + char displayname[8] = {0, 0, 0, 0, 0, 0, 0}; + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + lcd.setCursor(0, 0); + lcd.print("DrumSmp. Volume"); + } + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if (menu_select_toggle == false) { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) + { + if (LCDML.BT_checkDown()) + { + activesample = constrain(activesample + ENCODER[ENC_R].speed(), 0, num_drums - 2); + } + else if (LCDML.BT_checkUp()) + { + activesample = constrain(activesample - ENCODER[ENC_R].speed(), 0, num_drums - 2); + } + } + } else { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) + { + if (LCDML.BT_checkDown()) + { + temp_int = constrain(temp_int + ENCODER[ENC_R].speed(), 0, 100); + } + else if (LCDML.BT_checkUp()) + { + temp_int = constrain(temp_int - ENCODER[ENC_R].speed(), 0, 100); + } + } + } + if (LCDML.BT_checkEnter()) + { + if (menu_select_toggle) { + menu_select_toggle = false; + } else + { menu_select_toggle = true; + temp_int = (int)(drum_config[activesample].vol_max * 100); + } + } + if (menu_select_toggle == false) { + lcd.setCursor(11, 1); + lcd.print(" "); + lcd.setCursor(15, 1); + lcd.print(" "); + lcd.setCursor(0, 1); + lcd.print("["); + lcd.setCursor(3, 1); + lcd.print("]"); + lcd.setCursor(1, 1); + sprintf(displayname, "%02d", activesample); + lcd.print(displayname); + lcd.setCursor(4, 1); + strncpy(displayname, drum_config[activesample].filename + 5, 7); + lcd.print(displayname); + sprintf(displayname, "%03d", (int)(drum_config[activesample].vol_max * 100) ); + lcd.setCursor(12, 1); + lcd.print(displayname); + } else { + temp_float = mapfloat(temp_int, 0, 100, 0.0, 1.0); + lcd.setCursor(0, 1); + lcd.print(" "); + lcd.setCursor(3, 1); + lcd.print(" "); + lcd.setCursor(11, 1); + lcd.print("["); + lcd.setCursor(15, 1); + lcd.print("]"); + sprintf(displayname, "%03d", temp_int); + lcd.setCursor(12, 1); + lcd.print(displayname); + drum_config[activesample].vol_max = temp_float; + } + } + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + encoderDir[ENC_R].reset(); + } +} + +void UI_func_drum_pan(uint8_t param) +{ + char displayname[8] = {0, 0, 0, 0, 0, 0, 0}; + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + lcd.setCursor(0, 0); + lcd.print("DrmSmp. Panorama"); + } + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if (menu_select_toggle == false) { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) + { + if (LCDML.BT_checkDown()) + { + activesample = constrain(activesample + ENCODER[ENC_R].speed(), 0, num_drums - 2); + } + else if (LCDML.BT_checkUp()) + { + activesample = constrain(activesample - ENCODER[ENC_R].speed(), 0, num_drums - 2); + } + } + } else { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) + { + if (LCDML.BT_checkDown()) + { + temp_int = constrain(temp_int + ENCODER[ENC_R].speed(), -99, 99); + } + else if (LCDML.BT_checkUp()) + { + temp_int = constrain(temp_int - ENCODER[ENC_R].speed(), -99, 99); + } + } + } + if (LCDML.BT_checkEnter()) + { + if (menu_select_toggle) { + menu_select_toggle = false; + } else + { menu_select_toggle = true; + // if (drum_config[activesample].pan>0.00) + //temp_int=drum_config[activesample].pan*100; + //else + //temp_int=drum_config[activesample].pan*-100; + + } + } + if (menu_select_toggle == false) { + lcd.setCursor(11, 1); + lcd.print(" "); + lcd.setCursor(15, 1); + lcd.print(" "); + lcd.setCursor(0, 1); + lcd.print("["); + lcd.setCursor(3, 1); + lcd.print("]"); + lcd.setCursor(1, 1); + sprintf(displayname, "%02d", activesample); + lcd.print(displayname); + lcd.setCursor(4, 1); + strncpy(displayname, drum_config[activesample].filename + 5, 7); + lcd.print(displayname); + sprintf(displayname, "%+f", drum_config[activesample].pan); + lcd.setCursor(12, 1); + lcd.print(displayname); + } else { + lcd.setCursor(0, 1); + lcd.print(" "); + lcd.setCursor(3, 1); + lcd.print(" "); + lcd.setCursor(11, 1); + lcd.print("["); + lcd.setCursor(15, 1); + lcd.print("]"); + sprintf(displayname, "%+03d", temp_int); + lcd.setCursor(12, 1); + lcd.print(displayname); + drum_config[activesample].pan = mapfloat(temp_int, -99, 99, -1.0, 1.0); + } + } + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + encoderDir[ENC_R].reset(); + } +} const char* seq_find_shortname(uint8_t sstep) { const char* shortname = " "; bool found = false; - if (seq_active_track < 3) { for (uint8_t d = 0; d < num_drums - 1; d++) { @@ -3560,11 +3831,9 @@ const char* seq_find_shortname(uint8_t sstep) } } if (found == false) shortname = "-"; - } else { if (seq_data[ seq_patternchain[seq_chain_active_step][seq_active_track] ][sstep] > 0) shortname = "*"; else shortname = "-"; - } return shortname; } @@ -3585,6 +3854,84 @@ const char* seq_find_shortname(uint8_t sstep) // } //} +void UI_func_seq_live_transpose_oct(uint8_t param) +{ //Select octave for live transpose of sequencer instrument track. Should be one of the lowest octaves available on the keyboard. + //Allowed range: C1-C5 to not restrict too much, even for very unusual user setups/configurations. + + char note_name[4]; + char note_name2[4]; + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + getNoteName(note_name, seq_transpose); + getNoteName(note_name2, seq_transpose + 12); + lcd.setCursor(0, 0); + lcd.print(F("Live Transp.Oct.")); + lcd.setCursor(0, 1); + lcd.print(F("[")); + lcd.print(note_name); + lcd.print(F("] - ")); + lcd.print(("[")); + lcd.print(note_name2); + lcd.print(("]")); + } + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) + { + if (LCDML.BT_checkDown()) + seq_transpose = constrain(seq_transpose + ENCODER[ENC_R].speed(), 24, 60); + else if (LCDML.BT_checkUp()) + seq_transpose = constrain(seq_transpose - ENCODER[ENC_R].speed(), 24, 60); + } + getNoteName(note_name, seq_transpose); + getNoteName(note_name2, seq_transpose + 12); + lcd.setCursor(0, 1); + lcd.print(F("[")); + lcd.print(note_name); + lcd.print(F("] - ")); + lcd.print(("[")); + lcd.print(note_name2); + lcd.print(("]")); + } + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + encoderDir[ENC_R].reset(); + } +} + +void UI_func_seq_lenght(uint8_t param) +{ + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + lcd.setCursor(0, 0); + lcd.print(" Seq. lenght "); + } + + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) + { + if (LCDML.BT_checkDown()) + seq_chain_lenght = constrain(seq_chain_lenght + ENCODER[ENC_R].speed(), 0, 3); + else if (LCDML.BT_checkUp()) + seq_chain_lenght = constrain(seq_chain_lenght - ENCODER[ENC_R].speed(), 0, 3); + } + + lcd.setCursor(3, 1); + lcd.print((seq_chain_lenght + 1) * 16 ); + lcd.setCursor(7, 1); + lcd.print("Steps"); + + } + + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + encoderDir[ENC_R].reset(); + } +} + void UI_func_sequencer(uint8_t param) { @@ -3593,7 +3940,6 @@ void UI_func_sequencer(uint8_t param) if (LCDML.FUNC_setup()) // ****** SETUP ********* { encoderDir[ENC_R].reset(); - seq_button_r = false; seq_note_in = 0; // setup function lcd.setCursor(1, 0); @@ -3647,9 +3993,8 @@ void UI_func_sequencer(uint8_t param) seq_active_track = constrain(seq_active_track - 1, 0, 8); } } - if (seq_button_r) //handle button presses during menu >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if (LCDML.BT_checkEnter()) //handle button presses during menu >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> { - seq_button_r = false; if ( seq_menu == 0 && seq_active_function == 99) { seq_active_function = 0; @@ -3817,13 +4162,13 @@ void UI_func_seq_pat_chain(uint8_t param) if (LCDML.FUNC_setup()) // ****** SETUP ********* { // setup function - seq_button_r = false; lcd.setCursor( 12, 0); lcd.print(seq_chain_active_chainstep + 1); lcd.setCursor( 13, 0); - lcd.print("/4"); - + lcd.print("/"); + lcd.setCursor( 14, 0); + lcd.print(seq_chain_lenght + 1); lcd.setCursor(0 , 0); lcd.print("D"); lcd.setCursor(2 , 0); @@ -3859,9 +4204,9 @@ void UI_func_seq_pat_chain(uint8_t param) if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up())) { if (LCDML.BT_checkDown()) - seq_chain_active_chainstep = constrain(seq_chain_active_chainstep + 1, 0, 3); + seq_chain_active_chainstep = constrain(seq_chain_active_chainstep + 1, 0, seq_chain_lenght); else if (LCDML.BT_checkUp()) - seq_chain_active_chainstep = constrain(seq_chain_active_chainstep - 1, 0, 3); + seq_chain_active_chainstep = constrain(seq_chain_active_chainstep - 1, 0, seq_chain_lenght); } } else if (seq_chain_active_menu < 4) { @@ -3937,7 +4282,11 @@ void UI_func_seq_pat_chain(uint8_t param) lcd.setCursor( 12, 0); lcd.print(seq_chain_active_chainstep + 1); lcd.setCursor( 13, 0); - lcd.print("/4]"); + lcd.print("/"); + lcd.setCursor( 14, 0); + lcd.print(seq_chain_lenght + 1); + lcd.setCursor( 15, 0); + lcd.print("]"); } else if (seq_chain_select_menu == 4 && seq_chain_active_menu == 4) // Chainselect modify { lcd.setCursor( 11, 0); @@ -3945,7 +4294,11 @@ void UI_func_seq_pat_chain(uint8_t param) lcd.setCursor( 12, 0); lcd.print(seq_chain_active_chainstep + 1); lcd.setCursor( 13, 0); - lcd.print("/4]"); + lcd.print("/"); + lcd.setCursor( 14, 0); + lcd.print(seq_chain_lenght + 1); + lcd.setCursor( 15, 0); + lcd.print("]"); lcd.setCursor(2 , 0); lcd.print( seq_patternchain[seq_chain_active_chainstep][0]); @@ -3976,9 +4329,8 @@ void UI_func_seq_pat_chain(uint8_t param) lcd.print( seq_patternchain[seq_chain_active_chainstep][3]); } - if (seq_button_r) //handle button presses during menu >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if (LCDML.BT_checkEnter()) //handle button presses during menu >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> { - seq_button_r = false; if (seq_chain_active_menu == seq_chain_select_menu) { seq_chain_active_menu = 99; } else @@ -3993,7 +4345,6 @@ void UI_func_seq_pat_chain(uint8_t param) } } - void UI_func_information(uint8_t param) { if (LCDML.FUNC_setup()) // ****** SETUP ********* diff --git a/UI_FX_T4.h b/UI_FX_T4.h index 9bb3fe3..285748c 100644 --- a/UI_FX_T4.h +++ b/UI_FX_T4.h @@ -113,16 +113,16 @@ LCDML_add(79, LCDML_0_3_5, 1, "MIDI Recv Bank", UI_func_sysex_receive_bank); LCDML_add(80, LCDML_0_3_5, 2, "MIDI Snd Bank", UI_func_sysex_send_bank); LCDML_add(81, LCDML_0_3_5, 3, "MIDI Snd Voice", UI_func_sysex_send_voice); LCDML_add(82, LCDML_0, 4, "Drum Settings", NULL); -LCDML_add(83, LCDML_0_4, 1, "Drums Main Vol", NULL); -LCDML_add(84, LCDML_0_4, 2, "Drum Volumes", NULL); -LCDML_add(85, LCDML_0_4, 3, "Drum Pan", NULL); -LCDML_add(86, LCDML_0_4, 4, "Drum Rev.Send", NULL); +LCDML_add(83, LCDML_0_4, 1, "Drums Main Vol", UI_func_drum_main_volume); +LCDML_add(84, LCDML_0_4, 2, "Drum Volumes", UI_func_drum_volume); +LCDML_add(85, LCDML_0_4, 3, "Drum Pan", UI_func_drum_pan); +LCDML_add(86, LCDML_0_4, 4, "Drum Rev.Send", UI_func_drum_reverb_send); LCDML_add(87, LCDML_0, 5, "Sequencer Set.", NULL); LCDML_add(88, LCDML_0_5, 1, "Sequencer", UI_func_sequencer); LCDML_add(89, LCDML_0_5, 2, "Pattern Chain", UI_func_seq_pat_chain); -LCDML_add(90, LCDML_0_5, 3, "Seq. Length", NULL); +LCDML_add(90, LCDML_0_5, 3, "Seq. Length", UI_func_seq_lenght); LCDML_add(91, LCDML_0_5, 4, "Tempo", NULL); -LCDML_add(92, LCDML_0_5, 5, "Live-Trp.Key", NULL); +LCDML_add(92, LCDML_0_5, 5, "L.Transp.Key", UI_func_seq_live_transpose_oct); LCDML_add(93, LCDML_0_5, 6, "L.Trp.Offset", NULL); LCDML_add(94, LCDML_0_5, 7, "Pattern load", NULL); LCDML_add(95, LCDML_0_5, 8, "Pattern save", NULL); diff --git a/UI_NO_FX.h b/UI_NO_FX.h index ab5d008..778ec85 100644 --- a/UI_NO_FX.h +++ b/UI_NO_FX.h @@ -86,15 +86,15 @@ LCDML_add(52, LCDML_0_2_4, 1, "MIDI Recv Bank", UI_func_sysex_receive_bank); LCDML_add(53, LCDML_0_2_4, 2, "MIDI Snd Bank", UI_func_sysex_send_bank); LCDML_add(54, LCDML_0_2_4, 3, "MIDI Snd Voice", UI_func_sysex_send_voice); LCDML_add(55, LCDML_0, 3, "Drum Settings", NULL); -LCDML_add(56, LCDML_0_3, 1, "Drums Main Vol", NULL); -LCDML_add(57, LCDML_0_3, 2, "Drum Volumes", NULL); -LCDML_add(58, LCDML_0_3, 3, "Drum Pan", NULL); +LCDML_add(56, LCDML_0_3, 1, "Drums Main Vol", UI_func_drum_main_volume); +LCDML_add(57, LCDML_0_3, 2, "Drum Volumes", UI_func_drum_volume); +LCDML_add(58, LCDML_0_3, 3, "Drum Pan", UI_func_drum_pan); LCDML_add(59, LCDML_0, 4, "Sequencer Set.", NULL); LCDML_add(60, LCDML_0_4, 1, "Sequencer", UI_func_sequencer); LCDML_add(61, LCDML_0_4, 2, "Pattern Chain", UI_func_seq_pat_chain); LCDML_add(62, LCDML_0_4, 3, "Seq. Length", NULL); LCDML_add(63, LCDML_0_4, 4, "Tempo", NULL); -LCDML_add(64, LCDML_0_4, 5, "Live-Transp.Key", NULL); +LCDML_add(64, LCDML_0_4, 5, "L.Transp.Key", UI_func_seq_live_transpose_oct); LCDML_add(65, LCDML_0_4, 6, "Live-Tr.Offset", NULL); LCDML_add(66, LCDML_0_4, 7, "Pattern load", NULL); LCDML_add(67, LCDML_0_4, 8, "Pattern save", NULL);