1 /*
2 * Copyright (c) 2017 Oticon A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "bs_types.h"
7 #include "bs_tracing.h"
8 #include "bs_pc_2G4.h"
9 #include "NRF_HWLowL.h"
10 #include "time_machine_if.h"
11 #include "xo_if.h"
12
13 /*
14 * Do not actually connect to the phy.
15 * This is a minor debug switch to allow running the device without needing
16 * to run the phy. It can be useful if for example the device crashes
17 * during boot, or if running a test without any radio activity.
18 * Note that as soon as the radio attempts to have any activity the
19 * device will crash with a "not connected" error
20 */
21 static bool nosim;
22
hwll_set_nosim(bool new_nosim)23 void hwll_set_nosim(bool new_nosim){
24 nosim = new_nosim;
25 }
26
27 /**
28 * Return the equivalent phy time from a device time
29 */
hwll_phy_time_from_dev(bs_time_t d_t)30 bs_time_t hwll_phy_time_from_dev(bs_time_t d_t){
31 bs_time_t phy_t;
32 if ( d_t != TIME_NEVER ) {
33 phy_t = (bs_time_t)(1e6*phy_time_from_dev(((long double)d_t)*1e-6 ) + 0.5);
34 //Note: in x86 compiling with GCC for linux long double is 80bit (64bits
35 // mantissa), and therefore precission should be kept
36 } else {
37 phy_t = TIME_NEVER;
38 }
39 return phy_t;
40 }
41
42 /**
43 * Return the equivalent device time from a phy time
44 */
hwll_dev_time_from_phy(bs_time_t p_t)45 uint64_t hwll_dev_time_from_phy(bs_time_t p_t){
46 bs_time_t dev_t;
47 if ( p_t != TIME_NEVER ) {
48 dev_t = (bs_time_t)(1e6*dev_time_from_phy(((long double)p_t)*1e-6 ) + 0.5);
49 //Note: in x86 compiling with GCC for linux long double is 80bit (64bits
50 // mantissa), and therefore precission should be kept
51 } else {
52 dev_t = p_t;
53 }
54 return dev_t;
55 }
56
57 /**
58 * Every time we would like to "inform" the phy about our timing
59 * (if we are advancing it a lot relative to the phy time while idling in the radio)
60 * we can use this function to cause a wait
61 */
hwll_sync_time_with_phy(bs_time_t d_time)62 void hwll_sync_time_with_phy(bs_time_t d_time) {
63 if (nosim)
64 return;
65
66 pb_wait_t wait;
67
68 if ( d_time != TIME_NEVER ){
69 wait.end = hwll_phy_time_from_dev(d_time - 2);
70 //Wait for 2us less than the actual time, to allow for error with the
71 //rounding of the clock drift + 1 us extra in case the next Tx or Rx
72 //happens just in this same Time
73 } else {
74 wait.end = TIME_NEVER;
75 }
76
77 if ( p2G4_dev_req_wait_nc_b(&wait) != 0){
78 bs_trace_raw_manual_time(3, d_time, "The phy disconnected us\n");
79 hwll_disconnect_phy_and_exit();
80 }
81 }
82
83 /**
84 * Connect to the phy
85 */
hwll_connect_to_phy(uint d,const char * s,const char * p)86 int hwll_connect_to_phy(uint d, const char* s, const char* p){
87 if (!nosim) {
88 return p2G4_dev_initcom_nc(d, s, p);
89 } else {
90 return 0;
91 }
92 }
93
94 /**
95 * Disconnect from the phy, and ask it to end the simulation
96 */
hwll_terminate_simulation()97 void hwll_terminate_simulation(){
98 if (!nosim) {
99 p2G4_dev_terminate_nc();
100 }
101 }
102
103 /**
104 * Disconnect from the phy, but let the simulation continue without us
105 */
hwll_disconnect_phy()106 void hwll_disconnect_phy(){
107 if (!nosim) {
108 p2G4_dev_disconnect_nc();
109 }
110 }
111
112 /**
113 * Terminate the simulation for this device:
114 * Disconnection from the phy and exit
115 */
hwll_disconnect_phy_and_exit()116 void hwll_disconnect_phy_and_exit(){
117 hwll_disconnect_phy();
118 bs_trace_exit_line("\n");
119 }
120