kopia lustrzana https://github.com/kk4das/SSB_Radio_Control
522 wiersze
13 KiB
C++
522 wiersze
13 KiB
C++
|
#include "RadioControl.h"
|
||
|
#ifdef DISPLAY_NEXTION
|
||
|
|
||
|
//#define NEX_DEBUG // sends debug messages to the banner (bottom of screen)
|
||
|
//#define NEX_DEBUG1
|
||
|
|
||
|
// Dean Souleles, KK4DAS
|
||
|
// 7/25/2020
|
||
|
//
|
||
|
// Nextion Display Module for SSB_Radio_Contrl
|
||
|
// Nextion 2.8 Inch display
|
||
|
// Tested on Arduino Nano
|
||
|
//
|
||
|
// Arduino Nano Every
|
||
|
// PINS / WIRING
|
||
|
// ----------------------
|
||
|
// Arduino | Nextion
|
||
|
// --------|-------------
|
||
|
// 1 (RX) | TX (Blu) -- pins 0 and 1 are for Serial1
|
||
|
// 0 (TX) | RX (Yel)
|
||
|
// +5 | +5 (Red)
|
||
|
// Gnd | Gnd (Blk)
|
||
|
//------------------------
|
||
|
//
|
||
|
// Arduino Nano // deprecated - runs out of memory / stack crash
|
||
|
// PINS / WIRING
|
||
|
// ----------------------
|
||
|
// Arduino | Nextion
|
||
|
// --------|-------------
|
||
|
// 8 (RX) | TX (Blu) -- pins 8 and 9 are requuired by AltSoftSerial
|
||
|
// 9 (TX) | RX (Yel) -- to use other pins you can use SofwareSerial
|
||
|
// +5 | +5 (Red) -- but that will conflict with the interrupt
|
||
|
// Gnd | Gnd (Blk) -- used by the Rotary Encoder
|
||
|
//------------------------
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// We use the AltSoftSerial library to pins (8 and 9) rather than default 0,1
|
||
|
// AltSoftSerial is used rather than SoftwareSerial to free up the interrupt vector
|
||
|
// required for the digital encoder
|
||
|
// NOTE:
|
||
|
// AltSoftSerial uses only fixed pins 8,9 on an Uno or Nano
|
||
|
// Pin 10 cannot be used for PWM
|
||
|
// For other boards see: https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
|
||
|
//
|
||
|
// First, apply the serial fixes from Ray Livingston to the Nextion Libarary:
|
||
|
// https://forum.arduino.cc/index.php?topic=620821.0
|
||
|
// Replace files in the ../libraries/ITEADLIB_Arduino_Nextion folder:
|
||
|
// NexConfig.h
|
||
|
// NexHardware.h
|
||
|
// NexHardware.cpp
|
||
|
// Plus one more patch to fix a bug that was including SoftwareSerial when it should not have
|
||
|
// NexUpload.cpp (change by me, Dean Souleles)
|
||
|
//
|
||
|
// Next we edit NexConfig.h in the ../libraries/ITEADLIB_Arduino_Nextion folder as follows:
|
||
|
// Comment out this line:
|
||
|
// #define nexSerial Serial
|
||
|
//
|
||
|
// Add these three lines:
|
||
|
// #include <AltSoftSerial.h>
|
||
|
// extern AltSoftSerial HMISerial;
|
||
|
// #define nexSerial HMISerial
|
||
|
//
|
||
|
// Add the following to your sketch
|
||
|
// #include <AltSoftSerial.h>
|
||
|
// AltSoftSerial HMISerial; //RX TX - connect to Nextion TX RX - Must use Pins 9,10 on Uno/Nano
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include <Nextion.h> // https://github.com/itead/ITEADLIB_Arduino_Nextion
|
||
|
|
||
|
//#include <SoftwareSerial.h>
|
||
|
//SoftwareSerial HMISerial(8,9); //RX TX - connect to Nextion TX RX - Pins 8,9 on Uno/Nano
|
||
|
|
||
|
#if _BOARDTYPE == Nano
|
||
|
#include <AltSoftSerial.h>
|
||
|
AltSoftSerial HMISerial; //RX TX - connect to Nextion TX RX - Must use Pins 8,9 on Uno/Nano
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// Declare Nextion objects
|
||
|
// Use the page ID, component id and component name from the Nextion IDE
|
||
|
//
|
||
|
|
||
|
// Nextion PAGE
|
||
|
// Current design only uses one page of the display
|
||
|
#define PAGE 0
|
||
|
|
||
|
|
||
|
|
||
|
// Nextion Component IDs for buttons and text displays
|
||
|
// These ID's must match the ID's Nextion IDE
|
||
|
#define VFO_ID 2
|
||
|
#define SIDEBAND_ID 5
|
||
|
#define TUNE_ID 7
|
||
|
#define INCREMENT_ID 6
|
||
|
#define ACT_VFO_ID 3
|
||
|
#define ALT_VFO_ID 4
|
||
|
#define TX_RX_ID 8
|
||
|
#define SMETER_ID 10
|
||
|
#define BANNER_ID 9
|
||
|
#define TUNE_PLUS_ID 11
|
||
|
#define TUNE_MINUS_ID 12
|
||
|
#define TUNE_STATE_ID 15
|
||
|
#define ATOB_ID 18 // VFO A copy to B button
|
||
|
#define SPLIT_ID 19
|
||
|
#define VAB_ID 20 // VFO Inidicator
|
||
|
|
||
|
// Nextion Component names
|
||
|
// These names must match the names in the Nextion IDE
|
||
|
#define VFO_NAME "bVFO"
|
||
|
#define SIDEBAND_NAME "bSideband"
|
||
|
#define TUNE_NAME "bTune"
|
||
|
#define INCREMENT_NAME "bIncr"
|
||
|
#define ACT_VFO_NAME "tActVFO"
|
||
|
#define ALT_VFO_NAME "tAltVFO"
|
||
|
#define BANNER_NAME "tBanner"
|
||
|
#define TX_RX_NAME "tTxRx"
|
||
|
#define SMETER_NAME "pSmeter"
|
||
|
#define TUNE_PLUS_NAME "bPlus"
|
||
|
#define TUNE_MINUS_NAME "bMinus"
|
||
|
#define TUNE_STATE_NAME "tTuneState"
|
||
|
#define ATOB_NAME "bAtoB"
|
||
|
#define SPLIT_NAME "btSplit"
|
||
|
#define VAB_NAME "tVAB"
|
||
|
|
||
|
// Nextion Buttons
|
||
|
// Each user interface object that the user touches needs to be defined here
|
||
|
//
|
||
|
NexButton bVFO = NexButton(PAGE, VFO_ID, VFO_NAME);
|
||
|
NexButton bSideband = NexButton(PAGE, SIDEBAND_ID, SIDEBAND_NAME);
|
||
|
NexButton bTune = NexButton(PAGE, TUNE_ID, TUNE_NAME);
|
||
|
NexButton bIncrement = NexButton(PAGE, INCREMENT_ID, INCREMENT_NAME);
|
||
|
NexButton bTunePlus = NexButton(PAGE, TUNE_PLUS_ID, TUNE_PLUS_NAME);
|
||
|
NexButton bTuneMinus = NexButton(PAGE, TUNE_MINUS_ID, TUNE_MINUS_NAME);
|
||
|
NexButton bAtoB = NexButton(PAGE, ATOB_ID, ATOB_NAME);
|
||
|
NexDSButton btSplit = NexDSButton(PAGE, SPLIT_ID, SPLIT_NAME);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Setup a list of objects to respond to a touch event
|
||
|
//
|
||
|
NexTouch *nex_listen_list[] = {
|
||
|
&bVFO,
|
||
|
&bSideband,
|
||
|
&bTune,
|
||
|
&bIncrement,
|
||
|
&bTunePlus,
|
||
|
&bTuneMinus,
|
||
|
&bAtoB,
|
||
|
&btSplit,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
// HMI_send_command(cmd)
|
||
|
// Sends one command to the Nextion Display
|
||
|
//
|
||
|
// Example usage:
|
||
|
// String cmd;
|
||
|
// cmd = F("vis ");
|
||
|
// cmd = cmd + F(TUNE_STATE_NAME);
|
||
|
// cmd = cmd + F(",");
|
||
|
// if (on_off) {
|
||
|
// cmd = cmd + F("1");
|
||
|
// } else {
|
||
|
// cmd = cmd + F("0");
|
||
|
// }
|
||
|
// HMI_send_command(cmd.c_str());
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
void HMI_send_command(char* cmd) {
|
||
|
|
||
|
/*
|
||
|
// Send the command
|
||
|
HMISerial.print(cmd);
|
||
|
|
||
|
// Send end-of-message per Nextion protocol
|
||
|
HMISerial.write(0xff);
|
||
|
HMISerial.write(0xff);
|
||
|
HMISerial.write(0xff);
|
||
|
|
||
|
*/
|
||
|
// Send the command to the Nextion
|
||
|
nexSerial.print(cmd);
|
||
|
|
||
|
// Send end-of-message per Nextion protocol
|
||
|
nexSerial.write(0xff);
|
||
|
nexSerial.write(0xff);
|
||
|
nexSerial.write(0xff);
|
||
|
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
// displayActVFO(uint32_t freq)
|
||
|
// Formats and displays Active and Alternat VFO frequencies
|
||
|
// Legal values: Frequency in Hz
|
||
|
//
|
||
|
// To do - comibine into one function
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void displayActVFO(uint32_t freq) {
|
||
|
String cmd;
|
||
|
String fmt;
|
||
|
char f[11];
|
||
|
uint32_t mil, hund_thou, ten_thou, thou, hund, tens, ones;
|
||
|
|
||
|
// Format number as nn.nnn.nnn
|
||
|
mil = freq / 1000000;
|
||
|
hund_thou = (freq/100000)%10;
|
||
|
ten_thou = (freq/10000)%10;
|
||
|
thou = (freq/1000)%10;
|
||
|
hund = (freq/100)%10;
|
||
|
tens = (freq/10)%10;
|
||
|
ones = freq%10;
|
||
|
fmt=F("%2ld.%ld%ld%ld.%ld%ld%ld");
|
||
|
snprintf(f, sizeof(f),fmt.c_str(),mil, hund_thou, ten_thou,thou, hund, tens, ones);
|
||
|
|
||
|
cmd = F(ACT_VFO_NAME);
|
||
|
cmd += F(".txt=\"");
|
||
|
cmd += f;
|
||
|
cmd += F("\"");
|
||
|
HMI_send_command(cmd.c_str());
|
||
|
|
||
|
}
|
||
|
|
||
|
void displayAltVFO(uint32_t freq) {
|
||
|
String cmd;
|
||
|
String fmt;
|
||
|
char f[11];
|
||
|
uint32_t mil, hund_thou, ten_thou, thou, hund, tens, ones;
|
||
|
|
||
|
// Format number as nn.nnn.nnn
|
||
|
mil = freq / 1000000;
|
||
|
hund_thou = (freq/100000)%10;
|
||
|
ten_thou = (freq/10000)%10;
|
||
|
thou = (freq/1000)%10;
|
||
|
hund = (freq/100)%10;
|
||
|
tens = (freq/10)%10;
|
||
|
ones = freq%10;
|
||
|
fmt=F("%2ld.%ld%ld%ld.%ld%ld%ld");
|
||
|
snprintf(f, sizeof(f),fmt.c_str(),mil, hund_thou, ten_thou,thou, hund, tens, ones);
|
||
|
|
||
|
cmd = F(ALT_VFO_NAME);
|
||
|
cmd += F(".txt=\"");
|
||
|
cmd += f;
|
||
|
cmd += F("\"");
|
||
|
HMI_send_command(cmd.c_str());
|
||
|
|
||
|
}
|
||
|
|
||
|
void displaySMeter(byte level) {
|
||
|
// Nextion dipslay bar graph is set by integer percent 0-100
|
||
|
// Convert the S level into a % and send to display
|
||
|
|
||
|
String cmd;
|
||
|
float pct;
|
||
|
int scaled_level;
|
||
|
pct = (float(level)/13.0)*100.0;
|
||
|
scaled_level=pct;
|
||
|
|
||
|
cmd = F(SMETER_NAME);
|
||
|
cmd += F(".val=");
|
||
|
cmd += scaled_level;
|
||
|
|
||
|
HMI_send_command(cmd.c_str());
|
||
|
|
||
|
#ifdef NEX_DEBUG1
|
||
|
String msg = F("displaySMeter: ");
|
||
|
msg = msg + level;
|
||
|
msg = msg + F(" ");
|
||
|
msg = msg + scaled_level;
|
||
|
displayBanner(msg);
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
void displayBanner(String s) {
|
||
|
String cmd;
|
||
|
cmd = F(BANNER_NAME);
|
||
|
cmd += F(".txt=\"");
|
||
|
cmd += s;
|
||
|
cmd += F("\"");
|
||
|
HMI_send_command(cmd.c_str());
|
||
|
}
|
||
|
|
||
|
void displayVFOAB(int vfo) {
|
||
|
String cmd;
|
||
|
cmd = F(VAB_NAME);
|
||
|
cmd += F(".txt=\"");
|
||
|
if (vfo == VFOA) {
|
||
|
cmd += F("A");
|
||
|
} else {
|
||
|
cmd += F("B");
|
||
|
}
|
||
|
cmd += F("\"");
|
||
|
HMI_send_command(cmd.c_str());
|
||
|
|
||
|
#ifdef NEX_DEBUG
|
||
|
String msg = F("displayVFOAB: ");
|
||
|
msg = msg + vfo;
|
||
|
displayBanner(msg);
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
void displayTxRx(int tx_rx) {
|
||
|
String cmd;
|
||
|
cmd = F(TX_RX_NAME);
|
||
|
cmd += F(".txt=\"");
|
||
|
if (tx_rx == TX) {
|
||
|
cmd += F("TX");
|
||
|
} else {
|
||
|
cmd += F("RX");
|
||
|
}
|
||
|
cmd += F("\"");
|
||
|
HMI_send_command(cmd.c_str());
|
||
|
|
||
|
#ifdef NEX_DEBUG
|
||
|
String msg = F("displayTxRx: ");
|
||
|
msg = msg + tx_rx;
|
||
|
displayBanner(msg);
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
void displayMode(int mode) {
|
||
|
String modeString;
|
||
|
if (mode == USB) {
|
||
|
modeString = F("USB");
|
||
|
} else {
|
||
|
modeString = F("LSB");
|
||
|
}
|
||
|
bSideband.setText(modeString.c_str());
|
||
|
|
||
|
#ifdef NEX_DEBUG
|
||
|
String msg = F("displayMode: ");
|
||
|
msg = msg + modeString;
|
||
|
displayBanner(msg);
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
void displayIncr(uint32_t increment) {
|
||
|
String hertz;
|
||
|
switch (increment) {
|
||
|
case 1: hertz = F(" 1"); break;
|
||
|
case 10: hertz = F(" 10"); break;
|
||
|
case 100: hertz = F(" 100"); break;
|
||
|
case 1000: hertz = F(" 1K"); break;
|
||
|
case 10000: hertz = F(" 10K"); break;
|
||
|
case 100000: hertz= F("100K"); break;
|
||
|
case 1000000:hertz = F(" 1M");
|
||
|
}
|
||
|
bIncrement.setText(hertz.c_str());
|
||
|
|
||
|
#ifdef NEX_DEBUG
|
||
|
String msg = F("displayIncr: ");
|
||
|
msg = msg + hertz;
|
||
|
displayBanner(msg);
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
void displayTune(boolean on_off) {
|
||
|
// Send visibility command to Nextion
|
||
|
// Format: vis <object_name),<0/1>
|
||
|
String cmd;
|
||
|
cmd = F("vis ");
|
||
|
cmd += F(TUNE_STATE_NAME);
|
||
|
cmd += F(",");
|
||
|
cmd += on_off;
|
||
|
HMI_send_command(cmd.c_str());
|
||
|
|
||
|
#ifdef NEX_DEBUG
|
||
|
displayBanner(cmd);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
void displaySplit(boolean split) {
|
||
|
// The split button is a dual state button
|
||
|
// State 0 = blue = ff
|
||
|
// State 1 = green = on
|
||
|
// To change the state and color set the val property to 0/1
|
||
|
// This mimics a button press on the display
|
||
|
|
||
|
String cmd =F(SPLIT_NAME);
|
||
|
cmd += F(".val=");
|
||
|
if (split) {
|
||
|
cmd += 1;
|
||
|
} else {
|
||
|
cmd += 0;
|
||
|
}
|
||
|
HMI_send_command(cmd.c_str());
|
||
|
|
||
|
#ifdef NEX_DEBUG
|
||
|
String msg = F("displaySplit: ");
|
||
|
msg = msg + split;
|
||
|
displayBanner(msg);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Button Callback Functions
|
||
|
// Called whenever a button is pressed and released
|
||
|
//
|
||
|
|
||
|
// VFO A/B Button
|
||
|
void bVFOPopCallback(void *ptr) {
|
||
|
SwapVFO(); // call the VFO switch button handler
|
||
|
}
|
||
|
|
||
|
// LSB/USB Button
|
||
|
void bSidebandPopCallback(void *ptr) {
|
||
|
SwapSB();
|
||
|
}
|
||
|
|
||
|
// Tune Plus (increase VFO)
|
||
|
void bTunePlusPushCallback(void *ptr) {
|
||
|
AdjustVFO(increment);
|
||
|
}
|
||
|
|
||
|
// Tune Minus (decrease VFO)
|
||
|
void bTuneMinusPushCallback(void *ptr) {
|
||
|
AdjustVFO(-1 * increment);
|
||
|
}
|
||
|
|
||
|
// Tune Tone
|
||
|
void bTunePopCallback(void *ptr) {
|
||
|
DoTune();
|
||
|
}
|
||
|
|
||
|
// Tuning Increment Change
|
||
|
void bIncrementPopCallback(void *ptr) {
|
||
|
AdvanceIncrement();
|
||
|
}
|
||
|
|
||
|
// Split on/off
|
||
|
void btSplitPopCallback(void *ptr) {
|
||
|
uint32_t split_val;
|
||
|
|
||
|
btSplit.getValue(&split_val);
|
||
|
if (split_val==1) {
|
||
|
startSplit();
|
||
|
} else {
|
||
|
stopSplit();
|
||
|
}
|
||
|
|
||
|
#ifdef NEX_DEBUG
|
||
|
String msg = F("btSplitPopCallback: ");
|
||
|
msg = msg + split_val;
|
||
|
displayBanner(msg);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// Make Act and Alt VFO the same
|
||
|
void bAtoBPopCallback(void *ptr) {
|
||
|
|
||
|
if (active_vfo == VFOA) {
|
||
|
vfoBfreq = vfoAfreq;
|
||
|
} else {
|
||
|
vfoAfreq = vfoBfreq;
|
||
|
}
|
||
|
displayAltVFO(vfoAfreq); // update the Alt VFO display
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Setup
|
||
|
// Called once at startup
|
||
|
//
|
||
|
void displaySetup(String banner,
|
||
|
uint32_t vfoActfreq, uint32_t vfoAltfreq,
|
||
|
uint32_t activeVFO,
|
||
|
int tx_rx,
|
||
|
int sideband,
|
||
|
boolean split,
|
||
|
uint32_t increment,
|
||
|
byte s_meter) {
|
||
|
|
||
|
nexInit(9600); // Initialize the Nextion library
|
||
|
|
||
|
//
|
||
|
// Attach callback routines for each button
|
||
|
// attachPop will set the library to invoke the specified funtion each time a button is released
|
||
|
//
|
||
|
bVFO.attachPop(bVFOPopCallback, &bVFO); // VFO A/B button
|
||
|
bSideband.attachPop(bSidebandPopCallback, &bSideband); // LSB/USB button
|
||
|
bTune.attachPop(bTunePopCallback, &bTune); // Tune
|
||
|
bIncrement.attachPop(bIncrementPopCallback, &bIncrement); // Change Incrmement
|
||
|
btSplit.attachPop(btSplitPopCallback, &btSplit); // Split On/Off
|
||
|
bAtoB.attachPop(bAtoBPopCallback, &bAtoB); // Make Alt VFO = Act VFO
|
||
|
|
||
|
bTunePlus.attachPush(bTunePlusPushCallback, &bTunePlus); // Tune up
|
||
|
bTuneMinus.attachPush(bTuneMinusPushCallback, &bTuneMinus); // Tune down
|
||
|
|
||
|
//
|
||
|
// Display the intitial values
|
||
|
//
|
||
|
displayBanner(banner);
|
||
|
displayActVFO(vfoActfreq);
|
||
|
displayAltVFO(vfoAltfreq);
|
||
|
displayVFOAB(activeVFO);
|
||
|
displayTxRx(tx_rx);
|
||
|
displayMode(sideband);
|
||
|
displaySplit(split);
|
||
|
displayIncr(increment);
|
||
|
displaySMeter(s_meter);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void CheckTouch() {
|
||
|
// Call the Nextion check function to look for activites on your listen list
|
||
|
nexLoop(nex_listen_list);
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif
|