From c176572ec00d19c487813035d8a38cb4c621beaa Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Sat, 4 Jul 2020 09:15:57 -0500 Subject: [PATCH] Add options for sub-symbol integration for sync and symbol estimation. --- CMakeLists.txt | 1 + lib/fst240/get_fst240_bitmetrics.f90 | 13 ++- lib/fst240/get_fst240_bitmetrics2.f90 | 131 +++++++++++++++++++++++++ lib/fst240_decode.f90 | 136 +++++++++++++++----------- 4 files changed, 218 insertions(+), 63 deletions(-) create mode 100644 lib/fst240/get_fst240_bitmetrics2.f90 diff --git a/CMakeLists.txt b/CMakeLists.txt index 99e160a4e..911425a5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -604,6 +604,7 @@ set (wsjt_FSRCS lib/fst240/gen_fst240wave.f90 lib/fst240/genfst240.f90 lib/fst240/get_fst240_bitmetrics.f90 + lib/fst240/get_fst240_bitmetrics2.f90 lib/fst240/ldpcsim240_101.f90 lib/fst240/ldpcsim240_74.f90 lib/fst240/osd240_101.f90 diff --git a/lib/fst240/get_fst240_bitmetrics.f90 b/lib/fst240/get_fst240_bitmetrics.f90 index 49f46f411..e82d73c99 100644 --- a/lib/fst240/get_fst240_bitmetrics.f90 +++ b/lib/fst240/get_fst240_bitmetrics.f90 @@ -1,4 +1,4 @@ -subroutine get_fst240_bitmetrics(cd,nss,hmod,nmax,bitmetrics,s4,badsync) +subroutine get_fst240_bitmetrics(cd,nss,hmod,nmax,nhicoh,bitmetrics,s4,badsync) include 'fst240_params.f90' complex cd(0:NN*nss-1) @@ -87,10 +87,13 @@ subroutine get_fst240_bitmetrics(cd,nss,hmod,nmax,bitmetrics,s4,badsync) do nseq=1,nmax !Try coherent sequences of 1, 2, and 4 symbols if(nseq.eq.1) nsym=1 if(nseq.eq.2) nsym=2 - if(nseq.eq.3) nsym=3 - if(nseq.eq.4) nsym=4 -! if(nseq.eq.3) nsym=4 -! if(nseq.eq.4) nsym=8 + if(nhicoh.eq.0) then + if(nseq.eq.3) nsym=3 + if(nseq.eq.4) nsym=4 + else + if(nseq.eq.3) nsym=4 + if(nseq.eq.4) nsym=8 + endif nt=4**nsym do ks=1,NN-nsym+1,nsym s2=0 diff --git a/lib/fst240/get_fst240_bitmetrics2.f90 b/lib/fst240/get_fst240_bitmetrics2.f90 new file mode 100644 index 000000000..7b86841ba --- /dev/null +++ b/lib/fst240/get_fst240_bitmetrics2.f90 @@ -0,0 +1,131 @@ +subroutine get_fst240_bitmetrics2(cd,nss,hmod,nsizes,bitmetrics,s4hmod,badsync) + + include 'fst240_params.f90' + complex cd(0:NN*nss-1) + complex csymb(nss) + complex, allocatable, save :: c1(:,:) ! ideal waveforms, 4 tones + complex cp(0:3) ! accumulated phase shift over symbol types 0:3 + complex csum,cterm + integer isyncword1(0:7),isyncword2(0:7) + integer graymap(0:3) + integer ip(1) + integer hmod + logical one(0:65535,0:15) ! 65536 8-symbol sequences, 16 bits + logical first + logical badsync + real bitmetrics(2*NN,4) + real s2(0:65535) + real s4(0:3,NN,4),s4hmod(0:3,NN) + data isyncword1/0,1,3,2,1,0,2,3/ + data isyncword2/2,3,1,0,3,2,0,1/ + data graymap/0,1,3,2/ + data first/.true./,nss0/-1/ + save first,one,cp,nss0 + + if(nss.ne.nss0 .and. allocated(c1)) deallocate(c1) + if(first .or. nss.ne.nss0) then + allocate(c1(nss,0:3)) + one=.false. + do i=0,65535 + do j=0,15 + if(iand(i,2**j).ne.0) one(i,j)=.true. + enddo + enddo + twopi=8.0*atan(1.0) + dphi=twopi*hmod/nss + do itone=0,3 + dp=(itone-1.5)*dphi + phi=0.0 + do j=1,nss + c1(j,itone)=cmplx(cos(phi),sin(phi)) + phi=mod(phi+dp,twopi) + enddo + cp(itone)=cmplx(cos(phi),sin(phi)) + enddo + first=.false. + endif + + do k=1,NN + i1=(k-1)*NSS + csymb=cd(i1:i1+NSS-1) + do itone=0,3 + s4(itone,k,1)=abs(sum(csymb*conjg(c1(:,itone)))) + s4(itone,k,2)=abs(sum(csymb( 1:nss/2)*conjg(c1( 1:nss/2,itone)))) + & + abs(sum(csymb(nss/2+1: nss)*conjg(c1(nss/2+1: nss,itone)))) + s4(itone,k,3)=abs(sum(csymb( 1: nss/4)*conjg(c1( 1: nss/4,itone)))) + & + abs(sum(csymb( nss/4+1: nss/2)*conjg(c1( nss/4+1: nss/2,itone)))) + & + abs(sum(csymb( nss/2+1:3*nss/4)*conjg(c1( nss/2+1:3*nss/4,itone)))) + & + abs(sum(csymb(3*nss/4+1: nss)*conjg(c1(3*nss/4+1: nss,itone)))) + s4(itone,k,4)=abs(sum(csymb( 1: nss/8)*conjg(c1( 1: nss/8,itone)))) + & + abs(sum(csymb( nss/8+1: nss/4)*conjg(c1( nss/8+1: nss/4,itone)))) + & + abs(sum(csymb( nss/4+1:3*nss/8)*conjg(c1( nss/4+1:3*nss/8,itone)))) + & + abs(sum(csymb(3*nss/8+1: nss/2)*conjg(c1(3*nss/8+1: nss/2,itone)))) + & + abs(sum(csymb( nss/2+1:5*nss/8)*conjg(c1( nss/2+1:5*nss/8,itone)))) + & + abs(sum(csymb(5*nss/8+1:3*nss/4)*conjg(c1(5*nss/8+1:3*nss/4,itone)))) + & + abs(sum(csymb(3*nss/4+1:7*nss/8)*conjg(c1(3*nss/4+1:7*nss/8,itone)))) + & + abs(sum(csymb(7*nss/8+1: nss)*conjg(c1(7*nss/8+1: nss,itone)))) + + enddo + enddo + +! Sync quality check + is1=0 + is2=0 + is3=0 + is4=0 + is5=0 + badsync=.false. + ibmax=0 + + is1=0; is2=0; is3=0; is4=0; is5=0 + do k=1,8 + ip=maxloc(s4(:,k,1)) + if(isyncword1(k-1).eq.(ip(1)-1)) is1=is1+1 + ip=maxloc(s4(:,k+38,1)) + if(isyncword2(k-1).eq.(ip(1)-1)) is2=is2+1 + ip=maxloc(s4(:,k+76,1)) + if(isyncword1(k-1).eq.(ip(1)-1)) is3=is3+1 + ip=maxloc(s4(:,k+114,1)) + if(isyncword2(k-1).eq.(ip(1)-1)) is4=is4+1 + ip=maxloc(s4(:,k+152,1)) + if(isyncword1(k-1).eq.(ip(1)-1)) is5=is5+1 + enddo + nsync=is1+is2+is3+is4+is5 !Number of correct hard sync symbols, 0-40 + badsync=.false. + + if(nsync .lt. 16) then + badsync=.true. + return + endif + + bitmetrics=0.0 + do nsub=1,nsizes + do ks=1,NN + s2=0 + do i=0,3 + s2(i)=s4(graymap(i),ks,nsub) + enddo + ipt=1+(ks-1)*2 + ibmax=1 + do ib=0,ibmax + bm=maxval(s2(0:3),one(0:3,ibmax-ib)) - & + maxval(s2(0:3),.not.one(0:3,ibmax-ib)) + if(ipt+ib.gt.2*NN) cycle + bitmetrics(ipt+ib,nsub)=bm + enddo + enddo + enddo + + call normalizebmet(bitmetrics(:,1),2*NN) + call normalizebmet(bitmetrics(:,2),2*NN) + call normalizebmet(bitmetrics(:,3),2*NN) + call normalizebmet(bitmetrics(:,4),2*NN) + +! Return the s4 array corresponding to N=1/hmod. Will be used for SNR calculation + if(hmod.eq.1) s4hmod(:,:)=s4(:,:,1) + if(hmod.eq.2) s4hmod(:,:)=s4(:,:,2) + if(hmod.eq.4) s4hmod(:,:)=s4(:,:,3) + if(hmod.eq.8) s4hmod(:,:)=s4(:,:,4) + return + +end subroutine get_fst240_bitmetrics2 diff --git a/lib/fst240_decode.f90 b/lib/fst240_decode.f90 index 8fca098e6..00dda3882 100644 --- a/lib/fst240_decode.f90 +++ b/lib/fst240_decode.f90 @@ -83,6 +83,8 @@ contains dxcall13=hiscall ! initialize for use in packjt77 mycall13=mycall + fMHz=10.0 + if(first) then mcq=2*mod(mcq+rvec(1:29),2)-1 mrrr=2*mod(mrrr+rvec(59:77),2)-1 @@ -217,7 +219,7 @@ contains if(ndepth.eq.3) then - nblock=1 + nblock=4 if(hmod.eq.1) nblock=4 ! number of block sizes to try jittermax=2 norder=3 @@ -252,6 +254,20 @@ contains itype2=2 endif + if(hmod.eq.1) then + if(fMHz.lt.2.0) then + nsyncoh=8 ! Use N=8 for sync + nhicoh=1 ! Use N=1,2,4,8 for symbol estimation + else + nsyncoh=4 ! Use N=4 for sync + nhicoh=0 ! Use N=1,2,3,4 for symbol estimation + endif + else + if(hmod.eq.2) nsyncoh=1 + if(hmod.eq.4) nsyncoh=1 + if(hmod.eq.8) nsyncoh=1 + endif + do iqorw=itype1,itype2 ! iqorw=1 for QSO mode and iqorw=2 for wspr-type messages if( iwspr.lt.2 ) then if( single_decode ) then @@ -278,10 +294,8 @@ contains ndecodes=0 decodes=' ' - isbest1=0 - isbest8=0 - fc21=0. - fc28=0. + isbest=0 + fc2=0. do icand=1,ncand fc0=candidates(icand,1) detmet=candidates(icand,2) @@ -308,47 +322,29 @@ contains ifhw=12 df=.1*baud else if(isync.eq.1) then - fc1=fc21 - if(hmod.eq.1) fc1=fc28 - is0=isbest1 - if(hmod.eq.1) is0=isbest8 + fc1=fc2 + is0=isbest ishw=4*hmod isst=1*hmod ifhw=7 df=.02*baud endif - smax1=0.0 - smax8=0.0 + smax=0.0 do if=-ifhw,ifhw fc=fc1+df*if do istart=max(1,is0-ishw),is0+ishw,isst - call sync_fst240(c2,istart,fc,hmod,1,nfft2,nss,fs2,sync1) - call sync_fst240(c2,istart,fc,hmod,8,nfft2,nss,fs2,sync8) - if(sync8.gt.smax8) then - fc28=fc - isbest8=istart - smax8=sync8 - endif - if(sync1.gt.smax1) then - fc21=fc - isbest1=istart - smax1=sync1 + call sync_fst240(c2,istart,fc,hmod,nsyncoh,nfft2,nss,fs2,sync) + if(sync.gt.smax) then + fc2=fc + isbest=istart + smax=sync endif enddo enddo enddo call timer('sync240 ',1) - if(smax8/smax1 .lt. 0.65 ) then - fc2=fc21 - isbest=isbest1 - njitter=2 - else - fc2=fc28 - isbest=isbest8 - njitter=2 - endif fc_synced = fc0 + fc2 dt_synced = (isbest-fs2)*dt2 !nominal dt is 1 second so frame starts at sample fs2 candidates(icand,3)=fc_synced @@ -387,6 +383,7 @@ contains fc_synced=candidates(icand,3) isbest=nint(candidates(icand,4)) xdt=(isbest-nspsec)/fs2 + if(ntrperiod.eq.15) xdt=(isbest-real(nspsec)/2.0)/fs2 call fst240_downsample(c_bigfft,nfft1,ndown,fc_synced,sigbw,c2) @@ -398,7 +395,11 @@ contains if(is0.lt.0) cycle cframe=c2(is0:is0+160*nss-1) bitmetrics=0 - call get_fst240_bitmetrics(cframe,nss,hmod,nblock,bitmetrics,s4,badsync) + if(hmod.eq.1) then + call get_fst240_bitmetrics(cframe,nss,hmod,nblock,nhicoh,bitmetrics,s4,badsync) + else + call get_fst240_bitmetrics2(cframe,nss,hmod,nblock,bitmetrics,s4,badsync) + endif if(badsync) cycle hbits=0 @@ -409,7 +410,7 @@ contains ns4=count(hbits(229:244).eq.(/1,1,1,0,0,1,0,0,1,0,1,1,0,0,0,1/)) ns5=count(hbits(305:320).eq.(/0,0,0,1,1,0,1,1,0,1,0,0,1,1,1,0/)) nsync_qual=ns1+ns2+ns3+ns4+ns5 - if(nsync_qual.lt. 46) cycle !### Value ?? ### +! if(nsync_qual.lt. 46) cycle !### Value ?? ### scalefac=2.83 llra( 1: 60)=bitmetrics( 17: 76, 1) @@ -529,7 +530,7 @@ contains do i=1,ndecodes if(decodes(i).eq.msg) idupe=1 enddo - if(idupe.eq.1) exit + if(idupe.eq.1) goto 2002 ndecodes=ndecodes+1 decodes(ndecodes)=msg @@ -554,9 +555,9 @@ contains nsnr=nint(xsnr) qual=0. fsig=fc_synced - 1.5*hmod*baud -!write(21,'(i6,7i6,f7.1,f9.2,f7.1,1x,f7.2,1x,f7.1,1x,a37)') & -! nutc,icand,itry,iaptype,ijitter,ntype,nsync_qual,nharderrors,dmin,sync,xsnr,xdt,fsig,msg -!flush(21) + write(21,'(i6,8i6,f7.1,f9.2,f7.1,1x,f7.2,1x,f7.1,1x,a37)') & + nutc,icand,itry,nsyncoh,iaptype,ijitter,ntype,nsync_qual,nharderrors,dmin,sync,xsnr,xdt,fsig,msg + flush(21) call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & iaptype,qual,ntrperiod,lwspr) goto 2002 @@ -637,28 +638,47 @@ contains s4=0.0 s5=0.0 - nsec=8/ncoh - do i=1,nsec - is=(i-1)*ncoh*nss - z1=0 - if(i1+is.ge.1) then - z1=sum(cd0(i1+is:i1+is+ncoh*nss-1)*conjg(csynct1(is+1:is+ncoh*nss))) - endif - z2=sum(cd0(i2+is:i2+is+ncoh*nss-1)*conjg(csynct2(is+1:is+ncoh*nss))) - z3=sum(cd0(i3+is:i3+is+ncoh*nss-1)*conjg(csynct1(is+1:is+ncoh*nss))) - z4=sum(cd0(i4+is:i4+is+ncoh*nss-1)*conjg(csynct2(is+1:is+ncoh*nss))) - z5=0 - if(i5+is+ncoh*nss-1.le.np) then - z5=sum(cd0(i5+is:i5+is+ncoh*nss-1)*conjg(csynct1(is+1:is+ncoh*nss))) - endif - s1=s1+abs(z1)/(8*nss) - s2=s2+abs(z2)/(8*nss) - s3=s3+abs(z3)/(8*nss) - s4=s4+abs(z4)/(8*nss) - s5=s5+abs(z5)/(8*nss) - enddo + if(ncoh.gt.0) then + nsec=8/ncoh + do i=1,nsec + is=(i-1)*ncoh*nss + z1=0 + if(i1+is.ge.1) then + z1=sum(cd0(i1+is:i1+is+ncoh*nss-1)*conjg(csynct1(is+1:is+ncoh*nss))) + endif + z2=sum(cd0(i2+is:i2+is+ncoh*nss-1)*conjg(csynct2(is+1:is+ncoh*nss))) + z3=sum(cd0(i3+is:i3+is+ncoh*nss-1)*conjg(csynct1(is+1:is+ncoh*nss))) + z4=sum(cd0(i4+is:i4+is+ncoh*nss-1)*conjg(csynct2(is+1:is+ncoh*nss))) + z5=0 + if(i5+is+ncoh*nss-1.le.np) then + z5=sum(cd0(i5+is:i5+is+ncoh*nss-1)*conjg(csynct1(is+1:is+ncoh*nss))) + endif + s1=s1+abs(z1)/(8*nss) + s2=s2+abs(z2)/(8*nss) + s3=s3+abs(z3)/(8*nss) + s4=s4+abs(z4)/(8*nss) + s5=s5+abs(z5)/(8*nss) + enddo + else + nsub=-ncoh + nps=nss/nsub + do i=1,8 + do isub=1,nsub + is=(i-1)*nss+(isub-1)*nps + if(i1+is.ge.1) then + s1=s1+abs(sum(cd0(i1+is:i1+is+nps-1)*conjg(csynct1(is+1:is+nps)))) + endif + s2=s2+abs(sum(cd0(i2+is:i2+is+nps-1)*conjg(csynct1(is+1:is+nps)))) + s3=s3+abs(sum(cd0(i3+is:i3+is+nps-1)*conjg(csynct1(is+1:is+nps)))) + s4=s4+abs(sum(cd0(i4+is:i4+is+nps-1)*conjg(csynct1(is+1:is+nps)))) + s5=0 + if(i5+is+ncoh*nss-1.le.np) then + s5=s5+abs(sum(cd0(i5+is:i5+is+nps-1)*conjg(csynct1(is+1:is+nps)))) + endif + enddo + enddo + endif sync = s1+s2+s3+s4+s5 - return end subroutine sync_fst240