mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-04-10 13:40:37 -04:00
New scope: fixed trace display and triggers
This commit is contained in:
parent
199e915c62
commit
897a181028
@ -81,7 +81,10 @@ void ScopeVisNG::addTrace(const TraceData& traceData)
|
||||
|
||||
void ScopeVisNG::changeTrace(const TraceData& traceData, uint32_t traceIndex)
|
||||
{
|
||||
qDebug("ScopeVisNG::changeTrace: trace #%d", traceIndex);
|
||||
qDebug() << "ScopeVisNG::changeTrace:"
|
||||
<< " trace: " << traceIndex
|
||||
<< " m_amp: " << traceData.m_amp
|
||||
<< " m_ofs: " << traceData.m_ofs;
|
||||
Message* cmd = MsgScopeVisNGChangeTrace::create(traceData, traceIndex);
|
||||
getInputMessageQueue()->push(cmd);
|
||||
}
|
||||
@ -158,56 +161,18 @@ void ScopeVisNG::feed(const SampleVector::const_iterator& cbegin, const SampleVe
|
||||
|
||||
while (begin < end)
|
||||
{
|
||||
if (m_triggerState == TriggerDelay)
|
||||
{
|
||||
if (triggerCondition.m_triggerDelayCount > 0)
|
||||
{
|
||||
triggerCondition.m_triggerDelayCount--; // pass
|
||||
}
|
||||
else // delay expired => fire this trigger
|
||||
{
|
||||
if (!nextTrigger()) // finished
|
||||
{
|
||||
m_traceStart = true; // start trace processing
|
||||
m_triggerPoint = begin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // look for trigger
|
||||
{
|
||||
bool condition = compareTrigger(*begin, triggerCondition); // triggerCondition.m_projector->run(*begin) > triggerCondition.m_triggerData.m_triggerLevel;
|
||||
bool trigger;
|
||||
|
||||
if (triggerCondition.m_triggerData.m_triggerBothEdges) {
|
||||
trigger = triggerCondition.m_prevCondition ^ condition;
|
||||
} else {
|
||||
trigger = (triggerCondition.m_prevCondition ^ condition) && (condition ^ !triggerCondition.m_triggerData.m_triggerPositiveEdge);
|
||||
}
|
||||
|
||||
triggerCondition.m_prevCondition = condition;
|
||||
|
||||
if (trigger) // trigger condition
|
||||
{
|
||||
if (triggerCondition.m_triggerData.m_triggerDelay > 0) // there is a delay => initialize the delay
|
||||
{
|
||||
triggerCondition.m_triggerDelayCount = triggerCondition.m_triggerData.m_triggerDelay;
|
||||
m_triggerState = TriggerDelay;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!nextTrigger()) // finished
|
||||
{
|
||||
m_traceStart = true; // start trace processing
|
||||
m_triggerPoint = begin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// look for trigger
|
||||
if (m_triggerComparator.triggered(*begin, triggerCondition))
|
||||
{
|
||||
m_traceStart = true; // start trace processing
|
||||
m_triggerPoint = begin;
|
||||
m_triggerComparator.reset();
|
||||
m_triggerState = TriggerTriggered;
|
||||
break;
|
||||
}
|
||||
|
||||
++begin;
|
||||
} // begin < end
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -307,24 +272,22 @@ int ScopeVisNG::processTraces(int beginPointDelta, int endPointDelta, TraceBackB
|
||||
|
||||
if (itCtl->m_traceCount[m_traces.currentBufferIndex()] < m_traceSize)
|
||||
{
|
||||
float posLimit = 1.0 / itData->m_amp;
|
||||
float negLimit = -1.0 / itData->m_amp;
|
||||
ProjectionType projectionType = itData->m_projectionType;
|
||||
float v;
|
||||
|
||||
if (projectionType == ProjectionMagLin) {
|
||||
v = itCtl->m_projector->run(*begin)*itData->m_amp - itData->m_ofs - 1.0/itData->m_amp;
|
||||
} else if (projectionType == ProjectionMagDB) { // TODO: optimize computation using a specialized projector (2 projectors: value and trace)
|
||||
v = 1.0f + 2.0f*(((itCtl->m_projector->run(*begin))/100.0f) - itData->m_ofs) + 1.0f - 1.0f/itData->m_amp;
|
||||
//v = itCtl->m_projector->run(*begin) * itData->m_amp - itData->m_ofs;
|
||||
v = (itCtl->m_projector->run(*begin) - itData->m_ofs)*itData->m_amp - 1.0f;
|
||||
} else if (projectionType == ProjectionMagDB) {
|
||||
float p = itCtl->m_projector->run(*begin) - (100.0f * itData->m_ofs);
|
||||
v = ((p/50.0f) + 2.0f)*itData->m_amp - 1.0f;
|
||||
} else {
|
||||
v = itCtl->m_projector->run(*begin) * itData->m_amp - itData->m_ofs;
|
||||
v = (itCtl->m_projector->run(*begin) - itData->m_ofs) * itData->m_amp;
|
||||
}
|
||||
|
||||
if(v > posLimit) {
|
||||
v = posLimit;
|
||||
} else if (v < negLimit) {
|
||||
v = negLimit;
|
||||
if(v > 1.0f) {
|
||||
v = 1.0f;
|
||||
} else if (v < -1.0f) {
|
||||
v = -1.0f;
|
||||
}
|
||||
|
||||
(*itTrace)[2*(itCtl->m_traceCount[m_traces.currentBufferIndex()])]
|
||||
|
@ -350,16 +350,27 @@ private:
|
||||
virtual Real run(const Sample& s)
|
||||
{
|
||||
Real curArg = std::atan2((float) s.m_imag, (float) s.m_real);
|
||||
Real dPhi = curArg - m_prevArg;
|
||||
Real dPhi = (curArg - m_prevArg) / M_PI;
|
||||
m_prevArg = curArg;
|
||||
|
||||
if (dPhi < -M_PI) {
|
||||
dPhi += 2.0 * M_PI;
|
||||
} else if (dPhi > M_PI) {
|
||||
dPhi -= 2.0 * M_PI;
|
||||
if (dPhi < -1.0f) {
|
||||
dPhi += 2.0f;
|
||||
} else if (dPhi > 1.0f) {
|
||||
dPhi -= 2.0f;
|
||||
}
|
||||
|
||||
return dPhi/M_PI;
|
||||
return dPhi;
|
||||
|
||||
// Real dPhi = curArg - m_prevArg;
|
||||
// m_prevArg = curArg;
|
||||
//
|
||||
// if (dPhi < -M_PI) {
|
||||
// dPhi += 2.0 * M_PI;
|
||||
// } else if (dPhi > M_PI) {
|
||||
// dPhi -= 2.0 * M_PI;
|
||||
// }
|
||||
//
|
||||
// return dPhi/M_PI;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -668,6 +679,77 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
class TriggerComparator
|
||||
{
|
||||
public:
|
||||
TriggerComparator() : m_level(0), m_reset(true)
|
||||
{
|
||||
computeLevels();
|
||||
}
|
||||
|
||||
bool triggered(const Sample& s, TriggerCondition& triggerCondition)
|
||||
{
|
||||
if (triggerCondition.m_triggerData.m_triggerLevel != m_level)
|
||||
{
|
||||
m_level = triggerCondition.m_triggerData.m_triggerLevel;
|
||||
computeLevels();
|
||||
}
|
||||
|
||||
bool condition, trigger;
|
||||
|
||||
if (triggerCondition.m_projector->getProjectionType() == ProjectionMagDB) {
|
||||
condition = triggerCondition.m_projector->run(s) > m_levelPwoerDB;
|
||||
} else if (triggerCondition.m_projector->getProjectionType() == ProjectionMagLin) {
|
||||
condition = triggerCondition.m_projector->run(s) > m_levelPowerLin;
|
||||
} else {
|
||||
condition = triggerCondition.m_projector->run(s) > m_level;
|
||||
}
|
||||
|
||||
if (m_reset)
|
||||
{
|
||||
triggerCondition.m_prevCondition = condition;
|
||||
m_reset = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (triggerCondition.m_triggerData.m_triggerBothEdges) {
|
||||
trigger = triggerCondition.m_prevCondition ? !condition : condition; // This is a XOR between bools
|
||||
} else if (triggerCondition.m_triggerData.m_triggerPositiveEdge) {
|
||||
trigger = !triggerCondition.m_prevCondition && condition;
|
||||
} else {
|
||||
trigger = triggerCondition.m_prevCondition && !condition;
|
||||
}
|
||||
|
||||
// if (trigger) {
|
||||
// qDebug("ScopeVisNG::triggered: %s/%s %f/%f",
|
||||
// triggerCondition.m_prevCondition ? "T" : "F",
|
||||
// condition ? "T" : "F",
|
||||
// triggerCondition.m_projector->run(s),
|
||||
// triggerCondition.m_triggerData.m_triggerLevel);
|
||||
// }
|
||||
|
||||
triggerCondition.m_prevCondition = condition;
|
||||
return trigger;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_reset = true;
|
||||
}
|
||||
|
||||
private:
|
||||
void computeLevels()
|
||||
{
|
||||
m_levelPowerLin = m_level + 1.0f;
|
||||
m_levelPwoerDB = (100.0f * (m_level - 1.0f));
|
||||
}
|
||||
|
||||
Real m_level;
|
||||
Real m_levelPwoerDB;
|
||||
Real m_levelPowerLin;
|
||||
bool m_reset;
|
||||
};
|
||||
|
||||
GLScopeNG* m_glScope;
|
||||
uint32_t m_preTriggerDelay; //!< Pre-trigger delay in number of samples
|
||||
std::vector<TriggerCondition> m_triggerConditions; //!< Chain of triggers
|
||||
@ -686,21 +768,7 @@ private:
|
||||
TraceBackDiscreteMemory m_traceDiscreteMemory; //!< Complex trace memory for triggered states TODO: vectorize when more than on input is allowed
|
||||
bool m_freeRun; //!< True if free running (trigger globally disabled)
|
||||
int m_maxTraceDelay; //!< Maximum trace delay
|
||||
|
||||
/**
|
||||
* Test sample against trigger level. Returns true if sample is above level.
|
||||
* TODO: optimize power level computation by storing value when it changes
|
||||
*/
|
||||
bool compareTrigger(const Sample& s, TriggerCondition& triggerCondition)
|
||||
{
|
||||
if (triggerCondition.m_projector->getProjectionType() == ProjectionMagDB) {
|
||||
return triggerCondition.m_projector->run(s) > (100.0f * (triggerCondition.m_triggerData.m_triggerLevel - 1.0f));
|
||||
} else if (triggerCondition.m_projector->getProjectionType() == ProjectionMagLin) {
|
||||
return triggerCondition.m_projector->run(s) > triggerCondition.m_triggerData.m_triggerLevel + 1.0f;
|
||||
} else {
|
||||
return triggerCondition.m_projector->run(s) > triggerCondition.m_triggerData.m_triggerLevel;
|
||||
}
|
||||
}
|
||||
TriggerComparator m_triggerComparator; //!< Compares sample level to trigger level
|
||||
|
||||
/**
|
||||
* Moves on to the next trigger if any or increments trigger count if in repeat mode
|
||||
|
@ -305,7 +305,8 @@ void GLScopeNG::paintGL()
|
||||
float rectX = m_glScopeRect1.x();
|
||||
float rectY = m_glScopeRect1.y() + m_glScopeRect1.height() / 2.0f;
|
||||
float rectW = m_glScopeRect1.width() * (float)m_timeBase / (float)(m_traceSize - 1);
|
||||
float rectH = -(m_glScopeRect1.height() / 2.0f) * traceData.m_amp;
|
||||
//float rectH = -(m_glScopeRect1.height() / 2.0f) * traceData.m_amp;
|
||||
float rectH = -m_glScopeRect1.height() / 2.0f;
|
||||
|
||||
QVector4D color(1.0f, 1.0f, 0.25f, m_displayTraceIntensity / 100.0f);
|
||||
QMatrix4x4 mat;
|
||||
@ -994,9 +995,9 @@ void GLScopeNG::setYScale(ScaleEngine& scale, uint32_t highlightedTraceIndex)
|
||||
break;
|
||||
case ScopeVisNG::ProjectionMagLin:
|
||||
if (amp_range < 2.0) {
|
||||
scale.setRange(Unit::None, amp_ofs * 500.0, amp_range * 1000.0 + amp_ofs * 500.0);
|
||||
scale.setRange(Unit::None, amp_ofs * 1000.0, amp_range * 1000.0 + amp_ofs * 1000.0);
|
||||
} else {
|
||||
scale.setRange(Unit::None, amp_ofs/2.0, amp_range + amp_ofs/2.0);
|
||||
scale.setRange(Unit::None, amp_ofs, amp_range + amp_ofs);
|
||||
}
|
||||
break;
|
||||
case ScopeVisNG::ProjectionPhase: // Phase or frequency
|
||||
|
@ -352,7 +352,10 @@ void GLScopeNGGUI::on_trigDelay_valueChanged(int value)
|
||||
void GLScopeNGGUI::on_trigPre_valueChanged(int value)
|
||||
{
|
||||
setTrigPreDisplay();
|
||||
changeCurrentTrigger();
|
||||
m_scopeVis->configure(m_traceLenMult*ScopeVisNG::m_traceChunkSize,
|
||||
m_timeOffset*10,
|
||||
(uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)),
|
||||
ui->freerun->isChecked()); // TODO: implement one shot feature
|
||||
}
|
||||
|
||||
void GLScopeNGGUI::on_trigOneShot_toggled(bool checked)
|
||||
@ -615,8 +618,13 @@ void GLScopeNGGUI::fillTraceData(ScopeVisNG::TraceData& traceData)
|
||||
traceData.m_projectionType = (ScopeVisNG::ProjectionType) ui->traceMode->currentIndex();
|
||||
traceData.m_inputIndex = 0;
|
||||
traceData.m_amp = 0.2 / amps[ui->amp->value()];
|
||||
traceData.m_ofs = ((10.0 * ui->ofsCoarse->value()) + (ui->ofsFine->value() / 20.0)) / 1000.0f;
|
||||
traceData.m_traceDelay = 0;
|
||||
|
||||
if (traceData.m_projectionType == ScopeVisNG::ProjectionMagLin) {
|
||||
traceData.m_ofs = ((10.0 * ui->ofsCoarse->value()) + (ui->ofsFine->value() / 20.0)) / 2000.0f;
|
||||
} else {
|
||||
traceData.m_ofs = ((10.0 * ui->ofsCoarse->value()) + (ui->ofsFine->value() / 20.0)) / 1000.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void GLScopeNGGUI::fillTriggerData(ScopeVisNG::TriggerData& triggerData)
|
||||
|
Loading…
Reference in New Issue
Block a user