function [ChanMod_output, BS_output] = LTE_downconverter(ChanMod_output, BS_output, LTE_params)
% Function implementing downconversion and filtration in LTE
% Author:   Jiri Milos
% Date:     2014/07/03
% Brno University of Technology, DREL
%
% Inputs:   BS_output ... structure of outputs from base station
%           LTE_params ... structure of simulator parameters
% Outputs:  BS_output ... here for transparency (UE_input)

fs = LTE_params.Fs;
fc = LTE_params.carrier_freq;
delay = 15;
rolloff = LTE_params.rolloff;
B = LTE_params.Bandwidth;
fInterfOffset = LTE_params.InterfOffset;
% oversampling factor
oversamp = 2*ceil((fc+(B/2)+fInterfOffset)/fs);

hpulse = rcosine(fs,oversamp*fs,'normal',rolloff,delay);

Signal = ChanMod_output.y_rx; % POTREBA VYTVORIT!!!
% downkonverze
tt = (0:length(Signal)-1)*((1/fs)/oversamp);
InphaseNosna = sqrt(2)*cos(2*pi*fc*tt);
QuadratureNosna = sqrt(2)*sin(2*pi*fc*tt);

rxInphase = Signal.*InphaseNosna;
rxQuadrature = Signal.*QuadratureNosna;

clear Signal
% inverzni filtrace
% filtrace
if LTE_params.useGPU
    % Inphase
    CUDA_real = gpuArray(rxInphase);                % uložení do GPU
    InphaseSignalFiltCUDA=filter(hpulse,0.5,CUDA_real)/oversamp;    % výpočet
    rxInphaseSignalFiltered = gather(InphaseSignalFiltCUDA);          % uložení do workspace
    % vymazání proměných GPU pro uvlonění paměti
    clear CUDA_real InphaseSignalFiltCUDA
    % Quadrature
    CUDA_imag = gpuArray(rxQuadrature);                % uložení do GPU
    QuadratureSignalFiltCUDA=filter(hpulse,0.5,CUDA_imag)/oversamp;    % výpočet
    rxQuadratureSignalFiltered = gather(QuadratureSignalFiltCUDA);          % uložení do workspace
    % vymazání proměných GPU pro uvlonění paměti
    clear CUDA_imag QuadratureSignalFiltCUDA
else    
    rxInphaseSignalFiltered = filter(hpulse,0.5,rxInphase)/oversamp;
    rxQuadratureSignalFiltered = filter(hpulse,0.5,rxQuadrature)/oversamp;    
end

% downsampling
rxInphaseDownsampled = downsample(rxInphaseSignalFiltered,oversamp);
rxQuadratureDownsampled = downsample(rxQuadratureSignalFiltered,oversamp);

% kompenzace zpozdeni filtru
rxInphaseDownsampled = rxInphaseDownsampled(2*delay+1:end);
rxQuadratureDownsampled = rxQuadratureDownsampled(2*delay+1:end);

% prevedeni zpet na komplexni signal
ChanMod_output.y_rx = rxInphaseDownsampled+1j*rxQuadratureDownsampled;


% % % BS_output.txSignal = txInphase+txQuadrature;
% pwelch(BS_output.txSignal)

% rusivy = txInphase2+txQuadrature2;
% pwelch(BS_output.txSignal+rusivy)
end
