Fixed issue with duplicate decodes based on the ring buffer after tx cycles completed when it lined up with a decode cycle.

This commit is contained in:
Jordan Sherer 2019-11-05 15:43:34 -05:00
parent f4ae642cec
commit 720bd6b22a
5 changed files with 61 additions and 24 deletions

View File

@ -48,7 +48,11 @@ void Detector::clear ()
qint64 now (DriftingDateTime::currentMSecsSinceEpoch ()); qint64 now (DriftingDateTime::currentMSecsSinceEpoch ());
unsigned msInPeriod ((now % 86400000LL) % (m_period * 1000)); unsigned msInPeriod ((now % 86400000LL) % (m_period * 1000));
dec_data.params.kin = qMin ((msInPeriod * m_frameRate) / 1000, static_cast<unsigned> (sizeof (dec_data.d2) / sizeof (dec_data.d2[0]))); dec_data.params.kin = qMin ((msInPeriod * m_frameRate) / 1000, static_cast<unsigned> (sizeof (dec_data.d2) / sizeof (dec_data.d2[0])));
m_bufferPos = 0; m_bufferPos = m_samplesPerFFT;
// erase everything after kin.
memset(dec_data.d2 + dec_data.params.kin, 0, sizeof(dec_data.d2) - (sizeof(dec_data.d2[0]) * dec_data.params.kin));
qDebug() << "advancing detector buffer to" << dec_data.params.kin; qDebug() << "advancing detector buffer to" << dec_data.params.kin;
#else #else
dec_data.params.kin = 0; dec_data.params.kin = 0;

View File

@ -7,9 +7,8 @@
#define RX_SAMPLE_RATE 12000 #define RX_SAMPLE_RATE 12000
#define JS8_USE_REFSPEC 1 // compute the signal refspec #define JS8_USE_REFSPEC 1 // compute the signal refspec
#define JS8_USE_IHSYM 1 // compute ihsym manually instead of from symspec #define JS8_USE_IHSYM 0 // compute ihsym manually instead of from symspec
#define JS8_RING_BUFFER 1 // use a ring buffer instead of clearing the decode frames #define JS8_RING_BUFFER 1 // use a ring buffer instead of clearing the decode frames
#define JS8_DECODER_ONE 1 // decode only one mode at a time
#define JS8_DECODER_E2S 0 // decode every 2 seconds instead of at the half symbol stop #define JS8_DECODER_E2S 0 // decode every 2 seconds instead of at the half symbol stop
#define JS8_NUM_SYMBOLS 79 #define JS8_NUM_SYMBOLS 79

View File

@ -1,7 +1,7 @@
program jt9 program jt9
! Decoder for JT9. Can run stand-alone, reading data from *.wav files; ! Decoder for js8. Can run stand-alone, reading data from *.wav files;
! or as the back end of wsjt-x, with data placed in a shared memory region. ! or as the back end of js8call, with data placed in a shared memory region.
use options use options
use prog_args use prog_args
@ -15,7 +15,6 @@ program jt9
integer(C_INT) iret integer(C_INT) iret
type(wav_header) wav type(wav_header) wav
real*4 s(NSMAX)
character c character c
character(len=500) optarg, infile character(len=500) optarg, infile
character wisfile*80 character wisfile*80
@ -234,15 +233,6 @@ program jt9
4 call timer('read_wav',1) 4 call timer('read_wav',1)
nhsym=(k-2048)/kstep nhsym=(k-2048)/kstep
if(nhsym.ge.1 .and. nhsym.ne.nhsym0) then if(nhsym.ge.1 .and. nhsym.ne.nhsym0) then
if(mode.eq.9 .or. mode.eq.74) then
! Compute rough symbol spectra for the JT9 decoder
ingain=0
call timer('symspec ',0)
nminw=1
call symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb, &
s,df3,ihsym,npts8,pxdbmax)
call timer('symspec ',1)
endif
nhsym0=nhsym nhsym0=nhsym
if(nhsym.ge.181) exit if(nhsym.ge.181) exit
endif endif

View File

