mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-31 13:10:19 -04:00 
			
		
		
		
	git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7734 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
		
			
				
	
	
		
			198 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Fortran
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Fortran
		
	
	
	
	
	
| program msk144sd
 | |
| !
 | |
| ! A simple decoder for slow msk144.
 | |
| ! Can be used as a (slow) brute-force multi-decoder by looping
 | |
| ! over a set of carrier frequencies.
 | |
| !
 | |
|   use options
 | |
|   use timer_module, only: timer
 | |
|   use timer_impl, only: init_timer
 | |
|   use readwav
 | |
| 
 | |
|   parameter (NRECENT=10)
 | |
|   parameter (NSPM=864)
 | |
|   parameter (NPATTERNS=4)
 | |
| 
 | |
|   character ch
 | |
|   character*80 line
 | |
|   character*500 infile
 | |
|   character*12 mycall,hiscall
 | |
|   character*6 mygrid
 | |
|   character(len=500) optarg
 | |
|   character*22 msgreceived
 | |
|   character*12 recent_calls(NRECENT)
 | |
| 
 | |
|   complex cdat(30*375)
 | |
|   complex c(NSPM)
 | |
|   complex ct(NSPM)
 | |
| 
 | |
|   real softbits(144)
 | |
|   real xmc(NPATTERNS)
 | |
| 
 | |
|   logical :: display_help=.false.
 | |
| 
 | |
|   type(wav_header) :: wav
 | |
| 
 | |
|   integer iavmask(8)
 | |
|   integer iavpatterns(8,NPATTERNS)
 | |
|   integer npkloc(10)
 | |
| 
 | |
|   integer*2 id2(30*12000)
 | |
|   integer*2 ichunk(7*1024)
 | |
|   
 | |
|   data iavpatterns/ &
 | |
|        1,1,1,1,0,0,0,0, &
 | |
|        0,1,1,1,1,0,0,0, &
 | |
|        0,0,1,1,1,1,0,0, &
 | |
|        1,1,1,1,1,1,0,0/
 | |
|   data xmc/2.0,4.5,2.5,3.0/
 | |
| 
 | |
|   type (option) :: long_options(2) = [ &
 | |
|        option ('frequency',.true.,'f','rxfreq',''), &
 | |
|        option ('help',.false.,'h','Display this help message','') &
 | |
|        ]
 | |
|   t0=0.0
 | |
|   ntol=100
 | |
|   nrxfreq=1500
 | |
|  
 | |
|   do
 | |
|      call getopt('f:h',long_options,ch,optarg,narglen,nstat,noffset,nremain,.true.)
 | |
|      if( nstat .ne. 0 ) then
 | |
|         exit
 | |
|      end if
 | |
|      select case (ch)
 | |
|      case ('f')
 | |
|         read (optarg(:narglen), *) nrxfreq
 | |
|      case ('h')
 | |
|         display_help = .true.
 | |
|      end select
 | |
|   end do
 | |
| 
 | |
|   if(display_help .or. nstat.lt.0 .or. nremain.lt.1) then
 | |
|      print *, ''
 | |
|      print *, 'Usage: msk144sd [OPTIONS] file1 [file2 ...]'
 | |
|      print *, ''
 | |
|      print *, '       decode pre-recorded .WAV file(s)'
 | |
|      print *, ''
 | |
|      print *, 'OPTIONS:'
 | |
|      do i = 1, size (long_options)
 | |
|         call long_options(i) % print (6)
 | |
|      end do
 | |
|      go to 999
 | |
|   endif
 | |
| 
 | |
|   call init_timer ('timer.out')
 | |
|   call timer('msk144  ',0)
 | |
|   ndecoded=0
 | |
|   do ifile=noffset+1,noffset+nremain
 | |
|      call get_command_argument(ifile,optarg,narglen)
 | |
|      infile=optarg(:narglen)
 | |
|      call timer('read    ',0)
 | |
|      call wav%read (infile)
 | |
|      i1=index(infile,'.wav')
 | |
|      if( i1 .eq. 0 ) i1=index(infile,'.WAV')
 | |
|      read(infile(i1-6:i1-1),*,err=998) nutc
 | |
|      inquire(FILE=infile,SIZE=isize)
 | |
|      npts=min((isize-216)/2,360000)
 | |
|      read(unit=wav%lun) id2(1:npts)
 | |
|      close(unit=wav%lun)
 | |
|      call timer('read    ',1)
 | |
| 
 | |
| !   do if=1,89  ! brute force multi-decoder
 | |
|      fo=nrxfreq
 | |
| !     fo=(if-1)*25.0+300.0
 | |
|      call msksddc(id2,npts,fo,cdat)
 | |
|      np=npts/32
 | |
