function [portH, datastoreH] = addDSM(modelH, dsName, idx, posConsts, isReadFrom, isWrittenTo)
%

% Copyright 2005-2016 The MathWorks, Inc.

% If the given DSM 'dsName'
%  - is written to but is not read from: insert DSR block and Outport
%    (New behavior from 17a. See g1438610)
%  - is not written to but is read from: insert Inport and DSW block
%    (Continuing the old behavior)
%  - is written to and is read from: insert Inport and DSW block
%    (Continuing the old behavior. But will revisit for 17b. See g949938)

    colTotal = 1;
    rowIdx = ceil(idx/colTotal);
    colIdx = idx - ((rowIdx-1)*colTotal);

    rowSep = 90;
    origin = [15 posConsts.Bottom+40+rowSep*(rowIdx-1)];
    offset = origin(1) + (posConsts.PrtWidth + posConsts.DsWidth + 2*posConsts.PrtDsDelta)*(colIdx-1);

    modelName = get_param(modelH, 'Name');
    portPath = [modelName '/' dsName];
    portPath = Sldv.SubSystemExtract.findUniquePath(portPath);

    if isWrittenTo && ~isReadFrom   % g1438610
        drwPath = [modelName '/dr_' dsName];
    else
        drwPath = [modelName '/dw_' dsName];
    end
    drwPath = Sldv.SubSystemExtract.findUniquePath(drwPath);

    if isWrittenTo && ~isReadFrom   % g1438610
        % Add DSR block and Outport

        left = offset;
        right = left + posConsts.DsWidth;
        top = origin(2) + (posConsts.DsHeight/2);
        bottom = origin(2) - (posConsts.DsHeight/2);
        drPos = ceil([left bottom right top]);

        left = offset + posConsts.DsWidth + posConsts.PrtDsDelta;
        right = left + posConsts.PrtWidth;
        top = origin(2) + (posConsts.PrtHeight/2);
        bottom = origin(2) - (posConsts.PrtHeight/2);
        prtPos = ceil([left bottom right top]);

        % Add DSR block
        add_block('built-in/DataStoreRead', drwPath, 'Position', vparam(drPos));
        datastoreH = get_param(drwPath, 'Handle');
        set_param(datastoreH, 'dataStoreName', dsName);

        % Add Outport
        add_block('built-in/Outport', portPath, 'Position', vparam(prtPos));
        portH = get_param(portPath, 'Handle');

        % Wire the two together
        srcPorts = get_param(datastoreH, 'PortHandles');
        destPorts = get_param(portH, 'PortHandles');
        add_line(modelH, srcPorts.Outport(1), destPorts.Inport(1), 'autorouting', 'on');
    else
        % Add Inport and DSW block

        left = offset;
        right = left + posConsts.PrtWidth;
        top = origin(2) + (posConsts.PrtHeight/2);
        bottom = origin(2) - (posConsts.PrtHeight/2);
        prtPos = ceil([left bottom right top]);

        left = offset + posConsts.PrtWidth + posConsts.PrtDsDelta;
        right = left + posConsts.DsWidth;
        top = origin(2) + (posConsts.DsHeight/2);
        bottom = origin(2) - (posConsts.DsHeight/2);
        dwPos = ceil([left bottom right top]);

        % Add Inport
        add_block('built-in/Inport', portPath, 'Position', vparam(prtPos));
        portH = get_param(portPath, 'Handle');

        % Add DSW block
        add_block('built-in/DataStoreWrite', drwPath, 'Position', vparam(dwPos));
        datastoreH = get_param(drwPath, 'Handle');
        set_param(datastoreH, 'dataStoreName', dsName);

        % Wire the two together
        srcPorts = get_param(portH, 'PortHandles');
        destPorts = get_param(datastoreH, 'PortHandles');
        add_line(modelH, srcPorts.Outport(1), destPorts.Inport(1), 'autorouting','on');
    end
end

function str = vparam(in)
    str = ['[' num2str(in) ']'];
end
% LocalWords:  dw
