1 /******************************************************************************
3 * Copyright (c) 2020 Intel.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 *******************************************************************************/
20 * @brief XRAN Callback processing functionality and helper functions
21 * @file xran_cb_proc.c
22 * @ingroup group_source_xran
23 * @author Intel Corporation
28 #include <immintrin.h>
29 #include <rte_common.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>
37 #include <rte_timer.h>
40 #include "xran_fh_o_du.h"
41 #include "xran_main.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"
49 typedef void (*rx_dpdk_sym_cb_fn)(struct rte_timer *tim, void *arg);
51 void xran_timer_arm(struct rte_timer *tim, void* arg, void *p_dev_ctx)
53 struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)p_dev_ctx;
54 uint64_t t3 = MLogTick();
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);
60 MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());
63 void xran_timer_arm_cp_dl(struct rte_timer *tim, void* arg, void *p_dev_ctx)
65 struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)p_dev_ctx;
66 uint64_t t3 = MLogTick();
68 unsigned tim_lcore = xran_schedule_to_worker(XRAN_JOB_TYPE_CP_DL, p_xran_dev_ctx);
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);
74 MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());
77 void xran_timer_arm_cp_ul(struct rte_timer *tim, void* arg, void *p_dev_ctx)
79 struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)p_dev_ctx;
80 uint64_t t3 = MLogTick();
82 unsigned tim_lcore = xran_schedule_to_worker(XRAN_JOB_TYPE_CP_UL, p_xran_dev_ctx);
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);
88 MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());
91 void xran_timer_arm_for_deadline(struct rte_timer *tim, void* arg, void *p_dev_ctx)
93 struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)p_dev_ctx;
94 uint64_t t3 = MLogTick();
96 unsigned tim_lcore = xran_schedule_to_worker(XRAN_JOB_TYPE_DEADLINE, p_xran_dev_ctx);
101 uint32_t nSubframeIdx;
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)
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);
116 MLogTask(PID_TIME_ARM_TIMER_DEADLINE, t3, MLogTick());
119 void xran_timer_arm_user_cb(struct rte_timer *tim, void* arg, void *p_ctx)
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();
125 unsigned tim_lcore = xran_schedule_to_worker(XRAN_JOB_TYPE_SYM_CB, NULL);
129 uint32_t nFrameIdx = 0;
130 uint32_t nSubframeIdx = 0;
131 uint32_t nSlotIdx = 0;
132 uint64_t nSecond = 0;
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)
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;
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;
151 MLogTask(PID_TIME_ARM_USER_TIMER_DEADLINE, t3, MLogTick());
154 void xran_timer_arm_ex(struct rte_timer *tim, void* CbFct, void *CbArg, unsigned tim_lcore)
156 uint64_t t3 = MLogTick();
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);
162 MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());
166 xran_timing_create_cbs(void *args)
168 int32_t res = XRAN_STATUS_SUCCESS;
169 int32_t do_reset = 0;
172 uint32_t delay_cp_dl;
173 uint32_t delay_cp_ul;
175 uint32_t time_diff_us;
176 uint32_t delay_cp2up;
179 uint32_t time_diff_nSymb;
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;
186 /* ToS = Top of Second start +- 1.5us */
190 if (p_dev_ctx->fh_init.io_cfg.id == O_DU) {
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;
197 delay_cp2up = delay_up-delay_cp_dl;
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);
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);
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);
213 cb_elm = xran_create_cb(xran_timer_arm_cp_dl, tx_cp_dl_cb, (void*)p_dev_ctx);
215 LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[sym_cp_dl],
219 print_err("cb_elm is NULL\n");
220 res = XRAN_STATUS_FAIL;
224 cb_elm = xran_create_cb(xran_timer_arm_cp_ul, tx_cp_ul_cb, (void*)p_dev_ctx);
226 LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[sym_cp_ul],
230 print_err("cb_elm is NULL\n");
231 res = XRAN_STATUS_FAIL;
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);
238 LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[time_diff_nSymb],
242 print_err("cb_elm is NULL\n");
243 res = XRAN_STATUS_FAIL;
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);
250 LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[time_diff_nSymb + N_SYM_PER_SLOT/2],
254 print_err("cb_elm is NULL\n");
255 res = XRAN_STATUS_FAIL;
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);
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);
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);
272 LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[sym_up],
276 print_err("cb_elm is NULL\n");
282 timespec_get(&ts, TIME_UTC);
283 }while (ts.tv_nsec >1500);
284 struct tm * ptm = gmtime(&ts.tv_sec);
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);
291 return XRAN_STATUS_SUCCESS;
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){
298 LIST_REMOVE(cb_elm, pointers);
299 xran_destroy_cb(cb_elm);
304 return XRAN_STATUS_FAIL;
307 xran_timing_destroy_cbs(void *args)
309 int res = XRAN_STATUS_SUCCESS;
310 int32_t do_reset = 0;
313 struct xran_device_ctx * p_dev_ctx = (struct xran_device_ctx *)args;
314 struct cb_elem_entry * cb_elm = NULL;
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){
320 LIST_REMOVE(cb_elm, pointers);
321 xran_destroy_cb(cb_elm);
326 return XRAN_STATUS_SUCCESS;
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)
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);
340 printf("requested symb %d OTA coresponds to symb %d OTA time\n", symb, symb);
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;
348 p_loc_sym_cb_ctx->symCb = symCb;
349 p_loc_sym_cb_ctx->symCbParam = symCbParam;
350 p_loc_sym_cb_ctx->symCbTimeInfo = symCbTime;
352 p_loc_sym_cb_ctx->status = 1;
354 *p_sym_cb_ctx = p_loc_sym_cb_ctx;
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)
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;
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);
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) {
381 printf("time duration %d rounded up to duration of %d symbols\n", time_diff_us, time_diff_nSymb);
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);
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;
393 p_loc_sym_cb_ctx->symCb = symCb;
394 p_loc_sym_cb_ctx->symCbParam = symCbParam;
395 p_loc_sym_cb_ctx->symCbTimeInfo = symCbTime;
397 p_loc_sym_cb_ctx->status = 1;
399 *p_sym_cb_ctx =p_loc_sym_cb_ctx;
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)
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;
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);
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);
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;
434 p_loc_sym_cb_ctx->symCb = symCb;
435 p_loc_sym_cb_ctx->symCbParam = symCbParam;
436 p_loc_sym_cb_ctx->symCbTimeInfo = symCbTime;
438 p_loc_sym_cb_ctx->status = 1;
440 *p_sym_cb_ctx =p_loc_sym_cb_ctx;
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)
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;
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);
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) {
467 printf("time duration %d rounded up to duration of %d symbols\n", time_diff_us, time_diff_nSymb);
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);
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;
479 p_loc_sym_cb_ctx->symCb = symCb;
480 p_loc_sym_cb_ctx->symCbParam = symCbParam;
481 p_loc_sym_cb_ctx->symCbTimeInfo = symCbTime;
483 p_loc_sym_cb_ctx->status = 1;
485 *p_sym_cb_ctx = p_loc_sym_cb_ctx;
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)
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;
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);
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) {
512 printf("time duration %d rounded up to duration of %d symbols\n", time_diff_us, time_diff_nSymb);
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;
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;
524 p_loc_sym_cb_ctx->symCb = symCb;
525 p_loc_sym_cb_ctx->symCbParam = symCbParam;
526 p_loc_sym_cb_ctx->symCbTimeInfo = symCbTime;
528 p_loc_sym_cb_ctx->status = 1;
530 *p_sym_cb_ctx =p_loc_sym_cb_ctx;
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)
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;
544 if(xran_get_if_state() == XRAN_RUNNING) {
545 print_err("Cannot register callback while running!!");
550 p_dev_ctx = (struct xran_device_ctx *)pHandle;
552 print_err("pHandle==NULL");
553 ret = XRAN_STATUS_INVALID_PARAM;
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)
562 dpdk_cb_to_arm = rx_ul_user_sym_cb;
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)
568 dpdk_cb_to_arm = rx_ul_user_sym_cb;
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)
574 dpdk_cb_to_arm = rx_ul_user_sym_cb;
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)
580 dpdk_cb_to_arm = rx_ul_user_sym_cb;
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)
586 dpdk_cb_to_arm = rx_ul_user_sym_cb;
589 /* functionality is not yet implemented */
590 print_err("Functionality is not yet implemented !");
591 ret = XRAN_STATUS_INVALID_PARAM;
595 cb_elm = xran_create_cb(xran_timer_arm_user_cb, dpdk_cb_to_arm, (void*)p_sym_cb_ctx);
597 LIST_INSERT_HEAD(&p_dev_ctx->sym_cb_list_head[p_sym_cb_ctx->symb_num_ota],
601 print_err("cb_elm is NULL\n");
602 ret = XRAN_STATUS_FAIL;
610 xran_reg_physide_cb(void *pHandle, xran_fh_tti_callback_fn Cb, void *cbParam, int skipTtiNum, enum callback_to_phy_id id)
612 struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();
614 if(xran_get_if_state() == XRAN_RUNNING) {
615 print_err("Cannot register callback while running!!\n");
619 p_xran_dev_ctx->ttiCb[id] = Cb;
620 p_xran_dev_ctx->TtiCbParam[id] = cbParam;
621 p_xran_dev_ctx->SkipTti[id] = skipTtiNum;