233 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			233 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								subroutine ft8b(dd0,newdat,nfqso,f1,xdt,nharderrors,dmin,nbadcrc,message,xsnr)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  use timer_module, only: timer
							 | 
						||
| 
								 | 
							
								  include 'ft8_params.f90'
							 | 
						||
| 
								 | 
							
								  parameter(NRECENT=10,NP2=2812)
							 | 
						||
| 
								 | 
							
								  character message*22,msgsent*22
							 | 
						||
| 
								 | 
							
								  character*12 recent_calls(NRECENT)
							 | 
						||
| 
								 | 
							
								  real a(5)
							 | 
						||
| 
								 | 
							
								  real s1(0:7,ND),s2(0:7,NN)
							 | 
						||
| 
								 | 
							
								  real ps(0:7)
							 | 
						||
| 
								 | 
							
								  real rxdata(3*ND),llr(3*ND)               !Soft symbols
							 | 
						||
| 
								 | 
							
								  real dd0(15*12000)
							 | 
						||
| 
								 | 
							
								  integer*1 decoded(KK),apmask(3*ND),cw(3*ND)
							 | 
						||
| 
								 | 
							
								  integer itone(NN)
							 | 
						||
| 
								 | 
							
								  integer icos7(0:6)
							 | 
						||
| 
								 | 
							
								  complex cd0(3125)
							 | 
						||
| 
								 | 
							
								  complex csync(0:6,32)
							 | 
						||
| 
								 | 
							
								  complex ctwk(32)
							 | 
						||
| 
								 | 
							
								  complex csymb(32)
							 | 
						||
| 
								 | 
							
								  logical newdat,first
							 | 
						||
| 
								 | 
							
								  data icos7/2,5,6,0,4,1,3/
							 | 
						||
| 
								 | 
							
								  data first/.true./
							 | 
						||
| 
								 | 
							
								  save first,twopi,fs2,dt2,taus,baud,csync
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if( first ) then
							 | 
						||
| 
								 | 
							
								    twopi=8.0*atan(1.0)
							 | 
						||
| 
								 | 
							
								    fs2=12000.0/64.0
							 | 
						||
| 
								 | 
							
								    dt2=1/fs2
							 | 
						||
| 
								 | 
							
								    taus=32*dt2
							 | 
						||
| 
								 | 
							
								    baud=1/taus
							 | 
						||
| 
								 | 
							
								    do i=0,6
							 | 
						||
| 
								 | 
							
								      phi=0.0
							 | 
						||
| 
								 | 
							
								      dphi=twopi*icos7(i)*baud*dt2  
							 | 
						||
| 
								 | 
							
								      do j=1,32
							 | 
						||
| 
								 | 
							
								        csync(i,j)=cmplx(cos(phi),sin(phi))
							 | 
						||
| 
								 | 
							
								        phi=mod(phi+dphi,twopi)
							 | 
						||
| 
								 | 
							
								      enddo
							 | 
						||
| 
								 | 
							
								    enddo
							 | 
						||
| 
								 | 
							
								    first=.false.
							 | 
						||
| 
								 | 
							
								  endif  
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  max_iterations=40
							 | 
						||
| 
								 | 
							
								  norder=2
							 | 
						||
| 
								 | 
							
								!  if(abs(nfqso-f1).lt.10.0) norder=3
							 | 
						||
| 
								 | 
							
								  call timer('ft8_down',0)
							 | 
						||
| 
								 | 
							
								  call ft8_downsample(dd0,newdat,f1,cd0)
							 | 
						||
