#include <avr/interrupt.h>
#include <TimerOne.h>

#define LENGTH 9
int PIN_IRQ_COORDINATION=0; //pour pin 2 (en argument de attachInterrupt)
int PIN_XBEE_WAKE=4;// pin Digital utilisé pour endormir/réveiller le Xbee
int PIN_COMMANDE=8;
volatile float mesure=0x00;
volatile float consigne=0x00;
volatile int demande_ajout=0;
//volatile int manuel;
void setup(){
  cli();
  analogReference(DEFAULT);
  Serial.begin(9600);
  attachInterrupt(PIN_IRQ_COORDINATION,detecte_ajout,RISING);//pull up branchée sur le Pin 2
  pinMode(PIN_IRQ_COORDINATION,INPUT_PULLUP);
  wake_Xbee();
  pinMode(PIN_COMMANDE,OUTPUT);
  sei(); 
 }

void loop(){
  
 lit_trame();
     //mesure et consigne sont raffraichies
     //sinon elles sont égales à 0x00
    
    //hysteresis
    //la régulation commence lorsque le module reçoit des valeurs de mesure et de consigne différentes de leur valeur initiale
     if((mesure!=0x00)&&(consigne!=0x00)){
       if((consigne-mesure)>1){
         //la temperature de la piece est au dessous de consigne 
         //mise en marche du chauffage
         digitalWrite(PIN_COMMANDE,HIGH);
       }else if(mesure-consigne>1){
       //la temperature de la piece est au dessus de la consigne
       //arrêt du chauffage
       digitalWrite(PIN_COMMANDE,LOW);
       }
     }
      
      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();
      }
  }

//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);
}
//fonctions de réception d'une trame 
int lit_trame(){ 
	uint64_t adresse64=0;
	int adresse16=0;
	int bytes_number,length;
        signed int state;
	char msb=0;
	char lsb=0;
	unsigned char c=0;
	unsigned char frame_type;
	  
        unsigned char one;
        unsigned char two;

        int verify_checksum=0;
	//attente du délimiteur
        if(Serial.available()>0){
	  c=Serial.read();
          if(c!=0x7E){
           return -1;   
          }	
        }
        else{
        return -1;
        }
        
	//Frame Detected
	msb=Serial.read();
        if(msb==0x7d){  
          msb=Serial.read();
          msb^=0x20;
        }
       
        lsb=Serial.read();
        if(lsb==0x7d){
          lsb=Serial.read();
          lsb^=0x20;
        }
       
	length=(msb*256)+lsb;
	int i=0;//indice de la trame
        int xored=0;
        int test1=1;
        int test2=1;
        int ancien_xored=1;
        
        while(i<length)
        {
		c=Serial.read();
		 if(c==0x7d)
                 {
                   xored=1;
                   //continue;
                 }
                 
                 if (((xored==1)&&(ancien_xored==0))||(xored==0)){
                 ancien_xored=1;
                 if(xored){
                   c^=0x20;
                   xored=0;
                 }
                 
                verify_checksum+=c;
		
                if(i==0){	
			frame_type=c;
              pinMode(9,OUTPUT);
              PORTB|=0x02;
              delay(1000);
              PORTB^=0x02;
              delay(1000);
		  }
                //  RECEIVE PACKET
		if(frame_type==0x90){
                        state=1;
                        
    			if((i>0)&&(i<9)){
    				adresse64+=(c<<(64-(i)*8));
    			}
    			if(i==9){
      				adresse16=c<<8;
    			}
    			if(i==10){
    				adresse16+=c;
    			}
    			if(i>11){
      				if ((i==12)&&(c!='H')){
                                test1=0;
                                }
                                if ((i==13)&&(c!='I')){
                                  test2=0;
                                }
                                if((i==12)&&(c!=0x00)){
                                //module chauffage concerné : mode de commande manuel envoyé
                                switch(c){
                                case 0x01://mode confort
                                break;
                                case 0x02://mode arrêt
                                break;
                                default:/**/
                                ;
                                }
                                }
                                switch(i){
                                case 13://Partie entière mesure
                                        mesure=c;
                                break;
                                case 14://Partie flottante mesure
                                    mesure+=(((float)c)/10);
                                break;
                                case 15://Partie entière consigne
                                    consigne=c;
                                break;
                                case 16://Partie flottante mesure
                                     consigne+=(((float)c)/10);
                                break;
                                default:;
                                
                                }
    			}
             
		}
			//trame de statut de transmission
		if(frame_type==0x8b){
			if(i==1){
			printf("	#  Frame ID %x ....",c);
			}
			if(i==2){
			adresse16=c<<8;
			}
		        if(i==3){
		        adresse16+=c;
                        // RECUP' ADRESSE			
                        }
			if((i==4)&&(c==0x00)){
				//succes
                                state=0;     
                                 
			}else{
                   
                        }
			if(i>3){
                        if(i==4){

                          }
                         if(i==5){

                         }
			}
				
	            }
      i++;
     
                 }else{
                ancien_xored=0; 
                 }
      }  
   
  //lecture du champ checksum
  c=Serial.read();
  verify_checksum+=c;
  //calcul checksum
  if((verify_checksum&0x00FF)!=0x00FF){
       //Erreur dans le paquet
        state=-1;
  }

  return state;
}

///////////////
// Wake up the XBee
// peu importe le paramètrage du Xbee(registre SM à 1 ou à 0), il ne s'endormira pas.
////
void wake_Xbee(){
pinMode(PIN_XBEE_WAKE, OUTPUT);
digitalWrite(PIN_XBEE_WAKE, LOW);
}


