forked from brian09088/NB-IoT-support-for-NTN
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHelperSetupNTNChannel.m
390 lines (371 loc) · 20.4 KB
/
HelperSetupNTNChannel.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
function ntnChan = HelperSetupNTNChannel(chanParams)
%HelperSetupNTNChannel Set up NTN channel
%
% Note: This is a helper and its API and/or functionality may change
% in subsequent releases.
%
% NTNCHAN = HelperSetupNTNChannel(CHANPARAMS) sets up the New Radio
% (NR) non-terrestrial network (NTN) narrowband or tapped delay line
% (TDL) channel, as mentioned in TR 38.811, given the set of channel
% parameters CHANPARAMS. NTNCHAN is a structure consisting of building
% blocks of NTN channel.
%
% NTNCHAN is an output structure with fields:
% ChannelName - Name of the NTN channel.
% BaseChannel - Base channel model to generate the path gains
% due to mobile movement. It is either
% p681LMSChannel or nrTDLChannel System
% object.
% ChannelFilter - Filter signal using multipath gains at
% specified path delays using this
% comm.ChannelFilter System object.
% SatelliteDopplerShift - Doppler shift due to satellite movement.
% MobileDopplerSpread - Maximum Doppler shift due to mobile or UE
% movement.
%
% CHANPARAMS is an input structure with the fields:
%
% NTNChannelType - Type of NTN channel ("Narrowband", "TDL")
% CarrierFrequency - Carrier frequency of input signal (Hz)
% ElevationAngle - Elevation angle (degrees)
% SatelliteSpeed - Relative speed of satellite with respect to earth (m/s)
% SatelliteAltitude - Satellite altitude from the surface of earth (m)
% MobileSpeed - Speed of mobile terminal (m/s)
% SampleRate - Optional. Input signal sample rate (Hz)
% (default 30.72e6 for TDL, 7.68e6 for narrowband)
% OutputDataType - Optional. Data type of channel output
% ("double" (default), "single")
%
% Specify the following fields when NTNChannelType is set to
% "Narrowband". For more information of the optional fields, look at the
% help of <a href="matlab:help p681LMSChannel">p681LMSChannel</a>.
% AzimuthOrientation - Azimuth orientation (degrees)
% Environment - Type of propagation environment ("Urban",
% "Suburban", "RuralWooded", "Village", "Train",
% "Residential", "Highway", "Rural", "Custom")
% StateDistribution - Optional. Parameters of state distribution (dB)
% (default [3.0639 2.9108; 1.6980 1.2602])
% MinStateDuration - Optional. Minimum duration of each state (m)
% (default [10 6])
% DirectPathDistribution - Optional. Parameters of direct path amplitude
% distribution (dB)
% (default [-1.8225 -15.4844; 1.1317 3.3245])
% MultipathPowerCoefficients - Optional. Coefficients to calculate multipath
% power (default [-0.0481 0.9434; -14.7450 -1.7555])
% StandardDeviationCoefficients - Optional. Coefficients to compute standard
% deviation of direct path amplitude
% (default [-0.4643 -0.0798; 0.3334 2.8101])
% DirectPathCorrelationDistance - Optional. Direct path amplitude correlation
% distance (m) (default [1.7910 1.7910])
% TransitionLengthCoefficients - Optional. Coefficients to compute transition
% length (default [0.0744; 2.1423])
% StateProbabilityRange - Optional. Minimum and maximum probability of
% each state (default [0.05 0.1; 0.95 0.9])
% ChannelFiltering - Optional. Perform filtering of input signal
% (true (default), false)
% NumSamples - Optional. Number of time samples (default 7680)
% FadingTechnique - Optional. Channel model fading technique
% ("Filtered Gaussian noise" (default),
% "Sum of sinusoids")
% NumSinusoids - Optional. Number of sinusoids (default 48)
% RandomStream - Optional. Source of random number stream
% ("Global stream" (default), "mt19937ar with seed")
% Seed - Optional. Initial seed of mt19937ar random
% number stream generator (default 73)
%
% Specify the following fields when NTNChannelType is set to "TDL". For
% more information of the optional fields, look at the help of <a
% href="matlab:help nrTDLChannel">nrTDLChannel</a>.
% DelayProfile - NTN TDL delay profile ("NTN-TDL-A",
% "NTN-TDL-B", "NTN-TDL-C", "NTN-TDL-D", "Custom")
% PathDelays - Optional. Discrete path delay vector (s)
% (default 0)
% AveragePathGains - Optional. Average path gain vector (dB)
% (default 0)
% FadingDistribution - Optional. Rayleigh or Rician fading
% ("Rayleigh" (default), "Rician")
% KFactorFirstTap - Optional. K-factor of first tap (dB)
% (default 13.3 dB)
% DelaySpread - Optional. Desired delay spread (s)
% (default 30 ns)
% KFactorScaling - Optional. Enable K-factor scaling (logical)
% (default false)
% KFactor - Optional. Desired Rician K-factor (dB)
% (default 10.224)
% MIMOCorrelation - Optional. Correlation between UE and BS antennas
% ("Low" (default), "Medium", "Medium-A",
% "UplinkMedium", "High", "Custom")
% Polarization - Optional. Antenna polarization arrangement
% ("Co-Polar" (default), "Cross-Polar",
% "Custom")
% TransmissionDirection - Optional. Transmission direction (Uplink/Downlink)
% (default "Downlink")
% NumTransmitAntennas - Optional. Number of transmit antennas (default 1)
% NumReceiveAntennas - Optional. Number of receive antennas (default 2)
% TransmitCorrelationMatrix - Optional. Transmit spatial correlation
% matrix (or 3-D array) (default 1)
% ReceiveCorrelationMatrix - Optional. Receive spatial correlation
% matrix (or 3-D array) (default [1 0; 0 1])
% TransmitPolarizationAngles - Optional. Transmit polarization slant
% angles in degrees (default [45 -45])
% ReceivePolarizationAngles - Optional. Receive polarization slant
% angles in degrees (default [90 0])
% XPR - Optional. Cross polarization power ratio
% (dB) (default 10)
% SpatialCorrelationMatrix - Optional. Combined correlation matrix
% (or 3-D array) (default [1 0; 0 1])
% NormalizePathGains - Optional. Normalize path gains (logical)
% (default true)
% InitialTime - Optional. Start time of fading process (s)
% (default 0)
% NormalizeChannelOutputs - Optional. Normalize channel outputs by
% number of receive antennas (logical) (default true)
% NumTimeSamples - Optional. Number of time samples (default 30720)
% NumSinusoids - Optional. Number of sinusoids (default 48)
% RandomStream - Optional. Source of random number stream
% ("Global stream", "mt19937ar with seed" (default))
% Seed - Optional. Initial seed of mt19937ar random
% number stream generator (default 73)
%
% Note that the maximum Doppler shift caused by the movement of both
% mobile and satellite, must be less than one-tenth of SampleRate.
%
% % Example:
% % Setup the NTN narrowband channel for an urban environment. Consider a
% % LEO satellite operating in Ka-band at an altitude of 1500 km and
% % speed of 7.1172 km/s. Assume a static UE and elevation angle of
% % 50 degrees.
%
% chanParams = struct;
% chanParams.NTNChannelType = "Narrowband";
% chanParams.Environment = "Urban";
% chanParams.CarrierFrequency = 20e9; % In Hz
% chanParams.ElevationAngle = 50; % In degrees
% chanParams.SatelliteSpeed = 7117.2; % In m/s
% chanParams.SatelliteAltitude = 1500000; % In m
% chanParams.MobileSpeed = 0; % In m/s
% chanParams.AzimuthOrientation = 0; % In degrees
%
% ntnNarrowbandChan = HelperSetupNTNChannel(chanParams);
%
% See also HelperGenerateNTNChannel, nrTDLChannel, p681LMSChannel,
% comm.ChannelFilter.
% Copyright 2021-2023 The MathWorks, Inc.
% Check the mandatory fields
chanParams = validateMandatoryFields(chanParams);
% Assign temporary variables for carrier frequency and maximum Doppler
% shift due to mobile movement
fc = double(chanParams.CarrierFrequency);
maxDoppler = (double(chanParams.MobileSpeed)*fc)/physconst('LightSpeed');
if strcmpi(chanParams.NTNChannelType,'TDL')
% Construct nrTDLChannel
baseChan = nrTDLChannel;
baseChan = passign(chanParams,baseChan,{'DelaySpread'}, ...
~strcmp(chanParams.DelayProfile,'Custom'));
baseChan.DelayProfile = 'Custom';
baseChan = passign(chanParams,baseChan,{'FadingDistribution'}, ...
strcmp(chanParams.DelayProfile,'Custom'));
% Get the delay-profiles of the NTN channel and assign them to
% nrTDLChannel properties
hasLOSPath = (any(strcmpi(chanParams.DelayProfile,{'NTN-TDL-C','NTN-TDL-D'}))) ...
|| (strcmpi(baseChan.FadingDistribution,'Rician'));
if strcmpi(chanParams.DelayProfile,'Custom')
baseChan = passign(chanParams,baseChan,{'PathDelays'});
baseChan = passign(chanParams,baseChan,{'AveragePathGains'});
baseChan = passign(chanParams,baseChan,{'KFactorFirstTap'},hasLOSPath);
else
desiredKFactor = NaN;
if hasLOSPath
% Update to a LOS channel, to check the values of
% KFactorScaling and KFactor properties
baseChan.DelayProfile = 'TDL-D';
baseChan = passign(chanParams,baseChan,{'KFactorScaling'});
baseChan = passign(chanParams,baseChan,{'KFactor'}, ...
baseChan.KFactorScaling);
if baseChan.KFactorScaling
desiredKFactor = double(baseChan.KFactor);
else
desiredKFactor = NaN;
end
% Update to Custom profile
baseChan.DelayProfile = 'Custom';
end
switch lower(chanParams.DelayProfile)
case 'ntn-tdl-a'
pdp = [0 0; ...
1.0811 -4.675; ...
2.8416 -6.482];
case 'ntn-tdl-b'
pdp = [0 0; ...
0.7249 -1.973; ...
0.7410 -4.332; ...
5.7392 -11.914];
case 'ntn-tdl-c'
pdp = [0 -0.394; ...
0 -10.618; ...
14.8124 -23.373];
otherwise
pdp = [0 -0.284; ...
0 -11.991; ...
0.5596 -9.887; ...
7.3340 -16.771];
end
% Perform delay and K-factor scaling
pdp = double(wireless.internal.channelmodels.scaleDelaysAndKFactor( ...
pdp,desiredKFactor,baseChan.DelaySpread));
pathDelays = pdp(:,1).'; % 1st column is delay
pathGains = pdp(:,2).'; % 2nd column is power
if hasLOSPath
% Remove 2nd entry of delay profile, corresponding to the
% Rayleigh part of the Rician path. The Rician path is now
% captured through first entry of path gains and the
% K-factor of first tap
baseChan.FadingDistribution = 'Rician';
baseChan.KFactorFirstTap = pathGains(1) - pathGains(2);
pathGainsOut = [10*log10(sum(10.^(pathGains(1:2)/10))) pathGains(3:end)];
pathDelaysOut = pathDelays([1 3:end]);
else
baseChan.FadingDistribution = 'Rayleigh';
pathGainsOut = pathGains;
pathDelaysOut = pathDelays;
end
baseChan.PathDelays = pathDelaysOut;
baseChan.AveragePathGains = pathGainsOut;
end
% Assign other properties of nrTDLChannel
baseChan.ChannelFiltering = false; % Set ChannelFiltering to false
baseChan = passign(chanParams,baseChan,{'OutputDataType'});
baseChan.MaximumDopplerShift = maxDoppler;
[baseChan,mimoFlag] = passign(chanParams,baseChan,{'MIMOCorrelation'});
customMIMOProfile = mimoFlag && strcmp(chanParams.MIMOCorrelation,'Custom');
[baseChan,polarizationFlag] = passign(chanParams,baseChan,{'Polarization'});
customPolarization = polarizationFlag && strcmp(chanParams.Polarization,'Custom');
customMIMOAndCrossPolar = ...
customMIMOProfile && strcmp(baseChan.Polarization,'Cross-Polar');
inFieldNames = {'TransmissionDirection', 'NumReceiveAntennas', ...
'NumTransmitAntennas', 'TransmitCorrelationMatrix', 'ReceiveCorrelationMatrix', ...
'TransmitPolarizationAngles', 'ReceivePolarizationAngles', 'XPR', ...
'SpatialCorrelationMatrix', 'NormalizePathGains', 'NumSinusoids', ...
'InitialTime', 'RandomStream', 'NormalizeChannelOutputs', ...
'NumTimeSamples', 'SampleRate'};
acCond = [repmat(~customMIMOProfile,1,2) ~(customMIMOProfile && ~customPolarization) ...
repmat(~(~customMIMOProfile || customPolarization),1,2) ...
repmat(customMIMOAndCrossPolar,1,3) (customMIMOProfile && customPolarization) ...
ones(1,7)];
baseChan = passign(chanParams,baseChan,inFieldNames,acCond);
baseChan = passign(chanParams,baseChan,{'Seed'}, ...
strcmp(baseChan.RandomStream,'mt19937ar with seed'));
pathDelays = baseChan.PathDelays;
chanName = "NTN TDL with " + chanParams.DelayProfile + " delay profile";
else
% Construct p681LMSChannel
baseChan = p681LMSChannel;
baseChan.CarrierFrequency = chanParams.CarrierFrequency;
baseChan.MobileSpeed = chanParams.MobileSpeed;
baseChan.ElevationAngle = chanParams.ElevationAngle;
baseChan.AzimuthOrientation = chanParams.AzimuthOrientation;
baseChan.Environment = chanParams.Environment;
% Parse the optional fields
baseChan.ChannelFiltering = false; % Set ChannelFiltering to false
baseChan = passign(chanParams,baseChan,{'OutputDataType'});
inFieldNames = {'StateDistribution', 'MinStateDuration', ...
'DirectPathDistribution', 'MultipathPowerCoefficients', ...
'StandardDeviationCoefficients', 'DirectPathCorrelationDistance', ...
'TransitionLengthCoefficients', 'StateProbabilityRange', 'NumSamples', ...
'FadingTechnique', 'RandomStream', 'SampleRate', 'InitialState'};
customEnvi = strcmpi(baseChan.Environment,'Custom');
acCheck = [repmat(customEnvi,1,8) ones(1,5)];
baseChan = passign(chanParams,baseChan,inFieldNames,acCheck);
baseChan = passign(chanParams,baseChan,{'NumSinusoids'}, ...
strcmpi(baseChan.FadingTechnique,'sum of sinusoids'));
baseChan = passign(chanParams,baseChan,{'Seed'}, ...
strcmpi(baseChan.RandomStream,'mt19937ar with seed'));
pathDelays = 0;
chanName = "NTN narrowband with " + baseChan.Environment + " environment";
end
% Calculate the Doppler shift due to satellite movement
fdSat = satcom.internal.dopplerShift(fc,double(chanParams.SatelliteSpeed), ...
double(chanParams.ElevationAngle),double(chanParams.SatelliteAltitude));
% Check the maximum Doppler shift and sample rate
if ((maxDoppler+abs(fdSat)) >= (baseChan.SampleRate/10))
error("satcom:HelperSetupNTNChannel:MaxDoppler",...
"The maximum Doppler shift (%d) due to mobile and satellite "+ ...
"movement, must be less than one-tenth of SampleRate.", ...
(maxDoppler+abs(fdSat)));
end
% Set the channel filter
chanFilt = comm.ChannelFilter(...
'SampleRate',baseChan.SampleRate,'PathDelays',pathDelays, ...
'NormalizeChannelOutputs',false);
% Set the output structure
ntnChan = struct;
ntnChan.ChannelName = chanName;
ntnChan.BaseChannel = baseChan;
ntnChan.ChannelFilter = chanFilt;
ntnChan.SatelliteDopplerShift = fdSat;
ntnChan.MobileDopplerSpread = maxDoppler;
end
function chanParams = validateMandatoryFields(chanParams)
% Validate the mandatory fields
if isfield(chanParams,'NTNChannelType') && ...
isfield(chanParams,'CarrierFrequency') && ...
isfield(chanParams,'SatelliteSpeed') && ...
isfield(chanParams,'SatelliteAltitude') && ...
isfield(chanParams,'MobileSpeed') && ...
isfield(chanParams,'ElevationAngle')
chanParams.NTNChannelType = validatestring(chanParams.NTNChannelType, ...
{'Narrowband','TDL'},'','CHANPARAMS.NTNChannelType');
validateattributes(chanParams.CarrierFrequency, {'double'}, ...
{'scalar','real','finite','nonnegative'},'','CHANPARAMS.CarrierFrequency');
validateattributes(chanParams.SatelliteSpeed, {'double'}, ...
{'scalar','real','finite'},'','CHANPARAMS.SatelliteSpeed');
validateattributes(chanParams.SatelliteAltitude, {'double'}, ...
{'scalar','real','finite','nonnegative'},'','CHANPARAMS.SatelliteAltitude');
validateattributes(chanParams.MobileSpeed, {'double'}, ...
{'scalar','real','finite','nonnegative'},'','CHANPARAMS.MobileSpeed');
validateattributes(chanParams.ElevationAngle, {'double'}, ...
{'scalar','real','finite'},'','CHANPARAMS.ElevationAngle');
if strcmpi(chanParams.NTNChannelType,'TDL')
if isfield(chanParams,'DelayProfile')
chanParams.DelayProfile = validatestring(chanParams.DelayProfile, ...
{'NTN-TDL-A','NTN-TDL-B','NTN-TDL-C','NTN-TDL-D','Custom'}, ...
'','CHANPARAMS.DelayProfile');
else
error("satcom:HelperSetupNTNChannel:TDLRequiredFields", ...
"CHANPARAMS must have DelayProfile field when " + ...
"NTNChannelType field is set to TDL.");
end
else % Narrowband
if isfield(chanParams,'AzimuthOrientation') && ...
isfield(chanParams,'Environment')
validateattributes(chanParams.AzimuthOrientation, {'double'}, ...
{'scalar','real','finite'},'','CHANPARAMS.AzimuthOrientation');
chanParams.Environment = validatestring(chanParams.Environment, ...
{'Urban', 'Suburban', 'RuralWooded', 'Village', 'Train', ...
'Residential', 'Highway', 'Rural', 'Custom'},'', ...
'CHANPARAMS.Environment');
else
error("satcom:HelperSetupNTNChannel:NarrowbandRequiredFields", ...
"CHANPARAMS must have AzimuthOrientation and " + ...
"Environment fields, when NTNChannelType field is set to Narrowband.");
end
end
else
error("satcom:HelperSetupNTNChannel:CommonRequiredFields", ...
"CHANPARAMS must have the mandatory fields: NTNChannelType, " ...
+ "CarrierFrequency, SatelliteSpeed, SatelliteAltitude, " ...
+ "ElevationAngle, and MobileSpeed.");
end
end
function [o,cond] = passign(s,o,f,ac)
% Assign the fields of structure to the appropriate object properties
cond = isfield(s,f);
if nargin == 4
cond = cond & ac;
end
for i = 1:length(cond)
if cond(i)
o.(f{i}) = s.(f{i});
end
end
end