IT++ Logo
Simulation of a Multicode CDMA system on an AWGN channel

In this example we will introduce the multi-code spreading class Multicode_Spread_2d. This is the most general spreading class availiable in it++. Different spreading codes may be assigned to the I and Q branches. The number of multiple spreading codes and the spreading factor is determined by the number of rows and collumns respectively that is used when calling the member function set_codes. In this example we will use four Hadamard sequenced of length four, and the same spreading sequences will be used for the I and Q brances.

#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()
{
//Scalars:
int SF, Ncode, sc, i, j, NumOfBits, MaxIterations, MaxNrOfErrors, MinNrOfErrors;
double Eb;
//Vectors and matrixes:
vec EbN0dB, EbN0, N0, ber;
smat all_codes, spread_codesI, spread_codesQ;
bvec transmited_bits, received_bits;
cvec transmited_symbols, received_symbols, transmited_chips, received_chips;
//Classes:
AWGN_Channel channel;
QPSK qpsk;
BERC berc;
//Initialize the spreading:
SF = 4; //The spreading factor is 4
Ncode = 4; //Use all four codes in the multi-code spreader
all_codes = to_smat(hadamard(SF)); //Calculate the spreading codes
//Set the spreading codes:
spread_codesI.set_size(Ncode, SF, false);
spread_codesQ.set_size(Ncode, SF, false);
for (sc = 0; sc < Ncode; sc++) {
spread_codesI.set_row(sc, all_codes.get_row(sc));
spread_codesQ.set_row(sc, all_codes.get_row(sc));
}
mc_spread.set_codes(to_mat(spread_codesI), to_mat(spread_codesQ));
//Specify simulation specific variables:
EbN0dB = linspace(-2, 14, 17);
EbN0 = pow(10, EbN0dB / 10);
Eb = 1.0;
N0 = Eb * pow(EbN0, -1.0);
NumOfBits = 50000;
MaxIterations = 10;
MaxNrOfErrors = 200;
MinNrOfErrors = 5;
ber.set_size(EbN0dB.size(), false);
ber.clear();
//Randomize the random number generators:
for (i = 0; i < EbN0dB.length(); i++) {
cout << endl << "Simulating point nr " << i + 1 << endl;
berc.clear();
channel.set_noise(N0(i) / 2.0);
for (j = 0; j < MaxIterations; j++) {
transmited_bits = randb(NumOfBits);
transmited_symbols = qpsk.modulate_bits(transmited_bits);
//This is where we do the multi-code spreading:
transmited_chips = mc_spread.spread(transmited_symbols);
received_chips = channel(transmited_chips);
//The multi-code despreading:
//The second argument tells the despreader that the offset is zero chips.
//This offset is usefull on channels with delay.
received_symbols = mc_spread.despread(received_chips, 0);
received_bits = qpsk.demodulate_bits(received_symbols);
berc.count(transmited_bits, received_bits);
ber(i) = berc.get_errorrate();
cout << " Itteration " << j + 1 << ": ber = " << berc.get_errorrate() << endl;
if (berc.get_errors() > MaxNrOfErrors) {
cout << "Breaking on point " << i + 1 << " with " << berc.get_errors() << " errors." << endl;
break;
}
}
if (berc.get_errors() < MinNrOfErrors) {
cout << "Exiting Simulation on point " << i + 1 << endl;
break;
}
}
//Print results:
cout << endl;
cout << "EbN0dB = " << EbN0dB << endl;
cout << "ber = " << ber << endl;
//Exit program:
return 0;
}

A typical run of this program will look like this:

