Fix some timing issues resulting from non-integral m_TRperiod for FT4.

This commit is contained in:
Joe Taylor 2019-05-23 13:24:35 -04:00
parent 37291ff64c
commit dfedc40db1
4 changed files with 25 additions and 42 deletions

View File

@ -55,12 +55,14 @@ void Detector::clear ()
qint64 Detector::writeData (char const * data, qint64 maxSize) qint64 Detector::writeData (char const * data, qint64 maxSize)
{ {
int ns=secondInPeriod(); static unsigned mstr0=999999;
if(ns < m_ns) { // When ns has wrapped around to zero, restart the buffers qint64 ms0 = QDateTime::currentMSecsSinceEpoch() % 86400000;
unsigned mstr = ms0 % int(1000.0*m_period); // ms into the nominal Tx start time
if(mstr < mstr0) { //When mstr has wrapped around to 0, restart the buffer
dec_data.params.kin = 0; dec_data.params.kin = 0;
m_bufferPos = 0; m_bufferPos = 0;
} }
m_ns=ns; mstr0=mstr;
// no torn frames // no torn frames
Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ()))); Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ())));
@ -73,7 +75,7 @@ qint64 Detector::writeData (char const * data, qint64 maxSize)
if (framesAccepted < static_cast<size_t> (maxSize / bytesPerFrame ())) { if (framesAccepted < static_cast<size_t> (maxSize / bytesPerFrame ())) {
qDebug () << "dropped " << maxSize / bytesPerFrame () - framesAccepted qDebug () << "dropped " << maxSize / bytesPerFrame () - framesAccepted
<< " frames of data on the floor!" << " frames of data on the floor!"
<< dec_data.params.kin << ns; << dec_data.params.kin << mstr;
} }
for (unsigned remaining = framesAccepted; remaining; ) { for (unsigned remaining = framesAccepted; remaining; ) {
@ -121,14 +123,3 @@ qint64 Detector::writeData (char const * data, qint64 maxSize)
return maxSize; // we drop any data past the end of the buffer on return maxSize; // we drop any data past the end of the buffer on
// the floor until the next period starts // the floor until the next period starts
} }
unsigned Detector::secondInPeriod () const
{
// we take the time of the data as the following assuming no latency
// delivering it to us (not true but close enough for us)
qint64 now (QDateTime::currentMSecsSinceEpoch ());
unsigned secondInToday ((now % 86400000LL) / 1000);
unsigned secInPeriod = fmod(double(secondInToday),m_period);
return secInPeriod;
}

View File

@ -41,7 +41,6 @@ protected:
private: private:
void clear (); // discard buffer contents void clear (); // discard buffer contents
unsigned secondInPeriod () const;
unsigned m_frameRate; unsigned m_frameRate;
double m_period; double m_period;

View File

