No BSD License  

Highlights from
Developing custom modulation schemes

image thumbnail
from Developing custom modulation schemes by Marta
Performing Custom Modulation and Demodulation using Agilent Instruments, MATLAB, and Simulink

custommodulationagilentlogo.m
%% Developing custom modulation schemes
% This script shows how MATLAB can be used, together with Agilent instruments, 
% for prototyping custom modulation schemes. It demonstrates MATLAB functionality for data
% acquisition, visualisation and analysis. It finishes by a simple example illustrating the
% first step towards simulate the prototype communications system in Simulink.
% 
% More precisely, this script shows how to:
% 
% * Use MATLAB to prototype a communication system that consists of a random bit generator, 
% bit-to-integer converter, baseband modulator with custom modulation format, 
% channel, demodulator, integer-to-bit converter.
% * Compute the system's bit error rate (BER)
% * Upload generated custom waveform to an Agilent ESG Vector Signal Generator
% * Acquire the signal using Agilent MXA Signal Analyser 
% * Demodulate and analyse the acquired signal.
% * Design a prototype Simulink model simulating a communication system
% using custom modulation scheme
% 
% The demodulation of the acquired signal is based on IS136 demo written by
% Todd Atkins and the functions for creating Agilent logo constellation and 
% uploading the data on Agilent vector signal generator are from Tom Gaudette.


%% I. Prototype the communication system
% Use MATLAB and Communications Toolbox to prototype the communications
% system using custom modulation scheme.

%% Set system parameters
% Set the values of the main parameters 

% size of signal constellation:     32
M = 32; 
% number of bits per symbol:        5
k = log2(M); 
% number of bits to process:        30000
n = 3e4; 
% oversampling factor:              8
nSamp = 8;



%% Create signal source
% Create a binary data stream as a column vector.
% Then plot first 40 bits in a stem plot.

% random binary data stream
x = randint(n,1); 

stem(x(1:40), 'filled');
title('Random bits', 'FontSize', 18);
xlabel('Bit index', 'FontSize', 18); 
ylabel('Binary value', 'FontSize', 18);


