Improving decoder performance

This commit is contained in:
Jordan Sherer 2020-04-30 22:48:20 -04:00
parent 1a10ab5d13
commit 59ce3b1118
5 changed files with 84 additions and 67 deletions

View File

@ -4,7 +4,7 @@ parameter (NCOSTAS=1) !Which JS8 Costas Arrays to use (1=origina
parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100, JZ=62) ! 50 Hz 6.250 baud 16 wpm -25.0dB (1.0Eb/N0) 12.64s parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100, JZ=62) ! 50 Hz 6.250 baud 16 wpm -25.0dB (1.0Eb/N0) 12.64s
parameter (AZ=12000.0/(1.0*NSPS)*0.8d0) !Dedupe overlap in Hz parameter (AZ=12000.0/(1.0*NSPS)*0.64d0) !Dedupe overlap in Hz
parameter (ASTART=0.5) !Start delay in seconds parameter (ASTART=0.5) !Start delay in seconds
parameter (ASYNCMIN=1.5) !Minimum Sync parameter (ASYNCMIN=1.5) !Minimum Sync

View File

@ -21,6 +21,7 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
real bmeta(3*ND),bmetb(3*ND),bmetap(3*ND) real bmeta(3*ND),bmetb(3*ND),bmetap(3*ND)
real llr(3*ND),llra(3*ND),llr0(3*ND),llr1(3*ND),llrap(3*ND) !Soft symbols real llr(3*ND),llra(3*ND),llr0(3*ND),llr1(3*ND),llrap(3*ND) !Soft symbols
real dd0(NMAX) real dd0(NMAX)
integer icos
integer*1 decoded(KK),decoded0(KK),apmask(3*ND),cw(3*ND) integer*1 decoded(KK),decoded0(KK),apmask(3*ND),cw(3*ND)
integer*1 msgbits(KK) integer*1 msgbits(KK)
integer apsym(KK) integer apsym(KK)
@ -34,6 +35,7 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
complex cd0(0:NP-1) complex cd0(0:NP-1)
complex ctwk(7*NSPS/NDOWN) complex ctwk(7*NSPS/NDOWN)
complex csymb(NDOWNSPS) complex csymb(NDOWNSPS)
complex cs(0:7, NN)
logical first,newdat,lsubtract,lapon,lapcqonly,nagain logical first,newdat,lsubtract,lapon,lapcqonly,nagain
equivalence (s1,s1sort) equivalence (s1,s1sort)
data mcq/1,1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1/ data mcq/1,1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1/
@ -100,7 +102,7 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
delfbest=0. delfbest=0.
ibest=0 ibest=0
if(NWRITELOG.eq.0) then if(NWRITELOG.eq.1) then
write(*,*) '<DecodeDebug> downsampling', f1, fs2, dt2 write(*,*) '<DecodeDebug> downsampling', f1, fs2, dt2
flush(6) flush(6)
endif endif
@ -120,7 +122,7 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
do idt=i0-NQSYMBOL,i0+NQSYMBOL !Search over +/- one quarter symbol do idt=i0-NQSYMBOL,i0+NQSYMBOL !Search over +/- one quarter symbol
call syncjs8d(cd0,icos,idt,ctwk,0,sync) call syncjs8d(cd0,icos,idt,ctwk,0,sync)
if(NWRITELOG.eq.0) then if(NWRITELOG.eq.1) then
write(*,*) '<DecodeDebug> ', 'idt', idt, 'sync', sync write(*,*) '<DecodeDebug> ', 'idt', idt, 'sync', sync
flush(6) flush(6)
endif endif
@ -131,7 +133,7 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
enddo enddo
xdt2=ibest*dt2 !Improved estimate for DT xdt2=ibest*dt2 !Improved estimate for DT
if(NWRITELOG.eq.0) then if(NWRITELOG.eq.1) then
write(*,*) '<DecodeDebug> ', 'xdt2', xdt2, 'ibest', ibest write(*,*) '<DecodeDebug> ', 'xdt2', xdt2, 'ibest', ibest
flush(6) flush(6)
endif endif
@ -149,7 +151,7 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
phi=mod(phi+dphi,twopi) phi=mod(phi+dphi,twopi)
enddo enddo
call syncjs8d(cd0,icos,i0,ctwk,1,sync) call syncjs8d(cd0,icos,i0,ctwk,1,sync)
if(NWRITELOG.eq.0) then if(NWRITELOG.eq.1) then
write(*,*) '<DecodeDebug> ', 'df', delf, 'sync', sync write(*,*) '<DecodeDebug> ', 'df', delf, 'sync', sync
flush(6) flush(6)
endif endif
@ -165,11 +167,11 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
f1=f1+delfbest !Improved estimate of DF f1=f1+delfbest !Improved estimate of DF
if(NWRITELOG.eq.0) then if(NWRITELOG.eq.0) then
write(*,*) '<DecodeDebug> ', 'twk', xdt, f1, smax write(*,*) '<DecodeDebug> twk', xdt, f1, smax
flush(6) flush(6)
endif endif
call syncjs8d(cd0,icos,i0,ctwk,2,sync) call syncjs8d(cd0,icos,i0,ctwk,0,sync)
j=0 j=0
do k=1,NN do k=1,NN
@ -206,6 +208,10 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
call timer('badnsync', 0) call timer('badnsync', 0)
nbadcrc=1 nbadcrc=1
call timer('badnsync', 1) call timer('badnsync', 1)
if(NWRITELOG.eq.0) then
write(*,*) '<DecodeDebug> bad sync', nsync
flush(6)
endif
return return
endif endif
@ -226,7 +232,8 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
i4=3*j-2 i4=3*j-2
i2=3*j-1 i2=3*j-1
i1=3*j i1=3*j
! Max amplitude
! Max amplitude
ps=s1(0:7,j) ps=s1(0:7,j)
r1=max(ps(1),ps(3),ps(5),ps(7))-max(ps(0),ps(2),ps(4),ps(6)) r1=max(ps(1),ps(3),ps(5),ps(7))-max(ps(0),ps(2),ps(4),ps(6))
r2=max(ps(2),ps(3),ps(6),ps(7))-max(ps(0),ps(1),ps(4),ps(5)) r2=max(ps(2),ps(3),ps(6),ps(7))-max(ps(0),ps(1),ps(4),ps(5))
@ -237,7 +244,8 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
bmetap(i4)=r4 bmetap(i4)=r4
bmetap(i2)=r2 bmetap(i2)=r2
bmetap(i1)=r1 bmetap(i1)=r1
! Max log metric
! Max log metric
psl=log(ps+1e-32) psl=log(ps+1e-32)
r1=max(psl(1),psl(3),psl(5),psl(7))-max(psl(0),psl(2),psl(4),psl(6)) r1=max(psl(1),psl(3),psl(5),psl(7))-max(psl(0),psl(2),psl(4),psl(6))
r2=max(psl(2),psl(3),psl(6),psl(7))-max(psl(0),psl(1),psl(4),psl(5)) r2=max(psl(2),psl(3),psl(6),psl(7))-max(psl(0),psl(1),psl(4),psl(5))
@ -246,64 +254,65 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
bmetb(i2)=r2 bmetb(i2)=r2
bmetb(i1)=r1 bmetb(i1)=r1
! Metric for Cauchy noise ! ! Metric for Cauchy noise
r1=log(ps(1)**3+ps(3)**3+ps(5)**3+ps(7)**3)- & ! r1=log(ps(1)**3+ps(3)**3+ps(5)**3+ps(7)**3)- &
log(ps(0)**3+ps(2)**3+ps(4)**3+ps(6)**3) ! log(ps(0)**3+ps(2)**3+ps(4)**3+ps(6)**3)
r2=log(ps(2)**3+ps(3)**3+ps(6)**3+ps(7)**3)- & ! r2=log(ps(2)**3+ps(3)**3+ps(6)**3+ps(7)**3)- &
log(ps(0)**3+ps(1)**3+ps(4)**3+ps(5)**3) ! log(ps(0)**3+ps(1)**3+ps(4)**3+ps(5)**3)
r4=log(ps(4)**3+ps(5)**3+ps(6)**3+ps(7)**3)- & ! r4=log(ps(4)**3+ps(5)**3+ps(6)**3+ps(7)**3)- &
log(ps(0)**3+ps(1)**3+ps(2)**3+ps(3)**3) ! log(ps(0)**3+ps(1)**3+ps(2)**3+ps(3)**3)
! Metric for AWGN, no fading !
bscale=2.5 ! ! Metric for AWGN, no fading
b0=bessi0(bscale*ps(0)) ! bscale=2.5
b1=bessi0(bscale*ps(1)) ! b0=bessi0(bscale*ps(0))
b2=bessi0(bscale*ps(2)) ! b1=bessi0(bscale*ps(1))
b3=bessi0(bscale*ps(3)) ! b2=bessi0(bscale*ps(2))
b4=bessi0(bscale*ps(4)) ! b3=bessi0(bscale*ps(3))
b5=bessi0(bscale*ps(5)) ! b4=bessi0(bscale*ps(4))
b6=bessi0(bscale*ps(6)) ! b5=bessi0(bscale*ps(5))
b7=bessi0(bscale*ps(7)) ! b6=bessi0(bscale*ps(6))
r1=log(b1+b3+b5+b7)-log(b0+b2+b4+b6) ! b7=bessi0(bscale*ps(7))
r2=log(b2+b3+b6+b7)-log(b0+b1+b4+b5) ! r1=log(b1+b3+b5+b7)-log(b0+b2+b4+b6)
r4=log(b4+b5+b6+b7)-log(b0+b1+b2+b3) ! r2=log(b2+b3+b6+b7)-log(b0+b1+b4+b5)
! r4=log(b4+b5+b6+b7)-log(b0+b1+b2+b3)
if(nQSOProgress .eq. 0 .or. nQSOProgress .eq. 5) then ! if(nQSOProgress .eq. 0 .or. nQSOProgress .eq. 5) then
! When bits 88:115 are set as ap bits, bit 115 lives in symbol 39 along ! ! When bits 88:115 are set as ap bits, bit 115 lives in symbol 39 along
! with no-ap bits 116 and 117. Take care of metrics for bits 116 and 117. ! ! with no-ap bits 116 and 117. Take care of metrics for bits 116 and 117.
if(j.eq.39) then ! take care of bits that live in symbol 39 ! if(j.eq.39) then ! take care of bits that live in symbol 39
if(apsym(28).lt.0) then ! if(apsym(28).lt.0) then
bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1)) ! bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2)) ! bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
else ! else
bmetap(i2)=max(ps(6),ps(7))-max(ps(4),ps(5)) ! bmetap(i2)=max(ps(6),ps(7))-max(ps(4),ps(5))
bmetap(i1)=max(ps(5),ps(7))-max(ps(4),ps(6)) ! bmetap(i1)=max(ps(5),ps(7))-max(ps(4),ps(6))
endif ! endif
endif ! endif
endif ! endif
! When bits 116:143 are set as ap bits, bit 115 lives in symbol 39 along ! ! When bits 116:143 are set as ap bits, bit 115 lives in symbol 39 along
! with ap bits 116 and 117. Take care of metric for bit 115. ! ! with ap bits 116 and 117. Take care of metric for bit 115.
if(j.eq.39) then ! take care of bit 115 ! if(j.eq.39) then ! take care of bit 115
iii=2*(apsym(29)+1)/2 + (apsym(30)+1)/2 ! known values of bits 116 & 117 ! iii=2*(apsym(29)+1)/2 + (apsym(30)+1)/2 ! known values of bits 116 & 117
if(iii.eq.0) bmetap(i4)=ps(4)-ps(0) ! if(iii.eq.0) bmetap(i4)=ps(4)-ps(0)
if(iii.eq.1) bmetap(i4)=ps(5)-ps(1) ! if(iii.eq.1) bmetap(i4)=ps(5)-ps(1)
if(iii.eq.2) bmetap(i4)=ps(6)-ps(2) ! if(iii.eq.2) bmetap(i4)=ps(6)-ps(2)
if(iii.eq.3) bmetap(i4)=ps(7)-ps(3) ! if(iii.eq.3) bmetap(i4)=ps(7)-ps(3)
endif ! endif
! bit 144 lives in symbol 48 and will be 1 if it is set as an ap bit. ! ! bit 144 lives in symbol 48 and will be 1 if it is set as an ap bit.
! take care of metrics for bits 142 and 143 ! ! take care of metrics for bits 142 and 143
if(j.eq.48) then ! bit 144 is always 1 ! if(j.eq.48) then ! bit 144 is always 1
bmetap(i4)=max(ps(5),ps(7))-max(ps(1),ps(3)) ! bmetap(i4)=max(ps(5),ps(7))-max(ps(1),ps(3))
bmetap(i2)=max(ps(3),ps(7))-max(ps(1),ps(5)) ! bmetap(i2)=max(ps(3),ps(7))-max(ps(1),ps(5))
endif ! endif
! bit 154 lives in symbol 52 and will be 0 if it is set as an ap bit ! ! bit 154 lives in symbol 52 and will be 0 if it is set as an ap bit
! take care of metrics for bits 155 and 156 ! ! take care of metrics for bits 155 and 156
if(j.eq.52) then ! bit 154 will be 0 if it is set as an ap bit. ! if(j.eq.52) then ! bit 154 will be 0 if it is set as an ap bit.
bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1)) ! bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2)) ! bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
endif ! endif
enddo enddo
@ -404,7 +413,7 @@ subroutine js8dec(dd0,icos,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly
niterations) niterations)
call timer('bpd174 ',1) call timer('bpd174 ',1)
if(NWRITELOG.eq.1) then if(NWRITELOG.eq.0) then
write(*,*) '<DecodeDebug> bpd174', ipass, nharderrors, dmin write(*,*) '<DecodeDebug> bpd174', ipass, nharderrors, dmin
flush(6) flush(6)
endif endif

