192 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Fortran
		
	
	
	
	
	
		
		
			
		
	
	
			192 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Fortran
		
	
	
	
	
	
|   | subroutine fast9(id2,narg,line)
 | ||
|  | 
 | ||
|  | ! Decoder for "fast9" modes, JT9E to JT9H.
 | ||
|  | 
 | ||
|  |   parameter (NMAX=30*12000,NSAVE=500)
 | ||
|  |   integer*2 id2(0:NMAX)
 | ||
|  |   integer narg(0:14)
 | ||
|  |   integer*1 i1SoftSymbols(207)
 | ||
|  |   integer*1 i1save(207,NSAVE)
 | ||
|  |   integer indx(NSAVE)
 | ||
|  |   integer*8 count0,count1,clkfreq
 | ||
|  |   real s1(720000)                      !To reserve space.  Logically s1(nq,jz)
 | ||
|  |   real s2(240,340)                     !Symbol spectra at quarter-symbol steps
 | ||
|  |   real ss2(0:8,85)                     !Folded symbol spectra
 | ||
|  |   real ss3(0:7,69)                     !Folded spectra without sync symbols
 | ||
|  |   real s(1500)
 | ||
|  |   real ccfsave(NSAVE)
 | ||
|  |   real t0save(NSAVE)
 | ||
|  |   real t1save(NSAVE)
 | ||
|  |   real freqSave(NSAVE)
 | ||
|  |   real t(6)
 | ||
|  |   character*22 msg                     !Decoded message
 | ||
|  |   character*80 line(100)
 | ||
|  |   data nsubmode0/-1/,ntot/0/
 | ||
|  |   save s1,nsubmode0,ntot
 | ||
|  | 
 | ||
|  | ! Parameters from GUI are in narg():
 | ||
|  |   nutc=narg(0)                         !UTC
 | ||
|  |   npts=min(narg(1),NMAX)               !Number of samples in id2 (12000 Hz)
 | ||
|  |   nsubmode=narg(2)                     !0=A 1=B 2=C 3=D 4=E 5=F 6=G 7=H
 | ||
|  |   if(nsubmode.lt.4) go to 900
 | ||
|  |   newdat=narg(3)                       !1==> new data, compute symbol spectra
 | ||
|  |   minsync=narg(4)                      !Lower sync limit
 | ||
|  |   npick=narg(5)
 | ||
|  |   t0=0.001*narg(6)
 | ||
|  |   t1=0.001*narg(7)
 | ||
|  |   maxlines=narg(8)                     !Max # of decodes to return to caller
 | ||
|  |   nmode=narg(9)
 | ||
|  |   nrxfreq=narg(10)                     !Targer Rx audio frequency (Hz)
 | ||
|  |   ntol=narg(11)                        !Search range, +/- ntol (Hz)
 | ||
|  | 
 | ||
|  |   tmid=npts*0.5/12000.0
 | ||
|  |   line(1:100)(1:1)=char(0)
 | ||
|  |   s=0
 | ||
|  |   s2=0
 | ||
|  |   nsps=60 * 2**(7-nsubmode)            !Samples per sysbol
 | ||
|  |   nfft=2*nsps                          !FFT size
 | ||
|  |   nh=nfft/2
 | ||
|  |   nq=nfft/4
 | ||
|  |   istep=nsps/4                         !Symbol spectra at quarter-symbol steps
 | ||
|  |   jz=npts/istep
 | ||
|  |   df=12000.0/nfft                      !FFT bin width
 | ||
|  |   db1=db(2500.0/df)
 | ||
|  |   nfa=max(200,nrxfreq-ntol)            !Lower frequency limit
 | ||
|  |   nfb=min(nrxfreq+ntol,2500)           !Upper frequency limit
 | ||
|  |   nline=0
 | ||
|  |   t=0.
 | ||
|  | 
 | ||
|  |   if(newdat.eq.1 .or. nsubmode.ne.nsubmode0) then
 | ||
