Merged master 8748
This commit is contained in:
@@ -1,283 +0,0 @@
|
||||
<HTML><HEAD>
|
||||
|
||||
<TITLE> Encoding Message Blocks </TITLE>
|
||||
|
||||
</HEAD><BODY>
|
||||
|
||||
|
||||
<H1> Encoding Message Blocks </H1>
|
||||
|
||||
To use a code to send messages, we must define a mapping from a bit
|
||||
vector, <B>s</B>, of length <I>K</I>, representing a source message,
|
||||
to a codeword, <B>x</B>, of length <I>N</I>><I>K</I>. We will
|
||||
consider only linear mappings, which can be written in the form
|
||||
<B>x</B>=<B>G</B><SUP><SMALL>T</SMALL></SUP><B>s</B>, where <B>G</B>
|
||||
is a <I>generator matrix</I>. For a code with parity check matrix
|
||||
<B>H</B>, whose codewords satisfy <B>Hx</B>=<B>0</B>, the generator
|
||||
matrix must satisfy <B>HG</B><SUP><SMALL>T</SMALL></SUP>=<B>0</B>.
|
||||
This software assumes that the number of rows in the parity check
|
||||
matrix, <I>M</I>, is equal to <I>N-K</I>, as would normally be the
|
||||
case.
|
||||
|
||||
<P>This software deals only with <I>systematic</I> encodings, in which
|
||||
the <I>K</I> bits of <B>s</B> are copied unchanged to some subset of
|
||||
the <I>N</i> bits of <B>x</B> (the <I>message bits</I>), and the
|
||||
remaining <I>M=N-K</I> <I>check bits</I> of <B>x</B> are then set so
|
||||
as to make the result a codeword. For a linear code, a systematic
|
||||
encoding scheme always exists, for some choice of which bits of a
|
||||
codeword are message bits. It is conventional to rearrange the order
|
||||
of the bits in a codeword so that the message bits come first. The
|
||||
first <I>K</I> columns of the <I>K</I> by <I>N</I> generator matrix
|
||||
will then be the identity matrix.
|
||||
|
||||
<P>However, this software does <I>not</I> assume that the message bits
|
||||
come first, since different encoding methods prefer different
|
||||
locations for the message bits. Instead, a vector of indexes of where
|
||||
each message bit is located within a codeword is recorded in a file
|
||||
along with a representation of the part of the generator matrix that
|
||||
produces the check bits. More than one such generator matrix file can
|
||||
be created for a single parity check file, in which the locations of
|
||||
the message bits may be different. Decoding of a received message
|
||||
into a codeword (with <A
|
||||
HREF="decoding.html#decode"><TT>decode</TT></A>) does not depend on
|
||||
knowing which are the message bits, though this does need to be known
|
||||
in order to reconstruct the original message (with <A
|
||||
HREF="decoding.html#extract"><TT>extract</TT></A>).
|
||||
|
||||
<P>This software stores representations of generator matrices in files
|
||||
in a format that is not human-readable (except by using the <A
|
||||
HREF="#print-gen"><TT>print-gen</TT></A> program). However, these
|
||||
files <I>are</I> readable on a machine with a different architecture
|
||||
than they were written on.
|
||||
|
||||
|
||||
<A NAME="gen-rep"><H2>Generator matrix representations</H2></A>
|
||||
|
||||
<P>For simplicity of exposition, it will be assumed for the next few
|
||||
paragraphs that the message bits are located at the <I>end</I> of the
|
||||
codeword, so a codeword can be divided into <I>M</I> check bits,
|
||||
<B>c</B>, followed by <I>K</I> message bits, <B>s</B>.
|
||||
|
||||
<P>On the above assumption, the parity check matrix, <B>H</B>, can be divided
|
||||
into an <I>M</I> by <I>M</I> matrix <B>A</B> occupying
|
||||
the first <I>M</I> columns of <B>H</B> and an <I>M</I> by <I>K</I> matrix
|
||||
<B>B</B> occupying the remaining columns of <B>H</B>. The requirement that
|
||||
a codeword, <B>x</B>, satisfy all parity checks (ie, that <B>Hx</B>=<B>0</B>)
|
||||
can then be written as
|
||||
<BLOCKQUOTE>
|
||||
<B>Ac</B> + <B>Bs</B> = <B>0</B>
|
||||
</BLOCKQUOTE>
|
||||
Provided that <B>A</B> is non-singular, it follows that
|
||||
<BLOCKQUOTE>
|
||||
<B>c</B> = <B>A</B><SUP><SMALL>-1</SMALL></SUP><B>Bs</B>
|
||||
</BLOCKQUOTE>
|
||||
<B>A</B> may be singular for some choices of which codeword bits are message
|
||||
bits, but a choice for which <B>A</B> is non-singular always exists if the
|
||||
rows of <B>H</B> are linearly independent. It is possible, however, that the
|
||||
rows of <B>H</B> are not linearly independent (ie, some rows are redundant).
|
||||
This is an exceptional
|
||||
and not particularly interesting case, which is mostly ignored in the
|
||||
descriptions below; see the discussion of <A HREF="dep-H.html">linear
|
||||
dependence in parity check matrices</A> for the details.
|
||||
|
||||
<P>The equation <B>c</B> = <B>A</B><SUP><SMALL>-1</SMALL></SUP><B>Bs</B>
|
||||
defines what the check bits should be, but actual computation of these
|
||||
check bits can be done in several ways, three of which are implemented
|
||||
in this software. Each method involves a different representation of
|
||||
the generator matrix. (Note that none of these methods involves the
|
||||
explicit representation of the matrix <B>G</B> mentioned above.)
|
||||
|
||||
<P>In the <I>dense representation</I>, the <I>M</I> by <I>K</I> matrix
|
||||
<B>A</B><SUP><SMALL>-1</SMALL></SUP><B>B</B> is computed, and stored
|
||||
in a dense format (see the <A HREF="mod2dense.html">dense modulo-2
|
||||
matrix package</A>). A message is encoded by multiplying the
|
||||
source bits, <B>s</B>, by this matrix to obtain the required check bits.
|
||||
|
||||
<P>In the <I>mixed representation</I>, the <I>M</I> by <I>M</I> matrix
|
||||
<B>A</B><SUP><SMALL>-1</SMALL></SUP> is computed and stored in a dense
|
||||
format, and the <I>M</I> by <I>K</I> matrix <B>B</B>, the right
|
||||
portion of the parity check matrix, is also stored, in a sparse format
|
||||
(see the <A HREF="mod2sparse.html">sparse modulo-2 matrix package</A>).
|
||||
To encode a message, the source vector <B>s</B> is first multiplied on
|
||||
the left by <B>B</B>, an operation which can be done very quickly if
|
||||
<B>B</B> is sparse (as it will be for LDPC codes). The result is then
|
||||
multiplied on the left by <B>A</B><SUP><SMALL>-1</SMALL></SUP>. If
|
||||
<I>M</I><<I>K</I>, the total time may be less than when using the
|
||||
dense representation above.
|
||||
|
||||
<P>The <I>sparse representation</I> goes further, and avoids
|
||||
explicitly computing <B>A</B><SUP><SMALL>-1</SMALL></SUP>, which tends
|
||||
to be dense even if <B>H</B> is sparse. Instead, a <I>LU
|
||||
decomposition</I> of <B>A</B> is found, consisting of a lower
|
||||
triangular matrix <B>L</B> and an upper triangular matrix <B>U</B> for
|
||||
which <B>LU</B>=<B>A</B>. The effect of multiplying <B>Bs</B>=<B>z</B> by
|
||||
<B>A</B><SUP><SMALL>-1</SMALL></SUP> can then be obtained by
|
||||
<BLOCKQUOTE>
|
||||
Solving <B>Ly</B>=<B>z</B> for <B>y</B> using forward substitution.<BR>
|
||||
Solving <B>Uc</B>=<B>y</B> for <B>c</B> using backward substitution.
|
||||
</BLOCKQUOTE>
|
||||
Both of these operations will be fast if <B>L</B> and <B>U</B> are
|
||||
sparse. Heuristics are used to try to achieve this, by rearranging the
|
||||
rows and columns of <B>H</B> in the process of selecting <B>A</B> and
|
||||
finding its LU decomposition.
|
||||
|
||||
|
||||
<P><A NAME="make-gen"><HR><B>make-gen</B>: Make a generator matrix from
|
||||
a parity check matrix.
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
make-gen <I>pchk-file gen-file method</I>
|
||||
</PRE>
|
||||
<BLOCKQUOTE>
|
||||
where <TT><I>method</I></TT> is one of the following:
|
||||
<BLOCKQUOTE><PRE>
|
||||
sparse [ first | mincol | minprod ] [ <I>abandon-num abandon-when</I> ]
|
||||
|
||||
dense [ <I>other-gen-file </I> ]
|
||||
|
||||
mixed [ <I>other-gen-file </I> ]
|
||||
</PRE></BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P>Finds a generator matrix for the code whose parity check matrix is
|
||||
in <TT><I>pchk-file</I></TT>, and writes a representation of this
|
||||
generator matrix to <TT><I>gen-file</I></TT>. The remaining arguments
|
||||
specify what representation of the generator matrix is to be used (see
|
||||
the <A HREF="#gen-rep">description above</A>), and the method to be
|
||||
used in finding it. A message regarding the density of 1s in the
|
||||
resulting representation is displayed on standard error. For a sparse
|
||||
representation, a smaller number of 1s will produce faster encoding.
|
||||
|
||||
<P>All representations include a specification for how the columns of
|
||||
the parity check matrix should be re-ordered so that the message bits
|
||||
come last. References to columns of the parity check matrix below
|
||||
refer to their order after this reordering. For the <I>dense</I> and
|
||||
<I>mixed</I> representations, an <TT><I>other-gen-file</I></TT> may be
|
||||
specified, in which case the ordering of columns will be the same as
|
||||
the ordering stored in that file (which must produce a non-singular
|
||||
<B>A</B> matrix; redundant rows of <B>H</B> are not allowed with this
|
||||
option). Otherwise, <TT>make-gen</TT> decides on an appropriate
|
||||
ordering of columns itself. Note that the column rearrangement is
|
||||
recorded as part of the representation of the generator matrix; the
|
||||
parity check matrix as stored in its file is not altered.
|
||||
|
||||
<P>The <I>dense</I> representation consists of a dense representation
|
||||
of the matrix <B>A</B><SUP><SMALL>-1</SMALL></SUP><B>B</B>, where
|
||||
<B>A</B> is the matrix consisting of the first <I>M</I> columns (after
|
||||
reordering) of the parity check matrix, and <B>B</B> is the remaining
|
||||
columns. If <B>H</B> contains redundant rows, there is an additional
|
||||
reordering of columns of <B>A</B> in order create the same effect as
|
||||
if the redundant rows came last.
|
||||
|
||||
<P>The <I>mixed</I> representation consists of a dense representation
|
||||
of the matrix <B>A</B><SUP><SMALL>-1</SMALL></SUP>, where <B>A</B> is
|
||||
the matrix consisting of the first <I>M</I> columns (after reordering)
|
||||
of the parity check matrix. The remaining columns of the parity check
|
||||
matrix, making up the matrix <B>B</B>, are also part of the
|
||||
representation, but are not written to <TT><I>gen-file</I></TT>, since
|
||||
they can be obtained from <TT><I>pchk-file</I></TT>. As for mixed
|
||||
representations, an additional reordering of columns of <B>A</B> may
|
||||
be needed if <B>H</B> has redundant rows.
|
||||
|
||||
<P>A <I>sparse</I> representation consists of sparse representations
|
||||
of the <B>L</B> and <B>U</B> matrices, whose product is <B>A</B>, the
|
||||
first <I>M</I> columns of the parity check matrix (whose columns and
|
||||
rows may both have been reordered). The matrix <B>B</B>, consisting
|
||||
of the remaining columns of the parity check matrix, is also part of
|
||||
the representation, but it is not written to <TT><I>gen-file</I></TT>,
|
||||
since it can be obtained from <TT><I>pchk-file</I></TT>.
|
||||
|
||||
<P>If a sparse representation is chosen, arguments after
|
||||
<TT>sparse</TT> specify what heuristic is used when reordering columns
|
||||
and rows in order to try to make <B>L</B> and <B>U</B> as sparse as
|
||||
possible. The default if no heuristic is specified is
|
||||
<TT>minprod</TT>. If the <TT><I>abandon-num</I></TT> and
|
||||
<TT><I>abandon-when</I></TT> options are given, some information is
|
||||
discarded in order to speed up the process of finding <B>L</B> and
|
||||
<B>U</B>, at a possible cost in terms of how good a result is
|
||||
obtained. For details on these heuristics, see the descriptions of <A
|
||||
HREF="sparse-LU.html">sparse LU decomposition methods</A>.
|
||||
|
||||
<P><B>Example:</B> A dense representation of a generator matrix for the
|
||||
Hamming code created by the example for <A
|
||||
HREF="pchk.html#make-pchk"><TT>make-pchk</TT></A> can be created as follows:
|
||||
<UL><PRE>
|
||||
<LI>make-gen ham7.pchk ham7.gen dense
|
||||
Number of 1s per check in Inv(A) X B is 3.0
|
||||
</PRE></UL>
|
||||
|
||||
|
||||
<P><A NAME="print-gen"><HR><B>print-gen</B>: Print a representation of a
|
||||
generator matrix.
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
print-gen [ -d ] <I>gen-file</I>
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Prints in human-readable form the representation of the generator
|
||||
matrix that is stored in <TT><I>gen-file</I></TT>. The <B>-d</B>
|
||||
option causes the matrices involved to be printed in a dense format,
|
||||
even if they are stored in the file in a sparse format. See the <A
|
||||
HREF="#gen-rep">description above</A> for details of generator matrix
|
||||
representations. Note that the <B>L</B> matrix for a sparse representation
|
||||
will be lower triangular only after the rows are rearranged, and the <B>U</B>
|
||||
matrix will be upper triangular only after the columns are rearranged.
|
||||
The matrix <B>B</B> that is part of the sparse
|
||||
and mixed representations is not printed, since it is not stored
|
||||
in the <TT><I>gen-file</I></TT>, but is rather a subset of columns
|
||||
of the parity check matrix.
|
||||
|
||||
<P><B>Example:</B> The generator matrix for the
|
||||
Hamming code created by the example for <A
|
||||
HREF="#make-gen"><TT>make-gen</TT></A> can be printed as follows:
|
||||
<UL><PRE>
|
||||
<LI>print-gen ham7.gen
|
||||
|
||||
Generator matrix (dense representation):
|
||||
|
||||
Column order:
|
||||
|
||||
0 1 2 3 4 5 6
|
||||
|
||||
Inv(A) X B:
|
||||
|
||||
1 1 1 0
|
||||
1 1 0 1
|
||||
0 1 1 1
|
||||
</PRE></UL>
|
||||
For this example, the columns did not need to be rearranged, and hence the
|
||||
message bits will be in positions 3, 4, 5, and 6 of a codeword.
|
||||
|
||||
<P><A NAME="encode"><HR><B>encode</B>: Encode message blocks as codewords
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
encode [ -f ] <I>pchk-file gen-file source-file encoded-file</I>
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
Encodes message blocks of length <I>K</I>, read from
|
||||
<TT><I>source-file</I></TT>, as codewords of length <I>N</I>, which
|
||||
are written to <TT><I>encoded-file</I></TT>, replacing any previous
|
||||
data in this file. Here, <I>N</I> is the number of columns in the
|
||||
parity check matrix in <TT><I>pchk-file</I></TT>, and
|
||||
<I>K</I>=<I>N-M</I>, where <I>M</I> is the number of rows in the
|
||||
parity check matrix. The generator matrix used, from
|
||||
<TT><I>gen-file</I></TT>, determines which bits of the codeword are
|
||||
set to the message bits, and how the remaining check bits are
|
||||
computed. The generator matrix is created from
|
||||
<TT><I>pchk-file</I></TT> using <A HREF="#make-gen"><TT>make-gen</TT></A>.
|
||||
|
||||
<P>A newline is output at the end of each block written to
|
||||
<TT><I>encoded-file</I></TT>. Newlines in <TT><I>source-file</I></TT>
|
||||
are ignored.
|
||||
|
||||
<P>If the <B>-f</B> option is given, output to <TT><I>encoded-file</I></TT>
|
||||
is flushed after each block. This allows one to use encode as a server,
|
||||
reading blocks to encode from a named pipe, and writing the encoded block
|
||||
to another named pipe.
|
||||
|
||||
<HR>
|
||||
|
||||
<A HREF="index.html">Back to index for LDPC software</A>
|
||||
|
||||
</BODY></HTML>
|
||||
@@ -1,126 +0,0 @@
|
||||
program ft8sim
|
||||
|
||||
! Generate simulated data for a 15-second HF/6m mode using 8-FSK.
|
||||
! Output is saved to a *.wav file.
|
||||
|
||||
use wavhdr
|
||||
include 'ft8_params.f90' !Set various constants
|
||||
type(hdr) h !Header for .wav file
|
||||
character arg*12,fname*17,sorm*1
|
||||
character msg*22,msgsent*22
|
||||
character*6 mygrid6
|
||||
logical bcontest
|
||||
complex c0(0:NMAX-1)
|
||||
complex c(0:NMAX-1)
|
||||
integer itone(NN)
|
||||
integer*1 msgbits(KK)
|
||||
integer*2 iwave(NMAX) !Generated full-length waveform
|
||||
data mygrid6/'EM48 '/
|
||||
|
||||
! Get command-line argument(s)
|
||||
nargs=iargc()
|
||||
if(nargs.ne.8) then
|
||||
print*,'Usage: ft8sim "message" s|m f0 DT fdop del nfiles snr'
|
||||
print*,'Example: ft8sim "K1ABC W9XYZ EN37" m 1500.0 0.0 0.1 1.0 10 -18'
|
||||
print*,'s|m: "s" for single signal at 1500 Hz, "m" for 25 signals'
|
||||
print*,'f0 is ignored when sorm = m'
|
||||
print*,'Make nfiles negative to invoke 72-bit contest mode.'
|
||||
go to 999
|
||||
endif
|
||||
call getarg(1,msg) !Message to be transmitted
|
||||
call getarg(2,sorm) !s for single signal, m for multiple sigs
|
||||
if(sorm.eq."s") then
|
||||
print*,"Generating single signal at 1500 Hz."
|
||||
nsig=1
|
||||
elseif( sorm.eq."m") then
|
||||
print*,"Generating 25 signals per file."
|
||||
nsig=25
|
||||
else
|
||||
print*,"sorm parameter must be s (single) or m (multiple)."
|
||||
goto 999
|
||||
endif
|
||||
call getarg(3,arg)
|
||||
read(arg,*) f0 !Frequency (only used for single-signal)
|
||||
call getarg(4,arg)
|
||||
read(arg,*) xdt !Time offset from nominal (s)
|
||||
call getarg(5,arg)
|
||||
read(arg,*) fspread !Watterson frequency spread (Hz)
|
||||
call getarg(6,arg)
|
||||
read(arg,*) delay !Watterson delay (ms)
|
||||
call getarg(7,arg)
|
||||
read(arg,*) nfiles !Number of files
|
||||
call getarg(8,arg)
|
||||
read(arg,*) snrdb !SNR_2500
|
||||
|
||||
bcontest=nfiles.lt.0
|
||||
nfiles=abs(nfiles)
|
||||
twopi=8.0*atan(1.0)
|
||||
fs=12000.0 !Sample rate (Hz)
|
||||
dt=1.0/fs !Sample interval (s)
|
||||
tt=NSPS*dt !Duration of symbols (s)
|
||||
baud=1.0/tt !Keying rate (baud)
|
||||
bw=8*baud !Occupied bandwidth (Hz)
|
||||
txt=NZ*dt !Transmission length (s)
|
||||
bandwidth_ratio=2500.0/(fs/2.0)
|
||||
sig=sqrt(2*bandwidth_ratio) * 10.0**(0.05*snrdb)
|
||||
if(snrdb.gt.90.0) sig=1.0
|
||||
txt=NN*NSPS/12000.0
|
||||
i3bit=0 ! ### TEMPORARY ??? ###
|
||||
|
||||
! Source-encode, then get itone()
|
||||
call genft8(msg,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
|
||||
write(*,1000) f0,xdt,txt,snrdb,bw,msgsent
|
||||
1000 format('f0:',f9.3,' DT:',f6.2,' TxT:',f6.1,' SNR:',f6.1, &
|
||||
' BW:',f4.1,2x,a22)
|
||||
|
||||
write(*,'(28i1,1x,28i1)') msgbits(1:56)
|
||||
write(*,'(16i1)') msgbits(57:72)
|
||||
write(*,'(3i1)') msgbits(73:75)
|
||||
write(*,'(12i1)') msgbits(76:87)
|
||||
|
||||
! call sgran()
|
||||
do ifile=1,nfiles
|
||||
c=0.
|
||||
do isig=1,nsig
|
||||
c0=0.
|
||||
if(nsig.eq.25) then
|
||||
f0=(isig+2)*100.0
|
||||
endif
|
||||
k=-1 + nint((xdt+0.5+0.01*gran())/dt)
|
||||
! k=-1 + nint((xdt+0.5)/dt)
|
||||
phi=0.0
|
||||
do j=1,NN !Generate complex waveform
|
||||
dphi=twopi*(f0+itone(j)*baud)*dt
|
||||
do i=1,NSPS
|
||||
k=k+1
|
||||
phi=mod(phi+dphi,twopi)
|
||||
if(k.ge.0 .and. k.lt.NMAX) c0(k)=cmplx(cos(phi),sin(phi))
|
||||
enddo
|
||||
enddo
|
||||
if(fspread.ne.0.0 .or. delay.ne.0.0) call watterson(c0,NMAX,fs,delay,fspread)
|
||||
c=c+sig*c0
|
||||
enddo
|
||||
if(snrdb.lt.90) then
|
||||
do i=0,NMAX-1 !Add gaussian noise at specified SNR
|
||||
xnoise=gran()
|
||||
ynoise=gran()
|
||||
c(i)=c(i) + cmplx(xnoise,ynoise)
|
||||
enddo
|
||||
endif
|
||||
|
||||
fac=32767.0
|
||||
rms=100.0
|
||||
if(snrdb.ge.90.0) iwave(1:NMAX)=nint(fac*real(c))
|
||||
if(snrdb.lt.90.0) iwave(1:NMAX)=nint(rms*real(c))
|
||||
|
||||
h=default_header(12000,NMAX)
|
||||
write(fname,1102) ifile
|
||||
1102 format('000000_',i6.6,'.wav')
|
||||
open(10,file=fname,status='unknown',access='stream')
|
||||
write(10) h,iwave !Save to *.wav file
|
||||
close(10)
|
||||
write(*,1110) ifile,xdt,f0,snrdb,fname
|
||||
1110 format(i4,f7.2,f8.2,f7.1,2x,a17)
|
||||
enddo
|
||||
|
||||
999 end program ft8sim
|
||||
@@ -1,163 +0,0 @@
|
||||
|
||||
make-ldpc ex-wrong-model.pchk 1000 1800 1 evenboth 3 no4cycle
|
||||
Eliminated 19 cycles of length four by moving checks within column
|
||||
make-gen ex-wrong-model.pchk ex-wrong-model.gen dense
|
||||
Number of 1s per check in Inv(A) X B is 318.6
|
||||
rand-src ex-wrong-model.src 1 800x1000
|
||||
encode ex-wrong-model.pchk ex-wrong-model.gen ex-wrong-model.src \
|
||||
ex-wrong-model.enc
|
||||
Encoded 1000 blocks, source block size 800, encoded block size 1800
|
||||
|
||||
# FIRST SET OF TESTS, TRANSMITTING THROUGH AWGN CHANNEL WITH SIGMA=0.90
|
||||
|
||||
transmit ex-wrong-model.enc ex-wrong-model.rec 1 awgn 0.90
|
||||
Transmitted 1800000 bits
|
||||
|
||||
# DECODING WITH CORRECT AWGN NOISE MODEL, SIGMA=0.90
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.90 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 910 valid. Average 25.8 iterations, 13% bit changes
|
||||
Block counts: tot 1000, with chk errs 90, with src errs 89, both 89
|
||||
Bit error rate (on message bits only): 6.484e-03
|
||||
|
||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.95
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.95 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 909 valid. Average 25.7 iterations, 13% bit changes
|
||||
Block counts: tot 1000, with chk errs 91, with src errs 91, both 91
|
||||
Bit error rate (on message bits only): 6.540e-03
|
||||
|
||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.85
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.85 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 900 valid. Average 27.7 iterations, 13% bit changes
|
||||
Block counts: tot 1000, with chk errs 100, with src errs 100, both 100
|
||||
Bit error rate (on message bits only): 7.604e-03
|
||||
|
||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.40
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.40 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 755 valid. Average 42.3 iterations, 13% bit changes
|
||||
Block counts: tot 1000, with chk errs 245, with src errs 245, both 245
|
||||
Bit error rate (on message bits only): 1.884e-02
|
||||
|
||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.45
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.45 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 827 valid. Average 34.7 iterations, 13% bit changes
|
||||
Block counts: tot 1000, with chk errs 173, with src errs 172, both 172
|
||||
Bit error rate (on message bits only): 1.306e-02
|
||||
|
||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.50
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.50 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 849 valid. Average 31.7 iterations, 13% bit changes
|
||||
Block counts: tot 1000, with chk errs 151, with src errs 151, both 151
|
||||
Bit error rate (on message bits only): 1.069e-02
|
||||
|
||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.55
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.55 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 855 valid. Average 32.3 iterations, 13% bit changes
|
||||
Block counts: tot 1000, with chk errs 145, with src errs 145, both 145
|
||||
Bit error rate (on message bits only): 1.022e-02
|
||||
|
||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.60
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.60 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 790 valid. Average 40.0 iterations, 13% bit changes
|
||||
Block counts: tot 1000, with chk errs 210, with src errs 210, both 210
|
||||
Bit error rate (on message bits only): 1.452e-02
|
||||
|
||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.65
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.65 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 540 valid. Average 63.3 iterations, 11% bit changes
|
||||
Block counts: tot 1000, with chk errs 460, with src errs 460, both 460
|
||||
Bit error rate (on message bits only): 3.247e-02
|
||||
|
||||
# SECOND SET OF TESTS, TRANSMITTING THROUGH AWLN CHANNEL WITH WIDTH=0.50
|
||||
|
||||
transmit ex-wrong-model.enc ex-wrong-model.rec 1 awln 0.50
|
||||
Transmitted 1800000 bits
|
||||
|
||||
# DECODING WITH CORRECT AWLN NOISE MODEL, WIDTH=0.50
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.50 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 914 valid. Average 25.1 iterations, 12% bit changes
|
||||
Block counts: tot 1000, with chk errs 86, with src errs 86, both 86
|
||||
Bit error rate (on message bits only): 6.130e-03
|
||||
|
||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.55
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.55 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 907 valid. Average 25.6 iterations, 12% bit changes
|
||||
Block counts: tot 1000, with chk errs 93, with src errs 93, both 93
|
||||
Bit error rate (on message bits only): 6.474e-03
|
||||
|
||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.45
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.45 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 893 valid. Average 27.5 iterations, 12% bit changes
|
||||
Block counts: tot 1000, with chk errs 107, with src errs 107, both 107
|
||||
Bit error rate (on message bits only): 7.744e-03
|
||||
|
||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.80
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.80 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 702 valid. Average 44.9 iterations, 12% bit changes
|
||||
Block counts: tot 1000, with chk errs 298, with src errs 298, both 298
|
||||
Bit error rate (on message bits only): 2.245e-02
|
||||
|
||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.85
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.85 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 765 valid. Average 39.4 iterations, 12% bit changes
|
||||
Block counts: tot 1000, with chk errs 235, with src errs 235, both 235
|
||||
Bit error rate (on message bits only): 1.693e-02
|
||||
|
||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.90
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.90 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 808 valid. Average 35.7 iterations, 12% bit changes
|
||||
Block counts: tot 1000, with chk errs 192, with src errs 192, both 192
|
||||
Bit error rate (on message bits only): 1.374e-02
|
||||
|
||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.95
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.95 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 814 valid. Average 34.6 iterations, 12% bit changes
|
||||
Block counts: tot 1000, with chk errs 186, with src errs 186, both 186
|
||||
Bit error rate (on message bits only): 1.291e-02
|
||||
|
||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=1.00
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 1.00 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 808 valid. Average 35.6 iterations, 12% bit changes
|
||||
Block counts: tot 1000, with chk errs 192, with src errs 192, both 192
|
||||
Bit error rate (on message bits only): 1.320e-02
|
||||
|
||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=1.05
|
||||
|
||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 1.05 prprp 100 \
|
||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
||||
Decoded 1000 blocks, 771 valid. Average 40.7 iterations, 11% bit changes
|
||||
Block counts: tot 1000, with chk errs 229, with src errs 228, both 228
|
||||
Bit error rate (on message bits only): 1.524e-02
|
||||
@@ -1,310 +0,0 @@
|
||||
subroutine ft8b(dd0,newdat,nfqso,ndepth,lapon,napwid,lsubtract,iaptype,icand, &
|
||||
sync0,f1,xdt,apsym,nharderrors,dmin,nbadcrc,iap,ipass,iera,message,xsnr)
|
||||
|
||||
use timer_module, only: timer
|
||||
include 'ft8_params.f90'
|
||||
parameter(NRECENT=10,NP2=2812)
|
||||
character message*22,msgsent*22
|
||||
character*12 recent_calls(NRECENT)
|
||||
real a(5)
|
||||
real s1(0:7,ND),s2(0:7,NN)
|
||||
real ps(0:7)
|
||||
real rxdata(3*ND),rxdatap(3*ND)
|
||||
real llr(3*ND),llra(3*ND),llr0(3*ND),llrap(3*ND) !Soft symbols
|
||||
real dd0(15*12000)
|
||||
integer*1 decoded(KK),apmask(3*ND),cw(3*ND)
|
||||
integer*1 msgbits(KK)
|
||||
integer apsym(KK),rr73(11),cq(28)
|
||||
integer itone(NN)
|
||||
integer icos7(0:6),ip(1)
|
||||
complex cd0(3200)
|
||||
complex ctwk(32)
|
||||
complex csymb(32)
|
||||
logical newdat,lsubtract,lapon
|
||||
data icos7/2,5,6,0,4,1,3/
|
||||
data rr73/-1,1,1,1,1,1,1,-1,1,1,-1/
|
||||
data cq/1,1,1,1,1,-1,1,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,1,1,-1,-1,-1,1,1,-1,-1,1/
|
||||
|
||||
max_iterations=30
|
||||
nharderrors=-1
|
||||
fs2=12000.0/NDOWN
|
||||
dt2=1.0/fs2
|
||||
twopi=8.0*atan(1.0)
|
||||
delfbest=0.
|
||||
ibest=0
|
||||
|
||||
call timer('ft8_down',0)
|
||||
call ft8_downsample(dd0,newdat,f1,cd0) !Mix f1 to baseband and downsample
|
||||
call timer('ft8_down',1)
|
||||
|
||||
i0=nint((xdt+0.5)*fs2) !Initial guess for start of signal
|
||||
smax=0.0
|
||||
do idt=i0-8,i0+8 !Search over +/- one quarter symbol
|
||||
call sync8d(cd0,idt,ctwk,0,sync)
|
||||
if(sync.gt.smax) then
|
||||
smax=sync
|
||||
ibest=idt
|
||||
endif
|
||||
enddo
|
||||
xdt2=ibest*dt2 !Improved estimate for DT
|
||||
|
||||
! Now peak up in frequency
|
||||
i0=nint(xdt2*fs2)
|
||||
smax=0.0
|
||||
do ifr=-5,5 !Search over +/- 2.5 Hz
|
||||
delf=ifr*0.5
|
||||
dphi=twopi*delf*dt2
|
||||
phi=0.0
|
||||
do i=1,32
|
||||
ctwk(i)=cmplx(cos(phi),sin(phi))
|
||||
phi=mod(phi+dphi,twopi)
|
||||
enddo
|
||||
call sync8d(cd0,i0,ctwk,1,sync)
|
||||
if( sync .gt. smax ) then
|
||||
smax=sync
|
||||
delfbest=delf
|
||||
endif
|
||||
enddo
|
||||
a=0.0
|
||||
a(1)=-delfbest
|
||||
call twkfreq1(cd0,NP2,fs2,a,cd0)
|
||||
xdt=xdt2
|
||||
f1=f1+delfbest !Improved estimate of DF
|
||||
|
||||
call sync8d(cd0,i0,ctwk,2,sync)
|
||||
|
||||
j=0
|
||||
do k=1,NN
|
||||
i1=ibest+(k-1)*32
|
||||
csymb=cmplx(0.0,0.0)
|
||||
if( i1.ge.1 .and. i1+31 .le. NP2 ) csymb=cd0(i1:i1+31)
|
||||
call four2a(csymb,32,1,-1,1)
|
||||
s2(0:7,k)=abs(csymb(1:8))
|
||||
enddo
|
||||
|
||||
! sync quality check
|
||||
is1=0
|
||||
is2=0
|
||||
is3=0
|
||||
do k=1,7
|
||||
ip=maxloc(s2(:,k))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is1=is1+1
|
||||
ip=maxloc(s2(:,k+36))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is2=is2+1
|
||||
ip=maxloc(s2(:,k+72))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is3=is3+1
|
||||
enddo
|
||||
! hard sync sum - max is 21
|
||||
nsync=is1+is2+is3
|
||||
if(nsync .le. 6) then ! bail out
|
||||
nbadcrc=1
|
||||
return
|
||||
endif
|
||||
|
||||
j=0
|
||||
do k=1,NN
|
||||
if(k.le.7) cycle
|
||||
if(k.ge.37 .and. k.le.43) cycle
|
||||
if(k.gt.72) cycle
|
||||
j=j+1
|
||||
s1(0:7,j)=s2(0:7,k)
|
||||
enddo
|
||||
|
||||
do j=1,ND
|
||||
ps=s1(0:7,j)
|
||||
where (ps.gt.0.0) ps=log(ps)
|
||||
r1=max(ps(1),ps(3),ps(5),ps(7))-max(ps(0),ps(2),ps(4),ps(6))
|
||||
r2=max(ps(2),ps(3),ps(6),ps(7))-max(ps(0),ps(1),ps(4),ps(5))
|
||||
r4=max(ps(4),ps(5),ps(6),ps(7))-max(ps(0),ps(1),ps(2),ps(3))
|
||||
i4=3*j-2
|
||||
i2=3*j-1
|
||||
i1=3*j
|
||||
rxdata(i4)=r4
|
||||
rxdata(i2)=r2
|
||||
rxdata(i1)=r1
|
||||
rxdatap(i4)=r4
|
||||
rxdatap(i2)=r2
|
||||
rxdatap(i1)=r1
|
||||
! When bits 88:115 are set as ap bits, bit 115 lives in symbol 39 along
|
||||
! with no-ap bits 116 and 117. Take care of metrics for bits 116 and 117.
|
||||
! if(j.eq.39) then ! take care of bits that live in symbol 39
|
||||
! if(apsym(28).lt.0) then
|
||||
! rxdatap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
|
||||
! rxdatap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
|
||||
! else
|
||||
! rxdatap(i2)=max(ps(6),ps(7))-max(ps(4),ps(5))
|
||||
! rxdatap(i1)=max(ps(5),ps(7))-max(ps(4),ps(6))
|
||||
! endif
|
||||
! endif
|
||||
! When bits 116:143 are set as ap bits, bit 115 lives in symbol 39 along
|
||||
! with ap bits 116 and 117. Take care of metric for bit 115.
|
||||
if(j.eq.39) then ! take care of bit 115
|
||||
iii=2*(apsym(29)+1)/2 + (apsym(30)+1)/2 ! known values of bits 116 & 117
|
||||
if(iii.eq.0) rxdatap(i4)=ps(4)-ps(0)
|
||||
if(iii.eq.1) rxdatap(i4)=ps(5)-ps(1)
|
||||
if(iii.eq.2) rxdatap(i4)=ps(6)-ps(2)
|
||||
if(iii.eq.3) rxdatap(i4)=ps(7)-ps(3)
|
||||
endif
|
||||
! bit 144 lives in symbol 48 and will be 1 if it is set as an ap bit.
|
||||
! take care of metrics for bits 142 and 143
|
||||
if(j.eq.48) then ! bit 144 is always 1
|
||||
rxdatap(i4)=max(ps(5),ps(7))-max(ps(1),ps(3))
|
||||
rxdatap(i2)=max(ps(3),ps(7))-max(ps(1),ps(5))
|
||||
endif
|
||||
! bit 154 lives in symbol 52 and will be 0 if it is set as an ap bit
|
||||
! take care of metrics for bits 155 and 156
|
||||
if(j.eq.52) then ! bit 154 will be 0 if it is set as an ap bit.
|
||||
rxdatap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
|
||||
rxdatap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
|
||||
endif
|
||||
enddo
|
||||
|
||||
rxav=sum(rxdata)/(3.0*ND)
|
||||
rx2av=sum(rxdata*rxdata)/(3.0*ND)
|
||||
var=rx2av-rxav*rxav
|
||||
if( var .gt. 0.0 ) then
|
||||
rxsig=sqrt(var)
|
||||
else
|
||||
rxsig=sqrt(rx2av)
|
||||
endif
|
||||
rxdata=rxdata/rxsig
|
||||
! Let's just assume that rxsig is OK for rxdatap too...
|
||||
rxdatap=rxdatap/rxsig
|
||||
|
||||
ss=0.84
|
||||
llr0=2.0*rxdata/(ss*ss)
|
||||
llra=2.0*rxdatap/(ss*ss) ! llr's for use with ap
|
||||
apmag=4.0
|
||||
! If DxCall exists, only do "MyCall DxCall ???" for candidates within nfqso +/- napwid
|
||||
nap=0
|
||||
if(lapon.and.(iaptype.eq.1 .or. (iaptype.eq.2.and.abs(nfqso-f1).le.napwid))) nap=2
|
||||
if(lapon.and.iaptype.eq.2.and.abs(nfqso-f1).gt.napwid) nap=1
|
||||
|
||||
do iap=0,nap
|
||||
nera=1
|
||||
if(iap.eq.0) nera=3
|
||||
do iera=1,nera
|
||||
llr=llr0
|
||||
nblank=0
|
||||
if(nera.eq.3 .and. iera.eq.1) nblank=0
|
||||
if(nera.eq.3 .and. iera.eq.2) nblank=24
|
||||
if(nera.eq.3 .and. iera.eq.3) nblank=48
|
||||
if(nblank.gt.0) llr(1:nblank)=0.
|
||||
if(iap.eq.0) then
|
||||
apmask=0
|
||||
! apmask(160:162)=1
|
||||
llrap=llr
|
||||
! llrap(160:162)=apmag*apsym(73:75)/ss
|
||||
endif
|
||||
if(iaptype.eq.1) then
|
||||
if(iap.eq.1) then ! look for plain CQ
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! plain CQ
|
||||
apmask(144)=1 ! not free text
|
||||
! apmask(160:162)=1 ! 3 extra bits
|
||||
llrap=llr
|
||||
llrap(88:115)=apmag*cq/ss
|
||||
llrap(116:117)=llra(116:117)
|
||||
llrap(142:143)=llra(142:143)
|
||||
llrap(144)=-apmag/ss
|
||||
! llrap(160:162)=apmag*apsym(73:75)/ss
|
||||
endif
|
||||
if(iap.eq.2) then ! look for mycall
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(144)=1 ! not free text
|
||||
! apmask(160:162)=1 ! 3 extra bits
|
||||
llrap=llr
|
||||
llrap(88:115)=apmag*apsym(1:28)/ss
|
||||
llrap(116:117)=llra(116:117)
|
||||
llrap(142:143)=llra(142:143)
|
||||
llrap(144)=-apmag/ss
|
||||
! llrap(160:162)=apmag*apsym(73:75)/ss
|
||||
endif
|
||||
endif
|
||||
if(iaptype.eq.2) then
|
||||
if(iap.eq.1) then ! look for dxcall
|
||||
apmask=0
|
||||
! apmask(88:115)=1 ! mycall
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144)=1 ! not free text
|
||||
! apmask(160:162)=1 ! 3 extra bits
|
||||
llrap=llr
|
||||
! llrap(88:143)=apmag*apsym(1:56)/ss
|
||||
llrap(115)=llra(115)
|
||||
llrap(116:143)=apmag*apsym(29:56)/ss
|
||||
llrap(144)=-apmag/ss
|
||||
! llrap(160:162)=apmag*apsym(73:75)/ss
|
||||
endif
|
||||
if(iap.eq.2) then ! look mycall, dxcall
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144)=1 ! not free text
|
||||
! apmask(144:154)=1 ! RRR or 73
|
||||
! apmask(160:162)=1 ! 3 extra bits
|
||||
llrap=llr
|
||||
llrap(88:143)=apmag*apsym(1:56)/ss
|
||||
llrap(144)=-apmag/ss
|
||||
! llrap(144:154)=apmag*rr73/ss
|
||||
! llrap(155:156)=llra(155:156)
|
||||
! llrap(160:162)=apmag*apsym(73:75)/ss
|
||||
endif
|
||||
endif
|
||||
|
||||
cw=0
|
||||
call timer('bpd174 ',0)
|
||||
call bpdecode174(llrap,apmask,max_iterations,decoded,cw,nharderrors, &
|
||||
niterations)
|
||||
call timer('bpd174 ',1)
|
||||
dmin=0.0
|
||||
if(ndepth.eq.3 .and. nharderrors.lt.0) then
|
||||
norder=1
|
||||
if(abs(nfqso-f1).le.napwid) then
|
||||
if(iap.eq.0) then
|
||||
norder=2
|
||||
else
|
||||
norder=3
|
||||
endif
|
||||
endif
|
||||
call timer('osd174 ',0)
|
||||
call osd174(llrap,apmask,norder,decoded,cw,nharderrors,dmin)
|
||||
call timer('osd174 ',1)
|
||||
endif
|
||||
nbadcrc=1
|
||||
message=' '
|
||||
xsnr=-99.0
|
||||
if(count(cw.eq.0).eq.174) cycle !Reject the all-zero codeword
|
||||
if(any(decoded(75:75).ne.0)) cycle !Reject if any of the 3 extra bits are nonzero
|
||||
if(nharderrors.ge.0 .and. nharderrors+dmin.lt.60.0 .and. &
|
||||
.not.(sync.lt.2.0 .and. nharderrors.gt.35) .and. &
|
||||
.not.(iap.gt.0 .and. nharderrors.gt.39) .and. &
|
||||
.not.(iera.ge.2 .and. nharderrors.gt.30) &
|
||||
) then
|
||||
call chkcrc12a(decoded,nbadcrc)
|
||||
else
|
||||
nharderrors=-1
|
||||
cycle
|
||||
endif
|
||||
if(nbadcrc.eq.0) then
|
||||
call extractmessage174(decoded,message,ncrcflag,recent_calls,nrecent)
|
||||
call genft8(message,msgsent,msgbits,itone)
|
||||
if(lsubtract) call subtractft8(dd0,itone,f1,xdt2)
|
||||
xsig=0.0
|
||||
xnoi=0.0
|
||||
do i=1,79
|
||||
xsig=xsig+s2(itone(i),i)**2
|
||||
ios=mod(itone(i)+4,7)
|
||||
xnoi=xnoi+s2(ios,i)**2
|
||||
enddo
|
||||
xsnr=0.001
|
||||
if(xnoi.gt.0 .and. xnoi.lt.xsig) xsnr=xsig/xnoi-1.0
|
||||
xsnr=10.0*log10(xsnr)-27.0
|
||||
if(xsnr .lt. -24.0) xsnr=-24.0
|
||||
return
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine ft8b
|
||||
Reference in New Issue
Block a user