mbgtools-lx  4.2.8
mbghrtime.c
Go to the documentation of this file.
1 
2 /**************************************************************************
3  *
4  * $Id: mbghrtime.c 1.13 2018/11/15 12:12:34 martin TRASH $
5  *
6  * Description:
7  * Main file for mbghrtime program which demonstrates how to access
8  * a Meinberg device via IOCTL calls to read high resolution
9  * time stamps, if supported by the device.
10  *
11  * -----------------------------------------------------------------------
12  * $Log: mbghrtime.c $
13  * Revision 1.13 2018/11/15 12:12:34 martin
14  * Individual MBG_MICRO_VERSION codes are now obsolete.
15  * Revision 1.12 2017/07/05 19:02:13 martin
16  * New way to maintain version information.
17  * Support build under Windows.
18  * Support raw and burst mode.
19  * New options -s, -u, -v.
20  * Parameters -u and -s imply -c.
21  * Use more functions from common library modules.
22  * Use codes and inline functions from mbgerror.h.
23  * Proper return codes and exit codes.
24  * Revision 1.11 2010/05/21 12:54:33 martin
25  * Print warning if no cycles supported on the target platform
26  * and thus latencies can not be computed.
27  * Revision 1.10 2009/09/29 15:02:15 martin
28  * Updated version number to 3.4.0.
29  * Revision 1.9 2009/07/24 09:50:08 martin
30  * Updated version number to 3.3.0.
31  * Revision 1.8 2009/06/19 14:03:53 martin
32  * Use common mbg_print_hr_timestamp() for unified output format.
33  * Updated version number to 3.2.0.
34  * Revision 1.7 2009/03/20 11:45:16 martin
35  * Updated version number to 3.1.0.
36  * Updated copyright year to include 2009.
37  * Call mbg_get_hr_time_comp() instead of mbg_get_hr_time_cycles().
38  * Revision 1.6 2008/12/22 12:02:00 martin
39  * Updated description, copyright, revision number and string.
40  * Use unified functions from toolutil module.
41  * Accept device name(s) on the command line.
42  * Revision 1.5 2007/07/24 09:32:41 martin
43  * Updated copyright to include 2007.
44  * Revision 1.4 2004/11/08 15:45:22 martin
45  * Modifications to support 64 bit systems in a clean way.
46  * Revision 1.3 2003/04/25 10:28:05 martin
47  * Use new functions from mbgdevio library.
48  * New program version v2.1.
49  * Revision 1.2 2001/11/30 10:01:49 martin
50  * Account for the modified definition of PCPS_HR_TIME which
51  * uses the new structure PCPS_TIME_STAMP now.
52  * Revision 1.1 2001/09/17 15:08:31 martin
53  *
54  **************************************************************************/
55 
56 // include Meinberg headers
57 #include <mbgdevio.h>
58 #include <toolutil.h> // common utility functions
59 
60 // include system headers
61 #include <time.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 
65 
66 
67 #define MBG_FIRST_COPYRIGHT_YEAR 2001
68 #define MBG_LAST_COPYRIGHT_YEAR 0 // use default
69 
70 static const char *pname = "mbghrtime";
71 
72 
73 #define MAX_TS_BURST 1000
74 
75 static int loops;
76 static int burst_read;
77 static int read_raw;
78 static long sleep_secs;
79 static long sleep_usecs;
80 static int verbose;
81 
82 
83 
84 // The function below reads a number of time stamps and prints
85 // each timestamp immediately. This is not as fast as possible
86 // since printing the time stamp takes some time to execute.
87 // However, this can run continuously forever.
88 
89 static /*HDR*/
91 {
92  PCPS_HR_TIME ht = { { 0 } };
93  PCPS_HR_TIME prv_ht = { { 0 } };
94  PCPS_TIME_STAMP *p = NULL;
95  int32_t hns_latency = 0;
96  int this_loops = loops;
97 
98  for (;;)
99  {
100  int rc = read_raw ? mbg_get_hr_time( dh, &ht ) :
101  mbg_get_hr_time_comp( dh, &ht, &hns_latency );
102 
103  if ( mbg_cond_err_msg( rc, "mbg_get_hr_time_..." ) )
104  goto fail;
105 
106  mbg_print_hr_time( &ht, hns_latency, p, read_raw, verbose, verbose );
107 
108  prv_ht = ht;
109  p = &prv_ht.tstamp;
110 
111  if ( this_loops > 0 )
112  this_loops--;
113 
114  if ( this_loops == 0 )
115  break;
116 
117  if ( sleep_secs )
118  sleep( sleep_secs );
119  else
120  if ( sleep_usecs )
121  usleep( sleep_usecs );
122 
123  // if this_loops is < 0 then loop forever
124  }
125 
126  return 0;
127 
128 fail:
129  return -1;
130 
131 } // show_hr_timestamp
132 
133 
134 
135 // The function below takes a number of time stamps and saves
136 // them to a buffer. After the time stamps have been read
137 // a second loop prints the time stamps from the buffer.
138 // This way the time stamps are read in shorter intervals.
139 // However, this can not run continuously forever since
140 // the buffer size is somewhat limited.
141 
142 static /*HDR*/
144 {
145  PCPS_HR_TIME ht[MAX_TS_BURST] = { { { 0 } } };
146  int32_t hns_latency[MAX_TS_BURST];
147  int this_loops;
148  int i;
149 
150  this_loops = ( loops && ( loops < MAX_TS_BURST ) ) ? loops : MAX_TS_BURST;
151 
152 
153  if ( read_raw )
154  {
155  for ( i = 0; i < this_loops; i++ )
156  {
157  int rc = mbg_get_hr_time( dh, &ht[i] );
158 
159  if ( mbg_cond_err_msg( rc, "mbg_get_hr_time" ) )
160  goto fail;
161  }
162  }
163  else
164  for ( i = 0; i < this_loops; i++ )
165  {
166  int rc = mbg_get_hr_time_comp( dh, &ht[i], &hns_latency[i] );
167 
168  if ( mbg_cond_err_msg( rc, "mbg_get_hr_time_comp" ) )
169  goto fail;
170  }
171 
172  for ( i = 0; i < this_loops; i++ )
173  {
174  PCPS_HR_TIME *p_prv_ht = i ? &ht[i - 1] : NULL;
175  mbg_print_hr_time( &ht[i], hns_latency[i], &p_prv_ht->tstamp, read_raw, verbose, verbose );
176  }
177 
178  return 0;
179 
180 
181 fail:
182  return -1;
183 
184 } // show_hr_timestamp_burst
185 
186 
187 
188 static /*HDR*/
189 int do_mbghrtime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
190 {
191  int rc = mbg_chk_dev_has_hr_time( dh );
192 
193  if ( mbg_rc_is_error( rc ) )
194  {
195  if ( rc == MBG_ERR_NOT_SUPP_BY_DEV ) // ### TODO not_supp
196  printf( "High resolution time not supported by this device.\n" );
197  else
198  mbg_cond_err_msg( rc, "mbg_chk_dev_has_hr_time" );
199 
200  goto done;
201  }
202 
203  if ( burst_read )
205  else
206  show_hr_timestamp( dh );
207 
208 done:
209  return rc;
210 
211 } // do_mbghrtime
212 
214 
215 
216 
217 static /*HDR*/
218 void usage( void )
219 {
221  "This example program reads high resolution time stamps (HR time)\n"
222  "from a device.\n"
223  "This works only for devices which support high resolution time (HR time)."
224  );
226  mbg_print_opt_info( "-c", "run continuously" );
227  mbg_print_opt_info( "-n num", "run num loops" );
228  mbg_print_opt_info( "-b", "burst read" );
229  mbg_print_opt_info( "-r", "read raw time stamps, no cycles" );
230  mbg_print_opt_info( "-s num", "sleep num seconds between calls (implies -c)" );
231  mbg_print_opt_info( "-u num", "sleep num microseconds between calls (implies -c)" );
232  mbg_print_opt_info( "-v", "increase verbosity" );
234  puts( "" );
235 
236 } // usage
237 
238 
239 
240 int main( int argc, char *argv[] )
241 {
242  int rc;
243  int c;
244 
246 
247  // check command line parameters
248  while ( ( c = getopt( argc, argv, "bcn:rs:u:vh?" ) ) != -1 )
249  {
250  switch ( c )
251  {
252  case 'b':
253  burst_read = 1;
254  break;
255 
256  case 'c':
257  loops = -1;
258  break;
259 
260  case 'n':
261  loops = atoi( optarg );
262  break;
263 
264  case 'r':
265  read_raw = 1;
266  break;
267 
268  case 's':
269  sleep_secs = atoi( optarg );
270  loops = -1;
271  break;
272 
273  case 'u':
274  sleep_usecs = atoi( optarg );
275  loops = -1;
276  break;
277 
278  case 'v':
279  verbose++;
280  break;
281 
282  case 'h':
283  case '?':
284  default:
285  must_print_usage = 1;
286  }
287  }
288 
289  if ( must_print_usage )
290  {
291  usage();
292  return MBG_EXIT_CODE_USAGE;
293  }
294 
295 
296  #if !MBG_PC_CYCLES_SUPPORTED
297  printf( "** Warning: No cycles support to compute real latencies on this platform!\n" );
298 
299  if ( !read_raw )
300  {
301  read_raw = 1;
302  printf( "** Falling back to raw mode.\n" );
303  }
304 
305  printf( "\n" );
306  #endif
307 
308 
309  // Handle each of the specified devices.
310  rc = mbg_handle_devices( argc, argv, optind, do_mbghrtime, 0 );
311 
313 }
static MBG_DEV_HANDLER_FNC do_mbghrtime
Definition: mbghrtime.c:213
#define MBG_LAST_COPYRIGHT_YEAR
Definition: mbghrtime.c:68
static const char * pname
Definition: mbghrtime.c:70
int mbg_handle_devices(int argc, char *argv[], int optind, MBG_DEV_HANDLER_FNC *fnc, int chk_dev_flags)
Main action handler that can be called by utility programs.
Definition: toolutil.c:655
int must_print_usage
static int read_raw
Definition: mbghrtime.c:77
static long sleep_usecs
Definition: mbghrtime.c:79
void mbg_print_hr_time(PCPS_HR_TIME *p_ht, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int no_latency, int show_raw, int verbose)
Print date and time from a PCPS_HR_TIME structure.
Definition: toolutil.c:956
Requested action completed successfully.
Definition: mbgerror.h:631
static int verbose
Definition: mbghrtime.c:80
#define MAX_TS_BURST
Definition: mbghrtime.c:73
bool mbg_cond_err_msg(int rc, const char *what)
Check if a value is an error code and print an associated error message.
Definition: mbgerror.c:714
Unable to handle requested action, usage printed.
Definition: mbgerror.h:632
_MBG_API_ATTR int _MBG_API mbg_get_hr_time(MBG_DEV_HANDLE dh, PCPS_HR_TIME *p)
Read the card&#39;s current time with high resolution, including status.
Definition: mbgdevio.c:4625
#define mbg_rc_is_success(_rc)
Definition: mbgerror.h:618
MBG_CHK_SUPP_FNC mbg_chk_dev_has_hr_time
Check if a device supports the mbg_get_hr_time... functions.
Definition: mbgdevio.c:1360
static int burst_read
Definition: mbghrtime.c:76
#define MBG_FIRST_COPYRIGHT_YEAR
Definition: mbghrtime.c:67
void mbg_print_device_options(void)
Print common info on how to specify devices on the command line.
Definition: toolutil.c:270
void mbg_print_usage_intro(const char *pname, const char *info)
Print usage intro to console.
Definition: toolutil.c:217
static int show_hr_timestamp(MBG_DEV_HANDLE dh)
Definition: mbghrtime.c:90
int main(int argc, char *argv[])
Definition: mbghrtime.c:240
static long sleep_secs
Definition: mbghrtime.c:78
PCPS_TIME_STAMP tstamp
High resolution time stamp (UTC)
Definition: pcpsdefs.h:1087
static int loops
Definition: mbghrtime.c:75
int MBG_DEV_HANDLER_FNC(MBG_DEV_HANDLE, const PCPS_DEV *)
The type of functions to called to handle a device in a specific way.
Definition: toolutil.h:144
Action failed for specified device.
Definition: mbgerror.h:634
static void usage(void)
Definition: mbghrtime.c:218
High resolution time including status and local time offset.
Definition: pcpsdefs.h:1085
static int show_hr_timestamp_burst(MBG_DEV_HANDLE dh)
Definition: mbghrtime.c:143
void mbg_print_help_options(void)
Print info on common program help arguments.
Definition: toolutil.c:257
A high resolution time stamp.
Definition: pcpsdefs.h:972
void mbg_print_opt_info(const char *opt_name, const char *opt_info)
Print info on a single program option / argument.
Definition: toolutil.c:236
#define MBG_ERR_NOT_SUPP_BY_DEV
Command or feature not supported by device.
Definition: mbgerror.h:286
#define mbg_rc_is_error(_rc)
Definition: mbgerror.h:617
void mbg_print_program_info(const char *pname, int first_year, int last_year)
Print program info to console.
Definition: toolutil.c:193
_MBG_API_ATTR int _MBG_API mbg_get_hr_time_comp(MBG_DEV_HANDLE dh, PCPS_HR_TIME *p, int32_t *hns_latency)
Read the current high resolution time, and compensate the call&#39;s latency.
Definition: mbgdevio.c:6739
Device info structure.
Definition: pcpsdev.h:1043