Device Sample Rate improvements: UI, changed device sample rates to be expressed as long instead of int at some places for safety/consistency. Also pedantic harmless traces changes.

This commit is contained in:
vsonnier 2017-01-21 11:26:51 +01:00
parent 5e4f5d7d96
commit 196c664cf4
12 changed files with 171 additions and 58 deletions

View File

@ -709,9 +709,13 @@ void AppFrame::initDeviceParams(SDRDeviceInfo *devInfo) {
deviceChanged.store(true); deviceChanged.store(true);
} }
void AppFrame::notifyDeviceChanged() {
deviceChanged.store(true);
}
void AppFrame::updateDeviceParams() { void AppFrame::updateDeviceParams() {
if (!deviceChanged.load()) { if (!deviceChanged.load() || devInfo == nullptr) {
return; return;
} }
@ -800,16 +804,35 @@ void AppFrame::updateDeviceParams() {
menuBar->Replace(1, newSettingsMenu, wxT("&Settings")); menuBar->Replace(1, newSettingsMenu, wxT("&Settings"));
settingsMenu = newSettingsMenu; settingsMenu = newSettingsMenu;
// Build sample rate menu // Build/Rebuild the sample rate menu :
sampleRates = devInfo->getSampleRates(SOAPY_SDR_RX, 0); sampleRates = devInfo->getSampleRates(SOAPY_SDR_RX, 0);
sampleRateMenuItems.erase(sampleRateMenuItems.begin(),sampleRateMenuItems.end()); sampleRateMenuItems.clear();
wxMenu *newSampleRateMenu = new wxMenu; wxMenu *newSampleRateMenu = new wxMenu;
int ofs = 0; int ofs = 0;
//Current sample rate, try to keep it as is.
long sampleRate = wxGetApp().getSampleRate(); long sampleRate = wxGetApp().getSampleRate();
long minRate = sampleRates.front();
long maxRate = sampleRates.back();
//If it is beyond limits, make device choose a reasonable value
if (sampleRate < minRate || sampleRate > maxRate) {
sampleRate = devInfo->getSampleRateNear(SOAPY_SDR_RX, 0, sampleRate);
}
//Check if a manual entry was previously set: if so, check its value is still within the limits of the device. If not so, reset it.
if (manualSampleRate > 0 &&
manualSampleRate < minRate || manualSampleRate > maxRate) {
manualSampleRate = -1;
}
bool checked = false; bool checked = false;
for (vector<long>::iterator i = sampleRates.begin(); i != sampleRates.end(); i++) { for (vector<long>::iterator i = sampleRates.begin(); i != sampleRates.end(); i++) {
sampleRateMenuItems[wxID_BANDWIDTH_BASE+ofs] = newSampleRateMenu->AppendRadioItem(wxID_BANDWIDTH_BASE+ofs, frequencyToStr(*i)); sampleRateMenuItems[wxID_BANDWIDTH_BASE+ofs] = newSampleRateMenu->AppendRadioItem(wxID_BANDWIDTH_BASE+ofs, frequencyToStr(*i));
if (sampleRate == (*i)) { if (sampleRate == (*i)) {
sampleRateMenuItems[wxID_BANDWIDTH_BASE+ofs]->Check(true); sampleRateMenuItems[wxID_BANDWIDTH_BASE+ofs]->Check(true);
checked = true; checked = true;
@ -817,10 +840,26 @@ void AppFrame::updateDeviceParams() {
ofs++; ofs++;
} }
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL] = newSampleRateMenu->AppendRadioItem(wxID_BANDWIDTH_MANUAL, wxT("Manual Entry")); //Add a manual sample value radio button, but disabled by default in case the user
//never ever uses manual entry.
if (manualSampleRate <= 0) {
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL] = newSampleRateMenu->AppendRadioItem(wxID_BANDWIDTH_MANUAL, wxT("Manual : N/A"));
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Enable(false);
}
else {
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL] = newSampleRateMenu->AppendRadioItem(wxID_BANDWIDTH_MANUAL, wxT("Manual : ") + frequencyToStr(manualSampleRate));
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Enable(true);
}
//We apply the current sample rate after all
if (!checked) { if (!checked) {
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Check(true); sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Check(true);
} }
//Append a normal button (NOT a radio-button) for manual entry dialog at the end
newSampleRateMenu->AppendSeparator();
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL_DIALOG] = newSampleRateMenu->Append(wxID_BANDWIDTH_MANUAL_DIALOG, wxT("Manual Entry..."));
menuBar->Replace(2, newSampleRateMenu, wxT("Sample &Rate")); menuBar->Replace(2, newSampleRateMenu, wxT("Sample &Rate"));
sampleRateMenu = newSampleRateMenu; sampleRateMenu = newSampleRateMenu;
@ -890,7 +929,6 @@ void AppFrame::disableRig() {
} }
#endif #endif
void AppFrame::OnMenu(wxCommandEvent& event) { void AppFrame::OnMenu(wxCommandEvent& event) {
// if (event.GetId() >= wxID_RT_AUDIO_DEVICE && event.GetId() < wxID_RT_AUDIO_DEVICE + (int)devices.size()) { // if (event.GetId() >= wxID_RT_AUDIO_DEVICE && event.GetId() < wxID_RT_AUDIO_DEVICE + (int)devices.size()) {
@ -1129,41 +1167,51 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
bookmarkView->updateTheme(); bookmarkView->updateTheme();
} }
switch (event.GetId()) { if (event.GetId() == wxID_BANDWIDTH_MANUAL) {
case wxID_BANDWIDTH_MANUAL: wxGetApp().setSampleRate(manualSampleRate);
int rateHigh, rateLow; }
else if (event.GetId() == wxID_BANDWIDTH_MANUAL_DIALOG) {
SDRDeviceInfo *dev = wxGetApp().getDevice();
if (dev == NULL) { int rateHigh, rateLow;
break;
} SDRDeviceInfo *dev = wxGetApp().getDevice();
if (dev != nullptr) {
std::vector<long> sampleRates = dev->getSampleRates(SOAPY_SDR_RX, 0); std::vector<long> sampleRates = dev->getSampleRates(SOAPY_SDR_RX, 0);
rateLow = 2000000; //default
rateHigh = 30000000; rateLow = MANUAL_SAMPLE_RATE_MIN;
rateHigh = MANUAL_SAMPLE_RATE_MAX;
if (sampleRates.size()) { if (sampleRates.size()) {
rateLow = sampleRates[0]; rateLow = sampleRates.front();
rateHigh = sampleRates[sampleRates.size()-1]; rateHigh = sampleRates.back();
} }
long bw = wxGetNumberFromUser("\n" + dev->getName() + "\n\n " long bw = wxGetNumberFromUser("\n" + dev->getName() + "\n\n "
+ "min: " + std::to_string(rateLow) + " Hz" + "min: " + std::to_string(rateLow) + " Hz"
+ ", max: " + std::to_string(rateHigh) + " Hz\n", + ", max: " + std::to_string(rateHigh) + " Hz\n",
"Sample Rate in Hz", "Sample Rate in Hz",
"Manual Sample Rate Entry", "Manual Sample Rate Entry",
wxGetApp().getSampleRate(), //If a manual sample rate has already been input, recall this one.
rateLow, manualSampleRate > 0? manualSampleRate :wxGetApp().getSampleRate(),
rateHigh, rateLow,
this); rateHigh,
this);
if (bw != -1) { if (bw != -1) {
wxGetApp().setSampleRate(bw);
manualSampleRate = bw;
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Enable(true);
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->SetItemLabel(wxT("Manual : ") + frequencyToStr(manualSampleRate));
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Check(true);
wxGetApp().setSampleRate(manualSampleRate);
} }
break; }
} }
else if (event.GetId() >= wxID_BANDWIDTH_BASE && event.GetId() < wxID_BANDWIDTH_BASE + (int)sampleRates.size()) {
if (event.GetId() >= wxID_BANDWIDTH_BASE && event.GetId() < wxID_BANDWIDTH_BASE + (int)sampleRates.size()) {
wxGetApp().setSampleRate(sampleRates[event.GetId()-wxID_BANDWIDTH_BASE]); wxGetApp().setSampleRate(sampleRates[event.GetId()-wxID_BANDWIDTH_BASE]);
} }
@ -1842,18 +1890,54 @@ bool AppFrame::loadSession(std::string fileName) {
} }
if (header->hasAnother("sample_rate")) { if (header->hasAnother("sample_rate")) {
int sample_rate = *header->getNext("sample_rate");
long sample_rate = *header->getNext("sample_rate");
SDRDeviceInfo *dev = wxGetApp().getSDRThread()->getDevice(); SDRDeviceInfo *dev = wxGetApp().getSDRThread()->getDevice();
if (dev) { if (dev) {
// Try for a reasonable default sample rate. //retreive the available sample rates. A valid previously chosen manual
sample_rate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, sample_rate); //value is constrained within these limits. If it doesn't behave, lets the device choose
//for us.
long minRate = MANUAL_SAMPLE_RATE_MIN;
long maxRate = MANUAL_SAMPLE_RATE_MAX;
std::vector<long> sampleRates = dev->getSampleRates(SOAPY_SDR_RX, 0);
if (sampleRates.size()) {
minRate = sampleRates.front();
maxRate = sampleRates.back();
}
//If it is beyond limits, make device choose a reasonable value
if (sample_rate < minRate || sample_rate > maxRate) {
sample_rate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, sample_rate);
}
//scan the available sample rates and see if it matches a predifined one
int menuIndex = -1;
for (auto discreteRate : sampleRates) {
if (discreteRate == sample_rate) {
menuIndex++;
//activate Bandwidth Menu entry matching this predefined sample_rate.
sampleRateMenuItems[wxID_BANDWIDTH_BASE + menuIndex]->Check(true);
break;
}
} //end for
//this is a manual entry
if (menuIndex == -1) {
manualSampleRate = sample_rate;
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Enable(true);
// Apply the manual value, activate the menu entry
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->SetItemLabel(wxString("Manual Entry : ") + frequencyToStr(sample_rate));
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Check(true);
}
//update applied value
wxGetApp().setSampleRate(sample_rate); wxGetApp().setSampleRate(sample_rate);
deviceChanged.store(true); deviceChanged.store(true);
} else { } else {
wxGetApp().setSampleRate(sample_rate); wxGetApp().setSampleRate(sample_rate);
} }
} }
DemodulatorInstance *loadedActiveDemod = nullptr; DemodulatorInstance *loadedActiveDemod = nullptr;

