/*---------------------------------------------------------------------------*
 *                                   IT++			             *
 *---------------------------------------------------------------------------*
 * Copyright (c) 1995-2004 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 spread spectrum classes and functions
  \author Tony Ottosson

  1.8

  2004/09/03 07:47:28
*/

#include "base/binary.h"
#include "base/elmatfunc.h"
#include "base/stat.h"
#include "base/matfunc.h"
#include "base/fastmath.h"
#include "base/operators.h"
#include "comm/spread.h"

//------------- Spread1d -------------------

namespace itpp {

  Spread_1d::Spread_1d(const vec &incode)
  {
    set_code(incode);
  }

  void Spread_1d::set_code(const vec &incode)
  {
    N = incode.size();
    code=incode;
    code/=norm(code);
  }

  vec Spread_1d::get_code()
  {
    return code;
  }

  void Spread_1d::spread(const vec &symbols, vec &out)
  {
    out.set_size(symbols.length()*N, false);
  
    for(int i=0;i<symbols.length();i++)
      out.replace_mid(i*N,symbols(i)*code);
  }

  void Spread_1d::despread(const vec &rec_signal, vec &out, int timing)
  {
    int nosymbols=(int)std::floor(double((rec_signal.length()-timing))/N);
    out.set_size(nosymbols);
	
    for(int i=0;i<nosymbols;i++)
      out(i) = rec_signal.mid(i*N+timing,N)*code;
  }


  //---------------- Spread2d ----------------------

  vec Spread_2d::get_codeI()
  {
    return spreadI.get_code();
  }

  vec Spread_2d::get_codeQ()
  {
    return spreadQ.get_code();
  }

  Spread_2d::Spread_2d(const vec &incodeI, const vec &incodeQ)
  {
    set_code(incodeI,incodeQ);
  }

  void Spread_2d::set_code(const vec &incodeI, const vec &incodeQ)
  {
    it_assert(incodeI.length()==incodeQ.length(), "Size of I and Q codes doesn't match");
    spreadI.set_code(incodeI);
    spreadQ.set_code(incodeQ);
  }

  void Spread_2d::spread(const cvec &symbols, cvec &out)
  {
    out = to_cvec(spreadI.spread(real(symbols)),spreadQ.spread(imag(symbols)));
  }

  void Spread_2d::despread(const cvec &rec_signal, cvec &out, int timing)
  {
    out = to_cvec(spreadI.despread(real(rec_signal),timing),spreadQ.despread(imag(rec_signal),timing) );
  }



  //------------- Multicode_Spread_1d ----------------


  Multicode_Spread_1d::Multicode_Spread_1d(const mat &incodes)
  {
    set_codes(incodes);
  }

  void Multicode_Spread_1d::set_codes(const mat &incodes)
  {
    codes=incodes;
    N=incodes.cols();
    L=incodes.rows();
    for (int i=0; i<L; i++)
      codes.set_row(i, codes.get_row(i)/norm(codes.get_row(i)));
  }

  mat Multicode_Spread_1d::get_codes()
  {
    return codes;
  }

  vec Multicode_Spread_1d::spread(const vec &symbols)
  {
    int i;
    int nomcsymbols=(int)std::floor(double(symbols.length()/L));
    vec temp(nomcsymbols*N);
	
    for(i=0;i<nomcsymbols;i++) {
      temp.replace_mid(i*N,codes.T() * symbols.mid(i*L,L)); // TODO: this is now very slow
    }	

    return temp;
  }

  vec Multicode_Spread_1d::despread(const vec &receivedsignal, int timing)
  {
    int i;
    int nosymbols=(int)std::floor(double((receivedsignal.length()-timing))/N);
    vec temp(nosymbols*L);
	
    for(i=0;i<nosymbols;i++) {
      temp.replace_mid(i*L,codes*receivedsignal.mid(i*N+timing,N));
    }
    return temp;
  }


  //----------------- Multicode_Spread_2d -------------------


  Multicode_Spread_2d::Multicode_Spread_2d(const mat &incodesI, const mat &incodesQ)
  {
    set_codes(incodesI,incodesQ);
  }

  mat Multicode_Spread_2d::get_codesI()
  {
    return mcspreadI.get_codes();
  }

  mat Multicode_Spread_2d::get_codesQ()
  {
    return mcspreadQ.get_codes();
  }

  void Multicode_Spread_2d::set_codes(const mat &incodesI, const mat &incodesQ)
  {
    assert(incodesI.rows()==incodesQ.rows() && incodesI.cols()==incodesQ.cols());
    mcspreadI.set_codes(incodesI);
    mcspreadQ.set_codes(incodesQ);
  }

  cvec Multicode_Spread_2d::spread(const cvec &symbols)
  {
    return to_cvec(mcspreadI.spread(real(symbols)),mcspreadQ.spread(imag(symbols)));
  }

  cvec Multicode_Spread_2d::despread(const cvec &receivedsignal, int timing)
  {
    return to_cvec(mcspreadI.despread(real(receivedsignal),timing),mcspreadQ.despread(imag(receivedsignal),timing) );
  }

} //namespace itpp


syntax highlighted by Code2HTML, v. 0.9.1