Packet Communications: Difference between revisions

From GNU Radio
Jump to navigation Jump to search
(Completion of revisions for 3.10)
 
(29 intermediate revisions by 3 users not shown)
Line 1: Line 1:
This tutorial presents methods to transmit and receive packet data using burst transmissions. The examples show data originating from a PDU message source. A hardware simulation is shown using BPSK modulation.
<b>NOTE: This document has been revised. The previous version can be found in [[Packet_Communications_Test_Page]].</b><br>


This tutorial presents methods to transmit and receive packet data. As was shown in the QPSK and BPSK tutorials, the received bit data stream could be verified by comparing it to the (delayed) transmitted data. However, there was no way to recover the byte alignment of those bits. That is where packet processing comes into play.
<br><br>
== Prerequisites ==
== Prerequisites ==


Line 8: Line 10:
* [[Stream Tags|'''Stream Tags''']]
* [[Stream Tags|'''Stream Tags''']]
* [[Message Passing|'''Message Passing''']]
* [[Message Passing|'''Message Passing''']]
* [[Understanding_ZMQ_Blocks|'''Understanding ZMQ Blocks''']]
* [https://www.gnuradio.org/doc/doxygen/page_packet_comms.html '''Packet Communications''']


== Notes ==
== Header Format Object ==


The current tutorial has been revised and tested with GNU Radio version 3.9.4.0. The 'Polyphase Clock Sync' has been replaced with the [[Symbol_Sync]]; and the 'CMA Equalizer' has been replaced with the [[Linear_Equalizer]] and [[Adaptive_Algorithm]].
The following blocks:
* [[Protocol_Formatter]],
* [[Protocol_Formatter_(Async)]],
* [[Protocol_Parser]],
* [[Packet_Header_Generator]], and
* [[Packet_Header_Parser]]
use a "Header Format Object", but there is no block with that name. To create such an object, a [[Variable]] block is used. The 'Value' field can be one of several chioces depending on what type of header is needed, such as:
    * digital.header_format_default(access_code, threshold)
    * digital.header_format_crc(len_key, num_key)
    * digital.header_format_counter(access_code, threshold, bps)


Links to the flowgraphs have been updated to GNU Radio version 3.9.4.0.
== Simulating Packet Comms Using Messages ==


== Simulating Baseband Packet Processing ==
In order to grasp the basics of packet processing, this section presents a transmitter and receiver simulation using standard GNU Radio blocks without any modulation or channel impairments.
 
In order to grasp the basics of packet processing, this section presents a transmitter and receiver simulation using standard GNU Radio blocks without any modulation or channel impairments. As was shown in the QPSK and BPSK tutorials, the received bit data stream could be verified by comparing it to the (delayed) transmitted data. However, there was no way to recover the byte alignment of those bits. That is where packet processing comes into play.


=== Building the flowgraph ===
=== Building the flowgraph ===
Line 25: Line 32:
Build the following flowgraph using the details given below:
Build the following flowgraph using the details given below:


[[File:Pkt_7_base_fg.png|800px]]
[[File:Pkt_8_fg.png|800px]]


<hr>
<hr>


This flowgraph can be downloaded from [[Media:Pkt_7_base.grc]].
This flowgraph can be downloaded from [[Media:Pkt_8.grc]].


==== Message Strobe ====
; Message Strobe
For the Message Strobe to generate a PDU, the Message PMT must be of the form
For the Message Strobe to generate a PDU, the Message PMT must be of the form
   pmt.cons(pmt.PMT_NIL,pmt.init_u8vector(9,(71,78,85,32,82,97,100,105,111)))
   pmt.cons(pmt.PMT_NIL,pmt.init_u8vector(9,(71,78,85,32,82,97,100,105,111)))
This specific vector has a length of 9 and the character values of "GNU Radio". It is sent every two seconds.
This specific vector has a length of 9 and the character values of "GNU Radio". It is sent twice per second.
 
==== Async CRC32 ====


The Async CRC32 block computes the CRC of the payload and appends the value to it.
; CRC Append
The CRC Append block computes the CRC32 of the payload (message) and appends the value to it.


==== Variable, Id: hdr_format ====
; Variable, Id = hdr_format
The Protocol Formatter uses a Format Object to define its parameters. The one used in this example is
The Protocol Formatter uses a Format Object to define its parameters. The one used in this example is
   hdr_format digital.header_format_crc(len_key, num_key)
   hdr_format digital.header_format_default(access_key, 0)
It generates a header with the packet length, packet number, and a 16-bit CRC. No access code is created.
It generates a header with the access code and the 16-bit payload length (repeated).


==== Protocol Formatter ====
; Protocol Formatter (Async)
The entry for the Format Obj. is 'hdr_format'
The entry for the Format Obj. is 'hdr_format'. It produces separate header and payload output messages.


==== Tagged Stream Mux ====
; PDU to Tagged Stream
Converts received PDUs into a tagged stream by adding length tags.


The Tagged Stream Mux combines the header and the payload.
; Tagged Stream Mux
The Tagged Stream Mux combines the header and the payload into a single stream.


==== Header/Payload Demux ====
; Correlate Access Code - Tag Stream
This block searches the input stream for a match to the given Access Code. The code is given as a ''string'' with the 32 bit value (ones and zeros).


The Header/Payload Demux block synchronizes with the header data and then outputs the payload data.
; CRC Check
The CRC Check block computes the CRC of the payload and compares it to the CRC in the message. If they match, the payload is output to the "ok" port with the CRC stripped from the message. If the CRC does not match, the entire message with CRC is output to the "fail" port.


==== Protocol Parser ====
<hr>
The entry for the Format Obj. is 'hdr_format'


=== Testing ===
=== Testing ===


To test the flowgraph, click the "Execute the flowgraph" icon, or press F6. An example of the output is:
1. Open a new terminal window.<br>
 
2. Create a working directory, e.g. `~/GRdev`:
    mkdir ~/GRdev
3. Change to that directory:
    cd ~/GRdev
4. Assuming that you downloaded `Pkt_8.grc`, copy it to the working directory:
    cp ~/Downloads/Pkt_8.grc ./pkt_8.grc
5. Compile `pkt_8.grc`:
    grcc pkt_8.grc
6. Execute `pkt_8`:
    python3 -u pkt_8.py
7. A new window will open showing two Time Sinks which are the input and output of the 'Correlate Access Code - Tag Stream' block.<br>
8. Once the Correlate Output shows a signal, wait one second, then terminate that window (titled `pkt_8`) by clicking the "X" in the upper right corner.<br>
9. The terminal screen should show repeats of this message:<br>
<pre>
<pre>
***** VERBOSE PDU DEBUG PRINT ******
***** VERBOSE PDU DEBUG PRINT ******
()
()
pdu length = 4 bytes
pdu length =         9 bytes
pdu vector contents =
0000: 0d 10 00 3a
************************************
***** VERBOSE PDU DEBUG PRINT ******
()
pdu length = 13 bytes
pdu vector contents =
0000: 47 4e 55 20 52 61 64 69 6f 8f aa 09 f1
************************************
 
----------------------------------------------------------------------
Tag Debug:
Input Stream: 00
  Offset: 13  Source: n/a    Key: packet_len  Value: 13
  Offset: 13  Source: n/a    Key: packet_num  Value: 1
----------------------------------------------------------------------
***** VERBOSE PDU DEBUG PRINT ******
((packet_num . 1))
pdu length = 9 bytes
pdu vector contents =  
pdu vector contents =  
0000: 47 4e 55 20 52 61 64 69 6f  
0000: 47 4e 55 20 52 61 64 69 6f  
************************************
************************************
</pre>
</pre>
The "pdu vector contents" are the character codes for "GNU Radio".


The first PDU DEBUG PRINT is the header data containing the payload length, packet number, and a CRC16 of the header.
== Simulating Packet Comms Using Streams ==


The second PDU DEBUG PRINT is the payload including a CRC32 of the data.
=== Building the flowgraph ===
 
The Tag Debug shows the length tag and the packet number tag.
 
The third PDU DEBUG PRINT is the received payload ("GNU Radio").
 
== Using BPSK with Hardware Simulation (version 3.9) ==
 
The Protocol Formatter supports three header format types: default, count, and crc. The crc style is illustrated in the simulation above.
 
In order to create a preamble, a default header, and the payload data in one PDU message, an Embedded Python block was created. The code is contained in the GRC file, but also is shown here:
<pre>
"""
Embedded Python Block
"""
 
import numpy as np
from gnuradio import gr
import pmt
 
class blk(gr.sync_block):
    """Packet Format"""
 
    def __init__(self):
        gr.sync_block.__init__(self,
            name = "Packet Format",
            in_sig = None,
            out_sig = None)
        self.message_port_register_in(pmt.intern('PDU_in'))
        self.message_port_register_out(pmt.intern('PDU_out'))
        self.set_msg_handler(pmt.intern('PDU_in'), self.handle_msg)
 
    def handle_msg(self, msg):
        inMsg = pmt.to_python (msg)
        pld = inMsg[1]
        # print (pld)
        mLen = len(pld)
        # print (mLen)
        if (mLen > 0):
            char_list = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,225,90,232,147]
            char_list.append (mLen >> 8)
            char_list.append (mLen & 255)
            char_list.append (mLen >> 8)
            char_list.append (mLen & 255)
            char_list.extend (pld)
            # print (char_list)
            out_len = len(char_list)
            # print (out_len)
            self.message_port_pub(pmt.intern('PDU_out'), pmt.cons(pmt.PMT_NIL,pmt.init_u8vector(out_len,(char_list))))
