1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-23 10:05:46 -05:00

ATV demod: use common code for horizontal sync and different vertical sync detections for HSkip and standard

This commit is contained in:
f4exb 2020-07-22 08:48:23 +02:00
parent 432d6ed8fd
commit 8ae95f2e85
2 changed files with 74 additions and 123 deletions

View File

@ -325,11 +325,7 @@ void ATVDemodSink::demod(Complex& c)
if (m_registeredTVScreen) // can process only if the screen is available (set via the GUI)
{
if (m_settings.m_atvStd == ATVDemodSettings::ATVStdHSkip) {
processHSkip(sample, sampleVideo);
} else {
processClassic(sample, sampleVideo);
}
processSample(sample, sampleVideo);
}
}

View File

@ -195,7 +195,7 @@ private:
void demod(Complex& c);
void applyStandard(int sampleRate, const ATVDemodSettings& settings, float lineDuration);
inline void processClassic(float& sample, int& sampleVideo)
inline void processSample(float& sample, int& sampleVideo)
{
// Filling pixel on the current line - reference index 0 at start of sync pulse
m_registeredTVScreen->setDataColor(m_sampleIndex - m_numberSamplesPerHSync, sampleVideo, sampleVideo, sampleVideo);
@ -257,143 +257,98 @@ private:
if (m_sampleIndex >= m_samplesPerLine)
{
m_sampleIndex = 0;
m_lineIndex++;
if (m_lineIndex == m_numberOfVSyncLines + 3 && m_fieldIndex == 0)
{
float shiftSamples = 0.0f;
// Slow sync: slight adjustment is needed
if (m_hSyncShiftCount != 0 && m_settings.m_hSync)
{
shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount;
m_sampleIndex = shiftSamples;
m_hSyncShiftSum = 0.0f;
m_hSyncShiftCount = 0;
m_hSyncErrorCount = 0;
}
m_registeredTVScreen->renderImage(0,
shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples));
if (m_settings.m_atvStd == ATVDemodSettings::ATVStdHSkip) {
processEOLHSkip();
} else {
processEOLClassic();
}
if (m_vSyncDetectSampleCount > m_vSyncDetectThreshold &&
(m_lineIndex < 3 || m_lineIndex > m_numberOfVSyncLines + 1) && m_settings.m_vSync)
{
if (m_interleaved)
{
if (m_fieldDetectSampleCount > m_fieldDetectThreshold1)
m_fieldIndex = 0;
else if (m_fieldDetectSampleCount < m_fieldDetectThreshold2)
m_fieldIndex = 1;
}
m_lineIndex = 2;
}
m_fieldDetectSampleCount = 0;
m_vSyncDetectSampleCount = 0;
if (m_lineIndex > m_settings.m_nbLines / 2 + m_fieldIndex && m_interleaved)
{
m_lineIndex = 1;
m_fieldIndex = 1 - m_fieldIndex;
}
else if (m_lineIndex > m_settings.m_nbLines && !m_interleaved)
{
m_lineIndex = 1;
m_fieldIndex = 0;
}
int rowIndex = m_lineIndex - m_firstVisibleLine;
if (m_interleaved)
rowIndex = rowIndex * 2 - m_fieldIndex;
m_registeredTVScreen->selectRow(rowIndex);
}
prevSample = sample;
}
// Vertical sync is obtained by skipping horizontal sync on the line that triggers vertical sync (new frame)
inline void processHSkip(float& sample, int& sampleVideo)
// Standard vertical sync
inline void processEOLClassic()
{
// Filling pixel on the current line - reference index 0 at start of sync pulse
m_registeredTVScreen->setDataColor(m_sampleIndex - m_numberSamplesPerHSync, sampleVideo, sampleVideo, sampleVideo);
m_lineIndex++;
if (m_settings.m_hSync)
if (m_lineIndex == m_numberOfVSyncLines + 3 && m_fieldIndex == 0)
{
// Horizontal Synchro detection
if ((prevSample >= m_settings.m_levelSynchroTop &&
sample < m_settings.m_levelSynchroTop) // horizontal synchro detected
&& (m_sampleIndexDetected > m_samplesPerLine - m_numberSamplesPerHTopNom))
float shiftSamples = 0.0f;
// Slow sync: slight adjustment is needed
if (m_hSyncShiftCount != 0 && m_settings.m_hSync)
{
double sampleIndexDetectedFrac =
(sample - m_settings.m_levelSynchroTop) / (prevSample - sample);
double hSyncShift = -m_sampleIndex - sampleIndexDetectedFrac;
if (hSyncShift > m_samplesPerLine / 2)
hSyncShift -= m_samplesPerLine;
else if (hSyncShift < -m_samplesPerLine / 2)
hSyncShift += m_samplesPerLine;
if (fabs(hSyncShift) > m_numberSamplesPerHTopNom)
{
m_hSyncErrorCount++;
if (m_hSyncErrorCount >= 8)
{
// Fast sync: shift is too large, needs to be fixed ASAP
m_sampleIndex = 0;
m_hSyncShiftSum = 0.0;
m_hSyncShiftCount = 0;
m_hSyncErrorCount = 0;
}
}
else
{
m_hSyncShiftSum += hSyncShift;
m_hSyncShiftCount++;
m_hSyncErrorCount = 0;
}
m_sampleIndexDetected = 0;
shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount;
m_sampleIndex = shiftSamples;
m_hSyncShiftSum = 0.0f;
m_hSyncShiftCount = 0;
m_hSyncErrorCount = 0;
}
else
m_sampleIndexDetected++;
}
else
{
m_hSyncShiftSum = 0.0f;
m_hSyncShiftCount = 0;
m_registeredTVScreen->renderImage(0,
shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples));
}
m_sampleIndex++;
// end of line
if (m_sampleIndex >= m_samplesPerLine)
if (m_vSyncDetectSampleCount > m_vSyncDetectThreshold &&
(m_lineIndex < 3 || m_lineIndex > m_numberOfVSyncLines + 1) && m_settings.m_vSync)
{
m_sampleIndex = 0;
m_lineIndex++;
m_rowIndex++;
if ((m_sampleIndexDetected > (3*m_samplesPerLine) / 2) // Vertical sync is first horizontal sync after skip (count at least 1.5 line length)
|| (!m_settings.m_vSync && (m_lineIndex >= m_settings.m_nbLines))) // Vsync ignored and reached nominal number of lines per frame
if (m_interleaved)
{
float shiftSamples = 0.0f;
// Slow sync: slight adjustment is needed
if (m_hSyncShiftCount != 0 && m_settings.m_hSync)
{
shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount;
m_sampleIndex = shiftSamples;
m_hSyncShiftSum = 0.0f;
m_hSyncShiftCount = 0;
m_hSyncErrorCount = 0;
}
m_registeredTVScreen->renderImage(0,
shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples));
m_lineIndex = 0;
m_rowIndex = 0;
if (m_fieldDetectSampleCount > m_fieldDetectThreshold1)
m_fieldIndex = 0;
else if (m_fieldDetectSampleCount < m_fieldDetectThreshold2)
m_fieldIndex = 1;
}
m_lineIndex = 2;
}
m_fieldDetectSampleCount = 0;
m_vSyncDetectSampleCount = 0;
m_registeredTVScreen->selectRow(m_rowIndex);
if (m_lineIndex > m_settings.m_nbLines / 2 + m_fieldIndex && m_interleaved)
{
m_lineIndex = 1;
m_fieldIndex = 1 - m_fieldIndex;
}
else if (m_lineIndex > m_settings.m_nbLines && !m_interleaved)
{
m_lineIndex = 1;
m_fieldIndex = 0;
}
prevSample = sample;
int rowIndex = m_lineIndex - m_firstVisibleLine;
if (m_interleaved)
rowIndex = rowIndex * 2 - m_fieldIndex;
m_registeredTVScreen->selectRow(rowIndex);
}
// Vertical sync is obtained by skipping horizontal sync on the line that triggers vertical sync (new frame)
inline void processEOLHSkip()
{
m_lineIndex++;
m_rowIndex++;
if ((m_sampleIndexDetected > (3*m_samplesPerLine) / 2) // Vertical sync is first horizontal sync after skip (count at least 1.5 line length)
|| (!m_settings.m_vSync && (m_lineIndex >= m_settings.m_nbLines))) // Vsync ignored and reached nominal number of lines per frame
{
float shiftSamples = 0.0f;
// Slow sync: slight adjustment is needed
if (m_hSyncShiftCount != 0 && m_settings.m_hSync)
{
shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount;
m_sampleIndex = shiftSamples;
m_hSyncShiftSum = 0.0f;
m_hSyncShiftCount = 0;
m_hSyncErrorCount = 0;
}
m_registeredTVScreen->renderImage(0,
shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples));
m_lineIndex = 0;
m_rowIndex = 0;
}
m_registeredTVScreen->selectRow(m_rowIndex);
}
};