@ -32,8 +32,8 @@ Modulator::Modulator (unsigned frameRate, double periodLengthInSeconds,
, m_phi {0.0} , m_phi {0.0}
, m_toneSpacing {0.0} , m_toneSpacing {0.0}
, m_fSpread {0.0} , m_fSpread {0.0}
, m_frameRate {frameRate}
, m_period {periodLengthInSeconds} , m_period {periodLengthInSeconds}
, m_frameRate {frameRate}
, m_state {Idle} , m_state {Idle}
, m_tuning {false} , m_tuning {false}
, m_cwLevel {false} , m_cwLevel {false}
@ -50,13 +50,10 @@ void Modulator::start (unsigned symbolsLength, double framesPerSymbol,
Q_ASSERT (stream); Q_ASSERT (stream);
// Time according to this computer which becomes our base time // Time according to this computer which becomes our base time
qint64 ms0 = QDateTime::currentMSecsSinceEpoch() % 86400000; qint64 ms0 = QDateTime::currentMSecsSinceEpoch() % 86400000;
unsigned mstr = ms0 % int(1000.0*m_period); // ms into the nominal Tx start time
// qDebug() << "ModStart" << QDateTime::currentDateTimeUtc().toString("hh:mm:ss.sss"); if(m_state != Idle) stop();
if(m_state != Idle) stop ();
m_quickClose = false; m_quickClose = false;
m_symbolsLength = symbolsLength; m_symbolsLength = symbolsLength;
m_isym0 = std::numeric_limits<unsigned>::max (); // big number m_isym0 = std::numeric_limits<unsigned>::max (); // big number
m_frequency0 = 0.; m_frequency0 = 0.;
@ -68,37 +65,33 @@ void Modulator::start (unsigned symbolsLength, double framesPerSymbol,
m_toneSpacing = toneSpacing; m_toneSpacing = toneSpacing;
m_bFastMode=fastMode; m_bFastMode=fastMode;
m_TRperiod=TRperiod; m_TRperiod=TRperiod;
unsigned delay_ms = 1920 == m_nsps && 15 == m_period ? 500 : 1000; unsigned delay_ms=1000;
if(m_nsps==1920) delay_ms=500; //FT8
if(m_nsps==576) delay_ms=300; //FT4
// noise generator parameters // noise generator parameters
if (m_addNoise) { if (m_addNoise) {
m_snr = qPow (10.0, 0.05 * (dBSNR - 6.0)); m_snr = qPow (10.0, 0.05 * (dBSNR - 6.0));
m_fac = 3000.0; m_fac = 3000.0;
if (m_snr > 1.0) m_fac = 3000.0 / m_snr; if (m_snr > 1.0) m_fac = 3000.0 / m_snr;
} }
unsigned mstr = ms0 % int(1000.0*m_period); // ms in period // round up to an exact portion of a second that allows for startup delays
// round up to an exact portion of a second that allows for startup
// delays
m_ic = (mstr / delay_ms) * m_frameRate * delay_ms / 1000; m_ic = (mstr / delay_ms) * m_frameRate * delay_ms / 1000;
if(m_bFastMode) m_ic=0; if(m_bFastMode) m_ic=0;
m_silentFrames = 0; m_silentFrames = 0;
// calculate number of silent frames to send, so that audio will start at // calculate number of silent frames to send, so that audio will start at
// the nominal time "delay_ms" into the Tx sequence. // the nominal time "delay_ms" into the Tx sequence.
if (synchronize && !m_tuning && !m_bFastMode) { if (synchronize && !m_tuning && !m_bFastMode) {
m_silentFrames = m_ic + m_frameRate / (1000 / delay_ms) - (mstr * (m_frameRate / 1000)); m_silentFrames = m_ic + m_frameRate / (1000 / delay_ms) - (mstr * (m_frameRate / 1000));
} }
if(symbolsLength==105 and framesPerSymbol==576
and (toneSpacing==12000.0/576.0 or toneSpacing==-2.0)) { // qDebug() << "aa" << QDateTime::currentDateTimeUtc().toString("hh:mm:ss.zzz")
//### FT4 parameters // << m_ic << m_silentFrames << m_silentFrames/48000.0
m_ic=0; // << mstr << fmod(double(ms0),1000.0*m_period);
m_silentFrames=0;
}
// qDebug() << "Mod AA" << symbolsLength << framesPerSymbol << toneSpacing;
// qDebug() << "Mod AB" << delay_ms << mstr << m_ic << m_silentFrames;
initialize (QIODevice::ReadOnly, channel); initialize (QIODevice::ReadOnly, channel);
Q_EMIT stateChanged ((m_state = (synchronize && m_silentFrames) ? Q_EMIT stateChanged ((m_state = (synchronize && m_silentFrames) ?

View File

@ -2838,12 +2838,12 @@ void MainWindow::decode() //decode()
dec_data.params.nutc=100*ihr + imin; dec_data.params.nutc=100*ihr + imin;
if(m_mode=="ISCAT" or m_mode=="MSK144" or m_bFast9 or m_mode=="FT8" or m_mode=="FT4") { if(m_mode=="ISCAT" or m_mode=="MSK144" or m_bFast9 or m_mode=="FT8" or m_mode=="FT4") {
qint64 ms=1000.0*(2.0-m_TRperiod); qint64 ms=1000.0*(2.0-m_TRperiod);
if(m_mode=="FT4") ms=1000.0*(3.0-m_TRperiod); if(m_mode=="FT4") ms=1000.0*(2.0-m_TRperiod);
QDateTime t=QDateTime::currentDateTimeUtc().addMSecs(ms); QDateTime t=QDateTime::currentDateTimeUtc().addMSecs(ms);
ihr=t.toString("hh").toInt(); ihr=t.toString("hh").toInt();
imin=t.toString("mm").toInt(); imin=t.toString("mm").toInt();
int isec=t.toString("ss").toInt(); int isec=t.toString("ss").toInt();
if(m_mode!="FT4") isec=isec - fmod(double(isec),m_TRperiod); isec=isec - fmod(double(isec),m_TRperiod);
dec_data.params.nutc=10000*ihr + 100*imin + isec; dec_data.params.nutc=10000*ihr + 100*imin + isec;
} }
} }
@ -3498,9 +3498,9 @@ void MainWindow::guiUpdate()
if(m_transmitting or m_auto or m_tune) { if(m_transmitting or m_auto or m_tune) {
m_dateTimeLastTX = QDateTime::currentDateTimeUtc (); m_dateTimeLastTX = QDateTime::currentDateTimeUtc ();
// Check for "txboth" (testing purposes only) // Check for "txboth" (FT4 testing purposes only)
QFile f(m_appDir + "/txboth"); QFile f(m_appDir + "/txboth");
if(f.exists() and fmod(tsec,m_TRperiod) < (1.0 + 85.0*m_nsps/12000.0)) m_bTxTime=true; if(f.exists() and fmod(tsec,m_TRperiod) < (0.5 + 105.0*576.0/12000.0)) m_bTxTime=true;
// Don't transmit another mode in the 30 m WSPR sub-band // Don't transmit another mode in the 30 m WSPR sub-band
Frequency onAirFreq = m_freqNominal + ui->TxFreqSpinBox->value(); Frequency onAirFreq = m_freqNominal + ui->TxFreqSpinBox->value();