mbgtools-lx  4.2.8
mbgtcrcal.c
Go to the documentation of this file.
1 
2 /**************************************************************************
3  *
4  * $Id: mbgtcrcal.c 1.13 2018/12/14 13:04:53 martin TRASH $
5  *
6  * Description:
7  * Main file for mbgtcrcal program which can be used to calibrate
8  * the IRIG input of some TCR cards.
9  *
10  * -----------------------------------------------------------------------
11  * $Log: mbgtcrcal.c $
12  * Revision 1.13 2018/12/14 13:04:53 martin
13  * Unified usage output.
14  * Use predefined macros to check return codes.
15  * Revision 1.12 2018/12/11 16:15:39 martin
16  * Fixed compiler warning on Windows.
17  * Revision 1.11 2018/12/11 11:57:32Z martin
18  * Fixed compiler warnings on Windows.
19  * Revision 1.10 2018/11/15 12:39:29Z martin
20  * Individual MBG_MICRO_VERSION codes are now obsolete.
21  * Revision 1.9 2017/07/03 17:33:50 martin
22  * Account for renamed library symbols.
23  * Revision 1.8 2017/06/22 15:26:55 martin
24  * Proper return codes and exit codes.
25  * Revision 1.7 2016/10/20 14:12:42 martin
26  * Unified usage information.
27  * Revision 1.6 2016/08/10 12:54:07 martin
28  * Check for MBG_TGT_POSIX instead of MBG_TGT_UNIX.
29  * Revision 1.5 2016/07/22 09:53:54 martin
30  * Use new, safe library functions.
31  * Revision 1.4 2013/12/04 10:00:14 martin
32  * Fixed build under Windows.
33  * Revision 1.3 2013/07/22 16:26:42Z martin
34  * Updated a comment.
35  * Revision 1.2 2013/07/11 08:28:44 martin
36  * Account for modified function call parameter list.
37  * Revision 1.1 2012/01/17 14:04:22 martin
38  * Initial revision.
39  *
40  **************************************************************************/
41 
42 // include Meinberg headers
43 #include <irig_cal.h>
44 #include <toolutil.h> // common utility functions
45 #include <str_util.h>
46 
47 // include system headers
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <errno.h>
52 
53 
54 #define MBG_FIRST_COPYRIGHT_YEAR 2012
55 #define MBG_LAST_COPYRIGHT_YEAR 0 // use default
56 
57 
58 static const char *pname = "mbgtcrcal";
59 
60 static int verbose;
61 
64 
65 static double cal_val; // [microseconds]
66 static int must_set_cal_val;
67 static size_t max_label_len; // determined at runtime
68 
69 
70 
71 static /*HDR*/
72 char *str_comp_data( char *s, int max_len, int comp_data )
73 {
74  div_t dt = div( comp_data, 10 );
75 
76  snprintf_safe( s, max_len, "%i.%i", dt.quot, abs ( dt.rem ) );
77 
78  return s;
79 
80 } // str_comp_data
81 
82 
83 
84 static /*HDR*/
85 void print_cal_recs( int num_rec, int curr_group_idx, CAL_REC_IRIG_RX_COMP cal_rec_comp[] )
86 {
87  int idx;
88  char ws[20];
89 
90  for ( idx = 0; idx < num_rec; idx++ )
91  {
92  CAL_REC_IRIG_RX_COMP *p = &cal_rec_comp[idx];
93  int l = (int) ( max_label_len - strlen( irig_comp_names[idx] ) + 1 );
94 
95  printf( " Signal group %i (%s)%-*c %s", idx, irig_comp_names[idx], l, ':',
96  str_comp_data( ws, sizeof( ws ), p->comp_data.c[0] ) );
97 
98  if ( verbose )
99  {
100  int i;
101 
102  for ( i = 1; i < N_IRIG_RX_COMP_VAL; i++ )
103  printf( ", %s", str_comp_data( ws, sizeof( ws ), p->comp_data.c[i] ) );
104  }
105 
106  printf( " us\n" );
107  }
108 
109 } // print_cal_recs
110 
111 
112 
113 static /*HDR*/
114 int do_mbgtcrcal( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
115 {
117  CAL_REC_IRIG_RX_COMP cal_rec_comp[N_IRIG_RX_COMP] = { { { 0 } } };
119  int ret_val = MBG_SUCCESS;
120  int num_rec = 0;
121  int rc;
122  uint16_t idx;
123  char ws[20];
124  int curr_group_idx;
125 
126 
127  // check if this device provides an IRIG input
128  if ( !_pcps_is_irig_rx( p_dev ) )
129  {
130  printf( "This device does not provide an IRIG input.\n" );
131  goto done;
132  }
133 
134 
135  // read the current IRIG input configuration
136  rc = mbg_get_irig_rx_info( dh, &irig_rx_info );
137 
138  if ( mbg_rc_is_error( rc ) )
139  {
140  printf( "** Failed to read IRIG RX configuration, rc: %i\n", rc );
141  goto done;
142  }
143 
144 
145  // check if the currently configured IRIG code is supported by this program
146  if ( irig_rx_info.settings.icode >= N_ICODE_RX )
147  {
148  printf( "IRIG code %i configured on this device exceeds the maximum code supported by this program (%i)!\n",
149  irig_rx_info.settings.icode, N_ICODE_RX - 1 );
150  goto done;
151  }
152 
153  // determine the compensation code group for the current IRIG code
154  curr_group_idx = mbg_icode_rx_to_group_idx( irig_rx_info.settings.icode );
155 
156  if ( curr_group_idx < 0 )
157  printf( "Warning: Unable to assign IRIG RX code %s to a know compensation code group.\n",
158  icode_rx_names[irig_rx_info.settings.icode] );
159 
160  // We may continue here and display the current settings,
161  // but we will not be able to assign and save new settings.
162 
163 
164  if ( !_pcps_has_generic_io( p_dev ) )
165  {
166  printf( "This device does not support IRIG calibration\n" );
167  goto done;
168  }
169 
170 
171  // read current compensation settings
172  rc = mbg_get_cal_rec_irig_rx_num_rec( dh, &num_rec );
173 
174  #if defined( DEBUG )
175  printf( "mbg_get_cal_rec_irig_rx_num_rec() returned %i", rc );
176 
177  if ( mbg_rc_is_success( rc ) )
178  printf( ", irig_rx_num_rec: %i", num_rec );
179 
180  printf( "\n" );
181  #endif
182 
183  if ( mbg_rc_is_error( rc ) )
184  {
185  printf( "** Failed to read number of IRIG RX calibration records, rc: %i\n", rc );
186  goto done;
187  }
188 
189 
190  // do some plausibility checks
191 
192  if ( curr_group_idx >= num_rec )
193  {
194  printf( "** Warning: the compensation group index for the current IRIG code (%i)\n"
195  "exceeds the number of records supported by the card (%i).\n",
196  curr_group_idx, num_rec - 1 );
197  }
198 
199 
200  if ( num_rec > N_IRIG_RX_COMP )
201  {
202  printf( "** The number of calibration records actually supported by the card (%i)\n"
203  "exceeds the number of records supported by this program (%i).\n",
204  num_rec, N_IRIG_RX_COMP );
205  num_rec = N_IRIG_RX_COMP;
206  }
207 
208 
209  if ( num_rec == 0 )
210  {
211  printf( "** This card does not support any IRIG RX calibration records\n" );
212  goto done;
213  }
214 
215 
216  // determine the maximum length of the group names to be displayed later
217  for ( idx = 0; idx < num_rec; idx++ )
218  {
219  size_t l = strlen( irig_comp_names[idx] );
220 
221  if ( l > max_label_len )
222  max_label_len = l;
223  }
224 
225 
226  for ( idx = 0; idx < num_rec; idx++ )
227  {
228  p = &cal_rec_comp[idx];
229 
230  rc = mbg_get_cal_rec_irig_rx_comp( dh, idx, p );
231 
232  if ( mbg_rc_is_error( rc ) )
233  {
234  printf( "** Failed to read IRIG RX calibration record #%i. rc = %i\n", idx, rc );
235  goto done;
236  }
237 
238  if ( p->hdr.type != CAL_REC_TYPE_IRIG_RX_COMP )
239  {
240  printf( "** Calibration record header type is %i, no %i as expected.\n",
242  goto done;
243  }
244  }
245 
246  printf( "\nCurrent compensation settings:\n" );
247 
248  print_cal_recs( num_rec, curr_group_idx, cal_rec_comp );
249 
250  printf( "\nCurrent IRIG code: %s --> group %i compensation effective\n",
251  icode_rx_names[irig_rx_info.settings.icode],
252  curr_group_idx );
253 
254  if ( !must_set_cal_val )
255  goto done;
256 
257  if ( curr_group_idx < 0 )
258  goto done;
259 
260  if ( curr_group_idx >= num_rec )
261  goto done;
262 
263 
264  printf( "\n" );
265 
266  // save new calibration setting effective for the current IRIG code
267  p = &cal_rec_comp[curr_group_idx];
268  p->hdr.type = CAL_REC_TYPE_IRIG_RX_COMP; // just to be sure
269  memset( &p->comp_data, 0, sizeof( p->comp_data ) );
270  p->comp_data.c[0] = (int16_t) ( cal_val * 10 ); // us to hns
271 
272  rc = mbg_set_cal_rec_irig_rx_comp( dh, p );
273 
274  if ( mbg_rc_is_error( rc ) )
275  {
276  printf( "** Failed to save new IRIG calibration setting for group %s.\n",
277  irig_comp_names[curr_group_idx] );
278  goto done;
279  }
280 
281 
282  printf( "IRIG calibration setting for code group %s has been set to %s us.\n",
283  irig_comp_names[curr_group_idx], str_comp_data( ws, sizeof( ws ), p->comp_data.c[0] ) );
284 
285 
286 done:
287  mbg_close_device( &dh );
288 
289  return ret_val;
290 
291 } // do_mbgtcrcal
292 
293 
294 
295 static /*HDR*/
296 void usage( void )
297 {
298  char ws[20];
299 
301  "Show or set IRIG RX calibration parameters of devices which support this." );
302 
304  mbg_print_opt_info( "-c val", "set calibration value \'val\'" );
305  mbg_print_opt_info( "-v", "increase verbosity" );
307 
308  puts( "" );
309  printf( "Example usage:\n"
310  "\n"
311  "%s print current settings of the default device\n"
312  "%s [dev] print current settings of specific device [dev]\n"
313  "%s -c 10 compensate +10.0 us on default device\n"
314  "%s -c -12.1 [dev] compensate -12.1 us on specific device [dev]\n"
315  "\n", pname, pname, pname, pname );
316  printf( "New settings become effective for a group of IRIG codes with similar characteristics\n"
317  "to which the currently configured IRIG RX code belongs. Calibration values are\n"
318  "in microseconds, with 0.1 us resolution, in the range +/-%s us.\n",
319  str_comp_data( ws, sizeof( ws ), IRIG_RX_COMP_MAX )
320  );
321  puts( "" );
322 
323 } // usage
324 
325 
326 
327 int main( int argc, char *argv[] )
328 {
329  int rc;
330  int c;
331 
333 
334  // check command line parameters
335  while ( ( c = getopt( argc, argv, "c:vh?" ) ) != -1 )
336  {
337  switch ( c )
338  {
339  case 'c':
340  cal_val = atof( optarg );
341  must_set_cal_val = 1;
342  break;
343 
344  case 'v':
345  verbose++;
346  break;
347 
348  case 'h':
349  case '?':
350  default:
351  must_print_usage = 1;
352  }
353  }
354 
355  #if defined( MBG_TGT_POSIX )
356  if ( geteuid() != 0 )
357  must_print_usage = 1;
358  #endif
359 
360  if ( must_print_usage )
361  {
362  printf( "This program must be run " ROOT_PRIVILEGES_STR " to work correctly.\n" );
363  #if defined( DEBUG )
364  if ( !must_print_usage )
365  printf( "(Built with DEBUG, so resuming anyway)\n" );
366  #else
367  must_print_usage = 1;
368  #endif
369  printf( "\n" );
370  }
371 
372  if ( must_print_usage )
373  {
374  usage();
375  return MBG_EXIT_CODE_USAGE;
376  }
377 
378  // Handle each of the specified devices.
379  rc = mbg_handle_devices( argc, argv, optind, do_mbgtcrcal, 0 );
380 
382 }
static double cal_val
Definition: mbgtcrcal.c:65
static void print_cal_recs(int num_rec, int curr_group_idx, CAL_REC_IRIG_RX_COMP cal_rec_comp[])
Definition: mbgtcrcal.c:85
static int must_set_cal_val
Definition: mbgtcrcal.c:66
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
uint16_t type
record type, see CAL_REC_TYPES
Definition: gpsdefs.h:5120
int16_t c[4]
Delay compensation values [100 ns units].
Definition: gpsdefs.h:5097
int must_print_usage
#define DEFAULT_IRIG_RX_COMP_NAMES
Initializers for format name strings.
Definition: gpsdefs.h:5164
int main(int argc, char *argv[])
Definition: mbgtcrcal.c:327
static __mbg_inline int mbg_get_cal_rec_irig_rx_comp(MBG_DEV_HANDLE dh, uint16_t idx, CAL_REC_IRIG_RX_COMP *p)
Retrieve IRIG RX calibration record with specific index.
Definition: irig_cal.h:175
Requested action completed successfully.
Definition: mbgerror.h:631
static char * str_comp_data(char *s, int max_len, int comp_data)
Definition: mbgtcrcal.c:72
static __mbg_inline int mbg_get_cal_rec_irig_rx_num_rec(MBG_DEV_HANDLE dh, int *p_num_rec)
Get supported number of IRIG RX calibration records.
Definition: irig_cal.h:144
short int16_t
Definition: words.h:212
Structure used to transfer calibration records.
Definition: gpsdefs.h:5179
_MBG_API_ATTR int _MBG_API mbg_get_irig_rx_info(MBG_DEV_HANDLE dh, IRIG_INFO *p)
Read the current IRIG input settings plus capabilities.
Definition: mbgdevio.c:5028
IRIG_RX_COMP comp_data
IRIG receiver delay compensation.
Definition: gpsdefs.h:5182
Current IRIG settings and supported codes.
Definition: gpsdefs.h:5054
unsigned short uint16_t
Definition: words.h:213
Unable to handle requested action, usage printed.
Definition: mbgerror.h:632
#define mbg_rc_is_success(_rc)
Definition: mbgerror.h:618
static int verbose
Definition: mbgtcrcal.c:60
static IRIG_INFO irig_rx_info
Definition: mbgirigcfg.c:96
static size_t max_label_len
Definition: mbgtcrcal.c:67
#define IRIG_RX_COMP_MAX
Definition: gpsdefs.h:5111
#define MBG_LAST_COPYRIGHT_YEAR
Definition: mbgtcrcal.c:55
static int do_mbgtcrcal(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev)
Definition: mbgtcrcal.c:114
static const char * irig_comp_names[N_IRIG_RX_COMP]
Definition: mbgtcrcal.c:63
number of compensation values
Definition: gpsdefs.h:5157
void mbg_print_device_options(void)
Print common info on how to specify devices on the command line.
Definition: toolutil.c:270
static const char * pname
Definition: mbgtcrcal.c:58
void mbg_print_usage_intro(const char *pname, const char *info)
Print usage intro to console.
Definition: toolutil.c:217
static const char * icode_rx_names[N_ICODE_RX]
Definition: mbgtcrcal.c:62
#define MBG_FIRST_COPYRIGHT_YEAR
Definition: mbgtcrcal.c:54
CAL_REC_HDR hdr
data header
Definition: gpsdefs.h:5181
static void usage(void)
Definition: mbgtcrcal.c:296
IRIG_SETTINGS settings
current settings
Definition: gpsdefs.h:5056
#define DEFAULT_ICODE_RX_NAMES
Initializers for RX timecode format name strings.
Definition: gpsdefs.h:4564
#define MBG_SUCCESS
Error codes used with Meinberg devices and drivers.
Definition: mbgerror.h:259
_MBG_API_ATTR void _MBG_API mbg_close_device(MBG_DEV_HANDLE *dev_handle)
Close a device handle and set the handle value to MBG_INVALID_DEV_HANDLE.
Definition: mbgdevio.c:4190
IRIG receiver delay compensation.
Definition: gpsdefs.h:5139
Action failed for specified device.
Definition: mbgerror.h:634
#define ROOT_PRIVILEGES_STR
Definition: toolutil.h:107
uint16_t icode
IRIG signal code, see ICODE_RX_CODES and ICODE_TX_CODES.
Definition: gpsdefs.h:5001
#define _pcps_has_generic_io(_d)
Definition: pcpsdev.h:1212
void mbg_print_help_options(void)
Print info on common program help arguments.
Definition: toolutil.c:257
int snprintf_safe(char *s, size_t max_len, const char *fmt,...)
A portable, safe implementation of snprintf()
Definition: str_util.c:156
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
the number of known codes
Definition: gpsdefs.h:4556
static __mbg_inline int mbg_set_cal_rec_irig_rx_comp(MBG_DEV_HANDLE dh, const CAL_REC_IRIG_RX_COMP *p)
Write an IRIG RX calibration record to a device.
Definition: irig_cal.h:210
#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
#define _pcps_is_irig_rx(_d)
Definition: pcpsdev.h:1078
static __mbg_inline int mbg_icode_rx_to_group_idx(int icode_rx)
Get the IRIG calibration group index for a given IRIG RX code.
Definition: irig_cal.h:62
#define N_IRIG_RX_COMP_VAL
Definition: gpsdefs.h:5084
Device info structure.
Definition: pcpsdev.h:1043