From 6fe9e8f860285b02682f52854c0cca98a9681d4e Mon Sep 17 00:00:00 2001
From: Steve Franke <s.j.franke@icloud.com>
Date: Sat, 9 Jun 2018 13:05:11 -0500
Subject: [PATCH] Remove the need to re-order the parity-check matrix columns
 for compatibility with the generator matrix. Redefine the codeword to have
 the form [91 message bits|83 parity bits].

---
 lib/ft8/bpdecode174_91.f90                 |   8 +-
 lib/ft8/encode174_91.f90                   |   9 +-
 lib/ft8/genft8_174_91.f90                  |   4 +-
 lib/ft8/ldpc_174_91_c_reordered_parity.f90 | 270 +++++++++++++++++++++
 lib/ft8/ldpcsim174_91.f90                  |  11 +-
 lib/ft8/osd174_91.f90                      |  16 +-
 6 files changed, 287 insertions(+), 31 deletions(-)
 create mode 100644 lib/ft8/ldpc_174_91_c_reordered_parity.f90

diff --git a/lib/ft8/bpdecode174_91.f90 b/lib/ft8/bpdecode174_91.f90
index 6280dcaec..31effb5dd 100644
--- a/lib/ft8/bpdecode174_91.f90
+++ b/lib/ft8/bpdecode174_91.f90
@@ -4,7 +4,6 @@ subroutine bpdecode174_91(llr,apmask,maxiterations,decoded,cw,nharderror,iter)
 !
 integer, parameter:: N=174, K=91, M=N-K
 integer*1 codeword(N),cw(N),apmask(N)
-integer  colorder(N)
 integer*1 decoded(K)
 integer Nm(7,M)   
 integer Mn(3,N)  ! 3 checks per bit
@@ -17,8 +16,7 @@ real llr(N)
 real Tmn
 integer nrw(M),ncw
 
-include "ldpc_174_91_c_colorder.f90"
-include "ldpc_174_91_c_parity.f90"
+include "ldpc_174_91_c_reordered_parity.f90"
 
 decoded=0
 toc=0
@@ -55,8 +53,8 @@ do iter=0,maxiterations
   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(colorder+1)
-    decoded=codeword(M+1:N)
+    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
diff --git a/lib/ft8/encode174_91.f90 b/lib/ft8/encode174_91.f90
index 355a3ad90..6b09f837d 100644
--- a/lib/ft8/encode174_91.f90
+++ b/lib/ft8/encode174_91.f90
@@ -8,12 +8,9 @@ integer, parameter:: N=174, K=91, M=N-K
 
 integer*1 codeword(N)
 integer*1 gen(M,K)
-integer*1 itmp(N)
 integer*1 message(K)
 integer*1 pchecks(M)
-integer colorder(N)
 include "ldpc_174_91_c_generator.f90"
-include "ldpc_174_91_c_colorder.f90"
 logical first
 data first/.true./
 save first,gen
@@ -41,9 +38,9 @@ do i=1,M
   enddo
   pchecks(i)=mod(nsum,2)
 enddo
-itmp(1:M)=pchecks
-itmp(M+1:N)=message(1:K)
-codeword(colorder+1)=itmp(1:N)
+
+codeword(1:K)=message
+codeword(K+1:N)=pchecks
 
 return
 end subroutine encode174_91
diff --git a/lib/ft8/genft8_174_91.f90 b/lib/ft8/genft8_174_91.f90
index 6561a36b6..0a4c492da 100644
--- a/lib/ft8/genft8_174_91.f90
+++ b/lib/ft8/genft8_174_91.f90
@@ -15,7 +15,6 @@ subroutine genft8_174_91(msg,mygrid,bcontest,i5bit,msgsent,msgbits,itone)
   integer itone(79)
   integer icos7(0:6)
   integer graymap(0:7)
-#  data icos7/2,5,6,0,4,1,3/                   !Costas 7x7 tone pattern
   data icos7/3,1,4,0,6,5,2/                   !Costas 7x7 tone pattern
   data graymap/0,1,3,2,7,6,4,5/
 
