* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fapi_5g / source / api / fapi2mac / p7 / nr5g_fapi_proc_uci_ind.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2021 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  * @file
20  * This file consist of implementation of FAPI UCI.indication message.
21  *
22  **/
23
24 #include "nr5g_mac_phy_api.h"
25 #include "nr5g_fapi_framework.h"
26 #include "nr5g_fapi_fapi2mac_api.h"
27 #include "nr5g_fapi_fapi2mac_p7_proc.h"
28 #include "nr5g_fapi_fapi2mac_p7_pvt_proc.h"
29 #include "nr5g_fapi_memory.h"
30 #include "nr5g_fapi_snr_conversion.h"
31
32  /** @ingroup group_source_api_p7_fapi2mac_proc
33  *
34  *  @param[in]  p_phy_ctx     Pointer to PHY context.
35  *  @param[in]  p_phy_uci_ind Pointer to FAPI UCI.indication message structure.
36  *  
37  *  @return     Returns ::SUCCESS and ::FAILURE.
38  *
39  *  @description
40  *  This message includes UCI payload in PUCCH or PUSCH. 
41  *
42 **/
43 uint8_t nr5g_fapi_uci_indication(
44     bool is_urllc,
45     p_nr5g_fapi_phy_ctx_t p_phy_ctx,
46     p_fapi_api_stored_vendor_queue_elems vendor_extension_elems,
47     PRXUCIIndicationStruct p_phy_uci_ind)
48 {
49     uint8_t phy_id;
50     fapi_uci_indication_t *p_fapi_uci_ind;
51     p_fapi_api_queue_elem_t p_list_elem;
52     p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
53     nr5g_fapi_stats_t *p_stats;
54
55     if (NULL == p_phy_ctx) {
56         NR5G_FAPI_LOG(ERROR_LOG, ("[UCI.indication] Invalid Phy " "Context"));
57         return FAILURE;
58     }
59
60     if (NULL == p_phy_uci_ind) {
61         NR5G_FAPI_LOG(ERROR_LOG, ("[UCI.indication] Invalid Phy "
62                 "UCI indication"));
63         return FAILURE;
64     }
65
66     phy_id = p_phy_uci_ind->sSFN_Slot.nCarrierIdx;
67     p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
68     if ((p_phy_instance->phy_id != phy_id)) {
69         NR5G_FAPI_LOG(ERROR_LOG, ("[UCI.indication] Invalid " "phy instance"));
70         return FAILURE;
71     }
72
73     p_stats = &p_phy_instance->stats;
74     p_stats->iapi_stats.iapi_uci_ind++;
75
76     p_list_elem =
77         nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_UCI_INDICATION, 1,
78         sizeof(fapi_uci_indication_t));
79     if (!p_list_elem) {
80         NR5G_FAPI_LOG(ERROR_LOG, ("[UCI.indication] Unable to create "
81                 "list element. Out of memory!!!"));
82         return FAILURE;
83     }
84
85     p_fapi_uci_ind = (fapi_uci_indication_t *) (p_list_elem + 1);
86     p_fapi_uci_ind->header.msg_id = FAPI_UCI_INDICATION;
87     p_fapi_uci_ind->header.length = (uint16_t) sizeof(fapi_uci_indication_t);
88
89     fapi_vendor_p7_ind_msg_t* p_fapi_vend_p7 =
90         nr5g_fapi_proc_vendor_p7_msg_get(vendor_extension_elems, phy_id);
91     fapi_vendor_ext_snr_t* p_fapi_snr = p_fapi_vend_p7 ? &p_fapi_vend_p7->uci_snr : NULL;
92     fapi_vendor_ext_uci_ind_t* p_fapi_vend_uci_ind = p_fapi_vend_p7 ? &p_fapi_vend_p7->uci_ind : NULL;
93     
94     if (p_fapi_vend_uci_ind) {
95         p_fapi_vend_uci_ind->carrier_idx = phy_id;
96         p_fapi_vend_uci_ind->sym = p_phy_uci_ind->sSFN_Slot.nSym;
97     }
98
99     if (nr5g_fapi_uci_indication_to_fapi_translation(is_urllc, p_phy_instance,
100             p_phy_uci_ind, p_fapi_uci_ind, p_fapi_snr)) {
101         NR5G_FAPI_LOG(ERROR_LOG,
102             ("[UCI.indication] FAPI to L1 " "translation failed"));
103         return FAILURE;
104     }
105     /* Add element to send list */
106     nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem, is_urllc);
107
108     p_stats->fapi_stats.fapi_uci_ind++;
109     NR5G_FAPI_LOG(DEBUG_LOG, ("[UCI.indication][%u][%u,%u,%u] is_urllc %u",
110             p_phy_instance->phy_id,
111         p_phy_uci_ind->sSFN_Slot.nSFN, p_phy_uci_ind->sSFN_Slot.nSlot,
112         p_phy_uci_ind->sSFN_Slot.nSym, is_urllc));
113
114     return SUCCESS;
115 }
116
117  /** @ingroup group_source_api_p7_fapi2mac_proc
118  *
119  *  @param[in]   ue_id  Variable holding ue_id received in RX_DATA.Indication..
120  *  @param[in]   p_ul_slot_info Pointer to ul slot info structure that stores the 
121  *               UL_TTI.request PDU info.
122  *  
123  *  @return     Returns Pointer to pucch info, if handle of p_ul_slot_info matches ue_id.
124                         NULL, if handle of p_ul_slot_info not matches ue_id
125  *
126  *  @description
127 **/
128 nr5g_fapi_pucch_info_t *nr5g_fapi_get_pucch_info(
129     uint16_t ue_id,
130     nr5g_fapi_ul_slot_info_t * p_ul_slot_info)
131 {
132     uint8_t i, num_ulcch;
133     nr5g_fapi_pucch_info_t *p_pucch_info;
134
135     num_ulcch = p_ul_slot_info->num_ulcch;
136     for (i = 0; i < num_ulcch; i++) {
137         p_pucch_info = &p_ul_slot_info->pucch_info[i];
138         if (p_pucch_info->handle == ue_id) {
139             return p_pucch_info;
140         }
141     }
142     return NULL;
143 }
144
145  /** @ingroup group_source_api_p7_fapi2mac_proc
146  *
147  *  @param[in]   p_pucch_info Pointer to pucch_info stored in ul slot info during
148  *               UL_TTI.request processing
149  *  @param[in]   p_uci_pdu_data_struct Pointer to IAPI UCI PDU structure.
150  *  @param[out]  p_fapi_uci_pdu_info   Pointer to FAPI UCI PDU structure.
151  *  
152  *  @return     Returns ::SUCCESS and ::FAILURE.
153  *
154  *  @description
155  *  This function fills  FAPI UCI FORMAT0_FORMAT1 PDU from IAPI UCI PDU
156  *  structure.
157  *
158 **/
159 void nr5g_fapi_fill_uci_format_0_1(
160     nr5g_fapi_pucch_info_t * p_pucch_info,
161     ULUCIPDUDataStruct * p_uci_pdu_data_struct,
162     fapi_uci_pdu_info_t * p_fapi_uci_pdu_info,
163     int16_t * p_fapi_snr)
164 {
165     uint8_t pucch_detected, num_harq, i;
166
167     fapi_uci_o_pucch_f0f1_t *p_uci_pucch_f0_f1;
168     fapi_sr_f0f1_info_t *p_sr_info;
169     fapi_harq_f0f1_info_t *p_harq_info;
170
171     p_uci_pucch_f0_f1 = &p_fapi_uci_pdu_info->uci.uciPucchF0F1;
172     NR5G_FAPI_MEMSET(p_uci_pucch_f0_f1, sizeof(fapi_uci_o_pucch_f0f1_t), 0,
173         sizeof(fapi_uci_o_pucch_f0f1_t));
174
175     p_uci_pucch_f0_f1->handle = p_pucch_info->handle;
176     p_uci_pucch_f0_f1->pduBitmap = 0;
177     p_uci_pucch_f0_f1->pucchFormat = p_pucch_info->pucch_format;
178
179     if(p_fapi_snr)
180     {
181         *p_fapi_snr = p_uci_pdu_data_struct->nSNR;
182     }
183
184     p_uci_pucch_f0_f1->ul_cqi = nr5g_fapi_convert_snr_iapi_to_fapi(p_uci_pdu_data_struct->nSNR);
185     p_uci_pucch_f0_f1->rnti = p_uci_pdu_data_struct->nRNTI;
186     p_uci_pucch_f0_f1->timingAdvance = 31;
187     p_uci_pucch_f0_f1->rssi = 880;
188
189     if (p_uci_pdu_data_struct->nSRPresent) {
190         p_uci_pucch_f0_f1->pduBitmap |= 0x01;
191         p_sr_info = &p_uci_pucch_f0_f1->srInfo;
192         p_sr_info->srIndication = 1;
193         p_sr_info->srConfidenceLevel = 0xff;
194     }
195     pucch_detected = p_uci_pdu_data_struct->pucchDetected;
196     if (pucch_detected == 1) {
197         p_uci_pucch_f0_f1->pduBitmap |= 0x02;
198         p_harq_info = &p_uci_pucch_f0_f1->harqInfo;
199         p_harq_info->harqConfidenceLevel = 0xff;
200         num_harq = p_harq_info->numHarq = p_uci_pdu_data_struct->nPduBitLen;
201         for (i = 0; i < num_harq; i++) {
202             p_harq_info->harqValue[i] = p_uci_pdu_data_struct->nUciBits[i];
203         }
204     } else {                    // 0 or 2
205         p_uci_pucch_f0_f1->rssi = 0;
206     }
207 #ifdef DEBUG_MODE
208     p_uci_pucch_f0_f1->timingAdvance = p_uci_pdu_data_struct->nTA;
209     if (pucch_detected == 2) {
210         p_uci_pucch_f0_f1->pduBitmap |= 0x80;
211         p_harq_info = &p_uci_pucch_f0_f1->harqInfo;
212         p_harq_info->harqConfidenceLevel = 0xff;
213         num_harq = p_harq_info->numHarq = p_uci_pdu_data_struct->nPduBitLen;
214         for (i = 0; i < num_harq; i++) {
215             p_harq_info->harqValue[i] = p_uci_pdu_data_struct->nUciBits[i];
216         }
217     }
218 #endif
219 }
220
221  /** @ingroup group_source_api_p7_fapi2mac_proc
222  *
223  *  @param[in]   p_pucch_info Pointer to pucch_info stored in ul slot info during
224  *               UL_TTI.request processing
225  *  @param[in]   p_uci_pdu_data_struct Pointer to IAPI UCI PDU structure.
226  *  @param[out]  p_fapi_uci_pdu_info   Pointer to FAPI UCI PDU structure.
227  *  
228  *  @return     Returns ::SUCCESS and ::FAILURE.
229  *
230  *  @description
231  *  This function fills  FAPI UCI FORMAT2_FORMAT3_FORMAT4 PDU from IAPI UCI PDU
232  *  structure.
233  *
234 **/
235 void nr5g_fapi_fill_uci_format_2_3_4(
236     nr5g_fapi_pucch_info_t * p_pucch_info,
237     ULUCIPDUDataStruct * p_uci_pdu_data_struct,
238     fapi_uci_pdu_info_t * p_fapi_uci_pdu_info,
239     int16_t * p_fapi_snr)
240 {
241     uint8_t pucch_detected;
242     uint16_t num_uci_bits;
243
244     fapi_uci_o_pucch_f2f3f4_t *p_uci_pucch_f2_f3_f4;
245
246     p_uci_pucch_f2_f3_f4 = &p_fapi_uci_pdu_info->uci.uciPucchF2F3F4;
247
248     p_uci_pucch_f2_f3_f4->handle = p_pucch_info->handle;
249     p_uci_pucch_f2_f3_f4->pduBitmap = 0;
250     p_uci_pucch_f2_f3_f4->pucchFormat = p_pucch_info->pucch_format;
251     p_uci_pucch_f2_f3_f4->ul_cqi = nr5g_fapi_convert_snr_iapi_to_fapi(p_uci_pdu_data_struct->nSNR);
252     p_uci_pucch_f2_f3_f4->rnti = p_uci_pdu_data_struct->nRNTI;
253     p_uci_pucch_f2_f3_f4->timingAdvance = 31;
254
255     if(p_fapi_snr)
256     {
257         *p_fapi_snr = p_uci_pdu_data_struct->nSNR;
258     }
259
260     pucch_detected = p_uci_pdu_data_struct->pucchDetected;
261 #ifdef DEBUG_MODE
262     p_uci_pucch_f2_f3_f4->timingAdvance = p_uci_pdu_data_struct->nTA;
263     if (pucch_detected == 2) {
264         p_uci_pucch_f2_f3_f4->pduBitmap |= 0x80;
265     }
266 #endif
267     p_uci_pucch_f2_f3_f4->rssi = 880;
268     if (p_uci_pdu_data_struct->nSRPresent) {
269         p_uci_pucch_f2_f3_f4->pduBitmap |= 0x01;
270     }
271     pucch_detected = p_uci_pdu_data_struct->pucchDetected;
272     if (pucch_detected == 1) {
273         p_uci_pucch_f2_f3_f4->pduBitmap |= 0x02;
274     } else {
275         p_uci_pucch_f2_f3_f4->rssi = 0;
276     }
277     num_uci_bits = p_uci_pucch_f2_f3_f4->num_uci_bits =
278         p_uci_pdu_data_struct->nPduBitLen;
279     if (num_uci_bits > 0) {
280         NR5G_FAPI_MEMCPY(p_uci_pucch_f2_f3_f4->uciBits,
281             sizeof(uint8_t) * FAPI_MAX_UCI_BIT_BYTE_LEN,
282             p_uci_pdu_data_struct->nUciBits,
283             sizeof(uint8_t) * FAPI_MAX_UCI_BIT_BYTE_LEN);
284     }
285 }
286
287  /** @ingroup group_source_api_p7_fapi2mac_proc
288  *
289  *  @param[in]  p_phy_instance Pointer to PHY instance.
290  *  @param[in]   p_phy_uci_ind Pointer to IAPI UCI.indication structure.
291  *  @param[out]  p_fapi_uci_ind Pointer to FAPI UCI.indication structure.
292  *  
293  *  @return     Returns ::SUCCESS and ::FAILURE.
294  *
295  *  @description
296  *  This function converts IAPI UCI.indication to FAPI UCI.indication
297  *  structure.
298  *
299 **/
300 uint8_t nr5g_fapi_uci_indication_to_fapi_translation(
301     bool is_urllc,
302     p_nr5g_fapi_phy_instance_t p_phy_instance,
303     PRXUCIIndicationStruct p_phy_uci_ind,
304     fapi_uci_indication_t * p_fapi_uci_ind,
305     fapi_vendor_ext_snr_t * p_fapi_snr)
306 {
307     uint8_t num_uci, i;
308     uint8_t symbol_no, pucch_format;
309     uint16_t slot_no, frame_no;
310
311     nr5g_fapi_pucch_info_t *p_pucch_info;
312     fapi_uci_pdu_info_t *p_fapi_uci_pdu_info;
313     nr5g_fapi_ul_slot_info_t *p_ul_slot_info;
314     nr5g_fapi_stats_t *p_stats;
315     ULUCIPDUDataStruct *p_uci_pdu_data_struct;
316
317     p_stats = &p_phy_instance->stats;
318
319     frame_no = p_fapi_uci_ind->sfn = p_phy_uci_ind->sSFN_Slot.nSFN;
320     slot_no = p_fapi_uci_ind->slot = p_phy_uci_ind->sSFN_Slot.nSlot;
321     symbol_no = p_phy_uci_ind->sSFN_Slot.nSym;
322
323     p_ul_slot_info =
324         nr5g_fapi_get_ul_slot_info(is_urllc, frame_no, slot_no, symbol_no, p_phy_instance);
325
326     if (p_ul_slot_info == NULL) {
327         NR5G_FAPI_LOG(ERROR_LOG, (" [UCI.indication] No Valid data available "
328                 "for frame :%d and slot: %d", frame_no, slot_no));
329         return FAILURE;
330     }
331
332     num_uci = p_fapi_uci_ind->numUcis = p_phy_uci_ind->nUCI;
333     for (i = 0; i < num_uci; i++) {
334         p_stats->iapi_stats.iapi_uci_ind_pdus++;
335         p_fapi_uci_pdu_info = &p_fapi_uci_ind->uciPdu[i];
336         p_uci_pdu_data_struct = &p_phy_uci_ind->sULUCIPDUDataStruct[i];
337         p_pucch_info =
338             nr5g_fapi_get_pucch_info(p_uci_pdu_data_struct->nUEId,
339             p_ul_slot_info);
340         if (p_pucch_info == NULL) {
341             NR5G_FAPI_LOG(ERROR_LOG,
342                 (" [UCI.indication] No Valid data available "
343                     "for nUEId:%d with frameno:%d, slot_no:%d",
344                     p_uci_pdu_data_struct->nUEId, frame_no, slot_no));
345             return FAILURE;
346         }
347
348         pucch_format = p_pucch_info->pucch_format;
349         int16_t* p_fapi_snr_arr = p_fapi_snr ? &p_fapi_snr->nSNR[i] : NULL;
350
351         switch (pucch_format) {
352             case FAPI_PUCCH_FORMAT_TYPE_0:
353             case FAPI_PUCCH_FORMAT_TYPE_1:
354                 {
355                     p_fapi_uci_pdu_info->pduType = 1;
356                     p_fapi_uci_pdu_info->pduSize =
357                         sizeof(fapi_uci_o_pucch_f0f1_t);
358                     nr5g_fapi_fill_uci_format_0_1(p_pucch_info,
359                         p_uci_pdu_data_struct, p_fapi_uci_pdu_info, p_fapi_snr_arr);
360                 }
361                 break;
362
363             case FAPI_PUCCH_FORMAT_TYPE_2:
364             case FAPI_PUCCH_FORMAT_TYPE_3:
365             case FAPI_PUCCH_FORMAT_TYPE_4:
366                 {
367                     p_fapi_uci_pdu_info->pduType = 2;
368                     p_fapi_uci_pdu_info->pduSize =
369                         sizeof(fapi_uci_o_pucch_f2f3f4_t);
370                     nr5g_fapi_fill_uci_format_2_3_4(p_pucch_info,
371                         p_uci_pdu_data_struct, p_fapi_uci_pdu_info, p_fapi_snr_arr);
372                 }
373                 break;
374
375             default:
376                 {
377                     NR5G_FAPI_LOG(ERROR_LOG,
378                         (" [UCI.indication] Invalid PUCCH Format"
379                             "pucch_format:%d", pucch_format));
380                     return FAILURE;
381                 }
382                 break;
383         }
384         p_stats->fapi_stats.fapi_uci_ind_pdus++;
385     }
386     return SUCCESS;
387 }