Transceptor QRP Chingolito

//08/05: Vuelto a LSB

//28/03: USB en 40m, cambie frec inyeccion del DDS y rutina que suma/resta FI al TX.

// Hay que corroborar si TX y RX en misma frec.

//26/03: volvi a LSB en 40m. Agregue un decimal mas al dial.

//12/03: Cambie banda de 40m a USB solo RX. 

//11/03: agrande rango a 100 KHz de cada banda para experimentar RX de WSPR

//22/02: afine valores de ADC del pote de opcion banda/step

//18/02: se saco divisor resisitivo para cambio banda/step,

//se reemplazo por un potenciometro en A6. Ademas se incorpora 

//activación del rele del medidor de ROE por arduino seleccionandolo

//con la perilla de funciones que sirve para configurar usos del dial.

//Mensaje de inicio agregado.

//16/02: modificado texto del display

//11/02: modificado maxi para que sea 2000, no mas 2048.

//10/02: Agregado XIT y limpieza RIT/XIT on dial-

//10/02: Solucionado problema RIT, no mas pote, uso mismo encoder del dial.

//Solucionar seleccion de dial o clarificador con segundo pote...

// 09/02 agregado lectura ADC para RIT, apagado en extremos del pote.

//PROBLEMA: lectura del ADC varia con ruido y hace variar frec TX   <<<<=====

// 07/02 modificado para TX y RX en misma frecuencia e inicios de banda.

// 04/02 modificado paso de 100 y 500 hz, y modificado a solo 40 khz de banda y lcd

//22/01/2017 - 14:30 Hs. Malargue.

//Manipulador implementado por interrupcion

//Sintonia implementada por interrupcion

//Banda y paso de sintonia implementado mediante ADC en loop principal

//FI de 7MHZ seteada en 44319000

#include <math.h> 

#include <LiquidCrystal.h> 

volatile unsigned long int shift=0,stepp=1,FREC,rit=1024,ritt=0,rit_on,xit=1024,xitt=0;

int base=0;

volatile int TX=0;

LiquidCrystal lcd(14,13,19,18,17,16);

                //RS-EN-D4-D5-D6-D7

#define mini 0.0

#define maxi 2000.0

#define diferencia 0 //diferencia entre frec real y mostrada en display

                      //60 = 600 Hz

#define RS 14 //A0      // define nombres de los pines del LCD

#define EN 13 //D13-LED

#define D4 19 //A5  Dato 4 LCD

#define D5 18 //A4  Dato 5 LCD

#define D6 17 //A3  Dato 6 LCD                           

#define D7 16 //A2  Dato 7 LCD

#define A 2     //D2 - INT0: encoder, pin 1

#define B 4     //D4 - encoder pin 2

#define RXTX 3  //D3 - INT1: manipulador, cambio de RX a TX.

//#define LED 13

#define FREC7 114314500   //OK - 7.000MHZ por arriba  cristal rojo (recibe bien LSB)

//#define FREC7 25685500 //USB??? cambiar rutina que suma o resta frec, sino solo funciona RX

#define FREC14 95687000   //OK - 14.000MHZ por abajo USB

//#define FREC14 96357000   //OK - 14.068MHZ por abajo

#define REFCLK 1250000000   //Referencia del DDS

#define TUNE_Range 100   //Rango sintonia KHz

#define RIT_Range 5     //Rango RIT +/- KHz

#define XIT_Range 5     //Rango XIT +/- KHz

#define FASE 0

#define data 6      //D6 - Pin DDS

#define fqud 7      //D7 - Pin DDS

#define clk  8      //D8 - Pin DDS

#define RELE 9      //D9 - Pin que activa rele de cambio de banda.

#define SWR 15      //A1 - pin que activa rele de medidor de ROE SWR

#define FI07 44313500     //OK- Frecuencia intermedia 7MHZ OK.

#define FI14 44314500     //OK - Frecuencia intermedia 14MHZ OK.

