Zerospan mode for spectrum analyzer mode
This commit is contained in:
parent
6adac7ebb4
commit
8492b38936
Binary file not shown.
@ -573,6 +573,9 @@ These commands change or query spectrum analyzer settings. Although most of them
|
|||||||
\subsubsection{SA:FREQuency:FULL}
|
\subsubsection{SA:FREQuency:FULL}
|
||||||
\event{Sets the device to the maximum span possible}{SA:FREQuency:FULL}{None}
|
\event{Sets the device to the maximum span possible}{SA:FREQuency:FULL}{None}
|
||||||
|
|
||||||
|
\subsubsection{SA:FREQuency:ZERO}
|
||||||
|
\event{Sets the device to zero span mode}{SA:FREQuency:ZERO}{None}
|
||||||
|
|
||||||
\subsubsection{SA:ACQuisition:RBW}
|
\subsubsection{SA:ACQuisition:RBW}
|
||||||
\event{Sets the resolution bandwidth}{SA:ACQuisition:IFBW}{<resolution bandwidth>, in Hz}
|
\event{Sets the resolution bandwidth}{SA:ACQuisition:IFBW}{<resolution bandwidth>, in Hz}
|
||||||
\query{Queries the currently selected resolution bandwidth}{SA:ACQuisition:IFBW?}{None}{resolution bandwidth in Hz}
|
\query{Queries the currently selected resolution bandwidth}{SA:ACQuisition:IFBW?}{None}{resolution bandwidth in Hz}
|
||||||
|
@ -135,6 +135,13 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
|||||||
connect(bZoomOut, &QPushButton::clicked, this, &SpectrumAnalyzer::SpanZoomOut);
|
connect(bZoomOut, &QPushButton::clicked, this, &SpectrumAnalyzer::SpanZoomOut);
|
||||||
tb_sweep->addWidget(bZoomOut);
|
tb_sweep->addWidget(bZoomOut);
|
||||||
|
|
||||||
|
auto bZero = new QPushButton("0");
|
||||||
|
bZero->setToolTip("Zero span");
|
||||||
|
bZero->setMaximumWidth(28);
|
||||||
|
bZero->setMaximumHeight(24);
|
||||||
|
connect(bZero, &QPushButton::clicked, this, &SpectrumAnalyzer::SetZeroSpan);
|
||||||
|
tb_sweep->addWidget(bZero);
|
||||||
|
|
||||||
window->addToolBar(tb_sweep);
|
window->addToolBar(tb_sweep);
|
||||||
toolbars.insert(tb_sweep);
|
toolbars.insert(tb_sweep);
|
||||||
|
|
||||||
@ -450,6 +457,16 @@ void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d)
|
|||||||
|
|
||||||
d = average.process(d);
|
d = average.process(d);
|
||||||
|
|
||||||
|
if(settings.f_start == settings.f_stop) {
|
||||||
|
// keep track of first point time
|
||||||
|
if(d.pointNum == 0) {
|
||||||
|
firstPointTime = d.us;
|
||||||
|
d.us = 0;
|
||||||
|
} else {
|
||||||
|
d.us -= firstPointTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(normalize.measuring) {
|
if(normalize.measuring) {
|
||||||
if(average.currentSweep() == averages) {
|
if(average.currentSweep() == averages) {
|
||||||
// this is the last averaging sweep, use values for normalization
|
// this is the last averaging sweep, use values for normalization
|
||||||
@ -464,7 +481,7 @@ void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d)
|
|||||||
normalize.f_stop = settings.f_stop;
|
normalize.f_stop = settings.f_stop;
|
||||||
normalize.points = settings.pointNum;
|
normalize.points = settings.pointNum;
|
||||||
EnableNormalization(true);
|
EnableNormalization(true);
|
||||||
qDebug() << "Normalization measuremen complete";
|
qDebug() << "Normalization measurement complete";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -496,7 +513,7 @@ void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d)
|
|||||||
void SpectrumAnalyzer::SettingsChanged()
|
void SpectrumAnalyzer::SettingsChanged()
|
||||||
{
|
{
|
||||||
changingSettings = true;
|
changingSettings = true;
|
||||||
if(settings.f_stop - settings.f_start >= 1000) {
|
if(settings.f_stop - settings.f_start >= 1000 || settings.f_stop - settings.f_start <= 0) {
|
||||||
settings.pointNum = 1001;
|
settings.pointNum = 1001;
|
||||||
} else {
|
} else {
|
||||||
settings.pointNum = settings.f_stop - settings.f_start + 1;
|
settings.pointNum = settings.f_stop - settings.f_start + 1;
|
||||||
@ -505,10 +522,16 @@ void SpectrumAnalyzer::SettingsChanged()
|
|||||||
settings.applySourceCorrection = 1;
|
settings.applySourceCorrection = 1;
|
||||||
|
|
||||||
auto pref = Preferences::getInstance();
|
auto pref = Preferences::getInstance();
|
||||||
if(!settings.trackingGenerator && pref.Acquisition.useDFTinSAmode && settings.RBW <= pref.Acquisition.RBWLimitForDFT) {
|
if(settings.f_stop > settings.f_start) {
|
||||||
// Enable DFT if below RBW threshold and TG is not enabled
|
// non-zerospan, check usability of DFT
|
||||||
settings.UseDFT = 1;
|
if(!settings.trackingGenerator && pref.Acquisition.useDFTinSAmode && settings.RBW <= pref.Acquisition.RBWLimitForDFT) {
|
||||||
|
// Enable DFT if below RBW threshold and TG is not enabled
|
||||||
|
settings.UseDFT = 1;
|
||||||
|
} else {
|
||||||
|
settings.UseDFT = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// zerospan, DFT not usable
|
||||||
settings.UseDFT = 0;
|
settings.UseDFT = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,6 +643,13 @@ void SpectrumAnalyzer::SetFullSpan()
|
|||||||
ConstrainAndUpdateFrequencies();
|
ConstrainAndUpdateFrequencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpectrumAnalyzer::SetZeroSpan()
|
||||||
|
{
|
||||||
|
auto center = (settings.f_start + settings.f_stop) / 2;
|
||||||
|
SetStartFreq(center);
|
||||||
|
SetStopFreq(center);
|
||||||
|
}
|
||||||
|
|
||||||
void SpectrumAnalyzer::SpanZoomIn()
|
void SpectrumAnalyzer::SpanZoomIn()
|
||||||
{
|
{
|
||||||
auto center = (settings.f_start + settings.f_stop) / 2;
|
auto center = (settings.f_start + settings.f_stop) / 2;
|
||||||
@ -853,6 +883,11 @@ void SpectrumAnalyzer::SetupSCPI()
|
|||||||
SetFullSpan();
|
SetFullSpan();
|
||||||
return "";
|
return "";
|
||||||
}, nullptr));
|
}, nullptr));
|
||||||
|
scpi_freq->add(new SCPICommand("ZERO", [=](QStringList params) -> QString {
|
||||||
|
Q_UNUSED(params)
|
||||||
|
SetZeroSpan();
|
||||||
|
return "";
|
||||||
|
}, nullptr));
|
||||||
auto scpi_acq = new SCPINode("ACQuisition");
|
auto scpi_acq = new SCPINode("ACQuisition");
|
||||||
SCPINode::add(scpi_acq);
|
SCPINode::add(scpi_acq);
|
||||||
scpi_acq->add(new SCPICommand("RBW", [=](QStringList params) -> QString {
|
scpi_acq->add(new SCPICommand("RBW", [=](QStringList params) -> QString {
|
||||||
|
@ -61,6 +61,7 @@ private slots:
|
|||||||
void SetCenterFreq(double freq);
|
void SetCenterFreq(double freq);
|
||||||
void SetSpan(double span);
|
void SetSpan(double span);
|
||||||
void SetFullSpan();
|
void SetFullSpan();
|
||||||
|
void SetZeroSpan();
|
||||||
void SpanZoomIn();
|
void SpanZoomIn();
|
||||||
void SpanZoomOut();
|
void SpanZoomOut();
|
||||||
void SetSingleSweep(bool single);
|
void SetSingleSweep(bool single);
|
||||||
@ -92,6 +93,7 @@ private:
|
|||||||
bool changingSettings;
|
bool changingSettings;
|
||||||
unsigned int averages;
|
unsigned int averages;
|
||||||
bool singleSweep;
|
bool singleSweep;
|
||||||
|
double firstPointTime; // timestamp of the first point in the sweep, only use when zerospan is used
|
||||||
TraceModel traceModel;
|
TraceModel traceModel;
|
||||||
TraceWidget *traceWidget;
|
TraceWidget *traceWidget;
|
||||||
MarkerModel *markerModel;
|
MarkerModel *markerModel;
|
||||||
|
@ -120,11 +120,16 @@ void Trace::addData(const Trace::Data& d, DataType domain, double reference_impe
|
|||||||
emit outputSamplesChanged(index, index + 1);
|
emit outputSamplesChanged(index, index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Trace::addData(const Trace::Data &d, const Protocol::SpectrumAnalyzerSettings &s)
|
void Trace::addData(const Trace::Data &d, const Protocol::SpectrumAnalyzerSettings &s, int index)
|
||||||
{
|
{
|
||||||
settings.SA = s;
|
settings.SA = s;
|
||||||
settings.valid = true;
|
settings.valid = true;
|
||||||
addData(d, DataType::Frequency);
|
auto domain = DataType::Frequency;
|
||||||
|
if (s.f_start == s.f_stop) {
|
||||||
|
// in zerospan mode
|
||||||
|
domain = DataType::TimeZeroSpan;
|
||||||
|
}
|
||||||
|
addData(d, domain, 50.0, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Trace::setName(QString name) {
|
void Trace::setName(QString name) {
|
||||||
|
@ -46,15 +46,15 @@ public:
|
|||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
void addData(const Data& d, DataType domain, double reference_impedance = 50.0, int index = -1);
|
void addData(const Data& d, DataType domain, double reference_impedance = 50.0, int index = -1);
|
||||||
void addData(const Data& d, const Protocol::SpectrumAnalyzerSettings& s);
|
void addData(const Data& d, const Protocol::SpectrumAnalyzerSettings& s, int index = -1);
|
||||||
void setName(QString name);
|
void setName(QString name);
|
||||||
void setVelocityFactor(double v);
|
void setVelocityFactor(double v);
|
||||||
void fillFromTouchstone(Touchstone &t, unsigned int parameter);
|
void fillFromTouchstone(Touchstone &t, unsigned int parameter);
|
||||||
QString fillFromCSV(CSV &csv, unsigned int parameter); // returns the suggested trace name (not yet set in member data)
|
QString fillFromCSV(CSV &csv, unsigned int parameter); // returns the suggested trace name (not yet set in member data)
|
||||||
static void fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, const std::vector<VNAData> &data);
|
static void fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, const std::vector<VNAData> &data);
|
||||||
void fromLivedata(LivedataType type, LiveParameter param);
|
void fromLivedata(LivedataType type, LiveParameter param);
|
||||||
QString name() { return _name; };
|
QString name() { return _name; }
|
||||||
QColor color() { return _color; };
|
QColor color() { return _color; }
|
||||||
bool isVisible();
|
bool isVisible();
|
||||||
void pause();
|
void pause();
|
||||||
void resume();
|
void resume();
|
||||||
@ -65,7 +65,7 @@ public:
|
|||||||
bool isReflection();
|
bool isReflection();
|
||||||
LiveParameter liveParameter() { return _liveParam; }
|
LiveParameter liveParameter() { return _liveParam; }
|
||||||
LivedataType liveType() { return _liveType; }
|
LivedataType liveType() { return _liveType; }
|
||||||
TraceMath::DataType outputType() const { return lastMath->getDataType(); };
|
TraceMath::DataType outputType() const { return lastMath->getDataType(); }
|
||||||
unsigned int size() const;
|
unsigned int size() const;
|
||||||
double minX();
|
double minX();
|
||||||
double maxX();
|
double maxX();
|
||||||
@ -123,7 +123,7 @@ public:
|
|||||||
virtual nlohmann::json toJSON() override;
|
virtual nlohmann::json toJSON() override;
|
||||||
virtual void fromJSON(nlohmann::json j) override;
|
virtual void fromJSON(nlohmann::json j) override;
|
||||||
|
|
||||||
Type getType() override {return Type::Last;}; // can return invalid type, this will never be called
|
Type getType() override {return Type::Last;} // can return invalid type, this will never be called
|
||||||
|
|
||||||
// Traces are referenced by pointers throughout this project (e.g. when added to a graph)
|
// Traces are referenced by pointers throughout this project (e.g. when added to a graph)
|
||||||
// When saving the current graph configuration, the pointer is not useful. Instead a trace
|
// When saving the current graph configuration, the pointer is not useful. Instead a trace
|
||||||
|
@ -248,8 +248,15 @@ void TraceModel::addSAData(const Protocol::SpectrumAnalyzerResult& d, const Prot
|
|||||||
source = DataSource::SA;
|
source = DataSource::SA;
|
||||||
for(auto t : traces) {
|
for(auto t : traces) {
|
||||||
if (t->isLive() && !t->isPaused()) {
|
if (t->isLive() && !t->isPaused()) {
|
||||||
|
int index = -1;
|
||||||
Trace::Data td;
|
Trace::Data td;
|
||||||
td.x = d.frequency;
|
if(settings.f_start == settings.f_stop) {
|
||||||
|
// in zerospan mode, insert data by index
|
||||||
|
index = d.pointNum;
|
||||||
|
td.x = (double) d.us / 1000000.0;
|
||||||
|
} else {
|
||||||
|
td.x = d.frequency;
|
||||||
|
}
|
||||||
switch(t->liveParameter()) {
|
switch(t->liveParameter()) {
|
||||||
case Trace::LiveParameter::Port1: td.y = complex<double>(d.port1, 0); break;
|
case Trace::LiveParameter::Port1: td.y = complex<double>(d.port1, 0); break;
|
||||||
case Trace::LiveParameter::Port2: td.y = complex<double>(d.port2, 0); break;
|
case Trace::LiveParameter::Port2: td.y = complex<double>(d.port2, 0); break;
|
||||||
@ -257,7 +264,7 @@ void TraceModel::addSAData(const Protocol::SpectrumAnalyzerResult& d, const Prot
|
|||||||
// not a SA trace, skip
|
// not a SA trace, skip
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
t->addData(td, settings);
|
t->addData(td, settings, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,16 @@ using SpectrumAnalyzerSettings = struct _spectrumAnalyzerSettings {
|
|||||||
using SpectrumAnalyzerResult = struct _spectrumAnalyzerResult {
|
using SpectrumAnalyzerResult = struct _spectrumAnalyzerResult {
|
||||||
float port1;
|
float port1;
|
||||||
float port2;
|
float port2;
|
||||||
uint64_t frequency;
|
union {
|
||||||
|
struct {
|
||||||
|
// for non-zero span
|
||||||
|
uint64_t frequency;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
// for zero span
|
||||||
|
uint64_t us; // time in us since first datapoint
|
||||||
|
};
|
||||||
|
};
|
||||||
uint16_t pointNum;
|
uint16_t pointNum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,6 +36,10 @@ static uint8_t attenuator;
|
|||||||
static int64_t trackingFreq;
|
static int64_t trackingFreq;
|
||||||
static bool trackingLowband;
|
static bool trackingLowband;
|
||||||
|
|
||||||
|
static uint64_t firstPointTime;
|
||||||
|
static bool firstPoint;
|
||||||
|
static bool zerospan;
|
||||||
|
|
||||||
static void StartNextSample() {
|
static void StartNextSample() {
|
||||||
uint64_t freq = s.f_start + (s.f_stop - s.f_start) * pointCnt / (points - 1);
|
uint64_t freq = s.f_start + (s.f_stop - s.f_start) * pointCnt / (points - 1);
|
||||||
freq = Cal::FrequencyCorrectionToDevice(freq);
|
freq = Cal::FrequencyCorrectionToDevice(freq);
|
||||||
@ -205,6 +209,8 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
|
|||||||
points += s.pointNum - points % s.pointNum;
|
points += s.pointNum - points % s.pointNum;
|
||||||
binSize = points / s.pointNum;
|
binSize = points / s.pointNum;
|
||||||
LOG_DEBUG("%u displayed points, resulting in %lu points and bins of size %u", s.pointNum, points, binSize);
|
LOG_DEBUG("%u displayed points, resulting in %lu points and bins of size %u", s.pointNum, points, binSize);
|
||||||
|
|
||||||
|
zerospan = (s.f_start == s.f_stop);
|
||||||
// set initial state
|
// set initial state
|
||||||
pointCnt = 0;
|
pointCnt = 0;
|
||||||
// enable the required hardware resources
|
// enable the required hardware resources
|
||||||
@ -256,6 +262,7 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lastLO2 = 0;
|
lastLO2 = 0;
|
||||||
|
firstPoint = true;
|
||||||
active = true;
|
active = true;
|
||||||
StartNextSample();
|
StartNextSample();
|
||||||
}
|
}
|
||||||
@ -375,7 +382,19 @@ void SA::Work() {
|
|||||||
// Send result to application
|
// Send result to application
|
||||||
p.type = Protocol::PacketType::SpectrumAnalyzerResult;
|
p.type = Protocol::PacketType::SpectrumAnalyzerResult;
|
||||||
// measurements are already up to date, fill remaining fields
|
// measurements are already up to date, fill remaining fields
|
||||||
p.spectrumResult.frequency = s.f_start + (s.f_stop - s.f_start) * binIndex / (s.pointNum - 1);
|
if(zerospan) {
|
||||||
|
uint64_t timestamp = HW::getLastISRTimestamp();
|
||||||
|
if(firstPoint) {
|
||||||
|
p.spectrumResult.us = 0;
|
||||||
|
firstPointTime = timestamp;
|
||||||
|
firstPoint = false;
|
||||||
|
} else {
|
||||||
|
p.spectrumResult.us = timestamp - firstPointTime;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// non-zero span, set frequency
|
||||||
|
p.spectrumResult.frequency = s.f_start + (s.f_stop - s.f_start) * binIndex / (s.pointNum - 1);
|
||||||
|
}
|
||||||
// scale approximately (constant determined empirically)
|
// scale approximately (constant determined empirically)
|
||||||
p.spectrumResult.port1 /= 253000000.0;
|
p.spectrumResult.port1 /= 253000000.0;
|
||||||
p.spectrumResult.port2 /= 253000000.0;
|
p.spectrumResult.port2 /= 253000000.0;
|
||||||
|
Loading…
Reference in New Issue
Block a user