Skip to content

Commit

Permalink
implement calibration
Browse files Browse the repository at this point in the history
  • Loading branch information
nanovna committed Dec 6, 2019
1 parent f3e73d9 commit 27272e5
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 25 deletions.
48 changes: 48 additions & 0 deletions calibration.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#pragma once
#include "common.hpp"

// given the measured raw values for short, open, and load, compute the 3 calibration coefficients
inline array<complexf, 3> SOL_compute_coefficients(complexf sc, complexf oc, complexf load) {
complexf a=load, b=oc, c=sc;
complexf cal_X, cal_Y, cal_Z;
cal_Z=(2.f*a-b-c)/(b-c);
cal_X=a-c*(1.f-cal_Z);
cal_Y=a/cal_X;

return {cal_X, cal_Y, cal_Z};
}
// given the calibration coefficients and a raw value, compute the reflection coefficient
inline complexf SOL_compute_reflection(const array<complexf, 3>& coeffs, complexf raw) {
auto cal_X = coeffs[0];
auto cal_Y = coeffs[1];
auto cal_Z = coeffs[2];

return (cal_X*cal_Y-raw)/(raw*cal_Z-cal_X);
}

// given the measured raw values for S,O,L and a DUT raw value, compute the reflection coefficient
inline complexf SOL_compute_reflection(complexf sc, complexf oc, complexf load, complexf dut) {
complexf a=load, b=oc, c=sc, d = dut;
/*complexf cal_X, cal_Y, cal_Z;
cal_Z=(2.f*a-b-c)/(b-c);
cal_X=a-c*(1.f-cal_Z);
cal_Y=a/cal_X;
return (cal_X*cal_Y-dut)/(dut*cal_Z-cal_X);*/

/* derived from the above formulas and simplified using sympy:
from sympy import *
a = Symbol('a')
b = Symbol('b')
c = Symbol('c')
d = Symbol('d')
z = (2*a - b - c) / (b-c)
x = a - c*(1 - z)
y = a/x
result = (x*y-d)/(d*z-x)
simplify(result)
*/

return -(a - d)*(b - c)/(a*(b - c) + 2.f*c*(a - b) + d*(-2.f*a + b + c));
}

8 changes: 6 additions & 2 deletions common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ typedef uint64_t freqHz_t;
#define CAL_OPEN 1
#define CAL_SHORT 2
#define CAL_THRU 3
#define CAL_ISOLN 4

#define CALSTAT_LOAD (1<<0)
#define CALSTAT_OPEN (1<<1)
Expand Down Expand Up @@ -97,6 +96,11 @@ constexpr int adf4350_freqStep = 6; // adf4350 resolution, kHz
constexpr int adf4350_modulus = xtal_freq/adf4350_R/adf4350_freqStep;


constexpr int MEASUREMENT_NPERIODS_NORMAL = 14;
constexpr int MEASUREMENT_NPERIODS_CALIBRATING = 30;
constexpr int MEASUREMENT_ECAL_INTERVAL = 8;



