Baliza WSPR simple 2

//19/9/17 Reforma total tabla de horarios y modos, a probar.

//13/9/17 Agregado de funciones de salto de frecuencia segun horarios y prueba parcial

//Se debería ver como hacer para que elija modo segun la hora.

//13/9/17 Agregado identificacion en CW. Inhabilitada, comentada la funcion

//12/9/17 Agregada banda 137 y 472 KHz.

//8/9/17, con arduino 328 empezo a andar sin problemas

//19/8. Lo guardo porque funciona bien sin UART pero con disparo por pin externo.

//15/8/17. Anda bien temporizado y lectura GPS. Se clava cuando uso TX_WSPR.

//14/8/17 logre que el timestamp de gps comience la trama pero es a frecuencia constante...

//13/8/17. Conflicto entre timer1 y uart. Ambos andan por separado pero no juntos.

//Usar otra forma de timer que no sea output compare?? otra forma de leer uart?

//13/8/17 Problema al lanzar TIMSK1 me bloquea el codigo.

//10/08/17 seudocodigo en espera del GPS

//8/8/17 Anda parte de generacion de tonos, 

//falta parte de PPS del GPS y lectura datos HHMMSS del GPS.

//05/08/2017 Andando

#include <Wire.h>       //Libreria que necesita NT7S

#include <si5351.h>     //Libreria NT7S

#include <avr/io.h>

#include <avr/interrupt.h>

Si5351 si5351;

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

//                                DEFINES

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

#define BAND_HOP 1            //0=no band hopping, else yes band hopping, mode and band defined

#define FIXED_BAND 40         //band to TX when band hopping not enabled, only mode defined

#define WSPR_SELECT 0         //not used yet

#define CW_TX_ENABLE 1        //enable CW transmission, inhibits WSPR for now...

#define TIMER_SCALER_WSPR 42  //constant to manage WSPR timer, do not touch

#define TIMER_SCALER_CW 10    //constant to manage CW timer, can be touched

#define MODE_WSPR 0           //mode select

#define MODE_CW 1

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

volatile int cont=0,cont_scaler=0, flag_timer=0,flag_pps=0,flag_gps=0,be_prepared_wspr=0,be_prepared=0,be_prepared_cw=0,enableTX=0,timer_cont=0;

volatile int timer_scaler=42, mode_flag=0,minute=0;

String GPS_string="";

volatile unsigned long long f0, f1, f2, f3, f4;

//Mensajes

/*volatile byte WSPR_DATA_LU3HO_FF54_30[] = {3,1,2,0,0,2,2,2,3,

0,2,2,1,1,1,0,2,0,1,0,2,3,2,1,1,1,3,2,2,0,0,0,

2,2,3,0,2,1,2,3,0,2,2,2,0,0,3,2,3,1,0,0,1,1,2,3,2,0,2,3,1,0,3,0,

0,0,0,1,1,0,3,2,1,2,1,0,1,2,0,3,2,0,3,0,1,3,2,2,0,3,1,0,3,0,3,2,

2,2,1,0,0,2,0,2,1,0,2,1,0,2,1,1,1,0,1,3,0,2,1,1,2,3,0,2,2,1,3,1,

2,0,0,2,2,1,2,3,0,0,1,1,2,0,0,2,2,0,2,1,3,2,3,2,3,3,2,0,2,3,1,2,

0,2}; //LU3HO FF54 30

*/

volatile byte WSPR_DATA_LU3HO_FF54_35[] = {3,1,2,2,0,0,2,0,3,

2,2,2,1,1,1,2,2,0,1,0,2,3,2,3,1,1,3,0,2,2,0,0,2,2,3,0,2,3,2,

1,0,2,2,2,0,2,3,2,3,3,0,2,1,1,2,1,2,0,2,3,1,0,3,2,0,0,0,3,1,

2,3,2,1,2,1,0,1,0,0,1,2,2,3,2,1,3,2,0,0,3,1,2,3,2,3,2,2,2,1,

2,0,0,0,0,1,0,2,3,0,0,1,1,1,0,1,3,0,0,1,1,2,1,0,0,2,3,3,3,2,

0,0,0,2,1,2,3,0,2,1,1,2,2,0,2,2,2,2,3,3,0,3,2,3,3,2,2,2,1,1,

2,0,2}; //LU3HO FF54 35

volatile byte CW_DATA_LU3HO_FF54[]={  //  "LU3HO/M FF54"

1,0,1,1,1,0,1,0,1,/*L*/

0,0,0,/*esp*/

1,0,1,0,1,1,1,/*U*/

0,0,0,/*esp*/

1,0,1,0,1,0,1,1,1,0,1,1,1,/*3*/

0,0,0,/*esp*/

1,0,1,0,1,0,1,0,/*H*/

0,0,0,/*esp*/

1,1,1,0,1,1,1,0,1,1,1,/*O*/

0,0,0,/*esp*/

1,1,1,0,1,0,1,0,1,1,1,0,1,/*"/"*/

0,0,0,/*esp*/

1,1,1,0,1,1,1,/*M*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0,0,/*esp*/

1,0,1,0,1,1,1,0,1,/*F*/

0,0,0,/*esp*/

1,0,1,0,1,1,1,0,1,/*F*/

0,0,0,/*esp*/

1,0,1,0,1,0,1,0,1,/*5*/

0,0,0,/*esp*/

1,0,1,0,1,0,1,0,1,1,1,/*4*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0/*esp final sin coma*/

//162

};

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

void setup(void) 

{

  pinMode(13, OUTPUT);

  pinMode(2, OUTPUT);

  pinMode(3,INPUT_PULLUP);  //Pull Up de entrada, interrupcion por pin para el PPS

  digitalWrite(2, HIGH);

  SI5351_INIT();

  GPS_string.reserve(200);

 // cli();          // disable global interrupts

  TCCR2A = 0;     // set entire TCCR1A register to 0

  TCCR2B = 0;     // same for TCCR1B

 

  //OCR1A = 1000;

  // turn on CTC mode:

  TCCR2A |= (1 << WGM21);

  // Set CS10 and CS12 bits for 1024 prescaler:

  ////TCCR1B |= (1 << CS10);

  TCCR2B = 7;

   // set compare match register to desired timer count:

  OCR2A = 253; //254 valores

  // enable timer compare interrupt:

  //TIMSK1 |= (1 << OCIE1A);///////////////////////////////////////////PROBLEMA

  // enable global interrupts:

  // sei();

  attachInterrupt(digitalPinToInterrupt(3),ISR_PPS,FALLING);   //Detecta caida pulso PPS

  

  Serial.begin(9600);

}

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

//                      Inicio INTERRUPCIONES (no modificar)

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

ISR(TIMER2_COMPA_vect){     //TIMER2

  cont_scaler++;

  if(cont_scaler>=timer_scaler){

      flag_timer=1;

      cont_scaler=0;

      }

   else

      flag_timer=0;

  }

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

void ISR_PPS(){             //PIN de INT

  flag_pps=1;

  }

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

void serialEvent(){         //UART

   if(Serial.available()){

    char input_char=(char)Serial.read();

    GPS_string += input_char;

    if(input_char=='\n')

      flag_gps=1;

    else

      flag_gps=0;   

    }       

  }

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

//                      Final INTERRUPCIONES

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

//                           LOOOOOOOOOOP

