diff --git a/lib/q65_decode.f90 b/lib/q65_decode.f90 index 4269a3cc8..86d9264ab 100644 --- a/lib/q65_decode.f90 +++ b/lib/q65_decode.f90 @@ -146,6 +146,10 @@ contains endif endif call timer('q65loops',0) +! call q65_loops(c00,nutc,npts/2,nsps/2,nmode,mode65,nsubmode, & +! nFadingModel,ndepth,jpk0,xdt,f0,width,iaptype,apmask,apsymbols, & +! snr1,xdt1,f1,snr2,irc,dat4) +! baud rate required to compute B90TS later call q65_loops(c00,nutc,npts/2,nsps/2,nmode,mode65,nsubmode, & nFadingModel,ndepth,jpk0,xdt,f0,width,iaptype,apmask,apsymbols, & codewords,snr1,xdt1,f1,snr2,irc,dat4) diff --git a/lib/qra/q65/q65.c b/lib/qra/q65/q65.c index 03b5219f5..c91571ba6 100644 --- a/lib/qra/q65/q65.c +++ b/lib/qra/q65/q65.c @@ -277,9 +277,9 @@ int q65_esnodb(const q65_codec_ds *pCodec, float *pEsNodB, const int *ydec, cons // Symbol time interval in seconds #define TS_QRA64 0.576 -#define TS_Q65 0.640 +// #define TS_Q65 0.640 // T/R = 60 s // The tables are computed assuming that the bin spacing is that of QRA64, that's to say -// 1/Ts = 12000/6912 Hz, but in q65 Ts is longer (0.640 s) and the table index +// 1/Ts = 12000/6912 Hz, but in Q65 Ts depends on the T/R interval and the table index // corresponding to a given B90 must be scaled appropriately. // See below. @@ -287,7 +287,7 @@ int q65_intrinsics_fastfading(q65_codec_ds *pCodec, float *pIntrinsics, // intrinsic symbol probabilities output const float *pInputEnergies, // received energies input const int submode, // submode idx (0=A ... 4=E) - const float B90, // spread bandwidth (90% fractional energy) + const float B90Ts, // spread bandwidth (90% fractional energy) const int fadingModel) // 0=Gaussian 1=Lorentzian fade model { int n, k, j; @@ -295,26 +295,26 @@ int q65_intrinsics_fastfading(q65_codec_ds *pCodec, int hidx, hlen, hhsz, hlast; const float *hptr; float fTemp, fNoiseVar, sumix, maxlogp; - float EsNoMetric; + float EsNoMetric,B90; float *weight; const float *pCurSym, *pCurBin; float *pCurIx; +// printf("pcodec=%08x submode=%d fadingmodel=%d B90Ts=%f\n",pcodec, submode,fadingModel, B90Ts); + if (pCodec==NULL) return Q65_DECODE_INVPARAMS; // invalid pCodec pointer + if (submode<0 || submode>4) return Q65_DECODE_INVPARAMS; // invalid submode - // As the symbol duration in q65 is longer than in QRA64 the fading tables continue - // to be valid if the B90 parameter is scaled by the actual symbol rate + // As the symbol duration in q65 is different than in QRA64, + // the fading tables continue to be valid if the B90Ts parameter + // is properly scaled to the QRA64 symbol interval // Compute index to most appropriate weighting function coefficients - hidx = (int)(logf(B90*TS_Q65/TS_QRA64)/logf(1.09f) - 0.499f); - -// if (hidx<0 || hidx > 64) -// // index of weighting function out of range -// // B90 out of range -// return q65_DECODE_INVPARAMS; + B90 = B90Ts/TS_QRA64; + hidx = (int)(logf(B90)/logf(1.09f) - 0.499f); // Unlike in QRA64 we accept any B90, anyway limiting it to // the extreme cases (0.9 to 210 Hz approx.) diff --git a/lib/qra/q65/q65.h b/lib/qra/q65/q65.h index bd80a934c..2e764a32b 100644 --- a/lib/qra/q65/q65.h +++ b/lib/qra/q65/q65.h @@ -69,7 +69,7 @@ int q65_intrinsics_fastfading(q65_codec_ds *pCodec, float *pIntrinsics, // intrinsic symbol probabilities output const float *pInputEnergies, // received energies input const int submode, // submode idx (0=A ... 4=E) - const float B90, // spread bandwidth (90% fractional energy) + const float B90Ts, // normalized spread bandwidth (90% fractional energy) const int fadingModel); // 0=Gaussian 1=Lorentzian fade model diff --git a/lib/qra/q65/q65_loops.f90 b/lib/qra/q65/q65_loops.f90 index 5f680f18a..72eade730 100644 --- a/lib/qra/q65/q65_loops.f90 +++ b/lib/qra/q65/q65_loops.f90 @@ -85,7 +85,8 @@ subroutine q65_loops(c00,nutc,npts2,nsps,mode,mode64,nsubmode,nFadingModel, & if(b90.gt.230.0) cycle ! if(b90.lt.0.15*width) exit call timer('q65_intr',0) - call q65_intrinsics_ff(s3,nsubmode,b90,nFadingModel,s3prob) + b90ts = b90/baud + call q65_intrinsics_ff(s3,nsubmode,b90ts,nFadingModel,s3prob) call timer('q65_intr',1) if(iaptype.eq.4) then call timer('q65_apli',0) diff --git a/lib/qra/q65/q65_subs.c b/lib/qra/q65/q65_subs.c index 688ef899a..9f29da01c 100644 --- a/lib/qra/q65/q65_subs.c +++ b/lib/qra/q65/q65_subs.c @@ -46,7 +46,7 @@ void q65_enc_(int x[], int y[]) q65_encode(&codec,y,x); } -void q65_intrinsics_ff_(float s3[], int* submode, float* B90, +void q65_intrinsics_ff_(float s3[], int* submode, float* B90Ts, int* fadingModel, float s3prob[]) { @@ -69,7 +69,7 @@ void q65_intrinsics_ff_(float s3[], int* submode, float* B90, } first=0; } - rc = q65_intrinsics_fastfading(&codec,s3prob,s3,*submode,*B90,*fadingModel); + rc = q65_intrinsics_fastfading(&codec,s3prob,s3,*submode,*B90Ts,*fadingModel); if(rc<0) { printf("error in q65_intrinsics()\n"); exit(0); diff --git a/lib/sync_q65.f90 b/lib/sync_q65.f90 index 68cb5d919..1839aab0a 100644 --- a/lib/sync_q65.f90 +++ b/lib/sync_q65.f90 @@ -13,8 +13,10 @@ subroutine sync_q65(iwave,nmax,mode65,nsps,nfqso,ntol,xdt,f0,snr1,width) ! snr1 Relative SNR of sync signal parameter (NSTEP=8) !Step size nsps/NSTEP + character*37 msg,msgsent integer*2 iwave(0:nmax-1) !Raw data integer isync(22) !Indices of sync symbols + integer itone(85) real, allocatable :: s1(:,:) !Symbol spectra, quarter-symbol steps real, allocatable :: ccf(:,:) !CCF(freq,lag) real, allocatable :: ccf1(:) !CCF(freq) at best lag @@ -112,7 +114,7 @@ subroutine sync_q65(iwave,nmax,mode65,nsps,nfqso,ntol,xdt,f0,snr1,width) enddo f0=nfqso + ipk*df xdt=jpk*dtstep - + sq=0. nsq=0 do j=lag1,lag2 @@ -144,5 +146,69 @@ subroutine sync_q65(iwave,nmax,mode65,nsps,nfqso,ntol,xdt,f0,snr1,width) enddo width=i*1.414*df - return +!### Experimental: + nQSOprogress=3 + if(nQSOprogress.lt.1) go to 900 +! "Deep Likelihood" decode attempt + do imsg=1,3 + ccf=0. + msg='K1ABC W9XYZ RRR' + if(imsg.eq.2) msg='K1ABC W9XYZ RR73' + if(imsg.eq.3) msg='K1ABC W9XYZ 73' + call genq65(msg,0,msgsent,itone,i3,n3) + + do lag=lag1,lag2 + do k=1,85 + j=j0 + NSTEP*(k-1) + 1 + lag + if(j.ge.1 .and. j.le.jz) then + do i=-ia,ia + ii=i0+2*itone(k)+i + ccf(i,lag)=ccf(i,lag) + s1(ii,j) + enddo + endif + enddo + enddo + + ic=ntol/df + ccfmax=0. + ipk=0 + jpk=0 + do i=-ic,ic + do j=lag1,lag2 + if(ccf(i,j).gt.ccfmax) then + ipk=i + jpk=j + ccfmax=ccf(i,j) + endif + enddo + enddo + f0a=nfqso + ipk*df + xdta=jpk*dtstep + + sq=0. + nsq=0 + do j=lag1,lag2 + if(abs(j-jpk).gt.6) then + sq=sq + ccf(ipk,j)**2 + nsq=nsq+1 + endif + enddo + rms=sqrt(sq/nsq) + smax=ccf(ipk,jpk) + snr1a=smax/rms + write(57,3001) imsg,xdt,xdta,f0,f0a,snr1,snr1a +3001 format(i1,6f8.2) + + do j=lag1,lag2 + write(55,3055) j,j*dtstep,ccf(ipk,j)/rms +3055 format(i5,f8.3,f10.3) + enddo + + do i=-ia,ia + write(56,3056) i*df,ccf(i,jpk)/rms +3056 format(2f10.3) + enddo + enddo + +900 return end subroutine sync_q65