NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
LTENR_PHY.c
1/************************************************************************************
2* Copyright (C) 2023 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* This source code is licensed per the NetSim license agreement. *
12* *
13* No portion of this source code may be used as the basis for a derivative work, *
14* or used, for any purpose other than its intended use per the NetSim license *
15* agreement. *
16* *
17* This source code and the algorithms contained within it are confidential trade *
18* secrets of TETCOS and may not be used as the basis for any other software, *
19* hardware, product or service. *
20* *
21* Author: Shashi Kant Suman *
22* *
23* ----------------------------------------------------------------------------------*/
24
25#pragma region HEADER_FILES
26#include "stdafx.h"
27#include "LTENR_MAC.h"
28#include "LTENR_PHY.h"
29#include "LTENR_NetworkSlicing.h"
30#include "NTN_PropagationModel.h"
31#pragma endregion
32
33#pragma region FUNCTION_PROTOTYPE
34//PRB
35static void LTENR_form_prb_list(NETSIM_ID d, NETSIM_ID in, int CA_ID);
36
37//Active UE per CA
38static void LTENR_form_active_ue_list(NETSIM_ID gnbId, NETSIM_ID gnbIf, int CA_ID);
39
40//Frame
41static void LTENR_addStartFrameEvent(NETSIM_ID gnbId, NETSIM_ID gnbIf, double time, int CA_ID);
42void LTENR_handleStartFrameEvent();
43
44//SubFrame
45static void LTENR_addStartSubFrameEvent(NETSIM_ID gnbId, NETSIM_ID gnbIf, double time, int CA_ID);
46void LTENR_handleStartSubFrameEvent();
47
48//Slot
49static void LTENR_addStartSlotEvent(NETSIM_ID gnbId, NETSIM_ID gnbIf, double time, int CA_ID);
50void LTENR_handleStartSlotEvent();
51
52//Association
53void LTENR_PHY_ASSOCIATION(NETSIM_ID gnbId, NETSIM_ID gnbIf,
54 NETSIM_ID ueId, NETSIM_ID ueIf,
55 bool isAssociated);
56
57//AMC
58static void LTENR_PHY_initAMCInfo(ptrLTENR_GNBPHY phy, ptrLTENR_ASSOCIATEDUEPHYINFO assocInfo);
59static void LTENR_PHY_setAMCInfo(ptrLTENR_GNBPHY phy, ptrLTENR_ASSOCIATEDUEPHYINFO info, int CA_ID);
60
61//BWP
62void LTENR_ACTIVEUEINFO_ADD(NETSIM_ID ueId, NETSIM_ID ueIf, NETSIM_ID gnbId, NETSIM_ID gnbIf, int CA_ID);
63void LTENR_ACTIVEUEINFO_REMOVE(NETSIM_ID ueId, NETSIM_ID ueIf, NETSIM_ID gnbId, NETSIM_ID gnbIf, int CA_ID);
64//ptrLTENR_CA_UE_LIST LTENR_ACTIVEUEINFO_FIND(NETSIM_ID ueId, NETSIM_ID ueIf, NETSIM_ID gnbId, NETSIM_ID gnbIf, int CA_ID);
65#pragma endregion
66
67#pragma region OLLA_LOG
68static FILE* fpOLLALog = NULL;
69static void OpenOLLALog()
70{
71 if (get_protocol_log_status("LTENR_OLLA_LOG"))
72 {
73 char s[BUFSIZ];
74
75 if (isNTNScenario())
76 sprintf(s, "%s\\%s", pszIOLogPath, "NTN_OLLA_Log.csv");
77 else
78 sprintf(s, "%s\\%s", pszIOLogPath, "LTENR_OLLA_Log.csv");
79 fpOLLALog = fopen(s, "w");
80 if (!fpOLLALog)
81 {
82 fnSystemError("Unable to open %s file", s);
83 perror(s);
84 }
85 else
86 {
87 fprintf(fpOLLALog, "%s,%s,%s,%s,%s,",
88 "Time(ms)", "eNB/gNB Name", "UE Name", "Carrier ID", "Layer ID");
89
90 fprintf(fpOLLALog, "%s,%s,%s,%s,%s,",
91 "Frame Id", "Sub-Frame Id", "Slot Id", "Channel", "Phy SINR(dB)");
92
93 fprintf(fpOLLALog, "%s,%s,%s,%s,",
94 "SINR Delta(dB)", "Virtual SINR(dB)", "CQI without OLLA", "CQI with OLLA");
95
96 fprintf(fpOLLALog, "\n");
97 fflush(fpOLLALog);
98 }
99 }
100}
101
102static void CloseOLLALog()
103{
104 if (fpOLLALog) { fclose(fpOLLALog); }
105}
106
107void LTENR_OLLA_Log_Init()
108{
109 OpenOLLALog();
110}
111
112void LTENR_OLLA_Log_Finish()
113{
114 CloseOLLALog();
115}
116
117static void WriteOLLALog(char* format, ...)
118{
119 if (fpOLLALog)
120 {
121 va_list l;
122 va_start(l, format);
123 vfprintf(fpOLLALog, format, l);
124 if (nDbgFlag) fflush(fpOLLALog);
125 }
126}
127#pragma endregion //OLLA_LOG
128
129#pragma region PHY_INIT
130void fn_NetSim_LTENR_PHY_Init()
131{
132 LTENR_SUBEVENT_REGISTER(LTENR_SUBEVENT_PHY_STARTFRAME, "LTENR_STARTFRAME", LTENR_handleStartFrameEvent);
133 LTENR_SUBEVENT_REGISTER(LTENR_SUBEVENT_PHY_STARTSUBFRAME, "LTENR_STARTSUBFRAME", LTENR_handleStartSubFrameEvent);
134 LTENR_SUBEVENT_REGISTER(LTENR_SUBEVENT_PHY_STARTSLOT, "LTENR_STARTSLOT", LTENR_handleStartSlotEvent);
135
136 fn_NetSim_LTENR_RegisterCallBackForAssociation(LTENR_PHY_ASSOCIATION);
137}
138
139void fn_NetSim_LTENR_UEPHY_Init(NETSIM_ID ueId, NETSIM_ID ueIf)
140{
141}
142
143void fn_NetSim_LTENR_GNBPHY_Init(NETSIM_ID gnbId, NETSIM_ID gnbIf)
144{
145 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);
146 UINT i = 0;
147 for (i = 0; i < phy->ca_count; i++) {
148 phy->spectrumConfig->Current_CA_ID = i;
149
150 LTENR_form_prb_list(gnbId, gnbIf, i);
151
152 if(phy->spectrumConfig->CA[i]->isBWPEnabled)
153 LTENR_form_active_ue_list(gnbId, gnbIf, i);
154
155 LTENR_addStartFrameEvent(gnbId, gnbIf, 0, i);
156 }
157 //Beamforming
158 LTENR_BeamForming_InitCoherenceTimer(phy);
159}
160
161ptrLTENR_GNBPHY LTENR_GNBPHY_NEW(NETSIM_ID gnbId, NETSIM_ID gnbIf)
162{
163 ptrLTENR_GNBPHY phy = calloc(1, sizeof * phy);
164 phy->spectrumConfig = calloc(1, sizeof * phy->spectrumConfig);
165 phy->propagationConfig = calloc(1, sizeof * phy->propagationConfig);
166 phy->antenna = calloc(1, sizeof * phy->antenna);
167 LTENR_GNBPHY_SET(gnbId, gnbIf, phy);
168 phy->gnbId = gnbId;
169 phy->gnbIf = gnbIf;
170 return phy;
171}
172
173ptrLTENR_UEPHY LTENR_UEPHY_NEW(NETSIM_ID ueId, NETSIM_ID ueIf)
174{
175 ptrLTENR_UEPHY phy = calloc(1, sizeof * phy);
176 phy->propagationConfig = calloc(1, sizeof * phy->propagationConfig);
177 phy->antenna = calloc(1, sizeof * phy->antenna);
178 LTENR_UEPHY_SET(ueId, ueIf, phy);
179 phy->ueId = ueId;
180 phy->ueIf = ueIf;
181 return phy;
182}
183#pragma endregion
184
185#pragma region PRB
186static void LTENR_form_prb_list(NETSIM_ID d, NETSIM_ID in, int CA_ID)
187{
188 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(d, in);
189 ptrLTENR_SPECTRUMCONFIG sc = phy->spectrumConfig;
190 ptrLTENR_CA ca = sc->CA[CA_ID];
191 UINT i;
192 print_ltenr_log("Forming PRB list for gNB %d:%d -- \n", d, in);
193 double prbBandwidth_kHz = ca->prbBandwidth_kHz;
194 double guard_kHz = ca->guardBand_kHz;
195 print_ltenr_log("CA_ID = %d\n", CA_ID);
196 print_ltenr_log("\tF_Low_MHz = %d\n", ca->Flow_MHZ);
197 print_ltenr_log("\tF_High_MHz = %d\n", ca->Fhigh_MHz);
198 print_ltenr_log("\tChannel_Bandwidth_MHz = %lf\n", ca->channelBandwidth_mHz);
199 print_ltenr_log("\tPRB_Bandwidth_kHz = %lf\n", prbBandwidth_kHz);
200 print_ltenr_log("\tGuard_Bandwidth_kHz = %lf\n", guard_kHz);
201 print_ltenr_log("\tPRB_ID\tF_Low\tF_High\tF_center\n");
202
203 phy->prbList = calloc(ca->PRBCount, sizeof * phy->prbList);
204 for (i = 0; i < ca->PRBCount; i++)
205 {
206 phy->prbList[i].prbId = i + 1;
207 phy->prbList[i].lFrequency_MHz = ca->Flow_MHZ + guard_kHz * 0.001 + prbBandwidth_kHz * i * 0.001;
208 phy->prbList[i].uFrequency_MHz = phy->prbList[i].lFrequency_MHz + prbBandwidth_kHz * 0.001;
209 phy->prbList[i].centralFrequency_MHz = (phy->prbList[i].lFrequency_MHz + phy->prbList[i].uFrequency_MHz) / 2.0;
210 phy->prbList[i].prbBandwidth_MHz = prbBandwidth_kHz * 0.001;
211 print_ltenr_log("\t%3d\t%lf\t%lf\t%lf\n",
212 i + 1,
213 phy->prbList[i].lFrequency_MHz,
214 phy->prbList[i].uFrequency_MHz,
215 phy->prbList[i].centralFrequency_MHz);
216 }
217 print_ltenr_log("\n\n");
218}
219#pragma endregion
220
221#pragma region FRAME
222static void LTENR_addStartFrameEvent(NETSIM_ID gnbId, NETSIM_ID gnbIf, double time, int CA_ID)
223{
224 NetSim_EVENTDETAILS pevent;
225 memset(&pevent, 0, sizeof pevent);
226 pevent.dEventTime = time;
227 pevent.nDeviceId = gnbId;
228 pevent.nDeviceType = DEVICE_TYPE(gnbId);
229 pevent.nEventType = TIMER_EVENT;
230 pevent.nInterfaceId = gnbIf;
231 ptrLTENR_PROTODATA pd = LTENR_PROTODATA_GET(gnbId, gnbIf);
232 LTENR_SET_SUBEVENT(pd, &pevent, LTENR_SUBEVENT_PHY_STARTFRAME);
233#pragma warning (disable : 4312)
234 pevent.szOtherDetails = (void*)CA_ID;
235#pragma warning (default : 4312)
236 UINT id = fnpAddEvent(&pevent);
237}
238
239static void LTENR_resetFrame(ptrLTENR_GNBPHY phy, int CA_ID)
240{
241 ptrLTENR_FRAMEINFO info = phy->frameInfo[CA_ID];
242 ptrLTENR_SPECTRUMCONFIG sc = phy->spectrumConfig;
243
244 info->frameId++;
245 info->frameStartTime = pstruEventDetails->dEventTime;
246 info->frameEndTime = pstruEventDetails->dEventTime + sc->frameDuration;
247
248 //reset slot
249 info->slotEndTime = 0;
250 info->slotId = 0;
251 info->slotStartTime = 0;
252
253 //reset subframe
254 info->subFrameEndTime = 0;
255 info->subFrameId = 0;
256 info->subFrameStartTime = 0;
257}
258
259void LTENR_handleStartFrameEvent()
260{
261 NETSIM_ID gnbId = pstruEventDetails->nDeviceId;
262 NETSIM_ID gnbIf = pstruEventDetails->nInterfaceId;
263#pragma warning (disable : 4047)
264 int CA_ID = pstruEventDetails->szOtherDetails;
265#pragma warning (default : 4047)
266 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);
267
268 LTENR_resetFrame(phy, CA_ID);
269 print_ltenr_log("Starting new frame for gNB %d:%d\n", gnbId, gnbIf);
270 print_ltenr_log("CA_ID for Frame = %d\n", CA_ID);
271 print_ltenr_log("\tFrame Id = %d\n", phy->frameInfo[CA_ID]->frameId);
272 print_ltenr_log("\tFrame start time (µs) = %lf\n", phy->frameInfo[CA_ID]->frameStartTime);
273 print_ltenr_log("\tFrame end time (µs) = %lf\n", phy->frameInfo[CA_ID]->frameEndTime);
274
275 LTENR_addStartFrameEvent(gnbId, gnbIf,
276 phy->frameInfo[CA_ID]->frameEndTime, CA_ID);
277
278 LTENR_addStartSubFrameEvent(gnbId, gnbIf,
279 phy->frameInfo[CA_ID]->frameStartTime, CA_ID);
280}
281#pragma endregion
282
283#pragma region SUBFRAME
284static void LTENR_addStartSubFrameEvent(NETSIM_ID gnbId, NETSIM_ID gnbIf, double time, int CA_ID)
285{
286 NetSim_EVENTDETAILS pevent;
287 memset(&pevent, 0, sizeof pevent);
288 pevent.dEventTime = time;
289 pevent.nDeviceId = gnbId;
290 pevent.nDeviceType = DEVICE_TYPE(gnbId);
291 pevent.nEventType = TIMER_EVENT;
292 pevent.nInterfaceId = gnbIf;
293 ptrLTENR_PROTODATA pd = LTENR_PROTODATA_GET(gnbId, gnbIf);
294 LTENR_SET_SUBEVENT(pd, &pevent, LTENR_SUBEVENT_PHY_STARTSUBFRAME);
295#pragma warning (disable : 4312)
296 pevent.szOtherDetails = (void*)CA_ID;
297#pragma warning (default : 4312)
298 fnpAddEvent(&pevent);
299}
300
301static void LTENR_resetSubFrame(ptrLTENR_GNBPHY phy, int CA_ID)
302{
303 ptrLTENR_FRAMEINFO info = phy->frameInfo[CA_ID];
304 ptrLTENR_SPECTRUMCONFIG sc = phy->spectrumConfig;
305
306 //reset slot
307 info->slotEndTime = 0;
308 info->slotId = 0;
309 info->slotStartTime = 0;
310
311 //reset subframe
312 info->subFrameStartTime = pstruEventDetails->dEventTime;
313 info->subFrameEndTime = pstruEventDetails->dEventTime + sc->subFrameDuration;
314 info->subFrameId++;
315
316}
317
318void LTENR_handleStartSubFrameEvent()
319{
320 NETSIM_ID gnbId = pstruEventDetails->nDeviceId;
321 NETSIM_ID gnbIf = pstruEventDetails->nInterfaceId;
322 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);
323#pragma warning (disable : 4047)
324 int CA_ID = pstruEventDetails->szOtherDetails;
325#pragma warning (default : 4047)
326
327 LTENR_resetSubFrame(phy,CA_ID);
328 print_ltenr_log("Starting new sub frame for gNB %d:%d\n", gnbId, gnbIf);
329 print_ltenr_log("CA_ID for SubFrame = %d\n", CA_ID);
330 print_ltenr_log("\tFrame Id = %d\n", phy->frameInfo[CA_ID]->frameId);
331 print_ltenr_log("\tSubFrame Id = %d\n", phy->frameInfo[CA_ID]->subFrameId);
332 print_ltenr_log("\tSubFrame start time (µs) = %lf\n", phy->frameInfo[CA_ID]->subFrameStartTime);
333 print_ltenr_log("\tSubFrame end time (µs) = %lf\n", phy->frameInfo[CA_ID]->subFrameEndTime);
334
335 if (phy->frameInfo[CA_ID]->subFrameId != phy->spectrumConfig->subFramePerFrame)
336 LTENR_addStartSubFrameEvent(gnbId, gnbIf,
337 phy->frameInfo[CA_ID]->subFrameEndTime, CA_ID);
338
339 LTENR_addStartSlotEvent(gnbId, gnbIf,
340 phy->frameInfo[CA_ID]->subFrameStartTime, CA_ID);
341}
342#pragma endregion
343
344#pragma region SLOT
345static void LTENR_addStartSlotEvent(NETSIM_ID gnbId, NETSIM_ID gnbIf, double time, int CA_ID)
346{
347 NetSim_EVENTDETAILS pevent;
348 memset(&pevent, 0, sizeof pevent);
349 pevent.dEventTime = time;
350 pevent.nDeviceId = gnbId;
351 pevent.nDeviceType = DEVICE_TYPE(gnbId);
352 pevent.nEventType = TIMER_EVENT;
353 pevent.nInterfaceId = gnbIf;
354 ptrLTENR_PROTODATA pd = LTENR_PROTODATA_GET(gnbId, gnbIf);
355 LTENR_SET_SUBEVENT(pd, &pevent, LTENR_SUBEVENT_PHY_STARTSLOT);
356#pragma warning (disable : 4312)
357 pevent.szOtherDetails = (PVOID)CA_ID;
358#pragma warning (default : 4312)
359 fnpAddEvent(&pevent);
360}
361
362static void LTENR_resetSlot(ptrLTENR_GNBPHY phy, int CA_ID)
363{
364 ptrLTENR_FRAMEINFO info = phy->frameInfo[CA_ID];
365 ptrLTENR_CA ca = phy->spectrumConfig->CA[CA_ID];
366
367 //reset slot
368 info->slotId++;
369 info->slotStartTime = pstruEventDetails->dEventTime;
370 info->slotEndTime = pstruEventDetails->dEventTime + ca->slotDuration_us;
371
372 if (ca->configSlotType == SLOT_MIXED)
373 {
374 if (ca->totalSlotCount && (ca->dlSlotCount*1.0) / ca->totalSlotCount < ca->dlSlotRatio)
375 {
376 ca->dlSlotCount++;
377 info->slotType = SLOT_DOWNLINK;
378 }
379 else
380 info->slotType = SLOT_UPLINK;
381
382 ca->totalSlotCount++;
383 }
384 else
385 info->slotType = ca->configSlotType;
386}
387
388void LTENR_handleStartSlotEvent()
389{
390 NETSIM_ID gnbId = pstruEventDetails->nDeviceId;
391 NETSIM_ID gnbIf = pstruEventDetails->nInterfaceId;
392 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);
393
394#pragma warning (disable : 4047)
395 int CA_ID = pstruEventDetails->szOtherDetails;
396#pragma warning (default : 4047)
397
398 ptrLTENR_CA ca = phy->spectrumConfig->CA[CA_ID];
399
400 LTENR_resetSlot(phy,CA_ID);
401 print_ltenr_log("Starting new slot for gNB %d:%d\n", gnbId, gnbIf);
402 print_ltenr_log("CA_ID for Slot = %d\n", CA_ID);
403 print_ltenr_log("\tFrame Id = %d\n", phy->frameInfo[CA_ID]->frameId);
404 print_ltenr_log("\tSubFrame Id = %d\n", phy->frameInfo[CA_ID]->subFrameId);
405 print_ltenr_log("\tSlot Id = %d\n", phy->frameInfo[CA_ID]->slotId);
406 print_ltenr_log("\tSlot start time (µs) = %lf\n", phy->frameInfo[CA_ID]->slotStartTime);
407 print_ltenr_log("\tslot end time (µs) = %lf\n", phy->frameInfo[CA_ID]->slotEndTime);
408 print_ltenr_log("\tSlot type = %s\n", strLTENR_SLOTTYPE[phy->frameInfo[CA_ID]->slotType]);
409
410 phy->currentFrameInfo = phy->frameInfo[CA_ID];
411 phy->currentFrameInfo->Current_CA_ID = CA_ID;
412 if (phy->frameInfo[CA_ID]->slotId != ca->slotPerSubframe)
413 LTENR_addStartSlotEvent(gnbId, gnbIf,
414 phy->frameInfo[CA_ID]->slotEndTime, CA_ID);
415
416 ptrLTENR_ASSOCIATEDUEPHYINFO info = phy->associatedUEPhyInfo;
417 while (info)
418 {
419 if (info->isAssociated)
420 {
421 for (NETSIM_ID i = 0; i < phy->ca_count; i++)
422 LTENR_PHY_setAMCInfo(phy, info, i);
423
424 }
425 info = LTENR_ASSOCIATEDUEPHYINFO_NEXT(info);
426
427 }
428
429 ptrLTENR_GNBMAC mac = LTENR_GNBMAC_GET(gnbId, gnbIf);
430 ptrLTENR_SCHEDULERINFO schedulerInfo = mac->schedulerInfo[CA_ID];
431 LTENR_NotifyMACForStartingSlot();
432 phy->frameInfo[CA_ID]->prevSlotType = phy->frameInfo[CA_ID]->slotType;
433}
434#pragma endregion
435
436#pragma region PHY_PROPAGATION_INTERFACE
437static ptrLTENR_PROPAGATIONINFO LTENR_PHY_initPropagationInfo(ptrLTENR_GNBPHY phy,
438 NETSIM_ID ueId, NETSIM_ID ueIf,
439 int CA_ID)
440{
441 ptrLTENR_UEPHY uePhy = LTENR_UEPHY_GET(ueId, ueIf);
442 ptrLTENR_PROPAGATIONINFO info = calloc(1, sizeof * info);
443
444 ptrLTENR_CA ca = phy->spectrumConfig->CA[CA_ID];
445
446 info->gnbId = phy->gnbId;
447 info->gnbIf = phy->gnbIf;
448 memcpy(&info->gnbPos, DEVICE_POSITION(phy->gnbId), sizeof info->gnbPos);
449 memcpy(&info->uePos, DEVICE_POSITION(ueId), sizeof info->uePos);
450 info->ueId = ueId;
451 info->ueIf = ueIf;
452 info->bandwidth_MHz = ca->channelBandwidth_mHz;
453 info->centralFrequency_MHz = (ca->Fhigh_MHz + ca->Flow_MHZ) / 2.0;
454 info->centralFrequency_GHz = info->centralFrequency_MHz / 1000;
455 UINT ulLayerCount = LTENR_PHY_GET_ULLAYER_COUNT_FOR_NONASSOCIATED(phy, uePhy);
456 UINT dlLayerCount = LTENR_PHY_GET_DLLAYER_COUNT_FOR_NONASSOCIATED(phy, uePhy);
457 info->downlink.txPower_dbm = MW_TO_DBM(DBM_TO_MW(phy->propagationConfig->txPower_dbm));
458 info->uplink.txPower_dbm = MW_TO_DBM(DBM_TO_MW(uePhy->propagationConfig->txPower_dbm));
459 info->downlink.totaltxpower_dbm = phy->propagationConfig->txPower_dbm;
460 info->uplink.totaltxpower_dbm = uePhy->propagationConfig->txPower_dbm;
461
462 info->propagationConfig = phy->propagationConfig;
463 info->propagationConfig->UE_height = uePhy->propagationConfig->UE_height;
464
465 info->downlink.EB_by_N0 = calloc(dlLayerCount, sizeof * info->downlink.EB_by_N0);
466 info->downlink.SNR_db = calloc(dlLayerCount, sizeof * info->downlink.SNR_db);
467 info->downlink.SINR_db = calloc(dlLayerCount, sizeof * info->downlink.SINR_db);
468 info->downlink.InterferencePower_dbm = calloc(dlLayerCount, sizeof * info->downlink.InterferencePower_dbm);
469 info->downlink.spectralEfficiency = calloc(dlLayerCount, sizeof * info->downlink.spectralEfficiency);
470 info->downlink.rxPower_dbm = calloc(dlLayerCount, sizeof * info->downlink.rxPower_dbm);
471 info->downlink.layerCount = dlLayerCount;
472 info->downlink.txAntennaCount = phy->antenna->txAntennaCount;
473 info->downlink.rxAntennaCount = uePhy->antenna->rxAntennaCount;
474
475 info->uplink.EB_by_N0 = calloc(ulLayerCount, sizeof * info->uplink.EB_by_N0);
476 info->uplink.SNR_db = calloc(ulLayerCount, sizeof * info->uplink.SNR_db);
477 info->uplink.SINR_db = calloc(ulLayerCount, sizeof * info->uplink.SINR_db);
478 info->uplink.InterferencePower_dbm = calloc(ulLayerCount, sizeof * info->uplink.InterferencePower_dbm);
479 info->uplink.spectralEfficiency = calloc(ulLayerCount, sizeof * info->uplink.spectralEfficiency);
480 info->uplink.rxPower_dbm = calloc(ulLayerCount, sizeof * info->uplink.rxPower_dbm);
481 info->uplink.layerCount = ulLayerCount;
482 info->uplink.txAntennaCount = uePhy->antenna->txAntennaCount;
483 info->uplink.rxAntennaCount = phy->antenna->rxAntennaCount;
484 if(info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_AWGN_WITH_RAYLEIGH_FADING ||
485 info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_AWGN_WITH_RICIAN_FADING)
486 LTENR_BeamForming_Init(info);
487 return info;
488}
489
490static void LTENR_PHY_updatePropagationInfo(ptrLTENR_PROPAGATIONINFO info)
491{
492 memcpy(&info->gnbPos, DEVICE_POSITION(info->gnbId), sizeof info->gnbPos);
493 memcpy(&info->uePos, DEVICE_POSITION(info->ueId), sizeof info->uePos);
494}
495
496#define BOLTZMANN 1.38064852e-23 //m2kgs-2K-1
497#define TEMPERATURE 300 //kelvin
498static double LTENR_PHY_calculateThermalNoise(double bandwidth)
499{
500 double noise = BOLTZMANN * TEMPERATURE * bandwidth * 1000000; //in W
501 noise *= 1000; // in mW
502 double noise_dbm = MW_TO_DBM(noise);
503 return noise_dbm;
504}
505
506static double LTENR_PHY_GetDownlinkBeamFormingValue(ptrLTENR_PROPAGATIONINFO info, int layerId)
507{
508 if (info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_NO_FADING_MIMO_ARRAY_GAIN)
509 {
510 UINT MaxAntenaCount = max(info->downlink.rxAntennaCount, info->downlink.txAntennaCount);
511 info->downlink.ArrayGain = 10.0 * log10(MaxAntenaCount);
512 return info->downlink.ArrayGain;
513 }
514 if(info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_AWGN_WITH_RAYLEIGH_FADING||
515 info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_AWGN_WITH_RICIAN_FADING)
516 {
517 return LTENR_BeamForming_Downlink_GetValue(info, layerId);
518 }
519 else
520 return 0;
521}
522static double LTENR_PHY_GetUplinkBeamFormingValue(ptrLTENR_PROPAGATIONINFO info, int layerId)
523{
524 if (info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_NO_FADING_MIMO_ARRAY_GAIN) {
525 UINT MaxAntenaCount = max(info->uplink.rxAntennaCount, info->uplink.txAntennaCount);
526 info->uplink.ArrayGain = 10.0 * log10(MaxAntenaCount);
527 return info->uplink.ArrayGain;
528 }
529 if (info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_AWGN_WITH_RAYLEIGH_FADING ||
530 info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_AWGN_WITH_RICIAN_FADING) {
531 return LTENR_BeamForming_Uplink_GetValue(info, layerId);
532 }
533 else
534 return 0;
535}
536
537static double LTENR_PHY_GetDownlinkAnalogBeamFormingValue(ptrLTENR_PROPAGATIONINFO info)
538{
539 info->downlink.SSB_AnalogBeamformingGain_dB = 10.0 * log10(info->downlink.txAntennaCount * info->downlink.rxAntennaCount);
540 return info->downlink.SSB_AnalogBeamformingGain_dB;
541}
542
543static void LTENR_PHY_calculateSNR(double rxPower_dbm, double thermalNoise_dbm,
544 double* ebByN0,double* snrDB)
545{
546 double p = DBM_TO_MW(rxPower_dbm);
547 double n = DBM_TO_MW(thermalNoise_dbm);
548 *ebByN0 = p / n;
549 *snrDB = MW_TO_DBM(*ebByN0);
550}
551
552static void LTENR_PHY_calculateSINR(double rxPower_dbm, double thermalNoise_dbm, double InterferencePower_dbm,
553 double* sinrDB, double* ebByN0)
554{
555 double p = DBM_TO_MW(rxPower_dbm);
556 double n = DBM_TO_MW(thermalNoise_dbm);
557 double I = DBM_TO_MW(InterferencePower_dbm);
558 *ebByN0 = p / (n+I);
559 *sinrDB = MW_TO_DBM(*ebByN0);
560}
561double LTENR_PHY_GetDownlinkSpectralEfficiency(ptrLTENR_PROPAGATIONINFO info, int layerId,int CA_ID)
562{
563 if (isNTNScenario())
564 return NTN_GetDownlinkSpectralEfficiency(info, layerId, CA_ID);
565
566 ptrLTENR_PROTODATA pd = LTENR_PROTODATA_GET(info->gnbId, info->gnbIf);
567 ptrLTENR_ASSOCIATEDUEPHYINFO assocInfo = LTENR_ASSOCIATEDUEPHYINFO_GET(info->gnbId, info->gnbIf, info->ueId, info->ueIf);
568 double BeamFormingGain_dbm = assocInfo->isAssociated ? LTENR_PHY_GetDownlinkBeamFormingValue(info, layerId) : 0.0;
569 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(info->gnbId, info->gnbIf);
570 info->downlink.antennaGain = LTENR_PHY_GetAntennaGain(info, phy->antenna);
571 info->downlink.rxPower_dbm[layerId] = info->downlink.txPower_dbm - info->dTotalLoss + info->downlink.antennaGain;
572
573 info->downlink.thermalNoise = LTENR_PHY_calculateThermalNoise(info->bandwidth_MHz);
574 LTENR_Calculate_Interference(info, info->downlink.rxPower_dbm[layerId], &info->downlink.InterferencePower_dbm[layerId],layerId, CA_ID, true);
575 info->downlink.rxPower_dbm[layerId] = info->downlink.txPower_dbm - info->dTotalLoss + BeamFormingGain_dbm + info->downlink.antennaGain;
576 LTENR_PHY_calculateSNR(info->downlink.rxPower_dbm[layerId],
577 info->downlink.thermalNoise,
578 &info->downlink.EB_by_N0[layerId],
579 &info->downlink.SNR_db[layerId]);
580 if (info->propagationConfig->DownlinkInterferenceModel == LTENR_INTERFERENCE_OVER_THERMAL_INTERFERENCE)
581 {
582 ptrLTENR_PROPAGATIONCONFIG propagation = info->propagationConfig;
583 info->downlink.SINR_db[layerId] = info->downlink.SNR_db[layerId] - propagation->Downlink_IoT_dB;
584 if (propagation->Downlink_IoT_dB < 0)
585 {
586 fnNetSimError("Uplink Interference over thermal is less than 0. Value is %lf. Resetting it to 0.\n",
587 propagation->Downlink_IoT_dB);
588 propagation->Downlink_IoT_dB = 0;
589 }
590 if (propagation->Downlink_IoT_dB == 0)
591 info->downlink.InterferencePower_dbm[layerId] = NEGATIVE_DBM;
592 else
593 info->downlink.InterferencePower_dbm[layerId] = 10 * log10(DBM_TO_MW(info->downlink.thermalNoise) * (pow(10, propagation->Downlink_IoT_dB) - 1));
594 info->downlink.EB_by_N0[layerId] = DBM_TO_MW(info->downlink.SINR_db[layerId]);
595 }
596 else
597 {
598 LTENR_PHY_calculateSINR(info->downlink.rxPower_dbm[layerId],
599 info->downlink.thermalNoise,
600 info->downlink.InterferencePower_dbm[layerId],
601 &info->downlink.SINR_db[layerId], &info->downlink.EB_by_N0[layerId]);
602 }
603 info->downlink.spectralEfficiency[layerId] = pd->alpha*
604 log2(1 + info->downlink.EB_by_N0[layerId]);
605 return info->downlink.spectralEfficiency[layerId];
606}
607
608double LTENR_PHY_GetUplinkSpectralEfficiency(ptrLTENR_PROPAGATIONINFO info, int layerId, int CA_ID)
609{
610 if (isNTNScenario())
611 return NTN_GetUplinkSpectralEfficiency(info, layerId, CA_ID);
612
613 ptrLTENR_PROTODATA pd = LTENR_PROTODATA_GET(info->gnbId, info->gnbIf);
614 ptrLTENR_ASSOCIATEDUEPHYINFO assocInfo = LTENR_ASSOCIATEDUEPHYINFO_GET(info->gnbId, info->gnbIf, info->ueId, info->ueIf);
615 double BeamFormingGain_dbm = assocInfo->isAssociated ? LTENR_PHY_GetUplinkBeamFormingValue(info, layerId) : 0.0;
616 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(info->gnbId, info->gnbIf);
617 info->uplink.antennaGain = LTENR_PHY_GetAntennaGain(info, phy->antenna);
618 info->uplink.rxPower_dbm[layerId] = info->uplink.txPower_dbm - info->dTotalLoss + info->uplink.antennaGain;
619 info->uplink.thermalNoise = LTENR_PHY_calculateThermalNoise(info->bandwidth_MHz);
620 LTENR_Calculate_Interference(info, info->uplink.rxPower_dbm[layerId], &info->uplink.InterferencePower_dbm[layerId], layerId, CA_ID, false);
621 info->uplink.rxPower_dbm[layerId] = info->uplink.txPower_dbm - info->dTotalLoss + BeamFormingGain_dbm + info->uplink.antennaGain;
622 LTENR_PHY_calculateSNR(info->uplink.rxPower_dbm[layerId],
623 info->uplink.thermalNoise,
624 &info->uplink.EB_by_N0[layerId],
625 &info->uplink.SNR_db[layerId]);
626 ptrLTENR_PROPAGATIONCONFIG propagation = info->propagationConfig;
627 info->uplink.SINR_db[layerId] = info->uplink.SNR_db[layerId] - propagation->Uplink_IoT_dB;
628 if (propagation->Uplink_IoT_dB < 0)
629 {
630 fnNetSimError("Uplink Interference over thermal is less than 0. Value is %lf. Resetting it to 0.\n",
631 propagation->Uplink_IoT_dB);
632 propagation->Uplink_IoT_dB = 0;
633 }
634 if (propagation->Uplink_IoT_dB == 0)
635 info->uplink.InterferencePower_dbm[layerId] = NEGATIVE_DBM;
636 else
637 info->uplink.InterferencePower_dbm[layerId] = 10 * log10(DBM_TO_MW(info->uplink.thermalNoise) * (pow(10, propagation->Uplink_IoT_dB) - 1));
638 info->uplink.EB_by_N0[layerId] = DBM_TO_MW(info->uplink.SINR_db[layerId]);
639 info->uplink.spectralEfficiency[layerId] = pd->alpha *
640 log2(1 + info->uplink.EB_by_N0[layerId]);
641 return info->uplink.spectralEfficiency[layerId];
642}
643
644double NTN_GetUplinkSpectralEfficiency(ptrLTENR_PROPAGATIONINFO info, int layerId, int CA_ID)
645{
646 ptrLTENR_PROTODATA pd = LTENR_PROTODATA_GET(info->gnbId, info->gnbIf);
647 ptrLTENR_ASSOCIATEDUEPHYINFO assocInfo = LTENR_ASSOCIATEDUEPHYINFO_GET(info->gnbId, info->gnbIf, info->ueId, info->ueIf);
648 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(info->gnbId, info->gnbIf);
649
650 info->uplink.spectralEfficiency[layerId] = 15; // Need to be set properly
651 //NTN_BestBeamSelectionAlgorithm(info, layerId);
652
653 return info->uplink.spectralEfficiency[layerId];
654}
655
656double NTN_GetDownlinkSpectralEfficiency(ptrLTENR_PROPAGATIONINFO info, int layerId, int CA_ID)
657{
658 ptrLTENR_PROTODATA pd = LTENR_PROTODATA_GET(info->gnbId, info->gnbIf);
659 ptrLTENR_ASSOCIATEDUEPHYINFO assocInfo = LTENR_ASSOCIATEDUEPHYINFO_GET(info->gnbId, info->gnbIf, info->ueId, info->ueIf);
660 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(info->gnbId, info->gnbIf);
661 //NTN_BestBeamSelectionAlgorithm(info, layerId);
662 info->downlink.SNR_db[layerId] = calculateNTN_SNR(info, LTENR_BeamForming_Downlink_GetValue(info, layerId));
663
664 updateNTNRxPower(info, layerId);
665
666 NTN_calculateSINR(info, layerId);
667
668 updateNTN_EB_by_N0(info, layerId);
669 return info->downlink.spectralEfficiency[layerId];
670
671}
672
673static void NTN_UpdateSSBProp(ptrLTENR_PROPAGATIONINFO info, UINT layerId)
674{
675 info->downlink.SSB_rxPower_dBm = info->downlink.rxPower_dbm[layerId];
676 info->downlink.SSB_EB_by_N0 = info->downlink.EB_by_N0[layerId];
677 info->downlink.SSB_SNR_dB = info->downlink.SNR_db[layerId];
678 info->downlink.SSB_AnalogBeamformingGain_dB = 0; // Check what else can be done
679
680}
681
682void NTN_MapUe_SliceId(ptrLTENR_PROPAGATIONINFO info)
683{
684 UINT ueId, sliceId;
685
686 ueId = info->ueId;
687 sliceId = info->selectedBeamId;
688 nws->ueSliceId[ueId] = sliceId-1;
689
690 return;
691}
692
693static void NTN_calculateDownlinkSpectralEfficiency(ptrLTENR_GNBPHY phy, NETSIM_ID ueId,
694 NETSIM_ID ueIf, int CA_ID)
695{
696 ptrLTENR_PROTODATA pd = LTENR_PROTODATA_GET(phy->gnbId, phy->gnbIf);
697 ptrLTENR_ASSOCIATEDUEPHYINFO assocInfo = LTENR_ASSOCIATEDUEPHYINFO_GET(phy->gnbId, phy->gnbIf, ueId, ueIf);
698
699 ptrLTENR_PROPAGATIONINFO info = assocInfo->propagationInfo[CA_ID];
700
701 ptrLTENR_CA ca = phy->spectrumConfig->CA[CA_ID];
702
703 if (ca->configSlotType == SLOT_UPLINK)
704 return;
705
706 for (UINT i = 0; i < info->downlink.layerCount; i++)
707 {
708 NTN_BestBeamSelectionAlgorithm(info, CA_ID,i);
709 NTN_MapUe_SliceId(info);
710 NTN_UpdateSSBProp(info,i);
711 }
712}
713
714void deepCopyDownlinkPropagationInfo(ptrLTENR_PROPAGATIONINFO propInfo, ptrLTENR_PROPAGATIONINFO tempInfo)
715{
716 if (!propInfo || !tempInfo) {
717 fprintf(stderr, "PorpInfo not copied");
718 return;
719 }
720 UINT layerCount = propInfo->downlink.layerCount;
721
722 propInfo->angularAntennaGain_dB = tempInfo->angularAntennaGain_dB;
723 propInfo->netAntennaGain_dB = tempInfo->netAntennaGain_dB;
724 propInfo->rxG_T = tempInfo->rxG_T;
725 propInfo->selectedBeamId = tempInfo->selectedBeamId;
726
727 propInfo->slantHeight = tempInfo->slantHeight;
728 propInfo->theta_rad = tempInfo->theta_rad;
729 propInfo->dPathLoss = tempInfo->dPathLoss;
730 propInfo->dShadowFadingLoss = tempInfo->dShadowFadingLoss;
731 propInfo->dAdditionalLoss = tempInfo->dAdditionalLoss;
732 propInfo->dClutterLoss = tempInfo->dClutterLoss;
733 propInfo->dTotalLoss = tempInfo->dTotalLoss;
734 propInfo->downlink.thermalNoise = tempInfo->downlink.thermalNoise;
735
736 for (int layerId = 0; layerId < layerCount; layerId++)
737 {
738 propInfo->downlink.SNR_db[layerId] = tempInfo->downlink.SNR_db[layerId];
739 propInfo->downlink.rxPower_dbm[layerId] = tempInfo->downlink.rxPower_dbm[layerId];
740 propInfo->downlink.EB_by_N0[layerId] = tempInfo->downlink.EB_by_N0[layerId];
741 propInfo->downlink.spectralEfficiency[layerId] = tempInfo->downlink.spectralEfficiency[layerId];
742 propInfo->downlink.SINR_db[layerId] = tempInfo->downlink.SINR_db[layerId];
743 propInfo->downlink.InterferencePower_dbm[layerId] = tempInfo->downlink.InterferencePower_dbm[layerId];
744 }
745 return;
746}
747static void deepCopyUplinkPropagationInfo(ptrLTENR_PROPAGATIONINFO propInfo, ptrLTENR_PROPAGATIONINFO tempInfo)
748{
749 if (!propInfo || !tempInfo) {
750 fprintf(stderr, "PorpInfo not copied");
751 return;
752 }
753
754 propInfo->angularAntennaGain_dB = tempInfo->angularAntennaGain_dB;
755 propInfo->netAntennaGain_dB = tempInfo->netAntennaGain_dB;
756 propInfo->rxG_T = tempInfo->rxG_T;
757 propInfo->selectedBeamId = tempInfo->selectedBeamId;
758
759 propInfo->slantHeight = tempInfo->slantHeight;
760 propInfo->theta_rad = tempInfo->theta_rad;
761 propInfo->dPathLoss = tempInfo->dPathLoss;
762 propInfo->dShadowFadingLoss = tempInfo->dShadowFadingLoss;
763 propInfo->dAdditionalLoss = tempInfo->dAdditionalLoss;
764 propInfo->dClutterLoss = tempInfo->dClutterLoss;
765 propInfo->dTotalLoss = tempInfo->dTotalLoss;
766 propInfo->downlink.thermalNoise = tempInfo->downlink.thermalNoise;
767
768 UINT layerCount = propInfo->uplink.layerCount;
769
770 for (int layerId = 0; layerId < layerCount; layerId++)
771 {
772 propInfo->uplink.SNR_db[layerId] = tempInfo->uplink.SNR_db[layerId];
773 propInfo->uplink.rxPower_dbm[layerId] = tempInfo->uplink.rxPower_dbm[layerId];
774 propInfo->uplink.EB_by_N0[layerId] = tempInfo->uplink.EB_by_N0[layerId];
775 propInfo->uplink.spectralEfficiency[layerId] = tempInfo->uplink.spectralEfficiency[layerId];
776 propInfo->uplink.SINR_db[layerId] = tempInfo->uplink.SINR_db[layerId];
777 propInfo->uplink.InterferencePower_dbm[layerId] = tempInfo->uplink.InterferencePower_dbm[layerId];
778 }
779 return;
780}
781
782static void freeRankInfo(ptrLTENR_PROPAGATIONINFO propInfo)
783{
784 if (!propInfo) return;
785
786 if (propInfo->downlink.rxPower_dbm) free(propInfo->downlink.rxPower_dbm);
787 if (propInfo->downlink.SNR_db) free(propInfo->downlink.SNR_db);
788 if (propInfo->downlink.SINR_db) free(propInfo->downlink.SINR_db);
789 if (propInfo->downlink.EB_by_N0) free(propInfo->downlink.EB_by_N0);
790 if (propInfo->downlink.InterferencePower_dbm) free(propInfo->downlink.InterferencePower_dbm);
791 if (propInfo->downlink.spectralEfficiency) free(propInfo->downlink.spectralEfficiency);
792
793 if (propInfo->uplink.rxPower_dbm) free(propInfo->uplink.rxPower_dbm);
794 if (propInfo->uplink.SNR_db) free(propInfo->uplink.SNR_db);
795 if (propInfo->uplink.SINR_db) free(propInfo->uplink.SINR_db);
796 if (propInfo->uplink.EB_by_N0) free(propInfo->uplink.EB_by_N0);
797 if (propInfo->uplink.InterferencePower_dbm) free(propInfo->uplink.InterferencePower_dbm);
798 if (propInfo->uplink.spectralEfficiency) free(propInfo->uplink.spectralEfficiency);
799}
800static void LTENR_PHY_calculateSpectralEfficiency(ptrLTENR_GNBPHY phy,
801 NETSIM_ID ueId, NETSIM_ID ueIf,
802 int CA_ID)
803{
804 ptrLTENR_PROTODATA pd = LTENR_PROTODATA_GET(phy->gnbId, phy->gnbIf);
805 ptrLTENR_ASSOCIATEDUEPHYINFO assocInfo = LTENR_ASSOCIATEDUEPHYINFO_GET(phy->gnbId, phy->gnbIf, ueId, ueIf);
806 if (!assocInfo->propagationInfo[CA_ID])
807 assocInfo->propagationInfo[CA_ID] = LTENR_PHY_initPropagationInfo(phy, ueId, ueIf, CA_ID);
808 else
809 LTENR_PHY_updatePropagationInfo(assocInfo->propagationInfo[CA_ID]);
810
811 ptrLTENR_PROPAGATIONINFO info = assocInfo->propagationInfo[CA_ID];
812 if (!info)
813 {
814 fnNetSimError("Propagation info is NULL for CA_ID = %d for gNB %d-%d --> UE %d-%d.\n",
815 CA_ID,
816 phy->gnbId, phy->gnbIf,
817 assocInfo->ueId, assocInfo->ueIf);
818 return;
819 }
820
821 print_ltenr_log("\n\tCarrier Id = %d\n", CA_ID);
822
823 if (isNTNScenario())
824 {
825 NTN_calculateDownlinkSpectralEfficiency(phy, ueId, ueIf, CA_ID);
826 return;
827 }
828
829 //Call propagation model
830 LTENR_Propagation_TotalLoss(info);
831
832 if (DEVICE_MACPROTOCOL(info->gnbId, info->gnbIf) == MAC_PROTOCOL_LTE_NR)
833 {
834 info->downlink.antennaGain = LTENR_PHY_GetAntennaGain(info, phy->antenna);
835 info->downlink.SSB_rxPower_dBm = info->downlink.totaltxpower_dbm - info->dTotalLoss + LTENR_PHY_GetDownlinkAnalogBeamFormingValue(info)
836 + info->downlink.antennaGain;
837 }
838 else if (DEVICE_MACPROTOCOL(info->gnbId, info->gnbIf) == MAC_PROTOCOL_LTE)
839 info->downlink.SSB_rxPower_dBm = info->downlink.totaltxpower_dbm - info->dTotalLoss;
840 else
841 fnNetSimError("Unknown MAC protocol for gNB/eNB %d-%d", info->gnbId, info->gnbIf);
842
843 info->downlink.thermalNoise = LTENR_PHY_calculateThermalNoise(info->bandwidth_MHz);
844 LTENR_PHY_calculateSNR(info->downlink.SSB_rxPower_dBm,
845 info->downlink.thermalNoise,
846 &info->downlink.SSB_EB_by_N0,
847 &info->downlink.SSB_SNR_dB);
848
849 ptrLTENR_PROPAGATIONINFO tempInfo = (ptrLTENR_PROPAGATIONINFO)malloc(sizeof(LTENR_PROPAGATIONINFO));
850 memcpy(tempInfo, info, sizeof(*info));
851 allocateInfo(tempInfo);
852
853 double maxValue = 0;
854 UINT maxIndex = 0;
855 UINT layers = 0;
856 UINT dlLayerCount = min(info->downlink.txAntennaCount, info->downlink.rxAntennaCount);
857 if ((info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_AWGN_WITH_RAYLEIGH_FADING || info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_AWGN_WITH_RICIAN_FADING) &&
858 info->propagationConfig->channelRank == LTENR_CHANNEL_RANK_MAX_RATE)
859 {
860 layers = 0;
861 }
862 else {
863 layers = info->downlink.layerCount - 1 ;
864 }
865
866 for (UINT i = layers; i < dlLayerCount; i++)
867 {
868 double value = 0;
869
870 for (UINT m = 0; m <= i; m++)
871 {
872 double BeamFormingGain_dbm = assocInfo->isAssociated ? LTENR_PHY_GetDownlinkBeamFormingValue(tempInfo, m) : 0.0;
873 double tx_power = MW_TO_DBM(DBM_TO_MW(tempInfo->downlink.totaltxpower_dbm) / (i + 1));
874 tempInfo->downlink.rxPower_dbm[m] = tx_power - tempInfo->dTotalLoss + tempInfo->downlink.antennaGain;
875 tempInfo->downlink.thermalNoise = LTENR_PHY_calculateThermalNoise(tempInfo->bandwidth_MHz);
876 LTENR_Calculate_Interference(tempInfo, tempInfo->downlink.rxPower_dbm[m], &tempInfo->downlink.InterferencePower_dbm[m], m, CA_ID, true);
877 tempInfo->downlink.rxPower_dbm[m] = tx_power - tempInfo->dTotalLoss + BeamFormingGain_dbm + tempInfo->downlink.antennaGain;
878 LTENR_PHY_calculateSNR(tempInfo->downlink.rxPower_dbm[m],
879 tempInfo->downlink.thermalNoise,
880 &tempInfo->downlink.EB_by_N0[m],
881 &tempInfo->downlink.SNR_db[m]);
882 LTENR_PHY_calculateSINR(tempInfo->downlink.rxPower_dbm[m],
883 tempInfo->downlink.thermalNoise,
884 tempInfo->downlink.InterferencePower_dbm[m],
885 &tempInfo->downlink.SINR_db[m], &tempInfo->downlink.EB_by_N0[m]);
886 tempInfo->downlink.spectralEfficiency[m] = pd->alpha *
887 log2(1 + tempInfo->downlink.EB_by_N0[m]);
888
889 double sinr = DBM_TO_MW(tempInfo->downlink.SINR_db[m]);
890 value += log2(1 + sinr/(i+1));
891 }
892 if (value > maxValue)
893 {
894 maxValue = value;
895 maxIndex = i;
896 deepCopyDownlinkPropagationInfo(info, tempInfo);
897 }
898 }
899 freeRankInfo(tempInfo);
900 free(tempInfo);
901
902 ptrLTENR_PROPAGATIONINFO tempUplinkInfo = (ptrLTENR_PROPAGATIONINFO)malloc(sizeof(LTENR_PROPAGATIONINFO));
903 memcpy(tempUplinkInfo, info, sizeof(*info));
904 allocateInfo(tempUplinkInfo);
905 double maxUplinkValue = 0;
906 UINT maxUplinkIndex = 0;
907 UINT uplinkLayers = 0;
908 UINT ulLayerCount = min(info->uplink.txAntennaCount, info->uplink.rxAntennaCount);
909 if ((info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_AWGN_WITH_RAYLEIGH_FADING || info->propagationConfig->fastFadingModel == LTENR_FASTFADING_MODEL_AWGN_WITH_RICIAN_FADING) ||
910 info->propagationConfig->channelRank == LTENR_CHANNEL_RANK_MAX_RATE)
911 {
912 uplinkLayers = 0;
913 }
914 else {
915 uplinkLayers = info->uplink.layerCount - 1;
916 }
917 for (UINT i = uplinkLayers; i < ulLayerCount; i++)
918 {
919 double uplinkvalue = 0;
920 for (UINT m = 0; m <= i; m++)
921 {
922 double BeamFormingGain_dbm = assocInfo->isAssociated ? LTENR_PHY_GetUplinkBeamFormingValue(tempUplinkInfo, m) : 0.0;
923 double tx_power = MW_TO_DBM(DBM_TO_MW(tempUplinkInfo->uplink.totaltxpower_dbm) / (i + 1));
924 tempUplinkInfo->uplink.rxPower_dbm[m] = tx_power - tempUplinkInfo->dTotalLoss;
925 tempUplinkInfo->uplink.thermalNoise = LTENR_PHY_calculateThermalNoise(tempUplinkInfo->bandwidth_MHz);
926 LTENR_Calculate_Interference(tempUplinkInfo, tempUplinkInfo->uplink.rxPower_dbm[m], &tempUplinkInfo->uplink.InterferencePower_dbm[m], m, CA_ID, false);
927 tempUplinkInfo->uplink.rxPower_dbm[m] = tx_power - tempUplinkInfo->dTotalLoss + BeamFormingGain_dbm + tempUplinkInfo->uplink.antennaGain;
928 LTENR_PHY_calculateSNR(tempUplinkInfo->uplink.rxPower_dbm[m],
929 tempUplinkInfo->uplink.thermalNoise,
930 &tempUplinkInfo->uplink.EB_by_N0[m],
931 &tempUplinkInfo->uplink.SNR_db[m]);
932
933 ptrLTENR_PROPAGATIONCONFIG propagation = tempUplinkInfo->propagationConfig;
934 tempUplinkInfo->uplink.SINR_db[i] = tempUplinkInfo->uplink.SNR_db[m] - propagation->Uplink_IoT_dB;
935 if (propagation->Uplink_IoT_dB < 0)
936 {
937 fnNetSimError("Uplink Interference over thermal is less than 0. Value is %lf. Resetting it to 0.\n",
938 propagation->Uplink_IoT_dB);
939 propagation->Uplink_IoT_dB = 0;
940 }
941 if (propagation->Uplink_IoT_dB == 0)
942 tempUplinkInfo->uplink.InterferencePower_dbm[m] = NEGATIVE_DBM;
943 else
944 tempUplinkInfo->uplink.InterferencePower_dbm[m] = 10 * log10(DBM_TO_MW(tempUplinkInfo->uplink.thermalNoise) * (pow(10, propagation->Uplink_IoT_dB) - 1));
945 tempUplinkInfo->uplink.EB_by_N0[m] = DBM_TO_MW(tempUplinkInfo->uplink.SINR_db[m]);
946 tempUplinkInfo->uplink.spectralEfficiency[m] = pd->alpha *
947 log2(1 + tempUplinkInfo->uplink.EB_by_N0[m]);
948
949 double sinr = DBM_TO_MW(tempUplinkInfo->uplink.SINR_db[m]);
950 uplinkvalue += log2(1 + sinr/(i+1));
951 }
952 if (uplinkvalue > maxUplinkValue) {
953 maxUplinkValue = uplinkvalue;
954 maxUplinkIndex = i;
955 deepCopyUplinkPropagationInfo(info, tempUplinkInfo);
956 }
957
958 }
959 freeRankInfo(tempUplinkInfo);
960 free(tempUplinkInfo);
961 if (info->propagationConfig->channelRank == LTENR_CHANNEL_RANK_MAX_RATE)
962 {
963 info->downlink.layerCount = maxIndex + 1;
964 info->uplink.layerCount = maxUplinkIndex + 1;
965 }
966 info->downlink.txPower_dbm = MW_TO_DBM(DBM_TO_MW(info->downlink.totaltxpower_dbm) / info->downlink.layerCount);
967 info->uplink.txPower_dbm = MW_TO_DBM(DBM_TO_MW(info->uplink.totaltxpower_dbm) / info->uplink.layerCount);
968
969 for (UINT i = 0; i < info->downlink.layerCount; i++)
970 {
971 print_ltenr_log("\tDownlink for Layer %d\n", i + 1);
972 print_ltenr_log("\t\t Thermal Noise = %lf dBm\n", info->downlink.thermalNoise);
973 print_ltenr_log("\t\t Interference = %lf dBm\n", info->downlink.InterferencePower_dbm[i]);
974 print_ltenr_log("\t\t Signal to Noise Ratio (SNR) = %lf dB\n", info->downlink.SNR_db[i]);
975 print_ltenr_log("\t\t Signal to Interference & Noise Ratio (SINR) = %lf dB\n", info->downlink.SINR_db[i]);
976 print_ltenr_log("\t\t Spectral Efficiency = %lf dB\n", info->downlink.spectralEfficiency[i]);
977 print_ltenr_log("\n");
978 }
979
980 for (UINT i = 0; i < info->downlink.layerCount; i++)
981 {
982 print_ltenr_log("\tUplink for Layer %d\n", i + 1);
983 print_ltenr_log("\t\t Thermal Noise = %lf dBm\n", info->uplink.thermalNoise);
984 print_ltenr_log("\t\t Interference = %lf dBm\n", info->uplink.InterferencePower_dbm[i]);
985 print_ltenr_log("\t\t Signal to Noise Ratio (SNR) = %lf dB\n", info->uplink.SNR_db[i]);
986 print_ltenr_log("\t\t Signal to Interference & Noise Ratio (SINR) = %lf dB\n", info->uplink.SINR_db[i]);
987 print_ltenr_log("\t\t Spectral Efficiency = %lf dB\n", info->uplink.spectralEfficiency[i]);
988 print_ltenr_log("\n");
989 }
990}
991
992double LTENR_PHY_Send_SINR_to_RRC(ptrLTENR_GNBPHY phy)
993{
994 UINT c = 0;
995 double sinr = 0;
996 for (UINT i = 0; i < phy->ca_count; i++)
997 {
998 ptrLTENR_PROPAGATIONINFO info = phy->associatedUEPhyInfo->propagationInfo[i];
999 for (UINT j = 0; j < info->downlink.layerCount; j++)
1000 {
1001 c++;
1002 sinr += info->downlink.SNR_db[j];
1003 }
1004 }
1005 return sinr/c;
1006}
1007
1008double LTENR_PHY_Send_RSRP_to_RRC(ptrLTENR_GNBPHY phy) {
1009 UINT c = 0;
1010 double rsrp = 0;
1011 for (UINT i = 0; i < phy->ca_count; i++)
1012 {
1013 ptrLTENR_PROPAGATIONINFO info = phy->associatedUEPhyInfo->propagationInfo[i];
1014 for (UINT j = 0; j < info->downlink.layerCount; j++)
1015 {
1016 c++;
1017 rsrp += info->downlink.rxPower_dbm[j];
1018 }
1019 }
1020 return rsrp / c;
1021}
1022
1023static void setAMCInfo(ptrLTENR_GNBPHY phy, NETSIM_ID ueId, NETSIM_ID ueIf, ptrLTENR_AMCINFO amcInfo, bool isUplink, int caId, int layerId)
1024{
1025 ptrLTENR_ASSOCIATEDUEPHYINFO info = LTENR_ASSOCIATEDUEPHYINFO_GET(phy->gnbId, phy->gnbIf, ueId, ueIf);
1026
1027 WriteOLLALog("%.2lf,%s,%s,%d,%d,",
1028 ldEventTime / MILLISECOND, DEVICE_NAME(phy->gnbId), DEVICE_NAME(ueId), caId + 1, layerId);
1029
1030 WriteOLLALog("%d,%d,%d,%s,",
1031 phy->currentFrameInfo->frameId, phy->currentFrameInfo->subFrameId, phy->currentFrameInfo->slotId, isUplink ? "PUSCH" : "PDSCH");
1032
1033 ptrLTENR_PROTODATA pd = LTENR_PROTODATA_GET(phy->gnbId, phy->gnbIf);
1034 LTENR_CQITable ot = LTENR_GetCQITableFromSpectralEfficiency(phy->CSIReportConfig.cqiTable,
1035 amcInfo->SpectralEfficiency);
1036 double delta = LTENR_OLLA_GetDeltaSINR(phy->gnbId, phy->gnbIf, ueId, ueIf, isUplink, caId, layerId);
1037 double eff = amcInfo->SpectralEfficiency;
1038 eff /= pd->alpha;
1039 double eb = pow(2, eff) - 1;
1040 double sinr = MW_TO_DBM(eb) - delta;
1041 eff = pd->alpha * log2(1 + DBM_TO_MW(sinr));
1042 amcInfo->cqiTable = LTENR_GetCQITableFromSpectralEfficiency(phy->CSIReportConfig.cqiTable,
1043 eff);
1044 WriteOLLALog("%lf,%lf,%lf,%d,%d,\n",
1045 isUplink ? info->propagationInfo[caId]->uplink.SINR_db[layerId - 1] : info->propagationInfo[caId]->downlink.SINR_db[layerId - 1],
1046 delta, sinr, ot.CQIIndex, amcInfo->cqiTable.CQIIndex);
1047
1048 if (amcInfo->cqiTable.CQIIndex != 0)
1049 {
1050 if (isUplink)
1051 amcInfo->mcsTable = LTENR_GetMCSIndexTableFromSpectralEfficiency(phy->PUSCHConfig.mcsTable,
1052 amcInfo->cqiTable.efficiency);
1053 else
1054 amcInfo->mcsTable = LTENR_GetMCSIndexTableFromSpectralEfficiency(phy->PDSCHConfig.mcsTable,
1055 amcInfo->cqiTable.efficiency);
1056 }
1057 else
1058 {
1059 if (isUplink)
1060 amcInfo->mcsTable = ((ptrLTENR_MCSINDEXTABLE)phy->PUSCHConfig.mcsTable)[0];
1061 else
1062 amcInfo->mcsTable = ((ptrLTENR_MCSINDEXTABLE)phy->PDSCHConfig.mcsTable)[0];
1063 }
1064
1065
1066 print_ltenr_log("\t\tSpectral Efficiency = %lf\n", amcInfo->SpectralEfficiency);
1067 print_ltenr_log("\t\tCQI Table\n");
1068 print_ltenr_log("\t\t\t%d\t%s\t%d\t%lf\n",
1069 amcInfo->cqiTable.CQIIndex,
1070 strPHY_MODULATION[amcInfo->cqiTable.modulation],
1071 amcInfo->cqiTable.codeRate,
1072 amcInfo->cqiTable.efficiency);
1073 print_ltenr_log("\t\tMCS Table\n");
1074 print_ltenr_log("\t\t\t%d\t%s\t%d\t%lf\t%lf\n",
1075 amcInfo->mcsTable.mcsIndex,
1076 strPHY_MODULATION[amcInfo->mcsTable.modulation],
1077 amcInfo->mcsTable.modulationOrder,
1078 amcInfo->mcsTable.codeRate,
1079 amcInfo->mcsTable.spectralEfficiency);
1080}
1081
1082static void LTENR_PHY_setAMCInfo(ptrLTENR_GNBPHY phy, ptrLTENR_ASSOCIATEDUEPHYINFO info, int CA_ID)
1083{
1084 UINT layerCount;
1085 ptrLTENR_UEPHY uePhy = LTENR_UEPHY_GET(info->ueId, info->ueIf);
1086
1087 //Downlink
1088 layerCount = LTENR_PHY_GET_DLLAYER_COUNT(uePhy);
1089 for (UINT i = 0; i < layerCount; i++)
1090 {
1091 print_ltenr_log("\tAMC info between gNB %d:%d and UE %d:%d, Carrier Id = %d, Layer Id = %d for downlink-\n",
1092 phy->gnbId, phy->gnbIf,
1093 info->ueId, info->ueIf,
1094 CA_ID, i);
1095 info->downlinkAMCInfo[CA_ID][i]->SpectralEfficiency = LTENR_PHY_GetDownlinkSpectralEfficiency(info->propagationInfo[CA_ID], i, CA_ID);
1096 setAMCInfo(phy, info->ueId, info->ueIf, info->downlinkAMCInfo[CA_ID][i], false, CA_ID, i + 1);
1097 }
1098 LTENR_RadioMeasurements_PDSCH_Log(phy, CA_ID, info);
1099 NTNRadioMeasurementLog(phy, CA_ID, info);
1100 //Uplink
1101 layerCount = LTENR_PHY_GET_ULLAYER_COUNT(uePhy);
1102 for (UINT i = 0; i < layerCount; i++)
1103 {
1104 print_ltenr_log("\tAMC info between gNB %d:%d and UE %d:%d, Carrier Id = %d, Layer Id = %d for uplink-\n",
1105 phy->gnbId, phy->gnbIf,
1106 info->ueId, info->ueIf,
1107 CA_ID, i);
1108 info->uplinkAMCInfo[CA_ID][i]->SpectralEfficiency = LTENR_PHY_GetUplinkSpectralEfficiency(info->propagationInfo[CA_ID], i, CA_ID);
1109 setAMCInfo(phy, info->ueId, info->ueIf, info->uplinkAMCInfo[CA_ID][i], true, CA_ID, i + 1);
1110 }
1111 LTENR_RadioMeasurements_PUSCH_Log(phy, CA_ID, info);
1112}
1113#pragma endregion
1114
1115#pragma region PHY_AMCINFO
1116static void LTENR_PHY_initAMCInfo(ptrLTENR_GNBPHY phy, ptrLTENR_ASSOCIATEDUEPHYINFO assocInfo)
1117{
1118 NETSIM_ID i = 0;
1119 for (i = 0; i < phy->ca_count; i++)
1120 {
1121 if (!assocInfo->downlinkAMCInfo[i])
1122 {
1123 ptrLTENR_UEPHY uePhy = LTENR_UEPHY_GET(assocInfo->ueId, assocInfo->ueIf);
1124 UINT layerCount = LTENR_PHY_GET_DLLAYER_COUNT(uePhy);
1125 assocInfo->downlinkAMCInfo[i] = calloc(layerCount, sizeof * assocInfo->downlinkAMCInfo[i]);
1126 for (UINT j = 0; j < layerCount; j++)
1127 assocInfo->downlinkAMCInfo[i][j] = calloc(1, sizeof * assocInfo->downlinkAMCInfo[i][j]);
1128 }
1129 if (!assocInfo->uplinkAMCInfo[i])
1130 {
1131 ptrLTENR_UEPHY uePhy = LTENR_UEPHY_GET(assocInfo->ueId, assocInfo->ueIf);
1132 UINT layerCount = LTENR_PHY_GET_ULLAYER_COUNT(uePhy);
1133 assocInfo->uplinkAMCInfo[i] = calloc(layerCount, sizeof * assocInfo->uplinkAMCInfo[i]);
1134 for (UINT j = 0; j < layerCount; j++)
1135 assocInfo->uplinkAMCInfo[i][j] = calloc(1, sizeof * assocInfo->uplinkAMCInfo[i][j]);
1136 }
1137
1138 LTENR_PHY_calculateSpectralEfficiency(phy, assocInfo->ueId, assocInfo->ueIf, i);
1139 LTENR_PHY_setAMCInfo(phy, assocInfo, i);
1140 LTENR_RadioMeasurements_PBSCH_Log(phy, i, assocInfo);
1141 }
1142}
1143#pragma endregion
1144
1145#pragma region RSRP_SINR_FOR_RRC
1146double LTENR_PHY_RRC_RSRP_SINR(NETSIM_ID gnbId, NETSIM_ID gnbIf,
1147 NETSIM_ID ueId, NETSIM_ID ueIf) {
1148 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);
1149
1150 ptrLTENR_ASSOCIATEDUEPHYINFO info = LTENR_ASSOCIATEDUEPHYINFO_GET(gnbId, gnbIf, ueId, ueIf);
1151
1152 double Avg_SSB_SNR = 0;
1153 UINT c = 0;
1154 for (NETSIM_ID i = 0; i < phy->ca_count; i++)
1155 {
1156 if (info->propagationInfo[i] == NULL)
1157 LTENR_PHY_calculateSpectralEfficiency(phy, ueId, ueIf, i);
1158 if (info->propagationInfo[i] != NULL)
1159 Avg_SSB_SNR += DBM_TO_MW(info->propagationInfo[i]->downlink.SSB_SNR_dB);
1160 c++;
1161 LTENR_RadioMeasurements_PBSCH_Log(phy, i, info);
1162 }
1163 return MW_TO_DBM(Avg_SSB_SNR / c);
1164}
1165#pragma endregion
1166
1167#pragma region PHY_ASSOCIATION
1168static ptrLTENR_ASSOCIATEDUEPHYINFO LTENR_ASSOCIATEDUEPHYINFO_FIND(ptrLTENR_GNBPHY phy,
1169 NETSIM_ID ueId, NETSIM_ID ueIf)
1170{
1171 ptrLTENR_ASSOCIATEDUEPHYINFO info = phy->associatedUEPhyInfo;
1172 while (info)
1173 {
1174 if (info->ueId == ueId && info->ueIf == ueIf)
1175 return info;
1176 LTENR_ASSOCIATEDUEPHYINFO_NEXT(info);
1177 }
1178 return NULL;
1179}
1180
1181ptrLTENR_ASSOCIATEDUEPHYINFO LTENR_ASSOCIATEDUEPHYINFO_GET(NETSIM_ID gnbId, NETSIM_ID gnbIf,
1182 NETSIM_ID ueId, NETSIM_ID ueIf)
1183{
1184 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);
1185 ptrLTENR_ASSOCIATEDUEPHYINFO info = LTENR_ASSOCIATEDUEPHYINFO_FIND(phy, ueId, ueIf);
1186 if (info) return info;
1187
1188 info = LTENR_ASSOCIATEDUEPHYINFO_ALLOC();
1189 LTENR_ASSOCIATEDUEPHYINFO_ADD(phy, info);
1190 info->ueId = ueId;
1191 info->ueIf = ueIf;
1192
1193 return info;
1194}
1195
1196static void LTENR_PHY_associateUE(NETSIM_ID gnbId, NETSIM_ID gnbIf,
1197 NETSIM_ID ueId, NETSIM_ID ueIf)
1198{
1199 print_ltenr_log("PHY-- UE %d:%d is associated with gNB %d:%d\n",
1200 ueId, ueIf, gnbId, gnbIf);
1201
1202 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);
1203 ptrLTENR_ASSOCIATEDUEPHYINFO info = LTENR_ASSOCIATEDUEPHYINFO_GET(gnbId, gnbIf, ueId, ueIf);
1204
1205 info->isAssociated = true;
1206
1207 ptrLTENR_UEPHY uePhy = LTENR_UEPHY_GET(ueId, ueIf);
1208 uePhy->gnBId = gnbId;
1209 uePhy->gnbIf = gnbIf;
1210
1211 fn_NetSim_LTENR_Conditional_HO_TTT_Matrix_Add(gnbId, gnbIf, ueId, ueIf);
1212
1213 LTENR_ANTENNA_SET_LAYER_COUNT(phy->antenna, uePhy->antenna);
1214
1215 LTENR_PHY_initAMCInfo(phy, info);
1216
1217 HARQAssociationHandler(gnbId, gnbIf, ueId, ueIf, true);
1218
1219 ptrLTENR_GNBMAC mac = LTENR_GNBMAC_GET(gnbId, gnbIf);
1220 if (fn_NetSim_LTENR_IS_S1_INTERFACE_EXISTS(gnbId)) {
1221 if (mac->epcId != 0) {
1222 LTENR_EPC_ASSOCIATION(mac->epcId, mac->epcIf,
1223 gnbId, gnbIf,
1224 ueId, ueIf);
1225 }
1226 }
1227}
1228
1229static void LTENR_PHY_deassociateUE(NETSIM_ID gnbId, NETSIM_ID gnbIf,
1230 NETSIM_ID ueId, NETSIM_ID ueIf)
1231{
1232 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);
1233 ptrLTENR_ASSOCIATEDUEPHYINFO info = phy->associatedUEPhyInfo;
1234 while (info)
1235 {
1236 if (info->ueId == ueId && info->ueIf == ueIf)
1237 {
1238 info->isAssociated = false;
1239 HARQAssociationHandler(gnbId, gnbIf, ueId, ueIf, false);
1240 for (UINT i = 0; i < MAX_CA_COUNT; i++)
1241 {
1242 free(info->downlinkAMCInfo[i]);
1243 info->downlinkAMCInfo[i] = NULL;
1244 free(info->uplinkAMCInfo[i]);
1245 info->uplinkAMCInfo[i] = NULL;
1246 }
1247 break;
1248 }
1249 LTENR_ASSOCIATEDUEPHYINFO_NEXT(info);
1250 }
1251 fn_NetSim_LTENR_Conditional_HO_TTT_Matrix_Remove(gnbId, gnbIf, ueId, ueIf);
1252}
1253
1254void LTENR_PHY_ASSOCIATION(NETSIM_ID gnbId, NETSIM_ID gnbIf,
1255 NETSIM_ID ueId, NETSIM_ID ueIf,
1256 bool isAssociated)
1257{
1258 if (isAssociated)
1259 LTENR_PHY_associateUE(gnbId, gnbIf, ueId, ueIf);
1260 else
1261 LTENR_PHY_deassociateUE(gnbId, gnbIf, ueId, ueIf);
1262}
1263#pragma endregion
1264
1265#pragma region PHY_API
1266double LTENR_PHY_GetSlotEndTime(NETSIM_ID d, NETSIM_ID in)
1267{
1268 if (isGNB(d, in))
1269 {
1270 ptrLTENR_FRAMEINFO fi = ((ptrLTENR_GNBPHY)LTENR_GNBPHY_GET(d, in))->currentFrameInfo;
1271 return fi->slotEndTime;
1272 }
1273 else
1274 {
1275 ptrLTENR_UEPHY phy = LTENR_UEPHY_GET(d, in);
1276 return LTENR_PHY_GetSlotEndTime(phy->gnBId, phy->gnbIf);
1277 }
1278}
1279
1280static void fn_NetSim_UPDATE_SPECTRAL_EFFICIENCY_INFO(NETSIM_ID gnbID, NETSIM_ID gnbIF,
1281 NETSIM_ID ueID, NETSIM_ID ueIF)
1282{
1283 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbID, gnbIF);
1284 ptrLTENR_ASSOCIATEDUEPHYINFO info = LTENR_ASSOCIATEDUEPHYINFO_GET(gnbID, gnbIF, ueID, ueIF);
1285 for (NETSIM_ID i = 0; i < phy->ca_count; i++)
1286 {
1287 if (info->propagationInfo[i])
1288 {
1289 info->propagationInfo[i]->uePos.X = DEVICE_POSITION(ueID)->X;
1290 info->propagationInfo[i]->uePos.Y = DEVICE_POSITION(ueID)->Y;
1291 info->propagationInfo[i]->uePos.Z = DEVICE_POSITION(ueID)->Z;
1292 }
1293 LTENR_PHY_calculateSpectralEfficiency(phy, ueID, ueIF, i);
1294 }
1295}
1296
1297#pragma endregion
1298
1299void fn_NetSim_PHY_MOBILITY_HANDLE(NETSIM_ID d)
1300{
1301 for (NETSIM_ID in = 1; in <= DEVICE(d)->nNumOfInterface; in++)
1302 {
1303 if (!isLTENR_RANInterface(d, in)) continue;
1304
1305 if (isGNB(d, in))
1306 {
1307 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(d, in);
1308 ptrLTENR_ASSOCIATEDUEPHYINFO info = phy->associatedUEPhyInfo;
1309 while (info)
1310 {
1311 fn_NetSim_UPDATE_SPECTRAL_EFFICIENCY_INFO(d, in, info->ueId, info->ueIf);
1312 LTENR_ASSOCIATEDUEPHYINFO_NEXT(info);
1313 }
1314 }
1315 else if (isUE(d, in))
1316 {
1317 for (NETSIM_ID i = 1; i <= NETWORK->nDeviceCount; i++)
1318 {
1319 if (d == i) continue;
1320 for (NETSIM_ID j = 1; j <= DEVICE(i)->nNumOfInterface; j++)
1321 {
1322 if (!isLTENR_RANInterface(i, j)) continue;
1323
1324 if (isGNB(i, j))
1325 {
1326 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(i, j);
1327 ptrLTENR_ASSOCIATEDUEPHYINFO info = LTENR_ASSOCIATEDUEPHYINFO_GET(i, j, d, in);
1328 if (info) fn_NetSim_UPDATE_SPECTRAL_EFFICIENCY_INFO(i, j, d, in);
1329 }
1330 }
1331 }
1332 }
1333 }
1334}
1335
1336#pragma region ACTIVE_UE_LIST
1337
1338#pragma region INITIAL_UE_LIST_ADD
1339 void LTENR_form_active_ue_list(NETSIM_ID gnbId, NETSIM_ID gnbIf, int CA_ID)
1340{
1341 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);
1342
1343 ptrLTENR_SPECTRUMCONFIG sc = phy->spectrumConfig;
1344 ptrLTENR_CA ca = sc->CA[CA_ID];
1345
1346 for (NETSIM_ID i = 1; i <= NETWORK->nDeviceCount; i++)
1347 {
1348 for (NETSIM_ID in = 1; in <= DEVICE(i)->nNumOfInterface; in++)
1349 {
1350 if (!isLTE_NRInterface(i, in))
1351 continue;
1352
1353 if (isUE(i, in)) {
1354 if (LTENR_ISASSOCIATED(gnbId, gnbIf, i, in)) {
1355
1356 ptrLTENR_UEPHY ue_phy = LTENR_UEPHY_GET(i, in);
1357
1358 if (ue_phy->first_active_bwp_id == ca->bwp_id) {
1359
1360 ptrLTENR_CA_UE_LIST active_ue = calloc(1, sizeof * active_ue);
1361 active_ue->ue_id = i;
1362 active_ue->ue_in = in;
1363
1364 if (ca->ue_list) {
1365 ptrLTENR_CA_UE_LIST ue = ca->ue_list;
1366 while (ue->next) ue = ue->next;
1367 ue->next = active_ue;
1368 }
1369 else
1370 ca->ue_list = active_ue;
1371 }
1372 }
1373 }
1374 }
1375 }
1376}
1377#pragma endregion
1378
1379#pragma region ACTIVEUE_INFO_ADD
1380 void LTENR_ACTIVEUEINFO_ADD(NETSIM_ID ueId, NETSIM_ID ueIf, NETSIM_ID gnbId, NETSIM_ID gnbIf, int CA_ID)
1381 {
1382 // to get ca
1383 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);
1384 ptrLTENR_SPECTRUMCONFIG sc = phy->spectrumConfig;
1385 ptrLTENR_CA ca = sc->CA[CA_ID];
1386
1387 // to store new UE id
1388 ptrLTENR_CA_UE_LIST ue_info = calloc(1, sizeof * ue_info);
1389 ue_info->ue_id = ueId;
1390 ue_info->ue_in = ueIf;
1391
1392 // to add new ue to ue list
1393 if (ca->ue_list) {
1394 ptrLTENR_CA_UE_LIST ue = ca->ue_list;
1395 while (ue->next) ue = ue->next;
1396 ue->next = ue_info;
1397 }
1398 else
1399 ca->ue_list = ue_info;
1400 }
1401#pragma endregion
1402
1403#pragma region ACTIVEUE_INFO_REMOVE
1404 void LTENR_ACTIVEUEINFO_REMOVE(NETSIM_ID ueId, NETSIM_ID ueIf, NETSIM_ID gnbId, NETSIM_ID gnbIf, int CA_ID){
1405
1406 // for ca
1407 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);//to get ca
1408 ptrLTENR_SPECTRUMCONFIG sc = phy->spectrumConfig;
1409 ptrLTENR_CA ca = sc->CA[CA_ID];
1410
1411 // to get ue list
1412 ptrLTENR_UEPHY ue_phy = LTENR_UEPHY_GET(ueId, ueIf);
1413 ptrLTENR_CA_UE_LIST ca_ue_info = ca->ue_list;
1414 ptrLTENR_CA_UE_LIST p = NULL;
1415
1416 while (ca_ue_info) {
1417 if (ca_ue_info->ue_id == ueId &&
1418 ca_ue_info->ue_in == ueIf)
1419 {
1420 if (!p)
1421 {
1422 ca->ue_list = ca_ue_info->next;
1423 free(ca_ue_info);
1424 break;
1425 }
1426 else
1427 {
1428 p->next = ca_ue_info->next;
1429 free(ca_ue_info);
1430 break;
1431 }
1432 }
1433 p = ca_ue_info;
1434 ca_ue_info = ca_ue_info->next;
1435 }
1436 }
1437#pragma endregion
1438
1439#pragma region ACTIVEUE_INFO_FIND
1440 //ptrLTENR_CA_UE_LIST LTENR_ACTIVEUEINFO_FIND(NETSIM_ID ueId, NETSIM_ID ueIf, NETSIM_ID gnbId, NETSIM_ID gnbIf, int CA_ID) {
1441
1442 // ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(gnbId, gnbIf);//to get ca
1443 // ptrLTENR_SPECTRUMCONFIG sc = phy->spectrumConfig;
1444 // ptrLTENR_CA ca = sc->CA[CA_ID];
1445
1446 // ptrLTENR_UEPHY ue_phy = LTENR_UEPHY_GET(ueId, ueIf); // to get ue->list
1447 // ptrLTENR_CA_UE_LIST info = ca->ue_list;
1448 // ptrLTENR_CA_UE_LIST p = NULL;
1449
1450 //if (!ueId)
1451 // return info;
1452
1453 //while (info)
1454 //{
1455 // if (info->ue_id == ueId)
1456 // {
1457 // return info;
1458 // if (!ueIf)
1459 // return info;
1460 // else if (info->ue_in == ueIf)
1461 // return info;
1462 // }
1463 // info = info->next;
1464 //}
1465 //return NULL;
1466 //}
1467#pragma endregion
1468
1469#pragma endregion
1470
1471 ptrLTENR_BwpSwitch LTENR_BWP_Switch(ptrLTENR_SCHEDULERINFO schedulerInfo, ptrLTENR_UESCHEDULERINFO curr, UINT PRB_needed) {
1472
1473 ptrLTENR_GNBPHY phy = LTENR_GNBPHY_GET(schedulerInfo->gnbId, schedulerInfo->gnbIf);
1474 UINT CA_ID = phy->currentFrameInfo->Current_CA_ID;
1475 ptrLTENR_CA ca_old = phy->spectrumConfig->CA[CA_ID];
1476 UINT max = 0;
1477 UINT ca_max = 0;
1478
1479 ptrLTENR_BwpSwitch bwp_switch = calloc(1, sizeof * bwp_switch);;
1480
1481 if (ca_old->isBWPEnabled) {
1482 for (UINT i = 0; i < phy->ca_count; i++) {
1483 if (CA_ID <= i) {
1484 //switch for ca id higher
1485 ptrLTENR_CA ca = phy->spectrumConfig->CA[i];
1486 ptrLTENR_SPECTRUMCONFIG sc = phy->spectrumConfig;
1487
1488 bwp_switch->ca_new = true;
1489
1490 if (ca->PRBCount >= PRB_needed) {
1491 bwp_switch->bwp_active = true;
1492 LTENR_ACTIVEUEINFO_REMOVE(curr->ueId, curr->ueIf, schedulerInfo->gnbId, schedulerInfo->gnbIf, CA_ID);
1493 LTENR_ACTIVEUEINFO_ADD(curr->ueId, curr->ueIf, schedulerInfo->gnbId, schedulerInfo->gnbIf, i);
1494 return bwp_switch;
1495 }
1496 else
1497 {
1498 if (ca->PRBCount > max)
1499 {
1500 max = ca->PRBCount;
1501 ca_max = i;
1502 }
1503 }
1504 }
1505 else if (CA_ID > i) {
1506 // old greater than new
1507 ptrLTENR_CA ca = phy->spectrumConfig->CA[i];
1508 ptrLTENR_SPECTRUMCONFIG sc = phy->spectrumConfig;
1509
1510 bwp_switch->ca_new = false;
1511
1512 if (ca->PRBCount >= PRB_needed) {
1513 bwp_switch->bwp_active = true;
1514 bwp_switch->prb_count = ca->PRBCount;
1515 LTENR_ACTIVEUEINFO_REMOVE(curr->ueId, curr->ueIf, schedulerInfo->gnbId, schedulerInfo->gnbIf, CA_ID);
1516 LTENR_ACTIVEUEINFO_ADD(curr->ueId, curr->ueIf, schedulerInfo->gnbId, schedulerInfo->gnbIf, i);
1517 return bwp_switch;
1518 }
1519 else
1520 {
1521 if (ca->PRBCount > max)
1522 {
1523 max = ca->PRBCount;
1524 ca_max = i;
1525 }
1526 }
1527
1528 }
1529 }
1530
1531 //after for
1532 if (ca_max != CA_ID)
1533 {
1534 bwp_switch->bwp_active = true;
1535 LTENR_ACTIVEUEINFO_REMOVE(curr->ueId, curr->ueIf, schedulerInfo->gnbId, schedulerInfo->gnbIf, CA_ID);
1536 LTENR_ACTIVEUEINFO_ADD(curr->ueId, curr->ueIf, schedulerInfo->gnbId, schedulerInfo->gnbIf, ca_max);
1537 return bwp_switch;
1538 }
1539 else
1540 {
1541 bwp_switch->bwp_active = false;
1542 bwp_switch->prb_count = 0;
1543 return bwp_switch;
1544 }
1545
1546 }
1547 else if (!ca_old->isBWPEnabled)
1548 {
1549 bwp_switch->bwp_active = false;
1550 bwp_switch->prb_count = 0;
1551 return bwp_switch;
1552 }
1553 return NULL;
1554 }
1555
1556#pragma region PHYOUT
1557 static void LTENR_PhyOut_HandleBroadCast()
1558 {
1559 NetSim_PACKET* packet = pstruEventDetails->pPacket;
1560 NETSIM_ID d = pstruEventDetails->nDeviceId;
1561 NETSIM_ID in = pstruEventDetails->nInterfaceId;
1562 NETSIM_ID r = packet->nReceiverId;
1563
1564 for (r = 0; r < NETWORK->nDeviceCount; r++)
1565 {
1566 if (d == r + 1)
1567 continue;
1568
1569 for (NETSIM_ID rin = 0; rin < DEVICE(r + 1)->nNumOfInterface; rin++)
1570 {
1571 if (!isLTE_NRInterface(r + 1, rin + 1))
1572 continue;
1573
1574 ptrLTENR_PROTODATA data = LTENR_PROTODATA_GET(r + 1, rin + 1);
1575 if (data->isDCEnable) {
1576 if (data->MasterCellType == MMWAVE_CELL_TYPE) {
1577 if (fn_NetSim_isDeviceLTENR(r + 1, rin + 1)) {
1578 if (!fn_NetSim_isDeviceLTENR(d, in))
1579 continue;
1580 }
1581 else {
1582 continue;
1583 }
1584 }
1585 else {
1586 if (!fn_NetSim_isDeviceLTENR(r + 1, rin + 1)) {
1587 if (fn_NetSim_isDeviceLTENR(d, in))
1588 continue;
1589 }
1590 else {
1591 continue;
1592 }
1593 }
1594 }
1595 switch (data->deviceType)
1596 {
1597 case LTENR_DEVICETYPE_UE:
1598 {
1599 double endTime = LTENR_PHY_GetSlotEndTime(d, in);
1600 NetSim_PACKET* p = fn_NetSim_Packet_CopyPacket(packet);
1601
1602 p->pstruPhyData->dArrivalTime = pstruEventDetails->dEventTime;
1603 p->pstruPhyData->dEndTime = endTime - 1;
1604 p->pstruPhyData->dPacketSize = p->pstruMacData->dPacketSize;
1605 p->pstruPhyData->dPayload = p->pstruMacData->dPacketSize;
1606 p->pstruPhyData->dStartTime = pstruEventDetails->dEventTime;
1607 p->pstruMacData->Packet_MACProtocol = NULL;
1608 p->pstruMacData->Packet_MACProtocol = LTENR_MSG_COPY(packet);
1609
1610 pstruEventDetails->pPacket = p;
1611
1612 pstruEventDetails->dEventTime = endTime - 1;
1613 pstruEventDetails->nEventType = PHYSICAL_IN_EVENT;
1614 pstruEventDetails->nDeviceId = r + 1;
1615 pstruEventDetails->nDeviceType = DEVICE_TYPE(r + 1);
1616 pstruEventDetails->nInterfaceId = rin + 1;
1617 pstruEventDetails->pPacket->nTransmitterId = d;
1618 pstruEventDetails->pPacket->nReceiverId = r + 1;
1619
1620 fnpAddEvent(pstruEventDetails);
1621 }
1622 break;
1623 default:
1624 break;
1625 }
1626 }
1627 }
1628
1629 fn_NetSim_Packet_FreePacket(packet);
1630 pstruEventDetails->pPacket = NULL;
1631 }
1632
1633 static void LTENR_PhyOut_HandleUnicast()
1634 {
1635 NetSim_PACKET* packet = pstruEventDetails->pPacket;
1636 NETSIM_ID d = pstruEventDetails->nDeviceId;
1637 NETSIM_ID in = pstruEventDetails->nInterfaceId;
1638 NETSIM_ID r = packet->nReceiverId;
1639 NETSIM_ID rin = LTENR_FIND_ASSOCIATEINTERFACE(d, in, r);
1640
1641 if (rin == 0)
1642 {
1643 fn_NetSim_Packet_FreePacket(packet);
1644 return;
1645 }
1646
1647 double endTime = LTENR_PHY_GetSlotEndTime(d, in);
1648
1649 packet->pstruPhyData->dArrivalTime = pstruEventDetails->dEventTime;
1650 packet->pstruPhyData->dEndTime = endTime - 1;
1651 packet->pstruPhyData->dPacketSize = packet->pstruMacData->dPacketSize;
1652 packet->pstruPhyData->dPayload = packet->pstruMacData->dPacketSize;
1653 packet->pstruPhyData->dStartTime = pstruEventDetails->dEventTime;
1654
1655 pstruEventDetails->dEventTime = endTime - 1;
1656 pstruEventDetails->nEventType = PHYSICAL_IN_EVENT;
1657 pstruEventDetails->nDeviceId = r;
1658 pstruEventDetails->nDeviceType = DEVICE_TYPE(r);
1659 pstruEventDetails->nInterfaceId = rin;
1660 fnpAddEvent(pstruEventDetails);
1661 }
1662
1663 void fn_NetSim_LTENR_HandlePhyOut()
1664 {
1665 NetSim_PACKET* packet = pstruEventDetails->pPacket;
1666 NETSIM_ID r = packet->nReceiverId;
1667 if (isNTNScenario())
1668 {
1669 if (r == 0) LTENR_NTN_PhyOut_HandleBroadCast();
1670 else LTENR_NTN_PhyOut_HandleUnicast();
1671 }
1672 else
1673 {
1674 if (r == 0) LTENR_PhyOut_HandleBroadCast();
1675 else LTENR_PhyOut_HandleUnicast();
1676 }
1677 }
1678#pragma endregion
double txPower_dbm
Transmitter power.