170 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Fortran
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Fortran
		
	
	
	
	
	
| subroutine msk40decodeframe(c,mycall,hiscall,xsnr,bswl,nhasharray,             &
 | |
|                             recent_calls,nrecent,msgreceived,nsuccess)
 | |
| !  use timer_module, only: timer
 | |
| 
 | |
|   parameter (NSPM=240)
 | |
|   character*4 rpt(0:15)
 | |
|   character*6 mycall,hiscall,mycall0,hiscall0
 | |
|   character*22 hashmsg,msgreceived
 | |
|   character*12 recent_calls(nrecent)
 | |
|   complex cb(42)
 | |
|   complex cfac,cca
 | |
|   complex c(NSPM)
 | |
|   integer*1 cw(32)
 | |
|   integer*1 decoded(16)
 | |
|   integer s8r(8),hardbits(40)
 | |
|   integer nhasharray(nrecent,nrecent)
 | |
|   real*8 dt, fs, pi, twopi
 | |
|   real cbi(42),cbq(42)
 | |
|   real pp(12)
 | |
|   real softbits(40)
 | |
|   real llr(32)
 | |
|   logical first
 | |
|   logical*1 bswl
 | |
|   data first/.true./
 | |
|   data s8r/1,0,1,1,0,0,0,1/
 | |
|   data mycall0/'dummy'/,hiscall0/'dummy'/
 | |
|   data rpt/"-03 ","+00 ","+03 ","+06 ","+10 ","+13 ","+16 ", &
 | |
|            "R-03","R+00","R+03","R+06","R+10","R+13","R+16", &
 | |
|            "RRR ","73  "/
 | |
|   save first,cb,fs,pi,twopi,dt,s8r,pp,rpt,mycall0,hiscall0,ihash
 | |
| 
 | |
|   if(first) then
 | |
| ! define half-sine pulse and raised-cosine edge window
 | |
|      pi=4d0*datan(1d0)
 | |
|      twopi=8d0*datan(1d0)
 | |
|      fs=12000.0
 | |
|      dt=1.0/fs
 | |
| 
 | |
|      do i=1,12
 | |
|        angle=(i-1)*pi/12.0
 | |
|        pp(i)=sin(angle)
 | |
|      enddo
 | |
| 
 | |
| ! define the sync word waveforms
 | |
|      s8r=2*s8r-1  
 | |
|      cbq(1:6)=pp(7:12)*s8r(1)
 | |
|      cbq(7:18)=pp*s8r(3)
 | |
|      cbq(19:30)=pp*s8r(5)
 | |
|      cbq(31:42)=pp*s8r(7)
 | |
|      cbi(1:12)=pp*s8r(2)
 | |
|      cbi(13:24)=pp*s8r(4)
 | |
|      cbi(25:36)=pp*s8r(6)
 | |
|      cbi(37:42)=pp(1:6)*s8r(8)
 | |
|      cb=cmplx(cbi,cbq)
 | |
|      first=.false.
 | |
|   endif
 | |
| 
 | |
|   if(mycall.ne.mycall0 .or. hiscall.ne.hiscall0) then
 | |
|     hashmsg=trim(mycall)//' '//trim(hiscall)
 | |
|     if( hashmsg .ne. ' ' .and. hiscall .ne. ''  ) then ! protect against blank mycall/hiscall
 | |
|       call fmtmsg(hashmsg,iz)
 | |
|       call hash(hashmsg,22,ihash)
 | |
|       ihash=iand(ihash,4095)
 | |
|     else
 | |
|       ihash=9999  ! so that it can never match a received hash
 | |
|     endif
 | |
|     mycall0=mycall
 | |
|     hiscall0=hiscall
 | |
|   endif
 | |
| 
 | |
|   nsuccess=0
 | |
|   msgreceived=' '
 | |
| 
 | |
| ! Estimate carrier phase. 
 | |
|   cca=sum(c(1:1+41)*conjg(cb))
 | |
|   phase0=atan2(imag(cca),real(cca))
 | |
| 
 | |
| ! Remove phase error - want constellation rotated so that sample points lie on I/Q axes
 | |
|   cfac=cmplx(cos(phase0),sin(phase0))
 | |
|   c=c*conjg(cfac)
 | |
| 
 | |
| ! Matched filter.
 | |
|   softbits(1)=sum(imag(c(1:6))*pp(7:12))+sum(imag(c(NSPM-5:NSPM))*pp(1:6))
 | |
|   softbits(2)=sum(real(c(1:12))*pp)
 | |
|   do i=2,20
 | |
|     softbits(2*i-1)=sum(imag(c(1+(i-1)*12-6:1+(i-1)*12+5))*pp)
 | |
|     softbits(2*i)=sum(real(c(7+(i-1)*12-6:7+(i-1)*12+5))*pp)
 | |
