diff --git a/avr/cores/megacommand/A4/A4Pattern.h b/avr/cores/megacommand/A4/A4Pattern.h index 60a7cf3ac..ee18bfd11 100644 --- a/avr/cores/megacommand/A4/A4Pattern.h +++ b/avr/cores/megacommand/A4/A4Pattern.h @@ -33,13 +33,11 @@ class A4Pattern : public ElektronPattern { uint8_t data[8]; - A4Pattern() : ElektronPattern() { + A4Pattern(bool _init = true) : ElektronPattern(_init) { maxSteps = 64; maxParams = 24; maxTracks = 16; maxLocks = 64; - - init(); } /* XXX TODO extra pattern 64 */ diff --git a/avr/cores/megacommand/Elektron/ElektronPattern.h b/avr/cores/megacommand/Elektron/ElektronPattern.h index f28f57855..c1f86e144 100644 --- a/avr/cores/megacommand/Elektron/ElektronPattern.h +++ b/avr/cores/megacommand/Elektron/ElektronPattern.h @@ -32,12 +32,14 @@ class ElektronPattern: public ElektronSysexObject { int8_t lockTracks[64]; int8_t lockParams[64]; - ElektronPattern() { + ElektronPattern(bool _init) { maxParams = 0; maxTracks = 0; maxSteps = 0; maxLocks = 0; - clearPattern(); + if (_init) { + init(); + } } /** Clear the pattern. */ diff --git a/avr/cores/megacommand/MCL/MCLSd.h b/avr/cores/megacommand/MCL/MCLSd.h index 962c6ea64..2f7ea750c 100644 --- a/avr/cores/megacommand/MCL/MCLSd.h +++ b/avr/cores/megacommand/MCL/MCLSd.h @@ -5,6 +5,7 @@ #include "SdFat.h" #include "new.h" +#include "type_traits.h" #define SD_MAX_RETRIES 5 @@ -23,10 +24,18 @@ class MCLSd { ::new(data)T; return ret; } + /// Specialization for ElektronPattern... + template bool read_data_v_noinit(T *data, FatFile *filep) { + auto ret = read_data(data, sizeof(T), filep); + ::new(data)T(false); + return ret; + } + /// save data to SD card, including the vtable template bool write_data_v(T *data, FatFile *filep) { return write_data(data, sizeof(T), filep); } + }; extern MCLSd mcl_sd; diff --git a/avr/cores/megacommand/MCL/SDDrivePage.cpp b/avr/cores/megacommand/MCL/SDDrivePage.cpp index f3eabdf22..497b29467 100644 --- a/avr/cores/megacommand/MCL/SDDrivePage.cpp +++ b/avr/cores/megacommand/MCL/SDDrivePage.cpp @@ -209,7 +209,7 @@ void SDDrivePage::load_snapshot() { for (int i = 0; i < 128; ++i) { progress_i = i; mcl_gui.draw_progress("Loading pattern", i, 128); - if (!mcl_sd.read_data_v(&MD.pattern, &file)) { + if (!mcl_sd.read_data_v_noinit(&MD.pattern, &file)) { goto load_error; } MD.setSysexRecPos(8, i); diff --git a/avr/cores/megacommand/MD/MDMessages.cpp b/avr/cores/megacommand/MD/MDMessages.cpp index d282ce704..62486d120 100644 --- a/avr/cores/megacommand/MD/MDMessages.cpp +++ b/avr/cores/megacommand/MD/MDMessages.cpp @@ -60,7 +60,11 @@ bool MDGlobal::fromSysex(uint8_t *data, uint16_t len) { decoder.get8(&baseChannel); decoder.get8(&unused); - decoder.get16(&tempo); + uint8_t tempo_lower; + uint8_t tempo_upper; + decoder.get8(&tempo_upper); + decoder.get8(&tempo_lower); + tempo = (tempo_upper << 7 ) | tempo_lower; decoder.getb(&extendedMode); uint8_t byte = 0; @@ -108,7 +112,11 @@ bool MDGlobal::fromSysex(MidiClass *midi) { decoder.get8(&baseChannel); decoder.get8(&unused); - decoder.get16(&tempo); + uint8_t tempo_lower; + uint8_t tempo_upper; + decoder.get8(&tempo_upper); + decoder.get8(&tempo_lower); + tempo = (tempo_upper << 7 ) | tempo_lower; decoder.getb(&extendedMode); uint8_t byte = 0; @@ -470,7 +478,7 @@ bool MDSong::fromSysex(uint8_t *data, uint16_t len) { decoder.start7Bit(); decoder.get((uint8_t *)&rows[i], 4); decoder.get16(&rows[i].mutes); - decoder.get16(&rows[i].tempo); + decoder.get16(&rows[i].tempo); // different from MDGlobal tempo, this is 7bit encoded decoder.get(&rows[i].startPosition, 2); decoder.stop7Bit(); } diff --git a/avr/cores/megacommand/MD/MDMessages.h b/avr/cores/megacommand/MD/MDMessages.h index acd229f98..9135822dd 100644 --- a/avr/cores/megacommand/MD/MDMessages.h +++ b/avr/cores/megacommand/MD/MDMessages.h @@ -84,8 +84,7 @@ class MDGlobal: public ElektronSysexObject { uint8_t programChange; uint8_t trigMode; - MDGlobal() { - } + MDGlobal() : ElektronSysexObject() {}; virtual uint8_t getPosition() { return origPosition; } virtual void setPosition(uint8_t pos) { origPosition = pos; } @@ -198,6 +197,7 @@ class MDKit: public ElektronSysexObject { **/ public: + uint8_t origPosition; char name[17]; @@ -224,6 +224,8 @@ class MDKit: public ElektronSysexObject { /** The mute group selected for each track (255: OFF). **/ uint8_t muteGroups[16]; + MDKit(): ElektronSysexObject() {} + virtual bool fromSysex(uint8_t *sysex, uint16_t len); virtual bool fromSysex(MidiClass *midi); virtual uint16_t toSysex(uint8_t *sysex, uint16_t len); diff --git a/avr/cores/megacommand/MD/MDPattern.h b/avr/cores/megacommand/MD/MDPattern.h index af6130adb..20832818c 100644 --- a/avr/cores/megacommand/MD/MDPattern.h +++ b/avr/cores/megacommand/MD/MDPattern.h @@ -29,9 +29,6 @@ class MDPattern : public ElektronPattern { public: uint8_t origPosition; - uint8_t getPosition() { return origPosition; } - void setPosition(uint8_t _pos) { origPosition = _pos; } - /* SUPER IMPORTANT DO NOT CHANGE THE ORDER OF DECLARATION OF THESE VARIABLES */ @@ -64,12 +61,6 @@ class MDPattern : public ElektronPattern { uint8_t kit; uint8_t numLockedRows; // unused - uint8_t getKit() { return kit; } - void setKit(uint8_t _kit) { kit = _kit; } - - uint8_t getLength() { return patternLength; } - void setLength(uint8_t _len) { patternLength = _len; } - uint32_t accentEditAll; uint32_t slideEditAll; uint32_t swingEditAll; @@ -79,49 +70,57 @@ class MDPattern : public ElektronPattern { uint8_t numRows; int8_t paramLocks[16][24]; - int8_t getLockIdx(uint8_t track, uint8_t param) { - return paramLocks[track][param]; - } - void setLockIdx(uint8_t track, uint8_t param, int8_t value) { - paramLocks[track][param] = value; - } bool isExtraPattern; - MDPattern() : ElektronPattern() { + /** ElektronPattern implementation */ + + virtual uint8_t getPosition() { return origPosition; } + virtual void setPosition(uint8_t _pos) { origPosition = _pos; } + + virtual uint8_t getLength() { return patternLength; } + virtual void setLength(uint8_t _len) { patternLength = _len; } + + virtual uint8_t getKit() { return kit; } + virtual void setKit(uint8_t _kit) { kit = _kit; } + + virtual bool isTrackEmpty(uint8_t track); + virtual bool isTrigSet(uint8_t track, uint8_t trig) { return IS_BIT_SET64(trigPatterns[track], trig); } + + virtual void clearPattern(); + virtual void clearTrack(uint8_t track); + + virtual void setTrig(uint8_t track, uint8_t trig) { SET_BIT64(trigPatterns[track], trig); } + virtual void setNote(uint8_t track, uint8_t step, uint8_t pitch); + virtual void clearTrig(uint8_t track, uint8_t trig); + + virtual int8_t getLockIdx(uint8_t track, uint8_t param) { return paramLocks[track][param]; } + virtual void setLockIdx(uint8_t track, uint8_t param, int8_t value) { paramLocks[track][param] = value; } + + virtual void recalculateLockPatterns(); + + /** ElektronSysexObject implementation */ + virtual bool fromSysex(uint8_t *sysex, uint16_t len); + virtual bool fromSysex(MidiClass *midi); + virtual uint16_t toSysex(uint8_t *sysex, uint16_t len); + virtual uint16_t toSysex(ElektronDataToSysexEncoder *encoder); + + MDPattern(bool _init = true) : ElektronPattern(_init) { maxSteps = 64; maxParams = 24; maxTracks = 16; maxLocks = 64; isExtraPattern = false; - init(); } /* XXX TODO extra pattern 64 */ - virtual bool fromSysex(uint8_t *sysex, uint16_t len); - virtual bool fromSysex(MidiClass *midi); - virtual uint16_t toSysex(uint8_t *sysex, uint16_t len); - virtual uint16_t toSysex(ElektronDataToSysexEncoder *encoder); uint16_t toSysex(); - bool isTrackEmpty(uint8_t track); void clear_step_locks(uint8_t track, uint8_t step); - void clearPattern(); - void clearTrack(uint8_t track); - void clearTrig(uint8_t track, uint8_t trig); - inline void setTrig(uint8_t track, uint8_t trig) { - SET_BIT64(trigPatterns[track], trig); - } - inline bool isTrigSet(uint8_t track, uint8_t trig) { - return IS_BIT_SET64(trigPatterns[track], trig); - } - void setNote(uint8_t track, uint8_t step, uint8_t pitch); - - virtual void recalculateLockPatterns(); /** * Swap two tracks of the patterns by copying hits, param locks and diff --git a/avr/cores/megacommand/MNM/MNMPattern.h b/avr/cores/megacommand/MNM/MNMPattern.h index 25e7ac411..46aa37384 100644 --- a/avr/cores/megacommand/MNM/MNMPattern.h +++ b/avr/cores/megacommand/MNM/MNMPattern.h @@ -1,9 +1,9 @@ #ifndef MNMPATTERN_H__ #define MNMPATTERN_H__ -#include -#include "MNMDataEncoder.h" #include "ElektronPattern.h" +#include "MNMDataEncoder.h" +#include typedef struct mnm_note_s { unsigned note : 7; @@ -15,10 +15,7 @@ class MNMPattern : public ElektronPattern { public: uint8_t origPosition; - uint8_t getPosition() { return origPosition; } - void setPosition(uint8_t _pos) { origPosition = _pos; } - - /* SUPER IMPORTANT DO NOT CHANGE THE ORDER OF DECLARATION OF THESE VARIABLES */ + /* SUPER IMPORTANT DO NOT CHANGE THE ORDER OF DECLARATION OF THESE VARIABLES */ uint64_t ampTrigs[6]; uint64_t filterTrigs[6]; @@ -57,15 +54,15 @@ class MNMPattern : public ElektronPattern { uint8_t midiKey[6]; static const uint8_t ARP_PLAY_TRUE = 0; - static const uint8_t ARP_PLAY_UP = 1; + static const uint8_t ARP_PLAY_UP = 1; static const uint8_t ARP_PLAY_DOWN = 2; static const uint8_t ARP_PLAY_CYCLIC = 3; static const uint8_t ARP_PLAY_RND = 4; static const uint8_t ARP_MODE_OFF = 0; static const uint8_t ARP_MODE_KEY = 1; - static const uint8_t ARP_MODE_SID = 2; - static const uint8_t ARP_MODE_ADD = 3; + static const uint8_t ARP_MODE_SID = 2; + static const uint8_t ARP_MODE_ADD = 3; uint8_t arpPlay[6]; uint8_t arpMode[6]; @@ -75,97 +72,95 @@ class MNMPattern : public ElektronPattern { uint8_t arpLength[6]; uint8_t arpPattern[6][16]; - uint8_t midiArpPlay[6]; + uint8_t midiArpPlay[6]; uint8_t midiArpMode[6]; uint8_t midiArpOctaveRange[6]; uint8_t midiArpMultiplier[6]; uint8_t midiArpLength[6]; uint8_t midiArpPattern[6][16]; - uint8_t getKit() { return kit; } - void setKit(uint8_t _kit) { kit = _kit; } - - uint8_t getLength() { return patternLength; } - void setLength(uint8_t _len) { patternLength = _len; } - - uint8_t unused[4]; + uint8_t unused[4]; uint16_t midiNotesUsed; uint8_t chordNotesUsed; - uint8_t unused2; + uint8_t unused2; uint8_t locksUsed; uint8_t numRows; int8_t paramLocks[6][64]; - int8_t getLockIdx(uint8_t track, uint8_t param) { - return paramLocks[track][param]; - } - void setLockIdx(uint8_t track, uint8_t param, int8_t value) { - paramLocks[track][param] = value; - } - + mnm_note_t midiNotes[400]; mnm_note_t chordNotes[192]; - MNMPattern() : ElektronPattern() { - maxSteps = 64; - maxParams = 64; - maxTracks = 6; - maxLocks = 62; - init(); + /** ElektronPattern implementation */ + + virtual uint8_t getPosition() { return origPosition; } + virtual void setPosition(uint8_t _pos) { origPosition = _pos; } + + virtual uint8_t getLength() { return patternLength; } + virtual void setLength(uint8_t _len) { patternLength = _len; } + + virtual uint8_t getKit() { return kit; } + virtual void setKit(uint8_t _kit) { kit = _kit; } + + virtual bool isTrackEmpty(uint8_t track); + // TODO virtual bool isLockEmpty(uint8_t track, uint8_t param); + virtual bool isTrigSet(uint8_t track, uint8_t trig) { return isAmpTrigSet(track, trig); } + + virtual void clearPattern(); + virtual void clearTrack(uint8_t track); + + virtual void setTrig(uint8_t track, uint8_t trig) { setTrig(track, trig, true, true, true, true); } + virtual void setNote(uint8_t track, uint8_t step, uint8_t note); virtual void clearTrig(uint8_t track, uint8_t trig) { clearTrig(track, trig, true, true, true, true); } + + virtual int8_t getLockIdx(uint8_t track, uint8_t param) { return paramLocks[track][param]; } + virtual void setLockIdx(uint8_t track, uint8_t param, int8_t value) { paramLocks[track][param] = value; } + virtual void recalculateLockPatterns(); + + /** ElektronSysexObject implementation */ + virtual bool fromSysex(uint8_t *sysex, uint16_t len); + virtual bool fromSysex(MidiClass *midi); + virtual uint16_t toSysex(uint8_t *sysex, uint16_t len); + virtual uint16_t toSysex(ElektronDataToSysexEncoder *encoder); + + MNMPattern(bool _init = true) : ElektronPattern(_init) { + maxSteps = 64; + maxParams = 64; + maxTracks = 6; + maxLocks = 62; } - bool fromSysex(uint8_t *sysex, uint16_t len); - bool fromSysex(MidiClass *midi); - - uint16_t toSysex(uint8_t *sysex, uint16_t len); - uint16_t toSysex(ElektronDataToSysexEncoder *encoder); - - bool isTrackEmpty(uint8_t track); - bool isMidiTrackEmpty(uint8_t track); - - void clearPattern(); - void clearTrack(uint8_t track); - void clearMidiTrack(uint8_t track); - - void clearTrig(uint8_t track, uint8_t trig, - bool ampTrig, bool filterTrig = false, bool lfoTrig = false, - bool triglessTrig = false, bool chordTrig = false); - void clearTrig(uint8_t track, uint8_t trig) { - clearTrig(track, trig, true, true, true, true); - } - void setTrig(uint8_t track, uint8_t trig, - bool ampTrig, bool filterTrig = false, bool lfoTrig = false, - bool triglessTrig = false, bool chordTrig = false); - - void setTrig(uint8_t track, uint8_t trig) { - setTrig(track, trig, true, true, true, true); - } - - bool isTrigSet(uint8_t track, uint8_t trig, - bool ampTrig, bool filterTrig = false, bool lfoTrig = false, - bool triglessTrig = false, bool chordTrig = false); - - bool isTrigSet(uint8_t track, uint8_t trig) { - return isAmpTrigSet(track, trig); - } - - + + bool isMidiTrackEmpty(uint8_t track); + + void clearMidiTrack(uint8_t track); + + void clearTrig(uint8_t track, uint8_t trig, bool ampTrig, + bool filterTrig = false, bool lfoTrig = false, + bool triglessTrig = false, bool chordTrig = false); + + void setTrig(uint8_t track, uint8_t trig, bool ampTrig, + bool filterTrig = false, bool lfoTrig = false, + bool triglessTrig = false, bool chordTrig = false); + + bool isTrigSet(uint8_t track, uint8_t trig, bool ampTrig, + bool filterTrig = false, bool lfoTrig = false, + bool triglessTrig = false, bool chordTrig = false); + void clearAllTrig(uint8_t track, uint8_t trig) { clearTrig(track, trig, true, true, true, true, true); } + void setAllTrig(uint8_t track, uint8_t trig) { setTrig(track, trig, true, true, true, true); } void clearAmpTrig(uint8_t track, uint8_t trig) { clearTrig(track, trig, true); } - void setAmpTrig(uint8_t track, uint8_t trig) { - setTrig(track, trig, true); + void setAmpTrig(uint8_t track, uint8_t trig) { setTrig(track, trig, true); } + bool isAmpTrigSet(uint8_t track, uint8_t trig) { + return IS_BIT_SET64(ampTrigs[track], trig); } - bool isAmpTrigSet(uint8_t track, uint8_t trig) { - return IS_BIT_SET64(ampTrigs[track], trig); - } void clearFilterTrig(uint8_t track, uint8_t trig) { clearTrig(track, trig, false, true); } @@ -192,9 +187,7 @@ class MNMPattern : public ElektronPattern { } int8_t getNextEmptyLock(); - void recalculateLockPatterns(); - void setNote(uint8_t track, uint8_t step, uint8_t note); void setChordNote(uint8_t track, uint8_t step, uint8_t note); void clearChordNote(uint8_t track, uint8_t step, uint8_t note); @@ -203,6 +196,4 @@ class MNMPattern : public ElektronPattern { #endif }; - - #endif /* MNMPATTERN_H__ */ diff --git a/avr/cores/megacommand/type_traits.h b/avr/cores/megacommand/type_traits.h index 4a0d8bbdd..1f808ee6d 100644 --- a/avr/cores/megacommand/type_traits.h +++ b/avr/cores/megacommand/type_traits.h @@ -15,4 +15,20 @@ template enum { __value = 1 }; }; +// adapted from cppreference.com + +template + struct enable_if {}; + +template + struct enable_if { typedef T type; }; + +struct true_type + { + enum { __value = 1 }; + }; +struct false_type + { + enum { __value = 0 }; + };