Skip to content

Commit

Permalink
Fix digital phosphor effect
Browse files Browse the repository at this point in the history
  • Loading branch information
David Graeff committed Dec 25, 2017
1 parent 4a1617f commit db4f8ba
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 96 deletions.
182 changes: 96 additions & 86 deletions openhantek/src/glgenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ GlGenerator::GlGenerator(DsoSettingsScope *scope, DsoSettingsView *view) : setti
const int DIVS_TIME_S2 = (int)DIVS_TIME - 2;
const int DIVS_VOLTAGE_S2 = (int)DIVS_VOLTAGE - 2;
const int vaGrid0Size = (int) ((DIVS_TIME * DIVS_SUB - 2) * DIVS_VOLTAGE_S2 +
(DIVS_VOLTAGE * DIVS_SUB - 2) * DIVS_TIME_S2 -
(DIVS_TIME_S2 * DIVS_VOLTAGE_S2)) * 2;
(DIVS_VOLTAGE * DIVS_SUB - 2) * DIVS_TIME_S2 -
(DIVS_TIME_S2 * DIVS_VOLTAGE_S2)) * 2;

vaGrid[0].resize(vaGrid0Size);
std::vector<GLfloat>::iterator glIterator = vaGrid[0].begin();
Expand Down Expand Up @@ -105,106 +105,116 @@ const std::vector<GLfloat> &GlGenerator::grid(int a) const { return vaGrid[a]; }

bool GlGenerator::isReady() const { return ready; }

GlGenerator::PrePostStartTriggerSamples GlGenerator::computeSoftwareTriggerTY(const DataAnalyzerResult *result)
{
unsigned int preTrigSamples = 0;
unsigned int postTrigSamples = 0;
unsigned int swTriggerStart = 0;
unsigned int channel = settings->trigger.source;

// check trigger point for software trigger
if (settings->trigger.mode != Dso::TRIGGERMODE_SOFTWARE || channel >= settings->physicalChannels)
return PrePostStartTriggerSamples(preTrigSamples, postTrigSamples, swTriggerStart);

// Trigger channel not in use
if (!settings->voltage[channel].used || !result->data(channel) ||
result->data(channel)->voltage.sample.empty())
return PrePostStartTriggerSamples(preTrigSamples, postTrigSamples, swTriggerStart);

double value;
double level = settings->voltage[channel].trigger;
unsigned int sampleCount = result->data(channel)->voltage.sample.size();
double timeDisplay = settings->horizontal.timebase * 10;
double samplesDisplay = timeDisplay * settings->horizontal.samplerate;
if (samplesDisplay >= sampleCount) {
// For sure not enough samples to adjust for jitter.
// Following options exist:
// 1: Decrease sample rate
// 2: Change trigger mode to auto
// 3: Ignore samples
// For now #3 is chosen
timestampDebug(QString("Too few samples to make a steady "
"picture. Decrease sample rate"));
return PrePostStartTriggerSamples(preTrigSamples, postTrigSamples, swTriggerStart);
}
preTrigSamples = (settings->trigger.position * samplesDisplay);
postTrigSamples = sampleCount - (samplesDisplay - preTrigSamples);

const int threshold = 7;
double prev;
bool (*opcmp)(int,int,int);
bool (*smplcmp)(int,int);
if (settings->trigger.slope == Dso::SLOPE_POSITIVE) {
prev = INT_MAX;
opcmp = [](int value, int level, int prev) { return value > level && prev <= level;};
smplcmp = [](int sampleK, int value) { return sampleK >= value;};
} else {
prev = INT_MIN;
opcmp = [](int value, int level, int prev) { return value > level && prev <= level;};
smplcmp = [](int sampleK, int value) { return sampleK < value;};
}

for (unsigned int i = preTrigSamples; i < postTrigSamples; i++) {
value = result->data(channel)->voltage.sample[i];
if (opcmp(value, level, prev)) {
int rising = 0;
for (unsigned int k = i + 1; k < i + 11 && k < sampleCount; k++) {
if (smplcmp(result->data(channel)->voltage.sample[k], value)) { rising++; }
}
if (rising > threshold) {
swTriggerStart = i;
break;
}
}
prev = value;
}
if (swTriggerStart == 0) {
timestampDebug(QString("Trigger not asserted. Data ignored"));
}
return PrePostStartTriggerSamples(preTrigSamples, postTrigSamples, swTriggerStart);
}

