[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 05/06: digital: Complete overhaul of protoc
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 05/06: digital: Complete overhaul of protocol handling |
Date: |
Wed, 15 Jun 2016 04:11:15 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
jcorgan pushed a commit to branch packet3
in repository gnuradio.
commit 817f61bbdd180a2854116c85ccf1020e561c523f
Author: Tom Rondeau <address@hidden>
Date: Tue Jun 14 10:48:00 2016 -0700
digital: Complete overhaul of protocol handling
See documentation for details. In brief:
- digital_protocol_* classes added (replace packet header blocks)
- header_buffer class added
- Lots of QA
- default packet formatter: contains access code and payload length
fields.
- counter packet formatter: also contains the bits/sym in the payload
modulation and a packet number counter.
- Also adds QA code and the infrastructure for C++ QA code in
gr-digital.
- New block to use the packet formatter objects.
- The header and payload are transmitted as PDU messages out of
different ports.
- header_buffer class for header formatting.
- Used by packet_formatter_x classes to more easily add and format
header data for transmission.
- New blocks that parse headers.
- Handles either hard or soft bits. Produces an info message to
instruct payload demod.
- 'receive mode' to header_buffer class.
- Designed to make extracting fields from the received header bits
easier for packet formatter classes. Use extract_field[N] to get
the different fields out of a collected set of header bits. *
Docs describing both functions with small examples for how to use
them.
- Don't force access code to be a multiple of 8
- need to verify everything else handles this correctly.
- Throw an exception in the ctor if setting the code failed and emit a
log message.
Committed-By: Martin Braun <address@hidden>
---
gr-digital/doc/packet_comms.dox | 653 +++++++
gr-digital/examples/CMakeLists.txt | 8 +
gr-digital/examples/ofdm/tx_ofdm.grc | 2067 +++++++++++---------
gr-digital/grc/digital_block_tree.xml | 6 +-
.../grc/digital_protocol_formatter_async.xml | 33 +
gr-digital/grc/digital_protocol_formatter_bb.xml | 32 +
gr-digital/grc/digital_protocol_parser_b.xml | 25 +
gr-digital/grc/variable_header_format_default.xml | 35 +
gr-digital/include/gnuradio/digital/CMakeLists.txt | 11 +-
.../include/gnuradio/digital/header_buffer.h | 310 +++
.../include/gnuradio/digital/header_format_base.h | 225 +++
.../gnuradio/digital/header_format_counter.h | 135 ++
.../include/gnuradio/digital/header_format_crc.h | 118 ++
.../gnuradio/digital/header_format_default.h | 217 ++
.../include/gnuradio/digital/header_format_ofdm.h | 127 ++
.../gnuradio/digital/protocol_formatter_async.h | 88 +
.../gnuradio/digital/protocol_formatter_bb.h | 81 +
.../include/gnuradio/digital/protocol_parser_b.h | 80 +
gr-digital/lib/CMakeLists.txt | 46 +-
gr-digital/lib/header_buffer.cc | 211 ++
gr-digital/lib/header_format_base.cc | 70 +
gr-digital/lib/header_format_counter.cc | 120 ++
gr-digital/lib/header_format_crc.cc | 161 ++
gr-digital/lib/header_format_default.cc | 222 +++
gr-digital/lib/header_format_ofdm.cc | 180 ++
gr-digital/lib/packet_header_ofdm.cc | 9 +-
gr-digital/lib/protocol_formatter_async_impl.cc | 94 +
gr-digital/lib/protocol_formatter_async_impl.h | 50 +
gr-digital/lib/protocol_formatter_bb_impl.cc | 118 ++
gr-digital/lib/protocol_formatter_bb_impl.h | 56 +
gr-digital/lib/protocol_parser_b_impl.cc | 83 +
gr-digital/lib/protocol_parser_b_impl.h | 52 +
.../{swig/packet_header.i => lib/qa_digital.cc} | 39 +-
.../{swig/packet_header.i => lib/qa_digital.h} | 34 +-
gr-digital/lib/qa_header_buffer.cc | 364 ++++
gr-digital/lib/qa_header_buffer.h | 59 +
gr-digital/lib/qa_header_format.cc | 265 +++
.../packet_header.i => lib/qa_header_format.h} | 43 +-
.../packet_header.i => lib/test_gr_digital.cc} | 44 +-
gr-digital/python/digital/qa_packet_format.py | 135 ++
gr-digital/swig/CMakeLists.txt | 1 +
gr-digital/swig/digital_swig.i | 21 +-
gr-digital/swig/packet_header.i | 34 +-
43 files changed, 5757 insertions(+), 1005 deletions(-)
diff --git a/gr-digital/doc/packet_comms.dox b/gr-digital/doc/packet_comms.dox
new file mode 100644
index 0000000..9b9f59f
--- /dev/null
+++ b/gr-digital/doc/packet_comms.dox
@@ -0,0 +1,653 @@
+/*! \page page_packet_comms Packet Communications
+
+\section packet_introduction Introduction
+
+This page describes...
+
+The point of these examples and the work is to provide a canonical
+tool for exploring burst digital communications. Providing the entire
+PHY chain in GRC is to help us more easily explore and extract
+portions of the transmit and receive chains to better understand,
+tweak, and optimize the system.
+
+
+\section packet_tx Understanding the Transmitter
+
+The transmitter PHY layer defines the following properties of the
+transmitted frame:
+
+- Data integrity check, generally a \ref gr::digital::crc32_async_bb
+ "CRC". Standard practice would be to calculate a CRC32 of the
+ payload and append this to the end of the frame.
+
+- \ref page_fec "Forward Error Correction (FEC)". For correcting bit
+ errors during reception, we use FEC codes, which have different
+ properties for complexity, correcting capabilities, and amounts of
+ added redundancy. See our \ref page_fec "FEC-API page" in the manual
+ for more on how to use these and what types of codes are already
+ available.
+
+- Frame formatting. We expect the data to have been delivered to the
+ transmitter from some higher layer (MAC/Network), which we treat as
+ the payload. The PHY layer then puts on a bit of its own framing in
+ order to properly transmit it for other radios to receive
+ correctly. This often involves some information about the payload
+ format, such as the length, the type of FEC code used, and the type
+ of modulation or modulation parameters. The PHY layer frame will
+ also often add a known word to the front to help with
+ synchronization and identification. We use the Packet Header
+ Formatter block for this, which is completely defined by a packet
+ formatter object. See the gr::digital::header_format_base class
+ to understand more about how these formatters are created and used.
+
+ The \ref gr::digital::protocol_formatter_async "Protocol Formatter"
+ has two output paths, both emitted as PDUs from message ports. The
+ first message port is "header" that emits the header created for the
+ payload based on the formatter object. The second message port is
+ "payload" which is just the input payload PDU re-emitted. This
+ creates two paths, which allows us to separately modulate the header
+ and payload differently as well as encode the header with a
+ different FEC code. We often want to do this to provide a much
+ simpler and more robust modulation and FEC structure to the header
+ to ensure that it is correctly received and then use a different
+ modulation and code for the payload to maximize throughput.
+
+ NOTE: If the header formatter adds the known word / access code
+ here, and then we apply an FEC code to the header, then we have the
+ problem that the known word is also encoded. The receiver must be
+ made aware of this and correctly look for the encoded known
+ word. The packet_tx hier block example is a case where this
+ happens. If we use a repetition encoder, the access code is now
+ three bits out for every bit in. The packet_rx receiver example has
+ to account for this in the Correlation Estimator block that is
+ correlating against the known word.
+
+- Modulators. We create a modulator path for both the header and
+ payload. We define the operations of these two paths completely
+ using a \ref gr::digital::constellation "Constellation Object" (see
+ the \ref digital_constellations "Digital Modulation" manual page for
+ more information). The constellation objects define the mapping from
+ bits to complex symbols. You can use these objects in various ways,
+ but the packet_tx.grc example provides one way. After moving from
+ the PDU to tagged stream mode, the \ref gr::blocks::repack_bits_bb
+ "Repack Bits block" takes the packed 8-bits/byte data and converts
+ this into "chunks" of the number of bits per symbol of the
+ modulation (using the \ref
+ gr::digital::constellation::bits_per_symbol() "bits_per_symbol()"
+ property of the constellation object). We then map these chunks into
+ some known mapping function, most often a form of Gray Coding, using
+ the \ref gr::digital::map_bb "Map block" and the constellation object's \ref
+ gr::digital::constellation::pre_diff_code() "pre_diff_code()"
+ function. We then move these remapped chunks to complex symbols,
+ again as defined by the constellation object through the \ref
+ gr::digital::constellation::points() "points()" function in the
+ \ref gr::digital::chunks_to_symbols_bc "Chunks to Symbols block".
+
+- Combine the header and payload. We need to take both the header and
+ payload paths back together into a single stream. In packet_tx.grc,
+ we are working with tagged streams, so both paths keep track of the
+ size of their segments. Using the Tagged Stream Mux block, we
+ recombine these two paths into one.
+
+- Burst Shaping and Filtering. The next stage shapes the packet for
+ burst transmission. We apply two blocks to shape the burst
+ appropriately.
+
+ First, the \ref gr::digital::burst_shaper_cc "Burst Shaping block"
+ handles the structure of the burst by applying two different forms
+ of padding. First, there is a window that is applied to the time
+ domain of the burst. This involves a ramping up stage from 0 and a
+ ramping down stage back to 0. We define a window as a vector, and
+ the \ref gr::fft::window "fft.window" set of window functions is
+ useful here, such as using a Hann or Kaiser window. The size of the
+ window is split in half to apply the left half of the window for the
+ ramp-up and the right half of the window for the ramp-down. The
+ window has two different modes: to insert or not insert phasing
+ symbols. When inserting phasing symbols, a sequence of 1's and -1's
+ is inserted for the duration of the ramp-up and ramp-down
+ periods. So a window size of 20 will produce 10 alternative 1's and
+ -1's on the front of the burst and another 10 alternating symbols on
+ the rear of the burst. The window is then applied to these phasing
+ symbols and does not affect the burst symbols directly. If we are
+ not using the phasing symbols, the the window is applied to the
+ front and back of the burst directly.
+
+ The Burst Shaper can also add padded 0's to the front or back of the
+ burst. This allows us to provide some extra control over the
+ structure of the burst. In particular, it can be useful to add
+ post-padding 0's that is the length of the delay of the pulse
+ shaping filter that will come next. This makes sure that the full
+ burst of samples is pushed through the filter and transmitted
+ completely.
+
+
+\verbatim
+ ____________________
+ / \
+ / \
+ / \
+ ______/ \____
+ | E | D | C | B | A |
+
+ A: Pre-padding 0's
+ B: Ramp-up window
+ C: Frame
+ D: Ramp-down window
+ E: Post-padding 0's
+\endverbatim
+
+
+ When using phasing symbols, C is the entire frame and sections B
+ and D are filled with alternative 1's and -1's.
+
+ When not using phase symbols, the frame extends B through C to D.
+
+ After creating this burst shape, we then put the burst through a
+ pulse shaping filter. This filter both shapes the complex samples
+ into appropriate symbols for transmission based on a spectral mask
+ as well as up-samples the burst to the specified number of samples
+ per symbol. In packet_tx, we are using a Polyphase Arbitrary
+ Resampler to perform this task for us, which means that we can
+ specify and real value for the number of samples/symbol, as long as
+ it is greater than or equal to 2.0.
+
+ Typical pulse shape filters are \ref
+ gr::filter::firdes::root_raised_cosine "Root Raised Cosine (RRC)"
+ filters and \ref gr::filter::firdes::gaussian "Gaussian" filters.
+
+ Because the pulse shape filter up-samples, in packet_tx, we use a
+ \ref gr::blocks::tagged_stream_multiply_length "Tagged Stream Multiply
Length Tag block".
+ The resampler block knows nothing about
+ tagged streams, so when it up-samples, the \ref
+ page_tagged_stream_blocks "tagged stream block (TSB)" tag value does
+ not change. We need to change this tag's value, too, and so we use
+ the multiply length tag block for this purpose. This is helpful when
+ working with UHD devices, like in uhd_packet_tx.grc, because we can
+ explicitly tell the UHD USRP Sink block to expect a tagged stream to
+ manage the transmission of the burst.
+
+\subsection packet_tx_params Parameters of the packet_tx Example
+
+The canonical example for handling narrowband M-PSK or M-QAM is the
+packet_tx.grc hierarchical block.
+
+- Header FEC Code (hdr_enc)
+- Payload FEC Code (pld_enc)
+- Header Constellation Object (hdr_const)
+- Payload Constellation Object (pld_const)
+- Protocol Formatter Object (formatter)
+- Samples per symbol (sps as a float)
+- Pulse shaping filter (psf_taps, designed for the polyphase arbitrary
+ resampler)
+
+We can see all of these objects and settings in the
+packet_loopback_hier.grc example and uhd_packet_tx.grc if using a
+UHD-compatibly radio front end.
+
+\subsection packet_tx_examples Examples
+
+The following examples exist to showcase how to control each stage of
+the transmit processing.
+
+- tx_stage0.grc: simple creation of PDUs to input into the
+ transmitter. By default, this generates \ref gr::blocks::random_pdu
+ "random PDUs" for testing. However, we can switch in the \ref
+ gr::blocks::tuntap_pdu "TUNTAP PDU" block to create a tun or tap
+ device as the input of samples from some OS application. Note that
+ you will need root privileges to create a tun/tap device and
+ configure it.
+
+
+- tx_stage1.grc: Adding a CRC to the frame. The Message Debug prints
+ the before and after adding the \ref gr::digital::crc32_async_bb
+ "CRC32", so we can see the original PDU and then the PDU with the
+ added 4 bytes of check.
+
+
+- tx_stage2.grc: Adding \ref page_fec "forward error correction". This
+ adds an \ref gr::fec::async_encoder "FEC Async Encoder" block to
+ compare pre- and post-encoding. Three different FEC encoders are
+ available immediately in this example with the repetition encoder
+ enabled by default. This encoder just repeats every bit 3 times, so
+ it is easy to see the behavior before and after encoding. Simply
+ disable this FEC code and enabling one of the others will change the
+ encoding behavior.
+
+
+- tx_stage3.grc: takes the payload with the CRC32 check and creates
+ the packet structure. Both the header and payload are printed out,
+ where the payload is the input payload+CRC and the header is defined
+ by the 'formatter' object. The default formatter just applies an
+ access code (using the default 64-bit
+ digital.packet_utils.default_access_code code) and then it
+ calculates the payload length (in bytes) as a 16-bit value. This
+ 16-bit length field is duplicated, so in the receiver it can check
+ both 16-bit fields to make sure they agree. This formatter also
+ takes a threshold value. The transmitter does not use this
+ threshold. That parameter is used in the receiver to know how many
+ bits can be wrong in the access code and still pass.
+
+ Disabling the \ref gr::digital::header_format_default
+ "default header definition" and enabling the other 'formatter' to
+ change the protocol. This other protocol definition is the \ref
+ gr::digital::header_format_counter "counter header". It adds the
+ access code and payload length fields as the header like the default
+ formatter. This formatter includes two other fields as well: the
+ number of bits/symbol used in the payload modulator (as a 16-bit
+ field) and a 16-bit counter. Each packet transmitted increments this
+ counter by 1, which means we can keep track of how many packets we
+ have sent and/or received.
+
+- tx_stage4.grc: Here we add the modulation to both the header and
+ payload paths, defined by the hdr_const and pld_const objects,
+ respectively. Both are defined as BPSK constellations by
+ default. The output is shown in two \ref page_qtgui "QTGUI display"
+ graphs. We see the samples in time first, and this is triggering off
+ the TSB tag "packet_len". When the time display updates, we can see
+ the same pattern right after the tag, which is the header, and then
+ the changing samples are the random values in the payload.
+
+ When we look at this Freq tab of this example, we just see a mostly
+ flat frequency response over the entire frequency range. This
+ response is due to the samples just being +1's and -1's with no
+ transition between them and sampled at 1 sampler per symbol. This is
+ not something that we can just transmit as a burst. The square
+ pulses we use provide horrible out-of-band (OOB) emissions if we put
+ this over the air directly, and each burst would go from 0 to +/-1
+ within the coarse of a single sample, which again provides large OOB
+ emissions. We need to shape the bursts properly from here.
+
+- tx_stage5.grc: Adds the \ref gr::digital::burst_shaper_cc "Burst Shaper"
+ block. The default parameters are to use a Hann window of 50 symbols
+ and to add 10 0's as pre- and post-padding. We can adjust any of
+ these values to explore what the output burst looks like. We can
+ stop the time sink from updating and turn on the markers for the
+ Re{Data 0} channel to easily count the samples and observe the
+ effect of the window.
+
+ As an aside, the window of 50 produces 25 phasing samples on either
+ side. This is a lot, but we did this to help show off the way the
+ window looks a bit more clearly.
+
+- tx_stage6.grc: We then need to up-sample the signal by the number of
+ samples/symbol (sps) and apply our pulse-shaping filter. Again, we
+ are using some larger numbers than we really would in an actual
+ scenario to make it visually clear what is happening. The psf_taps
+ filter creates an RRC filter designed for the 32-arm (set by nfilts)
+ polyphase filterbank resampler. In this RRC Filter Taps object, we
+ set the number of taps to be 15*sps*nfilts. The sps and nfilts are
+ properties of the sample stream and upsampling factor. The value 15
+ is the number of symbols to represent in this filter; basically that
+ we are going to look over the history effects of 15 samples to
+ manage the inter-symbol interference (ISI). That is a long RRC filter
+ but done so to make the simulation look better. Five or seven is a
+ more realistic value. Similarly, we set sps=4 here to make the time
+ and frequency plots look better. Normally, we would want this closer
+ to 2.
+
+ Now looking at the time domain plot, we see the filtered samples,
+ which are not as pretty as before. They have over- and under-shoots,
+ and if we turned on the line markers, we would not see the original
+ bits easily through this. That is the effect of the RRC filter,
+ which introduces ISI into the transmitted stream. However, when we
+ look at the frequency domain, we see a much better shape, which we
+ can transmit as part of our channel assignment.
+
+- tx_stage6a.grc: An aside here to study the RRC filters more. This
+ example adds a second RRC filter (without any resampling) that
+ matches the transmitter's RRC filter. The matched filter means that
+ the samples are filtered by two RRC filters, which together make a
+ raised cosine (RC) filter. This RC filter is what is known as a
+ Nyquist filter and has the properties of 0 (or very close to 0)
+ ISI. Though we introduced ISI in the transmit RRC filter, the second
+ stage at the receiver undoes that ISI making for a clean, filtered
+ signal. Turning on marker in the time domain shows two clean lines
+ at +1 and -1. The receiver just needs to know which of the sps
+ samples to grad to get the original symbol that was transmitted. But
+ that is the job of the receiver.
+
+At this point, we have an encoded, modulated, and shaped burst ready
+to be transmitted out of a radio. The uhd_packet_tx.grc example puts
+all this together, where we have packaged up most of the transmitter
+behavior into packet_tx.grc. We then generate random PDU's, put them
+through the packet_tx block, and then through a Multiply Const block
+and into a USRP sink. The Multiply Const block is used for digital
+scaling of the signal to allow us power control on top of the
+transmitter gain inside the USRP radio itself.
+
+
+\section packet_rx Understanding the Receiver
+
+The receiver is far more complicated. The work involved here is
+largely in the detection and synchronization of the received
+frames. We must assume that frames are coming in as bursts with
+potentially random time intervals.
+
+It is important to understand that it is very difficult to make a
+simple protocol work in all scenarios. We have to assume that some
+packets will be lost through either a missed detection at the start or
+poor synchronization statistics during processing of the burst.
+
+The generic receiver example can be found in packet_rx.grc. This hier
+block provides the main detection, synchronization, header/payload
+management, demodulation, and decoding of the PHY frames. The input to
+this hier block should be not be too far off in frequency. The GNU
+Radio block \ref gr::digital::fll_band_edge_cc "FLL Band-Edge" tends
+to work well enough, though this is unnecessary if the radio are
+synchronized in frequency some other way (e.g., with a GPSDO such as
+is available on USRPs).
+
+The main flow of samples here is to detect a frame by discovering its
+known word, which also provides initial estimates on timing and phase
+offsets of the received frame. We then go through a clock sync block
+to perform matched filtering and sample time correction to produce
+resampled symbols at 1 sample/symbol. Now we have samples that are
+split between the header and payload. We might have information inside
+of the header that helps the receiver understand the payload. For
+instance, the length of the payload is generally encoded in the
+header. So we have to demux the header and payload.
+
+We assume that we know the length of the header in symbols, which we
+pass on to the header demodulator chain. Knowing the header
+modulation, we synchronize the phase and frequency, demodulate the
+symbols into soft bits, decode those soft bits based on the known
+header's FEC code, and then parse the header information. The header
+parser extracts information about the payload, such as the number of
+symbols in the payload and possibly the number of bits/symbol used in
+the payload modulation.
+
+The \ref gr::digital::header_payload_demux "Header/Payload Demux"
+block sends the appropriate number of samples to the payload demod
+chain. This chain does its own phase/freq synchronization for the
+appropriate constellation used in the payload, decodes the samples to
+soft bits, performs the FEC decoding, and then does the CRC32
+check. If this passes, the payload is sent out of the hier block as a
+PDU with the PHY layer framing stripped.
+
+When looking at the packet_rx.grc example, notice that we have
+instrumented a number of debug ports along the way. These ports are
+designed to make it possible for us to externally hook up graphing and
+debug blocks in whatever way we are comfortable with to see the signal
+along the path and more easily debug.
+
+
+\subsection packet_rx_correst Correlation Estimator
+
+The first stage of the receiver searches for the known word prepended
+to every burst from the transmitter. The known word has gone through
+two stages of processing: encoding with the header's FEC (optional)
+and modulated by the header's modulator. The correlation of the known
+word is done at the input sample stage, so we have to recreate the
+modulated and possible encoded known word at the receiver.
+
+To simplify dealing with the encoding process, in packet_rx.grc, we
+assume one of two types of codes: dummy code (or not coded) and a 3x
+repetition code. We then just simply calculated the preamble's bits
+for both cases. Depending on the header decoder (hdr_dec) used, the
+hier block knows which preamble to use.
+
+Next, we need to take the known, encoded word and modulate it with the
+header's modulator and pulse shaping filter. We create a simple
+modulator in the variable 'rxmod' that takes the header \ref
+gr::digital::constellation "constellation object" (hdr_const), the
+number of samples per symbol, and the pulse shape filter's bandwidth
+parameter (eb). The \ref gr::digital::modulate_vector_bc "Modulate Vector"
+block than combines this 'rxmod' modulator with the 'preamble'
+known word into a vector of complex symbols, here called
+'modulated_sync_word'. This variable is then passed to the \ref
+gr::digital::corr_est_cc "Correlation Estimator" block.
+
+One tricky thing about burst communications and network setups is the
+power of the received samples is unknown and time varying. It is
+preferential to try to auto-detect the burst and scale the signal to
++/-1 before coming in to packet_rx. There is still a lot of work to be
+done for AGC loops in the hardware and automatic scaling in
+software. The Correlation Estimator tries to deal with this. We use a
+threshold as an approximate probability of detection. This value
+should be set very high; the default here is 99.9%. The correlation
+tends to scale well as the amplitudes change and for relatively low
+SNR conditions. Still, it is always possible to miss a detection event
+or have a false positive.
+
+Another thing that the Correlation Estimator can do for us is provide
+information for digital scaling the samples. When received over
+hardware, the signals tend to be very small, but most of our follow-on
+processing assumes they are about +/-1. The Correlation Estimator
+finds the amplitude of the sample where the correlation peak was
+found, inverts it, and sends it as a tag with the key 'amp_est'. We
+can use this down stream to adjust the amplitude by rescaling the
+samples from this value. For our packet_rx example, we use the \ref
+gr::blocks::multiply_by_tag_value_cc "Multiply by Tag Value" block,
+which updates its multiplicitive factor based on the tag. Much of this
+could be handled by a good AGC routine in the hardware.
+
+Finally, the main purpose of the Correlation Estimator block is to
+provide the down-stream synchronization blocks with initial estimates
+of the timing and phase offset. The peak of the magnitude of the
+correlation event corresponds to the sampling timing of the data
+stream.
+
+\verbatim
+ 1. /\ 2. _
+ / \ / \
+ __/ \__ __/ \__
+\endverbatim
+
+The above two drawings show two different correlation scenarios. In
+scenario 1, the timing is exact and the sample at the peak of that
+curve is the proper sample time of the last symbol of the known
+word. In scenario 2, there is a timing offset where the correct timing
+offset is half-way between two samples. This would be a timing offset
+of 0.5 (or -0.5). Knowing where that estimated offset is helps our
+timing recover blocks start near the correct sample offset and then
+track from there.
+
+The magnitude of the correlation helps us discover the timing
+offset. The correlation itself is a complex vector. So where the peak
+of the magnitude happens, we can look to the complex value of the
+correlation at the same point and the phase difference between the
+real and imaginary parts is the phase offset of the signal.
+
+The Correlation Estimator block calculates the time and phase offsets
+and creates stream tags for "time_est" and "phase_est". It also
+creates two other tags: "corr_start" and "corr_est," both of which
+contain the value of the peak of the magnitude of the
+correlation. Because there is a delay in the correlation algorithm
+that is affected by the size of the correlation, we need to adjust
+where the correlation event occurs to where the tags are actually
+placed on the output stream. The block places the "corr_start" tag on
+the sample where the correlation actually occurred. It then places the
+other three tags offset by some "Tag marking delay," which is a
+user-calculated value to place the tags at the correct spot in the
+data stream for the actual start of the known word's first symbol.
+
+In packet_rx, we empirically discovered the tag marking delay for
+different values of the samples/symbol ('sps') variable and made a
+list 'mark_delays' that is index by 'sps' to properly set 'mark_delay'
+for the start of the known word. Getting is correct has a huge effect
+on the timing recover loop, which can take a while to converge if it
+starts offset in time by a sample.
+
+See the example example_corr_est.grc to explore the Correlation
+Estimator blocks more.
+
+
+\subsection packet_rx_timing Timing Recovery
+
+After detecting the frame and estimating the time and phase estimates,
+we have to actually perform the timing synchronization step. The
+packet_rx example uses the
+\ref gr::digital::pfb_clock_sync_ccf "Polyphase Clock Sync" block to
+do this. This PFB clock sync (PCS) block typically performs blind
+timing recovery on a series of samples. It is composed of 'nfilt'
+filters in a filterbank where each filter represents a different phase
+from [0, 2pi) in steps of 2pi/nfilts. The algorithm finds the correct
+arm of the filterbank that corresponds to the time shift of the
+samples. It also knows to look for a "time_est" stream tag and use
+that information to set its phase arm estimate. If we have a time
+estimate like scenario 1 above, we have perfect timing and so would
+select the 0th arm of the filterbank. In scenario 2, we are off by
+half a sample, so we select arm nfilts/2. The PCS is a tracking loop,
+so it will start with the initial estimate and then keep track of the
+timing as well as hone-in on actual timing information of the symbol
+stream.
+
+The PCS block uses a filterbank concept to perform its tracking
+operation. The filters within the filterbank operate best when they
+are phase offsets of the matched filter. So not only does the
+block recover the timing, it also performs the matched filtering and
+produces the optimal 1 sample/symbol output. These are then optimally
+sampled symbols in the complex constellation space. They need to be
+mapped back to bits and decoded. But first, we need to parse the
+header in order to discover information about the payload.
+
+See the example example_corr_est_and_clock_sync.grc to play with the
+parameters of time synchronization.
+
+
+\subsection packet_rx_hpd Header/Payload Demux
+
+Because the header and payload can be modulated differently, the rest
+of the symbol processing has to be split into two chains. We do this
+using the \ref gr::digital::header_payload_demux "Header/Payload Demux"
+block (HPD). We assume that we know the protocol, and so the format,
+coding, and modulation of the header. Generally speaking, these are
+all controlled through three different objects:
+
+- formatter: An object that described the header structure, derived
+ from gr::digital::header_format_base.
+
+- hdr_const: An object that describes the bit and symbol mapping,
+ derived from gr::digital::constellation.
+
+- hdr_dec: An object that describes the FEC code, derived from
+ gr::fec::generic_decoder.
+
+Through these, we can ask for any parameter to set up the following
+stages of processing.
+
+The HPD block is fairly complicated and we will only use it in one
+kind of configuration here. See the manual page for the \ref
+gr::digital::header_payload_demux "HPD" block itself for more
+details. In our use of the HPD block, it receives the data stream and
+looks for a Trigger Tag Key. We will use 'time_est', one of the tags
+produced by the Correlation Estimator to indicate the sample that
+starts the header. When the HPD block sees this trigger key, it passes
+along a known number of symbols out of the 'header' stream port. We
+know the number of symbols based on the formatter, constellation, and
+FEC decoder objects. The formatter objects knows the number of bits in
+the header via the header_nbits() function, the constellation knows
+how many bits per symbol (via bits_per_symbol()), and the FEC decoder
+knows the encoding rate (via 1/rate()). The number of symbols in the
+header is therefore:
+
+ (header_nbits() * 1/rate()) / bits_per_symbol()
+
+The HPD then sends this many symbols on to be processed. It holds up
+any more processing until triggered to do so with information through
+the 'header_data' input message port. The header processing chain will
+end with the Packet Parser producing the message here.
+
+When the 'header_data' input message port receives valid information,
+it releases the payload out of the 'payload' stream port. The main
+thing that the 'header_data' input message port receives is
+information about the length of the payload. The HPD parameter 'Length
+tag key' is matched to the message received in 'header_data', which is
+then used to gate the output of samples as the payload. In our case,
+we specify the length as the number of symbols through the message key
+'payload symbols'. This tag then becomes the tagged stream key for the
+payload chain.
+
+
+\subsection packet_rx_hdr_chain Header Processing Chain
+
+The header processing chain is kicked off when the HPD block receives
+the trigger stream tag (i.e., 'time_est'). We must first correct the
+phase and fine frequency offset of the received samples. The
+Correlation Estimator block will help us with this through the
+'phase_est' tag. The \ref gr::digital::costas_loop_cc "Costas Loop"
+looks for this tag, and, when found, it will take this estimate and
+reset its own internal phase value, which greatly speed up
+acquisition. The Costas loop will then track the phase and frequency
+over the course of the header.
+
+With the constellation locked in time, phase, and frequency, we can
+not decode the complex symbols. We use a \ref
+gr::digital::constellation_soft_decoder_cf "Constellation Soft Decoder"
+block for this, which uses the 'hdr_const' object to know the mappings
+from complex space to bits. Specifically, it performs a soft decoding,
+so the outputs are soft decision bits, which is useful for FEC
+decoding that is performed next.
+
+The \ref gr::fec::decoder "FEC decoder" operates on the soft decisions
+based on the hdr_dec object. Because of the bounded nature of the
+header, we would expect simple block codes used here as well as a
+fairly robust and easy to process code. In the current examples, we
+only provide no code (via the \ref gr::fec::code::dummy_encoder
+"Dummy Encoder" / \ref gr::fec::code::dummy_decoder "Dummy Decoder"
+classes) or a repetition code (via the
+\ref gr::fec::code::repetition_encoder "Repetition Encoder" / \ref
+gr::fec::code::repetition_decoder "Repetition Decoder" classes). The
+output of the FEC decoder block is a bit stream where each item is
+either a 1 or a 0.
+
+The last step in the header processing stage is to parse that bit
+stream back into the header. The \ref gr::digital::protocol_parser_b
+"Packet Parser" block does this by receiving a bit stream, passing it
+to the \ref gr::digital::header_format_base::parse "parse" function of
+the packet formatter object, and emitting a message with the
+information about the parsed data.
+
+The packet parsing is explained in detail in the \ref
+gr::digital::header_format_base "Packet Formatter Base" class. The
+parse function packs together the received bits into the different
+header fields, checks that the header is correct, and the constructs a
+PMT dictionary of the header information, such as the payload length
+and other possible information like the type of constellation or FEC
+coding used on the payload bits. This is the message that gets passed
+back to the HPD block to guide the payload processing.
+
+If the packet formatter parsing operation fails by not getting enough
+data or if the data is corrupted, it will return false. When the
+Packet Parser sees this, it emits a message that just contains a \ref
+page_pmt "PMT" False (pmt::PMT_F), which resets the HPD block to start
+looking for another header trigger event.
+
+If the header parsing completes successfully, the HPD block gets a
+message with information about the payload. Most importantly, it gets
+information about how many symbols make up the payload. It then sends
+a tagged stream to the payload processing chain with this many
+symbols.
+
+
+\subsection packet_rx_pld_chain Payload Processing Chain
+
+The payload processing chain behaves very similarly to the header
+processing chain for the first few blocks. It starts by locking the
+phase and frequency in another \ref gr::digital::costas_loop_cc
+"Costas loop", and then perform \ref
+gr::digital::constellation_soft_decoder_cf "soft decoding" on the
+symbols using the 'pld_const' object. Because we come in as symbols
+and out as soft decisions, the constellation soft decoder will produce
+\ref gr::digital::constellation::bits_per_symbol() "bits_per_symbol()"
+times as many outputs as inputs, but the soft decoder will not change
+the tag stream information. To compensate for this, we use a \ref
+gr::blocks::tagged_stream_multiply_length
+"Tagged Stream Multiply Length" block to update the tagged stream tag
+"payload symbols". We then move from the tagged stream mode into PDU
+mode and perform the FEC decoding through the \ref
+gr::fec::async_decoder "asynchronous FEC decoder". This decoder is
+nice in that it comes in with soft bits and produces packed
+bytes. These packed bytes are now the full payload with the CRC32
+appended. The \ref gr::digital::crc32_async_bb "Async CRC32" block in
+"Check CRC" mode will take this PDU of packed bytes, calculate the CRC
+and check it against the final four bytes of the payload. If they
+match, the PDU is stripped of the CRC bytes and the frame is passed
+out of the hier block. This PDU frame is now ready for use in higher
+layers of processing.
+
+This takes us through the entire processing chain on the
+receiver. From here, it is a matter of tweaking parameters and playing
+with options and other setups to improve behavior.
+
+*/
diff --git a/gr-digital/examples/CMakeLists.txt
b/gr-digital/examples/CMakeLists.txt
index 38ee443..abf97ac 100644
--- a/gr-digital/examples/CMakeLists.txt
+++ b/gr-digital/examples/CMakeLists.txt
@@ -95,3 +95,11 @@ install(
DESTINATION ${GR_PKG_DIGITAL_EXAMPLES_DIR}/demod
COMPONENT "digital_python"
)
+
+
+# PACKET
+install(
+ FILES
+ DESTINATION ${GR_PKG_DIGITAL_EXAMPLES_DIR}/packet
+ COMPONENT "digital_python"
+)
diff --git a/gr-digital/examples/ofdm/tx_ofdm.grc
b/gr-digital/examples/ofdm/tx_ofdm.grc
index 368f16b..3c8aca2 100644
--- a/gr-digital/examples/ofdm/tx_ofdm.grc
+++ b/gr-digital/examples/ofdm/tx_ofdm.grc
@@ -1,160 +1,151 @@
-<?xml version='1.0' encoding='ASCII'?>
+<?xml version='1.0' encoding='utf-8'?>
+<?grc format='1' created='3.7.10'?>
<flow_graph>
<timestamp>Wed Jul 9 15:49:47 2014</timestamp>
<block>
- <key>variable</key>
+ <key>options</key>
<param>
- <key>id</key>
- <value>sync_word2</value>
+ <key>author</key>
+ <value></value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>window_size</key>
+ <value>1280, 1024</value>
</param>
<param>
- <key>value</key>
- <value>[0, 0, 0, 0, 0, 0, -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, 0, 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, 0, 0, 0, 0, 0]
</value>
+ <key>category</key>
+ <value>Custom</value>
</param>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>description</key>
+ <value>Example of an OFDM Transmitter</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(496, 128)</value>
+ <value>(1, 0)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>variable</key>
<param>
- <key>id</key>
- <value>length_tag_key</value>
+ <key>generate_options</key>
+ <value>qt_gui</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>hier_block_src_path</key>
+ <value>.:</value>
</param>
<param>
- <key>value</key>
- <value>"packet_len"</value>
+ <key>id</key>
+ <value>tx_ofdm</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>max_nouts</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(352, 0)</value>
+ <key>qt_qss_theme</key>
+ <value></value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>realtime_scheduling</key>
+ <value></value>
</param>
- </block>
- <block>
- <key>variable</key>
<param>
- <key>id</key>
- <value>samp_rate</value>
+ <key>run_command</key>
+ <value>{python} -u {filename}</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>run_options</key>
+ <value>run</value>
</param>
<param>
- <key>value</key>
- <value>100000</value>
+ <key>run</key>
+ <value>True</value>
</param>
<param>
- <key>alias</key>
+ <key>thread_safe_setters</key>
<value></value>
</param>
<param>
- <key>_coordinate</key>
- <value>(255, 0)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
+ <key>title</key>
+ <value>OFDM Tx</value>
</param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>rolloff</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>0</value>
+ <key>_coordinate</key>
+ <value>(181, -1)</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(898, -1)</value>
+ <key>id</key>
+ <value>fft_len</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>value</key>
+ <value>64</value>
</param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>payload_mod</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
- <value>True</value>
+ <value>1</value>
</param>
<param>
- <key>value</key>
- <value>digital.constellation_qpsk()</value>
+ <key>_coordinate</key>
+ <value>(720, 69)</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(734, 0)</value>
+ <key>id</key>
+ <value>hdr_format</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>value</key>
+ <value>digital.header_format_ofdm(occupied_carriers, 1,
length_tag_key,)</value>
</param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>header_mod</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>digital.constellation_bpsk()</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
<key>_coordinate</key>
<value>(567, 0)</value>
</param>
@@ -162,479 +153,462 @@
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>id</key>
+ <value>header_mod</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>digital.constellation_bpsk()</value>
+ </param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>packet_len</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>96</value>
+ <key>_coordinate</key>
+ <value>(352, 0)</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(476, 0)</value>
+ <key>id</key>
+ <value>length_tag_key</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>value</key>
+ <value>"packet_len"</value>
</param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>fft_len</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>64</value>
+ <key>_coordinate</key>
+ <value>(320, 69)</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(181, -1)</value>
+ <key>id</key>
+ <value>occupied_carriers</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>value</key>
+ <value>(range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) +
range(8, 21) + range(22, 27),)</value>
</param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>header_formatter</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>digital.packet_header_ofdm(occupied_carriers, 1,
length_tag_key)</value>
+ <key>_coordinate</key>
+ <value>(476, 0)</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(708, 64)</value>
+ <key>id</key>
+ <value>packet_len</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>value</key>
+ <value>96</value>
</param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>pilot_carriers</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>((-21, -7, 7, 21,),)</value>
+ <key>_coordinate</key>
+ <value>(734, 0)</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(480, 64)</value>
+ <key>id</key>
+ <value>payload_mod</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>value</key>
+ <value>digital.constellation_qpsk()</value>
</param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>occupied_carriers</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>(range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) +
range(8, 21) + range(22, 27),)</value>
+ <key>_coordinate</key>
+ <value>(480, 69)</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(329, 64)</value>
+ <key>id</key>
+ <value>pilot_carriers</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>value</key>
+ <value>((-21, -7, 7, 21,),)</value>
</param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>pilot_symbols</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>((1, 1, 1, -1,),)</value>
+ <key>_coordinate</key>
+ <value>(608, 69)</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(601, 64)</value>
+ <key>id</key>
+ <value>pilot_symbols</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>value</key>
+ <value>((1, 1, 1, -1,),)</value>
</param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>sync_word1</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
- <value>True</value>
+ <value>1</value>
</param>
<param>
- <key>value</key>
- <value>[0., 0., 0., 0., 0., 0., 0., 1.41421356, 0., -1.41421356, 0.,
1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., 1.41421356,
0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., -1.41421356, 0.,
-1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356,
0., 1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0.,
1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356,
0., 1.41421356, 0., 0., 0., 0., 0., 0.]</value>
+ <key>_coordinate</key>
+ <value>(898, -1)</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(352, 128)</value>
+ <key>id</key>
+ <value>rolloff</value>
</param>
<param>
- <key>_rotation</key>
+ <key>value</key>
<value>0</value>
</param>
</block>
<block>
- <key>virtual_source</key>
+ <key>variable</key>
<param>
- <key>id</key>
- <value>virtual_source_0_0</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>stream_id</key>
- <value>Payload Bits</value>
- </param>
- <param>
<key>_coordinate</key>
- <value>(0, 458)</value>
+ <value>(255, 0)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>import</key>
<param>
<key>id</key>
- <value>import_0</value>
+ <value>samp_rate</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>value</key>
+ <value>100000</value>
</param>
+ </block>
+ <block>
+ <key>variable</key>
<param>
- <key>import</key>
- <value>import numpy</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(237, 93)</value>
+ <value>(8, 93)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>import</key>
<param>
<key>id</key>
- <value>import_1</value>
+ <value>sync_word1</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>value</key>
+ <value>[0., 0., 0., 0., 0., 0., 0., 1.41421356, 0., -1.41421356, 0.,
1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., 1.41421356,
0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., -1.41421356, 0.,
-1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356,
0., 1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0.,
1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356,
0., 1.41421356, 0., 0., 0., 0., 0., 0.]</value>
</param>
+ </block>
+ <block>
+ <key>variable</key>
<param>
- <key>import</key>
- <value>from gnuradio.digital.utils import tagged_streams</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(99, 93)</value>
+ <value>(152, 93)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>import</key>
<param>
<key>id</key>
- <value>import_0_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <value>sync_word2</value>
</param>
<param>
- <key>import</key>
- <value>import random</value>
+ <key>value</key>
+ <value>[0, 0, 0, 0, 0, 0, -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, 0, 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, 0, 0, 0, 0, 0]
</value>
</param>
+ </block>
+ <block>
+ <key>analog_random_source_x</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
- <key>_coordinate</key>
- <value>(3, 94)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
+ <key>comment</key>
+ <value></value>
</param>
- </block>
- <block>
- <key>virtual_source</key>
<param>
- <key>id</key>
- <value>virtual_source_0_0_0_0</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>stream_id</key>
- <value>Time Domain</value>
- </param>
- <param>
<key>_coordinate</key>
- <value>(1, 747)</value>
+ <value>(16, 167)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>virtual_sink</key>
<param>
<key>id</key>
- <value>virtual_sink_0_0_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <value>analog_random_source_x_0</value>
</param>
<param>
- <key>stream_id</key>
- <value>Pre-OFDM</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(745, 441)</value>
+ <key>max</key>
+ <value>255</value>
</param>
<param>
- <key>_rotation</key>
+ <key>minoutbuf</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>digital_chunks_to_symbols_xx</key>
<param>
- <key>id</key>
- <value>digital_chunks_to_symbols_xx_0_0</value>
+ <key>min</key>
+ <value>0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>num_samps</key>
+ <value>1000</value>
</param>
<param>
- <key>in_type</key>
+ <key>type</key>
<value>byte</value>
</param>
<param>
- <key>out_type</key>
- <value>complex</value>
- </param>
- <param>
- <key>symbol_table</key>
- <value>payload_mod.points()</value>
+ <key>repeat</key>
+ <value>True</value>
</param>
+ </block>
+ <block>
+ <key>blocks_multiply_const_vxx</key>
<param>
- <key>dimension</key>
- <value>1</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
- <key>num_ports</key>
- <value>1</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>const</key>
+ <value>0.05</value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
- </param>
- <param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(212, 450)</value>
+ <value>(208, 692)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>virtual_source</key>
<param>
<key>id</key>
- <value>virtual_source_0_0_0</value>
+ <value>blocks_multiply_const_vxx_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>stream_id</key>
- <value>Pre-OFDM</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(0, 578)</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
</block>
<block>
- <key>virtual_sink</key>
+ <key>blocks_repack_bits_bb</key>
<param>
- <key>id</key>
- <value>virtual_sink_0</value>
+ <key>k</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>l</key>
+ <value>payload_mod.bits_per_symbol()</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>stream_id</key>
- <value>Time Domain</value>
+ <key>endianness</key>
+ <value>gr.GR_LSB_FIRST</value>
</param>
<param>
<key>_coordinate</key>
- <value>(855, 578)</value>
+ <value>(664, 245)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>fft_vxx</key>
<param>
<key>id</key>
- <value>fft_vxx_0</value>
+ <value>blocks_repack_bits_bb_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>len_tag_key</key>
+ <value>length_tag_key</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>fft_size</key>
- <value>fft_len</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>forward</key>
+ <key>align_output</key>
<value>False</value>
</param>
+ </block>
+ <block>
+ <key>blocks_repack_bits_bb</key>
<param>
- <key>window</key>
- <value>()</value>
- </param>
- <param>
- <key>shift</key>
- <value>True</value>
+ <key>k</key>
+ <value>8</value>
</param>
<param>
- <key>nthreads</key>
+ <key>l</key>
<value>1</value>
</param>
<param>
@@ -642,300 +616,317 @@
<value></value>
</param>
<param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
<key>affinity</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>endianness</key>
+ <value>gr.GR_LSB_FIRST</value>
</param>
<param>
<key>_coordinate</key>
- <value>(414, 548)</value>
+ <value>(896, 157)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>blocks_multiply_const_vxx</key>
<param>
<key>id</key>
- <value>blocks_multiply_const_vxx_0</value>
+ <value>blocks_repack_bits_bb_0_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>len_tag_key</key>
+ <value>length_tag_key</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>const</key>
- <value>0.05</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>align_output</key>
+ <value>False</value>
</param>
+ </block>
+ <block>
+ <key>blocks_stream_to_tagged_stream</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
- <key>affinity</key>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(209, 747)</value>
+ <value>(192, 181)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>digital_chunks_to_symbols_xx</key>
<param>
<key>id</key>
- <value>digital_chunks_to_symbols_xx_0</value>
+ <value>blocks_stream_to_tagged_stream_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>len_tag_key</key>
+ <value>length_tag_key</value>
</param>
<param>
- <key>in_type</key>
- <value>byte</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>out_type</key>
- <value>complex</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>symbol_table</key>
- <value>header_mod.points()</value>
+ <key>packet_len</key>
+ <value>packet_len</value>
</param>
<param>
- <key>dimension</key>
- <value>1</value>
+ <key>type</key>
+ <value>byte</value>
</param>
<param>
- <key>num_ports</key>
+ <key>vlen</key>
<value>1</value>
</param>
+ </block>
+ <block>
+ <key>blocks_tag_debug</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
<key>affinity</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>display</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(214, 376)</value>
+ <value>(680, 822)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>analog_random_source_x</key>
<param>
<key>id</key>
- <value>analog_random_source_x_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <value>blocks_tag_debug_0</value>
</param>
<param>
<key>type</key>
<value>byte</value>
</param>
<param>
- <key>min</key>
- <value>0</value>
+ <key>filter</key>
+ <value>""</value>
</param>
<param>
- <key>max</key>
- <value>255</value>
+ <key>name</key>
+ <value>Rx'd Packets</value>
</param>
<param>
- <key>num_samps</key>
- <value>1000</value>
+ <key>num_inputs</key>
+ <value>1</value>
</param>
<param>
- <key>repeat</key>
- <value>True</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
+ </block>
+ <block>
+ <key>blocks_tag_gate</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
- <key>affinity</key>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(13, 220)</value>
+ <value>(376, 692)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>blocks_tagged_stream_mux</key>
<param>
<key>id</key>
- <value>blocks_tagged_stream_mux_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <value>blocks_tag_gate_0</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
- <key>ninputs</key>
- <value>2</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>lengthtagname</key>
- <value>length_tag_key</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>propagate_tags</key>
+ <value>False</value>
</param>
<param>
- <key>tag_preserve_head_pos</key>
- <value>0</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
+ </block>
+ <block>
+ <key>blocks_tagged_stream_mux</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
- <key>affinity</key>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(510, 428)</value>
+ <value>(512, 369)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>digital_ofdm_cyclic_prefixer</key>
<param>
<key>id</key>
- <value>digital_ofdm_cyclic_prefixer_0</value>
+ <value>blocks_tagged_stream_mux_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>input_size</key>
- <value>fft_len</value>
+ <key>lengthtagname</key>
+ <value>length_tag_key</value>
</param>
<param>
- <key>cp_len</key>
- <value>fft_len/4</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>rolloff</key>
- <value>rolloff</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>tagname</key>
- <value>length_tag_key</value>
+ <key>ninputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>tag_preserve_head_pos</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
</param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
- <key>affinity</key>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(632, 564)</value>
+ <value>(560, 692)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>blocks_tag_gate</key>
<param>
<key>id</key>
- <value>blocks_tag_gate_0</value>
+ <value>blocks_throttle_0</value>
</param>
<param>
- <key>_enabled</key>
+ <key>ignoretag</key>
<value>True</value>
</param>
<param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
<key>type</key>
<value>complex</value>
</param>
@@ -943,12 +934,19 @@
<key>vlen</key>
<value>1</value>
</param>
+ </block>
+ <block>
+ <key>channels_channel_model</key>
<param>
- <key>propagate_tags</key>
- <value>False</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
- <key>alias</key>
+ <key>block_tags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>comment</key>
<value></value>
</param>
<param>
@@ -956,292 +954,264 @@
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>epsilon</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>freq_offset</key>
+ <value>0.0</value>
</param>
<param>
<key>_coordinate</key>
- <value>(372, 747)</value>
+ <value>(192, 801)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>blocks_repack_bits_bb</key>
<param>
<key>id</key>
- <value>blocks_repack_bits_bb_0</value>
+ <value>channels_channel_model_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>k</key>
- <value>8</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>l</key>
- <value>payload_mod.bits_per_symbol()</value>
+ <key>noise_voltage</key>
+ <value>0.0</value>
</param>
<param>
- <key>len_tag_key</key>
- <value>length_tag_key</value>
+ <key>seed</key>
+ <value>0</value>
</param>
<param>
- <key>align_output</key>
- <value>False</value>
+ <key>taps</key>
+ <value>1.0 + 1.0j</value>
</param>
+ </block>
+ <block>
+ <key>digital_chunks_to_symbols_xx</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
<key>affinity</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>dimension</key>
+ <value>1</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(710, 301)</value>
+ <value>(216, 317)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>digital_packet_headergenerator_bb</key>
<param>
<key>id</key>
- <value>digital_packet_headergenerator_bb_0</value>
+ <value>digital_chunks_to_symbols_xx_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>in_type</key>
+ <value>byte</value>
</param>
<param>
- <key>header_formatter</key>
- <value>header_formatter.formatter()</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>len_tag_key</key>
- <value>"packet_len"</value>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>out_type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>symbol_table</key>
+ <value>header_mod.points()</value>
</param>
+ </block>
+ <block>
+ <key>digital_chunks_to_symbols_xx</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
<key>affinity</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>dimension</key>
+ <value>1</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(703, 242)</value>
+ <value>(216, 397)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>blocks_stream_to_tagged_stream</key>
<param>
<key>id</key>
- <value>blocks_stream_to_tagged_stream_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <value>digital_chunks_to_symbols_xx_0_0</value>
</param>
<param>
- <key>type</key>
+ <key>in_type</key>
<value>byte</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
- </param>
- <param>
- <key>packet_len</key>
- <value>packet_len</value>
- </param>
- <param>
- <key>len_tag_key</key>
- <value>length_tag_key</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>affinity</key>
- <value></value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>num_ports</key>
+ <value>1</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(193, 235)</value>
+ <key>out_type</key>
+ <value>complex</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>symbol_table</key>
+ <value>payload_mod.points()</value>
</param>
</block>
<block>
- <key>virtual_sink</key>
- <param>
- <key>id</key>
- <value>header_bits</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>stream_id</key>
- <value>Header Bits</value>
- </param>
+ <key>digital_crc32_bb</key>
<param>
- <key>_coordinate</key>
- <value>(936, 243)</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>comment</key>
+ <value></value>
</param>
- </block>
- <block>
- <key>virtual_sink</key>
<param>
- <key>id</key>
- <value>virtual_sink_0_0</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>stream_id</key>
- <value>Payload Bits</value>
- </param>
- <param>
<key>_coordinate</key>
- <value>(934, 324)</value>
+ <value>(432, 182)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>virtual_source</key>
<param>
<key>id</key>
- <value>virtual_source_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>stream_id</key>
- <value>Header Bits</value>
+ <value>digital_crc32_bb_0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(1, 382)</value>
+ <key>lengthtagname</key>
+ <value>length_tag_key</value>
</param>
<param>
- <key>_rotation</key>
+ <key>maxoutbuf</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>digital_crc32_bb</key>
- <param>
- <key>id</key>
- <value>digital_crc32_bb_0</value>
- </param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
<key>check</key>
<value>False</value>
</param>
<param>
- <key>lengthtagname</key>
- <value>length_tag_key</value>
+ <key>packed</key>
+ <value>True</value>
</param>
+ </block>
+ <block>
+ <key>digital_ofdm_carrier_allocator_cvc</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
<key>affinity</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>fft_len</key>
+ <value>fft_len</value>
</param>
<param>
<key>_coordinate</key>
- <value>(430, 235)</value>
+ <value>(192, 489)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>digital_ofdm_carrier_allocator_cvc</key>
<param>
<key>id</key>
<value>digital_ofdm_carrier_allocator_cvc_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>len_tag_key</key>
+ <value>length_tag_key</value>
</param>
<param>
- <key>fft_len</key>
- <value>fft_len</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
<key>occupied_carriers</key>
@@ -1259,12 +1229,19 @@
<key>sync_words</key>
<value>(sync_word1, sync_word2)</value>
</param>
+ </block>
+ <block>
+ <key>digital_ofdm_cyclic_prefixer</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
<param>
- <key>len_tag_key</key>
- <value>length_tag_key</value>
+ <key>cp_len</key>
+ <value>fft_len/4</value>
</param>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
@@ -1272,93 +1249,107 @@
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>input_size</key>
+ <value>fft_len</value>
</param>
<param>
<key>_coordinate</key>
- <value>(192, 540)</value>
+ <value>(632, 503)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>virtual_source</key>
<param>
<key>id</key>
- <value>virtual_source_1</value>
+ <value>digital_ofdm_cyclic_prefixer_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>tagname</key>
+ <value>length_tag_key</value>
</param>
<param>
- <key>stream_id</key>
- <value>Tx Signal</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(0, 894)</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>rolloff</key>
+ <value>rolloff</value>
</param>
</block>
<block>
- <key>virtual_sink</key>
+ <key>digital_ofdm_rx</key>
<param>
- <key>id</key>
- <value>virtual_sink_1</value>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>cp_len</key>
+ <value>fft_len/4</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>stream_id</key>
- <value>Tx Signal</value>
+ <key>fft_len</key>
+ <value>fft_len</value>
</param>
<param>
<key>_coordinate</key>
- <value>(990, 646)</value>
+ <value>(440, 766)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>digital_ofdm_rx</key>
+ <param>
+ <key>header_mod</key>
+ <value>"BPSK"</value>
+ </param>
<param>
<key>id</key>
<value>digital_ofdm_rx_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>log</key>
+ <value>False</value>
</param>
<param>
- <key>fft_len</key>
- <value>fft_len</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>cp_len</key>
- <value>fft_len/4</value>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>occupied_carriers</key>
+ <value>occupied_carriers</value>
</param>
<param>
<key>packet_len_key</key>
<value>"length"</value>
</param>
<param>
- <key>occupied_carriers</key>
- <value>occupied_carriers</value>
+ <key>payload_mod</key>
+ <value>"QPSK"</value>
</param>
<param>
<key>pilot_carriers</key>
@@ -1369,6 +1360,10 @@
<value>pilot_symbols</value>
</param>
<param>
+ <key>scramble_bits</key>
+ <value>False</value>
+ </param>
+ <param>
<key>sync_word1</key>
<value>sync_word1</value>
</param>
@@ -1376,83 +1371,62 @@
<key>sync_word2</key>
<value>sync_word2</value>
</param>
+ </block>
+ <block>
+ <key>digital_protocol_formatter_bb</key>
<param>
- <key>header_mod</key>
- <value>"BPSK"</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
- <key>payload_mod</key>
- <value>"QPSK"</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>scramble_bits</key>
- <value>False</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
- <key>log</key>
- <value>False</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>format</key>
+ <value>hdr_format</value>
</param>
<param>
- <key>affinity</key>
- <value></value>
- </param>
- <param>
- <key>minoutbuf</key>
- <value>0</value>
- </param>
- <param>
- <key>maxoutbuf</key>
- <value>0</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(439, 823)</value>
+ <key>_coordinate</key>
+ <value>(656, 157)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>channels_channel_model</key>
<param>
<key>id</key>
- <value>channels_channel_model_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>noise_voltage</key>
- <value>0.0</value>
- </param>
- <param>
- <key>freq_offset</key>
- <value>0.0</value>
+ <value>digital_protocol_formatter_bb_0</value>
</param>
<param>
- <key>epsilon</key>
- <value>1.0</value>
+ <key>len_tag_key</key>
+ <value>length_tag_key</value>
</param>
<param>
- <key>taps</key>
- <value>1.0 + 1.0j</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>seed</key>
+ <key>minoutbuf</key>
<value>0</value>
</param>
+ </block>
+ <block>
+ <key>fft_vxx</key>
<param>
- <key>block_tags</key>
- <value>True</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
@@ -1460,201 +1434,190 @@
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>fft_size</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>forward</key>
+ <value>False</value>
</param>
<param>
<key>_coordinate</key>
- <value>(193, 858)</value>
+ <value>(416, 496)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>blocks_tag_debug</key>
<param>
<key>id</key>
- <value>blocks_tag_debug_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <value>fft_vxx_0</value>
</param>
<param>
<key>type</key>
- <value>byte</value>
+ <value>complex</value>
</param>
<param>
- <key>name</key>
- <value>Rx'd Packets</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>filter</key>
- <value>""</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>num_inputs</key>
+ <key>nthreads</key>
<value>1</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>shift</key>
+ <value>True</value>
</param>
<param>
- <key>display</key>
- <value>True</value>
+ <key>window</key>
+ <value>()</value>
</param>
+ </block>
+ <block>
+ <key>virtual_sink</key>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>affinity</key>
- <value></value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(689, 889)</value>
+ <value>(1104, 164)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>blocks_throttle</key>
<param>
<key>id</key>
- <value>blocks_throttle_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <value>header_bits</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>stream_id</key>
+ <value>Header Bits</value>
</param>
+ </block>
+ <block>
+ <key>qtgui_freq_sink_x</key>
<param>
- <key>samples_per_second</key>
- <value>samp_rate</value>
+ <key>autoscale</key>
+ <value>True</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>average</key>
+ <value>1.0</value>
</param>
<param>
- <key>ignoretag</key>
+ <key>axislabels</key>
<value>True</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>bw</key>
+ <value>samp_rate</value>
</param>
<param>
- <key>affinity</key>
+ <key>alias</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
- </param>
- <param>
- <key>maxoutbuf</key>
+ <key>fc</key>
<value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(559, 747)</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>ctrlpanel</key>
+ <value>False</value>
</param>
- </block>
- <block>
- <key>qtgui_freq_sink_x</key>
<param>
- <key>id</key>
- <value>qtgui_freq_sink_x_0</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>fftsize</key>
+ <value>1024</value>
</param>
<param>
- <key>name</key>
- <value>FFT Plot</value>
+ <key>_coordinate</key>
+ <value>(960, 759)</value>
</param>
<param>
- <key>fftsize</key>
- <value>1024</value>
+ <key>gui_hint</key>
+ <value></value>
</param>
<param>
- <key>wintype</key>
- <value>firdes.WIN_BLACKMAN_hARRIS</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>fc</key>
- <value>0</value>
+ <key>grid</key>
+ <value>False</value>
</param>
<param>
- <key>bw</key>
- <value>samp_rate</value>
+ <key>id</key>
+ <value>qtgui_freq_sink_x_0</value>
</param>
<param>
- <key>autoscale</key>
+ <key>legend</key>
<value>True</value>
</param>
<param>
- <key>average</key>
+ <key>alpha1</key>
<value>1.0</value>
</param>
<param>
- <key>ymin</key>
- <value>-140</value>
+ <key>color1</key>
+ <value>"blue"</value>
</param>
<param>
- <key>ymax</key>
- <value>10</value>
+ <key>label1</key>
+ <value></value>
</param>
<param>
- <key>nconnections</key>
+ <key>width1</key>
<value>1</value>
</param>
<param>
- <key>update_time</key>
- <value>0.10</value>
+ <key>alpha10</key>
+ <value>1.0</value>
</param>
<param>
- <key>gui_hint</key>
- <value></value>
+ <key>color10</key>
+ <value>"dark blue"</value>
</param>
<param>
- <key>label1</key>
+ <key>label10</key>
<value></value>
</param>
<param>
- <key>width1</key>
+ <key>width10</key>
<value>1</value>
</param>
<param>
- <key>color1</key>
- <value>"blue"</value>
+ <key>alpha2</key>
+ <value>1.0</value>
</param>
<param>
- <key>alpha1</key>
- <value>1.0</value>
+ <key>color2</key>
+ <value>"red"</value>
</param>
<param>
<key>label2</key>
@@ -1665,12 +1628,12 @@
<value>1</value>
</param>
<param>
- <key>color2</key>
- <value>"red"</value>
+ <key>alpha3</key>
+ <value>1.0</value>
</param>
<param>
- <key>alpha2</key>
- <value>1.0</value>
+ <key>color3</key>
+ <value>"green"</value>
</param>
<param>
<key>label3</key>
@@ -1681,12 +1644,12 @@
<value>1</value>
</param>
<param>
- <key>color3</key>
- <value>"green"</value>
+ <key>alpha4</key>
+ <value>1.0</value>
</param>
<param>
- <key>alpha3</key>
- <value>1.0</value>
+ <key>color4</key>
+ <value>"black"</value>
</param>
<param>
<key>label4</key>
@@ -1697,12 +1660,12 @@
<value>1</value>
</param>
<param>
- <key>color4</key>
- <value>"black"</value>
+ <key>alpha5</key>
+ <value>1.0</value>
</param>
<param>
- <key>alpha4</key>
- <value>1.0</value>
+ <key>color5</key>
+ <value>"cyan"</value>
</param>
<param>
<key>label5</key>
@@ -1713,12 +1676,12 @@
<value>1</value>
</param>
<param>
- <key>color5</key>
- <value>"cyan"</value>
+ <key>alpha6</key>
+ <value>1.0</value>
</param>
<param>
- <key>alpha5</key>
- <value>1.0</value>
+ <key>color6</key>
+ <value>"magenta"</value>
</param>
<param>
<key>label6</key>
@@ -1729,12 +1692,12 @@
<value>1</value>
</param>
<param>
- <key>color6</key>
- <value>"magenta"</value>
+ <key>alpha7</key>
+ <value>1.0</value>
</param>
<param>
- <key>alpha6</key>
- <value>1.0</value>
+ <key>color7</key>
+ <value>"yellow"</value>
</param>
<param>
<key>label7</key>
@@ -1745,12 +1708,12 @@
<value>1</value>
</param>
<param>
- <key>color7</key>
- <value>"yellow"</value>
+ <key>alpha8</key>
+ <value>1.0</value>
</param>
<param>
- <key>alpha7</key>
- <value>1.0</value>
+ <key>color8</key>
+ <value>"dark red"</value>
</param>
<param>
<key>label8</key>
@@ -1761,12 +1724,12 @@
<value>1</value>
</param>
<param>
- <key>color8</key>
- <value>"dark red"</value>
+ <key>alpha9</key>
+ <value>1.0</value>
</param>
<param>
- <key>alpha8</key>
- <value>1.0</value>
+ <key>color9</key>
+ <value>"dark green"</value>
</param>
<param>
<key>label9</key>
@@ -1777,507 +1740,743 @@
<value>1</value>
</param>
<param>
- <key>color9</key>
- <value>"dark green"</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>alpha9</key>
- <value>1.0</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>label10</key>
- <value></value>
+ <key>name</key>
+ <value>FFT Plot</value>
</param>
<param>
- <key>width10</key>
+ <key>nconnections</key>
<value>1</value>
</param>
<param>
- <key>color10</key>
- <value>"dark blue"</value>
+ <key>showports</key>
+ <value>True</value>
</param>
<param>
- <key>alpha10</key>
- <value>1.0</value>
+ <key>freqhalf</key>
+ <value>True</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>tr_chan</key>
+ <value>0</value>
</param>
<param>
- <key>affinity</key>
- <value></value>
+ <key>tr_level</key>
+ <value>0.0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(966, 841)</value>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>tr_tag</key>
+ <value>""</value>
</param>
- </block>
- <block>
- <key>qtgui_time_sink_x</key>
<param>
- <key>id</key>
- <value>qtgui_time_sink_x_0</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>update_time</key>
+ <value>0.10</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>wintype</key>
+ <value>firdes.WIN_BLACKMAN_hARRIS</value>
</param>
<param>
- <key>name</key>
- <value>Scope Plot</value>
+ <key>label</key>
+ <value>Relative Gain</value>
</param>
<param>
- <key>size</key>
- <value>1024</value>
+ <key>ymax</key>
+ <value>10</value>
</param>
<param>
- <key>srate</key>
- <value>samp_rate</value>
+ <key>ymin</key>
+ <value>-140</value>
+ </param>
+ <param>
+ <key>units</key>
+ <value>dB</value>
</param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
<param>
<key>autoscale</key>
<value>True</value>
</param>
<param>
- <key>ymin</key>
- <value>-1</value>
+ <key>axislabels</key>
+ <value>True</value>
</param>
<param>
- <key>ymax</key>
- <value>1</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
- <key>nconnections</key>
- <value>1</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>update_time</key>
- <value>0.10</value>
+ <key>ctrlpanel</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
<key>entags</key>
<value>True</value>
</param>
<param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(960, 671)</value>
+ </param>
+ <param>
<key>gui_hint</key>
<value></value>
</param>
<param>
- <key>tr_mode</key>
- <value>qtgui.TRIG_MODE_FREE</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>tr_slope</key>
- <value>qtgui.TRIG_SLOPE_POS</value>
+ <key>grid</key>
+ <value>False</value>
</param>
<param>
- <key>tr_level</key>
- <value>0.0</value>
+ <key>id</key>
+ <value>qtgui_time_sink_x_0</value>
</param>
<param>
- <key>tr_delay</key>
- <value>0</value>
+ <key>legend</key>
+ <value>True</value>
</param>
<param>
- <key>tr_chan</key>
- <value>0</value>
+ <key>alpha1</key>
+ <value>1.0</value>
</param>
<param>
- <key>tr_tag</key>
- <value>""</value>
+ <key>color1</key>
+ <value>"blue"</value>
</param>
<param>
<key>label1</key>
<value>Scope Plot</value>
</param>
<param>
+ <key>marker1</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style1</key>
+ <value>1</value>
+ </param>
+ <param>
<key>width1</key>
<value>1</value>
</param>
<param>
- <key>color1</key>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color10</key>
<value>"blue"</value>
</param>
<param>
- <key>style1</key>
- <value>1</value>
+ <key>label10</key>
+ <value></value>
</param>
<param>
- <key>marker1</key>
+ <key>marker10</key>
<value>-1</value>
</param>
<param>
- <key>alpha1</key>
- <value>1.0</value>
+ <key>style10</key>
+ <value>1</value>
</param>
<param>
- <key>label2</key>
- <value></value>
+ <key>width10</key>
+ <value>1</value>
</param>
<param>
- <key>width2</key>
- <value>1</value>
+ <key>alpha2</key>
+ <value>1.0</value>
</param>
<param>
<key>color2</key>
<value>"red"</value>
</param>
<param>
- <key>style2</key>
- <value>1</value>
+ <key>label2</key>
+ <value></value>
</param>
<param>
<key>marker2</key>
<value>-1</value>
</param>
<param>
- <key>alpha2</key>
- <value>1.0</value>
+ <key>style2</key>
+ <value>1</value>
</param>
<param>
- <key>label3</key>
- <value></value>
+ <key>width2</key>
+ <value>1</value>
</param>
<param>
- <key>width3</key>
- <value>1</value>
+ <key>alpha3</key>
+ <value>1.0</value>
</param>
<param>
<key>color3</key>
<value>"green"</value>
</param>
<param>
- <key>style3</key>
- <value>1</value>
+ <key>label3</key>
+ <value></value>
</param>
<param>
<key>marker3</key>
<value>-1</value>
</param>
<param>
- <key>alpha3</key>
- <value>1.0</value>
+ <key>style3</key>
+ <value>1</value>
</param>
<param>
- <key>label4</key>
- <value></value>
+ <key>width3</key>
+ <value>1</value>
</param>
<param>
- <key>width4</key>
- <value>1</value>
+ <key>alpha4</key>
+ <value>1.0</value>
</param>
<param>
<key>color4</key>
<value>"black"</value>
</param>
<param>
- <key>style4</key>
- <value>1</value>
+ <key>label4</key>
+ <value></value>
</param>
<param>
<key>marker4</key>
<value>-1</value>
</param>
<param>
- <key>alpha4</key>
- <value>1.0</value>
+ <key>style4</key>
+ <value>1</value>
</param>
<param>
- <key>label5</key>
- <value></value>
+ <key>width4</key>
+ <value>1</value>
</param>
<param>
- <key>width5</key>
- <value>1</value>
+ <key>alpha5</key>
+ <value>1.0</value>
</param>
<param>
<key>color5</key>
<value>"cyan"</value>
</param>
<param>
- <key>style5</key>
- <value>1</value>
+ <key>label5</key>
+ <value></value>
</param>
<param>
<key>marker5</key>
<value>-1</value>
</param>
<param>
- <key>alpha5</key>
- <value>1.0</value>
+ <key>style5</key>
+ <value>1</value>
</param>
<param>
- <key>label6</key>
- <value></value>
+ <key>width5</key>
+ <value>1</value>
</param>
<param>
- <key>width6</key>
- <value>1</value>
+ <key>alpha6</key>
+ <value>1.0</value>
</param>
<param>
<key>color6</key>
<value>"magenta"</value>
</param>
<param>
- <key>style6</key>
- <value>1</value>
+ <key>label6</key>
+ <value></value>
</param>
<param>
<key>marker6</key>
<value>-1</value>
</param>
<param>
- <key>alpha6</key>
- <value>1.0</value>
+ <key>style6</key>
+ <value>1</value>
</param>
<param>
- <key>label7</key>
- <value></value>
+ <key>width6</key>
+ <value>1</value>
</param>
<param>
- <key>width7</key>
- <value>1</value>
+ <key>alpha7</key>
+ <value>1.0</value>
</param>
<param>
<key>color7</key>
<value>"yellow"</value>
</param>
<param>
- <key>style7</key>
- <value>1</value>
+ <key>label7</key>
+ <value></value>
</param>
<param>
<key>marker7</key>
<value>-1</value>
</param>
<param>
- <key>alpha7</key>
- <value>1.0</value>
+ <key>style7</key>
+ <value>1</value>
</param>
<param>
- <key>label8</key>
- <value></value>
+ <key>width7</key>
+ <value>1</value>
</param>
<param>
- <key>width8</key>
- <value>1</value>
+ <key>alpha8</key>
+ <value>1.0</value>
</param>
<param>
<key>color8</key>
<value>"dark red"</value>
</param>
<param>
- <key>style8</key>
- <value>1</value>
+ <key>label8</key>
+ <value></value>
</param>
<param>
<key>marker8</key>
<value>-1</value>
</param>
<param>
- <key>alpha8</key>
- <value>1.0</value>
+ <key>style8</key>
+ <value>1</value>
</param>
<param>
- <key>label9</key>
- <value></value>
+ <key>width8</key>
+ <value>1</value>
</param>
<param>
- <key>width9</key>
- <value>1</value>
+ <key>alpha9</key>
+ <value>1.0</value>
</param>
<param>
<key>color9</key>
<value>"dark green"</value>
</param>
<param>
- <key>style9</key>
- <value>1</value>
- </param>
+ <key>label9</key>
+ <value></value>
+ </param>
<param>
<key>marker9</key>
<value>-1</value>
</param>
<param>
- <key>alpha9</key>
- <value>1.0</value>
+ <key>style9</key>
+ <value>1</value>
</param>
<param>
- <key>label10</key>
- <value></value>
+ <key>width9</key>
+ <value>1</value>
</param>
<param>
- <key>width10</key>
+ <key>name</key>
+ <value>Scope Plot</value>
+ </param>
+ <param>
+ <key>nconnections</key>
<value>1</value>
</param>
<param>
- <key>color10</key>
- <value>"blue"</value>
+ <key>size</key>
+ <value>1024</value>
</param>
<param>
- <key>style10</key>
+ <key>srate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>ylabel</key>
+ <value>Amplitude</value>
+ </param>
+ <param>
+ <key>yunit</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>ymax</key>
<value>1</value>
</param>
<param>
- <key>marker10</key>
+ <key>ymin</key>
<value>-1</value>
</param>
+ </block>
+ <block>
+ <key>virtual_sink</key>
<param>
- <key>alpha10</key>
- <value>1.0</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>alias</key>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(856, 524)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>virtual_sink_0</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Time Domain</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_sink</key>
+ <param>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>affinity</key>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(856, 252)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>virtual_sink_0_0</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Payload Bits</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_sink</key>
+ <param>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(962, 714)</value>
+ <value>(744, 388)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>id</key>
+ <value>virtual_sink_0_0_0</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Pre-OFDM</value>
+ </param>
</block>
<block>
- <key>options</key>
+ <key>virtual_sink</key>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(960, 620)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
<param>
<key>id</key>
- <value>tx_ofdm</value>
+ <value>virtual_sink_1</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Tx Signal</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>title</key>
- <value>OFDM Tx</value>
+ <key>_coordinate</key>
+ <value>(0, 324)</value>
</param>
<param>
- <key>author</key>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>virtual_source_0</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Header Bits</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>description</key>
- <value>Example of an OFDM Transmitter</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>window_size</key>
- <value>1280, 1024</value>
+ <key>_coordinate</key>
+ <value>(0, 404)</value>
</param>
<param>
- <key>generate_options</key>
- <value>qt_gui</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>category</key>
- <value>Custom</value>
+ <key>id</key>
+ <value>virtual_source_0_0</value>
</param>
<param>
- <key>run_options</key>
- <value>run</value>
+ <key>stream_id</key>
+ <value>Payload Bits</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>run</key>
+ <key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>max_nouts</key>
+ <key>_coordinate</key>
+ <value>(0, 524)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
<value>0</value>
</param>
<param>
- <key>realtime_scheduling</key>
+ <key>id</key>
+ <value>virtual_source_0_0_0</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Pre-OFDM</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>alias</key>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(0, 692)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>virtual_source_0_0_0_0</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Time Domain</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(1, 0)</value>
+ <value>(0, 836)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>id</key>
+ <value>virtual_source_1</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Tx Signal</value>
+ </param>
</block>
<connection>
- <source_block_id>blocks_tagged_stream_mux_0</source_block_id>
- <sink_block_id>virtual_sink_0_0_0</sink_block_id>
+ <source_block_id>analog_random_source_x_0</source_block_id>
+ <sink_block_id>blocks_stream_to_tagged_stream_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>virtual_source_0_0</source_block_id>
- <sink_block_id>digital_chunks_to_symbols_xx_0_0</sink_block_id>
+ <source_block_id>blocks_multiply_const_vxx_0</source_block_id>
+ <sink_block_id>blocks_tag_gate_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>virtual_source_0</source_block_id>
- <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id>
+ <source_block_id>blocks_repack_bits_bb_0</source_block_id>
+ <sink_block_id>virtual_sink_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_chunks_to_symbols_xx_0_0</source_block_id>
- <sink_block_id>blocks_tagged_stream_mux_0</sink_block_id>
+ <source_block_id>blocks_repack_bits_bb_0_0</source_block_id>
+ <sink_block_id>header_bits</sink_block_id>
<source_key>0</source_key>
- <sink_key>1</sink_key>
+ <sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>virtual_source_0_0_0_0</source_block_id>
- <sink_block_id>blocks_multiply_const_vxx_0</sink_block_id>
+ <source_block_id>blocks_stream_to_tagged_stream_0</source_block_id>
+ <sink_block_id>digital_crc32_bb_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>virtual_source_0_0_0</source_block_id>
- <sink_block_id>digital_ofdm_carrier_allocator_cvc_0</sink_block_id>
+ <source_block_id>blocks_tag_gate_0</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_ofdm_carrier_allocator_cvc_0</source_block_id>
- <sink_block_id>fft_vxx_0</sink_block_id>
+ <source_block_id>blocks_tagged_stream_mux_0</source_block_id>
+ <sink_block_id>virtual_sink_0_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>fft_vxx_0</source_block_id>
- <sink_block_id>digital_ofdm_cyclic_prefixer_0</sink_block_id>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_ofdm_cyclic_prefixer_0</source_block_id>
- <sink_block_id>virtual_sink_0</sink_block_id>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_multiply_const_vxx_0</source_block_id>
- <sink_block_id>blocks_tag_gate_0</sink_block_id>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>virtual_sink_1</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_tag_gate_0</source_block_id>
- <sink_block_id>blocks_throttle_0</sink_block_id>
+ <source_block_id>channels_channel_model_0</source_block_id>
+ <sink_block_id>digital_ofdm_rx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
@@ -2288,74 +2487,80 @@
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>analog_random_source_x_0</source_block_id>
- <sink_block_id>blocks_stream_to_tagged_stream_0</sink_block_id>
+ <source_block_id>digital_chunks_to_symbols_xx_0_0</source_block_id>
+ <sink_block_id>blocks_tagged_stream_mux_0</sink_block_id>
<source_key>0</source_key>
- <sink_key>0</sink_key>
+ <sink_key>1</sink_key>
</connection>
<connection>
- <source_block_id>blocks_stream_to_tagged_stream_0</source_block_id>
- <sink_block_id>digital_crc32_bb_0</sink_block_id>
+ <source_block_id>digital_crc32_bb_0</source_block_id>
+ <sink_block_id>blocks_repack_bits_bb_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>digital_crc32_bb_0</source_block_id>
- <sink_block_id>digital_packet_headergenerator_bb_0</sink_block_id>
+ <sink_block_id>digital_protocol_formatter_bb_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_crc32_bb_0</source_block_id>
- <sink_block_id>blocks_repack_bits_bb_0</sink_block_id>
+ <source_block_id>digital_ofdm_carrier_allocator_cvc_0</source_block_id>
+ <sink_block_id>fft_vxx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_packet_headergenerator_bb_0</source_block_id>
- <sink_block_id>header_bits</sink_block_id>
+ <source_block_id>digital_ofdm_cyclic_prefixer_0</source_block_id>
+ <sink_block_id>virtual_sink_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_repack_bits_bb_0</source_block_id>
- <sink_block_id>virtual_sink_0_0</sink_block_id>
+ <source_block_id>digital_ofdm_rx_0</source_block_id>
+ <sink_block_id>blocks_tag_debug_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_throttle_0</source_block_id>
- <sink_block_id>virtual_sink_1</sink_block_id>
+ <source_block_id>digital_protocol_formatter_bb_0</source_block_id>
+ <sink_block_id>blocks_repack_bits_bb_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>virtual_source_1</source_block_id>
- <sink_block_id>channels_channel_model_0</sink_block_id>
+ <source_block_id>fft_vxx_0</source_block_id>
+ <sink_block_id>digital_ofdm_cyclic_prefixer_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>channels_channel_model_0</source_block_id>
- <sink_block_id>digital_ofdm_rx_0</sink_block_id>
+ <source_block_id>virtual_source_0</source_block_id>
+ <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_ofdm_rx_0</source_block_id>
- <sink_block_id>blocks_tag_debug_0</sink_block_id>
+ <source_block_id>virtual_source_0_0</source_block_id>
+ <sink_block_id>digital_chunks_to_symbols_xx_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_throttle_0</source_block_id>
- <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
+ <source_block_id>virtual_source_0_0_0</source_block_id>
+ <sink_block_id>digital_ofdm_carrier_allocator_cvc_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_throttle_0</source_block_id>
- <sink_block_id>qtgui_time_sink_x_0</sink_block_id>
+ <source_block_id>virtual_source_0_0_0_0</source_block_id>
+ <sink_block_id>blocks_multiply_const_vxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>virtual_source_1</source_block_id>
+ <sink_block_id>channels_channel_model_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
diff --git a/gr-digital/grc/digital_block_tree.xml
b/gr-digital/grc/digital_block_tree.xml
index 9bdf6e9..5e6e742 100644
--- a/gr-digital/grc/digital_block_tree.xml
+++ b/gr-digital/grc/digital_block_tree.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
- Copyright 2011-2015 Free Software Foundation, Inc.
+ Copyright 2011-2016 Free Software Foundation, Inc.
This file is part of GNU Radio
@@ -72,6 +72,10 @@
<block>digital_crc32_bb</block>
<block>digital_crc32_async_bb</block>
<block>digital_framer_sink_1</block>
+ <block>variable_header_format_default</block>
+ <block>digital_protocol_formatter_async</block>
+ <block>digital_protocol_formatter_bb</block>
+ <block>digital_protocol_parser_b</block>
<block>digital_header_payload_demux</block>
<block>digital_packet_headergenerator_bb</block>
<block>digital_packet_headergenerator_bb_default</block>
diff --git a/gr-digital/grc/digital_protocol_formatter_async.xml
b/gr-digital/grc/digital_protocol_formatter_async.xml
new file mode 100644
index 0000000..52a67ec
--- /dev/null
+++ b/gr-digital/grc/digital_protocol_formatter_async.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+
+<block>
+ <name>Protocol Formatter (Async)</name>
+ <key>digital_protocol_formatter_async</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.protocol_formatter_async($format)</make>
+
+ <param>
+ <name>Format Obj.</name>
+ <key>format</key>
+ <type>raw</type>
+ </param>
+
+ <sink>
+ <name>in</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+
+ <source>
+ <name>header</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+
+ <source>
+ <name>payload</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+
+</block>
diff --git a/gr-digital/grc/digital_protocol_formatter_bb.xml
b/gr-digital/grc/digital_protocol_formatter_bb.xml
new file mode 100644
index 0000000..b37a791
--- /dev/null
+++ b/gr-digital/grc/digital_protocol_formatter_bb.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+
+<block>
+ <name>Protocol Formatter</name>
+ <key>digital_protocol_formatter_bb</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.protocol_formatter_bb($format, $len_tag_key)</make>
+
+ <param>
+ <name>Format Obj.</name>
+ <key>format</key>
+ <type>raw</type>
+ </param>
+
+ <param>
+ <name>Length Tag Name</name>
+ <key>len_tag_key</key>
+ <value>"packet_len"</value>
+ <type>string</type>
+ </param>
+
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+
+</block>
diff --git a/gr-digital/grc/digital_protocol_parser_b.xml
b/gr-digital/grc/digital_protocol_parser_b.xml
new file mode 100644
index 0000000..27fb15e
--- /dev/null
+++ b/gr-digital/grc/digital_protocol_parser_b.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+
+<block>
+ <name>Protocol Parser</name>
+ <key>digital_protocol_parser_b</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.protocol_parser_b($format)</make>
+
+ <param>
+ <name>Format Obj.</name>
+ <key>format</key>
+ <type>raw</type>
+ </param>
+
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+
+ <source>
+ <name>info</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/gr-digital/grc/variable_header_format_default.xml
b/gr-digital/grc/variable_header_format_default.xml
new file mode 100644
index 0000000..55b361f
--- /dev/null
+++ b/gr-digital/grc/variable_header_format_default.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+# header_format_default object
+###################################################
+ -->
+<block>
+ <name>Default Header Format Obj.</name>
+ <key>variable_header_format_default</key>
+ <import>from gnuradio import digital</import>
+ <var_make>
+#if int($access_code())==0 #
+self.$(id) = $(id) =
digital.header_format_default(digital.packet_utils.default_access_code,
$threshold)
+#else
+self.$(id) = $(id) = digital.header_format_default($access_code, $threshold)
+#end if
+ </var_make>
+ <var_value>digital.header_format_default($access_code,
$threshold)</var_value>
+ <make></make>
+
+ <param>
+ <name>Access Code</name>
+ <key>access_code</key>
+ <value>0</value>
+ <type>string</type>
+ </param>
+
+ <param>
+ <name>Threshold</name>
+ <key>threshold</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+
+</block>
diff --git a/gr-digital/include/gnuradio/digital/CMakeLists.txt
b/gr-digital/include/gnuradio/digital/CMakeLists.txt
index d8fe2b6..1b22265 100644
--- a/gr-digital/include/gnuradio/digital/CMakeLists.txt
+++ b/gr-digital/include/gnuradio/digital/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2011-2015 Free Software Foundation, Inc.
+# Copyright 2011-2016 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -65,6 +65,7 @@ install(FILES
glfsr_source_f.h
hdlc_deframer_bp.h
hdlc_framer_pb.h
+ header_buffer.h
header_payload_demux.h
kurtotic_equalizer_cc.h
lfsr.h
@@ -90,6 +91,14 @@ install(FILES
ofdm_sampler.h
ofdm_serializer_vcc.h
ofdm_sync_sc_cfb.h
+ header_format_base.h
+ header_format_default.h
+ header_format_counter.h
+ header_format_crc.h
+ header_format_ofdm.h
+ protocol_formatter_async.h
+ protocol_formatter_bb.h
+ protocol_parser_b.h
packet_header_default.h
packet_header_ofdm.h
packet_headergenerator_bb.h
diff --git a/gr-digital/include/gnuradio/digital/header_buffer.h
b/gr-digital/include/gnuradio/digital/header_buffer.h
new file mode 100644
index 0000000..ddcc2a8
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/header_buffer.h
@@ -0,0 +1,310 @@
+/* -*- c++ -*- */
+/* Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_HEADER_BUFFER_H
+#define INCLUDED_DIGITAL_HEADER_BUFFER_H
+
+#include <gnuradio/digital/api.h>
+#include <vector>
+#include <stdint.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Helper class for handling payload headers.
+ * \ingroup packet_operators_blk
+ *
+ * \details
+ *
+ * This class is used by the header format blocks (e.g.,
+ * digital::header_format_default) to make it easier to deal with
+ * payload headers. This class functions in two different ways
+ * depending on if it is used in a transmitter or receiver. When
+ * used in a transmitter, this class helps us build headers out of
+ * the fields of the protocol. When used in a receiver, this class
+ * helps us parse the received bits into the protocol's fields.
+ *
+ * This page describes how to work with the different modes,
+ * transmit or receive. The class is instructed as to which mode
+ * it is in by how the constructor is called. If the constructor
+ * is passed a valid array (non NULL), then it is in transmit mode
+ * and will pack this buffer with the header fields. If that
+ * buffer is NULL, the object is in receive mode.
+ *
+ * \section header_buffer_tx Transmit Mode
+ *
+ * When passed a valid buffer in the constructor, this object is in
+ * transmit mode. We can then use the add_field[N] functions to
+ * add new fields to this header. The buffer MUST be large enough
+ * to hold the full header. As this class is meant to work mostly
+ * with the digital::header_format_default and child
+ * classes, the header length can be read from
+ * digital::header_format_default::header_nbytes().
+ *
+ * Each field is a specific length of 8, 16, 32, or 64 bits that
+ * are to be transmitted in network byte order. We can adjust the
+ * direction of the bytes by setting the byte-swap flag, \p bs, to
+ * true or false.
+ *
+ * The length argument (\p len) for all add_field[N] calls is the
+ * number of bytes actually accounted for in the data
+ * structure. Often, we would use the full size of the field,
+ * which is sizeof(dtype), and the add_field[N] call defaults to
+ * len=N. Occasionally, we may need to use fewer bytes than
+ * actually represented by the data type. An example would be the
+ * access code used in the header_format_default, which is a
+ * uint64_t type but may have fewer bytes used in the actual
+ * access code.
+ *
+ * The function that calls this class is expected to handle the
+ * memory handling of the buffer -- both allocating and
+ * deallocating.
+ *
+ * As simple example of using this class in transmit mode:
+ *
+ * \verbatim
+ uint8_t* buffer = (uint8_t*)volk_malloc(header_nbytes(),
+ volk_get_alignment());
+
+ header_buffer hdr(buffer);
+ hdr.add_field64(sync_word, sync_word_len);
+ hdr.add_field16(payload_length);
+ hdr.add_field8(header_flags);
+ hdr.add_field8(header_options);
+
+ // Do something with the header
+
+ volk_free(buffer);
+ \endverbatim
+ *
+ * In this example, the header contains four fields:
+ *
+ * \verbatim
+ |0 15|16 23|24 31|
+ | sync word |
+ | |
+ | length | flags | options |
+ \endverbatim
+ *
+ * The sync word can be up to 64-bits, but the add_field64 is also
+ * passed the number of actual bytes in the sync word and so could
+ * be fewer.
+ *
+ * \section header_buffer_rx Receive Mode
+ *
+ * In receive mode, we build up the header as bits are received by
+ * inserting them with insert_bit. We can find out how long the
+ * current header is, in bits, using the call to length(). If the
+ * header is of the appropriate length, we can then start
+ * extracting the fields from it. When we are done with the
+ * current header, call clear() to reset the internal buffer to
+ * empty, which will mean that length() returns 0.
+ *
+ * The header fields are extracted using the extract_field[N]
+ * functions. Like the add_field[N] functions, we specify the size
+ * (in bits) of the field we are extracting. We pass this function
+ * the bit-position of the expected field in the received header
+ * buffer. The extract_field[N] assumes that the number of bits
+ * for the field is N, but we can tell the function to use fewer
+ * bits if we want. Setting the length parameter of these
+ * functions greater than N is illegal, and it will throw an
+ * error.
+ *
+ * For example, given a header of | length | seq. num. | where the
+ * length is 16 bits and the sequence number is 32 bits, we would
+ * use:
+ *
+ * \verbatim
+ uint16_t len = d_hdr_reg.extract_field16(0);
+ uint32_t seq = d_hdr_reg.extract_field32(16);
+ \endverbatim
+ *
+ * The extract_field functions are specific to data types of the
+ * field and the number of bits for each field is inferred by the
+ * data type. So extract_field16 assumes we want all 16 bits in
+ * the field represented.
+ *
+ * Some headers have fields that are not standard sizes of
+ * integers, like a 1 bit, 4 bit, or even 12 bit fields. We can
+ * ask for fewer bits for each field. say:
+ *
+ * \verbatim
+ |0 15|16 19|20 31|
+ | len | flags | options |
+ \endverbatim
+ *
+ * We would use the following extraction functions:
+ *
+ * \verbatim
+ uint16_t len = d_hdr_reg.extract_field16(0);
+ uint8_t flags = d_hdr_reg.extract_field8(16, 4);
+ uint16_t opts = d_hdr_reg.extract_field16(20, 12);
+ \endverbatim
+ *
+ * \sa header_format_default
+ * \sa header_format_counter
+ * \sa header_format_crc
+ */
+ class DIGITAL_API header_buffer
+ {
+ private:
+ size_t d_offset;
+ uint8_t *d_buffer;
+
+ std::vector<bool> d_input;
+
+ public:
+ /*!
+ * Create a header buffer object with a pre-allocated buffer, \p
+ * buffer, to hold the formatted header data.
+ *
+ * If \p buffer is set to NULL, then this object is in receive
+ * mode meant to receive bits from an incoming data stream and
+ * provide the ability to extract fields. In this mode, calls to
+ * add_field are invalid and will be nops.
+ */
+ header_buffer(uint8_t *buffer=NULL);
+
+ /*!
+ * Class destructor.
+ */
+ ~header_buffer();
+
+ /*!
+ * Clears the header.
+ *
+ * In transmit mode, this resets the current offset so new
+ * add_field functions start adding data to the start of the
+ * buffer.
+ *
+ * In receive mode, this clears the buffer that we have inserted
+ * bits in to.
+ */
+ void clear();
+
+
+ /*!
+ * In transmit mode, this returns the length of the data in
+ * the buffer (not the allocated buffer length).
+ *
+ * In receiving mode, this returns the current length in bits of
+ * the received header.
+ */
+ size_t length() const;
+
+ /*!
+ * Returns a constant pointer to the buffer.
+ */
+ const uint8_t* header() const;
+
+ /*!
+ * Add an 8-bit field to the header.
+ *
+ * \param data The 8-bit data item.
+ * \param len Length (in bits) of \p data.
+ * \param bs Set to 'true' to byte swap the data.
+ */
+ void add_field8(uint8_t data, int len=8, bool bs=false);
+
+ /*!
+ * Add an 16-bit field to the header.
+ *
+ * \param data The 16-bit data item.
+ * \param len Length (in bits) of \p data.
+ * \param bs Set to 'true' to byte swap the data.
+ */
+ void add_field16(uint16_t data, int len=16, bool bs=false);
+
+ /*!
+ * Add an 32-bit field to the header.
+ *
+ * \param data The 32-bit data item.
+ * \param len Length (in bits) of \p data.
+ * \param bs Set to 'true' to byte swap the data.
+ */
+ void add_field32(uint32_t data, int len=32, bool bs=false);
+
+ /*!
+ * Add an 64-bit field to the header.
+ *
+ * \param data The 64-bit data item.
+ * \param len Length (in bits) of \p data.
+ * \param bs Set to 'true' to byte swap the data.
+ */
+ void add_field64(uint64_t data, int len=64, bool bs=false);
+
+
+
+ /*****************************************************
+ * Receive mode to build a header from bits *
+ *****************************************************/
+
+ /*!
+ * Insert a new bit on the back of the input buffer. This
+ * function is used in receive mode to add new bits as they are
+ * received for later use of the extract_field functions.
+ *
+ * \param bit New bit to add.
+ */
+ void insert_bit(int bit);
+
+ /*!
+ * Returns up to an 8-bit field in the packet header.
+ *
+ * \param pos Bit position of the start of the field.
+ * \param len The number of bits in the field.
+ * \param bs Set to 'true' to byte swap the data.
+ */
+ uint8_t extract_field8(int pos, int len=8, bool bs=false);
+
+ /*!
+ * Returns up to a 16-bit field in the packet header.
+ *
+ * \param pos Bit position of the start of the field.
+ * \param len The number of bits in the field.
+ * \param bs Set to 'true' to byte swap the data.
+ */
+ uint16_t extract_field16(int pos, int len=16, bool bs=false);
+
+ /*!
+ * Returns up to a 32-bit field in the packet header.
+ *
+ * \param pos Bit position of the start of the field.
+ * \param len The number of bits in the field.
+ * \param bs Set to 'true' to byte swap the data.
+ */
+ uint32_t extract_field32(int pos, int len=32, bool bs=false);
+
+ /*!
+ * Returns up to a 64-bit field in the packet header.
+ *
+ * \param pos Bit position of the start of the field.
+ * \param len The number of bits in the field.
+ * \param bs Set to 'true' to byte swap the data.
+ */
+ uint64_t extract_field64(int pos, int len=64, bool bs=false);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_HEADER_BUFFER_H */
diff --git a/gr-digital/include/gnuradio/digital/header_format_base.h
b/gr-digital/include/gnuradio/digital/header_format_base.h
new file mode 100644
index 0000000..557a55c
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/header_format_base.h
@@ -0,0 +1,225 @@
+/* -*- c++ -*- */
+/* Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_HEADER_FORMAT_BASE_H
+#define INCLUDED_DIGITAL_HEADER_FORMAT_BASE_H
+
+#include <pmt/pmt.h>
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/header_buffer.h>
+#include <gnuradio/logger.h>
+#include <boost/enable_shared_from_this.hpp>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Base header formatter class.
+ * \ingroup packet_operators_blk
+ *
+ * \details
+ *
+ * Creates a base class that other packet formatters will inherit
+ * from. The child classes create and parse protocol-specific
+ * headers. To add a new protocol processing class, create a class
+ * that inherits from this and overload the necessary
+ * functions. The main functions to overload are:
+ *
+ * \li header_format_base::format: takes in a payload and
+ * creates a header from it.
+ *
+ * \li header_format_base::parse: receive bits and extract
+ * the header info. These are expected to be hard bits (0 or 1)
+ * that have either been sliced or gone through an FEC decoder.
+ *
+ * \li header_format_base::header_nbits: the number of bits
+ * in the full header (including an access code).
+ *
+ * \li header_format_base::header_ok: checks to see if the
+ * received header is ok. Since the header often specifies the
+ * length of the frame to decode next, it is important that this
+ * information be correct.
+ *
+ * \li header_format_base::header_payload: unpacks the header
+ * register (from the class header_buffer) as a set of bits into
+ * its component parts of the header. For example, this may find
+ * and extract the frame length field as a 16-bit value and/or
+ * flags related to the type of modulation and FEC codes used in
+ * the frame's payload.
+ *
+ * Protected functions of this class that the child class should
+ * overload include:
+ *
+ * \li enter_search
+ * \li enter_have_sync
+ * \li enter_have_header
+ *
+ * These three function represent the different states of the
+ * parsing state machine. Expected behavior is that the protocol
+ * has some known word that we are first looking for the identify
+ * the start of the frame. The parsing FSM starts in a state to
+ * search for the beginning of the header, normally by looking for
+ * a known word (i.e., the access code). Then it changes state to
+ * read in the full header. We expect that the protocol provides
+ * the length of the header for processing, so the parsing looks
+ * pulls in the full length of the header. Then it changes state
+ * to the "have header" state for checking and processing. The
+ * base class provides the basic functionality for this state
+ * machine. However, most likely, each child class must manage
+ * these states for themselves.
+ *
+ * This class is specifically designed to work with packets/frames
+ * in the asynchronous PDU architecture of GNU Radio. See the
+ * packet_format_async block for formatting the headers onto
+ * payloads and packet_parse_b block for parsing headers in a
+ * receiver.
+ *
+ * The Packet Format block takes in a PDU and uses a formatter
+ * class derived from this class to add a header onto the
+ * packet. The Packet Format blocks takes in the PDU, unpacks the
+ * message, and passes it to a formatter class' format function,
+ * which builds a header based on the payload. The header is
+ * passed back and emitted from formatter block as a separate
+ * output. The async format block, packet_format_async, has two
+ * message output ports. The 'header' port passes the header out
+ * as a PDU and the 'payload' passes the payload out as a PDU. The
+ * flowgraph can then separately modulate and combine these two
+ * pieces in the follow-on processing.
+ *
+ * The packet_sync_b block uses the formatter class by calling the
+ * 'parse' function to parse the received packet headers. This
+ * parser block is a sink for the data stream and emits a message
+ * from an 'info' port that contains an PMT dictionary of the
+ * information in the header. The formatter class determines the
+ * dictionary keys.
+ *
+ * This is the base class for dealing with formatting headers for
+ * different protocols and purposes. For other header formatting
+ * behaviors, create a child class from here and overload the
+ * format, parse, and parsing state machine functions as
+ * necessary.
+ *
+ * \sa header_format_default
+ * \sa header_format_counter
+ */
+ class DIGITAL_API header_format_base
+ : public boost::enable_shared_from_this<gr::digital::header_format_base>
+ {
+ public:
+ typedef boost::shared_ptr<header_format_base> sptr;
+
+ header_format_base();
+ virtual ~header_format_base();
+
+ sptr base() { return shared_from_this(); };
+ sptr formatter() { return shared_from_this(); };
+
+ /*!
+ * Function to creates a header. The child classes overload this
+ * function to format the header in the protocol-specific way.
+ *
+ * \param nbytes_in The length (in bytes) of the \p input payload
+ * \param input An array of unsigned chars of the packet payload
+ * \param output A pmt::u8vector with the new header prepended
+ * onto the input data.
+ * \param info A pmt::dict containing meta data and info about
+ * the PDU (generally from the metadata portion of the
+ * input PDU). Data can be extracted from this for the
+ * header formatting or inserted.
+ *
+ * MUST be overloaded.
+ */
+ virtual bool format(int nbytes_in,
+ const unsigned char *input,
+ pmt::pmt_t &output,
+ pmt::pmt_t &info) = 0;
+
+ /*!
+ * Parses a header. This function is overloaded in the child
+ * class, which knows how to convert the incoming hard bits (0's
+ * and 1's) back into a packet header.
+ *
+ * \param nbits_in The number of bits in the input array.
+ * \param input The input as hard decision bits.
+ * \param info A vector of pmt::dicts to hold any meta data or
+ * info about the PDU. When parsing the header, the
+ * formatter can add info from the header into this dict.
+ * Each packet has a single PMT dictionary of info, so
+ * the vector length is the number of packets received
+ * extracted during one call to this parser function.
+ * \param nbits_processed Number of input bits actually
+ * processed; If all goes well, this is nbits_in. A
+ * premature return after a bad header could be less than
+ * this.
+ *
+ * MUST be overloaded.
+ */
+ virtual bool parse(int nbits_in,
+ const unsigned char *input,
+ std::vector<pmt::pmt_t> &info,
+ int &nbits_processed) = 0;
+
+ /*!
+ * Returns the length of the formatted header in bits.
+ * MUST be overloaded.
+ */
+ virtual size_t header_nbits() const = 0;
+
+ /*!
+ * Returns the length of the formatted header in bytes.
+ * Auto-calculated from the overloaded header_nbits().
+ */
+ size_t header_nbytes() const;
+
+ protected:
+ enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC};
+
+ state_t d_state; //!< state of the state machine
+ header_buffer d_hdr_reg; //!< header_buffer object to hold header bits
+ pmt::pmt_t d_info; //!< info captured from the header
+
+ //! Enter Search state of the state machine to find the access code.
+ virtual void enter_search();
+
+ //! Access code found, start getting the header
+ virtual void enter_have_sync();
+
+ //! Header found, setup for pulling in the hard decision bits
+ virtual void enter_have_header(int payload_len);
+
+ //! Verify that the header is valid
+ virtual bool header_ok() = 0;
+
+ /*! Get info from the header; return payload length and package
+ * rest of data in d_info dictionary.
+ */
+ virtual int header_payload() = 0;
+
+ /*! Used by blocks to access the logger system.
+ */
+ gr::logger_ptr d_logger;
+ gr::logger_ptr d_debug_logger;
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_HEADER_FORMAT_BASE_H */
diff --git a/gr-digital/include/gnuradio/digital/header_format_counter.h
b/gr-digital/include/gnuradio/digital/header_format_counter.h
new file mode 100644
index 0000000..5eb075a
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/header_format_counter.h
@@ -0,0 +1,135 @@
+/* -*- c++ -*- */
+/* Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_HEADER_FORMAT_COUNTER_H
+#define INCLUDED_DIGITAL_HEADER_FORMAT_COUNTER_H
+
+#include <pmt/pmt.h>
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/header_format_default.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Header formatter that adds the payload bits/symbol
+ * format and a packet number counter.
+ * \ingroup packet_operators_blk
+ *
+ * \details
+ *
+ * Child class of header_format_default. This version adds two
+ * fields to the header:
+ *
+ * \li bps (16 bits): bits/symbol used when modulating the payload.
+ * \li count (16 bits): a counter for the packet number.
+ *
+ * Like the default packet formatter, the length is encoded as a
+ * 16-bit value repeated twice. The full packet looks like:
+ * \verbatim
+ | access code | hdr | payload |
+ \endverbatim
+ *
+ * Where the access code is <= 64 bits and hdr is:
+ * \verbatim
+ | 0 -- 15 | 16 -- 31 |
+ | pkt len | pkt len |
+ | bits/sym | counter |
+ \endverbatim
+ *
+ * The access code and header are formatted for network byte order.
+ *
+ * \sa header_format_default
+ */
+ class DIGITAL_API header_format_counter
+ : public header_format_default
+ {
+ public:
+ header_format_counter(const std::string &access_code,
+ int threshold, int bps);
+ virtual ~header_format_counter();
+
+ /*!
+ * Creates a header from the access code and packet length to
+ * build an output packet in the form:
+ *
+ * \verbatim
+ | access code | pkt len | pkt len | bps | counter |
+ \endverbatim
+ *
+ * \param nbytes_in The length (in bytes) of the \p input payload
+ * \param input An array of unsigned chars of the packet payload
+ * \param output A pmt::u8vector with the new header prepended
+ * onto the input data.
+ * \param info A pmt::dict containing meta data and info about
+ * the PDU (generally from the metadata portion of the
+ * input PDU). Data can be extracted from this for the
+ * header formatting or inserted.
+ */
+ virtual bool format(int nbytes_in,
+ const unsigned char *input,
+ pmt::pmt_t &output,
+ pmt::pmt_t &info);
+
+ /*!
+ * Returns the length of the formatted header in bits.
+ */
+ virtual size_t header_nbits() const;
+
+ /*!
+ * Factory to create an async packet header formatter; returns
+ * an sptr to the object.
+ *
+ * \param access_code An access code that is used to find and
+ * synchronize the start of a packet. Used in the parser and in
+ * other blocks like a corr_est block that helps trigger the
+ * receiver. Can be up to 64-bits long.
+ * \param threshold How many bits can be wrong in the access
+ * code and still count as correct.
+ * \param bps The number of bits/second used in the payload's
+ * modulator.
+ */
+ static sptr make(const std::string &access_code,
+ int threshold, int bps);
+
+ protected:
+ uint16_t d_counter; //!< keeps track of the number of packets
transmitted
+ uint16_t d_bps; //!< bits/sec of payload modulation
+
+ //! Verify that the header is valid
+ bool header_ok();
+
+ /*! Get info from the header; return payload length and package
+ * rest of data in d_info dictionary.
+ *
+ * Extracts the header of the form:
+ *
+ * \verbatim
+ | access code | pkt len | pkt len | bps | counter | payload |
+ \endverbatim
+ */
+ int header_payload();
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_HEADER_FORMAT_COUNTER_H */
diff --git a/gr-digital/include/gnuradio/digital/header_format_crc.h
b/gr-digital/include/gnuradio/digital/header_format_crc.h
new file mode 100644
index 0000000..edb1884
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/header_format_crc.h
@@ -0,0 +1,118 @@
+/* -*- c++ -*- */
+/* Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_HEADER_FORMAT_CRC_H
+#define INCLUDED_DIGITAL_HEADER_FORMAT_CRC_H
+
+#include <pmt/pmt.h>
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/header_format_default.h>
+#include <boost/crc.hpp>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Header formatter that includes the payload length,
+ * packet number, and a CRC check on the header.
+ * \ingroup packet_operators_blk
+ *
+ * \details
+ *
+ * Child class of header_format_base. This version's header
+ * format looks like:
+ *
+ * \li length (12 bits): length of the payload
+ * \li number (12 bits): packet number
+ * \li CRC8 (8 bits): A CRC8 check on the header contents
+ *
+ * Instead of duplicating the payload length, we only add it once
+ * and use the CRC8 to make sure it's correctly received.
+ *
+ * \verbatim
+ | 0 -- 11 | 12 -- 23 | 24 -- 31 |
+ | len | pkt len | CRC8 |
+ \endverbatim
+ *
+ * Reimplements packet_header_default in the style of the
+ * header_format_base.
+ */
+ class DIGITAL_API header_format_crc
+ : public header_format_base
+ {
+ public:
+ header_format_crc(const std::string &len_key_name="packet_len",
+ const std::string &num_key_name="packet_num");
+ virtual ~header_format_crc();
+
+ void set_header_num(unsigned header_num) { d_header_number = header_num;
};
+
+ /*!
+ * \brief Encodes the header information in the given tags into
+ * bits and places them into \p out.
+ *
+ * \details
+ * Uses the following header format:
+ * - Bits 0-11: The packet length (what was stored in the tag with key
\p len_tag_key)
+ * - Bits 12-23: The header number (counts up everytime this function
is called)
+ * - Bit 24-31: 8-Bit CRC
+ */
+ virtual bool format(int nbytes_in,
+ const unsigned char *input,
+ pmt::pmt_t &output,
+ pmt::pmt_t &info);
+
+ virtual bool parse(int nbits_in,
+ const unsigned char *input,
+ std::vector<pmt::pmt_t> &info,
+ int &nbits_processed);
+
+ /*!
+ * Returns the length of the formatted header in bits.
+ */
+ virtual size_t header_nbits() const;
+
+ /*!
+ * Factory to create an async packet header formatter; returns
+ * an sptr to the object.
+ */
+ static sptr make(const std::string &len_key_name="packet_len",
+ const std::string &num_key_name="packet_num");
+
+ protected:
+ uint16_t d_header_number;
+ pmt::pmt_t d_len_key_name;
+ pmt::pmt_t d_num_key_name;
+ boost::crc_optimal<8, 0x07, 0xFF, 0x00, false, false> d_crc_impl;
+
+ //! Verify that the header is valid
+ virtual bool header_ok();
+
+ /*! Get info from the header; return payload length and package
+ * rest of data in d_info dictionary.
+ */
+ virtual int header_payload();
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_HEADER_FORMAT_CRC_H */
diff --git a/gr-digital/include/gnuradio/digital/header_format_default.h
b/gr-digital/include/gnuradio/digital/header_format_default.h
new file mode 100644
index 0000000..4abd7bb
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/header_format_default.h
@@ -0,0 +1,217 @@
+/* -*- c++ -*- */
+/* Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_HEADER_FORMAT_DEFAULT_H
+#define INCLUDED_DIGITAL_HEADER_FORMAT_DEFAULT_H
+
+#include <pmt/pmt.h>
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/header_format_base.h>
+#include <gnuradio/digital/header_buffer.h>
+#include <gnuradio/logger.h>
+#include <boost/enable_shared_from_this.hpp>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Default header formatter for PDU formatting.
+ * \ingroup packet_operators_blk
+ *
+ * \details
+ * Used to handle the default packet header.
+ *
+ * See the parent class header_format_base for details of how
+ * these classes operate.
+ *
+ * The default header created in this base class consists of an
+ * access code and the packet length. The length is encoded as a
+ * 16-bit value repeated twice:
+ *
+ * \verbatim
+ | access code | hdr | payload |
+ \endverbatim
+ *
+ * Where the access code is <= 64 bits and hdr is:
+ *
+ * \verbatim
+ | 0 -- 15 | 16 -- 31 |
+ | pkt len | pkt len |
+ \endverbatim
+ *
+ * The access code and header are formatted for network byte order.
+ *
+ * This header generator does not calculate or append a CRC to the
+ * packet. Use the CRC32 Async block for that before adding the
+ * header. The header's length will then measure the payload plus
+ * the CRC length (4 bytes for a CRC32).
+ *
+ * The default header parser produces a PMT dictionary that
+ * contains the following keys. All formatter blocks MUST produce
+ * these two values in any dictionary.
+ *
+ * \li "payload symbols": the number of symbols in the
+ * payload. The payload decoder will have to know how this relates
+ * to the number of bits received. This block knows nothing about
+ * the payload modulation or the number of bits/symbol. Use the
+ * gr::digital::header_format_counter for that purpose.
+ *
+ * \sa header_format_counter
+ * \sa header_format_crc
+ * \sa header_format_ofdm
+ */
+ class DIGITAL_API header_format_default
+ : public header_format_base
+ {
+ public:
+ header_format_default(const std::string &access_code, int threshold);
+ virtual ~header_format_default();
+
+ /*!
+ * Creates a header from the access code and packet length and
+ * creates an output header as a PMT vector in the form:
+ *
+ * \verbatim
+ | access code | pkt len | pkt len |
+ \endverbatim
+ *
+ * \param nbytes_in The length (in bytes) of the \p input payload
+ * \param input An array of unsigned chars of the packet payload
+ * \param output A pmt::u8vector with the new header prepended
+ * onto the input data.
+ * \param info A pmt::dict containing meta data and info about
+ * the PDU (generally from the metadata portion of the
+ * input PDU). Data can be extracted from this for the
+ * header formatting or inserted.
+ */
+ virtual bool format(int nbytes_in,
+ const unsigned char *input,
+ pmt::pmt_t &output,
+ pmt::pmt_t &info);
+
+ /*!
+ * Parses a header of the form:
+ *
+ * \verbatim
+ | access code | pkt len | pkt len | payload |
+ \endverbatim
+ *
+ * This is implemented as a state machine that starts off
+ * searching for the access code. Once found, the access code is
+ * used to find the start of the packet and the following
+ * header. This default header encodes the length of the payload
+ * a 16 bit integer twice. The state machine finds the header
+ * and checks that both payload length values are the same. It
+ * then goes into its final state that reads in the payload
+ * (based on the payload length) and produces a payload as a PMT
+ * u8 vector of packed bytes.
+ *
+ * \param nbits_in The number of bits in the input array.
+ * \param input The input as hard decision bits.
+ * \param info A vector of pmt::dicts to hold any meta data or
+ * info about the PDU. When parsing the header, the
+ * formatter can add info from the header into this dict.
+ * Each packet has a single PMT dictionary of info, so
+ * the vector length is the number of packets received
+ * extracted during one call to this parser function.
+ * \param nbits_processed Number of input bits actually
+ * processed; If all goes well, this is nbits_in. A
+ * premature return after a bad header could be less than
+ * this.
+ */
+ virtual bool parse(int nbits_in,
+ const unsigned char *input,
+ std::vector<pmt::pmt_t> &info,
+ int &nbits_processed);
+
+ /*!
+ * Returns the length of the formatted header in bits.
+ */
+ virtual size_t header_nbits() const;
+
+ /*!
+ * Updates the access code. Must be a string of 1's and 0's and
+ * <= 64 bits.
+ */
+ bool set_access_code(const std::string &access_code);
+
+ /*!
+ * Returns the formatted access code as a 64-bit register.
+ */
+ unsigned long long access_code() const;
+
+ /*!
+ * Sets the threshold for number of access code bits can be in
+ * error before detection. Defaults to 0.
+ */
+ void set_threshold(unsigned int thresh=0);
+
+ /*!
+ * Returns threshold value for access code detection.
+ */
+ unsigned int threshold() const;
+
+ /*!
+ * Factory to create an async packet header formatter; returns
+ * an sptr to the object.
+ *
+ * \param access_code An access code that is used to find and
+ * synchronize the start of a packet. Used in the parser and in
+ * other blocks like a corr_est block that helps trigger the
+ * receiver. Can be up to 64-bits long.
+ * \param threshold How many bits can be wrong in the access
+ * code and still count as correct.
+ */
+ static sptr make(const std::string &access_code, int threshold);
+
+ protected:
+ uint64_t d_access_code; //!< register to hold the access code
+ size_t d_access_code_len; //!< length in bits of the access code
+
+ unsigned long long d_data_reg; //!< used to look for access_code
+ unsigned long long d_mask; /*!< masks access_code bits (top N bits
are set where
+ N is the number of bits in the access
code) */
+ unsigned int d_threshold; //!< how many bits may be wrong in sync
vector
+
+ int d_pkt_len; //!< Length of the packet to put into the
output buffer
+ int d_pkt_count; //!< Number of bytes bits already received
+
+ int d_nbits; //!< num bits processed since reset
+
+ //! Access code found, start getting the header
+ virtual void enter_have_sync();
+
+ //! Header found, setup for pulling in the hard decision bits
+ virtual void enter_have_header(int payload_len);
+
+ //! Verify that the header is valid
+ virtual bool header_ok();
+
+ /*! Get info from the header; return payload length and package
+ * rest of data in d_info dictionary.
+ */
+ virtual int header_payload();
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_HEADER_FORMAT_DEFAULT_H */
diff --git a/gr-digital/include/gnuradio/digital/header_format_ofdm.h
b/gr-digital/include/gnuradio/digital/header_format_ofdm.h
new file mode 100644
index 0000000..b426c74
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/header_format_ofdm.h
@@ -0,0 +1,127 @@
+/* -*- c++ -*- */
+/* Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_HEADER_FORMAT_OFDM_H
+#define INCLUDED_DIGITAL_HEADER_FORMAT_OFDM_H
+
+#include <pmt/pmt.h>
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/header_format_crc.h>
+#include <boost/crc.hpp>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Header formatter that includes the payload length,
+ * packet number, and a CRC check on the header.
+ * \ingroup packet_operators_blk
+ *
+ * \details
+ *
+ * Child class of header_format_base. This version's header
+ * format looks like:
+ *
+ * \li length (12 bits): length of the payload
+ * \li number (12 bits): packet number
+ * \li CRC8 (8 bits): A CRC8 check on the header contents
+ *
+ * Instead of duplicating the payload length, we only add it once
+ * and use the CRC8 to make sure it's correctly received.
+ *
+ * \verbatim
+ | 0 -- 11 | 12 -- 23 | 24 -- 31 |
+ | len | pkt len | CRC8 |
+ \endverbatim
+ *
+ * Reimplements packet_header_default in the style of the
+ * header_format_base.
+ */
+ class DIGITAL_API header_format_ofdm
+ : public header_format_crc
+ {
+ public:
+ header_format_ofdm(const std::vector<std::vector<int> >
&occupied_carriers,
+ int n_syms,
+ const std::string &len_key_name="packet_len",
+ const std::string &frame_key_name="frame_len",
+ const std::string &num_key_name="packet_num",
+ int bits_per_header_sym=1,
+ int bits_per_payload_sym=1,
+ bool scramble_header=false);
+ virtual ~header_format_ofdm();
+
+ /*!
+ * \brief Encodes the header information in the given tags into
+ * bits and places them into \p out.
+ *
+ * \details
+ * Uses the following header format:
+ * - Bits 0-11: The packet length (what was stored in the tag with key
\p len_tag_key)
+ * - Bits 12-23: The header number (counts up everytime this function
is called)
+ * - Bit 24-31: 8-Bit CRC
+ */
+ virtual bool format(int nbytes_in,
+ const unsigned char *input,
+ pmt::pmt_t &output,
+ pmt::pmt_t &info);
+
+ virtual bool parse(int nbits_in,
+ const unsigned char *input,
+ std::vector<pmt::pmt_t> &info,
+ int &nbits_processed);
+
+ /*!
+ * Returns the length of the formatted header in bits.
+ */
+ virtual size_t header_nbits() const;
+
+ /*!
+ * Factory to create an async packet header formatter; returns
+ * an sptr to the object.
+ */
+ static sptr make(const std::vector<std::vector<int> > &occupied_carriers,
+ int n_syms,
+ const std::string &len_key_name="packet_len",
+ const std::string &frame_key_name="frame_len",
+ const std::string &num_key_name="packet_num",
+ int bits_per_header_sym=1,
+ int bits_per_payload_sym=1,
+ bool scramble_header=false);
+
+ protected:
+ pmt::pmt_t d_frame_key_name; //!< Tag key of the additional frame length
tag
+ const std::vector<std::vector<int> > d_occupied_carriers; //!< Which
carriers/symbols carry data
+ int d_syms_per_set; //!< Helper variable: Total number of elements in
d_occupied_carriers
+ int d_bits_per_payload_sym;
+ std::vector<uint8_t> d_scramble_mask; //!< Bits are xor'd with this
before tx'ing
+ size_t d_header_len;
+
+ /*! Get info from the header; return payload length and package
+ * rest of data in d_info dictionary.
+ */
+ virtual int header_payload();
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_HEADER_FORMAT_OFDM_H */
diff --git a/gr-digital/include/gnuradio/digital/protocol_formatter_async.h
b/gr-digital/include/gnuradio/digital/protocol_formatter_async.h
new file mode 100644
index 0000000..560a236
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/protocol_formatter_async.h
@@ -0,0 +1,88 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_DIGITAL_PROTOCOL_FORMATTER_ASYNC_H
+#define INCLUDED_DIGITAL_PROTOCOL_FORMATTER_ASYNC_H
+
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/header_format_base.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Uses a header format object to append a header onto a
+ * PDU.
+ *
+ * \ingroup packet_operators_blk
+ *
+ * \details
+ * This block takes in PDUs and creates a header, generally for
+ * MAC-level processing. Each received PDU is assumed to be its
+ * own frame, so any fragmentation would be done upstream in or
+ * before the flowgraph.
+ *
+ * The header that is created and transmitted out of the 'header'
+ * message port as a PDU. The header is based entirely on the \p
+ * format object, which is an object derived from the
+ * header_format_base class. All of these packet header format
+ * objects operate the same: they take in the payload data as well
+ * as possible extra metadata info about the PDU; the format
+ * object then returns the output PDU as a PMT argument along
+ * with any changes to the metadata info PMT.
+ *
+ * For different packet header formatting needs, we can define new
+ * classes that inherit from the header_format_base block
+ * and which overload the header_format_base::format
+ * function.
+ *
+ * \sa header_format_base
+ * \sa header_format_default
+ * \sa header_format_counter
+ *
+ * This block only uses asynchronous message passing interfaces to
+ * receiver and emit PDUs. The message ports are:
+ *
+ * \li in: receives PDUs for the frame payload
+ * \li header: the header formatted for the given frame
+ * \li payload: the payload
+ */
+ class DIGITAL_API protocol_formatter_async : virtual public block
+ {
+ public:
+ typedef boost::shared_ptr<protocol_formatter_async> sptr;
+
+ /*!
+ * Make a packet header block using a given \p format.
+ *
+ * \param format The format object to use when creating the
+ * header for the packet.
+ */
+ static sptr make(const header_format_base::sptr &format);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PROTOCOL_FORMATTER_ASYNC_H */
diff --git a/gr-digital/include/gnuradio/digital/protocol_formatter_bb.h
b/gr-digital/include/gnuradio/digital/protocol_formatter_bb.h
new file mode 100644
index 0000000..2a57fdc
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/protocol_formatter_bb.h
@@ -0,0 +1,81 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_DIGITAL_PROTOCOL_FORMATTER_BB_H
+#define INCLUDED_DIGITAL_PROTOCOL_FORMATTER_BB_H
+
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/header_format_base.h>
+#include <gnuradio/tagged_stream_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Uses a header format object to create a header from a
+ * tagged stream packet.
+ *
+ * \ingroup packet_operators_blk
+ *
+ * \details
+ * This block takes in tagged stream and creates a header,
+ * generally for MAC-level processing. Each received tagged stream
+ * is assumed to be its own frame, so any fragmentation would be
+ * done upstream in or before the flowgraph.
+ *
+ * The header that is created and transmitted from this block. The
+ * payload should then be sent as a parallel tagged stream to be
+ * muxed together later. The header is based entirely on the \p
+ * format object, which is an object derived from the
+ * header_format_base class. All of these packet header format
+ * objects operate the same: they take in the payload data as well
+ * as possible extra metadata info about the PDU; the format
+ * object then returns the output and metadata info. This block
+ * then transmits the header vector and attaches and metadata as
+ * tags at the start of the header.
+ *
+ * \sa protocol_formatter_async
+ */
+ class DIGITAL_API protocol_formatter_bb : virtual public
tagged_stream_block
+ {
+ public:
+ typedef boost::shared_ptr<protocol_formatter_bb> sptr;
+
+ /*!
+ * Make a packet header block using a given \p format.
+ *
+ * \param format The format object to use when creating the
+ * header for the packet. Derived from the
+ * header_format_base class.
+ * \param len_tag_key The tagged stream length key.
+ */
+ static sptr make(const header_format_base::sptr &format,
+ const std::string &len_tag_key="packet_len");
+
+ virtual void set_header_format(header_format_base::sptr &format) = 0;
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PROTOCOL_FORMATTER_BB_H */
diff --git a/gr-digital/include/gnuradio/digital/protocol_parser_b.h
b/gr-digital/include/gnuradio/digital/protocol_parser_b.h
new file mode 100644
index 0000000..89c7f7e
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/protocol_parser_b.h
@@ -0,0 +1,80 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_DIGITAL_PACKET_PARSE_B_H
+#define INCLUDED_DIGITAL_PACKET_PARSE_B_H
+
+#include <gnuradio/digital/api.h>
+#include <gnuradio/digital/header_format_base.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Block that synchronizes to a header based on a header
+ * format object class. Designed to accept hard bits and produce
+ * PDUs with packed bytes (pmt::u8vector).
+ *
+ * \ingroup packet_operators_blk
+ *
+ * \details
+ *
+ * A packet synchronizer block. This block takes in hard bits
+ * (unpacked bytes; 1's and 0's as the LSB) and finds the access
+ * code as a sync word to find the start of a frame.
+ *
+ * The block uses a format object derived from a
+ * header_format_base class.
+ *
+ * Once the frame is detected (usually through the use of an
+ * access code), the block uses the format object's parser
+ * function to decode the remaining header. Generally, as in the
+ * default header case, the header will contain the length of the
+ * frame's payload. That and anything else in the header will
+ * generally go into the PDU's meta-data dictionary.
+ *
+ * The block will output a PDU that contains frame's header info
+ * in the meta-data portion of the PDU and the payload itself. The
+ * payload is packed hard bits as taken from the input stream.
+ *
+ * \sa packet_sync_ff for a soft decision version.
+ */
+ class DIGITAL_API protocol_parser_b : virtual public sync_block
+ {
+ public:
+ typedef boost::shared_ptr<protocol_parser_b> sptr;
+
+ /*!
+ * Make a packet header block using a given \p format.
+ *
+ * \param format The format object to use when reading the
+ * header.
+ */
+ static sptr make(const header_format_base::sptr &format);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PROTOCOL_PARSER_B_H */
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index daa577f..84f53ec 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2011-2014 Free Software Foundation, Inc.
+# Copyright 2011-2016 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -83,6 +83,7 @@ list(APPEND digital_sources
glfsr_source_f_impl.cc
hdlc_deframer_bp_impl.cc
hdlc_framer_pb_impl.cc
+ header_buffer.cc
header_payload_demux_impl.cc
kurtotic_equalizer_cc_impl.cc
lms_dd_equalizer_cc_impl.cc
@@ -106,6 +107,14 @@ list(APPEND digital_sources
ofdm_sampler_impl.cc
ofdm_serializer_vcc_impl.cc
ofdm_sync_sc_cfb_impl.cc
+ header_format_base.cc
+ header_format_default.cc
+ header_format_counter.cc
+ header_format_crc.cc
+ header_format_ofdm.cc
+ protocol_formatter_async_impl.cc
+ protocol_formatter_bb_impl.cc
+ protocol_parser_b_impl.cc
packet_header_default.cc
packet_header_ofdm.cc
packet_headergenerator_bb_impl.cc
@@ -189,3 +198,38 @@ if(ENABLE_STATIC_LIBS)
ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT "digital_devel" # .lib
file
)
endif(ENABLE_STATIC_LIBS)
+
+
+########################################################################
+# QA C++ Code for gr-blocks
+########################################################################
+if(ENABLE_TESTING)
+ include(GrTest)
+
+ include_directories(
+ ${GR_DIGITAL_INCLUDE_DIRS}
+ ${CPPUNIT_INCLUDE_DIRS})
+ link_directories(${CPPUNIT_LIBRARY_DIRS})
+
+ list(APPEND test_gr_digital_sources
+ ${CMAKE_CURRENT_SOURCE_DIR}/test_gr_digital.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_digital.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_header_format.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_header_buffer.cc
+ )
+
+ add_executable(test-gr-digital ${test_gr_digital_sources})
+
+ list(APPEND GR_TEST_TARGET_DEPS test-gr-digital gnuradio-digital)
+
+ target_link_libraries(
+ test-gr-digital
+ gnuradio-runtime
+ gnuradio-digital
+ ${Boost_LIBRARIES}
+ ${CPPUNIT_LIBRARIES}
+ ${LOG4CPP_LIBRARIES}
+ )
+
+ GR_ADD_TEST(test_gr_digital test-gr-digital)
+endif(ENABLE_TESTING)
diff --git a/gr-digital/lib/header_buffer.cc b/gr-digital/lib/header_buffer.cc
new file mode 100644
index 0000000..04233da
--- /dev/null
+++ b/gr-digital/lib/header_buffer.cc
@@ -0,0 +1,211 @@
+/* -*- c++ -*- */
+/* Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <algorithm>
+#include <stdexcept>
+#include <volk/volk.h>
+#include <gnuradio/digital/header_buffer.h>
+
+namespace gr {
+ namespace digital {
+
+ header_buffer::header_buffer(uint8_t *bytes_out)
+ {
+ d_offset = 0;
+ d_buffer = bytes_out;
+ }
+
+ header_buffer::~header_buffer()
+ {
+ }
+
+ void
+ header_buffer::clear()
+ {
+ if(d_buffer) // TX mode
+ d_offset = 0;
+ else // RX mode
+ d_input.clear();
+ }
+
+ size_t
+ header_buffer::length() const
+ {
+ if(d_buffer) // TX mode
+ return d_offset;
+ else // RX mode
+ return d_input.size();
+ }
+
+ const uint8_t*
+ header_buffer::header() const
+ {
+ return d_buffer;
+ }
+
+ void
+ header_buffer::add_field8(uint8_t data, int len, bool bs)
+ {
+ int nbytes = len/8;
+ if(d_buffer) {
+ memcpy(&d_buffer[d_offset], &data, nbytes);
+ d_offset += nbytes;
+ }
+ }
+
+ void
+ header_buffer::add_field16(uint16_t data, int len, bool bs)
+ {
+ int nbytes = len/8;
+ if(d_buffer) {
+ uint16_t x = data;
+ if(!bs) {
+ volk_16u_byteswap(&x, 1);
+ x = x >> (16-len);
+ }
+ memcpy(&d_buffer[d_offset], &x, nbytes);
+ d_offset += nbytes;
+ }
+ }
+
+ void
+ header_buffer::add_field32(uint32_t data, int len, bool bs)
+ {
+ int nbytes = len/8;
+ if(d_buffer) {
+ uint32_t x = data;
+ if(!bs) {
+ volk_32u_byteswap(&x, 1);
+ x = x >> (32-len);
+ }
+ memcpy(&d_buffer[d_offset], &x, nbytes);
+ d_offset += nbytes;
+ }
+ }
+
+ void
+ header_buffer::add_field64(uint64_t data, int len, bool bs)
+ {
+ int nbytes = len/8;
+ if(d_buffer) {
+ uint64_t x = data;
+ if(!bs) {
+ volk_64u_byteswap(&x, 1);
+ x = x >> (64-len);
+ }
+ memcpy(&d_buffer[d_offset], &x, nbytes);
+ d_offset += nbytes;
+ }
+ }
+
+ void
+ header_buffer::insert_bit(int bit)
+ {
+ d_input.push_back(bit);
+ }
+
+ uint8_t
+ header_buffer::extract_field8(int pos, int len, bool bs)
+ {
+ if(len > 8) {
+ throw std::runtime_error("header_buffer::extract_field for "
+ "uint8_t length must be <= 8");
+ }
+
+ uint8_t field = 0x00;
+ std::vector<bool>::iterator itr;
+ for(itr = d_input.begin()+pos; itr != d_input.begin()+pos+len; itr++) {
+ field = (field << 1) | ((*itr) & 0x1);
+ }
+
+ return field;
+ }
+
+ uint16_t
+ header_buffer::extract_field16(int pos, int len, bool bs)
+ {
+ if(len > 16) {
+ throw std::runtime_error("header_buffer::extract_field for "
+ "uint16_t length must be <= 16");
+ }
+
+ uint16_t field = 0x0000;
+ std::vector<bool>::iterator itr;
+ for(itr = d_input.begin()+pos; itr != d_input.begin()+pos+len; itr++) {
+ field = (field << 1) | ((*itr) & 0x1);
+ }
+
+ if(bs) {
+ volk_16u_byteswap(&field, 1);
+ }
+
+ return field;
+ }
+
+ uint32_t
+ header_buffer::extract_field32(int pos, int len, bool bs)
+ {
+ if(len > 32) {
+ throw std::runtime_error("header_buffer::extract_field for "
+ "uint32_t length must be <= 32");
+ }
+
+ uint32_t field = 0x00000000;
+ std::vector<bool>::iterator itr;
+ for(itr = d_input.begin()+pos; itr != d_input.begin()+pos+len; itr++) {
+ field = (field << 1) | ((*itr) & 0x1);
+ }
+
+ if(bs) {
+ volk_32u_byteswap(&field, 1);
+ }
+
+ return field;
+ }
+
+ uint64_t
+ header_buffer::extract_field64(int pos, int len, bool bs)
+ {
+ if(len > 64) {
+ throw std::runtime_error("header_buffer::extract_field for "
+ "uint64_t length must be <= 64");
+ }
+
+ uint64_t field = 0x0000000000000000;
+ std::vector<bool>::iterator itr;
+ for(itr = d_input.begin()+pos; itr != d_input.begin()+pos+len; itr++) {
+ field = (field << 1) | ((*itr) & 0x1);
+ }
+
+ if(bs) {
+ volk_64u_byteswap(&field, 1);
+ }
+
+ return field;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/header_format_base.cc
b/gr-digital/lib/header_format_base.cc
new file mode 100644
index 0000000..a8d8c86
--- /dev/null
+++ b/gr-digital/lib/header_format_base.cc
@@ -0,0 +1,70 @@
+/* -*- c++ -*- */
+/* Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+#include <string.h>
+#include <volk/volk.h>
+#include <gnuradio/digital/header_format_base.h>
+#include <gnuradio/math.h>
+
+namespace gr {
+ namespace digital {
+
+ header_format_base::header_format_base()
+ {
+ enter_search();
+ configure_default_loggers(d_logger, d_debug_logger, "packet formatter");
+ }
+
+ header_format_base::~header_format_base()
+ {
+ }
+
+ size_t
+ header_format_base::header_nbytes() const
+ {
+ return header_nbits() / 8;
+ }
+
+ inline void
+ header_format_base::enter_search()
+ {
+ d_state = STATE_SYNC_SEARCH;
+ }
+
+ inline void
+ header_format_base::enter_have_sync()
+ {
+ d_state = STATE_HAVE_SYNC;
+ }
+
+ inline void
+ header_format_base::enter_have_header(int payload_len)
+ {
+ d_state = STATE_SYNC_SEARCH;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/header_format_counter.cc
b/gr-digital/lib/header_format_counter.cc
new file mode 100644
index 0000000..6244ec1
--- /dev/null
+++ b/gr-digital/lib/header_format_counter.cc
@@ -0,0 +1,120 @@
+/* -*- c++ -*- */
+/* Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+#include <iomanip>
+#include <string.h>
+#include <volk/volk.h>
+#include <gnuradio/digital/header_format_counter.h>
+#include <gnuradio/digital/header_buffer.h>
+#include <gnuradio/math.h>
+
+namespace gr {
+ namespace digital {
+
+ header_format_counter::sptr
+ header_format_counter::make(const std::string &access_code,
+ int threshold, int bps)
+ {
+ return header_format_counter::sptr
+ (new header_format_counter(access_code, threshold, bps));
+ }
+
+ header_format_counter::header_format_counter(const std::string
&access_code,
+ int threshold, int bps)
+ : header_format_default(access_code, threshold)
+ {
+ d_bps = bps;
+ d_counter = 0;
+ }
+
+ header_format_counter::~header_format_counter()
+ {
+ }
+
+ bool
+ header_format_counter::format(int nbytes_in,
+ const unsigned char *input,
+ pmt::pmt_t &output,
+ pmt::pmt_t &info)
+
+ {
+ uint8_t* bytes_out = (uint8_t*)volk_malloc(header_nbytes(),
+ volk_get_alignment());
+
+ header_buffer header(bytes_out);
+ header.add_field64(d_access_code, d_access_code_len);
+ header.add_field16((uint16_t)(nbytes_in));
+ header.add_field16((uint16_t)(nbytes_in));
+ header.add_field16((uint16_t)(d_bps));
+ header.add_field16((uint16_t)(d_counter));
+
+ // Package output data into a PMT vector
+ output = pmt::init_u8vector(header_nbytes(), bytes_out);
+
+ // Creating the output pmt copies data; free our own here.
+ volk_free(bytes_out);
+
+ d_counter++;
+
+ return true;
+ }
+
+ size_t
+ header_format_counter::header_nbits() const
+ {
+ return d_access_code_len + 8*4*sizeof(uint16_t);
+ }
+
+ bool
+ header_format_counter::header_ok()
+ {
+ // confirm that two copies of header info are identical
+ uint16_t len0 = d_hdr_reg.extract_field16(0);
+ uint16_t len1 = d_hdr_reg.extract_field16(16);
+ return (len0 ^ len1) == 0;
+ }
+
+ int
+ header_format_counter::header_payload()
+ {
+ uint16_t len = d_hdr_reg.extract_field16(0);
+ uint16_t bps = d_hdr_reg.extract_field16(32);
+ uint16_t counter = d_hdr_reg.extract_field16(48);
+
+ d_bps = bps;
+
+ d_info = pmt::make_dict();
+ d_info = pmt::dict_add(d_info, pmt::intern("payload symbols"),
+ pmt::from_long(8*len / d_bps));
+ d_info = pmt::dict_add(d_info, pmt::intern("bps"),
+ pmt::from_long(bps));
+ d_info = pmt::dict_add(d_info, pmt::intern("counter"),
+ pmt::from_long(counter));
+ return static_cast<int>(len);
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/header_format_crc.cc
b/gr-digital/lib/header_format_crc.cc
new file mode 100644
index 0000000..7594449
--- /dev/null
+++ b/gr-digital/lib/header_format_crc.cc
@@ -0,0 +1,161 @@
+/* -*- c++ -*- */
+/* Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <volk/volk.h>
+#include <gnuradio/digital/header_format_crc.h>
+#include <gnuradio/digital/header_buffer.h>
+
+namespace gr {
+ namespace digital {
+
+ header_format_crc::sptr
+ header_format_crc::make(const std::string &len_key_name,
+ const std::string &num_key_name)
+ {
+ return header_format_crc::sptr
+ (new header_format_crc(len_key_name, num_key_name));
+ }
+
+ header_format_crc::header_format_crc(const std::string &len_key_name,
+ const std::string &num_key_name)
+ : header_format_base(),
+ d_header_number(0)
+ {
+ d_len_key_name = pmt::intern(len_key_name);
+ d_num_key_name = pmt::intern(num_key_name);
+ }
+
+ header_format_crc::~header_format_crc()
+ {
+ }
+
+ bool
+ header_format_crc::format(int nbytes_in,
+ const unsigned char *input,
+ pmt::pmt_t &output,
+ pmt::pmt_t &info)
+ {
+ uint8_t* bytes_out = (uint8_t*)volk_malloc(header_nbytes(),
+ volk_get_alignment());
+ memset(bytes_out, 0, header_nbytes());
+
+ // Should this throw instead of mask if the payload is too big
+ // for 12-bit representation?
+ nbytes_in &= 0x0FFF;
+
+ d_crc_impl.reset();
+ d_crc_impl.process_bytes((void const *) &nbytes_in, 2);
+ d_crc_impl.process_bytes((void const *) &d_header_number, 2);
+ uint8_t crc = d_crc_impl();
+
+ // Form 2 12-bit items into 1 2-byte item
+ uint32_t concat = 0;
+ concat = (d_header_number << 12) | (nbytes_in);
+
+ header_buffer header(bytes_out);
+ header.add_field32(concat, 24, true);
+ header.add_field8(crc);
+
+ d_header_number++;
+ d_header_number &= 0x0FFF;
+
+ // Package output data into a PMT vector
+ output = pmt::init_u8vector(header_nbytes(), bytes_out);
+
+ // Creating the output pmt copies data; free our own here.
+ volk_free(bytes_out);
+
+ return true;
+ }
+
+ bool
+ header_format_crc::parse(int nbits_in,
+ const unsigned char *input,
+ std::vector<pmt::pmt_t> &info,
+ int &nbits_processed)
+ {
+ while(nbits_processed <= nbits_in) {
+ d_hdr_reg.insert_bit(input[nbits_processed++]);
+ if(d_hdr_reg.length() == header_nbits()) {
+ if(header_ok()) {
+ int payload_len = header_payload();
+ enter_have_header(payload_len);
+ info.push_back(d_info);
+ d_hdr_reg.clear();
+ return true;
+ }
+ else {
+ d_hdr_reg.clear();
+ return false;
+ }
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ size_t
+ header_format_crc::header_nbits() const
+ {
+ return 32;
+ }
+
+
+ bool
+ header_format_crc::header_ok()
+ {
+ uint32_t pkt = d_hdr_reg.extract_field32(0, 24, true);
+ uint16_t pktlen = static_cast<uint16_t>((pkt >> 8) & 0x0fff);
+ uint16_t pktnum = static_cast<uint16_t>((pkt >> 20) & 0x0fff);
+ uint8_t crc_rcvd = d_hdr_reg.extract_field8(24);
+
+ // Check CRC8
+ d_crc_impl.reset();
+ d_crc_impl.process_bytes((void const *) &pktlen, 2);
+ d_crc_impl.process_bytes((void const *) &pktnum, 2);
+ uint8_t crc_clcd = d_crc_impl();
+
+ return (crc_rcvd == crc_clcd);
+ }
+
+ int
+ header_format_crc::header_payload()
+ {
+ uint32_t pkt = d_hdr_reg.extract_field32(0, 24, true);
+ uint16_t pktlen = static_cast<uint16_t>((pkt >> 8) & 0x0fff);
+ uint16_t pktnum = static_cast<uint16_t>((pkt >> 20) & 0x0fff);
+
+ d_info = pmt::make_dict();
+ d_info = pmt::dict_add(d_info, d_len_key_name,
+ pmt::from_long(8*pktlen));
+ d_info = pmt::dict_add(d_info, d_num_key_name,
+ pmt::from_long(pktnum));
+ return static_cast<int>(pktlen);
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/header_format_default.cc
b/gr-digital/lib/header_format_default.cc
new file mode 100644
index 0000000..1b7a60e
--- /dev/null
+++ b/gr-digital/lib/header_format_default.cc
@@ -0,0 +1,222 @@
+/* -*- c++ -*- */
+/* Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+#include <string.h>
+#include <volk/volk.h>
+#include <gnuradio/digital/header_format_default.h>
+#include <gnuradio/math.h>
+
+namespace gr {
+ namespace digital {
+
+ header_format_default::sptr
+ header_format_default::make(const std::string &access_code,
+ int threshold)
+ {
+ return header_format_default::sptr
+ (new header_format_default(access_code, threshold));
+ }
+
+ header_format_default::header_format_default(const std::string
&access_code,
+ int threshold)
+ : header_format_base(),
+ d_data_reg(0), d_mask(0), d_threshold(0),
+ d_pkt_len(0), d_pkt_count(0), d_nbits(0)
+ {
+ if(!set_access_code(access_code)) {
+ throw std::runtime_error("header_format_default: Setting access code
failed");
+ }
+
+ set_threshold(threshold);
+ }
+
+ header_format_default::~header_format_default()
+ {
+ }
+
+ bool
+ header_format_default::set_access_code(const std::string &access_code)
+ {
+ d_access_code_len = access_code.length(); // # of bits in the
access code
+
+ if(access_code.size() > 64) {
+ return false;
+ }
+
+ // set len top bits to 1.
+ d_mask = ((~0ULL) >> (64 - d_access_code_len));
+
+ d_access_code = 0;
+ for(unsigned i = 0; i < d_access_code_len; i++) {
+ d_access_code = (d_access_code << 1) | (access_code[i] & 1);
+ }
+
+ return true;
+ }
+
+ unsigned long long
+ header_format_default::access_code() const
+ {
+ return d_access_code;
+ }
+
+ void
+ header_format_default::set_threshold(unsigned int thresh)
+ {
+ if(d_threshold > d_access_code_len) {
+ throw std::runtime_error("header_format_default: Cannot set threshold
" \
+ "larger than the access code length.");
+ }
+ d_threshold = thresh;
+ }
+
+ unsigned int
+ header_format_default::threshold() const
+ {
+ return d_threshold;
+ }
+
+ bool
+ header_format_default::format(int nbytes_in,
+ const unsigned char *input,
+ pmt::pmt_t &output,
+ pmt::pmt_t &info)
+ {
+ uint8_t* bytes_out = (uint8_t*)volk_malloc(header_nbytes(),
+ volk_get_alignment());
+
+ header_buffer header(bytes_out);
+ header.add_field64(d_access_code, d_access_code_len);
+ header.add_field16((uint16_t)(nbytes_in));
+ header.add_field16((uint16_t)(nbytes_in));
+
+ // Package output data into a PMT vector
+ output = pmt::init_u8vector(header_nbytes(), bytes_out);
+
+ // Creating the output pmt copies data; free our own here.
+ volk_free(bytes_out);
+
+ return true;
+ }
+
+ bool
+ header_format_default::parse(int nbits_in,
+ const unsigned char *input,
+ std::vector<pmt::pmt_t> &info,
+ int &nbits_processed)
+ {
+ nbits_processed = 0;
+
+ while(nbits_processed < nbits_in) {
+ switch(d_state) {
+ case STATE_SYNC_SEARCH: // Look for the access code correlation
+ while(nbits_processed < nbits_in) {
+ // shift in new data
+ d_data_reg = (d_data_reg << 1) | ((input[nbits_processed++]) &
0x1);
+
+ // compute hamming distance between desired access code and
current data
+ uint64_t wrong_bits = 0;
+ uint64_t nwrong = d_threshold+1;
+
+ wrong_bits = (d_data_reg ^ d_access_code) & d_mask;
+ volk_64u_popcnt(&nwrong, wrong_bits);
+
+ if(nwrong <= d_threshold) {
+ enter_have_sync();
+ break;
+ }
+ }
+ break;
+
+ case STATE_HAVE_SYNC:
+ while(nbits_processed <= nbits_in) { // Shift bits one at a time
into header
+ d_hdr_reg.insert_bit(input[nbits_processed++]);
+ if(d_hdr_reg.length() == (header_nbits()-d_access_code_len)) {
+
+ // we have a full header, check to see if it has been received
properly
+ if(header_ok()) {
+ int payload_len = header_payload();
+ enter_have_header(payload_len);
+ info.push_back(d_info);
+ return true;
+ }
+ else {
+ enter_search(); // bad header
+ return false;
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return false;
+ }
+
+ size_t
+ header_format_default::header_nbits() const
+ {
+ return d_access_code_len + 8*2*sizeof(uint16_t);
+ }
+
+ inline void
+ header_format_default::enter_have_sync()
+ {
+ d_state = STATE_HAVE_SYNC;
+ d_hdr_reg.clear();
+ }
+
+ inline void
+ header_format_default::enter_have_header(int payload_len)
+ {
+ d_state = STATE_SYNC_SEARCH;
+ d_pkt_len = payload_len;
+ d_pkt_count = 0;
+ }
+
+ bool
+ header_format_default::header_ok()
+ {
+ // confirm that two copies of header info are identical
+ uint16_t len0 = d_hdr_reg.extract_field16(0, 16);
+ uint16_t len1 = d_hdr_reg.extract_field16(16, 16);
+ return (len0 ^ len1) == 0;
+ }
+
+ int
+ header_format_default::header_payload()
+ {
+ uint16_t len = d_hdr_reg.extract_field16(0, 16);
+
+ d_info = pmt::make_dict();
+ d_info = pmt::dict_add(d_info, pmt::intern("payload symbols"),
+ pmt::from_long(8*len));
+ return static_cast<int>(len);
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/header_format_ofdm.cc
b/gr-digital/lib/header_format_ofdm.cc
new file mode 100644
index 0000000..acaf53b
--- /dev/null
+++ b/gr-digital/lib/header_format_ofdm.cc
@@ -0,0 +1,180 @@
+/* -*- c++ -*- */
+/* Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <volk/volk.h>
+#include <gnuradio/digital/header_format_ofdm.h>
+#include <gnuradio/digital/header_buffer.h>
+#include <gnuradio/digital/lfsr.h>
+
+namespace gr {
+ namespace digital {
+
+ header_format_ofdm::sptr
+ header_format_ofdm::make(const std::vector<std::vector<int> >
&occupied_carriers,
+ int n_syms,
+ const std::string &len_key_name,
+ const std::string &frame_key_name,
+ const std::string &num_key_name,
+ int bits_per_header_sym,
+ int bits_per_payload_sym,
+ bool scramble_header)
+ {
+ return header_format_ofdm::sptr
+ (new header_format_ofdm(occupied_carriers, n_syms,
+ len_key_name, frame_key_name, num_key_name,
+ bits_per_header_sym,
+ bits_per_payload_sym,
+ scramble_header));
+ }
+
+ header_format_ofdm::header_format_ofdm(const std::vector<std::vector<int>
> &occupied_carriers,
+ int n_syms,
+ const std::string &len_key_name,
+ const std::string &frame_key_name,
+ const std::string &num_key_name,
+ int bits_per_header_sym,
+ int bits_per_payload_sym,
+ bool scramble_header)
+ : header_format_crc(len_key_name, num_key_name),
+ d_frame_key_name(pmt::intern(frame_key_name)),
+ d_occupied_carriers(occupied_carriers),
+ d_bits_per_payload_sym(bits_per_payload_sym)
+ {
+ d_header_len = 0;
+ for(int i = 0; i < n_syms; i++) {
+ d_header_len += occupied_carriers[i].size();
+ }
+
+ d_syms_per_set = 0;
+ for(unsigned i = 0; i < d_occupied_carriers.size(); i++) {
+ d_syms_per_set += d_occupied_carriers[i].size();
+ }
+
+ // Init scrambler mask
+ d_scramble_mask = std::vector<uint8_t>(header_nbits(), 0);
+ if(scramble_header) {
+ // These are just random values which already have OK PAPR:
+ gr::digital::lfsr shift_reg(0x8a, 0x6f, 7);
+ for(size_t i = 0; i < header_nbytes(); i++) {
+ for(int k = 0; k < bits_per_header_sym; k++) {
+ d_scramble_mask[i] ^= shift_reg.next_bit() << k;
+ }
+ }
+ }
+ }
+
+ header_format_ofdm::~header_format_ofdm()
+ {
+ }
+
+ bool
+ header_format_ofdm::format(int nbytes_in,
+ const unsigned char *input,
+ pmt::pmt_t &output,
+ pmt::pmt_t &info)
+ {
+ bool ret_val = header_format_crc::format(nbytes_in, input,
+ output, info);
+
+ //size_t len;
+ //uint8_t *out = pmt::u8vector_writable_elements(output, len);
+ //for(size_t i = 0; i < len; i++) {
+ // out[i] ^= d_scramble_mask[i];
+ //}
+
+ return ret_val;
+ }
+
+ bool
+ header_format_ofdm::parse(int nbits_in,
+ const unsigned char *input,
+ std::vector<pmt::pmt_t> &info,
+ int &nbits_processed)
+ {
+ int index = 0;
+ while(nbits_processed <= nbits_in) {
+ d_hdr_reg.insert_bit(input[nbits_processed++] ^
d_scramble_mask[index++]);
+ if(d_hdr_reg.length() == header_nbits()) {
+ if(header_ok()) {
+ int payload_len = header_payload();
+ enter_have_header(payload_len);
+ info.push_back(d_info);
+ d_hdr_reg.clear();
+ return true;
+ }
+ else {
+ d_hdr_reg.clear();
+ return false;
+ }
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ size_t
+ header_format_ofdm::header_nbits() const
+ {
+ return d_header_len;
+ }
+
+ int
+ header_format_ofdm::header_payload()
+ {
+ uint32_t pkt = d_hdr_reg.extract_field32(0, 24, true);
+ uint16_t pktlen = static_cast<uint16_t>((pkt >> 8) & 0x0fff);
+ uint16_t pktnum = static_cast<uint16_t>((pkt >> 20) & 0x0fff);
+
+ // Convert num bytes to num complex symbols in payload
+ pktlen *= 8;
+ uint16_t pldlen = pktlen / d_bits_per_payload_sym;
+ if(pktlen % d_bits_per_payload_sym) {
+ pldlen++;
+ }
+
+ // frame_len = # of OFDM symbols in this frame
+ int framelen = pldlen / d_syms_per_set;
+ int k = 0;
+ int i = framelen * d_syms_per_set;
+ while(i < pldlen) {
+ framelen++;
+ //i += d_occupied_carriers[k++].size();
+ i += d_occupied_carriers[k].size();
+ }
+
+ d_info = pmt::make_dict();
+ d_info = pmt::dict_add(d_info, d_len_key_name,
+ pmt::from_long(pldlen));
+ d_info = pmt::dict_add(d_info, d_num_key_name,
+ pmt::from_long(pktnum));
+ d_info = pmt::dict_add(d_info, d_frame_key_name,
+ pmt::from_long(framelen));
+ return static_cast<int>(pldlen);
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/packet_header_ofdm.cc
b/gr-digital/lib/packet_header_ofdm.cc
index 7a95586..22d62df 100644
--- a/gr-digital/lib/packet_header_ofdm.cc
+++ b/gr-digital/lib/packet_header_ofdm.cc
@@ -1,18 +1,18 @@
/* -*- c++ -*- */
/* Copyright 2012 Free Software Foundation, Inc.
- *
+ *
* This file is part of GNU Radio
- *
+ *
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
- *
+ *
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
@@ -148,4 +148,3 @@ namespace gr {
} /* namespace digital */
} /* namespace gr */
-
diff --git a/gr-digital/lib/protocol_formatter_async_impl.cc
b/gr-digital/lib/protocol_formatter_async_impl.cc
new file mode 100644
index 0000000..83a2eed
--- /dev/null
+++ b/gr-digital/lib/protocol_formatter_async_impl.cc
@@ -0,0 +1,94 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <volk/volk.h>
+#include <gnuradio/io_signature.h>
+#include "protocol_formatter_async_impl.h"
+#include <stdio.h>
+
+namespace gr {
+ namespace digital {
+
+ protocol_formatter_async::sptr
+ protocol_formatter_async::make(const header_format_base::sptr &format)
+ {
+ return gnuradio::get_initial_sptr
+ (new protocol_formatter_async_impl(format));
+ }
+
+ protocol_formatter_async_impl::protocol_formatter_async_impl(const
header_format_base::sptr &format)
+ : block("protocol_formatter_async",
+ io_signature::make(0, 0, 0),
+ io_signature::make(0, 0, 0))
+ {
+ d_format = format;
+
+ d_in_port = pmt::mp("in");
+ d_hdr_port = pmt::mp("header");
+ d_pld_port = pmt::mp("payload");
+
+ message_port_register_in(d_in_port);
+ message_port_register_out(d_hdr_port);
+ message_port_register_out(d_pld_port);
+
+ set_msg_handler(d_in_port,
+ boost::bind(&protocol_formatter_async_impl::append, this
,_1) );
+ }
+
+ protocol_formatter_async_impl::~protocol_formatter_async_impl()
+ {
+ }
+
+ void
+ protocol_formatter_async_impl::append(pmt::pmt_t msg)
+ {
+ // extract input pdu
+ pmt::pmt_t meta(pmt::car(msg));
+ pmt::pmt_t input(pmt::cdr(msg));
+ pmt::pmt_t header, output;
+
+ size_t pkt_len = 0;
+ const uint8_t* bytes_in = pmt::u8vector_elements(input, pkt_len);
+
+ // Pad the payload with 0's
+ uint8_t* payload = (uint8_t*)volk_malloc(pkt_len*sizeof(uint8_t),
+ volk_get_alignment());
+ memcpy(payload, bytes_in, pkt_len*sizeof(uint8_t));
+ output = pmt::init_u8vector(pkt_len, payload);
+ volk_free(payload);
+
+ // Build the header from the input, metadata, and format
+ d_format->format(pkt_len, bytes_in, header, meta);
+
+ // Package and publish
+ pmt::pmt_t hdr_pdu = pmt::cons(meta, header);
+ pmt::pmt_t pld_pdu = pmt::cons(meta, output);
+ message_port_pub(d_hdr_port, hdr_pdu);
+ message_port_pub(d_pld_port, pld_pdu);
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/protocol_formatter_async_impl.h
b/gr-digital/lib/protocol_formatter_async_impl.h
new file mode 100644
index 0000000..79c80de
--- /dev/null
+++ b/gr-digital/lib/protocol_formatter_async_impl.h
@@ -0,0 +1,50 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_PROTOCOL_FORMATTER_ASYNC_IMPL_H
+#define INCLUDED_DIGITAL_PROTOCOL_FORMATTER_ASYNC_IMPL_H
+
+#include <gnuradio/digital/protocol_formatter_async.h>
+
+namespace gr {
+ namespace digital {
+
+ class protocol_formatter_async_impl
+ : public protocol_formatter_async
+ {
+ private:
+ header_format_base::sptr d_format;
+
+ pmt::pmt_t d_in_port;
+ pmt::pmt_t d_hdr_port, d_pld_port;
+
+ void append(pmt::pmt_t msg);
+
+ public:
+ protocol_formatter_async_impl(const header_format_base::sptr &format);
+ ~protocol_formatter_async_impl();
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PROTOCOL_FORMATTER_ASYNC_IMPL_H */
diff --git a/gr-digital/lib/protocol_formatter_bb_impl.cc
b/gr-digital/lib/protocol_formatter_bb_impl.cc
new file mode 100644
index 0000000..fcf2f66
--- /dev/null
+++ b/gr-digital/lib/protocol_formatter_bb_impl.cc
@@ -0,0 +1,118 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <volk/volk.h>
+#include <gnuradio/io_signature.h>
+#include "protocol_formatter_bb_impl.h"
+#include <stdio.h>
+
+namespace gr {
+ namespace digital {
+
+ protocol_formatter_bb::sptr
+ protocol_formatter_bb::make(const header_format_base::sptr &format,
+ const std::string &len_tag_key)
+ {
+ return gnuradio::get_initial_sptr
+ (new protocol_formatter_bb_impl(format, len_tag_key));
+ }
+
+ protocol_formatter_bb_impl::protocol_formatter_bb_impl(const
header_format_base::sptr &format,
+ const std::string
&len_tag_key)
+ : tagged_stream_block("protocol_formatter_bb",
+ io_signature::make(1, 1, sizeof(char)),
+ io_signature::make(1, 1, sizeof(char)),
+ len_tag_key),
+ d_format(format)
+ {
+ set_output_multiple(d_format->header_nbytes());
+
+ // This is the worst case rate, because we don't know the true value, of
course
+ set_relative_rate(d_format->header_nbytes());
+ set_tag_propagation_policy(TPP_DONT);
+ }
+
+ protocol_formatter_bb_impl::~protocol_formatter_bb_impl()
+ {
+ }
+
+ void
+ protocol_formatter_bb_impl::set_header_format(header_format_base::sptr
&format)
+ {
+ gr::thread::scoped_lock guard(d_setlock);
+ d_format = format;
+ }
+
+ int
+ protocol_formatter_bb_impl::work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr::thread::scoped_lock guard(d_setlock);
+ unsigned char *out = (unsigned char *) output_items[0];
+ const unsigned char *in = (const unsigned char *) input_items[0];
+
+ // Not really sure what to do with these tags; extract them and
+ // plug them into the info dictionary?
+ //std::vector<tag_t> tags;
+ //get_tags_in_window(tags, 0, 0, ninput_items[0]);
+
+ pmt::pmt_t pmt_out;
+ pmt::pmt_t info = pmt::PMT_NIL;
+ if(!d_format->format(ninput_items[0], in, pmt_out, info)) {
+ GR_LOG_FATAL(d_logger, boost::format("header format returned false "
+ "(this shouldn't happen).
Offending "
+ "header started at %1%") %
nitems_read(0));
+ throw std::runtime_error("header format returned false.");
+ }
+
+ size_t len;
+ const uint8_t *data = pmt::u8vector_elements(pmt_out, len);
+ if(len != d_format->header_nbytes()) {
+ throw std::runtime_error("Header format got wrong size header");
+ }
+ memcpy(out, data, len);
+
+ if(pmt::is_dict(info)) {
+ std::vector<tag_t> mtags;
+ pmt::pmt_t mkeys = pmt::dict_keys(info);
+ pmt::pmt_t mvals = pmt::dict_values(info);
+ for(size_t i = 0; i < pmt::length(mkeys); i++) {
+ tag_t tag;
+ tag.offset = nitems_written(0);
+ tag.key = pmt::nth(i, mkeys);
+ tag.value = pmt::nth(i, mvals);
+ tag.srcid = alias_pmt();
+ add_item_tag(0, tag);
+ }
+ }
+
+ return len;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/protocol_formatter_bb_impl.h
b/gr-digital/lib/protocol_formatter_bb_impl.h
new file mode 100644
index 0000000..c7c86e4
--- /dev/null
+++ b/gr-digital/lib/protocol_formatter_bb_impl.h
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_PROTOCOL_FORMATTER_BB_IMPL_H
+#define INCLUDED_DIGITAL_PROTOCOL_FORMATTER_BB_IMPL_H
+
+#include <gnuradio/digital/protocol_formatter_bb.h>
+
+namespace gr {
+ namespace digital {
+
+ class protocol_formatter_bb_impl : public protocol_formatter_bb
+ {
+ private:
+ header_format_base::sptr d_format;
+
+ public:
+ protocol_formatter_bb_impl(const header_format_base::sptr &format,
+ const std::string &len_tag_key);
+ ~protocol_formatter_bb_impl();
+
+ void set_header_format(header_format_base::sptr &format);
+
+ void remove_length_tags(const std::vector<std::vector<tag_t> > &tags) {};
+ int calculate_output_stream_length(const gr_vector_int &ninput_items) {
+ return d_format->header_nbytes(); };
+
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PROTOCOL_FORMATTER_BB_IMPL_H */
diff --git a/gr-digital/lib/protocol_parser_b_impl.cc
b/gr-digital/lib/protocol_parser_b_impl.cc
new file mode 100644
index 0000000..642fcae
--- /dev/null
+++ b/gr-digital/lib/protocol_parser_b_impl.cc
@@ -0,0 +1,83 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "protocol_parser_b_impl.h"
+#include <gnuradio/io_signature.h>
+#include <stdexcept>
+#include <volk/volk.h>
+#include <iostream>
+
+namespace gr {
+ namespace digital {
+
+ protocol_parser_b::sptr
+ protocol_parser_b::make(const header_format_base::sptr &format)
+ {
+ return gnuradio::get_initial_sptr
+ (new protocol_parser_b_impl(format));
+ }
+
+
+ protocol_parser_b_impl::protocol_parser_b_impl(const
header_format_base::sptr &format)
+ : sync_block("protocol_parser_b",
+ io_signature::make(1, 1, sizeof(char)),
+ io_signature::make(0, 0, 0))
+ {
+ d_format = format;
+
+ d_out_port = pmt::mp("info");
+ message_port_register_out(d_out_port);
+ }
+
+ protocol_parser_b_impl::~protocol_parser_b_impl()
+ {
+ }
+
+ int
+ protocol_parser_b_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char*)input_items[0];
+
+ int count = 0;
+ std::vector<pmt::pmt_t> info;
+ bool ret = d_format->parse(noutput_items, in, info, count);
+
+ if(ret) {
+ for(size_t i = 0; i < info.size(); i++) {
+ message_port_pub(d_out_port, info[i]);
+ }
+ }
+ else {
+ message_port_pub(d_out_port, pmt::PMT_F);
+ }
+
+ return count;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/protocol_parser_b_impl.h
b/gr-digital/lib/protocol_parser_b_impl.h
new file mode 100644
index 0000000..7b09313
--- /dev/null
+++ b/gr-digital/lib/protocol_parser_b_impl.h
@@ -0,0 +1,52 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_PROTOCOL_PARSER_B_IMPL_H
+#define INCLUDED_DIGITAL_PROTOCOL_PARSER_B_IMPL_H
+
+#include <gnuradio/digital/protocol_parser_b.h>
+
+namespace gr {
+ namespace digital {
+
+ class protocol_parser_b_impl : public protocol_parser_b
+ {
+ private:
+ header_format_base::sptr d_format;
+ pmt::pmt_t d_out_port;
+
+ public:
+ protocol_parser_b_impl(const header_format_base::sptr &format);
+ ~protocol_parser_b_impl();
+
+ void set_threshold(unsigned int thresh);
+ unsigned int threshold() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PROTOCOL_PARSER_B_IMPL_H */
diff --git a/gr-digital/swig/packet_header.i b/gr-digital/lib/qa_digital.cc
similarity index 57%
copy from gr-digital/swig/packet_header.i
copy to gr-digital/lib/qa_digital.cc
index 7c06d19..2888d21 100644
--- a/gr-digital/swig/packet_header.i
+++ b/gr-digital/lib/qa_digital.cc
@@ -1,34 +1,41 @@
-/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
- *
+ * Copyright 2014 Free Software Foundation, Inc.
+ *
* This file is part of GNU Radio
- *
+ *
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
- *
+ *
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
-%template(packet_header_default_sptr)
boost::shared_ptr<gr::digital::packet_header_default>;
-%pythoncode %{
-packet_header_default_sptr.__repr__ = lambda self: "<packet_header_default>"
-packet_header_default = packet_header_default .make;
-%}
+/*
+ * This class gathers together all the test cases for the gr-digital
+ * directory into a single test suite. As you create new test cases,
+ * add them here.
+ */
+
+#include "qa_digital.h"
+#include "qa_header_format.h"
+#include "qa_header_buffer.h"
+
+CppUnit::TestSuite *
+qa_digital::suite()
+{
+ CppUnit::TestSuite *s = new CppUnit::TestSuite("gr-digital");
-%template(packet_header_ofdm_sptr)
boost::shared_ptr<gr::digital::packet_header_ofdm>;
-%pythoncode %{
-packet_header_ofdm_sptr.__repr__ = lambda self: "<packet_header_ofdm>"
-packet_header_ofdm = packet_header_ofdm .make;
-%}
+ s->addTest(qa_header_format::suite());
+ s->addTest(qa_header_buffer::suite());
+ return s;
+}
diff --git a/gr-digital/swig/packet_header.i b/gr-digital/lib/qa_digital.h
similarity index 59%
copy from gr-digital/swig/packet_header.i
copy to gr-digital/lib/qa_digital.h
index 7c06d19..c5f3592 100644
--- a/gr-digital/swig/packet_header.i
+++ b/gr-digital/lib/qa_digital.h
@@ -1,34 +1,38 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
- *
+ * Copyright 2014 Free Software Foundation, Inc.
+ *
* This file is part of GNU Radio
- *
+ *
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
- *
+ *
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
-%template(packet_header_default_sptr)
boost::shared_ptr<gr::digital::packet_header_default>;
-%pythoncode %{
-packet_header_default_sptr.__repr__ = lambda self: "<packet_header_default>"
-packet_header_default = packet_header_default .make;
-%}
+#ifndef _QA_GR_DIGITAL_H_
+#define _QA_GR_DIGITAL_H_
-%template(packet_header_ofdm_sptr)
boost::shared_ptr<gr::digital::packet_header_ofdm>;
-%pythoncode %{
-packet_header_ofdm_sptr.__repr__ = lambda self: "<packet_header_ofdm>"
-packet_header_ofdm = packet_header_ofdm .make;
-%}
+#include <gnuradio/attributes.h>
+#include <cppunit/TestSuite.h>
+//! collect all the tests for the gr-digital directory
+
+class __GR_ATTR_EXPORT qa_digital
+{
+ public:
+ //! return suite of tests for all of gr-digital directory
+ static CppUnit::TestSuite *suite();
+};
+
+#endif /* _QA_GR_DIGITAL_H_ */
diff --git a/gr-digital/lib/qa_header_buffer.cc
b/gr-digital/lib/qa_header_buffer.cc
new file mode 100644
index 0000000..321e901
--- /dev/null
+++ b/gr-digital/lib/qa_header_buffer.cc
@@ -0,0 +1,364 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <volk/volk.h>
+#include <gnuradio/attributes.h>
+
+#include <stdio.h>
+#include <cppunit/TestAssert.h>
+
+#include "qa_header_buffer.h"
+#include <gnuradio/digital/header_buffer.h>
+
+void
+qa_header_buffer::test_add8()
+{
+ size_t len = sizeof(uint8_t);
+ uint8_t *buf = (uint8_t*)volk_malloc(len, volk_get_alignment());
+
+ gr::digital::header_buffer header(buf);
+ header.add_field8(0xAF);
+
+ CPPUNIT_ASSERT_EQUAL(len, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[0]);
+
+ header.clear();
+ CPPUNIT_ASSERT_EQUAL((size_t)0, header.length());
+
+ volk_free(buf);
+}
+
+void
+qa_header_buffer::test_add16()
+{
+ size_t len = sizeof(uint16_t);
+ uint8_t *buf = (uint8_t*)volk_malloc(len, volk_get_alignment());
+
+ uint16_t data = 0xAF5C;
+
+ gr::digital::header_buffer header(buf);
+ header.add_field16(data);
+
+ // Test standard add of a uint16
+ CPPUNIT_ASSERT_EQUAL(len, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[0]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[1]);
+
+ // Clear; test to make sure it's clear
+ header.clear();
+ CPPUNIT_ASSERT_EQUAL((size_t)0, header.length());
+
+ // Test adding some subset of bits (must be a byte boundary)
+ header.add_field16(data, 8);
+ CPPUNIT_ASSERT_EQUAL((size_t)1, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[0]);
+ header.clear();
+
+ // Test adding and byte swapping
+ header.add_field16(data, 16, true);
+ CPPUNIT_ASSERT_EQUAL((size_t)2, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[0]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[1]);
+ header.clear();
+
+ // Test adding some subset of bits and byte swapping
+ header.add_field16(data, 8, true);
+ CPPUNIT_ASSERT_EQUAL((size_t)1, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[0]);
+ header.clear();
+
+ volk_free(buf);
+}
+
+void
+qa_header_buffer::test_add32()
+{
+ size_t len = sizeof(uint32_t);
+ uint8_t *buf = (uint8_t*)volk_malloc(len, volk_get_alignment());
+
+ uint32_t data = 0xAF5C7654;
+
+ gr::digital::header_buffer header(buf);
+ header.add_field32(data);
+
+ // Test standard add of a uint32
+ CPPUNIT_ASSERT_EQUAL(len, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[0]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[1]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[2]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[3]);
+
+ // Clear; test to make sure it's clear
+ header.clear();
+ CPPUNIT_ASSERT_EQUAL((size_t)0, header.length());
+
+ // Test adding some subset of bits (must be a byte boundary)
+ header.add_field32(data, 8);
+ CPPUNIT_ASSERT_EQUAL((size_t)1, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[0]);
+ header.clear();
+
+ // Test adding and byte swapping
+ header.add_field32(data, 32, true);
+ CPPUNIT_ASSERT_EQUAL((size_t)4, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[0]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[1]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[2]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[3]);
+ header.clear();
+
+ // Test adding some subset of bits and byte swapping
+ header.add_field32(data, 24, true);
+ CPPUNIT_ASSERT_EQUAL((size_t)3, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[0]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[1]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[2]);
+ header.clear();
+
+ volk_free(buf);
+}
+
+void
+qa_header_buffer::test_add64()
+{
+ size_t len = sizeof(uint64_t);
+ uint8_t *buf = (uint8_t*)volk_malloc(len, volk_get_alignment());
+
+ uint64_t data = 0xAF5C765432104567;
+
+ gr::digital::header_buffer header(buf);
+ header.add_field64(data);
+
+ // Test standard add of a uint64
+ CPPUNIT_ASSERT_EQUAL(len, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[0]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[1]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[2]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[3]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x32, header.header()[4]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x10, header.header()[5]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[6]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x67, header.header()[7]);
+
+ // Clear; test to make sure it's clear
+ header.clear();
+ CPPUNIT_ASSERT_EQUAL((size_t)0, header.length());
+
+ // Test adding some subset of bits (must be a byte boundary)
+ header.add_field64(data, 48);
+ CPPUNIT_ASSERT_EQUAL((size_t)6, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[0]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[1]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x32, header.header()[2]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x10, header.header()[3]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[4]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x67, header.header()[5]);
+ header.clear();
+
+ // Test adding and byte swapping
+ header.add_field64(data, 64, true);
+ CPPUNIT_ASSERT_EQUAL((size_t)8, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x67, header.header()[0]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[1]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x10, header.header()[2]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x32, header.header()[3]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[4]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[5]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x5C, header.header()[6]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xAF, header.header()[7]);
+ header.clear();
+
+ // Test adding some subset of bits and byte swapping
+ header.add_field64(data, 40, true);
+ CPPUNIT_ASSERT_EQUAL((size_t)5, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x67, header.header()[0]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[1]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x10, header.header()[2]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x32, header.header()[3]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[4]);
+ header.clear();
+
+ volk_free(buf);
+}
+
+void
+qa_header_buffer::test_add_many()
+{
+ size_t len = (32+64+8+16+32)/8;
+ uint8_t *buf = (uint8_t*)volk_malloc(len, volk_get_alignment());
+
+ gr::digital::header_buffer header(buf);
+ header.add_field32(0x01234567);
+ header.add_field64(0x89ABCDEFFEDCBA98);
+ header.add_field8(0x76);
+ header.add_field16(0x5432);
+ header.add_field32(0x10012345);
+
+ CPPUNIT_ASSERT_EQUAL(len, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x01, header.header()[0]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x23, header.header()[1]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[2]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x67, header.header()[3]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x89, header.header()[4]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xAB, header.header()[5]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xCD, header.header()[6]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xEF, header.header()[7]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xFE, header.header()[8]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xDC, header.header()[9]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0xBA, header.header()[10]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x98, header.header()[11]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x76, header.header()[12]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x54, header.header()[13]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x32, header.header()[14]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x10, header.header()[15]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x01, header.header()[16]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x23, header.header()[17]);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x45, header.header()[18]);
+}
+
+void
+qa_header_buffer::test_extract8()
+{
+ gr::digital::header_buffer header;
+
+ uint64_t data = 0x0123456701234567;
+
+ // Packed format: 0x80C4A2E680C4A2E6
+
+ volk_64u_byteswap(&data, 1);
+ for(int i = 0; i < 64; i++) {
+ header.insert_bit((data >> i) & 0x01);
+ }
+
+ uint8_t x0 = header.extract_field8(0);
+ uint8_t x1 = header.extract_field8(12, 8);
+ uint8_t x2 = header.extract_field8(12, 4);
+
+ CPPUNIT_ASSERT_EQUAL((size_t)64, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x80, x0);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x4A, x1);
+ CPPUNIT_ASSERT_EQUAL((uint8_t)0x04, x2);
+}
+
+void
+qa_header_buffer::test_extract16()
+{
+ gr::digital::header_buffer header;
+
+ uint64_t data = 0x0123456701234567;
+
+ // Packed format: 0x80C4A2E680C4A2E6
+
+ volk_64u_byteswap(&data, 1);
+ for(int i = 0; i < 64; i++) {
+ header.insert_bit((data >> i) & 0x01);
+ }
+
+ uint16_t x0 = header.extract_field16(0);
+ uint16_t x1 = header.extract_field16(12, 16);
+ uint16_t x2 = header.extract_field16(12, 12);
+
+ CPPUNIT_ASSERT_EQUAL((size_t)64, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint16_t)0x80C4, x0);
+ CPPUNIT_ASSERT_EQUAL((uint16_t)0x4A2E, x1);
+ CPPUNIT_ASSERT_EQUAL((uint16_t)0x04A2, x2);
+}
+
+void
+qa_header_buffer::test_extract32()
+{
+ gr::digital::header_buffer header;
+
+ uint64_t data = 0x0123456701234567;
+
+ // Packed format: 0x80C4A2E680C4A2E6
+
+ volk_64u_byteswap(&data, 1);
+ for(int i = 0; i < 64; i++) {
+ header.insert_bit((data >> i) & 0x01);
+ }
+
+ uint32_t x0 = header.extract_field32(0);
+ uint32_t x1 = header.extract_field32(12, 32);
+ uint32_t x2 = header.extract_field32(12, 24);
+
+ CPPUNIT_ASSERT_EQUAL((size_t)64, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint32_t)0x80C4A2E6, x0);
+ CPPUNIT_ASSERT_EQUAL((uint32_t)0x4A2E680C, x1);
+ CPPUNIT_ASSERT_EQUAL((uint32_t)0x004A2E68, x2);
+}
+
+void
+qa_header_buffer::test_extract64()
+{
+ gr::digital::header_buffer header;
+
+ uint64_t data = 0x0123456701234567;
+
+ // Packed format: 0x80C4A2E680C4A2E6
+
+ volk_64u_byteswap(&data, 1);
+ for(int i = 0; i < 64; i++) {
+ header.insert_bit((data >> i) & 0x01);
+ }
+
+ uint64_t x0 = header.extract_field64(0);
+ uint64_t x1 = header.extract_field64(0, 32);
+ uint64_t x2 = header.extract_field64(0, 44);
+
+ CPPUNIT_ASSERT_EQUAL((size_t)64, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint64_t)0x80C4A2E680C4A2E6, x0);
+ CPPUNIT_ASSERT_EQUAL((uint64_t)0x0000000080C4A2E6, x1);
+ CPPUNIT_ASSERT_EQUAL((uint64_t)0x0000080C4A2E680C, x2);
+}
+
+void
+qa_header_buffer::test_extract_many()
+{
+ gr::digital::header_buffer header;
+
+ uint64_t data = 0x0123456701234567;
+
+ // Packed format: 0x80C4A2E680C4A2E6
+
+ volk_64u_byteswap(&data, 1);
+ for(int i = 0; i < 64; i++) {
+ header.insert_bit((data >> i) & 0x01);
+ }
+
+ uint64_t x0 = header.extract_field64(0);
+ uint16_t x1 = header.extract_field16(28, 12);
+ uint32_t x2 = header.extract_field32(40, 21);
+ uint16_t x3 = header.extract_field16(1, 12);
+ uint8_t x4 = header.extract_field8 (7, 5);
+
+ CPPUNIT_ASSERT_EQUAL((size_t)64, header.length());
+ CPPUNIT_ASSERT_EQUAL((uint64_t)0x80C4A2E680C4A2E6, x0);
+ CPPUNIT_ASSERT_EQUAL((uint16_t)0x0680, x1);
+ CPPUNIT_ASSERT_EQUAL((uint32_t)0x0018945C, x2);
+ CPPUNIT_ASSERT_EQUAL((uint16_t)0x0018, x3);
+ CPPUNIT_ASSERT_EQUAL((uint8_t) 0x0C, x4);
+}
diff --git a/gr-digital/lib/qa_header_buffer.h
b/gr-digital/lib/qa_header_buffer.h
new file mode 100644
index 0000000..48ab086
--- /dev/null
+++ b/gr-digital/lib/qa_header_buffer.h
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _QA_DIGITAL_HEADER_BUFFER_H_
+#define _QA_DIGITAL_HEADER_BUFFER_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_header_buffer : public CppUnit::TestCase
+{
+ CPPUNIT_TEST_SUITE(qa_header_buffer);
+ CPPUNIT_TEST(test_add8);
+ CPPUNIT_TEST(test_add16);
+ CPPUNIT_TEST(test_add32);
+ CPPUNIT_TEST(test_add64);
+ CPPUNIT_TEST(test_add_many);
+
+ CPPUNIT_TEST(test_extract8);
+ CPPUNIT_TEST(test_extract16);
+ CPPUNIT_TEST(test_extract32);
+ CPPUNIT_TEST(test_extract64);
+ CPPUNIT_TEST(test_extract_many);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void test_add8();
+ void test_add16();
+ void test_add32();
+ void test_add64();
+ void test_add_many();
+
+ void test_extract8();
+ void test_extract16();
+ void test_extract32();
+ void test_extract64();
+ void test_extract_many();
+};
+
+#endif /* _QA_DIGITAL_HEADER_BUFFER_H_ */
diff --git a/gr-digital/lib/qa_header_format.cc
b/gr-digital/lib/qa_header_format.cc
new file mode 100644
index 0000000..b06a2dd
--- /dev/null
+++ b/gr-digital/lib/qa_header_format.cc
@@ -0,0 +1,265 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015-2016 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gnuradio/attributes.h>
+
+#include <stdio.h>
+#include <cmath>
+#include <volk/volk.h>
+#include <gnuradio/expj.h>
+#include <cppunit/TestAssert.h>
+
+#include "qa_header_format.h"
+#include <gnuradio/digital/header_format_counter.h>
+#include <gnuradio/digital/header_format_default.h>
+#include <gnuradio/blocks/unpack_k_bits.h>
+
+void
+qa_header_format::test_default_format()
+{
+ static const int N = 4800;
+ int upper8 = (N >> 8) & 0xFF;
+ int lower8 = N & 0xFF;
+
+ std::string ac = "1010101010101010"; //0xAAAA
+ unsigned char *data = (unsigned char*)volk_malloc(N*sizeof(unsigned char),
+ volk_get_alignment());
+ srand (time(NULL));
+ for(unsigned int i = 0; i < N; i++) {
+ data[i] = rand() % 256;
+ }
+
+ gr::digital::header_format_default::sptr hdr_format;
+ hdr_format = gr::digital::header_format_default::make(ac, 0);
+
+ pmt::pmt_t output;
+ pmt::pmt_t info = pmt::make_dict();
+
+ bool ret = hdr_format->format(N, data, output, info);
+ size_t length = pmt::length(output);
+
+ CPPUNIT_ASSERT(ret);
+ CPPUNIT_ASSERT_EQUAL(length, hdr_format->header_nbytes());
+ CPPUNIT_ASSERT_EQUAL(8*length, hdr_format->header_nbits());
+
+ // Test access code formatted correctly
+ unsigned char h0 = pmt::u8vector_ref(output, 0);
+ unsigned char h1 = pmt::u8vector_ref(output, 1);
+ CPPUNIT_ASSERT_EQUAL(0xAA, (int)h0);
+ CPPUNIT_ASSERT_EQUAL(0xAA, (int)h1);
+
+ // Test upper and lower portion of length field, repeated twice
+ unsigned char h2 = pmt::u8vector_ref(output, 2);
+ unsigned char h3 = pmt::u8vector_ref(output, 3);
+ unsigned char h4 = pmt::u8vector_ref(output, 4);
+ unsigned char h5 = pmt::u8vector_ref(output, 5);
+ CPPUNIT_ASSERT_EQUAL(upper8, (int)h2);
+ CPPUNIT_ASSERT_EQUAL(lower8, (int)h3);
+ CPPUNIT_ASSERT_EQUAL(upper8, (int)h4);
+ CPPUNIT_ASSERT_EQUAL(lower8, (int)h5);
+
+ volk_free(data);
+}
+
+
+void
+qa_header_format::test_default_parse()
+{
+ static const int nbytes = 106;
+ static const int nbits = 8*nbytes;
+ unsigned char *bytes = (unsigned char*)volk_malloc(nbytes*sizeof(unsigned
char),
+ volk_get_alignment());
+ unsigned char *bits = (unsigned char*)volk_malloc(nbits*sizeof(unsigned
char),
+ volk_get_alignment());
+
+ srand(time(NULL));
+
+ // Fill bytes with random values
+ for(unsigned int i = 0; i < nbytes; i++) {
+ bytes[i] = rand() % 256;
+ }
+
+ int index = 0;
+ bytes[index+0] = 0xAA;
+ bytes[index+1] = 0xAA;
+ bytes[index+2] = 0x00;
+ bytes[index+3] = 0x64;
+ bytes[index+4] = 0x00;
+ bytes[index+5] = 0x64;
+
+ gr::blocks::kernel::unpack_k_bits unpacker =
gr::blocks::kernel::unpack_k_bits(8);
+ unpacker.unpack(bits, bytes, nbytes);
+
+ std::string ac = "1010101010101010"; //0xAAAA
+ gr::digital::header_format_default::sptr hdr_format;
+ hdr_format = gr::digital::header_format_default::make(ac, 0);
+
+ int count = 0;
+ std::vector<pmt::pmt_t> info;
+ bool ret = hdr_format->parse(nbits, bits, info, count);
+
+ CPPUNIT_ASSERT(ret);
+ CPPUNIT_ASSERT_EQUAL((size_t)1, info.size());
+
+ pmt::pmt_t dict = info[0];
+ int payload_bits = pmt::to_long(pmt::dict_ref(dict, pmt::intern("payload
symbols"),
+ pmt::from_long(-1)));
+
+ int hdr_bits = (int)hdr_format->header_nbits();
+ int expected_bits = nbits - hdr_bits;
+ CPPUNIT_ASSERT_EQUAL(expected_bits, payload_bits);
+
+ volk_free(bytes);
+ volk_free(bits);
+}
+
+void
+qa_header_format::test_counter_format()
+{
+ static const int N = 4800;
+ int upper8 = (N >> 8) & 0xFF;
+ int lower8 = N & 0xFF;
+
+ std::string ac = "1010101010101010"; //0xAAAA
+ unsigned char *data = (unsigned char*)volk_malloc(N*sizeof(unsigned char),
+ volk_get_alignment());
+ srand (time(NULL));
+ for(unsigned int i = 0; i < N; i++) {
+ data[i] = rand() % 256;
+ }
+
+ uint16_t expected_bps = 2;
+ gr::digital::header_format_counter::sptr hdr_format;
+ hdr_format = gr::digital::header_format_counter::make(ac, 0, expected_bps);
+
+ pmt::pmt_t output;
+ pmt::pmt_t info = pmt::make_dict();
+
+ bool ret = hdr_format->format(N, data, output, info);
+ size_t length = pmt::length(output);
+
+ CPPUNIT_ASSERT(ret);
+ CPPUNIT_ASSERT_EQUAL(length, hdr_format->header_nbytes());
+ CPPUNIT_ASSERT_EQUAL(8*length, hdr_format->header_nbits());
+
+ // Test access code formatted correctly
+ unsigned char h0 = pmt::u8vector_ref(output, 0);
+ unsigned char h1 = pmt::u8vector_ref(output, 1);
+ CPPUNIT_ASSERT_EQUAL(0xAA, (int)h0);
+ CPPUNIT_ASSERT_EQUAL(0xAA, (int)h1);
+
+ // Test upper and lower portion of length field, repeated twice
+ unsigned char h2 = pmt::u8vector_ref(output, 2);
+ unsigned char h3 = pmt::u8vector_ref(output, 3);
+ unsigned char h4 = pmt::u8vector_ref(output, 4);
+ unsigned char h5 = pmt::u8vector_ref(output, 5);
+ CPPUNIT_ASSERT_EQUAL(upper8, (int)h2);
+ CPPUNIT_ASSERT_EQUAL(lower8, (int)h3);
+ CPPUNIT_ASSERT_EQUAL(upper8, (int)h4);
+ CPPUNIT_ASSERT_EQUAL(lower8, (int)h5);
+
+ uint16_t h6 = (uint16_t)pmt::u8vector_ref(output, 6);
+ uint16_t h7 = (uint16_t)pmt::u8vector_ref(output, 7);
+ uint16_t bps = ((h6 << 8) & 0xFF00) | (h7 & 0x00FF);
+ CPPUNIT_ASSERT_EQUAL(expected_bps, bps);
+
+ uint16_t h8 = pmt::u8vector_ref(output, 8);
+ uint16_t h9 = pmt::u8vector_ref(output, 9);
+ uint16_t counter = ((h8 << 8) & 0xFF00) | (h9 & 0x00FF);
+ CPPUNIT_ASSERT_EQUAL((uint16_t)0, counter);
+
+ // Run another format to increment the counter to 1 and test.
+ ret = hdr_format->format(N, data, output, info);
+ h8 = pmt::u8vector_ref(output, 8);
+ h9 = pmt::u8vector_ref(output, 9);
+ counter = ((h8 << 8) & 0xFF00) | (h9 & 0x00FF);
+ CPPUNIT_ASSERT_EQUAL((uint16_t)1, counter);
+
+ volk_free(data);
+}
+
+
+void
+qa_header_format::test_counter_parse()
+{
+ static const int nbytes = 110;
+ static const int nbits = 8*nbytes;
+ unsigned char *bytes = (unsigned char*)volk_malloc(nbytes*sizeof(unsigned
char),
+ volk_get_alignment());
+ unsigned char *bits = (unsigned char*)volk_malloc(nbits*sizeof(unsigned
char),
+ volk_get_alignment());
+
+ srand(time(NULL));
+
+ // Fill bytes with random values
+ for(unsigned int i = 0; i < nbytes; i++) {
+ bytes[i] = rand() % 256;
+ }
+
+ int index = 0;
+ bytes[index+0] = 0xAA;
+ bytes[index+1] = 0xAA;
+ bytes[index+2] = 0x00;
+ bytes[index+3] = 0x64;
+ bytes[index+4] = 0x00;
+ bytes[index+5] = 0x64;
+ bytes[index+6] = 0x00;
+ bytes[index+7] = 0x02;
+ bytes[index+8] = 0x00;
+ bytes[index+9] = 0x00;
+
+ gr::blocks::kernel::unpack_k_bits unpacker =
gr::blocks::kernel::unpack_k_bits(8);
+ unpacker.unpack(bits, bytes, nbytes);
+
+ uint16_t expected_bps = 2;
+ std::string ac = "1010101010101010"; //0xAAAA
+ gr::digital::header_format_counter::sptr hdr_format;
+ hdr_format = gr::digital::header_format_counter::make(ac, 0, expected_bps);
+
+ int count = 0;
+ std::vector<pmt::pmt_t> info;
+ bool ret = hdr_format->parse(nbits, bits, info, count);
+
+ CPPUNIT_ASSERT(ret);
+ CPPUNIT_ASSERT_EQUAL((size_t)1, info.size());
+
+ pmt::pmt_t dict = info[0];
+ int payload_syms = pmt::to_long(pmt::dict_ref(dict, pmt::intern("payload
symbols"),
+ pmt::from_long(-1)));
+ int bps = pmt::to_long(pmt::dict_ref(dict, pmt::intern("bps"),
+ pmt::from_long(-1)));
+ int counter = pmt::to_long(pmt::dict_ref(dict, pmt::intern("counter"),
+ pmt::from_long(-1)));
+
+ int hdr_bits = (int)hdr_format->header_nbits();
+ int expected_bits = nbits - hdr_bits;
+ CPPUNIT_ASSERT_EQUAL(expected_bits, payload_syms * bps);
+ CPPUNIT_ASSERT_EQUAL(expected_bps, (uint16_t)bps);
+ CPPUNIT_ASSERT_EQUAL(0, counter);
+
+ volk_free(bytes);
+ volk_free(bits);
+}
diff --git a/gr-digital/swig/packet_header.i b/gr-digital/lib/qa_header_format.h
similarity index 51%
copy from gr-digital/swig/packet_header.i
copy to gr-digital/lib/qa_header_format.h
index 7c06d19..281e8f4 100644
--- a/gr-digital/swig/packet_header.i
+++ b/gr-digital/lib/qa_header_format.h
@@ -1,34 +1,47 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
- *
+ * Copyright 2015-2016 Free Software Foundation, Inc.
+ *
* This file is part of GNU Radio
- *
+ *
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
- *
+ *
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
-%template(packet_header_default_sptr)
boost::shared_ptr<gr::digital::packet_header_default>;
-%pythoncode %{
-packet_header_default_sptr.__repr__ = lambda self: "<packet_header_default>"
-packet_header_default = packet_header_default .make;
-%}
+#ifndef _QA_DIGITAL_HEADER_FORMAT_H_
+#define _QA_DIGITAL_HEADER_FORMAT_H_
-%template(packet_header_ofdm_sptr)
boost::shared_ptr<gr::digital::packet_header_ofdm>;
-%pythoncode %{
-packet_header_ofdm_sptr.__repr__ = lambda self: "<packet_header_ofdm>"
-packet_header_ofdm = packet_header_ofdm .make;
-%}
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+class qa_header_format : public CppUnit::TestCase
+{
+ CPPUNIT_TEST_SUITE(qa_header_format);
+ CPPUNIT_TEST(test_default_format);
+ CPPUNIT_TEST(test_default_parse);
+ CPPUNIT_TEST(test_counter_format);
+ CPPUNIT_TEST(test_counter_parse);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void test_default_format();
+ void test_default_parse();
+ void test_default_parse_soft();
+ void test_counter_format();
+ void test_counter_parse();
+ void test_counter_parse_soft();
+};
+
+#endif /* _QA_DIGITAL_HEADER_FORMAT_H_ */
diff --git a/gr-digital/swig/packet_header.i b/gr-digital/lib/test_gr_digital.cc
similarity index 53%
copy from gr-digital/swig/packet_header.i
copy to gr-digital/lib/test_gr_digital.cc
index 7c06d19..7a6049d 100644
--- a/gr-digital/swig/packet_header.i
+++ b/gr-digital/lib/test_gr_digital.cc
@@ -1,34 +1,48 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
- *
+ * Copyright 2014 Free Software Foundation, Inc.
+ *
* This file is part of GNU Radio
- *
+ *
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
- *
+ *
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
-%template(packet_header_default_sptr)
boost::shared_ptr<gr::digital::packet_header_default>;
-%pythoncode %{
-packet_header_default_sptr.__repr__ = lambda self: "<packet_header_default>"
-packet_header_default = packet_header_default .make;
-%}
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
-%template(packet_header_ofdm_sptr)
boost::shared_ptr<gr::digital::packet_header_ofdm>;
-%pythoncode %{
-packet_header_ofdm_sptr.__repr__ = lambda self: "<packet_header_ofdm>"
-packet_header_ofdm = packet_header_ofdm .make;
-%}
+#include <cppunit/TextTestRunner.h>
+#include <cppunit/XmlOutputter.h>
+#include <gnuradio/unittests.h>
+#include "qa_digital.h"
+#include <iostream>
+#include <fstream>
+
+int
+main(int argc, char **argv)
+{
+ CppUnit::TextTestRunner runner;
+ std::ofstream xmlfile(get_unittest_path("digital.xml").c_str());
+ CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(),
xmlfile);
+
+ runner.addTest(qa_digital::suite());
+ runner.setOutputter(xmlout);
+
+ bool was_successful = runner.run("", false);
+
+ return was_successful ? 0 : 1;
+}
diff --git a/gr-digital/python/digital/qa_packet_format.py
b/gr-digital/python/digital/qa_packet_format.py
new file mode 100644
index 0000000..6440b80
--- /dev/null
+++ b/gr-digital/python/digital/qa_packet_format.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+#
+# Copyright 2015,2016 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import random, time, struct
+import pmt
+from gnuradio import gr, gr_unittest, digital, blocks
+from gnuradio.digital import packet_utils
+
+class test_packet_format_fb(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_packet_format_async_default(self):
+ ac = packet_utils.default_access_code
+ hdr_format = digital.header_format_default(ac, 0)
+
+ formatter = digital.protocol_formatter_async(hdr_format)
+ snk_hdr = blocks.message_debug()
+ snk_pld = blocks.message_debug()
+
+ self.tb.msg_connect(formatter, 'header', snk_hdr, 'store')
+ self.tb.msg_connect(formatter, 'payload', snk_pld, 'store')
+
+
+ send_str = "Hello World"
+ send_pmt = pmt.make_u8vector(len(send_str), ord(' '))
+ for i in range(len(send_str)):
+ pmt.u8vector_set(send_pmt, i, ord(send_str[i]))
+ msg = pmt.cons(pmt.PMT_NIL, send_pmt)
+
+ port = pmt.intern("in")
+ formatter.to_basic_block()._post(port, msg)
+
+ self.tb.start()
+ while (snk_hdr.num_messages() < 1) and (snk_pld.num_messages() < 1):
+ time.sleep(0.1)
+ self.tb.stop()
+ self.tb.wait()
+
+ result_hdr_pmt = pmt.cdr(snk_hdr.get_message(0))
+ result_pld_pmt = pmt.cdr(snk_pld.get_message(0))
+
+ result_hdr = pmt.u8vector_elements(result_hdr_pmt)
+ result_pld = pmt.u8vector_elements(result_pld_pmt)
+ header = "".join([chr(r) for r in result_hdr])
+ payload = "".join([chr(r) for r in result_pld])
+
+ access_code =
packet_utils.conv_1_0_string_to_packed_binary_string(packet_utils.default_access_code)[0]
+ rx_access_code = header[0:len(access_code)]
+
+ length = len(send_str)
+ rx_length = struct.unpack_from("!H", header, len(access_code))[0]
+
+ self.assertEqual(access_code, rx_access_code)
+ self.assertEqual(length, rx_length)
+ self.assertEqual(length, len(payload))
+ self.assertEqual(send_str, payload[0:length])
+
+
+ def test_packet_format_async_counter(self):
+ bps = 2
+ ac = packet_utils.default_access_code
+ hdr_format = digital.header_format_counter(ac, 0, 2)
+
+ formatter = digital.protocol_formatter_async(hdr_format)
+ snk_hdr = blocks.message_debug()
+ snk_pld = blocks.message_debug()
+
+ self.tb.msg_connect(formatter, 'header', snk_hdr, 'store')
+ self.tb.msg_connect(formatter, 'payload', snk_pld, 'store')
+
+
+ send_str = "Hello World" + 1000*"xxx"
+ send_pmt = pmt.make_u8vector(len(send_str), ord(' '))
+ for i in range(len(send_str)):
+ pmt.u8vector_set(send_pmt, i, ord(send_str[i]))
+ msg = pmt.cons(pmt.PMT_NIL, send_pmt)
+
+ port = pmt.intern("in")
+ formatter.to_basic_block()._post(port, msg)
+
+ self.tb.start()
+ while (snk_hdr.num_messages() < 1) and (snk_pld.num_messages() < 1):
+ time.sleep(0.1)
+ self.tb.stop()
+ self.tb.wait()
+
+ result_hdr_pmt = pmt.cdr(snk_hdr.get_message(0))
+ result_pld_pmt = pmt.cdr(snk_pld.get_message(0))
+
+ result_hdr = pmt.u8vector_elements(result_hdr_pmt)
+ result_pld = pmt.u8vector_elements(result_pld_pmt)
+ header = "".join([chr(r) for r in result_hdr])
+ payload = "".join([chr(r) for r in result_pld])
+
+ access_code =
packet_utils.conv_1_0_string_to_packed_binary_string(packet_utils.default_access_code)[0]
+ rx_access_code = header[0:len(access_code)]
+
+ length = len(send_str)
+ rx_length = struct.unpack_from("!H", header, len(access_code))[0]
+ rx_bps = struct.unpack_from("!H", header, len(access_code)+4)[0]
+ rx_counter = struct.unpack_from("!H", header, len(access_code)+6)[0]
+
+ self.assertEqual(access_code, rx_access_code)
+ self.assertEqual(length, rx_length)
+ self.assertEqual(bps, rx_bps)
+ self.assertEqual(0, rx_counter)
+ self.assertEqual(length, len(payload))
+ self.assertEqual(send_str, payload[0:length])
+
+if __name__ == '__main__':
+ gr_unittest.run(test_packet_format_fb, "test_packet_format_fb.xml")
diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt
index d87b7e9..2f00dc1 100644
--- a/gr-digital/swig/CMakeLists.txt
+++ b/gr-digital/swig/CMakeLists.txt
@@ -30,6 +30,7 @@ set(GR_SWIG_INCLUDE_DIRS
${GR_FFT_INCLUDE_DIRS}
${GR_FILTER_INCLUDE_DIRS}
${GNURADIO_RUNTIME_SWIG_INCLUDE_DIRS}
+ ${VOLK_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index d7a3b81..8a38d65 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2015 Free Software Foundation, Inc.
+ * Copyright 2011-2016 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -100,6 +100,14 @@
#include "gnuradio/digital/ofdm_sampler.h"
#include "gnuradio/digital/ofdm_serializer_vcc.h"
#include "gnuradio/digital/ofdm_sync_sc_cfb.h"
+#include "gnuradio/digital/header_format_base.h"
+#include "gnuradio/digital/header_format_default.h"
+#include "gnuradio/digital/header_format_counter.h"
+#include "gnuradio/digital/header_format_crc.h"
+#include "gnuradio/digital/header_format_ofdm.h"
+#include "gnuradio/digital/protocol_formatter_async.h"
+#include "gnuradio/digital/protocol_formatter_bb.h"
+#include "gnuradio/digital/protocol_parser_b.h"
#include "gnuradio/digital/packet_header_default.h"
#include "gnuradio/digital/packet_header_ofdm.h"
#include "gnuradio/digital/packet_headergenerator_bb.h"
@@ -181,6 +189,14 @@
%include "gnuradio/digital/ofdm_sampler.h"
%include "gnuradio/digital/ofdm_serializer_vcc.h"
%include "gnuradio/digital/ofdm_sync_sc_cfb.h"
+%include "gnuradio/digital/header_format_base.h"
+%include "gnuradio/digital/header_format_default.h"
+%include "gnuradio/digital/header_format_counter.h"
+%include "gnuradio/digital/header_format_crc.h"
+%include "gnuradio/digital/header_format_ofdm.h"
+%include "gnuradio/digital/protocol_formatter_async.h"
+%include "gnuradio/digital/protocol_formatter_bb.h"
+%include "gnuradio/digital/protocol_parser_b.h"
%include "gnuradio/digital/packet_header_default.h"
%include "gnuradio/digital/packet_header_ofdm.h"
%include "gnuradio/digital/packet_headergenerator_bb.h"
@@ -249,6 +265,9 @@ GR_SWIG_BLOCK_MAGIC2(digital, ofdm_mapper_bcv);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_sampler);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_serializer_vcc);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_sync_sc_cfb);
+GR_SWIG_BLOCK_MAGIC2(digital, protocol_formatter_async);
+GR_SWIG_BLOCK_MAGIC2(digital, protocol_formatter_bb);
+GR_SWIG_BLOCK_MAGIC2(digital, protocol_parser_b);
GR_SWIG_BLOCK_MAGIC2(digital, packet_headergenerator_bb);
GR_SWIG_BLOCK_MAGIC2(digital, packet_headerparser_b);
GR_SWIG_BLOCK_MAGIC2(digital, packet_sink);
diff --git a/gr-digital/swig/packet_header.i b/gr-digital/swig/packet_header.i
index 7c06d19..ace7030 100644
--- a/gr-digital/swig/packet_header.i
+++ b/gr-digital/swig/packet_header.i
@@ -1,19 +1,19 @@
/* -*- c++ -*- */
/*
* Copyright 2012 Free Software Foundation, Inc.
- *
+ *
* This file is part of GNU Radio
- *
+ *
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
- *
+ *
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
@@ -32,3 +32,29 @@ packet_header_ofdm_sptr.__repr__ = lambda self:
"<packet_header_ofdm>"
packet_header_ofdm = packet_header_ofdm .make;
%}
+%template(header_format_base_sptr)
boost::shared_ptr<gr::digital::header_format_base>;
+
+%template(header_format_default_sptr)
boost::shared_ptr<gr::digital::header_format_default>;
+%pythoncode %{
+header_format_default_sptr.__repr__ = lambda self: "<header_format_default>"
+header_format_default = header_format_default .make;
+%}
+
+
+%template(header_format_counter_sptr)
boost::shared_ptr<gr::digital::header_format_counter>;
+%pythoncode %{
+header_format_counter_sptr.__repr__ = lambda self: "<header_format_counter>"
+header_format_counter = header_format_counter .make;
+%}
+
+%template(header_format_crc_sptr)
boost::shared_ptr<gr::digital::header_format_crc>;
+%pythoncode %{
+header_format_crc_sptr.__repr__ = lambda self: "<header_format_crc>"
+header_format_crc = header_format_crc .make;
+%}
+
+%template(header_format_ofdm_sptr)
boost::shared_ptr<gr::digital::header_format_ofdm>;
+%pythoncode %{
+header_format_ofdm_sptr.__repr__ = lambda self: "<header_format_ofdm>"
+header_format_ofdm = header_format_ofdm .make;
+%}
- [Commit-gnuradio] [gnuradio] branch packet3 created (now b9c0d10), git, 2016/06/15
- [Commit-gnuradio] [gnuradio] 04/06: digital: pfb_clock_sync_ccf tag offset update., git, 2016/06/15
- [Commit-gnuradio] [gnuradio] 01/06: runtime: executor fixes for tag propagation, git, 2016/06/15
- [Commit-gnuradio] [gnuradio] 02/06: blocks: Add `multiply tag by value' and `test tag variable rate' blocks, git, 2016/06/15
- [Commit-gnuradio] [gnuradio] 03/06: digital: Updated corr_est, git, 2016/06/15
- [Commit-gnuradio] [gnuradio] 05/06: digital: Complete overhaul of protocol handling,
git <=
- [Commit-gnuradio] [gnuradio] 06/06: digital: Added lots and lots of examples for overhauled packet format, git, 2016/06/15