#include <avr/sleep.h>
#include <avr/wdt.h>

#include <NexusTX.h>
#include <DHTStable.h>

#if defined(ARDUINO_AVR_NANO)
#include "pins-nano.h"
#elif defined(ARDUINO_AVR_ATTINYX5)
#include "pins-attiny85.h"
#else
#error "Pins undef for this core"
#endif

#include "config.h"

NexusTX transmitter(PIN_SEND); 
DHTStable DHT;

int sleeprepeat;

void LogS(const char* logstr)
{
  if(LOGGER) {
    Serial.print(logstr);
  }
}

void LogI(long unsigned int logint)
{
  if(LOGGER) {
    Serial.print(logint);
  }
}
void LogF(float logfloat)
{
  if(LOGGER) {
    Serial.print(logfloat);
  }
}
void Logln()
{
  if(LOGGER) {
    Serial.println();
  }
}

ISR(WDT_vect) {
  //Don't do anything. This is just here so that we wake up.
}

void setupWatchDogTimer(int time)
{
  if (time > 9 )
    time = 9; //Limit incoming amount to legal settings

  cli();
  MCUSR &= ~(1<<WDRF); // Clear watch dog reset flag
  _WD_CONTROL_REG |= (1<<WDCE) | (1<<WDE); // Set WD_change enable, set WD enable
  _WD_CONTROL_REG = (time & 7) | (time & 8) << 2;
  _WD_CONTROL_REG |= (1<<WDIE); // enable interrupt
  sei();
}

void powerDown(void)
{
  #if defined(BODS) && defined(BODSE)  //if MCU has bulit-in BOD it will be disabled, ATmega328P, ATtiny85, AVR_ATtiny45, ATtiny25
  sleep_bod_disable();                 //disable Brown Out Detector (BOD) before going to sleep, saves more power
  #endif
  sleep_mode();
}

void setup(void)
{
  Serial.begin(9600);
  #if defined(ARDUINO_AVR_NANO)
  pinMode(LED_BUILTIN, OUTPUT);
  #endif

  if(SEND_DELAY < 8)
  {
    sleeprepeat = 1;
  } else {
    sleeprepeat = lround(SEND_DELAY / 8);
  }
  
  delay(5000);

  // setup power
  ADCSRA &= ~(1<<ADEN); //Disable ADC, saves ~230uA
  setupWatchDogTimer(WDTO_8S);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Power down everything, wake up from WDT
  sleep_enable();

  transmitter.setChannel(0);
  transmitter.setId(SENSORID);
  transmitter.setBatteryFlag(1);

}

void loop(void)
{
  if(DHT.read22(PIN_DHT) == DHTLIB_OK)
  {
    LogS("Send ");
    LogS("Temperature: ");
    LogF(DHT.getTemperature());
    //LogF(DHT.temperature);
    LogS(" Humidity: ");
    LogF(DHT.getHumidity());
    //LogF(DHT.humidity);
    Logln();
    transmitter.setTemperature(DHT.getTemperature()); // -49.9C...+69.9C
    transmitter.setHumidity(lround(DHT.getHumidity()));      // 2...98%
    transmitter.SendPacket();
  } else {
     LogS("DHT Error");
     Logln();
  }
  #if defined(ARDUINO_AVR_NANO)
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
  #endif
  LogS("Sleep");
  Logln();
  delay(500);
  for (int i=0; i<sleeprepeat; i++)
    powerDown();
}
