diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index aa11a4f..a1822bd 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -18,8 +18,6 @@ #include "CoreFoundation/CoreFoundation.h" #endif -#include - IMPLEMENT_APP(CubicSDR) CubicSDR::CubicSDR() : appframe(NULL), m_glContext(NULL), frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE), directSamplingMode(0), @@ -51,6 +49,8 @@ bool CubicSDR::OnInit() { offset = 0; ppm = 0; directSamplingMode = 0; + devicesReady.store(false); + deviceSelectorOpen.store(false); // Visual Data spectrumVisualThread = new SpectrumVisualDataThread(); @@ -99,21 +99,24 @@ bool CubicSDR::OnInit() { t_DemodVisual = new std::thread(&SpectrumVisualDataThread::threadMain, demodVisualThread); // t_SDR = new std::thread(&SDRThread::threadMain, sdrThread); - sdrEnum = new SDREnumerator(); - t_SDREnum = new std::thread(&SDREnumerator::threadMain, sdrEnum); - + appframe = new AppFrame(); + deviceSelectorOpen.store(true); + deviceSelectorDialog = new SDRDevicesDialog(appframe); + deviceSelectorDialog->Show(); -#ifdef __APPLE__ - int main_policy; - struct sched_param main_param; + t_SDREnum = new std::thread(&SDREnumerator::threadMain, sdrEnum); - main_policy = SCHED_RR; - main_param.sched_priority = sched_get_priority_min(SCHED_RR)+2; - - pthread_setschedparam(pthread_self(), main_policy, &main_param); -#endif +//#ifdef __APPLE__ +// int main_policy; +// struct sched_param main_param; +// +// main_policy = SCHED_RR; +// main_param.sched_priority = sched_get_priority_min(SCHED_RR)+2; +// +// pthread_setschedparam(pthread_self(), main_policy, &main_param); +//#endif return true; } @@ -191,36 +194,61 @@ bool CubicSDR::OnCmdLineParsed(wxCmdLineParser& parser) { } void CubicSDR::deviceSelector() { - if (sdrEnum->isTerminated()) { - devs = SDREnumerator::enumerate_devices(); - SDRDevicesDialog *dlg = new SDRDevicesDialog(appframe); - dlg->Show(); + if (deviceSelectorOpen) { + deviceSelectorDialog->Raise(); + deviceSelectorDialog->SetFocus(); + return; } + deviceSelectorOpen = true; + deviceSelectorDialog = new SDRDevicesDialog(appframe); + deviceSelectorDialog->Show(); +} + +void CubicSDR::addRemote(std::string remoteAddr) { + SDREnumerator::addRemote(remoteAddr); + devicesReady.store(false); + t_SDREnum = new std::thread(&SDREnumerator::threadMain, sdrEnum); +} + +void CubicSDR::removeRemote(std::string remoteAddr) { + SDREnumerator::removeRemote(remoteAddr); } void CubicSDR::sdrThreadNotify(SDRThread::SDRThreadState state, std::string message) { + notify_busy.lock(); + if (state == SDRThread::SDR_THREAD_MESSAGE) { + notifyMessage = message; + } if (state == SDRThread::SDR_THREAD_TERMINATED) { t_SDR->join(); delete t_SDR; } if (state == SDRThread::SDR_THREAD_FAILED) { - wxMessageDialog *info; - info = new wxMessageDialog(NULL, message, wxT("Error initializing device"), wxOK | wxICON_ERROR); - info->ShowModal(); + notifyMessage = message; +// wxMessageDialog *info; +// info = new wxMessageDialog(NULL, message, wxT("Error initializing device"), wxOK | wxICON_ERROR); +// info->ShowModal(); } + appframe->SetStatusText(message); + notify_busy.unlock(); } void CubicSDR::sdrEnumThreadNotify(SDREnumerator::SDREnumState state, std::string message) { + notify_busy.lock(); + if (state == SDREnumerator::SDR_ENUM_MESSAGE) { + notifyMessage = message; + } if (state == SDREnumerator::SDR_ENUM_DEVICES_READY) { - deviceSelector(); + devs = SDREnumerator::enumerate_devices("", true); + devicesReady.store(true); } if (state == SDREnumerator::SDR_ENUM_FAILED) { + notifyMessage = message; sdrEnum->terminate(); - wxMessageDialog *info; - info = new wxMessageDialog(NULL, message, wxT("Error enumerating devices"), wxOK | wxICON_ERROR); - info->ShowModal(); } + appframe->SetStatusText(message); + notify_busy.unlock(); } @@ -296,11 +324,13 @@ void CubicSDR::setDevice(SDRDeviceInfo *dev) { freqHigh = chan->getRFRange().getHigh(); freqLow = chan->getRFRange().getLow(); - if (frequency > freqHigh) { - frequency = freqHigh; - } else if (frequency < freqLow) { - frequency = freqLow; - } +// upconverter settings don't like this, need to handle elsewhere.. +// if (frequency > freqHigh) { +// frequency = freqHigh; +// } +// else if (frequency < freqLow) { +// frequency = freqLow; +// } int rateHigh, rateLow; rateLow = chan->getSampleRates()[0]; @@ -344,7 +374,7 @@ SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcessor() { return demodVisualThread->getProcessor(); } -VisualDataReDistributor *CubicSDR::getSpectrumDistributor() { +VisualDataDistributor *CubicSDR::getSpectrumDistributor() { return &spectrumDistributor; } @@ -394,8 +424,7 @@ AppConfig *CubicSDR::getConfig() { } void CubicSDR::saveConfig() { -#warning Configuration Save Disabled -// config.save(); + config.save(); } void CubicSDR::setPPM(int ppm_in) { @@ -453,3 +482,23 @@ void CubicSDR::setFrequencySnap(int snap) { int CubicSDR::getFrequencySnap() { return snap; } + +bool CubicSDR::areDevicesReady() { + return devicesReady.load(); +} + +bool CubicSDR::areDevicesEnumerating() { + return !sdrEnum->isTerminated(); +} + +std::string CubicSDR::getNotification() { + std::string msg; + notify_busy.lock(); + msg = notifyMessage; + notify_busy.unlock(); + return msg; +} + +void CubicSDR::setDeviceSelectorClosed() { + deviceSelectorOpen.store(false); +} diff --git a/src/CubicSDR.h b/src/CubicSDR.h index d234af6..c942dbf 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -26,6 +26,7 @@ #include "ScopeVisualProcessor.h" #include "SpectrumVisualProcessor.h" #include "SpectrumVisualDataThread.h" +#include "SDRDevices.h" #include @@ -69,7 +70,7 @@ public: ScopeVisualProcessor *getScopeProcessor(); SpectrumVisualProcessor *getSpectrumProcessor(); SpectrumVisualProcessor *getDemodSpectrumProcessor(); - VisualDataReDistributor *getSpectrumDistributor(); + VisualDataDistributor *getSpectrumDistributor(); DemodulatorThreadOutputQueue* getAudioVisualQueue(); DemodulatorThreadInputQueue* getIQVisualQueue(); @@ -91,6 +92,15 @@ public: void showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetMode = FrequencyDialog::FDIALOG_TARGET_DEFAULT); AppFrame *getAppFrame(); + bool areDevicesReady(); + bool areDevicesEnumerating(); + std::string getNotification(); + + void addRemote(std::string remoteAddr); + void removeRemote(std::string remoteAddr); + + void setDeviceSelectorClosed(); + private: AppFrame *appframe; AppConfig config; @@ -121,9 +131,15 @@ private: ScopeVisualProcessor scopeProcessor; - VisualDataReDistributor spectrumDistributor; + VisualDataDistributor spectrumDistributor; + + SDRDevicesDialog *deviceSelectorDialog; std::thread *t_SDR, *t_SDREnum, *t_PostSDR, *t_SpectrumVisual, *t_DemodVisual; + std::atomic_bool devicesReady; + std::atomic_bool deviceSelectorOpen; + std::string notifyMessage; + std::mutex notify_busy; }; static const wxCmdLineEntryDesc commandLineInfo [] = diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index bb58265..7eed3fe 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -1,19 +1,21 @@ #include "SDRDevices.h" + +#include +#include + #include "CubicSDR.h" SDRDevicesDialog::SDRDevicesDialog( wxWindow* parent ): devFrame( parent ) { - wxTreeItemId devRoot = devTree->AddRoot("Devices"); - wxTreeItemId localBranch = devTree->AppendItem(devRoot, "Local"); - wxTreeItemId remoteBranch = devTree->AppendItem(devRoot, "Remote"); - - devs = SDREnumerator::enumerate_devices(); - for (devs_i = devs->begin(); devs_i != devs->end(); devs_i++) { - devItems[devTree->AppendItem(localBranch, (*devs_i)->getName())] = (*devs_i); - } - - devTree->ExpandAll(); + refresh = true; + m_addRemoteButton->Disable(); + m_useSelectedButton->Disable(); + m_deviceTimer.Start(250); } +void SDRDevicesDialog::OnClose( wxCloseEvent& event ) { + wxGetApp().setDeviceSelectorClosed(); + Destroy(); +} void SDRDevicesDialog::OnDeleteItem( wxTreeEvent& event ) { event.Skip(); @@ -24,7 +26,24 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { } void SDRDevicesDialog::OnAddRemote( wxMouseEvent& event ) { - event.Skip(); + if (!SDREnumerator::hasRemoteModule()) { + wxMessageDialog *info; + info = new wxMessageDialog(NULL, wxT("Install SoapyRemote module to add remote servers.\n\nhttps://github.com/pothosware/SoapyRemote"), wxT("SoapyRemote not found."), wxOK | wxICON_ERROR); + info->ShowModal(); + return; + } + + wxString remoteAddr = + wxGetTextFromUser("Remote Address (address[:port])\n\ni.e. 'raspberrypi.local', '192.168.1.103:1234'\n","SoapySDR Remote Address", "", this); + + if (!remoteAddr.Trim().empty()) { + wxGetApp().addRemote(remoteAddr.Trim().ToStdString()); + } + devTree->Disable(); + m_addRemoteButton->Disable(); + m_useSelectedButton->Disable(); + refresh = true; + } void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event ) { @@ -38,3 +57,58 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event ) { } } +void SDRDevicesDialog::OnTreeDoubleClick( wxMouseEvent& event ) { + OnUseSelected(event); +} + +void SDRDevicesDialog::OnDeviceTimer( wxTimerEvent& event ) { + if (refresh) { + if (wxGetApp().areDevicesEnumerating() || !wxGetApp().areDevicesReady()) { + std::string msg = wxGetApp().getNotification(); + devStatusBar->SetStatusText(msg); + devTree->DeleteAllItems(); + devTree->AddRoot(msg); + event.Skip(); + return; + } + + devTree->DeleteAllItems(); + + wxTreeItemId devRoot = devTree->AddRoot("Devices"); + wxTreeItemId localBranch = devTree->AppendItem(devRoot, "Local"); + wxTreeItemId remoteBranch = devTree->AppendItem(devRoot, "Remote"); + + devs[""] = SDREnumerator::enumerate_devices("",true); + if (devs[""] != NULL) { + for (devs_i = devs[""]->begin(); devs_i != devs[""]->end(); devs_i++) { + devItems[devTree->AppendItem(localBranch, (*devs_i)->getName())] = (*devs_i); + } + } + + std::vector remotes = SDREnumerator::getRemotes(); + std::vector::iterator remotes_i; + std::vector::iterator remoteDevs_i; + + if (remotes.size()) { + for (remotes_i = remotes.begin(); remotes_i != remotes.end(); remotes_i++) { + devs[*remotes_i] = SDREnumerator::enumerate_devices(*remotes_i, true); + wxTreeItemId remoteNode = devTree->AppendItem(remoteBranch, *remotes_i); + + if (devs[*remotes_i] != NULL) { + for (remoteDevs_i = devs[*remotes_i]->begin(); remoteDevs_i != devs[*remotes_i]->end(); remoteDevs_i++) { + devItems[devTree->AppendItem(remoteNode, (*remoteDevs_i)->getName())] = (*remoteDevs_i); + } + } + } + } + + m_addRemoteButton->Enable(); + m_useSelectedButton->Enable(); + devTree->Enable(); + devTree->ExpandAll(); + + devStatusBar->SetStatusText("Ready."); + + refresh = false; + } +} \ No newline at end of file diff --git a/src/forms/SDRDevices/SDRDevices.fbp b/src/forms/SDRDevices/SDRDevices.fbp index 3a693d9..362fade 100644 --- a/src/forms/SDRDevices/SDRDevices.fbp +++ b/src/forms/SDRDevices/SDRDevices.fbp @@ -44,7 +44,7 @@ devFrame - 692,467 + 392,467 wxDEFAULT_FRAME_STYLE CubicSDR :: SDR Devices @@ -62,7 +62,7 @@ - + OnClose @@ -307,7 +307,7 @@ none 5 - wxEXPAND + wxEXPAND|wxALIGN_RIGHT 1 1 @@ -330,7 +330,7 @@ Dock 0 Left - 1 + 0 1 @@ -368,7 +368,7 @@ - + OnTreeDoubleClick @@ -703,7 +703,7 @@ 0 0 - 0 + 1 wxID_ANY 0 @@ -1142,6 +1142,15 @@ + + 0 + wxID_ANY + m_deviceTimer + 0 + 5000 + protected + OnDeviceTimer + diff --git a/src/forms/SDRDevices/SDRDevices.h b/src/forms/SDRDevices/SDRDevices.h index f823114..ccd8a77 100644 --- a/src/forms/SDRDevices/SDRDevices.h +++ b/src/forms/SDRDevices/SDRDevices.h @@ -1,5 +1,7 @@ #pragma once +#include +#include #include "SDRDevices.h" #include "SDRDevicesForm.h" @@ -10,13 +12,17 @@ class SDRDevicesDialog: public devFrame { public: SDRDevicesDialog( wxWindow* parent ); + void OnClose( wxCloseEvent& event ); void OnDeleteItem( wxTreeEvent& event ); void OnSelectionChanged( wxTreeEvent& event ); void OnAddRemote( wxMouseEvent& event ); void OnUseSelected( wxMouseEvent& event ); - + void OnTreeDoubleClick( wxMouseEvent& event ); + void OnDeviceTimer( wxTimerEvent& event ); + private: - std::vector *devs; + bool refresh; + std::map* > devs; std::vector::iterator devs_i; std::map devItems; std::map::iterator devItems_i; diff --git a/src/forms/SDRDevices/SDRDevicesForm.cpp b/src/forms/SDRDevices/SDRDevicesForm.cpp index 2ca6e05..3e1a813 100644 --- a/src/forms/SDRDevices/SDRDevicesForm.cpp +++ b/src/forms/SDRDevices/SDRDevicesForm.cpp @@ -26,7 +26,9 @@ devFrame::devFrame( wxWindow* parent, wxWindowID id, const wxString& title, cons bSizer6 = new wxBoxSizer( wxVERTICAL ); devTree = new wxTreeCtrl( m_panel6, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_DEFAULT_STYLE ); - bSizer6->Add( devTree, 1, wxEXPAND, 5 ); + devTree->Enable( false ); + + bSizer6->Add( devTree, 1, wxEXPAND|wxALIGN_RIGHT, 5 ); m_panel4 = new wxPanel( m_panel6, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizer5; @@ -51,6 +53,8 @@ devFrame::devFrame( wxWindow* parent, wxWindowID id, const wxString& title, cons bSizer4->Add( m_panel6, 1, wxEXPAND | wxALL, 5 ); devTabs = new wxNotebook( m_panel3, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + devTabs->Hide(); + devInfoPanel = new wxPanel( devTabs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* devInfoSizer; devInfoSizer = new wxBoxSizer( wxVERTICAL ); @@ -87,22 +91,29 @@ devFrame::devFrame( wxWindow* parent, wxWindowID id, const wxString& title, cons this->SetSizer( devFrameSizer ); this->Layout(); + m_deviceTimer.SetOwner( this, wxID_ANY ); this->Centre( wxBOTH ); // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( devFrame::OnClose ) ); + devTree->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( devFrame::OnTreeDoubleClick ), NULL, this ); devTree->Connect( wxEVT_COMMAND_TREE_DELETE_ITEM, wxTreeEventHandler( devFrame::OnDeleteItem ), NULL, this ); devTree->Connect( wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( devFrame::OnSelectionChanged ), NULL, this ); m_addRemoteButton->Connect( wxEVT_LEFT_UP, wxMouseEventHandler( devFrame::OnAddRemote ), NULL, this ); m_useSelectedButton->Connect( wxEVT_LEFT_UP, wxMouseEventHandler( devFrame::OnUseSelected ), NULL, this ); + this->Connect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( devFrame::OnDeviceTimer ) ); } devFrame::~devFrame() { // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( devFrame::OnClose ) ); + devTree->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( devFrame::OnTreeDoubleClick ), NULL, this ); devTree->Disconnect( wxEVT_COMMAND_TREE_DELETE_ITEM, wxTreeEventHandler( devFrame::OnDeleteItem ), NULL, this ); devTree->Disconnect( wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( devFrame::OnSelectionChanged ), NULL, this ); m_addRemoteButton->Disconnect( wxEVT_LEFT_UP, wxMouseEventHandler( devFrame::OnAddRemote ), NULL, this ); m_useSelectedButton->Disconnect( wxEVT_LEFT_UP, wxMouseEventHandler( devFrame::OnUseSelected ), NULL, this ); + this->Disconnect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( devFrame::OnDeviceTimer ) ); } diff --git a/src/forms/SDRDevices/SDRDevicesForm.h b/src/forms/SDRDevices/SDRDevicesForm.h index 8795ae9..2857d5c 100644 --- a/src/forms/SDRDevices/SDRDevicesForm.h +++ b/src/forms/SDRDevices/SDRDevicesForm.h @@ -25,6 +25,7 @@ #include #include #include +#include #include /////////////////////////////////////////////////////////////////////////// @@ -50,17 +51,21 @@ class devFrame : public wxFrame wxListCtrl* m_DevInfoList; wxPanel* devParamsPanel; wxListCtrl* m_ParamInfoList; + wxTimer m_deviceTimer; // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } + virtual void OnTreeDoubleClick( wxMouseEvent& event ) { event.Skip(); } virtual void OnDeleteItem( wxTreeEvent& event ) { event.Skip(); } virtual void OnSelectionChanged( wxTreeEvent& event ) { event.Skip(); } virtual void OnAddRemote( wxMouseEvent& event ) { event.Skip(); } virtual void OnUseSelected( wxMouseEvent& event ) { event.Skip(); } + virtual void OnDeviceTimer( wxTimerEvent& event ) { event.Skip(); } public: - devFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("CubicSDR :: SDR Devices"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 692,467 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); + devFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("CubicSDR :: SDR Devices"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 392,467 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); ~devFrame(); diff --git a/src/sdr/SDRDeviceInfo.cpp b/src/sdr/SDRDeviceInfo.cpp index d6e16e5..255a564 100644 --- a/src/sdr/SDRDeviceInfo.cpp +++ b/src/sdr/SDRDeviceInfo.cpp @@ -24,7 +24,8 @@ void SDRDeviceRange::setHigh(double high) { } SDRDeviceChannel::SDRDeviceChannel() { - + hardwareDC = false; + hasCorr = false; } SDRDeviceChannel::~SDRDeviceChannel() { @@ -87,9 +88,26 @@ std::vector &SDRDeviceChannel::getFilterBandwidths() { return filterBandwidths; } +const bool& SDRDeviceChannel::hasHardwareDC() const { + return hardwareDC; +} + +void SDRDeviceChannel::setHardwareDC(const bool& hardware) { + hardwareDC = hardware; +} -SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false), hardwareDC(false) { + +const bool& SDRDeviceChannel::hasCORR() const { + return hardwareDC; +} + +void SDRDeviceChannel::setCORR(const bool& hardware) { + hardwareDC = hardware; +} + + +SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false) { } @@ -175,15 +193,6 @@ void SDRDeviceInfo::setHardware(const std::string& hardware) { this->hardware = hardware; } -const bool& SDRDeviceInfo::hasHardwareDC() const { - return hardwareDC; -} - -void SDRDeviceInfo::setHardwareDC(const bool& hardware) { - hardwareDC = hardware; -} - - bool SDRDeviceInfo::hasTimestamps() const { return timestamps; } diff --git a/src/sdr/SDRDeviceInfo.h b/src/sdr/SDRDeviceInfo.h index 7ebbcf5..638e3ee 100644 --- a/src/sdr/SDRDeviceInfo.h +++ b/src/sdr/SDRDeviceInfo.h @@ -71,9 +71,16 @@ public: std::vector &getSampleRates(); std::vector &getFilterBandwidths(); + const bool& hasHardwareDC() const; + void setHardwareDC(const bool& hardware); + + const bool& hasCORR() const; + void setCORR(const bool& corr); + + private: int channel; - bool fullDuplex, tx, rx; + bool fullDuplex, tx, rx, hardwareDC, hasCorr; SDRDeviceRange rangeGain, rangeLNA, rangeFull, rangeRF; std::vector sampleRates; std::vector filterBandwidths; @@ -113,9 +120,6 @@ public: const std::string& getHardware() const; void setHardware(const std::string& hardware); - const bool& hasHardwareDC() const; - void setHardwareDC(const bool& hardware); - bool hasTimestamps() const; void setTimestamps(bool timestamps); @@ -134,7 +138,7 @@ private: int index; std::string name, serial, product, manufacturer, tuner; std::string driver, hardware; - bool timestamps, available, hardwareDC; + bool timestamps, available; SoapySDR::Kwargs deviceArgs, streamArgs; std::vector channels; diff --git a/src/sdr/SDREnumerator.cpp b/src/sdr/SDREnumerator.cpp index fb72711..40db869 100644 --- a/src/sdr/SDREnumerator.cpp +++ b/src/sdr/SDREnumerator.cpp @@ -7,8 +7,10 @@ std::vector SDREnumerator::factories; std::vector SDREnumerator::modules; -std::vector SDREnumerator::devs; - +std::vector SDREnumerator::remotes; +std::map< std::string, std::vector > SDREnumerator::devs; +bool SDREnumerator::soapy_initialized = false; +bool SDREnumerator::has_remote = false; SDREnumerator::SDREnumerator() : IOThread() { @@ -19,48 +21,73 @@ SDREnumerator::~SDREnumerator() { } -std::vector *SDREnumerator::enumerate_devices() { +std::vector *SDREnumerator::enumerate_devices(std::string remoteAddr, bool noInit) { - if (SDREnumerator::devs.size()) { - return &SDREnumerator::devs; + if (SDREnumerator::devs[remoteAddr].size()) { + return &SDREnumerator::devs[remoteAddr]; } - std::cout << "SoapySDR init.." << std::endl; - std::cout << "\tAPI Version: v" << SoapySDR::getAPIVersion() << std::endl; - std::cout << "\tABI Version: v" << SoapySDR::getABIVersion() << std::endl; - std::cout << "\tInstall root: " << SoapySDR::getRootPath() << std::endl; + if (noInit) { + return NULL; + } + + if (!soapy_initialized) { + std::cout << "SoapySDR init.." << std::endl; + std::cout << "\tAPI Version: v" << SoapySDR::getAPIVersion() << std::endl; + std::cout << "\tABI Version: v" << SoapySDR::getABIVersion() << std::endl; + std::cout << "\tInstall root: " << SoapySDR::getRootPath() << std::endl; - modules = SoapySDR::listModules(); - for (size_t i = 0; i < modules.size(); i++) { - std::cout << "\tModule found: " << modules[i] << std::endl; - } - if (modules.empty()) { - std::cout << "No modules found!" << std::endl; - } - - std::cout << "\tLoading modules... " << std::flush; - SoapySDR::loadModules(); - std::cout << "done" << std::endl; - - if (SDREnumerator::factories.size()) { - SDREnumerator::factories.erase(SDREnumerator::factories.begin(), SDREnumerator::factories.end()); - } - - std::cout << "\tAvailable factories..."; - SoapySDR::FindFunctions factories = SoapySDR::Registry::listFindFunctions(); - for (SoapySDR::FindFunctions::const_iterator it = factories.begin(); it != factories.end(); ++it) { - if (it != factories.begin()) { - std::cout << ", "; + modules = SoapySDR::listModules(); + for (size_t i = 0; i < modules.size(); i++) { + std::cout << "\tModule found: " << modules[i] << std::endl; } - std::cout << it->first; - SDREnumerator::factories.push_back(it->first); + if (modules.empty()) { + std::cout << "No modules found!" << std::endl; + } + + std::cout << "\tLoading modules... " << std::flush; + SoapySDR::loadModules(); + std::cout << "done" << std::endl; + + if (SDREnumerator::factories.size()) { + SDREnumerator::factories.erase(SDREnumerator::factories.begin(), SDREnumerator::factories.end()); + } + + std::cout << "\tAvailable factories..."; + SoapySDR::FindFunctions factories = SoapySDR::Registry::listFindFunctions(); + for (SoapySDR::FindFunctions::const_iterator it = factories.begin(); it != factories.end(); ++it) { + if (it != factories.begin()) { + std::cout << ", "; + } + std::cout << it->first; + + if (it->first == "remote") { + has_remote = true; + } + SDREnumerator::factories.push_back(it->first); + } + if (factories.empty()) { + std::cout << "No factories found!" << std::endl; + } + std::cout << std::endl; + soapy_initialized = true; } - if (factories.empty()) { - std::cout << "No factories found!" << std::endl; + + std::vector results; + SoapySDR::Kwargs enumArgs; + bool isRemote = false; + + if (remoteAddr.length()) { + std::cout << "Enumerating remote address: " << remoteAddr << std::endl; + enumArgs["driver"] = "remote"; + enumArgs["remote"] = remoteAddr; + isRemote = true; + + results = SoapySDR::Device::enumerate(enumArgs); + } else { + results = SoapySDR::Device::enumerate(); } - std::cout << std::endl; - - std::vector results = SoapySDR::Device::enumerate(); + // Remote driver test.. /* * / @@ -85,11 +112,34 @@ std::vector *SDREnumerator::enumerate_devices() { SDRThread::devs.push_back(remoteDev); // */ - + if (isRemote) { + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Opening remote server ") + remoteAddr + ".."); + } for (size_t i = 0; i < results.size(); i++) { - std::cout << "Found device " << i << std::endl; +// std::cout << "Found device " << i << std::endl; SDRDeviceInfo *dev = new SDRDeviceInfo(); - for (SoapySDR::Kwargs::const_iterator it = results[i].begin(); it != results[i].end(); ++it) { + + SoapySDR::Kwargs deviceArgs = results[i]; + SoapySDR::Kwargs streamArgs; + + if (isRemote) { + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Querying remote " + remoteAddr + " device #" + std::to_string(i)); + deviceArgs["remote"] = remoteAddr; + if (deviceArgs.count("rtl") != 0) { + streamArgs["remote:mtu"] = "8192"; + streamArgs["remote:format"] = "CS8"; + streamArgs["remote:window"] = "16384000"; + } + } else { + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Found local device #") + std::to_string(i)); + } + + if (deviceArgs.count("rtl") != 0 || (deviceArgs.count("driver") != 0 && (deviceArgs["driver"] == "rtl" || deviceArgs["driver"] == "rtlsdr"))) { + streamArgs["buffers"] = "6"; + streamArgs["buflen"] = "16384"; + } + + for (SoapySDR::Kwargs::const_iterator it = deviceArgs.begin(); it != deviceArgs.end(); ++it) { std::cout << " " << it->first << " = " << it->second << std::endl; if (it->first == "driver") { dev->setDriver(it->second); @@ -97,8 +147,9 @@ std::vector *SDREnumerator::enumerate_devices() { dev->setName(it->second); } } - - dev->setDeviceArgs(results[i]); + + dev->setDeviceArgs(deviceArgs); + dev->setStreamArgs(deviceArgs); std::cout << "Make device " << i << std::endl; try { @@ -125,36 +176,44 @@ std::vector *SDREnumerator::enumerate_devices() { chan->getRFRange().setLow(rfMin); chan->getRFRange().setHigh(rfMax); + std::vector freqs = device->listFrequencies(SOAPY_SDR_RX,i); + if (std::find(freqs.begin(), freqs.end(), "CORR") != freqs.end()) { + chan->setCORR(true); + } else { + chan->setCORR(false); + } + + if (device->hasDCOffsetMode(SOAPY_SDR_RX, i)) { + chan->setHardwareDC(true); + } else { + chan->setHardwareDC(false); + } + std::vector rates = device->listSampleRates(SOAPY_SDR_RX, i); chan->getSampleRates().assign(rates.begin(), rates.end()); dev->addChannel(chan); } - if (device->hasDCOffsetMode(SOAPY_SDR_RX, 0)) { - device->setDCOffsetMode(SOAPY_SDR_RX, 0, true); - std::cout << "Hardware DC offset support detected; internal DC offset correction will be disabled." << std::endl; - dev->setHardwareDC(true); - } else { - dev->setHardwareDC(false); - } + SoapySDR::Device::unmake(device); dev->setAvailable(true); } catch (const std::exception &ex) { std::cerr << "Error making device: " << ex.what() << std::endl; + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Error making device #") + std::to_string(i)); dev->setAvailable(false); } std::cout << std::endl; - SDREnumerator::devs.push_back(dev); + SDREnumerator::devs[remoteAddr].push_back(dev); } - if (results.empty()) { - std::cout << "No devices found!" << std::endl; + if (SDREnumerator::devs[remoteAddr].empty()) { + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("No devices found!")); } std::cout << std::endl; - return &SDREnumerator::devs; + return &SDREnumerator::devs[remoteAddr]; } @@ -163,15 +222,61 @@ void SDREnumerator::run() { std::cout << "SDR enumerator starting." << std::endl; terminated.store(false); - std::cout << "Enumerator devices." << std::endl; - SDREnumerator::enumerate_devices(); +// if (!remotes.size()) { +// remotes.push_back("raspberrypi.local"); +// } + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Scanning local devices, please wait.."); + SDREnumerator::enumerate_devices(""); + + if (remotes.size()) { + std::vector::iterator remote_i; + for (remote_i = remotes.begin(); remote_i != remotes.end(); remote_i++) { + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Scanning devices at " + (*remote_i) + ", please wait.."); + SDREnumerator::enumerate_devices(*remote_i); + } + } + std::cout << "Reporting enumeration complete." << std::endl; terminated.store(true); - wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_DEVICES_READY, "Devices Ready."); - + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_DEVICES_READY, "Finished scanning devices."); std::cout << "SDR enumerator done." << std::endl; } + +void SDREnumerator::addRemote(std::string remoteAddr) { + std::vector::iterator remote_i = std::find(remotes.begin(), remotes.end(), remoteAddr); + + if (remote_i != remotes.end()) { + return; + } else { + remotes.push_back(remoteAddr); + } +} + +void SDREnumerator::removeRemote(std::string remoteAddr) { + std::vector::iterator remote_i = std::find(remotes.begin(), remotes.end(), remoteAddr); + + if (remote_i != remotes.end()) { + if (devs.find(*remote_i) != devs.end()) { + while (devs[*remote_i].size()) { + SDRDeviceInfo *devRemove = devs[*remote_i].back(); + devs[*remote_i].pop_back(); + delete devRemove; + } + } + remotes.erase(remote_i); + } else { + return; + } +} + +std::vector &SDREnumerator::getRemotes() { + return remotes; +} + +bool SDREnumerator::hasRemoteModule() { + return SDREnumerator::has_remote; +} diff --git a/src/sdr/SDREnumerator.h b/src/sdr/SDREnumerator.h index 8c7e8ea..e0c243d 100644 --- a/src/sdr/SDREnumerator.h +++ b/src/sdr/SDREnumerator.h @@ -1,7 +1,8 @@ #pragma once #include -#include "ThreadQueue.h" +#include +#include #include "IOThread.h" #include "SDRDeviceInfo.h" #include "AppConfig.h" @@ -18,14 +19,21 @@ private: public: SDREnumerator(); ~SDREnumerator(); - enum SDREnumState { SDR_ENUM_DEVICES_READY, SDR_ENUM_TERMINATED, SDR_ENUM_FAILED }; + enum SDREnumState { SDR_ENUM_DEVICES_READY, SDR_ENUM_MESSAGE, SDR_ENUM_TERMINATED, SDR_ENUM_FAILED }; - static std::vector *enumerate_devices(); + static std::vector *enumerate_devices(std::string remoteAddr = "", bool noInit=false); void run(); + static void addRemote(std::string remoteAddr); + static void removeRemote(std::string remoteAddr); + static std::vector &getRemotes(); + static bool hasRemoteModule(); + protected: + static bool soapy_initialized, has_remote; static std::vector factories; static std::vector modules; - static std::vector devs; + static std::vector remotes; + static std::map< std::string, std::vector > devs; }; diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index 6f653ae..61da248 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -39,7 +39,6 @@ void SDRThread::init() { deviceConfig.store(wxGetApp().getConfig()->getDevice(devInfo->getDeviceId())); DeviceConfig *devConfig = deviceConfig.load(); - frequency = wxGetApp().getConfig()->getCenterFreq(); ppm.store(devConfig->getPPM()); direct_sampling_mode.store(devConfig->getDirectSampling()); @@ -53,6 +52,7 @@ void SDRThread::init() { args["direct_samp"] = std::to_string(devConfig->getDirectSampling()); if (driverName == "rtl" || driverName == "rtlsdr") { + args["iq_swap"] = std::to_string(devConfig->getIQSwap()?1:0); args["buffers"] = "6"; args["buflen"] = "16384"; hasPPM = true; @@ -60,17 +60,30 @@ void SDRThread::init() { hasPPM = false; } + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Initializing device.")); device = SoapySDR::Device::make(args); stream = device->setupStream(SOAPY_SDR_RX,"CF32", std::vector(), devInfo->getStreamArgs()); + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Activating stream.")); device->activateStream(stream); device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load()); device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency - offset.load()); - if (hasPPM) { - device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm); + SDRDeviceChannel *chan = devInfo->getRxChannel(); + if (chan->hasCORR()) { + hasPPM.store(true); + device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm.load()); + } else { + hasPPM.store(false); } + if (chan->hasHardwareDC()) { + hasHardwareDC.store(true); + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Found hardware DC offset correction support, internal disabled.")); + device->setDCOffsetMode(SOAPY_SDR_RX, chan->getChannel(), true); + } else { + hasHardwareDC.store(false); + } + device->setGainMode(SOAPY_SDR_RX,0,true); - hasHardwareDC = devInfo->hasHardwareDC(); numElems = getOptimalElementCount(sampleRate.load(), 60); diff --git a/src/sdr/SoapySDRThread.h b/src/sdr/SoapySDRThread.h index 64370fb..542ce35 100644 --- a/src/sdr/SoapySDRThread.h +++ b/src/sdr/SoapySDRThread.h @@ -47,7 +47,7 @@ private: public: SDRThread(); ~SDRThread(); - enum SDRThreadState { SDR_THREAD_TERMINATED, SDR_THREAD_FAILED }; + enum SDRThreadState { SDR_THREAD_MESSAGE, SDR_THREAD_TERMINATED, SDR_THREAD_FAILED }; void run();