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;

}

*/

}