</pre>
 
The preamble is 32 bytes of 0x55 giving alternating 1's and 0's. The non-cyclical 32-bit access code is 0xe15ae893 (binary '11100001010110101110100010010011'). The length of the payload is repeated (16 bits). Then the payload is appended.
 
=== Transmitting a Signal ===


Build the following flowgraph using the details given below:
Build the following flowgraph using the details given below:


[[File:Pkt_xmt_fg.png|800px]]
[[File:Str_pkt_10_fg.png|800px]]


<hr>
<hr>
This flowgraph can be downloaded from [[Media:Str_pkt_10.grc]].


This flowgraph can be downloaded from [[Media:Pkt_xmt.grc]]. The BPSK modulation is done in the same manner as the [[Simulation_example:_BPSK_Demodulation|BPSK Demodulation]] tutorial. Do a Generate (F5) or Execute (F6) to create the pkt_xmt.py file.
; File Source
 
The File Source reads a padded text file and outputs to a stream.
=== Receiving a Signal ===


Build a separate flowgraph using the details below:
; Stream to Tagged Stream
Converts a regular stream into a tagged stream by adding length tags in regular intervals.


[[File:Pkt_rcv_fg.png|800px]]
; Stream CRC32
The Stream CRC32 block computes the CRC of the payload and appends the value to it.


