From cffee4925c88e0dc138985eb5a3b9f5fbcfeb167 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 28 Dec 2023 12:05:54 +1100 Subject: [PATCH 001/133] replace drawCircle with drawRoundRect --- avr/cores/megacommand/MCL/RAMPage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/RAMPage.cpp b/avr/cores/megacommand/MCL/RAMPage.cpp index 128cca79c..5d358f4e5 100644 --- a/avr/cores/megacommand/MCL/RAMPage.cpp +++ b/avr/cores/megacommand/MCL/RAMPage.cpp @@ -539,7 +539,8 @@ void RAMPage::display() { uint8_t w_x = 0, w_y = 2; oled_display.drawPixel(w_x + 24, w_y + 0, WHITE); - oled_display.drawCircle(w_x + 24, w_y + 0, 2, WHITE); + //oled_display.drawCircle(w_x + 24, w_y + 0, 2, WHITE); + oled_display.drawRoundRect(w_x + 22, w_y - 2, 5, 5, 1, WHITE); oled_display.drawLine(w_x + 12, w_y - 1, w_x + 24, w_y - 3, WHITE); oled_display.drawLine(w_x + 17, w_y + 15, w_x + 26, w_y + 2, WHITE); From 4ba348f2b586d338e958f910ed51e525770488bb Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 28 Dec 2023 12:16:54 +1100 Subject: [PATCH 002/133] Small optimization --- avr/cores/megacommand/MCL/MCLGUI.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLGUI.cpp b/avr/cores/megacommand/MCL/MCLGUI.cpp index a4e7bfd47..c32c104e1 100644 --- a/avr/cores/megacommand/MCL/MCLGUI.cpp +++ b/avr/cores/megacommand/MCL/MCLGUI.cpp @@ -11,19 +11,17 @@ void MCLGUI::put_value_at(uint8_t value, char *str) { str[0] = value + '0'; str[1] = '\0'; } else if (value < 100) { - str[0] = (value % 100) / 10 + '0'; - str[1] = (value % 10) + '0'; + str[0] = value / 10 + '0'; + str[1] = value % 10 + '0'; str[2] = '\0'; - } else if (value < 1000) { - str[0] = (value % 1000) / 100 + '0'; - str[1] = (value % 100) / 10 + '0'; - str[2] = (value % 10) + '0'; + str[0] = value / 100 + '0'; + str[1] = (value / 10) % 10 + '0'; + str[2] = value % 10 + '0'; str[3] = '\0'; } } - void MCLGUI::draw_textbox(const char *text, const char *text2) { auto oldfont = oled_display.getFont(); oled_display.setFont(); From 27e8f071e7e3ac064f85de5d39ba3b2738fe7bac Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 28 Dec 2023 12:18:16 +1100 Subject: [PATCH 003/133] Disable unused virtual functions in MDPattern that were still being linked --- avr/cores/megacommand/MD/MDPattern.cpp | 16 ++++++---------- avr/cores/megacommand/MD/MDPattern.h | 4 ++-- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/avr/cores/megacommand/MD/MDPattern.cpp b/avr/cores/megacommand/MD/MDPattern.cpp index ad2e07ed1..86b8db9a6 100644 --- a/avr/cores/megacommand/MD/MDPattern.cpp +++ b/avr/cores/megacommand/MD/MDPattern.cpp @@ -12,7 +12,6 @@ #endif // #include "GUI.h" - void MDPattern::clearPattern() { numRows = 0; @@ -21,9 +20,8 @@ void MDPattern::clearPattern() { memset(&accentPatterns, 0, 8 * 3 * 16 + 1); memset(paramLocks, -1, sizeof(paramLocks)); - memset(lockTracks, -1, sizeof(lockTracks)); - memset(lockParams, -1, sizeof(lockParams)); - memset(locks, -1, sizeof(locks)); + + memset(locks, -1, sizeof(locks) + sizeof(lockTracks) + sizeof(lockParams)); // accentPattern = 0; // slidePattern = 0; @@ -40,7 +38,7 @@ void MDPattern::clearPattern() { // kit = 0; // scale = 0; } - +/* void MDPattern::clear_step_locks(uint8_t track, uint8_t step) { for (uint8_t p = 0; p < 24; p++) { int8_t idxn = getLockIdx(track, p); @@ -49,7 +47,7 @@ void MDPattern::clear_step_locks(uint8_t track, uint8_t step) { } } } - +*/ bool MDPattern::fromSysex(MidiClass *midi) { init(); @@ -281,7 +279,6 @@ uint16_t MDPattern::toSysex(ElektronDataToSysexEncoder *encoder) { return 0; #endif } - void MDPattern::recalculateLockPatterns() { for (uint8_t track = 0; track < 16; track++) { lockPatterns[track] = 0; @@ -298,11 +295,10 @@ void MDPattern::recalculateLockPatterns() { * Pattern edit functions * ***************************************************************************/ - bool MDPattern::isTrackEmpty(uint8_t track) { return ((trigPatterns[track] == 0) && (lockPatterns[track] == 0)); } - +/* void MDPattern::clearTrack(uint8_t track) { if (track >= 16) return; @@ -325,7 +321,7 @@ void MDPattern::setNote(uint8_t track, uint8_t step, uint8_t pitch) { addLock(track, step, 0, pitch); setTrig(track, step); } - +*/ /*************************************************************************** * * Pattern manipulation functions diff --git a/avr/cores/megacommand/MD/MDPattern.h b/avr/cores/megacommand/MD/MDPattern.h index d3f0f0781..b14acbefc 100644 --- a/avr/cores/megacommand/MD/MDPattern.h +++ b/avr/cores/megacommand/MD/MDPattern.h @@ -102,6 +102,7 @@ class MDPattern : public ElektronPattern { } virtual void clearPattern(); + /* virtual void clearTrack(uint8_t track); virtual void setTrig(uint8_t track, uint8_t trig) { @@ -116,9 +117,8 @@ class MDPattern : public ElektronPattern { virtual void setLockIdx(uint8_t track, uint8_t param, int8_t value) { paramLocks[track][param] = value; } - + */ virtual void recalculateLockPatterns(); - /** ElektronSysexObject implementation */ virtual bool fromSysex(MidiClass *midi); virtual uint16_t toSysex(ElektronDataToSysexEncoder *encoder); From 4f097907645773f19e1940ecd828a357318a7e5c Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 28 Dec 2023 12:57:32 +1100 Subject: [PATCH 004/133] Disable load offset when exiting load page --- avr/cores/megacommand/MCL/GridIOPage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/avr/cores/megacommand/MCL/GridIOPage.cpp b/avr/cores/megacommand/MCL/GridIOPage.cpp index 3c65a1574..505fa6dd6 100644 --- a/avr/cores/megacommand/MCL/GridIOPage.cpp +++ b/avr/cores/megacommand/MCL/GridIOPage.cpp @@ -12,6 +12,7 @@ void GridIOPage::cleanup() { trig_interface.send_md_leds(); MD.popup_text(127, 2); proj.select_grid(old_grid); + offset = 255; } void GridIOPage::init() { From df5887432513d216700886f1b06186a1ccc7d664 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 28 Dec 2023 13:03:14 +1100 Subject: [PATCH 005/133] ArpSeqTrack was using inbuilt random function --- avr/cores/megacommand/MCL/ArpSeqTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/ArpSeqTrack.cpp b/avr/cores/megacommand/MCL/ArpSeqTrack.cpp index e05d180c2..0adddfa43 100644 --- a/avr/cores/megacommand/MCL/ArpSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/ArpSeqTrack.cpp @@ -127,7 +127,7 @@ void ArpSeqTrack::render(uint8_t mode_, uint8_t oct_, uint8_t fine_tune_, uint8_ for (uint8_t i = 0; i < num_of_notes; i++) { switch (mode) { case ARP_RND: - note = sort_up[get_random(num_of_notes)] + 12 * random(range); + note = sort_up[get_random(num_of_notes)] + 12 * get_random(range); break; case ARP_UP2: case ARP_UPP: From 55a16c70d0366bf049cecfcdffc234c5e289a147 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 28 Dec 2023 13:44:50 +1100 Subject: [PATCH 006/133] Route and Perf Tracks should obey transition_send[n] state during transition_load() --- avr/cores/megacommand/MCL/MDRouteTrack.cpp | 8 +++++--- avr/cores/megacommand/MCL/MDRouteTrack.h | 2 +- avr/cores/megacommand/MCL/PerfTrack.cpp | 4 +++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDRouteTrack.cpp b/avr/cores/megacommand/MCL/MDRouteTrack.cpp index 6797a46a7..7878c012c 100644 --- a/avr/cores/megacommand/MCL/MDRouteTrack.cpp +++ b/avr/cores/megacommand/MCL/MDRouteTrack.cpp @@ -5,9 +5,11 @@ void MDRouteTrack::transition_send(uint8_t tracknumber, uint8_t slotnumber) { void MDRouteTrack::transition_load(uint8_t tracknumber, SeqTrack *seq_track, uint8_t slotnumber) { GridTrack::transition_load(tracknumber, seq_track, slotnumber); - load_routes(); - //Send routes regardless - send_routes(); + if (mcl_actions.send_machine[slotnumber]) { + load_routes(); + //Send routes regardless + send_routes(); + } } uint16_t MDRouteTrack::calc_latency(uint8_t tracknumber) { diff --git a/avr/cores/megacommand/MCL/MDRouteTrack.h b/avr/cores/megacommand/MCL/MDRouteTrack.h index 08f08fd60..089489aef 100644 --- a/avr/cores/megacommand/MCL/MDRouteTrack.h +++ b/avr/cores/megacommand/MCL/MDRouteTrack.h @@ -42,5 +42,5 @@ class MDRouteTrack : public AUXTrack, public RouteData { virtual uint8_t get_device_type() { return MDROUTE_TRACK_TYPE; } virtual void *get_sound_data_ptr() { return &routing; } - virtual size_t get_sound_data_size() { return sizeof(routing); } + virtual size_t get_sound_data_size() { return sizeof(RouteData); } }; diff --git a/avr/cores/megacommand/MCL/PerfTrack.cpp b/avr/cores/megacommand/MCL/PerfTrack.cpp index 29cb24622..c21bb5198 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.cpp +++ b/avr/cores/megacommand/MCL/PerfTrack.cpp @@ -8,7 +8,9 @@ void PerfTrack::transition_load(uint8_t tracknumber, SeqTrack *seq_track, uint8_t slotnumber) { DEBUG_PRINTLN("transition send"); GridTrack::transition_load(tracknumber, seq_track, slotnumber); - load_perf(); + if (mcl_actions.send_machine[slotnumber]) { + load_perf(); + } } uint16_t PerfTrack::calc_latency(uint8_t tracknumber) { From 648c63551741c28872174f06d39e43782193f5be Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 28 Dec 2023 14:23:32 +1100 Subject: [PATCH 007/133] Add transition protection: Increase minimum queue length, if it's below 8 steps --- avr/cores/megacommand/MCL/MCLActions.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/avr/cores/megacommand/MCL/MCLActions.cpp b/avr/cores/megacommand/MCL/MCLActions.cpp index 415a64bc9..047ad3ebd 100644 --- a/avr/cores/megacommand/MCL/MCLActions.cpp +++ b/avr/cores/megacommand/MCL/MCLActions.cpp @@ -760,7 +760,11 @@ void MCLActions::cache_next_tracks(uint8_t *slot_select_array, links[n].loops = 1; links[n].length = (float)chains[n].get_length() / (float)gdt->seq_track->get_speed_multiplier(); + while (links[n].loops * links[n].length < 8) { + links[n].loops++; + } } + //if (links[n].length == 0) { links[n].length = 16; } chains[n].inc(); links[n].row = chains[n].get_row(); if (links[n].row == 255) { From d2b2c86b49ecee0d643cc49ee1b946112ab60591 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 1 Jan 2024 22:43:38 +1100 Subject: [PATCH 008/133] WavDesigner optimizations --- avr/cores/megacommand/MCL/OscPage.cpp | 50 ++++++++--------------- avr/cores/megacommand/MCL/WavDesigner.cpp | 5 +-- 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/avr/cores/megacommand/MCL/OscPage.cpp b/avr/cores/megacommand/MCL/OscPage.cpp index ecd2a1cd0..43d76b918 100644 --- a/avr/cores/megacommand/MCL/OscPage.cpp +++ b/avr/cores/megacommand/MCL/OscPage.cpp @@ -61,10 +61,10 @@ bool OscPage::handleEvent(gui_event_t *event) { } void OscPage::calc_largest_sine_peak() { - float max_sine_gain = ((float)1 / (float)16); + float max_sine_gain = 0.0004921259843f; // ((float)1 / (float)16) / 127; largest_sine_peak = 0; for (uint8_t f = 0; f < 16; f++) { - largest_sine_peak += max_sine_gain * ((float)sine_levels[f] / (float)127); + largest_sine_peak += max_sine_gain * (float)sine_levels[f]; } } @@ -122,6 +122,9 @@ void OscPage::loop() { trig_interface.off(); } } + +const char wave_names[][4] PROGMEM = {"--", "SIN", "TRI", "PUL", "SAW", "USR"}; + void OscPage::display() { // oled_display.clearDisplay(); oled_display.fillRect(0, 0, 64, 32, BLACK); @@ -135,12 +138,10 @@ void OscPage::display() { oled_display.setCursor(0, 0); switch (osc_waveform) { - case 0: - draw_wav(0); - oled_display.print(F("--")); + default: + sample_number = 0; break; case SIN_OSC: - oled_display.print(F("SIN")); draw_levels(); for (i = 0; i < 16; i++) { if (sine_levels[i] > 0) { @@ -148,30 +149,12 @@ void OscPage::display() { } } scanline_width = 64 / c; - draw_wav(SIN_OSC); - break; - case TRI_OSC: - oled_display.print(F("TRI")); - sample_number = 0; - draw_wav(TRI_OSC); - break; - case PUL_OSC: - oled_display.print(F("PUL")); - sample_number = 0; - draw_wav(PUL_OSC); - break; - case SAW_OSC: - oled_display.print(F("SAW")); - sample_number = 0; - draw_wav(SAW_OSC); - break; - case USR_OSC: - oled_display.print(F("USR")); - draw_wav(USR_OSC); - sample_number = 0; - draw_usr(); break; } + char buf1[4]; + draw_wav(osc_waveform); + strncpy_P(buf1, wave_names[osc_waveform], 4); + oled_display.print(buf1); oled_display.print(F(" ")); char str[] = " "; @@ -209,7 +192,7 @@ void OscPage::draw_wav(uint8_t wav_type) { SineOsc sine_osc(w); UsrOsc usr_osc(w); float sample; - float max_sine_gain = (float)1 / (float)16; + float max_sine_gain = 0.0004921259843f; // (float)1 / (float)16 / 127; uint8_t n = sample_number; // for (uint8_t n = 0; n < 128 - x; n++) { @@ -223,9 +206,8 @@ void OscPage::draw_wav(uint8_t wav_type) { sample = 0; for (uint8_t f = 1; f <= 16; f++) { if (sine_levels[f - 1] != 0) { - float sine_gain = ((float)sine_levels[f - 1] / (float)127); - sample += sine_osc.get_sample((uint32_t)n, 1 * (float)f) * sine_gain * - max_sine_gain; + float sine_gain = (float)sine_levels[f - 1] * max_sine_gain; + sample += sine_osc.get_sample((uint32_t)n, 1 * (float)f) * sine_gain; } } if (largest_sine_peak == 0) { @@ -264,6 +246,10 @@ void OscPage::draw_wav(uint8_t wav_type) { if (sample_number > 127 - x) { sample_number = 0; } + if (wav_type == USR_OSC) { + draw_usr(); + } + } void OscPage::draw_usr() { diff --git a/avr/cores/megacommand/MCL/WavDesigner.cpp b/avr/cores/megacommand/MCL/WavDesigner.cpp index 55780ddda..1feaef3af 100644 --- a/avr/cores/megacommand/MCL/WavDesigner.cpp +++ b/avr/cores/megacommand/MCL/WavDesigner.cpp @@ -84,7 +84,7 @@ bool WavDesigner::render() { uint32_t pos = 0; bool write_header = false; - float max_sine_gain = (float)1 / (float)16; + float max_sine_gain = 0.0004921259843f; ; //(float)1 / (float)16) / 127; // Zero crossing detection vars bool zero_crossing_found = false; @@ -110,8 +110,7 @@ bool WavDesigner::render() { // pages[i].get_freq() * (float) h, 0); if (pages[i].sine_levels[h - 1] != 0) { float sine_gain = - ((float)pages[i].sine_levels[h - 1] / (float)127) * - max_sine_gain; + ((float)pages[i].sine_levels[h - 1]) * max_sine_gain; osc_sample += sine_osc.get_sample(n, pages[i].get_freq() * (float)h) * From b325ed53db33bf8d010ad112dd5e2d1b1761b455 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 1 Jan 2024 22:44:04 +1100 Subject: [PATCH 009/133] small optimization --- avr/cores/megacommand/MCL/MenuPage.cpp | 55 ++++++++++++++------------ 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/avr/cores/megacommand/MCL/MenuPage.cpp b/avr/cores/megacommand/MCL/MenuPage.cpp index 0cf961d30..bf7befa13 100644 --- a/avr/cores/megacommand/MCL/MenuPage.cpp +++ b/avr/cores/megacommand/MCL/MenuPage.cpp @@ -34,36 +34,38 @@ void MenuPageBase::init() { void MenuPageBase::gen_menu_device_names() { MenuBase *m = get_menu(); - menu_option_t *p = (menu_option_t *)R.Allocate(sizeof(menu_option_t) * NUM_DEVS); + menu_option_t *p = + (menu_option_t *)R.Allocate(sizeof(menu_option_t) * NUM_DEVS); m->set_custom_options(p); for (uint8_t n = 0; n < NUM_DEVS; n++) { p->pos = n + 1; - strcpy(p->name,midi_active_peering.get_device(n + 1)->name); + strcpy(p->name, midi_active_peering.get_device(n + 1)->name); p++; } - } void MenuPageBase::gen_menu_row_names() { MenuBase *m = get_menu(); menu_option_t *p = (menu_option_t *)R.Allocate(sizeof(menu_option_t) * 128); m->set_custom_options(p); - uint8_t row_id = 0; - for (char bank = 'A'; bank <= 'H'; ++bank) { - for (uint8_t i = 1; i <= 16; ++i) { - p->pos = row_id++; - p->name[0] = bank; - if (i < 10) { - p->name[1] = '0'; - p->name[2] = '0' + i; - } else { - p->name[1] = '1'; - p->name[2] = '0' + i - 10; - } - p->name[3] = '\0'; - ++p; + for (uint8_t row_id = 0; row_id < 128; ++row_id) { + char bank = 'A' + row_id / 16; + uint8_t i = row_id % 16 + 1; + + p->pos = row_id; + p->name[0] = bank; + + if (i < 10) { + p->name[1] = '0'; + p->name[2] = '0' + i; + } else { + p->name[1] = '1'; + p->name[2] = '0' + i - 10; } + + p->name[3] = '\0'; + ++p; } } @@ -152,8 +154,9 @@ void MenuPageBase::draw_menu(uint8_t x_offset, uint8_t y_offset, oled_display.setCursor(x_offset, y_offset + 8 * n); if (n == cur_row) { oled_display.setTextColor(BLACK, WHITE); - oled_display.fillRect(max(0,oled_display.getCursorX() - 3), - max(0,oled_display.getCursorY() - 6), width, 7, WHITE); + oled_display.fillRect(max(0, oled_display.getCursorX() - 3), + max(0, oled_display.getCursorY() - 6), width, 7, + WHITE); } else { oled_display.setTextColor(WHITE, BLACK); } @@ -203,10 +206,12 @@ bool MenuPageBase::enter() { } bool MenuPageBase::exit() { - if (GUI.currentPage() != this) { return; } + if (GUI.currentPage() != this) { + return; + } void (*exit_func)() = get_menu()->get_exit_function(); if (exit_func != NULL) { - (*exit_func)(); + (*exit_func)(); } mcl.popPage(); } @@ -231,16 +236,16 @@ bool MenuPageBase::handleEvent(gui_event_t *event) { trig_interface.ignoreNextEvent(MDX_KEY_NO); goto NO; case MDX_KEY_UP: - encoders[1]->cur -= inc; + encoders[1]->cur -= inc; break; case MDX_KEY_DOWN: - encoders[1]->cur += inc; + encoders[1]->cur += inc; break; case MDX_KEY_LEFT: - encoders[0]->cur -= inc; + encoders[0]->cur -= inc; break; case MDX_KEY_RIGHT: - encoders[0]->cur += inc; + encoders[0]->cur += inc; break; } } From 171bc70ed0c5d07f2dba6045904e619fa3e04f6a Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 1 Jan 2024 22:45:00 +1100 Subject: [PATCH 010/133] ignore unused slots --- avr/cores/megacommand/MCL/MCLActionsEvents.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/avr/cores/megacommand/MCL/MCLActionsEvents.cpp b/avr/cores/megacommand/MCL/MCLActionsEvents.cpp index e400572f1..abb46e98f 100644 --- a/avr/cores/megacommand/MCL/MCLActionsEvents.cpp +++ b/avr/cores/megacommand/MCL/MCLActionsEvents.cpp @@ -89,6 +89,12 @@ void MCLActionsCallbacks::StopHardCallback() { bool proceed = false; for (uint8_t n = 0; n < NUM_SLOTS; n++) { + GridDeviceTrack *gdt = + mcl_actions.get_grid_dev_track(n); + + if (gdt == nullptr) + continue; + if (mcl_actions.chains[n].is_mode_queue()) { slot_select_array[n] = 1; row_array[n] = mcl_actions.chains[n].rows[0]; @@ -134,6 +140,12 @@ void MCLActionsCallbacks::onMidiStartCallback() { mcl_actions.start_clock32th = 0; mcl_actions.start_clock16th = 0; for (uint8_t n = 0; n < NUM_SLOTS; n++) { + GridDeviceTrack *gdt = + mcl_actions.get_grid_dev_track(n); + + if (gdt == nullptr) + continue; + if (grid_page.active_slots[n] != SLOT_DISABLED) { mcl_actions.next_transitions[n] = 0; mcl_actions.transition_offsets[n] = 0; From 565ba3caed527550f1341075720c54bb8fabda25 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 14 Feb 2024 13:37:44 +1100 Subject: [PATCH 011/133] Fix regression in load offset/destination. --- avr/cores/megacommand/MCL/GridLoadPage.cpp | 4 +--- avr/cores/megacommand/MCL/GridSavePage.cpp | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/avr/cores/megacommand/MCL/GridLoadPage.cpp b/avr/cores/megacommand/MCL/GridLoadPage.cpp index 4806a4851..eda42eb49 100644 --- a/avr/cores/megacommand/MCL/GridLoadPage.cpp +++ b/avr/cores/megacommand/MCL/GridLoadPage.cpp @@ -211,10 +211,8 @@ void GridLoadPage::load() { track_select_array[n] = 1; } } - mcl.setPage(GRID_PAGE); - trig_interface.off(); - grid_task.load_queue.put(mcl_cfg.load_mode, grid_page.getRow(), track_select_array, offset); + mcl.setPage(GRID_PAGE); } void GridLoadPage::group_select() { diff --git a/avr/cores/megacommand/MCL/GridSavePage.cpp b/avr/cores/megacommand/MCL/GridSavePage.cpp index 9fcb6fdc7..299dbdf07 100644 --- a/avr/cores/megacommand/MCL/GridSavePage.cpp +++ b/avr/cores/megacommand/MCL/GridSavePage.cpp @@ -96,9 +96,8 @@ void GridSavePage::save() { } } - mcl.setPage(GRID_PAGE); - trig_interface.off(); mcl_actions.save_tracks(grid_page.getRow(), track_select_array, save_mode); + mcl.setPage(GRID_PAGE); } void GridSavePage::group_select() { From 3dce954243fc216ade03adbc26b544d6bd694587 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 24 Apr 2024 16:53:06 +1000 Subject: [PATCH 012/133] Add Flash Checksum and SRAM testing. checksum.py will calculate firmware length and checksum value from intel hex file, main.hex. It will then embed these values in the firmware's last usable memory position - 6. By appending additonal records to the main.hex file. Length is 32bit, checksum is 16bit. SRAM testing is added immediate after RAM initialisation. MCL will not boot if either of these test fails. SRAM Failure = Both LEDs on. Checksum Failure = oled error message. --- avr/cores/megacommand/MCL/MCL.cpp | 54 +++++++++++- avr/cores/megacommand/Makefile | 5 +- avr/cores/megacommand/checksum.py | 105 +++++++++++++++++++++++ avr/cores/megacommand/main.cpp | 51 ++++++++++- avr/cores/megacommand/make_and_upload.sh | 7 +- 5 files changed, 213 insertions(+), 9 deletions(-) create mode 100755 avr/cores/megacommand/checksum.py diff --git a/avr/cores/megacommand/MCL/MCL.cpp b/avr/cores/megacommand/MCL/MCL.cpp index ed2467d82..8551241fb 100644 --- a/avr/cores/megacommand/MCL/MCL.cpp +++ b/avr/cores/megacommand/MCL/MCL.cpp @@ -2,6 +2,49 @@ #include "MCL_impl.h" #include "ResourceManager.h" + +uint32_t read_bytes_progmem(uint32_t address, uint8_t n) { + uint32_t value = 0; + for (uint8_t i = 0; i < n; i++) { + uint8_t byte = pgm_read_byte_far(address + i); // Read a byte from program memory + value |= (uint32_t)byte << (8 * i); // Combine bytes into a 32-bit value + } + return value; +} + + +bool health_check() { + uint32_t memoryAddress = 256 * 1024 - 16 * 1024 - 6; + uint32_t length = read_bytes_progmem(memoryAddress, 4); + uint16_t checksum = (uint16_t) read_bytes_progmem(memoryAddress + 4, 2); + DEBUG_PRINTLN(length); + DEBUG_PRINTLN(checksum); + + uint16_t calc_checksum = 0; + uint32_t n = 0; + uint8_t byte = 0; + + for (uint32_t n = 0; n < length; n++) { + uint8_t last_byte = byte; + byte = pgm_read_byte_far(n); + if (n % 2 == 0) { + calc_checksum ^= (byte << 8) | last_byte; + } + } + + DEBUG_PRINTLN(calc_checksum); + +#ifdef DEBUGMODE + if (calc_checksum != checksum) { + DEBUG_PRINTLN("checksum error"); + } +#endif + + return calc_checksum == checksum; + +} + + void sdcard_bench() { EmptyTrack empty_track; @@ -103,10 +146,17 @@ void MCL::setup() { DEBUG_PRINTLN(BANK3_FILE_ENTRIES_END); bool ret = false; - delay(100); - + delay(50); + bool health = health_check(); ret = mcl_sd.sd_init(); gfx.init_oled(); + + if (!health) { + oled_display.textbox("CHECKSUM ", "ERROR"); + oled_display.display(); + while (1); + } + R.Clear(); R.use_icons_boot(); diff --git a/avr/cores/megacommand/Makefile b/avr/cores/megacommand/Makefile index 344b2e380..0ab45ece6 100644 --- a/avr/cores/megacommand/Makefile +++ b/avr/cores/megacommand/Makefile @@ -128,8 +128,9 @@ clean: upload: main.hex echo "DEVICE is $(AVR_DEVICE)"; \ - echo "RAM USAGE: `$(AVRSIZE) main.elf | grep main | awk '{ print $$2 + $$3}'`"; \ - ${AVRDUDE} -C${AVRDUDE_CFG} -v -V -patmega2560 -cwiring -P${AVR_DEVICE} -b115200 -D -Uflash:w:./main.hex + echo "RAM USAGE: `$(AVRSIZE) main.elf | grep main | awk '{ print $$2 + $$3}'`"; \ + ./checksum.py main.hex; \ + ${AVRDUDE} -C${AVRDUDE_CFG} -v -V -patmega2560 -cwiring -P${AVR_DEVICE} -b115200 -D -Uflash:w:./main.hex debug: CXXFLAGS += -DDEBUGMODE=1 debug: CFLAGS += -DDEBUGMODE=1 diff --git a/avr/cores/megacommand/checksum.py b/avr/cores/megacommand/checksum.py new file mode 100755 index 000000000..b3f27d9d9 --- /dev/null +++ b/avr/cores/megacommand/checksum.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python + +import sys + +def dec(h): + return int(h, 16) + +def calculate_checksum(values): + checksum_sum = sum(values) + lsb = checksum_sum & 0xFF + twos_complement_lsb = (~lsb + 1) & 0xFF + record_checksum_str = format(twos_complement_lsb, '02X') + return record_checksum_str + +def insert_record(record_type, address, length, values): + print("insert record") + values.reverse() #endianess for atmega + output = length + address + record_type + values + checksum = calculate_checksum(output) + output = [format(byte, '02X') for byte in output] #convert to hex str format + output.append(checksum) + output.append("\n") + output = [":"] + output + print(''.join(output)) + lines.insert(-1, ''.join(output)) + +if len(sys.argv) != 2: + print("Usage: python script.py ") + sys.exit(1) + + +filename = sys.argv[1] +lines = [] +count = 0 + +b = [] +with open(filename, "r") as file: + for line in file: + lines.append(line) + line = line.strip() # Remove leading/trailing whitespace + length = len(line) + if line.startswith(":"): + n = dec(line[1:3]) # number of bytes in payload + record = line[7:7 + 2] + data = line[9:9 + (n * 2)] + data_checksum = line[-2:] + if record != "00": # only include data records + continue + # Print every two characters in the data payload + for i in range(0, n * 2, 2): + count += 1 + byte = data[i:i+2] + b.append(dec(byte)) + +n = 0 + +byte = 0 +checksum=0 +print(count) +while n < count: + last_byte = byte + byte = b[n] + if n % 2 == 0: + checksum ^= (byte << 8) | last_byte + n += 1 + +checksum_str = format(checksum, '04X') +length_str = format(count, '08X') + +print("Checksum: ", checksum_str) + +print(format(checksum, 'X')) + +print("Length: ", count) + +# Append the checksum to the main.hex file + +lines.insert(-1,":020000023000CC\n") # Extended Segment Address Record + +#256 * 1024 - 16 * 1024 - 6 + +# Length, 32bit @ 0xBFFA +data_bytes = [ dec(length_str[i:i+2]) for i in range(0, len(length_str), 2)] + +length_bytes = [ 0x04 ] +address_bytes = [ 0xBF, 0xFA ] +record_bytes = [ 0x00 ] + +insert_record(record_bytes, address_bytes, length_bytes, data_bytes) + +# Checksum, 16bit @ 0xBFFE + +data_bytes = [ dec(checksum_str[i:i+2]) for i in range(0, len(checksum_str), 2)] + +length_bytes = [ 0x02 ] +address_bytes = [ 0xBF, 0xFE ] +record_bytes = [ 0x00 ] + +insert_record(record_bytes, address_bytes, length_bytes, data_bytes) + +with open(filename, "w") as f: + f.truncate() + for line in lines: + f.write(line) + diff --git a/avr/cores/megacommand/main.cpp b/avr/cores/megacommand/main.cpp index 22915006a..4e3c024e6 100644 --- a/avr/cores/megacommand/main.cpp +++ b/avr/cores/megacommand/main.cpp @@ -44,8 +44,56 @@ void my_init_ram(void) { PORTB &= ~(_BV(PB0)); #endif XMCRA |= _BV(SRE); -} + //Leds + + DDRE |= _BV(PE4) | _BV(PE5); + //SRAM tests + + switch_ram_bank(1); + volatile uint8_t *ptr; + uint8_t linear = 0; + uint8_t read_bank0, read_bank1 = 0; + + for (ptr = reinterpret_cast (0x2200); ptr < reinterpret_cast (0xFFFF); ptr++) { + switch_ram_bank(0); + uint8_t random_number = pgm_read_byte(rand_ptr++) || 1; + //Store a random number in bank 0 + *ptr = random_number; + //Read value back from bank 0 + read_bank0 = *ptr; + switch_ram_bank(1); + //Store same random number in bank 1 + *ptr = read_bank0; + //Read bank1 + read_bank1 = *ptr; + if ((read_bank0 == 0) || (read_bank1 == 0) || (read_bank0 != random_number) || (read_bank1 != random_number)) { + goto fail; + } + //Store lineearly increases values in bank 1, for linear read later. (loop compaction) + *ptr = linear++; + } + + //Linear read. + linear = 0; + for (ptr = reinterpret_cast (0x2200); ptr < reinterpret_cast (0xFFFF); ptr++) { + read_bank0 = *ptr; + if (read_bank0 != linear) { + goto fail; + } + linear++; + } + + switch_ram_bank(0); + + return; + + fail: + while (1) { + setLed(); + setLed2(); + } +} uint8_t tcnt2; void timer_init(void) { @@ -112,7 +160,6 @@ void init(void) { SET_BIT(DDRD, PD4); SET_BIT(PORTD, PD4); - DDRE |= _BV(PE4) | _BV(PE5); //For MC SMD. Level shifter 1 + 2 enable. //PL4 == MEGA2560 level shifter enable diff --git a/avr/cores/megacommand/make_and_upload.sh b/avr/cores/megacommand/make_and_upload.sh index faf2af36d..e9861ffae 100755 --- a/avr/cores/megacommand/make_and_upload.sh +++ b/avr/cores/megacommand/make_and_upload.sh @@ -1,12 +1,13 @@ #!/bin/bash AVR_DIR=$(cd "../../../../tools/avr"; pwd) DEV=/dev/$(ls /dev | grep usb | grep cu | tail -n 1) +rm main.hex make -j8 if [ $? -eq 0 ]; then size=$(${AVR_DIR}/bin/avr-size main.elf | tail -n 1 | awk '{ print $1 + $2}') - limit=$((256 * 1024 - 16 * 1024)) + limit=$((256 * 1024 - 16 - 6 * 1024)) echo ROM_SIZE : $size echo ROM_LIMIT: $limit echo ROM_FREE : $(($limit - $size)) @@ -17,10 +18,10 @@ if [ $? -eq 0 ]; then ram_free=$((1024 * 64 - $ram_used - 8 * 1024)) echo RAM_USED: $ram_used echo RAM_FREE: $ram_free - ${AVR_DIR}/bin/avr-nm main.elf -Crtd --size-sort | grep -i ' [dbv] ' | sort + ./checksum.py main.hex; #avrdude -c atmelice_isp -p m2560 -D -Uflash:w:./main.hex -B 1 ${AVR_DIR}/bin/avrdude -C${AVR_DIR}/etc/avrdude.conf -V -patmega2560 -c arduino -P${DEV} -b115200 -D -Uflash:w:./main.hex -# ${AVR_DIR}/bin/avrdude -C${AVR_DIR}/etc/avrdude.conf -V -patmega2560 -c wiring -P${DEV} -b115200 -D -Uflash:w:./main.hex + #${AVR_DIR}/bin/avrdude -C${AVR_DIR}/etc/avrdude.conf -V -patmega2560 -c wiring -P${DEV} -b115200 -D -Uflash:w:./main.hex fi From 0ca604988335bb423c89b39e856b225c2236f7e7 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 9 Jul 2024 15:58:08 +1000 Subject: [PATCH 013/133] Disabling checksum checks for now, problem is resolved by correct fuse setting --- avr/cores/megacommand/MCL/MCL.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/avr/cores/megacommand/MCL/MCL.cpp b/avr/cores/megacommand/MCL/MCL.cpp index 8551241fb..da488ef4e 100644 --- a/avr/cores/megacommand/MCL/MCL.cpp +++ b/avr/cores/megacommand/MCL/MCL.cpp @@ -147,15 +147,19 @@ void MCL::setup() { bool ret = false; delay(50); +#ifdef CHECKSUM bool health = health_check(); +#endif ret = mcl_sd.sd_init(); gfx.init_oled(); +#ifdef CHECKSUM if (!health) { oled_display.textbox("CHECKSUM ", "ERROR"); oled_display.display(); while (1); } +#endif R.Clear(); R.use_icons_boot(); From 8b78b78f14d1e98c0b9459a972a085976fb88310 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 9 Jul 2024 15:59:11 +1000 Subject: [PATCH 014/133] SampleBrowser was reporting wav_file size = 0 --- avr/cores/megacommand/MCL/SampleBrowserPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp index 16f8c8d3c..92dd34865 100644 --- a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp @@ -71,7 +71,7 @@ void SampleBrowserPage::display() { oled_display.print(F(":")); oled_display.print(ms); */ - uint32_t size = wav_file.file.size(); + size = wav_file.file.size(); wav_file.close(); } else if (is_syx) { From dc00d068102f421fc8710d608706752e398d2ded Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 16 Jul 2024 17:53:06 +1000 Subject: [PATCH 015/133] disable sram checks on boot, not quite working --- avr/cores/megacommand/main.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/avr/cores/megacommand/main.cpp b/avr/cores/megacommand/main.cpp index 4e3c024e6..1c0f8ec6a 100644 --- a/avr/cores/megacommand/main.cpp +++ b/avr/cores/megacommand/main.cpp @@ -48,12 +48,12 @@ void my_init_ram(void) { //Leds DDRE |= _BV(PE4) | _BV(PE5); + return; //SRAM tests - switch_ram_bank(1); volatile uint8_t *ptr; uint8_t linear = 0; - uint8_t read_bank0, read_bank1 = 0; + volatile uint8_t read_bank0, read_bank1 = 0; for (ptr = reinterpret_cast (0x2200); ptr < reinterpret_cast (0xFFFF); ptr++) { switch_ram_bank(0); @@ -70,10 +70,23 @@ void my_init_ram(void) { if ((read_bank0 == 0) || (read_bank1 == 0) || (read_bank0 != random_number) || (read_bank1 != random_number)) { goto fail; } + // Check that the RAM bank toggle actually toggles to a different bank. + + random_number++; + //Store new random number in to bank1 + *ptr = random_number; + //Read bank1 + read_bank1 = *ptr; + //Read bank0; + switch_ram_bank(0); + read_bank0 = *ptr; + if (read_bank0 == read_bank1) { + goto fail; + } //Store lineearly increases values in bank 1, for linear read later. (loop compaction) *ptr = linear++; } - + switch_ram_bank(0); //Linear read. linear = 0; for (ptr = reinterpret_cast (0x2200); ptr < reinterpret_cast (0xFFFF); ptr++) { @@ -83,9 +96,7 @@ void my_init_ram(void) { } linear++; } - - switch_ram_bank(0); - + switch_ram_bank(1); return; fail: From 5f942b26ca91fc955c300136f52555a4b85c8f13 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 16 Jul 2024 17:54:54 +1000 Subject: [PATCH 016/133] MIDI Machine sequencing on port2 via MDSeqTrack, preliminary --- avr/cores/megacommand/MCL/MCL.h | 4 +- avr/cores/megacommand/MCL/MCLSeq.cpp | 5 +- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 186 +++++++++++++++++------ avr/cores/megacommand/MCL/MDSeqTrack.h | 71 +++++++-- avr/cores/megacommand/MCL/SeqTrack.h | 1 + 5 files changed, 204 insertions(+), 63 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index 4a86d4256..c8fc545e7 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -16,8 +16,8 @@ #include "Fonts/Elektrothic.h" #include "Fonts/TomThumb.h" -#define VERSION 4051 -#define VERSION_STR "4.51" +#define VERSION 4052 +#define VERSION_STR "D4.52" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index 723429206..f0b8c7d73 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -230,10 +230,11 @@ void MCLSeq::seq() { // Stopwatch sw; MDSeqTrack::md_trig_mask = 0; MDSeqTrack::load_machine_cache = 0; + MidiUartParent *uart_; for (uint8_t i = 0; i < num_md_tracks; i++) { - md_tracks[i].seq(uart); + md_tracks[i].seq(uart,uart2); md_arp_tracks[i].mute_state = md_tracks[i].mute_state; - md_arp_tracks[i].seq(uart); + md_arp_tracks[i].seq(uart_); } if (MDSeqTrack::md_trig_mask > 0) { diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index fe8348c1d..9507d63ce 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -34,20 +34,25 @@ void MDSeqTrack::set_length(uint8_t len, bool expand) { return; } } - MDSeqStep empty_step; - memset(&empty_step, 0, sizeof(empty_step)); - uint8_t a = 0; - for (uint8_t n = old_length; n < 64; n++) { - copy_step(a++, &empty_step); - paste_step(n, &empty_step); - if (a == old_length) { a = 0; } + MDSeqStep empty_step; + memset(&empty_step, 0, sizeof(empty_step)); + uint8_t a = 0; + for (uint8_t n = old_length; n < 64; n++) { + copy_step(a++, &empty_step); + paste_step(n, &empty_step); + if (a == old_length) { + a = 0; } + } } } void MDSeqTrack::store_mute_state() { for (uint8_t n = 0; n < NUM_MD_STEPS; n++) { - if (IS_BIT_SET64(mute_mask, n)) { set_step(n,MASK_PATTERN, 0); set_step(n,MASK_LOCK, 0); } + if (IS_BIT_SET64(mute_mask, n)) { + set_step(n, MASK_PATTERN, 0); + set_step(n, MASK_LOCK, 0); + } } clear_mutes(); } @@ -79,26 +84,29 @@ void MDSeqTrack::re_sync() { } void MDSeqTrack::load_cache() { -/* MDTrackChunk t; - DEBUG_PRINTLN("lc"); - for (uint8_t n = 0; n < t.get_chunk_count(); n++) { - t.load_from_mem_chunk(track_number, n); - t.load_chunk(data(), n); - }*/ + /* MDTrackChunk t; + DEBUG_PRINTLN("lc"); + for (uint8_t n = 0; n < t.get_chunk_count(); n++) { + t.load_from_mem_chunk(track_number, n); + t.load_chunk(data(), n); + }*/ MDTrack t; t.load_from_mem(track_number, MD_TRACK_TYPE); t.load_seq_data((SeqTrack *)this); if (load_sound) { - MD.insertMachineInKit(track_number, &(t.machine),false); + MD.insertMachineInKit(track_number, &(t.machine), false); SET_BIT32(load_machine_cache, track_number); load_sound = 0; } } -void MDSeqTrack::seq(MidiUartParent *uart_) { +void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { MidiUartParent *uart_old = uart; + MidiUartParent *uart2_old = uart2; + uart = uart_; + uart2 = uart2_; uint8_t timing_mid = get_timing_mid_inline(); @@ -117,9 +125,8 @@ void MDSeqTrack::seq(MidiUartParent *uart_) { if (count_down == 0) { reset(); mod12_counter = 0; - SET_BIT16(gui_update,track_number); - } - else if (count_down <= track_number / 4 + 1) { + SET_BIT16(gui_update, track_number); + } else if (count_down <= track_number / 4 + 1) { if (!cache_loaded) { load_cache(); cache_loaded = true; @@ -128,6 +135,13 @@ void MDSeqTrack::seq(MidiUartParent *uart_) { } } + if (notes.count_down) { + notes.count_down--; + if (notes.count_down == 0) { + send_notes_off(); + } + } + if (record_mutes) { uint8_t u = 0; uint8_t q = 0; @@ -135,8 +149,7 @@ void MDSeqTrack::seq(MidiUartParent *uart_) { SET_BIT64(mute_mask, s); } - if ((mute_state == SEQ_MUTE_OFF) && - (ignore_step != step_count)) { + if ((mute_state == SEQ_MUTE_OFF) && (ignore_step != step_count)) { uint8_t next_step = 0; if (step_count == (length - 1)) { @@ -161,16 +174,21 @@ void MDSeqTrack::seq(MidiUartParent *uart_) { lock_idx += popcount(steps[step_count].locks); } } - auto &step = steps[current_step]; uint8_t send_trig = trig_conditional(step.cond_id); - if (send_trig == TRIG_TRUE || (!step.cond_plock && send_trig != TRIG_ONESHOT)) { + if (send_trig == TRIG_TRUE || + (!step.cond_plock && send_trig != TRIG_ONESHOT)) { + if (MD.kit.models[track_number] & 0xF0 == MID_01_MODEL) { + send_notes_off(); + init_notes(); + } send_parameter_locks_inline(current_step, step.trig, lock_idx); if (step.slide) { locks_slides_recalc = current_step; locks_slides_idx = lock_idx; } if (send_trig == TRIG_TRUE && step.trig) { + notes.count_down = (notes.len * timing_mid); send_trig_inline(); } } @@ -178,6 +196,7 @@ void MDSeqTrack::seq(MidiUartParent *uart_) { } end: uart = uart_old; + uart2 = uart2_old; } bool MDSeqTrack::is_param(uint8_t param_id) { @@ -211,7 +230,9 @@ void MDSeqTrack::recalc_slides() { } auto lockidx = locks_slides_idx; - if (find_mask == 0) { goto end; } + if (find_mask == 0) { + goto end; + } find_next_locks(lockidx, step, find_mask); for (uint8_t c = 0; c < NUM_LOCKS; c++) { @@ -240,7 +261,7 @@ void MDSeqTrack::recalc_slides() { y1 = locks_slide_next_lock_val[c]; prepare_slide(c, x0, x1, y0, y1); } - end: +end: locks_slides_recalc = 255; } @@ -265,7 +286,8 @@ void MDSeqTrack::find_next_locks(uint8_t curidx, uint8_t step, uint8_t mask) { mask &= ~cur_mask; // all targets hit? } else if (steps[next_step].trig) { - locks_slide_next_lock_val[i] = MD.kit.params[track_number][locks_params[i] - 1]; + locks_slide_next_lock_val[i] = + MD.kit.params[track_number][locks_params[i] - 1]; locks_slide_next_lock_step[i] = next_step; mask &= ~cur_mask; } @@ -373,25 +395,80 @@ void MDSeqTrack::send_parameter_locks(uint8_t step, bool trig, void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uint16_t lock_idx) { + + const uint8_t number_midi_cc = 6; + uint8_t ccs[number_midi_cc][2]; + memset(ccs, 0, sizeof(ccs)); + for (uint8_t c = 0; c < NUM_LOCKS; c++) { bool lock_bit = steps[step].is_lock_bit(c); bool lock_present = steps[step].is_lock(c); bool send = false; - uint8_t send_param; + uint8_t val; uint8_t p = locks_params[c] - 1; if (locks_params[c]) { if (lock_present) { - send_param = locks[lock_idx]; + val = locks[lock_idx]; send = true; } else if (trig) { - send_param = MD.kit.params[track_number][p]; + val = MD.kit.params[track_number][p]; send = true; } } lock_idx += lock_bit; if (send) { - bool update_kit = false; - MD.setTrackParam_inline(track_number, p, send_param, uart, update_kit); + if ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL && p < 21) { + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + + switch (p) { + case 0: + case 1: + case 2: + ((uint8_t *)¬es)[p] = val; + break; + case 3: + notes.len = val; + break; + case 4: + notes.vel = val; + break; + case 5: + uart2->sendPitchBend(channel, val); + break; + case 6: + uart2->sendCC(channel, 0x1, val); + break; + case 7: + uart2->sendChannelPressure(channel, val); + break; + case 20: + uart2->sendProgramChange(channel, val); + break; + default: + bool t = p & 1; + uint8_t d = (p - 8) / 2; + ccs[d][t] = val; + break; + } + + if (c == NUM_LOCKS - 1) { + for (uint8_t n = 0; n < number_midi_cc; n++) { + uint8_t a = ccs[n]; + if (a) { + //0 = off + //1 = bank (0) + //2 = 2 + if (a == 1) { a = 0; }; + uart2->sendCC(channel, a, val); + } + } + } + } + + else { + bool update_kit = false; + MD.setTrackParam_inline(track_number, p, val, uart, update_kit); + } } } } @@ -442,14 +519,21 @@ void MDSeqTrack::send_trig() { send_trig_inline(); } void MDSeqTrack::send_trig_inline() { mixer_page.trig(track_number); - // MD.triggerTrack(track_number, 127, uart); - SET_BIT16(MDSeqTrack::md_trig_mask, track_number); + if ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL) { + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + send_notes_on(); + } else { + // MD.triggerTrack(track_number, 127, uart); + // Parallel trig: + SET_BIT16(MDSeqTrack::md_trig_mask, track_number); + } } uint8_t MDSeqTrack::trig_conditional(uint8_t condition) { bool send_trig = TRIG_FALSE; - if (IS_BIT_SET64(oneshot_mask, step_count) || IS_BIT_SET64(mute_mask, step_count)) { + if (IS_BIT_SET64(oneshot_mask, step_count) || + IS_BIT_SET64(mute_mask, step_count)) { return TRIG_ONESHOT; } if (condition == 14) { @@ -457,11 +541,10 @@ uint8_t MDSeqTrack::trig_conditional(uint8_t condition) { SET_BIT64(oneshot_mask, step_count); send_trig = TRIG_TRUE; } - } - else { + } else { send_trig = SeqTrack::conditional(condition); } - return send_trig; + return send_trig; } uint8_t MDSeqTrack::get_track_lock_implicit(uint8_t step, uint8_t param) { @@ -665,10 +748,10 @@ void MDSeqTrack::clear_param_locks(uint8_t param_id) { } } - MD.setTrackParam(track_number, param_id, MD.kit.params[track_number][locks_params[match] - 1]); + MD.setTrackParam(track_number, param_id, + MD.kit.params[track_number][locks_params[match] - 1]); } - void MDSeqTrack::clear_step_locks(uint8_t step) { uint8_t idx = get_lockidx(step); uint8_t cnt = popcount(steps[step].locks); @@ -680,7 +763,6 @@ void MDSeqTrack::clear_step_locks(uint8_t step) { } steps[step].locks = 0; steps[step].locks_enabled = false; - } void MDSeqTrack::disable_step_locks(uint8_t step) { @@ -695,9 +777,7 @@ uint8_t MDSeqTrack::get_step_locks(uint8_t step) { return steps[step].locks_enabled ? steps[step].locks : 0; } -void MDSeqTrack::clear_mute() { - mute_mask = 0; -} +void MDSeqTrack::clear_mute() { mute_mask = 0; } void MDSeqTrack::clear_mutes() { oneshot_mask = 0; @@ -836,15 +916,15 @@ void MDSeqTrack::modify_track(uint8_t dir) { memmove(timing + 1, timing, length - 1); steps[0] = step_buf; timing[0] = timing_buf; - ROTATE_RIGHT(mute_mask,length); + ROTATE_RIGHT(mute_mask, length); break; } case DIR_REVERSE: { uint8_t rev_locks[NUM_MD_LOCK_SLOTS]; memcpy(rev_locks, locks, sizeof(locks)); uint16_t l = 0, r = 0; - //mute_mask = 0; //unimplemented - // reverse steps & locks + // mute_mask = 0; //unimplemented + // reverse steps & locks for (uint8_t i = 0; i <= length / 2; ++i) { int j = length - i - 1; if (j < i) { @@ -864,10 +944,16 @@ void MDSeqTrack::modify_track(uint8_t dir) { timing[j] = timing_buf; bool a = IS_BIT_SET64(mute_mask, i); bool b = IS_BIT_SET64(mute_mask, j); - if (a) { SET_BIT64(mute_mask, j); } - else { CLEAR_BIT64(mute_mask,j); } - if (b) { SET_BIT64(mute_mask, i); } - else { CLEAR_BIT64(mute_mask,i); } + if (a) { + SET_BIT64(mute_mask, j); + } else { + CLEAR_BIT64(mute_mask, j); + } + if (b) { + SET_BIT64(mute_mask, i); + } else { + CLEAR_BIT64(mute_mask, i); + } } break; } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index c9ce470f1..7e320cce2 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -3,10 +3,10 @@ #ifndef MDSEQTRACK_H__ #define MDSEQTRACK_H__ +#include "DeviceTrack.h" #include "MD.h" -#include "SeqTrack.h" #include "MDSeqTrackData.h" -#include "DeviceTrack.h" +#include "SeqTrack.h" #define UART1_PORT 1 @@ -16,10 +16,19 @@ class MDTrack; +class TrigNotes { +public: + uint8_t note1; + uint8_t note2; + uint8_t note3; + uint8_t len; + uint8_t vel; + uint8_t count_down; +}; + class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { public: - uint64_t oneshot_mask; uint64_t mute_mask; @@ -27,11 +36,14 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { static uint16_t md_trig_mask; static uint32_t load_machine_cache; + TrigNotes notes; + MDSeqTrack() : SeqSlideTrack() { active = MD_TRACK_TYPE; } ALWAYS_INLINE() void reset() { SeqSlideTrack::reset(); oneshot_mask = 0; record_mutes = false; + send_notes_off(); } void get_mask(uint64_t *_pmask, uint8_t mask_type) const; @@ -39,7 +51,7 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { bool get_step(uint8_t step, uint8_t mask_type) const; void set_step(uint8_t step, uint8_t mask_type, bool val); - void seq(MidiUartParent *uart_); + void seq(MidiUartParent *uart_, MidiUartParent *uart2_); void mute() { mute_state = SEQ_MUTE_ON; } void unmute() { mute_state = SEQ_MUTE_OFF; } @@ -47,20 +59,24 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { void send_trig(); void send_trig_inline(); uint8_t trig_conditional(uint8_t condition); - void send_parameter_locks(uint8_t step, bool trig, uint16_t lock_idx = 0xFFFF); + void send_parameter_locks(uint8_t step, bool trig, + uint16_t lock_idx = 0xFFFF); void send_parameter_locks_inline(uint8_t step, bool trig, uint16_t lock_idx); void reset_params(); - void get_step_locks(uint8_t step, uint8_t *params, bool ignore_locks_disabled = false); + void get_step_locks(uint8_t step, uint8_t *params, + bool ignore_locks_disabled = false); void recalc_slides(); void find_next_locks(uint8_t curidx, uint8_t step, uint8_t mask); void set_track_pitch(uint8_t step, uint8_t pitch); - void set_track_step(uint8_t step, uint8_t utiming, uint8_t velocity = 127); + void set_track_step(uint8_t step, uint8_t utiming, + uint8_t velocity = 127); // !! Note lockidx is lock index, not param id bool set_track_locks_i(uint8_t step, uint8_t lockidx, uint8_t velocity); // !! Note track_param is param_id, not lock index - bool set_track_locks(uint8_t step, uint8_t track_param, uint8_t velocity); + bool set_track_locks(uint8_t step, uint8_t track_param, + uint8_t velocity); // !! Note lockidx is lock index, not param_id uint8_t get_track_lock(uint8_t step, uint8_t lockidx); @@ -96,13 +112,50 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { void modify_track(uint8_t dir); - void set_speed(uint8_t new_speed, uint8_t old_speed = 255, bool timing_adjust = true); + void set_speed(uint8_t new_speed, uint8_t old_speed = 255, + bool timing_adjust = true); void store_mute_state(); void copy_step(uint8_t n, MDSeqStep *step); void paste_step(uint8_t n, MDSeqStep *step); void load_cache(); + + void init_notes() { + // Copy 4 notes and notes.vel from kit to this structure; + memcpy(¬es.note1, MD.kit.params[track_number], 5); + notes.count_down = 0; + } + void send_notes_on() { + TrigNotes *n = ¬es; + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + + if (n->note1 != 255) { + uart2->sendNoteOn(channel, n->note1, n->vel); + if (n->note2 != 63) { + uart2->sendNoteOn(channel, n->note1 + n->note2 - 63, n->vel); + } + if (n->note3 != 63) { + uart2->sendNoteOn(channel, n->note1 + n->note3 - 63, n->vel); + } + } + } + + void send_notes_off() { + TrigNotes *n = ¬es; + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + + if (n->note1 != 255) { + uart2->sendNoteOff(channel, n->note1); + if (n->note2 != 63) { + uart2->sendNoteOff(channel, n->note1 + n->note2 - 63); + } + if (n->note3 != 63) { + uart2->sendNoteOff(channel, n->note1 + n->note3 - 63); + } + n->note1 = 255; + } + } }; #endif /* MDSEQTRACK_H__ */ diff --git a/avr/cores/megacommand/MCL/SeqTrack.h b/avr/cores/megacommand/MCL/SeqTrack.h index c74d31afb..eb700f1ea 100644 --- a/avr/cores/megacommand/MCL/SeqTrack.h +++ b/avr/cores/megacommand/MCL/SeqTrack.h @@ -69,6 +69,7 @@ class SeqTrackBase { uint8_t port = UART1_PORT; MidiUartParent *uart = &MidiUart; + MidiUartParent *uart2 = &MidiUart2; uint8_t mute_state = SEQ_MUTE_OFF; bool record_mutes; From 465e986536f64ab16597d40e072843f829ae4d80 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 16 Jul 2024 17:56:47 +1000 Subject: [PATCH 017/133] Regression --- avr/cores/megacommand/MCL/MCLSeq.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index f0b8c7d73..0a6507710 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -230,11 +230,10 @@ void MCLSeq::seq() { // Stopwatch sw; MDSeqTrack::md_trig_mask = 0; MDSeqTrack::load_machine_cache = 0; - MidiUartParent *uart_; for (uint8_t i = 0; i < num_md_tracks; i++) { md_tracks[i].seq(uart,uart2); md_arp_tracks[i].mute_state = md_tracks[i].mute_state; - md_arp_tracks[i].seq(uart_); + md_arp_tracks[i].seq(uart); } if (MDSeqTrack::md_trig_mask > 0) { From 8a9dd85e1c43f6080e33b1c1b2345b611ef0fd43 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 16 Jul 2024 18:04:49 +1000 Subject: [PATCH 018/133] Fixes --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 47 +++++++++++++----------- avr/cores/megacommand/MCL/MDSeqTrack.h | 2 +- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 9507d63ce..b25dbc66b 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -136,10 +136,10 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { } if (notes.count_down) { - notes.count_down--; - if (notes.count_down == 0) { - send_notes_off(); - } + notes.count_down--; + if (notes.count_down == 0) { + send_notes_off(); + } } if (record_mutes) { @@ -176,9 +176,11 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { } auto &step = steps[current_step]; uint8_t send_trig = trig_conditional(step.cond_id); + bool is_midi_machine = + (MD.kit.models[track_number] & 0xF0 == MID_01_MODEL); if (send_trig == TRIG_TRUE || (!step.cond_plock && send_trig != TRIG_ONESHOT)) { - if (MD.kit.models[track_number] & 0xF0 == MID_01_MODEL) { + if (is_midi_machine) { send_notes_off(); init_notes(); } @@ -188,8 +190,12 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { locks_slides_idx = lock_idx; } if (send_trig == TRIG_TRUE && step.trig) { - notes.count_down = (notes.len * timing_mid); - send_trig_inline(); + if (is_midi_machine) { + notes.count_down = (notes.len * timing_mid); + send_notes_on(); + } else { + send_trig_inline(); + } } } } @@ -445,9 +451,9 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uart2->sendProgramChange(channel, val); break; default: - bool t = p & 1; - uint8_t d = (p - 8) / 2; - ccs[d][t] = val; + bool t = p & 1; + uint8_t d = (p - 8) / 2; + ccs[d][t] = val; break; } @@ -455,10 +461,12 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, for (uint8_t n = 0; n < number_midi_cc; n++) { uint8_t a = ccs[n]; if (a) { - //0 = off - //1 = bank (0) - //2 = 2 - if (a == 1) { a = 0; }; + // 0 = off + // 1 = bank (0) + // 2 = 2 + if (a == 1) { + a = 0; + }; uart2->sendCC(channel, a, val); } } @@ -519,14 +527,9 @@ void MDSeqTrack::send_trig() { send_trig_inline(); } void MDSeqTrack::send_trig_inline() { mixer_page.trig(track_number); - if ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL) { - uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - send_notes_on(); - } else { - // MD.triggerTrack(track_number, 127, uart); - // Parallel trig: - SET_BIT16(MDSeqTrack::md_trig_mask, track_number); - } + // MD.triggerTrack(track_number, 127, uart); + // Parallel trig: + SET_BIT16(MDSeqTrack::md_trig_mask, track_number); } uint8_t MDSeqTrack::trig_conditional(uint8_t condition) { diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 7e320cce2..ad70f7cfc 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -122,7 +122,7 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { void load_cache(); void init_notes() { - // Copy 4 notes and notes.vel from kit to this structure; + // Copy 3 notes, len and vel from kit to notes structure; memcpy(¬es.note1, MD.kit.params[track_number], 5); notes.count_down = 0; } From c45c42bea1d874f5a0f9116a26fd92717cf2ea36 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 16 Jul 2024 18:32:25 +1000 Subject: [PATCH 019/133] needs to be uint16_t --- avr/cores/megacommand/MCL/MDSeqTrack.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index ad70f7cfc..401c94a50 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -23,7 +23,7 @@ class TrigNotes { uint8_t note3; uint8_t len; uint8_t vel; - uint8_t count_down; + uint16_t count_down; }; class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { From 02523db696eedfc6eade3d13d6d4b75a84bcf153 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 17 Jul 2024 15:06:01 +1000 Subject: [PATCH 020/133] this is probably not required as MD Note inteface is handled by TrigInterface --- avr/cores/megacommand/MCL/NoteInterface.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/NoteInterface.cpp b/avr/cores/megacommand/MCL/NoteInterface.cpp index 152b75703..2fde94dd2 100644 --- a/avr/cores/megacommand/MCL/NoteInterface.cpp +++ b/avr/cores/megacommand/MCL/NoteInterface.cpp @@ -124,7 +124,7 @@ void NoteInterfaceMidiEvents::onNoteOnCallback_Midi2(uint8_t *msg) { } void NoteInterfaceMidiEvents::onNoteOffCallback_Midi(uint8_t *msg) { // only accept input if device is not a MD - // MD input is handled by the NoteInterface object + // MD input is handled by the TrigInterface object if (midi_active_peering.get_device(UART1_PORT) == &MD) { return; } @@ -150,12 +150,14 @@ void NoteInterfaceMidiEvents::setup_callbacks() { if (state) { return; } +/* Midi.addOnNoteOnCallback( this, (midi_callback_ptr_t)&NoteInterfaceMidiEvents::onNoteOnCallback_Midi); Midi.addOnNoteOffCallback( this, (midi_callback_ptr_t)&NoteInterfaceMidiEvents::onNoteOffCallback_Midi); +*/ Midi2.addOnNoteOnCallback( this, (midi_callback_ptr_t)&NoteInterfaceMidiEvents::onNoteOnCallback_Midi2); @@ -170,12 +172,14 @@ void NoteInterfaceMidiEvents::remove_callbacks() { if (!state) { return; } +/* Midi.removeOnNoteOnCallback( this, (midi_callback_ptr_t)&NoteInterfaceMidiEvents::onNoteOnCallback_Midi); Midi.removeOnNoteOffCallback( this, (midi_callback_ptr_t)&NoteInterfaceMidiEvents::onNoteOffCallback_Midi); +*/ Midi2.removeOnNoteOnCallback( this, (midi_callback_ptr_t)&NoteInterfaceMidiEvents::onNoteOnCallback_Midi2); From 3591bdd606cb6666d2e1ce5e5e6a8cceabc1504d Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 17 Jul 2024 15:07:37 +1000 Subject: [PATCH 021/133] Added parameter resetting behaviour for note trigs which allows for manual trig via key press --- avr/cores/megacommand/MCL/MCLSeq.cpp | 15 ++++- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 84 ++++++++++++++---------- avr/cores/megacommand/MCL/MDSeqTrack.h | 11 ++++ avr/cores/megacommand/MCL/MixerPage.cpp | 19 ------ avr/cores/megacommand/MCL/MixerPage.h | 1 - 5 files changed, 74 insertions(+), 56 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index 0a6507710..ac294c3ec 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -282,7 +282,20 @@ void MCLSeq::seq() { } void MCLSeqMidiEvents::onNoteOnCallback_Midi(uint8_t *msg) { - mixer_page.onNoteOnCallback_Midi(msg); + uint8_t note_num = msg[1]; + uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); + + uint8_t n = MD.noteToTrack(msg[1]); + if (n < 16) { + bool is_midi_machine = ((MD.kit.models[n] & 0xF0) == MID_01_MODEL); + if (is_midi_machine) { + mcl_seq.md_tracks[n].send_notes(); + } + if (msg[0] != 153) { + mixer_page.disp_levels[n] = MD.kit.levels[n]; + } + + } } void MCLSeqMidiEvents::onNoteOffCallback_Midi(uint8_t *msg) {} diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index b25dbc66b..b89aeb295 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -177,7 +177,7 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { auto &step = steps[current_step]; uint8_t send_trig = trig_conditional(step.cond_id); bool is_midi_machine = - (MD.kit.models[track_number] & 0xF0 == MID_01_MODEL); + ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); if (send_trig == TRIG_TRUE || (!step.cond_plock && send_trig != TRIG_ONESHOT)) { if (is_midi_machine) { @@ -399,38 +399,14 @@ void MDSeqTrack::send_parameter_locks(uint8_t step, bool trig, send_parameter_locks_inline(step, trig, idx); } -void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, - uint16_t lock_idx) { - - const uint8_t number_midi_cc = 6; - uint8_t ccs[number_midi_cc][2]; - memset(ccs, 0, sizeof(ccs)); - - for (uint8_t c = 0; c < NUM_LOCKS; c++) { - bool lock_bit = steps[step].is_lock_bit(c); - bool lock_present = steps[step].is_lock(c); - bool send = false; - uint8_t val; - uint8_t p = locks_params[c] - 1; - if (locks_params[c]) { - if (lock_present) { - val = locks[lock_idx]; - send = true; - } else if (trig) { - val = MD.kit.params[track_number][p]; - send = true; - } - } - lock_idx += lock_bit; - if (send) { - if ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL && p < 21) { +void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t ccs[][2], bool send_ccs) { uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - switch (p) { + switch (param) { case 0: case 1: case 2: - ((uint8_t *)¬es)[p] = val; + ((uint8_t *)¬es)[param] = val; break; case 3: notes.len = val; @@ -451,15 +427,15 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uart2->sendProgramChange(channel, val); break; default: - bool t = p & 1; - uint8_t d = (p - 8) / 2; + bool t = param & 1; + uint8_t d = (param - 8) / 2; ccs[d][t] = val; break; } - if (c == NUM_LOCKS - 1) { + if (send_ccs) { for (uint8_t n = 0; n < number_midi_cc; n++) { - uint8_t a = ccs[n]; + uint8_t a = ccs[n][1]; if (a) { // 0 = off // 1 = bank (0) @@ -471,6 +447,34 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, } } } + +} + +void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, + uint16_t lock_idx) { + + uint8_t ccs[number_midi_cc][2]; + memset(ccs, 0, sizeof(ccs)); + + for (uint8_t c = 0; c < NUM_LOCKS; c++) { + bool lock_bit = steps[step].is_lock_bit(c); + bool lock_present = steps[step].is_lock(c); + bool send = false; + uint8_t val; + uint8_t p = locks_params[c] - 1; + if (locks_params[c]) { + if (lock_present) { + val = locks[lock_idx]; + send = true; + } else if (trig) { + val = MD.kit.params[track_number][p]; + send = true; + } + } + lock_idx += lock_bit; + if (send) { + if ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL && p < 21) { + process_note_locks(p, val, ccs, (c == (NUM_LOCKS - 1))); } else { @@ -483,11 +487,21 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, void MDSeqTrack::reset_params() { bool re_assign = false; + bool is_midi_machine = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); + uint8_t ccs[number_midi_cc][2]; + memset(ccs, 0, sizeof(ccs)); for (uint8_t c = 0; c < NUM_LOCKS; c++) { if (locks_params[c] > 0) { - MDTrack md_track; - md_track.get_machine_from_kit(track_number); - MD.assignMachineBulk(track_number, &md_track.machine, 255, 1, true); + if (is_midi_machine) { + uint8_t p = locks_params[c] - 1; + uint8_t val = MD.kit.params[track_number][p]; + process_note_locks(p, val, ccs, (c == (NUM_LOCKS - 1))); + } + else { + MDTrack md_track; + md_track.get_machine_from_kit(track_number); + MD.assignMachineBulk(track_number, &md_track.machine, 255, 1, true); + } return; } } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 401c94a50..349319842 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -38,6 +38,8 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { TrigNotes notes; + const uint8_t number_midi_cc = 6; + MDSeqTrack() : SeqSlideTrack() { active = MD_TRACK_TYPE; } ALWAYS_INLINE() void reset() { SeqSlideTrack::reset(); @@ -126,6 +128,13 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { memcpy(¬es.note1, MD.kit.params[track_number], 5); notes.count_down = 0; } + void process_note_locks(uint8_t param, uint8_t val, uint8_t ccs[][2], bool send_ccs); + void send_notes() { + if (notes.count_down) { send_notes_off(); } + init_notes(); + reset_params(); + send_notes_on(); + } void send_notes_on() { TrigNotes *n = ¬es; uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; @@ -155,7 +164,9 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { } n->note1 = 255; } + n->count_down = 0; } + }; #endif /* MDSEQTRACK_H__ */ diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 6711340c5..d12cc7c95 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -840,22 +840,3 @@ void MixerPage::onControlChangeCallback_Midi(uint8_t track, uint8_t track_param, mixer_page.set_display_mode(track_param); } -uint8_t MixerPage::note_to_trig(uint8_t note_num) { - uint8_t trig_num = 0; - for (uint8_t i = 0; i < sizeof(MD.global.drumMapping); i++) { - if (note_num == MD.global.drumMapping[i]) { - trig_num = i; - } - } - return trig_num; -} - -void MixerPage::onNoteOnCallback_Midi(uint8_t *msg) { - uint8_t note_num = msg[1]; - uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); - - uint8_t n = note_to_trig(msg[1]); - if (msg[0] != 153) { - mixer_page.disp_levels[n] = MD.kit.levels[n]; - } -} diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index 98480c6d4..28cc628fb 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -82,7 +82,6 @@ class MixerPage : public LightPage { void load_perf_locks(uint8_t state); void toggle_or_solo(bool solo = false); // Handled in MCLSeq - void onNoteOnCallback_Midi(uint8_t *msg); void onControlChangeCallback_Midi(uint8_t track, uint8_t track_param, uint8_t value); From e47d4f4e11ed2046dd45c839e215fafd1620e929 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 17 Jul 2024 20:41:07 +1000 Subject: [PATCH 022/133] Fixes note length, and compiler issue --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 143 +++++++++++++++-------- avr/cores/megacommand/MCL/MDSeqTrack.h | 39 +------ 2 files changed, 95 insertions(+), 87 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index b89aeb295..3cd992b44 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -180,7 +180,7 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); if (send_trig == TRIG_TRUE || (!step.cond_plock && send_trig != TRIG_ONESHOT)) { - if (is_midi_machine) { + if (is_midi_machine && send_trig == TRIG_TRUE && step.trig) { send_notes_off(); init_notes(); } @@ -399,55 +399,55 @@ void MDSeqTrack::send_parameter_locks(uint8_t step, bool trig, send_parameter_locks_inline(step, trig, idx); } -void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t ccs[][2], bool send_ccs) { - uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - - switch (param) { - case 0: - case 1: - case 2: - ((uint8_t *)¬es)[param] = val; - break; - case 3: - notes.len = val; - break; - case 4: - notes.vel = val; - break; - case 5: - uart2->sendPitchBend(channel, val); - break; - case 6: - uart2->sendCC(channel, 0x1, val); - break; - case 7: - uart2->sendChannelPressure(channel, val); - break; - case 20: - uart2->sendProgramChange(channel, val); - break; - default: - bool t = param & 1; - uint8_t d = (param - 8) / 2; - ccs[d][t] = val; - break; - } +void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, + uint8_t ccs[][2], bool send_ccs) { + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - if (send_ccs) { - for (uint8_t n = 0; n < number_midi_cc; n++) { - uint8_t a = ccs[n][1]; - if (a) { - // 0 = off - // 1 = bank (0) - // 2 = 2 - if (a == 1) { - a = 0; - }; - uart2->sendCC(channel, a, val); - } - } - } + switch (param) { + case 0: + case 1: + case 2: + ((uint8_t *)¬es)[param] = val; + break; + case 3: + notes.len = val; + break; + case 4: + notes.vel = val; + break; + case 5: + uart2->sendPitchBend(channel, val); + break; + case 6: + uart2->sendCC(channel, 0x1, val); + break; + case 7: + uart2->sendChannelPressure(channel, val); + break; + case 20: + uart2->sendProgramChange(channel, val); + break; + default: + bool t = param & 1; + uint8_t d = (param - 8) / 2; + ccs[d][t] = val; + break; + } + if (send_ccs) { + for (uint8_t n = 0; n < number_midi_cc; n++) { + uint8_t a = ccs[n][1]; + if (a) { + // 0 = off + // 1 = bank (0) + // 2 = 2 + if (a == 1) { + a = 0; + }; + uart2->sendCC(channel, a, val); + } + } + } } void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, @@ -474,7 +474,7 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, lock_idx += lock_bit; if (send) { if ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL && p < 21) { - process_note_locks(p, val, ccs, (c == (NUM_LOCKS - 1))); + process_note_locks(p, val, ccs, (c == (NUM_LOCKS - 1))); } else { @@ -496,8 +496,7 @@ void MDSeqTrack::reset_params() { uint8_t p = locks_params[c] - 1; uint8_t val = MD.kit.params[track_number][p]; process_note_locks(p, val, ccs, (c == (NUM_LOCKS - 1))); - } - else { + } else { MDTrack md_track; md_track.get_machine_from_kit(track_number); MD.assignMachineBulk(track_number, &md_track.machine, 255, 1, true); @@ -537,6 +536,48 @@ void MDSeqTrack::get_step_locks(uint8_t step, uint8_t *params, } } +void MDSeqTrack::send_notes() { + if (notes.count_down) { + send_notes_off(); + } + init_notes(); + reset_params(); + send_notes_on(); +} + +void MDSeqTrack::send_notes_on() { + TrigNotes *n = ¬es; + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + + if (n->note1 != 255) { + mixer_page.trig(track_number); + uart2->sendNoteOn(channel, n->note1, n->vel); + if (n->note2 != 64) { + uart2->sendNoteOn(channel, n->note1 + n->note2 - 64, n->vel); + } + if (n->note3 != 64) { + uart2->sendNoteOn(channel, n->note1 + n->note3 - 64, n->vel); + } + } +} + +void MDSeqTrack::send_notes_off() { + TrigNotes *n = ¬es; + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + + if (n->note1 != 255) { + uart2->sendNoteOff(channel, n->note1); + if (n->note2 != 64) { + uart2->sendNoteOff(channel, n->note1 + n->note2 - 64); + } + if (n->note3 != 64) { + uart2->sendNoteOff(channel, n->note1 + n->note3 - 64); + } + n->note1 = 255; + } + n->count_down = 0; +} + void MDSeqTrack::send_trig() { send_trig_inline(); } void MDSeqTrack::send_trig_inline() { diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 349319842..e6b123b6c 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -129,43 +129,10 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { notes.count_down = 0; } void process_note_locks(uint8_t param, uint8_t val, uint8_t ccs[][2], bool send_ccs); - void send_notes() { - if (notes.count_down) { send_notes_off(); } - init_notes(); - reset_params(); - send_notes_on(); - } - void send_notes_on() { - TrigNotes *n = ¬es; - uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - - if (n->note1 != 255) { - uart2->sendNoteOn(channel, n->note1, n->vel); - if (n->note2 != 63) { - uart2->sendNoteOn(channel, n->note1 + n->note2 - 63, n->vel); - } - if (n->note3 != 63) { - uart2->sendNoteOn(channel, n->note1 + n->note3 - 63, n->vel); - } - } - } - void send_notes_off() { - TrigNotes *n = ¬es; - uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - - if (n->note1 != 255) { - uart2->sendNoteOff(channel, n->note1); - if (n->note2 != 63) { - uart2->sendNoteOff(channel, n->note1 + n->note2 - 63); - } - if (n->note3 != 63) { - uart2->sendNoteOff(channel, n->note1 + n->note3 - 63); - } - n->note1 = 255; - } - n->count_down = 0; - } + void send_notes(); + void send_notes_on(); + void send_notes_off(); }; From 0f4eb54288d8098336924e19d8f97a797c9353aa Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 17 Jul 2024 20:49:39 +1000 Subject: [PATCH 023/133] send noteoff for MIDI machine notes on MidiStop --- avr/cores/megacommand/MCL/MCLSeq.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index ac294c3ec..6eebf1a78 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -148,6 +148,7 @@ void MCLSeq::onMidiStopCallback() { for (uint8_t i = 0; i < num_md_tracks; i++) { md_tracks[i].reset_params(); + md_tracks[i].send_notes_off(); md_tracks[i].locks_slides_recalc = 255; for (uint8_t c = 0; c < NUM_LOCKS; c++) { md_tracks[i].locks_slide_data[c].init(); From 877d318d868a6d68d2728eb40a7d38bde4a606b7 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 17 Jul 2024 20:50:30 +1000 Subject: [PATCH 024/133] Match original MD note length behaviour --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 3cd992b44..6e57e1249 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -191,7 +191,7 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { } if (send_trig == TRIG_TRUE && step.trig) { if (is_midi_machine) { - notes.count_down = (notes.len * timing_mid); + notes.count_down = (notes.len * timing_mid / 2); send_notes_on(); } else { send_trig_inline(); From a15311741071c66ce64644702c7754d3d9d4599c Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 17 Jul 2024 23:23:39 +1000 Subject: [PATCH 025/133] CC Locks working. CC parameter forward working --- avr/cores/megacommand/MCL/MCLSeq.cpp | 2 + avr/cores/megacommand/MCL/MDSeqTrack.cpp | 83 ++++++++++++++++-------- avr/cores/megacommand/MCL/MDSeqTrack.h | 5 +- 3 files changed, 62 insertions(+), 28 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index 6eebf1a78..9e6096df8 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -313,6 +313,8 @@ void MCLSeqMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { return; } + mcl_seq.md_tracks[track].onControlChangeCallback_Midi(track_param, value); + if (mcl.currentPage() == MIXER_PAGE) { mixer_page.onControlChangeCallback_Midi(track, track_param, value); } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 6e57e1249..c9b2bc86c 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -399,8 +399,27 @@ void MDSeqTrack::send_parameter_locks(uint8_t step, bool trig, send_parameter_locks_inline(step, trig, idx); } +void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + if (send_ccs) { + for (uint8_t n = 0; n < number_midi_cc; n++) { + uint8_t a = ccs[n * 2]; + if (a) { + uint8_t v = ccs[n * 2 + 1]; + // 0 = off + // 1 = bank (0) + // 2 = 2 + if (a == 1) { + a = 0; + }; + uart2->sendCC(channel, a, v); + } + } + } +} + void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, - uint8_t ccs[][2], bool send_ccs) { + uint8_t *ccs) { uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; switch (param) { @@ -416,7 +435,7 @@ void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, notes.vel = val; break; case 5: - uart2->sendPitchBend(channel, val); + uart2->sendPitchBend(channel, val << 7); break; case 6: uart2->sendCC(channel, 0x1, val); @@ -428,33 +447,21 @@ void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uart2->sendProgramChange(channel, val); break; default: - bool t = param & 1; - uint8_t d = (param - 8) / 2; - ccs[d][t] = val; + if (param < 20) { + uint8_t d = (param - 8); + ccs[d] = val; + } break; } - if (send_ccs) { - for (uint8_t n = 0; n < number_midi_cc; n++) { - uint8_t a = ccs[n][1]; - if (a) { - // 0 = off - // 1 = bank (0) - // 2 = 2 - if (a == 1) { - a = 0; - }; - uart2->sendCC(channel, a, val); - } - } - } } void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uint16_t lock_idx) { - uint8_t ccs[number_midi_cc][2]; - memset(ccs, 0, sizeof(ccs)); + uint8_t ccs[number_midi_cc * 2]; + memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + bool send_ccs = false; for (uint8_t c = 0; c < NUM_LOCKS; c++) { bool lock_bit = steps[step].is_lock_bit(c); @@ -474,7 +481,8 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, lock_idx += lock_bit; if (send) { if ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL && p < 21) { - process_note_locks(p, val, ccs, (c == (NUM_LOCKS - 1))); + process_note_locks(p, val, ccs); + send_ccs = p & 1 && p > 8; } else { @@ -483,19 +491,23 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, } } } + send_notes_ccs(ccs, send_ccs); + } void MDSeqTrack::reset_params() { bool re_assign = false; bool is_midi_machine = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); - uint8_t ccs[number_midi_cc][2]; - memset(ccs, 0, sizeof(ccs)); + uint8_t ccs[number_midi_cc * 2]; + bool send_ccs = false; + memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); for (uint8_t c = 0; c < NUM_LOCKS; c++) { if (locks_params[c] > 0) { if (is_midi_machine) { uint8_t p = locks_params[c] - 1; uint8_t val = MD.kit.params[track_number][p]; - process_note_locks(p, val, ccs, (c == (NUM_LOCKS - 1))); + process_note_locks(p, val, ccs); + send_ccs = p & 1 && p > 8; } else { MDTrack md_track; md_track.get_machine_from_kit(track_number); @@ -504,7 +516,7 @@ void MDSeqTrack::reset_params() { return; } } - + send_notes_ccs(ccs, send_ccs); /* for (uint8_t c = 0; c < NUM_LOCKS; c++) { bool send = false; @@ -578,6 +590,25 @@ void MDSeqTrack::send_notes_off() { n->count_down = 0; } +void MDSeqTrack::onControlChangeCallback_Midi(uint8_t track_param, + uint8_t value) { + bool is_midi_machine = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); + if (!is_midi_machine || MD.encoder_interface) { + return; + } + uint8_t ccs[number_midi_cc * 2]; + // memset(ccs, 0, sizeof(ccs)); + // Ignore notes, len and vel (those will be obtained from kit upon init_notes + if (track_param > 4 && track_param < 21) { + if (!(track_param & 1) && track_param > 7) { + return; + } // ignore cc destination + memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + process_note_locks(track_param, value, ccs); + send_notes_ccs(ccs, true); + } +} + void MDSeqTrack::send_trig() { send_trig_inline(); } void MDSeqTrack::send_trig_inline() { diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index e6b123b6c..d91a29752 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -128,12 +128,13 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { memcpy(¬es.note1, MD.kit.params[track_number], 5); notes.count_down = 0; } - void process_note_locks(uint8_t param, uint8_t val, uint8_t ccs[][2], bool send_ccs); - + void process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs); + void send_notes_ccs(uint8_t *ccs, bool send_ccs); void send_notes(); void send_notes_on(); void send_notes_off(); + void onControlChangeCallback_Midi(uint8_t track_param,uint8_t value); }; #endif /* MDSEQTRACK_H__ */ From ccdf11fab92dc54144ce1900489f2a770cbecb12 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 17 Jul 2024 23:32:39 +1000 Subject: [PATCH 026/133] program change forwarding --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index c9b2bc86c..ba407ecc1 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -600,7 +600,7 @@ void MDSeqTrack::onControlChangeCallback_Midi(uint8_t track_param, // memset(ccs, 0, sizeof(ccs)); // Ignore notes, len and vel (those will be obtained from kit upon init_notes if (track_param > 4 && track_param < 21) { - if (!(track_param & 1) && track_param > 7) { + if (!(track_param & 1) && track_param > 7 && track_param < 20) { return; } // ignore cc destination memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); From b67071398428793f6f325e4d9da03f7abf3d523f Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 18 Jul 2024 10:42:59 +1000 Subject: [PATCH 027/133] dont send all paramaters on CC change --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index ba407ecc1..91462e413 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -603,7 +603,9 @@ void MDSeqTrack::onControlChangeCallback_Midi(uint8_t track_param, if (!(track_param & 1) && track_param > 7 && track_param < 20) { return; } // ignore cc destination - memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + //memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + memset(ccs, 0, sizeof(ccs)); + if (track_param > 7) { ccs[track_param - 8 - 1] = MD.kit.params[track_number][track_param - 1]; } process_note_locks(track_param, value, ccs); send_notes_ccs(ccs, true); } From fba0dfcf62e239153141b3f50d9c41dfeb78834a Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 18 Jul 2024 12:54:21 +1000 Subject: [PATCH 028/133] Send all parameters on first trig/lock, keep track of PB,MW,AT,PROG and only transmit if they differ from last values --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 66 ++++++++++++++++++------ avr/cores/megacommand/MCL/MDSeqTrack.h | 8 +++ 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 91462e413..e58182739 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -176,11 +176,11 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { } auto &step = steps[current_step]; uint8_t send_trig = trig_conditional(step.cond_id); - bool is_midi_machine = + bool is_midi_model = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); if (send_trig == TRIG_TRUE || (!step.cond_plock && send_trig != TRIG_ONESHOT)) { - if (is_midi_machine && send_trig == TRIG_TRUE && step.trig) { + if (is_midi_model && send_trig == TRIG_TRUE && step.trig) { send_notes_off(); init_notes(); } @@ -190,7 +190,7 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { locks_slides_idx = lock_idx; } if (send_trig == TRIG_TRUE && step.trig) { - if (is_midi_machine) { + if (is_midi_model) { notes.count_down = (notes.len * timing_mid / 2); send_notes_on(); } else { @@ -435,20 +435,34 @@ void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, notes.vel = val; break; case 5: - uart2->sendPitchBend(channel, val << 7); + if (notes.pb != val) { + uart2->sendPitchBend(channel, val << 7); + notes.pb = val; + } break; case 6: - uart2->sendCC(channel, 0x1, val); + if (notes.mw != val) { + uart2->sendCC(channel, 0x1, val); + notes.mw = val; + } break; case 7: - uart2->sendChannelPressure(channel, val); + if (notes.at != val) { + uart2->sendChannelPressure(channel, val); + notes.at = val; + } break; case 20: + if (notes.prog != val) { uart2->sendProgramChange(channel, val); + notes.prog = val; + } break; default: if (param < 20) { uint8_t d = (param - 8); + //If the parameter is CC value and the CC dest is not yet set, use the kit value for CC dest + if ((d & 1) && ccs[d - 1] == 0) { ccs[d - 1] = MD.kit.params[track_number][param - 1]; } ccs[d] = val; } break; @@ -460,9 +474,17 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uint16_t lock_idx) { uint8_t ccs[number_midi_cc * 2]; - memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + uint8_t send_mask[20]; + if (notes.first_trig) { + //first note, we want to send all CCs regardless if they dont have locks. + memset(send_mask,0,sizeof(send_mask)); + memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + } + else { + memset(ccs,0,sizeof(ccs)); + } bool send_ccs = false; - + bool is_midi_model = (MD.kit.models[track_number] & 0xF0) == MID_01_MODEL; for (uint8_t c = 0; c < NUM_LOCKS; c++) { bool lock_bit = steps[step].is_lock_bit(c); bool lock_present = steps[step].is_lock(c); @@ -480,9 +502,10 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, } lock_idx += lock_bit; if (send) { - if ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL && p < 21) { + if (is_midi_model && p < 21) { process_note_locks(p, val, ccs); - send_ccs = p & 1 && p > 8; + send_mask[p] = 1; + send_ccs |= (p > 8) && (p & 1); } else { @@ -491,19 +514,29 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, } } } - send_notes_ccs(ccs, send_ccs); - + if (is_midi_model) { + if (notes.first_trig) { + const uint8_t params_to_check[] = {20, 5, 6, 7}; + for (uint8_t param : params_to_check) { + if (!send_mask[param]) { + process_note_locks(param, MD.kit.params[track_number][param], ccs); + } + } + notes.first_trig = false; + } + send_notes_ccs(ccs, send_ccs); + } } void MDSeqTrack::reset_params() { bool re_assign = false; - bool is_midi_machine = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); + bool is_midi_model = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); uint8_t ccs[number_midi_cc * 2]; bool send_ccs = false; memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); for (uint8_t c = 0; c < NUM_LOCKS; c++) { if (locks_params[c] > 0) { - if (is_midi_machine) { + if (is_midi_model) { uint8_t p = locks_params[c] - 1; uint8_t val = MD.kit.params[track_number][p]; process_note_locks(p, val, ccs); @@ -592,8 +625,8 @@ void MDSeqTrack::send_notes_off() { void MDSeqTrack::onControlChangeCallback_Midi(uint8_t track_param, uint8_t value) { - bool is_midi_machine = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); - if (!is_midi_machine || MD.encoder_interface) { + bool is_midi_model = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); + if (!is_midi_model || MD.encoder_interface) { return; } uint8_t ccs[number_midi_cc * 2]; @@ -605,7 +638,6 @@ void MDSeqTrack::onControlChangeCallback_Midi(uint8_t track_param, } // ignore cc destination //memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); memset(ccs, 0, sizeof(ccs)); - if (track_param > 7) { ccs[track_param - 8 - 1] = MD.kit.params[track_number][track_param - 1]; } process_note_locks(track_param, value, ccs); send_notes_ccs(ccs, true); } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index d91a29752..93aed995e 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -23,7 +23,14 @@ class TrigNotes { uint8_t note3; uint8_t len; uint8_t vel; + + uint8_t pb = 255; + uint8_t mw = 255; + uint8_t at = 255; + uint8_t prog = 255; + uint16_t count_down; + bool first_trig; }; class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { @@ -45,6 +52,7 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { SeqSlideTrack::reset(); oneshot_mask = 0; record_mutes = false; + notes.first_trig = true; send_notes_off(); } From aecec955a2f653b7759f65e280861a4c0add0dba Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 18 Jul 2024 12:54:42 +1000 Subject: [PATCH 029/133] overflow, resulting in graphics glitch seq page --- avr/cores/megacommand/MCL/SeqPage.cpp | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index d1f60a65d..e95e4cf6c 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -530,7 +530,7 @@ void SeqPage::draw_knob_conditional(uint8_t cond) { conditional_str(K, cond); draw_knob(0, "COND", K); } - +/* void SeqPage::conditional_str(char *str, uint8_t cond, bool is_md) { if (cond == 0) { strcpy(str, "L1"); @@ -558,6 +558,32 @@ void SeqPage::conditional_str(char *str, uint8_t cond, bool is_md) { } } } +*/ +void SeqPage::conditional_str(char *str, uint8_t cond, bool is_md) { + if (str == nullptr) return; + + if (cond == 0) { + str[0] = 'L'; str[1] = '1'; str[2] = '\0'; + } else { + if (cond > NUM_TRIG_CONDITIONS) { + cond -= NUM_TRIG_CONDITIONS; + } + + if (cond <= 8) { + str[0] = 'L'; str[1] = cond + '0'; str[2] = '\0'; + } else if (cond <= 13) { + static const uint8_t prob[5] = {1, 2, 5, 7, 9}; + str[0] = 'P'; str[1] = prob[cond - 9] + '0'; str[2] = '\0'; + } else if (cond == 14) { + str[0] = '1'; str[1] = 'S'; str[2] = '\0'; + } + + if (seq_param1.getValue() > NUM_TRIG_CONDITIONS) { + str[2] = is_md ? '+' : '^'; + str[3] = '\0'; + } + } +} void SeqPage::draw_knob_timing(uint8_t timing, uint8_t timing_mid) { char K[4]; From 106f6257a5bbe81ee50c89086f79396a38ed1ce5 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 18 Jul 2024 14:29:30 +1000 Subject: [PATCH 030/133] fix --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index e58182739..fa0eb9560 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -540,7 +540,7 @@ void MDSeqTrack::reset_params() { uint8_t p = locks_params[c] - 1; uint8_t val = MD.kit.params[track_number][p]; process_note_locks(p, val, ccs); - send_ccs = p & 1 && p > 8; + send_ccs |= p & 1 && p > 8; } else { MDTrack md_track; md_track.get_machine_from_kit(track_number); From 597c49c5efc53bdd77be74f118206b719d2db25c Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 18 Jul 2024 18:45:44 +1000 Subject: [PATCH 031/133] always send program change message for program change locks --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 6 +++--- avr/cores/megacommand/MCL/MDSeqTrack.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index fa0eb9560..8dec42322 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -419,7 +419,7 @@ void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { } void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, - uint8_t *ccs) { + uint8_t *ccs, bool is_lock) { uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; switch (param) { @@ -453,7 +453,7 @@ void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, } break; case 20: - if (notes.prog != val) { + if (notes.prog != val || is_lock) { uart2->sendProgramChange(channel, val); notes.prog = val; } @@ -503,7 +503,7 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, lock_idx += lock_bit; if (send) { if (is_midi_model && p < 21) { - process_note_locks(p, val, ccs); + process_note_locks(p, val, ccs, lock_present); send_mask[p] = 1; send_ccs |= (p > 8) && (p & 1); } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 93aed995e..624c60e17 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -136,7 +136,7 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { memcpy(¬es.note1, MD.kit.params[track_number], 5); notes.count_down = 0; } - void process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs); + void process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, bool is_lock = false); void send_notes_ccs(uint8_t *ccs, bool send_ccs); void send_notes(); void send_notes_on(); From 38ea07fb323a8a67289d1b09854c095d3e5c1550 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 18 Jul 2024 19:43:49 +1000 Subject: [PATCH 032/133] sending all CCs on first trig did not work --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 8dec42322..d0334c14e 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -475,15 +475,16 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uint8_t ccs[number_midi_cc * 2]; uint8_t send_mask[20]; + bool send_ccs = false; if (notes.first_trig) { //first note, we want to send all CCs regardless if they dont have locks. memset(send_mask,0,sizeof(send_mask)); memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + send_ccs = true; } else { memset(ccs,0,sizeof(ccs)); } - bool send_ccs = false; bool is_midi_model = (MD.kit.models[track_number] & 0xF0) == MID_01_MODEL; for (uint8_t c = 0; c < NUM_LOCKS; c++) { bool lock_bit = steps[step].is_lock_bit(c); @@ -927,6 +928,7 @@ void MDSeqTrack::clear_locks() { memset(locks, 0, sizeof(locks)); cur_event_idx = 0; + notes.first_trig = true; } void MDSeqTrack::clear_track(bool locks) { @@ -936,6 +938,7 @@ void MDSeqTrack::clear_track(bool locks) { clear_locks(); } memset(steps, 0, sizeof(steps)); + notes.first_trig = true; } void MDSeqTrack::merge_from_md(uint8_t track_number, MDPattern *pattern) { From 71ac3f524ffbff0f8a80df9e493231c9d3d814ff Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 18 Jul 2024 19:47:10 +1000 Subject: [PATCH 033/133] resetParams regression --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 67 +++++++++++------------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index d0334c14e..913089933 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -418,8 +418,8 @@ void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { } } -void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, - uint8_t *ccs, bool is_lock) { +void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, + bool is_lock) { uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; switch (param) { @@ -454,20 +454,22 @@ void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, break; case 20: if (notes.prog != val || is_lock) { - uart2->sendProgramChange(channel, val); - notes.prog = val; + uart2->sendProgramChange(channel, val); + notes.prog = val; } break; default: if (param < 20) { uint8_t d = (param - 8); - //If the parameter is CC value and the CC dest is not yet set, use the kit value for CC dest - if ((d & 1) && ccs[d - 1] == 0) { ccs[d - 1] = MD.kit.params[track_number][param - 1]; } + // If the parameter is CC value and the CC dest is not yet set, use the + // kit value for CC dest + if ((d & 1) && ccs[d - 1] == 0) { + ccs[d - 1] = MD.kit.params[track_number][param - 1]; + } ccs[d] = val; } break; } - } void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, @@ -477,13 +479,12 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uint8_t send_mask[20]; bool send_ccs = false; if (notes.first_trig) { - //first note, we want to send all CCs regardless if they dont have locks. - memset(send_mask,0,sizeof(send_mask)); + // first note, we want to send all CCs regardless if they dont have locks. + memset(send_mask, 0, sizeof(send_mask)); memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); send_ccs = true; - } - else { - memset(ccs,0,sizeof(ccs)); + } else { + memset(ccs, 0, sizeof(ccs)); } bool is_midi_model = (MD.kit.models[track_number] & 0xF0) == MID_01_MODEL; for (uint8_t c = 0; c < NUM_LOCKS; c++) { @@ -517,40 +518,32 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, } if (is_midi_model) { if (notes.first_trig) { - const uint8_t params_to_check[] = {20, 5, 6, 7}; - for (uint8_t param : params_to_check) { + const uint8_t params_to_check[] = {20, 5, 6, 7}; + for (uint8_t param : params_to_check) { if (!send_mask[param]) { - process_note_locks(param, MD.kit.params[track_number][param], ccs); + process_note_locks(param, MD.kit.params[track_number][param], ccs); } - } - notes.first_trig = false; + } + notes.first_trig = false; } send_notes_ccs(ccs, send_ccs); - } + } } void MDSeqTrack::reset_params() { bool re_assign = false; bool is_midi_model = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); - uint8_t ccs[number_midi_cc * 2]; - bool send_ccs = false; - memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); - for (uint8_t c = 0; c < NUM_LOCKS; c++) { - if (locks_params[c] > 0) { - if (is_midi_model) { - uint8_t p = locks_params[c] - 1; - uint8_t val = MD.kit.params[track_number][p]; - process_note_locks(p, val, ccs); - send_ccs |= p & 1 && p > 8; - } else { - MDTrack md_track; - md_track.get_machine_from_kit(track_number); - MD.assignMachineBulk(track_number, &md_track.machine, 255, 1, true); - } - return; - } + if (is_midi_model) { + uint8_t ccs[number_midi_cc * 2]; + bool send_ccs = true; + memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + send_notes_ccs(ccs, send_ccs); + } else { + MDTrack md_track; + md_track.get_machine_from_kit(track_number); + MD.assignMachineBulk(track_number, &md_track.machine, 255, 1, true); } - send_notes_ccs(ccs, send_ccs); + /* for (uint8_t c = 0; c < NUM_LOCKS; c++) { bool send = false; @@ -637,7 +630,7 @@ void MDSeqTrack::onControlChangeCallback_Midi(uint8_t track_param, if (!(track_param & 1) && track_param > 7 && track_param < 20) { return; } // ignore cc destination - //memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + // memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); memset(ccs, 0, sizeof(ccs)); process_note_locks(track_param, value, ccs); send_notes_ccs(ccs, true); From 0b778ded7ac72a24217d2a1b0b333d06b8b62c22 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 18 Jul 2024 20:05:20 +1000 Subject: [PATCH 034/133] Fix note trig for MID machines --- avr/cores/megacommand/Elektron/Elektron.h | 6 ------ avr/cores/megacommand/MCL/MCLSeq.cpp | 19 ++++++++++++++----- avr/cores/megacommand/MD/MD.cpp | 17 ++++------------- avr/cores/megacommand/MNM/MNM.cpp | 4 ---- 4 files changed, 18 insertions(+), 28 deletions(-) diff --git a/avr/cores/megacommand/Elektron/Elektron.h b/avr/cores/megacommand/Elektron/Elektron.h index 34036a4db..5f8aae0a1 100644 --- a/avr/cores/megacommand/Elektron/Elektron.h +++ b/avr/cores/megacommand/Elektron/Elektron.h @@ -335,10 +335,7 @@ class ElektronDevice : public MidiDevice { uint8_t currentBank; /** Stores the current pattern of the MD, usually set by the MDTask. **/ uint8_t currentPattern; - /** Set to true if the kit was loaded (usually set by MDTask). **/ - bool loadedKit; /** Set to true if the global was loaded (usually set by MDTask). **/ - bool loadedGlobal; bool encoder_interface; ElektronDevice( MidiClass* _midi, const char* _name, const uint8_t _id, @@ -349,9 +346,6 @@ class ElektronDevice : public MidiDevice { currentKit = -1; currentPattern = -1; - loadedKit = false; - loadedGlobal = false; - encoder_interface = false; } diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index 9e6096df8..5b6e941bf 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -285,7 +285,6 @@ void MCLSeq::seq() { void MCLSeqMidiEvents::onNoteOnCallback_Midi(uint8_t *msg) { uint8_t note_num = msg[1]; uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); - uint8_t n = MD.noteToTrack(msg[1]); if (n < 16) { bool is_midi_machine = ((MD.kit.models[n] & 0xF0) == MID_01_MODEL); @@ -299,7 +298,17 @@ void MCLSeqMidiEvents::onNoteOnCallback_Midi(uint8_t *msg) { } } -void MCLSeqMidiEvents::onNoteOffCallback_Midi(uint8_t *msg) {} +void MCLSeqMidiEvents::onNoteOffCallback_Midi(uint8_t *msg) { + uint8_t note_num = msg[1]; + uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); + uint8_t n = MD.noteToTrack(msg[1]); + if (n < 16) { + bool is_midi_machine = ((MD.kit.models[n] & 0xF0) == MID_01_MODEL); + if (is_midi_machine) { + mcl_seq.md_tracks[n].send_notes_off(); + } + } +} void MCLSeqMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); @@ -382,10 +391,10 @@ void MCLSeqMidiEvents::setup_callbacks() { Midi.addOnNoteOnCallback( this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOnCallback_Midi); - /* - Midi.addOnNoteOffCallback( + + Midi.addOnNoteOffCallback( this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOffCallback_Midi); - */ + update_params = true; Midi.addOnControlChangeCallback( this, diff --git a/avr/cores/megacommand/MD/MD.cpp b/avr/cores/megacommand/MD/MD.cpp index dbebeadf4..5cb4b8f99 100644 --- a/avr/cores/megacommand/MD/MD.cpp +++ b/avr/cores/megacommand/MD/MD.cpp @@ -274,16 +274,11 @@ MCLGIF *MDClass::gif() { return R.icons_logo->machinedrum_gif; } uint8_t *MDClass::gif_data() { return R.icons_logo->machinedrum_gif_data; } uint8_t MDClass::noteToTrack(uint8_t pitch) { - uint8_t i; - if (MD.loadedGlobal) { - for (i = 0; i < sizeof(MD.global.drumMapping); i++) { - if (pitch == MD.global.drumMapping[i]) + for (uint8_t i = 0; i < sizeof(MD.global.drumMapping); i++) { + if (pitch == MD.global.drumMapping[i]) return i; } - return 128; - } else { - return 128; - } + return 128; } void MDClass::parseCC(uint8_t channel, uint8_t cc, uint8_t *track, @@ -858,11 +853,7 @@ void MDClass::getPatternName(uint8_t pattern, char str[5]) { } bool MDClass::checkParamSettings() { - if (loadedGlobal) { - return (MD.global.baseChannel <= 12); - } else { - return false; - } + return (MD.global.baseChannel <= 12); } bool MDClass::checkTriggerSettings() { return false; } diff --git a/avr/cores/megacommand/MNM/MNM.cpp b/avr/cores/megacommand/MNM/MNM.cpp index 1ffa07572..c8a67e675 100644 --- a/avr/cores/megacommand/MNM/MNM.cpp +++ b/avr/cores/megacommand/MNM/MNM.cpp @@ -238,9 +238,7 @@ void MNMClass::setMidiTrack(uint8_t track) { setStatus(0x23, track); } void MNMClass::revertToCurrentKit(bool reloadKit) { if (!reloadKit) { - if (loadedKit) { MNM.loadKit(MNM.currentKit); - } } else { uint8_t kit = getCurrentKit(500); if (kit != 255) { @@ -251,9 +249,7 @@ void MNMClass::revertToCurrentKit(bool reloadKit) { void MNMClass::revertToTrack(uint8_t track, bool reloadKit) { if (!reloadKit) { - if (loadedKit) { setMachine(track, track); - } } } From 6b74f442bfbe5fde09252fba06654f34ef964fa4 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 18 Jul 2024 20:11:19 +1000 Subject: [PATCH 035/133] wip version --- avr/cores/megacommand/MCL/MCL.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index c8fc545e7..806955d9c 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -17,7 +17,7 @@ #include "Fonts/TomThumb.h" #define VERSION 4052 -#define VERSION_STR "D4.52" +#define VERSION_STR "E4.52" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 From ad86b225a96f2a084b325994af8e9fdd6df76e7b Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 18 Jul 2024 20:35:51 +1000 Subject: [PATCH 036/133] illuminate trig led for MID machines --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 913089933..c96c086fd 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -193,9 +193,9 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { if (is_midi_model) { notes.count_down = (notes.len * timing_mid / 2); send_notes_on(); - } else { - send_trig_inline(); } + send_trig_inline(); + } } } From b20f07e8acbe72b13e26862c16f345efcc643208 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 19 Jul 2024 00:24:34 +1000 Subject: [PATCH 037/133] refactor, needs testing --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 120 ++++++++++++----------- avr/cores/megacommand/MCL/MDSeqTrack.h | 7 +- 2 files changed, 65 insertions(+), 62 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index c96c086fd..5b0ada7ae 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -195,7 +195,6 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { send_notes_on(); } send_trig_inline(); - } } } @@ -403,16 +402,43 @@ void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; if (send_ccs) { for (uint8_t n = 0; n < number_midi_cc; n++) { - uint8_t a = ccs[n * 2]; - if (a) { - uint8_t v = ccs[n * 2 + 1]; - // 0 = off - // 1 = bank (0) - // 2 = 2 - if (a == 1) { - a = 0; - }; - uart2->sendCC(channel, a, v); + switch (n) { + case 0: + if (ccs[0] != 255) { + uart2->sendPitchBend(channel, ccs[0] << 7); + } + break; + case 1: + if (ccs[1] != 255) { + uart2->sendCC(channel, 0x1, ccs[1]); + } + break; + case 2: + if (ccs[2] != 255) { + uart2->sendChannelPressure(channel, ccs[2]); + } + break; + case 15: + if (ccs[15] != 255) { + notes.prog = ccs[15]; + uart2->sendProgramChange(channel, ccs[15]); + } + break; + default: + if (!(n & 1)) continue; + uint8_t a = ccs[n - 1]; + if (a > 0 && a != 255) { + uint8_t v = ccs[n]; + if (v == 255) continue; + // 0 = off + // 1 = bank (0) + // 2 = 2 + if (a == 1) { + a = 0; + }; + uart2->sendCC(channel, a, v); + break; + } } } } @@ -421,52 +447,39 @@ void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, bool is_lock) { uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - + uint8_t i = param - 5; switch (param) { case 0: case 1: case 2: - ((uint8_t *)¬es)[param] = val; - break; case 3: - notes.len = val; - break; case 4: - notes.vel = val; + //note values are set via init_notes initially. + ((uint8_t *)¬es)[param] = val; + //ccs[param] = val; not required. break; case 5: - if (notes.pb != val) { - uart2->sendPitchBend(channel, val << 7); - notes.pb = val; - } - break; case 6: - if (notes.mw != val) { - uart2->sendCC(channel, 0x1, val); - notes.mw = val; - } - break; case 7: - if (notes.at != val) { - uart2->sendChannelPressure(channel, val); - notes.at = val; - } + ccs[i] = val; break; case 20: if (notes.prog != val || is_lock) { - uart2->sendProgramChange(channel, val); - notes.prog = val; + ccs[i] = val; + } + else { + ccs[i] = 255; } break; default: if (param < 20) { - uint8_t d = (param - 8); // If the parameter is CC value and the CC dest is not yet set, use the // kit value for CC dest - if ((d & 1) && ccs[d - 1] == 0) { - ccs[d - 1] = MD.kit.params[track_number][param - 1]; + uint8_t j = i - 1; + if ((param & 1) && ccs[j] == 255) { + ccs[j] = MD.kit.params[track_number][param - 1]; } - ccs[d] = val; + ccs[i] = val; } break; } @@ -475,16 +488,17 @@ void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uint16_t lock_idx) { - uint8_t ccs[number_midi_cc * 2]; - uint8_t send_mask[20]; + uint8_t ccs[midi_cc_array_size]; bool send_ccs = false; if (notes.first_trig) { // first note, we want to send all CCs regardless if they dont have locks. - memset(send_mask, 0, sizeof(send_mask)); - memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + memcpy(ccs, &MD.kit.params[track_number][5], sizeof(ccs)); + //prevent re-transmission of program change. + process_note_locks(20, MD.kit.params[track_number][20],ccs); send_ccs = true; + notes.first_trig = false; } else { - memset(ccs, 0, sizeof(ccs)); + memset(ccs, 255, sizeof(ccs)); } bool is_midi_model = (MD.kit.models[track_number] & 0xF0) == MID_01_MODEL; for (uint8_t c = 0; c < NUM_LOCKS; c++) { @@ -506,8 +520,7 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, if (send) { if (is_midi_model && p < 21) { process_note_locks(p, val, ccs, lock_present); - send_mask[p] = 1; - send_ccs |= (p > 8) && (p & 1); + send_ccs |= (p > 4 && p < 8) | (p > 8) && (p & 1) | (p == 20); } else { @@ -517,15 +530,6 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, } } if (is_midi_model) { - if (notes.first_trig) { - const uint8_t params_to_check[] = {20, 5, 6, 7}; - for (uint8_t param : params_to_check) { - if (!send_mask[param]) { - process_note_locks(param, MD.kit.params[track_number][param], ccs); - } - } - notes.first_trig = false; - } send_notes_ccs(ccs, send_ccs); } } @@ -534,9 +538,11 @@ void MDSeqTrack::reset_params() { bool re_assign = false; bool is_midi_model = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); if (is_midi_model) { - uint8_t ccs[number_midi_cc * 2]; + uint8_t ccs[midi_cc_array_size]; bool send_ccs = true; - memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); + memcpy(ccs, &MD.kit.params[track_number][5], sizeof(ccs)); + ccs[15] = 255; //disable program change + //process_note_locks(20 - 5, MD.kit.params[track_number][20],ccs); send_notes_ccs(ccs, send_ccs); } else { MDTrack md_track; @@ -623,7 +629,7 @@ void MDSeqTrack::onControlChangeCallback_Midi(uint8_t track_param, if (!is_midi_model || MD.encoder_interface) { return; } - uint8_t ccs[number_midi_cc * 2]; + uint8_t ccs[midi_cc_array_size]; // memset(ccs, 0, sizeof(ccs)); // Ignore notes, len and vel (those will be obtained from kit upon init_notes if (track_param > 4 && track_param < 21) { @@ -631,7 +637,7 @@ void MDSeqTrack::onControlChangeCallback_Midi(uint8_t track_param, return; } // ignore cc destination // memcpy(ccs, &MD.kit.params[track_number][8], sizeof(ccs)); - memset(ccs, 0, sizeof(ccs)); + memset(ccs, 255, sizeof(ccs)); process_note_locks(track_param, value, ccs); send_notes_ccs(ccs, true); } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 624c60e17..6f88b7af0 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -23,10 +23,6 @@ class TrigNotes { uint8_t note3; uint8_t len; uint8_t vel; - - uint8_t pb = 255; - uint8_t mw = 255; - uint8_t at = 255; uint8_t prog = 255; uint16_t count_down; @@ -45,7 +41,8 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { TrigNotes notes; - const uint8_t number_midi_cc = 6; + const uint8_t number_midi_cc = 6 * 2 + 4; + const uint8_t midi_cc_array_size = 6 * 2 + 4; MDSeqTrack() : SeqSlideTrack() { active = MD_TRACK_TYPE; } ALWAYS_INLINE() void reset() { From 689a38022d06397b143f4691b9b8d52f4b57da18 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 19 Jul 2024 11:13:03 +1000 Subject: [PATCH 038/133] first trig only enabled on load. all encoders settings including program change are sent on first trig. --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 8 ++++---- avr/cores/megacommand/MCL/MDSeqTrack.h | 3 +-- avr/cores/megacommand/MCL/MDTrack.cpp | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 5b0ada7ae..9ce69b5d9 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -494,9 +494,8 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, // first note, we want to send all CCs regardless if they dont have locks. memcpy(ccs, &MD.kit.params[track_number][5], sizeof(ccs)); //prevent re-transmission of program change. - process_note_locks(20, MD.kit.params[track_number][20],ccs); + //process_note_locks(20, MD.kit.params[track_number][20],ccs); send_ccs = true; - notes.first_trig = false; } else { memset(ccs, 255, sizeof(ccs)); } @@ -519,7 +518,7 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, lock_idx += lock_bit; if (send) { if (is_midi_model && p < 21) { - process_note_locks(p, val, ccs, lock_present); + process_note_locks(p, val, ccs, true); send_ccs |= (p > 4 && p < 8) | (p > 8) && (p & 1) | (p == 20); } @@ -542,7 +541,8 @@ void MDSeqTrack::reset_params() { bool send_ccs = true; memcpy(ccs, &MD.kit.params[track_number][5], sizeof(ccs)); ccs[15] = 255; //disable program change - //process_note_locks(20 - 5, MD.kit.params[track_number][20],ccs); + //notes.prog = MD.kit.params[track_number][20]; + //process_note_locks(20, MD.kit.params[track_number][20],ccs); send_notes_ccs(ccs, send_ccs); } else { MDTrack md_track; diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 6f88b7af0..fc7c09d09 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -26,7 +26,7 @@ class TrigNotes { uint8_t prog = 255; uint16_t count_down; - bool first_trig; + bool first_trig = false; }; class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { @@ -49,7 +49,6 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { SeqSlideTrack::reset(); oneshot_mask = 0; record_mutes = false; - notes.first_trig = true; send_notes_off(); } diff --git a/avr/cores/megacommand/MCL/MDTrack.cpp b/avr/cores/megacommand/MCL/MDTrack.cpp index 7004dde62..7e3a50d13 100644 --- a/avr/cores/megacommand/MCL/MDTrack.cpp +++ b/avr/cores/megacommand/MCL/MDTrack.cpp @@ -120,6 +120,7 @@ void MDTrack::load_seq_data(SeqTrack *seq_track) { load_link_data(seq_track); md_seq_track->clear_mutes(); md_seq_track->set_length(md_seq_track->length); + md_seq_track->notes.first_trig = true; } void MDTrack::scale_seq_vol(float scale) { From a408e9b8b86167adb836f419ef42c198d7bb1701 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 19 Jul 2024 11:35:54 +1000 Subject: [PATCH 039/133] optimise --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 9ce69b5d9..22c1ecde8 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -402,34 +402,26 @@ void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; if (send_ccs) { for (uint8_t n = 0; n < number_midi_cc; n++) { - switch (n) { + if (ccs[n] == 255) continue; + switch (n) { case 0: - if (ccs[0] != 255) { uart2->sendPitchBend(channel, ccs[0] << 7); - } break; case 1: - if (ccs[1] != 255) { uart2->sendCC(channel, 0x1, ccs[1]); - } break; case 2: - if (ccs[2] != 255) { uart2->sendChannelPressure(channel, ccs[2]); - } break; case 15: - if (ccs[15] != 255) { notes.prog = ccs[15]; uart2->sendProgramChange(channel, ccs[15]); - } break; default: if (!(n & 1)) continue; uint8_t a = ccs[n - 1]; if (a > 0 && a != 255) { uint8_t v = ccs[n]; - if (v == 255) continue; // 0 = off // 1 = bank (0) // 2 = 2 From 861181499640385ce507f09a8f58a01e5b57acb3 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 19 Jul 2024 13:56:39 +1000 Subject: [PATCH 040/133] Fix old regression in device selection from SeqPages --- avr/cores/megacommand/MCL/SeqPage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index e95e4cf6c..1cae897c5 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -392,9 +392,9 @@ bool SeqPage::handleEvent(gui_event_t *event) { if (show_seq_menu) { row_func = seq_menu_page.menu.get_row_function(seq_menu_page.encoders[1]->cur); - MidiDevice* old_dev = opt_midi_device_capture; - opt_midi_device_capture = midi_active_peering.get_device(mcl_cfg.seq_dev); - if (old_dev == opt_midi_device_capture) { + MidiDevice* old_dev = midi_device; + midi_device = midi_active_peering.get_device(mcl_cfg.seq_dev); + if (old_dev == midi_device) { opt_speed_handler(); opt_length_handler(); opt_channel_handler(); From 27d0db1770033172b3efeed2ec4b5c4181e55d73 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 19 Jul 2024 16:57:13 +1000 Subject: [PATCH 041/133] simplify note on/off callbacks --- avr/cores/megacommand/MCL/MCLSeq.cpp | 33 +++++++++------------------- avr/cores/megacommand/MCL/MCLSeq.h | 3 ++- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index 5b6e941bf..f544a292a 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -282,34 +282,24 @@ void MCLSeq::seq() { } } -void MCLSeqMidiEvents::onNoteOnCallback_Midi(uint8_t *msg) { +void MCLSeqMidiEvents::onNoteCallback_Midi(uint8_t *msg) { uint8_t note_num = msg[1]; uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); uint8_t n = MD.noteToTrack(msg[1]); if (n < 16) { bool is_midi_machine = ((MD.kit.models[n] & 0xF0) == MID_01_MODEL); if (is_midi_machine) { - mcl_seq.md_tracks[n].send_notes(); + if (msg[2]) {mcl_seq.md_tracks[n].send_notes(); } + //velocity 0 == NoteOff + else { mcl_seq.md_tracks[n].send_notes_off(); } + } - if (msg[0] != 153) { + if (msg[0] != 153 && msg[2]) { mixer_page.disp_levels[n] = MD.kit.levels[n]; } } } - -void MCLSeqMidiEvents::onNoteOffCallback_Midi(uint8_t *msg) { - uint8_t note_num = msg[1]; - uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); - uint8_t n = MD.noteToTrack(msg[1]); - if (n < 16) { - bool is_midi_machine = ((MD.kit.models[n] & 0xF0) == MID_01_MODEL); - if (is_midi_machine) { - mcl_seq.md_tracks[n].send_notes_off(); - } - } -} - void MCLSeqMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); uint8_t param = msg[1]; @@ -390,10 +380,9 @@ void MCLSeqMidiEvents::setup_callbacks() { } Midi.addOnNoteOnCallback( - this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOnCallback_Midi); - + this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteCallback_Midi); Midi.addOnNoteOffCallback( - this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOffCallback_Midi); + this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteCallback_Midi); update_params = true; Midi.addOnControlChangeCallback( @@ -414,11 +403,9 @@ void MCLSeqMidiEvents::remove_callbacks() { } Midi.removeOnNoteOnCallback( - this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOnCallback_Midi); - /* + this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteCallback_Midi); Midi.removeOnNoteOffCallback( - this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOffCallback_Midi); - */ + this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteCallback_Midi); Midi.removeOnControlChangeCallback( this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onControlChangeCallback_Midi); diff --git a/avr/cores/megacommand/MCL/MCLSeq.h b/avr/cores/megacommand/MCL/MCLSeq.h index 869441711..10336deba 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.h +++ b/avr/cores/megacommand/MCL/MCLSeq.h @@ -33,7 +33,8 @@ class MCLSeqMidiEvents : public MidiCallback { void remove_callbacks(); uint8_t note_to_trig(uint8_t); - void onNoteOnCallback_Midi(uint8_t *msg); + void onNoteCallback_Midi(uint8_t *msg); + void onNoteOffCallback_Midi(uint8_t *msg); void onControlChangeCallback_Midi(uint8_t *msg); void onControlChangeCallback_Midi2(uint8_t *msg); From ce94058533d33547dc268eeee60401886b1b342f Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 19 Jul 2024 16:58:06 +1000 Subject: [PATCH 042/133] Chromatic support for MID machines --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 3 ++- avr/cores/megacommand/MCL/MDSeqTrack.h | 2 +- avr/cores/megacommand/MCL/SeqPage.cpp | 3 +++ avr/cores/megacommand/MCL/SeqPage.h | 1 + avr/cores/megacommand/MCL/SeqPtcPage.cpp | 20 ++++++++++++++++++-- avr/cores/megacommand/MCL/SeqStepPage.cpp | 20 ++++++++++++++------ 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 22c1ecde8..e3e6f8c57 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -573,11 +573,12 @@ void MDSeqTrack::get_step_locks(uint8_t step, uint8_t *params, } } -void MDSeqTrack::send_notes() { +void MDSeqTrack::send_notes(uint8_t note1) { if (notes.count_down) { send_notes_off(); } init_notes(); + if (note1 != 255) { notes.note1 = note1; } reset_params(); send_notes_on(); } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index fc7c09d09..aba38624d 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -134,7 +134,7 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { } void process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, bool is_lock = false); void send_notes_ccs(uint8_t *ccs, bool send_ccs); - void send_notes(); + void send_notes(uint8_t first_note = 255); void send_notes_on(); void send_notes_off(); diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index 1cae897c5..ab9c05bef 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -30,6 +30,8 @@ uint16_t SeqPage::mute_mask = 0; uint8_t SeqPage::step_select = 255; +bool SeqPage::is_midi_model = false; + uint32_t SeqPage::last_md_model = 255; uint8_t opt_speed = 1; @@ -232,6 +234,7 @@ void SeqPage::select_track(MidiDevice *device, uint8_t track, bool send) { DEBUG_PRINTLN(track); if (track >= NUM_MD_TRACKS) { return; } last_md_track = track; + is_midi_model = ((MD.kit.models[last_md_track] & 0xF0) == MID_01_MODEL); auto &active_track = mcl_seq.md_tracks[last_md_track]; MD.sync_seqtrack(active_track.length, active_track.speed, active_track.step_count); diff --git a/avr/cores/megacommand/MCL/SeqPage.h b/avr/cores/megacommand/MCL/SeqPage.h index a6d79f966..5bc94607f 100644 --- a/avr/cores/megacommand/MCL/SeqPage.h +++ b/avr/cores/megacommand/MCL/SeqPage.h @@ -100,6 +100,7 @@ class SeqPage : public LightPage { static uint8_t last_rec_event; static uint8_t last_step; static uint32_t last_md_model; + static bool is_midi_model; static bool recording; static uint16_t mute_mask; diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index cd0cde79b..806866073 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -415,7 +415,16 @@ void SeqPtcPage::trig_md(uint8_t note_num, uint8_t track_number, uint8_t channel } uint8_t next_track = get_next_voice(note_num, track_number, channel_event); + if (next_track > 15) { return; } + uint8_t machine_pitch = get_machine_pitch(next_track, note_num, fine_tune); + bool is_midi_model_ = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); + if (is_midi_model_) { + machine_pitch = note_num; + mcl_seq.md_tracks[track_number].send_notes_off(); + mcl_seq.md_tracks[track_number].send_notes(machine_pitch); + goto record; + } if (machine_pitch == 255) { return; } @@ -423,7 +432,7 @@ void SeqPtcPage::trig_md(uint8_t note_num, uint8_t track_number, uint8_t channel MD.setTrackParam(next_track, 0, machine_pitch, uart_); MD.triggerTrack(next_track, 127, uart_); mixer_page.trig(next_track); - + record: if ((recording) && (MidiClock.state == 2)) { reset_undo(); mcl_seq.md_tracks[next_track].record_track(127); @@ -814,7 +823,14 @@ void SeqPtcMidiEvents::note_off(uint8_t *msg, uint8_t channel_event) { pitch = seq_ptc_page.process_ext_event(note_num, false, channel); uint8_t n = seq_ptc_page.find_arp_track(channel_event); seq_ptc_page.render_arp(false, SeqPage::midi_device, n); - + if (pitch == 255) { return; } + ArpSeqTrack *arp_track = &mcl_seq.md_arp_tracks[n]; + bool is_midi_model_ = ((MD.kit.models[n] & 0xF0) == MID_01_MODEL);; + if (is_midi_model_) { + if (!arp_track->enabled || (MidiClock.state != 2)) { + mcl_seq.md_tracks[n].send_notes_off(); + } + } return; } diff --git a/avr/cores/megacommand/MCL/SeqStepPage.cpp b/avr/cores/megacommand/MCL/SeqStepPage.cpp index acea62933..95ebee2e3 100644 --- a/avr/cores/megacommand/MCL/SeqStepPage.cpp +++ b/avr/cores/megacommand/MCL/SeqStepPage.cpp @@ -6,11 +6,15 @@ void SeqStepPage::setup() { SeqPage::setup(); } void SeqStepPage::config() { + bool is_midi_model = ((MD.kit.models[last_md_track] & 0xF0) == MID_01_MODEL); tuning_t const *tuning = MD.getKitModelTuning(last_md_track); if (tuning) { seq_param4.max = tuning->len - 1 + tuning->base; - } else { + } else if (is_midi_model) { + seq_param4.max = 127; + } + else { seq_param4.max = 1; } seq_param4.cur = 0; @@ -130,8 +134,9 @@ void SeqStepPage::display() { draw_knob(2, "LEN", K); } tuning_t const *tuning = MD.getKitModelTuning(last_md_track); + bool is_ptc = ((MD.kit.models[last_md_track] & 0xF0) == MID_01_MODEL) || tuning != NULL; if (show_pitch) { - if (tuning != NULL) { + if (is_ptc) { strcpy(K, "--"); if (seq_param4.cur != 0) { // uint8_t base = tuning->base; @@ -151,7 +156,7 @@ void SeqStepPage::display() { if (mcl_gui.show_encoder_value(&seq_param4) && (seq_param4.cur > 0) && (note_interface.notes_count_on() > 0) && (!show_seq_menu) && - (tuning != NULL) && !(recording)) { + (is_ptc) && !(recording)) { uint64_t note_mask[2] = {}; uint8_t note = seq_param4.cur; // + tuning->base; SET_BIT64(note_mask, note); @@ -243,12 +248,12 @@ void SeqStepPage::loop() { break; } if (seq_param4.hasChanged() && (seq_param4.cur > 0) && - (last_md_track < NUM_MD_TRACKS) && (tuning != NULL)) { + (last_md_track < NUM_MD_TRACKS) && (tuning != NULL || is_midi_model)) { uint8_t base = tuning->base; uint8_t note_num = seq_param4.cur; uint8_t machine_pitch = seq_ptc_page.get_machine_pitch(last_md_track, note_num); - + if (is_midi_model) { machine_pitch = note_num; } if (machine_pitch != MD.kit.params[last_md_track][0]) { active_track.set_track_pitch(step, machine_pitch); seq_step_page.encoders_used_clock[3] = slowclock; // indicate that encoder has changed. @@ -376,8 +381,11 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { pitch_param = 255; } else if (tuning) { */ - if (tuning) { + if (tuning || is_midi_model) { uint8_t note_num = seq_ptc_page.get_note_from_machine_pitch(pitch); + if (is_midi_model) { + note_num = pitch; + } if (note_num == 255) { seq_param4.cur = 0; } else { From 4d4cfb3ffe0d411e5344090eb737f21e22779e4f Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 19 Jul 2024 16:59:05 +1000 Subject: [PATCH 043/133] Makefile improvements for enabling/disabling firmware checksum --- avr/cores/megacommand/Makefile | 10 +++++- avr/cores/megacommand/main.cpp | 3 +- avr/cores/megacommand/make_and_upload.sh | 42 +++++++++++++++++++++--- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/avr/cores/megacommand/Makefile b/avr/cores/megacommand/Makefile index 0ab45ece6..2fb5dcff3 100644 --- a/avr/cores/megacommand/Makefile +++ b/avr/cores/megacommand/Makefile @@ -31,12 +31,20 @@ UISP=uisp AVR_ARCH = atmega2560 F_CPU = 16000000L +CHECKSUM ?= 0 INOFILES=$(wildcard *.pde) OPTIM_FLAGS = -Os --short-enums WARN_FLAGS = -Wall -Wextra -Wdouble-promotion -COMPILE_FLAGS = -c $(OPTIM_FLAGS) $(WARN_FLAGS) -MMD +BASE_COMPILE_FLAGS = -c $(OPTIM_FLAGS) $(WARN_FLAGS) -MMD + +ifeq ($(CHECKSUM),1) + COMPILE_FLAGS = $(BASE_COMPILE_FLAGS) -DCHECKSUM +else + COMPILE_FLAGS = $(BASE_COMPILE_FLAGS) +endif + FEATURE_FLAGS = -ffunction-sections -fdata-sections -flto=jobserver -fshort-enums LINK_FLAGS = -lm -Wl,--gc-sections,--defsym=__stack=0x801FA1,--section-start,.sdcard=0x801FA2,--section-start,.data=0x802200,--defsym=__heap_end=0x80ffff,--relax ARCH_FLAGS = -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR diff --git a/avr/cores/megacommand/main.cpp b/avr/cores/megacommand/main.cpp index 1c0f8ec6a..3e6027af3 100644 --- a/avr/cores/megacommand/main.cpp +++ b/avr/cores/megacommand/main.cpp @@ -48,7 +48,7 @@ void my_init_ram(void) { //Leds DDRE |= _BV(PE4) | _BV(PE5); - return; + #if CHECKSUM //SRAM tests volatile uint8_t *ptr; @@ -104,6 +104,7 @@ void my_init_ram(void) { setLed(); setLed2(); } + #endif } uint8_t tcnt2; diff --git a/avr/cores/megacommand/make_and_upload.sh b/avr/cores/megacommand/make_and_upload.sh index e9861ffae..e004c369c 100755 --- a/avr/cores/megacommand/make_and_upload.sh +++ b/avr/cores/megacommand/make_and_upload.sh @@ -1,13 +1,40 @@ #!/bin/bash AVR_DIR=$(cd "../../../../tools/avr"; pwd) DEV=/dev/$(ls /dev | grep usb | grep cu | tail -n 1) +# Parse command line arguments + +run_checksum=false +no_upload=false +while getopts "c" opt; do + case $opt in + c) + run_checksum=true + ;; + n) + no_upload=true + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + esac +done + + rm main.hex -make -j8 +if $run_checksum; then + make -j8 CHECKSUM=1 +else + make -j8 +fi + + + -if [ $? -eq 0 ]; then +if ! $no_upload; then size=$(${AVR_DIR}/bin/avr-size main.elf | tail -n 1 | awk '{ print $1 + $2}') - limit=$((256 * 1024 - 16 - 6 * 1024)) + limit=$((256 * 1024 - 16 * 1024 - 6)) echo ROM_SIZE : $size echo ROM_LIMIT: $limit echo ROM_FREE : $(($limit - $size)) @@ -19,9 +46,14 @@ if [ $? -eq 0 ]; then echo RAM_USED: $ram_used echo RAM_FREE: $ram_free ${AVR_DIR}/bin/avr-nm main.elf -Crtd --size-sort | grep -i ' [dbv] ' | sort - ./checksum.py main.hex; + hex_file=main.hex + if $run_checksum; then + cp main.hex main_checksum.hex + ./checksum.py main_checksum.hex; + hex_file=main_checksum.hex + fi #avrdude -c atmelice_isp -p m2560 -D -Uflash:w:./main.hex -B 1 - ${AVR_DIR}/bin/avrdude -C${AVR_DIR}/etc/avrdude.conf -V -patmega2560 -c arduino -P${DEV} -b115200 -D -Uflash:w:./main.hex + ${AVR_DIR}/bin/avrdude -C${AVR_DIR}/etc/avrdude.conf -V -patmega2560 -c arduino -P${DEV} -b115200 -D -Uflash:w:./$hex_file #${AVR_DIR}/bin/avrdude -C${AVR_DIR}/etc/avrdude.conf -V -patmega2560 -c wiring -P${DEV} -b115200 -D -Uflash:w:./main.hex fi From 70c295bbef1f3af84839712e0a2569b2076d1e44 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sat, 20 Jul 2024 00:20:34 +1000 Subject: [PATCH 044/133] llm suggestion for find_next_locks. not bad --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 38 ++++++++++++++++++++++- avr/cores/megacommand/MCL/WavDesigner.cpp | 2 +- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index e3e6f8c57..66919ae95 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -269,7 +269,43 @@ void MDSeqTrack::recalc_slides() { end: locks_slides_recalc = 255; } +void MDSeqTrack::find_next_locks(uint8_t curidx, uint8_t step, uint8_t mask) { + uint8_t next_step = step + 1; + uint8_t max_len = length; + curidx += popcount(steps[step].locks); // Using original popcount lookup + + for (;;) { + if (next_step >= max_len) { + next_step = 0; + curidx = 0; + max_len = step; + } + + uint8_t lcks = get_step_locks(next_step); + uint8_t combined = mask & (lcks | (steps[next_step].trig ? 0xFF : 0)); + + while (combined) { + uint8_t cur_mask = combined & -combined; // Get lowest set bit + uint8_t i = popcount(cur_mask - 1); // Use popcount to get index + + if (lcks & cur_mask) { + locks_slide_next_lock_val[i] = locks[curidx]; + curidx++; + } else { + locks_slide_next_lock_val[i] = MD.kit.params[track_number][locks_params[i] - 1]; + } + locks_slide_next_lock_step[i] = next_step; + + mask &= ~cur_mask; + combined &= ~cur_mask; + if (!mask) return; // All targets hit + } + + next_step++; + } +} +/* void MDSeqTrack::find_next_locks(uint8_t curidx, uint8_t step, uint8_t mask) { DEBUG_PRINT_FN(); DEBUG_DUMP(step); @@ -313,7 +349,7 @@ void MDSeqTrack::find_next_locks(uint8_t curidx, uint8_t step, uint8_t mask) { goto again; } } - +*/ void MDSeqTrack::get_mask(uint64_t *_pmask, uint8_t mask_type) const { *_pmask = 0; for (uint8_t i = 0; i < NUM_MD_STEPS; i++) { diff --git a/avr/cores/megacommand/MCL/WavDesigner.cpp b/avr/cores/megacommand/MCL/WavDesigner.cpp index 1feaef3af..0e7ad8d97 100644 --- a/avr/cores/megacommand/MCL/WavDesigner.cpp +++ b/avr/cores/megacommand/MCL/WavDesigner.cpp @@ -238,7 +238,7 @@ bool WavDesigner::render() { } bool WavDesigner::send() { - return midi_sds.sendWav(WAV_NAME, mixer.enc4.cur, false); + return midi_sds.sendWav(WAV_NAME, WAV_NAME, mixer.enc4.cur, false); } WavDesigner wd; From 22bee4751c4822af9336f66812cb7a53d8660b91 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sat, 20 Jul 2024 00:32:34 +1000 Subject: [PATCH 045/133] disable -f permissive --- avr/cores/megacommand/A4/A4.cpp | 2 +- .../megacommand/CommonTools/RingBuffer.h | 4 +- avr/cores/megacommand/Elektron/Elektron.h | 2 +- avr/cores/megacommand/MCL/DeviceTrack.cpp | 2 +- avr/cores/megacommand/MCL/FXPage.cpp | 4 +- avr/cores/megacommand/MCL/FileBrowserPage.cpp | 4 +- avr/cores/megacommand/MCL/FileBrowserPage.h | 6 +-- avr/cores/megacommand/MCL/Grid.cpp | 3 +- avr/cores/megacommand/MCL/GridPage.cpp | 19 +++++---- avr/cores/megacommand/MCL/GridPage.h | 3 ++ avr/cores/megacommand/MCL/GridTrack.cpp | 2 +- avr/cores/megacommand/MCL/LFOSeqTrack.cpp | 2 +- avr/cores/megacommand/MCL/LoadProjectPage.cpp | 39 ++++++------------- avr/cores/megacommand/MCL/MCL.cpp | 2 +- avr/cores/megacommand/MCL/MCLActions.cpp | 2 +- avr/cores/megacommand/MCL/MenuPage.cpp | 2 +- avr/cores/megacommand/MCL/MenuPage.h | 2 +- .../megacommand/MCL/MidiActivePeering.cpp | 10 ++--- avr/cores/megacommand/MCL/MidiActivePeering.h | 4 +- avr/cores/megacommand/MCL/MixerPage.cpp | 2 +- avr/cores/megacommand/MCL/MixerPage.h | 4 +- avr/cores/megacommand/MCL/PageSelectPage.cpp | 10 ++--- avr/cores/megacommand/MCL/PerfPage.cpp | 8 ++-- .../megacommand/MCL/SampleBrowserPage.cpp | 2 +- avr/cores/megacommand/MCL/SeqPage.cpp | 4 +- avr/cores/megacommand/MCL/SeqStepPage.cpp | 2 +- avr/cores/megacommand/MCL/WavDesignerPage.cpp | 2 +- avr/cores/megacommand/MNM/MNM.cpp | 2 +- avr/cores/megacommand/Makefile | 2 +- avr/cores/megacommand/Midi/Midi.cpp | 2 +- avr/cores/megacommand/Midi/Midi.h | 8 ++-- 31 files changed, 75 insertions(+), 87 deletions(-) diff --git a/avr/cores/megacommand/A4/A4.cpp b/avr/cores/megacommand/A4/A4.cpp index 4e9460c1d..74c31ce57 100644 --- a/avr/cores/megacommand/A4/A4.cpp +++ b/avr/cores/megacommand/A4/A4.cpp @@ -228,7 +228,7 @@ bool A4Class::getBlockingSettingsX(uint8_t settings, uint16_t timeout) { return connected; } -void A4Class::muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr) { +void A4Class::muteTrack(uint8_t track, bool mute, MidiUartParent *uart_) { if (uart_ == nullptr) { uart_ = uart; } uart->sendCC(track, 94, mute); } diff --git a/avr/cores/megacommand/CommonTools/RingBuffer.h b/avr/cores/megacommand/CommonTools/RingBuffer.h index 897408741..b6a482d98 100644 --- a/avr/cores/megacommand/CommonTools/RingBuffer.h +++ b/avr/cores/megacommand/CommonTools/RingBuffer.h @@ -163,7 +163,7 @@ void CRingBuffer::put_h_isr(C *src, T n) volatile { if constexpr (N == 0) { memcpy_bank1(ptr + wr, src, s * sizeof(C)); } else { - memcpy(buf + wr, src, s * sizeof(C)); + memcpy((void*)(buf + wr), src, s * sizeof(C)); } wr += s; n -= s; @@ -171,7 +171,7 @@ void CRingBuffer::put_h_isr(C *src, T n) volatile { if constexpr (N == 0) { memcpy_bank1(ptr, src + s, n * sizeof(C)); } else { - memcpy(buf ,src + s, n * sizeof(C)); + memcpy((void*)buf ,src + s, n * sizeof(C)); } wr = n; } diff --git a/avr/cores/megacommand/Elektron/Elektron.h b/avr/cores/megacommand/Elektron/Elektron.h index 5f8aae0a1..a61e892a1 100644 --- a/avr/cores/megacommand/Elektron/Elektron.h +++ b/avr/cores/megacommand/Elektron/Elektron.h @@ -141,7 +141,7 @@ class MidiDevice { public: bool connected; MidiClass* midi; - MidiUartParent* uart; + MidiUartClass* uart; const char* const name; const uint8_t id; // Device identifier const bool isElektronDevice; diff --git a/avr/cores/megacommand/MCL/DeviceTrack.cpp b/avr/cores/megacommand/MCL/DeviceTrack.cpp index eca00204f..7c9795cb7 100644 --- a/avr/cores/megacommand/MCL/DeviceTrack.cpp +++ b/avr/cores/megacommand/MCL/DeviceTrack.cpp @@ -126,7 +126,7 @@ bool DeviceTrackChunk::load_chunk(volatile void *ptr, uint8_t chunk) { if (chunk == get_chunk_count() - 1) { chunk_size = get_seq_data_size() - sizeof(seq_data_chunk) * chunk; } - memcpy(ptr + sizeof(seq_data_chunk) * chunk, seq_data_chunk, chunk_size); + memcpy((uint8_t*) ptr + sizeof(seq_data_chunk) * chunk, seq_data_chunk, chunk_size); return true; } diff --git a/avr/cores/megacommand/MCL/FXPage.cpp b/avr/cores/megacommand/MCL/FXPage.cpp index 545eda603..45a963769 100644 --- a/avr/cores/megacommand/MCL/FXPage.cpp +++ b/avr/cores/megacommand/MCL/FXPage.cpp @@ -24,7 +24,7 @@ void FXPage::init() { void FXPage::update_encoders() { for (uint8_t n = 0; n < GUI_NUM_ENCODERS; n++) { - MCLEncoder * enc = encoders[n]; + MCLEncoder *enc = (MCLEncoder*) encoders[n]; enc->max = 127; uint8_t a = ((uint8_t)page_mode * GUI_NUM_ENCODERS) + n; @@ -60,7 +60,7 @@ void FXPage::loop() { for (uint8_t i = 0; i < GUI_NUM_ENCODERS; i++) { uint8_t n = i + (page_mode * GUI_NUM_ENCODERS); - MCLEncoder *enc = encoders[i]; + MCLEncoder *enc = (MCLEncoder *) encoders[i]; if (enc->hasChanged()) { uint8_t fx_param = params[n].param; uint8_t fx_type = params[n].type; diff --git a/avr/cores/megacommand/MCL/FileBrowserPage.cpp b/avr/cores/megacommand/MCL/FileBrowserPage.cpp index f3684e832..feea9fbcd 100644 --- a/avr/cores/megacommand/MCL/FileBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/FileBrowserPage.cpp @@ -47,12 +47,12 @@ void FileBrowserPage::setup() { encoders[2]->cur = 1; } -void FileBrowserPage::get_entry(uint16_t n, const char *entry) { +void FileBrowserPage::get_entry(uint16_t n, char *entry) { uint8_t discard_type; get_entry(n, entry, discard_type); } -void FileBrowserPage::get_entry(uint16_t n, const char *entry, uint8_t &type) { +void FileBrowserPage::get_entry(uint16_t n, char *entry, uint8_t &type) { volatile uint8_t *ptr = (uint8_t *)BANK3_FILE_ENTRIES_START + n * FILE_ENTRY_SIZE; char buf[FILE_ENTRY_SIZE]; diff --git a/avr/cores/megacommand/MCL/FileBrowserPage.h b/avr/cores/megacommand/MCL/FileBrowserPage.h index 3c3500716..8683fcb24 100644 --- a/avr/cores/megacommand/MCL/FileBrowserPage.h +++ b/avr/cores/megacommand/MCL/FileBrowserPage.h @@ -35,7 +35,7 @@ class FileBrowserFileTypes { char types[size][5]; uint8_t count = 0; public: - void add(char *str) { + void add(const char *str) { if (count < size) { strcpy(types[count], str); count++; @@ -140,8 +140,8 @@ class FileBrowserPage : public LightPage { static constexpr uint8_t DIR_TYPE = 1; bool add_entry(const char *entry, uint8_t type = FILE_TYPE); - void get_entry(uint16_t n, const char *entry); - void get_entry(uint16_t n, const char *entry, uint8_t &type); + void get_entry(uint16_t n, char *entry); + void get_entry(uint16_t n, char *entry, uint8_t &type); void draw_scrollbar(uint8_t x_offset); bool create_folder(); diff --git a/avr/cores/megacommand/MCL/Grid.cpp b/avr/cores/megacommand/MCL/Grid.cpp index 34841eba2..e40514ab9 100644 --- a/avr/cores/megacommand/MCL/Grid.cpp +++ b/avr/cores/megacommand/MCL/Grid.cpp @@ -65,7 +65,7 @@ bool Grid::new_file(const char *gridname) { bool Grid::new_grid(const char *gridname) { bool ret = false; - + uint8_t ledstatus = 0; DEBUG_PRINT_FN(); DEBUG_PRINTLN(F("Creating new grid")); if (!new_file(gridname)) { @@ -79,7 +79,6 @@ bool Grid::new_grid(const char *gridname) { oled_display.drawRect(15, 23, 98, 6, WHITE); #endif // Initialise the project file by filling the grid with blank data. - uint8_t ledstatus = 0; for (uint16_t i = 0; i < GRID_LENGTH; i++) { #ifdef OLED_DISPLAY diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index c4aefef8f..87e498fe9 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -83,7 +83,7 @@ void GridPage::close_bank_popup() { DEBUG_PRINTLN("setting page"); mcl.setPage(last_page); } - last_page = 255; + last_page = NULL_PAGE; bank_popup = 0; note_interface.init_notes(); // Clear blink leds @@ -611,8 +611,9 @@ bool GridPage::swap_grids() { proj.grid_select = grid_select_apply; ((MCLEncoder *)encoders[0])->max = getWidth() - 1; //load_slot_models(); - return; + return true; } + return false; } void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { @@ -621,6 +622,7 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { uint8_t _col = getCol();; + bool activate_header = false; //old_col != 255 indicates that the grid selection spans grids x and y. if (old_col != 255) { _col = old_col; @@ -630,8 +632,13 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { GridTrack temp_slot; temp_slot.load_from_grid(_col, getRow()); + uint8_t track_select_array[NUM_SLOTS] = {0}; + SeqTrack seq_track; + uint16_t target_length = slot.link.length * seq_track.get_speed_multiplier(slot.link.speed) * slot.link.loops; + + if (old_col == 255) { - if (swap_grids()) { return; } + if (!swap_grids()) { return; } } uint8_t load_mode_old = mcl_cfg.load_mode; @@ -722,16 +729,12 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { oled_display.display(); - bool activate_header = false; - uint8_t track_select_array[NUM_SLOTS] = {0}; GridRowHeader header; - SeqTrack seq_track; - uint16_t target_length = slot.link.length * seq_track.get_speed_multiplier(slot.link.speed) * slot.link.loops; - again: + for (uint8_t y = 0; y < height && y + getRow() < GRID_LENGTH; y++) { uint8_t ypos = y + getRow(); proj.read_grid_row_header(&header, y + getRow()); diff --git a/avr/cores/megacommand/MCL/GridPage.h b/avr/cores/megacommand/MCL/GridPage.h index 3b07b6ca1..89179cacf 100644 --- a/avr/cores/megacommand/MCL/GridPage.h +++ b/avr/cores/megacommand/MCL/GridPage.h @@ -15,6 +15,8 @@ #define SLOT_RAM_RECORD 252 #define SLOT_RAM_PLAY 251 +class GridTrack; + class GridPage : public LightPage { public: GridRowHeader row_headers[MAX_VISIBLE_ROWS]; @@ -89,6 +91,7 @@ class GridPage : public LightPage { void prepare(); bool swap_grids(); void apply_slot_changes(bool ignore_undo = false, bool ignore_func = false); + void load_old_col(); void close_bank_popup(); diff --git a/avr/cores/megacommand/MCL/GridTrack.cpp b/avr/cores/megacommand/MCL/GridTrack.cpp index c00ffce17..80a7bfd49 100644 --- a/avr/cores/megacommand/MCL/GridTrack.cpp +++ b/avr/cores/megacommand/MCL/GridTrack.cpp @@ -1,7 +1,7 @@ #include "MCL_impl.h" -bool GridTrack::write_grid(void *data, size_t len, uint8_t column, uint16_t row, Grid *grid = nullptr) { +bool GridTrack::write_grid(void *data, size_t len, uint8_t column, uint16_t row, Grid *grid) { if (grid == nullptr) { return proj.write_grid((uint8_t *)(this), len, column, row); } diff --git a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp index 7c6afa94f..741bc96a3 100644 --- a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp @@ -1,6 +1,6 @@ #include "MCL_impl.h" -static uint8_t LFOSeqTrack::wav_tables[4][WAV_LENGTH]; +uint8_t LFOSeqTrack::wav_tables[4][WAV_LENGTH]; void LFOSeqTrack::load_tables() { SinLFO sin_lfo; diff --git a/avr/cores/megacommand/MCL/LoadProjectPage.cpp b/avr/cores/megacommand/MCL/LoadProjectPage.cpp index 215ce4fe3..406c1234d 100644 --- a/avr/cores/megacommand/MCL/LoadProjectPage.cpp +++ b/avr/cores/megacommand/MCL/LoadProjectPage.cpp @@ -72,39 +72,32 @@ void LoadProjectPage::on_rename(const char *from, const char *to) { return; } + char grid_filename[f_len] = {'\0'}; + char to_grid_filename[f_len] = {'\0'}; + char proj_filename[f_len] = {'\0'}; + + char to_proj_filename[f_len] = {'\0'}; + uint8_t l = strlen(grid_filename); + uint8_t l2 = strlen(to_grid_filename); + + bool reload_current = false; + if (!SD.chdir(from)) { goto error; } - bool reload_current = false; if (strcmp(mcl_cfg.project, from) == 0) { DEBUG_PRINTLN("reload current"); reload_current = true; } - char grid_filename[f_len] = {'\0'}; - char to_grid_filename[f_len] = {'\0'}; - char proj_filename[f_len] = {'\0'}; - strncpy(proj_filename, from, f_len); strcat(proj_filename, ".mcl"); - char to_proj_filename[f_len] = {'\0'}; strncpy(to_proj_filename, to, f_len); strcat(to_proj_filename, ".mcl"); strncpy(to_grid_filename, to, f_len); strncpy(grid_filename, from, f_len); - uint8_t l = strlen(grid_filename); - uint8_t l2 = strlen(to_grid_filename); - - DEBUG_PRINTLN("check"); - DEBUG_PRINTLN(from); - DEBUG_PRINTLN(to); - DEBUG_PRINTLN(grid_filename); - DEBUG_PRINTLN(to_grid_filename); - DEBUG_PRINTLN(proj_filename); - DEBUG_PRINTLN(to_proj_filename); - for (uint8_t i = 0; i < NUM_GRIDS; i++) { grid_filename[l] = '.'; grid_filename[l + 1] = i + '0'; @@ -114,32 +107,22 @@ void LoadProjectPage::on_rename(const char *from, const char *to) { to_grid_filename[l2 + 1] = i + '0'; to_grid_filename[l2 + 2] = '\0'; - DEBUG_PRINTLN("from to grid filenames"); - DEBUG_PRINTLN(grid_filename); - DEBUG_PRINTLN(to_grid_filename); if (!SD.rename(grid_filename, to_grid_filename)) { DEBUG_PRINTLN("Rename failed"); goto error; } } - DEBUG_PRINTLN("from to project filename"); - DEBUG_PRINTLN(proj_filename); - DEBUG_PRINTLN(to_proj_filename); - if (!SD.rename(proj_filename, to_proj_filename)) { goto error; } SD.chdir(lwd); - DEBUG_PRINTLN("rename from to"); - DEBUG_PRINTLN(from); - DEBUG_PRINTLN(to); if (SD.rename(from, to)) { if (reload_current) { proj.load_project(to); } gfx.alert("SUCCESS", "Project renamed."); - return true; + return; } error: DEBUG_PRINTLN("error"); diff --git a/avr/cores/megacommand/MCL/MCL.cpp b/avr/cores/megacommand/MCL/MCL.cpp index da488ef4e..57173c17d 100644 --- a/avr/cores/megacommand/MCL/MCL.cpp +++ b/avr/cores/megacommand/MCL/MCL.cpp @@ -77,7 +77,7 @@ void sdcard_bench() { void mcl_setup() { mcl.setup(); } -static LightPage *const MCL::pages_table[NUM_PAGES] PROGMEM = { +LightPage *const MCL::pages_table[NUM_PAGES] PROGMEM = { &grid_page, // Index: 0 &page_select_page, // Index: 1 &system_page, // Index: 2 diff --git a/avr/cores/megacommand/MCL/MCLActions.cpp b/avr/cores/megacommand/MCL/MCLActions.cpp index 047ad3ebd..b59d3752f 100644 --- a/avr/cores/megacommand/MCL/MCLActions.cpp +++ b/avr/cores/megacommand/MCL/MCLActions.cpp @@ -170,7 +170,7 @@ void MCLActions::save_tracks(int row, uint8_t *slot_select_array, uint8_t merge, save_dev_tracks[i] = false; continue; } - ElektronPattern *p = elektron_devs[i]->getPattern(); + ElektronPattern *p = (ElektronPattern*) elektron_devs[i]->getPattern(); if (p->isEmpty()) { save_dev_tracks[i] = false; continue; diff --git a/avr/cores/megacommand/MCL/MenuPage.cpp b/avr/cores/megacommand/MCL/MenuPage.cpp index bf7befa13..9bb3542cb 100644 --- a/avr/cores/megacommand/MCL/MenuPage.cpp +++ b/avr/cores/megacommand/MCL/MenuPage.cpp @@ -205,7 +205,7 @@ bool MenuPageBase::enter() { return false; } -bool MenuPageBase::exit() { +void MenuPageBase::exit() { if (GUI.currentPage() != this) { return; } diff --git a/avr/cores/megacommand/MCL/MenuPage.h b/avr/cores/megacommand/MCL/MenuPage.h index 656fdebd8..78b269e59 100644 --- a/avr/cores/megacommand/MCL/MenuPage.h +++ b/avr/cores/megacommand/MCL/MenuPage.h @@ -39,7 +39,7 @@ class MenuPageBase : public LightPage { void setup(); void init(); bool enter(); - bool exit(); + void exit(); void cleanup(); void gen_menu_device_names(); void gen_menu_row_names(); diff --git a/avr/cores/megacommand/MCL/MidiActivePeering.cpp b/avr/cores/megacommand/MCL/MidiActivePeering.cpp index 1ab6fa5d6..545f183da 100644 --- a/avr/cores/megacommand/MCL/MidiActivePeering.cpp +++ b/avr/cores/megacommand/MCL/MidiActivePeering.cpp @@ -17,8 +17,8 @@ uint8_t GenericMidiDevice::get_mute_cc() { return mcl_cfg.uart2_cc_mute > 127 ? 255 : mcl_cfg.uart2_cc_mute; } -void GenericMidiDevice::muteTrack(uint8_t track, bool mute = true, - MidiUartParent *uart_ = nullptr) { +void GenericMidiDevice::muteTrack(uint8_t track, bool mute, + MidiUartClass *uart_) { if (track >= NUM_EXT_TRACKS || mcl_cfg.uart2_cc_mute > 127) { return; } @@ -30,7 +30,7 @@ void GenericMidiDevice::muteTrack(uint8_t track, bool mute = true, }; void GenericMidiDevice::setLevel(uint8_t track, uint8_t value, - MidiUartParent *uart_ = nullptr) { + MidiUartClass *uart_) { if (track >= NUM_EXT_TRACKS || mcl_cfg.uart2_cc_level > 127) { return; } @@ -52,8 +52,8 @@ void GenericMidiDevice::init_grid_devices(uint8_t device_idx) { } /// It is the caller's responsibility to check for null MidiUart device -static MidiUartParent *_getMidiUart(uint8_t port) { - MidiUartParent *ret = nullptr; +static MidiUartClass *_getMidiUart(uint8_t port) { + MidiUartClass *ret = nullptr; if (port == UART1_PORT) ret = &MidiUart; #ifdef EXT_TRACKS diff --git a/avr/cores/megacommand/MCL/MidiActivePeering.h b/avr/cores/megacommand/MCL/MidiActivePeering.h index 50942c45c..59d6ee4dd 100644 --- a/avr/cores/megacommand/MCL/MidiActivePeering.h +++ b/avr/cores/megacommand/MCL/MidiActivePeering.h @@ -40,8 +40,8 @@ class GenericMidiDevice : public MidiDevice { void init_grid_devices(uint8_t device_idx); virtual uint8_t get_mute_cc(); - virtual void muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr); - virtual void setLevel(uint8_t track, uint8_t value, MidiUartParent *uart_ = nullptr); + virtual void muteTrack(uint8_t track, bool mute = true, MidiUartClass *uart_ = nullptr); + virtual void setLevel(uint8_t track, uint8_t value, MidiUartClass *uart_ = nullptr); }; class NullMidiDevice : public MidiDevice { diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index d12cc7c95..770f12542 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -535,7 +535,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { mcl_seq.ext_tracks[track].toggle_mute(); } midi_device->muteTrack(track, seq_track->mute_state); - return; + return true; } // Toggle preview mutes diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index 28cc628fb..5ad1a3aa4 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -31,8 +31,8 @@ void encoder_lastparam_handle(EncoderParent *enc); class MixerPage : public LightPage { public: uint8_t level_pressmode = 0; - int8_t disp_levels[16]; - int8_t ext_disp_levels[6]; + uint8_t disp_levels[16]; + uint8_t ext_disp_levels[6]; bool mute_toggle = 0; uint8_t ext_key_down; MidiDevice *midi_device; diff --git a/avr/cores/megacommand/MCL/PageSelectPage.cpp b/avr/cores/megacommand/MCL/PageSelectPage.cpp index 8091e642a..fd0432fa2 100644 --- a/avr/cores/megacommand/MCL/PageSelectPage.cpp +++ b/avr/cores/megacommand/MCL/PageSelectPage.cpp @@ -18,7 +18,7 @@ static uint8_t get_pageidx(uint8_t page_number) { return i; } } - return 255; + return NULL_PAGE; } static PageIndex get_page(uint8_t pageidx, char *str) { @@ -31,7 +31,7 @@ static PageIndex get_page(uint8_t pageidx, char *str) { if (str) { strcpy(str, "----"); } - return 255; + return NULL_PAGE; } } @@ -123,7 +123,7 @@ void PageSelectPage::cleanup() { uint8_t PageSelectPage::get_nextpage_down() { for (int8_t i = page_select - 1; i >= 0; i--) { - if (get_page(get_pageidx(i), nullptr) != 255) { + if (get_page(get_pageidx(i), nullptr) != NULL_PAGE) { return i; } } @@ -132,7 +132,7 @@ uint8_t PageSelectPage::get_nextpage_down() { uint8_t PageSelectPage::get_nextpage_up() { for (uint8_t i = page_select + 1; i < 16; i++) { - if (get_page(get_pageidx(i), nullptr) != 255) { + if (get_page(get_pageidx(i), nullptr) != NULL_PAGE) { return i; } } @@ -353,7 +353,7 @@ bool PageSelectPage::handleEvent(gui_event_t *event) { release: PageIndex p; p = get_page(get_pageidx(page_select), nullptr); - if (BUTTON_DOWN(Buttons.BUTTON1) || (p == 255)) { + if (BUTTON_DOWN(Buttons.BUTTON1) || (p == NULL_PAGE)) { GUI.ignoreNextEvent(Buttons.BUTTON1); // md_exploit.off(); mcl.setPage(GRID_PAGE); diff --git a/avr/cores/megacommand/MCL/PerfPage.cpp b/avr/cores/megacommand/MCL/PerfPage.cpp index 5ce310ce1..b3754ee8b 100644 --- a/avr/cores/megacommand/MCL/PerfPage.cpp +++ b/avr/cores/megacommand/MCL/PerfPage.cpp @@ -232,8 +232,8 @@ void PerfPage::display() { // mcl_gui.draw_vertical_dashline(x, 0, knob_y); mcl_gui.draw_knob_frame(); - const char *info1 = ""; - const char *info2 = "PARAMETER"; + char *info1 = ""; + char *info2 = "PARAMETER"; uint8_t scene = learn - 1; @@ -513,7 +513,7 @@ bool PerfPage::handleEvent(gui_event_t *event) { } case MDX_KEY_PASTE: { if (undo < NUM_SCENES) { - return; + return true; } if (mcl_clipboard.paste_scene( &perf_encoders[perf_id]->perf_data.scenes[t])) { @@ -526,6 +526,7 @@ bool PerfPage::handleEvent(gui_event_t *event) { return true; } case MDX_KEY_CLEAR: { + char str[] = "CLEAR SCENE"; if (t == undo) { if (mcl_clipboard.paste_scene( &perf_encoders[perf_id]->perf_data.scenes[undo])) { @@ -542,7 +543,6 @@ bool PerfPage::handleEvent(gui_event_t *event) { mcl_clipboard.copy_scene( &perf_encoders[perf_id]->perf_data.scenes[t]); } - char str[] = "CLEAR SCENE"; oled_display.textbox(str, ""); MD.popup_text(str); perf_encoders[perf_id]->perf_data.clear_scene(t); diff --git a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp index 92dd34865..4921c36a7 100644 --- a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp @@ -351,7 +351,7 @@ bool SampleBrowserPage::_handle_filemenu() { return true; case FM_SENDALL: if (!mcl_gui.wait_for_confirm("Send all", "Overwrite?")) { - return; + return true; } char wav_name[FILE_ENTRY_SIZE] = ""; for (uint8_t n = 0; n < numEntries && !trig_interface.is_key_down(MDX_KEY_NO); n++) { diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index ab9c05bef..9178870f0 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -209,12 +209,12 @@ void SeqPage::toggle_ext_mask(uint8_t track) { if (track > 6) { track -= 8; if (track >= mcl_seq.num_ext_tracks) { - return true; + return; } mcl_seq.ext_tracks[track].toggle_mute(); } else { if (track >= mcl_seq.num_ext_tracks) { - return true; + return; } MidiDevice *dev = midi_active_peering.get_device(UART2_PORT); midi_device = dev; diff --git a/avr/cores/megacommand/MCL/SeqStepPage.cpp b/avr/cores/megacommand/MCL/SeqStepPage.cpp index 95ebee2e3..469dd5b12 100644 --- a/avr/cores/megacommand/MCL/SeqStepPage.cpp +++ b/avr/cores/megacommand/MCL/SeqStepPage.cpp @@ -416,7 +416,7 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { show_pitch = false; if (IS_BIT_SET16(ignore_release, track)) { CLEAR_BIT16(ignore_release, track); - return; + return true; } if (step >= active_track.length) { return true; diff --git a/avr/cores/megacommand/MCL/WavDesignerPage.cpp b/avr/cores/megacommand/MCL/WavDesignerPage.cpp index b0df7aeea..e7afc2a2e 100644 --- a/avr/cores/megacommand/MCL/WavDesignerPage.cpp +++ b/avr/cores/megacommand/MCL/WavDesignerPage.cpp @@ -21,7 +21,7 @@ void wavdesign_menu_handler() { if (WavDesignerPage::opt_mode == 3) { mcl.setPage(WD_MIXER_PAGE); } else { - mcl.setPage(WD_PAGE_0 + WavDesignerPage::opt_mode); + mcl.setPage((PageIndex) (WD_PAGE_0 + WavDesignerPage::opt_mode)); } } diff --git a/avr/cores/megacommand/MNM/MNM.cpp b/avr/cores/megacommand/MNM/MNM.cpp index c8a67e675..a55b3b87f 100644 --- a/avr/cores/megacommand/MNM/MNM.cpp +++ b/avr/cores/megacommand/MNM/MNM.cpp @@ -138,7 +138,7 @@ void MNMClass::setMultiEnvParam(uint8_t param, uint8_t value) { uart->sendNRPN(global.baseChannel, 0x40 + param, value); } -void MNMClass::muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr) { +void MNMClass::muteTrack(uint8_t track, bool mute, MidiUartParent *uart_) { if (uart_ == nullptr) { uart_ = uart; } uart->sendCC(track + global.baseChannel, 3, mute ? 0 : 1); } diff --git a/avr/cores/megacommand/Makefile b/avr/cores/megacommand/Makefile index 2fb5dcff3..02c48aee7 100644 --- a/avr/cores/megacommand/Makefile +++ b/avr/cores/megacommand/Makefile @@ -51,7 +51,7 @@ ARCH_FLAGS = -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR CFLAGS = -std=gnu11 $(COMPILE_FLAGS) $(FEATURE_FLAGS) $(LINK_FLAGS) $(ARCH_FLAGS) CXXFLAGS = -std=gnu++1z $(COMPILE_FLAGS) $(FEATURE_FLAGS) $(LINK_FLAGS) $(ARCH_FLAGS) -CXXFLAGS += -fpermissive -fno-exceptions -fno-threadsafe-statics -fno-rtti +CXXFLAGS += -fno-exceptions -fno-threadsafe-statics -fno-rtti LDFLAGS = $(OPTIM_FLAGS) $(WARN_FLAGS) -flto -fuse-linker-plugin -mrelax $(LINK_FLAGS) $(ARCH_FLAGS) diff --git a/avr/cores/megacommand/Midi/Midi.cpp b/avr/cores/megacommand/Midi/Midi.cpp index 7ae69d42a..73004faf4 100644 --- a/avr/cores/megacommand/Midi/Midi.cpp +++ b/avr/cores/megacommand/Midi/Midi.cpp @@ -19,7 +19,7 @@ const midi_parse_t midi_parse[] = {{MIDI_NOTE_OFF, midi_wait_byte_2}, {MIDI_TUNE_REQUEST, midi_wait_status}, {0, midi_ignore_message}}; -MidiClass::MidiClass(MidiUartParent *_uart, uint16_t _sysexBufLen, +MidiClass::MidiClass(MidiUartClass *_uart, uint16_t _sysexBufLen, volatile uint8_t *ptr) : midiSysex(_uart, _sysexBufLen, ptr) { midiActive = true; diff --git a/avr/cores/megacommand/Midi/Midi.h b/avr/cores/megacommand/Midi/Midi.h index ae02e9878..55326e419 100644 --- a/avr/cores/megacommand/Midi/Midi.h +++ b/avr/cores/megacommand/Midi/Midi.h @@ -68,7 +68,7 @@ class MidiClass { uint8_t in_msg_len; uint8_t msg[3]; - MidiUartParent *uart; + MidiUartClass *uart; MidiUartClass *uart_forward[NUM_FORWARD_PORTS]; @@ -83,7 +83,7 @@ class MidiClass { MidiSysexClass midiSysex; uint8_t receiveChannel; - MidiClass(MidiUartParent *_uart, uint16_t _sysexBufLen, volatile uint8_t *ptr); + MidiClass(MidiUartClass *_uart, uint16_t _sysexBufLen, volatile uint8_t *ptr); void init(); @@ -95,8 +95,8 @@ class MidiClass { } void processMidi() { - while (uart->avail()) { - handleByte(uart->m_getc()); + while (((MidiUartParent*)uart)->avail()) { + handleByte(((MidiUartParent*)uart)->m_getc()); } } From 65b6c31d1e6d2341870f357d3ef97e8c1786755e Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 14:37:15 +1000 Subject: [PATCH 046/133] drawPixel optimise --- .../Adafruit_SSD1305.cpp | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/avr/cores/megacommand/Adafruit_SSD1305_Library/Adafruit_SSD1305.cpp b/avr/cores/megacommand/Adafruit_SSD1305_Library/Adafruit_SSD1305.cpp index 2c2867448..f4883bd05 100644 --- a/avr/cores/megacommand/Adafruit_SSD1305_Library/Adafruit_SSD1305.cpp +++ b/avr/cores/megacommand/Adafruit_SSD1305_Library/Adafruit_SSD1305.cpp @@ -53,20 +53,17 @@ static uint8_t buffer[SSD1305_LCDHEIGHT * SSD1305_LCDWIDTH / 8] = {}; // the most basic function, set a single pixel void Adafruit_SSD1305::drawPixel(uint8_t x, uint8_t y, uint8_t color) { - if ((x >= width()) || (y >= height())) - return; - + if (x >= width() || y >= height()) + return; uint16_t index = x + (y / 8) * SSD1305_LCDWIDTH; - draw_pixel: - // x is which column + uint8_t bit = _BV(y & 7); + if (color == WHITE) - SET_BIT(buffer[index],y % 8); - else if (color == INVERT) { - color = - (IS_BIT_SET(buffer[index],y % 8)) ? BLACK : WHITE; - goto draw_pixel; - } else // BLACK - CLEAR_BIT(buffer[index],(y % 8)); + buffer[index] |= bit; + else if (color == BLACK) + buffer[index] &= ~bit; + else // INVERT + buffer[index] ^= bit; } void Adafruit_SSD1305::drawFastVLine(uint8_t x, uint8_t y, uint8_t h, From 778bca5582d42c3e32c43cb631326b60d9c9b1bb Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 14:37:47 +1000 Subject: [PATCH 047/133] get blocking optimise --- avr/cores/megacommand/Elektron/Elektron.cpp | 157 ++++++++++++-------- avr/cores/megacommand/Elektron/Elektron.h | 3 + 2 files changed, 94 insertions(+), 66 deletions(-) diff --git a/avr/cores/megacommand/Elektron/Elektron.cpp b/avr/cores/megacommand/Elektron/Elektron.cpp index 64d59e62d..7b23ec046 100644 --- a/avr/cores/megacommand/Elektron/Elektron.cpp +++ b/avr/cores/megacommand/Elektron/Elektron.cpp @@ -17,6 +17,29 @@ uint8_t *MidiDevice::gif_data() { return R.icons_logo->midi_gif_data; } MCLGIF *MidiDevice::gif() { return R.icons_logo->midi_gif; } uint16_t ElektronDevice::sendRequest(uint8_t *data, uint8_t len, bool send, MidiUartParent *uart_) { + if (!send) { + return len + sysex_protocol.header_size + 2; + } + + uart_ = uart_ ? uart_ : uart; + + uint8_t buf[256]; + uint8_t i = 0; + + buf[i++] = 0xF0; + memcpy(buf + i, sysex_protocol.header, sysex_protocol.header_size); + i += sysex_protocol.header_size; + + for (uint8_t n = 0; n < len; n++) { + buf[i++] = data[n] & 0x7F; + } + buf[i++] = 0xF7; + + uart_->m_putc(buf, i); + + return i; +} +/* if (uart_ == nullptr) { uart_ = uart; } uint8_t buf[256]; @@ -37,7 +60,7 @@ uint16_t ElektronDevice::sendRequest(uint8_t *data, uint8_t len, bool send, Midi } return len + sysex_protocol.header_size + 2; } - +*/ uint16_t ElektronDevice::sendRequest(uint8_t type, uint8_t param, bool send) { uint8_t data[] = {type, param}; return sendRequest(data, 2, send); @@ -318,78 +341,80 @@ uint8_t ElektronDevice::getBlockingStatus(uint8_t type, uint16_t timeout) { return connected ? cb.value : 255; } -bool ElektronDevice::getBlockingKit(uint8_t kit, uint16_t timeout) { - SysexCallback cb; - uint8_t count = SYSEX_RETRIES; - auto listener = getSysexListener(); - bool ret; - while ((MidiClock.state == 2) && - ((MidiClock.mod12_counter > 6) || (MidiClock.mod12_counter == 0))) - ; - while (count) { - listener->addOnKitMessageCallback( - &cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); - requestKit(kit); - DEBUG_PRINTLN("get blocking kit"); - ret = cb.waitBlocking(timeout); - listener->removeOnKitMessageCallback(&cb); - if (ret) { - midi->midiSysex.rd_cur = listener->msg_rd; - auto kit = getKit(); - if (kit != nullptr && kit->fromSysex(midi)) { - DEBUG_PRINTLN("finished"); - return true; - } +bool ElektronDevice::getBlockingData(DataType type, uint8_t index, uint16_t timeout) { + SysexCallback cb; + uint8_t count = (type == DataType::Global) ? 1 : SYSEX_RETRIES; + auto listener = getSysexListener(); + bool ret = false; + + while ((MidiClock.state == 2) && + ((MidiClock.mod12_counter > 6) || (MidiClock.mod12_counter == 0))) + ; + + while (count--) { + switch (type) { + case DataType::Kit: + listener->addOnKitMessageCallback(&cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); + requestKit(index); + break; + case DataType::Pattern: + listener->addOnPatternMessageCallback(&cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); + requestPattern(index); + break; + case DataType::Global: + listener->addOnGlobalMessageCallback(&cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); + requestGlobal(index); + break; + } + + ret = cb.waitBlocking(timeout); + + switch (type) { + case DataType::Kit: + listener->removeOnKitMessageCallback(&cb); + break; + case DataType::Pattern: + listener->removeOnPatternMessageCallback(&cb); + break; + case DataType::Global: + listener->removeOnGlobalMessageCallback(&cb); + break; + } + + if (ret) { + midi->midiSysex.rd_cur = listener->msg_rd; + void* data = nullptr; + switch (type) { + case DataType::Kit: + data = getKit(); + break; + case DataType::Pattern: + data = getPattern(); + break; + case DataType::Global: + data = getGlobal(); + break; + } + if (data != nullptr && ((ElektronSysexObject*)data)->fromSysex(midi)) { + if (type == DataType::Global) connected = true; + return true; + } + } } - count--; - } - return false; + return false; } -bool ElektronDevice::getBlockingPattern(uint8_t pattern, uint16_t timeout) { - SysexCallback cb; - uint8_t count = SYSEX_RETRIES; - auto listener = getSysexListener(); - bool ret; - while ((MidiClock.state == 2) && - ((MidiClock.mod12_counter > 6) || (MidiClock.mod12_counter == 0))) - ; - while (count) { - listener->addOnPatternMessageCallback( - &cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); - requestPattern(pattern); - ret = cb.waitBlocking(timeout); - listener->removeOnPatternMessageCallback(&cb); - - if (ret) { - midi->midiSysex.rd_cur = listener->msg_rd; - auto pattern = getPattern(); - if (pattern != nullptr && pattern->fromSysex(midi)) { - return true; - } - } - count--; - } - return false; +bool ElektronDevice::getBlockingKit(uint8_t kit, uint16_t timeout) { + return getBlockingData(DataType::Kit, kit, timeout);; +} + +bool ElektronDevice::getBlockingPattern(uint8_t pattern, uint16_t timeout) { + return getBlockingData(DataType::Pattern, pattern, timeout);; } bool ElektronDevice::getBlockingGlobal(uint8_t global, uint16_t timeout) { - SysexCallback cb; - auto listener = getSysexListener(); - listener->addOnGlobalMessageCallback( - &cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); - requestGlobal(global); - connected = cb.waitBlocking(timeout); - listener->removeOnGlobalMessageCallback(&cb); - if (connected) { - auto global = getGlobal(); - midi->midiSysex.rd_cur = listener->msg_rd; - if (global != nullptr && global->fromSysex(midi)) { - return true; - } - } - return connected; + return getBlockingData(DataType::Global, global, timeout); } uint8_t ElektronDevice::getCurrentTrack(uint16_t timeout) { diff --git a/avr/cores/megacommand/Elektron/Elektron.h b/avr/cores/megacommand/Elektron/Elektron.h index a61e892a1..1c58e0f0b 100644 --- a/avr/cores/megacommand/Elektron/Elektron.h +++ b/avr/cores/megacommand/Elektron/Elektron.h @@ -41,6 +41,8 @@ typedef struct short_machine_name_s { uint8_t id; } short_machine_name_t; +enum class DataType { Kit, Pattern, Global }; + /** * Class grouping various helper functions to convert elektron sysex * data. These are deprecated and should be replaced by the elektron @@ -465,6 +467,7 @@ class ElektronDevice : public MidiDevice { **/ void requestGlobal(uint8_t global); + bool getBlockingData(DataType type, uint8_t index, uint16_t timeout); /** * Get the status answer from the device, blocking until either * a message is received or the timeout has run out. From 4ca63d468cede7ccd0d9535eaeb416dc66ca15f4 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 14:38:05 +1000 Subject: [PATCH 048/133] GUI_private optimise --- avr/cores/megacommand/GUI_private.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/avr/cores/megacommand/GUI_private.h b/avr/cores/megacommand/GUI_private.h index 9d4042758..66443f088 100644 --- a/avr/cores/megacommand/GUI_private.h +++ b/avr/cores/megacommand/GUI_private.h @@ -39,11 +39,7 @@ class EncodersClass { ALWAYS_INLINE() int8_t getButton(uint8_t i) { return encoders[i].button; } ALWAYS_INLINE() int8_t limitValue(int8_t value, int8_t min, int8_t max) { - if (value > max) - return max; - if (value < min) - return min; - return value; + return (value > max) ? max : (value < min ? min : value); } }; From 9721c0f632adf923ef1ccc201f654c5289d08fdf Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 14:38:18 +1000 Subject: [PATCH 049/133] GridTrack optimise --- avr/cores/megacommand/MCL/GridTrack.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/GridTrack.h b/avr/cores/megacommand/MCL/GridTrack.h index a37515258..e504867ef 100644 --- a/avr/cores/megacommand/MCL/GridTrack.h +++ b/avr/cores/megacommand/MCL/GridTrack.h @@ -70,7 +70,7 @@ class GridTrack { /// caller guarantees that the type is reconstructed correctly /// downloads from BANK1 to the runtime object bool load_from_mem(uint8_t column, size_t size = 0) { - uint32_t bytes = size ? size : get_track_size(); + uint16_t bytes = size ? size : get_track_size(); uint32_t pos = get_region() + get_region_size() * (uint32_t)(column); volatile uint8_t *ptr = reinterpret_cast(pos); memcpy_bank1(this, ptr, bytes); From 9024a73fd621b7bf3fb06d4a7717d0c1a99a36e0 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 14:38:42 +1000 Subject: [PATCH 050/133] is_within_fov optimise --- avr/cores/megacommand/MCL/SeqExtStepPage.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqExtStepPage.h b/avr/cores/megacommand/MCL/SeqExtStepPage.h index 72bed3785..340754bc6 100644 --- a/avr/cores/megacommand/MCL/SeqExtStepPage.h +++ b/avr/cores/megacommand/MCL/SeqExtStepPage.h @@ -73,21 +73,20 @@ class SeqExtStepPage : public SeqPage { void pos_cur_y(int16_t diff); void pos_cur_w(int16_t diff); - bool is_within_fov(int16_t x) { - if ((x >= fov_offset) && (x < fov_offset + fov_length)) { - return true; - } - return false; + inline bool is_within_fov(int16_t x) { + return (x - fov_offset) < fov_length; } + bool is_within_fov(int16_t start_x, int16_t end_x) { - if (is_within_fov(start_x) || is_within_fov(end_x) || - ((start_x < fov_offset) && (end_x >= fov_offset + fov_length)) || - (end_x < start_x && - !((start_x > fov_offset + fov_length) && end_x < fov_offset))) { - return true; + int16_t fov_end = fov_offset + fov_length; + // Handle wrap-around case + if (end_x < start_x) { + return (start_x < fov_end) || (end_x >= fov_offset); } - return false; + // Normal case + return (start_x < fov_end) && (end_x >= fov_offset); } + void param_select_update(); void enter_notes(); void config_menu_entries(); From 8a00ce7391879c16111e9bf29011aedbc2a74e1a Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 14:39:30 +1000 Subject: [PATCH 051/133] MidiUartParent optimise --- avr/cores/megacommand/Midi/MidiUartParent.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/Midi/MidiUartParent.h b/avr/cores/megacommand/Midi/MidiUartParent.h index d6848e821..98e1d3280 100644 --- a/avr/cores/megacommand/Midi/MidiUartParent.h +++ b/avr/cores/megacommand/Midi/MidiUartParent.h @@ -158,7 +158,6 @@ class MidiUartParent { } */ - ALWAYS_INLINE() void sendNoteOn(uint8_t channel, uint8_t note, uint8_t velocity) { #ifdef MIDI_VALIDATE if ((channel >= 16) || (note >= 128) || (velocity >= 128)) @@ -170,7 +169,6 @@ class MidiUartParent { sendMessage(msg[0], msg[1], msg[2]); } - ALWAYS_INLINE() void sendNoteOff(uint8_t channel, uint8_t note) { #ifdef MIDI_VALIDATE if ((channel >= 16) || (note >= 128)) @@ -258,8 +256,8 @@ class MidiUartParent { m_putc(data, cnt); sendCommandByte(0xF7); } - ALWAYS_INLINE() void sendRaw(uint8_t *msg, uint16_t cnt) { m_putc(msg, cnt); } - ALWAYS_INLINE() void sendRaw(uint8_t byte) { m_putc(byte); } + void sendRaw(uint8_t *msg, uint16_t cnt) { m_putc(msg, cnt); } + void sendRaw(uint8_t byte) { m_putc(byte); } void sendString(const char *data) { sendString(data, strlen(data)); } void sendString(const char *data, uint16_t cnt); From 3ce164c1faf106becc244f7a2433df742411b4fd Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 14:53:41 +1000 Subject: [PATCH 052/133] memorybank switching optimise --- avr/cores/megacommand/MidiUart.cpp | 12 +++++----- avr/cores/megacommand/main.cpp | 4 ++-- avr/cores/megacommand/memory.h | 18 +++++++-------- avr/cores/megacommand/memorybank.h | 36 ++++++++++-------------------- avr/cores/megacommand/wiring.c | 2 +- 5 files changed, 30 insertions(+), 42 deletions(-) diff --git a/avr/cores/megacommand/MidiUart.cpp b/avr/cores/megacommand/MidiUart.cpp index bb11aa07c..e90d1977d 100644 --- a/avr/cores/megacommand/MidiUart.cpp +++ b/avr/cores/megacommand/MidiUart.cpp @@ -119,31 +119,31 @@ void MidiUartClass::realtime_isr(uint8_t c) { } ISR(USART0_RX_vect) { - select_bank(0); + select_bank(BANK0); MidiUartUSB.rx_isr(); } ISR(USART0_UDRE_vect) { - select_bank(0); + select_bank(BANK0); MidiUartUSB.tx_isr(); } ISR(USART1_RX_vect) { - select_bank(0); + select_bank(BANK0); MidiUart.rx_isr(); } ISR(USART1_UDRE_vect) { - select_bank(0); + select_bank(BANK0); MidiUart.tx_isr(); } ISR(USART2_RX_vect) { - select_bank(0); + select_bank(BANK0); MidiUart2.rx_isr(); } ISR(USART2_UDRE_vect) { - select_bank(0); + select_bank(BANK0); MidiUart2.tx_isr(); } diff --git a/avr/cores/megacommand/main.cpp b/avr/cores/megacommand/main.cpp index 3e6027af3..a1b85fba1 100644 --- a/avr/cores/megacommand/main.cpp +++ b/avr/cores/megacommand/main.cpp @@ -191,7 +191,7 @@ void loop(); ISR(TIMER1_COMPA_vect) { - select_bank(0); + select_bank(BANK0); clock++; MidiClock.div192th_countdown++; @@ -251,7 +251,7 @@ ALWAYS_INLINE() void gui_poll() { ISR(TIMER3_COMPA_vect) { - select_bank(0); + select_bank(BANK0); slowclock++; minuteclock++; diff --git a/avr/cores/megacommand/memory.h b/avr/cores/megacommand/memory.h index 8934300b6..880ece678 100644 --- a/avr/cores/megacommand/memory.h +++ b/avr/cores/megacommand/memory.h @@ -91,7 +91,7 @@ class RamBankSelector { uint8_t m_oldbank; public: FORCED_INLINE() RamBankSelector(uint8_t bank) { m_oldbank = switch_ram_bank(bank); } - FORCED_INLINE() ~RamBankSelector() { switch_ram_bank(m_oldbank); } + FORCED_INLINE() ~RamBankSelector() { switch_ram_bank_noret(m_oldbank); } }; class RamAccessFringe { @@ -116,33 +116,33 @@ class RamAccessFringe { template FORCED_INLINE() extern inline T get_bank1(volatile T *dst) { - select_bank(1); + select_bank(BANK1); return *dst; } template FORCED_INLINE() extern inline void put_bank1(volatile T *dst, T data) { - select_bank(1); + select_bank(BANK1); *dst = data; } FORCED_INLINE() extern inline int memcmp_bank1(volatile void *dst, volatile const void *src, uint16_t len) { - select_bank(1); + select_bank(BANK1); return memcmp((void*)dst, (void*)src, len); } FORCED_INLINE() extern inline void memcpy_bank1(volatile void *dst, volatile const void *src, uint16_t len) { - select_bank(1); + select_bank(BANK1); memcpy((void*)dst, (void*)src, len); } FORCED_INLINE() extern inline void put_byte_bank1(volatile uint8_t *dst, uint8_t byte) { - select_bank(1); + select_bank(BANK1); *dst = byte; } FORCED_INLINE() extern inline uint8_t get_byte_bank1(volatile uint8_t *dst) { - select_bank(1); + select_bank(BANK1); uint8_t c = *dst; return c; } @@ -155,7 +155,7 @@ FORCED_INLINE() extern inline void get_bank2(volatile void *dst, volatile const FORCED_INLINE() extern inline void get_bank3(volatile void *dst, volatile const void *src, uint16_t len) { ram_access_fringe(); - select_bank(1); + select_bank(BANK1); memcpy((void*)dst, (uint8_t*)src + 0x4000, len); } @@ -167,7 +167,7 @@ FORCED_INLINE() extern inline void put_bank2(volatile void *dst, volatile const FORCED_INLINE() extern inline void put_bank3(volatile void *dst, volatile const void *src, uint16_t len) { ram_access_fringe(); - select_bank(1); + select_bank(BANK1); memcpy((uint8_t*)dst + 0x4000, (uint8_t*)src, len); } diff --git a/avr/cores/megacommand/memorybank.h b/avr/cores/megacommand/memorybank.h index cd5748432..af45234c5 100644 --- a/avr/cores/megacommand/memorybank.h +++ b/avr/cores/megacommand/memorybank.h @@ -1,31 +1,19 @@ -#pragma once -#ifdef MEGACOMMAND - -#define PL6_MASK (1 << PL6) - -FORCED_INLINE() inline uint8_t switch_ram_bank(uint8_t x) { - uint8_t old_bank = (uint8_t) (PORTL & PL6_MASK); - - if (x != old_bank) { - PORTL ^= PL6_MASK; - return old_bank; - } - return x; -} +#define BANK0 0 +#ifdef MEGACOMMAND + #define BANK_PORT PORTL + #define BANK_MASK (1 << PL6) #else + #define BANK_PORT PORTB + #define BANK_MASK (1 << PB0) +#endif -#define PB0_MASK (1 << PB0) +#define BANK1 BANK_MASK FORCED_INLINE() inline uint8_t switch_ram_bank(uint8_t x) { - uint8_t old_bank = (uint8_t) (PORTB & PB0_MASK); - - if (x != old_bank) { - PORTB ^= PB0_MASK; - return old_bank; - } - return x; + uint8_t old_bank = BANK_PORT & BANK_MASK; + BANK_PORT = (BANK_PORT & ~BANK_MASK) | x; + return old_bank; } -#endif - +#define switch_ram_bank_noret(x) ((void)switch_ram_bank(x)) diff --git a/avr/cores/megacommand/wiring.c b/avr/cores/megacommand/wiring.c index 95c9baa56..a7dbc63c2 100644 --- a/avr/cores/megacommand/wiring.c +++ b/avr/cores/megacommand/wiring.c @@ -51,7 +51,7 @@ ISR(TIMER0_OVF_vect) // copy these to local variables so they can be stored in registers // (volatile variables must be read from memory on every access) - uint8_t old_bank = switch_ram_bank(0); + uint8_t old_bank = switch_ram_bank(BANK0); unsigned long m = timer0_millis; unsigned char f = timer0_fract; From f13fe12e5f6e681535a1d4884dd51ed47beb3308 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 16:27:55 +1000 Subject: [PATCH 053/133] optimise Adafruit-GFX-Library by only linking child virtual functions when defined --- .../Adafruit-GFX-Library/Adafruit_GFX.cpp | 11 +++++----- .../Adafruit-GFX-Library/Adafruit_GFX.h | 22 +++++++++---------- .../Adafruit_SSD1305.h | 8 +++---- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp b/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp index 94e4f8a54..baebef258 100755 --- a/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp +++ b/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp @@ -169,14 +169,15 @@ void Adafruit_GFX::endWrite() { // (x,y) is topmost point; if unsure, calling function // should sort endpoints or call drawLine() instead -void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, int16_t h, - uint16_t color) { +/* +void Adafruit_GFX::drawFastVLine(uint8_t x, uint8_t y, uint8_t h, + uint8_t color) { // Update in subclasses if desired! startWrite(); writeLine(x, y, x, y + h - 1, color); endWrite(); } - +*/ // (x,y) is leftmost point; if unsure, calling function // should sort endpoints or call drawLine() instead void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, int16_t w, @@ -187,8 +188,8 @@ void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, int16_t w, endWrite(); } -void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, - uint16_t color) { +void Adafruit_GFX::fillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, + uint8_t color) { // Update in subclasses if desired! startWrite(); for (int16_t i = x; i < x + w; i++) { diff --git a/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.h b/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.h index 3dff2ad1f..894b895d4 100755 --- a/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.h +++ b/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.h @@ -22,9 +22,9 @@ class Adafruit_GFX : public Print { // These MAY be overridden by the subclass to provide device-specific // optimized code. Otherwise 'generic' versions are used. virtual void startWrite(void); - virtual void writePixel(int16_t x, int16_t y, uint16_t color); - virtual void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); - virtual void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); + void writePixel(int16_t x, int16_t y, uint16_t color); + void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); + void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); virtual void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color); virtual void endWrite(void); @@ -39,15 +39,15 @@ class Adafruit_GFX : public Print { // BASIC DRAW API // These MAY be overridden by the subclass to provide device-specific // optimized code. Otherwise 'generic' versions are used. - virtual void - // It's good to implement those, even if using transaction API - drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color), - drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color), - fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color), - fillScreen(uint16_t color), + + void fillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color); + void fillScreen(uint16_t color); + virtual void drawFastVLine(uint8_t x, uint8_t y, uint8_t h, uint8_t color) = 0; + void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color); + + void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); // Optional and probably not necessary to change - drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color), - drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); + void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); // These exist only with Adafruit_GFX (no subclass overrides) void diff --git a/avr/cores/megacommand/Adafruit_SSD1305_Library/Adafruit_SSD1305.h b/avr/cores/megacommand/Adafruit_SSD1305_Library/Adafruit_SSD1305.h index ec84fe9a5..c6e55312e 100644 --- a/avr/cores/megacommand/Adafruit_SSD1305_Library/Adafruit_SSD1305.h +++ b/avr/cores/megacommand/Adafruit_SSD1305_Library/Adafruit_SSD1305.h @@ -103,7 +103,7 @@ All text above, and the splash screen must be included in any redistribution #define SSD1305_SETVCOMLEVEL 0xDB -class Adafruit_SSD1305 : public Adafruit_GFX { +class Adafruit_SSD1305 final : public Adafruit_GFX { private: bool screen_saver_active = false; @@ -132,11 +132,11 @@ class Adafruit_SSD1305 : public Adafruit_GFX { void textbox(const char *text, const char *text2, uint16_t delay = 800); void display(); - void drawPixel(uint8_t x, uint8_t y, uint8_t color); + virtual void drawPixel(uint8_t x, uint8_t y, uint8_t color); virtual void drawFastVLine(uint8_t x, uint8_t y, uint8_t h, uint8_t color); - virtual void fillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color); - virtual void fillScreen(uint8_t color); + void fillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color); + void fillScreen(uint8_t color); bool textbox_enabled = false; private: From 742a4e2c1645fe2b5ff5377798763ebe31382e07 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 19:37:26 +1000 Subject: [PATCH 054/133] fix mapping --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 66919ae95..a30bd7cd2 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -449,8 +449,8 @@ void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { case 2: uart2->sendChannelPressure(channel, ccs[2]); break; - case 15: - notes.prog = ccs[15]; + case 3: + notes.prog = ccs[3]; uart2->sendProgramChange(channel, ccs[15]); break; default: @@ -475,6 +475,7 @@ void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, bool is_lock) { uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + uint8_t i = param - 5; switch (param) { case 0: @@ -493,13 +494,14 @@ void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, break; case 20: if (notes.prog != val || is_lock) { - ccs[i] = val; + ccs[3] = val; } else { - ccs[i] = 255; + ccs[3] = 255; } break; default: + i = param - 8 + 4; if (param < 20) { // If the parameter is CC value and the CC dest is not yet set, use the // kit value for CC dest From 22d88748b5602f1fcaa2d52dcfde91797c4a6874 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 19:45:34 +1000 Subject: [PATCH 055/133] note.first_trig not disabled --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index a30bd7cd2..d9586f155 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -526,6 +526,7 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, //prevent re-transmission of program change. //process_note_locks(20, MD.kit.params[track_number][20],ccs); send_ccs = true; + notes.first_trig = false; } else { memset(ccs, 255, sizeof(ccs)); } @@ -570,7 +571,7 @@ void MDSeqTrack::reset_params() { uint8_t ccs[midi_cc_array_size]; bool send_ccs = true; memcpy(ccs, &MD.kit.params[track_number][5], sizeof(ccs)); - ccs[15] = 255; //disable program change + ccs[4] = 255; //disable program change //notes.prog = MD.kit.params[track_number][20]; //process_note_locks(20, MD.kit.params[track_number][20],ccs); send_notes_ccs(ccs, send_ccs); @@ -617,7 +618,7 @@ void MDSeqTrack::send_notes(uint8_t note1) { } init_notes(); if (note1 != 255) { notes.note1 = note1; } - reset_params(); + if (notes.first_trig) { reset_params(); notes.first_trig = false; } send_notes_on(); } From 221613aedf4d7757ef1e4470544d70b563368317 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 21:28:39 +1000 Subject: [PATCH 056/133] MIDI Machine slides --- avr/cores/megacommand/MCL/MCL.h | 2 +- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 81 ------------------ avr/cores/megacommand/MCL/MDSeqTrack.h | 5 -- avr/cores/megacommand/MCL/SeqTrack.cpp | 102 ++++++++++++++++++++++- avr/cores/megacommand/MCL/SeqTrack.h | 8 ++ 5 files changed, 110 insertions(+), 88 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index 806955d9c..c229cf840 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -17,7 +17,7 @@ #include "Fonts/TomThumb.h" #define VERSION 4052 -#define VERSION_STR "E4.52" +#define VERSION_STR "G4.52" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index d9586f155..ecf004c54 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -434,87 +434,6 @@ void MDSeqTrack::send_parameter_locks(uint8_t step, bool trig, send_parameter_locks_inline(step, trig, idx); } -void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { - uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - if (send_ccs) { - for (uint8_t n = 0; n < number_midi_cc; n++) { - if (ccs[n] == 255) continue; - switch (n) { - case 0: - uart2->sendPitchBend(channel, ccs[0] << 7); - break; - case 1: - uart2->sendCC(channel, 0x1, ccs[1]); - break; - case 2: - uart2->sendChannelPressure(channel, ccs[2]); - break; - case 3: - notes.prog = ccs[3]; - uart2->sendProgramChange(channel, ccs[15]); - break; - default: - if (!(n & 1)) continue; - uint8_t a = ccs[n - 1]; - if (a > 0 && a != 255) { - uint8_t v = ccs[n]; - // 0 = off - // 1 = bank (0) - // 2 = 2 - if (a == 1) { - a = 0; - }; - uart2->sendCC(channel, a, v); - break; - } - } - } - } -} - -void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, - bool is_lock) { - uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - - uint8_t i = param - 5; - switch (param) { - case 0: - case 1: - case 2: - case 3: - case 4: - //note values are set via init_notes initially. - ((uint8_t *)¬es)[param] = val; - //ccs[param] = val; not required. - break; - case 5: - case 6: - case 7: - ccs[i] = val; - break; - case 20: - if (notes.prog != val || is_lock) { - ccs[3] = val; - } - else { - ccs[3] = 255; - } - break; - default: - i = param - 8 + 4; - if (param < 20) { - // If the parameter is CC value and the CC dest is not yet set, use the - // kit value for CC dest - uint8_t j = i - 1; - if ((param & 1) && ccs[j] == 255) { - ccs[j] = MD.kit.params[track_number][param - 1]; - } - ccs[i] = val; - } - break; - } -} - void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uint16_t lock_idx) { diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index aba38624d..29a6d7c01 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -41,9 +41,6 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { TrigNotes notes; - const uint8_t number_midi_cc = 6 * 2 + 4; - const uint8_t midi_cc_array_size = 6 * 2 + 4; - MDSeqTrack() : SeqSlideTrack() { active = MD_TRACK_TYPE; } ALWAYS_INLINE() void reset() { SeqSlideTrack::reset(); @@ -132,8 +129,6 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { memcpy(¬es.note1, MD.kit.params[track_number], 5); notes.count_down = 0; } - void process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, bool is_lock = false); - void send_notes_ccs(uint8_t *ccs, bool send_ccs); void send_notes(uint8_t first_note = 255); void send_notes_on(); void send_notes_off(); diff --git a/avr/cores/megacommand/MCL/SeqTrack.cpp b/avr/cores/megacommand/MCL/SeqTrack.cpp index e605c1895..1f9f4486c 100644 --- a/avr/cores/megacommand/MCL/SeqTrack.cpp +++ b/avr/cores/megacommand/MCL/SeqTrack.cpp @@ -73,6 +73,12 @@ void SeqSlideTrack::prepare_slide(uint8_t lock_idx, int16_t x0, int16_t x1, int8 } void SeqSlideTrack::send_slides(volatile uint8_t *locks_params, uint8_t channel) { + uint8_t ccs[midi_cc_array_size]; + bool send_ccs = false; + bool is_midi_model = (MD.kit.models[track_number] & 0xF0) == MID_01_MODEL; + if (is_midi_model) { + memset(ccs, 255, sizeof(ccs)); + } for (uint8_t c = 0; c < NUM_LOCKS; c++) { if ((locks_params[c] > 0) && (locks_slide_data[c].dy > 0)) { @@ -110,7 +116,14 @@ void SeqSlideTrack::send_slides(volatile uint8_t *locks_params, uint8_t channel) uint8_t param = locks_params[c] - 1; switch (active) { case MD_TRACK_TYPE: - MD.setTrackParam_inline(track_number, param, val); + if (is_midi_model) { + uint8_t p = param; + send_ccs |= (p > 4 && p < 8) | (p > 8) && (p & 1) | (p == 20); + process_note_locks(p, val, ccs, true); + } + else { + MD.setTrackParam_inline(track_number, param, val); + } break; default: if (param == PARAM_PB) { @@ -126,6 +139,9 @@ void SeqSlideTrack::send_slides(volatile uint8_t *locks_params, uint8_t channel) } } } + if (is_midi_model) { + send_notes_ccs(ccs, send_ccs); + } } uint8_t SeqTrackBase::get_quantized_step(uint8_t &utiming, uint8_t quant) { @@ -230,3 +246,87 @@ bool SeqTrack::conditional(uint8_t condition) { } return send_note; } + +/* For MD MIDI Machines below */ + +void SeqSlideTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + if (send_ccs) { + for (uint8_t n = 0; n < number_midi_cc; n++) { + if (ccs[n] == 255) continue; + switch (n) { + case 0: + uart2->sendPitchBend(channel, ccs[0] << 7); + break; + case 1: + uart2->sendCC(channel, 0x1, ccs[1]); + break; + case 2: + uart2->sendChannelPressure(channel, ccs[2]); + break; + case 3: + mcl_seq.md_tracks[track_number].notes.prog = ccs[3]; + uart2->sendProgramChange(channel, ccs[15]); + break; + default: + if (!(n & 1)) continue; + uint8_t a = ccs[n - 1]; + if (a > 0 && a != 255) { + uint8_t v = ccs[n]; + // 0 = off + // 1 = bank (0) + // 2 = 2 + if (a == 1) { + a = 0; + }; + uart2->sendCC(channel, a, v); + break; + } + } + } + } +} + +void SeqSlideTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, + bool is_lock) { + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + TrigNotes *notes = &mcl_seq.md_tracks[track_number].notes; + uint8_t i = param - 5; + switch (param) { + case 0: + case 1: + case 2: + case 3: + case 4: + //note values are set via init_notes initially. + ((uint8_t *)notes)[param] = val; + //ccs[param] = val; not required. + break; + case 5: + case 6: + case 7: + ccs[i] = val; + break; + case 20: + if (notes->prog != val || is_lock) { + ccs[3] = val; + } + else { + ccs[3] = 255; + } + break; + default: + i = param - 8 + 4; + if (param < 20) { + // If the parameter is CC value and the CC dest is not yet set, use the + // kit value for CC dest + uint8_t j = i - 1; + if ((param & 1) && ccs[j] == 255) { + ccs[j] = MD.kit.params[track_number][param - 1]; + } + ccs[i] = val; + } + break; + } +} + diff --git a/avr/cores/megacommand/MCL/SeqTrack.h b/avr/cores/megacommand/MCL/SeqTrack.h index eb700f1ea..30aa0fac9 100644 --- a/avr/cores/megacommand/MCL/SeqTrack.h +++ b/avr/cores/megacommand/MCL/SeqTrack.h @@ -350,6 +350,9 @@ class SeqSlideTrack : public SeqTrack { uint8_t locks_slides_recalc = 255; uint16_t locks_slides_idx = 0; + const uint8_t number_midi_cc = 6 * 2 + 4; + const uint8_t midi_cc_array_size = 6 * 2 + 4; + ALWAYS_INLINE() void reset() { for (uint8_t n = 0; n < NUM_LOCKS; n++) { locks_slide_data[n].init(); @@ -361,6 +364,11 @@ class SeqSlideTrack : public SeqTrack { void prepare_slide(uint8_t lock_idx, int16_t x0, int16_t x1, int8_t y0, int8_t y1); void send_slides(volatile uint8_t *locks_params, uint8_t channel = 0); + + void process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, bool is_lock = false); + void send_notes_ccs(uint8_t *ccs, bool send_ccs); + + }; #endif /* SEQTRACK_H__ */ From 3b1f81d82294a02b1484ac43ae318faac5cbb1bf Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 21 Jul 2024 21:37:12 +1000 Subject: [PATCH 057/133] implement slides for MID tracks --- avr/cores/megacommand/MCL/MCL.h | 2 +- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 81 ++++++++++++++++++++++ avr/cores/megacommand/MCL/MDSeqTrack.h | 5 ++ avr/cores/megacommand/MCL/SeqTrack.cpp | 87 +----------------------- avr/cores/megacommand/MCL/SeqTrack.h | 4 -- 5 files changed, 89 insertions(+), 90 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index c229cf840..8ef822161 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -17,7 +17,7 @@ #include "Fonts/TomThumb.h" #define VERSION 4052 -#define VERSION_STR "G4.52" +#define VERSION_STR "H4.52" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index ecf004c54..d9586f155 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -434,6 +434,87 @@ void MDSeqTrack::send_parameter_locks(uint8_t step, bool trig, send_parameter_locks_inline(step, trig, idx); } +void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + if (send_ccs) { + for (uint8_t n = 0; n < number_midi_cc; n++) { + if (ccs[n] == 255) continue; + switch (n) { + case 0: + uart2->sendPitchBend(channel, ccs[0] << 7); + break; + case 1: + uart2->sendCC(channel, 0x1, ccs[1]); + break; + case 2: + uart2->sendChannelPressure(channel, ccs[2]); + break; + case 3: + notes.prog = ccs[3]; + uart2->sendProgramChange(channel, ccs[15]); + break; + default: + if (!(n & 1)) continue; + uint8_t a = ccs[n - 1]; + if (a > 0 && a != 255) { + uint8_t v = ccs[n]; + // 0 = off + // 1 = bank (0) + // 2 = 2 + if (a == 1) { + a = 0; + }; + uart2->sendCC(channel, a, v); + break; + } + } + } + } +} + +void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, + bool is_lock) { + uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; + + uint8_t i = param - 5; + switch (param) { + case 0: + case 1: + case 2: + case 3: + case 4: + //note values are set via init_notes initially. + ((uint8_t *)¬es)[param] = val; + //ccs[param] = val; not required. + break; + case 5: + case 6: + case 7: + ccs[i] = val; + break; + case 20: + if (notes.prog != val || is_lock) { + ccs[3] = val; + } + else { + ccs[3] = 255; + } + break; + default: + i = param - 8 + 4; + if (param < 20) { + // If the parameter is CC value and the CC dest is not yet set, use the + // kit value for CC dest + uint8_t j = i - 1; + if ((param & 1) && ccs[j] == 255) { + ccs[j] = MD.kit.params[track_number][param - 1]; + } + ccs[i] = val; + } + break; + } +} + void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uint16_t lock_idx) { diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 29a6d7c01..aba38624d 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -41,6 +41,9 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { TrigNotes notes; + const uint8_t number_midi_cc = 6 * 2 + 4; + const uint8_t midi_cc_array_size = 6 * 2 + 4; + MDSeqTrack() : SeqSlideTrack() { active = MD_TRACK_TYPE; } ALWAYS_INLINE() void reset() { SeqSlideTrack::reset(); @@ -129,6 +132,8 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { memcpy(¬es.note1, MD.kit.params[track_number], 5); notes.count_down = 0; } + void process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, bool is_lock = false); + void send_notes_ccs(uint8_t *ccs, bool send_ccs); void send_notes(uint8_t first_note = 255); void send_notes_on(); void send_notes_off(); diff --git a/avr/cores/megacommand/MCL/SeqTrack.cpp b/avr/cores/megacommand/MCL/SeqTrack.cpp index 1f9f4486c..2f5540208 100644 --- a/avr/cores/megacommand/MCL/SeqTrack.cpp +++ b/avr/cores/megacommand/MCL/SeqTrack.cpp @@ -119,7 +119,7 @@ void SeqSlideTrack::send_slides(volatile uint8_t *locks_params, uint8_t channel) if (is_midi_model) { uint8_t p = param; send_ccs |= (p > 4 && p < 8) | (p > 8) && (p & 1) | (p == 20); - process_note_locks(p, val, ccs, true); + mcl_seq.md_tracks[track_number].process_note_locks(p, val, ccs, true); } else { MD.setTrackParam_inline(track_number, param, val); @@ -140,7 +140,7 @@ void SeqSlideTrack::send_slides(volatile uint8_t *locks_params, uint8_t channel) } } if (is_midi_model) { - send_notes_ccs(ccs, send_ccs); + mcl_seq.md_tracks[track_number].send_notes_ccs(ccs, send_ccs); } } @@ -247,86 +247,3 @@ bool SeqTrack::conditional(uint8_t condition) { return send_note; } -/* For MD MIDI Machines below */ - -void SeqSlideTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { - uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - if (send_ccs) { - for (uint8_t n = 0; n < number_midi_cc; n++) { - if (ccs[n] == 255) continue; - switch (n) { - case 0: - uart2->sendPitchBend(channel, ccs[0] << 7); - break; - case 1: - uart2->sendCC(channel, 0x1, ccs[1]); - break; - case 2: - uart2->sendChannelPressure(channel, ccs[2]); - break; - case 3: - mcl_seq.md_tracks[track_number].notes.prog = ccs[3]; - uart2->sendProgramChange(channel, ccs[15]); - break; - default: - if (!(n & 1)) continue; - uint8_t a = ccs[n - 1]; - if (a > 0 && a != 255) { - uint8_t v = ccs[n]; - // 0 = off - // 1 = bank (0) - // 2 = 2 - if (a == 1) { - a = 0; - }; - uart2->sendCC(channel, a, v); - break; - } - } - } - } -} - -void SeqSlideTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, - bool is_lock) { - uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; - TrigNotes *notes = &mcl_seq.md_tracks[track_number].notes; - uint8_t i = param - 5; - switch (param) { - case 0: - case 1: - case 2: - case 3: - case 4: - //note values are set via init_notes initially. - ((uint8_t *)notes)[param] = val; - //ccs[param] = val; not required. - break; - case 5: - case 6: - case 7: - ccs[i] = val; - break; - case 20: - if (notes->prog != val || is_lock) { - ccs[3] = val; - } - else { - ccs[3] = 255; - } - break; - default: - i = param - 8 + 4; - if (param < 20) { - // If the parameter is CC value and the CC dest is not yet set, use the - // kit value for CC dest - uint8_t j = i - 1; - if ((param & 1) && ccs[j] == 255) { - ccs[j] = MD.kit.params[track_number][param - 1]; - } - ccs[i] = val; - } - break; - } -} - diff --git a/avr/cores/megacommand/MCL/SeqTrack.h b/avr/cores/megacommand/MCL/SeqTrack.h index 30aa0fac9..f894f2d2c 100644 --- a/avr/cores/megacommand/MCL/SeqTrack.h +++ b/avr/cores/megacommand/MCL/SeqTrack.h @@ -365,10 +365,6 @@ class SeqSlideTrack : public SeqTrack { int8_t y1); void send_slides(volatile uint8_t *locks_params, uint8_t channel = 0); - void process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, bool is_lock = false); - void send_notes_ccs(uint8_t *ccs, bool send_ccs); - - }; #endif /* SEQTRACK_H__ */ From 83a0fce97122190e77b4cbd1c18a3c568517f2da Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 22 Jul 2024 16:33:16 +1000 Subject: [PATCH 058/133] prevent convert function from being linked --- avr/cores/megacommand/MCL/ExtTrack.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/ExtTrack.h b/avr/cores/megacommand/MCL/ExtTrack.h index 840883470..f626c4ae8 100644 --- a/avr/cores/megacommand/MCL/ExtTrack.h +++ b/avr/cores/megacommand/MCL/ExtTrack.h @@ -37,7 +37,7 @@ class ExtTrack : public DeviceTrack { } virtual void load_immediate(uint8_t tracknumber, SeqTrack *seq_track); - bool virtual convert(ExtTrack_270 *old) { + bool convert(ExtTrack_270 *old) { link.row = old->link.row; link.loops = old->link.loops; if (link.row >= GRID_LENGTH) { From 85b05b09964d8ffd8244dbc444b24e7d6abb53ee Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 22 Jul 2024 16:33:28 +1000 Subject: [PATCH 059/133] MID track arp support + rec --- avr/cores/megacommand/MCL/ArpSeqTrack.cpp | 19 ++++++++++++----- avr/cores/megacommand/MCL/ArpSeqTrack.h | 2 +- avr/cores/megacommand/MCL/MCLSeq.cpp | 6 +++--- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 26 +++++++++++++---------- avr/cores/megacommand/MCL/MDSeqTrack.h | 6 +++--- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 19 +++++++++++------ avr/cores/megacommand/MCL/SeqPtcPage.h | 2 +- 7 files changed, 49 insertions(+), 31 deletions(-) diff --git a/avr/cores/megacommand/MCL/ArpSeqTrack.cpp b/avr/cores/megacommand/MCL/ArpSeqTrack.cpp index 0adddfa43..f68b27bea 100644 --- a/avr/cores/megacommand/MCL/ArpSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/ArpSeqTrack.cpp @@ -19,9 +19,11 @@ void ArpSeqTrack::set_length(uint8_t length_) { } } -void ArpSeqTrack::seq(MidiUartParent *uart_) { +void ArpSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { MidiUartParent *uart_old = uart; + MidiUartParent *uart2_old = uart2; uart = uart_; + uart2 = uart2_; uint8_t timing_mid = get_timing_mid_inline(); @@ -29,12 +31,13 @@ void ArpSeqTrack::seq(MidiUartParent *uart_) { if (mod12_counter == timing_mid) { step_count_inc(); if (active == EXT_ARP_TRACK_TYPE && last_note_on != 255 && step_count == length / 2) { - seq_ptc_page.note_off_ext(last_note_on, 0, track_number, uart); + seq_ptc_page.note_off_ext(last_note_on, 0, track_number, uart2_); last_note_on = 255; } mod12_counter = 0; } - + bool is_midi_model = + ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); if (mod12_counter == 0 && enabled && mute_state == SEQ_MUTE_OFF) { if (step_count == 0) { if (len > 0) { @@ -42,10 +45,15 @@ void ArpSeqTrack::seq(MidiUartParent *uart_) { note += oct*12; switch (active) { case MD_ARP_TRACK_TYPE: - seq_ptc_page.trig_md(note, track_number, CTRL_EVENT, fine_tune, uart); + if (is_midi_model) { + mcl_seq.md_tracks[track_number].send_notes(note, uart2_); + seq_ptc_page.record(note, track_number); + } else { + seq_ptc_page.trig_md(note, track_number, CTRL_EVENT, fine_tune, uart_); + } break; case EXT_ARP_TRACK_TYPE: - seq_ptc_page.note_on_ext(note, 127, track_number, uart); + seq_ptc_page.note_on_ext(note, 127, track_number, uart2_); last_note_on = note; break; } @@ -57,6 +65,7 @@ void ArpSeqTrack::seq(MidiUartParent *uart_) { } } uart = uart_old; + uart2 = uart2_old; } #define NOTE_RANGE 128 diff --git a/avr/cores/megacommand/MCL/ArpSeqTrack.h b/avr/cores/megacommand/MCL/ArpSeqTrack.h index 28679fc67..ce16bc03b 100644 --- a/avr/cores/megacommand/MCL/ArpSeqTrack.h +++ b/avr/cores/megacommand/MCL/ArpSeqTrack.h @@ -80,7 +80,7 @@ class ArpSeqTrack : public ArpSeqData, public SeqTrackBase { SeqTrackBase::reset(); } - ALWAYS_INLINE() void seq(MidiUartParent *uart_); + ALWAYS_INLINE() void seq(MidiUartParent *uart_, MidiUartParent *uart2_); void clear_track(); void re_sync(); void set_speed(uint8_t speed_); diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index f544a292a..dffce4ca3 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -234,7 +234,7 @@ void MCLSeq::seq() { for (uint8_t i = 0; i < num_md_tracks; i++) { md_tracks[i].seq(uart,uart2); md_arp_tracks[i].mute_state = md_tracks[i].mute_state; - md_arp_tracks[i].seq(uart); + md_arp_tracks[i].seq(uart,uart2); } if (MDSeqTrack::md_trig_mask > 0) { @@ -263,7 +263,7 @@ void MCLSeq::seq() { for (uint8_t i = 0; i < num_ext_tracks; i++) { ext_tracks[i].seq(uart2); ext_arp_tracks[i].mute_state = ext_tracks[i].mute_state; - ext_arp_tracks[i].seq(uart2); + ext_arp_tracks[i].seq(uart,uart2); } #endif @@ -289,7 +289,7 @@ void MCLSeqMidiEvents::onNoteCallback_Midi(uint8_t *msg) { if (n < 16) { bool is_midi_machine = ((MD.kit.models[n] & 0xF0) == MID_01_MODEL); if (is_midi_machine) { - if (msg[2]) {mcl_seq.md_tracks[n].send_notes(); } + if (msg[2]) {mcl_seq.md_tracks[n].send_notes(255,false); } //velocity 0 == NoteOff else { mcl_seq.md_tracks[n].send_notes_off(); } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index d9586f155..446977eca 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -612,43 +612,47 @@ void MDSeqTrack::get_step_locks(uint8_t step, uint8_t *params, } } -void MDSeqTrack::send_notes(uint8_t note1) { +void MDSeqTrack::send_notes(uint8_t note1, bool is_seq, MidiUartParent *uart2_) { + if (!uart2_) { uart2_ = uart2; } if (notes.count_down) { - send_notes_off(); + send_notes_off(uart2_); } init_notes(); if (note1 != 255) { notes.note1 = note1; } if (notes.first_trig) { reset_params(); notes.first_trig = false; } - send_notes_on(); + if (is_seq) { uint8_t timing_mid = get_timing_mid(); notes.count_down = (notes.len * timing_mid / 2); } + send_notes_on(uart2_); } -void MDSeqTrack::send_notes_on() { +void MDSeqTrack::send_notes_on(MidiUartParent *uart2_) { + if (!uart2_) { uart2_ = uart2; } TrigNotes *n = ¬es; uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; if (n->note1 != 255) { mixer_page.trig(track_number); - uart2->sendNoteOn(channel, n->note1, n->vel); + uart2_->sendNoteOn(channel, n->note1, n->vel); if (n->note2 != 64) { - uart2->sendNoteOn(channel, n->note1 + n->note2 - 64, n->vel); + uart2_->sendNoteOn(channel, n->note1 + n->note2 - 64, n->vel); } if (n->note3 != 64) { - uart2->sendNoteOn(channel, n->note1 + n->note3 - 64, n->vel); + uart2_->sendNoteOn(channel, n->note1 + n->note3 - 64, n->vel); } } } -void MDSeqTrack::send_notes_off() { +void MDSeqTrack::send_notes_off(MidiUartParent *uart2_) { + if (!uart2_) { uart2_ = uart2; } TrigNotes *n = ¬es; uint8_t channel = MD.kit.models[track_number] - MID_01_MODEL; if (n->note1 != 255) { - uart2->sendNoteOff(channel, n->note1); + uart2_->sendNoteOff(channel, n->note1); if (n->note2 != 64) { - uart2->sendNoteOff(channel, n->note1 + n->note2 - 64); + uart2_->sendNoteOff(channel, n->note1 + n->note2 - 64); } if (n->note3 != 64) { - uart2->sendNoteOff(channel, n->note1 + n->note3 - 64); + uart2_->sendNoteOff(channel, n->note1 + n->note3 - 64); } n->note1 = 255; } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index aba38624d..367b49f12 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -134,9 +134,9 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { } void process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, bool is_lock = false); void send_notes_ccs(uint8_t *ccs, bool send_ccs); - void send_notes(uint8_t first_note = 255); - void send_notes_on(); - void send_notes_off(); + void send_notes(uint8_t first_note = 255, bool is_seq = true, MidiUartParent *uart2_ = nullptr); + void send_notes_on(MidiUartParent *uart2_ = nullptr); + void send_notes_off(MidiUartParent *uart2_ = nullptr); void onControlChangeCallback_Midi(uint8_t track_param,uint8_t value); }; diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index 806866073..15917cd74 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -421,9 +421,10 @@ void SeqPtcPage::trig_md(uint8_t note_num, uint8_t track_number, uint8_t channel bool is_midi_model_ = ((MD.kit.models[track_number] & 0xF0) == MID_01_MODEL); if (is_midi_model_) { machine_pitch = note_num; - mcl_seq.md_tracks[track_number].send_notes_off(); - mcl_seq.md_tracks[track_number].send_notes(machine_pitch); - goto record; + next_track = track_number; + mcl_seq.md_tracks[next_track].send_notes_off(); + mcl_seq.md_tracks[next_track].send_notes(machine_pitch); + goto rec; } if (machine_pitch == 255) { return; @@ -432,14 +433,18 @@ void SeqPtcPage::trig_md(uint8_t note_num, uint8_t track_number, uint8_t channel MD.setTrackParam(next_track, 0, machine_pitch, uart_); MD.triggerTrack(next_track, 127, uart_); mixer_page.trig(next_track); - record: + rec: + record(next_track,machine_pitch); +} + +void SeqPtcPage::record(uint8_t pitch, uint8_t track) { if ((recording) && (MidiClock.state == 2)) { reset_undo(); - mcl_seq.md_tracks[next_track].record_track(127); - mcl_seq.md_tracks[next_track].record_track_pitch(machine_pitch); + mcl_seq.md_tracks[track].record_track(127); + mcl_seq.md_tracks[track].record_track_pitch(pitch); } -} +} void SeqPtcPage::note_on_ext(uint8_t note_num, uint8_t velocity, uint8_t track_number, MidiUartParent *uart_) { if (track_number == 255) { diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index ad4f676c0..bb6b0d21c 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -71,7 +71,7 @@ class SeqPtcPage : public SeqPage, public ClockCallback { uint8_t fine_tune = 255); uint8_t get_next_voice(uint8_t pitch, uint8_t track_number, uint8_t channel_event); uint8_t calc_scale_note(uint8_t note_num, bool padded = false); - + void record(uint8_t pitch, uint8_t tracknumber); void trig_md(uint8_t note_num, uint8_t track_number = 255, uint8_t channel_event = CTRL_EVENT, uint8_t fine_tune = 255, MidiUartParent *uart_ = nullptr); From ffda3b75b77915f8aceaf7677454f20016aa094e Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 22 Jul 2024 16:35:54 +1000 Subject: [PATCH 060/133] Revert "llm suggestion for find_next_locks. not bad" This reverts commit 70c295bbef1f3af84839712e0a2569b2076d1e44. --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 38 +---------------------- avr/cores/megacommand/MCL/WavDesigner.cpp | 2 +- 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 446977eca..62f235bba 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -269,43 +269,7 @@ void MDSeqTrack::recalc_slides() { end: locks_slides_recalc = 255; } -void MDSeqTrack::find_next_locks(uint8_t curidx, uint8_t step, uint8_t mask) { - uint8_t next_step = step + 1; - uint8_t max_len = length; - curidx += popcount(steps[step].locks); // Using original popcount lookup - - for (;;) { - if (next_step >= max_len) { - next_step = 0; - curidx = 0; - max_len = step; - } - - uint8_t lcks = get_step_locks(next_step); - uint8_t combined = mask & (lcks | (steps[next_step].trig ? 0xFF : 0)); - - while (combined) { - uint8_t cur_mask = combined & -combined; // Get lowest set bit - uint8_t i = popcount(cur_mask - 1); // Use popcount to get index - - if (lcks & cur_mask) { - locks_slide_next_lock_val[i] = locks[curidx]; - curidx++; - } else { - locks_slide_next_lock_val[i] = MD.kit.params[track_number][locks_params[i] - 1]; - } - locks_slide_next_lock_step[i] = next_step; - - mask &= ~cur_mask; - combined &= ~cur_mask; - if (!mask) return; // All targets hit - } - - next_step++; - } -} -/* void MDSeqTrack::find_next_locks(uint8_t curidx, uint8_t step, uint8_t mask) { DEBUG_PRINT_FN(); DEBUG_DUMP(step); @@ -349,7 +313,7 @@ void MDSeqTrack::find_next_locks(uint8_t curidx, uint8_t step, uint8_t mask) { goto again; } } -*/ + void MDSeqTrack::get_mask(uint64_t *_pmask, uint8_t mask_type) const { *_pmask = 0; for (uint8_t i = 0; i < NUM_MD_STEPS; i++) { diff --git a/avr/cores/megacommand/MCL/WavDesigner.cpp b/avr/cores/megacommand/MCL/WavDesigner.cpp index 0e7ad8d97..1feaef3af 100644 --- a/avr/cores/megacommand/MCL/WavDesigner.cpp +++ b/avr/cores/megacommand/MCL/WavDesigner.cpp @@ -238,7 +238,7 @@ bool WavDesigner::render() { } bool WavDesigner::send() { - return midi_sds.sendWav(WAV_NAME, WAV_NAME, mixer.enc4.cur, false); + return midi_sds.sendWav(WAV_NAME, mixer.enc4.cur, false); } WavDesigner wd; From dd3d39fe05f6db7e80fcac156869b10590734e99 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 22 Jul 2024 16:39:41 +1000 Subject: [PATCH 061/133] WavDesigner permissive fix --- avr/cores/megacommand/MCL/WavDesigner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/WavDesigner.cpp b/avr/cores/megacommand/MCL/WavDesigner.cpp index 1feaef3af..0e7ad8d97 100644 --- a/avr/cores/megacommand/MCL/WavDesigner.cpp +++ b/avr/cores/megacommand/MCL/WavDesigner.cpp @@ -238,7 +238,7 @@ bool WavDesigner::render() { } bool WavDesigner::send() { - return midi_sds.sendWav(WAV_NAME, mixer.enc4.cur, false); + return midi_sds.sendWav(WAV_NAME, WAV_NAME, mixer.enc4.cur, false); } WavDesigner wd; From c44de3597f86e096f78e30b65ad63eb0dd13a572 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 23 Jul 2024 13:36:25 +1000 Subject: [PATCH 062/133] LFO states were never properly stored/transmitted to the MD. Fix Fibonacci seed when both are 0 --- avr/cores/megacommand/MD/MDMessages.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/avr/cores/megacommand/MD/MDMessages.cpp b/avr/cores/megacommand/MD/MDMessages.cpp index b73ddc256..3d5b3f239 100644 --- a/avr/cores/megacommand/MD/MDMessages.cpp +++ b/avr/cores/megacommand/MD/MDMessages.cpp @@ -9,8 +9,6 @@ #define MDX_KIT_VERSION 64 -uint8_t lfo_statestore[31]; - void MDMachine::scale_vol(float scale) { params[MODEL_VOL] = (uint8_t)((float)params[MODEL_VOL] * scale); if (params[MODEL_VOL] > 127) { @@ -206,8 +204,7 @@ bool MDKit::fromSysex(MidiClass *midi) { decoder.start7Bit(); for (uint8_t i = 0; i < 16; i++) { - decoder.get((uint8_t *)&lfos[i], 5); - decoder.get((uint8_t *)&lfo_statestore, 31); + decoder.get((uint8_t *)&lfos[i], 5 + 31); } decoder.stop7Bit(); @@ -264,9 +261,9 @@ uint16_t MDKit::toSysex(ElektronDataToSysexEncoder *encoder) { encoder->start7Bit(); for (uint8_t i = 0; i < 16; i++) { // encoder->pack((uint8_t *)&lfos[i], 36); - - encoder->pack((uint8_t *)&lfos[i], 5); - encoder->pack((uint8_t *)&lfo_statestore[i], 31); + uint16_t *lfo_states2 = (uint16_t *) &lfos[i].state[5 + 18]; + if (!lfo_states2[0] && !lfo_states2[1]) { lfo_states2[1] = 0x29a; } //666 + encoder->pack((uint8_t *)&lfos[i], 5 + 31); } encoder->stop7Bit(); From 275c3cc5368090edcf2de1ec8ef55bd2f2710d31 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 23 Jul 2024 13:49:07 +1000 Subject: [PATCH 063/133] Note len fix for 0 --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 62f235bba..dc9675853 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -191,7 +191,7 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { } if (send_trig == TRIG_TRUE && step.trig) { if (is_midi_model) { - notes.count_down = (notes.len * timing_mid / 2); + notes.count_down = notes.len == 0 ? timing_mid / 4 : (notes.len * timing_mid / 2); send_notes_on(); } send_trig_inline(); @@ -584,7 +584,7 @@ void MDSeqTrack::send_notes(uint8_t note1, bool is_seq, MidiUartParent *uart2_) init_notes(); if (note1 != 255) { notes.note1 = note1; } if (notes.first_trig) { reset_params(); notes.first_trig = false; } - if (is_seq) { uint8_t timing_mid = get_timing_mid(); notes.count_down = (notes.len * timing_mid / 2); } + if (is_seq) { uint8_t timing_mid = get_timing_mid(); notes.count_down = notes.len == 0 ? timing_mid / 4 : (notes.len * timing_mid / 2);; } send_notes_on(uart2_); } From 2df0e5bf09aecbfdc5503ea3ca0a0b470467f8b5 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 25 Jul 2024 14:56:53 +1000 Subject: [PATCH 064/133] regression in grid_slot_apply --- avr/cores/megacommand/MCL/GridPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index 87e498fe9..72231c6c9 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -638,7 +638,7 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { if (old_col == 255) { - if (!swap_grids()) { return; } + if (swap_grids()) { return; } } uint8_t load_mode_old = mcl_cfg.load_mode; From 275b3d18e9d88bf84a01e41d042e999cd40ab0ac Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 25 Jul 2024 15:41:24 +1000 Subject: [PATCH 065/133] record regression, add MID machine support for trig event --- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index 15917cd74..57450d406 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -434,7 +434,7 @@ void SeqPtcPage::trig_md(uint8_t note_num, uint8_t track_number, uint8_t channel MD.triggerTrack(next_track, 127, uart_); mixer_page.trig(next_track); rec: - record(next_track,machine_pitch); + record(machine_pitch, next_track); } void SeqPtcPage::record(uint8_t pitch, uint8_t track) { @@ -761,7 +761,13 @@ void SeqPtcMidiEvents::note_on(uint8_t *msg, uint8_t channel_event) { if (pos > 15) { return; } - MD.triggerTrack(pos, msg[2]); + bool is_midi_model_ = ((MD.kit.models[pos] & 0xF0) == MID_01_MODEL);; + if (is_midi_model_) { + mcl_seq.md_tracks[pos].send_notes_on(); + } + else { + MD.triggerTrack(pos, msg[2]); + } if ((seq_ptc_page.recording) && (MidiClock.state == 2)) { reset_undo(); mcl_seq.md_tracks[pos].record_track(msg[2]); @@ -830,7 +836,7 @@ void SeqPtcMidiEvents::note_off(uint8_t *msg, uint8_t channel_event) { seq_ptc_page.render_arp(false, SeqPage::midi_device, n); if (pitch == 255) { return; } ArpSeqTrack *arp_track = &mcl_seq.md_arp_tracks[n]; - bool is_midi_model_ = ((MD.kit.models[n] & 0xF0) == MID_01_MODEL);; + bool is_midi_model_ = ((MD.kit.models[n] & 0xF0) == MID_01_MODEL); if (is_midi_model_) { if (!arp_track->enabled || (MidiClock.state != 2)) { mcl_seq.md_tracks[n].send_notes_off(); From cc4d6d02bce96a1dee7f862cb0af383a2c1adfba Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 25 Jul 2024 16:03:32 +1000 Subject: [PATCH 066/133] use note_len when sequencer is running --- avr/cores/megacommand/MCL/MCLSeq.cpp | 5 +++-- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 11 ++++++----- avr/cores/megacommand/MCL/MDSeqTrack.h | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index dffce4ca3..ce1c7dac9 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -289,9 +289,10 @@ void MCLSeqMidiEvents::onNoteCallback_Midi(uint8_t *msg) { if (n < 16) { bool is_midi_machine = ((MD.kit.models[n] & 0xF0) == MID_01_MODEL); if (is_midi_machine) { - if (msg[2]) {mcl_seq.md_tracks[n].send_notes(255,false); } + if (msg[2]) {mcl_seq.md_tracks[n].send_notes(255); } //velocity 0 == NoteOff - else { mcl_seq.md_tracks[n].send_notes_off(); } + //Only send note off if the sequener is not running, otherwise defer to note length + else if (MidiClock.state != 2) { mcl_seq.md_tracks[n].send_notes_off(); } } if (msg[0] != 153 && msg[2]) { diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index dc9675853..9a08f5be5 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -108,7 +108,7 @@ void MDSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { uart = uart_; uart2 = uart2_; - uint8_t timing_mid = get_timing_mid_inline(); + uint8_t timing_mid = get_timing_mid(); mod12_counter++; @@ -223,7 +223,7 @@ void MDSeqTrack::recalc_slides() { int16_t x0, x1; int8_t y0, y1; uint8_t step = locks_slides_recalc; - uint8_t timing_mid = get_timing_mid_inline(); + uint8_t timing_mid = get_timing_mid(); uint8_t find_mask = 0; uint8_t cur_mask = 1; @@ -535,7 +535,7 @@ void MDSeqTrack::reset_params() { uint8_t ccs[midi_cc_array_size]; bool send_ccs = true; memcpy(ccs, &MD.kit.params[track_number][5], sizeof(ccs)); - ccs[4] = 255; //disable program change + ccs[3] = 255; //disable program change //notes.prog = MD.kit.params[track_number][20]; //process_note_locks(20, MD.kit.params[track_number][20],ccs); send_notes_ccs(ccs, send_ccs); @@ -576,7 +576,7 @@ void MDSeqTrack::get_step_locks(uint8_t step, uint8_t *params, } } -void MDSeqTrack::send_notes(uint8_t note1, bool is_seq, MidiUartParent *uart2_) { +void MDSeqTrack::send_notes(uint8_t note1, MidiUartParent *uart2_) { if (!uart2_) { uart2_ = uart2; } if (notes.count_down) { send_notes_off(uart2_); @@ -584,7 +584,8 @@ void MDSeqTrack::send_notes(uint8_t note1, bool is_seq, MidiUartParent *uart2_) init_notes(); if (note1 != 255) { notes.note1 = note1; } if (notes.first_trig) { reset_params(); notes.first_trig = false; } - if (is_seq) { uint8_t timing_mid = get_timing_mid(); notes.count_down = notes.len == 0 ? timing_mid / 4 : (notes.len * timing_mid / 2);; } + uint8_t timing_mid = get_timing_mid(); + notes.count_down = notes.len == 0 ? timing_mid / 4 : (notes.len * timing_mid / 2); send_notes_on(uart2_); } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 367b49f12..94a53e83c 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -134,7 +134,7 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { } void process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, bool is_lock = false); void send_notes_ccs(uint8_t *ccs, bool send_ccs); - void send_notes(uint8_t first_note = 255, bool is_seq = true, MidiUartParent *uart2_ = nullptr); + void send_notes(uint8_t first_note = 255, MidiUartParent *uart2_ = nullptr); void send_notes_on(MidiUartParent *uart2_ = nullptr); void send_notes_off(MidiUartParent *uart2_ = nullptr); From a7e0c1a70f4a50b30a66b739e480d802a68f7412 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 25 Jul 2024 16:19:07 +1000 Subject: [PATCH 067/133] Fix cc and prog mapping yet again --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 9a08f5be5..08df4d2e4 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -404,18 +404,18 @@ void MDSeqTrack::send_notes_ccs(uint8_t *ccs, bool send_ccs) { for (uint8_t n = 0; n < number_midi_cc; n++) { if (ccs[n] == 255) continue; switch (n) { - case 0: - uart2->sendPitchBend(channel, ccs[0] << 7); - break; case 1: - uart2->sendCC(channel, 0x1, ccs[1]); + uart2->sendPitchBend(channel, ccs[1] << 7); break; case 2: - uart2->sendChannelPressure(channel, ccs[2]); + uart2->sendCC(channel, 0x1, ccs[2]); break; case 3: - notes.prog = ccs[3]; - uart2->sendProgramChange(channel, ccs[15]); + uart2->sendChannelPressure(channel, ccs[3]); + break; + case 0: + notes.prog = ccs[0]; + uart2->sendProgramChange(channel, ccs[0]); break; default: if (!(n & 1)) continue; @@ -454,14 +454,14 @@ void MDSeqTrack::process_note_locks(uint8_t param, uint8_t val, uint8_t *ccs, case 5: case 6: case 7: - ccs[i] = val; + ccs[i + 1] = val; break; case 20: if (notes.prog != val || is_lock) { - ccs[3] = val; + ccs[0] = val; } else { - ccs[3] = 255; + ccs[0] = 255; } break; default: @@ -486,7 +486,7 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, bool send_ccs = false; if (notes.first_trig) { // first note, we want to send all CCs regardless if they dont have locks. - memcpy(ccs, &MD.kit.params[track_number][5], sizeof(ccs)); + memcpy(ccs + 1, &MD.kit.params[track_number][5], sizeof(ccs) - 1); //prevent re-transmission of program change. //process_note_locks(20, MD.kit.params[track_number][20],ccs); send_ccs = true; @@ -534,8 +534,8 @@ void MDSeqTrack::reset_params() { if (is_midi_model) { uint8_t ccs[midi_cc_array_size]; bool send_ccs = true; - memcpy(ccs, &MD.kit.params[track_number][5], sizeof(ccs)); - ccs[3] = 255; //disable program change + memcpy(ccs + 1, &MD.kit.params[track_number][5], sizeof(ccs) - 1); + ccs[0] = 255; //disable program change //notes.prog = MD.kit.params[track_number][20]; //process_note_locks(20, MD.kit.params[track_number][20],ccs); send_notes_ccs(ccs, send_ccs); From a5525f3ed10ebb20d92301e7470c5d90da0b1a1f Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 25 Jul 2024 16:24:29 +1000 Subject: [PATCH 068/133] as per elektron --- avr/cores/megacommand/MD/MDMessages.h | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/avr/cores/megacommand/MD/MDMessages.h b/avr/cores/megacommand/MD/MDMessages.h index 1e36fc7b1..18ee88646 100644 --- a/avr/cores/megacommand/MD/MDMessages.h +++ b/avr/cores/megacommand/MD/MDMessages.h @@ -161,17 +161,11 @@ class MDLFO { uint8_t mix; void init(uint8_t track) { - destinationTrack = track; - destinationParam = 0; - shape1 = 0; - shape2 = 0; - type = 0; - for (uint8_t i = 0; i < 31; i++) { - state[i] = i; - } - speed = 64; - depth = 0; - mix = 0; + memset(&destinationTrack,0,sizeof(this)); + destinationTrack = track; + speed = 64; + uint16_t *lfo_states2 = (uint16_t *) &state[5 + 18]; + lfo_states2[1] = 0x29a; //666 } /* @} */ }; From 22f0f860e7354accdccb69d795b884555aac2867 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 26 Jul 2024 13:49:24 +1000 Subject: [PATCH 069/133] refactor elektron commands --- avr/cores/megacommand/Elektron/Elektron.cpp | 200 ++++++++++---------- avr/cores/megacommand/Elektron/Elektron.h | 20 ++ 2 files changed, 124 insertions(+), 96 deletions(-) diff --git a/avr/cores/megacommand/Elektron/Elektron.cpp b/avr/cores/megacommand/Elektron/Elektron.cpp index 7b23ec046..92f21cc29 100644 --- a/avr/cores/megacommand/Elektron/Elektron.cpp +++ b/avr/cores/megacommand/Elektron/Elektron.cpp @@ -154,53 +154,103 @@ void ElektronDevice::activate_encoder_interface(uint8_t *params) { //waitBlocking(); } -void ElektronDevice::deactivate_encoder_interface() { - uint8_t data[3] = {0x70, 0x36, 0x00}; - sendRequest(data, sizeof(data)); - encoder_interface = false; - //waitBlocking(); -} - -void ElektronDevice::activate_enhanced_midi() { - uint8_t data[3] = {0x70, 0x3E, 0x01}; - sendRequest(data, sizeof(data)); - // waitBlocking(); -} -void ElektronDevice::deactivate_enhanced_midi() { - uint8_t data[3] = {0x70, 0x3E, 0x00}; - sendRequest(data, sizeof(data)); - // waitBlocking(); -} +void ElektronDevice::sendCommand(ElektronCommand command, uint8_t param) { + uint8_t data[3] = {0x70, 0x00, 0x00}; + bool needsWait = false; + uint8_t l = 3; + switch (command) { + case ElektronCommand::DeactivateEncoderInterface: + data[1] = 0x36; + data[2] = 0x00; + encoder_interface = false; + break; + case ElektronCommand::ActivateEnhancedMidi: + data[1] = 0x3E; + data[2] = 0x01; + break; + case ElektronCommand::DeactivateEnhancedMidi: + data[1] = 0x3E; + data[2] = 0x00; + break; + case ElektronCommand::ActivateEnhancedGui: + data[1] = 0x37; + data[2] = 0x01; + break; + case ElektronCommand::DeactivateEnhancedGui: + data[1] = 0x37; + data[2] = 0x00; + break; + case ElektronCommand::SetSeqPage: + data[1] = 0x38; + data[2] = param; + break; + case ElektronCommand::SetRecMode: + data[1] = 0x3A; + data[2] = param; + break; + case ElektronCommand::SetKeyRepeat: + data[1] = 0x4E; + data[2] = param; + break; + case ElektronCommand::ActivateTrigInterface: + data[1] = 0x31; + data[2] = 0x01; + break; + case ElektronCommand::DeactivateTrigInterface: + data[1] = 0x31; + data[2] = 0x00; + break; + case ElektronCommand::ActivateTrackSelect: + data[1] = 0x32; + data[2] = 0x01; + needsWait = true; + break; + case ElektronCommand::DeactivateTrackSelect: + data[1] = 0x32; + data[2] = 0x00; + needsWait = true; + break; + case ElektronCommand::UndokitSync: + data[1] = 0x42; + l = 2; + break; + case ElektronCommand::ResetDspParams: + data[1] = 0x43; + l = 2; + break; + case ElektronCommand::DrawCloseBank: + data[1] = 0x3C; + data[2] = 0x23; + break; + case ElektronCommand::DrawCloseMicrotiming: + data[1] = 0x3C; + data[2] = 0x21; + break; + default: + return; // Invalid command + } -void ElektronDevice::activate_enhanced_gui() { - uint8_t data[3] = {0x70, 0x37, 0x01}; - sendRequest(data, sizeof(data)); - // waitBlocking(); + sendRequest(data, l); + if (needsWait) { + waitBlocking(); + } } -void ElektronDevice::deactivate_enhanced_gui() { - uint8_t data[3] = {0x70, 0x37, 0x00}; - sendRequest(data, sizeof(data)); - // waitBlocking(); -} -void ElektronDevice::set_seq_page(uint8_t page) { - uint8_t data[3] = {0x70, 0x38, page}; - sendRequest(data, sizeof(data)); +void ElektronDevice::draw_microtiming(uint8_t speed, uint8_t timing) { + uint8_t a = timing >> 7; + uint8_t b = timing & 0x7F; + uint8_t data[6] = {0x70, 0x3C, 0x20, speed, a, b}; + sendRequest(data, 6); // waitBlocking(); } -void ElektronDevice::set_rec_mode(uint8_t mode) { - uint8_t data[3] = {0x70, 0x3A, mode}; - sendRequest(data, sizeof(data)); +void ElektronDevice::draw_pattern_idx(uint8_t idx, uint8_t idx_other, uint8_t chain_mask) { + uint8_t data[6] = {0x70, 0x3C, 0x24, idx, idx_other, chain_mask }; + sendRequest(data, 6); // waitBlocking(); } -void ElektronDevice::set_key_repeat(uint8_t mode) { - uint8_t data[3] = {0x70, 0x4E, mode}; - sendRequest(data, sizeof(data)); - // waitBlocking(); -} void ElektronDevice::popup_text(uint8_t action_string, uint8_t persistent) { uint8_t data[4] = {0x70, 0x3B, persistent, action_string}; @@ -221,66 +271,24 @@ void ElektronDevice::draw_bank(uint8_t bank) { sendRequest(data, 5); // waitBlocking(); } -void ElektronDevice::draw_close_bank() { - uint8_t data[3] = {0x70, 0x3C, 0x23}; - sendRequest(data, 3); - // waitBlocking(); -} - -void ElektronDevice::draw_microtiming(uint8_t speed, uint8_t timing) { - uint8_t a = timing >> 7; - uint8_t b = timing & 0x7F; - uint8_t data[6] = {0x70, 0x3C, 0x20, speed, a, b}; - sendRequest(data, 6); - // waitBlocking(); -} -void ElektronDevice::draw_close_microtiming() { - uint8_t data[3] = {0x70, 0x3C, 0x21}; - sendRequest(data, 3); - // waitBlocking(); -} - -void ElektronDevice::draw_pattern_idx(uint8_t idx, uint8_t idx_other, uint8_t chain_mask) { - uint8_t data[6] = {0x70, 0x3C, 0x24, idx, idx_other, chain_mask }; - sendRequest(data, 6); - // waitBlocking(); -} - - -void ElektronDevice::activate_trig_interface() { - uint8_t data[3] = {0x70, 0x31, 0x01}; - sendRequest(data, sizeof(data)); - // waitBlocking(); -} - -void ElektronDevice::deactivate_trig_interface() { - uint8_t data[3] = {0x70, 0x31, 0x00}; - sendRequest(data, sizeof(data)); - // waitBlocking(); -} - -void ElektronDevice::activate_track_select() { - uint8_t data[3] = {0x70, 0x32, 0x01}; - sendRequest(data, sizeof(data)); - waitBlocking(); -} - -void ElektronDevice::deactivate_track_select() { - uint8_t data[3] = {0x70, 0x32, 0x00}; - sendRequest(data, sizeof(data)); - waitBlocking(); -} - -void ElektronDevice::undokit_sync() { - uint8_t data[2] = { 0x70, 0x42 }; - sendRequest(data, sizeof(data)); -} - -void ElektronDevice::reset_dsp_params() { - uint8_t data[2] = { 0x70, 0x43 }; - sendRequest(data, sizeof(data)); -} +// Implement the individual functions using the central sendCommand function +void ElektronDevice::deactivate_encoder_interface() { sendCommand(ElektronCommand::DeactivateEncoderInterface, 0); } +void ElektronDevice::activate_enhanced_midi() { sendCommand(ElektronCommand::ActivateEnhancedMidi, 0); } +void ElektronDevice::deactivate_enhanced_midi() { sendCommand(ElektronCommand::DeactivateEnhancedMidi, 0); } +void ElektronDevice::activate_enhanced_gui() { sendCommand(ElektronCommand::ActivateEnhancedGui, 0); } +void ElektronDevice::deactivate_enhanced_gui() { sendCommand(ElektronCommand::DeactivateEnhancedGui, 0); } +void ElektronDevice::set_seq_page(uint8_t page) { sendCommand(ElektronCommand::SetSeqPage, page); } +void ElektronDevice::set_rec_mode(uint8_t mode) { sendCommand(ElektronCommand::SetRecMode, mode); } +void ElektronDevice::set_key_repeat(uint8_t mode) { sendCommand(ElektronCommand::SetKeyRepeat, mode); } +void ElektronDevice::activate_trig_interface() { sendCommand(ElektronCommand::ActivateTrigInterface, 0); } +void ElektronDevice::deactivate_trig_interface() { sendCommand(ElektronCommand::DeactivateTrigInterface, 0); } +void ElektronDevice::activate_track_select() { sendCommand(ElektronCommand::ActivateTrackSelect, 0); } +void ElektronDevice::deactivate_track_select() { sendCommand(ElektronCommand::DeactivateTrackSelect, 0); } +void ElektronDevice::undokit_sync() { sendCommand(ElektronCommand::UndokitSync, 0); } +void ElektronDevice::reset_dsp_params() { sendCommand(ElektronCommand::ResetDspParams, 0); } +void ElektronDevice::draw_close_bank() { sendCommand(ElektronCommand::DrawCloseBank, 0); } +void ElektronDevice::draw_close_microtiming() { sendCommand(ElektronCommand::DrawCloseMicrotiming, 0); } void ElektronDevice::set_trigleds(uint16_t bitmask, TrigLEDMode mode, diff --git a/avr/cores/megacommand/Elektron/Elektron.h b/avr/cores/megacommand/Elektron/Elektron.h index 1c58e0f0b..8bca13d8d 100644 --- a/avr/cores/megacommand/Elektron/Elektron.h +++ b/avr/cores/megacommand/Elektron/Elektron.h @@ -261,6 +261,25 @@ enum TrigLEDMode { TRIGLED_MUTE = 4 }; +enum class ElektronCommand { + DeactivateEncoderInterface, + ActivateEnhancedMidi, + DeactivateEnhancedMidi, + ActivateEnhancedGui, + DeactivateEnhancedGui, + SetSeqPage, + SetRecMode, + SetKeyRepeat, + ActivateTrigInterface, + DeactivateTrigInterface, + ActivateTrackSelect, + DeactivateTrackSelect, + UndokitSync, + ResetDspParams, + DrawCloseBank, + DrawCloseMicrotiming +}; + /// sysex constants for constructing data frames class ElektronSysexProtocol { public: @@ -434,6 +453,7 @@ class ElektronDevice : public MidiDevice { * are wrapped in appropriate methods like requestKit, * requestPattern, etc... **/ + void sendCommand(ElektronCommand command, uint8_t param); virtual uint16_t sendRequest(uint8_t *data, uint8_t len, bool send = true, MidiUartParent *uart_ = nullptr); virtual uint16_t sendRequest(uint8_t type, uint8_t param, bool send = true); /** From 1391d66c5d74bba885cb33b8df1de975e9f3c298 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 26 Jul 2024 14:21:21 +1000 Subject: [PATCH 070/133] Refactor elektron drivers --- avr/cores/megacommand/A4/A4.cpp | 79 ++++++-------------- avr/cores/megacommand/A4/A4.h | 2 +- avr/cores/megacommand/A4/A4Sysex.cpp | 35 +-------- avr/cores/megacommand/A4/A4Sysex.h | 26 ------- avr/cores/megacommand/Elektron/Elektron.cpp | 67 +++++------------ avr/cores/megacommand/Elektron/Elektron.h | 55 ++------------ avr/cores/megacommand/MCL/PageSelectPage.cpp | 2 +- avr/cores/megacommand/MCL/PageSelectPage.h | 2 +- avr/cores/megacommand/MD/MD.cpp | 11 +-- avr/cores/megacommand/MD/MDSysex.cpp | 15 +--- avr/cores/megacommand/MD/MDSysex.h | 13 +--- avr/cores/megacommand/MNM/MNMSysex.cpp | 11 +-- 12 files changed, 63 insertions(+), 255 deletions(-) diff --git a/avr/cores/megacommand/A4/A4.cpp b/avr/cores/megacommand/A4/A4.cpp index 74c31ce57..0342a5cb4 100644 --- a/avr/cores/megacommand/A4/A4.cpp +++ b/avr/cores/megacommand/A4/A4.cpp @@ -152,82 +152,49 @@ void A4Class::requestGlobalX(uint8_t global) { sendRequest(A4_GLOBALX_REQUEST_ID, global); } -bool A4Class::getBlockingSound(uint8_t sound, uint16_t timeout) { - SysexCallback cb; - A4SysexListener.addOnSoundMessageCallback( - &cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); - requestSound(sound); - connected = cb.waitBlocking(timeout); - A4SysexListener.removeOnSoundMessageCallback(&cb); +bool A4Class::getBlockingGeneric(uint16_t timeout) { + SysexCallback cb; + A4SysexListener.addOnMessageCallback(&cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); + bool connected = cb.waitBlocking(timeout); + A4SysexListener.removeOnMessageCallback(&cb); + return connected; +} - return connected; +bool A4Class::getBlockingSound(uint8_t sound, uint16_t timeout) { + requestSound(sound); + return getBlockingGeneric(timeout); } bool A4Class::getBlockingSettings(uint8_t settings, uint16_t timeout) { - SysexCallback cb; - A4SysexListener.addOnSettingsMessageCallback( - &cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); - requestSettings(settings); - connected = cb.waitBlocking(timeout); - A4SysexListener.removeOnSettingsMessageCallback(&cb); - - return connected; + requestSettings(settings); + return getBlockingGeneric(timeout); } bool A4Class::getBlockingKitX(uint8_t kit, uint16_t timeout) { - SysexCallback cb; - A4SysexListener.addOnKitMessageCallback( - &cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); - requestKitX(kit); - connected = cb.waitBlocking(timeout); - A4SysexListener.removeOnKitMessageCallback(&cb); - - return connected; + requestKitX(kit); + return getBlockingGeneric(timeout); } bool A4Class::getBlockingPatternX(uint8_t pattern, uint16_t timeout) { - SysexCallback cb; - A4SysexListener.addOnPatternMessageCallback( - &cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); - requestPatternX(pattern); - connected = cb.waitBlocking(timeout); - A4SysexListener.removeOnPatternMessageCallback(&cb); - - return connected; + requestPatternX(pattern); + return getBlockingGeneric(timeout); } bool A4Class::getBlockingGlobalX(uint8_t global, uint16_t timeout) { - SysexCallback cb; - A4SysexListener.addOnGlobalMessageCallback( - &cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); - requestGlobalX(global); - connected = cb.waitBlocking(timeout); - A4SysexListener.removeOnGlobalMessageCallback(&cb); - - return connected; + requestGlobalX(global); + return getBlockingGeneric(timeout); } bool A4Class::getBlockingSoundX(uint8_t sound, uint16_t timeout) { - SysexCallback cb; - A4SysexListener.addOnSoundMessageCallback( - &cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); - requestSoundX(sound); - connected = cb.waitBlocking(timeout); - A4SysexListener.removeOnSoundMessageCallback(&cb); - - return connected; + requestSoundX(sound); + return getBlockingGeneric(timeout); } bool A4Class::getBlockingSettingsX(uint8_t settings, uint16_t timeout) { - SysexCallback cb; - A4SysexListener.addOnSettingsMessageCallback( - &cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); - requestSettingsX(settings); - connected = cb.waitBlocking(timeout); - A4SysexListener.removeOnSettingsMessageCallback(&cb); - - return connected; + requestSettingsX(settings); + return getBlockingGeneric(timeout); } + void A4Class::muteTrack(uint8_t track, bool mute, MidiUartParent *uart_) { if (uart_ == nullptr) { uart_ = uart; } uart->sendCC(track, 94, mute); diff --git a/avr/cores/megacommand/A4/A4.h b/avr/cores/megacommand/A4/A4.h index eefb5ab58..e458fadbd 100644 --- a/avr/cores/megacommand/A4/A4.h +++ b/avr/cores/megacommand/A4/A4.h @@ -84,7 +84,7 @@ class A4Class : public ElektronDevice { } virtual uint8_t get_mute_cc() { return 0x5E; } - + bool getBlockingGeneric(uint16_t timeout); /*X denotes get from RAM/unsaved */ bool getBlockingKitX(uint8_t kit, uint16_t timeout = 3000); bool getBlockingPatternX(uint8_t pattern, uint16_t timeout = 3000); diff --git a/avr/cores/megacommand/A4/A4Sysex.cpp b/avr/cores/megacommand/A4/A4Sysex.cpp index 02956634a..dd09a214f 100644 --- a/avr/cores/megacommand/A4/A4Sysex.cpp +++ b/avr/cores/megacommand/A4/A4Sysex.cpp @@ -52,51 +52,18 @@ void A4SysexListenerClass::end() { // break; case A4_GLOBAL_MESSAGE_ID: - onGlobalMessageCallbacks.call(); - break; - case A4_GLOBALX_MESSAGE_ID: - onGlobalMessageCallbacks.call(); - break; - case A4_KIT_MESSAGE_ID: - onKitMessageCallbacks.call(); - break; - case A4_KITX_MESSAGE_ID: - onKitMessageCallbacks.call(); - break; - case A4_SOUND_MESSAGE_ID: - onSoundMessageCallbacks.call(); - break; - case A4_SOUNDX_MESSAGE_ID: - onSoundMessageCallbacks.call(); - break; - case A4_PATTERN_MESSAGE_ID: - onPatternMessageCallbacks.call(); - break; - case A4_PATTERNX_MESSAGE_ID: - onPatternMessageCallbacks.call(); - break; - case A4_SONG_MESSAGE_ID: - onSongMessageCallbacks.call(); - break; - case A4_SONGX_MESSAGE_ID: - onSongMessageCallbacks.call(); - break; - case A4_SETTINGS_MESSAGE_ID: - onSettingsMessageCallbacks.call(); - break; - case A4_SETTINGSX_MESSAGE_ID: - onSettingsMessageCallbacks.call(); + onMessageCallbacks.call(); break; } diff --git a/avr/cores/megacommand/A4/A4Sysex.h b/avr/cores/megacommand/A4/A4Sysex.h index 883cde1a0..966c046d2 100644 --- a/avr/cores/megacommand/A4/A4Sysex.h +++ b/avr/cores/megacommand/A4/A4Sysex.h @@ -17,10 +17,6 @@ class A4SysexListenerClass : public ElektronSysexListenerClass { **/ public: - CallbackVector onSoundMessageCallbacks; - - CallbackVector onSettingsMessageCallbacks; - /** Stores if the currently received message is a MachineDrum sysex message. * **/ bool isA4Message; @@ -40,28 +36,6 @@ class A4SysexListenerClass : public ElektronSysexListenerClass { * automatically by the A4Task subsystem though). **/ void setup(MidiClass *_midi); - - void addOnSoundMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onSoundMessageCallbacks.add(obj, func); - } - void removeOnSoundMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onSoundMessageCallbacks.remove(obj, func); - } - void removeOnSoundMessageCallback(SysexCallback *obj) { - onSoundMessageCallbacks.remove(obj); - } - - void addOnSettingsMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onSettingsMessageCallbacks.add(obj, func); - } - void removeOnSettingsMessageCallback(SysexCallback *obj, - sysex_callback_ptr_t func) { - onSettingsMessageCallbacks.remove(obj, func); - } - void removeOnSettingsMessageCallback(SysexCallback *obj) { - onSettingsMessageCallbacks.remove(obj); - } - /* @} */ }; diff --git a/avr/cores/megacommand/Elektron/Elektron.cpp b/avr/cores/megacommand/Elektron/Elektron.cpp index 92f21cc29..a301ca4e6 100644 --- a/avr/cores/megacommand/Elektron/Elektron.cpp +++ b/avr/cores/megacommand/Elektron/Elektron.cpp @@ -135,7 +135,6 @@ bool ElektronDevice::get_fw_caps() { void ElektronDevice::activate_encoder_interface(uint8_t *params) { encoder_interface = true; uint8_t data[3 + 4 + 24] = {0x70, 0x36, 0x01}; - uint8_t mod7 = 0; uint8_t cnt = 0; @@ -154,31 +153,24 @@ void ElektronDevice::activate_encoder_interface(uint8_t *params) { //waitBlocking(); } +void ElektronDevice::deactivate_encoder_interface() { sendCommand(ElektronCommand::ActivateEncoderInterface, 0); } + void ElektronDevice::sendCommand(ElektronCommand command, uint8_t param) { uint8_t data[3] = {0x70, 0x00, 0x00}; bool needsWait = false; uint8_t l = 3; switch (command) { - case ElektronCommand::DeactivateEncoderInterface: + case ElektronCommand::ActivateEncoderInterface: data[1] = 0x36; - data[2] = 0x00; - encoder_interface = false; - break; + data[2] = param;; + encoder_interface = param; case ElektronCommand::ActivateEnhancedMidi: data[1] = 0x3E; - data[2] = 0x01; - break; - case ElektronCommand::DeactivateEnhancedMidi: - data[1] = 0x3E; - data[2] = 0x00; + data[2] = param; break; case ElektronCommand::ActivateEnhancedGui: data[1] = 0x37; - data[2] = 0x01; - break; - case ElektronCommand::DeactivateEnhancedGui: - data[1] = 0x37; - data[2] = 0x00; + data[2] = param; break; case ElektronCommand::SetSeqPage: data[1] = 0x38; @@ -194,20 +186,11 @@ void ElektronDevice::sendCommand(ElektronCommand command, uint8_t param) { break; case ElektronCommand::ActivateTrigInterface: data[1] = 0x31; - data[2] = 0x01; - break; - case ElektronCommand::DeactivateTrigInterface: - data[1] = 0x31; - data[2] = 0x00; + data[2] = param; break; case ElektronCommand::ActivateTrackSelect: data[1] = 0x32; - data[2] = 0x01; - needsWait = true; - break; - case ElektronCommand::DeactivateTrackSelect: - data[1] = 0x32; - data[2] = 0x00; + data[2] = param; needsWait = true; break; case ElektronCommand::UndokitSync: @@ -273,18 +256,17 @@ void ElektronDevice::draw_bank(uint8_t bank) { } // Implement the individual functions using the central sendCommand function -void ElektronDevice::deactivate_encoder_interface() { sendCommand(ElektronCommand::DeactivateEncoderInterface, 0); } -void ElektronDevice::activate_enhanced_midi() { sendCommand(ElektronCommand::ActivateEnhancedMidi, 0); } -void ElektronDevice::deactivate_enhanced_midi() { sendCommand(ElektronCommand::DeactivateEnhancedMidi, 0); } -void ElektronDevice::activate_enhanced_gui() { sendCommand(ElektronCommand::ActivateEnhancedGui, 0); } -void ElektronDevice::deactivate_enhanced_gui() { sendCommand(ElektronCommand::DeactivateEnhancedGui, 0); } +void ElektronDevice::activate_enhanced_midi() { sendCommand(ElektronCommand::ActivateEnhancedMidi, 1); } +void ElektronDevice::deactivate_enhanced_midi() { sendCommand(ElektronCommand::ActivateEnhancedMidi, 0); } +void ElektronDevice::activate_enhanced_gui() { sendCommand(ElektronCommand::ActivateEnhancedGui, 1); } +void ElektronDevice::deactivate_enhanced_gui() { sendCommand(ElektronCommand::ActivateEnhancedGui, 0); } void ElektronDevice::set_seq_page(uint8_t page) { sendCommand(ElektronCommand::SetSeqPage, page); } void ElektronDevice::set_rec_mode(uint8_t mode) { sendCommand(ElektronCommand::SetRecMode, mode); } void ElektronDevice::set_key_repeat(uint8_t mode) { sendCommand(ElektronCommand::SetKeyRepeat, mode); } -void ElektronDevice::activate_trig_interface() { sendCommand(ElektronCommand::ActivateTrigInterface, 0); } +void ElektronDevice::activate_trig_interface() { sendCommand(ElektronCommand::ActivateTrigInterface, 1); } void ElektronDevice::deactivate_trig_interface() { sendCommand(ElektronCommand::DeactivateTrigInterface, 0); } -void ElektronDevice::activate_track_select() { sendCommand(ElektronCommand::ActivateTrackSelect, 0); } -void ElektronDevice::deactivate_track_select() { sendCommand(ElektronCommand::DeactivateTrackSelect, 0); } +void ElektronDevice::activate_track_select() { sendCommand(ElektronCommand::ActivateTrackSelect, 1); } +void ElektronDevice::deactivate_track_select() { sendCommand(ElektronCommand::ActivateTrackSelect, 0); } void ElektronDevice::undokit_sync() { sendCommand(ElektronCommand::UndokitSync, 0); } void ElektronDevice::reset_dsp_params() { sendCommand(ElektronCommand::ResetDspParams, 0); } void ElektronDevice::draw_close_bank() { sendCommand(ElektronCommand::DrawCloseBank, 0); } @@ -360,34 +342,23 @@ bool ElektronDevice::getBlockingData(DataType type, uint8_t index, uint16_t time ; while (count--) { + + listener->addOnMessageCallback(&cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); switch (type) { case DataType::Kit: - listener->addOnKitMessageCallback(&cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); requestKit(index); break; case DataType::Pattern: - listener->addOnPatternMessageCallback(&cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); requestPattern(index); break; case DataType::Global: - listener->addOnGlobalMessageCallback(&cb, (sysex_callback_ptr_t)&SysexCallback::onSysexReceived); requestGlobal(index); break; } ret = cb.waitBlocking(timeout); - switch (type) { - case DataType::Kit: - listener->removeOnKitMessageCallback(&cb); - break; - case DataType::Pattern: - listener->removeOnPatternMessageCallback(&cb); - break; - case DataType::Global: - listener->removeOnGlobalMessageCallback(&cb); - break; - } + listener->removeOnMessageCallback(&cb); if (ret) { midi->midiSysex.rd_cur = listener->msg_rd; diff --git a/avr/cores/megacommand/Elektron/Elektron.h b/avr/cores/megacommand/Elektron/Elektron.h index 8bca13d8d..75e8ecb5a 100644 --- a/avr/cores/megacommand/Elektron/Elektron.h +++ b/avr/cores/megacommand/Elektron/Elektron.h @@ -185,18 +185,9 @@ class ElektronSysexListenerClass : public MidiSysexListenerClass { public: /** Vector storing the onGlobalMessage callbacks (called when a global message * is received). **/ - CallbackVector onGlobalMessageCallbacks; + CallbackVector onMessageCallbacks; /** Vector storing the onKitMessage callbacks (called when a kit message is * received). **/ - CallbackVector onKitMessageCallbacks; - /** Vector storing the onSongMessage callbacks (called when a song messages is - * received). **/ - CallbackVector onSongMessageCallbacks; - /** Vector storing the onPatternMessage callbacks (called when a pattern - * message is received). **/ - CallbackVector onPatternMessageCallbacks; - /** Vector storing the onStatusResponse callbacks (when a status response is - * received). **/ CallbackVector2 onStatusResponseCallbacks; void addOnStatusResponseCallback(SysexCallback *obj, @@ -211,44 +202,14 @@ class ElektronSysexListenerClass : public MidiSysexListenerClass { onStatusResponseCallbacks.remove(obj); } - void addOnGlobalMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onGlobalMessageCallbacks.add(obj, func); - } - void removeOnGlobalMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onGlobalMessageCallbacks.remove(obj, func); - } - void removeOnGlobalMessageCallback(SysexCallback *obj) { - onGlobalMessageCallbacks.remove(obj); - } - - void addOnKitMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onKitMessageCallbacks.add(obj, func); - } - void removeOnKitMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onKitMessageCallbacks.remove(obj, func); - } - void removeOnKitMessageCallback(SysexCallback *obj) { - onKitMessageCallbacks.remove(obj); - } - - void addOnPatternMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onPatternMessageCallbacks.add(obj, func); - } - void removeOnPatternMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onPatternMessageCallbacks.remove(obj, func); - } - void removeOnPatternMessageCallback(SysexCallback *obj) { - onPatternMessageCallbacks.remove(obj); - } - - void addOnSongMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onSongMessageCallbacks.add(obj, func); + void addOnMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { + onMessageCallbacks.add(obj, func); } - void removeOnSongMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onSongMessageCallbacks.remove(obj, func); + void removeOnMessageCallback(SysexCallback *obj, sysex_callback_ptr_t func) { + onMessageCallbacks.remove(obj, func); } - void removeOnSongMessageCallback(SysexCallback *obj) { - onSongMessageCallbacks.remove(obj); + void removeOnMessageCallback(SysexCallback *obj) { + onMessageCallbacks.remove(obj); } }; @@ -262,7 +223,7 @@ enum TrigLEDMode { }; enum class ElektronCommand { - DeactivateEncoderInterface, + ActivateEncoderInterface, ActivateEnhancedMidi, DeactivateEnhancedMidi, ActivateEnhancedGui, diff --git a/avr/cores/megacommand/MCL/PageSelectPage.cpp b/avr/cores/megacommand/MCL/PageSelectPage.cpp index fd0432fa2..6472e3a05 100644 --- a/avr/cores/megacommand/MCL/PageSelectPage.cpp +++ b/avr/cores/megacommand/MCL/PageSelectPage.cpp @@ -110,7 +110,7 @@ void PageSelectPage::draw_popup() { void PageSelectPage::md_prepare() { kit_cb.init(); auto listener = MD.getSysexListener(); - listener->addOnKitMessageCallback( + listener->addOnMessageCallback( &kit_cb, (sysex_callback_ptr_t)&MDCallback::onReceived); MD.requestKit(0x7F); } diff --git a/avr/cores/megacommand/MCL/PageSelectPage.h b/avr/cores/megacommand/MCL/PageSelectPage.h index a83cc5391..645a5f522 100644 --- a/avr/cores/megacommand/MCL/PageSelectPage.h +++ b/avr/cores/megacommand/MCL/PageSelectPage.h @@ -34,7 +34,7 @@ class MDCallback : public SysexCallback { mcl_seq.update_kit_params(); } auto listener = MD.getSysexListener(); - listener->removeOnKitMessageCallback(this); + listener->removeOnMessageCallback(this); state = false; } }; diff --git a/avr/cores/megacommand/MD/MD.cpp b/avr/cores/megacommand/MD/MD.cpp index 5cb4b8f99..8892db52f 100644 --- a/avr/cores/megacommand/MD/MD.cpp +++ b/avr/cores/megacommand/MD/MD.cpp @@ -237,11 +237,12 @@ bool MDClass::probe() { getBlockingKit(0x7F); setup(); - for (uint8_t x = 0; x < 2; x++) { - for (uint8_t y = 0; y < 16; y++) { - mcl_gui.draw_progress_bar(60, 60, false, 60, 25); - setStatus(0x22, y); - } + uint8_t y = 0; + for (uint8_t i = 0; i < 32; i++) { + mcl_gui.draw_progress_bar(60, 60, false, 60, 25); + setStatus(0x22, y); + y++; + if (y == 16) y = 0; } setStatus(0x22, currentTrack); diff --git a/avr/cores/megacommand/MD/MDSysex.cpp b/avr/cores/megacommand/MD/MDSysex.cpp index 1ffd471ca..a43be98fe 100644 --- a/avr/cores/megacommand/MD/MDSysex.cpp +++ b/avr/cores/megacommand/MD/MDSysex.cpp @@ -33,23 +33,10 @@ void MDSysexListenerClass::end() { break; case MD_GLOBAL_MESSAGE_ID: - onGlobalMessageCallbacks.call(); - break; - case MD_KIT_MESSAGE_ID: - onKitMessageCallbacks.call(); - break; - case MD_PATTERN_MESSAGE_ID: - onPatternMessageCallbacks.call(); - break; - case MD_SONG_MESSAGE_ID: - onSongMessageCallbacks.call(); - break; - - case MD_SAMPLE_NAME_ID: - onSampleNameCallbacks.call(); + onMessageCallbacks.call(); break; case MD_SET_RHYTHM_ECHO_PARAM_ID: diff --git a/avr/cores/megacommand/MD/MDSysex.h b/avr/cores/megacommand/MD/MDSysex.h index fa9cb6d09..5b0dba8ee 100644 --- a/avr/cores/megacommand/MD/MDSysex.h +++ b/avr/cores/megacommand/MD/MDSysex.h @@ -51,7 +51,6 @@ class MDSysexListenerClass : public ElektronSysexListenerClass { **/ public: - CallbackVector onSampleNameCallbacks; /** Stores if the currently received message is a MachineDrum sysex message. * **/ bool isMDMessage; @@ -73,17 +72,7 @@ class MDSysexListenerClass : public ElektronSysexListenerClass { **/ void setup(MidiClass *_midi); - void addOnSampleNameCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onSampleNameCallbacks.add(obj, func); - } - void removeOnSampleNameCallback(SysexCallback *obj, sysex_callback_ptr_t func) { - onSampleNameCallbacks.remove(obj, func); - } - void removeOnSampleNameCallback(SysexCallback *obj) { - onSampleNameCallbacks.remove(obj); - } - - /* @} */ + /* @} */ }; #include "MDMessages.h" diff --git a/avr/cores/megacommand/MNM/MNMSysex.cpp b/avr/cores/megacommand/MNM/MNMSysex.cpp index ebe7f6909..99a7d3bd7 100644 --- a/avr/cores/megacommand/MNM/MNMSysex.cpp +++ b/avr/cores/megacommand/MNM/MNMSysex.cpp @@ -28,19 +28,10 @@ void MNMSysexListenerClass::end() { break; case MNM_GLOBAL_MESSAGE_ID: - onGlobalMessageCallbacks.call(); - break; - case MNM_KIT_MESSAGE_ID: - onKitMessageCallbacks.call(); - break; - case MNM_PATTERN_MESSAGE_ID: - onPatternMessageCallbacks.call(); - break; - case MNM_SONG_MESSAGE_ID: - onSongMessageCallbacks.call(); + onMessageCallbacks.call(); break; } } From f3f727686dad45d1102d3871abc3749b6478d00c Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 26 Jul 2024 15:57:48 +1000 Subject: [PATCH 071/133] Trim unused characters from classic font --- .../Adafruit-GFX-Library/Adafruit_GFX.cpp | 7 +- .../Adafruit-GFX-Library/glcdfont.c | 195 ++++++++++++++++++ 2 files changed, 200 insertions(+), 2 deletions(-) diff --git a/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp b/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp index baebef258..844b07093 100755 --- a/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp +++ b/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp @@ -830,8 +830,11 @@ void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, ((y + 8 * size - 1) < 0)) // Clip top return; - if (!_cp437 && (c >= 176)) - c++; // Handle 'classic' charset behavior + + c -= 0x20; //Classic font is reduced in lengthand shifted. + if (c > 126) { c = 0; } + //if (!_cp437 && (c >= 176)) + // c++; // Handle 'classic' charset behavior startWrite(); for (int8_t i = 0; i < 5; i++) { // Char bitmap = 5 columns diff --git a/avr/cores/megacommand/Adafruit-GFX-Library/glcdfont.c b/avr/cores/megacommand/Adafruit-GFX-Library/glcdfont.c index 659c85f43..5bfc7a2f0 100755 --- a/avr/cores/megacommand/Adafruit-GFX-Library/glcdfont.c +++ b/avr/cores/megacommand/Adafruit-GFX-Library/glcdfont.c @@ -14,7 +14,201 @@ #endif // Standard ASCII 5x7 font +// Shifted to begin at 0x32, and limited to +static const unsigned char font[] PROGMEM = { + // Space + 0x00, 0x00, 0x00, 0x00, 0x00, + // Exclamation mark + 0x00, 0x00, 0x5F, 0x00, 0x00, + // Double quote + 0x00, 0x07, 0x00, 0x07, 0x00, + // Hash + 0x14, 0x7F, 0x14, 0x7F, 0x14, + // Dollar sign + 0x24, 0x2A, 0x7F, 0x2A, 0x12, + // Percent sign + 0x23, 0x13, 0x08, 0x64, 0x62, + // Ampersand + 0x36, 0x49, 0x56, 0x20, 0x50, + // Single quote + 0x00, 0x08, 0x07, 0x03, 0x00, + // Open parenthesis + 0x00, 0x1C, 0x22, 0x41, 0x00, + // Close parenthesis + 0x00, 0x41, 0x22, 0x1C, 0x00, + // Asterisk + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, + // Plus + 0x08, 0x08, 0x3E, 0x08, 0x08, + // Comma + 0x00, 0x80, 0x70, 0x30, 0x00, + // Dash + 0x08, 0x08, 0x08, 0x08, 0x08, + // Period + 0x00, 0x00, 0x60, 0x60, 0x00, + // Slash + 0x20, 0x10, 0x08, 0x04, 0x02, + // Digit '0' + 0x3E, 0x51, 0x49, 0x45, 0x3E, + // Digit '1' + 0x00, 0x42, 0x7F, 0x40, 0x00, + // Digit '2' + 0x72, 0x49, 0x49, 0x49, 0x46, + // Digit '3' + 0x21, 0x41, 0x49, 0x4D, 0x33, + // Digit '4' + 0x18, 0x14, 0x12, 0x7F, 0x10, + // Digit '5' + 0x27, 0x45, 0x45, 0x45, 0x39, + // Digit '6' + 0x3C, 0x4A, 0x49, 0x49, 0x31, + // Digit '7' + 0x41, 0x21, 0x11, 0x09, 0x07, + // Digit '8' + 0x36, 0x49, 0x49, 0x49, 0x36, + // Digit '9' + 0x46, 0x49, 0x49, 0x29, 0x1E, + // Colon + 0x00, 0x00, 0x14, 0x00, 0x00, + // Semicolon + 0x00, 0x40, 0x34, 0x00, 0x00, + // Less than + 0x08, 0x14, 0x22, 0x41, 0x00, + // Equal + 0x14, 0x14, 0x14, 0x14, 0x14, + // Greater than + 0x00, 0x41, 0x22, 0x14, 0x08, + // Question mark + 0x02, 0x01, 0x59, 0x09, 0x06, + // At symbol + 0x3E, 0x41, 0x5D, 0x59, 0x4E, + // Uppercase 'A' + 0x7C, 0x12, 0x11, 0x12, 0x7C, + // Uppercase 'B' + 0x7F, 0x49, 0x49, 0x49, 0x36, + // Uppercase 'C' + 0x3E, 0x41, 0x41, 0x41, 0x22, + // Uppercase 'D' + 0x7F, 0x41, 0x41, 0x41, 0x3E, + // Uppercase 'E' + 0x7F, 0x49, 0x49, 0x49, 0x41, + // Uppercase 'F' + 0x7F, 0x09, 0x09, 0x09, 0x01, + // Uppercase 'G' + 0x3E, 0x41, 0x49, 0x49, 0x7A, + // Uppercase 'H' + 0x7F, 0x08, 0x08, 0x08, 0x7F, + // Uppercase 'I' + 0x00, 0x41, 0x7F, 0x41, 0x00, + // Uppercase 'J' + 0x20, 0x40, 0x41, 0x3F, 0x01, + // Uppercase 'K' + 0x7F, 0x08, 0x14, 0x22, 0x41, + // Uppercase 'L' + 0x7F, 0x40, 0x40, 0x40, 0x40, + // Uppercase 'M' + 0x7F, 0x02, 0x0C, 0x02, 0x7F, + // Uppercase 'N' + 0x7F, 0x04, 0x08, 0x10, 0x7F, + // Uppercase 'O' + 0x3E, 0x41, 0x41, 0x41, 0x3E, + // Uppercase 'P' + 0x7F, 0x09, 0x09, 0x09, 0x06, + // Uppercase 'Q' + 0x3E, 0x41, 0x51, 0x21, 0x5E, + // Uppercase 'R' + 0x7F, 0x09, 0x19, 0x29, 0x46, + // Uppercase 'S' + 0x46, 0x49, 0x49, 0x49, 0x31, + // Uppercase 'T' + 0x01, 0x01, 0x7F, 0x01, 0x01, + // Uppercase 'U' + 0x3F, 0x40, 0x40, 0x40, 0x3F, + // Uppercase 'V' + 0x1F, 0x20, 0x40, 0x20, 0x1F, + // Uppercase 'W' + 0x7F, 0x20, 0x18, 0x20, 0x7F, + // Uppercase 'X' + 0x63, 0x14, 0x08, 0x14, 0x63, + // Uppercase 'Y' + 0x03, 0x04, 0x78, 0x04, 0x03, + // Uppercase 'Z' + 0x61, 0x51, 0x49, 0x45, 0x43, + // Open square bracket + 0x00, 0x7F, 0x41, 0x41, 0x00, + // Backslash + 0x02, 0x04, 0x08, 0x10, 0x20, + // Close square bracket + 0x00, 0x41, 0x41, 0x7F, 0x00, + // Caret + 0x04, 0x02, 0x01, 0x02, 0x04, + // Underscore + 0x40, 0x40, 0x40, 0x40, 0x40, + // Grave accent + 0x00, 0x03, 0x07, 0x08, 0x00, + // Lowercase 'a' + 0x20, 0x54, 0x54, 0x54, 0x78, + // Lowercase 'b' + 0x7F, 0x48, 0x44, 0x44, 0x38, + // Lowercase 'c' + 0x38, 0x44, 0x44, 0x44, 0x28, + // Lowercase 'd' + 0x38, 0x44, 0x44, 0x48, 0x7F, + // Lowercase 'e' + 0x38, 0x54, 0x54, 0x54, 0x18, + // Lowercase 'f' + 0x08, 0x7E, 0x09, 0x01, 0x02, + // Lowercase 'g' + 0x0C, 0x52, 0x52, 0x52, 0x3E, + // Lowercase 'h' + 0x7F, 0x08, 0x04, 0x04, 0x78, + // Lowercase 'i' + 0x00, 0x44, 0x7D, 0x40, 0x00, + // Lowercase 'j' + 0x20, 0x40, 0x44, 0x3D, 0x00, + // Lowercase 'k' + 0x7F, 0x10, 0x28, 0x44, 0x00, + // Lowercase 'l' + 0x00, 0x41, 0x7F, 0x40, 0x00, + // Lowercase 'm' + 0x7C, 0x04, 0x18, 0x04, 0x78, + // Lowercase 'n' + 0x7C, 0x08, 0x04, 0x04, 0x78, + // Lowercase 'o' + 0x38, 0x44, 0x44, 0x44, 0x38, + // Lowercase 'p' + 0x7C, 0x14, 0x14, 0x14, 0x08, + // Lowercase 'q' + 0x08, 0x14, 0x14, 0x18, 0x7C, + // Lowercase 'r' + 0x7C, 0x08, 0x04, 0x04, 0x08, + // Lowercase 's' + 0x48, 0x54, 0x54, 0x54, 0x24, + // Lowercase 't' + 0x04, 0x3F, 0x44, 0x40, 0x20, + // Lowercase 'u' + 0x3C, 0x40, 0x40, 0x20, 0x7C, + // Lowercase 'v' + 0x1C, 0x20, 0x40, 0x20, 0x1C, + // Lowercase 'w' + 0x3C, 0x40, 0x30, 0x40, 0x3C, + // Lowercase 'x' + 0x44, 0x28, 0x10, 0x28, 0x44, + // Lowercase 'y' + 0x0C, 0x50, 0x50, 0x50, 0x3C, + // Lowercase 'z' + 0x44, 0x64, 0x54, 0x4C, 0x44, + // Open curly brace + 0x00, 0x08, 0x36, 0x41, 0x00, + // Vertical bar + 0x00, 0x00, 0x7F, 0x00, 0x00, + // Close curly brace + 0x00, 0x41, 0x36, 0x08, 0x00, + // Tilde + 0x08, 0x08, 0x2A, 0x1C, 0x08, + }; +/* static const unsigned char font[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, @@ -273,4 +467,5 @@ static const unsigned char font[] PROGMEM = { 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP }; +*/ #endif // FONT5X7_H From d33c2af157669e5c6abb025b83b75782e20af85d Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 26 Jul 2024 22:21:15 +1000 Subject: [PATCH 072/133] fixes --- avr/cores/megacommand/Elektron/Elektron.cpp | 3 ++- avr/cores/megacommand/Elektron/Elektron.h | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/avr/cores/megacommand/Elektron/Elektron.cpp b/avr/cores/megacommand/Elektron/Elektron.cpp index a301ca4e6..c7be07475 100644 --- a/avr/cores/megacommand/Elektron/Elektron.cpp +++ b/avr/cores/megacommand/Elektron/Elektron.cpp @@ -164,6 +164,7 @@ void ElektronDevice::sendCommand(ElektronCommand command, uint8_t param) { data[1] = 0x36; data[2] = param;; encoder_interface = param; + break; case ElektronCommand::ActivateEnhancedMidi: data[1] = 0x3E; data[2] = param; @@ -264,7 +265,7 @@ void ElektronDevice::set_seq_page(uint8_t page) { sendCommand(ElektronCommand::S void ElektronDevice::set_rec_mode(uint8_t mode) { sendCommand(ElektronCommand::SetRecMode, mode); } void ElektronDevice::set_key_repeat(uint8_t mode) { sendCommand(ElektronCommand::SetKeyRepeat, mode); } void ElektronDevice::activate_trig_interface() { sendCommand(ElektronCommand::ActivateTrigInterface, 1); } -void ElektronDevice::deactivate_trig_interface() { sendCommand(ElektronCommand::DeactivateTrigInterface, 0); } +void ElektronDevice::deactivate_trig_interface() { sendCommand(ElektronCommand::ActivateTrigInterface, 0); } void ElektronDevice::activate_track_select() { sendCommand(ElektronCommand::ActivateTrackSelect, 1); } void ElektronDevice::deactivate_track_select() { sendCommand(ElektronCommand::ActivateTrackSelect, 0); } void ElektronDevice::undokit_sync() { sendCommand(ElektronCommand::UndokitSync, 0); } diff --git a/avr/cores/megacommand/Elektron/Elektron.h b/avr/cores/megacommand/Elektron/Elektron.h index 75e8ecb5a..026575353 100644 --- a/avr/cores/megacommand/Elektron/Elektron.h +++ b/avr/cores/megacommand/Elektron/Elektron.h @@ -225,16 +225,12 @@ enum TrigLEDMode { enum class ElektronCommand { ActivateEncoderInterface, ActivateEnhancedMidi, - DeactivateEnhancedMidi, ActivateEnhancedGui, - DeactivateEnhancedGui, SetSeqPage, SetRecMode, SetKeyRepeat, ActivateTrigInterface, - DeactivateTrigInterface, ActivateTrackSelect, - DeactivateTrackSelect, UndokitSync, ResetDspParams, DrawCloseBank, From 360c4d49462433e2f8c51baabe0214afd6924335 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 5 Aug 2024 13:33:43 +1000 Subject: [PATCH 073/133] fix regression, on_rename --- avr/cores/megacommand/MCL/LoadProjectPage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/MCL/LoadProjectPage.cpp b/avr/cores/megacommand/MCL/LoadProjectPage.cpp index 406c1234d..4802cadc9 100644 --- a/avr/cores/megacommand/MCL/LoadProjectPage.cpp +++ b/avr/cores/megacommand/MCL/LoadProjectPage.cpp @@ -77,11 +77,8 @@ void LoadProjectPage::on_rename(const char *from, const char *to) { char proj_filename[f_len] = {'\0'}; char to_proj_filename[f_len] = {'\0'}; - uint8_t l = strlen(grid_filename); - uint8_t l2 = strlen(to_grid_filename); - bool reload_current = false; - + uint8_t l, l2 = 0; if (!SD.chdir(from)) { goto error; } @@ -98,6 +95,9 @@ void LoadProjectPage::on_rename(const char *from, const char *to) { strncpy(to_grid_filename, to, f_len); strncpy(grid_filename, from, f_len); + l = strlen(grid_filename); + l2 = strlen(to_grid_filename); + for (uint8_t i = 0; i < NUM_GRIDS; i++) { grid_filename[l] = '.'; grid_filename[l + 1] = i + '0'; From 94101927c534cef2f7bd1059b2613171bbfe3e92 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 19 Sep 2024 14:31:27 +1000 Subject: [PATCH 074/133] Add ability to change port1 driver --- avr/cores/megacommand/MCL/MCLMenus.cpp | 2 + avr/cores/megacommand/MCL/MCLMenus.h | 2 +- avr/cores/megacommand/MCL/MCLSysConfig.cpp | 1 + avr/cores/megacommand/MCL/MCLSysConfig.h | 3 +- .../megacommand/MCL/MidiActivePeering.cpp | 18 +- avr/cores/megacommand/MCL/MidiSetup.cpp | 27 +- avr/cores/megacommand/resources/R.h | 8 +- .../megacommand/resources/R_menu_layouts.cpp | 274 +++++++++--------- resource/menu_layouts.cpp | 1 + 9 files changed, 180 insertions(+), 156 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLMenus.cpp b/avr/cores/megacommand/MCL/MCLMenus.cpp index 870fd74c4..0e2a577b6 100644 --- a/avr/cores/megacommand/MCL/MCLMenus.cpp +++ b/avr/cores/megacommand/MCL/MCLMenus.cpp @@ -102,6 +102,8 @@ const uint8_t *const menu_target_param[] PROGMEM = { &perf_page.perf_id, // 60 &mcl_cfg.uart2_cc_mute, + // 61 + &mcl_cfg.uart1_device, }; const menu_function_t menu_target_functions[] PROGMEM = { diff --git a/avr/cores/megacommand/MCL/MCLMenus.h b/avr/cores/megacommand/MCL/MCLMenus.h index 5c62ae2df..3ff9a8b06 100644 --- a/avr/cores/megacommand/MCL/MCLMenus.h +++ b/avr/cores/megacommand/MCL/MCLMenus.h @@ -64,7 +64,7 @@ extern MenuPage ram_config_page; constexpr size_t md_import_page_N = 4; extern MenuPage md_import_page; -constexpr size_t midiport_menu_page_N = 5; +constexpr size_t midiport_menu_page_N = 6; extern MenuPage midiport_menu_page; constexpr size_t midiprogram_menu_page_N = 3; diff --git a/avr/cores/megacommand/MCL/MCLSysConfig.cpp b/avr/cores/megacommand/MCL/MCLSysConfig.cpp index bb03de681..3f7a045e4 100644 --- a/avr/cores/megacommand/MCL/MCLSysConfig.cpp +++ b/avr/cores/megacommand/MCL/MCLSysConfig.cpp @@ -144,6 +144,7 @@ bool MCLSysConfig::cfg_init() { //ram_page_mode = 0; track_select = 1; track_type_select = 0b00000011; + uart1_device = 1; //uart2_device = 0; //uart_cc_loopback = 0; //uart2_prg_mode = 0; diff --git a/avr/cores/megacommand/MCL/MCLSysConfig.h b/avr/cores/megacommand/MCL/MCLSysConfig.h index 65ab7e1a0..0749418c2 100644 --- a/avr/cores/megacommand/MCL/MCLSysConfig.h +++ b/avr/cores/megacommand/MCL/MCLSysConfig.h @@ -4,7 +4,7 @@ #define MCLSYSCONFIG_H__ #include "SdFat.h" -#define CONFIG_VERSION 4010 +#define CONFIG_VERSION 4011 #define MIDI_OMNI_MODE 17 #define MIDI_LOCAL_MODE 0 @@ -67,6 +67,7 @@ class MCLSysConfigData { uint8_t seq_dev; uint8_t uart2_cc_mute; uint8_t uart2_cc_level; + uint8_t uart1_device; }; class MCLSysConfig : public MCLSysConfigData { diff --git a/avr/cores/megacommand/MCL/MidiActivePeering.cpp b/avr/cores/megacommand/MCL/MidiActivePeering.cpp index 545f183da..a4d3863f0 100644 --- a/avr/cores/megacommand/MCL/MidiActivePeering.cpp +++ b/avr/cores/megacommand/MCL/MidiActivePeering.cpp @@ -92,7 +92,7 @@ static void prepare_display(uint8_t *buf) { // the general probe accept whatever devices. static bool midi_device_setup(uint8_t port) { return true; } -static MidiDevice *port1_drivers[] = {&MD}; +static MidiDevice *port1_drivers[] = { &MD }; static MidiDevice *port2_drivers[] = { &MNM, @@ -243,17 +243,21 @@ void MidiActivePeering::run() { } #endif - probePort(UART1_PORT, port1_drivers, countof(port1_drivers), - &connected_midi_devices[0], resource_buf); + MidiDevice **drivers = port1_drivers; + uint8_t nr_drivers = countof(port1_drivers); + if (!mcl_cfg.uart1_device) { + nr_drivers = 1; + drivers = generic_drivers; + } + probePort(UART1_PORT, drivers, nr_drivers, &connected_midi_devices[0], resource_buf); #ifdef EXT_TRACKS - uint8_t nr_drivers = countof(port2_drivers); - MidiDevice **drivers = port2_drivers; + nr_drivers = countof(port2_drivers); + if (!mcl_cfg.uart2_device) { nr_drivers = 1; drivers = generic_drivers; } - probePort(UART2_PORT, drivers, nr_drivers, &connected_midi_devices[1], - resource_buf); + probePort(UART2_PORT, drivers, nr_drivers, &connected_midi_devices[1], resource_buf); if (resource_loaded) { // XXX doesn't work yet // R.Restore(resource_buf, resource_size); diff --git a/avr/cores/megacommand/MCL/MidiSetup.cpp b/avr/cores/megacommand/MCL/MidiSetup.cpp index 630f53882..972f3c764 100644 --- a/avr/cores/megacommand/MCL/MidiSetup.cpp +++ b/avr/cores/megacommand/MCL/MidiSetup.cpp @@ -130,22 +130,31 @@ void MidiSetup::cfg_ports(bool boot) { MidiUSB.uart); } - if (elektron_devs[0]) { - turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart1_turbo_speed), + if (mcl_cfg.uart1_device == 0) { + midi_active_peering.disconnect(UART1_PORT); + midi_active_peering.force_connect(UART1_PORT, &generic_midi_device); + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart1_turbo_speed), + Midi.uart); + } else if (elektron_devs[0]) { + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart1_turbo_speed), Midi.uart); - delay(100); - elektron_devs[0]->setup(); + delay(100); + elektron_devs[0]->setup(); + } else { + midi_active_peering.force_connect(UART1_PORT, &null_midi_device); } + if (mcl_cfg.uart2_device == 0) { - midi_active_peering.force_connect(UART2_PORT, &generic_midi_device); - if (mcl_cfg.uart2_turbo_speed) { + midi_active_peering.disconnect(UART2_PORT); + midi_active_peering.force_connect(UART2_PORT, &generic_midi_device); turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart2_turbo_speed), Midi2.uart); - } } else if (elektron_devs[1]) { - elektron_devs[1]->setup(); turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart2_turbo_speed), - Midi2.uart); + Midi2.uart); + delay(100); + elektron_devs[1]->setup(); + } else { midi_active_peering.force_connect(UART2_PORT, &null_midi_device); } diff --git a/avr/cores/megacommand/resources/R.h b/avr/cores/megacommand/resources/R.h index c78e2ee7e..39043a589 100644 --- a/avr/cores/megacommand/resources/R.h +++ b/avr/cores/megacommand/resources/R.h @@ -424,10 +424,10 @@ struct __T_menu_layouts { static constexpr size_t sizeofof_midiprogram_menu_layout = 74; union { menu_t midiport_menu_layout[0]; - char zz__midiport_menu_layout[116]; + char zz__midiport_menu_layout[137]; }; - static constexpr size_t countof_midiport_menu_layout = 116 / sizeof(menu_t); - static constexpr size_t sizeofof_midiport_menu_layout = 116; + static constexpr size_t countof_midiport_menu_layout = 137 / sizeof(menu_t); + static constexpr size_t sizeofof_midiport_menu_layout = 137; union { menu_t midiconfig_menu_layout[0]; char zz__midiconfig_menu_layout[137]; @@ -464,7 +464,7 @@ struct __T_menu_layouts { }; static constexpr size_t countof_boot_menu_layout = 95 / sizeof(menu_t); static constexpr size_t sizeofof_boot_menu_layout = 95; - static constexpr size_t __total_size = 2131; + static constexpr size_t __total_size = 2152; }; extern const unsigned char __R_menu_options[] PROGMEM; diff --git a/avr/cores/megacommand/resources/R_menu_layouts.cpp b/avr/cores/megacommand/resources/R_menu_layouts.cpp index 5df75eaed..d54010627 100644 --- a/avr/cores/megacommand/resources/R_menu_layouts.cpp +++ b/avr/cores/megacommand/resources/R_menu_layouts.cpp @@ -823,228 +823,234 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 153, 98, 172, - 42, + 63, 136, 155, - 4, + 61, 189, - 96, + 108, 84, - 197, - 76, - 224, + 20, + 25, + 50, + 38, + 4, + 96, 98, - 77, - 5, - 183, - 41, + 97, + 240, + 119, + 38, + 26, + 219, + 62, 56, - 189, - 132, + 210, 194, - 23, - 189, - 62, + 215, + 11, + 210, + 159, 26, 32, - 186, - 109, + 93, + 130, 70, - 21, - 162, - 131, - 97, + 10, + 183, + 193, + 118, + 142, 34, - 28, + 205, + 12, + 80, + 48, + 100, 184, - 24, - 59, - 97, - 79, - 113, 36, - 206, - 100, - 186, - 109, - 210, + 231, + 121, + 207, + 54, + 231, 71, - 128, + 192, 20, - 218, + 97, 37, - 252, - 16, - 6, - 88, + 17, + 66, + 27, + 11, 20, - 12, - 35, - 104, - 120, - 193, + 1, + 141, 35, - 96, - 20, + 141, + 24, 56, + 44, + 20, + 7, 38, 0, - 246, - 88, + 30, + 109, + 219, 40, - 216, 76, 24, - 29, + 3, + 185, 39, - 206, 3, + 205, 59, - 109, 157, + 180, 65, - 160, 27, - 230, - 55, + 28, + 76, + 216, 91, - 192, 75, - 150, - 7, - 234, + 18, + 28, + 221, 189, 1, - 126, - 66, + 79, + 87, 65, + 216, 85, 88, - 198, 31, + 217, 83, - 207, 41, + 246, 97, 103, - 178, 101, 34, - 225, + 92, 31, - 219, - 153, + 51, + 240, 185, - 97, - 186, - 109, + 44, + 45, + 207, 65, + 174, 118, - 116, 142, + 133, 74, - 40, - 210, - 193, - 233, - 164, + 231, + 24, + 254, + 53, 25, - 235, - 88, + 139, + 0, 19, - 74, - 104, - 24, + 9, + 77, + 45, 2, - 197, - 110, - 133, - 221, + 24, + 131, + 176, 221, + 187, 26, 179, + 163, 65, - 26, - 160, - 208, + 181, + 90, 129, - 42, - 94, - 86, + 5, + 115, 74, + 95, + 195, 204, - 29, + 176, 27, - 128, 125, - 178, + 22, 41, - 105, + 77, 29, - 213, - 13, - 129, + 33, + 234, + 176, 62, - 137, - 136, - 216, + 49, + 59, + 157, 101, - 44, + 5, + 132, 136, - 34, - 113, + 78, 0, 66, - 172, - 182, + 53, + 203, + 131, 14, - 28, 79, + 133, 83, - 44, - 205, + 226, + 134, 80, - 48, 73, - 212, - 70, + 26, + 91, 146, - 193, - 222, + 214, + 91, 127, 68, + 198, 70, 85, - 49, - 89, - 72, - 214, - 11, + 110, + 41, + 235, + 1, + 106, 169, - 83, - 2, - 174, - 78, - 176, + 117, + 23, + 214, + 99, 75, 20, - 24, + 3, 28, - 150, - 253, + 22, + 18, + 193, 88, - 13, - 172, - 89, - 0, - 11, + 171, + 193, + 21, + 33, + 112, 169, - 128, 0, 0, 0, 0, - 1, - 63, + 0, + 39, 255, }; diff --git a/resource/menu_layouts.cpp b/resource/menu_layouts.cpp index 2cb2d2798..14330a28c 100644 --- a/resource/menu_layouts.cpp +++ b/resource/menu_layouts.cpp @@ -86,6 +86,7 @@ menu_t midiport_menu_layout = { {"TURBO 1:", 0, 4, 4, 2, NULL_PAGE, 0, 2}, {"TURBO 2:", 0, 4, 4, 3, NULL_PAGE, 0, 2}, {"TURBO USB:", 0, 4, 4, 55, NULL_PAGE , 0, 2}, + {"DRIVER 1:", 0, 2, 2, 61, 0, NULL_PAGE, 84}, {"DRIVER 2:", 0, 2, 2, 4, 0, NULL_PAGE, 84}, {"CTRL PORT:", 1, 4, 4, 56, NULL_PAGE, 0, 100}, }, From 7ec6fa9b200ba6ac8786f9940280015d69cbe54d Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 19 Sep 2024 14:45:32 +1000 Subject: [PATCH 075/133] initialise TextInput buffer --- avr/cores/megacommand/MCL/TextInputPage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/avr/cores/megacommand/MCL/TextInputPage.cpp b/avr/cores/megacommand/MCL/TextInputPage.cpp index ac61831e9..b0e5a73be 100644 --- a/avr/cores/megacommand/MCL/TextInputPage.cpp +++ b/avr/cores/megacommand/MCL/TextInputPage.cpp @@ -36,6 +36,7 @@ void TextInputPage::init_text(char *text_, const char *title_, uint8_t len) { title = title_; length = len; max_length = len; + memset(text,0,sizeof(text)); strncpy(text, text_, len); //Replace null characeters with space, it will be added back in upon exit. bool after = false; From 123db1080c44e3ffb797864c4f33b2dc4d9b819c Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 19 Sep 2024 14:58:00 +1000 Subject: [PATCH 076/133] Fix file/folder name length consistency when creating/renaming --- avr/cores/megacommand/MCL/FileBrowserPage.cpp | 8 ++++---- avr/cores/megacommand/MCL/FileBrowserPage.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/MCL/FileBrowserPage.cpp b/avr/cores/megacommand/MCL/FileBrowserPage.cpp index feea9fbcd..8bcdd5dc3 100644 --- a/avr/cores/megacommand/MCL/FileBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/FileBrowserPage.cpp @@ -260,7 +260,7 @@ void FileBrowserPage::loop() { bool FileBrowserPage::create_folder() { char new_dir[17] = "new_folder "; - if (mcl_gui.wait_for_input(new_dir, "Create Folder", 8)) { + if (mcl_gui.wait_for_input(new_dir, "Create Folder", NAME_LENGTH)) { SD.mkdir(new_dir); init(); } @@ -366,7 +366,7 @@ bool FileBrowserPage::_handle_filemenu() { for (uint8_t n = 1; n < 32; n++) { buf2[n] = ' '; } - uint8_t name_length = 8; + uint8_t name_length = NAME_LENGTH; switch (file_menu_page.menu.get_item_index(file_menu_encoder.cur)) { case FM_NEW_FOLDER: // new folder @@ -386,8 +386,8 @@ bool FileBrowserPage::_handle_filemenu() { if (suffix_pos != nullptr) { buf2[suffix_pos - buf1] = '\0'; } - // default max length = 8, can extend if buf2 without suffix - // is longer than 8. + // default max length = NAME_LENGTH, can extend if buf2 without suffix + // is longer than NAME_LENGTH. name_length = max(name_length, strlen(buf2)); if (mcl_gui.wait_for_input(buf2, "RENAME TO:", name_length)) { if (suffix_pos != nullptr) { diff --git a/avr/cores/megacommand/MCL/FileBrowserPage.h b/avr/cores/megacommand/MCL/FileBrowserPage.h index 8683fcb24..a77e95145 100644 --- a/avr/cores/megacommand/MCL/FileBrowserPage.h +++ b/avr/cores/megacommand/MCL/FileBrowserPage.h @@ -30,6 +30,8 @@ #define FM_RECVALL 4 #define FM_SENDALL 5 +#define NAME_LENGTH 14 + class FileBrowserFileTypes { constexpr static uint8_t size = 2; char types[size][5]; From d018b320d69f5dafbd969d64f235a975af75dde2 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 19 Sep 2024 16:12:04 +1000 Subject: [PATCH 077/133] SRAM tests, still not working --- avr/cores/megacommand/main.cpp | 100 +++++++++++++++------------------ 1 file changed, 46 insertions(+), 54 deletions(-) diff --git a/avr/cores/megacommand/main.cpp b/avr/cores/megacommand/main.cpp index a1b85fba1..04c501884 100644 --- a/avr/cores/megacommand/main.cpp +++ b/avr/cores/megacommand/main.cpp @@ -33,6 +33,47 @@ __attribute__((section(".init3"))); void(* hardwareReset) (void) = 0; +bool test_sram_banks() { + volatile uint8_t* const start = reinterpret_cast(0x2200); + volatile uint8_t* const end = reinterpret_cast(0xFFFF); + + // Data line and bank switching test + uint8_t pattern = 0x55; + for (volatile uint8_t* ptr = start; ptr < end; ++ptr) { + switch_ram_bank_noret(0); + *ptr = pattern; + if (*ptr != pattern) return false; + switch_ram_bank_noret(1); + *ptr = ~pattern; + if (*ptr != ~pattern) return false; + // *ptr = 0x00; // initialise for later + switch_ram_bank_noret(0); + if (*ptr != pattern) return false; + // *ptr = 0x00; // initialise for later + pattern = (pattern << 1) | (pattern >> 7); + } + +/* + // Address line test, assumes initialised SRAM + for (uint16_t bit = 1; bit != 0 && (start + bit) < end; bit <<= 1) { + volatile uint8_t* const test_addr = start + bit; + // Write to test address + *test_addr = 0xAA; + // Check that only the test address changed + for (volatile uint8_t* ptr = start; ptr < end; ptr++) { + if (ptr == test_addr) { + if (*ptr != 0xAA) return false; // Test address didn't hold the value + } else { + if (*ptr != 0x00) return false; // Another address was affected + } + } + // Reset test address + *test_addr = 0x00; + } +*/ + return true; +} + void my_init_ram(void) { // Set PL6 as output @@ -43,68 +84,21 @@ void my_init_ram(void) { DDRB |= _BV(PB0); PORTB &= ~(_BV(PB0)); #endif + + //External SRAM Hardware Enable XMCRA |= _BV(SRE); //Leds DDRE |= _BV(PE4) | _BV(PE5); - #if CHECKSUM //SRAM tests - volatile uint8_t *ptr; - uint8_t linear = 0; - volatile uint8_t read_bank0, read_bank1 = 0; - - for (ptr = reinterpret_cast (0x2200); ptr < reinterpret_cast (0xFFFF); ptr++) { - switch_ram_bank(0); - uint8_t random_number = pgm_read_byte(rand_ptr++) || 1; - //Store a random number in bank 0 - *ptr = random_number; - //Read value back from bank 0 - read_bank0 = *ptr; - switch_ram_bank(1); - //Store same random number in bank 1 - *ptr = read_bank0; - //Read bank1 - read_bank1 = *ptr; - if ((read_bank0 == 0) || (read_bank1 == 0) || (read_bank0 != random_number) || (read_bank1 != random_number)) { - goto fail; - } - // Check that the RAM bank toggle actually toggles to a different bank. - - random_number++; - //Store new random number in to bank1 - *ptr = random_number; - //Read bank1 - read_bank1 = *ptr; - //Read bank0; - switch_ram_bank(0); - read_bank0 = *ptr; - if (read_bank0 == read_bank1) { - goto fail; - } - //Store lineearly increases values in bank 1, for linear read later. (loop compaction) - *ptr = linear++; - } - switch_ram_bank(0); - //Linear read. - linear = 0; - for (ptr = reinterpret_cast (0x2200); ptr < reinterpret_cast (0xFFFF); ptr++) { - read_bank0 = *ptr; - if (read_bank0 != linear) { - goto fail; - } - linear++; - } - switch_ram_bank(1); - return; - - fail: - while (1) { + /* Still not working? + while (!test_sram_banks()) { setLed(); setLed2(); } - #endif + */ } uint8_t tcnt2; @@ -164,8 +158,6 @@ void init(void) { /* move interrupts to bootloader section */ MCUCR = _BV(IVCE); - - // Enable External SRAM MCUCR = _BV(SRE); // activate lever converter From cdcbbed6eb68ba9b12c9a4ef9699e62134b3cbad Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 19 Sep 2024 16:22:40 +1000 Subject: [PATCH 078/133] Changelog 4.60 --- Changelog | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Changelog b/Changelog index c5920005e..89087acda 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,22 @@ +MCL 4.60 21/09/2024 + +- Changes: + + Support for Machinedrum MIDI machines has been added. + + Sequencing of external MIDI can now be performed using the Machinedrum's + inbuilt MIDI machines. The MIDI data is sent out on the MegaCommand's MIDI Port 2. + + It is now possible to change the Port 1 MIDI driver to Generic. + + Performance optimizations and improvements. + +Bug Fixes: + Fixed device selection in Chromatic Page + Route and Perf track types would not load correctly during transitions + WavDesigner sample transfer was broken. + GUI fixes for SampleBrowser and text input related pages. + MCL 4.51a 20/12/2023 Fixed [ Func ] + [ Clear ] regression in PianoRoll. From 899d6743edadaf2e256bb1066d2b09652dd60022 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 20 Sep 2024 12:23:39 +1000 Subject: [PATCH 079/133] Version 4.60 --- avr/cores/megacommand/Elektron/Elektron.h | 2 +- avr/cores/megacommand/MCL/MCL.h | 4 ++-- avr/cores/megacommand/MD/MD.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/Elektron/Elektron.h b/avr/cores/megacommand/Elektron/Elektron.h index 026575353..af6796f1b 100644 --- a/avr/cores/megacommand/Elektron/Elektron.h +++ b/avr/cores/megacommand/Elektron/Elektron.h @@ -294,7 +294,7 @@ class ElektronSysexObject { #define FW_CAP_ENHANCED_MIDI FW_CAP_HIGH(3) #define FW_CAP_MACHINE_CACHE FW_CAP_HIGH(4) #define FW_CAP_UNDO_CACHE FW_CAP_HIGH(5) - +#define FW_CAP_MID_MACHINE FW_CAP_HIGH(6) /// Base class for Elektron MidiDevice class ElektronDevice : public MidiDevice { public: diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index 8ef822161..d36fd80e2 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -16,8 +16,8 @@ #include "Fonts/Elektrothic.h" #include "Fonts/TomThumb.h" -#define VERSION 4052 -#define VERSION_STR "H4.52" +#define VERSION 4060 +#define VERSION_STR "A4.60" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 diff --git a/avr/cores/megacommand/MD/MD.cpp b/avr/cores/megacommand/MD/MD.cpp index 8892db52f..a64212fa0 100644 --- a/avr/cores/megacommand/MD/MD.cpp +++ b/avr/cores/megacommand/MD/MD.cpp @@ -211,7 +211,7 @@ bool MDClass::probe() { ((uint16_t)FW_CAP_MASTER_FX | (uint16_t)FW_CAP_TRIG_LEDS | (uint16_t)FW_CAP_UNDOKIT_SYNC | (uint16_t)FW_CAP_TONAL | (uint16_t)FW_CAP_ENHANCED_GUI | (uint16_t)FW_CAP_ENHANCED_MIDI) | - (uint16_t)FW_CAP_MACHINE_CACHE | (uint16_t)FW_CAP_UNDO_CACHE; + (uint16_t)FW_CAP_MACHINE_CACHE | (uint16_t)FW_CAP_UNDO_CACHE | (uint16_t)FW_CAP_MID_MACHINE; while ((!get_fw_caps() || ((fw_caps & fw_caps_mask) != fw_caps_mask)) && count) { From 494e4fd368d083ba233536e070fafb9637ba2c69 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 20 Sep 2024 12:25:55 +1000 Subject: [PATCH 080/133] Changelog --- Changelog | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index 89087acda..675394edf 100644 --- a/Changelog +++ b/Changelog @@ -1,8 +1,8 @@ MCL 4.60 21/09/2024 -- Changes: +Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.60. - Support for Machinedrum MIDI machines has been added. +- Changes: Sequencing of external MIDI can now be performed using the Machinedrum's inbuilt MIDI machines. The MIDI data is sent out on the MegaCommand's MIDI Port 2. @@ -13,8 +13,11 @@ MCL 4.60 21/09/2024 Bug Fixes: Fixed device selection in Chromatic Page + Route and Perf track types would not load correctly during transitions + WavDesigner sample transfer was broken. + GUI fixes for SampleBrowser and text input related pages. MCL 4.51a 20/12/2023 From 247700063fbcf85d0c257c40b423976dacada15c Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sat, 21 Sep 2024 22:58:58 +1000 Subject: [PATCH 081/133] fix regression in port2 driver loading --- avr/cores/megacommand/MCL/MidiActivePeering.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/MidiActivePeering.cpp b/avr/cores/megacommand/MCL/MidiActivePeering.cpp index a4d3863f0..abe4eb4e9 100644 --- a/avr/cores/megacommand/MCL/MidiActivePeering.cpp +++ b/avr/cores/megacommand/MCL/MidiActivePeering.cpp @@ -251,8 +251,8 @@ void MidiActivePeering::run() { } probePort(UART1_PORT, drivers, nr_drivers, &connected_midi_devices[0], resource_buf); #ifdef EXT_TRACKS + drivers = port2_drivers; nr_drivers = countof(port2_drivers); - if (!mcl_cfg.uart2_device) { nr_drivers = 1; drivers = generic_drivers; From af884f13796878f04854ab35662c3e0d7439f0d6 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 22 Sep 2024 12:54:38 +1000 Subject: [PATCH 082/133] Changelog --- Changelog | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index 675394edf..8e7589e08 100644 --- a/Changelog +++ b/Changelog @@ -4,8 +4,8 @@ Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.6 - Changes: - Sequencing of external MIDI can now be performed using the Machinedrum's - inbuilt MIDI machines. The MIDI data is sent out on the MegaCommand's MIDI Port 2. + MD's in-built MIDI machines are now supported via the MCL sequencer. + The MIDI data is transmitted on the MegaCommand's MIDI Port 2. It is now possible to change the Port 1 MIDI driver to Generic. @@ -20,6 +20,8 @@ Bug Fixes: GUI fixes for SampleBrowser and text input related pages. + MD's random LFO shape was broken when loading with MCL. + MCL 4.51a 20/12/2023 Fixed [ Func ] + [ Clear ] regression in PianoRoll. From 67382188bb2292bc792b5ee6da29c2463541589a Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 13 Oct 2024 12:19:48 +1100 Subject: [PATCH 083/133] Perf Encoders accessible on Grid Page --- avr/cores/megacommand/MCL/GridPage.cpp | 158 +++-- avr/cores/megacommand/MCL/GridPage.h | 2 + avr/cores/megacommand/MCL/MCL.cpp | 21 +- avr/cores/megacommand/MCL/MCL.h | 23 +- avr/cores/megacommand/MCL/MCLEncoder.cpp | 7 +- avr/cores/megacommand/MCL/MCLMenus.cpp | 3 +- avr/cores/megacommand/MCL/MCLMenus.h | 5 +- avr/cores/megacommand/MCL/MCLSysConfig.cpp | 1 + avr/cores/megacommand/MCL/MCLSysConfig.h | 1 + avr/cores/megacommand/MCL/MixerPage.cpp | 40 +- avr/cores/megacommand/MCL/MixerPage.h | 2 + avr/cores/megacommand/ResourceManager.cpp | 1 - avr/cores/megacommand/resources/R.h | 22 +- .../megacommand/resources/R_menu_layouts.cpp | 579 +++++++++--------- .../megacommand/resources/R_menu_options.cpp | 9 +- .../megacommand/resources/R_page_entries.cpp | 2 +- resource/menu_layouts.cpp | 15 +- resource/menu_options.cpp | 4 +- 18 files changed, 473 insertions(+), 422 deletions(-) diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index 72231c6c9..5a507f862 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -1,13 +1,27 @@ #include "MCL_impl.h" #include "ResourceManager.h" +#define PERF_ENC 1 +#define GRID_ENC 0 + void GridPage::init() { DEBUG_PRINTLN("Grid page init"); - encoders[0] = ¶m1; - encoders[1] = ¶m2; - ((MCLEncoder *)encoders[0])->max = getWidth() - 1; + if (mcl_cfg.grid_page_mode == PERF_ENC) { + encoders[0] = &perf_param1; + encoders[1] = &perf_param2; + encoders[2] = &perf_param3; + encoders[3] = &perf_param4; + } + else { + encoders[0] = ¶m1; + encoders[1] = ¶m2; + encoders[2] = ¶m3; + encoders[3] = ¶m4; + } + param1.max = getWidth() - 1; show_slot_menu = false; reload_slot_models = false; + draw_encoders = false; // Edge case, prevent R.Clear being called if we're outside of GridPage if (mcl.currentPage() != GRID_PAGE) { return; @@ -17,12 +31,13 @@ void GridPage::init() { oled_display.clearDisplay(); R.Clear(); R.use_machine_names_short(); + R.use_icons_knob(); } void GridPage::setup() { - encoders[0]->cur = encoders[0]->old = mcl_cfg.col; - encoders[1]->cur = encoders[1]->old = mcl_cfg.row; - encoders[2]->cur = 1; + param1.cur = param1.old = mcl_cfg.col; + param2.cur = param2.old = mcl_cfg.row; + param3.cur = 1; cur_col = mcl_cfg.cur_col; cur_row = mcl_cfg.cur_row; memset(active_slots, SLOT_DISABLED, sizeof(active_slots)); @@ -94,39 +109,47 @@ void GridPage::load_old_col() { cur_col = old_col; param1.cur = cur_col; param1.old = cur_col; - encoders[2]->cur = GRID_WIDTH - cur_col; - encoders[2]->old = encoders[2]->cur; + param3.cur = GRID_WIDTH - cur_col; + param3.old = param3.cur; grid_page.grid_select_apply = 0; proj.grid_select = 0; - ((MCLEncoder *)encoders[2])->max = getWidth() + 1; + param3.max = getWidth() + 1; } void GridPage::loop() { + if (mcl_cfg.grid_page_mode == PERF_ENC) { + //need to limit range of the alternate encoders + encoder_t *enc = nullptr; + param1.update(enc); + param2.update(enc); + param3.update(enc); + param4.update(enc); + } int8_t diff, new_val; if (show_slot_menu) { - if (encoders[2]->hasChanged()) { - if ((proj.get_grid() == 0) && (getCol() + encoders[2]->cur > GRID_WIDTH)) { + if (param3.hasChanged()) { + if ((proj.get_grid() == 0) && (getCol() + param3.cur > GRID_WIDTH)) { old_col = getCol(); cur_col = 0; param1.cur = 0; param1.old = 0; - encoders[2]->cur = 1; - encoders[2]->old = 1; + param3.cur = 1; + param3.old = 1; grid_page.grid_select_apply = 1; proj.grid_select = 1; - ((MCLEncoder *)encoders[2])->max = getWidth(); + param3.max = getWidth(); load_slot_models(); reload_slot_models = true; } - else if ((proj.get_grid() == 1) && (encoders[2]->cur == 0) && (old_col != 255)) { + else if ((proj.get_grid() == 1) && (param3.cur == 0) && (old_col != 255)) { load_old_col(); load_slot_models(); reload_slot_models = true; } - if (encoders[2]->cur == 0) { encoders[2]->cur = 1; encoders[2]->old = 1; } + if (param3.cur == 0) { param3.cur = 1; param3.old = 1; } } - if (encoders[3]->hasChanged()) { - if (cur_row + encoders[3]->cur > MAX_VISIBLE_ROWS - 1) { + if (param4.hasChanged()) { + if (cur_row + param4.cur > MAX_VISIBLE_ROWS - 1) { load_slot_models(); reload_slot_models = true; } @@ -134,21 +157,23 @@ void GridPage::loop() { grid_slot_page.loop(); return; } else { - } - /* - if (encoders[2]->hasChanged()) { - diff = encoders[2]->cur - encoders[2]->old; - if (cur_col + encoders[2]->cur > MAX_VISIBLE_COLS - 1) { - encoders[0]->cur += diff; - encoders[0]->old = encoders[0]->cur; + if (mcl_cfg.grid_page_mode == PERF_ENC) { + if (encoders[0]->hasChanged() || encoders[1]->hasChanged() || encoders[2]->hasChanged() || encoders[3]->hasChanged()) { + // mixer_page.encoder_entry_page = GRID_PAGE; + //mcl.setPage(MIXER_PAGE); + draw_encoders_lastclock = slowclock; + draw_encoders = true; + //return; + perf_page.encoder_send(); + } } - } -*/ - if (encoders[2]->hasChanged()) { - if (encoders[2]->cur == 0) { encoders[2]->cur = 1; encoders[2]->old = 1; } } - if (encoders[0]->hasChanged()) { - diff = encoders[0]->cur - encoders[0]->old; + + if (param3.hasChanged()) { + if (param3.cur == 0) { param3.cur = 1; param3.old = 1; } + } + if (param1.hasChanged()) { + diff = param1.cur - param1.old; new_val = cur_col + diff; if (new_val > MAX_VISIBLE_COLS - 1) { new_val = MAX_VISIBLE_COLS - 1; @@ -159,8 +184,8 @@ void GridPage::loop() { cur_col = new_val; } - if (encoders[1]->hasChanged()) { - diff = encoders[1]->cur - encoders[1]->old; + if (param2.hasChanged()) { + diff = param2.cur - param2.old; new_val = cur_row + diff; if (new_val > MAX_VISIBLE_ROWS - 1) { @@ -169,7 +194,6 @@ void GridPage::loop() { if (new_val < 0) { new_val = 0; } - // MD.assignMachine(0, encoders[1]->cur); cur_row = new_val; if ((cur_row == MAX_VISIBLE_ROWS - 1) || (cur_row == 0)) { load_slot_models(); @@ -180,10 +204,9 @@ void GridPage::loop() { volatile uint8_t *ptr; write_cfg = true; } - encoders[2]->cur = 1; - encoders[3]->cur = 1; - //((MCLEncoder *)encoders[2])->max = getWidth() + 1 - getCol(); - ((MCLEncoder *)encoders[3])->max = GRID_LENGTH - getRow(); + param3.cur = 1; + param4.cur = 1; + param4.max = GRID_LENGTH - getRow(); if (!reload_slot_models) { load_slot_models(); @@ -202,8 +225,8 @@ void GridPage::loop() { mcl_cfg.cur_col = cur_col; mcl_cfg.cur_row = cur_row; - mcl_cfg.col = encoders[0]->cur; - mcl_cfg.row = encoders[1]->cur; + mcl_cfg.col = param1.cur; + mcl_cfg.row = param2.cur; mcl_cfg.tempo = MidiClock.get_tempo(); DEBUG_PRINTLN(F("write cfg")); @@ -216,6 +239,13 @@ void GridPage::loop() { row_state_scan(); } + if (mcl_cfg.grid_page_mode == PERF_ENC) { + param1.checkHandle(); + param2.checkHandle(); + param3.checkHandle(); + param4.checkHandle(); + } + if (bank_popup == 2 && clock_diff(bank_popup_lastclock, slowclock) > 800) { close_bank_popup(); return; @@ -262,8 +292,8 @@ uint8_t GridPage::getWidth() { return GRID_WIDTH; } void GridPage::load_slot_models() { DEBUG_PRINTLN("load slot models"); uint8_t row_shift = 0; - if ((cur_row + encoders[3]->cur > MAX_VISIBLE_ROWS - 1)) { - row_shift = cur_row + encoders[3]->cur - MAX_VISIBLE_ROWS; + if ((cur_row + param4.cur > MAX_VISIBLE_ROWS - 1)) { + row_shift = cur_row + param4.cur - MAX_VISIBLE_ROWS; } for (uint8_t n = 0; n < MAX_VISIBLE_ROWS; n++) { @@ -357,13 +387,13 @@ void GridPage::display_grid_info() { oled_display.print(':'); char val[4]; - mcl_gui.put_value_at2(encoders[0]->cur + 1, val); + mcl_gui.put_value_at2(param1.cur + 1, val); val[2] = '\0'; oled_display.print(val); oled_display.print(F(" ")); - uint8_t b = encoders[1]->cur / 16; + uint8_t b = param2.cur / 16; oled_display.print((char)('A' + b)); - mcl_gui.put_value_at2(encoders[1]->cur - b * 16 + 1, val); + mcl_gui.put_value_at2(param2.cur - b * 16 + 1, val); oled_display.print(val); oled_display.setCursor(1, y_offset + 2 * 8); @@ -401,19 +431,21 @@ void GridPage::display_grid() { char str[3]; PGM_P tmp; - encoders[1]->handler = NULL; + +// encoders[1]->handler = NULL; + uint8_t row_shift = 0; uint8_t col_shift = 0; auto grid_id = proj.get_grid(); auto *device = midi_active_peering.get_device(grid_id + 1); if (show_slot_menu) { - if (cur_col + encoders[2]->cur > MAX_VISIBLE_COLS - 1) { + if (cur_col + param3.cur > MAX_VISIBLE_COLS - 1) { - col_shift = cur_col + encoders[2]->cur - MAX_VISIBLE_COLS; + col_shift = cur_col + param3.cur - MAX_VISIBLE_COLS; } - if (cur_row + encoders[3]->cur > MAX_VISIBLE_ROWS - 1) { - row_shift = cur_row + encoders[3]->cur - MAX_VISIBLE_ROWS; + if (cur_row + param4.cur > MAX_VISIBLE_ROWS - 1) { + row_shift = cur_row + param4.cur - MAX_VISIBLE_ROWS; } } for (uint8_t y = 0; y < MAX_VISIBLE_ROWS; y++) { @@ -484,8 +516,8 @@ void GridPage::display_grid() { break; } // Highlight the current cursor position + slot menu apply range - bool a = in_area(x, y + row_shift, cur_col, cur_row, encoders[2]->cur - 1, - encoders[3]->cur - 1); + bool a = in_area(x, y + row_shift, cur_col, cur_row, param3.cur - 1, + param4.cur - 1); bool b = is_slot_queue(track_idx, row_idx); if (a ^ b) { @@ -557,6 +589,13 @@ void GridPage::display() { display_slot_menu(); } display_grid(); + if (draw_encoders && clock_diff(draw_encoders_lastclock, slowclock) < 750) { + oled_display.setFont(); + mixer_page.draw_encs(); + } + else { + draw_encoders = false; + } /* if (row_scan) { mcl_gui.draw_progress_bar(8, 8, false, 18, 2, 9, 7, false); @@ -609,7 +648,7 @@ void apply_slot_changes_cb() { grid_page.apply_slot_changes(); } bool GridPage::swap_grids() { if (grid_select_apply != proj.grid_select) { proj.grid_select = grid_select_apply; - ((MCLEncoder *)encoders[0])->max = getWidth() - 1; + param1.max = getWidth() - 1; //load_slot_models(); return true; } @@ -656,8 +695,8 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { return; } } - width = old_col != 255 ? GRID_WIDTH - _col : encoders[2]->cur; - height = encoders[3]->cur; + width = old_col != 255 ? GRID_WIDTH - _col : param3.cur; + height = param4.cur; uint8_t slot_update = 0; @@ -694,7 +733,7 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { } mcl_clipboard.copy(_col + 16 * proj.get_grid(), getRow(), width, height); if (old_col != 255 && proj.get_grid() == 0) { - mcl_clipboard.copy(16, getRow(), encoders[2]->cur, height); + mcl_clipboard.copy(16, getRow(), param3.cur, height); mcl_clipboard.t_col = _col; mcl_clipboard.t_w += GRID_WIDTH - cur_col; DEBUG_PRINTLN("copy grid 1+2"); @@ -799,7 +838,7 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { if (old_col != 255) { if (proj.get_grid() == 0) { proj.select_grid(1); - width = encoders[2]->cur; + width = param3.cur; _col = 0; goto again; } @@ -911,6 +950,7 @@ bool GridPage::handleEvent(gui_event_t *event) { } next: if (event->mask == EVENT_BUTTON_PRESSED) { + draw_encoders = false; uint8_t inc = 1; if (trig_interface.is_key_down(MDX_KEY_FUNC)) { inc = 4; @@ -1089,8 +1129,8 @@ bool GridPage::handleEvent(gui_event_t *event) { DEBUG_DUMP(slot.link.row); encoders[0] = &grid_slot_param1; encoders[1] = &grid_slot_param2; - encoders[2]->cur = 1; - encoders[3]->cur = 1; + param3.cur = 1; + param4.cur = 1; slot_apply = 0; old_col = 255; if (!slot.is_ext_track()) { diff --git a/avr/cores/megacommand/MCL/GridPage.h b/avr/cores/megacommand/MCL/GridPage.h index 89179cacf..21abe7fbe 100644 --- a/avr/cores/megacommand/MCL/GridPage.h +++ b/avr/cores/megacommand/MCL/GridPage.h @@ -61,6 +61,8 @@ class GridPage : public LightPage { uint16_t bank_popup_lastclock; uint16_t bank_popup_loadmask; + bool draw_encoders; + uint16_t draw_encoders_lastclock; GridPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) : LightPage(e1, e2, e3, e4) {} diff --git a/avr/cores/megacommand/MCL/MCL.cpp b/avr/cores/megacommand/MCL/MCL.cpp index 57173c17d..1c2450c64 100644 --- a/avr/cores/megacommand/MCL/MCL.cpp +++ b/avr/cores/megacommand/MCL/MCL.cpp @@ -113,17 +113,16 @@ LightPage *const MCL::pages_table[NUM_PAGES] PROGMEM = { &chain_config_page, // Index: 28 &aux_config_page, // Index: 29 &mcl_config_page, // Index: 30 - &ram_config_page, // Index: 31 - &arp_page, // Index: 32 - &md_import_page, // Index: 33 - &midiport_menu_page, // Index: 34 - &midiprogram_menu_page, // Index: 35 - &midiclock_menu_page, // Index: 36 - &midiroute_menu_page, // Index: 37 - &midimachinedrum_menu_page,// Index: 38 - &midigeneric_menu_page, // Index: 39 - &sound_browser, // Index: 40 - &perf_page // Index: 41 + &arp_page, // Index: 31 + &md_import_page, // Index: 32 + &midiport_menu_page, // Index: 33 + &midiprogram_menu_page, // Index: 34 + &midiclock_menu_page, // Index: 35 + &midiroute_menu_page, // Index: 36 + &midimachinedrum_menu_page,// Index: 37 + &midigeneric_menu_page, // Index: 38 + &sound_browser, // Index: 39 + &perf_page // Index: 40 }; void MCL::setup() { diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index d36fd80e2..c67ab4099 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -17,7 +17,7 @@ #include "Fonts/TomThumb.h" #define VERSION 4060 -#define VERSION_STR "A4.60" +#define VERSION_STR "C4.60" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 @@ -63,17 +63,16 @@ enum PageIndex { CHAIN_CONFIG_PAGE, // Index: 28 AUX_CONFIG_PAGE, // Index: 29 MCL_CONFIG_PAGE, // Index: 30 - RAM_CONFIG_PAGE, // Index: 31 - ARP_PAGE, // Index: 32 - MD_IMPORT_PAGE, // Index: 33 - MIDIPORT_MENU_PAGE, // Index: 34 - MIDIPROGRAM_MENU_PAGE, // Index: 35 - MIDICLOCK_MENU_PAGE, // Index: 36 - MIDIROUTE_MENU_PAGE, // Index: 37 - MIDIMACHINEDRUM_MENU_PAGE,// Index: 38 - MIDIGENERIC_MENU_PAGE, // Index: 39 - SOUND_BROWSER, // Index: 40 - PERF_PAGE_0, // Index: 41 + ARP_PAGE, // Index: 31 + MD_IMPORT_PAGE, // Index: 32 + MIDIPORT_MENU_PAGE, // Index: 33 + MIDIPROGRAM_MENU_PAGE, // Index: 34 + MIDICLOCK_MENU_PAGE, // Index: 35 + MIDIROUTE_MENU_PAGE, // Index: 36 + MIDIMACHINEDRUM_MENU_PAGE,// Index: 37 + MIDIGENERIC_MENU_PAGE, // Index: 38 + SOUND_BROWSER, // Index: 39 + PERF_PAGE_0, // Index: 40 NULL_PAGE = 255 }; diff --git a/avr/cores/megacommand/MCL/MCLEncoder.cpp b/avr/cores/megacommand/MCL/MCLEncoder.cpp index 440336829..e9808bbaa 100644 --- a/avr/cores/megacommand/MCL/MCLEncoder.cpp +++ b/avr/cores/megacommand/MCL/MCLEncoder.cpp @@ -2,8 +2,11 @@ int MCLEncoder::update(encoder_t *enc) { - int inc = update_rotations(enc); - inc = inc + (fastmode ? 4 * enc->button : enc->button); + int inc = 0; + if (enc) { + inc = update_rotations(enc); + inc = inc + (fastmode ? 4 * enc->button : enc->button); + } cur = limit_value(cur, inc, min, max); return cur; } diff --git a/avr/cores/megacommand/MCL/MCLMenus.cpp b/avr/cores/megacommand/MCL/MCLMenus.cpp index 0e2a577b6..3b2e84c22 100644 --- a/avr/cores/megacommand/MCL/MCLMenus.cpp +++ b/avr/cores/megacommand/MCL/MCLMenus.cpp @@ -104,6 +104,8 @@ const uint8_t *const menu_target_param[] PROGMEM = { &mcl_cfg.uart2_cc_mute, // 61 &mcl_cfg.uart1_device, + // 62 + &mcl_cfg.grid_page_mode, }; const menu_function_t menu_target_functions[] PROGMEM = { @@ -173,7 +175,6 @@ MenuPage midi_config_page(&config_param1, &config_param3); MenuPage md_config_page(&config_param1, &config_param4); MenuPage chain_config_page(&config_param1, &config_param6); MenuPage mcl_config_page(&config_param1, &config_param5); -MenuPage ram_config_page(&config_param1, &config_param7); MenuPage md_import_page(&config_param1, &config_param8); MenuPage midiport_menu_page(&config_param1, &config_param9); diff --git a/avr/cores/megacommand/MCL/MCLMenus.h b/avr/cores/megacommand/MCL/MCLMenus.h index 3ff9a8b06..3f314c4eb 100644 --- a/avr/cores/megacommand/MCL/MCLMenus.h +++ b/avr/cores/megacommand/MCL/MCLMenus.h @@ -55,12 +55,9 @@ extern MenuPage mcl_config_page; constexpr size_t chain_config_page_N = 3; extern MenuPage chain_config_page; -constexpr size_t aux_config_page_N = 1; +constexpr size_t aux_config_page_N = 2; extern MenuPage aux_config_page; -constexpr size_t ram_config_page_N = 1; -extern MenuPage ram_config_page; - constexpr size_t md_import_page_N = 4; extern MenuPage md_import_page; diff --git a/avr/cores/megacommand/MCL/MCLSysConfig.cpp b/avr/cores/megacommand/MCL/MCLSysConfig.cpp index 3f7a045e4..bae1c4a7d 100644 --- a/avr/cores/megacommand/MCL/MCLSysConfig.cpp +++ b/avr/cores/megacommand/MCL/MCLSysConfig.cpp @@ -156,6 +156,7 @@ bool MCLSysConfig::cfg_init() { //seq_dev = 0; uart2_cc_mute = 128; uart2_cc_level = 128; + //grid_page_mode = 0; cfgfile.close(); ret = write_cfg(); if (!ret) { diff --git a/avr/cores/megacommand/MCL/MCLSysConfig.h b/avr/cores/megacommand/MCL/MCLSysConfig.h index 0749418c2..157acc9da 100644 --- a/avr/cores/megacommand/MCL/MCLSysConfig.h +++ b/avr/cores/megacommand/MCL/MCLSysConfig.h @@ -68,6 +68,7 @@ class MCLSysConfigData { uint8_t uart2_cc_mute; uint8_t uart2_cc_level; uint8_t uart1_device; + uint8_t grid_page_mode; }; class MCLSysConfig : public MCLSysConfigData { diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 770f12542..7b30731a0 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -12,6 +12,8 @@ void MixerPage::set_display_mode(uint8_t param) { } void MixerPage::oled_draw_mutes() { + if (encoder_entry_page != NULL_PAGE) { return; } + bool is_md_device = (midi_device == &MD); uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; @@ -88,6 +90,7 @@ void MixerPage::cleanup() { trig_interface.off(); ext_key_down = 0; mute_toggle = 0; + encoder_entry_page = NULL_PAGE; } void MixerPage::set_level(int curtrack, int value) { @@ -108,7 +111,7 @@ void MixerPage::load_perf_locks(uint8_t state) { } } void MixerPage::loop() { - constexpr int timeout = 1500; + constexpr int timeout = 750; perf_page.func_enc_check(); bool old_draw_encoders = draw_encoders; @@ -149,6 +152,10 @@ void MixerPage::loop() { } if (draw_encoders != old_draw_encoders) { if (!draw_encoders) { + if (encoder_entry_page != NULL_PAGE) { + mcl.setPage(encoder_entry_page); + return; + } redraw(); } } @@ -216,6 +223,23 @@ void encoder_lastparam_handle(EncoderParent *enc) { } */ +void MixerPage::draw_encs() { + constexpr uint8_t fader_y = 11; + oled_display.fillRect(0, fader_y, 128, 21, BLACK); + for (uint8_t n = 0; n < 4; n++) { + char str1[] = "A"; + str1[0] = 'A' + n; + uint8_t pos = n * 24; + bool highlight = + (preview_mute_set != 255) && (perf_locks[preview_mute_set][n] != 255); // && (trig_interface.is_key_down(MDX_KEY_NO)); + uint8_t val = + highlight ? perf_locks[preview_mute_set][n] : encoders[n]->cur; + mcl_gui.draw_encoder(24 + pos, fader_y + 4, val, highlight); + oled_display.setCursor(16 + pos, fader_y + 6); + oled_display.print(str1); + } +} + void MixerPage::adjust_param(EncoderParent *enc, uint8_t param) { if (midi_device != &MD) { @@ -271,19 +295,7 @@ void MixerPage::display() { } if (draw_encoders || preview_mute_set != 255) { // oled_display.clearDisplay(); - oled_display.fillRect(0, fader_y, 128, 21, BLACK); - for (uint8_t n = 0; n < 4; n++) { - char str1[] = "A"; - str1[0] = 'A' + n; - uint8_t pos = n * 24; - bool highlight = - (preview_mute_set != 255) && (perf_locks[preview_mute_set][n] != 255); // && (trig_interface.is_key_down(MDX_KEY_NO)); - uint8_t val = - highlight ? perf_locks[preview_mute_set][n] : encoders[n]->cur; - mcl_gui.draw_encoder(24 + pos, fader_y + 4, val, highlight); - oled_display.setCursor(16 + pos, fader_y + 6); - oled_display.print(str1); - } + draw_encs(); oled_display.display(); } else { diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index 5ad1a3aa4..ba1d79171 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -46,6 +46,7 @@ class MixerPage : public LightPage { bool draw_encoders; PageIndex last_page = NULL_PAGE; + PageIndex encoder_entry_page = NULL_PAGE; uint8_t current_mute_set = 255; uint8_t preview_mute_set = 255; @@ -69,6 +70,7 @@ class MixerPage : public LightPage { } void adjust_param(EncoderParent *enc, uint8_t param); void draw_levels(); + void draw_encs(); void redraw(); void set_level(int curtrack, int value); void set_display_mode(uint8_t param); diff --git a/avr/cores/megacommand/ResourceManager.cpp b/avr/cores/megacommand/ResourceManager.cpp index e4a4a1855..2c91c95c8 100644 --- a/avr/cores/megacommand/ResourceManager.cpp +++ b/avr/cores/megacommand/ResourceManager.cpp @@ -91,7 +91,6 @@ void ResourceManager::restore_menu_layout_deps() { midi_config_page.set_layout(R.menu_layouts->midiconfig_menu_layout); md_config_page.set_layout(R.menu_layouts->mdconfig_menu_layout); mcl_config_page.set_layout(R.menu_layouts->mclconfig_menu_layout); - ram_config_page.set_layout(R.menu_layouts->rampage1_menu_layout); file_menu_page.set_layout(R.menu_layouts->file_menu_layout); seq_menu_page.set_layout(R.menu_layouts->seq_menu_layout); grid_slot_page.set_layout(R.menu_layouts->slot_menu_layout); diff --git a/avr/cores/megacommand/resources/R.h b/avr/cores/megacommand/resources/R.h index 39043a589..69b461a2c 100644 --- a/avr/cores/megacommand/resources/R.h +++ b/avr/cores/megacommand/resources/R.h @@ -434,18 +434,12 @@ struct __T_menu_layouts { }; static constexpr size_t countof_midiconfig_menu_layout = 137 / sizeof(menu_t); static constexpr size_t sizeofof_midiconfig_menu_layout = 137; - union { - menu_t rampage1_menu_layout[0]; - char zz__rampage1_menu_layout[32]; - }; - static constexpr size_t countof_rampage1_menu_layout = 32 / sizeof(menu_t); - static constexpr size_t sizeofof_rampage1_menu_layout = 32; union { menu_t auxconfig_menu_layout[0]; - char zz__auxconfig_menu_layout[32]; + char zz__auxconfig_menu_layout[53]; }; - static constexpr size_t countof_auxconfig_menu_layout = 32 / sizeof(menu_t); - static constexpr size_t sizeofof_auxconfig_menu_layout = 32; + static constexpr size_t countof_auxconfig_menu_layout = 53 / sizeof(menu_t); + static constexpr size_t sizeofof_auxconfig_menu_layout = 53; union { menu_t system_menu_layout[0]; char zz__system_menu_layout[137]; @@ -464,18 +458,18 @@ struct __T_menu_layouts { }; static constexpr size_t countof_boot_menu_layout = 95 / sizeof(menu_t); static constexpr size_t sizeofof_boot_menu_layout = 95; - static constexpr size_t __total_size = 2152; + static constexpr size_t __total_size = 2141; }; extern const unsigned char __R_menu_options[] PROGMEM; struct __T_menu_options { union { menu_option_t MENU_OPTIONS[0]; - char zz__MENU_OPTIONS[1098]; + char zz__MENU_OPTIONS[1116]; }; - static constexpr size_t countof_MENU_OPTIONS = 1098 / sizeof(menu_option_t); - static constexpr size_t sizeofof_MENU_OPTIONS = 1098; - static constexpr size_t __total_size = 1098; + static constexpr size_t countof_MENU_OPTIONS = 1116 / sizeof(menu_option_t); + static constexpr size_t sizeofof_MENU_OPTIONS = 1116; + static constexpr size_t __total_size = 1116; }; extern const unsigned char __R_page_entries[] PROGMEM; diff --git a/avr/cores/megacommand/resources/R_menu_layouts.cpp b/avr/cores/megacommand/resources/R_menu_layouts.cpp index d54010627..b3858095c 100644 --- a/avr/cores/megacommand/resources/R_menu_layouts.cpp +++ b/avr/cores/megacommand/resources/R_menu_layouts.cpp @@ -262,190 +262,191 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 79, 67, 104, - 119, - 211, + 183, + 31, + 2, 75, 69, + 176, 89, - 96, 63, - 125, + 62, 12, 12, 19, - 184, + 220, 41, 104, 86, - 68, + 34, 233, - 37, + 18, 27, - 225, + 240, 0, 20, + 193, 48, - 130, 6, - 236, + 118, 78, 68, 21, - 191, + 95, 1, 15, 15, + 183, 21, - 110, 20, 60, 83, - 219, + 109, 82, 69, + 128, 21, - 1, - 252, + 254, 7, 7, 22, 255, 5, 41, - 55, + 27, 132, 71, 84, + 194, 72, - 132, 58, 153, - 191, + 95, 23, 255, 6, + 176, 0, - 97, 20, - 121, + 188, 2, 129, - 28, + 142, 67, 72, - 45, + 22, 248, 78, - 146, + 201, 108, - 27, + 13, 16, 24, + 225, 255, - 194, 7, 0, 111, - 67, + 33, + 252, 3, - 248, 3, 25, 255, 8, 27, - 66, + 33, 153, - 221, + 110, 20, + 228, 26, - 200, 255, 9, - 7, + 3, + 194, 10, - 132, 30, 153, - 45, - 223, + 22, + 239, 20, 27, 255, 11, 27, + 240, 83, - 225, 72, 73, 70, + 128, 59, - 1, - 252, + 254, 5, 5, 28, 255, 12, 35, - 43, + 21, 174, + 187, 232, - 118, 82, 83, 43, - 178, + 89, 41, - 127, + 63, 29, 255, 13, 27, 80, + 251, 79, - 246, 76, 89, 80, 72, 235, - 217, + 108, 89, 44, - 54, + 155, 11, 2, - 237, + 118, 81, 85, 167, - 132, + 194, 84, 79, - 14, + 7, 42, - 96, - 182, + 48, + 91, 121, 32, 65, - 133, + 66, 125, - 101, + 178, 20, - 205, + 230, 30, + 225, 83, - 194, 79, 85, 38, - 216, - 0, - 0, - 29, - 40, + 66, + 144, + 6, + 53, + 129, 189, 2, 14, @@ -570,430 +571,428 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 176, 84, 31, - 56, - 33, - 102, - 7, + 55, + 86, + 91, + 78, 18, - 219, 77, + 110, 178, 73, - 133, 90, + 21, 146, - 96, + 131, 147, - 219, 8, + 109, 73, 16, - 74, + 43, 253, - 222, 201, + 123, 32, 77, 73, - 215, 175, + 93, 62, - 91, 85, + 108, 188, 32, - 25, + 101, 240, - 125, + 246, 129, 1, 60, - 187, 31, + 237, 121, 24, 84, - 88, + 96, 30, - 35, + 142, 78, - 184, + 227, 82, 79, 32, - 246, 83, + 217, 33, - 125, + 246, 17, 2, 9, - 176, 31, + 195, 18, - 236, 208, + 176, 20, - 38, + 153, 46, - 93, + 117, 88, 84, - 109, + 182, 81, 71, - 132, 20, - 221, + 19, 57, + 118, 41, 24, - 180, 82, + 208, 201, - 32, + 130, 113, - 191, + 255, 80, 32, 49, - 227, 32, 70, + 141, 87, 220, - 82, + 73, 127, - 118, + 219, 7, 31, - 216, 10, + 99, 20, - 200, 50, - 12, + 32, + 50, 51, - 190, + 251, 92, 85, 83, 66, - 193, 17, - 72, + 5, + 32, 169, - 54, + 219, 52, 20, - 199, 96, + 28, 26, - 47, + 188, 116, - 9, + 37, 92, - 118, + 219, 11, 20, - 225, 86, + 133, 24, 124, - 66, + 10, 251, - 140, + 48, 5, - 22, + 90, 29, - 174, + 184, 8, - 15, + 60, 183, 58, - 25, + 103, 121, - 219, 5, + 108, 31, 7, - 2, + 8, 5, - 44, + 176, 20, - 14, + 57, 53, - 102, + 153, 41, - 97, + 134, 204, - 152, + 97, 115, - 112, + 194, 6, - 182, 72, + 216, 100, 41, - 44, + 176, 20, - 14, + 59, 54, - 222, 41, + 123, 100, 24, 80, - 219, 190, + 109, 71, 24, - 67, + 14, 220, - 181, + 214, 9, - 186, 220, + 235, 77, 79, - 230, 1, + 152, 126, - 29, + 118, 49, - 183, 31, + 223, 90, 20, - 225, 73, + 132, 78, 167, - 39, + 158, 18, 2, - 134, 47, + 25, 7, - 123, + 238, 20, 244, - 156, + 112, 21, - 16, + 65, 7, - 110, + 186, 48, 20, - 135, 24, + 30, 154, - 172, 83, + 179, 177, - 252, + 240, 85, 82, 66, 79, - 43, + 172, 8, 221, - 47, + 189, 2, 255, - 107, + 172, 78, 20, - 57, + 228, 50, - 46, + 185, 3, - 73, - 13, + 36, + 53, 13, 58, - 96, + 131, 20, - 205, 55, + 52, 68, - 10, + 42, + 102, 102, - 153, 98, - 172, 63, + 178, 136, - 155, + 109, 61, 189, - 108, + 176, 84, 20, - 25, + 100, 50, - 38, + 153, 4, - 96, - 98, + 129, + 139, 97, - 240, 119, - 38, + 192, + 155, 26, - 219, 62, + 111, 56, 210, - 194, + 8, 215, - 11, + 46, 210, - 159, + 125, 26, 32, - 93, + 116, 130, 70, - 10, + 43, 183, - 193, 118, - 142, - 34, + 6, + 33, + 56, 205, - 12, - 80, 48, + 80, + 194, 100, - 184, - 36, - 231, + 227, + 35, 121, + 156, 207, - 54, + 219, 231, 71, - 192, 20, - 97, - 37, + 1, + 133, + 36, 17, - 66, + 8, 27, - 11, + 44, 20, - 1, - 141, - 35, + 6, + 34, + 52, 141, - 24, + 96, 56, - 44, + 176, 20, - 7, - 38, + 28, + 37, 0, - 30, + 123, 109, - 219, 40, + 108, 76, 24, - 3, - 185, - 39, - 3, - 205, - 59, - 157, - 180, + 14, + 38, + 251, + 126, 65, - 27, - 28, - 76, - 216, - 91, - 75, - 18, - 28, - 221, + 23, + 65, + 151, + 139, + 32, + 107, + 35, + 138, + 66, + 123, + 179, 189, + 182, + 62, + 168, + 122, + 224, + 90, + 173, + 240, + 116, + 178, + 75, + 210, + 105, 1, - 79, - 87, - 65, - 216, - 85, - 88, - 31, + 108, 217, - 83, - 41, - 246, + 174, 97, - 103, - 101, - 34, - 92, - 31, - 51, - 240, - 185, - 44, - 45, - 207, + 196, + 109, 65, - 174, - 118, - 142, - 133, + 52, + 116, + 131, 74, - 231, - 24, - 254, - 53, + 40, + 220, + 193, + 243, + 164, 25, - 139, - 0, + 245, + 88, 19, - 9, - 77, - 45, + 74, + 104, + 34, 2, - 24, - 131, - 176, + 197, + 120, + 133, + 210, 221, - 187, 26, - 179, - 163, + 168, 65, - 181, - 90, - 129, - 5, - 115, - 74, - 95, - 195, - 204, - 176, + 26, + 170, + 208, + 93, + 42, + 104, + 86, + 84, + 193, + 29, 27, - 125, - 22, + 152, + 146, + 224, + 3, + 182, + 119, + 80, 41, - 77, + 29, 29, 33, - 234, + 223, 176, 62, 49, 59, - 157, + 146, 101, 5, 132, @@ -1002,55 +1001,55 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 0, 66, 53, - 203, + 192, 131, 14, 79, - 133, - 83, - 226, - 134, - 80, - 73, 26, - 91, - 146, - 214, - 91, + 107, + 208, + 100, + 195, + 62, + 80, + 82, + 203, + 75, 127, + 120, 68, - 198, 70, 85, - 110, - 41, - 235, - 1, - 106, - 169, - 117, - 23, - 214, + 197, 99, + 32, + 224, + 45, + 169, + 78, + 12, + 186, + 88, 75, + 192, 20, - 3, + 98, 28, - 22, - 18, - 193, + 216, + 7, 88, - 171, - 193, - 21, - 33, - 112, + 53, + 182, + 100, + 10, + 46, 169, 0, 0, 0, 0, 0, - 39, + 4, + 255, 255, }; diff --git a/avr/cores/megacommand/resources/R_menu_options.cpp b/avr/cores/megacommand/resources/R_menu_options.cpp index 8700bd812..e76a13cda 100644 --- a/avr/cores/megacommand/resources/R_menu_options.cpp +++ b/avr/cores/megacommand/resources/R_menu_options.cpp @@ -469,7 +469,14 @@ const unsigned char __R_menu_options[] PROGMEM = { 97, 128, 40, - 12, + 130, + 175, + 67, + 80, + 10, + 92, + 196, + 128, 0, 0, 0, diff --git a/avr/cores/megacommand/resources/R_page_entries.cpp b/avr/cores/megacommand/resources/R_page_entries.cpp index ad92cc649..6a8bad035 100644 --- a/avr/cores/megacommand/resources/R_page_entries.cpp +++ b/avr/cores/megacommand/resources/R_page_entries.cpp @@ -33,7 +33,7 @@ const unsigned char __R_page_entries[] PROGMEM = { 96, 42, 123, - 41, + 40, 2, 22, 109, diff --git a/resource/menu_layouts.cpp b/resource/menu_layouts.cpp index 14330a28c..537ea4c64 100644 --- a/resource/menu_layouts.cpp +++ b/resource/menu_layouts.cpp @@ -43,26 +43,19 @@ menu_t system_menu_layout = { {"NEW PROJECT", 0, 0, 0, 0, NULL_PAGE, 2, 0}, {"MIDI", 0, 0, 0, 0, MIDI_CONFIG_PAGE, 0, 0}, {"MACHINEDRUM", 0, 0, 0, 0, MD_CONFIG_PAGE, 0, 0}, - {"AUX PAGES", 0, 0, 0, 0, AUX_CONFIG_PAGE, 0, 0}, + {"PAGE SETUP", 0, 0, 0, 0, AUX_CONFIG_PAGE, 0, 0}, {"SYSTEM", 0, 0, 0, 0, MCL_CONFIG_PAGE, 0, 0}, }, 0 }; menu_t auxconfig_menu_layout = { - "AUX PAGES", + "PAGE", { // m r n d p f o - {"RAM Page" ,0, 0, 0, 0, RAM_CONFIG_PAGE, 0, 0}, - }, - 0 -}; -menu_t rampage1_menu_layout = { - "RAM PAGE", - { - // m r n d p f o - {"LINK:", 0, 2, 2, 1, NULL_PAGE, 0, 0}, + {"GRID ENCOD:", 0, 2, 2, 62, NULL_PAGE, 0, 122}, + {"RAM LINK:", 0, 2, 2, 1, NULL_PAGE, 0, 0}, }, 0 }; diff --git a/resource/menu_options.cpp b/resource/menu_options.cpp index 251c75009..16feb47cd 100644 --- a/resource/menu_options.cpp +++ b/resource/menu_options.cpp @@ -69,6 +69,8 @@ menu_option_t MENU_OPTIONS[] = { // 117 {0, "A"}, {1, "B"}, {2, "C"}, {3, "D"}, // 121 - {128, "--"} + {128, "--"}, + // 122 + {0, "--"}, {1,"PERF"} }; From 40772848e0f2fd71e217cac5dcf5558e7af83700 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 13 Oct 2024 15:02:53 +1100 Subject: [PATCH 084/133] Show pattern number when selecting multiple slots --- avr/cores/megacommand/MCL/GridPage.cpp | 27 +++++++++++++++++++++++++- avr/cores/megacommand/MCL/GridPage.h | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index 5a507f862..27e006849 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -566,6 +566,24 @@ void GridPage::display_slot_menu() { // grid_slot_page.draw_scrollbar(36); } +void GridPage::display_row_info() { + uint8_t row_shift = 0; + if ((cur_row + param4.cur > MAX_VISIBLE_ROWS - 1)) { + row_shift = cur_row + param4.cur - MAX_VISIBLE_ROWS; + } + char val[4]; + val[2] = '\0'; + + for (uint8_t n = 0; n < MAX_VISIBLE_ROWS; n++) { + uint8_t row = getRow() - cur_row + n + row_shift; + if (row >= GRID_LENGTH) { return; } + uint8_t b = row / 16; + oled_display.setCursor(27, (n + 1) * 8); + oled_display.print((char)('A' + b)); + mcl_gui.put_value_at2(row - b * 16 + 1, val); + oled_display.print(val); + } +} #ifdef FPS int frames; int frameclock; @@ -586,7 +604,12 @@ void GridPage::display() { if (!show_slot_menu) { display_grid_info(); } else { - display_slot_menu(); + if (param4.cur > 1) { + display_row_info(); + } + else{ + display_slot_menu(); + } } display_grid(); if (draw_encoders && clock_diff(draw_encoders_lastclock, slowclock) < 750) { @@ -1129,6 +1152,8 @@ bool GridPage::handleEvent(gui_event_t *event) { DEBUG_DUMP(slot.link.row); encoders[0] = &grid_slot_param1; encoders[1] = &grid_slot_param2; + encoders[2] = ¶m3; + encoders[3] = ¶m4; param3.cur = 1; param4.cur = 1; slot_apply = 0; diff --git a/avr/cores/megacommand/MCL/GridPage.h b/avr/cores/megacommand/MCL/GridPage.h index 21abe7fbe..44a1681b7 100644 --- a/avr/cores/megacommand/MCL/GridPage.h +++ b/avr/cores/megacommand/MCL/GridPage.h @@ -85,6 +85,7 @@ class GridPage : public LightPage { void display_counters(); void display_grid_info(); void display_grid(); + void display_row_info(); void display(); void display_oled(); void setup(); From 90215da34dc5893e57a455a24d797f68adc4c91d Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 14 Oct 2024 15:18:31 +1100 Subject: [PATCH 085/133] Allow device_independent mute_set loading --- Changelog | 15 ++++++++++++--- avr/cores/megacommand/MCL/MCL.h | 2 +- avr/cores/megacommand/MCL/MixerPage.cpp | 10 ++++++++-- avr/cores/megacommand/MCL/MixerPage.h | 2 +- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Changelog b/Changelog index 8e7589e08..9fcdb936e 100644 --- a/Changelog +++ b/Changelog @@ -4,10 +4,19 @@ Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.6 - Changes: - MD's in-built MIDI machines are now supported via the MCL sequencer. - The MIDI data is transmitted on the MegaCommand's MIDI Port 2. + The MD's in-built MIDI machines are now supported via the MCL sequencer. + MIDI data is transmitted on MegaCommand's MIDI Port 2. - It is now possible to change the Port 1 MIDI driver to Generic. + It's now possible to reconfigure the MCL Encoders to act as the four + Performance Controllers when using the GridPage. Via option: Config -> Page -> Grid Encod + + From the Mixer Page, mute sets can now be loaded for a single device. + - To load a Mute Set for active device, hold down an [ Arrow ] Key and press [ YES ] + - To load a Mute Set for both devices simultaneously (MD + External MIDI), hold down [ YES ] and then press an [ Arrow ]. + + When selecting multiple rows for copy/clear/paste operations the corresponding Bank/Pattern id is displayed on the left. + + The Port 1 MIDI driver can now be optionally changed to Generic. Performance optimizations and improvements. diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index c67ab4099..a7db37f62 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -17,7 +17,7 @@ #include "Fonts/TomThumb.h" #define VERSION 4060 -#define VERSION_STR "C4.60" +#define VERSION_STR "D4.60" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 7b30731a0..574e47343 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -416,16 +416,22 @@ void MixerPage::populate_mute_set() { } } -void MixerPage::switch_mute_set(uint8_t state) { +void MixerPage::switch_mute_set(uint8_t state, bool all_devices) { MidiDevice *devs[2] = { midi_active_peering.get_device(UART1_PORT), midi_active_peering.get_device(UART2_PORT), }; + uint8_t focus_device = (midi_device == &MD); + + for (uint8_t dev = 0; dev < 2; dev++) { bool is_md_device = dev == 0; + + if (!all_devices && focus_device != dev) continue; + uint8_t len = (is_md_device) ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; @@ -668,7 +674,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { case MDX_KEY_DOWN: { uint8_t set = get_mute_set(key); if (trig_interface.is_key_down(MDX_KEY_YES)) { - switch_mute_set(set); + switch_mute_set(set,false); } else { preview_mute_set = set; for (uint8_t n = 0; n < 4; n++) { diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index ba1d79171..8e6b37503 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -78,7 +78,7 @@ class MixerPage : public LightPage { void record_mutes_set(bool state); void disable_record_mutes(bool clear = false); void oled_draw_mutes(); - void switch_mute_set(uint8_t state); + void switch_mute_set(uint8_t state, bool all_devices = true); void populate_mute_set(); void load_perf_locks(uint8_t state); From 275dfab4468acf8ce48b3551257c2fad1de7c1dd Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 15 Oct 2024 22:27:03 +1100 Subject: [PATCH 086/133] Try pending mute method for ExtSeqTracks, to prevent blocking --- avr/cores/megacommand/MCL/ExtSeqTrack.cpp | 11 +++++++---- avr/cores/megacommand/MCL/ExtSeqTrack.h | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/MCL/ExtSeqTrack.cpp b/avr/cores/megacommand/MCL/ExtSeqTrack.cpp index e9e0ec586..f2d88127f 100644 --- a/avr/cores/megacommand/MCL/ExtSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/ExtSeqTrack.cpp @@ -678,6 +678,12 @@ void ExtSeqTrack::seq(MidiUartParent *uart_) { SET_BIT128_P(mute_mask, s); } + if (mute_state_pending) { + mute_state = SEQ_MUTE_ON; + mute_state_pending = false; + buffer_notesoff(); + } + if ((is_generic_midi || (!is_generic_midi && count_down == 0)) && (mute_state == SEQ_MUTE_OFF)) { // SEQ_MUTE_OFF)) { @@ -1213,10 +1219,7 @@ void ExtSeqTrack::toggle_mute() { if (mute_state == SEQ_MUTE_ON) { mute_state = SEQ_MUTE_OFF; } else { - mute_state = SEQ_MUTE_ON; - uint8_t mod12_counter_ = MidiClock.mod12_counter; - while (MidiClock.state == 2 && mod12_counter_ == MidiClock.mod12_counter) { - }; + mute_state_pending = true; buffer_notesoff(); } } diff --git a/avr/cores/megacommand/MCL/ExtSeqTrack.h b/avr/cores/megacommand/MCL/ExtSeqTrack.h index 3975859f1..b19bed45a 100644 --- a/avr/cores/megacommand/MCL/ExtSeqTrack.h +++ b/avr/cores/megacommand/MCL/ExtSeqTrack.h @@ -158,6 +158,7 @@ class ExtSeqTrack : public ExtSeqTrackData, public SeqSlideTrack { static uint8_t epoch; NoteVector notes_on[NUM_NOTES_ON]; uint8_t notes_on_count; + bool mute_state_pending; uint8_t locks_slide_next_lock_utiming[NUM_LOCKS]; @@ -168,6 +169,7 @@ class ExtSeqTrack : public ExtSeqTrackData, public SeqSlideTrack { memset(oneshot_mask,0,sizeof(oneshot_mask)); memset(ignore_notes,0, sizeof(ignore_notes)); pgm_oneshot = 0; + mute_state_pending = false; } void seq(MidiUartParent *uart_); From d5c00d9d924b53beacac8724c25e5a4a0a349e3f Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 15 Oct 2024 23:16:06 +1100 Subject: [PATCH 087/133] Autofill Perf Controller Scenes --- avr/cores/megacommand/MCL/MDFXTrack.cpp | 1 + avr/cores/megacommand/MCL/MixerPage.cpp | 43 ++++++++++++++++++++++- avr/cores/megacommand/MCL/PerfData.h | 38 ++++++++++++++++++++ avr/cores/megacommand/MCL/PerfEncoder.cpp | 5 +++ avr/cores/megacommand/MCL/PerfEncoder.h | 1 + avr/cores/megacommand/MD/MD.cpp | 8 +++++ avr/cores/megacommand/MD/MD.h | 1 + avr/cores/megacommand/MD/MDMessages.h | 4 +-- 8 files changed, 98 insertions(+), 3 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDFXTrack.cpp b/avr/cores/megacommand/MCL/MDFXTrack.cpp index a2fed0350..691aba0a3 100644 --- a/avr/cores/megacommand/MCL/MDFXTrack.cpp +++ b/avr/cores/megacommand/MCL/MDFXTrack.cpp @@ -60,6 +60,7 @@ void MDFXTrack::load_immediate_cleared(uint8_t tracknumber, SeqTrack *seq_track) void MDFXTrack::place_fx_in_kit() { DEBUG_PRINTLN("place"); memcpy(MD.kit.reverb, reverb, sizeof(reverb) * 4); + memcpy(MD.kit.fx_orig, reverb, sizeof(reverb) * 4); /* if (enable_reverb) { memcpy(&MD.kit.reverb, &reverb, sizeof(reverb)); diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 574e47343..87601cd64 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -626,6 +626,27 @@ bool MixerPage::handleEvent(gui_event_t *event) { break; } case MDX_KEY_NO: { + if (BUTTON_DOWN(Buttons.ENCODER1)) { + perf_param1.perf_data.init_params_verbose(); + redraw_mask = -1; + return true; + } + if (BUTTON_DOWN(Buttons.ENCODER2)) { + perf_param2.perf_data.init_params_verbose(); + redraw_mask = -1; + return true; + } + if (BUTTON_DOWN(Buttons.ENCODER3)) { + perf_param3.perf_data.init_params_verbose(); + redraw_mask = -1; + return true; + } + if (BUTTON_DOWN(Buttons.ENCODER4)) { + perf_param4.perf_data.init_params_verbose(); + redraw_mask = -1; + return true; + } + uint64_t mask = ((uint64_t)1 << MDX_KEY_LEFT) | ((uint64_t)1 << MDX_KEY_UP) | ((uint64_t)1 << MDX_KEY_RIGHT) | ((uint64_t)1 << MDX_KEY_DOWN); @@ -639,7 +660,27 @@ bool MixerPage::handleEvent(gui_event_t *event) { break; } case MDX_KEY_YES: { - if (preview_mute_set == 255 && + if (BUTTON_DOWN(Buttons.ENCODER1)) { + perf_param1.perf_data.quick_scene_populate(); + redraw_mask = -1; + return true; + } + if (BUTTON_DOWN(Buttons.ENCODER2)) { + perf_param2.perf_data.quick_scene_populate(); + redraw_mask = -1; + return true; + } + if (BUTTON_DOWN(Buttons.ENCODER3)) { + perf_param3.perf_data.quick_scene_populate(); + redraw_mask = -1; + return true; + } + if (BUTTON_DOWN(Buttons.ENCODER4)) { + perf_param4.perf_data.quick_scene_populate(); + redraw_mask = -1; + return true; + } + if (preview_mute_set == 255 && trig_interface.is_key_down(MDX_KEY_FUNC) && note_interface.notes_on == 0) { switch_mute_set(4); //---> Flip mutes diff --git a/avr/cores/megacommand/MCL/PerfData.h b/avr/cores/megacommand/MCL/PerfData.h index 467d42420..88a710123 100644 --- a/avr/cores/megacommand/MCL/PerfData.h +++ b/avr/cores/megacommand/MCL/PerfData.h @@ -207,6 +207,44 @@ class PerfData { } } + void init_params_verbose() { + oled_display.textbox("CLEAR SCENES", ""); + init_params(); + } + + void quick_scene_populate() { + oled_display.textbox("FILL SCENES", ""); + uint8_t scene = 0; + uint8_t *params = (uint8_t *) &MD.kit.params; + uint8_t *params_orig = (uint8_t *) &MD.kit.params_orig; + + for (uint8_t track = 0; track < 16; track++) { + for (uint8_t param = 0; param < 24; param++) { + if (MD.kit.params[track][param] != MD.kit.params_orig[track][param]) { + scene = MD.kit.params[track][param] >= MD.kit.params_orig[track][param]; + if (add_param(track,param,scene,MD.kit.params[track][param]) != 255) { + MD.kit.params[track][param] = MD.kit.params_orig[track][param]; + } + } + + } + } + for (uint8_t n = 0; n < 8 * 4; n++) { + uint8_t fx = n / 8; + uint8_t param = n - fx * 8; + //delay and reverb are flipped in memory + if (fx == 0) { fx = 1; } + else if (fx == 1) { fx = 0; } + uint8_t *fxs = (uint8_t *) &MD.kit.reverb; + uint8_t *fxs_orig = (uint8_t *) &MD.kit.fx_orig; + if (fxs[n] != fxs_orig[n]) { + scene = fxs[n] >= fxs_orig[n]; + if (add_param(fx + NUM_MD_TRACKS,param,scene,fxs[n]) != 255) { + fxs[n] = fxs_orig[n]; + } + } + } + } }; diff --git a/avr/cores/megacommand/MCL/PerfEncoder.cpp b/avr/cores/megacommand/MCL/PerfEncoder.cpp index f636fb2d9..3632755df 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.cpp +++ b/avr/cores/megacommand/MCL/PerfEncoder.cpp @@ -61,3 +61,8 @@ int PerfEncoder::update(encoder_t *enc) { return cur; } +void PerfEncoder::quick_scene_populate() { + perf_data.quick_scene_populate(); + cur = 127; + old = 127; +} diff --git a/avr/cores/megacommand/MCL/PerfEncoder.h b/avr/cores/megacommand/MCL/PerfEncoder.h index 8e7051fb0..3af7a152c 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.h +++ b/avr/cores/megacommand/MCL/PerfEncoder.h @@ -26,6 +26,7 @@ class PerfEncoder : public MCLEncoder { void send(); void send_param(uint8_t dest, uint8_t param, uint8_t val); void send_params(uint8_t cur_, PerfScene *s1, PerfScene *s2); + void quick_scene_populate(); /** Create a new range-limited encoder with max and min value, short name, initial value, and handling function. The initRangeEncoder diff --git a/avr/cores/megacommand/MD/MD.cpp b/avr/cores/megacommand/MD/MD.cpp index a64212fa0..6d4a7aebb 100644 --- a/avr/cores/megacommand/MD/MD.cpp +++ b/avr/cores/megacommand/MD/MD.cpp @@ -235,6 +235,7 @@ bool MDClass::probe() { mcl_gui.delay_progress(300); getCurrentTrack(CALLBACK_TIMEOUT); getBlockingKit(0x7F); + MD.save_kit_params(); setup(); uint8_t y = 0; @@ -364,8 +365,15 @@ void MDClass::parallelTrig(uint16_t mask, MidiUartParent *uart_) { } } +void MDClass::save_kit_params() { + memcpy(kit.params_orig, kit.params, sizeof(kit.params)); + memcpy(kit.fx_orig, kit.reverb, sizeof(kit.reverb) * 4); +} + + void MDClass::restore_kit_params() { memcpy(kit.params, kit.params_orig, sizeof(kit.params)); + memcpy(kit.reverb, kit.fx_orig, sizeof(kit.reverb) * 4); } void MDClass::restore_kit_param(uint8_t track, uint8_t param) { diff --git a/avr/cores/megacommand/MD/MD.h b/avr/cores/megacommand/MD/MD.h index 71f9374aa..8d224b5f2 100644 --- a/avr/cores/megacommand/MD/MD.h +++ b/avr/cores/megacommand/MD/MD.h @@ -115,6 +115,7 @@ class MDClass : public ElektronDevice { /* Restore modified kit params, with the original values. */ void restore_kit_params(); + void save_kit_params(); /* Restore a single kit param, and transmit the param to the MD */ void restore_kit_param(uint8_t track, uint8_t param); diff --git a/avr/cores/megacommand/MD/MDMessages.h b/avr/cores/megacommand/MD/MDMessages.h index 18ee88646..0df8c1cc5 100644 --- a/avr/cores/megacommand/MD/MDMessages.h +++ b/avr/cores/megacommand/MD/MDMessages.h @@ -239,7 +239,6 @@ class MDKit: public ElektronSysexObject { uint32_t models[16]; /** The LFO settings for each track. **/ MDLFO lfos[16]; - /** The settings of the reverb effect. **/ uint8_t reverb[8]; /** The settings of the delay effect. **/ @@ -248,7 +247,8 @@ class MDKit: public ElektronSysexObject { uint8_t eq[8]; /** The settings of the compressor effect. **/ uint8_t dynamics[8]; - + /** Duplicate fx params not included in the origin MD structure */ + uint8_t fx_orig[4][9]; /** The trig group selected for each track (255: OFF). **/ uint8_t trigGroups[16]; /** The mute group selected for each track (255: OFF). **/ From 78f0fe78b3d3b8991f8f50bc7ae0d7b309f7a950 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 17 Oct 2024 16:54:19 +1100 Subject: [PATCH 088/133] Muteset mute and perf transmission --- avr/cores/megacommand/MCL/MCLMemory.h | 2 +- avr/cores/megacommand/MCL/MCLSeq.cpp | 9 +++---- avr/cores/megacommand/MCL/MCLSeq.h | 2 ++ avr/cores/megacommand/MCL/MCL_impl.h | 1 + avr/cores/megacommand/MCL/MixerPage.cpp | 13 +++++++++- avr/cores/megacommand/MCL/MixerPage.h | 1 + avr/cores/megacommand/MCL/PerfData.h | 11 +++++++-- avr/cores/megacommand/MCL/PerfSeqTrack.cpp | 26 ++++++++++++++++++++ avr/cores/megacommand/MCL/PerfSeqTrack.h | 28 ++++++++++++++++++++++ avr/cores/megacommand/MCL/PerfTrack.cpp | 23 +++++++++++++++--- avr/cores/megacommand/MCL/PerfTrack.h | 2 +- avr/cores/megacommand/MD/MD.cpp | 2 +- 12 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 avr/cores/megacommand/MCL/PerfSeqTrack.cpp create mode 100644 avr/cores/megacommand/MCL/PerfSeqTrack.h diff --git a/avr/cores/megacommand/MCL/MCLMemory.h b/avr/cores/megacommand/MCL/MCLMemory.h index 847d142d0..e29b2c644 100644 --- a/avr/cores/megacommand/MCL/MCLMemory.h +++ b/avr/cores/megacommand/MCL/MCLMemory.h @@ -35,7 +35,7 @@ constexpr size_t NUM_EXT_TRACKS = 0; constexpr size_t NUM_INSTRUMENT_TRACKS = (NUM_MD_TRACKS + NUM_EXT_TRACKS); -constexpr size_t NUM_AUX_TRACKS = 4; +constexpr size_t NUM_AUX_TRACKS = 3; constexpr size_t GRIDCHAIN_TRACK_NUM = 10; constexpr size_t PERF_TRACK_NUM = 11; diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index ce1c7dac9..846501dde 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -39,6 +39,9 @@ void MCLSeq::setup() { mdfx_track.length = 16; mdfx_track.speed = SEQ_SPEED_1X; + perf_track.length = 16; + perf_track.speed = SEQ_SPEED_1X; + enable(); MidiClock.addOnMidiStopCallback( @@ -108,7 +111,7 @@ void MCLSeq::onMidiStartImmediateCallback() { aux_tracks[i].reset(); } mdfx_track.reset(); - + perf_track.reset(); #ifdef LFO_TRACKS for (uint8_t i = 0; i < num_lfo_tracks; i++) { lfo_tracks[i].sample_hold = 0; @@ -242,7 +245,6 @@ void MCLSeq::seq() { } mdfx_track.seq(); - if (MDSeqTrack::load_machine_cache) { MD.setKitName(grid_task.kit_names[0], uart); MD.loadMachinesCache(MDSeqTrack::load_machine_cache, uart); @@ -251,8 +253,7 @@ void MCLSeq::seq() { for (uint8_t i = 0; i < NUM_AUX_TRACKS; i++) { aux_tracks[i].seq(); } - // Arp - + perf_track.seq(); #ifdef LFO_TRACKS for (uint8_t i = 0; i < num_lfo_tracks; i++) { lfo_tracks[i].seq(uart, uart2); diff --git a/avr/cores/megacommand/MCL/MCLSeq.h b/avr/cores/megacommand/MCL/MCLSeq.h index 10336deba..f09ba8538 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.h +++ b/avr/cores/megacommand/MCL/MCLSeq.h @@ -11,6 +11,7 @@ #include "ArpSeqTrack.h" #include "ExtSeqTrack.h" #include "MDFXseqTrack.h" +#include "PerfSeqTrack.h" #define SEQ_MUTE_ON 1 #define SEQ_MUTE_OFF 0 @@ -63,6 +64,7 @@ class MCLSeq : public ClockCallback { SeqTrackBase aux_tracks[NUM_AUX_TRACKS]; + PerfSeqTrack perf_track; MDFXSeqTrack mdfx_track; MCLSeqMidiEvents midi_events; diff --git a/avr/cores/megacommand/MCL/MCL_impl.h b/avr/cores/megacommand/MCL/MCL_impl.h index c8182f87e..024c28f5c 100644 --- a/avr/cores/megacommand/MCL/MCL_impl.h +++ b/avr/cores/megacommand/MCL/MCL_impl.h @@ -82,6 +82,7 @@ #include "ArpSeqTrack.h" #include "EmptyTrack.h" #include "LFOSeqTrack.h" +#include "PerfSeqTrack.h" #include "MNMTrack.h" #include "MCLActions.h" diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 87601cd64..c26de909a 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -265,6 +265,7 @@ void MixerPage::adjust_param(EncoderParent *enc, uint8_t param) { void MixerPage::display() { auto oldfont = oled_display.getFont(); + //oled_display.setFont(); if (oled_display.textbox_enabled) { oled_display.clearDisplay(); oled_draw_mutes(); @@ -296,6 +297,12 @@ void MixerPage::display() { if (draw_encoders || preview_mute_set != 255) { // oled_display.clearDisplay(); draw_encs(); + if (load_mute_set != 255 && load_mute_set == preview_mute_set) { + oled_display.setFont(&TomThumb); + oled_display.setCursor(111, 31); + oled_display.print("LOAD"); + oled_display.setFont(); + } oled_display.display(); } else { @@ -708,7 +715,11 @@ bool MixerPage::handleEvent(gui_event_t *event) { } break; } - + case MDX_KEY_FUNC: { + if (load_mute_set == preview_mute_set) { load_mute_set = 255; } + else { load_mute_set = preview_mute_set; } + break; + } case MDX_KEY_LEFT: case MDX_KEY_UP: case MDX_KEY_RIGHT: diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index 8e6b37503..2e8fb4e04 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -50,6 +50,7 @@ class MixerPage : public LightPage { uint8_t current_mute_set = 255; uint8_t preview_mute_set = 255; + uint8_t load_mute_set = 255; void send_fx(uint8_t param, Encoder *enc, uint8_t type); // Don't change order diff --git a/avr/cores/megacommand/MCL/PerfData.h b/avr/cores/megacommand/MCL/PerfData.h index 88a710123..2f503793f 100644 --- a/avr/cores/megacommand/MCL/PerfData.h +++ b/avr/cores/megacommand/MCL/PerfData.h @@ -223,7 +223,12 @@ class PerfData { if (MD.kit.params[track][param] != MD.kit.params_orig[track][param]) { scene = MD.kit.params[track][param] >= MD.kit.params_orig[track][param]; if (add_param(track,param,scene,MD.kit.params[track][param]) != 255) { - MD.kit.params[track][param] = MD.kit.params_orig[track][param]; + //Kit encoders go back to normal, for save. + uint8_t val = MD.kit.params[track][param]; + MD.setTrackParam(track, param, MD.kit.params_orig[track][param], nullptr, + true); + MD.setTrackParam(track, param, val, nullptr, + false); } } @@ -240,7 +245,9 @@ class PerfData { if (fxs[n] != fxs_orig[n]) { scene = fxs[n] >= fxs_orig[n]; if (add_param(fx + NUM_MD_TRACKS,param,scene,fxs[n]) != 255) { - fxs[n] = fxs_orig[n]; + uint8_t val = fxs[n]; + MD.setFXParam(param, fxs_orig[n], fx + MD_FX_ECHO, true); + MD.setFXParam(param, val, fx + MD_FX_ECHO, false); } } } diff --git a/avr/cores/megacommand/MCL/PerfSeqTrack.cpp b/avr/cores/megacommand/MCL/PerfSeqTrack.cpp new file mode 100644 index 000000000..09cbb420f --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfSeqTrack.cpp @@ -0,0 +1,26 @@ +#include "MCL_impl.h" + +void PerfSeqTrack::seq() { + uint8_t timing_mid = get_timing_mid(); + mod12_counter++; + if (mod12_counter == timing_mid) { + mod12_counter = 0; + step_count_inc(); + } + if (count_down) { + count_down--; + if (count_down == 0) { + if (load_sound) { + for (uint8_t n = 0; n < 4; n++) { + if (perf_locks[n] != 255) { + mixer_page.encoders[n]->cur = perf_locks[n]; + mixer_page.encoders[n]->old = perf_locks[n] + 1; + } + perf_locks[n] = 255; + } + } + reset(); + mod12_counter = 0; + } + } +} diff --git a/avr/cores/megacommand/MCL/PerfSeqTrack.h b/avr/cores/megacommand/MCL/PerfSeqTrack.h new file mode 100644 index 000000000..2f7453ae4 --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfSeqTrack.h @@ -0,0 +1,28 @@ +/* Justin Mammarella jmamma@gmail.com 2021 */ + +#pragma once + +#include "MidiUartParent.h" +#include "SeqTrack.h" +#include "WProgram.h" +#include "GridTrack.h" + +//Ephemeral +class PerfSeqTrack : public SeqTrackBase { + +public: + + uint8_t perf_locks[4]; + + PerfSeqTrack() : SeqTrackBase() { + active = PERF_TRACK_TYPE; + init(); + } + void reset() { + memset(perf_locks,255,sizeof(perf_locks)); + SeqTrackBase::reset(); + } + + void seq(); + +}; diff --git a/avr/cores/megacommand/MCL/PerfTrack.cpp b/avr/cores/megacommand/MCL/PerfTrack.cpp index c21bb5198..7f2b1f17f 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.cpp +++ b/avr/cores/megacommand/MCL/PerfTrack.cpp @@ -9,7 +9,7 @@ void PerfTrack::transition_load(uint8_t tracknumber, SeqTrack *seq_track, DEBUG_PRINTLN("transition send"); GridTrack::transition_load(tracknumber, seq_track, slotnumber); if (mcl_actions.send_machine[slotnumber]) { - load_perf(); + load_perf(seq_track); } } @@ -34,10 +34,14 @@ void PerfTrack::get_perf() { DEBUG_PRINTLN(sizeof(scenes)); memcpy(scenes, PerfData::scenes, sizeof(PerfScene) * NUM_SCENES); memcpy(mute_sets,mixer_page.mute_sets, sizeof(mute_sets) + sizeof(perf_locks)); + //Encode the load_mute_set value into the high bit of the corresponding ext mutes. + if (mixer_page.load_mute_set < 4) { + mute_sets[1].mutes[mixer_page.load_mute_set] &= 0b01111111; + } } -void PerfTrack::load_perf() { +void PerfTrack::load_perf(SeqTrack *seq_track) { DEBUG_PRINTLN("load perf"); DEBUG_PRINTLN( sizeof(scenes)); for (uint8_t n = 0; n < 4; n++) { @@ -53,13 +57,26 @@ void PerfTrack::load_perf() { memcpy(e->name,encs[n].name, PERF_NAME_LENGTH); } memcpy(PerfData::scenes, scenes, sizeof(PerfScene) * NUM_SCENES); + + mixer_page.load_mute_set = 255; + for (uint8_t n = 0; n < 4; n++) { + if ((mute_sets[1].mutes[n] & 0b10000000) == 0) { + mixer_page.load_mute_set = n; + mute_sets[1].mutes[n] |= 0b11000000; + } + } memcpy(mixer_page.mute_sets, mute_sets, sizeof(mute_sets) + sizeof(perf_locks)); + if (mixer_page.load_mute_set < 4) { + mixer_page.switch_mute_set(mixer_page.load_mute_set); //Mute change is applied outside of sequencer runtime. + PerfSeqTrack *p = (PerfSeqTrack*) seq_track; + memcpy(p->perf_locks, &perf_locks[mixer_page.load_mute_set],4); //Perf change is pre-empted at sequencer runtime. + } } void PerfTrack::load_immediate(uint8_t tracknumber, SeqTrack *seq_track) { DEBUG_PRINTLN("load immediate"); load_link_data(seq_track); - load_perf(); + load_perf(seq_track); } bool PerfTrack::store_in_grid(uint8_t column, uint16_t row, diff --git a/avr/cores/megacommand/MCL/PerfTrack.h b/avr/cores/megacommand/MCL/PerfTrack.h index e86a916b0..79aac09a2 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.h +++ b/avr/cores/megacommand/MCL/PerfTrack.h @@ -59,7 +59,7 @@ class PerfTrack : public AUXTrack, public PerfTrackData { memset(perf_locks, 255, sizeof(perf_locks)); } - void load_perf(); + void load_perf(SeqTrack *seq_track); void get_perf(); uint16_t calc_latency(uint8_t tracknumber); diff --git a/avr/cores/megacommand/MD/MD.cpp b/avr/cores/megacommand/MD/MD.cpp index 6d4a7aebb..19632dda5 100644 --- a/avr/cores/megacommand/MD/MD.cpp +++ b/avr/cores/megacommand/MD/MD.cpp @@ -174,7 +174,7 @@ void MDClass::init_grid_devices(uint8_t device_idx) { add_track_to_grid(grid_idx, MDTEMPO_TRACK_NUM, &gdt); gdt.init(PERF_TRACK_TYPE, GROUP_PERF, device_idx, - (SeqTrack *)&(mcl_seq.aux_tracks[3]), 0); + (SeqTrack *)&(mcl_seq.perf_track), 0); add_track_to_grid(grid_idx, PERF_TRACK_NUM, &gdt); } From cb3aad35d0af43ec9a3928a06488fa3d63eb571d Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 18 Oct 2024 00:54:55 +1100 Subject: [PATCH 089/133] Improve perf lock loading on transition --- avr/cores/megacommand/MCL/MixerPage.cpp | 4 ++-- avr/cores/megacommand/MCL/MixerPage.h | 2 +- avr/cores/megacommand/MCL/PerfEncoder.cpp | 1 + avr/cores/megacommand/MCL/PerfEncoder.h | 2 ++ avr/cores/megacommand/MCL/PerfPage.cpp | 2 +- avr/cores/megacommand/MCL/PerfSeqTrack.cpp | 10 +++++++--- avr/cores/megacommand/MCL/PerfTrack.cpp | 14 ++++++++------ avr/cores/megacommand/MCL/PerfTrack.h | 2 +- 8 files changed, 23 insertions(+), 14 deletions(-) diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index c26de909a..ea6013eef 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -423,7 +423,7 @@ void MixerPage::populate_mute_set() { } } -void MixerPage::switch_mute_set(uint8_t state, bool all_devices) { +void MixerPage::switch_mute_set(uint8_t state, bool all_devices, bool load_perf) { MidiDevice *devs[2] = { midi_active_peering.get_device(UART1_PORT), @@ -463,7 +463,7 @@ void MixerPage::switch_mute_set(uint8_t state, bool all_devices) { } } } - if (state < 4) { + if (state < 4 && load_perf) { load_perf_locks(state); } oled_draw_mutes(); diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index 2e8fb4e04..652a6e494 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -79,7 +79,7 @@ class MixerPage : public LightPage { void record_mutes_set(bool state); void disable_record_mutes(bool clear = false); void oled_draw_mutes(); - void switch_mute_set(uint8_t state, bool all_devices = true); + void switch_mute_set(uint8_t state, bool all_devices = true, bool load_perf = false); void populate_mute_set(); void load_perf_locks(uint8_t state); diff --git a/avr/cores/megacommand/MCL/PerfEncoder.cpp b/avr/cores/megacommand/MCL/PerfEncoder.cpp index 3632755df..3deee9baf 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.cpp +++ b/avr/cores/megacommand/MCL/PerfEncoder.cpp @@ -53,6 +53,7 @@ void PerfEncoder::send() { PerfScene *s1 = active_scene_a == 255 ? nullptr : &perf_data.scenes[active_scene_a]; PerfScene *s2 = active_scene_b == 255 ? nullptr : &perf_data.scenes[active_scene_b]; send_params(cur, s1, s2); + resend = false; } int PerfEncoder::update(encoder_t *enc) { diff --git a/avr/cores/megacommand/MCL/PerfEncoder.h b/avr/cores/megacommand/MCL/PerfEncoder.h index 3af7a152c..8ff51db66 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.h +++ b/avr/cores/megacommand/MCL/PerfEncoder.h @@ -22,6 +22,8 @@ class PerfEncoder : public MCLEncoder { uint8_t active_scene_a = 0; uint8_t active_scene_b = 1; + bool resend = false; + void init() { perf_data.init(); } void send(); void send_param(uint8_t dest, uint8_t param, uint8_t val); diff --git a/avr/cores/megacommand/MCL/PerfPage.cpp b/avr/cores/megacommand/MCL/PerfPage.cpp index b3754ee8b..a9b7b6f2a 100644 --- a/avr/cores/megacommand/MCL/PerfPage.cpp +++ b/avr/cores/megacommand/MCL/PerfPage.cpp @@ -313,7 +313,7 @@ void PerfPage::encoder_check() { void PerfPage::encoder_send() { for (uint8_t i = 0; i < 4; i++) { - if (perf_encoders[i]->hasChanged()) { perf_encoders[i]->send(); } + if (perf_encoders[i]->hasChanged() || perf_encoders[i]->resend) { perf_encoders[i]->send(); } } } diff --git a/avr/cores/megacommand/MCL/PerfSeqTrack.cpp b/avr/cores/megacommand/MCL/PerfSeqTrack.cpp index 09cbb420f..95e96024a 100644 --- a/avr/cores/megacommand/MCL/PerfSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/PerfSeqTrack.cpp @@ -9,16 +9,20 @@ void PerfSeqTrack::seq() { } if (count_down) { count_down--; - if (count_down == 0) { + if (count_down <= 1) { if (load_sound) { for (uint8_t n = 0; n < 4; n++) { if (perf_locks[n] != 255) { - mixer_page.encoders[n]->cur = perf_locks[n]; - mixer_page.encoders[n]->old = perf_locks[n] + 1; + perf_page.perf_encoders[n]->cur = perf_locks[n]; + perf_page.perf_encoders[n]->old = perf_locks[n]; + perf_page.perf_encoders[n]->resend = true; } perf_locks[n] = 255; } + load_sound = 0; } + } + if (count_down == 0) { reset(); mod12_counter = 0; } diff --git a/avr/cores/megacommand/MCL/PerfTrack.cpp b/avr/cores/megacommand/MCL/PerfTrack.cpp index 7f2b1f17f..d0a1049d3 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.cpp +++ b/avr/cores/megacommand/MCL/PerfTrack.cpp @@ -9,7 +9,7 @@ void PerfTrack::transition_load(uint8_t tracknumber, SeqTrack *seq_track, DEBUG_PRINTLN("transition send"); GridTrack::transition_load(tracknumber, seq_track, slotnumber); if (mcl_actions.send_machine[slotnumber]) { - load_perf(seq_track); + load_perf(false, seq_track); } } @@ -41,7 +41,7 @@ void PerfTrack::get_perf() { } -void PerfTrack::load_perf(SeqTrack *seq_track) { +void PerfTrack::load_perf(bool immediate, SeqTrack *seq_track) { DEBUG_PRINTLN("load perf"); DEBUG_PRINTLN( sizeof(scenes)); for (uint8_t n = 0; n < 4; n++) { @@ -67,16 +67,18 @@ void PerfTrack::load_perf(SeqTrack *seq_track) { } memcpy(mixer_page.mute_sets, mute_sets, sizeof(mute_sets) + sizeof(perf_locks)); if (mixer_page.load_mute_set < 4) { - mixer_page.switch_mute_set(mixer_page.load_mute_set); //Mute change is applied outside of sequencer runtime. - PerfSeqTrack *p = (PerfSeqTrack*) seq_track; - memcpy(p->perf_locks, &perf_locks[mixer_page.load_mute_set],4); //Perf change is pre-empted at sequencer runtime. + mixer_page.switch_mute_set(mixer_page.load_mute_set, true, immediate); //Mute change is applied outside of sequencer runtime. + if (!immediate) { + PerfSeqTrack *p = (PerfSeqTrack*) seq_track; + memcpy(p->perf_locks, &perf_locks[mixer_page.load_mute_set],4); //Perf change is pre-empted at sequencer runtime. + } } } void PerfTrack::load_immediate(uint8_t tracknumber, SeqTrack *seq_track) { DEBUG_PRINTLN("load immediate"); load_link_data(seq_track); - load_perf(seq_track); + load_perf(true, seq_track); } bool PerfTrack::store_in_grid(uint8_t column, uint16_t row, diff --git a/avr/cores/megacommand/MCL/PerfTrack.h b/avr/cores/megacommand/MCL/PerfTrack.h index 79aac09a2..6da1cf809 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.h +++ b/avr/cores/megacommand/MCL/PerfTrack.h @@ -59,7 +59,7 @@ class PerfTrack : public AUXTrack, public PerfTrackData { memset(perf_locks, 255, sizeof(perf_locks)); } - void load_perf(SeqTrack *seq_track); + void load_perf(bool immediate, SeqTrack *seq_track); void get_perf(); uint16_t calc_latency(uint8_t tracknumber); From 71564c432837ee774b06d677c5b7395ca35e9f6d Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 18 Oct 2024 13:41:38 +1100 Subject: [PATCH 090/133] Improvements to system menu saving --- avr/cores/megacommand/MCL/GridPage.cpp | 5 +- .../megacommand/resources/R_menu_layouts.cpp | 364 +++++++++--------- resource/menu_layouts.cpp | 4 +- 3 files changed, 188 insertions(+), 185 deletions(-) diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index 27e006849..6cecf882a 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -120,6 +120,7 @@ void GridPage::loop() { if (mcl_cfg.grid_page_mode == PERF_ENC) { //need to limit range of the alternate encoders encoder_t *enc = nullptr; + perf_page.func_enc_check(); param1.update(enc); param2.update(enc); param3.update(enc); @@ -604,7 +605,7 @@ void GridPage::display() { if (!show_slot_menu) { display_grid_info(); } else { - if (param4.cur > 1) { + if (param4.cur > 4) { display_row_info(); } else{ @@ -973,7 +974,7 @@ bool GridPage::handleEvent(gui_event_t *event) { } next: if (event->mask == EVENT_BUTTON_PRESSED) { - draw_encoders = false; + if (key != MDX_KEY_FUNC) { draw_encoders = false; } uint8_t inc = 1; if (trig_interface.is_key_down(MDX_KEY_FUNC)) { inc = 4; diff --git a/avr/cores/megacommand/resources/R_menu_layouts.cpp b/avr/cores/megacommand/resources/R_menu_layouts.cpp index b3858095c..23966ea7f 100644 --- a/avr/cores/megacommand/resources/R_menu_layouts.cpp +++ b/avr/cores/megacommand/resources/R_menu_layouts.cpp @@ -586,470 +586,472 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 131, 147, 8, - 109, + 111, 73, 16, - 43, - 253, + 1, + 71, + 111, 201, - 123, 32, 77, 73, + 107, 175, - 93, 62, + 173, 85, - 108, 188, + 140, 32, - 101, 240, - 246, + 190, 129, 1, 60, + 221, 31, - 237, 121, 24, + 172, 84, - 96, 30, - 142, + 17, + 220, 78, - 227, 82, 79, 32, + 123, 83, - 217, 33, - 246, + 62, 17, 2, 9, + 216, 31, - 195, 18, + 118, 208, - 176, 20, - 153, + 19, + 46, 46, - 117, 88, 84, 182, 81, 71, + 194, 20, - 19, + 110, 57, - 118, 41, + 218, 24, 82, - 208, 201, - 130, + 16, 113, - 255, + 95, 80, 32, + 241, 49, 32, 70, - 141, 87, + 169, 220, - 73, 127, - 219, + 59, 7, 31, + 108, 10, - 99, 20, + 100, 50, - 32, - 50, + 6, 51, - 251, + 95, 92, 85, 83, 66, + 96, 17, - 5, - 32, + 164, 169, - 219, + 27, 52, 20, + 99, 96, - 28, 26, - 188, + 151, 116, - 37, + 132, 92, - 219, + 187, 11, 20, + 112, 86, - 133, 24, + 161, 124, - 10, 251, - 48, + 70, 5, - 90, + 11, 29, - 184, + 87, 8, - 60, + 7, 183, + 140, 58, - 103, 121, + 237, 5, - 108, 31, + 129, 7, - 8, 5, - 176, + 22, 20, - 57, + 7, 53, - 153, + 51, 41, - 134, + 48, + 204, 204, - 97, 115, - 194, + 56, 6, + 91, 72, - 216, 100, 41, - 176, + 22, 20, - 59, + 7, 54, + 111, 41, - 123, 100, 24, 80, - 190, 109, + 190, 71, + 161, 24, - 14, 220, - 214, + 218, 9, + 221, 220, - 235, 77, 79, + 115, 1, - 152, 126, - 118, + 14, 49, + 219, 31, - 223, 90, 20, + 240, 73, - 132, 78, + 147, 167, - 158, 18, + 195, 2, 47, - 25, 7, - 238, + 61, 20, + 206, 244, - 112, 21, - 65, + 8, 7, - 186, + 55, 48, 20, + 67, 24, - 30, 154, + 214, 83, - 179, 177, - 240, + 126, 85, 82, 66, 79, - 172, + 21, 8, + 151, 221, - 189, 2, + 181, 255, - 172, 78, + 156, 20, - 228, 50, - 185, + 151, 3, 36, - 53, + 134, 13, + 176, 58, - 131, 20, + 102, 55, - 52, + 133, 68, - 42, - 102, 102, + 76, 98, + 214, 63, - 178, 136, - 109, + 77, 61, + 182, 189, - 176, 84, 20, - 100, + 12, 50, - 153, + 147, 4, - 129, - 139, + 48, + 49, 97, + 120, 119, - 192, - 155, + 19, 26, + 109, 62, - 111, 56, + 225, 210, - 8, 215, - 46, + 5, + 207, 210, - 125, 26, + 174, 32, - 116, 130, + 133, 70, - 43, 183, + 96, 118, - 6, + 199, 33, - 56, 205, - 48, + 6, 80, - 194, + 24, 100, - 227, + 92, 35, + 115, 121, - 156, 207, - 219, + 155, 231, 71, + 96, 20, - 1, - 133, + 48, 36, + 161, 17, - 8, 27, - 44, + 5, + 128, 20, - 6, + 198, 34, - 52, 141, - 96, + 140, 56, - 176, + 22, 20, - 28, + 3, 37, - 0, - 123, + 6, + 107, + 142, + 109, 109, 40, - 108, 76, + 129, 24, - 14, + 223, 38, - 251, 126, 65, + 104, 23, - 65, - 151, + 50, 139, + 237, 32, - 107, 35, + 104, 138, - 66, + 86, 123, - 179, 189, - 182, + 118, 62, 168, + 220, 122, - 224, 90, - 173, + 21, 240, + 182, 116, - 178, 75, 210, - 105, + 78, 1, - 108, - 217, + 255, + 230, + 196, 174, - 97, + 88, + 91, 196, - 109, 65, 52, - 116, + 93, 131, 74, - 40, + 10, 220, - 193, + 48, 243, - 164, + 105, 25, 245, - 88, + 22, 19, - 74, - 104, + 18, + 154, 34, 2, - 197, + 49, 120, - 133, + 97, 210, - 221, + 119, 26, 168, + 70, 65, - 26, 170, - 208, + 180, 93, - 42, + 10, 104, - 86, + 149, 84, + 135, 193, - 29, 27, - 152, + 102, 146, - 224, + 56, 3, - 182, + 45, 119, 80, + 135, 41, 29, - 29, - 33, + 72, 223, - 176, + 108, 62, - 49, - 59, + 12, + 78, 146, + 193, 101, - 5, - 132, + 97, 136, - 78, + 19, 0, + 141, 66, - 53, 192, - 131, + 96, 14, + 198, 79, - 26, 107, - 208, + 180, 100, - 195, + 48, 62, + 212, 80, - 82, + 146, 203, - 75, + 222, 127, - 120, 68, 70, 85, - 197, + 49, 99, - 32, + 72, 224, - 45, + 11, 169, - 78, + 83, 12, - 186, + 174, 88, + 176, 75, - 192, 20, - 98, + 24, 28, - 216, + 182, 7, 88, - 53, + 13, 182, - 100, + 89, 10, - 46, + 11, 169, + 128, 0, 0, 0, 0, - 0, - 4, - 255, + 1, + 63, 255, }; diff --git a/resource/menu_layouts.cpp b/resource/menu_layouts.cpp index 537ea4c64..bb0041734 100644 --- a/resource/menu_layouts.cpp +++ b/resource/menu_layouts.cpp @@ -57,7 +57,7 @@ menu_t auxconfig_menu_layout = { {"GRID ENCOD:", 0, 2, 2, 62, NULL_PAGE, 0, 122}, {"RAM LINK:", 0, 2, 2, 1, NULL_PAGE, 0, 0}, }, - 0 + 1 }; menu_t midiconfig_menu_layout = { @@ -150,7 +150,7 @@ menu_t mdconfig_menu_layout = { {"IMPORT", 0, 0, 0, 0, MD_IMPORT_PAGE, 0, 0}, {"NORMALIZE:", 0, 2, 2, 8, NULL_PAGE, 0, 16}, }, - 0 + 1 }; menu_t mdimport_menu_layout = { From 2a45ee0622e282a25c0ecb94c2c8ca60b0235d0b Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 18 Oct 2024 13:41:51 +1100 Subject: [PATCH 091/133] not required --- avr/cores/megacommand/MCL/ExtSeqTrack.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/ExtSeqTrack.cpp b/avr/cores/megacommand/MCL/ExtSeqTrack.cpp index f2d88127f..32ff7813c 100644 --- a/avr/cores/megacommand/MCL/ExtSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/ExtSeqTrack.cpp @@ -1220,6 +1220,5 @@ void ExtSeqTrack::toggle_mute() { mute_state = SEQ_MUTE_OFF; } else { mute_state_pending = true; - buffer_notesoff(); } } From f2f02f8f3a760fe640ec1d416e88c8f163900144 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 18 Oct 2024 13:42:33 +1100 Subject: [PATCH 092/133] System page, hack to keep knobs glyphs in memory for grid page --- avr/cores/megacommand/MCL/MenuPage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/avr/cores/megacommand/MCL/MenuPage.cpp b/avr/cores/megacommand/MCL/MenuPage.cpp index 9bb3542cb..61fcceec8 100644 --- a/avr/cores/megacommand/MCL/MenuPage.cpp +++ b/avr/cores/megacommand/MCL/MenuPage.cpp @@ -5,6 +5,7 @@ void MenuPageBase::init() { DEBUG_PRINTLN("MenuPageBase::init"); R.Clear(); R.use_machine_names_short(); // for grid page + R.use_icons_knob(); // for grid page R.use_menu_options(); R.use_menu_layouts(); DEBUG_PRINT("R.Size() = "); From a6dcb131da67c1d0180036f1149cd4fd102205e5 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 18 Oct 2024 14:18:52 +1100 Subject: [PATCH 093/133] Fixes related to scene_populate scene assignment. --- avr/cores/megacommand/MCL/MixerPage.cpp | 16 ++++++++-------- avr/cores/megacommand/MCL/PerfData.h | 21 +++++++++------------ avr/cores/megacommand/MCL/PerfEncoder.cpp | 9 +++++++-- avr/cores/megacommand/MCL/PerfEncoder.h | 1 + 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index ea6013eef..57c0a8104 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -634,22 +634,22 @@ bool MixerPage::handleEvent(gui_event_t *event) { } case MDX_KEY_NO: { if (BUTTON_DOWN(Buttons.ENCODER1)) { - perf_param1.perf_data.init_params_verbose(); + perf_param1.clear_scenes(); redraw_mask = -1; return true; } if (BUTTON_DOWN(Buttons.ENCODER2)) { - perf_param2.perf_data.init_params_verbose(); + perf_param2.clear_scenes(); redraw_mask = -1; return true; } if (BUTTON_DOWN(Buttons.ENCODER3)) { - perf_param3.perf_data.init_params_verbose(); + perf_param3.clear_scenes(); redraw_mask = -1; return true; } if (BUTTON_DOWN(Buttons.ENCODER4)) { - perf_param4.perf_data.init_params_verbose(); + perf_param4.clear_scenes(); redraw_mask = -1; return true; } @@ -668,22 +668,22 @@ bool MixerPage::handleEvent(gui_event_t *event) { } case MDX_KEY_YES: { if (BUTTON_DOWN(Buttons.ENCODER1)) { - perf_param1.perf_data.quick_scene_populate(); + perf_param1.quick_scene_populate(); redraw_mask = -1; return true; } if (BUTTON_DOWN(Buttons.ENCODER2)) { - perf_param2.perf_data.quick_scene_populate(); + perf_param2.quick_scene_populate(); redraw_mask = -1; return true; } if (BUTTON_DOWN(Buttons.ENCODER3)) { - perf_param3.perf_data.quick_scene_populate(); + perf_param3.quick_scene_populate(); redraw_mask = -1; return true; } if (BUTTON_DOWN(Buttons.ENCODER4)) { - perf_param4.perf_data.quick_scene_populate(); + perf_param4.quick_scene_populate(); redraw_mask = -1; return true; } diff --git a/avr/cores/megacommand/MCL/PerfData.h b/avr/cores/megacommand/MCL/PerfData.h index 2f503793f..0424f7cfd 100644 --- a/avr/cores/megacommand/MCL/PerfData.h +++ b/avr/cores/megacommand/MCL/PerfData.h @@ -197,8 +197,10 @@ class PerfData { } void clear_scene(uint8_t scene) { - PerfScene *s = &scenes[scene]; - s->init(); + if (scene < NUM_SCENES) { + PerfScene *s = &scenes[scene]; + s->init(); + } } void init_params() { @@ -207,12 +209,7 @@ class PerfData { } } - void init_params_verbose() { - oled_display.textbox("CLEAR SCENES", ""); - init_params(); - } - - void quick_scene_populate() { + void quick_scene_populate(uint8_t scene_a, uint8_t scene_b) { oled_display.textbox("FILL SCENES", ""); uint8_t scene = 0; uint8_t *params = (uint8_t *) &MD.kit.params; @@ -221,8 +218,8 @@ class PerfData { for (uint8_t track = 0; track < 16; track++) { for (uint8_t param = 0; param < 24; param++) { if (MD.kit.params[track][param] != MD.kit.params_orig[track][param]) { - scene = MD.kit.params[track][param] >= MD.kit.params_orig[track][param]; - if (add_param(track,param,scene,MD.kit.params[track][param]) != 255) { + scene = MD.kit.params[track][param] >= MD.kit.params_orig[track][param] ? scene_b : scene_a; + if (scene < NUM_SCENES && add_param(track,param,scene,MD.kit.params[track][param]) != 255) { //Kit encoders go back to normal, for save. uint8_t val = MD.kit.params[track][param]; MD.setTrackParam(track, param, MD.kit.params_orig[track][param], nullptr, @@ -243,8 +240,8 @@ class PerfData { uint8_t *fxs = (uint8_t *) &MD.kit.reverb; uint8_t *fxs_orig = (uint8_t *) &MD.kit.fx_orig; if (fxs[n] != fxs_orig[n]) { - scene = fxs[n] >= fxs_orig[n]; - if (add_param(fx + NUM_MD_TRACKS,param,scene,fxs[n]) != 255) { + scene = fxs[n] >= fxs_orig[n] ? scene_b : scene_a; + if (scene < NUM_SCENES && add_param(fx + NUM_MD_TRACKS,param,scene,fxs[n]) != 255) { uint8_t val = fxs[n]; MD.setFXParam(param, fxs_orig[n], fx + MD_FX_ECHO, true); MD.setFXParam(param, val, fx + MD_FX_ECHO, false); diff --git a/avr/cores/megacommand/MCL/PerfEncoder.cpp b/avr/cores/megacommand/MCL/PerfEncoder.cpp index 3deee9baf..8644effaf 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.cpp +++ b/avr/cores/megacommand/MCL/PerfEncoder.cpp @@ -61,9 +61,14 @@ int PerfEncoder::update(encoder_t *enc) { // Update all params return cur; } - void PerfEncoder::quick_scene_populate() { - perf_data.quick_scene_populate(); + perf_data.quick_scene_populate(active_scene_a,active_scene_b); cur = 127; old = 127; } + +void PerfEncoder::clear_scenes() { + oled_display.textbox("CLEAR SCENES", ""); + perf_data.clear_scene(active_scene_a); + perf_data.clear_scene(active_scene_b); +} diff --git a/avr/cores/megacommand/MCL/PerfEncoder.h b/avr/cores/megacommand/MCL/PerfEncoder.h index 8ff51db66..c91f6b7dd 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.h +++ b/avr/cores/megacommand/MCL/PerfEncoder.h @@ -29,6 +29,7 @@ class PerfEncoder : public MCLEncoder { void send_param(uint8_t dest, uint8_t param, uint8_t val); void send_params(uint8_t cur_, PerfScene *s1, PerfScene *s2); void quick_scene_populate(); + void clear_scenes(); /** Create a new range-limited encoder with max and min value, short name, initial value, and handling function. The initRangeEncoder From c79d5694146a770a5c926e9da9acb285f81166e5 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 18 Oct 2024 14:51:09 +1100 Subject: [PATCH 094/133] changelog --- Changelog | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/Changelog b/Changelog index 9fcdb936e..286a3ed60 100644 --- a/Changelog +++ b/Changelog @@ -2,25 +2,42 @@ MCL 4.60 21/09/2024 Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.60. -- Changes: +- Sequencer: + + The MD's in-built MIDI machines are now supported via the MCL sequencer. + MIDI data is transmitted on MegaCommand's MIDI Port 2. + +- Grid Page: + + It's now possible to reconfigure the Grid Page Encoders to act as the four + Performance Controllers. Via option: Config -> Page -> Grid Encod + + When selecting multiple rows for copy/clear/paste operations the corresponding Bank/Pattern id is now displayed on the left. - The MD's in-built MIDI machines are now supported via the MCL sequencer. - MIDI data is transmitted on MegaCommand's MIDI Port 2. +- Mixer Page: - It's now possible to reconfigure the MCL Encoders to act as the four - Performance Controllers when using the GridPage. Via option: Config -> Page -> Grid Encod + Mute Sets can now be loaded for a single device: + - Press [ Scale ] to toggle the Mixer Page's active device (MD or External MIDI) + - To load a Mute Set for the Mixer Page's active device, hold down an [ Arrow ] Key and press [ YES ] + - To load a Mute Set for both devices simultaneously (MD + External MIDI), hold down [ YES ] and then press an [ Arrow ]. - From the Mixer Page, mute sets can now be loaded for a single device. - - To load a Mute Set for active device, hold down an [ Arrow ] Key and press [ YES ] - - To load a Mute Set for both devices simultaneously (MD + External MIDI), hold down [ YES ] and then press an [ Arrow ]. + A chosen mute set can now be made to auto-load when the Perf Slot in Grid Y is loaded: + - From the Mixer Page, Hold an [ Arrow ] key to visually preview the mute set and then press [ FUNC ] to enable auto "LOAD". + - Then save the Perf Slot, in Grid Y. - When selecting multiple rows for copy/clear/paste operations the corresponding Bank/Pattern id is displayed on the left. + A Perf Controller's assigned left and right scenes can be auto-filled with modified Kit parameters by holding down the MCL < Encoder Button > + and pressing [ YES ]. + + A Perf Controller's assigned left and right scenes can be auto-cleared with by holding down the MCL and pressing [ NO ]. + +- Misc: The Port 1 MIDI driver can now be optionally changed to Generic. Performance optimizations and improvements. -Bug Fixes: +- Bug Fixes: + Fixed device selection in Chromatic Page Route and Perf track types would not load correctly during transitions From 17dee69ae6f4a4b7056ecfa87d1e1649d75b7125 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 18 Oct 2024 16:55:17 +1100 Subject: [PATCH 095/133] Render perf encoder perf locks within sequencer isr --- avr/cores/megacommand/MCL/MCLSeq.cpp | 2 +- avr/cores/megacommand/MCL/MixerPage.cpp | 21 ++++++++++++--------- avr/cores/megacommand/MCL/PerfEncoder.cpp | 19 +++++++++++-------- avr/cores/megacommand/MCL/PerfEncoder.h | 6 +++--- avr/cores/megacommand/MCL/PerfSeqTrack.cpp | 5 +++-- avr/cores/megacommand/MCL/PerfSeqTrack.h | 2 +- 6 files changed, 31 insertions(+), 24 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index 846501dde..131a9e492 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -253,7 +253,7 @@ void MCLSeq::seq() { for (uint8_t i = 0; i < NUM_AUX_TRACKS; i++) { aux_tracks[i].seq(); } - perf_track.seq(); + perf_track.seq(uart, uart2); #ifdef LFO_TRACKS for (uint8_t i = 0; i < num_lfo_tracks; i++) { lfo_tracks[i].seq(uart, uart2); diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 57c0a8104..8c4f2a656 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -105,8 +105,7 @@ void MixerPage::load_perf_locks(uint8_t state) { uint8_t val = perf_locks[state][n]; if (val < 128) { enc->cur = val; - enc->old = val; - enc->send(); + enc->resend = true; } } } @@ -297,12 +296,16 @@ void MixerPage::display() { if (draw_encoders || preview_mute_set != 255) { // oled_display.clearDisplay(); draw_encs(); + oled_display.setFont(&TomThumb); + if (preview_mute_set != 255) { + oled_display.setCursor(0, 31); + oled_display.print(preview_mute_set + 1); + } if (load_mute_set != 255 && load_mute_set == preview_mute_set) { - oled_display.setFont(&TomThumb); oled_display.setCursor(111, 31); oled_display.print("LOAD"); - oled_display.setFont(); } + oled_display.setFont(); oled_display.display(); } else { @@ -694,16 +697,16 @@ bool MixerPage::handleEvent(gui_event_t *event) { break; } if (trig_interface.is_key_down(MDX_KEY_LEFT)) { - switch_mute_set(1); + switch_mute_set(1,true,true); break; } else if (trig_interface.is_key_down(MDX_KEY_UP)) { - switch_mute_set(2); + switch_mute_set(2,true,true); break; } else if (trig_interface.is_key_down(MDX_KEY_RIGHT)) { - switch_mute_set(3); + switch_mute_set(3,true,true); break; } else if (trig_interface.is_key_down(MDX_KEY_DOWN)) { - switch_mute_set(0); + switch_mute_set(0,true,true); break; } else { if (!note_interface.notes_on) { @@ -726,7 +729,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { case MDX_KEY_DOWN: { uint8_t set = get_mute_set(key); if (trig_interface.is_key_down(MDX_KEY_YES)) { - switch_mute_set(set,false); + switch_mute_set(set,false,true); } else { preview_mute_set = set; for (uint8_t n = 0; n < 4; n++) { diff --git a/avr/cores/megacommand/MCL/PerfEncoder.cpp b/avr/cores/megacommand/MCL/PerfEncoder.cpp index 8644effaf..f02905288 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.cpp +++ b/avr/cores/megacommand/MCL/PerfEncoder.cpp @@ -7,20 +7,23 @@ PerfScene PerfData::scenes[NUM_SCENES]; -void PerfEncoder::send_param(uint8_t dest, uint8_t param, uint8_t val) { +void PerfEncoder::send_param(uint8_t dest, uint8_t param, uint8_t val, MidiUartParent *uart_,MidiUartParent *uart2_) { + if (uart_ == nullptr) { uart_ = &MidiUart; } + if (uart2_ == nullptr) { uart2_ = &MidiUart2; } + if (dest >= NUM_MD_TRACKS + 4) { uint8_t channel = dest - NUM_MD_TRACKS - 4; DEBUG_PRINTLN("send cc"); DEBUG_PRINT(channel); DEBUG_PRINT(" "); DEBUG_PRINT(param); DEBUG_PRINT(" "); DEBUG_PRINTLN(val); - MidiUart2.sendCC(channel, param, val); + uart2_->sendCC(channel, param, val); } else if (dest >= NUM_MD_TRACKS) { - MD.setFXParam(param, val, MD_FX_ECHO + dest - NUM_MD_TRACKS); + MD.setFXParam(param, val, MD_FX_ECHO + dest - NUM_MD_TRACKS, false, uart_); } else { - MD.setTrackParam(dest, param, val); + MD.setTrackParam(dest, param, val, uart_, false); } } -void PerfEncoder::send_params(uint8_t cur_, PerfScene *s1, PerfScene *s2) { +void PerfEncoder::send_params(uint8_t cur_, PerfScene *s1, PerfScene *s2, MidiUartParent *uart_,MidiUartParent *uart2_) { PerfMorph morph; morph.populate(s1, s2); @@ -46,13 +49,13 @@ void PerfEncoder::send_params(uint8_t cur_, PerfScene *s1, PerfScene *s2) { continue; } DEBUG_PRINTLN(val); - send_param(f->dest - 1, f->param, val); + send_param(f->dest - 1, f->param, val, uart_, uart2_); } } -void PerfEncoder::send() { +void PerfEncoder::send(MidiUartParent *uart_,MidiUartParent *uart2_) { PerfScene *s1 = active_scene_a == 255 ? nullptr : &perf_data.scenes[active_scene_a]; PerfScene *s2 = active_scene_b == 255 ? nullptr : &perf_data.scenes[active_scene_b]; - send_params(cur, s1, s2); + send_params(cur, s1, s2, uart_, uart2_); resend = false; } diff --git a/avr/cores/megacommand/MCL/PerfEncoder.h b/avr/cores/megacommand/MCL/PerfEncoder.h index c91f6b7dd..39d7fc6b7 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.h +++ b/avr/cores/megacommand/MCL/PerfEncoder.h @@ -25,9 +25,9 @@ class PerfEncoder : public MCLEncoder { bool resend = false; void init() { perf_data.init(); } - void send(); - void send_param(uint8_t dest, uint8_t param, uint8_t val); - void send_params(uint8_t cur_, PerfScene *s1, PerfScene *s2); + void send(MidiUartParent *uart_ = nullptr,MidiUartParent *uart2_ = nullptr); + void send_param(uint8_t dest, uint8_t param, uint8_t val, MidiUartParent *uart_ = nullptr, MidiUartParent *uart2_ = nullptr); + void send_params(uint8_t cur_, PerfScene *s1, PerfScene *s2, MidiUartParent *uart_ = nullptr,MidiUartParent *uart2_ = nullptr); void quick_scene_populate(); void clear_scenes(); /** diff --git a/avr/cores/megacommand/MCL/PerfSeqTrack.cpp b/avr/cores/megacommand/MCL/PerfSeqTrack.cpp index 95e96024a..013abc45e 100644 --- a/avr/cores/megacommand/MCL/PerfSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/PerfSeqTrack.cpp @@ -1,6 +1,6 @@ #include "MCL_impl.h" -void PerfSeqTrack::seq() { +void PerfSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { uint8_t timing_mid = get_timing_mid(); mod12_counter++; if (mod12_counter == timing_mid) { @@ -15,7 +15,8 @@ void PerfSeqTrack::seq() { if (perf_locks[n] != 255) { perf_page.perf_encoders[n]->cur = perf_locks[n]; perf_page.perf_encoders[n]->old = perf_locks[n]; - perf_page.perf_encoders[n]->resend = true; + perf_page.perf_encoders[n]->send(uart_,uart2_); + //perf_page.perf_encoders[n]->resend = true; } perf_locks[n] = 255; } diff --git a/avr/cores/megacommand/MCL/PerfSeqTrack.h b/avr/cores/megacommand/MCL/PerfSeqTrack.h index 2f7453ae4..d59dd4a75 100644 --- a/avr/cores/megacommand/MCL/PerfSeqTrack.h +++ b/avr/cores/megacommand/MCL/PerfSeqTrack.h @@ -23,6 +23,6 @@ class PerfSeqTrack : public SeqTrackBase { SeqTrackBase::reset(); } - void seq(); + void seq(MidiUartParent *uart_, MidiUartParent *uart2_); }; From 874096d5e430d97ea759536f7418dea9bfce46b5 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 20 Oct 2024 20:26:09 +1100 Subject: [PATCH 096/133] Changing encoding scheme, allow toggling of loading mutes from mute_set --- avr/cores/megacommand/MCL/MixerPage.cpp | 84 +++++++++++++++---------- avr/cores/megacommand/MCL/MixerPage.h | 5 +- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 8c4f2a656..a2860d490 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -19,6 +19,8 @@ void MixerPage::oled_draw_mutes() { uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; uint8_t fader_x = 0; + bool draw = true; + if (preview_mute_set != 255 && load_types[preview_mute_set] == 0) { draw = false; } for (uint8_t i = 0; i < len; ++i) { // draw routing SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[i] @@ -34,10 +36,12 @@ void MixerPage::oled_draw_mutes() { // } else if (mute_state) { // No Mute (SEQ_MUTE_OFF) oled_display.fillRect(fader_x, 2, 6, 6, BLACK); - if (mute_state) { - oled_display.drawRect(fader_x, 2, 6, 6, WHITE); - } else { - oled_display.drawLine(fader_x, 5, 5 + (i * 8), 5, WHITE); + if (draw) { + if (mute_state) { + oled_display.drawRect(fader_x, 2, 6, 6, WHITE); + } else { + oled_display.drawLine(fader_x, 5, 5 + (i * 8), 5, WHITE); + } } fader_x += 8; } @@ -285,7 +289,9 @@ void MixerPage::display() { oled_draw_mutes(); } else if (mute_set != 255 && mute_sets[!is_md_device].mutes[mute_set] != seq_step_page.mute_mask) { + uint16_t mask = mute_sets[!is_md_device].mutes[mute_set]; + if (load_types[mute_set] == 0) { mask = 0; } if (!is_md_device) { mask &= 0b111111; } @@ -426,7 +432,7 @@ void MixerPage::populate_mute_set() { } } -void MixerPage::switch_mute_set(uint8_t state, bool all_devices, bool load_perf) { +void MixerPage::switch_mute_set(uint8_t state, bool all_devices, bool load_perf, bool load_mutes) { MidiDevice *devs[2] = { midi_active_peering.get_device(UART1_PORT), @@ -435,33 +441,33 @@ void MixerPage::switch_mute_set(uint8_t state, bool all_devices, bool load_perf) uint8_t focus_device = (midi_device == &MD); + if (load_mutes) { + for (uint8_t dev = 0; dev < 2; dev++) { + bool is_md_device = dev == 0; - for (uint8_t dev = 0; dev < 2; dev++) { + if (!all_devices && focus_device != dev) continue; - bool is_md_device = dev == 0; - - if (!all_devices && focus_device != dev) continue; - - uint8_t len = + uint8_t len = (is_md_device) ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; - for (uint8_t n = 0; n < len; n++) { - SeqTrack *seq_track = (is_md_device) ? (SeqTrack *)&mcl_seq.md_tracks[n] + for (uint8_t n = 0; n < len; n++) { + SeqTrack *seq_track = (is_md_device) ? (SeqTrack *)&mcl_seq.md_tracks[n] : (SeqTrack *)&mcl_seq.ext_tracks[n]; - uint8_t mute_set = state; - bool mute_state = IS_BIT_CLEAR16(mute_sets[dev].mutes[state], n); - // Flip - if (state == 4 && devs[dev] == midi_device) { - mute_state = !seq_track->mute_state; - } - // Switch - if (mute_state != seq_track->mute_state) { - devs[dev]->muteTrack(n, mute_state); - if (is_md_device) { - mcl_seq.md_tracks[n].toggle_mute(); - } else { - mcl_seq.ext_tracks[n].toggle_mute(); + uint8_t mute_set = state; + bool mute_state = IS_BIT_CLEAR16(mute_sets[dev].mutes[state], n); + // Flip + if (state == 4 && devs[dev] == midi_device) { + mute_state = !seq_track->mute_state; + } + // Switch + if (mute_state != seq_track->mute_state) { + devs[dev]->muteTrack(n, mute_state); + if (is_md_device) { + mcl_seq.md_tracks[n].toggle_mute(); + } else { + mcl_seq.ext_tracks[n].toggle_mute(); + } } } } @@ -547,7 +553,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; if (event->mask == EVENT_BUTTON_PRESSED && track < len) { if (note_interface.is_note(track)) { - if (show_mixer_menu || preview_mute_set != 255 || ext_key_down) { + if (show_mixer_menu || preview_mute_set != 255 && load_types[preview_mute_set] || ext_key_down) { if (ext_key_down) { mute_toggle = 1; } SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[track] @@ -667,6 +673,14 @@ bool MixerPage::handleEvent(gui_event_t *event) { } toggle_or_solo(true); } + else { + if (preview_mute_set != 255) { + load_types[preview_mute_set] = !load_types[preview_mute_set]; + if (load_types[preview_mute_set] == 0) { seq_step_page.mute_mask = 0; } + redraw_mutes = true; + break; + } + } break; } case MDX_KEY_YES: { @@ -697,16 +711,16 @@ bool MixerPage::handleEvent(gui_event_t *event) { break; } if (trig_interface.is_key_down(MDX_KEY_LEFT)) { - switch_mute_set(1,true,true); + switch_mute_set(1,true,true,load_types[1]); break; } else if (trig_interface.is_key_down(MDX_KEY_UP)) { - switch_mute_set(2,true,true); + switch_mute_set(2,true,true,load_types[2]); break; } else if (trig_interface.is_key_down(MDX_KEY_RIGHT)) { - switch_mute_set(3,true,true); + switch_mute_set(3,true,true,load_types[3]); break; } else if (trig_interface.is_key_down(MDX_KEY_DOWN)) { - switch_mute_set(0,true,true); + switch_mute_set(0,true,true,load_types[0]); break; } else { if (!note_interface.notes_on) { @@ -719,8 +733,10 @@ bool MixerPage::handleEvent(gui_event_t *event) { break; } case MDX_KEY_FUNC: { - if (load_mute_set == preview_mute_set) { load_mute_set = 255; } - else { load_mute_set = preview_mute_set; } + if (preview_mute_set != 255) { + if (load_mute_set == preview_mute_set) { load_mute_set = 255; } + else { load_mute_set = preview_mute_set; } + } break; } case MDX_KEY_LEFT: @@ -729,7 +745,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { case MDX_KEY_DOWN: { uint8_t set = get_mute_set(key); if (trig_interface.is_key_down(MDX_KEY_YES)) { - switch_mute_set(set,false,true); + switch_mute_set(set,false,true,load_types[set]); } else { preview_mute_set = set; for (uint8_t n = 0; n < 4; n++) { diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index 652a6e494..6f97831b0 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -51,11 +51,13 @@ class MixerPage : public LightPage { uint8_t current_mute_set = 255; uint8_t preview_mute_set = 255; uint8_t load_mute_set = 255; + void send_fx(uint8_t param, Encoder *enc, uint8_t type); // Don't change order MuteSet mute_sets[2]; uint8_t perf_locks[4][4]; + bool load_types[4]; // uint8_t perf_locks_temp[4]; @@ -68,6 +70,7 @@ class MixerPage : public LightPage { midi_device = &MD; memset(mute_sets, 0xFF, sizeof(mute_sets)); memset(perf_locks, 0xFF, sizeof(perf_locks)); + memset(load_types, 1, sizeof(load_types)); } void adjust_param(EncoderParent *enc, uint8_t param); void draw_levels(); @@ -79,7 +82,7 @@ class MixerPage : public LightPage { void record_mutes_set(bool state); void disable_record_mutes(bool clear = false); void oled_draw_mutes(); - void switch_mute_set(uint8_t state, bool all_devices = true, bool load_perf = false); + void switch_mute_set(uint8_t state, bool all_devices = true, bool load_perf = false, bool load_mutes = true); void populate_mute_set(); void load_perf_locks(uint8_t state); From 1e92191164626abf7485eeed7c20b80b02c59bec Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 20 Oct 2024 23:20:18 +1100 Subject: [PATCH 097/133] Refine new functionality related to mute sets --- avr/cores/megacommand/MCL/MCL.cpp | 3 +- avr/cores/megacommand/MCL/MCL.h | 2 +- avr/cores/megacommand/MCL/MixerPage.cpp | 60 +++++++++++------------ avr/cores/megacommand/MCL/PerfData.h | 11 ++--- avr/cores/megacommand/MCL/PerfEncoder.cpp | 4 +- avr/cores/megacommand/MCL/PerfEncoder.h | 2 +- avr/cores/megacommand/MCL/PerfTrack.cpp | 31 +++++++----- 7 files changed, 58 insertions(+), 55 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCL.cpp b/avr/cores/megacommand/MCL/MCL.cpp index 1c2450c64..bd0ec5bc6 100644 --- a/avr/cores/megacommand/MCL/MCL.cpp +++ b/avr/cores/megacommand/MCL/MCL.cpp @@ -278,7 +278,8 @@ bool mcl_handleEvent(gui_event_t *event) { case MDX_KEY_BANKD: { if (mcl.currentPage() == GRID_LOAD_PAGE || mcl.currentPage() == GRID_SAVE_PAGE || - (mcl.currentPage() == GRID_PAGE && grid_page.show_slot_menu)) { + (mcl.currentPage() == GRID_PAGE && grid_page.show_slot_menu)) { // || +// (mcl.currentPage() == MIXER_PAGE && mixer_page.preview_mute_set != 255)) { return false; } if (trig_interface.is_key_down(MDX_KEY_FUNC)) { diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index a7db37f62..276c2b141 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -17,7 +17,7 @@ #include "Fonts/TomThumb.h" #define VERSION 4060 -#define VERSION_STR "D4.60" +#define VERSION_STR "G4.60" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index a2860d490..48575c721 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -303,10 +303,6 @@ void MixerPage::display() { // oled_display.clearDisplay(); draw_encs(); oled_display.setFont(&TomThumb); - if (preview_mute_set != 255) { - oled_display.setCursor(0, 31); - oled_display.print(preview_mute_set + 1); - } if (load_mute_set != 255 && load_mute_set == preview_mute_set) { oled_display.setCursor(111, 31); oled_display.print("LOAD"); @@ -645,24 +641,23 @@ bool MixerPage::handleEvent(gui_event_t *event) { if (BUTTON_DOWN(Buttons.ENCODER1)) { perf_param1.clear_scenes(); redraw_mask = -1; - return true; + break; } if (BUTTON_DOWN(Buttons.ENCODER2)) { perf_param2.clear_scenes(); redraw_mask = -1; - return true; + break; } if (BUTTON_DOWN(Buttons.ENCODER3)) { perf_param3.clear_scenes(); redraw_mask = -1; - return true; + break; } if (BUTTON_DOWN(Buttons.ENCODER4)) { perf_param4.clear_scenes(); redraw_mask = -1; - return true; + break; } - uint64_t mask = ((uint64_t)1 << MDX_KEY_LEFT) | ((uint64_t)1 << MDX_KEY_UP) | ((uint64_t)1 << MDX_KEY_RIGHT) | ((uint64_t)1 << MDX_KEY_DOWN); @@ -673,37 +668,47 @@ bool MixerPage::handleEvent(gui_event_t *event) { } toggle_or_solo(true); } - else { - if (preview_mute_set != 255) { - load_types[preview_mute_set] = !load_types[preview_mute_set]; - if (load_types[preview_mute_set] == 0) { seq_step_page.mute_mask = 0; } - redraw_mutes = true; - break; - } + break; + } + case MDX_KEY_BANKA: { + if (preview_mute_set != 255) { + load_types[preview_mute_set] = !load_types[preview_mute_set]; + if (load_types[preview_mute_set] == 0) { seq_step_page.mute_mask = 0; } + redraw_mutes = true; + return true; + } + break; + } + case MDX_KEY_BANKB: { + if (preview_mute_set != 255) { + if (load_mute_set == preview_mute_set) { load_mute_set = 255; } + else { load_mute_set = preview_mute_set; } + return true; } break; } case MDX_KEY_YES: { if (BUTTON_DOWN(Buttons.ENCODER1)) { - perf_param1.quick_scene_populate(); + perf_param1.scene_autofill(); redraw_mask = -1; - return true; + break; } if (BUTTON_DOWN(Buttons.ENCODER2)) { - perf_param2.quick_scene_populate(); + perf_param2.scene_autofill(); redraw_mask = -1; - return true; + break; } if (BUTTON_DOWN(Buttons.ENCODER3)) { - perf_param3.quick_scene_populate(); + perf_param3.scene_autofill(); redraw_mask = -1; - return true; + break; } if (BUTTON_DOWN(Buttons.ENCODER4)) { - perf_param4.quick_scene_populate(); + perf_param4.scene_autofill(); redraw_mask = -1; - return true; + break; } + if (preview_mute_set == 255 && trig_interface.is_key_down(MDX_KEY_FUNC) && note_interface.notes_on == 0) { @@ -732,13 +737,6 @@ bool MixerPage::handleEvent(gui_event_t *event) { } break; } - case MDX_KEY_FUNC: { - if (preview_mute_set != 255) { - if (load_mute_set == preview_mute_set) { load_mute_set = 255; } - else { load_mute_set = preview_mute_set; } - } - break; - } case MDX_KEY_LEFT: case MDX_KEY_UP: case MDX_KEY_RIGHT: diff --git a/avr/cores/megacommand/MCL/PerfData.h b/avr/cores/megacommand/MCL/PerfData.h index 0424f7cfd..fbabf043b 100644 --- a/avr/cores/megacommand/MCL/PerfData.h +++ b/avr/cores/megacommand/MCL/PerfData.h @@ -209,17 +209,17 @@ class PerfData { } } - void quick_scene_populate(uint8_t scene_a, uint8_t scene_b) { + void scene_autofill(uint8_t scene) { oled_display.textbox("FILL SCENES", ""); - uint8_t scene = 0; + if (scene >= NUM_SCENES) { return; } + uint8_t *params = (uint8_t *) &MD.kit.params; uint8_t *params_orig = (uint8_t *) &MD.kit.params_orig; for (uint8_t track = 0; track < 16; track++) { for (uint8_t param = 0; param < 24; param++) { if (MD.kit.params[track][param] != MD.kit.params_orig[track][param]) { - scene = MD.kit.params[track][param] >= MD.kit.params_orig[track][param] ? scene_b : scene_a; - if (scene < NUM_SCENES && add_param(track,param,scene,MD.kit.params[track][param]) != 255) { + if (add_param(track,param,scene,MD.kit.params[track][param]) != 255) { //Kit encoders go back to normal, for save. uint8_t val = MD.kit.params[track][param]; MD.setTrackParam(track, param, MD.kit.params_orig[track][param], nullptr, @@ -240,8 +240,7 @@ class PerfData { uint8_t *fxs = (uint8_t *) &MD.kit.reverb; uint8_t *fxs_orig = (uint8_t *) &MD.kit.fx_orig; if (fxs[n] != fxs_orig[n]) { - scene = fxs[n] >= fxs_orig[n] ? scene_b : scene_a; - if (scene < NUM_SCENES && add_param(fx + NUM_MD_TRACKS,param,scene,fxs[n]) != 255) { + if (add_param(fx + NUM_MD_TRACKS,param,scene,fxs[n]) != 255) { uint8_t val = fxs[n]; MD.setFXParam(param, fxs_orig[n], fx + MD_FX_ECHO, true); MD.setFXParam(param, val, fx + MD_FX_ECHO, false); diff --git a/avr/cores/megacommand/MCL/PerfEncoder.cpp b/avr/cores/megacommand/MCL/PerfEncoder.cpp index f02905288..bb7818f7d 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.cpp +++ b/avr/cores/megacommand/MCL/PerfEncoder.cpp @@ -64,8 +64,8 @@ int PerfEncoder::update(encoder_t *enc) { // Update all params return cur; } -void PerfEncoder::quick_scene_populate() { - perf_data.quick_scene_populate(active_scene_a,active_scene_b); +void PerfEncoder::scene_autofill() { + perf_data.scene_autofill(active_scene_b); cur = 127; old = 127; } diff --git a/avr/cores/megacommand/MCL/PerfEncoder.h b/avr/cores/megacommand/MCL/PerfEncoder.h index 39d7fc6b7..402cd2721 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.h +++ b/avr/cores/megacommand/MCL/PerfEncoder.h @@ -28,7 +28,7 @@ class PerfEncoder : public MCLEncoder { void send(MidiUartParent *uart_ = nullptr,MidiUartParent *uart2_ = nullptr); void send_param(uint8_t dest, uint8_t param, uint8_t val, MidiUartParent *uart_ = nullptr, MidiUartParent *uart2_ = nullptr); void send_params(uint8_t cur_, PerfScene *s1, PerfScene *s2, MidiUartParent *uart_ = nullptr,MidiUartParent *uart2_ = nullptr); - void quick_scene_populate(); + void scene_autofill(); void clear_scenes(); /** Create a new range-limited encoder with max and min value, short diff --git a/avr/cores/megacommand/MCL/PerfTrack.cpp b/avr/cores/megacommand/MCL/PerfTrack.cpp index d0a1049d3..9570b55da 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.cpp +++ b/avr/cores/megacommand/MCL/PerfTrack.cpp @@ -18,7 +18,8 @@ uint16_t PerfTrack::calc_latency(uint8_t tracknumber) { } void PerfTrack::get_perf() { - + memcpy(scenes, PerfData::scenes, sizeof(PerfScene) * NUM_SCENES); + memcpy(mute_sets,mixer_page.mute_sets, sizeof(mute_sets) + sizeof(perf_locks)); for (uint8_t n = 0; n < 4; n++) { PerfEncoder *e = perf_page.perf_encoders[n]; PerfData *d = &e->perf_data; @@ -29,14 +30,16 @@ void PerfTrack::get_perf() { encs[n].active_scene_b = e->active_scene_b; encs[n].cur = e->cur; memcpy(encs[n].name,e->name, PERF_NAME_LENGTH); + + if (!mixer_page.load_types[n]) { + CLEAR_BIT16(mute_sets[1].mutes[n],14); + } } DEBUG_PRINTLN("get perf"); DEBUG_PRINTLN(sizeof(scenes)); - memcpy(scenes, PerfData::scenes, sizeof(PerfScene) * NUM_SCENES); - memcpy(mute_sets,mixer_page.mute_sets, sizeof(mute_sets) + sizeof(perf_locks)); - //Encode the load_mute_set value into the high bit of the corresponding ext mutes. + //Encode the load_mute_set value into the high bit of the corresponding ext mutes. if (mixer_page.load_mute_set < 4) { - mute_sets[1].mutes[mixer_page.load_mute_set] &= 0b01111111; + mute_sets[1].mutes[mixer_page.load_mute_set] &= 0b0111111111111111; } } @@ -44,6 +47,8 @@ void PerfTrack::get_perf() { void PerfTrack::load_perf(bool immediate, SeqTrack *seq_track) { DEBUG_PRINTLN("load perf"); DEBUG_PRINTLN( sizeof(scenes)); + mixer_page.load_mute_set = 255; + for (uint8_t n = 0; n < 4; n++) { PerfEncoder *e = perf_page.perf_encoders[n]; PerfData *d = &e->perf_data; @@ -55,19 +60,19 @@ void PerfTrack::load_perf(bool immediate, SeqTrack *seq_track) { e->cur = encs[n].cur; e->old = encs[n].cur; memcpy(e->name,encs[n].name, PERF_NAME_LENGTH); + + if ((mute_sets[1].mutes[n] & 0b1000000000000000) == 0) { + mixer_page.load_mute_set = n; + } + mixer_page.load_types[n] = mute_sets[1].mutes[n] & 0b0100000000000000; + mute_sets[1].mutes[n] |= 0b1100000000000000; + } memcpy(PerfData::scenes, scenes, sizeof(PerfScene) * NUM_SCENES); - mixer_page.load_mute_set = 255; - for (uint8_t n = 0; n < 4; n++) { - if ((mute_sets[1].mutes[n] & 0b10000000) == 0) { - mixer_page.load_mute_set = n; - mute_sets[1].mutes[n] |= 0b11000000; - } - } memcpy(mixer_page.mute_sets, mute_sets, sizeof(mute_sets) + sizeof(perf_locks)); if (mixer_page.load_mute_set < 4) { - mixer_page.switch_mute_set(mixer_page.load_mute_set, true, immediate); //Mute change is applied outside of sequencer runtime. + mixer_page.switch_mute_set(mixer_page.load_mute_set, true, immediate, mixer_page.load_types[mixer_page.load_mute_set]); //Mute change is applied outside of sequencer runtime. if (!immediate) { PerfSeqTrack *p = (PerfSeqTrack*) seq_track; memcpy(p->perf_locks, &perf_locks[mixer_page.load_mute_set],4); //Perf change is pre-empted at sequencer runtime. From 3844bcd9cb0e35cd41d83f561d2415657c6958eb Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 21 Oct 2024 12:07:40 +1100 Subject: [PATCH 098/133] Change button binding for scene autofill/clear --- avr/cores/megacommand/MCL/MixerPage.cpp | 101 ++++++++++-------------- 1 file changed, 43 insertions(+), 58 deletions(-) diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 48575c721..1ff1dda4d 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -638,26 +638,6 @@ bool MixerPage::handleEvent(gui_event_t *event) { break; } case MDX_KEY_NO: { - if (BUTTON_DOWN(Buttons.ENCODER1)) { - perf_param1.clear_scenes(); - redraw_mask = -1; - break; - } - if (BUTTON_DOWN(Buttons.ENCODER2)) { - perf_param2.clear_scenes(); - redraw_mask = -1; - break; - } - if (BUTTON_DOWN(Buttons.ENCODER3)) { - perf_param3.clear_scenes(); - redraw_mask = -1; - break; - } - if (BUTTON_DOWN(Buttons.ENCODER4)) { - perf_param4.clear_scenes(); - redraw_mask = -1; - break; - } uint64_t mask = ((uint64_t)1 << MDX_KEY_LEFT) | ((uint64_t)1 << MDX_KEY_UP) | ((uint64_t)1 << MDX_KEY_RIGHT) | ((uint64_t)1 << MDX_KEY_DOWN); @@ -688,27 +668,6 @@ bool MixerPage::handleEvent(gui_event_t *event) { break; } case MDX_KEY_YES: { - if (BUTTON_DOWN(Buttons.ENCODER1)) { - perf_param1.scene_autofill(); - redraw_mask = -1; - break; - } - if (BUTTON_DOWN(Buttons.ENCODER2)) { - perf_param2.scene_autofill(); - redraw_mask = -1; - break; - } - if (BUTTON_DOWN(Buttons.ENCODER3)) { - perf_param3.scene_autofill(); - redraw_mask = -1; - break; - } - if (BUTTON_DOWN(Buttons.ENCODER4)) { - perf_param4.scene_autofill(); - redraw_mask = -1; - break; - } - if (preview_mute_set == 255 && trig_interface.is_key_down(MDX_KEY_FUNC) && note_interface.notes_on == 0) { @@ -775,7 +734,12 @@ bool MixerPage::handleEvent(gui_event_t *event) { switch (key) { case MDX_KEY_GLOBAL: case MDX_KEY_YES: { - goto global_release; + preview_mute_set = 255; + show_mixer_menu = false; + disable_record_mutes(); + MD.set_trigleds(0, is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); + redraw(); + return true; } case MDX_KEY_EXTENDED: { @@ -816,26 +780,47 @@ bool MixerPage::handleEvent(gui_event_t *event) { } } } - if (EVENT_PRESSED(event, Buttons.BUTTON3) && !BUTTON_DOWN(Buttons.BUTTON4)) { - // show_mixer_menu = true; - if (note_interface.notes_on) { - setLed2(); - record_mutes_set(true); - } - return true; + if (BUTTON_DOWN(Buttons.BUTTON3)) { + if (BUTTON_DOWN(Buttons.ENCODER1)) { + perf_param1.clear_scenes(); + redraw_mask = -1; + } + if (BUTTON_DOWN(Buttons.ENCODER2)) { + perf_param2.clear_scenes(); + redraw_mask = -1; + } + if (BUTTON_DOWN(Buttons.ENCODER3)) { + perf_param3.clear_scenes(); + redraw_mask = -1; + } + if (BUTTON_DOWN(Buttons.ENCODER4)) { + perf_param4.clear_scenes(); + redraw_mask = -1; + } + return true; } - if (EVENT_RELEASED(event, Buttons.BUTTON3)) { - - global_release: - preview_mute_set = 255; - show_mixer_menu = false; - disable_record_mutes(); - MD.set_trigleds(0, is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); - redraw(); - return true; + if (BUTTON_DOWN(Buttons.BUTTON4)) { + if (BUTTON_DOWN(Buttons.ENCODER1)) { + perf_param1.scene_autofill(); + redraw_mask = -1; + } + if (BUTTON_DOWN(Buttons.ENCODER2)) { + perf_param2.scene_autofill(); + redraw_mask = -1; + } + if (BUTTON_DOWN(Buttons.ENCODER3)) { + perf_param3.scene_autofill(); + redraw_mask = -1; + } + if (BUTTON_DOWN(Buttons.ENCODER4)) { + perf_param4.scene_autofill(); + redraw_mask = -1; + } + return true; } + if (EVENT_PRESSED(event, Buttons.BUTTON2)) { mcl.setPage(PAGE_SELECT_PAGE); return true; From 32edce6e4cd950f8530c664eb8bcf19716a34eba Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 21 Oct 2024 22:32:27 +1100 Subject: [PATCH 099/133] small optimise for non midi tracks --- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 08df4d2e4..b9d243bd5 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -484,17 +484,20 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, uint8_t ccs[midi_cc_array_size]; bool send_ccs = false; - if (notes.first_trig) { - // first note, we want to send all CCs regardless if they dont have locks. - memcpy(ccs + 1, &MD.kit.params[track_number][5], sizeof(ccs) - 1); - //prevent re-transmission of program change. - //process_note_locks(20, MD.kit.params[track_number][20],ccs); - send_ccs = true; - notes.first_trig = false; - } else { - memset(ccs, 255, sizeof(ccs)); - } bool is_midi_model = (MD.kit.models[track_number] & 0xF0) == MID_01_MODEL; + + if (is_midi_model) { + if (notes.first_trig) { + // first note, we want to send all CCs regardless if they dont have locks. + memcpy(ccs + 1, &MD.kit.params[track_number][5], sizeof(ccs) - 1); + //prevent re-transmission of program change. + //process_note_locks(20, MD.kit.params[track_number][20],ccs); + send_ccs = true; + notes.first_trig = false; + } else { + memset(ccs, 255, sizeof(ccs)); + } + } for (uint8_t c = 0; c < NUM_LOCKS; c++) { bool lock_bit = steps[step].is_lock_bit(c); bool lock_present = steps[step].is_lock(c); From 7c4d1f996cdd49f2a8c792a0d64e800f353e89cd Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 21 Oct 2024 22:41:41 +1100 Subject: [PATCH 100/133] Changelog --- Changelog | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/Changelog b/Changelog index 286a3ed60..90b0f6845 100644 --- a/Changelog +++ b/Changelog @@ -16,19 +16,29 @@ Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.6 - Mixer Page: - Mute Sets can now be loaded for a single device: + Performance States (formely Mute Sets): + + As previously, there are 4 Performance State, each mapped to an individual [Arrow Key]. + Each Performance State contains Mutes for each device, and 4 Performance Controller Locks + + Performance States Manual Load (for a single device): - Press [ Scale ] to toggle the Mixer Page's active device (MD or External MIDI) - - To load a Mute Set for the Mixer Page's active device, hold down an [ Arrow ] Key and press [ YES ] - - To load a Mute Set for both devices simultaneously (MD + External MIDI), hold down [ YES ] and then press an [ Arrow ]. + - To load a Performance State for the Mixer Page's active device, hold down an [ Arrow ] Key and press [ YES ] + - To load a Performance State for both devices simultaneously (MD + External MIDI), hold down [ YES ] and then press an [ Arrow ]. + + Performance State Autoload: + A chosen Performance State can now be made to auto-load when the Perf Slot in Grid Y is loaded: + - From the Mixer Page, Hold an [ Arrow ] key to visually preview the Performance State and then press [ Swing / BANKB ] to enable auto "LOAD". + - Then save the Perf Slot, in Grid Y. + + The Mutes, in a Performance State can be permanantly disabled for the active device by holding an [ Arrow ] key and pressing [ Mute / BankA ] - A chosen mute set can now be made to auto-load when the Perf Slot in Grid Y is loaded: - - From the Mixer Page, Hold an [ Arrow ] key to visually preview the mute set and then press [ FUNC ] to enable auto "LOAD". - - Then save the Perf Slot, in Grid Y. + Performance Controller AutoFill: - A Perf Controller's assigned left and right scenes can be auto-filled with modified Kit parameters by holding down the MCL < Encoder Button > - and pressing [ YES ]. + - A Perf Controller's assigned right scenes can be auto-filled with modified Kit parameters by holding down the MCL < Encoder Button > + and pressing the MC's < Yes / Load > button. - A Perf Controller's assigned left and right scenes can be auto-cleared with by holding down the MCL and pressing [ NO ]. + - A Perf Controller's assigned right scenes can be auto-cleared with by holding down the MCL and pressing the MC's < Shift > button. - Misc: From 7845ca6d7a7820ac97171180aa91f8e5e3f53d12 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 21 Oct 2024 22:42:46 +1100 Subject: [PATCH 101/133] Performance States. Mutes enable/disable per device. --- avr/cores/megacommand/MCL/MixerPage.cpp | 20 ++++++++++---------- avr/cores/megacommand/MCL/MixerPage.h | 2 +- avr/cores/megacommand/MCL/PerfTrack.cpp | 11 ++++++++--- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 1ff1dda4d..7aaf80721 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -20,7 +20,7 @@ void MixerPage::oled_draw_mutes() { uint8_t fader_x = 0; bool draw = true; - if (preview_mute_set != 255 && load_types[preview_mute_set] == 0) { draw = false; } + if (preview_mute_set != 255 && load_types[!is_md_device][preview_mute_set] == 0) { draw = false; } for (uint8_t i = 0; i < len; ++i) { // draw routing SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[i] @@ -291,7 +291,7 @@ void MixerPage::display() { seq_step_page.mute_mask) { uint16_t mask = mute_sets[!is_md_device].mutes[mute_set]; - if (load_types[mute_set] == 0) { mask = 0; } + if (load_types[!is_md_device][mute_set] == 0) { mask = 0; } if (!is_md_device) { mask &= 0b111111; } @@ -549,7 +549,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; if (event->mask == EVENT_BUTTON_PRESSED && track < len) { if (note_interface.is_note(track)) { - if (show_mixer_menu || preview_mute_set != 255 && load_types[preview_mute_set] || ext_key_down) { + if (show_mixer_menu || preview_mute_set != 255 && load_types[!is_md_device][preview_mute_set] || ext_key_down) { if (ext_key_down) { mute_toggle = 1; } SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[track] @@ -652,8 +652,8 @@ bool MixerPage::handleEvent(gui_event_t *event) { } case MDX_KEY_BANKA: { if (preview_mute_set != 255) { - load_types[preview_mute_set] = !load_types[preview_mute_set]; - if (load_types[preview_mute_set] == 0) { seq_step_page.mute_mask = 0; } + load_types[!is_md_device][preview_mute_set] = !load_types[!is_md_device][preview_mute_set]; + if (load_types[!is_md_device][preview_mute_set] == 0) { seq_step_page.mute_mask = 0; } redraw_mutes = true; return true; } @@ -675,16 +675,16 @@ bool MixerPage::handleEvent(gui_event_t *event) { break; } if (trig_interface.is_key_down(MDX_KEY_LEFT)) { - switch_mute_set(1,true,true,load_types[1]); + switch_mute_set(1,true,true,load_types[!is_md_device][1]); break; } else if (trig_interface.is_key_down(MDX_KEY_UP)) { - switch_mute_set(2,true,true,load_types[2]); + switch_mute_set(2,true,true,load_types[!is_md_device][2]); break; } else if (trig_interface.is_key_down(MDX_KEY_RIGHT)) { - switch_mute_set(3,true,true,load_types[3]); + switch_mute_set(3,true,true,load_types[!is_md_device][3]); break; } else if (trig_interface.is_key_down(MDX_KEY_DOWN)) { - switch_mute_set(0,true,true,load_types[0]); + switch_mute_set(0,true,true,load_types[!is_md_device][0]); break; } else { if (!note_interface.notes_on) { @@ -702,7 +702,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { case MDX_KEY_DOWN: { uint8_t set = get_mute_set(key); if (trig_interface.is_key_down(MDX_KEY_YES)) { - switch_mute_set(set,false,true,load_types[set]); + switch_mute_set(set,false,true,load_types[!is_md_device][set]); } else { preview_mute_set = set; for (uint8_t n = 0; n < 4; n++) { diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index 6f97831b0..55b1c6e6a 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -57,7 +57,7 @@ class MixerPage : public LightPage { // Don't change order MuteSet mute_sets[2]; uint8_t perf_locks[4][4]; - bool load_types[4]; + bool load_types[2][4]; // uint8_t perf_locks_temp[4]; diff --git a/avr/cores/megacommand/MCL/PerfTrack.cpp b/avr/cores/megacommand/MCL/PerfTrack.cpp index 9570b55da..decb0e62b 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.cpp +++ b/avr/cores/megacommand/MCL/PerfTrack.cpp @@ -31,9 +31,13 @@ void PerfTrack::get_perf() { encs[n].cur = e->cur; memcpy(encs[n].name,e->name, PERF_NAME_LENGTH); - if (!mixer_page.load_types[n]) { + if (!mixer_page.load_types[0][n]) { + CLEAR_BIT16(mute_sets[1].mutes[n],13); + } + if (!mixer_page.load_types[1][n]) { CLEAR_BIT16(mute_sets[1].mutes[n],14); } + } DEBUG_PRINTLN("get perf"); DEBUG_PRINTLN(sizeof(scenes)); @@ -64,8 +68,9 @@ void PerfTrack::load_perf(bool immediate, SeqTrack *seq_track) { if ((mute_sets[1].mutes[n] & 0b1000000000000000) == 0) { mixer_page.load_mute_set = n; } - mixer_page.load_types[n] = mute_sets[1].mutes[n] & 0b0100000000000000; - mute_sets[1].mutes[n] |= 0b1100000000000000; + mixer_page.load_types[0][n] = mute_sets[1].mutes[n] & 0b0010000000000000; + mixer_page.load_types[1][n] = mute_sets[1].mutes[n] & 0b0100000000000000; + mute_sets[1].mutes[n] |= 0b1110000000000000; } memcpy(PerfData::scenes, scenes, sizeof(PerfScene) * NUM_SCENES); From 18ee0d850cefd5dd7632b0f6ba04bdda7db85089 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 22 Oct 2024 10:12:25 +1100 Subject: [PATCH 102/133] not required --- avr/cores/megacommand/MCL/GridPage.cpp | 11 ----------- avr/cores/megacommand/MCL/GridPage.h | 1 - avr/cores/megacommand/MCL/SoundBrowserPage.cpp | 2 -- 3 files changed, 14 deletions(-) diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index 6cecf882a..31fb6f90c 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -628,17 +628,6 @@ void GridPage::display() { oled_display.display(); } -void GridPage::prepare() { - if (MD.connected) { - MD.getCurrentTrack(CALLBACK_TIMEOUT); - MD.currentKit = MD.getCurrentKit(CALLBACK_TIMEOUT); - MD.getBlockingKit(0x7F); - if (MidiClock.state == 2) { - mcl_seq.update_kit_params(); - } - } -} - void rename_row() { const char *my_title = "Row Name:"; uint8_t old_grid = proj.get_grid(); diff --git a/avr/cores/megacommand/MCL/GridPage.h b/avr/cores/megacommand/MCL/GridPage.h index 44a1681b7..f89a279cb 100644 --- a/avr/cores/megacommand/MCL/GridPage.h +++ b/avr/cores/megacommand/MCL/GridPage.h @@ -91,7 +91,6 @@ class GridPage : public LightPage { void setup(); void cleanup(); void init(); - void prepare(); bool swap_grids(); void apply_slot_changes(bool ignore_undo = false, bool ignore_func = false); diff --git a/avr/cores/megacommand/MCL/SoundBrowserPage.cpp b/avr/cores/megacommand/MCL/SoundBrowserPage.cpp index e568ad65f..9cd1bea14 100644 --- a/avr/cores/megacommand/MCL/SoundBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/SoundBrowserPage.cpp @@ -38,7 +38,6 @@ void SoundBrowserPage::init() { void SoundBrowserPage::save_sound() { MDSound sound; - grid_page.prepare(); char sound_name[8]; uint8_t l = min(strlen(MD.kit.name),4); memcpy(sound_name, MD.kit.name, l); @@ -63,7 +62,6 @@ void SoundBrowserPage::save_sound() { void SoundBrowserPage::load_sound() { - grid_page.prepare(); if (file.isOpen()) { char temp_entry[FILE_ENTRY_SIZE]; MDSound sound; From 286093e220e4bdb66d73a10fc52ceef9a1d2ea96 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 22 Oct 2024 11:18:45 +1100 Subject: [PATCH 103/133] float -> int --- avr/cores/megacommand/MCL/MixerPage.cpp | 40 ++++++++++++++----------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 7aaf80721..f7277c7d7 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -332,8 +332,8 @@ void MixerPage::display() { fader_level = 127; } - fader_level = ((fader_level * 0.00787) * FADER_LEN) + 0; - meter_level = ((levels[i] * 0.00787) * FADER_LEN) + 0; + fader_level = (((uint16_t) fader_level * FADER_LEN) / 127) + 0; + meter_level = (((uint16_t) levels[i] * FADER_LEN) / 127) + 0; meter_level = min(fader_level, meter_level); if (IS_BIT_SET16(redraw_mask, i)) { @@ -734,12 +734,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { switch (key) { case MDX_KEY_GLOBAL: case MDX_KEY_YES: { - preview_mute_set = 255; - show_mixer_menu = false; - disable_record_mutes(); - MD.set_trigleds(0, is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); - redraw(); - return true; + goto global_release; } case MDX_KEY_EXTENDED: { @@ -780,43 +775,52 @@ bool MixerPage::handleEvent(gui_event_t *event) { } } } - if (BUTTON_DOWN(Buttons.BUTTON3)) { + if (EVENT_RELEASED(event, Buttons.BUTTON3)) { + global_release: + preview_mute_set = 255; + show_mixer_menu = false; + disable_record_mutes(); + MD.set_trigleds(0, is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); + redraw(); + return true; + } + if (EVENT_PRESSED(event,Buttons.BUTTON3)) { + // show_mixer_menu = true; + if (note_interface.notes_on) { + setLed2(); + record_mutes_set(true); + return true; + } if (BUTTON_DOWN(Buttons.ENCODER1)) { perf_param1.clear_scenes(); - redraw_mask = -1; } if (BUTTON_DOWN(Buttons.ENCODER2)) { perf_param2.clear_scenes(); - redraw_mask = -1; } if (BUTTON_DOWN(Buttons.ENCODER3)) { perf_param3.clear_scenes(); - redraw_mask = -1; } if (BUTTON_DOWN(Buttons.ENCODER4)) { perf_param4.clear_scenes(); - redraw_mask = -1; } + redraw_mask = -1; return true; } - if (BUTTON_DOWN(Buttons.BUTTON4)) { + if (EVENT_PRESSED(event, Buttons.BUTTON4)) { if (BUTTON_DOWN(Buttons.ENCODER1)) { perf_param1.scene_autofill(); - redraw_mask = -1; } if (BUTTON_DOWN(Buttons.ENCODER2)) { perf_param2.scene_autofill(); - redraw_mask = -1; } if (BUTTON_DOWN(Buttons.ENCODER3)) { perf_param3.scene_autofill(); - redraw_mask = -1; } if (BUTTON_DOWN(Buttons.ENCODER4)) { perf_param4.scene_autofill(); - redraw_mask = -1; } + redraw_mask = -1; return true; } From 94db78065d2d6add73549195684717a2fc1f6947 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 22 Oct 2024 11:31:39 +1100 Subject: [PATCH 104/133] PAGE_SELECT, common GUI --- avr/cores/megacommand/MCL/FXPage.cpp | 10 ---------- avr/cores/megacommand/MCL/GridPage.cpp | 4 ---- avr/cores/megacommand/MCL/MCL.cpp | 6 ++++++ avr/cores/megacommand/MCL/MixerPage.cpp | 6 ------ avr/cores/megacommand/MCL/PerfPageParent.cpp | 5 ----- avr/cores/megacommand/MCL/RAMPage.cpp | 5 ----- avr/cores/megacommand/MCL/RoutePage.cpp | 4 ---- avr/cores/megacommand/MCL/SampleBrowserPage.cpp | 5 ----- avr/cores/megacommand/MCL/SeqPage.cpp | 4 ---- avr/cores/megacommand/MCL/WavDesignerPage.cpp | 4 ---- 10 files changed, 6 insertions(+), 47 deletions(-) diff --git a/avr/cores/megacommand/MCL/FXPage.cpp b/avr/cores/megacommand/MCL/FXPage.cpp index 45a963769..e6aecb603 100644 --- a/avr/cores/megacommand/MCL/FXPage.cpp +++ b/avr/cores/megacommand/MCL/FXPage.cpp @@ -164,15 +164,5 @@ bool FXPage::handleEvent(gui_event_t *event) { return true; } - if (EVENT_PRESSED(event, Buttons.BUTTON3)) { - } - - if (EVENT_PRESSED(event, Buttons.BUTTON4)) { - } - if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - mcl.setPage(PAGE_SELECT_PAGE); - return true; - } - return false; } diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index 31fb6f90c..23f1d621a 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -1190,10 +1190,6 @@ bool GridPage::handleEvent(gui_event_t *event) { mcl.pushPage(SYSTEM_PAGE); return true; } - if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - mcl.setPage(PAGE_SELECT_PAGE); - return true; - } return false; } diff --git a/avr/cores/megacommand/MCL/MCL.cpp b/avr/cores/megacommand/MCL/MCL.cpp index bd0ec5bc6..db54b5df4 100644 --- a/avr/cores/megacommand/MCL/MCL.cpp +++ b/avr/cores/megacommand/MCL/MCL.cpp @@ -435,6 +435,12 @@ bool mcl_handleEvent(gui_event_t *event) { } } } + + if (EVENT_PRESSED(event, Buttons.BUTTON2)) { + mcl.setPage(PAGE_SELECT_PAGE); + return true; + } + return false; } diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index f7277c7d7..f57f23714 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -824,12 +824,6 @@ bool MixerPage::handleEvent(gui_event_t *event) { return true; } - - if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - mcl.setPage(PAGE_SELECT_PAGE); - return true; - } - if (preview_mute_set != 255 && (trig_interface.is_key_down(MDX_KEY_NO))) { if (event->source >= Buttons.ENCODER1 && event->source <= Buttons.ENCODER4) { diff --git a/avr/cores/megacommand/MCL/PerfPageParent.cpp b/avr/cores/megacommand/MCL/PerfPageParent.cpp index 0d291bbfd..0492bf95c 100644 --- a/avr/cores/megacommand/MCL/PerfPageParent.cpp +++ b/avr/cores/megacommand/MCL/PerfPageParent.cpp @@ -94,10 +94,5 @@ bool PerfPageParent::handleEvent(gui_event_t *event) { } } */ - if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - mcl.setPage(PAGE_SELECT_PAGE); - return true; - } - return false; } diff --git a/avr/cores/megacommand/MCL/RAMPage.cpp b/avr/cores/megacommand/MCL/RAMPage.cpp index 5d358f4e5..9d7bccdd8 100644 --- a/avr/cores/megacommand/MCL/RAMPage.cpp +++ b/avr/cores/megacommand/MCL/RAMPage.cpp @@ -753,11 +753,6 @@ bool RAMPage::handleEvent(gui_event_t *event) { } } - if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - mcl.setPage(PAGE_SELECT_PAGE); - return true; - } - return false; } diff --git a/avr/cores/megacommand/MCL/RoutePage.cpp b/avr/cores/megacommand/MCL/RoutePage.cpp index adc59edb5..e46eb79eb 100644 --- a/avr/cores/megacommand/MCL/RoutePage.cpp +++ b/avr/cores/megacommand/MCL/RoutePage.cpp @@ -163,10 +163,6 @@ bool RoutePage::handleEvent(gui_event_t *event) { // mcl.setPage(MIXER_PAGE); // return true; //} - if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - mcl.setPage(PAGE_SELECT_PAGE); - return true; - } /* if (EVENT_PRESSED(event, Buttons.ENCODER1) || EVENT_PRESSED(event, Buttons.ENCODER2) || diff --git a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp index 4921c36a7..da30b4dd8 100644 --- a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp @@ -267,11 +267,6 @@ bool SampleBrowserPage::handleEvent(gui_event_t *event) { return true; } - if (EVENT_PRESSED(event, Buttons.BUTTON1)) { - mcl.setPage(PAGE_SELECT_PAGE); - return true; - } - return FileBrowserPage::handleEvent(event); } diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index 9178870f0..6f593441f 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -356,10 +356,6 @@ bool SeqPage::handleEvent(gui_event_t *event) { return true; } - if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - mcl.setPage(PAGE_SELECT_PAGE); - } - if (EVENT_PRESSED(event, Buttons.BUTTON3)) { // If MD trig is held and BUTTON3 is pressed, launch note menu if (!show_seq_menu) { diff --git a/avr/cores/megacommand/MCL/WavDesignerPage.cpp b/avr/cores/megacommand/MCL/WavDesignerPage.cpp index e7afc2a2e..73f653c44 100644 --- a/avr/cores/megacommand/MCL/WavDesignerPage.cpp +++ b/avr/cores/megacommand/MCL/WavDesignerPage.cpp @@ -96,10 +96,6 @@ bool WavDesignerPage::handleEvent(gui_event_t *event) { } return true; } - if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - mcl.setPage(PAGE_SELECT_PAGE); - return true; - } return false; } From b760778e6891a6362857694192d2466230f68360 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 22 Oct 2024 11:46:13 +1100 Subject: [PATCH 105/133] PerfTrack latency estimation --- avr/cores/megacommand/MCL/PerfTrack.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/PerfTrack.cpp b/avr/cores/megacommand/MCL/PerfTrack.cpp index decb0e62b..30e11c571 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.cpp +++ b/avr/cores/megacommand/MCL/PerfTrack.cpp @@ -14,7 +14,15 @@ void PerfTrack::transition_load(uint8_t tracknumber, SeqTrack *seq_track, } uint16_t PerfTrack::calc_latency(uint8_t tracknumber) { - return 0; + uint8_t load_mute_set = 255; + + for (uint8_t n = 0; n < 4; n++) { + if ((mute_sets[1].mutes[n] & 0b1000000000000000) == 0) { + load_mute_set = n; + } + } + + return load_mute_set == 255 ? 0 : 32 * 3 * 4; // Worst case estimate, 32 parameters, 3 bytes each, 4 perf controllers. } void PerfTrack::get_perf() { From 49db9697a7a433cce531d4ea3aa7a6db537c161f Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 22 Oct 2024 19:52:34 +1100 Subject: [PATCH 106/133] Initialisation Optimization --- avr/cores/megacommand/MCL/MixerPage.h | 4 ++-- avr/cores/megacommand/MCL/PerfData.h | 18 +----------------- avr/cores/megacommand/MCL/PerfTrack.h | 5 +++-- 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index 55b1c6e6a..8d0b7f001 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -68,8 +68,8 @@ class MixerPage : public LightPage { Encoder *e4 = NULL) : LightPage(e1, e2, e3, e4) { midi_device = &MD; - memset(mute_sets, 0xFF, sizeof(mute_sets)); - memset(perf_locks, 0xFF, sizeof(perf_locks)); + memset(mute_sets, 0xFF, sizeof(mute_sets) + sizeof(perf_locks)); + //memset(perf_locks, 0xFF, sizeof(perf_locks)); memset(load_types, 1, sizeof(load_types)); } void adjust_param(EncoderParent *enc, uint8_t param); diff --git a/avr/cores/megacommand/MCL/PerfData.h b/avr/cores/megacommand/MCL/PerfData.h index fbabf043b..5074ab0d8 100644 --- a/avr/cores/megacommand/MCL/PerfData.h +++ b/avr/cores/megacommand/MCL/PerfData.h @@ -12,27 +12,11 @@ static uint8_t get_param_device(uint8_t dest, uint8_t param) { if (dest <= NUM_MD_TRACKS) { return MD.kit.params[dest - 1][param]; } else { - switch (dest - NUM_MD_TRACKS - 1) { - case MD_FX_ECHO - MD_FX_ECHO: - return MD.kit.delay[param]; - break; - case MD_FX_DYN - MD_FX_ECHO: - return MD.kit.dynamics[param]; - break; - - case MD_FX_REV - MD_FX_ECHO: - return MD.kit.reverb[param]; - break; - case MD_FX_EQ - MD_FX_ECHO: - return MD.kit.eq[param]; - break; - } + return MD.kit.get_fx_param(dest - NUM_MD_TRACKS - 1, param); } return 255; } - - class PerfParam { public: uint8_t dest; diff --git a/avr/cores/megacommand/MCL/PerfTrack.h b/avr/cores/megacommand/MCL/PerfTrack.h index 6da1cf809..ce7300dcc 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.h +++ b/avr/cores/megacommand/MCL/PerfTrack.h @@ -55,8 +55,9 @@ class PerfTrack : public AUXTrack, public PerfTrackData { } scenes[n].init(); } - memset(mute_sets, 0xFF, sizeof(mute_sets)); - memset(perf_locks, 255, sizeof(perf_locks)); + //memset(mute_sets, 0xFF, sizeof(mute_sets)); + //memset(perf_locks, 255, sizeof(perf_locks)); + memset(mute_sets, 0xFF, sizeof(mute_sets) + sizeof(perf_locks)); } void load_perf(bool immediate, SeqTrack *seq_track); From f119739cc69daa019d62766c9a73cdf6e88b0c61 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 22 Oct 2024 22:26:08 +1100 Subject: [PATCH 107/133] Consolidate repeated code --- Changelog | 2 +- avr/cores/megacommand/MCL/FXPage.cpp | 16 +--------------- avr/cores/megacommand/MCL/LFOSeqTrack.cpp | 15 +-------------- avr/cores/megacommand/MCL/PerfData.h | 2 +- avr/cores/megacommand/MD/MDMessages.h | 18 +++++++++++++++++- 5 files changed, 21 insertions(+), 32 deletions(-) diff --git a/Changelog b/Changelog index 90b0f6845..d97126127 100644 --- a/Changelog +++ b/Changelog @@ -28,7 +28,7 @@ Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.6 Performance State Autoload: A chosen Performance State can now be made to auto-load when the Perf Slot in Grid Y is loaded: - - From the Mixer Page, Hold an [ Arrow ] key to visually preview the Performance State and then press [ Swing / BANKB ] to enable auto "LOAD". + - From the Mixer Page, Hold an [ Arrow ] key to visually preview the Performance State and then press [ Accent / BANKB ] to enable auto "LOAD". - Then save the Perf Slot, in Grid Y. The Mutes, in a Performance State can be permanantly disabled for the active device by holding an [ Arrow ] key and pressing [ Mute / BankA ] diff --git a/avr/cores/megacommand/MCL/FXPage.cpp b/avr/cores/megacommand/MCL/FXPage.cpp index e6aecb603..c21a67aea 100644 --- a/avr/cores/megacommand/MCL/FXPage.cpp +++ b/avr/cores/megacommand/MCL/FXPage.cpp @@ -29,21 +29,7 @@ void FXPage::update_encoders() { uint8_t a = ((uint8_t)page_mode * GUI_NUM_ENCODERS) + n; uint8_t fx_param = params[a].param; - - switch (params[a].type) { - case MD_FX_ECHO: - enc->cur = MD.kit.delay[fx_param]; - break; - case MD_FX_REV: - enc->cur = MD.kit.reverb[fx_param]; - break; - case MD_FX_EQ: - enc->cur = MD.kit.eq[fx_param]; - break; - case MD_FX_DYN: - enc->cur = MD.kit.dynamics[fx_param]; - break; - } + enc->cur = MD.kit.get_fx_param(params[a].type, fx_param); enc->old = enc->cur; } diff --git a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp index 741bc96a3..90e130656 100644 --- a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp @@ -174,20 +174,7 @@ uint8_t LFOSeqTrack::get_param_offset(uint8_t dest, uint8_t param_id) { if (dest < NUM_MD_TRACKS) { return MD.kit.params[dest][param]; } else if (dest < NUM_MD_TRACKS + 4) { - switch (dest - NUM_MD_TRACKS) { - case MD_FX_ECHO - MD_FX_ECHO: - return MD.kit.delay[param]; - break; - case MD_FX_DYN - MD_FX_ECHO: - return MD.kit.dynamics[param]; - break; - case MD_FX_REV - MD_FX_ECHO: - return MD.kit.reverb[param]; - break; - case MD_FX_EQ - MD_FX_ECHO: - return MD.kit.eq[param]; - break; - } + return MD.kit.get_fx_param(dest - NUM_MD_TRACKS, param); } else { // MIDI return params[param_id].offset; diff --git a/avr/cores/megacommand/MCL/PerfData.h b/avr/cores/megacommand/MCL/PerfData.h index 5074ab0d8..06fb0473e 100644 --- a/avr/cores/megacommand/MCL/PerfData.h +++ b/avr/cores/megacommand/MCL/PerfData.h @@ -12,7 +12,7 @@ static uint8_t get_param_device(uint8_t dest, uint8_t param) { if (dest <= NUM_MD_TRACKS) { return MD.kit.params[dest - 1][param]; } else { - return MD.kit.get_fx_param(dest - NUM_MD_TRACKS - 1, param); + return MD.kit.get_fx_param(dest - NUM_MD_TRACKS - 1 + MD_FX_ECHO, param); } return 255; } diff --git a/avr/cores/megacommand/MD/MDMessages.h b/avr/cores/megacommand/MD/MDMessages.h index 0df8c1cc5..5c7825367 100644 --- a/avr/cores/megacommand/MD/MDMessages.h +++ b/avr/cores/megacommand/MD/MDMessages.h @@ -273,7 +273,23 @@ class MDKit: public ElektronSysexObject { uint8_t get_model(uint8_t track); bool get_tonal(uint8_t track); - + uint8_t get_fx_param(uint8_t fx, uint8_t param) { + uint8_t ret = 255; + switch (fx) { + case MD_FX_ECHO: + ret = delay[param]; + break; + case MD_FX_DYN: + ret = dynamics[param]; + break; + case MD_FX_REV: + ret = reverb[param]; + break; + case MD_FX_EQ: + ret = eq[param]; + } + return ret; + } /* @} */ }; From 773d3cfbaf01a911ecafbb40efdae978ec999df7 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 00:11:13 +1100 Subject: [PATCH 108/133] redraw mask, and redundant calls to oled_display --- avr/cores/megacommand/MCL/MixerPage.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index f57f23714..6bf897787 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -268,11 +268,9 @@ void MixerPage::adjust_param(EncoderParent *enc, uint8_t param) { void MixerPage::display() { auto oldfont = oled_display.getFont(); - //oled_display.setFont(); + oled_display.setFont(); if (oled_display.textbox_enabled) { - oled_display.clearDisplay(); - oled_draw_mutes(); - redraw_mask = -1; + redraw(); } if (redraw_mutes) { @@ -308,7 +306,6 @@ void MixerPage::display() { oled_display.print("LOAD"); } oled_display.setFont(); - oled_display.display(); } else { uint8_t fader_level; @@ -365,11 +362,7 @@ void MixerPage::display() { } } - if (!redraw_mask) { - oled_display.display(); - } else { - redraw_mask = -1; - } + redraw_mask = -1; oled_display.setFont(oldfont); } From d7d4bdcc6007654fa454110d9c010842bac53cb2 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 10:36:56 +1100 Subject: [PATCH 109/133] oled_display.display() is already called in the GUI loop --- avr/cores/megacommand/MCL/ArpPage.cpp | 1 - avr/cores/megacommand/MCL/FXPage.cpp | 1 - avr/cores/megacommand/MCL/FileBrowserPage.cpp | 1 - avr/cores/megacommand/MCL/GridLoadPage.cpp | 1 - avr/cores/megacommand/MCL/GridPage.cpp | 1 - avr/cores/megacommand/MCL/GridSavePage.cpp | 1 - avr/cores/megacommand/MCL/LFOPage.cpp | 1 - avr/cores/megacommand/MCL/MenuPage.cpp | 1 - avr/cores/megacommand/MCL/OscMixerPage.cpp | 1 - avr/cores/megacommand/MCL/OscPage.cpp | 1 - avr/cores/megacommand/MCL/PageSelectPage.cpp | 1 - avr/cores/megacommand/MCL/PerfPage.cpp | 1 - avr/cores/megacommand/MCL/PolyPage.cpp | 1 - avr/cores/megacommand/MCL/QuestionDialogPage.cpp | 1 - avr/cores/megacommand/MCL/RAMPage.cpp | 1 - avr/cores/megacommand/MCL/RoutePage.cpp | 1 - avr/cores/megacommand/MCL/SampleBrowserPage.cpp | 1 - avr/cores/megacommand/MCL/SeqExtStepPage.cpp | 1 - avr/cores/megacommand/MCL/SeqPtcPage.cpp | 1 - avr/cores/megacommand/MCL/SeqStepPage.cpp | 1 - avr/cores/megacommand/MCL/TextInputPage.cpp | 1 - 21 files changed, 21 deletions(-) diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp index a39ba0bb1..e829888c1 100644 --- a/avr/cores/megacommand/MCL/ArpPage.cpp +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -133,7 +133,6 @@ void ArpPage::display() { mcl_gui.put_value_at(encoders[3]->cur, str); mcl_gui.draw_text_encoder(x + 3 * mcl_gui.knob_w, y, "RANGE", str, param_select == 3); - oled_display.display(); oled_display.setFont(oldfont); } diff --git a/avr/cores/megacommand/MCL/FXPage.cpp b/avr/cores/megacommand/MCL/FXPage.cpp index c21a67aea..d80cf3265 100644 --- a/avr/cores/megacommand/MCL/FXPage.cpp +++ b/avr/cores/megacommand/MCL/FXPage.cpp @@ -92,7 +92,6 @@ void FXPage::display() { } info2 = &fx_page_title[0]; mcl_gui.draw_panel_labels(info1, info2); - oled_display.display(); oled_display.setFont(oldfont); } diff --git a/avr/cores/megacommand/MCL/FileBrowserPage.cpp b/avr/cores/megacommand/MCL/FileBrowserPage.cpp index 8bcdd5dc3..1ed9e1163 100644 --- a/avr/cores/megacommand/MCL/FileBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/FileBrowserPage.cpp @@ -226,7 +226,6 @@ void FileBrowserPage::display() { } draw_sidebar(); draw_filebrowser(); - oled_display.display(); return; } diff --git a/avr/cores/megacommand/MCL/GridLoadPage.cpp b/avr/cores/megacommand/MCL/GridLoadPage.cpp index eda42eb49..8d6e494b6 100644 --- a/avr/cores/megacommand/MCL/GridLoadPage.cpp +++ b/avr/cores/megacommand/MCL/GridLoadPage.cpp @@ -193,7 +193,6 @@ void GridLoadPage::display() { oled_display.print(F("SEQ")); */ } - oled_display.display(); oled_display.setFont(oldfont); } void GridLoadPage::load() { diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index 23f1d621a..63e9e5bf5 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -625,7 +625,6 @@ void GridPage::display() { mcl_gui.draw_progress_bar(8, 8, false, 18, 2, 9, 7, false); } */ - oled_display.display(); } void rename_row() { diff --git a/avr/cores/megacommand/MCL/GridSavePage.cpp b/avr/cores/megacommand/MCL/GridSavePage.cpp index 299dbdf07..f5e14539e 100644 --- a/avr/cores/megacommand/MCL/GridSavePage.cpp +++ b/avr/cores/megacommand/MCL/GridSavePage.cpp @@ -73,7 +73,6 @@ void GridSavePage::display() { oled_display.setCursor(data_x + 24 + 9, MCLGUI::s_menu_y + 18); oled_display.print(F("GRID")); } - oled_display.display(); oled_display.setFont(oldfont); } diff --git a/avr/cores/megacommand/MCL/LFOPage.cpp b/avr/cores/megacommand/MCL/LFOPage.cpp index cf77d307d..500b0e1e4 100644 --- a/avr/cores/megacommand/MCL/LFOPage.cpp +++ b/avr/cores/megacommand/MCL/LFOPage.cpp @@ -238,7 +238,6 @@ void LFOPage::display() { mcl_gui.draw_panel_labels(info1, info2); - oled_display.display(); oled_display.setFont(oldfont); } diff --git a/avr/cores/megacommand/MCL/MenuPage.cpp b/avr/cores/megacommand/MCL/MenuPage.cpp index 61fcceec8..d053b4091 100644 --- a/avr/cores/megacommand/MCL/MenuPage.cpp +++ b/avr/cores/megacommand/MCL/MenuPage.cpp @@ -185,7 +185,6 @@ void MenuPageBase::display() { if (number_of_items > visible_rows) { draw_scrollbar(120); } - oled_display.display(); } bool MenuPageBase::enter() { diff --git a/avr/cores/megacommand/MCL/OscMixerPage.cpp b/avr/cores/megacommand/MCL/OscMixerPage.cpp index 128e49cf8..522175a37 100644 --- a/avr/cores/megacommand/MCL/OscMixerPage.cpp +++ b/avr/cores/megacommand/MCL/OscMixerPage.cpp @@ -42,7 +42,6 @@ void OscMixerPage::display() { scanline_width = 4; draw_wav(); } - oled_display.display(); oled_display.setFont(oldfont); } diff --git a/avr/cores/megacommand/MCL/OscPage.cpp b/avr/cores/megacommand/MCL/OscPage.cpp index 43d76b918..f536facc5 100644 --- a/avr/cores/megacommand/MCL/OscPage.cpp +++ b/avr/cores/megacommand/MCL/OscPage.cpp @@ -177,7 +177,6 @@ void OscPage::display() { } // GUI.put_string_at(0, my_str); WavDesignerPage::display(); - oled_display.display(); oled_display.setFont(oldfont); } void OscPage::draw_wav(uint8_t wav_type) { diff --git a/avr/cores/megacommand/MCL/PageSelectPage.cpp b/avr/cores/megacommand/MCL/PageSelectPage.cpp index 6472e3a05..a3048511c 100644 --- a/avr/cores/megacommand/MCL/PageSelectPage.cpp +++ b/avr/cores/megacommand/MCL/PageSelectPage.cpp @@ -279,7 +279,6 @@ void PageSelectPage::display() { WHITE); } - oled_display.display(); uint16_t led_mask = 1 << page_select; if (trigled_mask != led_mask) { trigled_mask = led_mask; diff --git a/avr/cores/megacommand/MCL/PerfPage.cpp b/avr/cores/megacommand/MCL/PerfPage.cpp index a9b7b6f2a..77e0be252 100644 --- a/avr/cores/megacommand/MCL/PerfPage.cpp +++ b/avr/cores/megacommand/MCL/PerfPage.cpp @@ -302,7 +302,6 @@ void PerfPage::display() { oled_display.writeFastHLine(109, MCLGUI::pane_info2_y + 1, 5, WHITE); oled_display.writeFastVLine(109 + ((e->cur * 5) / 128), MCLGUI::pane_info2_y, 3, WHITE); - oled_display.display(); } diff --git a/avr/cores/megacommand/MCL/PolyPage.cpp b/avr/cores/megacommand/MCL/PolyPage.cpp index ee612006d..cc42c7247 100644 --- a/avr/cores/megacommand/MCL/PolyPage.cpp +++ b/avr/cores/megacommand/MCL/PolyPage.cpp @@ -64,7 +64,6 @@ void PolyPage::display() { } oled_display.setFont(oldfont); - oled_display.display(); } bool PolyPage::handleEvent(gui_event_t *event) { diff --git a/avr/cores/megacommand/MCL/QuestionDialogPage.cpp b/avr/cores/megacommand/MCL/QuestionDialogPage.cpp index 6b488a804..1b0e84008 100644 --- a/avr/cores/megacommand/MCL/QuestionDialogPage.cpp +++ b/avr/cores/megacommand/MCL/QuestionDialogPage.cpp @@ -19,7 +19,6 @@ void QuestionDialogPage::init(const char* title_, const char* text_) { oled_display.drawRect(MCLGUI::dlg_info_x2 - 57, MCLGUI::dlg_info_y1 + 16, 18, 9, WHITE); oled_display.setFont(oldfont); - oled_display.display(); } void QuestionDialogPage::display() { diff --git a/avr/cores/megacommand/MCL/RAMPage.cpp b/avr/cores/megacommand/MCL/RAMPage.cpp index 9d7bccdd8..b37264065 100644 --- a/avr/cores/megacommand/MCL/RAMPage.cpp +++ b/avr/cores/megacommand/MCL/RAMPage.cpp @@ -612,7 +612,6 @@ void RAMPage::display() { } wheel_spin_last_clock = MidiClock.div16th_counter; } - oled_display.display(); oled_display.setFont(oldfont); } diff --git a/avr/cores/megacommand/MCL/RoutePage.cpp b/avr/cores/megacommand/MCL/RoutePage.cpp index e46eb79eb..c6ea5e0bc 100644 --- a/avr/cores/megacommand/MCL/RoutePage.cpp +++ b/avr/cores/megacommand/MCL/RoutePage.cpp @@ -127,7 +127,6 @@ void RoutePage::display() { mcl_gui.draw_panel_labels("ROUTE", info_line2); draw_routes(); - oled_display.display(); oled_display.setFont(oldfont); } diff --git a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp index da30b4dd8..cb6bffde7 100644 --- a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp @@ -95,7 +95,6 @@ void SampleBrowserPage::display() { FileBrowserPage::selection_change = false; end: draw_filebrowser(); - oled_display.display(); } void SampleBrowserPage::init(uint8_t show_samplemgr_) { diff --git a/avr/cores/megacommand/MCL/SeqExtStepPage.cpp b/avr/cores/megacommand/MCL/SeqExtStepPage.cpp index 80326ea33..0644d2e33 100644 --- a/avr/cores/megacommand/MCL/SeqExtStepPage.cpp +++ b/avr/cores/megacommand/MCL/SeqExtStepPage.cpp @@ -804,7 +804,6 @@ void SeqExtStepPage::display() { } // oled_display.fillRect(draw_x, 0, 1 , fov_h, WHITE); - oled_display.display(); #endif } diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index 57450d406..b2cf177d1 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -274,7 +274,6 @@ void SeqPtcPage::display() { if (show_seq_menu) { display_mute_mask(midi_active_peering.get_device(UART2_PORT), 8); } - oled_display.display(); oled_display.setFont(oldfont); } diff --git a/avr/cores/megacommand/MCL/SeqStepPage.cpp b/avr/cores/megacommand/MCL/SeqStepPage.cpp index 469dd5b12..3c48c9d20 100644 --- a/avr/cores/megacommand/MCL/SeqStepPage.cpp +++ b/avr/cores/megacommand/MCL/SeqStepPage.cpp @@ -186,7 +186,6 @@ void SeqStepPage::display() { page_select_page.md_prepare(); prepare = false; } - oled_display.display(); oled_display.setFont(oldfont); } diff --git a/avr/cores/megacommand/MCL/TextInputPage.cpp b/avr/cores/megacommand/MCL/TextInputPage.cpp index b0e5a73be..10d276ce6 100644 --- a/avr/cores/megacommand/MCL/TextInputPage.cpp +++ b/avr/cores/megacommand/MCL/TextInputPage.cpp @@ -199,7 +199,6 @@ void TextInputPage::display() { else display_charpane(); - oled_display.display(); } bool TextInputPage::handleEvent(gui_event_t *event) { From 13d2712179f299f123f9f658de252ffdebe2dbf3 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 11:08:22 +1100 Subject: [PATCH 110/133] Optimise clearDisplay and setFont --- avr/cores/megacommand/GUI/GUI.cpp | 1 + avr/cores/megacommand/MCL/ArpPage.cpp | 3 --- avr/cores/megacommand/MCL/FXPage.cpp | 5 ----- avr/cores/megacommand/MCL/GridLoadPage.cpp | 4 ---- avr/cores/megacommand/MCL/GridSavePage.cpp | 3 --- avr/cores/megacommand/MCL/LFOPage.cpp | 2 -- avr/cores/megacommand/MCL/MixerPage.cpp | 3 --- avr/cores/megacommand/MCL/OscMixerPage.cpp | 3 --- avr/cores/megacommand/MCL/OscPage.cpp | 3 --- avr/cores/megacommand/MCL/PerfPage.cpp | 3 --- avr/cores/megacommand/MCL/PerfPageParent.cpp | 2 -- avr/cores/megacommand/MCL/PolyPage.cpp | 8 -------- avr/cores/megacommand/MCL/QuestionDialogPage.cpp | 3 --- avr/cores/megacommand/MCL/RAMPage.cpp | 5 ----- avr/cores/megacommand/MCL/RoutePage.cpp | 2 -- avr/cores/megacommand/MCL/SeqPage.cpp | 2 -- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 3 --- avr/cores/megacommand/MCL/SeqStepPage.cpp | 2 -- avr/cores/megacommand/MCL/TextInputPage.cpp | 3 --- 19 files changed, 1 insertion(+), 59 deletions(-) diff --git a/avr/cores/megacommand/GUI/GUI.cpp b/avr/cores/megacommand/GUI/GUI.cpp index 7502338a0..a5ed8488b 100644 --- a/avr/cores/megacommand/GUI/GUI.cpp +++ b/avr/cores/megacommand/GUI/GUI.cpp @@ -120,6 +120,7 @@ void GuiClass::display() { if (sketch != NULL) { page = sketch->currentPage(); if (page != NULL) { + oled_display.setFont(); page->display(); } } diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp index e829888c1..2f65b96e1 100644 --- a/avr/cores/megacommand/MCL/ArpPage.cpp +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -11,7 +11,6 @@ void ArpPage::setup() { void ArpPage::init() { DEBUG_PRINT_FN(); - oled_display.setFont(); // seq_ptc_page.display(); track_update(); trig_interface.send_md_leds(TRIGLED_EXCLUSIVE); @@ -88,7 +87,6 @@ const arp_name_t arp_names[] PROGMEM = { void ArpPage::display() { - auto oldfont = oled_display.getFont(); oled_display.setFont(&TomThumb); oled_display.fillRect(8, 2, 128 - 16, 32 - 2, BLACK); @@ -133,7 +131,6 @@ void ArpPage::display() { mcl_gui.put_value_at(encoders[3]->cur, str); mcl_gui.draw_text_encoder(x + 3 * mcl_gui.knob_w, y, "RANGE", str, param_select == 3); - oled_display.setFont(oldfont); } bool ArpPage::handleEvent(gui_event_t *event) { diff --git a/avr/cores/megacommand/MCL/FXPage.cpp b/avr/cores/megacommand/MCL/FXPage.cpp index d80cf3265..944c25035 100644 --- a/avr/cores/megacommand/MCL/FXPage.cpp +++ b/avr/cores/megacommand/MCL/FXPage.cpp @@ -10,8 +10,6 @@ void FXPage::setup() { DEBUG_PRINT_FN(); } void FXPage::init() { DEBUG_PRINT_FN(); - oled_display.clearDisplay(); - oled_display.setFont(); trig_interface.off(); update_encoders(); MD.set_key_repeat(0); @@ -39,7 +37,6 @@ void FXPage::update_encoders() { void FXPage::cleanup() { // md_exploit.off(); MD.set_key_repeat(1); - oled_display.clearDisplay(); } void FXPage::loop() { @@ -61,7 +58,6 @@ void FXPage::display() { char str[4]; PGM_P param_name = NULL; oled_display.clearDisplay(); - auto oldfont = oled_display.getFont(); uint8_t *icon = R.icons_page->icon_rhytmecho; if (page_id == 1) { @@ -92,7 +88,6 @@ void FXPage::display() { } info2 = &fx_page_title[0]; mcl_gui.draw_panel_labels(info1, info2); - oled_display.setFont(oldfont); } bool FXPage::handleEvent(gui_event_t *event) { diff --git a/avr/cores/megacommand/MCL/GridLoadPage.cpp b/avr/cores/megacommand/MCL/GridLoadPage.cpp index 8d6e494b6..32ce56381 100644 --- a/avr/cores/megacommand/MCL/GridLoadPage.cpp +++ b/avr/cores/megacommand/MCL/GridLoadPage.cpp @@ -108,8 +108,6 @@ void GridLoadPage::display() { const uint64_t mute_mask = 0, slide_mask = 0; - auto oldfont = oled_display.getFont(); - if (show_track_type) { mcl_gui.draw_track_type_select(mcl_cfg.track_type_select); } @@ -118,7 +116,6 @@ void GridLoadPage::display() { // mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 8, // "STEP", K); if (show_offset) { - oled_display.setFont(); oled_display.setCursor(MCLGUI::s_menu_x + 18, 12); oled_display.print("DESTINATION"); trig_mask = 0; @@ -193,7 +190,6 @@ void GridLoadPage::display() { oled_display.print(F("SEQ")); */ } - oled_display.setFont(oldfont); } void GridLoadPage::load() { diff --git a/avr/cores/megacommand/MCL/GridSavePage.cpp b/avr/cores/megacommand/MCL/GridSavePage.cpp index f5e14539e..19ac02637 100644 --- a/avr/cores/megacommand/MCL/GridSavePage.cpp +++ b/avr/cores/megacommand/MCL/GridSavePage.cpp @@ -28,8 +28,6 @@ void GridSavePage::display() { draw_popup(); - auto oldfont = oled_display.getFont(); - const uint64_t slide_mask = 0; const uint64_t mute_mask = 0; if (show_track_type) { @@ -73,7 +71,6 @@ void GridSavePage::display() { oled_display.setCursor(data_x + 24 + 9, MCLGUI::s_menu_y + 18); oled_display.print(F("GRID")); } - oled_display.setFont(oldfont); } void GridSavePage::save() { diff --git a/avr/cores/megacommand/MCL/LFOPage.cpp b/avr/cores/megacommand/MCL/LFOPage.cpp index 500b0e1e4..fc5578959 100644 --- a/avr/cores/megacommand/MCL/LFOPage.cpp +++ b/avr/cores/megacommand/MCL/LFOPage.cpp @@ -150,7 +150,6 @@ void LFOPage::loop() { void LFOPage::display() { oled_display.clearDisplay(); - auto oldfont = oled_display.getFont(); uint8_t lfo_track_num = lfo_track->track_number; mcl_gui.draw_panel_number(lfo_track_num); mcl_gui.draw_panel_toggle("ON", "OFF", lfo_track->enable); @@ -238,7 +237,6 @@ void LFOPage::display() { mcl_gui.draw_panel_labels(info1, info2); - oled_display.setFont(oldfont); } void LFOPage::learn_param(uint8_t track, uint8_t param, uint8_t value) { diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 6bf897787..ed88cf26f 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -267,8 +267,6 @@ void MixerPage::adjust_param(EncoderParent *enc, uint8_t param) { void MixerPage::display() { - auto oldfont = oled_display.getFont(); - oled_display.setFont(); if (oled_display.textbox_enabled) { redraw(); } @@ -363,7 +361,6 @@ void MixerPage::display() { } redraw_mask = -1; - oled_display.setFont(oldfont); } void MixerPage::record_mutes_set(bool state) { diff --git a/avr/cores/megacommand/MCL/OscMixerPage.cpp b/avr/cores/megacommand/MCL/OscMixerPage.cpp index 522175a37..c93b0fbc6 100644 --- a/avr/cores/megacommand/MCL/OscMixerPage.cpp +++ b/avr/cores/megacommand/MCL/OscMixerPage.cpp @@ -28,8 +28,6 @@ bool OscMixerPage::handleEvent(gui_event_t *event) { void OscMixerPage::loop() { WavDesignerPage::loop(); } void OscMixerPage::display() { - // oled_display.clearDisplay(); - auto oldfont = oled_display.getFont(); if (show_menu) { WavDesignerPage::display(); } else { @@ -42,7 +40,6 @@ void OscMixerPage::display() { scanline_width = 4; draw_wav(); } - oled_display.setFont(oldfont); } float OscMixerPage::get_max_gain() { diff --git a/avr/cores/megacommand/MCL/OscPage.cpp b/avr/cores/megacommand/MCL/OscPage.cpp index f536facc5..4afc3bafb 100644 --- a/avr/cores/megacommand/MCL/OscPage.cpp +++ b/avr/cores/megacommand/MCL/OscPage.cpp @@ -133,8 +133,6 @@ void OscPage::display() { uint8_t c = 1; uint8_t i = 0; - auto oldfont = oled_display.getFont(); - oled_display.setFont(); oled_display.setCursor(0, 0); switch (osc_waveform) { @@ -177,7 +175,6 @@ void OscPage::display() { } // GUI.put_string_at(0, my_str); WavDesignerPage::display(); - oled_display.setFont(oldfont); } void OscPage::draw_wav(uint8_t wav_type) { uint8_t x = 64; diff --git a/avr/cores/megacommand/MCL/PerfPage.cpp b/avr/cores/megacommand/MCL/PerfPage.cpp index 77e0be252..67594bd20 100644 --- a/avr/cores/megacommand/MCL/PerfPage.cpp +++ b/avr/cores/megacommand/MCL/PerfPage.cpp @@ -222,8 +222,6 @@ void PerfPage::display() { oled_display.clearDisplay(); - auto oldfont = oled_display.getFont(); - uint8_t x = mcl_gui.knob_x0 + 5; uint8_t y = 8; uint8_t lfo_height = 7; @@ -285,7 +283,6 @@ void PerfPage::display() { mcl_gui.draw_panel_number(scene + 1); } oled_display.setTextColor(WHITE, BLACK); - oled_display.setFont(oldfont); mcl_gui.draw_panel_labels(info1, info2); if (trig_interface.is_key_down(MDX_KEY_LEFT) || diff --git a/avr/cores/megacommand/MCL/PerfPageParent.cpp b/avr/cores/megacommand/MCL/PerfPageParent.cpp index 0492bf95c..3f05911e2 100644 --- a/avr/cores/megacommand/MCL/PerfPageParent.cpp +++ b/avr/cores/megacommand/MCL/PerfPageParent.cpp @@ -8,8 +8,6 @@ void PerfPageParent::setup() { DEBUG_PRINT_FN(); } void PerfPageParent::init() { DEBUG_PRINT_FN(); MD.set_key_repeat(0); - oled_display.clearDisplay(); - oled_display.setFont(); config_encoders(); R.Clear(); R.use_machine_param_names(); diff --git a/avr/cores/megacommand/MCL/PolyPage.cpp b/avr/cores/megacommand/MCL/PolyPage.cpp index cc42c7247..efaf2f5d3 100644 --- a/avr/cores/megacommand/MCL/PolyPage.cpp +++ b/avr/cores/megacommand/MCL/PolyPage.cpp @@ -8,14 +8,11 @@ void PolyPage::init() { DEBUG_PRINT_FN(); trig_interface.on(); note_interface.init_notes(); - oled_display.clearDisplay(); - oled_display.setFont(); MD.set_trigleds(mcl_cfg.poly_mask, TRIGLED_EXCLUSIVE); } void PolyPage::cleanup() { seq_ptc_page.init_poly(); - oled_display.clearDisplay(); trig_interface.off(); } @@ -47,12 +44,8 @@ void PolyPage::toggle_mask(uint8_t i) { } void PolyPage::display() { - auto oldfont = oled_display.getFont(); - oled_display.clearDisplay(); - oled_display.setFont(); - oled_display.setCursor(0, 15); oled_display.println("VOICE SELECT "); @@ -63,7 +56,6 @@ void PolyPage::display() { MD.set_trigleds(mcl_cfg.poly_mask, TRIGLED_EXCLUSIVE); } - oled_display.setFont(oldfont); } bool PolyPage::handleEvent(gui_event_t *event) { diff --git a/avr/cores/megacommand/MCL/QuestionDialogPage.cpp b/avr/cores/megacommand/MCL/QuestionDialogPage.cpp index 1b0e84008..a6a99431e 100644 --- a/avr/cores/megacommand/MCL/QuestionDialogPage.cpp +++ b/avr/cores/megacommand/MCL/QuestionDialogPage.cpp @@ -4,8 +4,6 @@ void QuestionDialogPage::init(const char* title_, const char* text_) { mcl_gui.draw_infobox(title_, text_, -1); oled_display.drawFastHLine(MCLGUI::dlg_info_x1 + 1, MCLGUI::dlg_info_y2, MCLGUI::dlg_info_w - 2, BLACK); - auto oldfont = oled_display.getFont(); - oled_display.setFont(&TomThumb); oled_display.setTextColor(WHITE); @@ -18,7 +16,6 @@ void QuestionDialogPage::init(const char* title_, const char* text_) { oled_display.drawRect(MCLGUI::dlg_info_x2 - 88, MCLGUI::dlg_info_y1 + 16, 18, 9, WHITE); oled_display.drawRect(MCLGUI::dlg_info_x2 - 57, MCLGUI::dlg_info_y1 + 16, 18, 9, WHITE); - oled_display.setFont(oldfont); } void QuestionDialogPage::display() { diff --git a/avr/cores/megacommand/MCL/RAMPage.cpp b/avr/cores/megacommand/MCL/RAMPage.cpp index b37264065..2495178cd 100644 --- a/avr/cores/megacommand/MCL/RAMPage.cpp +++ b/avr/cores/megacommand/MCL/RAMPage.cpp @@ -25,8 +25,6 @@ void RAMPage::setup() { void RAMPage::init() { DEBUG_PRINT_FN(); - oled_display.clearDisplay(); - oled_display.setFont(); trig_interface.off(); cc_link_enable = true; if (mcl_cfg.ram_page_mode == MONO) { @@ -448,8 +446,6 @@ void RAMPage::display() { oled_display.clearDisplay(); float remain; - auto oldfont = oled_display.getFont(); - oled_display.setFont(); oled_display.setCursor(28, 24); switch (RAMPage::rec_states[page_id]) { case STATE_QUEUE: @@ -612,7 +608,6 @@ void RAMPage::display() { } wheel_spin_last_clock = MidiClock.div16th_counter; } - oled_display.setFont(oldfont); } void RAMPage::onControlChangeCallback_Midi(uint8_t track, uint8_t track_param, uint8_t value) { diff --git a/avr/cores/megacommand/MCL/RoutePage.cpp b/avr/cores/megacommand/MCL/RoutePage.cpp index c6ea5e0bc..93e131f7f 100644 --- a/avr/cores/megacommand/MCL/RoutePage.cpp +++ b/avr/cores/megacommand/MCL/RoutePage.cpp @@ -97,7 +97,6 @@ void RoutePage::toggle_routes_batch(bool solo) { void RoutePage::display() { uint8_t x; - auto *oldfont = oled_display.getFont(); oled_display.clearDisplay(); oled_display.drawBitmap(0, 0, R.icons_page->icon_route, 24, 14, WHITE); @@ -127,7 +126,6 @@ void RoutePage::display() { mcl_gui.draw_panel_labels("ROUTE", info_line2); draw_routes(); - oled_display.setFont(oldfont); } bool RoutePage::handleEvent(gui_event_t *event) { diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index 6f593441f..512f68263 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -110,8 +110,6 @@ void SeqPage::init() { config_encoders(); seqpage_midi_events.setup_callbacks(); - oled_display.clearDisplay(); - toggle_device = true; DEBUG_PRINTLN("seq page init"); diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index b2cf177d1..9a2f3fa01 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -208,8 +208,6 @@ void SeqPtcPage::render_arp(bool recalc_notemask_, MidiDevice *midi_dev, void SeqPtcPage::display() { oled_display.clearDisplay(); - auto *oldfont = oled_display.getFont(); - bool is_poly = IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track); draw_knob_frame(); char buf1[4]; @@ -274,7 +272,6 @@ void SeqPtcPage::display() { if (show_seq_menu) { display_mute_mask(midi_active_peering.get_device(UART2_PORT), 8); } - oled_display.setFont(oldfont); } uint8_t SeqPtcPage::calc_scale_note(uint8_t note_num, bool padded) { diff --git a/avr/cores/megacommand/MCL/SeqStepPage.cpp b/avr/cores/megacommand/MCL/SeqStepPage.cpp index 3c48c9d20..83d411e26 100644 --- a/avr/cores/megacommand/MCL/SeqStepPage.cpp +++ b/avr/cores/megacommand/MCL/SeqStepPage.cpp @@ -117,7 +117,6 @@ void SeqStepPage::cleanup() { void SeqStepPage::display() { oled_display.clearDisplay(); - auto *oldfont = oled_display.getFont(); draw_knob_frame(); uint8_t timing_mid = mcl_seq.md_tracks[last_md_track].get_timing_mid(); @@ -186,7 +185,6 @@ void SeqStepPage::display() { page_select_page.md_prepare(); prepare = false; } - oled_display.setFont(oldfont); } void SeqStepPage::loop() { diff --git a/avr/cores/megacommand/MCL/TextInputPage.cpp b/avr/cores/megacommand/MCL/TextInputPage.cpp index 10d276ce6..ea263efed 100644 --- a/avr/cores/megacommand/MCL/TextInputPage.cpp +++ b/avr/cores/megacommand/MCL/TextInputPage.cpp @@ -146,9 +146,7 @@ void TextInputPage::display_normal() { auto time = clock_diff(last_clock, slowclock); // mcl_gui.clear_popup(); <-- E_TOOSLOW - auto oldfont = oled_display.getFont(); oled_display.fillRect(s_text_x, s_text_y, 6 * length, 8, BLACK); - oled_display.setFont(); oled_display.setCursor(s_text_x, s_text_y); oled_display.println(text); if (time < FLASH_SPEED) { @@ -163,7 +161,6 @@ void TextInputPage::display_normal() { if (time > FLASH_SPEED * 2) { last_clock = slowclock; } - oled_display.setFont(oldfont); } void TextInputPage::display_charpane() { From 26823c29195b6b56ab7f4f926ae762a302d74fa7 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 11:12:24 +1100 Subject: [PATCH 111/133] more clearDisplay cleanups --- avr/cores/megacommand/MCL/ArpPage.cpp | 2 +- avr/cores/megacommand/MCL/FileBrowserPage.cpp | 2 +- avr/cores/megacommand/MCL/GridPage.cpp | 1 - avr/cores/megacommand/MCL/LFOPage.cpp | 1 - avr/cores/megacommand/MCL/MixerPage.cpp | 1 - avr/cores/megacommand/MCL/RAMPage.cpp | 2 +- avr/cores/megacommand/MCL/SampleBrowserPage.cpp | 1 + 7 files changed, 4 insertions(+), 6 deletions(-) diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp index 2f65b96e1..8d544ba13 100644 --- a/avr/cores/megacommand/MCL/ArpPage.cpp +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -56,7 +56,7 @@ void ArpPage::track_update(uint8_t n, bool re_render) { last_arp_track = arp_track; } -void ArpPage::cleanup() { oled_display.clearDisplay(); } +void ArpPage::cleanup() {} void ArpPage::loop() { uint8_t n = current_track; diff --git a/avr/cores/megacommand/MCL/FileBrowserPage.cpp b/avr/cores/megacommand/MCL/FileBrowserPage.cpp index 1ed9e1163..729f65977 100644 --- a/avr/cores/megacommand/MCL/FileBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/FileBrowserPage.cpp @@ -172,7 +172,6 @@ void FileBrowserPage::draw_menu() { void FileBrowserPage::draw_sidebar() { constexpr uint8_t x_offset = 43; oled_display.clearDisplay(); - oled_display.setFont(&TomThumb); oled_display.setCursor(0, 8); oled_display.setTextColor(WHITE, BLACK); oled_display.println(title); @@ -220,6 +219,7 @@ void FileBrowserPage::draw_filebrowser() { } void FileBrowserPage::display() { + oled_display.setFont(&TomThumb); if (filemenu_active) { draw_menu(); return; diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index 63e9e5bf5..f83a964eb 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -28,7 +28,6 @@ void GridPage::init() { } trig_interface.off(); //load_slot_models(); - oled_display.clearDisplay(); R.Clear(); R.use_machine_names_short(); R.use_icons_knob(); diff --git a/avr/cores/megacommand/MCL/LFOPage.cpp b/avr/cores/megacommand/MCL/LFOPage.cpp index fc5578959..935ee2a1d 100644 --- a/avr/cores/megacommand/MCL/LFOPage.cpp +++ b/avr/cores/megacommand/MCL/LFOPage.cpp @@ -31,7 +31,6 @@ void LFOPage::init() { void LFOPage::cleanup() { PerfPageParent::cleanup(); trig_interface.off(); - oled_display.clearDisplay(); } void LFOPage::config_encoder_range(uint8_t i) { diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index ed88cf26f..b9ecafa94 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -88,7 +88,6 @@ void MixerPage::init() { void MixerPage::cleanup() { // md_exploit.off(); - oled_display.clearDisplay(); MD.set_key_repeat(1); disable_record_mutes(); trig_interface.off(); diff --git a/avr/cores/megacommand/MCL/RAMPage.cpp b/avr/cores/megacommand/MCL/RAMPage.cpp index 2495178cd..c60d823c0 100644 --- a/avr/cores/megacommand/MCL/RAMPage.cpp +++ b/avr/cores/megacommand/MCL/RAMPage.cpp @@ -48,7 +48,7 @@ void RAMPage::init() { R.use_icons_knob(); } -void RAMPage::cleanup() { oled_display.clearDisplay(); } +void RAMPage::cleanup() { } void RAMPage::setup_sequencer(uint8_t track) { USE_LOCK(); diff --git a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp index cb6bffde7..a3ab78017 100644 --- a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp @@ -20,6 +20,7 @@ void SampleBrowserPage::setup() { } void SampleBrowserPage::display() { + oled_display.setFont(&TomThumb); if (filemenu_active) { draw_menu(); return; From 67e793dd9307c7b62960e82b7b3aff47e040eb4b Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 11:28:06 +1100 Subject: [PATCH 112/133] USB Mode popups optimise --- avr/cores/megacommand/MCL/MCLSysConfig.cpp | 65 +++++++++++----------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLSysConfig.cpp b/avr/cores/megacommand/MCL/MCLSysConfig.cpp index bae1c4a7d..c3cc3fca3 100644 --- a/avr/cores/megacommand/MCL/MCLSysConfig.cpp +++ b/avr/cores/megacommand/MCL/MCLSysConfig.cpp @@ -1,59 +1,56 @@ #include "MCL_impl.h" - -void usb_wait() { +// Consolidated display function to reduce code duplication +static void show_message(const char* line1) { oled_display.clearDisplay(); - oled_display.textbox("PLEASE WAIT", ""); + oled_display.textbox(line1, ""); oled_display.display(); +} + +// Common wait routine +static inline void usb_wait() { + show_message("PLEASE WAIT"); delay(4000); } -bool megacmd_check() { +// Simplified megacmd check +static inline bool megacmd_check() { if (!IS_MEGACMD()) { - oled_display.textbox("MODE ", "N/A"); - oled_display.display(); + show_message("MODE N/A"); return false; } return true; } -void usb_os_update() { +// Combined USB mode change function +static void enter_usb_mode(uint8_t mode, const char* line1) { usb_wait(); - change_usb_mode(USB_SERIAL); - oled_display.clearDisplay(); - oled_display.textbox("OS UPDATE", ""); - oled_display.display(); - while (1) - ; + show_message(line1); + + if (mode == USB_STORAGE) { + LOCAL_SPI_DISABLE(); + EXTERNAL_SPI_ENABLE(); + } + + change_usb_mode(mode); + while (1); // Infinite loop +} + +// Optimized public functions +void usb_os_update() { + enter_usb_mode(USB_SERIAL, "OS UPDATE"); } void usb_dfu_mode() { - usb_wait(); - oled_display.clearDisplay(); - oled_display.textbox("DFU ", "MODE"); - oled_display.display(); - //DFU mode is activated via datalines between CPUs - SET_USB_MODE(USB_DFU); - while (1) - ; + enter_usb_mode(USB_DFU, "DFU MODE"); } void usb_disk_mode() { - if (!megacmd_check()) { - return; + if (megacmd_check()) { + enter_usb_mode(USB_STORAGE, "USB DISK"); } - usb_wait(); - oled_display.clearDisplay(); - - oled_display.textbox("USB ", "DISK"); - oled_display.display(); - - LOCAL_SPI_DISABLE(); - EXTERNAL_SPI_ENABLE(); - change_usb_mode(USB_STORAGE); - while (1) - ; } + void mclsys_apply_config() { DEBUG_PRINT_FN(); GUI.display_mirror = mcl_cfg.display_mirror; From 48bd31e5b6b7bf3757a229b7bd12845728bc3a02 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 16:07:07 +1100 Subject: [PATCH 113/133] memset --- avr/cores/megacommand/MCL/MCLActions.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLActions.cpp b/avr/cores/megacommand/MCL/MCLActions.cpp index b59d3752f..c06a79263 100644 --- a/avr/cores/megacommand/MCL/MCLActions.cpp +++ b/avr/cores/megacommand/MCL/MCLActions.cpp @@ -919,11 +919,7 @@ void MCLActions::calc_latency() { midi_active_peering.get_device(UART2_PORT), }; - for (uint8_t a = 0; a < NUM_DEVS; a++) { - dev_latency[a].latency = 0; - dev_latency[a].div32th_latency = 0; - dev_latency[a].div192th_latency = 0; - } + memset(dev_latency,0,sizeof(dev_latency)); bool send_dev[NUM_DEVS] = {0}; From 603bbf1e7b2e095bdda5bc1e7eb91e079095a256 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 16:19:22 +1100 Subject: [PATCH 114/133] Remove unused --- avr/cores/megacommand/MCL/SeqPage.cpp | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index 512f68263..e6ba45983 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -289,33 +289,6 @@ bool SeqPage::display_mute_mask(MidiDevice* device, uint8_t offset) { bool SeqPage::handleEvent(gui_event_t *event) { - if (note_interface.is_event(event)) { - uint8_t port = event->port; - MidiDevice *device = midi_active_peering.get_device(port); - - uint8_t track = event->source - 128; - - //Removing this block causes progmem to balloon by 1K ?? - if (BUTTON_DOWN(Buttons.BUTTON4)) { - // calculate the intended seq length. - uint8_t step = track; - step += 1 + page_select * 16; - encoders[2]->cur = step; - note_interface.ignoreNextEvent(track); - if (event->mask == EVENT_BUTTON_RELEASED) { - note_interface.clear_note(track); - } - GUI.ignoreNextEvent(Buttons.BUTTON4); - if (BUTTON_DOWN(Buttons.BUTTON3)) { - GUI.ignoreNextEvent(Buttons.BUTTON3); - } - - return true; - } - // notify derived class about unhandled TI event - return false; - } // end TI events - if (EVENT_CMD(event)) { if (trig_interface.is_key_down(MDX_KEY_PATSONG)) { return seq_menu_page.handleEvent(event); From 8426276b812c615fe20a549c63967cc85c83fb41 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 21:28:29 +1100 Subject: [PATCH 115/133] GridChainTrack not used --- avr/cores/megacommand/MCL/DeviceTrack.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/avr/cores/megacommand/MCL/DeviceTrack.cpp b/avr/cores/megacommand/MCL/DeviceTrack.cpp index 7c9795cb7..32106f787 100644 --- a/avr/cores/megacommand/MCL/DeviceTrack.cpp +++ b/avr/cores/megacommand/MCL/DeviceTrack.cpp @@ -31,9 +31,9 @@ DeviceTrack *DeviceTrack::init_track_type(uint8_t track_type) { case MNM_TRACK_TYPE: ::new (this) MNMTrack; break; - case GRIDCHAIN_TRACK_TYPE: - ::new (this) GridChainTrack; - break; +// case GRIDCHAIN_TRACK_TYPE: +// ::new (this) GridChainTrack; +// break; case PERF_TRACK_TYPE: ::new (this) PerfTrack; break; From 5474711f8365b4401db9f007239eddb2718d7b6b Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 22:18:32 +1100 Subject: [PATCH 116/133] init not required --- avr/cores/megacommand/MCL/MCLActions.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLActions.cpp b/avr/cores/megacommand/MCL/MCLActions.cpp index c06a79263..4a718a4a9 100644 --- a/avr/cores/megacommand/MCL/MCLActions.cpp +++ b/avr/cores/megacommand/MCL/MCLActions.cpp @@ -30,12 +30,6 @@ void MCLActions::setup() { // DEBUG_PRINTLN(F("mcl actions setup")); mcl_actions_callbacks.setup_callbacks(); mcl_actions_midievents.setup_callbacks(); - for (uint8_t i = 0; i < NUM_SLOTS; i++) { - next_transitions[i] = 0; - transition_offsets[i] = 0; - send_machine[i] = 0; - transition_level[i] = 0; - } } void MCLActions::init_chains() { From 3809a8d7a04ad5d29088557f7d66d72ad3adc55d Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 22:21:58 +1100 Subject: [PATCH 117/133] Warning --- avr/cores/megacommand/MCL/OscPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/OscPage.cpp b/avr/cores/megacommand/MCL/OscPage.cpp index 4afc3bafb..8680922fd 100644 --- a/avr/cores/megacommand/MCL/OscPage.cpp +++ b/avr/cores/megacommand/MCL/OscPage.cpp @@ -187,7 +187,7 @@ void OscPage::draw_wav(uint8_t wav_type) { SawOsc saw_osc(w, osc_width); SineOsc sine_osc(w); UsrOsc usr_osc(w); - float sample; + float sample = 0; float max_sine_gain = 0.0004921259843f; // (float)1 / (float)16 / 127; uint8_t n = sample_number; // for (uint8_t n = 0; n < 128 - x; n++) { From 69e5aefcc683681ecddb255162e3aee5b540db07 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 23 Oct 2024 23:24:50 +1100 Subject: [PATCH 118/133] fix font in show_menu --- avr/cores/megacommand/MCL/PerfPage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/avr/cores/megacommand/MCL/PerfPage.cpp b/avr/cores/megacommand/MCL/PerfPage.cpp index 67594bd20..0e00a6f41 100644 --- a/avr/cores/megacommand/MCL/PerfPage.cpp +++ b/avr/cores/megacommand/MCL/PerfPage.cpp @@ -213,6 +213,7 @@ void PerfPage::loop() { } void PerfPage::display() { + oled_display.setFont(&TomThumb); if (show_menu) { constexpr uint8_t width = 52; oled_display.fillRect(128 - width - 2, 0, width + 2, 32, BLACK); From 8dd6720fd89b6130e3c39ac35c9b0f492cffe058 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 24 Oct 2024 11:17:47 +1100 Subject: [PATCH 119/133] Menu option for Driver 1 --- avr/cores/megacommand/resources/R.h | 8 +- .../megacommand/resources/R_menu_layouts.cpp | 187 +++++++++--------- .../megacommand/resources/R_menu_options.cpp | 10 +- resource/menu_layouts.cpp | 2 +- resource/menu_options.cpp | 4 +- 5 files changed, 110 insertions(+), 101 deletions(-) diff --git a/avr/cores/megacommand/resources/R.h b/avr/cores/megacommand/resources/R.h index 69b461a2c..40e86043d 100644 --- a/avr/cores/megacommand/resources/R.h +++ b/avr/cores/megacommand/resources/R.h @@ -465,11 +465,11 @@ extern const unsigned char __R_menu_options[] PROGMEM; struct __T_menu_options { union { menu_option_t MENU_OPTIONS[0]; - char zz__MENU_OPTIONS[1116]; + char zz__MENU_OPTIONS[1134]; }; - static constexpr size_t countof_MENU_OPTIONS = 1116 / sizeof(menu_option_t); - static constexpr size_t sizeofof_MENU_OPTIONS = 1116; - static constexpr size_t __total_size = 1116; + static constexpr size_t countof_MENU_OPTIONS = 1134 / sizeof(menu_option_t); + static constexpr size_t sizeofof_MENU_OPTIONS = 1134; + static constexpr size_t __total_size = 1134; }; extern const unsigned char __R_page_entries[] PROGMEM; diff --git a/avr/cores/megacommand/resources/R_menu_layouts.cpp b/avr/cores/megacommand/resources/R_menu_layouts.cpp index 23966ea7f..324fab513 100644 --- a/avr/cores/megacommand/resources/R_menu_layouts.cpp +++ b/avr/cores/megacommand/resources/R_menu_layouts.cpp @@ -830,228 +830,229 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 61, 182, 189, - 84, + 124, 20, 12, 50, 147, 4, - 48, - 49, + 44, + 84, + 24, 97, - 120, + 188, 119, - 19, + 9, 26, - 109, + 182, 62, 56, - 225, + 240, 210, + 130, 215, - 5, - 207, + 231, 210, 26, - 174, + 215, 32, 130, - 133, + 66, 70, 183, - 96, + 176, 118, - 199, + 99, 33, 205, - 6, + 131, 80, - 24, + 12, 100, - 92, + 46, 35, - 115, + 57, 121, + 205, 207, - 155, 231, + 176, 71, - 96, 20, - 48, + 24, 36, - 161, + 80, 17, + 130, 27, - 5, - 128, + 192, 20, - 198, + 99, 34, 141, - 140, + 70, 56, - 22, + 11, 20, - 3, + 1, + 131, 37, - 6, 107, - 142, - 109, + 71, 109, + 54, 40, 76, - 129, + 192, 24, - 223, + 239, 38, 126, + 180, 65, - 104, 23, - 50, + 25, 139, - 237, + 118, 32, 35, - 104, + 180, 138, - 86, + 43, 123, 189, - 118, + 59, 62, 168, - 220, + 110, 122, 90, - 21, + 10, 240, - 182, + 219, 116, 75, 210, - 78, + 39, 1, 255, - 230, + 115, 196, 174, - 88, - 91, + 44, + 45, 196, 65, + 174, 52, - 93, 131, + 133, 74, - 10, 220, - 48, + 24, 243, - 105, + 52, 25, + 139, 245, - 22, 19, - 18, - 154, + 9, + 77, 34, 2, - 49, + 24, 120, - 97, + 176, 210, - 119, + 187, 26, 168, - 70, + 163, 65, 170, - 180, + 90, 93, - 10, + 5, 104, - 149, + 74, 84, - 135, + 195, 193, + 179, 27, - 102, 146, - 56, + 28, 3, - 45, + 22, 119, 80, - 135, + 195, 41, + 164, 29, - 72, 223, - 108, + 54, 62, - 12, - 78, + 6, + 39, 146, - 193, + 96, 101, - 97, + 176, 136, - 19, + 137, + 198, 0, - 141, 66, 192, - 96, + 176, 14, - 198, + 99, 79, 107, - 180, + 90, 100, - 48, + 24, 62, - 212, + 106, 80, - 146, + 73, 203, - 222, + 111, 127, 68, 70, 85, - 49, + 24, 99, - 72, + 164, 224, - 11, + 5, + 169, 169, - 83, 12, - 174, + 215, + 88, 88, - 176, 75, 20, - 24, + 12, 28, - 182, + 91, 7, 88, - 13, + 6, 182, - 89, + 172, 10, - 11, + 133, + 192, 169, - 128, 0, 0, 0, 0, - 1, - 63, + 0, + 159, 255, }; diff --git a/avr/cores/megacommand/resources/R_menu_options.cpp b/avr/cores/megacommand/resources/R_menu_options.cpp index e76a13cda..2a29d177d 100644 --- a/avr/cores/megacommand/resources/R_menu_options.cpp +++ b/avr/cores/megacommand/resources/R_menu_options.cpp @@ -475,13 +475,19 @@ const unsigned char __R_menu_options[] PROGMEM = { 80, 10, 92, - 196, + 208, 128, + 132, + 103, + 216, + 77, + 45, + 32, 0, 0, 0, 0, 0, - 19, + 159, 255, }; diff --git a/resource/menu_layouts.cpp b/resource/menu_layouts.cpp index bb0041734..6c8aba518 100644 --- a/resource/menu_layouts.cpp +++ b/resource/menu_layouts.cpp @@ -79,7 +79,7 @@ menu_t midiport_menu_layout = { {"TURBO 1:", 0, 4, 4, 2, NULL_PAGE, 0, 2}, {"TURBO 2:", 0, 4, 4, 3, NULL_PAGE, 0, 2}, {"TURBO USB:", 0, 4, 4, 55, NULL_PAGE , 0, 2}, - {"DRIVER 1:", 0, 2, 2, 61, 0, NULL_PAGE, 84}, + {"DRIVER 1:", 0, 2, 2, 61, 0, NULL_PAGE, 124}, {"DRIVER 2:", 0, 2, 2, 4, 0, NULL_PAGE, 84}, {"CTRL PORT:", 1, 4, 4, 56, NULL_PAGE, 0, 100}, }, diff --git a/resource/menu_options.cpp b/resource/menu_options.cpp index 16feb47cd..6d9172cb5 100644 --- a/resource/menu_options.cpp +++ b/resource/menu_options.cpp @@ -71,6 +71,8 @@ menu_option_t MENU_OPTIONS[] = { // 121 {128, "--"}, // 122 - {0, "--"}, {1,"PERF"} + {0, "--"}, {1,"PERF"}, + // 124 + {0, "GENER"}, {1,"MD"} }; From a3303ac0deacf94404ebf6b2ab016e835106c836 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 25 Oct 2024 13:06:40 +1100 Subject: [PATCH 120/133] Simplify switch_mute_state --- Changelog | 22 ++++++------ avr/cores/megacommand/MCL/MCL.h | 2 +- avr/cores/megacommand/MCL/MixerPage.cpp | 45 +++++++++++++------------ avr/cores/megacommand/MCL/MixerPage.h | 4 +-- avr/cores/megacommand/MCL/PerfTrack.cpp | 10 +++--- 5 files changed, 43 insertions(+), 40 deletions(-) diff --git a/Changelog b/Changelog index d97126127..e27c1c493 100644 --- a/Changelog +++ b/Changelog @@ -10,33 +10,33 @@ Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.6 - Grid Page: It's now possible to reconfigure the Grid Page Encoders to act as the four - Performance Controllers. Via option: Config -> Page -> Grid Encod + Performance Controllers. Via option: Config -> Page Setup -> Grid Encod When selecting multiple rows for copy/clear/paste operations the corresponding Bank/Pattern id is now displayed on the left. - Mixer Page: - Performance States (formely Mute Sets): + Performance States (formerly Mute Sets): As previously, there are 4 Performance State, each mapped to an individual [Arrow Key]. Each Performance State contains Mutes for each device, and 4 Performance Controller Locks - Performance States Manual Load (for a single device): - - Press [ Scale ] to toggle the Mixer Page's active device (MD or External MIDI) - - To load a Performance State for the Mixer Page's active device, hold down an [ Arrow ] Key and press [ YES ] - - To load a Performance State for both devices simultaneously (MD + External MIDI), hold down [ YES ] and then press an [ Arrow ]. + Press [Scale] to toggle between the Mixer's active device between MD and External MIDI. + + The Mutes, in a Performance State can be permanently disabled for the active device by holding an [Up/Down/Left/Right] key and pressing [Mute/BankA] + + Performance States Manual Load: + - To load a Performance State hold down an [Up/Down/Left/Right] Key and press [YES] Performance State Autoload: A chosen Performance State can now be made to auto-load when the Perf Slot in Grid Y is loaded: - - From the Mixer Page, Hold an [ Arrow ] key to visually preview the Performance State and then press [ Accent / BANKB ] to enable auto "LOAD". + - From the Mixer Page, Hold an [ Arrow ] key to visually preview the Performance State and then press [Accent/BANKB] to enable auto "LOAD". - Then save the Perf Slot, in Grid Y. - The Mutes, in a Performance State can be permanantly disabled for the active device by holding an [ Arrow ] key and pressing [ Mute / BankA ] - Performance Controller AutoFill: - - A Perf Controller's assigned right scenes can be auto-filled with modified Kit parameters by holding down the MCL < Encoder Button > - and pressing the MC's < Yes / Load > button. + - A Perf Controller's assigned right scenes can be auto-filled with modified Kit parameters by holding down the MCL + and pressing the MC's button. - A Perf Controller's assigned right scenes can be auto-cleared with by holding down the MCL and pressing the MC's < Shift > button. diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index 276c2b141..3504eb243 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -17,7 +17,7 @@ #include "Fonts/TomThumb.h" #define VERSION 4060 -#define VERSION_STR "G4.60" +#define VERSION_STR "L4.60" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index b9ecafa94..94df8bfd2 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -20,7 +20,7 @@ void MixerPage::oled_draw_mutes() { uint8_t fader_x = 0; bool draw = true; - if (preview_mute_set != 255 && load_types[!is_md_device][preview_mute_set] == 0) { draw = false; } + if (preview_mute_set != 255 && load_types[preview_mute_set][!is_md_device] == 0) { draw = false; } for (uint8_t i = 0; i < len; ++i) { // draw routing SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[i] @@ -286,7 +286,7 @@ void MixerPage::display() { seq_step_page.mute_mask) { uint16_t mask = mute_sets[!is_md_device].mutes[mute_set]; - if (load_types[!is_md_device][mute_set] == 0) { mask = 0; } + if (load_types[mute_set][!is_md_device] == 0) { mask = 0; } if (!is_md_device) { mask &= 0b111111; } @@ -417,20 +417,17 @@ void MixerPage::populate_mute_set() { } } -void MixerPage::switch_mute_set(uint8_t state, bool all_devices, bool load_perf, bool load_mutes) { +void MixerPage::switch_mute_set(uint8_t state, bool load_perf, bool *load_type) { MidiDevice *devs[2] = { midi_active_peering.get_device(UART1_PORT), midi_active_peering.get_device(UART2_PORT), }; - - uint8_t focus_device = (midi_device == &MD); - - if (load_mutes) { + if (load_type != nullptr) { for (uint8_t dev = 0; dev < 2; dev++) { bool is_md_device = dev == 0; - if (!all_devices && focus_device != dev) continue; + if (!load_type[dev]) continue; uint8_t len = (is_md_device) ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; @@ -538,7 +535,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; if (event->mask == EVENT_BUTTON_PRESSED && track < len) { if (note_interface.is_note(track)) { - if (show_mixer_menu || preview_mute_set != 255 && load_types[!is_md_device][preview_mute_set] || ext_key_down) { + if (show_mixer_menu || preview_mute_set != 255 && load_types[preview_mute_set][!is_md_device] || ext_key_down) { if (ext_key_down) { mute_toggle = 1; } SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[track] @@ -641,8 +638,8 @@ bool MixerPage::handleEvent(gui_event_t *event) { } case MDX_KEY_BANKA: { if (preview_mute_set != 255) { - load_types[!is_md_device][preview_mute_set] = !load_types[!is_md_device][preview_mute_set]; - if (load_types[!is_md_device][preview_mute_set] == 0) { seq_step_page.mute_mask = 0; } + load_types[preview_mute_set][!is_md_device] = !load_types[preview_mute_set][!is_md_device]; + if (load_types[preview_mute_set][!is_md_device] == 0) { seq_step_page.mute_mask = 0; } redraw_mutes = true; return true; } @@ -663,19 +660,25 @@ bool MixerPage::handleEvent(gui_event_t *event) { switch_mute_set(4); //---> Flip mutes break; } + uint8_t set = 255; + if (trig_interface.is_key_down(MDX_KEY_LEFT)) { - switch_mute_set(1,true,true,load_types[!is_md_device][1]); - break; + set = 1; } else if (trig_interface.is_key_down(MDX_KEY_UP)) { - switch_mute_set(2,true,true,load_types[!is_md_device][2]); - break; + set = 2; } else if (trig_interface.is_key_down(MDX_KEY_RIGHT)) { - switch_mute_set(3,true,true,load_types[!is_md_device][3]); - break; + set = 3; } else if (trig_interface.is_key_down(MDX_KEY_DOWN)) { - switch_mute_set(0,true,true,load_types[!is_md_device][0]); - break; - } else { + set = 0; + } + if (set != 255) { + //bool load_t[2]; + //load_t[0] = load_types[key][0]; + //load_t[1] = load_types[key][1]; + //load_t[is_md_device] = 0; + switch_mute_set(1,true,load_types[set]); + } + else { if (!note_interface.notes_on) { seq_step_page.mute_mask = 0; show_mixer_menu = true; @@ -691,7 +694,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { case MDX_KEY_DOWN: { uint8_t set = get_mute_set(key); if (trig_interface.is_key_down(MDX_KEY_YES)) { - switch_mute_set(set,false,true,load_types[!is_md_device][set]); + switch_mute_set(set,true,load_types[set]); } else { preview_mute_set = set; for (uint8_t n = 0; n < 4; n++) { diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index 8d0b7f001..e50d33179 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -57,7 +57,7 @@ class MixerPage : public LightPage { // Don't change order MuteSet mute_sets[2]; uint8_t perf_locks[4][4]; - bool load_types[2][4]; + bool load_types[4][2]; // uint8_t perf_locks_temp[4]; @@ -82,7 +82,7 @@ class MixerPage : public LightPage { void record_mutes_set(bool state); void disable_record_mutes(bool clear = false); void oled_draw_mutes(); - void switch_mute_set(uint8_t state, bool all_devices = true, bool load_perf = false, bool load_mutes = true); + void switch_mute_set(uint8_t state, bool load_perf = false, bool *load_types = nullptr); void populate_mute_set(); void load_perf_locks(uint8_t state); diff --git a/avr/cores/megacommand/MCL/PerfTrack.cpp b/avr/cores/megacommand/MCL/PerfTrack.cpp index 30e11c571..6b6732219 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.cpp +++ b/avr/cores/megacommand/MCL/PerfTrack.cpp @@ -39,10 +39,10 @@ void PerfTrack::get_perf() { encs[n].cur = e->cur; memcpy(encs[n].name,e->name, PERF_NAME_LENGTH); - if (!mixer_page.load_types[0][n]) { + if (!mixer_page.load_types[n][0]) { CLEAR_BIT16(mute_sets[1].mutes[n],13); } - if (!mixer_page.load_types[1][n]) { + if (!mixer_page.load_types[n][1]) { CLEAR_BIT16(mute_sets[1].mutes[n],14); } @@ -76,8 +76,8 @@ void PerfTrack::load_perf(bool immediate, SeqTrack *seq_track) { if ((mute_sets[1].mutes[n] & 0b1000000000000000) == 0) { mixer_page.load_mute_set = n; } - mixer_page.load_types[0][n] = mute_sets[1].mutes[n] & 0b0010000000000000; - mixer_page.load_types[1][n] = mute_sets[1].mutes[n] & 0b0100000000000000; + mixer_page.load_types[n][0] = mute_sets[1].mutes[n] & 0b0010000000000000; + mixer_page.load_types[n][1] = mute_sets[1].mutes[n] & 0b0100000000000000; mute_sets[1].mutes[n] |= 0b1110000000000000; } @@ -85,7 +85,7 @@ void PerfTrack::load_perf(bool immediate, SeqTrack *seq_track) { memcpy(mixer_page.mute_sets, mute_sets, sizeof(mute_sets) + sizeof(perf_locks)); if (mixer_page.load_mute_set < 4) { - mixer_page.switch_mute_set(mixer_page.load_mute_set, true, immediate, mixer_page.load_types[mixer_page.load_mute_set]); //Mute change is applied outside of sequencer runtime. + mixer_page.switch_mute_set(mixer_page.load_mute_set, immediate, mixer_page.load_types[mixer_page.load_mute_set]); //Mute change is applied outside of sequencer runtime. if (!immediate) { PerfSeqTrack *p = (PerfSeqTrack*) seq_track; memcpy(p->perf_locks, &perf_locks[mixer_page.load_mute_set],4); //Perf change is pre-empted at sequencer runtime. From 0f1b1389081d5c1da20089d230a7198711f44615 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sat, 26 Oct 2024 13:27:14 +1100 Subject: [PATCH 121/133] fixes --- avr/cores/megacommand/MCL/MCL.h | 2 +- avr/cores/megacommand/MCL/MixerPage.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index 3504eb243..12d5ea45b 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -17,7 +17,7 @@ #include "Fonts/TomThumb.h" #define VERSION 4060 -#define VERSION_STR "L4.60" +#define VERSION_STR "M4.60" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 94df8bfd2..c3a79bcc4 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -657,7 +657,9 @@ bool MixerPage::handleEvent(gui_event_t *event) { if (preview_mute_set == 255 && trig_interface.is_key_down(MDX_KEY_FUNC) && note_interface.notes_on == 0) { - switch_mute_set(4); //---> Flip mutes + bool load_t[2] = { 0, 0 }; + load_t[!is_md_device] = 1; + switch_mute_set(4,false,load_t); //---> Flip mutes break; } uint8_t set = 255; @@ -676,7 +678,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { //load_t[0] = load_types[key][0]; //load_t[1] = load_types[key][1]; //load_t[is_md_device] = 0; - switch_mute_set(1,true,load_types[set]); + switch_mute_set(set,true,load_types[set]); } else { if (!note_interface.notes_on) { From 0d6a9f107d1e09949687204b47e7cf9efd8f34ca Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 28 Oct 2024 12:30:04 +1100 Subject: [PATCH 122/133] remove redundant code, perf_encoder_temp was causing crash on MixerPage --- avr/cores/megacommand/MCL/GridPage.cpp | 1 - avr/cores/megacommand/MCL/MixerPage.cpp | 24 ++---------------------- avr/cores/megacommand/MCL/MixerPage.h | 3 --- 3 files changed, 2 insertions(+), 26 deletions(-) diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index f83a964eb..b18a0d181 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -159,7 +159,6 @@ void GridPage::loop() { } else { if (mcl_cfg.grid_page_mode == PERF_ENC) { if (encoders[0]->hasChanged() || encoders[1]->hasChanged() || encoders[2]->hasChanged() || encoders[3]->hasChanged()) { - // mixer_page.encoder_entry_page = GRID_PAGE; //mcl.setPage(MIXER_PAGE); draw_encoders_lastclock = slowclock; draw_encoders = true; diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index c3a79bcc4..c73d0cefb 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -12,7 +12,6 @@ void MixerPage::set_display_mode(uint8_t param) { } void MixerPage::oled_draw_mutes() { - if (encoder_entry_page != NULL_PAGE) { return; } bool is_md_device = (midi_device == &MD); @@ -77,7 +76,6 @@ void MixerPage::init() { redraw_mask = -1; seq_step_page.mute_mask++; show_mixer_menu = 0; - memset(perf_locks_temp, 255, sizeof(perf_locks_temp)); // populate_mute_set(); draw_encoders = false; redraw_mutes = true; @@ -93,7 +91,6 @@ void MixerPage::cleanup() { trig_interface.off(); ext_key_down = 0; mute_toggle = 0; - encoder_entry_page = NULL_PAGE; } void MixerPage::set_level(int curtrack, int value) { @@ -154,10 +151,6 @@ void MixerPage::loop() { } if (draw_encoders != old_draw_encoders) { if (!draw_encoders) { - if (encoder_entry_page != NULL_PAGE) { - mcl.setPage(encoder_entry_page); - return; - } redraw(); } } @@ -694,17 +687,12 @@ bool MixerPage::handleEvent(gui_event_t *event) { case MDX_KEY_UP: case MDX_KEY_RIGHT: case MDX_KEY_DOWN: { + if (trig_interface.is_key_down(MDX_KEY_NO)) { return true; } uint8_t set = get_mute_set(key); if (trig_interface.is_key_down(MDX_KEY_YES)) { switch_mute_set(set,true,load_types[set]); } else { - preview_mute_set = set; - for (uint8_t n = 0; n < 4; n++) { - if (perf_locks_temp[n] == 255 && (trig_interface.is_key_down(MDX_KEY_NO))) { - perf_locks_temp[n] = encoders[n]->cur; - encoders[n]->old = encoders[n]->cur; - } - } + preview_mute_set = set; // force redraw in display() seq_step_page.mute_mask++; } @@ -755,14 +743,6 @@ bool MixerPage::handleEvent(gui_event_t *event) { trig_interface.send_md_leds(is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); preview_mute_set = 255; redraw(); - for (uint8_t n = 0; n < 4; n++) { - MCLEncoder *enc = (MCLEncoder*) &encoders[n]; - if (perf_locks_temp[n] != 255 && (trig_interface.is_key_down(MDX_KEY_NO))) { - enc->cur = perf_locks_temp[n]; - enc->old = enc->cur; - } - perf_locks_temp[n] = 255; - } } break; } diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index e50d33179..9c5cae454 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -46,7 +46,6 @@ class MixerPage : public LightPage { bool draw_encoders; PageIndex last_page = NULL_PAGE; - PageIndex encoder_entry_page = NULL_PAGE; uint8_t current_mute_set = 255; uint8_t preview_mute_set = 255; @@ -60,8 +59,6 @@ class MixerPage : public LightPage { bool load_types[4][2]; // - uint8_t perf_locks_temp[4]; - uint8_t get_mute_set(uint8_t key); MixerPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, From 6688b9e16f8a2f26475692cdf7a1f945d83e65d4 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 28 Oct 2024 13:05:35 +1100 Subject: [PATCH 123/133] changelog --- Changelog | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Changelog b/Changelog index e27c1c493..3004baea3 100644 --- a/Changelog +++ b/Changelog @@ -18,12 +18,12 @@ Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.6 Performance States (formerly Mute Sets): - As previously, there are 4 Performance State, each mapped to an individual [Arrow Key]. - Each Performance State contains Mutes for each device, and 4 Performance Controller Locks + As previously, there are 4 Performance States, each mapped to an individual [Arrow Key]. + Each Performance State contains Mute settings for the MD and External MIDI tracks, and 4 Performance Controller Locks. - Press [Scale] to toggle between the Mixer's active device between MD and External MIDI. + Press [Scale] to toggle the Mixer's active device between MD and External MIDI. - The Mutes, in a Performance State can be permanently disabled for the active device by holding an [Up/Down/Left/Right] key and pressing [Mute/BankA] + The Mutes in a Performance State can be deactivated for the active device by holding an [Up/Down/Left/Right] key and pressing [Mute/BankA] Performance States Manual Load: - To load a Performance State hold down an [Up/Down/Left/Right] Key and press [YES] @@ -38,7 +38,7 @@ Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.6 - A Perf Controller's assigned right scenes can be auto-filled with modified Kit parameters by holding down the MCL and pressing the MC's button. - - A Perf Controller's assigned right scenes can be auto-cleared with by holding down the MCL and pressing the MC's < Shift > button. + - A Perf Controller's assigned right scenes can be cleared of paramater locks by holding down the MCL and pressing the MC's < Shift > button. - Misc: From 540778f1fa0c3a76fffe26e655183154978e7d60 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 29 Oct 2024 23:38:19 +1100 Subject: [PATCH 124/133] We need to check the channel does not exceed 16, otherwise the message could be malformed --- avr/cores/megacommand/MCL/LFOSeqTrack.cpp | 17 ++++++++- avr/cores/megacommand/Midi/MidiUartParent.h | 41 ++++++++------------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp index 90e130656..7c6afa94f 100644 --- a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp @@ -1,6 +1,6 @@ #include "MCL_impl.h" -uint8_t LFOSeqTrack::wav_tables[4][WAV_LENGTH]; +static uint8_t LFOSeqTrack::wav_tables[4][WAV_LENGTH]; void LFOSeqTrack::load_tables() { SinLFO sin_lfo; @@ -174,7 +174,20 @@ uint8_t LFOSeqTrack::get_param_offset(uint8_t dest, uint8_t param_id) { if (dest < NUM_MD_TRACKS) { return MD.kit.params[dest][param]; } else if (dest < NUM_MD_TRACKS + 4) { - return MD.kit.get_fx_param(dest - NUM_MD_TRACKS, param); + switch (dest - NUM_MD_TRACKS) { + case MD_FX_ECHO - MD_FX_ECHO: + return MD.kit.delay[param]; + break; + case MD_FX_DYN - MD_FX_ECHO: + return MD.kit.dynamics[param]; + break; + case MD_FX_REV - MD_FX_ECHO: + return MD.kit.reverb[param]; + break; + case MD_FX_EQ - MD_FX_ECHO: + return MD.kit.eq[param]; + break; + } } else { // MIDI return params[param_id].offset; diff --git a/avr/cores/megacommand/Midi/MidiUartParent.h b/avr/cores/megacommand/Midi/MidiUartParent.h index 98e1d3280..8f7d9d9fc 100644 --- a/avr/cores/megacommand/Midi/MidiUartParent.h +++ b/avr/cores/megacommand/Midi/MidiUartParent.h @@ -159,22 +159,16 @@ class MidiUartParent { */ void sendNoteOn(uint8_t channel, uint8_t note, uint8_t velocity) { -#ifdef MIDI_VALIDATE - if ((channel >= 16) || (note >= 128) || (velocity >= 128)) + if (channel >= 16) return; -#endif - uint8_t msg[3] = {(uint8_t)(MIDI_NOTE_ON | channel), note, velocity}; // noteOnCallbacks.call(msg); sendMessage(msg[0], msg[1], msg[2]); } void sendNoteOff(uint8_t channel, uint8_t note) { -#ifdef MIDI_VALIDATE - if ((channel >= 16) || (note >= 128)) + if (channel >= 16) return; -#endif - //uint8_t msg[3] = {(uint8_t)(MIDI_NOTE_OFF | channel), note, velocity}; //Send Note On VEL = 0, to leverage running status // @@ -184,55 +178,48 @@ class MidiUartParent { } void sendCC(uint8_t channel, uint8_t cc, uint8_t value) { -#ifdef MIDI_VALIDATE - if ((channel >= 16) || (note >= 128) || (velocity >= 128)) + if (channel >= 16) return; -#endif - uint8_t msg[3] = {(uint8_t)(MIDI_CONTROL_CHANGE | channel), cc, value}; // ccCallbacks.call(msg); sendMessage(msg[0], msg[1], msg[2]); } ALWAYS_INLINE() void sendProgramChange(uint8_t channel, uint8_t program) { -#ifdef MIDI_VALIDATE - if ((channel >= 16) || (note >= 128) || (velocity >= 128)) + if (channel >= 16) return; -#endif - sendMessage((uint8_t)(MIDI_PROGRAM_CHANGE | channel), program); } void sendPolyKeyPressure(uint8_t channel, uint8_t note, uint8_t pressure) { -#ifdef MIDI_VALIDATE - if ((channel >= 16) || (note >= 128) || (velocity >= 128)) + if (channel >= 16) return; -#endif - sendMessage((uint8_t)(MIDI_AFTER_TOUCH | channel), note, pressure); } void sendChannelPressure(uint8_t channel, uint8_t pressure) { -#ifdef MIDI_VALIDATE - if ((channel >= 16) || (note >= 128) || (velocity >= 128)) + if (channel >= 16) return; -#endif - sendMessage((uint8_t)(MIDI_CHANNEL_PRESSURE | channel), pressure); } void sendPitchBend(uint8_t channel, int16_t pitchbend) { - //pitchbend += 8192; + if (channel >= 16) + return; sendMessage((uint8_t)(MIDI_PITCH_WHEEL | channel), pitchbend, (pitchbend >> 7)); } void sendNRPN(uint8_t channel, uint16_t parameter, uint8_t value) { + if (channel >= 16) + return; sendCC(channel, 99, (parameter >> 7)); sendCC(channel, 98, (parameter)); sendCC(channel, 6, value); } void sendNRPN(uint8_t channel, uint16_t parameter, uint16_t value) { + if (channel >= 16) + return; sendCC(channel, 99, (parameter >> 7)); sendCC(channel, 98, (parameter)); sendCC(channel, 6, (value >> 7)); @@ -240,11 +227,15 @@ class MidiUartParent { } void sendRPN(uint8_t channel, uint16_t parameter, uint8_t value) { + if (channel >= 16) + return; sendCC(channel, 101, (parameter >> 7)); sendCC(channel, 100, (parameter)); sendCC(channel, 6, value); } void sendRPN(uint8_t channel, uint16_t parameter, uint16_t value) { + if (channel >= 16) + return; sendCC(channel, 101, (parameter >> 7)); sendCC(channel, 100, (parameter)); sendCC(channel, 6, (value >> 7)); From 46054385f436fd6059be1fdce942e78c6dbd9527 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 30 Oct 2024 00:19:39 +1100 Subject: [PATCH 125/133] static? --- avr/cores/megacommand/MCL/LFOSeqTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp index 7c6afa94f..741bc96a3 100644 --- a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp @@ -1,6 +1,6 @@ #include "MCL_impl.h" -static uint8_t LFOSeqTrack::wav_tables[4][WAV_LENGTH]; +uint8_t LFOSeqTrack::wav_tables[4][WAV_LENGTH]; void LFOSeqTrack::load_tables() { SinLFO sin_lfo; From 0bc847ef14c80ddf8f5a5b671048821b6908ae0b Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 30 Oct 2024 00:26:24 +1100 Subject: [PATCH 126/133] page index --- avr/cores/megacommand/MCL/MCL.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index 12d5ea45b..b4b75b6e1 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -79,7 +79,7 @@ enum PageIndex { class MCL { public: - static constexpr uint8_t NUM_PAGES = 42; + static constexpr uint8_t NUM_PAGES = static_cast(PageIndex::PERF_PAGE_0) + 1; static LightPage *const pages_table[NUM_PAGES] PROGMEM; From 00ef0c7e63b06c76319128eba9f36ac1480f43a7 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 31 Oct 2024 22:48:01 +1100 Subject: [PATCH 127/133] At very slow tempos, MCL would start transitions way too early, leaving a window of opportunity for GUI re-entrance --- avr/cores/megacommand/MCL/GridTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/GridTask.cpp b/avr/cores/megacommand/MCL/GridTask.cpp index 1c08d1b48..070d60988 100644 --- a/avr/cores/megacommand/MCL/GridTask.cpp +++ b/avr/cores/megacommand/MCL/GridTask.cpp @@ -118,7 +118,7 @@ void GridTask::transition_handler() { // = 0.032 * MidiClock.get_tempo() // while (MidiClock.clock_less_than( - MidiClock.div32th_counter + 0.032 * MidiClock.get_tempo(), + MidiClock.div32th_counter + 0.032 * max(60.0,MidiClock.get_tempo()), (uint32_t)mcl_actions.next_transition * 2) <= 0) { float div32th_per_second = MidiClock.get_tempo() * 0.133333333333f; From 122efd182f32e081e6189ab02a490a5b1a27cbce Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 31 Oct 2024 22:53:15 +1100 Subject: [PATCH 128/133] Changelog --- Changelog | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/Changelog b/Changelog index 3004baea3..097ba41e0 100644 --- a/Changelog +++ b/Changelog @@ -2,39 +2,38 @@ MCL 4.60 21/09/2024 Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.60. -- Sequencer: +- Sequencer: - The MD's in-built MIDI machines are now supported via the MCL sequencer. - MIDI data is transmitted on MegaCommand's MIDI Port 2. + The MD's in-built MIDI machines are now supported via the MCL sequencer. + MIDI data is transmitted on MegaCommand's MIDI Port 2. -- Grid Page: +- Grid Page: - It's now possible to reconfigure the Grid Page Encoders to act as the four - Performance Controllers. Via option: Config -> Page Setup -> Grid Encod + It's now possible to reconfigure the Grid Page Encoders to act as the four + Performance Controllers. Via option: Config -> Page Setup -> Grid Encod - When selecting multiple rows for copy/clear/paste operations the corresponding Bank/Pattern id is now displayed on the left. + When selecting multiple rows for copy/clear/paste operations the corresponding Bank/Pattern id is now displayed on the left. -- Mixer Page: +- Mixer Page: - Performance States (formerly Mute Sets): + Performance States (formerly Mute Sets): - As previously, there are 4 Performance States, each mapped to an individual [Arrow Key]. - Each Performance State contains Mute settings for the MD and External MIDI tracks, and 4 Performance Controller Locks. + As previously, there are 4 Performance States, each mapped to an individual [Arrow Key]. + Each Performance State contains Mute settings for the MD and External MIDI tracks, and 4 Performance Controller Locks. - Press [Scale] to toggle the Mixer's active device between MD and External MIDI. + Press [Scale] to toggle the Mixer's active device between MD and External MIDI. - The Mutes in a Performance State can be deactivated for the active device by holding an [Up/Down/Left/Right] key and pressing [Mute/BankA] + The Mutes in a Performance State can be deactivated for the active device by holding an [Up/Down/Left/Right] key and pressing [Mute/BankA] - Performance States Manual Load: - - To load a Performance State hold down an [Up/Down/Left/Right] Key and press [YES] + Performance States Manual Load: + - To load a Performance State hold down an [Up/Down/Left/Right] Key and press [YES] - Performance State Autoload: - A chosen Performance State can now be made to auto-load when the Perf Slot in Grid Y is loaded: + Performance State Autoload: + A chosen Performance State can now be made to auto-load when the Perf Slot in Grid Y is loaded: - From the Mixer Page, Hold an [ Arrow ] key to visually preview the Performance State and then press [Accent/BANKB] to enable auto "LOAD". - Then save the Perf Slot, in Grid Y. - Performance Controller AutoFill: - + Performance Controller AutoFill ( Kit Morph ): - A Perf Controller's assigned right scenes can be auto-filled with modified Kit parameters by holding down the MCL and pressing the MC's button. @@ -58,6 +57,10 @@ Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.6 MD's random LFO shape was broken when loading with MCL. + MCL LFO could transmit bogus MIDI data. + + MCL would crash when loading tracks at very slow tempo 30BPM. + MCL 4.51a 20/12/2023 Fixed [ Func ] + [ Clear ] regression in PianoRoll. From b19d7b4fe6134690be42e87701e09527ef1a6405 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 1 Nov 2024 11:41:16 +1100 Subject: [PATCH 129/133] Change sequencer rendering order to allow MDFX to be loaded before Perf. And Perf before trig --- avr/cores/megacommand/MCL/MCLSeq.cpp | 10 ++++++---- avr/cores/megacommand/MCL/PerfSeqTrack.cpp | 4 +--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index 131a9e492..7501fa596 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -240,11 +240,8 @@ void MCLSeq::seq() { md_arp_tracks[i].seq(uart,uart2); } - if (MDSeqTrack::md_trig_mask > 0) { - MD.parallelTrig(MDSeqTrack::md_trig_mask, uart); - } - mdfx_track.seq(); + if (MDSeqTrack::load_machine_cache) { MD.setKitName(grid_task.kit_names[0], uart); MD.loadMachinesCache(MDSeqTrack::load_machine_cache, uart); @@ -254,12 +251,17 @@ void MCLSeq::seq() { aux_tracks[i].seq(); } perf_track.seq(uart, uart2); + #ifdef LFO_TRACKS for (uint8_t i = 0; i < num_lfo_tracks; i++) { lfo_tracks[i].seq(uart, uart2); } #endif + if (MDSeqTrack::md_trig_mask > 0) { + MD.parallelTrig(MDSeqTrack::md_trig_mask, uart); + } + #ifdef EXT_TRACKS for (uint8_t i = 0; i < num_ext_tracks; i++) { ext_tracks[i].seq(uart2); diff --git a/avr/cores/megacommand/MCL/PerfSeqTrack.cpp b/avr/cores/megacommand/MCL/PerfSeqTrack.cpp index 013abc45e..dd99c91cd 100644 --- a/avr/cores/megacommand/MCL/PerfSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/PerfSeqTrack.cpp @@ -9,7 +9,7 @@ void PerfSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { } if (count_down) { count_down--; - if (count_down <= 1) { + if (count_down == 0) { if (load_sound) { for (uint8_t n = 0; n < 4; n++) { if (perf_locks[n] != 255) { @@ -22,8 +22,6 @@ void PerfSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { } load_sound = 0; } - } - if (count_down == 0) { reset(); mod12_counter = 0; } From 79eb450aa01d58d6a38a8ad8207eb2fc2c4d7ac9 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sat, 2 Nov 2024 12:13:07 +1100 Subject: [PATCH 130/133] send_tracks_to_devices does not need to cache mute state? --- avr/cores/megacommand/MCL/MCLActions.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLActions.cpp b/avr/cores/megacommand/MCL/MCLActions.cpp index 4a718a4a9..0981a1980 100644 --- a/avr/cores/megacommand/MCL/MCLActions.cpp +++ b/avr/cores/megacommand/MCL/MCLActions.cpp @@ -557,7 +557,6 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, midi_active_peering.get_device(UART2_PORT), }; - uint8_t mute_states[NUM_SLOTS]; uint8_t send_masks[NUM_SLOTS] = {0}; uint8_t row = 0; uint8_t old_grid = proj.get_grid(); @@ -585,9 +584,6 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, proj.select_grid(grid_idx); - mute_states[dst] = gdt_dst->seq_track->mute_state; - gdt_dst->seq_track->mute_state = SEQ_MUTE_ON; - row = grid_page.getRow(); if (row_array) { row = row_array[i]; @@ -637,7 +633,6 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, } } - // switch back to old grid before driving the GUI loop // note, do not re-enter grid_task -- stackoverflow GUI.removeTask(&grid_task); @@ -645,14 +640,7 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, // GUI.loop(); } GUI.addTask(&grid_task); - for (uint8_t i = 0; i < NUM_SLOTS; ++i) { - if (select_array[i] == 0) { continue; } - uint8_t dst = load_offset == 255 ? i : (i - first_slot) + load_offset; - GridDeviceTrack *gdt_dst = get_grid_dev_track(dst); - if (gdt_dst != nullptr) { - gdt_dst->seq_track->mute_state = mute_states[dst]; - } - } + /*All the tracks have been sent so clear the write queue*/ write_original = 0; From fd55bd641994f9335aae3316f1f151e2e8f07fd7 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 3 Nov 2024 14:08:04 +1100 Subject: [PATCH 131/133] rendering order --- avr/cores/megacommand/MCL/MCLSeq.cpp | 3 ++- avr/cores/megacommand/MCL/MixerPage.cpp | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index 7501fa596..31febba64 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -250,7 +250,6 @@ void MCLSeq::seq() { for (uint8_t i = 0; i < NUM_AUX_TRACKS; i++) { aux_tracks[i].seq(); } - perf_track.seq(uart, uart2); #ifdef LFO_TRACKS for (uint8_t i = 0; i < num_lfo_tracks; i++) { @@ -258,6 +257,8 @@ void MCLSeq::seq() { } #endif + perf_track.seq(uart, uart2); + if (MDSeqTrack::md_trig_mask > 0) { MD.parallelTrig(MDSeqTrack::md_trig_mask, uart); } diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index c73d0cefb..ecceb7d44 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -416,12 +416,11 @@ void MixerPage::switch_mute_set(uint8_t state, bool load_perf, bool *load_type) midi_active_peering.get_device(UART1_PORT), midi_active_peering.get_device(UART2_PORT), }; - if (load_type != nullptr) { + if (load_type != nullptr && state < 255) { for (uint8_t dev = 0; dev < 2; dev++) { bool is_md_device = dev == 0; if (!load_type[dev]) continue; - uint8_t len = (is_md_device) ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; @@ -429,7 +428,6 @@ void MixerPage::switch_mute_set(uint8_t state, bool load_perf, bool *load_type) SeqTrack *seq_track = (is_md_device) ? (SeqTrack *)&mcl_seq.md_tracks[n] : (SeqTrack *)&mcl_seq.ext_tracks[n]; - uint8_t mute_set = state; bool mute_state = IS_BIT_CLEAR16(mute_sets[dev].mutes[state], n); // Flip if (state == 4 && devs[dev] == midi_device) { From 2e2ffc799cb2d740fcfb00fb5c2fda9f37590370 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 11 Nov 2024 14:30:30 +1100 Subject: [PATCH 132/133] Changelog --- Changelog | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Changelog b/Changelog index 097ba41e0..8a056aa38 100644 --- a/Changelog +++ b/Changelog @@ -18,15 +18,15 @@ Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.6 Performance States (formerly Mute Sets): - As previously, there are 4 Performance States, each mapped to an individual [Arrow Key]. + As previously, there are 4 Performance States, each mapped to an individual [Up/Down/Left/Right] key. Each Performance State contains Mute settings for the MD and External MIDI tracks, and 4 Performance Controller Locks. Press [Scale] to toggle the Mixer's active device between MD and External MIDI. The Mutes in a Performance State can be deactivated for the active device by holding an [Up/Down/Left/Right] key and pressing [Mute/BankA] - Performance States Manual Load: - - To load a Performance State hold down an [Up/Down/Left/Right] Key and press [YES] + Apply Performance States: + - To apply a Performance State during a performance, hold down an [Up/Down/Left/Right] Key and press [YES] Performance State Autoload: A chosen Performance State can now be made to auto-load when the Perf Slot in Grid Y is loaded: @@ -34,11 +34,10 @@ Please upgrade to Machinedrum OS X.11 & Monomachine OS X.01 before using MCL 4.6 - Then save the Perf Slot, in Grid Y. Performance Controller AutoFill ( Kit Morph ): - - A Perf Controller's assigned right scenes can be auto-filled with modified Kit parameters by holding down the MCL + - A Perf Controller's assigned left + right scenes can be cleared of paramater locks by holding down the MCL and pressing the MC's < Shift > button. + - A Perf Controller's assigned right scenes can be auto-filled altered Kit parameters by holding down the MCL and pressing the MC's button. - - A Perf Controller's assigned right scenes can be cleared of paramater locks by holding down the MCL and pressing the MC's < Shift > button. - - Misc: The Port 1 MIDI driver can now be optionally changed to Generic. From c20acee82a6576ac4e3632fd7c1be2cd1eacc8e7 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 11 Nov 2024 14:31:43 +1100 Subject: [PATCH 133/133] version 4.60 --- avr/cores/megacommand/MCL/MCL.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index b4b75b6e1..1173c7864 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -17,7 +17,7 @@ #include "Fonts/TomThumb.h" #define VERSION 4060 -#define VERSION_STR "M4.60" +#define VERSION_STR "4.60" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800