GNU Radio 3.7.2 C++ API
In many cases, the PHY layer of a digital transceiver uses packetsto break down the transmission (as opposed to continuously broadcasting data), and GNU Radio natively supports this kind of transmission. The basic mechanisms which allow this are the Message Passing and the Tagged Stream Blocks.
With the tools provided in GNU Radio, simple digital packet transmission schemes are easily implemented, allowing the creation of packet-based communication links and even -networks.
Typically, a packet consists of the following elements:
At the transmitter stage, these are modulated and prepared for transmission (a forward error correction code may also be applied). Because the transmitter knows te packet length, is a trivial matter to create the transmit frames using the tagged stream blocks.
The receiver has to perform a multitude of things to obtain the packet again. Most importantly, it has to convert an infinite stream (coming from the receiver device, e.g. a UHD source block) into a packetized, tagged stream.
The key element to return back to packetized state is the gr::digital::header_payload_demux. At its first input, it receives a continuous stream of sample data, coming from the receiver device. It discards all the incoming samples, until the beginning of a packet is signalled, either by a stream tag, or a trigger signal on its second input.
Once such a beginning is detected, the demultiplexer copies the preamble and header to the first output (it must know the exact length of these elements). The header can then be demodulated with any suitable set of GNU Radio blocks.
To turn the information stored in the demodulated header bits into metadata which can be understood by GNU Radio, a gr::digital::packet_headerparser_b block is used to turn the header data into a message, which is passed back to the header/payload demuxer. The latter then knows the length of the payload, and passes that out on the second output, along with all the metadata obtained in the header demodulation chain.
The knowledge of the header structure (i.e. how to turn a sequence of bits into a payload length etc.) is stored in an object of type gr::digital::packet_header_default. This must be passed to the header parser block.
The image above shows an example of a simple OFDM receiver. It has no forward error correction, and uses the simplest possible frame structure.
The four elements of the packet receiver are highlighted. The first part is the packet detector and synchronizer. The samples piped into the header/payload demuxer are fine frequency corrected, and a trigger signal is sent to mark the beginning of the burst.
Next, the header demodulation receiver chain is activated. The FFT shifts OFDM symbols to the frequency domain. The coarse frequency offset and initial channel state are estimated from the preamble and are added to the stream as tags. The OFDM symbol containing the header is passed to an equalizer, which also corrects the coarse frequency offset. A serializer picks the data symbols from the OFDM symbol and outputs them as a sequence of scalar complex values, which are then demodulated into bits (in this case BPSK is used).
The bits are interpreted by the header parser, which uses a gr::digital::packet_header_ofdm object to interpret the bits (the latter is derived form gr::digital::packet_header_default). The result from the header parser is then fed back to the demuxer, which now knows the length of payload and outputs that as a tagged stream.
The payload demodulation chain is the same as the header demodulation chain, only the channel estimator block is unnecessary as the channel state information is still available as metadata on the payload tagged stream.
This flow graph, as well as the corresponding transmitter, can be found in gr-digital/examples/ofdm/rx_ofdm.grc and gr-digital/examples/ofdm/tx_ofdm.grc