2639 lines
92 KiB
C++
2639 lines
92 KiB
C++
/* The algorithms, source code, look-and-feel of WSJT-X and related
|
|
* programs, and protocol specifications for the modes FSK441, FT8, JT4,
|
|
* JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144, are Copyright © 2001-2017
|
|
* by one or more of the following authors: Joseph Taylor, K1JT; Bill
|
|
* Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam,
|
|
* KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q;
|
|
* and other members of the WSJT Development Group.
|
|
*
|
|
* MSHV Q65 Decoder
|
|
* Rewritten into C++ and modified by Hrisimir Hristov, LZ2HV 2015-2021
|
|
* (Edited by Harper Innes, VK1TTY - to remove Gendered Language and Replace with Non-Gendered language) NOTE:May be used under the terms of the GNU General Public License (GPL)
|
|
*/
|
|
|
|
#include "decoderq65.h"
|
|
//#include "../HvMsPlayer/libsound/gen_pulse_gfsk.h"
|
|
//#include "ft_all_ap_def.h"
|
|
//#include <unistd.h>
|
|
|
|
#define NSTEP 8
|
|
#define NMAX (120*12000) // !Max TRperiod is 300 s
|
|
#define PLOG_MIN -242.0 //!List decoding threshold
|
|
|
|
static const int isync[86] =
|
|
{
|
|
1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85
|
|
}
|
|
;//22
|
|
|
|
//#define s3_offsetc 84
|
|
#define ccf_offsetr 70 //and ccf1_
|
|
#define ccf_offsetc 7000 //and ccf1_
|
|
|
|
//#include <QtGui>
|
|
|
|
DecoderQ65::DecoderQ65()
|
|
{
|
|
pomAll.initPomAll();//2.66 for pctile_shell
|
|
f_multi_answer_modq65 = false;
|
|
LL0=iz0=jz0=0;
|
|
ncw = 0;
|
|
mode_q65 = 1;
|
|
s_ntrperiod = 30;//default
|
|
s_ndepth = 1;
|
|
TGenQ65 = new GenQ65(true);
|
|
npasses = 0;
|
|
ncontest0 = -1;//first
|
|
f_clravg_after_decode = false;
|
|
s_nQSOprogress = 0;
|
|
f_averaging = false;
|
|
f_single_decode = false;
|
|
lclearave = false;
|
|
nftx = 1200.0;
|
|
f_emedelay = false;
|
|
s_cont_id = 0;
|
|
s_cont_type = 0;
|
|
s_maxiters = 0;
|
|
s_lapon = false;
|
|
nhist = 0; //twopi=8.0*atan(1.0); //pi=4.0*atan(1.0);
|
|
drift = 0.0;
|
|
f_max_drift = false;
|
|
f0nd = 1200.0;
|
|
xdtnd = 0.01;
|
|
max_drift = 0;
|
|
}
|
|
DecoderQ65::~DecoderQ65()
|
|
{}
|
|
void DecoderQ65::SetStMultiAnswerMod(bool f)//2.65
|
|
{
|
|
f_multi_answer_modq65 = f;
|
|
}
|
|
void DecoderQ65::SetMaxDrift(bool f)
|
|
{
|
|
f_max_drift = f;
|
|
}
|
|
void DecoderQ65::SetPeriod(int i)
|
|
{
|
|
s_ntrperiod = i; //qDebug()<<i;
|
|
}
|
|
void DecoderQ65::SetStDecoderDeep(int i)
|
|
{
|
|
s_ndepth = i;
|
|
}
|
|
void DecoderQ65::SetStWords(QString s1,QString,int cq3,int ty4)
|
|
{
|
|
s_mycall = s1;//May call or my base call ?
|
|
s_cont_id = cq3;
|
|
s_cont_type = ty4; //qDebug()<<id3<<ty4;
|
|
}
|
|
void DecoderQ65::SetStTheirCallGrid(QString c,QString g)
|
|
{
|
|
s_theircall = c;
|
|
s_theirgrid = g; //qDebug()<<"s_cg"<<s_theircall<<s_theirgrid;
|
|
}
|
|
void DecoderQ65::SetStDecode(QString time,int mousebutton)
|
|
{
|
|
s_time = time;
|
|
s_mousebutton = mousebutton;//mousebutton Left=1, Right=3 fullfile=0 rtd=2
|
|
}
|
|
void DecoderQ65::SetStQSOProgress(int i)
|
|
{
|
|
s_nQSOprogress = i; //qDebug()<<"s_nQSOprogress"<<i;
|
|
}
|
|
void DecoderQ65::AutoClrAvgChanged(bool f)
|
|
{
|
|
f_clravg_after_decode = f; //qDebug()<<"Auto clar avg"<<f;
|
|
}
|
|
void DecoderQ65::AvgDecodeChanged(bool f)
|
|
{
|
|
f_averaging = f; //qDebug()<<"f_averaging"<<f;
|
|
}
|
|
void DecoderQ65::SetSingleDecQ65(bool f)
|
|
{
|
|
f_single_decode = f; //qDebug()<<"f_single_decode"<<f;
|
|
}
|
|
void DecoderQ65::SetClearAvgQ65()
|
|
{
|
|
lclearave = true; //qDebug()<<"lclearave"<<lclearave;
|
|
emit EmitAvgSavesQ65(0,0);
|
|
}
|
|
void DecoderQ65::SetTxFreq(double fr)
|
|
{
|
|
nftx = fr;
|
|
}
|
|
void DecoderQ65::SetDecAftEMEDelay(bool f)
|
|
{
|
|
f_emedelay = f; //qDebug()<<"f_emedelay"<<f_emedelay;
|
|
}
|
|
void DecoderQ65::SetStApDecode(bool f)
|
|
{
|
|
s_lapon = f; //qDebug()<<"s_lapon"<<s_lapon;
|
|
}
|
|
void DecoderQ65::q65_snr(int *dat4,double dtdec,double f0dec,int mode_q65,double &snr2)//int nused,
|
|
{
|
|
//! Estimate SNR of a decoded transmission by aligning the spectra of
|
|
//! all 85 symbols.
|
|
int codeword2[70];//63
|
|
int itone[100];//(85)
|
|
double spec[7000];//iz0 7000
|
|
|
|
q65S.q65_enc(dat4,codeword2);
|
|
int iii=0;
|
|
int kk=0;
|
|
for (int j = 0; j < 85 ; ++j)
|
|
{//do j=1,85
|
|
if (j==isync[iii]-1)//2.57 error -1
|
|
{
|
|
iii++;
|
|
itone[j]=0;
|
|
}
|
|
else
|
|
{
|
|
itone[j]=codeword2[kk] + 1;
|
|
kk++;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < 6700 ; ++i) spec[i]=0.0;
|
|
int lagpk=(int)(dtdec/dtstep);
|
|
for (int k = 0; k < 85 ; ++k)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do k=1,85
|
|
int j=j0 + NSTEP*k + lagpk;//j=j0 + NSTEP*(k-1) + 1 + lagpk
|
|
if (j>=0 && j<jz0)
|
|
{
|
|
for (int i = 0; i < iz0 ; ++i)
|
|
{//do i=1,iz0
|
|
int ii=i+mode_q65*itone[k];
|
|
if (ii>=0 && ii<iz0) spec[i]+=s1raw_[j][ii];//(ii,j)
|
|
}
|
|
}
|
|
}
|
|
|
|
int i00=(int)(f0dec/df);
|
|
int nsum=fmax(10*mode_q65,(int)(50.0/df));
|
|
int ia=fmax(0,(i00 - 2*nsum));//2.55 ia=max(1,i0-2*nsum) //old int ia=i00 - 2*nsum;
|
|
int ib=fmin(iz0,(i00+2*nsum));//2.55 ib=min(iz0,i0+2*nsum) //old int ib=i00 + 2*nsum;
|
|
int ibb = ib-nsum;
|
|
double sum1 = 0.0; //qDebug()<<ia<<ib<<nsum<<ibb;
|
|
double sum2 = 0.0;
|
|
for (int i = 0; i < nsum ; ++i)
|
|
{
|
|
sum1+=spec[i+ia];//sum1=sum(spec(ia:ia+nsum-1))
|
|
sum2+=spec[ibb+i];//sum2=sum(spec(ib-nsum+1:ib))
|
|
}
|
|
double avg=(sum1+sum2)/(2.0*(double)nsum);
|
|
if (avg==0.0) avg=0.000001;
|
|
for (int i = 0; i < iz0 ; ++i) spec[i]/=avg; //!Baseline level is now 1.0
|
|
//double smax = pomAll.maxval_da_beg_to_end(spec,ia,ib);//smax=maxval(spec(ia:ib))
|
|
double sig_area = 0.0;
|
|
for (int i = ia+nsum; i < ib-nsum ; ++i) sig_area+=(spec[i]-1.0); //sig_area=sum(spec(ia+nsum:ib-nsum)-1.0)
|
|
//w_equiv=sig_area/(smax-1.0)
|
|
snr2=pomAll.db(fmax(1.0,sig_area)) - pomAll.db(2500.0/df);//snr2=db(max(1.0,sig_area)) - db(2500.0/df)
|
|
//2.66 stop w260rc1
|
|
/*if (nused==2) snr2=snr2 - 2.0;
|
|
if (nused==3) snr2=snr2 - 2.9;
|
|
if (nused>=4) snr2=snr2 - 3.5;*/
|
|
}
|
|
void DecoderQ65::SetClearAvgQ65all()
|
|
{
|
|
//qDebug()<<"Clear ALL";
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
for (int j = 0; j < 798 ; ++j)
|
|
{
|
|
for (int z = 0; z < 6998 ; ++z) s1a_[i][j][z]=0.0;//s1a=0.
|
|
}
|
|
}
|
|
navg[0]=0;
|
|
navg[1]=0;
|
|
emit EmitAvgSavesQ65(0,0);
|
|
}
|
|
void DecoderQ65::q65_clravg()
|
|
{
|
|
//! Clear the averaging array to start a new average.
|
|
//s1a_[2][800][7000] = 0.0; //if(allocated(s1a)) s1a(:,:,iseq)=0.
|
|
for (int j = 0; j < 798 ; ++j)
|
|
{
|
|
for (int z = 0; z < 6998 ; ++z) s1a_[iseq][j][z]=0.0;//s1a=0.
|
|
}
|
|
navg[iseq]=0;
|
|
emit EmitAvgSavesQ65(navg[0],navg[1]);
|
|
}
|
|
bool DecoderQ65::isgrid4_rr73(QString s)
|
|
{
|
|
bool res = false;
|
|
/*isgrid(g1)=g1(1:1).ge.'A' .and. g1(1:1).le.'R' .and. g1(2:2).ge.'A' .and. &
|
|
g1(2:2).le.'R' .and. g1(3:3).ge.'0' .and. g1(3:3).le.'9' .and. &
|
|
g1(4:4).ge.'0' .and. g1(4:4).le.'9' .and. g1(1:4).ne.'RR73'*/
|
|
if (s.count()>3)
|
|
{
|
|
int c1 = (int)s.at(0).toLatin1();
|
|
int c2 = (int)s.at(1).toLatin1();
|
|
int c3 = (int)s.at(2).toLatin1();
|
|
int c4 = (int)s.at(3).toLatin1();
|
|
if (c1>=(int)'A' && c1<=(int)'R' && c2>=(int)'A' && c2<=(int)'R' &&
|
|
c3>=(int)'0' && c3<=(int)'9' && c4>=(int)'0' && c4<=(int)'9' && s.mid(0,4)!="RR73")
|
|
res = true;
|
|
}
|
|
return res;
|
|
}
|
|
void DecoderQ65::q65_hist(int if0,QString msg0,QString &dxcall,QString &dxgrid)//2.55 f=rtue=write f=false=find ,bool f
|
|
{
|
|
//! Save the MAXHIST most receent decodes, and their f0 values; or, if
|
|
//! dxcall is present, look up the most recent dxcall and dxgrid at the
|
|
//! specified f0.
|
|
const int MAXHIST = 60;//wsjt-x=100
|
|
QString g1;
|
|
|
|
//if(!dxcall.isEmpty()) goto c100; //if(present(dxcall)) goto c100; //!This is a lookup request
|
|
//if(!f) goto c100; //2.55 f=rtue=write f=false=find
|
|
if (!msg0.isEmpty())
|
|
{
|
|
if (nhist>MAXHIST-1)
|
|
{
|
|
for (int i = 0; i < MAXHIST-1; ++i) //!List is full, must make room
|
|
{
|
|
nf0[i]=nf0[i+1];
|
|
msg[i]=msg[i+1];
|
|
}
|
|
nhist = MAXHIST-1;
|
|
} //!Insert msg0 at end of list
|
|
nf0[nhist]=if0;
|
|
msg[nhist]=msg0;
|
|
nhist++;
|
|
//for (int i = 0; i < nhist ; ++i) qDebug()<<QString("%1").arg(nf0[i])<<msg[i];
|
|
//qDebug()<<"-------------------------";
|
|
return;
|
|
}
|
|
//c100:
|
|
//hv dxcall=""; //!This is a lookup request
|
|
//hv dxgrid=""; //! Look for a decode close to if0, starting with most recent ones
|
|
for (int i = nhist; i >= 0; --i)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do i=nhist,1,-1
|
|
if (fabs(nf0[i]-if0)>10) continue; //if(abs(nf0(i)-if0).gt.10) cycle
|
|
int i1 = msg[i].indexOf(" ",0); //i1=index(msg(i),' ')
|
|
if (i1>=3 && i1<=12) //LZ2HV SP9HWY KN23 if(i1>=4 .and. i1<=13) then
|
|
{
|
|
int i2=msg[i].indexOf(" ",i1+1); //i2=index(msg(i)(i1+1:),' ') + i1
|
|
dxcall=msg[i].mid(i1+1,i2-(i1+1)); //dxcall=msg(i)(i1+1:i2-1)
|
|
g1=msg[i].mid(i2+1,4); //g1=msg(i)(i2+1:i2+4)
|
|
if (isgrid4_rr73(g1)) dxgrid=g1; //if(isgrid(g1)) dxgrid=g1(1:4)
|
|
else dxgrid=""; //hv
|
|
break;
|
|
}
|
|
} //qDebug()<<"RESULT="<<if0<<dxcall<<dxgrid;
|
|
}
|
|
void DecoderQ65::q65_set_list(QString mycall,QString theircall,QString theirgrid)//2.61
|
|
{
|
|
ncw = 0;
|
|
if (theircall.isEmpty()) return;
|
|
ncw = MAX_NCW;
|
|
|
|
bool my_std = pomAll.isStandardCall(mycall.trimmed());
|
|
bool their_std = pomAll.isStandardCall(theircall.trimmed());
|
|
|
|
//QString msg0=mycall+" "+theircall+" ";
|
|
for (int i = 0; i < ncw; ++i)
|
|
{//do i=1,ncw
|
|
//QString msg = msg0;
|
|
QString msg = mycall+" "+theircall;
|
|
if (!my_std)
|
|
{
|
|
//if (i==0) msg = "<"+mycall+"> "+theircall;
|
|
//if (i>=5) msg = "<"+mycall+"> "+theircall+" ";
|
|
if (i==0 || i>=5) msg = "<"+mycall+"> "+theircall;
|
|
if (i>=1 && i<=3) msg = mycall+" <"+theircall+">";
|
|
}
|
|
else if (!their_std)
|
|
{
|
|
//if(i==0) msg = "<"+mycall+"> "+theircall;
|
|
//if(i>=1 && i<=3) msg = "<"+mycall+"> "+theircall+" ";
|
|
if (i<=3 || i==5) msg = "<"+mycall+"> "+theircall;//wsjt252
|
|
//if (i==5) msg = "TNX 73 GL";
|
|
if (i>=6) msg = mycall+" <"+theircall+">";
|
|
}
|
|
//else if (i==0) msg = msg0.trimmed();
|
|
|
|
if (i==1) msg.append(" RRR");
|
|
if (i==2) msg.append(" RR73");
|
|
if (i==3) msg.append(" 73");
|
|
if (i==4)
|
|
{
|
|
if (their_std) msg="CQ "+theircall+" "+theirgrid.mid(0,4);//KN23SF
|
|
if (!their_std) msg="CQ "+theircall;//KN23SF
|
|
}
|
|
if (i==5 && their_std) msg.append(" "+theirgrid.mid(0,4));
|
|
|
|
if (i>=6 && i<206)
|
|
{
|
|
int isnr = -50 + (i-6)/2; //isnr = -50 + (i-7)/2 ss.append(QString("%1").arg(abs(s.toInt()),2,10,QChar('0')));
|
|
if (((i+1) & 1)==1)
|
|
{
|
|
if (isnr>-1) msg.append(" +"+QString("%1").arg(abs(isnr),2,10,QChar('0')));
|
|
else msg.append(" -"+QString("%1").arg(abs(isnr),2,10,QChar('0')));
|
|
}
|
|
else
|
|
{
|
|
if (isnr>-1) msg.append(" R+"+QString("%1").arg(abs(isnr),2,10,QChar('0')));
|
|
else msg.append(" R-"+QString("%1").arg(abs(isnr),2,10,QChar('0')));
|
|
}
|
|
|
|
}
|
|
/*if (i<=9 || i>=200)
|
|
{
|
|
qDebug()<<i<<msg;
|
|
if (i==205) qDebug()<<"------------------------------";
|
|
}*/
|
|
int itone[90];
|
|
TGenQ65->genq65itone(msg,itone,false);
|
|
int x = 0;
|
|
int j = 0;
|
|
for (int k = 0; k < 85; ++k)
|
|
{//do k=1,85
|
|
if (k==isync[x]-1)
|
|
{
|
|
x++;
|
|
continue;
|
|
}
|
|
codewords_[i][j]=itone[k];//false make this -> codewords(j,i)=itone(k) - 1
|
|
j++;
|
|
} //qDebug()<<j<<x;
|
|
codewords_[i][j]=0;
|
|
//QString sss;
|
|
//for (int x = 0; x < 63; ++x) sss.append(QString("%1").arg((int)codewords_[i][x]));
|
|
//qDebug()<<"msg"<<sss;
|
|
}
|
|
int c_c = 0;
|
|
for (int i = 0; i < ncw; ++i)
|
|
{
|
|
for (int j = 0; j < 63; ++j)//po kolko da sa
|
|
{
|
|
codewords_1da[c_c]=codewords_[i][j];
|
|
c_c++;
|
|
}
|
|
}
|
|
}
|
|
/*void DecoderQ65::q65_set_list(QString mycall,QString theircall,QString theirgrid)
|
|
{
|
|
ncw = 0;
|
|
if (theircall.isEmpty()) return;
|
|
ncw = MAX_NCW;
|
|
|
|
QString msg0=mycall+" "+theircall+" ";
|
|
for (int i = 0; i < ncw; ++i)
|
|
{//do i=1,ncw
|
|
QString msg = msg0;
|
|
if (i==0) msg = msg0.trimmed();
|
|
if (i==1) msg.append("RRR");
|
|
if (i==2) msg.append("RR73");
|
|
if (i==3) msg.append("73");
|
|
if (i==4) msg="CQ "+theircall+" "+theirgrid.mid(0,4);//KN23SF
|
|
if (i==5) msg.append(theirgrid.mid(0,4));
|
|
if (i>=6 && i<206)
|
|
{
|
|
int isnr = -50 + (i-6)/2; //isnr = -50 + (i-7)/2 ss.append(QString("%1").arg(abs(s.toInt()),2,10,QChar('0')));
|
|
if (((i+1) & 1)==1)
|
|
{
|
|
|
|
if (isnr>-1) msg.append("+"+QString("%1").arg(abs(isnr),2,10,QChar('0')));
|
|
else msg.append("-"+QString("%1").arg(abs(isnr),2,10,QChar('0')));
|
|
}
|
|
else
|
|
{
|
|
if (isnr>-1) msg.append("R+"+QString("%1").arg(abs(isnr),2,10,QChar('0')));
|
|
else msg.append("R-"+QString("%1").arg(abs(isnr),2,10,QChar('0')));
|
|
}
|
|
|
|
} //qDebug()<<i<<msg;
|
|
int itone[90];
|
|
TGenQ65->genq65itone(msg,itone,false);
|
|
int x = 0;
|
|
int j = 0;
|
|
for (int k = 0; k < 85; ++k)
|
|
{//do k=1,85
|
|
if (k==isync[x]-1)
|
|
{
|
|
x++;
|
|
continue;
|
|
}
|
|
codewords_[i][j]=itone[k];//false make this -> codewords(j,i)=itone(k) - 1
|
|
j++;
|
|
} //qDebug()<<j<<x;
|
|
codewords_[i][j]=0;
|
|
//QString sss;
|
|
//for (int x = 0; x < 63; ++x) sss.append(QString("%1").arg((int)codewords_[i][x]));
|
|
//qDebug()<<"msg"<<sss;
|
|
}
|
|
int c_c = 0;
|
|
for (int i = 0; i < ncw; ++i)
|
|
{
|
|
for (int j = 0; j < 63; ++j)//po kolko da sa
|
|
{
|
|
codewords_1da[c_c]=codewords_[i][j];
|
|
c_c++;
|
|
}
|
|
}
|
|
}*/
|
|
void DecoderQ65::smo121(double *x,int beg,int nz)
|
|
{
|
|
double x0=x[beg];
|
|
for (int i =1; i<nz-1; i++)
|
|
{//do i=2,nz-1
|
|
double x1=x[i+beg];
|
|
x[i+beg]=0.5*x[i+beg] + 0.25*(x0+x[i+1+beg]);// x(i)=0.5*x(i) + 0.25*(x0+x(i+1))
|
|
x0=x1;
|
|
}
|
|
}
|
|
void DecoderQ65::q65_symspec(double *iwave,int iz,int jz,double s1_[800][7000])
|
|
{
|
|
//! Compute symbol spectra with NSTEP time-steps per symbol.
|
|
double complex c0[17000];//c0(0:nsps-1) 120 nsps=16000;
|
|
//double complex *c0= new double complex[17000];
|
|
double dc0[17000];
|
|
|
|
int nfft=nsps;
|
|
double fac=(1/32767.0)*0.01;//hv double correction ? =0.01
|
|
|
|
for (int j = 0; j < jz ; ++j)
|
|
{//do j=1,jz !Compute symbol spectra at step size
|
|
int i1=(j-0)*istep;
|
|
int i2=i1+nsps-0;
|
|
int k=0;//k=-1
|
|
for (int i = i1; i < i2; ++i)//for (int i = i1; i < i2; i+=2)
|
|
{//do i=i1,i2,2 //!Load iwave data into complex array c0, for r2c FFT
|
|
dc0[k]=fac*iwave[i]; //c0(k)=fac*cmplx(xx,yy)
|
|
/*double xx = iwave[i];
|
|
double yy = iwave[i+1];
|
|
c0[k]=fac*(xx+yy*I);*/
|
|
k++;
|
|
}
|
|
for (int z = 0; z < 16100 ; ++z) c0[z]=0.0+0.0*I;//c0(k+1:)=0.
|
|
f2a.four2a_d2c(c0,dc0,nfft,-1,0); //call four2a(c0,nfft,1,-1,0) / !r2c FFT f2a.four2a_d2c(cx_ft8,x,NFFT1,-1,0,decid);//call four2a(cx,NFFT1,1,-1,0)
|
|
for (int i = 0; i < iz ; ++i)
|
|
{//do i=1,iz
|
|
s1_[j][i]=(creal(c0[i])*creal(c0[i]) + cimag(c0[i])*cimag(c0[i]));//s1(i,j)=real(c0(i))**2 + aimag(c0(i))**2
|
|
} //qDebug()<<"nsmo"<<j<<iz<<s1_[100][100]<<s1_[200][300];
|
|
//! For large Doppler spreads, should we smooth the spectra here? //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
//qDebug()<<nsmo;
|
|
if (nsmo<=1) nsmo=0;
|
|
for (int i = 1; i <= nsmo; ++i)
|
|
{//do i=1,nsmo
|
|
smo121(s1_[j],0,iz);//call smo121(s1(1:iz,j),iz)
|
|
}
|
|
}
|
|
if (lnewdat)
|
|
{
|
|
/*for (int j = 0; j < jz ; ++j)
|
|
{
|
|
for (int z = 0; z < iz ; ++z) s1a_[iseq][j][z]+=s1_[j][z]; //s1a(:,:,iseq)=s1a(:,:,iseq) + s1
|
|
}
|
|
navg[iseq]+=1; //navg(iseq)=navg(iseq) + 1*/
|
|
|
|
navg[iseq]+=1; //navg(iseq)=navg(iseq) + 1
|
|
double ntc=fmin(navg[iseq],4); //!Averaging time constant in sequences
|
|
double u=1.0/ntc;
|
|
for (int j = 0; j < jz ; ++j) //s1a(:,:,iseq)=u*s1 + (1.0-u)*s1a(:,:,iseq)
|
|
{
|
|
for (int z = 0; z < iz ; ++z) s1a_[iseq][j][z] = u*s1_[j][z] + (1.0-u)*s1a_[iseq][j][z];
|
|
}
|
|
emit EmitAvgSavesQ65(navg[0],navg[1]);
|
|
}
|
|
}
|
|
void DecoderQ65::q65_ccf_85(double s1_[800][7000],int iz,int jz,double nfqso,int ia,int ia2,
|
|
int &ipk,int &jpk,double &f0,double &xdt/*,int &imsg_best*/,double &better/*,double *ccf1*/)
|
|
{
|
|
//! Attempt synchronization using all 85 symbols, in advance of an
|
|
//! attempt at q3 decoding. Return ccf1 for the "red sync curve".
|
|
//double ccf_[300][14000];//ccf(:,:) allocate(ccf(-ia2:ia2,-53:214)) -53:214=267 allocate(ccf1(-ia2:ia2)) 5000Hz= 6333*2
|
|
double (*ccf_)[14000] = new double[310][14000];
|
|
int itone[90];//integer itone(85)
|
|
double best[MAX_NCW+10];//2.59 MAX_NCW 206
|
|
|
|
ipk=0;
|
|
jpk=0;
|
|
double ccf_best=0.0;
|
|
int imsg_best=-1;
|
|
for (int imsg = 0; imsg < ncw; ++imsg)
|
|
{//do imsg=1,ncw
|
|
int i=0;
|
|
int k=0;
|
|
for (int j = 0; j < 85; ++j)
|
|
{//do j=1,85
|
|
if (j==isync[i]-1)
|
|
{
|
|
itone[j]=0;
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
itone[j]=codewords_[imsg][k] + 1;//codewords(k,imsg) + 1
|
|
k++;
|
|
}
|
|
}
|
|
|
|
//! Compute 2D ccf using all 85 symbols in the list message
|
|
for (int z = 0; z < lag2+ccf_offsetr; ++z)//299
|
|
{
|
|
for (int j = ccf_offsetc-ia2; j < ia2+ccf_offsetc; ++j) ccf_[z][j]=0.0;//ccf=0. //13999
|
|
}
|
|
int iia=(int)(200.0/df);
|
|
for (int lag = lag1; lag <= lag2; ++lag)
|
|
{//do lag=lag1,lag2
|
|
for (int x = 0; x < 85; ++x)
|
|
{//do k=1,85
|
|
int j=j0 + NSTEP*x +1 + lag; //j=j0 + NSTEP*(k-1) + 1 + lag
|
|
if (j>0 && j<jz)//if(j.ge.1 .and. j.le.jz) then //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{
|
|
for (int y = -ia2; y < ia2; ++y)
|
|
{//do i=-ia2,ia2
|
|
int ii=i0+mode_q65*itone[x]+y;//ii=i0+mode_q65*itone(k)+i
|
|
//if(ii.ge.iia .and. ii.le.iz) ccf(i,lag)=ccf(i,lag) + s1(ii,j)
|
|
if (ii>=iia && ii<iz)
|
|
{
|
|
ccf_[lag+ccf_offsetr][y+ccf_offsetc]+=s1_[j][ii];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
double ccfmax0=0.0;//2.59
|
|
for (int j = 0; j < lag2+ccf_offsetr; ++j)//299
|
|
{
|
|
double ccfmax = pomAll.maxval_da_beg_to_end(ccf_[j],(ccf_offsetc-ia),(ia+ccf_offsetc));//ccfmax=maxval(ccf(-ia:ia,:))
|
|
if (ccfmax>ccf_best)
|
|
{
|
|
ccf_best=ccfmax;
|
|
ipk = pomAll.maxloc_da_beg_to_end(ccf_[j],(ccf_offsetc-ia),(ia+ccf_offsetc))-ccf_offsetc;//(ccf(-ia:ia,:))
|
|
jpk = j-ccf_offsetr;//-15 -53-1;
|
|
f0 = nfqso+ipk*df;
|
|
xdt=jpk*dtstep;
|
|
imsg_best=imsg;
|
|
//for (int z = 0; z < 13999; ++z) ccf1[z]=ccf_[j][z];//no used hv -> ccf1=ccf(:,jpk)
|
|
//qDebug()<<"ccf_best"<<ccf_best<<nfqso + ipk*df;
|
|
}
|
|
if (ccfmax>ccfmax0) ccfmax0=ccfmax;
|
|
}
|
|
|
|
/*double ccfmax0=0.0;//2.59
|
|
int sj = 0;
|
|
for (int j = 0; j < lag2+ccf_offsetr; ++j)//299
|
|
{
|
|
double ccfmax = pomAll.maxval_da_beg_to_end(ccf_[j],(ccf_offsetc-ia),(ia+ccf_offsetc));//ccfmax=maxval(ccf(-ia:ia,:))
|
|
if (ccfmax>ccfmax0)
|
|
{
|
|
ccfmax0=ccfmax;
|
|
sj=j;
|
|
}
|
|
}
|
|
if (ccfmax0>ccf_best)
|
|
{
|
|
ccf_best=ccfmax0;
|
|
ipk = pomAll.maxloc_da_beg_to_end(ccf_[sj],(ccf_offsetc-ia),(ia+ccf_offsetc))-ccf_offsetc;//(ccf(-ia:ia,:))
|
|
jpk = sj-ccf_offsetr; //-15 -53-1;
|
|
f0 = nfqso+ipk*df;
|
|
xdt=jpk*dtstep;
|
|
imsg_best=imsg;
|
|
//qDebug()<<"ccf_best"<<ccf_best<<nfqso + ipk*df;
|
|
}*/
|
|
|
|
best[imsg]=ccfmax0;//2.59
|
|
|
|
/*ccfmax=maxval(ccf(-ia:ia,:))
|
|
if(ccfmax.gt.ccf_best) then
|
|
ccf_best=ccfmax
|
|
ijpk=maxloc(ccf(-ia:ia,:))
|
|
ipk=ijpk(1)-ia-1
|
|
jpk=ijpk(2)-53-1
|
|
f0=nfqso + ipk*df
|
|
xdt=jpk*dtstep
|
|
imsg_best=imsg
|
|
ccf1=ccf(:,jpk)
|
|
endif*/
|
|
} //! imsg
|
|
|
|
better=0.0; //2.59 c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
if (imsg_best>-1) //if(imsg_best.gt.0) then
|
|
{
|
|
best[imsg_best]=0.0;
|
|
double tbest = pomAll.maxval_da_beg_to_end(best,0,MAX_NCW);
|
|
if (tbest == 0.0) tbest = 0.001;
|
|
better=ccf_best/tbest;//better=ccf_best/maxval(best)
|
|
//qDebug()<<"1="<<ccf_best<<tbest<<better;
|
|
}
|
|
|
|
//deallocate(ccf)
|
|
//qDebug()<<"2="<<imsg_best<<ccf_best<<ipk<<jpk<<"f0="<<f0<<"xdt="<<xdt<<better;
|
|
delete [] ccf_;
|
|
}
|
|
int DecoderQ65::imaxval_da_beg_to_end(int*a,int a_beg,int a_end)
|
|
{
|
|
int max = a[a_beg];
|
|
for (int i = a_beg; i < a_end; i++)
|
|
{
|
|
if (a[i]>max)
|
|
{
|
|
max = a[i];
|
|
}
|
|
}
|
|
return max;
|
|
}
|
|
int DecoderQ65::fmaxloc_da_beg_to_end(float*a,int a_beg,int a_end)
|
|
{
|
|
float max = a[a_beg];
|
|
int loc = a_beg;
|
|
for (int i = a_beg; i < a_end; i++)
|
|
{
|
|
if (a[i]>max)
|
|
{
|
|
loc = i;
|
|
max = a[i];
|
|
}
|
|
}
|
|
return loc;
|
|
}
|
|
void DecoderQ65::q65_bzap(float *s3f,int LL)
|
|
{
|
|
const int NBZAP=15;
|
|
int hist[700];
|
|
for (int i = 0; i < 690 ; ++i) hist[i]=0;
|
|
|
|
for (int j = 0; j < 63 ; ++j)
|
|
{
|
|
int beg = j*LL;
|
|
int ipk1 = fmaxloc_da_beg_to_end(s3f,beg,beg+LL); //int ipk2 = ipk1;
|
|
ipk1 -= beg;// - 64;// - 65;//-65;//??
|
|
hist[ipk1]++; //qDebug()<<j<<ipk1; //=hist[ipk1]+1;
|
|
}
|
|
|
|
/*bool test=false;
|
|
QString sss;
|
|
if (imaxval_da_beg_to_end(hist,0,LL)>NBZAP) test=true;
|
|
if (test)
|
|
{
|
|
for (int x = 0; x < LL; ++x)
|
|
{
|
|
sss.append(QString("%1").arg((int)hist[x]));
|
|
if (hist[x]>9)sss.append(",");
|
|
}
|
|
qDebug()<<"msg"<<sss;
|
|
|
|
int kk = 0;
|
|
for (int j = 0; j < 5; ++j)
|
|
{
|
|
sss.clear();
|
|
for (int i = 0; i < LL; ++i)
|
|
{
|
|
int ss = (int)s3f[kk]; if (ss>1) ss=1;
|
|
sss.append(QString("%1").arg(ss));
|
|
kk++;
|
|
}
|
|
qDebug()<<"in "<<sss;
|
|
}
|
|
}*/
|
|
|
|
if (imaxval_da_beg_to_end(hist,0,LL)>NBZAP)
|
|
{
|
|
for (int i = 0; i < LL; ++i)
|
|
{
|
|
if (hist[i]>NBZAP)
|
|
{
|
|
for (int j = 0; j < 63; ++j)
|
|
{
|
|
s3f[j*LL+i]=1.0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*if (test)
|
|
{
|
|
int kk = 0;
|
|
for (int j = 0; j < 5; ++j)
|
|
{
|
|
sss.clear();
|
|
for (int i = 0; i < LL; ++i)
|
|
{
|
|
int ss = (int)s3f[kk]; if (ss>1) ss=1;
|
|
sss.append(QString("%1").arg(ss));
|
|
kk++;
|
|
} qDebug()<<"out"<<sss;
|
|
}
|
|
}*/
|
|
}
|
|
void DecoderQ65::q65_s1_to_s3(double s1_[800][7000],int iz,int jz,int ipk,int jpk,int LL,float *s3_1fa)
|
|
{
|
|
//! Copy synchronized symbol energies from s1 (or s1a) into s3.
|
|
int i1 = i0+ipk+mode_q65-64;
|
|
int i2 = i1 + LL; //int LL=64*(2+mode_q65);
|
|
int i3 = i2 - i1; //A=192 .... D=640
|
|
if (i1>0 && i2<iz)
|
|
{
|
|
int j=(j0+jpk-8); //j=j0+jpk-7
|
|
int n=0; //int nnn =0;
|
|
for (int k = 0; k < 85 ; ++k)
|
|
{//do k=1,85
|
|
j=j+8;
|
|
if (sync[k]>0.0) continue;
|
|
if (j>0 && j<jz)
|
|
{
|
|
//int nn = 0;
|
|
//QString sss;
|
|
//s3(-64:LL-65,n)=s1(i1:i2,j)
|
|
for (int i = 0; i < i3; ++i)
|
|
{
|
|
s3_1fa[n]=(float)s1_[j][i+i1];
|
|
n++;
|
|
//sss.append(QString("%1").arg((int)s3_1fa[n]));
|
|
//nn++;
|
|
}
|
|
//nnn++; //qDebug()<<nn<<sss;
|
|
}
|
|
} //qDebug()<<nnn<<n;
|
|
}
|
|
q65_bzap(s3_1fa,LL); //!Zap birdies
|
|
}
|
|
void DecoderQ65::SetArrayBits(int in,int in_bits,bool *ar,int &co)
|
|
{
|
|
int izz = in_bits-1;
|
|
for (int i = 0; i < in_bits; ++i)
|
|
{
|
|
ar[co]=(1 & (in >> -(i-izz)));
|
|
co++;
|
|
}
|
|
}
|
|
void DecoderQ65::q65_dec1(float *s3_1fa,int nsubmode,float b90ts,float &esnodb,int &irc,
|
|
int *dat4,QString &decoded)
|
|
{
|
|
//! Attmpt a full-AP list decode.
|
|
bool c77[100];
|
|
float s3prob[4132] = {0.0};//row= 63 col= 64=4032
|
|
bool unpk77_success = false;
|
|
|
|
float plog = PLOG_MIN;
|
|
int nFadingModel=1;
|
|
decoded=""; //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
q65S.q65_intrinsics_ff(s3_1fa,nsubmode,b90ts,nFadingModel,s3prob);
|
|
/*for (int i = 0; i < 63; ++i)
|
|
{
|
|
QString sss;
|
|
for (int j = 0; j < 64; ++j) sss.append(QString("%1").arg((int)s3prob[i+j]));
|
|
qDebug()<<"2="<<sss;
|
|
}*/
|
|
q65S.q65_dec_fullaplist(s3_1fa,s3prob,codewords_1da,ncw,esnodb,dat4,plog,irc);
|
|
//qDebug()<<"<<"<<s3prob[1000]<<s3prob[1001]<<s3prob[1002]<<"==="<<irc<<plog;
|
|
|
|
int sumd4 = 0;
|
|
for (int i = 0; i < 13; ++i) sumd4+=dat4[i];
|
|
if (sumd4<=0) irc=-2;
|
|
if (irc>=0 && plog>PLOG_MIN)//-242
|
|
{
|
|
int co_t = 0;
|
|
for (int i = 0; i < 13; ++i)
|
|
{
|
|
int bits = 6;
|
|
int in = dat4[i];
|
|
if (i==12)
|
|
{
|
|
in/=2;
|
|
bits = 5;
|
|
}
|
|
SetArrayBits(in,bits,c77,co_t);
|
|
}
|
|
decoded = TGenQ65->unpack77(c77,unpk77_success);
|
|
//qDebug()<<"==="<<sumd4<<irc<<plog<<"d="<<decoded<<unpk77_success;
|
|
}
|
|
else irc=-1;
|
|
}
|
|
void DecoderQ65::q65_dec_q3(double s1_[800][7000],int iz,int jz,float *s3_1fa,int LL,
|
|
int ipk,int jpk,double &snr2,int *dat4,int &idec,QString &decoded)
|
|
{
|
|
//! Copy synchronized symbol energies from s1 into s3, then attempt a q3 decode.
|
|
//double s3_[70][750];
|
|
int irc=-2;
|
|
|
|
q65_s1_to_s3(s1_,iz,jz,ipk,jpk,LL,s3_1fa);
|
|
|
|
int nsubmode=0;
|
|
if (mode_q65==2) nsubmode=1;
|
|
else if (mode_q65==4) nsubmode=2;
|
|
else if (mode_q65==8) nsubmode=3;
|
|
//if(mode_q65.eq.16) nsubmode=4
|
|
//if(mode_q65.eq.32) nsubmode=5
|
|
double baud=12000.0/(double)nsps;
|
|
//qDebug()<<ibwa<<ibwa;
|
|
for (int ibw = ibwa; ibw <= ibwb; ++ibw)// min =ibwb
|
|
{//do ibw=ibwa,ibwb
|
|
double b90=pow(1.72,ibw);//1.72**ibw
|
|
float b90ts=b90/baud;
|
|
irc=-2;
|
|
float esnodb=0.0;
|
|
q65_dec1(s3_1fa,nsubmode,b90ts,esnodb,irc,dat4,decoded); //qDebug()<<"ibw="<<ibw;
|
|
if (irc>=0) //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE. if(irc.ge.0) then
|
|
{
|
|
snr2=esnodb - pomAll.db(2500.0/baud) + 3.0; //!Empirical adjustment
|
|
idec=3;
|
|
break;//exit
|
|
}
|
|
}//qDebug()<<irc<<snr2<<idec<<decoded;
|
|
}
|
|
/*void DecoderQ65::q65_ccf_22(double s1_[800][7000],int iz,int jz,double nfqso,int,int &ipk,int &jpk,
|
|
double &f0,double &xdt) //,double *ccf2
|
|
{
|
|
double xdt2[7000];
|
|
double ccf3[7000];//hv correction
|
|
int indx[7000];
|
|
double ccfbest=0.0;
|
|
int ibest=0;
|
|
int lagpk=0;
|
|
int lagbest=0;
|
|
|
|
double mdec_df = 25;
|
|
double snfa = nfqso-mdec_df;
|
|
double snfb = nfqso+mdec_df;
|
|
if (f_single_decode)
|
|
{
|
|
snfa = nfa;
|
|
snfb = nfb;
|
|
}
|
|
//int sif1 = snfa/df;//<- in dots
|
|
//int sif2 = snfb/df;//<- in dots
|
|
//qDebug()<<"limit FREQ="<<snfa<<snfb<<df;
|
|
|
|
for (int i = 0; i < iz; ++i)
|
|
{//do i=1,iz
|
|
double ccfmax=0.0;
|
|
for (int lag = lag1; lag <= lag2; ++lag)
|
|
{//do lag=lag1,lag2
|
|
double ccft=0.0;
|
|
for (int k = 0; k < 85; ++k)
|
|
{//do k=1,85
|
|
int n=NSTEP*k; //n=NSTEP*(k-1) + 1 //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
int j=n+lag+j0; //hv+1 if(j>=1 .and. j<=jz) then
|
|
if (j>0 && j<jz) ccft += sync[k]*s1_[j][i]; //0.01 ccft=ccft + sync(k)*s1(i,j)
|
|
}
|
|
if (ccft>ccfmax) //if(ccft.gt.ccfmax) then
|
|
{
|
|
ccfmax=ccft;
|
|
lagpk=lag; //if (ccfmax>300) qDebug()<<i*df<<"====="<<ccfmax;
|
|
}
|
|
}
|
|
ccf3[i]=ccfmax;
|
|
//ccf2[i]=ccfmax;
|
|
xdt2[i]=(double)lagpk*dtstep; //xdt2(i)=lagpk*dtstep (i*df>=nfa && i*df<=nfb) fabs(i*df-nfqso)<=ftol_single
|
|
double f=(double)i*df; //if (f>=snfa && f<=snfb) qDebug()<<f;
|
|
//if (f>=1000 && f<=1600) qDebug()<<"="<<f<<ccfmax<<ccfbest;
|
|
if (ccfmax>ccfbest && (f>=snfa && f<=snfb)) //if(ccfmax.gt.ccfbest .and. abs(i*df-nfqso)<=ftol) then
|
|
//if (ccfmax>ccfbest && (i>=sif1-1 && i<=sif2+1))
|
|
{
|
|
ccfbest=ccfmax;
|
|
ibest=i;
|
|
lagbest=lagpk; //qDebug()<<"-------------------"<<i*df<<ccfbest;
|
|
}
|
|
}
|
|
|
|
//! Parameters for the top candidate:
|
|
ipk=ibest-i0; //ipk=ibest - i0
|
|
jpk=lagbest;
|
|
f0=nfqso+(double)ipk*df; //ibest*df;// precision error -> nfqso+ipk*df;
|
|
xdt=(double)jpk*dtstep;
|
|
//qDebug()<<"SINGLE="<<xdt<<f0<<ibest;
|
|
|
|
//! Save parameters for best candidates
|
|
int i1=(int)(fmax(nfa,100.0)/df);
|
|
int i2=(int)(fmin(nfb,4900.0)/df);
|
|
int jzz=i2-i1; //750,15
|
|
if (jzz<25) jzz = 25; // as mimimum
|
|
|
|
//int ccf1a = 200.0/df;
|
|
//int ccf1b = 3500.0/df; //2600.0
|
|
//int jzz1 = ccf1b - ccf1a;
|
|
|
|
double t_s[7000];
|
|
for (int z = 0; z < jzz; ++z) t_s[z] = ccf3[z+i1];
|
|
double base = pomAll.pctile_shell(t_s,jzz,40);//pctile(ccf2(i1:i2),jzz,40,base)
|
|
//for (int z = 0; z < jzz1; ++z) t_s[z] = ccf2[z+ccf1a];
|
|
//double base1 = pomAll.pctile_shell(t_s,jzz1,40);
|
|
if (base ==0.0) base =0.000001;
|
|
//if (base1==0.0) base1=0.000001;
|
|
for (int z = 0; z < 6800; ++z)
|
|
{
|
|
ccf3[z]/=base;
|
|
//ccf2[z]/=base1;
|
|
//ccf2[z]=ccf3[z];
|
|
}
|
|
double limit = 0.0;
|
|
for (int z = 0; z < jzz; ++z)
|
|
{
|
|
t_s[z] = ccf3[z+i1];
|
|
indx[z] = 0;
|
|
limit += t_s[z];
|
|
}
|
|
limit /= (double)jzz/2.5;// test 3 ok-> / 2.4
|
|
//limit+=0.5;
|
|
//limit protection ->if (jzz>0) pomAll.indexx_msk(t_s,jzz-1,indx); //call indexx(ccf2(i1:i2),jzz,indx)
|
|
pomAll.indexx_msk(t_s,jzz-1,indx);
|
|
|
|
//qDebug()<<"bASE=================="<<base<<"JZZ="<<jzz<<limit;
|
|
ncand=0;
|
|
int maxcand=20;
|
|
for (int j = 0; j < maxcand; ++j)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do j=1,20
|
|
int i=indx[jzz-j-1]+i1; //i=indx(jzz-j+1)+i1-1 //tested -1 ->1.69 n=ia + indx(iz+1-i) - 1
|
|
//qDebug()<<"ccf2="<<i<<(int)(i*df)<<"CCCCFFF="<<ccf3[i]<<xdt2[i];
|
|
if (ccf3[i]<limit) break;//if(ccf2(i).lt.3.3) exit// !Candidate limit
|
|
double f=(double)i*df; //qDebug()<<"ccf2="<<ccf2[i]<<nfqso<<ftol;
|
|
//double f=(double)nfqso+(i-i0)*df; //nfqso+ipk*df
|
|
//if(f>=(nfqso-ftol) .and. f<=(nfqso+ftol)) cycle
|
|
|
|
if (f>=snfa && f<=snfb) continue;//6.666 Hz error
|
|
//if (i>=sif1 && i<=sif2) continue;
|
|
|
|
int i3=fmax(0, i-mode_q65);//2.55 i3=max(1, i-mode_q65) old int i3=fmax(0,i-67*mode_q65); //max(1,i-67*mode_q65)
|
|
int i4=fmin(iz,i+mode_q65);//2.55 i4=min(iz,i+mode_q65) old int i4=fmin(iz,i+3*mode_q65); //min(iz,i+3*mode_q65)
|
|
double biggest=pomAll.maxval_da_beg_to_end(ccf3,i3,i4); //biggest=maxval(ccf2(i3:i4))
|
|
if (ccf3[i]!=biggest) continue; //if(ccf2(i).ne.biggest) cycle
|
|
//candidates_[0][ncand]=ccf3[i];
|
|
//qDebug()<<"candidats="<<f<<ccf3[i];
|
|
candidates_[0][ncand]=xdt2[i];
|
|
candidates_[1][ncand]=f;
|
|
ncand++;
|
|
if (ncand>maxcand-1) break; // no needed
|
|
}
|
|
//for (int i = 0; i < ncand; ++i)
|
|
//{
|
|
//qDebug()<<"candidats="<<candidates_[0][i]<<candidates_[1][i];
|
|
//}
|
|
}*/
|
|
void DecoderQ65::q65_ccf_22(double s1_[800][7000],int iz,int jz,double nfqso,int iavg,int &ipk,int &jpk,
|
|
double &f0,double &xdt)//,double *ccf2
|
|
{
|
|
double xdt2[7000];
|
|
double ccf3[7000];
|
|
double s1avg[7000];
|
|
int indx[7000];
|
|
//double ddrift[7000];
|
|
|
|
double mdec_df = 50;
|
|
double snfa = nfqso-mdec_df;
|
|
double snfb = nfqso+mdec_df;
|
|
if (f_single_decode)
|
|
{
|
|
snfa = nfa;
|
|
snfb = nfb;
|
|
}
|
|
//int sif1 = snfa/df;//<- in dots
|
|
//int sif2 = snfb/df;//<- in dots
|
|
max_drift = 0;
|
|
if (f_max_drift ) max_drift = 100.0/df;
|
|
if (max_drift>60) max_drift = 60;
|
|
//qDebug()<<"Max_Drift="<<max_drift<<"In Hz="<<df*(double)max_drift;
|
|
|
|
if (iavg!=0) max_drift = 0; //if(nqd!=1 || iavg!=0) max_drift=0;
|
|
|
|
int ia=(int)(fmax(nfa,100.0)/df);//ia=max(nint(100/df),nint((nfqso-ntol)/df))
|
|
int ib=(int)(fmin(nfb,4900.0)/df);//ib=min(nint(4900/df),nint((nfqso+ntol)/df))
|
|
|
|
for (int i = ia; i < ib; ++i)
|
|
{
|
|
double sum = 0.0;
|
|
for (int j = 0; j < jz; ++j)
|
|
{
|
|
sum += s1_[j][i];
|
|
}
|
|
s1avg[i]=sum;
|
|
}
|
|
|
|
double ccfbest=0.0;
|
|
int ibest=0;
|
|
int lagbest=0;
|
|
int idrift_best=0;
|
|
for (int i = ia; i < ib; ++i)
|
|
{
|
|
double ccfmax_s=0.0;
|
|
double ccfmax_m=0.0;
|
|
int lagpk_s=0;
|
|
int lagpk_m=0;
|
|
int idrift_max_s=0;
|
|
for (int lag = lag1; lag <= lag2; ++lag)
|
|
{
|
|
for (int idrift = -max_drift; idrift <= max_drift; ++idrift)
|
|
{
|
|
double ccft=0.0;
|
|
for (int kk = 0; kk < 22; ++kk)
|
|
{
|
|
int k=isync[kk]-1; //k=isync(kk)
|
|
double zz = (idrift*(k-43));
|
|
int ii = i + (int)(zz/85.0); //ii=i + nint(idrift*(k-43)/85.0)
|
|
if (ii<0 || ii>=iz) continue; //if(ii.lt.1 .or. ii.gt.iz) cycle
|
|
int n=NSTEP*k; //n=NSTEP*(k-1) + 1
|
|
int j=n+lag+j0; //j=n+lag+j0
|
|
if (j>-1 && j<jz) ccft += s1_[j][ii]; //if(j.ge.1 .and. j.le.jz) ccft=ccft + s1(ii,j)
|
|
}
|
|
ccft -= ((22.0/(double)jz)*s1avg[i]); //ccft=ccft - (22.0/jz)*s1avg(i)
|
|
if (ccft>ccfmax_s)
|
|
{
|
|
ccfmax_s=ccft;
|
|
lagpk_s=lag;
|
|
idrift_max_s=idrift;
|
|
}
|
|
//2.57 hv for multi dec no drift
|
|
if (ccft>ccfmax_m && idrift == 0)
|
|
{
|
|
ccfmax_m=ccft;
|
|
lagpk_m=lag;
|
|
}
|
|
}
|
|
}
|
|
|
|
ccf3[i]=ccfmax_m; //ccf2[i]=ccfmax;
|
|
xdt2[i]=(double)lagpk_m*dtstep; //xdt2(i)=lagpk*dtstep (i*df>=nfa && i*df<=nfb) fabs(i*df-nfqso)<=ftol_single
|
|
//ddrift[i]=df*(double)idrift_max_s;
|
|
|
|
double f=(double)i*df; //if (f>=snfa && f<=snfb) qDebug()<<f;
|
|
//if (f>=1200 && f<=1550) qDebug()<<"="<<(int)f<<ccfmax_s<<ccfbest<<idrift_max_s<<lagpk_s;
|
|
if (ccfmax_s>ccfbest && (f>=snfa && f<=snfb)) //if(ccfmax.gt.ccfbest .and. abs(i*df-nfqso)<=ftol) then
|
|
{
|
|
ccfbest=ccfmax_s;
|
|
ibest=i;
|
|
lagbest=lagpk_s;
|
|
idrift_best=idrift_max_s;
|
|
}
|
|
}
|
|
|
|
int corrp = pomAll.maxloc_da_beg_to_end(ccf3,snfa/df,snfb/df);
|
|
f0nd = f0=nfqso+(double)(corrp-i0)*df;
|
|
xdtnd = xdt2[corrp];
|
|
|
|
//! Parameters for the top candidate:
|
|
ipk=ibest-i0;
|
|
jpk=lagbest;
|
|
f0=nfqso+(double)ipk*df; //ibest*df;// precision error -> nfqso+ipk*df;
|
|
xdt=(double)jpk*dtstep; //qDebug()<<"SINGLE="<<xdt<<f0<<ibest;
|
|
drift=df*(double)idrift_best;
|
|
//qDebug()<<"MaxD="<<(double)max_drift*df<<"MinD="<<1.0*df<<" f0="<<f0<<"Drift Hz="<<drift;
|
|
|
|
for (int i = 0; i < ia; ++i) ccf3[i]=0.0;
|
|
for (int i = ib; i < iz; ++i) ccf3[i]=0.0;
|
|
|
|
//! Save parameters for best candidates
|
|
int jzz=ib-ia; //750,15
|
|
if (jzz<25) jzz = 25; // as mimimum
|
|
|
|
//int ccf1a = 200.0/df;
|
|
//int ccf1b = 3500.0/df; //2600.0
|
|
//int jzz1 = ccf1b - ccf1a;
|
|
|
|
double t_s[7000];
|
|
for (int z = 0; z < jzz; ++z) t_s[z] = ccf3[z+ia];
|
|
double base = pomAll.pctile_shell(t_s,jzz,40);//pctile(ccf2(i1:i2),jzz,40,base)
|
|
//for (int z = 0; z < jzz1; ++z) t_s[z] = ccf2[z+ccf1a];
|
|
//double base1 = pomAll.pctile_shell(t_s,jzz1,40);
|
|
if (base ==0.0) base =0.000001;
|
|
//if (base1==0.0) base1=0.000001;
|
|
for (int z = 0; z < 6800; ++z)
|
|
{
|
|
ccf3[z]/=base;
|
|
//ccf2[z]/=base1;
|
|
//ccf2[z]=ccf3[z];
|
|
}
|
|
double limit = 0.0;
|
|
for (int z = 0; z < jzz; ++z)
|
|
{
|
|
t_s[z] = ccf3[z+ia];
|
|
indx[z] = 0;
|
|
limit += t_s[z];
|
|
}
|
|
limit /= (double)jzz/2.5;// test 3 ok-> / 2.4
|
|
pomAll.indexx_msk(t_s,jzz-1,indx);
|
|
|
|
//qDebug()<<"bASE=================="<<base<<"JZZ="<<jzz<<limit;
|
|
ncand=0;
|
|
int maxcand=20;
|
|
for (int j = 0; j < maxcand; ++j)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do j=1,20
|
|
int k=jzz-j-1; //k=jzz-j+1
|
|
if (k<0 || k>=iz) continue;//if(k.lt.1 .or. k.gt.iz) cycle
|
|
int i=indx[k]+ia; //i=indx(jzz-j+1)+i1-1 //tested -1 ->1.69 n=ia + indx(iz+1-i) - 1
|
|
//qDebug()<<"ccf2="<<i<<(int)(i*df)<<"CCCCFFF="<<ccf3[i]<<xdt2[i];
|
|
if (ccf3[i]<limit) break;//if(ccf2(i).lt.3.3) exit// !Candidate limit
|
|
double f=(double)i*df; //qDebug()<<"ccf2="<<ccf2[i]<<nfqso<<ftol;
|
|
//double f=(double)nfqso+(i-i0)*df; //nfqso+ipk*df
|
|
//if(f>=(nfqso-ftol) .and. f<=(nfqso+ftol)) cycle
|
|
|
|
if (f>=snfa && f<=snfb) continue;//6.666 Hz error stopped in w260rc1
|
|
|
|
int i3=fmax(0, i-mode_q65);//2.55 i3=max(1, i-mode_q65) old int i3=fmax(0,i-67*mode_q65); //max(1,i-67*mode_q65)
|
|
int i4=fmin(iz,i+mode_q65);//2.55 i4=min(iz,i+mode_q65) old int i4=fmin(iz,i+3*mode_q65); //min(iz,i+3*mode_q65)
|
|
double biggest=pomAll.maxval_da_beg_to_end(ccf3,i3,i4); //biggest=maxval(ccf2(i3:i4))
|
|
if (ccf3[i]!=biggest) continue; //if(ccf2(i).ne.biggest) cycle
|
|
//candidates_[0][ncand]=ccf3[i];
|
|
//qDebug()<<"candidats="<<f<<ccf3[i];
|
|
//qDebug()<<"candidats="<<(int)(i*df)<<xdt2[i]<<ddrift[i]<<ccf3[i]<<limit;
|
|
candidates_[0][ncand]=xdt2[i];
|
|
candidates_[1][ncand]=f;
|
|
ncand++;
|
|
if (ncand>maxcand-1) break; // no needed
|
|
}
|
|
/*for (int i = 0; i < ncand; ++i)
|
|
{
|
|
qDebug()<<"candidats="<<candidates_[0][i]<<candidates_[1][i];
|
|
}*/
|
|
}
|
|
/*void DecoderQ65::q65_sync_curve(double *ccf1,int ia,int ib,double &rms1)
|
|
{
|
|
//! Condition the red or orange sync curve for plotting.
|
|
//real ccf1(ia:ib)
|
|
int ic=(ib-ia)/8;
|
|
int nsum=2*(ic); //2*(ic+1);
|
|
|
|
double sum1 = 0.0;
|
|
double sum2 = 0.0;
|
|
for (int i = 0; i < ic; ++i)
|
|
{
|
|
sum1+=ccf1[i+ia];
|
|
sum2+=ccf1[(ib-ic)+i];
|
|
}
|
|
|
|
double base1 = (sum1+sum2)/(double)nsum; //base1=(sum(ccf1(ia:ia+ic)) + sum(ccf1(ib-ic:ib)))/nsum
|
|
for (int i = ia; i < ib; ++i) ccf1[i]-=base1; //ccf1=ccf1-base1
|
|
|
|
double dp1= 0.0; //If the vectors are INTEGER or REAL -> DOT_PRODUCT(VECTOR_A, VECTOR_B) = SUM(VECTOR_A*VECTOR_B)
|
|
double dp2= 0.0;
|
|
for (int i = 0; i < ic; ++i)//sq=dot_product(ccf1(ia:ia+ic),ccf1(ia:ia+ic)) + dot_product(ccf1(ib-ic:ib),ccf1(ib-ic:ib))
|
|
{
|
|
dp1 += ccf1[i+ia] * ccf1[i+ia];
|
|
dp2 += ccf1[(ib-ic)+i] * ccf1[(ib-ic)+i];
|
|
}
|
|
double sq = dp1+dp2; //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
//qDebug()<<"q65_sync_curve"<<sq<<sqrt(sq);
|
|
rms1=0.0;
|
|
if (nsum>0) rms1=sqrt(sq/(double)nsum);
|
|
if (rms1>0.0)
|
|
{
|
|
for (int i = ia; i < ib; ++i) ccf1[i]=ccf1[i]/rms1; //if(rms1.gt.0.0) ccf1=ccf1/rms1 old ccf1=2.0*ccf1/rms1
|
|
}
|
|
//double smax1 = pomAll.maxval_da_beg_to_end(ccf1,ia,ib);//smax1=maxval(ccf1)
|
|
//if (smax1>10.0)
|
|
//{
|
|
//for (int i = ia; i < ib; ++i) ccf1[i]=10.0*ccf1[i]/smax1; //ccf1=10.0*ccf1/smax1
|
|
//}
|
|
}*/
|
|
/*
|
|
subroutine q65_write_red(iz,xdt,ccf2_avg,ccf2)
|
|
|
|
! Write data for the red and orange sync curves to LU 17.
|
|
|
|
real ccf2_avg(iz)
|
|
real ccf2(iz)
|
|
|
|
call q65_sync_curve(ccf2_avg,1,iz,rms1)
|
|
call q65_sync_curve(ccf2,1,iz,rms2)
|
|
|
|
rewind 17
|
|
write(17,1000) xdt,minval(ccf2_avg),maxval(ccf2_avg)
|
|
do i=max(1,nint(nfa/df)),min(iz,int(nfb/df))
|
|
freq=i*df
|
|
y1=ccf2_avg(i)
|
|
if(y1.gt.10.0) y1=10.0 + 2.0*log10(y1/10.0)
|
|
y2=ccf2(i)
|
|
if(y2.gt.10.0) y2=10.0 + 2.0*log10(y2/10.0)
|
|
write(17,1000) freq,y1,y2
|
|
1000 format(3f10.3)
|
|
enddo
|
|
flush(17)
|
|
|
|
return
|
|
end subroutine q65_write_red
|
|
*/
|
|
#include "ft_all_ap_def.h"
|
|
static const int naptypes_q65[6][4]=
|
|
{//gjhghghj
|
|
{1,2,0,0},{2,3,0,0},{2,3,0,0},{3,4,5,6},{3,4,5,6},{3,1,2,0}
|
|
};
|
|
void DecoderQ65::q65_ap(int nQSOprogresst,int ipass,int cont_id,int cont_type,bool lapcqonly,
|
|
int &iaptypet,int *apsym0t,bool *apmaskt,bool *apsymbolst)
|
|
{
|
|
/*! nQSOprogress
|
|
! 0 CALLING
|
|
! 1 REPLYING
|
|
! 2 REPORT
|
|
! 3 ROGER_REPORT
|
|
! 4 ROGERS
|
|
! 5 SIGNOFF*/
|
|
if (cont_id!=ncontest0)
|
|
{
|
|
/*! iaptype
|
|
!------------------------
|
|
! 1 CQ ??? ??? (29+4=33 ap bits)
|
|
! 2 MyCall ??? ??? (29+4=33 ap bits)
|
|
! 3 MyCall DxCall ??? (58+4=62 ap bits)
|
|
! 4 MyCall DxCall RRR (78 ap bits)
|
|
! 5 MyCall DxCall 73 (78 ap bits)
|
|
! 6 MyCall DxCall RR73 (78 ap bits)*/
|
|
for (int i = 0; i < 29; ++i)
|
|
{
|
|
/*if (cont_id== 0) mcq_q65[i]=mcq_ft[i];
|
|
else if (cont_id== 2) mcq_q65[i]=mcqtest_ft[i];
|
|
else if (cont_id== 3) mcq_q65[i]=mcqtest_ft[i];
|
|
else if (cont_id== 4) mcq_q65[i]=mcqfd_ft[i];
|
|
else if (cont_id== 5) mcq_q65[i]=mcqtest_ft[i];//mcq_q65[i]=mcqru_ft[i];
|
|
else if (cont_id== 6) mcq_q65[i]=mcqww_ft[i];
|
|
else if (cont_id== 7) mcq_q65[i]=mcqww_ft[i]; //mcq_q65[i]=mcqru_ft[i];
|
|
else if (cont_id== 8) mcq_q65[i]=mcqww_ft[i]; //mcq_q65[i]=mcqru_ft[i];
|
|
else if (cont_id== 9) mcq_q65[i]=mcqru_ft[i];
|
|
else if (cont_id==10) mcq_q65[i]=mcqbu_ft[i];
|
|
else if (cont_id==11) mcq_q65[i]=mcqft_ft[i];
|
|
else if (cont_id==12) mcq_q65[i]=mcqpdc_ft[i];
|
|
else if (cont_id==13) mcq_q65[i]=mcqtest_ft[i];*/
|
|
mcq_q65[i]=mcq_ft[cont_id][i];
|
|
}
|
|
ncontest0=cont_id;
|
|
}
|
|
|
|
for (int i = 0; i < 78; ++i) apsymbolst[i]=0;
|
|
iaptypet=naptypes_q65[nQSOprogresst][ipass-1]; //hv-1 iaptype=naptypes(nQSOProgress,ipass)
|
|
//qDebug()<<"iaptypet="<<iaptypet;
|
|
if (lapcqonly) iaptypet=1;
|
|
/*! ncontest=0 : NONE
|
|
! 1 : NA_VHF
|
|
! 2 : EU_VHF
|
|
! 3 : FIELD DAY
|
|
! 4 : RTTY
|
|
! 5 : WW_DIGI
|
|
! 6 : FOX
|
|
! 7 : HOUND*/
|
|
|
|
// Activity Type id type dec-id dec-type dec-cq
|
|
//"Standard" 0 0 0 = CQ 0 0
|
|
//"EU RSQ And Serial Number" 1 NONE 1 NONE NONE NONE
|
|
//"NA VHF Contest" 2 2 2 CQ TEST 1 3 = CQ TEST
|
|
//"EU VHF Contest" 3 3 3 CQ TEST 2 3 = CQ TEST
|
|
//"ARRL Field Day" 4 4 4 CQ FD 3 2 = CQ FD
|
|
//"ARRL Inter. Digital Contest" 5 2 5 CQ TEST 1 3 = CQ TEST
|
|
//"WW Digi DX Contest" 6 2 6 CQ WW 1 4 = CQ WW
|
|
//"FT4 DX Contest" 7 2 7 CQ WW 1 4 = CQ WW
|
|
//"FT8 DX Contest" 8 2 8 CQ WW 1 4 = CQ WW
|
|
//"FT Roundup Contest" 9 5 9 CQ RU 4 1 = CQ RU
|
|
//"Bucuresti Digital Contest" 10 5 10 CQ BU 4 5 = CQ BU
|
|
//"FT4 SPRINT Fast Training" 11 5 11 CQ FT 4 6 = CQ FT
|
|
//"PRO DIGI Contest" 12 5 12 CQ PDC 4 7 = CQ PDC
|
|
//"CQ WW VHF Contest" 13 2 13 CQ TEST 1 3 = CQ TEST
|
|
|
|
/*! Conditions that cause us to bail out of AP decoding
|
|
! if(ncontest.le.5 .and. iaptype.ge.3 .and. (abs(f1-nfqso).gt.napwid .and. abs(f1-nftx).gt.napwid) ) goto 900
|
|
! if(ncontest.eq.6) goto 900 !No AP for Foxes
|
|
! if(ncontest.eq.7.and.f1.gt.950.0) goto 900 !Hounds use AP only below 950 Hz*/
|
|
//if(ncontest.ge.6) goto 900
|
|
if (iaptypet>=2 && apsym0t[0]>1) return;//if(iaptype.ge.2 .and. apsym0(1).gt.1) goto 900 !No, or nonstandard, mycall
|
|
//if(ncontest.eq.7 .and. iaptype.ge.2 .and. aph10(1).gt.1) goto 900
|
|
if (iaptypet>=3 && apsym0t[29]>1) return;//if(iaptype.ge.3 .and. apsym0(30).gt.1) goto 900 !No, or nonstandard, dxcall
|
|
|
|
if (iaptypet==1) //! CQ or CQ RU or CQ TEST or CQ FD
|
|
{
|
|
for (int z = 0; z < 78; ++z)
|
|
{
|
|
apmaskt[z]=0;
|
|
if (z<29)
|
|
{
|
|
apmaskt[z]=1;
|
|
apsymbolst[z]=mcq_q65[z];
|
|
}
|
|
}
|
|
apmaskt[74]=1;
|
|
apmaskt[75]=1;
|
|
apmaskt[76]=1;
|
|
apmaskt[77]=1;
|
|
apsymbolst[74]=0;
|
|
apsymbolst[75]=0;
|
|
apsymbolst[76]=1;
|
|
apsymbolst[77]=0;
|
|
}
|
|
if (iaptypet==2) //then //! MyCall,???,???
|
|
{
|
|
for (int z = 0; z < 78; ++z)
|
|
apmaskt[z]=0;
|
|
if (cont_type==0 || cont_type==1)//hv new || cont_type==5
|
|
{
|
|
for (int z = 0; z < 29; ++z)
|
|
{
|
|
apmaskt[z]=1;
|
|
apsymbolst[z]=apsym0t[z];
|
|
}
|
|
apmaskt[74]=1;
|
|
apmaskt[75]=1;
|
|
apmaskt[76]=1;
|
|
apmaskt[77]=1;
|
|
apsymbolst[74]=0;
|
|
apsymbolst[75]=0;
|
|
apsymbolst[76]=1;
|
|
apsymbolst[77]=0;
|
|
}
|
|
else if (cont_type==2) //then
|
|
{
|
|
for (int z = 0; z < 28; ++z)
|
|
{
|
|
apmaskt[z]=1;
|
|
apsymbolst[z]=apsym0t[z];
|
|
}
|
|
apmaskt[71]=1;
|
|
apmaskt[72]=1;
|
|
apmaskt[73]=1;
|
|
apsymbolst[71]=0;
|
|
apsymbolst[72]=1;//+1=??
|
|
apsymbolst[73]=0;
|
|
apmaskt[74]=1;
|
|
apmaskt[75]=1;
|
|
apmaskt[76]=1;
|
|
apmaskt[77]=1;
|
|
apsymbolst[74]=0;
|
|
apsymbolst[75]=0;
|
|
apsymbolst[76]=0;
|
|
apsymbolst[77]=0;
|
|
}
|
|
else if (cont_type==3)
|
|
{
|
|
for (int z = 0; z < 28; ++z)
|
|
{
|
|
apmaskt[z]=1;
|
|
apsymbolst[z]=apsym0t[z];
|
|
}
|
|
apmaskt[74]=1;
|
|
apmaskt[75]=1;
|
|
apmaskt[76]=1;
|
|
apmaskt[77]=1;
|
|
apsymbolst[74]=0;
|
|
apsymbolst[75]=0;
|
|
apsymbolst[76]=0;
|
|
apsymbolst[77]=0;
|
|
}
|
|
else if (cont_type==4)// || ncontest==6 RTTY RU HV new
|
|
{
|
|
for (int z = 1; z < 29; ++z)
|
|
{
|
|
apmaskt[z]=1;
|
|
apsymbolst[z]=apsym0t[z];
|
|
}
|
|
apmaskt[74]=1;
|
|
apmaskt[75]=1;
|
|
apmaskt[76]=1;
|
|
apmaskt[77]=1;
|
|
apsymbolst[74]=0;
|
|
apsymbolst[75]=0;
|
|
apsymbolst[76]=1;
|
|
apsymbolst[77]=0;
|
|
}
|
|
/*else if(ncontest.eq.7) then ! ??? RR73; MyCall <Fox Call hash10> ???
|
|
apmask(29:56)=1
|
|
apsymbols(29:56)=apsym0(1:28)
|
|
apmask(57:66)=1
|
|
apsymbols(57:66)=aph10(1:10)
|
|
apmask(72:78)=1
|
|
apsymbols(72:74)=(/0,0,1/)
|
|
apsymbols(75:78)=0
|
|
endif*/
|
|
}
|
|
if (iaptypet==3) // ! MyCall,DxCall,???
|
|
{
|
|
for (int z = 0; z < 78; ++z)
|
|
apmaskt[z]=0;//apmask=0
|
|
//if(ncontest.eq.0.or.ncontest.eq.1.or.ncontest.eq.2.or.ncontest.eq.5.or.ncontest.eq.7) then
|
|
if (cont_type==0 || cont_type==1 || cont_type==2)//||ncontest==7 || ncontest==5
|
|
{
|
|
for (int z = 0; z < 58; ++z)
|
|
{
|
|
apmaskt[z]=1;
|
|
apsymbolst[z]=apsym0t[z];
|
|
}
|
|
apmaskt[74]=1;
|
|
apmaskt[75]=1;
|
|
apmaskt[76]=1;
|
|
apmaskt[77]=1;
|
|
apsymbolst[74]=0;
|
|
apsymbolst[75]=0;
|
|
apsymbolst[76]=1;
|
|
apsymbolst[77]=0;
|
|
}
|
|
else if (cont_type==3) //then ! Field Day
|
|
{
|
|
for (int z = 0; z < 57; ++z)
|
|
{
|
|
if (z<56)
|
|
apmaskt[z]=1;
|
|
if (z<28)
|
|
apsymbolst[z]=apsym0t[z];
|
|
if (z>28)
|
|
apsymbolst[z-1]=apsym0t[z];
|
|
}
|
|
apmaskt[71]=1;
|
|
apmaskt[72]=1;
|
|
apmaskt[73]=1;
|
|
apmaskt[74]=1;
|
|
apmaskt[75]=1;
|
|
apmaskt[76]=1;
|
|
apmaskt[77]=1;
|
|
apsymbolst[74]=0;
|
|
apsymbolst[75]=0;
|
|
apsymbolst[76]=0;
|
|
apsymbolst[77]=0;
|
|
}
|
|
else if (cont_type==4)//RTTY RU HV new || ncontest==6
|
|
{
|
|
for (int z = 0; z < 57; ++z)
|
|
{
|
|
if (z>0)
|
|
apmaskt[z]=1;
|
|
if (z<28)
|
|
apsymbolst[z+1]=apsym0t[z];
|
|
if (z>28)
|
|
apsymbolst[z]=apsym0t[z];
|
|
}
|
|
apmaskt[74]=1;
|
|
apmaskt[75]=1;
|
|
apmaskt[76]=1;
|
|
apmaskt[77]=1;
|
|
apsymbolst[74]=0;
|
|
apsymbolst[75]=0;
|
|
apsymbolst[76]=1;
|
|
apsymbolst[77]=0;
|
|
}
|
|
}
|
|
//if(iaptype==5 && ncontest==7) continue;//cycle !Hound
|
|
if (iaptypet==4 || iaptypet==5 || iaptypet==6)
|
|
{
|
|
for (int z = 0; z < 78; ++z)
|
|
apmaskt[z]=0;//apmask=0
|
|
//if(ncontest.le.5 || (ncontest.eq.7.and.iaptype.eq.6)) then
|
|
if (cont_type<=4)//HV new=4
|
|
{
|
|
for (int z = 0; z < 78; ++z)
|
|
{
|
|
apmaskt[z]=1;//apmask(1:77)=1 //! mycall, theircall, RRR|73|RR73
|
|
if (z<58)
|
|
apsymbolst[z]=apsym0t[z];
|
|
}
|
|
//apmask(72:74)=0
|
|
apmaskt[71]=0;
|
|
apmaskt[72]=0;
|
|
apmaskt[73]=0;
|
|
for (int z = 0; z < 19; ++z)
|
|
{
|
|
if (iaptypet==4)
|
|
apsymbolst[z+58]=mrrr_ft[z];//apsymbols(59:77)=mrrr
|
|
if (iaptypet==5)
|
|
apsymbolst[z+58]=m73_ft[z];//apsymbols(59:77)=m73
|
|
if (iaptypet==6)
|
|
apsymbolst[z+58]=mrr73_ft[z];//apsymbols(59:77)=mrr73
|
|
}
|
|
}
|
|
//HOUND = MSHV no
|
|
/*else if(ncontest.eq.7.and.iaptype.eq.4) then ! Hound listens for MyCall RR73;...
|
|
apmask(1:28)=1
|
|
apsymbols(1:28)=apsym0(1:28)
|
|
apmask(57:66)=1
|
|
apsymbols(57:66)=aph10(1:10)
|
|
apmask(72:78)=1
|
|
apsymbols(72:78)=(/0,0,1,0,0,0,0/)
|
|
endif*/
|
|
}
|
|
}
|
|
int DecoderQ65::BinToInt32(bool*a,int b_a,int bits_sz)
|
|
{
|
|
int k = 0;
|
|
for (int i = b_a; i < bits_sz; ++i)
|
|
{
|
|
k <<= 1;
|
|
k |= a[i];
|
|
}
|
|
return k;
|
|
}
|
|
void DecoderQ65::q65_dec2(float *s3_1fa,int nsubmode,float b90ts,float &esnodb,int &irc,int *dat4)
|
|
{
|
|
//! Attempt a q0, q1, or q2 decode using spcified AP information.
|
|
bool c77[100];
|
|
float s3prob[4132] = {0.0};//row= 63 col= 64=4032
|
|
bool unpk77_success = false;
|
|
|
|
int nFadingModel=1;
|
|
decoded="";
|
|
q65S.q65_intrinsics_ff(s3_1fa,nsubmode,b90ts,nFadingModel,s3prob);
|
|
q65S.q65_dec(s3_1fa,s3prob,apmask,apsymbols,s_maxiters,esnodb,dat4,irc);
|
|
|
|
int sumd4 = 0;
|
|
for (int i = 0; i < 13; ++i) sumd4+=dat4[i]; //if (sumd4!=0) qDebug()<<sumd4;//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
if (sumd4<=0) irc=-2;
|
|
if (irc>=0)
|
|
{
|
|
int co_t = 0;
|
|
for (int i = 0; i < 13; ++i)
|
|
{
|
|
int bits = 6;
|
|
int in = dat4[i];
|
|
if (i==12)
|
|
{
|
|
in/=2;
|
|
bits = 5;
|
|
}
|
|
SetArrayBits(in,bits,c77,co_t);
|
|
}
|
|
decoded = TGenQ65->unpack77(c77,unpk77_success);
|
|
//qDebug()<<"==="<<sumd4<<irc<<plog<<"d="<<decoded<<unpk77_success;
|
|
}
|
|
}
|
|
void DecoderQ65::q65_dec_q012(float *s3_1fa,double &snr2,int *dat4,int &idec, int nQSOprogress,
|
|
int cont_id,int cont_type)
|
|
{
|
|
//! Do separate passes attempting q0, q1, q2 decodes.
|
|
int irc=-2;
|
|
int nsubmode=0;
|
|
if (mode_q65==2) nsubmode=1;
|
|
else if (mode_q65==4) nsubmode=2;
|
|
else if (mode_q65==8) nsubmode=3;
|
|
//if(mode_q65.eq.16) nsubmode=4
|
|
//if(mode_q65.eq.32) nsubmode=5
|
|
|
|
double baud=12000.0/(double)nsps;
|
|
|
|
bool lapcqonly=false;
|
|
int iaptype = 0;
|
|
bool exitt = false;
|
|
for (int ipass = 0; ipass <= npasses ; ++ipass)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do ipass=0,npasses //!Loop over AP passes
|
|
for (int i = 0; i < 13 ; ++i)
|
|
{
|
|
apmask[i]=0; //13 //!Try first with no AP information
|
|
apsymbols[i]=0; //13
|
|
}
|
|
if (ipass>=1)//if(ipass.ge.1) then
|
|
{
|
|
//! Subsequent passes use AP information appropiate for nQSOprogress
|
|
q65_ap(nQSOprogress,ipass,cont_id,cont_type,lapcqonly,iaptype,apsym0,apmask1,apsymbols1);
|
|
/*write(c78,1050) apmask1
|
|
1050 format(78i1)
|
|
read(c78,1060) apmask
|
|
1060 format(13b6.6)
|
|
write(c78,1050) apsymbols1
|
|
read(c78,1060) apsymbols */
|
|
int z = 0;
|
|
for (int i = 0; i < 13; ++i)
|
|
{
|
|
apmask[i] = BinToInt32(apmask1,z,z+6);
|
|
apsymbols[i] = BinToInt32(apsymbols1,z,z+6);
|
|
z += 6;
|
|
}
|
|
}
|
|
for (int ibw = ibwa; ibw <= ibwb; ++ibw)
|
|
{//do ibw=ibwa,ibwb
|
|
double b90=pow(1.72,ibw);//b90=1.72**ibw
|
|
float b90ts=b90/baud;//b90ts=b90/baud
|
|
irc=-2;
|
|
float esnodb=0.0;
|
|
q65_dec2(s3_1fa,nsubmode,b90ts,esnodb,irc,dat4);
|
|
if (irc>=0)//if(irc.ge.0) then //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{
|
|
snr2=esnodb - pomAll.db(2500.0/baud) + 3.0;//snr2=esnodb - db(2500.0/baud) + 3.0 !Empirical adjustment
|
|
idec=iaptype;
|
|
exitt = true;
|
|
break;
|
|
}
|
|
}
|
|
if (exitt) break;
|
|
}
|
|
}
|
|
void DecoderQ65::q65_dec0(int iavg,double *iwave,double nfqso,
|
|
bool &lclearave,bool emedelay,double &xdt,double &f0,double &snr1,
|
|
int *dat4,double &snr2,int &idec,int nQSOp,int cont_id,int cont_type,int stageno)
|
|
{
|
|
/* Top-level routine in q65 module
|
|
! - Compute symbol spectra
|
|
! - Attempt sync and q3 decode using all 85 symbols
|
|
! - If that fails, try sync with 22 symbols and standard q[0124] decode
|
|
|
|
! Input: iavg 0 for single-period decode, 1 for average
|
|
! iwave(0:nmax-1) Raw data
|
|
! ntrperiod T/R sequence length (s)
|
|
! nfqso Target frequency (Hz)
|
|
! ntol Search range around nfqso (Hz)
|
|
! ndepth Requested decoding depth
|
|
! lclearave Flag to clear the accumulating array
|
|
! emedelay Extra delay for EME signals
|
|
! Output: xdt Time offset from nominal (s)
|
|
! f0 Frequency of sync tone
|
|
! snr1 Relative SNR of sync signal
|
|
! width Estimated Doppler spread
|
|
! dat4(13) Decoded message as 13 six-bit integers
|
|
! snr2 Estimated SNR of decoded signal
|
|
! idec Flag for decing results
|
|
! -1 No decode
|
|
! 0 No AP
|
|
! 1 "CQ ? ?"
|
|
! 2 "Mycall ? ?"
|
|
! 3 "MyCall TheirCall ?"*/
|
|
|
|
idec = -1;//2.57 inportent
|
|
int LL=64*(2+mode_q65); //LL=640 mode for q65D
|
|
int nfft=nsps;
|
|
df=12000.0/(double)nfft; //!Freq resolution = baud
|
|
istep=nsps/NSTEP;
|
|
int iz=(int)(5000.0/df); //!Uppermost frequency bin, at 5000 Hz
|
|
double txt=85.0*(double)nsps/12000.0;
|
|
int jz=(int)((txt+1.0)*12000.0/(double)istep); //!Number of symbol/NSTEP bins
|
|
if (nsps>=6912) jz=(int)((txt+2.0)*12000.0/(double)istep); //!For TR 60 s and higher
|
|
|
|
int ia=(int)(nfa/df);//ORG->int ia=(int)(ftol/df); ia=ntol/df
|
|
int ia2=(int)(nfb/df);
|
|
double xxmax = fmax(10*mode_q65,(int)(100.0/df)); //ORG->ia2=max(ia,10*mode_q65,nint(100.0/df))
|
|
ia2=fmax(ia,xxmax); //ORG->int ia2=fmax(ia,xxmax);
|
|
|
|
nsmo=int(0.7*(double)(mode_q65*mode_q65));
|
|
if (nsmo<1) nsmo=1;
|
|
//double s1_[800][7000];//max iz=120s=6666 jz=733 300s=17280 allocate(s1(iz,jz))
|
|
double (*s1_)[7000] = new double[800][7000];
|
|
//double s3_[70][750];//s3(-64:LL-65,63)) LL=640 mode for q65D
|
|
float s3_1fa[41320];//63*640=40320
|
|
//float *s3_1fa = new float[41320];//attention = 63*640=40320 q65d from q65_subs
|
|
//qDebug()<<ia2<<ia2*2<<jz;
|
|
|
|
/*int w3t;
|
|
int w3f;
|
|
int mm;*/
|
|
double (*s1w_)[7000] = new double[800][7000];
|
|
//integer stageno
|
|
|
|
//int s3_offset = 84;// = 63+20=83 all 83+LL=83+640=723
|
|
//double ccf1[14000]; //no used hv allocate(ccf1(-ia2:ia2)) 5000Hz= 6333*2
|
|
//int ccf1_offset = 7000;
|
|
//double ccf2[7000];//allocate(ccf2(iz)) iz = 6666
|
|
double base;
|
|
double t_s[700];//?? max=640 s1_[][7000] last column
|
|
double s1max = 0.0;
|
|
int ipk = 0;
|
|
int jpk = 0;
|
|
//int imsg_best = 0;// not used
|
|
double f0a = 0.0;
|
|
double xdta = 0.0;
|
|
//double rms2 = 0.0;
|
|
double smax = 0.0;
|
|
//int ibeg = nfa/df;
|
|
//int iend = 3000.0/df;
|
|
snr1=0.0;
|
|
|
|
//s1a(iz,jz,0:1) = iz =6666 jz=733
|
|
//qDebug()<<ia<<ia2<<iz<<jz;
|
|
static bool first = true;
|
|
if (first) //!Generate the sync vector
|
|
{
|
|
for (int i = 0; i<85; ++i) sync[i]=-22.0/63.0;//!Sync tone OFF //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
for (int k = 0; k<22; ++k) sync[isync[k]-1]=1.0;//do k=1,22 !Sync tone ON
|
|
first = false;
|
|
}
|
|
|
|
//if(LL.ne.LL0 .or. iz.ne.iz0 .or. jz.ne.jz0 .or. lclearave) then
|
|
if (LL!=LL0 || iz!=iz0 || jz!=jz0 || lclearave)
|
|
{
|
|
for (int i = 0; i < 2 ; ++i)//if(allocated(s1a)) deallocate(s1a) //allocate(s1a(iz,jz,0:1))
|
|
{
|
|
for (int j = 0; j < jz ; ++j)
|
|
{
|
|
for (int z = 0; z < iz ; ++z) s1a_[i][j][z]=0.0;//s1a=0.
|
|
}
|
|
}
|
|
navg[0]=0;
|
|
navg[1]=0;
|
|
LL0=LL;
|
|
iz0=iz;
|
|
jz0=jz;
|
|
lclearave=false;
|
|
}
|
|
|
|
dtstep = (double)nsps/((double)NSTEP*12000.0); //!Step size in seconds //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
lag1 = (int)(-1.0/dtstep);
|
|
lag2 = (int)(1.0/dtstep + 0.9999);
|
|
if (nsps>=3600 && emedelay) lag2 = (int)(5.5/dtstep + 0.9999);//50rc2 !Include EME
|
|
j0=(int)(0.5/dtstep);
|
|
if (nsps>=7200) j0=(int)(1.0/dtstep); //!Nominal start-signal index if(nsps.ge.7200) j0=1.0/dtstep
|
|
|
|
|
|
for (int i = 0; i < 40350 ; ++i) s3_1fa[i]=0.0;//attention = 63*640=40320 q65d from q65_subs
|
|
if (iavg==0) q65_symspec(iwave,iz,jz,s1_);//q65_symspec(iwave,ntrperiod*12000,iz,jz,s1) //! Compute symbol spectra with NSTEP time bins per symbol
|
|
else
|
|
{
|
|
for (int j = 0; j < jz ; ++j)
|
|
{
|
|
for (int z = 0; z < iz ; ++z) s1_[j][z]=s1a_[iseq][j][z];//s1=s1a(:,:,iseq)
|
|
}
|
|
}
|
|
|
|
//qDebug()<<"Bounds Restrict="<<(64*df)<<(5000 - (LL-64)*df);
|
|
//int i01 = 100; qDebug()<<i01-64<<i01-65+LL<<(i01-64+LL)-(i01-64);
|
|
//int iall = (i0-64+LL); //qDebug()<<iall-(i0-64);
|
|
i0=(int)(nfqso/df); //!Target QSO frequency
|
|
/*ii1=fmax(0,i0-64);//ii1=max(1,i0-64)
|
|
ii2=i0-64+LL; //ii2=i0-65+LL
|
|
if (i0-64<0 || i0-64+LL>iz-1) //if(i0-64.lt.1 .or. i0-65+LL.gt.iz) !Frequency out of range
|
|
{
|
|
//qDebug()<<"RESTRICT";
|
|
goto c900;
|
|
}*/
|
|
if (i0-64<0) i0=64;
|
|
if (i0-64+LL>iz-1) i0=iz+64-LL;
|
|
//qDebug()<<i0<<iz<<iz+64-LL<<(LL-1)+(iz+64-LL)-64;
|
|
|
|
for (int j = 0; j < jz ; ++j) //pctile(s1(i0-64:i0-65+LL,1:jz),LL*jz,40,base)
|
|
{
|
|
for (int z = 0; z < LL; ++z)
|
|
{
|
|
t_s[z] = s1_[j][z+i0-64];
|
|
//if (j==0) qDebug()<<LL<<z;
|
|
}
|
|
//call pctile(s1(i0-64:i0-65+LL,1:jz),LL*jz,45,base)
|
|
//call pctile(s1(ii1:ii2,1:jz),ii2-ii1+1*jz,45,base)
|
|
base = pomAll.pctile_shell(t_s,LL,45);
|
|
if (base==0.0) base=0.000001;
|
|
for (int z = 0; z < iz ; ++z)
|
|
{
|
|
s1_[j][z]/=base;//s1=s1/base
|
|
s1raw_[j][z]=s1_[j][z];
|
|
}
|
|
} //qDebug()<<"LL="<<LL;
|
|
|
|
for (int j = 0; j < jz ; ++j)
|
|
{
|
|
//! Apply fast AGC to the symbol spectra
|
|
s1max=20.0;//20.0 !Empirical choice
|
|
//smax = pomAll.maxval_da_beg_to_end(s1_[j],i0-64,iall);//smax=maxval(s1(i0-64:i0-65+LL,j))
|
|
smax = pomAll.maxval_da_beg_to_end(s1_[j],0,iz); //smax=maxval(s1(ii1:ii2,j))
|
|
//qDebug()<<j<<smax;
|
|
//if(smax>s1max) s1(i0-64:i0-65+LL,j)=s1(i0-64:i0-65+LL,j)*s1max/smax
|
|
if (smax>s1max)
|
|
{
|
|
//for (int z = i0-64; z < iall; ++z) s1_[j][z]=s1_[j][z]*s1max/smax;
|
|
//s1(ii1:ii2,j)=s1(ii1:ii2,j)*s1max/smax
|
|
for (int z = 0; z < iz; ++z) s1_[j][z]*=(s1max/smax);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < 14 ; ++i) dat4[i]=0;
|
|
//old if(ncw.gt.0 .and. iavg.lt.2) then
|
|
//i'ts same if(ncw.gt.0 .and. iavg.le.1) then
|
|
//qDebug()<<ncw<<iavg;
|
|
if (ncw>0 && iavg<=1) //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{
|
|
//! Try list decoding via "Deep Likelihood".
|
|
//! Try to synchronize using all 85 symbols
|
|
double better = 0.0;
|
|
q65_ccf_85(s1_,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt/*,imsg_best*/,better/*,ccf1*/);//q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf1)
|
|
if (better>=1.10 || mode_q65>=8) q65_dec_q3(s1_,iz,jz,s3_1fa,LL,ipk,jpk,snr2,dat4,idec,decoded);//2.59
|
|
}
|
|
|
|
/*if(iavg==0) then
|
|
call q65_ccf_22(s1,iz,jz,nfqso,ipk,jpk,f0a,xdta,ccf2)
|
|
endif*/
|
|
|
|
//! Get 2d CCF and ccf2 using sync symbols only
|
|
/*if(iavg>=1) then
|
|
call q65_ccf_22(s1,iz,jz,nfqso,ipk,jpk,f0a,xdta,ccf2_avg)
|
|
endif*/
|
|
|
|
//! Get 2d CCF and ccf2 using sync symbols only
|
|
q65_ccf_22(s1_,iz,jz,nfqso,iavg,ipk,jpk,f0a,xdta/*,ccf2*/);// maybe out of bandwidth df
|
|
if (idec<0) //if(idec.lt.0) then
|
|
{
|
|
f0=f0a;
|
|
xdt=xdta;
|
|
}
|
|
|
|
//hv not used for the moment
|
|
//int ccf1a = 200.0/df;
|
|
//int ccf1b = 2600.0/df;
|
|
//! Estimate rms on ccf2 baseline
|
|
/*rms2 = 0.0; //qDebug()<<200.0/df<<4500.0/df<<20<<iz-20;
|
|
q65_sync_curve(ccf2,200.0/df,4800.0/df,rms2); //call q65_sync_curve(ccf2,1,iz,rms2)
|
|
smax = pomAll.maxval_da_beg_to_end(ccf2,0,iz);//maxval(ccf2);
|
|
snr1=0.0; //qDebug()<<smax<<rms2;
|
|
if (rms2>0.0) snr1=smax/rms2;*/
|
|
|
|
if (idec<=0)//q65_s1_to_s3(s1_,iz,jz,ipk,jpk,LL,s3_1fa);
|
|
{
|
|
//! The q3 decode attempt failed. Copy synchronized symbol energies from s1
|
|
//! into s3 and prepare to try a more general decode.
|
|
q65_s1_to_s3(s1_,iz,jz,ipk,jpk,LL,s3_1fa);
|
|
}
|
|
|
|
/*smax = pomAll.maxval_da_beg_to_end(ccf1,0,13999);//maxval(ccf1)
|
|
//! Estimate frequenct spread
|
|
i1=-9999
|
|
i2=-9999
|
|
do i=-ia,ia
|
|
if(i1.eq.-9999 .and. ccf1(i).ge.0.5*smax) i1=i
|
|
if(i2.eq.-9999 .and. ccf1(-i).ge.0.5*smax) i2=-i
|
|
enddo
|
|
width=df*(i2-i1)
|
|
|
|
if(ncw.eq.0) ccf1=0.
|
|
call q65_write_red(iz,ia2,xdt,ccf1,ccf2)*/
|
|
|
|
//if (iavg==2) q65_dec_q012(s3_1fa,snr2,dat4,idec,nQSOp,cont_id,cont_type);//old 2.56
|
|
//if(iavg.eq.0 .or. iavg.eq.2) then //2.57 start ApS in first start ???
|
|
//if(idec.lt.0 .and. (iavg.eq.0 .or. iavg.eq.2)) 50rc2 //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
if (idec<0 && (iavg==0 || iavg==2)) q65_dec_q012(s3_1fa,snr2,dat4,idec,nQSOp,cont_id,cont_type);
|
|
|
|
//int max_drift=60;
|
|
if (idec<0 && max_drift!=0 && stageno==5) //2.61 if(idec.lt.0 .and. max_drift.eq.50 .and. stageno.eq.5)
|
|
{
|
|
for (int j = 0; j < jz ; ++j)//s1w=s1
|
|
{
|
|
for (int z = 0; z < iz ; ++z) s1w_[j][z] = s1_[j][z];
|
|
}
|
|
for (int w3t = 0; w3t < jz ; ++w3t)
|
|
{//do w3t=1,jz
|
|
for (int w3f = 0; w3f < iz ; ++w3f)
|
|
{//do w3f=1,iz
|
|
int mm = w3f + int((drift*(double)w3t)/((double)jz*df));//mm=w3f + nint(drift*w3t/(jz*df))
|
|
if (mm>=0 && mm<iz) s1w_[w3t][w3f] = s1_[w3t][mm]; //s1w(w3f,w3t)=s1(mm,w3t)
|
|
}
|
|
}
|
|
if (ncw>0 and iavg<=1) //! Try list decoding via "Deep Likelihood".
|
|
{
|
|
double better = 0.0; //! Try to synchronize using all 85 symbols
|
|
q65_ccf_85(s1w_,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt/*,imsg_best*/,better/*,ccf1*/);
|
|
//! nsubmode is Tone-spacing indicator, 0-4 for A-E: a 0; b 1; c 2; d 3; e 4.
|
|
//! and mode_q65=2**nsubmode
|
|
if (better>=1.10)// if(better.ge.1.10)
|
|
{
|
|
//! if(better.ge.1.04 .or. mode_q65.ge.8) then
|
|
//! if(better.ge.1.10 .or. mode_q65.ge.8) then ORIGINAL
|
|
q65_dec_q3(s1w_,iz,jz,s3_1fa,LL,ipk,jpk,snr2,dat4,idec,decoded);
|
|
}
|
|
}
|
|
if (idec==3) idec = 5;
|
|
}
|
|
|
|
delete [] s1w_;
|
|
delete [] s1_;
|
|
//delete [] s3_1fa;
|
|
}
|
|
void DecoderQ65::q65apset(QString mycall12,QString theircall12,int *apsym2)
|
|
{
|
|
int i3=0;
|
|
int n3=0;
|
|
bool c77[77+5];
|
|
for (int i = 0; i < 77; ++i)
|
|
c77[i]=0;
|
|
|
|
if (mycall12.isEmpty())
|
|
{
|
|
for (int i = 0; i < 58; ++i) // apsym2[58+5]
|
|
apsym2[i]=0;
|
|
apsym2[0]=99;
|
|
apsym2[29]=99;
|
|
return;
|
|
}
|
|
bool notheircall=false;
|
|
//theircall=theircall12;
|
|
if (theircall12.isEmpty())//if(len(trim(theircall)).eq.0) then
|
|
{
|
|
theircall12="LZ2ABC";//"K9ABC";
|
|
notheircall=true;
|
|
}
|
|
/* if needed for HOUND MSHV no HOUND Activity
|
|
call save_hash_call(hc13,n10,n12,n22)
|
|
write(c10,'(b10.10)') iand(n10,Z'3FF')
|
|
read(c10,'(10i1.1)',err=1) aph10 <-- int n10 = BinToInt32(aph10,0,10);
|
|
aph10=2*aph10-1*/
|
|
|
|
//! Encode a dummy standard message: i3=1, 28 1 28 1 1 15
|
|
//!
|
|
QString msgs2;
|
|
msgs2.append(mycall12.trimmed());
|
|
msgs2.append(" ");
|
|
msgs2.append(theircall12.trimmed());
|
|
msgs2.append(" ");
|
|
msgs2.append("RRR");
|
|
TGenQ65->pack77(msgs2,i3,n3,c77); //call pack77(msg,i3,n3,c77)
|
|
|
|
// ??? no need this
|
|
/*bool unpk77_success;
|
|
QString msgchk = TGenFt8->unpack77(c77,unpk77_success); //call unpack77(c77,1,msgchk,unpk77_success)
|
|
if(i3!=1 || (msgs2!=msgchk) || !unpk77_success) return;*/
|
|
|
|
if (i3!=1)
|
|
{
|
|
for (int i = 0; i < 58; ++i) // apsym2[58+5]
|
|
apsym2[i]=0;
|
|
apsym2[0]=99;
|
|
apsym2[29]=99;
|
|
return;
|
|
}
|
|
|
|
//read(c77,'(58i1)',err=1) apsym(1:58)
|
|
for (int i = 0; i < 58; ++i)
|
|
apsym2[i] = c77[i];
|
|
if (notheircall) apsym2[29]=99;
|
|
return;
|
|
//c1:
|
|
//??????????????????????
|
|
for (int i = 0; i < 58; ++i) // apsym2[58+5]
|
|
apsym2[i]=0;
|
|
apsym2[0]=99;
|
|
apsym2[29]=99;
|
|
return;
|
|
}
|
|
void DecoderQ65::ana64(double *iwave,int npts,double complex *c0)
|
|
{
|
|
/*integer*2 iwave(npts) !Raw data at 12000 Hz
|
|
complex c0(0:npts-1) !Complex data at 6000 Hz*/
|
|
int nfft1=npts;// 1440000
|
|
int nfft2=nfft1/2;//=720000 16000+8000=24000
|
|
//double df1=12000.0/nfft1;
|
|
double fac=(2.0/(32767.0*(double)nfft1))*0.01;// hv correction duble
|
|
for (int i=0; i<npts ; ++i) c0[i]=fac*iwave[i];//c0(0:npts-1)=fac*iwave(1:npts)
|
|
f2a.four2a_c2c(c0,nfft1,-1,1);//four2a(c0,nfft1,1,-1,1) //!Forward c2c FFT
|
|
for (int i=nfft2/2; i<nfft2; ++i) c0[i]=0.0+0.0*I;//c0(nfft2/2+1:nfft2-1)=0.
|
|
c0[0]=0.5*c0[0];// //c0(0)=0.5*c0(0)
|
|
f2a.four2a_c2c(c0,nfft2,1,1); //call four2a(c0,nfft2,1,1,1) //!Inverse c2c FFT; c0 is analytic sig
|
|
}
|
|
void DecoderQ65::twkfreq(double complex *c3,double complex *c4,int npts,double fsample,double *a)
|
|
{
|
|
double twopi=6.283185307;
|
|
//! Mix the complex signal
|
|
double complex w=1.0+1.0*I;
|
|
//double complex wstep=1.0+1.0*I;
|
|
int x0=0.5*(npts);//x0=0.5*(npts+1)
|
|
double s=2.0/(double)npts;//s=2.0/npts
|
|
for (int i =0; i<npts; ++i)
|
|
{//do i=1,npts
|
|
double x=s*(i-x0);//x=s*(i-x0)
|
|
double p2=1.5*x*x - 0.5; //p2=1.5*x*x - 0.5
|
|
//double p3=2.5*pow(x,3.0) - 1.5*x; //p3=2.5*(x**3) - 1.5*x
|
|
//double p4=4.375*pow(x,4.0) - 3.75*pow(x,2.0) + 0.375; //p4=4.375*(x**4) - 3.75*(x**2) + 0.375
|
|
double dphi=(a[0] + x*a[1] + p2*a[2]) * (twopi/fsample);
|
|
double complex wstep=cos(dphi)+sin(dphi)*I;//wstep=cmplx(cos(dphi),sin(dphi))
|
|
w=w*wstep;
|
|
c4[i]=w*c3[i];
|
|
}
|
|
}
|
|
void DecoderQ65::spec64(double complex *c0,int nsps,int jpk,float *s3f,int LL,int NN)//int npts,
|
|
{
|
|
//const int MAXFFT = 20736; //8000=120s
|
|
double complex cs[21736];//(0:MAXFFT-1)=20736
|
|
//double complex *cs = new double complex[21736];
|
|
double pom1[70][700];//63/640
|
|
//double (*pom1)[700] = new double[70][700];//63/640 //double (*ccf_)[14000] = new double[300][14000];
|
|
double xbase0[700];// max LL = 640
|
|
double xbase[700]; // max LL = 640
|
|
double pom[70];//63/640
|
|
double s3d[41320];//LN =40320 to made D s3_1fa
|
|
|
|
int nfft=nsps;//=721000
|
|
int j=0;
|
|
int n=0;
|
|
//qDebug()<<"nfft--------"<<nfft<<npts;
|
|
|
|
for (int k = 0; k < 84; ++k)//85=???
|
|
{//do k=1,84
|
|
if (k==isync[n]-1)
|
|
{
|
|
n++;
|
|
continue;
|
|
}
|
|
int ja=k*nsps+jpk;//ja=(k-1)*nsps + jpk
|
|
//if (ja+nsps>300000) qDebug()<<ja+nsps;
|
|
if (ja<0) ja=0;//2.58
|
|
//jb=ja+nsps-1
|
|
//if(ja.lt.0) ja=0
|
|
//if(jb.gt.npts-1) jb=npts-1
|
|
//nz=jb-ja
|
|
for (int x = 0; x < nfft; ++x) cs[x]=c0[x+ja];//cs(0:nfft-1)=c0(ja:jb) cs(0:nz)=c0(ja:jb)
|
|
//for (int x = nfft; x < 20736; ++x) cs[x]=0.0;//if(nz.lt.nfft-1) cs(nz+1:)=0.
|
|
f2a.four2a_c2c(cs,nsps,-1,1);//four2a(cs,nsps,1,-1,1) //!c2c FFT to frequency
|
|
for (int ii = 0; ii < LL; ++ii)//192 - 640 //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do ii=1,LL i1=i0+ipk-64 + mode_q65
|
|
int i=ii-64+mode_q65;//hv=64<-tested=?? old -65; i=ii-65+mode_q65 //-65=?? !mode_q65 = 1 2 4 8 16 for Q65 A B C D E
|
|
if (i<0)
|
|
{
|
|
i=i+nsps; //-1
|
|
}
|
|
//else i=i-1;
|
|
//if(k==1)qDebug()<<i<<LL;
|
|
//s3[j]=(creal(cs[i])*creal(cs[i]) + cimag(cs[i])*cimag(cs[i]));//s3(ii,j)=real(cs(i))**2 + aimag(cs(i))**2
|
|
pom1[j][ii]=(creal(cs[i])*creal(cs[i]) + cimag(cs[i])*cimag(cs[i]));
|
|
}
|
|
j++;
|
|
}
|
|
for (int i = 0; i < LL; ++i)
|
|
{//do i=1,LL
|
|
for (int x = 0; x < NN; ++x) pom[x] = pom1[x][i];
|
|
xbase0[i] = pomAll.pctile_shell(pom,NN,45);//pctile(s3(i,1:NN),NN,45,xbase0(i)) //!Get baseline for passband shape
|
|
}
|
|
int nh=25;
|
|
double sum0 = 0.0;
|
|
double sum1 = 0.0;
|
|
for (int i = 0; i < nh; ++i)
|
|
{
|
|
sum0+=xbase0[i];
|
|
sum1+=xbase0[i+LL-nh];
|
|
}
|
|
sum0/=((double)nh-1.0);
|
|
sum1/=((double)nh-1.0);
|
|
if (sum0==0.0) sum0=0.000001;
|
|
if (sum1==0.0) sum1=0.000001;
|
|
for (int i = 0; i < nh; ++i)
|
|
{
|
|
xbase[i]=xbase0[i]/sum0; //xbase(1:nh-1)=sum(xbase0(1:nh-1))/(nh-1.0)
|
|
xbase[i+LL-nh]=xbase0[i+LL-nh]/sum1; //xbase(1:nh-1)=sum(xbase0(1:nh-1))/(nh-1.0)
|
|
}
|
|
double sum3 = 0.0;
|
|
for (int i = 0; i <LL; ++i) sum3+=xbase0[i];
|
|
sum3/=(2.0*(double)nh+1.0);
|
|
if (sum3==0.0) sum3=0.000001;
|
|
for (int i = nh; i < LL-nh; ++i)
|
|
{//do i=nh,LL-nh
|
|
xbase[i]=xbase0[i]/sum3;//xbase(i)=sum(xbase0(i-nh+1:i+nh))/(2*nh+1) !Smoothed passband shape
|
|
}
|
|
|
|
//do i=1,LL
|
|
//s3(i,1:NN)=s3(i,1:NN)/(xbase(i)+0.001) !Apply frequency equalization
|
|
//enddo
|
|
|
|
j=0;
|
|
for (int i = 0; i < NN; ++i)
|
|
{//do i=1,LL
|
|
for (int x = 0; x < LL; ++x)
|
|
{
|
|
double del = (xbase[x]+0.001);
|
|
if (del==0.0) del=0.000001;
|
|
s3d[j] = pom1[i][x]/del;
|
|
j++;
|
|
}
|
|
}
|
|
|
|
double base = pomAll.pctile_shell(s3d,LL*NN,40);//pctile(s3,LL*NN,40,base)
|
|
if (base==0.0) base=0.000001;
|
|
for (int i = 0; i < NN*LL; ++i) s3f[i]=(float)(s3d[i]/base);
|
|
}
|
|
void DecoderQ65::q65_loops(double complex *c00,int npts2,int nsps2,int nsubmode,int ndepth,int jpk0,
|
|
double xdt0,double f0,int iaptype,double &xdt1,double &f1,double &snr2,
|
|
int *dat4,int &idec,bool sing_dec)
|
|
{
|
|
idec=-1;
|
|
//ircbest=9999
|
|
//double complex c0[721000];//allocate(c0(0:npts2-1)) 1440000/2=720000;
|
|
double complex *c0 = new double complex[721000];
|
|
int irc=-99;
|
|
double s3lim=20.0;
|
|
double baud=6000.0/(double)nsps2;
|
|
double ndf = 0.0;
|
|
double ndt = 0.0;
|
|
float esnodb = 0.0;
|
|
double a[5];//3
|
|
const int NN=63;
|
|
//const int LN=2176*63;//
|
|
float s3f[41320];//LN =40320 to made D
|
|
|
|
//ibwa = 4;
|
|
//ibwb = 8;
|
|
|
|
int idfmax=3;//2.57 old=3;
|
|
int idtmax=3;//2.57 old=3;
|
|
double ibw0=(double)(ibwa+ibwb)/2.0;
|
|
int maxdist=4; //2.57 old=5
|
|
if (ndepth==2)//(ndepth & 3)>=2
|
|
{
|
|
idfmax=4; //2.57 old=4
|
|
idtmax=4; //2.57 old=4
|
|
maxdist=6;//2.57 old=10
|
|
}
|
|
if (ndepth==3)
|
|
{
|
|
idfmax=5;
|
|
idtmax=5;
|
|
maxdist=15;
|
|
}
|
|
//qDebug()<<ibwa<<ibwb<<ibw0;
|
|
|
|
int LL=64*(mode_q65+2);//A=127
|
|
//napmin=99
|
|
xdt1=xdt0;
|
|
f1=f0;
|
|
/*int idfbest=0;
|
|
int idtbest=0;
|
|
int ndistbest=0;*/
|
|
|
|
//qDebug()<<"q65_loops"<<npts2;
|
|
bool exitt = false;
|
|
for (int idf = 1; idf <= idfmax; ++idf)//tested from 0 to < //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do idf=1,idfmax
|
|
ndf=(double)idf/2.0;
|
|
if (fmod(idf,2.0)==0) ndf=-ndf;
|
|
for (int x = 0; x < 3; ++x) a[x]=0.0;
|
|
a[0]=-(f0+0.5*baud*ndf); //if (f0>840 && f0<860) qDebug()<<a[0]<<f0; //+0.5 hv=0.53*
|
|
if (sing_dec) a[1]=-(0.5*drift);//2.57
|
|
twkfreq(c00,c0,npts2,6000.0,a);
|
|
for (int idt = 1; idt <= idtmax; ++idt)//tested from 0 to <
|
|
{//do idt=1,idtmax
|
|
ndt=(double)idt/2.0;
|
|
if (fmod(idt,2.0)==0) ndt=-ndt;
|
|
int jpk=(int)((double)jpk0 + (double)nsps2*ndt/16.0); //!tsym/16
|
|
//qDebug()<<jpk;
|
|
if (jpk<0) jpk=0; // jpk=max(0,jpk) if((int)f0==1533) qDebug()<<ndt<<jpk;
|
|
if (jpk>29000) jpk=29000;//2.58 jpk=min(29000,jpk)
|
|
spec64(c0,nsps2,jpk,s3f,LL,NN);//npts2
|
|
//double base = pomAll.pctile_shell(s3,LL*NN,40);//pctile(s3,LL*NN,40,base)
|
|
//if (base<0.0001) base=0.0001;
|
|
//for (int i = 0; i < LL*NN; ++i) s3[i]=s3[i]/base;
|
|
for (int i = 0; i < LL*NN; ++i)
|
|
{
|
|
if (s3f[i]>s3lim)
|
|
{
|
|
s3f[i]=s3lim; //where(s3(1:LL*NN)>s3lim) s3(1:LL*NN)=s3lim
|
|
//qDebug()<<i<<"s3lim";
|
|
}
|
|
}
|
|
q65_bzap(s3f,LL); //!Zap birdies
|
|
for (int ibw = ibwa; ibw <= ibwb; ++ibw)
|
|
{//do ibw=ibwa,ibwb
|
|
int ndist=(ndf*ndf + ndt*ndt + ((double)((double)ibw-ibw0)*((double)ibw-ibw0)));
|
|
if (ndist>maxdist) continue;
|
|
double b90=pow(1.72,ibw);
|
|
if (b90>345.0) continue;
|
|
float b90ts = b90/baud;
|
|
q65_dec2(s3f,nsubmode,b90ts,esnodb,irc,dat4);
|
|
//! irc > 0 ==> number of iterations required to decode
|
|
//! -1 = invalid params
|
|
//! -2 = decode failed
|
|
//! -3 = CRC mismatch
|
|
if (irc>=0)
|
|
{
|
|
//qDebug()<<decoded;
|
|
/*idfbest=idf;
|
|
idtbest=idt;
|
|
ndistbest=ndist;
|
|
nrc=irc;*/
|
|
exitt = true;
|
|
break;
|
|
}
|
|
} //! ibw (b90 loop)
|
|
if (exitt) break;
|
|
} //! idt (DT loop)
|
|
if (exitt) break;
|
|
}
|
|
//c100:
|
|
if (irc>=0)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{
|
|
idec=iaptype;
|
|
snr2=esnodb - pomAll.db(2500.0/baud);
|
|
xdt1=xdt0 + (double)nsps2*ndt/(16.0*6000.0);
|
|
f1=f0 + 0.5*baud*ndf;
|
|
}
|
|
delete [] c0;
|
|
}
|
|
void DecoderQ65::PrintMsg(QString tmm,double snrr,double dtt,int dff,QString mss,int frqq,QString idecc,
|
|
QString inf,bool &bgc, bool &havdd)//bool to2list,
|
|
{
|
|
if (bgc)
|
|
{
|
|
bgc = false;
|
|
emit EmitBackColor();
|
|
}
|
|
QString sdtxx = QString("%1").arg(dtt,0,'f',1);
|
|
if (sdtxx=="-0.0") sdtxx="0.0";
|
|
int nsnrr=(int)(fmax(-35.0,snrr));
|
|
if (nsnrr > 49) nsnrr = 49;
|
|
QStringList list;
|
|
list <<tmm<<QString("%1").arg(nsnrr)
|
|
<<sdtxx<<QString("%1").arg(dff)
|
|
<<mss<<idecc<<inf
|
|
<<QString("%1").arg(frqq);
|
|
emit EmitDecodetText(list);//,to2list
|
|
havdd = true;
|
|
}
|
|
void DecoderQ65::q65_decode(double *iwave,double nfa0,double nfb0,double fqso,int modid,bool &have_dec)
|
|
{
|
|
bool f_only_one_color = true;
|
|
static QString sl_mycall = "";
|
|
static QString sl_theircall = "";
|
|
static QString sl_theirgrid = "";
|
|
int dgen1[13];//13
|
|
int codewords1[63];
|
|
QString mycall = s_mycall.trimmed();
|
|
QString theircall = s_theircall.trimmed();
|
|
QString theirgrid = s_theirgrid.trimmed();
|
|
int ntrperiod = s_ntrperiod;
|
|
int ndepth = s_ndepth;
|
|
double nfqso = fqso;
|
|
bool emedelay = f_emedelay;
|
|
double f0 = 0.0;
|
|
double snr1 = 0.0;
|
|
//double width = 0.0;
|
|
int dat4[20];//13
|
|
double snr2 = 0.0;
|
|
int idec = -1;
|
|
double xdt = 0.0;
|
|
double dtdec = 0.0;
|
|
double f0dec = 0.0;
|
|
double xdt1 = 0.0;
|
|
double f1 = 0.0;
|
|
int nused = 0;
|
|
|
|
int jpk0 = 0;
|
|
int npts=ntrperiod*12000;//max 120*12000=1440000;
|
|
//int nfft1=ntrperiod*12000;//max 120*12000=1440000;
|
|
//double complex c00[1441000];//=1440000 allocate (c00(0:nfft1-1))
|
|
double complex *c00 = new double complex[1441000];
|
|
|
|
int nQSOprogress = s_nQSOprogress;//for the moment
|
|
int iaptype = 0;//for the moment
|
|
|
|
int cont_id = 0;
|
|
int cont_type = 0;
|
|
if (!f_multi_answer_modq65)//2.65
|
|
{
|
|
cont_id = s_cont_id;
|
|
cont_type = s_cont_type;
|
|
}
|
|
|
|
bool real_dec = false;
|
|
QString hv_dec = "?";
|
|
QString sidec = "?";
|
|
//bool f_averaging = false;
|
|
//bool lclearave = false; //>> clar avg
|
|
//bool f_clravg_after_decode = true;
|
|
//bool single_decode =
|
|
QString prev_sing_dec = "---";
|
|
bool lapcqonly = false;//for the moment
|
|
if (!s_lapon) lapcqonly = true;// only in mshv
|
|
|
|
bool lagain = false;
|
|
if (s_mousebutton==3)
|
|
lagain = true;
|
|
|
|
//if(lagain) ndepth=3; //ndepth=ior(ndepth,3) //wsjt252 !Use 'Deep' for manual Q65 decodes
|
|
|
|
//! Determine the T/R sequence: iseq=0 (even first), or iseq=1 (odd second)
|
|
/*n=nutc
|
|
if(ntrperiod>=60 .and. nutc<=2359) n=100*n // old if(ntrperiod.ge.60) n=100*n
|
|
write(cutc,'(i6.6)') n
|
|
read(cutc,'(3i2)') ih,im,is
|
|
int ih = tp.mid(0,2).toInt();
|
|
int im = tp.mid(2,2).toInt();//get min 120023
|
|
int is = tp.mid(4,2).toInt();//get seconds 120023
|
|
int nsec=3600*ih + 60*im + is;
|
|
iseq=fmod(nsec/ntrperiod,2);*/
|
|
int time_ss = s_time.midRef(4,2).toInt();//get seconds 120023
|
|
int time_mm = s_time.midRef(2,2).toInt();//get min 120023
|
|
int time_p = (time_mm*60)+time_ss;
|
|
time_p = time_p % (ntrperiod*2);
|
|
if (time_p<ntrperiod) iseq = 0;
|
|
else iseq = 1;
|
|
|
|
lnewdat = true;//hv for correction if in diferent time
|
|
//qDebug()<<iseq<<s_time;
|
|
|
|
if (modid==14) mode_q65 = 1;
|
|
else if (modid==15) mode_q65 = 2;
|
|
else if (modid==16) mode_q65 = 4;
|
|
else if (modid==17) mode_q65 = 8;
|
|
|
|
int nsubmode=0;
|
|
if (mode_q65==2) nsubmode=1;
|
|
else if (mode_q65==4) nsubmode=2;
|
|
else if (mode_q65==8) nsubmode=3;
|
|
//if(mode_q65.eq.16) nsubmode=4
|
|
//if(mode_q65.eq.32) nsubmode=5
|
|
|
|
//!w3sz added
|
|
/*int stageno;*/
|
|
int stageno = 0;
|
|
|
|
nfa=nfa0;
|
|
nfb=nfb0;
|
|
nfa=fmax(100,nfa); //hv nfa down
|
|
nfa=fmin(5000-10,nfa); //hv nfa up
|
|
nfb=fmax(100+10,nfb); //hv nfb down
|
|
nfb=fmin(5000,nfb); //hv nfb up
|
|
/*if (nfqso<nfa || nfqso>nfb)
|
|
{
|
|
nfqso = nfa + ((nfb-nfa)/2.0);
|
|
}*/
|
|
//double ntol = ftol;
|
|
//ftol = (nfb-nfa)/2.0;
|
|
//qDebug()<<nfqso<<"ftol"<<ftol<<(nfqso-ftol)<<(nfqso+ftol);
|
|
if (lagain) q65_hist(nfqso,"",theircall,theirgrid);//2.55 rtue=write false=find
|
|
|
|
if (lclearave) q65_clravg();
|
|
nsps = 1800;
|
|
if (ntrperiod== 30) nsps=3600;
|
|
else if (ntrperiod== 60) nsps=7200;
|
|
else if (ntrperiod==120) nsps=16000;
|
|
//else if (ntrperiod==300) nsps=41472;
|
|
|
|
int baud=12000.0/(double)nsps;
|
|
//nFadingModel=1
|
|
s_maxiters=33;//2.57 33=wsjt-x250rc1 myold=80
|
|
ibwa=fmax(1,int(1.8*log(baud*mode_q65)) + 1);
|
|
ibwb=fmin(10,ibwa+2);//2.57 ibwb=min(10,ibwa+2) myold=+4 //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
if (ndepth==2)//((ndepth & 3)>=2)
|
|
{
|
|
ibwa=fmax(1,int(1.8*log(baud*mode_q65)) + 1);//ibwa=fmax(1,int(1.8*log(baud*mode_q65)) + 2);
|
|
ibwb=fmin(10,ibwa+5);
|
|
s_maxiters=67;//2.57 67=wsjt-x250rc1 myold=90
|
|
}
|
|
else if (ndepth==3) //((ndepth & 3)==3)
|
|
{
|
|
ibwa=fmax(1,ibwa-1);
|
|
ibwb=fmin(10,ibwb+2);//2.61 hv=ibwb+2 ibwb=min(10,ibwb+1)
|
|
s_maxiters=100;
|
|
}
|
|
//qDebug()<<ibwa<<ibwb;
|
|
static bool init_q65_enc = true;
|
|
if (init_q65_enc)
|
|
{
|
|
for (int i = 0; i < 63; ++i)
|
|
{
|
|
if (i<13) dgen1[i]=0;
|
|
codewords1[i]=0;
|
|
}
|
|
q65S.q65_enc(dgen1,codewords1);
|
|
init_q65_enc = false;
|
|
}
|
|
|
|
if (mycall.isEmpty()) mycall = "XX2XX";
|
|
//if (theircall.isEmpty()) theircall= mycall; //stop for ft8apset
|
|
//if (theirgrid.isEmpty()) theirgrid= "FN20MM"; //stop for ft8apset
|
|
bool mhc = false;
|
|
bool lcc = false;
|
|
if (mycall!=sl_mycall || theircall!=sl_theircall)
|
|
{
|
|
mhc = true;
|
|
sl_mycall =mycall;
|
|
sl_theircall=theircall;
|
|
}
|
|
if (theirgrid!=sl_theirgrid)
|
|
{
|
|
lcc = true;
|
|
sl_theirgrid=theirgrid;
|
|
}
|
|
//ncw = 0; //stop=2.61 no Ap after 1 decode, add=2.57->ncw = 0;
|
|
if (mhc || lcc /*|| lagain*/) //2.57 myold=no_lagain wsjt-x250rc1 if(nqd.eq.1 .or. lagain) then
|
|
{
|
|
q65_set_list(mycall,theircall,theirgrid);
|
|
/*QString sss;
|
|
for (int i = 0; i < 63; ++i) sss.append(QString("%1").arg((int)codewords_[4][i]));
|
|
qDebug()<<"1="<<sss;
|
|
qDebug()<<"Call or Loc Cahnged"<<mycall<<theircall<<theirgrid;*/
|
|
//qDebug()<<"set_list ncw="<<ncw;
|
|
}
|
|
|
|
QString drft = "";
|
|
nused=1;
|
|
int iavg=0; //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
|
|
|
|
/*! W3SZ patch: Initialize AP params here, rather than afer the call to ana64().
|
|
call ft8apset(mycall,theircall,ncontest,apsym0,aph10) ! Generate ap symbols
|
|
where(apsym0.eq.-1) apsym0=0
|
|
npasses=2
|
|
if(nQSOprogress.eq.5) npasses=3*/
|
|
q65apset(mycall,theircall,apsym0);// ft8apset(mycall,theircall,ncontest,apsym0,aph10) //! Generate ap symbols
|
|
for (int x = 0; x < 59; ++x)//no possible ???
|
|
{
|
|
if (apsym0[x]==-1) apsym0[x]=0; //where(apsym0.eq.-1) apsym0=0
|
|
}
|
|
npasses=2;
|
|
if (nQSOprogress==5) npasses=3;//msg=73
|
|
|
|
|
|
//! Call top-level routine in q65 module: establish sync and try for a q3 decode.
|
|
q65_dec0(iavg,iwave,nfqso,lclearave,emedelay,xdt,f0,snr1,dat4,snr2,idec,nQSOprogress,cont_id,cont_type,stageno);
|
|
if (idec>=0)
|
|
{
|
|
dtdec=xdt; //!We have a list-decode result at nfqso
|
|
f0dec=f0;
|
|
hv_dec = "StdS";
|
|
if (idec>=1) hv_dec = "ApS"+QString("%1").arg(idec);
|
|
goto c100;
|
|
}
|
|
|
|
//! Prepare for a single-period decode with iaptype = 0, 1, 2, or 4
|
|
jpk0=(int)((xdt+1.0)*6000.0); //!Index of nominal start of signal
|
|
if (ntrperiod<=30) jpk0=(int)((xdt+0.5)*6000.0);// !For shortest sequences
|
|
if (jpk0<0) jpk0=0;
|
|
ana64(iwave,npts,c00); //!Convert to complex c00() at 6000 Sa/s
|
|
|
|
/*
|
|
q65apset(mycall,theircall,apsym0);// ft8apset(mycall,theircall,ncontest,apsym0,aph10) //! Generate ap symbols
|
|
for (int x = 0; x < 59; ++x)//no possible ???
|
|
{
|
|
if (apsym0[x]==-1) apsym0[x]=0; //where(apsym0.eq.-1) apsym0=0
|
|
}
|
|
npasses=2;
|
|
if (nQSOprogress==5) npasses=3;//msg=73
|
|
*/
|
|
|
|
if (lapcqonly) npasses=1;
|
|
iaptype=0;
|
|
for (int ipass = 0; ipass <= npasses; ++ipass)
|
|
{//do ipass=0,npasses !Loop over AP passes
|
|
for (int i = 0; i < 13 ; ++i)
|
|
{
|
|
apmask[i]=0; //13 //!Try first with no AP information
|
|
apsymbols[i]=0; //13 //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
}
|
|
if (ipass>=1)
|
|
{
|
|
//! Subsequent passes use AP information appropiate for nQSOprogress
|
|
q65_ap(nQSOprogress,ipass,cont_id,cont_type,lapcqonly,iaptype,apsym0,apmask1,apsymbols1);
|
|
int z = 0;
|
|
for (int i = 0; i < 13; ++i)
|
|
{
|
|
apmask[i] = BinToInt32(apmask1,z,z+6);
|
|
apsymbols[i] = BinToInt32(apsymbols1,z,z+6);
|
|
z += 6;
|
|
}
|
|
} //qDebug()<<ipass<<nQSOprogress<<f0;
|
|
q65_loops(c00,npts/2,nsps/2,nsubmode,ndepth,jpk0,xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec,true);
|
|
if (idec>=0)
|
|
{
|
|
if (f_max_drift && (drift<-14.0 || drift>14.0)) drft = "D";
|
|
dtdec=xdt1;
|
|
f0dec=f1;
|
|
hv_dec = "StdS";
|
|
if (ipass>=1) hv_dec = "ApS"+QString("%1").arg(iaptype);
|
|
goto c100; //!Successful decode, we're done
|
|
}
|
|
if (f_max_drift)// if no Successful decode try with no drift
|
|
{
|
|
int jpk0nd=(int)((xdtnd+1.0)*6000.0); //!Index of nominal start of signal
|
|
if (ntrperiod<=30) jpk0nd=(int)((xdtnd+0.5)*6000.0);//!For shortest sequences
|
|
if (jpk0nd<0) jpk0nd=0;
|
|
q65_loops(c00,npts/2,nsps/2,nsubmode,ndepth,jpk0nd,xdtnd,f0nd,iaptype,xdt1,f1,snr2,dat4,idec,false);
|
|
if (idec>=0)
|
|
{
|
|
dtdec=xdt1;
|
|
f0dec=f1;
|
|
hv_dec = "StdS";
|
|
if (ipass>=1) hv_dec = "ApS"+QString("%1").arg(iaptype);
|
|
goto c100; //!Successful decode, we're done
|
|
}
|
|
}
|
|
}
|
|
//(ndepth & 16)==0 average Include_averaging->setChecked(m_ndepth&16);
|
|
//Include_correlation->setChecked(m_ndepth&32);
|
|
//m_ndepth&64 Enable_AP_DXcall
|
|
//(ndepth & 128)==0 clar avg
|
|
if (!f_averaging || navg[iseq]<2) goto c100; //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
//! There was no single-transmission decode. Try for an average 'q3n' decode.
|
|
//! Call top-level routine in q65 module: establish sync and try for a q3
|
|
//! decode, this time using the cumulative 's1a' symbol spectra.
|
|
|
|
c50://2.55 ???
|
|
iavg=1; //nutc, no from this period
|
|
q65_dec0(iavg,iwave,nfqso,lclearave,emedelay,xdt,f0,snr1,dat4,snr2,idec,nQSOprogress,cont_id,cont_type,stageno);
|
|
if (idec>=0)
|
|
{
|
|
dtdec=xdt; //!We have a list-decode result from averaged data
|
|
f0dec=f0;
|
|
nused=navg[iseq]; //qDebug()<<"AVg111="<<decoded;
|
|
hv_dec = "Avg";
|
|
goto c100;
|
|
}
|
|
//! There was no 'q3n' decode. Try for a 'q[0124]n' decode.
|
|
//! Call top-level routine in q65 module: establish sync and try for a q[012]n
|
|
//! decode, this time using the cumulative 's1a' symbol spectra.
|
|
iavg=2;
|
|
q65_dec0(iavg,iwave,nfqso,lclearave,emedelay,xdt,f0,snr1,dat4,snr2,idec,nQSOprogress,cont_id,cont_type,stageno);
|
|
if (idec>=0)
|
|
{
|
|
dtdec=xdt;
|
|
f0dec=f0;
|
|
nused=navg[iseq]; //qDebug()<<"AVg222="<<decoded;
|
|
hv_dec = "Avg";
|
|
}
|
|
|
|
c100:
|
|
if (idec<0 && max_drift!=0)//wsjt252 if(idec.lt.0 .and. max_drift.eq.50) old //if (idec<0)
|
|
{
|
|
stageno = 5;//2.61 Call top-level routine in q65 module: establish sync and try for a q3 or q0 decode.
|
|
q65_dec0(iavg,iwave,nfqso,lclearave,emedelay,xdt,f0,snr1,dat4,snr2,idec,nQSOprogress,cont_id,cont_type,stageno);
|
|
if (idec>=0)
|
|
{
|
|
dtdec=xdt;
|
|
f0dec=f0;
|
|
}
|
|
}
|
|
|
|
if (idec>=0)
|
|
{
|
|
q65_snr(dat4,dtdec,f0dec,mode_q65,snr2);//nused,
|
|
prev_sing_dec = decoded;
|
|
int df_hv = (f0dec-nftx);
|
|
if (idec >= 0) sidec = "Q"+QString("%1").arg(idec);
|
|
if (nused>= 2) sidec.append(QString("%1").arg(nused));
|
|
sidec.append(drft);
|
|
PrintMsg(s_time,snr2,dtdec,df_hv,decoded,(int)f0dec,sidec,hv_dec,f_only_one_color,have_dec);
|
|
real_dec = true;
|
|
QString cc = "";
|
|
QString gg = "";
|
|
q65_hist((int)f0dec,decoded,cc,gg);//2.55 rtue=write false=find
|
|
//qDebug()<<"SINGLE="<<decoded;
|
|
}
|
|
/*else
|
|
{
|
|
snr1 = snr1 - 35;
|
|
int df_hv = (f0-nftx);
|
|
if (idec >= 0) sidec = "Q"+QString("%1").arg(idec);
|
|
if (nused>= 2) sidec.append(QString("%1").arg(nused));
|
|
//NO SINGLE DECODE
|
|
PrintMsg(s_time,snr1,xdt,df_hv,"---------",(int)f0,sidec,hv_dec,false,f_only_one_color,have_dec);
|
|
real_dec = false;
|
|
}*/
|
|
|
|
/*if(idec>=0) then
|
|
! idec Meaning
|
|
! ------------------------------------------------------
|
|
! -1: No decode
|
|
! 0: Decode without AP information
|
|
! 1: Decode with AP for "CQ ? ?"
|
|
! 2: Decode with AP for "MyCall ? ?"
|
|
! 3: Decode with AP for "MyCall DxCall ?"*/
|
|
|
|
//! Report snr1, even if no decode.
|
|
//nsnr=db(snr1) - 35.0
|
|
//if(nsnr<-35) nsnr=-35;
|
|
//idec=-1;
|
|
//navg0=1000*navg(0) + navg(1)
|
|
if (f_single_decode || lagain) goto c900;
|
|
|
|
for (int icand = 0; icand < ncand; ++icand)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do icand=1,ncand
|
|
//! Prepare for single-period candidate decodes with iaptype = 0, 1, 2, or 4
|
|
//qDebug()<<candidates_[0][icand];//(icand,1)
|
|
xdt= candidates_[0][icand];//(icand,2)
|
|
f0 = candidates_[1][icand];//(icand,3)
|
|
//qDebug()<<icand<<xdt<<f0;
|
|
jpk0=(int)((xdt+1.0)*6000.0); //!Index of nominal start of signal
|
|
if (ntrperiod<=30) jpk0=(int)((xdt+0.5)*6000.0); //!For shortest sequences
|
|
if (jpk0<0) jpk0=0; // qDebug()<<"jjjjjjjjjjjjjjjjjj"<<jpk0;
|
|
ana64(iwave,npts,c00); //!Convert to complex c00() at 6000 Sa/s
|
|
q65apset(mycall,theircall,apsym0); //! Generate ap symbols
|
|
for (int x = 0; x < 59; ++x)//no possible ???
|
|
{
|
|