@@ -49,8 +48,7 @@ subroutine genft8_174_91(msg,mygrid,bcontest,i5bit,msgsent,msgbits,itone)
      k=k+1
      if(j.eq.30) k=k+7
      indx=codeword(i)*4 + codeword(i+1)*2 + codeword(i+2)
-!     itone(k)=graymap(indx)
-     itone(k)=indx
+     itone(k)=graymap(indx)
   enddo
 
   return
diff --git a/lib/ft8/ldpc_174_91_c_reordered_parity.f90 b/lib/ft8/ldpc_174_91_c_reordered_parity.f90
new file mode 100644
index 000000000..2309ad8e8
--- /dev/null
+++ b/lib/ft8/ldpc_174_91_c_reordered_parity.f90
@@ -0,0 +1,270 @@
+data Mn/   &
+  16,  45,  73, &
+  25,  51,  62, &
+  33,  58,  78, &
+   1,  44,  45, &
+   2,   7,  61, &
+   3,   6,  54, &
+   4,  35,  48, &
+   5,  13,  21, &
+   8,  56,  79, &
+   9,  64,  69, &
+  10,  19,  66, &
+  11,  36,  60, &
+  12,  37,  58, &
+  14,  32,  43, &
+  15,  63,  80, &
+  17,  28,  77, &
+  18,  74,  83, &
+  22,  53,  81, &
+  23,  30,  34, &
+  24,  31,  40, &
+  26,  41,  76, &
+  27,  57,  70, &
+  29,  49,  65, &
+   3,  38,  78, &
+   5,  39,  82, &
+  46,  50,  73, &
+  51,  52,  74, &
+  55,  71,  72, &
+  44,  67,  72, &
+  43,  68,  78, &
+   1,  32,  59, &
+   2,   6,  71, &
+   4,  16,  54, &
+   7,  65,  67, &
+   8,  30,  42, &
+   9,  22,  31, &
+  10,  18,  76, &
+  11,  23,  82, &
+  12,  28,  61, &
+  13,  52,  79, &
+  14,  50,  51, &
+  15,  81,  83, &
+  17,  29,  60, &
+  19,  33,  64, &
+  20,  26,  73, &
+  21,  34,  40, &
+  24,  27,  77, &
+  25,  55,  58, &
+  35,  53,  66, &
+  36,  48,  68, &
+  37,  46,  75, &
+  38,  45,  47, &
+  39,  57,  69, &
+  41,  56,  62, &
+  20,  49,  53, &
+  46,  52,  63, &
+  45,  70,  75, &
+  27,  35,  80, &
+   1,  15,  30, &
+   2,  68,  80, &
+   3,  36,  51, &
+   4,  28,  51, &
+   5,  31,  56, &
+   6,  20,  37, &
+   7,  40,  82, &
+   8,  60,  69, &
+   9,  10,  49, &
+  11,  44,  57, &
+  12,  39,  59, &
+  13,  24,  55, &
+  14,  21,  65, &
+  16,  71,  78, &
+  17,  30,  76, &
+  18,  25,  80, &
+  19,  61,  83, &
+  22,  38,  77, &
+  23,  41,  50, &
+   7,  26,  58, &
+  29,  32,  81, &
+  33,  40,  73, &
+  18,  34,  48, &
+  13,  42,  64, &
+   5,  26,  43, &
+  47,  69,  72, &
+  54,  55,  70, &
+  45,  62,  68, &
+  10,  63,  67, &
+  14,  66,  72, &
+  22,  60,  74, &
+  35,  39,  79, &
+   1,  46,  64, &
+   1,  24,  66, &
+   2,   5,  70, &
+   3,  31,  65, &
+   4,  49,  58, &
+   1,   4,   5, &
+   6,  60,  67, &
+   7,  32,  75, &
+   8,  48,  82, &
+   9,  35,  41, &
+  10,  39,  62, &
+  11,  14,  61, &
+  12,  71,  74, &
+  13,  23,  78, &
+  11,  35,  55, &
+  15,  16,  79, &
+   7,   9,  16, &
+  17,  54,  63, &
+  18,  50,  57, &
+  19,  30,  47, &
+  20,  64,  80, &
+  21,  28,  69, &
+  22,  25,  43, &
+  13,  22,  37, &
+   2,  47,  51, &
+  23,  54,  74, &
+  26,  34,  72, &
+  27,  36,  37, &
+  21,  36,  63, &
+  29,  40,  44, &
+  19,  26,  57, &
+   3,  46,  82, &
+  14,  15,  58, &
+  33,  52,  53, &
+  30,  43,  52, &
+   6,   9,  52, &
+  27,  33,  65, &
+  25,  69,  73, &
+  38,  55,  83, &
+  20,  39,  77, &
+  18,  29,  56, &
+  32,  48,  71, &
+  42,  51,  59, &
+  28,  44,  79, &
+  34,  60,  62, &
+  31,  45,  61, &
+  46,  68,  77, &
+   6,  24,  76, &
+   8,  10,  78, &
+  40,  41,  70, &
+  17,  50,  53, &
+  42,  66,  68, &
+   4,  22,  72, &
+  36,  64,  81, &
+  13,  29,  47, &
+   2,   8,  81, &
+  56,  67,  73, &
+   5,  38,  50, &
+  12,  38,  64, &
+  59,  72,  80, &
+   3,  26,  79, &
+  45,  76,  81, &
+   1,  65,  74, &
+   7,  18,  77, &
+  11,  56,  59, &
+  14,  39,  54, &
+  16,  37,  66, &
+  10,  28,  55, &
+  15,  60,  70, &
+  17,  25,  82, &
+  20,  30,  31, &
+  12,  67,  68, &
+  23,  75,  80, &
+  27,  32,  62, &
+  24,  69,  75, &
+  19,  21,  71, &
+  34,  53,  61, &
+  35,  46,  47, &
+  33,  59,  76, &
+  40,  43,  83, &
+  41,  42,  63, &
+  49,  75,  83, &
+  20,  44,  48, &
+  42,  49,  57/
+
+data Nm/   &
+   4,  31,  59,  91,  92,  96, 153, &
+   5,  32,  60,  93, 115, 146,   0, &
+   6,  24,  61,  94, 122, 151,   0, &
+   7,  33,  62,  95,  96, 143,   0, &
+   8,  25,  63,  83,  93,  96, 148, &
+   6,  32,  64,  97, 126, 138,   0, &
+   5,  34,  65,  78,  98, 107, 154, &
+   9,  35,  66,  99, 139, 146,   0, &
+  10,  36,  67, 100, 107, 126,   0, &
+  11,  37,  67,  87, 101, 139, 158, &
+  12,  38,  68, 102, 105, 155,   0, &
+  13,  39,  69, 103, 149, 162,   0, &
+   8,  40,  70,  82, 104, 114, 145, &
+  14,  41,  71,  88, 102, 123, 156, &
+  15,  42,  59, 106, 123, 159,   0, &
+   1,  33,  72, 106, 107, 157,   0, &
+  16,  43,  73, 108, 141, 160,   0, &
+  17,  37,  74,  81, 109, 131, 154, &
+  11,  44,  75, 110, 121, 166,   0, &
+  45,  55,  64, 111, 130, 161, 173, &
+   8,  46,  71, 112, 119, 166,   0, &
+  18,  36,  76,  89, 113, 114, 143, &
+  19,  38,  77, 104, 116, 163,   0, &
+  20,  47,  70,  92, 138, 165,   0, &
+   2,  48,  74, 113, 128, 160,   0, &
+  21,  45,  78,  83, 117, 121, 151, &
+  22,  47,  58, 118, 127, 164,   0, &
+  16,  39,  62, 112, 134, 158,   0, &
+  23,  43,  79, 120, 131, 145,   0, &
+  19,  35,  59,  73, 110, 125, 161, &
+  20,  36,  63,  94, 136, 161,   0, &
+  14,  31,  79,  98, 132, 164,   0, &
+   3,  44,  80, 124, 127, 169,   0, &
+  19,  46,  81, 117, 135, 167,   0, &
+   7,  49,  58,  90, 100, 105, 168, &
+  12,  50,  61, 118, 119, 144,   0, &
+  13,  51,  64, 114, 118, 157,   0, &
+  24,  52,  76, 129, 148, 149,   0, &
+  25,  53,  69,  90, 101, 130, 156, &
+  20,  46,  65,  80, 120, 140, 170, &
+  21,  54,  77, 100, 140, 171,   0, &
+  35,  82, 133, 142, 171, 174,   0, &
+  14,  30,  83, 113, 125, 170,   0, &
+   4,  29,  68, 120, 134, 173,   0, &
+   1,   4,  52,  57,  86, 136, 152, &
+  26,  51,  56,  91, 122, 137, 168, &
+  52,  84, 110, 115, 145, 168,   0, &
+   7,  50,  81,  99, 132, 173,   0, &
+  23,  55,  67,  95, 172, 174,   0, &
+  26,  41,  77, 109, 141, 148,   0, &
+   2,  27,  41,  61,  62, 115, 133, &
+  27,  40,  56, 124, 125, 126,   0, &
+  18,  49,  55, 124, 141, 167,   0, &
+   6,  33,  85, 108, 116, 156,   0, &
+  28,  48,  70,  85, 105, 129, 158, &
+   9,  54,  63, 131, 147, 155,   0, &
+  22,  53,  68, 109, 121, 174,   0, &
+   3,  13,  48,  78,  95, 123,   0, &
+  31,  69, 133, 150, 155, 169,   0, &
+  12,  43,  66,  89,  97, 135, 159, &
+   5,  39,  75, 102, 136, 167,   0, &
+   2,  54,  86, 101, 135, 164,   0, &
+  15,  56,  87, 108, 119, 171,   0, &
+  10,  44,  82,  91, 111, 144, 149, &
+  23,  34,  71,  94, 127, 153,   0, &
+  11,  49,  88,  92, 142, 157,   0, &
+  29,  34,  87,  97, 147, 162,   0, &
+  30,  50,  60,  86, 137, 142, 162, &
+  10,  53,  66,  84, 112, 128, 165, &
+  22,  57,  85,  93, 140, 159,   0, &
+  28,  32,  72, 103, 132, 166,   0, &
+  28,  29,  84,  88, 117, 143, 150, &
+   1,  26,  45,  80, 128, 147,   0, &
+  17,  27,  89, 103, 116, 153,   0, &
+  51,  57,  98, 163, 165, 172,   0, &
+  21,  37,  73, 138, 152, 169,   0, &
+  16,  47,  76, 130, 137, 154,   0, &
+   3,  24,  30,  72, 104, 139,   0, &
+   9,  40,  90, 106, 134, 151,   0, &
+  15,  58,  60,  74, 111, 150, 163, &
+  18,  42,  79, 144, 146, 152,   0, &
+  25,  38,  65,  99, 122, 160,   0, &
+  17,  42,  75, 129, 170, 172,   0/
+
+data nrw/                           &
+7,6,6,6,7,6,7,6,6,7,6,6,7,7,6,6,    &
+6,7,6,7,6,7,6,6,6,7,6,6,6,7,6,6,    &
+6,6,7,6,6,6,7,7,6,6,6,6,7,7,6,6,    &
+6,6,7,6,6,6,7,6,6,6,6,7,6,6,6,7,    &
+6,6,6,7,7,6,6,7,6,6,6,6,6,6,6,7,    &
+6,6,6/
+
+ncw=3
diff --git a/lib/ft8/ldpcsim174_91.f90 b/lib/ft8/ldpcsim174_91.f90
index bdb16ac42..5b58dd177 100644
--- a/lib/ft8/ldpcsim174_91.f90
+++ b/lib/ft8/ldpcsim174_91.f90
@@ -13,14 +13,11 @@ integer*1 msgbits(K)
 integer*1 apmask(N), cw(N)
 integer*2 checksum
 integer*4 i4Msg6BitWords(13)
