From f4e8ee4f75240075889d1d6dbab7983cd132b1cb Mon Sep 17 00:00:00 2001
From: Steven Franke <s.j.franke@icloud.com>
Date: Fri, 21 Oct 2022 13:47:12 -0500
Subject: [PATCH 1/5] Improve ft8 decoding on crowded bands.

---
 lib/ft8/sync8.f90  | 55 +++++++++++++++++++++++++++++++++++-----------
 lib/ft8_decode.f90 |  2 +-
 2 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/lib/ft8/sync8.f90 b/lib/ft8/sync8.f90
index 5ea2254ad..a29d1c72d 100644
--- a/lib/ft8/sync8.f90
+++ b/lib/ft8/sync8.f90
@@ -2,8 +2,9 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
      ncand,sbase)
 
   include 'ft8_params.f90'
-  parameter (MAXPRECAND=500)
-! Search over +/- 2.5s relative to 0.5s TX start time. 
+  parameter (MAXPRECAND=1000)
+! Maximum sync correlation lag +/- 2.5s relative to 0.5s TX start time. 
+! 2.5s / 0.16s/symbol * 4 samples/symbol = 62.5 lag steps in 2.5s
   parameter (JZ=62)                        
   complex cx(0:NH1)
   real s(NH1,NHSYM)
@@ -12,11 +13,14 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
   real x(NFFT1)
   real sync2d(NH1,-JZ:JZ)
   real red(NH1)
+  real red2(NH1)
   real candidate0(3,MAXPRECAND)
   real candidate(3,maxcand)
   real dd(NMAX)
   integer jpeak(NH1)
+  integer jpeak2(NH1)
   integer indx(NH1)
+  integer indx2(NH1)
   integer ii(1)
   integer icos7(0:6)
   data icos7/3,1,4,0,6,5,2/                   !Costas 7x7 tone pattern
@@ -82,11 +86,16 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
   enddo
 
   red=0.
+  red2=0.
+  mlag=20
+  mlag2=62
   do i=ia,ib
-     ii=maxloc(sync2d(i,-JZ:JZ)) - 1 - JZ
-     j0=ii(1)
-     jpeak(i)=j0
-     red(i)=sync2d(i,j0)
+     ii=maxloc(sync2d(i,-mlag:mlag)) - 1 - mlag 
+     jpeak(i)=ii(1)
+     red(i)=sync2d(i,jpeak(i))
+     ii=maxloc(sync2d(i,-mlag2:mlag2)) - 1 - mlag2
+     jpeak2(i)=ii(1)
+     red2(i)=sync2d(i,jpeak2(i))
   enddo
   iz=ib-ia+1
   call indexx(red(ia:ib),iz,indx)
@@ -100,23 +109,43 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
   if(ibase.gt.nh1) ibase=nh1
   base=red(ibase)
   red=red/base
+  call indexx(red2(ia:ib),iz,indx2)
+  ibase=indx2(npctile) - 1 + ia
+  if(ibase.lt.1) ibase=1
+  if(ibase.gt.nh1) ibase=nh1
+  base2=red2(ibase)
+  red2=red2/base2
 
   do i=1,min(MAXPRECAND,iz)
      n=ia + indx(iz+1-i) - 1
-     if(red(n).lt.syncmin.or.isnan(red(n)).or.k.eq.MAXPRECAND) exit
-     k=k+1
-     candidate0(1,k)=n*df
-     candidate0(2,k)=(jpeak(n)-0.5)*tstep
-     candidate0(3,k)=red(n)
+     if(k.ge.MAXPRECAND) exit
+     if( (red(n).ge.syncmin) .and. (.not.isnan(red(n))) ) then 
+        k=k+1
+        candidate0(1,k)=n*df
+        candidate0(2,k)=(jpeak(n)-0.5)*tstep
+        candidate0(3,k)=red(n)
+!write(*,*) i, k, candidate0(1,k), candidate0(2,k), candidate0(3,k)
+     endif
+     if(abs(jpeak2(n)-jpeak(n)).eq.0) cycle 
+     if(k.ge.MAXPRECAND) exit
+     if( (red2(n).ge.syncmin) .and. (.not.isnan(red2(n))) ) then
+        k=k+1
+        candidate0(1,k)=n*df
+        candidate0(2,k)=(jpeak2(n)-0.5)*tstep
+        candidate0(3,k)=red2(n)
+!write(*,*) i, k, candidate0(1,k), candidate0(2,k), candidate0(3,k)
+     endif
   enddo
   ncand=k
