#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <elapsedMillis.h>
#include <EEPROM.h>
#include "variables.h"
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// #define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
///////////////////////////
// Create Clocks + Timeout Timers
/////////////////////////
elapsedMicros clock0Timer;
elapsedMicros clock1Timer;
elapsedMicros clock2Timer;
elapsedMicros clock3Timer;
elapsedMicros resetOutTimer;
elapsedMicros timeoutTimer;
elapsedMicros freerunTimer;
void setup() {
Serial.begin(115200);
Serial.println("=====================");
Serial.println(" Rusty Valve ");
Serial.println("=====================");
Serial.println("QUAD Clock Sequencer ");
Serial.println("=====================");
// get the savedSpaces array from EEPROM
//EEPROM.get(0, savedSpaces);
// initialise pins and interrupts
setPinModes();
setHardwareInterrupts();
// initialise arrays
preFill();
calcEuclideanGates(0);
calcEuclideanGates(1);
calcEuclideanGates(2);
calcEuclideanGates(3);
calcClock(0);
calcClock(1);
calcClock(2);
calcClock(3);
// initialise the display
initialiseDisplay();
// updateDisplay();
resetClock0();
resetClock1();
resetClock2();
resetClock3();
updateDisplay();
}
///////////////////////////
// Set Pin Modes
///////////////////////////
void setPinModes() {
// pinMode(upButtPin, INPUT);
// pinMode(downButtPin, INPUT);
// pinMode(leftButtPin, INPUT);
// pinMode(rightButtPin, INPUT);
// pinMode(encAPin, INPUT);
// pinMode(encBPin, INPUT);
// pinMode(encButtPin, INPUT);
// pinMode(clockSelectButtPin, INPUT);
// pinMode(pageSelectButtPin, INPUT);
// pinMode(clockResetButtPin, INPUT);
// pinMode(clockResetPin, INPUT);
pinMode(clock0Pin, OUTPUT);
pinMode(clock1Pin, OUTPUT);
pinMode(clock2Pin, OUTPUT);
pinMode(clock3Pin, OUTPUT);
pinMode(resetOutPin, OUTPUT);
///////////////////////////
// Set initial pin states
///////////////////////////
digitalWrite(clock0Pin, LOW);
digitalWrite(clock1Pin, LOW);
digitalWrite(clock2Pin, LOW);
digitalWrite(clock3Pin, LOW);
digitalWrite(resetOutPin, LOW);
}
///////////////////////////
// Set hardware interrupts on input pins
///////////////////////////
void setHardwareInterrupts() {
// attachInterrupt(digitalPinToInterrupt(upButtPin), upButtDOWN, RISING);
// attachInterrupt(digitalPinToInterrupt(downButtPin), downButtDOWN, RISING);
// attachInterrupt(digitalPinToInterrupt(leftButtPin), leftButtDOWN, RISING);
// attachInterrupt(digitalPinToInterrupt(rightButtPin), rightButtDOWN, RISING);
// attachInterrupt(digitalPinToInterrupt(encAPin), encARotated, RISING);
// attachInterrupt(digitalPinToInterrupt(encButtPin), encButtDOWN, RISING);
// attachInterrupt(digitalPinToInterrupt(clockSelectButtPin), clockSelectButtDOWN, RISING);
// attachInterrupt(digitalPinToInterrupt(pageSelectButtPin), pageSelectButtDOWN, RISING);
// attachInterrupt(digitalPinToInterrupt(clockResetButtPin), clockResetButtDOWN, RISING);
// attachInterrupt(digitalPinToInterrupt(clockResetPin), clockResetEXT, RISING);
}
///////////////////////////
// pre-fill the euclidGate, manualGate and manualSwing arrays with initial values of 1, 1 and 43 respectively
///////////////////////////
void preFill() {
for (uint8_t i = 0; i < 4; i++) {
for (uint8_t j = 0; j < MAX_STEPS + 1; j++) {
euclidGate[i][j] = 1;
manualGate[i][j] = 1;
manualSwing[i][j] = 43;
}
}
}
///////////////////////////
// Initialise display
///////////////////////////
void initialiseDisplay() {
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Clear the buffer
display.clearDisplay();
display.drawRect(0, 0, display.width(), display.height(), SSD1306_WHITE);
display.setTextSize(2); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.cp437(true); // Use full 256 char 'Code Page 437' font
// display the intro text
display.setCursor(5, 4);
display.print("Rusty");
display.setCursor(40, 19);
display.print("Valve");
display.setTextSize(1);
display.setCursor(5, 43);
display.print("QUAD");
display.setCursor(5, 53);
display.print("Clock Sequencer");
// update the display and delay by 5 seconds
display.display();
delay(500);
}
void loop() {
// check Clock 0 to see if it should be updated
if (clock0Timer >= stepHalfTime[0][currentStep[0]]) {
clockAction(0);
}
// check Clock 1 to see if it should be updated
if (clock1Timer >= stepHalfTime[1][currentStep[1]]) {
clockAction(1);
}
// check Clock 2 to see if it should be updated
if (clock2Timer >= stepHalfTime[2][currentStep[2]]) {
clockAction(2);
}
// check Clock 3 to see if it should be updated
if (clock3Timer >= stepHalfTime[3][currentStep[3]]) {
clockAction(3);
}
// check resetOutTimer to see if the pin should be set to LOW
if (resetOutTimerON == 1) {
if (resetOutTimer >= resetOutTimerTIME) {
digitalWrite(resetOutPin, LOW);
resetOutTimerON = 0;
// Serial.println("EXTERNAL reset turned OFF ");
}
}
// check timeoutTimer to see if screen should be turned off
if (timeOutOn == 1 && screenTimedOut == 0) {
if (timeoutTimer >= timeoutMicros[timeoutTime]) {
screenTimedOut = 1;
clearDisplay();
}
}
///////////////////////////
// receive commands over serial
///////////////////////////
if (Serial.available()) { // if there is data coming
String command = Serial.readStringUntil('\n'); // read string until newline character
if (command == "w") {
Serial.println("UP");
upButtDOWN();
}
if (command == "s") {
Serial.println("DOWN");
downButtDOWN();
}
if (command == "a") {
Serial.println("LEFT");
leftButtDOWN();
}
if (command == "d") {
Serial.println("RIGHT");
rightButtDOWN();
}
if (command == ".") {
Serial.println("ENCODER Rotate CW");
encARotated(1);
}
if (command == ",") {
Serial.println("ENCODER Rotate CCW");
encARotated(-1);
}
if (command == "/") {
Serial.println("ENCODER Button PRESSED");
encButtDOWN();
}
if (command == "c") {
Serial.println("CLOCK Button PRESSED");
clockSelectButtDOWN();
}
if (command == "p") {
Serial.println("PAGE Button PRESSED");
pageSelectButtDOWN();
}
if (command == "r") {
Serial.println("RESET Button PRESSED");
clockResetButtDOWN();
}
if (command == "e") {
Serial.println("EXTERNAL RESET Received");
clockResetEXT();
}
}
}