void setup(){

  pinMode(A,INPUT_PULLUP);  //Pull Up de entrada.

  pinMode(B,INPUT_PULLUP);

  pinMode(RXTX,INPUT_PULLUP);

//  pinMode(LED, OUTPUT);

  FREC=FREC7;     //Frecuencia de arranque del equipo

  

  pinMode(13, OUTPUT);    //LED

  pinMode(data, OUTPUT);  //pines DDS

  pinMode(fqud, OUTPUT);  //pines DDS

  pinMode(clk, OUTPUT);   //pines DDS

  pinMode(SWR, OUTPUT);   //rele medidor de ROE

  

  pinMode(A0, OUTPUT);  //declaro algunos pines analogicos como salidas digitales

  pinMode(A1, OUTPUT);  //rele de medidor de roe

  pinMode(A2, OUTPUT);

  pinMode(A3, OUTPUT);

  pinMode(A4, OUTPUT);

  pinMode(A5, OUTPUT);

  

  attachInterrupt(digitalPinToInterrupt(A),ISR_encoder,FALLING);  //Uso falling porque tienen pullup las entradas

  attachInterrupt(digitalPinToInterrupt(RXTX),ISR_key,CHANGE);   //Detecta suba o baja del manipulador

  Serial.begin(9600);

  lcd.begin(16, 2); //seteo numero de columnas y filas del display

  lcd.setCursor(0, 0);

  lcd.print("QRP  Chingolito "); //Imprimo mensaje

  lcd.setCursor(0, 1);

  lcd.print("LU3HO 3W 40/20m "); //Imprimo mensaje

  delay(5000);

  lcd.setCursor(0, 0);

  lcd.print("                "); //Imprimo mensaje

  lcd.setCursor(0, 1);

  lcd.print("                "); //Imprimo mensaje

}

void loop(){

    unsigned long int opt=analogRead(A6); //Lectura de los interruptores de banda y paso de sintonia

    

    rit_on=analogRead(A7);                //Lectura potenciometro de RIT

    

    int opcion=step_band(opt);            //360-300-190-0 las 4 opciones

    

    unsigned long int shiftt;

    

    Serial.print(opt);Serial.print("\n"); 

    

    swr_meter(rit_on);

    shiftt=shift*TUNE_Range*5;           //sintonia= 40 KHz

    ritt=(rit-1024)*RIT_Range*10;         //rit= 5KHz

    xitt=(xit-1024)*XIT_Range*10;

    

    lcd_display(opcion);      //escritura display

   

    AD9851_SetFreq(FREC+shiftt+ritt,FASE);       //Pone un dds en 0° y el otro en 90°.

 }

//__________________________________________________________________

int lcd_display(int opcion){

    char texto[16];

     long int rita,xita;

  

    lcd.setCursor(0, 0);      //banda

    if(opcion==1 || opcion==3)

      lcd.print("14,");

    else 

      lcd.print(" 7,"); 

    lcd.setCursor(3, 0);    //frecuencia

      sprintf(texto,"%.5d",(shift)*TUNE_Range/20);

      lcd.print(texto);

    lcd.setCursor(8, 0);

      lcd.print("MHz");

      

    lcd.setCursor(12, 0);       //Opcion dial de comando(pote)

      if(rit_on<=200)

        lcd.print("S");         //medidor de ROE /SWR

      if(rit_on>200 && rit_on<=400)

        lcd.print("F");         //comanda frecuencia

      if(rit_on>400 && rit_on<600)

        lcd.print("R");         //comanda RIT

      if(rit_on>=600 && rit_on<800)

        lcd.print("X");         //comanda XIT

      if(rit_on>=800)

        lcd.print("C");         //limpieza /Clear de RIT/XIT

    

    lcd.setCursor(0, 1);

      lcd.print("RX");

   lcd.setCursor(2,1);    //RIT

      if(rit>=1024)

        lcd.print("+");

      if(rit<1024)

        lcd.print("-");

     rita=(rit-1024);

     rita=pow(rita*rita,0.5); //valor absoluto del RIT

    

    lcd.setCursor(3, 1);    //frecuencia

      sprintf(texto,"%.4d",rita*RIT_Range);

      lcd.print(texto);

      

    lcd.setCursor(8, 1);        //XIT

      lcd.print("TX");

   lcd.setCursor(10,1);    

      if(xit>=1024)

        lcd.print("+");

      if(xit<1024)

        lcd.print("-");

     xita=(xit-1024);

     xita=pow(xita*xita,0.5);   //valor absoluto del XIT

    

    lcd.setCursor(11, 1);        //frecuencia

      sprintf(texto,"%.4d",xita*XIT_Range);

      lcd.print(texto);

      

  }

//__________________________________________________________________

void swr_meter(int rit_on){     //funcion que activa rele medidor de roe

 if(rit_on<=200){

  digitalWrite(SWR,HIGH);  

  //activar rele pin A1

  delayMicroseconds(1000);

}

else{

  digitalWrite(SWR,LOW);   

  //desactivar rele pin A1

  delayMicroseconds(1000);

  }

}