+!write(*,*) 'sync8: before deduping ',ncand
 
 ! Save only the best of near-dupe freqs.  
   do i=1,ncand
      if(i.ge.2) then
         do j=1,i-1
            fdiff=abs(candidate0(1,i))-abs(candidate0(1,j))
-           if(abs(fdiff).lt.4.0) then
+           tdiff=abs(candidate0(2,i)-candidate0(2,j))
+           if(abs(fdiff).lt.4.0.and.tdiff.lt.0.04) then
               if(candidate0(3,i).ge.candidate0(3,j)) candidate0(3,j)=0.
               if(candidate0(3,i).lt.candidate0(3,j)) candidate0(3,i)=0.
            endif
@@ -148,6 +177,6 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
      endif
   enddo
   ncand=k-1
-
+!write(*,*) 'sync8: after deduping ',ncand
   return
 end subroutine sync8
diff --git a/lib/ft8_decode.f90 b/lib/ft8_decode.f90
index b33629738..cc4b90a5a 100644
--- a/lib/ft8_decode.f90
+++ b/lib/ft8_decode.f90
@@ -44,7 +44,7 @@ contains
 
     class(ft8_decoder), intent(inout) :: this
     procedure(ft8_decode_callback) :: callback
-    parameter (MAXCAND=300,MAX_EARLY=100)
+    parameter (MAXCAND=500,MAX_EARLY=100)
     real*8 tsec,tseq
     real s(NH1,NHSYM)
     real sbase(NH1)

From 1bcad2eda5f43afa9af7a3b2233c3305107849ee Mon Sep 17 00:00:00 2001
From: Steven Franke <s.j.franke@icloud.com>
Date: Fri, 21 Oct 2022 13:50:01 -0500
Subject: [PATCH 2/5] Remove some debug statements.

---
 lib/ft8/sync8.f90 | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/lib/ft8/sync8.f90 b/lib/ft8/sync8.f90
index a29d1c72d..a4e74a161 100644
--- a/lib/ft8/sync8.f90
+++ b/lib/ft8/sync8.f90
@@ -124,7 +124,6 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
         candidate0(1,k)=n*df
         candidate0(2,k)=(jpeak(n)-0.5)*tstep
         candidate0(3,k)=red(n)
-!write(*,*) i, k, candidate0(1,k), candidate0(2,k), candidate0(3,k)
      endif
      if(abs(jpeak2(n)-jpeak(n)).eq.0) cycle 
      if(k.ge.MAXPRECAND) exit
@@ -133,11 +132,9 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
         candidate0(1,k)=n*df
         candidate0(2,k)=(jpeak2(n)-0.5)*tstep
         candidate0(3,k)=red2(n)
-!write(*,*) i, k, candidate0(1,k), candidate0(2,k), candidate0(3,k)
      endif
   enddo
   ncand=k
-!write(*,*) 'sync8: before deduping ',ncand
 
 ! Save only the best of near-dupe freqs.  
   do i=1,ncand
@@ -177,6 +174,5 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
      endif
   enddo
   ncand=k-1
-!write(*,*) 'sync8: after deduping ',ncand
   return
 end subroutine sync8

From 1bcbca4634251920bfa363f1f6c0abf948c539a1 Mon Sep 17 00:00:00 2001
From: Steven Franke <s.j.franke@icloud.com>
Date: Sun, 23 Oct 2022 16:48:21 -0500
Subject: [PATCH 3/5] FT8: Avoid a crash when a wav file is processed multiple
 times.

---
 lib/ft8/sync8.f90  | 2 +-
 lib/ft8_decode.f90 | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/ft8/sync8.f90 b/lib/ft8/sync8.f90
index a4e74a161..f048eb394 100644
--- a/lib/ft8/sync8.f90
+++ b/lib/ft8/sync8.f90
@@ -88,7 +88,7 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
   red=0.
   red2=0.
   mlag=20
-  mlag2=62
+  mlag2=JZ
   do i=ia,ib
      ii=maxloc(sync2d(i,-mlag:mlag)) - 1 - mlag 
      jpeak(i)=ii(1)
diff --git a/lib/ft8_decode.f90 b/lib/ft8_decode.f90
index cc4b90a5a..9804a6aea 100644
--- a/lib/ft8_decode.f90
+++ b/lib/ft8_decode.f90
@@ -80,7 +80,9 @@ contains
        dt0=0.
        f0=0.
     endif
