📄 displayroutines.cpp
字号:
for (freq = 0; freq<21; freq++) // compute at each frequency index
{
sumx = 0; sumy = 0;
sumxsq = 0; sumysq = 0; sumxy = 0;
sumf = 0;
for (level=0; level<26; level++) // compute from 0 dbm to -25 dbm
{
sumx += Mag[freq, level];
sumy += -level;
sumxsq += Mag[freq, level] * Mag[freq, level];
sumysq += level * level;
sumxy += Mag[freq, level] * -level;
}
m[freq] = (double)(n * sumxy - sumx * sumy) / (double)( n * sumxsq - sumx * sumx);
b[freq] = (double)(sumy - m[freq] * sumx) / (double)n;
r[freq] = (double)(n * sumxy - sumx * sumy) / sqrt((double)(n * sumxsq - sumx * sumx)* (n * sumysq - sumy * sumy));
for (level=50; level<=59; level++) // find count where detector curve flatens out
sumf += Mag[freq, level]; // Take average of bottom 10 level readings
flat[freq] = (double)sumf/10.0;
// 10-24-2005 Adjust 'b' (intercept) to align with 0 db.
// b[freq] -= m[freq] * Mag[freq, 0] + b[freq] - pow(10.0, ((flat[freq] + t1 - Mag[freq, 0]) / t2));
}
// Test whether the AmpCal results are good or poor from 500 KHz to 100 MHz
for (freq=3; freq<19; freq++)
{
if(r[freq] < 0.92) // poor correlation between cal measurememnts and detector model
return(false);
}
return(true); // good correlation
}
/// Convert VNA I/Q raw count readings to degrees
double Detector::IQtoDegrees(int I, int Q)
{
double degrees;
degrees = RAD2DEGR * atan2((double)(centerPhase - Q),(double)(I - centerPhase));
if (degrees > 180.0)
degrees -= 360.0;
if (calibrated)
degrees += pherror[(int)degrees+180]; // index to phase table is offset by 180 degrees
// pherror could change degress to be outside the range -180 to +180 - wrap the phase
if (degrees > 180.0)
degrees -= 360.0;
if (degrees < -180.0)
degrees += 360.0;
return (degrees);
//// find whether I or Q is closer to centerline
//if (abs(I - centerPhase) < abs(Q - centerPhase)) // I is closer
//{
// if (Q < centerPhase)
// degrees = 90.0 - ((float)(I - centerPhase) / (float)(upperPhase - lowerPhase)) * 90.0;
// else
// degrees = -90.0 + ((float)(I - centerPhase) / (float)(upperPhase - lowerPhase)) * 90.0;
//}
//else // Q is closer
//{
// if (I < centerPhase)
// degrees = -quadratureError + 180.0 - ((float)(centerPhase - Q) / (float)(upperPhase - lowerPhase)) * 90.0;
// else
// degrees = -quadratureError + ((float)(centerPhase - Q) / (float)(upperPhase - lowerPhase)) * 90.0;
//}
}/// Convert detector magnitude count to dB. via piecewise linear fit
double Detector::MagTodBRefl(int Freq, int Mag)
{
double result;
int FreqBase, FreqBaseNext; // Two adjacent cal frequency points
double FreqRemainder; // remainder of freq between cal points
double dBResultFLow, dBResultFHigh; // Intermediate interpolation results
if (calibrated)
{
// Result is frequency-dependent. Interpolate the frequency between two datasets to construct
// a linear-frequency approximation of the cal data for the desired frequency.
// Every 200 KHz from 200K to 1MHz, then every 10 MHz up to 120 MHz.
// Index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// Freq: 200k 300k 400k 500k 600k 700k 800k 900k 1M 10M 20M 30M 40M 50M 60M 70M 80M 90M 100M 110M
// Build interpolated dataset between two frequencies
if (Freq <= 1000000) // 1 MHZ and below
{
FreqBase = (Freq - 200000)/100000;
FreqRemainder = (double)(Freq - (FreqBase + 2) * 100000)/100000; // Remainder of frequency, value between 0..1
}
else if (Freq < 10000000) // Between 1 and 10 MHz
{
FreqBase = 8;
FreqRemainder = (double)(Freq - 1000000)/9000000;
}
else // 10 MHz to 120 MHz
{
FreqBase = (Freq / 10000000) + 8; // Base is the integer part of the frequency index
FreqRemainder = (double)(Freq - (FreqBase - 8) * 10000000)/10000000; // Remainder of frequency, value between 0..1
}
if (FreqRemainder < 0.001)
FreqBaseNext = FreqBase; // Prevent index overflow
else
FreqBaseNext = FreqBase + 1;
// Mag is the S11 raw ADC count measured with +0 dbm Tx Level
// Compute dbm from y = mx + b. Coefficients previously derived from linear regression
dBResultFLow = m[FreqBase] * Mag + b[FreqBase];
dBResultFHigh = m[FreqBaseNext] * Mag + b[FreqBaseNext];
// Tweak the bottom end of the reading for detector bottoming out. Based on 'flat' and
// emperically derived correction.
dBResultFLow = dBResultFLow - pow(10.0, ((flat[FreqBase] + t1 - Mag) / t2));
dBResultFHigh = dBResultFHigh - pow(10.0, ((flat[FreqBaseNext] + t1 - Mag) / t2));
// interpolate result between FLow and FHigh
result = dBResultFLow + (dBResultFHigh - dBResultFLow) * FreqRemainder;
return(result);
}
else // uncalibrated measurement
return(((Mag-MAXTRANMAGNITUDE)/57.0)); // roughly 57 counts per dB
}
/// Convert detector magnitude count to dB. via table lookup
double Detector::MagTodBTran(int Freq, int Mag0, int Mag34, int Mag17)
{
// bool HotSig; // TRUE = receiving hot signal, use Mag34
double result;
int FreqBase, FreqBaseNext; // Two adjacent cal frequency points
double FreqRemainder; // remainder of freq between cal points
// int Mag;
double dBResultFLow, dBResultFHigh; // Intermediate interpolation results
const int t1 = 110; // twiddle factors for detector floor correction
const int t2 = 110;
if (calibrated)
{
// Result is frequency-dependent. Interpolate the frequency between two datasets to construct
// a linear-frequency approximation of the cal data for the desired frequency.
// Every 200 KHz from 200K to 1MHz, then every 10 MHz up to 120 MHz.
// Index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// Freq: 200k 300k 400k 500k 600k 700k 800k 900k 1M 10M 20M 30M 40M 50M 60M 70M 80M 90M 100M 110M
if (Freq <= 1000000) // 1 MHZ and below
{
FreqBase = (Freq - 200000)/100000;
FreqRemainder = (double)(Freq - (FreqBase + 2) * 100000)/100000; // Remainder of frequency, value between 0..1
}
else if (Freq < 10000000) // Between 1 and 10 MHz
{
FreqBase = 8;
FreqRemainder = (double)(Freq - 1000000)/9000000;
}
else // 10 MHz to 120 MHz
{
FreqBase = (Freq / 10000000) + 8; // Base is the integer part of the frequency index
FreqRemainder = (double)(Freq - (FreqBase - 8) * 10000000)/10000000; // Remainder of frequency, value between 0..1
}
if (FreqRemainder < 0.001)
FreqBaseNext = FreqBase; // Prevent index overflow
else
FreqBaseNext = FreqBase + 1;
// V1.4 and previous algorithm
// Mag0 is the S21 raw ADC count measured with +0 dbm Tx Level
// Use Mag0 when the loss of the load is greater than 40 db
// Mag40 is the S21 raw ADC count measured with -40 dbm Tx Level
// Use Mag40 when the loss of the load is less than 40 db
//
// Some examples:
// Load has 0 db loss: Mag0 = ~3500 overload Mag34 = ~2900
// Load has 20 db loss: Mag0 = ~3800 overload Mag34 = ~1900
// Load has 40 db loss: Mag0 = ~3000 Mag34 = ~870
// Load has 60 db loss: Mag0 = ~1900 Mag34 = ~870
// Load has 80 db loss: Mag0 = ~870 Mag34 = ~870
//
// So the algorithm is: if Mag0 > ~3000, then use Mag43. The value used is
// when (m * Mag0 + b) > 3 Which is when Mag0 > -37 dbm.
//if ((m[FreqBase] * Mag0 + b[FreqBase]) > 3.0)
//{
// Mag = Mag34; // use attenuated signal
// HotSig = true;
//}
//else
//{
// Mag = Mag0; // use unattenuated signal
// HotSig = false;
//}
//// Compute dbm from y = mx + b. Coefficients previously derived from linear regression
//dBResultFLow = m[FreqBase] * Mag + b[FreqBase];
//dBResultFHigh = m[FreqBaseNext] * Mag + b[FreqBaseNext];
//// Tweak the bottom end of the reading for detector bottoming out. Based on 'flat' and
//// emperically derived correction.
//dBResultFLow = dBResultFLow - pow(10.0, ((flat[FreqBase] + t1 - Mag) / t2));
//dBResultFHigh = dBResultFHigh - pow(10.0, ((flat[FreqBaseNext] + t1 - Mag) / t2));
//// interpolate result between FLow and FHigh
//result = dBResultFLow + (dBResultFHigh - dBResultFLow) * FreqRemainder;
//if(!HotSig)
// result -= 40.0; // possibly make 40.0 a table value??
//else
// // Using -34 as the Hot level (was -40)
// result -=6.0;
//return(result);
// New algorithm for V1.5 - use Mag0 until resultant amplitude is > 0 db,
// then use Mag17 until it's resultant amplitude is > 0 db, then use Mag34
// copy to local values so we can debug
int Hi, Mid, Lo;
Hi = Mag0, Mid = Mag17, Lo = Mag34;
// Compute dbm from y = mx + b. Coefficients previously derived from linear regression
dBResultFLow = m[FreqBase] * Mag0 + b[FreqBase];
dBResultFHigh = m[FreqBaseNext] * Mag0 + b[FreqBaseNext];
// Tweak the bottom end of the reading for detector bottoming out. Based on 'flat' and
// emperically derived correction.
dBResultFLow = dBResultFLow - pow(10.0, ((flat[FreqBase] + t1 - Mag0) / t2));
dBResultFHigh = dBResultFHigh - pow(10.0, ((flat[FreqBaseNext] + t1 - Mag0) / t2));
// interpolate result between FLow and FHigh
result = dBResultFLow + (dBResultFHigh - dBResultFLow) * FreqRemainder;
if(result <= 0)
return(result-(double)TARGETLOMAG-6.0);
// Compute dbm from y = mx + b. Coefficients previously derived from linear regression
dBResultFLow = m[FreqBase] * Mag17 + b[FreqBase];
dBResultFHigh = m[FreqBaseNext] * Mag17 + b[FreqBaseNext];
// Tweak the bottom end of the reading for detector bottoming out. Based on 'flat' and
// emperically derived correction.
dBResultFLow = dBResultFLow - pow(10.0, ((flat[FreqBase] + t1 - Mag17) / t2));
dBResultFHigh = dBResultFHigh - pow(10.0, ((flat[FreqBaseNext] + t1 - Mag17) / t2));
// interpolate result between FLow and FHigh
result = dBResultFLow + (dBResultFHigh - dBResultFLow) * FreqRemainder;
if(result<= 0)
return(result-(double)TARGETMIDMAG-6.0);
// Compute dbm from y = mx + b. Coefficients previously derived from linear regression
dBResultFLow = m[FreqBase] * Mag34 + b[FreqBase];
dBResultFHigh = m[FreqBaseNext] * Mag34 + b[FreqBaseNext];
// Tweak the bottom end of the reading for detector bottoming out. Based on 'flat' and
// emperically derived correction.
dBResultFLow = dBResultFLow - pow(10.0, ((flat[FreqBase] + t1 - Mag34) / t2));
dBResultFHigh = dBResultFHigh - pow(10.0, ((flat[FreqBaseNext] + t1 - Mag34) / t2));
// interpolate result between FLow and FHigh
result = dBResultFLow + (dBResultFHigh - dBResultFLow) * FreqRemainder;
return(result-6.0);
}
else // uncalibrated measurement
return(((Mag34-MAXTRANMAGNITUDE)/57.0) + 8.0); // roughly 57 counts per dB
}
// New 10-17-2005 Directivity Cal
void Detector::DirectivityCal(int DirectivityMag __gc[,]) // Record directivity data
{
// Store the raw ADC counts from the Directivity Calibration
// The consuming routine needs to convert them to mag+phase
for (int i=0; i<21; i++)
{
DirMag[i] = DirectivityMag[i, 0];
DirIphs[i] = DirectivityMag[i, 1];
DirQphs[i] = DirectivityMag[i, 2];
}
}
/// CalDataSet Constructor - allocate memory for Calibration Data
CalDataSet::CalDataSet(String* StartUpDir)
{
RxDet = new Detector(); // construct AD8702 objects
TxDet = new Detector();
EdReal = new double __gc[1024]; EdImag = new double __gc[1024];
EsReal = new double __gc[1024]; EsImag = new double __gc[1024];
EtReal = new double __gc[1024]; EtImag = new double __gc[1024];
ThReal = new double __gc[1024]; ThImag = new double __gc[1024];
S11shortReal = new double __gc[1024]; S11shortImag = new double __gc[1024];
S11openReal = new double __gc[1024]; S11openImag = new double __gc[1024];
S11termReal = new double __gc[1024], S11termImag = new double __gc[1024];
/// Try to read in the detector.ica file to pre-load the Detector calibration constants
/// If the file does not exist, warn user to run detector cal first
FileStream* fs;
BinaryReader* br;
String * filename = String::Concat(StartUpDir, S"\\detector.ica");
try
{
// Create a filestream & binary reader
fs = new FileStream(filename, FileMode::Open, FileAccess::Read);
br = new BinaryReader(fs);
}
catch(System::IO::IOException* pe)
{
MessageBox::Show(S"Detector Calibration File Not Found.\n\r"
S"Be sure to run Calibration->Detector Calibration... first", pe->Message,
MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
if (br)
br->Close();
if (fs)
fs->Close();
return;
}
// Define header to match file identifying type and version
String* recognized = new String(S"VNA Detector Calibration Data Set Version 2.0.2");
String* header;
header = br->ReadString(); // get string header on infile
if (String::Compare(recognized, header) != 0)
{
MessageBox::Show(
S"detector.ica file is incompatible type or version.\n\rExpecting Detector Version 2.0.2"
S"\n\rRe-run Detector Calibration because the file format \n\rmay have been changed by a new software release",
S"Error", MessageBoxButtons::OK, MessageBoxIcon::Error);
br->Close();
fs->Close();
return;
}
// read in the AD8302 Phase Detector constants and error table
try
{
RxDet->centerPhase = br->ReadInt32();
RxDet->lowerPhase = br->ReadInt32();
RxDet->upperPhase = br-> ReadInt32();
for (int degree = 0; degree<360; degree++)
RxDet->pherror[degree] = br->ReadDouble();
TxDet->centerPhase = br->ReadInt32();
TxDet->lowerPhase = br->ReadInt32();
TxDet->upperPhase = br->ReadInt32();
for (int degree = 0; degree<360; degree++)
TxDet->pherror[degree] = br->ReadDouble();
// Read in the AD8302 Amplitude Detector coefficient tables
for (int FreqIdx=0; FreqIdx<21; FreqIdx++)
{
RxDet->m[FreqIdx] = br->ReadDouble();
RxDet->b[FreqIdx] = br->ReadDouble();
RxDet->r[FreqIdx] = br->ReadDouble();
RxDet->flat[FreqIdx] = br->ReadDouble();
}
for (int FreqIdx=0; FreqIdx<21; FreqIdx++)
{
TxDet->m[FreqIdx] = br->ReadDouble();
TxDet->b[FreqIdx] = br->ReadDouble();
TxDet->r[FreqIdx] = br->ReadDouble();
TxDet->flat[FreqIdx] = br->ReadDouble();
}
// Read in the Internal Crystal Frequency Error
// Test the value to make sure it's within reasonable range.
FreqError = br->ReadInt32();
if (Math::Abs(FreqError) > 3000000)
FreqError = 0;
// Read in the directivity calibration raw values 10-18-2005
for (int i=0; i<21; i++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -