classdef channelBlock < matlab.DiscreteEventSystem & matlab.system.mixin.Propagates & ...
                                          matlab.system.mixin.CustomIcon
%channelBlock Models the channel for a node
%
%   This is an example helper class.
%
%   This block has 1 input port:
%   1. WaveformIn - Abstracted waveform received
%       * Bus object of type "AbstractWaveform" available in the
%         wlanAbstractedPHYDataTypes.mat file
%
%   This block has 1 output port:
%   1. WaveformOut - Abstracted waveform sent out
%       * Bus object of type "AbstractWaveform" available in the
%         wlanAbstractedPHYDataTypes.mat file
%
%   This block performs the following operations:
%      - Range propagation modeling
%      - Free space pathloss modeling

%   Copyright 2019 The MathWorks, Inc.
    
    properties
        % Node ID
        RecvNodeID (1, 1) {mustBeInteger, mustBeGreaterThan(RecvNodeID, 0)} = 1;
        % Position
        RecvPos (1, 3) {mustBeNumeric} = [0 0 0];
        % Packet Receive Range (meters)
        PacketRxRange (1,1) {mustBeInteger, mustBeGreaterThan(PacketRxRange, 0)}  = 10000;
    end
    
    properties(Nontunable, Logical)
        % Apply Free-space Path Loss
        FreeSpacePathloss = true;
    end
    
    properties (Constant, Hidden)
        % Operating Frequency (GHz)
        Frequency = 5.18;
        % Queue for holding waveforms from PHY
        WaveformQueueID = 1;
        % Output port for waveforms from channel
        WaveformOutputPortIndex = 1;
    end
    
    % Discrete-event algorithms
    methods
        function [entity, events] = waveformEntry(obj, ~, entity, ~)
            %waveformEntry Apply range propagation loss and free-space pathloss
            
            % Calculate distance between sender and receiver
            dist = norm(entity.data.metaData.senderPosition - obj.RecvPos);
            
            if((entity.data.metaData.srcId ~= obj.RecvNodeID) && (dist <= obj.PacketRxRange))
                if obj.FreeSpacePathloss
                    lambda = physconst('LightSpeed')/(obj.Frequency*1e9);
                    % Calculate free space path loss (in dB)
                    pathLoss = fspl(dist, lambda);
                    % Apply pathloss on the signal power of the waveform
                    entity.data.metaData.sigPower  =  entity.data.metaData.sigPower - pathLoss;
                end
                
                events = obj.eventForward('output', obj.WaveformOutputPortIndex, 0);
            else
                % If the waveform is intended for self, or if the waveform is
                % beyond the configured range of distance, discard the
                % waveform
                events = obj.eventDestroy();
            end
        end
    end
    
    methods(Static, Access=protected)
        % Customize the dialog header
        function header = getHeaderImpl
            header = matlab.system.display.Header(...
                'channelBlock', ...
                'Title', 'Statistical Channel');
        end
        
        % Customize the property attributes
        function group = getPropertyGroupsImpl
            p1 = matlab.system.display.internal.Property('RecvNodeID', ...
                'IsGraphical', false); % Hide from dialog
            p2 = matlab.system.display.internal.Property('RecvPos', ...
                'IsGraphical', false); % Hide from dialog
            
            group = matlab.system.display.Section(...
                'Title', 'Parameters', ...
                'PropertyList', {p1, p2, 'PacketRxRange', 'FreeSpacePathloss'});
        end
    end
    
    methods (Access=protected)
        
        function entityTypes = getEntityTypesImpl(obj)
            % Return entity type structures with fields specifying
            % properties such as name, size, data type, and complexity
            entityTypes = obj.entityType('waveform', 'AbstractWaveform');
        end
        
        function [inputTypes,outputTypes] = getEntityPortsImpl(~)
            % Specify entity input and output ports. Return entity types at
            % a port as strings in a cell array. Use empty string to
            % indicate a data port.
            inputTypes = 'waveform';
            outputTypes = 'waveform';
        end
        
        function [storageSpecs, I, O] = getEntityStorageImpl(obj)
            % Return entity storage specification and connectivity
            % information from input ports and output ports to storage
            % Size of queue holding waveforms from PHY
            WaveformQueueSize = 5;
            storageSpecs = obj.queueFIFO('waveform', WaveformQueueSize);
            I = obj.WaveformQueueID;
            O = obj.WaveformQueueID;
        end
        
        function num = getNumInputsImpl(~)
            % Port for waveforms from PHY
            num = 1;
        end
        
        function name = getInputNamesImpl(~)
            % Return input port names for System block
            name = "WaveformIn";
        end
        
        function name = getOutputNamesImpl(~)
            % Return output port names for System block
            name = "WaveformOut";
        end
        
        function num = getNumOutputsImpl(~)
            % Port for waveforms from channel
            num =  1;
        end
        
        function out = getOutputSizeImpl(~)
            % Return size for each output port
            out = [1,1];
        end
        
        function out = getOutputDataTypeImpl(~)
            % Return data type for each output port
            out = 'waveform';
        end
        
        function out = isOutputComplexImpl(~)
            % Return true for each output port with complex data
            out = false;
        end
        
        function icon = getIconImpl(~)
            % Return icon for the DES block. Passing empty string for no
            % title/icon.
            icon = sprintf('');
        end
    end
end