|  |      call system_clock(count0,clkfreq)
 | ||
|  |      call spec9f(id2,npts,nsps,s1,jz,nq)          !Compute symbol spectra, s1 
 | ||
|  |      call system_clock(count1,clkfreq)
 | ||
|  |      t(1)=t(1)+float(count1-count0)/float(clkfreq)
 | ||
|  |   endif
 | ||
|  | 
 | ||
|  |   nsubmode0=nsubmode
 | ||
|  |   tmsg=nsps*85.0/12000.0
 | ||
|  |   limit=2000
 | ||
|  |   nlen0=0
 | ||
|  |   i1=0
 | ||
|  |   i2=0
 | ||
|  |   ccfsave=0.
 | ||
|  |   do ilength=1,14
 | ||
|  |      nlen=1.4142136**(ilength-1)
 | ||
|  |      if(nlen.gt.jz/340) nlen=jz/340
 | ||
|  |      if(nlen.eq.nlen0) cycle
 | ||
|  |      nlen0=nlen
 | ||
|  | 
 | ||
|  |      db0=db(float(nlen))
 | ||
|  |      jlen=nlen*340
 | ||
|  |      jstep=jlen/4                      !### Is this about right? ###
 | ||
|  |      if(nsubmode.ge.6) jstep=jlen/2
 | ||
|  | 
 | ||
|  |      do ja=1,jz-jlen,jstep
 | ||
|  |         jb=ja+jlen-1
 | ||
|  |         call system_clock(count0,clkfreq)
 | ||
|  |         call foldspec9f(s1,nq,jz,ja,jb,s2)        !Fold symbol spectra into s2
 | ||
|  |         call system_clock(count1,clkfreq)
 | ||
|  |         t(2)=t(2)+float(count1-count0)/float(clkfreq)
 | ||
|  | 
 | ||
|  | ! Find sync; put sync'ed symbol spectra into ss2 and ss3
 | ||
|  | ! Might want to do a peakup in DT and DF, then re-compute symbol spectra.
 | ||
|  | 
 | ||
|  |         call system_clock(count0,clkfreq)
 | ||
|  |         call sync9f(s2,nq,nfa,nfb,ss2,ss3,lagpk,ipk,ccfbest)
 | ||
|  |         call system_clock(count1,clkfreq)
 | ||
|  |         t(3)=t(3)+float(count1-count0)/float(clkfreq)
 | ||
|  | 
 | ||
|  |         i1=i1+1
 | ||
|  |         if(ccfbest.lt.30.0) cycle
 | ||
|  |         call system_clock(count0,clkfreq)
 | ||
|  |         call softsym9f(ss2,ss3,i1SoftSymbols)     !Compute soft symbols
 | ||
|  |         call system_clock(count1,clkfreq)
 | ||
|  |         t(4)=t(4)+float(count1-count0)/float(clkfreq)
 | ||
|  | 
 | ||
|  |         i2=i2+1
 | ||
|  |         ccfsave(i2)=ccfbest
 | ||
|  |         i1save(1:207,i2)=i1SoftSymbols
 | ||
|  |         t0=(ja-1)*istep/12000.0
 | ||
|  |         t1=(jb-1)*istep/12000.0
 | ||
|  |         t0save(i2)=t0
 | ||
|  |         t1save(i2)=t1
 | ||
|  |         freq=ipk*df
 | ||
|  |         freqSave(i2)=freq
 | ||
|  |      enddo
 | ||
|  |   enddo
 | ||
|  |   nsaved=i2
 | ||
|  | 
 | ||
|  |   ccfsave(1:nsaved)=-ccfsave(1:nsaved)
 | ||
|  |   call system_clock(count0,clkfreq)
 | ||
|  |   indx=0
 | ||
|  |   call indexx(ccfsave,nsaved,indx)
 | ||
|  |   call system_clock(count1,clkfreq)
 | ||
