#include <OneWire.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <TimerOne.h>
#include <avr/power.h>



#define LENGTH 9
int PIN_TEMPERATURE=8;//OK
int PIN_IRQ_COORDINATION=0; //pour pin 2 (en argument de attachInterrupt)
int PIN_ALIM_CAPTEUR=7;//
int PIN_XBEE_WAKE=4;// Arduino pin used to sleep the XBee (equivalent to pin4 on the PORTD)
int PIN_ATMEGA_AWAKE=3;

float BAND_GAP=1.1;
float SEUIL=3.0; //Seuil de décharge de la batterie
//A  déterminer en fonction du type de batterie, et du comportement du régulateur de tension. 
//Alcaline baisse de tension tardive mais trés marquée
//Nimh baisse de tension difficilement distinguable apparaissant tôt.

volatile float mesure;
volatile float consigne;
volatile int demande_ajout=0;
volatile float vcc; //alimentation pour autonomie
unsigned char receive_status1=0;
unsigned char receive_status2=0;


OneWire capt(PIN_TEMPERATURE);//pin 3

void setup(){
  cli();
  analogReference(DEFAULT);
  Serial.begin(9600);
  attachInterrupt(PIN_IRQ_COORDINATION,detecte_ajout,RISING);//pull up branchée sur le Pin 2
  //setup_adc(); //REGLADE DE L'ADC
  pinMode(PIN_IRQ_COORDINATION,INPUT_PULLUP);
  pinMode(PIN_ATMEGA_AWAKE,OUTPUT);
  wake_Xbee();
  reglage_watchdogtimer(); 
  
  //pin non utilisés:
  //pin 5 pin  6 pin 9 pin 10 pin 11 pin 12  inutilisé donc en pull up 
  //pour y appliquer un état de haute impédance, pour éviter des surconsommations dues aux captations du bruit.
  pinMode(5,INPUT_PULLUP);
  pinMode(6,INPUT_PULLUP);
  pinMode(9,INPUT_PULLUP);
  pinMode(10,INPUT_PULLUP);
  pinMode(11,INPUT_PULLUP);
  pinMode(12,INPUT_PULLUP); 
  DDRB=0x01;//pin 8 en sortie
  pinMode(PIN_ALIM_CAPTEUR,OUTPUT); 
  //pinMode(PIN_ALIM_CAPTEUR,HIGH);
  power_twi_disable(); //Two Wire Interface ne sont pas des fonctionnalités que nous utilisons, de plus elles consomment...
  power_spi_disable();  //De même pour SPI
  sei(); 
 }

void loop(){
  
  int j;
  sleep_Xbee();
  for(j=0;j<2;j++){//une itération de boucle 8 secondes de veilles : j<2 --> 16 secondes , environ 1 min de veille ---> j<8
     if(!demande_ajout){
      veille();
      } 
    }
     
      if((demande_ajout==1)){
      wake_Xbee();
      delay(1000);
      //Envoi d'une trame d'ajout
      Envoi_trame(00.0,2);
      delay(1000);
      sleep_Xbee();  
      cli();
      attachInterrupt(PIN_IRQ_COORDINATION,detecte_ajout,RISING);
      demande_ajout=0;
      sei();
      }
      
  //réveil Xbee
  wake_Xbee();
  //alimentation du capteur
  pinMode(PIN_ALIM_CAPTEUR,HIGH);
  delay(2000);
  //on interroge le capteur
  Envoi_trame(get_temperature(),1);
  delay(500);
  //mise en sommeil du capteur
  pinMode(PIN_ALIM_CAPTEUR,LOW);
  sleep_Xbee();
  //mise en sommeil Xbee
  }

//interruptions lancées sur front descendant du pin digital 2
void detecte_ajout(void)
{
  //level interrupt
  cli();
  detachInterrupt(0);
  demande_ajout=1;
  sei();
}

///////////////
// COMMUNICATION API
////

//Cette fonction permet d'écrire dans le port série.
//Elle échappe le caractère si besoin
void escape_char_and_send(unsigned char c)
{
 if((c==0x7e)||(c==0x7d)||(c==0x11)||(c==0x13))
          {
          Serial.write(0x7d);
          Serial.write(c^0x20);
          }
  else{
          Serial.write(c);
  }
}