| 
								 | 
							
								  call timer('ft8_down',1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  i0=xdt*fs2
							 | 
						||
| 
								 | 
							
								  smax=0.0
							 | 
						||
| 
								 | 
							
								  do idt=i0-16,i0+16 
							 | 
						||
| 
								 | 
							
								    sync=0
							 | 
						||
| 
								 | 
							
								    do i=0,6
							 | 
						||
| 
								 | 
							
								      i1=idt+i*32
							 | 
						||
| 
								 | 
							
								      i2=i1+36*32
							 | 
						||
| 
								 | 
							
								      i3=i1+72*32
							 | 
						||
| 
								 | 
							
								      term1=0.0  ! this needs to be fixed...
							 | 
						||
| 
								 | 
							
								      term2=0.0
							 | 
						||
| 
								 | 
							
								      term3=0.0
							 | 
						||
| 
								 | 
							
								      if( i1.ge.1 .and. i1+31.le.NP2 )  &
							 | 
						||
| 
								 | 
							
								        term1=abs(sum(cd0(i1:i1+31)*conjg(csync(i,1:32))))
							 | 
						||
| 
								 | 
							
								      if( i2.ge.1 .and. i2+31.le.NP2 )  & 
							 | 
						||
| 
								 | 
							
								        term2=abs(sum(cd0(i2:i2+31)*conjg(csync(i,1:32))))
							 | 
						||
| 
								 | 
							
								      if( i3.ge.1 .and. i3+31.le.NP2 )  &
							 | 
						||
| 
								 | 
							
								        term3=abs(sum(cd0(i3:i3+31)*conjg(csync(i,1:32))))
							 | 
						||
| 
								 | 
							
								      sync=sync+term1+term2+term3
							 | 
						||
| 
								 | 
							
								    enddo
							 | 
						||
| 
								 | 
							
								    if( sync .gt. smax ) then
							 | 
						||
| 
								 | 
							
								      smax=sync
							 | 
						||
| 
								 | 
							
								      ibest=idt
							 | 
						||
| 
								 | 
							
								    endif
							 | 
						||
| 
								 | 
							
								  enddo
							 | 
						||
| 
								 | 
							
								  xdt2=ibest*dt2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! peak up the frequency
							 | 
						||
| 
								 | 
							
								  i0=xdt2*fs2
							 | 
						||
| 
								 | 
							
								  smax=0.0
							 | 
						||
| 
								 | 
							
								  do ifr=-5,5
							 | 
						||
| 
								 | 
							
								    delf=ifr*0.5
							 | 
						||
| 
								 | 
							
								    dphi=twopi*delf*dt2
							 | 
						||
| 
								 | 
							
								    phi=0.0
							 | 
						||
| 
								 | 
							
								    do i=1,32
							 | 
						||
| 
								 | 
							
								      ctwk(i)=cmplx(cos(phi),sin(phi))
							 | 
						||
| 
								 | 
							
								      phi=mod(phi+dphi,twopi)
							 | 
						||
| 
								 | 
							
								    enddo
							 | 
						||
| 
								 | 
							
								    sync=0.0
							 | 
						||
| 
								 | 
							
								    do i=0,6
							 | 
						||
| 
								 | 
							
								      i1=i0+i*32
							 | 
						||
| 
								 | 
							
								      i2=i1+36*32
							 | 
						||
| 
								 | 
							
								      i3=i1+72*32
							 | 
						||
| 
								 | 
							
								      term1=0.0  ! this needs to be fixed...
							 | 
						||
| 
								 | 
							
								      term2=0.0
							 | 
						||
| 
								 | 
							
								      term3=0.0
							 | 
						||
| 
								 | 
							
								      if( i1.ge.1 .and. i1+31.le.NP2 )  &
							 | 
						||
| 
								 | 
							
								        term1=abs(sum(cd0(i1:i1+31)*conjg(ctwk*csync(i,1:32))))
							 | 
						||
| 
								 | 
							
								      if( i2.ge.1 .and. i2+31.le.NP2 )  & 
							 | 
						||
| 
								 | 
							
								        term2=abs(sum(cd0(i2:i2+31)*conjg(ctwk*csync(i,1:32))))
							 | 
						||
| 
								 | 
							
								      if( i3.ge.1 .and. i3+31.le.NP2 )  &
							 | 
						||
| 
								 | 
							
								        term3=abs(sum(cd0(i3:i3+31)*conjg(ctwk*csync(i,1:32))))
							 | 
						||
| 
								 | 
							
								      sync=sync+term1+term2+term3
							 | 
						||
| 
								 | 
							
								    enddo
							 | 
						||
| 
								 | 
							
								    if( sync .gt. smax ) then
							 | 
						||
| 
								 | 
							
								      smax=sync
							 | 
						||
| 
								 | 
							
								      delfbest=delf
							 | 
						||
| 
								 | 
							
								    endif
							 | 
						||
| 
								 | 
							
								  enddo
							 | 
						||
| 
								 | 
							
								  a=0.0
							 | 
						||
| 
								 | 
							
								  a(1)=-delfbest
							 | 
						||
| 
								 | 
							
								  call twkfreq1(cd0,NP2,fs2,a,cd0)
							 | 
						||
| 
								 | 
							
								  xdt=xdt2
							 | 
						||
| 
								 | 
							
								  f1=f1+delfbest
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  j=0
							 | 
						||
| 
								 | 
							
								  do k=1,NN
							 | 
						||
| 
								 | 
							
								    i1=ibest+(k-1)*32
							 | 
						||
| 
								 | 
							
								    csymb=cmplx(0.0,0.0)
							 | 
						||
| 
								 | 
							
								    if( i1.ge.1 .and. i1+31 .le. NP2 ) csymb=cd0(i1:i1+31)
							 | 
						||
| 
								 | 
							
								    call four2a(csymb,32,1,-1,1)
							 | 
						||
| 
								 | 
							
								    s2(0:7,k)=abs(csymb(1:8))
							 | 
						||
| 
								 | 
							
								  enddo  
							 | 
						||
| 
								 | 
							
								  j=0
							 | 
						||
| 
								 | 
							
								  do k=1,NN
							 | 
						||
| 
								 | 
							
								    if(k.le.7) cycle
							 | 
						||
| 
								 | 
							
								    if(k.ge.37 .and. k.le.43) cycle
							 | 
						||
| 
								 | 
							
								    if(k.gt.72) cycle
							 | 
						||
| 
								 | 
							
								    j=j+1
							 | 
						||
| 
								 | 
							
								    s1(0:7,j)=s2(0:7,k)
							 | 
						||
| 
								 | 
							
								  enddo  
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  do j=1,ND
							 | 
						||
| 
								 | 
							
								     ps=s1(0:7,j)
							 | 
						||
| 
								 | 
							
								     where (ps.gt.0.0) ps=log(ps)
							 | 
						||
| 
								 | 
							
								     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))
							 | 
						||