void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {

int digitalPhosphorDepth = view->digitalPhosphorDepth;
int digitalPhosphorDepth = view->digitalPhosphor ? view->digitalPhosphorDepth : 1;

// Handle all digital phosphor related list manipulations
for (int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) {
// Adapt the number of graphs
vaChannel[mode].resize(settings->voltage.size());
DrawLinesWithHistoryPerChannel& d = vaChannel[mode];
// Resize to the number of channels
d.resize(settings->voltage.size());

for (unsigned int channel = 0; channel < vaChannel[mode].size(); ++channel) {
DrawLinesWithHistory& drawLinesHistory = d[channel];
// Move the last list element to the front
vaChannel[mode][channel].push_front(std::vector<GLfloat>());
if (digitalPhosphorDepth > 1 && drawLinesHistory.size())
drawLinesHistory.push_front(drawLinesHistory.back());

// Resize lists for vector array to fit the digital phosphor depth
vaChannel[mode][channel].resize(digitalPhosphorDepth);
drawLinesHistory.resize(digitalPhosphorDepth);
}
}

ready = true;

unsigned int preTrigSamples = 0;
unsigned int postTrigSamples = 0;
unsigned preTrigSamples;
unsigned postTrigSamples;
unsigned swTriggerStart;
switch (settings->horizontal.format) {
case Dso::GRAPHFORMAT_TY: {
unsigned int swTriggerStart = 0;
// check trigger point for software trigger
if (settings->trigger.mode == Dso::TRIGGERMODE_SOFTWARE && settings->trigger.source <= 1) {
unsigned int channel = settings->trigger.source;
if (settings->voltage[channel].used && result->data(channel) &&
!result->data(channel)->voltage.sample.empty()) {
double value;
double level = settings->voltage[channel].trigger;
unsigned int sampleCount = result->data(channel)->voltage.sample.size();
double timeDisplay = settings->horizontal.timebase * 10;
double samplesDisplay = timeDisplay * settings->horizontal.samplerate;
if (samplesDisplay >= sampleCount) {
// For sure not enough samples to adjust for jitter.
// Following options exist:
// 1: Decrease sample rate
// 2: Change trigger mode to auto
// 3: Ignore samples
// For now #3 is chosen
timestampDebug(QString("Too few samples to make a steady "
"picture. Decrease sample rate"));
return;
}
preTrigSamples = (settings->trigger.position * samplesDisplay);
postTrigSamples = sampleCount - (samplesDisplay - preTrigSamples);

if (settings->trigger.slope == Dso::SLOPE_POSITIVE) {
double prev = INT_MAX;
for (unsigned int i = preTrigSamples; i < postTrigSamples; i++) {
value = result->data(channel)->voltage.sample[i];
if (value > level && prev <= level) {
int rising = 0;
for (unsigned int k = i + 1; k < i + 11 && k < sampleCount; k++) {
if (result->data(channel)->voltage.sample[k] >= value) { rising++; }
}
if (rising > 7) {
swTriggerStart = i;
break;
}
}
prev = value;
}
} else if (settings->trigger.slope == Dso::SLOPE_NEGATIVE) {
double prev = INT_MIN;
for (unsigned int i = preTrigSamples; i < postTrigSamples; i++) {
value = result->data(channel)->voltage.sample[i];
if (value < level && prev >= level) {
int falling = 0;
for (unsigned int k = i + 1; k < i + 11 && k < sampleCount; k++) {
if (result->data(channel)->voltage.sample[k] < value) { falling++; }
}
if (falling > 7) {
swTriggerStart = i;
break;
}
}
prev = value;
}
}
}
if (swTriggerStart == 0) {
timestampDebug(QString("Trigger not asserted. Data ignored"));
return;
}
}
case Dso::GRAPHFORMAT_TY:
std::tie(preTrigSamples, postTrigSamples, swTriggerStart) = computeSoftwareTriggerTY(result);

// Add graphs for channels
for (int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) {
for (int channel = 0; channel < (int)settings->voltage.size(); ++channel) {
// Check if this channel is used and available at the data analyzer
if (((mode == Dso::CHANNELMODE_VOLTAGE) ? settings->voltage[channel].used
: settings->spectrum[channel].used) &&
result->data(channel) && !result->data(channel)->voltage.sample.empty()) {
: settings->spectrum[channel].used) &&
result->data(channel) && !result->data(channel)->voltage.sample.empty()) {
// Check if the sample count has changed
size_t sampleCount = (mode == Dso::CHANNELMODE_VOLTAGE)
? result->data(channel)->voltage.sample.size()
: result->data(channel)->spectrum.sample.size();
? result->data(channel)->voltage.sample.size()
: result->data(channel)->spectrum.sample.size();
if (mode == Dso::CHANNELMODE_VOLTAGE) sampleCount -= (swTriggerStart - preTrigSamples);
size_t neededSize = sampleCount * 2;

Expand All @@ -227,12 +237,12 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
horizontalFactor = result->data(channel)->voltage.interval / settings->horizontal.timebase;
else
horizontalFactor =
result->data(channel)->spectrum.interval / settings->horizontal.frequencybase;
result->data(channel)->spectrum.interval / settings->horizontal.frequencybase;

// Fill vector array
if (mode == Dso::CHANNELMODE_VOLTAGE) {
std::vector<double>::const_iterator dataIterator =
result->data(channel)->voltage.sample.begin();
result->data(channel)->voltage.sample.begin();
const double gain = settings->voltage[channel].gain;
const double offset = settings->voltage[channel].offset;
const double invert = settings->voltage[channel].inverted ? -1.0 : 1.0;
Expand All @@ -245,7 +255,7 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
}
} else {
std::vector<double>::const_iterator dataIterator =
result->data(channel)->spectrum.sample.begin();
result->data(channel)->spectrum.sample.begin();
const double magnitude = settings->spectrum[channel].magnitude;
const double offset = settings->spectrum[channel].offset;

Expand All @@ -261,31 +271,31 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
}
}
}
} break;
break;

case Dso::GRAPHFORMAT_XY:
for (int channel = 0; channel < settings->voltage.size(); ++channel) {
// For even channel numbers check if this channel is used and this and the
// following channel are available at the data analyzer
if (channel % 2 == 0 && channel + 1 < settings->voltage.size() && settings->voltage[channel].used &&
result->data(channel) && !result->data(channel)->voltage.sample.empty() && result->data(channel + 1) &&
!result->data(channel + 1)->voltage.sample.empty()) {
result->data(channel) && !result->data(channel)->voltage.sample.empty() && result->data(channel + 1) &&
!result->data(channel + 1)->voltage.sample.empty()) {
// Check if the sample count has changed
const unsigned sampleCount = qMin(result->data(channel)->voltage.sample.size(),
result->data(channel + 1)->voltage.sample.size());
const unsigned neededSize = sampleCount * 2;
for (unsigned index = 0; index < (unsigned)digitalPhosphorDepth; ++index) {
if (vaChannel[Dso::CHANNELMODE_VOLTAGE][(size_t)channel][index].size() != neededSize)
vaChannel[Dso::CHANNELMODE_VOLTAGE][(size_t)channel][index]
.clear(); // Something was changed, drop old traces
.clear(); // Something was changed, drop old traces
}

// Set size directly to avoid reallocations
vaChannel[Dso::CHANNELMODE_VOLTAGE][(size_t)channel].front().resize(neededSize);

// Iterator to data for direct access
std::vector<GLfloat>::iterator glIterator =
vaChannel[Dso::CHANNELMODE_VOLTAGE][channel].front().begin();
vaChannel[Dso::CHANNELMODE_VOLTAGE][channel].front().begin();

// Fill vector array
unsigned int xChannel = channel;
Expand Down
8 changes: 7 additions & 1 deletion openhantek/src/glgenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,15 @@ class GlGenerator : public QObject {
bool isReady() const;

private:
typedef std::tuple<unsigned,unsigned,unsigned> PrePostStartTriggerSamples;
typedef std::vector<GLfloat> DrawLines;
typedef std::deque<DrawLines> DrawLinesWithHistory;
typedef std::vector<DrawLinesWithHistory> DrawLinesWithHistoryPerChannel;
DrawLinesWithHistoryPerChannel vaChannel[Dso::CHANNELMODE_COUNT];

PrePostStartTriggerSamples computeSoftwareTriggerTY(const DataAnalyzerResult *result);
DsoSettingsScope *settings;
DsoSettingsView *view;
std::vector<std::deque<std::vector<GLfloat>>> vaChannel[Dso::CHANNELMODE_COUNT];
std::vector<GLfloat> vaGrid[3];
bool ready = false;
signals:
Expand Down
17 changes: 9 additions & 8 deletions openhantek/src/glscope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ void GlScope::paintGL() {
glClear(GL_COLOR_BUFFER_BIT);
glLineWidth(1);

if (settings->view.digitalPhosphorDepth > 0 && generator->isReady()) { drawGraph(); }
int digitalPhosphorDepth = settings->view.digitalPhosphor ? settings->view.digitalPhosphorDepth : 1;
if (generator->isReady()) { drawGraph(digitalPhosphorDepth); }

if (!this->zoomed) {
// Draw vertical lines at marker positions
Expand Down Expand Up @@ -126,7 +127,7 @@ void GlScope::drawGraphDepth(int mode, int channel, int index) {
generator->channel(mode, channel, index).size() / 2);
}

void GlScope::drawGraph() {
void GlScope::drawGraph(int digitalPhosphorDepth) {
if (settings->view.antialiasing) {
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
Expand All @@ -142,11 +143,11 @@ void GlScope::drawGraph() {
}

// Values we need for the fading of the digital phosphor
if ((int)fadingFactor.size() != settings->view.digitalPhosphorDepth) {
fadingFactor.resize((size_t)settings->view.digitalPhosphorDepth);
if ((int)fadingFactor.size() != digitalPhosphorDepth) {
fadingFactor.resize((size_t)digitalPhosphorDepth);
fadingFactor[0] = 100;
double fadingRatio = pow(10.0, 2.0 / settings->view.digitalPhosphorDepth);
for (size_t index = 1; index < (size_t)settings->view.digitalPhosphorDepth; ++index)
double fadingRatio = pow(10.0, 2.0 / digitalPhosphorDepth);
for (size_t index = 1; index < (size_t)digitalPhosphorDepth; ++index)
fadingFactor[index] = fadingFactor[index - 1] * fadingRatio;
}

Expand All @@ -158,7 +159,7 @@ void GlScope::drawGraph() {
if (!channelUsed(mode, channel)) continue;

// Draw graph for all available depths
for (int index = settings->view.digitalPhosphorDepth - 1; index >= 0; index--) {
for (int index = digitalPhosphorDepth - 1; index >= 0; index--) {
drawGraphDepth(mode, channel, index);
}
}
Expand All @@ -169,7 +170,7 @@ void GlScope::drawGraph() {
// Real and virtual channels
for (int channel = 0; channel < settings->scope.voltage.size() - 1; channel += 2) {
if (settings->scope.voltage[channel].used) {
for (int index = settings->view.digitalPhosphorDepth - 1; index >= 0; index--) {
for (int index = digitalPhosphorDepth - 1; index >= 0; index--) {
drawGraphDepth(Dso::CHANNELMODE_VOLTAGE, channel, index);
}
}
Expand Down
2 changes: 1 addition & 1 deletion openhantek/src/glscope.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class GlScope : public GL_WIDGET_CLASS {

void drawGrid();
void drawGraphDepth(int mode, int channel, int index);
void drawGraph();
void drawGraph(int digitalPhosphorDepth);
bool channelUsed(int mode, int channel);

private:
Expand Down

0 comments on commit db4f8ba

Please sign in to comment.