// mode ==0 alors on envoie la mesure de la température, mode !=0  alors on envoie d'autre informations (événements d'ajout, alerte autonomie)
void envoi_trame(float temperature,int mode){
        char length;//sans les données length = 14
        unsigned char frame[20]={0x7e,0x00,length,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x00,0xDA,0xAA,0xAA};//il faudra ajouter le checksum
          switch(mode){
             case 1:
                   length=17;
                   frame[2]=length;
                   frame[17]=0x01;
                   frame[18]=(byte)(temperature/1); //Partie Entiere
                   frame[19]=(byte)((temperature-(temperature/1))*10);//Premier digit
             break;
             case 2://ajout d'un module
                 length=15;
                 frame[2]=length;
                 frame[17]=0x02;
             break;
             case 3://alerte autonomie
                 length=15;
                 frame[2]=length;
                 frame[17]=0x03;
             break;
             default:
             ;
          }
          int j;
          long checksum=0;
         Serial.write(frame[0]);//delimiteur
         for(j=1;j<(length+3);j++){
           escape_char_and_send(frame[j]);
           if(j>2){
           checksum+=frame[j];
           }
         }
         checksum=(0xFF - ( checksum & 0xFF));
        Serial.write((byte)checksum);
}


//interruptions basé sur le vecteur Watchdog timer, indispensable pour le réveil
ISR(WDT_vect){

}
///////////////
// Wake up the XBee
////
void wake_Xbee(){
pinMode(PIN_XBEE_WAKE, OUTPUT);
digitalWrite(PIN_XBEE_WAKE, LOW);
}

// put the XBee on sleep
void sleep_Xbee(){
pinMode(PIN_XBEE_WAKE, INPUT); //put pin in a high impedence state
digitalWrite(PIN_XBEE_WAKE, HIGH);
}
////////////
//// AUTONOMIE
////
//Initialisation du convertisseur Analogique Numérique
//Permet de détecter une baisse de la tension d'alimentation alors que la tension de référence change avec la tension d'alimentation

void setup_adc(void)
{
    ADMUX = 0xE;//Branchement logiciel de la tension de Band Gap (une tension toujours fixe à l'intérieur de l'atmega de 1 volts environ) en entrée du convertisseur
    ADCSRA = (1<<ADEN)|(1<<ADATE)|(1<<ADIE)|(1<<ADSC)|5;
}


//Dans cette interruption, on compare la tension de référence du CAN
//(donc la tension d'alimentation) avec la tension de Band Gap, qui devient notre nouvelle référence
ISR(ADC_vect) //ADC End of Conversion interrupt 
{
unsigned char adc_data;
adc_data = ADC>>2; //read 8 bit value
vcc = BAND_GAP * 255 / adc_data;
}
///////////////////
///// VEILLE WATCHDOG TIMER
/////////////////// 
void reglage_watchdogtimer(){
  cli();
  MCUSR &= ~(1<<WDRF); //reset du Watchdog timer (WDRF)
  WDTCSR |= (1<<WDCE) | (1<<WDE);//met le bit WDCE à 1 afin de pouvoir changer le prescaler (une sécurité)
 
  WDTCSR = 1<<WDP0 | 1<<WDP3; // equivalent à 8.0 seconds */
  //active les interruptions watchdog
  WDTCSR |= _BV(WDIE);
  sei();
  }
  
   
void veille(){
  cli();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable(); 
  sei();
  sleep_cpu(); 
  sleep_disable();
}
  
  
////////////////
/// TEMPERATURE
///////////////

float get_temperature()
{ 
 byte addr[8]={0,0,0,0,0,0,0,0};
 byte data[9];
 if(!capt.search(addr))
 {
 }
  capt.write(0x44,1);         // lance la commande de conversion
  delay(1000);
  int present = capt.reset();
  capt.select(addr);    
  capt.write(0xBE);         // commande de lecture de la mémoire du capteur (Scratchpad)
  int i;                   
  for ( i = 0; i < 9; i++) {           // taille du Scratchpad 9 octets
    data[i] = capt.read(); //data[0] LSB et data[1] MSB contiennent la tempÃ©rature
  }
  int temperature=0;
  if((data[1]&0x08)==0x00) //si la temp est positive
  {
  temperature=(data[1]<<8)+data[0];
  }
  if(OneWire::crc8( data, 8)!=data[8])
  { /*une erreur*/
  }
return (float)temperature*0.5;
}


void detecte_autonomie(){
  if(analogRead(0)<SEUIL){
    Serial.print("autonomie faible!");
      }
  else{
  //rien
      }
}


