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   (void) argv;
40   (void) offset;
41   xo_drift = tmp_xo_drift;
42 }
43 
trivial_xo_register_cmd_args(void)44 static void trivial_xo_register_cmd_args(void) {
45 
46   static bs_args_struct_t args_struct_toadd[] = {
47     {
48       .option = "xo_drift",
49       .name = "xo_drift",
50       .type = 'f',
51       .dest = (void*)&tmp_xo_drift,
52       .call_when_found = arg_xo_drift_found,
53       .descript = "Simple linear model of the XO drift of this device. For ex. for -30ppm set to -30e-6"
54     },
55     ARG_TABLE_ENDMARKER
56   };
57 
58   bs_add_extra_dynargs(args_struct_toadd);
59 }
60 
61 NSI_TASK(trivial_xo_register_cmd_args, PRE_BOOT_1, 100);
62 
trivial_xo_init(void)63 static void trivial_xo_init(void) {
64   if ((xo_drift < -3e-4) || (xo_drift > 3e-4)) {
65     bs_trace_warning_line("Very high clock drift set (%0.f ppm > 300ppm)\n", xo_drift*1e6);
66     if ((xo_drift < -1e-2) || (xo_drift > 1e-2)) {
67       bs_trace_error_line("Insane clock drift set (%0.f ppm)\n", xo_drift*1e6);
68     }
69   }
70 }
71 
72 NSI_TASK(trivial_xo_init, HW_INIT, 100);
73