summaryrefslogtreecommitdiff
path: root/gr-digital/include/gnuradio/digital/header_payload_demux.h
blob: bcd6bd108a9c2d6a977e593fb5f1e5da27bb7fdb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/* -*- c++ -*- */
/* Copyright 2012-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_PAYLOAD_DEMUX_H
#define INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_H

#include <gnuradio/digital/api.h>
#include <gnuradio/block.h>

namespace gr {
  namespace digital {

    /*!
     * \brief Header/Payload demuxer (HPD).
     * \ingroup packet_operators_blk
     *
     * \details
     * 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).
     *
     * \section hpd_theory_of_ops 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 \p trigger_tag_key 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 \p header_len items are copied to output 0.
     * The block then stalls until it receives a message on the message port
     * \p header_data. 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 \p length_tag_key is read
     * and taken as the payload length. The payload, together with the header data
     * as tags, is then copied to output 1.
     *
     * If the header demodulation fails, the header must send a PMT with value
     * pmt::PMT_F. The state gets reset and the header is ignored.
     *
     * \section hpd_item_sizes Symbols, Items and Item Sizes
     *
     * To generically and transparently handle different kinds of modulations,
     * including OFDM, this block distinguises between \b symbols and \b items.
     *
     * Items are what are consumed at the input. Anything that uses complex samples
     * will therefore use an itemsize of `sizeof(gr_complex)`. 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 \p items_per_symbol to the
     * IFFT / FFT length of the OFDM modulator / demodulator.
     * For single-carrier modulations, this value can be set to the number of
     * samples per symbol, to handle data in number of symbols, or to 1 to
     * handle data in number of samples.
     * If specified, \p guard_interval 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 \p output_symbols
     * to true. In that case, the output item size is the <em>symbol size</em>.
     *
     * \b Example: OFDM with 48 sub-carriers, using a length-64 IFFT on the
     * modulator, and a cyclic-prefix length of 16 samples. In this case,
     * \p itemsize is `sizeof(gr_complex)`, because we're receiving complex
     * samples. One OFDM symbol has 64 samples, hence \p items_per_symbol is
     * set to 64, and \p guard_interval to 16. The header length is specified
     * in number of OFDM symbols. Because we want to deal with full OFDM
     * symbols, we set \p output_symbols to true.
     *
     * \b Example: PSK-modulated signals, with 4 samples per symbol. Again,
     * \p itemsize is `sizeof(gr_complex)` because we're still dealing with
     * complex samples. \p items_per_symbol is 4, because one item is one
     * sample. \p guard_interval must be set to 0. The header length is
     * given in number of PSK symbols.
     *
     * \section hpd_uncertainty Handling timing uncertainty on the trigger
     *
     * By default, the assumption is made that the trigger arrives on *exactly*
     * the sample that the header starts. These triggers typically come from
     * timing synchronization algorithms which may be suboptimal, and have a
     * known timing uncertainty (e.g., we know the trigger might be a sample
     * too early or too late).
     *
     * The demuxer has an option for this case, the \p header_padding. If this
     * value is non-zero, it specifies the number of items that are prepended
     * and appended to the header before copying it to the header output.
     *
     * Example: Say our synchronization algorithm can be off by up to two
     * samples, and the header length is 20 samples. So we set \p header_len
     * to 20, and \p header_padding to 2.
     * Now assume a trigger arrives on sample index 100. We copy a total of
     * 24 samples to the header port, starting at sample index 98.
     *
     * The payload is *not* padded. Let's say the header demod reports a
     * payload length of 100. In the previous examples, we would copy 100
     * samples to the payload port, starting at sample index 120 (this means
     * the padded samples appended to the header are copied to both ports!).
     * However, the header demodulator has the option to specify a payload
     * offset, which cannot exceed the padding value. To do this, include
     * a key `payload_offset` in the message sent back to the HPD. A negative
     * value means the payload starts earlier than otherwise.
     * (If you wanted to always pad the payload, you could set `payload_offset`
     * to `-header_padding` and increase the reported length of the payload).
     *
     * Because the padding is specified in number of items, and not symbols,
     * this value can only be multiples of the number of items per symbol *if*
     * either \p output_symbols is true, or a guard interval is specified (or
     * both). Note that in practice, it is rare that both a guard interval is
     * specified *and* a padding value is required. The difference between the
     * padding value and a guard interval is that a guard interval is part of
     * the signal, and comes with *every* symbol, whereas the header padding
     * is added to only the header, and is not by design.
     *
     * \section hpd_tag_handling Tag Handling
     *
     * Any tags on the input stream are copied to the corresponding output *if* 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 there are tags that
     * carry important information that must not be list, there are two
     * additional mechanisms to preserve the tags:
     * - Timing tags might be relevant to know \b when a packet was received. By
     *   specifying the name of a timestamp tag and the sample rate at this block, it
     *   keeps track of the time and will add the time to the first item of every packet.
     *   The name of the timestamp tag is usually 'rx_time' (see, e.g.,
     *   gr::uhd::usrp_source::make()).
     *   The time value must be specified in the UHD time format.
     * - Other tags are simply stored and updated. As an example, the user might want to know the
     *   rx frequency, which UHD stores in the rx_freq tag. In this case, add the tag name 'rx_freq'
     *   to the list of \p special_tags. This block will then always save the most current value of
     *   'rx_freq' and add it to the beginning of every packet.
     *
     */
    class DIGITAL_API header_payload_demux : virtual public block
    {
     public:
      typedef boost::shared_ptr<header_payload_demux> sptr;

      /*!
       * \param header_len Number of symbols per header
       * \param items_per_symbol Number of items per symbol
       * \param guard_interval Number of items between two consecutive symbols
       * \param length_tag_key Key of the frame length tag
       * \param trigger_tag_key Key of the trigger tag
       * \param output_symbols Output symbols (true) or items (false)?
       * \param itemsize Item size (bytes per item)
       * \param timing_tag_key The name of the tag with timing information, usually 'rx_time' or empty (this means timing info is discarded)
       * \param samp_rate Sampling rate at the input. Necessary to calculate the rx time of packets.
       * \param special_tags A vector of strings denoting tags which shall be preserved (see \ref hpd_tag_handling)
       * \param header_padding A number of items that is appended and prepended to the header.
       */
      static sptr make(
          const int header_len,
          const int items_per_symbol=1,
          const int guard_interval=0,
          const std::string &length_tag_key="frame_len",
          const std::string &trigger_tag_key="",
          const bool output_symbols=false,
          const size_t itemsize=sizeof(gr_complex),
          const std::string &timing_tag_key="",
          const double samp_rate=1.0,
          const std::vector<std::string> &special_tags=std::vector<std::string>(),
          const size_t header_padding=0
      );
    };

  } // namespace digital
} // namespace gr

#endif /* INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_H */