GNU Radio Manual and C++ API Reference 3.7.14.0
The Free & Open Software Radio Ecosystem
header_buffer.h
Go to the documentation of this file.
1/* -*- c++ -*- */
2/* Copyright 2015-2016 Free Software Foundation, Inc.
3 *
4 * This file is part of GNU Radio
5 *
6 * GNU Radio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3, or (at your option)
9 * any later version.
10 *
11 * GNU Radio is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Radio; see the file COPYING. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street,
19 * Boston, MA 02110-1301, USA.
20 */
21
22#ifndef INCLUDED_DIGITAL_HEADER_BUFFER_H
23#define INCLUDED_DIGITAL_HEADER_BUFFER_H
24
26#include <stdint.h>
27#include <cstddef>
28#include <vector>
29
30namespace gr {
31namespace digital {
32
33/*!
34 * \brief Helper class for handling payload headers.
35 * \ingroup packet_operators_blk
36 *
37 * \details
38 *
39 * This class is used by the header format blocks (e.g.,
40 * digital::header_format_default) to make it easier to deal with
41 * payload headers. This class functions in two different ways
42 * depending on if it is used in a transmitter or receiver. When
43 * used in a transmitter, this class helps us build headers out of
44 * the fields of the protocol. When used in a receiver, this class
45 * helps us parse the received bits into the protocol's fields.
46 *
47 * This page describes how to work with the different modes,
48 * transmit or receive. The class is instructed as to which mode
49 * it is in by how the constructor is called. If the constructor
50 * is passed a valid array (non NULL), then it is in transmit mode
51 * and will pack this buffer with the header fields. If that
52 * buffer is NULL, the object is in receive mode.
53 *
54 * \section header_buffer_tx Transmit Mode
55 *
56 * When passed a valid buffer in the constructor, this object is in
57 * transmit mode. We can then use the add_field[N] functions to
58 * add new fields to this header. The buffer MUST be large enough
59 * to hold the full header. As this class is meant to work mostly
60 * with the digital::header_format_default and child
61 * classes, the header length can be read from
62 * digital::header_format_default::header_nbytes().
63 *
64 * Each field is a specific length of 8, 16, 32, or 64 bits that
65 * are to be transmitted in network byte order. We can adjust the
66 * direction of the bytes by setting the byte-swap flag, \p bs, to
67 * true or false.
68 *
69 * The length argument (\p len) for all add_field[N] calls is the
70 * number of bytes actually accounted for in the data
71 * structure. Often, we would use the full size of the field,
72 * which is sizeof(dtype), and the add_field[N] call defaults to
73 * len=N. Occasionally, we may need to use fewer bytes than
74 * actually represented by the data type. An example would be the
75 * access code used in the header_format_default, which is a
76 * uint64_t type but may have fewer bytes used in the actual
77 * access code.
78 *
79 * The function that calls this class is expected to handle the
80 * memory handling of the buffer -- both allocating and
81 * deallocating.
82 *
83 * As simple example of using this class in transmit mode:
84 *
85 * \verbatim
86 uint8_t* buffer = (uint8_t*)volk_malloc(header_nbytes(),
87 volk_get_alignment());
88
89 header_buffer hdr(buffer);
90 hdr.add_field64(sync_word, sync_word_len);
91 hdr.add_field16(payload_length);
92 hdr.add_field8(header_flags);
93 hdr.add_field8(header_options);
94
95 // Do something with the header
96
97 volk_free(buffer);
98 \endverbatim
99 *
100 * In this example, the header contains four fields:
101 *
102 * \verbatim
103 |0 15|16 23|24 31|
104 | sync word |
105 | |
106 | length | flags | options |
107 \endverbatim
108 *
109 * The sync word can be up to 64-bits, but the add_field64 is also
110 * passed the number of actual bytes in the sync word and so could
111 * be fewer.
112 *
113 * \section header_buffer_rx Receive Mode
114 *
115 * In receive mode, we build up the header as bits are received by
116 * inserting them with insert_bit. We can find out how long the
117 * current header is, in bits, using the call to length(). If the
118 * header is of the appropriate length, we can then start
119 * extracting the fields from it. When we are done with the
120 * current header, call clear() to reset the internal buffer to
121 * empty, which will mean that length() returns 0.
122 *
123 * The header fields are extracted using the extract_field[N]
124 * functions. Like the add_field[N] functions, we specify the size
125 * (in bits) of the field we are extracting. We pass this function
126 * the bit-position of the expected field in the received header
127 * buffer. The extract_field[N] assumes that the number of bits
128 * for the field is N, but we can tell the function to use fewer
129 * bits if we want. Setting the length parameter of these
130 * functions greater than N is illegal, and it will throw an
131 * error.
132 *
133 * For example, given a header of | length | seq. num. | where the
134 * length is 16 bits and the sequence number is 32 bits, we would
135 * use:
136 *
137 * \verbatim
138 uint16_t len = d_hdr_reg.extract_field16(0);
139 uint32_t seq = d_hdr_reg.extract_field32(16);
140 \endverbatim
141 *
142 * The extract_field functions are specific to data types of the
143 * field and the number of bits for each field is inferred by the
144 * data type. So extract_field16 assumes we want all 16 bits in
145 * the field represented.
146 *
147 * Some headers have fields that are not standard sizes of
148 * integers, like a 1 bit, 4 bit, or even 12 bit fields. We can
149 * ask for fewer bits for each field. say:
150 *
151 * \verbatim
152 |0 15|16 19|20 31|
153 | len | flags | options |
154 \endverbatim
155 *
156 * We would use the following extraction functions:
157 *
158 * \verbatim
159 uint16_t len = d_hdr_reg.extract_field16(0);
160 uint8_t flags = d_hdr_reg.extract_field8(16, 4);
161 uint16_t opts = d_hdr_reg.extract_field16(20, 12);
162 \endverbatim
163 *
164 * \sa header_format_default
165 * \sa header_format_counter
166 * \sa header_format_crc
167 */
169{
170private:
171 std::size_t d_offset;
172 uint8_t* d_buffer;
173
174 std::vector<bool> d_input;
175
176public:
177 /*!
178 * Create a header buffer object with a pre-allocated buffer, \p
179 * buffer, to hold the formatted header data.
180 *
181 * If \p buffer is set to NULL, then this object is in receive
182 * mode meant to receive bits from an incoming data stream and
183 * provide the ability to extract fields. In this mode, calls to
184 * add_field are invalid and will be nops.
185 */
186 header_buffer(uint8_t* buffer = NULL);
187
188 /*!
189 * Class destructor.
190 */
192
193 /*!
194 * Clears the header.
195 *
196 * In transmit mode, this resets the current offset so new
197 * add_field functions start adding data to the start of the
198 * buffer.
199 *
200 * In receive mode, this clears the buffer that we have inserted
201 * bits in to.
202 */
203 void clear();
204
205
206 /*!
207 * In transmit mode, this returns the length of the data in
208 * the buffer (not the allocated buffer length).
209 *
210 * In receiving mode, this returns the current length in bits of
211 * the received header.
212 */
213 std::size_t length() const;
214
215 /*!
216 * Returns a constant pointer to the buffer.
217 */
218 const uint8_t* header() const;
219
220 /*!
221 * Add an 8-bit field to the header.
222 *
223 * \param data The 8-bit data item.
224 * \param len Length (in bits) of \p data.
225 * \param bs Set to 'true' to byte swap the data.
226 */
227 void add_field8(uint8_t data, int len = 8, bool bs = false);
228
229 /*!
230 * Add an 16-bit field to the header.
231 *
232 * \param data The 16-bit data item.
233 * \param len Length (in bits) of \p data.
234 * \param bs Set to 'true' to byte swap the data.
235 */
236 void add_field16(uint16_t data, int len = 16, bool bs = false);
237
238 /*!
239 * Add an 32-bit field to the header.
240 *
241 * \param data The 32-bit data item.
242 * \param len Length (in bits) of \p data.
243 * \param bs Set to 'true' to byte swap the data.
244 */
245 void add_field32(uint32_t data, int len = 32, bool bs = false);
246
247 /*!
248 * Add an 64-bit field to the header.
249 *
250 * \param data The 64-bit data item.
251 * \param len Length (in bits) of \p data.
252 * \param bs Set to 'true' to byte swap the data.
253 */
254 void add_field64(uint64_t data, int len = 64, bool bs = false);
255
256
257 /*****************************************************
258 * Receive mode to build a header from bits *
259 *****************************************************/
260
261 /*!
262 * Insert a new bit on the back of the input buffer. This
263 * function is used in receive mode to add new bits as they are
264 * received for later use of the extract_field functions.
265 *
266 * \param bit New bit to add.
267 */
268 void insert_bit(int bit);
269
270 /*!
271 * Returns up to an 8-bit field in the packet header.
272 *
273 * \param pos Bit position of the start of the field.
274 * \param len The number of bits in the field.
275 * \param bs Set to 'true' to byte swap the data.
276 */
277 uint8_t extract_field8(int pos, int len = 8, bool bs = false);
278
279 /*!
280 * Returns up to a 16-bit field in the packet header.
281 *
282 * \param pos Bit position of the start of the field.
283 * \param len The number of bits in the field.
284 * \param bs Set to 'true' to byte swap the data.
285 */
286 uint16_t extract_field16(int pos, int len = 16, bool bs = false);
287
288 /*!
289 * Returns up to a 32-bit field in the packet header.
290 *
291 * \param pos Bit position of the start of the field.
292 * \param len The number of bits in the field.
293 * \param bs Set to 'true' to byte swap the data.
294 */
295 uint32_t extract_field32(int pos, int len = 32, bool bs = false);
296
297 /*!
298 * Returns up to a 64-bit field in the packet header.
299 *
300 * \param pos Bit position of the start of the field.
301 * \param len The number of bits in the field.
302 * \param bs Set to 'true' to byte swap the data.
303 */
304 uint64_t extract_field64(int pos, int len = 64, bool bs = false);
305};
306
307} // namespace digital
308} // namespace gr
309
310#endif /* INCLUDED_DIGITAL_HEADER_BUFFER_H */
Single writer, multiple reader fifo.
Definition: buffer.h:57
Helper class for handling payload headers.
Definition: header_buffer.h:169
void add_field8(uint8_t data, int len=8, bool bs=false)
uint32_t extract_field32(int pos, int len=32, bool bs=false)
void add_field64(uint64_t data, int len=64, bool bs=false)
uint16_t extract_field16(int pos, int len=16, bool bs=false)
void add_field16(uint16_t data, int len=16, bool bs=false)
uint8_t extract_field8(int pos, int len=8, bool bs=false)
std::size_t length() const
void add_field32(uint32_t data, int len=32, bool bs=false)
header_buffer(uint8_t *buffer=NULL)
uint64_t extract_field64(int pos, int len=64, bool bs=false)
const uint8_t * header() const
#define DIGITAL_API
Definition: gr-digital/include/gnuradio/digital/api.h:30
Include this header to use the message passing features.
Definition: basic_block.h:45