<hr>
; Protocol Formatter
The entry for the Format Obj. is 'hdr_format'. The Protocol Formatter produces the header for the packet.


This flowgraph can be downloaded from [[Media:Pkt_rcv.grc]]. For GNU Radio version 3.9 there are two changes: the Polyphase Clock Sync has been replaced by the [[Symbol_Sync]] block; and the CMA equalizer has been replaced by a Linear Equalizer and an Adaptive Algorithm.
; Tagged Stream Mux
The Mux combines the protocol header and the payload data into one packet.


The output of the Map block is the received bit stream. The 'Correlate Access Code - Tag Stream' block searches for the given access code by slicing the soft decision symbol inputs. Once found, it expects the following 32 samples to contain a header that includes the frame length (16 bits for the length, repeated). It decodes the header to get the frame length in order to set up the the tagged stream key information.
; Correlate Access Code - Tag Stream
The Access Code is a ''string'' with the 32 bit value.


The remaining blocks operate as in the simulation example above.
<hr>


=== Testing ===
=== Testing ===


When using GRC, doing a Generate and/or Run creates a Python file with the same name as the .grc file. You can execute the Python file without running GRC again.
==== Create an input file ====
 
For testing this system we will use two processes, so we will need two terminal windows.


Terminal 1:
The success of this methodology is based on the input file being padded to a multiple of 'packet_len' bytes so that the last few bytes of the source file are not lost in a partial unprocessed packet. To create a padded file for input to the flowgraph, the following Python program can be used:
* since you just finished building the pkt_rcv flowgraph, you can just do a Run. After a few seconds, a window will open with the GUI Constellation Sink.