void loop(void) {

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

if(flag_gps==1){  //GPS data arrived from UART.

   

   be_prepared=0;

   

//Condicionales para ejecucion rutina WPSR

   if(GPS_string[0]=='$' && GPS_string[1]=='G' && GPS_string[3]=='Z' && GPS_string[4]=='D' && GPS_string[5]=='A')

   if(GPS_string[10]=='1' || 

      GPS_string[10]=='3' ||  //commented

      GPS_string[10]=='5' || 

      GPS_string[10]=='7' ||  //commented

      GPS_string[10]=='9')

   if(GPS_string[11]=='5' && GPS_string[12]=='9'){

            //timer_scaler=TIMER_SCALER_WSPR;    //no tocar, wspr

            be_prepared=1;

            //mode_flag=0;

           }

      

   //conversion del minuto a empezar de char a int para que lo tome la funcion de seleccion de banda

   minute=(int(GPS_string[9])-48)*10 + int(GPS_string[10])-48 + 1;

   if(minute>58)

      minute=0;

  Serial.print(GPS_string);       

  GPS_string="";

  flag_gps=0;

}

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

flag_pps=1;

if(flag_pps==1){                  //interrupcion por pin, señal PPS. Coordina temporizado de trama.

   if(be_prepared==1){       //Ejecucion rutina WSPR

      cont=0;                     //para empezar desde el inicio el mensaje

      if(BAND_HOP==1)

        BAND_SEL(BAND_TIME_SEL_MM(minute));

      else 

        BAND_SEL(FIXED_BAND);

      //flag_pps=0;               //habilita una nueva entrada al IF

      //enableTX=1;

      be_prepared=0;

      TCCR2B = 7;                 //Reconfiguro timer ya que lo apague haciendo cero el registro entero

      TIMSK2 |= (1 << OCIE2A);    //habilita int timer2 asi empieza a generar el temporizado de las frecuencias

      } 

      

   flag_pps=0;      

}

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

//coordinates frequency generation on SI5351A.

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

if(flag_timer==1){          

  

//WSPR mode

if(mode_flag==MODE_WSPR){

    if(cont<=161){ //162 tonos

      digitalWrite(2, LOW);   //enable TX chain

      TX_WSPR();

      digitalWrite(13,!digitalRead(13));

      cont++;

      //flag_timer=0;

      }

    else{

      TCCR2B = 0; //alternative to stop timer count    

      TIMSK2 |= (0 << OCIE2A);      ///////////////////////////////////////////PROBLEMA???

      cont=0;

      //enableTX=0;

      digitalWrite(2, HIGH);  //disable cadena TX

      si5351.output_enable(SI5351_CLK0, 0);   //disable output

    }

  }

  

//CW mode

if(mode_flag==MODE_CW){

 if(cont<=161){ //162 dits or its equivalent in time

      //digitalWrite(2, LOW);   //enable cadena TX

      TX_CW();

      digitalWrite(13,!digitalRead(13));

      cont++;

      //flag_timer=0;

      }

    else{

      TCCR2B = 0; //alternativa para detener timer    

      TIMSK2 |= (0 << OCIE2A);      ///////////////////////////////////////////PROBLEMA???

      cont=0;

      //enableTX=0;

      digitalWrite(2, HIGH);  //disable cadena TX

      si5351.output_enable(SI5351_CLK0, 0);   //disable output

    }

}

  flag_timer=0;

  

}//end of (flag_timer)

}//end of loop()

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

void SI5351_INIT(){

  

  // Start serial and initialize the Si5351

  si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);

  

  //set output power

  si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);

  

  //calibration constant

  //si5351.set_correction(20000);

  si5351.set_correction(20000);

  

}

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

void SI_FREC(unsigned long long frec){

    si5351.set_freq(frec, SI5351_CLK0);

}

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

//SELECT BAND and MODE ACCORDING TO THE TIME

//mode_flag: MODE_WSPR or MODE_CW

//timer_scaler: TIMER_SCALER_WSPR or timer_scaler=TIMER_SCALER_CW

//Choose return band=0 to avoid TX during that time slot

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

