Make stream deactivated before a sample-rate change and reactivated afterwards (#718)

* Make stream deactivated before a sample-rate chnage and reactivated afterwards

* Re-read sample rate and MTU AFTER stream activation to recompute CubicSDR buffers
This commit is contained in:
Vincent Sonnier 2019-03-15 06:30:55 +01:00 committed by GitHub
parent 0f098e3cbb
commit c27e1e6514
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 61 deletions

View File

@ -87,6 +87,7 @@ bool SDRThread::init() {
std::string streamExceptionStr("");
//1. setup stream for CF32:
try {
stream = device->setupStream(SOAPY_SDR_RX,"CF32", std::vector<size_t>(), currentStreamArgs);
} catch(exception e) {
@ -98,23 +99,17 @@ bool SDRThread::init() {
std::cout << "Stream setup failed, stream is null. " << streamExceptionStr << std::endl;
return false;
}
int streamMTU = device->getStreamMTU(stream);
mtuElems.store(streamMTU);
//2. Set sample rate:
device->setSampleRate(SOAPY_SDR_RX, 0, sampleRate.load());
//3. Store Stream-specific parameters to current Device
deviceInfo.load()->setStreamArgs(currentStreamArgs);
deviceConfig.load()->setStreamOpts(currentStreamArgs);
wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Activating stream."));
device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load());
// TODO: explore bandwidth setting option to see if this is necessary for others
if (device->getDriverKey() == "bladeRF") {
device->setBandwidth(SOAPY_SDR_RX, 0, sampleRate.load());
}
//4. Apply other settings: Frequency, PPM correction, Gains, Device-specific settings:
device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency - offset.load());
device->activateStream(stream);
if (devInfo->hasCORR(SOAPY_SDR_RX, 0)) {
hasPPM.store(true);
device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm.load());
@ -133,28 +128,12 @@ bool SDRThread::init() {
device->setGainMode(SOAPY_SDR_RX, 0, agc_mode.load());
}
numChannels.store(getOptimalChannelCount(sampleRate.load()));
numElems.store(getOptimalElementCount(sampleRate.load(), TARGET_DISPLAY_FPS));
//fallback if mtuElems was wrong
if (!mtuElems.load()) {
mtuElems.store(numElems.load());
std::cout << "SDRThread::init(): Device Stream MTU is broken, use " << mtuElems.load() << "instead..." << std::endl << std::flush;
} else {
std::cout << "SDRThread::init(): Device Stream set to MTU: " << mtuElems.load() << std::endl << std::flush;
}
overflowBuffer.data.resize(mtuElems.load());
buffs[0] = malloc(mtuElems.load() * 4 * sizeof(float));
numOverflow = 0;
SoapySDR::ArgInfoList settingsInfo = device->getSettingInfo();
SoapySDR::ArgInfoList::const_iterator settings_i;
if (!setting_value_changed.load()) {
settings.erase(settings.begin(), settings.end());
settingChanged.erase(settingChanged.begin(), settingChanged.end());
settings.clear();
settingChanged.clear();
}
//apply settings.
@ -174,11 +153,15 @@ bool SDRThread::init() {
setting_value_changed.store(false);
} //leave lock guard scope
updateSettings();
wxGetApp().sdrThreadNotify(SDRThread::SDR_THREAD_INITIALIZED, std::string("Device Initialized."));
//5. Activate stream: (through update settings)
wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Activating stream."));
rate_changed.store(true);
updateSettings();
//rebuild menu now that settings are really been applied.
wxGetApp().notifyMainUIOfDeviceChange(true);
@ -188,7 +171,13 @@ bool SDRThread::init() {
void SDRThread::deinit() {
device->deactivateStream(stream);
device->closeStream(stream);
free(buffs[0]);
if (buffs[0] != nullptr) {
::free(buffs[0]);
buffs[0] = nullptr;
}
stream = nullptr;
}
void SDRThread::assureBufferMinSize(SDRThreadIQData * dataOut, size_t minSize) {
@ -413,11 +402,12 @@ void SDRThread::readLoop() {
void SDRThread::updateGains() {
SDRDeviceInfo *devInfo = deviceInfo.load();
gainValues.erase(gainValues.begin(),gainValues.end());
gainChanged.erase(gainChanged.begin(),gainChanged.end());
gainValues.clear();
gainChanged.clear();
SDRRangeMap gains = devInfo->getGains(SOAPY_SDR_RX, 0);
for (SDRRangeMap::iterator gi = gains.begin(); gi != gains.end(); gi++) {
gainValues[gi->first] = device->getGain(SOAPY_SDR_RX, 0, gi->first);
gainChanged[gi->first] = false;
}
@ -448,39 +438,49 @@ void SDRThread::updateSettings() {
}
if (rate_changed.load()) {
device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load());
//1. Silence the device:
device->deactivateStream(stream);
//2. Set the (new) sample rate
device->setSampleRate(SOAPY_SDR_RX, 0, sampleRate.load());
//2.2 Device-specific workarounds:
// TODO: explore bandwidth setting option to see if this is necessary for others
if (device->getDriverKey() == "bladeRF") {
device->setBandwidth(SOAPY_SDR_RX, 0, sampleRate.load());
}
// Fix for LimeSDR-USB not properly handling samplerate changes while device is
// active.
else if (device->getHardwareKey() == "LimeSDR-USB") {
std::cout << "SDRThread::updateSettings(): Force deactivate / activate limeSDR stream" << std::endl << std::flush;
device->deactivateStream(stream);
device->activateStream(stream);
}
sampleRate.store(device->getSampleRate(SOAPY_SDR_RX,0));
//3. Re-activate stream:
device->activateStream(stream);
//4. Re-do Cubic buffers :
//re-read current sample rate and MTU:
sampleRate.store(device->getSampleRate(SOAPY_SDR_RX, 0));
numChannels.store(getOptimalChannelCount(sampleRate.load()));
numElems.store(getOptimalElementCount(sampleRate.load(), TARGET_DISPLAY_FPS));
//read (new) MTU size:
int streamMTU = device->getStreamMTU(stream);
mtuElems.store(streamMTU);
//fallback if mtuElems was wrong
if (!mtuElems.load()) {
mtuElems.store(numElems.load());
std::cout << "SDRThread::updateSettings(): Device Stream MTU is broken, use " << mtuElems.load() << "instead..." << std::endl << std::flush;
std::cout << "SDRThread: Device Stream MTU is broken, use " << mtuElems.load() << " instead..." << std::endl << std::flush;
} else {
std::cout << "SDRThread::updateSettings(): Device Stream changing to MTU: " << mtuElems.load() << std::endl << std::flush;
std::cout << "SDRThread : Device Stream set to MTU: " << mtuElems.load() << std::endl << std::flush;
}
overflowBuffer.data.resize(mtuElems.load());
free(buffs[0]);
buffs[0] = malloc(mtuElems.load() * 4 * sizeof(float));
if (buffs[0] != nullptr) {
::free(buffs[0]);
}
buffs[0] = ::malloc(mtuElems.load() * 4 * sizeof(float));
//clear overflow buffer
numOverflow = 0;
//
rate_changed.store(false);
doUpdate = true;
}
@ -499,11 +499,7 @@ void SDRThread::updateSettings() {
}
freq_changed.store(false);
}
// double devFreq = device->getFrequency(SOAPY_SDR_RX,0);
// if (((long long)devFreq + offset.load()) != frequency.load()) {
// wxGetApp().setFrequency((long long)devFreq + offset.load());
// }
if (agc_mode_changed.load()) {
if (device->hasGainMode(SOAPY_SDR_RX, 0)) {

View File

@ -106,9 +106,9 @@ protected:
void updateSettings();
SoapySDR::Kwargs combineArgs(SoapySDR::Kwargs a, SoapySDR::Kwargs b);
SoapySDR::Stream *stream;
SoapySDR::Stream *stream = nullptr;
SoapySDR::Device *device;
void *buffs[1];
void *buffs[1] = { nullptr };
ReBuffer<SDRThreadIQData> buffers;
SDRThreadIQData overflowBuffer;
int numOverflow;