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