Packing Bits: Difference between revisions

From GNU Radio
Jump to navigation Jump to search
(all 0's equals zero not one. (you could write 2^0 - 1 but that seems needlessly confusing)
 
(46 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{TutorialNavigation}}
<div style="float:right">
 
{{Template:BeginnerTutorials}}
This tutorial describes how to pack 8 bits into a byte using the ''Pack K Bits'' block, and how unpack a byte into 8 bits, using the ''Unpack K Bits'' block.
</div>
This tutorial describes how to pack bits into a byte using the ''Pack K Bits'' block, and how to unpack a byte into bits, using the ''Unpack K Bits'' block.


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


== Packing Bits ==
== Starting the Packing Bits Flowgraph ==


Packing bits into a ''byte'' is useful in representing binary data (as opposed to digitized RF samples) as well 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:
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:


[[File:AddRandomSourceToWorkspace.png|400px]]
[[File:AddRandomSourceToWorkspace.png|400px]]




Click on ''Random Source''. It is selected when outlined in <span style="color:aqua">aqua</span>:
Click on ''Random Source''. It is selected when outlined in '''<span style="color:aqua">light blue</span>''':


[[File:SelectRandomSourceBlock.png|400px]]
[[File:SelectRandomSourceBlock.png|400px]]




Press the ''UP'' or ''DOWN'' keys to cycle through the different data types until the ''byte'' data type is selected, denoted by the <span style="color:magenta">magenta</span> output port color:
Press the ''UP'' or ''DOWN'' keys to cycle through the different data types until the ''byte'' data type is selected, denoted by the '''<span style="color:purple">purple</span>''' output port color:


[[File:ChangeRandomSourceToByte.png|400px]]
[[File:ChangeRandomSourceToByte.png|400px]]




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 gather, or ''pack'', multiple bits into a single byte to represent larger binary values.
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:
Add the ''Throttle'', ''Pack K Bits'', ''Char to Float'', and ''QT GUI Histogram Sink'' blocks to the flowgraph and connect them:
Line 28: Line 29:
[[File:PackBitsStartingFlowgraph.png|800px]]
[[File:PackBitsStartingFlowgraph.png|800px]]


The ''Pack K Bits'' block takes ''K'' bits and places them into a byte by filling the LSB first.
== Explaining the ''Packing K Bits'' Block ==
 
The ''Pack K Bits'' block takes ''K'' bits and places them into a byte by filling the least significant bit (LSB) first.
 
For this example ''K=4''. The ''Random Source'' will generate bit ''B<sub>0</sub>'' first. This will be received by ''Pack K Bits'' and then stored in the LSB:


For this example ''K=4''. The ''Random Source'' will generate bit ''A'' first. This will be received by ''Pack K Bits'' and then stored in the LSB:
::[0 0 0 0 0 0 0 B<sub>0</sub>]


<pre>[0 0 0 0 0 0 0 A]</pre>
The second bit generated by ''Pack K Bits'' is ''B<sub>1</sub>'', which is then stored by ''Pack K Bits'' according to:


The second bit generated by ''Pack K Bits'' is ''B'', which is then stored by ''Pack K Bits'' according to:
::[0 0 0 0 0 0 B<sub>1</sub> B<sub>0</sub>]


<pre>[0 0 0 0 0 0 B A]</pre>
Following this trend, the next bits ''B<sub>2</sub>'' and ''B<sub>3</sub>'' will then be stored as:


Following this trent, the 3rd and 4th bits ''C'' and ''D'' will then be stored as:
::[0 0 0 0 B<sub>3</sub> B<sub>2</sub> B<sub>1</sub> B<sub>0</sub>]


<pre>[0 0 0 0 D C B A]</pre>
The following image demonstrates how the block works:


Because ''K=4'' bits have been packed, the byte ''0000DCBA'' will be produced as an output and a new byte will be started. The output value of the byte in decimal (base-10) is:
[[File:PackingBitsExample.png|700px]]


<pre>A*1 + B*2 + C*4 + D*8</pre>
 
Because ''K=4'' bits have been packed, the byte ''0000B<sub>3</sub>B<sub>2</sub>B<sub>1</sub>B<sub>0</sub>'' will be produced as an output and a new byte will be started. The output value of the byte in decimal (base-10) is:
 
:: = (B<sub>3</sub>*2<sup>3</sup>) + (B<sub>2</sub>*2<sup>2</sup>) + (B<sub>1</sub>*2<sup>1</sup>) + (B<sub>0</sub>*2<sup>0</sup>)
:: = (B<sub>3</sub>*8) + (B<sub>2</sub>*4) + (B<sub>1</sub>*2) + (B<sub>0</sub>)


For example, if:
For example, if:
* ''A=0''
* ''B<sub>0</sub>=0''
* ''B=1''
* ''B<sub>1</sub>=1''
* ''C=0''
* ''B<sub>2</sub>=0''
* ''D=1''
* ''B<sub>3</sub>=1''


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


<pre>0 + 2 + 0 + 8 = 10</pre>
<pre>8 + 0 + 2 + 0 = 10</pre>
 
== Finishing the ''Pack K Bits'' Flowgraph ==


Edit the properties of ''Pack K Bits'':
Edit the properties of ''Pack K Bits'':
Line 62: Line 73:




Four bits produces numbers from ''2^0=1'' to ''(2^4)-1=15''. Edit the top ''QT GUI Histogram Sink'' properties and change the following:
Four bits produces numbers from 0 to ''2<sup>4</sup>-1=15''. Edit the top ''QT GUI Histogram Sink'' properties and change the following:
* Title: ''4 Bits''
* Title: ''4 Bits''
* Number of Bins: ''1024''
* Number of Bins: ''1024''
Line 69: Line 80:
[[File:HistogramSink4Bits.png|500px]]
[[File:HistogramSink4Bits.png|500px]]


Four bits produces numbers from ''2^0=1'' to ''(2^4)-1=15''. Edit the bottom ''QT GUI Histogram Sink'' properties and change the following:
Four bits produces numbers from 0 to ''2<sup>4</sup>-1=15''. Edit the bottom ''QT GUI Histogram Sink'' properties and change the following:
* Title: ''1 Bit''
* Title: ''1 Bit''
* Number of Bins: ''1024''
* Number of Bins: ''1024''
Line 76: Line 87:
[[File:HistogramSink1Bit.png|500px]]
[[File:HistogramSink1Bit.png|500px]]


The flowgraph should look like the following:


Run the flowgraph. The ''1 Bit'' histogram shows values of ''0'' and ''1'', while the ''4 Bit'' histogram shows values from ''0'' to ''15'':
[[File:PackBitsFinalFlowgraph.png|800px]]
 
 
Run the flowgraph. The ''1 Bit'' histogram shows values of ''0'' and ''1'', while the ''4 Bits'' histogram shows values from ''0'' to ''15'':


[[File:Histogram4Bits1Bit.png|500px]]
[[File:Histogram4Bits1Bit.png|500px]]
Line 83: Line 98:
== Unpacking Bits ==
== 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 and enter ''K: 4''.
[[File:UnpackBitsFlowgraph.png|800px]]
Run the flowgraph. The ''1 Bit'' Histogram shows the packed 4 bits are unpacked (serialized) back into values of ''0'' and ''1'':
[[File:HistogramUnpackBits.png|500px]]
The unpacking starts with the ''LSB'' first and proceeds to the ''most significant bit (MSB)''. From the previous example, the ''Pack K Bits'' produced a byte with bits ''0000B<sub>3</sub>B<sub>2</sub>B<sub>1</sub>B<sub>0</sub>''. The ''Unpack K Bits'' block produces an output with bit ''B<sub>0</sub>'' first, then ''B<sub>1</sub>'', ''B<sub>2</sub>'' and ''B<sub>3</sub>'' and the 4 remaining 4 zeros in the byte are ignored.
The ''Unpack K Bits'' block perfectly reverses 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:
[[File:TwoInputsTimeSink.png|500px]]
Connect the blocks:
[[File:PackUnpackFlowgraph.png|800px]]
The ''QT QUI Time Sink'' shows the output:
[[File:PackUnpackTimeSink.png|700px]]
Left-mouse click and drag over a smaller portion to zoom in:
[[File:ClickAndDragTimeSink.png|700px]]




* pack and unpack bits
The two plots are perfectly overlapping. The input to the ''Pack K Bits'' block is the exact same as the output of the ''Unpack K Bits'' block. This demonstrates how the ''Pack K Bits'' and ''Unpack Bits'' perform perfect inverse operations.
* describe how it works for char/byte type


[[File:PackUnpackTimeSinkZoom.png|700px]]






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

Latest revision as of 16:40, 3 November 2023

Beginner Tutorials

Introducing GNU Radio

  1. What is GNU Radio?
  2. Installing GNU Radio
  3. Your First Flowgraph

Flowgraph Fundamentals

  1. Python Variables in GRC
  2. Variables in Flowgraphs
  3. Runtime Updating Variables
  4. Signal Data Types
  5. Converting Data Types
  6. Packing Bits
  7. Streams and Vectors
  8. Hier Blocks and Parameters

Creating and Modifying Python Blocks

  1. Creating Your First Block
  2. Python Block With Vectors
  3. Python Block Message Passing
  4. Python Block Tags

DSP Blocks

  1. Low Pass Filter Example
  2. Designing Filter Taps
  3. Sample Rate Change
  4. Frequency Shifting
  5. Reading and Writing Binary Files

SDR Hardware

  1. RTL-SDR FM Receiver
  2. B200-B205mini FM Receiver

This tutorial describes how to pack bits into a byte using the Pack K Bits block, and how to 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:

AddRandomSourceToWorkspace.png


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

SelectRandomSourceBlock.png


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

ChangeRandomSourceToByte.png


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:

PackBitsStartingFlowgraph.png

Explaining the Packing K Bits Block

The Pack K Bits block takes K bits and places them into a byte by filling the least significant bit (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:

PackingBitsExample.png


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

Pack4Bits.png


Four bits produces numbers from 0 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

HistogramSink4Bits.png

Four bits produces numbers from 0 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

HistogramSink1Bit.png

The flowgraph should look like the following:

PackBitsFinalFlowgraph.png


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

Histogram4Bits1Bit.png

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 and enter K: 4.

UnpackBitsFlowgraph.png


Run the flowgraph. The 1 Bit Histogram shows the packed 4 bits are unpacked (serialized) back into values of 0 and 1:

HistogramUnpackBits.png


The unpacking starts with the LSB first and proceeds to the most significant bit (MSB). From the previous example, the Pack K Bits produced a byte with bits 0000B3B2B1B0. The Unpack K Bits block produces an output with bit B0 first, then B1, B2 and B3 and the 4 remaining 4 zeros in the byte are ignored.

The Unpack K Bits block perfectly reverses 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:

TwoInputsTimeSink.png


Connect the blocks:

PackUnpackFlowgraph.png


The QT QUI Time Sink shows the output:

PackUnpackTimeSink.png


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

ClickAndDragTimeSink.png


The two plots are perfectly overlapping. The input to the Pack K Bits block is the exact same as the output of the Unpack K Bits block. This demonstrates how the Pack K Bits and Unpack Bits perform perfect inverse operations.

PackUnpackTimeSinkZoom.png


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