46e3b5e00d8158f0cfc8eef388f9def56fe225c6
[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,
99             p_phy_uci_ind->sSFN_Slot.nSlot));
100
101     return SUCCESS;
102 }
103
104  /** @ingroup group_source_api_p7_fapi2mac_proc
105  *
106  *  @param[in]   ue_id  Variable holding ue_id received in RX_DATA.Indication..
107  *  @param[in]   p_ul_slot_info Pointer to ul slot info structure that stores the 
108  *               UL_TTI.request PDU info.
109  *  
110  *  @return     Returns Pointer to pucch info, if handle of p_ul_slot_info matches ue_id.
111                         NULL, if handle of p_ul_slot_info not matches ue_id
112  *
113  *  @description
114 **/
115 nr5g_fapi_pucch_info_t *nr5g_fapi_get_pucch_info(
116     uint16_t ue_id,
117     nr5g_fapi_ul_slot_info_t * p_ul_slot_info)
118 {
119     uint8_t i, num_ulcch;
120     nr5g_fapi_pucch_info_t *p_pucch_info;
121
122     num_ulcch = p_ul_slot_info->num_ulcch;
123     for (i = 0; i < num_ulcch; i++) {
124         p_pucch_info = &p_ul_slot_info->pucch_info[i];
125         if (p_pucch_info->handle == ue_id) {
126             return p_pucch_info;
127         }
128     }
129     return NULL;
130 }
131
132  /** @ingroup group_source_api_p7_fapi2mac_proc
133  *
134  *  @param[in]   p_pucch_info Pointer to pucch_info stored in ul slot info during
135  *               UL_TTI.request processing
136  *  @param[in]   p_uci_pdu_data_struct Pointer to IAPI UCI PDU structure.
137  *  @param[out]  p_fapi_uci_pdu_info   Pointer to FAPI UCI PDU structure.
138  *  
139  *  @return     Returns ::SUCCESS and ::FAILURE.
140  *
141  *  @description
142  *  This function fills  FAPI UCI FORMAT0_FORMAT1 PDU from IAPI UCI PDU
143  *  structure.
144  *
145 **/
146 void nr5g_fapi_fill_uci_format_0_1(
147     nr5g_fapi_pucch_info_t * p_pucch_info,
148     ULUCIPDUDataStruct * p_uci_pdu_data_struct,
149     fapi_uci_pdu_info_t * p_fapi_uci_pdu_info)
150 {
151     uint8_t pucch_detected, num_harq, i;
152
153     fapi_uci_o_pucch_f0f1_t *p_uci_pucch_f0_f1;
154     fapi_sr_f0f1_info_t *p_sr_info;
155     fapi_harq_f0f1_info_t *p_harq_info;
156
157     p_uci_pucch_f0_f1 = &p_fapi_uci_pdu_info->uci.uciPucchF0F1;
158     NR5G_FAPI_MEMSET(p_uci_pucch_f0_f1, sizeof(fapi_uci_o_pucch_f0f1_t), 0,
159         sizeof(fapi_uci_o_pucch_f0f1_t));
160
161     p_uci_pucch_f0_f1->handle = p_pucch_info->handle;
162     p_uci_pucch_f0_f1->pduBitmap = 0;
163     p_uci_pucch_f0_f1->pucchFormat = p_pucch_info->pucch_format;
164
165     p_uci_pucch_f0_f1->ul_cqi = (p_uci_pdu_data_struct->nSNR + 64) * 2;
166     p_uci_pucch_f0_f1->rnti = p_uci_pdu_data_struct->nRNTI;
167     p_uci_pucch_f0_f1->timingAdvance = 31;
168     p_uci_pucch_f0_f1->rssi = 880;
169
170     if (p_uci_pdu_data_struct->nSRPresent) {
171         p_uci_pucch_f0_f1->pduBitmap |= 0x01;
172         p_sr_info = &p_uci_pucch_f0_f1->srInfo;
173         p_sr_info->srIndication = 1;
174         p_sr_info->srConfidenceLevel = 0xff;
175     }
176     pucch_detected = p_uci_pdu_data_struct->pucchDetected;
177     if (pucch_detected == 1) {
178         p_uci_pucch_f0_f1->pduBitmap |= 0x02;
179         p_harq_info = &p_uci_pucch_f0_f1->harqInfo;
180         p_harq_info->harqConfidenceLevel = 0xff;
181         num_harq = p_harq_info->numHarq = p_uci_pdu_data_struct->nPduBitLen;
182         for (i = 0; i < num_harq; i++) {
183             p_harq_info->harqValue[i] = p_uci_pdu_data_struct->nUciBits[i];
184         }
185     } else {                    // 0 or 2
186         p_uci_pucch_f0_f1->rssi = 0;
187     }
188 #ifdef DEBUG_MODE
189     p_uci_pucch_f0_f1->timingAdvance = p_uci_pdu_data_struct->nTA;
190     if (pucch_detected == 2) {
191         p_uci_pucch_f0_f1->pduBitmap |= 0x80;
192         p_harq_info = &p_uci_pucch_f0_f1->harqInfo;
193         p_harq_info->harqConfidenceLevel = 0xff;
194         num_harq = p_harq_info->numHarq = p_uci_pdu_data_struct->nPduBitLen;
195         for (i = 0; i < num_harq; i++) {
196             p_harq_info->harqValue[i] = p_uci_pdu_data_struct->nUciBits[i];
197         }
198     }
199 #endif
200 }
201
202  /** @ingroup group_source_api_p7_fapi2mac_proc
203  *
204  *  @param[in]   p_pucch_info Pointer to pucch_info stored in ul slot info during
205  *               UL_TTI.request processing
206  *  @param[in]   p_uci_pdu_data_struct Pointer to IAPI UCI PDU structure.
207  *  @param[out]  p_fapi_uci_pdu_info   Pointer to FAPI UCI PDU structure.
208  *  
209  *  @return     Returns ::SUCCESS and ::FAILURE.
210  *
211  *  @description
212  *  This function fills  FAPI UCI FORMAT2_FORMAT3_FORMAT4 PDU from IAPI UCI PDU
213  *  structure.
214  *
215 **/
216 void nr5g_fapi_fill_uci_format_2_3_4(
217     nr5g_fapi_pucch_info_t * p_pucch_info,
218     ULUCIPDUDataStruct * p_uci_pdu_data_struct,
219     fapi_uci_pdu_info_t * p_fapi_uci_pdu_info)
220 {
221     uint8_t pucch_detected;
222     uint16_t num_uci_bits;
223
224     fapi_uci_o_pucch_f2f3f4_t *p_uci_pucch_f2_f3_f4;
225
226     p_uci_pucch_f2_f3_f4 = &p_fapi_uci_pdu_info->uci.uciPucchF2F3F4;
227
228     p_uci_pucch_f2_f3_f4->handle = p_pucch_info->handle;
229     p_uci_pucch_f2_f3_f4->pduBitmap = 0;
230     p_uci_pucch_f2_f3_f4->pucchFormat = p_pucch_info->pucch_format;
231     p_uci_pucch_f2_f3_f4->ul_cqi = (p_uci_pdu_data_struct->nSNR + 64) * 2;
232     p_uci_pucch_f2_f3_f4->rnti = p_uci_pdu_data_struct->nRNTI;
233     p_uci_pucch_f2_f3_f4->timingAdvance = 31;
234
235     pucch_detected = p_uci_pdu_data_struct->pucchDetected;
236 #ifdef DEBUG_MODE
237     p_uci_pucch_f2_f3_f4->timingAdvance = p_uci_pdu_data_struct->nTA;
238     if (pucch_detected == 2) {
239         p_uci_pucch_f2_f3_f4->pduBitmap |= 0x80;
240     }
241 #endif
242     p_uci_pucch_f2_f3_f4->rssi = 880;
243     if (p_uci_pdu_data_struct->nSRPresent) {
244         p_uci_pucch_f2_f3_f4->pduBitmap |= 0x01;
245     }
246     pucch_detected = p_uci_pdu_data_struct->pucchDetected;
247     if (pucch_detected == 1) {
248         p_uci_pucch_f2_f3_f4->pduBitmap |= 0x02;
249     } else {
250         p_uci_pucch_f2_f3_f4->rssi = 0;
251     }
252     num_uci_bits = p_uci_pucch_f2_f3_f4->num_uci_bits =
253         p_uci_pdu_data_struct->nPduBitLen;
254     if (num_uci_bits > 0) {
255         NR5G_FAPI_MEMCPY(p_uci_pucch_f2_f3_f4->uciBits,
256             sizeof(uint8_t) * FAPI_MAX_UCI_BIT_BYTE_LEN,
257             p_uci_pdu_data_struct->nUciBits, num_uci_bits);
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 }