diff --git a/Hardware/gtoe/midi-panel.kicad_pcb b/Hardware/gtoe/midi-panel.kicad_pcb index d030574..680d6da 100644 --- a/Hardware/gtoe/midi-panel.kicad_pcb +++ b/Hardware/gtoe/midi-panel.kicad_pcb @@ -8087,6 +8087,7 @@ (gr_line (start 97.62 161.03) (end 96.82 161.03) (layer "Edge.Cuts") (width 0.05) (tstamp 601bde20-61eb-49ab-8f7f-530cb12abd4f)) (gr_circle (center 64.71 82.29) (end 67.74 82.29) (layer "Edge.Cuts") (width 0.05) (fill none) (tstamp 657cd3f1-2e41-44b3-8034-6d394ba3318f)) (gr_circle (center 94.61 129) (end 95.66 129) (layer "Edge.Cuts") (width 0.05) (fill none) (tstamp 6a0981d5-08d6-40c8-b4a2-41753fd8531c)) + (gr_circle (center 94.61 151.52) (end 95.96 151.52) (layer "Edge.Cuts") (width 0.05) (fill none) (tstamp 6acce12f-b607-4db1-b1d6-0a2789449d91)) (gr_circle (center 64.71 48.59) (end 61.66 48.59) (layer "Edge.Cuts") (width 0.05) (fill none) (tstamp a079e287-f038-487b-8f6a-bfcda0331a0f)) (gr_circle (center 64.7 72.08) (end 65.75 72.08) (layer "Edge.Cuts") (width 0.05) (fill none) (tstamp a99f1583-1858-47bc-a23e-4b0348d21d69)) (gr_circle (center 74.71 90.09) (end 75.76 90.09) (layer "Edge.Cuts") (width 0.05) (fill none) (tstamp aff8863a-e54c-4813-859d-7d5b33e05755)) diff --git a/Software/Gravity/Gravity.ino b/Software/Gravity/Gravity.ino index 2239e50..bce60c0 100644 --- a/Software/Gravity/Gravity.ino +++ b/Software/Gravity/Gravity.ino @@ -39,7 +39,7 @@ bool rotateScreen = false; #define ANALOGUE_INPUT_1_PIN A2 #define ANALOGUE_INPUT_2_PIN A1 -const byte clockOutPin = 0; +const byte clockOutPin = 13; const int outsPins[6] = {6, 11, 7, 10, 8, 9}; bool rotateScreen = true; */ @@ -49,7 +49,7 @@ int CV1Calibration = 512; int CV2Calibration = 512; bool showDone = false; -const int subDivs[17] = { -24, -12, -8, -6, -4, -3, -2, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32 }; //positive - divide, negative - multiply, 0 - off +const int subDivs[20] = { -24, -12, -8, -6, -4, -3, -2, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 64, 128 }; //positive - divide, negative - multiply, 0 - off byte bpm = 130; byte bpmModulationChannel = 200; //0 - CV1, 1 - CV2, 255 - OFF @@ -114,6 +114,7 @@ unsigned int tickCount = 0; unsigned int pulseCount = 0; byte masterClockMode = 0; // 0 - internal, 1 - external 24ppqn, 2 - MIDI +byte extClockPPQN = 0; // 0 - 24, 1 - 4 (1/16) unsigned long lastExtPulseTime; unsigned long newExtPulseTime; @@ -141,6 +142,9 @@ unsigned long shiftPressedTime; unsigned long shiftReleasedTime; bool encBtnPushed; +int extResetCountdown; +int extTriggerCount; + //unsigned long lastInteractionTime; // used for display timeout U8G2_SSD1306_128X64_NONAME_2_HW_I2C u8g2(U8G2_R2, SCL, SDA, U8X8_PIN_NONE); @@ -163,22 +167,26 @@ const uint8_t velvetscreen[437] U8G2_FONT_SECTION("velvetscreen") = "\7p\10\255\364V\266\323\2q\7\255\364\216\257\5r\10\253d\242\32*\2t\6\255t\376#w\11" "\255\364V\245FN\13x\6\233dR\7\0\0\0\4\377\377\0"; -const uint8_t fabryka[450] U8G2_FONT_SECTION("fabryka") = - "\17\0\4\4\4\5\2\1\6\17\30\1\0\30\0\0\0\1K\0\0\1\245%'\17\37\313\330R#&" - "\32!F\14\211I\310\24!\65\204(MF\21)Cd\304\10\62b\14\215\60Vb\334\20\0/\15" - "\376\36\357\244$\351\77\35;\26\0\60$\216\37\17*\65,\210\35\264\335\61T\42\14\11\61#\306\210" - " \23\242\220\235\63h\303c$\330\250B\3\0\61\27\216\37\27\311\202\346\216\221\30Ed\324\230Q\202" - "\306\316\377\263\26\35\62\33\216\37\17*\65,\210\35\64\70v\246\344\316h\203\252$\321\261s\373\340\1" - "\3\63\35\216\37\17*\65,\210\35\64\70v(IZZKv\266\6\15\36#\301F\25\32\0\64\37" - "\216\37\227\240\331\20\32Bj\310\260\21\304F\214\33\61n\304\70\203\366\360\301\203\20m\347\3\65\32\216" - "\37\7\213.\306\316'\205\326\60!E\226\354\334\32\226\261\245FL" + "\64B\214\30\22\223\220)Bj\10Q\232\214\42R\206\310\210\21d\304\30\32a\254\304\270!\0/\15" + "\356=\336II\322\177:v,\0\60$\16\77\36TjX\20;h\273c\250D\30\22bF\214\21" + "A&D!;g\320\206\307H\260Q\205\6\0\61\27\16\77.\222\5\315\35#\61\212\310\250\61\243\4" + "\215\235\377g-:\62\33\16\77\36TjX\20;hp\354L\311\235\321\6UI\242c\347\366\301\3" + "\6\63\35\16\77\36TjX\20;hp\354P\222\264\264\226\354l\15\32= pulsePeriod && pulseCount < (PPQN - 1)) { // ((6 * (extTriggerCount + 1)) - 1)) { //this formula puts it out of sync, so there's PPQN-1 for now + tickCount = 0; + pulseCount++; + } + } if (masterClockMode == 2 && MIDIClockRecived) { // MIDI should happen here (needs testing) tickCount = 0; //to make things happen in the main clock function @@ -289,7 +305,7 @@ void externalClock() { lastExtPulseTime = newExtPulseTime; newExtPulseTime = millis(); - if (masterClockMode == 1) { // EXT-24 + if (masterClockMode == 1 && extClockPPQN == 0) { // EXT-24 //reset cycles if there was no pulses for a while if ((newExtPulseTime - lastExtPulseTime) > 125) { //125ms is 20bpm for (byte i = 0; i < 6; i++) { @@ -306,7 +322,33 @@ void externalClock() { } else { pulseCount = 0; } - } + } else if (masterClockMode == 1 && extClockPPQN == 1) { //EXT 1/16 + if (!isPlaying) { + isPlaying = true; + } + if ((newExtPulseTime - lastExtPulseTime) > 750) { + resetClocks(); + extResetCountdown = 0; + extTriggerCount = 0; + } + + if (extTriggerCount == 0) { //happens on beat + pulseCount = 0; + tickCount = 0; + } + if (extTriggerCount < 3) { + extTriggerCount++; + } else { + extTriggerCount = 0; + } + + if (extResetCountdown < 4) { //reset on the second beat (5th pulse), so that BPM is already calculated correctly + extResetCountdown++; + } else if (extResetCountdown == 4) { + resetClocks(); + extResetCountdown++; //to get out of the loop + } + } } void sendTriggers() { @@ -474,10 +516,7 @@ void calculateBPMTiming() { } pulsePeriod = 60000 / ((bpm + mod) * PPQN); - } else if (masterClockMode == 2) { //for external beat clock - pulsePeriod = (newExtPulseTime - lastExtPulseTime) / PPQN; - - } else if (masterClockMode == 3) { //for ext 1/16 clock (hardcoded) + } else if (masterClockMode == 1 && extClockPPQN == 1) { //for ext 1/16 clock (hardcoded) pulsePeriod = (newExtPulseTime - lastExtPulseTime) / 6; } } diff --git a/Software/Gravity/Interactions.ino b/Software/Gravity/Interactions.ino index c602793..037afe6 100644 --- a/Software/Gravity/Interactions.ino +++ b/Software/Gravity/Interactions.ino @@ -175,7 +175,11 @@ void checkInputs() { masterClockMode = 2; } saveState(); - } else if (insideTab && (menuItemSelected || shiftBtnPushed) && displayTab == 0 && menuItem == 2) { //Modulation channel + } else if (insideTab + && (menuItemSelected || shiftBtnPushed) + && displayTab == 0 + && menuItem == 2 + && masterClockMode == 0) { //Modulation channel bpmModulationChannel = bpmModulationChannel + change; if (bpmModulationChannel == 0 || bpmModulationChannel == 1) { bpmModulationRange = 1; @@ -186,7 +190,22 @@ void checkInputs() { bpmModulationChannel = 1; } saveState(); - } else if (insideTab && (menuItemSelected || shiftBtnPushed) && displayTab == 0 && menuItem == 3) { //Modulation range + } else if (insideTab + && (menuItemSelected || shiftBtnPushed) + && displayTab == 0 + && menuItem == 2 + && masterClockMode == 1) { //PPQN + extClockPPQN = extClockPPQN + change; + if (extClockPPQN > 100) { + extClockPPQN = 0; + } else if (extClockPPQN > 1) { + extClockPPQN = 1; + } + saveState(); + } else if (insideTab + && (menuItemSelected || shiftBtnPushed) + && displayTab == 0 + && menuItem == 3) { //Modulation range bpmModulationRange = bpmModulationRange + change; if (bpmModulationRange == 0) { bpmModulationRange = 1; @@ -196,7 +215,10 @@ void checkInputs() { bpmModulationRange = 5; } saveState(); - } else if (insideTab && (menuItemSelected || shiftBtnPushed) && displayTab != 0 && menuItem == 1) { //Channel Mode + } else if (insideTab + && (menuItemSelected || shiftBtnPushed) + && displayTab != 0 + && menuItem == 1) { //Channel Mode channels[displayTab - 1].mode = channels[displayTab - 1].mode + change; if (channels[displayTab - 1].mode > 100) { channels[displayTab - 1].mode = 0; @@ -206,7 +228,10 @@ void checkInputs() { channels[displayTab - 1].CV1Target = 0; channels[displayTab - 1].CV2Target = 0; saveState(); - } else if (insideTab && (menuItemSelected || shiftBtnPushed) && displayTab != 0 && menuItem == 2 && channels[displayTab - 1].mode == 0) { //Offset + } else if (insideTab + && (menuItemSelected || shiftBtnPushed) + && displayTab != 0 && menuItem == 2 + && channels[displayTab - 1].mode == 0) { //Offset channels[displayTab - 1].offset = channels[displayTab - 1].offset + change; if (channels[displayTab - 1].offset > 1000) { channels[displayTab - 1].offset = 0; @@ -214,7 +239,11 @@ void checkInputs() { channels[displayTab - 1].offset = channelPulsesPerCycle[displayTab-1]; } saveState(); - } else if (insideTab && (menuItemSelected || shiftBtnPushed) && displayTab != 0 && menuItem == 2 && channels[displayTab - 1].mode == 1) { //SUBDIV for RANDOM + } else if (insideTab + && (menuItemSelected || shiftBtnPushed) + && displayTab != 0 + && menuItem == 2 + && channels[displayTab - 1].mode == 1) { //SUBDIV for RANDOM channels[displayTab - 1].subDiv = channels[displayTab - 1].subDiv - change; if (channels[displayTab - 1].subDiv > 200) { channels[displayTab - 1].subDiv = 0; @@ -225,7 +254,11 @@ void checkInputs() { calculateCycles(); } saveState(); - } else if (insideTab && (menuItemSelected || shiftBtnPushed) && displayTab != 0 && menuItem == 3 && channels[displayTab - 1].mode == 0) { //CV for CLK + } else if (insideTab + && (menuItemSelected || shiftBtnPushed) + && displayTab != 0 + && menuItem == 3 + && channels[displayTab - 1].mode == 0) { //CV for CLK if (channels[displayTab - 1].CV1Target == 1 && channels[displayTab - 1].CV2Target == 0) { channelCV = 1; } else if (channels[displayTab - 1].CV1Target == 0 && channels[displayTab - 1].CV2Target == 1) { diff --git a/Software/Gravity/UI.ino b/Software/Gravity/UI.ino index 301929b..ba053ac 100644 --- a/Software/Gravity/UI.ino +++ b/Software/Gravity/UI.ino @@ -24,7 +24,7 @@ void updateScreen() { } else if (masterClockMode == 0 && bpmModulationRange != 0) { lastMenuItem = 3; } else if (masterClockMode == 1) { - lastMenuItem = 1; + lastMenuItem = 2; } else if (masterClockMode == 2) { lastMenuItem = 1; } @@ -34,6 +34,8 @@ void updateScreen() { valueStr = "MODE:"; } else if (i == 2 && masterClockMode == 0) { valueStr = "MOD:"; + } else if (i == 2 && masterClockMode == 1) { + valueStr = "PPQN:"; } else if (i == 3 && masterClockMode == 0) { valueStr = "RANGE:"; } @@ -62,6 +64,10 @@ void updateScreen() { valueStr = "CV2"; } else if (i == 2 && masterClockMode == 0 && bpmModulationRange == 0) { valueStr = "OFF"; + } else if (i == 2 && masterClockMode == 1 && extClockPPQN == 0) { + valueStr = "24"; + } else if (i == 2 && masterClockMode == 1 && extClockPPQN == 1) { + valueStr = "4"; } else if (i == 3 && bpmModulationRange != 0) { valueStr = String(bpmModulationRange * 10); } @@ -82,7 +88,7 @@ void updateScreen() { if (masterClockMode == 0) { bpmStr = String(bpm); } else if (masterClockMode == 1) { - bpmStr = "24"; + bpmStr = "EXT"; } else if (masterClockMode == 2) { bpmStr = "MIDI"; } @@ -109,11 +115,11 @@ void updateScreen() { } } - if (masterClockMode == 1) { + if (masterClockMode != 0) { //EXT and MIDI u8g2.setFont(fabryka); u8g2.drawButtonUTF8(leftOffset, 28, U8G2_BTN_BW0|U8G2_BTN_HCENTER, width, 0, 0, bpmChar ); - u8g2.setFont(velvetscreen); - u8g2.drawButtonUTF8(leftOffset, 40, U8G2_BTN_BW0|U8G2_BTN_HCENTER, width, 0, 2, "PPQN" ); + //u8g2.setFont(velvetscreen); + //u8g2.drawButtonUTF8(leftOffset, 40, U8G2_BTN_BW0|U8G2_BTN_HCENTER, width, 0, 2, "PPQN" ); } }