wiki:WARPLab/Porting

Changes in WARPLab 7.6

WARPLab 7.6 adopts a new, cleaner syntax for handling the numeric IDs of RF interfaces and trigger inputs/outputs. The previous syntax is still supported in WARPLab 7.6 but will be removed in future releases. Refer to the code snippets below for details. All WARPLab examples have been updated with the new syntax.

Refer to the reference design user guide for details of the new structures returned by the wl_getInterfaceIDs(), wl_getTriggerInputIDs(), and wl_getTriggerOutputIDs() methods.

Old WARPLab 7.5 Syntax

% WARPLab 7.5

% Read Trigger IDs into workspace
[T_IN_ETH_A, T_IN_ENERGY, T_IN_AGCDONE, T_IN_REG, T_IN_D0, T_IN_D1, T_IN_D2, T_IN_D3, T_IN_ETH_B] =  wl_getTriggerInputIDs(nodes(1));
[T_OUT_BASEBAND, T_OUT_AGC, T_OUT_D0, T_OUT_D1, T_OUT_D2, T_OUT_D3] = wl_getTriggerOutputIDs(nodes(1));

% Connect the ETH_A trigger input to the BASEBAND and AGC trigger outputs
wl_triggerManagerCmd(nodes, 'output_config_input_selection', [T_OUT_BASEBAND, T_OUT_AGC], [T_IN_ETH_A]);

% Read RF interface IDs into the workspace
[RFA,RFB] = wl_getInterfaceIDs(nodes(1));

% Call some interface commands
wl_interfaceCmd(nodes, RFA, 'channel', 2.4, 11);
wl_interfaceCmd(nodes, RFB, 'channel', 2.4, 6);
wl_interfaceCmd(nodes, 'RF_ALL', 'tx_gains', 3, 20);


New WARPLab 7.6 Syntax

% WARPLab 7.6

% Read Trigger IDs into workspace
trig_in_ids  = wl_getTriggerInputIDs(nodes(1));
trig_out_ids = wl_getTriggerOutputIDs(nodes(1));

% Connect the ETH_A trigger input to the BASEBAND and AGC trigger outputs
wl_triggerManagerCmd(nodes, 'output_config_input_selection', [trig_out_ids.BASEBAND, trig_out_ids.AGC], [trig_in_ids.ETH_A]);

% Read RF interface IDs into the workspace
ifc_ids = wl_getInterfaceIDs(nodes(1));

wl_interfaceCmd(nodes, ifc_ids.RF_A, 'channel', 2.4, 11);
wl_interfaceCmd(nodes, ifc_ids.RF_B, 'channel', 2.4, 6);
wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_gains', 3, 20);


Changes in WARPLab 7.5

WARPLab 7.5 was designed to be fully compatible with unmodified WARPLab 7.4 scripts. Some syntax and behaviors from WARPLab 7.4 will be deprecated in future WARPLab releases. WARPLab 7.5 will print warnings when these features are encountered. In this documentation, we describe this deprecated behavior and explain the small changes required to adopt the new syntax. Users should adopt these conventions in their current scripts as the deprecated commands may be removed in a future release of WARPLab.


Choosing a Transmission Length: In our previous WARPLab examples, we adopted the convention of building a transmission waveform whose length was equal to the maximum buffer length the board could support. As of WARPLab 7.5, this number can be extremely large. We have updated all of our example scripts with the following change.

% WARPLab 7.4

% We will use the transmitter's I/Q buffer length to determine
% how long our transmission can be
%
% node_tx - WARPLab node object for the transmitter

txLength = node_tx.baseband.txIQLen;
wl_basebandCmd(node_tx, 'tx_length', txLength);

% WARPLab 7.5

% We will read the transmitter's maximum I/Q buffer length
% and assign that value to a temporary variable.
%
% node_tx - WARPLab node object for the transmitter
% RF_TX - index of RF interface used for transmission

maximum_buffer_len = wl_basebandCmd(node_tx, RF_TX, 'tx_buff_max_num_samples');

% Our transmission length for this example does not need
% to fill the entire transmit buffer, so we will use the smaller
% of two values: the maximum buffer length the board
% can support or an arbitrary value defined by this script

txLength = min(32768, maximum_buffer_len);
wl_basebandCmd(node_tx, 'tx_length', txLength);

In WARPLab 7.5, the txIQLen parameter of a node object still exists and defaults to 32 kSamp for WARP v3 hardware and 16 kSamp for WARP v2 hardware. Attempting to read this parameter will work, but it will print a deprecation warning to the MATLAB console. Instead, users should use the new tx_buff_max_num_samples baseband command to determine the maximum number of samples that the transmit buffers can support.


Choosing a Reception Length: In our previous WARPLab examples, we never bothered to tell the board to capture a certain number of samples. Because the overall buffer size was small, we just let the board capture and fill the entire receive buffer. This is no longer appropriate in WARPLab 7.5 because the maximum receive buffer size can be very large.

% WARPLab 7.4

% Trigger of transmission and reception
%
% eth_trig - UDP broadcast trigger object

eth_trig.send();

