Improve impulse response interpolation
This commit is contained in:
parent
7ca93af620
commit
329f4487ee
@ -214,7 +214,7 @@ void EyeDiagramDialog::updateThread(unsigned int width, unsigned int height)
|
||||
updating = false;
|
||||
return;
|
||||
}
|
||||
if(datarate <= trace->getSample(0).x) {
|
||||
if(datarate <= 0) {
|
||||
emit calculationStatus("Data rate too low");
|
||||
updating = false;
|
||||
return;
|
||||
@ -347,16 +347,27 @@ void EyeDiagramDialog::updateThread(unsigned int width, unsigned int height)
|
||||
}
|
||||
}
|
||||
|
||||
auto scale = timestep / (length / (samples - 1));
|
||||
unsigned long convolutedSize = length / timestep;
|
||||
if(convolutedSize > inVec.size()) {
|
||||
// impulse response is longer than what we display, truncate
|
||||
convolutedSize = inVec.size();
|
||||
}
|
||||
impulseVec.resize(convolutedSize);
|
||||
/*
|
||||
* we can't use the impulse response directly because we most likely need samples inbetween
|
||||
* the calculated values. Interpolation is available but if our sample spacing here is much
|
||||
* wider than the impulse response data, we might miss peaks (or severely miscalculate their
|
||||
* amplitude.
|
||||
* Instead, the step response is interpolated and the impulse response determined by deriving
|
||||
* it from the interpolated step response data. As the step response is the integrated imulse
|
||||
* response data, we can't miss narrow peaks that way.
|
||||
*/
|
||||
double lastStepResponse = 0.0;
|
||||
for(unsigned long i=0;i<convolutedSize;i++) {
|
||||
auto x = i*timestep;
|
||||
impulseVec[i] = tdr->getInterpolatedSample(x).y.real() * scale;
|
||||
auto step = tdr->getInterpolatedStepResponse(x);
|
||||
impulseVec[i] = step - lastStepResponse;
|
||||
lastStepResponse = step;
|
||||
}
|
||||
|
||||
eyeTimeShift += (risetime + falltime) * 1.25 / 4;
|
||||
|
@ -106,6 +106,37 @@ double TraceMath::getStepResponse(unsigned int index)
|
||||
}
|
||||
}
|
||||
|
||||
double TraceMath::getInterpolatedStepResponse(double x)
|
||||
{
|
||||
if(stepResponse.size() != data.size()) {
|
||||
// make sure all the step response data is available
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
double ret = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
if(data.size() == 0 || x < data.front().x || x > data.back().x) {
|
||||
ret = std::numeric_limits<double>::quiet_NaN();
|
||||
} else {
|
||||
auto it = lower_bound(data.begin(), data.end(), x, [](const Data &lhs, const double x) -> bool {
|
||||
return lhs.x < x;
|
||||
});
|
||||
if(it->x == x) {
|
||||
ret = stepResponse[it - data.begin()];
|
||||
} else {
|
||||
// no exact match, needs to interpolate
|
||||
unsigned int highIndex = it - data.begin();
|
||||
unsigned int lowIndex = highIndex - 1;
|
||||
auto high = *it;
|
||||
it--;
|
||||
auto low = *it;
|
||||
double alpha = (x - low.x) / (high.x - low.x);
|
||||
ret = stepResponse[lowIndex] * (1 - alpha) + stepResponse[highIndex] * alpha;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
TraceMath::Data TraceMath::getInterpolatedSample(double x)
|
||||
{
|
||||
Data ret;
|
||||
|
@ -91,8 +91,9 @@ public:
|
||||
static TypeInfo getInfo(Type type);
|
||||
|
||||
Data getSample(unsigned int index);
|
||||
double getStepResponse(unsigned int index);
|
||||
Data getInterpolatedSample(double x);
|
||||
double getStepResponse(unsigned int index);
|
||||
double getInterpolatedStepResponse(double x);
|
||||
unsigned int numSamples();
|
||||
|
||||
static QString dataTypeToString(DataType type);
|
||||
|
Loading…
Reference in New Issue
Block a user