On the Performance of QPSK Modulation over Downlink NOMA: From error probability derivation to SDR-based validation
This repository is associated to the article available here.
Description
In this project, we study the performance of QPSK modulation in the context of multi-user downlink NOMA with a successive interference canceller (SIC) at the receiver side. We derive the analytical formula on its closed-form in the associated paper, and use the code in this repository to verify it, both through simulation and experimental validation. Numerical simulations are used to not only to corroborate the tightness of our theoretical expressions, but also to analyze the problem of power allocation in the two and three users cases. Finally, the code for an experimental validation testbed using NOMA with software defined radio is provided.
Table of content
- GNURadio : GNURadio flowgraphs used in our experimental setup
- gr-NOMA : Custom-made blocks, using C++, used in the flowgraphs
- Matlab : Matlab code used to generate the channel parameters used in simulations
- Python : Python scripts used for the simulations and optimization
GNURadio
These flowgraphs rely on the blocs defined in gr-NOMA, they must be installed first.
flowgraph_NOMA_2_users.grc
A flowgraph generating random symbols for 2 users, combining them using NOMA, and transmitting them through 2 antennas. They are then decoded, and the BER is computer for each user.
In this setup, the power allocated to each user can be chosen in live transmissions.
flowgraph_NOMA_3_users.grc
A flowgraph generating random symbols for 3 users, combining them using NOMA, and transmitting them through 2 antennas. They are then decoded, and the BER is computer for each user.
In this setup, the power allocated to each user can be chosen in live transmissions.
noise_generator.grc
This flowgraph generates random complex symbols, following a Gaussian repartition. These symbols are then sent at a given frequency, to generate random noise in our channel.
The noise's power can be modified during the transmission.
sync_test_flowgraph.grc
This simple flowgraph is used to test the phrase-shift correction for the blocs sync_frames_sender
and sync_frames_receiver
.
gr-NOMA
It is assumed that GNURadio is installed for the following steps. This repository should also be cloned or downloaded.
Installation
First, move to the right folder:
cd [...]/gr-NOMA
Then, create a build
build folder (if it doesn't already exist) :
mkdir build
cd build
Then, compile the blocks:
cmake .. && make
And install them:
sudo make install
For linux, each time new blocks are installed, you must run this command:
sudo ldconfig
Blocs description
Note: The blocs' code is located in the gr-NOMA/lib
subfolder.
BERCounter
Compute the Binary Error Rate for N users when provided the expected and decoded results.
- in[0...N-1]: Reference values
- in[N...2N-1]: Received values
- out: BER
in[0] is compared to in[N], in[1] to in[N+1] and so one.
decode_cc
Decode N users NOMA symbol, expected input to use a QPSK constellation for each user.
- in[0...N-1]: Each user's power (in decreasing order of magnitude)
- in[N]: The complex symbol to decode
- out[0...N-1]: Each user's decoded symbol
random_source_c
Generate a random complex number at a given frequency.
freq
corresponds to samp_rate / sps
, with sps
the number of samples per symbol to output.
resampler_cc
Keeps only 1 symbol out of resamp_ratio
, dephased starting at phase_shift * resamp_ratio
.
Allows the user to extract only meaningful values from a given set. The resamp_ratio
is typically sps
(number of samples per symbol).
phase_shift
helps choosing which value is kept. For example, if resamp_ratio = 32
and phase_shift = 0.5
, then, out of 32 values, only the 16th value is kept (which probably corresponds to the max power).
signalMerger
Create a single symbol from multiple users' symbols using NOMA.
- in[0...N-1]: Each user's power (in decreasing order of magnitude)
- in[N...2N-1]: Each user's symbol to transmit
- out[0...N-1]: The ponderated sum of the users' symbols
The output corresponds to in[0] * sqrt(in[N] / 2) + in[1] * sqrt(in[N+1] / 2) + ...
.
sync_frames_receiver
Block which automatically corrects the phase and amplitude of received symbols.
This should be at the receiving end of a sync_frame_sender
bloc.
This block uses an initial burst of known symbols to compute the average phase and amplitude difference, and corrects it for all the following symbols.
It expects the initial known symbols (defined in the syncFrames
vector of complex values) to be sent with a frequency of freq
(where freq = sample_rate / sps
).
No symbol is dropped by the block (it just prepends some symbols at the start).
Increasing procPerSymbol
means that, for each known symbol, multiple values will be analyzed to compute the phase and amplitude difference. It is recommended to only increase this if the received symbols stay long enough at the optimal amplitude (i.e. the transition period is small).
Warning: The values in syncFrames
MUST be != 0. Indeed, since this block is meant to be placed after an USRP source, it will initally be given noise by the antenna until the USRP source actually sends symbols. This means we have to find out which symbols are noise. This is done with a simple amplitude threshold on received values.
sync_frames_sender
Block which initially sends reference symbols and, coupled with a sync_frams_receiver
, corrects the phase and amplitude of received symbols.
This should be at the sending end of a sync_frame_sender
bloc.
This block sends an initial burst of known symbols, later used in sync_frames_receiver
to compute the average phase and amplitude difference, and correct it for all the following symbols.
It sends the initial known symbols (defined in the syncFrames
vector of complex values) with a frequency of freq
(where freq = sample_rate / sps
).
After sending those symbols, it just acts as a passthrough block. No symbol is dropped by the block (it just prepends some symbols at the start).
Warning: The values in syncFrames
MUST be != 0 (see sync_frames_receiver for details).
Matlab
In order to use this code, the parameters from BaseCodeMS.m
must be modified, especially the values of N
(the noise of the canal) and g
(the attenuation for each user).
The power of the noise, N
, must be simply converted in sigma
(used in our algorithms), the standard deviation of the Gaussian noise.
Python
We assume that Python 3 and numpy are installed on the machine.
Script descriptions
Comparison_Experiment_Theory.py
Contains measured BER (Bit Error Rate) for 3 users, and compares them with theoretical results.
Comparison_Model_Theory.py
Contains several functions to compare the theoretical BER with a statistical BER calculated using the Monte Carlo method.
Find_Optimum.py
Contains the algorithm for searching for the optimum power distribution. A custom implementation is compared to an existing solution. It is based on scipy and uses the file Theorie_N_receptors.py
.
Its behavior is detailed in our report, and explanations on the matrices used in the optimization are given at the beginning of the file.
Model_N_receivers.py
Contains functions to calculate an error rate by following the ideal channel model with the Monte-Carlo method.
Usage examples are given in Comparison_Model_Theorie.py
and at the end of the file.
NOMA_Optimize.c
Contains an implementation of the proposed algorithm to find the optimum power distributions for N users. This file can be compiled using python3 setup.py --install
, and then used as a standard module (see Time_Optimum.py
for an example).
Theory_N_receivers.py
Contains functions to calculate the theoretical error rate using the formula developed in the report (and the pseudo code given therein).
Usage examples are given in Comparaison_Modele_Theorie.py
and at the end of the file.
Time_Optimum.py
Contains the algorithm used to compare our proposed optimization method with the Basin-Hopping implementation in Scipy. It imports the contents of NOMA_Optimize.c
as a module, which requires the command python3 setup.py --install
to be run beforehand.
Appendixes
OFDMA
An implementation of OFDMA could be interesting, as seen in the following publication: https://www.researchgate.net/publication/322924686_OFDMA_Simulations_on_GNU_Radio. We were however unable to reproduce the flowgraph describe.