ubitx-v5x/control_lcd_45mhz_if_v4.ino

900 lines
24 KiB
Arduino
Raw Normal View History

2017-03-02 14:36:45 -05:00
/**
* This source file is under General Public License version 3.
*
* Most source code are meant to be understood by the compilers and the computers.
* Code that has to be hackable needs to be well understood and properly documented.
* Donald Knuth coined the term Literate Programming to indicate code that is written be
* easily read and understood.
*
* The Raduino is a small board that includes the Arduin Nano, a 16x2 LCD display and
* an Si5351a frequency synthesizer. This board is manufactured by Paradigm Ecomm Pvt Ltd
*
* To learn more about Arduino you may visit www.arduino.cc.
*
* The Arduino works by firt executing the code in a function called setup() and then it
* repeatedly keeps calling loop() forever. All the initialization code is kept in setup()
* and code to continuously sense the tuning knob, the function button, transmit/receive,
* etc is all in the loop() function. If you wish to study the code top down, then scroll
* to the bottom of this file and read your way up.
*
* Below are the libraries to be included for building the Raduino
* The EEPROM library is used to store settings like the frequency memory, caliberation data,
* callsign etc .
*/
#include <EEPROM.h>
/**
* The main chip which generates upto three oscillators of various frequencies in the
* Raduino is the Si5351a. To learn more about Si5351a you can download the datasheet
* from www.silabs.com although, strictly speaking it is not a requirment to understand this code.
* Instead, you can look up the Si5351 library written by xxx, yyy. You can download and
* install it from www.url.com to complile this file.
* The Wire.h library is used to talk to the Si5351 and we also declare an instance of
* Si5351 object to control the clocks.
*/
#include <Wire.h>
#include <si5351.h>
Si5351 si5351;
/**
* The Radiono board is the size of a standard 16x2 LCD panel. It has three connectors:
*
* First, is an 8 pin connector that provides +5v, GND and six analog input pins that can also be
* configured to be used as digital input or output pins. These are referred to as A0,A1,A2,
* A3,A6 and A7 pins. The A4 and A5 pins are missing from this connector as they are used to
* talk to the Si5351 over I2C protocol.
*
* Second is a 16 pin LCD connector. This connector is meant specifically for the standard 16x2
* LCD display in 4 bit mode. The 4 bit mode requires 4 data lines and two control lines to work:
* Lines used are : RESET, ENABLE, D4, D5, D6, D7
* We include the library and declare the configuration of the LCD panel too
*/
#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,10,11,12,13);
/**
* The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory.
* We have to be very careful with variables that are declared inside the functions as they are
* created in a memory region called the stack. The stack has just a few bytes of space on the Arduino
* if you declare large strings inside functions, they can easily exceed the capacity of the stack
* and mess up your programs.
* We circumvent this by declaring a few global buffers as kitchen counters where we can
* slice and dice our strings. These strings are mostly used to control the display or handle
* the input and output from the USB port. We must keep a count of the bytes used while reading
* the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable.
*/
char serial_in[32], c[30], b[30], printBuff[32];
int count = 0;
unsigned char serial_in_count = 0;
/**
* We need to carefully pick assignment of pin for various purposes.
* There are two sets of completely programmable pins on the Raduino.
* First, on the top of the board, in line with the LCD connector is an 8-pin connector
* that is largely meant for analog inputs and front-panel control. It has a regulated 5v output,
* ground and six pins. Each of these six pins can be individually programmed
* either as an analog input, a digital input or a digital output.
* The pins are assigned as follows:
* A0, A1, A2, A3, +5v, GND, A6, A7
* (while holding the board up so that back of the board faces you)
*
* Though, this can be assigned anyway, for this application of the Arduino, we will make the following
* assignment
* A2 will connect to the PTT line, which is the usually a part of the mic connector
* A3 is connected to a push button that can momentarily ground this line. This will be used for RIT/Bandswitching, etc.
* A6 is to implement a keyer, it is reserved and not yet implemented
* A7 is connected to a center pin of good quality 100K or 10K linear potentiometer with the two other ends connected to
* ground and +5v lines available on the connector. This implments the tuning mechanism
*/
#define S_METER (A0)
#define PTT (A1)
#define FBUTTON (A3)
#define ANALOG_KEYER (A7)
#define ANALOG_TUNING (A6)
/**
* The second set of 16 pins on the bottom connector are have the three clock outputs and the digital lines to control the rig.
* This assignment is as follows :
* Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
* GND +5V CLK0 GND GND CLK1 GND GND CLK2 GND D2 D3 D4 D5 D6 D7
* These too are flexible with what you may do with them, for the Raduino, we use them to :
* - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer
* - CW_KEY line : turns on the carrier for CW
*/
#define TX_RX (7)
#define CW_TONE (6)
#define TX_LPF_SEL (5)
#define CW_KEY (4)
/**
* The raduino has a number of timing parameters, all specified in milliseconds
* CW_TIMEOUT : how many milliseconds between consecutive keyup and keydowns before switching back to receive?
* The next set of three parameters determine what is a tap, a double tap and a hold time for the funciton button
* TAP_DOWN_MILLIS : upper limit of how long a tap can be to be considered as a button_tap
* TAP_UP_MILLIS : upper limit of how long a gap can be between two taps of a button_double_tap
* TAP_HOLD_MILIS : many milliseconds of the buttonb being down before considering it to be a button_hold
*/
#define TAP_UP_MILLIS (500)
#define TAP_DOWN_MILLIS (600)
#define TAP_HOLD_MILLIS (2000)
#define CW_TIMEOUT (2000l) // in milliseconds, this is the parameter that determines how long the tx will hold between cw key downs
/**
* The Raduino supports two VFOs : A and B and receiver incremental tuning (RIT).
* we define a variables to hold the frequency of the two VFOs, RITs
* the rit offset as well as status of the RIT
*/
#define VFO_A 0
#define VFO_B 1
char ritOn = 0;
char vfoActive = VFO_A;
unsigned long vfoA=7100000L, vfoB=14200000L, ritA, ritB, sideTone=800, lsbCarrier, usbCarrier;
#define MASTER_CAL 0
#define LSB_CAL 4
#define USB_CAL 8
#define SIDE_TONE 12
/**
* Raduino needs to keep track of current state of the transceiver. These are a few variables that do it
*/
char inTx = 0;
char keyDown = 0;
char isUSB = 0;
unsigned long cwTimeout = 0;
unsigned char txFilter = 0;
/** Tuning Mechanism of the Raduino
* We use a linear pot that has two ends connected to +5 and the ground. the middle wiper
* is connected to ANALOG_TUNNING pin. Depending upon the position of the wiper, the
* reading can be anywhere from 0 to 1024.
* The tuning control works in steps of 50Hz each for every increment between 50 and 950.
* Hence the turning the pot fully from one end to the other will cover 50 x 900 = 45 KHz.
* At the two ends, that is, the tuning starts slowly stepping up or down in 10 KHz steps
* To stop the scanning the pot is moved back from the edge.
* To rapidly change from one band to another, you press the function button and then
* move the tuning pot. Now, instead of 50 Hz, the tuning is in steps of 50 KHz allowing you
* rapidly use it like a 'bandset' control.
* To implement this, we fix a 'base frequency' to which we add the offset that the pot
* points to. We also store the previous position to know if we need to wake up and change
* the frequency.
*/
unsigned long baseTune = 7100000L;
int old_knob = 0;
#define FIRST_IF (45000000l)
#define SECOND_OSC (57000000l)
#define INIT_USB_FREQ (11996500l)
#define INIT_LSB_FREQ (11998500l)
#define LOWEST_FREQ (3000000l)
#define HIGHEST_FREQ (30000000l)
long frequency, stepSize=100000;
/**
* The raduino can be booted into multiple modes:
* MODE_NORMAL : works the radio normally
* MODE_CALIBRATION : used to calibrate Raduino.
* To enter this mode, hold the function button down and power up. Tune to exactly 10 MHz on clock0 and release the function button
*/
#define MODE_NORMAL (0)
#define MODE_CALIBRATE (1)
char mode = MODE_NORMAL;
char meter[17];
byte s_meter[] = {
B0,B0,B0,B0,B0,B00000,B0,B10101,
B0,B0,B0,B0,B10000,B10000,B0,B10101,
B0,B0,B0,B0,B11000,B11000,B0,B10101,
B0,B0,B0,B0,B11100,B11100,B0,B10101,
B0,B0,B0,B0,B11110,B11110,B0,B10101,
B0,B0,B0,B0,B11111,B11111,B0,B10101
};
void setupSmeter(){
lcd.createChar(1, s_meter);
lcd.createChar(2, s_meter + 8);
lcd.createChar(3, s_meter + 16);
lcd.createChar(4, s_meter + 24);
lcd.createChar(5, s_meter + 32);
lcd.createChar(6, s_meter + 40);
}
/* display routines */
void printLine1(char *c){
if (strcmp(c, printBuff)){
lcd.setCursor(0, 0);
lcd.print(c);
strcpy(printBuff, c);
count++;
}
}
void printLine2(char *c){
if (strlen(c) > 16)
c[16] = 0;
lcd.setCursor(0, 1);
lcd.print(c);
}
void displayFrequency(unsigned long f){
int mhz, khz, hz;
mhz = f / 1000000l;
khz = (f % 1000000l)/1000;
hz = f % 1000l;
sprintf(b, "[%02d.%03d.%03d]", mhz, khz, hz);
printLine1(b);
}
void updateMeter(){
int16_t best, i, s;
best = 0;
//take 100 readings, take the peaks
for (i = 0; i < 100; i++){
s = analogRead(S_METER);
if (s > best)
best = s;
}
//now, use the s to get the signal
s = best *2;
sprintf(meter, "%3d", s);
for (i = 3; i < 14; i++){
if (s >= 5)
meter[i] = 6;
else if (s > 0)
meter[i] = 1 + s;
else
meter[i] = 1;
s = s - 5;
}
meter[i] = 0;
printLine2(meter);
}
/**
* Defines for menus
*/
byte menuOn = 0;
int ritToggle(int btn){
if (!btn){
if (ritOn == 1)
printLine2("RIT:On, Off? ");
else
printLine2("RIT:Off, On? ");
}
else {
if (ritOn == 0){
ritOn = 1;
printLine2("RIT is On. ");
}
else {
ritOn = 0;
printLine2("RIT Is Off. ");
}
}
}
int vfoToggle(int btn){
if (!btn){
if (vfoActive == VFO_A)
printLine2("Select VFO B? ");
else
printLine2("Select VFO A? ");
}
else {
if (vfoActive == VFO_A){
vfoActive = VFO_A;
printLine1("Selected VFO A ");
frequency = vfoA;
}
else {
vfoActive = VFO_B;
printLine1("Selected VFO B ");
frequency = vfoB;
}
setFrequency(frequency);
updateDisplay();
resetBasefrequency();
}
}
/**
* Load the new correction and resets the clock 0 to 10 MHz
*/
void recalibrate(int32_t correction){
si5351.set_correction(correction);
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLB);
si5351.output_enable(SI5351_CLK0, 1);
si5351.output_enable(SI5351_CLK1, 0);
si5351.output_enable(SI5351_CLK2, 0);
si5351.set_freq(1000000000ULL, SI5351_CLK0);
}
void calibrateMaster(int btn){
int knob = 0;
int32_t correction;
if (!btn){
printLine2("Set Calibration?");
return;
}
printLine1("Set to 10.000.000");
printLine2("PTT to confirm. ");
delay(2000);
recalibrate(0);
//disable all clock 1 and clock 2
while(digitalRead(PTT) == HIGH && !btnDown()){
knob = analogRead(ANALOG_TUNING);
correction = (knob - 500) * 500ULL;
recalibrate(correction);
//abort if this button is down
if (btnDown()){
//re-enable the clock1 and clock 2
break;
}
sprintf(c, "%3d ", knob);
printLine2(c);
}
//save the setting
if (digitalRead(PTT) == LOW){
printLine2("Calibration set!");
EEPROM.put(MASTER_CAL, correction);
delay(2000);
}
else {
EEPROM.get(MASTER_CAL, correction);
}
si5351.set_correction(correction);
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLB);
si5351.output_enable(SI5351_CLK0, 1);
si5351.output_enable(SI5351_CLK1, 1);
si5351.output_enable(SI5351_CLK2, 1);
resetBasefrequency();
setFrequency(frequency);
updateDisplay();
menuOn = 0;
}
void setBFO(int btn, byte isLSB){
int knob = 0;
int32_t lsb_Freq;
if (!btn){
if (isLSB)
printLine2("Set LSB Carrier ");
else
printLine2("Set USB Carrier ");
return;
}
if (isLSB)
printLine1("Tune to best LSB");
else
printLine1("Tune to best USB");
printLine2("PTT to confirm. ");
delay(2000);
//disable all clock 1 and clock 2
while(digitalRead(PTT) == HIGH && !btnDown()){
knob = analogRead(ANALOG_TUNING);
if (isLSB){
lsbCarrier = 12000000l - knob * 10;
si5351.set_freq(lsbCarrier * 100ULL, SI5351_CLK0);
}
else {
usbCarrier = 12000000l - knob * 10;
si5351.set_freq(usbCarrier * 100ULL, SI5351_CLK0);
}
//abort if this button is down
if (btnDown()){
break;
}
sprintf(c, "%3d ", knob);
printLine2(c);
}
//save the setting
if (digitalRead(PTT) == LOW){
printLine2("Carrier set! ");
if (isLSB)
EEPROM.put(LSB_CAL, lsbCarrier);
else
EEPROM.put(USB_CAL, usbCarrier);
delay(2000);
}
else {
EEPROM.get(LSB_CAL, lsbCarrier);
EEPROM.get(USB_CAL, usbCarrier);
}
resetBasefrequency();
setFrequency(frequency);
updateDisplay();
menuOn = 0;
}
void resetBasefrequency(){
int knob = analogRead(ANALOG_TUNING);
baseTune = frequency - (50l * knob);
}
int exitMenu(int btn){
if (!btn){
printLine2("Exit Menu? ");
}
else{
menuOn = 0;
resetBasefrequency();
}
}
void doMenu(){
int select, btnState;
menuOn = 1;
while(menuOn){
select = analogRead(ANALOG_TUNING);
//downscale the selection
select = (select-50)/50;
btnState = btnDown();
delay(200);
switch(select){
case 0:
ritToggle(btnState);
break;
case 1:
vfoToggle(btnState);
break;
case 2:
calibrateMaster(btnState);
break;
case 3:
setBFO(btnState, 1);
break;
case 4:
setBFO(btnState, 0);
break;
default:
exitMenu(btnState);
break;
}
}
}
void updateDisplay(){
sprintf(b, "%8ld", frequency);
sprintf(c, "%s:%.2s.%.3s.%1s", vfoActive == VFO_A ? "A" : "B" , b, b+2, b+5);
if (isUSB)
strcat(c, " USB");
else
strcat(c, " LSB");
if (inTx)
strcat(c, " TX");
else if (ritOn)
strcat(c, " +R");
else
strcat(c, " ");
printLine1(c);
/* sprintf(c, "%s %s %d", isLSB ? "LSB" : "USB", inTx ? " TX" : " RX", digitalRead(FBUTTON));
printLine2(c); */
}
void setSidebandAndTXFilters(unsigned long freq){
if (freq > 10000000L){
isUSB = 1;
si5351.set_freq(usbCarrier * 100ULL, SI5351_CLK0);
digitalWrite(TX_LPF_SEL, 1);
}
else{
isUSB = 0;
digitalWrite(TX_LPF_SEL, 0);
si5351.set_freq(lsbCarrier * 100ULL, SI5351_CLK0);
}
}
void setFrequency(unsigned long f){
uint64_t osc_f;
setSidebandAndTXFilters(f);
if (isUSB)
si5351.set_freq((SECOND_OSC - usbCarrier + f) * 100ULL, SI5351_CLK2);
else
si5351.set_freq((SECOND_OSC - lsbCarrier + f) * 100ULL, SI5351_CLK2);
frequency = f;
}
void checkTX(){
//we don't check for ptt when transmitting cw
if (cwTimeout > 0)
return;
if (digitalRead(PTT) == 0 && inTx == 0){
inTx = 1;
digitalWrite(TX_RX, 1);
updateDisplay();
}
if (digitalRead(PTT) == 1 && inTx == 1){
inTx = 0;
digitalWrite(TX_RX, 0);
updateDisplay();
}
}
/*
byte prevWasDot = 0;
void keyer(){
int key = analogRead(ANALOG_KEYER);
if (key < 50) //straight key
keyDown();
else if (key < 300) // both
if (prevWasDot){
keyDown(dotPeriod * 3);
prevWasDot = 0;
}
else {
keyDown(dotPeriod);
prevWasDot = 1;
}
else if (key < 600){ //dash
keyDown(dotPeriod * 3);
prevWasDot = 0;
}
else if (key > 900){ //dot
keyUp();
}
}
*/
void checkCW2(){
if (keyDown == 0 && analogRead(ANALOG_KEYER) < 50){
//switch to transmit mode if we are not already in it
if (inTx == 0){
digitalWrite(TX_RX, 1);
// selectTransmitFilter();
//give the relays a few ms to settle the T/R relays
delay(50);
}
inTx = 1;
keyDown = 1;
tone(CW_TONE, (int)sideTone);
updateDisplay();
}
//reset the timer as long as the key is down
if (keyDown == 1){
cwTimeout = CW_TIMEOUT + millis();
}
//if we have a keyup
if (keyDown == 1 && analogRead(ANALOG_KEYER) > 150){
keyDown = 0;
noTone(CW_TONE);
cwTimeout = millis() + CW_TIMEOUT;
}
//if we are in cw-mode and have a keyuup for a longish time
if (cwTimeout > 0 && inTx == 1 && cwTimeout < millis()){
//move the radio back to receive
digitalWrite(TX_RX, 0);
inTx = 0;
cwTimeout = 0;
updateDisplay();
}
}
void checkCW3(){
if (keyDown == 0 && analogRead(ANALOG_KEYER) < 50){
//switch to transmit mode if we are not already in it
if (inTx == 0){
if (isUSB)
si5351.set_freq((frequency + sideTone) * 100ULL, SI5351_CLK2);
else
si5351.set_freq((frequency - sideTone) * 100ULL, SI5351_CLK2);
//switch off the second oscillator and the bfo
si5351.output_enable(SI5351_CLK0, 0);
si5351.output_enable(SI5351_CLK1, 0);
si5351.output_enable(SI5351_CLK2, 1);
digitalWrite(TX_RX, 1);
// selectTransmitFilter();
//give the relays a few ms to settle the T/R relays
delay(50);
}
inTx = 1;
keyDown = 1;
tone(CW_TONE, (int)sideTone);
digitalWrite(CW_KEY, 1);
updateDisplay();
}
//reset the timer as long as the key is down
if (keyDown == 1){
cwTimeout = CW_TIMEOUT + millis();
}
//if we have a keyup
if (keyDown == 1 && analogRead(ANALOG_KEYER) > 150){
keyDown = 0;
noTone(CW_TONE);
digitalWrite(CW_KEY, 0);
cwTimeout = millis() + CW_TIMEOUT;
}
//if we are in cw-mode and have a keyuup for a longish time
if (cwTimeout > 0 && inTx == 1 && cwTimeout < millis()){
//move the radio back to receive
digitalWrite(TX_RX, 0);
inTx = 0;
cwTimeout = 0;
updateDisplay();
//switch off the second oscillator and the bfo
si5351.output_enable(SI5351_CLK0, 1);
si5351.output_enable(SI5351_CLK1, 1);
si5351.output_enable(SI5351_CLK2, 1);
setFrequency(frequency);
}
}
void checkCW(){
if (keyDown == 0 && analogRead(ANALOG_KEYER) < 50){
//switch to transmit mode if we are not already in it
if (inTx == 0){
digitalWrite(TX_RX, 1);
delay(50);
inTx = 1;
keyDown = 1;
}
if (isUSB)
si5351.set_freq((frequency + sideTone) * 100ULL, SI5351_CLK2);
else
si5351.set_freq((frequency - sideTone) * 100ULL, SI5351_CLK2);
//switch off the second oscillator and the bfo
si5351.output_enable(SI5351_CLK0, 0);
si5351.output_enable(SI5351_CLK1, 0);
si5351.output_enable(SI5351_CLK2, 1);
digitalWrite(CW_KEY, 1);
tone(CW_TONE, sideTone);
updateDisplay();
}
//reset the timer as long as the key is down
if (keyDown == 1){
cwTimeout = CW_TIMEOUT + millis();
}
//if we have a keyup
if (keyDown == 1 && analogRead(ANALOG_KEYER) > 150){
keyDown = 0;
noTone(CW_TONE);
digitalWrite(CW_KEY, 0);
cwTimeout = millis() + CW_TIMEOUT;
}
//if we are in cw-mode and have a keyuup for a longish time
if (cwTimeout > 0 && inTx == 1 && cwTimeout < millis()){
//move the radio back to receive
digitalWrite(TX_RX, 0);
inTx = 0;
cwTimeout = 0;
//switch off the second oscillator and the bfo
si5351.output_enable(SI5351_CLK0, 1);
si5351.output_enable(SI5351_CLK1, 1);
si5351.output_enable(SI5351_CLK2, 1);
setFrequency(frequency);
updateDisplay();
}
}
int btnDown(){
if (digitalRead(FBUTTON) == HIGH)
return 0;
else
return 1;
}
void checkButton(){
int i, t1, t2, knob, new_knob, duration;
//only if the button is pressed
if (!btnDown())
return;
//wait for 50 ms before declaring the button to be really down
delay(50);
if (!btnDown())
return;
t1 = millis();
knob = analogRead(ANALOG_TUNING);
duration = 0;
/* keep measuring how long the duration of btn down has been to a max of 3 seconds */
while (btnDown() && duration < 3000){
/* if the tuning knob is moved while the btn is down,
then track the bandset until the button is up and return
*/
new_knob = analogRead(ANALOG_TUNING);
if (abs(new_knob - knob) > 10){
int count = 0;
/* track the tuning and return */
while (btnDown()){
frequency = baseTune = ((analogRead(ANALOG_TUNING) * 30000l) + 1000000l);
setFrequency(frequency);
updateDisplay();
count++;
delay(200);
}
delay(1000);
return;
} /* end of handling the bandset */
delay(100);
duration += 100;
}
if (duration < 1000) {
printLine2("Menu.");
doMenu();
}
}
void doTuning(){
unsigned long newFreq;
int knob = analogRead(ANALOG_TUNING);
unsigned long old_freq = frequency;
if (knob < 10 && frequency > LOWEST_FREQ) {
baseTune = baseTune - 1000l;
frequency = baseTune;
updateDisplay();
setFrequency(frequency);
delay(50);
}
else if (knob > 1010 && frequency < HIGHEST_FREQ) {
baseTune = baseTune + 1000l;
frequency = baseTune + 50000l;
setFrequency(frequency);
updateDisplay();
delay(50);
}
// in the middle, it is business as usual
else if (knob != old_knob){
frequency = baseTune + (50l * knob);
old_knob = knob;
setFrequency(frequency);
updateDisplay();
}
}
void setup()
{
int32_t cal;
lcd.begin(16, 2);
setupSmeter();
printBuff[0] = 0;
printLine1("HFuino v0.01 ");
printLine2(" ");
EEPROM.get(MASTER_CAL, cal);
EEPROM.get(LSB_CAL, lsbCarrier);
EEPROM.get(USB_CAL, usbCarrier);
//set the lsb and usb to defaults
if (lsbCarrier == 0)
lsbCarrier = INIT_LSB_FREQ;
if (usbCarrier == 0)
usbCarrier = INIT_USB_FREQ;
// Start serial and initialize the Si5351
Serial.begin(9600);
analogReference(DEFAULT);
Serial.println("*HFuino v0.01\n");
Serial.println("*Searching Si5351\n");
//configure the function button to use the external pull-up
pinMode(FBUTTON, INPUT);
digitalWrite(FBUTTON, HIGH);
pinMode(PTT, INPUT);
digitalWrite(PTT, HIGH);
digitalWrite(ANALOG_KEYER, HIGH);
pinMode(CW_TONE, OUTPUT);
digitalWrite(CW_TONE, 0);
pinMode(TX_RX,OUTPUT);
digitalWrite(TX_RX, 0);
pinMode(TX_LPF_SEL, OUTPUT);
digitalWrite(TX_LPF_SEL, 0);
pinMode(CW_KEY, OUTPUT);
digitalWrite(CW_KEY, 0);
EEPROM.get(0,cal);
si5351.init(SI5351_CRYSTAL_LOAD_8PF,25000000l,0);
si5351.set_correction(cal);
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLB);
si5351.output_enable(SI5351_CLK0, 1);
si5351.output_enable(SI5351_CLK1, 1);
si5351.output_enable(SI5351_CLK2, 1);
// printLine1("check freq ");
// si5351.set_freq(1000000000l, SI5351_CLK2);
// delay(20000);
si5351.set_freq(lsbCarrier * 100ULL, SI5351_CLK0);
si5351.set_freq(SECOND_OSC * 100ULL, SI5351_CLK1);
si5351.set_freq(5900000000l, SI5351_CLK2);
printLine2(b);
delay(2000);
// Set CLK0 to output 7 MHz with a fixed PLL frequency
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);
si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA);
si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_8MA);
Serial.println("*Si5350 ON");
delay(10);
}
void loop(){
//generateCW(10000);
//the order of testing first for cw and then for ptt is important.
checkCW3();
checkTX();
checkButton();
//tune only when not tranmsitting
if (!inTx)
doTuning();
updateMeter();
delay(50);
}