|      ntol=200  ! actual ntol is ntol/32=6.25 Hz. Detection window is 12.5 Hz wide
 | |
|      fc=1500.0
 | |
|      call msk144spd(cdat,np,ntol,ndecodesuccess,msgreceived,fc,fest,tdec,navg,ct, &
 | |
|                     softbits,recent_calls,nrecent)
 | |
|      nsnr=0  ! need an snr estimate
 | |
|      if( ndecodesuccess .eq. 1 ) then
 | |
|        fest=fo+fest-fc   ! fudging because spd thinks input signal is at 1500 Hz
 | |
|        goto 900 
 | |
|      endif
 | |
| ! If short ping decoder doesn't find a decode 
 | |
|      npat=NPATTERNS
 | |
|      do iavg=1,npat
 | |
|        iavmask=iavpatterns(1:8,iavg)
 | |
|        navg=sum(iavmask)
 | |
|        deltaf=4.0/real(navg)  ! search increment for frequency sync
 | |
|        npeaks=4
 | |
|        ntol=200
 | |
|        fc=1500.0
 | |
|        call msk144sync(cdat(1:6*NSPM),6,ntol,deltaf,iavmask,npeaks,fc,           &
 | |
|           fest,npkloc,nsyncsuccess,xmax,c)
 | |
|        if( nsyncsuccess .eq. 0 ) cycle
 | |
| 
 | |
|        do ipk=1,npeaks
 | |
|          do is=1,3   
 | |
|            ic0=npkloc(ipk)
 | |
|            if(is.eq.2) ic0=max(1,ic0-1)
 | |
|            if(is.eq.3) ic0=min(NSPM,ic0+1)
 | |
|            ct=cshift(c,ic0-1)
 | |
|            call msk144decodeframe(ct,softbits,msgreceived,ndecodesuccess,      &
 | |
|                                   recent_calls,nrecent)
 | |
|            if(ndecodesuccess .gt. 0) then
 | |
|               tdec=tsec+xmc(iavg)*tframe
 | |
|               fest=fo+(fest-fc)/32.0   
 | |
|               goto 900
 | |
|            endif
 | |
|          enddo                         !Slicer dither
 | |
|        enddo                            !Peak loop 
 | |
|      enddo
 | |
| 
 | |
| !   enddo
 | |
| 900 continue
 | |
|     if( ndecodesuccess .gt. 0 ) then
 | |
|        write(*,1020) nutc,nsnr,tdec,nint(fest),' % ',msgreceived,navg
 | |
| 1020   format(i6.6,i4,f5.1,i5,a3,a22,i4)
 | |
|     endif
 | |
|   enddo
 | |
| 
 | |
|   call timer('msk144  ',1)
 | |
|   call timer('msk144  ',101)
 | |
|   go to 999
 | |
| 
 | |
| 998 print*,'Cannot read from file:'
 | |
|   print*,infile
 | |
| 
 | |
| 999 continue
 | |
| end program msk144sd
 | |
| 
 | |
| subroutine msksddc(id2,npts,fc,cdat)
 | |
| 
 | |
| ! The msk144 detector/demodulator/decoder will decode signals
 | |
| ! with carrier frequency, fc, in the range fN/4 +/- 0.03333*fN. 
 | |
| !
 | |
| ! For slow MSK144 with nslow=32: 
 | |
| !  fs=12000/32=375 Hz, fN=187.5 Hz
 | |
| !
 | |
| ! This routine accepts input samples with fs=12000 Hz. It
 | |
| ! downconverts and decimates by 32 to center a signal with input carrier
 | |
| ! frequency fc at new carrier frequency 1500/32=46.875 Hz.
 | |
| ! The analytic signal is returned.
 | |
|  
 | |
|   parameter (NFFT1=30*12000,NFFT2=30*375)
 | |
|   integer*2 id2(npts)
 | |
|   complex cx(0:NFFT1)
 | |
|   complex cdat(30*375)
 | |
| 
 | |
|   dt=1.0/12000.0
 | |
|   df=1.0/(NFFT1*dt)
 | |
|   icenter=int(fc/df+0.5)
 | |
|   i46p875=int(46.875/df+0.5)
 | |
|   ishift=icenter-i46p875
 | |
|   cx=cmplx(0.0,0.0)
 | |
|   cx(1:npts)=id2
 | |
|   call four2a(cx,NFFT1,1,-1,1)
 | |
|   cx=cshift(cx,ishift)
 | |
|   cx(1)=0.5*cx(1)
 | |
|   cx(2*i46p875+1:)=cmplx(0.0,0.0)
 | |
|   call four2a(cx,NFFT2,1,1,1)
 | |
|   cdat(1:npts/32)=cx(0:npts/32-1)/NFFT1
 | |
|   return
 | |
| 
 | |
| end subroutine msksddc
 | |
| 
 |