I am trying to build a simulation for a 2PPM signal, modulate it at high frequency and then retrieve my baseband signal. Here is my full code (minus the plots) before explaining more.

% ---------Building the Binary Pulse Position Modulated signal :--------%

% Parameters
messageLength = 10;                 % Number of symbols in the message
Ts = 1;                             % Symbol period (in seconds)
messageTime = messageLength * Ts;   % Message length in seconds
Rs = 1 / Ts;                        % Symbol rate (in Hz)
A = 1;                              % Pulse amplitude
Fc = 50;                             % Carrrier frequency (in Hz)
Fs = 10 * Rs;                       % Sampling rate (in Hz)*
B = 2 / Ts;                         % Signal bandwidth (in Hz)
SNR = 50;                           % Signal-to-Noise-Ratio

% Generate the message vector
message = randi([0, 1], 1, messageLength);
fprintf('Message length: %d\n', length(message));

% Generate the time vector
t = linspace(0, messageLength * Ts, 100 * messageLength);
fprintf("Time vector length : %d\n", length(t));

% Generate PPM waveform
ppmBB = zeros(size(t));
for i = 1:messageLength
    if message(i) == 1
        % Set the pulse amplitude for symbol '1' in the first half of the symbol duration
        ppmBB(t >= (i - 1) * Ts & t < (i - 0.5) * Ts) = A;
        % Set the pulse amplitude for symbol '0' in the second half of the symbol duration
        ppmBB(t >= (i - 0.5) * Ts & t < i * Ts) = A;

% Add carrier frequency to the PPM signal
carrierWave = cos(2 * pi * Fc * t);
ppmPB = ppmBB .* carrierWave;

% ------------ Additive White Gaussian Noise Channel ------------------%

% We wish to generate a white gaussian noise vector of appropriate strength
% depending on the input Signal-to-Noise-Ratio in the parameters

% Calculate the signal power
signalPowerW = (1 / messageLength) * sum(abs(ppmPB).^2);
signalPowerdB = 10 * log(signalPowerW);
fprintf("PPM passband signal power (in dB) : %d\n", signalPowerdB);

% Convert SNR from dB to linear scale
SNR_linear = 10^(SNR/10);

% Calculate the noise power spectral density in watts per Hertz
N0 = signalPowerW / SNR_linear;
fprintf("Noise power spectral density (in W/Hz) : %d\n", N0);

% Generate the noise vector
n = sqrt(N0/2)*randn(size(ppmPB));

% Received signal
ppmPB_noise = ppmPB + n;

% ------------ Pulse Position Modulated signal receiver ----------------%

% Take the ppm signal back to baseband
carrierWaveReceiver = cos(2 * pi * Fc * t);
ppmBB_noise = ppmPB_noise .* carrierWaveReceiver;

The simulation starts by creating a random vector of 1s ans 0s. The vector is converted into a PPM signal according to the ADS-B specification (not going into detailq about this here) and the signal looks like this :

PPM baseband signal

The second step is to take the baseband signal and multiply it with a carrier wave at frequency Fc. My first issue appears here. In my code I am using Fc = 50 Hz (for testing) and i can see a low frequency amplitude modulation of my signal that is not intended. You can see the passband signal here :

PPM passband signal

The signal is then passend through a AWGN channel and I think I didnt make mistake on this part. After the AWGN channel the signal is once again multiplied by the carrier wave to retrieve the baseband signal. I still dont understand why but I dont get the baseband signal, you can see it here :

Retrieved baseband signal

I think the way I create my signal is not correct and I should use sampling but I dont know how to implement it and I dont think it is the main issue in my code. Feel free to criticize my code and help me get this simulation working.


  • 2
    $\begingroup$ I don't have the time to go through all this at the moment but wanted to make some quick hopefully helpful comments: Don't simulate the carrier, there is no reason to at all. Just use the complex baseband equivalent signal (with carrier offsets, etc) and the simulation will be much simpler and more efficient. If you are seeing an oscillation, I suspect the loop isn't set up correctly and you may be unstable, could that be the case? I go through all this in great detail complete with Python examples at this "DSP for Software Radio" course fast approaching: dsprelated.com/courses $\endgroup$ Jan 13 at 15:58
  • $\begingroup$ Thanks for the plots, that is very helpful! $\endgroup$ Jan 13 at 20:05

1 Answer 1


From the OP's plot it appears there is a very small frequency offset (we see 1/2 cycle envelope in 10 seconds consistent with a frequency offset of 1/20th of a Hz).

If sampling was at 10 Hz with a 1/100th Hz offset, this would multiply up to 1/20th of Hz of frequency offset at the 5th harmonic where the carrier is.

I initially thought part of the issue was simulating a 50 Hz carrier with a 10 Hz sampling rate, but then I reviewed the code a little further and see that the sampling rate is actually synthesized with

t = linspace(0, messageLength * Ts, 100 * messageLength);

Which is 1000 samples in the time duration from 0 to 10 seconds. So this is close to 100 Hz sampling which is sufficient to simulate the 50 Hz carrier with modulation. However this is creating the fractional sampling error as we should not have a sample at 10 seconds exactly if we are including t=0. (The actual sampling rate used comes out to 99.9 Hz which you can confirm by subtracting t(2) from t(1) and inverting it.

To create the accurate time instants, instead I recommend:

t = [0: 100 * messageLength] * 1/fs2

Where fs2 =100 if we wish to simulate a 100 Hz sampling rate.

As far as simulations in general, there is no real need to include a carrier frequency as everything can be done with the complex baseband equivalent signal (and as we see here, simulating the carrier requires a much higher sampling rate). But as a quick solution here, just increasing the sampling rate should be fine. In general for practical implementation, down-converting directly to baseband by multiplying with a real sinusoidal carrier will not work due to the likelihood of small frequency offsets between transmitter and receiver (a certainty if the two are not otherwise synchronized), which will also result in waveforms that appear as the OP sees here. To do this properly, the down-conversion should be done by multiplying with $e^{-j\omega_c t}$, which is done in practice with an IQ frequency translator (mixer), where $\omega_c$ is the frequency of the carrier in radians/sec, followed by a low pass filter. This will provide the complex baseband signal, which can then be used to correct for the small residual frequency offsets.

These other posts may help take the mystery out of "complex baseband" and IQ frequency translation:

baseband and passband modulation

Does bandwidth include negative frequencies?

Frequency shifting of a quadrature mixed signal

  • $\begingroup$ Thank you for your help @DanBoschen ! I now understand better the issues in my simulation. I would like to add that the protocol I am studying and which I talked about in my post uses only the real part of the signal and no IQ sampling is required. Should I modulate using a complex exponential anyway and discard the imaginary part at the demodulation phase ? $\endgroup$ Jan 13 at 22:25
  • $\begingroup$ Yes absolutely, the reason is (with concern of an actual implementation) there can (will) be small frequency offsets between the transmitter and receiver. Read through the links I gave if you want to really understand this but ultimately due to any offset your received signal will land either at $+f_{\Delta}$ or $-f_{\Delta}$ and if restricted to be a real signal will destructively alias onto itself (since for a real signal the positive and negative frequencies must be complex conjugate symmetric). So in your simple sim you can guarantee 0 offset but in practice that won't be the case. $\endgroup$ Jan 13 at 22:56
  • $\begingroup$ Yes thank you so much ! Everything is working well now. I am now trying to demodulate PPM with matched filter and get new problems ahah but off topic. $\endgroup$ Jan 14 at 18:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.