function idx = channelIndex(txIdx,rxIdx,varargin)
%channelIndex returns the index of a channel matrix in a multinode simulation
% IDX = channelIndex(TXIDX,RXIDX,NUMNODES) the index IDX to extract the
% channel between two nodes of interest. This assumes the channel matrix to
% extract from was generated with |generateChannels|.
%
% TXIDX is the transmitting node index (1-based).
%
% RXIDX is the transmitting node index (1-based).
%
% NUMNODES is the number of nodes in the simulation. This assumes all nodes
% can transmit and receive and channels between the nodes are reciprocal.
%
% IDX = channelIndex(TXIDX,RXIDX,NUMNODES) the index IDX to extract the
% channel between two nodes of interest in a simulation for downlink node
% links described by LINKMASK.
%
% LINKMASK is a NumTxNodes-by-NumRxNodes logical array were an element is
% true if a link between a transmitter and receiver is to be modeled and
% false otherwise. NumTxNodes is the number of transmitters and NumRxNodes
% is the number of receivers. This assumes that the transmitters and
% receivers are separate nodes and there are no reciprocal channels.
 
%   See also generateChannels.
 
%   Copyright 2019 The MathWorks, Inc.
 
%#codegen
 
if isscalar(varargin{1})
    numNodes = varargin{1};
    % Generate channels between all transmitters and receivers.
    % * Assume a transmitter and receiver are the same node,
    %   therefore do not generate a channel between a node and
    %   itself.
    % * Assume the channel is reciprocal between a transmitter
    %   and receiver therefore only generate channels in one
    %   direction.
    linkMask = triu(~eye(numNodes,numNodes));
    chanIndLUT = mappingTable(linkMask);
 
    % Assume all nodes can transmit and receive
    % Channel is reciprocal and channel has been generated for rxIdx being
    % always greater than txIdx.
    if txIdx>rxIdx
        rxIdxUse = txIdx;
        txIdxUse = rxIdx;
    else
        rxIdxUse = rxIdx;
        txIdxUse = txIdx;
    end
else
    linkMask = logical(varargin{1}); % Force to logical
    chanIndLUT = mappingTable(linkMask);
 
    % Assume transmitting nodes are different to receiving nodes
    rxIdxUse = rxIdx;
    txIdxUse = txIdx;
end
idx = chanIndLUT(txIdxUse,rxIdxUse);
    
end
 
function chanIndLUT = mappingTable(linkMask)
    % Map requested channel between a pair of nodes (tx,rx) to a channel
    numChannels = sum(linkMask,'all');
    chanIndLUT = zeros(size(linkMask,1),size(linkMask,2));
    chanIndLUT(linkMask) = 1:numChannels;
end

