Manual Gain Control :-)
- Disable AGC from settings menu - Requires latest SoapySDRPlay gain commits for SDRPlay
This commit is contained in:
parent
68d80bde9e
commit
ac93aa369b
|
@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 2.8)
|
||||||
|
|
||||||
SET(CUBICSDR_VERSION_MAJOR "0")
|
SET(CUBICSDR_VERSION_MAJOR "0")
|
||||||
SET(CUBICSDR_VERSION_MINOR "1")
|
SET(CUBICSDR_VERSION_MINOR "1")
|
||||||
SET(CUBICSDR_VERSION_PATCH "13")
|
SET(CUBICSDR_VERSION_PATCH "14")
|
||||||
SET(CUBICSDR_VERSION_REL "alpha")
|
SET(CUBICSDR_VERSION_REL "alpha")
|
||||||
SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}-${CUBICSDR_VERSION_REL}")
|
SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}-${CUBICSDR_VERSION_REL}")
|
||||||
|
|
||||||
|
@ -237,6 +237,7 @@ SET (cubicsdr_sources
|
||||||
src/visual/ScopeContext.cpp
|
src/visual/ScopeContext.cpp
|
||||||
src/visual/SpectrumCanvas.cpp
|
src/visual/SpectrumCanvas.cpp
|
||||||
src/visual/WaterfallCanvas.cpp
|
src/visual/WaterfallCanvas.cpp
|
||||||
|
src/visual/GainCanvas.cpp
|
||||||
src/process/VisualProcessor.cpp
|
src/process/VisualProcessor.cpp
|
||||||
src/process/ScopeVisualProcessor.cpp
|
src/process/ScopeVisualProcessor.cpp
|
||||||
src/process/SpectrumVisualProcessor.cpp
|
src/process/SpectrumVisualProcessor.cpp
|
||||||
|
@ -296,6 +297,7 @@ SET (cubicsdr_headers
|
||||||
src/visual/ScopeContext.h
|
src/visual/ScopeContext.h
|
||||||
src/visual/SpectrumCanvas.h
|
src/visual/SpectrumCanvas.h
|
||||||
src/visual/WaterfallCanvas.h
|
src/visual/WaterfallCanvas.h
|
||||||
|
src/visual/GainCanvas.h
|
||||||
src/process/VisualProcessor.h
|
src/process/VisualProcessor.h
|
||||||
src/process/ScopeVisualProcessor.h
|
src/process/ScopeVisualProcessor.h
|
||||||
src/process/SpectrumVisualProcessor.h
|
src/process/SpectrumVisualProcessor.h
|
||||||
|
|
|
@ -48,7 +48,7 @@ AppFrame::AppFrame() :
|
||||||
|
|
||||||
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
||||||
wxBoxSizer *demodVisuals = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer *demodVisuals = new wxBoxSizer(wxVERTICAL);
|
||||||
wxBoxSizer *demodTray = new wxBoxSizer(wxHORIZONTAL);
|
demodTray = new wxBoxSizer(wxHORIZONTAL);
|
||||||
wxBoxSizer *demodScopeTray = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer *demodScopeTray = new wxBoxSizer(wxVERTICAL);
|
||||||
|
|
||||||
int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
|
int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
|
||||||
|
@ -59,6 +59,13 @@ AppFrame::AppFrame() :
|
||||||
|
|
||||||
wxPanel *demodPanel = new wxPanel(mainSplitter, wxID_ANY);
|
wxPanel *demodPanel = new wxPanel(mainSplitter, wxID_ANY);
|
||||||
|
|
||||||
|
gainCanvas = new GainCanvas(demodPanel, attribList);
|
||||||
|
|
||||||
|
gainSizerItem = demodTray->Add(gainCanvas, 0, wxEXPAND | wxALL, 0);
|
||||||
|
gainSizerItem->Show(false);
|
||||||
|
gainSpacerItem = demodTray->AddSpacer(1);
|
||||||
|
gainSpacerItem->Show(false);
|
||||||
|
|
||||||
demodModeSelector = new ModeSelectorCanvas(demodPanel, attribList);
|
demodModeSelector = new ModeSelectorCanvas(demodPanel, attribList);
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_FM, "FM");
|
demodModeSelector->addChoice(DEMOD_TYPE_FM, "FM");
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_AM, "AM");
|
demodModeSelector->addChoice(DEMOD_TYPE_AM, "AM");
|
||||||
|
@ -252,6 +259,9 @@ AppFrame::AppFrame() :
|
||||||
|
|
||||||
menu->AppendSubMenu(dsMenu, "Direct Sampling");
|
menu->AppendSubMenu(dsMenu, "Direct Sampling");
|
||||||
|
|
||||||
|
agcMenuItem = menu->AppendCheckItem(wxID_AGC_CONTROL, "Automatic Gain");
|
||||||
|
agcMenuItem->Check(wxGetApp().getAGCMode());
|
||||||
|
|
||||||
menuBar->Append(menu, wxT("&Settings"));
|
menuBar->Append(menu, wxT("&Settings"));
|
||||||
|
|
||||||
menu = new wxMenu;
|
menu = new wxMenu;
|
||||||
|
@ -451,6 +461,22 @@ void AppFrame::initDeviceParams(SDRDeviceInfo *devInfo) {
|
||||||
if (!checked) {
|
if (!checked) {
|
||||||
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Check(true);
|
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Check(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!wxGetApp().getAGCMode()) {
|
||||||
|
gainSpacerItem->Show(true);
|
||||||
|
gainSizerItem->Show(true);
|
||||||
|
gainSizerItem->SetMinSize(devInfo->getRxChannel()->getGains().size()*50,0);
|
||||||
|
demodTray->Layout();
|
||||||
|
gainCanvas->updateGainUI();
|
||||||
|
gainCanvas->Refresh();
|
||||||
|
gainCanvas->Refresh();
|
||||||
|
} else {
|
||||||
|
gainSpacerItem->Show(false);
|
||||||
|
gainSizerItem->Show(false);
|
||||||
|
demodTray->Layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
agcMenuItem->Check(wxGetApp().getAGCMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -481,6 +507,22 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
||||||
wxGetApp().setSwapIQ(swap_state);
|
wxGetApp().setSwapIQ(swap_state);
|
||||||
wxGetApp().saveConfig();
|
wxGetApp().saveConfig();
|
||||||
iqSwapMenuItem->Check(swap_state);
|
iqSwapMenuItem->Check(swap_state);
|
||||||
|
} else if (event.GetId() == wxID_AGC_CONTROL) {
|
||||||
|
if (!wxGetApp().getAGCMode()) {
|
||||||
|
wxGetApp().setAGCMode(true);
|
||||||
|
gainSpacerItem->Show(false);
|
||||||
|
gainSizerItem->Show(false);
|
||||||
|
demodTray->Layout();
|
||||||
|
} else {
|
||||||
|
wxGetApp().setAGCMode(false);
|
||||||
|
gainSpacerItem->Show(true);
|
||||||
|
gainSizerItem->Show(true);
|
||||||
|
gainSizerItem->SetMinSize(wxGetApp().getDevice()->getRxChannel()->getGains().size()*40,0);
|
||||||
|
demodTray->Layout();
|
||||||
|
gainCanvas->updateGainUI();
|
||||||
|
gainCanvas->Refresh();
|
||||||
|
gainCanvas->Refresh();
|
||||||
|
}
|
||||||
} else if (event.GetId() == wxID_SDR_DEVICES) {
|
} else if (event.GetId() == wxID_SDR_DEVICES) {
|
||||||
wxGetApp().deviceSelector();
|
wxGetApp().deviceSelector();
|
||||||
} else if (event.GetId() == wxID_SET_PPM) {
|
} else if (event.GetId() == wxID_SET_PPM) {
|
||||||
|
@ -554,6 +596,9 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
||||||
if (event.GetId() >= wxID_THEME_DEFAULT && event.GetId() <= wxID_THEME_RADAR) {
|
if (event.GetId() >= wxID_THEME_DEFAULT && event.GetId() <= wxID_THEME_RADAR) {
|
||||||
demodTuner->Refresh();
|
demodTuner->Refresh();
|
||||||
demodModeSelector->Refresh();
|
demodModeSelector->Refresh();
|
||||||
|
waterfallSpeedMeter->Refresh();
|
||||||
|
spectrumAvgMeter->Refresh();
|
||||||
|
gainCanvas->setThemeColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event.GetId()) {
|
switch (event.GetId()) {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <wx/frame.h>
|
#include <wx/frame.h>
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
#include <wx/splitter.h>
|
#include <wx/splitter.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
|
||||||
#include "PrimaryGLContext.h"
|
#include "PrimaryGLContext.h"
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
#include "MeterCanvas.h"
|
#include "MeterCanvas.h"
|
||||||
#include "TuningCanvas.h"
|
#include "TuningCanvas.h"
|
||||||
#include "ModeSelectorCanvas.h"
|
#include "ModeSelectorCanvas.h"
|
||||||
|
#include "GainCanvas.h"
|
||||||
#include "FFTVisualDataThread.h"
|
#include "FFTVisualDataThread.h"
|
||||||
#include "SDRDeviceInfo.h"
|
#include "SDRDeviceInfo.h"
|
||||||
//#include "UITestCanvas.h"
|
//#include "UITestCanvas.h"
|
||||||
|
@ -27,6 +29,7 @@
|
||||||
#define wxID_SET_DS_Q 2006
|
#define wxID_SET_DS_Q 2006
|
||||||
#define wxID_SET_SWAP_IQ 2007
|
#define wxID_SET_SWAP_IQ 2007
|
||||||
#define wxID_SDR_DEVICES 2008
|
#define wxID_SDR_DEVICES 2008
|
||||||
|
#define wxID_AGC_CONTROL 2009
|
||||||
|
|
||||||
#define wxID_MAIN_SPLITTER 2050
|
#define wxID_MAIN_SPLITTER 2050
|
||||||
#define wxID_VIS_SPLITTER 2051
|
#define wxID_VIS_SPLITTER 2051
|
||||||
|
@ -83,7 +86,10 @@ private:
|
||||||
MeterCanvas *spectrumAvgMeter;
|
MeterCanvas *spectrumAvgMeter;
|
||||||
MeterCanvas *waterfallSpeedMeter;
|
MeterCanvas *waterfallSpeedMeter;
|
||||||
ModeSelectorCanvas *demodMuteButton;
|
ModeSelectorCanvas *demodMuteButton;
|
||||||
|
GainCanvas *gainCanvas;
|
||||||
|
wxSizerItem *gainSizerItem, *gainSpacerItem;
|
||||||
wxSplitterWindow *mainVisSplitter, *mainSplitter;
|
wxSplitterWindow *mainVisSplitter, *mainSplitter;
|
||||||
|
wxBoxSizer *demodTray;
|
||||||
|
|
||||||
DemodulatorInstance *activeDemodulator;
|
DemodulatorInstance *activeDemodulator;
|
||||||
|
|
||||||
|
@ -96,6 +102,7 @@ private:
|
||||||
std::map<int, wxMenuItem *> directSamplingMenuItems;
|
std::map<int, wxMenuItem *> directSamplingMenuItems;
|
||||||
wxMenuItem *iqSwapMenuItem;
|
wxMenuItem *iqSwapMenuItem;
|
||||||
wxMenu *sampleRateMenu;
|
wxMenu *sampleRateMenu;
|
||||||
|
wxMenuItem *agcMenuItem;
|
||||||
std::vector<long> sampleRates;
|
std::vector<long> sampleRates;
|
||||||
|
|
||||||
std::string currentSessionFile;
|
std::string currentSessionFile;
|
||||||
|
|
|
@ -115,6 +115,7 @@ long long strToFrequency(std::string freqStr) {
|
||||||
CubicSDR::CubicSDR() : appframe(NULL), m_glContext(NULL), frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE), directSamplingMode(0),
|
CubicSDR::CubicSDR() : appframe(NULL), m_glContext(NULL), frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE), directSamplingMode(0),
|
||||||
sdrThread(NULL), sdrPostThread(NULL), spectrumVisualThread(NULL), demodVisualThread(NULL), pipeSDRIQData(NULL), pipeIQVisualData(NULL), pipeAudioVisualData(NULL), t_SDR(NULL), t_PostSDR(NULL) {
|
sdrThread(NULL), sdrPostThread(NULL), spectrumVisualThread(NULL), demodVisualThread(NULL), pipeSDRIQData(NULL), pipeIQVisualData(NULL), pipeAudioVisualData(NULL), t_SDR(NULL), t_PostSDR(NULL) {
|
||||||
sampleRateInitialized.store(false);
|
sampleRateInitialized.store(false);
|
||||||
|
agcMode.store(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -597,3 +598,22 @@ void CubicSDR::setDeviceSelectorClosed() {
|
||||||
bool CubicSDR::isDeviceSelectorOpen() {
|
bool CubicSDR::isDeviceSelectorOpen() {
|
||||||
return deviceSelectorOpen.load();
|
return deviceSelectorOpen.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CubicSDR::setAGCMode(bool mode) {
|
||||||
|
agcMode.store(mode);
|
||||||
|
sdrThread->setAGCMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CubicSDR::getAGCMode() {
|
||||||
|
return agcMode.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CubicSDR::setGain(std::string name, float gain_in) {
|
||||||
|
sdrThread->setGain(name,gain_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CubicSDR::getGain(std::string name) {
|
||||||
|
return sdrThread->getGain(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,12 @@ public:
|
||||||
void setDeviceSelectorClosed();
|
void setDeviceSelectorClosed();
|
||||||
bool isDeviceSelectorOpen();
|
bool isDeviceSelectorOpen();
|
||||||
|
|
||||||
|
void setAGCMode(bool mode);
|
||||||
|
bool getAGCMode();
|
||||||
|
|
||||||
|
void setGain(std::string name, float gain_in);
|
||||||
|
float getGain(std::string name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AppFrame *appframe;
|
AppFrame *appframe;
|
||||||
AppConfig config;
|
AppConfig config;
|
||||||
|
@ -121,6 +127,7 @@ private:
|
||||||
int ppm, snap;
|
int ppm, snap;
|
||||||
long long sampleRate;
|
long long sampleRate;
|
||||||
int directSamplingMode;
|
int directSamplingMode;
|
||||||
|
std::atomic_bool agcMode;
|
||||||
|
|
||||||
SDRThread *sdrThread;
|
SDRThread *sdrThread;
|
||||||
SDREnumerator *sdrEnum;
|
SDREnumerator *sdrEnum;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "FFTDataDistributor.h"
|
#include "FFTDataDistributor.h"
|
||||||
|
|
||||||
FFTDataDistributor::FFTDataDistributor() : linesPerSecond(DEFAULT_WATERFALL_LPS), lineRateAccum(0.0), fftSize(DEFAULT_FFT_SIZE) {
|
FFTDataDistributor::FFTDataDistributor() : linesPerSecond(DEFAULT_WATERFALL_LPS), lineRateAccum(0.0), fftSize(DEFAULT_FFT_SIZE) {
|
||||||
|
bufferedItems = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFTDataDistributor::setFFTSize(int fftSize) {
|
void FFTDataDistributor::setFFTSize(int fftSize) {
|
||||||
|
|
|
@ -11,6 +11,10 @@ SDRDeviceRange::SDRDeviceRange(double low, double high) {
|
||||||
this->high = high;
|
this->high = high;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDRDeviceRange::SDRDeviceRange(std::string name, double low, double high) : SDRDeviceRange(low, high) {
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
double SDRDeviceRange::getLow() {
|
double SDRDeviceRange::getLow() {
|
||||||
return low;
|
return low;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +28,14 @@ void SDRDeviceRange::setHigh(double high) {
|
||||||
this->high = high;
|
this->high = high;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SDRDeviceRange::getName() {
|
||||||
|
return this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDRDeviceRange::setName(std::string name) {
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
SDRDeviceChannel::SDRDeviceChannel() {
|
SDRDeviceChannel::SDRDeviceChannel() {
|
||||||
hardwareDC = false;
|
hardwareDC = false;
|
||||||
hasCorr = false;
|
hasCorr = false;
|
||||||
|
@ -81,6 +93,18 @@ SDRDeviceRange &SDRDeviceChannel::getRFRange() {
|
||||||
return rangeRF;
|
return rangeRF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDRDeviceChannel::addGain(SDRDeviceRange range) {
|
||||||
|
gainInfo.push_back(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SDRDeviceRange> &SDRDeviceChannel::getGains() {
|
||||||
|
return gainInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDRDeviceChannel::addGain(std::string name, SoapySDR::Range range) {
|
||||||
|
gainInfo.push_back(SDRDeviceRange(name,range.minimum(),range.maximum()));
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<long> &SDRDeviceChannel::getSampleRates() {
|
std::vector<long> &SDRDeviceChannel::getSampleRates() {
|
||||||
return sampleRates;
|
return sampleRates;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,13 +36,17 @@ class SDRDeviceRange {
|
||||||
public:
|
public:
|
||||||
SDRDeviceRange();
|
SDRDeviceRange();
|
||||||
SDRDeviceRange(double low, double high);
|
SDRDeviceRange(double low, double high);
|
||||||
|
SDRDeviceRange(std::string name, double low, double high);
|
||||||
|
|
||||||
double getLow();
|
double getLow();
|
||||||
void setLow(double low);
|
void setLow(double low);
|
||||||
double getHigh();
|
double getHigh();
|
||||||
void setHigh(double high);
|
void setHigh(double high);
|
||||||
|
std::string getName();
|
||||||
|
void setName(std::string name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string name;
|
||||||
double low, high;
|
double low, high;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,6 +67,10 @@ public:
|
||||||
bool isRx();
|
bool isRx();
|
||||||
void setRx(bool rx);
|
void setRx(bool rx);
|
||||||
|
|
||||||
|
void addGain(SDRDeviceRange range);
|
||||||
|
void addGain(std::string name, SoapySDR::Range range);
|
||||||
|
std::vector<SDRDeviceRange> &getGains();
|
||||||
|
|
||||||
SDRDeviceRange &getGain();
|
SDRDeviceRange &getGain();
|
||||||
SDRDeviceRange &getLNAGain();
|
SDRDeviceRange &getLNAGain();
|
||||||
SDRDeviceRange &getFreqRange();
|
SDRDeviceRange &getFreqRange();
|
||||||
|
@ -89,6 +97,7 @@ private:
|
||||||
std::vector<long> sampleRates;
|
std::vector<long> sampleRates;
|
||||||
std::vector<long long> filterBandwidths;
|
std::vector<long long> filterBandwidths;
|
||||||
SoapySDR::ArgInfoList streamArgInfo;
|
SoapySDR::ArgInfoList streamArgInfo;
|
||||||
|
std::vector<SDRDeviceRange> gainInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,12 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
|
||||||
|
|
||||||
chan->setStreamArgsInfo(device->getStreamArgsInfo(SOAPY_SDR_RX, i));
|
chan->setStreamArgsInfo(device->getStreamArgsInfo(SOAPY_SDR_RX, i));
|
||||||
|
|
||||||
|
std::vector<std::string> gainNames = device->listGains(SOAPY_SDR_RX, i);
|
||||||
|
|
||||||
|
for (std::vector<std::string>::iterator gname = gainNames.begin(); gname!= gainNames.end(); gname++) {
|
||||||
|
chan->addGain((*gname),device->getGainRange(SOAPY_SDR_RX, i, (*gname)));
|
||||||
|
}
|
||||||
|
|
||||||
dev->addChannel(chan);
|
dev->addChannel(chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -332,6 +332,18 @@ void SDRPostThread::run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool doUpdate = false;
|
||||||
|
for (int j = 0; j < nRunDemods; j++) {
|
||||||
|
DemodulatorInstance *demod = runDemods[j];
|
||||||
|
if (abs(frequency - demod->getFrequency()) > (sampleRate / 2)) {
|
||||||
|
doUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doUpdate) {
|
||||||
|
updateActiveDemodulators();
|
||||||
|
}
|
||||||
|
|
||||||
busy_demod.unlock();
|
busy_demod.unlock();
|
||||||
}
|
}
|
||||||
data_in->decRefCount();
|
data_in->decRefCount();
|
||||||
|
|
|
@ -33,6 +33,10 @@ SDRThread::SDRThread() : IOThread() {
|
||||||
numChannels.store(8);
|
numChannels.store(8);
|
||||||
hasDirectSampling.store(false);
|
hasDirectSampling.store(false);
|
||||||
hasIQSwap.store(false);
|
hasIQSwap.store(false);
|
||||||
|
|
||||||
|
agc_mode.store(true);
|
||||||
|
agc_mode_changed.store(false);
|
||||||
|
gain_value_changed.store(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDRThread::~SDRThread() {
|
SDRThread::~SDRThread() {
|
||||||
|
@ -90,7 +94,7 @@ void SDRThread::init() {
|
||||||
hasIQSwap.store(true);
|
hasIQSwap.store(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
device->setGainMode(SOAPY_SDR_RX,0,true);
|
device->setGainMode(SOAPY_SDR_RX,0,agc_mode.load());
|
||||||
|
|
||||||
numChannels.store(getOptimalChannelCount(sampleRate.load()));
|
numChannels.store(getOptimalChannelCount(sampleRate.load()));
|
||||||
numElems.store(getOptimalElementCount(sampleRate.load(), 30));
|
numElems.store(getOptimalElementCount(sampleRate.load(), 30));
|
||||||
|
@ -152,6 +156,8 @@ void SDRThread::readLoop() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateGains();
|
||||||
|
|
||||||
while (!terminated.load()) {
|
while (!terminated.load()) {
|
||||||
if (offset_changed.load()) {
|
if (offset_changed.load()) {
|
||||||
if (!freq_changed.load()) {
|
if (!freq_changed.load()) {
|
||||||
|
@ -186,12 +192,48 @@ void SDRThread::readLoop() {
|
||||||
device->writeSetting("iq_swap", iq_swap.load()?"true":"false");
|
device->writeSetting("iq_swap", iq_swap.load()?"true":"false");
|
||||||
iq_swap_changed.store(false);
|
iq_swap_changed.store(false);
|
||||||
}
|
}
|
||||||
|
if (agc_mode_changed.load()) {
|
||||||
|
SDRDeviceInfo *devInfo = deviceInfo.load();
|
||||||
|
|
||||||
|
device->setGainMode(SOAPY_SDR_RX,devInfo->getRxChannel()->getChannel(),agc_mode.load());
|
||||||
|
agc_mode_changed.store(false);
|
||||||
|
if (!agc_mode.load()) {
|
||||||
|
updateGains();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gain_value_changed.load() && !agc_mode.load()) {
|
||||||
|
SDRDeviceInfo *devInfo = deviceInfo.load();
|
||||||
|
|
||||||
|
for (std::map<std::string,std::atomic_bool>::iterator gci = gainChanged.begin(); gci != gainChanged.end(); gci++) {
|
||||||
|
if (gci->second.load()) {
|
||||||
|
device->setGain(SOAPY_SDR_RX, devInfo->getRxChannel()->getChannel(), gci->first, gainValues[gci->first]);
|
||||||
|
gainChanged[gci->first] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gain_value_changed.store(false);
|
||||||
|
}
|
||||||
|
|
||||||
readStream(iqDataOutQueue);
|
readStream(iqDataOutQueue);
|
||||||
}
|
}
|
||||||
buffers.purge();
|
buffers.purge();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDRThread::updateGains() {
|
||||||
|
SDRDeviceInfo *devInfo = deviceInfo.load();
|
||||||
|
|
||||||
|
gainValues.erase(gainValues.begin(),gainValues.end());
|
||||||
|
gainChanged.erase(gainChanged.begin(),gainChanged.end());
|
||||||
|
|
||||||
|
std::vector<SDRDeviceRange> gains = devInfo->getRxChannel()->getGains();
|
||||||
|
for (std::vector<SDRDeviceRange>::iterator gi = gains.begin(); gi != gains.end(); gi++) {
|
||||||
|
gainValues[(*gi).getName()] = device->getGain(SOAPY_SDR_RX, devInfo->getRxChannel()->getChannel(), (*gi).getName());
|
||||||
|
gainChanged[(*gi).getName()] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gain_value_changed.store(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SDRThread::run() {
|
void SDRThread::run() {
|
||||||
//#ifdef __APPLE__
|
//#ifdef __APPLE__
|
||||||
|
@ -320,3 +362,22 @@ void SDRThread::setIQSwap(bool iqSwap) {
|
||||||
bool SDRThread::getIQSwap() {
|
bool SDRThread::getIQSwap() {
|
||||||
return iq_swap.load();
|
return iq_swap.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDRThread::setAGCMode(bool mode) {
|
||||||
|
agc_mode.store(mode);
|
||||||
|
agc_mode_changed.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDRThread::getAGCMode() {
|
||||||
|
return agc_mode.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDRThread::setGain(std::string name, float value) {
|
||||||
|
gainValues[name].store(value);
|
||||||
|
gainChanged[name].store(true);
|
||||||
|
gain_value_changed.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
float SDRThread::getGain(std::string name) {
|
||||||
|
return gainValues[name].load();
|
||||||
|
}
|
||||||
|
|
|
@ -74,8 +74,16 @@ public:
|
||||||
|
|
||||||
void setIQSwap(bool iqSwap);
|
void setIQSwap(bool iqSwap);
|
||||||
bool getIQSwap();
|
bool getIQSwap();
|
||||||
|
|
||||||
|
void setAGCMode(bool mode);
|
||||||
|
bool getAGCMode();
|
||||||
|
|
||||||
|
void setGain(std::string name, float value);
|
||||||
|
float getGain(std::string name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void updateGains();
|
||||||
|
|
||||||
SoapySDR::Stream *stream;
|
SoapySDR::Stream *stream;
|
||||||
SoapySDR::Device *device;
|
SoapySDR::Device *device;
|
||||||
void *buffs[1];
|
void *buffs[1];
|
||||||
|
@ -88,6 +96,8 @@ protected:
|
||||||
std::atomic_llong frequency, offset;
|
std::atomic_llong frequency, offset;
|
||||||
std::atomic_int ppm, direct_sampling_mode, numElems, numChannels;
|
std::atomic_int ppm, direct_sampling_mode, numElems, numChannels;
|
||||||
std::atomic_bool hasPPM, hasHardwareDC, hasDirectSampling, hasIQSwap;
|
std::atomic_bool hasPPM, hasHardwareDC, hasDirectSampling, hasIQSwap;
|
||||||
std::atomic_bool iq_swap, rate_changed, freq_changed, offset_changed,
|
std::atomic_bool iq_swap, agc_mode, rate_changed, freq_changed, offset_changed,
|
||||||
ppm_changed, direct_sampling_changed, device_changed, iq_swap_changed;
|
ppm_changed, direct_sampling_changed, device_changed, iq_swap_changed, agc_mode_changed, gain_value_changed;
|
||||||
|
std::map<std::string,std::atomic<float> > gainValues;
|
||||||
|
std::map<std::string,std::atomic_bool> gainChanged;
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
using namespace CubicVR;
|
using namespace CubicVR;
|
||||||
|
|
||||||
GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), transform(mat4::identity()) {
|
GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), visible(true), transform(mat4::identity()) {
|
||||||
pos[0] = 0.0f;
|
pos[0] = 0.0f;
|
||||||
pos[1] = 0.0f;
|
pos[1] = 0.0f;
|
||||||
rot[0] = 0.0f;
|
rot[0] = 0.0f;
|
||||||
|
@ -19,6 +19,8 @@ GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), transf
|
||||||
setCoordinateSystem(GLPANEL_Y_UP);
|
setCoordinateSystem(GLPANEL_Y_UP);
|
||||||
setMarginPx(0);
|
setMarginPx(0);
|
||||||
setBorderPx(0);
|
setBorderPx(0);
|
||||||
|
srcBlend = GL_SRC_ALPHA;
|
||||||
|
dstBlend = GL_ONE_MINUS_SRC_ALPHA;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLPanel::genArrays() {
|
void GLPanel::genArrays() {
|
||||||
|
@ -174,6 +176,19 @@ void GLPanel::setCoordinateSystem(GLPanelCoordinateSystem coord_in) {
|
||||||
genArrays();
|
genArrays();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLPanel::hitTest(CubicVR::vec2 pos, CubicVR::vec2 &result) {
|
||||||
|
CubicVR::vec4 hitPos = CubicVR::mat4::vec4_multiply(CubicVR::vec4(pos.x, pos.y, 0.0, 1.0), transformInverse);
|
||||||
|
|
||||||
|
if (hitPos.x >= -1.0 && hitPos.x <= 1.0 && hitPos.y >= -1.0 && hitPos.y <= 1.0) {
|
||||||
|
result.x = hitPos.x;
|
||||||
|
result.y = hitPos.y;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLPanel::setFill(GLPanelFillType fill_mode) {
|
void GLPanel::setFill(GLPanelFillType fill_mode) {
|
||||||
fillType = fill_mode;
|
fillType = fill_mode;
|
||||||
genArrays();
|
genArrays();
|
||||||
|
@ -210,6 +225,11 @@ void GLPanel::setBorderPx(float bordl, float bordr, float bordt, float bordb) {
|
||||||
borderPx.bottom = bordb;
|
borderPx.bottom = bordb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLPanel::setBlend(GLuint src, GLuint dst) {
|
||||||
|
srcBlend = src;
|
||||||
|
dstBlend = dst;
|
||||||
|
}
|
||||||
|
|
||||||
void GLPanel::addChild(GLPanel *childPanel) {
|
void GLPanel::addChild(GLPanel *childPanel) {
|
||||||
std::vector<GLPanel *>::iterator i = std::find(children.begin(), children.end(), childPanel);
|
std::vector<GLPanel *>::iterator i = std::find(children.begin(), children.end(), childPanel);
|
||||||
|
|
||||||
|
@ -278,6 +298,8 @@ void GLPanel::calcTransform(mat4 transform_in) {
|
||||||
if (marginPx) {
|
if (marginPx) {
|
||||||
transform *= mat4::scale(1.0 - marginPx * 2.0 * pvec.x / size[0], 1.0 - marginPx * 2.0 * pvec.y / size[1], 1);
|
transform *= mat4::scale(1.0 - marginPx * 2.0 * pvec.x / size[0], 1.0 - marginPx * 2.0 * pvec.y / size[1], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transformInverse = CubicVR::mat4::inverse(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLPanel::draw() {
|
void GLPanel::draw() {
|
||||||
|
@ -285,9 +307,9 @@ void GLPanel::draw() {
|
||||||
|
|
||||||
glLoadMatrixf(transform);
|
glLoadMatrixf(transform);
|
||||||
|
|
||||||
if (fillType != GLPANEL_FILL_NONE) {
|
if (fillType != GLPANEL_FILL_NONE && visible) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(srcBlend, dstBlend);
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
glVertexPointer(2, GL_FLOAT, 0, &glPoints[0]);
|
glVertexPointer(2, GL_FLOAT, 0, &glPoints[0]);
|
||||||
|
|
|
@ -45,8 +45,8 @@ public:
|
||||||
GLPanelEdges borderPx;
|
GLPanelEdges borderPx;
|
||||||
RGBA4f fill[2];
|
RGBA4f fill[2];
|
||||||
RGBA4f borderColor;
|
RGBA4f borderColor;
|
||||||
bool contentsVisible;
|
bool contentsVisible, visible;
|
||||||
CubicVR::mat4 transform;
|
CubicVR::mat4 transform, transformInverse;
|
||||||
CubicVR::mat4 localTransform;
|
CubicVR::mat4 localTransform;
|
||||||
float min, mid, max;
|
float min, mid, max;
|
||||||
// screen dimensions
|
// screen dimensions
|
||||||
|
@ -55,7 +55,8 @@ public:
|
||||||
CubicVR::vec2 umin, umax, ucenter;
|
CubicVR::vec2 umin, umax, ucenter;
|
||||||
// pixel dimensions
|
// pixel dimensions
|
||||||
CubicVR::vec2 pdim, pvec;
|
CubicVR::vec2 pdim, pvec;
|
||||||
|
GLuint srcBlend, dstBlend;
|
||||||
|
|
||||||
std::vector<GLPanel *> children;
|
std::vector<GLPanel *> children;
|
||||||
|
|
||||||
GLPanel();
|
GLPanel();
|
||||||
|
@ -68,6 +69,8 @@ public:
|
||||||
float getHeightPx();
|
float getHeightPx();
|
||||||
void setCoordinateSystem(GLPanelCoordinateSystem coord);
|
void setCoordinateSystem(GLPanelCoordinateSystem coord);
|
||||||
|
|
||||||
|
bool hitTest(CubicVR::vec2 pos, CubicVR::vec2 &result);
|
||||||
|
|
||||||
void setFill(GLPanelFillType fill_mode);
|
void setFill(GLPanelFillType fill_mode);
|
||||||
void setFillColor(RGBA4f color1);
|
void setFillColor(RGBA4f color1);
|
||||||
void setFillColor(RGBA4f color1, RGBA4f color2);
|
void setFillColor(RGBA4f color1, RGBA4f color2);
|
||||||
|
@ -77,6 +80,8 @@ public:
|
||||||
void setBorderPx(float bord);
|
void setBorderPx(float bord);
|
||||||
void setBorderPx(float bordl, float bordr, float bordt, float bordb);
|
void setBorderPx(float bordl, float bordr, float bordt, float bordb);
|
||||||
|
|
||||||
|
void setBlend(GLuint src, GLuint dst);
|
||||||
|
|
||||||
void addChild(GLPanel *childPanel);
|
void addChild(GLPanel *childPanel);
|
||||||
void removeChild(GLPanel *childPanel);
|
void removeChild(GLPanel *childPanel);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,305 @@
|
||||||
|
#include "GainCanvas.h"
|
||||||
|
|
||||||
|
#include "wx/wxprec.h"
|
||||||
|
|
||||||
|
#ifndef WX_PRECOMP
|
||||||
|
#include "wx/wx.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !wxUSE_GLCANVAS
|
||||||
|
#error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "CubicSDR.h"
|
||||||
|
#include "CubicSDRDefs.h"
|
||||||
|
#include "AppFrame.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
wxBEGIN_EVENT_TABLE(GainCanvas, wxGLCanvas) EVT_PAINT(GainCanvas::OnPaint)
|
||||||
|
EVT_IDLE(GainCanvas::OnIdle)
|
||||||
|
EVT_MOTION(GainCanvas::OnMouseMoved)
|
||||||
|
EVT_LEFT_DOWN(GainCanvas::OnMouseDown)
|
||||||
|
EVT_LEFT_UP(GainCanvas::OnMouseReleased)
|
||||||
|
EVT_LEAVE_WINDOW(GainCanvas::OnMouseLeftWindow)
|
||||||
|
EVT_ENTER_WINDOW(GainCanvas::OnMouseEnterWindow)
|
||||||
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
|
GainCanvas::GainCanvas(wxWindow *parent, int *attribList) :
|
||||||
|
InteractiveCanvas(parent, attribList) {
|
||||||
|
|
||||||
|
glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this));
|
||||||
|
bgPanel.setCoordinateSystem(GLPanel::GLPANEL_Y_UP);
|
||||||
|
bgPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_X);
|
||||||
|
|
||||||
|
numGains = 1;
|
||||||
|
spacing = 2.0/numGains;
|
||||||
|
barWidth = (1.0/numGains)*0.8;
|
||||||
|
startPos = spacing/2.0;
|
||||||
|
barHeight = 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
GainCanvas::~GainCanvas() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||||
|
wxPaintDC dc(this);
|
||||||
|
const wxSize ClientSize = GetClientSize();
|
||||||
|
|
||||||
|
glContext->SetCurrent(*this);
|
||||||
|
initGLExtensions();
|
||||||
|
|
||||||
|
glViewport(0, 0, ClientSize.x, ClientSize.y);
|
||||||
|
|
||||||
|
float i = 0;
|
||||||
|
for (std::vector<GainInfo *>::iterator gi = gainInfo.begin(); gi != gainInfo.end(); gi++) {
|
||||||
|
GainInfo *gInfo = (*gi);
|
||||||
|
float midPos = -1.0+startPos+spacing*i;
|
||||||
|
|
||||||
|
gInfo->labelPanel.setSize(spacing/2.0,(15.0/float(ClientSize.y)));
|
||||||
|
gInfo->labelPanel.setPosition(midPos, -barHeight-(20.0/float(ClientSize.y)));
|
||||||
|
|
||||||
|
gInfo->valuePanel.setSize(spacing/2.0,(15.0/float(ClientSize.y)));
|
||||||
|
gInfo->valuePanel.setPosition(midPos, barHeight+(20.0/float(ClientSize.y)));
|
||||||
|
|
||||||
|
i+=1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bgPanel.draw();
|
||||||
|
|
||||||
|
SwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainCanvas::OnIdle(wxIdleEvent &event) {
|
||||||
|
if (mouseTracker.mouseInView()) {
|
||||||
|
Refresh();
|
||||||
|
} else {
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<GainInfo *>::iterator gi = gainInfo.begin(); gi != gainInfo.end(); gi++) {
|
||||||
|
GainInfo *gInfo = (*gi);
|
||||||
|
if (gInfo->changed) {
|
||||||
|
wxGetApp().setGain(gInfo->name, gInfo->current);
|
||||||
|
gInfo->changed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GainCanvas::GetPanelHit(CubicVR::vec2 &result) {
|
||||||
|
std::vector<GainInfo *>::iterator gi;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (gi = gainInfo.begin(); gi != gainInfo.end(); gi++) {
|
||||||
|
GainInfo *gInfo = (*gi);
|
||||||
|
|
||||||
|
CubicVR::vec2 hitResult;
|
||||||
|
if (gInfo->panel.hitTest(CubicVR::vec2((mouseTracker.getMouseX()-0.5)*2.0, (mouseTracker.getMouseY()-0.5)*2.0), hitResult)) {
|
||||||
|
// std::cout << "Hit #" << i << " result: " << hitResult << std::endl;
|
||||||
|
result = (hitResult + CubicVR::vec2(1.0,1.0)) * 0.5;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GainCanvas::SetLevel() {
|
||||||
|
CubicVR::vec2 hitResult;
|
||||||
|
int panelHit = GetPanelHit(hitResult);
|
||||||
|
|
||||||
|
if (panelHit >= 0) {
|
||||||
|
gainInfo[panelHit]->levelPanel.setSize(1.0, hitResult.y);
|
||||||
|
gainInfo[panelHit]->levelPanel.setPosition(0.0, (-1.0+(hitResult.y)));
|
||||||
|
gainInfo[panelHit]->current = gainInfo[panelHit]->low+(hitResult.y * (gainInfo[panelHit]->high-gainInfo[panelHit]->low));
|
||||||
|
gainInfo[panelHit]->changed = true;
|
||||||
|
gainInfo[panelHit]->valuePanel.setText(std::to_string(int(gainInfo[panelHit]->current)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainCanvas::OnMouseMoved(wxMouseEvent& event) {
|
||||||
|
InteractiveCanvas::OnMouseMoved(event);
|
||||||
|
|
||||||
|
CubicVR::vec2 hitResult;
|
||||||
|
int panelHit = GetPanelHit(hitResult);
|
||||||
|
|
||||||
|
if (panelHit >= 0) {
|
||||||
|
gainInfo[panelHit]->highlightPanel.setSize(1.0, hitResult.y);
|
||||||
|
gainInfo[panelHit]->highlightPanel.setPosition(0.0, (-1.0+(hitResult.y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (std::vector<GainInfo *>::iterator gi = gainInfo.begin(); gi != gainInfo.end(); gi++) {
|
||||||
|
(*gi)->highlightPanel.visible = (i==panelHit);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseTracker.mouseDown()) {
|
||||||
|
SetLevel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainCanvas::OnMouseDown(wxMouseEvent& event) {
|
||||||
|
InteractiveCanvas::OnMouseDown(event);
|
||||||
|
SetLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
|
||||||
|
InteractiveCanvas::OnMouseWheelMoved(event);
|
||||||
|
// Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainCanvas::OnMouseReleased(wxMouseEvent& event) {
|
||||||
|
InteractiveCanvas::OnMouseReleased(event);
|
||||||
|
// Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
|
||||||
|
InteractiveCanvas::OnMouseLeftWindow(event);
|
||||||
|
SetCursor(wxCURSOR_CROSS);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (std::vector<GainInfo *>::iterator gi = gainInfo.begin(); gi != gainInfo.end(); gi++) {
|
||||||
|
(*gi)->highlightPanel.visible = false;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainCanvas::OnMouseEnterWindow(wxMouseEvent& event) {
|
||||||
|
InteractiveCanvas::mouseTracker.OnMouseEnterWindow(event);
|
||||||
|
SetCursor(wxCURSOR_CROSS);
|
||||||
|
// Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void GainCanvas::setHelpTip(std::string tip) {
|
||||||
|
helpTip = tip;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainCanvas::updateGainUI() {
|
||||||
|
const wxSize ClientSize = GetClientSize();
|
||||||
|
|
||||||
|
SDRDeviceInfo *devInfo = wxGetApp().getDevice();
|
||||||
|
|
||||||
|
std::vector<SDRDeviceRange> &gains = devInfo->getRxChannel()->getGains();
|
||||||
|
std::vector<SDRDeviceRange>::iterator gi;
|
||||||
|
|
||||||
|
numGains = gains.size();
|
||||||
|
float i = 0;
|
||||||
|
|
||||||
|
if (!numGains) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spacing = 2.0/numGains;
|
||||||
|
barWidth = (1.0/numGains)*0.7;
|
||||||
|
startPos = spacing/2.0;
|
||||||
|
barHeight = 0.8;
|
||||||
|
|
||||||
|
RGBA4f c1, c2;
|
||||||
|
|
||||||
|
while (gainInfo.size()) {
|
||||||
|
GainInfo *giDel;
|
||||||
|
giDel = gainInfo.back();
|
||||||
|
gainInfo.pop_back();
|
||||||
|
|
||||||
|
giDel->panel.removeChild(&giDel->levelPanel);
|
||||||
|
bgPanel.removeChild(&(giDel->labelPanel));
|
||||||
|
bgPanel.removeChild(&(giDel->valuePanel));
|
||||||
|
bgPanel.removeChild(&(giDel->panel));
|
||||||
|
delete giDel;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (gi = gains.begin(); gi != gains.end(); gi++) {
|
||||||
|
GainInfo *gInfo = new GainInfo;
|
||||||
|
float midPos = -1.0+startPos+spacing*i;
|
||||||
|
|
||||||
|
gInfo->name = (*gi).getName();
|
||||||
|
gInfo->low = (*gi).getLow();
|
||||||
|
gInfo->high = (*gi).getHigh();
|
||||||
|
gInfo->current = wxGetApp().getGain(gInfo->name);
|
||||||
|
|
||||||
|
gInfo->panel.setBorderPx(1);
|
||||||
|
gInfo->panel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X);
|
||||||
|
gInfo->panel.setPosition(midPos, 0);
|
||||||
|
gInfo->panel.setSize(barWidth, barHeight);
|
||||||
|
gInfo->panel.setBlend(GL_ONE, GL_ONE);
|
||||||
|
|
||||||
|
gInfo->levelPanel.setBorderPx(0);
|
||||||
|
gInfo->levelPanel.setMarginPx(1);
|
||||||
|
gInfo->levelPanel.setSize(1.0,0.8);
|
||||||
|
float levelVal = float(gInfo->current-gInfo->low)/float(gInfo->high-gInfo->low);
|
||||||
|
gInfo->levelPanel.setSize(1.0, levelVal);
|
||||||
|
gInfo->levelPanel.setPosition(0.0, (-1.0+(levelVal)));
|
||||||
|
gInfo->levelPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X);
|
||||||
|
gInfo->levelPanel.setBlend(GL_ONE, GL_ONE);
|
||||||
|
|
||||||
|
gInfo->panel.addChild(&gInfo->levelPanel);
|
||||||
|
|
||||||
|
gInfo->highlightPanel.setBorderPx(0);
|
||||||
|
gInfo->highlightPanel.setMarginPx(1);
|
||||||
|
gInfo->highlightPanel.setSize(1.0,0.8);
|
||||||
|
gInfo->highlightPanel.setPosition(0.0,-0.2);
|
||||||
|
gInfo->highlightPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X);
|
||||||
|
gInfo->highlightPanel.setBlend(GL_ONE, GL_ONE);
|
||||||
|
gInfo->highlightPanel.visible = false;
|
||||||
|
|
||||||
|
gInfo->panel.addChild(&gInfo->highlightPanel);
|
||||||
|
|
||||||
|
gInfo->labelPanel.setSize(spacing/2.0,(15.0/float(ClientSize.y)));
|
||||||
|
gInfo->labelPanel.setPosition(midPos, -barHeight-(20.0/float(ClientSize.y)));
|
||||||
|
gInfo->labelPanel.setText((*gi).getName());
|
||||||
|
gInfo->labelPanel.setFill(GLPanel::GLPANEL_FILL_NONE);
|
||||||
|
|
||||||
|
bgPanel.addChild(&(gInfo->labelPanel));
|
||||||
|
|
||||||
|
gInfo->valuePanel.setSize(spacing/2.0,(15.0/float(ClientSize.y)));
|
||||||
|
gInfo->valuePanel.setPosition(midPos, barHeight+(20.0/float(ClientSize.y)));
|
||||||
|
gInfo->valuePanel.setText(std::to_string(int(gInfo->current)));
|
||||||
|
gInfo->valuePanel.setFill(GLPanel::GLPANEL_FILL_NONE);
|
||||||
|
|
||||||
|
bgPanel.addChild(&(gInfo->valuePanel));
|
||||||
|
|
||||||
|
bgPanel.addChild(&(gInfo->panel));
|
||||||
|
gainInfo.push_back(gInfo);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
setThemeColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainCanvas::setThemeColors() {
|
||||||
|
std::vector<GainInfo *>::iterator gi;
|
||||||
|
|
||||||
|
RGBA4f c1, c2;
|
||||||
|
|
||||||
|
c1 = ThemeMgr::mgr.currentTheme->generalBackground;
|
||||||
|
c2 = ThemeMgr::mgr.currentTheme->generalBackground * 0.5;
|
||||||
|
|
||||||
|
bgPanel.setFillColor(c1, c2);
|
||||||
|
|
||||||
|
for (gi = gainInfo.begin(); gi != gainInfo.end(); gi++) {
|
||||||
|
GainInfo *gInfo = (*gi);
|
||||||
|
|
||||||
|
c1 = ThemeMgr::mgr.currentTheme->generalBackground;
|
||||||
|
c2 = ThemeMgr::mgr.currentTheme->generalBackground * 0.5;
|
||||||
|
c1.a = 1.0;
|
||||||
|
c2.a = 1.0;
|
||||||
|
gInfo->panel.setFillColor(c1, c2);
|
||||||
|
|
||||||
|
c1 = ThemeMgr::mgr.currentTheme->meterLevel * 0.5;
|
||||||
|
c2 = ThemeMgr::mgr.currentTheme->meterLevel;
|
||||||
|
c1.a = 1.0;
|
||||||
|
c2.a = 1.0;
|
||||||
|
gInfo->levelPanel.setFillColor(c1, c2);
|
||||||
|
|
||||||
|
c1 = RGBA4f(0.3,0.3,0.3,1.0);
|
||||||
|
c2 = RGBA4f(0.65,0.65,0.65,1.0);;
|
||||||
|
gInfo->highlightPanel.setFillColor(c1, c2);
|
||||||
|
}
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wx/glcanvas.h"
|
||||||
|
#include "wx/timer.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#include "InteractiveCanvas.h"
|
||||||
|
#include "MouseTracker.h"
|
||||||
|
#include "GLPanel.h"
|
||||||
|
#include "PrimaryGLContext.h"
|
||||||
|
|
||||||
|
#include "fftw3.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
class GainInfo {
|
||||||
|
public:
|
||||||
|
std::string name;
|
||||||
|
float low, high, current;
|
||||||
|
bool changed;
|
||||||
|
GLPanel panel;
|
||||||
|
GLPanel levelPanel;
|
||||||
|
GLPanel highlightPanel;
|
||||||
|
GLTextPanel labelPanel;
|
||||||
|
GLTextPanel valuePanel;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GainCanvas: public InteractiveCanvas {
|
||||||
|
public:
|
||||||
|
GainCanvas(wxWindow *parent, int *attribList = NULL);
|
||||||
|
~GainCanvas();
|
||||||
|
|
||||||
|
void setHelpTip(std::string tip);
|
||||||
|
void updateGainUI();
|
||||||
|
void setThemeColors();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnPaint(wxPaintEvent& event);
|
||||||
|
void OnIdle(wxIdleEvent &event);
|
||||||
|
|
||||||
|
int GetPanelHit(CubicVR::vec2 &result);
|
||||||
|
void SetLevel();
|
||||||
|
|
||||||
|
void OnShow(wxShowEvent& event);
|
||||||
|
void OnMouseMoved(wxMouseEvent& event);
|
||||||
|
void OnMouseDown(wxMouseEvent& event);
|
||||||
|
void OnMouseWheelMoved(wxMouseEvent& event);
|
||||||
|
void OnMouseReleased(wxMouseEvent& event);
|
||||||
|
void OnMouseEnterWindow(wxMouseEvent& event);
|
||||||
|
void OnMouseLeftWindow(wxMouseEvent& event);
|
||||||
|
|
||||||
|
PrimaryGLContext *glContext;
|
||||||
|
std::string helpTip;
|
||||||
|
std::vector<GainInfo *> gainInfo;
|
||||||
|
GLPanel bgPanel;
|
||||||
|
|
||||||
|
float spacing, barWidth, startPos, barHeight, numGains;
|
||||||
|
wxSize clientSize;
|
||||||
|
//
|
||||||
|
wxDECLARE_EVENT_TABLE();
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue