diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index c155eaa..ff118f3 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -187,6 +187,33 @@ AppFrame::AppFrame() : menuBar->Append(menu, wxT("&Input Bandwidth")); + std::vector *devs = wxGetApp().getDevices(); + std::vector::iterator devs_i; + + if (devs->size() > 1) { + + menu = new wxMenu; + + int p = 0; + for (devs_i = devs->begin(); devs_i != devs->end(); devs_i++) { + std::string devName = (*devs_i)->getName(); + if ((*devs_i)->isAvailable()) { + devName.append(": "); + devName.append((*devs_i)->getProduct()); + devName.append(" ["); + devName.append((*devs_i)->getSerial()); + devName.append("]"); + } else { + devName.append(" (In Use?)"); + } + + menu->Append(wxID_DEVICE_ID+p, devName); + p++; + } + + menuBar->Append(menu,wxT("&Device")); + } + SetMenuBar(menuBar); CreateStatusBar(); @@ -298,6 +325,11 @@ void AppFrame::OnMenu(wxCommandEvent& event) { wxGetApp().setSampleRate(3200000); break; } + + std::vector *devs = wxGetApp().getDevices(); + if (event.GetId() >= wxID_DEVICE_ID && event.GetId() <= wxID_DEVICE_ID+devs->size()) { + wxGetApp().setDevice(event.GetId()-wxID_DEVICE_ID); + } } void AppFrame::OnClose(wxCommandEvent& WXUNUSED(event)) { diff --git a/src/AppFrame.h b/src/AppFrame.h index 350508f..93dad38 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -31,6 +31,9 @@ #define wxID_BANDWIDTH_2880M 2156 #define wxID_BANDWIDTH_3200M 2158 +#define wxID_DEVICE_ID 3500 + + // Define a new frame type class AppFrame: public wxFrame { public: diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 3c21c78..50b265a 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -39,6 +39,32 @@ bool CubicSDR::OnInit() { sdrPostThread->setIQDataInQueue(iqPostDataQueue); sdrPostThread->setIQVisualQueue(iqVisualQueue); + std::vector::iterator devs_i; + + SDRThread::enumerate_rtl(&devs); + + if (devs.size() > 1) { + wxArrayString choices; + for (devs_i = devs.begin(); devs_i != devs.end(); devs_i++) { + std::string devName = (*devs_i)->getName(); + if ((*devs_i)->isAvailable()) { + devName.append(": "); + devName.append((*devs_i)->getProduct()); + devName.append(" ["); + devName.append((*devs_i)->getSerial()); + devName.append("]"); + } else { + devName.append(" (In Use?)"); + } + choices.Add(devName); + } + + int devId = wxGetSingleChoiceIndex(wxT("Devices"),wxT("Choose Input Device"),choices); + + std::cout << "Chosen: " << devId << std::endl; + sdrThread->setDeviceId(devId); + } + t_PostSDR = new std::thread(&SDRPostThread::threadMain, sdrPostThread); t_SDR = new std::thread(&SDRThread::threadMain, sdrThread); @@ -163,3 +189,14 @@ void CubicSDR::removeDemodulator(DemodulatorInstance *demod) { } sdrPostThread->removeDemodulator(demod); } + +std::vector* CubicSDR::getDevices() { + return &devs; +} + +void CubicSDR::setDevice(int deviceId) { + sdrThread->setDeviceId(deviceId); + SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_SET_DEVICE); + command.llong_value = deviceId; + threadCmdQueueSDR->push(command); +} diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 0fdf89b..8ac9d8d 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -38,6 +38,9 @@ public: void setSampleRate(long long rate_in); long long getSampleRate(); + std::vector *getDevices(); + void setDevice(int deviceId); + DemodulatorThreadOutputQueue* getAudioVisualQueue(); DemodulatorThreadInputQueue* getIQVisualQueue(); DemodulatorMgr &getDemodMgr(); @@ -47,6 +50,7 @@ public: private: PrimaryGLContext *m_glContext; + std::vector devs; DemodulatorMgr demodMgr; diff --git a/src/sdr/SDRThread.cpp b/src/sdr/SDRThread.cpp index b28c311..8cd7dbb 100644 --- a/src/sdr/SDRThread.cpp +++ b/src/sdr/SDRThread.cpp @@ -4,7 +4,7 @@ #include "CubicSDR.h" SDRThread::SDRThread(SDRThreadCommandQueue* pQueue) : - commandQueue(pQueue), iqDataOutQueue(NULL), terminated(false), offset(0) { + commandQueue(pQueue), iqDataOutQueue(NULL), terminated(false), offset(0), deviceId(-1) { dev = NULL; sampleRate = DEFAULT_SAMPLE_RATE; } @@ -13,7 +13,7 @@ SDRThread::~SDRThread() { rtlsdr_close(dev); } -int SDRThread::enumerate_rtl() { +int SDRThread::enumerate_rtl(std::vector *devs) { int first_available = -1; @@ -24,37 +24,51 @@ int SDRThread::enumerate_rtl() { std::cout << "RTL Devices: " << rtl_count << std::endl; for (int i = 0; i < rtl_count; i++) { - std::cout << "Device #" << i << ": " << rtlsdr_get_device_name(i) << std::endl; + std::string deviceName(rtlsdr_get_device_name(i)); + std::string deviceManufacturer; + std::string deviceProduct; + std::string deviceTuner; + std::string deviceSerial; + + bool deviceAvailable = false; + std::cout << "Device #" << i << ": " << deviceName << std::endl; if (rtlsdr_get_device_usb_strings(i, manufact, product, serial) == 0) { std::cout << "\tManufacturer: " << manufact << ", Product Name: " << product << ", Serial: " << serial << std::endl; - rtlsdr_open(&dev, i); + deviceSerial = serial; + deviceAvailable = true; + deviceProduct = product; + deviceManufacturer = manufact; + + rtlsdr_dev_t *devTest; + rtlsdr_open(&devTest, i); std::cout << "\t Tuner type: "; - switch (rtlsdr_get_tuner_type(dev)) { + switch (rtlsdr_get_tuner_type(devTest)) { case RTLSDR_TUNER_UNKNOWN: - std::cout << "Unknown"; + deviceTuner = "Unknown"; break; case RTLSDR_TUNER_E4000: - std::cout << "Elonics E4000"; + deviceTuner = "Elonics E4000"; break; case RTLSDR_TUNER_FC0012: - std::cout << "Fitipower FC0012"; + deviceTuner = "Fitipower FC0012"; break; case RTLSDR_TUNER_FC0013: - std::cout << "Fitipower FC0013"; + deviceTuner = "Fitipower FC0013"; break; case RTLSDR_TUNER_FC2580: - std::cout << "Fitipower FC2580"; + deviceTuner = "Fitipower FC2580"; break; case RTLSDR_TUNER_R820T: - std::cout << "Rafael Micro R820T"; + deviceTuner = "Rafael Micro R820T"; break; case RTLSDR_TUNER_R828D: + deviceTuner = "Rafael Micro R828D"; break; } - std::cout << std::endl; + std::cout << deviceTuner << std::endl; /* int num_gains = rtlsdr_get_tuner_gains(dev, NULL); @@ -73,7 +87,7 @@ int SDRThread::enumerate_rtl() { free(gains); */ - rtlsdr_close(dev); + rtlsdr_close(devTest); if (first_available == -1) { first_available = i; } @@ -82,6 +96,15 @@ int SDRThread::enumerate_rtl() { std::cout << "\tUnable to access device #" << i << " (in use?)" << std::endl; } + if (devs != NULL) { + SDRDeviceInfo *devInfo = new SDRDeviceInfo(); + devInfo->setName(deviceName); + devInfo->setAvailable(deviceAvailable); + devInfo->setProduct(deviceProduct); + devInfo->setSerial(deviceSerial); + devInfo->setManufacturer(deviceManufacturer); + devs->push_back(devInfo); + } } return first_available; @@ -92,27 +115,29 @@ void SDRThread::threadMain() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO) - 1; - sched_param prio = {priority}; // scheduling priority of thread + sched_param prio = { priority }; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif std::cout << "SDR thread initializing.." << std::endl; int devCount = rtlsdr_get_device_count(); - int firstDevAvailable = enumerate_rtl(); + if (deviceId == -1) { + deviceId = enumerate_rtl(NULL); + } - if (firstDevAvailable == -1) { + if (deviceId == -1) { std::cout << "No devices found.. SDR Thread exiting.." << std::endl; return; } else { - std::cout << "Using first available RTL-SDR device #" << firstDevAvailable << std::endl; + std::cout << "Using device #" << deviceId << std::endl; } signed char buf[BUF_SIZE]; long long frequency = DEFAULT_FREQ; - rtlsdr_open(&dev, firstDevAvailable); + rtlsdr_open(&dev, deviceId); rtlsdr_set_sample_rate(dev, sampleRate); rtlsdr_set_center_freq(dev, frequency - offset); rtlsdr_set_agc_mode(dev, 1); @@ -138,9 +163,11 @@ void SDRThread::threadMain() { bool freq_changed = false; bool offset_changed = false; bool rate_changed = false; + bool device_changed = false; long long new_freq; long long new_offset; long long new_rate; + int new_device; while (!cmdQueue->empty()) { SDRThreadCommand command; @@ -165,11 +192,25 @@ void SDRThread::threadMain() { new_rate = command.llong_value; std::cout << "Set sample rate: " << new_rate << std::endl; break; + case SDRThreadCommand::SDR_THREAD_CMD_SET_DEVICE: + device_changed = true; + new_device = (int) command.llong_value; + std::cout << "Set device: " << new_device << std::endl; + break; default: break; } } + if (device_changed) { + rtlsdr_close(dev); + rtlsdr_open(&dev, new_device); + rtlsdr_set_sample_rate(dev, sampleRate); + rtlsdr_set_center_freq(dev, frequency - offset); + rtlsdr_set_agc_mode(dev, 1); + rtlsdr_set_offset_tuning(dev, 0); + rtlsdr_reset_buffer(dev); + } if (offset_changed && !freq_changed) { new_freq = frequency; freq_changed = true; diff --git a/src/sdr/SDRThread.h b/src/sdr/SDRThread.h index c335095..032178f 100644 --- a/src/sdr/SDRThread.h +++ b/src/sdr/SDRThread.h @@ -14,10 +14,71 @@ #include "ThreadQueue.h" #include "DemodulatorMgr.h" +class SDRDeviceInfo { +public: + SDRDeviceInfo() : name(""), serial(""), available(false) { } + + bool isAvailable() const { + return available; + } + + void setAvailable(bool available) { + this->available = available; + } + + const std::string& getName() const { + return name; + } + + void setName(const std::string& name) { + this->name = name; + } + + const std::string& getSerial() const { + return serial; + } + + void setSerial(const std::string& serial) { + this->serial = serial; + } + + const std::string& getTuner() const { + return tuner; + } + + void setTuner(const std::string& tuner) { + this->tuner = tuner; + } + + const std::string& getManufacturer() const { + return manufacturer; + } + + void setManufacturer(const std::string& manufacturer) { + this->manufacturer = manufacturer; + } + + const std::string& getProduct() const { + return product; + } + + void setProduct(const std::string& product) { + this->product = product; + } + +private: + std::string name; + std::string serial; + std::string product; + std::string manufacturer; + std::string tuner; + bool available; +}; + class SDRThreadCommand { public: enum SDRThreadCommandEnum { - SDR_THREAD_CMD_NULL, SDR_THREAD_CMD_TUNE, SDR_THREAD_CMD_SET_OFFSET, SDR_THREAD_CMD_SET_SAMPLERATE + SDR_THREAD_CMD_NULL, SDR_THREAD_CMD_TUNE, SDR_THREAD_CMD_SET_OFFSET, SDR_THREAD_CMD_SET_SAMPLERATE, SDR_THREAD_CMD_SET_DEVICE }; SDRThreadCommand() : @@ -65,7 +126,7 @@ public: SDRThread(SDRThreadCommandQueue* pQueue); ~SDRThread(); - int enumerate_rtl(); + static int enumerate_rtl(std::vector *devs); void threadMain(); @@ -74,6 +135,15 @@ public: } void terminate(); + + int getDeviceId() const { + return deviceId; + } + + void setDeviceId(int deviceId) { + this->deviceId = deviceId; + } + protected: uint32_t sampleRate; long long offset; @@ -81,4 +151,5 @@ protected: std::atomic iqDataOutQueue; std::atomic terminated; + int deviceId; };