IT++ Logo

Simulation of QPSK modulation on an AWGN channel

In this example we will introduce a few new features compared to the BPSK example. We will use the it_ifile class to store the results of the simulation. We will use the Real_Timer class to measure the execution time of our program. Furthermore we will use one of the channel classes, the AWGN_Channel. We will also show how to read the results in to Matlab with the load_it function. The program is as follows:

#include <itpp/itcomm.h>

using namespace itpp;

//These lines are needed for use of cout and endl
using std::cout;
using std::endl;

int main()
{
  //Declarations of scalars and vectors:
  int i, Number_of_bits;
  double Ec, Eb;
  vec EbN0dB, EbN0, N0, noise_variance, bit_error_rate; //vec is a vector containing double
  bvec transmitted_bits, received_bits;                 //bvec is a vector containing bits
  cvec transmitted_symbols, received_symbols;           //cvec is a vector containing double_complex

  //Declarations of classes:
  QPSK qpsk;                     //The QPSK modulator class
  AWGN_Channel awgn_channel;     //The AWGN channel class
  it_file ff;                    //For saving the results to file
  BERC berc;                     //Used to count the bit errors
  Real_Timer tt;                 //The timer used to measure the execution time

  //Reset and start the timer:
  tt.tic();

  //Init:
  Ec = 1.0;                      //The transmitted energy per QPSK symbol is 1.
  Eb = Ec / 2.0;                 //The transmitted energy per bit is 0.5.
  EbN0dB = linspace(0.0,9.0,10); //Simulate for 10 Eb/N0 values from 0 to 9 dB.
  EbN0 = inv_dB(EbN0dB);         //Calculate Eb/N0 in a linear scale instead of dB.
  N0 = Eb * pow(EbN0,-1.0);      //N0 is the variance of the (complex valued) noise.
  Number_of_bits = 100000;       //One hundred thousand bits is transmitted for each Eb/N0 value

  //Allocate storage space for the result vector.
  //The "false" argument means "Do not copy the old content of the vector to the new storage area."
  bit_error_rate.set_size(EbN0dB.length(),false);

  //Randomize the random number generators in it++:
  RNG_randomize();

  //Iterate over all EbN0dB values:
  for (i=0; i<EbN0dB.length(); i++) {

    //Show how the simulation progresses:
    cout << "Now simulating Eb/N0 value number " << i+1 << " of " << EbN0dB.length() << endl;

    //Generate a vector of random bits to transmit:
    transmitted_bits = randb(Number_of_bits);

    //Modulate the bits to QPSK symbols:
    transmitted_symbols = qpsk.modulate_bits(transmitted_bits);

    //Set the noise variance of the AWGN channel:
    awgn_channel.set_noise(N0(i));

    //Run the transmited symbols through the channel using the () operator:
    received_symbols = awgn_channel(transmitted_symbols);

    //Demodulate the received QPSK symbols into received bits:
    received_bits = qpsk.demodulate_bits(received_symbols);

    //Calculate the bit error rate:
    berc.clear();                               //Clear the bit error rate counter
    berc.count(transmitted_bits,received_bits); //Count the bit errors
    bit_error_rate(i) = berc.get_errorrate();   //Save the estimated BER in the result vector

  }

  tt.toc();

  //Print the results:
  cout << endl;
  cout << "EbN0dB = " << EbN0dB << " [dB]" << endl;
  cout << "BER = " << bit_error_rate << endl;
  cout << "Saving results to ./qpsk_result_file.it" << endl;
  cout << endl;

  //Save the results to file:
  ff.open("qpsk_result_file.it");
  ff << Name("EbN0dB") << EbN0dB;
  ff << Name("ber") << bit_error_rate;
  ff.close();

  //Exit program:
  return 0;

}

When you run this program, the output will look something like this:

Now simulating Eb/N0 value number 1 of 10
Now simulating Eb/N0 value number 2 of 10
Now simulating Eb/N0 value number 3 of 10
Now simulating Eb/N0 value number 4 of 10
Now simulating Eb/N0 value number 5 of 10
Now simulating Eb/N0 value number 6 of 10
Now simulating Eb/N0 value number 7 of 10
Now simulating Eb/N0 value number 8 of 10
Now simulating Eb/N0 value number 9 of 10
Now simulating Eb/N0 value number 10 of 10
Elapsed time = 0.460899 seconds

EbN0dB = [0 1 2 3 4 5 6 7 8 9] [dB]
BER = [0.07968 0.0559 0.03729 0.02294 0.01243 0.0058 0.0025 0.00076 0.00013 6e-05]
Saving results to ./qpsk_result_file.it

Now it is time to plot the simulation results in Matlab and compare with theory using the Matlab code below. The results will be stored in a file called "qpsk_result_file.it". Make sure load_it.m is in your Matlab path (look in /matlab) and that you run the example code below from the directory where qpsk_result_file.it is located

figure(1); clf;
load_it qpsk_result_file.it
h1 = semilogy(EbN0dB,ber,'*-r'); hold on
ebn0db = 0:.1:10;
ebn0 = 10.^(ebn0db/10);
Pb = 0.5 * erfc(sqrt(ebn0));
h2 = semilogy(ebn0db,Pb);
set(gca,'fontname','times','fontsize',16);
xlabel('{\it E_b} / {\it N}_0 [dB]');
ylabel('BER')
title('QPSK on an AWGN Channel');
legend([h1 h2],'Simulation','Theory');
grid on;
SourceForge Logo

Generated on Sat Apr 19 10:41:18 2008 for IT++ by Doxygen 1.5.5