[3917] | 1 | % Mango 802.11 Reference Design |
---|
| 2 | % WLAN PHY Tx Init script |
---|
[5095] | 3 | % Copyright 2016 Mango Communications |
---|
[3917] | 4 | % Distributed under the Mango Research License: |
---|
| 5 | % http://mangocomm.com/802.11/license |
---|
| 6 | |
---|
[5095] | 7 | %clear |
---|
[2129] | 8 | addpath('./util'); |
---|
[2088] | 9 | addpath('./mcode_blocks'); |
---|
[5095] | 10 | addpath('./blackboxes'); |
---|
[2088] | 11 | |
---|
[3917] | 12 | %Define sane values for maximum parameter values; these maximums define |
---|
| 13 | % the bit widths of various signals throughout the design. Increasing |
---|
| 14 | % these maximum values will increae resource usage in hardware. |
---|
[2088] | 15 | MAX_NUM_BYTES = 4096; |
---|
| 16 | MAX_NUM_SC = 64; |
---|
| 17 | MAX_CP_LEN = 32; |
---|
| 18 | MAX_NUM_SAMPS = 50e3; |
---|
| 19 | MAX_NUM_SYMS = 600; |
---|
[5095] | 20 | MAX_DATA_BITS_PER_SYM_PERIOD = 2*260; %64-QAM 5/6 rate N_SS=2 |
---|
| 21 | MAX_NCBPS = 312; %Max coded bits per OFDM sym sets size of de-interleave RAM |
---|
[2088] | 22 | |
---|
[3917] | 23 | %% |
---|
| 24 | %Define a few interesting MPDU payloads. These byte sequences start with |
---|
| 25 | % the MAC header, followed by the MAC payload, followed by the FCS. The FCS |
---|
| 26 | % is calculated and inserted by the PHY automatically, so 4 zeros are defined |
---|
| 27 | % as placeholders in each byte sequence below. |
---|
[2088] | 28 | |
---|
[3917] | 29 | %Null data frame: |
---|
| 30 | % Frame Control field: 0x4811 |
---|
| 31 | % Duration: 0x2c00 (44 usec) |
---|
| 32 | % Receiver address: 40-d8-55-04-21-4a |
---|
| 33 | % Transmitter address: 40-d8-55-04-21-5a |
---|
| 34 | % Destination address: 40-d8-55-04-21-4a |
---|
| 35 | % Fragment/Seq Num field: 0xf092 |
---|
| 36 | % FCS placeholder: 0x00000000 |
---|
| 37 | MPDU_Null_Data = sscanf('48 11 2c 00 40 d8 55 04 21 4a 40 d8 55 04 21 5a 40 d8 55 04 21 4a f0 92 00 00 00 00', '%02x'); |
---|
[2088] | 38 | |
---|
[3922] | 39 | %Data frames: |
---|
[3917] | 40 | % Frame Control field: 0x0801 |
---|
| 41 | % Duration: 0x2c00 (44 usec) |
---|
| 42 | % Receiver address: 40-d8-55-04-21-4a |
---|
| 43 | % Transmitter address: 40-d8-55-04-21-5a |
---|
| 44 | % Destination address: 40-d8-55-04-21-6a |
---|
| 45 | % Fragment/Seq Num field: 0xb090 |
---|
| 46 | % LLC header: aa-aa-03-00-00-00-08-00 |
---|
| 47 | % Arbitrary payload: 00-01-02...0f |
---|
| 48 | % FCS placeholder: 0x00000000 |
---|
[2088] | 49 | |
---|
[3921] | 50 | %Short pkt - 16 payload bytes |
---|
| 51 | MPDU_Data_short = sscanf(['08 01 2c 00 40 d8 55 04 21 4a 40 d8 55 04 21 5a 40 d8 55 04 21 6a b0 90 aa aa 03 00 00 00 08 00 ' sprintf('%02x ', [0:15]) ' 00 00 00 00'], '%02x'); |
---|
| 52 | |
---|
[5095] | 53 | %Mid-size pkt - 150 payload bytes |
---|
[5186] | 54 | MPDU_Data_mid = sscanf(['08 01 2c 00 40 d8 55 04 21 4a 40 d8 55 04 21 5a 40 d8 55 04 21 6a b0 90 aa aa 03 00 00 00 08 00 ' sprintf('%02x ', mod([1:513], 256)) ' 00 00 00 00'], '%02x'); |
---|
[5095] | 55 | |
---|
[3921] | 56 | %Long pkt - 1420 payload bytes |
---|
[5186] | 57 | MPDU_Data_long = sscanf(['08 01 2c 00 40 d8 55 04 21 4a 40 d8 55 04 21 5a 40 d8 55 04 21 6a b0 90 aa aa 03 00 00 00 08 00 ' sprintf('%02x ', mod([1:1434], 256)) ' 00 00 00 00'], '%02x'); |
---|
[3921] | 58 | |
---|
[3917] | 59 | %ACK frame: |
---|
| 60 | % Frame Control field: 0xd400 |
---|
| 61 | % Duration: 0x0000 (0 usec) |
---|
| 62 | % Receiver address: 40-d8-55-04-21-4a |
---|
| 63 | % FCS placeholder: 0x00000000 |
---|
| 64 | ControlFrame_ACK = sscanf('d4 00 00 00 40 d8 55 04 21 4a 00 00 00 00', '%02x'); |
---|
[2088] | 65 | |
---|
[6325] | 66 | %CTS frame: |
---|
| 67 | % Frame Control field: 0xc400 |
---|
| 68 | % Duration: 0x01F4 (500 usec) |
---|
| 69 | % Receiver address: 40-d8-55-04-21-4a |
---|
| 70 | % FCS placeholder: 0x00000000 |
---|
| 71 | ControlFrame_CTS = sscanf('c4 00 F4 01 40 d8 55 04 21 4a 00 00 00 00', '%02x'); |
---|
| 72 | |
---|
[5095] | 73 | %100-Byte random payload with valid FCS, used with IEEE waveform generator |
---|
| 74 | %wgen_pyld = sscanf(['26 bd 8e b7 f4 13 e7 5c 31 c6 a4 5b ac 95 e9 5c 7c dc 42 10 6d 73 0f 0c 82 8e d9 b2 c8 48 f3 e2 75 fe 92 20 f4 74 f1 fa e0 ae cb 06 55 70 ed 63 1a 9b e7 6e 2b 61 7a df f4 fc b6 20 ba d1 09 8f 31 ea 8b de 1d 77 ce 78 c3 0b dd 25 d2 55 63 23 7c 31 cd 35 f5 75 1e 08 b2 2e 5b a4 67 3f 95 26 a3 54 37 cd'], '%02x'); |
---|
[2088] | 75 | |
---|
[5186] | 76 | ltg_pyld = sscanf('08 02 26 00 40 d8 55 04 24 f4 40 d8 55 04 24 b6 40 d8 55 04 24 b6 30 f1 aa aa 03 00 00 00 90 90 13 3f bc 02 00 00 00 00 79 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 96 6d 42 55', '%02x'); |
---|
| 77 | |
---|
[5095] | 78 | %Setup params for the sim |
---|
| 79 | % In hardware these params are set per packet by the MAC core/code |
---|
| 80 | % Bypass if running multiple sims via the gen_sim_waveforms script |
---|
| 81 | if(~exist('gen_waveform_mode', 'var')) |
---|
| 82 | tx_sim = struct(); |
---|
[6325] | 83 | tx_sim.MAC_payload = ControlFrame_CTS; |
---|
[5095] | 84 | tx_sim.payload_len = length(tx_sim.MAC_payload); |
---|
[6325] | 85 | tx_sim.PHY_mode = 1; %1=11a, 2=11n |
---|
| 86 | tx_sim.mcs = 0; |
---|
[5186] | 87 | tx_sim.samp_rate = 40; %Must be in [10 20 40] |
---|
[6325] | 88 | tx_sim.num_pkts = 1; |
---|
[5095] | 89 | end |
---|
[2088] | 90 | |
---|
[5095] | 91 | %MCS6, length=57, HTSIG should be: |
---|
| 92 | % 06 39 00 07 E0 00 (per IEEE waveform gen) |
---|
| 93 | % instead, current sim is: |
---|
| 94 | % 06 39 00 07 48 00 - clearly CRC calc is wrong for some MCS/Length values |
---|
[2088] | 95 | |
---|
[5095] | 96 | %Construct the initial value for the simulated packet buffer |
---|
| 97 | % This code is only for sim - CPU Low handles the packet buffer |
---|
| 98 | % init in the actual design |
---|
[2088] | 99 | |
---|
[5095] | 100 | %Tx packet buffer bytes (zero indexed): |
---|
| 101 | %11a Tx: |
---|
| 102 | % [ 0: 2] SIGNAL field |
---|
| 103 | % [ 3: 4] SERVICE field (always [0 0]) |
---|
| 104 | % [ 5:15] Reserved (ignored by Tx PHY logic) |
---|
| 105 | % [16: N] MAC payload |
---|
| 106 | % |
---|
| 107 | %11n Tx: |
---|
| 108 | % [ 0: 2] L-SIG field |
---|
| 109 | % [ 3: 8] HT-SIG |
---|
| 110 | % [ 9:10] SERVICE field (always [0 0]) |
---|
| 111 | % [11:15] Reserved (ignored by Tx PHY logic) |
---|
| 112 | % [16: N] MAC payload |
---|
[2088] | 113 | |
---|
[5095] | 114 | PPDU_bytes = zeros(1, MAX_NUM_BYTES); |
---|
[2088] | 115 | |
---|
[5095] | 116 | [SIGNAL, HTSIG] = calc_phy_preamble(tx_sim.PHY_mode, tx_sim.mcs, tx_sim.payload_len); |
---|
[3917] | 117 | |
---|
[5095] | 118 | if(tx_sim.PHY_mode == 1) |
---|
| 119 | PPDU_bytes(1:3) = SIGNAL; |
---|
[3917] | 120 | |
---|
[5095] | 121 | %Insert SERVICE field (always 0) |
---|
| 122 | PPDU_bytes(4:5) = [0 0]; |
---|
| 123 | |
---|
| 124 | %Reserved bytes |
---|
| 125 | PPDU_bytes(6:16) = zeros(1,11); |
---|
| 126 | else |
---|
| 127 | [SIGNAL, HTSIG] = calc_phy_preamble(2, tx_sim.mcs, tx_sim.payload_len); |
---|
| 128 | |
---|
| 129 | %11n mode - L-SIG contains rate=6Mbps, length corresponding to TX_TIME |
---|
| 130 | PPDU_bytes(1:3) = SIGNAL; |
---|
[3917] | 131 | |
---|
[5095] | 132 | %HT-SIG field |
---|
| 133 | PPDU_bytes(4:9) = HTSIG; |
---|
| 134 | |
---|
| 135 | %Insert SERVICE field (always 0) |
---|
| 136 | PPDU_bytes(10:11) = [0 0]; |
---|
| 137 | |
---|
| 138 | %Reserved bytes |
---|
| 139 | PPDU_bytes(12:16) = zeros(1, 5); |
---|
| 140 | end |
---|
[3917] | 141 | |
---|
[5095] | 142 | %Insert MAC payload - payload starts at byte index 16 |
---|
| 143 | PPDU_bytes(16 + (1:numel(tx_sim.MAC_payload))) = tx_sim.MAC_payload; |
---|
[5056] | 144 | |
---|
[5095] | 145 | %Reshape byte vector to u32 vector, necessary to initialize the 32-bit BRAM in the simulation |
---|
| 146 | PPDU_bytes4 = reshape(PPDU_bytes, 4, numel(PPDU_bytes)/4); |
---|
| 147 | PPDU_words = sum(PPDU_bytes4 .* repmat(2.^[0:8:24]', 1, size(PPDU_bytes4,2))); |
---|
[3917] | 148 | |
---|
| 149 | |
---|
| 150 | %Define the complex-valued sequence for the preamble ROMs |
---|
[5095] | 151 | PLCP_Preamble = PLCP_Preamble_gen; |
---|
[2088] | 152 | Preamble_IQ = PLCP_Preamble.Preamble_t; |
---|
| 153 | |
---|
[3917] | 154 | %% Register Init |
---|
| 155 | |
---|
| 156 | %Sane initial values for PHY config registers. These values will be overwritten |
---|
| 157 | % at run-time by the software in CPU Low |
---|
| 158 | PHY_CONFIG_NUM_SC = 64; |
---|
| 159 | PHY_CONFIG_CP_LEN = 16; |
---|
| 160 | PHY_CONFIG_FFT_SCALING = bin2dec('101010'); |
---|
[6259] | 161 | PHY_TX_ACTIVE_EXTENSION = 1; |
---|
[2115] | 162 | PHY_TX_RF_EN_EXTENSION = 50; |
---|
[5095] | 163 | PHY_TX_RXSIG_INVALID_EXTENSION = 120; |
---|
[2115] | 164 | |
---|
| 165 | REG_Tx_Timing = ... |
---|
| 166 | 2^0 * (PHY_TX_ACTIVE_EXTENSION) + ... %b[7:0] |
---|
[6259] | 167 | 2^10 * (PHY_TX_RF_EN_EXTENSION) + ... %b[15:8] |
---|
| 168 | 2^20 * (PHY_TX_RXSIG_INVALID_EXTENSION) + ... %b[23:16] |
---|
[2115] | 169 | 0; |
---|
| 170 | |
---|
[2088] | 171 | REG_TX_FFT_Config = ... |
---|
| 172 | 2^0 * (PHY_CONFIG_NUM_SC) +... %b[7:0] |
---|
| 173 | 2^8 * (PHY_CONFIG_CP_LEN) +... %b[15:8] |
---|
| 174 | 2^24 * (PHY_CONFIG_FFT_SCALING) + ... b[29:24] |
---|
| 175 | 0; |
---|
| 176 | |
---|
| 177 | REG_TX_Config = ... |
---|
[2369] | 178 | 2^0 * 1 + ... %Force RxEN to radio_controller |
---|
| 179 | 2^1 * 0 + ... %Reset scrambler per pkt |
---|
| 180 | 2^2 * 1 + ... %Enable Tx on RF A |
---|
| 181 | 2^3 * 0 + ... %Enable Tx on RF B |
---|
[2671] | 182 | 2^4 * 0 + ... %Enable Tx on RF C |
---|
| 183 | 2^5 * 0 + ... %Enable Tx on RF D |
---|
[3562] | 184 | 2^6 * 1 + ... %Use ant mask from MAC hw port |
---|
[5095] | 185 | 2^7 * 0 + ... %Use un-delayed TX_ACTIVE signal on debug port |
---|
| 186 | 2^12 * 1 + ... %PHY mode (1=11a, 2=11n), only used for software-initiated Tx |
---|
[2088] | 187 | 0; |
---|
| 188 | |
---|
[2835] | 189 | REG_TX_PKT_BUF_SEL = ... |
---|
| 190 | 2^0 * 0 + ... %b[3:0] pkt buf index |
---|
| 191 | 2^4 * 32 + ... %b[9:4] timestamp insert start byte |
---|
| 192 | 2^10 * 31 + ... %b[15:10] timestamp insert end byte |
---|
| 193 | 2^16 * 0 + ... %b[23:16] pkt buf address offset |
---|
| 194 | 0; |
---|
| 195 | |
---|
[5056] | 196 | REG_TX_Output_Scaling = (2.0 * 2^12) + (2^16 * 2.0 * 2^12); %UFix16_12 values |
---|
[2088] | 197 | |
---|
| 198 | |
---|
| 199 | %% Cyclic Redundancy Check parameters |
---|
[5095] | 200 | CRCPolynomial32 = hex2dec('04c11db7'); %CRC-32, for payload FCS |
---|
[2088] | 201 | CRC_Table32 = CRC_table_gen(CRCPolynomial32, 32); |
---|
[2143] | 202 | |
---|
[5095] | 203 | CRCPolynomial8 = hex2dec('07'); %CRC-8, for HT-SIG |
---|
| 204 | CRC_Table8 = CRC_table_gen(CRCPolynomial8, 8); |
---|
[2143] | 205 | |
---|
[5186] | 206 | %% |
---|
| 207 | %Load the MCS info table |
---|
| 208 | [mcs_rom_11ag, mcs_rom_11n] = tx_mcs_info_rom_init(); |
---|
| 209 | |
---|
| 210 | |
---|
| 211 | |
---|
[5095] | 212 | %% Constellation scaling |
---|
| 213 | |
---|
[4238] | 214 | %Common scaling for preamble and all constellations that keeps all points within |
---|
| 215 | % numeric range of Fix16_15 values at input to IFFT |
---|
| 216 | ALL_MOD_SCALING = ( 1.0 - (2^-15) )/(7/sqrt(42)); |
---|
| 217 | Preamble_IQ_scaled = ALL_MOD_SCALING * Preamble_IQ; |
---|
[2143] | 218 | |
---|
[4238] | 219 | Mod_Constellation_BPSK(1) = ALL_MOD_SCALING * -1; |
---|
| 220 | Mod_Constellation_BPSK(2) = ALL_MOD_SCALING * 1; |
---|
[2143] | 221 | |
---|
[4238] | 222 | Mod_Constellation_QPSK(1) = ALL_MOD_SCALING * -1/sqrt(2); |
---|
| 223 | Mod_Constellation_QPSK(2) = ALL_MOD_SCALING * 1/sqrt(2); |
---|
[2153] | 224 | |
---|
[4238] | 225 | Mod_Constellation_16QAM(1) = ALL_MOD_SCALING * -3/sqrt(10); |
---|
| 226 | Mod_Constellation_16QAM(2) = ALL_MOD_SCALING * -1/sqrt(10); |
---|
| 227 | Mod_Constellation_16QAM(3) = ALL_MOD_SCALING * 3/sqrt(10); |
---|
| 228 | Mod_Constellation_16QAM(4) = ALL_MOD_SCALING * 1/sqrt(10); |
---|
| 229 | |
---|
| 230 | Mod_Constellation_64QAM(1) = ALL_MOD_SCALING * -7/sqrt(42); |
---|
| 231 | Mod_Constellation_64QAM(2) = ALL_MOD_SCALING * -5/sqrt(42); |
---|
| 232 | Mod_Constellation_64QAM(3) = ALL_MOD_SCALING * -1/sqrt(42); |
---|
| 233 | Mod_Constellation_64QAM(4) = ALL_MOD_SCALING * -3/sqrt(42); |
---|
| 234 | Mod_Constellation_64QAM(5) = ALL_MOD_SCALING * 7/sqrt(42); |
---|
| 235 | Mod_Constellation_64QAM(6) = ALL_MOD_SCALING * 5/sqrt(42); |
---|
| 236 | Mod_Constellation_64QAM(7) = ALL_MOD_SCALING * 1/sqrt(42); |
---|
| 237 | Mod_Constellation_64QAM(8) = ALL_MOD_SCALING * 3/sqrt(42); |
---|
| 238 | |
---|
[5095] | 239 | |
---|
| 240 | %% HT preamble |
---|
| 241 | |
---|
| 242 | %Define the frequency domain 20MHz HT-STF (IEEE 802.11-2012 20.3.9.4.5) |
---|
| 243 | % Array indexes [0 ... 63] correspond to subcarriers [0 1 ... 31 -32 -31 ... -1] |
---|
| 244 | ht_stf_20_fd = zeros(1,64); |
---|
| 245 | ht_stf_20_fd(1:27) = [0 0 0 0 -1-1i 0 0 0 -1-1i 0 0 0 1+1i 0 0 0 1+1i 0 0 0 1+1i 0 0 0 1+1i 0 0]; |
---|
| 246 | ht_stf_20_fd(39:64) = [0 0 1+1i 0 0 0 -1-1i 0 0 0 1+1i 0 0 0 -1-1i 0 0 0 -1-1i 0 0 0 1+1i 0 0 0]; |
---|
| 247 | |
---|
| 248 | %Define the frequency domain 20MHz HT-LTF (IEEE 802.11-2012 20.3.9.4.6) |
---|
| 249 | % Array indexes [0 ... 63] correspond to subcarriers [0 1 ... 31 -32 -31 ... -1] |
---|
| 250 | ht_ltf_20_fd = [0 1 -1 -1 1 1 -1 1 -1 1 -1 -1 -1 -1 -1 1 1 -1 -1 1 -1 1 -1 1 1 1 1 -1 -1 0 0 0 0 0 0 0 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 1]; |
---|
| 251 | |
---|
| 252 | %Define init vector for HT preamble ROM |
---|
| 253 | % 20MHz HT-STF and HT-LTF are concatenated |
---|
[5186] | 254 | % FIXME: HT-STF scaling isn't quite right - it should be a bit bigger |
---|
| 255 | % Need to figure out best way to build that, given IFFT Fix16_15 input type |
---|
| 256 | ht_preamble_rom = [ht_stf_20_fd ALL_MOD_SCALING .* ht_ltf_20_fd]; |
---|
[5095] | 257 | |
---|
| 258 | %% Interleaver and subcarrier maps |
---|
| 259 | |
---|
| 260 | % Use util script to generate interleaver address mapping ROM contents |
---|
| 261 | wlan_tx_interleave_rom = wlan_tx_interleave_rom_gen(); |
---|
| 262 | |
---|
| 263 | %Initialize a vector defining the subcarrier map |
---|
| 264 | % This vector is used by the interleaver control logic to select which |
---|
| 265 | % subcarriers carry data symbols. A value of MAX_NUM_SC tells the hardware to |
---|
| 266 | % not use the subcarrier for data. |
---|
| 267 | sc_ind_data_11a = [2:7 9:21 23:27 39:43 45:57 59:64]; |
---|
| 268 | sc_data_sym_map_11a = MAX_NUM_SC*ones(1,MAX_NUM_SC); |
---|
| 269 | sc_data_sym_map_11a(sc_ind_data_11a) = 0:length(sc_ind_data_11a)-1; |
---|
| 270 | sc_data_sym_map_11a_bool = double(sc_data_sym_map_11a ~= MAX_NUM_SC); |
---|
| 271 | |
---|
| 272 | sc_ind_data_11n = [2:7 9:21 23:29 37:43 45:57 59:64]; |
---|
| 273 | sc_data_sym_map_11n = MAX_NUM_SC*ones(1,MAX_NUM_SC); |
---|
| 274 | sc_data_sym_map_11n(sc_ind_data_11n) = 0:length(sc_ind_data_11n)-1; |
---|
| 275 | sc_data_sym_map_11n_bool = double(sc_data_sym_map_11n ~= MAX_NUM_SC); |
---|
| 276 | |
---|