1 /*
2 * Copyright (c) 2017 Oticon A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 //Simple model of a constant XO drift
7
8 #include "bs_tracing.h"
9 #include "bs_types.h"
10 #include "nsi_tasks.h"
11 #include "weak_stubs.h"
12
13 static double xo_drift = 0.0; //Crystal oscillator drift relative to the phy
14 static double time_off = 0.0; //Time offset relative to the phy
15
dev_time_from_phy(long double p_t)16 long double __attribute__((weak)) dev_time_from_phy(long double p_t){
17 long double dev_time;
18 dev_time = ((1.0 + xo_drift)*(long double)p_t) - time_off;
19 //Note: in x86 compiling with GCC for Linux long double is 80bit (64bits
20 // mantissa), and therefore precision should be kept
21 return dev_time;
22 }
23
phy_time_from_dev(long double d_t)24 long double __attribute__((weak)) phy_time_from_dev(long double d_t){
25 long double phy_time;
26 phy_time = ((long double)(d_t + time_off))/(1.0 + xo_drift);
27 //Note: in x86 compiling with GCC for Linux long double is 80bit (64bits
28 // mantissa), and therefore precision should be kept
29 return phy_time;
30 }
31
xo_model_set_toffset(double t_off)32 void xo_model_set_toffset(double t_off) {
33 time_off = ((double)t_off)/1e6;
34 }
35
36 static double tmp_xo_drift;
37
arg_xo_drift_found(char * argv,int offset)38 static void arg_xo_drift_found(char * argv, int offset) {
39 xo_drift = tmp_xo_drift;
40 }
41
trivial_xo_register_cmd_args(void)42 static void trivial_xo_register_cmd_args(void) {
43
44 static bs_args_struct_t args_struct_toadd[] = {
45 {
46 .option = "xo_drift",
47 .name = "xo_drift",
48 .type = 'f',
49 .dest = (void*)&tmp_xo_drift,
50 .call_when_found = arg_xo_drift_found,
51 .descript = "Simple linear model of the XO drift of this device. For ex. for -30ppm set to -30e-6"
52 },
53 ARG_TABLE_ENDMARKER
54 };
55
56 bs_add_extra_dynargs(args_struct_toadd);
57 }
58
59 NSI_TASK(trivial_xo_register_cmd_args, PRE_BOOT_1, 100);
60
trivial_xo_init(void)61 static void trivial_xo_init(void) {
62 if ((xo_drift < -3e-4) || (xo_drift > 3e-4)) {
63 bs_trace_warning_line("Very high clock drift set (%0.f ppm > 300ppm)\n", xo_drift*1e6);
64 if ((xo_drift < -1e-2) || (xo_drift > 1e-2)) {
65 bs_trace_error_line("Insane clock drift set (%0.f ppm)\n", xo_drift*1e6);
66 }
67 }
68 }
69
70 NSI_TASK(trivial_xo_init, HW_INIT, 100);
71