1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-15 04:41:55 -05:00

ATV Demod: corrected implementation of horizontal leap vertical sync with horizontal sync loopback

This commit is contained in:
f4exb 2017-04-04 03:18:11 +02:00
parent e3b1aad053
commit b2be9f6a0d
2 changed files with 274 additions and 178 deletions

View File

@ -37,6 +37,7 @@ ATVDemod::ATVDemod(BasebandSampleSink* objScopeSink) :
m_objRegisteredATVScreen(NULL),
m_intImageIndex(0),
m_intColIndex(0),
m_intSampleIndex(0),
m_intRowIndex(0),
m_intLineIndex(0),
m_intSynchroPoints(0),
@ -235,8 +236,6 @@ void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
void ATVDemod::demod(Complex& c)
{
float fltDivSynchroBlack = 1.0f - m_objRunning.m_fltVoltLevelSynchroBlack;
int intSynchroTimeSamples= (3*m_intNumberSamplePerLine)/4;
float fltSynchroTrameLevel = 0.5f*((float)intSynchroTimeSamples) * m_objRunning.m_fltVoltLevelSynchroBlack;
float fltNormI;
float fltNormQ;
float fltNorm;
@ -424,186 +423,15 @@ void ATVDemod::demod(Complex& c)
intVal=255;
}
//////////////////////
//********** process video sample **********
// Horizontal Synchro detection
// Floor Detection 0
if (fltVal < m_objRunning.m_fltVoltLevelSynchroTop)
if (m_objRunning.m_enmATVStandard == ATVStdHLeap)
{
m_intSynchroPoints++;
processHLeap(fltVal, intVal);
}
// Black detection 0.3
else if (fltVal > m_objRunning.m_fltVoltLevelSynchroBlack)
else
{
m_intSynchroPoints = 0;
}
m_blnSynchroDetected = (m_intSynchroPoints == m_intNumberSamplePerTop);
//Horizontal Synchro processing
bool blnNewLine = false;
if (!m_objRunning.m_blnHSync && (m_intColIndex >= m_intNumberSamplePerLine)) // H Sync not active
{
m_intColIndex = 0;
blnNewLine = true;
}
else if (m_objRunning.m_blnHSync && m_blnSynchroDetected // Valid H sync detected
&& (m_intColIndex > m_intNumberSamplePerLine - m_intNumberSamplePerTop)
&& (m_intColIndex < m_intNumberSamplePerLine + m_intNumberSamplePerTop))
{
// qDebug("HSync: %d", m_intColIndex);
// m_intColIndex = 0;
m_intAvgColIndex = m_objAvgColIndex.run(m_intColIndex);
m_intColIndex = m_intColIndex - m_intAvgColIndex;
blnNewLine = true;
}
else if (m_intColIndex >= m_intNumberSamplePerLine + m_intNumberSamplePerTop) // No valid H sync
{
if (m_objRunning.m_enmATVStandard == ATVStdHLeap) // new image in hSync leap mode
{
m_objRegisteredATVScreen->renderImage(0);
if (m_objRFRunning.m_enmModulation == ATV_AM)
{
m_fltAmpMin = m_fltEffMin;
m_fltAmpMax = m_fltEffMax;
m_fltAmpDelta = m_fltEffMax-m_fltEffMin;
if(m_fltAmpDelta<=0.0)
{
m_fltAmpDelta=1.0f;
}
//Reset extrema
m_fltEffMin = 2000000.0f;
m_fltEffMax = -2000000.0f;
}
m_intColIndex = m_intNumberSamplePerTop; // catch up with passed samples from the line length point
m_intRowIndex = 0;
m_objRegisteredATVScreen->selectRow(m_intRowIndex);
m_intLineIndex = 0;
m_intImageIndex++;
blnNewLine = false; // done already
}
else
{
//qDebug("HLine: %d", m_intColIndex);
m_intColIndex = 0;
blnNewLine = true;
}
}
if (blnNewLine)
{
m_fltAmpLineAverage=0.0f;
//New line + Interleaving
m_intRowIndex += m_interleaved ? 2 : 1;
if (m_intRowIndex < m_intNumberOfLines)
{
m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
}
m_intLineIndex++;
}
// Filling pixels
m_objRegisteredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop, intVal, intVal, intVal);
m_intColIndex++;
// Vertical sync and image rendering
if ((m_objRunning.m_blnVSync) && (m_objRunning.m_enmATVStandard != ATVStdHLeap)) // VSync activated
{
if (m_intColIndex >= intSynchroTimeSamples)
{
if (m_fltAmpLineAverage <= fltSynchroTrameLevel)
{
m_fltAmpLineAverage = 0.0f;
if (!m_blnVerticalSynchroDetected) // not yet
{
m_blnVerticalSynchroDetected = true; // prevent repetition
if ((m_intLineIndex % 2 == 0) || !m_interleaved) // even => odd image
{
m_objRegisteredATVScreen->renderImage(0);
if (m_objRFRunning.m_enmModulation == ATV_AM)
{
m_fltAmpMin = m_fltEffMin;
m_fltAmpMax = m_fltEffMax;
m_fltAmpDelta = m_fltEffMax-m_fltEffMin;
if(m_fltAmpDelta<=0.0)
{
m_fltAmpDelta=1.0f;
}
//Reset extrema
m_fltEffMin = 2000000.0f;
m_fltEffMax = -2000000.0f;
}
m_intRowIndex = 1;
}
else
{
m_intRowIndex = 0;
}
m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
m_intLineIndex = 0;
m_intImageIndex++;
}
}
else
{
m_blnVerticalSynchroDetected = false; // reset
}
}
}
else // no VSync => arbitrary
{
if (m_intLineIndex >= m_intNumberOfLines/2)
{
if (m_intImageIndex % 2 == 1) // odd image
{
m_objRegisteredATVScreen->renderImage(0);
if (m_objRFRunning.m_enmModulation == ATV_AM)
{
m_fltAmpMin = m_fltEffMin;
m_fltAmpMax = m_fltEffMax;
m_fltAmpDelta = m_fltEffMax-m_fltEffMin;
if(m_fltAmpDelta<=0.0)
{
m_fltAmpDelta=1.0f;
}
//Reset extrema
m_fltEffMin = 2000000.0f;
m_fltEffMax = -2000000.0f;
}
m_intRowIndex = 1;
}
else
{
m_intRowIndex = 0;
}
m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
m_intLineIndex = 0;
m_intImageIndex++;
}
processClassic(fltVal, intVal);
}
}

