function ind = ehtRUSubcarrierIndices(chanBW,varargin)
%ehtRUSubcarrierIndices RU subcarrier indices as per IEEE P802.11be/D1.0, Section 36.3.2.1
% 
%   IND = ehtRUSubcarrierIndices(CHANBW,RUSIZE) returns a matrix containing
%   the indices for all RUs. Each column contains the indices for an RU.
%
%   CHANBW is the channel bandwidth and must be 20, 40, 80, 160, or 320.
%
%   RUSIZE is the RU size in subcarriers and must be one of 26, 52, 106,
%   242, 484, 996, 2*996, or 4*996.
%
%   IND = ehtRUSubcarrierIndices(CHANBW) returns a matrix containing the
%   indices for all RUs assuming a full bandwidth allocation.
%
%   IND = ehtRUSubcarrierIndices(CHANBW,RUSIZE,RUINDEX) optionally returns
%   the indices for only the RU specified by RUINDEX. When RUSIZE and
%   RUINDEX are vectors IND is the subcarriers for all RUs.

%   Copyright 2020-2021 The MathWorks, Inc.

if nargin>1
    ruSize = varargin{1};
else
    ruSize = wlan.internal.heFullBandRUSize(chanBW);
    ind = singleRUInd(chanBW,ruSize);
    return
end

if isscalar(ruSize)
    ind = singleRUInd(chanBW,ruSize,varargin{2:end});
else
    ruIndex = varargin{2}; % Expect RU index when vector of RU sizes
    ind = zeros(0,1);
    for mru = 1:numel(ruSize)
        ind = [ind; singleRUInd(chanBW,ruSize(mru),ruIndex(mru))]; %#ok<AGROW> 
    end
end
end

function ind = singleRUInd(chanBW,ruSize,varargin)
    % IEEE P802.11ax/D4.1, Table 27-7/8/9 - Subcarrier indices for RUs in a 20/40/80 MHz HE PPDU
    switch chanBW
        case {20,40}
            ruSizeInd = wlan.internal.heRUSubcarrierIndices(chanBW,ruSize);
        case 80
            ruSizeInd = cbw80Size(ruSize);
        case 160
           ruSizeInd = cbw160Size(ruSize);
        otherwise
           assert(chanBW==320)
           ruSizeInd = cbw320Size(ruSize);
    end
    if nargin>2
        % Return indices for RU index of interest
        ruIndex = varargin{1};
        ind = ruSizeInd(:,ruIndex);
    else
        % Return indices for all RU indices
        ind = ruSizeInd;
    end
end