Terminal 2:
Open another terminal window.
* change to whatever directory you used to generate the flowgraph for pkt_xmt
* execute the following command:
    python3 pkt_xmt.py
* After a few seconds, a window will open with the GUI Time Sink.
The output of the transmitter is:
[[File:Pkt_xmt_out.png|800px]]
The output of the receiver is shown on the GRC console.
<pre>
<pre>
***** VERBOSE PDU DEBUG PRINT ******
#!/usr/bin/python3
()
# -*- coding: utf-8 -*-
pdu length = 9 bytes
pdu vector contents =
0000: 47 4e 55 20 52 61 64 69 6f
************************************
</pre>


The PDU DEBUG PRINT is the received payload ("GNU Radio").
# Padded_File_Source.py


To terminate each of the processes cleanly, click on the 'X' in the upper corner of the GUI rather than using Control-C.
import os.path
import sys


== Using BPSK with Hardware Simulation (version 3.8) ==
Pkt_len = 252
_debug = 1          # set to zero to turn off diagnostics


The Protocol Formatter supports three header format types: default, count, and crc. The crc style is illustrated in the simulation above.
if (len(sys.argv) < 2):
    print ('Usage: python3 Padded_File_Source.py <input file>')
    print ('Number of arguments=', len(sys.argv))
    print ('Argument List:', str(sys.argv))
    exit (1)
# test if file exists
fn = sys.argv[1]
if (_debug):
    print (fn)
if not(os.path.exists(fn)):
    print('The input file does not exist')
    exit (1)


In order to create a preamble, a default header, and the payload data in one PDU message, an Embedded Python block was created. The code is contained in the GRC file, but also is shown here:
# open input file
* note that for GNURadio 3.8 a numpy array is used in the handling of the incoming PMT message. It must also be put into a byte array before being placed into the PMT u8vector for publishing to the "PDU_out" port
f_in = open (fn, 'r')
<pre>
"""
Embedded Python Block
"""


import numpy as np
# open output file
from gnuradio import gr
f_out = open ("padded.txt", 'w')
import pmt
import array
class blk(gr.sync_block):
    """Packet Format"""


     def __init__(self):
while True:
         gr.sync_block.__init__(self,
     buff = f_in.read (Pkt_len)
            name = "Packet Format GR38",
    b_len = len(buff)
            in_sig = None,
    if (_debug):
            out_sig = None)
         print (b_len)
         self.message_port_register_in(pmt.intern('PDU_in'))
    if b_len == 0:
         self.message_port_register_out(pmt.intern('PDU_out0'))
         print ('End of file')
         self.set_msg_handler(pmt.intern('PDU_in'), self.handle_msg)
        break
    while (b_len < Pkt_len):
         buff += ' '
         b_len += 1
    # write output
    f_out.write (buff)


    def handle_msg(self, msg):
f_in.close()
        inMsg = pmt.to_python (msg)
f_out.close()
        pld = inMsg[1] ## type-> numpy.ndarray
        mLen = len(pld)
        if (mLen > 0):
            ## create a numpy array of type 'int' with preamble and sync word
            tmp_char_list = np.array([85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,225,90,232,147],dtype=int)
            ## append length 2x
            tmp_char_list=np.append(tmp_char_list,(mLen >> 8))
            tmp_char_list=np.append(tmp_char_list,(mLen & 255))
            tmp_char_list=np.append(tmp_char_list,(mLen >> 8))
            tmp_char_list=np.append(tmp_char_list,(mLen & 255))
            tmp_char_list_len=len(tmp_char_list)
            ## append original payload
            new_char_list=np.insert(tmp_char_list,tmp_char_list_len,pld)
            new_char_list_len=len(new_char_list)
            ## save final numpy array as byte array (requires 'import array')
            byte_array_new_char_list=array.array('B',new_char_list)
            new_bytes_out_len = len(byte_array_new_char_list)
            ## create PMT u8vector using byte array
            new_out_bytes_pmt=pmt.cons(pmt.PMT_NIL,pmt.init_u8vector(new_bytes_out_len,(byte_array_new_char_list)))
            self.message_port_pub(pmt.intern('PDU_out0'), new_out_bytes_pmt)
