From fc040d435a8217fea77f39b513bce685846cd1f9 Mon Sep 17 00:00:00 2001 From: Joe Taylor <joe@princeton.edu> Date: Wed, 4 Jan 2023 12:02:10 -0500 Subject: [PATCH] Sort out some stuff having to do with multiple decodes in Q65 mode. --- lib/q65_decode.f90 | 16 +++++++++++-- lib/qra/q65/q65.f90 | 57 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/lib/q65_decode.f90 b/lib/q65_decode.f90 index 515cdab6e..0834395bb 100644 --- a/lib/q65_decode.f90 +++ b/lib/q65_decode.f90 @@ -70,6 +70,7 @@ contains character*80 fmt integer*2 iwave(NMAX) !Raw data real, allocatable :: dd(:) !Raw data + real f0decodes(100) integer dat4(13) !Decoded message as 12 6-bit integers integer dgen(13) logical lclearave,lnewdat0,lapcqonly,unpk77_success @@ -83,8 +84,13 @@ contains call sec0(0,tdecode) ndecodes=0 decodes=' ' + f0decodes=0. nfa=nfa0 nfb=nfb0 + if(single_decode) then + nfa=nfqso-ntol + nfb=nfqso+ntol + endif nqd=nqd0 lnewdat=lnewdat0 max_drift=max_drift0 @@ -169,8 +175,6 @@ contains call q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, & emedelay,xdt,f0,snr1,width,dat4,snr2,idec,stageno) call timer('q65_dec0',1) -! write(*,3001) '=a',nfqso,ntol,ndepth,xdt,f0,idec -!3001 format(a2,3i5,f7.2,f7.1,i5) if(idec.ge.0) then dtdec=xdt !We have a q3 or q0 decode at nfqso @@ -280,6 +284,7 @@ contains if(idupe.eq.0) then ndecodes=min(ndecodes+1,100) decodes(ndecodes)=decoded + f0decodes(ndecodes)=f0dec call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2) nsnr=nint(snr2) call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, & @@ -317,6 +322,10 @@ contains snr1=candidates(icand,1) xdt= candidates(icand,2) f0 = candidates(icand,3) + do i=1,ndecodes + fdiff=f0-f0decodes(i) + if(fdiff.gt.-baud*mode_q65 .and. fdiff.lt.65*baud*mode_q65) go to 800 + enddo jpk0=(xdt+1.0)*6000 !Index of nominal start of signal if(ntrperiod.le.30) jpk0=(xdt+0.5)*6000 !For shortest sequences if(jpk0.lt.0) jpk0=0 @@ -365,6 +374,7 @@ contains if(idupe.eq.0) then ndecodes=min(ndecodes+1,100) decodes(ndecodes)=decoded + f0decodes(ndecodes)=f0dec call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2) nsnr=nint(snr2) call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, & @@ -373,6 +383,7 @@ contains if(iand(ndepth,128).ne.0 .and. .not.lagain .and. & int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg call sec0(1,tdecode) + ios=1 ! open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown',& ! position='append',iostat=ios) if(ios.eq.0) then @@ -394,6 +405,7 @@ contains endif endif endif +800 continue enddo ! icand if(iavg.eq.0 .and.navg(iseq).ge.2 .and. iand(ndepth,16).ne.0) go to 50 900 return diff --git a/lib/qra/q65/q65.f90 b/lib/qra/q65/q65.f90 index aa104bbfc..fa548e18f 100644 --- a/lib/qra/q65/q65.f90 +++ b/lib/qra/q65/q65.f90 @@ -148,15 +148,15 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, & ii1=max(1,i0-64) ii2=i0-65+LL call pctile(s1(ii1:ii2,1:jz),ii2-ii1+1*jz,45,base) - s1=s1/base +! s1=s1/base s1raw=s1 ! Apply fast AGC to the symbol spectra - s1max=20.0 !Empirical choice - do j=1,jz !### Maybe wrong way? ### - smax=maxval(s1(ii1:ii2,j)) - if(smax.gt.s1max) s1(ii1:ii2,j)=s1(ii1:ii2,j)*s1max/smax - enddo +! s1max=20.0 !Empirical choice +! do j=1,jz !### Maybe wrong way? ### +! smax=maxval(s1(ii1:ii2,j)) +! if(smax.gt.s1max) s1(ii1:ii2,j)=s1(ii1:ii2,j)*s1max/smax +! enddo dat4=0 if(ncw.gt.0 .and. iavg.le.1) then @@ -219,7 +219,7 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, & width=df*(i2-i1) if(ncw.eq.0) ccf1=0. call q65_write_red(iz,xdt,ccf2_avg,ccf2) !### Need this call for WSJT-X - + if(idec.lt.0 .and. (iavg.eq.0 .or. iavg.eq.2)) then call q65_dec_q012(s3,LL,snr2,dat4,idec,decoded) endif @@ -489,11 +489,14 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, & real ccf2(iz) !Orange sync curve real, allocatable :: xdt2(:) real, allocatable :: s1avg(:) + real, allocatable :: ccf_lag(:) integer, allocatable :: indx(:) + integer ipk1(1) allocate(xdt2(iz)) allocate(s1avg(iz)) allocate(indx(iz)) + allocate(ccf_lag(lag1:lag2)) ia=max(nfa,100)/df ib=min(nfb,4900)/df @@ -507,12 +510,15 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, & s1avg(i)=sum(s1(i,1:jz)) enddo + call pctile(s1avg(ia:ib),ib-ia+1,40,base0) ccfbest=0. ibest=0 lagpk=0 lagbest=0 idrift_best=0 do i=ia,ib + stest=s1avg(i)/(1.015*base0) + if(stest.lt.1.4) cycle ccfmax=0. do lag=lag1,lag2 do idrift=-max_drift,max_drift @@ -533,6 +539,40 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, & endif enddo ! idrift enddo ! lag + +! Look at SNR on the "blue curve" + idrift=idrift_max + do lag=lag1,lag2 + ccft=0. + do kk=1,22 + k=isync(kk) + ii=i + nint(idrift*(k-43)/85.0) + if(ii.lt.1 .or. ii.gt.iz) cycle + n=NSTEP*(k-1) + 1 + j=n+lag+j0 + if(j.ge.1 .and. j.le.jz) ccft=ccft + s1(ii,j) + enddo ! kk + ccf_lag(lag)=ccft - (22.0/jz)*s1avg(i) + enddo + + pk=maxval(ccf_lag) + ipk1=maxloc(ccf_lag) + lag0=ipk1(1)-1+lag1 + xsum=0. + sq=0. + nsum=0 + do j=lag1,lag2 + if(abs(j-lag0).gt.7) then + xsum=xsum+ccf_lag(j) + sq=sq+ccf_lag(j)**2 + nsum=nsum+1 + endif + enddo + ave=xsum/nsum + rms=sqrt(sq/nsum - ave*ave) + snr=(pk-ave)/rms + if(snr.lt.5.0) cycle !Blue SNR must be at least 5 + ccf2(i)=ccfmax xdt2(i)=lagpk*dtstep if(ccfmax.gt.ccfbest .and. abs(i*df-nfqso).le.ftol) then @@ -554,8 +594,6 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, & ! Save parameters for best candidates jzz=ib-ia+1 - call pctile(ccf2(ia:ib),jzz,40,base) - ccf2=ccf2/base call indexx(ccf2(ia:ib),jzz,indx) ncand=0 maxcand=20 @@ -563,7 +601,6 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, & k=jzz-j+1 if(k.lt.1 .or. k.gt.iz) cycle i=indx(k)+ia-1 - if(ccf2(i).lt.3.3) exit !Candidate limit f=i*df i3=max(1, i-mode_q65) i4=min(iz,i+mode_q65)