diff --git a/src/AppConfig.cpp b/src/AppConfig.cpp index 09e1767..53e4e2d 100644 --- a/src/AppConfig.cpp +++ b/src/AppConfig.cpp @@ -392,6 +392,8 @@ bool AppConfig::save() { *rig_node->newChild("port") = rigPort; *rig_node->newChild("control") = rigControlMode.load()?1:0; *rig_node->newChild("follow") = rigFollowMode.load()?1:0; + *rig_node->newChild("center_lock") = rigCenterLock.load()?1:0; + *rig_node->newChild("follow_modem") = rigFollowModem.load()?1:0; #endif std::string cfgFileName = getConfigFileName(); @@ -560,6 +562,16 @@ bool AppConfig::load() { rig_node->getNext("follow")->element()->get(loadFollow); rigFollowMode.store(loadFollow?true:false); } + if (rig_node->hasAnother("center_lock")) { + int loadCenterLock; + rig_node->getNext("center_lock")->element()->get(loadCenterLock); + rigCenterLock.store(loadCenterLock?true:false); + } + if (rig_node->hasAnother("follow_modem")) { + int loadFollow; + rig_node->getNext("follow_modem")->element()->get(loadFollow); + rigFollowModem.store(loadFollow?true:false); + } } #endif @@ -615,6 +627,22 @@ bool AppConfig::getRigFollowMode() { return rigFollowMode.load(); } +void AppConfig::setRigCenterLock(bool cLock) { + rigCenterLock.store(cLock); +} + +bool AppConfig::getRigCenterLock() { + return rigCenterLock.load(); +} + +void AppConfig::setRigFollowModem(bool fMode) { + rigFollowModem.store(fMode); +} + +bool AppConfig::getRigFollowModem() { + return rigFollowModem.load(); +} + void AppConfig::setRigEnabled(bool enabled) { rigEnabled.store(enabled); } diff --git a/src/AppConfig.h b/src/AppConfig.h index c8ca860..dabadb1 100644 --- a/src/AppConfig.h +++ b/src/AppConfig.h @@ -106,6 +106,12 @@ public: void setRigFollowMode(bool fMode); bool getRigFollowMode(); + + void setRigCenterLock(bool cLock); + bool getRigCenterLock(); + + void setRigFollowModem(bool fMode); + bool getRigFollowModem(); void setRigEnabled(bool enabled); bool getRigEnabled(); @@ -131,6 +137,6 @@ private: #if USE_HAMLIB std::atomic_int rigModel, rigRate; std::string rigPort; - std::atomic_bool rigEnabled, rigFollowMode, rigControlMode; + std::atomic_bool rigEnabled, rigFollowMode, rigControlMode, rigCenterLock, rigFollowModem; #endif }; diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index cfd89cf..04344a4 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -461,6 +461,12 @@ AppFrame::AppFrame() : rigFollowMenuItem = rigMenu->AppendCheckItem(wxID_RIG_FOLLOW, wxT("Follow Rig")); rigFollowMenuItem->Check(wxGetApp().getConfig()->getRigFollowMode()); + rigCenterLockMenuItem = rigMenu->AppendCheckItem(wxID_RIG_CENTERLOCK, wxT("Floating Center")); + rigCenterLockMenuItem->Check(wxGetApp().getConfig()->getRigCenterLock()); + + rigFollowModemMenuItem = rigMenu->AppendCheckItem(wxID_RIG_FOLLOW_MODEM, wxT("Track Modem")); + rigFollowModemMenuItem->Check(wxGetApp().getConfig()->getRigFollowModem()); + wxMenu *rigModelMenu = new wxMenu; RigList &rl = RigThread::enumerate(); numRigs = rl.size(); @@ -1082,6 +1088,28 @@ void AppFrame::OnMenu(wxCommandEvent& event) { } } + if (event.GetId() == wxID_RIG_CENTERLOCK) { + if (wxGetApp().rigIsActive()) { + RigThread *rt = wxGetApp().getRigThread(); + rt->setCenterLock(!rt->getCenterLock()); + rigCenterLockMenuItem->Check(rt->getCenterLock()); + wxGetApp().getConfig()->setRigCenterLock(rt->getCenterLock()); + } else { + wxGetApp().getConfig()->setRigCenterLock(rigCenterLockMenuItem->IsChecked()); + } + } + + if (event.GetId() == wxID_RIG_FOLLOW_MODEM) { + if (wxGetApp().rigIsActive()) { + RigThread *rt = wxGetApp().getRigThread(); + rt->setFollowModem(!rt->getFollowModem()); + rigFollowModemMenuItem->Check(rt->getFollowModem()); + wxGetApp().getConfig()->setRigFollowModem(rt->getFollowModem()); + } else { + wxGetApp().getConfig()->setRigFollowModem(rigFollowModemMenuItem->IsChecked()); + } + } + if (wxGetApp().rigIsActive() && resetRig) { wxGetApp().stopRig(); wxGetApp().initRig(rigModel, rigPort, rigSerialRate); @@ -1112,6 +1140,8 @@ void AppFrame::OnClose(wxCloseEvent& event) { wxGetApp().getConfig()->setRigPort(rigPort); wxGetApp().getConfig()->setRigFollowMode(rigFollowMenuItem->IsChecked()); wxGetApp().getConfig()->setRigControlMode(rigControlMenuItem->IsChecked()); + wxGetApp().getConfig()->setRigCenterLock(rigCenterLockMenuItem->IsChecked()); + wxGetApp().getConfig()->setRigFollowModem(rigFollowModemMenuItem->IsChecked()); #endif wxGetApp().getConfig()->save(); event.Skip(); @@ -1774,12 +1804,14 @@ int AppFrame::OnGlobalKeyDown(wxKeyEvent &event) { case ']': if (lastDemod) { lastDemod->setFrequency(lastDemod->getFrequency()+snap); + lastDemod->updateLabel(lastDemod->getFrequency()); } return 1; break; case '[': if (lastDemod) { lastDemod->setFrequency(lastDemod->getFrequency()-snap); + lastDemod->updateLabel(lastDemod->getFrequency()); } return 1; break; diff --git a/src/AppFrame.h b/src/AppFrame.h index 977817e..2e06889 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -59,6 +59,8 @@ #define wxID_RIG_SDR_IF 11902 #define wxID_RIG_CONTROL 11903 #define wxID_RIG_FOLLOW 11904 +#define wxID_RIG_CENTERLOCK 11905 +#define wxID_RIG_FOLLOW_MODEM 11906 #define wxID_RIG_SERIAL_BASE 11950 #define wxID_RIG_MODEL_BASE 12000 #endif @@ -159,6 +161,8 @@ private: wxMenuItem *rigPortMenuItem; wxMenuItem *rigControlMenuItem; wxMenuItem *rigFollowMenuItem; + wxMenuItem *rigCenterLockMenuItem; + wxMenuItem *rigFollowModemMenuItem; wxMenuItem *sdrIFMenuItem; std::map rigSerialMenuItems; std::map rigModelMenuItems; diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index ee38442..0d877af 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -838,6 +838,8 @@ void CubicSDR::initRig(int rigModel, std::string rigPort, int rigSerialRate) { rigThread->initRig(rigModel, rigPort, rigSerialRate); rigThread->setControlMode(wxGetApp().getConfig()->getRigControlMode()); rigThread->setFollowMode(wxGetApp().getConfig()->getRigFollowMode()); + rigThread->setCenterLock(wxGetApp().getConfig()->getRigCenterLock()); + rigThread->setFollowModem(wxGetApp().getConfig()->getRigFollowModem()); t_Rig = new std::thread(&RigThread::threadMain, rigThread); } diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index e3565d8..4f145b8 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -1,6 +1,10 @@ #include "DemodulatorInstance.h" #include "CubicSDR.h" +#if USE_HAMLIB +#include "RigThread.h" +#endif + DemodulatorInstance::DemodulatorInstance() : t_PreDemod(nullptr), t_Demod(nullptr), t_Audio(nullptr) { @@ -329,6 +333,11 @@ void DemodulatorInstance::setFrequency(long long freq) { } } #endif +#if USE_HAMLIB + if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && wxGetApp().getDemodMgr().getLastActiveDemodulator() == this) { + wxGetApp().getRigThread()->setFrequency(freq,true); + } +#endif } long long DemodulatorInstance::getFrequency() { diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index ea8af51..8f80829 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -6,6 +6,10 @@ #include #include +#if USE_HAMLIB +#include "RigThread.h" +#endif + bool demodFreqCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->getFrequency()getFrequency()); } bool inactiveCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->isActive()isActive()); } @@ -179,6 +183,11 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo lastActiveDemodulator = demod; } updateLastState(); +#if USE_HAMLIB + if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && lastActiveDemodulator) { + wxGetApp().getRigThread()->setFrequency(lastActiveDemodulator->getFrequency(),true); + } +#endif } if (activeVisualDemodulator) { diff --git a/src/rig/RigThread.cpp b/src/rig/RigThread.cpp index 59cd8ca..ffd1d2d 100644 --- a/src/rig/RigThread.cpp +++ b/src/rig/RigThread.cpp @@ -10,6 +10,8 @@ RigThread::RigThread() { termStatus = 0; controlMode.store(true); followMode.store(true); + centerLock.store(false); + followModem.store(false); } RigThread::~RigThread() { @@ -69,10 +71,15 @@ void RigThread::run() { while (!terminated.load()) { std::this_thread::sleep_for(std::chrono::milliseconds(150)); + + DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); + DemodulatorInstance *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + if (freqChanged.load() && (controlMode.load() || setOneShot.load())) { status = rig_get_freq(rig, RIG_VFO_CURR, &freq); if (status == 0 && !terminated.load()) { - if (freq != newFreq) { + + if (freq != newFreq && setOneShot.load()) { freq = newFreq; rig_set_freq(rig, RIG_VFO_CURR, freq); // std::cout << "Set Rig Freq: %f" << newFreq << std::endl; @@ -86,16 +93,32 @@ void RigThread::run() { } } else { freq_t checkFreq; - - status = rig_get_freq(rig, RIG_VFO_CURR, &checkFreq); + status = rig_get_freq(rig, RIG_VFO_CURR, &checkFreq); + if (status == 0 && !terminated.load()) { if (checkFreq != freq && followMode.load()) { freq = checkFreq; - wxGetApp().setFrequency((long long)checkFreq); - } else if (wxGetApp().getFrequency() != freq && controlMode.load()) { + if (followModem.load()) { + if (lastDemod) { + lastDemod->setFrequency(freq); + lastDemod->updateLabel(freq); + lastDemod->setFollow(true); + } + } else { + wxGetApp().setFrequency((long long)checkFreq); + } + } else if (wxGetApp().getFrequency() != freq && controlMode.load() && !centerLock.load() && !followModem.load()) { freq = wxGetApp().getFrequency(); rig_set_freq(rig, RIG_VFO_CURR, freq); + } else if (followModem.load()) { + if (lastDemod) { + if (lastDemod->getFrequency() != freq) { + lastDemod->setFrequency(freq); + lastDemod->updateLabel(freq); + lastDemod->setFollow(true); + } + } } } else { termStatus = 0; @@ -103,6 +126,10 @@ void RigThread::run() { } } + if (!centerLock.load() && followModem.load() && wxGetApp().getFrequency() != freq && (lastDemod && lastDemod != activeDemod)) { + wxGetApp().setFrequency((long long)freq); + } + // std::cout << "Rig Freq: " << freq << std::endl; } @@ -141,3 +168,19 @@ void RigThread::setFollowMode(bool fMode) { bool RigThread::getFollowMode() { return followMode.load(); } + +void RigThread::setCenterLock(bool cLock) { + centerLock.store(cLock); +} + +bool RigThread::getCenterLock() { + return centerLock.load(); +} + +void RigThread::setFollowModem(bool mFollow) { + followModem.store(mFollow); +} + +bool RigThread::getFollowModem() { + return followModem.load(); +} diff --git a/src/rig/RigThread.h b/src/rig/RigThread.h index d7e3768..386e17b 100644 --- a/src/rig/RigThread.h +++ b/src/rig/RigThread.h @@ -31,9 +31,16 @@ public: void setControlMode(bool cMode); bool getControlMode(); + void setFollowMode(bool fMode); bool getFollowMode(); + + void setCenterLock(bool cLock); + bool getCenterLock(); + void setFollowModem(bool mFollow); + bool getFollowModem(); + static RigList &enumerate(); static int add_hamlib_rig(const struct rig_caps *rc, void* f); @@ -46,6 +53,6 @@ private: freq_t freq; freq_t newFreq; std::atomic_bool freqChanged, setOneShot; - std::atomic_bool controlMode, followMode; + std::atomic_bool controlMode, followMode, centerLock, followModem; static RigList rigCaps; }; \ No newline at end of file diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 09ef9e5..3904bc4 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -454,9 +454,9 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { wxGetApp().setFrequency(freq); } #ifdef USE_HAMLIB - if (wxGetApp().rigIsActive() && !wxGetApp().getRigThread()->getControlMode()) { - wxGetApp().getRigThread()->setFrequency(wxGetApp().getFrequency(),true); - } + if (wxGetApp().rigIsActive() && (!wxGetApp().getRigThread()->getControlMode() || wxGetApp().getRigThread()->getCenterLock())) { + wxGetApp().getRigThread()->setFrequency(wxGetApp().getFrequency(),true); + } #endif break; default: