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}
|
||||
\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}
|
||||
\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}
|
||||
|
@ -135,6 +135,13 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
||||
connect(bZoomOut, &QPushButton::clicked, this, &SpectrumAnalyzer::SpanZoomOut);
|
||||
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);
|
||||
toolbars.insert(tb_sweep);
|
||||
|
||||
@ -450,6 +457,16 @@ void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult 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(average.currentSweep() == averages) {
|
||||
// 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.points = settings.pointNum;
|
||||
EnableNormalization(true);
|
||||
qDebug() << "Normalization measuremen complete";
|
||||
qDebug() << "Normalization measurement complete";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,7 +513,7 @@ void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d)
|
||||
void SpectrumAnalyzer::SettingsChanged()
|
||||
{
|
||||
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;
|
||||
} else {
|
||||
settings.pointNum = settings.f_stop - settings.f_start + 1;
|
||||
@ -505,10 +522,16 @@ void SpectrumAnalyzer::SettingsChanged()
|
||||
settings.applySourceCorrection = 1;
|
||||
|
||||
auto pref = Preferences::getInstance();
|
||||
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;
|
||||
if(settings.f_stop > settings.f_start) {
|
||||
// non-zerospan, check usability of DFT
|
||||
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 {
|
||||
// zerospan, DFT not usable
|
||||
settings.UseDFT = 0;
|
||||
}
|
||||
|
||||
@ -620,6 +643,13 @@ void SpectrumAnalyzer::SetFullSpan()
|
||||
ConstrainAndUpdateFrequencies();
|
||||
}
|
||||
|
||||
void SpectrumAnalyzer::SetZeroSpan()
|
||||
{
|
||||
auto center = (settings.f_start + settings.f_stop) / 2;
|
||||
SetStartFreq(center);
|
||||
SetStopFreq(center);
|
||||
}
|
||||
|
||||
void SpectrumAnalyzer::SpanZoomIn()
|
||||
{
|
||||
auto center = (settings.f_start + settings.f_stop) / 2;
|
||||
@ -853,6 +883,11 @@ void SpectrumAnalyzer::SetupSCPI()
|
||||
SetFullSpan();
|
||||
return "";
|
||||
}, nullptr));
|
||||
scpi_freq->add(new SCPICommand("ZERO", [=](QStringList params) -> QString {
|
||||
Q_UNUSED(params)
|
||||
SetZeroSpan();
|
||||
return "";
|
||||
}, nullptr));
|
||||
auto scpi_acq = new SCPINode("ACQuisition");
|
||||
SCPINode::add(scpi_acq);
|
||||
scpi_acq->add(new SCPICommand("RBW", [=](QStringList params) -> QString {
|
||||
|
@ -61,6 +61,7 @@ private slots:
|
||||
void SetCenterFreq(double freq);
|
||||
void SetSpan(double span);
|
||||
void SetFullSpan();
|
||||
void SetZeroSpan();
|
||||
void SpanZoomIn();
|
||||
void SpanZoomOut();
|
||||
void SetSingleSweep(bool single);
|
||||
@ -92,6 +93,7 @@ private:
|
||||
bool changingSettings;
|
||||
unsigned int averages;
|
||||
bool singleSweep;
|
||||
double firstPointTime; // timestamp of the first point in the sweep, only use when zerospan is used
|
||||
TraceModel traceModel;
|
||||
TraceWidget *traceWidget;
|
||||
MarkerModel *markerModel;
|
||||
|
@ -120,11 +120,16 @@ void Trace::addData(const Trace::Data& d, DataType domain, double reference_impe
|
||||
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.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) {
|
||||
|
@ -46,15 +46,15 @@ public:
|
||||
|
||||
void clear();
|
||||
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 setVelocityFactor(double v);
|
||||
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)
|
||||
static void fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, const std::vector<VNAData> &data);
|
||||
void fromLivedata(LivedataType type, LiveParameter param);
|
||||
QString name() { return _name; };
|
||||
QColor color() { return _color; };
|
||||
QString name() { return _name; }
|
||||
QColor color() { return _color; }
|
||||
bool isVisible();
|
||||
void pause();
|
||||
void resume();
|
||||
@ -65,7 +65,7 @@ public:
|
||||
bool isReflection();
|
||||
LiveParameter liveParameter() { return _liveParam; }
|
||||
LivedataType liveType() { return _liveType; }
|
||||
TraceMath::DataType outputType() const { return lastMath->getDataType(); };
|
||||
TraceMath::DataType outputType() const { return lastMath->getDataType(); }
|
||||
unsigned int size() const;
|
||||
double minX();
|
||||
double maxX();
|
||||
@ -123,7 +123,7 @@ public:
|
||||
virtual nlohmann::json toJSON() 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)
|
||||
// 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;
|
||||
for(auto t : traces) {
|
||||
if (t->isLive() && !t->isPaused()) {
|
||||
int index = -1;
|
||||
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()) {
|
||||
case Trace::LiveParameter::Port1: td.y = complex<double>(d.port1, 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
|
||||
continue;
|
||||
}
|
||||
t->addData(td, settings);
|
||||
t->addData(td, settings, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +152,16 @@ using SpectrumAnalyzerSettings = struct _spectrumAnalyzerSettings {
|
||||
using SpectrumAnalyzerResult = struct _spectrumAnalyzerResult {
|
||||
float port1;
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -36,6 +36,10 @@ static uint8_t attenuator;
|
||||
static int64_t trackingFreq;
|
||||
static bool trackingLowband;
|
||||
|
||||
static uint64_t firstPointTime;
|
||||
static bool firstPoint;
|
||||
static bool zerospan;
|
||||
|
||||
static void StartNextSample() {
|
||||
uint64_t freq = s.f_start + (s.f_stop - s.f_start) * pointCnt / (points - 1);
|
||||
freq = Cal::FrequencyCorrectionToDevice(freq);
|
||||
@ -205,6 +209,8 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
|
||||
points += s.pointNum - 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);
|
||||
|
||||
zerospan = (s.f_start == s.f_stop);
|
||||
// set initial state
|
||||
pointCnt = 0;
|
||||
// enable the required hardware resources
|
||||
@ -256,6 +262,7 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
|
||||
}
|
||||
|
||||
lastLO2 = 0;
|
||||
firstPoint = true;
|
||||
active = true;
|
||||
StartNextSample();
|
||||
}
|
||||
@ -375,7 +382,19 @@ void SA::Work() {
|
||||
// Send result to application
|
||||
p.type = Protocol::PacketType::SpectrumAnalyzerResult;
|
||||
// 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)
|
||||
p.spectrumResult.port1 /= 253000000.0;
|
||||
p.spectrumResult.port2 /= 253000000.0;
|
||||
|
Loading…
Reference in New Issue
Block a user