function msfcn_udpReceiveFcn(block)
% Copyright 2012 Borja Fons Albert, Hèctor Usach Molina, Joan Vila Carbó.
% All rights reserved.
% 
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
% 
%  1. Redistributions of source code must retain the above copyright
%     notice, this list of conditions and the following disclaimer.
% 
%  2. Redistributions in binary form must reproduce the above copyright
%     notice, this list of conditions and the following disclaimer in the
%     documentation and/or other materials provided with the distribution.
% 
% THIS SOFTWARE IS PROVIDED BY BORJA FONS ALBERT, HÈCTOR USACH MOLINA AND
% JOAN VILA CARBÓ ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
% AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
% BORJA FONS ALBERT, HÈCTOR USACH MOLINA AND JOAN VILA CARBÓ OR
% CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
% PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
% LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
% 
% The views and conclusions contained in the software and documentation are
% those of the authors and should not be interpreted as representing
% official policies, either expressed or implied, of Borja Fons Albert,
% Hèctor Usach Molina and Joan Vila Carbó.

setup(block);

%endfunction

%*****************************************************************************************
% SETUP
%*****************************************************************************************
function setup(block)

% Registrar metodos ----------
block.RegBlockMethod('SetInputPortSamplingMode',@SetInputPortSamplingMode);
block.RegBlockMethod('Terminate',@Terminate);
block.RegBlockMethod('Outputs', @Output);

% Registrar entradas ---------
block.NumInputPorts = 0;


% Setup functional port properties to dynamically inherited.
block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;

% Registrar salidas ---------
recv_dref = block.DialogPrm(2).Data;
Noutput = length(recv_dref);
block.NumOutputPorts = Noutput+1;
for i=1:Noutput
    block.OutputPort(i).DataTypeID = 0; %double
    block.OutputPort(i).Dimensions = 1;
    block.OutputPort(i).SamplingMode = 0; % frame
end
%Integrity port
block.OutputPort(Noutput+1).DataTypeID = 8; %boolean
block.OutputPort(Noutput+1).Dimensions = 1;
block.OutputPort(Noutput+1).SamplingMode = 0; % frame


% Registrar parametros ----------
block.NumDialogPrms = 3; % Puerto, dataref y Periodo
block.DialogPrmsTunable = {'Nontunable' 'Nontunable' 'Nontunable'};

% Registrar sampling times
block.SampleTimes = [block.DialogPrm(3).Data 0];

% Set the block simStateCompliance to default (i.e., same as a built-in block)
block.SimStateCompliance = 'DefaultSimState';

% Run accelerator on TLC
block.SetAccelRunOnTLC(true);


%endfunction


function SetInputPortSamplingMode(block, idx, fd)

%endfunction


%*****************************************************************************************
% OUTPUT
%*****************************************************************************************
function Output(block)

global rsock recv_pkt
persistent recv_dref pindex pdata

import java.io.*;
import java.net.*;
import java.lang.*;

if isempty(rsock)
    port = block.DialogPrm(1).Data;
    rsock = java.net.DatagramSocket(port);
    rsock.setSoTimeout(1000);
    recv_pkt = java.net.DatagramPacket(uint8(zeros(1,256)), 256);
    recv_dref = block.DialogPrm(2).Data;
end

if isempty(pindex)
    pindex=zeros(length(recv_dref));
    pdata=zeros(length(recv_dref));
end

try
    rsock.receive(recv_pkt);
    comm_integrity=1;
catch err
    %warning(getReport(err));
    warning('Receive timed out')
    comm_integrity=0;
end

recv_data = recv_pkt.getData();
recv_data = recv_data(6:end);
numbytes = recv_pkt.getLength();
n = (numbytes-5)/8;

try
    for i=1:n
        pindex(i)=typecast(recv_data((i-1)*8+1:(i-1)*8+4),'uint32');
        pdata(pindex(i))=typecast(recv_data((i-1)*8+5:(i-1)*8+8),'single');
    end
    data=double(pdata);
catch
    data=zeros(1,length(recv_dref));
end
%index=pindex;

% Salida de datos
for i=1:length(recv_dref)
    block.OutputPort(i).Data = data(i);
end
block.OutputPort(length(recv_dref)+1).Data = logical(comm_integrity);
%endfunction


%*****************************************************************************************
% TERMINATE
%*****************************************************************************************
function Terminate(block)

% Al acabar se cierra el socket
global rsock recv_pkt tant
close(rsock)
clearvars -GLOBAL rsock recv_pkt tant
%endfunction
