GNU Radio Manual and C++ API Reference  3.8.1.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 
25 #include <gnuradio/digital/api.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <vector>
29 
30 namespace gr {
31 namespace 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 {
170 private:
171  size_t d_offset;
172  uint8_t* d_buffer;
173 
174  std::vector<bool> d_input;
175 
176 public:
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  */
191  ~header_buffer();
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  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 */
#define DIGITAL_API
Definition: gr-digital/include/gnuradio/digital/api.h:30
Single writer, multiple reader fifo.
Definition: buffer.h:56
GNU Radio logging wrapper for log4cpp library (C++ port of log4j)
Definition: basic_block.h:43
Helper class for handling payload headers.
Definition: header_buffer.h:168
PMT_API size_t length(const pmt_t &v)
Return the number of elements in v.