</pre>
</pre>


=== Transmitting a Signal ===
Note that the 'Pkt_len' in the Python program and the 'packet_len' value in the flowgraph 'Stream to Tagged Stream' block must be the same. The output of the Python program is a file named "padded.txt".
Build the following flowgraph using the details given below:
[[File:Pkt_xmt_gr38.png]]


=== Receiving a Signal ===
1. In a terminal window change to `~/GRdev`:
Build a separate flowgraph using the details below:
    cd ~/GRdev
* note for GNURadio 3.8: the Linear Equalizer shown in the GNURadio 3.9 example is not available. The LMS DD Equalizer has been used instead.
2. Copy the `Padded_File_Source.py` file above into a text file in `~/GRdev`.<br>
[[File:pkt_rcv_gr38.png]]
3. Create a padded text file:
    python3 Padded_File_Source.py <input text file>
Choose a text file which is not very long and not a multiple of 252 bytes.


=== Testing ===
==== Executing the flowgraph ====


== Adding Channel Impairments ==
4. Assuming that you downloaded `Str_pkt_10.grc`, copy it to the working directory:
    cp ~/Downloads/Str_pkt_10.grc ./str_pkt_10.grc
5. Execute `gnuradio-companion`.
    gnuradio-companion
6. Open the `str_pkt_10.grc` flowgraph.<br>
7. Right click on the 'File Source' block and select Properties.<br>
8. Change the File path to your 'padded.text'. (Your user name will be different!)<br>
9. Click 'Apply' and 'OK'.<br>
10. Click 'Generate the flowgraph' or press F5.<br>
11. Exit `gnuradio-companion` by clicking the "X" in the upper right corner of the screen.<br>
12. On the same terminal screen, execute `str_pkt_10`:
    python3 -u str_pkt_10.py
13. A new window will open showing two Time Sinks which are the input and output of the Correlate Access Code - Tag Stream block.<br>
14. Once the Correlate Output signal quits changing, the file transfer has finished. Terminate that window (titled `str_pkt_10`) by clicking the "X" in the upper right corner.<br>
15. Examine the output file "output.txt". The output file will be the same as the original file, but will have trailing spaces at the end as a result of the padding.<br>


<b>NOTE:</b> For the testing above, the transmitter data on port 49203 was fed directly into the receiver on port 49203. In this section, we will insert another flowgraph between those two ZMQ ports, so the ZMQ SUB Source port in the receiver needs to be changed to 49201 and the flowgraph regenerated.
== Observations ==


Build the following flowgraph:
During the development and testing for this tutorial, the following items were observed:
 
[[File:Chan_loopback_fg.png|810px]]


* The 'Header/Payload Demux' and 'Protocol Parser' blocks seem to work only with the 'digital.header_format_crc' format.
* The 'Correlate Access Code - Tag Stream' block requires the Default Header Format Obj. and expects a 32-bit access code.
<hr>
<hr>
 
<code>Tested with v3.10.9.2</code><br>
This flowgraph can be downloaded from [[Media:Chan_loopback.grc]].
[[Category:Tutorials]]
 
[[Category:Tested With 3.10]]
For testing this arrangement we will use three processes, so we will need three terminal windows.
 
Terminal 1:
* since you just finished building the chan_loopback flowgraph, you can just do a Run. After a few seconds, a window will open with GUI Range controls for noise level, frequency offset, and timing offset.
 
Terminal 2:
Open another terminal window.
* change to whatever directory you used to generate the flowgraph for pkt_xmt
* execute the following command:
    python3 pkt_xmt.py
* After a few seconds, a window will open with the GUI Time Sink.
 
Terminal 3:
Open another terminal window.
* change to whatever directory you used to generate the flowgraph for pkt_rcv
* execute the following command:
    python3 pkt_rcv.py
* After a few seconds, a window will open with the GUI Constellation Sink.
 
