More work on msk144.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6778 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Steven Franke 2016-06-16 23:18:22 +00:00
parent 9734a70242
commit 469b57cbd0
2 changed files with 123 additions and 146 deletions

View File

@ -1,12 +1,7 @@
subroutine detectmsk144(cbig,n,pchk_file,lines,nmessages,nutc) subroutine detectmsk144(cbig,n,pchk_file,lines,nmessages,nutc)
!nutc and t0 are for debug output
use iso_c_binding, only: c_loc,c_size_t
use packjt
use hashing
use timer_module, only: timer use timer_module, only: timer
parameter (NSPM=864, NPTS=3*NSPM) parameter (NSPM=864, NPTS=3*NSPM, MAXSTEPS=1500)
integer, parameter :: nstep=693
character*22 msgreceived,allmessages(20) character*22 msgreceived,allmessages(20)
character*80 lines(100) character*80 lines(100)
character*512 pchk_file,gen_file character*512 pchk_file,gen_file
@ -22,17 +17,14 @@ subroutine detectmsk144(cbig,n,pchk_file,lines,nmessages,nutc)
complex cc2(NPTS) complex cc2(NPTS)
complex bb(6) complex bb(6)
integer s8(8),hardbits(144) integer s8(8),hardbits(144)
integer*1, target:: i1Dec8BitBytes(10)
integer, dimension(1) :: iloc integer, dimension(1) :: iloc
integer*4 i4Dec6BitWords(12)
integer*1 decoded(80) integer*1 decoded(80)
integer*1 i1hashdec integer indices(MAXSTEPS)
integer indices(nstep)
integer ipeaks(10) integer ipeaks(10)
logical ismask(6000) logical ismask(6000)
real cbi(42),cbq(42) real cbi(42),cbq(42)
real detmet(-2:nstep+3) real detmet(-2:MAXSTEPS+3)
real detfer(nstep) real detfer(MAXSTEPS)
real tonespec(6000) real tonespec(6000)
real rcw(12) real rcw(12)
real dd(NPTS) real dd(NPTS)
@ -46,11 +38,11 @@ subroutine detectmsk144(cbig,n,pchk_file,lines,nmessages,nutc)
real lratio(128) real lratio(128)
logical first logical first
data first/.true./ data first/.true./
data s8/0,1,1,1,0,0,1,0/ data s8/0,1,1,1,0,0,1,0/
save df,first,cb,fs,nfft,pi,twopi,dt,s8,rcw,pp save df,first,cb,fs,nfft,pi,twopi,dt,s8,rcw,pp
if(first) then if(first) then
nmatchedfilter=1
i=index(pchk_file,".pchk") i=index(pchk_file,".pchk")
gen_file=pchk_file(1:i-1)//".gen" gen_file=pchk_file(1:i-1)//".gen"
call init_ldpc(trim(pchk_file)//char(0),trim(gen_file)//char(0)) call init_ldpc(trim(pchk_file)//char(0),trim(gen_file)//char(0))
@ -84,12 +76,12 @@ subroutine detectmsk144(cbig,n,pchk_file,lines,nmessages,nutc)
endif endif
! fill the detmet, detferr arrays ! fill the detmet, detferr arrays
nstep=(n-NSPM)/256
detmet=0 detmet=0
do istp=1,nstep do istp=1,nstep
ns=1+256*(istp-1) ns=1+256*(istp-1)
ne=ns+NPTS-1 ne=ns+NPTS-1
if( ne .gt. n ) exit if( ne .gt. n ) exit
tt=(ns+ne)/2.0/12000.0
cdat=cbig(ns:ne) cdat=cbig(ns:ne)
! Coarse carrier frequency sync - seek tones at 2000 Hz and 4000 Hz in ! Coarse carrier frequency sync - seek tones at 2000 Hz and 4000 Hz in
@ -127,7 +119,7 @@ subroutine detectmsk144(cbig,n,pchk_file,lines,nmessages,nutc)
endif endif
detmet(istp)=ah+al detmet(istp)=ah+al
detfer(istp)=ferr detfer(istp)=ferr
enddo ! end of detection-metric, snr, and frequency error estimation loop enddo ! end of detection-metric and frequency error estimation loop
call indexx(detmet(1:nstep),nstep,indices) !find median of detection metric vector call indexx(detmet(1:nstep),nstep,indices) !find median of detection metric vector
xmed=detmet(indices(nstep/2)) xmed=detmet(indices(nstep/2))
@ -138,7 +130,7 @@ subroutine detectmsk144(cbig,n,pchk_file,lines,nmessages,nutc)
do ip=1,20 ! use something like the "clean" algorithm to find candidates do ip=1,20 ! use something like the "clean" algorithm to find candidates
iloc=maxloc(detmet(1:nstep)) iloc=maxloc(detmet(1:nstep))
il=iloc(1) il=iloc(1)
if( (detmet(il) .lt. 2.0) .or. (abs(detfer(il)) .gt. 100.0) ) cycle if( (detmet(il) .lt. 1.5) .or. (abs(detfer(il)) .gt. 100.0) ) cycle
ndet=ndet+1 ndet=ndet+1
times(ndet)=((il-1)*256+NPTS/2)*dt times(ndet)=((il-1)*256+NPTS/2)*dt
ferrs(ndet)=detfer(il) ferrs(ndet)=detfer(il)
@ -188,7 +180,6 @@ subroutine detectmsk144(cbig,n,pchk_file,lines,nmessages,nutc)
ic0=ipeaks(ipk) ic0=ipeaks(ipk)
! fine adjustment of sync index ! fine adjustment of sync index
! bb lag used to place the sampling index at the center of the eye
do i=1,6 do i=1,6
if( ic0+11+NSPM .le. NPTS ) then if( ic0+11+NSPM .le. NPTS ) then
bb(i) = sum( ( cdat(ic0+i-1+6:ic0+i-1+6+NSPM:6) * conjg( cdat(ic0+i-1:ic0+i-1+NSPM:6) ) )*2 ) bb(i) = sum( ( cdat(ic0+i-1+6:ic0+i-1+6+NSPM:6) * conjg( cdat(ic0+i-1:ic0+i-1+NSPM:6) ) )*2 )
@ -201,7 +192,8 @@ subroutine detectmsk144(cbig,n,pchk_file,lines,nmessages,nutc)
bba=abs(bb(ibb)) bba=abs(bb(ibb))
if( ibb .le. 3 ) ibb=ibb-1 if( ibb .le. 3 ) ibb=ibb-1
if( ibb .gt. 3 ) ibb=ibb-7 if( ibb .gt. 3 ) ibb=ibb-7
do id=1,3 ! slicer dither
do id=1,3 ! slicer dither. bb is very good - may be able to remove this.
if( id .eq. 1 ) is=0 if( id .eq. 1 ) is=0
if( id .eq. 2 ) is=-1 if( id .eq. 2 ) is=-1
if( id .eq. 3 ) is=1 if( id .eq. 3 ) is=1
@ -224,152 +216,136 @@ subroutine detectmsk144(cbig,n,pchk_file,lines,nmessages,nutc)
endif endif
! Final estimate of the carrier frequency - returned to the calling program ! Final estimate of the carrier frequency - returned to the calling program
fest=1500+ferr+ferr2 fest=1500+ferr+ferr2
do idf=0,10 ! frequency jitter
if( idf .eq. 0 ) then
deltaf=0.0
elseif( mod(idf,2) .eq. 0 ) then
deltaf=idf/2.0
else
deltaf=-(idf+1)/2.0
endif
! Remove fine frequency error ! Remove fine frequency error
call tweak1(cdat,NPTS,-ferr2,cdat2) call tweak1(cdat,NPTS,-(ferr2+deltaf),cdat2)
! place the beginning of frame at index NSPM+1 ! place the beginning of frame at index NSPM+1
cdat2=cshift(cdat2,ic-(NSPM+1)) cdat2=cshift(cdat2,ic-(NSPM+1))
do iav=1,7 ! try each of 7 averaging patterns, hope that one works do iav=1,8 ! Hopefully we can eliminate some of these after looking at more examples
if( iav .eq. 1 ) then
if( iav .eq. 1 ) then c=cdat2(NSPM+1:2*NSPM)
c(1:NSPM)=cdat2(NSPM+1:2*NSPM) !avg 1 frame to the right of ic elseif( iav .eq. 2 ) then
elseif( iav .eq. 2 ) then c=cdat2(NSPM-431:NSPM+432)
c=cdat2(NSPM-431:NSPM+432) !1 frame centered on ic c=cshift(c,-432)
c=cshift(c,-432) elseif( iav .eq. 3 ) then
elseif( iav .eq. 3 ) then !1 frame to the left of ic c=cdat2(2*NSPM-431:2*NSPM+432)
c=cdat2(1:NSPM) c=cshift(c,-432)
elseif( iav .eq. 4 ) then elseif( iav .eq. 4 ) then
c=cdat2(NSPM+432:NSPM+432+863) !1 frame beginning 36ms to the right of ic c=cdat2(1:NSPM)
c=cshift(c,432) elseif( iav .eq. 5 ) then
elseif( iav .eq. 5 ) then c=cdat2(2*NSPM+1:NPTS)
c=cdat2(1:NSPM)+cdat2(NSPM+1:2*NSPM) elseif( iav .eq. 6 ) then
elseif( iav .eq. 6 ) then c=cdat2(1:NSPM)+cdat2(NSPM+1:2*NSPM)
c=cdat2(NSPM+1:2*NSPM)+cdat2(2*NSPM+1:NPTS) elseif( iav .eq. 7 ) then
elseif( iav .eq. 7 ) then c=cdat2(NSPM+1:2*NSPM)+cdat2(2*NSPM+1:NPTS)
c=cdat2(1:NSPM)+cdat2(NSPM+1:2*NSPM)+cdat2(2*NSPM+1:NPTS) elseif( iav .eq. 8 ) then
endif c=cdat2(1:NSPM)+cdat2(NSPM+1:2*NSPM)+cdat2(2*NSPM+1:NPTS)
endif
! Estimate final frequency error and carrier phase. ! Estimate final frequency error and carrier phase.
cca=sum(c(1:1+41)*conjg(cb)) cca=sum(c(1:1+41)*conjg(cb))
ccb=sum(c(1+56*6:1+56*6+41)*conjg(cb)) ccb=sum(c(1+56*6:1+56*6+41)*conjg(cb))
cfac=ccb*conjg(cca) cfac=ccb*conjg(cca)
ffin=atan2(imag(cfac),real(cfac))/(twopi*56*6*dt) ffin=atan2(imag(cfac),real(cfac))/(twopi*56*6*dt)
phase0=atan2(imag(cca+ccb),real(cca+ccb)) phase0=atan2(imag(cca+ccb),real(cca+ccb))
! Remove phase error - want constellation such that sample points lie on re,im axes ! Remove phase error - want constellation rotated so that sample points lie on I/Q axes
cfac=cmplx(cos(phase0),sin(phase0)) cfac=cmplx(cos(phase0),sin(phase0))
c=c*conjg(cfac) c=c*conjg(cfac)
if( nmatchedfilter .eq. 0 ) then
! sample to get softsamples ! sample to get softsamples
! do i=1,72 do i=1,72
! softbits(2*i-1)=imag(c(1+(i-1)*12)) softbits(2*i-1)=imag(c(1+(i-1)*12))
! softbits(2*i)=real(c(7+(i-1)*12)) softbits(2*i)=real(c(7+(i-1)*12))
! enddo enddo
else
! matched filter - might be possible to improve this ! matched filter -
softbits(1)=sum(imag(c(1:6))*pp(7:12))+sum(imag(c(864-5:864))*pp(1:6)) ! how much mismatch does the RX/TX/analytic filter cause?, how rig (pair) dependent is this loss?
softbits(2)=sum(real(c(1:12))*pp) softbits(1)=sum(imag(c(1:6))*pp(7:12))+sum(imag(c(864-5:864))*pp(1:6))
do i=2,72 softbits(2)=sum(real(c(1:12))*pp)
softbits(2*i-1)=sum(imag(c(1+(i-1)*12-6:1+(i-1)*12+5))*pp) do i=2,72
softbits(2*i)=sum(real(c(7+(i-1)*12-6:7+(i-1)*12+5))*pp) softbits(2*i-1)=sum(imag(c(1+(i-1)*12-6:1+(i-1)*12+5))*pp)
enddo softbits(2*i)=sum(real(c(7+(i-1)*12-6:7+(i-1)*12+5))*pp)
enddo
hardbits=0
do i=1,144
if( softbits(i) .ge. 0.0 ) then
hardbits(i)=1
endif endif
enddo
nbadsync1=(8-sum( (2*hardbits(1:8)-1)*s8 ) )/2 ! sync word hard error weight is a good discriminator for
nbadsync2=(8-sum( (2*hardbits(1+56:8+56)-1)*s8 ) )/2 ! frames that have reasonable probability of decoding
nbadsync=nbadsync1+nbadsync2 hardbits=0
if( nbadsync .gt. 4 ) cycle do i=1,144
if( softbits(i) .ge. 0.0 ) then
hardbits(i)=1
endif
enddo
nbadsync1=(8-sum( (2*hardbits(1:8)-1)*s8 ) )/2
nbadsync2=(8-sum( (2*hardbits(1+56:8+56)-1)*s8 ) )/2
nbadsync=nbadsync1+nbadsync2
if( nbadsync .gt. 6 ) cycle
! normalize the softsymbols before submitting to decoder ! normalize the softsymbols before submitting to decoder
sav=sum(softbits)/144 sav=sum(softbits)/144
s2av=sum(softbits*softbits)/144 s2av=sum(softbits*softbits)/144
ssig=sqrt(s2av-sav*sav) ssig=sqrt(s2av-sav*sav)
softbits=softbits/ssig softbits=softbits/ssig
sigma=0.65 sigma=0.65
lratio(1:48)=softbits(9:9+47) lratio(1:48)=softbits(9:9+47)
lratio(49:128)=softbits(65:65+80-1) lratio(49:128)=softbits(65:65+80-1)
lratio=exp(2.0*lratio/(sigma*sigma)) lratio=exp(2.0*lratio/(sigma*sigma))
unscrambledsoftbits(1:127:2)=lratio(1:64) unscrambledsoftbits(1:127:2)=lratio(1:64)
unscrambledsoftbits(2:128:2)=lratio(65:128) unscrambledsoftbits(2:128:2)=lratio(65:128)
max_iterations=20 max_iterations=20
max_dither=1 max_dither=1
call ldpc_decode(unscrambledsoftbits, decoded, & call ldpc_decode(unscrambledsoftbits, decoded, &
max_iterations, niterations, max_dither, ndither) max_iterations, niterations, max_dither, ndither)
if( niterations .ge. 0.0 ) then if( niterations .ge. 0.0 ) then
goto 778 call extractmessage144(decoded,msgreceived,nhashflag)
endif if( nhashflag .gt. 0 ) then ! CRCs match, so print it
ndupe=0
enddo ! frame averaging loop do im=1,nmessages
if( allmessages(im) .eq. msgreceived ) ndupe=1
enddo
if( ndupe .eq. 0 ) then
nmessages=nmessages+1
allmessages(nmessages)=msgreceived
write(lines(nmessages),1020) nutc,nsnr,t0,nint(fest),msgreceived
1020 format(i6.6,i4,f5.1,i5,' & ',a22)
endif
goto 999
else
msgreceived=' '
ndither=-99 ! -99 is bad hash flag
! write(78,1001) nutc,t0,nsnr,ipk,is,idf,iav,deltaf,fest,ffin,nbadsync1,nbadsync2, &
! phase0,niterations,ndither,msgreceived
endif
endif
enddo ! frame averaging loop
enddo ! frequency dithering loop
enddo ! sample-time dither loop enddo ! sample-time dither loop
enddo ! peak loop - could be made more efficient enddo ! peak loop - could be made more efficient by working harder to find good peaks
msgreceived=' ' msgreceived=' '
phase0=-98 ndither=-98
i1hashdec=0
goto 999
778 continue
! The decoder found a codeword - compare decoded hash with calculated
! Collapse 80 decoded bits to 10 bytes. Bytes 1-9 are the message, byte 10 is the hash
do ibyte=1,10
itmp=0
do ibit=1,8
itmp=ishft(itmp,1)+iand(1,decoded((ibyte-1)*8+ibit))
enddo
i1Dec8BitBytes(ibyte)=itmp
enddo
! Calculate the hash using the first 9 bytes.
ihashdec=nhash(c_loc(i1Dec8BitBytes),int(9,c_size_t),146)
ihashdec=2*iand(ihashdec,255)
! Compare calculated hash with received byte 10 - if they agree, keep the message.
i1hashdec=ihashdec
if( i1hashdec .eq. i1Dec8BitBytes(10) ) then
! Good hash --- unpack 72-bit message
do ibyte=1,12
itmp=0
do ibit=1,6
itmp=ishft(itmp,1)+iand(1,decoded((ibyte-1)*6+ibit))
enddo
i4Dec6BitWords(ibyte)=itmp
enddo
call unpackmsg(i4Dec6BitWords,msgreceived)
else
msgreceived=' '
phase0=-99
endif
if( msgreceived .ne. ' ' ) then
ndupe=0
do im=1,nmessages
if( allmessages(im) .eq. msgreceived ) ndupe=1
enddo
if( ndupe .eq. 0 ) then
nmessages=nmessages+1
allmessages(nmessages)=msgreceived
write(lines(nmessages),1020) nutc,nsnr,t0,nint(fest),msgreceived
1020 format(i6.6,i4,f5.1,i5,' & ',a22)
endif
endif
999 continue 999 continue
! write(78,1001) nutc,t0,iav,ipk,is,fest,ffin,nbadsync1,nbadsync2, & ! write(78,1001) nutc,t0,nsnr,ipk,is,idf,iav,deltaf,fest,ffin,nbadsync1,nbadsync2, &
! phase0,niterations,ndither,i1hashdec,i1Dec8BitBytes(10),msgreceived ! phase0,niterations,ndither,msgreceived
!1001 format(i6,f8.2,i4,i4,i4,f8.2,f8.2,i4,i4,f8.2,i4,i4,i4,i4,2x,a22) !1001 format(i6.6,f8.2,i4,i4,i4,i4,i4,f8.2,f8.2,f8.2,i4,i4,f8.2,i5,i5,2x,a22)
enddo enddo
return return
end subroutine detectmsk144 end subroutine detectmsk144

View File

@ -12,8 +12,8 @@ program msk144d
character*512 pchk_file character*512 pchk_file
logical :: display_help=.false. logical :: display_help=.false.
type(wav_header) :: wav type(wav_header) :: wav
integer*2 id2(15*12000) integer*2 id2(30*12000)
character*80 infile character*500 infile
character(len=500) optarg character(len=500) optarg
type (option) :: long_options(2) = [ & type (option) :: long_options(2) = [ &
@ -60,7 +60,8 @@ program msk144d
i1=index(infile,'.wav') i1=index(infile,'.wav')
if( i1 .eq. 0 ) i1=index(infile,'.WAV') if( i1 .eq. 0 ) i1=index(infile,'.WAV')
read(infile(i1-6:i1-1),*,err=998) nutc read(infile(i1-6:i1-1),*,err=998) nutc
npts=15*12000 inquire(FILE=infile,SIZE=isize)
npts=min((isize-216)/2,360000)
read(unit=wav%lun) id2(1:npts) read(unit=wav%lun) id2(1:npts)
close(unit=wav%lun) close(unit=wav%lun)
call timer('read ',1) call timer('read ',1)