From a2e8b27ae537ae54568868abae852fa637a077bd Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 1 Mar 2020 14:05:13 +1100 Subject: [PATCH 01/27] Add appegiator to Chromatic Page --- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 123 ++++++++++++++++++++--- avr/cores/megacommand/MCL/SeqPtcPage.h | 20 +++- 2 files changed, 127 insertions(+), 16 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index d21a0e382..7475a94d1 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -45,6 +45,7 @@ void SeqPtcPage::setup() { SeqPage::setup(); init_poly(); midi_events.setup_callbacks(); + setup_arp(); } void SeqPtcPage::cleanup() { SeqPage::cleanup(); @@ -191,7 +192,7 @@ void ptc_pattern_len_handler(Encoder *enc) { void SeqPtcPage::loop() { if (re_init) { - init(); + init(); } #ifdef EXT_TRACKS if (ptc_param_oct.hasChanged() || ptc_param_scale.hasChanged()) { @@ -357,7 +358,8 @@ uint8_t SeqPtcPage::get_next_voice(uint8_t pitch) { uint8_t voice = 255; uint8_t count = 0; - if (poly_max == 0 || (!IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track) && (mcl_cfg.uart2_ctrl_mode == 0))) { + if (poly_max == 0 || (!IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track) && + (mcl_cfg.uart2_ctrl_mode == 0))) { return last_md_track; } // If track previously played pitch, re-use this track @@ -448,6 +450,96 @@ void SeqPtcPage::trig_md_fromext(uint8_t note_num) { void SeqPtcPage::queue_redraw() { deferred_timer = slowclock; } +void SeqPtcPage::setup_arp() { + arp_enabled = true; + arp_idx = 0; + MidiClock.addOn16Callback( + this, (midi_clock_callback_ptr_t)&SeqPtcPage::on_16_callback); +} + +void SeqPtcPage::remove_arp() { + arp_enabled = false; + MidiClock.removeOn16Callback( + this, (midi_clock_callback_ptr_t)&SeqPtcPage::on_16_callback); +} + +uint8_t SeqPtcPage::arp_get_next_note_up(uint8_t cur) { + + for (uint8_t i = cur + 1; i < NUM_MD_TRACKS; i++) { + if (note_interface.notes[i] == 1) { + return i; + } + } + for (uint8_t i = 0; i <= cur; i++) { + if (note_interface.notes[i] == 1) { + return i; + } + } + return 255; +} + +uint8_t SeqPtcPage::arp_get_next_note_down(uint8_t cur) { + + for (uint8_t i = cur - 1; i > 0; i--) { + if (note_interface.notes[i] == 1) { + return i; + } + } + for (uint8_t i = NUM_MD_TRACKS - 1; i >= cur; i--) { + if (note_interface.notes[i] == 1) { + return i; + } + } + return 255; +} + +void SeqPtcPage::on_16_callback() { + bool trig = false; + uint8_t note; + + switch (arp_speed) { + case 0: + trig = true; + break; + case 1: + if ((arp_count == 0) || (arp_count == 2) || (arp_count == 4) || + (arp_count == 6)) { + trig = true; + } + break; + case 2: + if ((arp_count == 0) || (arp_count == 4)) { + trig = true; + } + break; + case 3: + if (arp_count == 0) { + trig = true; + } + } + + if (trig == true) { + switch (arp_mode) { + case ARP_UP: + note = arp_get_next_note_up(arp_idx); + break; + case ARP_DOWN: + note = arp_get_next_note_down(arp_idx); + break; + } + if (note < NUM_MD_TRACKS) { + arp_idx = note; + uint8_t pitch = calc_pitch(note); + trig_md(note, pitch); + } + } + + arp_count++; + if (arp_count > 7) { + arp_count = 0; + } +} + bool SeqPtcPage::handleEvent(gui_event_t *event) { if (SeqPage::handleEvent(event)) { @@ -482,7 +574,8 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { config_encoders(); } midi_device = device; - trig_md(note, pitch); + + if (!arp_enabled) { trig_md(note, pitch); } } else if (mask == EVENT_BUTTON_RELEASED) { CLEAR_BIT(note_mask, pitch); } @@ -495,9 +588,9 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { if (EVENT_RELEASED(event, Buttons.BUTTON1)) { if (BUTTON_DOWN(Buttons.BUTTON4)) { - re_init = true; - GUI.pushPage(&poly_page); - return true; + re_init = true; + GUI.pushPage(&poly_page); + return true; } seq_ptc_page.queue_redraw(); recording = !recording; @@ -512,31 +605,31 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { if (EVENT_RELEASED(event, Buttons.BUTTON4)) { if (BUTTON_DOWN(Buttons.BUTTON1)) { - GUI.pushPage(&poly_page); - return true; + GUI.pushPage(&poly_page); + return true; } if (midi_device == DEVICE_MD) { if (poly_count > 1) { #ifdef OLED_DISPLAY - oled_display.textbox("CLEAR ", "POLY TRACKS"); + oled_display.textbox("CLEAR ", "POLY TRACKS"); #endif for (uint8_t c = 0; c < 16; c++) { if (IS_BIT_SET16(mcl_cfg.poly_mask, c)) { - mcl_seq.md_tracks[c].clear_track(); + mcl_seq.md_tracks[c].clear_track(); } } } else { #ifdef OLED_DISPLAY - oled_display.textbox("CLEAR ", "TRACK"); + oled_display.textbox("CLEAR ", "TRACK"); #endif - mcl_seq.md_tracks[last_md_track].clear_track(); + mcl_seq.md_tracks[last_md_track].clear_track(); } } #ifdef EXT_TRACKS else { #ifdef OLED_DISPLAY - oled_display.textbox("CLEAR ", "EXT TRACK"); + oled_display.textbox("CLEAR ", "EXT TRACK"); #endif mcl_seq.ext_tracks[last_ext_track].clear_track(); } @@ -595,8 +688,8 @@ void SeqPtcMidiEvents::onNoteOnCallback_Midi2(uint8_t *msg) { return; } - uint8_t scaled_pitch = pitch - (pitch / 24) * 24; - SET_BIT64(seq_ptc_page.note_mask, scaled_pitch); + uint8_t scaled_pitch = pitch - (pitch / 24) * 24; + SET_BIT64(seq_ptc_page.note_mask, scaled_pitch); #ifdef EXT_TRACKS // otherwise, translate the message and send it back to MIDI2. diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index dfe9a4ed3..48245daeb 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -25,7 +25,12 @@ class SeqPtcMidiEvents : public MidiCallback { void onControlChangeCallback_Midi(uint8_t *msg); }; -class SeqPtcPage : public SeqPage { +#define ARP_UP 0 +#define ARP_DOWN 1 +#define ARP_CIRC 2 +#define ARP_RND 3 + +class SeqPtcPage : public SeqPage, public ClockCallback { public: bool re_init = false; @@ -56,6 +61,19 @@ class SeqPtcPage : public SeqPage { void init_poly(); void queue_redraw(); + bool arp_enabled = false; + uint8_t arp_idx; + uint8_t arp_speed; + uint8_t arp_mode; + uint8_t arp_oct; + uint8_t arp_count; + + void setup_arp(); + void remove_arp(); + uint8_t arp_get_next_note_up(uint8_t); + uint8_t arp_get_next_note_down(uint8_t); + void on_16_callback(); + virtual bool handleEvent(gui_event_t *event); virtual void display(); virtual void setup(); From 937318e1c2895eacd6e94e045213e24dc5bfaec3 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 1 Mar 2020 20:06:58 +1100 Subject: [PATCH 02/27] Arp GUI + modes + oct working --- avr/cores/megacommand/MCL/SeqPage.cpp | 5 +- avr/cores/megacommand/MCL/SeqPages.cpp | 7 ++- avr/cores/megacommand/MCL/SeqPages.h | 4 +- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 64 ++++++++++++++++++------ avr/cores/megacommand/MCL/SeqPtcPage.h | 5 +- 5 files changed, 63 insertions(+), 22 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index a4e647a58..14e2aa905 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -51,11 +51,12 @@ void SeqPage::init() { oled_display.clearDisplay(); #endif toggle_device = true; - if (mcl_cfg.track_select == 1) { seq_menu_page.menu.enable_entry(0, false); + if (mcl_cfg.track_select == 1) { + seq_menu_page.menu.enable_entry(1, false); } else { - seq_menu_page.menu.enable_entry(0, true); + seq_menu_page.menu.enable_entry(1, true); } } diff --git a/avr/cores/megacommand/MCL/SeqPages.cpp b/avr/cores/megacommand/MCL/SeqPages.cpp index 96b9b101b..b2b70629b 100644 --- a/avr/cores/megacommand/MCL/SeqPages.cpp +++ b/avr/cores/megacommand/MCL/SeqPages.cpp @@ -26,9 +26,12 @@ SeqExtStepPage seq_extstep_page(&seq_param1, &seq_param2, &seq_param3, SeqPtcPage seq_ptc_page(&ptc_param_oct, &ptc_param_finetune, &ptc_param_len, &ptc_param_scale); -const menu_t<8> seq_menu_layout PROGMEM = { +ArpPage arp_page(&arp_mode, &arp_speed, &arp_oct, &arp_und); + +const menu_t<9> seq_menu_layout PROGMEM = { "SEQ", { + {"ARPEGIATOR:", 0, 0, 0, (uint8_t *)NULL, (Page *) &arp_page, NULL, {}}, {"TRACK SEL:", 1, 17, 0, (uint8_t *)&opt_trackid, (Page *)NULL, opt_trackid_handler, {}}, {"COPY:", 0, 3, 3, (uint8_t *)&opt_copy, (Page *)NULL, opt_copy_track_handler, { {0, "--",}, {1, "TRK"}, {2, "ALL"}}}, {"CLEAR:", 0, 3, 3, (uint8_t *)&opt_clear, (Page *)NULL, opt_clear_track_handler, { {0, "--",}, {1, "TRK"}, {2, "ALL"}}}, @@ -43,7 +46,7 @@ const menu_t<8> seq_menu_layout PROGMEM = { MCLEncoder seq_menu_value_encoder(0, 16, ENCODER_RES_PAT); MCLEncoder seq_menu_entry_encoder(0, 9, ENCODER_RES_PAT); -MenuPage<8> seq_menu_page(&seq_menu_layout, &seq_menu_value_encoder, &seq_menu_entry_encoder); +MenuPage<9> seq_menu_page(&seq_menu_layout, &seq_menu_value_encoder, &seq_menu_entry_encoder); const menu_t<4> step_menu_layout PROGMEM = { "STP", diff --git a/avr/cores/megacommand/MCL/SeqPages.h b/avr/cores/megacommand/MCL/SeqPages.h index 9511de334..13e589aca 100644 --- a/avr/cores/megacommand/MCL/SeqPages.h +++ b/avr/cores/megacommand/MCL/SeqPages.h @@ -6,6 +6,7 @@ #include "MCLEncoder.h" #include "MCLMemory.h" #include "MCLMenus.h" +#include "ArpPage.h" #ifdef OLED_DISPLAY #define ENCODER_RES_SEQ 2 @@ -51,10 +52,11 @@ extern MCLEncoder ptc_param_len; extern MCLEncoder ptc_param_scale; extern SeqPtcPage seq_ptc_page; +extern ArpPage arp_page; extern MCLEncoder seq_menu_value_encoder; extern MCLEncoder seq_menu_entry_encoder; -extern MenuPage<8> seq_menu_page; +extern MenuPage<9> seq_menu_page; extern MCLEncoder step_menu_value_encoder; extern MCLEncoder step_menu_entry_encoder; diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index 7475a94d1..bd073f594 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -1,3 +1,4 @@ +#include "ArpPage.h" #include "MCL.h" #include "SeqPtcPage.h" @@ -91,6 +92,7 @@ void SeqPtcPage::init_poly() { void SeqPtcPage::init() { DEBUG_PRINT_FN(); SeqPage::init(); + seq_menu_page.menu.enable_entry(0, true); ptc_param_len.handler = ptc_pattern_len_handler; recording = false; midi_events.setup_callbacks(); @@ -466,30 +468,30 @@ void SeqPtcPage::remove_arp() { uint8_t SeqPtcPage::arp_get_next_note_up(uint8_t cur) { for (uint8_t i = cur + 1; i < NUM_MD_TRACKS; i++) { - if (note_interface.notes[i] == 1) { - return i; + if ((note_interface.notes[i] == 1)) { + return i; } } for (uint8_t i = 0; i <= cur; i++) { if (note_interface.notes[i] == 1) { - return i; + return i; } } return 255; } uint8_t SeqPtcPage::arp_get_next_note_down(uint8_t cur) { - - for (uint8_t i = cur - 1; i > 0; i--) { - if (note_interface.notes[i] == 1) { + for (int8_t i = cur - 1; i >= 0; i--) { + if ((note_interface.notes[i] == 1)) { return i; } } for (uint8_t i = NUM_MD_TRACKS - 1; i >= cur; i--) { - if (note_interface.notes[i] == 1) { - return i; + if (note_interface.notes[i] == 1) { + return i; } } + return 255; } @@ -497,7 +499,7 @@ void SeqPtcPage::on_16_callback() { bool trig = false; uint8_t note; - switch (arp_speed) { + switch (arp_speed.cur) { case 0: trig = true; break; @@ -519,18 +521,50 @@ void SeqPtcPage::on_16_callback() { } if (trig == true) { - switch (arp_mode) { + switch (arp_mode.cur) { case ARP_UP: note = arp_get_next_note_up(arp_idx); + if (note < arp_idx) { + if (arp_base < arp_oct.cur) { arp_base++; } + else { arp_base = 0; } + } break; case ARP_DOWN: note = arp_get_next_note_down(arp_idx); + if (note > arp_idx) { + if (arp_base > 0) { arp_base--; } + else { arp_base = arp_oct.cur; } + } break; + case ARP_CIRC: + uint8_t note_tmp; + if (arp_dir == 0) { + note_tmp = arp_get_next_note_up(arp_idx); + if (note_tmp > arp_idx) { + note = note_tmp; + } else { + if (arp_base < arp_oct.cur) { arp_base++; note = note_tmp; } + else { + arp_dir = 1; + note = arp_get_next_note_down(arp_idx); + } + } + } else if (arp_dir == 1) { + note_tmp = arp_get_next_note_down(arp_idx); + if (note_tmp < arp_idx) { + note = note_tmp; + } else { + if (arp_base > 0) { arp_base--; note = note_tmp; } + else { arp_dir = 0; + note = arp_get_next_note_up(arp_idx); + } + } + } } if (note < NUM_MD_TRACKS) { - arp_idx = note; - uint8_t pitch = calc_pitch(note); - trig_md(note, pitch); + arp_idx = note; + uint8_t pitch = calc_pitch(note) + arp_base * 12; + trig_md(note, pitch); } } @@ -575,7 +609,9 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { } midi_device = device; - if (!arp_enabled) { trig_md(note, pitch); } + if (!arp_enabled) { + trig_md(note, pitch); + } } else if (mask == EVENT_BUTTON_RELEASED) { CLEAR_BIT(note_mask, pitch); } diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index 48245daeb..5971bde78 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -63,9 +63,8 @@ class SeqPtcPage : public SeqPage, public ClockCallback { bool arp_enabled = false; uint8_t arp_idx; - uint8_t arp_speed; - uint8_t arp_mode; - uint8_t arp_oct; + uint8_t arp_base; + uint8_t arp_dir; uint8_t arp_count; void setup_arp(); From a4c8881067e2aeef24545604e73b8ba4a1db6978 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 1 Mar 2020 21:02:15 +1100 Subject: [PATCH 03/27] improvemnets --- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 88 +++++++++++++++++++----- avr/cores/megacommand/MCL/SeqPtcPage.h | 2 + 2 files changed, 73 insertions(+), 17 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index bd073f594..e301a7f48 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -469,12 +469,12 @@ uint8_t SeqPtcPage::arp_get_next_note_up(uint8_t cur) { for (uint8_t i = cur + 1; i < NUM_MD_TRACKS; i++) { if ((note_interface.notes[i] == 1)) { - return i; + return i; } } for (uint8_t i = 0; i <= cur; i++) { if (note_interface.notes[i] == 1) { - return i; + return i; } } return 255; @@ -487,8 +487,8 @@ uint8_t SeqPtcPage::arp_get_next_note_down(uint8_t cur) { } } for (uint8_t i = NUM_MD_TRACKS - 1; i >= cur; i--) { - if (note_interface.notes[i] == 1) { - return i; + if (note_interface.notes[i] == 1) { + return i; } } @@ -520,20 +520,28 @@ void SeqPtcPage::on_16_callback() { } } + bool ignore_base = false; + if (trig == true) { switch (arp_mode.cur) { case ARP_UP: note = arp_get_next_note_up(arp_idx); if (note < arp_idx) { - if (arp_base < arp_oct.cur) { arp_base++; } - else { arp_base = 0; } + if (arp_base < arp_oct.cur) { + arp_base++; + } else { + arp_base = 0; + } } break; case ARP_DOWN: note = arp_get_next_note_down(arp_idx); if (note > arp_idx) { - if (arp_base > 0) { arp_base--; } - else { arp_base = arp_oct.cur; } + if (arp_base > 0) { + arp_base--; + } else { + arp_base = arp_oct.cur; + } } break; case ARP_CIRC: @@ -543,27 +551,73 @@ void SeqPtcPage::on_16_callback() { if (note_tmp > arp_idx) { note = note_tmp; } else { - if (arp_base < arp_oct.cur) { arp_base++; note = note_tmp; } - else { - arp_dir = 1; - note = arp_get_next_note_down(arp_idx); - } + if (arp_base < arp_oct.cur) { + arp_base++; + note = note_tmp; + } else { + arp_dir = 1; + note = arp_get_next_note_down(arp_idx); } + } } else if (arp_dir == 1) { note_tmp = arp_get_next_note_down(arp_idx); if (note_tmp < arp_idx) { note = note_tmp; } else { - if (arp_base > 0) { arp_base--; note = note_tmp; } - else { arp_dir = 0; - note = arp_get_next_note_up(arp_idx); + if (arp_base > 0) { + arp_base--; + note = note_tmp; + } else { + arp_dir = 0; + note = arp_get_next_note_up(arp_idx); } } } + break; + case ARP_RND: + note = arp_get_next_note_down(get_random_byte() & 0xF); + arp_base = get_random_byte() & arp_oct.cur; + break; + case ARP_UPTHUMB: + note = arp_get_next_note_up(arp_idx); + note_tmp = arp_get_next_note_up(arp_idx); + ignore_base = true; + if (note_tmp < arp_idx) { + ignore_base = false; + } + if (note < arp_idx) { + if (arp_base < arp_oct.cur) { + arp_base++; + } else { + arp_base = 0; + } + } + break; + case ARP_DOWNPINK: + note = arp_get_next_note_down(arp_idx); + note_tmp = arp_get_next_note_down(arp_idx); + ignore_base = true; + if (note_tmp >arp_idx) { + ignore_base = false; + } + if (note > arp_idx) { + if (arp_base > 0) { + arp_base--; + } else { + arp_base = arp_oct.cur; + } + } + break; + + } if (note < NUM_MD_TRACKS) { arp_idx = note; - uint8_t pitch = calc_pitch(note) + arp_base * 12; + uint8_t pitch; + if (ignore_base) { pitch = calc_pitch(note); } + else { + pitch = calc_pitch(note) + arp_base * 12; + } trig_md(note, pitch); } } diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index 5971bde78..09cfff7ab 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -29,6 +29,8 @@ class SeqPtcMidiEvents : public MidiCallback { #define ARP_DOWN 1 #define ARP_CIRC 2 #define ARP_RND 3 +#define ARP_UPTHUMB 4 +#define ARP_DOWNPINK 5 class SeqPtcPage : public SeqPage, public ClockCallback { From a82c23eb55064fb3e2e4c2389e37f71c5c93282c Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 1 Mar 2020 22:54:50 +1100 Subject: [PATCH 04/27] Use note_mask for arp so ext midi is supported --- avr/cores/megacommand/MCL/ArpPage.cpp | 102 +++++++++++++++++++++++ avr/cores/megacommand/MCL/ArpPage.h | 31 +++++++ avr/cores/megacommand/MCL/SeqPtcPage.cpp | 57 ++++++++++--- avr/cores/megacommand/MCL/SeqPtcPage.h | 4 +- 4 files changed, 180 insertions(+), 14 deletions(-) create mode 100644 avr/cores/megacommand/MCL/ArpPage.cpp create mode 100644 avr/cores/megacommand/MCL/ArpPage.h diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp new file mode 100644 index 000000000..6240b4e41 --- /dev/null +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -0,0 +1,102 @@ +#include "ArpPage.h" +#include "MCL.h" + +MCLEncoder arp_oct(0, 3, ENCODER_RES_SEQ); +MCLEncoder arp_mode(0, 7, ENCODER_RES_SEQ); +MCLEncoder arp_speed(0, 4, ENCODER_RES_SEQ); +MCLEncoder arp_und(0, 4, ENCODER_RES_SEQ); + +void ArpPage::setup() {} + +void ArpPage::init() { + + DEBUG_PRINT_FN(); +#ifdef OLED_DISPLAY + classic_display = false; + oled_display.setFont(); + seq_ptc_page.redisplay = true; + seq_ptc_page.display(); +#endif +} + +void ArpPage::cleanup() { + // md_exploit.off(); +#ifdef OLED_DISPLAY + oled_display.clearDisplay(); +#endif +} + +void ArpPage::display() { + + if (!classic_display) { + } + auto oldfont = oled_display.getFont(); + oled_display.setFont(&TomThumb); + + oled_display.setTextColor(WHITE); + + oled_display.fillRect(8, 2, 128 - 16, 32 - 2, BLACK); + oled_display.drawRect(8 + 1, 2 + 1, 128 - 16 - 2, 32 - 2 - 2, WHITE); + + oled_display.setCursor(34, 10); + oled_display.print("ARPEGGIATOR"); + char str[5]; + switch (encoders[0]->cur) { + case ARP_UP: + strcpy(str,"UP"); + break; + case ARP_DOWN: + strcpy(str,"DWN"); + break; + case ARP_CIRC: + strcpy(str,"CIR"); + break; + case ARP_RND: + strcpy(str,"RND"); + break; + case ARP_UPTHUMB: + strcpy(str,"UPT"); + break; + case ARP_DOWNPINK: + strcpy(str,"DNP"); + break; + case ARP_UPPINK: + strcpy(str,"UPP"); + break; + case ARP_DOWNTHUMB: + strcpy(str,"DNT"); + break; + default: + break; + } + uint8_t y = 12; + mcl_gui.draw_text_encoder(mcl_gui.knob_x0,y, "MODE", str); + + itoa(encoders[1]->cur, str, 10); + mcl_gui.draw_text_encoder(mcl_gui.knob_x0 + 1 * mcl_gui.knob_w, y, "SPD", str); + + itoa(encoders[2]->cur, str, 10); + mcl_gui.draw_text_encoder(mcl_gui.knob_x0 + 2 * mcl_gui.knob_w, y, "OCT", str); + + oled_display.display(); + oled_display.setFont(oldfont); +} + +bool ArpPage::handleEvent(gui_event_t *event) { + seq_ptc_page.handleEvent(event); + + if (note_interface.is_event(event)) { + uint8_t track = event->source - 128; + if (midi_active_peering.get_device(event->port) != DEVICE_MD) { + return true; + } + } + if (EVENT_PRESSED(event, Buttons.BUTTON1) || + EVENT_PRESSED(event, Buttons.BUTTON4)) { + GUI.ignoreNextEvent(event->source); + GUI.popPage(); + return true; + } + + return false; +} diff --git a/avr/cores/megacommand/MCL/ArpPage.h b/avr/cores/megacommand/MCL/ArpPage.h new file mode 100644 index 000000000..83a9c8435 --- /dev/null +++ b/avr/cores/megacommand/MCL/ArpPage.h @@ -0,0 +1,31 @@ +/* Justin Mammarella jmamma@gmail.com 2018 */ + +#ifndef ARPPAGE_H__ +#define ARPPAGE_H__ + +//#include "Pages.hh" +#include "GUI.h" +#include "MCLEncoder.h" + +extern MCLEncoder arp_speed; +extern MCLEncoder arp_oct; +extern MCLEncoder arp_mode; +extern MCLEncoder arp_und; + +class ArpPage : public LightPage { +public: + + ArpPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, + Encoder *e4 = NULL) + : LightPage(e1, e2, e3, e4) { + } + + bool handleEvent(gui_event_t *event); + + void display(); + void setup(); + void init(); + void cleanup(); +}; + +#endif /* ARPPAGE_H__ */ diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index e301a7f48..b45d6b447 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -467,13 +467,13 @@ void SeqPtcPage::remove_arp() { uint8_t SeqPtcPage::arp_get_next_note_up(uint8_t cur) { - for (uint8_t i = cur + 1; i < NUM_MD_TRACKS; i++) { - if ((note_interface.notes[i] == 1)) { + for (uint8_t i = cur + 1; i < 24; i++) { + if (IS_BIT_SET32(note_mask, i)) { return i; } } for (uint8_t i = 0; i <= cur; i++) { - if (note_interface.notes[i] == 1) { + if (IS_BIT_SET32(note_mask, i)) { return i; } } @@ -482,12 +482,12 @@ uint8_t SeqPtcPage::arp_get_next_note_up(uint8_t cur) { uint8_t SeqPtcPage::arp_get_next_note_down(uint8_t cur) { for (int8_t i = cur - 1; i >= 0; i--) { - if ((note_interface.notes[i] == 1)) { + if (IS_BIT_SET32(note_mask, i)) { return i; } } for (uint8_t i = NUM_MD_TRACKS - 1; i >= cur; i--) { - if (note_interface.notes[i] == 1) { + if (IS_BIT_SET32(note_mask, i)) { return i; } } @@ -573,11 +573,27 @@ void SeqPtcPage::on_16_callback() { } } } - break; + break; case ARP_RND: note = arp_get_next_note_down(get_random_byte() & 0xF); arp_base = get_random_byte() & arp_oct.cur; break; + case ARP_DOWNTHUMB: + note = arp_get_next_note_down(arp_idx); + note_tmp = arp_get_next_note_up(arp_idx); + ignore_base = true; + if (note_tmp < arp_idx) { + ignore_base = false; + } + note = arp_get_next_note_down(arp_idx); + if (note > arp_idx) { + if (arp_base > 0) { + arp_base--; + } else { + arp_base = arp_oct.cur; + } + } + break; case ARP_UPTHUMB: note = arp_get_next_note_up(arp_idx); note_tmp = arp_get_next_note_up(arp_idx); @@ -595,9 +611,24 @@ void SeqPtcPage::on_16_callback() { break; case ARP_DOWNPINK: note = arp_get_next_note_down(arp_idx); - note_tmp = arp_get_next_note_down(arp_idx); + note_tmp = arp_get_next_note_down(arp_idx); ignore_base = true; - if (note_tmp >arp_idx) { + if (note_tmp > arp_idx) { + ignore_base = false; + } + if (note > arp_idx) { + if (arp_base > 0) { + arp_base--; + } else { + arp_base = arp_oct.cur; + } + } + break; + case ARP_UPPINK: + note = arp_get_next_note_up(arp_idx); + note_tmp = arp_get_next_note_down(arp_idx); + ignore_base = true; + if (note_tmp > arp_idx) { ignore_base = false; } if (note > arp_idx) { @@ -608,14 +639,13 @@ void SeqPtcPage::on_16_callback() { } } break; - - } if (note < NUM_MD_TRACKS) { arp_idx = note; uint8_t pitch; - if (ignore_base) { pitch = calc_pitch(note); } - else { + if (ignore_base) { + pitch = calc_pitch(note); + } else { pitch = calc_pitch(note) + arp_base * 12; } trig_md(note, pitch); @@ -667,7 +697,8 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { trig_md(note, pitch); } } else if (mask == EVENT_BUTTON_RELEASED) { - CLEAR_BIT(note_mask, pitch); + + CLEAR_BIT64(note_mask, pitch); } // deferred trigger redraw to update TI keyboard feedback. diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index 09cfff7ab..950ac90c3 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -30,7 +30,9 @@ class SeqPtcMidiEvents : public MidiCallback { #define ARP_CIRC 2 #define ARP_RND 3 #define ARP_UPTHUMB 4 -#define ARP_DOWNPINK 5 +#define ARP_UPPINK 5 +#define ARP_DOWNPINK 6 +#define ARP_DOWNTHUMB 7 class SeqPtcPage : public SeqPage, public ClockCallback { From 7b5d07386a97f1f6131fe421cecb4f1cc1996d42 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 2 Mar 2020 02:24:30 +1100 Subject: [PATCH 05/27] fixes --- avr/cores/megacommand/MCL/ArpPage.cpp | 78 ++++++++++++++++-------- avr/cores/megacommand/MCL/ArpPage.h | 1 + avr/cores/megacommand/MCL/SeqPages.cpp | 2 +- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 8 ++- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp index 6240b4e41..452d12de3 100644 --- a/avr/cores/megacommand/MCL/ArpPage.cpp +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -4,7 +4,7 @@ MCLEncoder arp_oct(0, 3, ENCODER_RES_SEQ); MCLEncoder arp_mode(0, 7, ENCODER_RES_SEQ); MCLEncoder arp_speed(0, 4, ENCODER_RES_SEQ); -MCLEncoder arp_und(0, 4, ENCODER_RES_SEQ); +MCLEncoder arp_und(0, 1, ENCODER_RES_SEQ); void ArpPage::setup() {} @@ -25,6 +25,21 @@ void ArpPage::cleanup() { oled_display.clearDisplay(); #endif } +#define ARP_ON 1 +#define ARP_OFF 0 + +void ArpPage::loop() { + if (encoders[0]->hasChanged()) { + switch (encoders[0]->cur) { + case ARP_ON: + seq_ptc_page.setup_arp(); + break; + case ARP_OFF: + seq_ptc_page.remove_arp(); + break; + } + } +} void ArpPage::display() { @@ -33,56 +48,78 @@ void ArpPage::display() { auto oldfont = oled_display.getFont(); oled_display.setFont(&TomThumb); - oled_display.setTextColor(WHITE); oled_display.fillRect(8, 2, 128 - 16, 32 - 2, BLACK); oled_display.drawRect(8 + 1, 2 + 1, 128 - 16 - 2, 32 - 2 - 2, WHITE); - oled_display.setCursor(34, 10); + + + oled_display.setCursor(42, 10); + + oled_display.setTextColor(WHITE); oled_display.print("ARPEGGIATOR"); char str[5]; + uint8_t y = 12; + uint8_t x = 16; + switch (encoders[0]->cur) { + case ARP_ON: + strcpy(str, "ON"); + break; + case ARP_OFF: + strcpy(str, "--"); + break; + } + mcl_gui.draw_text_encoder(x + 0 * mcl_gui.knob_w, y, "ARP", str); + + switch (encoders[1]->cur) { case ARP_UP: - strcpy(str,"UP"); + strcpy(str, "UP"); break; case ARP_DOWN: - strcpy(str,"DWN"); + strcpy(str, "DWN"); break; case ARP_CIRC: - strcpy(str,"CIR"); + strcpy(str, "CIR"); break; case ARP_RND: - strcpy(str,"RND"); + strcpy(str, "RND"); break; case ARP_UPTHUMB: - strcpy(str,"UPT"); + strcpy(str, "UPT"); break; case ARP_DOWNPINK: - strcpy(str,"DNP"); + strcpy(str, "DNP"); break; case ARP_UPPINK: - strcpy(str,"UPP"); + strcpy(str, "UPP"); break; case ARP_DOWNTHUMB: - strcpy(str,"DNT"); + strcpy(str, "DNT"); break; default: break; } - uint8_t y = 12; - mcl_gui.draw_text_encoder(mcl_gui.knob_x0,y, "MODE", str); - - itoa(encoders[1]->cur, str, 10); - mcl_gui.draw_text_encoder(mcl_gui.knob_x0 + 1 * mcl_gui.knob_w, y, "SPD", str); + mcl_gui.draw_text_encoder(x + 1 * mcl_gui.knob_w, y, "MODE", str); itoa(encoders[2]->cur, str, 10); - mcl_gui.draw_text_encoder(mcl_gui.knob_x0 + 2 * mcl_gui.knob_w, y, "OCT", str); + mcl_gui.draw_text_encoder(x + 2 * mcl_gui.knob_w, y, "SPD", str); + + itoa(encoders[3]->cur, str, 10); + mcl_gui.draw_text_encoder(x + 3 * mcl_gui.knob_w, y, "OCT", str); oled_display.display(); oled_display.setFont(oldfont); } bool ArpPage::handleEvent(gui_event_t *event) { + if (EVENT_PRESSED(event, Buttons.BUTTON1) || EVENT_PRESSED(event, Buttons.BUTTON3) || EVENT_PRESSED(event, Buttons.BUTTON2) || + EVENT_PRESSED(event, Buttons.BUTTON4)) { + GUI.ignoreNextEvent(event->source); + GUI.popPage(); + return true; + } + seq_ptc_page.handleEvent(event); if (note_interface.is_event(event)) { @@ -91,12 +128,5 @@ bool ArpPage::handleEvent(gui_event_t *event) { return true; } } - if (EVENT_PRESSED(event, Buttons.BUTTON1) || - EVENT_PRESSED(event, Buttons.BUTTON4)) { - GUI.ignoreNextEvent(event->source); - GUI.popPage(); - return true; - } - return false; } diff --git a/avr/cores/megacommand/MCL/ArpPage.h b/avr/cores/megacommand/MCL/ArpPage.h index 83a9c8435..e74110225 100644 --- a/avr/cores/megacommand/MCL/ArpPage.h +++ b/avr/cores/megacommand/MCL/ArpPage.h @@ -22,6 +22,7 @@ class ArpPage : public LightPage { bool handleEvent(gui_event_t *event); + void loop(); void display(); void setup(); void init(); diff --git a/avr/cores/megacommand/MCL/SeqPages.cpp b/avr/cores/megacommand/MCL/SeqPages.cpp index b2b70629b..54e01e6b6 100644 --- a/avr/cores/megacommand/MCL/SeqPages.cpp +++ b/avr/cores/megacommand/MCL/SeqPages.cpp @@ -26,7 +26,7 @@ SeqExtStepPage seq_extstep_page(&seq_param1, &seq_param2, &seq_param3, SeqPtcPage seq_ptc_page(&ptc_param_oct, &ptc_param_finetune, &ptc_param_len, &ptc_param_scale); -ArpPage arp_page(&arp_mode, &arp_speed, &arp_oct, &arp_und); +ArpPage arp_page(&arp_und, &arp_mode, &arp_speed, &arp_oct); const menu_t<9> seq_menu_layout PROGMEM = { "SEQ", diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index b45d6b447..f11c59c4d 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -46,7 +46,6 @@ void SeqPtcPage::setup() { SeqPage::setup(); init_poly(); midi_events.setup_callbacks(); - setup_arp(); } void SeqPtcPage::cleanup() { SeqPage::cleanup(); @@ -199,6 +198,7 @@ void SeqPtcPage::loop() { #ifdef EXT_TRACKS if (ptc_param_oct.hasChanged() || ptc_param_scale.hasChanged()) { mcl_seq.ext_tracks[last_ext_track].buffer_notesoff(); + note_mask = 0; } #endif @@ -453,6 +453,7 @@ void SeqPtcPage::trig_md_fromext(uint8_t note_num) { void SeqPtcPage::queue_redraw() { deferred_timer = slowclock; } void SeqPtcPage::setup_arp() { + if (arp_enabled) { return; } arp_enabled = true; arp_idx = 0; MidiClock.addOn16Callback( @@ -460,6 +461,7 @@ void SeqPtcPage::setup_arp() { } void SeqPtcPage::remove_arp() { + if (!arp_enabled) { return; } arp_enabled = false; MidiClock.removeOn16Callback( this, (midi_clock_callback_ptr_t)&SeqPtcPage::on_16_callback); @@ -526,7 +528,7 @@ void SeqPtcPage::on_16_callback() { switch (arp_mode.cur) { case ARP_UP: note = arp_get_next_note_up(arp_idx); - if (note < arp_idx) { + if (note <= arp_idx) { if (arp_base < arp_oct.cur) { arp_base++; } else { @@ -536,7 +538,7 @@ void SeqPtcPage::on_16_callback() { break; case ARP_DOWN: note = arp_get_next_note_down(arp_idx); - if (note > arp_idx) { + if (note >= arp_idx) { if (arp_base > 0) { arp_base--; } else { From bf92550cfa1d3910cd4d5fc110b48ea0430cbe62 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 2 Mar 2020 02:36:18 +1100 Subject: [PATCH 06/27] SeqMenu config was out of alignment --- avr/cores/megacommand/MCL/SeqPage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index 14e2aa905..c436daccd 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -912,14 +912,14 @@ void step_menu_handler() { void SeqPage::config_as_trackedit() { - seq_menu_page.menu.enable_entry(2, true); - seq_menu_page.menu.enable_entry(3, false); + seq_menu_page.menu.enable_entry(3, true); + seq_menu_page.menu.enable_entry(4, false); } void SeqPage::config_as_lockedit() { - seq_menu_page.menu.enable_entry(2, false); - seq_menu_page.menu.enable_entry(3, true); + seq_menu_page.menu.enable_entry(3, false); + seq_menu_page.menu.enable_entry(4, true); } void SeqPage::loop() { From 188fcb132b34f8e4940d8bfb7f046e82b699c520 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 2 Mar 2020 13:56:23 +1100 Subject: [PATCH 07/27] Defer ARP rendering outside of ISR --- avr/cores/megacommand/MCL/ArpPage.cpp | 7 +- avr/cores/megacommand/MCL/MDSeqTrack.cpp | 6 +- avr/cores/megacommand/MCL/MDSeqTrack.h | 7 +- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 182 ++++++++++++++-------- avr/cores/megacommand/MCL/SeqPtcPage.h | 13 +- avr/cores/megacommand/MCL/SeqRtrkPage.cpp | 2 +- 6 files changed, 140 insertions(+), 77 deletions(-) diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp index 452d12de3..f6a6dce19 100644 --- a/avr/cores/megacommand/MCL/ArpPage.cpp +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -4,7 +4,7 @@ MCLEncoder arp_oct(0, 3, ENCODER_RES_SEQ); MCLEncoder arp_mode(0, 7, ENCODER_RES_SEQ); MCLEncoder arp_speed(0, 4, ENCODER_RES_SEQ); -MCLEncoder arp_und(0, 1, ENCODER_RES_SEQ); +MCLEncoder arp_und(0, 3, ENCODER_RES_SEQ); void ArpPage::setup() {} @@ -25,8 +25,6 @@ void ArpPage::cleanup() { oled_display.clearDisplay(); #endif } -#define ARP_ON 1 -#define ARP_OFF 0 void ArpPage::loop() { if (encoders[0]->hasChanged()) { @@ -39,6 +37,9 @@ void ArpPage::loop() { break; } } + if (encoders[1]->hasChanged() || encoders[2]->hasChanged() || encoders[3]->hasChanged()) { + seq_ptc_page.render_arp(); + } } void ArpPage::display() { diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index d1e260d62..41f9564f3 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -337,7 +337,7 @@ void MDSeqTrack::record_track_pitch(uint8_t pitch) { } set_track_pitch(step_count, pitch); } -void MDSeqTrack::record_track(uint8_t note_num, uint8_t velocity) { +void MDSeqTrack::record_track(uint8_t velocity) { /*uint8_t step_count = (MidiClock.div16th_counter - mcl_actions.start_clock32th / 2) - (length * ((MidiClock.div16th_counter - mcl_actions.start_clock32th / 2) @@ -347,10 +347,10 @@ void MDSeqTrack::record_track(uint8_t note_num, uint8_t velocity) { return; } uint8_t utiming = MidiClock.mod12_counter + 12; - set_track_step(step_count, utiming, note_num, velocity); + set_track_step(step_count, utiming, velocity); } -void MDSeqTrack::set_track_step(uint8_t step, uint8_t utiming, uint8_t note_num, +void MDSeqTrack::set_track_step(uint8_t step, uint8_t utiming, uint8_t velocity) { uint8_t condition = 0; diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 450610c20..30b89a046 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -28,7 +28,7 @@ class MDSeqTrack : public MDSeqTrackData { uint8_t locks_params_orig[4]; bool load = false; -// uint8_t params[24]; + // uint8_t params[24]; uint8_t trigGroup; uint32_t start_step; @@ -45,12 +45,11 @@ class MDSeqTrack : public MDSeqTrackData { ALWAYS_INLINE() void send_parameter_locks(uint8_t step); void set_track_pitch(uint8_t step, uint8_t pitch); - void set_track_step(uint8_t step, uint8_t utiming, uint8_t note_num, - uint8_t velocity); + void set_track_step(uint8_t step, uint8_t utiming, uint8_t velocity); void set_track_locks(uint8_t step, uint8_t track_param, uint8_t velocity); uint8_t get_track_lock(uint8_t step, uint8_t track_param); - void record_track(uint8_t note_num, uint8_t velocity); + void record_track(uint8_t velocity); void record_track_locks(uint8_t track_param, uint8_t value); void record_track_pitch(uint8_t pitch); void clear_step_locks(uint8_t step); diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index f11c59c4d..ccc97ea21 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -411,7 +411,7 @@ uint8_t SeqPtcPage::get_machine_pitch(uint8_t track, uint8_t pitch) { return machine_pitch; } -void SeqPtcPage::trig_md(uint8_t note, uint8_t pitch) { +void SeqPtcPage::trig_md(uint8_t pitch) { pitch = octave_to_pitch() + pitch; uint8_t next_track = get_next_voice(pitch); uint8_t machine_pitch = get_machine_pitch(next_track, pitch); @@ -422,7 +422,7 @@ void SeqPtcPage::trig_md(uint8_t note, uint8_t pitch) { if ((recording) && (MidiClock.state == 2)) { if (!BUTTON_DOWN(Buttons.BUTTON2)) { - mcl_seq.md_tracks[next_track].record_track(note, 127); + mcl_seq.md_tracks[next_track].record_track(127); } mcl_seq.md_tracks[next_track].record_track_pitch(machine_pitch); } @@ -431,6 +431,7 @@ void SeqPtcPage::trig_md(uint8_t note, uint8_t pitch) { void SeqPtcPage::clear_trig_fromext(uint8_t note_num) { uint8_t pitch = seq_ext_pitch(note_num - 32); CLEAR_BIT64(note_mask, pitch); + render_arp(); } void SeqPtcPage::trig_md_fromext(uint8_t note_num) { @@ -438,13 +439,14 @@ void SeqPtcPage::trig_md_fromext(uint8_t note_num) { uint8_t next_track = get_next_voice(pitch); uint8_t machine_pitch = get_machine_pitch(next_track, pitch); SET_BIT64(note_mask, pitch); + render_arp(); MD.setTrackParam(next_track, 0, machine_pitch); if (!BUTTON_DOWN(Buttons.BUTTON2)) { MD.triggerTrack(next_track, 127); } if ((recording) && (MidiClock.state == 2)) { if (!BUTTON_DOWN(Buttons.BUTTON2)) { - mcl_seq.md_tracks[next_track].record_track(note_num, 127); + mcl_seq.md_tracks[next_track].record_track(127); } mcl_seq.md_tracks[next_track].record_track_pitch(machine_pitch); } @@ -453,15 +455,21 @@ void SeqPtcPage::trig_md_fromext(uint8_t note_num) { void SeqPtcPage::queue_redraw() { deferred_timer = slowclock; } void SeqPtcPage::setup_arp() { - if (arp_enabled) { return; } + if (arp_enabled) { + return; + } arp_enabled = true; + arp_len = 0; arp_idx = 0; + render_arp(); MidiClock.addOn16Callback( this, (midi_clock_callback_ptr_t)&SeqPtcPage::on_16_callback); } void SeqPtcPage::remove_arp() { - if (!arp_enabled) { return; } + if (!arp_enabled) { + return; + } arp_enabled = false; MidiClock.removeOn16Callback( this, (midi_clock_callback_ptr_t)&SeqPtcPage::on_16_callback); @@ -497,38 +505,35 @@ uint8_t SeqPtcPage::arp_get_next_note_down(uint8_t cur) { return 255; } -void SeqPtcPage::on_16_callback() { - bool trig = false; - uint8_t note; - - switch (arp_speed.cur) { - case 0: - trig = true; - break; - case 1: - if ((arp_count == 0) || (arp_count == 2) || (arp_count == 4) || - (arp_count == 6)) { - trig = true; - } - break; - case 2: - if ((arp_count == 0) || (arp_count == 4)) { - trig = true; - } - break; - case 3: - if (arp_count == 0) { - trig = true; +void SeqPtcPage::render_arp() { + if (!arp_enabled) { + return; + } + uint8_t first_note = 255; + arp_len = 0; + for (uint8_t i = 0; i < ARP_MAX_NOTES && first_note == 255; i++) { + if (IS_BIT_SET32(note_mask, i)) { + first_note = i; } } + if (first_note == 255) { + return; + } + uint8_t idx = first_note; + uint8_t note = 255; - bool ignore_base = false; + uint8_t pitch = 255; + uint8_t first_pitch = calc_pitch(first_note); - if (trig == true) { +// arp_notes[0] = first_pitch; +// arp_len++; + + while (pitch != first_pitch && arp_len < ARP_MAX_NOTES) { + bool ignore_base = false; switch (arp_mode.cur) { case ARP_UP: - note = arp_get_next_note_up(arp_idx); - if (note <= arp_idx) { + note = arp_get_next_note_up(idx); + if (note <= idx) { if (arp_base < arp_oct.cur) { arp_base++; } else { @@ -537,8 +542,8 @@ void SeqPtcPage::on_16_callback() { } break; case ARP_DOWN: - note = arp_get_next_note_down(arp_idx); - if (note >= arp_idx) { + note = arp_get_next_note_down(idx); + if (note >= idx) { if (arp_base > 0) { arp_base--; } else { @@ -549,8 +554,8 @@ void SeqPtcPage::on_16_callback() { case ARP_CIRC: uint8_t note_tmp; if (arp_dir == 0) { - note_tmp = arp_get_next_note_up(arp_idx); - if (note_tmp > arp_idx) { + note_tmp = arp_get_next_note_up(idx); + if (note_tmp > idx) { note = note_tmp; } else { if (arp_base < arp_oct.cur) { @@ -558,12 +563,12 @@ void SeqPtcPage::on_16_callback() { note = note_tmp; } else { arp_dir = 1; - note = arp_get_next_note_down(arp_idx); + note = arp_get_next_note_down(idx); } } } else if (arp_dir == 1) { - note_tmp = arp_get_next_note_down(arp_idx); - if (note_tmp < arp_idx) { + note_tmp = arp_get_next_note_down(idx); + if (note_tmp < idx) { note = note_tmp; } else { if (arp_base > 0) { @@ -571,7 +576,7 @@ void SeqPtcPage::on_16_callback() { note = note_tmp; } else { arp_dir = 0; - note = arp_get_next_note_up(arp_idx); + note = arp_get_next_note_up(idx); } } } @@ -581,14 +586,14 @@ void SeqPtcPage::on_16_callback() { arp_base = get_random_byte() & arp_oct.cur; break; case ARP_DOWNTHUMB: - note = arp_get_next_note_down(arp_idx); - note_tmp = arp_get_next_note_up(arp_idx); + note = arp_get_next_note_down(idx); + note_tmp = arp_get_next_note_up(idx); ignore_base = true; - if (note_tmp < arp_idx) { + if (note_tmp < idx) { ignore_base = false; } - note = arp_get_next_note_down(arp_idx); - if (note > arp_idx) { + note = arp_get_next_note_down(idx); + if (note > idx) { if (arp_base > 0) { arp_base--; } else { @@ -597,13 +602,13 @@ void SeqPtcPage::on_16_callback() { } break; case ARP_UPTHUMB: - note = arp_get_next_note_up(arp_idx); - note_tmp = arp_get_next_note_up(arp_idx); + note = arp_get_next_note_up(idx); + note_tmp = arp_get_next_note_up(idx); ignore_base = true; - if (note_tmp < arp_idx) { + if (note_tmp < idx) { ignore_base = false; } - if (note < arp_idx) { + if (note < idx) { if (arp_base < arp_oct.cur) { arp_base++; } else { @@ -612,13 +617,13 @@ void SeqPtcPage::on_16_callback() { } break; case ARP_DOWNPINK: - note = arp_get_next_note_down(arp_idx); - note_tmp = arp_get_next_note_down(arp_idx); + note = arp_get_next_note_down(idx); + note_tmp = arp_get_next_note_down(idx); ignore_base = true; - if (note_tmp > arp_idx) { + if (note_tmp > idx) { ignore_base = false; } - if (note > arp_idx) { + if (note > idx) { if (arp_base > 0) { arp_base--; } else { @@ -627,13 +632,13 @@ void SeqPtcPage::on_16_callback() { } break; case ARP_UPPINK: - note = arp_get_next_note_up(arp_idx); - note_tmp = arp_get_next_note_down(arp_idx); + note = arp_get_next_note_up(idx); + note_tmp = arp_get_next_note_down(idx); ignore_base = true; - if (note_tmp > arp_idx) { + if (note_tmp > idx) { ignore_base = false; } - if (note > arp_idx) { + if (note > idx) { if (arp_base > 0) { arp_base--; } else { @@ -643,14 +648,59 @@ void SeqPtcPage::on_16_callback() { break; } if (note < NUM_MD_TRACKS) { - arp_idx = note; - uint8_t pitch; - if (ignore_base) { - pitch = calc_pitch(note); - } else { - pitch = calc_pitch(note) + arp_base * 12; + idx = note; + arp_notes[arp_len] = calc_pitch(note); + if (!ignore_base) { + arp_notes[arp_len] += arp_base * 12; + pitch = arp_notes[arp_len]; + } + else { + pitch = arp_notes[arp_len] + arp_base * 12; } - trig_md(note, pitch); + arp_len++; + } + } + if (arp_idx >= arp_len) { arp_idx = arp_len - 1; } +} + +void SeqPtcPage::on_16_callback() { + bool trig = false; + uint8_t note; + + uint8_t arp_count_tmp = arp_count; + if (arp_und.cur == ARP_SHIFT) { + arp_count_tmp++; + } else if (((arp_und.cur == ARP_SKIP) && (arp_count_tmp != 0)) || (arp_und.cur == ARP_ON)) { + switch (arp_speed.cur) { + case 0: + trig = true; + break; + case 1: + if ((arp_count_tmp == 0) || (arp_count_tmp == 2) || + (arp_count_tmp == 4) || (arp_count_tmp == 6)) { + trig = true; + } + break; + case 2: + if ((arp_count_tmp == 0) || (arp_count_tmp == 4)) { + trig = true; + } + break; + case 3: + if (arp_count_tmp == 0) { + trig = true; + } + } + } + bool ignore_base = false; + + if (trig == true) { + if (arp_len > 0) { + trig_md(arp_notes[arp_idx]); + arp_idx++; + if (arp_idx == arp_len) { + arp_idx = 0; + } } } @@ -687,6 +737,7 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { if (mask == EVENT_BUTTON_PRESSED) { SET_BIT64(note_mask, pitch); + render_arp(); if (midi_device != DEVICE_MD) { midi_device = device; config(); @@ -696,11 +747,12 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { midi_device = device; if (!arp_enabled) { - trig_md(note, pitch); + trig_md(pitch); } } else if (mask == EVENT_BUTTON_RELEASED) { CLEAR_BIT64(note_mask, pitch); + render_arp(); } // deferred trigger redraw to update TI keyboard feedback. @@ -813,7 +865,7 @@ void SeqPtcMidiEvents::onNoteOnCallback_Midi2(uint8_t *msg) { uint8_t scaled_pitch = pitch - (pitch / 24) * 24; SET_BIT64(seq_ptc_page.note_mask, scaled_pitch); - + seq_ptc_page.render_arp(); #ifdef EXT_TRACKS // otherwise, translate the message and send it back to MIDI2. if (SeqPage::midi_device != midi_active_peering.get_device(UART2_PORT) || diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index 950ac90c3..2c6843698 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -34,6 +34,12 @@ class SeqPtcMidiEvents : public MidiCallback { #define ARP_DOWNPINK 6 #define ARP_DOWNTHUMB 7 +#define ARP_ON 1 +#define ARP_SKIP 2 +#define ARP_SHIFT 3 +#define ARP_OFF 0 + +#define ARP_MAX_NOTES 16 * 3 class SeqPtcPage : public SeqPage, public ClockCallback { public: @@ -56,7 +62,7 @@ class SeqPtcPage : public SeqPage, public ClockCallback { uint8_t get_next_voice(uint8_t pitch); uint8_t calc_pitch(uint8_t note_num); - void trig_md(uint8_t note_num, uint8_t pitch); + void trig_md(uint8_t pitch); void trig_md_fromext(uint8_t note_num); void clear_trig_fromext(uint8_t note_num); @@ -66,6 +72,9 @@ class SeqPtcPage : public SeqPage, public ClockCallback { void queue_redraw(); bool arp_enabled = false; + uint8_t arp_notes[ARP_MAX_NOTES]; + uint8_t arp_len; + uint8_t arp_idx; uint8_t arp_base; uint8_t arp_dir; @@ -73,6 +82,8 @@ class SeqPtcPage : public SeqPage, public ClockCallback { void setup_arp(); void remove_arp(); + void render_arp(); + uint8_t arp_get_next_note_up(uint8_t); uint8_t arp_get_next_note_down(uint8_t); void on_16_callback(); diff --git a/avr/cores/megacommand/MCL/SeqRtrkPage.cpp b/avr/cores/megacommand/MCL/SeqRtrkPage.cpp index 7d47342ec..5ad5d9026 100644 --- a/avr/cores/megacommand/MCL/SeqRtrkPage.cpp +++ b/avr/cores/megacommand/MCL/SeqRtrkPage.cpp @@ -124,7 +124,7 @@ bool SeqRtrkPage::handleEvent(gui_event_t *event) { seq_param3.cur = mcl_seq.md_tracks[last_md_track].length; MD.triggerTrack(track, 127); if (MidiClock.state == 2) { - mcl_seq.md_tracks[last_md_track].record_track(track, 127); + mcl_seq.md_tracks[last_md_track].record_track(127); return true; } From 5039fdd26ceec808e4989f9dce0be93c6a25999f Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 3 Mar 2020 22:13:22 +1100 Subject: [PATCH 08/27] Rewrite arp render engine, use sort algo. Add 16 modes --- avr/cores/megacommand/MCL/ArpPage.cpp | 61 ++-- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 442 ++++++++++++++++++----- avr/cores/megacommand/MCL/SeqPtcPage.h | 29 +- 3 files changed, 389 insertions(+), 143 deletions(-) diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp index f6a6dce19..3acc451d2 100644 --- a/avr/cores/megacommand/MCL/ArpPage.cpp +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -2,9 +2,9 @@ #include "MCL.h" MCLEncoder arp_oct(0, 3, ENCODER_RES_SEQ); -MCLEncoder arp_mode(0, 7, ENCODER_RES_SEQ); -MCLEncoder arp_speed(0, 4, ENCODER_RES_SEQ); -MCLEncoder arp_und(0, 3, ENCODER_RES_SEQ); +MCLEncoder arp_mode(0, 17, ENCODER_RES_SEQ); +MCLEncoder arp_speed(0, 3, ENCODER_RES_SEQ); +MCLEncoder arp_und(0, 1, ENCODER_RES_SEQ); void ArpPage::setup() {} @@ -37,11 +37,19 @@ void ArpPage::loop() { break; } } - if (encoders[1]->hasChanged() || encoders[2]->hasChanged() || encoders[3]->hasChanged()) { - seq_ptc_page.render_arp(); + if (encoders[1]->hasChanged() || encoders[2]->hasChanged() || + encoders[3]->hasChanged()) { + seq_ptc_page.render_arp(); } } +typedef char arp_name_t[4]; + +const arp_name_t arp_names[] PROGMEM = { + "UP", "DWN", "UD", "DU", "UND", "DNU", "CNV", "DIV", "CND", + "PU", "PD", "UPP", "DP", "UPM", "DM", "U2", "D2", "RND", +}; + void ArpPage::display() { if (!classic_display) { @@ -49,12 +57,9 @@ void ArpPage::display() { auto oldfont = oled_display.getFont(); oled_display.setFont(&TomThumb); - oled_display.fillRect(8, 2, 128 - 16, 32 - 2, BLACK); oled_display.drawRect(8 + 1, 2 + 1, 128 - 16 - 2, 32 - 2 - 2, WHITE); - - oled_display.setCursor(42, 10); oled_display.setTextColor(WHITE); @@ -70,37 +75,17 @@ void ArpPage::display() { case ARP_OFF: strcpy(str, "--"); break; - } - mcl_gui.draw_text_encoder(x + 0 * mcl_gui.knob_w, y, "ARP", str); - - switch (encoders[1]->cur) { - case ARP_UP: - strcpy(str, "UP"); - break; - case ARP_DOWN: - strcpy(str, "DWN"); + case ARP_SKIP: + strcpy(str, "SKP"); break; - case ARP_CIRC: - strcpy(str, "CIR"); - break; - case ARP_RND: - strcpy(str, "RND"); - break; - case ARP_UPTHUMB: - strcpy(str, "UPT"); - break; - case ARP_DOWNPINK: - strcpy(str, "DNP"); - break; - case ARP_UPPINK: - strcpy(str, "UPP"); - break; - case ARP_DOWNTHUMB: - strcpy(str, "DNT"); - break; - default: + case ARP_SHIFT: + strcpy(str, "SHF"); break; } + mcl_gui.draw_text_encoder(x + 0 * mcl_gui.knob_w, y, "ARP", str); + + m_strncpy_p(str, arp_names[encoders[1]->cur], 4); + mcl_gui.draw_text_encoder(x + 1 * mcl_gui.knob_w, y, "MODE", str); itoa(encoders[2]->cur, str, 10); @@ -114,7 +99,9 @@ void ArpPage::display() { } bool ArpPage::handleEvent(gui_event_t *event) { - if (EVENT_PRESSED(event, Buttons.BUTTON1) || EVENT_PRESSED(event, Buttons.BUTTON3) || EVENT_PRESSED(event, Buttons.BUTTON2) || + if (EVENT_PRESSED(event, Buttons.BUTTON1) || + EVENT_PRESSED(event, Buttons.BUTTON3) || + EVENT_PRESSED(event, Buttons.BUTTON2) || EVENT_PRESSED(event, Buttons.BUTTON4)) { GUI.ignoreNextEvent(event->source); GUI.popPage(); diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index ccc97ea21..4596aa6e8 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -199,6 +199,8 @@ void SeqPtcPage::loop() { if (ptc_param_oct.hasChanged() || ptc_param_scale.hasChanged()) { mcl_seq.ext_tracks[last_ext_track].buffer_notesoff(); note_mask = 0; + recalc_notemask(); + render_arp(); } #endif @@ -412,7 +414,7 @@ uint8_t SeqPtcPage::get_machine_pitch(uint8_t track, uint8_t pitch) { } void SeqPtcPage::trig_md(uint8_t pitch) { - pitch = octave_to_pitch() + pitch; + pitch = ptc_param_oct.cur * 12 + pitch; uint8_t next_track = get_next_voice(pitch); uint8_t machine_pitch = get_machine_pitch(next_track, pitch); MD.setTrackParam(next_track, 0, machine_pitch); @@ -475,14 +477,12 @@ void SeqPtcPage::remove_arp() { this, (midi_clock_callback_ptr_t)&SeqPtcPage::on_16_callback); } -uint8_t SeqPtcPage::arp_get_next_note_up(uint8_t cur) { +uint8_t SeqPtcPage::arp_get_next_note_down(uint8_t cur) {} +#define NOTE_RANGE 24 - for (uint8_t i = cur + 1; i < 24; i++) { - if (IS_BIT_SET32(note_mask, i)) { - return i; - } - } - for (uint8_t i = 0; i <= cur; i++) { +uint8_t SeqPtcPage::arp_get_next_note_up(int8_t cur) { + + for (int8_t i = cur + 1; i < NOTE_RANGE; i++) { if (IS_BIT_SET32(note_mask, i)) { return i; } @@ -490,54 +490,296 @@ uint8_t SeqPtcPage::arp_get_next_note_up(uint8_t cur) { return 255; } -uint8_t SeqPtcPage::arp_get_next_note_down(uint8_t cur) { - for (int8_t i = cur - 1; i >= 0; i--) { - if (IS_BIT_SET32(note_mask, i)) { - return i; +void SeqPtcPage::render_arp() { + DEBUG_PRINT_FN(); + if (!arp_enabled) { + return; + } + arp_len = 0; + + uint8_t num_of_notes; + uint8_t note = 0; + uint8_t b = 0; + + uint8_t sort_up[NOTE_RANGE]; + uint8_t sort_down[NOTE_RANGE]; + + note = arp_get_next_note_up(-1); + if (note != 255) { + num_of_notes++; + sort_up[0] = note; + } else { + return; + } + + // Collect notes, sort in ascending order + DEBUG_PRINTLN("collecting notes"); + for (uint8_t i = 1; i < NOTE_RANGE && note != 255; i++) { + note = arp_get_next_note_up(sort_up[i - 1]); + if (note != 255) { + num_of_notes++; + sort_up[i] = note; + DEBUG_PRINTLN(i); } } - for (uint8_t i = NUM_MD_TRACKS - 1; i >= cur; i--) { - if (IS_BIT_SET32(note_mask, i)) { - return i; + DEBUG_PRINTLN("finish"); + DEBUG_PRINTLN(num_of_notes); + if (num_of_notes == 0) { + return; + } + // Sort notes in descending order + + for (uint8_t i = 0; i < num_of_notes; i++) { + sort_down[num_of_notes - i - 1] = sort_up[i]; + } + note = 255; + + // Generate 1 itteration of the arp + switch (arp_mode.cur) { + + case ARP_UP2: + case ARP_UPM: + case ARP_UPP: + case ARP_UP: + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_up[i]; + arp_notes[i] = calc_pitch(note); + arp_len++; + } + break; + case ARP_DOWN2: + case ARP_DOWNM: + case ARP_DOWNP: + case ARP_DOWN: + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_down[i]; + arp_notes[i] = calc_pitch(note); + arp_len++; + } + break; + + case ARP_UPDOWN: + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_up[i]; + arp_notes[i] = calc_pitch(note); + arp_len++; + } + for (uint8_t i = 1; i < num_of_notes - 1; i++) { + note = sort_down[i]; + arp_notes[arp_len] = calc_pitch(note); + arp_len++; + } + break; + case ARP_DOWNUP: + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_down[i]; + arp_notes[i] = calc_pitch(note); + arp_len++; + } + for (uint8_t i = 1; i < num_of_notes - 1; i++) { + note = sort_up[i]; + arp_notes[arp_len] = calc_pitch(note); + arp_len++; + } + + break; + case ARP_UPNDOWN: + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_up[i]; + arp_notes[i] = calc_pitch(note); + arp_len++; } + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_down[i]; + arp_notes[arp_len] = calc_pitch(note); + arp_len++; + } + break; + case ARP_DOWNNUP: + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_down[i]; + arp_notes[i] = calc_pitch(note); + arp_len++; + } + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_up[i]; + arp_notes[arp_len] = calc_pitch(note); + arp_len++; + } + break; + case ARP_CONV: + for (uint8_t i = 0; i < num_of_notes; i++) { + if (i & 1) { + note = sort_down[b]; + b++; + } else { + note = sort_up[b]; + } + arp_notes[i] = calc_pitch(note); + arp_len++; + } + break; + case ARP_DIV: + for (uint8_t i = 0; i < num_of_notes; i++) { + if (i & 1) { + note = sort_up[b]; + b++; + } else { + note = sort_down[b]; + } + arp_notes[i] = calc_pitch(note); + arp_len++; + } + break; + case ARP_CONVDIV: + for (uint8_t i = 0; i < num_of_notes; i++) { + if (i & 1) { + note = sort_down[b]; + b++; + } else { + note = sort_up[b]; + } + arp_notes[i] = calc_pitch(note); + arp_len++; + } + b = 0; + for (uint8_t i = 1; i < num_of_notes; i++) { + if (i & 1) { + note = sort_down[b]; + b++; + } else { + note = sort_up[b]; + } + arp_notes[i] = calc_pitch(note); + arp_len++; + } + break; + case ARP_PINKUP: + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_up[i]; + arp_notes[arp_len] = calc_pitch(note); + arp_len += 2; + } + for (uint8_t i = 1; i < arp_len; i += 2) { + note = sort_down[0]; + arp_notes[i] = note; + } + + break; + + case ARP_PINKDOWN: + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_down[i]; + arp_notes[arp_len] = calc_pitch(note); + arp_len += 2; + } + for (uint8_t i = 1; i < arp_len; i += 2) { + note = sort_up[0]; + arp_notes[i] = note; + } + + break; + + } - return 255; -} + // Generate subsequent octave itterations + if (arp_mode.cur <= ARP_PINKDOWN) { + for (uint8_t n = 0; n < arp_oct.cur; n++) { + for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { + arp_notes[arp_len] = arp_notes[i] + (n + 1) * 12; + arp_len++; + } + } + } + else { + switch (arp_mode.cur) { + case ARP_UPP: + case ARP_DOWNP: + for (uint8_t n = 0; n < arp_oct.cur; n++) { + for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { + arp_notes[arp_len] = arp_notes[i]; + if (i == num_of_notes - 1) { arp_notes[arp_len] += (n + 1) * 12; } + arp_len++; + } + } + break; + case ARP_UPM: + case ARP_DOWNM: + for (uint8_t n = 0; n < arp_oct.cur; n++) { + for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { + arp_notes[arp_len] = arp_notes[i]; + if (i == 0) { arp_notes[arp_len] += (n + 1) * 12; } + arp_len++; + } + } + break; + case ARP_UP2: + case ARP_DOWN2: + for (uint8_t n = 0; n < arp_oct.cur; n++) { + for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { + arp_notes[arp_len] = arp_notes[i]; + if (!(i & 1)) { arp_notes[arp_len] += (n + 1) * 12; } + arp_len++; + } + } + break; -void SeqPtcPage::render_arp() { + + } + + } + if (arp_idx >= arp_len) { + arp_idx = arp_len - 1; + } +} +/* +void SeqPtcPage::render_arp2() { if (!arp_enabled) { return; } + if (arp_mode.cur == ARP_RND) { + arp_len = 1; + return; + } + uint8_t first_note = 255; + uint8_t last_note = 255; arp_len = 0; - for (uint8_t i = 0; i < ARP_MAX_NOTES && first_note == 255; i++) { + for (uint8_t i = 0; i < ARP_MAX_NOTES; i++) { if (IS_BIT_SET32(note_mask, i)) { - first_note = i; + last_note = i; + if (first_note == 255) { + first_note = i; + } } } if (first_note == 255) { return; } uint8_t idx = first_note; + uint8_t idx2 = last_note; uint8_t note = 255; uint8_t pitch = 255; uint8_t first_pitch = calc_pitch(first_note); -// arp_notes[0] = first_pitch; -// arp_len++; - - while (pitch != first_pitch && arp_len < ARP_MAX_NOTES) { + while (((pitch != first_pitch) || (arp_len == 1)) && + arp_len < ARP_MAX_NOTES) { bool ignore_base = false; + switch (arp_mode.cur) { case ARP_UP: - note = arp_get_next_note_up(idx); - if (note <= idx) { - if (arp_base < arp_oct.cur) { - arp_base++; - } else { - arp_base = 0; + if (arp_len == 0) { + note = first_note; + } else { + note = arp_get_next_note_up(idx); + if (note <= idx) { + if (arp_base < arp_oct.cur) { + arp_base++; + } else { + arp_base = 0; + } } } break; @@ -551,6 +793,24 @@ void SeqPtcPage::render_arp() { } } break; + case ARP_CONV: + if (arp_dir == 0) { + uint8_t note_tmp = arp_get_next_note_up(idx); + if (note_tmp < note) { + if (arp_base < arp_oct.cur) { + arp_base++; + } else { + arp_base = 0; + } + } + note = note_tmp; + arp_dir = 1; + } else { + note = arp_get_next_note_down(idx2); + idx2 = note; + arp_dir = 0; + } + break; case ARP_CIRC: uint8_t note_tmp; if (arp_dir == 0) { @@ -581,26 +841,6 @@ void SeqPtcPage::render_arp() { } } break; - case ARP_RND: - note = arp_get_next_note_down(get_random_byte() & 0xF); - arp_base = get_random_byte() & arp_oct.cur; - break; - case ARP_DOWNTHUMB: - note = arp_get_next_note_down(idx); - note_tmp = arp_get_next_note_up(idx); - ignore_base = true; - if (note_tmp < idx) { - ignore_base = false; - } - note = arp_get_next_note_down(idx); - if (note > idx) { - if (arp_base > 0) { - arp_base--; - } else { - arp_base = arp_oct.cur; - } - } - break; case ARP_UPTHUMB: note = arp_get_next_note_up(idx); note_tmp = arp_get_next_note_up(idx); @@ -631,21 +871,6 @@ void SeqPtcPage::render_arp() { } } break; - case ARP_UPPINK: - note = arp_get_next_note_up(idx); - note_tmp = arp_get_next_note_down(idx); - ignore_base = true; - if (note_tmp > idx) { - ignore_base = false; - } - if (note > idx) { - if (arp_base > 0) { - arp_base--; - } else { - arp_base = arp_oct.cur; - } - } - break; } if (note < NUM_MD_TRACKS) { idx = note; @@ -653,54 +878,66 @@ void SeqPtcPage::render_arp() { if (!ignore_base) { arp_notes[arp_len] += arp_base * 12; pitch = arp_notes[arp_len]; - } - else { + } else { pitch = arp_notes[arp_len] + arp_base * 12; } arp_len++; + } else { + break; } } - if (arp_idx >= arp_len) { arp_idx = arp_len - 1; } + if (arp_idx >= arp_len) { + arp_idx = arp_len - 1; + } } - +*/ void SeqPtcPage::on_16_callback() { bool trig = false; uint8_t note; - uint8_t arp_count_tmp = arp_count; - if (arp_und.cur == ARP_SHIFT) { - arp_count_tmp++; - } else if (((arp_und.cur == ARP_SKIP) && (arp_count_tmp != 0)) || (arp_und.cur == ARP_ON)) { - switch (arp_speed.cur) { - case 0: + switch (arp_speed.cur) { + case 0: + trig = true; + break; + case 1: + if ((arp_count == 0) || (arp_count == 2) || (arp_count == 4) || + (arp_count == 6)) { trig = true; - break; - case 1: - if ((arp_count_tmp == 0) || (arp_count_tmp == 2) || - (arp_count_tmp == 4) || (arp_count_tmp == 6)) { - trig = true; - } - break; - case 2: - if ((arp_count_tmp == 0) || (arp_count_tmp == 4)) { - trig = true; - } - break; - case 3: - if (arp_count_tmp == 0) { - trig = true; - } } + break; + case 2: + if ((arp_count == 0) || (arp_count == 4)) { + trig = true; + } + break; + case 3: + if (arp_count == 0) { + trig = true; + } + break; } + bool ignore_base = false; if (trig == true) { if (arp_len > 0) { - trig_md(arp_notes[arp_idx]); - arp_idx++; - if (arp_idx == arp_len) { - arp_idx = 0; - } + if (arp_mode.cur == ARP_RND) { + if (note_mask > 0) { + note = 255; + while (note == 255) { + note = arp_get_next_note_up(get_random_byte() & 0xF); + if (note == 255) { note = arp_get_next_note_down(get_random_byte() & 0xF); } + } + arp_base = get_random_byte() & arp_oct.cur; + trig_md(note + arp_base * 12); + } + } else { + trig_md(arp_notes[arp_idx]); + } + arp_idx++; + if (arp_idx == arp_len) { + arp_idx = 0; + } } } @@ -710,6 +947,15 @@ void SeqPtcPage::on_16_callback() { } } +void SeqPtcPage::recalc_notemask() { + for (uint8_t i = 0; i < 24; i++) { + if (note_interface.notes[i] == 1) { + uint8_t pitch = calc_pitch(i); + SET_BIT64(note_mask, pitch); + } + } +} + bool SeqPtcPage::handleEvent(gui_event_t *event) { if (SeqPage::handleEvent(event)) { @@ -829,8 +1075,8 @@ uint8_t SeqPtcPage::seq_ext_pitch(uint8_t note_num) { // } // if (seq_param5.getValue() > 0) { - pitch = - octave_to_pitch() + scales[ptc_param_scale.cur]->pitches[pos] + oct * 12; + pitch = ptc_param_oct.cur * 12 + scales[ptc_param_scale.cur]->pitches[pos] + + oct * 12; // } return pitch; diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index 2c6843698..bf6476819 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -6,6 +6,7 @@ #include "MidiActivePeering.h" #include "Scales.h" #include "SeqPage.h" +#include "SeqPages.h" #define MAX_POLY_NOTES 16 @@ -27,12 +28,23 @@ class SeqPtcMidiEvents : public MidiCallback { #define ARP_UP 0 #define ARP_DOWN 1 -#define ARP_CIRC 2 -#define ARP_RND 3 -#define ARP_UPTHUMB 4 -#define ARP_UPPINK 5 -#define ARP_DOWNPINK 6 -#define ARP_DOWNTHUMB 7 +#define ARP_UPDOWN 2 +#define ARP_DOWNUP 3 +#define ARP_UPNDOWN 4 +#define ARP_DOWNNUP 5 +#define ARP_CONV 6 +#define ARP_DIV 7 +#define ARP_CONVDIV 8 +#define ARP_PINKUP 9 +#define ARP_PINKDOWN 10 +#define ARP_UPP 11 +#define ARP_DOWNP 12 +#define ARP_UPM 13 +#define ARP_DOWNM 14 +#define ARP_UP2 15 +#define ARP_DOWN2 16 +#define ARP_RND 17 + #define ARP_ON 1 #define ARP_SKIP 2 @@ -66,7 +78,6 @@ class SeqPtcPage : public SeqPage, public ClockCallback { void trig_md_fromext(uint8_t note_num); void clear_trig_fromext(uint8_t note_num); - inline uint8_t octave_to_pitch() { return encoders[0]->getValue() * 12; } void config_encoders(); void init_poly(); void queue_redraw(); @@ -84,7 +95,9 @@ class SeqPtcPage : public SeqPage, public ClockCallback { void remove_arp(); void render_arp(); - uint8_t arp_get_next_note_up(uint8_t); + void recalc_notemask(); + + uint8_t arp_get_next_note_up(int8_t); uint8_t arp_get_next_note_down(uint8_t); void on_16_callback(); From aa11c96a724a1331746f0a0fb7d99cfe090981f1 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 4 Mar 2020 21:21:22 +1100 Subject: [PATCH 09/27] Don't call clockcallbacks twice when starting --- avr/cores/megacommand/Midi/MidiClock.h | 1 - 1 file changed, 1 deletion(-) diff --git a/avr/cores/megacommand/Midi/MidiClock.h b/avr/cores/megacommand/Midi/MidiClock.h index 2fa3b67d3..b3446ad44 100644 --- a/avr/cores/megacommand/Midi/MidiClock.h +++ b/avr/cores/megacommand/Midi/MidiClock.h @@ -391,7 +391,6 @@ class MidiClockClass { } else if (state == STARTING && (mode == INTERNAL_MIDI || useImmediateClock)) { state = STARTED; - callCallbacks(true); } } From ca9aba8722476aca1f7e44843dce78fbbf75330c Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Wed, 4 Mar 2020 21:30:55 +1100 Subject: [PATCH 10/27] init trig interface when opening PolyPage --- avr/cores/megacommand/MCL/PolyPage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/avr/cores/megacommand/MCL/PolyPage.cpp b/avr/cores/megacommand/MCL/PolyPage.cpp index 2c2bd5e88..61d27ceb5 100644 --- a/avr/cores/megacommand/MCL/PolyPage.cpp +++ b/avr/cores/megacommand/MCL/PolyPage.cpp @@ -8,6 +8,7 @@ void PolyPage::init() { poly_mask = &mcl_cfg.poly_mask; DEBUG_PRINT_FN(); trig_interface.on(); + note_interface.init_notes(); note_interface.state = true; #ifdef OLED_DISPLAY classic_display = false; From 29354ee8e37a32f2c88cc1aa52ed25d2951d431e Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Thu, 5 Mar 2020 22:52:33 +1100 Subject: [PATCH 11/27] Add LATCH mode. Improve algo for RND. Add THUMB modes. Fix PINK modes --- avr/cores/megacommand/MCL/ArpPage.cpp | 15 +-- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 141 ++++++++++++----------- avr/cores/megacommand/MCL/SeqPtcPage.h | 11 +- 3 files changed, 85 insertions(+), 82 deletions(-) diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp index 3acc451d2..5504ea7c7 100644 --- a/avr/cores/megacommand/MCL/ArpPage.cpp +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -4,7 +4,7 @@ MCLEncoder arp_oct(0, 3, ENCODER_RES_SEQ); MCLEncoder arp_mode(0, 17, ENCODER_RES_SEQ); MCLEncoder arp_speed(0, 3, ENCODER_RES_SEQ); -MCLEncoder arp_und(0, 1, ENCODER_RES_SEQ); +MCLEncoder arp_und(0, 2, ENCODER_RES_SEQ); void ArpPage::setup() {} @@ -36,6 +36,10 @@ void ArpPage::loop() { seq_ptc_page.remove_arp(); break; } + if (encoders[0]->old > 1) { + seq_ptc_page.note_mask = 0; + seq_ptc_page.render_arp(); + } } if (encoders[1]->hasChanged() || encoders[2]->hasChanged() || encoders[3]->hasChanged()) { @@ -47,7 +51,7 @@ typedef char arp_name_t[4]; const arp_name_t arp_names[] PROGMEM = { "UP", "DWN", "UD", "DU", "UND", "DNU", "CNV", "DIV", "CND", - "PU", "PD", "UPP", "DP", "UPM", "DM", "U2", "D2", "RND", + "PU", "PD", "TU", "TD", "UPP", "DP", "U2", "D2", "RND", }; void ArpPage::display() { @@ -75,11 +79,8 @@ void ArpPage::display() { case ARP_OFF: strcpy(str, "--"); break; - case ARP_SKIP: - strcpy(str, "SKP"); - break; - case ARP_SHIFT: - strcpy(str, "SHF"); + case ARP_LATCH: + strcpy(str, "LAT"); break; } mcl_gui.draw_text_encoder(x + 0 * mcl_gui.knob_w, y, "ARP", str); diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index 4596aa6e8..dc7524895 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -536,9 +536,14 @@ void SeqPtcPage::render_arp() { // Generate 1 itteration of the arp switch (arp_mode.cur) { + case ARP_RND: + for (uint8_t i = 0; i < num_of_notes; i++) { + note = sort_up[random(0, num_of_notes)]; + arp_notes[arp_len++] = calc_pitch(note) + 12 * random(0,arp_oct.cur); + } + break; case ARP_UP2: - case ARP_UPM: case ARP_UPP: case ARP_UP: for (uint8_t i = 0; i < num_of_notes; i++) { @@ -548,7 +553,6 @@ void SeqPtcPage::render_arp() { } break; case ARP_DOWN2: - case ARP_DOWNM: case ARP_DOWNP: case ARP_DOWN: for (uint8_t i = 0; i < num_of_notes; i++) { @@ -655,79 +659,87 @@ void SeqPtcPage::render_arp() { } break; case ARP_PINKUP: - for (uint8_t i = 0; i < num_of_notes; i++) { - note = sort_up[i]; - arp_notes[arp_len] = calc_pitch(note); - arp_len += 2; + if (num_of_notes == 1) { + note = sort_up[0]; + arp_notes[arp_len++] = calc_pitch(note); } - for (uint8_t i = 1; i < arp_len; i += 2) { + for (uint8_t i = 0; i < num_of_notes - 1; i++) { + note = sort_up[i]; + arp_notes[arp_len++] = calc_pitch(note); note = sort_down[0]; - arp_notes[i] = note; + arp_notes[arp_len++] = calc_pitch(note); } break; case ARP_PINKDOWN: - for (uint8_t i = 0; i < num_of_notes; i++) { + for (uint8_t i = 1; i < num_of_notes; i++) { note = sort_down[i]; - arp_notes[arp_len] = calc_pitch(note); - arp_len += 2; + arp_notes[arp_len++] = calc_pitch(note); + note = sort_down[0]; + arp_notes[arp_len++] = calc_pitch(note); } - for (uint8_t i = 1; i < arp_len; i += 2) { - note = sort_up[0]; - arp_notes[i] = note; + break; + + case ARP_THUMBUP: + if (num_of_notes == 1) { + note = sort_down[0]; + arp_notes[arp_len++] = calc_pitch(note); + } + for (uint8_t i = 0; i < num_of_notes - 1; i++) { + note = sort_up[i]; + arp_notes[arp_len++] = calc_pitch(note); + note = sort_down[0]; + arp_notes[arp_len++] = calc_pitch(note); } break; - + case ARP_THUMBDOWN: + for (uint8_t i = 1; i < num_of_notes; i++) { + note = sort_down[i]; + arp_notes[arp_len++] = calc_pitch(note); + note = sort_down[0]; + arp_notes[arp_len++] = calc_pitch(note); + } + break; } // Generate subsequent octave itterations - if (arp_mode.cur <= ARP_PINKDOWN) { - for (uint8_t n = 0; n < arp_oct.cur; n++) { - for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { - arp_notes[arp_len] = arp_notes[i] + (n + 1) * 12; - arp_len++; - } - } - } - else { - switch (arp_mode.cur) { - case ARP_UPP: - case ARP_DOWNP: + if (arp_mode.cur <= ARP_THUMBDOWN) { for (uint8_t n = 0; n < arp_oct.cur; n++) { for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { - arp_notes[arp_len] = arp_notes[i]; - if (i == num_of_notes - 1) { arp_notes[arp_len] += (n + 1) * 12; } + arp_notes[arp_len] = arp_notes[i] + (n + 1) * 12; arp_len++; } - } - break; - case ARP_UPM: - case ARP_DOWNM: - for (uint8_t n = 0; n < arp_oct.cur; n++) { - for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { - arp_notes[arp_len] = arp_notes[i]; - if (i == 0) { arp_notes[arp_len] += (n + 1) * 12; } - arp_len++; + } + } else { + switch (arp_mode.cur) { + case ARP_UPP: + case ARP_DOWNP: + for (uint8_t n = 0; n < arp_oct.cur; n++) { + for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { + arp_notes[arp_len] = arp_notes[i]; + if (i == num_of_notes - 1) { + arp_notes[arp_len] += (n + 1) * 12; + } + arp_len++; + } } - } - break; - case ARP_UP2: - case ARP_DOWN2: - for (uint8_t n = 0; n < arp_oct.cur; n++) { - for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { - arp_notes[arp_len] = arp_notes[i]; - if (!(i & 1)) { arp_notes[arp_len] += (n + 1) * 12; } - arp_len++; + break; + case ARP_UP2: + case ARP_DOWN2: + for (uint8_t n = 0; n < arp_oct.cur; n++) { + for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { + arp_notes[arp_len] = arp_notes[i]; + if (!(i & 1)) { + arp_notes[arp_len] += (n + 1) * 12; + } + arp_len++; + } } - } - break; - - - } - + break; + } } if (arp_idx >= arp_len) { arp_idx = arp_len - 1; @@ -921,19 +933,7 @@ void SeqPtcPage::on_16_callback() { if (trig == true) { if (arp_len > 0) { - if (arp_mode.cur == ARP_RND) { - if (note_mask > 0) { - note = 255; - while (note == 255) { - note = arp_get_next_note_up(get_random_byte() & 0xF); - if (note == 255) { note = arp_get_next_note_down(get_random_byte() & 0xF); } - } - arp_base = get_random_byte() & arp_oct.cur; - trig_md(note + arp_base * 12); - } - } else { - trig_md(arp_notes[arp_idx]); - } + trig_md(arp_notes[arp_idx]); arp_idx++; if (arp_idx == arp_len) { arp_idx = 0; @@ -992,13 +992,14 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { } midi_device = device; - if (!arp_enabled) { + if ((!arp_enabled) || (MidiClock.state != 2)) { trig_md(pitch); } } else if (mask == EVENT_BUTTON_RELEASED) { - + if (arp_und.cur != ARP_LATCH) { CLEAR_BIT64(note_mask, pitch); render_arp(); + } } // deferred trigger redraw to update TI keyboard feedback. @@ -1152,8 +1153,10 @@ void SeqPtcMidiEvents::onNoteOffCallback_Midi2(uint8_t *msg) { uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); uint8_t pitch = seq_ptc_page.calc_pitch(note_num); uint8_t scaled_pitch = pitch - (pitch / 24) * 24; + if (arp_und.cur != ARP_LATCH) { CLEAR_BIT64(seq_ptc_page.note_mask, scaled_pitch); - + seq_ptc_page.render_arp(); + } if ((mcl_cfg.uart2_ctrl_mode - 1 == channel) || (mcl_cfg.uart2_ctrl_mode == MIDI_OMNI_MODE)) { seq_ptc_page.clear_trig_fromext(pitch); diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index bf6476819..2159f308d 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -37,18 +37,17 @@ class SeqPtcMidiEvents : public MidiCallback { #define ARP_CONVDIV 8 #define ARP_PINKUP 9 #define ARP_PINKDOWN 10 -#define ARP_UPP 11 -#define ARP_DOWNP 12 -#define ARP_UPM 13 -#define ARP_DOWNM 14 +#define ARP_THUMBUP 11 +#define ARP_THUMBDOWN 12 +#define ARP_UPP 13 +#define ARP_DOWNP 14 #define ARP_UP2 15 #define ARP_DOWN2 16 #define ARP_RND 17 #define ARP_ON 1 -#define ARP_SKIP 2 -#define ARP_SHIFT 3 +#define ARP_LATCH 2 #define ARP_OFF 0 #define ARP_MAX_NOTES 16 * 3 From 3734af53b1f5b0b7b7ddc1b8b3c21dd88b9143c9 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 6 Mar 2020 18:18:45 +1100 Subject: [PATCH 12/27] Add back in more chords --- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 37 ++++++++++-------------- avr/cores/megacommand/MCL/SeqPtcPage.h | 3 +- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index dc7524895..432c0637d 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -5,25 +5,18 @@ #define MIDI_LOCAL_MODE 0 #define NUM_KEYS 24 -scale_t *scales[16]{ - &chromaticScale, &ionianScale, - //&dorianScale, - &phrygianScale, - //&lydianScale, - //&mixolydianScale, - //&aeolianScale, - //&locrianScale, - &harmonicMinorScale, &melodicMinorScale, +scale_t *scales[24]{ + &chromaticScale, &ionianScale, &dorianScale, &phrygianScale, &lydianScale, + &mixolydianScale, &aeolianScale, &locrianScale, &harmonicMinorScale, + &melodicMinorScale, //&lydianDominantScale, //&wholeToneScale, //&wholeHalfStepScale, //&halfWholeStepScale, &majorPentatonicScale, &minorPentatonicScale, &suspendedPentatonicScale, - &inSenScale, &bluesScale, - //&majorBebopScale, - //&dominantBebopScale, - //&minorBebopScale, - &majorArp, &minorArp, &majorMaj7Arp, &majorMin7Arp, &minorMin7Arp, + &inSenScale, &bluesScale, &majorBebopScale, &dominantBebopScale, + &minorBebopScale, &majorArp, &minorArp, &majorMaj7Arp, &majorMin7Arp, + &minorMin7Arp, //&minorMaj7Arp, &majorMaj7Arp9, //&majorMaj7ArpMin9, @@ -38,8 +31,9 @@ scale_t *scales[16]{ typedef char scale_name_t[4]; const scale_name_t scale_names[] PROGMEM = { - "---", "ION", "PHR", "mHA", "mME", "MPE", "mPE", "sPE", - "ISS", "BLU", "MAJ", "MIN", "MM7", "Mm7", "mm7", "M79", + "---", "MAJ", "DOR", "PHR", "LYD", "MIX", "MIN", "LOC", + "mHA", "mME", "MPE", "mPE", "sPE", "ISS", "BLU", "MBP", + "DBP", "mBP", "MA", "MIA", "MM7", "Mm7", "mm7", "M79", }; void SeqPtcPage::setup() { @@ -534,12 +528,11 @@ void SeqPtcPage::render_arp() { } note = 255; - // Generate 1 itteration of the arp switch (arp_mode.cur) { case ARP_RND: for (uint8_t i = 0; i < num_of_notes; i++) { note = sort_up[random(0, num_of_notes)]; - arp_notes[arp_len++] = calc_pitch(note) + 12 * random(0,arp_oct.cur); + arp_notes[arp_len++] = calc_pitch(note) + 12 * random(0, arp_oct.cur); } break; @@ -997,8 +990,8 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { } } else if (mask == EVENT_BUTTON_RELEASED) { if (arp_und.cur != ARP_LATCH) { - CLEAR_BIT64(note_mask, pitch); - render_arp(); + CLEAR_BIT64(note_mask, pitch); + render_arp(); } } @@ -1154,8 +1147,8 @@ void SeqPtcMidiEvents::onNoteOffCallback_Midi2(uint8_t *msg) { uint8_t pitch = seq_ptc_page.calc_pitch(note_num); uint8_t scaled_pitch = pitch - (pitch / 24) * 24; if (arp_und.cur != ARP_LATCH) { - CLEAR_BIT64(seq_ptc_page.note_mask, scaled_pitch); - seq_ptc_page.render_arp(); + CLEAR_BIT64(seq_ptc_page.note_mask, scaled_pitch); + seq_ptc_page.render_arp(); } if ((mcl_cfg.uart2_ctrl_mode - 1 == channel) || (mcl_cfg.uart2_ctrl_mode == MIDI_OMNI_MODE)) { diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index 2159f308d..063051182 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -10,7 +10,7 @@ #define MAX_POLY_NOTES 16 -extern scale_t *scales[16]; +extern scale_t *scales[24]; void ptc_pattern_len_handler(Encoder *enc); @@ -45,7 +45,6 @@ class SeqPtcMidiEvents : public MidiCallback { #define ARP_DOWN2 16 #define ARP_RND 17 - #define ARP_ON 1 #define ARP_LATCH 2 #define ARP_OFF 0 From 1f79b2b3021a90e857df9bf613751d10500171f2 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 6 Mar 2020 20:45:36 +1100 Subject: [PATCH 13/27] Remove undocumented button commands from ptc page --- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index 432c0637d..d0fed2220 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -412,14 +412,10 @@ void SeqPtcPage::trig_md(uint8_t pitch) { uint8_t next_track = get_next_voice(pitch); uint8_t machine_pitch = get_machine_pitch(next_track, pitch); MD.setTrackParam(next_track, 0, machine_pitch); - if (!BUTTON_DOWN(Buttons.BUTTON2)) { - MD.triggerTrack(next_track, 127); - } + MD.triggerTrack(next_track, 127); if ((recording) && (MidiClock.state == 2)) { - if (!BUTTON_DOWN(Buttons.BUTTON2)) { - mcl_seq.md_tracks[next_track].record_track(127); - } + mcl_seq.md_tracks[next_track].record_track(127); mcl_seq.md_tracks[next_track].record_track_pitch(machine_pitch); } } @@ -437,13 +433,9 @@ void SeqPtcPage::trig_md_fromext(uint8_t note_num) { SET_BIT64(note_mask, pitch); render_arp(); MD.setTrackParam(next_track, 0, machine_pitch); - if (!BUTTON_DOWN(Buttons.BUTTON2)) { - MD.triggerTrack(next_track, 127); - } + MD.triggerTrack(next_track, 127); if ((recording) && (MidiClock.state == 2)) { - if (!BUTTON_DOWN(Buttons.BUTTON2)) { - mcl_seq.md_tracks[next_track].record_track(127); - } + mcl_seq.md_tracks[next_track].record_track(127); mcl_seq.md_tracks[next_track].record_track_pitch(machine_pitch); } } From fa9340118f4f2123968aecf47a453ecb6893e1eb Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Fri, 6 Mar 2020 22:00:54 +1100 Subject: [PATCH 14/27] fix active peering on chromatic page --- avr/cores/megacommand/MCL/MidiActivePeering.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/avr/cores/megacommand/MCL/MidiActivePeering.cpp b/avr/cores/megacommand/MCL/MidiActivePeering.cpp index 02d4da947..bbee4f049 100644 --- a/avr/cores/megacommand/MCL/MidiActivePeering.cpp +++ b/avr/cores/megacommand/MCL/MidiActivePeering.cpp @@ -35,6 +35,13 @@ void MidiActivePeering::delay_progress(uint16_t clock_) { void MidiActivePeering::md_setup() { DEBUG_PRINT_FN(); + + bool ts = md_track_select.state; + bool ti = trig_interface.state; + + if (ts) { md_track_select.off(); } + if (ti) { trig_interface.off(); } + MidiIDSysexListener.setup(&Midi); MidiUart.set_speed((uint32_t)31250, 1); #ifdef OLED_DISPLAY @@ -100,7 +107,11 @@ void MidiActivePeering::md_setup() { delay(250); } } + MidiIDSysexListener.cleanup(); + if (ts) { md_track_select.on(); } + if (ti) { trig_interface.on(); } + GUI.currentPage()->redisplay = true; #ifdef OLED_DISPLAY oled_display.setFont(oldfont); #endif From 86772c39809f5800af06f2f91dc4553903baa888 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sat, 7 Mar 2020 16:25:34 +1100 Subject: [PATCH 15/27] Fix sysex handler overuse, causing ti bug on poly page --- avr/cores/megacommand/MCL/MDTrackSelect.cpp | 9 +++++---- avr/cores/megacommand/MCL/PolyPage.cpp | 3 --- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 15 +++++++++++---- avr/cores/megacommand/MCL/TrigInterface.cpp | 6 +++--- avr/cores/megacommand/Midi/MidiSysex.hh | 7 ++++++- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/avr/cores/megacommand/MCL/MDTrackSelect.cpp b/avr/cores/megacommand/MCL/MDTrackSelect.cpp index 83932842a..5d362fa63 100644 --- a/avr/cores/megacommand/MCL/MDTrackSelect.cpp +++ b/avr/cores/megacommand/MCL/MDTrackSelect.cpp @@ -7,27 +7,28 @@ void MDTrackSelect::start() { } bool MDTrackSelect::on() { - MD.activate_track_select(); - sysex->addSysexListener(this); if (state) { return false; } if (!MD.connected) { return false; } + MD.activate_track_select(); + sysex->addSysexListener(this); + state = true; return true; } bool MDTrackSelect::off() { - MD.deactivate_track_select(); - sysex->removeSysexListener(this); if (!state) { return false; } if (!MD.connected) { return false; } + MD.deactivate_track_select(); + sysex->removeSysexListener(this); state = false; return true; } diff --git a/avr/cores/megacommand/MCL/PolyPage.cpp b/avr/cores/megacommand/MCL/PolyPage.cpp index 61d27ceb5..5b70ddb5d 100644 --- a/avr/cores/megacommand/MCL/PolyPage.cpp +++ b/avr/cores/megacommand/MCL/PolyPage.cpp @@ -9,7 +9,6 @@ void PolyPage::init() { DEBUG_PRINT_FN(); trig_interface.on(); note_interface.init_notes(); - note_interface.state = true; #ifdef OLED_DISPLAY classic_display = false; oled_display.clearDisplay(); @@ -18,9 +17,7 @@ void PolyPage::init() { } void PolyPage::cleanup() { - // md_exploit.off(); seq_ptc_page.init_poly(); - note_interface.state = false; #ifdef OLED_DISPLAY oled_display.clearDisplay(); #endif diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index d0fed2220..fdc48b330 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -43,6 +43,7 @@ void SeqPtcPage::setup() { } void SeqPtcPage::cleanup() { SeqPage::cleanup(); + //trig_interface.off(); recording = false; if (MidiClock.state != 2) { MD.setTrackParam(last_md_track, 0, MD.kit.params[last_md_track][0]); @@ -88,10 +89,10 @@ void SeqPtcPage::init() { seq_menu_page.menu.enable_entry(0, true); ptc_param_len.handler = ptc_pattern_len_handler; recording = false; - midi_events.setup_callbacks(); note_mask = 0; DEBUG_PRINTLN("control mode:"); DEBUG_PRINTLN(mcl_cfg.uart2_ctrl_mode); + trig_interface.on(); if (mcl_cfg.uart2_ctrl_mode == MIDI_LOCAL_MODE) { trig_interface.on(); note_interface.state = true; @@ -288,7 +289,6 @@ void SeqPtcPage::display() { oled_display.clearDisplay(); auto *oldfont = oled_display.getFont(); - if (midi_device == DEVICE_MD) { dev_num = last_md_track; } @@ -338,6 +338,11 @@ void SeqPtcPage::display() { // draw TI keyboard mcl_gui.draw_keyboard(32, 23, 6, 9, NUM_KEYS, note_mask); + oled_display.setFont(&TomThumb); + if (mcl_cfg.poly_mask > 0) { + oled_display.setCursor(107, 32); + oled_display.print("POLY"); + } SeqPage::display(); oled_display.display(); oled_display.setFont(oldfont); @@ -995,12 +1000,13 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { if (EVENT_RELEASED(event, Buttons.BUTTON1)) { if (BUTTON_DOWN(Buttons.BUTTON4)) { - re_init = true; - GUI.pushPage(&poly_page); + re_init = true; + GUI.pushPage(&poly_page); return true; } seq_ptc_page.queue_redraw(); recording = !recording; + if (recording) { oled_display.textbox("RECORDING", ""); } return true; } /* @@ -1012,6 +1018,7 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { if (EVENT_RELEASED(event, Buttons.BUTTON4)) { if (BUTTON_DOWN(Buttons.BUTTON1)) { + re_init = true; GUI.pushPage(&poly_page); return true; } diff --git a/avr/cores/megacommand/MCL/TrigInterface.cpp b/avr/cores/megacommand/MCL/TrigInterface.cpp index a7f312eb9..5085eae84 100644 --- a/avr/cores/megacommand/MCL/TrigInterface.cpp +++ b/avr/cores/megacommand/MCL/TrigInterface.cpp @@ -27,14 +27,14 @@ bool TrigInterface::on() { } bool TrigInterface::off() { - sysex->removeSysexListener(this); - note_interface.note_proceed = false; - if (!state) { + if (!state) { return false; } if (!MD.connected) { return false; } + sysex->removeSysexListener(this); + note_interface.note_proceed = false; DEBUG_PRINTLN("deactiviating trig interface"); state = false; MD.deactivate_trig_interface(); diff --git a/avr/cores/megacommand/Midi/MidiSysex.hh b/avr/cores/megacommand/Midi/MidiSysex.hh index 7003872cc..5ea6a6da5 100644 --- a/avr/cores/megacommand/Midi/MidiSysex.hh +++ b/avr/cores/megacommand/Midi/MidiSysex.hh @@ -156,7 +156,12 @@ public: } bool addSysexListener(MidiSysexListenerClass *listener) { for (int i = 0; i < NUM_SYSEX_SLAVES; i++) { - if (listeners[i] == NULL || listeners[i] == listener) { + if (listeners[i] == listener) { + return true; + } + } + for (int i = 0; i < NUM_SYSEX_SLAVES; i++) { + if (listeners[i] == NULL) { listeners[i] = listener; listener->sysex = this; return true; From 7f32f2b8659580307bf327261b8473dee96a763f Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sat, 7 Mar 2020 16:30:32 +1100 Subject: [PATCH 16/27] increase scale count to 24 --- avr/cores/megacommand/MCL/SeqPages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/SeqPages.cpp b/avr/cores/megacommand/MCL/SeqPages.cpp index 54e01e6b6..30c894328 100644 --- a/avr/cores/megacommand/MCL/SeqPages.cpp +++ b/avr/cores/megacommand/MCL/SeqPages.cpp @@ -11,7 +11,7 @@ MCLEncoder seq_lock2(0, 127, ENCODER_RES_PARAM); MCLEncoder ptc_param_oct(0, 8, ENCODER_RES_SEQ); MCLEncoder ptc_param_finetune(0, 64, ENCODER_RES_SEQ); MCLEncoder ptc_param_len(0, 64, ENCODER_RES_SEQ); -MCLEncoder ptc_param_scale(0, 15, ENCODER_RES_SEQ); +MCLEncoder ptc_param_scale(0, 23, ENCODER_RES_SEQ); SeqParamPage seq_param_page[NUM_PARAM_PAGES]; SeqStepPage seq_step_page(&seq_param1, &seq_param2, &seq_param3, &seq_param4); From 8385d4a5db96fefbb1f7e9d803383587a9987097 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sat, 7 Mar 2020 17:28:33 +1100 Subject: [PATCH 17/27] Add CC listened on Midi2 for Poly Tracks, CC messages 16, 39 control MD params 0,23. --- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 36 ++++++++++++++++++++++-- avr/cores/megacommand/MCL/SeqPtcPage.h | 1 + 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index fdc48b330..6d386d71a 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -193,7 +193,6 @@ void SeqPtcPage::loop() { #ifdef EXT_TRACKS if (ptc_param_oct.hasChanged() || ptc_param_scale.hasChanged()) { mcl_seq.ext_tracks[last_ext_track].buffer_notesoff(); - note_mask = 0; recalc_notemask(); render_arp(); } @@ -320,7 +319,12 @@ void SeqPtcPage::display() { // draw LEN if (midi_device == DEVICE_MD) { itoa(ptc_param_len.getValue(), buf1, 10); + if (mcl_cfg.poly_mask > 0) { + draw_knob(2, "PLEN", buf1); + } + else { draw_knob(2, "LEN", buf1); + } } #ifdef EXT_TRACKS else { @@ -938,6 +942,7 @@ void SeqPtcPage::on_16_callback() { } void SeqPtcPage::recalc_notemask() { + note_mask = 0; for (uint8_t i = 0; i < 24; i++) { if (note_interface.notes[i] == 1) { uint8_t pitch = calc_pitch(i); @@ -1171,14 +1176,31 @@ void SeqPtcMidiEvents::onNoteOffCallback_Midi2(uint8_t *msg) { #endif } -void SeqPtcMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { +void SeqPtcMidiEvents::onControlChangeCallback_Midi2(uint8_t *msg) { uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); uint8_t param = msg[1]; uint8_t value = msg[2]; uint8_t track; uint8_t track_param; - // If external keyboard controlling MD pitch, send parameter updates + // If external keyboard controlling MD param, send parameter updates // to all polyphonic tracks + if ((param < 16) || (param > 39)) { return; } + // If Midi2 forwarding data to port 1 , ignore this to prevent double messages. + // + if (mcl_cfg.midi_forward == 2) { return; } + if ((mcl_cfg.uart2_ctrl_mode - 1 == channel) || + (mcl_cfg.uart2_ctrl_mode == MIDI_OMNI_MODE)) { + for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { + if (IS_BIT_SET16(mcl_cfg.poly_mask,n)) { MD.setTrackParam(n, param - 16, value); } + } + } +} +void SeqPtcMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { + uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); + uint8_t param = msg[1]; + uint8_t value = msg[2]; + uint8_t track; + uint8_t track_param; MD.parseCC(channel, param, &track, &track_param); uint8_t start_track; @@ -1209,6 +1231,10 @@ void SeqPtcMidiEvents::setup_callbacks() { Midi.addOnControlChangeCallback( this, (midi_callback_ptr_t)&SeqPtcMidiEvents::onControlChangeCallback_Midi); + Midi2.addOnControlChangeCallback( + this, + (midi_callback_ptr_t)&SeqPtcMidiEvents::onControlChangeCallback_Midi2); + state = true; } @@ -1226,6 +1252,10 @@ void SeqPtcMidiEvents::remove_callbacks() { Midi.removeOnControlChangeCallback( this, (midi_callback_ptr_t)&SeqPtcMidiEvents::onControlChangeCallback_Midi); + Midi.removeOnControlChangeCallback( + this, + (midi_callback_ptr_t)&SeqPtcMidiEvents::onControlChangeCallback_Midi2); + state = false; } diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index 063051182..1b62d0a4a 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -24,6 +24,7 @@ class SeqPtcMidiEvents : public MidiCallback { void onNoteOnCallback_Midi2(uint8_t *msg); void onNoteOffCallback_Midi2(uint8_t *msg); void onControlChangeCallback_Midi(uint8_t *msg); + void onControlChangeCallback_Midi2(uint8_t *msg); }; #define ARP_UP 0 From 075d574beb91f5253b4b72eae33b4d76d14afad4 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sat, 7 Mar 2020 18:27:44 +1100 Subject: [PATCH 18/27] create new icon sprites for RAM pages --- art/sprites/ram_1_icon.png | Bin 0 -> 303 bytes art/sprites/ram_2_icon.png | Bin 0 -> 283 bytes avr/cores/megacommand/MCL/MCLGUI.cpp | 70 +++++++++++++------ avr/cores/megacommand/MCL/MCLGUI.h | 4 ++ avr/cores/megacommand/MCL/PageSelectPage.cpp | 4 +- 5 files changed, 54 insertions(+), 24 deletions(-) create mode 100644 art/sprites/ram_1_icon.png create mode 100644 art/sprites/ram_2_icon.png diff --git a/art/sprites/ram_1_icon.png b/art/sprites/ram_1_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..980823fc700ec11ba20912454401dc24dee87caf GIT binary patch literal 303 zcmV+~0nq-5P)X1^@s6D=Y3@00001b5ch_0Itp) z=>Px#=}AOER7efQQ~?eHAqdlD|NpYPCRfuTh`VTJa#5hPfbnW6rCr~#^*Y9U6TelU zwLQ($T03nQ0J#P_;=w_=j*sZLKp&Bv#IN@ejn@^>8B)j+Sd7|Q>~us?k`iQ?P#{Z$ z$O^_4;5a}Kk*r`)gnI`FkO1dstzg^^BEl#Bumh4|M6;E3fuBZa$jD|w8dK3P0R`LRBYGtvCCO(=s>|Bu(tJiaSCG}1Q=xHw7Ju7iQ#9ASnQ#If>zEDw4%sM-@ytw zFkbcWhaGs;AR$^&2ZMmE#M)LMjb91X1^@s6D=Y3@00001b5ch_0Itp) z=>Px#)k#D_R7efIQ~?fyAP|FP|Nk;u6HB`0z(ZvuhU4h9Tv2N&rG1}mtbJrKs0jtI5s@OVBZHY*q-0m)VFx74Tr{!K40HPr=!`5Ph;nM(k3a;z zoBRJAxJ~*xdW`NAuhy{hTOBC5iwy 2) { resolution = 1; } + if (resolution == 0) { + resolution = 1; + } + if (resolution > 2) { + resolution = 1; + } uint8_t degrees = 24 / resolution; uint8_t heights[12]; if (resolution == 1) { - uint8_t heights_highres[12] = { 12, 2, 4, 8, 6, 2, 10, 2, 6, 8, 4, 2 }; - memcpy(&heights, &heights_highres, 12); - } - else { - uint8_t heights_lowres[6] = { 12, 4, 6, 10, 4, 8 }; - memcpy(&heights, &heights_lowres, 6); + uint8_t heights_highres[12] = {12, 2, 4, 8, 6, 2, 10, 2, 6, 8, 4, 2}; + memcpy(&heights, &heights_highres, 12); + } else { + uint8_t heights_lowres[6] = {12, 4, 6, 10, 4, 8}; + memcpy(&heights, &heights_lowres, 6); } uint8_t y_pos = 11; uint8_t a = 0; @@ -459,23 +462,27 @@ void MCLGUI::draw_microtiming(uint8_t resolution, uint8_t timing) { uint8_t x_w = (w / (degrees)); uint8_t x = x_pos; - oled_display.fillRect(8,2,128 - 16, 32 - 2,BLACK); + oled_display.fillRect(8, 2, 128 - 16, 32 - 2, BLACK); oled_display.drawRect(8 + 1, 2 + 1, 128 - 16 - 2, 32 - 2 - 2, WHITE); oled_display.setCursor(x_pos + 34, 10); oled_display.print("uTIMING"); - - oled_display.drawLine(x, y_pos + heights[0], x + w, y_pos + heights[0], WHITE); + + oled_display.drawLine(x, y_pos + heights[0], x + w, y_pos + heights[0], + WHITE); for (uint8_t n = 0; n <= degrees; n++) { - oled_display.drawLine(x, y_pos + heights[0], x, y_pos + heights[0] - heights[a] , WHITE); - a++; - if (n == timing) { - oled_display.fillRect(x - 1, y_pos + heights[0] + 3, 3, 3, WHITE); - oled_display.drawPixel(x, y_pos + heights[0] + 2, WHITE); - } + oled_display.drawLine(x, y_pos + heights[0], x, + y_pos + heights[0] - heights[a], WHITE); + a++; + if (n == timing) { + oled_display.fillRect(x - 1, y_pos + heights[0] + 3, 3, 3, WHITE); + oled_display.drawPixel(x, y_pos + heights[0] + 2, WHITE); + } - if (a == degrees / 2) { a = 0; } - x += x_w; + if (a == degrees / 2) { + a = 0; + } + x += x_w; } oled_display.setFont(oldfont); #endif @@ -650,9 +657,9 @@ void MCLGUI::draw_leds(uint8_t x, uint8_t y, uint8_t offset, uint64_t lock_mask, show_current_step && step_count == idx && MidiClock.state == 2; bool locked = in_range && IS_BIT_SET64(lock_mask, i + offset); -// if (note_interface.notes[i] == 1) { - // TI feedback - // oled_display.drawRect(x, y, seq_w, led_h, WHITE); + // if (note_interface.notes[i] == 1) { + // TI feedback + // oled_display.drawRect(x, y, seq_w, led_h, WHITE); if (!in_range) { // don't draw } else if (current ^ locked) { @@ -913,6 +920,25 @@ const unsigned char icon_sound[] PROGMEM = { 0x01, 0xc7, 0xe0, 0x07, 0xc7, 0xc0, 0x0f, 0xc3, 0x80, 0x0f, 0xc0, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00}; +// 'ram_2_icon2', 24x25px +const unsigned char icon_ram2[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf8, 0x20, 0x00, + 0x04, 0x20, 0x00, 0x04, 0x20, 0x00, 0x04, 0x23, 0xff, 0xc4, 0x26, + 0x43, 0x24, 0x25, 0x42, 0xa4, 0x24, 0xc2, 0x64, 0x23, 0x81, 0xc4, + 0x20, 0x00, 0x04, 0x20, 0x00, 0x04, 0x20, 0xff, 0x04, 0x1f, 0xff, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x6c, 0xe0, 0x0f, + 0x6d, 0xf0, 0x06, 0x6d, 0xb0, 0x06, 0x7d, 0xb0, 0x06, 0x7d, 0xb0, + 0x06, 0x7d, 0xf0, 0x06, 0x38, 0xe0, 0x00, 0x00, 0x00}; +// 'ram_1_icon', 24x25px +const unsigned char icon_ram1[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf8, 0x20, 0x00, + 0x04, 0x20, 0x00, 0x04, 0x20, 0x00, 0x04, 0x23, 0xff, 0xc4, 0x24, + 0xc2, 0x64, 0x25, 0x42, 0xa4, 0x26, 0x43, 0x24, 0x23, 0x81, 0xc4, + 0x20, 0x00, 0x04, 0x20, 0x00, 0x04, 0x20, 0xff, 0x04, 0x1f, 0xff, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x38, 0x70, 0x0f, + 0xbc, 0xf0, 0x0d, 0xb6, 0xc0, 0x0d, 0xb6, 0xf0, 0x0d, 0xb6, 0xc0, + 0x0f, 0xb6, 0xf0, 0x07, 0x36, 0x70, 0x00, 0x00, 0x00}; + // 'md_rev', 34x24px const unsigned char icon_md[] PROGMEM = { 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x00, 0x00, 0x00, diff --git a/avr/cores/megacommand/MCL/MCLGUI.h b/avr/cores/megacommand/MCL/MCLGUI.h index ad27cb0ec..ecbf5258a 100644 --- a/avr/cores/megacommand/MCL/MCLGUI.h +++ b/avr/cores/megacommand/MCL/MCLGUI.h @@ -231,6 +231,10 @@ extern const unsigned char icon_para[]; extern const unsigned char icon_step[]; // 'gatebox', 24x25px extern const unsigned char icon_gatebox[]; +// 'ram1', 24x25px +extern const unsigned char icon_ram1[]; +// 'ram2', 24x25px +extern const unsigned char icon_ram2[]; // 'rythmecho', 24x25px extern const unsigned char icon_rhytmecho []; // 'route', 24x16px diff --git a/avr/cores/megacommand/MCL/PageSelectPage.cpp b/avr/cores/megacommand/MCL/PageSelectPage.cpp index 776cdb5e7..d2279b8fe 100644 --- a/avr/cores/megacommand/MCL/PageSelectPage.cpp +++ b/avr/cores/megacommand/MCL/PageSelectPage.cpp @@ -46,8 +46,8 @@ const PageSelectEntry Entries[] PROGMEM = { #endif {"DELAY", &fx_page_a, 12, 3, 24, 25, (uint8_t *)icon_rhytmecho}, {"REVERB", &fx_page_b, 13, 3, 24, 25, (uint8_t *)icon_gatebox}, - {"RAM-1", &ram_page_a, 14, 3, 19, 19, (uint8_t *)wheel_top}, - {"RAM-2", &ram_page_b, 15, 3, 19, 19, (uint8_t *)wheel_angle}, + {"RAM-1", &ram_page_a, 14, 3, 24, 25, (uint8_t *)icon_ram1}, + {"RAM-2", &ram_page_b, 15, 3, 24, 25, (uint8_t *)icon_ram2}, }; constexpr uint8_t n_category = sizeof(Categories) / sizeof(PageCategory); From c14026e937d8afbff633881968c3f423487804e5 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 10 Mar 2020 15:39:32 +1100 Subject: [PATCH 19/27] remove md_set_recv_position --- avr/cores/megacommand/MCL/MCLActions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avr/cores/megacommand/MCL/MCLActions.cpp b/avr/cores/megacommand/MCL/MCLActions.cpp index 7676b96ea..969ce3cb9 100644 --- a/avr/cores/megacommand/MCL/MCLActions.cpp +++ b/avr/cores/megacommand/MCL/MCLActions.cpp @@ -362,12 +362,12 @@ void MCLActions::send_tracks_to_devices() { memcpy(&MD.kit.dynamics[0], kit_extra.dynamics, sizeof(kit_extra.dynamics)); } - MD.kit.origPosition = 0xF7; + MD.kit.origPosition = 0x7F; /*Send the encoded kit to the MD via sysex*/ uint16_t myclock = slowclock; - md_setsysex_recpos(4, MD.kit.origPosition); + //md_setsysex_recpos(4, MD.kit.origPosition); MD.kit.toSysex(); // mcl_seq.disable(); From af07e1124bfa4bd0786266f1bc6fa4ef1bbfbbc6 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Tue, 10 Mar 2020 15:42:26 +1100 Subject: [PATCH 20/27] add precautionary delay between set_recv_position and send sysex dump --- avr/cores/megacommand/MCL/SDDrivePage.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/SDDrivePage.cpp b/avr/cores/megacommand/MCL/SDDrivePage.cpp index 7fd65c2ec..bb919bada 100644 --- a/avr/cores/megacommand/MCL/SDDrivePage.cpp +++ b/avr/cores/megacommand/MCL/SDDrivePage.cpp @@ -196,6 +196,7 @@ void SDDrivePage::load_snapshot() { mcl_actions.md_setsysex_recpos(2, i); { ElektronDataToSysexEncoder encoder(&MidiUart); + delay(20); MD.global.toSysex(encoder); #ifndef OLED_DISPLAY delay(20); @@ -211,6 +212,7 @@ void SDDrivePage::load_snapshot() { goto load_error; } mcl_actions.md_setsysex_recpos(8, i); + delay(20); MD.pattern.toSysex(); #ifndef OLED_DISPLAY delay(20); @@ -225,11 +227,12 @@ void SDDrivePage::load_snapshot() { goto load_error; } mcl_actions.md_setsysex_recpos(4, i); + delay(20); MD.kit.toSysex(); #ifndef OLED_DISPLAY delay(20); #endif - + } // Load complete progress_max = 0; From 20cb645480bd0086e607d35b6caafc72e5349dbb Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 15 Mar 2020 12:15:27 +1100 Subject: [PATCH 21/27] optimize arp rendering 1 --- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 240 ++++------------------- 1 file changed, 39 insertions(+), 201 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index 6d386d71a..2dc3f91f3 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -43,7 +43,7 @@ void SeqPtcPage::setup() { } void SeqPtcPage::cleanup() { SeqPage::cleanup(); - //trig_interface.off(); + // trig_interface.off(); recording = false; if (MidiClock.state != 2) { MD.setTrackParam(last_md_track, 0, MD.kit.params[last_md_track][0]); @@ -320,10 +320,9 @@ void SeqPtcPage::display() { if (midi_device == DEVICE_MD) { itoa(ptc_param_len.getValue(), buf1, 10); if (mcl_cfg.poly_mask > 0) { - draw_knob(2, "PLEN", buf1); - } - else { - draw_knob(2, "LEN", buf1); + draw_knob(2, "PLEN", buf1); + } else { + draw_knob(2, "LEN", buf1); } } #ifdef EXT_TRACKS @@ -700,203 +699,35 @@ void SeqPtcPage::render_arp() { } // Generate subsequent octave itterations - if (arp_mode.cur <= ARP_THUMBDOWN) { - for (uint8_t n = 0; n < arp_oct.cur; n++) { - for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { - arp_notes[arp_len] = arp_notes[i] + (n + 1) * 12; - arp_len++; - } - } - } else { - switch (arp_mode.cur) { - case ARP_UPP: - case ARP_DOWNP: - for (uint8_t n = 0; n < arp_oct.cur; n++) { - for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { - arp_notes[arp_len] = arp_notes[i]; - if (i == num_of_notes - 1) { - arp_notes[arp_len] += (n + 1) * 12; - } - arp_len++; + for (uint8_t n = 0; n < arp_oct.cur; n++) { + for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { + switch (arp_mode.cur) { + case ARP_UP2: + case ARP_DOWN2: + arp_notes[arp_len] = arp_notes[i]; + if (!(i & 1)) { + arp_notes[arp_len] += (n + 1) * 12; } - } - break; - case ARP_UP2: - case ARP_DOWN2: - for (uint8_t n = 0; n < arp_oct.cur; n++) { - for (uint8_t i = 0; i < num_of_notes && arp_len < ARP_MAX_NOTES; i++) { - arp_notes[arp_len] = arp_notes[i]; - if (!(i & 1)) { - arp_notes[arp_len] += (n + 1) * 12; - } - arp_len++; + break; + case ARP_UPP: + case ARP_DOWNP: + arp_notes[arp_len] = arp_notes[i]; + if (i == num_of_notes - 1) { + arp_notes[arp_len] += (n + 1) * 12; } - } - break; - } - } - if (arp_idx >= arp_len) { - arp_idx = arp_len - 1; - } -} -/* -void SeqPtcPage::render_arp2() { - if (!arp_enabled) { - return; - } - if (arp_mode.cur == ARP_RND) { - arp_len = 1; - return; - } - - uint8_t first_note = 255; - uint8_t last_note = 255; - arp_len = 0; - for (uint8_t i = 0; i < ARP_MAX_NOTES; i++) { - if (IS_BIT_SET32(note_mask, i)) { - last_note = i; - if (first_note == 255) { - first_note = i; - } - } - } - if (first_note == 255) { - return; - } - uint8_t idx = first_note; - uint8_t idx2 = last_note; - uint8_t note = 255; - - uint8_t pitch = 255; - uint8_t first_pitch = calc_pitch(first_note); - - while (((pitch != first_pitch) || (arp_len == 1)) && - arp_len < ARP_MAX_NOTES) { - bool ignore_base = false; - - switch (arp_mode.cur) { - case ARP_UP: - if (arp_len == 0) { - note = first_note; - } else { - note = arp_get_next_note_up(idx); - if (note <= idx) { - if (arp_base < arp_oct.cur) { - arp_base++; - } else { - arp_base = 0; - } - } - } - break; - case ARP_DOWN: - note = arp_get_next_note_down(idx); - if (note >= idx) { - if (arp_base > 0) { - arp_base--; - } else { - arp_base = arp_oct.cur; - } - } - break; - case ARP_CONV: - if (arp_dir == 0) { - uint8_t note_tmp = arp_get_next_note_up(idx); - if (note_tmp < note) { - if (arp_base < arp_oct.cur) { - arp_base++; - } else { - arp_base = 0; - } - } - note = note_tmp; - arp_dir = 1; - } else { - note = arp_get_next_note_down(idx2); - idx2 = note; - arp_dir = 0; - } - break; - case ARP_CIRC: - uint8_t note_tmp; - if (arp_dir == 0) { - note_tmp = arp_get_next_note_up(idx); - if (note_tmp > idx) { - note = note_tmp; - } else { - if (arp_base < arp_oct.cur) { - arp_base++; - note = note_tmp; - } else { - arp_dir = 1; - note = arp_get_next_note_down(idx); - } - } - } else if (arp_dir == 1) { - note_tmp = arp_get_next_note_down(idx); - if (note_tmp < idx) { - note = note_tmp; - } else { - if (arp_base > 0) { - arp_base--; - note = note_tmp; - } else { - arp_dir = 0; - note = arp_get_next_note_up(idx); - } - } - } - break; - case ARP_UPTHUMB: - note = arp_get_next_note_up(idx); - note_tmp = arp_get_next_note_up(idx); - ignore_base = true; - if (note_tmp < idx) { - ignore_base = false; - } - if (note < idx) { - if (arp_base < arp_oct.cur) { - arp_base++; - } else { - arp_base = 0; - } - } - break; - case ARP_DOWNPINK: - note = arp_get_next_note_down(idx); - note_tmp = arp_get_next_note_down(idx); - ignore_base = true; - if (note_tmp > idx) { - ignore_base = false; - } - if (note > idx) { - if (arp_base > 0) { - arp_base--; - } else { - arp_base = arp_oct.cur; - } - } - break; - } - if (note < NUM_MD_TRACKS) { - idx = note; - arp_notes[arp_len] = calc_pitch(note); - if (!ignore_base) { - arp_notes[arp_len] += arp_base * 12; - pitch = arp_notes[arp_len]; - } else { - pitch = arp_notes[arp_len] + arp_base * 12; + break; + default: + arp_notes[arp_len] = arp_notes[i] + (n + 1) * 12; + break; } arp_len++; - } else { - break; } } + if (arp_idx >= arp_len) { arp_idx = arp_len - 1; } } -*/ void SeqPtcPage::on_16_callback() { bool trig = false; uint8_t note; @@ -1005,13 +836,15 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { if (EVENT_RELEASED(event, Buttons.BUTTON1)) { if (BUTTON_DOWN(Buttons.BUTTON4)) { - re_init = true; - GUI.pushPage(&poly_page); + re_init = true; + GUI.pushPage(&poly_page); return true; } seq_ptc_page.queue_redraw(); recording = !recording; - if (recording) { oled_display.textbox("RECORDING", ""); } + if (recording) { + oled_display.textbox("RECORDING", ""); + } return true; } /* @@ -1184,14 +1017,21 @@ void SeqPtcMidiEvents::onControlChangeCallback_Midi2(uint8_t *msg) { uint8_t track_param; // If external keyboard controlling MD param, send parameter updates // to all polyphonic tracks - if ((param < 16) || (param > 39)) { return; } - // If Midi2 forwarding data to port 1 , ignore this to prevent double messages. + if ((param < 16) || (param > 39)) { + return; + } + // If Midi2 forwarding data to port 1 , ignore this to prevent double + // messages. // - if (mcl_cfg.midi_forward == 2) { return; } + if (mcl_cfg.midi_forward == 2) { + return; + } if ((mcl_cfg.uart2_ctrl_mode - 1 == channel) || (mcl_cfg.uart2_ctrl_mode == MIDI_OMNI_MODE)) { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { - if (IS_BIT_SET16(mcl_cfg.poly_mask,n)) { MD.setTrackParam(n, param - 16, value); } + if (IS_BIT_SET16(mcl_cfg.poly_mask, n)) { + MD.setTrackParam(n, param - 16, value); + } } } } @@ -1235,7 +1075,6 @@ void SeqPtcMidiEvents::setup_callbacks() { this, (midi_callback_ptr_t)&SeqPtcMidiEvents::onControlChangeCallback_Midi2); - state = true; } @@ -1256,6 +1095,5 @@ void SeqPtcMidiEvents::remove_callbacks() { this, (midi_callback_ptr_t)&SeqPtcMidiEvents::onControlChangeCallback_Midi2); - state = false; } From 274383d93f411b70859653401499c64d43a0b3e8 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 15 Mar 2020 23:11:14 +1100 Subject: [PATCH 22/27] Add TRX-S2 tuning and params --- avr/cores/megacommand/MD/MDParams.cpp | 21 +++++++++++++++++++-- avr/cores/megacommand/MD/MDParams.hh | 14 ++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/MD/MDParams.cpp b/avr/cores/megacommand/MD/MDParams.cpp index 1d87e6567..294f87170 100644 --- a/avr/cores/megacommand/MD/MDParams.cpp +++ b/avr/cores/megacommand/MD/MDParams.cpp @@ -31,7 +31,7 @@ const char *MDLFONames[8] = { #ifndef DISABLE_MACHINE_NAMES -md_machine_name_t_short const machine_names_short[134] PROGMEM = { +md_machine_name_t_short const machine_names_short[135] PROGMEM = { { "GN","--", 0}, { "GN", "SN", 1}, { "GN", "NS", 2}, @@ -49,6 +49,7 @@ md_machine_name_t_short const machine_names_short[134] PROGMEM = { { "TR", "CL", 26}, { "TR", "XC", 27}, { "TR", "B2", 28}, + { "TR", "S2", 29}, { "FM", "BD", 32}, { "FM", "SD", 33}, { "FM", "XT", 34}, @@ -168,7 +169,7 @@ md_machine_name_t_short const machine_names_short[134] PROGMEM = { { "RO", "48", 191} }; -const md_machine_name_t machine_names[134] PROGMEM = { +const md_machine_name_t machine_names[135] PROGMEM = { { "GND---", 0}, { "GND-SN", 1}, { "GND-NS", 2}, @@ -186,6 +187,7 @@ const md_machine_name_t machine_names[134] PROGMEM = { { "TRX-CL", 26}, { "TRX-XC", 27}, { "TRX-B2", 28}, + { "TRX-S2", 29}, { "EFM-BD", 32}, { "EFM-SD", 33}, { "EFM-XT", 34}, @@ -362,6 +364,14 @@ const model_param_name_t trx_b2_model_names[] PROGMEM = { { "PTC", 0}, { "NS", 5}, { "DRT", 6}, { "DST", 7}, {"", 127} }; +const model_param_name_t trx_s2_model_names[] PROGMEM = { { "PTC", 0}, + { "DEC", 1}, + { "NS", 2}, + { "NDE", 3}, + { "PWR", 4}, + { "TUN", 5}, + { "NTU", 6}, + { "NTY", 7}, {"", 127} }; const model_param_name_t trx_sd_model_names[] PROGMEM = { { "PTC", 0}, { "DEC", 1}, { "BMP", 2}, @@ -860,6 +870,7 @@ model_to_param_names_t model_param_names[] = { { TRX_MA_MODEL, trx_ma_model_names }, { TRX_CL_MODEL, trx_cl_model_names }, { TRX_XC_MODEL, trx_xc_model_names }, + { TRX_S2_MODEL, trx_s2_model_names }, { EFM_BD_MODEL, efm_bd_model_names }, { EFM_SD_MODEL, efm_sd_model_names }, @@ -1047,6 +1058,11 @@ static const uint8_t trx_bd_tuning[] PROGMEM = { 1, 7, 12, 17, 23, 28, 33, 39, 44, 49, 55, 60, 66, 71, 76, 82, 87, 92, 98, 103, 108, 114, 119, 124, }; + +static const uint8_t trx_s2_tuning[] PROGMEM = { + 3, 7, 11, 15, 20, 24, 30, 35, 41, 47, 54, 60, 68, 76, 84, 92, 101, 111, 121 +}; + static const uint8_t rom_tuning[] PROGMEM = { 0, 2, 5, 7, 9, 12, 14, 16, 19, 21, 23, 26, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 102, 105, 107, @@ -1114,6 +1130,7 @@ static const tuning_t tunings[] = { { GND_SN_MODEL, MIDI_NOTE_F2, sizeof(gnd_sn_tuning), 3, gnd_sn_tuning }, { TRX_B2_MODEL, MIDI_NOTE_A1, sizeof(trx_b2_tuning), 8, trx_b2_tuning }, { TRX_RS_MODEL, MIDI_NOTE_F4, sizeof(trx_rs_tuning), 13, trx_rs_tuning }, + { TRX_S2_MODEL, MIDI_NOTE_F2, sizeof(trx_s2_tuning), 0, trx_s2_tuning }, { EFM_CB_MODEL, MIDI_NOTE_F3, sizeof(efm_cb_tuning), 5, efm_cb_tuning }, { ROM_MODEL, MIDI_NOTE_A3, sizeof(rom_tuning), 4, rom_tuning }, { EFM_CY_MODEL, MIDI_NOTE_B2, sizeof(efm_cy_tuning), 6, efm_cy_tuning }, diff --git a/avr/cores/megacommand/MD/MDParams.hh b/avr/cores/megacommand/MD/MDParams.hh index 9d0400c23..58a78904f 100644 --- a/avr/cores/megacommand/MD/MDParams.hh +++ b/avr/cores/megacommand/MD/MDParams.hh @@ -88,6 +88,7 @@ #define TRX_CL_MODEL 26 #define TRX_XC_MODEL 27 #define TRX_B2_MODEL 28 +#define TRX_S2_MODEL 29 #define EFM_BD_MODEL 32 #define EFM_SD_MODEL 33 @@ -356,6 +357,15 @@ #define TRX_XC_DIST 5 #define TRX_XC_DTYP 6 +#define TRX_S2_PTCH 0 +#define TRX_S2_DEC 1 +#define TRX_S2_NOISE 2 +#define TRX_S2_NDEC 3 +#define TRX_S2_POWER 4 +#define TRX_S2_TUNE 5 +#define TRX_S2_NTUNE 6 +#define TRX_S2_NTYPE 7 + #define EFM_BD_PTCH 0 #define EFM_BD_DEC 1 #define EFM_BD_RAMP 2 @@ -868,7 +878,7 @@ PGM_P model_param_name(uint8_t model, uint8_t param); extern const char *MDLFONames[8]; -extern const md_machine_name_t machine_names[134] PROGMEM; +extern const md_machine_name_t machine_names[135] PROGMEM; typedef struct md_machine_name_s_short { char name1[3]; @@ -876,7 +886,7 @@ typedef struct md_machine_name_s_short { uint8_t id; } md_machine_name_t_short; -extern md_machine_name_t_short const machine_names_short[134] PROGMEM; +extern md_machine_name_t_short const machine_names_short[135] PROGMEM; PGM_P getMachineNameShort(uint8_t machine, uint8_t type); extern PGM_P fx_param_name(uint8_t fx_type, uint8_t param); From 9e041ad4049f0512d2aa42836b990e13226e58bf Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Sun, 15 Mar 2020 23:20:04 +1100 Subject: [PATCH 23/27] only show poly mode, if poly track selected --- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index 2dc3f91f3..29063aae2 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -296,14 +296,14 @@ void SeqPtcPage::display() { dev_num = last_ext_track + 16; } #endif - + bool is_poly = IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track); draw_knob_frame(); char buf1[4]; // draw OCTAVE itoa(ptc_param_oct.getValue(), buf1, 10); draw_knob(0, "OCT", buf1); - + // draw FREQ if (ptc_param_finetune.getValue() < 32) { strcpy(buf1, "-"); @@ -319,7 +319,7 @@ void SeqPtcPage::display() { // draw LEN if (midi_device == DEVICE_MD) { itoa(ptc_param_len.getValue(), buf1, 10); - if (mcl_cfg.poly_mask > 0) { + if ((mcl_cfg.poly_mask > 0) && (is_poly)) { draw_knob(2, "PLEN", buf1); } else { draw_knob(2, "LEN", buf1); @@ -342,7 +342,7 @@ void SeqPtcPage::display() { mcl_gui.draw_keyboard(32, 23, 6, 9, NUM_KEYS, note_mask); oled_display.setFont(&TomThumb); - if (mcl_cfg.poly_mask > 0) { + if ((mcl_cfg.poly_mask > 0) && (is_poly)) { oled_display.setCursor(107, 32); oled_display.print("POLY"); } From a00db8a22af7a499eb9b32cbfea0ecddddcf43f6 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 16 Mar 2020 09:58:20 +1100 Subject: [PATCH 24/27] Spelling --- avr/cores/megacommand/MCL/SeqPages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/cores/megacommand/MCL/SeqPages.cpp b/avr/cores/megacommand/MCL/SeqPages.cpp index 30c894328..c0ee0c92a 100644 --- a/avr/cores/megacommand/MCL/SeqPages.cpp +++ b/avr/cores/megacommand/MCL/SeqPages.cpp @@ -31,7 +31,7 @@ ArpPage arp_page(&arp_und, &arp_mode, &arp_speed, &arp_oct); const menu_t<9> seq_menu_layout PROGMEM = { "SEQ", { - {"ARPEGIATOR:", 0, 0, 0, (uint8_t *)NULL, (Page *) &arp_page, NULL, {}}, + {"ARPEGGIATOR", 0, 0, 0, (uint8_t *)NULL, (Page *) &arp_page, NULL, {}}, {"TRACK SEL:", 1, 17, 0, (uint8_t *)&opt_trackid, (Page *)NULL, opt_trackid_handler, {}}, {"COPY:", 0, 3, 3, (uint8_t *)&opt_copy, (Page *)NULL, opt_copy_track_handler, { {0, "--",}, {1, "TRK"}, {2, "ALL"}}}, {"CLEAR:", 0, 3, 3, (uint8_t *)&opt_clear, (Page *)NULL, opt_clear_track_handler, { {0, "--",}, {1, "TRK"}, {2, "ALL"}}}, From 93d4cc059352b04fa8aceda0f688613b592e40c9 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 16 Mar 2020 13:03:56 +1100 Subject: [PATCH 25/27] MCL version + changelog --- Changelog | 17 +++++++++++++++++ avr/cores/megacommand/MCL/MCL.h | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index 7400057ad..2c2695493 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,20 @@ +MCL 2.61 16/03/2020 + +Changes: + + - Arpeggitaor added to Chromatic Page. Accessible from Track Select Menu. + - MIDI CC can be used to control MD Parms across poly tracks. + CC 16 to 40 controls MD Params 1 to 24. + - Added many more scales to Chromatic Page + - Chromatic Page now indicates when in POLY mode. + - Added support for TRX-S2 + +Bug Fixes: + + - Peering was broken in certain pages. Fixed + - Fixed PolyPage selection bugs. + + MCL 2.60 15/02/2019 Note: MCL update 2.60, requires that you upgrade your Machinedrum to OS version 1.70. diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index d077e5fe0..bf35eeef6 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -91,8 +91,8 @@ #include "Fonts/Elektrothic.h" #endif -#define VERSION 2060 -#define VERSION_STR "2.60" +#define VERSION 2061 +#define VERSION_STR "2.61" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 From 26cfac06ed893aca597b619931e6385e21f0a874 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 16 Mar 2020 14:56:39 +1100 Subject: [PATCH 26/27] Add support for HD44780 on ArpPage --- avr/cores/megacommand/MCL/ArpPage.cpp | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp index 5504ea7c7..1c4d92f68 100644 --- a/avr/cores/megacommand/MCL/ArpPage.cpp +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -54,6 +54,40 @@ const arp_name_t arp_names[] PROGMEM = { "PU", "PD", "TU", "TD", "UPP", "DP", "U2", "D2", "RND", }; +#ifndef OLED_DISPLAY +void ArpPage::display() { + uint8_t dev_num; + if (!redisplay) { + return true; + } + GUI.setLine(GUI.LINE1); + + GUI.put_string_at(0, "ARP"); + GUI.put_string_at(4, "MOD"); + GUI.put_string_at(8, "SPD"); + GUI.put_string_at(12,"OCT"); + + GUI.setLine(GUI.LINE2); + char str[5]; + + switch (encoders[0]->cur) { + case ARP_ON: + strcpy(str, "ON"); + break; + case ARP_OFF: + strcpy(str, "--"); + break; + case ARP_LATCH: + strcpy(str, "LAT"); + break; + } + GUI.put_string_at(0, str); + m_strncpy_p(str, arp_names[encoders[1]->cur], 4); + GUI.put_string_at(4,str); + GUI.put_value_at2(8, encoders[2]->cur); + GUI.put_value_at2(12, encoders[3]->cur); +} +#else void ArpPage::display() { if (!classic_display) { @@ -99,6 +133,7 @@ void ArpPage::display() { oled_display.setFont(oldfont); } +#endif bool ArpPage::handleEvent(gui_event_t *event) { if (EVENT_PRESSED(event, Buttons.BUTTON1) || EVENT_PRESSED(event, Buttons.BUTTON3) || From 8dc65146a0cda4b292f61bdd94a9ee5972cfc100 Mon Sep 17 00:00:00 2001 From: Justin Mammarella Date: Mon, 16 Mar 2020 14:59:15 +1100 Subject: [PATCH 27/27] fix compile for hd44780 --- avr/cores/megacommand/MCL/SeqPtcPage.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index 29063aae2..638a8bf8d 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -842,9 +842,11 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { } seq_ptc_page.queue_redraw(); recording = !recording; +#ifdef OLED_DISPLAY if (recording) { oled_display.textbox("RECORDING", ""); } +#endif return true; } /*