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 ); ?????
}