Driver in Matlab
This driver is written for TDD SISO communication between two Iris boards. It is assumed that the communication between the boards is done through block ram transmission mode where a whole block of data (packet) is transmitted and received at slots allocated for these two functionalities. Note that block ram transmission corresponds to a P (pilot transmission) in the TDD scheduling map.
Click here for the complete code.
We begin by defining the iris_py class which will be the interface between the Matlab script that calls the Matlab driver and the underlying Python driver and object. The list of properties include parameters such as sample rate, transmitter gain, and frequency, receiver gain and frequency, number of samples of the packet. A variable sdr_params will be used to receive the experiment’s values for the aforementioned parameters and py_obj will contain the Python object created through the Python Driver’s object class corresponding to an Iris node.
Note that we must zero-pad our data to account for the analog path and over-the-air delays. Example values for zero-padding are given in the tutorial scripts that follow. Also, it is important that the number of samples to be transmitted is below 4096 including zero-padding. This is due to the size of the Iris board ram that we use for bursty transmission.
classdef iris_py < handle properties sdr_params; py_obj; %pyhton object % Parameters to feed python (pun very intended!) serial_id; sample_rate; tx_freq; rx_freq; bw; tx_gain; rx_gain; n_samp; tdd_sched; n_zpad_samp; %number of zero-padding samples end
Matlab Object Constructor
The constructor initializes the experiment’s parameters received from the caller Matlab script(s), creates a python object and assigns it to the variable py_obj, and passes the parameters to that Python object.
function obj = iris_py(sdr_params) if nargin > 0 obj.sdr_params = sdr_params; obj.serial_id = sdr_params.id; obj.sample_rate = sdr_params.sample_rate; obj.tx_freq = sdr_params.txfreq; obj.rx_freq = sdr_params.rxfreq; obj.tx_gain = sdr_params.txgain; obj.rx_gain = sdr_params.rxgain; obj.n_samp = sdr_params.n_samp; obj.tdd_sched = sdr_params.tdd_sched; obj.n_zpad_samp = sdr_params.n_zpad_samp; obj.py_obj = py.iris_py.Iris_py( pyargs('serial_id',obj.serial_id,... 'tx_freq', obj.tx_freq, 'rx_freq', obj.rx_freq,... 'tx_gain',obj.tx_gain,'rx_gain',obj.rx_gain,... 'sample_rate',obj.sample_rate, 'n_samp',obj.n_samp,'n_zpad_samp',obj.n_zpad_samp) ); end end end
The functions below are a bridge between the Matlab experiment scripts and the underlying Python Driver and objects. They translate calls from the scripts to calls on the Python objects.
Set the trigger
Generate a trigger signal to start the frame count. Used in the chained mode where the boards are chained together and exchange control commands directly and off the air.
function sdrtrigger(obj, trig) obj.py_obj.set_trigger(pyargs('trig',trig)); end
In the chained mode, used by the node assumed to be the base station to synchronize the delays between itself and the UE node. In the unchained mode, it resets the correlator on the UE node to start trying to find the beginning of the frame by correlating with a known sequence, i.e., the beacon.
function sdrsync(obj, is_bs) obj.py_obj.sync_delays(pyargs('is_bs', is_bs)); end
Set up the correlator
Called to setup the correlator on the UE node.
function sdr_setcorr(obj) obj.py_obj.set_corr(); end
Transmission control gain
This function will turn on the gain control on the transmitter side.
function sdr_txgainctrl(obj) obj.py_obj.tx_gain_ctrl(); end
Start transmitting the beacon
In the unchained mode, by calling the function below, the base station node will burn the beacon sequence onto the base station’ ram to be transmitted at each pilot slot in the scheduling frame.
function sdr_txbeacon(obj, prefix_len) obj.py_obj.burn_beacon( pyargs('prefix_len', prefix_len) ); end
Set the frame schedule
Configure the scheduling frame on an Iris node. If in chained mode, the same functionality is expected by both the UE and the base station nodes. Otherwise, the UE needs to configure the trigger_out parameter.
function set_config(obj, chained_mode, is_bs, trigger_out) if chained_mode obj.py_obj.config_sdr_tdd_chained(pyargs('tdd_sched', obj.tdd_sched)); else obj.py_obj.config_sdr_tdd( pyargs('tdd_sched', obj.tdd_sched, 'is_bs', is_bs, 'trigger_out', trigger_out)); end end
Set up and activate the reading stream
These functions set the receiver streams up and activate them.
function sdrrxsetup(obj) obj.py_obj.setup_stream_rx(); end function sdr_activate_rx(obj) obj.py_obj.activate_stream_rx(); end
Block ram transmission
The data packet received from the caller Matlab script are burnt onto the node’s ram memory.
function sdrtx(obj, data) re = real(data); im = imag(data); obj.py_obj.burn_data( pyargs('data_r', re, 'data_i', im) ); end
Read the data
This function reads the recieved data sent from the Python driver, turns them into complex floats and sends them back to the caller Matlab script.
function [data, len] = sdrrx(obj) rcv_data = obj.py_obj.recv_stream_tdd(); data = double( py.array.array( 'd',py.numpy.nditer( py.numpy.real(rcv_data) ) ) ) + ... 1i*double( py.array.array( 'd',py.numpy.nditer( py.numpy.imag(rcv_data) ) ) ); len = length(data); end
Close and clean up
Finally, using the function bellow, the opened streams are closed and the Iris boards are reset.
function sdr_close(obj) obj.py_obj.close(); delete(obj.py_obj); end