MATLAB Examples

Packetized Modem with Data Link Layer

This example shows you how to implement a packetized modem with Data Link Layer [ 1 ] using MATLAB® and Communications System Toolbox™. The modem features a packet-based physical layer and an ALOHA-based Data Link Layer. You can either simulate the system or run with radios using the Communications System Toolbox Support Package for USRP® Radio.


Required Hardware and Software

To simulate the system performance, you need the following software:

To measure system performance with radios, you also need the following hardware:

  • USRP® radios (B2xx, N2xx, or X3xx)

and the following software

For a full list of Communications System Toolbox supported SDR platforms, refer to the Supported Hardware section of Software Defined Radio (SDR) discovery page.


Packetized wireless modems are communications systems that transmit information in bursts called packets through a wireless channel. Each modem, also called a node, features a physical layer where packets are modulated, transmitted and received on a shared frequency band, and demodulated. Since the same frequency band is used by all nodes, a medium access control (MAC) algorithm is required to reduce the packet loss due to collisions (i.e. simultaneous transmissions). Data Link Layer includes a MAC sublayer and a logical link control sublayer to share the same channel and provides an error free link between two nodes. Data Link Layer is also called Layer 2 and sits between Network Layer (Layer 3) and Physical Layer (Layer 1).

Run the Example

To run the example, type PacketizedModemNetworkExample in the MATLAB Command Window or click the link. The example code creates three packetized modem node objects and connects them through a channel object. Each node can send packets to the other two nodes. ACKTimeout determines the timeout duration before a node decides the DATA packet transmission was not successful. ACKTimeout must be greater than the round trip duration for a DATA-ACK exchange, which is 0.21 seconds for this example. The simulation is time-based and simulates the full physical layer processing together with the data link layer.

% Set simulation parameters
runDuration = 10;         % Seconds
numPayloadBits = 19530;   % Bits
packetArrivalRate = 0.2;  % Packets per second
ackTimeOut = 0.25;        % ACK time out in seconds
maxBackoffTime = 10;      % Maximum backoff time in ackTimeOut durations
mMaxDataRetries = 5;      % Maximum DATA retries
queueSize = 10;           % Data Link Layer queue size in packets
samplesPerFrame = 2000;   % Number of samples processed every iteration
verbose = true;           % Print packet activity to command line
sampleRate = 200e3;

% Create packetized modem nodes
node1 = helperPacketizedModemNode(...
  'Address', 1, ...
  'DestinationList', [2, 3], ...
  'NumPayloadBits', numPayloadBits, ...
  'PacketArrivalRate', packetArrivalRate, ...
  'ACKTimeOut', ackTimeOut, ...
  'MaxBackoffTime', maxBackoffTime, ...
  'MaxDataRetries', mMaxDataRetries, ...
  'QueueSize', queueSize, ...
  'CarrierDetectorThreshold', 1e-5, ...
  'AGCMaxPowerGain', 65, ...
  'SamplesPerFrame', samplesPerFrame, ...
  'Verbose', verbose, ...
  'SampleRate', sampleRate);
node2 = helperPacketizedModemNode(...
  'Address', 2, ...
  'DestinationList', [1 3], ...
  'NumPayloadBits', numPayloadBits, ...
  'PacketArrivalRate', packetArrivalRate, ...
  'ACKTimeOut', ackTimeOut, ...
  'MaxBackoffTime', maxBackoffTime, ...
  'MaxDataRetries', mMaxDataRetries, ...
  'QueueSize', queueSize, ...
  'CarrierDetectorThreshold', 1e-5, ...
  'AGCMaxPowerGain', 65, ...
  'SamplesPerFrame', samplesPerFrame, ...
  'Verbose', verbose, ...
  'SampleRate', sampleRate);