function ruSizeInd = cbw80Size(ruSize)
% IEEE P802.11be/D1.0, Table 36-5
    switch ruSize
        case 26
            ruSizeInd = [(-499:-474).' (-473:-448).' (-445:-420).' (-419:-394).' (-392:-367).' (-365:-340).' (-339:-314).' (-311:-286).' (-285:-260).' ...
                (-252:-227).' (-226:-201).' (-198:-173).' (-172:-147).' (-145:-120).' (-118:-93).' (-92:-67).' (-64:-39).' (-38:-13).' ...
                nan(26,1) ... % RU 19 [not defined]
                (13:38).' (39:64).' (67:92).' (93:118).' (120:145).' (147:172).' (173:198).' (201:226).' (227:252).' ...
                (260:285).' (286:311).' (314:339).' (340:365).' (367:392).' (394:419).' (420:445).' (448:473).' (474:499).'];
        case 52
            ruSizeInd = [(-499:-448).' (-445:-394).' (-365:-314).' (-311:-260).' (-252:-201).' (-198:-147).' (-118:-67).' (-64:-13).' ...
                (13:64).' (67:118).' (147:198).' (201:252).' (260:311).' (314:365).' (394:445).' (448:499).'];
        case 106
            ruSizeInd = [(-499:-394).' (-365:-260).' (-252:-147).' (-118:-13).' ...
                (13:118).' (147:252).' (260:365).' (394:499).'];
        case 242
            ruSizeInd = [(-500:-259).' (-253:-12).' (12:253).' (259:500).'];
        case 484
            ruSizeInd = [[-500:-259 -253:-12].' [12:253 259:500].'];
        otherwise % 996
            ruSizeInd = [-500:-3 3:500].';
    end
end

function ruSizeInd = cbw160Size(ruSize)
% IEEE P802.11be/D1.0, Table 36-6
    switch ruSize
        case 26
            ruSizeInd = [(-1011:-986).' (-985:-960).' (-957:-932).' (-931:-906).' (-904:-879).' (-877:-852).' (-851:-826).' (-823:-798).' (-797:-772).' ...
                (-764:-739).' (-738:-713).' (-710:-685).' (-684:-659).' (-657:-632).' (-630:-605).' (-604:-579).' (-576:-551).' (-550:-525).' ...
                nan(26,1) ... % RU 19 [not defined]
                (-499:-474).' (-473:-448).' (-445:-420).' (-419:-394).' (-392:-367).' (-365:-340).' (-339:-314).' (-311:-286).' (-285:-260).' ...
                (-252:-227).' (-226:-201).' (-198:-173).' (-172:-147).' (-145:-120).' (-118:-93).' (-92:-67).' (-64:-39).' (-38:-13).' ...
                (13:38).' (39:64).' (67:92).' (93:118).' (120:145).' (147:172).' (173:198).' (201:226).' (227:252).' ...
                (260:285).' (286:311).' (314:339).' (340:365).' (367:392).' (394:419).' (420:445).' (448:473).' (474:499).' ...
                nan(26,1) ... % RU 56 [not defined]
                (525:550).' (551:576).' (579:604).' (605:630).' (632:657).' (659:684).' (685:710).' (713:738).' (739:764).' ...
                (772:797).' (798:823).' (826:851).' (852:877).' (879:904).' (906:931).' (932:957).' (960:985).' (986:1011).'];
        case 52
            ruSizeInd = [(-1011:-960).' (-957:-906).' (-877:-826).' (-823:-772).' ...
                (-764:-713).' (-710:-659).' (-630:-579).' (-576:-525).' ...
                (-499:-448).' (-445:-394).' (-365:-314).' (-311:-260).' ...
                (-252:-201).' (-198:-147).' (-118:-67).' (-64:-13).' ...
                (13:64).' (67:118).' (147:198).' (201:252).' ...
                (260:311).' (314:365).' (394:445).' (448:499).' ...
                (525:576).' (579:630).' (659:710).' (713:764).' ...
                (772:823).' (826:877).' (906:957).' (960:1011).'];
        case 106
            ruSizeInd = [(-1011:-906).' (-877:-772).' (-764:-659).' (-630:-525).' ...
                (-499:-394).' (-365:-260).' (-252:-147).' (-118:-13).' ...
                (13:118).' (147:252).' (260:365).' (394:499).' ...
                (525:630).' (659:764).' (772:877).' (906:1011).'];
        case 242
            ruSizeInd = [(-1012:-771).' (-765:-524).' (-500:-259).' (-253:-12).' (12:253).' (259:500).' (524:765).' (771:1012).'];
        case 484
            ruSizeInd = [[-1012:-771 -765:-524].' [-500:-259 -253:-12].' [12:253 259:500].' [524:765 771:1012].'];
        case 996
            ruSizeInd = [[-1012:-515 -509:-12].' [12:509 515:1012].'];
        otherwise % 2x996
            ruSizeInd = [-1012:-515 -509:-12 12:509 515:1012].';
    end
end

function ruSizeInd = cbw320Size(ruSize)
% IEEE P802.11be/D1.0, Table 36-7
    switch ruSize
        case 26
            ruSizeInd = [(-2035:-2010).' (-2009:-1984).' (-1981:-1956).' (-1955:-1930).' (-1928:-1903).' ...
                (-1901:-1876).' (-1875:-1850).' (-1847:-1822).' (-1821:-1796).' ...
                (-1788:-1763).' (-1762:-1737).' (-1734:-1709).' (-1708:-1683).' (-1681:-1656).' ... 
                (-1654:-1629).' (-1628:-1603).' (-1600:-1575).' (-1574:-1549).' ...
                nan(26,1) ... % RU 19 [not defined]
                (-1523:-1498).' (-1497:-1472).' (-1469:-1444).' (-1443:-1418).' (-1416:-1391).' ... 
                (-1389:-1364).' (-1363:-1338).' (-1335:-1310).' (-1309:-1284).' ...
                (-1276:-1251).' (-1250:-1225).' (-1222:-1197).' (-1196:-1171).' (-1169:-1144).' ... 
                (-1142:-1117).' (-1116:-1091).' (-1088:-1063).' (-1062:-1037).' ...
                (-1011:-986).' (-985:-960).' (-957:-932).' (-931:-906).' (-904:-879).' ... 
                (-877:-852).' (-851:-826).' (-823:-798).' (-797:-772).' ...
                (-764:-739).' (-738:-713).' (-710:-685).' (-684:-659).' (-657:-632).' ...
                (-630:-605).' (-604:-579).' (-576:-551).' (-550:-525).' ...
                nan(26,1) ... % RU 56 [not defined]
                (-499:-474).' (-473:-448).' (-445:-420).' (-419:-394).' (-392:-367).' ...
                (-365:-340).' (-339:-314).' (-311:-286).' (-285:-260).' ...
                (-252:-227).' (-226:-201).' (-198:-173).' (-172:-147).' (-145:-120).' ...
                (-118:-93).' (-92:-67).' (-64:-39).' (-38:-13).' ...
                (13:38).' (39:64).' (67:92).' (93:118).' (120:145).' ...
                (147:172).' (173:198).' (201:226).' (227:252).' ...
                (260:285).' (286:311).' (314:339).' (340:365).' (367:392).' ...
                (394:419).' (420:445).' (448:473).' (474:499).' ...
                nan(26,1) ... % RU 93 [not defined]
                (525:550).' (551:576).' (579:604).' (605:630).' (632:657).' ...
                (659:684).' (685:710).' (713:738).' (739:764).' ...
                (772:797).' (798:823).' (826:851).' (852:877).' (879:904).' ...
                (906:931).' (932:957).' (960:985).' (986:1011).' ...
                (1037:1062).' (1063:1088).' (1091:1116).' (1117:1142).' (1144:1169).' ...
                (1171:1196).' (1197:1222).' (1225:1250).' (1251:1276).' ...
                (1284:1309).' (1310:1335).' (1338:1363).' (1364:1389).' (1391:1416).' ...
                (1418:1443).' (1444:1469).' (1472:1497).' (1498:1523).' ...
                nan(26,1) ... % RU 130 [not defined]
                (1549:1574).' (1575:1600).' (1603:1628).' (1629:1654).' (1656:1681).' ...
                (1683:1708).' (1709:1734).' (1737:1762).' (1763:1788).' ...
                (1796:1821).' (1822:1847).' (1850:1875).' (1876:1901).' (1903:1928).' ...
                (1930:1955).' (1956:1981).' (1984:2009).' (2010:2035).'];
        case 52
            ruSizeInd = [(-2035:-1984).' (-1981:-1930).' (-1901:-1850).' (-1847:-1796).' ...
                (-1788:-1737).' (-1734:-1683).' (-1654:-1603).' (-1600:-1549).' ...
                (-1523:-1472).' (-1469:-1418).' (-1389:-1338).' (-1335:-1284).' ...
                (-1276:-1225).' (-1222:-1171).' (-1142:-1091).' (-1088:-1037).' ...
                (-1011:-960).' (-957:-906).' (-877:-826).' (-823:-772).' ...               
                (-764:-713).' (-710:-659).' (-630:-579).' (-576:-525).' ...
                (-499:-448).' (-445:-394).' (-365:-314).' (-311:-260).' ...
                (-252:-201).' (-198:-147).' (-118:-67).' (-64:-13).' ...
                (13:64).' (67:118).' (147:198).' (201:252).' ...
                (260:311).' (314:365).' (394:445).' (448:499).' ...
                (525:576).' (579:630).' (659:710).' (713:764).' ...
                (772:823).' (826:877).' (906:957).' (960:1011).' ...
                (1037:1088).' (1091:1142).' (1171:1222).' (1225:1276).' ...
                (1284:1335).' (1338:1389).' (1418:1469).' (1472:1523).' ...
                (1549:1600).' (1603:1654).' (1683:1734).' (1737:1788).' ...
                (1796:1847).' (1850:1901).' (1930:1981).' (1984:2035).'];
        case 106
            ruSizeInd = [(-2035:-1930).' (-1901:-1796).' (-1788:-1683).' (-1654:-1549).' ...
                (-1523:-1418).' (-1389:-1284).' (-1276:-1171).' (-1142:-1037).' ...
                (-1011:-906).' (-877:-772).' (-764:-659).' (-630:-525).' ...
                (-499:-394).' (-365:-260).' (-252:-147).' (-118:-13).' ...
                (13:118).' (147:252).' (260:365).' (394:499).' ...
                (525:630).' (659:764).' (772:877).' (906:1011).' ...
                (1037:1142).' (1171:1276).' (1284:1389).' (1418:1523).' ...
                (1549:1654).' (1683:1788).' (1796:1901).' (1930:2035).'];
        case 242
            ruSizeInd = [(-2036:-1795).' (-1789:-1548).' (-1524:-1283).' (-1277:-1036).' ...
                (-1012:-771).' (-765:-524).' (-500:-259).' (-253:-12).' ...
                (12:253).' (259:500).' (524:765).' (771:1012).' ...
                (1036:1277).' (1283:1524).' (1548:1789).' (1795:2036).'];
        case 484
            ruSizeInd = [[-2036:-1795 -1789:-1548].' [-1524:-1283 -1277:-1036].' [-1012:-771 -765:-524].' [-500:-259 -253:-12].' ...
                [12:253 259:500].' [524:765 771:1012].' [1036:1277 1283:1524].' [1548:1789 1795:2036].'];
        case 996
            ruSizeInd = [[-2036:-1539 -1533:-1036].' [-1012:-515 -509:-12].' [12:509 515:1012].' [1036:1533 1539:2036].'];
        case 2*996
            ruSizeInd = [[-2036:-1539 -1533:-1036 -1012:-515 -509:-12].' [12:509 515:1012 1036:1533 1539:2036].'];
        otherwise % 4x996
            ruSizeInd = [-2036:-1539 -1533:-1036 -1012:-515 -509:-12 12:509 515:1012 1036:1533 1539:2036].';
    end
end