Blocks and utilities for digital modulation and demodulation.
Scramble an input stream using an LFSR.
This block scrambles up to 8 bits per byte of the input data stream, starting at the LSB.
The scrambler works by XORing the incoming bit stream by the output of the LFSR. Optionally, after bits have been processed, the shift register is reset to the value. This allows processing fixed length vectors of samples.
Alternatively, the LFSR can be reset using a reset tag to scramble variable length vectors. However, it cannot be reset between bytes.
For details on configuring the LFSR, see gr::digital::lfsr.
Constructor Specific Documentation:
Create additive scrambler.
Parameters: |
|
---|
declare_sample_delay(additive_scrambler_bb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(additive_scrambler_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(additive_scrambler_bb_sptr self) -> pmt_vector_float
Slice float binary symbol producing 1 bit output.
Constructor Specific Documentation:
Make binary symbol slicer block.
declare_sample_delay(binary_slicer_fb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(binary_slicer_fb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(binary_slicer_fb_sptr self) -> pmt_vector_float
Burst shaper block for applying burst padding and ramping.
This block applies a configurable amount of zero padding before and/or after a burst indicated by tagged stream length tags.
If phasing symbols are used, an alternating pattern of +1/-1 symbols of length ceil(N/2) will be inserted before and after each burst, where N is the length of the taps vector. The ramp- up/ramp-down shape will be applied to these phasing symbols.
If phasing symbols are not used, the taper will be applied directly to the head and tail of each burst.
Length tags will be updated to include the length of any added zero padding or phasing symbols and will be placed at the beginning of the modified tagged stream. Any other tags found at the same offset as a length tag will also be placed at the beginning of the modified tagged stream, since these tags are assumed to be associated with the burst rather than a specific sample. For example, if “tx_time” tags are used to control bursts, their offsets should be consistent with their associated burst’s length tags. Tags at other offsets will be placed with the samples on which they were found.
Constructor Specific Documentation:
Make a burst shaper block.
Parameters: |
|
---|
declare_sample_delay(burst_shaper_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(burst_shaper_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(burst_shaper_cc_sptr self) -> pmt_vector_float
Returns the amount of zero padding inserted after each burst.
Returns the amount of zero padding inserted before each burst.
Returns the total amount of zero padding and phasing symbols inserted before each burst.
Returns the total amount of zero padding and phasing symbols inserted after each burst.
Burst shaper block for applying burst padding and ramping.
This block applies a configurable amount of zero padding before and/or after a burst indicated by tagged stream length tags.
If phasing symbols are used, an alternating pattern of +1/-1 symbols of length ceil(N/2) will be inserted before and after each burst, where N is the length of the taps vector. The ramp- up/ramp-down shape will be applied to these phasing symbols.
If phasing symbols are not used, the taper will be applied directly to the head and tail of each burst.
Length tags will be updated to include the length of any added zero padding or phasing symbols and will be placed at the beginning of the modified tagged stream. Any other tags found at the same offset as a length tag will also be placed at the beginning of the modified tagged stream, since these tags are assumed to be associated with the burst rather than a specific sample. For example, if “tx_time” tags are used to control bursts, their offsets should be consistent with their associated burst’s length tags. Tags at other offsets will be placed with the samples on which they were found.
Constructor Specific Documentation:
Make a burst shaper block.
Parameters: |
|
---|
declare_sample_delay(burst_shaper_ff_sptr self, unsigned int delay)
pc_input_buffers_full_avg(burst_shaper_ff_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(burst_shaper_ff_sptr self) -> pmt_vector_float
Returns the amount of zero padding inserted after each burst.
Returns the amount of zero padding inserted before each burst.
Returns the total amount of zero padding and phasing symbols inserted before each burst.
Returns the total amount of zero padding and phasing symbols inserted after each burst.
Map a stream of unpacked symbol indexes to stream of float or complex constellation points in D dimensions (D = 1 by default)
The combination of gr::blocks::packed_to_unpacked_XX followed by gr::digital::chunks_to_symbols_XY handles the general case of mapping from a stream of bytes or shorts into arbitrary float or complex symbols.
Constructor Specific Documentation:
Make a chunks-to-symbols block.
Parameters: |
|
---|
declare_sample_delay(chunks_to_symbols_bc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(chunks_to_symbols_bc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(chunks_to_symbols_bc_sptr self) -> pmt_vector_float
Map a stream of unpacked symbol indexes to stream of float or complex constellation points in D dimensions (D = 1 by default)
The combination of gr::blocks::packed_to_unpacked_XX followed by gr::digital::chunks_to_symbols_XY handles the general case of mapping from a stream of bytes or shorts into arbitrary float or complex symbols.
Constructor Specific Documentation:
Make a chunks-to-symbols block.
Parameters: |
|
---|
declare_sample_delay(chunks_to_symbols_bf_sptr self, unsigned int delay)
pc_input_buffers_full_avg(chunks_to_symbols_bf_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(chunks_to_symbols_bf_sptr self) -> pmt_vector_float
Map a stream of unpacked symbol indexes to stream of float or complex constellation points in D dimensions (D = 1 by default)
The combination of gr::blocks::packed_to_unpacked_XX followed by gr::digital::chunks_to_symbols_XY handles the general case of mapping from a stream of bytes or shorts into arbitrary float or complex symbols.
Constructor Specific Documentation:
Make a chunks-to-symbols block.
Parameters: |
|
---|
declare_sample_delay(chunks_to_symbols_ic_sptr self, unsigned int delay)
pc_input_buffers_full_avg(chunks_to_symbols_ic_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(chunks_to_symbols_ic_sptr self) -> pmt_vector_float
Map a stream of unpacked symbol indexes to stream of float or complex constellation points in D dimensions (D = 1 by default)
The combination of gr::blocks::packed_to_unpacked_XX followed by gr::digital::chunks_to_symbols_XY handles the general case of mapping from a stream of bytes or shorts into arbitrary float or complex symbols.
Constructor Specific Documentation:
Make a chunks-to-symbols block.
Parameters: |
|
---|
declare_sample_delay(chunks_to_symbols_if_sptr self, unsigned int delay)
pc_input_buffers_full_avg(chunks_to_symbols_if_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(chunks_to_symbols_if_sptr self) -> pmt_vector_float
Map a stream of unpacked symbol indexes to stream of float or complex constellation points in D dimensions (D = 1 by default)
The combination of gr::blocks::packed_to_unpacked_XX followed by gr::digital::chunks_to_symbols_XY handles the general case of mapping from a stream of bytes or shorts into arbitrary float or complex symbols.
Constructor Specific Documentation:
Make a chunks-to-symbols block.
Parameters: |
|
---|
declare_sample_delay(chunks_to_symbols_sc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(chunks_to_symbols_sc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(chunks_to_symbols_sc_sptr self) -> pmt_vector_float
Map a stream of unpacked symbol indexes to stream of float or complex constellation points in D dimensions (D = 1 by default)
The combination of gr::blocks::packed_to_unpacked_XX followed by gr::digital::chunks_to_symbols_XY handles the general case of mapping from a stream of bytes or shorts into arbitrary float or complex symbols.
Constructor Specific Documentation:
Make a chunks-to-symbols block.
Parameters: |
|
---|
declare_sample_delay(chunks_to_symbols_sf_sptr self, unsigned int delay)
pc_input_buffers_full_avg(chunks_to_symbols_sf_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(chunks_to_symbols_sf_sptr self) -> pmt_vector_float
Mueller and M?ller (M&M) based clock recovery block with complex input, complex output.
This implements the Mueller and M?ller (M&M) discrete-time error-tracking synchronizer.
The complex version here is based on: Modified Mueller and Muller clock recovery circuit:
Constructor Specific Documentation:
Make a M&M clock recovery block.
Parameters: |
|
---|
declare_sample_delay(clock_recovery_mm_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(clock_recovery_mm_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(clock_recovery_mm_cc_sptr self) -> pmt_vector_float
Mueller and M?ller (M&M) based clock recovery block with float input, float output.
This implements the Mueller and M?ller (M&M) discrete-time error-tracking synchronizer.
See “Digital Communication Receivers: Synchronization, Channel Estimation and Signal Processing” by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel. ISBN 0-471-50275-8.
Constructor Specific Documentation:
Make a M&M clock recovery block.
Parameters: |
|
---|
declare_sample_delay(clock_recovery_mm_ff_sptr self, unsigned int delay)
pc_input_buffers_full_avg(clock_recovery_mm_ff_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(clock_recovery_mm_ff_sptr self) -> pmt_vector_float
Implements constant modulus adaptive filter on complex stream.
The error value and tap update equations (for p=2) can be found in:
D. Godard, “Self-Recovering Equalization and Carrier Tracking in Two-Dimensional Data Communication Systems,” IEEE Transactions on Communications, Vol. 28, No. 11, pp. 1867 - 1875, 1980.
Constructor Specific Documentation:
Make a CMA Equalizer block
Parameters: |
|
---|
declare_sample_delay(cma_equalizer_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(cma_equalizer_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(cma_equalizer_cc_sptr self) -> pmt_vector_float
Constellation Decoder.
Decode a constellation’s points from a complex space to (unpacked) bits based on the map of the object.
Constructor Specific Documentation:
Make constellation decoder block.
Parameters: | constellation – A constellation derived from class ‘constellation’. Use base() method to get a shared pointer to this base class type. |
---|
declare_sample_delay(constellation_decoder_cb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(constellation_decoder_cb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(constellation_decoder_cb_sptr self) -> pmt_vector_float
This block makes hard decisions about the received symbols (using a constellation object) and also fine tunes phase synchronization.
The phase and frequency synchronization are based on a Costas loop that finds the error of the incoming signal point compared to its nearest constellation point. The frequency and phase of the NCO are updated according to this error.
Message Ports:
set_constellation (input): Receives a PMT any containing a new gr::digital::constellation object. The PMT is cast back to a gr::digital::constellation_sptr and passes this to set_constellation.
rotate_phase (input): Receives a PMT double to update the phase. The phase value passed in the message is added to the current phase of the receiver.
Constructor Specific Documentation:
Constructs a constellation receiver that (phase/fine freq) synchronizes and decodes constellation points specified by a constellation object.
Parameters: |
|
---|
declare_sample_delay(constellation_receiver_cb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(constellation_receiver_cb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(constellation_receiver_cb_sptr self) -> pmt_vector_float
Constellation Decoder.
Decode a constellation’s points from a complex space to soft bits based on the map and soft decision LUT of the object.
Constructor Specific Documentation:
Make constellation decoder block.
Parameters: | constellation – A constellation derived from class ‘constellation’. Use base() method to get a shared pointer to this base class type. |
---|
declare_sample_delay(constellation_soft_decoder_cf_sptr self, unsigned int delay)
pc_input_buffers_full_avg(constellation_soft_decoder_cf_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(constellation_soft_decoder_cf_sptr self) -> pmt_vector_float
Examine input for specified access code, one bit at a time.
input: stream of bits, 1 bit per input byte (data in LSB) output: stream of bits, 2 bits per output byte (data in LSB, flag in next higher bit)
Each output byte contains two valid bits, the data bit, and the flag bit. The LSB (bit 0) is the data bit, and is the original input data, delayed 64 bits. Bit 1 is the flag bit and is 1 if the corresponding data bit is the first data bit following the access code. Otherwise the flag bit is 0.
Constructor Specific Documentation:
Make a correlate_access_code block.
Parameters: |
|
---|
declare_sample_delay(correlate_access_code_bb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(correlate_access_code_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(correlate_access_code_bb_sptr self) -> pmt_vector_float
Set a new access code.
Examine input for specified access code, one bit at a time.
input: stream of bits (unpacked bytes) output: a tagged stream set of bits from the payload following the access code and header.
This block searches for the given access code by reading in the input bits. Once found, it expects the following 32 samples to contain a header that includes the frame length (16 bits for the length, repeated). It decodes the header to get the frame length in order to set up the the tagged stream key information.
The output of this block is appropriate for use with tagged stream blocks.
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(correlate_access_code_bb_ts_sptr self, unsigned int delay)
pc_input_buffers_full_avg(correlate_access_code_bb_ts_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(correlate_access_code_bb_ts_sptr self) -> pmt_vector_float
Examine input for specified access code, one bit at a time.
input: stream of floats (generally, soft decisions) output: a tagged stream set of samples from the payload following the access code and header.
This block searches for the given access code by slicing the soft decision symbol inputs. Once found, it expects the following 32 samples to contain a header that includes the frame length (16 bits for the length, repeated). It decodes the header to get the frame length in order to set up the the tagged stream key information.
The output of this block is appropriate for use with tagged stream blocks.
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(correlate_access_code_ff_ts_sptr self, unsigned int delay)
pc_input_buffers_full_avg(correlate_access_code_ff_ts_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(correlate_access_code_ff_ts_sptr self) -> pmt_vector_float
Examine input for specified access code, one bit at a time.
input: stream of bits, 1 bit per input byte (data in LSB) output: unaltered stream of bits (plus tags)
This block annotates the input stream with tags. The tags have key name [tag_name], specified in the constructor. Used for searching an input data stream for preambles, etc.
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(correlate_access_code_tag_bb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(correlate_access_code_tag_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(correlate_access_code_tag_bb_sptr self) -> pmt_vector_float
Correlate to a preamble and send time/phase sync info.
Input: Output: This block is designed to search for a preamble by correlation and uses the results of the correlation to get a time and phase offset estimate. These estimates are passed downstream as stream tags for use by follow-on synchronization blocks.
The preamble is provided as a set of symbols along with a baseband matched filter which we use to create the filtered and upsampled symbol that we will receive over-the-air.
The phase_est tag is used to adjust the phase estimation of any downstream synchronization blocks and is currently used by the gr::digital::costas_loop_cc block.
The time_est tag is used to adjust the sampling timing estimation of any downstream synchronization blocks and is currently used by the gr::digital::pfb_clock_sync_ccf block.
Constructor Specific Documentation:
Make a block that correlates against the vector and outputs a phase and symbol timing estimate.
Parameters: |
|
---|
declare_sample_delay(correlate_and_sync_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(correlate_and_sync_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(correlate_and_sync_cc_sptr self) -> pmt_vector_float
Correlate stream with a pre-defined sequence and estimate peak.
Input: Output:
This block is designed to search for a sync word by correlation and uses the results of the correlation to get a time and phase offset estimate. These estimates are passed downstream as stream tags for use by follow-on synchronization blocks.
The sync word is provided as a set of symbols along with a baseband matched filter which we use to create the filtered and upsampled symbols that we will receive over-the-air.
The phase_est tag can be used by downstream blocks to adjust their phase estimatopm/correction loops, and is currently implemented by the gr::digital::costas_loop_cc block.
The time_est tag can be used to adjust the sampling timing estimate of any downstream synchronization blocks and is currently implemented by the gr::digital::pfb_clock_sync_ccf block.
The caller must provide a “time_est” and “phase_est” tag marking delay from the start of the correlated signal segment, in order to mark the proper point in the sync word for downstream synchronization blocks. Generally this block cannot know where the actual sync word symbols are located relative to “corr_start”, given that some modulations have pulses with intentional ISI. The user should manually examine the primary output and the “corr_start” tag postition to determine the required tag delay settings for the particular modulation, sync word, and downstream blocks used.
For a discussion of the properties of complex correlations, with respect to signal processing, see: Marple, Jr., S. L., “Estimating Group Delay and Phase Delay via Discrete-Time ‘Analytic’ Cross-Correlation, , Volume 47, No. 9, September 1999
Constructor Specific Documentation:
Make a block that correlates against the vector and outputs a phase and symbol timing estimate.
Parameters: |
|
---|
declare_sample_delay(corr_est_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(corr_est_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(corr_est_cc_sptr self) -> pmt_vector_float
A Costas loop carrier recovery module.
The Costas loop locks to the center frequency of a signal and downconverts it to baseband.
More details can be found online:
J. Feigin, “Practical Costas loop design: Designing a simple and inexpensive BPSK Costas loop carrier recovery circuit,” RF signal processing, pp. 20-36, 2002.
The Costas loop can have two output streams: There is a single optional message input:
Constructor Specific Documentation:
Make a Costas loop carrier recovery block.
Parameters: |
|
---|
declare_sample_delay(costas_loop_cc_sptr self, unsigned int delay)
Returns the current value of the loop error.
pc_input_buffers_full_avg(costas_loop_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(costas_loop_cc_sptr self) -> pmt_vector_float
Generic CPM modulator.
Examples:
The input of this block are symbols from an M-ary alphabet +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the valid inputs are +/-1. The modulator will silently accept any other inputs, though. The output is the phase-modulated signal.
Constructor Specific Documentation:
Make CPM modulator block.
Parameters: |
|
---|
Return the value of beta for the modulator.
Make GMSK modulator block.
The type is GAUSSIAN and the modulation index for GMSK is 0.5. This are populated automatically by this factory function.
Return the number of samples per symbol.
Return the phase response FIR taps.
Byte-stream CRC block for async messages.
Processes packets (as async PDU messages) for CRC32. The parameter determines if the block acts to check and strip the CRC or to calculate and append the CRC32.
The input PDU is expected to be a message of packet bytes.
When using check mode, if the CRC passes, the output is a payload of the message with the CRC stripped, so the output will be 4 bytes smaller than the input.
When using calculate mode (check == false), then the CRC is calculated on the PDU and appended to it. The output is then 4 bytes longer than the input.
This block implements the CRC32 using the Boost crc_optimal class for 32-bit CRCs with the standard generator 0x04C11DB7.
Constructor Specific Documentation:
Parameters: | check – Set to true if you want to check CRC, false to create CRC. |
---|
declare_sample_delay(crc32_async_bb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(crc32_async_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(crc32_async_bb_sptr self) -> pmt_vector_float
Byte-stream CRC block.
Input: stream of bytes, which form a packet. The first byte of the packet has a tag with key “length” and the value being the number of bytes in the packet.
Output: The same bytes as incoming, but trailing a CRC32 of the packet. The tag is re-set to the new length.
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(crc32_bb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(crc32_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(crc32_bb_sptr self) -> pmt_vector_float
Descramber an input stream using an LFSR.
Descramble an input stream using an LFSR. This block works on the LSB only of the input data stream, i.e., on an “unpacked binary” stream, and produces the same format on its output.
Constructor Specific Documentation:
Make a descrambler block.
Parameters: |
|
---|
declare_sample_delay(descrambler_bb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(descrambler_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(descrambler_bb_sptr self) -> pmt_vector_float
Differential encoder: y[0] = (x[0] - x[-1]) % M.
Uses current and previous symbols and the alphabet modulus to perform differential decoding.
Constructor Specific Documentation:
Make a differntial decoder block.
Parameters: | modulus – Modulus of code’s alphabet |
---|
declare_sample_delay(diff_decoder_bb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(diff_decoder_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(diff_decoder_bb_sptr self) -> pmt_vector_float
Differential decoder: y[0] = (x[0] + y[-1]) % M.
Uses current and previous symbols and the alphabet modulus to perform differential encoding.
Constructor Specific Documentation:
Make a differntial encoder block.
Parameters: | modulus – Modulus of code’s alphabet |
---|
declare_sample_delay(diff_encoder_bb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(diff_encoder_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(diff_encoder_bb_sptr self) -> pmt_vector_float
Differential decoding based on phase change.
Uses the phase difference between two symbols to determine the output symbol:
Constructor Specific Documentation:
Make a differential phasor decoding block.
declare_sample_delay(diff_phasor_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(diff_phasor_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(diff_phasor_cc_sptr self) -> pmt_vector_float
Frequency Lock Loop using band-edge filters.
The frequency lock loop derives a band-edge filter that covers the upper and lower bandwidths of a digitally-modulated signal. The bandwidth range is determined by the excess bandwidth (e.g., rolloff factor) of the modulated signal. The placement in frequency of the band-edges is determined by the oversampling ratio (number of samples per symbol) and the excess bandwidth. The size of the filters should be fairly large so as to average over a number of symbols.
The FLL works by filtering the upper and lower band edges into x_u(t) and x_l(t), respectively. These are combined to form cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining these to form the signal e(t) = Re{cc(t) imes ss(t)^*} (where ^* is the complex conjugate) provides an error signal at the DC term that is directly proportional to the carrier frequency. We then make a second-order loop using the error signal that is the running average of e(t).
In practice, the above equation can be simplified by just comparing the absolute value squared of the output of both filters: abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)).
In theory, the band-edge filter is the derivative of the matched filter in frequency, (H_be(f) = frac{H(f)}{df}). In practice, this comes down to a quarter sine wave at the point of the matched filter’s rolloff (if it’s a raised-cosine, the derivative of a cosine is a sine). Extend this sine by another quarter wave to make a half wave around the band-edges is equivalent in time to the sum of two sinc functions. The baseband filter fot the band edges is therefore derived from this sum of sincs. The band edge filters are then just the baseband signal modulated to the correct place in frequency. All of these calculations are done in the ‘design_filter’ function.
Note
We use FIR filters here because the filters have to have a flat phase response over the entire frequency range to allow their comparisons to be valid.
It is very important that the band edge filters be the derivatives of the pulse shaping filter, and that they be linear phase. Otherwise, the variance of the error will be very large.
Constructor Specific Documentation:
Make an FLL block.
Parameters: |
|
---|
declare_sample_delay(fll_band_edge_cc_sptr self, unsigned int delay)
Returns the number of taps of the filter.
pc_input_buffers_full_avg(fll_band_edge_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(fll_band_edge_cc_sptr self) -> pmt_vector_float
Print the taps to screen.
Returns the rolloff factor used for the filter.
Returns the number of sampler per symbol used for the filter.
Set the number of taps in the filter.
This sets the number of taps in the band-edge filters. Setting this will force a recalculation of the filter taps.
This should be about the same number of taps used in the transmitter’s shaping filter and also not very large. A large number of taps will result in a large delay between input and frequency estimation, and so will not be as accurate. Between 30 and 70 taps is usual.
Set the rolloff factor of the shaping filter.
This sets the rolloff factor that is used in the pulse shaping filter and is used to calculate the filter taps. Changing this will force a recalculation of the filter taps.
This should be the same value that is used in the transmitter’s pulse shaping filter. It must be between 0 and 1 and is usually between 0.2 and 0.5 (where 0.22 and 0.35 are commonly used values).
Set the number of samples per symbol.
Set’s the number of samples per symbol the system should use. This value is uesd to calculate the filter taps and will force a recalculation.
Given a stream of bits and access_code flags, assemble packets.
input: stream of bytes from digital_correlate_access_code_bb output: none. Pushes assembled packet into target queue
The framer expects a fixed length header of 2 16-bit shorts containing the payload length, followed by the payload. If the 2 16-bit shorts are not identical, this packet is ignored. Better algs are welcome.
The input data consists of bytes that have two bits used. Bit 0, the LSB, contains the data bit. Bit 1 if set, indicates that the corresponding bit is the the first bit of the packet. That is, this bit is the first one after the access code.
Constructor Specific Documentation:
Make a framer_sink_1 block.
Parameters: | target_queue – The message queue where frames go. |
---|
declare_sample_delay(framer_sink_1_sptr self, unsigned int delay)
pc_input_buffers_full_avg(framer_sink_1_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(framer_sink_1_sptr self) -> pmt_vector_float
Galois LFSR pseudo-random source.
Constructor Specific Documentation:
Make a Galois LFSR pseudo-random source block.
Parameters: |
|
---|
declare_sample_delay(glfsr_source_b_sptr self, unsigned int delay)
pc_input_buffers_full_avg(glfsr_source_b_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(glfsr_source_b_sptr self) -> pmt_vector_float
Galois LFSR pseudo-random source generating float outputs -1.0 - 1.0.
Constructor Specific Documentation:
Make a Galois LFSR pseudo-random source block.
Parameters: |
|
---|
declare_sample_delay(glfsr_source_f_sptr self, unsigned int delay)
pc_input_buffers_full_avg(glfsr_source_f_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(glfsr_source_f_sptr self) -> pmt_vector_float
HDLC deframer which takes in unpacked bits, and outputs PDU binary blobs. Frames which do not pass CRC are rejected.
Constructor Specific Documentation:
Return a shared_ptr to a new instance of digital::hdlc_deframer.
Parameters: |
|
---|
declare_sample_delay(hdlc_deframer_bp_sptr self, unsigned int delay)
pc_input_buffers_full_avg(hdlc_deframer_bp_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(hdlc_deframer_bp_sptr self) -> pmt_vector_float
HDLC framer which takes in PMT binary blobs and outputs HDLC frames as unpacked bits, with CRC and bit stuffing added. The first sample of the frame is tagged with the tag frame_tag_name and includes a length field for tagged_stream use.
This block outputs one whole frame at a time; if there is not enough output buffer space to fit a frame, it is pushed onto a queue. As a result flowgraphs which only run for a finite number of samples may not receive all frames in the queue, due to the scheduler’s granularity. For flowgraphs that stream continuously (anything using a USRP) this should not be an issue.
Constructor Specific Documentation:
Return a shared_ptr to a new instance of digital::hdlc_framer.
Parameters: | frame_tag_name – The tag to add to the first sample of each frame. |
---|
declare_sample_delay(hdlc_framer_pb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(hdlc_framer_pb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(hdlc_framer_pb_sptr self) -> pmt_vector_float
Header/Payload demuxer.
This block is designed to demultiplex packets from a bursty transmission. The typical application for this block is the case when you are receiving packets with yet-to-determine length. This block will pass the header section to other blocks for demodulation. Using the information from the demodulated header, it will then output the payload. The beginning of the header needs to be identified by a trigger signal (see below).
Theory of Operation Input 0 takes a continuous transmission of samples (items). Input 1 is an optional input for the trigger signal (mark beginning of packets). In this case, a non-zero value on input 1 identifies the beginning of a packet. Otherwise, a tag with the key specified in is used as a trigger (its value is irrelevant).
Until a trigger signal is detected, all samples are dropped onto the floor. Once a trigger is detected, a total of items are copied to output 0. The block then stalls until it receives a message on the message port . The message must be a PMT dictionary; all key/value pairs are copied as tags to the first item of the payload (which is assumed to be the first item after the header). The value corresponding to the key specified in is read and taken as the payload length. The payload, together with the header data as tags, is then copied to output 1.
Symbols, Items and Item Sizes To generically and transparently handle different kinds of modulations, including OFDM, this block distinguises between and .
Items are what are consumed at the input. Anything that uses complex samples will therefore use an itemsize of . Symbols are a way of grouping items. In OFDM, we usually don’t care about individual samples, but we do care about full OFDM symbols, so we set to the IFFT / FFT length of the OFDM modulator / demodulator. For most single-carrier modulations, this value can be set to 1 (the default value). If specified, items are discarded before every symbol. This is useful for demuxing bursts of OFDM signals.
On the output, we can deal with symbols directly by setting to true. In that case, the output item size is the .
OFDM with 48 sub-carriers, using a length-64 IFFT on the modulator, and a cyclic-prefix length of 16 samples. In this case, the itemsize is , because we’re receiving complex samples. One OFDM symbol has 64 samples, hence is set to 64, and to
Tag Handling Any tags on the input stream are copied to the corresponding output they’re on an item that is propagated. Note that a tag on the header items is copied to the header stream; that means the header-parsing block must handle these tags if they should go on the payload. A special case are tags on items that make up the guard interval. These are copied to the first item of the following symbol. If a tag is situated very close to the end of the payload, it might be unclear if it belongs to this packet or the following. In this case, it is possible that the tag might be propagated twice.
Tags outside of packets are generally discarded. If this information is important, there are two additional mechanisms to preserve the tags:
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(header_payload_demux_sptr self, unsigned int delay)
pc_input_buffers_full_avg(header_payload_demux_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(header_payload_demux_sptr self) -> pmt_vector_float
Implements a kurtosis-based adaptive equalizer on complex stream.
Warning
This block does not yet work.
“Y. Guo, J. Zhao, Y. Sun, “Sign kurtosis maximization based blind equalization algorithm,” IEEE Conf. on Control, Automation, Robotics and Vision, Vol. 3, Dec. 2004, pp. 2052 - 2057.”
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(kurtotic_equalizer_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(kurtotic_equalizer_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(kurtotic_equalizer_cc_sptr self) -> pmt_vector_float
Least-Mean-Square Decision Directed Equalizer (complex in/out)
This block implements an LMS-based decision-directed equalizer. It uses a set of weights, w, to correlate against the inputs, u, and a decisions is then made from this output. The error in the decision is used to update the weight vector.
y[n] = conj(w[n]) u[n] d[n] = decision(y[n]) e[n] = d[n] - y[n] w[n+1] = w[n] + mu u[n] conj(e[n])
Where mu is a gain value (between 0 and 1 and usualy small, around 0.001 - 0.01.
This block uses the digital_constellation object for making the decision from y[n]. Create the constellation object for whatever constellation is to be used and pass in the object. In Python, you can use something like:
self.constellation = digital.constellation_qpsk()
To create a QPSK constellation (see the digital_constellation block for more details as to what constellations are available or how to create your own). You then pass the object to this block as an sptr, or using “self.constellation.base()”.
The theory for this algorithm can be found in Chapter 9 of: S. Haykin, Adaptive Filter Theory, Upper Saddle River, NJ: Prentice Hall, 1996.
Constructor Specific Documentation:
Make an LMS decision-directed equalizer
Parameters: |
|
---|
declare_sample_delay(lms_dd_equalizer_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(lms_dd_equalizer_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(lms_dd_equalizer_cc_sptr self) -> pmt_vector_float
output[i] = map[input[i]]
This block maps an incoming signal to the value in the map. The block expects that the incoming signal has a maximum value of len(map)-1.
-> output[i] = map[input[i]]
Constructor Specific Documentation:
Make a map block.
Parameters: | map – a vector of integers that maps x to map[x]. |
---|
declare_sample_delay(map_bb_sptr self, unsigned int delay)
Apply element-wise to the elements of list and returns a list of the results, in order.
must be a list. The dynamic order in which is applied to the elements of is unspecified.
pc_input_buffers_full_avg(map_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(map_bb_sptr self) -> pmt_vector_float
This block takes care of receiving M-PSK modulated signals through phase, frequency, and symbol synchronization.
It performs carrier frequency and phase locking as well as symbol timing recovery. It works with (D)BPSK, (D)QPSK, and (D)8PSK as tested currently. It should also work for OQPSK and PI/4 DQPSK.
The phase and frequency synchronization are based on a Costas loop that finds the error of the incoming signal point compared to its nearest constellation point. The frequency and phase of the NCO are updated according to this error. There are optimized phase error detectors for BPSK and QPSK, but 8PSK is done using a brute-force computation of the constellation points to find the minimum.
The symbol synchronization is done using a modified Mueller and Muller circuit from the paper:
“G. R. Danesfahani, T. G. Jeans, “Optimisation of modified Mueller and Muller algorithm,” Electronics Letters, Vol. 31, no. 13, 22 June 1995, pp. 1032 - 1033.”
This circuit interpolates the downconverted sample (using the NCO developed by the Costas loop) every mu samples, then it finds the sampling error based on this and the past symbols and the decision made on the samples. Like the phase error detector, there are optimized decision algorithms for BPSK and QPKS, but 8PSK uses another brute force computation against all possible symbols. The modifications to the M&M used here reduce self-noise.
Constructor Specific Documentation:
Make a M-PSK receiver block.
The constructor also chooses which phase detector and decision maker to use in the work loop based on the value of M.
Parameters: |
|
---|
declare_sample_delay(mpsk_receiver_cc_sptr self, unsigned int delay)
Returns mu gain factor.
Returns omega gain factor.
Returns the relative omega limit.
Returns the modulation order (M) currently set.
Returns current value of mu.
Returns current value of omega.
pc_input_buffers_full_avg(mpsk_receiver_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(mpsk_receiver_cc_sptr self) -> pmt_vector_float
Sets value for mu gain factor.
Sets value for omega gain factor.
Sets the relative omega limit and resets omega min/max values.
Sets the modulation order (M) currently.
Sets value of mu.
Sets value of omega and its min and max values.
Sets value of theta.
Returns current value of theta.
A block for computing SNR of a signal.
This block can be used to monitor and retrieve estimations of the signal SNR. It is designed to work in a flowgraph and passes all incoming data along to its output.
The block is designed for use with M-PSK signals especially. The type of estimator is specified as the parameter in the constructor. The estimators tend to trade off performance for accuracy, although experimentation should be done to figure out the right approach for a given implementation. Further, the current set of estimators are designed and proven theoretically under AWGN conditions; some amount of error should be assumed and/or estimated for real channel conditions.
Constructor Specific Documentation:
Factory function returning shared pointer of this class
Parameters: |
|
---|
Get the running-average coefficient.
declare_sample_delay(mpsk_snr_est_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(mpsk_snr_est_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(mpsk_snr_est_cc_sptr self) -> pmt_vector_float
Set the running-average coefficient.
Set the number of samples between SNR tags.
Set type of estimator to use.
Return the estimated signal-to-noise ratio in decibels.
Return how many samples between SNR tags.
MSK/GMSK timing recovery
This block performs timing synchronization on CPM modulations using a fourth-order nonlinearity feedback method which is non-data-aided. The block does not require prior phase synchronization but is relatively sensitive to frequency offset (keep offset to 0.1x symbol rate).
For details on the algorithm, see: A.N. D’Andrea, U. Mengali, R. Reggiannini: A digital approach to clock recovery in generalized minimum shift keying. IEEE Transactions on Vehicular Technology, Vol. 39, Issue 3.
Constructor Specific Documentation:
Make an MSK timing recovery block.
Parameters: |
|
---|
declare_sample_delay(msk_timing_recovery_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(msk_timing_recovery_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(msk_timing_recovery_cc_sptr self) -> pmt_vector_float
Create frequency domain OFDM symbols from complex values, add pilots.
This block turns a stream of complex, scalar modulation symbols into vectors which are the input for an IFFT in an OFDM transmitter. It also supports the possibility of placing pilot symbols onto the carriers.
The carriers can be allocated freely, if a carrier is not allocated, it is set to zero. This allows doing OFDMA-style carrier allocations.
Input: A tagged stream of complex scalars. The first item must have a tag containing the number of complex symbols in this frame. Output: A tagged stream of complex vectors of length fft_len. This can directly be connected to an FFT block. Make sure to set this block to ‘reverse’ for the IFFT. If is true, the FFT block must activate FFT shifting, otherwise, set shifting to false. If given, sync words are prepended to the output. Note that sync words are prepended verbatim, make sure they are shifted (or not).
Carrier indexes are always such that index 0 is the DC carrier (note: you should not allocate this carrier). The carriers below the DC carrier are either indexed with negative numbers, or with indexes larger than . Index -1 and index both identify the carrier below the DC carrier.
There are some basic checks in place during initialization which check that the carrier allocation table is valid. However, it is possible to overwrite data symbols with pilot symbols, or provide a carrier allocation that has mismatching pilot symbol positions and -values.
Tags are propagated such that a tag on an incoming complex symbol is mapped to the corresponding OFDM symbol. There is one exception: If a tag is on the first OFDM symbol, it is assumed that this tag should stay there, so it is moved to the front even if a sync word is included (any other tags will never be attached to the sync word). This allows tags to control the transmit timing to pass through in the correct position.
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(ofdm_carrier_allocator_cvc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(ofdm_carrier_allocator_cvc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(ofdm_carrier_allocator_cvc_sptr self) -> pmt_vector_float
Estimate channel and coarse frequency offset for OFDM from preambles
Input: OFDM symbols (in frequency domain). The first one (or two) symbols are expected to be synchronisation symbols, which are used to estimate the coarse freq offset and the initial equalizer taps (these symbols are removed from the stream). The following are passed through unmodified (the actual equalisation must be done elsewhere). Output: The data symbols, without the synchronisation symbols. The first data symbol passed through has two tags: ‘ofdm_sync_carr_offset’ (integer), the coarse frequency offset as number of carriers, and ‘ofdm_sync_eq_taps’ (complex vector). Any tags attached to the synchronisation symbols are attached to the first data symbol. All other tags are propagated as expected.
Note
The vector on ofdm_sync_eq_taps is already frequency-corrected, whereas the rest is not.
This block assumes the frequency offset is even (i.e. an integer multiple of 2).
[1] Schmidl, T.M. and Cox, D.C., “Robust frequency and timing synchronization for OFDM”, Communications, IEEE Transactions on, 1997. [2] K.D. Kammeyer, “Nachrichtenuebertragung,” Chapter. 16.3.2.
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(ofdm_chanest_vcvc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(ofdm_chanest_vcvc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(ofdm_chanest_vcvc_sptr self) -> pmt_vector_float
Adds a cyclic prefix and performs pulse shaping on OFDM symbols.
Input: OFDM symbols (in the time domain, i.e. after the IFFT). Optionally, entire frames can be processed. In this case, must be specified which holds the key of the tag that denotes how many OFDM symbols are in a frame. Output: A stream of (scalar) complex symbols, which include the cyclic prefix and the pulse shaping. Note: If complete frames are processed, and is greater than zero, the final OFDM symbol is followed by the delay line of the pulse shaping.
The pulse shape is a raised cosine in the time domain.
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(ofdm_cyclic_prefixer_sptr self, unsigned int delay)
pc_input_buffers_full_avg(ofdm_cyclic_prefixer_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(ofdm_cyclic_prefixer_sptr self) -> pmt_vector_float
Proxy of C++ gr::digital::ofdm_equalizer_base class
equalize(ofdm_equalizer_base_sptr self, gr_complex * frame, int n_sym, pmt_vector_cfloat initial_taps=std::vector< gr_complex >(), tags_vector_t tags=std::vector< gr::tag_t >())
Run the actual equalization.
Return the current channel state.
Reset the channel information state knowledge.
Constructor Specific Documentation:
Parameters: |
|
---|
equalize(ofdm_equalizer_simpledfe_sptr self, gr_complex * frame, int n_sym, pmt_vector_cfloat initial_taps=std::vector< gr_complex >(), tags_vector_t tags=std::vector< gr::tag_t >())
Run the actual equalization.
Return the current channel state.
Reset the channel information state knowledge.
Constructor Specific Documentation:
Parameters: |
|
---|
equalize(ofdm_equalizer_static_sptr self, gr_complex * frame, int n_sym, pmt_vector_cfloat initial_taps=std::vector< gr_complex >(), tags_vector_t tags=std::vector< gr::tag_t >())
Run the actual equalization.
Return the current channel state.
Reset the channel information state knowledge.
take a vector of complex constellation points in from an FFT and performs a correlation and equalization.
This block takes the output of an FFT of a received OFDM symbol and finds the start of a frame based on two known symbols. It also looks at the surrounding bins in the FFT output for the correlation in case there is a large frequency shift in the data. This block assumes that the fine frequency shift has already been corrected and that the samples fall in the middle of one FFT bin.
It then uses one of those known symbols to estimate the channel response over all subcarriers and does a simple 1-tap equalization on all subcarriers. This corrects for the phase and amplitude distortion caused by the channel.
Constructor Specific Documentation:
Make an OFDM correlator and equalizer.
Parameters: |
|
---|
declare_sample_delay(ofdm_frame_acquisition_sptr self, unsigned int delay)
pc_input_buffers_full_avg(ofdm_frame_acquisition_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(ofdm_frame_acquisition_sptr self) -> pmt_vector_float
Return an estimate of the SNR of the channel.
OFDM frame equalizer.
Performs equalization in one or two dimensions on a tagged OFDM frame.
This does two things: First, it removes the coarse carrier offset. If a tag is found on the first item with the key ‘ofdm_sync_carr_offset’, this is interpreted as the coarse frequency offset in number of carriers. Next, it performs equalization in one or two dimensions on a tagged OFDM frame. The actual equalization is done by a ofdm_frame_equalizer object, outside of the block.
Note that the tag with the coarse carrier offset is not removed. Blocks downstream from this block must not attempt to also correct this offset.
Input: a tagged series of OFDM symbols. Output: The same as the input, but equalized and frequency-corrected.
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(ofdm_frame_equalizer_vcvc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(ofdm_frame_equalizer_vcvc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(ofdm_frame_equalizer_vcvc_sptr self) -> pmt_vector_float
Takes an OFDM symbol in, demaps it into bits of 0’s and 1’s, packs them into packets, and sends to to a message queue sink.
NOTE: The mod input parameter simply chooses a pre-defined demapper/slicer. Eventually, we want to be able to pass in a reference to an object to do the demapping and slicing for a given modulation type.
Constructor Specific Documentation:
Make an OFDM frame sink block.
Parameters: |
|
---|
declare_sample_delay(ofdm_frame_sink_sptr self, unsigned int delay)
pc_input_buffers_full_avg(ofdm_frame_sink_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(ofdm_frame_sink_sptr self) -> pmt_vector_float
insert “pre-modulated” preamble symbols before each payload.
Constructor Specific Documentation:
Make an OFDM preamble inserter block.
Parameters: |
|
---|
declare_sample_delay(ofdm_insert_preamble_sptr self, unsigned int delay)
pc_input_buffers_full_avg(ofdm_insert_preamble_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(ofdm_insert_preamble_sptr self) -> pmt_vector_float
take a stream of bytes in and map to a vector of complex constellation points suitable for IFFT input to be used in an ofdm modulator.
Abstract class must be subclassed with specific mapping.
Constructor Specific Documentation:
Make an OFDM mapper block.
Parameters: |
|
---|
declare_sample_delay(ofdm_mapper_bcv_sptr self, unsigned int delay)
pc_input_buffers_full_avg(ofdm_mapper_bcv_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(ofdm_mapper_bcv_sptr self) -> pmt_vector_float
does the rest of the OFDM stuff
Constructor Specific Documentation:
Make an OFDM sampler block.
Parameters: |
|
---|
declare_sample_delay(ofdm_sampler_sptr self, unsigned int delay)
pc_input_buffers_full_avg(ofdm_sampler_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(ofdm_sampler_sptr self) -> pmt_vector_float
make(ofdm_carrier_allocator_cvc_sptr allocator, std::string const & packet_len_tag_key=””, int symbols_skipped=0, std::string const & carr_offset_key=””, bool input_is_shifted=True) -> ofdm_serializer_vcc_sptr
Serializes complex modulations symbols from OFDM sub-carriers.
This is the inverse block to the carrier_allocator_cvc. It outputs the complex data symbols as a tagged stream, discarding the pilot symbols.
If given, two different tags are parsed: The first key () specifies the number of OFDM symbols in the frame at the input. The second key () specifies the number of complex symbols that are coded into this frame. If given, this second key is then used at the output, otherwise, is used. If both are given, the packet length specifies the maximum number of output items, and the frame length specifies the exact number of consumed input items.
It is possible to correct a carrier offset in this function by passing another tag with said offset.
Input: Complex vectors of length Output: Complex scalars, in the same order as specified in occupied_carriers.
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(ofdm_serializer_vcc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(ofdm_serializer_vcc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(ofdm_serializer_vcc_sptr self) -> pmt_vector_float
Schmidl & Cox synchronisation for OFDM.
Input: complex samples. Output 0: Fine frequency offset, scaled by the OFDM symbol duration. This is in [1]. The normalized frequency offset is then 2.0*output0/fft_len. Output 1: Beginning of the first OFDM symbol after the first (doubled) OFDM symbol. The beginning is marked with a 1 (it’s 0 everywhere else).
The evaluation of the coarse frequency offset is done in this block. Also, the initial equalizer taps are not calculated here.
Note that we use a different normalization factor in the timing metric than the authors do in their original work[1]. If the timing metric (8) is we calculate the normalization as i.e., we estimate the energy from half-symbols. This avoids spurious detects at the end of a burst, when the energy level suddenly drops.
[1] Schmidl, T.M. and Cox, D.C., “Robust frequency and timing synchronization for OFDM”, Communications, IEEE Transactions on, 1997.
Constructor Specific Documentation:
Parameters: |
|
---|
Default header formatter for digital packet transmission.
For bursty/packetized digital transmission, packets are usually prepended with a packet header, containing the number of bytes etc. This class is not a block, but a tool to create these packet header.
This is a default packet header (see header_formatter()) for a description on the header format). To create other header, derive packet header creator classes from this function.
gr::digital::packet_headergenerator_bb uses header generators derived from this class to create packet headers from data streams.
Constructor Specific Documentation:
Parameters: |
|
---|
Encodes the header information in the given tags into bits and places them into .
Uses the following header format: Bits 0-11: The packet length (what was stored in the tag with key ) Bits 12-23: The header number (counts up everytime this function is called) Bit 24-31: 8-Bit CRC All other bits: Are set to zero
If the header length is smaller than 32, bits are simply left out. For this reason, they always start with the LSB.
However, it is recommended to stay above 32 Bits, in order to have a working CRC.
Inverse function to header_formatter().
Reads the bit stream in and writes a corresponding tag into .
make(long header_len, std::string const & len_tag_key=”packet_len”) -> packet_headergenerator_bb_sptr
Generates a header for a tagged, streamed packet.
Input: A tagged stream. This is consumed entirely, it is not appended to the output stream. Output: An tagged stream containing the header. The details on the header are set in a header formatter object (of type packet_header_default or a subclass thereof). If only a number of bits is specified, a default header is generated (see packet_header_default).
Constructor Specific Documentation:
Parameters: |
|
---|
declare_sample_delay(packet_headergenerator_bb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(packet_headergenerator_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(packet_headergenerator_bb_sptr self) -> pmt_vector_float
Header utility for OFDM signals.
Constructor Specific Documentation:
Parameters: |
|
---|
Encodes the header information in the given tags into bits and places them into .
Uses the following header format: Bits 0-11: The packet length (what was stored in the tag with key ) Bits 12-23: The header number (counts up everytime this function is called) Bit 24-31: 8-Bit CRC All other bits: Are set to zero
If the header length is smaller than 32, bits are simply left out. For this reason, they always start with the LSB.
However, it is recommended to stay above 32 Bits, in order to have a working CRC.
Inverse function to header_formatter().
Reads the bit stream in and writes a corresponding tag into .
make(long header_len, std::string const & len_tag_key) -> packet_headerparser_b_sptr
Post header metadata as a PMT.
In a sense, this is the inverse block to packet_headergenerator_bb. The difference is, the parsed header is not output as a stream, but as a PMT dictionary, which is published to message port with the id “header_data”.
The dictionary consists of the tags created by the header formatter object. You should be able to use the exact same formatter object as used on the Tx side in the packet_headergenerator_bb.
If only a header length is given, this block uses the default header format.
Constructor Specific Documentation:
Parameters: | header_formatter – Header object. This should be the same as used for packet_headergenerator_bb. |
---|
declare_sample_delay(packet_headerparser_b_sptr self, unsigned int delay)
pc_input_buffers_full_avg(packet_headerparser_b_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(packet_headerparser_b_sptr self) -> pmt_vector_float
process received bits looking for packet sync, header, and process bits into packet
input: stream of symbols to be sliced.
output: none. Pushes assembled packet into target queue
The packet sink takes in a stream of binary symbols that are sliced around 0. The bits are then checked for the to determine find and decode the packet. It then expects a fixed length header of 2 16-bit shorts containing the payload length, followed by the payload. If the 2 16-bit shorts are not identical, this packet is ignored. Better algs are welcome.
This block is not very useful anymore as it only works with 2-level modulations such as BPSK or GMSK. The block can generally be replaced with a correlate access code and frame sink blocks.
Constructor Specific Documentation:
Make a packet_sink block.
Parameters: |
|
---|
return true if we detect carrier
declare_sample_delay(packet_sink_sptr self, unsigned int delay)
pc_input_buffers_full_avg(packet_sink_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(packet_sink_sptr self) -> pmt_vector_float
Timing synchronizer using polyphase filterbanks.
This block performs timing synchronization for PAM signals by minimizing the derivative of the filtered signal, which in turn maximizes the SNR and minimizes ISI.
This approach works by setting up two filterbanks; one filterbank contains the signal’s pulse shaping matched filter (such as a root raised cosine filter), where each branch of the filterbank contains a different phase of the filter. The second filterbank contains the derivatives of the filters in the first filterbank. Thinking of this in the time domain, the first filterbank contains filters that have a sinc shape to them. We want to align the output signal to be sampled at exactly the peak of the sinc shape. The derivative of the sinc contains a zero at the maximum point of the sinc (sinc(0) = 1, sinc(0)’ = 0). Furthermore, the region around the zero point is relatively linear. We make use of this fact to generate the error signal.
If the signal out of the derivative filters is d_i[n] for the ith filter, and the output of the matched filter is x_i[n], we calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in the real and imaginary parts. There are two reasons we multiply by the signal itself. First, if the symbol could be positive or negative going, but we want the error term to always tell us to go in the same direction depending on which side of the zero point we are on. The sign of x_i[n] adjusts the error term to do this. Second, the magnitude of x_i[n] scales the error term depending on the symbol’s amplitude, so larger signals give us a stronger error term because we have more confidence in that symbol’s value. Using the magnitude of x_i[n] instead of just the sign is especially good for signals with low SNR.
The error signal, e[n], gives us a value proportional to how far away from the zero point we are in the derivative signal. We want to drive this value to zero, so we set up a second order loop. We have two variables for this loop; d_k is the filter number in the filterbank we are on and d_rate is the rate which we travel through the filters in the steady state. That is, due to the natural clock differences between the transmitter and receiver, d_rate represents that difference and would traverse the filter phase paths to keep the receiver locked. Thinking of this as a second-order PLL, the d_rate is the frequency and d_k is the phase. So we update d_rate and d_k using the standard loop equations based on two error signals, d_alpha and d_beta. We have these two values set based on each other for a critically damped system, so in the block constructor, we just ask for “gain,” which is d_alpha while d_beta is equal to (gain^2)/4.
The block’s parameters are:
Reference: f. j. harris and M. Rice, “Multirate Digital Filters for Symbol Timing Synchronization in Software Defined Radios”, IEEE Selected Areas in Communications, Vol. 19, No. 12, Dec., 2001.
Constructor Specific Documentation:
Build the polyphase filterbank timing synchronizer.
Parameters: |
|
---|
Returns the loop gain alpha.
Returns the loop gain beta.
Returns the taps of the matched filter for a particular channel
Returns the current clock rate.
Returns the loop damping factor.
declare_sample_delay(pfb_clock_sync_ccf_sptr self, unsigned int delay)
Returns the taps in the derivative filter for a particular channel
Returns all of the taps of the derivative filter
Return the derivative filter taps as a formatted string for printing
Returns the current error of the control loop.
Returns the loop bandwidth.
pc_input_buffers_full_avg(pfb_clock_sync_ccf_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(pfb_clock_sync_ccf_sptr self) -> pmt_vector_float
Returns the current phase arm of the control loop.
Returns the current rate of the control loop.
Set the loop gain alpha.
Set’s the loop filter’s alpha gain parameter.
This value should really only be set by adjusting the loop bandwidth and damping factor.
Set the loop gain beta.
Set’s the loop filter’s beta gain parameter.
This value should really only be set by adjusting the loop bandwidth and damping factor.
Set the loop damping factor.
Set the loop filter’s damping factor to . The damping factor should be sqrt(2)/2.0 for critically damped systems. Set it to anything else only if you know what you are doing. It must be a number between 0 and 1.
When a new damping factor is set, the gains, alpha and beta, of the loop are recalculated by a call to update_gains().
Set the loop bandwidth.
Set the loop filter’s bandwidth to . This should be between 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive number.
When a new damping factor is set, the gains, alpha and beta, of the loop are recalculated by a call to update_gains().
Set the maximum deviation from 0 d_rate can have
set_taps(pfb_clock_sync_ccf_sptr self, pmt_vector_float taps, std::vector< std::vector< float,std::allocator< float > >,std::allocator< std::vector< float,std::allocator< float > > > > & ourtaps, std::vector< gr::filter::kernel::fir_filter_ccf *,std::allocator< gr::filter::kernel::fir_filter_ccf * > > & ourfilter)
Resets the filterbank’s filter taps with the new prototype filter
Returns all of the taps of the matched filter
Return the taps as a formatted string for printing
update the system gains from omega and eta
This function updates the system gains based on the loop bandwidth and damping factor of the system. These two factors can be set separately through their own set functions.
Timing synchronizer using polyphase filterbanks.
This block performs timing synchronization for PAM signals by minimizing the derivative of the filtered signal, which in turn maximizes the SNR and minimizes ISI.
This approach works by setting up two filterbanks; one filterbank contains the signal’s pulse shaping matched filter (such as a root raised cosine filter), where each branch of the filterbank contains a different phase of the filter. The second filterbank contains the derivatives of the filters in the first filterbank. Thinking of this in the time domain, the first filterbank contains filters that have a sinc shape to them. We want to align the output signal to be sampled at exactly the peak of the sinc shape. The derivative of the sinc contains a zero at the maximum point of the sinc (sinc(0) = 1, sinc(0)’ = 0). Furthermore, the region around the zero point is relatively linear. We make use of this fact to generate the error signal.
If the signal out of the derivative filters is d_i[n] for the ith filter, and the output of the matched filter is x_i[n], we calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in the real and imaginary parts. There are two reasons we multiply by the signal itself. First, if the symbol could be positive or negative going, but we want the error term to always tell us to go in the same direction depending on which side of the zero point we are on. The sign of x_i[n] adjusts the error term to do this. Second, the magnitude of x_i[n] scales the error term depending on the symbol’s amplitude, so larger signals give us a stronger error term because we have more confidence in that symbol’s value. Using the magnitude of x_i[n] instead of just the sign is especially good for signals with low SNR.
The error signal, e[n], gives us a value proportional to how far away from the zero point we are in the derivative signal. We want to drive this value to zero, so we set up a second order loop. We have two variables for this loop; d_k is the filter number in the filterbank we are on and d_rate is the rate which we travel through the filters in the steady state. That is, due to the natural clock differences between the transmitter and receiver, d_rate represents that difference and would traverse the filter phase paths to keep the receiver locked. Thinking of this as a second-order PLL, the d_rate is the frequency and d_k is the phase. So we update d_rate and d_k using the standard loop equations based on two error signals, d_alpha and d_beta. We have these two values set based on each other for a critically damped system, so in the block constructor, we just ask for “gain,” which is d_alpha while d_beta is equal to (gain^2)/4.
The block’s parameters are:
Reference: f. j. harris and M. Rice, “Multirate Digital Filters for Symbol Timing Synchronization in Software Defined Radios”, IEEE Selected Areas in Communications, Vol. 19, No. 12, Dec., 2001.
Constructor Specific Documentation:
Build the polyphase filterbank timing synchronizer.
Parameters: |
|
---|
Returns the loop gain alpha.
Returns the loop gain beta.
Returns the taps of the matched filter for a particular channel
Returns the current clock rate.
Returns the loop damping factor.
declare_sample_delay(pfb_clock_sync_fff_sptr self, unsigned int delay)
Returns the taps in the derivative filter for a particular channel
Returns all of the taps of the derivative filter
Return the derivative filter taps as a formatted string for printing
Returns the loop bandwidth.
pc_input_buffers_full_avg(pfb_clock_sync_fff_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(pfb_clock_sync_fff_sptr self) -> pmt_vector_float
Set the loop gain alpha.
Set’s the loop filter’s alpha gain parameter.
This value should really only be set by adjusting the loop bandwidth and damping factor.
Set the loop gain beta.
Set’s the loop filter’s beta gain parameter.
This value should really only be set by adjusting the loop bandwidth and damping factor.
Set the loop damping factor.
Set the loop filter’s damping factor to . The damping factor should be sqrt(2)/2.0 for critically damped systems. Set it to anything else only if you know what you are doing. It must be a number between 0 and 1.
When a new damping factor is set, the gains, alpha and beta, of the loop are recalculated by a call to update_gains().
Set the loop bandwidth.
Set the loop filter’s bandwidth to . This should be between 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive number.
When a new damping factor is set, the gains, alpha and beta, of the loop are recalculated by a call to update_gains().
Set the maximum deviation from 0 d_rate can have
set_taps(pfb_clock_sync_fff_sptr self, pmt_vector_float taps, std::vector< std::vector< float,std::allocator< float > >,std::allocator< std::vector< float,std::allocator< float > > > > & ourtaps, std::vector< gr::filter::kernel::fir_filter_fff *,std::allocator< gr::filter::kernel::fir_filter_fff * > > & ourfilter)
Resets the filterbank’s filter taps with the new prototype filter
Returns all of the taps of the matched filter
Return the taps as a formatted string for printing
update the system gains from omega and eta
This function updates the system gains based on the loop bandwidth and damping factor of the system. These two factors can be set separately through their own set functions.
PN code sequential search correlator.
Receives complex baseband signal, outputs complex correlation against reference PN code, one sample per PN code period. The PN sequence is generated using a GLFSR.
Constructor Specific Documentation:
Make PN code sequential search correlator block.
Parameters: |
|
---|
declare_sample_delay(pn_correlator_cc_sptr self, unsigned int delay)
pc_input_buffers_full_avg(pn_correlator_cc_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(pn_correlator_cc_sptr self) -> pmt_vector_float
This block maintains a running average of the input stream and makes it available as an accessor function. The input stream is type unsigned char.
If you send this block a stream of unpacked bytes, it will tell you what the bit density is.
Constructor Specific Documentation:
Make a density probe block.
Parameters: | alpha – Average filter constant |
---|
declare_sample_delay(probe_density_b_sptr self, unsigned int delay)
Returns the current density value.
pc_input_buffers_full_avg(probe_density_b_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(probe_density_b_sptr self) -> pmt_vector_float
Set the average filter constant.
A probe for computing SNR of a PSK signal.
This is a probe block (a sink) that can be used to monitor and retrieve estimations of the signal SNR. This probe is designed for use with M-PSK signals especially. The type of estimator is specified as the parameter in the constructor. The estimators tend to trade off performance for accuracy, although experimentation should be done to figure out the right approach for a given implementation. Further, the current set of estimators are designed and proven theoretically under AWGN conditions; some amount of error should be assumed and/or estimated for real channel conditions.
The block has three output message ports that will emit a message every msg_samples number of samples. These message ports are: Some calibration is required to convert dBx of the signal and noise power estimates to real measurements, such as dBm.
Constructor Specific Documentation:
Make an MPSK SNR probe.
Parameters:
Parameters: |
|
---|
Get the running-average coefficient.
declare_sample_delay(probe_mpsk_snr_est_c_sptr self, unsigned int delay)
Return how many samples between SNR messages.
Return the estimated noise power in decibels.
pc_input_buffers_full_avg(probe_mpsk_snr_est_c_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(probe_mpsk_snr_est_c_sptr self) -> pmt_vector_float
Set the running-average coefficient.
Set the number of samples between SNR messages.
Set type of estimator to use.
Return the estimated signal power in decibels.
Return the estimated signal-to-noise ratio in decibels.
Scramble an input stream using an LFSR.
This block works on the LSB only of the input data stream, i.e., on an “unpacked binary” stream, and produces the same format on its output.
Constructor Specific Documentation:
Make a scramber block.
Parameters: |
|
---|
declare_sample_delay(scrambler_bb_sptr self, unsigned int delay)
pc_input_buffers_full_avg(scrambler_bb_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(scrambler_bb_sptr self) -> pmt_vector_float
inverse of simple_framer (more or less)
Constructor Specific Documentation:
Parameters: | payload_bytesize – |
---|
declare_sample_delay(simple_correlator_sptr self, unsigned int delay)
pc_input_buffers_full_avg(simple_correlator_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(simple_correlator_sptr self) -> pmt_vector_float
add sync field, seq number and command field to payload
Takes in enough samples to create a full output frame. The frame is prepended with the GRSF_SYNC (defind in simple_framer_sync.h) and an 8-bit sequence number.
Constructor Specific Documentation:
Make a simple_framer block.
Parameters: | payload_bytesize – The size of the payload in bytes. |
---|
declare_sample_delay(simple_framer_sptr self, unsigned int delay)
pc_input_buffers_full_avg(simple_framer_sptr self) -> pmt_vector_float
pc_output_buffers_full_avg(simple_framer_sptr self) -> pmt_vector_float