Simulating point nr 1
Itteration 1: ber = 0.13016
Breaking on point 1 with 6508 errors.
Simulating point nr 2
Itteration 1: ber = 0.103
Breaking on point 2 with 5150 errors.
Simulating point nr 3
Itteration 1: ber = 0.07886
Breaking on point 3 with 3943 errors.
Simulating point nr 4
Itteration 1: ber = 0.05534
Breaking on point 4 with 2767 errors.
Simulating point nr 5
Itteration 1: ber = 0.03822
Breaking on point 5 with 1911 errors.
Simulating point nr 6
Itteration 1: ber = 0.02388
Breaking on point 6 with 1194 errors.
Simulating point nr 7
Itteration 1: ber = 0.01316
Breaking on point 7 with 658 errors.
Simulating point nr 8
Itteration 1: ber = 0.00586
Breaking on point 8 with 293 errors.
Simulating point nr 9
Itteration 1: ber = 0.0027
Itteration 2: ber = 0.00247
Breaking on point 9 with 247 errors.
Simulating point nr 10
Itteration 1: ber = 0.00094
Itteration 2: ber = 0.00086
Itteration 3: ber = 0.00076
Itteration 4: ber = 0.00077
Itteration 5: ber = 0.0008
Itteration 6: ber = 0.000796667
Breaking on point 10 with 239 errors.
Simulating point nr 11
Itteration 1: ber = 0.00016
Itteration 2: ber = 0.00016
Itteration 3: ber = 0.000186667
Itteration 4: ber = 0.000175
Itteration 5: ber = 0.000172
Itteration 6: ber = 0.000173333
Itteration 7: ber = 0.000162857
Itteration 8: ber = 0.00017
Itteration 9: ber = 0.000166667
Itteration 10: ber = 0.000172
Simulating point nr 12
Itteration 1: ber = 4e-05
Itteration 2: ber = 2e-05
Itteration 3: ber = 2.66667e-05
Itteration 4: ber = 2.5e-05
Itteration 5: ber = 2e-05
Itteration 6: ber = 2e-05
Itteration 7: ber = 3.14286e-05
Itteration 8: ber = 2.75e-05
Itteration 9: ber = 2.44444e-05
Itteration 10: ber = 2.6e-05
Simulating point nr 13
Itteration 1: ber = 0
Itteration 2: ber = 0
Itteration 3: ber = 0
Itteration 4: ber = 0
Itteration 5: ber = 0
Itteration 6: ber = 0
Itteration 7: ber = 0
Itteration 8: ber = 2.5e-06
Itteration 9: ber = 2.22222e-06
Itteration 10: ber = 2e-06
Exiting Simulation on point 13
EbN0dB = [-2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
ber = [0.13016 0.103 0.07886 0.05534 0.03822 0.02388 0.01316 0.00586 0.00247 0.000796667 0.000172 2.6e-05 2e-06 0 0 0 0]

Use copy-and-paste to insert the variables EbN0dB and ber into Matlab and plot the result.

itpp::AWGN_Channel::set_noise
void set_noise(double noisevar)
Set noise variance (for complex-valued channels the sum of real and imaginary parts)
Definition: channel.h:1094
itpp::QPSK
QPSK modulator.
Definition: modulator.h:677
itpp::BERC::get_errorrate
double get_errorrate() const
Returns the estimated bit error rate.
Definition: error_counters.h:103
itpp::RNG_randomize
void RNG_randomize()
Set a random seed for all Random Number Generators in the current thread.
Definition: random.cpp:254
itpp::Modulator::modulate_bits
virtual void modulate_bits(const bvec &bits, Vec< T > &output) const
Modulation of bits.
Definition: modulator.h:362
itpp
itpp namespace
Definition: itmex.h:36
itpp::BERC::clear
void clear()
Clears the bit error counter.
Definition: error_counters.h:91
itpp::PSK::demodulate_bits
void demodulate_bits(const cvec &signal, bvec &bits) const
Hard demodulation of bits.
Definition: modulator.cpp:151
itpp::randb
bin randb(void)
Generates a random bit (equally likely 0s and 1s)
Definition: random.h:793
itpp::hadamard
imat hadamard(int size)
Hadamard matrix.
Definition: specmat.cpp:149
itpp::Multicode_Spread_2d
Multicode spreading of complex symbols to complex output.
Definition: spread.h:247
itpp::Multicode_Spread_2d::set_codes
void set_codes(const mat &incodesI, const mat &incodesQ)
Set the spreading codes.
Definition: spread.cpp:176
itpp::linspace
vec linspace(double from, double to, int points)
linspace (works in the same way as the MATLAB version)
Definition: specmat.cpp:106
itpp::AWGN_Channel
Ordinary AWGN Channel for cvec or vec inputs and outputs.
Definition: channel.h:1088
itpp::Multicode_Spread_2d::despread
cvec despread(const cvec &receivedsignal, int timing)
Despreading of signal. timing is the start position of the first symbol, given in number of samples.
Definition: spread.cpp:189
itpp::pow
vec pow(const double x, const vec &y)
Calculates x to the power of y (x^y)
Definition: log_exp.h:176
itpp::Multicode_Spread_2d::spread
cvec spread(const cvec &symbols)
Spreading of signal.
Definition: spread.cpp:184
itpp::BERC::get_errors
double get_errors() const
Returns the counted number of bit errors.
Definition: error_counters.h:97
itpp::BERC
Bit Error Rate Counter (BERC) Class.
Definition: error_counters.h:67
itpp::to_smat
smat to_smat(const Mat< T > &m)
Converts a Mat<T> to smat.
Definition: converters.h:184
itcomm.h
Include file for the IT++ communications module.
itpp::BERC::count
void count(const bvec &in1, const bvec &in2)
Cumulative error counter.
Definition: error_counters.cpp:49
itpp::to_mat
mat to_mat(const Mat< T > &m)
Converts a Mat<T> to mat.
Definition: converters.h:216

Generated on Mon Mar 23 2020 06:18:03 for IT++ by Doxygen 1.8.17