1 /*
2  * Copyright 2018 Oticon A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <time.h>
7 #include <stdint.h>
8 #include "bs_tracing.h"
9 #include "bs_pc_base.h"
10 #include "bs_types.h"
11 #include "bs_handbrake_args.h"
12 
13 /**
14  * This device slows down a simulation close to a given ratio of the real time
15  */
16 pb_dev_state_t pb_dev_state = {0};
17 
clean_up()18 static uint8_t clean_up() {
19   bs_trace_raw(8,"Cleaning up\n");
20   pb_dev_disconnect(&pb_dev_state);
21   return 0;
22 }
23 
main(int argc,char * argv[])24 int main(int argc, char *argv[]) {
25   handbrake_args_t args;
26 
27   bs_trace_register_cleanup_function(clean_up);
28   bs_handbrake_argparse(argc, argv, &args);
29 
30   bs_trace_raw(9,"Connecting...\n");
31   pb_dev_init_com(&pb_dev_state, args.device_nbr, args.s_id, args.p_id);
32 
33   uint Stop = 0;
34   pb_wait_t wait_s;
35   struct timespec tv;
36 
37   //we first wait 1us to enable all devices to do their basic initialization
38   wait_s.end = args.poke_period;
39   if ( pb_dev_request_wait_block(&pb_dev_state, &wait_s) == -1 ){
40     bs_trace_raw(3,"We have been terminated\n");
41     Stop = 1;
42   }
43 
44   clock_gettime(CLOCK_MONOTONIC, &tv);
45   bs_time_t Expected_time = tv.tv_sec*1e6 + tv.tv_nsec/1000;
46 
47   while ( !Stop ) {
48     wait_s.end += args.poke_period;
49     if ( pb_dev_request_wait_block(&pb_dev_state, &wait_s) == -1 ){
50       bs_trace_raw(3,"We have been terminated\n");
51       break;
52     }
53     Expected_time += (bs_time_t)(( (double)args.poke_period ) / args.real_time_ratio);
54     clock_gettime(CLOCK_MONOTONIC, &tv);
55     bs_time_t RealCurrentTime = tv.tv_sec*1e6 + tv.tv_nsec/1000;
56     int64_t diff = Expected_time - RealCurrentTime;
57 
58     bs_trace_raw(7,"Diff = %li\n",diff);
59     if ( diff > 0 ){
60       struct timespec requested_time;
61       struct timespec remaining;
62 
63       requested_time.tv_sec = diff / 1e6;
64       requested_time.tv_nsec = ( diff - requested_time.tv_sec*1e6 )*1e3;
65       int s = nanosleep(&requested_time, &remaining);
66       if ( s == -1 ){
67         bs_trace_warning_line("Interrupted or error\n");
68         break;
69       }
70       bs_trace_raw(6,"@%"PRItime" Stalled until real time = %"PRIuMAX"\n", wait_s.end, (uintmax_t)Expected_time);
71     }
72   }
73 
74   bs_trace_raw(9,"Disconnecting...\n");
75   pb_dev_disconnect(&pb_dev_state);
76 
77   bs_trace_silent_exit(0);
78 }
79