192 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			192 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								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
							 |