/*---------------------------------------------------------------------------*
* IT++ *
*---------------------------------------------------------------------------*
* Copyright (c) 1995-2002 by Tony Ottosson, Thomas Eriksson, Pål Frenger, *
* Tobias Ringström, and Jonas Samuelsson. *
* *
* Permission to use, copy, modify, and distribute this software and its *
* documentation under the terms of the GNU General Public License is hereby *
* granted. No representations are made about the suitability of this *
* software for any purpose. It is provided "as is" without expressed or *
* implied warranty. See the GNU General Public License for more details. *
*---------------------------------------------------------------------------*/
/*!
\file
\brief Implementation of an Orthogonal Frequency Division Multiplex (OFDM) class.
\author Pål Frenger, Anders Persson and Tony Ottosson
1.5
2003/05/22 08:55:20
*/
#include "comm/ofdm.h"
#include "base/specmat.h"
#include "base/transforms.h"
#include "base/operators.h"
namespace itpp {
OFDM::OFDM(int inNfft, int inNcp)
{
set_parameters(inNfft, inNcp);
}
void OFDM::set_parameters(const int inNfft, const int inNcp){
it_assert(inNfft >= 2, "OFDM: Nfft must be >=2.");
it_assert(inNcp >=0 && inNcp <= inNfft, "OFDM: Ncp must be >=0 and <=Nfft.");
Nfft = inNfft;
Ncp = inNcp;
setup_done = true;
}
void OFDM::modulate(const cvec &input, cvec &output){
it_assert(setup_done == true, "OFDM: You must set the length of the FFT and the cyclic prefix!");
const int N = input.length()/Nfft;
it_assert(N*Nfft == input.length(), "OFDM: Length of input vector is not a multiple of Nfft.");
output.set_length(N*(Nfft+Ncp));
cvec outtemp(Nfft);
const double norm_factor = sqrt((double)(Nfft*Nfft)/(Nfft+Ncp));
for(int i=0; i<N; i++) {
outtemp = ifft(input.mid(i*Nfft, Nfft))*norm_factor;
output.replace_mid((Nfft+Ncp)*i, concat(outtemp.right(Ncp), outtemp));
}
}
cvec OFDM::modulate(const cvec &input)
{
it_assert(setup_done == true,"OFDM: You must set the length of the FFT and the cyclic prefix!");
const int N = input.length()/Nfft;
it_assert(input.length() == N*Nfft, "OFDM: Length of input vector is not a multiple of Nfft.");
cvec output(N*(Nfft+Ncp));
modulate(input, output);
return output;
}
void OFDM::demodulate(const cvec& input, cvec &output){
it_assert(setup_done == true, "OFDM: You must set the length of the FFT and the cyclic prefix!");
const int N = input.length()/(Nfft+Ncp);
it_assert(N*(Nfft+Ncp) == input.length(), "OFDM: Length of input vector is not a multiple of Nfft+Ncp.");
output.set_length(N*Nfft);
// normalize also taking the energy loss into the cyclic prefix into account
const double norm_factor = 1.0/sqrt((double)(Nfft*Nfft)/(Nfft+Ncp));
for(int i =0; i<N; i++)
output.replace_mid(Nfft*i, fft(input.mid(i*(Nfft+Ncp)+Ncp, Nfft))*norm_factor);
}
cvec OFDM::demodulate(const cvec &input){
it_assert(setup_done == true, "OFDM: You must set the length of the FFT and the cyclic prefix!");
const int N = input.length()/(Nfft+Ncp);
it_assert(N*(Nfft+Ncp) == input.length(), "OFDM: Length of input vector is not a multiple of Nfft+Ncp.");
cvec output(N*Nfft);
demodulate(input, output);
return output;
}
} //namespace itpp
syntax highlighted by Code2HTML, v. 0.9.1