#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <si5351.h>
#include <FreqMeasure.h>
#define MODE_SWITCH 7 // Mode switch is on D7
#define PTT 2 // PTT output is on D2
double sum = 0;
int count = 0;
int TX_heartbeat = 0;
int TX_heartbeat_count = 0;
float frequency = 0;
unsigned long start_vox_timer;
unsigned long current_vox_timer;
long Mode = 0;
const long WSPR_40 = 7038600;
const long FT8_40 = 7074000;
const long JS8_40 = 7078000;
const long WSPR_20 = 14095600;
const long FT8_20 = 14074000;
const long JS8_20 = 14078000;
// Instantiate the Objects
Si5351 si5351;
Adafruit_SSD1306 display(4);
void setup()
{
// Set up switches
pinMode(MODE_SWITCH, INPUT);
digitalWrite(MODE_SWITCH, HIGH);
pinMode(PTT, OUTPUT);
digitalWrite(PTT, LOW);
// Initialize the frequency measureing routine
FreqMeasure.begin();
Mode = WSPR_40;
// Initialize the display with the I2C addr 0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.setTextColor(WHITE);
display.clearDisplay();
display.setTextSize(2);
UpdateDisplay();
// Initialize the DDS
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
si5351.set_correction(123200, SI5351_PLL_INPUT_XO); // Set to specific Si5351 calibration number
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_2MA);
si5351.output_enable(SI5351_CLK0, 0);
start_vox_timer = millis(); // Initial start of the vox timer
//Serial.begin(57600);
}
void loop()
{
current_vox_timer = millis(); // Update the vox timer in preparation
if (digitalRead(MODE_SWITCH) == LOW)
{
if (Mode == WSPR_40)
Mode = FT8_40;
else if (Mode == FT8_40)
Mode = JS8_40;
else if (Mode == JS8_40)
Mode = WSPR_20;
else if (Mode == WSPR_20)
Mode = FT8_20;
else if (Mode == FT8_20)
Mode = JS8_20;
else if (Mode == JS8_20)
Mode = WSPR_40;
UpdateDisplay();
delay(100);
}
if (FreqMeasure.available()) // If available, average several frequency readings for greater accuuracy
{
TX_heartbeat = 1; // Set the TX_heartbeat to 1 as we are still transmitting
TX_heartbeat_count = 0; // Reset the TX heartbeat counter
sum = sum + FreqMeasure.read();
count = count + 1;
if (count > 60)
{
frequency = FreqMeasure.countToFrequency(sum / count);
si5351.output_enable(SI5351_CLK0, 1); // Turn on the Si5351
digitalWrite(PTT, HIGH); // Key the transmitter
si5351.set_freq(((frequency + Mode) * 100ULL), SI5351_CLK0); // Convert to TX freq and update the Si5351
sum = 0; // Clear the sum ready for next time
count = 0; // Reset the count ready for next time
}
}
if (current_vox_timer - start_vox_timer >= 100) // Test to see if we are still transmitting
{
if (TX_heartbeat == 0)
TX_heartbeat_count = TX_heartbeat_count + 1; // Increment the counter
if (TX_heartbeat_count >= 10) // Turn off after 1 second of no TX heartbeat (10 x 100mS = 1Sec)
{
si5351.output_enable(SI5351_CLK0, 0); // Turn off the Si5351
digitalWrite(PTT, LOW); // Turn off the transmitter
}
start_vox_timer = current_vox_timer; // Reset the vox timer ready for next time
}
TX_heartbeat = 0; // Set the TX_heartbeat to 0 ready for next check
}
void UpdateDisplay()
{
display.clearDisplay();
display.setCursor(0, 0);
display.println("Digi Radio");
display.setCursor(0, 18);
if (Mode == WSPR_40)
display.println("40m WSPR");
if (Mode == FT8_40)
display.println("40m FT8");
if (Mode == JS8_40)
display.println("40m JS8");
if (Mode == WSPR_20)
display.println("20m WSPR");
if (Mode == FT8_20)
display.println("20m FT8");
if (Mode == JS8_20)
display.println("20m JS8");
display.display();
}