1703 lines
63 KiB
C++
1703 lines
63 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 FT4 Decoder
|
|
* Rewritten into C++ and modified by Hrisimir Hristov, LZ2HV 2015-2020
|
|
* May be used under the terms of the GNU General Public License (GPL)
|
|
*/
|
|
|
|
#include "decoderms.h"
|
|
#include "../HvMsPlayer/libsound/genpom.h"
|
|
#include "ft_all_ap_def.h"
|
|
//#include <QtGui>
|
|
|
|
static const int nappasses_4[6]=
|
|
{
|
|
2,2,2,2,2,3
|
|
};
|
|
static const int naptypes_4[6][4]=
|
|
{//gjhghghj
|
|
{1,2,0,0},{2,3,0,0},{2,3,0,0},{3,6,0,0},{3,6,0,0},{3,1,2,0}
|
|
};
|
|
//! iaptype
|
|
//!------------------------
|
|
//! 1 CQ ??? ??? (29 ap bits)
|
|
//! 2 MyCall ??? ??? (29 ap bits)
|
|
//! 3 MyCall DxCall ??? (58 ap bits)
|
|
//! 4 MyCall DxCall RRR (77 ap bits)
|
|
//! 5 MyCall DxCall 73 (77 ap bits)
|
|
//! 6 MyCall DxCall RR73 (77 ap bits)
|
|
//!********
|
|
DecoderFt4::DecoderFt4(int id)
|
|
{
|
|
pomFt.initPomFt();
|
|
pomAll.initPomAll();//2.66 for pctile_shell
|
|
decid = id;
|
|
TGenFt4 = new GenFt4(true);//f_dec_gen = dec=true gen=false
|
|
gen_pulse_gfsk_(pulse_ft4_rx,864.0,1.0,576); //576
|
|
first_ft4_ds = true;
|
|
first_ft4detcad = true;
|
|
first_ft4_sync4d = true;
|
|
first_subsft4 = true;
|
|
first_ft4bm = true;
|
|
first_ft4d = true;
|
|
DEC_SAMPLE_RATE = 12000.0;
|
|
twopi=8.0*atan(1.0);
|
|
pi=4.0*atan(1.0);
|
|
cont_id0_ft4_2 = 0;
|
|
//f_new_p = true;
|
|
}
|
|
DecoderFt4::~DecoderFt4()
|
|
{}
|
|
static double s_nftx4 = 1200.0;
|
|
void DecoderFt4::SetStTxFreq(double f)
|
|
{
|
|
s_nftx4 = f;
|
|
}
|
|
static bool f_multi_answer_mod4 = false;
|
|
void DecoderFt4::SetStMultiAnswerMod(bool f)
|
|
{
|
|
f_multi_answer_mod4 = f;
|
|
}
|
|
static int s_decoder_deep4 = 1;
|
|
void DecoderFt4::SetStDecoderDeep(int d)
|
|
{
|
|
s_decoder_deep4 = d;
|
|
//qDebug()<<"s_decoder_deep="<<s_decoder_deep;
|
|
}
|
|
static bool s_lapon4 = false;// only in mshv
|
|
void DecoderFt4::SetStApDecode(bool f)
|
|
{
|
|
s_lapon4 = f;
|
|
}
|
|
static int s_nQSOProgress4 = 0;
|
|
void DecoderFt4::SetStQSOProgress(int i)
|
|
{
|
|
s_nQSOProgress4 = i;
|
|
}
|
|
static QString s_time4 = "0.0";
|
|
static int s_mousebutton4 = 0;
|
|
//static bool s_fopen4 = false;
|
|
void DecoderFt4::SetStDecode(QString time,int mousebutton)
|
|
{
|
|
s_time4 = time;
|
|
s_mousebutton4 = mousebutton;//mousebutton Left=1, Right=3 fullfile=0 rtd=2
|
|
//s_fopen4 = ffopen;
|
|
}
|
|
static QString s_MyCall4 = "NOT__EXIST";
|
|
//static QString s_MyBaseCall4 = "NOT__EXIST";
|
|
static int s_id_cont_ft4_28 = 0;
|
|
static int s_ty_cont_ft4_28 = 0;
|
|
void DecoderFt4::SetStWords(QString s1,QString,int cq3,int ty4)
|
|
{
|
|
s_MyCall4 = s1;
|
|
s_id_cont_ft4_28 = cq3;
|
|
s_ty_cont_ft4_28 = ty4;
|
|
}
|
|
static QString s_HisCall4 = "NOCALL";
|
|
void DecoderFt4::SetStHisCall(QString c)
|
|
{
|
|
s_HisCall4 = c;
|
|
}
|
|
void DecoderFt4::SetMAMCalls(QStringList ls)
|
|
{
|
|
TGenFt4->save_hash_call_mam(ls);
|
|
}
|
|
/*static QString s_cqstr_ft4 = "CQ";
|
|
void DecoderFt4::SetStCqStr(QString s)
|
|
{
|
|
s_cqstr_ft4 = s;
|
|
}*/
|
|
void DecoderFt4::dshift1(double *a,int cou_a,int ish)
|
|
{
|
|
//HV for single shift vareable
|
|
//Left Shift ISHFT ISHFT(N,M) (M > 0) << n<<m n shifted left by m bits
|
|
//Right Shift ISHFT ISHFT(N,M) (M < 0) >> n>>m n shifted right by m bits
|
|
|
|
//double complex t[cou_a]; //garmi hv v1.42
|
|
//double complex t[cou_a*2+ish+50]; //garmi hv v1.43 ok
|
|
double *t = new double[cou_a+100]; //garmi pri goliam count hv v1.43 correct ok
|
|
for (int i=0; i< cou_a; i++)
|
|
t[i]=a[i];
|
|
|
|
if (ish>0)
|
|
{
|
|
for (int i = 0; i < cou_a; i++)
|
|
{
|
|
if (i+ish<cou_a)
|
|
a[i]=t[i+ish];
|
|
else
|
|
a[i]=t[i+ish-cou_a];
|
|
}
|
|
}
|
|
if (ish<0)
|
|
{
|
|
for (int i = 0; i < cou_a; i++)
|
|
{
|
|
if (i+ish<0)
|
|
a[i]=t[i+ish+cou_a];
|
|
else
|
|
a[i]=t[i+ish];
|
|
}
|
|
}
|
|
delete [] t;
|
|
}
|
|
void DecoderFt4::ft4_downsample(double *dd,bool newdata,double f0,double complex *c)
|
|
{
|
|
//! Input: real data in dd() at sample rate 12000 Hz
|
|
//! Output: Complex data in c(), sampled at 1200 Hz
|
|
const int NMAX = 72576; //(NMAX=21*3456)=72576;
|
|
const int NDOWN = 18;
|
|
const int NFFT2 = NMAX/NDOWN; //=4032
|
|
const int NSPS = 576;
|
|
double x[NMAX+50];
|
|
double complex c1[NFFT2+100];//(0:NFFT2-1)
|
|
|
|
double df=DEC_SAMPLE_RATE/(double)NMAX;
|
|
double baud=DEC_SAMPLE_RATE/(double)NSPS;
|
|
if (first_ft4_ds)
|
|
{
|
|
double bw_transition = 0.5*baud;
|
|
double bw_flat = 4.0*baud;
|
|
int iwt = (bw_transition/df);
|
|
int iwf = (bw_flat/df);
|
|
int z = iwt-1;
|
|
for (int i = 0; i < iwt; ++i)
|
|
window_ft4_ds[i] = 0.5*(1.0+cos(pi*(double)(z-i)/(double)iwt));//window(0:iwt-1) = 0.5*(1+cos(pi*(/(i,i=iwt-1,0,-1)/)/iwt))
|
|
for (int i = iwt; i < iwt+iwf; ++i)
|
|
window_ft4_ds[i]=1.0;//window(iwt:iwt+iwf-1)=1.0
|
|
for (int i = 0; i < iwt; ++i)
|
|
window_ft4_ds[i+iwt+iwf] = 0.5*(1.0+cos(pi*(double)(i)/(double)iwt));//window(iwt+iwf:2*iwt+iwf-1) = 0.5*(1+cos(pi*(/(i,i=0,iwt-1)/)/iwt))
|
|
for (int i = 2*iwt+iwf; i < NFFT2; ++i)
|
|
window_ft4_ds[i]=0.0;//window(2*iwt+iwf:)=0.0
|
|
|
|
int iws = (int)(baud/df);
|
|
dshift1(window_ft4_ds,NFFT2,iws);//window_ft4_ds=cshift(window_ft4_ds,iws) window=cshift(window,iws)
|
|
first_ft4_ds=false;
|
|
}
|
|
|
|
if (newdata)
|
|
{
|
|
for (int i = 0; i < NMAX; ++i)
|
|
x[i]=dd[i]*0.01;
|
|
f2a.four2a_d2c(cx_ft4_ds,x,NMAX,-1,0,decid);//four2a(x,NMAX,1,-1,0) // !r2c FFT to freq domain
|
|
}
|
|
int i0=(int)(f0/df);
|
|
for (int i = 0; i < NFFT2; ++i)
|
|
c[i]=0.0+0.0*I;
|
|
c1[0]=cx_ft4_ds[i0];
|
|
for (int i = 1; i < NFFT2/2; ++i)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do i=1,NFFT2/2
|
|
if (i0+i<NMAX/2) c1[i]=cx_ft4_ds[i0+i];//if(i0+i.le.NMAX/2) c1(i)=cx(i0+i)
|
|
if (i0-i>=0) c1[NFFT2-i]=cx_ft4_ds[i0-i];//if(i0-i.ge.0) c1(NFFT2-i)=cx(i0-i)
|
|
}
|
|
|
|
for (int i = 0; i < NFFT2; ++i)
|
|
c1[i]*=window_ft4_ds[i]/(double)NFFT2;//c1=c1*window/NFFT2
|
|
|
|
f2a.four2a_c2c(c1,NFFT2,1,1,decid);//call four2a(c1,NFFT2,1,1,1) //!c2c FFT back to time domain
|
|
|
|
for (int i = 0; i < NMAX/NDOWN; ++i)
|
|
c[i]=c1[i];//c[]=c1(0:NMAX/NDOWN-1)
|
|
}
|
|
|
|
void DecoderFt4::ft4_baseline(double *s,int nfa,int nfb,double *sbase)
|
|
{
|
|
//! Fit baseline to spectrum
|
|
//! Input: s(npts) Linear scale in power
|
|
//! Output: sbase(npts) Baseline
|
|
|
|
const int NFFT1=2304;
|
|
const int NH1=NFFT1/2;//=1152
|
|
double df=DEC_SAMPLE_RATE/(double)NFFT1; //!3.125 Hz
|
|
int ia=fmax((int)(200.0/df),nfa);
|
|
int ib=fmin(NH1,nfb);
|
|
int nseg = 10;
|
|
int npct = 10;
|
|
double t_s[1252];//NH1/2
|
|
//double *t_s = new double[1920+20];
|
|
double x[1010];
|
|
double y[1010];
|
|
double a[8];
|
|
|
|
for (int i = ia; i<ib; ++i)
|
|
{//do i=ia,ib
|
|
if (s[i]<0.000001) s[i]=0.000001;
|
|
s[i]=10.0*log10(s[i]); //!Convert to dB scale
|
|
}
|
|
|
|
int nterms=5;
|
|
int nlen=(ib-ia+0)/nseg; //!Length of test segment
|
|
int i0=(ib-ia+0)/2; //!Midpoint
|
|
int k=0;//???
|
|
|
|
for (int n = 0; n<nseg; ++n)
|
|
{//do n=1,nseg //!Loop over all segments
|
|
int ja=ia + (n-0)*nlen;
|
|
int jb=ja+nlen-0;
|
|
|
|
for (int z = 0; z<NH1-ja; ++z)//NH1=1152
|
|
t_s[z] = s[z+ja];
|
|
//qDebug()<<"ja jb"<<ja<<jb<<nlen<<1920-ja;
|
|
double base = pomAll.pctile_shell(t_s,nlen,npct);//pctile(s(ja),nlen,npct,base); //!Find lowest npct of points
|
|
//qDebug()<<"base"<<base;
|
|
for (int i = ja; i<jb; ++i)
|
|
{//do i=ja,jb
|
|
if (s[i]<=base)// then //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{
|
|
//if (k<1000) k++; //!Save all "lower envelope" points
|
|
x[k]=i-i0;
|
|
y[k]=s[i];
|
|
if (k<999)
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
|
|
int kz=k;
|
|
//if(kz<32) kz=32;
|
|
|
|
pomAll.zero_double_beg_end(a,0,6);//a=0.
|
|
//call polyfit(x,y,y,kz,nterms,0,a,chisqr) //!Fit a low-order polynomial
|
|
double chisqr = 0.0;
|
|
pomAll.polyfit(x,y,y,kz,nterms,0,a,chisqr);
|
|
//qDebug()<<"a"<<a[0]<<a[1]<<a[2]<<a[3]<<a[4]<<i0;
|
|
for (int i = ia; i<ib; ++i)
|
|
{//do i=ia,ib
|
|
double t=i-i0;
|
|
sbase[i]=a[0]+t*(a[1]+t*(a[2]+t*(a[3]+t*(a[4])))) + 0.65;
|
|
//! write(51,3051) i*df,s(i),sbase(i)
|
|
//!3051 format(3f12.3)
|
|
sbase[i]=pow(10,(sbase[i]/10.0)); //sbase[i]=10**(sbase[i]/10.0) nt=pow(2,2*nsym);//nt=2**(2*nsym)
|
|
}
|
|
}
|
|
void DecoderFt4::getcandidates4(double *dd,double fa,double fb,double fa1,double fb1,double syncmin,double nfqso,
|
|
int maxcand,double candidate[2][115],int &ncand)
|
|
{
|
|
const int NFFT1=2304;
|
|
const int NSTEP=576;
|
|
const int NMAX=21*3456;//=72576 !Samples in iwave
|
|
const int NHSYM=((NMAX-NFFT1)/NSTEP); //=122 153hv !Number of symbol spectra (1/4-sym steps)
|
|
const int NH1=NFFT1/2;
|
|
double x[NFFT1+10];
|
|
double complex cx[NH1+50];
|
|
double s_[NHSYM+10][NH1+10];//(NH1,NHSYM)
|
|
double savsm[NH1+50];
|
|
//int indx[NH1+50];
|
|
double sbase[NH1+50];
|
|
double savg[NH1+50];
|
|
double candidatet[2][115];
|
|
//qDebug()<<NHSYM;
|
|
|
|
if (first_ft4detcad)
|
|
{
|
|
first_ft4detcad=false;
|
|
for (int i = 0; i < NFFT1; ++i)
|
|
window_ft4[i]=0.0;
|
|
pomFt.nuttal_window(window_ft4,NFFT1);
|
|
}
|
|
|
|
//! Compute symbol spectra, stepping by NSTEP steps.
|
|
for (int i = 0; i < NH1; ++i)
|
|
{
|
|
//sbase[i]=0.0;
|
|
savg[i]=0.0;
|
|
}
|
|
|
|
//tstep=NSTEP/12000.0
|
|
double df=12000.0/(double)NFFT1;
|
|
double fac=1.0/300.0;
|
|
for (int j = 0; j < NHSYM; ++j)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do j=1,NHSYM
|
|
int ia=j*NSTEP;//ia=(j-1)*NSTEP + 1
|
|
int ib=ia+NFFT1; //ib=ia+NFFT1-1
|
|
if (ib>NMAX) break;// if(ib.gt.NMAX) exit
|
|
for (int z = 0; z < NFFT1; ++z)
|
|
x[z]=fac*dd[ia+z]*window_ft4[z]*0.01;
|
|
f2a.four2a_d2c(cx,x,NFFT1,-1,0,decid); //!r2c FFT
|
|
for (int i = 0; i < NH1; ++i)
|
|
{//do i=1,NH1
|
|
//s_[j][i]=pomAll.ps_hv(cx[i]);//old -> s(i,j)=real(cx(i))**2 + aimag(cx(i))**2
|
|
s_[j][i]=cabs(cx[i])*cabs(cx[i]);//fin s(1:NH1,j)=abs(cx(1:NH1))**2
|
|
savg[i]+=s_[j][i];
|
|
}
|
|
//savg=savg + s(1:NH1,j) !Average spectrum
|
|
}
|
|
for (int i = 0; i < NH1; ++i)
|
|
savsm[i]=0.0;
|
|
for (int i = 7; i < NH1-7; ++i)
|
|
{//do i=8,NH1-7
|
|
double sum = 0.0;
|
|
for (int j = -7; j < 8; ++j)
|
|
sum+=savg[i-j];
|
|
savsm[i]=sum/15.0;//savsm(i)=sum(savg(i-7:i+7))/15.
|
|
}
|
|
|
|
//double corrt=0.0;//corr for threads
|
|
//if (decid>0) corrt=100.0;
|
|
//int nfa=(int)(fa-corrt)/df;
|
|
int nfa=(int)fa/df;
|
|
if (nfa<38) nfa=38;
|
|
int nfb=(int)(fb)/df;
|
|
if (nfb>942) nfb=942;
|
|
|
|
int nfa1 = (int)fa1/df;//nfa;//
|
|
if (nfa1<38) nfa1=38;
|
|
int nfb1 = (int)fb1/df;//nfb;//
|
|
if (nfb1>942) nfb1=942;
|
|
|
|
ncand=0;
|
|
//qDebug()<<200.0/df<<4910.0/df;// 38.3 942.7
|
|
//1000/df=192=96 1200/df=230=115 1500/df=288=144 2000/df=384=192 3000/df=576=288 HV correction
|
|
if ((fb1-fa1)<2000)
|
|
{
|
|
nfb1 = nfa1 + 384;
|
|
if (nfb1>942)
|
|
{
|
|
nfb1 = 942; //5000.0/df=960
|
|
//nfa1 = 960 - 384;
|
|
}
|
|
}
|
|
//qDebug()<<decid<<nfa<<nfb<<"---"<<nfa1<<nfb1;
|
|
ft4_baseline(savg,nfa1,nfb1,sbase);
|
|
//ft4_baseline(savg,nfa,nfb,sbase);
|
|
//ft4_baseline(savg,200.0/df,3500.0/df,sbase);//2.22 important
|
|
|
|
bool any_is0 = false;
|
|
for (int i = nfa; i < nfb; ++i)
|
|
{
|
|
if (sbase[i]<=0.0)
|
|
{
|
|
any_is0 = true;
|
|
break;
|
|
}
|
|
}
|
|
if (any_is0) return;
|
|
//qDebug()<<"--------------"<<any_is0;
|
|
|
|
/*double tdel = 0.0;
|
|
int ctdel = 0;
|
|
for (int i = nfa1+10; i < nfb1-10; i+=5)
|
|
{
|
|
tdel += sbase[i];
|
|
ctdel++;
|
|
}
|
|
tdel /= (double)ctdel;
|
|
if (tdel<=0.0) tdel = 0.001;*/
|
|
|
|
for (int i = nfa; i < nfb; ++i)
|
|
{
|
|
savsm[i] /= sbase[i];
|
|
//savsm[i] /= tdel;
|
|
}
|
|
//qDebug()<<decid<<nfa<<nfb<<"---"<<nfa1<<nfb1<<" dots="<<ctdel;
|
|
|
|
double f_offset = -1.5*12000.0/(double)NSTEP;//-4.0;//no in 2.29 tested -> +0.3 for 32/64bit tested - 0.5
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
for (int j = 0; j < 100; ++j)
|
|
candidatet[i][j]=0.0;
|
|
}
|
|
int nq=0;
|
|
for (int i = nfa+1; i < nfb-1; ++i) //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do i=nfa+1,nfb-1
|
|
//if (i*df>810 && i*df<880) qDebug()<<"Pickkkk===="<<decid<<(int)i*df<<savsm[i];
|
|
if (savsm[i]>=savsm[i-1] && savsm[i]>=savsm[i+1] && savsm[i]>=syncmin)
|
|
{
|
|
//if (i*df>810 && i*df<880) qDebug()<<"Pickkkk===="<<decid<<(int)i*df<<savsm[i]<<"innnnn";
|
|
double den=savsm[i-1]-2.0*savsm[i]+savsm[i+1];//den=savsm(i-1)-2*savsm(i)+savsm(i+1);
|
|
double del=0.0;
|
|
if (den!=0.0) del=0.5*(savsm[i-1]-savsm[i+1])/den;
|
|
double fpeak=((double)i+del)*df+f_offset;
|
|
if (fpeak<100.0 || fpeak>4910.0) continue;//cycle
|
|
double speak=savsm[i]-0.25*(savsm[i-1]-savsm[i+1])*del;
|
|
|
|
candidatet[0][ncand]=fpeak;//candidate(1,ncand)=fpeak
|
|
candidatet[1][ncand]=speak;//candidate(3,ncand)=speak
|
|
|
|
|
|
if (fabs(fpeak-nfqso)<=20.0) nq++;//int nq=count(fabs(candidatet(1,1:ncand)-nfqso)<=20.0)
|
|
|
|
if (ncand<(maxcand-1))
|
|
ncand++;
|
|
else
|
|
break;
|
|
//if(ncand.eq.maxcand) exit
|
|
}
|
|
}
|
|
//qDebug()<<"test"<<ncand; //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
int n1=0;//1;
|
|
int n2=nq;//nq+1;
|
|
for (int i = 0; i < ncand; ++i)
|
|
{//do i=1,ncand
|
|
if (fabs(candidatet[0][i]-nfqso)<=20.0) //if(abs(candidatet(1,i)-nfqso)<=20.0) then
|
|
{
|
|
candidate[0][n1]=candidatet[0][i];//candidate(1:2,n1)=candidatet(1:2,i)
|
|
candidate[1][n1]=candidatet[1][i];
|
|
n1++;//n1=n1+1
|
|
}
|
|
else
|
|
{
|
|
candidate[0][n2]=candidatet[0][i];
|
|
candidate[1][n2]=candidatet[1][i];
|
|
n2++;
|
|
}
|
|
}
|
|
}
|
|
void DecoderFt4::sync4d(double complex *cd0,int i0,double complex *ctwk,int itwk,double &sync)
|
|
{
|
|
const int NDOWN=18;
|
|
const int NSPS=576;//512;
|
|
const int NSS=NSPS/NDOWN; //576/18=32
|
|
const int NMAX=21*3456;//=72576
|
|
const int NP=NMAX/NDOWN;//=4032
|
|
double complex csync2[2*NSS+20];//=64
|
|
int icos4a[4]=
|
|
{
|
|
0,1,3,2
|
|
};
|
|
int icos4b[4]=
|
|
{
|
|
1,0,2,3
|
|
};
|
|
int icos4c[4]=
|
|
{
|
|
2,3,1,0
|
|
};
|
|
int icos4d[4]=
|
|
{
|
|
3,2,0,1
|
|
};
|
|
|
|
if (first_ft4_sync4d)
|
|
{
|
|
int k=0; //k=1;
|
|
double phia=0.0;
|
|
double phib=0.0;
|
|
double phic=0.0;
|
|
double phid=0.0;
|
|
for (int i = 0; i < 4; ++i)
|
|
{//do i=0,3
|
|
double dphia=2.0*twopi*(double)icos4a[i]/(double)NSS;
|
|
double dphib=2.0*twopi*(double)icos4b[i]/(double)NSS;
|
|
double dphic=2.0*twopi*(double)icos4c[i]/(double)NSS;
|
|
double dphid=2.0*twopi*(double)icos4d[i]/(double)NSS;
|
|
for (int j = 0; j < NSS/2; ++j)
|
|
{//do j=1,NSS/2
|
|
csynca_ft4_sync[k]=cos(phia)+sin(phia)*I;
|
|
csyncb_ft4_sync[k]=cos(phib)+sin(phib)*I;
|
|
csyncc_ft4_sync[k]=cos(phic)+sin(phic)*I;
|
|
csyncd_ft4_sync[k]=cos(phid)+sin(phid)*I;
|
|
phia=fmod(phia+dphia,twopi);
|
|
phib=fmod(phib+dphib,twopi);
|
|
phic=fmod(phic+dphic,twopi);
|
|
phid=fmod(phid+dphid,twopi);
|
|
k++;//k=k+1
|
|
}
|
|
}
|
|
first_ft4_sync4d=false;
|
|
fac_ft4_sync=1.0/(double)(2.0*NSS);
|
|
}
|
|
|
|
int i1=i0; //!four Costas arrays
|
|
int i2=i0+33*NSS;
|
|
int i3=i0+66*NSS;
|
|
int i4=i0+99*NSS;
|
|
|
|
double complex z1=0.0+0.0*I;
|
|
double complex z2=0.0+0.0*I;
|
|
double complex z3=0.0+0.0*I;
|
|
double complex z4=0.0+0.0*I; //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
|
|
if (itwk==1) //csync2=ctwk*csynca !Tweak the frequency
|
|
{
|
|
for (int i = 0; i < 2*NSS; ++i)
|
|
csync2[i]=ctwk[i]*csynca_ft4_sync[i];
|
|
}
|
|
if (i1>=0 && i1+4*NSS-1<=NP-1) //z1=sum(cd0(i1:i1+4*NSS-1:2)*conjg(csync2))
|
|
{
|
|
int z =0;
|
|
for (int i = 0; i < 2*NSS; ++i)
|
|
{
|
|
z1+=cd0[i1+z]*conj(csync2[i]);
|
|
z+=2;
|
|
}
|
|
}
|
|
else if (i1<0)
|
|
{
|
|
int npts=(i1+4*NSS-1)/2;// npts=(i1+4*NSS-1)/2
|
|
if (npts<=16)// if(npts.le.16) then
|
|
z1=0.0+0.0*I;
|
|
else
|
|
{
|
|
//z1=sum(cd0(0:i1+4*NSS-1:2)*conjg(csync2(2*NSS-npts:)))
|
|
int z =0;
|
|
for (int i = 2*NSS-npts; i < 2*NSS; ++i)//NSS=32 cd0[4032];
|
|
{
|
|
z1+=cd0[z]*conj(csync2[i]);
|
|
z+=2;
|
|
}
|
|
//qDebug()<<"cd0="<<z<<"csync2="<<2*NSS-1;
|
|
}
|
|
}
|
|
|
|
if (itwk==1) //csync2=ctwk*csyncb //!Tweak the frequency
|
|
{
|
|
for (int i = 0; i < 2*NSS; ++i)
|
|
csync2[i]=ctwk[i]*csyncb_ft4_sync[i];
|
|
}
|
|
if (i2>=0 && i2+4*NSS-1<=NP-1) //z2=sum(cd0(i2:i2+4*NSS-1:2)*conjg(csync2))
|
|
{
|
|
int z =0;
|
|
for (int i = 0; i < 2*NSS; ++i)
|
|
{
|
|
z2+=cd0[i2+z]*conj(csync2[i]);
|
|
z+=2;
|
|
}
|
|
}
|
|
|
|
if (itwk==1) //csync2=ctwk*csyncc !Tweak the frequency
|
|
{
|
|
for (int i = 0; i < 2*NSS; ++i)
|
|
csync2[i]=ctwk[i]*csyncc_ft4_sync[i];
|
|
}
|
|
if (i3>=0 && i3+4*NSS-1<=NP-1) //z3=sum(cd0(i3:i3+4*NSS-1:2)*conjg(csync2))
|
|
{
|
|
int z =0;
|
|
for (int i = 0; i < 2*NSS; ++i)
|
|
{
|
|
z3+=cd0[i3+z]*conj(csync2[i]);
|
|
z+=2;
|
|
}
|
|
}
|
|
|
|
if (itwk==1) //csync2=ctwk*csyncd !Tweak the frequency
|
|
{
|
|
for (int i = 0; i < 2*NSS; ++i)
|
|
csync2[i]=ctwk[i]*csyncd_ft4_sync[i];
|
|
}
|
|
if (i4>=0 && i4+4*NSS-1<=NP-1) //z4=sum(cd0(i4:i4+4*NSS-1:2)*conjg(csync2))
|
|
{
|
|
int z =0;
|
|
for (int i = 0; i < 2*NSS; ++i)
|
|
{
|
|
z4+=cd0[i4+z]*conj(csync2[i]);
|
|
z+=2;
|
|
}
|
|
}//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
else if (i4+4*NSS-1>NP-1) //else if( i4+4*NSS-1.gt.NP-1 ) then
|
|
{
|
|
int npts=(NP-1-i4+1)/2;//npts=(NP-1-i4+1)/2;
|
|
if (npts<=16) //if(npts.le.16) then
|
|
z4=0.0+0.0*I;
|
|
else
|
|
{
|
|
//z4=sum(cd0(i4:i4+2*npts-1:2)*conjg(csync2(1:npts)))
|
|
int z =0;
|
|
for (int i = 0; i < npts; ++i)//NSS=32 cd0[4032];
|
|
{
|
|
z4+=cd0[i4+z]*conj(csync2[i]);
|
|
z+=2;
|
|
}
|
|
//qDebug()<<"cd0="<<i4<<i4+(npts-1)<<"csync2="<<npts-1;
|
|
}
|
|
}
|
|
//old p(z1)=real(z1*fac)**2 + aimag(z1*fac)**2
|
|
//new p(z1)=(real(z1*fac)**2 + aimag(z1*fac)**2)**0.5
|
|
//sync = ps_hv(z1*fac_ft4_sync) + ps_hv(z2*fac_ft4_sync) + ps_hv(z3*fac_ft4_sync) + ps_hv(z4*fac_ft4_sync);
|
|
sync = pow(pomAll.ps_hv(z1*fac_ft4_sync),0.5) + pow(pomAll.ps_hv(z2*fac_ft4_sync),0.5) +
|
|
pow(pomAll.ps_hv(z3*fac_ft4_sync),0.5) + pow(pomAll.ps_hv(z4*fac_ft4_sync),0.5);
|
|
}
|
|
void DecoderFt4::gen_ft4cwaveRx(int *i4tone,double f_tx,double complex *cwave)
|
|
{
|
|
//////////////////////// GFSK MODULATOR ////////////////////////////////////////////
|
|
int nsym=103;
|
|
int nsps=576; //=576 for 12000=512
|
|
int nwave=(nsym+2)*nsps;//max rx=60480 max rx=53760
|
|
//double dphi[240000+10]; //real dphi(0:240000-1)
|
|
double *dphi=new double[60540]; //max rx=60480
|
|
double hmod=1.0;
|
|
double dt=1.0/12000.0;// for RX=12000 for tx=48000
|
|
|
|
//! Compute the smoothed frequency waveform.
|
|
//! Length = (nsym+2)*nsps samples, zero-padded (nsym+2)*nsps TX=215040 RX=53760
|
|
double dphi_peak=twopi*hmod/(double)nsps;
|
|
for (int i= 0; i < 60500; ++i)//max rx=60480
|
|
dphi[i]=0.0;
|
|
|
|
for (int j= 0; j < nsym; ++j)
|
|
{
|
|
int ib=j*nsps;
|
|
for (int i= 0; i < 3*nsps; ++i)//=1728
|
|
dphi[i+ib] += dphi_peak*pulse_ft4_rx[i]*(double)i4tone[j];
|
|
}
|
|
|
|
double ofs = twopi*f_tx*dt;
|
|
double phi=0.0;
|
|
for (int j= 0; j < nwave; ++j)//rx=60480 rx=53760
|
|
{
|
|
cwave[j]=cos(phi)+sin(phi)*I;
|
|
phi=fmod(phi+dphi[j]+ofs,twopi);
|
|
}
|
|
//qDebug()<<"nsamp="<<nsamp<<nwave;
|
|
for (int i = 0; i < nsps; ++i)
|
|
cwave[i]*=(1.0-cos(twopi*(double)i/(2.0*nsps)))/2.0;
|
|
int k2=(nsym+1)*nsps+1; //=2047 before stop
|
|
for (int i = 0; i < nsps; ++i)
|
|
cwave[i+k2]*=(1.0+cos(twopi*(double)i/(2.0*nsps)))/2.0;
|
|
//qDebug()<<"nsamp="<<k2+nsps-1;
|
|
delete [] dphi;
|
|
}
|
|
void DecoderFt4::subtractft4(double *dd,int *itone,double f0,double dt)
|
|
{
|
|
//const int NSPS=576;
|
|
const int NFRAME=(103+2)*576;//60480
|
|
const int NMAX=21*3456;//=72576
|
|
const int NFILT=1400;
|
|
const int NFFT=NMAX;
|
|
int offset_w = NFILT/2+25;
|
|
int nstart=dt*12000.0+1.0-576.0;
|
|
|
|
double complex *cref = new double complex[62481];//max rx=60481 +ramp
|
|
double complex *cfilt= new double complex[72800];//72576 NMAX+100
|
|
//double dd66[72800];// __attribute__((aligned(16)));
|
|
//pomAll.zero_double_beg_end(dd66,0,72600);
|
|
//double *dd66 = new double[72700]; // <- slow w10
|
|
|
|
pomAll.zero_double_comp_beg_end(cfilt,0,(NMAX+25));
|
|
//pomAll.zero_double_comp_beg_end(cref,0,NFRAME+25);
|
|
|
|
gen_ft4cwaveRx(itone,f0,cref); //gen_ft4wave(itone,nsym,nsps,fs,f0,cref,xjunk,icmplx,NFRAME);
|
|
|
|
if (first_subsft4)
|
|
{
|
|
//! Create and normalize the filter
|
|
double window[NFILT+100] __attribute__((aligned(16)));
|
|
double fac=1.0/double(NFFT);
|
|
double sum=0.0;
|
|
for (int j = -NFILT/2; j < NFILT/2; ++j)
|
|
{//do j=-NFILT/2,NFILT/2
|
|
window[j+offset_w]=cos(pi*(double)j/(double)NFILT)*cos(pi*(double)j/(double)NFILT);
|
|
sum+=window[j+offset_w];
|
|
}
|
|
pomAll.zero_double_comp_beg_end(cw_subsft4,0,NMAX+25);
|
|
if (sum<=0.0) // no devide by zero
|
|
sum=0.01;
|
|
for (int i = 0; i < NFILT+1; ++i)
|
|
cw_subsft4[i]=window[i+offset_w-NFILT/2]/sum;//cw(1:NFILT+1)=window/sum
|
|
|
|
pomAll.cshift1(cw_subsft4,NMAX,(NFILT/2+1)); //cw=cshift(cw,NFILT/2+1);
|
|
|
|
f2a.four2a_c2c(cw_subsft4,NFFT,-1,1,decid);//call four2a(cw,nfft,1,-1,1)
|
|
for (int i = 0; i < NMAX; ++i)
|
|
cw_subsft4[i]*=fac;
|
|
first_subsft4=false;
|
|
}
|
|
|
|
for (int i = 0; i < NFRAME; ++i)
|
|
{
|
|
int id=nstart+i-1;//0 -1
|
|
if (id>=0 && id<NMAX)
|
|
{
|
|
cfilt[i]=dd[id]*conj(cref[i]);//camp[i];//cfilt(1:nframe)=camp(1:nframe)
|
|
}
|
|
}
|
|
|
|
f2a.four2a_c2c(cfilt,NFFT,-1,1,decid);//call four2a(cfilt,nfft,1,-1,1)
|
|
for (int i = 0; i < NFFT; ++i)//cfilt(1:nfft)=cfilt(1:nfft)*cw(1:nfft)
|
|
cfilt[i]*=cw_subsft4[i];
|
|
f2a.four2a_c2c(cfilt,NFFT,1,1,decid);//call four2a(cfilt,nfft,1,1,1)
|
|
|
|
//! Subtract the reconstructed signal
|
|
for (int i = 0; i < NFRAME; ++i)//if(j.ge.1 .and. j.le.NMAX) dd(j)=dd(j)-2*REAL(cfilt(i)*cref(i))
|
|
{//do i=1,nframe
|
|
int j=nstart+i-1;//0 -1
|
|
if (j>=0 && j<NMAX)
|
|
dd[j]-=1.94*creal(cfilt[i]*cref[i]);//2.35 1.94 2.18 1.93
|
|
}
|
|
/*int kstop = 0;
|
|
for (int i = 0; i < NFRAME; ++i)//if(j.ge.1 .and. j.le.NMAX) dd(j)=dd(j)-2*REAL(cfilt(i)*cref(i))
|
|
{
|
|
int j=nstart+i-1;//0 -1
|
|
if (j>=0 && j<NMAX)
|
|
{
|
|
dd66[j]=1.94*creal(cfilt[i]*cref[i]);//2.35 1.94 2.26 1.93 no->2.0 //2.07 1.92<-tested 1.5,1.6 ,1.7ok,
|
|
kstop=j;
|
|
}
|
|
}
|
|
int kstart = nstart-1;
|
|
if (kstart<0) kstart=0;
|
|
for (int i = kstart; i < kstop+1; ++i)
|
|
dd[i]-=dd66[i];*/
|
|
|
|
delete [] cref;
|
|
delete [] cfilt;
|
|
}
|
|
int DecoderFt4::count_eq_bits(bool *a,int b_a,bool *b,int c)
|
|
{
|
|
int ns1=0;
|
|
for (int x = 0; x < c; ++x)
|
|
if (a[x+b_a]==b[x]) ns1++;
|
|
return ns1;
|
|
}
|
|
void DecoderFt4::get_ft4_bitmetrics(double complex *cd,double bitmetrics_[3][220],bool &badsync)
|
|
{
|
|
const int NN=103;
|
|
const int NSPS=576;
|
|
const int NDOWN=18;
|
|
const int NSS=NSPS/NDOWN;//=32
|
|
double complex csymb[NSS+10];//complex csymb(NSS)
|
|
double complex cs_[NN+10][4];//complex cs(0:3,NN)
|
|
double s4_[NN+10][4];// real s4(0:3,NN)
|
|
double s2[256+20];
|
|
int graymap[4]=
|
|
{
|
|
0,1,3,2
|
|
};
|
|
int icos4a[4]=
|
|
{
|
|
0,1,3,2
|
|
};
|
|
int icos4b[4]=
|
|
{
|
|
1,0,2,3
|
|
};
|
|
int icos4c[4]=
|
|
{
|
|
2,3,1,0
|
|
};
|
|
int icos4d[4]=
|
|
{
|
|
3,2,0,1
|
|
};
|
|
|
|
if (first_ft4bm)
|
|
{
|
|
for (int i = 0; i < 8; ++i)//one_ft4_2[8][256];
|
|
{//do i=0,255
|
|
for (int j = 0; j < 256; ++j)
|
|
{//do j=0,7
|
|
//if(iand(i,2**j).ne.0) one(i,j)=.true.
|
|
if ((j & (int)pow(2,i))!=0)
|
|
one_ft4_2[i][j]=true;
|
|
else
|
|
one_ft4_2[i][j]=false;
|
|
}
|
|
}
|
|
first_ft4bm = false;
|
|
}
|
|
|
|
for (int k = 0; k < NN; ++k)//NN=103
|
|
{//do k=1,NN
|
|
int i1=k*NSS;//i1=(k-1)*NSS
|
|
for (int z = 0; z < NSS; ++z)//NSS=32
|
|
csymb[z]=cd[z+i1]; //csymb=cd(i1:i1+NSS-1)
|
|
f2a.four2a_c2c(csymb,NSS,-1,1,decid);//four2a(csymb,NSS,1,-1,1)
|
|
for (int x = 0; x < 4; ++x)
|
|
{
|
|
cs_[k][x]=csymb[x]; //cs(0:3,k)=csymb(1:4)
|
|
s4_[k][x]=cabs(csymb[x]);//s4(0:3,k)=abs(csymb(1:4))
|
|
}
|
|
}
|
|
|
|
//! Sync quality check
|
|
int is1=0;
|
|
int is2=0;
|
|
int is3=0;
|
|
int is4=0;
|
|
badsync=false;
|
|
for (int k = 0; k < 4; ++k)//s4_[103][4] s4(0:3,NN) NN=103
|
|
{//do k=1,4
|
|
int ip=pomAll.maxloc_da_beg_to_end(s4_[k],0,4); //ip=maxloc(s4(:,k)) ip=maxloc_da_beg_to_end(s8_[k],0,8);
|
|
if (icos4a[k]==ip) is1++; //if(icos4a(k-1).eq.(ip(1)-1)) is1=is1+1
|
|
ip=pomAll.maxloc_da_beg_to_end(s4_[k+33],0,4); //ip=maxloc(s4(:,k+33))
|
|
if (icos4b[k]==ip) is2++; //if(icos4b(k-1).eq.(ip(1)-1)) is2=is2+1
|
|
ip=pomAll.maxloc_da_beg_to_end(s4_[k+66],0,4); //ip=maxloc(s4(:,k+66))
|
|
if (icos4c[k]==ip) is3++; //if(icos4c(k-1).eq.(ip(1)-1)) is3=is3+1
|
|
ip=pomAll.maxloc_da_beg_to_end(s4_[k+99],0,4); //ip=maxloc(s4(:,k+99))
|
|
if (icos4d[k]==ip) is4++; //if(icos4d(k-1).eq.(ip(1)-1)) is4=is4+1
|
|
}
|
|
int nsync=is1+is2+is3+is4;
|
|
|
|
if (nsync < 8)
|
|
{
|
|
badsync=true;
|
|
return;
|
|
}
|
|
//if (smax < 0.7 || nsync < 8) continue;//cycle //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
//qDebug()<<"2nsync="<<nsync<<is1<<is2<<is3<<is4<<smax<<f0;
|
|
for (int nseq = 1; nseq <= 3; ++nseq)
|
|
{//do nseq=1,3 // !Try coherent sequences of 1, 2, and 4 symbols
|
|
int nsym=1;
|
|
if (nseq==1) nsym=1;
|
|
if (nseq==2) nsym=2;
|
|
if (nseq==3) nsym=4;
|
|
int nt=pow(2,2*nsym);//nt=2**(2*nsym)
|
|
for (int ks = 1; ks <= NN-nsym+1; ks+=nsym)//NN=103 103-4+1
|
|
{//do ks=1,NN-nsym+1,nsym //!87+16=103 symbols.
|
|
//amax=-1.0
|
|
for (int i = 0; i < nt; ++i)//graymap[4]
|
|
{//do i=0,nt-1
|
|
int i1=i/64;
|
|
int i2=(i & 63)/16;
|
|
int i3=(i & 15)/4;
|
|
int i4=(i & 3);
|
|
if (nsym==1) //s2[256]
|
|
s2[i]=cabs(cs_[ks-1][graymap[i4]]);//graymap(i4),ks)
|
|
else if (nsym==2) //cs_(graymap(i3),ks)+cs(graymap(i4),ks+1)
|
|
s2[i]=cabs(cs_[ks-1][graymap[i3]]+cs_[ks+0][graymap[i4]]);
|
|
else if (nsym==4)//cs_(graymap(i1),ks) + cs(graymap(i2),ks+1) + cs(graymap(i3),ks+2) + cs(graymap(i4),ks+3)
|
|
s2[i]=cabs(cs_[ks-1][graymap[i1]] + cs_[ks+0][graymap[i2]] + cs_[ks+1][graymap[i3]] + cs_[ks+2][graymap[i4]]);
|
|
//else //no possyble
|
|
//print*,"Error - nsym must be 1, 2, or 4."
|
|
}
|
|
int ipt=0+(ks-1)*2;//ipt=1+(ks-1)*2;
|
|
int ibmax = 1;
|
|
if (nsym==1) ibmax=1;
|
|
if (nsym==2) ibmax=3;
|
|
if (nsym==4) ibmax=7; //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
for (int ib = 0; ib <= ibmax; ++ib)//bmeta[206] (2*NN)
|
|
{//do ib=0,ibmax //s2[256] bool one_ft4_2[8][256];//(0:255,0:7)
|
|
//bm=maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib))-maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib))
|
|
double max1v=0.0;
|
|
for (int zz = 0; zz < nt; ++zz)
|
|
{
|
|
if (one_ft4_2[ibmax-ib][zz]==true)
|
|
{
|
|
double tmax1v=s2[zz];
|
|
if (tmax1v>max1v)
|
|
max1v=tmax1v;
|
|
}
|
|
}
|
|
double max2v=0.0;
|
|
for (int zz = 0; zz < nt; ++zz)
|
|
{
|
|
if (one_ft4_2[ibmax-ib][zz]==false)
|
|
{
|
|
double tmax2v=s2[zz];
|
|
if (tmax2v>max2v)
|
|
max2v=tmax2v;
|
|
}
|
|
}
|
|
double bm=max1v-max2v;
|
|
|
|
if (ipt+ib>(2*NN-1)) continue;//cycle
|
|
/*if (nsym==1)
|
|
bmeta[ipt+ib]=bm;
|
|
else if (nsym==2)
|
|
bmetb[ipt+ib]=bm;
|
|
else if (nsym==4)
|
|
bmetc[ipt+ib]=bm;*/
|
|
bitmetrics_[nseq-1][ipt+ib]=bm;//bitmetrics(ipt+ib,nseq)=bm
|
|
}
|
|
}
|
|
}
|
|
|
|
bitmetrics_[1][204]=bitmetrics_[0][204];//bmetb(205:206)=bmeta(205:206)
|
|
bitmetrics_[1][205]=bitmetrics_[0][205];
|
|
for (int zz = 200; zz < 204; ++zz)
|
|
bitmetrics_[2][zz]=bitmetrics_[1][zz];//bmetc(201:204)=bmetb(201:204)
|
|
bitmetrics_[2][204]=bitmetrics_[0][204];//bmetc(205:206)=bmeta(205:206)
|
|
bitmetrics_[2][205]=bitmetrics_[0][205];
|
|
|
|
pomFt.normalizebmet(bitmetrics_[0],2*NN);
|
|
pomFt.normalizebmet(bitmetrics_[1],2*NN);
|
|
pomFt.normalizebmet(bitmetrics_[2],2*NN);
|
|
|
|
}
|
|
/*void DecoderFt4::SetResetPrevT(QString ptime)
|
|
{
|
|
s_time4_prev = ptime;
|
|
}
|
|
void DecoderFt4::SetNewP(bool f)
|
|
{
|
|
f_new_p = f;
|
|
}*/
|
|
void DecoderFt4::ft4_decode(double *dd,double f0a,double f0b,double f0a1,double f0b1,double fqso,bool &have_dec)//,int /*npts no need*/)
|
|
{
|
|
have_dec = false;
|
|
const int NDOWN=18; //!Downsample factor
|
|
const int NSPS=576;
|
|
const int NSS=NSPS/NDOWN;//=32
|
|
const int ND=87;
|
|
//const int NFFT1=2304;
|
|
//const int NH1=NFFT1/2;//=1152
|
|
const int NMAX=21*3456;//=72576
|
|
const int NDMAX=NMAX/NDOWN;//=4032
|
|
const int NS=16;//<-?????
|
|
const int NN=NS+ND; //=103
|
|
const int maxcand=100;
|
|
const int c_cb = NDMAX;//=4032
|
|
const int c_cd = NN*NSS;//=3296
|
|
const int c_cd2 = NDMAX;//=4032
|
|
double fs=DEC_SAMPLE_RATE/(double)NDOWN; //!Sample rate after downsampling
|
|
//double dt=1.0/fs; //!Sample interval after downsample (s)
|
|
//tt=NSPS*dt //!Duration of "itone" symbols (s)
|
|
//txt=NZ*dt //!Transmission length (s) without ramp up/down
|
|
//h=1.0
|
|
double a[5];
|
|
double complex ctwk[2*NSS];
|
|
//double complex ctwk2_[33][2*NSS]; //ctwk2(2*NSS,-16:16) 2*32=64
|
|
bool rvec[77]=
|
|
{
|
|
0,1,0,0,1,0,1,0,0,1,0,1,1,1,1,0,1,0,0,0,1,0,0,1,1,0,1,1,0,
|
|
1,0,0,1,0,1,1,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,1,1,0,0,1,0,1,
|
|
0,1,0,1,0,1,1,0,1,1,1,1,1,0,0,0,1,0,1
|
|
};
|
|
QString hiscall = s_HisCall4;
|
|
QString mycall = s_MyCall4;
|
|
QString message;
|
|
QString msgsent;
|
|
bool c77[100];//77+10
|
|
//bool message77[130];
|
|
bool message91[140];
|
|
bool cw[2*ND+20];//174
|
|
//double savg[NH1+10];
|
|
//double sbase[NH1+10];
|
|
double complex cd2[NDMAX+100];
|
|
double complex cb[NDMAX+100];
|
|
double complex cd[4000];//(103*32-1)=3295 //!Complex waveform
|
|
bool hbits[220];//(2*NN)=206
|
|
double llr [180];//(2*ND)=174
|
|
double llra[180];//(2*ND)=174
|
|
double llrb[180];//(2*ND)=174
|
|
double llrc[180];//(2*ND)=174
|
|
double llrd[180];//(2*ND)=174
|
|
bool apmask[174];//(2*ND)=174
|
|
int iaptype=0;
|
|
bool f_only_one_color = true;
|
|
double bitmetrics_[3][220];//real bitmetrics(2*NN,3)//2*NN = 206
|
|
bool badsync = false;
|
|
|
|
int ndecodes=0;
|
|
QString decodes[maxcand+20];
|
|
for (int i = 0; i < maxcand; ++i)
|
|
decodes[i]=" ";
|
|
|
|
//int ntol = G_DfTolerance;
|
|
double nfqso=fqso;
|
|
double nfa=f0a;//100.0; // mybe from waterfull scale
|
|
double nfb=f0b;//3000.0;
|
|
double nfa1=f0a1;//100.0; // mybe from waterfull scale
|
|
double nfb1=f0b1;//3000.0;
|
|
bool nagain = false;//s_mousebutton = mousebutton; //mousebutton Left=1, Right=3 fullfile=0 rtd=2
|
|
if (s_mousebutton4==3)
|
|
nagain = true;
|
|
|
|
int nQSOProgress = s_nQSOProgress4;
|
|
int cont_type = 0;
|
|
int cont_id = 0;
|
|
if (!f_multi_answer_mod4)
|
|
{
|
|
cont_type = s_ty_cont_ft4_28;
|
|
cont_id = s_id_cont_ft4_28;
|
|
}
|
|
//double nftx = s_nftx;
|
|
//bool lapon = s_lapon;
|
|
bool lapcqonly = false;//lapcqonly<-no used fom me. if no TX more then 10min use only AP1
|
|
if (!s_lapon4) lapcqonly = true;// only in mshv
|
|
|
|
|
|
if (first_ft4d || (cont_id!=cont_id0_ft4_2))
|
|
{
|
|
for (int idf = 0; idf < 41; ++idf) // 41 33
|
|
{//do idf=-16,16
|
|
a[0]=(double)(idf-20); //-+20 +-16
|
|
a[1]=0.0;
|
|
a[2]=0.0;
|
|
a[3]=0.0;
|
|
a[4]=0.0;
|
|
for (int i = 0; i < 2*NSS; ++i)
|
|
ctwk[i]=1.0;
|
|
pomFt.twkfreq1(ctwk,2*NSS,fs/2.0,a,ctwk2_ft4_[idf]);// ctwk2(:,idf)
|
|
}
|
|
|
|
for (int i = 0; i < 29; ++i)
|
|
{
|
|
/*if (cont_id== 0) mcq_ft4[i]=2*fmod(mcq_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id== 2) mcq_ft4[i]=2*fmod(mcqtest_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id== 3) mcq_ft4[i]=2*fmod(mcqtest_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id== 4) mcq_ft4[i]=2*fmod(mcqfd_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id== 5) mcq_ft4[i]=2*fmod(mcqtest_ft[i]+rvec[i],2)-1;//mcq_ft4[i]=2*fmod(mcqru_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id== 6) mcq_ft4[i]=2*fmod(mcqww_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id== 7) mcq_ft4[i]=2*fmod(mcqww_ft[i]+rvec[i],2)-1; //mcq_ft4[i]=2*fmod(mcqru_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id== 8) mcq_ft4[i]=2*fmod(mcqww_ft[i]+rvec[i],2)-1; //mcq_ft4[i]=2*fmod(mcqru_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id== 9) mcq_ft4[i]=2*fmod(mcqru_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id==10) mcq_ft4[i]=2*fmod(mcqbu_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id==11) mcq_ft4[i]=2*fmod(mcqft_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id==12) mcq_ft4[i]=2*fmod(mcqpdc_ft[i]+rvec[i],2)-1;
|
|
else if (cont_id==13) mcq_ft4[i]=2*fmod(mcqtest_ft[i]+rvec[i],2)-1;*/
|
|
mcq_ft4[i]=2*fmod(mcq_ft[cont_id][i]+rvec[i],2)-1;
|
|
if (i<19)
|
|
{
|
|
mrrr_ft4[i]=2*fmod(mrrr_ft[i]+rvec[i+58],2)-1;
|
|
m73_ft4[i]=2*fmod(m73_ft[i]+rvec[i+58],2)-1;
|
|
mrr73_ft4[i]=2*fmod(mrr73_ft[i]+rvec[i+58],2)-1;
|
|
}
|
|
} //qDebug()<<cont_id;
|
|
|
|
mycall0_ft4="";
|
|
hiscall0_ft4="";
|
|
cont_id0_ft4_2 = cont_id;
|
|
first_ft4d=false;
|
|
}
|
|
|
|
//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
mycall=mycall.trimmed();
|
|
hiscall=hiscall.trimmed();
|
|
if (mycall!=mycall0_ft4 || hiscall!=hiscall0_ft4)
|
|
{
|
|
//QString sss = "";
|
|
for (int i = 0; i < 2*ND; ++i)
|
|
apbits_ft4[i]=0;
|
|
apbits_ft4[0]=99;
|
|
apbits_ft4[29]=99;
|
|
for (int i = 0; i < 28; ++i)
|
|
{
|
|
apmy_ru_ft4[i]=0;
|
|
aphis_fd_ft4[i]=0;
|
|
}
|
|
bool nohiscall;
|
|
int i3;
|
|
int n3;
|
|
bool unpk77_success;
|
|
if (mycall.count()<3) goto c10;//if(len(trim(mycall)) .lt. 3) go to 10
|
|
|
|
nohiscall=false;
|
|
hiscall0_ft4=hiscall;
|
|
if (hiscall0_ft4.count()<3)//if(len(trim(hiscall0)).lt.3) then
|
|
{
|
|
hiscall0_ft4=mycall; //! use mycall for dummy hiscall - mycall won't be hashed.
|
|
nohiscall=true;
|
|
}
|
|
message=mycall+" "+hiscall0_ft4+" RR73";//message=trim(mycall)//' '//trim(hiscall0)//' RR73'
|
|
i3=0;//i3=-1
|
|
n3=0;//n3=-1
|
|
unpk77_success=false;
|
|
TGenFt4->pack77(message,i3,n3,c77);
|
|
msgsent=TGenFt4->unpack77(c77,unpk77_success);
|
|
if (i3!=1 || (message!=msgsent) || !unpk77_success) goto c10;
|
|
//read(c77,'(77i1)') message77
|
|
for (int i = 0; i < 28; ++i)
|
|
{
|
|
apmy_ru_ft4[i]=2*fmod(c77[i]+rvec[i+1],2)-1;
|
|
aphis_fd_ft4[i]=2*fmod(c77[i+29]+rvec[i+28],2)-1;
|
|
}
|
|
for (int i = 0; i < 77; ++i)
|
|
c77[i]=fmod(c77[i]+rvec[i],2);
|
|
|
|
TGenFt4->encode174_91(c77,cw);
|
|
for (int i = 0; i < 2*ND; ++i)
|
|
apbits_ft4[i]=2*cw[i]-1;
|
|
if (nohiscall) apbits_ft4[29]=99;
|
|
c10:
|
|
//continue;
|
|
mycall0_ft4=mycall;
|
|
hiscall0_ft4=hiscall;
|
|
}
|
|
|
|
if (nagain)
|
|
{
|
|
//ntol = 50;// +/-10 hv +/-25
|
|
nfa = nfqso-50;//50
|
|
nfb = nfqso+50;//50
|
|
}
|
|
nfa=fmax(200,nfa); //hv nfa down
|
|
nfa=fmin(5000-10,nfa); //hv nfa up
|
|
nfb=fmax(200+10,nfb); //hv nfb down
|
|
nfb=fmin(5000,nfb); //hv nfb up
|
|
|
|
nfa1=fmax(200,nfa1); //hv nfa down
|
|
nfa1=fmin(5000-10,nfa1); //hv nfa up
|
|
nfb1=fmax(200+10,nfb1); //hv nfb down
|
|
nfb1=fmin(5000,nfb1); //hv nfb up
|
|
|
|
//double nfqso_calc = nfqso;
|
|
if (nfqso<nfa || nfqso>nfb)
|
|
{
|
|
nfqso = nfa + ((nfb-nfa)/2.0);
|
|
//qDebug()<<"FT4 D="<<decid<<nfqso;
|
|
}
|
|
|
|
//! ndepth=3: 3 passes, bp+osd
|
|
//! ndepth=2: 3 passes, bp only
|
|
//! ndepth=1: 1 pass, no subtraction
|
|
int ndepth = s_decoder_deep4;
|
|
//int max_iterations=40;
|
|
double syncmin=1.2;//1.2
|
|
bool dosubtract=true;
|
|
bool doosd=true;
|
|
int nsp=3;//2
|
|
|
|
if (ndepth==2)
|
|
doosd=false;
|
|
if (ndepth==1)
|
|
{
|
|
nsp=1;
|
|
dosubtract=false;
|
|
doosd=false;
|
|
}
|
|
//qDebug()<<"new==============================================";
|
|
|
|
///subtract error
|
|
/*double dd[96000];//9s 12000*9=108000 //8s 12000*8=96000
|
|
for (int i = 0; i < 96000; ++i)
|
|
dd[i]=dd01[i];*/
|
|
///subtract error
|
|
|
|
int nd1 = 0;
|
|
int nd2 = 0;
|
|
for (int isp = 1; isp <= nsp; ++isp)
|
|
{//do isp = 1,nsp
|
|
if (isp==2)
|
|
{
|
|
if (ndecodes==0) break;//exit
|
|
nd1=ndecodes;
|
|
}
|
|
else if (isp==3)
|
|
{
|
|
nd2=ndecodes-nd1;
|
|
if (nd2==0) break;//exit
|
|
}
|
|
|
|
double candidate[2][115];//(3,100)
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
for (int j = 0; j < 101; ++j)
|
|
candidate[i][j]=0.0;
|
|
}
|
|
int ncand=0;
|
|
getcandidates4(dd,nfa,nfb,nfa1,nfb1,syncmin,nfqso,maxcand,candidate,ncand);//,sbase
|
|
|
|
/*for (int z= 0; z < ncand; z++)
|
|
{
|
|
QString sss = "";
|
|
sss.append(QString("%1").arg((int)candidate[0][z]));
|
|
sss.append(" ");
|
|
double xsnr=10*log10(candidate[1][z])-14.0;
|
|
sss.append(QString("%1").arg(xsnr,0,'f',1));
|
|
qDebug()<<z<<sss;
|
|
} */
|
|
|
|
bool dobigfft=true;
|
|
for (int icand = 0; icand < ncand; ++icand)//c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{//do icand=1,ncand
|
|
double f0=candidate[0][icand]; //f0=candidate(1,icand)
|
|
double snr=candidate[1][icand]-1.0; //snr=candidate(3,icand)-1.0
|
|
//if (f0>1200 && f0<1400) qDebug()<<icand<<f0<<snr;
|
|
ft4_downsample(dd,dobigfft,f0,cd2); //!Downsample to 32 Sam/Sym
|
|
if (dobigfft) dobigfft=false;
|
|
double sum2=0.0;
|
|
for (int i = 0; i < c_cd2; ++i)
|
|
sum2+=creal(cd2[i]*conj(cd2[i]));//???
|
|
sum2=sum2/((double)NMAX/(double)NDOWN);//sum2=sum(cd2*conjg(cd2))/(real(NZZ)/real(NDOWN))
|
|
|
|
if (sum2>0.0)//if(sum2.gt.0.0) cd2=cd2/sqrt(sum2)
|
|
{
|
|
for (int i = 0; i < c_cd2; ++i)
|
|
cd2[i]=cd2[i]/sqrt(sum2);
|
|
}
|
|
//! Sample rate is now 12000/18 = 666.67 samples/second
|
|
|
|
//int idfbest = 0;
|
|
//int ibest = 0;
|
|
//double smax=-99.0;
|
|
//int kkk = 0;
|
|
//double sf0 = f0;
|
|
for (int iseg = 1; iseg <= 3; ++iseg)//! DT search is done over 3 segments
|
|
{//do iseg=1,3
|
|
int idfbest = 0;
|
|
int ibest = -1;
|
|
double smax=-99.0;
|
|
double smax1=-99.0;
|
|
for (int isync = 1; isync <= 2; ++isync)
|
|
{
|
|
int idfmin,idfmax,idfstp,ibmin,ibmax,ibstp;
|
|
ibmin = 108;
|
|
ibmax = 565;
|
|
if (isync==1)
|
|
{
|
|
idfmin=-12;//12
|
|
idfmax=12; //12
|
|
idfstp=3; //3
|
|
//ibmin=-344;
|
|
//ibmax=1012;
|
|
if (iseg==1)
|
|
{
|
|
ibmin=108;
|
|
ibmax=565;//560
|
|
}
|
|
else if (iseg==2)
|
|
{
|
|
smax1=smax;
|
|
ibmin=555;//560
|
|
ibmax=1012;
|
|
}
|
|
else if (iseg==3)
|
|
{
|
|
ibmin=-344;
|
|
ibmax=118;//108
|
|
}
|
|
ibstp=4;
|
|
}
|
|
else
|
|
{
|
|
idfmin=idfbest-4;//-4
|
|
idfmax=idfbest+4;//4
|
|
idfstp=1;
|
|
ibmin=ibest-5;//ibmin=fmax(0,ibest-5);
|
|
ibmax=ibest+5;//ibmax=fmin(ibest+5,NDMAX/NDOWN-1);
|
|
ibstp=1;
|
|
}
|
|
//qDebug()<<"m/m"<<isync<<idfmin<<idfmax<<idfbest;
|
|
ibest=-1;
|
|
smax=-99.0;
|
|
idfbest=0;
|
|
for (int idf = idfmin; idf <= idfmax; idf+=idfstp)
|
|
{//do idf=idfmin,idfmax,idfstp
|
|
for (int istart = ibmin; istart <= ibmax; istart+=ibstp)
|
|
{//do istart=ibmin,ibmax,ibstp
|
|
double sync=-99.0;
|
|
sync4d(cd2,istart,ctwk2_ft4_[idf+20],1,sync);//20 sync4d(cd2,istart,ctwk2(:,idf),1,sync) //!Find sync power
|
|
if (sync>smax) //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
{
|
|
smax=sync;
|
|
ibest=istart;//+ibstp;
|
|
idfbest=idf;//+idfstp;
|
|
}
|
|
}
|
|
}
|
|
//if(f0>1905 && f0<1930)
|
|
//qDebug()<<"iseg"<<smax<<iseg<<f0<<f0+idfbest<<ibest;
|
|
}
|
|
//if(f0>1905 && f0<1930)
|
|
//qDebug()<<"CORR======"<<f0+idfbest<<idfbest<<ibest;
|
|
if (iseg==1) smax1=smax;
|
|
if (smax<1.2) continue;
|
|
if (iseg>1 && smax<smax1) continue;
|
|
double f1=f0+(double)idfbest; //qDebug()<<idfbest<<f1;
|
|
if ( f1<=10.0 || f1>=4990.0 ) continue;//cycle
|
|
ft4_downsample(dd,dobigfft,f1,cb); //!Final downsample, corrected f1
|
|
sum2=0.0;
|
|
for (int i = 0; i < c_cb; ++i)//sum2=sum(abs(cb)**2)/(real(NSS)*NN)
|
|
sum2+=cabs(cb[i])*cabs(cb[i]);
|
|
sum2 = sum2/(double)(NSS*NN);
|
|
if (sum2>0.0)
|
|
{
|
|
for (int i = 0; i < c_cb; ++i)
|
|
cb[i]=cb[i]/sqrt(sum2);
|
|
}
|
|
//????????????????????????????
|
|
//qDebug()<<"kkk="<<ibest<<f1;
|
|
//const int c_cb = NDMAX;//=4032
|
|
//const int c_cd = NN*NSS;//=3296
|
|
for (int i = 0; i < c_cd+5; ++i) //cd=0. //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
cd[i]=0.0;
|
|
if (ibest>=0)
|
|
{
|
|
int it=fmin(NDMAX-1,ibest+NN*NSS-1);
|
|
int np=it-ibest+1;
|
|
for (int i = 0; i < np; ++i)
|
|
cd[i]=cb[i+ibest];//cd(0:np-1)=cb(ibest:it)
|
|
//qDebug()<<"kkk="<<np<<ibest<<it;
|
|
}
|
|
else
|
|
{
|
|
//cd(-ibest:ibest+NN*NSS-1)=cb(0:NN*NSS+2*ibest-1)
|
|
for (int i = 0; i < (NN*NSS+2*ibest); ++i)
|
|
{
|
|
if (i-ibest>=0)//for any case array out of bounds
|
|
cd[i-ibest]=cb[i];
|
|
}
|
|
}
|
|
//qDebug()<<fmin(NDMAX-1,ibest+NN*NSS-1)-ibest+1<<NN*NSS+2*ibest<<c_cd<<c_cb<<f1;
|
|
|
|
get_ft4_bitmetrics(cd,bitmetrics_,badsync);
|
|
//qDebug()<<badsync<<f1;
|
|
if (badsync) continue;
|
|
//hbits=0 //hbits[206] //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
//where(bmeta>=0) hbits=1;
|
|
for (int x = 0; x < 2*NN; ++x)
|
|
{
|
|
if (bitmetrics_[0][x]>=0.0) hbits[x]=1;
|
|
else hbits[x]=0;
|
|
}
|
|
|
|
bool ms1[8] = {0,0,0,1,1,0,1,1};//count(hbits( 1: 8)==(/0,0,0,1,1,0,1,1/))
|
|
int ns1=count_eq_bits(hbits,0, ms1,8);
|
|
bool ms2[8] = {0,1,0,0,1,1,1,0};//count(hbits( 67: 74)==(/0,1,0,0,1,1,1,0/))
|
|
int ns2=count_eq_bits(hbits,66, ms2,8);
|
|
bool ms3[8] = {1,1,1,0,0,1,0,0};//count(hbits(133:140)==(/1,1,1,0,0,1,0,0/))
|
|
int ns3=count_eq_bits(hbits,132,ms3,8);
|
|
bool ms4[8] = {1,0,1,1,0,0,0,1};//count(hbits(199:206)==(/1,0,1,1,0,0,0,1/))
|
|
int ns4=count_eq_bits(hbits,198,ms4,8);
|
|
int nsync_qual=ns1+ns2+ns3+ns4;
|
|
//qDebug()<<"nsync_qual="<<nsync_qual<<ns1<<ns2<<ns3<<ns4<<f1;
|
|
if (nsync_qual<20) continue;//cycle
|
|
|
|
double scalefac=2.83; //llr[174]; =2*ND
|
|
for (int x = 0; x < 58; ++x)
|
|
{
|
|
llra[x]=bitmetrics_[0][x+8];
|
|
llra[x+58]=bitmetrics_[0][x+74];
|
|
llra[x+116]=bitmetrics_[0][x+140];
|
|
llrb[x]=bitmetrics_[1][x+8];
|
|
llrb[x+58]=bitmetrics_[1][x+74];
|
|
llrb[x+116]=bitmetrics_[1][x+140];
|
|
llrc[x]=bitmetrics_[2][x+8];
|
|
llrc[x+58]=bitmetrics_[2][x+74];
|
|
llrc[x+116]=bitmetrics_[2][x+140];
|
|
}
|
|
double maxval_llra_abs = 0.0;
|
|
for (int x = 0; x < 2*ND; ++x)//llr[174]; =2*ND
|
|
{
|
|
llra[x]=scalefac*llra[x];
|
|
llrb[x]=scalefac*llrb[x];
|
|
llrc[x]=scalefac*llrc[x];
|
|
|
|
double llra_abs = fabs(llra[x]);
|
|
if (llra_abs>maxval_llra_abs)
|
|
maxval_llra_abs=llra_abs;
|
|
}
|
|
double apmag = maxval_llra_abs*1.1;//apmag=maxval(abs(llra))*1.1
|
|
|
|
/*int npasses;
|
|
if (lapon)
|
|
{
|
|
//if (!lapcqonly)
|
|
npasses=3+nappasses_4[nQSOProgress];//ft4=2,2,2,2,2,3 ft8=2,2,2,4,4,3
|
|
//else
|
|
//npasses=4;
|
|
}
|
|
else
|
|
npasses=3;*/
|
|
int npasses=3+nappasses_4[nQSOProgress];//npasses=3+nappasses(nQSOProgress)
|
|
if (lapcqonly) npasses=4;//??? new if(lapcqonly) npasses=4
|
|
if (ndepth==1) npasses=3;
|
|
//hv=5 new if(ncontest.ge.6) npasses=3 ! Don't support Fox and Hound
|
|
if (cont_type>=5) npasses=3;
|
|
|
|
int nharderror = -1;
|
|
for (int ipass = 1; ipass <= npasses; ++ipass)
|
|
{//do ipass=1,npasses
|
|
for (int z = 0; z < 2*ND; ++z)
|
|
{
|
|
if (ipass==1)
|
|
llr[z]=llra[z];//if(ipass.eq.2) llr=llr1
|
|
else if (ipass==2)
|
|
llr[z]=llrb[z];
|
|
else if (ipass==3)
|
|
llr[z]=llrc[z];//llr=llr0
|
|
//if (ipass==1)
|
|
//qDebug()<<"ft8b ipass======== Start"<<llrd[z];
|
|
}
|
|
if (ipass<=3)
|
|
{
|
|
for (int z = 0; z < 2*ND; ++z)
|
|
apmask[z]=0;
|
|
iaptype=0;
|
|
}
|
|
double napwid=80.0; //2.39 old double napwid=60.0;
|
|
if (ipass > 3)
|
|
{
|
|
for (int z = 0; z < 2*ND; ++z)
|
|
llrd[z]=llrc[z]; //2.39 old llrd[z]=llra[z];
|
|
//iaptype=naptypes(nQSOProgress,ipass-3)
|
|
iaptype=naptypes_4[nQSOProgress][ipass-(3+1)];// v1 4+1
|
|
if (lapcqonly) iaptype=1;
|
|
//! ncontest=0 : NONE CQ
|
|
//! 1 : NA_VHF TEST
|
|
//! 2 : EU_VHF TEST
|
|
//! 3 : FIELD DAY FD
|
|
//! 4 : RTTY RU
|
|
//! 5 : WW_DIGI MSHV= WW
|
|
//! 6 : FOX MSHV= BU
|
|
//! 7 : HOUND NONE
|
|
//!
|
|
//! Conditions that cause us to bail out of AP decoding
|
|
|
|
// 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
|
|
|
|
//double napwid=60.0; //c++ ==.EQ. !=.NE. >.GT. <.LT. >=.GE. <=.LE.
|
|
//hv new =4
|
|
if (cont_type<=4 && iaptype>=3 && fabs(f1-nfqso)>napwid) continue;
|
|
//if(iaptype.ge.2 .and. apbits(1).gt.1) cycle ! No, or nonstandard, mycall
|
|
//if(iaptype.ge.3 .and. apbits(30).gt.1) cycle ! No, or nonstandard, dxcall
|
|
if (iaptype>=2 && apbits_ft4[0]>1) continue;
|
|
if (iaptype>=3 && apbits_ft4[29]>1) continue;
|
|
|
|
if (iaptype==1) //then ! CQ or CQ TEST or CQ FD or CQ RU or CQ SCC
|
|
{
|
|
for (int z = 0; z < 2*ND; ++z)//2*ND=174
|
|
{
|
|
apmask[z]=0;
|
|
if (z<29)
|
|
{
|
|
apmask[z]=1;
|
|
llrd[z]=apmag*(double)mcq_ft4[z];
|
|
}
|
|
} //qDebug()<<iaptype;
|
|
}
|
|
if (iaptype==2) //then ! MyCall,???,???
|
|
{
|
|
for (int z = 0; z < 2*ND; ++z)
|
|
apmask[z]=0;
|
|
if (cont_type==0 || cont_type==1)// || ncontest==5
|
|
{
|
|
for (int z = 0; z < 29; ++z)
|
|
{
|
|
apmask[z]=1;//apmask(1:29)=1
|
|
llrd[z]=apmag*(double)apbits_ft4[z];//llrd(1:29)=apmag*apsym(1:29)
|
|
}
|
|
}
|
|
else if (cont_type==2)
|
|
{
|
|
for (int z = 0; z < 28; ++z)
|
|
{
|
|
apmask[z]=1;//apmask(1:28)=1
|
|
llrd[z]=apmag*(double)apbits_ft4[z];//llrd(1:28)=apmag*apsym(1:28)
|
|
}
|
|
}
|
|
else if (cont_type==3)
|
|
{
|
|
for (int z = 0; z < 28; ++z)
|
|
{
|
|
apmask[z]=1; //apmask(1:28)=1
|
|
llrd[z]=apmag*(double)apbits_ft4[z];//llrd(1:28)=apmag*apbits(1:28)
|
|
}
|
|
}
|
|
else if (cont_type==4)//RTTY UU HV-6=BU || ncontest==6
|
|
{
|
|
for (int z = 1; z < 29; ++z)
|
|
{
|
|
apmask[z]=1;//apmask(2:29)=1
|
|
llrd[z]=apmag*(double)apmy_ru_ft4[z-1];//llrd(2:29)=apmag*apmy_ru(1:28)
|
|
}
|
|
}
|
|
}
|
|
if (iaptype==3) //then ! MyCall,DxCall,???
|
|
{
|
|
for (int z = 0; z < 2*ND; ++z)
|
|
apmask[z]=0;
|
|
if (cont_type==0 || cont_type==1 || cont_type==2)// || ncontest==5
|
|
{
|
|
for (int z = 0; z < 58; ++z)
|
|
{
|
|
apmask[z]=1;// apmask(1:58)=1
|
|
llrd[z]=apmag*(double)apbits_ft4[z];// llrd(1:58)=apmag*apbits(1:58)
|
|
}
|
|
}
|
|
else if (cont_type==3) //then ! Field Day
|
|
{
|
|
for (int z = 0; z < 56; ++z)//2.36 57 or 56 ???
|
|
{
|
|
//2.36 if (z<56)//57 or 56 ???
|
|
apmask[z]=1;//apmask(1:56)=1
|
|
if (z<28)
|
|
llrd[z]=apmag*(double)apbits_ft4[z];//llrd(1:28)=apmag*apbits(1:28)
|
|
if (z<28)
|
|
llrd[z+28]=apmag*(double)aphis_fd_ft4[z];//llrd(29:56)=apmag*aphis_fd(1:28)????
|
|
}
|
|
}
|
|
else if (cont_type==4)//then ! RTTY RU HV 6=BU // || ncontest==6
|
|
{
|
|
for (int z = 0; z < 57; ++z)
|
|
{
|
|
if (z>0)
|
|
apmask[z]=1;// apmask(2:57)=1
|
|
if (z<28)
|
|
llrd[z+1]=apmag*(double)apmy_ru_ft4[z];//llrd(2:29)=apmag*apmy_ru(1:28)
|
|
if (z>28)
|
|
llrd[z]=apmag*(double)apbits_ft4[z];// llrd(30:57)=apmag*apbits(30:57)
|
|
}
|
|
}
|
|
}
|
|
if (iaptype==4 || iaptype==5 || iaptype==6)
|
|
{
|
|
for (int z = 0; z < 2*ND; ++z)
|
|
apmask[z]=0;
|
|
//if(ncontest.le.5) then
|
|
if (cont_type<=4)//hv new=4
|
|
{
|
|
for (int z = 0; z < 77; ++z)
|
|
apmask[z]=1; //apmask(1:77)=1 //! mycall, hiscall, RRR|73|RR73
|
|
if (iaptype==6)
|
|
{
|
|
for (int z = 0; z < 77; ++z)
|
|
llrd[z]=apmag*apbits_ft4[z];//llrd(1:77)=apmag*apbits(1:77)
|
|
}
|
|
}
|
|
}
|
|
for (int z = 0; z < 2*ND; ++z)
|
|
llr[z]=llrd[z];
|
|
}
|
|
|
|
for (int z = 0; z < 174; ++z)
|
|
{
|
|
cw[z]=0;
|
|
if (z<120)
|
|
message91[z]=0;
|
|
}
|
|
double dmin=0.0;
|
|
|
|
int ndeep=2;
|
|
int maxosd=2;
|
|
if (fabs(nfqso-f1)<=napwid)
|
|
{
|
|
ndeep=2;
|
|
maxosd=3;
|
|
}
|
|
if (!doosd) maxosd = -1;
|
|
//ndeep=3;
|
|
//Keff=91
|
|
pomFt.decode174_91(llr,maxosd,ndeep,apmask,message91,cw,nharderror,dmin);//Keff,ntype,
|
|
//for (int z = 0; z < 77; ++z)//message77=message91(1:77)
|
|
//message77[z]=message91[z];
|
|
|
|
//if(sum(message77).eq.0) cycle
|
|
int c_m77 = 0;
|
|
for (int z = 0; z < 77; z++)
|
|
c_m77 +=message91[z];
|
|
if (c_m77==0) continue;
|
|
/*int c_cw = 0;
|
|
for (int z = 0; z < 174; z++)
|
|
{
|
|
if (cw[z]==0)// 3*ND=174
|
|
c_cw++;
|
|
}
|
|
if (c_cw==174) continue;*/
|
|
|
|
if ( nharderror>=0 )
|
|
{
|
|
for (int z = 0; z < 77; z++)
|
|
message91[z]=fmod(message91[z]+rvec[z],2); //! remove rvec scrambling
|
|
|
|
bool unpk77_success=false;
|
|
QString message = TGenFt4->unpack77(message91,unpk77_success);
|
|
if (!unpk77_success) break;//2.43 exit
|
|
|
|
//if(message.isEmpty()) {qDebug()<<"EMPTY MSG"<<message; /*continue;*/}//2.21
|
|
if (unpk77_success && dosubtract)
|
|
{
|
|
//int i3=4*message77[74] + 2*message77[75] + message77[76];
|
|
int i4tone[120];
|
|
TGenFt4->make_c77_i4tone(message91,i4tone);
|
|
|
|
double dt=(double)ibest/666.67;//750.0;
|
|
subtractft4(dd,i4tone,f1,dt);
|
|
//qDebug()<<"subtractft4"<<message<<dt<<f1<<ipass<<i3;
|
|
}
|
|
//qDebug()<<"mmm"<<message;
|
|
bool ldupe=false;
|
|
for (int z = 0; z < ndecodes; z++)//maxcand
|
|
{//do i=1,ndecodes
|
|
if (decodes[z]==message)
|
|
{
|
|
ldupe=true;
|
|
break;
|
|
}
|
|
}
|
|
if (ldupe) break;// inportent for subtract
|
|
|
|
decodes[ndecodes]=message;
|
|
if (ndecodes < (maxcand-1)) ndecodes++;
|
|
|
|
double xsnr = 0.0;
|
|
if (snr>0.0) xsnr=10*log10(snr)-14.8;
|
|
else xsnr=-21.0;
|
|
|
|
int nsnr=(int)(fmax(-21.0,xsnr));
|
|
if (nsnr > 49) nsnr = 49; //2.31
|
|
|
|
float xdt=(float)ibest/666.67 - 0.5;
|
|
|
|
if (f_only_one_color)
|
|
{
|
|
f_only_one_color = false;
|
|
emit EmitBackColor();
|
|
}
|
|
/*if (s_time4_prev!=s_time4)
|
|
{
|
|
s_time4_prev=s_time4;
|
|
emit EmitBackColor();
|
|
}*/
|
|
/*if (f_new_p)
|
|
{
|
|
f_new_p = false;
|
|
emit EmitBackColor();
|
|
}*/
|
|
|
|
//double dmin = 0.0;
|
|
//double qual=1.0-((double)nharderror+dmin)/60.0;
|
|
//float qual=1.0-((float)nharderror)/60.0;
|
|
float qual=1.0-((float)nharderror+(float)dmin)/60.0;
|
|
if (qual<0.001) qual=0.0;//no show -0.0
|
|
|
|
QString str_iaptype = "";
|
|
if (qual<0.17) str_iaptype = "? ";
|
|
if (iaptype!=0) str_iaptype.append("AP");
|
|
str_iaptype.append(QString("%1").arg(iaptype));
|
|
|
|
int df_hv = f1-s_nftx4;//2.12
|
|
QString sdtx = QString("%1").arg(xdt,0,'f',1);
|
|
if (sdtx=="-0.0") sdtx="0.0";//2.08 remove -0.0 exception
|
|
|
|
QStringList list;
|
|
list <<s_time4<<QString("%1").arg(nsnr)
|
|
<<sdtx<<QString("%1").arg((int)df_hv)
|
|
<<message<<str_iaptype
|
|
<<QString("%1").arg(qual,0,'f',1)
|
|
<<QString("%1").arg((int)f1);
|
|
|
|
emit EmitDecodetTextFt(list);//1.27 psk rep fopen bool true false no file open
|
|
have_dec = true;
|
|
|
|
/*//if (abs((int)s_nfqso65-(int)f1)<=10 || list.at(4).contains(s_MyCall))
|
|
//"TA2NC RR73; SP9HWY <LZ2HV> +00"
|
|
//"TU; LZ2HV SP9HWY R 589 NY"
|
|
//"TU; LZ2HV SP9HWY R 589 0001"
|
|
QString tstr = list.at(4);
|
|
tstr.remove("<");//v2 protokol 2.02
|
|
tstr.remove(">");//v2 protokol 2.02
|
|
QStringList tlist = tstr.split(" ");
|
|
bool fmyc = false;
|
|
for (int x = 0; x<tlist.count(); ++x)
|
|
{
|
|
if (tlist.at(x)==s_MyBaseCall4 || tlist.at(x)==s_MyCall4)//2.02
|
|
{
|
|
fmyc = true;
|
|
break;
|
|
}
|
|
}
|
|
if (abs((int)nfqso_calc-(int)f1)<=10 || fmyc)
|
|
emit EmitDecodetTextRxFreq(list,true);//1.60= true no emit other infos from decode list2 s_fopen*/
|
|
|
|
break;//exit
|
|
}
|
|
} //!Sequence estimation
|
|
if (nharderror>=0) break;
|
|
} //!3 DT segments
|
|
} //!Candidate list
|
|
} //!Subtraction loop
|
|
}
|
|
|