@ -1,9 +1,10 @@
subroutine symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb,s, & subroutine symspec(shared_data,k,k0,ntrperiod,nsps,ingain,nminw,pxdb,s, &
df3,ihsym,npts8,pxdbmax) df3,ihsym,npts8,pxdbmax)
! Input: ! Input:
! shared_data pointer to the most recent new data ! shared_data pointer to the most recent new data
! k frames in that data ! k frames in that data
! k0 the last k observed
! ntrperiod T/R sequence length, minutes ! ntrperiod T/R sequence length, minutes
! nsps samples per symbol, at 12000 Hz ! nsps samples per symbol, at 12000 Hz
! ndiskdat 0/1 to indicate if data from disk ! ndiskdat 0/1 to indicate if data from disk
@ -32,7 +33,7 @@ subroutine symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb,s, &
integer nch(7) integer nch(7)
common/spectra/syellow(NSMAX),ref(0:3456),filter(0:3456) common/spectra/syellow(NSMAX),ref(0:3456),filter(0:3456)
data k0/99999999/,nfft3z/0/ data nfft3z/0/
data nch/1,2,4,9,18,36,72/ data nch/1,2,4,9,18,36,72/
equivalence (xc,cx) equivalence (xc,cx)
save save

View File

@ -79,7 +79,7 @@
extern "C" { extern "C" {
//----------------------------------------------------- C and Fortran routines //----------------------------------------------------- C and Fortran routines
void symspec_(struct dec_data *, int* k, int* ntrperiod, int* nsps, int* ingain, void symspec_(struct dec_data *, int* k, int* k0, int* ntrperiod, int* nsps, int* ingain,
int* minw, float* px, float s[], float* df3, int* nhsym, int* npts8, int* minw, float* px, float s[], float* df3, int* nhsym, int* npts8,
float *m_pxmax); float *m_pxmax);
@ -2542,11 +2542,16 @@ int MainWindow::computeFramesNeededForDecode(int submode, int period){
//-------------------------------------------------------------- dataSink() //-------------------------------------------------------------- dataSink()
void MainWindow::dataSink(qint64 frames) void MainWindow::dataSink(qint64 frames)
{ {
static int k0 = 0; static int k0 = 999999999;
static float s[NSMAX]; static float s[NSMAX];
char line[80]; char line[80];
int k (frames); int k (frames);
if(k0 == 999999999){
m_ihsym = int((float)frames/(float)m_nsps)*2;
k0 = k;
}
QString fname {QDir::toNativeSeparators(m_config.writeable_data_dir ().absoluteFilePath ("refspec.dat"))}; QString fname {QDir::toNativeSeparators(m_config.writeable_data_dir ().absoluteFilePath ("refspec.dat"))};
QByteArray bafname = fname.toLatin1(); QByteArray bafname = fname.toLatin1();
const char *c_fname = bafname.data(); const char *c_fname = bafname.data();
@ -2588,25 +2593,37 @@ void MainWindow::dataSink(qint64 frames)
} }
k0 = k; k0 = k;
int ihs = m_ihsym; int ihs = m_ihsym;
symspec_(&dec_data,&k,&trmin,&nsps,&m_inGain,&nsmo,&m_px,s,&m_df3,&ihs,&m_npts8,&m_pxmax); dec_data.params.kpos = computeCycleStartForDecode(computeCurrentCycle(m_TRperiod), m_TRperiod);
symspec_(&dec_data,&k,&k0,&trmin,&nsps,&m_inGain,&nsmo,&m_px,s,&m_df3,&ihs,&m_npts8,&m_pxmax);
// 3) if symspec wants ihs to be 0, set it. // 3) if symspec wants ihs to be 0, set it.
if(ihs == 0){ if(ihs == 0){
m_ihsym = ihs; m_ihsym = ihs;
} else { } else {
m_ihsym += 1; m_ihsym += 1;
} }
qDebug() << "dataSink" << k << "ihsym" << m_ihsym << "ihs" << ihs;
// make ihsym similar to how it was...relative to the tr period
m_ihsym = m_ihsym % (m_TRperiod*RX_SAMPLE_RATE/m_nsps*2);
/// qDebug() << "dataSink" << k << "ihsym" << m_ihsym << "ihs" << ihs;
/// QVector<float> sss;
/// for(int i = 0; i < 10; i++){
/// sss << s[i];
/// }
/// qDebug() << "-->" << sss;
/// END IHSYM /// END IHSYM
#else #else
symspec_(&dec_data,&k,&trmin,&nsps,&m_inGain,&nsmo,&m_px,s,&m_df3,&m_ihsym,&m_npts8,&m_pxmax); m_ihsym=m_ihsym%(m_TRperiod*RX_SAMPLE_RATE/m_nsps*2);
qDebug() << "k" << k << "k0" << k0 << "ihsym" << m_ihsym;
symspec_(&dec_data,&k,&k0,&trmin,&nsps,&m_inGain,&nsmo,&m_px,s,&m_df3,&m_ihsym,&m_npts8,&m_pxmax);
#endif #endif
if(m_ihsym <= 0) return; if(m_ihsym <= 0) return;
if(ui) ui->signal_meter_widget->setValue(m_px,m_pxmax); // Update thermometer if(ui) ui->signal_meter_widget->setValue(m_px,m_pxmax); // Update thermometer
if(m_monitoring || m_diskData) { if(m_monitoring || m_diskData) {
m_wideGraph->dataSink2(s,m_df3,m_ihsym,m_diskData); m_wideGraph->dataSink2(s, m_df3, m_ihsym, m_diskData);
} }
fixStop(); fixStop();
@ -4140,6 +4157,31 @@ bool MainWindow::decodeReady(int submode, int period, int *pSubmode, int *pPerio
strncpy(dec_data.params.hiscall,(hisCall + " ").toLatin1 ().constData (), 12); strncpy(dec_data.params.hiscall,(hisCall + " ").toLatin1 ().constData (), 12);
strncpy(dec_data.params.hisgrid,(hisGrid + " ").toLatin1 ().constData (), 6); strncpy(dec_data.params.hisgrid,(hisGrid + " ").toLatin1 ().constData (), 6);
#if 0
// for waterfall computation
memset(dec_data.d1, 0, sizeof(dec_data.d1));
int start = 0;
int frames = 0;
if(m_nSubMode == Varicode::JS8CallNormal){
start = dec_data.params.kposA;
frames = dec_data.params.kszA;
}
else if(m_nSubMode == Varicode::JS8CallFast){
start = dec_data.params.kposB;
frames = dec_data.params.kszB;
}
else if(m_nSubMode == Varicode::JS8CallTurbo){
start = dec_data.params.kposC;
frames = dec_data.params.kszC;
}
else if(m_nSubMode == Varicode::JS8CallUltra){
start = dec_data.params.kposD;
frames = dec_data.params.kszD;
}
memcpy(dec_data.d1, dec_data.d2 + start, sizeof(dec_data.d2[0]) * frames);
#endif
#if JS8_TWO_BUFFERS #if JS8_TWO_BUFFERS
#if JS8_RING_BUFFER #if JS8_RING_BUFFER
// clear out d1 // clear out d1
@ -7190,12 +7232,13 @@ void MainWindow::on_actionJS8_triggered()
m_TRperiod = computeSubmodePeriod(m_nSubMode); m_TRperiod = computeSubmodePeriod(m_nSubMode);
m_wideGraph->show(); m_wideGraph->show();
ui->decodedTextLabel2->setText(" UTC dB DT Freq Message"); ui->decodedTextLabel2->setText(" UTC dB DT Freq Message");
m_wideGraph->setPeriod(m_TRperiod, m_nsps);
m_modulator->setTRPeriod(m_TRperiod); // TODO - not thread safe m_modulator->setTRPeriod(m_TRperiod); // TODO - not thread safe
#if JS8_RING_BUFFER #if JS8_RING_BUFFER
Q_ASSERT(NTMAX == 60); Q_ASSERT(NTMAX == 60);
m_wideGraph->setPeriod(m_TRperiod, m_nsps);
m_detector->setTRPeriod(NTMAX / 2); // TODO - not thread safe m_detector->setTRPeriod(NTMAX / 2); // TODO - not thread safe
#else #else
m_wideGraph->setPeriod(m_TRperiod, m_nsps);
m_detector->setTRPeriod(m_TRperiod); // TODO - not thread safe m_detector->setTRPeriod(m_TRperiod); // TODO - not thread safe
#endif #endif
ui->label_7->setText("Rx Frequency"); ui->label_7->setText("Rx Frequency");