Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0b35104b4d13
Choose a base ref
...
head repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 28b440a602d8
Choose a head ref
  • 1 commit
  • 3 files changed
  • 1 contributor

Commits on Jul 23, 2020

  1. Copy the full SHA
    28b440a View commit details
Showing with 67 additions and 18 deletions.
  1. +47 −8 scopehal/TouchstoneParser.cpp
  2. +1 −1 scopehal/TouchstoneParser.h
  3. +19 −9 scopeprotocols/DeEmbedDecoder.cpp
55 changes: 47 additions & 8 deletions scopehal/TouchstoneParser.cpp
Original file line number Diff line number Diff line change
@@ -92,8 +92,29 @@ SParameterPoint SParameterVector::InterpolatePoint(float frequency)
float amp_hi = m_points[last_hi].m_amplitude;
ret.m_amplitude = amp_lo + (amp_hi - amp_lo)*frac;

//TODO: figure out phase. For now leave it at zero (i.e. don't de-embed phase, just do scalar amplitude correction)
ret.m_phase = 0;
//Interpolate phase (angles in radians)
float phase_lo = m_points[last_lo].m_phase;
float phase_hi = m_points[last_hi].m_phase;

//If both values have the same sign, no wrapping needed.
//If values have opposite signs, but are smallish, we cross at 0 vs +/- pi, so also no wrapping needed.
if(
( (phase_hi > 0) && (phase_lo > 0) ) ||
( (fabs(phase_hi) < M_PI_4) && (fabs(phase_lo) < M_PI_4) )
)
{
ret.m_phase = phase_lo + (phase_hi - phase_lo)*frac;
}

//Wrapping needed.
//Shift everything by pi, then interpolate normally, then shift back.
else
{
phase_lo += M_PI;
phase_hi += M_PI;

ret.m_phase = phase_lo + (phase_hi - phase_lo)*frac - M_PI;
}

ret.m_frequency = frequency;
return ret;
@@ -146,6 +167,7 @@ bool TouchstoneParser::Load(string fname)

//Read line by line.
char line[256];
double unit_scale = 1;
while(!feof(fp))
{
fgets(line, sizeof(line), fp);
@@ -168,30 +190,47 @@ bool TouchstoneParser::Load(string fname)
}

//Figure out units
if(0 != strcmp(freq_unit, "MHZ"))
string funit(freq_unit);
if(funit == "MHZ")
unit_scale = 1e6;
else if(funit == "GHZ")
unit_scale = 1e9;
else if(funit == "KHZ")
unit_scale = 1e3;
else if(funit == "HZ")
unit_scale = 1;
else
{
LogError("S2P frequency units other than MHZ not yet supported (got %s)\n", freq_unit);
LogError("Unrecognized S2P frequency unit (got %s)\n", freq_unit);
return false;
}
if(0 != strcmp(volt_unit, "MA"))
{
LogError("S2P voltage units other than MA not yet supported (got %s)\n", volt_unit);
LogError("S2P formats other than mag-angle not yet supported (got %s)\n", volt_unit);
return false;
}

continue;
}

//Each S2P line is formatted as freq s11 s21 s12 s22
float mhz, s11m, s11p, s21m, s21p, s12m, s12p, s22m, s22p;
if(9 != sscanf(line, "%f %f %f %f %f %f %f %f %f", &mhz, &s11m, &s11p, &s21m, &s21p, &s12m, &s12p, &s22m, &s22p))
float hz, s11m, s11p, s21m, s21p, s12m, s12p, s22m, s22p;
if(9 != sscanf(line, "%f %f %f %f %f %f %f %f %f", &hz, &s11m, &s11p, &s21m, &s21p, &s12m, &s12p, &s22m, &s22p))
{
LogError("Malformed S2P line \"%s\"", line);
return false;
}

//Rescale frequency
hz *= unit_scale;

//Convert angles from degrees to radians
s11p *= (M_PI / 180);
s21p *= (M_PI / 180);
s12p *= (M_PI / 180);
s22p *= (M_PI / 180);

//Save everything
float hz = mhz * 1e6;
m_params[SPair(1,1)]->m_points.push_back(SParameterPoint(hz, s11m, s11p));
m_params[SPair(2,1)]->m_points.push_back(SParameterPoint(hz, s21m, s21p));
m_params[SPair(1,2)]->m_points.push_back(SParameterPoint(hz, s12m, s12p));
2 changes: 1 addition & 1 deletion scopehal/TouchstoneParser.h
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ class SParameterPoint

float m_frequency; //Hz
float m_amplitude; //magnitude
float m_phase; //radians
float m_phase; //radians from -pi to +pi
};

/**
28 changes: 19 additions & 9 deletions scopeprotocols/DeEmbedDecoder.cpp
Original file line number Diff line number Diff line change
@@ -89,12 +89,16 @@ bool DeEmbedDecoder::NeedsConfig()

void DeEmbedDecoder::SetDefaultName()
{
string fname = m_parameters[m_fname].GetFileName();
string base = basename(fname.c_str());

char hwname[256];
snprintf(
hwname,
sizeof(hwname),
"DeEmbed(%s)",
m_channels[0]->m_displayname.c_str()
"DeEmbed(%s, %s)",
m_channels[0]->m_displayname.c_str(),
base.c_str()
);

m_hwname = hwname;
@@ -179,16 +183,22 @@ void DeEmbedDecoder::Refresh()
//Do the actual de-embed
for(size_t i=0; i<nouts; i++)
{
//Calculate frequency of this bin and look up the resampled S21 parameter for it
float freq = bin_hz * i;
auto point = m_sparams.SamplePoint(2, 1, freq);
//Resample the S-parameter file for our point
auto point = m_sparams.SamplePoint(2, 1, bin_hz * i);
float cosval = cos(-point.m_phase);
float sinval = sin(-point.m_phase);

//Uncorrected complex value
float real_orig = rdout[i*2 + 0];
float imag_orig = rdout[i*2 + 1];

//TODO: Phase correction
//Phase correction
float real = real_orig*cosval - imag_orig*sinval;
float imag = real_orig*sinval + imag_orig*cosval;

//Amplitude correction
//We need to scale both real and imaginary parts
rdout[i*2 + 0] /= point.m_amplitude;
rdout[i*2 + 1] /= point.m_amplitude;
rdout[i*2 + 0] = real / point.m_amplitude;
rdout[i*2 + 1] = imag / point.m_amplitude;
}

//Set up the inverse FFT