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

View File

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