-integer colorder(N)
 integer nerrtot(N),nerrdec(N),nmpcbad(K)
 logical checksumok
 real*8, allocatable ::  rxdata(:)
 real, allocatable :: llr(:)
 
-include "ldpc_174_91_c_colorder.f90"
-
 nerrtot=0
 nerrdec=0
 nmpcbad=0  ! Used to collect the number of errors in the message+crc part of the codeword
@@ -51,8 +48,8 @@ write(*,*) "niter= ",max_iterations," s= ",s
 allocate ( codeword(N), decoded(K), message(K) )
 allocate ( rxdata(N), llr(N) )
 
-  msg="K1JT K9AN EN50"
-!  msg="G4WJS K9AN EN50"
+!  msg="K1JT K9AN EN50"
+  msg="G4WJS K9AN EN50"
   call packmsg(msg,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes
   call unpackmsg(i4Msg6BitWords,msgsent,.false.,grid) !Unpack to get msgsent
   write(*,*) "message sent ",msgsent
@@ -148,9 +145,9 @@ do idb = 20,-10,-1
 
     llr=2.0*rxdata/(ss*ss)
     nap=0 ! number of AP bits
-    llr(colorder(174-91+1:174-91+nap)+1)=5*(2.0*msgbits(1:nap)-1.0)
+    llr(1:nap)=5*(2.0*msgbits(1:nap)-1.0)
     apmask=0
-    apmask(colorder(174-91+1:174-91+nap)+1)=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)
diff --git a/lib/ft8/osd174_91.f90 b/lib/ft8/osd174_91.f90
index 34419f98f..7a9cb1076 100644
--- a/lib/ft8/osd174_91.f90
+++ b/lib/ft8/osd174_91.f90
@@ -8,7 +8,6 @@ integer*1 gen(K,N)
 integer*1 genmrb(K,N),g2(N,K)
 integer*1 temp(K),m0(K),me(K),mi(K),misub(K),e2sub(N-K),e2(N-K),ui(N-K)
 integer*1 r2pat(N-K)