% Read samples from the receive buffer
%
% node_rx - WARPLab node object for the receiver
% RF_TX - index of RF interface used for transmission
% rxLength - number of samples to read

rx_IQ = wl_basebandCmd(node_rx, [RF_RX], 'read_IQ', 0, rxLength);
% WARPLab 7.5

% Set the number of samples that should be captured
%
% node_rx - WARPLab node object for the receiver
% rxLength - number of samples to receive

wl_basebandCmd(node_rx, 'rx_length', rxLength);

% Trigger of transmission and reception
%
% eth_trig - UDP broadcast trigger object

eth_trig.send();

% Read samples from the receive buffer
%
% node_rx - WARPLab node object for the receiver
% RF_TX - index of RF interface used for transmission
% rxLength - number of samples to read

rx_IQ = wl_basebandCmd(node_rx, [RF_RX], 'read_IQ', 0, rxLength);

Without the rx_length command, the board will default to capturing 32 kSamp in WARP v3 hardware and 16 kSamp in WARP v2 hardware. Using this command will explicitly tell the board to capture the given number of samples. Note: the value of rxLength should not exceed the maximum receive buffer size the board can support. To determine this value, use the rx_buff_max_num_samples command.


Porting Code from WARPLab 6

The basic flow of an experiment is the same across all versions of WARPLab. However WARPLab 7 has been designed to simplify experiments utilizing multiple nodes, each with multiple RF interfaces. The code samples below illustrate equivalent processes in WARPLab 6 and WARPLab 7, emphasizing the more compact and portable syntax available in the WARPLab 7 framework.

The code on this page is not a complete example; please see the WARPLab 7 examples for ready-to-use scripts.


Initialization: WARPLab 7 provides a utility script wl_initNodes which simplifies the process of establishing a connection from MATLAB to multiple WARP nodes running the WARPLab reference design. The array returned by wl_initNodes replaces the individual socket handles used in WARPLab 6.

%WARPLab 6

%Load the many global variables for the framework
warplab_defines

%Initialize two WARP nodes
[socketHandles, packetNum] = warplab_initialize(2);

%Retrieve socket handles for the trigger and both nodes
udp_Sync = socketHandles(1);
udp_node1 = socketHandles(2);
udp_node2 = socketHandles(3);
%WARPLab 7

%Initialize two WARP nodes
nodes = wl_initNodes(2);

%Retrieve IDs for available RF interfaces
[RFA, RFB] = wl_getInterfaceIDs(nodes(1));

%Create an Ethernet trigger and assign it to both nodes
eth_trig = wl_trigger_eth_udp_broadcast;
wl_triggerManagerCmd(nodes, 'add_ethernet_trigger', eth_trig);


Setting Parameters: WARPLab 7 enables setting the same RF and baseband parameters as previous versions. However the syntax for sending commands to nodes has changed. The new syntax allows the same command to be sent to multiple nodes in one line. Each node can be assigned the same parameter value, or multiple values (one per node) can be passed as an array argument. The example below shows equivalent code for setting a few parameters for two nodes.

%WARPLab 6
warplab_writeRegister(udp_node1, TX_DELAY, 0);
warplab_writeRegister(udp_node1, TX_LENGTH, 2^14);

warplab_writeRegister(udp_node2, TX_DELAY, 0);
warplab_writeRegister(udp_node2, TX_LENGTH, 2^14);

warplab_setRadioParameter(udp_node1, CARRIER_CHANNEL, 11);
warplab_setRadioParameter(udp_node2, CARRIER_CHANNEL, 11);
%WARPLab 7
wl_basebandCmd(nodes, 'tx_delay', 0);
wl_basebandCmd(nodes, 'tx_length', 2^14);
wl_interfaceCmd(nodes, 'RF_ALL', 'channel', 2.4, 11);

Writing Samples: Vectors of samples are constructed in MATLAB and written to buffers assigned to specific RF interfaces on the WARP nodes. In WARPLab 7 the buffer selection is parametric, simplifying the processing of iterating over nodes and interfaces, switching interfaces programmatically, etc. The example below illustrates how different waveforms can be written to multiple interfaces in one line. For complete documentation of the write_iq command, refer to the command documentation.

%WARPLab 6

%Time vector (assumes 40MHz sampling rate)
t = (1/40e6) .* [0 : 2^14-1];

%Generate a 1MHz sinusoid
txSigA = exp(1i*2*pi*t*1e6);

%Generate a 2MHz sinusoid
txSigB = exp(1i*2*pi*t*2e6);

%Write the two signals to RF A and B on both nodes
warplab_writeSMWO(udp_node1, RADIO2_TXDATA, txSigA);
warplab_writeSMWO(udp_node1, RADIO3_TXDATA, txSigB);
warplab_writeSMWO(udp_node2, RADIO2_TXDATA, txSigA);
warplab_writeSMWO(udp_node2, RADIO3_TXDATA, txSigB);
%WARPLab 7

%Time column vector (assumes 40MHz sampling rate)
t = (1/40e6) .* [0 : 2^14-1].';

%Generate a 1MHz sinusoid
txSigA = exp(1i*2*pi*t*1e6);

