mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-31 13:10:19 -04:00 
			
		
		
		
	Functioning JTMSK decoder, within stand-alone program msk.
git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/jtms3@2519 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
		
							parent
							
								
									71ddb3fd1e
								
							
						
					
					
						commit
						8b55eb3a28
					
				| @ -1,6 +1,6 @@ | ||||
| [Setup] | ||||
| AppName=JTMS3 | ||||
| AppVerName=JTMS3 Version 0.2 r2516 | ||||
| AppVerName=JTMS3 Version 0.2 r2517 | ||||
| AppCopyright=Copyright (C) 2001-2012 by Joe Taylor, K1JT | ||||
| DefaultDirName=c:\JTMS3 | ||||
| DefaultGroupName=JTMS3 | ||||
|  | ||||
| @ -6,10 +6,10 @@ | ||||
| 
 | ||||
| QT       += core gui network | ||||
| CONFIG   += qwt thread | ||||
| #CONFIG   += console | ||||
| CONFIG   += console | ||||
| 
 | ||||
| TARGET = jtms3 | ||||
| VERSION = 0.1 | ||||
| VERSION = 0.2 | ||||
| TEMPLATE = app | ||||
| 
 | ||||
| win32 { | ||||
|  | ||||
| @ -17,7 +17,7 @@ CFLAGS = -I. -fbounds-check | ||||
| %.o: %.F90 | ||||
| 	${FC} ${FFLAGS} -c $< | ||||
| 
 | ||||
| all:    libm65.a ms3.exe t1.exe | ||||
| all:    libm65.a msk.exe  | ||||
| 
 | ||||
| OBJS1 = trimlist.o display.o getdphi.o pctile.o ccf65.o \
 | ||||
| 	decode1a.o sort.o filbig.o fil6521.o afc65b.o \
 | ||||
| @ -32,15 +32,17 @@ OBJS1 = trimlist.o display.o getdphi.o pctile.o ccf65.o \ | ||||
| 	geocentric.o moon2.o toxyz.o dot.o dcoord.o f77_wisdom.o \
 | ||||
| 	gen65.o chkmsg.o ptt.o astrosub.o astro0.o recvpkt.o symspec.o \
 | ||||
| 	iqcal.o iqfix.o timf2.o s3avg.o genjtms3.o analytic.o \
 | ||||
| 	db.o specjtms.o genmsk.o | ||||
| 	db.o specjtms.o genmsk.o mskdf.o tweak1.o syncmsk.o \
 | ||||
| 	lenmsk.o decodemsk.o ping.o makepings.o alignmsg.o match.o \
 | ||||
| 	rtping.o jtmsk.o hipass.o setupmsk.o foldmsk.o  | ||||
| 
 | ||||
| libm65.a: $(OBJS1) | ||||
| 	ar cr libm65.a $(OBJS1)  | ||||
| 	ranlib libm65.a | ||||
| 
 | ||||
| OBJS3 = ms3.o  | ||||
| ms3.exe: $(OBJS3) libm65.a | ||||
| 	$(FC) -o ms3.exe $(OBJS3) libm65.a ../libfftw3f_win.a \
 | ||||
| OBJS3 = msk.o  | ||||
| msk.exe: $(OBJS3) libm65.a | ||||
| 	$(FC) -o msk.exe $(OBJS3) libm65.a ../libfftw3f_win.a  | ||||
| 
 | ||||
| OBJS2 = JT65code.o | ||||
| JT65code.exe: $(OBJS2) libm65.a | ||||
|  | ||||
| @ -2,9 +2,10 @@ subroutine analytic(d,npts,nfft,s,c) | ||||
| 
 | ||||
| ! Convert real data to analytic signal | ||||
| 
 | ||||
|   parameter (NFFTMAX=128*1024) | ||||
|   real d(npts) | ||||
|   real s(npts) | ||||
|   complex c(npts) | ||||
|   complex c(NFFTMAX) | ||||
| 
 | ||||
|   nh=nfft/2 | ||||
|   fac=2.0/nfft | ||||
|  | ||||
							
								
								
									
										39
									
								
								libm65/decodemsk.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								libm65/decodemsk.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| subroutine decodemsk(cdat,npts,cw,i1,nchar,s2,msg) | ||||
| 
 | ||||
| ! DF snd sync have been established, now decode the message | ||||
| 
 | ||||
|   complex cdat(npts) | ||||
|   complex cw(168,0:63)                  !Complex waveforms for codewords | ||||
|   real s2(0:63,400) | ||||
|   character msg*400 | ||||
|   complex z,zmax | ||||
|   character cc*64 | ||||
| !                    1         2         3         4         5         6 | ||||
| !          0123456789012345678901234567890123456789012345678901234567890123 | ||||
|   data cc/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ./?-                 _     @'/ | ||||
| 
 | ||||
|   msg=' ' | ||||
|   do j=1,nchar                         !Find best match for each character | ||||
|      ia=i1 + (j-1)*168 | ||||
|      smax=0. | ||||
|      do k=0,40 | ||||
|         kk=k | ||||
|         if(k.eq.40) kk=57 | ||||
|         z=0. | ||||
|         do i=1,168 | ||||
|            z=z + cdat(ia+i)*conjg(cw(i,kk)) | ||||
|         enddo | ||||
|         ss=abs(z) | ||||
|         s2(k,j)=ss | ||||
|         if(ss.gt.smax) then | ||||
|            smax=ss | ||||
|            zmax=z | ||||
|            kpk=kk | ||||
|         endif | ||||
|      enddo | ||||
|      msg(j:j)=cc(kpk+1:kpk+1) | ||||
|      if(kpk.eq.57) msg(j:j)=' ' | ||||
|   enddo | ||||
| 
 | ||||
|   return | ||||
| end subroutine decodemsk | ||||
							
								
								
									
										50
									
								
								libm65/foldmsk.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								libm65/foldmsk.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| subroutine foldmsk(s2,msglen,nchar,mycall,msg,msg29) | ||||
| 
 | ||||
| ! Fold the 2-d "goodness of fit" array s2 modulo message length,  | ||||
| ! then decode the folded message. | ||||
| 
 | ||||
|   real s2(0:63,400) | ||||
|   real fs2(0:63,29) | ||||
|   integer nfs2(29) | ||||
|   character mycall*12 | ||||
|   character msg*400,msg29*29 | ||||
|   character cc*64 | ||||
| !                    1         2         3         4         5         6 | ||||
| !          0123456789012345678901234567890123456789012345678901234567890123 | ||||
|   data cc/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ./?-                 _     @'/ | ||||
| 
 | ||||
|   fs2=0. | ||||
|   nfs2=0 | ||||
|   do j=1,nchar                           !Fold s2 into fs2, modulo msglen | ||||
|      jj=mod(j-1,msglen)+1 | ||||
|      nfs2(jj)=nfs2(jj)+1 | ||||
|      do i=0,40 | ||||
|         fs2(i,jj)=fs2(i,jj) + s2(i,j) | ||||
|      enddo | ||||
|   enddo | ||||
| 
 | ||||
|   msg=' ' | ||||
|   do j=1,msglen | ||||
|      smax=0. | ||||
|      do k=0,40 | ||||
|         if(fs2(k,j).gt.smax) then | ||||
|            smax=fs2(k,j) | ||||
|            kpk=k | ||||
|         endif | ||||
|      enddo | ||||
|      if(kpk.eq.40) kpk=57 | ||||
|      msg(j:j)=cc(kpk+1:kpk+1) | ||||
|      if(kpk.eq.57) msg(j:j)=' ' | ||||
|   enddo | ||||
| 
 | ||||
|   msg29=msg(1:msglen) | ||||
| 
 | ||||
|   call alignmsg('  ',2,msg29,msglen,idone) | ||||
|   if(idone.eq.0) call alignmsg('CQ',  3,msg29,msglen,idone) | ||||
|   if(idone.eq.0) call alignmsg('QRZ', 3,msg29,msglen,idone) | ||||
|   if(idone.eq.0) call alignmsg(mycall,4,msg29,msglen,idone) | ||||
|   if(idone.eq.0) call alignmsg(' ',   1,msg29,msglen,idone) | ||||
|   msg29=adjustl(msg29) | ||||
| 
 | ||||
|   return | ||||
| end subroutine foldmsk | ||||
| @ -65,7 +65,6 @@ subroutine genmsk(msg28,iwave,nwave) | ||||
|   f0=48000.d0/nsps | ||||
|   dfgen=0.5d0*f0 | ||||
|   foffset=1500.d0 - f0 | ||||
|   print*,f0,dfgen,foffset | ||||
|   t=0.d0 | ||||
|   k=0 | ||||
|   phi=0.d0 | ||||
| @ -95,5 +94,9 @@ subroutine genmsk(msg28,iwave,nwave) | ||||
|   if(isrch.eq.0) iwave(k+1:)=0 | ||||
|   nwave=k | ||||
| 
 | ||||
| !  call makepings(iwave,nwave) | ||||
| !  write(71) iwave | ||||
| !  call flush(71) | ||||
| 
 | ||||
|   return | ||||
| end subroutine genmsk | ||||
|  | ||||
							
								
								
									
										86
									
								
								libm65/jtmsk.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								libm65/jtmsk.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | ||||
| subroutine jtmsk(dat,npts,cfile6,t2,mswidth,ndb,nrpt,Nfreeze,       & | ||||
|      ntol,MouseDF,pick) | ||||
| 
 | ||||
| ! Decode a JTMS ping | ||||
| 
 | ||||
|   parameter (NZ=30*48000) | ||||
|   real dat(npts)                        !Raw data | ||||
|   complex cdat(NZ)                      !Analytic form of signal | ||||
|   character*6 cfile6                    !FileID | ||||
|   logical pick | ||||
|   character*12 mycall,hiscall | ||||
|   real s(NZ)                            !Power spectrum | ||||
|   real s2(0:63,400) | ||||
|   real r(60000) | ||||
|   complex cw(168,0:63)                   !Complex waveforms for all codewords | ||||
|   complex cwb(168)                       !Complex waveform for <space> | ||||
|   logical first | ||||
|   character msg*400,msg29*29 | ||||
|   character*90 line | ||||
|   common/ccom/nline,tping(100),line(100) | ||||
|   data first/.true./ | ||||
|   save first,cw,cwb | ||||
|   save cdat                             !Fix its address, for four2 | ||||
| 
 | ||||
|   if(first) call setupmsk(cw,cwb)       !Calculate waveforms for codewords | ||||
|   first=.false. | ||||
| 
 | ||||
|   nsps=24                               !Samples per symbol | ||||
|   f0=1000.0                             !Nominal frequency for bit=0 | ||||
|   n=log(float(npts))/log(2.0) + 1.0 | ||||
|   nfft1=2**n                            !FFT length | ||||
|   call analytic(dat,npts,nfft1,s,cdat)  !Convert to analytic signal | ||||
| 
 | ||||
|   call mskdf(cdat,npts,t2,nfft1,f0,nfreeze,mousedf,ntol,     & | ||||
|        dfx,snrsq2)                      !Get DF | ||||
|   print*,'b',dfx,snrsq2 | ||||
|   sq2lim=7.0 | ||||
|   if(pick) sq2lim=5.0 | ||||
|   if(snrsq2.lt.sq2lim) go to 900           !Reject non-JTMS signals | ||||
| 
 | ||||
|   call tweak1(cdat,npts,-dfx,cdat)      !Mix to standard frequency | ||||
| 
 | ||||
| ! DF is known, now establish character sync. | ||||
| 
 | ||||
|   call syncmsk(cdat,npts,cwb,r,i1)       !Get character sync | ||||
| 
 | ||||
|   call lenmsk(r,npts,msglen)             !Find message length | ||||
|    | ||||
|   s2=0. | ||||
|   nchar=(npts-168+1-i1)/168 | ||||
|   if(nchar.gt.400) nchar=400 | ||||
| 
 | ||||
|   call decodemsk(cdat,npts,cw,i1,nchar,s2,msg)   !Decode the message | ||||
|   print*,'B',i1,msglen,nchar | ||||
|   print*,msg(1:nchar) | ||||
| 
 | ||||
| !  ia=1 | ||||
| !  if(nchar.ge.40) ia=min(nchar/3,nchar-28)     | ||||
| !  ib=min(ia+28,nchar)                   !Can better limits ia, ib be found? | ||||
| !  print*,'A',ia,ib,nchar | ||||
| !  print*,msg(1:nchar) | ||||
| !  msg29=adjustl(msg(ia:ib)) | ||||
|   msg=adjustl(msg) | ||||
|   ib=min(nchar,45) | ||||
|   ndf=nint(dfx) | ||||
|   nchk=max(20,nint(1.5*msglen)) | ||||
| 
 | ||||
|   if(msglen.eq.0 .or. nchar.lt.nchk .or. pick) then | ||||
|      if(nline.le.99) nline=nline+1 | ||||
|      tping(nline)=t2 | ||||
|      write(line(nline),1110) cfile6,t2,mswidth,ndb,nrpt,ndf,msg(1:45) | ||||
| 1110 format(a6,f5.1,i5,i3,1x,i2.2,i5,5x,a45) | ||||
|   endif | ||||
| 
 | ||||
|   if(msglen.gt.0 .and. nchar.ge.nchk) then | ||||
|      call foldmsk(s2,msglen,nchar,mycall,msg,msg29)   !Decode folded message | ||||
|      if(nline.le.99) nline=nline+1 | ||||
|      tping(nline)=t2 | ||||
|      write(line(nline),1120) cfile6,t2,mswidth,ndb,nrpt,ndf,msg29 | ||||
| 1120 format(a6,f5.1,i5,i3,1x,i2.2,i5,5x,a29,11x,'*') | ||||
|    endif | ||||
| 
 | ||||
| 900 continue | ||||
| 
 | ||||
|   return | ||||
| end subroutine jtmsk | ||||
							
								
								
									
										56
									
								
								libm65/lenmsk.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								libm65/lenmsk.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| subroutine lenmsk(r,npts,msglen) | ||||
| 
 | ||||
| ! Determine length of the user message in a JTMS ping. | ||||
| 
 | ||||
|   real r(60000) | ||||
|   real acf(4872) | ||||
|   integer np(9) | ||||
|   data np/5,7,9,11,13,17,19,23,29/      !Permissible message lengths | ||||
|   save acf                              !Why necessary?  (But don't remove!) | ||||
| 
 | ||||
|   msglen=0                              !Use ACF to find msg length | ||||
|   if(npts.ge.8*168) then | ||||
|      r=r-sum(r(1:npts))/npts | ||||
|      acfmax=0. | ||||
|      acf0=dot_product(r(1:npts),r(1:npts)) | ||||
|      kz=min(nint(0.75*npts),29*168) | ||||
|      do k=8,kz | ||||
|         fac=float(npts)/(npts-k) | ||||
|         acf(k)=fac*dot_product(r(1:npts),r(1+k:npts+k))/acf0 | ||||
|      enddo | ||||
|      call hipass(acf(8),kz-7,50) | ||||
| 
 | ||||
|      do k=8,kz                          !Find acfmax, kpk | ||||
|         if(acf(k).gt.acfmax) then | ||||
|            acfmax=acf(k) | ||||
|            kpk=k | ||||
|         endif | ||||
|      enddo | ||||
| 
 | ||||
|      sumsq=0. | ||||
|      n=0 | ||||
|      do k=8,kz                          !Find rms, skipping around kpk | ||||
|         if(abs(k-kpk).gt.10) then | ||||
|            sumsq=sumsq+acf(k)**2 | ||||
|            n=n+1 | ||||
|         endif | ||||
|      enddo | ||||
|      rms=sqrt(sumsq/n) | ||||
|      acf=acf/rms                        !Normalize the acf | ||||
| 
 | ||||
|      amax2=0. | ||||
|      acflim=3.5 | ||||
|      do i=1,9 | ||||
|         k=168*np(i)                     !Check only the permitted lengths | ||||
|         if(k.gt.kz) go to 10 | ||||
|         if(acf(k).gt.acflim .and. acf(k).gt.amax2) then   | ||||
|            amax2=acf(k)                 !Save best value >3.5 sigma | ||||
|            msglen=np(i)                 !Save message length | ||||
|            kpk2=k | ||||
|         endif | ||||
|      enddo | ||||
| 10   continue | ||||
|   endif | ||||
| 
 | ||||
|   return | ||||
| end subroutine lenmsk | ||||
							
								
								
									
										59
									
								
								libm65/msk.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								libm65/msk.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| program msk | ||||
| 
 | ||||
| ! Starting code for a JTMSK decoder. | ||||
| 
 | ||||
|   parameter (NSMAX=30*48000) | ||||
|   character*80 infile | ||||
|   character*6 cfile6 | ||||
|   character*12 arg | ||||
|   real dat(NSMAX) | ||||
|   real x(NSMAX) | ||||
|   complex cx(0:NSMAX/2) | ||||
|   integer hdr(11) | ||||
|   integer*2 id | ||||
|   common/mscom/id(NSMAX),s1(215,703),s2(215,703) | ||||
| 
 | ||||
|   nargs=iargc() | ||||
|   if(nargs.lt.1) then | ||||
|      print*,'Usage: msk <snr>' | ||||
|      go to 999 | ||||
|   endif | ||||
|   call getarg(1,arg) | ||||
|   read(arg,*) snr | ||||
| 
 | ||||
|   open(71,file='dat.71',form='unformatted',status='old') | ||||
|   read(71) id | ||||
|   cfile6='123400' | ||||
| 
 | ||||
|   npts=30*48000 | ||||
|   kstep=2048 | ||||
|   minsigdb=6 | ||||
|   mousedf=0 | ||||
|   ntol=200  | ||||
| 
 | ||||
|   call random_number(x) | ||||
|   nfft=NSMAX | ||||
|   call four2a(x,nfft,1,-1,0) | ||||
|   df=48000.0/nfft | ||||
|   ia=nint(300.0/df) | ||||
|   ib=nint(2800.0/df) | ||||
|   cx(:ia)=0. | ||||
|   cx(ib:)=0. | ||||
|   call four2a(cx,nfft,1,1,-1) | ||||
|   x(1)=0. | ||||
|   sq=0. | ||||
|   do i=1,NSMAX | ||||
|      sq=sq + x(i)**2 | ||||
|   enddo | ||||
|   rms=sqrt(sq/NSMAX) | ||||
|   x=x/rms | ||||
|   sig=(10.0**(0.05*snr))/32768.0 | ||||
|   dat=sig*id + x | ||||
| 
 | ||||
|   k=0 | ||||
|   do iblk=1,npts/kstep | ||||
|      k=k+kstep | ||||
|      call rtping(dat,k,cfile6,MinSigdB,MouseDF,ntol) | ||||
|   enddo | ||||
| 
 | ||||
| 999 end program msk | ||||
							
								
								
									
										49
									
								
								libm65/msk0.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								libm65/msk0.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| program msk | ||||
| 
 | ||||
| ! Starting code for a JTMSK decoder. | ||||
| 
 | ||||
|   parameter (NSMAX=30*48000) | ||||
|   character*80 infile | ||||
|   character*6 cfile6 | ||||
|   real dat(NSMAX) | ||||
|   integer hdr(11) | ||||
|   integer*2 id | ||||
|   common/mscom/id(NSMAX),s1(215,703),s2(215,703) | ||||
| 
 | ||||
|   nargs=iargc() | ||||
|   if(nargs.lt.1) then | ||||
|      print*,'Usage: msk file1 [file2 ...]' | ||||
|      print*,'       Reads data from *.wav files.' | ||||
|      go to 999 | ||||
|   endif | ||||
| 
 | ||||
|   npts=30*48000 | ||||
|   kstep=2048 | ||||
|   minsigdb=6 | ||||
|   mousedf=0 | ||||
|   ntol=200  | ||||
| 
 | ||||
|   do ifile=1,nargs | ||||
|      call getarg(ifile,infile) | ||||
|      open(10,file=infile,access='stream',status='old',err=998) | ||||
|      read(10) hdr | ||||
|      read(10) id | ||||
|      close(10) | ||||
|      hdr(1)=hdr(2) | ||||
|      i1=index(infile,'.wav') | ||||
|      cfile6=infile(i1-6:i1-1) | ||||
|      dat=id | ||||
| 
 | ||||
|      k=0 | ||||
|      do iblk=1,npts/kstep | ||||
|         k=k+kstep | ||||
|         call rtping(dat,k,cfile6,MinSigdB,MouseDF,ntol) | ||||
|      enddo | ||||
|   enddo | ||||
| 
 | ||||
|   go to 999 | ||||
| 
 | ||||
| 998 print*,'Cannot open file:' | ||||
|   print*,infile | ||||
| 
 | ||||
| 999 end program msk | ||||
							
								
								
									
										75
									
								
								libm65/mskdf.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								libm65/mskdf.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | ||||
| subroutine mskdf(cdat,npts,t2,nfft1,f0,nfreeze,mousedf,ntol,dfx,snrsq2) | ||||
| 
 | ||||
| ! Determine DF for a JTMS signal.  Also find ferr, a measure of | ||||
| ! frequency differerence between 1st and 2nd harmonic.   | ||||
| ! (Should be 0.000) | ||||
| 
 | ||||
|   parameter (NZ=128*1024) | ||||
|   complex cdat(npts) | ||||
|   integer ntol | ||||
|   real sq(NZ) | ||||
|   real ccf(-2600:2600)                  !Correct limits? | ||||
|   real tmp(NZ) | ||||
|   complex c(NZ) | ||||
|   data nsps/8/ | ||||
|   save c | ||||
| 
 | ||||
|   df1=48000.0/nfft1 | ||||
|   nh=nfft1/2 | ||||
|   fac=1.0/(nfft1**2) | ||||
| 
 | ||||
|   do i=1,npts | ||||
|      c(i)=fac*cdat(i)**2 | ||||
|   enddo | ||||
|   c(npts+1:nfft1)=0. | ||||
|   call four2a(c,nfft1,1,-1,1) | ||||
| 
 | ||||
| ! In the "doubled-frequencies" spectrum of squared cdat: | ||||
|   fa=2.0*(f0-400) | ||||
|   fb=2.0*(f0+400) | ||||
|   j0=nint(2.0*f0/df1) | ||||
|   ja=nint(fa/df1) | ||||
|   jb=nint(fb/df1) | ||||
|   jd=nfft1/nsps | ||||
| 
 | ||||
|   do j=1,nh+1 | ||||
|      sq(j)=real(c(j))**2 + aimag(c(j))**2 | ||||
| !     if(j*df1.lt.6000.0) write(54,3009) j*df1,sq(j),db(sq(j)) | ||||
| !3009 format(3f12.3) | ||||
|   enddo | ||||
| 
 | ||||
|   ccf=0. | ||||
|   do j=ja,jb | ||||
|      ccf(j-j0-1)=sq(j)+sq(j+jd) | ||||
|   enddo | ||||
| 
 | ||||
|   call pctile(ccf(ja-j0-1),tmp,jb-ja+1,50,base) | ||||
|   ccf=ccf/base | ||||
| 
 | ||||
|   if(NFreeze.gt.0) then | ||||
|      fa=2.0*(f0+MouseDF-ntol) | ||||
|      fb=2.0*(f0+MouseDF+ntol) | ||||
|   endif   | ||||
|   ja=nint(fa/df1) | ||||
|   jb=nint(fb/df1) | ||||
| 
 | ||||
| !  rewind 51 | ||||
|   smax=0. | ||||
|   do j=ja,jb | ||||
|      k=j-j0-1 | ||||
|      if(ccf(k).gt.smax) then | ||||
|         smax=ccf(k) | ||||
|         jpk=j | ||||
|      endif | ||||
|      f=0.5*k*df1 | ||||
| !     write(51,3002) f,ccf(k) | ||||
| !3002 format(2f12.3) | ||||
|   enddo | ||||
| !  call flush(51) | ||||
| 
 | ||||
|   fpk=(jpk-1)*df1   | ||||
|   dfx=0.5*fpk-f0 | ||||
|   snrsq2=smax | ||||
| 
 | ||||
|   return | ||||
| end subroutine mskdf | ||||
							
								
								
									
										42
									
								
								libm65/ping.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								libm65/ping.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| subroutine ping(s,nz,dtbuf,slim,wmin,pingdat,nping) | ||||
| 
 | ||||
| ! Detect pings and make note of their start time, duration, and peak strength. | ||||
| 
 | ||||
|   real*4 s(nz) | ||||
|   real*4 pingdat(3,100) | ||||
|   logical inside | ||||
| 
 | ||||
|   nping=0 | ||||
|   peak=0. | ||||
|   inside=.false. | ||||
|   snrlim=10.0**(0.1*slim) - 1.0 | ||||
|   sdown=10.0*log10(0.25*snrlim+1.0) | ||||
| 
 | ||||
|   i0=0                                 !Silence compiler warnings. | ||||
|   tstart=0.0 | ||||
|   do i=2,nz | ||||
|      if(s(i).ge.slim .and. .not.inside) then | ||||
|         i0=i | ||||
|         tstart=i0*dtbuf | ||||
|         inside=.true. | ||||
|         peak=0. | ||||
|      endif | ||||
|      if(inside .and. s(i).gt.peak) then | ||||
|         peak=s(i) | ||||
|      endif | ||||
|      if(inside .and. (s(i).lt.sdown .or. i.eq.nz)) then | ||||
|         if(i.gt.i0) then | ||||
|            if(dtbuf*(i-i0).ge.wmin) then | ||||
|               if(nping.le.99) nping=nping+1 | ||||
|               pingdat(1,nping)=tstart | ||||
|               pingdat(2,nping)=dtbuf*(i-i0) | ||||
|               pingdat(3,nping)=peak | ||||
|            endif | ||||
|            inside=.false. | ||||
|            peak=0. | ||||
|         endif | ||||
|      endif | ||||
|   enddo | ||||
| 
 | ||||
|   return | ||||
| end subroutine ping | ||||
							
								
								
									
										103
									
								
								libm65/rtping.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								libm65/rtping.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| subroutine rtping(dat,k,cfile6,MinSigdB,MouseDF,ntol) | ||||
| 
 | ||||
| !subroutine rtping(dat,jz,nz,MinSigdB,MinWidth,NFreeze,DFTolerance,    & | ||||
| !     MouseDF,istart,pick,cfile6,mycall,hiscall,mode,ps0) | ||||
| 
 | ||||
| ! Decode Multi-Tone FSK441 mesages. | ||||
| 
 | ||||
|   parameter (NSMAX=30*48000) | ||||
|   parameter (NZMAX=NSMAX/2048) | ||||
|   real dat(NSMAX)                !Raw audio data | ||||
|   logical pick | ||||
|   character*6 cfile6 | ||||
|   real sig(NZMAX)                !Sq-law detected signal, sampled at 43 ms | ||||
|   real sigdb(NZMAX)              !Signal in dB, sampled at 43 ms | ||||
|   real work(NZMAX) | ||||
|   real pingdat(3,100) | ||||
| !  character msg*40,msg3*3 | ||||
|   character*90 line | ||||
|   common/ccom/nline,tping(100),line(100) | ||||
|   data nping0/0/ | ||||
|   save | ||||
| 
 | ||||
|   slim=MinSigdB | ||||
| !  nf1=-ntol | ||||
| !  nf2=ntol | ||||
|   dt=1.0/48000.0 | ||||
|   kstep=2048 | ||||
| !  pick=.false. | ||||
|   istart=1 | ||||
|   jz=k | ||||
| 
 | ||||
| ! Find signal power | ||||
|   j=k/kstep | ||||
|   sig(j)=dot_product(dat(k-kstep+1:k),dat(k-kstep+1:k))/kstep | ||||
|   if(j.lt.10) return | ||||
| 
 | ||||
| ! Remove baseline, compute signal level in dB  | ||||
|   call pctile (sig,work,j,50,base1) | ||||
|   do i=1,j | ||||
|      sigdb(i)=db(sig(i)/base1) | ||||
|      if(j.eq.703) write(13,3001) i,sig(i),sigdb(i) | ||||
| 3001 format(i5,2e12.3) | ||||
|   enddo | ||||
| 
 | ||||
|   dtbuf=kstep*dt | ||||
|   wmin=0.040 | ||||
|   call ping(sigdb,j,dtbuf,slim,wmin,pingdat,nping) | ||||
| 
 | ||||
| ! If this is a "mouse pick" and no ping was found, force a pseudo-ping  | ||||
| ! at center of data. | ||||
| !  if(pick.and.nping.eq.0) then | ||||
| !     if(nping.le.99) nping=nping+1 | ||||
| !     pingdat(1,nping)=0.5*jz*dt | ||||
| !     pingdat(2,nping)=0.16 | ||||
| !     pingdat(3,nping)=1.0 | ||||
| !  endif | ||||
| 
 | ||||
|   do iping=1,nping | ||||
| ! Find starting place and length of data to be analyzed: | ||||
|      tstart=pingdat(1,iping) | ||||
|      width=pingdat(2,iping) | ||||
|      peak=pingdat(3,iping) | ||||
| !     mswidth=10*nint(100.0*width) | ||||
|      jj=(tstart-0.02)/dt | ||||
|      if(jj.lt.1) jj=1 | ||||
|      jjz=nint((width+0.02)/dt)+1 | ||||
|      jjz=min(jjz,jz+1-jj) | ||||
| 
 | ||||
| ! Compute average spectrum of this ping. | ||||
| !     call spec441(dat(jj),jjz,ps,f0) | ||||
| 
 | ||||
| ! Decode the message. | ||||
| !     msg=' ' | ||||
| !     call longx(dat(jj),jjz,ps,DFTolerance,noffset,msg,msglen,bauderr) | ||||
| 
 | ||||
| ! Assemble a signal report: | ||||
|      nwidth=0 | ||||
|      if(width.ge.0.04) nwidth=1     !These might depend on NSPD | ||||
|      if(width.ge.0.12) nwidth=2 | ||||
|      if(width.gt.1.00) nwidth=3 | ||||
|      nstrength=6 | ||||
|      if(peak.ge.11.0) nstrength=7 | ||||
|      if(peak.ge.17.0) nstrength=8 | ||||
|      if(peak.ge.23.0) nstrength=9 | ||||
| !     nrpt=10*nwidth + nstrength | ||||
|      t2=tstart + dt*(istart-1) | ||||
| 
 | ||||
|      jjzz=min(jjz,2*48000)       !Max data size 2 s  | ||||
| !### | ||||
|      jjzz=14400 | ||||
|      jj=jj-200 | ||||
| !### | ||||
| 
 | ||||
|      if(nping.gt.nping0) then | ||||
|         print*,'a',jj,jjzz,jj*dt,jjzz*dt,t2,width | ||||
|         call jtmsk(dat(jj),jjzz,cfile6,t2,mswidth,int(peak),nrpt,      & | ||||
|              nfreeze,DFTolerance,MouseDF,pick) | ||||
|         nping0=nping | ||||
|      endif | ||||
|   enddo | ||||
| 
 | ||||
|   return | ||||
| end subroutine rtping | ||||
							
								
								
									
										51
									
								
								libm65/setupmsk.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								libm65/setupmsk.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| subroutine setupmsk(cw,cwb) | ||||
| 
 | ||||
| ! Calculate the JTMS character waveforms. | ||||
| 
 | ||||
|   complex cw(168,0:63) | ||||
|   complex cwb(168) | ||||
|   integer nb(7) | ||||
| !  real*8 twopi,dt,f0,f1 | ||||
|   character cc*64 | ||||
| !                   1         2         3         4         5         6 | ||||
| !          0123456789012345678901234567890123456789012345678901234567890123 | ||||
|   data cc/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ./?-                 _     @'/ | ||||
| 
 | ||||
|   nsps=24 | ||||
|   twopi=8.d0*atan(1.d0) | ||||
|   dt=1.d0/48000.d0                     !Sample interval | ||||
|   f0=1000.d0 | ||||
|   f1=2000.d0 | ||||
|   dphi0=twopi*dt*f0 | ||||
|   dphi1=twopi*dt*f1 | ||||
| 
 | ||||
|   do i=0,63 | ||||
|      k=0 | ||||
|      m=0 | ||||
|      do n=5,0,-1                          !Each character gets 6+1 bits | ||||
|         k=k+1 | ||||
|         nb(k)=iand(1,ishft(i,-n)) | ||||
|         m=m+nb(k) | ||||
|      enddo | ||||
|      k=k+1 | ||||
|      nb(k)=iand(m,1)                      !Insert parity bit | ||||
| 
 | ||||
|      phi=0. | ||||
|      j=0 | ||||
|      do k=1,7                             !Generate the waveform | ||||
|         if(nb(k).eq.0) then | ||||
|            dphi=dphi0 | ||||
|         else | ||||
|            dphi=dphi1 | ||||
|         endif | ||||
|         do ii=1,nsps | ||||
|            j=j+1 | ||||
|            phi=phi+dphi | ||||
|            cw(j,i)=cmplx(cos(phi),sin(phi)) | ||||
|         enddo | ||||
|      enddo | ||||
|   enddo | ||||
|   cwb=cw(1:168,57) | ||||
| 
 | ||||
|   return | ||||
| end subroutine setupmsk | ||||
							
								
								
									
										38
									
								
								libm65/syncmsk.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								libm65/syncmsk.f90
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| subroutine syncmsk(cdat,npts,cwb,r,i1) | ||||
| 
 | ||||
| ! Establish character sync within a JTMS ping. | ||||
| 
 | ||||
|   complex cdat(npts)                    !Analytic signal | ||||
|   complex cwb(168)                      !Complex waveform for 'space' | ||||
|   real r(60000) | ||||
|   real tmp(60000) | ||||
|   integer hist(168),hmax(1) | ||||
|   complex z | ||||
| 
 | ||||
|   r=0. | ||||
|   jz=npts-168+1 | ||||
|   do j=1,jz | ||||
|      z=0. | ||||
|      ss=0. | ||||
|      do i=1,168 | ||||
|         ss=ss + abs(cdat(i+j-1))          !Total power | ||||
|         z=z + cdat(i+j-1)*conjg(cwb(i))   !Signal matching <space> | ||||
|      enddo | ||||
|      r(j)=abs(z)/ss                       !Goodness-of-fit to <space> | ||||
| !     write(52,3001) j/168.0,r(j),cdat(j) | ||||
| !3001 format(4f12.3) | ||||
|   enddo | ||||
| 
 | ||||
|   ncut=99.0*float(jz-10)/float(jz) | ||||
|   call pctile(r,tmp,jz,ncut,rlim) | ||||
|   hist=0 | ||||
|   do j=1,jz | ||||
|      k=mod(j-1,168)+1 | ||||
|      if(r(j).gt.rlim) hist(k)=hist(k)+1 | ||||
|   enddo | ||||
| 
 | ||||
|   hmax=maxloc(hist) | ||||
|   i1=hmax(1) | ||||
| 
 | ||||
|   return | ||||
| end subroutine syncmsk | ||||
| @ -1309,7 +1309,7 @@ void MainWindow::ba2msg(QByteArray ba, char message[])             //ba2msg() | ||||
| { | ||||
|   bool eom; | ||||
|   eom=false; | ||||
|   for(int i=0;i<22; i++) { | ||||
|   for(int i=0;i<28; i++) { | ||||
|     if((int)ba[i] == 0) eom=true; | ||||
|     if(eom) { | ||||
|       message[i]=32; | ||||
| @ -1317,7 +1317,7 @@ void MainWindow::ba2msg(QByteArray ba, char message[])             //ba2msg() | ||||
|       message[i]=ba[i]; | ||||
|     } | ||||
|   } | ||||
|   message[22]=0; | ||||
|   message[28]=0; | ||||
| } | ||||
| 
 | ||||
| void MainWindow::on_txFirstCheckBox_stateChanged(int nstate)        //TxFirst
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user