// #include <TimerOne.h>
#include <avdweb_SAMDtimer.h>
// #include <TimerTC3.h>
#include "variables.h"
// SAMDtimer timer3_1Hz = SAMDtimer(3, TC_COUNTER_SIZE_16BIT, LED4, 1e6, 9e5); // LED4 1Hz, pulse width 0.9s (this is the constructor)
SAMDtimer envelopeTimer = SAMDtimer(3, envelopeTimerISR, ENVELOPE_OUT_TIMER_RATE);
SAMDtimer analogInTimer = SAMDtimer(4, analogInputTimerISR, ANALOG_IN_TIMER_RATE);
void setup() {
SerialUSB.begin(115200);
Serial.println("==================");
Serial.println("ENVELOPE GENERATOR");
Serial.println("==================");
// initialise pins and interrupts
setPinModes();
getPotValues();
// TEST PURPOSES ONLY
sendPotValues();
// TEST PURPOSES ONLY
timerSetup();
setHardwareInterrupts();
// // TEST PURPOSES ONLY
// TESTtimerSetup();
// // TEST PURPOSES ONLY
}
///////////////////////////
// Set Pin Modes
///////////////////////////
void setPinModes() {
analogWriteResolution(10); // 0 - 1023
analogReadResolution(10); // 0 - 1023
pinMode(gateONPin, INPUT);
pinMode(gateOFFPin, INPUT);
pinMode(attackPin, INPUT);
pinMode(decayPin, INPUT);
pinMode(sustainPin, INPUT);
pinMode(releasePin, INPUT);
pinMode(levelPin, INPUT);
pinMode(timePin, INPUT);
pinMode(envelopePin, OUTPUT);
///////////////////////////
// Set initial pin states
///////////////////////////
digitalWrite(envelopePin, LOW);
}
///////////////////////////
// Set hardware interrupts on input pins
///////////////////////////
void setHardwareInterrupts() {
attachInterrupt(digitalPinToInterrupt(gateONPin), gateON, RISING);
attachInterrupt(digitalPinToInterrupt(gateOFFPin), gateOFF, FALLING);
}
///////////////////////////
// Update the pot values
///////////////////////////
void getPotValues() {
// // TEST PURPOSES ONLY
// TCNT2 = 0;
// // TEST PURPOSES ONLY
uint16_t thisLevel = analogRead(levelPin); // read the input pin
uint16_t thisTime = analogRead(timePin); // read the input pin
uint16_t thisAttack = analogRead(attackPin); // read the input pin
uint16_t thisDecay = analogRead(decayPin); // read the input pin
uint16_t thisSustain = analogRead(sustainPin); // read the input pin
uint16_t thisRelease = analogRead(releasePin); // read the input pin
uint8_t stagesUpdate = 0;
// // TEST PURPOSES ONLY
// uint32_t TEST_Ticks = TCNT1;
// Serial.println(TEST_Ticks);
// // TEST PURPOSES ONLY
if (level != thisLevel) {
level = thisLevel;
float thisLevelVal = level / 1023.0;
cli(); // stop interrupts
levelVal = thisLevelVal;
sei(); // allow interrupts
// TEST PURPOSES ONLY
sendPotValues();
// TEST PURPOSES ONLY
}
if (time != thisTime) {
time = thisTime;
float thisTimeVal = time / 1023.0;
stagesUpdate = 1;
cli(); // stop interrupts
timeVal = thisTimeVal;
sei(); // allow interrupts
// TEST PURPOSES ONLY
sendPotValues();
// TEST PURPOSES ONLY
}
if (attack != thisAttack || stagesUpdate) {
attack = thisAttack;
Serial.print("attack: ");
Serial.print(attack);
Serial.print(", attackLOGLookup[attack]: ");
Serial.println(attackLOGLookup[attack]);
uint32_t thisAttackTicks = round(((timeVal * MAX_TIME) * (attackLOGLookup[attack] / 1023.0)) * SAMPLE_RATE) + 100;
cli(); // stop interrupts
attackTicks = thisAttackTicks;
sei(); // allow interrupts
// TEST PURPOSES ONLY
sendPotValues();
// TEST PURPOSES ONLY
}
if (decay != thisDecay || stagesUpdate) {
decay = thisDecay;
uint32_t thisDecayTicks = round(((timeVal * MAX_TIME) * (attackLOGLookup[decay] / 1023.0)) * SAMPLE_RATE) + 100;
cli(); // stop interrupts
decayTicks = thisDecayTicks;
sei(); // allow interrupts
// TEST PURPOSES ONLY
sendPotValues();
// TEST PURPOSES ONLY
}
if (sustain != thisSustain) {
sustain = thisSustain;
float thisSustainLevel = sustain / 1023.0;
cli(); // stop interrupts
sustainLevel = thisSustainLevel;
sei(); // allow interrupts
// TEST PURPOSES ONLY
sendPotValues();
// TEST PURPOSES ONLY
}
if (release != thisRelease || stagesUpdate) {
release = thisRelease;
uint32_t thisReleaseTicks = round(((timeVal * MAX_TIME) * (attackLOGLookup[release] / 1023.0)) * SAMPLE_RATE) + 100;
cli(); // stop interrupts
releaseTicks = thisReleaseTicks;
sei(); // allow interrupts
// TEST PURPOSES ONLY
sendPotValues();
// TEST PURPOSES ONLY
}
}
// TEST PURPOSES ONLY
///////////////////////////
// Send values to serial port
///////////////////////////
void sendPotValues() {
Serial.print("A: ");
Serial.print(attack);
Serial.print(", D: ");
Serial.print(decay);
Serial.print(", S: ");
Serial.print(sustain);
Serial.print(", R: ");
Serial.print(release);
Serial.print(", Level: ");
Serial.print(level);
Serial.print(", Time: ");
Serial.println(time);
Serial.print("A: ");
Serial.print(attackTicks);
Serial.print(", D: ");
Serial.print(decayTicks);
Serial.print(", S: ");
Serial.print(sustainLevel, 3);
Serial.print(", R: ");
Serial.print(releaseTicks);
Serial.print(", Level: ");
Serial.print(levelVal, 3);
Serial.print(", Time: ");
Serial.println(timeVal, 3);
Serial.println();
}
// TEST PURPOSES ONLY
void loop() {
///////////////////////////
// receive commands over serial
///////////////////////////
if (Serial.available()) { // if there is data coming
String command = Serial.readStringUntil('\n'); // read string until newline character
if (command == "g") {
// Serial.println("GATE ON");
gateON();
}
if (command == "h") {
// Serial.println("GATE OFF");
gateOFF();
}
}
}