O-RAN E Maintenance Release contribution for ODULOW
[o-du/phy.git] / fapi_5g / source / api / fapi2phy / p7 / nr5g_fapi_proc_dl_tti_req.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 Intel.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19 /**
20  * @file
21  * This file consist of implementation of FAPI DL_TTI.request message.
22  *
23  **/
24 #include <rte_memcpy.h>
25 #include "nr5g_fapi_framework.h"
26 #include "gnb_l1_l2_api.h"
27 #include "nr5g_fapi_dpdk.h"
28 #include "nr5g_fapi_fapi2mac_api.h"
29 #include "nr5g_fapi_fapi2phy_api.h"
30 #include "nr5g_fapi_fapi2phy_p7_proc.h"
31 #include "nr5g_fapi_fapi2phy_p7_pvt_proc.h"
32 #include "nr5g_fapi_memory.h"
33
34 /** @ingroup group_source_api_p5_fapi2phy_proc
35  *
36  *  @param[in]  p_phy_instance Pointer to PHY instance.
37  *  @param[in]  p_fapi_req Pointer to FAPI DL_TTI.request message structure.
38  *  
39  *  @return     Returns ::SUCCESS and ::FAILURE.
40  *
41  *  @description
42  *  This message indicates the control information for a downlink slot. 
43  *
44 **/
45 uint8_t nr5g_fapi_dl_tti_request(
46     bool is_urllc,
47     p_nr5g_fapi_phy_instance_t p_phy_instance,
48     fapi_dl_tti_req_t * p_fapi_req,
49     fapi_vendor_msg_t * p_fapi_vendor_msg)
50 {
51     PDLConfigRequestStruct p_ia_dl_config_req;
52     PMAC2PHY_QUEUE_EL p_list_elem;
53     nr5g_fapi_stats_t *p_stats;
54
55     if (NULL == p_phy_instance) {
56         NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI.request] Invalid " "Phy Instance"));
57         return FAILURE;
58     }
59
60     p_stats = &p_phy_instance->stats;
61     p_stats->fapi_stats.fapi_dl_tti_req++;
62
63     if (NULL == p_fapi_req) {
64         NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI.request] Invalid fapi " "message"));
65         return FAILURE;
66     }
67
68     p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
69         MSG_TYPE_PHY_DL_CONFIG_REQ, 1,
70         (uint32_t) sizeof(DLConfigRequestStruct));
71     if (!p_list_elem) {
72         NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI.request] Unable to create "
73                 "list element. Out of memory!!!"));
74         return FAILURE;
75     }
76
77     p_ia_dl_config_req = (PDLConfigRequestStruct) (p_list_elem + 1);
78     if (FAILURE == nr5g_fapi_dl_tti_req_to_phy_translation(p_phy_instance,
79             p_fapi_req, p_fapi_vendor_msg, p_ia_dl_config_req)) {
80         nr5g_fapi_fapi2phy_destroy_api_list_elem(p_list_elem);
81         NR5G_FAPI_LOG(DEBUG_LOG, ("[DL_TTI.request][%d][%d,%d] Not Sent",
82                 p_phy_instance->phy_id, p_ia_dl_config_req->sSFN_Slot.nSFN,
83                 p_ia_dl_config_req->sSFN_Slot.nSlot));
84         return FAILURE;
85     }
86     /* Add element to send list */
87     nr5g_fapi_fapi2phy_add_to_api_list(is_urllc, p_list_elem);
88
89     p_stats->iapi_stats.iapi_dl_config_req++;
90     NR5G_FAPI_LOG(DEBUG_LOG, ("[DL_TTI.request][%u][%u,%u,%u] is_urllc %u",
91         p_phy_instance->phy_id,
92         p_ia_dl_config_req->sSFN_Slot.nSFN, p_ia_dl_config_req->sSFN_Slot.nSlot,
93         p_ia_dl_config_req->sSFN_Slot.nSym, is_urllc));
94
95     return SUCCESS;
96 }
97
98  /** @ingroup group_source_api_p7_fapi2phy_proc
99  *
100  *  @param[in]   p_fapi_req Pointer to FAPI DL_TTI.request structure.
101  *  @param[out]  p_ia_dl_config_req Pointer to IAPI DL_TTI.request structure.
102  *  
103  *  @return     Returns ::SUCCESS and ::FAILURE.
104  *
105  *  @description
106  *  This function converts FAPI DL_TTI.request to IAPI DL_Config.request
107  *  structure.
108  *
109 **/
110 uint8_t nr5g_fapi_dl_tti_req_to_phy_translation(
111     p_nr5g_fapi_phy_instance_t p_phy_instance,
112     fapi_dl_tti_req_t * p_fapi_req,
113     fapi_vendor_msg_t * p_fapi_vendor_msg,
114     PDLConfigRequestStruct p_phy_req)
115 {
116     int idx = 0, nDCI = 0, jdx = 0;
117     uint32_t pdsch_size, pdcch_size, pbch_size, csirs_size, total_size;
118     nr5g_fapi_stats_t *p_stats;
119
120     fapi_dl_tti_req_pdu_t *p_fapi_dl_tti_req_pdu = NULL;
121     fapi_dl_pdcch_pdu_t *p_pdcch_pdu = NULL;
122     fapi_dl_pdsch_pdu_t *p_pdsch_pdu = NULL;
123     fapi_dl_csi_rs_pdu_t *p_csi_rs_pdu = NULL;
124     fapi_dl_ssb_pdu_t *p_ssb_pdu = NULL;
125     fapi_ue_info_t *p_ueGrpInfo = NULL;
126
127     PPDUStruct pPduStruct = NULL;
128     PDLSCHPDUStruct p_dlsch_pdu = NULL;
129     PDCIPDUStruct p_dci_pdu = NULL;
130     PBCHPDUStruct p_bch_pdu = NULL;
131     PCSIRSPDUStruct pCSIRSPdu = NULL;
132     PPDSCHGroupInfoStruct pPDSCHGroupInfoStruct = NULL;
133
134     total_size = sizeof(DLConfigRequestStruct);
135     pdsch_size = RUP32B(sizeof(DLSCHPDUStruct));
136     pdcch_size = RUP32B(sizeof(DCIPDUStruct));
137     pbch_size = RUP32B(sizeof(BCHPDUStruct));
138     csirs_size = RUP32B(sizeof(CSIRSPDUStruct));
139
140     p_stats = &p_phy_instance->stats;
141     NR5G_FAPI_MEMSET(p_phy_req, sizeof(DLConfigRequestStruct), 0, total_size);
142     p_phy_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_DL_CONFIG_REQ;
143     p_phy_req->sSFN_Slot.nCarrierIdx = p_phy_instance->phy_id;
144     p_phy_req->nGroup = p_fapi_req->nGroup;
145     p_phy_req->nPDU = p_fapi_req->nPdus;
146     p_phy_req->sSFN_Slot.nSFN = p_fapi_req->sfn;
147     p_phy_req->sSFN_Slot.nSlot = p_fapi_req->slot;
148
149     for (idx = 0; idx < p_phy_req->nGroup; ++idx) {
150         p_ueGrpInfo = &p_fapi_req->ue_grp_info[idx];
151         pPDSCHGroupInfoStruct = &p_phy_req->sPDSCHGroupInfoStruct[idx];
152         pPDSCHGroupInfoStruct->nUE = p_ueGrpInfo->nUe;
153         pPDSCHGroupInfoStruct->rsv1[0] = 0;
154         pPDSCHGroupInfoStruct->rsv1[1] = 0;
155         pPDSCHGroupInfoStruct->rsv1[2] = 0;
156         for (jdx = 0; jdx < p_ueGrpInfo->nUe; ++jdx) {
157             pPDSCHGroupInfoStruct->nPduIdx[jdx] = p_ueGrpInfo->pduIdx[jdx];
158         }
159     }
160
161     pPduStruct = p_phy_req->sDLPDU;
162     for (idx = 0; idx < p_phy_req->nPDU; ++idx) {
163         p_stats->fapi_stats.fapi_dl_tti_pdus++;
164         p_fapi_dl_tti_req_pdu = &p_fapi_req->pdus[idx];
165         switch (p_fapi_dl_tti_req_pdu->pduType) {
166             case FAPI_PDCCH_PDU_TYPE:
167                 nDCI++;
168                 p_dci_pdu = (PDCIPDUStruct) pPduStruct;
169                 NR5G_FAPI_MEMSET(p_dci_pdu, RUP32B(sizeof(DCIPDUStruct)), 0,
170                     pdcch_size);
171                 p_pdcch_pdu = &p_fapi_dl_tti_req_pdu->pdu.pdcch_pdu;
172                 p_dci_pdu->sPDUHdr.nPDUType = DL_PDU_TYPE_DCI;
173                 p_dci_pdu->sPDUHdr.nPDUSize = pdcch_size;
174                 total_size += pdcch_size;
175                 nr5g_fapi_fill_dci_pdu(p_phy_instance, p_pdcch_pdu, p_dci_pdu);
176                 break;
177
178             case FAPI_PDSCH_PDU_TYPE:
179                 p_dlsch_pdu = (PDLSCHPDUStruct) pPduStruct;
180                 p_pdsch_pdu = &p_fapi_dl_tti_req_pdu->pdu.pdsch_pdu;
181                 NR5G_FAPI_MEMSET(p_dlsch_pdu, RUP32B(sizeof(DLSCHPDUStruct)), 0,
182                     pdsch_size);
183                 p_dlsch_pdu->sPDUHdr.nPDUType = DL_PDU_TYPE_DLSCH;
184                 p_dlsch_pdu->sPDUHdr.nPDUSize = pdsch_size;
185                 total_size += pdsch_size;
186                 nr5g_fapi_fill_pdsch_pdu(p_phy_instance, p_pdsch_pdu, p_dlsch_pdu);
187                 break;
188
189             case FAPI_PBCH_PDU_TYPE:
190                 p_bch_pdu = (PBCHPDUStruct) pPduStruct;
191                 p_ssb_pdu = &p_fapi_dl_tti_req_pdu->pdu.ssb_pdu;
192                 NR5G_FAPI_MEMSET(p_bch_pdu, RUP32B(sizeof(BCHPDUStruct)), 0,
193                     pbch_size);
194                 p_bch_pdu->sPDUHdr.nPDUType = DL_PDU_TYPE_PBCH;
195                 p_bch_pdu->sPDUHdr.nPDUSize = pbch_size;
196                 total_size += pbch_size;
197                 nr5g_fapi_fill_ssb_pdu(p_phy_instance, p_bch_pdu, p_ssb_pdu);
198                 break;
199
200             case FAPI_CSIRS_PDU_TYPE:
201                 pCSIRSPdu = (PCSIRSPDUStruct) pPduStruct;
202                 p_csi_rs_pdu = &p_fapi_dl_tti_req_pdu->pdu.csi_rs_pdu;
203                 NR5G_FAPI_MEMSET(pCSIRSPdu, RUP32B(sizeof(CSIRSPDUStruct)), 0,
204                     csirs_size);
205                 pCSIRSPdu->sPDUHdr.nPDUType = DL_PDU_TYPE_CSIRS;
206                 pCSIRSPdu->sPDUHdr.nPDUSize = csirs_size;
207                 total_size += csirs_size;
208                 nr5g_fapi_fill_csi_rs_pdu(p_phy_instance, p_csi_rs_pdu, pCSIRSPdu);
209                 break;
210
211             default:
212                 NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI] Invalid Pdu Type: %d",
213                         pPduStruct->nPDUType));
214                 return FAILURE;
215         }
216         pPduStruct =
217             (PDUStruct *) ((uint8_t *) pPduStruct + pPduStruct->nPDUSize);
218         p_stats->iapi_stats.iapi_dl_tti_pdus++;
219     }
220
221     p_phy_req->nDCI = nDCI;
222     p_phy_req->sMsgHdr.nMessageLen = total_size;
223
224     if (NULL != p_fapi_vendor_msg)
225     {
226         nr5g_fapi_dl_tti_req_to_phy_translation_vendor_ext(p_phy_instance,
227                                                            p_fapi_vendor_msg,
228                                                            p_phy_req);
229     }
230
231     return SUCCESS;
232 }
233
234  /** @ingroup group_source_api_p5_fapi2phy_proc
235  *
236  *  @param[in]   p_fapi_vendor_msg  Pointer to FAPI DL_TTI.request vendor message.
237  *  @param[out]  p_ia_dl_config_req Pointer to IAPI DL_TTI.request structure.
238  *
239  *  @return     no return.
240  *
241  *  @description
242  *  This function fills fields for DL_TTI.request structure that come from
243  *  a vendor extension.
244  *
245 **/
246 void nr5g_fapi_dl_tti_req_to_phy_translation_vendor_ext(
247     p_nr5g_fapi_phy_instance_t p_phy_instance,
248     fapi_vendor_msg_t * p_fapi_vendor_msg,
249     PDLConfigRequestStruct p_phy_req)
250 {
251     int idx = 0;
252
253     fapi_vendor_dl_tti_req_t *p_vendor_dl_tti_req = NULL;
254     fapi_vendor_dl_pdcch_pdu_t *p_vendor_pdcch_pdu = NULL;
255     fapi_vendor_dl_pdsch_pdu_t *p_vendor_pdsch_pdu = NULL;
256     fapi_vendor_csi_rs_pdu_t *p_vendor_csi_rs_pdu = NULL;
257
258     PPDUStruct pPduStruct = NULL;
259     PDCIPDUStruct p_dci_pdu = NULL;
260     PDLSCHPDUStruct p_dlsch_pdu = NULL;
261     PCSIRSPDUStruct p_CSIRS_pdu = NULL;
262
263     p_vendor_dl_tti_req = &p_fapi_vendor_msg->p7_req_vendor.dl_tti_req;
264
265     p_phy_req->sSFN_Slot.nSym = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.sym;
266
267     p_phy_req->nLte_CRS_Present = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.lte_crs_present;
268     p_phy_req->nLte_CRS_carrierFreqDL = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.lte_crs_carrier_freq_dl;
269     p_phy_req->nLte_CRS_carrierBandwidthDL = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.lte_crs_carrier_bandwidth_dl;
270     p_phy_req->nLte_CRS_nrofCRS_Ports = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.lte_crs_nr_of_crs_ports;
271     p_phy_req->nLte_CRS_v_shift = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.lte_crs_v_shift;
272     p_phy_req->nPdcchPrecoderEn = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.pdcch_precoder_en;
273     p_phy_req->nSSBPrecoderEn = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.ssb_precoder_en;
274
275     pPduStruct = p_phy_req->sDLPDU;
276     for (idx = 0; idx < p_phy_req->nPDU; ++idx) {
277         switch (pPduStruct->nPDUType) {
278             case DL_PDU_TYPE_DCI: 
279                 p_dci_pdu = (PDCIPDUStruct) pPduStruct;
280                 p_vendor_pdcch_pdu =
281                     &p_vendor_dl_tti_req->pdus[idx].pdu.pdcch_pdu;
282
283                 if (USE_VENDOR_EPREXSSB == p_phy_instance->phy_config.use_vendor_EpreXSSB)
284                 {
285                     p_dci_pdu->nEpreRatioOfPDCCHToSSB =
286                         p_vendor_pdcch_pdu->dl_dci[0].epre_ratio_of_pdcch_to_ssb;
287                     p_dci_pdu->nEpreRatioOfDmrsToSSB =
288                         p_vendor_pdcch_pdu->dl_dci[0].epre_ratio_of_dmrs_to_ssb;
289                 }
290                 break;
291
292             case DL_PDU_TYPE_DLSCH:
293                 p_dlsch_pdu = (PDLSCHPDUStruct) pPduStruct;
294                 p_vendor_pdsch_pdu =
295                     &p_vendor_dl_tti_req->pdus[idx].pdu.pdsch_pdu;
296
297                 p_dlsch_pdu->nNrOfAntennaPorts = p_vendor_pdsch_pdu->nr_of_antenna_ports;
298
299                 if (USE_VENDOR_EPREXSSB == p_phy_instance->phy_config.use_vendor_EpreXSSB)
300                 {
301                     p_dlsch_pdu->nEpreRatioOfDmrsToSSB =
302                         p_vendor_pdsch_pdu->epre_ratio_of_dmrs_to_ssb;
303                     p_dlsch_pdu->nEpreRatioOfPDSCHToSSB =
304                         p_vendor_pdsch_pdu->epre_ratio_of_pdsch_to_ssb;
305                 }
306
307                 NR5G_FAPI_MEMCPY(p_dlsch_pdu->nTxRUIdx, sizeof(p_dlsch_pdu->nTxRUIdx),
308                     p_vendor_pdsch_pdu->tx_ru_idx, sizeof(p_vendor_pdsch_pdu->tx_ru_idx));
309                 break;
310
311             case DL_PDU_TYPE_PBCH:
312                 // No vendor ext
313                 break;
314
315             case DL_PDU_TYPE_CSIRS:
316                 p_CSIRS_pdu = (PCSIRSPDUStruct) pPduStruct;
317                 p_vendor_csi_rs_pdu = &p_vendor_dl_tti_req->pdus[idx].pdu.csi_rs_pdu;
318
319                 if (USE_VENDOR_EPREXSSB == p_phy_instance->phy_config.use_vendor_EpreXSSB)
320                 {
321                     p_CSIRS_pdu->nEpreRatioToSSB = p_vendor_csi_rs_pdu->epre_ratio_to_ssb;
322                 }
323                 break;
324
325             default:
326                 NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI] Invalid Pdu Type: %d",
327                         pPduStruct->nPDUType));
328                 return;
329         }
330         pPduStruct =
331             (PDUStruct *) ((uint8_t *) pPduStruct + pPduStruct->nPDUSize);
332     }
333 }
334
335 /** @ingroup group_nr5g_test_config
336  *
337  *  @param[in]   p_pdcch_pdu
338  *  @param[out]  p_dci_pdu
339  *
340  *  @return      void
341  *
342  *  @description
343  *  This function fills IAPI DCIPdu from FAPI PDCCH Pdu
344  *
345 **/
346 void nr5g_fapi_fill_dci_pdu(
347     p_nr5g_fapi_phy_instance_t p_phy_instance,
348     fapi_dl_pdcch_pdu_t * p_pdcch_pdu,
349     PDCIPDUStruct p_dci_pdu)
350 {
351     nr5g_fapi_stats_t *p_stats = NULL;
352
353     p_stats = &p_phy_instance->stats;
354     p_stats->fapi_stats.fapi_dl_tti_pdcch_pdus++;
355
356     p_dci_pdu->nBWPSize = p_pdcch_pdu->bwpSize;
357     p_dci_pdu->nBWPStart = p_pdcch_pdu->bwpStart;
358     p_dci_pdu->nSubcSpacing = p_pdcch_pdu->subCarrierSpacing;
359     p_dci_pdu->nCpType = p_pdcch_pdu->cyclicPrefix;
360     p_dci_pdu->nCCEStartIndex = p_pdcch_pdu->startSymbolIndex;
361     p_dci_pdu->nNrOfSymbols = p_pdcch_pdu->durationSymbols;
362     p_dci_pdu->nStartSymbolIndex = p_pdcch_pdu->startSymbolIndex;
363     p_dci_pdu->nFreqDomain[0] = ((uint32_t) p_pdcch_pdu->freqDomainResource[0] |
364         (((uint32_t) p_pdcch_pdu->freqDomainResource[1]) << 8) |
365         (((uint32_t) p_pdcch_pdu->freqDomainResource[2]) << 16) |
366         (((uint32_t) p_pdcch_pdu->freqDomainResource[3]) << 24));
367     p_dci_pdu->nFreqDomain[1] = ((uint32_t) p_pdcch_pdu->freqDomainResource[4] |
368         (((uint32_t) p_pdcch_pdu->freqDomainResource[5]) << 8));
369     p_dci_pdu->nCCEToREGType = p_pdcch_pdu->cceRegMappingType;
370     p_dci_pdu->nREGBundleSize = p_pdcch_pdu->regBundleSize;
371     p_dci_pdu->nInterleaveSize = p_pdcch_pdu->interleaverSize;
372     p_dci_pdu->nShift = p_pdcch_pdu->shiftIndex;
373     p_dci_pdu->nCoreSetType = p_pdcch_pdu->coreSetType;
374     p_dci_pdu->nCCEStartIndex = p_pdcch_pdu->dlDci[0].cceIndex;
375     p_dci_pdu->nAggrLvl = p_pdcch_pdu->dlDci[0].aggregationLevel;
376     p_dci_pdu->nScid = p_pdcch_pdu->dlDci[0].scramblingId;
377     p_dci_pdu->nID = p_pdcch_pdu->dlDci[0].scramblingId;
378     p_dci_pdu->nRNTIScramb = p_pdcch_pdu->dlDci[0].scramblingRnti;
379     p_dci_pdu->nRNTI = p_pdcch_pdu->dlDci[0].rnti;
380     p_dci_pdu->nTotalBits = p_pdcch_pdu->dlDci[0].payloadSizeBits;
381
382     if (USE_VENDOR_EPREXSSB != p_phy_instance->phy_config.use_vendor_EpreXSSB) {
383     p_dci_pdu->nEpreRatioOfPDCCHToSSB =
384         nr5g_fapi_calculate_nEpreRatioOfPDCCHToSSB(p_pdcch_pdu->
385         dlDci[0].beta_pdcch_1_0);
386     p_dci_pdu->nEpreRatioOfDmrsToSSB =
387             nr5g_fapi_calculate_nEpreRatioOfDmrsToSSB(p_pdcch_pdu->
388                 dlDci[0].powerControlOffsetSS);
389     }
390
391     if (FAILURE == NR5G_FAPI_MEMCPY(p_dci_pdu->nDciBits,
392             sizeof(uint8_t) * MAX_DCI_BIT_BYTE_LEN,
393             p_pdcch_pdu->dlDci[0].payload,
394             sizeof(uint8_t) * MAX_DCI_BIT_BYTE_LEN)) {
395         NR5G_FAPI_LOG(ERROR_LOG, ("PDCCH: RNTI: %d -- DCI Bits copy error.",
396                 p_pdcch_pdu->dlDci[0].rnti));
397     }
398     p_stats->iapi_stats.iapi_dl_tti_pdcch_pdus++;
399 }
400
401 /** @ingroup group_nr5g_test_config
402  *
403  *  @param[in]    p_pdsch_pdu
404  *  @param[out]   p_dlsch_pdu
405  *
406  *  @return      void
407  *
408  *  @description
409  *  This function fills FAPI PDSCH Pdu from IAPI DLSCHPDU
410  *
411 **/
412 void nr5g_fapi_fill_pdsch_pdu(
413     p_nr5g_fapi_phy_instance_t p_phy_instance,
414     fapi_dl_pdsch_pdu_t * p_pdsch_pdu,
415     PDLSCHPDUStruct p_dlsch_pdu)
416 {
417     uint8_t idx, port_index = 0;
418     nr5g_fapi_stats_t *p_stats;
419
420     p_stats = &p_phy_instance->stats;
421     p_stats->fapi_stats.fapi_dl_tti_pdsch_pdus++;
422
423     p_dlsch_pdu->nBWPSize = p_pdsch_pdu->bwpSize;
424     p_dlsch_pdu->nBWPStart = p_pdsch_pdu->bwpStart;
425     p_dlsch_pdu->nSubcSpacing = p_pdsch_pdu->subCarrierSpacing;
426     p_dlsch_pdu->nCpType = p_pdsch_pdu->cyclicPrefix;
427     p_dlsch_pdu->nRNTI = p_pdsch_pdu->rnti;
428     p_dlsch_pdu->nUEId = p_pdsch_pdu->pdu_index;
429
430     // Codeword Information
431     p_dlsch_pdu->nNrOfCodeWords = p_pdsch_pdu->nrOfCodeWords;
432     p_dlsch_pdu->nMCS[0] = p_pdsch_pdu->cwInfo[0].mcsIndex;
433     p_dlsch_pdu->nMcsTable = p_pdsch_pdu->cwInfo[0].mcsTable;
434     p_dlsch_pdu->nRV[0] = p_pdsch_pdu->cwInfo[0].rvIndex;
435     p_dlsch_pdu->nTBSize[0] = p_pdsch_pdu->cwInfo[0].tbSize;
436     if (p_pdsch_pdu->nrOfCodeWords == 2) {
437         p_dlsch_pdu->nMCS[1] = p_pdsch_pdu->cwInfo[1].mcsIndex;
438         p_dlsch_pdu->nRV[1] = p_pdsch_pdu->cwInfo[1].rvIndex;
439         p_dlsch_pdu->nTBSize[1] = p_pdsch_pdu->cwInfo[1].tbSize;
440     }
441     //p_dlsch_pdu->nNrOfAntennaPorts = p_phy_instance->phy_config.n_nr_of_rx_ant;
442     p_dlsch_pdu->nNrOfLayers = p_pdsch_pdu->nrOfLayers;
443     p_dlsch_pdu->nNrOfAntennaPorts = p_dlsch_pdu->nNrOfLayers;
444     p_dlsch_pdu->nTransmissionScheme = p_pdsch_pdu->transmissionScheme;
445     p_dlsch_pdu->nDMRSConfigType = p_pdsch_pdu->dmrsConfigType;
446     p_dlsch_pdu->nNIDnSCID = p_pdsch_pdu->dlDmrsScramblingId;
447     p_dlsch_pdu->nNid = p_pdsch_pdu->dataScramblingId;
448     p_dlsch_pdu->nSCID = p_pdsch_pdu->scid;
449
450     for (idx = 0;
451         (idx < FAPI_MAX_DMRS_PORTS && port_index < p_dlsch_pdu->nNrOfLayers);
452         idx++) {
453         if ((p_pdsch_pdu->dmrsPorts >> idx) && 0x0001) {
454             p_dlsch_pdu->nPortIndex[port_index++] = idx;
455         }
456     }
457
458     // Resource Allocation Information
459     if (FAILURE == NR5G_FAPI_MEMCPY(p_dlsch_pdu->nRBGIndex,
460             sizeof(uint32_t) * MAX_DL_RBG_BIT_NUM,
461             p_pdsch_pdu->rbBitmap, sizeof(uint32_t) * MAX_DL_RBG_BIT_NUM)) {
462         NR5G_FAPI_LOG(ERROR_LOG, ("PDSCH: RNTI: %d Pdu Index: %d -- RB Bitmap"
463                 "cpy error.", p_pdsch_pdu->rnti, p_pdsch_pdu->pdu_index));
464     }
465     p_dlsch_pdu->nResourceAllocType = p_pdsch_pdu->resourceAlloc;
466     p_dlsch_pdu->nRBStart = p_pdsch_pdu->rbStart;
467     p_dlsch_pdu->nRBSize = p_pdsch_pdu->rbSize;
468     p_dlsch_pdu->nPMI = (p_pdsch_pdu->preCodingAndBeamforming.numPrgs > 0)
469         ? p_pdsch_pdu->preCodingAndBeamforming.pmi_bfi[0].pmIdx
470         : 0;
471     p_dlsch_pdu->nVRBtoPRB = p_pdsch_pdu->vrbToPrbMapping;
472     p_dlsch_pdu->nStartSymbolIndex = p_pdsch_pdu->startSymbIndex;
473     p_dlsch_pdu->nNrOfSymbols = p_pdsch_pdu->nrOfSymbols;
474     p_dlsch_pdu->nNrOfCDMs = p_pdsch_pdu->numDmrsCdmGrpsNoData;
475     p_dlsch_pdu->nMappingType = p_pdsch_pdu->mappingType;
476     p_dlsch_pdu->nNrOfDMRSSymbols = p_pdsch_pdu->nrOfDmrsSymbols;
477     p_dlsch_pdu->nDMRSAddPos = p_pdsch_pdu->dmrsAddPos;
478
479     // PTRS Information
480     p_dlsch_pdu->nPTRSTimeDensity = p_pdsch_pdu->ptrsTimeDensity;
481     p_dlsch_pdu->nPTRSFreqDensity = p_pdsch_pdu->ptrsFreqDensity;
482     p_dlsch_pdu->nPTRSReOffset = p_pdsch_pdu->ptrsReOffset;
483     p_dlsch_pdu->nEpreRatioOfPDSCHToPTRS = p_pdsch_pdu->nEpreRatioOfPdschToPtrs;
484
485     if (USE_VENDOR_EPREXSSB != p_phy_instance->phy_config.use_vendor_EpreXSSB) {
486         p_dlsch_pdu->nEpreRatioOfDmrsToSSB =
487             nr5g_fapi_calculate_nEpreRatioOfDmrsToSSB(
488                 p_pdsch_pdu->powerControlOffsetSS);
489         p_dlsch_pdu->nEpreRatioOfPDSCHToSSB =
490             nr5g_fapi_calculate_nEpreRatioOfPDSCHToSSB(
491                 p_pdsch_pdu->powerControlOffset);
492     }
493
494     // PTRS Information
495     p_dlsch_pdu->nPTRSPresent = p_pdsch_pdu->pduBitMap & 0x0001;
496     p_dlsch_pdu->nNrOfPTRSPorts =
497         __builtin_popcount(p_pdsch_pdu->ptrsPortIndex);
498     for (idx = 0; idx < p_dlsch_pdu->nNrOfPTRSPorts &&
499         idx < MAX_DL_PER_UE_PTRS_PORT_NUM; idx++) {
500         p_dlsch_pdu->nPTRSPortIndex[idx] = idx;
501     }
502
503     // Don't Cares
504     p_dlsch_pdu->nNrOfDMRSAssPTRS[0] = 0x1;
505     p_dlsch_pdu->nNrOfDMRSAssPTRS[1] = 0x1;
506     p_dlsch_pdu->n1n2 = 0x201;
507
508     p_dlsch_pdu->nNrofTxRU = port_index;
509
510     p_stats->iapi_stats.iapi_dl_tti_pdsch_pdus++;
511 }
512
513 /** @ingroup group_nr5g_test_config
514  *
515  *  @param[in]  beta_pdcch_1_0
516  *
517  *  @return     uint16_t mapping
518  *
519  *  @description
520  *  This function maps FAPI to IAPI value range.
521  *
522  *
523  * Please refer 5G FAPI-IAPI Translator Module SW Design Document for details on
524  * the mapping.
525  *
526  * |-----------------------------------------|
527  * | nEpreRatioOfPDCCHToSSb | beta_PDCCH_1_0 |
528  * |-----------------------------------------|
529  * |             1          |      0 - 2     |
530  * |          1000          |        3       |
531  * |          2000          |        4       |
532  * |          3000          |        5       |
533  * |          4000          |        6       |
534  * |          5000          |        7       |
535  * |          6000          |        8       |
536  * |          7000          |        9       |
537  * |          8000          |       10       |
538  * |          9000          |       11       |
539  * |         10000          |       12       |
540  * |         11000          |       13       |
541  * |         12000          |       14       |
542  * |         13000          |       15       |
543  * |         14000          |       16       |
544  * |         14000          |       17       |
545  * |-----------------------------------------|
546  *
547 **/
548 uint16_t nr5g_fapi_calculate_nEpreRatioOfPDCCHToSSB(
549     uint8_t beta_pdcch_1_0)
550 {
551     if (beta_pdcch_1_0 > 0 && beta_pdcch_1_0 <= 2) {
552         return 1;
553     } else if (beta_pdcch_1_0 > 1 && beta_pdcch_1_0 < 17) {
554         return ((beta_pdcch_1_0 - 2) * 1000);
555     } else if (beta_pdcch_1_0 == 17) {
556         return ((beta_pdcch_1_0 - 3) * 1000);
557     } else {
558         return 0;
559     }
560 }
561
562 /** @ingroup group_nr5g_test_config
563  *
564  *  @param[in]  power_control_offset_ss
565  *
566  *  @return     uint16_t mapping
567  *
568  *  @description
569  *  This function maps FAPI to IAPI value range.
570  *
571  *
572  * nEpreRatioOfDmrsToSSB: 1->20000, 0.001dB step, -6dB to 14dB
573  * powerControlOffsetSS:  0->3, 3dB step, -3dB to 6dB
574  * |----------------------------------------------|
575  * | nEpreRatioOfDmrsToSSB | powerControlOffsetSS |
576  * |----------------------------------------------|
577  * |     3000              |          0           |
578  * |     6000              |          1           |
579  * |     9000              |          2           |
580  * |     12000             |          3           |
581  * |----------------------------------------------|
582  *
583 **/
584 uint16_t nr5g_fapi_calculate_nEpreRatioOfDmrsToSSB(
585     uint8_t power_control_offset_ss)
586 {
587     switch(power_control_offset_ss)
588     {
589         case 0:
590             return 3000;
591         case 1:
592             return 6000;
593         case 2:
594             return 9000;
595         case 3:
596             return 12000;
597         default:
598             NR5G_FAPI_LOG(ERROR_LOG,
599                 ("Unsupported value of power_control_offset_ss."));
600             return 0;
601     }
602 }
603
604
605 /** @ingroup group_nr5g_test_config
606  *
607  *  @param[in]  power_control_offset
608  *
609  *  @return     uint16_t mapping
610  *
611  *  @description
612  *  This function maps FAPI to IAPI value range.
613  *
614  *
615  * nEpreRatioOfPDSCHToSSB: 1->20000, 0.001dB step, -6dB to 14dB
616  * powerControlOffset:  0->23, 1dB step, -8dB to 15dB
617  * |----------------------------------------------|
618  * | nEpreRatioOfPDSCHToSSB | powerControlOffset  |
619  * |----------------------------------------------|
620  * |             1          |        0-2          |
621  * |          1000          |          3          |
622  * |          2000          |          4          |
623  * |          3000          |          5          |
624  * |          4000          |          6          |
625  * |          5000          |          7          |
626  * |          6000          |          8          |
627  * |          7000          |          9          |
628  * |          8000          |         10          |
629  * |          9000          |         11          |
630  * |         10000          |         12          |
631  * |         11000          |         13          |
632  * |         12000          |         14          |
633  * |         13000          |         15          |
634  * |         14000          |         16          |
635  * |         15000          |         17          |
636  * |         16000          |         18          |
637  * |         17000          |         19          |
638  * |         18000          |         20          |
639  * |         19000          |         21          |
640  * |         20000          |      22-23          |
641  * |----------------------------------------------|
642  *
643 **/
644 uint16_t nr5g_fapi_calculate_nEpreRatioOfPDSCHToSSB(uint8_t power_control_offset)
645 {
646     static const uint8_t MAPPING_SIZE = 24;
647     static const uint16_t power_control_offset_to_epre_ratio[MAPPING_SIZE] = {
648     //      0      1      2      3      4      5      6      7
649             1,     1,     1,  1000,  2000,  3000,  4000,  5000,
650     //      8      9     10     11     12     13     14     15
651          6000,  7000,  8000,  9000, 10000, 11000, 12000, 13000,
652     //     16     17     18     19     20     21     22     23
653         14000, 15000, 16000, 17000, 18000, 19000, 20000, 20000
654     };
655
656     if(MAPPING_SIZE > power_control_offset)
657     {
658         return power_control_offset_to_epre_ratio[power_control_offset];
659     }
660     else
661     {
662         NR5G_FAPI_LOG(ERROR_LOG,
663             ("Unsupported value of power_control_offset=%u.",
664             power_control_offset));
665         return 0;
666     }
667 }
668
669 /** @ingroup group_nr5g_test_config
670  *
671  *  @param[in]  ssb_offset_point_a
672  *  @param[in]  sub_c_common
673  *
674  *  @return     uint8_t nSSBPrbOffset
675  *
676  *  @description
677  *  This function maps FAPI to IAPI value range.
678  *
679  * Please refer 5G FAPI-IAPI Translator Module SW Design Document for details on
680  * the mapping.
681  *
682 **/
683 uint8_t nr5g_fapi_calculate_nSSBPrbOffset(
684     uint16_t ssb_offset_point_a, uint8_t sub_c_common)
685 {
686     return ssb_offset_point_a/pow(2, sub_c_common);
687 }
688
689 /** @ingroup group_nr5g_test_config
690  *
691  *  @param[in]   p_dlsch_pdu
692  *  @param[out]  p_pdsch_pdu
693  *
694  *  @return      void
695  *
696  *  @description
697  *  This function fills FAPI PDSCH Pdu from IAPI DLSCHPDU
698  *
699 **/
700 void nr5g_fapi_fill_ssb_pdu(
701     p_nr5g_fapi_phy_instance_t p_phy_instance,
702     PBCHPDUStruct p_bch_pdu,
703     fapi_dl_ssb_pdu_t * p_ssb_pdu)
704 {
705     uint8_t *p_mib = (uint8_t *) & p_bch_pdu->nMIB[0];
706     uint8_t *payload = (uint8_t *) & p_ssb_pdu->bchPayload.bchPayload;
707     nr5g_fapi_stats_t *p_stats;
708
709     p_mib[0] = payload[0];
710     p_mib[1] = payload[1];
711     p_mib[2] = payload[2];
712     p_stats = &p_phy_instance->stats;
713     p_stats->fapi_stats.fapi_dl_tti_ssb_pdus++;
714     p_bch_pdu->nSSBSubcOffset = p_ssb_pdu->ssbSubCarrierOffset;
715     p_bch_pdu->nSSBPrbOffset =
716         nr5g_fapi_calculate_nSSBPrbOffset(p_ssb_pdu->ssbOffsetPointA,
717             p_phy_instance->phy_config.sub_c_common);
718     p_stats->iapi_stats.iapi_dl_tti_ssb_pdus++;
719 }
720
721 /** @ingroup group_nr5g_test_config
722  *
723  *  @param[in]   p_dlsch_pdu
724  *  @param[out]  p_pdsch_pdu
725  *
726  *  @return      void
727  *
728  *  @description
729  *  This function fills FAPI PDSCH Pdu from IAPI DLSCHPDU
730  *
731 **/
732 void nr5g_fapi_fill_csi_rs_pdu(
733     p_nr5g_fapi_phy_instance_t p_phy_instance,
734     fapi_dl_csi_rs_pdu_t * p_csi_rs_pdu,
735     PCSIRSPDUStruct p_CSIRS_pdu)
736 {
737     nr5g_fapi_stats_t *p_stats;
738
739     p_stats = &p_phy_instance->stats;
740     p_stats->fapi_stats.fapi_dl_tti_csi_rs_pdus++;
741
742     p_CSIRS_pdu->nBWPSize = p_csi_rs_pdu->bwpSize;
743     p_CSIRS_pdu->nBWPStart = p_csi_rs_pdu->bwpStart;
744     p_CSIRS_pdu->nCDMType = p_csi_rs_pdu->cdmType;
745     p_CSIRS_pdu->nCSIType = p_csi_rs_pdu->csiType;
746     p_CSIRS_pdu->nCpType = p_csi_rs_pdu->cyclicPrefix;
747     p_CSIRS_pdu->nFreqDensity = p_csi_rs_pdu->freqDensity;
748     p_CSIRS_pdu->nFreqDomain = p_csi_rs_pdu->freqDomain;
749     p_CSIRS_pdu->nNrOfRBs = p_csi_rs_pdu->nrOfRbs;
750     p_CSIRS_pdu->nScrambId = p_csi_rs_pdu->scramId;
751     p_CSIRS_pdu->nStartRB = p_csi_rs_pdu->startRb;
752     p_CSIRS_pdu->nSubcSpacing = p_csi_rs_pdu->subCarrierSpacing;
753     p_CSIRS_pdu->nSymbL0 = p_csi_rs_pdu->symbL0;
754     p_CSIRS_pdu->nSymbL1 = p_csi_rs_pdu->symbL1;
755     p_CSIRS_pdu->nRow = p_csi_rs_pdu->row;
756     // Not mapping the beamforming parameters
757     // p_CSIRS_pdu->powerControlOffset = p_csi_rs_pdu->powerControlOffset;
758
759     if (USE_VENDOR_EPREXSSB != p_phy_instance->phy_config.use_vendor_EpreXSSB) {
760         p_CSIRS_pdu->nEpreRatioToSSB = nr5g_fapi_calculate_nEpreRatioOfDmrsToSSB(p_csi_rs_pdu->powerControlOffsetSs);
761     }
762
763     p_stats->iapi_stats.iapi_dl_tti_csi_rs_pdus++;
764 }