1 /******************************************************************************
3 * Copyright (c) 2019 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 *******************************************************************************/
21 * @brief This file provides implementation to Timing for XRAN.
24 * @ingroup group_lte_source_xran
25 * @author Intel Corporation
34 #include "xran_timer.h"
35 #include "xran_printf.h"
37 #include "mlog_lnx_xRAN.h"
41 #include "xran_lib_mlog_tasks_id.h"
44 #define NSEC_PER_SEC 1000000000L
45 #define NSEC_PER_USEC 1000L
46 #define THRESHOLD 35 /**< the avg cost of clock_gettime() in ns */
47 #define TIMECOMPENSATION 2 /**< time compensation in us, avg latency of clock_nanosleep */
49 #define SEC_MOD_STOP (30)
51 static struct timespec started_time;
52 static struct timespec last_time;
53 static struct timespec cur_time;
55 static struct timespec* p_cur_time = &cur_time;
56 static struct timespec* p_last_time = &last_time;
58 static struct timespec* p_temp_time;
60 static unsigned long current_second = 0;
61 static unsigned long started_second = 0;
62 extern uint32_t xran_lib_ota_sym;
63 extern uint32_t xran_lib_ota_tti;
64 extern uint32_t xran_lib_ota_sym_idx;
66 static int debugStop = 0;
68 uint64_t timing_get_current_second(void)
70 return current_second;
73 int timing_set_debug_stop(int value)
78 clock_gettime(CLOCK_REALTIME, &started_time);
79 started_second =started_time.tv_sec;
84 int timing_get_debug_stop(void)
89 long poll_next_tick(long interval_ns)
93 static int counter = 0;
94 static long sym_acc = 0;
95 static long sym_cnt = 0;
98 clock_gettime(CLOCK_REALTIME, p_last_time);
99 current_second = p_last_time->tv_sec;
103 target_time = (p_last_time->tv_sec * NSEC_PER_SEC + p_last_time->tv_nsec + interval_ns);
107 clock_gettime(CLOCK_REALTIME, p_cur_time);
108 delta = (p_cur_time->tv_sec * NSEC_PER_SEC + p_cur_time->tv_nsec) - target_time;
109 if(delta > 0 || (delta < 0 && abs(delta) < THRESHOLD)) {
110 if(current_second != p_cur_time->tv_sec){
111 current_second = p_cur_time->tv_sec;
112 xran_lib_ota_sym_idx = 0;
113 xran_lib_ota_tti = 0;
114 xran_lib_ota_sym = 0;
117 print_dbg("ToS:C Sync timestamp: [%ld.%09ld]\n", p_cur_time->tv_sec, p_cur_time->tv_nsec);
119 if(p_cur_time->tv_sec > started_second && ((p_cur_time->tv_sec % SEC_MOD_STOP) == 0)){
121 printf("STOP:[%ld.%09ld]\n", p_cur_time->tv_sec, p_cur_time->tv_nsec);
124 MLogTask(PID_TIME_SYSTIME_STOP, t1, MLogTick());
125 xran_if_current_state = XRAN_STOPPED;
128 p_cur_time->tv_nsec = 0; // adjust to 1pps
130 xran_lib_ota_sym_idx = XranIncrementSymIdx(xran_lib_ota_sym_idx, 14*8);
131 /* adjust to sym boundary */
136 /* fine tune to second boundary */
137 if(sym_cnt % 13 == 0)
140 p_cur_time->tv_nsec = sym_acc;
143 if(debugStop && delta < interval_ns*10)
144 MLogTask(PID_TIME_SYSTIME_POLL, (p_last_time->tv_sec * NSEC_PER_SEC + p_last_time->tv_nsec), (p_cur_time->tv_sec * NSEC_PER_SEC + p_cur_time->tv_nsec));
145 p_temp_time = p_last_time;
146 p_last_time = p_cur_time;
147 p_cur_time = p_temp_time;
155 long sleep_next_tick(long interval)
157 struct timespec start_time;
158 struct timespec cur_time;
159 //struct timespec target_time_convert;
160 struct timespec sleep_target_time_convert;
162 long sleep_target_time;
165 clock_gettime(CLOCK_REALTIME, &start_time);
166 target_time = (start_time.tv_sec * NSEC_PER_SEC + start_time.tv_nsec + interval * NSEC_PER_USEC) / (interval * NSEC_PER_USEC) * interval;
167 //printf("target: %ld, current: %ld, %ld\n", target_time, start_time.tv_sec, start_time.tv_nsec);
168 sleep_target_time = target_time - TIMECOMPENSATION;
169 sleep_target_time_convert.tv_sec = sleep_target_time * NSEC_PER_USEC / NSEC_PER_SEC;
170 sleep_target_time_convert.tv_nsec = (sleep_target_time * NSEC_PER_USEC) % NSEC_PER_SEC;
172 //target_time_convert.tv_sec = target_time * NSEC_PER_USEC / NSEC_PER_SEC;
173 //target_time_convert.tv_nsec = (target_time * NSEC_PER_USEC) % NSEC_PER_SEC;
175 clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &sleep_target_time_convert, NULL);
177 clock_gettime(CLOCK_REALTIME, &cur_time);
179 delta = (cur_time.tv_sec * NSEC_PER_SEC + cur_time.tv_nsec) - target_time * NSEC_PER_USEC;