void SDRPostThread::updateActiveDemodulators() { // In range? std::vector<DemodulatorInstance *>::iterator demod_i; nRunDemods = 0; long long centerFreq = wxGetApp().getFrequency(); for (demod_i = demodulators.begin(); demod_i != demodulators.end(); demod_i++) { DemodulatorInstance *demod = *demod_i; DemodulatorThreadInputQueue *demodQueue = demod->getIQInputDataPipe(); // not in range? if (demod->isDeltaLock()) { if (demod->getFrequency() != centerFreq + demod->getDeltaLockOfs()) { demod->setFrequency(centerFreq + demod->getDeltaLockOfs()); demod->updateLabel(demod->getFrequency()); demod->setFollow(false); demod->setTracking(false); } } if (abs(frequency - demod->getFrequency()) > (sampleRate / 2)) { // deactivate if active if (demod->isActive() && !demod->isFollow() && !demod->isTracking()) { demod->setActive(false); DemodulatorThreadIQData *dummyDataOut = new DemodulatorThreadIQData; dummyDataOut->frequency = frequency; dummyDataOut->sampleRate = sampleRate; demodQueue->push(dummyDataOut); } // follow if follow mode if (demod->isFollow() && centerFreq != demod->getFrequency()) { wxGetApp().setFrequency(demod->getFrequency()); demod->setFollow(false); } } else if (!demod->isActive()) { // in range, activate if not activated demod->setActive(true); if (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) { wxGetApp().getDemodMgr().setActiveDemodulator(demod); } } if (!demod->isActive()) { continue; } // Add to the current run if (nRunDemods == runDemods.size()) { runDemods.push_back(demod); demodChannel.push_back(-1); } else { runDemods[nRunDemods] = demod; demodChannel[nRunDemods] = -1; } nRunDemods++; } }
void SDRPostThread::run() { #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 pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif dcFilter = iirfilt_crcf_create_dc_blocker(0.0005); std::cout << "SDR post-processing thread started.." << std::endl; iqDataInQueue = (SDRThreadIQDataQueue*)getInputQueue("IQDataInput"); iqDataOutQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQDataOutput"); iqVisualQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQVisualDataOutput"); ReBuffer<DemodulatorThreadIQData> buffers; std::vector<liquid_float_complex> fpData; std::vector<liquid_float_complex> dataOut; iqDataInQueue->set_max_num_items(0); while (!terminated) { SDRThreadIQData *data_in; iqDataInQueue->pop(data_in); // std::lock_guard < std::mutex > lock(data_in->m_mutex); if (data_in && data_in->data.size()) { int dataSize = data_in->data.size()/2; if (dataSize > fpData.capacity()) { fpData.reserve(dataSize); dataOut.reserve(dataSize); } if (dataSize != fpData.size()) { fpData.resize(dataSize); dataOut.resize(dataSize); } if (swapIQ) { for (int i = 0; i < dataSize; i++) { fpData[i] = _lut_swap[*((uint16_t*)&data_in->data[2*i])]; } } else { for (int i = 0; i < dataSize; i++) { fpData[i] = _lut[*((uint16_t*)&data_in->data[2*i])]; } } iirfilt_crcf_execute_block(dcFilter, &fpData[0], dataSize, &dataOut[0]); if (iqVisualQueue != NULL && !iqVisualQueue->full()) { DemodulatorThreadIQData *visualDataOut = visualDataBuffers.getBuffer(); visualDataOut->setRefCount(1); int num_vis_samples = dataOut.size(); // if (visualDataOut->data.size() < num_vis_samples) { // if (visualDataOut->data.capacity() < num_vis_samples) { // visualDataOut->data.reserve(num_vis_samples); // } // visualDataOut->data.resize(num_vis_samples); // } // visualDataOut->frequency = data_in->frequency; visualDataOut->sampleRate = data_in->sampleRate; visualDataOut->data.assign(dataOut.begin(), dataOut.begin() + num_vis_samples); iqVisualQueue->push(visualDataOut); } busy_demod.lock(); int activeDemods = 0; bool pushedData = false; if (demodulators.size() || iqDataOutQueue != NULL) { std::vector<DemodulatorInstance *>::iterator demod_i; for (demod_i = demodulators.begin(); demod_i != demodulators.end(); demod_i++) { DemodulatorInstance *demod = *demod_i; if (demod->getFrequency() != data_in->frequency && abs(data_in->frequency - demod->getFrequency()) > (wxGetApp().getSampleRate() / 2)) { continue; } activeDemods++; } if (iqDataOutQueue != NULL) { activeDemods++; } DemodulatorThreadIQData *demodDataOut = buffers.getBuffer(); // std::lock_guard < std::mutex > lock(demodDataOut->m_mutex); demodDataOut->frequency = data_in->frequency; demodDataOut->sampleRate = data_in->sampleRate; demodDataOut->setRefCount(activeDemods); demodDataOut->data.assign(dataOut.begin(), dataOut.end()); for (demod_i = demodulators.begin(); demod_i != demodulators.end(); demod_i++) { DemodulatorInstance *demod = *demod_i; DemodulatorThreadInputQueue *demodQueue = demod->getIQInputDataPipe(); if (abs(data_in->frequency - demod->getFrequency()) > (wxGetApp().getSampleRate() / 2)) { if (demod->isActive() && !demod->isFollow() && !demod->isTracking()) { demod->setActive(false); DemodulatorThreadIQData *dummyDataOut = new DemodulatorThreadIQData; dummyDataOut->frequency = data_in->frequency; dummyDataOut->sampleRate = data_in->sampleRate; demodQueue->push(dummyDataOut); } if (demod->isFollow() && wxGetApp().getFrequency() != demod->getFrequency()) { wxGetApp().setFrequency(demod->getFrequency()); } } else if (!demod->isActive()) { demod->setActive(true); if (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) { wxGetApp().getDemodMgr().setActiveDemodulator(demod); } } if (!demod->isActive()) { continue; } if (demod->isFollow()) { demod->setFollow(false); } demodQueue->push(demodDataOut); pushedData = true; } if (iqDataOutQueue != NULL) { if (!iqDataOutQueue->full()) { iqDataOutQueue->push(demodDataOut); pushedData = true; } else { demodDataOut->decRefCount(); } } if (!pushedData && iqDataOutQueue == NULL) { demodDataOut->setRefCount(0); } } busy_demod.unlock(); } data_in->decRefCount(); } // buffers.purge(); if (iqVisualQueue && !iqVisualQueue->empty()) { DemodulatorThreadIQData *visualDataDummy; iqVisualQueue->pop(visualDataDummy); } // visualDataBuffers.purge(); std::cout << "SDR post-processing thread done." << std::endl; }
void AppFrame::OnIdle(wxIdleEvent& event) { bool work_done = false; //#ifdef __APPLE__ // std::this_thread::sleep_for(std::chrono::milliseconds(4)); // std::this_thread::yield(); //#endif DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); if (demod) { DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); if (demod->isTracking()) { if (spectrumCanvas->getViewState()) { long long diff = abs(demod->getFrequency() - spectrumCanvas->getCenterFrequency()) + (demod->getBandwidth()/2) + (demod->getBandwidth()/4); if (diff > spectrumCanvas->getBandwidth()/2) { if (demod->getBandwidth() > spectrumCanvas->getBandwidth()) { diff = abs(demod->getFrequency() - spectrumCanvas->getCenterFrequency()); } else { diff = diff - spectrumCanvas->getBandwidth()/2; } spectrumCanvas->moveCenterFrequency((demod->getFrequency() < spectrumCanvas->getCenterFrequency())?diff:-diff); demod->setTracking(false); } } else { demod->setTracking(false); } } if (demod != activeDemodulator) { demodSignalMeter->setInputValue(demod->getSquelchLevel()); demodGainMeter->setInputValue(demod->getGain()); int outputDevice = demod->getOutputDevice(); scopeCanvas->setDeviceName(outputDevices[outputDevice].name); outputDeviceMenuItems[outputDevice]->Check(true); int dType = demod->getDemodulatorType(); demodModeSelector->setSelection(dType); } if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) { long long centerFreq = demod->getFrequency(); unsigned int demodBw = (unsigned int) ceil((float) demod->getBandwidth() * 2.25); if (demod->getDemodulatorType() == DEMOD_TYPE_USB) { demodBw /= 2; centerFreq += demod->getBandwidth() / 4; } if (demod->getDemodulatorType() == DEMOD_TYPE_LSB) { demodBw /= 2; centerFreq -= demod->getBandwidth() / 4; } if (demodBw > wxGetApp().getSampleRate() / 2) { demodBw = wxGetApp().getSampleRate() / 2; } if (demodBw < 20000) { demodBw = 20000; } if (centerFreq != demodWaterfallCanvas->getCenterFrequency()) { demodWaterfallCanvas->setCenterFrequency(centerFreq); demodSpectrumCanvas->setCenterFrequency(centerFreq); } int dSelection = demodModeSelector->getSelection(); if (dSelection != -1 && dSelection != demod->getDemodulatorType()) { demod->setDemodulatorType(dSelection); } demodWaterfallCanvas->setBandwidth(demodBw); demodSpectrumCanvas->setBandwidth(demodBw); } demodSignalMeter->setLevel(demod->getSignalLevel()); demodGainMeter->setLevel(demod->getGain()); if (demodSignalMeter->inputChanged()) { demod->setSquelchLevel(demodSignalMeter->getInputValue()); } if (demodGainMeter->inputChanged()) { demod->setGain(demodGainMeter->getInputValue()); demodGainMeter->setLevel(demodGainMeter->getInputValue()); } activeDemodulator = demod; } else { DemodulatorMgr *mgr = &wxGetApp().getDemodMgr(); int dSelection = demodModeSelector->getSelection(); if (dSelection != -1 && dSelection != mgr->getLastDemodulatorType()) { mgr->setLastDemodulatorType(dSelection); } demodGainMeter->setLevel(mgr->getLastGain()); if (demodSignalMeter->inputChanged()) { mgr->setLastSquelchLevel(demodSignalMeter->getInputValue()); } if (demodGainMeter->inputChanged()) { mgr->setLastGain(demodGainMeter->getInputValue()); demodGainMeter->setLevel(demodGainMeter->getInputValue()); } if (wxGetApp().getFrequency() != demodWaterfallCanvas->getCenterFrequency()) { demodWaterfallCanvas->setCenterFrequency(wxGetApp().getFrequency()); demodSpectrumCanvas->setCenterFrequency(wxGetApp().getFrequency()); } if (spectrumCanvas->getViewState() && abs(wxGetApp().getFrequency()-spectrumCanvas->getCenterFrequency()) > (wxGetApp().getSampleRate()/2)) { spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency()); waterfallCanvas->setCenterFrequency(wxGetApp().getFrequency()); } } if (demodTuner->getMouseTracker()->mouseInView()) { if (!demodTuner->HasFocus()) { demodTuner->SetFocus(); } } else if (!waterfallCanvas->HasFocus()) { waterfallCanvas->SetFocus(); } scopeCanvas->setPPMMode(demodTuner->isAltDown()); event.Skip(); }