-integer colorder(N)
 integer indices(N),nxor(N)
 integer*1 cw(N),ce(N),c0(N),hdec(N)
 integer*1 decoded(K)
@@ -16,7 +15,6 @@ integer indx(N)
 real llr(N),rx(N),absrx(N)
 
 include "ldpc_174_91_c_generator.f90"
-include "ldpc_174_91_c_colorder.f90"
 
 logical first,reset
 data first/.true./
@@ -31,19 +29,18 @@ if( first ) then ! fill the generator matrix
       if(j.eq.23) ibmax=3
       do jj=1, ibmax 
         irow=(j-1)*4+jj
-        if( btest(istr,4-jj) ) gen(irow,i)=1 
+        if( btest(istr,4-jj) ) gen(irow,K+i)=1 
       enddo
     enddo
   enddo
   do irow=1,K
-    gen(irow,M+irow)=1
+    gen(irow,irow)=1
   enddo
 first=.false.
 endif
 
-! Re-order received vector to place systematic msg bits at the end.
-rx=llr(colorder+1) 
-apmaskr=apmask(colorder+1)
+rx=llr
+apmaskr=apmask
 
 ! Hard decisions on the received word.
 hdec=0            
@@ -246,11 +243,10 @@ if(npre2.eq.1) then
 endif
 
 998 continue
-! Re-order the codeword to place message bits at the end.
+! Re-order the codeword to [message bits][parity bits] format. 
 cw(indices)=cw
 hdec(indices)=hdec
-decoded=cw(M+1:N) 
-cw(colorder+1)=cw ! put the codeword back into received-word order
+decoded=cw(1:K) 
 return
 end subroutine osd174_91