mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-09-07 15:47:50 -04:00
ATV Modulator: fixed timings and AM levels
This commit is contained in:
parent
3860ed8e72
commit
d5cb0bf267
@ -125,8 +125,8 @@ void ATVMod::modulateSample()
|
|||||||
pullVideo(t);
|
pullVideo(t);
|
||||||
calculateLevel(t);
|
calculateLevel(t);
|
||||||
|
|
||||||
// TODO For now do AM 95%
|
// TODO For now do AM 90%
|
||||||
m_modSample.real((t*0.95 + 1.0f) * 16384.0f); // modulate and scale zero frequency carrier
|
m_modSample.real((t*1.8f + 0.1f) * 16384.0f); // modulate and scale zero frequency carrier
|
||||||
m_modSample.imag(0.0f);
|
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)))
|
if ((m_lineCount < 21) || (m_lineCount > 621) || ((m_lineCount > 309) && (m_lineCount < 335)))
|
||||||
{
|
{
|
||||||
pullVSyncLine(m_horizontalCount - (m_pointsPerSync + m_pointsPerBP), sample);
|
pullVSyncLine(sample);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pullImageLine(sample);
|
pullImageLine(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_horizontalCount < m_nbHorizPoints)
|
if (m_horizontalCount < m_nbHorizPoints - 1)
|
||||||
{
|
{
|
||||||
m_horizontalCount++;
|
m_horizontalCount++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_lineCount < m_nbLines)
|
if (m_lineCount < m_nbLines - 1)
|
||||||
{
|
{
|
||||||
m_lineCount++;
|
m_lineCount++;
|
||||||
|
if (m_lineCount > (m_nbLines/2)) m_evenImage = !m_evenImage;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_lineCount = 0;
|
m_lineCount = 0;
|
||||||
|
m_evenImage = !m_evenImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_horizontalCount = 0;
|
m_horizontalCount = 0;
|
||||||
@ -237,8 +239,8 @@ void ATVMod::apply(bool force)
|
|||||||
(m_config.m_atvStd != m_running.m_atvStd) ||
|
(m_config.m_atvStd != m_running.m_atvStd) ||
|
||||||
(m_config.m_rfBandwidth != m_running.m_rfBandwidth) || force)
|
(m_config.m_rfBandwidth != m_running.m_rfBandwidth) || force)
|
||||||
{
|
{
|
||||||
int rateMultiple = getSampleRateMultiple(m_config.m_atvStd);
|
int rateUnits = getSampleRateUnits(m_config.m_atvStd);
|
||||||
m_tvSampleRate = (m_config.m_outputSampleRate / rateMultiple) * rateMultiple;
|
m_tvSampleRate = (m_config.m_outputSampleRate / rateUnits) * rateUnits; // make sure working sample rate is a multiple of rate units
|
||||||
|
|
||||||
m_settingsMutex.lock();
|
m_settingsMutex.lock();
|
||||||
|
|
||||||
@ -273,33 +275,49 @@ void ATVMod::apply(bool force)
|
|||||||
m_running.m_uniformLevel = m_config.m_uniformLevel;
|
m_running.m_uniformLevel = m_config.m_uniformLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ATVMod::getSampleRateMultiple(ATVStd std)
|
int ATVMod::getSampleRateUnits(ATVStd std)
|
||||||
{
|
{
|
||||||
switch(std)
|
switch(std)
|
||||||
{
|
{
|
||||||
|
case ATVStdPAL525:
|
||||||
|
return 1008000;
|
||||||
|
break;
|
||||||
case ATVStdPAL625:
|
case ATVStdPAL625:
|
||||||
default:
|
default:
|
||||||
return 1000000;
|
return 1000000; // Exact MS/s - us
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATVMod::applyStandard()
|
void ATVMod::applyStandard()
|
||||||
{
|
{
|
||||||
int rateMultiple = getSampleRateMultiple(m_config.m_atvStd);
|
int rateUnits = getSampleRateUnits(m_config.m_atvStd);
|
||||||
m_pointsPerTU = m_tvSampleRate / rateMultiple;
|
m_pointsPerTU = m_tvSampleRate / rateUnits; // TV sample rate is already set at a multiple of rate units
|
||||||
|
|
||||||
switch(m_config.m_atvStd)
|
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:
|
case ATVStdPAL625:
|
||||||
default:
|
default:
|
||||||
m_pointsPerSync = 5 * m_pointsPerTU; // would be 4.7 us actually
|
m_pointsPerSync = (uint32_t) roundf(4.7f * m_pointsPerTU); // normal sync pulse (4.7 us)
|
||||||
m_pointsPerBP = 5 * m_pointsPerTU; // would be 4.7 us actually
|
m_pointsPerBP = (uint32_t) roundf(4.7f * m_pointsPerTU); // back porch (4.7 us)
|
||||||
m_pointsPerFP = 2 * m_pointsPerTU; // would be 1.5 us actually
|
m_pointsPerFP = (uint32_t) roundf(1.5f * m_pointsPerTU); // front porch (1.5 us)
|
||||||
m_pointsPerFSync = 3 * m_pointsPerTU; // would be 2.3 us actually
|
m_pointsPerFSync = (uint32_t) roundf(2.3f * m_pointsPerTU); // equalizing pulse (2.3 us)
|
||||||
m_pointsPerLine = (64 - 12) * m_pointsPerTU; // what is left in a 64 us line
|
// what is left in a 64 us line for the image
|
||||||
m_pointsPerBar = 10 * m_pointsPerTU; // set a bar length to 10 us (~5 bars per line)
|
m_pointsPerImgLine = 64 * m_pointsPerTU - m_pointsPerSync - m_pointsPerBP - m_pointsPerFP;
|
||||||
m_nbLines = 625;
|
m_pointsPerBar = 10 * m_pointsPerTU; // set a bar length to 10 us (~5 bars per line)
|
||||||
m_interlaced = true;
|
m_nbLines = 625;
|
||||||
m_nbHorizPoints = 64 * m_pointsPerTU;
|
m_interlaced = true;
|
||||||
|
m_nbHorizPoints = 64 * m_pointsPerTU; // full line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,8 @@ class ATVMod : public BasebandSampleSource {
|
|||||||
public:
|
public:
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
ATVStdPAL625
|
ATVStdPAL625,
|
||||||
|
ATVStdPAL525
|
||||||
} ATVStd;
|
} ATVStd;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -62,7 +63,7 @@ public:
|
|||||||
|
|
||||||
Real getMagSq() const { return m_movingAverage.average(); }
|
Real getMagSq() const { return m_movingAverage.average(); }
|
||||||
|
|
||||||
static int getSampleRateMultiple(ATVStd std);
|
static int getSampleRateUnits(ATVStd std);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
@ -142,7 +143,7 @@ private:
|
|||||||
int m_tvSampleRate; //!< sample rate for generating signal
|
int m_tvSampleRate; //!< sample rate for generating signal
|
||||||
uint32_t m_pointsPerSync; //!< number of line points for the horizontal sync
|
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_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_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_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
|
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
|
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);
|
int pointIndex = m_horizontalCount - (m_pointsPerSync + m_pointsPerBP);
|
||||||
|
|
||||||
@ -191,7 +192,7 @@ private:
|
|||||||
sample = (pointIndex / m_pointsPerBar) * (m_spanLevel/5.0f) + m_blackLevel;
|
sample = (pointIndex / m_pointsPerBar) * (m_spanLevel/5.0f) + m_blackLevel;
|
||||||
break;
|
break;
|
||||||
case ATVModInputGradient:
|
case ATVModInputGradient:
|
||||||
sample = (pointIndex / m_pointsPerLine) * m_spanLevel + m_blackLevel;
|
sample = (pointIndex / (float) m_pointsPerImgLine) * m_spanLevel + m_blackLevel;
|
||||||
break;
|
break;
|
||||||
case ATVModInputUniform:
|
case ATVModInputUniform:
|
||||||
default:
|
default:
|
||||||
@ -204,14 +205,14 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void pullVSyncLine(int pointIndex, Real& sample)
|
inline void pullVSyncLine(Real& sample)
|
||||||
{
|
{
|
||||||
switch (m_lineCount)
|
switch (m_lineCount)
|
||||||
{
|
{
|
||||||
case 0: // __|__|
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
case 313:
|
case 313:
|
||||||
case 314:
|
case 314: // Whole line "long" pulses
|
||||||
{
|
{
|
||||||
int halfIndex = m_horizontalCount % (m_nbHorizPoints/2);
|
int halfIndex = m_horizontalCount % (m_nbHorizPoints/2);
|
||||||
|
|
||||||
@ -225,25 +226,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: // __||XX
|
case 3:
|
||||||
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 4:
|
case 4:
|
||||||
case 310:
|
case 310:
|
||||||
case 311:
|
case 311:
|
||||||
@ -251,7 +234,7 @@ private:
|
|||||||
case 316:
|
case 316:
|
||||||
case 622:
|
case 622:
|
||||||
case 623:
|
case 623:
|
||||||
case 624:
|
case 624: // Whole line equalizing pulses
|
||||||
{
|
{
|
||||||
int halfIndex = m_horizontalCount % (m_nbHorizPoints/2);
|
int halfIndex = m_horizontalCount % (m_nbHorizPoints/2);
|
||||||
|
|
||||||
@ -265,22 +248,40 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 312: // |XX__|
|
case 2: // long pulse then equalizing pulse
|
||||||
if (m_horizontalCount < m_pointsPerFSync)
|
if (m_horizontalCount < (m_nbHorizPoints/2) - m_pointsPerSync)
|
||||||
{
|
{
|
||||||
sample = 0.0f;
|
sample = 0.0f; // ultra-black
|
||||||
}
|
}
|
||||||
else if (m_horizontalCount < (m_nbHorizPoints/2))
|
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
|
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;
|
break;
|
||||||
default: // black images
|
default: // black images
|
||||||
|
Loading…
x
Reference in New Issue
Block a user