diff --git a/src/AppConfig.cpp b/src/AppConfig.cpp index 63d7eb1..09e1767 100644 --- a/src/AppConfig.cpp +++ b/src/AppConfig.cpp @@ -205,9 +205,12 @@ AppConfig::AppConfig() : configName("") { waterfallLinesPerSec.store(DEFAULT_WATERFALL_LPS); spectrumAvgSpeed.store(0.65f); #ifdef USE_HAMLIB + rigEnabled.store(false); rigModel.store(1); rigRate.store(57600); rigPort = "/dev/ttyUSB0"; + rigControlMode.store(true); + rigFollowMode.store(true); #endif } @@ -383,9 +386,12 @@ bool AppConfig::save() { #ifdef USE_HAMLIB DataNode *rig_node = cfg.rootNode()->newChild("rig"); + *rig_node->newChild("enabled") = rigEnabled.load()?1:0; *rig_node->newChild("model") = rigModel.load(); *rig_node->newChild("rate") = rigRate.load(); *rig_node->newChild("port") = rigPort; + *rig_node->newChild("control") = rigControlMode.load()?1:0; + *rig_node->newChild("follow") = rigFollowMode.load()?1:0; #endif std::string cfgFileName = getConfigFileName(); @@ -526,6 +532,11 @@ bool AppConfig::load() { if (cfg.rootNode()->hasAnother("rig")) { DataNode *rig_node = cfg.rootNode()->getNext("rig"); + if (rig_node->hasAnother("enabled")) { + int loadEnabled; + rig_node->getNext("enabled")->element()->get(loadEnabled); + rigEnabled.store(loadEnabled?true:false); + } if (rig_node->hasAnother("model")) { int loadModel; rig_node->getNext("model")->element()->get(loadModel); @@ -539,6 +550,16 @@ bool AppConfig::load() { if (rig_node->hasAnother("port")) { rigPort = rig_node->getNext("port")->element()->toString(); } + if (rig_node->hasAnother("control")) { + int loadControl; + rig_node->getNext("control")->element()->get(loadControl); + rigControlMode.store(loadControl?true:false); + } + if (rig_node->hasAnother("follow")) { + int loadFollow; + rig_node->getNext("follow")->element()->get(loadFollow); + rigFollowMode.store(loadFollow?true:false); + } } #endif @@ -578,4 +599,28 @@ void AppConfig::setRigPort(std::string rigPort) { this->rigPort = rigPort; } +void AppConfig::setRigControlMode(bool cMode) { + rigControlMode.store(cMode); +} + +bool AppConfig::getRigControlMode() { + return rigControlMode.load(); +} + +void AppConfig::setRigFollowMode(bool fMode) { + rigFollowMode.store(fMode); +} + +bool AppConfig::getRigFollowMode() { + return rigFollowMode.load(); +} + +void AppConfig::setRigEnabled(bool enabled) { + rigEnabled.store(enabled); +} + +bool AppConfig::getRigEnabled() { + return rigEnabled.load(); +} + #endif diff --git a/src/AppConfig.h b/src/AppConfig.h index 8227c3b..c8ca860 100644 --- a/src/AppConfig.h +++ b/src/AppConfig.h @@ -100,6 +100,15 @@ public: std::string getRigPort(); void setRigPort(std::string rigPort); + + void setRigControlMode(bool cMode); + bool getRigControlMode(); + + void setRigFollowMode(bool fMode); + bool getRigFollowMode(); + + void setRigEnabled(bool enabled); + bool getRigEnabled(); #endif void setConfigName(std::string configName); @@ -122,5 +131,6 @@ private: #if USE_HAMLIB std::atomic_int rigModel, rigRate; std::string rigPort; + std::atomic_bool rigEnabled, rigFollowMode, rigControlMode; #endif }; diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index fa16fb3..12b0056 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -446,7 +446,13 @@ AppFrame::AppFrame() : rigEnableMenuItem = rigMenu->AppendCheckItem(wxID_RIG_TOGGLE, wxT("Enable Rig")); rigMenu->Append(wxID_RIG_SDR_IF, wxT("SDR-IF")); + + rigControlMenuItem = rigMenu->AppendCheckItem(wxID_RIG_CONTROL, wxT("Control Rig")); + rigControlMenuItem->Check(wxGetApp().getConfig()->getRigControlMode()); + rigFollowMenuItem = rigMenu->AppendCheckItem(wxID_RIG_FOLLOW, wxT("Follow Rig")); + rigFollowMenuItem->Check(wxGetApp().getConfig()->getRigFollowMode()); + wxMenu *rigModelMenu = new wxMenu; RigList &rl = RigThread::enumerate(); numRigs = rl.size(); @@ -685,6 +691,11 @@ void AppFrame::updateDeviceParams() { #if USE_HAMLIB + if (wxGetApp().getConfig()->getRigEnabled() && !wxGetApp().rigIsActive()) { + enableRig(); + rigEnableMenuItem->Check(true); + } + std::string deviceId = devInfo->getDeviceId(); DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(deviceId); @@ -701,6 +712,33 @@ void AppFrame::updateDeviceParams() { deviceChanged.store(false); } +#ifdef USE_HAMLIB +void AppFrame::enableRig() { + wxGetApp().stopRig(); + wxGetApp().initRig(rigModel, rigPort, rigSerialRate); + + if (devInfo != nullptr) { + std::string deviceId = devInfo->getDeviceId(); + DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(deviceId); + rigSDRIF = devConfig->getRigIF(rigModel); + if (rigSDRIF) { + wxGetApp().lockFrequency(rigSDRIF); + } else { + wxGetApp().unlockFrequency(); + } + } else { + wxGetApp().unlockFrequency(); + } + + wxGetApp().getConfig()->setRigEnabled(true); +} + +void AppFrame::disableRig() { + wxGetApp().stopRig(); + wxGetApp().unlockFrequency(); + wxGetApp().getConfig()->setRigEnabled(false); +} +#endif void AppFrame::OnMenu(wxCommandEvent& event) { if (event.GetId() >= wxID_RT_AUDIO_DEVICE && event.GetId() < wxID_RT_AUDIO_DEVICE + (int)devices.size()) { @@ -972,24 +1010,9 @@ void AppFrame::OnMenu(wxCommandEvent& event) { if (event.GetId() == wxID_RIG_TOGGLE) { resetRig = false; if (!wxGetApp().rigIsActive()) { - wxGetApp().stopRig(); - wxGetApp().initRig(rigModel, rigPort, rigSerialRate); - - if (devInfo != nullptr) { - std::string deviceId = devInfo->getDeviceId(); - DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(deviceId); - rigSDRIF = devConfig->getRigIF(rigModel); - if (rigSDRIF) { - wxGetApp().lockFrequency(rigSDRIF); - } else { - wxGetApp().unlockFrequency(); - } - } else { - wxGetApp().unlockFrequency(); - } + enableRig(); } else { - wxGetApp().stopRig(); - wxGetApp().unlockFrequency(); + disableRig(); } } @@ -1010,6 +1033,28 @@ void AppFrame::OnMenu(wxCommandEvent& event) { } } + if (event.GetId() == wxID_RIG_CONTROL) { + if (wxGetApp().rigIsActive()) { + RigThread *rt = wxGetApp().getRigThread(); + rt->setControlMode(!rt->getControlMode()); + rigControlMenuItem->Check(rt->getControlMode()); + wxGetApp().getConfig()->setRigControlMode(rt->getControlMode()); + } else { + wxGetApp().getConfig()->setRigControlMode(rigControlMenuItem->IsChecked()); + } + } + + if (event.GetId() == wxID_RIG_FOLLOW) { + if (wxGetApp().rigIsActive()) { + RigThread *rt = wxGetApp().getRigThread(); + rt->setFollowMode(!rt->getFollowMode()); + rigFollowMenuItem->Check(rt->getFollowMode()); + wxGetApp().getConfig()->setRigFollowMode(rt->getFollowMode()); + } else { + wxGetApp().getConfig()->setRigFollowMode(rigFollowMenuItem->IsChecked()); + } + } + if (wxGetApp().rigIsActive() && resetRig) { wxGetApp().stopRig(); wxGetApp().initRig(rigModel, rigPort, rigSerialRate); @@ -1034,9 +1079,12 @@ void AppFrame::OnClose(wxCloseEvent& event) { wxGetApp().getConfig()->setWaterfallLinesPerSec(waterfallDataThread->getLinesPerSecond()); wxGetApp().getConfig()->setManualDevices(SDREnumerator::getManuals()); #ifdef USE_HAMLIB + wxGetApp().getConfig()->setRigEnabled(rigEnableMenuItem->IsChecked()); wxGetApp().getConfig()->setRigModel(rigModel); wxGetApp().getConfig()->setRigRate(rigSerialRate); wxGetApp().getConfig()->setRigPort(rigPort); + wxGetApp().getConfig()->setRigFollowMode(rigFollowMenuItem->IsChecked()); + wxGetApp().getConfig()->setRigControlMode(rigControlMenuItem->IsChecked()); #endif wxGetApp().getConfig()->save(); event.Skip(); @@ -1348,6 +1396,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { if (rigEnableMenuItem->IsChecked()) { if (!wxGetApp().rigIsActive()) { rigEnableMenuItem->Check(false); + wxGetApp().getConfig()->setRigEnabled(false); } } #endif diff --git a/src/AppFrame.h b/src/AppFrame.h index ed957a3..a61562c 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -56,6 +56,8 @@ #define wxID_RIG_TOGGLE 11900 #define wxID_RIG_PORT 11901 #define wxID_RIG_SDR_IF 11902 +#define wxID_RIG_CONTROL 11903 +#define wxID_RIG_FOLLOW 11904 #define wxID_RIG_SERIAL_BASE 11950 #define wxID_RIG_MODEL_BASE 12000 #endif @@ -148,9 +150,14 @@ private: wxMenuItem *showTipMenuItem; #ifdef USE_HAMLIB + void enableRig(); + void disableRig(); + wxMenu *rigMenu; wxMenuItem *rigEnableMenuItem; wxMenuItem *rigPortMenuItem; + wxMenuItem *rigControlMenuItem; + wxMenuItem *rigFollowMenuItem; wxMenuItem *sdrIFMenuItem; std::map rigSerialMenuItems; std::map rigModelMenuItems; @@ -160,6 +167,7 @@ private: std::vector rigSerialRates; std::string rigPort; int numRigs; + bool rigInit; #endif wxDECLARE_EVENT_TABLE(); diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 2e25490..584b7ad 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -269,6 +269,13 @@ bool CubicSDR::OnInit() { } int CubicSDR::OnExit() { +#if USE_HAMLIB + if (rigIsActive()) { + std::cout << "Terminating Rig thread.." << std::endl; + stopRig(); + } +#endif + demodMgr.terminateAll(); std::cout << "Terminating SDR thread.." << std::endl; @@ -817,6 +824,9 @@ void CubicSDR::initRig(int rigModel, std::string rigPort, int rigSerialRate) { } rigThread = new RigThread(); rigThread->initRig(rigModel, rigPort, rigSerialRate); + rigThread->setControlMode(wxGetApp().getConfig()->getRigControlMode()); + rigThread->setFollowMode(wxGetApp().getConfig()->getRigFollowMode()); + t_Rig = new std::thread(&RigThread::threadMain, rigThread); } diff --git a/src/rig/RigThread.cpp b/src/rig/RigThread.cpp index bc21ac1..59cd8ca 100644 --- a/src/rig/RigThread.cpp +++ b/src/rig/RigThread.cpp @@ -8,6 +8,8 @@ RigThread::RigThread() { newFreq = freq; freqChanged.store(true); termStatus = 0; + controlMode.store(true); + followMode.store(true); } RigThread::~RigThread() { @@ -42,6 +44,7 @@ void RigThread::run() { int retcode, status; termStatus = 0; + terminated.store(false); std::cout << "Rig thread starting." << std::endl; @@ -66,9 +69,9 @@ void RigThread::run() { while (!terminated.load()) { std::this_thread::sleep_for(std::chrono::milliseconds(150)); - if (freqChanged.load()) { + if (freqChanged.load() && (controlMode.load() || setOneShot.load())) { status = rig_get_freq(rig, RIG_VFO_CURR, &freq); - if (status == 0) { + if (status == 0 && !terminated.load()) { if (freq != newFreq) { freq = newFreq; rig_set_freq(rig, RIG_VFO_CURR, freq); @@ -76,26 +79,27 @@ void RigThread::run() { } freqChanged.store(false); + setOneShot.store(false); } else { termStatus = 0; - terminate(); + break; } } else { freq_t checkFreq; status = rig_get_freq(rig, RIG_VFO_CURR, &checkFreq); - if (status == 0) { - if (checkFreq != freq) { + if (status == 0 && !terminated.load()) { + if (checkFreq != freq && followMode.load()) { freq = checkFreq; wxGetApp().setFrequency((long long)checkFreq); - } else if (wxGetApp().getFrequency() != freq) { + } else if (wxGetApp().getFrequency() != freq && controlMode.load()) { freq = wxGetApp().getFrequency(); rig_set_freq(rig, RIG_VFO_CURR, freq); } } else { termStatus = 0; - terminate(); + break; } } @@ -109,15 +113,31 @@ void RigThread::run() { }; freq_t RigThread::getFrequency() { - if (freqChanged.load()) { + if (freqChanged.load() && (setOneShot.load() || controlMode.load())) { return newFreq; } else { return freq; } } -void RigThread::setFrequency(freq_t new_freq) { +void RigThread::setFrequency(freq_t new_freq, bool oneShot) { newFreq = new_freq; freqChanged.store(true); + setOneShot.store(oneShot); } +void RigThread::setControlMode(bool cMode) { + controlMode.store(cMode); +} + +bool RigThread::getControlMode() { + return controlMode.load(); +} + +void RigThread::setFollowMode(bool fMode) { + followMode.store(fMode); +} + +bool RigThread::getFollowMode() { + return followMode.load(); +} diff --git a/src/rig/RigThread.h b/src/rig/RigThread.h index d161640..d7e3768 100644 --- a/src/rig/RigThread.h +++ b/src/rig/RigThread.h @@ -27,7 +27,12 @@ public: int terminationStatus(); freq_t getFrequency(); - void setFrequency(freq_t new_freq); + void setFrequency(freq_t new_freq, bool oneShot); + + void setControlMode(bool cMode); + bool getControlMode(); + void setFollowMode(bool fMode); + bool getFollowMode(); static RigList &enumerate(); static int add_hamlib_rig(const struct rig_caps *rc, void* f); @@ -40,6 +45,7 @@ private: int termStatus; freq_t freq; freq_t newFreq; - std::atomic_bool freqChanged; + std::atomic_bool freqChanged, setOneShot; + std::atomic_bool controlMode, followMode; static RigList rigCaps; }; \ No newline at end of file