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