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;
}
*/
}