#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <elapsedMillis.h>
#include "variables.h"
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// // Declaration for an SSD1306 display connected to SPI (MOSI, SCK pins)
// #define OLED_DC 18
// #define OLED_CS 19
// #define OLED_RESET 10
// Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, OLED_DC, OLED_RESET, OLED_CS);
elapsedMillis testTimer;
elapsedMicros benchmarkTimer;
void setup() {
// // begin SPI interface
// SPI.begin();
Serial.begin(115200);
Serial.println("=============");
Serial.println(" Rusty Valve ");
Serial.println("=============");
Serial.println(" Arpeggiator ");
Serial.println("=============");
preFill();
getRandomSeeds();
setPinModes();
// setHardwareInterrupts();
getInitialValues();
calcArp();
parseRoot();
parseCurrentRoot();
initialiseDisplay();
updateDisplay();
sendNote();
testTimer = 0;
}
///////////////////////////
// pre-fill the euclidGate array with initial values of 1
///////////////////////////
void preFill() {
for (uint8_t i = 0; i < MAX_STEPS; i++) {
arpSequence[i] = -1;
}
}
///////////////////////////
// Get Random Seed Values
///////////////////////////
void getRandomSeeds() {
// // timing test
// uint32_t benchTime = 0;
// benchmarkTimer = 0;
// //
randomSeeds[0] = analogRead(A3);
randomSeeds[1] = analogRead(A2);
randomSeeds[2] = analogRead(A1);
randomSeeds[3] = analogRead(A2);
randomSeeds[4] = analogRead(A5);
randomSeeds[5] = analogRead(A4);
randomSeeds[6] = analogRead(A3);
randomSeeds[7] = analogRead(A5);
randomSeeds[8] = analogRead(A2);
randomSeeds[9] = analogRead(A5);
randomSeeds[10] = analogRead(A2);
randomSeeds[11] = analogRead(A0);
randomSeeds[12] = analogRead(A4);
randomSeeds[13] = analogRead(A3);
randomSeeds[14] = analogRead(A0);
randomSeeds[15] = analogRead(A5);
uint16_t randomSeedInt = 0;
uint8_t thisRandomChooser = random(16);
randomSeed(randomSeeds[thisRandomChooser]);
thisRandomChooser = random(16);
randomSeed(randomSeeds[thisRandomChooser]);
for (uint8_t i = 0; i < 16; i++) {
thisRandomChooser = random(16);
randomSeed(randomSeeds[thisRandomChooser]);
uint16_t mask = 0000000000000001;
uint16_t thisByte = randomSeeds[thisRandomChooser];
uint16_t thisMaskedByte = thisByte & mask;
bitWrite(randomSeedInt, 0, thisMaskedByte);
if (i < 15) {
uint16_t interRandomInt = randomSeedInt << 1;
randomSeedInt = interRandomInt;
}
}
randomSeed(randomSeedInt);
// // Timing Test
// benchTime = benchmarkTimer;
// Serial.print("getRandomSeeds took ");
// Serial.print(benchTime);
// Serial.println(" uS");
// //
// Serial.print("randomSeeds = ");
// for (uint8_t i = 0; i < 16; i++) {
// Serial.print(randomSeeds[i]);
// if (i < 15) {
// Serial.print(", ");
// }
// }
// Serial.println("");
}
///////////////////////////
// Get Random Seed Values
///////////////////////////
uint8_t getRandomBits(uint8_t thisRandomChoice) {
// // timing test
// uint32_t benchTime = 0;
// benchmarkTimer = 0;
// //
uint8_t returnVal = random(thisRandomChoice);
// // Timing Test
// benchTime = benchmarkTimer;
// Serial.print("getRandomBits took ");
// Serial.print(benchTime);
// Serial.println(" uS");
// //
return returnVal;
}
///////////////////////////
// Set Pin Modes
///////////////////////////
void setPinModes() {
pinMode(rootPin, INPUT);
pinMode(modePin, INPUT);
pinMode(chordPin, INPUT);
pinMode(octavesPin, INPUT);
// pinMode(clockPin, INPUT);
// pinMode(syncPin, INPUT);
pinMode(DACPins[0], OUTPUT);
pinMode(DACPins[1], OUTPUT);
pinMode(DACPins[2], OUTPUT);
pinMode(DACPins[3], OUTPUT);
pinMode(DACPins[4], OUTPUT);
pinMode(DACPins[5], OUTPUT);
pinMode(DACPins[6], OUTPUT);
}
///////////////////////////
// Set hardware interrupts on input pins
///////////////////////////
void setHardwareInterrupts() {
// attachInterrupt(digitalPinToInterrupt(clockINPin), clockSignalIN, RISING);
// attachInterrupt(digitalPinToInterrupt(syncPin), syncClock, RISING);
}
///////////////////////////
// Get initial values from potentiometers
///////////////////////////
void getInitialValues() {
uint8_t thisRoot = (analogRead(rootPin) >> 3) + 1;
root = map(thisRoot, 1, 128, 1, TOP_NOTE);
Serial.print("root = ");
Serial.println(root);
parseRoot();
parseCurrentRoot();
uint8_t thisMode = (analogRead(modePin) >> 6);
mode = map(thisMode, 0, 15, 0, 9);
Serial.print("mode = ");
Serial.println(mode);
chord = (analogRead(chordPin) >> 6);
Serial.print("chord = ");
Serial.println(chord);
ChordOverSerial();
octaves = (analogRead(octavesPin) >> 8) + 1;
Serial.print("octaves = ");
Serial.println(octaves);
}
///////////////////////////
// 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(1); // 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 Valve");
display.setTextSize(1);
display.setCursor(5, 20);
display.print("Arpeggiator");
// update the display and delay by 5 seconds
display.display();
// sendTheBuffer();
delay(500);
}
void loop() {
//////////////////////////////////////////////////////
// Check Analog Pins
//////////////////////////////////////////////////////
uint8_t thisRoot = (analogRead(rootPin) >> 3) + 1;
thisRoot = map(thisRoot, 1, 128, 1, TOP_NOTE);
uint8_t thisMode = (analogRead(modePin) >> 6);
thisMode = map(thisMode, 0, 15, 0, 9);
uint8_t thisChord = (analogRead(chordPin) >> 6);
uint8_t thisOctaves = (analogRead(octavesPin) >> 8) + 1;
if (thisRoot != root) {
root = thisRoot;
Serial.print("root = ");
Serial.println(root);
parseRoot();
calcArp();
updateNoteThroughInputs();
updateDisplay();
}
if (thisMode != mode) {
mode = thisMode;
Serial.print("mode = ");
Serial.println(mode);
calcArp();
updateDisplay();
}
if (thisChord != chord) {
chord = thisChord;
Serial.print("chord = ");
Serial.println(chord);
ChordOverSerial();
parseRoot();
calcArp();
updateNoteThroughInputs();
updateDisplay();
}
if (thisOctaves != octaves) {
octaves = thisOctaves;
Serial.print("octaves = ");
Serial.println(octaves);
calcArp();
updateDisplay();
}
///////////////////////////
// receive commands over serial
///////////////////////////
if (Serial.available()) { // if there is data coming
String command = Serial.readStringUntil('\n'); // read string until newline character
// Clock signal received
if (command == "1") {
Serial.println("CLOCK Received");
clockSignalIN();
}
// sync signal received
if (command == "2") {
Serial.println("SYNC Received");
syncClock();
}
}
///////////////////////////
// TEST CLOCK IN SIGNAL
///////////////////////////
if (testTimer >= 500) {
testTimer = 0;
clockSignalIN();
}
}
// show Chord over serial
void ChordOverSerial() {
switch (chord) {
case 0:
Serial.println("Major");
break;
case 1:
Serial.println("Minor");
break;
case 2:
Serial.println("Augmented");
break;
case 3:
Serial.println("Diminished");
break;
case 4:
Serial.println("Dominant 7th");
break;
case 5:
Serial.println("Major 7th");
break;
case 6:
Serial.println("Minor 7th");
break;
case 7:
Serial.println("Min-Maj 7th");
break;
case 8:
Serial.println("Half-Dim 7th");
break;
case 9:
Serial.println("Diminished 7th");
break;
case 10:
Serial.println("Augmented 7th");
break;
case 11:
Serial.println("Aug-Maj 7th");
break;
case 12:
Serial.println("Suspended 2nd");
break;
case 13:
Serial.println("Suspended 4th");
break;
case 14:
Serial.println("Dom 7th Sus 4");
break;
case 15:
Serial.println("Mu");
break;
}
}
// show Root Note over serial
void RootNoteOverSerial() {
switch (rootNote) {
case 1:
Serial.println(" || C");
break;
case 2:
Serial.println(" || C#");
break;
case 3:
Serial.println(" || D");
break;
case 4:
Serial.println(" || D#");
break;
case 5:
Serial.println(" || E");
break;
case 6:
Serial.println(" || F");
break;
case 7:
Serial.println(" || F#");
break;
case 8:
Serial.println(" || G");
break;
case 9:
Serial.println(" || G#");
break;
case 10:
Serial.println(" || A");
break;
case 11:
Serial.println(" || A#");
break;
case 12:
Serial.println(" || B");
break;
}
}