O-RAN E Maintenance Release contribution for ODULOW
[o-du/phy.git] / fhi_lib / lib / src / xran_cb_proc.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2020 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  * @brief XRAN Callback processing functionality and helper functions
21  * @file xran_cb_proc.c
22  * @ingroup group_source_xran
23  * @author Intel Corporation
24  **/
25
26 #include <unistd.h>
27 #include <stdio.h>
28 #include <immintrin.h>
29 #include <rte_common.h>
30 #include <rte_eal.h>
31 #include <rte_errno.h>
32 #include <rte_lcore.h>
33 #include <rte_cycles.h>
34 #include <rte_memory.h>
35 #include <rte_memzone.h>
36 #include <rte_mbuf.h>
37 #include <rte_timer.h>
38
39 #include "ethdi.h"
40 #include "xran_fh_o_du.h"
41 #include "xran_main.h"
42 #include "xran_dev.h"
43 #include "xran_common.h"
44 #include "xran_cb_proc.h"
45 #include "xran_mlog_lnx.h"
46 #include "xran_lib_mlog_tasks_id.h"
47 #include "xran_printf.h"
48
49 typedef void (*rx_dpdk_sym_cb_fn)(struct rte_timer *tim, void *arg);
50
51 void xran_timer_arm(struct rte_timer *tim, void* arg, void *p_dev_ctx)
52 {
53     struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)p_dev_ctx;
54     uint64_t t3 = MLogTick();
55
56     if (xran_if_current_state == XRAN_RUNNING){
57         rte_timer_cb_t fct = (rte_timer_cb_t)arg;
58         rte_timer_reset_sync(tim, 0, SINGLE, p_xran_dev_ctx->fh_init.io_cfg.timing_core, fct, p_dev_ctx);
59     }
60     MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());
61 }
62
63 void xran_timer_arm_cp_dl(struct rte_timer *tim, void* arg, void *p_dev_ctx)
64 {
65     struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)p_dev_ctx;
66     uint64_t t3 = MLogTick();
67
68     unsigned tim_lcore = xran_schedule_to_worker(XRAN_JOB_TYPE_CP_DL, p_xran_dev_ctx);
69
70     if (xran_if_current_state == XRAN_RUNNING){
71         rte_timer_cb_t fct = (rte_timer_cb_t)arg;
72         rte_timer_reset_sync(tim, 0, SINGLE, tim_lcore, fct, p_dev_ctx);
73     }
74     MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());
75 }
76
77 void xran_timer_arm_cp_ul(struct rte_timer *tim, void* arg, void *p_dev_ctx)
78 {
79     struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)p_dev_ctx;
80     uint64_t t3 = MLogTick();
81
82     unsigned tim_lcore = xran_schedule_to_worker(XRAN_JOB_TYPE_CP_UL, p_xran_dev_ctx);
83
84     if (xran_if_current_state == XRAN_RUNNING){
85         rte_timer_cb_t fct = (rte_timer_cb_t)arg;
86         rte_timer_reset_sync(tim, 0, SINGLE, tim_lcore, fct, p_dev_ctx);
87     }
88     MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());
89 }
90
91 void xran_timer_arm_for_deadline(struct rte_timer *tim, void* arg,  void *p_dev_ctx)
92 {
93     struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)p_dev_ctx;
94     uint64_t t3 = MLogTick();
95
96     unsigned tim_lcore = xran_schedule_to_worker(XRAN_JOB_TYPE_DEADLINE, p_xran_dev_ctx);
97
98     int32_t rx_tti;
99     int32_t cc_id;
100     uint32_t nFrameIdx;
101     uint32_t nSubframeIdx;
102     uint32_t nSlotIdx;
103     uint64_t nSecond;
104
105     xran_get_slot_idx(p_xran_dev_ctx->xran_port_id, &nFrameIdx, &nSubframeIdx, &nSlotIdx, &nSecond);
106     rx_tti = nFrameIdx*SUBFRAMES_PER_SYSTEMFRAME*SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local)
107            + nSubframeIdx*SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local)
108            + nSlotIdx;
109
110     p_xran_dev_ctx->cb_timer_ctx[p_xran_dev_ctx->timer_put %  MAX_CB_TIMER_CTX].tti_to_process = rx_tti;
111     if (xran_if_current_state == XRAN_RUNNING){
112         rte_timer_cb_t fct = (rte_timer_cb_t)arg;
113         rte_timer_reset_sync(tim, 0, SINGLE, tim_lcore, fct, p_xran_dev_ctx);
114     }
115
116     MLogTask(PID_TIME_ARM_TIMER_DEADLINE, t3, MLogTick());
117 }
118
119 void xran_timer_arm_user_cb(struct rte_timer *tim, void* arg,  void *p_ctx)
120 {
121     struct cb_user_per_sym_ctx* p_sym_cb_ctx = (struct cb_user_per_sym_ctx *)p_ctx;
122     struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)p_sym_cb_ctx->p_dev;
123     uint64_t t3 = MLogTick();
124
125     unsigned tim_lcore = xran_schedule_to_worker(XRAN_JOB_TYPE_SYM_CB, NULL);
126
127     int32_t rx_tti;
128     int32_t cc_id;
129     uint32_t nFrameIdx = 0;
130     uint32_t nSubframeIdx = 0;
131     uint32_t nSlotIdx = 0;
132     uint64_t nSecond = 0;
133
134     xran_get_slot_idx(p_xran_dev_ctx->xran_port_id, &nFrameIdx, &nSubframeIdx, &nSlotIdx, &nSecond);
135     rx_tti = nFrameIdx*SUBFRAMES_PER_SYSTEMFRAME*SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local)
136            + nSubframeIdx*SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local)
137            + nSlotIdx;
138
139     p_sym_cb_ctx->user_cb_timer_ctx[p_sym_cb_ctx->user_timer_put % MAX_CB_TIMER_CTX].tti_to_process = rx_tti;
140     p_sym_cb_ctx->user_cb_timer_ctx[p_sym_cb_ctx->user_timer_put % MAX_CB_TIMER_CTX].ota_sym_idx = xran_lib_ota_sym_idx[p_xran_dev_ctx->xran_port_id];
141     p_sym_cb_ctx->user_cb_timer_ctx[p_sym_cb_ctx->user_timer_put % MAX_CB_TIMER_CTX].xran_sfn_at_sec_start = xran_getSfnSecStart();
142     p_sym_cb_ctx->user_cb_timer_ctx[p_sym_cb_ctx->user_timer_put % MAX_CB_TIMER_CTX].current_second = nSecond;
143
144     if (xran_if_current_state == XRAN_RUNNING){
145         rte_timer_cb_t fct = (rte_timer_cb_t)arg;
146         rte_timer_reset_sync(tim, 0, SINGLE, tim_lcore, fct, p_sym_cb_ctx);
147         if (++p_sym_cb_ctx->user_timer_put >= MAX_CB_TIMER_CTX)
148             p_sym_cb_ctx->user_timer_put = 0;
149     }
150
151     MLogTask(PID_TIME_ARM_USER_TIMER_DEADLINE, t3, MLogTick());
152 }
153
154 void xran_timer_arm_ex(struct rte_timer *tim, void* CbFct, void *CbArg, unsigned tim_lcore)
155 {
156     uint64_t t3 = MLogTick();
157
158     if (xran_if_current_state == XRAN_RUNNING){
159         rte_timer_cb_t fct = (rte_timer_cb_t)CbFct;
160         rte_timer_reset_sync(tim, 0, SINGLE, tim_lcore, fct, CbArg);
161     }
162     MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());
163 }
164
165 int32_t
166 xran_timing_create_cbs(void *args)
167 {
168     int32_t  res = XRAN_STATUS_SUCCESS;
169     int32_t  do_reset = 0;
170     uint64_t t1 = 0;
171     int32_t  result1,i,j;
172     uint32_t delay_cp_dl;
173     uint32_t delay_cp_ul;
174     uint32_t delay_up;
175     uint32_t time_diff_us;
176     uint32_t delay_cp2up;
177     uint32_t sym_cp_dl;
178     uint32_t sym_cp_ul;
179     uint32_t time_diff_nSymb;
180     int32_t  sym_up;
181     struct xran_device_ctx * p_dev_ctx =  (struct xran_device_ctx *)args;
182     uint64_t tWake = 0, tWakePrev = 0, tUsed = 0;
183     struct cb_elem_entry * cb_elm = NULL;
184     uint32_t interval_us_local = p_dev_ctx->interval_us_local;
185
186     /* ToS = Top of Second start +- 1.5us */
187     struct timespec ts;
188     char buff[100];
189
190     if (p_dev_ctx->fh_init.io_cfg.id == O_DU) {
191
192         delay_cp_dl = interval_us_local - p_dev_ctx->fh_cfg.T1a_max_cp_dl;
193         delay_cp_ul = interval_us_local - p_dev_ctx->fh_cfg.T1a_max_cp_ul;
194         delay_up    = p_dev_ctx->fh_cfg.T1a_max_up;
195         time_diff_us = p_dev_ctx->fh_cfg.Ta4_max;
196
197         delay_cp2up = delay_up-delay_cp_dl;
198
199         sym_cp_dl = delay_cp_dl*1000/(interval_us_local*1000/N_SYM_PER_SLOT)+1;
200         sym_cp_ul = delay_cp_ul*1000/(interval_us_local*1000/N_SYM_PER_SLOT)+1;
201         time_diff_nSymb = time_diff_us*1000/(interval_us_local*1000/N_SYM_PER_SLOT);
202         p_dev_ctx->sym_up = sym_up = -(delay_up*1000/(interval_us_local*1000/N_SYM_PER_SLOT));
203         p_dev_ctx->sym_up_ul = time_diff_nSymb = (time_diff_us*1000/(interval_us_local*1000/N_SYM_PER_SLOT)+1);
204
205         printf("Start C-plane DL %d us after TTI  [trigger on sym %d]\n", delay_cp_dl, sym_cp_dl);
206         printf("Start C-plane UL %d us after TTI  [trigger on sym %d]\n", delay_cp_ul, sym_cp_ul);
207         printf("Start U-plane DL %d us before OTA [offset  in sym %d]\n", delay_up, sym_up);
208         printf("Start U-plane UL %d us OTA        [offset  in sym %d]\n", time_diff_us, time_diff_nSymb);
209
210         printf("C-plane to U-plane delay %d us after TTI\n", delay_cp2up);
211         printf("Start Sym timer %ld ns\n", TX_TIMER_INTERVAL/N_SYM_PER_SLOT);
212
213         cb_elm = xran_create_cb(xran_timer_arm_cp_dl, tx_cp_dl_cb, (void*)p_dev_ctx);
214         if(cb_elm){
215             LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[sym_cp_dl],
216                              cb_elm,
217                              pointers);
218         } else {
219             print_err("cb_elm is NULL\n");
220             res =  XRAN_STATUS_FAIL;
221             goto err0;
222         }
223
224         cb_elm = xran_create_cb(xran_timer_arm_cp_ul, tx_cp_ul_cb, (void*)p_dev_ctx);
225         if(cb_elm){
226             LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[sym_cp_ul],
227                              cb_elm,
228                              pointers);
229         } else {
230             print_err("cb_elm is NULL\n");
231             res =  XRAN_STATUS_FAIL;
232             goto err0;
233         }
234
235         /* Full slot UL OTA + time_diff_us */
236         cb_elm = xran_create_cb(xran_timer_arm_for_deadline, rx_ul_deadline_full_cb, (void*)p_dev_ctx);
237         if(cb_elm){
238             LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[time_diff_nSymb],
239                              cb_elm,
240                              pointers);
241         } else {
242             print_err("cb_elm is NULL\n");
243             res =  XRAN_STATUS_FAIL;
244             goto err0;
245         }
246
247         /* Half slot UL OTA + time_diff_us*/
248         cb_elm = xran_create_cb(xran_timer_arm_for_deadline, rx_ul_deadline_half_cb, (void*)p_dev_ctx);
249         if(cb_elm){
250             LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[time_diff_nSymb + N_SYM_PER_SLOT/2],
251                          cb_elm,
252                          pointers);
253         } else {
254             print_err("cb_elm is NULL\n");
255             res =  XRAN_STATUS_FAIL;
256             goto err0;
257         }
258     } else {    // APP_O_RU
259         /* calculate when to send UL U-plane */
260         delay_up = p_dev_ctx->fh_cfg.Ta3_min;
261         p_dev_ctx->sym_up = sym_up = delay_up*1000/(interval_us_local*1000/N_SYM_PER_SLOT)+1;
262         printf("Start UL U-plane %d us after OTA [offset in sym %d]\n", delay_up, sym_up);
263
264         /* calcualte when to Receive DL U-plane */
265         delay_up = p_dev_ctx->fh_cfg.T2a_max_up;
266         sym_up = delay_up*1000/(interval_us_local*1000/N_SYM_PER_SLOT)+1;
267         printf("Receive DL U-plane %d us after OTA [offset in sym %d]\n", delay_up, sym_up);
268
269         /* Full slot UL OTA + time_diff_us */
270         cb_elm = xran_create_cb(xran_timer_arm_for_deadline, rx_ul_deadline_full_cb, (void*)p_dev_ctx);
271         if(cb_elm){
272             LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[sym_up],
273                              cb_elm,
274                              pointers);
275         } else {
276             print_err("cb_elm is NULL\n");
277             res =  -1;
278             goto err0;
279         }
280
281         do {
282            timespec_get(&ts, TIME_UTC);
283         }while (ts.tv_nsec >1500);
284         struct tm * ptm = gmtime(&ts.tv_sec);
285         if(ptm){
286             strftime(buff, sizeof buff, "%D %T", ptm);
287             printf("RU: thread_run start time: %s.%09ld UTC [%d]\n", buff, ts.tv_nsec, interval_us_local);
288         }
289     }
290
291     return XRAN_STATUS_SUCCESS;
292
293     err0:
294     for (j = 0; j< XRAN_NUM_OF_SYMBOL_PER_SLOT; j++){
295         struct cb_elem_entry *cb_elm;
296         LIST_FOREACH(cb_elm, &p_dev_ctx->sym_cb_list_head[j], pointers){
297             if(cb_elm){
298                 LIST_REMOVE(cb_elm, pointers);
299                 xran_destroy_cb(cb_elm);
300             }
301         }
302     }
303
304     return XRAN_STATUS_FAIL;
305 }
306 int32_t
307 xran_timing_destroy_cbs(void *args)
308 {
309     int res = XRAN_STATUS_SUCCESS;
310     int32_t   do_reset = 0;
311     uint64_t  t1 = 0;
312     int32_t   result1,i,j;
313     struct xran_device_ctx * p_dev_ctx = (struct xran_device_ctx *)args;
314     struct cb_elem_entry * cb_elm = NULL;
315
316     for (j = 0; j< XRAN_NUM_OF_SYMBOL_PER_SLOT; j++){
317         struct cb_elem_entry *cb_elm;
318         LIST_FOREACH(cb_elm, &p_dev_ctx->sym_cb_list_head[j], pointers){
319             if(cb_elm){
320                 LIST_REMOVE(cb_elm, pointers);
321                 xran_destroy_cb(cb_elm);
322             }
323         }
324     }
325
326     return XRAN_STATUS_SUCCESS;
327 }
328
329 static int32_t
330 xran_reg_sym_cb_ota(struct xran_device_ctx * p_dev_ctx, xran_callback_sym_fn symCb, void * symCbParam, struct xran_sense_of_time* symCbTime,  uint8_t symb,
331     struct cb_user_per_sym_ctx **p_sym_cb_ctx)
332 {
333     int32_t ret = XRAN_STATUS_SUCCESS;
334     struct cb_user_per_sym_ctx *p_loc_sym_cb_ctx = &p_dev_ctx->symCbCtx[symb][XRAN_CB_SYM_OTA_TIME];
335     if(p_loc_sym_cb_ctx->status){
336         ret =  XRAN_STATUS_RESOURCE;
337         print_err("timer sym %d type id %d was already created",symb, XRAN_CB_SYM_OTA_TIME);
338         return ret;
339     }
340     printf("requested symb %d OTA coresponds to symb %d OTA time\n", symb, symb);
341
342     p_loc_sym_cb_ctx->symb_num_req  = symb;
343     p_loc_sym_cb_ctx->sym_diff      = 0; /* OTA and Request Symb are the same */
344     p_loc_sym_cb_ctx->symb_num_ota  = symb;
345     p_loc_sym_cb_ctx->cb_type_id    = XRAN_CB_SYM_OTA_TIME;
346     p_loc_sym_cb_ctx->p_dev         = p_dev_ctx;
347
348     p_loc_sym_cb_ctx->symCb         = symCb;
349     p_loc_sym_cb_ctx->symCbParam    = symCbParam;
350     p_loc_sym_cb_ctx->symCbTimeInfo = symCbTime;
351
352     p_loc_sym_cb_ctx->status        = 1;
353
354     *p_sym_cb_ctx = p_loc_sym_cb_ctx;
355
356     return ret;
357 }
358
359 static int32_t
360 xran_reg_sym_cb_rx_win_end(struct xran_device_ctx * p_dev_ctx, xran_callback_sym_fn symCb, void * symCbParam, struct xran_sense_of_time* symCbTime,
361     uint8_t symb, struct cb_user_per_sym_ctx **p_sym_cb_ctx)
362 {
363     int32_t ret = XRAN_STATUS_SUCCESS;
364     struct cb_user_per_sym_ctx *p_loc_sym_cb_ctx = &p_dev_ctx->symCbCtx[symb][XRAN_CB_SYM_RX_WIN_END];
365     uint32_t time_diff_us      = 0;
366     uint32_t time_diff_nSymb   = 0;
367     uint32_t absolute_ota_sym  = 0;
368     uint32_t interval_us_local = p_dev_ctx->interval_us_local;
369
370     if(p_loc_sym_cb_ctx->status) {
371         ret =  XRAN_STATUS_RESOURCE;
372         print_err("timer sym %d type id %d was already created",symb, XRAN_CB_SYM_RX_WIN_END);
373         return ret;
374     }
375
376     time_diff_us = p_dev_ctx->fh_cfg.Ta4_max;
377     printf("RX WIN end Ta4_max is %d [us] where TTI is %d [us] \n", time_diff_us, interval_us_local);
378     time_diff_nSymb = time_diff_us*1000/(interval_us_local*1000/N_SYM_PER_SLOT);
379     if ((time_diff_nSymb/1000/(interval_us_local*1000/N_SYM_PER_SLOT)) < time_diff_us) {
380         time_diff_nSymb+=1;
381         printf("time duration %d rounded up to duration of %d symbols\n", time_diff_us, time_diff_nSymb);
382     }
383     printf("U-plane UL delay %d [us] measured against OTA time [offset in symbols is %d]\n", time_diff_us, time_diff_nSymb);
384     absolute_ota_sym =  (symb + time_diff_nSymb) % XRAN_NUM_OF_SYMBOL_PER_SLOT;
385     printf("requested symb %d pkt arrival time [deadline] coresponds to symb %d OTA time\n", symb, absolute_ota_sym);
386
387     p_loc_sym_cb_ctx->symb_num_req  = symb;
388     p_loc_sym_cb_ctx->sym_diff      = -time_diff_nSymb;
389     p_loc_sym_cb_ctx->symb_num_ota  = absolute_ota_sym;
390     p_loc_sym_cb_ctx->cb_type_id    = XRAN_CB_SYM_RX_WIN_END;
391     p_loc_sym_cb_ctx->p_dev         = p_dev_ctx;
392
393     p_loc_sym_cb_ctx->symCb         = symCb;
394     p_loc_sym_cb_ctx->symCbParam    = symCbParam;
395     p_loc_sym_cb_ctx->symCbTimeInfo = symCbTime;
396
397     p_loc_sym_cb_ctx->status        = 1;
398
399     *p_sym_cb_ctx  =p_loc_sym_cb_ctx;
400
401     return ret;
402 }
403
404 static int32_t
405 xran_reg_sym_cb_rx_win_begin(struct xran_device_ctx * p_dev_ctx, xran_callback_sym_fn symCb, void * symCbParam, struct xran_sense_of_time* symCbTime,
406     uint8_t symb, struct cb_user_per_sym_ctx **p_sym_cb_ctx)
407 {
408     int32_t ret = XRAN_STATUS_SUCCESS;
409     struct cb_user_per_sym_ctx *p_loc_sym_cb_ctx = &p_dev_ctx->symCbCtx[symb][XRAN_CB_SYM_RX_WIN_BEGIN];
410     uint32_t time_diff_us      = 0;
411     uint32_t time_diff_nSymb   = 0;
412     uint32_t absolute_ota_sym  = 0;
413     uint32_t interval_us_local = p_dev_ctx->interval_us_local;
414
415     if(p_loc_sym_cb_ctx->status) {
416         ret =  XRAN_STATUS_RESOURCE;
417         print_err("timer sym %d type id %d was already created",symb, XRAN_CB_SYM_RX_WIN_BEGIN);
418         return ret;
419     }
420
421     time_diff_us = p_dev_ctx->fh_cfg.Ta4_min;
422     printf("RX WIN begin Ta4_min is %d [us] where TTI is %d [us] \n", time_diff_us, interval_us_local);
423     time_diff_nSymb = time_diff_us*1000/(interval_us_local*1000/N_SYM_PER_SLOT);
424     printf("U-plane UL delay %d [us] measured against OTA time [offset in symbols is %d]\n", time_diff_us, time_diff_nSymb);
425     absolute_ota_sym =  (symb + time_diff_nSymb) % XRAN_NUM_OF_SYMBOL_PER_SLOT;
426     printf("requested symb %d pkt arrival time [deadline] coresponds to symb %d OTA time\n", symb, absolute_ota_sym);
427
428     p_loc_sym_cb_ctx->symb_num_req  = symb;
429     p_loc_sym_cb_ctx->sym_diff      = -time_diff_nSymb;
430     p_loc_sym_cb_ctx->symb_num_ota  = absolute_ota_sym;
431     p_loc_sym_cb_ctx->cb_type_id    = XRAN_CB_SYM_RX_WIN_BEGIN;
432     p_loc_sym_cb_ctx->p_dev         = p_dev_ctx;
433
434     p_loc_sym_cb_ctx->symCb         = symCb;
435     p_loc_sym_cb_ctx->symCbParam    = symCbParam;
436     p_loc_sym_cb_ctx->symCbTimeInfo = symCbTime;
437
438     p_loc_sym_cb_ctx->status        = 1;
439
440     *p_sym_cb_ctx  =p_loc_sym_cb_ctx;
441
442     return ret;
443 }
444
445 static int32_t
446 xran_reg_sym_cb_tx_win_end(struct xran_device_ctx * p_dev_ctx, xran_callback_sym_fn symCb, void * symCbParam, struct xran_sense_of_time* symCbTime,
447     uint8_t symb, struct cb_user_per_sym_ctx **p_sym_cb_ctx)
448 {
449     int32_t ret = XRAN_STATUS_SUCCESS;
450     struct cb_user_per_sym_ctx *p_loc_sym_cb_ctx = &p_dev_ctx->symCbCtx[symb][XRAN_CB_SYM_TX_WIN_END];
451     uint32_t time_diff_us      = 0;
452     uint32_t time_diff_nSymb   = 0;
453     uint32_t absolute_ota_sym  = 0;
454     uint32_t interval_us_local = p_dev_ctx->interval_us_local;
455
456     if(p_loc_sym_cb_ctx->status) {
457         ret =  XRAN_STATUS_RESOURCE;
458         print_err("timer sym %d type id %d was already created",symb, XRAN_CB_SYM_TX_WIN_END);
459         return ret;
460     }
461
462     time_diff_us = p_dev_ctx->fh_cfg.T1a_min_up;
463     printf("TX WIN end -T1a_min_up is %d [us] where TTI is %d [us] \n", time_diff_us, interval_us_local);
464     time_diff_nSymb = time_diff_us*1000/(interval_us_local*1000/N_SYM_PER_SLOT);
465     if ((time_diff_nSymb/1000/(interval_us_local*1000/N_SYM_PER_SLOT)) < time_diff_us) {
466         time_diff_nSymb +=1;
467         printf("time duration %d rounded up to duration of %d symbols\n", time_diff_us, time_diff_nSymb);
468     }
469     printf("U-plane DL advance is %d [us] measured against OTA time [offset in symbols is %d]\n", time_diff_us, -time_diff_nSymb);
470     absolute_ota_sym =  ((symb + XRAN_NUM_OF_SYMBOL_PER_SLOT) - time_diff_nSymb) % XRAN_NUM_OF_SYMBOL_PER_SLOT;
471     printf("requested symb %d pkt tx time [deadline] corresponds to symb %d OTA time\n", symb, absolute_ota_sym);
472
473     p_loc_sym_cb_ctx->symb_num_req  = symb;
474     p_loc_sym_cb_ctx->sym_diff      = time_diff_nSymb;
475     p_loc_sym_cb_ctx->symb_num_ota  = absolute_ota_sym;
476     p_loc_sym_cb_ctx->cb_type_id    = XRAN_CB_SYM_TX_WIN_END;
477     p_loc_sym_cb_ctx->p_dev         = p_dev_ctx;
478
479     p_loc_sym_cb_ctx->symCb         = symCb;
480     p_loc_sym_cb_ctx->symCbParam    = symCbParam;
481     p_loc_sym_cb_ctx->symCbTimeInfo = symCbTime;
482
483     p_loc_sym_cb_ctx->status        = 1;
484
485     *p_sym_cb_ctx  = p_loc_sym_cb_ctx;
486
487     return ret;
488 }
489
490 static int32_t
491 xran_reg_sym_cb_tx_win_begin(struct xran_device_ctx * p_dev_ctx, xran_callback_sym_fn symCb, void * symCbParam, struct xran_sense_of_time* symCbTime,
492      uint8_t symb, struct cb_user_per_sym_ctx **p_sym_cb_ctx)
493 {
494     int32_t ret = XRAN_STATUS_SUCCESS;
495     struct cb_user_per_sym_ctx *p_loc_sym_cb_ctx = &p_dev_ctx->symCbCtx[symb][XRAN_CB_SYM_TX_WIN_BEGIN];
496     uint32_t time_diff_us      = 0;
497     uint32_t time_diff_nSymb   = 0;
498     uint32_t absolute_ota_sym  = 0;
499     uint32_t interval_us_local = p_dev_ctx->interval_us_local;
500
501     if(p_loc_sym_cb_ctx->status) {
502         ret =  XRAN_STATUS_RESOURCE;
503         print_err("timer sym %d type id %d was already created",symb, XRAN_CB_SYM_TX_WIN_BEGIN);
504         return ret;
505     }
506
507     time_diff_us = p_dev_ctx->fh_cfg.T1a_max_up;
508     printf("TX WIN begin -T1a_max_up is %d [us] where TTI is %d [us] \n", time_diff_us, interval_us_local);
509     time_diff_nSymb = (time_diff_us*1000/(interval_us_local*1000/N_SYM_PER_SLOT));
510     if ((time_diff_nSymb/1000/(interval_us_local*1000/N_SYM_PER_SLOT)) < time_diff_us) {
511         time_diff_nSymb +=1;
512         printf("time duration %d rounded up to duration of %d symbols\n", time_diff_us, time_diff_nSymb);
513     }
514     printf("U-plane DL advance is %d [us] measured against OTA time [offset in symbols is %d]\n", time_diff_us, -time_diff_nSymb);
515     printf("requested symb %d pkt tx time [deadline] corresponds to symb %d OTA time\n", symb, absolute_ota_sym);
516     absolute_ota_sym =  ((symb + XRAN_NUM_OF_SYMBOL_PER_SLOT) - time_diff_nSymb) % XRAN_NUM_OF_SYMBOL_PER_SLOT;
517
518     p_loc_sym_cb_ctx->symb_num_req  = symb;
519     p_loc_sym_cb_ctx->sym_diff      = time_diff_nSymb;
520     p_loc_sym_cb_ctx->symb_num_ota  = absolute_ota_sym;
521     p_loc_sym_cb_ctx->cb_type_id    = XRAN_CB_SYM_TX_WIN_BEGIN;
522     p_loc_sym_cb_ctx->p_dev         = p_dev_ctx;
523
524     p_loc_sym_cb_ctx->symCb         = symCb;
525     p_loc_sym_cb_ctx->symCbParam    = symCbParam;
526     p_loc_sym_cb_ctx->symCbTimeInfo = symCbTime;
527
528     p_loc_sym_cb_ctx->status        = 1;
529
530     *p_sym_cb_ctx  =p_loc_sym_cb_ctx;
531
532     return ret;
533 }
534
535 int32_t
536 xran_reg_sym_cb(void *pHandle, xran_callback_sym_fn symCb, void * symCbParam, struct xran_sense_of_time* symCbTime, uint8_t symb, enum cb_per_sym_type_id cb_sym_t_id)
537 {
538     int32_t ret = XRAN_STATUS_SUCCESS;
539     struct xran_device_ctx * p_dev_ctx       = NULL;
540     struct cb_elem_entry * cb_elm            = NULL;
541     struct cb_user_per_sym_ctx *p_sym_cb_ctx = NULL;
542     rx_dpdk_sym_cb_fn dpdk_cb_to_arm         = NULL;
543
544     if(xran_get_if_state() == XRAN_RUNNING) {
545         print_err("Cannot register callback while running!!");
546         return (-1);
547     }
548
549     if(pHandle) {
550         p_dev_ctx = (struct xran_device_ctx *)pHandle;
551     } else {
552         print_err("pHandle==NULL");
553         ret = XRAN_STATUS_INVALID_PARAM;
554         return ret;
555     }
556
557     switch (cb_sym_t_id) {
558         case XRAN_CB_SYM_OTA_TIME:
559             ret = xran_reg_sym_cb_ota(p_dev_ctx, symCb, symCbParam, symCbTime, symb, &p_sym_cb_ctx);
560             if(ret != XRAN_STATUS_SUCCESS)
561                 return ret;
562             dpdk_cb_to_arm = rx_ul_user_sym_cb;
563         break;
564         case XRAN_CB_SYM_RX_WIN_BEGIN:
565             ret = xran_reg_sym_cb_rx_win_begin(p_dev_ctx, symCb, symCbParam, symCbTime, symb, &p_sym_cb_ctx);
566             if(ret != XRAN_STATUS_SUCCESS)
567                 return ret;
568             dpdk_cb_to_arm = rx_ul_user_sym_cb;
569             break;
570         case XRAN_CB_SYM_RX_WIN_END:
571             ret = xran_reg_sym_cb_rx_win_end(p_dev_ctx, symCb, symCbParam, symCbTime, symb, &p_sym_cb_ctx);
572             if(ret != XRAN_STATUS_SUCCESS)
573                 return ret;
574             dpdk_cb_to_arm = rx_ul_user_sym_cb;
575         break;
576         case XRAN_CB_SYM_TX_WIN_BEGIN:
577             ret = xran_reg_sym_cb_tx_win_begin(p_dev_ctx, symCb, symCbParam, symCbTime, symb, &p_sym_cb_ctx);
578             if(ret != XRAN_STATUS_SUCCESS)
579                 return ret;
580             dpdk_cb_to_arm = rx_ul_user_sym_cb;
581             break;
582         case XRAN_CB_SYM_TX_WIN_END:
583             ret = xran_reg_sym_cb_tx_win_end(p_dev_ctx, symCb, symCbParam, symCbTime, symb, &p_sym_cb_ctx);
584             if(ret != XRAN_STATUS_SUCCESS)
585                 return ret;
586             dpdk_cb_to_arm = rx_ul_user_sym_cb;
587         break;
588         default:
589             /* functionality is not yet implemented */
590             print_err("Functionality is not yet implemented !");
591             ret = XRAN_STATUS_INVALID_PARAM;
592             return ret;
593     }
594
595     cb_elm = xran_create_cb(xran_timer_arm_user_cb, dpdk_cb_to_arm, (void*)p_sym_cb_ctx);
596     if(cb_elm){
597         LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[p_sym_cb_ctx->symb_num_ota],
598                             cb_elm,
599                             pointers);
600     } else {
601         print_err("cb_elm is NULL\n");
602         ret =  XRAN_STATUS_FAIL;
603         return ret;
604     }
605
606     return ret;
607 }
608
609 int32_t
610 xran_reg_physide_cb(void *pHandle, xran_fh_tti_callback_fn Cb, void *cbParam, int skipTtiNum, enum callback_to_phy_id id)
611 {
612     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();
613
614     if(xran_get_if_state() == XRAN_RUNNING) {
615         print_err("Cannot register callback while running!!\n");
616         return (-1);
617     }
618
619     p_xran_dev_ctx->ttiCb[id]      = Cb;
620     p_xran_dev_ctx->TtiCbParam[id] = cbParam;
621     p_xran_dev_ctx->SkipTti[id]    = skipTtiNum;
622
623     return 0;
624 }
625
626
627
628