mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-26 21:58:37 -05:00
Merge pull request #499 from vsonnier/sample_rate_gui_improvements
Device Sample Rate improvements: UI, rates handled as long, misc...
This commit is contained in:
commit
6bcf0eb56a
158
src/AppFrame.cpp
158
src/AppFrame.cpp
@ -709,9 +709,13 @@ void AppFrame::initDeviceParams(SDRDeviceInfo *devInfo) {
|
||||
deviceChanged.store(true);
|
||||
}
|
||||
|
||||
void AppFrame::notifyDeviceChanged() {
|
||||
deviceChanged.store(true);
|
||||
}
|
||||
|
||||
void AppFrame::updateDeviceParams() {
|
||||
|
||||
if (!deviceChanged.load()) {
|
||||
if (!deviceChanged.load() || devInfo == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -800,16 +804,35 @@ void AppFrame::updateDeviceParams() {
|
||||
menuBar->Replace(1, newSettingsMenu, wxT("&Settings"));
|
||||
settingsMenu = newSettingsMenu;
|
||||
|
||||
// Build sample rate menu
|
||||
// Build/Rebuild the sample rate menu :
|
||||
sampleRates = devInfo->getSampleRates(SOAPY_SDR_RX, 0);
|
||||
sampleRateMenuItems.erase(sampleRateMenuItems.begin(),sampleRateMenuItems.end());
|
||||
sampleRateMenuItems.clear();
|
||||
|
||||
wxMenu *newSampleRateMenu = new wxMenu;
|
||||
int ofs = 0;
|
||||
|
||||
//Current sample rate, try to keep it as is.
|
||||
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;
|
||||
for (vector<long>::iterator i = sampleRates.begin(); i != sampleRates.end(); i++) {
|
||||
|
||||
sampleRateMenuItems[wxID_BANDWIDTH_BASE+ofs] = newSampleRateMenu->AppendRadioItem(wxID_BANDWIDTH_BASE+ofs, frequencyToStr(*i));
|
||||
|
||||
if (sampleRate == (*i)) {
|
||||
sampleRateMenuItems[wxID_BANDWIDTH_BASE+ofs]->Check(true);
|
||||
checked = true;
|
||||
@ -817,10 +840,26 @@ void AppFrame::updateDeviceParams() {
|
||||
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) {
|
||||
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"));
|
||||
sampleRateMenu = newSampleRateMenu;
|
||||
@ -890,7 +929,6 @@ void AppFrame::disableRig() {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void AppFrame::OnMenu(wxCommandEvent& event) {
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
switch (event.GetId()) {
|
||||
case wxID_BANDWIDTH_MANUAL:
|
||||
int rateHigh, rateLow;
|
||||
|
||||
SDRDeviceInfo *dev = wxGetApp().getDevice();
|
||||
if (dev == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (event.GetId() == wxID_BANDWIDTH_MANUAL) {
|
||||
wxGetApp().setSampleRate(manualSampleRate);
|
||||
}
|
||||
else if (event.GetId() == wxID_BANDWIDTH_MANUAL_DIALOG) {
|
||||
|
||||
int rateHigh, rateLow;
|
||||
|
||||
SDRDeviceInfo *dev = wxGetApp().getDevice();
|
||||
if (dev != nullptr) {
|
||||
|
||||
std::vector<long> sampleRates = dev->getSampleRates(SOAPY_SDR_RX, 0);
|
||||
|
||||
rateLow = 2000000;
|
||||
rateHigh = 30000000;
|
||||
|
||||
|
||||
//default
|
||||
rateLow = MANUAL_SAMPLE_RATE_MIN;
|
||||
rateHigh = MANUAL_SAMPLE_RATE_MAX;
|
||||
|
||||
if (sampleRates.size()) {
|
||||
rateLow = sampleRates[0];
|
||||
rateHigh = sampleRates[sampleRates.size()-1];
|
||||
rateLow = sampleRates.front();
|
||||
rateHigh = sampleRates.back();
|
||||
}
|
||||
|
||||
long bw = wxGetNumberFromUser("\n" + dev->getName() + "\n\n "
|
||||
+ "min: " + std::to_string(rateLow) + " Hz"
|
||||
+ ", max: " + std::to_string(rateHigh) + " Hz\n",
|
||||
"Sample Rate in Hz",
|
||||
"Manual Sample Rate Entry",
|
||||
wxGetApp().getSampleRate(),
|
||||
rateLow,
|
||||
rateHigh,
|
||||
this);
|
||||
+ "min: " + std::to_string(rateLow) + " Hz"
|
||||
+ ", max: " + std::to_string(rateHigh) + " Hz\n",
|
||||
"Sample Rate in Hz",
|
||||
"Manual Sample Rate Entry",
|
||||
//If a manual sample rate has already been input, recall this one.
|
||||
manualSampleRate > 0? manualSampleRate :wxGetApp().getSampleRate(),
|
||||
rateLow,
|
||||
rateHigh,
|
||||
this);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.GetId() >= wxID_BANDWIDTH_BASE && event.GetId() < wxID_BANDWIDTH_BASE + (int)sampleRates.size()) {
|
||||
else if (event.GetId() >= wxID_BANDWIDTH_BASE && event.GetId() < wxID_BANDWIDTH_BASE + (int)sampleRates.size()) {
|
||||
|
||||
wxGetApp().setSampleRate(sampleRates[event.GetId()-wxID_BANDWIDTH_BASE]);
|
||||
}
|
||||
|
||||
@ -1842,18 +1890,54 @@ bool AppFrame::loadSession(std::string fileName) {
|
||||
}
|
||||
|
||||
if (header->hasAnother("sample_rate")) {
|
||||
int sample_rate = *header->getNext("sample_rate");
|
||||
|
||||
|
||||
long sample_rate = *header->getNext("sample_rate");
|
||||
|
||||
SDRDeviceInfo *dev = wxGetApp().getSDRThread()->getDevice();
|
||||
if (dev) {
|
||||
// Try for a reasonable default sample rate.
|
||||
sample_rate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, sample_rate);
|
||||
//retreive the available sample rates. A valid previously chosen manual
|
||||
//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);
|
||||
deviceChanged.store(true);
|
||||
} else {
|
||||
wxGetApp().setSampleRate(sample_rate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DemodulatorInstance *loadedActiveDemod = nullptr;
|
||||
|
@ -55,6 +55,7 @@
|
||||
#define wxID_DISPLAY_BOOKMARKS 2107
|
||||
|
||||
#define wxID_BANDWIDTH_BASE 2150
|
||||
#define wxID_BANDWIDTH_MANUAL_DIALOG 2199
|
||||
#define wxID_BANDWIDTH_MANUAL 2200
|
||||
|
||||
#define wxID_DISPLAY_BASE 2250
|
||||
@ -118,6 +119,12 @@ public:
|
||||
|
||||
BookmarkView *getBookmarkView();
|
||||
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
|
||||
bool canFocus();
|
||||
@ -174,6 +181,7 @@ private:
|
||||
SoapySDR::ArgInfoList settingArgs;
|
||||
int settingsIdMax;
|
||||
std::vector<long> sampleRates;
|
||||
long manualSampleRate = -1;
|
||||
|
||||
std::string currentSessionFile;
|
||||
|
||||
|
@ -917,6 +917,10 @@ bool CubicSDR::areDevicesReady() {
|
||||
return devicesReady.load();
|
||||
}
|
||||
|
||||
void CubicSDR::notifyMainUIOfDeviceChange() {
|
||||
appframe->notifyDeviceChanged();
|
||||
}
|
||||
|
||||
bool CubicSDR::areDevicesEnumerating() {
|
||||
return !sdrEnum->isTerminated();
|
||||
}
|
||||
|
@ -138,6 +138,8 @@ public:
|
||||
bool areDevicesEnumerating();
|
||||
bool areModulesMissing();
|
||||
std::string getNotification();
|
||||
|
||||
void notifyMainUIOfDeviceChange();
|
||||
|
||||
void addRemote(std::string remoteAddr);
|
||||
void removeRemote(std::string remoteAddr);
|
||||
|
@ -40,4 +40,6 @@ const char filePathSeparator =
|
||||
|
||||
#define CHANNELIZER_RATE_MAX 500000
|
||||
|
||||
#define MANUAL_SAMPLE_RATE_MIN 2000000 // 2MHz
|
||||
#define MANUAL_SAMPLE_RATE_MAX 200000000 // 200MHz (We are 2017+ after all)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
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;
|
||||
|
@ -116,8 +116,8 @@ void SDRDevicesDialog::refreshDeviceProperties() {
|
||||
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()) );
|
||||
|
||||
int currentSampleRate = wxGetApp().getSampleRate();
|
||||
int deviceSampleRate = devConfig->getSampleRate();
|
||||
long currentSampleRate = wxGetApp().getSampleRate();
|
||||
long deviceSampleRate = devConfig->getSampleRate();
|
||||
|
||||
if (!deviceSampleRate) {
|
||||
deviceSampleRate = selDev->getSampleRateNear(SOAPY_SDR_RX, 0, currentSampleRate);
|
||||
@ -318,7 +318,7 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event) {
|
||||
wxGetApp().setDeviceArgs(settingArgs);
|
||||
wxGetApp().setStreamArgs(streamArgs);
|
||||
wxGetApp().setDevice(dev,0);
|
||||
|
||||
wxGetApp().notifyMainUIOfDeviceChange();
|
||||
Close();
|
||||
}
|
||||
event.Skip();
|
||||
@ -438,13 +438,14 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) {
|
||||
DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId());
|
||||
|
||||
std::string strRate = deviceArgs["sample_rate"].options[event.GetPropertyValue().GetInteger()];
|
||||
int srate = 0;
|
||||
long srate = 0;
|
||||
try {
|
||||
srate = std::stoi(strRate);
|
||||
srate = std::stol(strRate);
|
||||
devConfig->setSampleRate(srate);
|
||||
|
||||
if (dev->isActive() || !wxGetApp().getDevice()) {
|
||||
wxGetApp().setSampleRate(srate);
|
||||
wxGetApp().notifyMainUIOfDeviceChange();
|
||||
}
|
||||
} catch (std::invalid_argument e) {
|
||||
// nop
|
||||
|
@ -208,7 +208,12 @@ void SDRThread::readStream(SDRThreadIQDataQueue* iqDataOutQueue) {
|
||||
int n_stream_read = device->readStream(stream, buffs, mtElems, flags, timeNs);
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
@ -226,7 +231,7 @@ void SDRThread::readStream(SDRThreadIQDataQueue* iqDataOutQueue) {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} //end while
|
||||
|
||||
if (n_read > 0 && !stopping && !iqDataOutQueue->full()) {
|
||||
SDRThreadIQData *dataOut = buffers.getBuffer();
|
||||
@ -515,7 +520,7 @@ long long SDRThread::getOffset() {
|
||||
return offset.load();
|
||||
}
|
||||
|
||||
void SDRThread::setSampleRate(int rate) {
|
||||
void SDRThread::setSampleRate(long rate) {
|
||||
sampleRate.store(rate);
|
||||
rate_changed = true;
|
||||
DeviceConfig *devConfig = deviceConfig.load();
|
||||
@ -524,7 +529,7 @@ void SDRThread::setSampleRate(int rate) {
|
||||
}
|
||||
// std::cout << "Set sample rate: " << sampleRate.load() << std::endl;
|
||||
}
|
||||
int SDRThread::getSampleRate() {
|
||||
long SDRThread::getSampleRate() {
|
||||
return sampleRate.load();
|
||||
}
|
||||
|
||||
|
@ -70,8 +70,8 @@ public:
|
||||
void setOffset(long long ofs);
|
||||
long long getOffset();
|
||||
|
||||
void setSampleRate(int rate);
|
||||
int getSampleRate();
|
||||
void setSampleRate(long rate);
|
||||
long getSampleRate();
|
||||
|
||||
void setPPM(int ppm);
|
||||
int getPPM();
|
||||
@ -109,7 +109,7 @@ protected:
|
||||
std::map<std::string, std::string> settings;
|
||||
std::map<std::string, bool> settingChanged;
|
||||
|
||||
std::atomic<uint32_t> sampleRate;
|
||||
std::atomic_llong sampleRate;
|
||||
std::atomic_llong frequency, offset, lock_freq;
|
||||
std::atomic_int ppm, numElems, mtuElems, numChannels;
|
||||
std::atomic_bool hasPPM, hasHardwareDC;
|
||||
|
@ -170,6 +170,13 @@ void GainCanvas::setHelpTip(std::string tip) {
|
||||
|
||||
void GainCanvas::updateGainUI() {
|
||||
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());
|
||||
|
||||
gains = devInfo->getGains(SOAPY_SDR_RX, 0);
|
||||
|
@ -30,7 +30,7 @@ InteractiveCanvas::InteractiveCanvas(wxWindow *parent, int *dispAttrs) :
|
||||
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;
|
||||
centerFreq = center_freq_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;
|
||||
}
|
||||
|
||||
unsigned int InteractiveCanvas::getBandwidth() {
|
||||
long long InteractiveCanvas::getBandwidth() {
|
||||
if (isView) {
|
||||
return bandwidth;
|
||||
} else {
|
||||
|
@ -17,15 +17,15 @@ public:
|
||||
long long getFrequencyAt(float x);
|
||||
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();
|
||||
bool getViewState();
|
||||
|
||||
void setCenterFrequency(long long center_freq_in);
|
||||
long long getCenterFrequency();
|
||||
|
||||
void setBandwidth(unsigned int bandwidth_in);
|
||||
unsigned int getBandwidth();
|
||||
void setBandwidth(long long bandwidth_in);
|
||||
long long getBandwidth();
|
||||
|
||||
MouseTracker *getMouseTracker();
|
||||
bool isMouseInView();
|
||||
@ -59,8 +59,8 @@ protected:
|
||||
bool ctrlDown;
|
||||
|
||||
long long centerFreq;
|
||||
unsigned int bandwidth;
|
||||
unsigned int lastBandwidth;
|
||||
long long bandwidth;
|
||||
long long lastBandwidth;
|
||||
|
||||
bool isView;
|
||||
std::string lastToolTip;
|
||||
|
Loading…
Reference in New Issue
Block a user