View File

@ -55,6 +55,7 @@
#define wxID_DISPLAY_BOOKMARKS 2107 #define wxID_DISPLAY_BOOKMARKS 2107
#define wxID_BANDWIDTH_BASE 2150 #define wxID_BANDWIDTH_BASE 2150
#define wxID_BANDWIDTH_MANUAL_DIALOG 2199
#define wxID_BANDWIDTH_MANUAL 2200 #define wxID_BANDWIDTH_MANUAL 2200
#define wxID_DISPLAY_BASE 2250 #define wxID_DISPLAY_BASE 2250
@ -118,6 +119,12 @@ public:
BookmarkView *getBookmarkView(); BookmarkView *getBookmarkView();
void disableSave(bool state); void disableSave(bool state);
//call this in case the main UI is not
//the origin of device changes / sample rate by operator,
//and must be notified back to update its UI elements
//(ex: SDR Devices dialog changing the configuration)
void notifyDeviceChanged();
#ifdef _WIN32 #ifdef _WIN32
bool canFocus(); bool canFocus();
@ -174,6 +181,7 @@ private:
SoapySDR::ArgInfoList settingArgs; SoapySDR::ArgInfoList settingArgs;
int settingsIdMax; int settingsIdMax;
std::vector<long> sampleRates; std::vector<long> sampleRates;
long manualSampleRate = -1;
std::string currentSessionFile; std::string currentSessionFile;

