15 #include "pulseanalyzer.h"
18 REGISTER_TYPE(
XDriverList, NMRBuiltInNetworkAnalyzer,
"NMR Built-In Network Analyzer");
20 XNMRBuiltInNetworkAnalyzer::XNMRBuiltInNetworkAnalyzer(
const char *name,
bool runtime,
21 Transaction &tr_meas,
const shared_ptr<XMeasure> &meas) :
31 const char *cand[] = {
"OFF",
"11",
"21",
"51",
"101",
"201",
"401",
"801",
"1601",
"3201",
""};
32 for(
const char **it = cand; strlen( *it); it++) {
33 tr[ *points()].add( *it);
35 tr[ *
this].m_sweeping =
false;
40 XNMRBuiltInNetworkAnalyzer::clear() {
41 restart(CAL_NONE,
true);
74 int pts = atoi(
Snapshot( *
this)[ *points()].to_str().c_str());
86 XNMRBuiltInNetworkAnalyzer::getMarkerPos(
unsigned int num,
double &x,
double &y) {
90 x = shot[ *
this].m_marker_min.first;
91 y = shot[ *
this].m_marker_min.second;
94 x = shot[ *
this].m_marker_max.first;
95 y = shot[ *
this].m_marker_max.second;
102 XNMRBuiltInNetworkAnalyzer::oneSweep() {
103 bool ret = restart(CAL_NONE);
106 while(
Snapshot( *
this)[ *
this].m_sweeping) {
111 XNMRBuiltInNetworkAnalyzer::restart(
int calmode,
bool clear) {
116 restart(tr, calmode, clear);
128 XNMRBuiltInNetworkAnalyzer::restart(
Transaction &tr,
int calmode,
bool clear) {
131 int pts = atoi(shot_this[ *points()].to_str().c_str());
132 tr[ *
this].m_sweepPoints = pts;
136 tr[ *
this].m_ftsum.clear();
137 tr[ *
this].m_ftsum_weight.clear();
138 tr[ *
this].m_calMode = calmode;
139 if(clear || tr[ *
this].m_raw_open.empty()) {
140 tr[ *
this].m_raw_open.clear();
141 tr[ *
this].m_raw_short.clear();
142 tr[ *
this].m_raw_term.clear();
143 tr[ *
this].m_raw_thru.clear();
144 tr[ *
this].m_raw_open.resize(pts, 1.0);
145 tr[ *
this].m_raw_short.resize(pts, -1.0);
146 tr[ *
this].m_raw_term.resize(pts, 0.0);
147 tr[ *
this].m_raw_thru.resize(pts, 1.0);
150 shared_ptr<XPulser> pulse = shot_this[ *m_pulser];
153 shared_ptr<XSG> sg = shot_this[ *m_sg];
156 shared_ptr<XDSO> dso = shot_this[ *m_dso];
163 if( !shot_dso[ *dso].time() || !shot_dso[ *dso].numChannels()) {
168 interval = shot_dso[ *dso].timeInterval();
169 dso_len = shot_dso[ *dso].length();
172 double fmax = shot_this[ *stopFreq()];
173 tr[ *
this].m_sweepStop = fmax;
174 double fmin = shot_this[ *startFreq()];
175 tr[ *
this].m_sweepStart = fmin;
176 if((fmax <= fmin) || (fmin <= 0.1))
180 double plsbw = trp[ *pulse].paPulseBW() * 1e-3;
181 double fstep = plsbw *1.0;
182 fstep = std::max(fstep, (fmax - fmin) / (pts - 1));
185 tr[ *
this].m_sweepStep = fstep;
186 trp[ *pulse->pulseAnalyzerMode()] =
true;
187 double rept_ms = std::max(2.0 / ((fmax - fmin) / (pts - 1)) * 1e-3 * 2, 0.2);
188 rept_ms = interval * 1e3 * lrint(rept_ms / (interval * 1e3));
189 trp[ *pulse->paPulseRept()] = rept_ms;
190 trp[ *pulse->output()] =
true;
193 trans( *sg->freq()) = fmin;
196 int avg = std::max(1L, lrint(0.03 / (interval * dso_len)));
197 avg *= std::max(1u, (
unsigned int)shot_this[ *average()]);
198 trd[ *dso->average()] = (avg + 3) / 4 * 4;
199 trd[ *dso->firEnabled()] =
false;
200 trd[ *dso->restart()].touch();
203 tr[ *
this].m_sweeping =
true;
206 XNMRBuiltInNetworkAnalyzer::startContSweep() {
208 shared_ptr<XPulser> pulse = shot_this[ *m_pulser];
211 tr[ *pulse->pulseAnalyzerMode()] =
false;
212 tr[ *pulse->output()] =
false;
215 shared_ptr<XSG> sg = shot_this[ *m_sg];
217 trans( *sg->freq()) = (
double)shot_this[ *this].m_marker_min.first;
228 XNMRBuiltInNetworkAnalyzer::writeTraceAndMarkers(
Transaction &tr) {
230 double fmin = shot_this[ *
this].m_sweepStart;
231 double fmax = shot_this[ *
this].m_sweepStop;
232 int pts = shot_this[ *
this].m_sweepPoints;
236 tr[ *
this].m_startFreq = fmin;
237 double df = (fmax - fmin) / (pts - 1);
238 tr[ *
this].m_freqInterval = df;
239 tr[ *
this].trace_().resize(pts);
241 auto ftsum = &tr[ *
this].m_ftsum[0];
242 auto ftsum_weight = &tr[ *
this].m_ftsum_weight[0];
243 for(
unsigned int i = 0; i < pts; i++) {
244 ftsum[i] /= ftsum_weight[i];
248 switch(tr[ *
this].m_calMode) {
252 tr[ *
this].m_raw_open.resize(pts);
253 std::copy(tr[ *
this].m_ftsum.begin(), tr[ *
this].m_ftsum.end(), tr[ *
this].m_raw_open.begin());
256 tr[ *
this].m_raw_short.resize(pts);
257 std::copy(tr[ *
this].m_ftsum.begin(), tr[ *
this].m_ftsum.end(), tr[ *
this].m_raw_short.begin());
260 tr[ *
this].m_raw_term.resize(pts);
261 std::copy(tr[ *
this].m_ftsum.begin(), tr[ *
this].m_ftsum.end(), tr[ *
this].m_raw_term.begin());
264 tr[ *
this].m_raw_thru.resize(pts);
265 std::copy(tr[ *
this].m_ftsum.begin(), tr[ *
this].m_ftsum.end(), tr[ *
this].m_raw_thru.begin());
269 auto rawopen = &tr[ *
this].m_raw_open[0];
270 auto rawshort = &tr[ *
this].m_raw_short[0];
271 auto rawterm = &tr[ *
this].m_raw_term[0];
272 auto trace = &tr[ *
this].trace_()[0];
273 for(
unsigned int i = 0; i < pts; i++) {
274 auto zport_in = - rawopen[i] / rawshort[i];
275 auto s11_dut = 1.0 - 2.0 / ((1.0 + zport_in) / (1.0 - (ftsum[i] - rawterm[i]) / rawopen[i]) + 1.0 - zport_in);
280 auto &mkmin = tr[ *
this].m_marker_min;
282 auto &mkmax = tr[ *
this].m_marker_max;
283 mkmax.second = -1000;
284 auto z = tr[ *
this].trace();
285 for(
unsigned int i = 0; i < pts; i++) {
286 double r = 20.0 * log10(std::abs( *z++));
288 mkmin = std::pair<double, double>(i * df + fmin, r);
290 mkmax = std::pair<double, double>(i * df + fmin, r);
301 if( !shot_this[ *
this].m_sweeping)
303 shared_ptr<XPulser> pulse = shot_this[ *m_pulser];
304 if( !pulse)
return false;
305 shared_ptr<XDSO> dso = shot_this[ *m_dso];
306 if( !dso)
return false;
307 shared_ptr<XSG> sg = shot_this[ *m_sg];
308 if( !sg)
return false;
309 if(emitter != dso.get())
311 if(shot_emitter[ *dso].timeAwared() < shot_others[ *sg].time())
return false;
318 int pts = shot_this[ *
this].m_sweepPoints;
320 tr[ *
this].m_sweeping =
false;
324 const Snapshot &shot_dso(shot_emitter);
325 const Snapshot &shot_sg(shot_others);
326 const Snapshot &shot_pulse(shot_others);
327 shared_ptr<XPulser> pulse = shot_this[ *m_pulser];
328 shared_ptr<XDSO> dso = shot_this[ *m_dso];
329 shared_ptr<XSG> sg = shot_this[ *m_sg];
331 assert(shot_dso[ *dso].time() );
333 if(shot_dso[ *dso].numChannels() < 1) {
336 if(shot_dso[ *dso].numChannels() < 2) {
339 if( !shot_dso[ *dso->singleSequence()]) {
340 g_statusPrinter->printWarning(i18n(
"Use sequential average in DSO."));
342 int dso_len = shot_dso[ *dso].length();
344 double interval = shot_dso[ *dso].timeInterval();
346 throw XSkippedRecordError(i18n(
"Invalid time interval in waveforms."), __FILE__, __LINE__);
348 int pos = lrint(shot_dso[ *dso].trigPos());
357 if( !shot_pulse[ *pulse].isPulseAnalyzerMode())
358 throw XSkippedRecordError(i18n(
"Pulser configured not in Built-In Network Analyzer Mode."), __FILE__, __LINE__);
360 double rept = shot_pulse[ *pulse].rtime() * 1e-3;
361 double plsorg = shot_pulse[ *pulse].paPulseOrigin() * 1e-6;
363 double fmin = shot_this[ *
this].m_sweepStart;
364 double fmax = shot_this[ *
this].m_sweepStop;
366 unsigned int fftlen = (
unsigned int)floor(std::max(plsorg / interval, 1e-6 / ((fmax - fmin) / (pts - 1)) / interval * 2));
367 fftlen =
FFT::fitLength(std::min(fftlen, (
unsigned int)floor(rept / interval)));
368 if( !m_fft || m_fft->length() != fftlen) {
369 m_fft.reset(
new FFT(-1, fftlen));
370 m_fftin.resize(fftlen);
371 m_fftout.resize(fftlen);
373 std::fill(m_fftin.begin(), m_fftin.end(), 0.0);
374 unsigned int avg_in_wave = floor((dso_len - pos) / (rept / interval));
377 avg_in_wave = avg_in_wave / 2 * 2;
379 for(
unsigned int av = 0; av < avg_in_wave; ++av) {
380 int lpos = lrint(pos + (rept * av) / interval);
381 int org = lrint(pos + (plsorg + rept * av) / interval);
382 bool inverted = (av % 2 == 1);
383 const double *wavecos = &shot_dso[ *dso].wave(0)[lpos];
384 const double *wavesin = &shot_dso[ *dso].wave(1)[lpos];
385 for(
unsigned int i = fftlen - (org - lpos); i < fftlen; ++i) {
386 m_fftin[i] += std::complex<double>( *wavecos++, *wavesin++) * (inverted ? -1.0 : 1.0);
388 for(
unsigned int i = 0; i < fftlen - (org - lpos); ++i) {
389 m_fftin[i] += std::complex<double>( *wavecos++, *wavesin++) * (inverted ? -1.0 : 1.0);
392 double fft_df = 1.0 / (interval * fftlen) * 1e-6;
393 m_fft->exec(m_fftin, m_fftout);
395 double plsbw = shot_pulse[ *pulse].paPulseBW() * 1e-3;
397 if(tr[ *
this].m_ftsum.size() != pts) {
398 tr[ *
this].m_ftsum.resize(pts);
399 tr[ *
this].m_ftsum_weight.resize(pts);
400 std::fill(tr[ *
this].m_ftsum.begin(), tr[ *
this].m_ftsum.end(), 0.0);
401 std::fill(tr[ *
this].m_ftsum_weight.begin(), tr[ *
this].m_ftsum_weight.end(), 0);
403 double freq = shot_sg[ *sg].freq();
404 tr[ *
this].m_lastCenterFreq = freq;
405 if(freq < fmin - plsbw/2) {
406 restart(tr, shot_this[ *
this].m_calMode);
409 double normalize = 1.0 / avg_in_wave / fftlen;
410 auto ftsum = &tr[ *
this].m_ftsum[0];
411 auto ftsum_weight = &tr[ *
this].m_ftsum_weight[0];
412 for(
int i = 0; i < fftlen; ++i) {
413 double f = fft_df * ((i >= fftlen / 2) ? i - (
int)fftlen : i);
414 if(abs(f) > plsbw / 2)
417 int j = lrint((f - fmin) / (fmax - fmin) * (pts - 1));
418 if((j < 0) || (j >= pts))
420 ftsum[j] += m_fftout[i] * normalize;
423 if( !shot_this[ *
this].m_ftsum.size()) {
424 restart(tr, shot_this[ *
this].m_calMode);
427 double fstep = shot_this[ *
this].m_sweepStep;
428 if(freq + fstep / 2 > fmax) {
429 writeTraceAndMarkers(tr);
430 tr[ *
this].m_sweeping =
false;
436 if(shot[ *
this].m_sweeping) {
437 double freq = shot[ *
this].m_lastCenterFreq;
438 double fstep = shot[ *
this].m_sweepStep;
441 shared_ptr<XSG> sg = shot[ *m_sg];
443 trans( *sg->freq()) = freq;