Work in progress: Q65-30B candidate selection now basically working.

This commit is contained in:
Joe Taylor 2023-12-05 15:11:57 -05:00
parent 76e28298a3
commit 7348bc323e
4 changed files with 81 additions and 29 deletions

View File

@ -6,6 +6,7 @@ subroutine getcand2(ss,savg0,nts_q65,nagain,ntol,f0_selected,cand,ncand)
real :: snr !Relative S/N of sync detection
real :: f !Freq of sync tone, 0 to 96000 Hz
real :: xdt !DT of matching sync pattern, -1.0 to +4.0 s
integer :: ntrperiod !60 for Q65-60x, 30 for Q65-30x
end type candidate
parameter (NFFT=32768) !FFTs done in symspec()
@ -48,20 +49,57 @@ subroutine getcand2(ss,savg0,nts_q65,nagain,ntol,f0_selected,cand,ncand)
i0=ipk1(1) + i - 1 !Index of local peak in savg()
fpk=0.001*i0*df !Frequency of peak (kHz)
! Check to see if sync tone is present.
call q65_sync(ss,i0,nts_q65,sync_ok,snr_sync,xdt)
if(.not.sync_ok) cycle
ntrperiod=60
iseq=0
call q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr_sync,xdt)
if(sync_ok) then
! Sync tone is present, we have a candidate for decoding
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
write(*,3301) j,fpk+80-48,xdt,snr_sync
3301 format(i3,f8.1,f8.2,f8.1)
if(j.ge.MAX_CANDIDATES) exit
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
cand(j)%ntrperiod=ntrperiod
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
! write(*,3301) j,fpk+80-48,xdt,snr_sync,ntrperiod,iseq
3301 format(i3,f8.1,f8.2,f8.1,2i5)
if(j.ge.MAX_CANDIDATES) exit
endif
ntrperiod=30
! if(ntrperiod.eq.30) cycle
call q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr_sync,xdt)
if(sync_ok) then
! Sync tone is present, we have a candidate for decoding
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
cand(j)%ntrperiod=ntrperiod
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
! write(*,3301) j,fpk+80-48,xdt,snr_sync,ntrperiod,iseq
if(j.ge.MAX_CANDIDATES) exit
endif
iseq=1
call q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr_sync,xdt)
if(sync_ok) then
! Sync tone is present, we have a candidate for decoding
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
cand(j)%ntrperiod=ntrperiod
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
! write(*,3301) j,fpk+80-48,xdt,snr_sync,ntrperiod,iseq
if(j.ge.MAX_CANDIDATES) exit
endif
enddo
ncand=j !Total number of candidates found

View File

@ -1,4 +1,4 @@
subroutine q65_sync(ss,i0,nts_q65,sync_ok,snr,xdt)
subroutine q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr,xdt)
! Test for presence of Q65 sync tone
@ -7,26 +7,36 @@ subroutine q65_sync(ss,i0,nts_q65,sync_ok,snr,xdt)
real ss(373,NFFT) !Symbol spectra
real ccf(0:LAGMAX) !The WSJT "blue curve", peak at DT
logical sync_ok
logical first
integer isync0(22),isync(22),ipk(1)
! Q65 sync symbols
data isync0/1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85/
sync_ok=.false.
! if(ntrperiod.ne.60) return
tstep=0.15 !0.5*tsym_Q65-30x, 0.25*tsys_Q65-60x
nfac=4
if(ntrperiod.eq.30) nfac=2
do i=1,22 !Expand sync stride for Q65-60x
isync(i)=4*(isync0(i)-1) + 1
isync(i)=nfac*(isync0(i)-1) + 1
enddo
m=nts_q65/2
if(ntrperiod.eq.30) m=nts_q65/4
i1=max(1,i0-m)
i2=min(NFFT,i0+m)
ccf=0.
do lag=0,LAGMAX !Search over range of DT
do j=1,22 !Test for Q65 sync
k=isync(j) + lag
ccf(lag)=ccf(lag) + sum(ss(k,i1:i2)) + sum(ss(k+1,i1:i2)) &
+ sum(ss(k+2,i1:i2)) + sum(ss(k+3,i1:i2))
k=isync(j) + lag + iseq*200
if(ntrperiod.eq.60) then
ccf(lag)=ccf(lag) + sum(ss(k,i1:i2)) + sum(ss(k+1,i1:i2)) &
+ sum(ss(k+2,i1:i2)) + sum(ss(k+3,i1:i2))
else
if(k.ge.372) cycle
ccf(lag)=ccf(lag) + sum(ss(k,i1:i2)) + sum(ss(k+1,i1:i2))
endif
! Q: Should we use weighted sums, perhaps a Lorentzian peak?
enddo
enddo
@ -34,16 +44,20 @@ subroutine q65_sync(ss,i0,nts_q65,sync_ok,snr,xdt)
ipk=maxloc(ccf)
lagbest=ipk(1)-1
xdt=lagbest*tstep - 1.0
if(ntrperiod.eq.30) xd=xdt+0.6 !Why ???
xsum=0.
sq=0.
nsum=0
fpk=0.001*i0*96000.0/32768.0 + 32.0
do i=0,lagmax !Compute ave and rms of "blue curve"
if(abs(i-lagbest).gt.2) then
xsum=xsum+ccf(i)
sq=sq+ccf(i)**2
nsum=nsum+1
endif
write(40,3040) i,i*tstep-1.0,ccf(i),fpk
3040 format(i5,3f8.2)
enddo
ave=xsum/nsum
rms=sqrt(sq/nsum - ave*ave)

View File

@ -10,6 +10,7 @@ subroutine qmapa(dd,ss,savg,newdat,nutc,fcenter,ntol,nfa,nfb, &
real :: snr !Relative S/N of sync detection
real :: f !Freq of sync tone, 0 to 96000 Hz
real :: xdt !DT of matching sync pattern, -1.0 to +4.0 s
integer :: ntrperiod !60 for Q65-60x, 30 for Q65-30x
end type candidate
parameter (NFFT=32768) !Size of FFTs done in symspec()

View File

@ -26,20 +26,21 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
data rms/999.0/,k0/99999999/,nadjx/0/,nadjy/0/
save
hsym=0.15d0*96000.d0 !Samples per Q65-30x half-symbol
npts=2*hsym !Full Q65-30x symbol
if(k.gt.5751000) go to 999
if(k.lt.NFFT) then
if(k.lt.npts) then
ihsym=0
go to 999 !Wait for enough samples to start
endif
if(k0.eq.99999999) then
pi=4.0*atan(1.0)
do i=1,NFFT
w(i)=(sin(i*pi/NFFT))**2 !Window
enddo
! pi=4.0*atan(1.0)
! do i=1,NFFT
! w(i)=(sin(i*pi/NFFT))**2 !Window
! enddo
w=0.7 !Flat window
endif
hsym=0.15d0*96000.d0 !Samples per Q65-30x half-symbol
if(k.lt.k0) then
ts=1.d0 - hsym
savg=0.
@ -76,12 +77,9 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
k1=k1+kstep
enddo
npts=NFFT !Samples used in each half-symbol FFT
ts=ts+hsym
ja=ts !Index of first sample
jb=ja+npts-1 !Last sample
i=0
fac=0.0002
do j=ja,jb !Copy data into cx
@ -90,6 +88,7 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
i=i+1
cx(i)=fac*cmplx(x1,x2)
enddo
cx(npts+1:)=0.
if(nzap/178.lt.50 .and. (ndiskdat.eq.0 .or. ihsym.lt.280)) then
nsum=nblks*kstep - nzap