node3 = helperPacketizedModemNode(...
  'Address', 3, ...
  'DestinationList', [1 2], ...
  'NumPayloadBits', numPayloadBits, ...
  'PacketArrivalRate', packetArrivalRate, ...
  'ACKTimeOut', ackTimeOut, ...
  'MaxBackoffTime', maxBackoffTime, ...
  'MaxDataRetries', mMaxDataRetries, ...
  'QueueSize', queueSize, ...
  'CarrierDetectorThreshold', 1e-5, ...
  'AGCMaxPowerGain', 65, ...
  'SamplesPerFrame', samplesPerFrame, ...
  'Verbose', verbose, ...
  'SampleRate', sampleRate);

% Setup channel
channel = helperMultiUserChannel(...
  'NumNodes', 3, ...
  'EnableTimingSkew', true, ...
  'DelayType', 'Triangle', ...
  'TimingError', 20, ...
  'EnableFrequencyOffset', true, ...
	'PhaseOffset', 47, ...
  'FrequencyOffset', 2000, ...
  'EnableAWGN', true, ...
  'EbNo', 25, ...
  'BitsPerSymbol', 2, ...
  'SamplesPerSymbol', 4, ...
  'EnableRicianMultipath', true, ...
  'PathDelays', [0 node1.SamplesPerSymbol/node1.SampleRate], ...
  'AveragePathGains', [15 0], ...
  'KFactor', 15, ...
	'MaximumDopplerShift', 10, ...
  'SampleRate', node1.SampleRate);

% Main loop
radioTime = 0;
nodeInfo = info(node1);
frameDuration = node1.SamplesPerFrame/node1.SampleRate;
[rcvd1,rcvd2,rcvd3] = deal(complex(zeros(node1.SamplesPerFrame,1)));
while radioTime < runDuration
  trans1 = node1(rcvd1, radioTime);
  trans2 = node2(rcvd2, radioTime);
  trans3 = node3(rcvd3, radioTime);

  % Multi-user channel
  [rcvd1,rcvd2,rcvd3] = channel(trans1,trans2,trans3);

  % Update radio time.
  radioTime = radioTime + frameDuration;
|   Time    |     Link    |   Action   |  Seq #  | Backoff 
| 4.76000 s |   2 ->>   1 |       DATA | #     0 |
| 4.97000 s |   1 <<-   2 |       DATA | #     0 |
| 4.97000 s |   1 ->>   2 |        ACK | #     0 |
| 4.99000 s |   2 <<-   1 |        ACK | #     0 |
| 5.04000 s |   1 ->>   2 |       DATA | #     0 |
| 5.10000 s |   3 ->>   1 |       DATA | #     0 |
| 5.30000 s |   1 ->>   2 |   Back Off | #     0 | 1.75000 s |
| 5.36000 s |   3 ->>   1 |   Back Off | #     0 | 2.00000 s |
| 7.06000 s |   1 ->>   2 |       DATA | #     0 |
| 7.27000 s |   2 <<-   1 |       DATA | #     0 |
| 7.27000 s |   2 ->>   1 |        ACK | #     0 |
| 7.29000 s |   1 <<-   2 |        ACK | #     0 |
| 7.37000 s |   3 ->>   1 |       DATA | #     0 |
| 7.58000 s |   1 <<-   3 |       DATA | #     0 |
| 7.58000 s |   1 ->>   3 |        ACK | #     0 |
| 7.60000 s |   3 <<-   1 |        ACK | #     0 |
| 9.73000 s |   2 ->>   1 |       DATA | #     1 |
| 9.77000 s |   3 ->>   1 |       DATA | #     1 |
| 9.99000 s |   2 ->>   1 |   Back Off | #     1 | 2.25000 s |


The Node object collect statistics on the performance of the Data Link Layer algorithm. Call the info method of the Node object to access these statistics. Following shows a sample result for a 10 second simulated time with 0.2 packets/second packet arrival rate. Each data packet is 200 msec long.

% Display statistics
nodeInfo(1) = info(node1);
nodeInfo(2) = info(node2);
nodeInfo(3) = info(node3);