View File

@ -12,6 +12,7 @@ subroutine syncjs8(dd,icos,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
real candidate0(3,200) real candidate0(3,200)
real candidate(3,200) real candidate(3,200)
real dd(NMAX) real dd(NMAX)
integer icos
integer jpeak(NH1) integer jpeak(NH1)
integer indx(NH1) integer indx(NH1)
integer ii(1) integer ii(1)
@ -52,6 +53,7 @@ subroutine syncjs8(dd,icos,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
enddo enddo
savg=savg + s(1:NH1,j) !Average spectrum savg=savg + s(1:NH1,j) !Average spectrum
enddo enddo
call baselinejs8(savg,nfa,nfb,sbase) call baselinejs8(savg,nfa,nfb,sbase)
ia=max(1,nint(nfa/df)) ! min freq ia=max(1,nint(nfa/df)) ! min freq
@ -147,7 +149,7 @@ subroutine syncjs8(dd,icos,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
if(k.ge.200) exit if(k.ge.200) exit
n=ia + indx(iz+1-i) - 1 n=ia + indx(iz+1-i) - 1
if(red(n).lt.syncmin.or.isnan(red(n))) exit if(red(n).lt.syncmin.or.isnan(red(n))) exit
if(NWRITELOG.eq.1) then if(NWRITELOG.eq.0) then
write(*,*) '<DecodeDebug> red candidate', red(n), n*df, (jpeak(n)-1)*tstep write(*,*) '<DecodeDebug> red candidate', red(n), n*df, (jpeak(n)-1)*tstep
flush(6) flush(6)
endif endif
@ -158,6 +160,11 @@ subroutine syncjs8(dd,icos,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
enddo enddo
ncand=k ncand=k
! Put nfqso at top of list
do i=1,ncand
if(abs(candidate0(1,i)-nfqso).lt.10.0) candidate0(1,i)=-candidate0(1,i)
enddo
! Save only the best of near-dupe freqs. ! Save only the best of near-dupe freqs.
do i=1,ncand do i=1,ncand
if(i.ge.2) then if(i.ge.2) then
@ -165,7 +172,7 @@ subroutine syncjs8(dd,icos,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
fdiff=abs(candidate0(1,i))-abs(candidate0(1,j)) fdiff=abs(candidate0(1,i))-abs(candidate0(1,j))
if(abs(fdiff).lt.AZ) then ! note: this dedupe difference is dependent on symbol spacing if(abs(fdiff).lt.AZ) then ! note: this dedupe difference is dependent on symbol spacing
if(NWRITELOG.eq.1) then if(NWRITELOG.eq.1) then
write(*,*) '<DecodeDebug> candidate dupe', fdiff, candidate0(1,i), candidate0(1,j) write(*,*) '<DecodeDebug> dupe', fdiff, candidate0(1,i), candidate0(3,i), candidate0(1,j), candidate0(3,j)
flush(6) flush(6)
endif endif
if(candidate0(3,i).ge.candidate0(3,j)) candidate0(3,j)=0. if(candidate0(3,i).ge.candidate0(3,j)) candidate0(3,j)=0.

View File

@ -10,6 +10,7 @@ subroutine syncjs8d(cd0,icos,i0,ctwk,itwk,sync)
complex ctwk(7*NDOWNSPS) complex ctwk(7*NDOWNSPS)
complex z1,z2,z3 complex z1,z2,z3
logical first logical first
integer icos
data first/.true./ data first/.true./
save first,twopi,csynca,csyncb,csyncc save first,twopi,csynca,csyncb,csyncc

View File

@ -101,7 +101,7 @@ contains
xdt=candidate(2,icand) xdt=candidate(2,icand)
xbase=10.0**(0.1*(sbase(nint(f1/(12000.0/NFFT1)))-40.0)) ! 3.125Hz xbase=10.0**(0.1*(sbase(nint(f1/(12000.0/NFFT1)))-40.0)) ! 3.125Hz
if(NWRITELOG.eq.1) then if(NWRITELOG.eq.0) then
write(*,*) '<DecodeDebug> candidate', icand, 'f1', f1, 'sync', sync, 'xdt', xdt, 'xbase', xbase write(*,*) '<DecodeDebug> candidate', icand, 'f1', f1, 'sync', sync, 'xdt', xdt, 'xbase', xbase
flush(6) flush(6)
endif endif