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.
Contents
- I. Prototype the communication system
- Set system parameters
- Create signal source
- Map bits to symbols
- Create desired constellation
- Modulate the signal
- Perform the pulse shaping
- Apply channel model
- Downsample the signal
- View constellation with a scatter plot
- Demodulate the signal
- Map symbols to bits
- Computate BER
- II. Test the system on real data using instruments
- Upload data to ESG Vector Signal Generator
- Receive data from MXA Signal Analyser
- Save the IQ vector
- Analyse the acquired signal
- Load IQ data
- Rescale the data
- Isolate the Symbols
- Extract symbols
- Perform phase correction
- Perform global rotation
- III. Use pattern search to separate the symbols
- Initiate pattern search
- Run pattern search
- IV. Simulate the communication system
- Elaborate the model
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)
number_of_errors =
801
bit_error_rate =
0.0267
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')
ESG_DL allows the user to pass ESG control parameters via Simulink 'ESG Download Block' and then download the simulated data to the Agilent E4438C Signal Generator Function variables which get passed from Simulink are: 'data' Complex data structure generated from Simulink 'Fs' Sample Rate 'ipaddress' IP Address of ESG 'Source_Freq' ESG RF Frequency 'RF_Amplitude_Out' ESG RF Amplitude NOTE: The called functions below require the Agilent Waveform Download Assistant .m files loaded in your path Written by David L. Barner - 12/7/2006 Revision Marta Wilczkowiak - 01/10/2007
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
MATLAB/MXA example 7
Getting IQ data using the MXA driver and plot display
nInstrSamp =
2.0001
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)
cost = 334.4100
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);
Optimization terminated: mesh size less than options.TolMesh.
x =
4.2929 1.2679 -0.1541 -1.1460
fval =
21.1228
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')