| 
								 | 
							
								     r4=max(ps(4),ps(5),ps(6),ps(7))-max(ps(0),ps(1),ps(2),ps(3))
							 | 
						||
| 
								 | 
							
								     rxdata(3*j-2)=r4
							 | 
						||
| 
								 | 
							
								     rxdata(3*j-1)=r2
							 | 
						||
| 
								 | 
							
								     rxdata(3*j)=r1
							 | 
						||
| 
								 | 
							
								  enddo
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  rxav=sum(rxdata)/(3.0*ND)
							 | 
						||
| 
								 | 
							
								  rx2av=sum(rxdata*rxdata)/(3.0*ND)
							 | 
						||
| 
								 | 
							
								  var=rx2av-rxav*rxav
							 | 
						||
| 
								 | 
							
								  if( var .gt. 0.0 ) then
							 | 
						||
| 
								 | 
							
								     rxsig=sqrt(var)
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								     rxsig=sqrt(rx2av)
							 | 
						||
| 
								 | 
							
								  endif
							 | 
						||
| 
								 | 
							
								  rxdata=rxdata/rxsig
							 | 
						||
| 
								 | 
							
								  ss=0.84
							 | 
						||
| 
								 | 
							
								  llr=2.0*rxdata/(ss*ss)
							 | 
						||
| 
								 | 
							
								  apmask=0
							 | 
						||
| 
								 | 
							
								  cw=0
							 | 
						||
| 
								 | 
							
								  call timer('bpd174  ',0)
							 | 
						||
| 
								 | 
							
								  call bpdecode174(llr,apmask,max_iterations,decoded,cw,nharderrors)
							 | 
						||
| 
								 | 
							
								  call timer('bpd174  ',1)
							 | 
						||
| 
								 | 
							
								  dmin=0.0
							 | 
						||
| 
								 | 
							
								  if(nharderrors.lt.0) then
							 | 
						||
| 
								 | 
							
								     call timer('osd174  ',0)
							 | 
						||
| 
								 | 
							
								     call osd174(llr,norder,decoded,cw,nharderrors,dmin)
							 | 
						||
| 
								 | 
							
								     call timer('osd174  ',1)
							 | 
						||
| 
								 | 
							
								  endif
							 | 
						||
| 
								 | 
							
								  nbadcrc=1
							 | 
						||
| 
								 | 
							
								  message='                      '
							 | 
						||
| 
								 | 
							
								  xsnr=-99.0
							 | 
						||
| 
								 | 
							
								  if(count(cw.eq.0).eq.174) go to 900           !Reject the all-zero codeword
							 | 
						||
| 
								 | 
							
								  if( nharderrors.ge.0 .and. dmin.le.30.0 .and. nharderrors .lt. 30) then
							 | 
						||
| 
								 | 
							
								    call chkcrc12a(decoded,nbadcrc)
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    nharderrors=-1
							 | 
						||
| 
								 | 
							
								    go to 900
							 | 
						||
