SVN r8748

This commit is contained in:
Jordan Sherer
2018-06-14 21:27:34 -04:00
parent 419c039d08
commit 4f1fe4fc94
581 changed files with 69338 additions and 39836 deletions
@@ -1,125 +0,0 @@
<HTML><HEAD>
<TITLE> Notes on Modifying the LDPC Programs </TITLE>
</HEAD><BODY>
<H1> Notes on Modifying the LDPC Programs </H1>
<P>Here are a few notes on how to modify the programs to add new types of
channel, new decoding procedures, etc. You should also look at the <A
HREF="modules.html">module documentation</A>.
<H2> Adding a new type of channel </H2>
<P>Channels are involved in two programs:
<A HREF="channel.html#transmit"><B>transmit</B></A> and
<A HREF="decoding.html#decode"><B>decode</B></A>.
Adding another type of memoryless channel should be straightforward.
Adding a channel with memory may involve more work. Here are the
steps needed if no major reorganizations are required:
<OL>
<LI> Decide on a syntax for specifying the new channel type and its
parameters, and on an internal name for the channel type. Add
the internal name as a possibility in the enumerated <TT>channel_type</TT>
declared in <A HREF="channel.h"><TT>channel.h</TT></A>. You
may also need to declare new global variables to store parameters of
the channel in <A HREF="channel.h"><TT>channel.h</TT></A> and
<A HREF="channel.c"><TT>channel.c</TT></A>.
<LI> Modify the <TT>channel_parse</TT> and
<TT>channel_usage</TT> procedures in
<A HREF="channel.c"><TT>channel.c</TT></A> to
parse the specification of the new channel and display an appropriate
usage message.
<LI> Decide on how the new channel's output is represented in a file
(eg, for an erasure channel, what the symbol for an erasure is), and
update <A HREF="transmit.c"><TT>transmit.c</TT></A> to write the
new channel's output for each transmitted bit, after randomly generating
any noise (see
the <A HREF="rand.html">documentation on random number generation</A>).
<LI> Modify <A HREF="decode.c"><TT>decode.c</TT></A> in three places to
accommodate the new channel. The three sections of code to modify
allocate space for data from the channel, read data from the channel,
and set likelihood ratios based on the data read. The setting of
likelihood ratios is based on the assumption that the channel is
memoryless (ie, data received for different bits is independent).
Adding a channel with memory would require changing this assumption,
which would involve modifications to the decoding procedures too.
<LI> Document the new channel type in <A HREF="channel.html">channel.html</A>
and <A HREF="decoding.html">decoding.html</A>.
</OL>
<H2> Adding a new decoding procedure </H2>
A new decoding method can be implemented as follows:
<OL>
<LI> Decide on a syntax for specifying the method and its parameters,
using the trailing arguments to the
<A HREF="decoding.html#decode"><TT>decode</TT></A> program. Pick an
internal name for the method, and add it as a possibility in the
enumerated <TT>decoding_method</TT> type in
<A HREF="dec.h"><TT>dec.h</TT></A>. You may also need to declare
new variables for the method's parameters in
<A HREF="dec.h"><TT>dec.h</TT></A> and <A HREF="dec.c"><TT>dec.c</TT></A>.
<LI> Modify the argument parsing code in
<A HREF="decode.c"><TT>decode.c</TT></A>
to handle specifications of the new method, and change the <TT>usage</TT>
procedure to display the syntax for specifying the new method.
<LI> Write a setup procedure for your decoding method, putting it in
<A HREF="dec.c"><TT>dec.c</TT></A>, with a declaration in
<A HREF="dec.h"><TT>dec.h</TT></A>. At a minimum, this procedure
should print headers for the table of detailed decoding information
when the <B>-T</B> option was specified.
<LI> Write a decode procedure implementing your method, putting it in
<A HREF="dec.c"><TT>dec.c</TT></A>, with a declaration in
<A HREF="dec.h"><TT>dec.h</TT></A>. This procedure should output
detailed trace information when the <B>-T</B> option was specified.
<LI> Modify <A HREF="decode.c"><TT>decode.c</TT></A> in the appropriate
places to call the setup procedure and the decode procedure you wrote.
<LI> Document the new decoding method in
<A HREF="decoding.html">decoding.html</A> and
<A HREF="decode-detail.html">decode-detail.html</A>.
</OL>
<H2> Adding a new method of making a low-density parity-check matrix </H2>
<P>The <A HREF="pchk.html#make-ldpc"><B>make-ldpc</B></A> program can be
changed to add a new method for generating a LDPC code by modifying
<A HREF="make-ldpc.c"><TT>make-ldpc.c</TT></A>. A radically different
method might better be implemented by writing a new program of similar
structure.
<H2> Adding a new encoding method </H2>
<P>A new heuristic for finding a sparse LU decomposition can be
implemented by changing <A HREF="make-gen.c">make-gen.c</A> to allow
the new heuristic to be specified on the command line, changing the <A
HREF="mod2sparse.html#decomp"><B>mod2sparse_decomp</B></A> procedure
in <A HREF="mod2sparse.c"><TT>mod2sparse.c</TT></A> to implement the
heuristic, and documenting the new heuristic in <A
HREF="encoding.html">encoding.html</A>, <A
HREF="sparse-LU.html">sparse-LU.html</A>, and <A
HREF="mod2sparse.html">mod2sparse.html</A>.
<P>To implement a completely new encoding method, you will first need
to define a new file format for a generator matrix, modify <A
HREF="make-gen.c">make-gen.c</A> appropriately to write out this new
format, and modify the <TT>read_gen</TT> procedure in <A
HREF="rcode.c"><TT>rcode.c</TT></A> to read this format. You will
need to implement the new method in a procedure in <A
HREF="enc.c">enc.c</A>, and modify <A HREF="encode.c">encode.c</A> so
that it will call this new procedure when the new method is used. The
<TT>enum_decode</TT> procedure in <A HREF="dec.c">dec.c</A> will also
need to be modified so it can call the new encoding method. Finally,
you should document the new method in <A
HREF="encoding.html">encoding.html</A>
<P>
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>
@@ -1,131 +0,0 @@
#include "NetworkMessage.hpp"
#include <exception>
#include <QString>
#include <QByteArray>
#include "pimpl_impl.hpp"
namespace NetworkMessage
{
Builder::Builder (QIODevice * device, Type type, QString const& id, quint32 schema)
: QDataStream {device}
{
common_initialization (type, id, schema);
}
Builder::Builder (QByteArray * a, Type type, QString const& id, quint32 schema)
: QDataStream {a, QIODevice::WriteOnly}
{
common_initialization (type, id, schema);
}
void Builder::common_initialization (Type type, QString const& id, quint32 schema)
{
if (schema <= 1)
{
setVersion (QDataStream::Qt_5_0); // Qt schema version
}
#if QT_VERSION >= 0x050200
else if (schema <= 2)
{
setVersion (QDataStream::Qt_5_2); // Qt schema version
}
#endif
#if QT_VERSION >= 0x050400
else if (schema <= 3)
{
setVersion (QDataStream::Qt_5_4); // Qt schema version
}
#endif
else
{
throw std::runtime_error {"Unrecognized message schema"};
}
// the following two items assume that the quint32 encoding is
// unchanged over QDataStream versions
*this << magic;
*this << schema;
*this << static_cast<quint32> (type) << id.toUtf8 ();
}
class Reader::impl
{
public:
void common_initialization (Reader * parent)
{
quint32 magic;
*parent >> magic;
if (magic != Builder::magic)
{
throw std::runtime_error {"Invalid message format"};
}
*parent >> schema_;
if (schema_ > Builder::schema_number)
{
throw std::runtime_error {"Unrecognized message schema"};
}
if (schema_ <= 1)
{
parent->setVersion (QDataStream::Qt_5_0);
}
#if QT_VERSION >= 0x050200
else if (schema_ <= 2)
{
parent->setVersion (QDataStream::Qt_5_2);
}
#endif
#if QT_VERSION >= 0x050400
else if (schema_ <= 3)
{
parent->setVersion (QDataStream::Qt_5_4);
}
#endif
quint32 type;
*parent >> type >> id_;
if (type >= maximum_message_type_)
{
throw std::runtime_error {"Unrecognized message type"};
}
type_ = static_cast<Type> (type);
}
quint32 schema_;
Type type_;
QByteArray id_;
};
Reader::Reader (QIODevice * device)
: QDataStream {device}
{
m_->common_initialization (this);
}
Reader::Reader (QByteArray const& a)
: QDataStream {a}
{
m_->common_initialization (this);
}
Reader::~Reader ()
{
}
quint32 Reader::schema () const
{
return m_->schema_;
}
Type Reader::type () const
{
return static_cast<Type> (m_->type_);
}
QString Reader::id () const
{
return QString::fromUtf8 (m_->id_);
}
}
@@ -0,0 +1,31 @@
#include <boost/crc.hpp>
#include <boost/config.hpp>
extern "C"
{
short crc14 (unsigned char const * data, int length);
bool crc14_check (unsigned char const * data, int length);
}
#define POLY 0x2757
#ifdef BOOST_NO_CXX11_CONSTEXPR
#define TRUNCATED_POLYNOMIAL POLY
#else
namespace
{
unsigned long constexpr TRUNCATED_POLYNOMIAL = POLY;
}
#endif
// assumes CRC is last 14 bits of the data and is set to zero
// caller should assign the returned CRC into the message in big endian byte order
short crc14 (unsigned char const * data, int length)
{
return boost::augmented_crc<14, TRUNCATED_POLYNOMIAL> (data, length);
}
bool crc14_check (unsigned char const * data, int length)
{
return !boost::augmented_crc<14, TRUNCATED_POLYNOMIAL> (data, length);
}
@@ -0,0 +1,316 @@
subroutine wqdec(data0,message,ntype)
use packjt
parameter (N15=32758)
integer*1 data0(11)
character*22 message
character*12 callsign
character*3 cdbm,cf
character*2 crpt
character*4 grid,psfx
character*9 name
character*36 fmt
character*6 cwx(4)
character*7 cwind(5)
character ccur*4,cxp*2
logical first
character*12 dcall(0:N15-1)
data first/.true./
data cwx/'CLEAR','CLOUDY','RAIN','SNOW'/
data cwind/'CALM','BREEZES','WINDY','DRY','HUMID'/
save first,dcall
if(first) then
dcall=' '
first=.false.
endif
message=' '
call unpack50(data0,n1,n2)
call unpackcall(n1,callsign,iv2,psfx)
i1=index(callsign,' ')
call unpackgrid(n2/128,grid)
ntype=iand(n2,127) -64
! Standard WSPR message (types 0 3 7 10 13 17 ... 60)
nu=mod(ntype,10)
if(ntype.ge.0 .and. ntype.le.60 .and. (nu.eq.0 .or. nu.eq.3 .or. &
nu.eq.7)) then
write(cdbm,'(i3)'),ntype
if(cdbm(1:1).eq.' ') cdbm=cdbm(2:)
if(cdbm(1:1).eq.' ') cdbm=cdbm(2:)
message=callsign(1:i1)//grid//' '//cdbm
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1)
! "Best DX" WSPR response (type 1)
else if(ntype.eq.1) then
message=grid//' DE '//callsign
! CQ (msg 3; types 2,4,5)
else if(ntype.eq.2) then
message='CQ '//callsign(:i1)//grid
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1)
else if(ntype.eq.4 .or. ntype.eq.5) then
ng=n2/128 + 32768*(ntype-4)
call unpackpfx(ng,callsign)
message='CQ '//callsign
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1)
! Reply to CQ (msg #2; type 6)
else if(ntype.eq.6) then
ih=(n2-64-ntype)/128
if(dcall(ih)(1:1).ne.' ') then
i2=index(dcall(ih),' ')
message='<'//dcall(ih)(:i2-1)//'> '//callsign(:i1-1)
else
message='<...> '//callsign
endif
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! Reply to CQ (msg #2; type 8)
else if(ntype.eq.8) then
message='DE '//callsign(:i1)//grid
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! Reply to CQ, DE pfx/call (msg #2; types 9, 11)
else if(ntype.eq.9 .or. ntype.eq.11) then
ng=n2/128 + 32768*(ntype-9)/2
call unpackpfx(ng,callsign)
message='DE '//callsign
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! Calls and report (msg #3; types -1 to -9)
else if(ntype.le.-1 .and. ntype.ge.-9) then
write(crpt,1010) -ntype
1010 format('S',i1)
ih=(n2-62-ntype)/128
if(dcall(ih)(1:1).ne.' ') then
i2=index(dcall(ih),' ')
message=callsign(:i1)//'<'//dcall(ih)(:i2-1)//'> '//crpt
else
message=callsign(:i1)//'<...> '//crpt
endif
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! pfx/call and report (msg #3; types -10 to -27)
else if(ntype.le.-10 .and. ntype.ge.-27) then
ng=n2/128
nrpt=-ntype-9
if(ntype.le.-19) then
ng=ng + 32768
nrpt=-ntype-18
endif
write(crpt,1010) nrpt
call unpackpfx(ng,callsign)
message=callsign//' '//crpt
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! Calls and R and report (msg #4; types -28 to -36)
else if(ntype.le.-28 .and. ntype.ge.-36) then
write(crpt,1010) -(ntype+27)
ih=(n2-64+28-ntype)/128
if(dcall(ih)(1:1).ne.' ') then
i2=index(dcall(ih),' ')
message=callsign(:i1)//'<'//dcall(ih)(:i2-1)//'> '//'R '//crpt
else
message=callsign(:i1)//'<...> '//'R '//crpt
endif
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! pfx/call R and report (msg #4; types -37 to -54)
else if(ntype.le.-37 .and. ntype.ge.-54) then
ng=n2/128
nrpt=-ntype-36
if(ntype.le.-46) then
ng=ng + 32768
nrpt=-ntype-45
endif
write(crpt,1010) nrpt
call unpackpfx(ng,callsign)
message=callsign//' R '//crpt
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! Calls and RRR (msg#5; type 12)
else if(ntype.eq.12) then
ih=(n2-64+28-ntype)/128
if(dcall(ih)(1:1).ne.' ') then
i2=index(dcall(ih),' ')
message=callsign(:i1)//'<'//dcall(ih)(:i2-1)//'> RRR'
else
message=callsign(:i1)//'<...> RRR'
endif
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! Calls and RRR (msg#5; type 14)
else if(ntype.eq.14) then
ih=(n2-64+28-ntype)/128
if(dcall(ih)(1:1).ne.' ') then
i2=index(dcall(ih),' ')
message='<'//dcall(ih)(:i2-1)//'> '//callsign(:i1)//'RRR'
else
message='<...> '//callsign(:i1)//' RRR'
endif
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! DE pfx/call and RRR (msg#5; types 15, 16)
else if(ntype.eq.15 .or. ntype.eq.16) then
ng=n2/128 + 32768*(ntype-15)
call unpackpfx(ng,callsign)
message='DE '//callsign//' RRR'
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! TNX [name] 73 GL (msg #6; type 18)
else if(ntype.eq.18) then
ng=(n2-18-64)/128
call unpackname(n1,ng,name,len)
message='TNX '//name(:len)//' 73 GL'
! OP [name] 73 GL (msg #6; type 18)
else if(ntype.eq.-56) then
ng=(n2+56-64)/128
call unpackname(n1,ng,name,len)
message='OP '//name(:len)//' 73 GL'
! 73 DE [call] [grid] (msg #6; type 19)
else if(ntype.eq.19) then
ng=(n2-19-64)/128
message='73 DE '//callsign(:i1)//grid
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! 73 DE pfx/call (msg #6; type 21, 22)
else if(ntype.eq.21 .or. ntype.eq.22) then
ng=n2/128 + (ntype-21)*32768
call unpackpfx(ng,callsign)
i1=index(callsign,' ')
message='73 DE '//callsign
call hash(callsign,i1-1,ih)
dcall(ih)=callsign(:i1-1)
! [power] W [gain] DBD 73 GL (msg#6; type 24, 25)
else if(ntype.eq.24 .or. ntype.eq.25) then
ng=(n2-24-64)/128 - 32
i1=1
if(n1.gt.0) i1=log10(float(n1)) + 1
i2=1
if(ng.ge.10) i2=2
if(ng.lt.0) i2=i2+1
if(n1.le.3000) then
if(ntype.eq.24) fmt="(i4,' W ',i2,' DBD 73 GL')"
if(ntype.eq.25) fmt="(i4,' W ',i2,' DBD ')"
fmt(3:3)=char(48+i1)
fmt(12:12)=char(48+i2)
if(ng.le.100) then
write(message,fmt) n1,ng
else
if(ng.eq.30000) fmt=fmt(1:8)//"DIPOLE')"
if(ng.eq.30001) fmt=fmt(1:8)//"VERTICAL')"
write(message,fmt) n1
endif
else
mw=n1-3000
if(ntype.eq.24) fmt="('0.',i3.3,' W ',i2,' DBD 73 GL')"
if(ntype.eq.25) fmt="('0.',i3.3,' W ',i2,' DBD ')"
fmt(19:19)=char(48+i2)
if(ng.le.100) then
write(message,fmt) mw,ng
else
if(ng.eq.30000) fmt=fmt(1:15)//"DIPOLE')"
if(ng.eq.30001) fmt=fmt(1:15)//"VERTICAL')"
write(message,fmt) n1
endif
if(index(message,'***').gt.0) go to 700
endif
! QRZ call (msg #3; type 26)
else if(ntype.eq.26) then
ng=(n2-24-64)/128 - 32
message='QRZ '//callsign
! PSE QSY [nnn] KHZ (msg #6; type 28)
else if(ntype.eq.28) then
if(n1.gt.0) i1=log10(float(n1)) + 1
fmt="('PSE QSY ',i2,' KHZ')"
fmt(14:14)=char(48+i1)
write(message,fmt) n1
! WX wx temp C/F wind (msg #6; type 29)
else if(ntype.eq.29) then
nwx=n1/10000
ntemp=mod(n1,10000) - 100
cf=' F '
if(ntemp.gt.800) then
ntemp=ntemp-1000
cf=' C '
endif
n2a=n2/128
if(nwx.ge.1 .and. nwx.le.4 .and. n2a.ge.1 .and. n2a.le.5) then
write(message,1020) cwx(nwx),ntemp,cf,cwind(n2/128)
1020 format('WX ',a6,i3,a3,a7)
else
message='WX'//' (BadMsg)'
endif
! Hexadecimal data (type 62)
else if(ntype.eq.62) then
ng=n2/128
write(message,'(z4.4,z7.7)') ng,n1
! Solar/geomagnetic/ionospheric data (type 63)
else if(ntype.eq.63) then
ih=(n2-64-ntype)/128
if(dcall(ih)(1:1).ne.' ') then
i2=index(dcall(ih),' ')
message='<'//dcall(ih)(:i2-1)//'> '
else
message='<...> '
endif
call unpackprop(n1,k,muf,ccur,cxp)
i2=index(message,'>')
write(message(i2+1:),'(i3,i3)') k,muf
message=message(:i2+7)//ccur//' '//cxp
! [plain text] (msg #6; type -57)
else if(ntype.eq.-57) then
ng=n2/128
call unpacktext2(n1,ng,message)
else
go to 700
endif
go to 750
! message='<Unknown message type>'
700 i1=index(callsign,' ')
if(i1.lt.1) i1=12
message=callsign(:i1)//' (BadMsg)'
750 do i=1,22
if(ichar(message(i:i)).eq.0) message(i:i)=' '
enddo
do i=22,1,-1
if(message(i:i).ne.' ') go to 800
enddo
800 i2=i
do n=1,20
i1=index(message(:i2),' ')
if(i1.le.0) go to 900
message=message(1:i1)//message(i1+2:)
i2=i2-1
enddo
900 return
end subroutine wqdec