Now you can adjust the various channel impairments to see the effect on the received constellation and the ability to synchronize on the received data. The sample rate should be set to 768kHz.
 
To terminate each of the processes cleanly, click on the 'X' in the upper corner of the GUI rather than using Control-C.
 
== Using Hardware ==
 
If you look at https://github.com/duggabe/gr-control you will see that this tutorial follows the same design. If the user were to build two computer installations with this setup, they could send and receive packets.
 
== Conclusions ==
 
Based on this tutorial, there are several things which can be concluded:
 
# BPSK and QPSK are not well suited for burst transmissions due to the need for the receiver to converge on the actual timing and frequency values.
# The longer the times between bursts of data, the more the receiver will need to reconverge on the timing and frequency values for the new burst.
# Since almost all amateur radio communications are half duplex and bursts of data, a more appropriate modulation would be FSK or AFSK. The same packet formatting and recovery would still apply.

Latest revision as of 17:42, 29 January 2025

NOTE: This document has been revised. The previous version can be found in Packet_Communications_Test_Page.

This tutorial presents methods to transmit and receive packet data. As was shown in the QPSK and BPSK tutorials, the received bit data stream could be verified by comparing it to the (delayed) transmitted data. However, there was no way to recover the byte alignment of those bits. That is where packet processing comes into play.

Prerequisites

Header Format Object

The following blocks:

use a "Header Format Object", but there is no block with that name. To create such an object, a Variable block is used. The 'Value' field can be one of several chioces depending on what type of header is needed, such as:

   * digital.header_format_default(access_code, threshold)
   * digital.header_format_crc(len_key, num_key)
   * digital.header_format_counter(access_code, threshold, bps)

Simulating Packet Comms Using Messages

In order to grasp the basics of packet processing, this section presents a transmitter and receiver simulation using standard GNU Radio blocks without any modulation or channel impairments.

Building the flowgraph

Build the following flowgraph using the details given below:

Pkt 8 fg.png


This flowgraph can be downloaded from Media:Pkt_8.grc.

Message Strobe

For the Message Strobe to generate a PDU, the Message PMT must be of the form

 pmt.cons(pmt.PMT_NIL,pmt.init_u8vector(9,(71,78,85,32,82,97,100,105,111)))

This specific vector has a length of 9 and the character values of "GNU Radio". It is sent twice per second.

CRC Append

The CRC Append block computes the CRC32 of the payload (message) and appends the value to it.

Variable, Id = hdr_format

The Protocol Formatter uses a Format Object to define its parameters. The one used in this example is

 hdr_format digital.header_format_default(access_key, 0)

It generates a header with the access code and the 16-bit payload length (repeated).

Protocol Formatter (Async)

The entry for the Format Obj. is 'hdr_format'. It produces separate header and payload output messages.

PDU to Tagged Stream

Converts received PDUs into a tagged stream by adding length tags.

Tagged Stream Mux

The Tagged Stream Mux combines the header and the payload into a single stream.

Correlate Access Code - Tag Stream

This block searches the input stream for a match to the given Access Code. The code is given as a string with the 32 bit value (ones and zeros).

CRC Check

The CRC Check block computes the CRC of the payload and compares it to the CRC in the message. If they match, the payload is output to the "ok" port with the CRC stripped from the message. If the CRC does not match, the entire message with CRC is output to the "fail" port.


Testing

1. Open a new terminal window.
2. Create a working directory, e.g. `~/GRdev`:

   mkdir ~/GRdev

3. Change to that directory:

   cd ~/GRdev

4. Assuming that you downloaded `Pkt_8.grc`, copy it to the working directory:

   cp ~/Downloads/Pkt_8.grc ./pkt_8.grc

5. Compile `pkt_8.grc`:

   grcc pkt_8.grc

6. Execute `pkt_8`:

   python3 -u pkt_8.py

7. A new window will open showing two Time Sinks which are the input and output of the 'Correlate Access Code - Tag Stream' block.
8. Once the Correlate Output shows a signal, wait one second, then terminate that window (titled `pkt_8`) by clicking the "X" in the upper right corner.
9. The terminal screen should show repeats of this message:

