MATLAB Examples

Walkie-Talkie Transmitter Using Analog Devices AD9361/AD9364

This example shows how to use the Xilinx® Zynq-Based Radio Support Package with MATLAB® to implement a walkie-talkie transmitter. The transmitted signal can be received by a compatible commercial walkie-talkie. Alternatively, the signal can be received by the companion Walkie-Talkie Receiver Using Analog Devices™ AD9361/AD9364 example if you have a second SDR platform.

Refer to the Getting Started documentation for details on configuring your host computer to work with the Support Package for Xilinx® Zynq-Based Radio.



Walkie-talkies provide a subscription-free method of communicating over short distances. There are a number of different standards used around the world. This example uses MATLAB SDR system objects to implement two of these standards: Family Radio Service and Personal Mobile Radio 446.

  • Family Radio Service (FRS): Operates on 14 channels at frequencies around 462 MHz and 467 MHz. The channel spacing is 25 kHz. FRS radios are commonly found in the North and South America. More details on FRS can be found in [ 1 ].
  • Personal Mobile Radio 446 (PMR446): Operates on 8 channels around 446 MHz. The channel spacing is 12.5 kHz. PMR446 radios are commonly found in Europe. More details on PMR446 can be found in [ 2 ].

Both FRS and PMR446 use analog frequency modulation (FM) with a maximum frequency deviation of +-2.5 kHz. They also use a Continuous Tone-Code Squelch System (CTCSS) to filter unwanted signals at the receiver. CTCSS is implemented in this example.

This example allows the transmitted audio to be a continuous tone, a chirp signal or voice from an audio file. The audio sample rate is always 8 kHz.


Before running the example, ensure you have performed the following steps:

1. Configure your host computer to work with the Support Package for Xilinx® Zynq-Based Radio. See Getting Started for help.

2. Ensure that you have a suitable receiver. This example is designed to work in conjunction with any of the following possible receivers:

3. Ensure that your receiver is set to the same protocol, channel and CTCSS code.

Running the Example

Before running the example, make sure that the protocol variable is set to a standard that is legal for use in your location. The example can be run by executing zynqRadioWalkieTalkieTransmitterAD9361AD9364ML.m.

Once both the transmitter and receiver are active, you should hear the transmitted audio on your receiver. By default, a voice signal is transmitted.

Transmitter Design: System Architecture

The general structure of the walkie-talkie transmitter can be described as follows:

  1. Generate the audio signal to be transmitted
  2. Generate the CTCSS tone
  3. Combine the CTCSS tone with the audio signal
  4. Upsample the 8 kHz audio signal to 528 kHz
  5. FM modulate the audio signal
  6. Send the modulated signal to the SDR hardware for further upsampling and transmission

The high level functionality of the transmitter, such as the protocol used and the channel, can be controlled by changing the variables in the code section below.

Set the variables that control the transmitter. The protocol variable should be set to 'FRS' or 'PMR446' depending on which standard is legal in your location. The audio variable can be 'Audio file', 'Chirp' or 'Pure tone'.

protocol = 'FRS';
% protocol = 'PMR446';
channel = 1;
CTCSSCode = 5;
audioSource = 'Audio file';
% audioSource = 'Chirp';
% audioSource = 'Pure tone';
transmissionStopTime = 20; % in seconds

% Set the variables that control the system sample rates
baseFrameSize = 512;
audioSampleRate = 8e3; % constant, in Hertz
radioSampleRate = 528e3; % in Hertz
softwareInterpolationFactor = radioSampleRate / audioSampleRate;

