kopia lustrzana https://github.com/kk4das/SSB_Radio_Control
376 wiersze
13 KiB
C++
376 wiersze
13 KiB
C++
/*
|
|
SSB_Radio_Control
|
|
Dean Souleles, KK4DAS, contact kk4das@gmail.com
|
|
|
|
This sketch implement s basic SSB radio control panel with the following features:
|
|
Dual VFO A/B
|
|
Rotary encoder for tuning, push button to change tuning increment
|
|
SI5351 Clock generator for the LO and BFO
|
|
CAT Control (emulates an ICOM IC-746)
|
|
Split mode support (Split from CAT, manual split requres Nextion touch screen)
|
|
Settings memory (last frequency and mode are saved)
|
|
Optional S-Meter
|
|
|
|
Controls
|
|
* Rotary encoder to change frequence
|
|
* Rotary encode button changes tuning increment
|
|
* VFO A/B Select toggle
|
|
* Mode select USB/LSB toggle
|
|
* Tune button (emits 10 second pulsed tone at 800Hz for tuning)
|
|
* MOX toggle - puts rig in to Tx/Rx
|
|
* Optional dual-band support 20/40
|
|
|
|
Modules for different display types
|
|
* 20x4 LCD
|
|
* 320x240 TFT color display
|
|
* 2.8" Nextion Touch Screen
|
|
|
|
Display features
|
|
* Dual VFOS
|
|
* Mode indicator SSB/LSB
|
|
* Tx/Rx ndicator
|
|
* TuningStep Inidicator
|
|
* Optional S Meter
|
|
* Banner including callsign
|
|
|
|
Additional controls with the Nextion display
|
|
* Continuous scanning
|
|
* Split mode
|
|
|
|
Version 1.4
|
|
March 9 2021
|
|
Rstored LCD Display Option
|
|
Compile time selection of S-Meter and Dual Band mods
|
|
Refactoring of encoder handling
|
|
|
|
Version 1.3
|
|
Jan 25, 2021
|
|
Changed CAT module to IC-746
|
|
|
|
Version 1.2
|
|
Dec 14, 2020
|
|
Dual Band 20/40 Support
|
|
S-Meter
|
|
|
|
Version 1.1
|
|
Dec 13. 2020
|
|
Ported to Nano Every for more sweet SRAM
|
|
* * Updated interrupt handling in Encoder.cpp to work with Nano Every (as well as UNO/Nano)
|
|
* * Replaced SoftwareSerial connections to Nextion with Hardware Serial - Serial1
|
|
|
|
Version 1.0
|
|
Aug 13, 2020
|
|
Adapted from SimpleSSB Sketch by N6QW, Pete Juliano and others
|
|
|
|
|
|
NOTE TO BUILDERS
|
|
This is a reference implementation of an SSB radio control program for a homebrew SSB transceiver.
|
|
It is a fully functioning SSB radio control program. While it has been built for my particular hardware
|
|
configuration every attempt has been made to make it modular in design so that the builder can swap out
|
|
modules at will. It should be fairly straight forward to adapt to the builder's hardware selection
|
|
of switches, buttons and knobs or even alternate displays.
|
|
|
|
*/
|
|
|
|
#include "RadioControl.h"
|
|
|
|
#ifdef DEBUG
|
|
char debugmsg[25];
|
|
#endif
|
|
|
|
//=============== Globals ============================================
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// si5351 Clock Module //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////
|
|
Si5351 si5351;
|
|
|
|
// Calibration offest - adjust for variability in the SI5351 module
|
|
// crystal - must be set for the particular SI5351 installed
|
|
//#define CALIBRATION_OFFSET 1190 // Calibration for the SI-5351
|
|
#define CALIBRATION_OFFSET 880 // Calibration for the SI-5351
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// BFO and VFO Constants and Variables //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef BFO12MHZ
|
|
const uint32_t USB_BFO = 12001600L;
|
|
const uint32_t LSB_BFO = 11998600L;
|
|
#endif
|
|
|
|
#ifdef BFO9MHZ
|
|
const uint32_t USB_BFO = 9001500L;
|
|
const uint32_t LSB_BFO = 8998500L;
|
|
#endif
|
|
|
|
uint32_t bfo = LSB_BFO; // Startup BFO frequency
|
|
const uint32_t BFO_DELTA = USB_BFO - LSB_BFO; // Difference between USB and LSB for BFO change
|
|
|
|
//
|
|
// Startup VFO A/B frequencies
|
|
//
|
|
uint32_t vfoAfreq = 7200000L; // 7.200.000
|
|
uint32_t vfoBfreq = 7074000L; // FT-8 7.074.000
|
|
byte vfoASideband = LSB;
|
|
byte vfoBSideband = USB;
|
|
|
|
uint32_t increment = 1000; // startup VFO tuning increment in HZ.
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Active VFO //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////
|
|
byte active_vfo = VFOA; // startup on VFOA
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Sideband Selection //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////
|
|
byte sideband = LSB; // startup in LSB
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Sideband Selection //
|
|
// //
|
|
/////////////////////////////////////////////////////////////////////
|
|
uint32_t band20Freq = 14200000L; // 14.200.000
|
|
uint32_t band40Freq = 7200000L; // 7.200.000
|
|
byte band20Sideband = USB;
|
|
byte band40Sideband = LSB;
|
|
byte band = BAND40;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Transmit / Receive Indicators //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////
|
|
byte TxRxState = RX; // startup in RX
|
|
byte lastTxRxState = RX; // previous TxRxState
|
|
byte txSource = PTT_MIC; // transmit source - Mic, Tune, CAT
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// S Meter 0-9 +10, +20 +30 //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////
|
|
byte smeter = 0; // startup s_meter reading (requires SMETER)
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Split Mode On/Off //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool split = false;
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// setBandFilters(band) //
|
|
// For 20 meters turn relay ON (NO) //
|
|
// For 40 meters turn relay OFF (NC) //
|
|
///////////////////////////////////////////////////////////
|
|
void setBandFilters(int band) {
|
|
#ifdef DUAL_BAND
|
|
switch (band) {
|
|
case BAND20:
|
|
digitalWrite(BAND_PIN, HIGH);
|
|
break;
|
|
case BAND40:
|
|
digitalWrite(BAND_PIN, LOW);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef CW
|
|
//
|
|
// setCW()
|
|
//
|
|
// Experimental code to generate CW tone on key down at 700Hz above the dial frequency
|
|
// Needs a bunch of scaffolding to implement CW mode
|
|
//
|
|
// Turns off the BFO, sets the LO to the VFO frequency + 700
|
|
//
|
|
// After testing -
|
|
// tone produced OK but needs an amplifier to get significant power out
|
|
//
|
|
void setCW() {
|
|
si5351.set_freq(0, 0, SI5351_CLK2); // turn off BFO
|
|
si5351.set_freq(vfoAfreq+700L , SI5351_PLL_FIXED, SI5351_CLK0); // set LO to operating freq
|
|
}
|
|
#endif
|
|
|
|
//********************setVFO******************************************
|
|
void setVFO(uint32_t freq) {
|
|
//
|
|
// Set CLK0 to the to input frequency adjusted for the current BFO frequency
|
|
|
|
#ifdef DUAL_BAND
|
|
//
|
|
// Set filters for the band based on frequency
|
|
// Save frequency and sideband for band switching
|
|
//
|
|
if (freq >= BAND20_EDGE) {
|
|
setBandFilters(BAND20);
|
|
band20Freq = freq;
|
|
band20Sideband = sideband;
|
|
band = BAND20;
|
|
} else if (freq >= BAND40_EDGE) {
|
|
setBandFilters(BAND40);
|
|
band40Freq = freq;
|
|
band40Sideband = sideband;
|
|
band=BAND40;
|
|
}
|
|
#endif
|
|
|
|
si5351.set_freq(freq + bfo, SI5351_PLL_FIXED, SI5351_CLK0);
|
|
startSettingsTimer(); // start timer to save current settings
|
|
}
|
|
|
|
void setBFO(uint32_t freq) {
|
|
//
|
|
// Set CLK2 to the to input frequency
|
|
//
|
|
|
|
si5351.set_freq(freq, 0, SI5351_CLK2);
|
|
}
|
|
|
|
|
|
//*********************Setup Arduino Pins*****************************
|
|
|
|
void setupPins() {
|
|
//
|
|
// Set the control buttons to INPUT_PULLUP
|
|
// Button state will be HIGH when open and LOW when pressed
|
|
//
|
|
pinMode(TUNE_BTN, INPUT_PULLUP); // Tune - momentary button
|
|
pinMode(VFO_BTN, INPUT_PULLUP); // VFO A/B Select - momentary button
|
|
pinMode(SIDEBAND_BTN, INPUT_PULLUP); // Upper/lower SB Select - momentary button
|
|
pinMode(BAND_BTN, INPUT_PULLUP); // Band Switch 20/40 - momentary button
|
|
pinMode(PTT_SENSE, INPUT_PULLUP); // Mic PTT swtich
|
|
pinMode(PTT, OUTPUT); digitalWrite(PTT, LOW); // HIGH to enable TX
|
|
pinMode(BAND_PIN, OUTPUT); digitalWrite(BAND_PIN, LOW); // Band Switch Relay (LOW = NC = 40m, HIGH = NO = 20m)
|
|
|
|
pinMode(LED_BUILTIN, OUTPUT);
|
|
|
|
}
|
|
|
|
|
|
//**********************Initialize SI5351******************************
|
|
|
|
void setupSI5351() {
|
|
si5351.init(SI5351_CRYSTAL_LOAD_8PF);
|
|
si5351.set_correction(CALIBRATION_OFFSET); // calibration offset
|
|
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
|
|
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // Higher Drive since it is a ADE-1 DBM
|
|
si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_8MA);
|
|
si5351.set_freq(bfo, 0, SI5351_CLK2); // Initialize the bfo
|
|
|
|
//
|
|
// Initialize the VFO
|
|
//
|
|
switch (active_vfo) {
|
|
case VFOA:
|
|
setVFO(vfoAfreq);
|
|
break;
|
|
case VFOB:
|
|
setVFO(vfoBfreq);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Setup //
|
|
// //
|
|
// Called once by the Arduino operating system at startup //
|
|
// All initialization code goes here //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////
|
|
void setup() {
|
|
|
|
uint32_t vfoActfreq;
|
|
uint32_t vfoAltfreq;
|
|
|
|
#ifdef DEBUG
|
|
Serial.begin(57600);
|
|
#endif
|
|
|
|
setupPins(); // Initialize arduino pins
|
|
setupEncoder(); // Initialize interrupt service for rotary encoder
|
|
setupSettings(); // Retrive settings from EEPROM
|
|
setupSI5351();
|
|
|
|
|
|
if (active_vfo == VFOA) {
|
|
vfoActfreq = vfoAfreq;
|
|
vfoAltfreq = vfoBfreq;
|
|
} else {
|
|
vfoActfreq = vfoBfreq;
|
|
vfoAltfreq = vfoAfreq;
|
|
}
|
|
|
|
|
|
// Initialize the display with startup values
|
|
Delay(500); // short delay to let the display initialize - needed for Nextion
|
|
|
|
// Construct banner for TFT or Nextion display
|
|
// "Vx.x RIGNAME CALLSIGN"
|
|
String banner;
|
|
banner = F("V");
|
|
banner += F(VERSION);
|
|
banner += F(" ");
|
|
banner += F(RIGNAME);
|
|
banner += F(" ");
|
|
banner += F(CALLSIGN);
|
|
|
|
displaySetup(banner, // version number. call sign
|
|
vfoActfreq, vfoAltfreq, // Initial active and alternate VFO
|
|
active_vfo, // VFO A/B indicator
|
|
TxRxState, // TX/RX indicator
|
|
sideband, // LSB/USB,
|
|
split, // Split mode on/off
|
|
increment, // Tuning increment
|
|
smeter); // S Meter
|
|
|
|
setupCat();
|
|
}
|
|
|
|
void loop() {
|
|
|
|
CheckEncoder(); //VFO frequency changes
|
|
CheckIncrement(); // Encoder Button
|
|
|
|
#ifdef DUAL_BAND
|
|
CheckBand(); // Band Switch 20/40
|
|
#endif
|
|
|
|
CheckVFO(); // VFO A/B change
|
|
CheckSB(); // USB/LSB change
|
|
CheckPTT(); // Check for Mic PTT
|
|
CheckTune(); // Check for Tune button press
|
|
|
|
#ifdef SMETER
|
|
CheckSmeter(); // Signal strength
|
|
#endif
|
|
|
|
CheckCat(); // CAT Control
|
|
CheckSettings(); // Update EEPROM on Settings Change
|
|
|
|
#ifdef DISPLAY_NEXTION
|
|
CheckTouch(); // Check for touch screen action
|
|
#endif
|
|
|
|
}
|