From 1a31e5b2d6d88f32d51cc93c61ddfcaee8631398 Mon Sep 17 00:00:00 2001 From: Steve Franke Date: Sun, 17 Jun 2018 08:44:10 -0500 Subject: [PATCH] For (174,91) code, move CRC generation and testing into encode and decode routines. Make ldpcsim174_91.f90 work with the new encode/decode routines. --- lib/encode128_90.f90 | 5 +- lib/ft8/bpdecode174_91.f90 | 26 +++++---- lib/ft8/encode174_91.f90 | 24 ++++++-- lib/ft8/ldpcsim174_91.f90 | 116 +++++++++---------------------------- lib/ft8/osd174_91.f90 | 7 ++- lib/ldpcsim128_90.f90 | 15 +---- 6 files changed, 70 insertions(+), 123 deletions(-) diff --git a/lib/encode128_90.f90 b/lib/encode128_90.f90 index 808eb1ccd..7377370dc 100644 --- a/lib/encode128_90.f90 +++ b/lib/encode128_90.f90 @@ -1,7 +1,6 @@ subroutine encode128_90(message77,codeword) -! Encode an 90-bit message and return a 128-bit codeword. -! The generator matrix has dimensions (38,90). -! The code is a (128,90) regular ldpc code with column weight 3. +! +! Add a 13-bit CRC to a 77-bit message and return a 128-bit codeword ! use, intrinsic :: iso_c_binding use iso_c_binding, only: c_loc,c_size_t diff --git a/lib/ft8/bpdecode174_91.f90 b/lib/ft8/bpdecode174_91.f90 index 31effb5dd..78809f19e 100644 --- a/lib/ft8/bpdecode174_91.f90 +++ b/lib/ft8/bpdecode174_91.f90 @@ -1,10 +1,14 @@ -subroutine bpdecode174_91(llr,apmask,maxiterations,decoded,cw,nharderror,iter) +subroutine bpdecode174_91(llr,apmask,maxiterations,message77,cw,nharderror,iter) ! ! A log-domain belief propagation decoder for the (174,91) code. ! +use iso_c_binding, only: c_loc,c_size_t +use crc integer, parameter:: N=174, K=91, M=N-K -integer*1 codeword(N),cw(N),apmask(N) +integer*1 cw(N),apmask(N) integer*1 decoded(K) +integer*1 message77(77) +integer nrw(M),ncw integer Nm(7,M) integer Mn(3,N) ! 3 checks per bit integer synd(M) @@ -14,7 +18,6 @@ real tanhtoc(7,M) real zn(N) real llr(N) real Tmn -integer nrw(M),ncw include "ldpc_174_91_c_reordered_parity.f90" @@ -52,15 +55,14 @@ do iter=0,maxiterations ! if( mod(synd(i),2) .ne. 0 ) write(*,*) 'check ',i,' unsatisfied' enddo ! write(*,*) 'number of unsatisfied parity checks ',ncheck - if( ncheck .eq. 0 ) then ! we have a codeword - reorder the columns and return it - codeword=cw - decoded=codeword(1:K) - nerr=0 - do i=1,N - if( (2*cw(i)-1)*llr(i) .lt. 0.0 ) nerr=nerr+1 - enddo - nharderror=nerr - return + if( ncheck .eq. 0 ) then ! we have a codeword - if crc is good, return it + decoded=cw(1:K) + call chkcrc14a(decoded,nbadcrc) + nharderror=count( (2*cw-1)*llr .lt. 0.0 ) + if(nbadcrc.eq.0) then + message77=decoded(1:77) + return + endif endif if( iter.gt.0 ) then ! this code block implements an early stopping criterion diff --git a/lib/ft8/encode174_91.f90 b/lib/ft8/encode174_91.f90 index 6b09f837d..0ffa4841a 100644 --- a/lib/ft8/encode174_91.f90 +++ b/lib/ft8/encode174_91.f90 @@ -1,15 +1,18 @@ -subroutine encode174_91(message,codeword) -! Encode an 91-bit message and return a 174-bit codeword. -! The generator matrix has dimensions (83,91). -! The code is a (174,91) regular ldpc code with column weight 3. +subroutine encode174_91(message77,codeword) ! +! Add a 14-bit CRC to a 77-bit message and return a 174-bit codeword +! +use, intrinsic :: iso_c_binding +use iso_c_binding, only: c_loc,c_size_t +use crc integer, parameter:: N=174, K=91, M=N-K - +character*91 tmpchar integer*1 codeword(N) integer*1 gen(M,K) -integer*1 message(K) +integer*1 message77(77),message(K) integer*1 pchecks(M) +integer*1, target :: i1MsgBytes(12) include "ldpc_174_91_c_generator.f90" logical first data first/.true./ @@ -31,6 +34,15 @@ if( first ) then ! fill the generator matrix first=.false. endif +! Add 14-bit CRC to form 91-bit message+CRC14 +write(tmpchar,'(77i1)') message77 +tmpchar(78:80)='000' +i1MsgBytes=0 +read(tmpchar,'(10b8)') i1MsgBytes(1:10) +ncrc14 = crc14 (c_loc (i1MsgBytes), 12) +write(tmpchar(78:91),'(b14)') ncrc14 +read(tmpchar,'(91i1)') message + do i=1,M nsum=0 do j=1,K diff --git a/lib/ft8/ldpcsim174_91.f90 b/lib/ft8/ldpcsim174_91.f90 index 5b58dd177..7410d7363 100644 --- a/lib/ft8/ldpcsim174_91.f90 +++ b/lib/ft8/ldpcsim174_91.f90 @@ -7,20 +7,18 @@ integer, parameter:: N=174, K=91, M=N-K character*22 msg,msgsent,msgreceived character*8 arg character*6 grid +character*96 tmpchar integer*1, allocatable :: codeword(:), decoded(:), message(:) -integer*1, target:: i1Msg8BitBytes(12) -integer*1 msgbits(K) +integer*1 msgbits(77) +integer*1 message77(77) integer*1 apmask(N), cw(N) -integer*2 checksum integer*4 i4Msg6BitWords(13) -integer nerrtot(N),nerrdec(N),nmpcbad(K) -logical checksumok +integer nerrtot(0:N),nerrdec(0:N) real*8, allocatable :: rxdata(:) real, allocatable :: llr(:) nerrtot=0 nerrdec=0 -nmpcbad=0 ! Used to collect the number of errors in the message+crc part of the codeword nargs=iargc() if(nargs.ne.4) then @@ -54,73 +52,31 @@ allocate ( rxdata(N), llr(N) ) call unpackmsg(i4Msg6BitWords,msgsent,.false.,grid) !Unpack to get msgsent write(*,*) "message sent ",msgsent - i4=0 - ik=0 - im=0 - do i=1,12 - nn=i4Msg6BitWords(i) - do j=1, 6 - ik=ik+1 - i4=i4+i4+iand(1,ishft(nn,j-6)) - i4=iand(i4,255) - if(ik.eq.8) then - im=im+1 -! if(i4.gt.127) i4=i4-256 - i1Msg8BitBytes(im)=i4 - ik=0 - endif - enddo - enddo - - i1Msg8BitBytes(10:12)=0 - checksum = crc14 (c_loc (i1Msg8BitBytes), 12) -! For reference, the next 3 lines show how to check the CRC - i1Msg8BitBytes(11)=checksum/256 - i1Msg8BitBytes(12)=iand (checksum,255) - checksumok = crc14_check(c_loc (i1Msg8BitBytes), 12) - if( checksumok ) write(*,*) 'Good checksum' - -! K=91, For now: -! msgbits(1:72) JT message bits -! msgbits(73:77) 5 free message bits (set to 0) -! msgbits(78:91) CRC14 - mbit=0 - do i=1, 9 - i1=i1Msg8BitBytes(i) - do ibit=1,8 - mbit=mbit+1 - msgbits(mbit)=iand(1,ishft(i1,ibit-8)) - enddo - enddo - msgbits(73:77)=0 ! the five extra message bits go here - i1=i1Msg8BitBytes(11) ! First 6 bits of crc12 are LSB of this byte - do ibit=1,6 - msgbits(77+ibit)=iand(1,ishft(i1,ibit-6)) - enddo - i1=i1Msg8BitBytes(12) ! Now shift in last 8 bits of the CRC - do ibit=1,8 - msgbits(83+ibit)=iand(1,ishft(i1,ibit-8)) - enddo + tmpchar=' ' + write(tmpchar,'(12b6.6)') i4Msg6BitWords(1:12) + tmpchar(73:77)='00000' !i5bit + read(tmpchar,'(77i1)') msgbits(1:77) write(*,*) 'message' - write(*,'(12(8i1,1x))') msgbits + write(*,'(28i1,1x,28i1,1x,16i1,1x,5i1)') msgbits +! msgbits is the 77-bit message, codeword is 174 bits call encode174_91(msgbits,codeword) + call init_random_seed() -! call sgran() write(*,*) 'codeword' write(*,'(22(8i1,1x))') codeword -write(*,*) "Eb/N0 SNR2500 ngood nundetected nbadcrc sigma" +write(*,*) "Eb/N0 SNR2500 ngood nundetected sigma psymerr" do idb = 20,-10,-1 !do idb = 0,0,-1 db=idb/2.0-1.0 sigma=1/sqrt( 2*rate*(10**(db/10.0)) ) ngood=0 nue=0 - nbadcrc=0 - nberr=0 + nsumerr=0 + do itrial=1, ntrials ! Create a realization of a noisy received word do i=1,N @@ -131,7 +87,6 @@ do idb = 20,-10,-1 if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1 enddo if(nerr.ge.1) nerrtot(nerr)=nerrtot(nerr)+1 - nberr=nberr+nerr rxav=sum(rxdata)/N rx2av=sum(rxdata*rxdata)/N @@ -150,38 +105,26 @@ do idb = 20,-10,-1 apmask(1:nap)=1 ! max_iterations is max number of belief propagation iterations - call bpdecode174_91(llr, apmask, max_iterations, decoded, cw, nharderrors,niterations) - if( ndepth .ge. 0 .and. nharderrors .lt. 0 ) call osd174_91(llr, apmask, ndepth, decoded, cw, nharderrors, dmin) + call bpdecode174_91(llr, apmask, max_iterations, message77, cw, nharderrors,niterations) + if( ndepth .ge. 0 .and. nharderrors .lt. 0 ) call osd174_91(llr, apmask, ndepth, message77, cw, nharderrors, dmin) ! If the decoder finds a valid codeword, nharderrors will be .ge. 0. if( nharderrors .ge. 0 ) then - call extractmessage174_91(decoded,msgreceived,ncrcflag) - if( ncrcflag .ne. 1 ) then - nbadcrc=nbadcrc+1 - endif - - nueflag=0 - nerrmpc=0 - do i=1,K ! find number of errors in message+crc part of codeword - if( msgbits(i) .ne. decoded(i) ) then - nueflag=1 - nerrmpc=nerrmpc+1 - endif - enddo - if(nerrmpc.ge.1) nmpcbad(nerrmpc)=nmpcbad(nerrmpc)+1 - if( ncrcflag .eq. 1 ) then - if( nueflag .eq. 0 ) then - ngood=ngood+1 - if(nerr.ge.1) nerrdec(nerr)=nerrdec(nerr)+1 - else if( nueflag .eq. 1 ) then - nue=nue+1; - endif + call extractmessage77(message77,msgreceived) + nhw=count(cw.ne.codeword) + if(nhw.eq.0) then ! this is a good decode + ngood=ngood+1 + nerrdec(nerr)=nerrdec(nerr)+1 + else + nue=nue+1 endif endif + nsumerr=nsumerr+nerr enddo + baud=12000/1920 snr2500=db+10.0*log10((baud/2500.0)) - pberr=real(nberr)/(real(ntrials*N)) - write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,1x,i8,8x,f5.2,8x,e10.3)") db,SNR2500,ngood,nue,nbadcrc,ss,pberr + pberr=real(nsumerr)/(real(ntrials*N)) + write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,8x,f5.2,8x,e10.3)") db,SNR2500,ngood,nue,ss,pberr enddo @@ -190,10 +133,5 @@ do i=1,174 write(23,'(i4,2x,i10,i10,f10.2)') i,nerrdec(i),nerrtot(i),real(nerrdec(i))/real(nerrtot(i)+1e-10) enddo close(23) -open(unit=25,file='nmpcbad.dat',status='unknown') -do i=1,87 - write(25,'(i4,2x,i10)') i,nmpcbad(i) -enddo -close(25) end program ldpcsim174_91 diff --git a/lib/ft8/osd174_91.f90 b/lib/ft8/osd174_91.f90 index 7a9cb1076..958b0c9fd 100644 --- a/lib/ft8/osd174_91.f90 +++ b/lib/ft8/osd174_91.f90 @@ -1,4 +1,4 @@ -subroutine osd174_91(llr,apmask,ndeep,decoded,cw,nhardmin,dmin) +subroutine osd174_91(llr,apmask,ndeep,message77,cw,nhardmin,dmin) ! ! An ordered-statistics decoder for the (174,91) code. ! @@ -11,6 +11,7 @@ integer*1 r2pat(N-K) integer indices(N),nxor(N) integer*1 cw(N),ce(N),c0(N),hdec(N) integer*1 decoded(K) +integer*1 message77(77) integer indx(N) real llr(N),rx(N),absrx(N) @@ -247,6 +248,10 @@ endif cw(indices)=cw hdec(indices)=hdec decoded=cw(1:K) +call chkcrc14a(decoded,nbadcrc) +message77=decoded(1:77) +if(nbadcrc.eq.1) nhardmin=-nhardmin + return end subroutine osd174_91 diff --git a/lib/ldpcsim128_90.f90 b/lib/ldpcsim128_90.f90 index a3346b5b9..6ddfda22d 100644 --- a/lib/ldpcsim128_90.f90 +++ b/lib/ldpcsim128_90.f90 @@ -9,9 +9,8 @@ character*8 arg integer*1 codeword(N), message77(77) integer*1 apmask(N),cw(N) integer*1 msgbits(77) -integer*2 ncrc13 integer*4 i4Msg6BitWords(13) -integer nerrtot(0:N),nerrdec(0:N),nmpcbad(0:K),nbadwt(0:N) +integer nerrtot(0:N),nerrdec(0:N) real*8 rxdata(N), rxavgd(N) real llr(N) @@ -20,8 +19,6 @@ do i=1,NRECENT enddo nerrtot=0 nerrdec=0 -nmpcbad=0 -nbadwt=0 nargs=iargc() if(nargs.ne.4) then @@ -55,7 +52,7 @@ msg="G4WJS K1JT FN20" read(tmpchar,'(77i1)') msgbits(1:77) write(*,*) 'msgbits' - write(*,'(28i1,1x,28i1,1x,16i1,1x,5i1,1x,13i1)') msgbits + write(*,'(28i1,1x,28i1,1x,16i1,1x,5i1)') msgbits ! msgbits is the 77-bit message, codeword is 128 bits call encode128_90(msgbits,codeword) @@ -109,7 +106,7 @@ do idb = 14,-6,-1 ! If the decoder finds a valid codeword, nharderrors will be .ge. 0. if( nharderrors .ge. 0 ) then call extractmessage77(message77,msgreceived) - nhw=count(message77.ne.codeword(1:77)) + nhw=count(cw.ne.codeword) if(nhw.eq.0) then ! this is a good decode ngood=ngood+1 nerrdec(nerr)=nerrdec(nerr)+1 @@ -132,10 +129,4 @@ do i=0,N enddo close(23) -open(unit=25,file='badcrc_hamming_weight.dat',status='unknown') -do i=0,N - write(25,'(i4,2x,i10)') i,nbadwt(i) -enddo -close(25) - end program ldpcsim