% Create the interpolation filter for 8 kHz to 528 kHz
interpolatorCoefficients = dspmltiFIRDefaultFilter(softwareInterpolationFactor,1);
softwareInterpolator = dsp.FIRInterpolator(softwareInterpolationFactor, ...

Each component of the transmitter is described in more detail in the following sections.

Generating the Audio Signal

The audio to be transmitted is composed of two components:

  1. The actual audio, such as a speech signal, that will be audible at the receiver. This audio is generated by a custom system object, sdrzWalkieTalkieTransmitter_AudioSource.
  2. The CTCSS tone, that is generated by a dsp.SineWave system object.

Continuous Tone-Coded Squelch System (CTCSS)

Walkie-Talkies operate on a shared public channel, allowing multiple users to access the same channel simultaneously. CTCSS [ 3 ] systems filter out undesired communication or interference from these other users. The transmitter generates a tone between 67 Hz and 250 Hz and transmits it along with the source signal. The receiver contains logic to detect this tone, and acknowledges a message if the detected tone matches the code setting on the receiver. The receiver filters out the tone so that the user does not hear it.

The CTCSS tone generator generates a continuous phase sine wave with a frequency corresponding to the selected private code. The amplitude of the tone is usually 10%-15% of the maximum amplitude of the modulating signal. Note that because the maximum amplitude of all the source signals is 1, the default amplitude of 0.15 for the CTCSS tone corresponds to 15% of the modulating signal's maximum amplitude.

audioGenerator = sdrzWalkieTalkieTransmitter_AudioSource( ...
                     'SignalSource', audioSource, ...
                     'SamplesPerFrame', baseFrameSize);
CTCSSAmplitude = 0.15; % normalized amplitude i.e. 0 to 1;
% Convert the CTCSS code to a frequency
CTCSSTone = sdrzWalkieTalkieHelper_CTCSSCode2Tone(CTCSSCode);
CTCSSGenerator = dsp.SineWave(...
                              'Frequency', CTCSSTone, ...
                              'Amplitude', CTCSSAmplitude, ...
                              'SampleRate', audioSampleRate, ...
                              'SamplesPerFrame', baseFrameSize, ...
                              'OutputDataType',   'single');

Performing the Frequency Modulation

This example implements the FM modulator using a simple digital IIR filter as an integrator. The IIR filter is implemented using a dsp.IIRFilter system object. The frequency sensitivity parameter, frequencySensitivityGain, is used to control the modulation. It is related to the frequency deviation by the formula:

frequencySensitivityGain = frequencyDeviation * (2*pi*Ts) / A

where peakFrequencyDeviation is 2.5 kHz, Ts is the sampling period of the SDR transmitter, and A represents the maximum amplitude of the modulating signal i.e. the audio signal. This example assumes the generated audio is normalized and therefore has a peak amplitude of 1.

See [ 4 ] for more information on frequency modulation.

integratingFilter = dsp.IIRFilter(...
  'Structure',    'Direct form I', ...
  'Numerator',    1, ...
  'Denominator',  [1 -1]);

peakAudioAmplitude = 1;
frequencyDeviation = 2.5e3;
radioSamplePeriod = (1/radioSampleRate);
frequencySensitivityGain  = frequencyDeviation * 2 * pi * ...
                                radioSamplePeriod / peakAudioAmplitude;

Creating the SDR Transmitter system object

An SDR Transmitter system object is used to send baseband data to the SDR hardware. By default, the example is configured to run with ZC706 and ADI FMCOMMS2/3/4 hardware. You can uncomment one of the following lines, as applicable, to set the SDRDeviceName.

% % SDRDeviceName='ZedBoard and FMCOMMS2/3/4';
% % SDRDeviceName='ADI RF SOM';

SDRDeviceName = 'ZC706 and FMCOMMS2/3/4';
radio = sdrdev(SDRDeviceName);
setupSession(radio); % Only needed once per session, but multiple calls are OK

radioCenterFrequency = sdrzWalkieTalkieHelper_Channel2Frequency( ...
                                  protocol, channel);
sdrTransmitter = sdrtx(SDRDeviceName,...
    'IPAddress',             '', ...
    'Gain',                  0,...
    'BasebandSampleRate',    radioSampleRate, ...
    'CenterFrequency',       radioCenterFrequency, ...
    'ChannelMapping',        1);

Baseband Processing and Transmission

The actual processing and transmission of the data is enclosed in a try/catch block. This means that if there is an error, the system objects still get released properly.

By enclosing the data processing and transmission in a while loop controlled using a tic/toc pair, the transmission will run for approximately the desired real world time.

    % The first time the SDR transmitter object is used to transmit data, it
    % performs some initial setup and takes about 4s. Using a very small set
    % of complex values as the input will establish this connection with the
    % correct data type but not send any significant data. Note that the
    % RF carrier will be present. The data received during this initial
    % setup is discarded. This means the setup time is not included as
    % part of the desired run time.

    radioSamplesPerFrame = baseFrameSize*softwareInterpolationFactor;
    dummyData = single(complex(ones(radioSamplesPerFrame,1),ones(radioSamplesPerFrame,1))*1e-12);
    display('Starting transmission')

    tic; % start timing the transmission
    while toc < transmissionStopTime
        % Generate the audio data to be transmitted
        audioData = audioGenerator();

        % Generate the CTCSS tone
        CTCSSData = CTCSSGenerator();

        % Combine the CTCSS tone with the audio data
        audioPlusCTCSS = audioData + CTCSSData;

        % Upsample the 8 kHz audio to 528 kHz
        upsampledBasebandData = softwareInterpolator(audioPlusCTCSS);

        % FM modulate the audio
        outInteg  = integratingFilter(upsampledBasebandData);
        FMPhase = exp(1i * frequencySensitivityGain * outInteg);
        FMAmplitude = 0.9; % can be used to control the transmit power
        FMModulatedData    = FMAmplitude .* FMPhase;

        % Send the data to the SDR hardware
        droppedSamples = sdrTransmitter(FMModulatedData);

        if droppedSamples
            disp('Unable to send data fast enough to SDR hardware!')
    disp('Finished transmitting')
catch ME
% Release system objects associated with hardware

Transmitter Design: System Sample Rates

The system has two different sample rates:

  1. The audio sample rate, 8 kHz
  2. The SDR hardware baseband rate, 528 kHz

The upsample by 32 from 8 kHz to 528 kHz is done in software using a dsp.FIRInterpolator object, softwareInterpolator. The upsample to 528 kHz is used for two reasons:

  1. By Carson's rule, the approximate passband bandwidth of the desired FM signal is 2*(frequencyDeviation + peakAudioFrequency). In this example, that equates to a signal bandwidth of 2*(2.5e3 + 4e3) = 13 kHz. This means we need to use a sample rate greater than 13 kHz.
  2. The sample rates in software have no relation to the real world transmission rates. The actually transmission rate is determined entirely by the SDR hardware baseband rate. To make the software sample rates meaningful, the sample rates at the software/hardware interface must match. For the AD9361/AD9364, one possible baseband sample rates that is a multiple of 8 kHz and greater than 13 kHz is 528 kHz. Using an integer upsample factor means a smaller interpolation filter (fewer taps) can be used.

Things to Try

To modify the example, save a local copy of zynqRadioWalkieTalkieTransmitterAD9361AD9364ML.m. Some possible modifications include:

  • Try changing the channel by changing the channel variable.
  • Try changing the CTCSS code by changing the CTCSSCode variable. Note that the receiver will not play the transmission out loud unless it has the same CTCSS code, or it has CTCSS disabled by setting the code to 0.
  • Try changing the audio source by changing the audioSource variable. You can send a voice recording, a single tone or a chirp signal.
  • Try replacing the sdrzWalkieTalkieTransmitter_AudioSource object with a audioDeviceReader System object, so that you can transmit audio captured from a microphone in real time. This requires Audio System Toolbox™.

Alternative Implementations

This example implements a walkie-talkie transmitter in MATLAB. You can also view the equivalent system implemented using Simulink in the Walkie-Talkie Transmitter with Analog Devices AD9361/AD9364 using Simulink example.

Troubleshooting the Example

If you cannot hear the transmitted signal on your receiver, try the following:

  • Make sure that the transmitter and the receiver are set to the same protocol, channel and CTCSS code.
  • Disable CTCSS on the receiver by setting the code to 0. Note that codes higher than 38 use Digital Coded Squelch, which is not implemented in this example.
  • Vary the relative amplitude of the CTCSS tone by changing the CTCSSAmplitude variable.

General tips for troubleshooting SDR hardware can be found in Xilinx Zynq-Based Radio Processing Errors and Fixes.

List of Example Helper Files

This example uses the following helper functions


  1. Family Radio Service on Wikipedia®
  2. PMR446 on Wikipedia
  3. Continuous Tone-Coded Squelch System on Wikipedia
  4. Frequency Modulation on Wikipedia