for p=1:length(nodeInfo)
  fprintf('\nNode %d:\n', p);
  fprintf('\tNumGeneratedPackets: %d\n', nodeInfo(p).NumGeneratedPackets)
  fprintf('\tNumReceivedPackets: %d\n', nodeInfo(p).NumReceivedPackets)
  fprintf('\tAverageRetries: %f\n', nodeInfo(p).Layer2.AverageRetries)
  fprintf('\tAverageRoundTripTime: %f\n', nodeInfo(p).Layer2.AverageRoundTripTime)
  fprintf('\tNumDroppedPackets: %d\n', nodeInfo(p).Layer2.NumDroppedPackets)
  fprintf('\tNumDroppedPackets (Max retries): %d\n', nodeInfo(p).Layer2.NumDroppedPacketsDueToRetries)
  fprintf('\tThroughput: %d\n', numPayloadBits / nodeInfo(p).Layer2.AverageRoundTripTime)
  fprintf('\tLatency: %d\n', nodeInfo(p).Layer2.AverageLatency)
Node 1:
	NumGeneratedPackets: 1
	NumReceivedPackets: 2
	AverageRetries: 1.000000
	AverageRoundTripTime: 2.249961
	NumDroppedPackets: 0
	NumDroppedPackets (Max retries): 0
	Throughput: 8.680151e+03
	Latency: 2.690625e+00

Node 2:
	NumGeneratedPackets: 2
	NumReceivedPackets: 1
	AverageRetries: 0.000000
	AverageRoundTripTime: 0.230234
	NumDroppedPackets: 0
	NumDroppedPackets (Max retries): 0
	Throughput: 8.482660e+04
	Latency: 2.229961e+00

Node 3:
	NumGeneratedPackets: 2
	NumReceivedPackets: 0
	AverageRetries: 1.000000
	AverageRoundTripTime: 2.500391
	NumDroppedPackets: 0
	NumDroppedPackets (Max retries): 0
	Throughput: 7.810780e+03
	Latency: 0

Data Link Layer (Layer 2)

This example implements a Data Link Layer based on the ALOHA random access protocol [ 2 ]. The following flow diagram shows how the ALOHA protocol transmits and receives data packets.

When Data Link Layer has a Layer 3 packet to transmit, it starts a new session and sends the packet right away using a DATA packet. The algorithm waits for an acknowledgment (ACK) packet. If an ACK is not received before the timeout period, it backs off a random amount of time and sends the DATA packet again. If it fails to receive an ACK after a number of retries, it drops the packet. If during this session, a new Layer 3 packet is received, the Layer 3 packet is put in a first-in-first-out (FIFO) queue. If the FIFO queue is full, packet is dropped.

The algorithm is implemented in the helperPacketizedModemDataLinkLayer System object. The helperPacketizedModemDataLinkLayer System object defines a state machine with three states: IDLE, ACK_WAIT, and BACKOFF. The following state machine describes how the data link layer algorithm is implemented in this object. Statements in brackets, [...], and curly braces, {...}, are conditions and actions, respectively. Small circles are passthrough states used to represent multiple conditions.

The original ALOHA protocol uses a hub/star topology. The uplink and downlink utilizes two separate frequency bands. The following example employs a mesh network topology where nodes transmit and receive using the same frequency band.

Modem Structure

The following presents the modem code structure. The processing has six main parts and runs in the following order:

  1. Source Controller
  2. Message Generator
  3. PHY Decoder
  4. Data Link Layer
  5. Message Parser
  6. PHY Encoder

The Data Link Layer processes outputs of the Message Generator and PHY Decoder, so it must run after those two operations. The Message Parser and PHY Encoder process outputs of the Data Link Layer. This sequence ensures that the modem can receive packets and respond to them in the same time interval. The helperPacketizedModemNode object implements the modem.

Source Controller

The Source Controller generates an enable signal and a random destination address based on the user selected packet arrival distribution.

Message Generator

The Message Generator starts creating layer 3 data packets when enabled by the source controller. The packets contain a digitized text message. If the message does not fit into one packet, the generator creates multiple packets. The packet structure is as follows:

  • To Address: 8 bits
  • From Address: 8 bits
  • Packet Number: 16 bits
  • Payload: M bits

