mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-15 12:51:49 -05:00
ATV demod: fixed AM demodulator. Fixes issue #459
This commit is contained in:
parent
587a8b4e1e
commit
9c05329bb3
@ -42,11 +42,11 @@ ATVDemodSink::ATVDemodSink() :
|
|||||||
m_verticalSynchroDetected(false),
|
m_verticalSynchroDetected(false),
|
||||||
m_ampLineSum(0.0f),
|
m_ampLineSum(0.0f),
|
||||||
m_ampLineAvg(0.0f),
|
m_ampLineAvg(0.0f),
|
||||||
m_effMin(2000000.0f),
|
m_effMin(2.0f),
|
||||||
m_effMax(-2000000.0f),
|
m_effMax(-2.0f),
|
||||||
m_ampMin(0.0f),
|
m_ampMin(-1.0f),
|
||||||
m_ampMax(0.3f),
|
m_ampMax(1.0f),
|
||||||
m_ampDelta(0.3f),
|
m_ampDelta(2.0f),
|
||||||
m_ampSample(0.0f),
|
m_ampSample(0.0f),
|
||||||
m_colIndex(0),
|
m_colIndex(0),
|
||||||
m_sampleIndex(0),
|
m_sampleIndex(0),
|
||||||
@ -170,7 +170,7 @@ void ATVDemodSink::demod(Complex& c)
|
|||||||
{
|
{
|
||||||
//Amplitude FM
|
//Amplitude FM
|
||||||
magSq = fltI*fltI + fltQ*fltQ;
|
magSq = fltI*fltI + fltQ*fltQ;
|
||||||
m_objMagSqAverage(magSq);
|
m_magSqAverage(magSq);
|
||||||
sampleNorm = sqrt(magSq);
|
sampleNorm = sqrt(magSq);
|
||||||
sampleNormI = fltI/sampleNorm;
|
sampleNormI = fltI/sampleNorm;
|
||||||
sampleNormQ = fltQ/sampleNorm;
|
sampleNormQ = fltQ/sampleNorm;
|
||||||
@ -225,14 +225,14 @@ void ATVDemodSink::demod(Complex& c)
|
|||||||
{
|
{
|
||||||
//Amplitude AM
|
//Amplitude AM
|
||||||
magSq = fltI*fltI + fltQ*fltQ;
|
magSq = fltI*fltI + fltQ*fltQ;
|
||||||
m_objMagSqAverage(magSq);
|
m_magSqAverage(magSq);
|
||||||
sampleNorm = sqrt(magSq);
|
sampleNorm = sqrt(magSq);
|
||||||
sample = sampleNorm / SDR_RX_SCALEF;
|
sample = 2.0 * (sampleNorm / SDR_RX_SCALEF) - 1.0;
|
||||||
}
|
}
|
||||||
else if ((m_settings.m_atvModulation == ATVDemodSettings::ATV_USB) || (m_settings.m_atvModulation == ATVDemodSettings::ATV_LSB))
|
else if ((m_settings.m_atvModulation == ATVDemodSettings::ATV_USB) || (m_settings.m_atvModulation == ATVDemodSettings::ATV_LSB))
|
||||||
{
|
{
|
||||||
magSq = fltI*fltI + fltQ*fltQ;
|
magSq = fltI*fltI + fltQ*fltQ;
|
||||||
m_objMagSqAverage(magSq);
|
m_magSqAverage(magSq);
|
||||||
sampleNorm = sqrt(magSq);
|
sampleNorm = sqrt(magSq);
|
||||||
|
|
||||||
Real bfoValues[2];
|
Real bfoValues[2];
|
||||||
@ -254,13 +254,13 @@ void ATVDemodSink::demod(Complex& c)
|
|||||||
{
|
{
|
||||||
float rawDeviation;
|
float rawDeviation;
|
||||||
sample = m_objPhaseDiscri.phaseDiscriminatorDelta(c, magSq, rawDeviation) + 0.5f;
|
sample = m_objPhaseDiscri.phaseDiscriminatorDelta(c, magSq, rawDeviation) + 0.5f;
|
||||||
m_objMagSqAverage(magSq);
|
m_magSqAverage(magSq);
|
||||||
sampleNorm = sqrt(magSq);
|
sampleNorm = sqrt(magSq);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
magSq = fltI*fltI + fltQ*fltQ;
|
magSq = fltI*fltI + fltQ*fltQ;
|
||||||
m_objMagSqAverage(magSq);
|
m_magSqAverage(magSq);
|
||||||
sampleNorm = sqrt(magSq);
|
sampleNorm = sqrt(magSq);
|
||||||
sample = 0.0f;
|
sample = 0.0f;
|
||||||
}
|
}
|
||||||
@ -281,7 +281,7 @@ void ATVDemodSink::demod(Complex& c)
|
|||||||
m_effMax = sample;
|
m_effMax = sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_amSampleIndex < m_samplesPerLine * m_settings.m_nbLines) // do not extend estimation period past a full image
|
if (m_amSampleIndex < m_samplesPerLine * m_settings.m_nbLines * m_settings.m_fps * 5) // calculate on 5s
|
||||||
{
|
{
|
||||||
m_amSampleIndex++;
|
m_amSampleIndex++;
|
||||||
}
|
}
|
||||||
@ -290,25 +290,25 @@ void ATVDemodSink::demod(Complex& c)
|
|||||||
// scale signal based on extrema on the estimation period
|
// scale signal based on extrema on the estimation period
|
||||||
m_ampMin = m_effMin;
|
m_ampMin = m_effMin;
|
||||||
m_ampMax = m_effMax;
|
m_ampMax = m_effMax;
|
||||||
m_ampDelta = (m_ampMax - m_ampMin) * 0.3f;
|
m_ampDelta = (m_ampMax - m_ampMin);
|
||||||
m_ampSample = 0.3f; // allow passing to fine scale estimation
|
m_ampSample = 0.3f; // allow passing to fine scale estimation
|
||||||
|
|
||||||
if (m_ampDelta <= 0.0) {
|
if (m_ampDelta <= 0.0) {
|
||||||
m_ampDelta = 0.3f;
|
m_ampDelta = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug("ATVDemod::demod: m_ampMin: %f m_ampMax: %f m_ampDelta: %f", m_ampMin, m_ampMax, m_ampDelta);
|
qDebug("ATVDemod::demod: m_ampMin: %f m_ampMax: %f m_ampDelta: %f", m_ampMin, m_ampMax, m_ampDelta);
|
||||||
|
|
||||||
//Reset extrema
|
//Reset extrema
|
||||||
m_effMin = 2000000.0f;
|
m_effMin = 2.0f;
|
||||||
m_effMax = -2000000.0;
|
m_effMax = -2.0f;
|
||||||
|
|
||||||
m_amSampleIndex = 0;
|
m_amSampleIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Normalisation of current sample
|
//Normalisation of current sample
|
||||||
sample -= m_ampMin;
|
sample -= m_ampMin;
|
||||||
sample /= (m_ampDelta * 3.1f);
|
sample /= (m_ampDelta*0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
sample = m_settings.m_invertVideo ? 1.0f - sample : sample;
|
sample = m_settings.m_invertVideo ? 1.0f - sample : sample;
|
||||||
|
@ -45,7 +45,7 @@ public:
|
|||||||
|
|
||||||
void setScopeSink(BasebandSampleSink* scopeSink) { m_scopeSink = scopeSink; }
|
void setScopeSink(BasebandSampleSink* scopeSink) { m_scopeSink = scopeSink; }
|
||||||
void setTVScreen(TVScreen *tvScreen) { m_registeredTVScreen = tvScreen; } //!< set by the GUI
|
void setTVScreen(TVScreen *tvScreen) { m_registeredTVScreen = tvScreen; } //!< set by the GUI
|
||||||
double getMagSq() const { return m_objMagSqAverage; } //!< Beware this is scaled to 2^30
|
double getMagSq() const { return m_magSqAverage; } //!< Beware this is scaled to 2^30
|
||||||
bool getBFOLocked();
|
bool getBFOLocked();
|
||||||
void setVideoTabIndex(int videoTabIndex) { m_videoTabIndex = videoTabIndex; }
|
void setVideoTabIndex(int videoTabIndex) { m_videoTabIndex = videoTabIndex; }
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ private:
|
|||||||
|
|
||||||
int m_colIndex;
|
int m_colIndex;
|
||||||
int m_sampleIndex;
|
int m_sampleIndex;
|
||||||
unsigned int m_amSampleIndex;
|
int m_amSampleIndex;
|
||||||
int m_rowIndex;
|
int m_rowIndex;
|
||||||
int m_lineIndex;
|
int m_lineIndex;
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ private:
|
|||||||
|
|
||||||
//*************** RF ***************
|
//*************** RF ***************
|
||||||
|
|
||||||
MovingAverageUtil<double, double, 32> m_objMagSqAverage;
|
MovingAverageUtil<double, double, 32> m_magSqAverage;
|
||||||
|
|
||||||
NCO m_nco;
|
NCO m_nco;
|
||||||
SimplePhaseLock m_bfoPLL;
|
SimplePhaseLock m_bfoPLL;
|
||||||
@ -194,12 +194,12 @@ private:
|
|||||||
// Floor Detection (0.1 nominal)
|
// Floor Detection (0.1 nominal)
|
||||||
if (sample < m_settings.m_levelSynchroTop)
|
if (sample < m_settings.m_levelSynchroTop)
|
||||||
{
|
{
|
||||||
if (m_synchroSamples == 0) // AM scale reset on transition if within range
|
// if (m_synchroSamples == 0) // AM scale reset on transition if within range
|
||||||
{
|
// {
|
||||||
m_effMin = 2000000.0f;
|
// m_effMin = 2000000.0f;
|
||||||
m_effMax = -2000000.0f;
|
// m_effMax = -2000000.0f;
|
||||||
m_amSampleIndex = 0;
|
// m_amSampleIndex = 0;
|
||||||
}
|
// }
|
||||||
|
|
||||||
m_synchroSamples++;
|
m_synchroSamples++;
|
||||||
}
|
}
|
||||||
@ -209,16 +209,16 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Refine AM scale estimation on HSync pulse sequence
|
// Refine AM scale estimation on HSync pulse sequence
|
||||||
if (m_amSampleIndex == (3*m_numberSamplesPerHTop)/2)
|
// if (m_amSampleIndex == (3*m_numberSamplesPerHTop)/2)
|
||||||
{
|
// {
|
||||||
m_ampMin = m_effMin;
|
// m_ampMin = m_effMin;
|
||||||
m_ampMax = m_effMax;
|
// m_ampMax = m_effMax;
|
||||||
m_ampDelta = (m_ampMax - m_ampMin);
|
// m_ampDelta = (m_ampMax - m_ampMin);
|
||||||
|
|
||||||
if (m_ampDelta <= 0.0) {
|
// if (m_ampDelta <= 0.0) {
|
||||||
m_ampDelta = 0.3f;
|
// m_ampDelta = 0.3f;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// H sync pulse
|
// H sync pulse
|
||||||
m_horizontalSynchroDetected = (m_synchroSamples == m_numberSamplesPerHTop);
|
m_horizontalSynchroDetected = (m_synchroSamples == m_numberSamplesPerHTop);
|
||||||
@ -285,12 +285,12 @@ private:
|
|||||||
// Floor Detection 0
|
// Floor Detection 0
|
||||||
if (sample < m_settings.m_levelSynchroTop)
|
if (sample < m_settings.m_levelSynchroTop)
|
||||||
{
|
{
|
||||||
if ((m_synchroSamples == 0) && (m_ampSample > 0.25f) && (m_ampSample < 0.35f)) // AM scale reset on transition
|
// if ((m_synchroSamples == 0) && (m_ampSample > 0.25f) && (m_ampSample < 0.35f)) // AM scale reset on transition
|
||||||
{
|
// {
|
||||||
m_effMin = 2000000.0f;;
|
// m_effMin = 2000000.0f;;
|
||||||
m_effMax = -2000000.0f;;
|
// m_effMax = -2000000.0f;;
|
||||||
m_amSampleIndex = 0;
|
// m_amSampleIndex = 0;
|
||||||
}
|
// }
|
||||||
|
|
||||||
m_synchroSamples++;
|
m_synchroSamples++;
|
||||||
}
|
}
|
||||||
@ -300,17 +300,17 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Refine AM scale estimation on HSync pulse sequence
|
// Refine AM scale estimation on HSync pulse sequence
|
||||||
if ((m_amSampleIndex == (3*m_numberSamplesPerHTop)/2) && (sample > 0.25f) && (sample < 0.35f))
|
// if ((m_amSampleIndex == (3*m_numberSamplesPerHTop)/2) && (sample > 0.25f) && (sample < 0.35f))
|
||||||
{
|
// {
|
||||||
m_ampSample = sample;
|
// m_ampSample = sample;
|
||||||
m_ampMin = m_effMin;
|
// m_ampMin = m_effMin;
|
||||||
m_ampMax = m_effMax;
|
// m_ampMax = m_effMax;
|
||||||
m_ampDelta = (m_ampMax - m_ampMin);
|
// m_ampDelta = (m_ampMax - m_ampMin);
|
||||||
|
|
||||||
if (m_ampDelta <= 0.0) {
|
// if (m_ampDelta <= 0.0) {
|
||||||
m_ampDelta = 0.3f;
|
// m_ampDelta = 0.3f;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// H sync pulse
|
// H sync pulse
|
||||||
m_horizontalSynchroDetected = (m_synchroSamples == m_numberSamplesPerHTop) && (m_sampleIndex > (m_samplesPerLine/2) + m_numberSamplesPerLineSignals);
|
m_horizontalSynchroDetected = (m_synchroSamples == m_numberSamplesPerHTop) && (m_sampleIndex > (m_samplesPerLine/2) + m_numberSamplesPerLineSignals);
|
||||||
|
Loading…
Reference in New Issue
Block a user