-    if(nutc.ne.nutc0) then
+!Added 41==nzhsym to force a reset if the same wav file is processed twice or more in a row,
+!in which case nutc.eq.nutc0 and ndec(jseq,1) doesn't get reset
+    if(nzhsym==41 .or. (nutc.ne.nutc0)) then
 ! New UTC.  Move previously saved 'a7' data from k=1 to k=0
        iz=ndec(jseq,1)
        dt0(1:iz,jseq,0)  = dt0(1:iz,jseq,1)

From a99798fec474ca4b030453dc4284a6c6b68da27c Mon Sep 17 00:00:00 2001
From: Steven Franke <s.j.franke@icloud.com>
Date: Tue, 1 Nov 2022 17:58:36 -0500
Subject: [PATCH 4/5] Improve sync for early decodes.

---
 lib/ft8/sync8.f90  | 26 ++++++++++++++++++--------
 lib/ft8_decode.f90 |  6 ++++--
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/lib/ft8/sync8.f90 b/lib/ft8/sync8.f90
index f048eb394..d498e6f4c 100644
--- a/lib/ft8/sync8.f90
+++ b/lib/ft8/sync8.f90
@@ -1,4 +1,4 @@
-subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
+subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,nzhsym,candidate,   &
      ncand,sbase)
 
   include 'ft8_params.f90'
@@ -73,6 +73,10 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
               t0c=t0c + sum(s(i:i+nfos*6:nfos,m+nssy*72))
            endif
         enddo
+        t=ta+tb
+        t0=t0a+t0b
+        t0=(t0-t)/6.0
+        sync_ab=t/t0
         t=ta+tb+tc
         t0=t0a+t0b+t0c
         t0=(t0-t)/6.0
@@ -81,13 +85,20 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
         t0=t0b+t0c
         t0=(t0-t)/6.0
         sync_bc=t/t0
-        sync2d(i,j)=max(sync_abc,sync_bc)
+        if(j.le.-12) then
+           sync2d(i,j)=sync_bc
+        elseif(j.gt.-12 .and. j.lt. 49) then
+           if(nzhsym.eq.41) sync2d(i,j)=sync_ab
+           if(nzhsym.eq.50) sync2d(i,j)=max(sync_abc,sync_bc)
+        elseif(j.ge.49) then
+           sync2d(i,j)=sync_ab
+        endif
      enddo
   enddo
 
   red=0.
   red2=0.
-  mlag=20
+  mlag=10
   mlag2=JZ
   do i=ia,ib
      ii=maxloc(sync2d(i,-mlag:mlag)) - 1 - mlag 
@@ -110,12 +121,11 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate,   &
   base=red(ibase)
   red=red/base
   call indexx(red2(ia:ib),iz,indx2)
-  ibase=indx2(npctile) - 1 + ia
-  if(ibase.lt.1) ibase=1
-  if(ibase.gt.nh1) ibase=nh1
-  base2=red2(ibase)
+  ibase2=indx2(npctile) - 1 + ia
+  if(ibase2.lt.1) ibase2=1
+  if(ibase2.gt.nh1) ibase2=nh1
+  base2=red2(ibase2)
   red2=red2/base2
-
   do i=1,min(MAXPRECAND,iz)
      n=ia + indx(iz+1-i) - 1
      if(k.ge.MAXPRECAND) exit
diff --git a/lib/ft8_decode.f90 b/lib/ft8_decode.f90
index 9804a6aea..755157d7c 100644
--- a/lib/ft8_decode.f90
+++ b/lib/ft8_decode.f90
@@ -166,11 +166,13 @@ contains
 ! ndepth=2: subtraction, 3 passes, bp+osd (no subtract refinement) 
 ! ndepth=3: subtraction, 3 passes, bp+osd
     npass=3
-    if(ndepth.eq.1) npass=1
+    if(ndepth.eq.1) npass=2
     do ipass=1,npass
       newdat=.true.
       syncmin=1.3
       if(ndepth.le.2) syncmin=1.6
+!      if(nzhsym.eq.41.or.ipass.eq.1) syncmin=2.0
+      if(nzhsym.eq.41) syncmin=2.0
       if(ipass.eq.1) then
         lsubtract=.true.
         ndeep=ndepth
@@ -187,7 +189,7 @@ contains
       endif 
       call timer('sync8   ',0)
       maxc=MAXCAND
