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

ATV Modulator: fixed timings and AM levels

This commit is contained in:
f4exb 2017-03-06 18:40:14 +01:00
parent 3860ed8e72
commit d5cb0bf267
2 changed files with 75 additions and 56 deletions

View File

@ -125,8 +125,8 @@ void ATVMod::modulateSample()
pullVideo(t);
calculateLevel(t);
// TODO For now do AM 95%
m_modSample.real((t*0.95 + 1.0f) * 16384.0f); // modulate and scale zero frequency carrier
// TODO For now do AM 90%
m_modSample.real((t*1.8f + 0.1f) * 16384.0f); // modulate and scale zero frequency carrier
m_modSample.imag(0.0f);
}
@ -134,26 +134,28 @@ void ATVMod::pullVideo(Real& sample)
{
if ((m_lineCount < 21) || (m_lineCount > 621) || ((m_lineCount > 309) && (m_lineCount < 335)))
{
pullVSyncLine(m_horizontalCount - (m_pointsPerSync + m_pointsPerBP), sample);
pullVSyncLine(sample);
}
else
{
pullImageLine(sample);
}
if (m_horizontalCount < m_nbHorizPoints)
if (m_horizontalCount < m_nbHorizPoints - 1)
{
m_horizontalCount++;
}
else
{
if (m_lineCount < m_nbLines)
if (m_lineCount < m_nbLines - 1)
{
m_lineCount++;
if (m_lineCount > (m_nbLines/2)) m_evenImage = !m_evenImage;
}
else
{
m_lineCount = 0;
m_evenImage = !m_evenImage;
}
m_horizontalCount = 0;
@ -237,8 +239,8 @@ void ATVMod::apply(bool force)
(m_config.m_atvStd != m_running.m_atvStd) ||
(m_config.m_rfBandwidth != m_running.m_rfBandwidth) || force)
{
int rateMultiple = getSampleRateMultiple(m_config.m_atvStd);
m_tvSampleRate = (m_config.m_outputSampleRate / rateMultiple) * rateMultiple;
int rateUnits = getSampleRateUnits(m_config.m_atvStd);
m_tvSampleRate = (m_config.m_outputSampleRate / rateUnits) * rateUnits; // make sure working sample rate is a multiple of rate units
m_settingsMutex.lock();
@ -273,33 +275,49 @@ void ATVMod::apply(bool force)
m_running.m_uniformLevel = m_config.m_uniformLevel;
}
int ATVMod::getSampleRateMultiple(ATVStd std)
int ATVMod::getSampleRateUnits(ATVStd std)
{
switch(std)
{
case ATVStdPAL525:
return 1008000;
break;
case ATVStdPAL625:
default:
return 1000000;
return 1000000; // Exact MS/s - us
}
}
void ATVMod::applyStandard()
{
int rateMultiple = getSampleRateMultiple(m_config.m_atvStd);
m_pointsPerTU = m_tvSampleRate / rateMultiple;
int rateUnits = getSampleRateUnits(m_config.m_atvStd);
m_pointsPerTU = m_tvSampleRate / rateUnits; // TV sample rate is already set at a multiple of rate units
switch(m_config.m_atvStd)
{
case ATVStdPAL525:
m_pointsPerSync = (uint32_t) roundf(4.7f * m_pointsPerTU); // normal sync pulse (4.7/1.008 us)
m_pointsPerBP = (uint32_t) roundf(4.7f * m_pointsPerTU); // back porch (4.7/1.008 us)
m_pointsPerFP = (uint32_t) roundf(1.5f * m_pointsPerTU); // front porch (1.5/1.008 us)
m_pointsPerFSync = (uint32_t) roundf(2.3f * m_pointsPerTU); // equalizing pulse (2.3/1.008 us)
// what is left in a 64/1.008 us line for the image
m_pointsPerImgLine = 64 * m_pointsPerTU - m_pointsPerSync - m_pointsPerBP - m_pointsPerFP;
m_pointsPerBar = 10 * m_pointsPerTU; // set a bar length to 10/1.008 us (~5 bars per line)
m_nbLines = 525;
m_interlaced = true;
m_nbHorizPoints = 64 * m_pointsPerTU; // full line
break;
case ATVStdPAL625:
default:
m_pointsPerSync = 5 * m_pointsPerTU; // would be 4.7 us actually
m_pointsPerBP = 5 * m_pointsPerTU; // would be 4.7 us actually
m_pointsPerFP = 2 * m_pointsPerTU; // would be 1.5 us actually
m_pointsPerFSync = 3 * m_pointsPerTU; // would be 2.3 us actually
m_pointsPerLine = (64 - 12) * m_pointsPerTU; // what is left in a 64 us line
m_pointsPerBar = 10 * m_pointsPerTU; // set a bar length to 10 us (~5 bars per line)
m_nbLines = 625;
m_interlaced = true;
m_nbHorizPoints = 64 * m_pointsPerTU;
m_pointsPerSync = (uint32_t) roundf(4.7f * m_pointsPerTU); // normal sync pulse (4.7 us)
m_pointsPerBP = (uint32_t) roundf(4.7f * m_pointsPerTU); // back porch (4.7 us)
m_pointsPerFP = (uint32_t) roundf(1.5f * m_pointsPerTU); // front porch (1.5 us)
m_pointsPerFSync = (uint32_t) roundf(2.3f * m_pointsPerTU); // equalizing pulse (2.3 us)
// what is left in a 64 us line for the image
m_pointsPerImgLine = 64 * m_pointsPerTU - m_pointsPerSync - m_pointsPerBP - m_pointsPerFP;
m_pointsPerBar = 10 * m_pointsPerTU; // set a bar length to 10 us (~5 bars per line)
m_nbLines = 625;
m_interlaced = true;
m_nbHorizPoints = 64 * m_pointsPerTU; // full line
}
}

View File

@ -34,7 +34,8 @@ class ATVMod : public BasebandSampleSource {
public:
typedef enum
{
ATVStdPAL625
ATVStdPAL625,
ATVStdPAL525
} ATVStd;
typedef enum
@ -62,7 +63,7 @@ public:
Real getMagSq() const { return m_movingAverage.average(); }
static int getSampleRateMultiple(ATVStd std);
static int getSampleRateUnits(ATVStd std);
signals:
/**
@ -142,7 +143,7 @@ private:
int m_tvSampleRate; //!< sample rate for generating signal
uint32_t m_pointsPerSync; //!< number of line points for the horizontal sync
uint32_t m_pointsPerBP; //!< number of line points for the back porch
uint32_t m_pointsPerLine; //!< number of line points for the image line
uint32_t m_pointsPerImgLine; //!< number of line points for the image line
uint32_t m_pointsPerFP; //!< number of line points for the front porch
uint32_t m_pointsPerFSync; //!< number of line points for the field first sync
uint32_t m_pointsPerBar; //!< number of line points for a bar of the bar chart
@ -179,9 +180,9 @@ private:
}
else if (m_horizontalCount < m_pointsPerSync + m_pointsPerBP) // back porch
{
sample = 0.3f; // black
sample = m_blackLevel; // black
}
else if (m_horizontalCount < m_pointsPerSync + m_pointsPerBP + m_pointsPerLine)
else if (m_horizontalCount < m_pointsPerSync + m_pointsPerBP + m_pointsPerImgLine)
{
int pointIndex = m_horizontalCount - (m_pointsPerSync + m_pointsPerBP);
@ -191,7 +192,7 @@ private:
sample = (pointIndex / m_pointsPerBar) * (m_spanLevel/5.0f) + m_blackLevel;
break;
case ATVModInputGradient:
sample = (pointIndex / m_pointsPerLine) * m_spanLevel + m_blackLevel;
sample = (pointIndex / (float) m_pointsPerImgLine) * m_spanLevel + m_blackLevel;
break;
case ATVModInputUniform:
default:
@ -204,14 +205,14 @@ private:
}
}
inline void pullVSyncLine(int pointIndex, Real& sample)
inline void pullVSyncLine(Real& sample)
{
switch (m_lineCount)
{
case 0: // __|__|
case 0:
case 1:
case 313:
case 314:
case 314: // Whole line "long" pulses
{
int halfIndex = m_horizontalCount % (m_nbHorizPoints/2);
@ -225,25 +226,7 @@ private:
}
}
break;
case 2: // __||XX
if (m_horizontalCount < (m_nbHorizPoints/2) - m_pointsPerSync)
{
sample = 0.0f;
}
else if (m_horizontalCount < (m_nbHorizPoints/2))
{
sample = m_blackLevel;
}
else if (m_horizontalCount < (m_nbHorizPoints/2) + m_pointsPerFSync)
{
sample = 0.0f;
}
else
{
sample = m_blackLevel;
}
break;
case 3: // |XX|XX
case 3:
case 4:
case 310:
case 311:
@ -251,7 +234,7 @@ private:
case 316:
case 622:
case 623:
case 624:
case 624: // Whole line equalizing pulses
{
int halfIndex = m_horizontalCount % (m_nbHorizPoints/2);
@ -265,22 +248,40 @@ private:
}
}
break;
case 312: // |XX__|
if (m_horizontalCount < m_pointsPerFSync)
case 2: // long pulse then equalizing pulse
if (m_horizontalCount < (m_nbHorizPoints/2) - m_pointsPerSync)
{
sample = 0.0f;
sample = 0.0f; // ultra-black
}
else if (m_horizontalCount < (m_nbHorizPoints/2))
{
sample = m_blackLevel;
sample = m_blackLevel; // black
}
else if (m_horizontalCount < m_nbHorizPoints - m_pointsPerSync)
else if (m_horizontalCount < (m_nbHorizPoints/2) + m_pointsPerFSync)
{
sample = 0.0f;
sample = 0.0f; // ultra-black
}
else
{
sample = m_blackLevel;
sample = m_blackLevel; // black
}
break;
case 312: // equalizing pulse then long pulse
if (m_horizontalCount < m_pointsPerFSync)
{
sample = 0.0f; // ultra-black
}
else if (m_horizontalCount < (m_nbHorizPoints/2))
{
sample = m_blackLevel; // black
}
else if (m_horizontalCount < m_nbHorizPoints - m_pointsPerSync)
{
sample = 0.0f; // ultra-black
}
else
{
sample = m_blackLevel; // black
}
break;
default: // black images