View File

@ -917,6 +917,10 @@ bool CubicSDR::areDevicesReady() {
return devicesReady.load(); return devicesReady.load();
} }
void CubicSDR::notifyMainUIOfDeviceChange() {
appframe->notifyDeviceChanged();
}
bool CubicSDR::areDevicesEnumerating() { bool CubicSDR::areDevicesEnumerating() {
return !sdrEnum->isTerminated(); return !sdrEnum->isTerminated();
} }

View File

@ -138,6 +138,8 @@ public:
bool areDevicesEnumerating(); bool areDevicesEnumerating();
bool areModulesMissing(); bool areModulesMissing();
std::string getNotification(); std::string getNotification();
void notifyMainUIOfDeviceChange();
void addRemote(std::string remoteAddr); void addRemote(std::string remoteAddr);
void removeRemote(std::string remoteAddr); void removeRemote(std::string remoteAddr);

View File

@ -40,4 +40,6 @@ const char filePathSeparator =
#define CHANNELIZER_RATE_MAX 500000 #define CHANNELIZER_RATE_MAX 500000
#define MANUAL_SAMPLE_RATE_MIN 2000000 // 2MHz
#define MANUAL_SAMPLE_RATE_MAX 200000000 // 200MHz (We are 2017+ after all)

View File