|  |   t(5)=t(5)+float(count1-count0)/float(clkfreq)
 | ||
|  | 
 | ||
|  |   ccfsave(1:nsaved)=-ccfsave(1:nsaved)
 | ||
|  | 
 | ||
|  |   do iter=1,2
 | ||
|  | !     do isave=1,nsaved
 | ||
|  |      do isave=1,50
 | ||
|  |         i2=indx(isave)
 | ||
|  |         if(i2.lt.1 .or. i2.gt.nsaved) cycle      !### Why needed? ###
 | ||
|  |         t0=t0save(i2)
 | ||
|  |         t1=t1save(i2)
 | ||
|  |         if(iter.eq.1 .and. t1.lt.tmid) cycle
 | ||
|  |         if(iter.eq.2 .and. t1.ge.tmid) cycle
 | ||
|  |         ccfbest=ccfsave(i2)
 | ||
|  |         i1SoftSymbols=i1save(1:207,i2)
 | ||
|  |         freq=freqSave(i2)
 | ||
|  |         call system_clock(count0,clkfreq)
 | ||
|  |         call jt9fano(i1SoftSymbols,limit,nlim,msg)      !Invoke Fano decoder
 | ||
|  |         call system_clock(count1,clkfreq)
 | ||
|  |         t(6)=t(6)+float(count1-count0)/float(clkfreq)
 | ||
|  | 
 | ||
|  |         i=t0*12000.0
 | ||
|  |         kz=(t1-t0)/0.02
 | ||
|  |         smax=0.
 | ||
|  |         do k=1,kz
 | ||
|  |            sq=0.
 | ||
|  |            do n=1,240
 | ||
|  |               i=i+1
 | ||
|  |               x=id2(i)
 | ||
|  |               sq=sq+x*x
 | ||
|  |            enddo
 | ||
|  |            s(k)=sq/240.
 | ||
|  |            smax=max(s(k),smax)
 | ||
|  |         enddo
 | ||
|  |         call pctile(s,kz,35,base)
 | ||
|  |         snr=smax/(1.1*base) - 1.0
 | ||
|  |         nsnr=-20
 | ||
|  |         if(snr.gt.0.0) nsnr=nint(db(snr))
 | ||
|  | 
 | ||
|  | !        write(72,3002) nutc,iter,isave,nlen,tmid,t0,t1,ccfbest,   &
 | ||
|  | !             nint(freq),nlim,msg
 | ||
|  | !3002    format(i6.6,i1,i4,i3,4f6.1,i5,i7,1x,a22)
 | ||
|  | 
 | ||
|  |         if(msg.ne.'                      ') then
 | ||
|  | 
 | ||
|  | ! Display multiple decodes only if they differ:
 | ||
|  |            do n=1,nline
 | ||
|  |               if(index(line(n),msg).gt.1) go to 100
 | ||
|  |            enddo
 | ||
|  | !### Might want to use decoded message to get a complete estimate of S/N.
 | ||
|  |            nline=nline+1
 | ||
|  |            write(line(nline),1000) nutc,nsnr,t0,nint(freq),msg,char(0)
 | ||
|  | 1000       format(i6.6,i4,f5.1,i5,1x,'@ ',1x,a22,a1)
 | ||
|  |            ntot=ntot+1
 | ||
|  | !           write(70,5001) nsaved,isave,nline,maxlines,ntot,nutc,msg
 | ||
|  | !5001       format(5i5,i7.6,1x,a22)
 | ||
|  |            if(nline.ge.maxlines) go to 900
 | ||
|  |         endif
 | ||
|  | 100     continue
 | ||
|  |      enddo
 | ||
|  |   enddo
 | ||
|  | 
 | ||
|  | 900 continue
 | ||
|  | !  write(*,6001) t,t(6)/sum(t)
 | ||
|  | !6001 format(7f10.3)
 | ||
|  | 
 | ||
|  |   return
 | ||
|  | end subroutine fast9
 |