***** VERBOSE PDU DEBUG PRINT ******
()
pdu length =          9 bytes
pdu vector contents = 
0000: 47 4e 55 20 52 61 64 69 6f 
************************************

The "pdu vector contents" are the character codes for "GNU Radio".

Simulating Packet Comms Using Streams

Building the flowgraph

Build the following flowgraph using the details given below:

Str pkt 10 fg.png


This flowgraph can be downloaded from Media:Str_pkt_10.grc.

File Source

The File Source reads a padded text file and outputs to a stream.

Stream to Tagged Stream

Converts a regular stream into a tagged stream by adding length tags in regular intervals.

Stream CRC32

The Stream CRC32 block computes the CRC of the payload and appends the value to it.

Protocol Formatter

The entry for the Format Obj. is 'hdr_format'. The Protocol Formatter produces the header for the packet.

Tagged Stream Mux

The Mux combines the protocol header and the payload data into one packet.

Correlate Access Code - Tag Stream

The Access Code is a string with the 32 bit value.


Testing

Create an input file

The success of this methodology is based on the input file being padded to a multiple of 'packet_len' bytes so that the last few bytes of the source file are not lost in a partial unprocessed packet. To create a padded file for input to the flowgraph, the following Python program can be used:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

# Padded_File_Source.py

import os.path
import sys

Pkt_len = 252
_debug = 1          # set to zero to turn off diagnostics

if (len(sys.argv) < 2):
    print ('Usage: python3 Padded_File_Source.py <input file>')
    print ('Number of arguments=', len(sys.argv))
    print ('Argument List:', str(sys.argv))
    exit (1)
# test if file exists
fn = sys.argv[1]
if (_debug):
    print (fn)
if not(os.path.exists(fn)):
    print('The input file does not exist')
    exit (1)

# open input file
f_in = open (fn, 'r')

# open output file
f_out = open ("padded.txt", 'w')

while True:
    buff = f_in.read (Pkt_len)
    b_len = len(buff)
    if (_debug):
        print (b_len)
    if b_len == 0:
        print ('End of file')
        break
    while (b_len < Pkt_len):
        buff += ' '
        b_len += 1
    # write output
    f_out.write (buff)

f_in.close()
f_out.close()

Note that the 'Pkt_len' in the Python program and the 'packet_len' value in the flowgraph 'Stream to Tagged Stream' block must be the same. The output of the Python program is a file named "padded.txt".

1. In a terminal window change to `~/GRdev`:

   cd ~/GRdev

2. Copy the `Padded_File_Source.py` file above into a text file in `~/GRdev`.
3. Create a padded text file:

   python3 Padded_File_Source.py <input text file>

Choose a text file which is not very long and not a multiple of 252 bytes.

Executing the flowgraph

4. Assuming that you downloaded `Str_pkt_10.grc`, copy it to the working directory:

   cp ~/Downloads/Str_pkt_10.grc ./str_pkt_10.grc

5. Execute `gnuradio-companion`.

   gnuradio-companion

6. Open the `str_pkt_10.grc` flowgraph.
7. Right click on the 'File Source' block and select Properties.
8. Change the File path to your 'padded.text'. (Your user name will be different!)
9. Click 'Apply' and 'OK'.
10. Click 'Generate the flowgraph' or press F5.
11. Exit `gnuradio-companion` by clicking the "X" in the upper right corner of the screen.
12. On the same terminal screen, execute `str_pkt_10`:

   python3 -u str_pkt_10.py

13. A new window will open showing two Time Sinks which are the input and output of the Correlate Access Code - Tag Stream block.
14. Once the Correlate Output signal quits changing, the file transfer has finished. Terminate that window (titled `str_pkt_10`) by clicking the "X" in the upper right corner.
15. Examine the output file "output.txt". The output file will be the same as the original file, but will have trailing spaces at the end as a result of the padding.

Observations

During the development and testing for this tutorial, the following items were observed:

  • The 'Header/Payload Demux' and 'Protocol Parser' blocks seem to work only with the 'digital.header_format_crc' format.
  • The 'Correlate Access Code - Tag Stream' block requires the Default Header Format Obj. and expects a 32-bit access code.

Tested with v3.10.9.2