PHY Decoder

The PHY Decoder receives baseband I/Q samples and creates layer 2 packets. PHY Decoder can correct for amplitude variations using an AGC, frequency offsets with a frequency offset estimator and compensator, and timing skews and multipath using a fractionally spaced decision feedback equalizer (DFE). The block diagram of the physical layer (Layer 1) receiver is as follows:

When data payload size is set to 19530 bits, the total packet length of the modem is 39956 samples. The modem processes SamplesPerFrame samples, which is 2000 samples for this example, at each iteration. A smaller SamplesPerFrame results in smaller latency but increases the overhead of the modem algorithm. An increased overhead may increase the processing time such that the modem does not run in real-time anymore.

Data Link Layer

Data Link Layer provides a link between two neighboring nodes. It employs the ALOHA-based protocol described in the Data Link Layer (Layer 2) section. The packet structure is as follows:

  • Type: 4 bits
  • Version: 2 bits
  • Reserved: 2 bits
  • To Address: 8 bits
  • From Address: 8 bits
  • Sequence Number: 8 bits
  • Time stamp: 32 bits
  • Payload: N ( = M+32) bits

Data Link Layer also collects following statistics:

  • Number of successful packet transfers, which is defined as the number of successfully received ACK packets
  • Average retries
  • Average round trip time in seconds
  • Number of dropped packets due to layer 3 packet queue being full
  • Number of dropped packets due to retries
  • Throughput defined as successful data delivery rate in bits per second
  • Average latency in seconds defined as the time between the generation of the layer 3 data packet and reception of it at the destination node

Message Parser

The Message Parser parses received layer 2 payload and creates Layer 3 packet. It also collects the following statistics:

  • Number of received packets
  • Number of received duplicate packets

PHY Encoder

PHY Encoder creates physical layer packets by modulating the layer 2 packets in to baseband I/Q samples. The packet structure is as follows:

The dummy symbols are used to train the AGC and for carrier detection. The synchronization symbols are a modulated PN-sequence. The header has following fields:

  • Payload length: 16 bits
  • CRC: 16 bits

The block diagram of the physical layer (Layer 1) transmitter is as follows:

Channel Model

This example simulates a three node network but any number of nodes can be simulated. The outputs of each node is passed to the channel simulator. The channel adds baseband signals from all three nodes after imposing the following channel impairments:

  • Timing skew
  • Frequency offset
  • Rician multipath
  • AWGN

In addition to these impairments, the signals from neighboring nodes are applied a path loss of 20 dB, while the self-interference is added directly.

Running Using Radios

You can also run this example using radios instead of a simulated channel. The combination of an SDR hardware and a host computer that runs a MATLAB session comprises a node. The following steps show you how to setup a three-node network. This example uses USRP® B200 and B210 radios.

1) Connect a USRP® radio to host computer A, which we will call Node 1. Follow the instruction in Setup and Configuration of USRP® Support Package to install and setup your host computer for use with USRP® radios. Start a MATLAB session.

2) Set up Node 1 as a transmitter for initialization. Run helperPacketizedModemInitializeRadio('tx', PLATFORM, ADDRESS, FC, RT), where PLATFORM is the type of the USRP® radio and ADDRESS is the serial number or IP address, FC is the center frequency, and RT is run time in seconds. This example uses 915 MHz center frequency. Assuming that your radio is a B200 with serial number 'ABCDE', the function call will be helperPacketizedModemInitializeRadio('tx', 'B200', 'ABCDE', 915e6, 120). This function will run the transmitter for 120 seconds. If you need more time to finish the initialization, rerun the command with a longer run time.

3) Repeat step 1 for a second radio and host computer and call this node Node 2.

4) Set up Node 2 as a receiver for initialization. Run [CDT, MAXGAIN, RXGAIN] = helperPacketizedModemInitializeRadio('rx', PLATFORM, ADDRESS, FC, RT). Assuming that your radio is a B210 with serial number '12345', the function call will be [CDT1, MAXGAIN1, RXGAIN1] = helperPacketizedModemInitializeRadio('rx', 'B210', '12345', 915e6, 120). The function will run until it determines the best values for carrier detector threshold (CDT), maximum AGC gain (MAXGAIN), and radio receive gain (RXGAIN) or until RT seconds have elapsed. If the initialization algorithm cannot determine suitable parameters, it may suggest increasing or decreasing the transmitter power and retrying the initialization.

