# Transmitting on the AIR-T¶

In this tutorial we show you how to perform basic transmit functionality with the AIR-T using the Python interface. You will learn how to interact with the radio drivers in order to stream signal data to the radio from the Tegra. We provide the source code, and plenty of comments. The code is broken down into two main functions: make_tone and transmit_tone. Enjoy!

## Creating a Tone Signal¶

First, we must to ensure that we are able to create a tone that is head-to-tail repeatable without any phase discontinuities. To do this, we provide a function that creates a tone segment where the frequency is an integer multiple of the sample rate. The ouput of the function is a numpy array that contains the interleaved complex int16 samples.

``````def make_tone(n, fcen, fs, phi=0.285):
"""
Generates tone signal window with a frequency that is an integer
multiple of the sample rate so it can be repeated without a phase
discontinuity.
"""
period = fs / fcen
assert n % period == 0, 'Total samples is not an integer number of periods'
a = 2**15
# Make Complex Valued Tone Signal
wt = np.array(2 * np.pi * fcen * np.arange(n) / fs)
sig_cplx = np.exp(1j * (wt + phi))
# Convert to interleaved int16 values
sig_int16 = np.empty(2 * n, dtype=np.int16)
sig_int16[0::2] = 32767 * sig_cplx.real
sig_int16[1::2] = 32767 * sig_cplx.imag
return sig_int16
``````

## Transmitting a Signal¶

Second, we leverage the `make_tone` function above and the SoapySDR python calls to transmit the signal from the AIR-T. The function below will continuously transmit the signal until the user exits using ctrl-c.

``````def transmit_tone(freq, chan=0, fs=31.25, gain=-20, buff_len=16384):
""" Transmit a tone out of the AIR-T """
# Generate tone buffer that can be repeated without phase discontunity
bb_freq = fs / 8  # baseband frequency of tone
tx_buff = make_tone(buff_len, bb_freq, fs)
lo_freq = freq - bb_freq  # Calc LO freq to put tone at tone_rf

sdr = SoapySDR.Device()  # Create AIR-T instance
sdr.setSampleRate(SOAPY_SDR_TX, chan, fs)  # Set sample rate
sdr.setFrequency(SOAPY_SDR_TX, chan, lo_freq)  # Tune the LO
sdr.setGain(SOAPY_SDR_TX, chan, gain)

tx_stream = sdr.setupStream(SOAPY_SDR_TX, SOAPY_SDR_CS16, [chan])
sdr.activateStream(tx_stream)  # this turns the radio on

# Transmit
print('Now Transmitting')
while True:
try:
rc = sdr.writeStream(tx_stream, [tx_buff], buff_len)
if rc.ret != buff_len:
print('TX Error {}: {}'.format(rc.ret, errToStr(rc.ret)))
except KeyboardInterrupt:
break

# Stop streaming
sdr.deactivateStream(tx_stream)
sdr.closeStream(tx_stream)
``````

## Complete Code - Command Line Interface¶

Finally, we combine the two functions into an executable python file with command line input arguments.

``````#!/usr/bin/env python3

"""
Transmits a tone out of the AIR-T. The script will create a tone segment that
is infinity repeatable without a phase discontinuity and with 8 samples per
period. The TX LO of the AIR-T is set such that the baseband frequency of the
generated tone plus the LO frequency will transmit at the desired RF.
"""
import sys
import numpy as np
import argparse
import SoapySDR
from SoapySDR import SOAPY_SDR_TX, SOAPY_SDR_CS16, errToStr

def make_tone(n, fcen, fs, phi=0.285):
"""
Generates tone signal window with a frequency that is an integer
multiple of the sample rate so it can be repeated without a phase
discontinuity.
"""
period = fs / fcen
assert n % period == 0, 'Total samples not integer number of periods'
a = 2**15
# Make Complex Valued Tone Signal
wt = np.array(2 * np.pi * fcen * np.arange(n) / fs)
sig_cplx = np.exp(1j * (wt + phi))
# Convert to interleaved int16 values
sig_int16 = np.empty(2 * n, dtype=np.int16)
sig_int16[0::2] = 32767 * sig_cplx.real
sig_int16[1::2] = 32767 * sig_cplx.imag
return sig_int16

def transmit_tone(freq, chan=0, fs=31.25, gain=-20, buff_len=16384):
""" Transmit a tone out of the AIR-T """
# Generate tone buffer that can be repeated without phase discontunity
bb_freq = fs / 8  # baseband frequency of tone
tx_buff = make_tone(buff_len, bb_freq, fs)
lo_freq = freq - bb_freq  # Calc LO freq to put tone at tone_rf

sdr = SoapySDR.Device()  # Create AIR-T instance
sdr.setSampleRate(SOAPY_SDR_TX, chan, fs)  # Set sample rate
sdr.setFrequency(SOAPY_SDR_TX, chan, lo_freq)  # Tune the LO
sdr.setGain(SOAPY_SDR_TX, chan, gain)

tx_stream = sdr.setupStream(SOAPY_SDR_TX, SOAPY_SDR_CS16, [chan])
sdr.activateStream(tx_stream)  # this turns the radio on

# Transmit
print('Now Transmitting')
while True:
try:
rc = sdr.writeStream(tx_stream, [tx_buff], buff_len)
if rc.ret != buff_len:
print('TX Error {}: {}'.format(rc.ret, errToStr(rc.ret)))
except KeyboardInterrupt:
break

# Stop streaming
sdr.deactivateStream(tx_stream)
sdr.closeStream(tx_stream)

def parse_command_line_arguments():
""" Create command line options for transmit function """
help_formatter = argparse.ArgumentDefaultsHelpFormatter
parser = argparse.ArgumentParser(description='Transmit a tone on the AIR-T',
formatter_class=help_formatter)
default=2400e6, help='TX Tone Frequency')
default=0, help='TX Channel Number [0 or 1]')
default=31.25e6, help='TX Sample Rate')
default=0, help='TX gain')
default=16384, help='TX Buffer Size')
return parser.parse_args(sys.argv[1:])

if __name__ == '__main__':
pars = parse_command_line_arguments()
transmit_tone(pars.freq, pars.chan, pars.fs, pars.gain, pars.buff_len)
``````

This function may be called from the command line of the AIR-T to transmit a tone. By default, it will transmit a tone at 2.4 GHz, but we also provide a help menu as follows to change the signal parameters.

``````\$ ./transmit_tone.py -h
usage: transmit_tone.py [-h] [-f FREQ] [-c CHAN] [-s FS] [-g GAIN]
[-n BUFF_LEN]

Transmit a tone from the AIR-T

optional arguments:
-h, --help   show this help message and exit
-f FREQ      TX Tone Frequency (default: 2400000000.0)
-c CHAN      TX Channel Number [0 or 1] (default: 0)
-s FS        TX Sample Rate (default: 31250000.0)
-g GAIN      TX gain (default: 0)
-n BUFF_LEN  TX Buffer Size (default: 16384)
``````

Last update: May 8, 2020