diff --git a/Changelog b/Changelog index 52538da78..98dee0105 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,89 @@ +MCL 4.51 01/12/2023 + +Please upgrade to Machinedrum OS X.10 & Monomachine OS X.01 before using MCL 4.51. + +- Changes: + + [ Classic/Extended] button must now be held down for 1.5 seconds to switch + between Enhanced and Classic/Extended modes when the sequencer is stopped. + +- Improvements: + + When the sequencer is running the Mixer page can be opened and closed by pressing [ Classic/Extended ]. + + Hold down [ Classic/Extended ] + [ Trig ] for fast for mute toggles. + + Minimum transition load latency reduced from approximately two 16th notes, to exactly half a 16th note per device. + + More reliable transitions, and better slot loading responsiveness. + + Load Page - Press [ Function ] to select the destination track offset for next load. + + Sample transfers between MCL and MD can be cancelled by pressing MCL button < SAVE/NO > + + Microtiming is no longer cleared when unsetting a trig with locks in Step Edit. + + Added arrow key parameter selection to Arp Page. + + Arpeggiator gets a true random mode "RN2" + + Mixer Page trig LEDs now flash when MD tracks are triggered. + + New General MIDI menu added to configure the Generic MIDI driver. Assign + custom mute CC paramater which can be received/transmitted via the MixerPage's ext device, mute toggle. + + TURBO MIDI speeds will now be enabled on MIDI port 2, when Generic Driver is + selected. This activates TURBO MIDI for compatible machines that we haven't implemented a specific driver for. + + PianoRoll, added step delete [ Trig ] + [ Clear ] + +- Bug Fixes: + + New Project creation could fail. + + Project rename could fail. + + Microtiming window would unexpectedly display when setting PTC + + Wav Designer page switching was broken. + + Wav Designer oscillator tuning rounding error and cents adjustment fix. + + Fix sequencer LED cursor sync in certain circumstances. + + MD IMPORT patterns menu, row names were broken and the range was too small. + + PerfPage parameter learning was broken if dest the same as LFO dest + + LFO offset for MIDI destinations was broken. + + At low tempos, MIDI tracks would not always load. + + Bulk sample receive was broken. + + When AUTO Loading, comparison of MD sounds could be incorrect causing sound retransmission. + + Don't cd up in SoundBrowser when pressing [ NO ], instead revert back to Step Edit page. + + PerfEncoder scene assignment was not distributed correctly when loading a blank PF slot. + + Parameter lock parameters should be reverted correctly on sequencer stop. + + Tracks triggered manually would not use the unlocked parameter values. + + Sequencer: Don't allow paste before copy. + + MixerPage poly-link fader display bug. + + Arpeggiator behaviour in poly mode could be unpredictable. + + Arpeggiator D2 and RND modes could not be selected. + + MIDI active-peering would use the Elektron driver, even when Generic was selected. + MCL 4.50 24/07/2023 -Please install Machinedrum OS X.09 & Monomachine OS X.01 before using MCL 4.50. +Please upgrade to Machinedrum OS X.09 & Monomachine OS X.01 before using MCL 4.50. - Performance Page + Performance Controllers A new Performance Page has been added featuring 8 Scenes (1->8) that are shared @@ -220,7 +303,7 @@ MCL 4.41 10/03/2023 MCL 4.40 25/02/2023 -Please install Machinedrum OS X.08 & Monomachine OS X.01 before using MCL 4.40. +Please upgrade to Machinedrum OS X.08 & Monomachine OS X.01 before using MCL 4.40. Perform the USB DFU firmware procedure to upgrade the USB microcontroller for class compliant USB MIDI. - Improvements: @@ -247,7 +330,7 @@ Perform the USB DFU firmware procedure to upgrade the USB microcontroller for cl MCL 4.30 12/01/2023 -Please install Machinedrum OS X.08 & Monomachine OS X.01 before using MCL 4.30. +Please upgrade to Machinedrum OS X.08 & Monomachine OS X.01 before using MCL 4.30. Perform the USB DFU firmware procedure to upgrade the USB microcontroller for class compliant USB MIDI. - Fixes: @@ -265,7 +348,7 @@ Perform the USB DFU firmware procedure to upgrade the USB microcontroller for cl MCL 4.20 14/07/2022 -Please install Machinedrum OS X.07 & Monomachine OS X.01 before using MCL 4.20. +Please upgrade to Machinedrum OS X.07 & Monomachine OS X.01 before using MCL 4.20. Perform the USB DFU firmware procedure to upgrade the USB microcontroller for class compliant USB MIDI. - Fixes: @@ -343,7 +426,7 @@ Perform the USB DFU firmware procedure to upgrade the USB microcontroller for cl MCL 4.11 30/03/2022 -Please install Machinedrum OS X.06 before using MCL 4.11 +Please upgrade to Machinedrum OS X.06 before using MCL 4.11 - Bug Fixes: @@ -376,7 +459,7 @@ Please install Machinedrum OS X.06 before using MCL 4.11 MCL 4.10 19/03/2022 -Please install Machinedrum OS X.06 before using MCL 4.10 +Please upgrade to Machinedrum OS X.06 before using MCL 4.10 - Key Binding Changes: diff --git a/art/sprites/midi_icon.png b/art/sprites/midi_icon.png new file mode 100644 index 000000000..6ed1bb00f Binary files /dev/null and b/art/sprites/midi_icon.png differ diff --git a/art/sprites/turbo_icon.png b/art/sprites/turbo_icon.png new file mode 100644 index 000000000..5608b45b9 Binary files /dev/null and b/art/sprites/turbo_icon.png differ diff --git a/avr/cores/megacommand/A4/A4.cpp b/avr/cores/megacommand/A4/A4.cpp index 1885f7ba6..4e9460c1d 100644 --- a/avr/cores/megacommand/A4/A4.cpp +++ b/avr/cores/megacommand/A4/A4.cpp @@ -105,7 +105,7 @@ bool A4Class::probe() { if (getBlockingSettings(0)) { connected = true; DEBUG_DUMP(connected); - turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart2_turbo), uart); + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart2_turbo_speed), uart); } return connected; } @@ -230,7 +230,7 @@ bool A4Class::getBlockingSettingsX(uint8_t settings, uint16_t timeout) { } void A4Class::muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr) { if (uart_ == nullptr) { uart_ = uart; } - uart->sendCC(track, 94, mute ? 1 : 0); + uart->sendCC(track, 94, mute); } void A4Class::setLevel(uint8_t track, uint8_t value) { diff --git a/avr/cores/megacommand/Arduino.h b/avr/cores/megacommand/Arduino.h index 40a093072..d53e56028 100644 --- a/avr/cores/megacommand/Arduino.h +++ b/avr/cores/megacommand/Arduino.h @@ -132,7 +132,7 @@ void analogWrite(uint8_t, int); unsigned long millis(void); unsigned long micros(void); -void delay(unsigned long); +void delay(uint16_t ms); void delayMicroseconds(unsigned int us); unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout); diff --git a/avr/cores/megacommand/Elektron/Elektron.cpp b/avr/cores/megacommand/Elektron/Elektron.cpp index a6217ce9a..64d59e62d 100644 --- a/avr/cores/megacommand/Elektron/Elektron.cpp +++ b/avr/cores/megacommand/Elektron/Elektron.cpp @@ -268,7 +268,7 @@ void ElektronDevice::set_trigleds(uint16_t bitmask, TrigLEDMode mode, // trigleds[7..13] data[3] = (bitmask >> 7) & 0x7F; // trigleds[14..15] - data[4] = (bitmask >> 14) | (mode << 2) | (blink << 4); + data[4] = (bitmask >> 14) | (mode << 2) | (blink << 5); sendRequest(data, sizeof(data)); // waitBlocking(); } diff --git a/avr/cores/megacommand/Elektron/Elektron.h b/avr/cores/megacommand/Elektron/Elektron.h index aa6c4d076..34036a4db 100644 --- a/avr/cores/megacommand/Elektron/Elektron.h +++ b/avr/cores/megacommand/Elektron/Elektron.h @@ -255,7 +255,8 @@ enum TrigLEDMode { TRIGLED_OVERLAY = 0, TRIGLED_STEPEDIT = 1, TRIGLED_EXCLUSIVE = 2, - TRIGLED_EXCLUSIVENDYNAMIC = 3 + TRIGLED_EXCLUSIVENDYNAMIC = 3, + TRIGLED_MUTE = 4 }; /// sysex constants for constructing data frames @@ -543,8 +544,6 @@ class ElektronDevice : public MidiDevice { }; extern const char* getMachineNameShort(uint8_t machine, uint8_t type, const short_machine_name_t* table, size_t size); -#define copyMachineNameShort(src, dst) \ - (dst)[0] = (src)[0]; \ - (dst)[1] = (src)[1]; +#define copyMachineNameShort(src, dst) memcpy(dst,src,2); #endif /* ELEKTRON_H__ */ diff --git a/avr/cores/megacommand/Elektron/ElektronDataEncoder.cpp b/avr/cores/megacommand/Elektron/ElektronDataEncoder.cpp index cb433184e..c24ee99ca 100755 --- a/avr/cores/megacommand/Elektron/ElektronDataEncoder.cpp +++ b/avr/cores/megacommand/Elektron/ElektronDataEncoder.cpp @@ -52,21 +52,7 @@ void ElektronDataToSysexEncoder::startChecksum() { } void ElektronDataToSysexEncoder::uart_send(uint8_t c) { - if (throttle) { - /* bool do_throttle = false; - uint8_t v = 0; - if (MidiClock.mod6_counter == 0) { - do_throttle = true; - } - if (MidiClock.mod12_counter == throttle_mod12) { - do_throttle = true; - } - if (do_throttle) { */ - delayMicroseconds(THROTTLE_US); - uart->m_putc_immediate(c); - } else { - uart->m_putc(c); - } + uart->m_putc(c); } void ElektronDataToSysexEncoder::finishChecksum() { uint16_t len = retLen - 5; diff --git a/avr/cores/megacommand/Elektron/ElektronDataEncoder.h b/avr/cores/megacommand/Elektron/ElektronDataEncoder.h index bda38d68b..7ba688940 100644 --- a/avr/cores/megacommand/Elektron/ElektronDataEncoder.h +++ b/avr/cores/megacommand/Elektron/ElektronDataEncoder.h @@ -39,19 +39,13 @@ class ElektronDataToSysexEncoder : public DataEncoder { uint16_t checksum; bool inChecksum; public: - bool throttle; - uint8_t throttle_mod12; ElektronDataToSysexEncoder(uint8_t *_sysex = nullptr) { init(_sysex); - throttle = false; - throttle_mod12 = 255; } ElektronDataToSysexEncoder(MidiUartParent *_uart) { init(0, _uart); - throttle = false; - throttle_mod12 = 255; } void uart_send(uint8_t c); diff --git a/avr/cores/megacommand/GUI/Events.cpp b/avr/cores/megacommand/GUI/Events.cpp index 4509139ab..2a6229595 100644 --- a/avr/cores/megacommand/GUI/Events.cpp +++ b/avr/cores/megacommand/GUI/Events.cpp @@ -8,7 +8,7 @@ volatile CRingBuffer EventRB; volatile uint8_t event_ignore_next_mask; void pollEventGUI() { - for (int i = 0; i < MAX_BUTTONS; i++) { + for (uint8_t i = 0; i < MAX_BUTTONS; i++) { gui_event_t event; event.source = i; if (BUTTON_PRESSED(i)) { diff --git a/avr/cores/megacommand/GUI/GUI.cpp b/avr/cores/megacommand/GUI/GUI.cpp index 8cfc7a692..7502338a0 100644 --- a/avr/cores/megacommand/GUI/GUI.cpp +++ b/avr/cores/megacommand/GUI/GUI.cpp @@ -62,23 +62,24 @@ void GuiClass::loop() { oled_display.screen_saver = false; gui_event_t event; EventRB.getp(&event); - for (int i = 0; i < eventHandlers.size; i++) { + bool ret = false; + if (sketch != NULL) { + ret = sketch->handleTopEvent(&event); + if (ret) + continue; + } + + for (uint8_t i = 0; i < eventHandlers.size; i++) { if (eventHandlers.arr[i] != NULL) { - bool ret = eventHandlers.arr[i](&event); - if (ret) { + ret = eventHandlers.arr[i](&event); + if (ret) continue; - } } } - if (sketch != NULL) { - bool ret = sketch->handleTopEvent(&event); - if (ret) - continue; - } } - for (int i = 0; i < tasks.size; i++) { + for (uint8_t i = 0; i < tasks.size; i++) { if (tasks.arr[i] != NULL) { tasks.arr[i]->checkTask(); } diff --git a/avr/cores/megacommand/GUI/Pages.cpp b/avr/cores/megacommand/GUI/Pages.cpp index 450605067..709da83ee 100644 --- a/avr/cores/megacommand/GUI/Pages.cpp +++ b/avr/cores/megacommand/GUI/Pages.cpp @@ -38,6 +38,7 @@ void PageContainer::pushPage(LightPage* page) { pageStack.push(page); page->init(); page->show(); + page->init_encoders_used_clock(); #ifdef ENABLE_DIAG_LOGGING // deactivate diagnostic page on pushPage diag_page.deactivate(); diff --git a/avr/cores/megacommand/GUI_private.cpp b/avr/cores/megacommand/GUI_private.cpp index 5f6e0883f..f9f95b312 100644 --- a/avr/cores/megacommand/GUI_private.cpp +++ b/avr/cores/megacommand/GUI_private.cpp @@ -154,7 +154,7 @@ ButtonsClass::ButtonsClass() { } void ButtonsClass::clear() { - for (int i = 0; i < GUI_NUM_BUTTONS; i++) { + for (uint8_t i = 0; i < GUI_NUM_BUTTONS; i++) { CLEAR_B_DOUBLE_CLICK(i); CLEAR_B_CLICK(i); CLEAR_B_LONG_CLICK(i); diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp index b9d6009f9..a39ba0bb1 100644 --- a/avr/cores/megacommand/MCL/ArpPage.cpp +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -1,11 +1,12 @@ #include "MCL_impl.h" MCLEncoder arp_range(0, 4, ENCODER_RES_SEQ); -MCLEncoder arp_mode(0, 17, ENCODER_RES_SEQ); +MCLEncoder arp_mode(0, 18, ENCODER_RES_SEQ); MCLEncoder arp_rate(1, 16, ENCODER_RES_SEQ); MCLEncoder arp_enabled(0, 2, ENCODER_RES_SEQ); void ArpPage::setup() { + param_select = 255; } void ArpPage::init() { @@ -28,6 +29,8 @@ void ArpPage::track_update(uint8_t n, bool re_render) { arp_track = &mcl_seq.ext_arp_tracks[n]; } + current_track = n; + arp_rate.cur = arp_track->length; arp_rate.old = arp_rate.cur; @@ -57,10 +60,7 @@ void ArpPage::track_update(uint8_t n, bool re_render) { void ArpPage::cleanup() { oled_display.clearDisplay(); } void ArpPage::loop() { - uint8_t n = last_ext_track; - if (seq_ptc_page.midi_device == &MD) { - n = last_md_track; - } + uint8_t n = current_track; if (encoders[0]->hasChanged()) { arp_track->enabled = encoders[0]->cur; @@ -83,6 +83,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", "TU", "TD", "UPP", "DP", "U2", "D2", "RND", + "RN2", }; void ArpPage::display() { @@ -99,7 +100,7 @@ void ArpPage::display() { oled_display.print(F("ARPEGGIATOR: T")); if (seq_ptc_page.midi_device == &MD) { - oled_display.print(last_md_track + 1); + oled_display.print(current_track + 1); } else { oled_display.print(last_ext_track + 1); } @@ -119,17 +120,18 @@ void ArpPage::display() { strcpy(str, "LAT"); break; } - mcl_gui.draw_text_encoder(x + 0 * mcl_gui.knob_w, y, "ARP", str); + + mcl_gui.draw_text_encoder(x + 0 * mcl_gui.knob_w, y, "ARP", str, param_select == 0); strncpy_P(str, arp_names[encoders[1]->cur], 4); - mcl_gui.draw_text_encoder(x + 1 * mcl_gui.knob_w, y, "MODE", str); + mcl_gui.draw_text_encoder(x + 1 * mcl_gui.knob_w, y, "MODE", str, param_select == 1); mcl_gui.put_value_at(encoders[2]->cur, str); - mcl_gui.draw_text_encoder(x + 2 * mcl_gui.knob_w, y, "RATE", str); + mcl_gui.draw_text_encoder(x + 2 * mcl_gui.knob_w, y, "RATE", str, param_select == 2); mcl_gui.put_value_at(encoders[3]->cur, str); - mcl_gui.draw_text_encoder(x + 3 * mcl_gui.knob_w, y, "RANGE", str); + mcl_gui.draw_text_encoder(x + 3 * mcl_gui.knob_w, y, "RANGE", str, param_select == 3); oled_display.display(); oled_display.setFont(oldfont); @@ -139,11 +141,35 @@ bool ArpPage::handleEvent(gui_event_t *event) { if (EVENT_CMD(event)) { uint8_t key = event->source - 64; if (event->mask == EVENT_BUTTON_PRESSED) { + switch (key) { case MDX_KEY_YES: case MDX_KEY_NO: goto exit; } + if (param_select == 255) { param_select = 0; return true; } + switch (key) { + case MDX_KEY_LEFT: { + if (param_select > 0) { + param_select--; + } + return true; + } + case MDX_KEY_RIGHT: { + if (param_select < 3) { + param_select++; + } + return true; + } + case MDX_KEY_UP: { + encoders[param_select]->cur++; + return true; + } + case MDX_KEY_DOWN: { + encoders[param_select]->cur--; + return true; + } + } } } if (EVENT_PRESSED(event, Buttons.BUTTON1) || diff --git a/avr/cores/megacommand/MCL/ArpPage.h b/avr/cores/megacommand/MCL/ArpPage.h index e8033d2c7..6aa715717 100644 --- a/avr/cores/megacommand/MCL/ArpPage.h +++ b/avr/cores/megacommand/MCL/ArpPage.h @@ -17,7 +17,8 @@ class ArpPage : public LightPage { public: ArpSeqTrack *arp_track; ArpSeqTrack *last_arp_track; - + uint8_t current_track; + uint8_t param_select = 0; ArpPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) : LightPage(e1, e2, e3, e4) { diff --git a/avr/cores/megacommand/MCL/ArpSeqTrack.cpp b/avr/cores/megacommand/MCL/ArpSeqTrack.cpp index a516ff999..e05d180c2 100644 --- a/avr/cores/megacommand/MCL/ArpSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/ArpSeqTrack.cpp @@ -38,10 +38,11 @@ void ArpSeqTrack::seq(MidiUartParent *uart_) { if (mod12_counter == 0 && enabled && mute_state == SEQ_MUTE_OFF) { if (step_count == 0) { if (len > 0) { - uint8_t note = notes[idx] + oct * 12; + uint8_t note = mode == ARP_RND2 ? notes[get_random(len)] : notes[idx]; + note += oct*12; switch (active) { case MD_ARP_TRACK_TYPE: - seq_ptc_page.trig_md(note, track_number, fine_tune, uart); + seq_ptc_page.trig_md(note, track_number, CTRL_EVENT, fine_tune, uart); break; case EXT_ARP_TRACK_TYPE: seq_ptc_page.note_on_ext(note, 127, track_number, uart); @@ -133,6 +134,7 @@ void ArpSeqTrack::render(uint8_t mode_, uint8_t oct_, uint8_t fine_tune_, uint8_ case ARP_UP: case ARP_UPDOWN: case ARP_UPNDOWN: + case ARP_RND2: note = sort_up[i]; break; case ARP_DOWN2: @@ -207,31 +209,9 @@ void ArpSeqTrack::render(uint8_t mode_, uint8_t oct_, uint8_t fine_tune_, uint8_ next2: switch (mode) { case ARP_PINKUP: - if (num_of_notes == 1) { - note = sort_up[0]; - notes[len++] = note; - } - for (uint8_t i = 0; i < num_of_notes - 1; i++) { - note = sort_up[i]; - notes[len++] = note; - note = sort_down[0]; - notes[len++] = note; - } - - break; - - case ARP_PINKDOWN: - for (uint8_t i = 1; i < num_of_notes; i++) { - note = sort_down[i]; - notes[len++] = note; - note = sort_up[0]; - notes[len++] = note; - } - break; - case ARP_THUMBUP: if (num_of_notes == 1) { - note = sort_down[0]; + note = mode == ARP_PINKUP ? sort_up[0] : sort_down[0]; notes[len++] = note; } for (uint8_t i = 0; i < num_of_notes - 1; i++) { @@ -243,11 +223,12 @@ void ArpSeqTrack::render(uint8_t mode_, uint8_t oct_, uint8_t fine_tune_, uint8_ break; + case ARP_PINKDOWN: case ARP_THUMBDOWN: for (uint8_t i = 1; i < num_of_notes; i++) { note = sort_down[i]; notes[len++] = note; - note = sort_down[0]; + note = mode == ARP_PINKDOWN ? sort_up[0] : sort_down[0]; notes[len++] = note; } break; @@ -279,7 +260,7 @@ void ArpSeqTrack::render(uint8_t mode_, uint8_t oct_, uint8_t fine_tune_, uint8_ len++; } } - + end: if (idx >= len) { idx = len - 1; } diff --git a/avr/cores/megacommand/MCL/ArpSeqTrack.h b/avr/cores/megacommand/MCL/ArpSeqTrack.h index 61ca64988..28679fc67 100644 --- a/avr/cores/megacommand/MCL/ArpSeqTrack.h +++ b/avr/cores/megacommand/MCL/ArpSeqTrack.h @@ -25,6 +25,7 @@ #define ARP_UP2 15 #define ARP_DOWN2 16 #define ARP_RND 17 +#define ARP_RND2 18 #define ARP_ON 1 #define ARP_LATCH 2 @@ -39,8 +40,8 @@ class ArpSeqData { uint8_t enabled : 4; uint8_t range : 4; - uint8_t oct : 4; - uint8_t mode : 4; + uint8_t oct; + uint8_t mode; uint8_t fine_tune; uint64_t note_mask[2]; //input notes @@ -67,7 +68,7 @@ class ArpSeqTrack : public ArpSeqData, public SeqTrackBase { void init() { speed = SEQ_SPEED_2X; - length = 1; + length = 2; enabled = false; range = 0; oct = 1; diff --git a/avr/cores/megacommand/MCL/DeviceTrack.h b/avr/cores/megacommand/MCL/DeviceTrack.h index 88f81b280..71e57c01f 100644 --- a/avr/cores/megacommand/MCL/DeviceTrack.h +++ b/avr/cores/megacommand/MCL/DeviceTrack.h @@ -109,7 +109,7 @@ class DeviceTrack : public GridTrack { int memcmp_sound(uint8_t column) { uint16_t pos = get_region() + get_track_size() * (uint16_t)(column) + ((uint16_t) get_sound_data_ptr() - (uint16_t) this); volatile uint8_t *ptr = reinterpret_cast(pos); - return memcmp_bank1(get_sound_data_ptr(), ptr, get_track_size()); + return memcmp_bank1(get_sound_data_ptr(), ptr, get_sound_data_size()); } template T *load_from_mem(uint8_t col) { @@ -151,6 +151,7 @@ class DeviceTrackChunk : public DeviceTrack { virtual void *get_sound_data_ptr() = 0; virtual size_t get_sound_data_size() = 0; + virtual size_t get_sound_cmp_size() { return get_sound_data_size(); } }; #endif /* DEVICETRACK_H__ */ diff --git a/avr/cores/megacommand/MCL/ExtSeqTrack.cpp b/avr/cores/megacommand/MCL/ExtSeqTrack.cpp index 6ba663195..e9e0ec586 100644 --- a/avr/cores/megacommand/MCL/ExtSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/ExtSeqTrack.cpp @@ -656,16 +656,15 @@ void ExtSeqTrack::seq(MidiUartParent *uart_) { if (count_down) { count_down--; - if (is_generic_midi) { - if (count_down == (track_number + 5)) { - load_cache(); - goto end; - } - } if (count_down == 0) { reset(); mod12_counter = 0; - } else if (is_generic_midi && count_down < track_number + 5) { + } + else if (is_generic_midi && count_down <= (track_number + 5)) { + if (!cache_loaded) { + load_cache(); + cache_loaded = true; + } goto end; } } diff --git a/avr/cores/megacommand/MCL/FXPage.cpp b/avr/cores/megacommand/MCL/FXPage.cpp index b75a46c6e..545eda603 100644 --- a/avr/cores/megacommand/MCL/FXPage.cpp +++ b/avr/cores/megacommand/MCL/FXPage.cpp @@ -24,26 +24,27 @@ void FXPage::init() { void FXPage::update_encoders() { for (uint8_t n = 0; n < GUI_NUM_ENCODERS; n++) { - ((MCLEncoder *)encoders[n])->max = 127; + MCLEncoder * enc = encoders[n]; + enc->max = 127; uint8_t a = ((uint8_t)page_mode * GUI_NUM_ENCODERS) + n; uint8_t fx_param = params[a].param; switch (params[a].type) { case MD_FX_ECHO: - encoders[n]->cur = MD.kit.delay[fx_param]; + enc->cur = MD.kit.delay[fx_param]; break; case MD_FX_REV: - encoders[n]->cur = MD.kit.reverb[fx_param]; + enc->cur = MD.kit.reverb[fx_param]; break; case MD_FX_EQ: - encoders[n]->cur = MD.kit.eq[fx_param]; + enc->cur = MD.kit.eq[fx_param]; break; case MD_FX_DYN: - encoders[n]->cur = MD.kit.dynamics[fx_param]; + enc->cur = MD.kit.dynamics[fx_param]; break; } - encoders[n]->old = encoders[n]->cur; + enc->old = enc->cur; } init_encoders_used_clock(); @@ -59,27 +60,13 @@ void FXPage::loop() { for (uint8_t i = 0; i < GUI_NUM_ENCODERS; i++) { uint8_t n = i + (page_mode * GUI_NUM_ENCODERS); - - if (encoders[i]->hasChanged()) { + MCLEncoder *enc = encoders[i]; + if (enc->hasChanged()) { uint8_t fx_param = params[n].param; uint8_t fx_type = params[n].type; uint8_t val; - MD.sendFXParam(fx_param, encoders[i]->cur, fx_type); - switch (fx_type) { - case MD_FX_ECHO: - MD.kit.delay[fx_param] = encoders[i]->cur; - break; - case MD_FX_DYN: - MD.kit.dynamics[fx_param] = encoders[i]->cur; - break; - case MD_FX_REV: - MD.kit.reverb[fx_param] = encoders[i]->cur; - break; - case MD_FX_EQ: - MD.kit.eq[fx_param] = encoders[i]->cur; - break; - } + MD.setFXParam(fx_param, enc->cur, fx_type, true); } } } diff --git a/avr/cores/megacommand/MCL/FileBrowserPage.cpp b/avr/cores/megacommand/MCL/FileBrowserPage.cpp index d301d425f..f3684e832 100644 --- a/avr/cores/megacommand/MCL/FileBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/FileBrowserPage.cpp @@ -85,7 +85,6 @@ void FileBrowserPage::query_filesystem() { file_menu_page.menu.enable_entry(FM_NEW_FOLDER, show_new_folder); file_menu_page.menu.enable_entry(FM_DELETE, true); // delete file_menu_page.menu.enable_entry(FM_RENAME, true); // rename - file_menu_page.menu.enable_entry(FM_OVERWRITE, false); //show_overwrite); file_menu_page.menu.enable_entry(FM_CANCEL, true); // cancel file_menu_page.menu.enable_entry(FM_RECVALL, false); file_menu_page.menu.enable_entry(FM_SENDALL, false); @@ -164,8 +163,8 @@ void FileBrowserPage::init() { } void FileBrowserPage::draw_menu() { - oled_display.fillRect(0, 3, 45, 28, BLACK); - oled_display.drawRect(1, 4, 43, 26, WHITE); + oled_display.fillRect(0, 3, 45, 29, BLACK); + oled_display.drawRect(1, 4, 43, 27, WHITE); file_menu_page.draw_menu(6, 12, 39); oled_display.display(); } @@ -319,7 +318,7 @@ bool FileBrowserPage::_cd(const char *child) { DEBUG_PRINTLN(lwd); file.close(); - char *ptr = child; + const char *ptr = child; if (child[0] == '/' && child[1] != '\0') { SD.chdir("/"); @@ -398,18 +397,6 @@ bool FileBrowserPage::_handle_filemenu() { on_rename(buf1, buf2); } return true; - case FM_OVERWRITE: // overwrite - /* - strcpy(buf2, "Overwrite "); - strcat(buf2, buf1); - strcat(buf2, "?"); - if (mcl_gui.wait_for_confirm("CONFIRM", buf2)) { - // the derived class may expect the file to be open - // when on_select is called. - file.open(buf1, O_READ); - on_select(buf1); - }*/ - break; } return false; } diff --git a/avr/cores/megacommand/MCL/FileBrowserPage.h b/avr/cores/megacommand/MCL/FileBrowserPage.h index 8ecf6d494..3c3500716 100644 --- a/avr/cores/megacommand/MCL/FileBrowserPage.h +++ b/avr/cores/megacommand/MCL/FileBrowserPage.h @@ -27,9 +27,8 @@ #define FM_NEW_FOLDER 1 #define FM_DELETE 2 #define FM_RENAME 3 -#define FM_OVERWRITE 4 -#define FM_RECVALL 5 -#define FM_SENDALL 6 +#define FM_RECVALL 4 +#define FM_SENDALL 5 class FileBrowserFileTypes { constexpr static uint8_t size = 2; diff --git a/avr/cores/megacommand/MCL/Grid.cpp b/avr/cores/megacommand/MCL/Grid.cpp index 7945abed2..34841eba2 100644 --- a/avr/cores/megacommand/MCL/Grid.cpp +++ b/avr/cores/megacommand/MCL/Grid.cpp @@ -74,13 +74,12 @@ bool Grid::new_grid(const char *gridname) { if (!write_header()) { goto end; } - DEBUG_PRINTLN(F("Initializing grid.. please wait")); #ifdef OLED_DISPLAY oled_display.drawRect(15, 23, 98, 6, WHITE); #endif // Initialise the project file by filling the grid with blank data. - uint8_t ledstatus; + uint8_t ledstatus = 0; for (uint16_t i = 0; i < GRID_LENGTH; i++) { #ifdef OLED_DISPLAY @@ -154,7 +153,7 @@ bool Grid::clear_slot(uint8_t column, uint16_t row, bool update_header) { temp_track.active = EMPTY_TRACK_TYPE; temp_track.link.init(row); - int32_t offset = get_slot_offset(column, row); + uint32_t offset = get_slot_offset(column, row); ret = file.seekSet(offset); @@ -167,7 +166,6 @@ bool Grid::clear_slot(uint8_t column, uint16_t row, bool update_header) { } // DEBUG_PRINTLN("Writing"); // DEBUG_DUMP(sizeof(temptrack.active)); - ret = mcl_sd.write_data((uint8_t *)&(temp_track), sizeof(temp_track), &file); if (!ret) { DEBUG_PRINTLN(F("Write failed")); @@ -180,7 +178,7 @@ bool Grid::clear_row(uint16_t row) { GridRowHeader row_header; row_header.init(); for (uint8_t x = 0; x < GRID_WIDTH; x++) { - clear_slot(x, row, false); + if (!clear_slot(x, row, false)) { return false; } } return write_row_header(&row_header, row); } diff --git a/avr/cores/megacommand/MCL/Grid.h b/avr/cores/megacommand/MCL/Grid.h index f752321e4..77ff8aa92 100644 --- a/avr/cores/megacommand/MCL/Grid.h +++ b/avr/cores/megacommand/MCL/Grid.h @@ -49,7 +49,7 @@ class Grid : public GridHeader { return offset; } - uint32_t get_row_header_offset(int16_t row) { + uint32_t get_row_header_offset(uint16_t row) { uint32_t offset = (uint32_t)(GRID_SLOT_BYTES * GRID_WIDTH) + (uint32_t)(0 + (row * (GRID_WIDTH + 1))) * (uint32_t)GRID_SLOT_BYTES; diff --git a/avr/cores/megacommand/MCL/GridIOPage.cpp b/avr/cores/megacommand/MCL/GridIOPage.cpp index edbb70cd8..3c65a1574 100644 --- a/avr/cores/megacommand/MCL/GridIOPage.cpp +++ b/avr/cores/megacommand/MCL/GridIOPage.cpp @@ -3,6 +3,9 @@ uint32_t GridIOPage::track_select = 0; bool GridIOPage::show_track_type = false; +bool GridIOPage::show_offset = false; +uint8_t GridIOPage::offset = 0; + uint8_t GridIOPage::old_grid = 0; void GridIOPage::cleanup() { @@ -15,6 +18,8 @@ void GridIOPage::init() { old_grid = proj.get_grid(); show_track_type = false; track_select = 0; + show_offset = 0; + offset = 255; R.Clear(); R.use_icons_logo(); } @@ -57,13 +62,24 @@ bool GridIOPage::handleEvent(gui_event_t *event) { MD.set_trigleds(mcl_cfg.track_type_select, TRIGLED_EXCLUSIVE); } } else { + if (show_offset) { + offset = track; + } trig_interface.send_md_leds(TRIGLED_OVERLAY); } } else { if (!show_track_type) { trig_interface.send_md_leds(TRIGLED_OVERLAY); + if (note_interface.notes_all_off()) { - if (BUTTON_DOWN(Buttons.BUTTON2)) { + if (show_offset) { + show_offset = !show_offset; + note_interface.init_notes(); + if (show_offset) { + offset = 255; + } + } + else if (BUTTON_DOWN(Buttons.BUTTON2)) { return true; } else { action(); @@ -78,6 +94,9 @@ bool GridIOPage::handleEvent(gui_event_t *event) { uint8_t key = event->source - 64; if (event->mask == EVENT_BUTTON_PRESSED) { switch (key) { + case MDX_KEY_BANKD: { + return true; + } case MDX_KEY_NO: { goto close; } diff --git a/avr/cores/megacommand/MCL/GridIOPage.h b/avr/cores/megacommand/MCL/GridIOPage.h index f41a2a6ba..33e3a9476 100644 --- a/avr/cores/megacommand/MCL/GridIOPage.h +++ b/avr/cores/megacommand/MCL/GridIOPage.h @@ -11,6 +11,8 @@ class GridIOPage : public LightPage { static uint8_t old_grid; static bool show_track_type; + static bool show_offset; + static uint8_t offset; GridIOPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) : LightPage( e1, e2, e3 ,e4) { diff --git a/avr/cores/megacommand/MCL/GridLoadPage.cpp b/avr/cores/megacommand/MCL/GridLoadPage.cpp index ad30cfa8d..4806a4851 100644 --- a/avr/cores/megacommand/MCL/GridLoadPage.cpp +++ b/avr/cores/megacommand/MCL/GridLoadPage.cpp @@ -2,8 +2,6 @@ void GridLoadPage::init() { GridIOPage::init(); - MD.currentKit = MD.getCurrentKit(CALLBACK_TIMEOUT); - // MD.requestKit(MD.currentKit); note_interface.init_notes(); trig_interface.send_md_leds(TRIGLED_OVERLAY); trig_interface.on(); @@ -46,8 +44,8 @@ void GridLoadPage::draw_popup() { strcpy(str, "GROUP LOAD"); if (!show_track_type) { - strcpy(str, "LOAD FROM "); - str[10] = 'X' + proj.get_grid(); + strcpy(str, "LOAD TRACKS"); + //str[10] = 'X' + proj.get_grid(); } mcl_gui.draw_popup(str, true); } @@ -114,8 +112,23 @@ void GridLoadPage::display() { if (show_track_type) { mcl_gui.draw_track_type_select(mcl_cfg.track_type_select); - } else { - mcl_gui.draw_trigs(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 4 + 20, note_interface.notes_off | note_interface.notes_on ); + } + else { + uint16_t trig_mask = note_interface.notes_off | note_interface.notes_on; + // mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 8, + // "STEP", K); + if (show_offset) { + oled_display.setFont(); + oled_display.setCursor(MCLGUI::s_menu_x + 18, 12); + oled_display.print("DESTINATION"); + trig_mask = 0; + SET_BIT16(trig_mask,offset); + //if (offset < 16) { + // oled_display.setCursor(MCLGUI::s_menu_x + 4 + offset * MCLGUI::seq_w + 1, 16); + // oled_display.print(">"); + // } + } + else { oled_display.setFont(&Elektrothic); @@ -125,8 +138,6 @@ void GridLoadPage::display() { oled_display.setFont(&TomThumb); char K[4] = {'\0'}; - // mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 8, - // "STEP", K); char modestr[7]; get_modestr(modestr); @@ -153,8 +164,9 @@ void GridLoadPage::display() { mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + MCLGUI::s_menu_w - 38, MCLGUI::s_menu_y + 7, "QUANT", K); - oled_display.setFont(&TomThumb); // draw step count + } + oled_display.setFont(&TomThumb); uint8_t step_count = (MidiClock.div16th_counter - mcl_actions.start_clock32th / 2) - (64 * @@ -163,6 +175,8 @@ void GridLoadPage::display() { MCLGUI::s_menu_y + 4 + 17); oled_display.print(step_count); + + mcl_gui.draw_trigs(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 4 + 20, trig_mask ); // draw data flow in the center /* oled_display.setCursor(48, MCLGUI::s_menu_y + 4 + 12); @@ -183,10 +197,6 @@ void GridLoadPage::display() { oled_display.setFont(oldfont); } void GridLoadPage::load() { - //display_load(); -// oled_display.display(); - /// !Note, note_off_event has reentry issues, so we have to first set - /// the page to avoid driving this code path again. uint8_t track_select_array[NUM_SLOTS] = {0}; @@ -204,7 +214,7 @@ void GridLoadPage::load() { mcl.setPage(GRID_PAGE); trig_interface.off(); - grid_task.load_queue.put(mcl_cfg.load_mode, grid_page.getRow(), track_select_array); + grid_task.load_queue.put(mcl_cfg.load_mode, grid_page.getRow(), track_select_array, offset); } void GridLoadPage::group_select() { @@ -214,7 +224,7 @@ void GridLoadPage::group_select() { MD.set_trigleds(mcl_cfg.track_type_select, TRIGLED_EXCLUSIVE); } -void GridLoadPage::group_load(uint8_t row) { +void GridLoadPage::group_load(uint8_t row, uint8_t offset_) { if (row >= GRID_LENGTH) { return; } uint8_t track_select_array[NUM_SLOTS] = {0}; @@ -226,7 +236,7 @@ void GridLoadPage::group_load(uint8_t row) { //oled_display.display(); mcl_actions.write_original = 1; - grid_task.load_queue.put(mcl_cfg.load_mode, row, track_select_array); + grid_task.load_queue.put(mcl_cfg.load_mode, row, track_select_array, offset); } bool GridLoadPage::handleEvent(gui_event_t *event) { @@ -243,10 +253,21 @@ bool GridLoadPage::handleEvent(gui_event_t *event) { mcl.setPage(GRID_PAGE); return false; } + case MDX_KEY_FUNC: { + if (mcl_cfg.load_mode == LOAD_MANUAL) { + show_offset = !show_offset; + note_interface.init_notes(); + if (show_offset) { offset = 255; } + } + return true; + } case MDX_KEY_YES: { group_select(); return true; } + case MDX_KEY_EXTENDED: { + return false; + } case MDX_KEY_BANKA: case MDX_KEY_BANKB: case MDX_KEY_BANKC: { @@ -275,9 +296,11 @@ bool GridLoadPage::handleEvent(gui_event_t *event) { load_groups: trig_interface.off(); - group_load(grid_page.getRow()); - + group_load(grid_page.getRow(), offset); + grid_task.load_queue_handler(); + grid_task.transition_handler(); mcl.setPage(GRID_PAGE); return true; } + return false; } diff --git a/avr/cores/megacommand/MCL/GridLoadPage.h b/avr/cores/megacommand/MCL/GridLoadPage.h index 5f9f6c10f..07dddc76b 100644 --- a/avr/cores/megacommand/MCL/GridLoadPage.h +++ b/avr/cores/megacommand/MCL/GridLoadPage.h @@ -15,7 +15,7 @@ class GridLoadPage : public GridIOPage { void get_modestr(char *modestr); void load(); void group_select(); - void group_load(uint8_t row); + void group_load(uint8_t row, uint8_t offset_ = 255); bool handleEvent(gui_event_t *event); void get_mode_str(char *str, uint8_t mode); void display_load(); diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index 68bfa2f21..c4aefef8f 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -13,7 +13,7 @@ void GridPage::init() { return; } trig_interface.off(); - load_slot_models(); + //load_slot_models(); oled_display.clearDisplay(); R.Clear(); R.use_machine_names_short(); @@ -439,7 +439,9 @@ void GridPage::display_grid() { switch (track_type) { case MD_TRACK_TYPE: { auto tmp = getMDMachineNameShort(model, 2); - copyMachineNameShort(tmp, str); + if (tmp) { + copyMachineNameShort(tmp, str); + } break; } case A4_TRACK_TYPE: @@ -886,6 +888,7 @@ bool GridPage::handleEvent(gui_event_t *event) { case MDX_KEY_BANKA: case MDX_KEY_BANKB: case MDX_KEY_BANKC: { + loadmode: mcl_cfg.load_mode = key - MDX_KEY_BANKA + 1; bool persistent = false; grid_load_page.draw_popup_title(mcl_cfg.load_mode, persistent); @@ -972,8 +975,7 @@ bool GridPage::handleEvent(gui_event_t *event) { case MDX_KEY_BANKB: case MDX_KEY_BANKC: { if (!trig_interface.is_key_down(MDX_KEY_FUNC)) { - mcl_cfg.load_mode = key - MDX_KEY_BANKA + 1; - return true; + goto loadmode; } } } @@ -1097,7 +1099,6 @@ bool GridPage::handleEvent(gui_event_t *event) { } show_slot_menu = true; grid_slot_page.init(); - grid_slot_page.gen_menu_row_names(); return true; } diff --git a/avr/cores/megacommand/MCL/GridPage.h b/avr/cores/megacommand/MCL/GridPage.h index aa445d510..3b07b6ca1 100644 --- a/avr/cores/megacommand/MCL/GridPage.h +++ b/avr/cores/megacommand/MCL/GridPage.h @@ -11,8 +11,9 @@ #define SLOT_DISABLED 255 #define SLOT_PENDING 254 -#define SLOT_RAM_RECORD 253 -#define SLOT_RAM_PLAY 252 +#define SLOT_OFFSET_LOAD 253 +#define SLOT_RAM_RECORD 252 +#define SLOT_RAM_PLAY 251 class GridPage : public LightPage { public: diff --git a/avr/cores/megacommand/MCL/GridRowHeader.cpp b/avr/cores/megacommand/MCL/GridRowHeader.cpp index 868e3087e..827f55cfd 100644 --- a/avr/cores/megacommand/MCL/GridRowHeader.cpp +++ b/avr/cores/megacommand/MCL/GridRowHeader.cpp @@ -18,7 +18,7 @@ bool GridRowHeader::is_empty() { } void GridRowHeader::init() { - memset(this, 0, sizeof(GridRowHeader)); + memset(&active, 0, GRID_ROW_HEADER_LENGTH); /* active = false; for (uint8_t x = 0; x < GRID_WIDTH; x++) { diff --git a/avr/cores/megacommand/MCL/GridRowHeader.h b/avr/cores/megacommand/MCL/GridRowHeader.h index 131befb13..fc4417ac0 100644 --- a/avr/cores/megacommand/MCL/GridRowHeader.h +++ b/avr/cores/megacommand/MCL/GridRowHeader.h @@ -13,6 +13,8 @@ class GridRowHeader_270 { uint8_t model[22]; }; +#define GRID_ROW_HEADER_LENGTH (1 + 17 + GRID_WIDTH + GRID_WIDTH) + class GridRowHeader { public: bool active; diff --git a/avr/cores/megacommand/MCL/GridSavePage.cpp b/avr/cores/megacommand/MCL/GridSavePage.cpp index c5313fcc4..9fcb6fdc7 100644 --- a/avr/cores/megacommand/MCL/GridSavePage.cpp +++ b/avr/cores/megacommand/MCL/GridSavePage.cpp @@ -18,8 +18,7 @@ void GridSavePage::draw_popup() { char str[16] = "GROUP SAVE"; if (!show_track_type) { - strcpy(str, "SAVE TO "); - str[8] = 'X' + proj.get_grid(); + strcpy(str, "SAVE TRACKS"); } mcl_gui.draw_popup(str, true); } @@ -79,7 +78,7 @@ void GridSavePage::display() { } void GridSavePage::save() { - oled_display.textbox("SAVE SLOTS", ""); + oled_display.textbox("SAVE TRACKS", ""); oled_display.display(); uint8_t save_mode = SAVE_SEQ; @@ -127,6 +126,9 @@ bool GridSavePage::handleEvent(gui_event_t *event) { group_select(); return true; } + case MDX_KEY_EXTENDED: { + return false; + } case MDX_KEY_BANKA: case MDX_KEY_BANKB: case MDX_KEY_BANKC: { @@ -165,4 +167,5 @@ bool GridSavePage::handleEvent(gui_event_t *event) { mcl.setPage(GRID_PAGE); return true; } + return false; } diff --git a/avr/cores/megacommand/MCL/GridTask.cpp b/avr/cores/megacommand/MCL/GridTask.cpp index 28f364986..1c08d1b48 100644 --- a/avr/cores/megacommand/MCL/GridTask.cpp +++ b/avr/cores/megacommand/MCL/GridTask.cpp @@ -14,41 +14,24 @@ void GridTask::row_update() { void GridTask::gui_update() { if (MDSeqTrack::gui_update) { if (MidiClock.state == 2) { + if (mcl.currentPage() == SEQ_STEP_PAGE && IS_BIT_SET16(MDSeqTrack::gui_update,last_md_track)) { + auto active_track = mcl_seq.md_tracks[last_md_track]; + MD.sync_seqtrack(active_track.length, active_track.speed, active_track.step_count); + } if (last_active_row < GRID_LENGTH) { - if (mcl.currentPage() == SEQ_STEP_PAGE && IS_BIT_SET16(MDSeqTrack::gui_update,last_md_track)) { - auto active_track = mcl_seq.md_tracks[last_md_track]; - MD.sync_seqtrack(active_track.length, active_track.speed, active_track.length - 1); - } - row_update(); + row_update(); } } MDSeqTrack::gui_update = 0; } } - -void GridTask::run() { - // DEBUG_PRINTLN(MidiClock.div32th_counter / 2); - // A4Track *a4_track = (A4Track *)&temp_track; - // ExtTrack *ext_track = (ExtTrack *)&temp_track; - // MD GUI update. - - perf_page.encoder_check(); - trig_interface.check_key_throttle(); - - if (stop_hard_callback) { - mcl_actions_callbacks.StopHardCallback(); - stop_hard_callback = false; - load_queue.init(); - return; - } - - gui_update(); - +void GridTask::load_queue_handler() { if (!load_queue.is_empty()) { uint8_t mode; + uint8_t offset; uint8_t row_select_array[NUM_SLOTS]; uint8_t track_select[NUM_SLOTS] = {0}; - load_queue.get(&mode, row_select_array); + load_queue.get(mode, offset, row_select_array); DEBUG_PRINTLN("load queue get"); DEBUG_PRINTLN(mode); for (uint8_t n = 0; n < NUM_SLOTS; n++) { @@ -62,8 +45,28 @@ void GridTask::run() { DEBUG_PRINTLN(row_select_array[n]); } mcl_actions.write_original = 1; - mcl_actions.load_tracks(255, track_select, row_select_array, mode); + mcl_actions.load_tracks(255, track_select, row_select_array, mode, offset); } +} + +void GridTask::run() { + // DEBUG_PRINTLN(MidiClock.div32th_counter / 2); + // A4Track *a4_track = (A4Track *)&temp_track; + // ExtTrack *ext_track = (ExtTrack *)&temp_track; + // MD GUI update. + + perf_page.encoder_check(); + trig_interface.check_key_throttle(); + + if (stop_hard_callback) { + mcl_actions_callbacks.StopHardCallback(); + stop_hard_callback = false; + load_queue.init(); + return; + } + + gui_update(); + load_queue_handler(); GridTask::transition_handler(); } @@ -177,8 +180,8 @@ void GridTask::transition_handler() { float tempo = MidiClock.get_tempo(); // float div192th_per_second = tempo * 0.8f; // float div192th_time = 1.0 / div192th_per_second; - float div192th_time = 1.0 / (tempo * 0.8f); - // diff * div19th_time > 0.8ms equivalent to diff > (0.8/1.25) * tempo + // float div192th_time = 1.0 / (tempo * 0.8f); + // diff * div19th_time > 0.08 equivalent to diff > (0.8 * 0.08) * tempo for (int8_t c = NUM_DEVS - 1; c >= 0; c--) { wait = true; @@ -208,17 +211,19 @@ void GridTask::transition_handler() { MidiClock.div192th_counter, go_step)) != 0) && (MidiClock.div192th_counter < go_step) && (MidiClock.state == 2)) { - MidiUartParent::handle_midi_lock = 1; - handleIncomingMidi(); - MidiUartParent::handle_midi_lock = 0; - if ((float)diff > (tempo * 0.8f) * 0.08) { - GUI.loop(); - } + MidiUartParent::handle_midi_lock = 1; + handleIncomingMidi(); + MidiUartParent::handle_midi_lock = 0; + if ((float)diff > tempo * 0.064f) { //0.8 * 0.08 = 0.128f + GUI.loop(); + } } } wait = false; if (transition_load(n, track_idx, gdt)) { - grid_page.active_slots[n] = slots_changed[n]; + if (grid_page.active_slots[n] != SLOT_OFFSET_LOAD) { + grid_page.active_slots[n] = slots_changed[n]; + } } } } @@ -301,7 +306,8 @@ bool GridTask::transition_load(uint8_t n, uint8_t track_idx, } gdt->seq_track->count_down = -1; - if (mcl_actions.send_machine[n] == 0) { + gdt->seq_track->load_sound = mcl_actions.send_machine[n]; + if (mcl_actions.send_machine[n] == 1) { pmem_track->transition_send(track_idx, n); } diff --git a/avr/cores/megacommand/MCL/GridTask.h b/avr/cores/megacommand/MCL/GridTask.h index d28d9858c..93b683c50 100644 --- a/avr/cores/megacommand/MCL/GridTask.h +++ b/avr/cores/megacommand/MCL/GridTask.h @@ -6,10 +6,16 @@ #include "Elektron.h" #include "GridChain.h" +class LoadQueueModes { + public: + uint8_t mode; + uint8_t offset; +}; + class LoadQueue { public: uint8_t row_selects[NUM_LINKS][NUM_SLOTS]; - uint8_t modes[NUM_LINKS]; + LoadQueueModes modes[NUM_LINKS]; uint8_t rd; uint8_t wr; bool full; @@ -20,10 +26,11 @@ class LoadQueue { bool full = false; } - void put(uint8_t mode, uint8_t *row_select) { + void put(uint8_t mode, uint8_t *row_select, uint8_t offset = 255) { if (full) { return; } memcpy(row_selects[wr],row_select,NUM_SLOTS); - modes[wr++] = mode; + modes[wr].mode = mode; + modes[wr++].offset = offset; if (wr == NUM_LINKS) { wr = 0; } @@ -33,14 +40,15 @@ class LoadQueue { } - void put(uint8_t mode, uint8_t row, uint8_t *track_select_array) { + void put(uint8_t mode, uint8_t row, uint8_t *track_select_array, uint8_t offset = 255) { if (full) { return; } for (uint8_t n = 0; n < NUM_SLOTS; n++) { row_selects[wr][n] = 255; if (track_select_array[n]) { row_selects[wr][n] = row; } } - modes[wr++] = mode; + modes[wr].mode = mode; + modes[wr++].offset = offset; if (wr == NUM_LINKS) { wr = 0; } @@ -49,9 +57,10 @@ class LoadQueue { } } - void get(uint8_t *mode, uint8_t *row_select) { + void get(uint8_t &mode, uint8_t &offset, uint8_t *row_select) { memcpy(row_select,row_selects[rd],NUM_SLOTS); - *mode = modes[rd++]; + mode = modes[rd].mode; + offset = modes[rd++].offset; if (rd == NUM_LINKS) { rd = 0; } @@ -108,6 +117,7 @@ class GridTask : public Task { void row_update(); void gui_update(); void update_transition_details(); + void load_queue_handler(); void transition_handler(); bool link_load(uint8_t n, uint8_t track_idx, uint8_t *slots_changed, uint8_t *track_select_array, GridDeviceTrack *gdt); diff --git a/avr/cores/megacommand/MCL/LFOPage.cpp b/avr/cores/megacommand/MCL/LFOPage.cpp index 0e39ec9f1..cf77d307d 100644 --- a/avr/cores/megacommand/MCL/LFOPage.cpp +++ b/avr/cores/megacommand/MCL/LFOPage.cpp @@ -266,7 +266,7 @@ void LFOPage::learn_param(uint8_t track, uint8_t param, uint8_t value) { lfo_track->params[1].offset = value; reconfig = true; } - if (reconfig) { config_encoders(); } + if (mcl.currentPage() == LFO_PAGE && reconfig) { config_encoders(); } } @@ -303,8 +303,7 @@ bool LFOPage::handleEvent(gui_event_t *event) { if (event->mask == EVENT_BUTTON_PRESSED) { switch (key) { case MDX_KEY_YES: { - lfo_track->enable = !(lfo_track->enable); - break; + goto lfo_enable; } case MDX_KEY_UP: { if (page_mode < LFO_OFFSET) { @@ -344,7 +343,9 @@ bool LFOPage::handleEvent(gui_event_t *event) { } if (EVENT_PRESSED(event, Buttons.BUTTON1)) { + lfo_enable: lfo_track->enable = !(lfo_track->enable); + if (!lfo_track->enable) { lfo_track->reset_params(); } } return false; } diff --git a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp index 2ac0d4594..7c6afa94f 100644 --- a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp @@ -9,7 +9,6 @@ void LFOSeqTrack::load_tables() { IExpLFO iexp_lfo; LFO *lfo; - for (uint8_t n = 0; n < 4; n++) { switch (n) { case SIN_WAV: @@ -36,39 +35,44 @@ int16_t LFOSeqTrack::get_sample(uint8_t n) { int16_t out = 0; switch (wav_type) { - case IRAMP_WAV: - case EXP_WAV: + case IRAMP_WAV: + case EXP_WAV: out = 128 - wav_tables[wav_type - 2][n]; break; - default: + default: out = wav_tables[wav_type][n]; break; } switch (wav_type) { - //OFFSET CENTRE - case SIN_WAV: - case TRI_WAV: - out -= 64; - break; - //OFFSET MAX - default: - out -= 128; - break; + // OFFSET CENTRE + case SIN_WAV: + case TRI_WAV: + out -= 64; + break; + // OFFSET MAX + default: + out -= 128; + break; } return out; } -uint8_t LFOSeqTrack::get_wav_value(uint8_t sample_count, uint8_t dest, uint8_t param) { - int8_t offset = get_param_offset(dest, params[param].param); - int16_t depth = params[param].depth; +uint8_t LFOSeqTrack::get_wav_value(uint8_t sample_count, uint8_t dest, + uint8_t param_id) { + int8_t offset = get_param_offset(dest, param_id); + int16_t depth = params[param_id].depth; - int16_t sample = ((get_sample(sample_count) * depth) / 128) + offset; + int16_t sample = ((get_sample(sample_count) * depth) / 128) + offset; - if (sample > 127) { return 127; } - if (sample < 0) { return 0; } + if (sample > 127) { + return 127; + } + if (sample < 0) { + return 0; + } - return (uint8_t) sample; + return (uint8_t)sample; } void LFOSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { @@ -76,12 +80,14 @@ void LFOSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { uart = uart_; if ((MidiClock.mod12_counter == 0) && (mode != LFO_MODE_FREE) && - IS_BIT_SET64(pattern_mask, step_count)) { - sample_count = 0; - } + IS_BIT_SET64(pattern_mask, step_count)) { + sample_count = 0; + } if (enable) { for (uint8_t i = 0; i < NUM_LFO_PARAMS; i++) { - if (params[i].dest == 0) { continue; } + if (params[i].dest == 0) { + continue; + } uint8_t dest = params[i].dest - 1; uint8_t wav_value = get_wav_value(sample_count, dest, i); if (last_wav_value[i] != wav_value) { @@ -91,7 +97,7 @@ void LFOSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { uint8_t channel = dest - (NUM_MD_TRACKS + 4); uart2_->sendCC(channel, param, wav_value); } else if (dest >= NUM_MD_TRACKS) { - MD.sendFXParam(param, wav_value, MD_FX_ECHO + dest - NUM_MD_TRACKS, + MD.setFXParam(param, wav_value, MD_FX_ECHO + dest - NUM_MD_TRACKS, false, uart); } else { MD.setTrackParam(dest, param, wav_value, uart); @@ -111,17 +117,17 @@ void LFOSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { } } - /* - if (speed < 8) { - sample_count += 8 - speed; - } else { - sample_hold += 1; - if (sample_hold >= (speed - 8)) { - sample_hold = 0; - sample_count += 1; - } - } - */ + /* + if (speed < 8) { + sample_count += 8 - speed; + } else { + sample_hold += 1; + if (sample_hold >= (speed - 8)) { + sample_hold = 0; + sample_count += 1; + } + } + */ if (sample_count >= LFO_LENGTH) { // Free running LFO should reset, oneshot should hold at last value. if (mode == LFO_MODE_ONE) { @@ -141,7 +147,30 @@ void LFOSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { uart = uart_old; } -uint8_t LFOSeqTrack::get_param_offset(uint8_t dest, uint8_t param) { +void LFOSeqTrack::reset_params() { + uint16_t mod12_counter = MidiClock.mod12_counter; +// while (MidiClock.state == 2 && mod12_counter == MidiClock.mod12_counter) {}; + + for (uint8_t i = 0; i < NUM_LFO_PARAMS; i++) { + if (params[i].dest == 0) { + continue; + } + uint8_t dest = params[i].dest - 1; + uint8_t param = params[i].param; + uint8_t wav_value = get_param_offset(dest, i); + if (dest >= NUM_MD_TRACKS + 4) { + uint8_t channel = dest - (NUM_MD_TRACKS + 4); + MidiUart2.sendCC(channel, param, wav_value); + } else if (dest >= NUM_MD_TRACKS) { + MD.setFXParam(param, wav_value, MD_FX_ECHO + dest - NUM_MD_TRACKS, false, &MidiUart); + } else { + MD.setTrackParam(dest, param, wav_value, &MidiUart); + } + } +} + +uint8_t LFOSeqTrack::get_param_offset(uint8_t dest, uint8_t param_id) { + uint8_t param = params[param_id].param; if (dest < NUM_MD_TRACKS) { return MD.kit.params[dest][param]; } else if (dest < NUM_MD_TRACKS + 4) { @@ -159,10 +188,9 @@ uint8_t LFOSeqTrack::get_param_offset(uint8_t dest, uint8_t param) { return MD.kit.eq[param]; break; } - } - else { - //MIDI - return param; + } else { + // MIDI + return params[param_id].offset; } return 255; } diff --git a/avr/cores/megacommand/MCL/LFOSeqTrack.h b/avr/cores/megacommand/MCL/LFOSeqTrack.h index 56b5a3975..4dc4cbf9f 100644 --- a/avr/cores/megacommand/MCL/LFOSeqTrack.h +++ b/avr/cores/megacommand/MCL/LFOSeqTrack.h @@ -77,8 +77,10 @@ class LFOSeqTrack : public LFOSeqTrackData { void load_tables(); - uint8_t get_param_offset(uint8_t dest, uint8_t param); - ALWAYS_INLINE() uint8_t get_wav_value(uint8_t sample_count, uint8_t dest, uint8_t param); + uint8_t get_param_offset(uint8_t dest, uint8_t param_id); + void reset_params(); + + uint8_t get_wav_value(uint8_t sample_count, uint8_t dest, uint8_t param_id); void set_wav_type(uint8_t _wav_type) { wav_type = _wav_type; @@ -88,7 +90,7 @@ class LFOSeqTrack : public LFOSeqTrackData { params[param].depth = depth; } void load_wav_table(uint8_t table); - ALWAYS_INLINE() void seq(MidiUartParent *uart_, MidiUartParent *uart2_); + void seq(MidiUartParent *uart_, MidiUartParent *uart2_); }; #endif /* LFOSEQTRACK_H__ */ diff --git a/avr/cores/megacommand/MCL/LoadProjectPage.cpp b/avr/cores/megacommand/MCL/LoadProjectPage.cpp index 3204781a7..215ce4fe3 100644 --- a/avr/cores/megacommand/MCL/LoadProjectPage.cpp +++ b/avr/cores/megacommand/MCL/LoadProjectPage.cpp @@ -1,8 +1,8 @@ #include "MCL_impl.h" - void LoadProjectPage::init() { + DEBUG_PRINTLN("load project page init") DEBUG_PRINT_FN(); show_dirs = true; select_dirs = true; @@ -13,7 +13,7 @@ void LoadProjectPage::init() { show_overwrite = false; FileBrowserPage::init(); - strncpy(focus_match,mcl_cfg.project,PRJ_NAME_LEN); + strncpy(focus_match, mcl_cfg.project, PRJ_NAME_LEN); query_filesystem(); } @@ -28,7 +28,7 @@ void LoadProjectPage::on_select(const char *entry) { file.close(); - char proj_filename[PRJ_NAME_LEN + 5] = {'\0'}; + char proj_filename[f_len] = {'\0'}; strcpy(proj_filename, entry); uint8_t count = 2; while (count--) { @@ -41,7 +41,6 @@ void LoadProjectPage::on_select(const char *entry) { memcpy(proj_filename, mcl_cfg.project, sizeof(proj_filename)); } } - } void LoadProjectPage::on_delete(const char *entry) { @@ -52,63 +51,97 @@ void LoadProjectPage::on_delete(const char *entry) { gfx.alert("ERROR", "CURRENT PROJECT"); return; } - if (dir) { rm_dir(entry); } + if (dir) { + rm_dir(entry); + } } void LoadProjectPage::on_rename(const char *from, const char *to) { + /* + char to[f_len] = {0}; + strncpy(to,to_,f_len); + char from[f_len] = {0}; + strncpy(from,from_,f_len); +*/ + DEBUG_PRINTLN("on rename"); + file.open(from, O_READ); + bool dir = file.isDirectory(); + file.close(); + + if (!dir) { + return; + } + + if (!SD.chdir(from)) { + goto error; + } bool reload_current = false; if (strcmp(mcl_cfg.project, from) == 0) { DEBUG_PRINTLN("reload current"); reload_current = true; } - char grid_filename[PRJ_NAME_LEN + 5] = {'\0'}; - strcpy(grid_filename, from); - uint8_t l = strlen(grid_filename); + char grid_filename[f_len] = {'\0'}; + char to_grid_filename[f_len] = {'\0'}; + char proj_filename[f_len] = {'\0'}; - char to_grid_filename[PRJ_NAME_LEN + 5] = {'\0'}; - strcpy(to_grid_filename, to); - uint8_t l2 = strlen(to_grid_filename); - - char proj_filename[PRJ_NAME_LEN + 5] = {'\0'}; - strcpy(proj_filename, from); + strncpy(proj_filename, from, f_len); strcat(proj_filename, ".mcl"); - char to_proj_filename[PRJ_NAME_LEN + 5] = {'\0'}; - strcpy(to_proj_filename, to); + char to_proj_filename[f_len] = {'\0'}; + strncpy(to_proj_filename, to, f_len); strcat(to_proj_filename, ".mcl"); - file.open(from, O_READ); - bool dir = file.isDirectory(); - file.close(); - - if (!dir) { - return; - } - - if (_cd(from)) { - for (uint8_t i = 0; i < NUM_GRIDS; i++) { - grid_filename[l] = '.'; - grid_filename[l + 1] = i + '0'; - grid_filename[l + 2] = '\0'; - - to_grid_filename[l2] = '.'; - to_grid_filename[l2 + 1] = i + '0'; - to_grid_filename[l2 + 2] = '\0'; + strncpy(to_grid_filename, to, f_len); + strncpy(grid_filename, from, f_len); + uint8_t l = strlen(grid_filename); + uint8_t l2 = strlen(to_grid_filename); - SD.rename(grid_filename, to_grid_filename); + DEBUG_PRINTLN("check"); + DEBUG_PRINTLN(from); + DEBUG_PRINTLN(to); + DEBUG_PRINTLN(grid_filename); + DEBUG_PRINTLN(to_grid_filename); + DEBUG_PRINTLN(proj_filename); + DEBUG_PRINTLN(to_proj_filename); + + for (uint8_t i = 0; i < NUM_GRIDS; i++) { + grid_filename[l] = '.'; + grid_filename[l + 1] = i + '0'; + grid_filename[l + 2] = '\0'; + + to_grid_filename[l2] = '.'; + to_grid_filename[l2 + 1] = i + '0'; + to_grid_filename[l2 + 2] = '\0'; + + DEBUG_PRINTLN("from to grid filenames"); + DEBUG_PRINTLN(grid_filename); + DEBUG_PRINTLN(to_grid_filename); + if (!SD.rename(grid_filename, to_grid_filename)) { + DEBUG_PRINTLN("Rename failed"); + goto error; } + } - SD.rename(proj_filename, to_proj_filename); + DEBUG_PRINTLN("from to project filename"); + DEBUG_PRINTLN(proj_filename); + DEBUG_PRINTLN(to_proj_filename); - _cd_up(); + if (!SD.rename(proj_filename, to_proj_filename)) { + goto error; } + SD.chdir(lwd); + DEBUG_PRINTLN("rename from to"); + DEBUG_PRINTLN(from); + DEBUG_PRINTLN(to); if (SD.rename(from, to)) { if (reload_current) { proj.load_project(to); } gfx.alert("SUCCESS", "Project renamed."); - } else { - gfx.alert("ERROR", "Not renamed."); + return true; } +error: + DEBUG_PRINTLN("error"); + gfx.alert("ERROR", "Not renamed."); } diff --git a/avr/cores/megacommand/MCL/LoadProjectPage.h b/avr/cores/megacommand/MCL/LoadProjectPage.h index 109f414f6..44b3f45b3 100644 --- a/avr/cores/megacommand/MCL/LoadProjectPage.h +++ b/avr/cores/megacommand/MCL/LoadProjectPage.h @@ -12,12 +12,13 @@ class LoadProjectPage : public FileBrowserPage { public: + const uint8_t f_len = PRJ_NAME_LEN + 5; LoadProjectPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) : FileBrowserPage(e1, e2, e3, e4) {} virtual void on_select(const char *entry); virtual void on_delete(const char *entry); - virtual void on_rename(const char *from, const char *to); + virtual void on_rename( const char *from, const char *to); virtual void setup(); virtual void init(); }; diff --git a/avr/cores/megacommand/MCL/MCL.cpp b/avr/cores/megacommand/MCL/MCL.cpp index da502f799..20368bc9d 100644 --- a/avr/cores/megacommand/MCL/MCL.cpp +++ b/avr/cores/megacommand/MCL/MCL.cpp @@ -78,8 +78,9 @@ static LightPage *const MCL::pages_table[NUM_PAGES] PROGMEM = { &midiclock_menu_page, // Index: 36 &midiroute_menu_page, // Index: 37 &midimachinedrum_menu_page,// Index: 38 - &sound_browser, // Index: 39 - &perf_page // Index: 40 + &midigeneric_menu_page, // Index: 39 + &sound_browser, // Index: 40 + &perf_page // Index: 41 }; void MCL::setup() { @@ -208,7 +209,16 @@ bool mcl_handleEvent(gui_event_t *event) { return false; } */ - + case MDX_KEY_EXTENDED: { + if (MidiClock.state == 2 && mcl.currentPage() != MIXER_PAGE) { + mixer_page.last_page = mcl.currentPage(); + mcl.setPage(MIXER_PAGE); + mixer_page.ext_key_down = 1; + mixer_page.mute_toggle = 1; + return true; + } + break; + } case MDX_KEY_BANKA: case MDX_KEY_BANKB: case MDX_KEY_BANKC: @@ -291,6 +301,9 @@ bool mcl_handleEvent(gui_event_t *event) { mcl.currentPage() == SEQ_EXTSTEP_PAGE) { opt_copy = SeqPage::recording ? 2 : 1; } + else { + opt_midi_device_capture = &MD; + } opt_copy_track_handler_cb(); break; } @@ -308,12 +321,15 @@ bool mcl_handleEvent(gui_event_t *event) { mcl.currentPage() == SEQ_EXTSTEP_PAGE) { opt_paste = SeqPage::recording ? 2 : 1; } + else { + opt_midi_device_capture = &MD; + } reset_undo(); opt_paste_track_handler(); break; } case MDX_KEY_CLEAR: { - if (mcl.currentPage() == SEQ_STEP_PAGE || mcl.currentPage() == PERF_PAGE_0) + if (mcl.currentPage() == SEQ_STEP_PAGE || mcl.currentPage() == PERF_PAGE_0 || mcl.currentPage() == SEQ_EXTSTEP_PAGE) break; if ((note_interface.notes_count_on() > 0) || (trig_interface.is_key_down(MDX_KEY_SCALE) || @@ -322,10 +338,13 @@ bool mcl_handleEvent(gui_event_t *event) { opt_clear = 2; // MidiDevice *dev = midi_active_peering.get_device(UART2_PORT); if (mcl.currentPage() == SEQ_PTC_PAGE) { opt_clear = 1; } - if (mcl.currentPage() == SEQ_EXTSTEP_PAGE) { + else if (mcl.currentPage() == SEQ_EXTSTEP_PAGE) { opt_clear = 1; if (seq_extstep_page.pianoroll_mode > 0) { opt_clear_locks_handler(); break; } } + else { + opt_midi_device_capture = &MD; + } opt_clear_track_handler(); break; } @@ -334,6 +353,7 @@ bool mcl_handleEvent(gui_event_t *event) { break; } case MDX_KEY_FUNCEXTENDED: { + trig_interface.ignoreNextEvent(MDX_KEY_EXTENDED); MD.restore_kit_params(); break; } @@ -342,24 +362,26 @@ bool mcl_handleEvent(gui_event_t *event) { if (event->mask == EVENT_BUTTON_RELEASED) { switch (key) { - - case MDX_KEY_REC: { + case MDX_KEY_REC: { if (!SeqPage::recording && (mcl.currentPage() == SEQ_PTC_PAGE || mcl.currentPage() == SEQ_EXTSTEP_PAGE)) { - if (mcl.currentPage() != SEQ_STEP_PAGE) { seq_step_page.prepare = true; seq_step_page.last_page = mcl.currentPage(); mcl.setPage(SEQ_STEP_PAGE); - } return true; } } case MDX_KEY_REALTIME: { return true; } + case MDX_KEY_FUNCEXTENDED: { + trig_interface.ignoreNextEventClear(MDX_KEY_EXTENDED); + return true; + } } } } + return false; } MCL mcl; diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index aa374a552..4a86d4256 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -16,8 +16,8 @@ #include "Fonts/Elektrothic.h" #include "Fonts/TomThumb.h" -#define VERSION 4050 -#define VERSION_STR "4.50" +#define VERSION 4051 +#define VERSION_STR "4.51" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 @@ -71,15 +71,16 @@ enum PageIndex { MIDICLOCK_MENU_PAGE, // Index: 36 MIDIROUTE_MENU_PAGE, // Index: 37 MIDIMACHINEDRUM_MENU_PAGE,// Index: 38 - SOUND_BROWSER, // Index: 39 - PERF_PAGE_0, // Index: 40 + MIDIGENERIC_MENU_PAGE, // Index: 39 + SOUND_BROWSER, // Index: 40 + PERF_PAGE_0, // Index: 41 NULL_PAGE = 255 }; class MCL { public: - static constexpr uint8_t NUM_PAGES = 41; + static constexpr uint8_t NUM_PAGES = 42; static LightPage *const pages_table[NUM_PAGES] PROGMEM; diff --git a/avr/cores/megacommand/MCL/MCLActions.cpp b/avr/cores/megacommand/MCL/MCLActions.cpp index e2fa5d292..415a64bc9 100644 --- a/avr/cores/megacommand/MCL/MCLActions.cpp +++ b/avr/cores/megacommand/MCL/MCLActions.cpp @@ -36,7 +36,6 @@ void MCLActions::setup() { send_machine[i] = 0; transition_level[i] = 0; } - memset(dev_sync_slot, 255, NUM_DEVS); } void MCLActions::init_chains() { @@ -68,9 +67,10 @@ void MCLActions::kit_reload(uint8_t pattern) { GridDeviceTrack *MCLActions::get_grid_dev_track(uint8_t slot_number) { - + if (slot_number >= GRID_WIDTH * 2) { return nullptr; } uint8_t grid_idx = 0; if (slot_number >= GRID_WIDTH) { slot_number -= GRID_WIDTH; grid_idx = 1; } + // Find first device that is hosting this slot_number. GridDeviceTrack *gdt = &proj.grids[grid_idx].tracks[slot_number]; @@ -267,7 +267,7 @@ void MCLActions::save_tracks(int row, uint8_t *slot_select_array, uint8_t merge, } void MCLActions::load_tracks(int row, uint8_t *slot_select_array, - uint8_t *_row_array, uint8_t load_mode) { + uint8_t *_row_array, uint8_t load_mode, uint8_t load_offset) { // DEBUG_PRINT_FN(); ElektronDevice *elektron_devs[2] = { midi_active_peering.get_device(UART1_PORT)->asElektronDevice(), @@ -276,17 +276,21 @@ void MCLActions::load_tracks(int row, uint8_t *slot_select_array, if (load_mode == 255) { load_mode = mcl_cfg.load_mode; } + if (load_mode != LOAD_MANUAL) { + load_offset = 255; + } uint8_t row_array[NUM_SLOTS] = {}; uint8_t cache_track_array[NUM_SLOTS] = {}; bool recache = false; DEBUG_PRINTLN("load tracks"); DEBUG_PRINTLN(load_mode); for (uint8_t n = 0; n < NUM_SLOTS; ++n) { + if (slot_select_array[n] == 0) { continue; } + GridDeviceTrack *gdt = get_grid_dev_track(n); - // DEBUG_PRINTLN(slot_select_array[n]); - if ((slot_select_array[n] == 0) || gdt == nullptr) { - continue; - } + + if (gdt == nullptr) { continue; } + if (_row_array == nullptr) { row_array[n] = row; } else { @@ -310,10 +314,12 @@ void MCLActions::load_tracks(int row, uint8_t *slot_select_array, } if (MidiClock.state == 2) { - manual_transition(slot_select_array, row_array); + manual_transition(slot_select_array, row_array, load_offset); return; } + if (load_offset != 255) { recache = false; } + for (uint8_t i = 0; i < NUM_DEVS; ++i) { if (elektron_devs[i] != nullptr && elektron_devs[i]->canReadWorkspaceKit()) { @@ -324,25 +330,33 @@ void MCLActions::load_tracks(int row, uint8_t *slot_select_array, bool gui_update = false; cache_next_tracks(cache_track_array, gui_update); } else { - send_tracks_to_devices(slot_select_array, row_array); + send_tracks_to_devices(slot_select_array, row_array, load_offset); } } void MCLActions::collect_tracks(uint8_t *slot_select_array, - uint8_t *row_array) { + uint8_t *row_array, uint8_t load_offset) { uint8_t old_grid = proj.get_grid(); - memset(dev_sync_slot, 255, NUM_DEVS); - + uint8_t first_slot = 255; for (uint8_t n = 0; n < NUM_SLOTS; ++n) { + if (slot_select_array[n] == 0) { continue; } + if (first_slot == 255) { first_slot = n; } + + uint8_t dst = load_offset == 255 ? n : (n - first_slot) + load_offset; + GridDeviceTrack *gdt = get_grid_dev_track(n); uint8_t grid_idx = get_grid_idx(n); uint8_t track_idx = get_track_idx(n); + GridDeviceTrack *gdt_dst = get_grid_dev_track(dst); + uint8_t grid_idx_dst = get_grid_idx(dst); + uint8_t track_idx_dst = get_track_idx(dst); + proj.select_grid(grid_idx); - if ((slot_select_array[n] == 0) || gdt == nullptr) { + if (gdt == nullptr || gdt_dst == nullptr || (gdt->track_type != gdt_dst->track_type)) { // Ignore slots that are not device supported. slot_select_array[n] = 0; continue; @@ -357,18 +371,19 @@ void MCLActions::collect_tracks(uint8_t *slot_select_array, if (device_track->active != EMPTY_TRACK_TYPE) { empty_track.init(); } device_track = device_track->init_track_type(gdt->track_type); if (device_track) { - device_track->init(track_idx, gdt->seq_track); + device_track->init(track_idx_dst, gdt_dst->seq_track); } - send_machine[n] = 1; + send_machine[dst] = 0; } else { if (device_track->get_parent_model() == gdt->track_type && device_track->allow_cast_to_parent()) { device_track->init_track_type(device_track->get_parent_model()); } - send_machine[n] = device_track->transition_cache(track_idx, n); - dev_sync_slot[gdt->device_idx] = n; + if (load_offset != 255) { device_track->on_copy(track_idx, track_idx_dst, false); } + device_track->transition_cache(track_idx_dst, dst); + send_machine[dst] = 1; } if (device_track) { - device_track->store_in_mem(gdt->mem_slot_idx); + device_track->store_in_mem(gdt_dst->mem_slot_idx); } } @@ -376,77 +391,81 @@ void MCLActions::collect_tracks(uint8_t *slot_select_array, } void MCLActions::manual_transition(uint8_t *slot_select_array, - uint8_t *row_array) { + uint8_t *row_array, uint8_t load_offset) { // DEBUG_PRINT_FN(); uint8_t q = get_quant(); // DEBUG_CHECK_STACK(); - collect_tracks(slot_select_array, row_array); + collect_tracks(slot_select_array, row_array, load_offset); uint16_t next_step = q == 255 ? (uint16_t) -1 : (MidiClock.div16th_counter / q) * q + q; bool increase_loops = 0; bool recalc_latency = true; - uint8_t headroom = 3; + uint8_t headroom = 0; //uint8_t headroom = ceil(MidiClock.get_tempo()* 0.133333333333f * 0.200f); ////DEBUG_PRINTLN("manual trans"); + uint8_t first_slot = 255; again: bool overflow = next_step < MidiClock.div16th_counter; uint8_t row = grid_task.next_active_row; uint16_t div16th_counter = MidiClock.div16th_counter; + for (uint8_t n = 0; n < NUM_SLOTS; n++) { - if (slot_select_array[n] > 0) { + if (slot_select_array[n] == 0) { continue; } + + if (first_slot == 255) { first_slot = n; } + + uint8_t dst = load_offset == 255 ? n : (n - first_slot) + load_offset; row = row_array[n]; if (q == 255) { - GridDeviceTrack *gdt = get_grid_dev_track(n); - if (gdt != nullptr) { - transition_level[n] = 0; + + GridDeviceTrack *gdt_dst = get_grid_dev_track(dst); + + if (gdt_dst != nullptr) { + transition_level[dst] = 0; if (increase_loops) { - if (next_transitions[n] == next_transition) { + if (next_transitions[dst] == next_transition) { DEBUG_PRINTLN("increasing loops"); - links[n].loops++; + links[dst].loops++; } } else { - links[n].loops = 1; + links[dst].loops = 1; } - links[n].speed = gdt->seq_track->speed; - links[n].length = gdt->seq_track->length; - links[n].row = row; + links[dst].speed = gdt_dst->seq_track->speed; + links[dst].length = gdt_dst->seq_track->length; + links[dst].row = row; - next_transitions[n] = MidiClock.div16th_counter - ((float)gdt->seq_track->step_count * - gdt->seq_track->get_speed_multiplier() + (gdt->seq_track->mod12_counter / 12) ); + next_transitions[dst] = MidiClock.div16th_counter - ((float)gdt_dst->seq_track->step_count * + gdt_dst->seq_track->get_speed_multiplier() + (gdt_dst->seq_track->mod12_counter / 12) ); bool ignore_chain_settings = true; bool ignore_overflow = true; - calc_next_slot_transition(n, ignore_chain_settings, ignore_overflow); + calc_next_slot_transition(dst, ignore_chain_settings, ignore_overflow); - if (MidiClock.clock_less_than(next_transitions[n], next_step)) { - next_step = next_transitions[n]; + if (MidiClock.clock_less_than(next_transitions[dst], next_step)) { + next_step = next_transitions[dst]; } - grid_page.active_slots[n] = SLOT_PENDING; } } else { // transition_level[n] = gridio_param3.getValue(); - transition_level[n] = 0; - next_transitions[n] = next_step; - links[n].row = row; - links[n].loops = 1; + transition_level[dst] = 0; + next_transitions[dst] = next_step; + links[dst].row = row; + links[dst].loops = 1; // if (grid_page.active_slots[n] < 0) { DEBUG_PRINT("slot man trans "); - DEBUG_PRINT(n); + DEBUG_PRINT(dst); DEBUG_PRINT(" "); - DEBUG_PRINTLN(next_transitions[n]); - grid_page.active_slots[n] = SLOT_PENDING; + DEBUG_PRINTLN(next_transitions[dst]); // } } - } else { - // calc_next_slot_transition(n); - } + grid_page.active_slots[dst] = load_offset == 255 ? SLOT_PENDING : SLOT_OFFSET_LOAD; } calc_next_transition(); @@ -478,8 +497,8 @@ void MCLActions::manual_transition(uint8_t *slot_select_array, } uint32_t next_32th = next_16th * 2; - if (next_32th - (div192th_total_latency / 6) - headroom < - (uint32_t)MidiClock.div16th_counter * 2) { + if (next_32th - (div192th_total_latency / 6) - headroom <= + (uint32_t)MidiClock.div32th_counter) { if (q == 255) { increase_loops = 1; @@ -493,8 +512,10 @@ void MCLActions::manual_transition(uint8_t *slot_select_array, } } -bool MCLActions::load_track(uint8_t track_idx, uint8_t row, uint8_t pos, - GridDeviceTrack *gdt, uint8_t *send_masks) { +bool MCLActions::load_track_immediate(uint8_t row, uint8_t i, uint8_t dst, + GridDeviceTrack *gdt, GridDeviceTrack *gdt_dst, uint8_t *send_masks) { + uint8_t track_idx = get_track_idx(i); + uint8_t track_idx_dst = get_track_idx(dst); EmptyTrack empty_track; auto *ptrack = empty_track.load_from_grid_512(track_idx, row); @@ -503,32 +524,33 @@ bool MCLActions::load_track(uint8_t track_idx, uint8_t row, uint8_t pos, return false; } // read failure - ptrack->link.store_in_mem(pos, &(links[0])); + ptrack->link.store_in_mem(dst, &(links[0])); if (ptrack->active != gdt->track_type && ptrack->get_parent_model() != gdt->track_type) { empty_track.clear(); if (ptrack->active != EMPTY_TRACK_TYPE) { empty_track.init(); } ptrack->init_track_type(gdt->track_type); - ptrack->init(track_idx, gdt->seq_track); - ptrack->load_immediate_cleared(track_idx, gdt->seq_track); + ptrack->init(track_idx_dst, gdt_dst->seq_track); + ptrack->load_immediate_cleared(dst, gdt_dst->seq_track); } else { if (ptrack->get_parent_model() == gdt->track_type && ptrack->allow_cast_to_parent()) { ptrack->init_track_type(ptrack->get_parent_model()); } if (ptrack != nullptr) { - send_masks[pos] = 1; - ptrack->load_immediate(track_idx, gdt->seq_track); + send_masks[dst] = 1; + if (i != dst) { ptrack->on_copy(track_idx, track_idx_dst, false); } + ptrack->load_immediate(track_idx_dst, gdt_dst->seq_track); } } if (ptrack != nullptr) { - ptrack->store_in_mem(gdt->mem_slot_idx); + ptrack->store_in_mem(gdt_dst->mem_slot_idx); } return true; } void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, - uint8_t *row_array) { + uint8_t *row_array, uint8_t load_offset) { // DEBUG_PRINT_FN(); DEBUG_PRINTLN("send tracks to devices"); @@ -551,38 +573,39 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, // DEBUG_CHECK_STACK(); uint8_t last_slot = 255; + uint8_t first_slot = 255; for (uint8_t i = 0; i < NUM_SLOTS; i++) { + + if (select_array[i] == 0) { continue; } + + if (first_slot == 255) { first_slot = i; } + GridDeviceTrack *gdt = get_grid_dev_track(i); uint8_t grid_idx = get_grid_idx(i); - uint8_t track_idx = get_track_idx(i); - proj.select_grid(grid_idx); + uint8_t dst = load_offset == 255 ? i : (i - first_slot) + load_offset; + GridDeviceTrack *gdt_dst = get_grid_dev_track(dst); + uint8_t grid_idx_dst = get_grid_idx(dst); - if (gdt == nullptr) { - goto cont; - } + if (gdt == nullptr || gdt_dst == nullptr || (gdt->track_type != gdt_dst->track_type)) { select_array[i] = 0; continue; } - mute_states[i] = gdt->seq_track->mute_state; - gdt->seq_track->mute_state = SEQ_MUTE_ON; + proj.select_grid(grid_idx); - if ((select_array[i] == 0)) { - cont: - select_array[i] = 0; - continue; - } + mute_states[dst] = gdt_dst->seq_track->mute_state; + gdt_dst->seq_track->mute_state = SEQ_MUTE_ON; - row = grid_page.getRow(); + row = grid_page.getRow(); if (row_array) { row = row_array[i]; } - last_slot = i; + last_slot = dst; - grid_page.active_slots[i] = row; + grid_page.active_slots[dst] = load_offset == 255 ? row : SLOT_OFFSET_LOAD; // DEBUG_DUMP("here"); // DEBUG_DUMP(row); - if (!load_track(track_idx, row, i, gdt, send_masks)) { + if (!load_track_immediate(row, i, dst, gdt, gdt_dst, send_masks)) { select_array[i] = 0; } } @@ -629,9 +652,11 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, } GUI.addTask(&grid_task); for (uint8_t i = 0; i < NUM_SLOTS; ++i) { - GridDeviceTrack *gdt = get_grid_dev_track(i); - if (gdt != nullptr) { - gdt->seq_track->mute_state = mute_states[i]; + if (select_array[i] == 0) { continue; } + uint8_t dst = load_offset == 255 ? i : (i - first_slot) + load_offset; + GridDeviceTrack *gdt_dst = get_grid_dev_track(dst); + if (gdt_dst != nullptr) { + gdt_dst->seq_track->mute_state = mute_states[dst]; } } /*All the tracks have been sent so clear the write queue*/ @@ -644,23 +669,26 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, // Cache // DEBUG_CHECK_STACK(); + + if (load_offset == 255) { bool gui_update = false; cache_next_tracks(select_array, gui_update); // in_sysex = 0; - for (uint8_t n = 0; n < NUM_SLOTS; n++) { - if ((select_array[n] > 0) && (grid_page.active_slots[n] != SLOT_DISABLED)) { - GridDeviceTrack *gdt = get_grid_dev_track(n); - if (gdt != nullptr) { - transition_level[n] = 0; - next_transitions[n] = MidiClock.div16th_counter - - (gdt->seq_track->step_count * - gdt->seq_track->get_speed_multiplier()); - calc_next_slot_transition(n); - } + for (uint8_t n = 0; n < NUM_SLOTS; n++) { + if ((select_array[n] == 0) || (grid_page.active_slots[n] == SLOT_DISABLED)) { continue; } + GridDeviceTrack *gdt = get_grid_dev_track(n); + if (gdt != nullptr) { + transition_level[n] = 0; + next_transitions[n] = MidiClock.div16th_counter - + (gdt->seq_track->step_count * + gdt->seq_track->get_speed_multiplier()); + calc_next_slot_transition(n); + } } } + grid_task.last_active_row = row; grid_task.next_active_row = row; grid_task.chain_behaviour = false; @@ -676,14 +704,11 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, calc_latency(); } - void MCLActions::cache_next_tracks(uint8_t *slot_select_array, bool gui_update) { uint8_t old_grid = proj.get_grid(); - memset(dev_sync_slot, 255, sizeof(dev_sync_slot)); - const uint8_t div32th_margin = 1; uint32_t diff = 0; @@ -711,6 +736,8 @@ void MCLActions::cache_next_tracks(uint8_t *slot_select_array, if (gdt == nullptr) continue; + //Assumes next transisiton is only 4 steps away + // uint32_t diff = MidiClock.clock_diff_div192( MidiClock.div192th_counter, (uint32_t)next_transition * 12 + 4 * 12); @@ -749,7 +776,7 @@ void MCLActions::cache_next_tracks(uint8_t *slot_select_array, EmptyTrack empty_track; auto *ptrack = empty_track.load_from_grid_512(track_idx, links[n].row); - send_machine[n] = 1; + send_machine[n] = 0; if (ptrack == nullptr || ptrack->active != gdt->track_type && ptrack->get_parent_model() != gdt->track_type) { // EMPTY_TRACK_TYPE @@ -763,10 +790,11 @@ void MCLActions::cache_next_tracks(uint8_t *slot_select_array, ptrack->init_track_type(ptrack->get_parent_model()); } if (ptrack->get_sound_data_ptr() && ptrack->get_sound_data_size()) { + DEBUG_PRINTLN("comparing sound"); if (ptrack->memcmp_sound(gdt->mem_slot_idx) != 0) { + DEBUG_PRINTLN("no match"); ptrack->transition_cache(track_idx, n); - send_machine[n] = 0; - dev_sync_slot[gdt->device_idx] = n; + send_machine[n] = 1; } } } @@ -891,11 +919,6 @@ void MCLActions::calc_latency() { dev_latency[a].latency = 0; dev_latency[a].div32th_latency = 0; dev_latency[a].div192th_latency = 0; - - if (dev_sync_slot[a] != 255) { - dev_latency[a].latency += 2 + 7; - } - // dev_latency[a].load_latency = 0; } bool send_dev[NUM_DEVS] = {0}; @@ -913,8 +936,9 @@ void MCLActions::calc_latency() { if (gdt == nullptr) { continue; } + uint8_t device_idx = gdt->device_idx; - if (send_machine[n] == 0) { + if (send_machine[n] == 1) { // Optimised, assume we dont need to read the entire object to calculate // latency. auto *ptrack = empty_track.load_from_mem( @@ -949,28 +973,39 @@ void MCLActions::calc_latency() { for (uint8_t a = 0; a < NUM_DEVS; a++) { if (send_dev[a]) { float bytes_per_second_uart1 = devs[a]->uart->speed * 0.1f; - float latency_in_seconds = (float)dev_latency[a].latency / - bytes_per_second_uart1; // 25ms minimum. - if (num_devices == 1) { - latency_in_seconds += .10; - } else if (a == 1) { - latency_in_seconds += .20; - } + float latency_in_seconds = (float)dev_latency[a].latency/ + bytes_per_second_uart1; + // latency_in_seconds = max(.010,latency_in_seconds); - // latency_in_seconds += (float) dev_latency[a].load_latency * .0002; + DEBUG_PRINT("Bytes: "); + DEBUG_PRINTLN(dev_latency[a].latency); + DEBUG_PRINT("Lat: "); + DEBUG_PRINTLN(latency_in_seconds); - dev_latency[a].div32th_latency = - ceil(div32th_per_second * latency_in_seconds); - dev_latency[a].div192th_latency = - ceil(div192th_per_second * latency_in_seconds); + //latency_in_seconds += 0.020; //16ms additional latency per device + // latency_in_seconds += (float) dev_latency[a].load_latency * .0002; + //Transimission Latency + // + dev_latency[a].div32th_latency = ceil(div32th_per_second * latency_in_seconds); + dev_latency[a].div192th_latency = ceil(div192th_per_second * latency_in_seconds); + + //Load Latency + //We need at least 6 sequencer ticks of latency to account for seq_track load_cache() functions + //which are splayed over count_down duration + //if (a == 0) { + dev_latency[a].div32th_latency = max(1, dev_latency[a].div32th_latency); + dev_latency[a].div192th_latency = max(6, dev_latency[a].div192th_latency); + // } // Program change minimum delay = 1 x 16th. + /* if (mcl_cfg.uart2_prg_out > 0 && a == 1) { if (dev_latency[a].div32th_latency < 2) { dev_latency[a].div32th_latency = 2; dev_latency[a].div192th_latency = 12; } } + */ div32th_total_latency += dev_latency[a].div32th_latency; div192th_total_latency += dev_latency[a].div192th_latency; diff --git a/avr/cores/megacommand/MCL/MCLActions.h b/avr/cores/megacommand/MCL/MCLActions.h index e2df415ed..658864cf4 100644 --- a/avr/cores/megacommand/MCL/MCLActions.h +++ b/avr/cores/megacommand/MCL/MCLActions.h @@ -107,10 +107,10 @@ class MCLActions : public LinkModeData { uint8_t readpattern = 255); void load_tracks(int row, uint8_t *slot_select_array, - uint8_t *_row_array = nullptr, uint8_t load_mode = 255); + uint8_t *_row_array = nullptr, uint8_t load_mode = 255, uint8_t load_offset = 255); void send_tracks_to_devices(uint8_t *slot_select_array, - uint8_t *row_array = nullptr); - void manual_transition(uint8_t *slot_select_array, uint8_t *row_array); + uint8_t *row_array = nullptr, uint8_t load_offset = 0); + void manual_transition(uint8_t *slot_select_array, uint8_t *row_array, uint8_t load_offset); void cache_next_tracks(uint8_t *slot_select_array, bool gui_update = false); void calc_next_slot_transition(uint8_t n, bool ignore_chain_settings = false, @@ -119,11 +119,11 @@ class MCLActions : public LinkModeData { void calc_latency(); private: - void collect_tracks(uint8_t *slot_select_array, uint8_t *row_array); + void collect_tracks(uint8_t *slot_select_array, uint8_t *row_array, uint8_t load_offset); void cache_track(uint8_t n, uint8_t track_idx, uint8_t dev_idx, GridDeviceTrack *gdt); - bool load_track(uint8_t track_idx, uint8_t row, uint8_t pos, - GridDeviceTrack *gdt, uint8_t *send_masks); + bool load_track_immediate(uint8_t row, uint8_t i, uint8_t dst, + GridDeviceTrack *gdt, GridDeviceTrack *gdt_dst, uint8_t *send_masks); }; extern void md_import(); diff --git a/avr/cores/megacommand/MCL/MCLClipBoard.cpp b/avr/cores/megacommand/MCL/MCLClipBoard.cpp index f34ece62b..8a8457185 100644 --- a/avr/cores/megacommand/MCL/MCLClipBoard.cpp +++ b/avr/cores/megacommand/MCL/MCLClipBoard.cpp @@ -215,7 +215,7 @@ bool MCLClipBoard::copy(uint8_t col, uint16_t row, uint8_t w, uint16_t h) { if (h > 4) { mcl_gui.draw_progress("", y, h); } - for (int x = 0; x < w; x++) { + for (uint8_t x = 0; x < w; x++) { uint8_t s_col = x + col; if (x + col >= 16) { s_col -= 16; grid = 1; } proj.select_grid(grid); @@ -273,7 +273,7 @@ bool MCLClipBoard::paste(uint8_t col, uint16_t row) { if (t_h > 8) { mcl_gui.draw_progress("", y, t_h); } - for (int x = 0; x < t_w && x + col < GRID_WIDTH * 2; x++) { + for (uint8_t x = 0; x < t_w && x + col < GRID_WIDTH * 2; x++) { uint8_t s_col = x + t_col; uint8_t d_col = x + col; diff --git a/avr/cores/megacommand/MCL/MCLGUI.cpp b/avr/cores/megacommand/MCL/MCLGUI.cpp index 449e28a5d..a4e7bfd47 100644 --- a/avr/cores/megacommand/MCL/MCLGUI.cpp +++ b/avr/cores/megacommand/MCL/MCLGUI.cpp @@ -360,7 +360,7 @@ bool MCLGUI::show_encoder_value(Encoder *encoder, int timeout) { } void MCLGUI::draw_text_encoder(uint8_t x, uint8_t y, const char *name, - const char *value) { + const char *value, bool highlight) { oled_display.setFont(&TomThumb); oled_display.setTextColor(WHITE); oled_display.setCursor(x + 4, y + 6); @@ -369,6 +369,8 @@ void MCLGUI::draw_text_encoder(uint8_t x, uint8_t y, const char *name, oled_display.setFont(); oled_display.setCursor(x + 4, y + 8); oled_display.print(value); + + if (highlight) { oled_display.fillRect(x,y,23,16, INVERT); } } void MCLGUI::draw_md_encoder(uint8_t x, uint8_t y, Encoder *encoder, @@ -455,7 +457,7 @@ void MCLGUI::draw_light_encoder(uint8_t x, uint8_t y, uint8_t value, y += 2; draw_encoder(x, y, value); - if (highlight) { oled_display.fillRect(x - 2, 0, 15,20,INVERT); } + if (highlight) { oled_display.fillRect(x - 2, 0, 16,20,INVERT); } oled_display.setFont(oldfont); } diff --git a/avr/cores/megacommand/MCL/MCLGUI.h b/avr/cores/megacommand/MCL/MCLGUI.h index 310be7c42..cc1a84791 100644 --- a/avr/cores/megacommand/MCL/MCLGUI.h +++ b/avr/cores/megacommand/MCL/MCLGUI.h @@ -71,7 +71,7 @@ class MCLGUI { bool show_encoder_value(Encoder *encoder, int timeout = SHOW_VALUE_TIMEOUT); void draw_text_encoder(uint8_t x, uint8_t y, const char *name, - const char *value); + const char *value, bool highlight = false); void draw_md_encoder(uint8_t x, uint8_t y, Encoder *encoder, const char *name); void draw_md_encoder(uint8_t x, uint8_t y, uint8_t value, const char *name, diff --git a/avr/cores/megacommand/MCL/MCLMenus.cpp b/avr/cores/megacommand/MCL/MCLMenus.cpp index 442cf6b83..870fd74c4 100644 --- a/avr/cores/megacommand/MCL/MCLMenus.cpp +++ b/avr/cores/megacommand/MCL/MCLMenus.cpp @@ -20,6 +20,7 @@ MCLEncoder config_param10(0, 17, ENCODER_RES_SYS); MCLEncoder config_param11(0, 17, ENCODER_RES_SYS); MCLEncoder config_param12(0, 17, ENCODER_RES_SYS); MCLEncoder config_param13(0, 17, ENCODER_RES_SYS); +MCLEncoder config_param14(0, 17, ENCODER_RES_SYS); uint8_t opt_import_src = 0; @@ -35,7 +36,7 @@ const uint8_t *const menu_target_param[] PROGMEM = { &mcl_cfg.ram_page_mode, // 2 - &mcl_cfg.uart1_turbo, &mcl_cfg.uart2_turbo, &mcl_cfg.uart2_device, + &mcl_cfg.uart1_turbo_speed, &mcl_cfg.uart2_turbo_speed, &mcl_cfg.uart2_device, &mcl_cfg.clock_rec, &mcl_cfg.clock_send, &mcl_cfg.midi_forward_1, // 8 @@ -90,7 +91,7 @@ const uint8_t *const menu_target_param[] PROGMEM = { // 54 &mcl_cfg.midi_transport_send, // 55 - &mcl_cfg.usb_turbo, + &mcl_cfg.usb_turbo_speed, // 56 &mcl_cfg.midi_ctrl_port, // 57 @@ -99,6 +100,8 @@ const uint8_t *const menu_target_param[] PROGMEM = { &perf_page.page_mode, // 59 &perf_page.perf_id, + // 60 + &mcl_cfg.uart2_cc_mute, }; const menu_function_t menu_target_functions[] PROGMEM = { @@ -176,6 +179,7 @@ MenuPage midiprogram_menu_page(&config_param1, &config_ MenuPage midiclock_menu_page(&config_param1, &config_param11); MenuPage midiroute_menu_page(&config_param1, &config_param12); MenuPage midimachinedrum_menu_page(&config_param1, &config_param13); +MenuPage midigeneric_menu_page(&config_param1, &config_param14); MCLEncoder input_encoder1(0, 127, ENCODER_RES_SYS); MCLEncoder input_encoder2(0, 127, ENCODER_RES_SYS); diff --git a/avr/cores/megacommand/MCL/MCLMenus.h b/avr/cores/megacommand/MCL/MCLMenus.h index fc25de8cb..5c62ae2df 100644 --- a/avr/cores/megacommand/MCL/MCLMenus.h +++ b/avr/cores/megacommand/MCL/MCLMenus.h @@ -30,6 +30,7 @@ extern MCLEncoder config_param10; extern MCLEncoder config_param11; extern MCLEncoder config_param12; extern MCLEncoder config_param13; +extern MCLEncoder config_param14; extern void new_proj_handler(); @@ -42,7 +43,7 @@ extern MenuPage start_menu_page; constexpr size_t system_menu_page_N = 6; extern MenuPage system_page; -constexpr size_t midi_config_page_N = 5; +constexpr size_t midi_config_page_N = 6; extern MenuPage midi_config_page; constexpr size_t md_config_page_N = 2; @@ -78,6 +79,9 @@ extern MenuPage midiroute_menu_page; constexpr size_t midimachinedrum_menu_page_N = 3; extern MenuPage midimachinedrum_menu_page; +constexpr size_t midigeneric_menu_page_N = 1; +extern MenuPage midigeneric_menu_page; + extern MCLEncoder input_encoder1; extern MCLEncoder input_encoder2; @@ -85,7 +89,7 @@ extern TextInputPage text_input_page; extern MCLEncoder file_menu_encoder; -constexpr size_t file_menu_page_N = 7; +constexpr size_t file_menu_page_N = 6; extern MenuPage file_menu_page; extern MCLEncoder seq_menu_value_encoder; diff --git a/avr/cores/megacommand/MCL/MCLSd.cpp b/avr/cores/megacommand/MCL/MCLSd.cpp index e705f9326..3f0505798 100644 --- a/avr/cores/megacommand/MCL/MCLSd.cpp +++ b/avr/cores/megacommand/MCL/MCLSd.cpp @@ -94,91 +94,69 @@ bool MCLSd::load_init() { } bool MCLSd::seek(uint32_t pos, File *filep) { - bool pass = false; bool ret; - for (uint8_t n = 0; n < SD_MAX_RETRIES; n++) { + uint8_t n = 0; + if (!filep) { + DEBUG_PRINTLN(F("huh")); + return false; + } + + do { DEBUG_CHECK_STACK(); - if (!filep) { DEBUG_PRINTLN(F("huh")); } ret = filep->seekSet(pos); - if (!ret) { - //SD.cardBegin(SD_CS, SPI_FULL_SPEED); - //oled_display.textbox("SEEK RETRY", ""); - //oled_display.display(); - DEBUG_PRINTLN("seek retry"); - DEBUG_PRINTLN(pos); - delay(20); - continue; + if (ret) { + return true; } - pass = true; - break; - } - return pass; + DEBUG_PRINTLN("seek retry"); + DEBUG_PRINTLN(pos); + delay(20); + n++; + } while (n < SD_MAX_RETRIES); + + return false; } bool MCLSd::write_data(void *data, size_t len, File *filep) { - - size_t b; - bool pass = false; bool ret; uint32_t pos = filep->curPosition(); + uint8_t n = 0; - for (uint8_t n = 0; n < SD_MAX_RETRIES; n++) { - if (n > 0) { - DEBUG_PRINTLN("write retry"); - //SD.cardBegin(SD_CS, SPI_FULL_SPEED); - //oled_display.textbox("WRITE RETRY", ""); - //oled_display.display(); - delay(20); - } - if (pos != filep->curPosition()) { - ret = filep->seekSet(pos); - if (!ret) - continue; - } - b = filep->write((uint8_t *)data, len); - if (b != len) { - write_fail++; - continue; + do { + size_t b = filep->write((uint8_t *)data, len); + if (b == len) { + return true; } - pass = true; - break; - } + DEBUG_PRINTLN("write retry"); + delay(20); + write_fail++; + ret = filep->seekSet(pos); + n++; + } while (n < SD_MAX_RETRIES); - return pass; + return false; } + /* Function for reading from the project file */ bool MCLSd::read_data(void *data, size_t len, File *filep) { - - size_t b; bool ret; uint32_t pos = filep->curPosition(); + uint8_t n = 0; - bool pass = false; - for (uint8_t n = 0; n < SD_MAX_RETRIES; n++) { - if (n > 0) { - DEBUG_PRINTLN("read retry"); - //SD.cardBegin(SD_CS, SPI_FULL_SPEED); - //oled_display.textbox("READ RETRY", ""); - //oled_display.display(); - delay(20); - } - if (pos != filep->curPosition()) { - ret = filep->seekSet(pos); - if (!ret) - continue; - } - b = filep->read((uint8_t *)data, len); - if (b != len) { - read_fail++; - continue; + do { + size_t b = filep->read((uint8_t *)data, len); + if (b == len) { + return true; } - pass = true; - break; - } + DEBUG_PRINTLN("read retry"); + delay(20); + read_fail++; + ret = filep->seekSet(pos); + n++; + } while (n < SD_MAX_RETRIES); - return pass; + return false; } MCLSd mcl_sd; diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index a1abed7ce..723429206 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -83,6 +83,7 @@ uint8_t MCLSeq::find_ext_track(uint8_t channel) { void MCLSeq::onMidiContinueCallback() { update_params(); seq_rec_play(); + SET_BIT16(MDSeqTrack::gui_update, last_md_track); //force cursor resync } void MCLSeq::onMidiStartImmediateCallback() { @@ -146,12 +147,17 @@ void MCLSeq::onMidiStopCallback() { MD.reset_dsp_params(); for (uint8_t i = 0; i < num_md_tracks; i++) { + md_tracks[i].reset_params(); md_tracks[i].locks_slides_recalc = 255; for (uint8_t c = 0; c < NUM_LOCKS; c++) { md_tracks[i].locks_slide_data[c].init(); } } #ifdef LFO_TRACKS + for (uint8_t i = 0; i < num_lfo_tracks; i++) { + lfo_tracks[i].reset_params(); + } + #endif } @@ -296,6 +302,7 @@ void MCLSeqMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { if (mcl.currentPage() == MIXER_PAGE) { mixer_page.onControlChangeCallback_Midi(track, track_param, value); } + ram_page_a.onControlChangeCallback_Midi(track, track_param, value); if (track_param == 32) { // Mute mcl_seq.md_tracks[track].mute_state = value > 0; @@ -326,7 +333,7 @@ void MCLSeqMidiEvents::onControlChangeCallback_Midi2(uint8_t *msg) { uint8_t value = msg[2]; if (param == midi_active_peering.get_device(UART2_PORT)->get_mute_cc()) { - for (uint8_t n = 0; n < NUM_EXT_TRACKS; n++) { + for (uint8_t n = 0; n < NUM_EXT_TRACKS; n++) { if (mcl_seq.ext_tracks[n].channel != channel) { continue; } @@ -343,6 +350,7 @@ void MCLSeqMidiEvents::onControlChangeCallback_Midi2(uint8_t *msg) { mixer_page.mute_sets[1].mutes[mixer_page.current_mute_set], n); } } + mixer_page.redraw_mutes = true; return; } diff --git a/avr/cores/megacommand/MCL/MCLSysConfig.cpp b/avr/cores/megacommand/MCL/MCLSysConfig.cpp index 0564bbd4c..bb03de681 100644 --- a/avr/cores/megacommand/MCL/MCLSysConfig.cpp +++ b/avr/cores/megacommand/MCL/MCLSysConfig.cpp @@ -107,50 +107,54 @@ bool MCLSysConfig::cfg_init() { char my_string[16] = "/project000.mcl"; + memset((uint8_t *)&version, 0, sizeof(MCLSysConfigData)); //<---- flush zero to config + version = CONFIG_VERSION; - number_projects = 0; + //number_projects = 0; strncpy(project, my_string, 16); - clock_send = 0; - clock_rec = 0; - uart1_turbo = 3; - uart2_turbo = 3; - usb_turbo = 3; - col = 0; - row = 0; - cur_row = 0; - cur_col = 0; + //clock_send = 0; + //clock_rec = 0; + uart1_turbo_speed = 3; + //uart2_turbo_speed = 0; + usb_turbo_speed = 3; + //col = 0; + //row = 0; + //cur_row = 0; + //cur_col = 0; memset(&routing, 6, sizeof(routing)); - poly_mask = 0; + //poly_mask = 0; uart2_ctrl_chan = MIDI_LOCAL_MODE; uart2_poly_chan = MIDI_LOCAL_MODE; uart2_prg_in = MIDI_LOCAL_MODE; uart2_prg_out = MIDI_LOCAL_MODE; - mutes = 0; - display_mirror = 0; - rec_quant = 0; + //mutes = 0; + //display_mirror = 0; + //rec_quant = 0; tempo = 125; - midi_forward_1 = 0; - midi_forward_2 = 0; - midi_forward_usb = 0; + //midi_forward_1 = 0; + //midi_forward_2 = 0; + //midi_forward_usb = 0; rec_automation = 1; auto_normalize = 1; load_mode = LOAD_MANUAL; chain_queue_length = 1; chain_load_quant = 16; - ram_page_mode = 0; + //ram_page_mode = 0; track_select = 1; track_type_select = 0b00000011; - uart2_device = 0; - uart_cc_loopback = 0; - uart2_prg_mode = 0; + //uart2_device = 0; + //uart_cc_loopback = 0; + //uart2_prg_mode = 0; usb_mode = USB_SERIAL; - midi_transport_rec = 0; - midi_transport_send = 0; + //midi_transport_rec = 0; + //midi_transport_send = 0; midi_ctrl_port = 1; - md_trig_channel = 0; - seq_dev = 0; + //md_trig_channel = 0; + //seq_dev = 0; + uart2_cc_mute = 128; + uart2_cc_level = 128; cfgfile.close(); ret = write_cfg(); if (!ret) { diff --git a/avr/cores/megacommand/MCL/MCLSysConfig.h b/avr/cores/megacommand/MCL/MCLSysConfig.h index 3c785099f..65ab7e1a0 100644 --- a/avr/cores/megacommand/MCL/MCLSysConfig.h +++ b/avr/cores/megacommand/MCL/MCLSysConfig.h @@ -4,7 +4,7 @@ #define MCLSYSCONFIG_H__ #include "SdFat.h" -#define CONFIG_VERSION 4007 +#define CONFIG_VERSION 4010 #define MIDI_OMNI_MODE 17 #define MIDI_LOCAL_MODE 0 @@ -22,9 +22,9 @@ class MCLSysConfigData { uint32_t version; char project[16]; uint8_t number_projects; - uint8_t uart1_turbo; - uint8_t uart2_turbo; - uint8_t usb_turbo; + uint8_t uart1_turbo_speed; + uint8_t uart2_turbo_speed; + uint8_t usb_turbo_speed; uint8_t clock_send; uint8_t clock_rec; uint8_t drumRouting[16]; @@ -65,6 +65,8 @@ class MCLSysConfigData { uint8_t midi_ctrl_port; uint8_t md_trig_channel; uint8_t seq_dev; + uint8_t uart2_cc_mute; + uint8_t uart2_cc_level; }; class MCLSysConfig : public MCLSysConfigData { diff --git a/avr/cores/megacommand/MCL/MDFXSeqTrack.h b/avr/cores/megacommand/MCL/MDFXSeqTrack.h index 363c07eb6..3c549f677 100644 --- a/avr/cores/megacommand/MCL/MDFXSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDFXSeqTrack.h @@ -23,7 +23,10 @@ class MDFXSeqTrack : public SeqTrackBase { if (count_down) { count_down--; if (count_down == 0) { - MDSeqTrack::load_machine_cache |= ((uint32_t) 0b1111 << 16); + if (load_sound) { + MDSeqTrack::load_machine_cache |= ((uint32_t) 0b1111 << 16); + load_sound = 0; + } reset(); mod12_counter = 0; } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index c673d4d21..fe8348c1d 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -88,10 +88,12 @@ void MDSeqTrack::load_cache() { MDTrack t; t.load_from_mem(track_number, MD_TRACK_TYPE); - MD.insertMachineInKit(track_number, &(t.machine),false); t.load_seq_data((SeqTrack *)this); - - SET_BIT32(load_machine_cache, track_number); + if (load_sound) { + MD.insertMachineInKit(track_number, &(t.machine),false); + SET_BIT32(load_machine_cache, track_number); + load_sound = 0; + } } void MDSeqTrack::seq(MidiUartParent *uart_) { @@ -112,16 +114,16 @@ void MDSeqTrack::seq(MidiUartParent *uart_) { } if (count_down) { count_down--; - if (count_down == track_number / 4 + 1) { - load_cache(); - goto end; - } if (count_down == 0) { reset(); mod12_counter = 0; SET_BIT16(gui_update,track_number); } - else if (count_down < track_number / 4 + 1) { + else if (count_down <= track_number / 4 + 1) { + if (!cache_loaded) { + load_cache(); + cache_loaded = true; + } goto end; } } @@ -376,22 +378,47 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, bool lock_present = steps[step].is_lock(c); bool send = false; uint8_t send_param; + uint8_t p = locks_params[c] - 1; if (locks_params[c]) { if (lock_present) { send_param = locks[lock_idx]; send = true; } else if (trig) { - send_param = MD.kit.params[track_number][locks_params[c] - 1]; + send_param = MD.kit.params[track_number][p]; send = true; } } lock_idx += lock_bit; if (send) { + bool update_kit = false; + MD.setTrackParam_inline(track_number, p, send_param, uart, update_kit); + } + } +} + +void MDSeqTrack::reset_params() { + bool re_assign = false; + for (uint8_t c = 0; c < NUM_LOCKS; c++) { + if (locks_params[c] > 0) { + MDTrack md_track; + md_track.get_machine_from_kit(track_number); + MD.assignMachineBulk(track_number, &md_track.machine, 255, 1, true); + return; + } + } + + /* + for (uint8_t c = 0; c < NUM_LOCKS; c++) { + bool send = false; + uint8_t send_param; + if (locks_params[c]) { uint8_t p = locks_params[c] - 1; + uint8_t send_param = MD.kit.params[track_number][p]; bool update_kit = false; MD.setTrackParam_inline(track_number, p, send_param, uart, update_kit); - } + } } +*/ } void MDSeqTrack::get_step_locks(uint8_t step, uint8_t *params, @@ -414,11 +441,7 @@ void MDSeqTrack::get_step_locks(uint8_t step, uint8_t *params, void MDSeqTrack::send_trig() { send_trig_inline(); } void MDSeqTrack::send_trig_inline() { - mixer_page.disp_levels[track_number] = MD.kit.levels[track_number]; - if (MD.kit.trigGroups[track_number] < 16) { - mixer_page.disp_levels[MD.kit.trigGroups[track_number]] = - MD.kit.levels[MD.kit.trigGroups[track_number]]; - } + mixer_page.trig(track_number); // MD.triggerTrack(track_number, 127, uart); SET_BIT16(MDSeqTrack::md_trig_mask, track_number); } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 236b2d411..c9ce470f1 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -49,6 +49,7 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { uint8_t trig_conditional(uint8_t condition); void send_parameter_locks(uint8_t step, bool trig, uint16_t lock_idx = 0xFFFF); void send_parameter_locks_inline(uint8_t step, bool trig, uint16_t lock_idx); + void reset_params(); void get_step_locks(uint8_t step, uint8_t *params, bool ignore_locks_disabled = false); void recalc_slides(); diff --git a/avr/cores/megacommand/MCL/MDTrack.h b/avr/cores/megacommand/MCL/MDTrack.h index b7ea5ab3a..7817483eb 100644 --- a/avr/cores/megacommand/MCL/MDTrack.h +++ b/avr/cores/megacommand/MCL/MDTrack.h @@ -137,6 +137,7 @@ class MDTrack : public DeviceTrack { virtual void *get_sound_data_ptr() { return &machine; } virtual size_t get_sound_data_size() { return sizeof(MDMachine); } + virtual size_t get_sound_cmp_size() { return 27; } //params,track,level,model }; class MDTrackChunk : public DeviceTrackChunk { diff --git a/avr/cores/megacommand/MCL/MenuPage.cpp b/avr/cores/megacommand/MCL/MenuPage.cpp index fc49906fc..0cf961d30 100644 --- a/avr/cores/megacommand/MCL/MenuPage.cpp +++ b/avr/cores/megacommand/MCL/MenuPage.cpp @@ -10,6 +10,7 @@ void MenuPageBase::init() { DEBUG_PRINT("R.Size() = "); DEBUG_PRINTLN(R.Size()); R.restore_menu_layout_deps(); + gen_menu_row_names(); ((MCLEncoder *)encoders[1])->max = get_menu()->get_number_of_items() - 1; @@ -68,6 +69,11 @@ void MenuPageBase::gen_menu_row_names() { void MenuPageBase::setup() {} +void MenuPageBase::cleanup() { + trig_interface.ignoreNextEventClear(MDX_KEY_YES); + trig_interface.ignoreNextEventClear(MDX_KEY_NO); +} + void MenuPageBase::loop() { if (encoders[1]->hasChanged()) { @@ -219,10 +225,10 @@ bool MenuPageBase::handleEvent(gui_event_t *event) { } switch (key) { case MDX_KEY_YES: - // trig_interface.ignoreNextEvent(MDX_KEY_YES); + trig_interface.ignoreNextEvent(MDX_KEY_YES); goto YES; case MDX_KEY_NO: - // trig_interface.ignoreNextEvent(MDX_KEY_NO); + trig_interface.ignoreNextEvent(MDX_KEY_NO); goto NO; case MDX_KEY_UP: encoders[1]->cur -= inc; @@ -253,4 +259,5 @@ bool MenuPageBase::handleEvent(gui_event_t *event) { exit(); return true; } + return false; } diff --git a/avr/cores/megacommand/MCL/MenuPage.h b/avr/cores/megacommand/MCL/MenuPage.h index 4f8975e58..656fdebd8 100644 --- a/avr/cores/megacommand/MCL/MenuPage.h +++ b/avr/cores/megacommand/MCL/MenuPage.h @@ -40,6 +40,7 @@ class MenuPageBase : public LightPage { void init(); bool enter(); bool exit(); + void cleanup(); void gen_menu_device_names(); void gen_menu_row_names(); virtual bool handleEvent(gui_event_t *event); diff --git a/avr/cores/megacommand/MCL/MidiActivePeering.cpp b/avr/cores/megacommand/MCL/MidiActivePeering.cpp index 8432312ee..1ab6fa5d6 100644 --- a/avr/cores/megacommand/MCL/MidiActivePeering.cpp +++ b/avr/cores/megacommand/MCL/MidiActivePeering.cpp @@ -1,6 +1,46 @@ #include "MCL_impl.h" #include "ResourceManager.h" +uint8_t *GenericMidiDevice::icon() { return R.icons_device->icon_turbo; } + +bool GenericMidiDevice::probe() { + if (mcl_cfg.uart2_turbo_speed) { + mcl_gui.delay_progress(1200); + connected = true; + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart2_turbo_speed), + uart); + } + return true; +} + +uint8_t GenericMidiDevice::get_mute_cc() { + return mcl_cfg.uart2_cc_mute > 127 ? 255 : mcl_cfg.uart2_cc_mute; +} + +void GenericMidiDevice::muteTrack(uint8_t track, bool mute = true, + MidiUartParent *uart_ = nullptr) { + if (track >= NUM_EXT_TRACKS || mcl_cfg.uart2_cc_mute > 127) { + return; + } + if (uart_ == nullptr) { + uart_ = uart; + } + uart_->sendCC(mcl_seq.ext_tracks[track].channel, mcl_cfg.uart2_cc_mute, + mute ? 127 : 0); +}; + +void GenericMidiDevice::setLevel(uint8_t track, uint8_t value, + MidiUartParent *uart_ = nullptr) { + if (track >= NUM_EXT_TRACKS || mcl_cfg.uart2_cc_level > 127) { + return; + } + if (uart_ == nullptr) { + uart_ = uart; + } + uart_->sendCC(mcl_seq.ext_tracks[track].channel, mcl_cfg.uart2_cc_level, + value); +} + void GenericMidiDevice::init_grid_devices(uint8_t device_idx) { uint8_t grid_idx = 1; GridDeviceTrack gdt; @@ -13,31 +53,31 @@ void GenericMidiDevice::init_grid_devices(uint8_t device_idx) { /// It is the caller's responsibility to check for null MidiUart device static MidiUartParent *_getMidiUart(uint8_t port) { + MidiUartParent *ret = nullptr; if (port == UART1_PORT) - return &MidiUart; + ret = &MidiUart; #ifdef EXT_TRACKS else if (port == UART2_PORT) - return &MidiUart2; + ret = &MidiUart2; #endif - else - return nullptr; + return ret; } /// It is the caller's responsibility to check for null MidiClass device static MidiClass *_getMidiClass(uint8_t port) { + MidiClass *ret = nullptr; if (port == UART1_PORT) - return &Midi; + ret = &Midi; #ifdef EXT_TRACKS else if (port == UART2_PORT) - return &Midi2; + ret = &Midi2; #endif - else - return nullptr; + return ret; } static bool resource_loaded = false; static size_t resource_size = 0; -static void prepare_display(uint8_t* buf) { +static void prepare_display(uint8_t *buf) { oled_display.clearDisplay(); oled_display.setFont(); oled_display.setCursor(60, 10); @@ -60,14 +100,20 @@ static MidiDevice *port2_drivers[] = { &generic_midi_device, }; +static MidiDevice *generic_drivers[] = { + &generic_midi_device, +}; + static MidiDevice *connected_midi_devices[2] = {&null_midi_device, &null_midi_device}; void MidiActivePeering::disconnect(uint8_t port) { - DEBUG_PRINTLN("disconnect"); - DEBUG_PRINTLN(port); + DEBUG_PRINTLN("disconnect"); + DEBUG_PRINTLN(port); MidiUartClass *pmidi = _getMidiUart(port); - if (!pmidi) { return; } + if (!pmidi) { + return; + } MidiDevice **drivers; uint8_t nr_drivers = 1; if (port == UART1_PORT) { @@ -79,7 +125,7 @@ void MidiActivePeering::disconnect(uint8_t port) { for (size_t i = 0; i < nr_drivers; ++i) { if (drivers[i]->connected) { if (midi_active_peering.get_device(port)->asElektronDevice()) { - turbo_light.set_speed(0, pmidi); + turbo_light.set_speed(0, pmidi); } drivers[i]->disconnect(port - 1); } @@ -104,7 +150,7 @@ void MidiActivePeering::force_connect(uint8_t port, MidiDevice *driver) { } static void probePort(uint8_t port, MidiDevice *drivers[], size_t nr_drivers, - MidiDevice **active_device, uint8_t* resource_buf) { + MidiDevice **active_device, uint8_t *resource_buf) { MidiUartClass *pmidi = _getMidiUart(port); auto *pmidi_class = _getMidiClass(port); if (!pmidi || !pmidi_class) @@ -114,9 +160,9 @@ static void probePort(uint8_t port, MidiDevice *drivers[], size_t nr_drivers, if (id != DEVICE_NULL && pmidi->recvActiveSenseTimer > 300 && pmidi->speed > 31250) { - - if ((port == UART1_PORT && MidiClock.uart_clock_recv == pmidi) || (port == UART2_PORT && MidiClock.uart_clock_recv == pmidi)) { - //Disable MidiClock/Transport on disconnected port. + if ((port == UART1_PORT && MidiClock.uart_clock_recv == pmidi) || + (port == UART2_PORT && MidiClock.uart_clock_recv == pmidi)) { + // Disable MidiClock/Transport on disconnected port. MidiClock.uart_clock_recv = nullptr; MidiClock.init(); } @@ -126,7 +172,7 @@ static void probePort(uint8_t port, MidiDevice *drivers[], size_t nr_drivers, if (drivers[i]->connected) drivers[i]->disconnect(port - 1); } - // reset MidiID to none + // reset MidiID to none pmidi->device.init(); // reset connected device to /dev/null *active_device = &null_midi_device; @@ -138,7 +184,7 @@ static void probePort(uint8_t port, MidiDevice *drivers[], size_t nr_drivers, auto oldfont = oled_display.getFont(); prepare_display(resource_buf); - uint8_t* icon = drivers[i]->icon(); + uint8_t *icon = drivers[i]->icon(); if (icon) { oled_display.drawBitmap(14, 8, icon, 34, 42, WHITE); } @@ -157,7 +203,7 @@ static void probePort(uint8_t port, MidiDevice *drivers[], size_t nr_drivers, pmidi->device.set_name(drivers[i]->name); drivers[i]->init_grid_devices(port - 1); *active_device = drivers[i]; - //Re-enable MidiClock/Transport recv + // Re-enable MidiClock/Transport recv midi_setup.cfg_clock_recv(); break; } @@ -186,22 +232,31 @@ void MidiActivePeering::run() { byte resource_buf[RM_BUFSIZE]; resource_loaded = false; - //Setting USB turbo speed too early can cause OS upload to fail + // Setting USB turbo speed too early can cause OS upload to fail #ifndef DEBUGMODE - if (turbo_light.tmSpeeds[turbo_light.lookup_speed(mcl_cfg.usb_turbo)] != MidiUartUSB.speed && slowclock > 4000 && usb_set_speed) { - turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.usb_turbo), MidiUSB.uart); - usb_set_speed = false; + if (turbo_light.tmSpeeds[turbo_light.lookup_speed(mcl_cfg.usb_turbo_speed)] != + MidiUartUSB.speed && + slowclock > 4000 && usb_set_speed) { + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.usb_turbo_speed), + MidiUSB.uart); + usb_set_speed = false; } #endif probePort(UART1_PORT, port1_drivers, countof(port1_drivers), &connected_midi_devices[0], resource_buf); #ifdef EXT_TRACKS - probePort(UART2_PORT, port2_drivers, countof(port2_drivers), - &connected_midi_devices[1], resource_buf); + uint8_t nr_drivers = countof(port2_drivers); + MidiDevice **drivers = port2_drivers; + if (!mcl_cfg.uart2_device) { + nr_drivers = 1; + drivers = generic_drivers; + } + probePort(UART2_PORT, drivers, nr_drivers, &connected_midi_devices[1], + resource_buf); if (resource_loaded) { // XXX doesn't work yet - //R.Restore(resource_buf, resource_size); + // R.Restore(resource_buf, resource_size); GUI.currentPage()->init(); resource_loaded = false; } diff --git a/avr/cores/megacommand/MCL/MidiActivePeering.h b/avr/cores/megacommand/MCL/MidiActivePeering.h index e512693ba..50942c45c 100644 --- a/avr/cores/megacommand/MCL/MidiActivePeering.h +++ b/avr/cores/megacommand/MCL/MidiActivePeering.h @@ -6,17 +6,18 @@ #include "Elektron.h" #include "MidiID.h" #include "Task.h" +#include "MCLSysConfig.h" +#include "MCLSeq.h" #define UART1_PORT 1 #define UART2_PORT 2 class MidiActivePeering : public Task { public: - MidiActivePeering(uint16_t _interval = 0) : Task(_interval) { + MidiActivePeering(uint16_t _interval = 250) : Task(_interval) { setup(_interval); } - - virtual void setup(uint16_t _interval = 0) { interval = _interval; } + virtual void setup(uint16_t _interval = 250) { interval = _interval; } virtual void disconnect(uint8_t port); virtual void force_connect(uint8_t port, MidiDevice *driver); virtual void run(); @@ -32,8 +33,15 @@ class MidiActivePeering : public Task { class GenericMidiDevice : public MidiDevice { public: GenericMidiDevice(); - virtual bool probe() { return true; } + + virtual uint8_t* icon(); + + virtual bool probe(); + void init_grid_devices(uint8_t device_idx); + virtual uint8_t get_mute_cc(); + virtual void muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr); + virtual void setLevel(uint8_t track, uint8_t value, MidiUartParent *uart_ = nullptr); }; class NullMidiDevice : public MidiDevice { diff --git a/avr/cores/megacommand/MCL/MidiSetup.cpp b/avr/cores/megacommand/MCL/MidiSetup.cpp index c27cc47a5..630f53882 100644 --- a/avr/cores/megacommand/MCL/MidiSetup.cpp +++ b/avr/cores/megacommand/MCL/MidiSetup.cpp @@ -126,21 +126,25 @@ void MidiSetup::cfg_ports(bool boot) { } if (!boot) { - turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.usb_turbo), + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.usb_turbo_speed), MidiUSB.uart); } if (elektron_devs[0]) { - turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart1_turbo), + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart1_turbo_speed), Midi.uart); delay(100); elektron_devs[0]->setup(); } if (mcl_cfg.uart2_device == 0) { midi_active_peering.force_connect(UART2_PORT, &generic_midi_device); + if (mcl_cfg.uart2_turbo_speed) { + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart2_turbo_speed), + Midi2.uart); + } } else if (elektron_devs[1]) { elektron_devs[1]->setup(); - turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart2_turbo), + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart2_turbo_speed), Midi2.uart); } else { midi_active_peering.force_connect(UART2_PORT, &null_midi_device); diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 2816a9c98..6711340c5 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -2,7 +2,7 @@ #include "ResourceManager.h" #define FADER_LEN 18 -#define FADE_RATE 16 +#define FADE_RATE 8 void MixerPage::set_display_mode(uint8_t param) { if (display_mode != param) { @@ -51,6 +51,7 @@ encoders[3]->handler = encoder_filtq_handle; } void MixerPage::init() { + DEBUG_PRINTLN("mixer init"); level_pressmode = 0; /* for (uint8_t i = 0; i < 4; i++) { @@ -60,13 +61,15 @@ void MixerPage::init() { */ MD.set_key_repeat(0); trig_interface.on(); - MD.set_trigleds(0, TRIGLED_OVERLAY); + bool is_md_device = (midi_device == &MD); + MD.set_trigleds(0, is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); preview_mute_set = 255; bool switch_tracks = false; oled_display.clearDisplay(); set_display_mode(MODEL_LEVEL); first_track = 255; redraw_mask = -1; + seq_step_page.mute_mask++; show_mixer_menu = 0; memset(perf_locks_temp, 255, sizeof(perf_locks_temp)); // populate_mute_set(); @@ -83,6 +86,8 @@ void MixerPage::cleanup() { MD.set_key_repeat(1); disable_record_mutes(); trig_interface.off(); + ext_key_down = 0; + mute_toggle = 0; } void MixerPage::set_level(int curtrack, int value) { @@ -93,15 +98,15 @@ void MixerPage::set_level(int curtrack, int value) { void MixerPage::load_perf_locks(uint8_t state) { for (uint8_t n = 0; n < GUI_NUM_ENCODERS; n++) { + PerfEncoder *enc = (PerfEncoder*) encoders[n]; uint8_t val = perf_locks[state][n]; if (val < 128) { - encoders[n]->cur = val; - encoders[n]->old = val; - ((PerfEncoder *)encoders[n])->send(); + enc->cur = val; + enc->old = val; + enc->send(); } } } - void MixerPage::loop() { constexpr int timeout = 1500; perf_page.func_enc_check(); @@ -110,12 +115,13 @@ void MixerPage::loop() { if ((trig_interface.is_key_down(MDX_KEY_NO))&& preview_mute_set != 255 && note_interface.notes_on == 0) { for (uint8_t n = 0; n < GUI_NUM_ENCODERS; n++) { - if (encoders[n]->hasChanged()) { + PerfEncoder *enc = (PerfEncoder*) encoders[n]; + if (enc->hasChanged()) { if (BUTTON_DOWN(Buttons.ENCODER1 + n)) { GUI.ignoreNextEvent(Buttons.ENCODER1 + n); } - perf_locks[preview_mute_set][n] = encoders[n]->cur; - encoders[n]->old = encoders[n]->cur; + perf_locks[preview_mute_set][n] = enc->cur; + enc->old = enc->cur; } } } @@ -126,12 +132,12 @@ void MixerPage::loop() { draw_encoders = true; } else { draw_encoders = false; - for (uint8_t n = 0; n < 4; n++) { uint64_t mask = ((uint64_t)1 << MDX_KEY_LEFT) | ((uint64_t)1 << MDX_KEY_UP) | ((uint64_t)1 << MDX_KEY_RIGHT) | ((uint64_t)1 << MDX_KEY_DOWN) | ((uint64_t)1 << MDX_KEY_YES); - bool check = (trig_interface.cmd_key_state & mask); + for (uint8_t n = 0; n < 4; n++) { + bool check = (trig_interface.cmd_key_state & mask); if (note_interface.notes_on || check) { encoders_used_clock[n] = slowclock + timeout + 1; @@ -151,7 +157,6 @@ void MixerPage::loop() { init_encoders_used_clock(timeout); } } - void MixerPage::draw_levels() {} void encoder_level_handle(EncoderParent *enc) { @@ -178,26 +183,12 @@ void encoder_level_handle(EncoderParent *enc) { void send_fx(uint8_t param, EncoderParent *enc, uint8_t type) { // for (int val = enc->old; val > enc->cur; val--) { - MD.sendFXParam(param, enc->cur, type); + MD.setFXParam(param, enc->cur, type, true); // } // for (int val = enc->old; val > enc->cur; val++) { // MD.sendFXParam(param, val, type); // } PGM_P param_name = NULL; - switch (type) { - case MD_FX_ECHO: - MD.kit.delay[param] = enc->cur; - break; - case MD_FX_DYN: - MD.kit.dynamics[param] = enc->cur; - break; - case MD_FX_REV: - MD.kit.reverb[param] = enc->cur; - break; - case MD_FX_EQ: - MD.kit.eq[param] = enc->cur; - break; - } char str[4]; char str2[] = "-- "; @@ -236,7 +227,7 @@ void MixerPage::adjust_param(EncoderParent *enc, uint8_t param) { int dir = enc->getValue() - enc->old; int newval; - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { if (note_interface.is_note_on(i)) { newval = min(max(MD.kit.params[i][param] + dir, 0), 127); MD.setTrackParam(i, param, newval, nullptr, true); @@ -266,7 +257,7 @@ void MixerPage::display() { uint8_t mute_set = preview_mute_set; - if (show_mixer_menu && seq_step_page.display_mute_mask(midi_device)) { + if (((ext_key_down && mute_set == 255) || show_mixer_menu) && seq_step_page.display_mute_mask(midi_device)) { oled_draw_mutes(); } else if (mute_set != 255 && mute_sets[!is_md_device].mutes[mute_set] != seq_step_page.mute_mask) { @@ -274,7 +265,7 @@ void MixerPage::display() { if (!is_md_device) { mask &= 0b111111; } - MD.set_trigleds(mask, TRIGLED_EXCLUSIVE); + MD.set_trigleds(mask, is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); seq_step_page.mute_mask = mask; oled_draw_mutes(); } @@ -303,9 +294,9 @@ void MixerPage::display() { uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; uint8_t *levels = is_md_device ? disp_levels : ext_disp_levels; - uint8_t dec = (uint16_t)MidiClock.get_tempo() / FADE_RATE; + uint8_t dec = FADE_RATE; - for (int i = 0; i < len; i++) { + for (uint8_t i = 0; i < len; i++) { if (is_md_device) { if (display_mode == MODEL_LEVEL) { @@ -475,7 +466,7 @@ void MixerPage::redraw() { void MixerPage::toggle_or_solo(bool solo) { uint8_t is_md_device = (midi_device == &MD); uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; - for (int i = 0; i < len; i++) { + for (uint8_t i = 0; i < len; i++) { bool note_on = note_interface.is_note_on(i); bool mute_state = false; @@ -509,6 +500,7 @@ void MixerPage::toggle_or_solo(bool solo) { bool MixerPage::handleEvent(gui_event_t *event) { + uint8_t is_md_device = (midi_device == &MD); if (note_interface.is_event(event)) { uint8_t mask = event->mask; uint8_t port = event->port; @@ -516,20 +508,19 @@ bool MixerPage::handleEvent(gui_event_t *event) { uint8_t track = event->source - 128; - uint8_t is_md_device = (midi_device == &MD); if (track > 16) { return false; } - if (!show_mixer_menu && preview_mute_set == 255) { - trig_interface.send_md_leds(TRIGLED_OVERLAY); + if (!ext_key_down && !show_mixer_menu && preview_mute_set == 255) { + trig_interface.send_md_leds(is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); } uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; if (event->mask == EVENT_BUTTON_PRESSED && track < len) { if (note_interface.is_note(track)) { - if (show_mixer_menu || preview_mute_set != 255) { - + if (show_mixer_menu || preview_mute_set != 255 || ext_key_down) { + if (ext_key_down) { mute_toggle = 1; } SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[track] : (SeqTrack *)&mcl_seq.ext_tracks[track]; @@ -561,6 +552,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { first_track = track; MD.setStatus(0x22, track); } + oled_draw_mutes(); } return true; } @@ -601,6 +593,9 @@ bool MixerPage::handleEvent(gui_event_t *event) { break; } case MDX_KEY_EXTENDED: { + DEBUG_PRINTLN("key extended"); + ext_key_down = 1; + redraw(); if (midi_device == &MD) { for (uint8_t i = 0; i < 16; i++) { if (note_interface.is_note_on(i)) { @@ -676,11 +671,14 @@ bool MixerPage::handleEvent(gui_event_t *event) { break; } case MDX_KEY_SCALE: { + if (midi_device != &MD) { midi_device = &MD; } else { midi_device = midi_active_peering.get_device(UART2_PORT); } + is_md_device = (midi_device == &MD); + trig_interface.send_md_leds(is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); redraw(); break; } @@ -692,6 +690,20 @@ bool MixerPage::handleEvent(gui_event_t *event) { case MDX_KEY_YES: { goto global_release; } + case MDX_KEY_EXTENDED: { + + ext_key_down = 0; + if (note_interface.notes_on == 0 && !mute_toggle) { + if (last_page != NULL_PAGE) { mcl.setPage(last_page); last_page = NULL_PAGE; } + else { mcl.setPage(GRID_PAGE); } + return true; + } + mute_toggle = 0; + if (!show_mixer_menu && preview_mute_set == 255) { + trig_interface.send_md_leds(is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); + } + return true; + } case MDX_KEY_LEFT: case MDX_KEY_UP: case MDX_KEY_RIGHT: @@ -700,13 +712,14 @@ bool MixerPage::handleEvent(gui_event_t *event) { ((uint64_t)1 << MDX_KEY_LEFT) | ((uint64_t)1 << MDX_KEY_UP) | ((uint64_t)1 << MDX_KEY_RIGHT) | ((uint64_t)1 << MDX_KEY_DOWN) | ((uint64_t)1 << MDX_KEY_YES); if ((trig_interface.cmd_key_state & mask) == 0) { - trig_interface.send_md_leds(TRIGLED_OVERLAY); + trig_interface.send_md_leds(is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); preview_mute_set = 255; redraw(); for (uint8_t n = 0; n < 4; n++) { + MCLEncoder *enc = (MCLEncoder*) &encoders[n]; if (perf_locks_temp[n] != 255 && (trig_interface.is_key_down(MDX_KEY_NO))) { - encoders[n]->cur = perf_locks_temp[n]; - encoders[n]->old = encoders[n]->cur; + enc->cur = perf_locks_temp[n]; + enc->old = enc->cur; } perf_locks_temp[n] = 255; } @@ -731,7 +744,7 @@ bool MixerPage::handleEvent(gui_event_t *event) { preview_mute_set = 255; show_mixer_menu = false; disable_record_mutes(); - MD.set_trigleds(0, TRIGLED_OVERLAY); + MD.set_trigleds(0, is_md_device ? TRIGLED_OVERLAY : TRIGLED_EXCLUSIVE); redraw(); return true; } @@ -818,7 +831,7 @@ void MixerPage::onControlChangeCallback_Midi(uint8_t track, uint8_t track_param, return; } SET_BIT16(mixer_page.redraw_mask, track); - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { if (note_interface.is_note_on(i) && (i != track)) { MD.setTrackParam(i, track_param, value, nullptr, true); SET_BIT16(mixer_page.redraw_mask, i); diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index 77c939310..98480c6d4 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -3,12 +3,11 @@ #ifndef MIXERPAGE_H__ #define MIXERPAGE_H__ -//#include "Pages.h" +// #include "Pages.h" #include "GUI.h" - class MuteSet { - public: +public: uint16_t mutes[4]; }; @@ -31,12 +30,12 @@ void encoder_lastparam_handle(EncoderParent *enc); class MixerPage : public LightPage { public: - uint8_t level_pressmode = 0; int8_t disp_levels[16]; int8_t ext_disp_levels[6]; - - MidiDevice* midi_device; + bool mute_toggle = 0; + uint8_t ext_key_down; + MidiDevice *midi_device; uint8_t display_mode; uint8_t first_track; @@ -46,11 +45,13 @@ class MixerPage : public LightPage { bool draw_encoders; + PageIndex last_page = NULL_PAGE; + uint8_t current_mute_set = 255; uint8_t preview_mute_set = 255; void send_fx(uint8_t param, Encoder *enc, uint8_t type); - //Don't change order + // Don't change order MuteSet mute_sets[2]; uint8_t perf_locks[4][4]; // @@ -62,10 +63,10 @@ class MixerPage : public LightPage { MixerPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) : LightPage(e1, e2, e3, e4) { - midi_device = &MD; - memset(mute_sets,0xFF,sizeof(mute_sets)); - memset(perf_locks,0xFF,sizeof(perf_locks)); - } + midi_device = &MD; + memset(mute_sets, 0xFF, sizeof(mute_sets)); + memset(perf_locks, 0xFF, sizeof(perf_locks)); + } void adjust_param(EncoderParent *enc, uint8_t param); void draw_levels(); void redraw(); @@ -80,11 +81,19 @@ class MixerPage : public LightPage { void load_perf_locks(uint8_t state); void toggle_or_solo(bool solo = false); - //Handled in MCLSeq + // Handled in MCLSeq void onNoteOnCallback_Midi(uint8_t *msg); - void onControlChangeCallback_Midi(uint8_t track, uint8_t track_param, uint8_t value); + void onControlChangeCallback_Midi(uint8_t track, uint8_t track_param, + uint8_t value); uint8_t note_to_trig(uint8_t note_num); + void trig(uint8_t track_number) { + disp_levels[track_number] = MD.kit.levels[track_number]; + if (MD.kit.trigGroups[track_number] < 16) { + disp_levels[MD.kit.trigGroups[track_number]] = + MD.kit.levels[MD.kit.trigGroups[track_number]]; + } + } virtual bool handleEvent(gui_event_t *event); virtual void display(); diff --git a/avr/cores/megacommand/MCL/OscMixerPage.cpp b/avr/cores/megacommand/MCL/OscMixerPage.cpp index 1c45a913f..128e49cf8 100644 --- a/avr/cores/megacommand/MCL/OscMixerPage.cpp +++ b/avr/cores/megacommand/MCL/OscMixerPage.cpp @@ -7,11 +7,11 @@ void OscMixerPage::setup() {} void OscMixerPage::init() { WavDesignerPage::init(); trig_interface.off(); - wd.last_page = mcl.currentPage(); wavdesign_menu_page.menu.enable_entry(1, false); wavdesign_menu_page.menu.enable_entry(2, true); } -void OscMixerPage::cleanup() {} +void OscMixerPage::cleanup() { } + bool OscMixerPage::handleEvent(gui_event_t *event) { if (WavDesignerPage::handleEvent(event)) { return true; diff --git a/avr/cores/megacommand/MCL/OscPage.cpp b/avr/cores/megacommand/MCL/OscPage.cpp index 0a786b17f..ecd2a1cd0 100644 --- a/avr/cores/megacommand/MCL/OscPage.cpp +++ b/avr/cores/megacommand/MCL/OscPage.cpp @@ -17,19 +17,17 @@ float OscPage::get_freq() { float a = pow(2.00, 1.00 / 12.00); float n = enc1.cur - 64; float fn = fzero * pow(a, n); - float fout = fn * pow(2, (float)(enc2.cur - 100) / (float)1200); + float fout = fn * pow(2, (float)(100 - enc2.cur) / (float)1200); return fout; } void OscPage::init() { - if (wd.last_page != 255 && wd.last_page != WD_PAGE_0 + id) { mcl.setPage(wd.last_page); wd.last_page = 255; return; } WavDesignerPage::init(); - wd.last_page = mcl.currentPage(); wavdesign_menu_page.menu.enable_entry(1, true); wavdesign_menu_page.menu.enable_entry(2, false); oled_display.clearDisplay(); } -void OscPage::cleanup() { DEBUG_PRINT_FN(); } +void OscPage::cleanup() { } bool OscPage::handleEvent(gui_event_t *event) { if (WavDesignerPage::handleEvent(event)) { return true; @@ -128,8 +126,6 @@ void OscPage::display() { // oled_display.clearDisplay(); oled_display.fillRect(0, 0, 64, 32, BLACK); - MusicalNotes number_to_note; - scanline_width = 64; uint8_t c = 1; @@ -189,12 +185,12 @@ void OscPage::display() { uint8_t note = s - (floor(s / 12) * 12); oled_display.print(number_to_note.notes_upper[note]); oled_display.print((uint8_t)floor(s / 12)); - if (enc3.cur < 0) { - oled_display.print(F("-")); - } else { + if (enc2.cur < 0) { oled_display.print(F("+")); } - oled_display.print(enc2.cur); + if (enc2.cur != 0) { + oled_display.print(-1 * enc2.cur); + } } // GUI.put_string_at(0, my_str); WavDesignerPage::display(); @@ -296,7 +292,7 @@ void OscPage::draw_levels() { uint8_t w = 128 - x; UsrOsc usr_osc(w); - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { scaled_level = (uint8_t)(((float)sine_levels[i] / (float)127) * 15); if (note_interface.is_note_on(i)) { diff --git a/avr/cores/megacommand/MCL/PageSelectPage.cpp b/avr/cores/megacommand/MCL/PageSelectPage.cpp index cfd40973a..8091e642a 100644 --- a/avr/cores/megacommand/MCL/PageSelectPage.cpp +++ b/avr/cores/megacommand/MCL/PageSelectPage.cpp @@ -97,17 +97,14 @@ void PageSelectPage::init() { trigled_mask = 0; draw_popup(); md_prepare(); - display(); MidiUartParent::handle_midi_lock = _midi_lock_tmp; } void PageSelectPage::draw_popup() { char str[16]; uint8_t pageidx = get_pageidx(page_select); - if (pageidx < 16) { - get_page(pageidx, str); - MD.popup_text(str, true); - } + get_page(pageidx, str); + MD.popup_text(str, true); } void PageSelectPage::md_prepare() { diff --git a/avr/cores/megacommand/MCL/PerfData.h b/avr/cores/megacommand/MCL/PerfData.h index 95a1eda0a..467d42420 100644 --- a/avr/cores/megacommand/MCL/PerfData.h +++ b/avr/cores/megacommand/MCL/PerfData.h @@ -54,9 +54,10 @@ class PerfScene { void init() { count = 0; for (uint8_t a = 0; a < NUM_PERF_PARAMS; a++) { - params[a].dest = 0; - params[a].param = 0; - params[a].val = 255; + PerfParam *p = ¶ms[a]; + p->dest = 0; + p->param = 0; + p->val = 255; } } @@ -108,10 +109,11 @@ class PerfScene { if (count == 0) { return; } for (uint8_t a = 0; a < NUM_PERF_PARAMS; a++) { // Find match - if (params[a].dest == dest + 1 && params[a].param == param) { - params[a].val = 255; - params[a].dest = 0; - params[a].param = 0; + PerfParam *p = ¶ms[a]; + if (p->dest == dest + 1 && p->param == param) { + p->val = 255; + p->dest = 0; + p->param = 0; count--; } } @@ -131,7 +133,8 @@ class PerfScene { uint8_t find_match(uint8_t dest_, uint8_t param_) { for (uint8_t a = 0; a < NUM_PERF_PARAMS; a++) { - if (params[a].dest == dest_ + 1 && params[a].param == param_ && params[a].val != 255) { + PerfParam *p = ¶ms[a]; + if (p->dest == dest_ + 1 && p->param == param_ && p->val != 255) { return a; } } diff --git a/avr/cores/megacommand/MCL/PerfEncoder.cpp b/avr/cores/megacommand/MCL/PerfEncoder.cpp index cea092d71..f636fb2d9 100644 --- a/avr/cores/megacommand/MCL/PerfEncoder.cpp +++ b/avr/cores/megacommand/MCL/PerfEncoder.cpp @@ -14,7 +14,7 @@ void PerfEncoder::send_param(uint8_t dest, uint8_t param, uint8_t val) { DEBUG_PRINT(channel); DEBUG_PRINT(" "); DEBUG_PRINT(param); DEBUG_PRINT(" "); DEBUG_PRINTLN(val); MidiUart2.sendCC(channel, param, val); } else if (dest >= NUM_MD_TRACKS) { - MD.sendFXParam(param, val, MD_FX_ECHO + dest - NUM_MD_TRACKS); + MD.setFXParam(param, val, MD_FX_ECHO + dest - NUM_MD_TRACKS); } else { MD.setTrackParam(dest, param, val); } diff --git a/avr/cores/megacommand/MCL/PerfPage.cpp b/avr/cores/megacommand/MCL/PerfPage.cpp index 94dfec52a..5ce310ce1 100644 --- a/avr/cores/megacommand/MCL/PerfPage.cpp +++ b/avr/cores/megacommand/MCL/PerfPage.cpp @@ -321,7 +321,8 @@ void PerfPage::learn_param(uint8_t dest, uint8_t param, uint8_t value) { // Intercept controller param. for (uint8_t i = 0; i < 4; i++) { - PerfData *d = &perf_encoders[i]->perf_data; + PerfEncoder *e = perf_encoders[i]; + PerfData *d = &e->perf_data; if (dest + 1 == d->src && param == d->param) { // Controller param, start value; uint8_t min = d->min; @@ -330,7 +331,7 @@ void PerfPage::learn_param(uint8_t dest, uint8_t param, uint8_t value) { int16_t cur = value - min; int16_t range = max - min; uint8_t val = (cur * (int16_t)127) / range; - perf_encoders[i]->cur = val; + e->cur = val; //perf_encoders[i]->send(); if (mcl.currentPage() == PERF_PAGE_0) { update_params(); @@ -578,7 +579,7 @@ bool PerfPage::handleEvent(gui_event_t *event) { } } } - return true; + return false; } if (EVENT_RELEASED(event, Buttons.ENCODER4)) { diff --git a/avr/cores/megacommand/MCL/PerfTrack.h b/avr/cores/megacommand/MCL/PerfTrack.h index cc37412b0..e86a916b0 100644 --- a/avr/cores/megacommand/MCL/PerfTrack.h +++ b/avr/cores/megacommand/MCL/PerfTrack.h @@ -15,10 +15,11 @@ class PerfTrackEncoderData { uint8_t active_scene_b; uint8_t cur; - void init() { + void init(uint8_t n) { src = param = min = 0; - active_scene_a = 0; - active_scene_b = 1; + uint8_t c = n * 2; + active_scene_a = 0 + c; + active_scene_b = 1 + c; const char *str = "CONTROL"; strcpy(name, str); } @@ -50,7 +51,7 @@ class PerfTrack : public AUXTrack, public PerfTrackData { void init() { for (uint8_t n = 0; n < NUM_SCENES; n++) { if (n < 4) { - encs[n].init(); + encs[n].init(n); } scenes[n].init(); } diff --git a/avr/cores/megacommand/MCL/PolyPage.cpp b/avr/cores/megacommand/MCL/PolyPage.cpp index b3edfab33..ee612006d 100644 --- a/avr/cores/megacommand/MCL/PolyPage.cpp +++ b/avr/cores/megacommand/MCL/PolyPage.cpp @@ -23,21 +23,16 @@ void PolyPage::draw_mask() { for (uint8_t i = 0; i < 16; i++) { uint8_t x = i * 8; - if (note_interface.is_note(i)) { - oled_display.fillRect(x, 2, 6, 6, WHITE); + bool is_note = note_interface.is_note(i); + oled_display.fillRect(x, 2, 6, 6, is_note); + if (is_note) { } - else if (IS_BIT_SET16(*poly_mask, i)) { - - oled_display.fillRect(x, 2, 6, 6, BLACK); oled_display.drawRect(x, 2, 6, 6, WHITE); } - else { - - oled_display.fillRect(x, 2, 6, 6, BLACK); oled_display.drawLine(x, 5, 5 + x, 5, WHITE); } } diff --git a/avr/cores/megacommand/MCL/Project.cpp b/avr/cores/megacommand/MCL/Project.cpp index a30470de7..77a2af4d4 100644 --- a/avr/cores/megacommand/MCL/Project.cpp +++ b/avr/cores/megacommand/MCL/Project.cpp @@ -9,11 +9,10 @@ bool Project::new_project(const char *newprj) { // Create parent project directory // chdir_projects(); - + DEBUG_PRINTLN(newprj); + DEBUG_PRINTLN(strlen(newprj)); // Create project directory - SD.mkdir(newprj, true); - - if (!SD.chdir(newprj)) { + if (!SD.mkdir(newprj, true) || !SD.chdir(newprj)) { gfx.alert("ERROR", "DIR"); return false; } diff --git a/avr/cores/megacommand/MCL/RAMPage.cpp b/avr/cores/megacommand/MCL/RAMPage.cpp index 556eb0254..128cca79c 100644 --- a/avr/cores/megacommand/MCL/RAMPage.cpp +++ b/avr/cores/megacommand/MCL/RAMPage.cpp @@ -34,9 +34,9 @@ void RAMPage::init() { } else { ((MCLEncoder *)encoders[0])->max = 1; } - if (page_id == 0) { - setup_callbacks(); - } +// if (page_id == 0) { +// setup_callbacks(); +// } if (mcl_cfg.ram_page_mode == LINK) { for (uint8_t n = 0; n < 4; n++) { if (page_id == 0) { @@ -67,7 +67,7 @@ void RAMPage::prepare_link(uint8_t track, uint8_t steps, uint8_t row, mcl_actions.links[track].row = row; mcl_actions.links[track].loops = 1; - mcl_actions.send_machine[track] = 0; + mcl_actions.send_machine[track] = 1; uint16_t next_step = (MidiClock.div16th_counter / steps) * steps + steps; grid_page.active_slots[track] = SLOT_PENDING; mcl_actions.transition_level[track] = transition; @@ -615,32 +615,17 @@ void RAMPage::display() { oled_display.setFont(oldfont); } -void RAMPage::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; - // If external keyboard controlling MD pitch, send parameter updates - // to all polyphonic tracks +void RAMPage::onControlChangeCallback_Midi(uint8_t track, uint8_t track_param, uint8_t value) { uint8_t param_true = 0; - if ((mcl_cfg.ram_page_mode == MONO) || (!cc_link_enable)) { + if ((mcl_cfg.ram_page_mode == MONO) || (!cc_link_enable) || grid_page.active_slots[track] != SLOT_RAM_PLAY) { return; } - MD.parseCC(channel, param, &track, &track_param); - if (track > 15) { - return; - } if (track_param == 32) { return; } // ignore mute - if (grid_page.active_slots[track] != SLOT_RAM_PLAY) { - return; - } - for (uint8_t n = 0; n < 16; n++) { if ((grid_page.active_slots[n] == SLOT_RAM_PLAY) && (n != track)) { @@ -666,7 +651,7 @@ void RAMPage::onControlChangeCallback_Midi(uint8_t *msg) { // in_sysex = 0; } } - +/* void RAMPage::setup_callbacks() { if (midi_state) { return; @@ -686,7 +671,7 @@ void RAMPage::remove_callbacks() { midi_state = false; } - +*/ bool RAMPage::handleEvent(gui_event_t *event) { if (EVENT_CMD(event)) { uint8_t key = event->source - 64; diff --git a/avr/cores/megacommand/MCL/RAMPage.h b/avr/cores/megacommand/MCL/RAMPage.h index 1cad8ab3e..2c4308db4 100644 --- a/avr/cores/megacommand/MCL/RAMPage.h +++ b/avr/cores/megacommand/MCL/RAMPage.h @@ -9,7 +9,7 @@ #define NUM_RAM_PAGES 2 -class RAMPage : public LightPage, MidiCallback { +class RAMPage : public LightPage { public: RAMPage(uint8_t _page_id, Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) @@ -60,10 +60,10 @@ class RAMPage : public LightPage, MidiCallback { void setup_sequencer(uint8_t track); - void setup_callbacks(); - void remove_callbacks(); + //void setup_callbacks(); + //void remove_callbacks(); - void onControlChangeCallback_Midi(uint8_t *msg); + void onControlChangeCallback_Midi(uint8_t track, uint8_t track_param, uint8_t value); }; extern MCLEncoder ram_a_param1; diff --git a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp index 946ee47d2..16f8c8d3c 100644 --- a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp @@ -177,15 +177,17 @@ void SampleBrowserPage::send_sample(int slot, char *newname, bool silent) { } void SampleBrowserPage::recv_wav(int slot, bool silent) { - char wav_name[FILE_ENTRY_SIZE] = ""; + //limit len to 16 char. + const uint8_t len = 16; + char wav_name[len] = ""; // should be of form "ID - NAME..." // ^--~~~~~~~ // memmove get_entry(slot, wav_name); - memmove(wav_name + 2, wav_name + 5, FILE_ENTRY_SIZE - 5); - wav_name[FILE_ENTRY_SIZE - 3] = '\0'; - wav_name[FILE_ENTRY_SIZE - 2] = '\0'; - wav_name[FILE_ENTRY_SIZE - 1] = '\0'; + memmove(wav_name + 2, wav_name + 5, len - 5); + wav_name[len - 3] = '\0'; + wav_name[len - 2] = '\0'; + wav_name[len - 1] = '\0'; if (!silent) { if (!mcl_gui.wait_for_input(wav_name, "Sample Name", @@ -260,13 +262,12 @@ bool SampleBrowserPage::handleEvent(gui_event_t *event) { file_menu_page.menu.enable_entry(FM_NEW_FOLDER, !state); file_menu_page.menu.enable_entry(FM_DELETE, !state); // delete file_menu_page.menu.enable_entry(FM_RENAME, !state); // rename - file_menu_page.menu.enable_entry(FM_OVERWRITE, !state); file_menu_page.menu.enable_entry(FM_RECVALL, state); file_menu_page.menu.enable_entry(FM_SENDALL, state); return true; } - if (EVENT_PRESSED(event, Buttons.BUTTON2)) { + if (EVENT_PRESSED(event, Buttons.BUTTON1)) { mcl.setPage(PAGE_SELECT_PAGE); return true; } @@ -275,6 +276,7 @@ bool SampleBrowserPage::handleEvent(gui_event_t *event) { } void SampleBrowserPage::query_sample_slots() { + DEBUG_PRINTLN("query sample slots"); encoders[1]->cur = 0; encoders[1]->old = 0; old_cur_row = cur_row; @@ -323,18 +325,18 @@ bool SampleBrowserPage::_handle_filemenu() { } switch (file_menu_page.menu.get_item_index(file_menu_encoder.cur)) { case FM_RECVALL: + if (!mcl_gui.wait_for_confirm("Receive all", "Overwrite?")) { + goto end; + } show_ram_slots = true; init(true); if (numEntries == 0) { gfx.alert("NON", "UW"); goto end; } - if (!mcl_gui.wait_for_confirm("Receive all", "Overwrite?")) { - goto end; - } - DEBUG_PRINTLN("Recv samples"); + DEBUG_PRINTLN("Recv samples"); DEBUG_PRINTLN(numEntries); - for (uint8_t n = 0; n < numEntries; n++) { + for (uint8_t n = 0; n < numEntries && !trig_interface.is_key_down(MDX_KEY_NO); n++) { DEBUG_PRINTLN("Recv wav"); char wav_name[FILE_ENTRY_SIZE] = ""; get_entry(n, wav_name); @@ -352,7 +354,7 @@ bool SampleBrowserPage::_handle_filemenu() { return; } char wav_name[FILE_ENTRY_SIZE] = ""; - for (uint8_t n = 0; n < numEntries; n++) { + for (uint8_t n = 0; n < numEntries && !trig_interface.is_key_down(MDX_KEY_NO); n++) { get_entry(n, wav_name); DEBUG_PRINTLN(wav_name); if (!isdigit(wav_name[0]) || !isdigit(wav_name[1])) diff --git a/avr/cores/megacommand/MCL/SeqExtStepPage.cpp b/avr/cores/megacommand/MCL/SeqExtStepPage.cpp index 45ae2e8a7..e7ccd8c47 100644 --- a/avr/cores/megacommand/MCL/SeqExtStepPage.cpp +++ b/avr/cores/megacommand/MCL/SeqExtStepPage.cpp @@ -74,6 +74,7 @@ void SeqExtStepPage::init() { midi_device = midi_active_peering.get_device(UART2_PORT); SeqPage::init(); + MD.set_rec_mode(3); param_select = PARAM_OFF; trig_interface.on(); trig_interface.send_md_leds(TRIGLED_EXCLUSIVE); @@ -87,6 +88,7 @@ void SeqExtStepPage::init() { void SeqExtStepPage::cleanup() { SeqPage::cleanup(); + MD.set_rec_mode(0); // midi_events.remove_callbacks(); } @@ -759,7 +761,6 @@ void SeqExtStepPage::display() { mcl_gui.put_value_at(cur_x/timing_mid + 1,info1); epoch = active_track.epoch; if (pianoroll_mode == 0) { - MusicalNotes number_to_note; uint8_t oct = cur_y / 12; uint8_t note = cur_y - 12 * (cur_y / 12); char str[4] = " "; @@ -945,6 +946,12 @@ bool SeqExtStepPage::handleEvent(gui_event_t *event) { pos_cur_w(w); return true; } + case MDX_KEY_CLEAR: { + for (uint8_t n = 0; n < 127; n++) { + active_track.del_note(cur_x, w - 1, n); + } + return true; + } } } else { switch (key) { @@ -1050,6 +1057,7 @@ bool SeqExtStepPage::handleEvent(gui_event_t *event) { if (SeqPage::handleEvent(event)) { return true; } + return false; } void SeqExtStepMidiEvents::onControlChangeCallback_Midi2(uint8_t *msg) { diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index 19eb9021a..d1f60a65d 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -4,6 +4,7 @@ uint8_t SeqPage::page_select = 0; MidiDevice *SeqPage::midi_device = &MD; +MidiDevice *opt_midi_device_capture; uint8_t SeqPage::last_param_id = 0; uint8_t SeqPage::last_rec_event = 0; @@ -55,6 +56,10 @@ uint8_t SeqPage::last_step = 255; static MCLEncoder *opt_param1_capture = nullptr; static MCLEncoder *opt_param2_capture = nullptr; +MusicalNotes number_to_note; + +uint8_t copy_mask = 0; + void SeqPage::setup() {} void SeqPage::check_and_set_page_select() { @@ -145,7 +150,6 @@ void SeqPage::init() { void SeqPage::cleanup() { seqpage_midi_events.remove_callbacks(); note_interface.init_notes(); - midi_device = &MD; disable_record(); if (show_seq_menu) { encoders[0] = opt_param1_capture; @@ -275,7 +279,7 @@ bool SeqPage::display_mute_mask(MidiDevice* device, uint8_t offset) { } } if (last_mute_mask != mute_mask) { - MD.set_trigleds(mute_mask, TRIGLED_EXCLUSIVE); + MD.set_trigleds(mute_mask, is_md_device ? TRIGLED_MUTE : TRIGLED_EXCLUSIVE); return true; } return false; @@ -283,6 +287,7 @@ bool SeqPage::display_mute_mask(MidiDevice* device, uint8_t offset) { bool SeqPage::handleEvent(gui_event_t *event) { + if (note_interface.is_event(event)) { uint8_t port = event->port; MidiDevice *device = midi_active_peering.get_device(port); @@ -315,29 +320,19 @@ bool SeqPage::handleEvent(gui_event_t *event) { return seq_menu_page.handleEvent(event); } uint8_t key = event->source - 64; - uint8_t step = note_interface.get_first_md_note() + (page_select * 16); - if (note_interface.get_first_md_note() == 255) { - step = 255; - } + uint8_t first_note = note_interface.get_first_md_note(); + if (first_note != 255) { return false; } + if (event->mask == EVENT_BUTTON_PRESSED && trig_interface.is_key_down(MDX_KEY_FUNC)) { switch (key) { case MDX_KEY_LEFT: - if (step != 255) { - return false; - } - mcl_seq.md_tracks[last_md_track].rotate_left(); + mcl_seq.md_tracks[last_md_track].rotate_left(); return true; case MDX_KEY_RIGHT: - if (step != 255) { - return false; - } mcl_seq.md_tracks[last_md_track].rotate_right(); return true; case MDX_KEY_UP: - if (step != 255) { - return false; - } mcl_seq.md_tracks[last_md_track].reverse(); return true; } @@ -366,8 +361,7 @@ bool SeqPage::handleEvent(gui_event_t *event) { // If MD trig is held and BUTTON3 is pressed, launch note menu if (!show_seq_menu) { show_seq_menu = true; - - if (midi_device == &MD) { + if (opt_midi_device_capture == &MD) { auto &active_track = mcl_seq.md_tracks[last_md_track]; opt_trackid = last_md_track + 1; opt_speed = active_track.speed; @@ -385,7 +379,7 @@ bool SeqPage::handleEvent(gui_event_t *event) { encoders[1] = &seq_menu_entry_encoder; seq_menu_page.init(); seq_menu_page.gen_menu_device_names(); - mcl_cfg.seq_dev = midi_device == &MD ? UART1_PORT : UART2_PORT; + mcl_cfg.seq_dev = opt_midi_device_capture == &MD ? UART1_PORT : UART2_PORT; return true; } } @@ -398,9 +392,9 @@ bool SeqPage::handleEvent(gui_event_t *event) { if (show_seq_menu) { row_func = seq_menu_page.menu.get_row_function(seq_menu_page.encoders[1]->cur); - MidiDevice* old_dev = midi_device; - midi_device = midi_active_peering.get_device(mcl_cfg.seq_dev); - if (old_dev == midi_device) { + MidiDevice* old_dev = opt_midi_device_capture; + opt_midi_device_capture = midi_active_peering.get_device(mcl_cfg.seq_dev); + if (old_dev == opt_midi_device_capture) { opt_speed_handler(); opt_length_handler(); opt_channel_handler(); @@ -582,7 +576,7 @@ void SeqPage::draw_knob_timing(uint8_t timing, uint8_t timing_mid) { void SeqPage::length_handler(uint8_t length, bool multi) { bool is_poly = IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track); - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { if (multi) { for (uint8_t c = 0; c < 16; c++) { @@ -630,7 +624,7 @@ void opt_length_handler() { } void opt_channel_handler() { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { } else { uint8_t chan = opt_channel - 1; if (mcl_seq.ext_tracks[last_ext_track].channel != chan) { @@ -643,12 +637,12 @@ void opt_channel_handler() { void opt_mask_handler() { seq_step_page.config_mask_info(false); } void opt_trackid_handler() { - seq_step_page.select_track(SeqPage::midi_device, opt_trackid - 1); + seq_step_page.select_track(opt_midi_device_capture, opt_trackid - 1); } void opt_speed_handler() { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { DEBUG_PRINTLN(F("okay using MD for length update")); if (BUTTON_DOWN(Buttons.BUTTON4)) { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { @@ -699,11 +693,12 @@ void opt_clear_track_handler() { COPY: copy = true; } - if (SeqPage::midi_device == &MD || !(mcl.currentPage() == SEQ_PTC_PAGE || mcl.currentPage() == SEQ_EXTSTEP_PAGE)) { + if (opt_midi_device_capture == &MD || !(mcl.currentPage() == SEQ_PTC_PAGE || mcl.currentPage() == SEQ_EXTSTEP_PAGE)) { if (opt_clear == 2) { MD.popup_text(2); oled_display.textbox("CLEAR MD ", "TRACKS"); + oled_display.display(); uint8_t old_mutes[16]; for (uint8_t n = 0; n < 16; n++) { old_mutes[n] = mcl_seq.md_tracks[n].mute_state; @@ -723,6 +718,7 @@ void opt_clear_track_handler() { str = "CLEAR POLY TRACKS"; } oled_display.textbox(str, ""); + oled_display.display(); MD.popup_text((char*) str); if (copy) { opt_copy_track_handler(opt_clear); @@ -761,7 +757,7 @@ void opt_clear_track_handler() { void opt_clear_locks_handler() { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { if (opt_clear == 2) { for (uint8_t n = 0; n < 16; ++n) { oled_display.textbox("CLEAR MD ", "LOCKS"); @@ -790,7 +786,7 @@ void opt_clear_locks_handler() { } void opt_clear_all_tracks_handler() { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { } #ifdef EXT_TRACKS else { @@ -800,7 +796,7 @@ void opt_clear_all_tracks_handler() { } void opt_clear_all_locks_handler() { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { } #ifdef EXT_TRACKS else { @@ -819,15 +815,19 @@ void opt_copy_track_handler(uint8_t op) { opt_undo = op; silent = true; } + else { + SET_BIT(copy_mask, (uint8_t) (opt_midi_device_capture == &MD) * 4 + opt_copy); + } DEBUG_PRINTLN("copying"); DEBUG_PRINTLN(opt_copy); DEBUG_PRINTLN(op); DEBUG_PRINTLN("/end"); if (opt_copy == 2) { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { if (!silent) { oled_display.textbox("COPY MD ", "TRACKS"); + oled_display.display(); MD.popup_text(1); } mcl_clipboard.copy_sequencer(); @@ -836,13 +836,14 @@ void opt_copy_track_handler(uint8_t op) { else { if (!silent) { oled_display.textbox("COPY EXT ", "TRACKS"); + oled_display.display(); } mcl_clipboard.copy_sequencer(NUM_MD_TRACKS); } #endif } if (opt_copy == 1) { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { if (!silent) { oled_display.textbox("COPY TRACK", ""); MD.popup_text(4); @@ -853,7 +854,9 @@ void opt_copy_track_handler(uint8_t op) { #ifdef EXT_TRACKS else { if (!silent) { - oled_display.textbox("COPY EXT ", "TRACK"); + const char *str = "COPY EXT TRACK"; + MD.popup_text((char*)str); + oled_display.textbox(str,""); } mcl_clipboard.copy_track = last_ext_track + NUM_MD_TRACKS; mcl_clipboard.copy_sequencer_track(last_ext_track + NUM_MD_TRACKS); @@ -868,14 +871,19 @@ void opt_paste_track_handler() { if (opt_undo != 255) { undo = true; } + else if (!IS_BIT_SET(copy_mask, (uint8_t) (opt_midi_device_capture == &MD) * 4 + opt_paste)) { + return; + } if (opt_paste == 2) { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { if (!undo) { oled_display.textbox("PASTE MD ", "TRACKS"); + oled_display.display(); MD.popup_text(3); } else { oled_display.textbox("UNDO ", "TRACKS"); + oled_display.display(); MD.popup_text(22); } mcl_clipboard.paste_sequencer(); @@ -885,12 +893,13 @@ void opt_paste_track_handler() { str = "PASTE EXT TRACKS"; } oled_display.textbox(str, ""); + oled_display.display(); MD.popup_text((char*)str); mcl_clipboard.paste_sequencer(NUM_MD_TRACKS); } } if (opt_paste == 1) { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { bool is_poly = false; if (!undo) { oled_display.textbox("PASTE TRACK", ""); @@ -903,7 +912,7 @@ void opt_paste_track_handler() { if (is_poly) { for (uint8_t c = 0; c < 16; c++) { if (IS_BIT_SET16(mcl_cfg.poly_mask, c)) { - mcl_clipboard.paste_sequencer_track(mcl_clipboard.copy_track, c); + mcl_clipboard.paste_sequencer_track(c, c); } } } @@ -1072,7 +1081,7 @@ void opt_clear_step_locks_handler() { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { if (note_interface.is_note_on(n)) { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { mcl_seq.md_tracks[last_md_track].clear_step_locks( n + SeqPage::page_select * 16); } else { @@ -1087,7 +1096,7 @@ void opt_clear_step_locks_handler() { void opt_shift_track_handler() { switch (opt_shift) { case 1: - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { mcl_seq.md_tracks[last_md_track].rotate_left(); } #ifdef EXT_TRACKS @@ -1097,7 +1106,7 @@ void opt_shift_track_handler() { #endif break; case 2: - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { mcl_seq.md_tracks[last_md_track].rotate_right(); } #ifdef EXT_TRACKS @@ -1107,7 +1116,7 @@ void opt_shift_track_handler() { #endif break; case 3: - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { mcl_seq.md_tracks[n].rotate_left(); } @@ -1121,7 +1130,7 @@ void opt_shift_track_handler() { #endif break; case 4: - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { mcl_seq.md_tracks[n].rotate_right(); } @@ -1140,7 +1149,7 @@ void opt_shift_track_handler() { void opt_reverse_track_handler() { if (opt_reverse == 2) { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { // oled_display.textbox("REVERSE ", "MD TRACKS"); for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { mcl_seq.md_tracks[n].reverse(); @@ -1157,7 +1166,7 @@ void opt_reverse_track_handler() { } if (opt_reverse == 1) { - if (SeqPage::midi_device == &MD) { + if (opt_midi_device_capture == &MD) { // oled_display.textbox("REVERSE ", "TRACK"); mcl_seq.md_tracks[last_md_track].reverse(); } @@ -1197,6 +1206,8 @@ bool SeqPage::md_track_change_check() { void SeqPage::loop() { + opt_midi_device_capture = midi_device; + if (last_midi_state != MidiClock.state) { last_midi_state = MidiClock.state; DEBUG_DUMP("hii") @@ -1206,7 +1217,7 @@ void SeqPage::loop() { if (show_seq_menu) { seq_menu_page.loop(); - if (midi_device != &MD && opt_trackid > NUM_EXT_TRACKS) { + if (opt_midi_device_capture != &MD && opt_trackid > NUM_EXT_TRACKS) { // lock trackid to [1..4] opt_trackid = min(opt_trackid, NUM_EXT_TRACKS); seq_menu_value_encoder.cur = opt_trackid; diff --git a/avr/cores/megacommand/MCL/SeqPage.h b/avr/cores/megacommand/MCL/SeqPage.h index 8be0863ff..a6d79f966 100644 --- a/avr/cores/megacommand/MCL/SeqPage.h +++ b/avr/cores/megacommand/MCL/SeqPage.h @@ -6,6 +6,7 @@ #include "GUI.h" #include "midi-common.h" #include "Elektron.h" +#include "shared.h" #define REC_EVENT_TRIG 0 #define REC_EVENT_CC 1 @@ -20,7 +21,7 @@ class SeqPageMidiEvents : public MidiCallback, public ClockCallback { void onMidiStartCallback(); }; - +extern MidiDevice *opt_midi_device_capture; extern void pattern_len_handler(EncoderParent *enc); extern uint8_t opt_trackid; @@ -63,7 +64,9 @@ extern void opt_paste_page_handler(); extern void opt_clear_step_handler(); extern void seq_menu_handler(); +extern uint8_t copy_mask; +extern MusicalNotes number_to_note; class MidiDevice; @@ -99,7 +102,6 @@ class SeqPage : public LightPage { static uint32_t last_md_model; static bool recording; - static uint16_t mute_mask; bool display_page_index = true; diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index 876e8ef9a..cd0cde79b 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -38,17 +38,19 @@ void SeqPtcPage::setup() { SeqPage::setup(); init_poly(); midi_events.setup_callbacks(); - octs[0] = 1; + octs[0] = 0; octs[1] = 1; fine_tunes[0] = 32; fine_tunes[1] = 32; memset(dev_note_masks, 0, sizeof(dev_note_masks)); memset(dev_note_channels, 17, sizeof(dev_note_channels)); memset(note_mask, 0, sizeof(note_mask)); + config_encoders(); isSetup = true; } void SeqPtcPage::cleanup() { SeqPage::cleanup(); + last_midi_device = midi_device; params_reset(); } void SeqPtcPage::config_encoders() { @@ -85,6 +87,7 @@ void SeqPtcPage::init_poly() { void SeqPtcPage::init() { DEBUG_PRINT_FN(); + if (last_midi_device != nullptr) { midi_device = last_midi_device; } SeqPage::init(); seq_menu_page.menu.enable_entry(SEQ_MENU_DEVICE, true); seq_menu_page.menu.enable_entry(SEQ_MENU_TRACK, true); @@ -162,6 +165,7 @@ void SeqPtcPage::loop() { } uint8_t SeqPtcPage::find_arp_track(uint8_t channel_event) { uint8_t track = last_md_track; + if (IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track)) { channel_event = POLY_EVENT; } if (channel_event == POLY_EVENT) { uint16_t mask = mcl_cfg.poly_mask; uint8_t n = 0; @@ -405,38 +409,21 @@ uint8_t SeqPtcPage::get_machine_pitch(uint8_t track, uint8_t note_num, return min(machine_pitch, 127); } -void SeqPtcPage::trig_md(uint8_t note_num, uint8_t track_number, - uint8_t fine_tune, MidiUartParent *uart_) { +void SeqPtcPage::trig_md(uint8_t note_num, uint8_t track_number, uint8_t channel_event, uint8_t fine_tune, MidiUartParent *uart_) { if (track_number == 255) { track_number = last_md_track; } - uint8_t next_track = get_next_voice(note_num, track_number, CTRL_EVENT); + uint8_t next_track = get_next_voice(note_num, track_number, channel_event); uint8_t machine_pitch = get_machine_pitch(next_track, note_num, fine_tune); if (machine_pitch == 255) { return; } + MD.setTrackParam(next_track, 0, machine_pitch, uart_); MD.triggerTrack(next_track, 127, uart_); - if ((recording) && (MidiClock.state == 2)) { - reset_undo(); - mcl_seq.md_tracks[next_track].record_track(127); - mcl_seq.md_tracks[next_track].record_track_pitch(machine_pitch); - } -} + mixer_page.trig(next_track); -void SeqPtcPage::trig_md_fromext(uint8_t note_num, uint8_t channel_event) { - uint8_t next_track = get_next_voice(note_num, last_md_track, channel_event); - uint8_t machine_pitch = get_machine_pitch(next_track, note_num); - if (machine_pitch == 255) { - return; - } - if (mcl.currentPage() == SEQ_STEP_PAGE && channel_event == CTRL_EVENT) { - seq_step_page.pitch_param = note_num; - // get_note_from_machine_pitch(machine_pitch); - } - MD.setTrackParam(next_track, 0, machine_pitch); - MD.triggerTrack(next_track, 127); if ((recording) && (MidiClock.state == 2)) { reset_undo(); mcl_seq.md_tracks[next_track].record_track(127); @@ -489,8 +476,9 @@ void SeqPtcPage::recalc_notemask() { void SeqPtcPage::draw_popup_transpose() { char str[] = "KEY: "; - mcl_gui.put_value_at(transpose, str + 5); + strcpy(str + 5, number_to_note.notes_upper[transpose]); MD.popup_text(str); + oled_display.textbox(str, ""); } void SeqPtcPage::draw_popup_octave() { @@ -536,7 +524,7 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { bool is_poly = IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track); channel_event = is_poly ? POLY_EVENT : CTRL_EVENT; } else { - note += MIDI_NOTE_C1; +// note += MIDI_NOTE_C1; } uint8_t msg[] = {MIDI_NOTE_ON | (is_md ? last_md_track : last_ext_track), note, 127}; @@ -771,10 +759,7 @@ void SeqPtcMidiEvents::note_on(uint8_t *msg, uint8_t channel_event) { pitch = seq_ptc_page.process_ext_event(note_num, note_on, channel); uint8_t n = seq_ptc_page.find_arp_track(channel_event); - - if (channel_event == CTRL_EVENT) { - arp_page.track_update(n); - } + arp_page.track_update(n); seq_ptc_page.render_arp(false, SeqPage::midi_device, n); @@ -783,7 +768,11 @@ void SeqPtcMidiEvents::note_on(uint8_t *msg, uint8_t channel_event) { ArpSeqTrack *arp_track = &mcl_seq.md_arp_tracks[n]; if (!arp_track->enabled || (MidiClock.state != 2)) { - seq_ptc_page.trig_md_fromext(pitch, channel_event); + seq_ptc_page.trig_md(pitch, n, channel_event); + if (mcl.currentPage() == SEQ_STEP_PAGE && channel_event == CTRL_EVENT) { + seq_step_page.pitch_param = pitch; + } + } return; @@ -1021,6 +1010,7 @@ void SeqPtcMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { (track_param < 8 && MD.kit.models[n] == MD.kit.models[track])) { MD.setTrackParam(n, track_param, value, nullptr, true); display_polylink = 1; + if (mcl.currentPage() == MIXER_PAGE) { SET_BIT16(mixer_page.redraw_mask, n); } } } // in_sysex = 0; diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index 5ce462a39..ad4f676c0 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -59,6 +59,7 @@ class SeqPtcPage : public SeqPage, public ClockCallback { uint8_t fine_tunes[NUM_DEVS]; uint8_t find_arp_track(uint8_t channel_event); + MidiDevice *last_midi_device = nullptr; SeqPtcMidiEvents midi_events; SeqPtcPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, @@ -71,9 +72,8 @@ class SeqPtcPage : public SeqPage, public ClockCallback { uint8_t get_next_voice(uint8_t pitch, uint8_t track_number, uint8_t channel_event); uint8_t calc_scale_note(uint8_t note_num, bool padded = false); - void trig_md(uint8_t note_num, uint8_t track_number = 255, + void trig_md(uint8_t note_num, uint8_t track_number = 255, uint8_t channel_event = CTRL_EVENT, uint8_t fine_tune = 255, MidiUartParent *uart_ = nullptr); - void trig_md_fromext(uint8_t note_num, uint8_t channel_event); void note_on_ext(uint8_t note_num, uint8_t velocity, uint8_t track_number = 255, MidiUartParent *uart_ = nullptr); diff --git a/avr/cores/megacommand/MCL/SeqStepPage.cpp b/avr/cores/megacommand/MCL/SeqStepPage.cpp index 0222ececb..acea62933 100644 --- a/avr/cores/megacommand/MCL/SeqStepPage.cpp +++ b/avr/cores/megacommand/MCL/SeqStepPage.cpp @@ -137,7 +137,6 @@ void SeqStepPage::display() { // uint8_t base = tuning->base; uint8_t note_num = seq_param4.cur; // + base; - MusicalNotes number_to_note; uint8_t note = note_num - (note_num / 12) * 12; uint8_t oct = note_num / 12; @@ -170,7 +169,7 @@ void SeqStepPage::display() { MidiUartParent::handle_midi_lock = _midi_lock_tmp; SeqPage::display(); - if (mcl_gui.show_encoder_value(&seq_param2) && + if (md_micro && mcl_gui.show_encoder_value(&seq_param2) && (note_interface.notes_count_on() > 0) && (!show_seq_menu) && (!recording)) { @@ -252,8 +251,7 @@ void SeqStepPage::loop() { if (machine_pitch != MD.kit.params[last_md_track][0]) { active_track.set_track_pitch(step, machine_pitch); - seq_step_page.encoders_used_clock[3] = - slowclock; // indicate that encoder has changed. + seq_step_page.encoders_used_clock[3] = slowclock; // indicate that encoder has changed. } } } @@ -407,13 +405,11 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { } } else if (event->mask == EVENT_BUTTON_RELEASED) { disable_md_micro(); + show_pitch = false; if (IS_BIT_SET16(ignore_release, track)) { CLEAR_BIT16(ignore_release, track); return; } - if (last_md_track < 15) { - show_pitch = false; - } if (step >= active_track.length) { return true; } @@ -425,11 +421,11 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { TRIG_HOLD_TIME) { reset_undo(); active_track.set_step(step, mask_type, false); - if (mask_type == MASK_PATTERN) { + //if (mask_type == MASK_PATTERN && !active_track.steps[step].locks) { active_track.steps[step].cond_id = 0; active_track.steps[step].cond_plock = false; active_track.timing[step] = active_track.get_timing_mid(); - } + //} } } return true; @@ -482,7 +478,7 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { } } send_locks(step); - break; + return true; } } @@ -495,13 +491,14 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { disable_md_micro(); } else if (trig_interface.is_key_down(MDX_KEY_SCALE)) { opt_copy_page_handler_cb(); + page_copy = 1; trig_interface.ignoreNextEvent(MDX_KEY_SCALE); } else { // Track copy opt_copy = recording ? 2 : 1; opt_copy_track_handler_cb(); } - break; + return true; } case MDX_KEY_PASTE: { // Note paste @@ -511,6 +508,7 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { disable_md_micro(); send_locks(step); } else if (trig_interface.is_key_down(MDX_KEY_SCALE)) { + if (!page_copy || (opt_undo != 255)) { break; } opt_paste_page_handler(); trig_interface.ignoreNextEvent(MDX_KEY_SCALE); } else { @@ -518,7 +516,7 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { opt_paste = recording ? 2 : 1; opt_paste_track_handler(); } - break; + return true; } case MDX_KEY_CLEAR: { // Note clear @@ -531,6 +529,7 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { disable_md_micro(); last_step = step; } else if (trig_interface.is_key_down(MDX_KEY_SCALE)) { + page_copy = 1; opt_clear_page_handler(); trig_interface.ignoreNextEvent(MDX_KEY_SCALE); } else { @@ -538,7 +537,7 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { opt_clear = recording ? 2 : 1; opt_clear_track_handler(); } - break; + return true; } case MDX_KEY_NO: { if (mask_type != MASK_PATTERN) { @@ -553,7 +552,7 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { } } } - break; + return true; } case MDX_KEY_BANKB: { if (trig_interface.is_key_down(MDX_KEY_FUNC)) { @@ -563,8 +562,8 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { mask_type = MASK_LOCK; } config_mask_info(false); + return true; } - break; } case MDX_KEY_BANKC: { if (trig_interface.is_key_down(MDX_KEY_FUNC)) { @@ -574,8 +573,8 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { mask_type = MASK_MUTE; } config_mask_info(false); + return true; } - break; } case MDX_KEY_BANKD: { @@ -586,8 +585,8 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { mask_type = MASK_SLIDE; } config_mask_info(false); + return true; } - break; } } if (step != 255) { @@ -596,28 +595,27 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { active_track.send_parameter_locks(step, true); reset_on_release = true; MD.triggerTrack(last_md_track, 127); - break; + return true; } case MDX_KEY_UP: { seq_param1.cur += 1; - break; + return true; } case MDX_KEY_DOWN: { seq_param1.cur -= 1; - break; + return true; } case MDX_KEY_LEFT: { seq_param2.cur -= 1; - break; + return true; } case MDX_KEY_RIGHT: { seq_param2.cur += 1; - break; + return true; } } } - return true; } } /* diff --git a/avr/cores/megacommand/MCL/SeqStepPage.h b/avr/cores/megacommand/MCL/SeqStepPage.h index e9c195d70..9bd5cb418 100644 --- a/avr/cores/megacommand/MCL/SeqStepPage.h +++ b/avr/cores/megacommand/MCL/SeqStepPage.h @@ -20,6 +20,7 @@ class SeqStepPage : public SeqPage { bool reset_on_release = false; bool update_params_queue; bool prepare = false; + bool page_copy = 0; uint8_t pitch_param; uint16_t ignore_release; diff --git a/avr/cores/megacommand/MCL/SeqTrack.cpp b/avr/cores/megacommand/MCL/SeqTrack.cpp index 3771e307a..e605c1895 100644 --- a/avr/cores/megacommand/MCL/SeqTrack.cpp +++ b/avr/cores/megacommand/MCL/SeqTrack.cpp @@ -191,6 +191,7 @@ bool SeqTrack::conditional(uint8_t condition) { if (iterations_8 == 8) { send_note = true; } + break; case 5: if (iterations_5 == 5) { send_note = true; diff --git a/avr/cores/megacommand/MCL/SeqTrack.h b/avr/cores/megacommand/MCL/SeqTrack.h index 44109a442..c74d31afb 100644 --- a/avr/cores/megacommand/MCL/SeqTrack.h +++ b/avr/cores/megacommand/MCL/SeqTrack.h @@ -81,6 +81,8 @@ class SeqTrackBase { uint8_t mod12_counter; uint8_t count_down; + bool cache_loaded : 4; + bool load_sound : 4; SeqTrackBase() { active = EMPTY_TRACK_TYPE; record_mutes = false; } @@ -114,6 +116,9 @@ class SeqTrackBase { ALWAYS_INLINE() void reset() { mod12_counter = -1; step_count = 0; + count_down = 0; + cache_loaded = 0; + load_sound = 0; } void toggle_mute() { mute_state = !mute_state; } @@ -281,7 +286,6 @@ class SeqTrack : public SeqTrackBase { SeqTrack() { reset(); } ALWAYS_INLINE() void reset() { - count_down = 0; cur_event_idx = 0; iterations_5 = 1; iterations_6 = 1; diff --git a/avr/cores/megacommand/MCL/SoundBrowserPage.cpp b/avr/cores/megacommand/MCL/SoundBrowserPage.cpp index 54dd0f6f5..e568ad65f 100644 --- a/avr/cores/megacommand/MCL/SoundBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/SoundBrowserPage.cpp @@ -38,13 +38,16 @@ void SoundBrowserPage::init() { void SoundBrowserPage::save_sound() { MDSound sound; - char sound_name[9] = " "; - grid_page.prepare(); - memcpy(sound_name, MD.kit.name, 4); + char sound_name[8]; + uint8_t l = min(strlen(MD.kit.name),4); + memcpy(sound_name, MD.kit.name, l); const char *tmp = getMDMachineNameShort(MD.kit.get_model(MD.currentTrack), 2); - copyMachineNameShort(tmp, sound_name + 4); - sound_name[6] = '\0'; + if (tmp) { + copyMachineNameShort(tmp, sound_name + l + 1); + } + sound_name[l+3] = '\0'; + sound_name[l] = '_'; if (mcl_gui.wait_for_input(sound_name, "Sound Name", 8)) { char temp_entry[FILE_ENTRY_SIZE]; @@ -92,8 +95,9 @@ void SoundBrowserPage::on_new() { } void SoundBrowserPage::on_cancel() { - if (strcmp(lwd, "/") == 0) { mcl.popPage(); return; } - _cd_up(); + //if (strcmp(lwd, "/") == 0) { mcl.popPage(); return; } + //_cd_up(); + mcl.popPage(); } void SoundBrowserPage::on_select(const char *__) { @@ -107,7 +111,6 @@ bool SoundBrowserPage::handleEvent(gui_event_t *event) { file_menu_page.menu.enable_entry(FM_NEW_FOLDER, !state); file_menu_page.menu.enable_entry(FM_DELETE, !state); // delete file_menu_page.menu.enable_entry(FM_RENAME, !state); // rename - file_menu_page.menu.enable_entry(FM_OVERWRITE, !state); file_menu_page.menu.enable_entry(FM_RECVALL, state); file_menu_page.menu.enable_entry(FM_SENDALL, state); return true; diff --git a/avr/cores/megacommand/MCL/TextInputPage.cpp b/avr/cores/megacommand/MCL/TextInputPage.cpp index d75ecfc45..ac61831e9 100644 --- a/avr/cores/megacommand/MCL/TextInputPage.cpp +++ b/avr/cores/megacommand/MCL/TextInputPage.cpp @@ -38,8 +38,9 @@ void TextInputPage::init_text(char *text_, const char *title_, uint8_t len) { max_length = len; strncpy(text, text_, len); //Replace null characeters with space, it will be added back in upon exit. + bool after = false; for (uint8_t n = 0; n < len; n++) { - if (text[n] == '\0') { text[n] = ' '; } + if (text[n] == '\0' || after) { text[n] = ' '; after = true; } } text[sizeof(text) - 1] = '\0'; cursor_position = 0; diff --git a/avr/cores/megacommand/MCL/TrigInterface.h b/avr/cores/megacommand/MCL/TrigInterface.h index 97e15ce46..961ef413e 100644 --- a/avr/cores/megacommand/MCL/TrigInterface.h +++ b/avr/cores/megacommand/MCL/TrigInterface.h @@ -80,6 +80,9 @@ class TrigInterface : public MidiSysexListenerClass { void ignoreNextEvent(uint8_t i) { SET_BIT64(ignore_next_mask, i); } + void ignoreNextEventClear(uint8_t i) { + CLEAR_BIT64(ignore_next_mask, i); + } bool on(bool clear_states = true); bool off(); diff --git a/avr/cores/megacommand/MCL/WavDesigner.cpp b/avr/cores/megacommand/MCL/WavDesigner.cpp index 03ee2769c..55780ddda 100644 --- a/avr/cores/megacommand/MCL/WavDesigner.cpp +++ b/avr/cores/megacommand/MCL/WavDesigner.cpp @@ -52,8 +52,9 @@ bool WavDesigner::render() { // Recalculate sample rate using base frequency, for sample alignment. - uint32_t n_cycle = ((floor(sample_rate / fund_freq))); - + uint32_t n_cycle = ((round(sample_rate / fund_freq))); + DEBUG_PRINTLN("n_cycle 1"); + DEBUG_PRINTLN(n_cycle); sample_rate = n_cycle * fund_freq; SineOsc sine_osc(sample_rate); diff --git a/avr/cores/megacommand/MCL/WavDesigner.h b/avr/cores/megacommand/MCL/WavDesigner.h index 51dae15ed..3af437c23 100644 --- a/avr/cores/megacommand/MCL/WavDesigner.h +++ b/avr/cores/megacommand/MCL/WavDesigner.h @@ -16,7 +16,6 @@ class WavDesigner { OscMixerPage mixer; uint32_t loop_start; uint32_t loop_end; - PageIndex last_page; WavDesigner() { for (uint8_t i = 0; i < 3; i++) { pages[i].id = i; @@ -24,7 +23,6 @@ class WavDesigner { mixer.id = MIXER_ID; pages[0].osc_waveform = 1; mixer.enc4.cur = 0; - last_page = WD_PAGE_0; } void prompt_send(); bool render(); diff --git a/avr/cores/megacommand/MCL/WavDesignerPage.cpp b/avr/cores/megacommand/MCL/WavDesignerPage.cpp index 0479369c0..b0df7aeea 100644 --- a/avr/cores/megacommand/MCL/WavDesignerPage.cpp +++ b/avr/cores/megacommand/MCL/WavDesignerPage.cpp @@ -50,10 +50,10 @@ bool WavDesignerPage::handleEvent(gui_event_t *event) { // if (show_menu) { switch (key) { case MDX_KEY_DOWN: - encoders[1]->cur -= inc; + encoders[1]->cur += inc; break; case MDX_KEY_UP: - encoders[1]->cur += inc; + encoders[1]->cur -= inc; break; case MDX_KEY_LEFT: encoders[0]->cur -= inc; diff --git a/avr/cores/megacommand/MD/MD.cpp b/avr/cores/megacommand/MD/MD.cpp index e78159017..dbebeadf4 100644 --- a/avr/cores/megacommand/MD/MD.cpp +++ b/avr/cores/megacommand/MD/MD.cpp @@ -9,11 +9,17 @@ void MDMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { uint8_t track_param; MD.parseCC(channel, param, &track, &track_param); - if (track == 255) { return; } + if (track == 255) { + return; + } if (param >= 16) { - if (track > 15) { return; } - if (track_param > 23) { return; } + if (track > 15) { + return; + } + if (track_param > 23) { + return; + } MD.kit.params[track][track_param] = value; last_md_param = track_param; } else { @@ -22,13 +28,11 @@ void MDMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { MD.kit.levels[track] = value; } } - } void MDMidiEvents::onControlChangeCallback_Midi2(uint8_t *msg) {} -void MDMidiEvents::onNoteOnCallback_Midi(uint8_t *msg) { -} +void MDMidiEvents::onNoteOnCallback_Midi(uint8_t *msg) {} void MDMidiEvents::enable_live_kit_update() { if (kitupdate_state) { @@ -153,21 +157,25 @@ void MDClass::init_grid_devices(uint8_t device_idx) { } grid_idx = 1; - gdt.init(MDFX_TRACK_TYPE, GROUP_DEV, device_idx, (SeqTrack*) &(mcl_seq.mdfx_track), 0); + gdt.init(MDFX_TRACK_TYPE, GROUP_DEV, device_idx, + (SeqTrack *)&(mcl_seq.mdfx_track), 0); add_track_to_grid(grid_idx, MDFX_TRACK_NUM, &gdt); - gdt.init(MDLFO_TRACK_TYPE, GROUP_PERF, device_idx, (SeqTrack*) &(mcl_seq.aux_tracks[0]), 0); + gdt.init(MDLFO_TRACK_TYPE, GROUP_PERF, device_idx, + (SeqTrack *)&(mcl_seq.aux_tracks[0]), 0); add_track_to_grid(grid_idx, MDLFO_TRACK_NUM, &gdt); - gdt.init(MDROUTE_TRACK_TYPE, GROUP_AUX, device_idx, (SeqTrack*) &(mcl_seq.aux_tracks[1]), 0); + gdt.init(MDROUTE_TRACK_TYPE, GROUP_AUX, device_idx, + (SeqTrack *)&(mcl_seq.aux_tracks[1]), 0); add_track_to_grid(grid_idx, MDROUTE_TRACK_NUM, &gdt); - gdt.init(MDTEMPO_TRACK_TYPE, GROUP_TEMPO, device_idx, (SeqTrack*) &(mcl_seq.aux_tracks[2]), 0); + gdt.init(MDTEMPO_TRACK_TYPE, GROUP_TEMPO, device_idx, + (SeqTrack *)&(mcl_seq.aux_tracks[2]), 0); add_track_to_grid(grid_idx, MDTEMPO_TRACK_NUM, &gdt); - gdt.init(PERF_TRACK_TYPE, GROUP_PERF, device_idx, (SeqTrack*) &(mcl_seq.aux_tracks[3]), 0); + gdt.init(PERF_TRACK_TYPE, GROUP_PERF, device_idx, + (SeqTrack *)&(mcl_seq.aux_tracks[3]), 0); add_track_to_grid(grid_idx, PERF_TRACK_NUM, &gdt); - } void MDClass::get_mutes() { @@ -203,7 +211,7 @@ bool MDClass::probe() { ((uint16_t)FW_CAP_MASTER_FX | (uint16_t)FW_CAP_TRIG_LEDS | (uint16_t)FW_CAP_UNDOKIT_SYNC | (uint16_t)FW_CAP_TONAL | (uint16_t)FW_CAP_ENHANCED_GUI | (uint16_t)FW_CAP_ENHANCED_MIDI) | - (uint16_t)FW_CAP_MACHINE_CACHE | (uint16_t)FW_CAP_UNDO_CACHE; + (uint16_t)FW_CAP_MACHINE_CACHE | (uint16_t)FW_CAP_UNDO_CACHE; while ((!get_fw_caps() || ((fw_caps & fw_caps_mask) != fw_caps_mask)) && count) { @@ -218,12 +226,12 @@ bool MDClass::probe() { return false; } - turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart1_turbo), uart); + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart1_turbo_speed), uart); mcl_gui.delay_progress(100); - // if (mcl_cfg.clock_rec == 0) { - // MidiClock.uart_clock_recv = uart; - // } + // if (mcl_cfg.clock_rec == 0) { + // MidiClock.uart_clock_recv = uart; + // } mcl_gui.delay_progress(300); getCurrentTrack(CALLBACK_TIMEOUT); getBlockingKit(0x7F); @@ -366,7 +374,8 @@ void MDClass::restore_kit_params() { void MDClass::restore_kit_param(uint8_t track, uint8_t param) { if (MD.kit.params[track][param] != MD.kit.params_orig[track][param]) { - MD.setTrackParam(track, param, MD.kit.params_orig[track][param], nullptr, true); + MD.setTrackParam(track, param, MD.kit.params_orig[track][param], nullptr, + true); } } @@ -391,20 +400,23 @@ void MDClass::setTrackParam_inline(uint8_t track, uint8_t param, uint8_t value, } else { cc += 24 + b * 24; } - if (update_kit) { kit.params[track][param] = value; } + if (update_kit) { + kit.params[track][param] = value; + } } else if (param == 32) { // MUTE cc = 12 + b; } else if (param == 33) { // LEV - if (update_kit) { kit.levels[track] = value; } + if (update_kit) { + kit.levels[track] = value; + } cc = 8 + b; } else { return; } if (update_kit) { - uart_->sendCC(channel + global.baseChannel, cc, value); - } - else { - uart_->sendPolyKeyPressure(channel + global.baseChannel, cc, value); + uart_->sendCC(channel + global.baseChannel, cc, value); + } else { + uart_->sendPolyKeyPressure(channel + global.baseChannel, cc, value); } } @@ -450,26 +462,48 @@ uint8_t MDClass::setCompressorParams(uint8_t *values, bool send) { return sendFXParams(values, MD_SET_DYNAMIX_PARAM_ID, send); } -uint8_t MDClass::sendFXParam(uint8_t param, uint8_t value, uint8_t type, - bool send) { - uint8_t data[3] = {type, param, value}; - return sendRequest(data, 3, send); +void MDClass::setFXParam(uint8_t param, uint8_t value, uint8_t type, + bool update_kit, MidiUartParent *uart_) { + + if (uart_ == nullptr) { + uart_ = uart; + } + uint8_t len = 4; + if (update_kit) { + switch (type) { + case MD_FX_ECHO: + MD.kit.delay[param] = value; + break; + case MD_FX_DYN: + MD.kit.dynamics[param] = value; + break; + case MD_FX_REV: + MD.kit.reverb[param] = value; + break; + case MD_FX_EQ: + MD.kit.eq[param] = value; + break; + } + len = 3; + } + uint8_t data[4] = {type, param, value, 0x7F}; + sendRequest(data, len); } -uint8_t MDClass::setEchoParam(uint8_t param, uint8_t value, bool send) { - return sendFXParam(param, value, MD_SET_RHYTHM_ECHO_PARAM_ID, send); +void MDClass::setEchoParam(uint8_t param, uint8_t value) { + return setFXParam(param, value, MD_SET_RHYTHM_ECHO_PARAM_ID); } -uint8_t MDClass::setReverbParam(uint8_t param, uint8_t value, bool send) { - return sendFXParam(param, value, MD_SET_GATE_BOX_PARAM_ID, send); +void MDClass::setReverbParam(uint8_t param, uint8_t value) { + return setFXParam(param, value, MD_SET_GATE_BOX_PARAM_ID); } -uint8_t MDClass::setEQParam(uint8_t param, uint8_t value, bool send) { - return sendFXParam(param, value, MD_SET_EQ_PARAM_ID, send); +void MDClass::setEQParam(uint8_t param, uint8_t value) { + return setFXParam(param, value, MD_SET_EQ_PARAM_ID); } -uint8_t MDClass::setCompressorParam(uint8_t param, uint8_t value, bool send) { - return sendFXParam(param, value, MD_SET_DYNAMIX_PARAM_ID, send); +void MDClass::setCompressorParam(uint8_t param, uint8_t value) { + return setFXParam(param, value, MD_SET_DYNAMIX_PARAM_ID); } /*** tunings ***/ @@ -668,7 +702,8 @@ void MDClass::setMachine(uint8_t track, MDMachine *machine) { uint8_t MDClass::assignMachineBulk(uint8_t track, MDMachine *machine, uint8_t level, uint8_t mode, bool send) { - DEBUG_PRINT("assign machine bulk: "); DEBUG_PRINTLN(track); + DEBUG_PRINT("assign machine bulk: "); + DEBUG_PRINTLN(track); uint8_t data[43] = {0x70, 0x5b}; uint8_t i = 2; data[i++] = track; @@ -718,7 +753,7 @@ void MDClass::loadMachinesCache(uint32_t track_mask, MidiUartParent *uart_) { uint8_t a = track_mask & 0x7F; uint8_t b = (track_mask >> 7) & 0x7F; uint8_t c = (track_mask >> 14) & 0x7F; - uint8_t data[5] = { 0x70, 0x62, a, b, c }; + uint8_t data[5] = {0x70, 0x62, a, b, c}; sendRequest(data, countof(data), uart_); } @@ -730,7 +765,8 @@ void MDClass::setOrigParams(uint8_t track, MDMachine *machine) { void MDClass::insertMachineInKit(uint8_t track, MDMachine *machine, bool set_level) { - DEBUG_PRINT("insert machine in kit "); DEBUG_PRINTLN(track); + DEBUG_PRINT("insert machine in kit "); + DEBUG_PRINTLN(track); MDKit *kit_ = &kit; @@ -775,13 +811,15 @@ uint8_t MDClass::sendMachine(uint8_t track, MDMachine *machine, bool send_level, uint8_t level = 255; uint8_t track_ = track; - if (track_ > 15) { track_ -= 16; } + if (track_ > 15) { + track_ -= 16; + } if ((send_level) && (kit_->levels[track_] != machine->level)) { level = machine->level; } - MD.assignMachineBulk(track, machine, level, 255, send); + bytes = MD.assignMachineBulk(track, machine, level, 255, send); return bytes; } @@ -795,7 +833,7 @@ void MDClass::muteTrack(uint8_t track, bool mute, MidiUartParent *uart_) { uint8_t channel = track >> 2; uint8_t b = track & 3; uint8_t cc = 12 + b; - uart_->sendCC(channel + global.baseChannel, cc, (uint8_t) mute); + uart_->sendCC(channel + global.baseChannel, cc, (uint8_t)mute); } void MDClass::setGlobal(uint8_t id) { @@ -1167,14 +1205,13 @@ void MDClass::updateKitParams() { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { mcl_seq.md_tracks[n].mute_state = old_mutes[n]; } - } uint16_t MDClass::sendKitParams(uint8_t *masks) { /// Ignores masks and scratchpad, and send the whole kit. MD.kit.origPosition = 0x7F; MD.kit.toSysex(); - activate_track_select(); //<-- includes waitBlocking, we need to wait for the + get_fw_caps(); //<-- includes waitBlocking, we need to wait for the // sysex message to be received before unmuting seq return 0; } diff --git a/avr/cores/megacommand/MD/MD.h b/avr/cores/megacommand/MD/MD.h index 15ca21bc2..71f9374aa 100644 --- a/avr/cores/megacommand/MD/MD.h +++ b/avr/cores/megacommand/MD/MD.h @@ -149,16 +149,15 @@ class MDClass : public ElektronDevice { uint8_t setEQParams(uint8_t *values, bool send = true); uint8_t setCompressorParams(uint8_t *values, bool send = true); - uint8_t sendFXParam(uint8_t param, uint8_t value, uint8_t type, - bool send = true); + void setFXParam(uint8_t param, uint8_t value, uint8_t type, bool update_kit = false, MidiUartParent *uart_ = nullptr); /** Set the value of an ECHO FX parameter. **/ - uint8_t setEchoParam(uint8_t param, uint8_t value, bool send = true); + void setEchoParam(uint8_t param, uint8_t value); /** Set the value of a REVERB FX parameter. **/ - uint8_t setReverbParam(uint8_t param, uint8_t value, bool send = true); + void setReverbParam(uint8_t param, uint8_t value); /** Set the value of an EQ FX parameter. **/ - uint8_t setEQParam(uint8_t param, uint8_t value, bool send = true); + void setEQParam(uint8_t param, uint8_t value); /** Set the value of a COMPRESSOR FX parameter. **/ - uint8_t setCompressorParam(uint8_t param, uint8_t value, bool send = true); + void setCompressorParam(uint8_t param, uint8_t value); /** * Get the actual PITCH value for the MIDI pitch for the given * track. If the track is melodic, this will lookup the actual PITCH diff --git a/avr/cores/megacommand/MD/MDMessages.cpp b/avr/cores/megacommand/MD/MDMessages.cpp index 57c86312f..b73ddc256 100644 --- a/avr/cores/megacommand/MD/MDMessages.cpp +++ b/avr/cores/megacommand/MD/MDMessages.cpp @@ -235,13 +235,13 @@ uint16_t MDKit::toSysex() { } uint16_t MDKit::toSysex(ElektronDataToSysexEncoder *encoder) { - if ((MidiClock.state == 2) && (MD.midi->uart->speed > 62500)) { - encoder->throttle = true; + //if ((MidiClock.state == 2) && (MD.midi->uart->speed > 62500)) { + //encoder->throttle = true; // float swing = (float) MD->swing_last / 16385->0; // encoder->throttle_mod12 = floor((swing) * 12); // DEBUG_PRINTLN(F("swing")); // DEBUG_DUMP(encoder->throttle_mod12); - } + //} encoder->stop7Bit(); encoder->begin(); encoder->pack(machinedrum_sysex_hdr, sizeof(machinedrum_sysex_hdr)); diff --git a/avr/cores/megacommand/MD/MDPattern.cpp b/avr/cores/megacommand/MD/MDPattern.cpp index 1cfb06c12..ad2e07ed1 100644 --- a/avr/cores/megacommand/MD/MDPattern.cpp +++ b/avr/cores/megacommand/MD/MDPattern.cpp @@ -156,8 +156,8 @@ uint16_t MDPattern::toSysex(ElektronDataToSysexEncoder *encoder) { isExtraPattern = patternLength > 32; if ((MidiClock.state == 2) && (MD.midi->uart->speed > 62500)) { - DEBUG_PRINTLN(F("using throttle")); - encoder->throttle = true; + //DEBUG_PRINTLN(F("using throttle")); + //encoder->throttle = true; //float swing = (float) MD.swing_last / 16385.0; //encoder.throttle_mod12 = round(swing * 12); } diff --git a/avr/cores/megacommand/MNM/MNM.cpp b/avr/cores/megacommand/MNM/MNM.cpp index cf5bb7f77..1ffa07572 100644 --- a/avr/cores/megacommand/MNM/MNM.cpp +++ b/avr/cores/megacommand/MNM/MNM.cpp @@ -49,7 +49,7 @@ bool MNMClass::probe() { connected = false; DEBUG_PRINTLN("MNM probe"); if (255 != MNM.getCurrentKit(CALLBACK_TIMEOUT)) { - turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart2_turbo), uart); + turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.uart2_turbo_speed), uart); // wait 400 ms, should be enought time to allow midiclock tempo to be // calculated before proceeding. mcl_gui.delay_progress(400); diff --git a/avr/cores/megacommand/MNM/MNMMessages.cpp b/avr/cores/megacommand/MNM/MNMMessages.cpp index a6be26679..0712ffa98 100644 --- a/avr/cores/megacommand/MNM/MNMMessages.cpp +++ b/avr/cores/megacommand/MNM/MNMMessages.cpp @@ -176,9 +176,9 @@ bool MNMKit::fromSysex(MidiClass *midi) { } uint16_t MNMKit::toSysex(ElektronDataToSysexEncoder *encoder) { - if ((MidiClock.state == 2) && (MNM.midi->uart->speed > 62500)) { - encoder->throttle = true; - } + //if ((MidiClock.state == 2) && (MNM.midi->uart->speed > 62500)) { + //encoder->throttle = true; + //} encoder->stop7Bit(); encoder->begin(); encoder->pack(monomachine_sysex_hdr, sizeof(monomachine_sysex_hdr)); diff --git a/avr/cores/megacommand/Midi/MidiSDS.cpp b/avr/cores/megacommand/Midi/MidiSDS.cpp index 57ece1b4a..c7b6f1769 100644 --- a/avr/cores/megacommand/Midi/MidiSDS.cpp +++ b/avr/cores/megacommand/Midi/MidiSDS.cpp @@ -154,6 +154,7 @@ bool MidiSDSClass::sendSyx(const char *filename, uint16_t sample_number) { if (pos >= fsize) { break; } + if (trig_interface.is_key_down(MDX_KEY_NO)) { goto cleanup; } if (++show_progress > 10) { show_progress = 0; mcl_gui.draw_progress("Sending sample", pos * 80 / fsize ,80); @@ -286,7 +287,7 @@ bool MidiSDSClass::sendSamples(bool show_progress) { for (samplesSoFar = 0; samplesSoFar < midi_sds.sampleLength; samplesSoFar += num_of_samples) { - + if (trig_interface.is_key_down(MDX_KEY_NO)) { return false; } ++show_progress_i; if (show_progress && show_progress_i == 10) { @@ -419,6 +420,7 @@ bool MidiSDSClass::recvWav(const char* filename, uint16_t sample_number) { goto recv_fail; } while(true) { + if (trig_interface.is_key_down(MDX_KEY_NO)) { goto recv_fail; } uint8_t msg = waitForMsg(2000); if (msg == 255 || msg == MIDI_SDS_CANCEL) { DEBUG_PRINTLN("sds recv abort"); @@ -513,13 +515,13 @@ bool MidiSDSClass::sendData(uint8_t *buf, uint8_t len) { uint8_t data[127] = {0xF0, 0x7E, deviceID, 0x02, packetNumber}; uint8_t checksum = 0; uint8_t n = 5; - for (int i = 1; i < 5; i++) + for (uint8_t i = 1; i < 5; i++) checksum ^= data[i]; - for (int i = 0; i < len; i++) { + for (uint8_t i = 0; i < len; i++) { data[n++] = buf[i]; checksum ^= buf[i]; } - for (int i = len; i < 120; i++) + for (uint8_t i = len; i < 120; i++) data[n++] = 0x00; data[n++] = checksum & 0x7F; data[n] = 0xF7; diff --git a/avr/cores/megacommand/Midi/MidiSDSSysex.cpp b/avr/cores/megacommand/Midi/MidiSDSSysex.cpp index a364154d4..117fa5e1c 100644 --- a/avr/cores/megacommand/Midi/MidiSDSSysex.cpp +++ b/avr/cores/megacommand/Midi/MidiSDSSysex.cpp @@ -146,16 +146,14 @@ void MidiSDSSysexListenerClass::dump_header() { my_string[1] = (midi_sds.sampleNumber % 100) / 10 + '0'; my_string[2] = (midi_sds.sampleNumber % 10) + '0'; - if ((midi_sds.sampleFormat != 8) && (midi_sds.sampleFormat != 16) && - (midi_sds.sampleFormat != 24)) { - midi_sds.sendNakMessage(); - return; - } bool overwrite = true; - if (!midi_sds.wav_file.open(my_string, overwrite, 1, sampleRate, - midi_sds.sampleFormat, midi_sds.loopType != 0x7F)) { + if ((midi_sds.sampleFormat != 8) && (midi_sds.sampleFormat != 16) && + (midi_sds.sampleFormat != 24) || (!midi_sds.wav_file.open(my_string, overwrite, 1, sampleRate, + midi_sds.sampleFormat, midi_sds.loopType != 0x7F))) { midi_sds.sendCancelMessage(); midi_sds.cancel(); + midi_sds.state = SDS_READY; + return; } if (midi_sds.loopType != 0x7F) { midi_sds.wav_file.header.smpl.init(midi_sds.wav_file.header.fmt, diff --git a/avr/cores/megacommand/Midi/MidiSysex.h b/avr/cores/megacommand/Midi/MidiSysex.h index 7bce09c0c..bb524ae96 100644 --- a/avr/cores/megacommand/Midi/MidiSysex.h +++ b/avr/cores/megacommand/Midi/MidiSysex.h @@ -111,8 +111,8 @@ class MidiSysexClass { Rb.check = false; #endif } - ALWAYS_INLINE() uint16_t get_recordLen() { return ledger[rd_cur].recordLen; } - ALWAYS_INLINE() volatile uint8_t *get_ptr() { return ledger[rd_cur].ptr; } + uint16_t get_recordLen() { return ledger[rd_cur].recordLen; } + volatile uint8_t *get_ptr() { return ledger[rd_cur].ptr; } bool avail() { return ((msg_wr != msg_rd) && ledger[msg_rd].state == SYSEX_STATE_FIN && @@ -134,14 +134,14 @@ class MidiSysexClass { } } - ALWAYS_INLINE() void startRecord() { + void startRecord() { recording = true; ledger[msg_wr].recordLen = 0; ledger[msg_wr].ptr = (Rb.ptr + Rb.wr); ledger[msg_wr].state = SYSEX_STATE_REC; } - ALWAYS_INLINE() void stopRecord() { + void stopRecord() { recording = false; ledger[msg_wr].state = SYSEX_STATE_FIN; if (is_full()) { @@ -156,7 +156,7 @@ class MidiSysexClass { } } - ALWAYS_INLINE() void putByte(uint16_t n, uint8_t c) { + void putByte(uint16_t n, uint8_t c) { uint16_t r = (uint16_t) ledger[rd_cur].ptr - (uint16_t) Rb.ptr; if (r + n > Rb.len - 1) { n = n - Rb.len; @@ -164,9 +164,9 @@ class MidiSysexClass { volatile uint8_t *dst = ledger[rd_cur].ptr + n; put_bank1(dst, c); } - ALWAYS_INLINE() void putByte(uint8_t c) { Rb.put_h_isr(c); } + void putByte(uint8_t c) { Rb.put_h_isr(c); } - ALWAYS_INLINE() uint8_t getByte(uint16_t n) { + uint8_t getByte(uint16_t n) { uint16_t r = (uint16_t) ledger[rd_cur].ptr - (uint16_t) Rb.ptr; if (r + n > Rb.len - 1) { n = n - Rb.len; @@ -175,37 +175,36 @@ class MidiSysexClass { return get_bank1(src); } - ALWAYS_INLINE() void recordByte(uint8_t c) { + void recordByte(uint8_t c) { putByte(c); ledger[msg_wr].recordLen++; } void initSysexListeners() { - for (int i = 0; i < NUM_SYSEX_SLAVES; i++) + for (uint8_t i = 0; i < NUM_SYSEX_SLAVES; i++) listeners[i] = NULL; } bool addSysexListener(MidiSysexListenerClass *listener) { - for (int i = 0; i < NUM_SYSEX_SLAVES; i++) { + for (uint8_t i = 0; i < NUM_SYSEX_SLAVES; i++) { 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; } + } return false; } void removeSysexListener(MidiSysexListenerClass *listener) { - for (int i = 0; i < NUM_SYSEX_SLAVES; i++) { + for (uint8_t i = 0; i < NUM_SYSEX_SLAVES; i++) { if (listeners[i] == listener) listeners[i] = NULL; } } - ALWAYS_INLINE() bool isListenerActive(MidiSysexListenerClass *listener) { + bool isListenerActive(MidiSysexListenerClass *listener) { if (listener == NULL) return false; /* catch all */ @@ -222,12 +221,12 @@ class MidiSysexClass { return false; } - ALWAYS_INLINE() void abort() { + void abort() { recording = false; memset(&ledger[msg_wr], 0, sizeof(MidiSysexLedger)); } - ALWAYS_INLINE() void reset() { startRecord(); } + void reset() { startRecord(); } // Handled by main loop void end() { @@ -238,7 +237,7 @@ class MidiSysexClass { recvIds[1] = getByte(1); recvIds[2] = getByte(2); } - for (int i = 0; i < NUM_SYSEX_SLAVES; i++) { + for (uint8_t i = 0; i < NUM_SYSEX_SLAVES; i++) { if (isListenerActive(listeners[i])) { listeners[i]->msg_rd = rd_cur; listeners[i]->end(); @@ -247,11 +246,11 @@ class MidiSysexClass { } // Handled by interrupts - ALWAYS_INLINE() void end_immediate() { + void end_immediate() { stopRecord(); } - ALWAYS_INLINE() void handleByte(uint8_t byte) { + void handleByte(uint8_t byte) { if (recording) { //if (ledger[msg_rd].state == SYSEX_STATE_FIN && ledger[msg_rd].ptr == Rb.ptr + Rb.wr) { abort(); return; } //memset(&ledger[msg_rd],0,sizeof(MidiSysexLedger)); diff --git a/avr/cores/megacommand/ResourceManager.cpp b/avr/cores/megacommand/ResourceManager.cpp index cb7c1ad08..e4a4a1855 100644 --- a/avr/cores/megacommand/ResourceManager.cpp +++ b/avr/cores/megacommand/ResourceManager.cpp @@ -104,6 +104,7 @@ void ResourceManager::restore_menu_layout_deps() { midiclock_menu_page.set_layout(R.menu_layouts->midiclock_menu_layout); midiroute_menu_page.set_layout(R.menu_layouts->midiroute_menu_layout); midimachinedrum_menu_page.set_layout(R.menu_layouts->midimachinedrum_menu_layout); + midigeneric_menu_page.set_layout(R.menu_layouts->midigeneric_menu_layout); perf_menu_page.set_layout(R.menu_layouts->perf_menu_layout); } diff --git a/avr/cores/megacommand/main.cpp b/avr/cores/megacommand/main.cpp index 83b7fb13c..22915006a 100644 --- a/avr/cores/megacommand/main.cpp +++ b/avr/cores/megacommand/main.cpp @@ -49,43 +49,6 @@ void my_init_ram(void) { uint8_t tcnt2; void timer_init(void) { - // on the ATmega168, timer 0 is also used for fast hardware pwm - // (using phase-correct PWM would mean that timer 0 overflowed half as often - // resulting in different millis() behavior on the ATmega8 and ATmega168) -#if defined(TCCR0A) && defined(WGM01) - sbi(TCCR0A, WGM01); - sbi(TCCR0A, WGM00); -#endif - - // set timer 0 prescale factor to 64 -#if defined(__AVR_ATmega128__) - // CPU specific: different values for the ATmega128 - sbi(TCCR0, CS02); -#elif defined(TCCR0) && defined(CS01) && defined(CS00) - // this combination is for the standard atmega8 - sbi(TCCR0, CS01); - sbi(TCCR0, CS00); -#elif defined(TCCR0B) && defined(CS01) && defined(CS00) - // this combination is for the standard 168/328/1280/2560 - sbi(TCCR0B, CS01); - sbi(TCCR0B, CS00); -#elif defined(TCCR0A) && defined(CS01) && defined(CS00) - // this combination is for the __AVR_ATmega645__ series - sbi(TCCR0A, CS01); - sbi(TCCR0A, CS00); -#else -#error Timer 0 prescale factor 64 not set correctly -#endif - - // enable timer 0 overflow interrupt -#if defined(TIMSK) && defined(TOIE0) - sbi(TIMSK, TOIE0); -#elif defined(TIMSK0) && defined(TOIE0) - sbi(TIMSK0, TOIE0); -#else -#error Timer 0 overflow interrupt not set correctly -#endif - TCCR1A = _BV(WGM10); // | _BV(COM1A1) | _BV(COM1B1); TCCR1B |= _BV(CS10) | _BV(WGM12); // every cycle diff --git a/avr/cores/megacommand/memory.h b/avr/cores/megacommand/memory.h index ee121551a..8934300b6 100644 --- a/avr/cores/megacommand/memory.h +++ b/avr/cores/megacommand/memory.h @@ -179,7 +179,10 @@ FORCED_INLINE() extern inline uint8_t get_random_byte() { return (pgm_read_byte(rand_ptr++) ^ get_byte_bank1(rand_ptr) ^ slowclock); } -extern inline uint8_t get_random(uint8_t range) { return get_random_byte() % range; } +extern inline uint8_t get_random(uint8_t range) { + uint8_t randomValue = get_random_byte(); + return (uint8_t)((uint16_t)randomValue * range / 256); +} #endif// __cplusplus diff --git a/avr/cores/megacommand/resources/R.h b/avr/cores/megacommand/resources/R.h index 821477b57..c78e2ee7e 100644 --- a/avr/cores/megacommand/resources/R.h +++ b/avr/cores/megacommand/resources/R.h @@ -21,6 +21,12 @@ struct __T_icons_boot { extern const unsigned char __R_icons_device[] PROGMEM; struct __T_icons_device { + union { + unsigned char icon_turbo[0]; + char zz__icon_turbo[120]; + }; + static constexpr size_t countof_icon_turbo = 120 / sizeof(unsigned char); + static constexpr size_t sizeofof_icon_turbo = 120; union { unsigned char icon_mnm[0]; char zz__icon_mnm[120]; @@ -39,7 +45,7 @@ struct __T_icons_device { }; static constexpr size_t countof_icon_md = 120 / sizeof(unsigned char); static constexpr size_t sizeofof_icon_md = 120; - static constexpr size_t __total_size = 360; + static constexpr size_t __total_size = 480; }; extern const unsigned char __R_icons_knob[] PROGMEM; @@ -364,10 +370,10 @@ struct __T_menu_layouts { static constexpr size_t sizeofof_seq_menu_layout = 515; union { menu_t file_menu_layout[0]; - char zz__file_menu_layout[158]; + char zz__file_menu_layout[137]; }; - static constexpr size_t countof_file_menu_layout = 158 / sizeof(menu_t); - static constexpr size_t sizeofof_file_menu_layout = 158; + static constexpr size_t countof_file_menu_layout = 137 / sizeof(menu_t); + static constexpr size_t sizeofof_file_menu_layout = 137; union { menu_t mclconfig_menu_layout[0]; char zz__mclconfig_menu_layout[32]; @@ -386,6 +392,12 @@ struct __T_menu_layouts { }; static constexpr size_t countof_mdconfig_menu_layout = 53 / sizeof(menu_t); static constexpr size_t sizeofof_mdconfig_menu_layout = 53; + union { + menu_t midigeneric_menu_layout[0]; + char zz__midigeneric_menu_layout[32]; + }; + static constexpr size_t countof_midigeneric_menu_layout = 32 / sizeof(menu_t); + static constexpr size_t sizeofof_midigeneric_menu_layout = 32; union { menu_t midimachinedrum_menu_layout[0]; char zz__midimachinedrum_menu_layout[74]; @@ -418,10 +430,10 @@ struct __T_menu_layouts { static constexpr size_t sizeofof_midiport_menu_layout = 116; union { menu_t midiconfig_menu_layout[0]; - char zz__midiconfig_menu_layout[116]; + char zz__midiconfig_menu_layout[137]; }; - static constexpr size_t countof_midiconfig_menu_layout = 116 / sizeof(menu_t); - static constexpr size_t sizeofof_midiconfig_menu_layout = 116; + static constexpr size_t countof_midiconfig_menu_layout = 137 / sizeof(menu_t); + static constexpr size_t sizeofof_midiconfig_menu_layout = 137; union { menu_t rampage1_menu_layout[0]; char zz__rampage1_menu_layout[32]; @@ -452,18 +464,18 @@ struct __T_menu_layouts { }; static constexpr size_t countof_boot_menu_layout = 95 / sizeof(menu_t); static constexpr size_t sizeofof_boot_menu_layout = 95; - static constexpr size_t __total_size = 2099; + static constexpr size_t __total_size = 2131; }; extern const unsigned char __R_menu_options[] PROGMEM; struct __T_menu_options { union { menu_option_t MENU_OPTIONS[0]; - char zz__MENU_OPTIONS[1089]; + char zz__MENU_OPTIONS[1098]; }; - static constexpr size_t countof_MENU_OPTIONS = 1089 / sizeof(menu_option_t); - static constexpr size_t sizeofof_MENU_OPTIONS = 1089; - static constexpr size_t __total_size = 1089; + static constexpr size_t countof_MENU_OPTIONS = 1098 / sizeof(menu_option_t); + static constexpr size_t sizeofof_MENU_OPTIONS = 1098; + static constexpr size_t __total_size = 1098; }; extern const unsigned char __R_page_entries[] PROGMEM; diff --git a/avr/cores/megacommand/resources/R_icons_device.cpp b/avr/cores/megacommand/resources/R_icons_device.cpp index 3ceb3fcb0..2976c66bc 100644 --- a/avr/cores/megacommand/resources/R_icons_device.cpp +++ b/avr/cores/megacommand/resources/R_icons_device.cpp @@ -1,210 +1,273 @@ #include "R.h" const unsigned char __R_icons_device[] PROGMEM = { - 247, + 229, + 0, + 0, + 0, + 35, + 62, + 255, + 137, + 231, + 28, + 0, + 8, + 138, + 40, + 162, + 97, + 4, + 51, + 72, + 118, + 139, + 207, + 34, + 24, + 11, + 4, + 33, + 218, + 114, + 47, + 49, + 200, 0, + 247, + 65, + 240, + 4, + 109, + 39, + 24, + 3, + 246, + 60, + 62, + 15, + 224, + 5, + 255, + 115, + 247, + 56, 0, + 30, + 83, + 253, + 183, + 44, + 9, + 12, 0, + 176, + 192, + 41, + 187, 64, 3, - 110, + 183, 1, 224, 4, - 205, + 102, 7, 48, + 205, 28, - 155, 152, 123, + 187, 204, - 118, 18, 233, 230, - 109, + 55, 162, 147, - 191, - 4, - 30, + 0, + 111, + 55, 138, 252, 128, + 183, 0, - 255, - 114, - 47, + 99, 48, 128, + 255, 1, 192, 188, 195, - 255, 64, 7, 0, 243, + 255, 12, 192, 28, 1, - 255, 204, 51, 192, 104, + 255, 7, 240, 207, 0, - 255, 108, 28, 195, 60, + 246, 0, 190, 115, 12, - 238, - 240, - 0, + 110, + 221, 211, 18, - 246, 0, + 237, 239, 48, 207, 48, - 221, + 187, 116, 18, 0, - 155, 59, - 0, + 187, + 12, + 129, 29, - 55, - 0, + 51, + 118, + 108, 14, 207, - 125, + 251, 92, 60, - 219, 4, + 183, 3, 112, 107, - 222, - 112, - 192, + 217, + 64, 119, - 247, + 14, 6, 176, + 236, 4, - 102, 26, 216, - 221, + 219, 107, 172, 18, + 179, 174, - 155, 182, + 110, 186, 255, - 118, 119, + 237, 235, 140, - 92, - 115, + 128, + 184, + 187, 174, - 217, + 119, 193, 184, - 178, + 54, 3, 227, - 246, + 94, 26, 13, 236, + 221, 81, - 238, 107, 55, + 219, 119, - 221, 111, 220, 100, + 182, 188, - 178, 243, 119, - 110, + 77, 240, + 214, 100, - 176, 118, 119, - 43, - 146, + 5, + 114, 160, - 100, + 76, 232, - 61, + 135, 238, + 187, 190, - 216, 45, 58, 231, - 109, + 13, 2, 27, + 183, 156, - 189, 119, 112, 14, + 186, 112, - 215, 239, 31, + 237, 119, - 110, 128, 111, + 219, 239, - 221, 193, 156, 119, + 183, 102, - 186, 112, 239, + 93, 253, - 237, 100, 191, + 176, 255, - 133, 239, - 24, + 163, 0, 0, 0, 0, 0, - 39, + 4, + 255, 255, }; diff --git a/avr/cores/megacommand/resources/R_menu_layouts.cpp b/avr/cores/megacommand/resources/R_menu_layouts.cpp index 7a568ff98..5df75eaed 100644 --- a/avr/cores/megacommand/resources/R_menu_layouts.cpp +++ b/avr/cores/megacommand/resources/R_menu_layouts.cpp @@ -441,39 +441,38 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 79, 85, 38, - 132, - 144, - 12, - 107, - 129, + 216, + 0, + 0, + 29, + 40, + 189, 2, - 123, 14, 70, 73, 169, - 82, + 169, 73, - 11, + 5, + 182, 72, - 109, 67, 240, - 24, + 140, 34, - 75, + 37, + 161, 2, - 66, 2, - 225, + 112, 87, 32, + 182, 219, - 118, 82, - 46, 20, - 6, + 18, 57, 23, 173, @@ -483,233 +482,243 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 41, 35, 97, - 43, - 117, + 22, 20, - 79, - 212, - 198, 87, - 173, - 34, - 44, - 97, - 41, - 127, 67, + 249, 86, 32, 65, 76, - 144, 76, - 150, - 236, - 181, - 156, - 145, + 9, + 107, + 215, + 135, + 89, 20, - 186, + 27, 21, + 161, 89, - 26, - 49, + 28, + 175, 77, - 246, 13, - 132, - 133, - 208, - 198, + 104, + 111, + 92, + 187, 76, 65, - 17, - 178, - 210, - 109, + 43, + 252, + 189, + 38, 13, + 222, 31, - 236, 23, 1, 77, - 208, - 158, + 201, + 187, + 233, 83, 82, 67, - 153, - 51, - 32, - 52, - 49, + 30, + 146, + 31, + 3, 43, - 205, - 171, - 168, - 106, + 28, + 150, + 214, + 147, 62, - 66, - 73, - 103, + 164, + 52, + 38, 44, - 10, - 7, - 16, - 49, - 24, - 1, - 219, - 66, + 118, + 242, + 132, + 28, + 5, + 53, + 115, 45, + 237, 147, - 218, 19, - 25, - 26, - 132, - 189, - 218, + 12, + 5, + 194, + 168, + 109, 25, 3, - 203, + 101, 94, - 165, + 210, 73, - 146, - 27, - 155, + 125, + 141, + 134, + 176, 84, - 96, 31, - 112, + 56, 33, - 205, - 28, + 102, + 7, 18, - 183, + 219, 77, 178, 73, + 133, 90, - 10, - 167, - 193, + 146, + 96, 147, - 182, + 219, 8, 73, 16, - 238, - 52, + 74, + 253, + 222, + 201, 32, 77, 73, - 208, - 174, - 254, - 81, - 72, + 215, + 175, + 62, + 91, + 85, + 188, + 32, + 25, + 240, + 125, + 129, + 1, + 60, + 187, + 31, + 121, + 24, + 84, + 88, + 30, + 35, + 78, + 184, 82, 79, 32, - 61, - 72, - 159, - 31, + 246, + 83, + 33, + 125, 17, 2, 9, - 44, + 176, + 31, 18, - 59, - 197, + 236, + 208, 20, - 9, - 151, + 38, 46, + 93, 88, 84, - 11, - 35, + 109, + 81, 71, - 97, + 132, 20, - 55, + 221, 57, 41, - 109, 24, + 180, 82, - 169, - 8, - 57, - 47, + 201, + 32, + 113, + 191, 80, - 248, 32, 49, + 227, 32, 70, 87, - 212, - 209, - 157, - 116, + 220, + 82, + 127, + 118, 7, - 182, 31, + 216, 10, 20, + 200, 50, - 50, - 3, + 12, 51, - 47, + 190, 92, 85, 83, - 176, 66, + 193, 17, - 82, - 158, - 13, + 72, + 169, + 54, 52, - 177, 20, + 199, 96, - 203, - 15, - 105, - 194, - 60, - 93, + 26, + 47, + 116, + 9, + 92, + 118, 11, - 184, 20, + 225, 86, 24, - 80, - 92, - 161, - 240, - 250, + 124, + 66, + 251, + 140, 5, - 169, + 22, 29, - 253, - 131, - 151, - 198, + 174, + 8, + 15, + 183, 58, - 110, - 118, + 25, + 121, + 219, 5, 31, - 214, 7, - 250, + 2, + 5, 44, 20, 14, @@ -717,13 +726,13 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 102, 41, 97, - 172, + 204, 152, 115, 112, 6, 182, - 40, + 72, 100, 41, 44, @@ -740,15 +749,15 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 71, 24, 67, - 188, + 220, 181, 9, 186, 220, 77, 79, - 102, - 246, + 230, + 1, 126, 29, 49, @@ -759,7 +768,7 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 225, 73, 78, - 135, + 167, 39, 18, 2, @@ -778,10 +787,10 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 20, 135, 24, - 122, + 154, 172, 83, - 166, + 177, 252, 85, 82, @@ -811,8 +820,8 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 68, 10, 102, - 57, - 144, + 153, + 98, 172, 42, 136, @@ -822,209 +831,220 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 96, 84, 197, - 65, - 235, + 76, + 224, 98, - 250, - 54, + 77, + 5, + 183, 41, - 222, 56, 189, - 16, + 132, 194, - 92, + 23, 189, - 250, + 62, 26, 32, - 232, - 98, + 186, + 109, 70, - 86, + 21, 162, + 131, 97, - 12, 34, - 112, - 152, - 97, + 28, + 184, + 24, 59, - 133, - 47, - 199, + 97, + 79, + 113, 36, - 68, - 57, + 206, + 100, 186, - 182, + 109, 210, 71, + 128, 20, - 3, + 218, 37, - 104, 252, - 65, + 16, 6, - 96, + 88, 20, - 56, + 12, 35, - 0, - 195, + 104, + 120, + 193, 35, 96, 20, - 55, + 56, 38, + 0, + 246, + 88, + 40, + 216, + 76, + 24, + 29, + 39, + 206, 3, - 57, - 38, - 184, - 136, + 59, + 109, + 157, 65, - 71, - 107, - 242, - 76, - 70, - 107, + 160, + 27, + 230, + 55, + 91, + 192, 75, - 231, - 45, - 212, - 168, + 150, + 7, + 234, + 189, 1, - 253, - 13, + 126, + 66, 65, 85, 88, - 141, + 198, 31, 83, - 159, + 207, 41, 97, 103, - 101, + 178, 101, 34, - 195, + 225, 31, - 198, - 50, - 164, - 194, - 165, - 218, - 65, + 219, + 153, + 185, 97, - 232, - 121, + 186, + 109, + 65, + 118, + 116, + 142, 74, - 81, - 189, - 131, - 180, + 40, + 210, + 193, + 233, + 164, 25, - 72, - 203, - 176, + 235, + 88, 19, - 182, - 252, - 198, + 74, + 104, + 24, 2, - 89, - 44, - 200, - 46, + 197, + 110, + 133, + 221, + 221, 26, - 232, - 158, + 179, 65, - 214, - 139, - 129, + 26, + 160, + 208, 129, - 62, - 82, - 21, - 176, - 183, - 236, + 42, + 94, + 86, + 74, + 204, + 29, 27, + 128, 125, - 5, - 147, + 178, 41, + 105, 29, - 72, - 160, - 108, + 213, + 13, + 129, 62, - 12, - 78, - 104, - 193, + 137, + 136, + 216, 101, - 97, + 44, 136, - 19, + 34, + 113, 0, - 141, 66, - 161, - 96, + 172, + 182, 14, - 225, + 28, 79, 83, - 184, - 97, + 44, + 205, 80, - 52, - 134, - 49, - 164, - 140, - 150, + 48, + 73, + 212, + 70, + 146, + 193, + 222, 127, - 241, 68, 70, 85, - 138, - 68, - 64, - 161, - 90, + 49, + 89, + 72, + 214, + 11, 169, - 61, - 237, - 117, - 25, + 83, + 2, + 174, + 78, + 176, 75, - 128, 20, - 196, + 24, 28, - 181, - 221, + 150, + 253, 88, - 169, - 112, - 203, - 33, - 112, - 169, + 13, + 172, + 89, 0, + 11, + 169, + 128, 0, 0, 0, 0, - 39, + 1, + 63, 255, }; diff --git a/avr/cores/megacommand/resources/R_menu_options.cpp b/avr/cores/megacommand/resources/R_menu_options.cpp index b4379ad48..8700bd812 100644 --- a/avr/cores/megacommand/resources/R_menu_options.cpp +++ b/avr/cores/megacommand/resources/R_menu_options.cpp @@ -403,76 +403,78 @@ const unsigned char __R_menu_options[] PROGMEM = { 32, 41, 71, - 65, + 67, 8, 211, 123, - 65, + 67, 35, 35, 6, - 66, + 68, 195, 71, - 104, - 148, - 65, - 148, 176, - 67, - 26, - 118, - 5, 68, 17, - 14, - 6, - 68, - 65, - 165, - 7, - 30, - 8, - 148, - 45, 105, - 8, + 4, + 3, + 66, 148, - 54, + 11, + 78, + 66, + 148, + 13, 70, + 131, 26, - 12, + 7, 10, - 104, + 245, 16, - 65, 148, - 216, + 108, 71, - 35, + 17, + 28, 9, - 48, - 67, - 161, + 65, + 131, + 10, + 144, + 65, + 99, + 11, + 17, + 5, + 193, + 107, 104, + 66, 95, - 216, + 118, + 65, 116, - 13, + 29, 66, 135, 152, 67, - 97, + 100, 116, 176, - 98, - 192, + 8, + 97, + 128, + 40, + 12, 0, 0, 0, 0, - 1, - 63, + 0, + 19, 255, }; diff --git a/avr/cores/megacommand/resources/R_page_entries.cpp b/avr/cores/megacommand/resources/R_page_entries.cpp index 6a8bad035..ad92cc649 100644 --- a/avr/cores/megacommand/resources/R_page_entries.cpp +++ b/avr/cores/megacommand/resources/R_page_entries.cpp @@ -33,7 +33,7 @@ const unsigned char __R_page_entries[] PROGMEM = { 96, 42, 123, - 40, + 41, 2, 22, 109, diff --git a/avr/cores/megacommand/uzlib/adler32.c b/avr/cores/megacommand/uzlib/adler32.c deleted file mode 100644 index 5ee7b6cf8..000000000 --- a/avr/cores/megacommand/uzlib/adler32.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Adler-32 checksum - * - * Copyright (c) 2003 by Joergen Ibsen / Jibz - * All Rights Reserved - * - * http://www.ibsensoftware.com/ - * - * This software is provided 'as-is', without any express - * or implied warranty. In no event will the authors be - * held liable for any damages arising from the use of - * this software. - * - * Permission is granted to anyone to use this software - * for any purpose, including commercial applications, - * and to alter it and redistribute it freely, subject to - * the following restrictions: - * - * 1. The origin of this software must not be - * misrepresented; you must not claim that you - * wrote the original software. If you use this - * software in a product, an acknowledgment in - * the product documentation would be appreciated - * but is not required. - * - * 2. Altered source versions must be plainly marked - * as such, and must not be misrepresented as - * being the original software. - * - * 3. This notice may not be removed or altered from - * any source distribution. - */ - -/* - * Adler-32 algorithm taken from the zlib source, which is - * Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler - */ - -#include "tinf.h" - -#define A32_BASE 65521 -#define A32_NMAX 5552 - -uint32_t uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum /* 1 */) -{ - const unsigned char *buf = (const unsigned char *)data; - - unsigned int s1 = prev_sum & 0xffff; - unsigned int s2 = prev_sum >> 16; - - while (length > 0) - { - int k = length < A32_NMAX ? length : A32_NMAX; - int i; - - for (i = k / 16; i; --i, buf += 16) - { - s1 += buf[0]; s2 += s1; s1 += buf[1]; s2 += s1; - s1 += buf[2]; s2 += s1; s1 += buf[3]; s2 += s1; - s1 += buf[4]; s2 += s1; s1 += buf[5]; s2 += s1; - s1 += buf[6]; s2 += s1; s1 += buf[7]; s2 += s1; - - s1 += buf[8]; s2 += s1; s1 += buf[9]; s2 += s1; - s1 += buf[10]; s2 += s1; s1 += buf[11]; s2 += s1; - s1 += buf[12]; s2 += s1; s1 += buf[13]; s2 += s1; - s1 += buf[14]; s2 += s1; s1 += buf[15]; s2 += s1; - } - - for (i = k % 16; i; --i) { s1 += *buf++; s2 += s1; } - - s1 %= A32_BASE; - s2 %= A32_BASE; - - length -= k; - } - - return ((uint32_t)s2 << 16) | s1; -} diff --git a/avr/cores/megacommand/uzlib/crc32.c b/avr/cores/megacommand/uzlib/crc32.c deleted file mode 100644 index 10231181a..000000000 --- a/avr/cores/megacommand/uzlib/crc32.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * CRC32 checksum - * - * Copyright (c) 1998-2003 by Joergen Ibsen / Jibz - * All Rights Reserved - * - * http://www.ibsensoftware.com/ - * - * This software is provided 'as-is', without any express - * or implied warranty. In no event will the authors be - * held liable for any damages arising from the use of - * this software. - * - * Permission is granted to anyone to use this software - * for any purpose, including commercial applications, - * and to alter it and redistribute it freely, subject to - * the following restrictions: - * - * 1. The origin of this software must not be - * misrepresented; you must not claim that you - * wrote the original software. If you use this - * software in a product, an acknowledgment in - * the product documentation would be appreciated - * but is not required. - * - * 2. Altered source versions must be plainly marked - * as such, and must not be misrepresented as - * being the original software. - * - * 3. This notice may not be removed or altered from - * any source distribution. - */ - -/* - * CRC32 algorithm taken from the zlib source, which is - * Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler - */ - -#include "tinf.h" - -static const uint32_t tinf_crc32tab[16] = { - 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, - 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, - 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, - 0xbdbdf21c -}; - -/* crc is previous value for incremental computation, 0xffffffff initially */ -uint32_t uzlib_crc32(const void *data, unsigned int length, uint32_t crc) -{ - const unsigned char *buf = (const unsigned char *)data; - unsigned int i; - - for (i = 0; i < length; ++i) - { - crc ^= buf[i]; - crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4); - crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4); - } - - // return value suitable for passing in next time, for final value invert it - return crc/* ^ 0xffffffff*/; -} diff --git a/avr/cores/megacommand/uzlib/defl_static.c b/avr/cores/megacommand/uzlib/defl_static.c deleted file mode 100644 index 522d48561..000000000 --- a/avr/cores/megacommand/uzlib/defl_static.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - -Routines in this file are based on: -Zlib (RFC1950 / RFC1951) compression for PuTTY. - -PuTTY is copyright 1997-2014 Simon Tatham. - -Portions copyright Robert de Bath, Joris van Rantwijk, Delian -Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, -Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus -Kuhn, Colin Watson, and CORE SDI S.A. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation files -(the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE -FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include -#include -#include -#include -#include "defl_static.h" - -#define snew(type) ( (type *) malloc(sizeof(type)) ) -#define snewn(n, type) ( (type *) malloc((n) * sizeof(type)) ) -#define sresize(x, n, type) ( (type *) realloc((x), (n) * sizeof(type)) ) -#define sfree(x) ( free((x)) ) - -#ifndef FALSE -#define FALSE 0 -#define TRUE (!FALSE) -#endif - -/* ---------------------------------------------------------------------- - * Zlib compression. We always use the static Huffman tree option. - * Mostly this is because it's hard to scan a block in advance to - * work out better trees; dynamic trees are great when you're - * compressing a large file under no significant time constraint, - * but when you're compressing little bits in real time, things get - * hairier. - * - * I suppose it's possible that I could compute Huffman trees based - * on the frequencies in the _previous_ block, as a sort of - * heuristic, but I'm not confident that the gain would balance out - * having to transmit the trees. - */ - -void outbits(struct Outbuf *out, unsigned long bits, int nbits) -{ - assert(out->noutbits + nbits <= 32); - out->outbits |= bits << out->noutbits; - out->noutbits += nbits; - while (out->noutbits >= 8) { - if (out->outlen >= out->outsize) { - out->outsize = out->outlen + 64; - out->outbuf = sresize(out->outbuf, out->outsize, unsigned char); - } - out->outbuf[out->outlen++] = (unsigned char) (out->outbits & 0xFF); - out->outbits >>= 8; - out->noutbits -= 8; - } -} - -static const unsigned char mirrorbytes[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -}; - -typedef struct { - uint8_t extrabits; - uint8_t min, max; -} len_coderecord; - -typedef struct { - uint8_t code, extrabits; - uint16_t min, max; -} dist_coderecord; - -#define TO_LCODE(x, y) x - 3, y - 3 -#define FROM_LCODE(x) (x + 3) - -static const len_coderecord lencodes[] = { - {0, TO_LCODE(3, 3)}, - {0, TO_LCODE(4, 4)}, - {0, TO_LCODE(5, 5)}, - {0, TO_LCODE(6, 6)}, - {0, TO_LCODE(7, 7)}, - {0, TO_LCODE(8, 8)}, - {0, TO_LCODE(9, 9)}, - {0, TO_LCODE(10, 10)}, - {1, TO_LCODE(11, 12)}, - {1, TO_LCODE(13, 14)}, - {1, TO_LCODE(15, 16)}, - {1, TO_LCODE(17, 18)}, - {2, TO_LCODE(19, 22)}, - {2, TO_LCODE(23, 26)}, - {2, TO_LCODE(27, 30)}, - {2, TO_LCODE(31, 34)}, - {3, TO_LCODE(35, 42)}, - {3, TO_LCODE(43, 50)}, - {3, TO_LCODE(51, 58)}, - {3, TO_LCODE(59, 66)}, - {4, TO_LCODE(67, 82)}, - {4, TO_LCODE(83, 98)}, - {4, TO_LCODE(99, 114)}, - {4, TO_LCODE(115, 130)}, - {5, TO_LCODE(131, 162)}, - {5, TO_LCODE(163, 194)}, - {5, TO_LCODE(195, 226)}, - {5, TO_LCODE(227, 257)}, - {0, TO_LCODE(258, 258)}, -}; - -static const dist_coderecord distcodes[] = { - {0, 0, 1, 1}, - {1, 0, 2, 2}, - {2, 0, 3, 3}, - {3, 0, 4, 4}, - {4, 1, 5, 6}, - {5, 1, 7, 8}, - {6, 2, 9, 12}, - {7, 2, 13, 16}, - {8, 3, 17, 24}, - {9, 3, 25, 32}, - {10, 4, 33, 48}, - {11, 4, 49, 64}, - {12, 5, 65, 96}, - {13, 5, 97, 128}, - {14, 6, 129, 192}, - {15, 6, 193, 256}, - {16, 7, 257, 384}, - {17, 7, 385, 512}, - {18, 8, 513, 768}, - {19, 8, 769, 1024}, - {20, 9, 1025, 1536}, - {21, 9, 1537, 2048}, - {22, 10, 2049, 3072}, - {23, 10, 3073, 4096}, - {24, 11, 4097, 6144}, - {25, 11, 6145, 8192}, - {26, 12, 8193, 12288}, - {27, 12, 12289, 16384}, - {28, 13, 16385, 24576}, - {29, 13, 24577, 32768}, -}; - -void zlib_literal(struct Outbuf *out, unsigned char c) -{ - if (out->comp_disabled) { - /* - * We're in an uncompressed block, so just output the byte. - */ - outbits(out, c, 8); - return; - } - - if (c <= 143) { - /* 0 through 143 are 8 bits long starting at 00110000. */ - outbits(out, mirrorbytes[0x30 + c], 8); - } else { - /* 144 through 255 are 9 bits long starting at 110010000. */ - outbits(out, 1 + 2 * mirrorbytes[0x90 - 144 + c], 9); - } -} - -void zlib_match(struct Outbuf *out, int distance, int len) -{ - const dist_coderecord *d; - const len_coderecord *l; - int i, j, k; - int lcode; - - assert(!out->comp_disabled); - - while (len > 0) { - int thislen; - - /* - * We can transmit matches of lengths 3 through 258 - * inclusive. So if len exceeds 258, we must transmit in - * several steps, with 258 or less in each step. - * - * Specifically: if len >= 261, we can transmit 258 and be - * sure of having at least 3 left for the next step. And if - * len <= 258, we can just transmit len. But if len == 259 - * or 260, we must transmit len-3. - */ - thislen = (len > 260 ? 258 : len <= 258 ? len : len - 3); - len -= thislen; - - /* - * Binary-search to find which length code we're - * transmitting. - */ - i = -1; - j = sizeof(lencodes) / sizeof(*lencodes); - while (1) { - assert(j - i >= 2); - k = (j + i) / 2; - if (thislen < FROM_LCODE(lencodes[k].min)) - j = k; - else if (thislen > FROM_LCODE(lencodes[k].max)) - i = k; - else { - l = &lencodes[k]; - break; /* found it! */ - } - } - - lcode = l - lencodes + 257; - - /* - * Transmit the length code. 256-279 are seven bits - * starting at 0000000; 280-287 are eight bits starting at - * 11000000. - */ - if (lcode <= 279) { - outbits(out, mirrorbytes[(lcode - 256) * 2], 7); - } else { - outbits(out, mirrorbytes[0xc0 - 280 + lcode], 8); - } - - /* - * Transmit the extra bits. - */ - if (l->extrabits) - outbits(out, thislen - FROM_LCODE(l->min), l->extrabits); - - /* - * Binary-search to find which distance code we're - * transmitting. - */ - i = -1; - j = sizeof(distcodes) / sizeof(*distcodes); - while (1) { - assert(j - i >= 2); - k = (j + i) / 2; - if (distance < distcodes[k].min) - j = k; - else if (distance > distcodes[k].max) - i = k; - else { - d = &distcodes[k]; - break; /* found it! */ - } - } - - /* - * Transmit the distance code. Five bits starting at 00000. - */ - outbits(out, mirrorbytes[d->code * 8], 5); - - /* - * Transmit the extra bits. - */ - if (d->extrabits) - outbits(out, distance - d->min, d->extrabits); - } -} - -void zlib_start_block(struct Outbuf *out) -{ -// outbits(out, 0x9C78, 16); - outbits(out, 1, 1); /* Final block */ - outbits(out, 1, 2); /* Static huffman block */ -} - -void zlib_finish_block(struct Outbuf *out) -{ - outbits(out, 0, 7); /* close block */ - outbits(out, 0, 7); /* Make sure all bits are flushed */ -} diff --git a/avr/cores/megacommand/uzlib/defl_static.h b/avr/cores/megacommand/uzlib/defl_static.h deleted file mode 100644 index 292734d77..000000000 --- a/avr/cores/megacommand/uzlib/defl_static.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) uzlib authors - * - * This software is provided 'as-is', without any express - * or implied warranty. In no event will the authors be - * held liable for any damages arising from the use of - * this software. - * - * Permission is granted to anyone to use this software - * for any purpose, including commercial applications, - * and to alter it and redistribute it freely, subject to - * the following restrictions: - * - * 1. The origin of this software must not be - * misrepresented; you must not claim that you - * wrote the original software. If you use this - * software in a product, an acknowledgment in - * the product documentation would be appreciated - * but is not required. - * - * 2. Altered source versions must be plainly marked - * as such, and must not be misrepresented as - * being the original software. - * - * 3. This notice may not be removed or altered from - * any source distribution. - */ - -/* This files contains type declaration and prototypes for defl_static.c. - They may be altered/distinct from the originals used in PuTTY source - code. */ - -struct Outbuf { - unsigned char *outbuf; - int outlen, outsize; - unsigned long outbits; - int noutbits; - int comp_disabled; -}; - -void outbits(struct Outbuf *out, unsigned long bits, int nbits); -void zlib_start_block(struct Outbuf *ctx); -void zlib_finish_block(struct Outbuf *ctx); -void zlib_literal(struct Outbuf *ectx, unsigned char c); -void zlib_match(struct Outbuf *ectx, int distance, int len); diff --git a/avr/cores/megacommand/uzlib/genlz77.c b/avr/cores/megacommand/uzlib/genlz77.c deleted file mode 100644 index c3dad68a7..000000000 --- a/avr/cores/megacommand/uzlib/genlz77.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * genlz77 - Generic LZ77 compressor - * - * Copyright (c) 2014 by Paul Sokolovsky - * - * This software is provided 'as-is', without any express - * or implied warranty. In no event will the authors be - * held liable for any damages arising from the use of - * this software. - * - * Permission is granted to anyone to use this software - * for any purpose, including commercial applications, - * and to alter it and redistribute it freely, subject to - * the following restrictions: - * - * 1. The origin of this software must not be - * misrepresented; you must not claim that you - * wrote the original software. If you use this - * software in a product, an acknowledgment in - * the product documentation would be appreciated - * but is not required. - * - * 2. Altered source versions must be plainly marked - * as such, and must not be misrepresented as - * being the original software. - * - * 3. This notice may not be removed or altered from - * any source distribution. - */ -#include -#include -#include -#include "uzlib.h" - -#if 0 -#define HASH_BITS 12 -#else -#define HASH_BITS data->hash_bits -#endif - -#define HASH_SIZE (1<dict_size -#endif - -#ifdef DUMP_LZTXT - -/* Counter for approximate compressed length in LZTXT mode. */ -/* Literal is counted as 1, copy as 2 bytes. */ -unsigned approx_compressed_len; - -void literal(void *data, uint8_t val) -{ - printf("L%02x # %c\n", val, (val >= 0x20 && val <= 0x7e) ? val : '?'); - approx_compressed_len++; -} - -void copy(void *data, unsigned offset, unsigned len) -{ - printf("C-%u,%u\n", offset, len); - approx_compressed_len += 2; -} - -#else - -static inline void literal(void *data, uint8_t val) -{ - zlib_literal(data, val); -} - -static inline void copy(void *data, unsigned offset, unsigned len) -{ - zlib_match(data, offset, len); -} - -#endif - diff --git a/avr/cores/megacommand/uzlib/tinf.h b/avr/cores/megacommand/uzlib/tinf.h deleted file mode 100644 index ae6e1c407..000000000 --- a/avr/cores/megacommand/uzlib/tinf.h +++ /dev/null @@ -1,3 +0,0 @@ -/* Compatibility header for the original tinf lib/older versions of uzlib. - Note: may be removed in the future, please migrate to uzlib.h. */ -#include "uzlib.h" diff --git a/avr/cores/megacommand/uzlib/tinf_compat.h b/avr/cores/megacommand/uzlib/tinf_compat.h deleted file mode 100644 index f763804bd..000000000 --- a/avr/cores/megacommand/uzlib/tinf_compat.h +++ /dev/null @@ -1,9 +0,0 @@ -/* This header contains compatibility defines for the original tinf API - and uzlib 2.x and below API. These defines are deprecated and going - to be removed in the future, so applications should migrate to new - uzlib API. */ -#define TINF_DATA struct uzlib_uncomp - -#define destSize dest_size -#define destStart dest_start -#define readSource source_read_cb diff --git a/avr/cores/megacommand/uzlib/tinfgzip.c b/avr/cores/megacommand/uzlib/tinfgzip.c deleted file mode 100644 index 22b000df9..000000000 --- a/avr/cores/megacommand/uzlib/tinfgzip.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) - * - * Copyright (c) 2003 by Joergen Ibsen / Jibz - * All Rights Reserved - * - * http://www.ibsensoftware.com/ - * - * Copyright (c) 2014-2018 by Paul Sokolovsky - * - * This software is provided 'as-is', without any express - * or implied warranty. In no event will the authors be - * held liable for any damages arising from the use of - * this software. - * - * Permission is granted to anyone to use this software - * for any purpose, including commercial applications, - * and to alter it and redistribute it freely, subject to - * the following restrictions: - * - * 1. The origin of this software must not be - * misrepresented; you must not claim that you - * wrote the original software. If you use this - * software in a product, an acknowledgment in - * the product documentation would be appreciated - * but is not required. - * - * 2. Altered source versions must be plainly marked - * as such, and must not be misrepresented as - * being the original software. - * - * 3. This notice may not be removed or altered from - * any source distribution. - */ - -#include "tinf.h" - -#define FTEXT 1 -#define FHCRC 2 -#define FEXTRA 4 -#define FNAME 8 -#define FCOMMENT 16 - -void tinf_skip_bytes(TINF_DATA *d, int num); -uint16_t tinf_get_uint16(TINF_DATA *d); - -void tinf_skip_bytes(TINF_DATA *d, int num) -{ - while (num--) uzlib_get_byte(d); -} - -uint16_t tinf_get_uint16(TINF_DATA *d) -{ - unsigned int v = uzlib_get_byte(d); - v = (uzlib_get_byte(d) << 8) | v; - return v; -} - -int uzlib_gzip_parse_header(TINF_DATA *d) -{ - unsigned char flg; - - /* -- check format -- */ - - /* check id bytes */ - if (uzlib_get_byte(d) != 0x1f || uzlib_get_byte(d) != 0x8b) return TINF_DATA_ERROR; - - /* check method is deflate */ - if (uzlib_get_byte(d) != 8) return TINF_DATA_ERROR; - - /* get flag byte */ - flg = uzlib_get_byte(d); - - /* check that reserved bits are zero */ - if (flg & 0xe0) return TINF_DATA_ERROR; - - /* -- find start of compressed data -- */ - - /* skip rest of base header of 10 bytes */ - tinf_skip_bytes(d, 6); - - /* skip extra data if present */ - if (flg & FEXTRA) - { - unsigned int xlen = tinf_get_uint16(d); - tinf_skip_bytes(d, xlen); - } - - /* skip file name if present */ - if (flg & FNAME) { while (uzlib_get_byte(d)); } - - /* skip file comment if present */ - if (flg & FCOMMENT) { while (uzlib_get_byte(d)); } - - /* check header crc if present */ - if (flg & FHCRC) - { - /*unsigned int hcrc =*/ tinf_get_uint16(d); - - // TODO: Check! -// if (hcrc != (tinf_crc32(src, start - src) & 0x0000ffff)) -// return TINF_DATA_ERROR; - } - - /* initialize for crc32 checksum */ - d->checksum_type = TINF_CHKSUM_CRC; - d->checksum = ~0; - - return TINF_OK; -} diff --git a/avr/cores/megacommand/uzlib/tinflate.c b/avr/cores/megacommand/uzlib/tinflate.c deleted file mode 100644 index d719d802a..000000000 --- a/avr/cores/megacommand/uzlib/tinflate.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) - * - * Copyright (c) 2003 by Joergen Ibsen / Jibz - * All Rights Reserved - * http://www.ibsensoftware.com/ - * - * Copyright (c) 2014-2018 by Paul Sokolovsky - * - * This software is provided 'as-is', without any express - * or implied warranty. In no event will the authors be - * held liable for any damages arising from the use of - * this software. - * - * Permission is granted to anyone to use this software - * for any purpose, including commercial applications, - * and to alter it and redistribute it freely, subject to - * the following restrictions: - * - * 1. The origin of this software must not be - * misrepresented; you must not claim that you - * wrote the original software. If you use this - * software in a product, an acknowledgment in - * the product documentation would be appreciated - * but is not required. - * - * 2. Altered source versions must be plainly marked - * as such, and must not be misrepresented as - * being the original software. - * - * 3. This notice may not be removed or altered from - * any source distribution. - */ - -#include -#include -#include "tinf.h" - -#define UZLIB_DUMP_ARRAY(heading, arr, size) \ - { \ - printf("%s", heading); \ - for (int i = 0; i < size; ++i) { \ - printf(" %d", (arr)[i]); \ - } \ - printf("\n"); \ - } - -uint32_t tinf_get_le_uint32(TINF_DATA *d); -uint32_t tinf_get_be_uint32(TINF_DATA *d); - -/* --------------------------------------------------- * - * -- uninitialized global data (static structures) -- * - * --------------------------------------------------- */ - -#ifdef RUNTIME_BITS_TABLES - -/* extra bits and base tables for length codes */ -unsigned char length_bits[30]; -unsigned short length_base[30]; - -/* extra bits and base tables for distance codes */ -unsigned char dist_bits[30]; -unsigned short dist_base[30]; - -#else - -const unsigned char length_bits[30] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, - 5, 5, 5, 5 -}; -const unsigned short length_base[30] = { - 3, 4, 5, 6, 7, 8, 9, 10, - 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, - 131, 163, 195, 227, 258 -}; - -const unsigned char dist_bits[30] = { - 0, 0, 0, 0, 1, 1, 2, 2, - 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, - 11, 11, 12, 12, 13, 13 -}; -const unsigned short dist_base[30] = { - 1, 2, 3, 4, 5, 7, 9, 13, - 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, - 4097, 6145, 8193, 12289, 16385, 24577 -}; - -#endif - -/* special ordering of code length codes */ -const unsigned char clcidx[] = { - 16, 17, 18, 0, 8, 7, 9, 6, - 10, 5, 11, 4, 12, 3, 13, 2, - 14, 1, 15 -}; - -/* ----------------------- * - * -- utility functions -- * - * ----------------------- */ - -#ifdef RUNTIME_BITS_TABLES -/* build extra bits and base tables */ -static void tinf_build_bits_base(unsigned char *bits, unsigned short *base, int delta, int first) -{ - int i, sum; - - /* build bits table */ - for (i = 0; i < delta; ++i) bits[i] = 0; - for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta; - - /* build base table */ - for (sum = first, i = 0; i < 30; ++i) - { - base[i] = sum; - sum += 1 << bits[i]; - } -} -#endif - -/* build the fixed huffman trees */ -static void tinf_build_fixed_trees(TINF_TREE *lt, TINF_TREE *dt) -{ - int i; - - /* build fixed length tree */ - for (i = 0; i < 7; ++i) lt->table[i] = 0; - - lt->table[7] = 24; - lt->table[8] = 152; - lt->table[9] = 112; - - for (i = 0; i < 24; ++i) lt->trans[i] = 256 + i; - for (i = 0; i < 144; ++i) lt->trans[24 + i] = i; - for (i = 0; i < 8; ++i) lt->trans[24 + 144 + i] = 280 + i; - for (i = 0; i < 112; ++i) lt->trans[24 + 144 + 8 + i] = 144 + i; - - /* build fixed distance tree */ - for (i = 0; i < 5; ++i) dt->table[i] = 0; - - dt->table[5] = 32; - - for (i = 0; i < 32; ++i) dt->trans[i] = i; -} - -/* given an array of code lengths, build a tree */ -static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned int num) -{ - unsigned short offs[16]; - unsigned int i, sum; - - /* clear code length count table */ - for (i = 0; i < 16; ++i) t->table[i] = 0; - - /* scan symbol lengths, and sum code length counts */ - for (i = 0; i < num; ++i) t->table[lengths[i]]++; - - #if UZLIB_CONF_DEBUG_LOG >= 2 - UZLIB_DUMP_ARRAY("codelen counts:", t->table, TINF_ARRAY_SIZE(t->table)); - #endif - - /* In the lengths array, 0 means unused code. So, t->table[0] now contains - number of unused codes. But table's purpose is to contain # of codes of - particular length, and there're 0 codes of length 0. */ - t->table[0] = 0; - - /* compute offset table for distribution sort */ - for (sum = 0, i = 0; i < 16; ++i) - { - offs[i] = sum; - sum += t->table[i]; - } - - #if UZLIB_CONF_DEBUG_LOG >= 2 - UZLIB_DUMP_ARRAY("codelen offsets:", offs, TINF_ARRAY_SIZE(offs)); - #endif - - /* create code->symbol translation table (symbols sorted by code) */ - for (i = 0; i < num; ++i) - { - if (lengths[i]) t->trans[offs[lengths[i]]++] = i; - } -} - -/* ---------------------- * - * -- decode functions -- * - * ---------------------- */ - -unsigned char uzlib_get_byte(TINF_DATA *d) -{ - /* If end of source buffer is not reached, return next byte from source - buffer. */ - if (d->source < d->source_limit) { - return *d->source++; - } - - /* Otherwise if there's callback and we haven't seen EOF yet, try to - read next byte using it. (Note: the callback can also update ->source - and ->source_limit). */ - if (d->readSource && !d->eof) { - int val = d->readSource(d); - if (val >= 0) { - return (unsigned char)val; - } - } - - /* Otherwise, we hit EOF (either from ->readSource() or from exhaustion - of the buffer), and it will be "sticky", i.e. further calls to this - function will end up here too. */ - d->eof = true; - - return 0; -} - -uint32_t tinf_get_le_uint32(TINF_DATA *d) -{ - uint32_t val = 0; - int i; - for (i = 4; i--;) { - val = val >> 8 | ((uint32_t)uzlib_get_byte(d)) << 24; - } - return val; -} - -uint32_t tinf_get_be_uint32(TINF_DATA *d) -{ - uint32_t val = 0; - int i; - for (i = 4; i--;) { - val = val << 8 | uzlib_get_byte(d); - } - return val; -} - -/* get one bit from source stream */ -static int tinf_getbit(TINF_DATA *d) -{ - unsigned int bit; - - /* check if tag is empty */ - if (!d->bitcount--) - { - /* load next tag */ - d->tag = uzlib_get_byte(d); - d->bitcount = 7; - } - - /* shift bit out of tag */ - bit = d->tag & 0x01; - d->tag >>= 1; - - return bit; -} - -/* read a num bit value from a stream and add base */ -static unsigned int tinf_read_bits(TINF_DATA *d, int num, int base) -{ - unsigned int val = 0; - - /* read num bits */ - if (num) - { - unsigned int limit = 1 << (num); - unsigned int mask; - - for (mask = 1; mask < limit; mask *= 2) - if (tinf_getbit(d)) val += mask; - } - - return val + base; -} - -/* given a data stream and a tree, decode a symbol */ -static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t) -{ - int sum = 0, cur = 0, len = 0; - - /* get more bits while code value is above sum */ - do { - - cur = 2*cur + tinf_getbit(d); - - if (++len == TINF_ARRAY_SIZE(t->table)) { - return TINF_DATA_ERROR; - } - - sum += t->table[len]; - cur -= t->table[len]; - - } while (cur >= 0); - - sum += cur; - #if UZLIB_CONF_PARANOID_CHECKS - if (sum < 0 || sum >= TINF_ARRAY_SIZE(t->trans)) { - return TINF_DATA_ERROR; - } - #endif - - return t->trans[sum]; -} - -/* given a data stream, decode dynamic trees from it */ -static int tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) -{ - /* code lengths for 288 literal/len symbols and 32 dist symbols */ - unsigned char lengths[288+32]; - unsigned int hlit, hdist, hclen, hlimit; - unsigned int i, num, length; - - /* get 5 bits HLIT (257-286) */ - hlit = tinf_read_bits(d, 5, 257); - - /* get 5 bits HDIST (1-32) */ - hdist = tinf_read_bits(d, 5, 1); - - /* get 4 bits HCLEN (4-19) */ - hclen = tinf_read_bits(d, 4, 4); - - for (i = 0; i < 19; ++i) lengths[i] = 0; - - /* read code lengths for code length alphabet */ - for (i = 0; i < hclen; ++i) - { - /* get 3 bits code length (0-7) */ - unsigned int clen = tinf_read_bits(d, 3, 0); - - lengths[clcidx[i]] = clen; - } - - /* build code length tree, temporarily use length tree */ - tinf_build_tree(lt, lengths, 19); - - /* decode code lengths for the dynamic trees */ - hlimit = hlit + hdist; - for (num = 0; num < hlimit; ) - { - int sym = tinf_decode_symbol(d, lt); - unsigned char fill_value = 0; - int lbits, lbase = 3; - - /* error decoding */ - if (sym < 0) return sym; - - switch (sym) - { - case 16: - /* copy previous code length 3-6 times (read 2 bits) */ - if (num == 0) return TINF_DATA_ERROR; - fill_value = lengths[num - 1]; - lbits = 2; - break; - case 17: - /* repeat code length 0 for 3-10 times (read 3 bits) */ - lbits = 3; - break; - case 18: - /* repeat code length 0 for 11-138 times (read 7 bits) */ - lbits = 7; - lbase = 11; - break; - default: - /* values 0-15 represent the actual code lengths */ - lengths[num++] = sym; - /* continue the for loop */ - continue; - } - - /* special code length 16-18 are handled here */ - length = tinf_read_bits(d, lbits, lbase); - if (num + length > hlimit) return TINF_DATA_ERROR; - for (; length; --length) - { - lengths[num++] = fill_value; - } - } - - #if UZLIB_CONF_DEBUG_LOG >= 2 - printf("lit code lengths (%d):", hlit); - UZLIB_DUMP_ARRAY("", lengths, hlit); - printf("dist code lengths (%d):", hdist); - UZLIB_DUMP_ARRAY("", lengths + hlit, hdist); - #endif - - #if UZLIB_CONF_PARANOID_CHECKS - /* Check that there's "end of block" symbol */ - if (lengths[256] == 0) { - return TINF_DATA_ERROR; - } - #endif - - /* build dynamic trees */ - tinf_build_tree(lt, lengths, hlit); - tinf_build_tree(dt, lengths + hlit, hdist); - - return TINF_OK; -} - -/* ----------------------------- * - * -- block inflate functions -- * - * ----------------------------- */ - -/* given a stream and two trees, inflate next chunk of output (a byte or more) */ -static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) -{ - if (d->curlen == 0) { - unsigned int offs; - int dist; - int sym = tinf_decode_symbol(d, lt); - //printf("huff sym: %02x\n", sym); - - if (d->eof) { - return TINF_DATA_ERROR; - } - - /* literal byte */ - if (sym < 256) { - TINF_PUT(d, sym); - return TINF_OK; - } - - /* end of block */ - if (sym == 256) { - return TINF_DONE; - } - - /* substring from sliding dictionary */ - sym -= 257; - if (sym >= 29) { - return TINF_DATA_ERROR; - } - - /* possibly get more bits from length code */ - d->curlen = tinf_read_bits(d, length_bits[sym], length_base[sym]); - - dist = tinf_decode_symbol(d, dt); - if (dist >= 30) { - return TINF_DATA_ERROR; - } - - /* possibly get more bits from distance code */ - offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]); - - /* calculate and validate actual LZ offset to use */ - if (d->dict_ring) { - if (offs > d->dict_size) { - return TINF_DICT_ERROR; - } - /* Note: unlike full-dest-in-memory case below, we don't - try to catch offset which points to not yet filled - part of the dictionary here. Doing so would require - keeping another variable to track "filled in" size - of the dictionary. Appearance of such an offset cannot - lead to accessing memory outside of the dictionary - buffer, and clients which don't want to leak unrelated - information, should explicitly initialize dictionary - buffer passed to uzlib. */ - - d->lzOff = d->dict_idx - offs; - if (d->lzOff < 0) { - d->lzOff += d->dict_size; - } - } else { - /* catch trying to point before the start of dest buffer */ - if (offs > d->dest - d->destStart) { - return TINF_DATA_ERROR; - } - d->lzOff = -offs; - } - } - - /* copy next byte from dict substring */ - if (d->dict_ring) { - TINF_PUT(d, d->dict_ring[d->lzOff]); - if ((unsigned)++d->lzOff == d->dict_size) { - d->lzOff = 0; - } - } else { - #if UZLIB_CONF_USE_MEMCPY - /* copy as much as possible, in one memcpy() call */ - unsigned int to_copy = d->curlen, dest_len = d->dest_limit - d->dest; - if (to_copy > dest_len) { - to_copy = dest_len; - } - memcpy(d->dest, d->dest + d->lzOff, to_copy); - d->dest += to_copy; - d->curlen -= to_copy; - return TINF_OK; - #else - d->dest[0] = d->dest[d->lzOff]; - d->dest++; - #endif - } - d->curlen--; - return TINF_OK; -} - -/* inflate next byte from uncompressed block of data */ -static int tinf_inflate_uncompressed_block(TINF_DATA *d) -{ - if (d->curlen == 0) { - unsigned int length, invlength; - - /* get length */ - length = uzlib_get_byte(d); - length += 256 * uzlib_get_byte(d); - /* get one's complement of length */ - invlength = uzlib_get_byte(d); - invlength += 256 * uzlib_get_byte(d); - /* check length */ - if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR; - - /* increment length to properly return TINF_DONE below, without - producing data at the same time */ - d->curlen = length + 1; - - /* make sure we start next block on a byte boundary */ - d->bitcount = 0; - } - - if (--d->curlen == 0) { - return TINF_DONE; - } - - unsigned char c = uzlib_get_byte(d); - TINF_PUT(d, c); - return TINF_OK; -} - -/* ---------------------- * - * -- public functions -- * - * ---------------------- */ - -/* initialize global (static) data */ -void uzlib_init(void) -{ -#ifdef RUNTIME_BITS_TABLES - /* build extra bits and base tables */ - tinf_build_bits_base(length_bits, length_base, 4, 3); - tinf_build_bits_base(dist_bits, dist_base, 2, 1); - - /* fix a special case */ - length_bits[28] = 0; - length_base[28] = 258; -#endif -} - -/* initialize decompression structure */ -void uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen) -{ - d->eof = 0; - d->bitcount = 0; - d->bfinal = 0; - d->btype = -1; - d->dict_size = dictLen; - d->dict_ring = dict; - d->dict_idx = 0; - d->curlen = 0; -} - -/* inflate next output bytes from compressed stream */ -int uzlib_uncompress(TINF_DATA *d) -{ - do { - int res; - - /* start a new block */ - if (d->btype == -1) { - int old_btype; -next_blk: - old_btype = d->btype; - /* read final block flag */ - d->bfinal = tinf_getbit(d); - /* read block type (2 bits) */ - d->btype = tinf_read_bits(d, 2, 0); - - #if UZLIB_CONF_DEBUG_LOG >= 1 - printf("Started new block: type=%d final=%d\n", d->btype, d->bfinal); - #endif - - if (d->btype == 1 && old_btype != 1) { - /* build fixed huffman trees */ - tinf_build_fixed_trees(&d->ltree, &d->dtree); - } else if (d->btype == 2) { - /* decode trees from stream */ - res = tinf_decode_trees(d, &d->ltree, &d->dtree); - if (res != TINF_OK) { - return res; - } - } - } - - /* process current block */ - switch (d->btype) - { - case 0: - /* decompress uncompressed block */ - res = tinf_inflate_uncompressed_block(d); - break; - case 1: - case 2: - /* decompress block with fixed/dynamic huffman trees */ - /* trees were decoded previously, so it's the same routine for both */ - res = tinf_inflate_block_data(d, &d->ltree, &d->dtree); - break; - default: - return TINF_DATA_ERROR; - } - - if (res == TINF_DONE && !d->bfinal) { - /* the block has ended (without producing more data), but we - can't return without data, so start procesing next block */ - goto next_blk; - } - - if (res != TINF_OK) { - return res; - } - - } while (d->dest < d->dest_limit); - - return TINF_OK; -} - -/* inflate next output bytes from compressed stream, updating - checksum, and at the end of stream, verify it */ -int uzlib_uncompress_chksum(TINF_DATA *d) -{ - int res; - unsigned char *data = d->dest; - - res = uzlib_uncompress(d); - - if (res < 0) return res; - - switch (d->checksum_type) { - - case TINF_CHKSUM_ADLER: - d->checksum = uzlib_adler32(data, d->dest - data, d->checksum); - break; - - case TINF_CHKSUM_CRC: - d->checksum = uzlib_crc32(data, d->dest - data, d->checksum); - break; - } - - if (res == TINF_DONE) { - unsigned int val; - - switch (d->checksum_type) { - - case TINF_CHKSUM_ADLER: - val = tinf_get_be_uint32(d); - if (d->checksum != val) { - return TINF_CHKSUM_ERROR; - } - break; - - case TINF_CHKSUM_CRC: - val = tinf_get_le_uint32(d); - if (~d->checksum != val) { - return TINF_CHKSUM_ERROR; - } - // Uncompressed size. TODO: Check - val = tinf_get_le_uint32(d); - break; - } - } - - return res; -} diff --git a/avr/cores/megacommand/uzlib/tinfzlib.c b/avr/cores/megacommand/uzlib/tinfzlib.c deleted file mode 100644 index 5cb8852fc..000000000 --- a/avr/cores/megacommand/uzlib/tinfzlib.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) - * - * Copyright (c) 2003 by Joergen Ibsen / Jibz - * All Rights Reserved - * - * http://www.ibsensoftware.com/ - * - * Copyright (c) 2014-2018 by Paul Sokolovsky - * - * This software is provided 'as-is', without any express - * or implied warranty. In no event will the authors be - * held liable for any damages arising from the use of - * this software. - * - * Permission is granted to anyone to use this software - * for any purpose, including commercial applications, - * and to alter it and redistribute it freely, subject to - * the following restrictions: - * - * 1. The origin of this software must not be - * misrepresented; you must not claim that you - * wrote the original software. If you use this - * software in a product, an acknowledgment in - * the product documentation would be appreciated - * but is not required. - * - * 2. Altered source versions must be plainly marked - * as such, and must not be misrepresented as - * being the original software. - * - * 3. This notice may not be removed or altered from - * any source distribution. - */ - -#include "tinf.h" - -int uzlib_zlib_parse_header(TINF_DATA *d) -{ - unsigned char cmf, flg; - - /* -- get header bytes -- */ - - cmf = uzlib_get_byte(d); - flg = uzlib_get_byte(d); - - /* -- check format -- */ - - /* check checksum */ - if ((256*cmf + flg) % 31) return TINF_DATA_ERROR; - - /* check method is deflate */ - if ((cmf & 0x0f) != 8) return TINF_DATA_ERROR; - - /* check window size is valid */ - if ((cmf >> 4) > 7) return TINF_DATA_ERROR; - - /* check there is no preset dictionary */ - if (flg & 0x20) return TINF_DATA_ERROR; - - /* initialize for adler32 checksum */ - d->checksum_type = TINF_CHKSUM_ADLER; - d->checksum = 1; - - return cmf >> 4; -} diff --git a/avr/cores/megacommand/uzlib/uzlib.h b/avr/cores/megacommand/uzlib/uzlib.h deleted file mode 100644 index 1fb1fde61..000000000 --- a/avr/cores/megacommand/uzlib/uzlib.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) - * - * Copyright (c) 2003 by Joergen Ibsen / Jibz - * All Rights Reserved - * http://www.ibsensoftware.com/ - * - * Copyright (c) 2014-2018 by Paul Sokolovsky - * - * This software is provided 'as-is', without any express - * or implied warranty. In no event will the authors be - * held liable for any damages arising from the use of - * this software. - * - * Permission is granted to anyone to use this software - * for any purpose, including commercial applications, - * and to alter it and redistribute it freely, subject to - * the following restrictions: - * - * 1. The origin of this software must not be - * misrepresented; you must not claim that you - * wrote the original software. If you use this - * software in a product, an acknowledgment in - * the product documentation would be appreciated - * but is not required. - * - * 2. Altered source versions must be plainly marked - * as such, and must not be misrepresented as - * being the original software. - * - * 3. This notice may not be removed or altered from - * any source distribution. - */ - -#ifndef UZLIB_H_INCLUDED -#define UZLIB_H_INCLUDED - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#include "defl_static.h" - -#include "uzlib_conf.h" -#if UZLIB_CONF_DEBUG_LOG -#include -#endif - -/* calling convention */ -#ifndef TINFCC - #ifdef __WATCOMC__ - #define TINFCC __cdecl - #else - #define TINFCC - #endif -#endif - -/* ok status, more data produced */ -#define TINF_OK 0 -/* end of compressed stream reached */ -#define TINF_DONE 1 -#define TINF_DATA_ERROR (-3) -#define TINF_CHKSUM_ERROR (-4) -#define TINF_DICT_ERROR (-5) - -/* checksum types */ -#define TINF_CHKSUM_NONE 0 -#define TINF_CHKSUM_ADLER 1 -#define TINF_CHKSUM_CRC 2 - -/* helper macros */ -#define TINF_ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr))) - -/* data structures */ - -typedef struct { - uint16_t table[16]; /* table of code length counts */ - uint16_t trans[288]; /* code -> symbol translation table */ -} TINF_TREE; - -struct uzlib_uncomp { - /* Pointer to the next byte in the input buffer */ - const unsigned char *source; - /* Pointer to the next byte past the input buffer (source_limit = source + len) */ - const unsigned char *source_limit; - /* If source_limit == NULL, or source >= source_limit, this function - will be used to read next byte from source stream. The function may - also return -1 in case of EOF (or irrecoverable error). Note that - besides returning the next byte, it may also update source and - source_limit fields, thus allowing for buffered operation. */ - int (*source_read_cb)(struct uzlib_uncomp *uncomp); - - unsigned int tag; - unsigned int bitcount; - - /* Destination (output) buffer start */ - unsigned char *dest_start; - /* Current pointer in dest buffer */ - unsigned char *dest; - /* Pointer past the end of the dest buffer, similar to source_limit */ - unsigned char *dest_limit; - - /* Accumulating checksum */ - unsigned int checksum; - char checksum_type; - bool eof; - - int btype; - int bfinal; - unsigned int curlen; - int lzOff; - unsigned char *dict_ring; - unsigned int dict_size; - unsigned int dict_idx; - - TINF_TREE ltree; /* dynamic length/symbol tree */ - TINF_TREE dtree; /* dynamic distance tree */ -}; - -#include "tinf_compat.h" - -#define TINF_PUT(d, c) \ - { \ - *d->dest++ = c; \ - if (d->dict_ring) { d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; } \ - } - -unsigned char TINFCC uzlib_get_byte(TINF_DATA *d); - -/* Decompression API */ - -void TINFCC uzlib_init(void); -void TINFCC uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen); -int TINFCC uzlib_uncompress(TINF_DATA *d); -int TINFCC uzlib_uncompress_chksum(TINF_DATA *d); - -int TINFCC uzlib_zlib_parse_header(TINF_DATA *d); -int TINFCC uzlib_gzip_parse_header(TINF_DATA *d); - -/* Checksum API */ - -/* prev_sum is previous value for incremental computation, 1 initially */ -uint32_t TINFCC uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum); -/* crc is previous value for incremental computation, 0xffffffff initially */ -uint32_t TINFCC uzlib_crc32(const void *data, unsigned int length, uint32_t crc); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UZLIB_H_INCLUDED */ diff --git a/avr/cores/megacommand/uzlib/uzlib_conf.h b/avr/cores/megacommand/uzlib/uzlib_conf.h deleted file mode 100644 index fd67dec8a..000000000 --- a/avr/cores/megacommand/uzlib/uzlib_conf.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) - * - * Copyright (c) 2014-2018 by Paul Sokolovsky - */ - -#ifndef UZLIB_CONF_H_INCLUDED -#define UZLIB_CONF_H_INCLUDED - -#ifndef UZLIB_CONF_DEBUG_LOG -/* Debug logging level 0, 1, 2, etc. */ -#define UZLIB_CONF_DEBUG_LOG 0 -#endif - -#ifndef UZLIB_CONF_PARANOID_CHECKS -/* Perform extra checks on the input stream, even if they aren't proven - to be strictly required (== lack of them wasn't proven to lead to - crashes). */ -#define UZLIB_CONF_PARANOID_CHECKS 0 -#endif - -#ifndef UZLIB_CONF_USE_MEMCPY -/* Use memcpy() for copying data out of LZ window or uncompressed blocks, - instead of doing this byte by byte. For well-compressed data, this - may noticeably increase decompression speed. But for less compressed, - it can actually deteriorate it (due to the fact that many memcpy() - implementations are optimized for large blocks of data, and have - too much overhead for short strings of just a few bytes). */ -#define UZLIB_CONF_USE_MEMCPY 0 -#endif - -#endif /* UZLIB_CONF_H_INCLUDED */ diff --git a/avr/cores/megacommand/wiring.c b/avr/cores/megacommand/wiring.c index 743ff1152..95c9baa56 100644 --- a/avr/cores/megacommand/wiring.c +++ b/avr/cores/megacommand/wiring.c @@ -23,6 +23,7 @@ #include "wiring_private.h" #include "memorybank.h" +#include "helpers.h" // the prescaler is set so that timer0 ticks every 64 clock cycles, and the // the overflow handler is called every 256 ticks. #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) @@ -38,8 +39,9 @@ volatile unsigned long timer0_overflow_count = 0; volatile unsigned long timer0_millis = 0; -static unsigned char timer0_fract = 0; +static unsigned char timer0_fract = 0; +/* #if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ISR(TIM0_OVF_vect) #else @@ -67,7 +69,7 @@ ISR(TIMER0_OVF_vect) switch_ram_bank(old_bank); } - +*/ unsigned long millis() { unsigned long m; @@ -76,7 +78,8 @@ unsigned long millis() // disable interrupts while we read timer0_millis or we might get an // inconsistent value (e.g. in the middle of a write to timer0_millis) cli(); - m = timer0_millis; + //m = timer0_millis; + m = slowclock; SREG = oldSREG; return m; @@ -109,16 +112,11 @@ unsigned long micros() { return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); } -void delay(unsigned long ms) +void delay(uint16_t ms) { - uint32_t start = micros(); - - while (ms > 0) { + uint16_t start = slowclock; + while (clock_diff(start,slowclock) < ms) { yield(); - while ( ms > 0 && (micros() - start) >= 1000) { - ms--; - start += 1000; - } } } diff --git a/resource/icons_device.cpp b/resource/icons_device.cpp index 23ce7424a..c081ddfc3 100644 --- a/resource/icons_device.cpp +++ b/resource/icons_device.cpp @@ -37,3 +37,28 @@ unsigned char icon_mnm[] = { 0x33, 0xc0, 0x00, 0x00, 0x0e, 0xcf, 0x00, 0x00, 0x00, 0x07, 0x3c, 0x00, 0x00, 0x00, 0x03, 0x70, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00}; +// 'turbo_icon' 34x24px +unsigned char icon_turbo[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x89, + 0xe7, 0x1c, 0x00, 0x08, 0x8a, 0x28, 0xa2, 0x00, 0x08, 0x8a, 0x28, 0xa2, + 0x00, 0x08, 0x8a, 0x28, 0xa2, 0x00, 0x08, 0x8a, 0x48, 0xa2, 0x00, 0x08, + 0x8b, 0xcf, 0x22, 0x00, 0x08, 0x8a, 0x28, 0xa2, 0x00, 0x08, 0x8a, 0x28, + 0xa2, 0x00, 0x08, 0x8a, 0x28, 0xa2, 0x00, 0x08, 0x8a, 0x28, 0xa2, 0x00, + 0x08, 0x72, 0x2f, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0x00, + 0x00, 0x00, 0x27, 0x18, 0x00, 0x00, 0x3c, 0x3e, 0x0f, 0xe0, 0x00, 0x00, + 0x73, 0xf7, 0x38, 0x00, 0x1e, 0x53, 0xfd, 0x2c, 0x00, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +/* +// 'midi_icon', 34x24px +unsigned char icon_midi[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xf0, 0xcf, 0x0c, 0x00, 0x0f, 0xf0, 0xcf, 0x0c, + 0x00, 0x0c, 0xcc, 0xc0, 0xcc, 0x00, 0x0c, 0xcc, 0xc0, 0xcc, 0x00, 0x0c, + 0xcc, 0xcc, 0xcc, 0x00, 0x0c, 0xcc, 0xcc, 0xcc, 0x00, 0x0c, 0xcc, 0xcc, + 0xcc, 0x00, 0x0c, 0xcc, 0xcc, 0xcc, 0x00, 0x0c, 0xcc, 0xcc, 0xcc, 0x00, + 0x0c, 0xcc, 0xcc, 0xcc, 0x00, 0x0c, 0xcc, 0xcf, 0x0c, 0x00, 0x0c, 0xcc, + 0xcf, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x00, 0x0f, + 0xff, 0xff, 0xfc, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; */ diff --git a/resource/menu_layouts.cpp b/resource/menu_layouts.cpp index a8f332451..2cb2d2798 100644 --- a/resource/menu_layouts.cpp +++ b/resource/menu_layouts.cpp @@ -75,6 +75,7 @@ menu_t midiconfig_menu_layout = { {"ROUTING", 0, 0, 0, 0, MIDIROUTE_MENU_PAGE, 0, 0}, {"PROGRAM", 0, 0, 0, 0, MIDIPROGRAM_MENU_PAGE, 0, 0}, {"MD MIDI", 0, 0, 0, 0, MIDIMACHINEDRUM_MENU_PAGE, 0 ,0}, + {"GENRAL MIDI", 0, 0, 0, 0, MIDIGENERIC_MENU_PAGE, 0 ,0}, }, 0 }; @@ -138,6 +139,16 @@ menu_t midimachinedrum_menu_layout = { 24 }; +menu_t midigeneric_menu_layout = { + "GEN MIDI", + { + // m r n d p f o + {"MUTE CC:", 0, 129, 1, 60, NULL_PAGE, 0, 121}, + }, + 24 +}; + + menu_t mdconfig_menu_layout = { "MD", { @@ -154,7 +165,7 @@ menu_t mdimport_menu_layout = { // m r n d p f o {"SRC: ", 0, 128, 128, 43, NULL_PAGE, 0, 128}, {"DEST: ", 0, 128, 128, 44, NULL_PAGE, 0, 128}, - {"COUNT:", 1, 128, 0, 45, NULL_PAGE, 0, 0}, + {"COUNT:", 1, 129, 0, 45, NULL_PAGE, 0, 0}, {"RUN", 0, 0, 0, 0, NULL_PAGE, 25, 0}, }, 0 @@ -174,10 +185,9 @@ menu_t file_menu_layout = { { // m r n d p f o {"CANCEL", 0, 0, 0, 0, NULL_PAGE, 0, 0}, - {"NEW DIR.", 0, 0, 0, 0, NULL_PAGE, 0, 0}, + {"NEW DIR", 0, 0, 0, 0, NULL_PAGE, 0, 0}, {"DELETE", 0, 0, 0, 0, NULL_PAGE, 0, 0}, {"RENAME", 0, 0, 0, 0, NULL_PAGE, 0, 0}, - {"OVERWRITE", 0, 0, 0, 0, NULL_PAGE, 0, 0}, {"RECV ALL", 0, 0, 0, 0, NULL_PAGE, 0, 0}, {"SEND ALL", 0, 0, 0, 0, NULL_PAGE, 0, 0}, }, diff --git a/resource/menu_options.cpp b/resource/menu_options.cpp index cb7842204..251c75009 100644 --- a/resource/menu_options.cpp +++ b/resource/menu_options.cpp @@ -63,10 +63,12 @@ menu_option_t MENU_OPTIONS[] = { // 100: MIDI CLK SEND {0, "OFF"}, {1, "2"}, {2, "USB"}, {3, "2 + USB"}, // 104: NOTES - {0, "A"}, {1, "A#"}, {2, "B"}, {3, "C"}, {4, "C#"}, {5, "D"}, {6, "D#"}, {7, "E"}, {8, "F"}, {9, "F#"}, {10, "G"}, {11, "G#"}, + {0, "C"}, {1, "C#"}, {2, "D"}, {3, "D#"}, {4, "E"}, {5, "F"}, {6, "F#"}, {7, "G"}, {8, "G#"}, {9, "A"}, {10, "A#"}, {11, "B"}, // 116 {0, "CTRL"}, // 117 - {0, "A"}, {1, "B"}, {2, "C"}, {3, "D"} + {0, "A"}, {1, "B"}, {2, "C"}, {3, "D"}, + // 121 + {128, "--"} };