%Generate a 2MHz sinusoid
txSigB = exp(1i*2*pi*t*2e6);

%Write the two signals to RF A and B on both nodes
% Use vector arguments for interface selection and per-interface signals
wl_basebandCmd(nodes, [RFA RFB], 'write_IQ', [txSigA txSigB]);


Tx/Rx Cycle: The basic flow of a Tx/Rx cycle in WARPLab 7 is unchanged:

  • Write samples to Tx buffers (see above)
  • Enable Tx radios and buffers
  • Enable Rx radios and buffers
  • Send trigger to Tx and Rx nodes
  • Disable Tx/Rx radios and buffers
  • Retrieve captured samples from Rx buffers (see below)

The code below illustrates the updated syntax for en/disabling radios and buffers and sending triggers.

%WARPLab 6

%Enable the RF transceivers
warplab_sendCmd(udp_node1, RADIO2_TXEN, packetNum);
warplab_sendCmd(udp_node1, RADIO3_TXEN, packetNum);
warplab_sendCmd(udp_node2, RADIO2_RXEN, packetNum);
warplab_sendCmd(udp_node2, RADIO3_RXEN, packetNum);

%Enable the Tx/Rx buffers
warplab_sendCmd(udp_node1, RADIO2TXBUFF_TXEN, packetNum);
warplab_sendCmd(udp_node1, RADIO3TXBUFF_TXEN, packetNum);
warplab_sendCmd(udp_node2, RADIO2RXBUFF_RXEN, packetNum);
warplab_sendCmd(udp_node2, RADIO3RXBUFF_RXEN, packetNum);

%Prepare nodes for trigger reception
warplab_sendCmd(udp_node1, TX_START, packetNum);
warplab_sendCmd(udp_node2, RX_START, packetNum);

% Send the trigger
warplab_sendSync(udp_Sync);

%Disable the RF transceivers
warplab_sendCmd(udp_node1, RADIO2_TXDIS, packetNum);
warplab_sendCmd(udp_node1, RADIO3_TXDIS, packetNum);
warplab_sendCmd(udp_node2, RADIO2_RXDIS, packetNum);
warplab_sendCmd(udp_node2, RADIO3_RXDIS, packetNum);

%Disable the Tx/Rx buffers
warplab_sendCmd(udp_node1, RADIO2TXBUFF_TXDIS, packetNum);
warplab_sendCmd(udp_node1, RADIO3TXBUFF_TXDIS, packetNum);
warplab_sendCmd(udp_node2, RADIO2RXBUFF_RXDIS, packetNum);
warplab_sendCmd(udp_node2, RADIO3RXBUFF_RXDIS, packetNum);


%WARPLab 7

%Enable the RF transceivers
wl_interfaceCmd(nodes(1), [RFA RFB], 'tx_en');
wl_interfaceCmd(nodes(2), [RFA RFB], 'rx_en');

%Enable the sample buffers
wl_basebandCmd(nodes(1), [RFA RFB], 'tx_buff_en');
wl_basebandCmd(nodes(2), [RFA RFB], 'rx_buff_en');

%Send the broadcast trigger
eth_trig.send();

%Disable the transceivers and buffers
wl_basebandCmd(nodes, 'RF_ALL', 'tx_rx_buff_dis');
wl_interfaceCmd(nodes, 'RF_ALL', 'tx_rx_dis');

Reading Samples: WARPLab 7 simplifies the process for reading samples from multiple nodes and multiple buffers. The example below illustrates reading IQ and RSSI samples from two interfaces (RFA and RFB) on one node.

%WARPLab 6

%Retrieve and format the IQ samples from RFA and RFB
[Node2_Radio2_RawRxData] = warplab_readSMRO(udp_node2, RADIO2_RXDATA, 2^14);
[Node2_Radio2_RxData] = warplab_processRawRxData(Node2_Radio2_RawRxData);
[Node2_Radio3_RawRxData] = warplab_readSMRO(udp_node2, RADIO3_RXDATA, 2^14);
[Node2_Radio3_RxData] = warplab_processRawRxData(Node2_Radio3_RawRxData);

%Retrieve and format the RSSI samples from RFA and RFB
[Node2_Radio2_RawRSSIData] = warplab_readSMRO(udp_node2, RADIO2_RSSIDATA, 2^12);
[Node2_Radio2_RSSIData] = warplab_processRawRSSIData(Node2_Radio2_RawRSSIData);
[Node2_Radio3_RawRSSIData] = warplab_readSMRO(udp_node2, RADIO3_RSSIDATA, 2^12);
[Node2_Radio3_RSSIData] = warplab_processRawRSSIData(Node2_Radio3_RawRSSIData);

%WARPLab 7

%Retrieve the IQ and RSSI samples from both interfaces on the Rx node
rx_IQ = wl_basebandCmd(nodes(2), [RFA RFB], 'read_IQ', 0, 2^14);
rx_RSSI = wl_basebandCmd(nodes(2), [RFA RFB], 'read_RSSI', 0, 2^12);
Last modified 22 months ago Last modified on Sep 17, 2015, 2:10:57 PM