Firmware for HexBoard MIDI controller
Diffstat (limited to 'Classes.h')
| -rw-r--r-- | Classes.h | 158 |
1 files changed, 158 insertions, 0 deletions
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 |