int BAND_TIME_SEL_MM (int minuto){

  

  if(minuto== 0){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto== 2){mode_flag=MODE_CW;   timer_scaler=TIMER_SCALER_CW;   return 40;}

  if(minuto== 4){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto== 6){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 0;}

  if(minuto== 8){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  

  if(minuto==10){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==12){mode_flag=MODE_CW;   timer_scaler=TIMER_SCALER_CW;   return 40;}

  if(minuto==14){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==16){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 0;}

  if(minuto==18){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

 

  if(minuto==20){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==22){mode_flag=MODE_CW;   timer_scaler=TIMER_SCALER_CW;   return 40;}

  if(minuto==24){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==26){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 0;}

  if(minuto==28){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==30){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==32){mode_flag=MODE_CW;   timer_scaler=TIMER_SCALER_CW;   return 40;}

  if(minuto==34){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==36){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 0;}

  if(minuto==38){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  

  if(minuto==40){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==42){mode_flag=MODE_CW;   timer_scaler=TIMER_SCALER_CW;   return 40;}

  if(minuto==44){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==46){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 0;}

  if(minuto==48){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

   

  if(minuto==50){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==52){mode_flag=MODE_CW;   timer_scaler=TIMER_SCALER_CW;   return 40;} 

  if(minuto==54){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  if(minuto==56){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 0;}

  if(minuto==58){mode_flag=MODE_WSPR; timer_scaler=TIMER_SCALER_WSPR; return 40;}

  

  return 0;

  }

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

//set global variables of frequency

//f0,f1,f2,f3 are for WSPR

//f4 is for CW

//Dont forget to establish frequency correction for every band for the particular SI5351

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

void BAND_SEL(int band){  

  if(band==0) {si5351.output_enable(SI5351_CLK0, 0); cont=200;} //error                    

  if(band==137){f0= 13750000; f1= 13750146; f2= 13750293; f3= 13750439; f4= 13770000;si5351.set_correction(0);}

  if(band==472){f0= 47570000; f1= 47570146; f2= 47570293; f3= 47570439; f4= 47590000;si5351.set_correction(0);}

  if(band==160){f0=183810000; f1=183810146; f2=183810293; f3=183810439; f4=183830000;si5351.set_correction(0);}

  if(band==80) {f0=359410000; f1=359410146; f2=359410293; f3=359410439; f4=359430000;si5351.set_correction(0);}  

  if(band==60) {f0=528870000; f1=528870146; f2=528870293; f3=528870439; f4=528890000;si5351.set_correction(0);}

  if(band==40) {f0=704010000; f1=704010146; f2=704010293; f3=704010439; f4=704030000;si5351.set_correction(20000);}

  if(band==30){f0=1014020000;f1=1014020146;f2=1014020293;f3=1014020439;f4=1014030000;si5351.set_correction(0);}

  if(band==20){f0=1409710000;f1=1409710146;f2=1409710293;f3=1409710439;f4=1409730000;si5351.set_correction(0);}

  if(band==17){f0=1810610000;f1=1810610146;f2=1810610293;f3=1810610439;f4=1810630000;si5351.set_correction(0);}

  if(band==15){f0=2109610000;f1=2109610146;f2=2109610293;f3=2109610439;f4=2109640000;si5351.set_correction(0);}

  if(band==12){f0=2492610000;f1=2492610146;f2=2492610293;f3=2492610439;f4=2492640000;si5351.set_correction(0);}

  if(band==10){f0=2812610000;f1=2812610146;f2=2812610293;f3=2812610439;f4=2812640000;si5351.set_correction(14000);}

  if(band==6) {f0=5029450000;f1=5029450146;f2=5029450293;f3=5029450439;f4=5029480000;si5351.set_correction(0);}

}

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

//Select proper frequency for each WSPR time slot

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

void TX_WSPR(void){

    switch(WSPR_DATA_LU3HO_FF54_35[cont]){   //elegir el mensaje

      case 0: SI_FREC(f0);break;

      case 1: SI_FREC(f1);break;

      case 2: SI_FREC(f2);break;

      case 3: SI_FREC(f3);break;

      default:SI_FREC(f4);break;

     }

  }

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

//Keyed CW transmission

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

void TX_CW(void){

  if(CW_TX_ENABLE==1){

    switch(CW_DATA_LU3HO_FF54[cont]){   //elegir el mensaje

      case 0: si5351.output_enable(SI5351_CLK0,0); digitalWrite(2,HIGH);  break;  //No TX

      case 1: SI_FREC(f4); digitalWrite(2, LOW);                          break;  //Si TX

      default:si5351.output_enable(SI5351_CLK0,0); digitalWrite(2,HIGH);  break;

     }

    }

  }

********************************************************************************************************************************

----------------------------------------------------------------------------------------------------------------------------------------------------------------

//13/9/17 Agregado de funciones de salto de frecuencia segun horarios y prueba parcial

//Se debería ver como hacer para que elija modo segun la hora.

//13/9/17 Agregado identificacion en CW. Inhabilitada, comentada la funcion

//12/9/17 Agregada banda 137 y 472 KHz.

//8/9/17, con arduino 328 empezo a andar sin problemas

//19/8. Lo guardo porque funciona bien sin UART pero con disparo por pin externo.

//15/8/17. Anda bien temporizado y lectura GPS. Se clava cuando uso TX_WSPR.

//14/8/17 logre que el timestamp de gps comience la trama pero es a frecuencia constante...

//13/8/17. Conflicto entre timer1 y uart. Ambos andan por separado pero no juntos.

//Usar otra forma de timer que no sea output compare?? otra forma de leer uart?

//13/8/17 Problema al lanzar TIMSK1 me bloquea el codigo.

//10/08/17 seudocodigo en espera del GPS

//8/8/17 Anda parte de generacion de tonos, 

//falta parte de PPS del GPS y lectura datos HHMMSS del GPS.

//05/08/2017 Andando

#include <Wire.h>       //Libreria que necesita NT7S

#include <si5351.h>     //Libreria NT7S

#include <avr/io.h>

#include <avr/interrupt.h>

Si5351 si5351;

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

//                                DEFINES

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

#define BAND_HOP 0        //0=no band hopping, else yes band hopping

#define FIXED_BAND 40     //band to TX when band hopping not enabled

#define WSPR_SELECT 0     //not used yet

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

volatile int cont=0,cont_scaler=0, flag_timer=0,flag_pps=0,flag_gps=0,be_prepared_wspr=0,be_prepared_cw=0,enableTX=0,timer_cont=0;

volatile int timer_scaler=42, mode_flag=0,minute=0;

String GPS_string="";

volatile unsigned long long f0, f1, f2, f3, f4;

//Mensajes

/*volatile byte WSPR_DATA_LU3HO_FF54_30[] = {3,1,2,0,0,2,2,2,3,

0,2,2,1,1,1,0,2,0,1,0,2,3,2,1,1,1,3,2,2,0,0,0,

2,2,3,0,2,1,2,3,0,2,2,2,0,0,3,2,3,1,0,0,1,1,2,3,2,0,2,3,1,0,3,0,

0,0,0,1,1,0,3,2,1,2,1,0,1,2,0,3,2,0,3,0,1,3,2,2,0,3,1,0,3,0,3,2,

2,2,1,0,0,2,0,2,1,0,2,1,0,2,1,1,1,0,1,3,0,2,1,1,2,3,0,2,2,1,3,1,

2,0,0,2,2,1,2,3,0,0,1,1,2,0,0,2,2,0,2,1,3,2,3,2,3,3,2,0,2,3,1,2,

0,2}; //LU3HO FF54 30

*/

volatile byte WSPR_DATA_LU3HO_FF54_35[] = {3,1,2,2,0,0,2,0,3,

2,2,2,1,1,1,2,2,0,1,0,2,3,2,3,1,1,3,0,2,2,0,0,2,2,3,0,2,3,2,

1,0,2,2,2,0,2,3,2,3,3,0,2,1,1,2,1,2,0,2,3,1,0,3,2,0,0,0,3,1,

2,3,2,1,2,1,0,1,0,0,1,2,2,3,2,1,3,2,0,0,3,1,2,3,2,3,2,2,2,1,

2,0,0,0,0,1,0,2,3,0,0,1,1,1,0,1,3,0,0,1,1,2,1,0,0,2,3,3,3,2,

0,0,0,2,1,2,3,0,2,1,1,2,2,0,2,2,2,2,3,3,0,3,2,3,3,2,2,2,1,1,

2,0,2}; //LU3HO FF54 35

volatile byte CW_DATA_LU3HO_FF54[]={  //  "LU3HO/M FF54"

1,0,1,1,1,0,1,0,1,/*L*/

0,0,0,/*esp*/

1,0,1,0,1,1,1,/*U*/

0,0,0,/*esp*/

1,0,1,0,1,0,1,1,1,0,1,1,1,/*3*/

0,0,0,/*esp*/

1,0,1,0,1,0,1,0,/*H*/

0,0,0,/*esp*/

1,1,1,0,1,1,1,0,1,1,1,/*O*/

0,0,0,/*esp*/

1,1,1,0,1,0,1,0,1,1,1,0,1,/*"/"*/

0,0,0,/*esp*/

1,1,1,0,1,1,1,/*M*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0,0,/*esp*/

1,0,1,0,1,1,1,0,1,/*F*/

0,0,0,/*esp*/

1,0,1,0,1,1,1,0,1,/*F*/

0,0,0,/*esp*/

1,0,1,0,1,0,1,0,1,/*5*/

0,0,0,/*esp*/

1,0,1,0,1,0,1,0,1,1,1,/*4*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0,0,/*esp*/

0,0/*esp final sin coma*/

//162

};

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

void setup(void) 

{

  pinMode(13, OUTPUT);

  pinMode(2, OUTPUT);

  pinMode(3,INPUT_PULLUP);  //Pull Up de entrada, interrupcion por pin para el PPS

  digitalWrite(2, HIGH);

  SI5351_INIT();

  GPS_string.reserve(200);

 // cli();          // disable global interrupts

  TCCR2A = 0;     // set entire TCCR1A register to 0

  TCCR2B = 0;     // same for TCCR1B

 

  //OCR1A = 1000;

  // turn on CTC mode:

  TCCR2A |= (1 << WGM21);

  // Set CS10 and CS12 bits for 1024 prescaler:

  ////TCCR1B |= (1 << CS10);

  TCCR2B = 7;

   // set compare match register to desired timer count:

  OCR2A = 253; //254 valores

  // enable timer compare interrupt:

  //TIMSK1 |= (1 << OCIE1A);///////////////////////////////////////////PROBLEMA

  // enable global interrupts:

  // sei();

  attachInterrupt(digitalPinToInterrupt(3),ISR_PPS,FALLING);   //Detecta caida pulso PPS

  

  Serial.begin(9600);

}

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

//                      Inicio INTERRUPCIONES (no modificar)

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

ISR(TIMER2_COMPA_vect){     //TIMER2

  cont_scaler++;

  if(cont_scaler>=timer_scaler){

      flag_timer=1;

      cont_scaler=0;

      }

   else

      flag_timer=0;

  }

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

void ISR_PPS(){             //PIN de INT

  flag_pps=1;

  }

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

void serialEvent(){         //UART

   if(Serial.available()){

    char input_char=(char)Serial.read();

    GPS_string += input_char;

    if(input_char=='\n')

      flag_gps=1;

    else

      flag_gps=0;   

    }       

  }

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

//                      Final INTERRUPCIONES

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

void loop(void) {

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

if(flag_gps==1){  //GPS data arrived from UART.

   

   be_prepared_wspr=0;

   be_prepared_cw=0;

   

//Condicionales para ejecucion rutina WPSR

   if(GPS_string[0]=='$' && GPS_string[1]=='G' && GPS_string[3]=='Z' && GPS_string[4]=='D' && GPS_string[5]=='A')

   if(GPS_string[10]=='1' || 

      GPS_string[10]=='3' || 

      GPS_string[10]=='5' || 

      GPS_string[10]=='7' || 

      GPS_string[10]=='9')

   if(GPS_string[11]=='5' && GPS_string[12]=='9'){

            timer_scaler=42;    //no tocar, wspr

            be_prepared_wspr=1;

            mode_flag=0;

           }

//Condicionales para ejecucion rutina CW

    if(GPS_string[0]=='*')    ///////////INHABILTACION 

   if(GPS_string[0]=='$' && GPS_string[1]=='G' && GPS_string[3]=='Z' && GPS_string[4]=='D' && GPS_string[5]=='A')

   if(GPS_string[10]=='1' || 

      GPS_string[10]=='3' || 

      GPS_string[10]=='5' || 

      GPS_string[10]=='7' || 

      GPS_string[10]=='9')

   if(GPS_string[11]=='5' && GPS_string[12]=='9'){

            timer_scaler=10;      //achicar para aumentar ppm de CW

            be_prepared_cw=1;

            mode_flag=1;

           }

           

   //conversion del minuto a empezar de char a int para que lo tome la funcion de seleccion de banda

   minute=(int(GPS_string[9])-48)*10 + int(GPS_string[10])-48 + 1;

   if(minute>58)

      minute=0;

  Serial.print(GPS_string);       

  GPS_string="";

  flag_gps=0;

}

 

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

flag_pps=1;

if(flag_pps==1){                  //interrupcion por pin, señal PPS. Coordina temporizado de trama.

   if(be_prepared_wspr==1){       //Ejecucion rutina WSPR

      if(BAND_HOP==1)

        BAND_SEL(BAND_TIME_SEL_WSPR(minute));

      else 

        BAND_SEL(FIXED_BAND);

      cont=0;                     //para empezar desde el inicio el mensaje

      //flag_pps=0;               //habilita una nueva entrada al IF

      //enableTX=1;

      be_prepared_wspr=0;

      TCCR2B = 7;                 //Reconfiguro timer ya que lo apague haciendo cero el registro entero

      TIMSK2 |= (1 << OCIE2A);    //habilita int timer2 asi empieza a generar el temporizado de las frecuencias

      } 

   if(be_prepared_cw==1){            //Ejecucion rutina CW

       if(BAND_HOP==1)

        BAND_SEL(BAND_TIME_SEL_WSPR(minute));

      else 

        BAND_SEL(FIXED_BAND);

      cont=0;                     //para empezar desde el inicio el mensaje

      //flag_pps=0;               //habilita una nueva entrada al IF

      //enableTX=1;

      be_prepared_cw=0;

      TCCR2B = 7;                 //Reconfiguro timer ya que lo apague haciendo cero el registro entero

      TIMSK2 |= (1 << OCIE2A);    //habilita int timer2 asi empieza a generar el temporizado de las frecuencias

    }   

   

   flag_pps=0;      

}

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

//coordinates frequency generation on SI5351A.

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

if(flag_timer==1){          

  

//WSPR mode

if(mode_flag==0){

    if(cont<=161){ //162 tonos

      digitalWrite(2, LOW);   //enable TX chain

      TX_WSPR();

      digitalWrite(13,!digitalRead(13));

      cont++;

      //flag_timer=0;

      }

    else{

      TCCR2B = 0; //alternative to stop timer count    

      TIMSK2 |= (0 << OCIE2A);      ///////////////////////////////////////////PROBLEMA???

      cont=0;

      //enableTX=0;

      digitalWrite(2, HIGH);  //disable cadena TX

      si5351.output_enable(SI5351_CLK0, 0);   //disable output

    }

  }

  

//CW mode

if(mode_flag==1){

 if(cont<=161){ //162 dits or its equivalent in time

      //digitalWrite(2, LOW);   //enable cadena TX

      TX_CW();

      digitalWrite(13,!digitalRead(13));

      cont++;

      //flag_timer=0;

      }

    else{

      TCCR2B = 0; //alternativa para detener timer    

      TIMSK2 |= (0 << OCIE2A);      ///////////////////////////////////////////PROBLEMA???

      cont=0;

      //enableTX=0;

      digitalWrite(2, HIGH);  //disable cadena TX

      si5351.output_enable(SI5351_CLK0, 0);   //disable output

    }

}

  flag_timer=0;

  

}//end of (flag_timer)

}//end of loop()

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

void SI5351_INIT(){

  

  // Start serial and initialize the Si5351

  si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);

  

  //set output power

  si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);

  

  //calibration constant

  //si5351.set_correction(20000);

  si5351.set_correction(20000);

  

}

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

void SI_FREC(unsigned long long frec){

    si5351.set_freq(frec, SI5351_CLK0);

}

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

//SELECT BAND ACCORDING TO THE TIME, USER DEFINED FOR WSPR

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

int BAND_TIME_SEL_WSPR (int minuto){

  if(minuto== 0 || minuto==20 || minuto==40){return 160;}

  if(minuto== 2 || minuto==22 || minuto==42){return 80;}

  if(minuto== 4 || minuto==24 || minuto==44){return 60;}

  if(minuto== 6 || minuto==26 || minuto==46){return 40;}

  if(minuto== 8 || minuto==28 || minuto==48){return 30;}

  if(minuto==10 || minuto==30 || minuto==50){return 20;}

  if(minuto==12 || minuto==32 || minuto==52){return 17;}

  if(minuto==14 || minuto==34 || minuto==54){return 15;}

  if(minuto==16 || minuto==36 || minuto==56){return 12;}

  if(minuto==18 || minuto==38 || minuto==58){return 10;}

  return 0;

  }

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

//SELECT BAND ACCORDING TO THE TIME, USER DEFINED FOR CW

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

int BAND_TIME_SEL_CW (int minuto){

  if(minuto== 0 || minuto==20 || minuto==40){return 160;}

  if(minuto== 2 || minuto==22 || minuto==42){return 80;}

  if(minuto== 4 || minuto==24 || minuto==44){return 60;}

  if(minuto== 6 || minuto==26 || minuto==46){return 40;}

  if(minuto== 8 || minuto==28 || minuto==48){return 30;}

  if(minuto==10 || minuto==30 || minuto==50){return 20;}

  if(minuto==12 || minuto==32 || minuto==52){return 17;}

  if(minuto==14 || minuto==34 || minuto==54){return 15;}

  if(minuto==16 || minuto==36 || minuto==56){return 12;}

  if(minuto==18 || minuto==38 || minuto==58){return 10;}

  return 0;

  }

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

//set global variables of frequency

//f0,f1,f2,f3 are for WSPR

//f4 is for CW

//Dont forget to establish frequency correction for every band for the particular SI5351

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

void BAND_SEL(int band){  

  if(band==0) {si5351.output_enable(SI5351_CLK0, 0); cont=200;} //error                    

  if(band==137){f0= 13750000; f1= 13750146; f2= 13750293; f3= 13750439; f4= 13770000;si5351.set_correction(0);}

  if(band==472){f0= 47570000; f1= 47570146; f2= 47570293; f3= 47570439; f4= 47590000;si5351.set_correction(0);}

  if(band==160){f0=183810000; f1=183810146; f2=183810293; f3=183810439; f4=183830000;si5351.set_correction(0);}

  if(band==80) {f0=359410000; f1=359410146; f2=359410293; f3=359410439; f4=359430000;si5351.set_correction(0);}  

  if(band==60) {f0=528870000; f1=528870146; f2=528870293; f3=528870439; f4=528890000;si5351.set_correction(0);}

  if(band==40) {f0=704010000; f1=704010146; f2=704010293; f3=704010439; f4=704030000;si5351.set_correction(20000);}

  if(band==30){f0=1014020000;f1=1014020146;f2=1014020293;f3=1014020439;f4=1014030000;si5351.set_correction(0);}

  if(band==20){f0=1409710000;f1=1409710146;f2=1409710293;f3=1409710439;f4=1409730000;si5351.set_correction(0);}

  if(band==17){f0=1810610000;f1=1810610146;f2=1810610293;f3=1810610439;f4=1810630000;si5351.set_correction(0);}

  if(band==15){f0=2109610000;f1=2109610146;f2=2109610293;f3=2109610439;f4=2109640000;si5351.set_correction(0);}

  if(band==12){f0=2492610000;f1=2492610146;f2=2492610293;f3=2492610439;f4=2492640000;si5351.set_correction(0);}

  if(band==10){f0=2812610000;f1=2812610146;f2=2812610293;f3=2812610439;f4=2812640000;si5351.set_correction(14000);}

  if(band==6) {f0=5029450000;f1=5029450146;f2=5029450293;f3=5029450439;f4=5029480000;si5351.set_correction(0);}

}

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

//Select proper frequency for each WSPR time slot

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

void TX_WSPR(void){

    switch(WSPR_DATA_LU3HO_FF54_35[cont]){   //elegir el mensaje

      case 0: SI_FREC(f0);break;

      case 1: SI_FREC(f1);break;

      case 2: SI_FREC(f2);break;

      case 3: SI_FREC(f3);break;

      default:SI_FREC(f4);break;

     }

  }

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

//Keyed CW transmission

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

void TX_CW(void){

  /*

    switch(CW_DATA_LU3HO_FF54[cont]){   //elegir el mensaje

      case 0: si5351.output_enable(SI5351_CLK0,0); digitalWrite(2,HIGH);  break;  //No TX

      case 1: SI_FREC(f4); digitalWrite(2, LOW);                          break;  //Si TX

      default:si5351.output_enable(SI5351_CLK0,0); digitalWrite(2,HIGH);  break;

     }

   */  

  }