#include <Sleepy.h>


/****************************  STATIC VALUES FOR TEMPTERATURE INPUT AND CALCULATION  ****************************/
#define THERMISTORPIN A0   // The analoginput Pin for the Thermistor   
#define THERMISTORNOMINAL 10000      // Thermistor nominal resistance at 25 degrees C
#define TEMPERATURENOMINAL 25   // temp. for nominal resistance
#define NUMSAMPLES 10 // how many samples to take and average (to smooth analog read values), more takes longer-
#define BCOEFFICIENT 3950// The beta coefficient of the thermistor (usually 3000-4000)
#define SERIESRESISTOR 10000    // the value of the 'other' resistor

/* INITIALIZE RADIO MODULE *************************************************/
#include <SPI.h>
#include <RH_RF95.h>

// BASE DETAILS
int NODEID = 2;

// Singleton instance of the radio driver
RH_RF95 rf95;

/****************************  DATA STRUCTURE FOR SENDING PACKETS OVER RADIO  ****************************/
typedef struct {
  int nodeID;
  float temp;
  int count;
  long voltage;
} Payload;
Payload payload;
int sendCount;
float temperature; //variable to hold our temperature

void setup() 
{
  
  Serial.begin(9600);

  sendCount = 1;

  /*********************************************************************/

  // Serial.println("RADIOHEAD SETUP: ");

  /* RADIOHEAD *********************************************************/
      
  while (!Serial) ; // Wait for serial port to be available
  if (!rf95.init())
    Serial.println("init failed");
  // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
  rf95.setFrequency(915.0);
  rf95.setTxPower(20);
  rf95.setModemConfig(RH_RF95::Bw31_25Cr48Sf512);

  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then 
  // you can set transmitter powers from 5 to 23 dBm:
  
}

// Initialize Counter for GPS
uint32_t timer = millis();

// Initialize sleepy countdown timer
ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Setup for low power waiting

int countThrough;

void loop()
{
  
  // Declare payload values
  payload.temp = 0;

  delay(200);

  temperature = 0; // Reset from the last reading
  
  temperature = getTemp(THERMISTORPIN, NUMSAMPLES); //make temperature reading and do averaging
  
  // Set payload value for temperature
  payload.temp = temperature; //set temperature

  // Read voltage and set it!
  payload.voltage = readVcc();
  
  // Set count
  payload.count = sendCount;
  
  delay(200);
  
  /* RADIOHEAD ********************************************/
  // Serial.println("Sending to rf95_server");
  // Send a message to rf95_server
  payload.nodeID = NODEID;

  
  
  // DEBUG
  // Serial.println("\nDEBUG\n");

  // Serial.print("NodeID: ");
  // Serial.print(payload.nodeID);
  // Serial.print(", Temp: ");
  // Serial.print(payload.temp);
  // Serial.print(", Count: ");
  // Serial.print(payload.count);
  // Serial.print(", Voltage: ");
  // Serial.print(payload.voltage);
  // Serial.println("\n\n");

  
  rf95.send((const uint8_t*)(&payload), sizeof(payload));

  delay(500);

  rf95.sleep();

  // Sleep for 4 hours ( 240 / 60 = 4 )
  for (int i = 0; i < 2; ++i) {

    Sleepy::loseSomeTime(60000);

    delay(10);
    
  }

  sendCount++;
  
}

/* FUNCTIONS **********************************************/
float getTemp(int pin, int n_samples) {
  //do Thermistor readings and caclulations to turn resistance into temperature
  //this code was taken from the Adafruit tutorial:
  //https://learn.adafruit.com/thermistor/using-a-thermistor

  int samples[NUMSAMPLES];
  float result;
  float steinhart;
  // take N samples in a row, with a slight delay
  for (int i=0; i< n_samples; i++) {
    samples[i] = analogRead(pin);
    delay(10);
  }
  // average all the samples out
  result = 0;
  for (int i=0; i< NUMSAMPLES; i++) {
    result += samples[i];
  }
  result /= n_samples;
  result = 1023 / result - 1;
  result = SERIESRESISTOR / result;
  steinhart = result / THERMISTORNOMINAL;     // (R/Ro)
  steinhart = log(steinhart);                  // ln(R/Ro)
  steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                 // Invert
  steinhart -= 273.15;                         // convert to C
  return steinhart;
}

// ******************************************************************************************************
// Read and return the current battery voltage
// ******************************************************************************************************
long readVcc()
{
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);
#else
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA, ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
  uint8_t high = ADCH; // unlocks both

  long result = (high << 8) | low;

  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}


