Files
GravityHW/software/GToE/GToE.ino
2023-01-22 18:33:17 +02:00

202 lines
4.5 KiB
C++

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RotaryEncoder.h>
#include <MsTimer2.h>
#include <EEPROM.h>
#define SCREEN_ADDRESS 0x3C
#define INPUT_CONNECTED_PIN 12
#define INPUT_PIN 2
#define ENC_BTN_PIN 17
#define ENC_D1_PIN 4
#define ENC_D2_PIN 3
#define START_STOP_BTN_PIN 14
//Output pins are defined in the array below
//TODO :
//Add min and max values
//External clock
//Switch to another timer lib (FlexiTimer?)
//Switch to U8G2 for screen
//Save state to EEPROM when stopped
int outsPins[6] = {5, 6, 7, 8, 9, 10};
int outsValues[6] = {1, 2, 4, -4, 1, 1}; //positive - divide, negative - multiply, 0 - off
int outsPeriods[6];
int outsClocksCounts[6] = {0, 0, 0, 0, 0, 0};
bool clockMode;
bool clockModeOld;
int inputMode; //clock, reset, start/stop
int clockCount = 0;
int bpm = 120;
int bpmPeriod;
bool isPlaying = 0;
int displayTab = 0;
int displayTabOld;
bool needToChangeTab = 0;
bool buttonPushed = false;
bool changesSaved;
int encPositionOld = 0;
Adafruit_SSD1306 display(128, 64, &Wire, -1);
RotaryEncoder encoder(ENC_D1_PIN, ENC_D2_PIN, RotaryEncoder::LatchMode::TWO03);
void setup() {
Serial.begin(9600);
pinMode(INPUT_CONNECTED_PIN, INPUT_PULLUP);
pinMode(ENC_BTN_PIN, INPUT_PULLUP);
pinMode(START_STOP_BTN_PIN, INPUT_PULLUP);
pinMode(INPUT_PIN, INPUT_PULLUP); //probably will need interrupt
for (int i=0; i<6; i++) {
pinMode(outsPins[i], OUTPUT);
}
display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
updateScreen();
updatePeriods();
MsTimer2::set(1, internalClock); // 1ms period
MsTimer2::start();
}
void loop() {
checkInputs();
}
void internalClock() {
if (isPlaying) {
for (int i = 0; i<6; i++) {
if (outsClocksCounts[i] >= outsPeriods[i]) {
outsClocksCounts[i] = 0;
}
if (outsClocksCounts[i] == 0) {
digitalWrite(outsPins[i], HIGH);
}
if (outsClocksCounts[i] == 15) {
digitalWrite(outsPins[i], LOW);
}
outsClocksCounts[i]++;
}
}
}
void updatePeriods() {
bpmPeriod = 60000 / bpm;
for (int i = 0; i<6; i++) {
if (outsValues[i]>0) {
outsPeriods[i] = bpmPeriod * outsValues[i];
} else {
outsPeriods[i] = bpmPeriod / outsValues[i] * - 1;
}
}
}
void checkInputs() {
clockMode = digitalRead(INPUT_CONNECTED_PIN);
if (clockMode != clockModeOld) {
updateScreen();
clockModeOld = clockMode;
}
if (needToChangeTab == 0 && digitalRead(ENC_BTN_PIN) == 0) {
needToChangeTab = 1;
}
if (needToChangeTab == 1 && digitalRead(ENC_BTN_PIN) == 1) {
displayTabOld = displayTab;
displayTab++;
if (displayTab>6) {
displayTab = 0;
}
needToChangeTab = 0;
updateScreen();
}
encoder.tick();
int encPosition = encoder.getPosition();
if (encPositionOld != encPosition) {
int change = encPositionOld - encPosition;
if (displayTab == 0) {
bpm = bpm + change;
} else {
outsValues[displayTab-1] = outsValues[displayTab-1] + change;
}
updatePeriods();
updateScreen();
encPositionOld = encPosition;
}
if (!digitalRead(START_STOP_BTN_PIN) && !buttonPushed) {
isPlaying = !isPlaying;
buttonPushed = true;
} else if (digitalRead(START_STOP_BTN_PIN) && buttonPushed) {
buttonPushed = false;
}
}
void updateScreen() {
display.clearDisplay();
//Tabs
display.setCursor(0,0);
display.setTextSize(1);
if (displayTab == 0) {
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.print(F(" "));
display.setTextColor(SSD1306_WHITE);
display.print(F(" bpm "));
} else {
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.print(F(" bpm"));
}
for (int i = 1; i <= 6; i++) {
if (displayTab == i) {
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.print(" ");
display.setTextColor(SSD1306_WHITE);
display.print(" ");
display.print(i);
display.print(" ");
} else {
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.print(" ");
display.print(i);
}
}
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.println(F(" "));
display.println();
//Content
display.setTextSize(3);
display.setTextColor(SSD1306_WHITE);
if (displayTab == 0) {
display.print(bpm);
display.println(F("bpm"));
} else {
if (outsValues[displayTab-1]>0) {
display.print(F("/"));
} else {
display.print(F("x"));
}
display.print(abs(outsValues[displayTab-1]));
}
display.display();
}