-      call sync8(dd,ifa,ifb,syncmin,nfqso,maxc,s,candidate,   &
+      call sync8(dd,ifa,ifb,syncmin,nfqso,maxc,nzhsym,candidate,   &
            ncand,sbase)
       call timer('sync8   ',1)
       do icand=1,ncand

From 2b0aa9325d1598714f0fca8b6e1693528fa92023 Mon Sep 17 00:00:00 2001
From: Steven Franke <s.j.franke@icloud.com>
Date: Mon, 7 Nov 2022 08:55:40 -0600
Subject: [PATCH 5/5] FT8: disable a7 decoding for Fox/Hound and when Enable AP
 is not checked.

---
 lib/ft8/ft8b.f90   | 8 +++++---
 lib/ft8_decode.f90 | 2 +-
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/lib/ft8/ft8b.f90 b/lib/ft8/ft8b.f90
index d96cbd9c7..30cd95c83 100644
--- a/lib/ft8/ft8b.f90
+++ b/lib/ft8/ft8b.f90
@@ -287,6 +287,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon,     &
 !          5 : WW_DIGI 
 !          6 : FOX
 !          7 : HOUND
+!          8 : ARRL_DIGI
 !
 ! Conditions that cause us to bail out of AP decoding
         if(ncontest.le.5 .and. iaptype.ge.3 .and. (abs(f1-nfqso).gt.napwid .and. abs(f1-nftx).gt.napwid) ) cycle
@@ -306,6 +307,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon,     &
            if(ncontest.eq.4) llrz(1:29)=apmag*mcqru(1:29)
            if(ncontest.eq.5) llrz(1:29)=apmag*mcqww(1:29)
            if(ncontest.eq.7) llrz(1:29)=apmag*mcq(1:29)
+           if(ncontest.eq.8) llrz(1:29)=apmag*mcqtest(1:29)
            apmask(75:77)=1 
            llrz(75:76)=apmag*(-1)
            llrz(77)=apmag*(+1)
@@ -313,7 +315,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon,     &
 
         if(iaptype.eq.2) then ! MyCall,???,??? 
            apmask=0
-           if(ncontest.eq.0.or.ncontest.eq.1.or.ncontest.eq.5) then
+           if(ncontest.eq.0.or.ncontest.eq.1.or.ncontest.eq.5.or.ncontest.eq.8) then
               apmask(1:29)=1  
               llrz(1:29)=apmag*apsym(1:29)
               apmask(75:77)=1 
@@ -353,7 +355,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon,     &
 
         if(iaptype.eq.3) then ! MyCall,DxCall,??? 
            apmask=0
-           if(ncontest.eq.0.or.ncontest.eq.1.or.ncontest.eq.2.or.ncontest.eq.5.or.ncontest.eq.7) then
+           if(ncontest.eq.0.or.ncontest.eq.1.or.ncontest.eq.2.or.ncontest.eq.5.or.ncontest.eq.7.or.ncontest.eq.8) then
               apmask(1:58)=1  
               llrz(1:58)=apmag*apsym
               apmask(75:77)=1 
@@ -379,7 +381,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon,     &
         if(iaptype.eq.5.and.ncontest.eq.7) cycle !Hound
         if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype.eq.6) then  
            apmask=0
-           if(ncontest.le.5 .or. (ncontest.eq.7.and.iaptype.eq.6)) then
+           if(ncontest.le.5 .or. (ncontest.eq.7.and.iaptype.eq.6) .or. ncontest.eq.8) then
               apmask(1:77)=1   ! mycall, hiscall, RRR|73|RR73
               llrz(1:58)=apmag*apsym
               if(iaptype.eq.4) llrz(59:77)=apmag*mrrr 
diff --git a/lib/ft8_decode.f90 b/lib/ft8_decode.f90
index 755157d7c..911ecb31e 100644
--- a/lib/ft8_decode.f90
+++ b/lib/ft8_decode.f90
@@ -241,7 +241,7 @@ contains
    if(nzhsym.lt.50) ndec_early=ndecodes
    
 900 continue
-   if(nzhsym.eq.50 .and. ndec(jseq,0).ge.1) then
+   if(lft8apon .and. ncontest.ne.6 .and. ncontest.ne.7 .and. nzhsym.eq.50 .and. ndec(jseq,0).ge.1) then
       newdat=.true.
       do i=1,ndec(jseq,0)
          if(f0(i,jseq,0).eq.-99.0) exit