📄 displayroutines.cpp
字号:
catch(System::IO::IOException* pe)
{
MessageBox::Show(S"Error", pe->Message);
}
__finally
{
if (fs)
fs->Flush();
if (bw)
bw->Close();
if (fs)
fs->Close();
}
}
/// Convert Log Tx Level to linear value needed by DAC register
unsigned short TxLevLinear(int tranLevel)
{
// 0 dbm is the max level. Corresponds to 4095 decimal for IDAC control register.
// 0 dbm -> 4095 -20 dbm -> 410 -40 dbm -> 41
unsigned short linlevel = (unsigned short)((double)MAX_DDS_LEVEL * pow(10.0,(((double)tranLevel)/20.0)) + 0.5);
return (linlevel);
};
/// Convert linear DAC level to dBm. 4095 = 0 dBm.
float dBFromLinear(int DAClevel)
{
float dB = (float)(20.0 * log10 ((float(DAClevel)/(float)MAX_DDS_LEVEL)));
return (dB);
};
/// Convert Return Loss (S11 mag) to SWR, then to Y-coordinate.
int ToDisplayAsSWR(double mag, int height, int scaledB)
{
/// Derive vertical plot value using dB scale factor as SWR range.
/// scaledB has value 10, 5, 2 or 1 dB/division.
/// Interpret it as 10 SWR units full scale - i.e. 1 to 11
/// or as 5 units (1 to 6), 2 units (1..3), or as 1 unit (1..2)
if (mag > 1.0) // clip display if S11 mag is greater than unity
mag = 1.0; // indicates something wrong in compensation
int vertical;
double swr = ( 1.0 + mag ) / ( 1.0 - mag);
vertical = (int)(((swr - 1.0) / (double)scaledB) * (double)height);
vertical = height - vertical; // flip display -- SWR = 1 is at bottom line of display
if (vertical > height) // crop display - probably a better way to do this
vertical = height;
if (vertical < 0)
vertical = 0;
return(vertical); // return Y as positive number
}
/// Export S-parameters to file.
void ExportSParams(int mode, FrequencyGrid * FG,
double S11Mag __gc[], double S11Phs __gc[],
double S21Mag __gc[], double S21Phs __gc[],
double S22Mag __gc[], double S22Phs __gc[],
double S12Mag __gc[], double S12Phs __gc[])
{
/// Uses Mag/Phase Forward and Reverse held in internal storage variables.
/// mode: 0 -> S2P rectangular mode, 1 -> S2P polar mode, 2-> CSV rectangular mode
double FwdTranMagdB, FwdTranPhsDeg, FwdReflMagdB, FwdReflPhsDeg;
double RevTranMagdB, RevTranPhsDeg, RevReflMagdB, RevReflPhsDeg;
double FwdTranRe, FwdTranIm, FwdReflRe, FwdReflIm;
double RevTranRe, RevTranIm, RevReflRe, RevReflIm;
FileStream* fs;
StreamWriter* sw;
SaveFileDialog* outfile = new SaveFileDialog();
if(mode<2) // S2P format
outfile->Filter = "s-parameter 2-port files (*.s2p)|*.s2p";
else // CSV format
outfile->Filter = "CSV format files (*.csv)|*.csv";
outfile->AddExtension = true;
if (outfile->ShowDialog() != DialogResult::OK)
return;
try
{
// Create a filestream & stream writer
fs = new FileStream(outfile->FileName, FileMode::Create, FileAccess::Write);
sw = new StreamWriter(fs);
// Write Header for S-parameter file
sw->WriteLine(S"! Vector Network Analyzer VNA R2"); // put string header on outfile
sw->WriteLine(S"! Tucson Amateur Packet Radio"); // put string header on outfile
DateTime today = DateTime::Now;
sw->Write(S"! ");
sw->Write(today.ToLongDateString());
sw->Write(S" ");
sw->WriteLine(today.ToLongTimeString());
// Header line defines type of file
if (mode==1) // S2P polar
{
sw->WriteLine(S"! Frequency S11 S21 S12 S22");
sw->WriteLine(S"# HZ S DB R 50"); // polar is in DB amplitude and degrees WRT 50 ohms
}
if (mode==0) // S2P rectangular
{
sw->WriteLine(S"! Frequency S11 S21 S12 S22");
sw->WriteLine(S"# HZ S RI R 50"); // rectangular is in Real and Imaginary WRT 50 ohms
}
if (mode==2) // CSV rectangular
{
sw->WriteLine(S"50+j0,\"=COMPLEX(50,0)\",,Unity,\"=COMPLEX(1,0)\"");
sw->WriteLine(S",");
sw->WriteLine(S"Frequency (Hz.),S11,S21,S12,S22,,Zin,Zout");
}
// write out the parameters
if (mode==1) // S2P polar format
for(int i=0; i<FG->Points; i++)
{
FwdReflMagdB = 20.0 * log10(S11Mag[i]);
FwdReflPhsDeg = S11Phs[i];
FwdTranMagdB = 20.0 * log10(S21Mag[i]);
FwdTranPhsDeg = S21Phs[i];
RevTranMagdB = 20.0 * log10(S12Mag[i]);
RevTranPhsDeg = S12Phs[i];
RevReflMagdB = 20.0 * log10(S22Mag[i]);
RevReflPhsDeg = S22Phs[i];
sw->Write(FG->Frequency(i).ToString("D9")); sw->Write(S" ");
sw->Write(FwdReflMagdB.ToString("F3")); sw->Write(S" ");
sw->Write(FwdReflPhsDeg.ToString("F3")); sw->Write(S" ");
sw->Write(FwdTranMagdB.ToString("F3")); sw->Write(S" ");
sw->Write(FwdTranPhsDeg.ToString("F3")); sw->Write(S" ");
sw->Write(RevTranMagdB.ToString("F3")); sw->Write(S" ");
sw->Write(RevTranPhsDeg.ToString("F3")); sw->Write(S" ");
sw->Write(RevReflMagdB.ToString("F3")); sw->Write(S" ");
sw->WriteLine(RevReflPhsDeg.ToString("F3"));
}
if (mode==0) // S2P rectangular format
for(int i=0; i<FG->Points; i++)
{
FwdReflRe = S11Mag[i] * cos(S11Phs[i] * DEGR2RAD);
FwdReflIm = S11Mag[i] * sin(S11Phs[i] * DEGR2RAD);
FwdTranRe = S21Mag[i] * cos(S21Phs[i] * DEGR2RAD);
FwdTranIm = S21Mag[i] * sin(S21Phs[i] * DEGR2RAD);
RevTranRe = S12Mag[i] * cos(S12Phs[i] * DEGR2RAD);
RevTranIm = S12Mag[i] * sin(S12Phs[i] * DEGR2RAD);
RevReflRe = S22Mag[i] * cos(S22Phs[i] * DEGR2RAD);
RevReflIm = S22Mag[i] * sin(S22Phs[i] * DEGR2RAD);
sw->Write(FG->Frequency(i).ToString("D9")); sw->Write(S" ");
sw->Write(FwdReflRe.ToString("E5")); sw->Write(S" ");
sw->Write(FwdReflIm.ToString("E5")); sw->Write(S" ");
sw->Write(FwdTranRe.ToString("E5")); sw->Write(S" ");
sw->Write(FwdTranIm.ToString("E5")); sw->Write(S" ");
sw->Write(RevTranRe.ToString("E5")); sw->Write(S" ");
sw->Write(RevTranIm.ToString("E5")); sw->Write(S" ");
sw->Write(RevReflRe.ToString("E5")); sw->Write(S" ");
sw->WriteLine(RevReflIm.ToString("E5"));
}
if (mode==2) // CSV rectangular format
for(int i=0; i<FG->Points; i++)
{
FwdReflRe = S11Mag[i] * cos(S11Phs[i] * DEGR2RAD);
FwdReflIm = S11Mag[i] * sin(S11Phs[i] * DEGR2RAD);
FwdTranRe = S21Mag[i] * cos(S21Phs[i] * DEGR2RAD);
FwdTranIm = S21Mag[i] * sin(S21Phs[i] * DEGR2RAD);
RevTranRe = S12Mag[i] * cos(S12Phs[i] * DEGR2RAD);
RevTranIm = S12Mag[i] * sin(S12Phs[i] * DEGR2RAD);
RevReflRe = S22Mag[i] * cos(S22Phs[i] * DEGR2RAD);
RevReflIm = S22Mag[i] * sin(S22Phs[i] * DEGR2RAD);
sw->Write(FG->Frequency(i).ToString("D9")); sw->Write(S",");
sw->Write(S"\"=COMPLEX({0},{1})\",",FwdReflRe.ToString("E5"),FwdReflIm.ToString("E5"));
sw->Write(S"\"=COMPLEX({0},{1})\",",FwdTranRe.ToString("E5"),FwdTranIm.ToString("E5"));
sw->Write(S"\"=COMPLEX({0},{1})\",",RevTranRe.ToString("E5"),RevTranIm.ToString("E5"));
sw->Write(S"\"=COMPLEX({0},{1})\",,",RevReflRe.ToString("E5"),RevReflIm.ToString("E5"));
// build row number - data starts in the 7th row of the spreadsheet
int rownum = i+7;
String * Row = rownum.ToString();
// Zin (S11 converted to impedance)
//=IMPRODUCT(50ohms,(IMDIV(IMSUM(unity,S11),IMSUB(unity,S11)))
sw->Write(S"\"=IMPRODUCT($B$4,(IMDIV(IMSUM($E$4,$B{0}),IMSUB($E$4,$B{0}))))\",",Row);
//Zout (S22 converted to impedance)
sw->WriteLine(S"\"=IMPRODUCT($B$4,(IMDIV(IMSUM($E$4,$E{0}),IMSUB($E$4,$E{0}))))\",",Row);
}
sw->WriteLine();
}
catch(System::IO::IOException* pe)
{
MessageBox::Show(S"File Output Error", pe->Message);
}
__finally
{
if (sw)
sw->Flush();
if (sw)
sw->Close();
if (fs)
fs->Close();
}
}
/// Store S-parameters to internal temporary storage.
void StoreSParams(bool calmode, FrequencyGrid * FG, CalDataSet * CalData,
unsigned short trace2 __gc[], unsigned short trace3 __gc[], unsigned short trace4 __gc[],
unsigned short trace7 __gc[], unsigned short trace8 __gc[], unsigned short trace9 __gc[],
unsigned short trace11 __gc[], unsigned short trace12 __gc[],
double reflMag __gc[], double reflPhs __gc[], double tranMag __gc[], double tranPhs __gc[])
{
/// Store Forward caller gives us pointers to Forward storage,
/// store Reverse caller gives us pointers to Reverse storage
/// calmode: 1 -> use fixture calibration
double fmagnitude; // 0 to 1
double fphase; // -180 to +180
double& rmag = fmagnitude;
double& rphs = fphase;
for (int i=0; i<FG->Points; i++) // Display measurements on the frequency grid
{
// Compute S11 or S22
CalData->ResolveReflPolar(trace3[i], trace4[i], trace2[i], FG->Frequency(i), rmag, rphs, true);
if (calmode)
CorrectS11(CalData, FG->Frequency(i), fmagnitude, fphase, rmag, rphs);
reflMag[i] = fmagnitude; // store reflected component in polar form
reflPhs[i] = fphase;
// Compute S21 or S12
CalData->ResolveTranPolar(trace8[i], trace9[i], trace7[i], trace11[i], trace12[i], FG->Frequency(i), rmag, rphs);
if (calmode)
CorrectS21(CalData, FG->Frequency(i), fmagnitude, fphase, rmag, rphs);
tranMag[i] = fmagnitude; // store transmitted component in polar form
tranPhs[i] = fphase;
}
}
// Linear interpolation of Xval between Xlow and Xhigh yielding Y result between Ylow and Yhi
//double public Interpolate(int Xval, int Xlow, int Ylow, int Xhi, int Yhi)
//{
// float slope = ((float)Yhi - (float)Ylow) / ((float)Xhi-(float)Xlow);
// double result = (float)Ylow + (((float)Xval - (float)Xlow) * slope);
// return(result);
//}
//double public Interpolate(float Xval, float Xlow, float Ylow, float Xhi, float Yhi)
//{
// float slope = (Yhi - Ylow) / (Xhi-Xlow);
// double result = Ylow + ((Xval - Xlow) * slope);
// return(result);
//}
// Median filtering routine. Input is 7 measurements [0..6]. Returns the median value.
int Median7(unsigned short data __gc[], int index)
{
int i, j;
unsigned short temp;
unsigned short numbers[7];
for (i=0; i<7; i++) // make a local copy of the data
numbers[i] = data[index + i]; // don't alter what was given to us
// bubble sort the elements
for (i=6; i>=0; i--)
for (j=1; j<=i; j++)
if (numbers[j-1] > numbers[j])
{
temp = numbers[j-1];
numbers[j-1] = numbers[j];
numbers[j] = temp;
}
return(numbers[3]); // the median value
}
// Median filtering routine. Input is 7 measurements. Returns the median value.
int Median7i(int numbers __gc[])
{
int i, j;
unsigned short temp;
// bubble sort the elements
for (i=6; i>=0; i--)
for (j=1; j<=i; j++)
if (numbers[j-1] > numbers[j])
{
temp = numbers[j-1];
numbers[j-1] = numbers[j];
numbers[j] = temp;
}
return(numbers[3]); // the median value
}
// Range routine. Determine range of middle 5 samples in a group of 7 samples.
// If the range is small, then the samples look like one another even if one
// of them is a glitch.
int Range(unsigned short data __gc[], int index)
{
int i, j;
unsigned short temp;
unsigned short numbers[7];
for (i=0; i<7; i++) // make a local copy of the data
numbers[i] = data[index + i]; // don't alter what was given to us
// bubble sort the elements
for (i=6; i>=0; i--)
for (j=1; j<=i; j++)
if (numbers[j-1] > numbers[j])
{
temp = numbers[j-1];
numbers[j-1] = numbers[j];
numbers[j] = temp;
}
return(numbers[5]-numbers[1]); // the range of central samples
}
// DrawLine routines that checks and bounds points to within display rectangle.
// The gr->SetClip() function should do this, but certain values of arguments to DrawLine outside the
// clipped region cause it to throw an exception rather than clip. These routines fix that problem.
void DrawLineBound(System::Drawing::Graphics * gr, System::Drawing::Rectangle r,
System::Drawing::Pen * pen, int x1, int y1, int x2, int y2)
{
if(x1 < r.X) // bound x1, x2, y1, y2 within the rectangle r
x1 = r.X;
if(x1 > r.Right)
x1 = r.Right;
if(x2 < r.X)
x2 = r.X;
if(x2 > r.Right)
x2 = r.Right;
if(y1 < r.Y)
y1 = r.Y;
if(y1 > r.Bottom)
y1 = r.Bottom;
if(y2 < r.Y)
y2 = r.Y;
if(y2 > r.Bottom)
y2 = r.Bottom;
gr->DrawLine(pen, x1, y1, x2, y2); // draw the bounded line
}
void DrawLineBound(System::Drawing::Graphics * gr, System::Drawing::Rectangle r,
System::Drawing::Pen * pen, System::Drawing::Point p1, System::Drawing::Point p2)
{
DrawLineBound(gr, r, pen, p1.X, p1.Y, p2.X, p2.Y); // draw the bounded line
}
void AddPolar(double& mag, double& phase, double magadd, double phaseadd)
{
double x, y;
x = mag * cos(phase*DEGR2RAD);
y = mag * sin(phase*DEGR2RAD);
x += magadd * cos(phaseadd*DEGR2RAD);
y += magadd * sin(phaseadd*DEGR2RAD);
mag = sqrt(x*x+y*y);
phase = atan2(y,x) * RAD2DEGR;
}
// Convert MeasurementDelay string to target's loop count
int MeasureDelayStringToCount(String * value)
{
// time delay is very roughly 30 usec + loopcount * 40 microseconds
// Values other than "FAST" use the "SLOW" mode of the buffer
if(String::Compare(value, S"Fast") == 0)
return 0;
if(String::Compare(value, S"30 us") == 0)
return 0;
if(String::Compare(value, S"100 us") == 0)
return 2;
if(String::Compare(value, S"300 us") == 0)
return 6;
if(String::Compare(value, S"1 ms") == 0)
return 16;
if(String::Compare(value, S"3 ms") == 0)
return 48;
if(String::Compare(value, S"10 ms") == 0)
return 160;
return 0; // no delay if unexpected string
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -