-
Notifications
You must be signed in to change notification settings - Fork 87
/
vna_measurement.hpp
140 lines (102 loc) · 4 KB
/
vna_measurement.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#pragma once
#include <mculib/small_function.hpp>
#include "common.hpp"
#include "sample_processor.hpp"
enum class VNAMeasurementPhases {
REFERENCE,
REFL,
THRU,
ECALLOAD,
ECALSHORT,
ECALTHRU
};
// implements sweep, rf switch timing, and dsp for single-receiver
// switched path VNAs (one receiver with switches to select reference,
// reflected, and thru paths).
// given switch & synthesizer controls and adc data feed, emit a stream
// of data points.
class VNAMeasurement {
public:
typedef complex<int32_t> complexi;
// how many periods to wait after changing rf switches
uint16_t nWaitSwitch = 1;
// how many periods to wait after changing synthesizer frequency
uint16_t nWaitSynth = 30;
// how many periods to average over
uint16_t nMeasureCount = 0;
uint16_t nPeriods = 14;
uint16_t nPeriodsCalibrating = 28;
uint16_t nPeriodsMultiplier = 1;
// every ecalIntervalPoints we will measure one frequency point for ecal
uint16_t ecalIntervalPoints = 8;
// AGC parameters; VNAMeasurement will detect ADC clip events and inform the
// host when baseband/rf gain needs to be changed.
uint8_t gainMin = 0, gainMax = 3;
float adcFullScale = 0;
// automatically reset before each measurement; indicates whether the current
// S11 data point is corrupted when emitDataPoint() is called.
bool clipFlag = false;
// same as clipFlag, but for S21
// bool clipFlag2 = false;
// called when a new data point is available.
// ecal is load, short, thru.
small_function<void(int freqIndex, freqHz_t freqHz, const VNAObservationSet& v, const complexf* ecal)> emitDataPoint;
// called to change rf switch direction;
// the function may assume the phase progression is always:
// REFERENCE, REFL1, REFL2, THRU,
// except that REFERENCE may be switched to at any time and from any phase.
small_function<void(VNAMeasurementPhases ph)> phaseChanged;
// called to change synthesizer frequency
small_function<void(freqHz_t freqHz)> frequencyChanged;
// called when sweep setup change is processed in measurement 'thread'
small_function<void(freqHz_t start, freqHz_t stop)> sweepSetupChanged;
// called to change overall system gain; gain is a user defined value
// and VNAMeasurement will only increment or decrement it if ADC
// clips occur or signal value is too low.
// the gain applies to THRU measurements only.
small_function<void(int gain)> gainChanged;
VNAMeasurement();
void init();
void setCorrelationTable(const int16_t* table, int length);
void processSamples(uint16_t* buf, int len);
// if points is 1, sets frequency to startFreqHz and disables sweep
void setSweep(freqHz_t startFreqHz, freqHz_t stepFreqHz, int points, int dataPointsPerFreq=1);
void resetSweep();
struct _emitValue_t {
VNAMeasurement* m;
void operator()(int32_t* valRe, int32_t* valIm);
};
SampleProcessor<_emitValue_t> sampleProcessor;
public:
// state variables
VNAMeasurementPhases measurementPhase = VNAMeasurementPhases::REFERENCE;
// number of periods left to wait
uint32_t periodCounterSynth = 0;
// number of periods since changing rf switches
uint32_t periodCounterSwitch = 0;
// number of data points since synthesizer frequency change
uint32_t dpCounterSynth = 0;
// counts up every data point; resets when it reaches ecalIntervalPoints
uint32_t ecalCounter = 0;
uint32_t ecalCounterOffset = 0;
// What measurements to make
enum MeasurementMode measurement_mode = MEASURE_MODE_FULL;
// number of frequency points since start of sweep
volatile int sweepCurrPoint = 0;
uint16_t currThruGain = 0;
uint16_t currReflGain = 0;
bool gainChangeOccurred = false;
// current data point variables
int64_t currDP_re, currDP_im;
complexf currFwd, currRefl, currThru;
// sweep params
freqHz_t sweepStartHz = 0, sweepStepHz = 0;
int sweepPoints = 1;
uint32_t sweepDataPointsPerFreq = 1;
freqHz_t currFreq;
complexf ecal[ECAL_CHANNELS];
void setMeasurementPhase(VNAMeasurementPhases ph);
void sweepAdvance();
void sampleProcessor_emitValue(int32_t valRe, int32_t valIm, bool clipped);
void doEmitValue(bool ecal);
};