#include "SAMDTimerInterrupt.h"
#include "SAMD_ISR_Timer.h"

SAMDTimer TaskTimer(TIMER_TC3);
SAMD_ISR_Timer TasksISRs;

enum {
  TEMPERATURE = 0,
  HUMIDITY,
  PRESSURE,
  SENSORS
};

// COUNTDOWN is effectively multiplied by METRONOME_INTERVAL
const int COUNTDOWN = 600;
// INTERVALS and TIMESHARES given in [ms]
const uint TASK_HANDLER_INTERVAL = 20;
const uint METRONOME_INTERVAL = 1000;
const uint SENSOR_INTERVAL = 1000;
const uint SENSOR_TIMESHARE[SENSORS] = {90000, 20000, 10000};
// FREQUENCY in [Hz]
const uint BUZZER_FREQ = 300;

const uint BUTTON_PIN = 6;
const uint BUTTON_LED_PIN = 5;
const uint BUZZER_PIN = 0;

/* Metronome state is expressed by countdown:
    -1 - IDLE
     0 - BEATING
    >0 - COUNTDOWN
   Unless metronome is in COUNTDOWN mode, display rotates through sensor readings.
*/
volatile int countdown = -1;
// Units: temperature [C], humidity [%], pressure [P]
volatile float sensorValue[SENSORS] = {};
volatile uint displaySensor = TEMPERATURE;
volatile bool displayNeedsUpdate = false;
volatile bool tubeRotated = false;
int tubeTimerID;

void TasksHandler(void) {
  TasksISRs.run();

  if (displayNeedsUpdate || tubeRotated)
    updateTube();

  if (tubeRotated) {
    TasksISRs.changeInterval(tubeTimerID, SENSOR_TIMESHARE[displaySensor]);
    tubeRotated = false;
  }
}

void setup() {
  initButton();
  initBME280();
  initBuzzer();
  initTube();

  readSensors();
  updateTube();

  TaskTimer.attachInterruptInterval_MS(TASK_HANDLER_INTERVAL, TasksHandler);
  TasksISRs.setInterval(METRONOME_INTERVAL, runMetronome);
  TasksISRs.setInterval(SENSOR_INTERVAL, readSensors);
  tubeTimerID = TasksISRs.setInterval(SENSOR_TIMESHARE[displaySensor], rotateTube);
}

void runMetronome() {
  if (countdown > 0) {
    countdown -= 1;

    digitalWrite(BUTTON_LED_PIN, countdown % 2 ? HIGH : LOW);

    displayNeedsUpdate = true;
  } else if (countdown == 0) {
    TasksISRs.setTimeout(100, noBuzz);
    buzz();
  }
}

void loop() {}