|   enddo
 | |
| 
 | |
| ! Sync word hard error weight is used to reject frames that 
 | |
| ! are unlikely to decode.
 | |
|   hardbits=0
 | |
|   do i=1,40
 | |
|     if( softbits(i) .ge. 0.0 ) then
 | |
|       hardbits(i)=1
 | |
|     endif
 | |
|   enddo
 | |
|   nbadsync1=(8-sum( (2*hardbits(1:8)-1)*s8r ) )/2
 | |
|   nbadsync=nbadsync1
 | |
|   if( nbadsync .gt. 3 ) then
 | |
|     return
 | |
|   endif
 | |
| 
 | |
| ! Normalize the softsymbols before submitting to decoder.
 | |
|   sav=sum(softbits)/40
 | |
|   s2av=sum(softbits*softbits)/40
 | |
|   ssig=sqrt(s2av-sav*sav)
 | |
|   softbits=softbits/ssig
 | |
| 
 | |
|   sigma=0.75
 | |
| !  if(xsnr.lt.0.0) sigma=0.75-0.0875*xsnr
 | |
|   if(xsnr.lt.0.0) sigma=0.75-0.11*xsnr
 | |
|   llr(1:32)=softbits(9:40)
 | |
|   llr=2.0*llr/(sigma*sigma)
 | |
|   
 | |
|   max_iterations=5
 | |
|   call bpdecode40(llr,max_iterations,decoded,niterations)
 | |
| 
 | |
|   if( niterations .ge. 0.0 ) then
 | |
|     call encode_msk40(decoded,cw)
 | |
|     nhammd=0
 | |
|     cord=0.0
 | |
|     do i=1,32
 | |
|       if( cw(i) .ne. hardbits(i+8) ) then
 | |
|         nhammd=nhammd+1
 | |
|         cord=cord+abs(softbits(i+8))
 | |
|       endif
 | |
|     enddo
 | |
| 
 | |
|     imsg=0
 | |
|     do i=1,16
 | |
|       imsg=ishft(imsg,1)+iand(1,decoded(17-i))
 | |
|     enddo
 | |
|     nrxrpt=iand(imsg,15)
 | |
|     nrxhash=(imsg-nrxrpt)/16
 | |
| 
 | |
|     if(nhammd.le.4 .and. cord .lt. 0.65 .and.                                  &
 | |
|        nrxhash.eq.ihash .and. nrxrpt.ge.7) then
 | |
| !write(*,*) 'decodeframe 1',nbadsync,nhammd,cord,nrxhash,nrxrpt,ihash,xsnr,sigma
 | |
|       nsuccess=1    
 | |
|       write(msgreceived,'(a1,a,1x,a,a1,1x,a4)') "<",trim(mycall),   &
 | |
|                                     trim(hiscall),">",rpt(nrxrpt)
 | |
|       return
 | |
|     elseif(bswl .and. nhammd.le.4 .and. cord.lt.0.65 .and. nrxrpt.ge.7 ) then
 | |
|       do i=1,nrecent
 | |
|         do j=i+1,nrecent
 | |
|           if( nrxhash .eq. nhasharray(i,j) ) then
 | |
|             nsuccess=2
 | |
|             write(msgreceived,'(a1,a,1x,a,a1,1x,a4)') "<",trim(recent_calls(i)),   &
 | |
|                                   trim(recent_calls(j)),">",rpt(nrxrpt)
 | |
| !write(*,*) 'decodeframe 2',nbadsync,nhammd,cord,nrxhash,nrxrpt,ihash,xsnr,sigma
 | |
|           elseif( nrxhash .eq. nhasharray(j,i) ) then
 | |
|             nsuccess=2
 | |
|             write(msgreceived,'(a1,a,1x,a,a1,1x,a4)') "<",trim(recent_calls(j)),   &
 | |
|                                   trim(recent_calls(i)),">",rpt(nrxrpt)
 | |
| !write(*,*) 'decodeframe 3',nbadsync,nhammd,cord,nrxhash,nrxrpt,ihash,xsnr,sigma
 | |
|           endif
 | |
|         enddo
 | |
|       enddo
 | |
|       if(nsuccess.eq.0) then
 | |
|         nsuccess=3
 | |
| !write(*,*) 'decodeframe 4',bswl,nbadsync,nhammd,cord,nrxhash,nrxrpt,ihash,xsnr,sigma,nsuccess
 | |
|         write(msgreceived,'(a1,i4.4,a1,1x,a4)') "<",nrxhash,">",rpt(nrxrpt)
 | |
|       endif
 | |
|     endif 
 | |
|   endif
 | |
| 
 | |
|   return
 | |
| end subroutine msk40decodeframe
 | 