%% Map bits to symbols
% Convert the bits in x into k-bit symbols.  7500 symbols (30000/4) ranging
% from 0 to 31
xsym = bi2de(reshape(x, k, length(x)/k).', 'left-msb');

% plot first 10 symbols in a stem plot.
figure; 
stem(xsym(1:10));
title('Random symbols', 'FontSize', 18);
xlabel('Symbol index', 'FontSize', 18);
ylabel('Integer value', 'FontSize', 18);

%% Create desired constellation
% MATLAB provides a lot of flexibility in generating the modulation
% schemes. Let's create a custom constellation, for example in shape of
% Agilent logo.

% constellation is represented by 32 complex numbers
constellation = agilentlogo();

f = figure;
plot(constellation, '.', 'MarkerSize', 16);

% or create more customised plot...
s = repmat([2^8 2^7 2^6  2^2], [1,8]);
scatter(imag(constellation), real(constellation), s, 'filled');
axis off
set(f, 'Color', 'w')

%% Modulate the signal 
% Modulate with 32 general QAM. 

% complex signal, 6000 symbols.
ytx = genqammod(xsym, constellation);


%% Perform the pulse shaping
% Modulation is often followed by pulse shaping, and demodulation is often
% preceded by a filtering or an integrate-and-dump operation. This section presents
% an example involving rectangular pulse shaping. 
% Rectangular pulse shaping repeats each output from the modulator a fixed number of times
% to create an up-sampled signal. Rectangular pulse shaping can be a first step
% or an exploratory step in algorithm development, though it is less realistic
% than other kinds of pulse shaping (e.g. using Raised Cosine Filter). 
[ytxs] = rectpulse(ytx, nSamp);  

%% Apply channel model
% Send signal over an AWGN channel.
EbNo = 10; % In dB
snr = EbNo + 10*log10(k) - 10*log10(nSamp);  % 16.021 db
yrxs = awgn(ytxs, snr, 'measured');

%% Downsample the signal
% If the transmitter up-samples the modulated signal, then the receiver 
% should down-sample the received signal before demodulating. 
% The "integrate and dump" operation is one way to down-sample the received signal.

yrx = intdump(yrxs, nSamp);

%% View constellation with a scatter plot
% Create scatter plot of noisy signal and transmitted
% signal on the same axes.  plotting 5000 symbols

h = scatterplot(yrx(1:5e3), 1, 0, 'b.');
hold on;
scatterplot(ytx(1:5e3), 1, 0, 'r.', h); 
title('Received Signal');
legend('Received signal', 'Signal constellation');
% set axis ranges.
axis([-1.2, 1.2, -1.2, 1.2]); 
hold off;

%% Demodulate the signal
% Demodulate the signal using the same Modem object as for the modulation

zsym = genqamdemod(yrx, constellation);

%% Map symbols to bits
% Undo the bit-to-symbol mapping performed earlier.

% convert integers to bits.
z = de2bi(zsym, 'left-msb'); 
% convert z from a matrix to a vector.
z = reshape(z.', numel(z), 1);

%% Computate BER 
% Compare x and z to obtain the number of errors and
% the bit error rate.
[number_of_errors, bit_error_rate] = biterr(x, z)

%% II. Test the system on real data using instruments
% We have seen above how to use MATLAB and Communications Toolbox to prototype 
% and test a communication system using custom modulation. In order to test
% the behaviour of the system on real data, we can replace the simulated channel
% by instruments, such as arbitrary waveform generator and signal analyser.
% In order to control the instruments and acquire the data we are going to
% use the Instrument Control Toolbox.

%% Upload data to ESG Vector Signal Generator
% Upload the simulated signal to a Vector Signal Generator. In this example we have used 
% AGILENT E4438C Vector Signal Generator. We uploaded the function using Agilent Waveform Download Assistant. 

% define the instrument host name
esgIp = 'E4438C_A16616';

% define the instrument sample rate
esgSampleRate = 22.5e6; 

% upload the waveform and play it with sampleRate 22.5 MHz
% ESG_DL(ytxs, esgSampleClock, esgIp, 'SOURce:FREQuency 2E9', 'POWer -20')

% Here is the description of function ESG_DL
help('ESG_DL')

%% Receive data from MXA Signal Analyser
% Acquire the IQ data. In this example we have used Agilent MXA Signal
% Analyser and MATLAB Instrument Driver for this instrument from MATLAB
% Central. To acquire the signal to MATLAB, you can use TMTOOL or one of the 
% Agilent MXA examples from www.agilent.com/find/sa_programming.
% In this example the data was acquired from MXA Signal Analyzer in 
% IQ analyzer mode with bandwith 25MHz and time span 2ms. 
% The resulting MXA sample time was 22.221e-9s. This
% means that for each uploaded sample we acquired around 2 samples.

% define the instrument IP address
mxaIp = '172.16.27.192';

% Acquire IQ vector
% iq = acquireIqVector(mxaIp);
% Here is the description of function acquireIqVector
help('acquireIqVector')

% compute the rate ration between the instruments
mxaSampleTime = 22.221e-9;
mxaSampleRate = 1/mxaSampleTime;
nInstrSamp = mxaSampleRate/esgSampleRate




%% Save the IQ vector
% Save the IQ vector to file acquiredIQ.mat.

% save acquiredIQ iq

%% Analyse the acquired signal
% Use MATLAB algorithm development environment to locate the symbols in the
% acquired IQ vector.

%% Load IQ data
% If you do not have hardware, you can perform the following analysis on
% the data saved in MAT file.

load acquiredIQ;

figure
plot(iq, 'r.')
title('Acquired IQ vector')
xlabel('In-Phase')
ylabel('Quadrature')

%% Rescale the data
% Rescale the acquired data so that IQ values are within [-1, 1] range.
% The scaling is required only for the optional automatic step at the end.
iq = (iq.');
maxVal = max( [ real( iq(:) ); imag( iq(:) ) ] );
iq = iq /(maxVal);

%% Isolate the Symbols
% Because of differences between the rate at which symbols are broadcast,
% the rate at which samples are taken, and the blurring effect of
% transmission, the symbols are uniformly spaced throughout the acquired IQ
% data.  The remainder of the samples are transitions between symbols. 
% We know the symbol spacing from how signal is broadcasted and how it
% was acquired. 
% By using the value manipulation tools in the editor and Cell mode, we can
% immediately visualize the results of different symbol choices.
% 
% In this step we allow also manual scaling of the signal, so that the
% symbol clusters most distant from the center lie on the unit circle.

% manipulate the values below in Cell mode in order to separate the symbols
scale = 1.2;
s0 = 2;
ds = round(nSamp*nInstrSamp);

% subsample and scale the signal. 
plot(iq(s0:ds:end)*scale, 'r.')
title('Subsampled IQ vector')
xlabel('In-Phase')
ylabel('Quadrature')



%% Extract symbols
% Extract the symbols for the further processing
manualSymbols= iq(s0:ds:end)*scale;

%% Perform phase correction 
% At this point, we have located our symbols in the IQ data.  However, the
% symbols still don't cluster into eight nice neat groupings.  The problem
% is that we need to account for skew in the signal.  If everything is not
% synchronized correctly, the symbols appear to "walk" around between their
% intended locations.  We can correct for that with a linear phase
% correction.

% modify this with cell mode (by .1 or less).  
phaseValue = -0.15; 

% create vector of complex numbers representing the increasing rotation
skewCorrection = exp(2*pi*i*linspace(0,phaseValue,length(manualSymbols)));
% multiply the original signal 
manualSymbolsDeskewed = manualSymbols.*skewCorrection; 

plot(manualSymbolsDeskewed, 'r.');
title('Subsampled IQ vector after phase correction')
xlabel('In-Phase')
ylabel('Quadrature')



%% Perform global rotation
% Now that we have located our symbols and corrected for skew between the
% clocks, if our clusters aren't aligned correctly globally (all shifted
% clockwise or counter clockwise) we can apply a global rotation.

% modify this with cell mode (by .1 or less).  
rotation = -0.025; 

% add global rotation
symbols = manualSymbolsDeskewed.*exp(2*pi*i*rotation); 
plot(symbols,'r*');
title('Subsampled IQ vector after rotation correction')
xlabel('In-Phase')
ylabel('Quadrature')

%% III. Use pattern search to separate the symbols
% At this point we have obtained the symbol separation using Cell mode, a part of MATLAB
% algorithm development environment. There are ways of finding the values
% allowing for the symbol separation automatically, using optimization
% methods. The cost function, corresponding to the distance of the
% separated symbols from the ideal points on the constellation contains a
% lot of local minima and in order to use classic optimisation methods we
% would need to know the approximate solutions. We can try to use global 
% optimization methods, such as pattern search from Genetic Algorithm and Direct Search
% Toolbox in order to find the parameter values automatically without need
% of accurate starting point.


%% Initiate pattern search
% Define starting point and explore the corresponding solution

% define the starting point
% [firstSymbol, scaling, phase, rotation]
x0 = [2, 1, 0, 0];

% sample rate should be known from transmition/acquisition sample rates so
% no need to optimize
sampleRate = round(nSamp*nInstrSamp); 

% different parameters to be optimised have quite different values,
% which can influence the optimisation. Let's scale them in order to work
% with parameters with similar orders of magnitude
s = [1 1 100 100]; 

% show the current solution
showSolutionDemod(x0, sampleRate, iq);

% show the initial value of the cost function
cost = costSymbolSeparation(x0.*s, sampleRate, iq)

%% Run pattern search
% Use fundtion PATTERNSEARCH to separate symbols

% define paramterews for pattern search
os = psoptimset('CompletePoll', 'on', 'CompleteSearch', 'on', 'SearchMethod', 'MADSPositiveBasis2N');

% set parameters bounds
lb = [1 0.5 -2*pi*100 -pi/2*100];
ub = [15,1.5,2*pi*100,pi/2*100];
% perform search
[xn, fval] = patternsearch(@(x)costSymbolSeparation(x, sampleRate, iq), ...
    x0.*s, [], [], [], [], lb, ub, [], os);

% de-scale the solution
x = xn./s

% show the current value of the cost function
fval

figure
showSolutionDemod(x, sampleRate, iq);

%% IV. Simulate the communication system
% We have seen above how to use MATLAB functionality to prototype and explore the properties of a
% communications system. We have seen also how to use instruments to test
% this system on real data. As a next step, we could simulate the behaviour
% of this system over time using Simulink. Here is a simple model
% simulating the system developed on the beginning of this script. It
% generates random bit sequences, transmits them and verifies the bit error
% rate. 

% todo colors, channel
custommodulationagilentlogoSL

%% Elaborate the model
% The model above is fairly simple and does not take into account issues
% such as symbol timing recovery or phase recovery, which are necessary for processing life data.
% If it was to be implemented as a part of a real system, consideration would also have to be given to 
% optimisation of the code for the performance, solving fixed points settings and 
% partitioning of the system into components. For this particular problem, 
% we have not developed models taking taking into consideration these real-world 
% implementation issues, but we could give examples on how to tackle these 
% problems using existing GPS or FM models as examples.

% see the logo for the last time...
f = figure;
constellation = agilentlogo();
s = repmat([2^8 2^7 2^6  2^2], [1,8]);
scatter(imag(constellation), real(constellation), s, 'filled');
axis off
set(f, 'Color', 'w')

Contact us at files@mathworks.com