Merged master 8748
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user