#include #include #include #include #include #include "globals.h" #include "Out.h" #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C #define CLK 2 #define DT 3 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); byte play = 1; byte BPM = 100; unsigned long minute = 60000000L; byte ppqn = 96; unsigned long period = (minute / BPM) / ppqn; volatile boolean beatToggle = false; Out out1(4); Out out2(5); Out out3(6); Out out4(7); Out out5(8); Out out6(9); Out out7(10); Out out8(11); byte btnPin = 13; byte btnState = 0; volatile long rPotPos = 0; unsigned long rPotLastUpdate = 0; const unsigned long rPotThrottle = 50; void setup() { Serial.begin(9600); pinMode(btnPin, INPUT_PULLUP); // rotary encoder set up pinMode(CLK, INPUT_PULLUP); pinMode(DT, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(CLK), updateEncoder, FALLING); if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); for (;;); } display.clearDisplay(); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(0, 0); String bpmString = "BPM: "; String bpmCalculatedString = bpmString + BPM; display.println(bpmCalculatedString); display.display(); // init timer Timer1.initialize(1000000); Timer1.attachInterrupt(clock); Timer1.setPeriod(period); // init outputs out1.setLen(period); out2.setLen(period); out3.setLen(period); out4.setLen(period); out5.setLen(period); out6.setLen(period); out7.setLen(period); out8.setLen(period); // manual setup out1.setDiv(8, 0); out1.setWidth(50); out2.setDiv(4, 0); out2.setWidth(50); out3.setDiv(2, 0); out3.setWidth(50); out4.setDiv(1); out4.setWidth(50); out5.setDiv(2); out5.setWidth(50); out6.setDiv(4); out6.setWidth(50); out7.setDiv(8); out7.setWidth(50); out8.setDiv(16); out8.setWidth(50); } void clock(void) { if (play == 1) { beatToggle = true; } } void loop() { if (beatToggle) { out1.turnOn(); out2.turnOn(); out3.turnOn(); out4.turnOn(); out5.turnOn(); out6.turnOn(); out7.turnOn(); out8.turnOn(); beatToggle = false; } out1.turnOff(); out2.turnOff(); out3.turnOff(); out4.turnOff(); out5.turnOff(); out6.turnOff(); out7.turnOff(); out8.turnOff(); checkBtn(); checkRPot(); } void checkBtn() { byte currentBtnState = digitalRead(btnPin); if (currentBtnState != btnState) { if (currentBtnState == 1) { play = (play == 1) ? 0 : 1; }; } btnState = currentBtnState; }; void checkRPot() { if (millis() - rPotLastUpdate >= rPotThrottle) { noInterrupts(); long currentPos = rPotPos; interrupts(); // Print position only if it has changed static long previousPos = -999; if (currentPos != previousPos) { Serial.print("Encoder Position: "); Serial.println(currentPos); previousPos = currentPos; } rPotLastUpdate = millis(); // Reset the timer for throttling the output } } void updateEncoder() { // The ISR should be as short and fast as possible // Check the state of the DT pin to determine direction if (digitalRead(3) == LOW) { rPotPos++; // Clockwise } else { rPotPos--; // Counter-clockwise } }