//__________________________________________________________________

int step_band(unsigned long int opt){

  if(opt>=0 && opt<150){               //40metros - 1 KHz  if(opt>=330)

    if(FREC==FREC14 || FREC==FREC14+FI14)

      FREC=FREC7;

    //stepp=10;

    stepp=25;

    digitalWrite(RELE,LOW);

     lcd.setCursor(14, 0);

      lcd.print("g");

    return 0;

  }

  if(opt>=480 && opt<800){    //20metros - 1 KHz    if(opt>=250 && opt<330)

    if(FREC==FREC7 || FREC==FREC7-FI07)

      FREC=FREC14;

    //stepp=10;

    stepp=25;

    digitalWrite(RELE,HIGH);

    lcd.setCursor(14, 0);

      lcd.print("g");

    return 1;

  }

  if(opt>=150 && opt<480){    //40metros - 100 Hz   if(opt>=100 && opt<250)

    if(FREC==FREC14 || FREC==FREC14+FI14)

      FREC=FREC7;

    stepp=1;

    digitalWrite(RELE,LOW);

    lcd.setCursor(14, 0);

      lcd.print("f");

    return 2;

  }

  if(opt>=800 && opt<=1023){                //20metros - 100 if(opt>=0 && opt<100)

    if(FREC==FREC7 || FREC==FREC7-FI07)

      FREC=FREC14;

    stepp=1;

    digitalWrite(RELE,HIGH);

    lcd.setCursor(14, 0);

      lcd.print("f");

    return 3;

  }

  return 4;

}

//__________________________________________________________________

void ISR_encoder(){         //Parece que mas o menos anda...

  

if(rit_on>200 && rit_on<=400){               //comando dial principal

  if(digitalRead(B)==0) //CW

    if(shift<maxi &&((shift+stepp)<maxi))

      //shift++;

      shift=shift+stepp;

    else

      shift=maxi;

  else                 //CCW

    if(shift>mini &&((shift-stepp)>stepp))

      //shift--;

      shift=shift-stepp;

    else

      shift=mini;

  delayMicroseconds(1000);//evita el rebote de los terminales

}

if(rit_on>400 && rit_on<600){         //comando dial secundario RIT

  if(digitalRead(B)==0) //CW

    if(rit<maxi &&((rit+stepp)<maxi))

      //shift++;

      rit=rit+stepp;

    else

      rit=maxi;

  else                 //CCW

    if(rit>mini &&((rit-stepp)>stepp))

      //shift--;

      rit=rit-stepp;

    else

      rit=mini;

  delayMicroseconds(1000);//evita el rebote de los terminales

}

if(rit_on>=600 && rit_on<800){                    //comando dial secundario RIT

  if(digitalRead(B)==0) //CW

    if(xit<maxi &&((xit+stepp)<maxi))

      //shift++;

      xit=xit+stepp;

    else

      xit=maxi;

  else                 //CCW

    if(xit>mini &&((xit-stepp)>stepp))

      //shift--;

      xit=xit-stepp;

    else

      xit=mini;

  delayMicroseconds(1000);//evita el rebote de los terminales

}

if(rit_on>=800){                    //comando dial secundario RIT

  if(digitalRead(B)==0) //CW

    xit=1024;

  else                 //CCW

    rit=1024;

  delayMicroseconds(1000);//evita el rebote de los terminales

}

}

//__________________________________________________________________

void ISR_key(){   //cambia frecuencia del oscilador al TX

 

  if(digitalRead(RXTX)==0)

    TX=1;

  else

    TX=0;

    /* Original LSB, anda bien

  if(FREC==FREC7||(FREC>=FREC7-FI07-100000 && FREC<=FREC7-FI07+100000)){

    if(digitalRead(RXTX)==0)  //se presiono manipulador

      FREC=FREC7-FI07-ritt+xitt;   //LSB-> resta

    else                      //se solto manipulador      

      FREC=FREC7;                       

  }

  */

//prueba para USB, no olvidar modificar frecuencia del DDS

if(FREC==FREC7||(FREC>=FREC7-FI07-100000 && FREC<=FREC7-FI07+100000)){//LSB->resta

//if(FREC==FREC7||(FREC>=FREC7+FI07-100000 && FREC<=FREC7+FI07+100000)){//USB->suma    

    if(digitalRead(RXTX)==0)  //se presiono manipulador

      //FREC=FREC7+FI07-ritt+xitt;   //USB->suma

      FREC=FREC7-FI07-ritt+xitt;   //LSB->resta

    else                      //se solto manipulador      

      FREC=FREC7;                       

  }

 

  if(FREC==FREC14||(FREC>=FREC14+FI14-100000 && FREC<=FREC14+FI14+100000)){

    if(digitalRead(RXTX)==0)  //se presiono manipulador

      FREC=FREC14+FI14-ritt+xitt; //USB->suma

    else

      FREC=FREC14;            //se solto manipulador

  }

}

