16QAM Modem model (Basic)
The code models basic functions of a 16QAM Modem. For simplicity, it is kept in matlab floating and it does not include bit processing functions such as encoding/interleaving ...etc., or channel noise, symbol clock recovery or carrier tracking which obviously need more advanced models.
clear all; close all;
n = 2^16; %number of symbols
Fsym = 12.5; %Msps
Fs = 100; %MHz, IF sampling frequency
Fc = 20; %MHz, upconverter frequency
%generate 16QAM raw symbols
alphabet = [-1 -1/3 +1/3 +1];
tx = complex(randsrc(1,n,alphabet),randsrc(1,n,alphabet));
%pulse shaping, root raised cosine
h = firrcos(50,Fsym/4,.15,Fsym,'rolloff','sqrt');
tx_up1 = zeros(1,2*n);
tx_up1(1:2:end-1) = tx;
tx_shaped = filter(2*h,1,tx_up1);
%further upsampling by 4
tx_up2 = resample(tx_shaped,4,1);
%upconvert to 10MHz centre
f1 = exp(1i*2*pi*(0:8*n-1)*Fc/Fs);
tx_upconverted = tx_up2 .* f1;
%channel signal
rx_real = real(tx_upconverted);
%Rx shifts signal back to zero
f2 = exp(1i*2*pi*(0:8*n-1)*-Fc/Fs);
rx_downconverted = rx_real.*f2;
%Rx downsamples back by 4
rx_dn1 = resample(rx_downconverted,1,4);
%rx matched filter
rx_dn2 = filter(2*h,1,rx_dn1);
rx_dn2 = rx_dn2(50:end); %remove initial zeros
%one phase should be correct(odd/even)
rx_e = rx_dn2(1:2:end); %odd
rx_o = rx_dn2(2:2:end); %even
subplot(3,1,1);plot(real(tx),imag(tx),'o');
axis([-2 +2 -2 +2]);grid;
title('Tx constellations')
subplot(3,1,2);plot(real(rx_e),imag(rx_e),'o');
axis([-2 +2 -2 +2]);grid;
title('Rx constellations, first phase')
subplot(3,1,3);plot(real(rx_o),imag(rx_o),'o');
axis([-2 +2 -2 +2]);grid;
title('Rx constellations, second phase')