| 
								 | 
							
								  endif
							 | 
						||
| 
								 | 
							
								  if(nbadcrc.eq.0) then
							 | 
						||
| 
								 | 
							
								     call extractmessage174(decoded,message,ncrcflag,recent_calls,nrecent)
							 | 
						||
| 
								 | 
							
								     call genft8(message,msgsent,itone)
							 | 
						||
| 
								 | 
							
								     xsig=0.0
							 | 
						||
| 
								 | 
							
								     xnoi=0.0
							 | 
						||
| 
								 | 
							
								     do i=1,79
							 | 
						||
| 
								 | 
							
								        xsig=xsig+s2(itone(i),i)**2
							 | 
						||
| 
								 | 
							
								        ios=mod(itone(i)+4,7)
							 | 
						||
| 
								 | 
							
								        xnoi=xnoi+s2(ios,i)**2
							 | 
						||
| 
								 | 
							
								     enddo
							 | 
						||
| 
								 | 
							
								     xsnr=0.001
							 | 
						||
| 
								 | 
							
								     if( xnoi.gt.0 .and. xnoi.lt.xsig ) xsnr=xsig/xnoi-1.0
							 | 
						||
| 
								 | 
							
								     xsnr=10.0*log10(xsnr)-27.0
							 | 
						||
| 
								 | 
							
								     if( xsnr .lt. -24.0 ) xsnr=-24.0
							 | 
						||
| 
								 | 
							
								  endif
							 | 
						||
| 
								 | 
							
								900 continue
							 | 
						||
| 
								 | 
							
								  return
							 | 
						||
| 
								 | 
							
								end subroutine ft8b
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								subroutine ft8_downsample(dd,newdat,f0,c1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! Downconvert to complex data sampled at 187.5 Hz, 32 samples/symbol
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  parameter (NMAX=15*12000)
							 | 
						||
| 
								 | 
							
								  parameter (NFFT1=200000,NFFT2=3125)      !200000/64 = 3125
							 | 
						||
| 
								 | 
							
								  logical newdat
							 | 
						||
| 
								 | 
							
								  complex c1(0:NFFT2-1)
							 | 
						||
| 
								 | 
							
								  complex cx(0:NFFT1/2)
							 | 
						||
| 
								 | 
							
								  real dd(NMAX),x(NFFT1)
							 | 
						||
| 
								 | 
							
								  equivalence (x,cx)
							 | 
						||
| 
								 | 
							
								  save cx
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if(newdat) then
							 | 
						||
| 
								 | 
							
								! Data in dd have changed, recompute the long FFT     
							 | 
						||
| 
								 | 
							
								     x(1:NMAX)=dd
							 | 
						||
| 
								 | 
							
								     x(NMAX+1:NFFT1)=0.                       !Zero-pad the x array
							 | 
						||
| 
								 | 
							
								     call four2a(cx,NFFT1,1,-1,0)             !r2c FFT to freq domain
							 | 
						||
| 
								 | 
							
								     newdat=.false.
							 | 
						||
| 
								 | 
							
								  endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  df=12000.0/NFFT1
							 | 
						||
| 
								 | 
							
								  baud=12000.0/2048.0
							 | 
						||
| 
								 | 
							
								  i0=nint(f0/df)
							 | 
						||
| 
								 | 
							
								  ft=f0+8.0*baud
							 | 
						||
| 
								 | 
							
								  it=min(nint(ft/df),NFFT1/2)
							 | 
						||
| 
								 | 
							
								  fb=f0-1.0*baud
							 | 
						||
| 
								 | 
							
								  ib=max(1,nint(fb/df))
							 | 
						||
| 
								 | 
							
								  k=0
							 | 
						||
| 
								 | 
							
								  c1=0.
							 | 
						||
| 
								 | 
							
								  do i=ib,it
							 | 
						||
| 
								 | 
							
								   c1(k)=cx(i)
							 | 
						||
| 
								 | 
							
								   k=k+1
							 | 
						||
| 
								 | 
							
								  enddo
							 | 
						||
| 
								 | 
							
								  c1=cshift(c1,i0-ib)
							 | 
						||
| 
								 | 
							
								  call four2a(c1,NFFT2,1,1,1)            !c2c FFT back to time domain
							 | 
						||
| 
								 | 
							
								  fac=1.0/sqrt(float(NFFT1)*NFFT2)
							 | 
						||
| 
								 | 
							
								  c1=fac*c1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return
							 | 
						||
| 
								 | 
							
								end subroutine ft8_downsample
							 |