Packing Bits

This tutorial describes how to pack bits into a byte using the Pack K Bits block, and how unpack a byte into bits, using the Unpack K Bits block.

The previous tutorial, Converting Data Types, describes the char or byte data type and how to convert between data types. The next tutorial, Streams and Vectors, describes the differences between streams and vectors and how to use them in flowgraphs.

Starting the Packing Bits Flowgraph
Packing bits into a byte is useful in representing binary data (as opposed to digitized RF samples) as well as when using the modulator blocks: Constellation Modulator, GFSK Mod and OFDM Transmitter. Create a new flowgraph and add the Random Source block to the workspace:



Click on Random Source. It is selected when outlined in aqua :



Press the UP or DOWN keys to cycle through the different data types until the byte data type is selected, denoted by the magenta output port color:



The random source generates bytes with a minimum value of Minimum up to a maximum value of Maximum-1. In this case, Minimum = 0 and Maximum = 2, so it will create binary 0 and 1. A Pack K Bits block is used to parallelize, or pack, multiple bits into a single byte to represent larger binary values.

Add the Throttle, Pack K Bits, Char to Float, and QT GUI Histogram Sink blocks to the flowgraph and connect them:



Explaining the Packing K Bits Block
The Pack K Bits block takes K bits and places them into a byte by filling the LSB first.

For this example K=4. The Random Source will generate bit B0 first. This will be received by Pack K Bits and then stored in the LSB:


 * [0 0 0 0 0 0 0 B0]

The second bit generated by Pack K Bits is B1, which is then stored by Pack K Bits according to:


 * [0 0 0 0 0 0 B1 B0]

Following this trend, the next bits B2 and B3 will then be stored as:


 * [0 0 0 0 B3 B2 B1 B0]

The following image demonstrates how the block works:



Because K=4 bits have been packed, the byte 0000B3B2B1B0 will be produced as an output and a new byte will be started. The output value of the byte in decimal (base-10) is:


 * = (B3*23) + (B2*22) + (B1*21) + (B0*20)
 * = (B3*8) + (B2*4) + (B1*2) + (B0)

For example, if:
 * B0=0
 * B1=1
 * B2=0
 * B3=1

the byte would be represented by 00001010 and the decimal value is:

8 + 0 + 2 + 0 = 10

Finishing the Pack K Bits Flowgraph
Edit the properties of Pack K Bits:
 * K: 4



Four bits produces numbers from 20=1 to 24-1=15. Edit the top QT GUI Histogram Sink properties and change the following:
 * Title: 4 Bits
 * Number of Bins: 1024
 * Max x-axis: 16



Four bits produces numbers from 20=1 to 24-1=15. Edit the bottom QT GUI Histogram Sink properties and change the following:
 * Title: 1 Bit
 * Number of Bins: 1024
 * Max x-axis: 16



The flowgraph should now look like the following:



Run the flowgraph. The 1 Bit histogram shows values of 0 and 1, while the 4 Bits histogram shows values from 0 to 15:



Unpacking Bits
Unpacking serializes a byte into a string of bits. Add the Unpack K Bits block to the workspace and connect it between the Pack K Bits block and the Char to Float block. Edit the Unpack K Bits block properties:
 * K: 4



Run the flowgraph. The 1 Bit Histogram shows that the 4 bits have been serialized into values of 0 and 1:



The unpacking starts with the LSB first and proceeds to the MSB. From the previous example, the Pack K Bits produced a byte with bits 0000DCBA. The Unpack K Bits block then produces an output with bit A first, then B, C and D and the 4 remaining 4 zeros in the byte are ignored.

The Unpack K Bits block perfectly undoes the the operation by the Pack K Bits input stream. This can be verified by adding a QT GUI Time Sink block with two inputs:



Connect the flowgraph according to the following:



The QT QUI Time Sink will show the output:



Left-mouse click and drag over a smaller portion to zoom in:



The two plots are perfectly overlapping, showing the input to the Pack K Bits block is the exact same as the output of the Unpack K Bits block:



The next tutorial, Streams and Vectors, describes the differences between streams and vectors and how to use them in flowgraphs.