Move DC correction to channel 0, reduce demod vis CPU usage

- Demod vis now uses channelizer output instead of decimation
- DC correction now only applied to channel 0
This commit is contained in:
Charles J. Cliffe 2015-10-17 16:17:12 -04:00
parent b438fc5a42
commit f1475fb9be
7 changed files with 62 additions and 62 deletions

View File

@ -671,8 +671,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
if (demod) { if (demod) {
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
if (demod->isTracking()) { if (demod->isTracking()) {
if (spectrumCanvas->getViewState()) { if (spectrumCanvas->getViewState()) {
long long diff = abs(demod->getFrequency() - spectrumCanvas->getCenterFrequency()) + (demod->getBandwidth()/2) + (demod->getBandwidth()/4); long long diff = abs(demod->getFrequency() - spectrumCanvas->getCenterFrequency()) + (demod->getBandwidth()/2) + (demod->getBandwidth()/4);
@ -816,7 +814,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
wxGetApp().getAudioVisualQueue()->set_max_num_items((scopeCanvas->scopeVisible()?1:0) + (scopeCanvas->spectrumVisible()?1:0)); wxGetApp().getAudioVisualQueue()->set_max_num_items((scopeCanvas->scopeVisible()?1:0) + (scopeCanvas->spectrumVisible()?1:0));
wxGetApp().getScopeProcessor()->run(); wxGetApp().getScopeProcessor()->run();
wxGetApp().getSpectrumDistributor()->run(); // wxGetApp().getSpectrumDistributor()->run();
SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcessor(); SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcessor();

View File

@ -59,22 +59,14 @@ bool CubicSDR::OnInit() {
pipeIQVisualData = new DemodulatorThreadInputQueue(); pipeIQVisualData = new DemodulatorThreadInputQueue();
pipeIQVisualData->set_max_num_items(1); pipeIQVisualData->set_max_num_items(1);
spectrumDistributor.setInput(pipeIQVisualData);
pipeDemodIQVisualData = new DemodulatorThreadInputQueue(); pipeDemodIQVisualData = new DemodulatorThreadInputQueue();
pipeDemodIQVisualData->set_max_num_items(1); pipeDemodIQVisualData->set_max_num_items(1);
pipeSpectrumIQVisualData = new DemodulatorThreadInputQueue();
pipeSpectrumIQVisualData->set_max_num_items(1);
pipeWaterfallIQVisualData = new DemodulatorThreadInputQueue(); pipeWaterfallIQVisualData = new DemodulatorThreadInputQueue();
pipeWaterfallIQVisualData->set_max_num_items(128); pipeWaterfallIQVisualData->set_max_num_items(128);
spectrumDistributor.attachOutput(pipeDemodIQVisualData);
spectrumDistributor.attachOutput(pipeSpectrumIQVisualData);
getDemodSpectrumProcessor()->setInput(pipeDemodIQVisualData); getDemodSpectrumProcessor()->setInput(pipeDemodIQVisualData);
getSpectrumProcessor()->setInput(pipeSpectrumIQVisualData); getSpectrumProcessor()->setInput(pipeIQVisualData);
pipeAudioVisualData = new DemodulatorThreadOutputQueue(); pipeAudioVisualData = new DemodulatorThreadOutputQueue();
pipeAudioVisualData->set_max_num_items(1); pipeAudioVisualData->set_max_num_items(1);
@ -89,19 +81,17 @@ bool CubicSDR::OnInit() {
sdrThread->setOutputQueue("IQDataOutput",pipeSDRIQData); sdrThread->setOutputQueue("IQDataOutput",pipeSDRIQData);
sdrPostThread = new SDRPostThread(); sdrPostThread = new SDRPostThread();
// sdrPostThread->setNumVisSamples(BUF_SIZE);
sdrPostThread->setInputQueue("IQDataInput", pipeSDRIQData); sdrPostThread->setInputQueue("IQDataInput", pipeSDRIQData);
sdrPostThread->setOutputQueue("IQVisualDataOutput", pipeIQVisualData); sdrPostThread->setOutputQueue("IQVisualDataOutput", pipeIQVisualData);
sdrPostThread->setOutputQueue("IQDataOutput", pipeWaterfallIQVisualData); sdrPostThread->setOutputQueue("IQDataOutput", pipeWaterfallIQVisualData);
sdrPostThread->setOutputQueue("IQActiveDemodVisualDataOutput", pipeDemodIQVisualData);
t_PostSDR = new std::thread(&SDRPostThread::threadMain, sdrPostThread); t_PostSDR = new std::thread(&SDRPostThread::threadMain, sdrPostThread);
t_SpectrumVisual = new std::thread(&SpectrumVisualDataThread::threadMain, spectrumVisualThread); t_SpectrumVisual = new std::thread(&SpectrumVisualDataThread::threadMain, spectrumVisualThread);
t_DemodVisual = new std::thread(&SpectrumVisualDataThread::threadMain, demodVisualThread); t_DemodVisual = new std::thread(&SpectrumVisualDataThread::threadMain, demodVisualThread);
// t_SDR = new std::thread(&SDRThread::threadMain, sdrThread);
sdrEnum = new SDREnumerator(); sdrEnum = new SDREnumerator();
appframe = new AppFrame(); appframe = new AppFrame();
t_SDREnum = new std::thread(&SDREnumerator::threadMain, sdrEnum); t_SDREnum = new std::thread(&SDREnumerator::threadMain, sdrEnum);
@ -371,11 +361,6 @@ SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcessor() {
return demodVisualThread->getProcessor(); return demodVisualThread->getProcessor();
} }
VisualDataDistributor<DemodulatorThreadIQData> *CubicSDR::getSpectrumDistributor() {
return &spectrumDistributor;
}
DemodulatorThreadOutputQueue* CubicSDR::getAudioVisualQueue() { DemodulatorThreadOutputQueue* CubicSDR::getAudioVisualQueue() {
return pipeAudioVisualData; return pipeAudioVisualData;
} }

View File

@ -70,11 +70,11 @@ public:
ScopeVisualProcessor *getScopeProcessor(); ScopeVisualProcessor *getScopeProcessor();
SpectrumVisualProcessor *getSpectrumProcessor(); SpectrumVisualProcessor *getSpectrumProcessor();
SpectrumVisualProcessor *getDemodSpectrumProcessor(); SpectrumVisualProcessor *getDemodSpectrumProcessor();
VisualDataDistributor<DemodulatorThreadIQData> *getSpectrumDistributor();
DemodulatorThreadOutputQueue* getAudioVisualQueue(); DemodulatorThreadOutputQueue* getAudioVisualQueue();
DemodulatorThreadInputQueue* getIQVisualQueue(); DemodulatorThreadInputQueue* getIQVisualQueue();
DemodulatorThreadInputQueue* getWaterfallVisualQueue(); DemodulatorThreadInputQueue* getWaterfallVisualQueue();
DemodulatorThreadInputQueue* getActiveDemodVisualQueue();
DemodulatorMgr &getDemodMgr(); DemodulatorMgr &getDemodMgr();
void bindDemodulator(DemodulatorInstance *demod); void bindDemodulator(DemodulatorInstance *demod);
@ -122,18 +122,15 @@ private:
SpectrumVisualDataThread *spectrumVisualThread; SpectrumVisualDataThread *spectrumVisualThread;
SpectrumVisualDataThread *demodVisualThread; SpectrumVisualDataThread *demodVisualThread;
// SDRThreadCommandQueue* pipeSDRCommand;
SDRThreadIQDataQueue* pipeSDRIQData; SDRThreadIQDataQueue* pipeSDRIQData;
DemodulatorThreadInputQueue* pipeIQVisualData; DemodulatorThreadInputQueue* pipeIQVisualData;
DemodulatorThreadOutputQueue* pipeAudioVisualData; DemodulatorThreadOutputQueue* pipeAudioVisualData;
DemodulatorThreadInputQueue* pipeDemodIQVisualData; DemodulatorThreadInputQueue* pipeDemodIQVisualData;
DemodulatorThreadInputQueue* pipeSpectrumIQVisualData;
DemodulatorThreadInputQueue* pipeWaterfallIQVisualData; DemodulatorThreadInputQueue* pipeWaterfallIQVisualData;
DemodulatorThreadInputQueue* pipeActiveDemodIQVisualData;
ScopeVisualProcessor scopeProcessor; ScopeVisualProcessor scopeProcessor;
VisualDataDistributor<DemodulatorThreadIQData> spectrumDistributor;
SDRDevicesDialog *deviceSelectorDialog; SDRDevicesDialog *deviceSelectorDialog;
std::thread *t_SDR, *t_SDREnum, *t_PostSDR, *t_SpectrumVisual, *t_DemodVisual; std::thread *t_SDR, *t_SDREnum, *t_PostSDR, *t_SpectrumVisual, *t_DemodVisual;

View File

@ -18,6 +18,7 @@ SDRPostThread::SDRPostThread() : IOThread() {
nRunDemods = 0; nRunDemods = 0;
doRefresh.store(false); doRefresh.store(false);
dcFilter = iirfilt_crcf_create_dc_blocker(0.0005);
} }
SDRPostThread::~SDRPostThread() { SDRPostThread::~SDRPostThread() {
@ -65,9 +66,7 @@ void SDRPostThread::initPFBChannelizer() {
chanCenters.resize(numChannels); chanCenters.resize(numChannels);
demodChannelActive.resize(numChannels); demodChannelActive.resize(numChannels);
// firpfbch2 returns 2x sample rate per channel // std::cout << "Channel bandwidth spacing: " << (chanBw) << std::endl;
// so, max demodulation without gaps is 1/2 chanBw ..?
// std::cout << "Channel bandwidth spacing: " << (chanBw/2) << " actual bandwidth: " << chanBw << std::endl;
} }
void SDRPostThread::updateActiveDemodulators() { void SDRPostThread::updateActiveDemodulators() {
@ -141,9 +140,12 @@ void SDRPostThread::run() {
iqDataInQueue = (SDRThreadIQDataQueue*)getInputQueue("IQDataInput"); iqDataInQueue = (SDRThreadIQDataQueue*)getInputQueue("IQDataInput");
iqDataOutQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQDataOutput"); iqDataOutQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQDataOutput");
iqVisualQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQVisualDataOutput"); iqVisualQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQVisualDataOutput");
iqActiveDemodVisualQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQActiveDemodVisualDataOutput");
iqDataInQueue->set_max_num_items(0); iqDataInQueue->set_max_num_items(0);
std::vector<liquid_float_complex> dcBuf;
while (!terminated) { while (!terminated) {
SDRThreadIQData *data_in; SDRThreadIQData *data_in;
@ -178,24 +180,25 @@ void SDRPostThread::run() {
// } // }
// } // }
if (iqVisualQueue != NULL || iqDataOutQueue != NULL) { if (iqDataOutQueue != NULL && !iqDataOutQueue->full()) {
bool doIQVis = iqVisualQueue && !iqVisualQueue->full();
bool doIQOut = iqDataOutQueue != NULL;
DemodulatorThreadIQData *iqDataOut = visualDataBuffers.getBuffer(); DemodulatorThreadIQData *iqDataOut = visualDataBuffers.getBuffer();
iqDataOut->setRefCount((doIQVis?1:0) + (doIQOut?1:0));
bool doVis = false;
if (iqVisualQueue != NULL && !iqVisualQueue->full()) {
doVis = true;
}
iqDataOut->setRefCount(1 + (doVis?1:0));
iqDataOut->frequency = data_in->frequency; iqDataOut->frequency = data_in->frequency;
iqDataOut->sampleRate = data_in->sampleRate; iqDataOut->sampleRate = data_in->sampleRate;
iqDataOut->data.assign(data_in->data.begin(), data_in->data.begin() + dataSize); iqDataOut->data.assign(data_in->data.begin(), data_in->data.begin() + dataSize);
if (doIQVis) { iqDataOutQueue->push(iqDataOut);
if (doVis) {
iqVisualQueue->push(iqDataOut); iqVisualQueue->push(iqDataOut);
} }
if (doIQOut) {
iqDataOutQueue->push(iqDataOut);
}
} }
busy_demod.lock(); busy_demod.lock();
@ -211,6 +214,8 @@ void SDRPostThread::run() {
doRefresh.store(false); doRefresh.store(false);
} }
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
int activeDemodChannel = -1;
// Find active demodulators // Find active demodulators
if (nRunDemods) { if (nRunDemods) {
@ -220,7 +225,7 @@ void SDRPostThread::run() {
// } // }
// channelize data // channelize data
// firpfbch2 output rate is 2 x ( input rate / channels ) // firpfbch output rate is (input rate / channels)
for (int i = 0, iMax = dataSize; i < iMax; i+=numChannels) { for (int i = 0, iMax = dataSize; i < iMax; i+=numChannels) {
firpfbch_crcf_analyzer_execute(channelizer, &data_in->data[i], &dataOut[i]); firpfbch_crcf_analyzer_execute(channelizer, &data_in->data[i], &dataOut[i]);
} }
@ -239,6 +244,9 @@ void SDRPostThread::run() {
if (fdelta < minDelta) { if (fdelta < minDelta) {
minDelta = fdelta; minDelta = fdelta;
demodChannel[i] = j; demodChannel[i] = j;
if (demod == activeDemod) {
activeDemodChannel = j;
}
} }
} }
} }
@ -250,16 +258,12 @@ void SDRPostThread::run() {
} }
} }
// Run channels // Run channels
for (int i = 0; i < numChannels; i++) { for (int i = 0; i < numChannels; i++) {
if (demodChannelActive[i] == 0) { bool doVis = (activeDemodChannel == i) && (iqActiveDemodVisualQueue != NULL) && !iqActiveDemodVisualQueue->full();
// Nothing using this channel, skip
continue;
}
DemodulatorThreadIQData *demodDataOut = buffers.getBuffer(); DemodulatorThreadIQData *demodDataOut = buffers.getBuffer();
demodDataOut->setRefCount(demodChannelActive[i]); demodDataOut->setRefCount(demodChannelActive[i] + (doVis?1:0));
demodDataOut->frequency = chanCenters[i]; demodDataOut->frequency = chanCenters[i];
demodDataOut->sampleRate = chanBw; demodDataOut->sampleRate = chanBw;
@ -274,9 +278,24 @@ void SDRPostThread::run() {
} }
// prepare channel data buffer // prepare channel data buffer
for (int j = 0, idx = i; j < chanDataSize; j++) { if (i == 0) { // Channel 0 requires DC correction
idx += numChannels; if (dcBuf.size() != chanDataSize) {
demodDataOut->data[j] = dataOut[idx]; dcBuf.resize(chanDataSize);
}
for (int j = 0, idx = i; j < chanDataSize; j++) {
idx += numChannels;
dcBuf[j] = dataOut[idx];
}
iirfilt_crcf_execute_block(dcFilter, &dcBuf[0], chanDataSize, &demodDataOut->data[0]);
} else {
for (int j = 0, idx = i; j < chanDataSize; j++) {
idx += numChannels;
demodDataOut->data[j] = dataOut[idx];
}
}
if (doVis) {
iqActiveDemodVisualQueue->push(demodDataOut);
} }
for (int j = 0; j < nRunDemods; j++) { for (int j = 0; j < nRunDemods; j++) {

View File

@ -25,6 +25,7 @@ protected:
SDRThreadIQDataQueue *iqDataInQueue; SDRThreadIQDataQueue *iqDataInQueue;
DemodulatorThreadInputQueue *iqDataOutQueue; DemodulatorThreadInputQueue *iqDataOutQueue;
DemodulatorThreadInputQueue *iqVisualQueue; DemodulatorThreadInputQueue *iqVisualQueue;
DemodulatorThreadInputQueue *iqActiveDemodVisualQueue;
std::mutex busy_demod; std::mutex busy_demod;
std::vector<DemodulatorInstance *> demodulators; std::vector<DemodulatorInstance *> demodulators;
@ -51,4 +52,5 @@ private:
int numChannels, sampleRate; int numChannels, sampleRate;
long long frequency; long long frequency;
firpfbch_crcf channelizer; firpfbch_crcf channelizer;
iirfilt_crcf dcFilter;
}; };

View File

@ -30,7 +30,7 @@ SDRThread::SDRThread() : IOThread() {
hasHardwareDC.store(false); hasHardwareDC.store(false);
numChannels.store(8); numChannels.store(8);
dcFilter = iirfilt_crcf_create_dc_blocker(0.0005); // dcFilter = iirfilt_crcf_create_dc_blocker(0.0005);
} }
SDRThread::~SDRThread() { SDRThread::~SDRThread() {
@ -80,7 +80,7 @@ void SDRThread::init() {
} }
if (chan->hasHardwareDC()) { if (chan->hasHardwareDC()) {
hasHardwareDC.store(true); hasHardwareDC.store(true);
wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Found hardware DC offset correction support, internal disabled.")); // wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Found hardware DC offset correction support, internal disabled."));
device->setDCOffsetMode(SOAPY_SDR_RX, chan->getChannel(), true); device->setDCOffsetMode(SOAPY_SDR_RX, chan->getChannel(), true);
} else { } else {
hasHardwareDC.store(false); hasHardwareDC.store(false);
@ -121,14 +121,14 @@ void SDRThread::readStream(SDRThreadIQDataQueue* iqDataOutQueue) {
if (n_read > 0 && !terminated) { if (n_read > 0 && !terminated) {
SDRThreadIQData *dataOut = buffers.getBuffer(); SDRThreadIQData *dataOut = buffers.getBuffer();
if (hasHardwareDC) { // if (hasHardwareDC) {
dataOut->data.assign(inpBuffer.data.begin(), inpBuffer.data.begin()+n_read); dataOut->data.assign(inpBuffer.data.begin(), inpBuffer.data.begin()+n_read);
} else { // } else {
if (dataOut->data.size() != n_read) { // if (dataOut->data.size() != n_read) {
dataOut->data.resize(n_read); // dataOut->data.resize(n_read);
} // }
iirfilt_crcf_execute_block(dcFilter, &inpBuffer.data[0], n_read, &dataOut->data[0]); // iirfilt_crcf_execute_block(dcFilter, &inpBuffer.data[0], n_read, &dataOut->data[0]);
} // }
dataOut->setRefCount(1); dataOut->setRefCount(1);

View File

@ -77,7 +77,6 @@ protected:
SoapySDR::Device *device; SoapySDR::Device *device;
void *buffs[1]; void *buffs[1];
ReBuffer<SDRThreadIQData> buffers; ReBuffer<SDRThreadIQData> buffers;
iirfilt_crcf dcFilter;
SDRThreadIQData inpBuffer; SDRThreadIQData inpBuffer;
std::atomic<DeviceConfig *> deviceConfig; std::atomic<DeviceConfig *> deviceConfig;
std::atomic<SDRDeviceInfo *> deviceInfo; std::atomic<SDRDeviceInfo *> deviceInfo;