Advertisement
Guest User

Big_Wheel_Macro_Pad_Firmware_Edit.ino

a guest
Dec 30th, 2020
384
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 18.75 KB | None | 0 0
  1. /*
  2.    "Big Wheel" macro pad firmware
  3.    Copyright Sept. 2020 Zack Freedman of Voidstar Lab and edited by Omnisairen
  4.    Licensed Creative Commons 4.0 Noncommercial Share-Alike
  5.  
  6.    This code is designed to run on this hardware: https://github.com/ZackFreedman/Big-Wheel
  7.    This was used in a YouTube video! Check it out! https://www.youtube.com/watch?v=72a85tWOJVY
  8.  
  9.    Intended for Teensy LC, but should also work on Teensy 3.X and maybe Teensy 4.0
  10.    These hotkeys and shortcuts are designed to control Premiere Pro, but you do you fam
  11.  
  12.    REMEMBER: Tools --> USB Type --> Serial + Keyboard + Mouse + Joystick
  13. */
  14.  
  15. #include <Keyboard.h>
  16. #include <Encoder.h>
  17. #include "actions.h"
  18. #include "pins.h"
  19.  
  20. //#define DEBUG_DUMP_EVENTS
  21. //#define DEBUG_DUMP_MATRIX
  22. //#define DEBUG_DUMP_WHEEL_SPEED
  23. //#define DEBUG_PLOT_WHEEL_SPEED
  24. //#define DEBUG_SHUTTLE
  25.  
  26. Encoder topKnob(topKnobA, topKnobB);
  27. Encoder middleKnob(middleKnobA, middleKnobB);
  28. Encoder lowerKnob(lowerKnobA, lowerKnobB);
  29. Encoder wheel(wheelA, wheelB);
  30.  
  31. long lastKnobPositions[4] = {0, 0, 0, 0};
  32. int lastKnobDeltas[4];
  33. bool lastSwitchStates[18];
  34. bool debouncedSwitchStates[18];
  35. bool lastDebouncedSwitchStates[18];
  36. elapsedMillis switchDebounceTimestamps[18];
  37. #define switchDebounceTime 50
  38.  
  39. int lastActions[6];
  40. int allActionsThisFrame[6];
  41. byte actionIndex = 0;
  42.  
  43. // Used to calculate rotational velocity of big wheel
  44. // 1 detent = 4 pulses in the same direction
  45. // 1 delta = Time between two successive detents, in ms
  46. #define wheelDetentDeltaAverageCount 5  // More detents = smoother but laggier shuttling
  47.  
  48. // How many ms must elapse without wheel motion before resetting velocity measurements
  49. // wheelTimeout must be > 1000.0 / max(abs(minimumDpsForReverse), minimumDpsForPlay)
  50. #define wheelTimeout 50
  51.  
  52. // More detents = more predictable but laggier shuttling.
  53. // minimumWheelDetentsToAverage must be <= wheelDetentDeltaAverageCount!
  54. #define minimumWheelDetentsToAverage 2
  55.  
  56. elapsedMillis timeSinceLastWheelDetent;
  57. long wheelDetentDeltas[wheelDetentDeltaAverageCount];
  58. byte wheelDetentDeltaIndex;  // Used to treat wheelDetentDeltas as a circular buffer
  59. float averageWheelDetentDelta;
  60.  
  61. // Shuttle states. In normal mode, one big knob detent (4 pulses) moves by 1 frame.
  62. // In other states, a shuttle movement (Hotkeys J or K in Premiere) is in effect.
  63. #define NO_STATE -255 // Shuttle state should never be this
  64. #define STATE_TRIPLE_REVERSE -3
  65. #define STATE_DOUBLE_REVERSE -2
  66. #define STATE_REVERSE -1
  67. #define STATE_NORMAL 0
  68. #define STATE_PLAY 1
  69. #define STATE_DOUBLE_PLAY 2
  70. #define STATE_TRIPLE_PLAY 3
  71.  
  72. // Minimum speed the wheel must spin to engage a shuttle mode
  73. // DPS = detents per second
  74. // Positive = clockwise
  75. #define minimumDpsForTripleReverse -1140
  76. #define minimumDpsForDoubleReverse -1130
  77. #define minimumDpsForReverse -1120
  78. #define minimumDpsForPlay 1125
  79. #define minimumDpsForDoubleSpeed 1140
  80. #define minimumDpsForTripleSpeed 1150
  81.  
  82. // To engage a shuttle mode, user must keep turning wheel at the threshold speed,
  83. // or a higher threshold speed, for this many ms.
  84. // Increase to make shuttling more predictable but less responsive.
  85. // No effect on dead stops - wheelTimeout always takes priority.
  86. #define timeUntilSpeedTransition 200
  87.  
  88. int shuttleState = STATE_NORMAL;
  89. int stateTransitioningInto = NO_STATE;
  90. elapsedMillis speedTransitionTimer;
  91.  
  92. // Special behavior - turning wheel while holding ALT key (2, 1)
  93. // locks the shuttle into the Play or Reverse state, making viewing more comfortable.
  94. // Any wheel movement, even one detent, unlocks the shuttle and returns to the Normal state.
  95. bool shuttleLocked = false;
  96. elapsedMillis shuttleLockTimer;
  97. #define shuttleLockout 200  //  Wheel movement is ignored for this many ms after locking the shuttle.
  98.  
  99. // Lock the system by holding ALT (2, 1) and pressing Undo (2, 6)
  100. bool systemLocked = false;  // While the system is locked, no keystrokes are sent over USB.
  101. bool lockKeysLatched = false;  // After locking/unlocking, both keys are disabled until both are released
  102. elapsedMillis ctrlGuardTimer;
  103. // When ALT is pressed, user might be locking system.
  104. // Don't send ALT until this many ms have passed.
  105. #define ctrlGracePeriod 50
  106.  
  107. // Basic event buffer to collect all applicable shortcut/hotkey actions and send appropriate keystrokes
  108. // Up to 6 actions can be queued, because I don't think the user can realistically hit more.
  109. void queueAction(int action) {
  110. #ifdef DEBUG_DUMP_EVENTS
  111.   Serial.print("Action: ");
  112.   Serial.println(action);
  113. #endif
  114.  
  115.   if (action != NO_ACTION && actionIndex < 7) {
  116.     allActionsThisFrame[actionIndex] = action;
  117.     actionIndex++;
  118.   }
  119. }
  120.  
  121. void setup() {
  122.   Serial.begin(9600);
  123.  
  124.   // Prepare key matrix pins (including encoder clicks)
  125.   // Note that the Encoder library prepares its own pins.
  126.   for (int i = 0; i < 6; i++) {
  127.     pinMode(allButtonRowPins[i], OUTPUT);
  128.     digitalWrite(allButtonRowPins[i], HIGH);
  129.     pinMode(allButtonColumnPins[i], INPUT_PULLUP);
  130.   }
  131. }
  132.  
  133. void loop() {
  134.   long knobPositions[] = {topKnob.read(), middleKnob.read(), lowerKnob.read(), wheel.read()};
  135.   int knobDeltas[] = {0, 0, 0, 0};
  136.   bool switchStates[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  137.   for (int i = 0; i < 6; i++) allActionsThisFrame[i] = NO_ACTION;
  138.   actionIndex = 0;
  139.  
  140.   // This is necessary to implement shuttle lock
  141.   bool ctrlBeingHeld = debouncedSwitchStates[15];
  142.  
  143.   if (timeSinceLastWheelDetent >= wheelTimeout) {
  144. #ifdef DEBUG_SHUTTLE
  145.     if (averageWheelDetentDelta != 0)
  146.       Serial.println("Resetting speedometer");
  147. #endif
  148.  
  149.     for (int i = 0; i < wheelDetentDeltaAverageCount; i++)
  150.       wheelDetentDeltas[i] = 0;
  151.     wheelDetentDeltaIndex = 0;
  152.  
  153.     averageWheelDetentDelta = 0;
  154.  
  155.     if (!shuttleLocked && shuttleState != STATE_NORMAL) {
  156. #ifdef DEBUG_SHUTTLE
  157.       Serial.println("Stopping shuttle (timeout)");
  158. #endif
  159.  
  160.       Keyboard.release(MODIFIERKEY_GUI);
  161.  
  162.       Keyboard.press(KEY_K);
  163.       Keyboard.release(KEY_K);
  164.  
  165.       if (ctrlBeingHeld)
  166.         Keyboard.press(MODIFIERKEY_GUI);
  167.  
  168.       shuttleState = STATE_NORMAL;
  169.     }
  170.  
  171.     stateTransitioningInto = NO_STATE;
  172.   }
  173.  
  174.  
  175.   for (int i = 0; i < 3; i++) {
  176.     digitalWrite(leftButtonRowPins[i], LOW);
  177.     for (int j = 0; j < 3; j++) {
  178.       if (!digitalRead(leftButtonColumnPins[j])) {
  179. #ifdef DEBUG_DUMP_MATRIX
  180.         Serial.print("Left: ");
  181.         Serial.print(i);
  182.         Serial.print(',');
  183.         Serial.print(j);
  184.         Serial.print(" (Button ");
  185.         Serial.print(keyMatrix[0][i][j]);
  186.         Serial.println(')');
  187. #endif
  188.  
  189.         switchStates[keyMatrix[0][i][j]] = true;
  190.       }
  191.     }
  192.     digitalWrite(leftButtonRowPins[i], HIGH);
  193.  
  194.     digitalWrite(rightButtonRowPins[i], LOW);
  195.     for (int j = 0; j < 3; j++) {
  196.       if (!digitalRead(rightButtonColumnPins[j])) {
  197. #ifdef DEBUG_DUMP_MATRIX
  198.         Serial.print("Right: ");
  199.         Serial.print(i);
  200.         Serial.print(',');
  201.         Serial.print(j);
  202.         Serial.print(" (Button ");
  203.         Serial.print(keyMatrix[1][i][j]);
  204.         Serial.println(')');
  205. #endif
  206.  
  207.         switchStates[keyMatrix[1][i][j]] = true;
  208.       }
  209.     }
  210.     digitalWrite(rightButtonRowPins[i], HIGH);
  211.   }
  212.  
  213.   for (int i = 0; i < 18; i++) {
  214.     if (switchStates[i] != lastSwitchStates[i]) {
  215.       switchDebounceTimestamps[i] = 0;
  216.     }
  217.  
  218.     if (switchDebounceTimestamps[i] >= switchDebounceTime) {
  219.       lastDebouncedSwitchStates[i] = debouncedSwitchStates[i];
  220.       debouncedSwitchStates[i] = switchStates[i];
  221.     }
  222.  
  223.     // Perform most actions only on falling edge
  224.     if (debouncedSwitchStates[i] && !lastDebouncedSwitchStates[i]) {
  225.       // Special buttons with multiple roles
  226.       if (i == 15) {
  227.         if (!debouncedSwitchStates[16] && !lockKeysLatched)
  228.           queueAction(switchAssignments[i]);
  229.       }
  230.       else if (i == 16) {
  231.         if (!debouncedSwitchStates[15] && !lockKeysLatched)
  232.           queueAction(switchAssignments[i]);
  233.       }
  234.       else {
  235. #ifdef DEBUG_DUMP_EVENTS
  236.         Serial.print("Queuing action ");
  237.         Serial.println(switchAssignments[i]);
  238. #endif
  239.         queueAction(switchAssignments[i]);
  240.       }
  241.     }
  242.   }
  243.  
  244.   if (!debouncedSwitchStates[15] && lastDebouncedSwitchStates[15]) {
  245.     Keyboard.release(MODIFIERKEY_GUI);
  246.     Serial.println("Ctrl up");
  247.   }
  248.  
  249.   if (!systemLocked) {
  250.     for (int i = 0; i < 4; i++) {
  251.       if (abs(knobPositions[i] - lastKnobPositions[i]) >= 4) {
  252. #ifdef DEBUG_DUMP_EVENTS
  253.         Serial.print("Knob ");
  254.         Serial.print(i);
  255.         Serial.print(" ");
  256.         Serial.print(lastKnobPositions[i]);
  257.         Serial.print(" --> ");
  258.         Serial.print(knobPositions[i]);
  259.         Serial.print(" ");
  260. #endif
  261.  
  262.         if (knobPositions[i] > lastKnobPositions[i]) {
  263. #ifdef DEBUG_DUMP_EVENTS
  264.           Serial.println("CW");
  265. #endif
  266.           knobDeltas[i] = 1;
  267.         }
  268.         else {
  269. #ifdef DEBUG_DUMP_EVENTS
  270.           Serial.println("CCW");
  271. #endif
  272.           knobDeltas[i] = -1;
  273.         }
  274.  
  275.         lastKnobPositions[i] = knobPositions[i];
  276.       }
  277.     }
  278.  
  279.     if (knobDeltas[3] != 0) {
  280.       wheelDetentDeltas[wheelDetentDeltaIndex] =
  281.         long(timeSinceLastWheelDetent) * knobDeltas[3];  // Positive: CW, Negative: CCW
  282.  
  283.       wheelDetentDeltaIndex = (wheelDetentDeltaIndex + 1) % wheelDetentDeltaAverageCount;  // Baby's first circular buffer
  284.  
  285.       float detentsAveraged = 0;  // I think this needs to be a float or the division op will be truncated
  286.       long runningTotal = 0;
  287.       for (int i = 0; i < wheelDetentDeltaAverageCount; i++) {
  288.         if (wheelDetentDeltas[i] == 0) break;
  289.  
  290.         detentsAveraged++;
  291.         runningTotal += wheelDetentDeltas[i];
  292.       }
  293.  
  294.       if (detentsAveraged >= minimumWheelDetentsToAverage) {
  295.         averageWheelDetentDelta = float(runningTotal) / detentsAveraged;
  296.  
  297. #ifdef DEBUG_DUMP_WHEEL_SPEED
  298.         Serial.print(averageWheelDetentDelta);
  299.         Serial.print("ms --> ");
  300.         Serial.print(1000.0 / averageWheelDetentDelta);
  301.         Serial.println("/sec");
  302. #endif
  303.       }
  304.  
  305.       timeSinceLastWheelDetent = 0;
  306.     }
  307.  
  308.     for (int i = 0; i < 4; i++) {
  309.       // CW
  310.       if (knobDeltas[i] > 0) {
  311.         switch (i) {
  312.           case 0:
  313.             queueAction(topKnobAssignments[0]);
  314.             break;
  315.           case 1:
  316.             queueAction(middleKnobAssignments[0]);
  317.             break;
  318.           case 2:
  319.             queueAction(lowerKnobAssignments[0]);
  320.             break;
  321.           case 3:
  322.             if (shuttleState == STATE_NORMAL)
  323.               queueAction(wheelAssignments[0]);
  324.             break;
  325.           default:
  326.             break;
  327.         }
  328.       }
  329.       // CCW
  330.       else if (knobDeltas[i] < 0) {
  331.         switch (i) {
  332.           case 0:
  333.             queueAction(topKnobAssignments[1]);
  334.             break;
  335.           case 1:
  336.             queueAction(middleKnobAssignments[1]);
  337.             break;
  338.           case 2:
  339.             queueAction(lowerKnobAssignments[1]);
  340.             break;
  341.           case 3:
  342.             if (shuttleState == STATE_NORMAL)
  343.               queueAction(wheelAssignments[1]);
  344.             break;
  345.           default:
  346.             break;
  347.         }
  348.       }
  349.     }
  350.  
  351.     if (debouncedSwitchStates[15]) {  // Lock shuttle if CTRL is held
  352.       if (shuttleLockTimer > shuttleLockout && knobDeltas[3] != 0) {
  353.         Keyboard.release(MODIFIERKEY_GUI);
  354.  
  355.         Serial.print("Knob position: ");
  356.         Serial.print(knobPositions[3]);
  357.         Serial.print(" Last position: ");
  358.         Serial.println(lastKnobPositions[3]);
  359.  
  360.         if (knobDeltas[3] == 1) {
  361.           if (shuttleState != STATE_PLAY) {
  362. #ifdef DEBUG_SHUTTLE
  363.             Serial.println("Locking shuttle in Play");
  364. #endif
  365.  
  366.             shuttleState = STATE_PLAY;
  367.             Keyboard.press(KEY_K);
  368.             Keyboard.release(KEY_K);
  369.             Keyboard.press(KEY_L);
  370.             Keyboard.release(KEY_L);
  371.           }
  372.         }
  373.         else if (knobDeltas[3] == -1) {
  374.           if (shuttleState != STATE_REVERSE) {
  375. #ifdef DEBUG_SHUTTLE
  376.             Serial.println("Locking shuttle in Reverse");
  377. #endif
  378.  
  379.             shuttleState = STATE_REVERSE;
  380.             Keyboard.press(KEY_K);
  381.             Keyboard.release(KEY_K);
  382.             Keyboard.press(KEY_J);
  383.             Keyboard.release(KEY_J);
  384.           }
  385.         }
  386.  
  387.         stateTransitioningInto = NO_STATE;
  388.         shuttleLocked = true;
  389.         shuttleLockTimer = 0;
  390.  
  391.         Keyboard.press(MODIFIERKEY_GUI);
  392.       }
  393.     }
  394.     else {
  395.       if (knobDeltas[3] != 0 && shuttleLocked) {
  396. #ifdef DEBUG_SHUTTLE
  397.         Serial.print("Shuttle unlocked");
  398. #endif
  399.  
  400.         Keyboard.press(KEY_K);
  401.         Keyboard.release(KEY_K);
  402.         shuttleState = STATE_NORMAL;
  403.         shuttleLocked = false;
  404.       }
  405.  
  406.       int stateShuttleShouldBeIn = NO_STATE;
  407.  
  408.       if (averageWheelDetentDelta == 0) {  // If wheel is still, remain locked or return to frame-by-frame scrubbing
  409.         if (shuttleLocked)
  410.           stateShuttleShouldBeIn = shuttleState;
  411.         else
  412.           stateShuttleShouldBeIn = STATE_NORMAL;
  413.       }
  414.       else {  // Wheel is moving and ALT is up. Are we moving fast enough to shuttle?
  415.         float clicksPerSecond = 1000.0 / averageWheelDetentDelta;
  416.  
  417.         if (clicksPerSecond >= minimumDpsForTripleSpeed)
  418.           stateShuttleShouldBeIn = STATE_TRIPLE_PLAY;
  419.         else if (clicksPerSecond >= minimumDpsForDoubleSpeed)
  420.           stateShuttleShouldBeIn = STATE_DOUBLE_PLAY;
  421.         else if (clicksPerSecond >= minimumDpsForPlay)
  422.           stateShuttleShouldBeIn = STATE_PLAY;
  423.         else if (clicksPerSecond <= minimumDpsForTripleReverse)
  424.           stateShuttleShouldBeIn = STATE_TRIPLE_REVERSE;
  425.         else if (clicksPerSecond <= minimumDpsForDoubleReverse)
  426.           stateShuttleShouldBeIn = STATE_DOUBLE_REVERSE;
  427.         else if (clicksPerSecond <= minimumDpsForReverse)
  428.           stateShuttleShouldBeIn = STATE_REVERSE;
  429.         else
  430.           stateShuttleShouldBeIn = STATE_NORMAL;
  431.       }
  432.  
  433.       if (shuttleState == stateShuttleShouldBeIn) {  // No need to change state - we're already there
  434.         if (stateTransitioningInto != NO_STATE) {
  435. #ifdef DEBUG_SHUTTLE
  436.           Serial.println("Cancelling transition");
  437. #endif
  438.  
  439.           speedTransitionTimer = 0;
  440.         }
  441.         stateTransitioningInto = NO_STATE;
  442.       }
  443.  
  444.       // To switch into a shuttle state, the wheel needs to keep spinning
  445.       // at the appropriate speed or faster for a period of time.
  446.       else if (stateTransitioningInto == stateShuttleShouldBeIn ||
  447.                (stateTransitioningInto < 0 && stateShuttleShouldBeIn < stateTransitioningInto) ||
  448.                (stateTransitioningInto > 0 && stateShuttleShouldBeIn > stateTransitioningInto)) {
  449.         if (speedTransitionTimer >= timeUntilSpeedTransition) {
  450.           if (stateTransitioningInto == STATE_NORMAL) {
  451.             // Any transition to normal mode (frame-by-frame scrubbing) happens immediately.
  452.             // The user must be able to precisely control the playhead at a moment's notice.
  453.  
  454. #ifdef DEBUG_SHUTTLE
  455.             Serial.println("Stopping shuttle (slowdown)");
  456. #endif
  457.  
  458.             Keyboard.press(KEY_K);
  459.             Keyboard.release(KEY_K);
  460.           }
  461.           else {
  462.             if (stateTransitioningInto == NO_STATE) {
  463. #ifdef DEBUG_SHUTTLE
  464.               Serial.println("Tried to transition into NO_STATE");
  465. #endif
  466.             }
  467.             else {
  468.               // Successive presses of the J and L keys control shuttle speed in Premiere Pro.
  469.               // Pressing L starts shuttling at normal speed, L again goes to double speed,
  470.               // then J goes back to normal speed, then J twice more reverses
  471.               byte shiftsToPerform = abs(shuttleState - stateTransitioningInto);
  472.               bool shiftDirection = stateTransitioningInto > shuttleState;
  473.  
  474. #ifdef DEBUG_SHUTTLE
  475.               Serial.print(shiftDirection ? ">>> " : "<<< ");
  476.               Serial.print("Shifting shuttle speed ");
  477.               Serial.print(shiftDirection ? "up " : "down ");
  478.               Serial.print(shiftsToPerform);
  479.               Serial.print(" times, from ");
  480.               Serial.print(shuttleState);
  481.               Serial.print(" to ");
  482.               Serial.println(stateTransitioningInto);
  483. #endif
  484.  
  485.               if (shuttleLocked)  // We can adjust the speed of a locked shuttle...
  486.                 Keyboard.release(MODIFIERKEY_GUI);  // ...but not by pressing CTRL + L
  487.  
  488.               for (int i = 0; i < shiftsToPerform; i++) {
  489.                 if (shiftDirection) {
  490.                   Keyboard.press(KEY_L);
  491.                   Keyboard.release(KEY_L);
  492.                 }
  493.                 else {
  494.                   Keyboard.press(KEY_J);
  495.                   Keyboard.release(KEY_J);
  496.                 }
  497.               }
  498.  
  499.               if (shuttleLocked)
  500.                 Keyboard.press(MODIFIERKEY_GUI);
  501.             }
  502.           }
  503.  
  504.           shuttleState = stateTransitioningInto;
  505.           stateTransitioningInto = NO_STATE;
  506.         }
  507.       }
  508.       else {
  509. #ifdef DEBUG_SHUTTLE
  510.         Serial.print("Starting transition to ");
  511.         Serial.println(stateShuttleShouldBeIn);
  512. #endif
  513.  
  514.         stateTransitioningInto = stateShuttleShouldBeIn;
  515.         speedTransitionTimer = 0;
  516.       }
  517.     }
  518.  
  519.     if (timeSinceLastWheelDetent >= wheelTimeout) {
  520.       for (int i = 0; i < wheelDetentDeltaAverageCount; i++)
  521.         wheelDetentDeltas[i] = 0;
  522.       wheelDetentDeltaIndex = 0;
  523.     }
  524.  
  525. #ifdef DEBUG_PLOT_WHEEL_SPEED
  526.     // Good for making your own thresholds for shuttling
  527.     if (averageWheelDetentDelta == 0)
  528.       Serial.println(0.0);
  529.     else
  530.       Serial.println(1000.0 / averageWheelDetentDelta);
  531. #endif
  532.   }
  533.  
  534.  
  535.   if (!systemLocked) {
  536.     for (int i = 0; i < 6; i++) {
  537.       bool actionAlreadyDone = false;
  538.  
  539.       if (allActionsThisFrame[i] == NO_ACTION) continue;
  540.  
  541.       for (int j = 0; j < 6; j++) {
  542.         if (lastActions[j] == allActionsThisFrame[i]) {
  543.           actionAlreadyDone = true;
  544.           break;
  545.         }
  546.       }
  547.  
  548.       if (!actionAlreadyDone) {
  549.         performAction(allActionsThisFrame[i]);
  550.       }
  551.     }
  552.   }
  553.  
  554.   if (!debouncedSwitchStates[15] && !debouncedSwitchStates[16])
  555.     lockKeysLatched = false;
  556.  
  557.   if (debouncedSwitchStates[15] && debouncedSwitchStates[16] && !lockKeysLatched) {
  558.     Keyboard.releaseAll();
  559.  
  560.     for (int i = 0; i < 6; i++) {
  561.       lastActions[i] = 0;
  562.       allActionsThisFrame[i] = 0;
  563.     }
  564.  
  565.     if (systemLocked) {
  566.       Serial.println("System unlocked");
  567.       systemLocked = false;
  568.     }
  569.     else {
  570.       Serial.println("System locked");
  571.       systemLocked = true;
  572.     }
  573.  
  574.     lockKeysLatched = true;
  575.   }
  576.  
  577.   for (int i = 0; i < 6; i++)
  578.     lastActions[i] = allActionsThisFrame[i];
  579.  
  580.   for (int i = 0; i < 6; i++)
  581.     lastKnobDeltas[i] = knobDeltas[i];
  582.  
  583.   for (int i = 0; i < 18; i++)
  584.     lastSwitchStates[i] = switchStates[i];
  585.  
  586. #ifdef DEBUG_PLOT_WHEEL_SPEED
  587.   // Don't kick computer in the crotch with firehose of USB traffic
  588.   delay(10);
  589. #endif
  590. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement