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