-
Notifications
You must be signed in to change notification settings - Fork 1
/
SSB_Radio_Control.ino
375 lines (303 loc) · 12.8 KB
/
SSB_Radio_Control.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*
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
}