Merged master 8748

This commit is contained in:
Jordan Sherer
2018-08-05 11:33:30 -04:00
parent 8f8772f1bd
commit 62899069bf
1222 changed files with 70382 additions and 406763 deletions
@@ -1,342 +0,0 @@
<HTML><HEAD>
<TITLE> Decoding Received Blocks </TITLE>
</HEAD><BODY>
<H1> Decoding Received Blocks </H1>
Transmitted codewords are decoded from the received data on the basis
of the <I>likelihood</I> of the possible codewords, which is the
probability of receiving the data that was actually received if the
codeword is question were the one that was sent. This software
presently deals only with memoryless channels, in which the noise is
independent from bit to bit. For such a channel, the likelihood
factorizes into a product of likelihoods for each bit.
For decoding purposes, all that matters is the relative likelihood
for a bit to be 1 versus 0. This is captured by the <I>likelihood
ratio</I> in favour of a 1, which is P(data | bit is 1) / P(data |
bit is 0).
<P>For a Binary Symmetric Channel with error probability <I>p</I>,
the likelihood ratio in favour of a 1 bit is as follows:
<BLOCKQUOTE>
If the received data was +1: (1-<I>p</I>) / <I>p</I><BR>
If the received data was -1: <I>p</I> / (1-<I>p</I>)
</BLOCKQUOTE>
For an Additive White Gaussian Noise channel, with signals of +1 for a 1 bit
and or -1 for a 0 bit, and with noise standard deviation <I>s</I>, the
likelihood ratio in favour of a 1 bit when data <I>y</I> was received is
<BLOCKQUOTE>
exp ( 2y / s<SUP><SMALL>2</SMALL></SUP> )
</BLOCKQUOTE>
For an Additive White Logistic Noise channel, the corresponding
likelihood ratio is
<I>d</I><SUB><SMALL>1</SMALL></SUB>/<I>d</I><SUB><SMALL>0</SMALL></SUB>,
where
<I>d</I><SUB><SMALL>1</SMALL></SUB>=<I>e</I><SUB><SMALL>1</SMALL></SUB>
/ (1+<I>e</I><SUB><SMALL>1</SMALL></SUB>)<SUP><SMALL>2</SMALL></SUP> and
<I>d</I><SUB><SMALL>0</SMALL></SUB>=<I>e</I><SUB><SMALL>0</SMALL></SUB>
/ (1+<I>e</I><SUB><SMALL>0</SMALL></SUB>)<SUP><SMALL>2</SMALL></SUP>,
with <I>e</I><SUB><SMALL>1</SMALL></SUB>=exp(-(<I>y</I>-1)/<I>w</I>) and
<I>e</I><SUB><SMALL>0</SMALL></SUB>=exp(-(<I>y</I>+1)/<I>w</I>).
<BLOCKQUOTE> </BLOCKQUOTE>
<P>It is usual to consider codewords to be equally likely <I>a
priori</I>. This is reasonable if the source messages are all equally
likely (any source redundancy being ignored, or remove by a
preliminary data compression stage), provided that the mapping from
source messages to codewords is onto. Decoding can then be done using
only the parity check matrix defining the codewords, without reference
to the generator matrix defining the mapping from source messages to
codewords. Note that the condition that this mapping be onto isn't
true with this software in the atypical case where the code is defined
by a parity check matrix with redundant rows; see the discussion of <A
HREF="dep-H.html">linear dependence in parity check matrices</A>.
This minor complication is mostly ignored here, except by the exhaustive
enumeration decoding methods.
<P>Assuming equal <I>a priori</I> probabilities for codewords, the
probability of correctly decoding an entire codeword is minimized by
picking the codeword with the highest likelihood. One might instead
wish to decode each bit to the value that is most probable. This
minimizes the bit error rate, but is not in general guaranteed to lead
a decoding for each block to the most probable complete codeword;
indeed, the decoding may not be a codeword at all. Minimizing the bit
error rate seems nevertheless to be the most sensible objective,
unless block boundaries have some significance in a wider context.
<P>Optimal decoding by either criterion is infeasible for general
linear codes when messages are more than about 20 or 30 bits in
length. The fundamental advantage of Low Density Parity Check codes
is that good (though not optimal) decodings can be obtained by methods
such as probability propagation, described next.
<A NAME="prprp"><H2>Decoding by probability propagation</H2></A>
<P>The probability propagation algorithm was originally devised by
Robert Gallager in the early 1960's and later reinvented by David
MacKay and myself. It can be seen as an instance of the sum-product
algorithm for inference on factor graphs, and as an instance of belief
propagation in probabilistic networks. See the <A
HREF="refs.html">references</A> for details. Below, I give a fairly
intuitive description of the algorithm.
<P>The algorithm uses only the parity check matrix for the code, whose
columns correspond to codeword bits, and whose rows correspond to
parity checks, and the likelihood ratios for the bits derived from the
data. It aims to find the probability of each bit of the transmitted
codeword being 1, though the results of the algorithm are in general
only approximate.
<P>The begin, information about each bit of the codeword derived from
the received data for that bit alone is expressed as a <I>probability
ratio</I>, the probability of the bit being 1 divided by the
probability of the bit being 0. This probability ratio is equal to
the likelihood ratio (see above) for that bit, since 0 and 1 are
assumed to be equally likely <I>a priori</I>. As the algorithm
progresses, these probability ratios will be modified to take account
of information obtained from other bits, in conjunction with the
requirement that the parity checks be satisfied. To avoid double
counting of information, for every bit, the algorithm maintains a
separate probability ratio for each parity check that that bit
participates in, giving the probability for that bit to be 1 versus 0
based only on information derived from <I>other</I> parity checks,
along with the data received for the bit.
<P>For each parity check, the algorithm maintains separate
<I>likelihood ratios</I> (analogous to, but distinct from, the
likelihood ratios based on received data), for every bit that
participates in that parity check. These ratios give the probability
of that parity check being satisfied if the bit in question is 1
divided by the probability of the check being satisfied if the bit is
0, taking account of the probabilities of each of the <I>other</I>
bits participating in this check being 1, as derived from the
probability ratios for these bits with respect to this check.
<P>The algorithm alternates between recalculating the likelihood
ratios for each check, which are stored in the <B>lr</B> fields of the
parity check matrix entries, and recalculating the probability ratios
for each bit, which are stored in the <B>pr</B> fields of the entries
in the sparse matrix representation of the parity check matrix. (See
the documentation on <A HREF="mod2sparse.html#rep">representation of
sparse matrices</A> for details on these entries.)
<P>Recalculating the likelihood ratio for a check with respect to some
bit may appear time consuming, requiring that all possible
combinations of values for the other bits participating in the check
be considered. Fortunately, there is a short cut. One can calculate
<BLOCKQUOTE>
<I>t</I>
= product of [ 1 / (1+<I>p<SUB><SMALL>i</SMALL></SUB></I>)
- <I>p<SUB><SMALL>i</SMALL></SUB></I> /
(1+<I>p<SUB><SMALL>i</SMALL></SUB></I>) ]
= product of [ 2 / (1+<I>p<SUB><SMALL>i</SMALL></SUB></I>) - 1 ]
</BLOCKQUOTE>
where the product is over the probability ratios
<I>p<SUB><SMALL>i</SMALL></SUB></I> for the other bits participating
in this check. Factor <I>i</I> in this product is equal to probability
of bit <I>i</I> being 0 minus the probability that it is 1. The terms
in the expansion of this product (in the first form above) correspond to
possible combinations of values for the other bits, with the result that
<I>t</I> will be the probability of the check being satisfied if the bit
in question is 0 minus the probability if the bit in question is 1. The
likelihood ratio for this check with respect to the bit in question can then
be calculated as (1-<I>t</I>)/(1+<I>t</I>).
<P>For a particular check, the product above differs for different
bits, with respect to which we wish to calculate a likelihood ratio,
only in that for each bit the factor corresponding to that bit is left
out. We can calculate all these products easily by ordering the bits
arbitrarily, computing running products of the factor for the first
bit, the factors for the first two bits, etc., and also running
products of the factor for the last bit, the factors for the last two
bits, etc. Multiplying the running product of the factors up to
<I>i</I>-1 by the running product of the factors from <I>i</I>+1 on
gives the product needed for bit <I>i</I>. The second form of the
factors above is used, as it requires less computation, and is still
well defined even if some ratios are infinite.
<P>To recalculate the probability ratio for a bit with respect to a
check, all that is need is to multiply together the likelihood ratio
for this bit derived from the received data (see above), and the
current values of the likelihood ratios for all the <I>other</I>
checks that this bit participates in, with respect to this bit. To
save time, these products are computed by combining forward and
backward products, similarly to the method used for likelihood ratios.
<P>By including likelihood ratios from all checks, a similar
calculation produces the current probability ratio for the bit to be 1
versus 0 based on all information that has propagated to the bit so
far. This ratio can be thresholded at one to produce the current best
guess as to whether this bit is a 1 or a 0.
<P>The hope is that this algorithm will eventually converge to a state
where these bit probabilities give a near-optimal decoding. This is
does not always occur, but the algorithm behaves well enough to
produce very good results at rates approaching (though not yet
reaching) the theoretical Shannon limit.
<P><A NAME="decode"><HR><B>decode</B>: Decode blocks of received data
into codewords.
<BLOCKQUOTE><PRE>
decode [ -f ] [ -t | -T ] <I>pchk-file received-file decoded-file</I> [ <I>bp-file</I> ] <I>channel method</I>
</PRE>
<BLOCKQUOTE>
where <TT><I>channel</I></TT> is one of:
<BLOCKQUOTE><PRE>
bsc <I>error-probability</I>
awgn <I>standard-deviation</I>
awln <I>width</I>
</PRE></BLOCKQUOTE>
and <TT><I>method</I></TT> is one of:
<BLOCKQUOTE><PRE>
enum-block <TT><I>gen-file</I></TT>
enum-bit <TT><I>gen-file</I></TT>
prprp <TT>[-]<I>max-iterations</I></TT>
</PRE></BLOCKQUOTE>
</BLOCKQUOTE>
</BLOCKQUOTE>
<P>Decodes the blocks in <TT><I>received-file</I></TT>, which are
assumed to be have been received through the specified channel. The
results written to <TT><I>decoded-file</I></TT> are the specified
decoding method's guesses as to what bits were sent through the
channel, given what was received. The probability of each bit being a
1, as judged by the decoding method being used, is written to
<TT><I>bp-file</I></TT>, if given.
<P>A newline is output at the end of each block written to
<TT><I>decoded-file</I></TT> and <TT><I>bp-file</I></TT>. Newlines in
<TT><I>received-file</I></TT> are ignored. A warning is displayed on
standard error if the number of bits in <TT><I>received-file</I></TT>
is not a multiple of the block length.
<P>A summary is displayed on standard error, giving the total number
of blocks decoded, the number of blocks that decoded to valid
codewords, the average number of iterations of the decoding algorithm
used, and the percent of bits that were changed from the values one
would guess for them based just on their individual likelihood ratios.
<P>If the <B>-t</B> option is given, a line of information regarding each block
decoded is written to standard output, preceded by a line of headers.
The information for each block is as follows:
<BLOCKQUOTE>
<TABLE>
<tr align="left" valign="top">
<td> <B>block</B> </td>
<td>The number of the block, from zero</td></tr>
<tr align="left" valign="top">
<td> <B>iterations</B> </td>
<td>The number of "iterations" used in decoding. What exactly an iteration
is depends on the decoding method used (see
<A HREF="decode-detail.html">here</A>).</td></tr>
<tr align="left" valign="top">
<td> <B>valid</B> </td>
<td>Has the value 1 if the decoding is a valid codeword, 0 if not.</td></tr>
<tr align="left" valign="top">
<td> <B>changed</B> </td>
<td>The number of bits in the decoding that differ from the bit that would
be chosen based just on the likelihood ratio for that bit. Bits whose
likelihood ratios are exactly one contribute 0.5 to this count.</td></tr>
</TABLE>
</BLOCKQUOTE>
The file produced is is suitable for
reading into the S-Plus or R statistics packages, with a command such as
<BLOCKQUOTE><PRE>
data <- read.table(<I>file</I>,header=T)
</PRE></BLOCKQUOTE>
<P>If instead the <B>-T</B> option is given, detailed information on
the process of decoding each block will be written to standard output.
For a description, see the <A HREF="decode-detail.html">documentation
on detailed decoding trace information</A>.
<P>The type of channel that is assumed is specified after the file
name arguments. This may currently be either <TT>bsc</TT> (or
<TT>BSC</TT>) for the Binary Symmetric Channel, or <TT>awgn</TT> (or
<TT>AWGN</TT>) for the Additive White Gaussian Noise channel, or
<TT>awln</TT> (or <TT>AWLN</TT>) for the Additive White Logistic Noise
channel. The channel type is followed by an argument specifying the
assumed characteristics of the channel, as follows:
<BLOCKQUOTE>
<P>BSC: The probability that a bit will be flipped by noise - ie, the
probability that the bit received is an error.
<P>AWGN: The standard deviation of the Gaussian noise added to the
encodings of the bits.
<P>AWLN: The width parameter of the logistic distribution for the noise
that is added to the encodings of the bits.
</BLOCKQUOTE>
See the description of <A HREF="channel.html">channel transmission</A>
for more about these channels.
<P>Following the channel specification is a specification of the
decoding method to use. The <TT>enum-block</TT> and <TT>enum-bit</TT>
methods find the optimal decoding by exhaustive enumeration of
codewords derived from all possible source messages. They differ in
that <TT>enum-block</TT> decodes to the most likely codeword, whereas
<TT>enum-bit</TT> decodes to the bits that are individually most
probable. These methods require that a file containing a
representation of a generator matrix be given, to allow enumeration of
codewords. If the parity check matrix has no redundant rows, any
valid generator matrix will give the same decoding (except perhaps if
there is a tie). If redundant rows exist, the generator matrix should
specify the same set of message bits as the generator matrix that was
used for the actual encoding, since the redundancy will lead to some
codeword bits being fixed at zero (see <A HREF="dep-H.html">linear
dependence in parity check matrices</A>).
<P>The <TT>prprp</TT> decoding method decodes using <A
HREF="#prprp">probability propagation</A>. The maximum number of
iterations of probability propagation to do is given following
<TT>prprp</TT>. If a minus sign precedes this number, the maximum
number of iterations is always done. If no minus sign is present, the
algorithm stops once the tentative decoding, based on bit-by-bit
probabilities, is a valid codeword. Note that continuing to the
maximum number of iterations will usually result in
at least slightly different bit probabilities (written to
<TT><I>bp-file</I></TT> if specified), and could conceivably change
the decoding compared to stopping at the first valid codeword, or
result in a failure to decode to a valid codeword even though one was
found earlier.
<P>If the <B>-f</B> option is given, output to <TT><I>decoded-file</I></TT>
is flushed after each block. This allows one to use decode as a server,
reading blocks to decode from a named pipe, and writing the decoded block
to another named pipe.
<P><A NAME="extract"><HR><B>extract</B>: Extract the message bits from a block.
<BLOCKQUOTE><PRE>
extract <I>gen-file decoded-file extracted-file</I>
</PRE></BLOCKQUOTE>
<P>Given a file of codewords in <TT><I>decoded-file</I></TT> (usually,
decoded blocks output by <A HREF="#decode"><TT>decode</TT></A>), and a
generator matrix from <TT><I>gen-file</I></TT> (needed only to
determine where the message bits are located in a codeword), this
program writes the message bits extracted from these codewords to the
file <TT><I>extracted-file</I></TT>.
<P>A newline is output at the end of each block written to
<TT><I>extracted-file</I></TT>. Newlines in
<TT><I>decoded-file</I></TT> are ignored. A warning is displayed on
standard error if the number of bits in <TT><I>decoded-file</I></TT>
is not a multiple of the block length.
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>
@@ -1,200 +0,0 @@
#ifndef TRANSCEIVER_FACTORY_HPP__
#define TRANSCEIVER_FACTORY_HPP__
#include <memory>
#include <QObject>
#include <QMap>
#include "Transceiver.hpp"
#include "qt_helpers.hpp"
class QString;
class QThread;
class QDir;
//
// Transceiver Factory
//
class TransceiverFactory
: public QObject
{
Q_OBJECT
Q_ENUMS (DataBits StopBits Handshake PTTMethod TXAudioSource SplitMode)
public:
//
// Capabilities of a Transceiver that can be determined without
// actually instantiating one, these are for use in Configuration
// GUI behaviour determination
//
struct Capabilities
{
enum PortType {none, serial, network, usb};
explicit Capabilities (int model_number = 0
, PortType port_type = none
, bool has_CAT_PTT = false
, bool has_CAT_PTT_mic_data = false
, bool has_CAT_indirect_serial_PTT = false
, bool asynchronous = false)
: model_number_ {model_number}
, port_type_ {port_type}
, has_CAT_PTT_ {has_CAT_PTT}
, has_CAT_PTT_mic_data_ {has_CAT_PTT_mic_data}
, has_CAT_indirect_serial_PTT_ {has_CAT_indirect_serial_PTT}
, asynchronous_ {asynchronous}
{
}
int model_number_;
PortType port_type_;
bool has_CAT_PTT_;
bool has_CAT_PTT_mic_data_;
bool has_CAT_indirect_serial_PTT_; // OmniRig controls RTS/DTR via COM interface
bool asynchronous_;
};
//
// Dictionary of Transceiver types Capabilities
//
typedef QMap<QString, Capabilities> Transceivers;
//
// various Transceiver parameters
//
enum DataBits {seven_data_bits = 7, eight_data_bits};
Q_ENUM (DataBits)
enum StopBits {one_stop_bit = 1, two_stop_bits};
Q_ENUM (StopBits)
enum Handshake {handshake_none, handshake_XonXoff, handshake_hardware};
Q_ENUM (Handshake)
enum PTTMethod {PTT_method_VOX, PTT_method_CAT, PTT_method_DTR, PTT_method_RTS};
Q_ENUM (PTTMethod)
enum TXAudioSource {TX_audio_source_front, TX_audio_source_rear};
Q_ENUM (TXAudioSource)
enum SplitMode {split_mode_none, split_mode_rig, split_mode_emulate};
Q_ENUM (SplitMode)
TransceiverFactory ();
~TransceiverFactory ();
static char const * const basic_transceiver_name_; // dummy transceiver is basic model
//
// fetch all supported rigs as a list of name and model id
//
Transceivers const& supported_transceivers () const;
// supported model queries
Capabilities::PortType CAT_port_type (QString const& name) const; // how to talk to CAT
bool has_CAT_PTT (QString const& name) const; // can be keyed via CAT
bool has_CAT_PTT_mic_data (QString const& name) const; // Tx audio port is switchable via CAT
bool has_CAT_indirect_serial_PTT (QString const& name) const; // Can PTT via CAT port use DTR or RTS (OmniRig for example)
bool has_asynchronous_CAT (QString const& name) const; // CAT asynchronous rather than polled
struct ParameterPack
{
QString rig_name; // from supported_transceivers () key
QString serial_port; // serial port device name or empty
QString network_port; // hostname:port or empty
QString usb_port; // [vid[:pid[:vendor[:product]]]]
int baud;
DataBits data_bits;
StopBits stop_bits;
Handshake handshake;
bool force_dtr;
bool dtr_high; // to power interface
bool force_rts;
bool rts_high; // to power interface
PTTMethod ptt_type; // "CAT" | "DTR" | "RTS" | "VOX"
TXAudioSource audio_source; // some rigs allow audio routing
// to Mic/Data connector
SplitMode split_mode; // how to support split TX mode
QString ptt_port; // serial port device name or special
// value "CAT"
int poll_interval; // in seconds for interfaces that
// require polling for state changes
bool operator == (ParameterPack const& rhs) const
{
return rhs.rig_name == rig_name
&& rhs.serial_port == serial_port
&& rhs.network_port == network_port
&& rhs.usb_port == usb_port
&& rhs.baud == baud
&& rhs.data_bits == data_bits
&& rhs.stop_bits == stop_bits
&& rhs.handshake == handshake
&& rhs.force_dtr == force_dtr
&& rhs.dtr_high == dtr_high
&& rhs.force_rts == force_rts
&& rhs.rts_high == rts_high
&& rhs.ptt_type == ptt_type
&& rhs.audio_source == audio_source
&& rhs.split_mode == split_mode
&& rhs.ptt_port == ptt_port
&& rhs.poll_interval == poll_interval
;
}
};
// make a new Transceiver instance
//
// cat_port, cat_baud, cat_data_bits, cat_stop_bits, cat_handshake,
// cat_dtr_control, cat_rts_control are only relevant to interfaces
// that are served by Hamlib
//
// PTT port and to some extent ptt_type are independent of interface
// type
//
std::unique_ptr<Transceiver> create (ParameterPack const&, QThread * target_thread = nullptr);
private:
Transceivers transceivers_;
};
inline
bool operator != (TransceiverFactory::ParameterPack const& lhs, TransceiverFactory::ParameterPack const& rhs)
{
return !(lhs == rhs);
}
//
// boilerplate routines to make enum types useable and debuggable in
// Qt
//
#if QT_VERSION < 0x050500
Q_DECLARE_METATYPE (TransceiverFactory::DataBits);
Q_DECLARE_METATYPE (TransceiverFactory::StopBits);
Q_DECLARE_METATYPE (TransceiverFactory::Handshake);
Q_DECLARE_METATYPE (TransceiverFactory::PTTMethod);
Q_DECLARE_METATYPE (TransceiverFactory::TXAudioSource);
Q_DECLARE_METATYPE (TransceiverFactory::SplitMode);
#endif
#if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, DataBits);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, StopBits);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, Handshake);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, PTTMethod);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, TXAudioSource);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, SplitMode);
#endif
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, DataBits);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, StopBits);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, Handshake);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, PTTMethod);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, TXAudioSource);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, SplitMode);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, DataBits);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, StopBits);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, Handshake);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, PTTMethod);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, TXAudioSource);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, SplitMode);
#endif
@@ -0,0 +1,68 @@
// -*- Mode: C++ -*-
#ifndef LogQSO_H
#define LogQSO_H
#ifdef QT5
#include <QtWidgets>
#else
#include <QtGui>
#endif
#include <QString>
#include <QScopedPointer>
#include <QDateTime>
#include "Radio.hpp"
namespace Ui {
class LogQSO;
}
class QSettings;
class Configuration;
class QByteArray;
class LogQSO : public QDialog
{
Q_OBJECT
public:
explicit LogQSO(QString const& programTitle, QSettings *, Configuration const *, QWidget *parent = 0);
~LogQSO();
void initLogQSO(QString const& hisCall, QString const& hisGrid, QString mode,
QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn,
QDateTime const& dateTimeOff,
Radio::Frequency dialFreq, QString const& myCall, QString const& myGrid,
bool noSuffix, bool toRTTY, bool dBtoComments, bool bFox, QString const& opCall);
public slots:
void accept();
signals:
void acceptQSO (QDateTime const& QSO_date_off, QString const& call, QString const& grid
, Radio::Frequency dial_freq, QString const& mode
, QString const& rpt_sent, QString const& rpt_received
, QString const& tx_power, QString const& comments
, QString const& name, QDateTime const& QSO_date_on, QString const& operator_call
, QString const& my_call, QString const& my_grid, QByteArray const& ADIF);
protected:
void hideEvent (QHideEvent *);
private:
void loadSettings ();
void storeSettings () const;
QScopedPointer<Ui::LogQSO> ui;
QSettings * m_settings;
Configuration const * m_config;
QString m_txPower;
QString m_comments;
Radio::Frequency m_dialFreq;
QString m_myCall;
QString m_myGrid;
QDateTime m_dateTimeOn;
QDateTime m_dateTimeOff;
};
#endif // LogQSO_H
@@ -1,238 +0,0 @@
program ldpcsim174
! End to end test of the (174,75)/crc12 encoder and decoder.
use crc
use packjt
parameter(NRECENT=10)
character*12 recent_calls(NRECENT)
character*22 msg,msgsent,msgreceived
character*8 arg
integer*1, allocatable :: codeword(:), decoded(:), message(:)
integer*1, target:: i1Msg8BitBytes(11)
integer*1 msgbits(87)
integer*1 apmask(174), cw(174)
integer*2 checksum
integer*4 i4Msg6BitWords(13)
integer colorder(174)
integer nerrtot(174),nerrdec(174),nmpcbad(87)
logical checksumok,fsk,bpsk
real*8, allocatable :: rxdata(:)
real, allocatable :: llr(:)
data colorder/ &
0, 1, 2, 3, 30, 4, 5, 6, 7, 8, 9, 10, 11, 32, 12, 40, 13, 14, 15, 16,&
17, 18, 37, 45, 29, 19, 20, 21, 41, 22, 42, 31, 33, 34, 44, 35, 47, 51, 50, 43,&
36, 52, 63, 46, 25, 55, 27, 24, 23, 53, 39, 49, 59, 38, 48, 61, 60, 57, 28, 62,&
56, 58, 65, 66, 26, 70, 64, 69, 68, 67, 74, 71, 54, 76, 72, 75, 78, 77, 80, 79,&
73, 83, 84, 81, 82, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,&
100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,&
120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,&
140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,&
160,161,162,163,164,165,166,167,168,169,170,171,172,173/
do i=1,NRECENT
recent_calls(i)=' '
enddo
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
print*,'Usage: ldpcsim niter norder #trials s '
print*,'eg: ldpcsim 10 2 1000 0.84'
print*,'belief propagation iterations: niter, ordered-statistics order: norder'
print*,'If s is negative, then value is ignored and sigma is calculated from SNR.'
return
endif
call getarg(1,arg)
read(arg,*) max_iterations
call getarg(2,arg)
read(arg,*) norder
call getarg(3,arg)
read(arg,*) ntrials
call getarg(4,arg)
read(arg,*) s
fsk=.false.
bpsk=.true.
! don't count crc bits as data bits
N=174
K=87
! scale Eb/No for a (174,87) code
rate=real(K)/real(N)
write(*,*) "rate: ",rate
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"
call packmsg(msg,i4Msg6BitWords,itype) !Pack into 12 6-bit bytes
call unpackmsg(i4Msg6BitWords,msgsent) !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:11)=0
checksum = crc12 (c_loc (i1Msg8BitBytes), 11)
! For reference, the next 3 lines show how to check the CRC
i1Msg8BitBytes(10)=checksum/256
i1Msg8BitBytes(11)=iand (checksum,255)
checksumok = crc12_check(c_loc (i1Msg8BitBytes), 11)
if( checksumok ) write(*,*) 'Good checksum'
! K=87, For now:
! msgbits(1:72) JT message bits
! msgbits(73:75) 3 free message bits (set to 0)
! msgbits(76:87) CRC12
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:75)=0 ! the three extra message bits go here
i1=i1Msg8BitBytes(10) ! First 4 bits of crc12 are LSB of this byte
do ibit=1,4
msgbits(75+ibit)=iand(1,ishft(i1,ibit-4))
enddo
i1=i1Msg8BitBytes(11) ! Now shift in last 8 bits of the CRC
do ibit=1,8
msgbits(79+ibit)=iand(1,ishft(i1,ibit-8))
enddo
write(*,*) 'message'
write(*,'(11(8i1,1x))') msgbits
call encode174(msgbits,codeword)
call init_random_seed()
call sgran()
write(*,*) 'codeword'
write(*,'(22(8i1,1x))') codeword
write(*,*) "Es/N0 SNR2500 ngood nundetected nbadcrc sigma"
do idb = 20,-10,-1
db=idb/2.0-1.0
sigma=1/sqrt( 2*(10**(db/10.0)) )
ngood=0
nue=0
nbadcrc=0
nberr=0
do itrial=1, ntrials
! Create a realization of a noisy received word
do i=1,N
if( bpsk ) then
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
elseif( fsk ) then
if( codeword(i) .eq. 1 ) then
r1=(1.0 + sigma*gran())**2 + (sigma*gran())**2
r2=(sigma*gran())**2 + (sigma*gran())**2
elseif( codeword(i) .eq. 0 ) then
r2=(1.0 + sigma*gran())**2 + (sigma*gran())**2
r1=(sigma*gran())**2 + (sigma*gran())**2
endif
! rxdata(i)=0.35*(sqrt(r1)-sqrt(r2))
! rxdata(i)=0.35*(exp(r1)-exp(r2))
rxdata(i)=0.12*(log(r1)-log(r2))
endif
enddo
nerr=0
do i=1,N
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
enddo
nerrtot(nerr)=nerrtot(nerr)+1
nberr=nberr+nerr
! Correct signal normalization is important for this decoder.
rxav=sum(rxdata)/N
rx2av=sum(rxdata*rxdata)/N
rxsig=sqrt(rx2av-rxav*rxav)
rxdata=rxdata/rxsig
! To match the metric to the channel, s should be set to the noise standard deviation.
! For now, set s to the value that optimizes decode probability near threshold.
! The s parameter can be tuned to trade a few tenth's dB of threshold for an order of
! magnitude in UER
if( s .lt. 0 ) then
ss=sigma
else
ss=s
endif
llr=2.0*rxdata/(ss*ss)
nap=0 ! number of AP bits
llr(colorder(174-87+1:174-87+nap)+1)=5*(2.0*msgbits(1:nap)-1.0)
apmask=0
apmask(colorder(174-87+1:174-87+nap)+1)=1
! max_iterations is max number of belief propagation iterations
call bpdecode174(llr, apmask, max_iterations, decoded, cw, nharderrors)
if( norder .ge. 0 .and. nharderrors .lt. 0 ) call osd174(llr, norder, decoded, cw, nharderrors)
! If the decoder finds a valid codeword, nharderrors will be .ge. 0.
if( nharderrors .ge. 0 ) then
call extractmessage174(decoded,msgreceived,ncrcflag,recent_calls,nrecent)
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
nmpcbad(nerrmpc)=nmpcbad(nerrmpc)+1
if( ncrcflag .eq. 1 ) then
if( nueflag .eq. 0 ) then
ngood=ngood+1
nerrdec(nerr)=nerrdec(nerr)+1
else if( nueflag .eq. 1 ) then
nue=nue+1;
endif
endif
endif
enddo
baud=12000/2048
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
enddo
open(unit=23,file='nerrhisto.dat',status='unknown')
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