From 71137e972928c15694675c90d73ad5f3190f4b2c Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Mon, 30 Oct 2017 21:35:44 +0000 Subject: [PATCH] Add some experimental routines. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@8201 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- lib/fsk4hf/gf64_osd.f90 | 108 +++++++++++++++++++++++++++ lib/fsk4hf/gf64math.f90 | 59 +++++++++++++++ lib/fsk4hf/jt65_generator_matrix.f90 | 75 +++++++++++++++++++ lib/fsk4hf/jt65osdtest.f90 | 32 ++++++++ 4 files changed, 274 insertions(+) create mode 100644 lib/fsk4hf/gf64_osd.f90 create mode 100644 lib/fsk4hf/gf64math.f90 create mode 100644 lib/fsk4hf/jt65_generator_matrix.f90 create mode 100644 lib/fsk4hf/jt65osdtest.f90 diff --git a/lib/fsk4hf/gf64_osd.f90 b/lib/fsk4hf/gf64_osd.f90 new file mode 100644 index 000000000..2755b51d8 --- /dev/null +++ b/lib/fsk4hf/gf64_osd.f90 @@ -0,0 +1,108 @@ +subroutine gf64_osd(mrsym,mrprob,mr2sym,mr2prob,cw) + use jt65_generator_matrix + integer mrsym(63),mrprob(63),mr2sym(63),mr2prob(63),cw(63) + integer indx(63) + integer gmrb(12,63) + integer correct(63) + integer correctr(63) + integer candidate(63) + integer candidater(63) + logical mask(63) + data correct/ & ! K1ABC W9XYZ EN37 + 41, 0, 54, 46, 55, 29, 57, 35, 35, 48, 48, 61, & + 21, 58, 25, 10, 50, 43, 28, 37, 10, 2, 61, 55, & + 25, 5, 5, 57, 28, 11, 32, 45, 16, 55, 31, 46, & + 44, 55, 34, 38, 50, 62, 52, 58, 17, 62, 35, 34, & + 28, 21, 15, 47, 33, 20, 15, 28, 58, 4, 58, 61, & + 59, 42, 2/ + + correctr=correct(63:1:-1) + call indexx(mrprob,63,indx) +! do i=1,63 +! write(*,*) i,correctr(indx(i)),mrsym(indx(i)),mr2sym(indx(i)) +! enddo + + nhard=count(mrsym.ne.correctr) + nerrtop12=count(mrsym(indx(52:63)).ne.correctr(indx(52:63))) + nerrnext12=count(mrsym(indx(40:51)).ne.correctr(indx(40:51))) + write(*,*) 'nerr, nerrtop12, nerrnext12 ',nerr,nerrtop12,nerrnext12 + +! The best 12 symbols will be used as the Most Reliable Basis +! Reorder the columns of the generator matrix in order of decreasing quality. + do i=1,63 + gmrb(:,i)=g(:,indx(63+1-i)) + enddo +! Put the generator matrix in standard form so that top 12 symbols are +! encoded systematically. + call gf64_standardize_genmat(gmrb) + +! Add various error patterns to the 12 basis symbols and reencode each one +! to get a list of codewords. For now, just find the zero'th order codeword. + call gf64_encode(gmrb,mrsym(indx(63:52:-1)),candidate) +! Undo the sorting to put the codeword symbols back into the "right" order. + candidater=candidate(63:1:-1) + candidate(indx)=candidater + +!write(*,'(63i3)') candidate +!write(*,'(63i3)') correctr +!write(*,'(63i3)') mrsym + nerr=count(correctr.ne.candidate) +write(*,*) 'Number of differences between candidate and correct codeword: ',nerr + if( nerr .eq. 0 ) write(*,*) 'Successful decode' + return +end subroutine gf64_osd + +subroutine gf64_standardize_genmat(gmrb) + use gf64math + integer gmrb(12,63),temp(63),gkk,gjk,gkkinv + do k=1,12 + gkk=gmrb(k,k) + if(gkk.eq.0) then ! zero pivot - swap with the first row with nonzero value + do kk=k+1,12 + if(gmrb(kk,k).ne.0) then + temp=gmrb(k,:) + gmrb(k,:)=gmrb(kk,:) + gmrb(kk,:)=temp + gkk=gmrb(k,k) + goto 20 + endif + enddo + endif +20 gkkinv=gf64_inverse(gkk) + do ic=1,63 + gmrb(k,ic)=gf64_product(gmrb(k,ic),gkkinv) + enddo + do j=1,12 + if(j.ne.k) then + gjk=gmrb(j,k) + do ic=1,63 + gmrb(j,ic)=gf64_sum(gmrb(j,ic),gf64_product(gmrb(k,ic),gjk)) + enddo + endif + enddo + enddo + + return +end subroutine gf64_standardize_genmat + +subroutine gf64_encode(gg,message,codeword) +! +! Encoder for a (63,12) Reed-Solomon code. +! The generator matrix is supplied in array gg. +! + use gf64math + integer message(12) !Twelve 6-bit data symbols + integer codeword(63) !RS(63,12) codeword + integer gg(12,63) + + codeword=0 + do j=1,12 + do i=1,63 + iprod=gf64_product(message(j),gg(j,i)) + codeword(i)=gf64_sum(codeword(i),iprod) + enddo + enddo + + return +end subroutine gf64_encode + diff --git a/lib/fsk4hf/gf64math.f90 b/lib/fsk4hf/gf64math.f90 new file mode 100644 index 000000000..1ace7c014 --- /dev/null +++ b/lib/fsk4hf/gf64math.f90 @@ -0,0 +1,59 @@ +module gf64math +! Basic math in GF(64), for JT65 and QRA64 + + implicit none + integer :: gf64exp(0:62),gf64log(0:63) + +! gf64exp: GF(64) decimal representation, indexed by logarithm + data gf64exp/ & + 1, 2, 4, 8, 16, 32, 3, 6, 12, 24, & + 48, 35, 5, 10, 20, 40, 19, 38, 15, 30, & + 60, 59, 53, 41, 17, 34, 7, 14, 28, 56, & + 51, 37, 9, 18, 36, 11, 22, 44, 27, 54, & + 47, 29, 58, 55, 45, 25, 50, 39, 13, 26, & + 52, 43, 21, 42, 23, 46, 31, 62, 63, 61, & + 57, 49, 33/ + +! logarithms of GF(64) elements, indexed by decimal representation + data gf64log/ & + -1, 0, 1, 6, 2, 12, 7, 26, 3, 32, & + 13, 35, 8, 48, 27, 18, 4, 24, 33, 16, & + 14, 52, 36, 54, 9, 45, 49, 38, 28, 41, & + 19, 56, 5, 62, 25, 11, 34, 31, 17, 47, & + 15, 23, 53, 51, 37, 44, 55, 40, 10, 61, & + 46, 30, 50, 22, 39, 43, 29, 60, 42, 21, & + 20, 59, 57, 58/ + + contains + +! Product of two GF(64) field elements + function gf64_product(i1,i2) + integer, intent(in) :: i1,i2 + integer :: gf64_product + if(i1.ne.0.and.i2.ne.0) then + gf64_product=gf64exp(mod(gf64log(i1)+gf64log(i2),63)) + else + gf64_product=0 + endif + end function gf64_product + +! Inverse of a GF(64) field element for arguments in [1,63]. Undefined otherwise. + function gf64_inverse(i1) + integer, intent(in) :: i1 + integer :: gf64_inverse + if(i1.gt.1) then + gf64_inverse=gf64exp(63-gf64log(i1)) + else + gf64_inverse=1 + endif + end function gf64_inverse + +! Sum two GF(64) field elements + function gf64_sum(i1,i2) + integer, intent(in) :: i1,i2 + integer :: gf64_sum + gf64_sum=ieor(i1,i2) + end function gf64_sum + +end module gf64math + diff --git a/lib/fsk4hf/jt65_generator_matrix.f90 b/lib/fsk4hf/jt65_generator_matrix.f90 new file mode 100644 index 000000000..baf247ecd --- /dev/null +++ b/lib/fsk4hf/jt65_generator_matrix.f90 @@ -0,0 +1,75 @@ +module jt65_generator_matrix + + implicit none + +! generator matrix for the jt65 (63,12) RS code + integer :: g(12,63) + data g/ & + 58,56,36,31,12,21,48,25,62,11, 3,62, & + 22,19,36,16,27,62, 5, 6,50, 6,10,40, & + 62,59, 9,40,57,11,28,60,30, 6,61,18, & + 5,31,43,14,53,12,60,52,50,62,48,51, & + 24,56,29, 2,21,43,35,57,37,54,40,33, & + 29, 4,42,51, 4,62,51,14,38, 1,22,55, & + 53, 5,16,60,24,13,20,17,34,14,27,58, & + 59,57,15,27, 8,61,24, 5, 7,54, 3,13, & + 14,47,39,18, 4,36, 2,43,63,59,33,57, & + 54, 9,10,13,50,30,34,56,60,54,51,54, & + 15,22,57, 3,42,46, 4,25,42,31,47,33, & + 29,19, 4,23, 5, 1,54,41, 6,14,63,48, & + 21,43,62,12,24,36,61,24,57,31,29,47, & + 30,22, 8,44, 1,32,16, 8,60,60,45,57, & + 54,25,51,34,12,27,38,42,31,53,52,58, & + 59,58,19,56,22,41,14,55,60,11,56,34, & + 16,44, 7,28,42, 2,34, 8,41, 5,46,38, & + 61,34, 7,55,62,41,12, 3,43,60,44,13, & + 14,41,60,26,40,18,22,63,57,23,43,22, & + 40,10,47, 4,55,10,32,25,12,53,45,24, & + 43,51,61,43,34, 6,20,55,17,33,29,37, & + 48,18,55,44,29,30,27,30,21,25,13,63, & + 44,33,42,28,36,58,62,52,11,38,27,24, & + 43,55,22,46,58,21,36,41,60,38,14,19, & + 63,50, 3,14,63,26,18,21,25,23,19,62, & + 22,22,46,55,10,13,10,36,62,33,22,56, & + 12,41,23,27,27, 5,59,41,13,60,42,63, & + 44,29,17,60,19,60,37,20,60,62,62,63, & + 44,61,37,58,52,52,28,10, 1,15,60,43, & + 51,10, 8, 8, 7,27, 5,14,19,40,49,37, & + 48,10,14,25,62,59, 6,15,44,27, 4,19, & + 63,41,62,22, 8,30,60,55,63, 7,46,52, & + 56,44,18, 9,41,62,39,53,26,10,24, 3, & + 13,51, 3,51,29,22,45,12,52, 7,15,25, & + 17,46,32,24,25,57,56,35,58,18,44,57, & + 54,22,11,10,56, 3,63, 2,52,51,26,59, & + 1, 2,56,31,50, 8,38,55,42,43,61,50, & + 34, 4,36,14, 8,57,23,58,24,37,62,18, & + 5, 3,20,35,19,61,14,63,52,56,19,48, & + 21,51,46,28,44,50, 1,32,47,45,43, 3, & + 13,30,28,15, 8,19,33,42,33,50,40,42, & + 9,19,15,46,62,50,18,42,13, 3,15,15, & + 57,46, 6,44,41,56,46,19,47,39,18,10, & + 46, 3, 9, 5,23,45,17,17,21,34,57,20, & + 31,25,14,15,48,31,60,44,29,15,30,53, & + 2,52, 6,38,60,19,22,44,63,35,19,13, & + 14,22,42,27,57,16,44,37,22, 3,52,41, & + 4,27,40,57,62,60, 2,12, 3,41,59,18, & + 5,37,11,47,36,11,11,42, 2,35,31,53, & + 2,46,58,35,28, 7, 2,27,57,60,63,12, & + 52,46,20,56,48,37, 8,40,31,14,40,59, & + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, & + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, & + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, & + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, & + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, & + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, & + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, & + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, & + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, & + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, & + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, & + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/ + + contains + +end module jt65_generator_matrix + diff --git a/lib/fsk4hf/jt65osdtest.f90 b/lib/fsk4hf/jt65osdtest.f90 new file mode 100644 index 000000000..61fa3e464 --- /dev/null +++ b/lib/fsk4hf/jt65osdtest.f90 @@ -0,0 +1,32 @@ +program jt65osdtest +! +! Test k9an's JT65 encoder by comparing codewords with +! those produced by the tried-and-true KA9Q encoder +! + use jt65_generator_matrix + use gf64math + + integer m(12),cwka9q(63),cwk9an(63),cwtest(63) + integer gmrb(12,63) + do i=1,12 + m(i)=i + enddo + call rs_encode(m,cwka9q) + write(*,'(63i3)') cwka9q + call gf64_encode(g,m,cwk9an) + write(*,'(63i3)') cwk9an + + gmrb=g + call gf64_standardize_genmat(gmrb) + do i=1,12 + write(*,'(63i3)') gmrb(i,:) + enddo + + m(1:12)=cwk9an(1:12) + call gf64_encode(gmrb,m,cwtest) + write(*,*) 'Test message:' + write(*,'(12i3)') m + write(*,*) 'Codeword:' + write(*,'(63i3)') cwtest + +end program jt65osdtest