clear all;
close all;
clc
Fc = 2.5e6; % Carrier frequency (Hz)
Rsym = 1e6; % Symbol rate (symbols/second)
nSamps = 8; % Number of samples per symbol
frameLength = 2048; % Number of symbols in a frame
M = 16; % Modulation order (16-QAM)
EbNo = 15; % Ratio of baseband bit energy
% to noise power spectral density (dB)
% Calculate sampling frequency in Hz
Fs = Rsym * nSamps;
% Calculate passband SNR in dB. The noise variance of the baseband signal
% is double that of the corresponding bandpass signal [1]. Increase the SNR
% value by 10*log10(2) dB to account for this difference and have
% equivalent baseband and passband performance.
SNR = EbNo + 10*log10(log2(M)/nSamps) + 10*log10(2);
% Create a scatter plot scope for received symbols.
scatScope = commscope.ScatterPlot('SamplingFrequency', Rsym, ...
'SamplesPerSymbol', 1); close(scatScope)
% Create a 16-QAM modulator.
hMod = modem.qammod('M',M);
% Set the expected constellation of the scatter plot scope.
scatScope.Constellation = hMod.Constellation;
scatScope.PlotSettings.Constellation = 'on';
scatScope.PlotSettings.ConstellationStyle = '*r';
% Generate random data symbols.
b = randi([0 hMod.M-1], frameLength, 1);
% Modulate the random data.
txSym = modulate(hMod, b);
% Specify a square root raised cosine filter with a filter length of eight
% symbols and a rolloff factor of 0.2.
nSym = 8; % Length of the filter in symbols
beta = 0.2; % Rolloff factor
filterSpec = fdesign.pulseshaping(nSamps, 'Square root raised cosine', ...
'Nsym,Beta', nSym, beta);
% Design the transmitter filter.
hXmtFlt = design(filterSpec);
% Apply pulse shaping by upsampling and filtering. Alternatively, you can
% use an efficient multirate filter. See help for fdesign.interpolator for
% more information.
x = filter(hXmtFlt, upsample(txSym, nSamps));
% Plot spectrum estimate of pulse shaped signal.
hFig = figure;
pwelch(x,hamming(512),[],[],Fs,'centered')
% Generate carrier. The sqrt(2) factor ensures that the power of the
% frequency upconverted signal is equal to the power of its baseband
% counterpart.
t = (0:1/Fs:(frameLength/Rsym)-1/Fs).';
carrier = sqrt(2)*exp(1i*2*pi*Fc*t);
% Frequency upconvert to passband.
xUp = real(x.*carrier);
% Plot spectrum estimate.
pwelch(xUp,hamming(512),[],[],Fs,'centered')
% Create the passband interference by raising an adjacent channel tone to
% the third power.
Fint = Fc/3+50e3;
interference = 0.7*cos(2*pi*Fint*t+pi/8).^3;
% Calculate the total signal power for the given pulse shape. Account for
% the average power of the baseband 16-QAM upsampled signal. For a
% constellation that contains points with +/- 1 and +/- 3 amplitude levels,
% the average power of a 16-QAM signal is 10 W. The upsampling operation
% reduces this power by a factor of nSamps leading to a net power of
% 10*log10(10/nSamps), or 0.97 dBW for nSamps = 8.
avgPwrBaseBand16QAM = 10*log10(sum(abs(hMod.Constellation).^2)/(M*nSamps));
sigPower = 10*log10(sum(hXmtFlt.Numerator.^2)) + avgPwrBaseBand16QAM;
% Add white Gaussian noise based on the computed signal power.
yUp = awgn(xUp, SNR, sigPower);
% Add the adjacent channel interference to the signal.
yUpACI = yUp + interference;
% Estimate spectrum of the noisy signal and compare it to the spectrum of
% the original upconverted signal.
figure(hFig);hold on;
pwelch(yUpACI,hamming(512),[],[],Fs,'centered')
hLines = get(gca,'Children');
set(hLines(1),'Color',[1 0 0]);
legend('Signal at channel input',...
'Signal at channel output','Location','southwest')
% Downconvert to baseband (Assumes perfect synchronization).
yACI = yUpACI.*conj(carrier);
% Estimate spectrum of the downconverted signal with adjacent channel
% interference.
figure(hFig); hold off;
pwelch(yACI,hamming(512),[],[],Fs,'centered')
% Make a copy of the transmitter filter and use it as matched filter.
hRcvFlt = copy(hXmtFlt);
% Filter the frequency downconverted signal.
rcvSymACI = filter(hRcvFlt, yACI);
% Estimate spectrum of the filtered signal and compare it to the spectrum
% of the signal at the filter input.
figure(hFig);
hold on;
pwelch(rcvSymACI,hamming(512),[],[],Fs,'centered');
hLines=get(gca,'Children');
set(hLines(1),'Color',[1 0 0]);
legend('Signal at filter input',...
'Signal at filter output','Location','southwest')
% Amplify the signal to compensate for the power loss caused by pulse
% shaping and matched filtering. This places the received signal symbols
% around the expected 16-QAM constellation points.
rcvSymACI = nSym*rcvSymACI;
% Downsample the filtered signal. Discard the first nSym symbols due to
% filter delay.
e2eDelay = nSamps*nSym;
rcvSymDownACI = rcvSymACI(e2eDelay+1:nSamps:end);
% Obtain the scatter plot of the received signal with adjacent channel
% interference.
update(scatScope, rcvSymDownACI)
% Create demodulator.
hDemod = modem.qamdemod(hMod);
% Demodulate received symbols and count the number of symbol errors.
xHatACI = demodulate(hDemod, rcvSymDownACI);
numErr = sum(xHatACI~=b(1:end-nSym))