diff --git a/Software/Gravity/Gravity.ino b/Software/Gravity/Gravity.ino index 7bb59be..7438f81 100644 --- a/Software/Gravity/Gravity.ino +++ b/Software/Gravity/Gravity.ino @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -148,7 +147,6 @@ int extTriggerCount; //uint32_t lastInteractionTime; // used for display timeout U8G2_SSD1306_128X64_NONAME_2_HW_I2C u8g2(U8G2_R2, SCL, SDA, U8X8_PIN_NONE); -RotaryEncoder encoder(ENC_D1_PIN, ENC_D2_PIN, RotaryEncoder::LatchMode::TWO03); String version; @@ -170,6 +168,16 @@ void setup() { pinMode(clockOutPin, OUTPUT); + + pinMode(ENC_D1_PIN, INPUT_PULLUP); + pinMode(ENC_D2_PIN, INPUT_PULLUP); + + //Enabling PinChange Interrupts for the encoder + //pins 17 (PC3/PCINT11) and 4 (PD4/PCINT20), ports C and D + PCICR |= 0b00000110; + PCMSK1 |= 0b00001000; + PCMSK2 |= 0b00010000; + loadState(); u8g2.begin(); @@ -178,6 +186,7 @@ void setup() { calculateCycles(); calculateBPMTiming(); + checkEncoderStatus(); resetClocks(); @@ -192,6 +201,64 @@ void loop() { checkInputs(); } +//Encoder interrupts +ISR (PCINT1_vect) { + checkEncoderStatus(); +} +ISR (PCINT2_vect) { + checkEncoderStatus(); +} + +uint8_t encoderStatus; +uint32_t encoderCheckTime = 0; +uint32_t encoderTimeBetweenPulses = 0; +bool encoderDirectionOld; //0 = -, 1 = +, Old because current direction can be determined by encoderChange +int8_t encoderChange = 0; +uint8_t encoderBurstCount = 0; + +void checkEncoderStatus() { + bool pin1Status = digitalRead(ENC_D1_PIN); + bool pin2Status = digitalRead(ENC_D2_PIN); + uint8_t newStatus = (pin1Status << 1) | pin2Status; + switch(encoderStatus) { // encoderStatus & 0b00000011 - to check only 2 last bits + case 0b00: + if (newStatus == 0b01) { + encoderChange++; + } else if (newStatus == 0b10) { + encoderChange--; + } + break; + case 0b01: + if (newStatus == 0b11) { + encoderChange++; + } else if (newStatus == 0b00) { + encoderChange--; + } + break; + case 0b11: + if (newStatus == 0b10) { + encoderChange++; + } else if (newStatus == 0b01) { + encoderChange--; + } + break; + case 0b10: + if (newStatus == 0b00) { + encoderChange++; + } else if (newStatus == 0b11) { + encoderChange--; + } + break; + } + //encoderStatus = (encoderStatus << 2); //previous status is now stored in bits 2 and 3 + encoderStatus = bitWrite(encoderStatus, 1, pin1Status); + encoderStatus = bitWrite(encoderStatus, 0, pin2Status); //This can probably be more optimizied with bit logic + + uint32_t currentTime = millis(); + encoderTimeBetweenPulses = currentTime - encoderCheckTime; + encoderCheckTime = currentTime; +} + void sendMIDIClock() { NeoSerial.write(0xF8); } diff --git a/Software/Gravity/Interactions.ino b/Software/Gravity/Interactions.ino index 2cb5889..accc3b4 100644 --- a/Software/Gravity/Interactions.ino +++ b/Software/Gravity/Interactions.ino @@ -61,27 +61,30 @@ void checkInputs() { } //encoder - encoder.tick(); - int encPosition = encoder.getPosition(); - uint8_t encDirection = (int)(encoder.getDirection()); - if (encPositionOld != encPosition) { - uint8_t change = encPositionOld - encPosition; - if (reverseEnc) { - change = change * -1; + if (encoderChange != 0) { + if (!reverseEnc) { + encoderChange = encoderChange * -1; } - uint32_t ms = encoder.getMillisBetweenRotations(); - /*if (encDirectionOld == encDirection && ms < 20) { //encoder acceleration - change = change * 5; - } else if (encDirectionOld == encDirection && ms < 80) { - change = change * 2; - } else */ if (encDirectionOld != encDirection && ms < 200) { //filter out encoder "jumps" - change = 0; + + /*if (((encoderChange > 0) != encoderDirectionOld) && encoderTimeBetweenPulses < 150) { //filter out encoder "jumps". Comented out + encoderChange = 0; //because it seems like sometimes it was preventing normal scroll + } //if it works ok without it delete encoderDirectionOld var altogether + encoderDirectionOld = (encoderChange > 0);*/ + + //encoder acceleration + if (encoderTimeBetweenPulses < 15) { // <-- + encoderBurstCount++; + } else { + encoderBurstCount = 0; } - encDirectionOld = encDirection; + if (encoderBurstCount > 3) { // <-- + encoderChange = encoderChange * 3; // <-- The three params need to be finetuned to feel natural + } + if (displayScreen == 0) { uint8_t channelCV; if (!insideTab && !shiftBtnPushed) { //Change tab - displayTab = displayTab + change; + displayTab = displayTab + encoderChange; if (displayTab > 100) { //to address "negative" numbers displayTab = 0; } else if (displayTab > (extraChannel ? 7 : 6)) { @@ -91,7 +94,7 @@ void checkInputs() { || (insideTab && menuItem == 0 && (menuItemSelected || shiftBtnPushed))) && displayTab == 0 && masterClockMode == 0) { //Change BPM - bpm = bpm + change; + bpm = bpm + encoderChange; if (bpm > MAXBPM) { bpm = MAXBPM; } else if (bpm < MINBPM) { @@ -104,7 +107,7 @@ void checkInputs() { && (menuItemSelected || shiftBtnPushed))) && displayTab != 0 && channels[displayTab - 1].mode == Clock) { - channels[displayTab - 1].subDiv = channels[displayTab - 1].subDiv - change; + channels[displayTab - 1].subDiv = channels[displayTab - 1].subDiv - encoderChange; //channels[displayTab - 1].offset = 0; if (channels[displayTab - 1].subDiv > 100) { channels[displayTab - 1].subDiv = 0; @@ -129,7 +132,7 @@ void checkInputs() { && (menuItemSelected || shiftBtnPushed))) && displayTab != 0 && channels[displayTab - 1].mode == Random) { //Change Random - channels[displayTab - 1].random = channels[displayTab - 1].random + change; + channels[displayTab - 1].random = channels[displayTab - 1].random + encoderChange; if (channels[displayTab - 1].random > 100) { channels[displayTab - 1].random = 0; } else if (channels[displayTab - 1].random > 9) { @@ -141,12 +144,12 @@ void checkInputs() { && (menuItemSelected || shiftBtnPushed))) && displayTab != 0 && channels[displayTab - 1].mode == Sequencer) { //Change SEQ pattern - if (channels[displayTab - 1].seqPattern == 0 && change == -1) { + if (channels[displayTab - 1].seqPattern == 0 && encoderChange == -1) { channels[displayTab - 1].seqPattern = 0; - } else if (channels[displayTab - 1].seqPattern == 31 && change == 1) { + } else if (channels[displayTab - 1].seqPattern == 31 && encoderChange == 1) { channels[displayTab - 1].seqPattern = 31; } else { - channels[displayTab - 1].seqPattern = channels[displayTab - 1].seqPattern + change; + channels[displayTab - 1].seqPattern = channels[displayTab - 1].seqPattern + encoderChange; } saveState(); } else if (((!insideTab && shiftBtnPushed) @@ -154,7 +157,7 @@ void checkInputs() { && (menuItemSelected || shiftBtnPushed))) && displayTab != 0 && channels[displayTab - 1].mode == Swing) { //Change SWING - channels[displayTab - 1].swing = channels[displayTab - 1].swing + change; + channels[displayTab - 1].swing = channels[displayTab - 1].swing + encoderChange; if (channels[displayTab - 1].swing > 6) { channels[displayTab - 1].swing = 0; } else if (channels[displayTab - 1].swing > 5) { @@ -166,7 +169,7 @@ void checkInputs() { && (menuItemSelected || shiftBtnPushed))) && displayTab != 0 && channels[displayTab - 1].mode == Gate) { //Change GATE - channels[displayTab - 1].gate = channels[displayTab - 1].gate + change; + channels[displayTab - 1].gate = channels[displayTab - 1].gate + encoderChange; if (channels[displayTab - 1].gate > 100 || channels[displayTab - 1].gate == 0) { channels[displayTab - 1].gate = 1; } else if (channels[displayTab - 1].gate > 99) { @@ -175,7 +178,7 @@ void checkInputs() { calculateGate(displayTab - 1); saveState(); } else if (insideTab && !shiftBtnPushed && !menuItemSelected) { - menuItem = menuItem + change; + menuItem = menuItem + encoderChange; if (menuItem > 100) { //for "negative" values menuItem = 0; } else if (menuItem > lastMenuItem) { @@ -185,11 +188,11 @@ void checkInputs() { && (shiftBtnPushed || menuItemSelected) && displayTab == 0 && menuItem == 1) { //Master Clock Mode - if (masterClockMode == 1) { // && change == -1) { //Stop when switching from ext to int or to midi + if (masterClockMode == 1) { // && encoderChange == -1) { //Stop when switching from ext to int or to midi isPlaying = false; } - masterClockMode = masterClockMode + change; + masterClockMode = masterClockMode + encoderChange; if (masterClockMode > 100) { masterClockMode = 0; } else if (masterClockMode > 2) { @@ -201,7 +204,7 @@ void checkInputs() { && displayTab == 0 && menuItem == 2 && masterClockMode == 0) { //Modulation channel - bpmModulationChannel = bpmModulationChannel + change; + bpmModulationChannel = bpmModulationChannel + encoderChange; if (bpmModulationChannel == 0 || bpmModulationChannel == 1) { bpmModulationRange = 1; } else if (bpmModulationChannel > 100) { @@ -216,7 +219,7 @@ void checkInputs() { && displayTab == 0 && menuItem == 2 && masterClockMode == 1) { //PPQN - extClockPPQN = extClockPPQN + change; + extClockPPQN = extClockPPQN + encoderChange; if (extClockPPQN > 100) { extClockPPQN = 0; } else if (extClockPPQN > 1) { @@ -227,7 +230,7 @@ void checkInputs() { && (menuItemSelected || shiftBtnPushed) && displayTab == 0 && menuItem == 3) { //Modulation range - bpmModulationRange = bpmModulationRange + change; + bpmModulationRange = bpmModulationRange + encoderChange; if (bpmModulationRange == 0) { bpmModulationRange = 1; } else if (bpmModulationRange > 100) { @@ -240,7 +243,7 @@ void checkInputs() { && (menuItemSelected || shiftBtnPushed) && displayTab != 0 && menuItem == 1) { //Channel Mode - channels[displayTab - 1].mode = channels[displayTab - 1].mode + change; + channels[displayTab - 1].mode = channels[displayTab - 1].mode + encoderChange; if (channels[displayTab - 1].mode == 7) { channels[displayTab - 1].mode = 4; //to make it cycle through all the modes } else if (channels[displayTab - 1].mode > 4) { @@ -253,7 +256,7 @@ void checkInputs() { && (menuItemSelected || shiftBtnPushed) && displayTab != 0 && menuItem == 2 && channels[displayTab - 1].mode == Clock) { //Offset - channels[displayTab - 1].offset = channels[displayTab - 1].offset + change; + channels[displayTab - 1].offset = channels[displayTab - 1].offset + encoderChange; if (channels[displayTab - 1].offset == 255) { // 0 - 1 for uint8 is 255 channels[displayTab - 1].offset = 0; } else if (channels[displayTab - 1].offset > channelPulsesPerCycle[displayTab-1]) { @@ -265,7 +268,7 @@ void checkInputs() { && displayTab != 0 && menuItem == 2 && (channels[displayTab - 1].mode == Random || channels[displayTab - 1].mode == Gate)) { //SUBDIV for RANDOM and GATE - channels[displayTab - 1].subDiv = channels[displayTab - 1].subDiv - change; + channels[displayTab - 1].subDiv = channels[displayTab - 1].subDiv - encoderChange; if (channels[displayTab - 1].subDiv > 200) { channels[displayTab - 1].subDiv = 0; } else if (channels[displayTab - 1].subDiv > (sizeof(subDivs) / sizeof(subDivs[0])) - 1) { @@ -287,7 +290,7 @@ void checkInputs() { } else { channelCV = 0; } - channelCV = channelCV + change; + channelCV = channelCV + encoderChange; if (channelCV == 0 || channelCV > 100) { channelCV = 0; channels[displayTab - 1].CV1Target = 0; @@ -309,7 +312,7 @@ void checkInputs() { } else { channelCV = 0; } - channelCV = channelCV + change; + channelCV = channelCV + encoderChange; if (channelCV == 0 || channelCV > 100) { channelCV = 0; channels[displayTab - 1].CV1Target = 0; @@ -331,7 +334,7 @@ void checkInputs() { } else { channelCV = 0; } - channelCV = channelCV + change; + channelCV = channelCV + encoderChange; if (channelCV == 0 || channelCV > 100) { channelCV = 0; channels[displayTab - 1].CV1Target = 0; @@ -347,19 +350,19 @@ void checkInputs() { saveState(); } } else if (displayScreen == 1 && !isRecording && !shiftBtnPushed) { - stepNumSelected = stepNumSelected + change; + stepNumSelected = stepNumSelected + encoderChange; if (stepNumSelected < -1 ) { stepNumSelected = -1; } else if (stepNumSelected > sequences[channels[displayTab - 1].seqPattern].length && !shiftBtnPushed) { stepNumSelected = 0; } } else if (displayScreen == 1 && !isRecording && stepNumSelected == -1 && shiftBtnPushed) { - if ((sequences[channels[displayTab - 1].seqPattern].length != 31 && change > 0) || - (sequences[channels[displayTab - 1].seqPattern].length != 0 && change < 0)) { - sequences[channels[displayTab - 1].seqPattern].length += change; + if ((sequences[channels[displayTab - 1].seqPattern].length != 31 && encoderChange > 0) || + (sequences[channels[displayTab - 1].seqPattern].length != 0 && encoderChange < 0)) { + sequences[channels[displayTab - 1].seqPattern].length += encoderChange; } } else if (displayScreen == 2 && !shiftBtnPushed) { - menuItem = menuItem + change; + menuItem = menuItem + encoderChange; if (menuItem > 100) { //for "negative" values menuItem = 0; } else if (menuItem > lastMenuItem) { @@ -368,7 +371,7 @@ void checkInputs() { } updateScreen(); - encPositionOld = encPosition; + encoderChange = 0; } //play button