MSHV-269-Non-Gendered/src/HvDecoderMs/decoderq65.cpp
2024-02-12 11:29:54 +11:00

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 ???
{