enum {
TRC_LOGMAG, TRC_PHASE, TRC_DELAY, TRC_SMITH, TRC_POLAR, TRC_LINEAR, TRC_SWR, TRC_REAL, TRC_IMAG, TRC_R, TRC_X, TRC_OFF
Expand Down Expand Up @@ -128,7 +132,7 @@ struct alignas(4) properties_t {
int16_t _sweep_points;
uint16_t _cal_status;

complexf _cal_data[5][SWEEP_POINTS_MAX];
complexf _cal_data[4][SWEEP_POINTS_MAX];
float _electrical_delay; // picoseconds

trace_t _trace[TRACES_MAX];
Expand Down
2 changes: 1 addition & 1 deletion globals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ extern uistat_t uistat;
#define sweep_points current_props._sweep_points
#define cal_status current_props._cal_status
#define frequencies current_props._frequencies
#define cal_data active_props->_cal_data
#define cal_data current_props._cal_data
#define electrical_delay current_props._electrical_delay

#define trace current_props._trace
Expand Down
86 changes: 69 additions & 17 deletions main2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "vna_measurement.hpp"
#include "fifo.hpp"
#include "flash.hpp"
#include "calibration.hpp"

#include <libopencm3/stm32/timer.h>

Expand Down Expand Up @@ -88,6 +89,11 @@ FIFO<small_function<void()>, 8> eventQueue;
volatile bool usbDataMode = false;
volatile bool refreshEnabled = true;

volatile int collectMeasurementType = -1;
int collectMeasurementOffset = -1;
int collectMeasurementState = 0;
small_function<void()> collectMeasurementCB;

void adc_process();

template<unsigned int N>
Expand Down Expand Up @@ -388,22 +394,45 @@ void measurementPhaseChanged(VNAMeasurementPhases ph) {
static void measurementEmitDataPoint(int freqIndex, uint64_t freqHz, const VNAObservation& v, const complexf* ecal) {
if(ecal != nullptr) {
complexf scale = complexf(1., 0.)/v[1];
if(ecalState == ECAL_STATE_DONE) {
scale *= 0.2f;
measuredEcal[0][freqIndex] = measuredEcal[0][freqIndex] * 0.8f + ecal[0] * scale;
measuredEcal[1][freqIndex] = measuredEcal[1][freqIndex] * 0.8f + ecal[1] * scale;
measuredEcal[2][freqIndex] = measuredEcal[2][freqIndex] * 0.8f + ecal[2] * scale;
} else {

if(collectMeasurementType >= 0) {
// we are collecting a measurement for calibration
measuredEcal[0][freqIndex] = ecal[0] * scale;
measuredEcal[1][freqIndex] = ecal[1] * scale;
measuredEcal[2][freqIndex] = ecal[2] * scale;
}
if(ecalState == ECAL_STATE_MEASURING
&& freqIndex == vnaMeasurement.sweepPoints - 1) {
ecalState = ECAL_STATE_2NDSWEEP;
} else if(ecalState == ECAL_STATE_2NDSWEEP) {
ecalState = ECAL_STATE_DONE;
vnaMeasurement.ecalIntervalPoints = 8;
current_props._cal_data[collectMeasurementType][freqIndex] = v[0]/v[1] - measuredEcal[0][freqIndex];

if(collectMeasurementState == 0) {
collectMeasurementState = 1;
collectMeasurementOffset = freqIndex;
} else if(collectMeasurementState == 1 && collectMeasurementOffset == freqIndex) {
collectMeasurementState = 2;
collectMeasurementOffset += 2;
if(collectMeasurementOffset >= vnaMeasurement.sweepPoints)
collectMeasurementOffset -= vnaMeasurement.sweepPoints;
} else if(collectMeasurementState == 2 && collectMeasurementOffset == freqIndex) {
collectMeasurementState = 0;
collectMeasurementType = -1;
eventQueue.enqueue(collectMeasurementCB);
}
} else {
if(ecalState == ECAL_STATE_DONE) {
scale *= 0.2f;
measuredEcal[0][freqIndex] = measuredEcal[0][freqIndex] * 0.8f + ecal[0] * scale;
measuredEcal[1][freqIndex] = measuredEcal[1][freqIndex] * 0.8f + ecal[1] * scale;
measuredEcal[2][freqIndex] = measuredEcal[2][freqIndex] * 0.8f + ecal[2] * scale;
} else {
measuredEcal[0][freqIndex] = ecal[0] * scale;
measuredEcal[1][freqIndex] = ecal[1] * scale;
measuredEcal[2][freqIndex] = ecal[2] * scale;
}
if(ecalState == ECAL_STATE_MEASURING
&& freqIndex == vnaMeasurement.sweepPoints - 1) {
ecalState = ECAL_STATE_2NDSWEEP;
} else if(ecalState == ECAL_STATE_2NDSWEEP) {
ecalState = ECAL_STATE_DONE;
vnaMeasurement.ecalIntervalPoints = MEASUREMENT_ECAL_INTERVAL;
}
}
}
// enqueue new data point
Expand Down Expand Up @@ -440,6 +469,7 @@ void measurement_setup() {
vnaMeasurement.frequencyChanged = [](uint64_t freqHz) {
setFrequency(freqHz);
};
vnaMeasurement.nPeriods = MEASUREMENT_NPERIODS_NORMAL;
vnaMeasurement.init();
updateSweepParams();
}
Expand Down Expand Up @@ -548,8 +578,19 @@ void processDataPoint() {
while(rdRPos != rdWPos) {
usbDataPoint& usbDP = usbTxQueue[rdRPos];
VNAObservation& value = usbDP.value;
measured[0][usbDP.freqIndex] = value[0]/value[1] - measuredEcal[0][usbDP.freqIndex];
measured[1][usbDP.freqIndex] = value[2]/value[1] - measuredEcal[2][usbDP.freqIndex]*0.8f;
int freqIndex = usbDP.freqIndex;
auto refl = value[0]/value[1] - measuredEcal[0][freqIndex];
auto thru = value[2]/value[1] - measuredEcal[2][freqIndex]*0.8f;
if(current_props._cal_status & CALSTAT_APPLY) {
//refl -= current_props._cal_data[CAL_LOAD][usbDP.freqIndex];
refl = SOL_compute_reflection(
current_props._cal_data[CAL_SHORT][freqIndex],
current_props._cal_data[CAL_OPEN][freqIndex],
current_props._cal_data[CAL_LOAD][freqIndex],
refl);
}
measured[0][usbDP.freqIndex] = refl;
measured[1][usbDP.freqIndex] = thru;

rdRPos = (rdRPos + 1) & usbTxQueueMask;
}
Expand Down Expand Up @@ -672,10 +713,19 @@ extern "C" void *memcpy(char *dest, const char *src, uint32_t n) {
namespace UIActions {

void cal_collect(int type) {

collectMeasurementCB = [type]() {
vnaMeasurement.ecalIntervalPoints = MEASUREMENT_ECAL_INTERVAL;
vnaMeasurement.nPeriods = MEASUREMENT_NPERIODS_NORMAL;
current_props._cal_status |= (1 << type);
ui_cal_collected();
};
__sync_synchronize();
vnaMeasurement.ecalIntervalPoints = 1;
vnaMeasurement.nPeriods = MEASUREMENT_NPERIODS_CALIBRATING;
collectMeasurementType = type;
}
void cal_done(void) {

current_props._cal_status |= CALSTAT_APPLY;
}


Expand Down Expand Up @@ -710,6 +760,8 @@ namespace UIActions {
default: return;
}
updateSweepParams();
current_props._cal_status = 0;
draw_cal_status();
}
freqHz_t get_sweep_frequency(int type) {
switch (type) {
Expand Down
18 changes: 13 additions & 5 deletions ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ enum {
uint8_t ui_mode = UI_NORMAL;
uint8_t keypad_mode;
int8_t selection = 0;
bool ui_disabled = false;

typedef struct {
uint8_t type;
Expand Down Expand Up @@ -352,18 +353,20 @@ menu_calop_cb(UIEvent evt, int item)
case 2: // LOAD
cal_collect(CAL_LOAD);
break;
case 3: // ISOLN
cal_collect(CAL_ISOLN);
break;
case 4: // THRU
cal_collect(CAL_THRU);
break;
}
selection = item+1;
//selection = item+1;
ui_disabled = true;
draw_cal_status();
draw_menu();
}

void ui_cal_collected() {
ui_disabled = false;
draw_menu();
}

extern const menuitem_t menu_save[];

Expand Down Expand Up @@ -786,7 +789,6 @@ const menuitem_t menu_calop[] = {
{ MT_CALLBACK, "OPEN", menu_calop_cb },
{ MT_CALLBACK, "SHORT", menu_calop_cb },
{ MT_CALLBACK, "LOAD", menu_calop_cb },
{ MT_CALLBACK, "ISOLN", menu_calop_cb },
{ MT_CALLBACK, "THRU", menu_calop_cb },
{ MT_CALLBACK, "DONE", menu_caldone_cb },
{ MT_CANCEL, S_LARROW" BACK", NULL },
Expand Down Expand Up @@ -1263,6 +1265,10 @@ menu_item_modify_attribute(const menuitem_t *menu, int item,
*fg = 0xffff;
}
}
if(*bg == 0x0000 && ui_disabled)
*bg = 0x6666;
if(*fg == 0x0000 && ui_disabled)
*fg = 0x6666;
}

void
Expand Down Expand Up @@ -1915,6 +1921,8 @@ ui_process(UIEvent evt)
return;
}

if(ui_disabled) return;

if(evt.isTouchPress())
awd_count++;

Expand Down
3 changes: 3 additions & 0 deletions ui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@ void enter_dfu(void);
void ui_mode_menu(void);
void show_usb_data_mode(void);
void draw_numeric_input(const char *buf);
void draw_menu();

void ui_cal_collected();

void show_dmesg();

0 comments on commit 27272e5

Please sign in to comment.