View File

@ -375,6 +375,7 @@ private:
float m_fltBufferQ[6];
int m_intColIndex;
int m_intSampleIndex;
int m_intRowIndex;
int m_intLineIndex;
@ -420,6 +421,273 @@ private:
void applyStandard();
void demod(Complex& c);
static float getRFBandwidthDivisor(ATVModulation modulation);
inline void processHLeap(float& fltVal, int& intVal)
{
m_objRegisteredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop, intVal, intVal, intVal);
// Horizontal Synchro detection
// Floor Detection 0
if (fltVal < m_objRunning.m_fltVoltLevelSynchroTop)
{
m_intSynchroPoints++;
}
// Black detection 0.3
else if (fltVal > m_objRunning.m_fltVoltLevelSynchroBlack)
{
m_intSynchroPoints = 0;
}
// sync pulse
m_blnSynchroDetected = (m_intSynchroPoints == m_intNumberSamplePerTop);
if (m_blnSynchroDetected)
{
if (m_intSampleIndex >= (3*m_intNumberSamplePerLine)/2) // first after leap
{
//qDebug("VSync: %d %d %d", m_intColIndex, m_intSampleIndex, m_intLineIndex);
m_intAvgColIndex = m_intColIndex;
m_objRegisteredATVScreen->renderImage(0);
if ((m_objRFRunning.m_enmModulation == ATV_AM)
|| (m_objRFRunning.m_enmModulation == ATV_LSB)
|| (m_objRFRunning.m_enmModulation == ATV_USB))
{
m_fltAmpMin = m_fltEffMin;
m_fltAmpMax = m_fltEffMax;
m_fltAmpDelta = m_fltEffMax-m_fltEffMin;
if(m_fltAmpDelta<=0.0)
{
m_fltAmpDelta=1.0f;
}
//Reset extrema
m_fltEffMin = 2000000.0f;
m_fltEffMax = -2000000.0f;
}
m_intImageIndex++;
m_intLineIndex = 0;
m_intRowIndex = 0;
}
m_intSampleIndex = 0;
}
else
{
m_intSampleIndex++;
}
if (m_intColIndex < m_intNumberSamplePerLine + m_intNumberSamplePerTop - 1)
{
m_intColIndex++;
}
else
{
if (m_objRunning.m_blnHSync && (m_intLineIndex == 0))
{
//qDebug("HCorr: %d", m_intAvgColIndex);
m_intColIndex = m_intNumberSamplePerTop + m_intNumberSamplePerLine - m_intAvgColIndex;
}
else
{
m_intColIndex = m_intNumberSamplePerTop;
}
m_objRegisteredATVScreen->selectRow(m_intRowIndex);
m_intLineIndex++;
m_intRowIndex++;
}
}
inline void processClassic(float& fltVal, int& intVal)
{
int intSynchroTimeSamples= (3*m_intNumberSamplePerLine)/4;
float fltSynchroTrameLevel = 0.5f*((float)intSynchroTimeSamples) * m_objRunning.m_fltVoltLevelSynchroBlack;
// Horizontal Synchro detection
// Floor Detection 0
if (fltVal < m_objRunning.m_fltVoltLevelSynchroTop)
{
m_intSynchroPoints++;
}
// Black detection 0.3
else if (fltVal > m_objRunning.m_fltVoltLevelSynchroBlack)
{
m_intSynchroPoints = 0;
}
m_blnSynchroDetected = (m_intSynchroPoints == m_intNumberSamplePerTop);
//Horizontal Synchro processing
bool blnNewLine = false;
if (!m_objRunning.m_blnHSync && (m_intColIndex >= m_intNumberSamplePerLine)) // H Sync not active
{
m_intColIndex = 0;
blnNewLine = true;
}
else if (m_objRunning.m_blnHSync && m_blnSynchroDetected // Valid H sync detected
&& (m_intColIndex > m_intNumberSamplePerLine - m_intNumberSamplePerTop)
&& (m_intColIndex < m_intNumberSamplePerLine + m_intNumberSamplePerTop))
{
// qDebug("HSync: %d", m_intColIndex);
// m_intColIndex = 0;
m_intAvgColIndex = m_objAvgColIndex.run(m_intColIndex);
m_intColIndex = m_intColIndex - m_intAvgColIndex;
blnNewLine = true;
}
else if (m_intColIndex >= m_intNumberSamplePerLine + m_intNumberSamplePerTop) // No valid H sync
{
if (m_objRunning.m_enmATVStandard == ATVStdHLeap) // new image in hSync leap mode
{
m_objRegisteredATVScreen->renderImage(0);
if (m_objRFRunning.m_enmModulation == ATV_AM)
{
m_fltAmpMin = m_fltEffMin;
m_fltAmpMax = m_fltEffMax;
m_fltAmpDelta = m_fltEffMax-m_fltEffMin;
if(m_fltAmpDelta<=0.0)
{
m_fltAmpDelta=1.0f;
}
//Reset extrema
m_fltEffMin = 2000000.0f;
m_fltEffMax = -2000000.0f;
}
m_intColIndex = m_intNumberSamplePerTop; // catch up with passed samples from the line length point
m_intRowIndex = 0;
m_objRegisteredATVScreen->selectRow(m_intRowIndex);
m_intLineIndex = 0;
m_intImageIndex++;
blnNewLine = false; // done already
}
else
{
//qDebug("HLine: %d", m_intColIndex);
m_intColIndex = 0;
blnNewLine = true;
}
}
if (blnNewLine)
{
m_fltAmpLineAverage=0.0f;
//New line + Interleaving
m_intRowIndex += m_interleaved ? 2 : 1;
if (m_intRowIndex < m_intNumberOfLines)
{
m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
}
m_intLineIndex++;
}
// Filling pixels
m_objRegisteredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop, intVal, intVal, intVal);
m_intColIndex++;
// Vertical sync and image rendering
if ((m_objRunning.m_blnVSync) && (m_objRunning.m_enmATVStandard != ATVStdHLeap)) // VSync activated
{
if (m_intColIndex >= intSynchroTimeSamples)
{
if (m_fltAmpLineAverage <= fltSynchroTrameLevel)
{
m_fltAmpLineAverage = 0.0f;
if (!m_blnVerticalSynchroDetected) // not yet
{
m_blnVerticalSynchroDetected = true; // prevent repetition
if ((m_intLineIndex % 2 == 0) || !m_interleaved) // even => odd image
{
m_objRegisteredATVScreen->renderImage(0);
if (m_objRFRunning.m_enmModulation == ATV_AM)
{
m_fltAmpMin = m_fltEffMin;
m_fltAmpMax = m_fltEffMax;
m_fltAmpDelta = m_fltEffMax-m_fltEffMin;
if(m_fltAmpDelta<=0.0)
{
m_fltAmpDelta=1.0f;
}
//Reset extrema
m_fltEffMin = 2000000.0f;
m_fltEffMax = -2000000.0f;
}
m_intRowIndex = 1;
}
else
{
m_intRowIndex = 0;
}
m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
m_intLineIndex = 0;
m_intImageIndex++;
}
}
else
{
m_blnVerticalSynchroDetected = false; // reset
}
}
}
else // no VSync => arbitrary
{
if (m_intLineIndex >= m_intNumberOfLines/2)
{
if (m_intImageIndex % 2 == 1) // odd image
{
m_objRegisteredATVScreen->renderImage(0);
if (m_objRFRunning.m_enmModulation == ATV_AM)
{
m_fltAmpMin = m_fltEffMin;
m_fltAmpMax = m_fltEffMax;
m_fltAmpDelta = m_fltEffMax-m_fltEffMin;
if(m_fltAmpDelta<=0.0)
{
m_fltAmpDelta=1.0f;
}
//Reset extrema
m_fltEffMin = 2000000.0f;
m_fltEffMax = -2000000.0f;
}
m_intRowIndex = 1;
}
else
{
m_intRowIndex = 0;
}
m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
m_intLineIndex = 0;
m_intImageIndex++;
}
}
}
};
#endif // INCLUDE_ATVDEMOD_H