@ -260,7 +260,7 @@ void AudioThread::enumerateDevices(std::vector<RtAudio::DeviceInfo> &devs) {
std::cout << "\t\t32-bit float normalized between plus/minus 1.0." << std::endl; std::cout << "\t\t32-bit float normalized between plus/minus 1.0." << std::endl;
} }
if (nFormats & RTAUDIO_FLOAT64) { if (nFormats & RTAUDIO_FLOAT64) {
std::cout << "\t\t32-bit float normalized between plus/minus 1.0." << std::endl; std::cout << "\t\t64-bit float normalized between plus/minus 1.0." << std::endl;
} }
std::vector<unsigned int>::iterator srate; std::vector<unsigned int>::iterator srate;

View File

@ -116,8 +116,8 @@ void SDRDevicesDialog::refreshDeviceProperties() {
devSettings["name"] = m_propertyGrid->Append( new wxStringProperty("Name", wxPG_LABEL, devConfig->getDeviceName()) ); devSettings["name"] = m_propertyGrid->Append( new wxStringProperty("Name", wxPG_LABEL, devConfig->getDeviceName()) );
devSettings["offset"] = m_propertyGrid->Append( new wxIntProperty("Offset (Hz)", wxPG_LABEL, devConfig->getOffset()) ); devSettings["offset"] = m_propertyGrid->Append( new wxIntProperty("Offset (Hz)", wxPG_LABEL, devConfig->getOffset()) );
int currentSampleRate = wxGetApp().getSampleRate(); long currentSampleRate = wxGetApp().getSampleRate();
int deviceSampleRate = devConfig->getSampleRate(); long deviceSampleRate = devConfig->getSampleRate();
if (!deviceSampleRate) { if (!deviceSampleRate) {
deviceSampleRate = selDev->getSampleRateNear(SOAPY_SDR_RX, 0, currentSampleRate); deviceSampleRate = selDev->getSampleRateNear(SOAPY_SDR_RX, 0, currentSampleRate);
@ -318,7 +318,7 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event) {
wxGetApp().setDeviceArgs(settingArgs); wxGetApp().setDeviceArgs(settingArgs);
wxGetApp().setStreamArgs(streamArgs); wxGetApp().setStreamArgs(streamArgs);
wxGetApp().setDevice(dev,0); wxGetApp().setDevice(dev,0);
wxGetApp().notifyMainUIOfDeviceChange();
Close(); Close();
} }
event.Skip(); event.Skip();
@ -438,13 +438,14 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) {
DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId());
std::string strRate = deviceArgs["sample_rate"].options[event.GetPropertyValue().GetInteger()]; std::string strRate = deviceArgs["sample_rate"].options[event.GetPropertyValue().GetInteger()];
int srate = 0; long srate = 0;
try { try {
srate = std::stoi(strRate); srate = std::stol(strRate);
devConfig->setSampleRate(srate); devConfig->setSampleRate(srate);
if (dev->isActive() || !wxGetApp().getDevice()) { if (dev->isActive() || !wxGetApp().getDevice()) {
wxGetApp().setSampleRate(srate); wxGetApp().setSampleRate(srate);
wxGetApp().notifyMainUIOfDeviceChange();
} }
} catch (std::invalid_argument e) { } catch (std::invalid_argument e) {
// nop // nop

View File

@ -208,7 +208,12 @@ void SDRThread::readStream(SDRThreadIQDataQueue* iqDataOutQueue) {
int n_stream_read = device->readStream(stream, buffs, mtElems, flags, timeNs); int n_stream_read = device->readStream(stream, buffs, mtElems, flags, timeNs);
//if the n_stream_read <= 0, bail out from reading. //if the n_stream_read <= 0, bail out from reading.
if (n_stream_read <= 0) { if (n_stream_read == 0) {
std::cout << "SDRThread::readStream(): read blocking..." << std::endl;
break;
}
else if (n_stream_read < 0) {
std::cout << "SDRThread::readStream(): read failed with code: " << n_stream_read << std::endl;
break; break;
} }
@ -226,7 +231,7 @@ void SDRThread::readStream(SDRThreadIQDataQueue* iqDataOutQueue) {
} else { } else {
break; break;
} }
} } //end while
if (n_read > 0 && !stopping && !iqDataOutQueue->full()) { if (n_read > 0 && !stopping && !iqDataOutQueue->full()) {
SDRThreadIQData *dataOut = buffers.getBuffer(); SDRThreadIQData *dataOut = buffers.getBuffer();
@ -515,7 +520,7 @@ long long SDRThread::getOffset() {
return offset.load(); return offset.load();
} }
void SDRThread::setSampleRate(int rate) { void SDRThread::setSampleRate(long rate) {
sampleRate.store(rate); sampleRate.store(rate);
rate_changed = true; rate_changed = true;
DeviceConfig *devConfig = deviceConfig.load(); DeviceConfig *devConfig = deviceConfig.load();
@ -524,7 +529,7 @@ void SDRThread::setSampleRate(int rate) {
} }
// std::cout << "Set sample rate: " << sampleRate.load() << std::endl; // std::cout << "Set sample rate: " << sampleRate.load() << std::endl;
} }
int SDRThread::getSampleRate() { long SDRThread::getSampleRate() {
return sampleRate.load(); return sampleRate.load();
} }