5) Run the same experiment with Node 1 as the receiver and Node 2 as the transmitter to determine best receiver parameters for Node 1. In most cases the channel should be dual and the parameters will be very close.

6) Repeat steps 1-5 for all other pairs of radios, i.e. Node 1 and Node 3, Node 3 and Node 2. Obtain CDT, MAXGAIN, and RXGAIN values for each node. If you get different values for the same node while initializing for different links, choose the maximum values for MAXGAIN and RXGAIN, and minimum of CDT.

7) Start Node 1 by running the function helperPacketizedModemRadio(P,RA,NA,DA,FC,CDT,MAXG,RGAIN,D), where P is platform, RA is radio address, NA is node address, DA is destination address list, FC is center frequency, CDT is carrier detection threshold, MAXG is maximum AGC gain, RGAIN is radio receiver gain, and D is duration. For example, run as helperPacketizedModemRadio('B200', 'ABCDE', 1, [2 3], 915e6, CDT1, MAXGAIN1, RXGAIN1, 120).

8) Start Node 2 by running helperPacketizedModemRadio('B210', '12345', 2, [1 3], 915e6, CDT2, MAXGAIN2, RXGAIN2, 120).

9) Start Node 3 by running helperPacketizedModemRadio('B200', 'A1B2C', 3, [1 2], 915e6, CDT3, MAXGAIN3, RXGAIN3, 120).

10) Once the session ends, each node prints out its statistics.

A three network setup operated for two hours. Each node generated packets at a rate of 0.2 packets/second according to a Poisson distribution. The nodes were placed approximately equal distance. One of the links had line-of-sight while other two did not. The following is the results collected on all three nodes. Since the round trip time of a DATA-ACK exchange using the B2xx radios connected over USB can be as high as 800 msec, the average round trip time of the network is greater than 3 sec. The algorithm minimizes packet loss and provides a fair access to the shared channel to all nodes.

Node 1:
 NumGeneratedPackets: 1440
 NumReceivedPackets: 1389
 AverageRetries: 0.533738
 AverageRoundTripTime: 3.725093
 NumDroppedPackets: 95
 NumDroppedPackets (Max retries): 23
 Throughput: 5.242823e+03
Node 2:
 NumGeneratedPackets: 1440
 NumReceivedPackets: 1340
 AverageRetries: 0.473157
 AverageRoundTripTime: 3.290775
 NumDroppedPackets: 31
 NumDroppedPackets (Max retries): 9
 Throughput: 5.934772e+03
Node 3:
 NumGeneratedPackets: 1440
 NumReceivedPackets: 1385
 AverageRetries: 0.516129
 AverageRoundTripTime: 3.558408
 NumDroppedPackets: 107
 NumDroppedPackets (Max retries): 29
 Throughput: 5.488410e+03


The simulation code from previous sections and the helperPacketizedModemRadio.m function both utilize the helperPacketizedModemNode.m System object to implement the modem node. In the current example, the same code is used to evaluate a system, first using a simulated channel, then using SDR hardware and over-the-air channels.

Even though the code using simulated channels is time-based, the modem node object could be used to run an event-based simulation. This example does not provide an event-based simulation kernel.

Further Exploration

You can vary the following parameters to investigate their effect on data link layer performance:

  • PacketArrivalRate
  • ACKTimeOut
  • MaxBackoffTime
  • MaxDataRetries
  • QueueSize

You can also explore the following functions for details of the implementation of the algorithms:

You can examine the physical layer only performance using the PacketizedModemPhysicalLayerTxRxExample script.

Selected Bibliography

Copyright Notice

Universal Software Radio Peripheral® and USRP® are trademarks of National Instruments Corp.