//__________________________________________________________________

                                 //FUNCIONES

void AD9851_RFDAT( int value )

{

    if ( value )

        digitalWrite(data, HIGH);

    else

        digitalWrite(data, LOW);

    //delay(1);

}

void AD9851_RESET( int value ){}

void AD9851_CLK( int value )

{

    if ( value )

        digitalWrite(clk, HIGH);

    else

        digitalWrite(clk, LOW); 

    //delay(1);

}

void AD9851_FQUD( int value )

{

    if ( value )

        digitalWrite(fqud, HIGH);

    else

        digitalWrite(fqud, LOW);

    //delay(1);

}

unsigned long int VNA_FreqToTW(unsigned long int RefClk, unsigned long int F0)

{

  unsigned long long int x;

  x = F0;

  x <<= 32;

  x += (RefClk >> 1);

  x /= RefClk;

  return (unsigned long int) x;

}

void AD9851_SetFreq( unsigned long int hz, unsigned long int phase )

{

  int i;

  unsigned long int divisor;

  divisor =  VNA_FreqToTW(REFCLK,hz);       //reemplazado eeb0.refclk  por valor refclk

//  printf("  %u Hz tuning word = %u\n",hz,divisor);

  // set  freq(32) from divisor

  for (i=0; i<32; i++)

  {

    if (divisor & 0x00000001L)

    {

      AD9851_RFDAT(1);

      //AD9851_LODAT(1);

    }

    else

    {

      AD9851_RFDAT(0);

    }

    AD9851_CLK(1);

    AD9851_CLK(0);

    divisor >>= 1;

  }

  // set direct osc(1), test bit(1),powerup both DDS chips (1)

  AD9851_RFDAT(0);

  for (i=0; i<3; i++)

  {

    AD9851_CLK(1);

    AD9851_CLK(0);

  }

  AD9851_RFDAT(0);    // rf is always 0 deg

  for (i=0; i<5; i++)

  { 

    AD9851_CLK(1);

    AD9851_CLK(0);

  }

  // now activate the new configuration

  AD9851_FQUD(1);

  AD9851_FQUD(0);

}

void AD9851_Reset( void )

{

  int i;

  // set dds lines in a known position

  AD9851_CLK(0);

  AD9851_FQUD(0);

  AD9851_RESET(0);

  AD9851_RFDAT(0);

  // reset both dds ( needs to be > 5 ref clk periods )

  AD9851_RESET(1);

  AD9851_RESET(0);

  // enter DDS serial programming mode

  AD9851_CLK(1);

  AD9851_CLK(0);

  AD9851_FQUD(1);

  AD9851_FQUD(0);

  // we are now in serial mode but not synced

  // clock a power down word into 40 bit SR

  for( i=0; i<34; i++)

  {

    AD9851_CLK(1);    // clocks 0..33

    AD9851_CLK(0);

  }

  AD9851_RFDAT(1);

  AD9851_CLK(1);      // clock 34

  AD9851_CLK(0);

  AD9851_RFDAT(0);

  for( i=0; i<5; i++)

  {

    AD9851_CLK(1);    // clocks 35..39

    AD9851_CLK(0);

  }

  // reset both dds ( needs to be > 5 ref clk periods )

  AD9851_RESET(1);

  AD9851_RESET(0);

  // clock power down word into core

  AD9851_FQUD(1);

  AD9851_FQUD(0);

  // enter DDS serial programming mode

  AD9851_CLK(1);

  AD9851_CLK(0);

  AD9851_FQUD(1);

  AD9851_FQUD(0);

  // we are now in serial mode, synced and powered down

  // now clock out 40 zeros to power us up

  for( i=0; i<40; i++)

  {

    AD9851_CLK(1);    // clocks 0..39

    AD9851_CLK(0);

  }

  AD9851_FQUD(1);

  AD9851_FQUD(0);

  AD9851_SetFreq( 100000000, 90 );      ////AD9851_SetFreq( 100000000L, 0L );   ?????

}