View File

@ -70,8 +70,8 @@ public:
void setOffset(long long ofs); void setOffset(long long ofs);
long long getOffset(); long long getOffset();
void setSampleRate(int rate); void setSampleRate(long rate);
int getSampleRate(); long getSampleRate();
void setPPM(int ppm); void setPPM(int ppm);
int getPPM(); int getPPM();
@ -109,7 +109,7 @@ protected:
std::map<std::string, std::string> settings; std::map<std::string, std::string> settings;
std::map<std::string, bool> settingChanged; std::map<std::string, bool> settingChanged;
std::atomic<uint32_t> sampleRate; std::atomic_llong sampleRate;
std::atomic_llong frequency, offset, lock_freq; std::atomic_llong frequency, offset, lock_freq;
std::atomic_int ppm, numElems, mtuElems, numChannels; std::atomic_int ppm, numElems, mtuElems, numChannels;
std::atomic_bool hasPPM, hasHardwareDC; std::atomic_bool hasPPM, hasHardwareDC;

View File

@ -170,6 +170,13 @@ void GainCanvas::setHelpTip(std::string tip) {
void GainCanvas::updateGainUI() { void GainCanvas::updateGainUI() {
SDRDeviceInfo *devInfo = wxGetApp().getDevice(); SDRDeviceInfo *devInfo = wxGetApp().getDevice();
//possible if we 'Refresh Devices' then devInfo becomes null
//until a new device is selected.
if (devInfo == nullptr) {
return;
}
DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(devInfo->getDeviceId()); DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(devInfo->getDeviceId());
gains = devInfo->getGains(SOAPY_SDR_RX, 0); gains = devInfo->getGains(SOAPY_SDR_RX, 0);

View File

@ -30,7 +30,7 @@ InteractiveCanvas::InteractiveCanvas(wxWindow *parent, int *dispAttrs) :
InteractiveCanvas::~InteractiveCanvas() { InteractiveCanvas::~InteractiveCanvas() {
} }
void InteractiveCanvas::setView(long long center_freq_in, int bandwidth_in) { void InteractiveCanvas::setView(long long center_freq_in, long long bandwidth_in) {
isView = true; isView = true;
centerFreq = center_freq_in; centerFreq = center_freq_in;
bandwidth = bandwidth_in; bandwidth = bandwidth_in;
@ -74,11 +74,11 @@ long long InteractiveCanvas::getCenterFrequency() {
} }
} }
void InteractiveCanvas::setBandwidth(unsigned int bandwidth_in) { void InteractiveCanvas::setBandwidth(long long bandwidth_in) {
bandwidth = bandwidth_in; bandwidth = bandwidth_in;
} }
unsigned int InteractiveCanvas::getBandwidth() { long long InteractiveCanvas::getBandwidth() {
if (isView) { if (isView) {
return bandwidth; return bandwidth;
} else { } else {

View File

@ -17,15 +17,15 @@ public:
long long getFrequencyAt(float x); long long getFrequencyAt(float x);
long long getFrequencyAt(float x, long long iqCenterFreq, long long iqBandwidth); long long getFrequencyAt(float x, long long iqCenterFreq, long long iqBandwidth);
virtual void setView(long long center_freq_in, int bandwidth_in); virtual void setView(long long center_freq_in, long long bandwidth_in);
virtual void disableView(); virtual void disableView();
bool getViewState(); bool getViewState();
void setCenterFrequency(long long center_freq_in); void setCenterFrequency(long long center_freq_in);
long long getCenterFrequency(); long long getCenterFrequency();
void setBandwidth(unsigned int bandwidth_in); void setBandwidth(long long bandwidth_in);
unsigned int getBandwidth(); long long getBandwidth();
MouseTracker *getMouseTracker(); MouseTracker *getMouseTracker();
bool isMouseInView(); bool isMouseInView();
@ -59,8 +59,8 @@ protected:
bool ctrlDown; bool ctrlDown;
long long centerFreq; long long centerFreq;
unsigned int bandwidth; long long bandwidth;
unsigned int lastBandwidth; long long lastBandwidth;
bool isView; bool isView;
std::string lastToolTip; std::string lastToolTip;