2016-01-11 10:00:43 -05:00
|
|
|
module jt65_decode
|
|
|
|
|
|
|
|
integer, parameter :: NSZ=3413, NZMAX=60*12000, NFFT=1000
|
|
|
|
|
|
|
|
type :: jt65_decoder
|
|
|
|
procedure(jt65_decode_callback), pointer :: callback => null()
|
|
|
|
contains
|
|
|
|
procedure :: decode
|
|
|
|
end type jt65_decoder
|
|
|
|
|
|
|
|
!
|
|
|
|
! Callback function to be called with each decode
|
|
|
|
!
|
|
|
|
abstract interface
|
|
|
|
subroutine jt65_decode_callback (this, utc, sync, snr, dt, freq, drift, &
|
|
|
|
decoded, ft, qual, candidates, tries, total_min, hard_min, aggression)
|
|
|
|
import jt65_decoder
|
|
|
|
implicit none
|
|
|
|
class(jt65_decoder), intent(inout) :: this
|
|
|
|
integer, intent(in) :: utc
|
|
|
|
real, intent(in) :: sync
|
|
|
|
integer, intent(in) :: snr
|
|
|
|
real, intent(in) :: dt
|
|
|
|
integer, intent(in) :: freq
|
|
|
|
integer, intent(in) :: drift
|
|
|
|
character(len=22), intent(in) :: decoded
|
|
|
|
integer, intent(in) :: ft
|
|
|
|
integer, intent(in) :: qual
|
|
|
|
integer, intent(in) :: candidates
|
|
|
|
integer, intent(in) :: tries
|
|
|
|
integer, intent(in) :: total_min
|
|
|
|
integer, intent(in) :: hard_min
|
|
|
|
integer, intent(in) :: aggression
|
|
|
|
end subroutine jt65_decode_callback
|
|
|
|
end interface
|
|
|
|
|
|
|
|
contains
|
|
|
|
|
|
|
|
subroutine decode(this,callback,dd0,npts,newdat,nutc,nf1,nf2,nfqso,ntol,nsubmode, &
|
|
|
|
minsync,nagain,n2pass,nrobust,ntrials,naggressive,ndepth, &
|
|
|
|
mycall,hiscall,hisgrid,nexp_decode)
|
|
|
|
|
|
|
|
! Process dd0() data to find and decode JT65 signals.
|
|
|
|
|
|
|
|
use timer_module, only: timer
|
|
|
|
|
|
|
|
include 'constants.f90'
|
|
|
|
|
|
|
|
class(jt65_decoder), intent(inout) :: this
|
|
|
|
procedure(jt65_decode_callback) :: callback
|
|
|
|
real, intent(in) :: dd0(NZMAX)
|
|
|
|
integer, intent(in) :: npts, nutc, nf1, nf2, nfqso, ntol &
|
|
|
|
, nsubmode, minsync, n2pass, ntrials, naggressive, ndepth &
|
|
|
|
, nexp_decode
|
|
|
|
logical, intent(in) :: newdat, nagain, nrobust
|
|
|
|
character(len=12), intent(in) :: mycall, hiscall
|
|
|
|
character(len=6), intent(in) :: hisgrid
|
|
|
|
|
|
|
|
real dd(NZMAX)
|
|
|
|
real ss(322,NSZ)
|
|
|
|
real savg(NSZ)
|
|
|
|
real a(5)
|
|
|
|
character*22 decoded,decoded0
|
|
|
|
type candidate
|
|
|
|
real freq
|
|
|
|
real dt
|
|
|
|
real sync
|
|
|
|
end type candidate
|
|
|
|
type(candidate) ca(300)
|
|
|
|
type accepted_decode
|
|
|
|
real freq
|
|
|
|
real dt
|
|
|
|
real sync
|
|
|
|
character*22 decoded
|
|
|
|
end type accepted_decode
|
|
|
|
type(accepted_decode) dec(50)
|
|
|
|
logical :: first_time, robust
|
|
|
|
|
|
|
|
integer h0(0:11),d0(0:11),ne(0:11)
|
|
|
|
real r0(0:11)
|
|
|
|
common/decstats/ntry65a,ntry65b,n65a,n65b,num9,numfano
|
|
|
|
common/steve/thresh0
|
|
|
|
common/test000/ncandidates,nhard_min,nsoft_min,nera_best,nrtt1000, &
|
|
|
|
ntotal_min,ntry,nq1000,npp1 !### TEST ONLY ###
|
|
|
|
|
|
|
|
! 0 1 2 3 4 5 6 7 8 9 10 11
|
|
|
|
data h0/41,42,43,43,44,45,46,47,48,48,49,49/
|
|
|
|
data d0/71,72,73,74,76,77,78,80,81,82,83,83/
|
|
|
|
|
|
|
|
! 0 1 2 3 4 5 6 7 8 9 10 11
|
|
|
|
data r0/0.70,0.72,0.74,0.76,0.78,0.80,0.82,0.84,0.86,0.88,0.90,0.90/
|
|
|
|
save
|
|
|
|
|
|
|
|
this%callback => callback
|
|
|
|
first_time=newdat
|
|
|
|
robust=nrobust
|
|
|
|
dd=dd0
|
|
|
|
ndecoded=0
|
|
|
|
do ipass=1,n2pass ! 2-pass decoding loop
|
|
|
|
first_time=.true.
|
|
|
|
if(ipass.eq.1) then !first-pass parameters
|
|
|
|
thresh0=2.5
|
|
|
|
nsubtract=1
|
|
|
|
elseif( ipass.eq.2 ) then !second-pass parameters
|
|
|
|
thresh0=2.5
|
|
|
|
nsubtract=0
|
|
|
|
endif
|
|
|
|
if(n2pass.lt.2) nsubtract=0
|
|
|
|
|
|
|
|
! if(newdat) then
|
|
|
|
call timer('symsp65 ',0)
|
|
|
|
ss=0.
|
|
|
|
call symspec65(dd,npts,ss,nhsym,savg) !Get normalized symbol spectra
|
|
|
|
call timer('symsp65 ',1)
|
|
|
|
! endif
|
|
|
|
nfa=nf1
|
|
|
|
nfb=nf2
|
|
|
|
if(naggressive.gt.0 .and. ntol.lt.1000) then
|
|
|
|
nfa=max(200,nfqso-ntol)
|
|
|
|
nfb=min(4000,nfqso+ntol)
|
|
|
|
thresh0=1.0
|
|
|
|
endif
|
|
|
|
|
|
|
|
! robust = .false.: use float ccf. Only if ncand>50 fall back to robust (1-bit) ccf
|
|
|
|
! robust = .true. : use only robust (1-bit) ccf
|
|
|
|
ncand=0
|
|
|
|
if(.not.robust) then
|
|
|
|
call timer('sync65 ',0)
|
|
|
|
call sync65(ss,nfa,nfb,naggressive,ntol,nhsym,ca,ncand,0)
|
|
|
|
call timer('sync65 ',1)
|
|
|
|
endif
|
|
|
|
if(ncand.gt.50) robust=.true.
|
|
|
|
if(robust) then
|
|
|
|
ncand=0
|
|
|
|
call timer('sync65 ',0)
|
|
|
|
call sync65(ss,nfa,nfb,naggressive,ntol,nhsym,ca,ncand,1)
|
|
|
|
call timer('sync65 ',1)
|
|
|
|
endif
|
|
|
|
|
|
|
|
call fqso_first(nfqso,ntol,ca,ncand)
|
|
|
|
|
|
|
|
nvec=ntrials
|
|
|
|
if(ncand.gt.75) then
|
|
|
|
! write(*,*) 'Pass ',ipass,' ncandidates too large ',ncand
|
|
|
|
nvec=100
|
|
|
|
endif
|
|
|
|
|
|
|
|
df=12000.0/NFFT !df = 12000.0/8192 = 1.465 Hz
|
|
|
|
mode65=2**nsubmode
|
|
|
|
nflip=1 !### temporary ###
|
|
|
|
nqd=0
|
|
|
|
decoded0=""
|
|
|
|
freq0=0.
|
|
|
|
|
|
|
|
do icand=1,ncand
|
|
|
|
freq=ca(icand)%freq
|
|
|
|
dtx=ca(icand)%dt
|
|
|
|
sync1=ca(icand)%sync
|
|
|
|
if(ipass.eq.1) ntry65a=ntry65a + 1
|
|
|
|
if(ipass.eq.2) ntry65b=ntry65b + 1
|
|
|
|
call timer('decod65a',0)
|
|
|
|
call decode65a(dd,npts,first_time,nqd,freq,nflip,mode65,nvec, &
|
|
|
|
naggressive,ndepth,mycall,hiscall,hisgrid,nexp_decode, &
|
|
|
|
sync2,a,dtx,nft,qual,nhist,decoded)
|
|
|
|
call timer('decod65a',1)
|
|
|
|
n=naggressive
|
|
|
|
rtt=0.001*nrtt1000
|
|
|
|
if(nft.lt.2) then
|
|
|
|
if(nhard_min.gt.50) cycle
|
|
|
|
if(nhard_min.gt.h0(n)) cycle
|
|
|
|
if(ntotal_min.gt.d0(n)) cycle
|
|
|
|
if(rtt.gt.r0(n)) cycle
|
|
|
|
endif
|
|
|
|
|
|
|
|
! !### Suppress false decodes in crowded HF bands ###
|
|
|
|
! if(naggressive.eq.0 .and. ntrials.le.10000) then
|
|
|
|
! if(ntry.eq.ntrials) then
|
|
|
|
! if(nhard_min.ge.42 .or. ntotal_min.ge.71) cycle
|
|
|
|
! endif
|
|
|
|
! endif
|
|
|
|
if(decoded.eq.decoded0 .and. abs(freq-freq0).lt. 3.0 .and. &
|
|
|
|
minsync.ge.0) cycle !Don't display dupes
|
|
|
|
if(decoded.ne.' ' .or. minsync.lt.0) then
|
|
|
|
if( nsubtract .eq. 1 ) then
|
|
|
|
call timer('subtr65 ',0)
|
|
|
|
call subtract65(dd,npts,freq,dtx)
|
|
|
|
call timer('subtr65 ',1)
|
|
|
|
endif
|
|
|
|
nfreq=nint(freq+a(1))
|
|
|
|
ndrift=nint(2.0*a(2))
|
|
|
|
s2db=10.0*log10(sync2) - 35 !### empirical ###
|
|
|
|
nsnr=nint(s2db)
|
|
|
|
if(nsnr.lt.-30) nsnr=-30
|
|
|
|
if(nsnr.gt.-1) nsnr=-1
|
|
|
|
|
|
|
|
ndupe=0 ! de-dedupe
|
|
|
|
do i=1, ndecoded
|
|
|
|
if(decoded==dec(i)%decoded) then
|
|
|
|
ndupe=1
|
|
|
|
exit
|
|
|
|
endif
|
|
|
|
enddo
|
|
|
|
if(ndupe.ne.1 .or. minsync.lt.0) then
|
|
|
|
if(ipass.eq.1) n65a=n65a + 1
|
|
|
|
if(ipass.eq.2) n65b=n65b + 1
|
|
|
|
ndecoded=ndecoded+1
|
|
|
|
dec(ndecoded)%freq=freq+a(1)
|
|
|
|
dec(ndecoded)%dt=dtx
|
|
|
|
dec(ndecoded)%sync=sync2
|
|
|
|
dec(ndecoded)%decoded=decoded
|
|
|
|
nqual=min(qual,9999.0)
|
|
|
|
! if(nqual.gt.10) nqual=10
|
|
|
|
if (associated(this%callback)) then
|
|
|
|
call this%callback(nutc,sync1,nsnr,dtx-1.0,nfreq,ndrift,decoded &
|
|
|
|
,nft,nqual,ncandidates,ntry,ntotal_min,nhard_min,naggressive)
|
|
|
|
end if
|
|
|
|
endif
|
|
|
|
decoded0=decoded
|
|
|
|
freq0=freq
|
|
|
|
if(decoded0.eq.' ') decoded0='*'
|
|
|
|
endif
|
|
|
|
enddo !candidate loop
|
|
|
|
if(ndecoded.lt.1) exit
|
|
|
|
enddo !two-pass loop
|
|
|
|
|
|
|
|
return
|
|
|
|
end subroutine decode
|
|
|
|
|
|
|
|
end module jt65_decode
|