DSPRelated.com
Code

16QAM Modem model (Basic)

kaz - December 12, 2011 Coded in Matlab

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')