WSJT-X/lib/sync24.f90

180 lines
4.6 KiB
Fortran

subroutine sync24(dat,jz,DFTolerance,NFreeze,MouseDF,mode,mode4, &
dtx,dfx,snrx,snrsync,ccfblue,ccfred1,flip,width)
! Synchronizes JT4 data, finding the best-fit DT and DF.
parameter (NFFTMAX=2520) !Max length of FFTs
parameter (NHMAX=NFFTMAX/2) !Max length of power spectra
parameter (NSMAX=525) !Max number of half-symbol steps
integer DFTolerance !Range of DF search
real dat(jz)
real psavg(NHMAX) !Average spectrum of whole record
real s2(NHMAX,NSMAX) !2d spectrum, stepped by half-symbols
real ccfblue(-5:540) !CCF with pseudorandom sequence
real ccfred(-450:450) !Peak of ccfblue, as function of freq
real ccfred1(-224:224) !Peak of ccfblue, as function of freq
real tmp(1260)
save
! Do FFTs of twice symbol length, stepped by half symbols. Note that
! we have already downsampled the data by factor of 2.
nsym=207
nfft=2520
nh=nfft/2
nq=nfft/4
nsteps=jz/nq - 1
df=0.5*11025.0/nfft
psavg(1:nh)=0.
do j=1,nsteps !Compute spectrum for each step, get average
k=(j-1)*nq + 1
call ps24(dat(k),nfft,s2(1,j))
psavg(1:nh)=psavg(1:nh) + s2(1:nh,j)
enddo
call flat1(psavg,s2,nh,nsteps,NHMAX,NSMAX) !Flatten spectra
! Set freq and lag ranges
famin=200.
fbmax=2700.
fa=famin
fb=fbmax
if(NFreeze.eq.1) then
fa=max(famin,1270.46+MouseDF-DFTolerance)
fb=min(fbmax,1270.46+MouseDF+DFTolerance)
else
fa=max(famin,1270.46+MouseDF-600)
fb=min(fbmax,1270.46+MouseDF+600)
endif
ia=fa/df
ib=fb/df
if(mode.eq.7) then
ia=ia - 3*mode4
ib=ib - 3*mode4
endif
i0=nint(1270.46/df)
lag1=-5
lag2=59
syncbest=-1.e30
syncbest2=-1.e30
ccfred=0.
do i=ia,ib !Find best frequency channel for CCF
call xcor24(s2,i,nsteps,nsym,lag1,lag2,mode4,ccfblue,ccf0,lagpk0,flip)
j=i-i0
if(mode.eq.7) j=j + 3*mode4
if(j.ge.-372 .and. j.le.372) ccfred(j)=ccf0
! Find rms of the CCF, without main peak
call slope(ccfblue(lag1),lag2-lag1+1,lagpk0-lag1+1.0)
sync=abs(ccfblue(lagpk0))
ppmax=psavg(i)-1.0
! Find best sync value
if(sync.gt.syncbest2) then
ipk2=i
lagpk2=lagpk0
syncbest2=sync
endif
! We are most interested if snrx will be more than -30 dB.
if(ppmax.gt.0.2938) then !Corresponds to snrx.gt.-30.0
if(sync.gt.syncbest) then
ipk=i
lagpk=lagpk0
syncbest=sync
endif
endif
enddo
! If we found nothing with snrx > -30 dB, take the best sync that *was* found.
if(syncbest.lt.-10.) then
ipk=ipk2
lagpk=lagpk2
syncbest=syncbest2
endif
dfx=(ipk-i0)*df
if(mode.eq.7) dfx=dfx + 3*mode4*df
! Peak up in time, at best whole-channel frequency
call xcor24(s2,ipk,nsteps,nsym,lag1,lag2,mode4,ccfblue,ccfmax,lagpk,flip)
xlag=lagpk
if(lagpk.gt.lag1 .and. lagpk.lt.lag2) then
call peakup(ccfblue(lagpk-1),ccfmax,ccfblue(lagpk+1),dx2)
xlag=lagpk+dx2
endif
! Find rms of the CCF, without the main peak
call slope(ccfblue(lag1),lag2-lag1+1,xlag-lag1+1.0)
sq=0.
nsq=0
do lag=lag1,lag2
if(abs(lag-xlag).gt.2.0) then
sq=sq+ccfblue(lag)**2
nsq=nsq+1
endif
enddo
rms=sqrt(sq/nsq)
snrsync=abs(ccfblue(lagpk))/rms - 1.1 !Empirical
dt=2.0/11025.0
istart=xlag*nq
dtx=istart*dt
snrx=-99.0
ppmax=psavg(ipk)-1.0
if(ppmax.gt.0.0001) then
snrx=db(ppmax*df/2500.0) + 7.5 !Empirical
if(mode.eq.7) snrx=snrx + 3.0 !Empirical
endif
if(snrx.lt.-33.0) snrx=-33.0
! Compute width of sync tone to outermost -3 dB points
i1=max(-450,ia-i0)
i2=min(450,ib-i0)
call pctile(ccfred(i1),i2-i1+1,45,base)
jpk=ipk-i0
if(abs(jpk).gt.450) then
print*,'sync24 a:',jpk,ipk,i0
snrsync=0.
go to 999
else
stest=base + 0.5*(ccfred(jpk)-base) ! -3 dB
endif
do i=-10,0
if(jpk+i.ge.-371) then
if(ccfred(jpk+i).gt.stest) go to 30
endif
enddo
i=0
30 continue
if(abs(jpk+i-1).gt.450 .or. abs(jpk+i).gt.450) then
print*,'sync24 b:',jpk,i
else
x1=i-0.5
endif
do i=10,0,-1
if(jpk+i.le.371) then
if(ccfred(jpk+i).gt.stest) go to 32
endif
enddo
i=0
32 x2=i+0.5
width=x2-x1
if(width.gt.1.2) width=sqrt(width**2 - 1.44)
width=df*width
width=max(0.0,min(99.0,width))
do i=-224,224
ccfred1(i)=ccfred(i)
enddo
999 return
end subroutine sync24