From dc5a26d411bc90b35ad8fea64fecae120e93cf7e Mon Sep 17 00:00:00 2001 From: Nicholas Fox Date: Tue, 23 Apr 2024 22:00:00 -0400 Subject: Updates: MENU 1) even more preset scales in the non-12 tunings -- some are super funky! 2) transpose should be working again 3) moved key signature change into the Scales page 4) wheel speed options are restored FEATURES 1) POLYPHONIC BUZZER 2) wheel function back to "regular" 3) color palette improvements STILL NOT QUITE WORKING 1) buzzer only works in polyphony mode for now -- haven't gotten mono or arpeggio working right yet I moved some stuff into .h headers, but no changes to the patches you need for rotary / g8u2. --- Classes.h | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 Classes.h (limited to 'Classes.h') diff --git a/Classes.h b/Classes.h new file mode 100644 index 0000000..133d3a5 --- /dev/null +++ b/Classes.h @@ -0,0 +1,158 @@ +// class definitions are in a header so that +// they get read before compiling the main program. + +class tuningDef { +public: + std::string name; // limit is 17 characters for GEM menu + byte cycleLength; // steps before period/cycle/octave repeats + float stepSize; // in cents, 100 = "normal" semitone. + SelectOptionInt keyChoices[MAX_SCALE_DIVISIONS]; + int spanCtoA() { + return (- keyChoices[0].val_int); + }; +}; + +class layoutDef { +public: + std::string name; // limit is 17 characters for GEM menu + bool isPortrait; // affects orientation of the GEM menu only. + byte hexMiddleC; // instead of "what note is button 1", "what button is the middle" + int8_t acrossSteps; // defined this way to be compatible with original v1.1 firmare + int8_t dnLeftSteps; // defined this way to be compatible with original v1.1 firmare + byte tuning; // index of the tuning that this layout is designed for +}; + +class colorDef { +public: + float hue; + byte sat; + byte val; + colorDef mixWithWhite() { + colorDef temp; + temp.hue = this->hue; + temp.sat = ((this->sat > SAT_TINT) ? SAT_TINT : this->sat); + temp.val = VALUE_FULL; + return temp; + }; +}; + +class paletteDef { +public: + colorDef swatch[MAX_SCALE_DIVISIONS]; // the different colors used in this palette + byte colorNum[MAX_SCALE_DIVISIONS]; // map key (c,d...) to swatches + colorDef getColor(byte givenStepFromC) { + return swatch[colorNum[givenStepFromC] - 1]; + }; + float getHue(byte givenStepFromC) { + return getColor(givenStepFromC).hue; + }; + byte getSat(byte givenStepFromC) { + return getColor(givenStepFromC).sat; + }; + byte getVal(byte givenStepFromC) { + return getColor(givenStepFromC).val; + }; +}; + +class buttonDef { +public: + byte btnState = 0; // binary 00 = off, 01 = just pressed, 10 = just released, 11 = held + void interpBtnPress(bool isPress) { + btnState = (((btnState << 1) + isPress) & 3); + }; + int8_t coordRow = 0; // hex coordinates + int8_t coordCol = 0; // hex coordinates + uint32_t timePressed = 0; // timecode of last press + uint32_t LEDcolorAnim = 0; // calculate it once and store value, to make LED playback snappier + uint32_t LEDcolorPlay = 0; // calculate it once and store value, to make LED playback snappier + uint32_t LEDcolorOn = 0; // calculate it once and store value, to make LED playback snappier + uint32_t LEDcolorOff = 0; // calculate it once and store value, to make LED playback snappier + bool animate = 0; // hex is flagged as part of the animation in this frame, helps make animations smoother + int16_t stepsFromC = 0; // number of steps from C4 (semitones in 12EDO; microtones if >12EDO) + bool isCmd = 0; // 0 if it's a MIDI note; 1 if it's a MIDI control cmd + bool inScale = 0; // 0 if it's not in the selected scale; 1 if it is + byte note = UNUSED_NOTE; // MIDI note or control parameter corresponding to this hex + int16_t bend = 0; // in microtonal mode, the pitch bend for this note needed to be tuned correctly + byte channel = 0; // what MIDI channel this note is playing on + float frequency = 0.0; // what frequency to ring on the buzzer +}; + +class wheelDef { +public: + bool alternateMode; // two ways to control + bool isSticky; // TRUE if you leave value unchanged when no buttons pressed + byte* topBtn; // pointer to the key Status of the button you use as this button + byte* midBtn; + byte* botBtn; + int16_t minValue; + int16_t maxValue; + int* stepValue; // this can be changed via GEM menu + int16_t defValue; // snapback value + int16_t curValue; + int16_t targetValue; + uint32_t timeLastChanged; + void setTargetValue() { + if (alternateMode) { + if (*midBtn >> 1) { // middle button toggles target (0) vs. step (1) mode + int16_t temp = curValue; + if (*topBtn == 1) {temp += *stepValue;}; // tap button + if (*botBtn == 1) {temp -= *stepValue;}; // tap button + if (temp > maxValue) {temp = maxValue;} + else if (temp <= minValue) {temp = minValue;}; + targetValue = temp; + } else { + switch (((*topBtn >> 1) << 1) + (*botBtn >> 1)) { + case 0b10: targetValue = maxValue; break; + case 0b11: targetValue = defValue; break; + case 0b01: targetValue = minValue; break; + default: targetValue = curValue; break; + }; + }; + } else { + switch (((*topBtn >> 1) << 2) + ((*midBtn >> 1) << 1) + (*botBtn >> 1)) { + case 0b100: targetValue = maxValue; break; + case 0b110: targetValue = (3 * maxValue + minValue) / 4; break; + case 0b010: + case 0b111: + case 0b101: targetValue = (maxValue + minValue) / 2; break; + case 0b011: targetValue = (maxValue + 3 * minValue) / 4; break; + case 0b001: targetValue = minValue; break; + case 0b000: targetValue = (isSticky ? curValue : defValue); break; + default: break; + }; + } + }; + bool updateValue(uint32_t givenTime) { + int16_t temp = targetValue - curValue; + if (temp != 0) { + if ((givenTime - timeLastChanged) >= CC_MSG_COOLDOWN_MICROSECONDS ) { + timeLastChanged = givenTime; + if (abs(temp) < *stepValue) { + curValue = targetValue; + } else { + curValue = curValue + (*stepValue * (temp / abs(temp))); + }; + return 1; + } else { + return 0; + }; + } else { + return 0; + }; + }; +}; +// back button + +class scaleDef { +public: + std::string name; + byte tuning; + byte pattern[MAX_SCALE_DIVISIONS]; +}; + +// this class should only be touched by the 2nd core +class oscillator { +public: + uint16_t increment = 0; + uint16_t counter = 0; +}; \ No newline at end of file -- cgit 1.4.1