summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Burnicki <martin.burnicki@meinberg.de>2013-04-11 12:00:00 +0200
committerMartin Burnicki <martin.burnicki@meinberg.de>2013-04-11 12:00:00 +0200
commit912230275b4e315f35c6e6bb52746ae994a65919 (patch)
treec3bb9a38dcb705e6c55449d6360da76da18e1921
downloadmbgtools-win-912230275b4e315f35c6e6bb52746ae994a65919.tar.gz
mbgtools-win-912230275b4e315f35c6e6bb52746ae994a65919.zip
Initial version imported into git2013-04-11
Contains project files for VC6 only.
-rw-r--r--mbgctrl/mbgctrl.c2460
-rw-r--r--mbgfasttstamp/mbgfasttstamp.c300
-rw-r--r--mbggpscap/mbggpscap.c412
-rw-r--r--mbghrtime/mbghrtime.c323
-rw-r--r--mbglib/common/cfg_hlp.h127
-rw-r--r--mbglib/common/cnv_wday.h100
-rw-r--r--mbglib/common/ctry.c176
-rw-r--r--mbglib/common/ctry.h239
-rw-r--r--mbglib/common/ctrydttm.c184
-rw-r--r--mbglib/common/ctrydttm.h74
-rw-r--r--mbglib/common/deviohlp.c322
-rw-r--r--mbglib/common/deviohlp.h168
-rw-r--r--mbglib/common/gpsdefs.h6801
-rw-r--r--mbglib/common/gpsutils.h84
-rw-r--r--mbglib/common/lan_util.c1288
-rw-r--r--mbglib/common/lan_util.h579
-rw-r--r--mbglib/common/mbg_arch.h167
-rw-r--r--mbglib/common/mbg_tgt.h566
-rw-r--r--mbglib/common/mbgdevio.h3939
-rw-r--r--mbglib/common/mbgerror.h172
-rw-r--r--mbglib/common/mbggeo.h301
-rw-r--r--mbglib/common/mbgmutex.h259
-rw-r--r--mbglib/common/mbgpccyc.h305
-rw-r--r--mbglib/common/mbgtime.h322
-rw-r--r--mbglib/common/myutil.h225
-rw-r--r--mbglib/common/parmgps.c242
-rw-r--r--mbglib/common/parmgps.h142
-rw-r--r--mbglib/common/parmpcps.c115
-rw-r--r--mbglib/common/parmpcps.h163
-rw-r--r--mbglib/common/pci_asic.h391
-rw-r--r--mbglib/common/pcpsdefs.h1496
-rw-r--r--mbglib/common/pcpsdev.h1711
-rw-r--r--mbglib/common/pcpslstr.c500
-rw-r--r--mbglib/common/pcpslstr.h1052
-rw-r--r--mbglib/common/pcpsmktm.c53
-rw-r--r--mbglib/common/pcpsmktm.h62
-rw-r--r--mbglib/common/pcpsutil.c162
-rw-r--r--mbglib/common/pcpsutil.h198
-rw-r--r--mbglib/common/toolutil.c530
-rw-r--r--mbglib/common/toolutil.h128
-rw-r--r--mbglib/common/usbdefs.h151
-rw-r--r--mbglib/common/use_pack.h43
-rw-r--r--mbglib/common/words.h360
-rw-r--r--mbglib/lib/bc/mbgdevio.libbin0 -> 29696 bytes
-rw-r--r--mbglib/lib/bc/mbgsvcio.libbin0 -> 2560 bytes
-rw-r--r--mbglib/lib/bc/mbgsvctl.libbin0 -> 8192 bytes
-rw-r--r--mbglib/lib/bc/mbgutil.libbin0 -> 6144 bytes
-rw-r--r--mbglib/lib/msc/mbgdevio.libbin0 -> 223752 bytes
-rw-r--r--mbglib/lib/msc/mbgsvcio.libbin0 -> 7148 bytes
-rw-r--r--mbglib/lib/msc/mbgsvctl.libbin0 -> 57888 bytes
-rw-r--r--mbglib/lib/msc/mbgutil.libbin0 -> 45706 bytes
-rw-r--r--mbglib/lib64/msc/mbgdevio.libbin0 -> 39182 bytes
-rw-r--r--mbglib/lib64/msc/mbgsvcio.libbin0 -> 4164 bytes
-rw-r--r--mbglib/lib64/msc/mbgsvctl.libbin0 -> 10978 bytes
-rw-r--r--mbglib/lib64/msc/mbgutil.libbin0 -> 8630 bytes
-rw-r--r--mbglib/win32/mbg_w32.h309
-rw-r--r--mbglib/win32/wingetopt.c90
-rw-r--r--mbglib/win32/wingetopt.h32
-rw-r--r--mbgstatus/mbgstatus.c895
-rw-r--r--mbgversion.h37
-rw-r--r--test/mbgcmptime/mbgcmptime.c345
-rw-r--r--vc6/mbgcmptime/mbgcmptime.dsp194
-rw-r--r--vc6/mbgctrl/mbgctrl.dsp214
-rw-r--r--vc6/mbgfasttstamp/mbgfasttstamp.dsp194
-rw-r--r--vc6/mbggpscap/mbggpscap.dsp194
-rw-r--r--vc6/mbghrtime/mbghrtime.dsp194
-rw-r--r--vc6/mbgstatus/mbgstatus.dsp130
-rw-r--r--vc6/mbgtools-win.dsw89
68 files changed, 30309 insertions, 0 deletions
diff --git a/mbgctrl/mbgctrl.c b/mbgctrl/mbgctrl.c
new file mode 100644
index 0000000..edb6608
--- /dev/null
+++ b/mbgctrl/mbgctrl.c
@@ -0,0 +1,2460 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgctrl.c 1.22.1.14 2012/12/12 10:44:35Z martin TEST $
+ *
+ * Description:
+ * Main file for mbgctrl program which sends commands and
+ * configuration parameters to a Meinberg device via IOCTL calls.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgctrl.c $
+ * Revision 1.22.1.14 2012/12/12 10:44:35Z martin
+ * Fixed wording of some message.
+ * Revision 1.22.1.13 2012/12/05 16:13:37 martin
+ * Chaged some faulty message texts.
+ * Revision 1.22.1.12 2012/10/16 10:44:20 martin
+ * Removed obsolete code.
+ * Revision 1.22.1.11 2012/07/12 08:37:47 martin
+ * Account for renamed structure.
+ * Revision 1.22.1.10 2012/06/01 18:46:21 martin
+ * Revision 1.22.1.9 2012/06/01 16:55:58 martin
+ * Account for library symbols moved to a new header.
+ * Revision 1.22.1.8 2011/09/26 15:58:58 martin
+ * Started modifications for PTP unicast master configuration.
+ * Warn if trying to handle serial port cfg but no serial port is supported.
+ * Modified program version handling.
+ * Use O_RDWR flag when opening a device.
+ * Account for modified library functions which can now
+ * optionally print the raw (hex) HR time stamp.
+ * Revision 1.22.1.7 2011/04/19 10:02:37 martin
+ * Syntax fix.
+ * Revision 1.22.1.6 2011/04/19 09:57:00 martin
+ * Untabbified and removed trailing spaces.
+ * Revision 1.22.1.5 2011/03/21 08:32:18 martin
+ * Fixed compiler warning.
+ * Revision 1.22.1.4 2011/03/03 10:01:00 daniel
+ * Support configuring PTP roles.
+ * Revision 1.22.1.3 2011/02/18 13:35:59 daniel
+ * Revision 1.22.1.2 2011/02/18 13:35:11 daniel
+ * Revision 1.22.1.1 2011/02/18 11:27:29 daniel
+ * Preliminary support for configuring PTP parameters incl. Unicast
+ * Bugfix: accept parameter keyword only when substring is found at the
+ * start of the parameter string.
+ * Revision 1.22 2009/09/29 14:58:18 martin
+ * Unified and simplified parameter evaluation.
+ * Updated version number to 3.4.0.
+ * Revision 1.21 2009/09/28 09:36:43 martin
+ * Support configuration of antenna cable length.
+ * Removed duplicate usage message for event time.
+ * Revision 1.20 2009/09/28 07:19:03 martin
+ * Made parameter syntax for enable_flags and LAN configuration more flexible.
+ * Revision 1.19 2009/08/20 14:19:29 martin
+ * Updated version number to 3.3.1.
+ * Support configuration of board's LAN interface.
+ * Revision 1.18 2009/07/24 09:50:08 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.17 2009/06/19 12:38:51 martin
+ * Updated version number to 3.2.0.
+ * Revision 1.16 2009/06/18 15:14:53 martin
+ * Added command TZOFFS which can be used to set TZDL to UTC, and then
+ * configure the standard TZDL offset to a dedicated number of seconds, to the
+ * output time has a configurable UTC offset against the time derived from the
+ * input signal.
+ * Revision 1.15 2009/03/20 11:53:19 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Support programmable time scales.
+ * Revision 1.14 2008/12/22 12:39:00 martin
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Accept device name(s) on the command line.
+ * Don't use printf() without format, which migth produce warnings
+ * with newer gcc versions.
+ * Revision 1.13 2008/11/07 10:25:49 martin
+ * Support modification of a card's ENABLE_FLAGS.
+ * Changes due to renamed library function.
+ * Changes due to renamed library function.
+ * Revision 1.12 2008/09/15 14:20:21 martin
+ * Support generic serial settings including string type and mode.
+ * Reworked evaluation of command line parameters.
+ * New parameter COM0= to configure an individual port.
+ * Account for renamed library symbols.
+ * Revision 1.11 2007/07/24 09:31:39 martin
+ * Changes due to renamed library symbols.
+ * Revision 1.10 2007/03/01 16:09:16 martin
+ * Be able to set the board date and/or time.
+ * Revision 1.9 2007/02/22 16:38:50 martin
+ * Added function to set on-board date.
+ * Revision 1.8 2006/08/28 10:45:50 martin
+ * Picked up Heiko's patch to set the GPS receiver position.
+ * Revision 1.7 2004/11/08 15:47:40 martin
+ * Using type cast to avoid compiler warning.
+ * Revision 1.6 2003/08/26 14:37:35 martin
+ * Support configuration of some standard time zones,
+ * also for GPS devices.
+ * Revision 1.5 2003/07/31 13:48:54 martin
+ * Added function to set COM port parms for GPS clocks.
+ * Usage shows which parameters are supported by a device.
+ * Revision 1.4 2003/04/25 10:27:58 martin
+ * Use new functions from mbgdevio library.
+ * New program version v2.1.
+ * Revision 1.3 2002/08/22 14:52:49 martin
+ * Added function to set clock's COM port parameters.
+ * Revision 1.2 2001/12/03 16:04:46 martin
+ * New program version 1.2.
+ * Added new function set_event_time().
+ * Fixed a bug in eval of cmd line parameters.
+ * Revision 1.1 2001/09/17 15:07:56 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <deviohlp.h>
+#include <pcpsmktm.h>
+#include <pcpsutil.h>
+#include <parmpcps.h>
+#include <parmgps.h>
+#include <myutil.h>
+#include <gpsutils.h>
+#include <cnv_wday.h>
+#include <toolutil.h>
+#include <lan_util.h>
+//##+++++++++++++++++++++ #include <ptpdflts.h>
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+
+#define MBG_MICRO_VERSION 0
+#define MBG_FIRST_COPYRIGHT_YEAR 2001
+#define MBG_LAST_COPYRIGHT_YEAR 0 // use default
+
+
+static const char *pname = "mbgctrl";
+
+static char *dev_name;
+
+static int err_unicast_nsupp;
+static const char str_unknown[] = "(unknown)";
+
+static TZDL tzdl_utc = DEFAULT_TZDL_UTC;
+static TZDL tzdl_cet_cest = DEFAULT_TZDL_CET_CEST_EN;
+static TZDL tzdl_eet_eest = DEFAULT_TZDL_EET_EEST_EN;
+static long max_tzdl_offs = 0x7FFFFFFFL; // max val for int32_t
+
+static const char tz_info_utc[] = TZ_INFO_UTC;
+static const char tz_info_cet_cest[] = TZ_INFO_CET_CEST_EN;
+static const char tz_info_eet_eest[] = TZ_INFO_EET_EEST_EN;
+
+static const char *mode_names[N_STR_MODE] = DEFAULT_ENG_MODE_NAMES;
+static const char *time_scale_name[N_MBG_TIME_SCALE] = MBG_TIME_SCALE_STRS;
+
+#define _get_time_scale_name( _i ) \
+ ( ( (_i) < N_MBG_TIME_SCALE ) ? time_scale_name[_i] : str_unknown )
+
+
+static const char no_gps_cmd[] = "does not support GPS commands";
+static const char no_tzdl[] = "does not support configurable time zone";
+static const char no_tz[] = "does not support time zones";
+static const char no_event_time[] = "does not support event times";
+static const char no_enable_flags[] = "does not support enable flags";
+static const char no_time_scale[] = "does not support a configurable time scale";
+static const char no_lan_intf[] = "does not provide a LAN interface";
+static const char no_ptp[] = "does not provide PTP";
+static const char no_cab_len[] = "does not support antenna signal delay compensation";
+
+
+typedef struct
+{
+ const char *name;
+ uint16_t *flags;
+ uint16_t on_flags;
+} EF_INFO;
+
+#define N_EF_INFO 3
+
+static const char ef_name_serial[] = "SERIAL";
+static const char ef_name_pulses[] = "PULSES";
+static const char ef_name_synth[] = "SYNTH";
+
+
+typedef struct
+{
+ const char *name;
+ IP4_ADDR *addr;
+} IP4_INFO;
+
+#define N_IP4_INFO 4
+
+static const char ip4_name_ip[] = "IP";
+static const char ip4_name_nm[] = "NM";
+static const char ip4_name_ba[] = "BA";
+static const char ip4_name_gw[] = "GW";
+
+static const char ptp_name_net[] = "NP";
+static const char ptp_name_del[] = "DM";
+static const char ptp_name_dom[] = "DO";
+static const char ptp_name_v1[] = "HW";
+
+static const char ptp_name_role[] = "ROLE";
+
+static const char ptp_name_gmip[] = "GMIP";
+static const char ptp_name_gmid[] = "GMID";
+static const char ptp_name_pid[] = "PID";
+static const char ptp_name_smi[] = "SMI";
+static const char ptp_name_ami[] = "AMI";
+static const char ptp_name_dri[] = "DRI";
+static const char ptp_name_dur[] = "DUR";
+
+//##+++++
+static const char *delay_mech[] = PTP_DELAY_MECH_NAMES;
+static const char *nw_prot[] = PTP_NW_PROT_STRS;
+static const char *nw_prot_short[] = PTP_NW_PROT_STRS_SHORT;
+
+static const char *ptp_roles[] = PTP_ROLE_STRS;
+static const char *ptp_roles_short[] = PTP_ROLE_STRS_SHORT;
+
+
+//##+++++++++++++++++++
+// If unicast is not supported for a PTP device then the device is definitely
+// a multicast slave, in which case index 0 returns the correct role name.
+#define _ptp_role_name( _i ) \
+ ( ( (_i) < N_PTP_ROLES ) ? ptp_roles[_i] : str_unknown )
+
+#define _ptp_role_name_short( _i ) \
+ ( ( (_i) < N_PTP_ROLES ) ? ptp_roles_short[_i] : str_unknown )
+
+
+
+
+static /*HDR*/
+void err_msg( const PCPS_DEV *p_dev, const char *msg )
+{
+ printf( "This device %s.\n", msg );
+
+} // err_msg
+
+
+
+static /*HDR*/
+int set_tz_code( MBG_DEV_HANDLE dh, PCPS_TZCODE tzcode, const char *s )
+{
+ int rc = mbg_set_tzcode( dh, &tzcode );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_tzcode" ) )
+ return rc;
+
+ printf( "The clock's time zone setting has been set to %s.\n", s );
+
+ return MBG_SUCCESS;
+
+} // set_tz_code
+
+
+
+static /*HDR*/
+int set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *tzdl, const char *info )
+{
+ int rc = mbg_set_gps_tzdl( dh, tzdl );
+
+ if ( mbg_ioctl_err( rc, "set_gps_tzdl" ) )
+ return rc;
+
+ if ( info )
+ printf( "The clock's time zone setting has been set to %s.\n", info );
+
+ return MBG_SUCCESS;
+
+} // set_gps_tzdl
+
+
+
+static /*HDR*/
+int set_timezone( MBG_DEV_HANDLE dh, const char *tz_name, const PCPS_DEV *p_dev )
+{
+ const char *tz_info = NULL;
+ TZDL *tz_tzdl = NULL;
+ PCPS_TZCODE tz_code = 0;
+ int rc = MBG_SUCCESS;
+
+ if ( strcmp( tz_name, "UTC" ) == 0 )
+ {
+ tz_info = tz_info_utc;
+ tz_tzdl = &tzdl_utc;
+ tz_code = PCPS_TZCODE_UTC;
+ }
+ else if ( strcmp( tz_name, "CET" ) == 0 )
+ {
+ tz_info = tz_info_cet_cest;
+ tz_tzdl = &tzdl_cet_cest;
+ tz_code = PCPS_TZCODE_MEZMESZ;
+ }
+ else if ( strcmp( tz_name, "EET" ) == 0 )
+ {
+ tz_info = tz_info_eet_eest;
+ tz_tzdl = &tzdl_eet_eest;
+ tz_code = PCPS_TZCODE_OEZ;
+ }
+ else
+ {
+ printf( "** Unknown timezone name %s\n", tz_name );
+ rc = 1;
+ }
+
+ if ( tz_info )
+ {
+ if ( _pcps_has_tzcode( p_dev ) )
+ rc = set_tz_code( dh, tz_code, tz_info );
+ else
+ if ( _pcps_has_tzdl( p_dev ) )
+ rc = set_gps_tzdl( dh, tz_tzdl, tz_info );
+ else
+ err_msg( p_dev, no_tz );
+ }
+
+ return rc;
+
+} // set_timezone
+
+
+
+static /*HDR*/
+int show_tzdl_offs( MBG_DEV_HANDLE dh, const char *info )
+{
+ TZDL tzdl;
+ int rc = mbg_get_gps_tzdl( dh, &tzdl );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_tzdl" ) )
+ return rc;
+
+ printf( "%s timezone offset: UTC%+lis", info, (long) tzdl.offs );
+
+ return MBG_SUCCESS;
+
+} // show_tzdl_offs
+
+
+
+static /*HDR*/
+int set_tzdl_offs( MBG_DEV_HANDLE dh, const char *s )
+{
+ TZDL tzdl = tzdl_utc;
+ long tzdl_offs = atol( s );
+
+ if ( labs( tzdl_offs ) > max_tzdl_offs ) // max val for int32_t
+ {
+ fprintf( stderr, "** Time zone offset %li exceeds range (%li..%li)\n",
+ tzdl_offs, -max_tzdl_offs, max_tzdl_offs );
+ return MBG_ERR_CFG;
+ }
+
+ tzdl.offs = (int32_t) tzdl_offs;
+
+ return set_gps_tzdl( dh, &tzdl, NULL );
+
+} // set_tzdl_offs
+
+
+
+static /*HDR*/
+int show_lan_intf( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
+{
+ IP4_SETTINGS ip4_settings;
+ char ws[256];
+
+ int rc = mbg_get_ip4_settings( dh, &ip4_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ip4_settings" ) )
+ return rc;
+
+ printf( "On-board LAN interface settings:" );
+
+ if ( ip4_settings.flags & IP4_MSK_DHCP )
+ printf( " (DHCP client)\n" );
+ else
+ {
+ printf( "\n" );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.ip_addr, NULL );
+ printf( " IP Address: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.netmask, NULL );
+ printf( " Net Mask: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.broad_addr, NULL );
+ printf( " Broadcast Addr: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.gateway, NULL );
+ printf( " Gateway: %s\n", ws );
+ }
+
+ return MBG_SUCCESS;
+
+} // show_lan_intf
+
+
+
+static /*HDR*/
+int show_ptp_cfg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
+{
+ ALL_PTP_CFG_INFO all_ptp_cfg_info;
+ char ws[256];
+ int unicast_supported;
+ int idx;
+
+ int rc = mbg_get_all_ptp_cfg_info( dh, &all_ptp_cfg_info );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_all_ptp_cfg_info" ) )
+ return rc;
+
+ unicast_supported = ( all_ptp_cfg_info.ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) != 0;
+
+ printf( "\nPTP configuration:\n");
+
+ idx = all_ptp_cfg_info.ptp_cfg_info.settings.ptp_role;
+ printf( " PTP Role : %s (%s)\n", _ptp_role_name_short( idx ), _ptp_role_name( idx ) );
+
+ idx = all_ptp_cfg_info.ptp_cfg_info.settings.nw_prot;
+ printf( " Network Protocol: %s (%s)\n", nw_prot_short[idx], nw_prot[idx] );
+
+ printf( " Delay Mechanism : %s\n", delay_mech[all_ptp_cfg_info.ptp_cfg_info.settings.delay_mech] );
+ printf( " Domain Number : %d\n", all_ptp_cfg_info.ptp_cfg_info.settings.domain_number );
+ printf( " V1 HW Compat. : %d\n", ( all_ptp_cfg_info.ptp_cfg_info.settings.flags & PTP_CFG_MSK_V1_HW_COMPAT ) ? 1 : 0 );
+
+ if ( unicast_supported )
+ {
+ PTP_UC_MASTER_CFG_LIMITS *p_uc_limits = &all_ptp_cfg_info.ptp_uc_master_cfg_limits;
+ int i;
+
+ for ( i = 0; i < p_uc_limits->n_supp_master; i++ )
+ {
+ PTP_UC_MASTER_SETTINGS *p = &all_ptp_cfg_info.all_ptp_uc_master_info_idx[i].info.settings;
+
+ printf( "\nPTP unicast master" );
+
+ if ( p_uc_limits->n_supp_master > 1 )
+ printf( " %i", i );
+
+ printf( ":\n");
+
+ printf( " GM Host: %s\n", p->gm_host );
+
+ snprint_octets( ws, sizeof( ws ), p->gm_clock_id.b, sizeof( p->gm_clock_id.b ), MAC_SEP_CHAR, NULL );
+ printf( " GM Clock ID: %s\n", ws );
+
+ printf( " GM Port ID: %d\n\n", p->gm_port_id );
+ printf( " Sync Msg Interval [2^x s]: %i\n", p->sync_intv );
+ printf( " Ann. Msg Interval [2^x s]: %i\n", p->ann_intv );
+ printf( " DelReq Msg Interval [2^x s]: %i\n", p->delay_req_intv );
+ printf( " Message Duration: %i s\n", p->message_duration );
+ }
+
+ }
+
+ return MBG_SUCCESS;
+
+} // show_ptp_cfg
+
+
+
+static /*HDR*/
+/**
+ * @brief Lookup a string in a string table and return the table index
+ *
+ * @param s The string to be searched for in the string table
+ * @param tbl A table of strings to be searched
+ * @param n_entries The number of strings in the string table
+ * @param supp_mask A string with a given index is only supported if the
+ * corresponding bit is set in this mask.
+ * @param info A descriptive name of the parameter which is to be
+ * set to the index of the searched string
+ *
+ * @return >=0 A valid, supported table index
+ * <0 Unknown or unsupported parameter
+ */
+int get_chk_str_table_idx( const char *s, const char *tbl[], int n_entries,
+ uint32_t supp_mask, const char *info )
+{
+ int i;
+ const char *cp;
+
+ for ( i = 0; i < n_entries; i++ )
+ {
+ cp = tbl[i];
+
+ if ( strncmp( s, cp, strlen( cp ) ) == 0 )
+ if ( supp_mask & ( 1UL << i ) )
+ return i;
+ }
+
+ printf( "error: %s %s\n",
+ ( i == n_entries ) ? "unknown" : "unsupported",
+ info );
+
+ return -3;
+
+} // get_chk_str_table_idx
+
+
+
+static /*HDR*/
+/**
+ * @brief Lookup a parameter in an argument list and check if a colon is appended
+ *
+ * @param arg An argument list of the form: "name:val,name:val,..."
+ * @param s A parameter name searched for in the argument list
+ * @param p A pointer to a (char *) which is set to the beginning
+ * of the value part of a parameter string
+ *
+ * @return <0 Syntax error, i.e. missing colon
+ * 0 No error. If parameter has been found then *p set
+ * to the parameter value, else to NULL.
+ */
+int chk_parm_name( const char *arg, const char *id, char **p )
+{
+ char *cp = strstr( arg, id );
+
+ if ( cp )
+ {
+ cp += strlen( id );
+
+ if ( *cp != ':' )
+ return -1;
+
+ cp++;
+ }
+
+ if ( p )
+ *p = cp; // may be NULL
+
+ return 0;
+
+} // chk_parm_name
+
+
+
+static /*HDR*/
+/**
+ * @brief Lookup a parameter in an argument list and check if the value string is valid
+ *
+ * This function expects that the parameter value is a known string which can
+ * be found in a table of known strings. A bit mask indicates if a string with
+ * a given table index is supported, or not.
+ *
+ * @param arg An argument list of the form: "name:val,name:val,..."
+ * @param id The name of the argument to be checked.
+ * @param tbl A table of strings with predefined parameter values
+ * @param n_entries The number of strings in the string table
+ * @param supp_mask A string with a given index is only supported if the
+ * corresponding bit is set in this mask.
+ * @param info A descriptive name of the parameter which is to be
+ * set to the index of the searched string
+ *
+ * @return >=0 A valid, supported table index
+ * -1 Parameter not found
+ * -2 Unknown or unsupported parameter, or syntax error
+ */
+int chk_tbl_parm( const char *arg, const char *id, const char *tbl[],
+ int n_entries, uint32_t supp_mask, const char *info )
+{
+ char *cp;
+ int rc = chk_parm_name( arg, id, &cp );
+
+ if ( rc < 0 )
+ return -2;
+
+ if ( cp == NULL )
+ return -1;
+
+ rc = get_chk_str_table_idx( cp, tbl, n_entries, supp_mask, info );
+
+ if ( rc < 0 )
+ return -2;
+
+ return rc;
+
+} // chk_tbl_parm
+
+
+
+static /*HDR*/
+/**
+ * @brief Lookup an int16_t parameter in an argument list
+ *
+ * Check and save the numeric parameter if in a valid range.
+ *
+ * @param arg An argument list of the form: "name:val,name:val,..."
+ * @param id The name of the argument to be checked.
+ * @param p A pointer to a variable where the parameter value is
+ * saved if valid
+ * @param range_min The minimum allowed value for the parameter
+ * @param range_max The maximum allowed value for the parameter
+ * @param is_supported A flag indicating if the parameter is actually supported
+ * @param info A descriptive name of the parameter
+ *
+ * @return >=0 A valid, supported table index
+ * -1 Parameter not found, or out of range
+ */
+int chk_int16_parm( const char *arg, const char *id, int16_t *p, int16_t range_min,
+ int16_t range_max, int is_supported, const char *info )
+{
+ char *cp;
+ int idx = chk_parm_name( arg, id, &cp );
+
+ if ( idx < 0 ) // parameter error
+ return -1;
+
+ if ( cp ) // parameter found
+ {
+ if ( !is_supported )
+ err_unicast_nsupp = 1;
+ else
+ {
+ int16_t tmp = atoi( cp );
+
+ if ( ( tmp < range_min ) || ( tmp > range_max ) )
+ {
+ printf( "error: %s %i out of range (%i..%i)\n", info, tmp, range_min, range_max );
+ return -1;
+ }
+
+ *p = tmp;
+ printf( " setting %s: %i\n", info, tmp );
+ }
+ }
+
+ return 0;
+
+} // chk_int16_parm
+
+
+
+static /*HDR*/
+int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
+{
+ ALL_PTP_CFG_INFO all_ptp_cfg_info;
+ ALL_PTP_CFG_INFO prv_all_ptp_cfg_info;
+ PTP_CFG_INFO *p_info;
+ PTP_CFG_SETTINGS *p_settings;
+ PTP_UC_MASTER_CFG_LIMITS *p_uc_limits;
+ PTP_UC_MASTER_INFO *p_uc_info;
+ PTP_UC_MASTER_SETTINGS *p_uc_settings;
+ uint32_t supp_mask;
+ IP4_ADDR ip4addr;
+ char ws[256];
+ char *cp;
+ int idx;
+ int unicast_supported;
+ int uc_master_idx = 0;
+ int16_t tmp_int16;
+
+ int rc = mbg_get_all_ptp_cfg_info( dh, &all_ptp_cfg_info );
+
+ if ( rc < 0 )
+ return rc; // failed to read current settings and capabilities
+
+
+ err_unicast_nsupp = 0;
+
+ // save a copy of the current settings
+ prv_all_ptp_cfg_info = all_ptp_cfg_info;
+
+ p_info = &all_ptp_cfg_info.ptp_cfg_info;
+ p_settings = &p_info->settings;
+ unicast_supported = ( p_info->supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) != 0;
+
+ p_uc_limits = &all_ptp_cfg_info.ptp_uc_master_cfg_limits;
+ // The pointers below need to be updated wnenever uc_master_idx is changed
+ p_uc_info = &all_ptp_cfg_info.all_ptp_uc_master_info_idx[uc_master_idx].info;
+ p_uc_settings = &p_uc_info->settings;
+
+
+ // Network protocol
+ idx = chk_tbl_parm( arg, ptp_name_net, nw_prot_short, N_PTP_NW_PROT, p_info->supp_nw_prot, "network protocol type" );
+
+ if ( idx >= 0 ) // valid parameter found
+ p_settings->nw_prot = idx;
+ else
+ if ( idx < -1 )
+ goto fail;
+
+
+ // Delay Mechanism
+ idx = chk_tbl_parm( arg, ptp_name_del, delay_mech, N_PTP_DELAY_MECH, p_info->supp_delay_mech, "delay mechanism" );
+
+ if ( idx >= 0 ) // valid parameter found
+ p_settings->delay_mech = idx;
+ else
+ if ( idx < -1 )
+ goto fail;
+
+
+ // Domain Number
+ idx = chk_parm_name( arg, ptp_name_dom, &cp );
+
+ if ( idx < 0 ) // parameter error
+ goto fail;
+
+ if ( cp ) // parameter found
+ {
+ idx = atoi( cp );
+ //##+++++ must check range!!
+ p_settings->domain_number = idx;
+ }
+
+
+ // V1 Hardware compatibility flag
+ idx = chk_parm_name( arg, ptp_name_v1, &cp );
+
+ if ( idx < 0 ) // parameter error
+ goto fail;
+
+ if ( cp ) // parameter found
+ {
+ idx = atoi( cp );
+
+ switch ( idx )
+ {
+ case 0:
+ p_settings->flags &= ~PTP_CFG_MSK_V1_HW_COMPAT;
+ break;
+
+ case 1:
+ p_settings->flags |= PTP_CFG_MSK_V1_HW_COMPAT;
+ break;
+
+ default:
+ printf( "error: No valid V1 HWC settings!\n" );
+ goto fail;
+ }
+ }
+
+
+ //---- unicast stuff ----
+
+ // PTP role
+ supp_mask = _get_supp_ptp_role_idx_msk( p_info->supp_flags );
+ idx = chk_tbl_parm( arg, ptp_name_role, ptp_roles_short, N_PTP_ROLES, supp_mask, "PTP role" );
+
+ if ( idx >= 0 ) // valid parameter found
+ {
+ if ( !unicast_supported )
+ err_unicast_nsupp = 1;
+ else
+ p_settings->ptp_role = idx;
+ }
+ else
+ if ( idx < -1 ) // parameter error
+ goto fail;
+
+
+ // GM Host
+ idx = chk_parm_name( arg, ptp_name_gmip, &cp );
+
+ if ( idx < 0 ) // parameter error
+ goto fail;
+
+ if ( cp ) // parameter found
+ {
+ if ( !unicast_supported )
+ err_unicast_nsupp = 1;
+ else
+ {
+ // currently IP addresses are accepted only, so check for
+ // a valid IPv4 address
+ if ( str_to_ip4_addr( &ip4addr, cp ) )
+ {
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4addr, NULL );
+ printf( " GM IP Address: %s\n", ws );
+
+ memset( p_uc_settings->gm_host, 0, sizeof( p_uc_settings->gm_host ) );
+ strcpy( p_uc_settings->gm_host, ws );
+ }
+ else
+ goto fail;
+ }
+ }
+
+
+ // GM Clock ID
+ idx = chk_parm_name( arg, ptp_name_gmid, &cp );
+
+ if ( idx < 0 ) // parameter error
+ goto fail;
+
+ if ( cp ) // parameter found
+ {
+ if ( !unicast_supported )
+ err_unicast_nsupp = 1;
+ else
+ {
+ PTP_CLOCK_ID gm_clock_id;
+ idx = str_to_octets( gm_clock_id.b, sizeof( gm_clock_id.b ), cp );
+
+ if ( idx != sizeof( gm_clock_id ) )
+ {
+ printf( "Syntax error in specified GM clock ID\n" );
+ goto fail;
+ }
+ else
+ {
+ p_uc_settings->gm_clock_id = gm_clock_id;
+
+ snprint_octets( ws, sizeof( ws ), p_uc_settings->gm_clock_id.b,
+ sizeof( p_uc_settings->gm_clock_id.b ), MAC_SEP_CHAR, NULL );
+ printf( " setting GM Clock ID: %s\n", ws );
+ }
+ }
+ }
+
+
+ // GM Target Port ID
+ idx = chk_parm_name( arg, ptp_name_pid, &cp );
+
+ if ( idx < 0 ) // parameter error
+ goto fail;
+
+ if ( cp ) // parameter found
+ {
+ if ( !unicast_supported )
+ err_unicast_nsupp = 1;
+ else
+ {
+ p_uc_settings->gm_port_id = strtoul( cp, NULL, 0 );
+ printf( " setting GM port id: %d\n", p_uc_settings->gm_port_id );
+ }
+ }
+
+
+ // Sync Message Rate
+ idx = chk_int16_parm( arg, ptp_name_smi, &p_uc_settings->sync_intv,
+ p_uc_limits->sync_intv_min, p_uc_limits->sync_intv_max,
+ unicast_supported, "sync intv." );
+ if ( idx < 0 )
+ goto fail;
+
+
+ // Announce Message Rate
+ idx = chk_int16_parm( arg, ptp_name_ami, &p_uc_settings->ann_intv,
+ p_uc_limits->ann_intv_min, p_uc_limits->ann_intv_max,
+ unicast_supported, "ann. intv." );
+ if ( idx < 0 )
+ goto fail;
+
+
+ // Delay Message Rate
+ idx = chk_int16_parm( arg, ptp_name_dri, &p_uc_settings->delay_req_intv,
+ p_uc_limits->delay_req_intv_min, p_uc_limits->delay_req_intv_max,
+ unicast_supported, "delay req. intv." );
+ if ( idx < 0 )
+ goto fail;
+
+
+ // Message Duration //##++++ TODO: should this be added to the structure
+ tmp_int16 = p_uc_settings->message_duration;
+ idx = chk_int16_parm( arg, ptp_name_dur, &tmp_int16,
+ PTP_UC_MSG_DURATION_MIN, PTP_UC_MSG_DURATION_MAX,
+ unicast_supported, "msg. duration" );
+ if ( idx < 0 )
+ goto fail;
+
+ p_uc_settings->message_duration = tmp_int16;
+
+#if 0 //##++++++++++++
+
+ cp = strstr( arg, ptp_name_dur );
+
+ if ( cp != NULL )
+ {
+ l = strlen( ptp_name_dur );
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ ptp_unicast_settings.message_duration = atoi( cp+l );
+ printf( " setting message duration: %i seconds\n", ptp_unicast_settings.message_duration );
+ }
+#endif
+
+
+ rc = mbg_set_ptp_cfg_settings( dh, p_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_ptp_cfg_settings" ) )
+ return rc;
+
+ return MBG_SUCCESS;
+
+
+fail:
+ printf( "Syntax error in argument!\n" );
+
+ return MBG_ERR_CFG;
+
+} // set_ptp_cfg
+
+
+
+static /*HDR*/
+int ip4_check_parm( const char *s, IP4_INFO *p )
+{
+ int l = strlen( p->name );
+ int n;
+
+ if ( strncmp( s, p->name, l ) != 0 )
+ return 0; // parameter does not match
+
+ if ( s[l] != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ n = str_to_ip4_addr( p->addr, &s[l] );
+
+ if ( n < 0 )
+ goto fail; // parameter syntax error: failed to convert numeric address
+
+ return n + l; //##++++++ needs to be verified
+
+fail:
+ return MBG_ERR_CFG;
+
+} // ip4_check_parm
+
+
+
+static /*HDR*/
+int set_lan_intf( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
+{
+ IP4_SETTINGS prv_ip4_settings;
+ IP4_SETTINGS ip4_settings = { 0 };
+ IP4_ADDR default_broad_addr;
+
+ IP4_INFO ip4_info[N_IP4_INFO] =
+ {
+ { ip4_name_ip, &ip4_settings.ip_addr },
+ { ip4_name_nm, &ip4_settings.netmask },
+ { ip4_name_ba, &ip4_settings.broad_addr },
+ { ip4_name_gw, &ip4_settings.gateway }
+ };
+
+ int rc = mbg_get_ip4_settings( dh, &prv_ip4_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ip4_settings" ) )
+ return rc;
+
+ if ( strcmp( arg, "DHCP" ) == 0 )
+ {
+ ip4_settings = prv_ip4_settings;
+ ip4_settings.flags |= IP4_MSK_DHCP;
+ goto save;
+ }
+
+ for (;;)
+ {
+ int i;
+
+ for ( i = 0; i < N_IP4_INFO; i++ )
+ {
+ rc = ip4_check_parm( arg, &ip4_info[i] );
+
+ if ( rc == 0 ) // check next
+ continue;
+
+ if ( rc < 0 ) // error
+ goto invalid_msg;
+
+ arg += rc;
+
+ if ( *arg == 0 ) // end of parameter string
+ goto done;
+
+ if ( *arg != ',' )
+ goto invalid_msg;
+
+ arg++;
+ }
+ }
+
+
+done: // now check static configuration
+ if ( ip4_settings.ip_addr == 0 ) // no IP address specified on the command line
+ ip4_settings.ip_addr = prv_ip4_settings.ip_addr; // use previous IP address
+
+ if ( ip4_settings.ip_addr == 0 ) // no IP address specified at all
+ {
+ printf( "*** Aborting: No IP address specified\n" );
+ goto invalid;
+ }
+
+ if ( ip4_settings.netmask == 0 ) // no network mask specified on the command line
+ ip4_settings.netmask = prv_ip4_settings.netmask; // use previous network mask
+
+ if ( ip4_settings.netmask == 0 ) // no network mask specified at all
+ {
+ printf( "*** Aborting: No network mask specified\n" );
+ goto invalid;
+ }
+
+ // the default broadcast address is computed from the IP address and the network mask
+ default_broad_addr = ip4_settings.ip_addr | ~ip4_settings.netmask;
+
+ if ( ip4_settings.broad_addr == 0 ) // no broadcast address specified on the command line
+ ip4_settings.broad_addr = default_broad_addr;
+ else
+ if ( ip4_settings.broad_addr != default_broad_addr )
+ {
+ char ws1[40];
+ char ws2[40];
+ snprint_ip4_addr( ws1, sizeof( ws1 ), &ip4_settings.broad_addr, NULL );
+ snprint_ip4_addr( ws2, sizeof( ws2 ), &default_broad_addr, NULL );
+ printf( "*** Warning: Broadcast address %s does not match the default broadcast address %s\n",
+ ws1, ws2 );
+ }
+
+ if ( ip4_settings.gateway == 0 )
+ ip4_settings.gateway = prv_ip4_settings.gateway;
+
+ ip4_settings.flags = prv_ip4_settings.flags & ~IP4_MSK_DHCP;
+ // fall through to save:
+
+save:
+ rc = mbg_set_ip4_settings( dh, &ip4_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_ip4_settings" ) )
+ return rc;
+
+ return MBG_SUCCESS;
+
+
+invalid_msg:
+ printf( "*** Warning: invalid LAN interface parameter syntax\n" );
+ // fall through to invalid:
+
+invalid:
+ return MBG_ERR_CFG; // invalid parameter or parameter syntax error
+
+} // set_lan_intf
+
+
+
+static /*HDR*/
+int set_gps_pos( MBG_DEV_HANDLE dh, const char *gp )
+{
+ LLA new_pos_lla;
+ char *cp;
+ int rc;
+ double r2d = 180 / PI;
+
+ new_pos_lla[LAT] = strtod( gp, &cp ) / r2d;
+
+ if ( *cp++ != ',' )
+ goto invalid;
+
+ new_pos_lla[LON] = strtod( cp, &cp ) / r2d;
+
+ if ( *cp++ != ',' )
+ goto invalid;
+
+ new_pos_lla[ALT] = strtod( cp, &cp );
+
+ if (
+ ( ( new_pos_lla[LAT] * r2d ) < -90 ) ||
+ ( ( new_pos_lla[LAT] * r2d ) > +90 ) ||
+ ( ( new_pos_lla[LON] * r2d ) < -180 ) ||
+ ( ( new_pos_lla[LON] * r2d ) > +180 ) ||
+ ( new_pos_lla[ALT] < -50 ) ||
+ ( new_pos_lla[ALT] > 20000 )
+ )
+ goto invalid;
+
+
+ rc = mbg_set_gps_pos_lla ( dh, new_pos_lla );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_pos_lla" ) )
+ return rc;
+
+ printf( "The clock's receiver position has been set to lat=%+.4f, lon=%+.4f, alt=%.0fm\n",
+ new_pos_lla[LAT] * r2d, new_pos_lla[LON] * r2d, new_pos_lla[ALT] );
+
+ return rc;
+
+
+invalid:
+ fprintf( stderr, "** Invalid GPS position parameters: %s\n", gp );
+
+ return MBG_ERR_CFG;
+
+} // set_gps_pos
+
+
+
+static /*HDR*/
+int set_date_time( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev,
+ const char *sdate, const char *stime )
+{
+ PCPS_TIME_UNION u = { { 0 } };
+ TTM ttm = { 0 };
+ unsigned int year = 0;
+ unsigned int month = 0;
+ unsigned int mday = 0;
+ unsigned int hour = 0;
+ unsigned int min = 0;
+ unsigned int sec = 0;
+ unsigned int sec100 = 0;
+ int rc;
+
+ // Either a date string, a time string, or both
+ // may have been passed to this function.
+ // If either of them is NULL read the current date/time
+ // as default values.
+ if ( sdate == NULL || stime == NULL )
+ {
+ rc = mbg_get_time( dh, &u.t );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_time" ) )
+ return rc;
+ }
+
+
+ if ( sdate )
+ {
+ rc = sscanf( sdate, "%u-%u-%u", &year, &month, &mday );
+
+ if ( ( rc < 3 )
+ || ( month < 1 ) || ( month > 12 )
+ || ( mday < 1 ) || ( mday > 31 ) )
+ {
+ printf( "** Invalid date: %04u-%02u-%02u\n", year, month, mday );
+ return MBG_ERR_CFG;
+ }
+ }
+
+
+ if ( stime )
+ {
+ rc = sscanf( stime, "%u:%u:%u.%u", &hour, &min, &sec, &sec100 );
+
+ if ( ( rc < 2 ) // at least hours and minutes are required
+ || ( hour > 23 )
+ || ( min > 59 )
+ || ( sec > 60 )
+ || ( sec100 > 99 ) )
+ {
+ printf( "** Invalid time: %02u:%02u:%02u.%02u\n", hour, min, sec, sec100 );
+ return MBG_ERR_CFG;
+ }
+ }
+
+ // GPS and non-GPS cards require different API calls which use
+ // different structures to set the on-board date and time,
+ // so we have to distinguish.
+
+ if ( _pcps_is_gps( p_dev ) ) // is a GPS card
+ {
+ ttm.channel = -1;
+
+ if ( sdate ) // new date
+ {
+ ttm.tm.year = year;
+ ttm.tm.month = month;
+ ttm.tm.mday = mday;
+ }
+ else // copy current date as default
+ {
+ ttm.tm.year = u.t.year + 2000;
+ ttm.tm.month = u.t.month;
+ ttm.tm.mday = u.t.mday;
+ }
+
+ if ( stime ) // new time
+ {
+ ttm.tm.hour = hour;
+ ttm.tm.min = min;
+ ttm.tm.sec = sec;
+ ttm.tm.frac = sec100;
+ }
+ else // copy current time as default
+ {
+ ttm.tm.hour = u.t.hour;
+ ttm.tm.min = u.t.min;
+ ttm.tm.sec = u.t.sec;
+ ttm.tm.frac = u.t.sec100;
+ }
+
+ ttm.tm.frac *= 100000; // fracs are in 100 ns units
+
+ #if 0
+ // Existing versions of the GPS cards just take
+ // TTM.tm as local time without accounting for
+ // the status flags, or UTC offset.
+ // Instead, the TTM.tm time is converted on-board
+ // to UTC depending on the local TZDL configuration.
+ // This works if the system time and the
+ ttm.tm.offs_from_utc = 7200;
+ ttm.tm.status |= TM_UTC | TM_LOCAL;
+ ttm.tm.status |= TM_DL_ENB;
+ #endif
+
+ rc = mbg_set_gps_time( dh, &ttm );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_time" ) )
+ return rc;
+ }
+ else // is not a GPS card
+ {
+ if ( sdate ) // new date
+ {
+ // determine the day-of-week for the given date
+ struct tm tm = { 0 };
+
+ tm.tm_year = year - 1900;
+ tm.tm_mon = month - 1;
+ tm.tm_mday = mday;
+ tm.tm_hour = 12;
+ tm.tm_isdst = -1;
+ mktime( &tm );
+
+ u.stime.year = year % 100;
+ u.stime.month = month;
+ u.stime.mday = mday;
+ u.stime.wday = _wday_sun06_to_mon17( tm.tm_wday );
+ }
+
+ if ( stime ) // new time
+ {
+ u.stime.hour = hour;
+ u.stime.min = min;
+ u.stime.sec = sec;
+ u.stime.sec100 = sec100;
+ }
+
+ if ( u.stime.wday == 0 )
+ u.stime.wday = 1; // dummy
+
+ rc = mbg_set_time( dh, &u.stime );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_time" ) )
+ return rc;
+ }
+
+ printf( "Device date/time have been set.\n" );
+
+ return MBG_SUCCESS;
+
+} // set_date_time
+
+
+
+static /*HDR*/
+void check_setup_receiver_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev,
+ RECEIVER_INFO *p_ri )
+{
+ // Set up the RECEIVER_INFO structure only if this has not been done
+ // before. Check the ticks_per_sec field to see if the structure
+ // has already been set up or not.
+ if ( p_ri->ticks_per_sec == 0 )
+ mbg_setup_receiver_info( dh, p_dev, p_ri );
+
+} // check_setup_receiver_info
+
+
+
+static /*HDR*/
+int check_get_receiver_port_cfg( MBG_DEV_HANDLE dh, RECEIVER_PORT_CFG *p_rpcfg,
+ const PCPS_DEV *p_dev, RECEIVER_INFO *p_ri )
+{
+ int rc = MBG_SUCCESS;
+
+ check_setup_receiver_info( dh, p_dev, p_ri );
+
+ // Set up the RECEIVER_PORT_CFG structure only if this has not been done
+ // before. Check whether the number of ports is > 0 and the first port's
+ // baud rate is still 0 to see if the structure has already been set up.
+ if ( ( p_ri->n_com_ports > 0 ) &&
+ ( p_rpcfg->pii[0].port_info.port_settings.parm.baud_rate == 0 ) )
+ {
+ rc = mbg_get_serial_settings( dh, p_dev, p_rpcfg, p_ri );
+
+ mbg_ioctl_err( rc, "mbg_get_serial_settings" );
+ }
+
+ return rc;
+
+} // check_get_receiver_port_cfg
+
+
+
+static /*HDR*/
+int snprint_port_cfg( char *s, int sz, unsigned int port_num,
+ const RECEIVER_PORT_CFG *p_rpcfg )
+{
+ const PORT_SETTINGS *p_ps = &p_rpcfg->pii[port_num].port_info.port_settings;
+
+ int n = snprintf( s, sz, "\"%s\" %s at %lu/%s",
+ p_rpcfg->stii[p_ps->str_type].str_type_info.long_name,
+ mode_names[p_ps->mode],
+ (unsigned long) p_ps->parm.baud_rate,
+ p_ps->parm.framing
+ );
+
+ return n;
+
+} // snprint_port_cfg
+
+
+
+static /*HDR*/
+void show_serial_settings( MBG_DEV_HANDLE dh, const RECEIVER_PORT_CFG *p_rpcfg,
+ const RECEIVER_INFO *p_ri )
+{
+ char ws[256];
+ unsigned int i;
+
+ for ( i = 0; i < p_ri->n_com_ports; i ++ )
+ {
+ snprint_port_cfg( ws, sizeof( ws ), i, p_rpcfg );
+ printf( "Serial port COM%u: %s.\n", i, ws );
+ }
+
+} // show_serial_settings
+
+
+
+static /*HDR*/
+void print_port_info_errors( const char *port_name, unsigned int port_num,
+ int flags, const RECEIVER_PORT_CFG *p_rpcfg )
+{
+ const char *msg_nsupp_drvr = "is not supported by the driver software";
+
+ const PORT_INFO *p_pi = &p_rpcfg->pii[port_num].port_info;
+ const PORT_SETTINGS *p_ps = &p_pi->port_settings;
+
+
+ if ( flags & MBG_PS_MSK_BAUD_RATE_OVR_SW )
+ printf( "** Baud rate %lu %s.\n", (ulong) p_ps->parm.baud_rate, msg_nsupp_drvr );
+ else
+ if ( flags & MBG_PS_MSK_BAUD_RATE )
+ printf( "** Baud rate %lu is not supported by %s%u.\n",
+ (ulong) p_ps->parm.baud_rate, port_name, port_num );
+
+
+ if ( flags & MBG_PS_MSK_FRAMING_OVR_SW )
+ printf( "** Framing %s %s.\n", p_ps->parm.framing, msg_nsupp_drvr );
+ else
+ if ( flags & MBG_PS_MSK_FRAMING )
+ printf( "** Framing %s is not supported by %s%u.\n",
+ p_ps->parm.framing, port_name, port_num );
+
+
+ if ( flags & MBG_PS_MSK_HS_OVR_SW )
+ printf( "** Handshake mode %u %s.\n", p_ps->parm.handshake, msg_nsupp_drvr );
+ else
+ if ( flags & MBG_PS_MSK_HS )
+ printf( "** Handshake mode %u is not supported by %s%u.\n",
+ (unsigned int) p_ps->parm.handshake, port_name, port_num );
+
+
+ if ( flags & MBG_PS_MSK_STR_TYPE_OVR_DEV )
+ printf( "** String type index %u exceeds number of string types supp. by device.\n",
+ p_ps->str_type );
+ else
+ if ( flags & MBG_PS_MSK_STR_TYPE )
+ printf( "** String type \"%s\" is not supported by %s%u.\n",
+ p_rpcfg->stii[p_ps->str_type].str_type_info.long_name,
+ port_name, port_num );
+
+
+ if ( flags & MBG_PS_MSK_STR_MODE_OVR_SW )
+ printf( "** String mode index %u exceeds number of string modes supported by driver software (%u).\n",
+ p_ps->mode, N_STR_MODE );
+ else
+ if ( flags & MBG_PS_MSK_STR_MODE )
+ printf( "** String mode \"%s\" is not supported by string type \"%s\" via %s%u .\n",
+ mode_names[p_ps->mode],
+ p_rpcfg->stii[p_ps->str_type].str_type_info.long_name,
+ port_name, port_num );
+
+} // print_port_info_errors
+
+
+
+static /*HDR*/
+int save_serial_settings( MBG_DEV_HANDLE dh, unsigned int port_num, const char *parm_str,
+ const PCPS_DEV *p_dev, const RECEIVER_INFO *p_ri )
+{
+ char ws[256];
+ RECEIVER_PORT_CFG rpcfg = { { { 0 } } };
+ PORT_INFO *p_pi = &rpcfg.pii[port_num].port_info;
+ PORT_SETTINGS *p_ps = &p_pi->port_settings;
+ ulong ul;
+ const char *cp;
+ char *p_tail;
+ int rc;
+ int flags;
+ int i;
+
+ // load current settings and supported settings
+ rc = mbg_get_serial_settings( dh, p_dev, &rpcfg, p_ri );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_serial_settings" ) )
+ return rc;
+
+
+ cp = parm_str;
+ p_ps->parm.baud_rate = strtoul( cp, &p_tail, 10 );
+
+ if ( p_tail == cp ) // no number found
+ goto invalid;
+
+ cp = p_tail;
+
+ if ( *cp++ != ',' ) // separator before framing missing
+ goto invalid;
+
+ for ( i = 0; i < sizeof( p_ps->parm.framing ); i++ )
+ {
+ int c = *cp;
+
+ if ( !isalnum( c ) ) // stop copying if non-alpha and non-digit
+ break;
+
+ p_ps->parm.framing[i] = *cp++;
+ }
+
+ p_ps->parm.framing[i] = 0; // force terminating 0
+
+ p_ps->parm.handshake = HS_NONE; // this is the only supported setting
+
+
+ // get optional string type index
+
+ if ( *cp++ != ',' )
+ goto done_parm_str;
+
+ ul = strtoul( cp, &p_tail, 10 );
+
+ if ( p_tail != cp )
+ p_ps->str_type = ul;
+
+ cp = p_tail;
+
+
+ // get optional string mode index
+
+ if ( *cp++ != ',' )
+ goto done_parm_str;
+
+ ul = strtoul( cp, &p_tail, 10 );
+
+ if ( p_tail != cp )
+ p_ps->mode = ul;
+
+
+done_parm_str:
+
+ // check if the new parameter set is valid
+ flags = check_valid_port_info( p_pi, rpcfg.stii, p_ri->n_str_type );
+
+ if ( flags ) // parameters not valid
+ {
+ print_port_info_errors( "COM", port_num, flags, &rpcfg );
+ goto invalid;
+ }
+
+ // save new parameters
+ rc = mbg_save_serial_settings( dh, p_dev, &rpcfg, port_num );
+
+ if ( mbg_ioctl_err( rc, "mbg_save_serial_settings" ) )
+ return rc;
+
+
+ snprint_port_cfg( ws, sizeof( ws ), port_num, &rpcfg );
+ printf( "The clock's COM%u port has been set to %s.\n", port_num, ws );
+
+ return MBG_SUCCESS;
+
+
+invalid:
+ fprintf( stderr, "** Invalid COM port parameters: %s\n", parm_str );
+ return MBG_ERR_CFG;
+
+} // save_serial_settings
+
+
+
+static /*HDR*/
+void printf_ef( uint16_t flag, const char *info )
+{
+ printf( "%s:%u", info, ( flag == EF_OFF ) ? 0 : 1 );
+
+} // printf_ef
+
+
+
+static /*HDR*/
+int show_enable_flags( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
+{
+ ENABLE_FLAGS ef;
+ int rc;
+
+ rc = mbg_get_gps_enable_flags( dh, &ef );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_enable_flags" ) )
+ return rc;
+
+ printf( "%s enable flags: ", info );
+ printf_ef( ef.serial, ef_name_serial );
+ printf( "," );
+ printf_ef( ef.pulses, ef_name_pulses );
+
+ if ( _pcps_has_synth( p_dev ) )
+ {
+ printf( "," );
+ printf_ef( ef.synth, ef_name_synth );
+ }
+
+ printf( "\n" );
+
+ return MBG_SUCCESS;
+
+} // show_enable_flags
+
+
+
+static /*HDR*/
+int ef_check_parm( const char *s, EF_INFO *p )
+{
+ int l = strlen( p->name );
+
+ if ( strncmp( s, p->name, l ) != 0 )
+ return 0; // parameter does not match
+
+ if ( s[l] != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ if ( s[l] != '0' && s[l] != '1' )
+ goto fail; // parameter syntax error: colon not followed by '0' or '1'
+
+ *p->flags = ( s[l] == '0' ) ? EF_OFF : p->on_flags;
+
+ l++;
+
+ return l;
+
+
+fail:
+ return MBG_ERR_CFG;
+
+} // ef_check_parm
+
+
+
+static /*HDR*/
+int set_enable_flags( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
+{
+ ENABLE_FLAGS ef;
+
+ EF_INFO ef_parms[N_EF_INFO] =
+ {
+ { ef_name_serial, &ef.serial, EF_SERIAL_BOTH },
+ { ef_name_pulses, &ef.pulses, EF_PULSES_BOTH },
+ { ef_name_synth, &ef.synth, EF_SYNTH }
+ };
+
+ int rc;
+
+ rc = mbg_get_gps_enable_flags( dh, &ef );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_enable_flags" ) )
+ return rc;
+
+ // Scan input parameters
+ for (;;)
+ {
+ int i;
+
+ for ( i = 0; i < N_EF_INFO; i++ )
+ {
+ rc = ef_check_parm( arg, &ef_parms[i] );
+
+ if ( rc == 0 ) // check next
+ continue;
+
+ if ( rc < 0 ) // error
+ return rc;
+
+ arg += rc;
+
+ if ( *arg == 0 ) // done
+ goto save;
+
+ if ( *arg != ',' )
+ return MBG_ERR_CFG; // invalid parameter or parameter syntax error
+
+ arg++;
+ }
+ }
+
+save:
+ rc = mbg_set_gps_enable_flags( dh, &ef );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_enable_flags" ) )
+ return rc;
+
+ return MBG_SUCCESS;
+
+} // set_enable_flags
+
+
+
+static /*HDR*/
+int send_gps_cmd( MBG_DEV_HANDLE dh, ushort cmd )
+{
+ int rc = mbg_set_gps_cmd( dh, &cmd );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_cmd" ) )
+ return rc;
+
+ printf( "NOTE: the command code %u has been sent to the GPS clock.\n", cmd );
+
+ return MBG_SUCCESS;
+
+} // send_gps_cmd
+
+
+
+static /*HDR*/
+int show_ant_cable_len( MBG_DEV_HANDLE dh, const char *info )
+{
+ ANT_CABLE_LEN len;
+ int rc = mbg_get_gps_ant_cable_len( dh, &len );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_ant_cable_len" ) )
+ return rc;
+
+ printf( "%s antenna cable length: %u meter(s)", info, len );
+
+ return MBG_SUCCESS;
+
+} // show_ant_cable_len
+
+
+
+static /*HDR*/
+int set_ant_cable_len( MBG_DEV_HANDLE dh, const char *s )
+{
+ ANT_CABLE_LEN len = atol( s );
+ int rc = mbg_set_gps_ant_cable_len( dh, &len );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_ant_cable_len" ) )
+ return rc;
+
+ return MBG_SUCCESS;
+
+} // set_ant_cable_len
+
+
+
+static /*HDR*/
+int set_event_time( MBG_DEV_HANDLE dh, const char *s )
+{
+ char ws[80];
+ time_t event_time;
+ PCPS_TIME_STAMP event_ts;
+ int rc;
+
+ // set event at current system time + number of seconds
+ event_time = time( NULL ) + strtol( s, NULL, 10 );
+ event_ts.sec = event_time; // Unix UTC seconds
+ event_ts.frac = 0; // fraction of second, 0xFFFFFFFF == 0.99.. sec
+
+ rc = mbg_set_event_time( dh, &event_ts );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_event_time" ) )
+ return rc;
+
+ mbg_snprint_hr_tstamp( ws, sizeof( ws ), &event_ts, 0 ); // raw timestamp?
+ printf( "Event time set to UTC %s\n", ws );
+
+ return MBG_SUCCESS;
+
+} // set_event_time
+
+
+
+static /*HDR*/
+int get_n_time_scale( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p_tsci )
+{
+ MBG_TIME_SCALE_INFO tsci = { { 0 } };
+ int rc;
+ int i;
+
+ rc = mbg_dev_has_time_scale( dh, &i );
+
+ if ( ( rc != MBG_SUCCESS ) || ( i == 0 ) )
+ goto done; // failed or not supported
+
+ rc = mbg_get_time_scale_info( dh, &tsci );
+
+ if ( rc != MBG_SUCCESS )
+ goto done;
+
+ if ( p_tsci )
+ *p_tsci = tsci;
+
+done:
+ return tsci.max_settings.scale;
+
+} // get_n_time_scale
+
+
+
+static /*HDR*/
+int show_time_scale( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
+{
+ MBG_TIME_SCALE_INFO tsci = { { 0 } };
+ int rc;
+
+ rc = mbg_get_time_scale_info( dh, &tsci );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_time_scale_info" ) )
+ return rc;
+
+ printf( "%s time scale index: %u (%s)", info, tsci.settings.scale,
+ _get_time_scale_name( tsci.settings.scale ) );
+
+ printf( "\n" );
+
+ return MBG_SUCCESS;
+
+} // show_time_scale
+
+
+
+static /*HDR*/
+int set_time_scale( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
+{
+ MBG_TIME_SCALE_INFO tsci = { { 0 } };
+ int rc;
+
+ rc = mbg_get_time_scale_info( dh, &tsci );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_time_scale_info" ) )
+ return rc;
+
+
+ tsci.settings.scale = atoi( arg );
+
+ if ( tsci.settings.scale >= tsci.max_settings.scale )
+ {
+ printf( "*** Error: new time scale index (%u) out of range (0..%u)\n",
+ tsci.settings.scale, tsci.max_settings.scale - 1 );
+ return MBG_ERR_CFG;
+ }
+
+ if ( !( tsci.supp_scales & ( 1UL << tsci.settings.scale ) ) )
+ {
+ printf( "*** Warning: new time scale index (%u) not supported by device\n",
+ tsci.settings.scale );
+ return MBG_ERR_CFG;
+ }
+
+ rc = mbg_set_time_scale_settings( dh, &tsci.settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_time_scale_settings" ) )
+ return rc;
+
+ return MBG_SUCCESS;
+
+} // set_time_scale
+
+
+
+static /*HDR*/
+void usage( MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri,
+ RECEIVER_PORT_CFG *p_rpcfg )
+{
+ int i;
+ int n_time_scale;
+
+ if ( p_dev )
+ {
+ check_setup_receiver_info( dh, p_dev, p_ri );
+ check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri );
+ }
+
+ printf( "Usage: %s cmd [dev]\n"
+ "\n"
+ "where cmd can be one of the following:\n"
+ " BOOT set GPS clock to boot mode\n"
+ " GPSPOS=x.x,y.y,z set GPS position to (lat,lon,alt)\n",
+ pname
+ );
+
+
+ printf( " DATE=yyyy-mm-dd set on-board date to year, month, day-of-month\n"
+ " TIME=hh:mm:ss.hh set on-board time to hours, mins, secs, hundredths\n"
+ );
+
+
+ printf( " TIMESCALE show clock's time scale setting, if supported\n"
+ " TIMESCALE=<n> set clock's time scale to scale with index <n>\n"
+ );
+
+ n_time_scale = p_dev ? get_n_time_scale( dh, NULL ) : N_MBG_TIME_SCALE;
+
+ if ( n_time_scale )
+ {
+ printf( " Known time scales:\n" );
+ for ( i = 0; i < n_time_scale; i++ )
+ {
+ printf( " %u: %s", i, _get_time_scale_name( i ) );
+
+ if ( i == 0 )
+ printf( " (default)" );
+
+ printf( "\n" );
+ }
+ }
+ else
+ printf( " (Configurable time scales not supported by this device)\n" );
+
+
+ printf( " TZOFFS show clock's time zone offset, if supported\n"
+ " TZOFFS=<n> set clock's basic time zone to UTC with additional offset, in seconds\n"
+ );
+
+ printf( " TZ=UTC set time zone code to %s\n"
+ " TZ=CET set time zone code to %s\n"
+ " TZ=EET set time zone code to %s\n",
+ tz_info_utc,
+ tz_info_cet_cest,
+ tz_info_eet_eest
+ );
+
+
+ printf( " COMPARM show clock's COM port parameters\n"
+ " COM<n>=<bd>,<f>[,<t>[,<m>]] set parameters of clock's port COM<n>"
+ );
+
+ printf( ", where\n"
+ " <bd> is one of:" );
+ for ( i = 0; i < N_MBG_BAUD_RATES; i++ )
+ printf( " %s", mbg_baud_str[i] );
+
+ printf( "\n"
+ " <f> is one of:" );
+ for ( i = 0; i < N_MBG_FRAMINGS; i++ )
+ printf( " %s", mbg_framing_str[i] );
+
+ printf( "\n <t> optional time string format index" );
+
+ if ( p_dev )
+ {
+ printf( ":" );
+
+ for ( i = 0; i < p_ri->n_str_type; i ++ )
+ {
+ const STR_TYPE_INFO *p_sti = &p_rpcfg->stii[i].str_type_info;
+
+ printf( "\n %u: %s", i, p_sti->long_name );
+ }
+ }
+
+ printf( "\n <m> optional time string mode index" );
+
+ if ( p_dev )
+ {
+ printf( ":" );
+
+ for ( i = 0; i < N_STR_MODE; i ++ )
+ printf( "\n %u: %s", i, mode_names[i] );
+
+ printf( "\n"
+ " Please note not each baud rate, framing, string format and mode\n"
+ " must necessarily be supported by every individual serial port.\n" );
+ }
+
+ printf( "\n" );
+
+ printf( " EF show clock's enable flags\n"
+ " EF=SERIAL:0,PULSES:1,SYNTH:0 modify clock's enable flags\n"
+ "\n"
+ " SERIAL controls the serial port output\n"
+ " PULSES controls pulse outputs and IRIG timecode output, if available\n"
+ " SYNTH controls a programmable synthesizer output, if available\n"
+ "\n"
+ " 0 or 1 controls when the corresponding output signals are enabled:\n"
+ " 0: only after the card has synchronized to its incoming signal\n"
+ " 1: immediately after power-up\n"
+ "\n"
+ " Please note that not every device supports enable flags.\n"
+ "\n"
+ );
+
+ printf( " LAN show board's LAN interface settings\n"
+ " LAN=DHCP set LAN interface to be configured via DHCP\n"
+ " LAN=IP:<ip>[,NM:<nm>][,BA:<ba>][,GW:<gw>] set LAN interface to given static settings\n"
+ "\n"
+ " where each of <ip>,<nm>,<ba>,<gw> is an IPv4 address of the form aaa.bbb.ccc.ddd, e.g.:\n"
+ " IP:192.168.1.115 specifies the IP address\n"
+ " NM:255.255.255.0 specifies the net mask\n"
+ " BA:192.168.1.255 specifies the broadcast address\n"
+ " GW:192.168.1.1 specifies the default gateway\n"
+ "\n"
+ " If no broadcast address is specified then the default broadcast address\n"
+ " is computed from the IP address and the network mask.\n"
+ "\n"
+ " Please note that not every device provides a LAN interface.\n"
+ " Also, the IP values above are examples only. The real values to be used\n"
+ " depend on the settings of the network to which the card is attached.\n"
+ "\n"
+ );
+
+ printf( " PTP show board's PTP settings\n"
+ " PTP=NP:<np>[,DM:<dm>][,DO:<do>][,HW:<hw>] set general PTP protocol parameters\n"
+ "\n"
+ " where, e.g. :\n"
+ " NP:IP4 specifies UDP/IPv4 (Layer 3) as network protocol\n"
+ " NP:ETH specifies IEEE 802.3 (Layer 2) as network protocol\n"
+ " DM:E2E specifies end-to-end delay mechanism\n"
+ " DM:P2P specifies peer-to-peer delay mechanism\n"
+ " DO:0 specifies PTP domain number [0..255]\n"
+ " HW:1 specifies if the \"v1 hardware compatibility flag\" shall be set ('1') or disabled ('0')\n"
+ " (this is usually not required)\n"
+ "\n"
+ );
+
+ printf( " If the PTP device supports unicast slave mode then the following parameters\n"
+ " can be specified to configure a unicast master to be queried:\n"
+ " PTP=ROLE:<rl>[,GMIP:<ip>][,GMID:<id>][,PID:<po>][,SMI:<sr>][,AMI:<ar>][,DMI:<dr>][,DUR:<du>] set PTP unicast parameters\n"
+ "\n"
+ " where, e.g.:\n"
+ " ROLE:MCS specifies \"Multicast Slave\" PTP role\n"
+ " ROLE:UCS specifies \"Unicast Slave\" PTP role\n"
+ " GMIP:192.168.1.115 specifies the IP address of the grandmaster\n"
+ " GMID:FF:FF:FF:FF:FF:FF:FF:FF specifies the Clock ID of the grandmaster, or '*' as wildcard for all FF\n"
+ " PID:1 specifies the target port ID of the grandmaster port to be used, or '*' for wildcard\n"
+ " SMI:0 specifies the Sync message interval requested from the grandmaster in 2^x seconds [-6..6]\n"
+ " AMI:1 specifies the Announce message interval requested from the grandmaster in 2^x seconds [-6..6]\n"
+ " DMI:1 specifies the DelayRequest message interval requested from the grandmaster in 2^x seconds [-6..6]\n"
+ " DUR:300 specifies the duration in seconds how long the master shall send messages to the slave until a timeout or renewal occurs\n"
+ "\n"
+ );
+
+ printf( " ANT_CABLE_LEN show the configured antenna cable length\n"
+ " ANT_CABLE_LEN=<len> set the antenna cable length to be compensated to <len>, in meters.\n"
+ "\n"
+ " Please note note this parameter is only supported with cards which provide\n"
+ " compensation of the antenna cable signal propagation delay, i.e. GPS cards.\n"
+ "\n"
+ );
+
+ if ( p_dev )
+ {
+ if ( _pcps_has_event_time( p_dev ) )
+ printf( " EVENT=<n> set event time to system time + <n> seconds\n" );
+ }
+
+} // usage
+
+
+
+static /*HDR*/
+const char *str_parm_p( const char *s, const char *keyword )
+{
+ char *match = strstr( s, keyword );
+
+ if ( match && ( match == s ) )
+ return &s[strlen( keyword )];
+ else
+ return NULL;
+
+} // str_parm_p
+
+
+
+static /*HDR*/
+int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev,
+ RECEIVER_INFO *p_ri, RECEIVER_PORT_CFG *p_rpcfg )
+{
+ const char *sdate = NULL;
+ const char *stime = NULL;
+ const char *cp;
+ int i;
+ int rc = 0;
+ int error_occurred = 0;
+
+ must_print_usage = 0;
+
+ for ( i = 1; i < argc; i++ )
+ {
+ if ( rc < 0 )
+ error_occurred = 1;
+
+ if ( rc > 0 )
+ must_print_usage = 1;
+
+ rc = 0;
+
+ if ( ( strcmp( argv[i], "-?" ) == 0 ) ||
+ ( strcmp( argv[i], "-h" ) == 0 ) ||
+ ( strcmp( argv[i], "--help" ) == 0 ) )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ if ( strcmp( argv[i], "BOOT" ) == 0 )
+ {
+ if ( p_dev )
+ {
+ if ( _pcps_is_gps( p_dev ) )
+ rc = send_gps_cmd( dh, PC_GPS_CMD_BOOT );
+ else
+ err_msg( p_dev, no_gps_cmd );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "TZ=" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ rc = set_timezone( dh, cp, p_dev );
+
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "GPSPOS=" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ if ( _pcps_is_gps( p_dev ) )
+ rc = set_gps_pos( dh, cp );
+ else
+ err_msg( p_dev, no_gps_cmd );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "DATE=" );
+
+ if ( cp )
+ {
+ sdate = cp;
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "TIME=" );
+
+ if ( cp )
+ {
+ stime = cp;
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "COMPARM" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ check_setup_receiver_info( dh, p_dev, p_ri );
+ if ( p_ri->n_com_ports )
+ {
+ check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri );
+
+ if ( *cp != 0 )
+ {
+ printf( "** Invalid parameter: %s\n", argv[i] );
+ must_print_usage = 1;
+ continue;
+ }
+
+ show_serial_settings( dh, p_rpcfg, p_ri );
+ }
+ else
+ printf( "** This device does not provide a configurable COM port.\n" );
+ }
+
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "COM" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *p_tail;
+ ulong port_num;
+
+ check_setup_receiver_info( dh, p_dev, p_ri );
+ check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri );
+
+ port_num = strtoul( cp, &p_tail, 10 );
+
+ if ( p_tail == cp ) // no COM port number specified
+ {
+ printf( "** Invalid COM port specification: %s\n", argv[i] );
+ must_print_usage = 1;
+ continue;
+ }
+
+ cp = p_tail;
+
+ if ( port_num >= (ulong) p_ri->n_com_ports )
+ {
+ printf( "** COM port number %lu exceeds maximum %u\n",
+ port_num, p_ri->n_com_ports );
+ must_print_usage = 1;
+ continue;
+ }
+
+ if ( *cp != '=' )
+ {
+ printf( "** Invalid COM port specification: %s\n", argv[i] );
+ must_print_usage = 1;
+ continue;
+ }
+
+ rc = save_serial_settings( dh, (unsigned) port_num, ++cp, p_dev, p_ri );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "EF" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_gps_data( p_dev ) )
+ {
+ err_msg( p_dev, no_enable_flags );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_enable_flags( dh, ++cp, p_dev );
+
+ if ( rc < 0 )
+ {
+ printf( "*** Warning: invalid enable flag parameter syntax\n" );
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_enable_flags( dh, p_dev, info );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "TIMESCALE" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_time_scale( p_dev ) )
+ {
+ err_msg( p_dev, no_time_scale );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_time_scale( dh, ++cp, p_dev );
+
+ if ( rc < 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_time_scale( dh, p_dev, info );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "TZOFFS" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_tzdl( p_dev ) )
+ {
+ err_msg( p_dev, no_tzdl );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_tzdl_offs( dh, ++cp );
+
+ if ( rc < 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_tzdl_offs( dh, info );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "LAN" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_lan_intf( p_dev ) )
+ {
+ err_msg( p_dev, no_lan_intf );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_lan_intf( dh, ++cp, p_dev );
+
+ if ( rc < 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_lan_intf( dh, p_dev, info );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "PTP" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_ptp( p_dev ) )
+ {
+ err_msg( p_dev, no_ptp );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_ptp_cfg( dh, ++cp, p_dev );
+
+ if ( rc < 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_ptp_cfg( dh, p_dev, info );
+ }
+ continue;
+ }
+
+ cp = str_parm_p( argv[i], "ANT_CABLE_LEN" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_cab_len( p_dev ) )
+ {
+ err_msg( p_dev, no_cab_len );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_ant_cable_len( dh, ++cp );
+
+ if ( rc < 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_ant_cable_len( dh, info );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "EVENT" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ if ( _pcps_has_event_time( p_dev ) )
+ {
+ if ( *cp == '=' )
+ rc = set_event_time( dh, ++cp );
+ else
+ rc = -1;
+
+ if ( rc < 0 )
+ printf( "*** Warning: invalid event time parameter\n" );
+ }
+ else
+ err_msg( p_dev, no_event_time );
+ }
+ continue;
+ }
+
+ if ( dev_name == NULL )
+ dev_name = argv[i];
+
+#if 0 //##++
+ else
+ {
+ printf( "** Unknown command: %s\n", argv[i] );
+ must_print_usage = 1;
+ }
+#endif
+
+ }
+
+ if ( p_dev )
+ if ( sdate || stime )
+ rc = set_date_time( dh, p_dev, sdate, stime );
+
+ if ( error_occurred )
+ return -1;
+
+ if ( must_print_usage )
+ return 1;
+
+ return MBG_SUCCESS;
+
+} // check_cmd_line
+
+
+
+int main( int argc, char *argv[] )
+{
+ RECEIVER_PORT_CFG rpcfg = { { { 0 } } };
+ RECEIVER_INFO ri = { 0 };
+ PCPS_DEV dev = { { 0 } };
+ PCPS_DEV *pdev = NULL;
+ MBG_DEV_HANDLE dh = MBG_INVALID_DEV_HANDLE;
+ int rc;
+
+ mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR );
+
+ // If no arguments have been given, just print usage.
+ if ( argc < 2 )
+ goto show_usage;
+
+ // Check the command line for a device name, but don't
+ // pass a device handle, so commands are not evaluated.
+ check_cmd_line( argc, argv, dh, NULL, &ri, &rpcfg );
+
+ if ( dev_name )
+ dh = open( dev_name, O_RDWR ); // open specific device
+ else
+ dh = mbg_open_device( 0 ); // open first device found
+
+ if ( dh == MBG_INVALID_DEV_HANDLE )
+ {
+ //##++++++++++++++++++++++
+ if ( dev_name )
+ fprintf( stderr, "%s: ", dev_name );
+
+ perror( "Unable to open device" );
+ goto fail;
+ }
+
+ // get information about the device
+ rc = mbg_get_show_dev_info( dh, dev_name, &dev );
+
+ if ( rc < 0 )
+ goto fail;
+
+
+ pdev = &dev;
+
+ rc = check_cmd_line( argc, argv, dh, pdev, &ri, &rpcfg );
+
+ if ( rc < 0 )
+ goto fail;
+
+ if ( rc > 0 )
+ goto show_usage;
+
+ printf( "\n" );
+
+ mbg_close_device( &dh );
+
+ return 0;
+
+
+show_usage:
+ usage( dh, pdev, &ri, &rpcfg );
+ return 1;
+
+fail:
+ return 2;
+}
diff --git a/mbgfasttstamp/mbgfasttstamp.c b/mbgfasttstamp/mbgfasttstamp.c
new file mode 100644
index 0000000..c9b2d91
--- /dev/null
+++ b/mbgfasttstamp/mbgfasttstamp.c
@@ -0,0 +1,300 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgfasttstamp.c 1.6.1.8 2013/04/10 15:40:28Z martin TEST martin $
+ *
+ * Description:
+ * Main file for mbgfasttstamp program which demonstrates how to access
+ * a Meinberg device via memory mapped I/O, if supported by the device.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgfasttstamp.c $
+ * Revision 1.6.1.8 2013/04/10 15:40:28Z martin
+ * Revision 1.6.1.7 2013/01/24 14:39:33Z martin
+ * Revision 1.6.1.6 2012/06/01 18:46:52 martin
+ * Added option to sleep between calls.
+ * Revision 1.6.1.5 2011/12/19 16:09:17 martin
+ * Revision 1.6.1.4 2011/09/26 16:00:51 martin
+ * Modified program version handling.
+ * Account for modified library functions which can now
+ * optionally print the raw (hex) HR time stamp.
+ * Started to support signal handler to catch CTRL-C.
+ * Revision 1.6.1.3 2011/01/28 12:04:07 martin
+ * Revision 1.6.1.2 2011/01/28 11:51:13 martin
+ * Revision 1.6.1.1 2011/01/28 11:17:00 martin
+ * Abort if MM access not supported on the target OS.
+ * Revision 1.6 2010/05/21 12:54:33 martin
+ * Print warning if no cycles supported on the target platform
+ * and thus latencies can not be computed.
+ * Revision 1.5 2009/09/29 15:02:14 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.4 2009/07/24 09:50:08 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.3 2009/06/19 14:01:32 martin
+ * Made print_hr_timestamp() to toolutil.c as mbg_print_hr_timestamp().
+ * Updated version number to 3.2.0.
+ * Revision 1.2 2009/03/20 11:48:19 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * New parameter -r lets the program read raw timestamps
+ * using the new API call mbg_get_fast_hr_timestamp().
+ * Revision 1.1 2008/12/22 11:45:01 martin
+ * Initial revision.
+ * Revision 1.1 2008/12/22 11:05:24 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#define MBG_MICRO_VERSION 0
+#define MBG_FIRST_COPYRIGHT_YEAR 2007
+#define MBG_LAST_COPYRIGHT_YEAR 0 // use default
+
+static const char *pname = "mbgfasttstamp";
+
+
+#define MAX_TS_BURST 1000
+
+static int loops;
+static int burst_read;
+static int read_raw;
+static long sleep_secs;
+static long sleep_usecs;
+
+
+
+// The function below reads a number of time stamps and prints
+// each timestamp immediately. This is not as fast as possible
+// since printing the time stamp takes some time to execute.
+// However, this can run continuously forever.
+
+static /*HDR*/
+int show_fast_hr_timestamp( MBG_DEV_HANDLE dh )
+{
+ int this_loops = loops;
+ PCPS_TIME_STAMP ts;
+ int32_t hns_latency = 0;
+
+ for (;;)
+ {
+ int rc = read_raw ? mbg_get_fast_hr_timestamp( dh, &ts ) :
+ mbg_get_fast_hr_timestamp_comp( dh, &ts, &hns_latency );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp..." ) )
+ goto fail;
+
+ mbg_print_hr_timestamp( &ts, hns_latency, NULL, read_raw, 1 ); // raw timestamp?
+
+ if ( this_loops > 0 )
+ this_loops--;
+
+ if ( this_loops == 0 )
+ break;
+
+ if ( sleep_secs )
+ sleep( sleep_secs );
+ else
+ if ( sleep_usecs )
+ usleep( sleep_usecs );
+
+ // if this_loops is < 0 then loop forever
+ }
+
+ return 0;
+
+fail:
+ return -1;
+
+} // show_fast_hr_timestamp
+
+
+
+// The function below takes a number of time stamps and saves
+// them to a buffer. After the time stamps have been read
+// a second loop prints the time stamps from the buffer.
+// This way the time stamps are read in shorter intervals.
+// However, this can not run continuously forever since
+// the buffer size is somewhat limited.
+
+static /*HDR*/
+int show_fast_hr_timestamp_burst( MBG_DEV_HANDLE dh )
+{
+ PCPS_TIME_STAMP ts[MAX_TS_BURST];
+ int32_t hns_latency[MAX_TS_BURST];
+ int this_loops;
+ int i;
+
+ this_loops = ( loops && ( loops < MAX_TS_BURST ) ) ? loops : MAX_TS_BURST;
+
+
+ if ( read_raw )
+ {
+ for ( i = 0; i < this_loops; i++ )
+ {
+ int rc = mbg_get_fast_hr_timestamp( dh, &ts[i] );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp" ) )
+ goto fail;
+ }
+ }
+ else
+ for ( i = 0; i < this_loops; i++ )
+ {
+ int rc = mbg_get_fast_hr_timestamp_comp( dh, &ts[i], &hns_latency[i] );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp_comp" ) )
+ goto fail;
+ }
+
+ for ( i = 0; i < this_loops; i++ )
+ {
+ PCPS_TIME_STAMP *p_prv_ts = i ? &ts[i - 1] : NULL;
+ mbg_print_hr_timestamp( &ts[i], hns_latency[i], p_prv_ts, read_raw, 0 ); // raw timestamp?
+ }
+
+ return 0;
+
+
+fail:
+ return -1;
+
+} // show_fast_hr_timestamp_burst
+
+
+
+static /*HDR*/
+int do_mbgfasttstamp( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ int supported = 0;
+ int rc = mbg_dev_has_fast_hr_timestamp( dh, &supported );
+
+ if ( mbg_ioctl_err( rc, "mbg_has_fast_hr_timestamp" ) )
+ goto done;
+
+ if ( !supported )
+ {
+ printf( "This device does not support fast (memory mapped) time stamps.\n" );
+ goto done;
+ }
+
+ if ( burst_read )
+ show_fast_hr_timestamp_burst( dh );
+ else
+ show_fast_hr_timestamp( dh );
+
+done:
+ mbg_close_device( &dh );
+
+ return rc;
+
+} // do_mbgfasttstamp
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This example program reads fast high resolution time stamps.\n"
+ "\n"
+ "This is done using memory mapped I/O in the kernel driver, so\n"
+ "this works only with cards which support memory mapped I/O."
+ );
+ mbg_print_help_options();
+ mbg_print_opt_info( "-c", "run continuously" );
+ mbg_print_opt_info( "-n num", "run num loops" );
+ mbg_print_opt_info( "-b", "burst read" );
+ mbg_print_opt_info( "-r", "read raw time stamps, no cycles" );
+ mbg_print_opt_info( "-s num", "sleep num seconds between calls" );
+ mbg_print_opt_info( "-u num", "sleep num microseconds between calls" );
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int rc;
+ int c;
+
+ mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "bcn:rs:u:h?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'b':
+ burst_read = 1;
+ break;
+
+ case 'c':
+ loops = -1;
+ break;
+
+ case 'n':
+ loops = atoi( optarg );
+ break;
+
+ case 'r':
+ read_raw = 1;
+ break;
+
+ case 's':
+ sleep_secs = atoi( optarg );
+ break;
+
+ case 'u':
+ sleep_usecs = atoi( optarg );
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+ #if !MBG_TGT_SUPP_MEM_ACC
+ printf( "** Memory mapped access not supported on this target platform.\n\n" );
+ return 1;
+ #endif
+
+ #if !MBG_PC_CYCLES_SUPPORTED
+ printf( "** Warning: No cycles support to compute real latencies on this platform!\n" );
+
+ if ( !read_raw )
+ {
+ read_raw = 1;
+ printf( "** Falling back to raw mode.\n" );
+ }
+
+ printf( "\n" );
+ #endif
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbgfasttstamp );
+
+ return abs( rc );
+}
diff --git a/mbggpscap/mbggpscap.c b/mbggpscap/mbggpscap.c
new file mode 100644
index 0000000..8dc8b53
--- /dev/null
+++ b/mbggpscap/mbggpscap.c
@@ -0,0 +1,412 @@
+
+/**************************************************************************
+ *
+ * $Id: mbggpscap.c 1.10.1.7 2013/04/10 15:40:28Z martin TEST martin $
+ *
+ * Description:
+ * Main file for mbggpscap program which demonstrates how to access
+ * a Meinberg device via IOCTL calls and read entries from the time
+ * capture FIFO buffer.
+ *
+ * Please note that this may only work with devices which provide
+ * time capture input(s).
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbggpscap.c $
+ * Revision 1.10.1.7 2013/04/10 15:40:28Z martin
+ * Revision 1.10.1.6 2011/09/09 08:28:22Z martin
+ * Revision 1.10.1.5 2011/09/07 15:12:33 martin
+ * New option -r which displays raw timestamps and raw status.
+ * New option -o which forces usage of old API.
+ * Fixed a bug when displaying the capture event status. TTM and PCPS_HR_TIME
+ * are using different sets of status flags.
+ * Revision 1.10.1.4 2011/07/05 15:35:54 martin
+ * Modified version handling.
+ * Revision 1.10.1.3 2011/07/05 14:35:18 martin
+ * New way to maintain version information.
+ * Revision 1.10.1.2 2010/11/12 12:27:17 martin
+ * Improved reading capture events arriving at a high rate.
+ * Support validation of capture signals arriving at a constant rate.
+ * Revision 1.10.1.1 2010/03/10 16:42:33 martin
+ * Improved code execution paths.
+ * Revision 1.10 2009/09/29 15:02:15 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.9 2009/07/24 09:50:08 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.8 2009/06/19 12:38:51 martin
+ * Updated version number to 3.2.0.
+ * Revision 1.7 2009/03/19 17:04:26 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Revision 1.6 2008/12/22 12:00:55 martin
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Accept device name(s) on the command line.
+ * Don't use printf() without format, which migth produce warnings
+ * with newer gcc versions.
+ * Revision 1.5 2007/07/24 09:32:26 martin
+ * Updated copyright to include 2007.
+ * Revision 1.4 2006/02/22 15:29:17 martin
+ * Support new ucap API.
+ * Print an error message if device can't be opened.
+ * Revision 1.3 2004/11/08 15:47:10 martin
+ * Using type cast to avoid compiler warning.
+ * Revision 1.2 2003/04/25 10:28:05 martin
+ * Use new functions from mbgdevio library.
+ * New program version v2.1.
+ * Revision 1.1 2001/09/17 15:08:22 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+#define USLEEP_INTV 10000 // [microseconds]
+
+
+#define MBG_MICRO_VERSION 0
+#define MBG_FIRST_COPYRIGHT_YEAR 2001
+#define MBG_LAST_COPYRIGHT_YEAR 0 // use default
+
+static const char *pname = "mbggpscap";
+
+
+static int continuous;
+static double nom_cap_intv; // nominal capture interval to check [s]
+static double max_cap_jitter; // max allowed jitter [s]
+static int raw;
+static int force_old_api;
+
+static int has_been_called;
+static int must_check_intv;
+static ulong err_cnt;
+static PCPS_HR_TIME prv_ucap;
+
+
+
+static /*HDR*/
+void show_ucap_event( const PCPS_HR_TIME *ucap )
+{
+ char ws[80];
+
+ // Print converted date and time to a string:
+ mbg_snprint_hr_time( ws, sizeof( ws ), ucap, raw );
+
+ // Print the time stamp, ucap->signal contains the channel number:
+ printf( "New capture: CH%i: %s", ucap->signal, ws );
+
+ if ( must_check_intv && has_been_called )
+ {
+ double abs_delta;
+ double d = ucap->tstamp.sec - prv_ucap.tstamp.sec;
+ d += ( (double) ucap->tstamp.frac - prv_ucap.tstamp.frac ) / PCPS_HRT_BIN_FRAC_SCALE;
+
+ printf( " %+.6f", d );
+
+ abs_delta = d - nom_cap_intv;
+
+ if ( abs_delta < 0.0 )
+ abs_delta = -abs_delta;
+
+ if ( abs_delta > max_cap_jitter )
+ err_cnt++;
+
+ if ( err_cnt )
+ printf( " ** %lu", err_cnt );
+ }
+
+ // status bit definitions can be found in pcpsdefs.h.
+
+ if ( raw )
+ printf( ", st: 0x%04X", ucap->status );
+
+ if ( ucap->status & PCPS_UCAP_OVERRUN ) // capture events have occurred too fast
+ printf( " << CAP OVR" );
+
+ if ( ucap->status & PCPS_UCAP_BUFFER_FULL ) // capture buffer has been full, events lost
+ printf( " << BUF OVR" );
+
+ prv_ucap = *ucap;
+ has_been_called = 1;
+
+ printf( "\n" );
+
+} // show_ucap_event
+
+
+
+// The function below is normally outdated, and show_ucap_event()
+// above should be used if possible, together with the associated
+// API calls.
+
+static /*HDR*/
+void show_gps_ucap( const TTM *ucap )
+{
+ printf( "New capture: CH%i: %04i-%02i-%02i %2i:%02i:%02i.%07li",
+ ucap->channel,
+ ucap->tm.year,
+ ucap->tm.month,
+ ucap->tm.mday,
+ ucap->tm.hour,
+ ucap->tm.min,
+ ucap->tm.sec,
+ (ulong) ucap->tm.frac
+ );
+
+ if ( raw )
+ printf( ", st: 0x%04lX", (ulong) ucap->tm.status );
+
+ printf( "\n" );
+
+} // show_gps_ucap
+
+
+
+static /*HDR*/
+void check_serial_mode( MBG_DEV_HANDLE dh )
+{
+ PORT_PARM port_parm;
+ int i;
+ int must_modify = 0;
+
+ // read the clock's current port settings
+ int rc = mbg_get_gps_port_parm( dh, &port_parm );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_port_parm" ) )
+ return;
+
+
+ // If one of the ports has been set to send user captures
+ // then the user capture buffer will most often be empty
+ // if we check for captures, so modify the port mode.
+ for ( i = 0; i < N_COM; i++ )
+ {
+ if ( port_parm.mode[i] == STR_UCAP )
+ {
+ port_parm.mode[i] = STR_UCAP_REQ;
+ must_modify = 1;
+ }
+ }
+
+ if ( !must_modify )
+ return;
+
+
+ rc = mbg_set_gps_port_parm( dh, &port_parm );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_port_parm" ) )
+ return;
+
+ printf( "NOTE: the clock's serial port mode has been changed.\n" );
+
+} // check_serial_mode
+
+
+
+static /*HDR*/
+int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ int rc;
+
+ must_check_intv = continuous && ( nom_cap_intv != 0 );
+ has_been_called = 0;
+ err_cnt = 0;
+
+ if ( !_pcps_has_ucap( p_dev ) && !_pcps_is_gps( p_dev ) )
+ {
+ printf( "This device type does not provide time capture inputs.\n" );
+ return 0;
+ }
+
+ check_serial_mode( dh );
+
+ printf( "Be sure the card has been properly configured to enable capture inputs.\n" );
+
+ // There's an older API which has been introduced with the first GPS boards
+ // and uses the TTM structure to return the capture events. However, that
+ // API call is slow and not very flexible, so a new set of API calls has been
+ // introduced to handle capture events.
+ // The new API calls are supported by all supported by all newer boards which
+ // provide user capture inputs, and also for older boards with a firmware update.
+
+ if ( !force_old_api && _pcps_has_ucap( p_dev ) ) // check if the new API is supported
+ {
+ // The new API provides the following functions:
+ // mbg_clr_ucap_buff() clear the on-board FIFO buffer
+ // mbg_get_ucap_entries() get the max number of FIFO entries, and the current number of entries
+ // mbg_get_ucap_event() read one entry from the FIFO
+
+ PCPS_UCAP_ENTRIES ucap_entries;
+
+ // retrieve and print information of the maximum number of events that can
+ // be stored in the on-board FIFO, and the number of events that are currently
+ // stored
+ rc = mbg_get_ucap_entries( dh, &ucap_entries );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ // Cards report they could save one more capture event
+ // than they actually do save, so adjust the reported value
+ // for a proper display.
+ if ( ucap_entries.max )
+ ucap_entries.max--;
+
+ printf( "\nOn-board FIFO: %u of %u entries used\n\n",
+ ucap_entries.used, ucap_entries.max );
+ }
+
+ // If the program is not to run continuously and no
+ // capture events are available then we're through.
+ if ( !continuous && ucap_entries.used == 0 )
+ return 0;
+
+
+ printf( ( ucap_entries.used == 0 ) ?
+ "Waiting for capture events:\n" :
+ "Reading capture events:\n"
+ );
+
+ // Now read out all events from the FIFO and wait
+ // for new events if the FIFO is empty.
+ for (;;)
+ {
+ PCPS_HR_TIME ucap_event;
+
+ rc = mbg_get_ucap_event( dh, &ucap_event );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ucap_event" ) )
+ break; // an error has occurred
+
+ // If a user capture event has been read then it
+ // has been removed from the card's FIFO buffer.
+
+ // If the time stamp is not 0 then a new capture event has been retrieved.
+ if ( ucap_event.tstamp.sec || ucap_event.tstamp.frac )
+ {
+ show_ucap_event( &ucap_event );
+ continue;
+ }
+
+ usleep( USLEEP_INTV ); // sleep, then try again
+ }
+ }
+ else // use the old API
+ {
+ printf( "Checking for capture events using the old API:\n" );
+
+ for (;;)
+ {
+ TTM ucap_ttm;
+
+ rc = mbg_get_gps_ucap( dh, &ucap_ttm );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_ucap" ) )
+ break; // an error has occurred
+
+
+ // If a user capture event has been read then it
+ // has been removed from the card's FIFO buffer.
+
+ // If a new capture event has been available then
+ // the ucap.tm contains a time stamp.
+ if ( _pcps_time_is_read( &ucap_ttm.tm ) )
+ show_gps_ucap( &ucap_ttm );
+
+ if ( !continuous )
+ {
+ printf( "No capture event available!\n" );
+ break;
+ }
+
+ usleep( USLEEP_INTV ); // sleep, then try again
+ }
+ }
+
+ return 0;
+
+} // do_mbggpscap
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This example program reads time capture events from a card.\n"
+ "This works only with cards which provide time capture inputs."
+ );
+ mbg_print_help_options();
+ mbg_print_opt_info( "-c", "run continuously" );
+ mbg_print_opt_info( "-i val", "check interval between captures events [s]" );
+ mbg_print_opt_info( "-j val", "max allowed jitter of capture interval [s]" );
+ mbg_print_opt_info( "-r", "show raw (hex) timestamp and status)" );
+ mbg_print_opt_info( "-o", "force usage of old API (for testing only)" );
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int rc;
+ int c;
+
+ mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "ci:j:roh?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'c':
+ continuous = 1;
+ break;
+
+ case 'i':
+ nom_cap_intv = atof( optarg );
+ break;
+
+ case 'j':
+ max_cap_jitter = atof( optarg );
+ break;
+
+ case 'r':
+ raw = 1;
+ break;
+
+ case 'o':
+ force_old_api = 1;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbggpscap );
+
+ return abs( rc );
+}
diff --git a/mbghrtime/mbghrtime.c b/mbghrtime/mbghrtime.c
new file mode 100644
index 0000000..cf71778
--- /dev/null
+++ b/mbghrtime/mbghrtime.c
@@ -0,0 +1,323 @@
+
+/**************************************************************************
+ *
+ * $Id: mbghrtime.c 1.11.1.10 2013/04/10 15:40:29Z martin TEST martin $
+ *
+ * Description:
+ * Main file for mbghrtime program which demonstrates how to access
+ * a Meinberg device via IOCTL calls to read high resolution
+ * time stamps, if supported by the device.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbghrtime.c $
+ * Revision 1.11.1.10 2013/04/10 15:40:29Z martin
+ * Revision 1.11.1.9 2011/12/19 16:13:46Z martin
+ * Revision 1.11.1.8 2011/09/29 16:28:34 martin
+ * New options -s, -u, -v.
+ * Print time using new function mbg_print_hr_time().
+ * Revision 1.11.1.7 2011/09/07 15:08:55 martin
+ * Account for modified library functions which can now
+ * optionally print the raw (hex) HR time stamp.
+ * Revision 1.11.1.6 2011/07/05 15:35:54 martin
+ * Modified version handling.
+ * Revision 1.11.1.5 2011/07/05 14:35:18 martin
+ * New way to maintain version information.
+ * Revision 1.11.1.4 2011/01/28 12:04:08 martin
+ * Revision 1.11.1.3 2011/01/28 11:52:51 martin
+ * Revision 1.11.1.2 2011/01/28 11:51:13 martin
+ * Revision 1.11.1.1 2011/01/28 11:17:33 martin
+ * Starrted to support raw and burst.
+ * Revision 1.11 2010/05/21 12:54:33 martin
+ * Print warning if no cycles supported on the target platform
+ * and thus latencies can not be computed.
+ * Revision 1.10 2009/09/29 15:02:15 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.9 2009/07/24 09:50:08 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.8 2009/06/19 14:03:53 martin
+ * Use common mbg_print_hr_timestamp() for unified output format.
+ * Updated version number to 3.2.0.
+ * Revision 1.7 2009/03/20 11:45:16 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Call mbg_get_hr_time_comp() instead of mbg_get_hr_time_cycles().
+ * Revision 1.6 2008/12/22 12:02:00 martin
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Accept device name(s) on the command line.
+ * Revision 1.5 2007/07/24 09:32:41 martin
+ * Updated copyright to include 2007.
+ * Revision 1.4 2004/11/08 15:45:22 martin
+ * Modifications to support 64 bit systems in a clean way.
+ * Revision 1.3 2003/04/25 10:28:05 martin
+ * Use new functions from mbgdevio library.
+ * New program version v2.1.
+ * Revision 1.2 2001/11/30 10:01:49 martin
+ * Account for the modified definition of PCPS_HR_TIME which
+ * uses the new structure PCPS_TIME_STAMP now.
+ * Revision 1.1 2001/09/17 15:08:31 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+
+// include system headers
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+
+#define MBG_MICRO_VERSION 0
+#define MBG_FIRST_COPYRIGHT_YEAR 2001
+#define MBG_LAST_COPYRIGHT_YEAR 0 // use default
+
+static const char *pname = "mbghrtime";
+
+
+#define MAX_TS_BURST 1000
+
+static int loops;
+static int burst_read;
+static int read_raw;
+static long sleep_secs;
+static long sleep_usecs;
+static int verbose;
+
+
+
+// The function below reads a number of time stamps and prints
+// each timestamp immediately. This is not as fast as possible
+// since printing the time stamp takes some time to execute.
+// However, this can run continuously forever.
+
+static /*HDR*/
+int show_hr_timestamp( MBG_DEV_HANDLE dh )
+{
+ PCPS_HR_TIME ht = { { 0 } };
+ PCPS_HR_TIME prv_ht = { { 0 } };
+ PCPS_TIME_STAMP *p = NULL;
+ int32_t hns_latency = 0;
+ int this_loops = loops;
+
+ for (;;)
+ {
+ int rc = read_raw ? mbg_get_hr_time( dh, &ht ) :
+ mbg_get_hr_time_comp( dh, &ht, &hns_latency );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_hr_time_..." ) )
+ goto fail;
+
+ mbg_print_hr_time( &ht, hns_latency, p, read_raw, verbose, verbose );
+
+ prv_ht = ht;
+ p = &prv_ht.tstamp;
+
+ if ( this_loops > 0 )
+ this_loops--;
+
+ if ( this_loops == 0 )
+ break;
+
+ if ( sleep_secs )
+ sleep( sleep_secs );
+ else
+ if ( sleep_usecs )
+ usleep( sleep_usecs );
+
+ // if this_loops is < 0 then loop forever
+ }
+
+ return 0;
+
+fail:
+ return -1;
+
+} // show_hr_timestamp
+
+
+
+// The function below takes a number of time stamps and saves
+// them to a buffer. After the time stamps have been read
+// a second loop prints the time stamps from the buffer.
+// This way the time stamps are read in shorter intervals.
+// However, this can not run continuously forever since
+// the buffer size is somewhat limited.
+
+static /*HDR*/
+int show_hr_timestamp_burst( MBG_DEV_HANDLE dh )
+{
+ PCPS_HR_TIME ht[MAX_TS_BURST] = { { { 0 } } };
+ int32_t hns_latency[MAX_TS_BURST];
+ int this_loops;
+ int i;
+
+ this_loops = ( loops && ( loops < MAX_TS_BURST ) ) ? loops : MAX_TS_BURST;
+
+
+ if ( read_raw )
+ {
+ for ( i = 0; i < this_loops; i++ )
+ {
+ int rc = mbg_get_hr_time( dh, &ht[i] );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_hr_time" ) )
+ goto fail;
+ }
+ }
+ else
+ for ( i = 0; i < this_loops; i++ )
+ {
+ int rc = mbg_get_hr_time_comp( dh, &ht[i], &hns_latency[i] );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_hr_time_comp" ) )
+ goto fail;
+ }
+
+ for ( i = 0; i < this_loops; i++ )
+ {
+ PCPS_HR_TIME *p_prv_ht = i ? &ht[i - 1] : NULL;
+ mbg_print_hr_time( &ht[i], hns_latency[i], &p_prv_ht->tstamp, read_raw, verbose, verbose );
+ }
+
+ return 0;
+
+
+fail:
+ return -1;
+
+} // show_hr_timestamp_burst
+
+
+
+static /*HDR*/
+int do_mbghrtime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ int supported = 0;
+ int rc = mbg_dev_has_hr_time( dh, &supported );
+
+ if ( mbg_ioctl_err( rc, "mbg_dev_has_hr_time" ) )
+ goto done;
+
+ if ( !supported )
+ {
+ printf( "High resolution time not supported by this device.\n" );
+ goto done;
+ }
+
+ if ( burst_read )
+ show_hr_timestamp_burst( dh );
+ else
+ show_hr_timestamp( dh );
+
+done:
+ mbg_close_device( &dh );
+
+ return rc;
+
+} // do_mbghrtime
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This example program reads high resolution time stamps (HR time)\n"
+ "from a device.\n"
+ "This works only for devices which support high resolution time (HR time)."
+ );
+ mbg_print_help_options();
+ mbg_print_opt_info( "-c", "run continuously" );
+ mbg_print_opt_info( "-n num", "run num loops" );
+ mbg_print_opt_info( "-b", "burst read" );
+ mbg_print_opt_info( "-r", "read raw time stamps, no cycles" );
+ mbg_print_opt_info( "-s num", "sleep num seconds between calls" );
+ mbg_print_opt_info( "-u num", "sleep num microseconds between calls" );
+ mbg_print_opt_info( "-v", "increase verbosity" );
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int rc;
+ int c;
+
+ mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "bcn:rs:u:vh?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'b':
+ burst_read = 1;
+ break;
+
+ case 'c':
+ loops = -1;
+ break;
+
+ case 'n':
+ loops = atoi( optarg );
+ break;
+
+ case 'r':
+ read_raw = 1;
+ break;
+
+ case 's':
+ sleep_secs = atoi( optarg );
+ break;
+
+ case 'u':
+ sleep_usecs = atoi( optarg );
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+
+ #if !MBG_PC_CYCLES_SUPPORTED
+ printf( "** Warning: No cycles support to compute real latencies on this platform!\n" );
+
+ if ( !read_raw )
+ {
+ read_raw = 1;
+ printf( "** Falling back to raw mode.\n" );
+ }
+
+ printf( "\n" );
+ #endif
+
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbghrtime );
+
+ return abs( rc );
+}
diff --git a/mbglib/common/cfg_hlp.h b/mbglib/common/cfg_hlp.h
new file mode 100644
index 0000000..a485d98
--- /dev/null
+++ b/mbglib/common/cfg_hlp.h
@@ -0,0 +1,127 @@
+
+/**************************************************************************
+ *
+ * $Id: cfg_hlp.h 1.2 2012/10/02 18:16:26Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for configuration programs.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: cfg_hlp.h $
+ * Revision 1.2 2012/10/02 18:16:26Z martin
+ * Modified some typedefs to be more compliant with the underlying types.
+ * Revision 1.1 2011/09/21 15:59:59 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _CFG_HLP_H
+#define _CFG_HLP_H
+
+
+/* Other headers to be included */
+
+#include <gpsdefs.h>
+
+
+#ifdef _CFG_HLP
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * The definitions and types below are used to collect
+ * all configuration parameters of a clock's serial ports
+ * that can be handled by this library:
+ */
+
+
+/*
+ * The maximum number of clocks' serial ports and string types
+ * that can be handled by the configuration programs.
+ * WARNING: Changing these constants affects the size of the
+ * structures ALL_PORT_INFO ALL_STR_TYPE_INFO
+ */
+#define MAX_PARM_PORT 4
+#define MAX_PARM_STR_TYPE 20
+
+typedef PORT_INFO_IDX ALL_PORT_INFO_IDX[MAX_PARM_PORT];
+typedef STR_TYPE_INFO_IDX ALL_STR_TYPE_INFO_IDX[MAX_PARM_STR_TYPE];
+
+typedef struct
+{
+ ALL_PORT_INFO_IDX pii;
+ ALL_STR_TYPE_INFO_IDX stii;
+ PORT_PARM tmp_pp;
+
+} RECEIVER_PORT_CFG;
+
+
+/*
+ * The definitions and types below are used to collect
+ * all configuration parameters of a clock's programmable
+ * pulse outputs that can be handled by this library:
+ */
+
+#define MAX_PARM_POUT 4
+
+#if 1 //##+++++++++++++++++++++++
+
+typedef POUT_INFO_IDX ALL_POUT_INFO_IDX[MAX_PARM_POUT];
+
+#else
+
+typedef struct
+{
+ POUT_INFO_IDX pii[MAX_PARM_POUT];
+} POUT_CFG;
+
+#endif
+
+
+/*
+ * The definitions and types below are used to collect
+ * all configuration parameters of PTP device's unicast
+ * master specification:
+ */
+
+#define MAX_PARM_PTP_UC_MASTER 3
+
+typedef PTP_UC_MASTER_INFO_IDX ALL_PTP_UC_MASTER_INFO_IDX[MAX_PARM_PTP_UC_MASTER];
+
+
+
+
+/* function prototypes: */
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _CFG_HLP_H */
diff --git a/mbglib/common/cnv_wday.h b/mbglib/common/cnv_wday.h
new file mode 100644
index 0000000..7736135
--- /dev/null
+++ b/mbglib/common/cnv_wday.h
@@ -0,0 +1,100 @@
+
+/***************************************************************************/
+/* */
+/* File: CNV_WDAY.H $Revision: 1.1 $ */
+/* */
+/* Project: Common C Library */
+/* */
+/* Compiler: Borland C++ and others */
+/* */
+/* Author: M. Burnicki, Meinberg Funkuhren */
+/* */
+/* */
+/* Description: */
+/* This header provides macros which can be used to convert */
+/* day-of-week codes from one convention to another. */
+/* */
+/* The conventions supported yet have been named as describrd below: */
+/* */
+/* name range assignment used with ... */
+/* ---------------------------------------------------------------- */
+/* sun06 0..6 0 = Sunday RTC72421, DOS1.10+, Novell */
+/* sun17 1..7 1 = Sunday RTC146818 */
+/* mon17 1..7 1 = Monday DCF77 */
+/* */
+/***************************************************************************/
+
+
+#ifndef _CNV_WDAY_H
+
+
+/* Other headers to be included */
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _CNV_WDAY
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+/* use the following macros if sure that the source value is in range */
+
+#define _wday_mon17_to_mon06( d ) ( ( d ) - 1 )
+#define _wday_mon06_to_mon17( d ) ( ( d ) + 1 )
+
+#define _wday_mon17_to_sun17( d ) ( ( (d) >= 7 ) ? 1 : ( (d) + 1 ) )
+#define _wday_sun17_to_mon17( d ) ( ( (d) < 2 ) ? 7 : ( (d) - 1 ) )
+
+#define _wday_mon17_to_sun06( d ) ( ( (d) >= 7 ) ? 0 : (d) )
+#define _wday_sun06_to_mon17( d ) ( ( (d) < 1 ) ? 7 : (d) )
+
+#define _wday_sun17_to_sun06( d ) ( (d) - 1 )
+#define _wday_sun06_to_sun17( d ) ( (d) + 1 )
+
+
+/* use the macros below to check for valid ranges */
+
+#define _inrng( d, what, min, lt, max, gt ) ( ( (d) < (min) ) ? (lt) : ( ( (d) > (max) ) ? (gt) : (what) ) )
+ /* _inrng is a local macro which does the boundary check */
+ /* d the day code to be converted */
+ /* what the conversion algorithm if in range */
+ /* min, lt if (d) is below (min), the macro returns (lt) */
+ /* max, gt if (d) is above (max), the macro returns (gt) */
+
+#define _wday_chk_mon17_to_sun17( d ) _inrng( (d), _wday_mon17_to_sun17( (d) ), 1, 7, 7, 6 )
+#define _wday_chk_sun17_to_mon17( d ) _inrng( (d), _wday_sun17_to_mon17( (d) ), 1, 7, 7, 6 )
+
+
+#define _wday_chk_mon17_to_sun06( d ) _inrng( (d), _wday_mon17_to_sun06( (d) ), 1, 1, 7, 0 )
+#define _wday_chk_sun06_to_mon17( d ) _inrng( (d), _wday_sun06_to_mon17( (d) ), 0, 1, 6, 6 )
+
+#define _wday_chk_sun17_to_sun06( d ) _inrng( (d), _wday_sun17_to_sun06( (d) ), 1, 0, 7, 6 )
+#define _wday_chk_sun06_to_sun17( d ) _inrng( (d), _wday_sun06_to_sun17( (d) ), 0, 1, 6, 7 )
+
+
+/* function prototypes: */
+
+/* #include <CNV_WDAY.hdr> not needed yet */
+
+/* End of header body */
+
+
+#undef _ext
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _CNV_WDAY_H
+
+#endif /* _CNV_WDAY_H */
+
diff --git a/mbglib/common/ctry.c b/mbglib/common/ctry.c
new file mode 100644
index 0000000..c726f22
--- /dev/null
+++ b/mbglib/common/ctry.c
@@ -0,0 +1,176 @@
+
+/**************************************************************************
+ *
+ * $Id: ctry.c 1.7 2010/07/15 08:26:57Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions providing support for different country settings
+ * and languages.
+ *
+ * Some OS dependent functions may be required which can be found
+ * in the OS dependent modules ctry_xxx.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: ctry.c $
+ * Revision 1.7 2010/07/15 08:26:57Z martin
+ * Added clstr_lng() implemented by stefan returning a translated string
+ * by giving the different strings as function arguments.
+ * Revision 1.6 2007/03/29 12:21:51 martin
+ * New functions lstr_idx() and lstr_array_idx().
+ * Revision 1.5 2004/10/26 07:39:37Z martin
+ * Use C99 fixed-size definitions where appropriate.
+ * Revision 1.4 2001/09/14 12:02:12 MARTIN
+ * Modified parameters for lstr_lng().
+ * Revision 1.3 2000/11/27 14:09:24 MARTIN
+ * Replaced lstr() by lstr_lng() with takes a language paramter to allow
+ * retrieval of strings for another than the current language.
+ * A new macro _lstr() has been added to ctry.h which calls lstr_lng()
+ * passing the current language.
+ * The functions ctry_fmt_dt() and ctry_fmt_times() and associated
+ * definitions have been moved to a new module ctry_fmt.c/ctry_fmt.h.
+ * Revision 1.2 2000/07/21 10:00:08 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _CTRY
+ #include <ctry.h>
+#undef _CTRY
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+// Return the index of a CLSTR component for a
+// certain language lng
+
+/*HDR*/
+int lstr_idx( CLSTR s, int lng )
+{
+ if ( lng >= N_LNG ) // if lng out of range
+ return 0; // use default index
+
+ // If there are duplicate strings for several languages
+ // then the duplicate strings may be NULL, in which case
+ // the string at index 0 must be used.
+ return s[lng] ? lng : 0;
+
+} // lstr_idx
+
+
+
+// Return the index of a CLSTR component for a
+// certain language lng out of an array of CLSTRs.
+// CLSTR s: the array of CLSTRs
+// int idx: the index of the array element
+// int n_lng: the number of supported languages
+// int lng: the language for which the inex shall be retrieved
+
+/*HDR*/
+int lstr_array_idx( CLSTR s, int idx, int n_lng, int lng )
+{
+ int str_idx = n_lng * idx;
+ return str_idx + lstr_idx( &s[str_idx], lng );
+
+} // lstr_array_idx
+
+
+
+/*HDR*/
+const char *lstr_lng( CLSTR s, int lng )
+{
+ return s[lstr_idx( s, lng)];
+
+} // lstr_lng
+
+
+
+/*HDR*/
+void ctry_setup( CTRY_CODE code )
+{
+ language = LNG_ENGLISH;
+ ctry.code = code;
+
+ switch ( code )
+ {
+ case CTRY_US:
+ ctry.dt_fmt = DT_FMT_MMDDYYYY;
+ ctry.dt_sep = DT_SEP_MINUS;
+ ctry.tm_fmt = TM_FMT_24H;
+ ctry.tm_sep = TM_SEP_COLON;
+ break;
+
+
+ case CTRY_UK:
+ ctry.dt_fmt = DT_FMT_DDMMYYYY;
+ ctry.dt_sep = DT_SEP_SLASH;
+ ctry.tm_fmt = TM_FMT_24H;
+ ctry.tm_sep = TM_SEP_COLON;
+ break;
+
+
+ default:
+ language = LNG_GERMAN;
+ ctry.code = CTRY_GERMANY;
+
+ ctry.dt_fmt = DT_FMT_DDMMYYYY;
+ ctry.dt_sep = DT_SEP_DOT;
+ ctry.tm_fmt = TM_FMT_24H;
+ ctry.tm_sep = TM_SEP_COLON;
+
+ } /* switch */
+
+
+} /* ctry_setup */
+
+
+
+/*HDR*/
+void ctry_next( void )
+{
+ switch ( ctry.code )
+ {
+ case CTRY_GERMANY:
+ ctry_setup( CTRY_US );
+ break;
+
+ case CTRY_US:
+ ctry_setup( CTRY_UK );
+ break;
+
+ default:
+ ctry_setup( CTRY_GERMANY );
+ break;
+
+ } // switch
+
+} // ctry_next
+
+
+
+/*HDR*/
+const char *clstr_lng( int index, ... )
+{
+ const char *ret;
+ const char *default_ret;
+ int i;
+ typedef char *MY_LSTR;
+
+ va_list ap;
+ va_start( ap, index );
+
+ ret = va_arg( ap, MY_LSTR );
+ default_ret = ret;
+
+ for ( i = 1; ( i <= index ) && ( ret != NULL ); i++ )
+ ret = va_arg( ap, MY_LSTR );
+
+ va_end( ap );
+
+ return ret ? ret : default_ret;
+
+} // clstr_lng
+
diff --git a/mbglib/common/ctry.h b/mbglib/common/ctry.h
new file mode 100644
index 0000000..f66b817
--- /dev/null
+++ b/mbglib/common/ctry.h
@@ -0,0 +1,239 @@
+
+/**************************************************************************
+ *
+ * $Id: ctry.h 1.13 2012/11/29 12:01:09Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for ctry.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: ctry.h $
+ * Revision 1.13 2012/11/29 12:01:09Z martin
+ * Don't include mbg_tgt.h explicitely since this will anyway be
+ * included by words.h for non-firmware targets. So mbg_tgt.h
+ * must not necessarily be added to firmware projects.
+ * Revision 1.12 2011/06/22 07:37:57Z martin
+ * Cleaned up handling of pragma pack().
+ * Revision 1.11 2010/07/15 08:33:41 martin
+ * Added some macros implemented by Stefan.
+ * Updated function prototypes.
+ * Revision 1.10 2007/03/29 12:21:10 martin
+ * Updated function prototypes.
+ * Revision 1.9 2004/10/26 07:38:50Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Updated function prototypes.
+ * Revision 1.8 2004/04/14 08:47:28 martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.7 2002/02/19 09:28:00Z MARTIN
+ * Use new header mbg_tgt.h to check the target environment.
+ * Revision 1.6 2001/09/14 12:04:40 MARTIN
+ * Modified definition for CLSTR.
+ * Updated function prototypes.
+ * Revision 1.5 2001/02/28 15:07:06 MARTIN
+ * Modified preprocessor syntax.
+ * Revision 1.4 2000/11/27 14:13:27 MARTIN
+ * New types CLSTR, PLSTR, and PCLSTR.
+ * New macro _lstr() calls lstr_lng() for the current language.
+ * Definitions associated with ctry_fmt_dt() and ctry_fmt_times()
+ * have been moved to a new file ctry_fmt.h.
+ * Updated function prototypes.
+ * Revision 1.3 2000/08/17 15:35:02 MARTIN
+ * No init function by default (previously DOS),
+ * Revision 1.2 2000/07/21 09:48:34 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _CTRY_H
+#define _CTRY_H
+
+
+/* Other headers to be included */
+
+#include <words.h>
+
+#if defined( MBG_TGT_NETWARE )
+ #include <ctry_nw.h>
+#elif defined( MBG_TGT_OS2 )
+ #include <ctry_os2.h>
+#elif defined( MBG_TGT_WIN32 )
+ // #include <ctry_w32.h>
+#elif defined( MBG_TGT_LINUX )
+ // #include <ctry_lx.h>
+#elif defined( MBG_TGT_DOS )
+ #include <ctry_dos.h>
+#else
+ // nothing to include for C166 etc.
+#endif
+
+#include <use_pack.h>
+
+
+#ifdef _CTRY
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// the definitions below are used to support different languages:
+typedef uint8_t LANGUAGE;
+typedef uint16_t CTRY_CODE;
+
+// codes used with LANGUAGE:
+#if !defined LNG_DEFINED
+ enum
+ {
+ LNG_ENGLISH,
+ LNG_GERMAN,
+ N_LNG
+ };
+
+ #define LNG_DEFINED
+#endif
+
+// the type below is used to declare string variables
+// for several languages
+typedef char *LSTR[N_LNG]; // array of strings
+typedef char **PLSTR; // pointer to array
+
+// same as above, but const
+typedef const char * const CLSTR[N_LNG]; // array of strings
+typedef const char * const *PCLSTR; // pointer to array
+
+
+// the definitions below are used to handle date and time
+// formats used by different countries:
+typedef struct
+{
+ CTRY_CODE code;
+
+ uint8_t dt_fmt; // (codes defined below)
+ uint8_t tm_fmt; // (codes defined below)
+ char dt_sep; // (valid chars defined below)
+ char tm_sep; // (valid chars defined below)
+} CTRY;
+
+
+// codes used with CTRY.code:
+#define CTRY_US 1
+#define CTRY_UK 44
+#define CTRY_GERMANY 49
+
+
+#ifndef CTRY_DEFINED
+
+ #define CTRY_DEFINED
+
+ // codes used with CTRY.dt_fmt:
+ enum
+ {
+ DT_FMT_DDMMYYYY,
+ DT_FMT_MMDDYYYY,
+ DT_FMT_YYYYMMDD,
+ N_DT_FMT
+ };
+
+ // codes used with CTRY.tm_fmt:
+ enum
+ {
+ TM_FMT_24H,
+ // TM_FMT_12H, // not yet supported
+ N_TM_FMT
+ };
+
+
+ // codes used with CTRY.dt_sep:
+ #define DT_SEP_DOT '.'
+ #define DT_SEP_MINUS '-'
+ #define DT_SEP_SLASH '/'
+
+ // a zero-terminated list of valid dt_sep characters
+ #define DT_SEP_LIST { DT_SEP_DOT, DT_SEP_MINUS, DT_SEP_SLASH, 0 }
+
+
+ // codes used with CTRY.tm_sep:
+ #define TM_SEP_COLON ':'
+ #define TM_SEP_DOT '.'
+
+ // a zero-terminated list of valid tm_sep characters
+ #define TM_SEP_LIST { TM_SEP_COLON, TM_SEP_DOT, 0 }
+
+#endif // CTRY_DEFINED
+
+
+extern LANGUAGE language;
+extern CTRY ctry;
+
+
+#define _ctry_init() \
+ ctry_setup( ctry_get_code() )
+
+
+#define _next_language() \
+{ \
+ if ( ++language >= N_LNG ) \
+ language = 0; \
+ \
+} // next_language
+
+
+// macro to call lstr_lng with the current language
+#define _lstr( _s ) lstr_lng( (_s), language )
+
+// macro to call clstr_lng with the current language, and a set of strings
+#define _clstr( _s ) clstr_lng( language, _s )
+
+// macros used in wxWidgets projects
+#if defined( __WXWINDOWS__ )
+ #define _wx_lstr( _s ) wxString::From8BitData( lstr_lng( (_s), language ) )
+ #define _wx_clstr( _s ) wxString::From8BitData( clstr_lng( language, _s ) )
+#endif
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ int lstr_idx( CLSTR s, int lng ) ;
+ int lstr_array_idx( CLSTR s, int idx, int n_lng, int lng ) ;
+ const char *lstr_lng( CLSTR s, int lng ) ;
+ void ctry_setup( CTRY_CODE code ) ;
+ void ctry_next( void ) ;
+ const char *clstr_lng( int index, ... ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+
+#undef _ext
+
+#endif /* _CTRY_H */
+
diff --git a/mbglib/common/ctrydttm.c b/mbglib/common/ctrydttm.c
new file mode 100644
index 0000000..d846ed8
--- /dev/null
+++ b/mbglib/common/ctrydttm.c
@@ -0,0 +1,184 @@
+
+/**************************************************************************
+ *
+ * $Id: ctrydttm.c 1.5 2008/11/24 16:15:46Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions converting dates and time into strings depending on
+ * language/country settings.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: ctrydttm.c $
+ * Revision 1.5 2008/11/24 16:15:46Z martin
+ * Don't use sprintf() without format string.
+ * Revision 1.4 2000/11/27 10:06:27 MARTIN
+ * Renamed local variable wday_str to lstrs_wday.
+ * If macro USER_LSTR_WDAY is defined, lstrs_wday can be declared
+ * externally to override the defaults.
+ * Revision 1.3 2000/09/14 15:13:25 MARTIN
+ * Renamed sprint_short_ctry_dt() to sprint_ctry_dt_short() to match
+ * other naming conventions.
+ * Revision 1.2 2000/07/21 11:53:42 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _CTRYDTTM
+ #include <ctrydttm.h>
+#undef _CTRYDTTM
+
+#include <ctry.h>
+
+#include <stdio.h>
+
+
+#ifndef DAYS_PER_WEEK
+ #define DAYS_PER_WEEK 7
+#endif
+
+#ifdef USER_LSTRS_WDAY
+ extern const char *lstrs_wday[N_LNG][DAYS_PER_WEEK];
+#else
+ static const char *lstrs_wday[N_LNG][DAYS_PER_WEEK] =
+ {
+ { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" },
+ { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" }
+ };
+#endif
+
+extern CTRY ctry;
+extern LANGUAGE language;
+
+
+/*HDR*/
+ushort sprint_02u( char *s, uchar uc )
+{
+ return( sprintf( s, "%02u", uc ) );
+
+} // sprint_02u
+
+
+
+/*HDR*/
+ushort sprint_04u( char *s, ushort us )
+{
+ return( sprintf( s, "%04u", us ) );
+
+} // sprint_04u
+
+
+
+/*HDR*/
+ushort sprint_ctry_wday( char *s, uchar wday, ushort language )
+{
+ if ( language >= N_LNG )
+ language = LNG_ENGLISH;
+
+ return( sprintf( s, "%s", ( wday < DAYS_PER_WEEK ) ?
+ lstrs_wday[language][wday] : "--" ) );
+
+} // sprint_ctry_wday
+
+
+
+/*HDR*/
+ushort sprint_ctry_dt_short( char *s, uchar mday, uchar month )
+{
+ uchar tmp_1;
+ uchar tmp_2;
+ ushort n = 0;
+
+
+ switch( ctry.dt_fmt )
+ {
+ case DT_FMT_YYYYMMDD:
+ case DT_FMT_MMDDYYYY:
+ tmp_1 = month;
+ tmp_2 = mday;
+ break;
+
+ default:
+ tmp_1 = mday;
+ tmp_2 = month;
+ break;
+
+ } // switch
+
+ n = sprint_02u( s, tmp_1 );
+ s[n++] = ctry.dt_sep;
+ n += sprint_02u( &s[n], tmp_2 );
+ s[n++] = ctry.dt_sep;
+ s[n] = 0;
+
+ return( n );
+
+} // sprint_ctry_dt_short
+
+
+
+/*HDR*/
+ushort sprint_ctry_dt( char *s, uchar mday, uchar month, ushort year )
+{
+ ushort n = 0;
+
+
+ if ( ctry.dt_fmt == DT_FMT_YYYYMMDD )
+ {
+ n = sprint_04u( s, year );
+ s[n++] = ctry.dt_sep;
+ }
+
+ n += sprint_ctry_dt_short( &s[n], mday, month );
+
+ if ( ctry.dt_fmt == DT_FMT_YYYYMMDD )
+ s[--n] = 0;
+ else
+ n += sprint_04u( &s[n], year );
+
+ return( n );
+
+} // sprint_ctry_dt
+
+
+
+/*HDR*/
+ushort sprint_ctry_tm_short( char *s, uchar hour, uchar minute )
+{
+ ushort n = sprint_02u( s, hour );
+ s[n++] = ctry.tm_sep;
+ n += sprint_02u( &s[n], minute );
+
+ return( n );
+
+} // sprint_ctry_tm_short
+
+
+
+/*HDR*/
+ushort sprint_ctry_tm( char *s, uchar hour, uchar minute, uchar second )
+{
+ ushort n = sprint_ctry_tm_short( s, hour, minute );
+ s[n++] = ctry.tm_sep;
+ n += sprint_02u( &s[n], second );
+
+ return( n );
+
+} // sprint_ctry_tm
+
+
+
+/*HDR*/
+ushort sprint_ctry_tm_long( char *s, uchar hour, uchar minute, uchar second,
+ long frac, ushort frac_digits )
+{
+ ushort n = sprint_ctry_tm( s, hour, minute, second );
+ s[n++] = '.';
+ n += sprintf( &s[n], "%0*lu", frac_digits, frac );
+
+ return( n );
+
+} // sprint_ctry_tm_long
+
+
diff --git a/mbglib/common/ctrydttm.h b/mbglib/common/ctrydttm.h
new file mode 100644
index 0000000..8032d89
--- /dev/null
+++ b/mbglib/common/ctrydttm.h
@@ -0,0 +1,74 @@
+
+/**************************************************************************
+ *
+ * $Id: ctrydttm.h 1.3 2000/09/14 15:13:45Z MARTIN REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for ctrydttm.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: ctrydttm.h $
+ * Revision 1.3 2000/09/14 15:13:45Z MARTIN
+ * Updated function prototypes.
+ * Revision 1.2 2000/07/21 11:50:43 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _CTRYDTTM_H
+#define _CTRYDTTM_H
+
+
+/* Other headers to be included */
+
+#include <ctry.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _CTRYDTTM
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+
+
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ ushort sprint_02u( char *s, uchar uc ) ;
+ ushort sprint_04u( char *s, ushort us ) ;
+ ushort sprint_ctry_wday( char *s, uchar wday, ushort language ) ;
+ ushort sprint_ctry_dt_short( char *s, uchar mday, uchar month ) ;
+ ushort sprint_ctry_dt( char *s, uchar mday, uchar month, ushort year ) ;
+ ushort sprint_ctry_tm_short( char *s, uchar hour, uchar minute ) ;
+ ushort sprint_ctry_tm( char *s, uchar hour, uchar minute, uchar second ) ;
+ ushort sprint_ctry_tm_long( char *s, uchar hour, uchar minute, uchar second, long frac, ushort frac_digits ) ;
+
+/* ----- function prototypes end ----- */
+
+/* End of header body */
+
+
+#undef _ext
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _CTRYDTTM_H */
+
diff --git a/mbglib/common/deviohlp.c b/mbglib/common/deviohlp.c
new file mode 100644
index 0000000..8de1a19
--- /dev/null
+++ b/mbglib/common/deviohlp.c
@@ -0,0 +1,322 @@
+
+/**************************************************************************
+ *
+ * $Id: deviohlp.c 1.2 2012/10/15 13:48:35Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Device configuration helper functions. This is an extension to
+ * mbgdevio.c providing useful functions to simplify reading/writing
+ * complex device configuration structure sets.
+ *
+ * Warning:
+ * These functions should not be implemented in a DLL / shared library
+ * since the parameter sizes might vary with different versions
+ * of the API calls, which which would make different versions of
+ * precompiled libraries incompatible to each other.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: deviohlp.c $
+ * Revision 1.2 2012/10/15 13:48:35Z martin
+ * Added functions mbg_get_all_ptp_cfg_info(), mbg_save_all_ptp_cfg_info().
+ * Revision 1.1.1.9 2012/07/18 11:00:46 martin
+ * Revision 1.1.1.8 2012/07/12 09:07:36Z martin
+ * Revision 1.1.1.7 2012/07/12 08:38:50Z martin
+ * Account for renamed structure.
+ * Revision 1.1.1.6 2012/07/10 09:53:57 martin
+ * Revision 1.1.1.5 2012/04/11 15:45:10Z martin
+ * Updated doxygen comments.
+ * Revision 1.1.1.4 2011/09/21 14:45:24 martin
+ * Moved mbgextio support functions to new module extiohlp.c.
+ * Revision 1.1.1.3 2011/09/20 15:36:02 marvin
+ * new functions:
+ * mbg_get_serial_settings
+ * mbg_set_serial_settings
+ * include mbgextio.h
+ * Revision 1.1.1.2 2011/08/05 10:30:28 martin
+ * Revision 1.1.1.1 2011/08/05 09:55:52 martin
+ * Revision 1.1 2011/08/03 15:37:00Z martin
+ * Initial revision with functions moved here from mbgdevio.
+ *
+ **************************************************************************/
+
+#define _DEVIOHLP
+ #include <deviohlp.h>
+#undef _DEVIOHLP
+
+#include <parmpcps.h>
+#include <parmgps.h>
+
+
+
+/*HDR*/
+/**
+ Read all serial port settings and supported configuration parameters.
+
+ The functions mbg_get_device_info() and mbg_setup_receiver_info()
+ must have been called before, and the returned ::PCPS_DEV and
+ ::RECEIVER_INFO structures must be passed to this function.
+
+ The complementary function mbg_save_serial_settings() should be used
+ to write the modified serial port configuration back to the board.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *pdev Pointer to a ::PCPS_DEV structure.
+ @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure to be filled up.
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_device_info()
+ @see mbg_setup_receiver_info()
+ @see mbg_save_serial_settings()
+*/
+int mbg_get_serial_settings( MBG_DEV_HANDLE dh,
+ const PCPS_DEV *pdev,
+ RECEIVER_PORT_CFG *pcfg,
+ const RECEIVER_INFO *p_ri )
+{
+ int rc;
+ int i;
+
+ memset( pcfg, 0, sizeof( *pcfg ) );
+
+ if ( _pcps_has_receiver_info( pdev ) )
+ {
+ rc = mbg_get_gps_all_port_info( dh, pcfg->pii, p_ri );
+ if ( rc != MBG_SUCCESS )
+ goto error;
+
+ rc = mbg_get_gps_all_str_type_info( dh, pcfg->stii, p_ri );
+ if ( rc != MBG_SUCCESS )
+ goto error;
+ }
+ else
+ {
+ if ( _pcps_is_gps( pdev ) )
+ {
+ rc = mbg_get_gps_port_parm( dh, &pcfg->tmp_pp );
+ if ( rc != MBG_SUCCESS )
+ goto error;
+
+ for ( i = 0; i < p_ri->n_com_ports; i++ )
+ {
+ PORT_INFO_IDX *p_pii = &pcfg->pii[i];
+ PORT_INFO *p_pi = &p_pii->port_info;
+
+ p_pii->idx = i;
+ port_settings_from_port_parm( &p_pi->port_settings,
+ i, &pcfg->tmp_pp, 1 );
+
+ p_pi->supp_baud_rates = DEFAULT_GPS_BAUD_RATES_C166;
+ p_pi->supp_framings = DEFAULT_GPS_FRAMINGS_C166;
+ p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_GPS;
+ }
+ }
+ else
+ if ( _pcps_has_serial ( pdev ) ) // Not all non-GPS clocks have a serial port!
+ {
+ PCPS_SERIAL ser_code;
+
+ rc = mbg_get_serial( dh, &ser_code );
+ if ( rc != MBG_SUCCESS )
+ goto error;
+
+
+ port_info_from_pcps_serial( pcfg->pii, ser_code,
+ _pcps_has_serial_hs( pdev ) ?
+ DEFAULT_BAUD_RATES_DCF_HS :
+ DEFAULT_BAUD_RATES_DCF
+ );
+ }
+
+ for ( i = 0; i < p_ri->n_str_type; i++ )
+ {
+ STR_TYPE_INFO_IDX *stip = &pcfg->stii[i];
+ stip->idx = i;
+ stip->str_type_info = default_str_type_info[i];
+ }
+ }
+
+ return MBG_SUCCESS;
+
+
+error:
+ return rc;
+
+} // mbg_get_serial_settings
+
+
+
+/*HDR*/
+/**
+ Write the configuration settings for a single serial port to the board.
+
+ Modifications to the serial port configuration should be made only
+ after mbg_get_serial_settings() had been called to read all serial port
+ settings and supported configuration parameters.
+ This function has finally to be called once for every serial port
+ the configuration of which has been modified.
+
+ As also required by mbg_get_serial_settings(), the functions
+ mbg_get_device_info() and mbg_setup_receiver_info() must have been
+ called before, and the returned ::PCPS_DEV and ::RECEIVER_INFO structures
+ must be passed to this function.
+
+ @param dh Valid handle to a Meinberg device
+ @param *pdev Pointer to a ::PCPS_DEV structure
+ @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure
+ @param port_num Index of the ::serial port to be saved
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_serial_settings()
+ @see mbg_get_device_info()
+ @see mbg_setup_receiver_info()
+*/
+int mbg_save_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev,
+ RECEIVER_PORT_CFG *pcfg, int port_num )
+{
+ int rc;
+
+ if ( _pcps_has_receiver_info( pdev ) )
+ {
+ rc = mbg_set_gps_port_settings( dh, &pcfg->pii[port_num].port_info.port_settings, port_num );
+ }
+ else
+ {
+ if ( _pcps_is_gps( pdev ) )
+ {
+ port_parm_from_port_settings( &pcfg->tmp_pp, port_num,
+ &pcfg->pii[port_num].port_info.port_settings, 1 );
+
+ rc = mbg_set_gps_port_parm( dh, &pcfg->tmp_pp );
+ }
+ else
+ {
+ PCPS_SERIAL ser_code;
+
+ pcps_serial_from_port_info( &ser_code, pcfg->pii );
+
+ rc = mbg_set_serial( dh, &ser_code );
+ }
+ }
+
+ return rc;
+
+} // mbg_save_serial_settings
+
+
+
+/*HDR*/
+/**
+ Read all PTP settings and supported configuration parameters.
+
+ The complementary function mbg_save_all_ptp_cfg_info() should
+ be used to write the modified configuration back to the device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::ALL_PTP_CFG_INFO structure.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_all_ptp_cfg_info()
+ @see mbg_get_ptp_cfg_info()
+ @see mbg_get_ptp_uc_master_cfg_limits()
+ @see mbg_get_all_ptp_uc_master_info()
+ @see mbg_dev_has_ptp()
+ @see mbg_dev_has_ptp_unicast()
+*/
+int mbg_get_all_ptp_cfg_info( MBG_DEV_HANDLE dh, ALL_PTP_CFG_INFO *p )
+{
+ int rc = MBG_SUCCESS;
+
+ memset( p, 0, sizeof( *p ) );
+
+ rc = mbg_get_ptp_cfg_info( dh, &p->ptp_cfg_info );
+
+ if ( rc < 0 )
+ return rc;
+
+ if ( p->ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST )
+ {
+ rc = mbg_get_ptp_uc_master_cfg_limits( dh, &p->ptp_uc_master_cfg_limits );
+
+ if ( rc < 0 )
+ return rc;
+
+ if ( p->ptp_uc_master_cfg_limits.n_supp_master > MAX_PARM_PTP_UC_MASTER )
+ {
+ // The number of PTP unicast masters supported by this device
+ // exceeds the number of unicast masters supporterd by this driver.
+ return MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP;
+ }
+
+ rc = mbg_get_all_ptp_uc_master_info( dh, p->all_ptp_uc_master_info_idx,
+ &p->ptp_uc_master_cfg_limits );
+ if ( rc < 0 )
+ return rc;
+ }
+
+ return MBG_SUCCESS;
+
+} // mbg_get_all_ptp_cfg_info
+
+
+
+/*HDR*/
+/**
+ Write all PTP settings and supported configuration parameters
+ to a device.
+
+ The complementary function mbg_get_all_ptp_cfg_info() should
+ have been used to read the original PTP settings and supported
+ configuration parameters.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::ALL_PTP_CFG_INFO structure.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_all_ptp_cfg_info()
+ @see mbg_set_ptp_cfg_settings()
+ @see mbg_set_ptp_uc_master_settings_idx()
+ @see mbg_dev_has_ptp()
+ @see mbg_dev_has_ptp_unicast()
+*/
+int mbg_save_all_ptp_cfg_info( MBG_DEV_HANDLE dh, const ALL_PTP_CFG_INFO *p )
+{
+ int rc = MBG_SUCCESS;
+
+ rc = mbg_set_ptp_cfg_settings( dh, &p->ptp_cfg_info.settings );
+
+ if ( rc < 0 )
+ return rc;
+
+
+ if ( p->ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST )
+ {
+ int i;
+
+ for ( i = 0; i < p->ptp_uc_master_cfg_limits.n_supp_master; i++ )
+ {
+ PTP_UC_MASTER_SETTINGS_IDX s;
+
+ memset( &s, 0, sizeof( s ) );
+
+ s.idx = i;
+ s.settings = p->all_ptp_uc_master_info_idx[i].info.settings;
+
+ rc = mbg_set_ptp_uc_master_settings_idx( dh, &s );
+
+ if ( rc < 0 )
+ return rc;
+ }
+ }
+
+ return MBG_SUCCESS;
+
+} // mbg_save_all_ptp_cfg_info
+
+
diff --git a/mbglib/common/deviohlp.h b/mbglib/common/deviohlp.h
new file mode 100644
index 0000000..f6ed431
--- /dev/null
+++ b/mbglib/common/deviohlp.h
@@ -0,0 +1,168 @@
+
+/**************************************************************************
+ *
+ * $Id: deviohlp.h 1.2 2012/10/15 13:51:18Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for deviohlp.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: deviohlp.h $
+ * Revision 1.2 2012/10/15 13:51:18Z martin
+ * Include cfg_hlp.h.
+ * Added structure ALL_PTP_CFG_INFO.
+ * Updated function prototypes.
+ * Revision 1.1 2011/08/03 15:36:44Z martin
+ * Initial revision with functions moved here from mbgdevio.
+ *
+ **************************************************************************/
+
+#ifndef _DEVIOHLP_H
+#define _DEVIOHLP_H
+
+
+/* Other headers to be included */
+
+#include <mbgdevio.h>
+#include <cfg_hlp.h>
+
+
+#ifdef _DEVIOHLP
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct
+{
+ PTP_CFG_INFO ptp_cfg_info;
+ PTP_UC_MASTER_CFG_LIMITS ptp_uc_master_cfg_limits;
+ ALL_PTP_UC_MASTER_INFO_IDX all_ptp_uc_master_info_idx;
+
+} ALL_PTP_CFG_INFO;
+
+
+
+/* function prototypes: */
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ /**
+ Read all serial port settings and supported configuration parameters.
+
+ The functions mbg_get_device_info() and mbg_setup_receiver_info()
+ must have been called before, and the returned ::PCPS_DEV and
+ ::RECEIVER_INFO structures must be passed to this function.
+
+ The complementary function mbg_save_serial_settings() should be used
+ to write the modified serial port configuration back to the board.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *pdev Pointer to a ::PCPS_DEV structure.
+ @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure to be filled up.
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_device_info()
+ @see mbg_setup_receiver_info()
+ @see mbg_save_serial_settings()
+*/
+ int mbg_get_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_PORT_CFG *pcfg, const RECEIVER_INFO *p_ri ) ;
+
+ /**
+ Write the configuration settings for a single serial port to the board.
+
+ Modifications to the serial port configuration should be made only
+ after mbg_get_serial_settings() had been called to read all serial port
+ settings and supported configuration parameters.
+ This function has finally to be called once for every serial port
+ the configuration of which has been modified.
+
+ As also required by mbg_get_serial_settings(), the functions
+ mbg_get_device_info() and mbg_setup_receiver_info() must have been
+ called before, and the returned ::PCPS_DEV and ::RECEIVER_INFO structures
+ must be passed to this function.
+
+ @param dh Valid handle to a Meinberg device
+ @param *pdev Pointer to a ::PCPS_DEV structure
+ @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure
+ @param port_num Index of the ::serial port to be saved
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_serial_settings()
+ @see mbg_get_device_info()
+ @see mbg_setup_receiver_info()
+*/
+ int mbg_save_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_PORT_CFG *pcfg, int port_num ) ;
+
+ /**
+ Read all PTP settings and supported configuration parameters.
+
+ The complementary function mbg_save_all_ptp_cfg_info() should
+ be used to write the modified configuration back to the device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::ALL_PTP_CFG_INFO structure.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_all_ptp_cfg_info()
+ @see mbg_get_ptp_cfg_info()
+ @see mbg_get_ptp_uc_master_cfg_limits()
+ @see mbg_get_all_ptp_uc_master_info()
+ @see mbg_dev_has_ptp()
+ @see mbg_dev_has_ptp_unicast()
+*/
+ int mbg_get_all_ptp_cfg_info( MBG_DEV_HANDLE dh, ALL_PTP_CFG_INFO *p ) ;
+
+ /**
+ Write all PTP settings and supported configuration parameters
+ to a device.
+
+ The complementary function mbg_get_all_ptp_cfg_info() should
+ have been used to read the original PTP settings and supported
+ configuration parameters.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::ALL_PTP_CFG_INFO structure.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_all_ptp_cfg_info()
+ @see mbg_set_ptp_cfg_settings()
+ @see mbg_set_ptp_uc_master_settings_idx()
+ @see mbg_dev_has_ptp()
+ @see mbg_dev_has_ptp_unicast()
+*/
+ int mbg_save_all_ptp_cfg_info( MBG_DEV_HANDLE dh, const ALL_PTP_CFG_INFO *p ) ;
+
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _DEVIOHLP_H */
diff --git a/mbglib/common/gpsdefs.h b/mbglib/common/gpsdefs.h
new file mode 100644
index 0000000..25eff0f
--- /dev/null
+++ b/mbglib/common/gpsdefs.h
@@ -0,0 +1,6801 @@
+
+/**************************************************************************
+ *
+ * $Id: gpsdefs.h 1.113 2013/04/04 09:02:01Z martin REL_M Gregoire $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * General definitions to be used with Meinberg clocks.
+ * These definitions have initially be used with GPS devices only.
+ * However, more and more Meinberg non-GPS devices also use some of
+ * these definitions.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: gpsdefs.h $
+ * Revision 1.113 2013/04/04 09:02:01Z martin
+ * Added definitions to support HaveQuick.
+ * Fixed a typo.
+ * Revision 1.112 2013/02/19 15:39:13 martin
+ * New PTP settings field ann_rcpt_timeout and associated
+ * values PTP_ANN_RCPT_TIMEOUT_LIMITS.
+ * Changed many defines to named enums to simplify references
+ * with doxygen.
+ * Updated doxygen comments.
+ * Revision 1.111 2013/02/01 15:37:36 martin
+ * Added and modified a huge number of doxygen comments.
+ * Revision 1.110 2013/01/16 15:23:25 martin
+ * Fixed 2 comments which were interchanged.
+ * Revision 1.109 2013/01/11 10:39:34 martin
+ * Added definitions for IMS.
+ * Support XMR_HOLDOVER_INTV.
+ * New XMRS status bit XMRS_BIT_LOW_JITTER / XMRS_MSK_LOW_JITTER.
+ * Added framing type 8E2, though most UARTs don't support this.
+ * Added enum names and updated comments for doxygen.
+ * Revision 1.108 2012/10/30 11:31:16 martin
+ * Defined PTP_UC_MSG_DURATION_MIN and PTP_UC_MSG_DURATION_MAX.
+ * Fixed some doxygen comments.
+ * Changes by andre: changed reserved field to ssm and boc in BITS_OUT settings.
+ * Revision 1.107 2012/10/12 07:40:12 martin
+ * New PTP state flags PTP_FLAG_MSK_UTC_VALID and
+ * PTP_CFG_MSK_SUPP_UTC_VALID.
+ * Revision 1.106 2012/10/02 18:22:10 martin
+ * Added default baud rate and framing for binary protocol.
+ * Added definitions for IRIG codes E002/E112 and NASA36.
+ * Reworked GPIO structures.
+ * Added definitions for GRC, LIU, DCF600RS, and DCF600HS.
+ * New flag POUT_FIXED_PULSE_LEN.
+ * New flag POUT_NOT_INVERTIBLE.
+ * Unified capitalization in MBG_XMRS_STATUS_STRS.
+ * Revision 1.105 2012/06/01 16:31:16 martin
+ * Some TIME_SLOT definitions added by marvin.
+ * Moved some PTP configuration defaults and limits to ptpdflts.h.
+ * Revision 1.104 2012/04/11 16:02:55Z martin
+ * Fixed some doxygen comments.
+ * Revision 1.103 2012/04/02 11:08:57Z martin
+ * Extended description of GPS UTC/leap second data.
+ * Revision 1.102 2012/03/16 11:43:31 martin
+ * Fixed a potential compiler warning.
+ * Revision 1.101 2012/03/06 16:56:01Z martin
+ * Added support for PTP multicast auto role.
+ * Merged Daniel's definitions for PTP profile support.
+ * Support time slot mode for programmable pulse outputs.
+ * Support LNO180.
+ * Moved definition of MBG_MAC_ADDR here.
+ * Use MBG_MAC_ADDR in definition of LAN_IF_INFO.
+ * Revision 1.100 2012/01/17 13:33:55 martin
+ * Added new IRIG RX delay compensation code groups for G0xx and G1xx codes.
+ * As a consequence the value of N_IRIG_RX_COMP has changed.
+ * Added definition of IRIG_RX_COMP_MAX.
+ * Updated IRIG code classification macros.
+ * Removed obsolete/unused definition of CAL_REC_INFO.
+ * Added some comments.
+ * Revision 1.99 2011/12/09 09:22:03 martin
+ * Fixed a typo.
+ * Revision 1.98 2011/11/25 14:58:34 martin
+ * Renamed some evt_log definitions.
+ * Revision 1.97 2011/11/25 10:11:17 martin
+ * Initializers for XMRS status bit strings added by gregoire.
+ * New feature GPS_FEAT_EVT_LOG.
+ * Added definitions used with event logs.
+ * Moved cal_reg and gen_io stuff here.
+ * Added macro _mbg_swab_debug_status().
+ * Updated some comments.
+ * Revision 1.96 2011/10/11 13:40:46Z andre
+ * changed reserved field into slot_id in XMULTI_REF_INSTANCES
+ * Revision 1.95.1.1 2011/10/07 09:31:58Z andre
+ * Revision 1.95 2011/10/04 09:35:41Z martin
+ * Added support for ESI180.
+ * Changed RECEIVER_INFO::flags bit GPS_10MHZ_DISBD to a RECEIVER_INFO::features bit.
+ * Support MULTI_REF_INTERNAL, MULTI_REF_LWR and MULTI_REF_PZF.
+ * Added MBG_GPIO_BITS structure and associated definitions.
+ * Revision 1.94 2011/08/25 07:42:43Z martin
+ * Fixed a bug in macro _mbg_swab_pout_settings() where the 16 bit timeout
+ * field was swapped using a macro for 32 bit types.
+ * Use shorter names for some PTP unicast master default values.
+ * Revision 1.93 2011/08/10 08:19:38Z martin
+ * New PORT_INFO and PORT_SETTINGS flag PORT_FLAG_PORT_INVISIBLE.
+ * Revision 1.92 2011/07/29 09:49:35 martin
+ * Support PZF180PEX, MGR180, MSF600, WWVB600, JJY600,
+ * GPS180HS, and GPS180AMC.
+ * Added receiver info features GPS_FEAT_PTP_UNICAST
+ * and GPS_FEAT_XMRS_MULT_INSTC.
+ * Added receiver info flag bit GPS_10MHZ_DISBD.
+ * Added initializers for PTP timescale names.
+ * New PTP_STATE flags bit PTP_FLAG_MSK_IS_UNICAST.
+ * Made unused PTP_STATE fields num_clients and num_masters reserved.
+ * Account for different PTP roles.
+ * Added / renamed some definitions for PTP.
+ * Modified default string for PTP layer 2 protocol.
+ * Support PTP unicast configuration.
+ * Support GPIO configuration.
+ * Introduced XMULTI_REF_INSTANCES.
+ * Moved flags XMRS_..._IS_EXTERNAL and XMRS_..._INSTC_EXCEEDED
+ * to definitions for XMULTI_REF_STATUS::status.
+ * Some comments added, updated, and converted to doxygen style.
+ * Cleaned up handling of pragma pack().
+ * Removed trailing whitespace and hard tabs.
+ * Revision 1.91 2011/01/31 11:23:56Z martin
+ * Added model type name definitions for GPS180PEX and TCR180PEX.
+ * Introduced synthesizer mode for programmable outputs.
+ * Added IRIG-RX code TXC-101 DTR-6.
+ * Fixed missing comma bugs in DEFAULT_GPS_MODEL_NAMES.
+ * Fixed missing comma bugs in some IRIG string initializers.
+ * Fixed AFNOR notation.
+ * Modified some comments for doxygen.
+ * Revision 1.90 2010/10/15 11:47:53 martin
+ * Added definitions POUT_TIMEBASE_UTC and POUT_SUPP_DCF77_UTC.
+ * Added receiver info feature GPS_FEAT_RAW_IRIG_TIME.
+ * Support IRIG format C37.118.
+ * Added initializers for short IRIG code names.
+ * Cleaned up IRIG definitions and comments.
+ * Revision 1.89 2010/09/06 07:40:02Z martin
+ * Picked up Daniel's definitions for multi GNSS support.
+ * Moved MBG_IRIG_CTRL_BITS, MBG_RAW_IRIG_DATA and related definitions
+ * from pcpsdefs.h here.
+ * Added macros _pcps_tfom_from_irig_ctrl_bits()
+ * and _pcps_tfom_from_raw_irig_data().
+ * Added RI_FEATURES type.
+ * Revision 1.88 2010/04/21 13:47:54 daniel
+ * Added support for new model GLN170.
+ * Revision 1.87 2010/03/10 11:29:37Z martin
+ * Added definitions for GPS180.
+ * Added multiref source 1 PPS plus associated string.
+ * Revision 1.86 2010/02/17 14:16:42 martin
+ * Added definitions for PZF600 and TCR600.
+ * Revision 1.85 2010/02/15 11:34:36 martin
+ * Changed definition of PTP_TABLE::name to const char *.
+ * Added definitions to support new model JJY511.
+ * Revision 1.84 2010/02/01 13:20:50 martin
+ * Support programmable outputs being disabled when sync. is lost.
+ * Revision 1.83 2010/01/28 09:15:50 martin
+ * Added new POUT mode DCF77_M59 and associated definitions.
+ * Revision 1.82 2010/01/07 09:04:55 martin
+ * Added XMR status bit XMRS_BIT_NOT_PHASE_LOCKED.
+ * Revision 1.81 2009/11/09 09:08:24 martin
+ * New TM_GPS status bit TM_INVT.
+ * Added definitions to support VLAN.
+ * Changed DEFAULT_PTP_DELAY_MECH_MASK to include also
+ * PTP_DELAY_MECH_MSK_P2P.
+ * There is now only one type of TCXO supported which matches the former
+ * TCXO HQ, so the default name for TCXO HQ has been changed to TCXO.
+ * TCXO LQ and MQ names are still supported for backward compatibility.
+ * Revision 1.80 2009/09/28 14:55:53 martin
+ * Support IRIG formats G002/G142 and G006/G146.
+ * Modified IRIG format description strings.
+ * Revision 1.79 2009/08/12 14:12:38 daniel
+ * Added definitions to support new model MGR170.
+ * Added definitions and commands to support configuration
+ * of navigation engine (currently supported by u-blox
+ * receivers only).
+ * Renamed simulation values in PTP_SETTINGS to reserved.
+ * Added "UNINITIALIZED" to PTP port state.
+ * Removed obsolete braces in initializer.
+ * Revision 1.78 2009/06/25 15:49:05Z martin
+ * Added macro _nano_time_negative().
+ * Revision 1.77 2009/06/08 19:22:32Z daniel
+ * Added feature GPS_HAS_PTP.
+ * Added preliminary structures and definitions for PTP
+ * configuration and state.
+ * Added IP4_ADDR type.
+ * Added Bitmask IP4_MSK_DHCP.
+ * Added byte swapper macros for LAN and PTP structures.
+ * Moved LAN interface configuration definitions here.
+ * Moved DAC_VAL definition here.
+ * Changed type iof FPGA_INFO::start_addr for non-firmware applications.
+ * Revision 1.76 2009/04/08 08:26:56 daniel
+ * Added feature GPS_FEAT_IRIG_CTRL_BITS.
+ * Revision 1.75 2009/03/19 14:06:39Z martin
+ * Modified string initializer for unknown oscillator type.
+ * Revision 1.74 2009/03/18 13:45:53 daniel
+ * Added missing commas in
+ * MBG_DEBUG_STATUS_STRS initializer.
+ * Adjusted some comments for doxygen parser.
+ * Revision 1.73 2009/03/10 16:55:33Z martin
+ * Support configurable time scales GPS and TAI.
+ * Defined extended TM status type and associated flags.
+ * Added definition TM_MSK_TIME_VALID.
+ * Added some macros to swap endianess of structures.
+ * Revision 1.72 2008/11/28 09:26:21Z daniel
+ * Added definitions to support WWVB511
+ * Revision 1.71 2008/10/31 14:31:44Z martin
+ * Added definitions for TCR170PEX.
+ * Revision 1.70 2008/09/18 11:14:39 martin
+ * Added definitions to support GEN170.
+ * Revision 1.69 2008/09/15 14:16:17 martin
+ * Added more macros to convert the endianess of structures.
+ * Added N_COM_HS to the enumeration of handshake modes.
+ * Added MBG_PS_... codes.
+ * Revision 1.68 2008/08/25 10:51:13 martin
+ * Added definitions for PTP270PEX and FRC511PEX.
+ * Revision 1.67 2008/07/17 08:54:52Z martin
+ * Added macros to convert the endianess of structures.
+ * Added multiref fixed frequency source.
+ * Revision 1.66 2008/05/19 14:49:07 daniel
+ * Renamed s_addr to start_addr in FPGA_INFO.
+ * Revision 1.65 2008/05/19 09:00:01Z martin
+ * Added definitions for GPS162.
+ * Added FPGA_INFO and GPS_HAS_FPGA.
+ * Added FPGA_START_INFO and associated definitions.
+ * Added new XMRS status XMRS_..._NOT_SETTLED.
+ * Added initializer XMULTI_REF_STATUS_INVALID.
+ * Revision 1.64 2008/01/17 11:50:33Z daniel
+ * Made IGNORE_LOCK bit maskable.
+ * Revision 1.63 2008/01/17 11:42:09Z daniel
+ * Made comments compatible for Doxygen parser.
+ * No sourcecode changes.
+ * Revision 1.62 2007/11/15 13:23:33Z martin
+ * Decide whether other Meinberg headers are to be included depending on whether
+ * CLOCK_MEINBERG is defined (as with NTP) or not. Previous versions checked
+ * for "PACKAGE" which is also defined by the Borland C++ build environment, though.
+ * Revision 1.61 2007/11/13 13:28:54 daniel
+ * Added definitions to support GPS170PEX.
+ * Revision 1.60 2007/09/13 12:37:35Z martin
+ * Modified and added initializers for TZDL.
+ * Added multiref source PTP over E1.
+ * Added codes for MSF511 and GRC170 devices.
+ * Modified XMULTI_REF_SETTINGS and XMULTI_REF_STATUS structures.
+ * Avoid inclusion of other Meinberg headers in non-Meinberg projects.
+ * Added device classification macros _mbg_rcvr_is_...().
+ * Modified feature name string initializer for non-GPS devices.
+ * Updated some comments.
+ * Removed some obsolete comments.
+ * Revision 1.59 2007/07/19 07:41:56Z martin
+ * Added symbol MBG_REF_OFFS_NOT_CFGD.
+ * Revision 1.58 2007/05/21 15:46:44Z martin
+ * Fixed a typo.
+ * Revision 1.57 2007/03/29 12:20:43 martin
+ * Fixed some TZDL initializers.
+ * Revision 1.56 2007/02/14 14:17:10Z andre
+ * bug fixed in mask XMRS_MSK_NO_CONN
+ * Revision 1.55 2007/02/06 16:23:18Z martin
+ * Added definitions for AM511.
+ * Made SVNO unsigned.
+ * Added support for OPT_SETTINGS.
+ * Added XMULTI_REF_... definitions.
+ * Added string initializer DEFAULT_FREQ_RANGES.
+ * Revision 1.54 2007/01/04 11:39:39Z martin
+ * Added definitions for TCR511.
+ * Added definition GPS_FEAT_5_MHZ.
+ * Updated some comments related to duplicate features/options
+ * IGNORE_LOCK and EMU_SYNC.
+ * Revision 1.53 2006/12/13 09:31:49 martin
+ * Added feature flag for ignore_lock.
+ * Revision 1.52 2006/12/12 15:47:18 martin
+ * Added MBG_DEBUG_STATUS type and associated definitions.
+ * Added definition GPS_HAS_REF_OFFS.
+ * Moved PCPS_REF_OFFS and associated definitions from pcpsdefs.h here
+ * and renamed them to MBG_REF_OFFS, etc.
+ * Revision 1.51 2006/10/23 15:31:27 martin
+ * Added definitions for GPS170.
+ * Added definitions for new multi_ref sources IRIG, NTP, and PTP.
+ * Added some definitions useful when editing synth frequency.
+ * Revision 1.50 2006/08/25 09:29:28Z martin
+ * Added structure NANO_TIME.
+ * Revision 1.49 2006/08/09 07:06:42Z martin
+ * New TM_GPS status flag TM_EXT_SYNC.
+ * Revision 1.48 2006/08/08 12:51:20Z martin
+ * Added definitions for IRIG codes B006/B126 and B007/B127.
+ * Revision 1.47 2006/07/06 08:41:45Z martin
+ * Added definition of MEINBERG_MAGIC.
+ * Revision 1.46 2006/06/21 14:08:53Z martin
+ * Added masks of IRIG codes which contain time zone information.
+ * Revision 1.45 2006/06/15 12:13:32Z martin
+ * Added MULTI_REF_STATUS and associated flags.
+ * Added ROM_CSUM, RCV_TIMEOUT, and IGNORE_LOCK types.
+ * Revision 1.44 2006/05/18 09:34:41Z martin
+ * Added definitions for POUT max. pulse_len and max timeout.
+ * Changed comment for POUT_SETTINGS::timeout.
+ * Units are minutes, not seconds.
+ * Added definition for MAX_POUT_TIME_STR_PORTS.
+ * Added definitions for POUT mode 10MHz.
+ * Added hint strings for POUT modes.
+ * Added definitions for PZF511.
+ * Revision 1.43 2006/01/24 07:53:29Z martin
+ * New TM_GPS status flag TM_HOLDOVER.
+ * Revision 1.42 2005/11/24 14:53:22Z martin
+ * Added definitions for manchester encoded DC IRIG frames.
+ * Added POUT_TIMESTR and related definitions.
+ * Revision 1.41 2005/11/03 15:06:59Z martin
+ * Added definitions to support GPS170PCI.
+ * Revision 1.40 2005/10/28 08:58:29Z martin
+ * Added definitions for OCXO_DHQ.
+ * Revision 1.39 2005/09/08 14:06:00Z martin
+ * Added definition SYNTH_PHASE_SYNC_LIMIT.
+ * Revision 1.38 2005/08/18 10:27:35 andre
+ * added definitions for GPS164,
+ * added POUT_TIMECODE,
+ * struct SCU_STAT changed,
+ * ulong flags changed into two byte clk_info and ushort flags
+ * Revision 1.37 2005/05/02 14:44:55Z martin
+ * Added structure SYNTH_STATE and associated definitions.
+ * Revision 1.36 2005/03/29 12:44:07Z martin
+ * New RECEIVER_INFO::flags code: GPS_IRIG_FO_IN
+ * Revision 1.35 2004/12/09 14:04:38Z martin
+ * Changed max synth freq from 12 MHz to 10 MHz.
+ * Revision 1.34 2004/11/23 16:20:09Z martin
+ * Added bit definitions for the existing TTM status bit masks.
+ * Revision 1.33 2004/11/09 12:39:59Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Added model code and name for TCR167PCI.
+ * New type GPS_CMD.
+ * Defined type BVAR_STAT and associated flags.
+ * Revision 1.32 2004/09/20 12:46:25 andre
+ * Added structures and definitions for SCU board.
+ * Revision 1.31 2004/07/08 08:30:36Z martin
+ * Added feature GPS_FEAT_RCV_TIMEOUT.
+ * Revision 1.30 2004/06/21 13:38:42 martin
+ * New flag MBG_OPT_BIT_EMU_SYNC/MBG_OPT_FLAG_EMU_SYNC
+ * lets the receicer emulate/pretend to be always synchronized.
+ * Revision 1.30 2004/06/21 13:35:46Z martin
+ * Revision 1.29 2004/06/16 12:47:53Z martin
+ * Moved OPT_SETTINGS related definitions from pcpsdefs.h
+ * here and renamed symbols from PCPS_.. to to MBG_...
+ * Revision 1.28 2004/03/26 10:37:00Z martin
+ * Added definitions to support multiple ref sources.
+ * Added definitions OSC_DAC_RANGE, OSC_DAC_BIAS.
+ * Revision 1.27 2004/03/08 14:06:45Z martin
+ * New model code and name for GPS169PCI.
+ * Existing feature GPS_FEAT_IRIG has been
+ * renamed to GPS_FEAT_IRIG_TX.
+ * Added feature GPS_FEAT_IRIG_RX.
+ * Added IPv4 LAN interface feature flags.
+ * Renamed IFLAGS_IGNORE_TFOM to IFLAGS_DISABLE_TFOM.
+ * Revision 1.26 2003/12/05 12:28:20Z martin
+ * Added some codes used with IRIG cfg.
+ * Revision 1.25 2003/10/29 16:18:14Z martin
+ * Added 7N2 to DEFAULT_GPS_FRAMINGS_GP2021.
+ * Revision 1.24 2003/09/30 08:49:48Z martin
+ * New flag TM_LS_ANN_NEG which is set in addition to
+ * TM_LS_ANN if next leap second is negative.
+ * Revision 1.23 2003/08/26 14:32:33Z martin
+ * Added some initializers for commonly used
+ * TZDL configurations.
+ * Revision 1.22 2003/04/25 10:18:11 martin
+ * Fixed typo inside an IRIG name string initializer.
+ * Revision 1.21 2003/04/15 09:18:48 martin
+ * New typedef ANT_CABLE_LEN.
+ * Revision 1.20 2003/04/03 11:03:44Z martin
+ * Extended definitions for IRIG support.
+ * Revision 1.19 2003/01/31 13:38:20 MARTIN
+ * Modified type of RECEIVER_INFO::fixed_freq field.
+ * Revision 1.18 2002/10/28 09:24:07 MARTIN
+ * Added/renamed some POUT related symbols.
+ * Revision 1.17 2002/09/05 10:58:39 MARTIN
+ * Renamed some symbols related to programmable outputs.
+ * Revision 1.16 2002/08/29 08:04:47 martin
+ * Renamed structure POUT_PROG to POUT_SETTINGS.
+ * New structures POUT_SETTINGS_IDX, POUT_INFO,
+ * POUT_INFO_IDX and associated definitions.
+ * Updated some comments.
+ * Revision 1.15 2002/07/17 07:39:39Z Andre
+ * comma added in definition DEFAULT_GPS_OSC_NAMES
+ * Revision 1.14 2002/06/27 12:17:29Z MARTIN
+ * Added new oscillator code TCXO_MQ.
+ * Added initializer for oscillator names.
+ * Added initializer for oscillator list ordered by quality.
+ * Revision 1.13 2002/05/08 08:16:03 MARTIN
+ * Added GPS_OSC_CFG_SUPP for RECEIVER_INFO::flags.
+ * Fixed some comments.
+ * Revision 1.12 2002/03/14 13:45:56 MARTIN
+ * Changed type CSUM from short to ushort.
+ * Revision 1.11 2002/03/01 12:29:30 Andre
+ * Added GPS_MODEL_GPS161 and GPS_MODEL_NAME_GPS161.
+ * Revision 1.10 2002/02/25 08:02:33Z MARTIN
+ * Added array of chars to union IDENT.
+ * Revision 1.9 2002/01/29 15:21:46 MARTIN
+ * Added new field "reserved" to struct SW_REV to fix C166 data
+ * alignment/structure size. Converted structure IDENT to a union.
+ * The changes above should not affect existing monitoring programs.
+ * New status flag TM_ANT_SHORT.
+ * New structure RECEIVER_INFO and associated definitions to
+ * enhance control from monitoring programs.
+ * New structures PORT_INFO, STR_TYPE_INFO, and associated
+ * definitions to simplify and unify configuration from external programs.
+ * New structures IRIG_INFO and POUT_PROG_IDX to configure an
+ * optional IRIG interface and programmable pulse outputs.
+ * Modified some comments.
+ * Revision 1.8 2001/03/30 11:44:11 MARTIN
+ * Control alignment of structures from new file use_pack.h.
+ * Defined initializers with valid baud rate and framing parameters.
+ * Modified some comments.
+ * Revision 1.7 2001/03/01 08:09:22 MARTIN
+ * Modified preprocessor syntax.
+ * Revision 1.6 2000/07/21 14:04:33 MARTIN
+ * Added som #if directives to protect structures against being multiply
+ * defined.
+ * Modified some comments.
+ * Comments using characters for +/- and degree now include ASCII
+ * characters only.
+ *
+ **************************************************************************/
+
+#ifndef _GPSDEFS_H
+#define _GPSDEFS_H
+
+
+/* Other headers to be included */
+
+#if defined( HAVE_CONFIG_H )
+ // this is mainly to simplify usage in non-Meinberg projects
+ #include <config.h>
+#endif
+
+// CLOCK_MEINBERG is defined in NTP's config.h if configured
+// to support Meinberg clocks.
+#if !defined( CLOCK_MEINBERG )
+ // avoid having to use these headers in non-Meinberg projects
+ #include <words.h>
+ #include <use_pack.h>
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+
+/* "magic" number */
+#define MEINBERG_MAGIC 0x6AAC
+
+#define MIN_SVNO 1 /* min. SV number */
+#define MAX_SVNO 32 /* max. SV number */
+#define N_SVNO ( MAX_SVNO - MIN_SVNO + 1) /* number of possibly active SVs */
+
+
+#define GPS_ID_STR_LEN 16
+#define GPS_ID_STR_SIZE ( GPS_ID_STR_LEN + 1 )
+
+#define GPS_EPLD_STR_LEN 8
+#define GPS_EPLD_STR_SIZE ( GPS_EPLD_STR_LEN + 1 )
+
+
+#define DEFAULT_GPS_TICKS_PER_SEC 10000000L ///< system time base, see ::GPS_TICKS_PER_SEC
+
+#if !defined( GPS_TICKS_PER_SEC )
+ /*
+ * The actual ticks per seconds may vary for different
+ * GPS receiver models. If this is the case, the receiver
+ * model support the RECEIVER_INFO structure which contains
+ * the actual value.
+ */
+ #define GPS_TICKS_PER_SEC DEFAULT_GPS_TICKS_PER_SEC ///< @see DEFAULT_GPS_TICKS_PER_SEC
+
+#endif
+
+
+typedef uint16_t SVNO; ///< the number of an SV (Space Vehicle, i.e. satellite)
+typedef uint16_t HEALTH; ///< an SV's health code
+typedef uint16_t CFG; ///< an SV's configuration code
+typedef uint16_t IOD; ///< Issue-Of-Data code
+
+
+/* the type of various checksums */
+
+#ifndef _CSUM_DEFINED
+ typedef uint16_t CSUM; ///< checksum used by some structures stored in non-volatile memory
+ #define _CSUM_DEFINED
+
+ #define _mbg_swab_csum( _p ) _mbg_swab16( _p )
+#endif
+
+
+/**
+ * @brief The type of a GPS command code
+ *
+ * These command codes can be passed via
+ * @ref group_gps_cmds_serial "serial port" (see @file gpsserio.h), or
+ * @ref group_gps_cmds_bus "system bus" (see @file pcpsdefs.h).
+ */
+typedef uint16_t GPS_CMD;
+
+#define _mbg_swab_gps_cmd( _p ) _mbg_swab16( _p )
+
+
+/**
+ * @brief Software revision information
+ *
+ * Contains a software revision code, plus an optional
+ * identifier for a customized version.
+ */
+typedef struct
+{
+ uint16_t code; ///< Version number, e.g. 0x0120 means v1.20
+ char name[GPS_ID_STR_SIZE]; ///< Optional string identifying a customized version
+ uint8_t reserved; ///< Reserved field to yield even structure size
+} SW_REV;
+
+#define _mbg_swab_sw_rev( _p ) \
+{ \
+ _mbg_swab16( &(_p)->code ); \
+}
+
+
+
+/**
+ * @defgroup group_bvar_stat BVAR_STAT status of buffered GPS data
+ *
+ * Status word, associated bit numbers and bit masks indicating
+ * whether certain data from the GPS satellites are
+ * available and valid.
+ *
+ * These bits defined are set in ::BVAR_STAT if the corresponding
+ * parameters are NOT valid and complete.
+ *
+ * @{ */
+
+/**
+ * @brief Status flags of battery buffered data received
+ * from GPS satellites.
+ *
+ * All '0' means OK, single bits set to '1' indicate
+ * the associated type of GPS data is not available.
+ */
+typedef uint16_t BVAR_STAT;
+
+#define _mbg_swab_bvar_stat( _p ) _mbg_swab16( (_p) )
+
+
+/**
+ * @brief Enumeration of bits used with BVAR_STAT
+ *
+ * For each bit which is set this means the associated data set in
+ * non-volatile memory is not available or incomplete.
+ * Most data sets will just be re-collected from the data streams sent
+ * by the satellites. However, the receiver position has usually been
+ * computed earlier during normal operation, and will be re-computed
+ * when a sufficient number of satellites can be received.
+ */
+enum BVAR_BITS
+{
+ BVAR_BIT_CFGH_INVALID, ///< Satellite configuration and health parameters incomplete
+ BVAR_BIT_ALM_NOT_COMPLETE, ///< Almanac parameters incomplete
+ BVAR_BIT_UTC_INVALID, ///< %UTC offset parameters incomplete
+ BVAR_BIT_IONO_INVALID, ///< Ionospheric correction parameters incomplete
+ BVAR_BIT_RCVR_POS_INVALID, ///< No valid receiver position available
+ N_BVAR_BIT ///< number of defined ::BVAR_STAT bits
+};
+
+#define BVAR_CFGH_INVALID ( 1UL << BVAR_BIT_CFGH_INVALID ) ///< Configuration and health data (::CFGH) not valid
+#define BVAR_ALM_NOT_COMPLETE ( 1UL << BVAR_BIT_ALM_NOT_COMPLETE ) ///< Almanach data (::ALM) not complete
+#define BVAR_UTC_INVALID ( 1UL << BVAR_BIT_UTC_INVALID ) ///< ::UTC data not valid
+#define BVAR_IONO_INVALID ( 1UL << BVAR_BIT_IONO_INVALID ) ///< Ionospheric correction data (::IONO) not valid
+#define BVAR_RCVR_POS_INVALID ( 1UL << BVAR_BIT_RCVR_POS_INVALID ) ///< Receiver position (::POS) not valid
+
+#define BVAR_MASK ( ( 1UL << N_BVAR_BIT ) - 1 ) ///< Bit mask for all defined bits
+
+/** @} group_bvar_stat */
+
+
+
+/**
+ * @brief A structure used to hold a fixed frequency value
+ *
+ * @note frequ[kHz] = khz_val * 10^range
+ */
+typedef struct
+{
+ uint16_t khz_val; ///< the base frequency in [kHz]
+ int16_t range; ///< an optional base 10 exponent
+} FIXED_FREQ_INFO;
+
+#define _mbg_swab_fixed_freq_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->khz_val ); \
+ _mbg_swab16( &(_p)->range ); \
+}
+
+
+/**
+ * @brief A data type to specify feature flags within ::RECEIVER_INFO
+ */
+typedef uint32_t RI_FEATURES; ///< @see GPS_FEATURE_MASKS
+
+
+
+/**
+ * @brief A structure used to identify a device type and supported features
+ *
+ * @note This may not be supported by some very old devices.
+ */
+typedef struct
+{
+ uint16_t model_code; ///< identifier for receiver model, see ::GPS_MODEL_CODES
+ SW_REV sw_rev; ///< software revision and ID
+ char model_name[GPS_ID_STR_SIZE]; ///< ASCIIZ, name of receiver model
+ char sernum[GPS_ID_STR_SIZE]; ///< ASCIIZ, serial number
+ char epld_name[GPS_EPLD_STR_SIZE]; ///< ASCIIZ, file name of EPLD image
+ uint8_t n_channels; ///< number of satellites which can be tracked simultaneously
+ uint32_t ticks_per_sec; ///< resolution of fractions of seconds, see ::GPS_TICKS_PER_SEC
+ RI_FEATURES features; ///< optional features, see ::GPS_FEATURE_MASKS
+ FIXED_FREQ_INFO fixed_freq; ///< optional non-standard fixed frequency
+ uint8_t osc_type; ///< type of installed oscillator, see ::GPS_OSC_TYPES
+ uint8_t osc_flags; ///< oscillator flags, actually not used and always 0
+ uint8_t n_ucaps; ///< number of user time capture inputs
+ uint8_t n_com_ports; ///< number of on-board serial ports
+ uint8_t n_str_type; ///< max num of string types supported by any port
+ uint8_t n_prg_out; ///< number of programmable pulse outputs
+ uint16_t flags; ///< additional information, see ::RECEIVER_INFO_FLAG_BITS
+} RECEIVER_INFO;
+
+#define _mbg_swab_receiver_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->model_code ); \
+ _mbg_swab_sw_rev( &(_p)->sw_rev ); \
+ _mbg_swab16( &(_p)->ticks_per_sec ); \
+ _mbg_swab32( &(_p)->features ); \
+ _mbg_swab_fixed_freq_info( &(_p)->fixed_freq ); \
+ _mbg_swab16( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Known device ID codes for RECEIVER_INFO::model_code
+ */
+enum GPS_MODEL_CODES
+{
+ GPS_MODEL_UNKNOWN,
+ GPS_MODEL_GPS166,
+ GPS_MODEL_GPS167,
+ GPS_MODEL_GPS167SV,
+ GPS_MODEL_GPS167PC,
+ GPS_MODEL_GPS167PCI,
+ GPS_MODEL_GPS163,
+ GPS_MODEL_GPS168PCI,
+ GPS_MODEL_GPS161,
+ GPS_MODEL_GPS169PCI,
+ GPS_MODEL_TCR167PCI,
+ GPS_MODEL_GPS164,
+ GPS_MODEL_GPS170PCI,
+ GPS_MODEL_PZF511,
+ GPS_MODEL_GPS170,
+ GPS_MODEL_TCR511,
+ GPS_MODEL_AM511,
+ GPS_MODEL_MSF511,
+ GPS_MODEL_GRC170,
+ GPS_MODEL_GPS170PEX,
+ GPS_MODEL_GPS162,
+ GPS_MODEL_PTP270PEX,
+ GPS_MODEL_FRC511PEX,
+ GPS_MODEL_GEN170,
+ GPS_MODEL_TCR170PEX,
+ GPS_MODEL_WWVB511,
+ GPS_MODEL_MGR170,
+ GPS_MODEL_JJY511,
+ GPS_MODEL_PZF600,
+ GPS_MODEL_TCR600,
+ GPS_MODEL_GPS180,
+ GPS_MODEL_GLN170,
+ GPS_MODEL_GPS180PEX,
+ GPS_MODEL_TCR180PEX,
+ GPS_MODEL_PZF180PEX,
+ GPS_MODEL_MGR180,
+ GPS_MODEL_MSF600,
+ GPS_MODEL_WWVB600,
+ GPS_MODEL_JJY600,
+ GPS_MODEL_GPS180HS,
+ GPS_MODEL_GPS180AMC,
+ GPS_MODEL_ESI180,
+ GPS_MODEL_CPE180,
+ GPS_MODEL_LNO180,
+ GPS_MODEL_GRC180,
+ GPS_MODEL_LIU,
+ GPS_MODEL_DCF600HS,
+ GPS_MODEL_DCF600RS,
+ N_GPS_MODEL
+ /* If new model codes are added then care must be taken
+ * to update the associated string initializers below
+ * accordingly, and to check whether the classification macros
+ * also cover the new model names. */
+};
+
+
+
+
+/*
+ * String initializers for each of the GPS
+ * receiver models enum'ed above:
+ */
+#define GPS_MODEL_NAME_UNKNOWN "(unknown)"
+#define GPS_MODEL_NAME_GPS166 "GPS166"
+#define GPS_MODEL_NAME_GPS167 "GPS167"
+#define GPS_MODEL_NAME_GPS167SV "GPS167SV"
+#define GPS_MODEL_NAME_GPS167PC "GPS167PC"
+#define GPS_MODEL_NAME_GPS167PCI "GPS167PCI"
+#define GPS_MODEL_NAME_GPS163 "GPS163"
+#define GPS_MODEL_NAME_GPS168PCI "GPS168PCI"
+#define GPS_MODEL_NAME_GPS161 "GPS161"
+#define GPS_MODEL_NAME_GPS169PCI "GPS169PCI"
+#define GPS_MODEL_NAME_TCR167PCI "TCR167PCI"
+#define GPS_MODEL_NAME_GPS164 "GPS164"
+#define GPS_MODEL_NAME_GPS170PCI "GPS170PCI"
+#define GPS_MODEL_NAME_PZF511 "PZF511"
+#define GPS_MODEL_NAME_GPS170 "GPS170"
+#define GPS_MODEL_NAME_TCR511 "TCR511"
+#define GPS_MODEL_NAME_AM511 "AM511"
+#define GPS_MODEL_NAME_MSF511 "MSF511"
+#define GPS_MODEL_NAME_GRC170 "GRC170"
+#define GPS_MODEL_NAME_GPS170PEX "GPS170PEX"
+#define GPS_MODEL_NAME_GPS162 "GPS162"
+#define GPS_MODEL_NAME_PTP270PEX "PTP270PEX"
+#define GPS_MODEL_NAME_FRC511PEX "FRC511PEX"
+#define GPS_MODEL_NAME_GEN170 "GEN170"
+#define GPS_MODEL_NAME_TCR170PEX "TCR170PEX"
+#define GPS_MODEL_NAME_WWVB511 "WWVB511"
+#define GPS_MODEL_NAME_MGR170 "MGR170"
+#define GPS_MODEL_NAME_JJY511 "JJY511"
+#define GPS_MODEL_NAME_PZF600 "PZF600"
+#define GPS_MODEL_NAME_TCR600 "TCR600"
+#define GPS_MODEL_NAME_GPS180 "GPS180"
+#define GPS_MODEL_NAME_GLN170 "GLN170"
+#define GPS_MODEL_NAME_GPS180PEX "GPS180PEX"
+#define GPS_MODEL_NAME_TCR180PEX "TCR180PEX"
+#define GPS_MODEL_NAME_PZF180PEX "PZF180PEX"
+#define GPS_MODEL_NAME_MGR180 "MGR180"
+#define GPS_MODEL_NAME_MSF600 "MSF600"
+#define GPS_MODEL_NAME_WWVB600 "WWVB600"
+#define GPS_MODEL_NAME_JJY600 "JJY600"
+#define GPS_MODEL_NAME_GPS180HS "GPS180HS"
+#define GPS_MODEL_NAME_GPS180AMC "GPS180AMC"
+#define GPS_MODEL_NAME_ESI180 "ESI180"
+#define GPS_MODEL_NAME_CPE180 "CPE180"
+#define GPS_MODEL_NAME_LNO180 "LNO180"
+#define GPS_MODEL_NAME_GRC180 "GRC180"
+#define GPS_MODEL_NAME_LIU "LIU"
+#define GPS_MODEL_NAME_DCF600HS "DCF600HS"
+#define GPS_MODEL_NAME_DCF600RS "DCF600RS"
+
+/*
+ * The definition below can be used to initialize
+ * an array of N_GPS_MODEL type name strings.
+ * Including the trailing 0, each name must not
+ * exceed GPS_ID_STR_SIZE chars.
+ */
+#define DEFAULT_GPS_MODEL_NAMES \
+{ \
+ GPS_MODEL_NAME_UNKNOWN, \
+ GPS_MODEL_NAME_GPS166, \
+ GPS_MODEL_NAME_GPS167, \
+ GPS_MODEL_NAME_GPS167SV, \
+ GPS_MODEL_NAME_GPS167PC, \
+ GPS_MODEL_NAME_GPS167PCI, \
+ GPS_MODEL_NAME_GPS163, \
+ GPS_MODEL_NAME_GPS168PCI, \
+ GPS_MODEL_NAME_GPS161, \
+ GPS_MODEL_NAME_GPS169PCI, \
+ GPS_MODEL_NAME_TCR167PCI, \
+ GPS_MODEL_NAME_GPS164, \
+ GPS_MODEL_NAME_GPS170PCI, \
+ GPS_MODEL_NAME_PZF511, \
+ GPS_MODEL_NAME_GPS170, \
+ GPS_MODEL_NAME_TCR511, \
+ GPS_MODEL_NAME_AM511, \
+ GPS_MODEL_NAME_MSF511, \
+ GPS_MODEL_NAME_GRC170, \
+ GPS_MODEL_NAME_GPS170PEX, \
+ GPS_MODEL_NAME_GPS162, \
+ GPS_MODEL_NAME_PTP270PEX, \
+ GPS_MODEL_NAME_FRC511PEX, \
+ GPS_MODEL_NAME_GEN170, \
+ GPS_MODEL_NAME_TCR170PEX, \
+ GPS_MODEL_NAME_WWVB511, \
+ GPS_MODEL_NAME_MGR170, \
+ GPS_MODEL_NAME_JJY511, \
+ GPS_MODEL_NAME_PZF600, \
+ GPS_MODEL_NAME_TCR600, \
+ GPS_MODEL_NAME_GPS180, \
+ GPS_MODEL_NAME_GLN170, \
+ GPS_MODEL_NAME_GPS180PEX, \
+ GPS_MODEL_NAME_TCR180PEX, \
+ GPS_MODEL_NAME_PZF180PEX, \
+ GPS_MODEL_NAME_MGR180, \
+ GPS_MODEL_NAME_MSF600, \
+ GPS_MODEL_NAME_WWVB600, \
+ GPS_MODEL_NAME_JJY600, \
+ GPS_MODEL_NAME_GPS180HS, \
+ GPS_MODEL_NAME_GPS180AMC, \
+ GPS_MODEL_NAME_ESI180, \
+ GPS_MODEL_NAME_CPE180, \
+ GPS_MODEL_NAME_LNO180, \
+ GPS_MODEL_NAME_GRC180, \
+ GPS_MODEL_NAME_LIU, \
+ GPS_MODEL_NAME_DCF600HS, \
+ GPS_MODEL_NAME_DCF600RS \
+}
+
+
+/*
+ * The macros below can be used to classify a receiver,
+ * e.g. depending on the time source and/or depending on
+ * whether it's a plug-in card or an external device.
+ */
+
+#define _mbg_rcvr_is_plug_in( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "PC" ) || \
+ ( strstr( (_p_ri)->model_name, "PEX" ) )
+
+#define _mbg_rcvr_is_gps( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "GPS" ) || \
+ ( strstr( (_p_ri)->model_name, "MGR" ) )
+
+#define _mbg_rcvr_is_mobile_gps( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "MGR" ) )
+
+#define _mbg_rcvr_is_gps_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_gps( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_irig( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "TCR" ) )
+
+#define _mbg_rcvr_is_irig_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_irig( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_dcf77_am( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "AM" ) )
+
+#define _mbg_rcvr_is_dcf77_am_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_dcf77_am( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_dcf77_pzf( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "PZF" ) )
+
+#define _mbg_rcvr_is_dcf77_pzf_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_dcf77_pzf( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_any_dcf77( _p_ri ) \
+ ( _mbg_rcvr_is_dcf77_am( _p_ri ) || \
+ _mbg_rcvr_is_dcf77_pzf( _p_ri ) )
+
+#define _mbg_rcvr_is_any_dcf77_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_any_dcf77( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_msf( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "MSF" ) )
+
+#define _mbg_rcvr_is_jjy( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "JJY" ) )
+
+#define _mbg_rcvr_is_msf_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_msf( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_glonass( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "GRC" ) || \
+ ( strstr( (_p_ri)->model_name, "GLN" ) )
+
+#define _mbg_rcvr_is_glonass_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_glonass( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_wwvb( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "WWVB" ) )
+
+#define _mbg_rcvr_is_wwvb_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_wwvb( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+
+/**
+ * @brief Oscillator classification codes used with RECEIVER_INFO::osc_type
+ *
+ * New codes will just be appended to the enumeration, so the sequence
+ * of codes does NOT reflect the order of quality.
+ */
+enum GPS_OSC_TYPES
+{
+ GPS_OSC_UNKNOWN,
+ GPS_OSC_TCXO_LQ,
+ GPS_OSC_TCXO_HQ,
+ GPS_OSC_OCXO_LQ,
+ GPS_OSC_OCXO_MQ,
+ GPS_OSC_OCXO_HQ,
+ GPS_OSC_OCXO_XHQ,
+ GPS_OSC_RUBIDIUM,
+ GPS_OSC_TCXO_MQ,
+ GPS_OSC_OCXO_DHQ,
+ N_GPS_OSC
+};
+
+
+/*
+ * The sequence and number of oscillator names
+ * listed below must correspond to the enumeration
+ * above:
+ */
+#define DEFAULT_GPS_OSC_NAMES \
+{ \
+ "[unknown]", \
+ "TCXO LQ", \
+ "TCXO", \
+ "OCXO LQ", \
+ "OCXO MQ", \
+ "OCXO HQ", \
+ "OCXO XHQ", \
+ "RUBIDIUM", \
+ "TCXO MQ", \
+ "OCXO DHQ" \
+}
+
+
+/*
+ * The initializer below can be used to initialize
+ * an array (e.g. "int osc_quality_idx[N_GPS_OSC]")
+ * which allows to display the oscillator types
+ * ordered by quality:
+ */
+#define DEFAULT_GPS_OSC_QUALITY_IDX \
+{ \
+ GPS_OSC_UNKNOWN, \
+ GPS_OSC_TCXO_LQ, \
+ GPS_OSC_TCXO_MQ, \
+ GPS_OSC_TCXO_HQ, \
+ GPS_OSC_OCXO_LQ, \
+ GPS_OSC_OCXO_MQ, \
+ GPS_OSC_OCXO_HQ, \
+ GPS_OSC_OCXO_DHQ, \
+ GPS_OSC_OCXO_XHQ, \
+ GPS_OSC_RUBIDIUM \
+}
+
+
+
+/**
+ * @brief Enumeration of device features flags reported in RECEIVER_INFO::features
+ *
+ * Each flags indicates if a device supports the associated feature.
+ */
+enum GPS_FEATURE_BITS
+{
+ GPS_FEAT_PPS, ///< has pulse per second output
+ GPS_FEAT_PPM, ///< has pulse per minute output
+ GPS_FEAT_SYNTH, ///< has programmable synthesizer output
+ GPS_FEAT_DCFMARKS, ///< has DCF77 compatible time mark output
+ GPS_FEAT_IRIG_TX, ///< has on-board IRIG output
+ GPS_FEAT_IRIG_RX, ///< has on-board IRIG input
+ GPS_FEAT_LAN_IP4, ///< has LAN IPv4 interface
+ GPS_FEAT_MULTI_REF, ///< has multiple input sources with priorities
+
+ GPS_FEAT_RCV_TIMEOUT, ///< timeout after GPS reception has stopped
+ GPS_FEAT_IGNORE_LOCK, ///< supports "ignore lock", MBG_OPT_BIT_EMU_SYNC can be set alternatively
+ GPS_FEAT_5_MHZ, ///< output 5 MHz rather than 100 kHz
+ GPS_FEAT_XMULTI_REF, ///< has extended multiple input source configuration
+ GPS_FEAT_OPT_SETTINGS, ///< supports MBG_OPT_SETTINGS
+ GPS_FEAT_TIME_SCALE, ///< supports configurable time scale (%UTC, TAI, GPS, ...)
+ GPS_FEAT_IRIG_CTRL_BITS, ///< supports IRIG control bits
+ GPS_FEAT_PTP, ///< has PTP support
+
+ GPS_FEAT_NAV_ENGINE_SETTINGS, ///< supports navigation engine configuration
+ GPS_FEAT_RAW_IRIG_DATA, ///< supports reading raw IRIG input data
+ GPS_FEAT_RAW_IRIG_TIME, ///< supports reading decoded IRIG time
+ GPS_FEAT_PTP_UNICAST, ///< has PTP Unicast support
+ GPS_FEAT_GPIO, ///< has general purpose in/outputs
+ GPS_FEAT_XMRS_MULT_INSTC, ///< multiple XMRS instances of the same ref type supported, see ::XMRSF_BIT_MULT_INSTC_SUPP
+ GPS_FEAT_10MHZ_DISBD, ///< 10 MHz output is always disabled
+ GPS_FEAT_EVT_LOG, ///< Event logging supported
+
+ GPS_FEAT_IMS, ///< Support IMS data structures
+ GPS_FEAT_HAVEQUICK, ///< Support HaveQuick structures
+
+ N_GPS_FEATURE ///< the number of valid features
+ /*
+ * If new features are added then care must be taken to update the associated
+ * definitions below accordingly, e.g. string initializers and bit masks.
+ */
+};
+
+
+/**
+ * @brief Names of device features
+ *
+ * @see GPS_FEATURE_BITS
+ */
+#define DEFAULT_GPS_FEATURE_NAMES \
+{ \
+ "Pulse Per Second", \
+ "Pulse Per Minute", \
+ "Programmable Synth.", \
+ "DCF77 Time Marks", \
+ "IRIG Out", \
+ "IRIG In", \
+ "IPv4 LAN Interface", \
+ "Multiple Ref. Sources", \
+ "Receive Timeout", \
+ "Ignore Lock", \
+ "5 MHz Output", \
+ "Ext. Multiple Ref. Src. Cfg.", \
+ "Optional Settings", \
+ "Configurable Time Scale", \
+ "IRIG Control Bits", \
+ "PTP/IEEE1588", \
+ "Nav. Engine Settings", \
+ "Raw IRIG Data", \
+ "Raw IRIG Time", \
+ "PTP/IEEE1588 Unicast", \
+ "General Purpose I/O", \
+ "Multiple XMRS Instances", \
+ "10 MHz Output Disabled", \
+ "Event Logging", \
+ "IMS data", \
+ "HaveQuick" \
+}
+
+
+/**
+ * @brief Bit masks used with RECEIVER_INFO::features
+ *
+ * @see GPS_FEATURE_BITS
+ */
+enum GPS_FEATURE_MASKS
+{
+ GPS_HAS_PPS = ( 1UL << GPS_FEAT_PPS ), ///< see ::GPS_FEAT_PPS
+ GPS_HAS_PPM = ( 1UL << GPS_FEAT_PPM ), ///< see ::GPS_FEAT_PPM
+ GPS_HAS_SYNTH = ( 1UL << GPS_FEAT_SYNTH ), ///< see ::GPS_FEAT_SYNTH
+ GPS_HAS_DCFMARKS = ( 1UL << GPS_FEAT_DCFMARKS ), ///< see ::GPS_FEAT_DCFMARKS
+ GPS_HAS_IRIG_TX = ( 1UL << GPS_FEAT_IRIG_TX ), ///< see ::GPS_FEAT_IRIG_TX
+ GPS_HAS_IRIG_RX = ( 1UL << GPS_FEAT_IRIG_RX ), ///< see ::GPS_FEAT_IRIG_RX
+ GPS_HAS_LAN_IP4 = ( 1UL << GPS_FEAT_LAN_IP4 ), ///< see ::GPS_FEAT_LAN_IP4
+ GPS_HAS_MULTI_REF = ( 1UL << GPS_FEAT_MULTI_REF ), ///< see ::GPS_FEAT_MULTI_REF
+
+ GPS_HAS_RCV_TIMEOUT = ( 1UL << GPS_FEAT_RCV_TIMEOUT ), ///< see ::GPS_FEAT_RCV_TIMEOUT
+ GPS_HAS_IGNORE_LOCK = ( 1UL << GPS_FEAT_IGNORE_LOCK ), ///< see ::GPS_FEAT_IGNORE_LOCK
+ GPS_HAS_5_MHZ = ( 1UL << GPS_FEAT_5_MHZ ), ///< see ::GPS_FEAT_5_MHZ
+ GPS_HAS_XMULTI_REF = ( 1UL << GPS_FEAT_XMULTI_REF ), ///< see ::GPS_FEAT_XMULTI_REF
+ GPS_HAS_OPT_SETTINGS = ( 1UL << GPS_FEAT_OPT_SETTINGS ), ///< see ::GPS_FEAT_OPT_SETTINGS
+ GPS_HAS_TIME_SCALE = ( 1UL << GPS_FEAT_TIME_SCALE ), ///< see ::GPS_FEAT_TIME_SCALE
+ GPS_HAS_IRIG_CTRL_BITS = ( 1UL << GPS_FEAT_IRIG_CTRL_BITS ), ///< see ::GPS_FEAT_IRIG_CTRL_BITS
+ GPS_HAS_PTP = ( 1UL << GPS_FEAT_PTP ), ///< see ::GPS_FEAT_PTP
+
+ GPS_HAS_NAV_ENGINE_SETTINGS = ( 1UL << GPS_FEAT_NAV_ENGINE_SETTINGS ), ///< see ::GPS_FEAT_NAV_ENGINE_SETTINGS
+ GPS_HAS_RAW_IRIG_DATA = ( 1UL << GPS_FEAT_RAW_IRIG_DATA ), ///< see ::GPS_FEAT_RAW_IRIG_DATA
+ GPS_HAS_RAW_IRIG_TIME = ( 1UL << GPS_FEAT_RAW_IRIG_TIME ), ///< see ::GPS_FEAT_RAW_IRIG_TIME
+ GPS_HAS_PTP_UNICAST = ( 1UL << GPS_FEAT_PTP_UNICAST ), ///< see ::GPS_FEAT_PTP_UNICAST
+ GPS_HAS_GPIO = ( 1UL << GPS_FEAT_GPIO ), ///< see ::GPS_FEAT_GPIO
+ GPS_HAS_XMRS_MULT_INSTC = ( 1UL << GPS_FEAT_XMRS_MULT_INSTC ), ///< see ::GPS_FEAT_XMRS_MULT_INSTC
+ GPS_HAS_10MHZ_DISBD = ( 1UL << GPS_FEAT_10MHZ_DISBD ), ///< see ::GPS_FEAT_10MHZ_DISBD
+ GPS_HAS_EVT_LOG = ( 1UL << GPS_FEAT_EVT_LOG ), ///< see ::GPS_FEAT_EVT_LOG
+
+ GPS_HAS_IMS = ( 1UL << GPS_FEAT_IMS ), ///< see ::GPS_FEAT_IMS
+ GPS_HAS_HAVEQUICK = ( 1UL << GPS_FEAT_HAVEQUICK ), ///< see ::GPS_FEAT_HAVEQUICK
+
+ // the next ones are special since they just shadow another flag:
+ GPS_HAS_REF_OFFS = GPS_HAS_IRIG_RX, ///< always supported with IRIG inputs, see ::GPS_HAS_IRIG_RX
+ GPS_HAS_DEBUG_INFO = GPS_HAS_IRIG_RX ///< always supported with IRIG inputs, see ::GPS_HAS_IRIG_RX
+};
+
+
+/*
+ * The features below are supported by default by older
+ * C166 based GPS receivers:
+ */
+#define DEFAULT_GPS_FEATURES_C166 \
+{ \
+ GPS_HAS_PPS | \
+ GPS_HAS_PPM | \
+ GPS_HAS_SYNTH | \
+ GPS_HAS_DCFMARKS \
+}
+
+
+/**
+ * @brief Bits to be used with RECEIVER_INFO::flags
+ */
+enum RECEIVER_INFO_FLAG_BITS
+{
+ GPS_BIT_OSC_CFG_SUPP, ///< oscillator cfg is supported, see ::RECEIVER_INFO::osc_type
+ GPS_BIT_IRIG_FO_IN, ///< IRIG input via fiber optics
+ GPS_BIT_HAS_FPGA, ///< device provides on-board FPGA
+ N_RECEIVER_INFO_FLAG_BITS ///< number of known bits
+};
+
+#define GPS_OSC_CFG_SUPP ( 1UL << GPS_BIT_OSC_CFG_SUPP )
+#define GPS_IRIG_FO_IN ( 1UL << GPS_BIT_IRIG_FO_IN )
+#define GPS_HAS_FPGA ( 1UL << GPS_BIT_HAS_FPGA )
+
+
+
+/*
+ * If the GPS_HAS_FPGA flag is set in RECEIVER_INFO::flags then the card
+ * provides an FPGA and the following information about the FPGA is available:
+ */
+#define FPGA_NAME_LEN 31 // max name length
+#define FPGA_NAME_SIZE ( FPGA_NAME_LEN + 1 ) // size including trailing 0
+
+#define FPGA_INFO_SIZE 128
+
+typedef union
+{
+ struct
+ {
+ CSUM csum;
+ uint32_t fsize;
+ #if _IS_MBG_FIRMWARE
+ uint32_t start_addr;
+ #else
+ uint8_t *start_addr;
+ #endif
+ char name[FPGA_NAME_SIZE];
+ } hdr;
+
+ char b[FPGA_INFO_SIZE];
+
+} FPGA_INFO;
+
+
+
+/*
+ * The definitions below are used to specify where a FPGA image is located
+ * in the flash memory:
+ */
+typedef struct
+{
+ CSUM csum;
+ uint16_t fpga_start_seg; // Number of the 4k block where an FPGA image is located
+} FPGA_START_INFO;
+
+#define DEFAULT_FPGA_START_SEG 0x60
+
+#define DEFAULT_FPGA_START_INFO \
+{ \
+ 0x1234 + DEFAULT_FPGA_START_SEG, \
+ DEFAULT_FPGA_START_SEG \
+}
+
+
+
+/**
+ * @brief A structure used to hold time in GPS format
+ *
+ * Date and time refer to the linear time scale defined by GPS, with
+ * the epoch starting at %UTC midnight at the beginning of January 6, 1980.
+ *
+ * GPS time is counted by the week numbers since the epoch, plus second
+ * of the week, plus fraction of the second. The week number transmitted
+ * by the satellites rolls over from 1023 to 0, but Meinberg devices
+ * just continue to count the weeks beyond the 1024 week limit to keep
+ * the receiver's internal time.
+ *
+ * %UTC time differs from GPS time since a number of leap seconds have
+ * been inserted in the %UTC time scale after the GPS epoche. The number
+ * of leap seconds is disseminated by the satellites using the ::UTC
+ * parameter set, which also provides info on pending leap seconds.
+ */
+typedef struct
+{
+ uint16_t wn; ///< the week number since GPS has been installed
+ uint32_t sec; ///< the second of that week
+ uint32_t tick; ///< fractions of a second; scale: 1/::RECEIVER_INFO::ticks_per_sec
+} T_GPS;
+
+#define _mbg_swab_t_gps( _p ) \
+{ \
+ _mbg_swab16( &(_p)->wn ); \
+ _mbg_swab32( &(_p)->sec ); \
+ _mbg_swab32( &(_p)->tick ); \
+}
+
+
+/**
+ * @brief Local date and time computed from GPS time
+ *
+ * The current number of leap seconds have to be added to get %UTC
+ * from GPS time. Additional corrections could have been made according
+ * to the time zone/daylight saving parameters ::TZDL defined by the user.
+ * The status field can be checked to see which corrections
+ * have actually been applied.
+ *
+ * @note Conversion from GPS time to %UTC and/or local time can only be
+ * done if some valid ::UTC correction parameters are available in the
+ * receiver's non-volatile memory.
+ */
+typedef struct
+{
+ int16_t year; ///< year number, 0..9999
+ int8_t month; ///< month, 1..12
+ int8_t mday; ///< day of month, 1..31
+ int16_t yday; ///< day of year, 1..366
+ int8_t wday; ///< day of week, 0..6 == Sun..Sat
+ int8_t hour; ///< hours, 0..23
+ int8_t min; ///< minutes, 0..59
+ int8_t sec; ///< seconds, 0..59
+ int32_t frac; ///< fractions of a second; scale: 1/::RECEIVER_INFO::ticks_per_sec
+ int32_t offs_from_utc; ///< local time's offset from %UTC
+ uint16_t status; ///< status flags, see ::TM_GPS_STATUS_BITS
+} TM_GPS;
+
+#define _mbg_swab_tm_gps( _p ) \
+{ \
+ _mbg_swab16( &(_p)->year ); \
+ _mbg_swab16( &(_p)->yday ); \
+ _mbg_swab32( &(_p)->frac ); \
+ _mbg_swab32( &(_p)->offs_from_utc ); \
+ _mbg_swab16( &(_p)->status ); \
+}
+
+
+/**
+ * @brief Status flags used with TM_GPS::status
+ *
+ * These bits report info on the time conversion from GPS time to %UTC
+ * and/or local time as well as device status info.
+ */
+enum TM_GPS_STATUS_BITS
+{
+ TM_BIT_UTC, ///< %UTC correction has been made
+ TM_BIT_LOCAL, ///< %UTC has been converted to local time according to ::TZDL settings
+ TM_BIT_DL_ANN, ///< state of daylight saving is going to change
+ TM_BIT_DL_ENB, ///< daylight saving is in effect
+ TM_BIT_LS_ANN, ///< leap second pending
+ TM_BIT_LS_ENB, ///< current second is leap second
+ TM_BIT_LS_ANN_NEG, ///< set in addition to ::TM_BIT_LS_ANN if leap sec is negative
+ TM_BIT_INVT, ///< invalid time, e.g. if RTC battery bas been empty
+
+ TM_BIT_EXT_SYNC, ///< synchronized externally
+ TM_BIT_HOLDOVER, ///< in holdover mode after previous synchronization
+ TM_BIT_ANT_SHORT, ///< antenna cable short circuited
+ TM_BIT_NO_WARM, ///< OCXO has not warmed up
+ TM_BIT_ANT_DISCONN, ///< antenna currently disconnected
+ TM_BIT_SYN_FLAG, ///< TIME_SYN output is low
+ TM_BIT_NO_SYNC, ///< time sync actually not verified
+ TM_BIT_NO_POS ///< position actually not verified, LOCK LED off
+};
+
+// bit masks corresponding to the flag bits above
+#define TM_UTC ( 1UL << TM_BIT_UTC )
+#define TM_LOCAL ( 1UL << TM_BIT_LOCAL )
+#define TM_DL_ANN ( 1UL << TM_BIT_DL_ANN )
+#define TM_DL_ENB ( 1UL << TM_BIT_DL_ENB )
+#define TM_LS_ANN ( 1UL << TM_BIT_LS_ANN )
+#define TM_LS_ENB ( 1UL << TM_BIT_LS_ENB )
+#define TM_LS_ANN_NEG ( 1UL << TM_BIT_LS_ANN_NEG )
+#define TM_INVT ( 1UL << TM_BIT_INVT )
+
+#define TM_EXT_SYNC ( 1UL << TM_BIT_EXT_SYNC )
+#define TM_HOLDOVER ( 1UL << TM_BIT_HOLDOVER )
+#define TM_ANT_SHORT ( 1UL << TM_BIT_ANT_SHORT )
+#define TM_NO_WARM ( 1UL << TM_BIT_NO_WARM )
+#define TM_ANT_DISCONN ( 1UL << TM_BIT_ANT_DISCONN )
+#define TM_SYN_FLAG ( 1UL << TM_BIT_SYN_FLAG )
+#define TM_NO_SYNC ( 1UL << TM_BIT_NO_SYNC )
+#define TM_NO_POS ( 1UL << TM_BIT_NO_POS )
+
+
+/**
+ * @brief Type of an extended TM status which is mainly used inside the firmware
+ */
+typedef uint32_t TM_STATUS_EXT;
+
+/**
+ * @brief Enumeration of extended status bits used with TM_STATUS_EXT
+ *
+ * @note The lower 16 bits correspond to ::TM_GPS_STATUS_BITS
+ */
+enum TM_GPS_STATUS_BITS_EX
+{
+ TM_BIT_SCALE_GPS = 16, ///< time scale configured to return GPS time
+ TM_BIT_SCALE_TAI ///< time scale configured to return TAI
+ // the remaining bits are reserved
+};
+
+// The following bits are only used with the TM_STATUS_X type:
+#define TM_SCALE_GPS ( 1UL << TM_BIT_SCALE_GPS )
+#define TM_SCALE_TAI ( 1UL << TM_BIT_SCALE_TAI )
+
+#define TM_MSK_TIME_VALID ( TM_UTC | TM_SCALE_GPS | TM_SCALE_TAI )
+
+
+/**
+ * @brief A structure used to transmit information on date and time
+ *
+ * This structure can be used to transfer the current time, in which
+ * case the channel field has to be set to -1, or an event capture time
+ * retrieved from the on-board FIFO, in which case the channel field
+ * contains the index of the time capture input, e.g. 0 or 1.
+ */
+typedef struct
+{
+ int16_t channel; ///< -1: the current on-board time; >= 0 the capture channel number
+ T_GPS t; ///< time in GPS scale and format
+ TM_GPS tm; ///< time converted to %UTC and/or local time according to ::TZDL settings
+} TTM;
+
+#define _mbg_swab_ttm( _p ) \
+{ \
+ _mbg_swab16( &(_p)->channel ); \
+ _mbg_swab_t_gps( &(_p)->t ); \
+ _mbg_swab_tm_gps( &(_p)->tm ); \
+}
+
+
+
+/**
+ * @brief A timestamp with nanosecond resolution
+ */
+typedef struct
+{
+ int32_t nano_secs; ///< [nanoseconds]
+ int32_t secs; ///< [seconds]
+} NANO_TIME;
+
+#define _mbg_swab_nano_time( _p ) \
+{ \
+ _mbg_swab32( &(_p)->nano_secs ); \
+ _mbg_swab32( &(_p)->secs ); \
+}
+
+// The macro below checks if a NANO_TIME value is negative.
+#define _nano_time_negative( _nt ) \
+ ( ( (_nt)->secs < 0 ) || ( (_nt)->nano_secs < 0 ) )
+
+
+
+/* Two types of variables used to store a position. Type XYZ is */
+/* used with a position in earth centered, earth fixed (ECEF) */
+/* coordinates whereas type LLA holds such a position converted */
+/* to geographic coordinates as defined by WGS84 (World Geodetic */
+/* System from 1984). */
+
+#ifndef _XYZ_DEFINED
+ /**
+ * @brief Sequence and number of components of a cartesian position
+ */
+ enum XYZ_FIELDS { XP, YP, ZP, N_XYZ }; // x, y, z
+
+ /**
+ * @brief An array holding a cartesian position
+ */
+ typedef double XYZ[N_XYZ]; ///< values are in [m], see ::XYZ_FIELDS
+
+ #define _XYZ_DEFINED
+#endif
+
+#define _mbg_swab_xyz( _p ) _mbg_swab_doubles( _p, N_XYZ )
+
+
+#ifndef _LLA_DEFINED
+ /**
+ * @brief Sequence and number of components of a geographic position
+ */
+ enum LLA_FIELDS { LAT, LON, ALT, N_LLA }; /* latitude, longitude, altitude */
+
+ /**
+ * @brief An array holding a geographic position
+ */
+ typedef double LLA[N_LLA]; ///< lon, lat in [rad], alt in [m], see ::LLA_FIELDS
+
+ #define _LLA_DEFINED
+#endif
+
+#define _mbg_swab_lla( _p ) _mbg_swab_doubles( _p, N_LLA )
+
+
+/**
+ @defgroup group_synth Synthesizer parameters
+
+ Synthesizer frequency is expressed as a
+ four digit decimal number (freq) to be multiplied by 0.1 Hz and an
+ base 10 exponent (range). If the effective frequency is less than
+ 10 kHz its phase is synchronized corresponding to the variable phase.
+ Phase may be in a range from -360 deg to +360 deg with a resolution
+ of 0.1 deg, so the resulting numbers to be stored are in a range of
+ -3600 to +3600.
+
+ Example:<br>
+ Assume the value of freq is 2345 (decimal) and the value of phase is 900.
+ If range == 0 the effective frequency is 234.5 Hz with a phase of +90 deg.
+ If range == 1 the synthesizer will generate a 2345 Hz output frequency
+ and so on.
+
+ Limitations:<br>
+ If freq == 0 the synthesizer is disabled. If range == 0 the least
+ significant digit of freq is limited to 0, 3, 5 or 6. The resulting
+ frequency is shown in the examples below:
+ - freq == 1230 --> 123.0 Hz
+ - freq == 1233 --> 123 1/3 Hz (real 1/3 Hz, NOT 123.3 Hz)
+ - freq == 1235 --> 123.5 Hz
+ - freq == 1236 --> 123 2/3 Hz (real 2/3 Hz, NOT 123.6 Hz)
+
+ If range == MAX_RANGE the value of freq must not exceed 1000, so the
+ output frequency is limited to 10 MHz.
+ @{
+*/
+
+#define N_SYNTH_FREQ_DIGIT 4 ///< number of digits to edit
+#define MAX_SYNTH_FREQ 1000 ///< if range == ::MAX_SYNTH_RANGE
+
+#define MIN_SYNTH_RANGE 0
+#define MAX_SYNTH_RANGE 5
+#define N_SYNTH_RANGE ( MAX_SYNTH_RANGE - MIN_SYNTH_RANGE + 1 )
+
+#define N_SYNTH_PHASE_DIGIT 4
+#define MAX_SYNTH_PHASE 3600
+
+
+#define MAX_SYNTH_FREQ_EDIT 9999 ///< max sequence of digits when editing
+
+/**
+ * @brief The maximum frequency that can be configured for the synthesizer
+ */
+#define MAX_SYNTH_FREQ_VAL 10000000UL ///< 10 MHz
+/* == MAX_SYNTH_FREQ * 10^(MAX_SYNTH_RANGE-1) */
+
+/**
+ * @brief The synthesizer's phase is only be synchronized if the frequency is below this limit
+ */
+#define SYNTH_PHASE_SYNC_LIMIT 10000UL ///< 10 kHz
+
+/**
+ * A Macro used to determine the position of the decimal point
+ * when printing the synthesizer frequency as 4 digit value
+ */
+#define _synth_dp_pos_from_range( _r ) \
+ ( ( ( N_SYNTH_RANGE - (_r) ) % ( N_SYNTH_FREQ_DIGIT - 1 ) ) + 1 )
+
+/**
+ * @brief Synthesizer frequency units
+ *
+ * An initializer for commonly displayed synthesizer frequency units
+ * (N_SYNTH_RANGE strings)
+ */
+#define DEFAULT_FREQ_RANGES \
+{ \
+ "Hz", \
+ "kHz", \
+ "kHz", \
+ "kHz", \
+ "MHz", \
+ "MHz", \
+}
+
+
+
+/**
+ * @brief Synthesizer configuration parameters
+ */
+typedef struct
+{
+ int16_t freq; ///< four digits used; scale: 0.1; e.g. 1234 -> 123.4 Hz
+ int16_t range; ///< scale factor for freq; 0..::MAX_SYNTH_RANGE
+ int16_t phase; ///< -::MAX_SYNTH_PHASE..+::MAX_SYNTH_PHASE; >0 -> pulses later
+} SYNTH;
+
+#define _mbg_swab_synth( _p ) \
+{ \
+ _mbg_swab16( &(_p)->freq ); \
+ _mbg_swab16( &(_p)->range ); \
+ _mbg_swab16( &(_p)->phase ); \
+}
+
+
+/**
+ * @brief Enumeration of synthesizer states
+ */
+enum SYNTH_STATES
+{
+ SYNTH_DISABLED, ///< disbled by cfg, i.e. freq == 0.0
+ SYNTH_OFF, ///< not enabled after power-up
+ SYNTH_FREE, ///< enabled, but not synchronized
+ SYNTH_DRIFTING, ///< has initially been sync'd, but now running free
+ SYNTH_SYNC, ///< fully synchronized
+ N_SYNTH_STATE ///< the number of known states
+};
+
+
+/**
+ * @brief A structure used to report the synthesizer state
+ */
+typedef struct
+{
+ uint8_t state; ///< state code as enumerated in ::SYNTH_STATES
+ uint8_t flags; ///< reserved, currently always 0
+} SYNTH_STATE;
+
+#define _mbg_swab_synth_state( _p ) _nop_macro_fnc()
+
+#define SYNTH_FLAG_PHASE_IGNORED 0x01
+
+/** @} group_synth */
+
+/**
+ * @defgroup group_tzdl Time zone/daylight saving parameters
+ *
+ * Example: <br>
+ * For automatic daylight saving enable/disable in Central Europe,
+ * the variables are to be set as shown below: <br>
+ * - offs = 3600L one hour from %UTC
+ * - offs_dl = 3600L one additional hour if daylight saving enabled
+ * - tm_on = first Sunday from March 25, 02:00:00h ( year |= DL_AUTO_FLAG )
+ * - tm_off = first Sunday from October 25, 03:00:00h ( year |= DL_AUTO_FLAG )
+ * - name[0] == "CET " name if daylight saving not enabled
+ * - name[1] == "CEST " name if daylight saving is enabled
+ * @{
+ */
+
+/**
+ * @brief The name of a time zone
+ *
+ * @note Up to 5 printable characters plus trailing zero
+ */
+typedef char TZ_NAME[6];
+
+/**
+ * @brief Time zone / daylight saving parameters
+ *
+ * This structure is used to specify how a device is to convert
+ * on-board %UTC to local time, including computation of beginning
+ * and end of daylight saving time (DST), if required.
+ */
+typedef struct
+{
+ int32_t offs; ///< standard offset from %UTC to local time [sec]
+ int32_t offs_dl; ///< additional offset if daylight saving enabled [sec]
+ TM_GPS tm_on; ///< date/time when daylight saving starts
+ TM_GPS tm_off; ///< date/time when daylight saving ends
+ TZ_NAME name[2]; ///< names without and with daylight saving enabled
+} TZDL;
+
+#define _mbg_swab_tzdl( _p ) \
+{ \
+ _mbg_swab32( &(_p)->offs ); \
+ _mbg_swab32( &(_p)->offs_dl ); \
+ _mbg_swab_tm_gps( &(_p)->tm_on ); \
+ _mbg_swab_tm_gps( &(_p)->tm_off ); \
+}
+
+
+/**
+ * @brief A flag indicating automatic computation of DST
+ *
+ * If this flag is or'ed to the year numbers in TZDL::tm_on and TZDL::tm_off
+ * then daylight saving is computed automatically year by year.
+ */
+#define DL_AUTO_FLAG 0x8000
+
+
+
+// Below there are some initializers for commonly used TZDL configurations:
+
+#define DEFAULT_TZDL_AUTO_YEAR ( 2007 | DL_AUTO_FLAG )
+
+#define DEFAULt_TZDL_OFFS_DL 3600L /**< usually DST is +1 hour */
+
+
+/**
+ * An initializer for TZDL::tm_on and TZDL::tm_off for time zones
+ * which do not observe DST.
+ */
+#define DEFAULT_TZDL_TM_ON_OFF_NO_DST \
+ { DEFAULT_TZDL_AUTO_YEAR, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+
+// Settings used with %UTC:
+
+#define TZ_INFO_UTC "UTC (Universal Time, Coordinated)"
+
+#define DEFAULT_TZDL_NAMES_UTC { "UTC ", "UTC " }
+
+#define DEFAULT_TZDL_UTC \
+{ \
+ 0L, /**< offs */ \
+ 0L, /**< offs_dl */ \
+ DEFAULT_TZDL_TM_ON_OFF_NO_DST, /**< tm_on */ \
+ DEFAULT_TZDL_TM_ON_OFF_NO_DST, /**< tm_off */ \
+ DEFAULT_TZDL_NAMES_UTC /**< name[] */ \
+}
+
+
+/**
+ * @brief An initializer for TZDL::tm_on according to the rules for Central Europe
+ */
+#define DEFAULT_TZDL_TM_ON_CET_CEST \
+ { DEFAULT_TZDL_AUTO_YEAR, 3, 25, 0, 0, 2, 0, 0, 0L, 0L, 0 }
+
+/**
+ * @brief An initializer for TZDL::tm_off according to the rules for Central Europe
+ */
+#define DEFAULT_TZDL_TM_OFF_CET_CEST \
+ { DEFAULT_TZDL_AUTO_YEAR, 10, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 }
+
+
+// Settings used with Central European Time:
+
+#define TZ_INFO_CET_CEST_EN "CET/CEST (Central Europe)"
+#define TZ_INFO_CET_CEST_DE "MEZ/MESZ (Mitteleuropa)"
+
+#define DEFAULT_TZDL_NAMES_CET_CEST_EN { "CET ", "CEST " }
+#define DEFAULT_TZDL_NAMES_CET_CEST_DE { "MEZ ", "MESZ " }
+
+#define DEFAULT_TZDL_OFFS_CET 3600L
+
+#define DEFAULT_TZDL_CET_CEST_EN \
+{ \
+ DEFAULT_TZDL_OFFS_CET, /**< offs */ \
+ DEFAULt_TZDL_OFFS_DL, /**< offs_dl */ \
+ DEFAULT_TZDL_TM_ON_CET_CEST, /**< tm_on */ \
+ DEFAULT_TZDL_TM_OFF_CET_CEST, /**< tm_off */ \
+ DEFAULT_TZDL_NAMES_CET_CEST_EN /**< name[] */ \
+}
+
+#define DEFAULT_TZDL_CET_CEST_DE \
+{ \
+ DEFAULT_TZDL_OFFS_CET, /**< offs */ \
+ DEFAULt_TZDL_OFFS_DL, /**< offs_dl */ \
+ DEFAULT_TZDL_TM_ON_CET_CEST, /**< tm_on */ \
+ DEFAULT_TZDL_TM_OFF_CET_CEST, /**< tm_off */ \
+ DEFAULT_TZDL_NAMES_CET_CEST_DE /**< name[] */ \
+}
+
+
+// The symbols below specify beginning and end of DST for
+// Easter Europe, as constituted by the European Parliament:
+
+#define DEFAULT_TZDL_TM_ON_EET_EEST \
+ { DEFAULT_TZDL_AUTO_YEAR, 3, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 }
+
+#define DEFAULT_TZDL_TM_OFF_EET_EEST \
+ { DEFAULT_TZDL_AUTO_YEAR, 10, 25, 0, 0, 4, 0, 0, 0L, 0L, 0 }
+
+
+// Settings used with Eastern European Time:
+
+#define TZ_INFO_EET_EEST_EN "EET/EEST (East Europe)"
+#define TZ_INFO_EET_EEST_DE "OEZ/OEST (Osteuropa)"
+
+#define DEFAULT_TZDL_NAMES_EET_EEST_EN { "EET ", "EEST " }
+#define DEFAULT_TZDL_NAMES_EET_EEST_DE { "OEZ ", "OESZ " }
+
+#define DEFAULT_TZDL_OFFS_EET 7200L
+
+#define DEFAULT_TZDL_EET_EEST_EN \
+{ \
+ DEFAULT_TZDL_OFFS_EET, /* offs */ \
+ DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \
+ DEFAULT_TZDL_TM_ON_EET_EEST, /* tm_on */ \
+ DEFAULT_TZDL_TM_OFF_EET_EEST, /* tm_off */ \
+ DEFAULT_TZDL_NAMES_EET_EEST_EN /* name[] */ \
+}
+
+#define DEFAULT_TZDL_EET_EEST_DE \
+{ \
+ DEFAULT_TZDL_OFFS_EET, /* offs */ \
+ DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \
+ DEFAULT_TZDL_TM_ON_EET_EEST, /* tm_on */ \
+ DEFAULT_TZDL_TM_OFF_EET_EEST, /* tm_off */ \
+ DEFAULT_TZDL_NAMES_EET_EEST_DE /* name[] */ \
+}
+
+/** @} group_tzdl */
+
+
+
+/**
+ * @brief Antenna status information
+ *
+ * The structure below reflects the status of the antenna,
+ * the times of last disconnect/reconnect, and the board's
+ * clock offset after the disconnection interval.
+ *
+ * @note ANT_INFO::status changes back to ::ANT_RECONN only
+ * after the antenna has been reconnected <b>and</b> the
+ * receiver has re-synchronized to the satellite signal.
+ * In this case ANT_INFO::delta_t reports the time offset
+ * before resynchronization, i.e. how much the internal
+ * time has drifted while the antenna was disconnected.
+ */
+typedef struct
+{
+ int16_t status; ///< current status of antenna, see ::ANT_STATUS_CODES
+ TM_GPS tm_disconn; ///< time of antenna disconnect
+ TM_GPS tm_reconn; ///< time of antenna reconnect
+ int32_t delta_t; ///< clock offs at reconn. time in 1/::RECEIVER_INFO::ticks_per_sec
+} ANT_INFO;
+
+#define _mbg_swab_ant_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->status ); \
+ _mbg_swab_tm_gps( &(_p)->tm_disconn ); \
+ _mbg_swab_tm_gps( &(_p)->tm_reconn ); \
+ _mbg_swab32( &(_p)->delta_t ); \
+}
+
+
+/**
+ * @brief Status code used with ANT_INFO::status
+ */
+enum ANT_STATUS_CODES
+{
+ ANT_INVALID, ///< No other fields valid since antenna has not yet been disconnected
+ ANT_DISCONN, ///< Antenna is disconnected, tm_reconn and delta_t not yet set
+ ANT_RECONN, ///< Antenna has been disconnect, and receiver sync. after reconnect, so all fields valid
+ N_ANT_STATUS_CODES ///< the number of known status codes
+};
+
+
+/* Defines used with ENABLE_FLAGS */
+
+#define EF_OFF 0x00 /**< outputs off until sync'd */
+
+#define EF_SERIAL_BOTH 0x03 /**< both serial ports on */
+#define EF_PULSES_BOTH 0x03 /**< both pulses P_SEC and P_MIN on */
+#define EF_FREQ_ALL 0x07 /**< all fixed freq. outputs on */
+#define EF_SYNTH 0x01 /**< synth. on */
+
+/**
+ * @brief A structure controlling when output signals are enabled
+ *
+ * The structure holds some flags which let the corresponding outputs
+ * be disabled after power-up until the receiver has synchronized
+ * (flag == ::EF_OFF, the default) or force the outputs to be enabled
+ * immediately after power-up. The fixed frequency output is hard-wired
+ * to be enabled immediately after power-up, so ENABLE_FLAGS::freq must
+ * always be set to ::EF_FREQ_ALL.
+ */
+typedef struct
+{
+ uint16_t serial; ///< ::EF_OFF or ::EF_SERIAL_BOTH
+ uint16_t pulses; ///< ::EF_OFF or ::EF_PULSES_BOTH
+ uint16_t freq; ///< always ::EF_FREQ_ALL
+ uint16_t synth; ///< ::EF_OFF or ::EF_SYNTH
+} ENABLE_FLAGS;
+
+#define _mbg_swab_enable_flags( _p ) \
+{ \
+ _mbg_swab16( &(_p)->serial ); \
+ _mbg_swab16( &(_p)->pulses ); \
+ _mbg_swab16( &(_p)->freq ); \
+ _mbg_swab16( &(_p)->synth ); \
+}
+
+
+/* A struct used to hold the settings of a serial port: */
+
+#ifndef _COM_HS_DEFINED
+ /**
+ * @brief Enumeration of handshake modes
+ */
+ enum COM_HANSHAKE_MODES { HS_NONE, HS_XONXOFF, HS_RTSCTS, N_COM_HS };
+ #define _COM_HS_DEFINED
+#endif
+
+#ifndef _COM_PARM_DEFINED
+ /**
+ * @brief A data type to configure a baud rate
+ */
+ typedef int32_t BAUD_RATE;
+
+ /**
+ * @brief Indices used to identify a parameter in the framing string
+ */
+ enum { F_DBITS, F_PRTY, F_STBITS };
+
+ /**
+ * @brief A structure to store the configuration of a serial port
+ */
+ typedef struct
+ {
+ BAUD_RATE baud_rate; ///< transmission speed, e.g. 19200L
+ char framing[4]; ///< ASCIIZ framing string, e.g. "8N1" or "7E2"
+ int16_t handshake; ///< handshake mode, yet only ::HS_NONE supported
+
+ } COM_PARM;
+
+ #define _COM_PARM_DEFINED
+#endif
+
+#define _mbg_swab_baud_rate( _p ) _mbg_swab32( _p )
+
+#define _mbg_swab_com_parm( _p ) \
+{ \
+ _mbg_swab_baud_rate( &(_p)->baud_rate ); \
+ _mbg_swab16( &(_p)->handshake ); \
+}
+
+
+/**
+ * @brief Indices of any supported serial port baud rates
+ *
+ * @note Most clock models and/or serial ports don't support all defined baud rates.
+ */
+enum MBG_BAUD_RATE_CODES
+{
+ MBG_BAUD_RATE_300,
+ MBG_BAUD_RATE_600,
+ MBG_BAUD_RATE_1200,
+ MBG_BAUD_RATE_2400,
+ MBG_BAUD_RATE_4800,
+ MBG_BAUD_RATE_9600,
+ MBG_BAUD_RATE_19200,
+ MBG_BAUD_RATE_38400,
+ N_MBG_BAUD_RATES /**< the number of supported baud rates */
+};
+
+/*
+ * An initializer for a table of baud rate values.
+ * The values must correspond to the enumeration above.
+ */
+#define MBG_BAUD_RATES \
+{ \
+ 300L, \
+ 600L, \
+ 1200L, \
+ 2400L, \
+ 4800L, \
+ 9600L, \
+ 19200L, \
+ 38400L \
+}
+
+/*
+ * An initializer for a table of baud rate strings.
+ * The values must correspond to the enumeration above.
+ */
+#define MBG_BAUD_STRS \
+{ \
+ "300", \
+ "600", \
+ "1200", \
+ "2400", \
+ "4800", \
+ "9600", \
+ "19200", \
+ "38400" \
+}
+
+/*
+ * The bit masks below can be used to determine which baud rates
+ * are supported by a serial port. This may vary between
+ * different ports of the same device since different
+ * types of UART are used which must not necessarily support
+ * each baud rate:
+ */
+#define MBG_PORT_HAS_300 ( 1UL << MBG_BAUD_RATE_300 )
+#define MBG_PORT_HAS_600 ( 1UL << MBG_BAUD_RATE_600 )
+#define MBG_PORT_HAS_1200 ( 1UL << MBG_BAUD_RATE_1200 )
+#define MBG_PORT_HAS_2400 ( 1UL << MBG_BAUD_RATE_2400 )
+#define MBG_PORT_HAS_4800 ( 1UL << MBG_BAUD_RATE_4800 )
+#define MBG_PORT_HAS_9600 ( 1UL << MBG_BAUD_RATE_9600 )
+#define MBG_PORT_HAS_19200 ( 1UL << MBG_BAUD_RATE_19200 )
+#define MBG_PORT_HAS_38400 ( 1UL << MBG_BAUD_RATE_38400 )
+
+
+/**
+ * @brief Indices of any supported serial port framings.
+ *
+ * @note Most clock models and/or serial ports don't support all defined framing types.
+ */
+enum MBG_FRAMING_CODES
+{
+ MBG_FRAMING_7N2,
+ MBG_FRAMING_7E1,
+ MBG_FRAMING_7E2,
+ MBG_FRAMING_8N1,
+ MBG_FRAMING_8N2,
+ MBG_FRAMING_8E1,
+ MBG_FRAMING_7O1,
+ MBG_FRAMING_7O2,
+ MBG_FRAMING_8O1,
+ MBG_FRAMING_8E2, /**< @note: Most serial ports don't support this! */
+ N_MBG_FRAMINGS /**< the number of supported framings */
+};
+
+/*
+ * An initializer for a table of framing strings.
+ * The values must correspond to the enumeration above.
+ */
+#define MBG_FRAMING_STRS \
+{ \
+ "7N2", \
+ "7E1", \
+ "7E2", \
+ "8N1", \
+ "8N2", \
+ "8E1", \
+ "7O1", \
+ "7O2", \
+ "8O1", \
+ "8E2" \
+}
+
+/*
+ * The bit masks below can be used to determine which framings
+ * are supported by a serial port. This may vary between
+ * different ports of the same device since different
+ * types of UART are used which must not necessarily support
+ * each framing type:
+ */
+#define MBG_PORT_HAS_7N2 ( 1UL << MBG_FRAMING_7N2 )
+#define MBG_PORT_HAS_7E1 ( 1UL << MBG_FRAMING_7E1 )
+#define MBG_PORT_HAS_7E2 ( 1UL << MBG_FRAMING_7E2 )
+#define MBG_PORT_HAS_8N1 ( 1UL << MBG_FRAMING_8N1 )
+#define MBG_PORT_HAS_8N2 ( 1UL << MBG_FRAMING_8N2 )
+#define MBG_PORT_HAS_8E1 ( 1UL << MBG_FRAMING_8E1 )
+#define MBG_PORT_HAS_7O1 ( 1UL << MBG_FRAMING_7O1 )
+#define MBG_PORT_HAS_7O2 ( 1UL << MBG_FRAMING_7O2 )
+#define MBG_PORT_HAS_8O1 ( 1UL << MBG_FRAMING_8O1 )
+#define MBG_PORT_HAS_8E2 ( 1UL << MBG_FRAMING_8E2 )
+
+
+// Default port settings to be used
+// with the binary protocol
+#define MBG_DEFAULT_BAUDRATE 19200L
+#define MBG_DEFAULT_FRAMING "8N1"
+
+
+
+/*
+ * By default, the baud rates and framings below
+ * are supported by the UARTs integrated into
+ * the C166 microcontroller:
+ */
+#define DEFAULT_GPS_BAUD_RATES_C166 \
+( \
+ MBG_PORT_HAS_300 | \
+ MBG_PORT_HAS_600 | \
+ MBG_PORT_HAS_1200 | \
+ MBG_PORT_HAS_2400 | \
+ MBG_PORT_HAS_4800 | \
+ MBG_PORT_HAS_9600 | \
+ MBG_PORT_HAS_19200 \
+)
+
+#define DEFAULT_GPS_FRAMINGS_C166 \
+( \
+ MBG_PORT_HAS_7N2 | \
+ MBG_PORT_HAS_7E1 | \
+ MBG_PORT_HAS_7E2 | \
+ MBG_PORT_HAS_8N1 | \
+ MBG_PORT_HAS_8N2 | \
+ MBG_PORT_HAS_8E1 \
+)
+
+
+/*
+ * By default, the baud rates and framings below
+ * are supported by the UARTs integrated into
+ * the GP2021 chipset:
+ */
+#define DEFAULT_GPS_BAUD_RATES_GP2021 \
+( \
+ MBG_PORT_HAS_300 | \
+ MBG_PORT_HAS_600 | \
+ MBG_PORT_HAS_1200 | \
+ MBG_PORT_HAS_2400 | \
+ MBG_PORT_HAS_4800 | \
+ MBG_PORT_HAS_9600 | \
+ MBG_PORT_HAS_19200 \
+)
+
+#define DEFAULT_GPS_FRAMINGS_GP2021 \
+( \
+ MBG_PORT_HAS_7N2 | \
+ MBG_PORT_HAS_7E2 | \
+ MBG_PORT_HAS_8N1 | \
+ MBG_PORT_HAS_8E1 | \
+ MBG_PORT_HAS_8O1 \
+)
+
+
+/**
+ * @brief Configuration settings of a serial port
+ *
+ * @note This should be used preferably instead of
+ * ::PORT_PARM, which is deprecated.
+ */
+typedef struct
+{
+ COM_PARM parm; ///< transmission speed, framing, etc.
+ uint8_t mode; ///< string mode, see ::STR_MODES
+ uint8_t str_type; ///< index of the supported time string formats, see ::STR_TYPE_INFO_IDX
+ uint32_t flags; ///< @see COM_CFG_STATUS_BITS
+} PORT_SETTINGS;
+
+#define _mbg_swab_port_settings( _p ) \
+{ \
+ _mbg_swab_com_parm( &(_p)->parm ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Flag bits used to marks individual ::PORT_SETTINGS fields
+ *
+ * These definitions can be used to mark specific fields of a
+ * PORT_SETTINGS structure, e.g. which fields have changed when
+ * editing, or which fields have settings which are not valid.
+ */
+enum MBG_COM_CFG_STATUS_BITS
+{
+ MBG_PS_BIT_BAUD_RATE_OVR_SW, ///< Baud rate index exceeds num supp by driver SW
+ MBG_PS_BIT_BAUD_RATE_OVR_DEV, ///< Baud rate index exceeds num supp by device
+ MBG_PS_BIT_BAUD_RATE, ///< Baud rate not supp by given port
+ MBG_PS_BIT_FRAMING_OVR_SW, ///< Framing index exceeds num supp by driver SW
+ MBG_PS_BIT_FRAMING_OVR_DEV, ///< Framing index exceeds num supp by device
+ MBG_PS_BIT_FRAMING, ///< Framing not supp by given port
+ MBG_PS_BIT_HS_OVR_SW, ///< Handshake index exceeds num supp by driver SW
+ MBG_PS_BIT_HS, ///< Handshake mode not supp by given port
+ MBG_PS_BIT_STR_TYPE_OVR_SW, ///< String type index exceeds num supp by driver SW
+ MBG_PS_BIT_STR_TYPE_OVR_DEV, ///< String type index exceeds num supp by device
+ MBG_PS_BIT_STR_TYPE, ///< String type not supp by given port
+ MBG_PS_BIT_STR_MODE_OVR_SW, ///< String mode index exceeds num supp by driver SW
+ MBG_PS_BIT_STR_MODE_OVR_DEV, ///< String mode index exceeds num supp by device
+ MBG_PS_BIT_STR_MODE, ///< String mode not supp by given port and string type
+ MBG_PS_BIT_FLAGS_OVR_SW, ///< Flags not supp by driver SW
+ MBG_PS_BIT_FLAGS, ///< Flags not supp by device
+ N_MBG_PS_BIT
+};
+
+#define MBG_PS_MSK_BAUD_RATE_OVR_SW ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_SW )
+#define MBG_PS_MSK_BAUD_RATE_OVR_DEV ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_DEV )
+#define MBG_PS_MSK_BAUD_RATE ( 1UL << MBG_PS_BIT_BAUD_RATE )
+#define MBG_PS_MSK_FRAMING_OVR_SW ( 1UL << MBG_PS_BIT_FRAMING_OVR_SW )
+#define MBG_PS_MSK_FRAMING_OVR_DEV ( 1UL << MBG_PS_BIT_FRAMING_OVR_DEV )
+#define MBG_PS_MSK_FRAMING ( 1UL << MBG_PS_BIT_FRAMING )
+#define MBG_PS_MSK_HS_OVR_SW ( 1UL << MBG_PS_BIT_HS_OVR_SW )
+#define MBG_PS_MSK_HS ( 1UL << MBG_PS_BIT_HS )
+#define MBG_PS_MSK_STR_TYPE_OVR_SW ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_SW )
+#define MBG_PS_MSK_STR_TYPE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_DEV )
+#define MBG_PS_MSK_STR_TYPE ( 1UL << MBG_PS_BIT_STR_TYPE )
+#define MBG_PS_MSK_STR_MODE_OVR_SW ( 1UL << MBG_PS_BIT_STR_MODE_OVR_SW )
+#define MBG_PS_MSK_STR_MODE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_MODE_OVR_DEV )
+#define MBG_PS_MSK_STR_MODE ( 1UL << MBG_PS_BIT_STR_MODE )
+#define MBG_PS_MSK_FLAGS_OVR_SW ( 1UL << MBG_PS_BIT_FLAGS_OVR_SW )
+#define MBG_PS_MSK_FLAGS ( 1UL << MBG_PS_BIT_FLAGS )
+
+
+
+/**
+ * @brief Configuration settings of a specific serial port
+ *
+ * This structure should be sent to a device to configure
+ * a specific serial port. The number of supported ports
+ * is RECEIVER_INFO::n_com_port.
+ *
+ * @note The ::PORT_INFO_IDX structure should be read from
+ * a device to retrieve the current settings and capabilities.
+ *
+ * @see STR_TYPE_INFO
+ */
+typedef struct
+{
+ uint16_t idx; ///< port index, 0..RECEIVER_INFO::n_com_port - 1
+ PORT_SETTINGS port_settings;
+} PORT_SETTINGS_IDX;
+
+#define _mbg_swab_port_settings_idx( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_port_settings( &(_p)->port_settings ); \
+}
+
+
+/**
+ * @brief Current settings and general capabilities of a serial port
+ *
+ * @note This structure should be read from a device to retrieve
+ * the current settings of a serial port plus its capabilities,
+ * e.g. supported baud rates, supported string formats, etc.
+ *
+ * @see STR_TYPE_INFO
+ */
+typedef struct
+{
+ PORT_SETTINGS port_settings; ///< current configuration of the port
+ uint32_t supp_baud_rates; ///< bit mask of baud rates supp. by this port, see ::MBG_BAUD_RATE_CODES
+ uint32_t supp_framings; ///< bit mask of framings supp. by this port, see ::MBG_FRAMING_CODES
+ uint32_t supp_str_types; ///< bit mask of string types supp. by this port, i.e. bit 0 set if str_type[0] is supp.
+ uint32_t reserved; ///< reserved for future use, currently always 0
+ uint32_t flags; ///< @see COM_CFG_STATUS_BITS
+} PORT_INFO;
+
+#define _mbg_swab_port_info( _p ) \
+{ \
+ _mbg_swab_port_settings( &(_p)->port_settings ); \
+ _mbg_swab32( &(_p)->supp_baud_rates ); \
+ _mbg_swab32( &(_p)->supp_framings ); \
+ _mbg_swab32( &(_p)->supp_str_types ); \
+ _mbg_swab32( &(_p)->reserved ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Flags used with PORT_SETTINGS::flags and PORT_INFO::flags
+ */
+enum COM_CFG_STATUS_BITS
+{
+ PORT_FLAG_BIT_PORT_INVISIBLE, ///< port is used internally and should not be displayed by config apps
+ N_PORT_FLAGS ///< the number of defined bits
+};
+
+#define PORT_FLAG_PORT_INVISIBLE ( 1UL << PORT_FLAG_BIT_PORT_INVISIBLE )
+
+
+
+/**
+ * @brief Current settings and general capabilities of a specific serial port
+ *
+ * This structure should be read from the device to retrieve the
+ * current settings of a specific serial port plus its capabilities,
+ * e.g. supported baud rates, supported string formats, etc.
+ * The number of supported ports is RECEIVER_INFO::n_com_port.
+ *
+ * @note The ::PORT_SETTINGS_IDX structure should be send back to
+ * the device to configure the specified serial port.
+ */
+typedef struct
+{
+ uint16_t idx; ///< port index, 0..RECEIVER_INFO::n_com_port - 1
+ PORT_INFO port_info;
+} PORT_INFO_IDX;
+
+#define _mbg_swab_port_info_idx( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_port_info( &(_p)->port_info ); \
+}
+
+
+/**
+ * @brief Information on a supported string format
+ *
+ * Information includes the name of the string format, which
+ * transmission modes are supported, etc.
+ *
+ * The number of string types, and which string types are supported
+ * depends on the device type and firmware version.
+ *
+ * @note The structure ::STR_TYPE_INFO_IDX should be read repeatedly
+ * to retrieve all supported string types.
+ */
+typedef struct
+{
+ uint32_t supp_modes; ///< bit mask of modes supp. for this string type
+ char long_name[23]; ///< long name of the string format
+ char short_name[11]; ///< short name of the string format
+ uint16_t flags; ///< reserved, currently always 0
+} STR_TYPE_INFO;
+
+#define _mbg_swab_str_type_info( _p ) \
+{ \
+ _mbg_swab32( &(_p)->supp_modes ); \
+ _mbg_swab16( &(_p)->flags ); \
+}
+
+
+
+/**
+ * @brief Information on a specific supported string format
+ *
+ * This structure should be read from a device to retrieve information
+ * on a specific supported time string type from an array of supported
+ * string types. The number of supported string types is returned
+ * in RECEIVER_INFO::n_str_type.
+ *
+ * A selected index number can be saved in PORT_SETTINGS::str_type to
+ * configure the selected string type for the specific serial port.
+ */
+typedef struct
+{
+ uint16_t idx; ///< string type index, 0..RECEIVER_INFO::n_str_type - 1
+ STR_TYPE_INFO str_type_info;
+} STR_TYPE_INFO_IDX;
+
+#define _mbg_swab_str_type_info_idx( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_str_type_info( &(_p)->str_type_info ); \
+}
+
+
+/**
+ * @brief Modes supported for time string transmission
+ *
+ * This determines e.g. at which point in time a string starts
+ * to be transmitted via the serial port.
+ */
+enum STR_MODES
+{
+ STR_ON_REQ, ///< transmission on request by received '?' only
+ STR_PER_SEC, ///< transmission automatically if second changes
+ STR_PER_MIN, ///< transmission automatically if minute changes
+ STR_AUTO, ///< transmission automatically if required, e.g. on capture event
+ STR_ON_REQ_SEC, ///< transmission if second changes and a request has been received before
+ N_STR_MODE ///< the number of known modes
+};
+
+
+#define DEFAULT_SHORT_MODE_NAMES \
+{ \
+ "'?'", \
+ "1 sec", \
+ "1 min", \
+ "auto", \
+ "'?' sec" \
+}
+
+
+/*
+ * Default initializers for English mode string names. Initializers
+ * for multi-language strings can be found in pcpslstr.h.
+ */
+#define ENG_MODE_NAME_STR_ON_REQ "on request '?' only"
+#define ENG_MODE_NAME_STR_PER_SEC "per second"
+#define ENG_MODE_NAME_STR_PER_MIN "per minute"
+#define ENG_MODE_NAME_STR_AUTO "automatically"
+#define ENG_MODE_NAME_STR_ON_REQ_SEC "sec after request"
+
+#define DEFAULT_ENG_MODE_NAMES \
+{ \
+ ENG_MODE_NAME_STR_ON_REQ, \
+ ENG_MODE_NAME_STR_PER_SEC, \
+ ENG_MODE_NAME_STR_PER_MIN, \
+ ENG_MODE_NAME_STR_AUTO, \
+ ENG_MODE_NAME_STR_ON_REQ_SEC \
+}
+
+/*
+ * The definitions below are used to set up bit masks
+ * which restrict the modes which can be used with
+ * a given string type:
+ */
+#define MSK_STR_ON_REQ ( 1UL << STR_ON_REQ )
+#define MSK_STR_PER_SEC ( 1UL << STR_PER_SEC )
+#define MSK_STR_PER_MIN ( 1UL << STR_PER_MIN )
+#define MSK_STR_AUTO ( 1UL << STR_AUTO )
+#define MSK_STR_ON_REQ_SEC ( 1UL << STR_ON_REQ_SEC )
+
+
+/*
+ * The modes below are supported by most string types:
+ */
+#define DEFAULT_STR_MODES \
+( \
+ MSK_STR_ON_REQ | \
+ MSK_STR_PER_SEC | \
+ MSK_STR_PER_MIN \
+)
+
+
+/*
+ * The modes below can be used with the capture string:
+ */
+#define DEFAULT_STR_MODES_UCAP \
+( \
+ MSK_STR_ON_REQ | \
+ MSK_STR_AUTO \
+)
+
+
+
+/**
+ * The number of serial ports which are at least available
+ * even with very old GPS receiver models
+ */
+#define DEFAULT_N_COM 2
+
+/*
+ * By default that's also the number of ports
+ * currently available:
+ */
+#ifndef N_COM
+ #define N_COM DEFAULT_N_COM
+#endif
+
+/**
+ * @brief A The structure used to store the configuration of both serial ports
+ *
+ * @deprecated This structure is deprecated, ::PORT_SETTINGS and related structures
+ * should be used instead, if supported by the device.
+ */
+typedef struct
+{
+ COM_PARM com[DEFAULT_N_COM]; /**< COM0 and COM1 settings */
+ uint8_t mode[DEFAULT_N_COM]; /**< COM0 and COM1 output mode */
+} PORT_PARM;
+
+#define _mbg_swab_port_parm( _p ) \
+{ \
+ int i; \
+ for ( i = 0; i < DEFAULT_N_COM; i++ ) \
+ { \
+ _mbg_swab_com_parm( &(_p)->com[i] ); \
+ /* no need to swap mode byte */ \
+ } \
+}
+
+
+/*
+ * The codes below were used with the obsolete
+ * PORT_PARM.mode above. They are defined for
+ * compatibility with older devices only:
+ */
+enum
+{
+ /* STR_ON_REQ, defined above */
+ /* STR_PER_SEC, defined above */
+ /* STR_PER_MIN, defined above */
+ N_STR_MODE_0 = STR_AUTO, /* COM0 and COM1 */
+ STR_UCAP = N_STR_MODE_0,
+ STR_UCAP_REQ,
+ N_STR_MODE_1 /* COM1 only */
+};
+
+
+
+/**
+ @defgroup group_icode IRIG codes
+
+ The following definitions are used to configure an optional
+ on-board IRIG input or output. Which frame types are supported
+ by a device depends on the device type, and may eventually
+ depend on the device's firmware version.
+
+ All IRIG frames transport the day-of-year number plus the time-of-day,
+ and include a control field segment which can transport user defined
+ information.
+
+ Some newer IRIG frames are compatible with older frame types but support
+ well defined extensions like the year number, local time offset, DST status,
+ etc., in the control fields:
+
+ - Supported IRIG signal code types:
+ - \b A002: 1000 bps, DCLS, time-of-year
+ - \b A003: 1000 bps, DCLS, time-of-year, SBS
+ - \b A132: 1000 bps, 10 kHz carrier, time-of-year
+ - \b A133: 1000 bps, 10 kHz carrier, time-of-year, SBS
+ - \b B002: 100 bps, DCLS, time-of-year
+ - \b B003: 100 bps, DCLS, time-of-year, SBS
+ - \b B122: 100 bps, 1 kHz carrier, time-of-year
+ - \b B123: 100 bps, 1 kHz carrier, time-of-year, SBS
+ - \b B006: 100 bps, DCLS, complete date
+ - \b B007: 100 bps, DCLS, complete date, SBS
+ - \b B126: 100 bps, 1 kHz carrier, complete date
+ - \b B127: 100 bps, 1 kHz carrier, complete date, SBS
+ - \b B220/1344: 100 bps, DCLS, manchester encoded, IEEE1344 extensions
+ - \b B222: 100 bps, DCLS, manchester encoded, time-of-year
+ - \b B223: 100 bps, DCLS, manchester encoded, time-of-year, SBS
+ - \b G002: 10 kbps, DCLS, time-of-year
+ - \b G142: 10 kbps, 100 kHz carrier, time-of-year
+ - \b G006: 10 kbps, DCLS, complete date
+ - \b G146: 10 kbps, 100 kHz carrier, complete date
+ - \b AFNOR: 100 bps, 1 kHz carrier, SBS, complete date
+ - <b> AFNOR DC:</b> 100 bps, DCLS, SBS, complete date
+ - \b IEEE1344: 100 bps, 1 kHz carrier, time-of-year, SBS, IEEE1344 extensions (B120)
+ - <b> IEEE1344 DC:</b> 100 bps, DCLS, time-of-year, SBS, IEEE1344 extensions (B000)
+ - \b C37.118: like IEEE1344, but %UTC offset with reversed sign
+ - \b C37.118 DC: like IEEE1344 DC, but %UTC offset with reversed sign
+
+ - time-of-year: day-of-year, hours, minutes, seconds
+ - complete date: time-of-year plus year number
+ - SBS: straight binary seconds, second-of-day
+
+ AFNOR codes are based on the french standard AFNOR NF S87-500
+
+ IEEE1344 codes are defined in IEEE standard 1344-1995. The code frame is compatible
+ with B002/B122 but provides some well defined extensions in the control field which
+ include a quality indicator (time figure of merit, TFOM), year number, DST and leap
+ second status, and local time offset from %UTC.
+
+ C37.118 codes are defined in IEEE standard C37.118-2005 which includes a revised version
+ of the IEEE 1344 standard from 1995. These codes provide the same extensions as IEEE 1344
+ but unfortunately define the %UTC offset with reversed sign.
+
+ @note There are 3rd party IRIG devices out there which apply the %UTC offset as specified
+ in C37.118, but claim to be compatible with IEEE 1344. So if local time is transmitted
+ by the IRIG signal then care must be taken that the %UTC offset is evaluated by the IRIG
+ receiver in the same way as computed by the IRIG generator. Otherwise the %UTC
+ time computed by the receiver may be <b>wrong</b>.
+ @{
+ */
+
+/**
+ * @brief Known IRIG TX code formats
+ *
+ * Definitions used with IRIG transmitters which usually output both
+ * the unmodulated and the modulated IRIG signals at the same time.
+ */
+enum ICODE_TX_CODES
+{
+ ICODE_TX_B002_B122,
+ ICODE_TX_B003_B123,
+ ICODE_TX_A002_A132,
+ ICODE_TX_A003_A133,
+ ICODE_TX_AFNOR,
+ ICODE_TX_IEEE1344,
+ ICODE_TX_B2201344, ///< DCLS only
+ ICODE_TX_B222, ///< DCLS only
+ ICODE_TX_B223, ///< DCLS only
+ ICODE_TX_B006_B126,
+ ICODE_TX_B007_B127,
+ ICODE_TX_G002_G142,
+ ICODE_TX_G006_G146,
+ ICODE_TX_C37118,
+ ICODE_TX_TXC101,
+ ICODE_TX_E002_E112,
+ ICODE_TX_NASA36,
+ N_ICODE_TX ///< number of known codes
+};
+
+
+/**
+ * Initializers for format name strings.
+ */
+#define DEFAULT_ICODE_TX_NAMES \
+{ \
+ "B002+B122", \
+ "B003+B123", \
+ "A002+A132", \
+ "A003+A133", \
+ "AFNOR NF S87-500", \
+ "IEEE1344", \
+ "B220(1344) DCLS", \
+ "B222 DCLS", \
+ "B223 DCLS", \
+ "B006+B126", \
+ "B007+B127", \
+ "G002+G142", \
+ "G006+G146", \
+ "C37.118", \
+ "TXC-101 DTR-6", \
+ "E002+E112", \
+ "NASA 36" \
+}
+
+/**
+ * Initializers for short name strings which must not
+ * be longer than 10 printable characters.
+ */
+#define DEFAULT_ICODE_TX_NAMES_SHORT \
+{ \
+ "B002+B122", \
+ "B003+B123", \
+ "A002+A132", \
+ "A003+A133", \
+ "AFNOR NF-S", \
+ "IEEE1344", \
+ "B220/1344", \
+ "B222 DC", \
+ "B223 DC", \
+ "B006+B126", \
+ "B007+B127", \
+ "G002+G142", \
+ "G006+G146", \
+ "C37.118", \
+ "TXC-101", \
+ "E002+E112", \
+ "NASA 36" \
+}
+
+
+/**
+ * Initializers for English format description strings.
+ */
+#define DEFAULT_ICODE_TX_DESCRIPTIONS_ENG \
+{ \
+ "100 bps, DCLS or 1 kHz carrier", \
+ "100 bps, DCLS or 1 kHz carrier, SBS", \
+ "1000 bps, DCLS or 10 kHz carrier", \
+ "1000 bps, DCLS or 10 kHz carrier, SBS", \
+ "100 bps, DCLS or 1 kHz carrier, SBS, complete date", \
+ "100 bps, DCLS or 1 kHz carrier, SBS, complete date, time zone info", \
+ "100 bps, Manchester enc., DCLS only, SBS, complete date, time zone info", \
+ "100 bps, Manchester enc., DCLS only", \
+ "100 bps, Manchester enc., DCLS only, SBS", \
+ "100 bps, DCLS or 1 kHz carrier, complete date", \
+ "100 bps, DCLS or 1 kHz carrier, complete date, SBS", \
+ "10 kbps, DCLS or 100 kHz carrier", \
+ "10 kbps, DCLS or 100 kHz carrier, complete date", \
+ "like IEEE1344, but UTC offset with reversed sign", \
+ "code from TV time sync device TXC-101 DTR-6", \
+ "10 bps, DCLS or 100 Hz carrier", \
+ "100 bps, DCLS or 1 kHz carrier" \
+}
+
+/*
+ * The definitions below are used to set up bit masks
+ * which restrict the IRIG formats which are supported
+ * by a given IRIG transmitter device:
+ */
+#define MSK_ICODE_TX_B002_B122 ( 1UL << ICODE_TX_B002_B122 )
+#define MSK_ICODE_TX_B003_B123 ( 1UL << ICODE_TX_B003_B123 )
+#define MSK_ICODE_TX_A002_A132 ( 1UL << ICODE_TX_A002_A132 )
+#define MSK_ICODE_TX_A003_A133 ( 1UL << ICODE_TX_A003_A133 )
+#define MSK_ICODE_TX_AFNOR ( 1UL << ICODE_TX_AFNOR )
+#define MSK_ICODE_TX_IEEE1344 ( 1UL << ICODE_TX_IEEE1344 )
+#define MSK_ICODE_TX_B2201344 ( 1UL << ICODE_TX_B2201344 )
+#define MSK_ICODE_TX_B222 ( 1UL << ICODE_TX_B222 )
+#define MSK_ICODE_TX_B223 ( 1UL << ICODE_TX_B223 )
+#define MSK_ICODE_TX_B006_B126 ( 1UL << ICODE_TX_B006_B126 )
+#define MSK_ICODE_TX_B007_B127 ( 1UL << ICODE_TX_B007_B127 )
+#define MSK_ICODE_TX_G002_G142 ( 1UL << ICODE_TX_G002_G142 )
+#define MSK_ICODE_TX_G006_G146 ( 1UL << ICODE_TX_G006_G146 )
+#define MSK_ICODE_TX_C37118 ( 1UL << ICODE_TX_C37118 )
+#define MSK_ICODE_TX_TXC101 ( 1UL << ICODE_TX_TXC101 )
+#define MSK_ICODE_TX_E002_E112 ( 1UL << ICODE_TX_E002_E112 )
+#define MSK_ICODE_TX_NASA36 ( 1UL << ICODE_TX_NASA36 )
+
+/**
+ * A mask of IRIG formats with manchester encoded DC output:
+ */
+#define MSK_ICODE_TX_DC_MANCH \
+( \
+ MSK_ICODE_TX_B2201344 | \
+ MSK_ICODE_TX_B222 | \
+ MSK_ICODE_TX_B223 \
+)
+
+/**
+ * A mask of IRIG formats with 100 Hz carrier:
+ */
+#define MSK_ICODE_TX_100HZ \
+( \
+ MSK_ICODE_TX_E002_E112 \
+)
+
+/**
+ * A mask of IRIG formats with 1 kHz carrier:
+ */
+#define MSK_ICODE_TX_1KHZ \
+( \
+ MSK_ICODE_TX_B002_B122 | \
+ MSK_ICODE_TX_B003_B123 | \
+ MSK_ICODE_TX_AFNOR | \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_B2201344 | \
+ MSK_ICODE_TX_B222 | \
+ MSK_ICODE_TX_B223 | \
+ MSK_ICODE_TX_B006_B126 | \
+ MSK_ICODE_TX_B007_B127 | \
+ MSK_ICODE_TX_C37118 | \
+ MSK_ICODE_TX_NASA36 \
+)
+
+/**
+ * A mask of IRIG formats with 10 kHz carrier:
+ */
+#define MSK_ICODE_TX_10KHZ \
+( \
+ MSK_ICODE_TX_A002_A132 | \
+ MSK_ICODE_TX_A003_A133 \
+)
+
+/**
+ * A mask of IRIG formats with 100 kHz carrier:
+ */
+#define MSK_ICODE_TX_100KHZ \
+( \
+ MSK_ICODE_TX_G002_G142 | \
+ MSK_ICODE_TX_G006_G146 \
+)
+
+/**
+ * A mask of IRIG formats with 10 bps data rate:
+ */
+#define MSK_ICODE_TX_10BPS \
+( \
+ MSK_ICODE_TX_E002_E112 \
+)
+
+/**
+ * A mask of IRIG formats with 100 bps data rate:
+ */
+#define MSK_ICODE_TX_100BPS \
+( \
+ MSK_ICODE_TX_B002_B122 | \
+ MSK_ICODE_TX_B003_B123 | \
+ MSK_ICODE_TX_AFNOR | \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_B006_B126 | \
+ MSK_ICODE_TX_B007_B127 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * A mask of IRIG formats with 1000 bps data rate:
+ */
+#define MSK_ICODE_TX_1000BPS \
+( \
+ MSK_ICODE_TX_A002_A132 | \
+ MSK_ICODE_TX_A003_A133 \
+)
+
+/**
+ * A mask of IRIG formats with 10 kbps data rate:
+ */
+#define MSK_ICODE_TX_10000BPS \
+( \
+ MSK_ICODE_TX_G002_G142 | \
+ MSK_ICODE_TX_G006_G146 \
+)
+
+/**
+ * A mask of IRIG formats which support TFOM:
+ */
+#define MSK_ICODE_TX_HAS_TFOM \
+( \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * A mask of IRIG formats which support time zone information:
+ */
+#define MSK_ICODE_TX_HAS_TZI \
+( \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * The default mask of IRIG formats supported by
+ * IRIG transmitters:
+ */
+#if !defined( SUPP_MSK_ICODE_TX )
+ #define SUPP_MSK_ICODE_TX \
+ ( \
+ MSK_ICODE_TX_B002_B122 | \
+ MSK_ICODE_TX_B003_B123 | \
+ MSK_ICODE_TX_A002_A132 | \
+ MSK_ICODE_TX_A003_A133 | \
+ MSK_ICODE_TX_AFNOR \
+ )
+#endif
+
+
+
+/**
+ * @brief Known IRIG RX code formats
+ *
+ * Definitions used with IRIG receivers which decode
+ * two similar IRIG codes (with or without SBS)
+ * at the same time.
+ */
+enum ICODE_RX_CODES
+{
+ ICODE_RX_B122_B123, ///< modulated
+ ICODE_RX_A132_A133, ///< modulated
+ ICODE_RX_B002_B003, ///< DCLS
+ ICODE_RX_A002_A003, ///< DCLS
+ ICODE_RX_AFNOR, ///< modulated
+ ICODE_RX_AFNOR_DC, ///< DCLS
+ ICODE_RX_IEEE1344, ///< modulated
+ ICODE_RX_IEEE1344_DC, ///< DCLS
+ ICODE_RX_B126_B127, ///< modulated
+ ICODE_RX_B006_B007, ///< DCLS
+ ICODE_RX_G142_G146, ///< modulated
+ ICODE_RX_G002_G006, ///< DCLS
+ ICODE_RX_C37118, ///< modulated
+ ICODE_RX_C37118_DC, ///< DCLS
+ ICODE_RX_TXC101, ///< modulated
+ ICODE_RX_TXC101_DC, ///< DCLS
+ ICODE_RX_E112, ///< modulated
+ ICODE_RX_E002, ///< DCLS
+ ICODE_RX_NASA36, ///< modulated
+ ICODE_RX_NASA36_DC, ///< DCLS
+ N_ICODE_RX ///< the number of known codes
+};
+
+/**
+ * Initializers for format name strings.
+ */
+#define DEFAULT_ICODE_RX_NAMES \
+{ \
+ "B122/B123", \
+ "A132/A133", \
+ "B002/B003 (DCLS)", \
+ "A002/A003 (DCLS)", \
+ "AFNOR NF S87-500", \
+ "AFNOR NF S87-500 (DCLS)", \
+ "IEEE1344", \
+ "IEEE1344 (DCLS)", \
+ "B126/B127", \
+ "B006/B007 (DCLS)", \
+ "G142/G146", \
+ "G002/G006 (DCLS)", \
+ "C37.118", \
+ "C37.118 (DCLS)", \
+ "TXC-101 DTR-6", \
+ "TXC-101 DTR-6 (DCLS)", \
+ "E112", \
+ "E002 (DCLS)", \
+ "NASA-36", \
+ "NASA-36 (DCLS)" \
+}
+
+/**
+ * Initializers for short name strings which must not
+ * be longer than 11 printable characters.
+ */
+#define DEFAULT_ICODE_RX_NAMES_SHORT \
+{ \
+ "B122/B123", \
+ "A132/A133", \
+ "B002/B003", \
+ "A002/A003", \
+ "AFNOR NF-S", \
+ "AFNOR DC", \
+ "IEEE1344", \
+ "IEEE1344 DC", \
+ "B126/B127", \
+ "B006/B007", \
+ "G142/G146", \
+ "G002/G006", \
+ "C37.118", \
+ "C37.118 DC", \
+ "TXC-101", \
+ "TXC-101 DC", \
+ "E112", \
+ "E002 DC", \
+ "NASA-36", \
+ "NASA-36 DC" \
+}
+
+
+/**
+ * Initializers for English format description strings.
+ */
+#define DEFAULT_ICODE_RX_DESCRIPTIONS_ENG \
+{ \
+ "100 bps, 1 kHz carrier, SBS optionally", \
+ "1000 bps, 10 kHz carrier, SBS optionally", \
+ "100 bps, DCLS, SBS optionally", \
+ "1000 bps, DCLS, SBS optionally", \
+ "100 bps, 1 kHz carrier, SBS, complete date", \
+ "100 bps, DCLS, SBS, complete date", \
+ "100 bps, 1 kHz carrier, SBS, time zone info", \
+ "100 bps, DCLS, SBS, time zone info", \
+ "100 bps, 1 kHz carrier, complete date, SBS optionally", \
+ "100 bps, DCLS, complete date, SBS optionally", \
+ "10 kbps, 100 kHz carrier, complete date optionally", \
+ "10 kbps, DCLS, complete date optionally", \
+ "like IEEE1344, but UTC offset with reversed sign", \
+ "like IEEE1344 DC, but UTC offset with reversed sign", \
+ "code from TV time sync device TXC-101 DTR-6", \
+ "DC code from TV time sync device TXC-101 DTR-6", \
+ "10 bps, 100 Hz carrier", \
+ "10 bps, DCLS", \
+ "100 bps, 1 kHz carrier", \
+ "100 bps, DCLS" \
+}
+
+/*
+ * Bit masks corresponding to the enumeration above:
+ */
+#define MSK_ICODE_RX_B122_B123 ( 1UL << ICODE_RX_B122_B123 )
+#define MSK_ICODE_RX_A132_A133 ( 1UL << ICODE_RX_A132_A133 )
+#define MSK_ICODE_RX_B002_B003 ( 1UL << ICODE_RX_B002_B003 )
+#define MSK_ICODE_RX_A002_A003 ( 1UL << ICODE_RX_A002_A003 )
+#define MSK_ICODE_RX_AFNOR ( 1UL << ICODE_RX_AFNOR )
+#define MSK_ICODE_RX_AFNOR_DC ( 1UL << ICODE_RX_AFNOR_DC )
+#define MSK_ICODE_RX_IEEE1344 ( 1UL << ICODE_RX_IEEE1344 )
+#define MSK_ICODE_RX_IEEE1344_DC ( 1UL << ICODE_RX_IEEE1344_DC )
+#define MSK_ICODE_RX_B126_B127 ( 1UL << ICODE_RX_B126_B127 )
+#define MSK_ICODE_RX_B006_B007 ( 1UL << ICODE_RX_B006_B007 )
+#define MSK_ICODE_RX_G142_G146 ( 1UL << ICODE_RX_G142_G146 )
+#define MSK_ICODE_RX_G002_G006 ( 1UL << ICODE_RX_G002_G006 )
+#define MSK_ICODE_RX_C37118 ( 1UL << ICODE_RX_C37118 )
+#define MSK_ICODE_RX_C37118_DC ( 1UL << ICODE_RX_C37118_DC )
+#define MSK_ICODE_RX_TXC101 ( 1UL << ICODE_RX_TXC101 )
+#define MSK_ICODE_RX_TXC101_DC ( 1UL << ICODE_RX_TXC101_DC )
+#define MSK_ICODE_RX_E112 ( 1UL << ICODE_RX_E112 )
+#define MSK_ICODE_RX_E002 ( 1UL << ICODE_RX_E002 )
+#define MSK_ICODE_RX_NASA36 ( 1UL << ICODE_RX_NASA36 )
+#define MSK_ICODE_RX_NASA36_DC ( 1UL << ICODE_RX_NASA36_DC )
+
+/**
+ * A mask of IRIG DCLS formats:
+ */
+#define MSK_ICODE_RX_DC \
+( \
+ MSK_ICODE_RX_B002_B003 | \
+ MSK_ICODE_RX_A002_A003 | \
+ MSK_ICODE_RX_AFNOR_DC | \
+ MSK_ICODE_RX_IEEE1344_DC | \
+ MSK_ICODE_RX_B006_B007 | \
+ MSK_ICODE_RX_G002_G006 | \
+ MSK_ICODE_RX_C37118_DC | \
+ MSK_ICODE_RX_TXC101_DC | \
+ MSK_ICODE_RX_E002 | \
+ MSK_ICODE_RX_NASA36_DC \
+)
+
+/**
+ * A mask of IRIG formats with 100 Hz carrier:
+ */
+#define MSK_ICODE_RX_100HZ \
+( \
+ MSK_ICODE_RX_E112 | \
+ MSK_ICODE_RX_E002 \
+)
+
+/**
+ * A mask of IRIG formats with 1 kHz carrier:
+ */
+#define MSK_ICODE_RX_1KHZ \
+( \
+ MSK_ICODE_RX_B122_B123 | \
+ MSK_ICODE_RX_AFNOR | \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_B126_B127 | \
+ MSK_ICODE_RX_C37118 | \
+ MSK_ICODE_RX_TXC101 | \
+ MSK_ICODE_RX_NASA36 \
+)
+
+/**
+ * A mask of IRIG formats with 10 kHz carrier:
+ */
+#define MSK_ICODE_RX_10KHZ \
+( \
+ MSK_ICODE_RX_A132_A133 \
+)
+
+/**
+ * A mask of IRIG formats with 100 kHz carrier:
+ */
+#define MSK_ICODE_RX_100KHZ \
+( \
+ MSK_ICODE_RX_G142_G146 \
+)
+
+/**
+ * A mask of IRIG formats with 10 bps data rate:
+ */
+#define MSK_ICODE_RX_10BPS \
+( \
+ MSK_ICODE_RX_E002_E112 | \
+ MSK_ICODE_RX_E002_E002 \
+)
+
+/**
+ * A mask of IRIG formats with 100 bps data rate:
+ */
+#define MSK_ICODE_RX_100BPS \
+( \
+ MSK_ICODE_RX_B122_B123 | \
+ MSK_ICODE_RX_B002_B003 | \
+ MSK_ICODE_RX_AFNOR | \
+ MSK_ICODE_RX_AFNOR_DC | \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_IEEE1344_DC | \
+ MSK_ICODE_RX_B126_B127 | \
+ MSK_ICODE_RX_B006_B007 | \
+ MSK_ICODE_RX_C37118 | \
+ MSK_ICODE_RX_C37118_DC | \
+ MSK_ICODE_RX_TXC101 | \
+ MSK_ICODE_RX_TXC101_DC | \
+ MSK_ICODE_RX_NASA36 | \
+ MSK_ICODE_RX_NASA36_DC \
+)
+
+/**
+ * A mask of IRIG formats with 1000 bps data rate:
+ */
+#define MSK_ICODE_RX_1000BPS \
+( \
+ MSK_ICODE_RX_A132_A133 | \
+ MSK_ICODE_RX_A002_A003 \
+)
+
+/**
+ * A mask of IRIG formats with 10 kbps data rate:
+ */
+#define MSK_ICODE_RX_10000BPS \
+( \
+ MSK_ICODE_RX_G142_G146 | \
+ MSK_ICODE_RX_G002_G006 \
+)
+
+/**
+ * A mask of IRIG formats which support TFOM:
+ */
+#define MSK_ICODE_RX_HAS_TFOM \
+( \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_IEEE1344_DC | \
+ MSK_ICODE_RX_C37118 | \
+ MSK_ICODE_RX_C37118_DC \
+)
+
+/**
+ * A mask of IRIG formats which support time zone information:
+ */
+#define MSK_ICODE_RX_HAS_TZI \
+( \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_IEEE1344_DC | \
+ MSK_ICODE_RX_C37118 | \
+ MSK_ICODE_RX_C37118_DC \
+)
+
+/**
+ * The default mask of IRIG formats supported by
+ * IRIG receivers:
+ */
+#if !defined( SUPP_MSK_ICODE_RX )
+ #define SUPP_MSK_ICODE_RX \
+ ( \
+ MSK_ICODE_RX_B122_B123 | \
+ MSK_ICODE_RX_A132_A133 | \
+ MSK_ICODE_RX_B002_B003 | \
+ MSK_ICODE_RX_A002_A003 | \
+ MSK_ICODE_RX_AFNOR | \
+ MSK_ICODE_RX_AFNOR_DC \
+ )
+#endif
+
+/** @} group_icode */
+
+
+
+/**
+ * @brief Configuration settings of an IRIG input or output
+ *
+ * @see group_icode
+ */
+typedef struct
+{
+ uint16_t icode; ///< IRIG signal code, see ::ICODE_RX_CODES
+ uint16_t flags; ///< see ::IFLAGS_BITS
+} IRIG_SETTINGS;
+
+#define _mbg_swab_irig_settings( _p ) \
+{ \
+ _mbg_swab16( &(_p)->icode ); \
+ _mbg_swab16( &(_p)->flags ); \
+}
+
+
+
+/**
+ * @brief Bits used with IRIG_SETTINGS::flags
+ *
+ * @note The presence or absence of the ::IFLAGS_BIT_DISABLE_TFOM flag for the IRIG RX
+ * settings of some PCI cards may not be evaluated correctly by some firmware
+ * versions for those cards, even if an IRIG code has been configured which supports
+ * this flag. See the comments near the declaration of the _pcps_incoming_tfom_ignored()
+ * macro in pcpsdev.h for details.
+ */
+enum IFLAGS_BITS
+{
+ IFLAGS_BIT_DISABLE_TFOM, ///< for RX ignore, for TX don't generate TFOM flag
+ IFLAGS_BIT_TX_GEN_LOCAL_TIME, ///< TX output local time, not %UTC
+ N_IFLAGS_BITS ///< number of known bits
+};
+
+#define IFLAGS_DISABLE_TFOM ( 1UL << IFLAGS_BIT_DISABLE_TFOM )
+#define IFLAGS_TX_GEN_LOCAL_TIME ( 1UL << IFLAGS_BIT_TX_GEN_LOCAL_TIME )
+
+#define IFLAGS_MASK ( ( 1UL << N_IFLAGS_BITS ) - 1 ) ///< mask of all known flags
+
+
+
+/**
+ * @brief Current IRIG settings and supported codes
+ *
+ * Used to query the current IRIG settings
+ * plus a mask of supported codes.
+ */
+typedef struct
+{
+ IRIG_SETTINGS settings; ///< current settings
+ uint32_t supp_codes; ///< bit mask of supported codes
+} IRIG_INFO;
+
+#define _mbg_swab_irig_info( _p ) \
+{ \
+ _mbg_swab_irig_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->supp_codes ); \
+}
+
+
+/**
+ * @defgroup group_irig_comp IRIG input delay compensation
+ *
+ * These definitions are used with IRIG RX delay compensation
+ * which is supported by some IRIG receivers. Delay compensation
+ * depends on the basic frame type, so there are different records
+ * required for the different frame type groups.
+ * @{ */
+
+/**
+ * The number of coefficients of a compensation record
+ * for a single frame type group, and the structure
+ * which contains those coefficients.
+ */
+#define N_IRIG_RX_COMP_VAL 4
+
+/**
+ * @brief A structure used to store compensation values
+ */
+typedef struct
+{
+ /**
+ * @brief Delay compensation values [100 ns units]
+ *
+ * @note Only the first value is actually used to compensate
+ * a delay, so the remaining values should be 0.
+ */
+ int16_t c[N_IRIG_RX_COMP_VAL];
+
+} IRIG_RX_COMP;
+
+#define _mbg_swab_irig_rx_comp( _p ) \
+{ \
+ int i; \
+ for ( i = 0; i < N_IRIG_RX_COMP_VAL; i++ ) \
+ _mbg_swab16( &(_p)->c[i] ); \
+}
+
+
+/** The absolute value of the maximum compensation value accepted by a device */
+#define IRIG_RX_COMP_MAX 999 // [100 ns units], i.e. valid range is +/-99.9 us
+
+
+
+/**
+ * @brief Structure used to retrieve the number of records for a given type
+ */
+typedef struct
+{
+ uint16_t type; ///< record type @see CAL_REC_TYPES
+ uint16_t idx; ///< index if several records of same type are supported, see ::IRIG_RX_COMP_GROUPS
+} CAL_REC_HDR;
+
+#define _mbg_swab_cal_rec_hdr( _p ) \
+{ \
+ _mbg_swab16( &(_p)->type ); \
+ _mbg_swab16( &(_p)->idx ); \
+}
+
+
+/**
+ * @brief Types to be used with CAL_REC_HDR::type
+ */
+enum CAL_REC_TYPES
+{
+ CAL_REC_TYPE_UNDEF, ///< undefined type
+ CAL_REC_TYPE_IRIG_RX_COMP, ///< IRIG receiver delay compensation
+ N_CAL_REC_TYPE ///< number of known types
+};
+
+
+/**
+ * @brief Types to be used with CAL_REC_HDR::idx
+ *
+ * IRIG frame type groups to be distinguished for delay compensation.
+ */
+enum IRIG_RX_COMP_GROUPS
+{
+ IRIG_RX_COMP_B1, ///< codes B1xx, AFNOR, IEEE1344
+ IRIG_RX_COMP_A1, ///< code A1xx
+ IRIG_RX_COMP_B0, ///< codes B0xx, AFNOR DC, IEEE1344 DC
+ IRIG_RX_COMP_A0, ///< code A0xx
+ IRIG_RX_COMP_G1, ///< code G14x
+ IRIG_RX_COMP_G0, ///< code G00x
+ N_IRIG_RX_COMP ///< number of compensation values
+};
+
+
+/**
+ * @brief Initializers for format name strings
+ */
+#define DEFAULT_IRIG_RX_COMP_NAMES \
+{ \
+ "B1xx/AFNOR/IEEE1344", \
+ "A1xx", \
+ "B0xx/AFNOR DC/IEEE1344 DC", \
+ "A0xx", \
+ "G14X", \
+ "G00X", \
+}
+
+
+
+/**
+ * @brief Structure used to transfer calibration records
+ */
+typedef struct
+{
+ CAL_REC_HDR hdr;
+ IRIG_RX_COMP comp_data; ///< IRIG receiver delay compensation
+
+} CAL_REC_IRIG_RX_COMP;
+
+#define _mbg_swab_cal_rec_irig_rx_comp( _p ) \
+{ \
+ _mbg_swab_cal_rec_hdr( &(_p)->hdr ); \
+ _mbg_swab_irig_rx_comp( &(_p)->comp_data ); \
+}
+
+/** @} group_irig_comp */
+
+
+
+/**
+ * @brief A data type used to read the board's debug status
+ *
+ * @note This also include IRIG decoder status.
+ */
+typedef uint32_t MBG_DEBUG_STATUS; ///< @see MBG_DEBUG_STATUS_BITS
+
+#define _mbg_swab_debug_status( _p ) \
+ _mbg_swab32( _p )
+
+
+
+/**
+ * @brief Enumeration of bits used with ::MBG_DEBUG_STATUS
+ */
+enum MBG_DEBUG_STATUS_BITS
+{
+ MBG_IRIG_BIT_WARMED_UP, /**< Osc has warmed up */
+ MBG_IRIG_BIT_PPS_ACTIVE, /**< PPS output is active */
+ MBG_IRIG_BIT_INV_CONFIG, /**< Invalid config, e.g. data csum error */
+ MBG_IRIG_BIT_MSG_DECODED, /**< IRIG msg could be decoded */
+ MBG_IRIG_BIT_MSG_INCONSISTENT, /**< IRIG msg contains inconsistent data */
+ MBG_IRIG_BIT_LOOP_LOCKED, /**< Decoder control loop is locked */
+ MBG_IRIG_BIT_JITTER_TOO_LARGE, /**< Phase jitter too large */
+ MBG_IRIG_BIT_INV_REF_OFFS, /**< %UTC ref offset not configured */
+
+ MBG_SYS_BIT_INV_TIME, /**< Internal time not valid/set */
+ MBG_SYS_BIT_TIME_SET_VIA_API, /**< On board time set externally */
+ MBG_SYS_BIT_INV_RTC, /**< On board RTC invalid */
+ MBG_SYS_BIT_CPU_PLL_FAILED, /**< The CPU's PLL watchdog */
+
+ N_MBG_DEBUG_BIT
+};
+
+/**
+ * @brief Initializers for debug status bit strings
+ */
+#define MBG_DEBUG_STATUS_STRS \
+{ \
+ "Osc has warmed up", \
+ "PPS output is active", \
+ "Config set to default", \
+ "IRIG msg decoded", \
+ "IRIG msg not consistent", \
+ "Decoder control loop locked", \
+ "Phase jitter too large", \
+ "Invalid ref offset", \
+ \
+ "Internal time not valid", \
+ "On board time set via API", \
+ "On board RTC invalid", \
+ "CPU PLL failure, needs restart" \
+}
+
+
+
+#define MBG_IRIG_MSK_WARMED_UP ( 1UL << MBG_IRIG_BIT_WARMED_UP )
+#define MBG_IRIG_MSK_PPS_ACTIVE ( 1UL << MBG_IRIG_BIT_PPS_ACTIVE )
+#define MBG_IRIG_MSK_INV_CONFIG ( 1UL << MBG_IRIG_BIT_INV_CONFIG )
+#define MBG_IRIG_MSK_MSG_DECODED ( 1UL << MBG_IRIG_BIT_MSG_DECODED )
+#define MBG_IRIG_MSK_MSG_INCONSISTENT ( 1UL << MBG_IRIG_BIT_MSG_INCONSISTENT )
+#define MBG_IRIG_MSK_LOOP_LOCKED ( 1UL << MBG_IRIG_BIT_LOOP_LOCKED )
+#define MBG_IRIG_MSK_JITTER_TOO_LARGE ( 1UL << MBG_IRIG_BIT_JITTER_TOO_LARGE )
+#define MBG_IRIG_MSK_INV_REF_OFFS ( 1UL << MBG_IRIG_BIT_INV_REF_OFFS )
+
+#define MBG_SYS_MSK_INV_TIME ( 1UL << MBG_SYS_BIT_INV_TIME )
+#define MBG_SYS_MSK_TIME_SET_VIA_API ( 1UL << MBG_SYS_BIT_TIME_SET_VIA_API )
+#define MBG_SYS_MSK_INV_RTC ( 1UL << MBG_SYS_BIT_INV_RTC )
+#define MBG_SYS_MSK_CPU_PLL_FAILED ( 1UL << MBG_SYS_BIT_CPU_PLL_FAILED )
+
+
+
+/**
+ * @brief A data type used to configure the ref offset
+ *
+ * The ref offset if the offset of the incoming reference time from %UTC.
+ * For some types of signal (e.g. most IRIG frame formats) this can't be
+ * determined automatically.
+ *
+ * @note There's a special flag ::MBG_REF_OFFS_NOT_CFGD indicating that
+ * this parameter is unconfigured
+ */
+typedef int16_t MBG_REF_OFFS; ///< -::MBG_REF_OFFS_MAX..::MBG_REF_OFFS_MAX, or ::MBG_REF_OFFS_NOT_CFGD
+
+#define _mbg_swab_mbg_ref_offs( _p ) _mbg_swab16( (_p) )
+
+
+/**
+ * @brief The maximum allowed positive / negative ref offset
+ */
+#define MBG_REF_OFFS_MAX ( ( 12L * 60 ) + 30 ) // [minutes]
+
+/**
+ * @brief A flag indicating that the ref offset has not yet been configured
+ *
+ * If this flag is set in ::MBG_REF_OFFS this means the ref offset
+ * (time offset from %UTC) has not yet been configured. This is usually
+ * the case for IRIG receiver devices right after they have been shipped.
+ */
+#define MBG_REF_OFFS_NOT_CFGD 0x8000
+
+
+/**
+ * @brief A structure used to configure optional settings
+ *
+ * Optional settings are a generic way to configure some extended settings.
+ */
+typedef struct
+{
+ uint32_t flags; ///< @see MBG_OPT_BITS
+} MBG_OPT_SETTINGS;
+
+#define _mbg_swab_mbg_opt_settings( _p ) \
+{ \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief A structure used to configure optional settings
+ *
+ * This structure includes the current settings, and a bit mask
+ * indicating which flags are supported.
+ */
+typedef struct
+{
+ MBG_OPT_SETTINGS settings;
+ uint32_t supp_flags; ///< bit mask of supported flags, see ::MBG_OPT_BITS
+} MBG_OPT_INFO;
+
+#define _mbg_swab_mbg_opt_info( _p ) \
+{ \
+ _mbg_swab_mbg_opt_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->supp_flags ); \
+}
+
+
+enum MBG_OPT_BITS
+{
+ MBG_OPT_BIT_STR_UTC, /**< serial string contains %UTC time */
+ MBG_OPT_BIT_EMU_SYNC, /**< emulate/pretend to be synchronized, alternatively
+ ::GPS_FEAT_IGNORE_LOCK may be supported */
+ N_MBG_OPT_BIT
+};
+
+/*
+ * Bit masks corresponding to the enumeration above:
+ */
+#define MBG_OPT_FLAG_STR_UTC ( 1UL << MBG_OPT_BIT_STR_UTC )
+#define MBG_OPT_FLAG_EMU_SYNC ( 1UL << MBG_OPT_BIT_EMU_SYNC )
+
+
+
+/**
+ * @brief Bit coded return type for ::PCPS_GET_IRIG_CTRL_BITS
+ *
+ * This type returns the control bits an IRIG receiver has decoded
+ * from an incoming time code signal.
+ */
+typedef uint32_t MBG_IRIG_CTRL_BITS;
+
+#define _mbg_swab_irig_ctrl_bits( _p ) _mbg_swab32( _p )
+
+
+// The following macro extracts the 4 bit TFOM code from the
+// IRIG control bits read from a card. This only works if the received
+// IRIG code is a code which supports TFOM, this is currently
+// only IEEE1344.
+#define _pcps_tfom_from_irig_ctrl_bits( _p ) \
+ ( ( ( *(_p) ) >> 24 ) & 0x0F )
+
+
+
+#define RAW_IRIG_SIZE 16
+
+/**
+ * @brief A buffer used to read raw IRIG data bits from an IRIG receiver
+ *
+ * Used to get the raw data bits from the IRIG decoder. A maximum number
+ * of ::RAW_IRIG_SIZE bytes can be filled up, depending on the IRIG code.
+ * If less bytes are used then the rest of the bytes are filled with zeros.
+ *
+ * @note The first IRIG bit received from the transmitter is saved
+ * in the MSB (bit 7) of data_bytes[0], etc.
+ */
+typedef struct
+{
+ uint8_t data_bytes[RAW_IRIG_SIZE];
+} MBG_RAW_IRIG_DATA;
+
+// The following macro extracts the 4 bit TFOM code from the raw
+// data bits read from a card. This only works if the received
+// IRIG code is a code which supports TFOM, this is currently
+// only IEEE1344.
+#define _pcps_tfom_from_raw_irig_data( _p ) \
+ ( ( ( (_p)->data_bytes[9] >> 2 ) & 0x08 ) \
+ | ( ( (_p)->data_bytes[9] >> 4 ) & 0x04 ) \
+ | ( ( (_p)->data_bytes[9] >> 6 ) & 0x02 ) \
+ | ( ( (_p)->data_bytes[8] & 0x01 ) ) )
+
+
+
+/**
+ @defgroup group_time_scale Time Scale Configuration
+
+ The structures and defines can be used to configure the GPS receiver's
+ basic time scale. By default this is %UTC which can optionally
+ be converted to some local time. However, some applications
+ prefer TAI or pure GPS time. This can be configured using the
+ structures below if the GPS_HAS_TIME_SCALE flag is set in
+ RECEIVER_INFO::features.
+ @{
+*/
+
+/**
+ * @brief Known time scales
+ *
+ * @note See also the extended status bits ::TM_SCALE_GPS
+ * and ::TM_SCALE_TAI indicating the active time scale setting
+ */
+enum MBG_TIME_SCALES
+{
+ MBG_TIME_SCALE_DEFAULT, ///< %UTC or local time according to ::UTC parameters and ::TZDL configuration
+ MBG_TIME_SCALE_GPS, ///< GPS time as sent by the satellites, monotonical
+ MBG_TIME_SCALE_TAI, ///< TAI, i.e. GPS time plus constant offset (::GPS_TAI_OFFSET)
+ N_MBG_TIME_SCALE
+};
+
+#define MBG_TIME_SCALE_MSK_DEFAULT ( 1UL << MBG_TIME_SCALE_DEFAULT )
+#define MBG_TIME_SCALE_MSK_GPS ( 1UL << MBG_TIME_SCALE_GPS )
+#define MBG_TIME_SCALE_MSK_TAI ( 1UL << MBG_TIME_SCALE_TAI )
+
+
+#define MBG_TIME_SCALE_STRS \
+{ \
+ "UTC/local", \
+ "GPS", \
+ "TAI" \
+}
+
+
+
+/**
+ * @brief The constant time offset between the GPS and TAI time scales, in seconds
+ */
+#define GPS_TAI_OFFSET 19 ///< [s], TAI = GPS + GPS_TAI_OFFSET
+
+
+/**
+ * @brief Time scale configuration settings
+ */
+typedef struct
+{
+ uint8_t scale; ///< current time scale code from enum MBG_TIME_SCALES
+ uint8_t flags; ///< reserved, currently always 0
+} MBG_TIME_SCALE_SETTINGS;
+
+#define _mbg_swab_mbg_time_scale_settings( _p ) \
+ _nop_macro_fnc()
+
+
+/**
+ * @brief Time scale configuration settings plus capabilities
+ */
+typedef struct
+{
+ MBG_TIME_SCALE_SETTINGS settings; ///< current settings
+ MBG_TIME_SCALE_SETTINGS max_settings; ///< numb. of scales, all supported flags
+ uint32_t supp_scales; ///< bit masks of supported scales
+} MBG_TIME_SCALE_INFO;
+
+#define _mbg_swab_mbg_time_scale_info( _p ) \
+{ \
+ _mbg_swab_mbg_time_scale_settings( &(_p)->settings ); \
+ _mbg_swab_mbg_time_scale_settings( &(_p)->max_settings ); \
+ _mbg_swab32( &(_p)->supp_scales ); \
+}
+
+/** @} group_time_scale */
+
+
+/*
+ * The structures below are required to setup the programmable
+ * pulse outputs which are provided by some GPS receivers.
+ * The number of programmable pulse outputs supported by a GPS
+ * receiver is reported in the RECEIVER_INFO::n_str_type field.
+ */
+
+/**
+ * @brief A calendar date including full year number
+ */
+typedef struct
+{
+ uint8_t mday; ///< 1..28,29,30,31
+ uint8_t month; ///< 1..12
+ uint16_t year; ///< including century
+} MBG_DATE;
+
+#define _mbg_swab_mbg_date( _p ) \
+{ \
+ _mbg_swab16( &(_p)->year ); \
+}
+
+
+/**
+ * @brief The time of day including hundredths of seconds
+ */
+typedef struct
+{
+ uint8_t hour; ///< 0..23
+ uint8_t min; ///< 0..59
+ uint8_t sec; ///< 0..59,60
+ uint8_t sec100; ///< reserved, currently always 0
+} MBG_TIME;
+
+#define _mbg_swab_mbg_time( _p ) \
+ _nop_macro_fnc() // nothing to swap
+
+
+/**
+ * @brief Date and time specification for switching operations
+ */
+typedef struct
+{
+ MBG_DATE d; ///< date to switch
+ MBG_TIME t; ///< time to switch
+ uint8_t wday; ///< reserved, currently always 0
+ uint8_t flags; ///< reserved, currently 0
+} MBG_DATE_TIME;
+
+#define _mbg_swab_mbg_date_time( _p ) \
+{ \
+ _mbg_swab_mbg_date( &(_p)->d ); \
+ _mbg_swab_mbg_time( &(_p)->t ); \
+}
+
+
+/**
+ * @brief A structure to define on/off cycle times
+ */
+typedef struct
+{
+ MBG_DATE_TIME on; ///< date and time to switch on
+ MBG_DATE_TIME off; ///< date and time to switch off
+} POUT_TIME;
+
+#define _mbg_swab_pout_time( _p ) \
+{ \
+ _mbg_swab_mbg_date_time( &(_p)->on ); \
+ _mbg_swab_mbg_date_time( &(_p)->off ); \
+}
+
+
+/**
+ * @brief The number of ::POUT_TIME settings for each programmable pulse output
+ *
+ * @note This can't be changed without breaking compatibility of the API
+ */
+#define N_POUT_TIMES 3
+
+/**
+ * @brief Configuration settings for a single programmable pulse output
+ */
+typedef struct
+{
+ uint16_t mode; ///< mode of operation, see ::POUT_MODES
+ uint16_t pulse_len; ///< 10 msec units, or COM port number
+ uint16_t timeout; ///< [min], for DCF77 emulation mode only
+ uint16_t flags; ///< @see POUT_SETTINGS_FLAG_BITS
+ POUT_TIME tm[N_POUT_TIMES]; ///< switching times, or other data, see ::POUT_DATA
+} POUT_SETTINGS;
+
+/**
+ * @brief A Generic data field for programmable output settings
+ *
+ * If the mode is set to ::POUT_TIME_SLOTS then POUT_SETTINGS::tm must be
+ * interpreted as ::POUT_DATA, i.e. just an array of bytes. We can not change
+ * the type of the tm field to a union for compatibility reasons ... :(
+ */
+typedef union
+{
+ uint8_t b[N_POUT_TIMES * sizeof( POUT_TIME )];
+} POUT_DATA;
+
+// When reading data from a device we first need to correct the endianess
+// of the mode first, and correct the endianess of the tm field only
+// if the tm field is not interpreted as POUT_DATA.
+#define _mbg_swab_pout_settings_on_get( _p ) \
+{ \
+ _mbg_swab16( &(_p)->mode ); \
+ _mbg_swab16( &(_p)->pulse_len ); \
+ _mbg_swab16( &(_p)->timeout ); \
+ _mbg_swab16( &(_p)->flags ); \
+ \
+ if ( (_p)->mode != POUT_TIME_SLOTS ) \
+ { \
+ int i; \
+ \
+ for ( i = 0; i < N_POUT_TIMES; i++ ) \
+ _mbg_swab_pout_time( &(_p)->tm[i] ); \
+ } \
+}
+
+// When writing data to a device we first need to check the mode,
+// and correct the endianess of the tm field only if the tm field
+// is not interpreted as POUT_DATA. Finally we can also correct
+// the endianess of the mode field.
+#define _mbg_swab_pout_settings_on_set( _p ) \
+{ \
+ if ( (_p)->mode != POUT_TIME_SLOTS ) \
+ { \
+ int i; \
+ \
+ for ( i = 0; i < N_POUT_TIMES; i++ ) \
+ _mbg_swab_pout_time( &(_p)->tm[i] ); \
+ } \
+ \
+ _mbg_swab16( &(_p)->mode ); \
+ _mbg_swab16( &(_p)->pulse_len ); \
+ _mbg_swab16( &(_p)->timeout ); \
+ _mbg_swab16( &(_p)->flags ); \
+}
+
+
+
+// In POUT_TIME_SLOTS mode the number of time slots per minute is stored
+// in the pulse_len field. Valid numbers all numbers n in the range 1..60
+// for which the remainder of 60 / n is 0.
+#define MIN_TIME_SLOTS_PER_MINUTE 1
+#define MAX_TIME_SLOTS_PER_MINUTE 60
+#define TIME_SLOT_REGISTER_IN_SEC 60
+
+#define TIMEOUT_DIVIDED_BY 10
+#define TIME_SLOT_SWITCH_OFF_BUFFER_MIN 50 / TIMEOUT_DIVIDED_BY
+#define TIME_SLOT_SWITCH_OFF_BUFFER_MAX 500 / TIMEOUT_DIVIDED_BY
+#define TIME_SLOT_SWITCH_OFF_BUFFER_STD 500 / TIMEOUT_DIVIDED_BY
+#define TIME_SLOT_SWITCH_OFF_BUFFER_STEP_SIZE 50 / TIMEOUT_DIVIDED_BY
+
+#define _valid_time_slots_per_minute( _n ) \
+ ( ( (_n) >= MIN_TIME_SLOTS_PER_MINUTE ) && \
+ ( (_n) <= MAX_TIME_SLOTS_PER_MINUTE ) && \
+ ( ( 60 % (_n) ) == 0 ) \
+ )
+
+
+#define MAX_POUT_PULSE_LEN 1000 ///< 10 secs, in 10 msec units
+#define MAX_POUT_DCF_TIMOUT ( 48 * 60 ) ///< 48 hours, in minutes
+
+
+/**
+ * @brief Operation modes for a programmable pulse output
+ *
+ * These codes are used with POUT_SETTINGS::mode.
+ *
+ * @note Not every programmable pulse output supports all modes.
+ */
+enum POUT_MODES
+{
+ POUT_IDLE, ///< always off, or on if ::POUT_INVERTED flag is set
+ POUT_TIMER, ///< switch on/off at configured times
+ POUT_SINGLE_SHOT, ///< pulse at time POUT_SETTINGS::tm[0].on
+ POUT_CYCLIC_PULSE, ///< pulse every POUT_SETTINGS::tm[0].on.t interval
+ POUT_PER_SEC, ///< pulse if second changes
+ POUT_PER_MIN, ///< pulse if minute changes
+ POUT_PER_HOUR, ///< pulse if hour changes
+ POUT_DCF77, ///< emulate DCF77 signal
+ POUT_POS_OK, ///< on if pos. OK (nav_solved)
+ POUT_TIME_SYNC, ///< on if time sync (time_syn)
+ POUT_ALL_SYNC, ///< on if pos. OK and time sync
+ POUT_TIMECODE, ///< IRIG/AFNOR DCLS output
+ POUT_TIMESTR, ///< COM port number in pulse_len field
+ POUT_10MHZ, ///< 10 MHz fixed frequency
+ POUT_DCF77_M59, ///< DCF77-like signal with 500 ms pulse in 59th second
+ POUT_SYNTH, ///< programmable synthesizer frequency
+ POUT_TIME_SLOTS, ///< programmable time slots during each minute
+ N_POUT_MODES ///< the number of known modes
+};
+
+
+/*
+ * Default initializers for English pulse mode names. Initializers
+ * for multi-language strings can be found in pcpslstr.h.
+ */
+#define ENG_POUT_NAME_IDLE "Idle"
+#define ENG_POUT_NAME_TIMER "Timer"
+#define ENG_POUT_NAME_SINGLE_SHOT "Single Shot"
+#define ENG_POUT_NAME_CYCLIC_PULSE "Cyclic Pulse"
+#define ENG_POUT_NAME_PER_SEC "Pulse Per Second"
+#define ENG_POUT_NAME_PER_MIN "Pulse Per Min"
+#define ENG_POUT_NAME_PER_HOUR "Pulse Per Hour"
+#define ENG_POUT_NAME_DCF77 "DCF77 Marks"
+#define ENG_POUT_NAME_POS_OK "Position OK"
+#define ENG_POUT_NAME_TIME_SYNC "Time Sync"
+#define ENG_POUT_NAME_ALL_SYNC "All Sync"
+#define ENG_POUT_NAME_TIMECODE "DCLS Time Code"
+#define ENG_POUT_NAME_TIMESTR "COM Time String"
+#define ENG_POUT_NAME_10MHZ "10 MHz Frequency"
+#define ENG_POUT_NAME_DCF77_M59 "DCF77-like M59"
+#define ENG_POUT_NAME_SYNTH "Synthesizer Frequency"
+#define ENG_POUT_NAME_TIME_SLOTS "Time Slots per Minute"
+
+#define DEFAULT_ENG_POUT_NAMES \
+{ \
+ ENG_POUT_NAME_IDLE, \
+ ENG_POUT_NAME_TIMER, \
+ ENG_POUT_NAME_SINGLE_SHOT, \
+ ENG_POUT_NAME_CYCLIC_PULSE, \
+ ENG_POUT_NAME_PER_SEC, \
+ ENG_POUT_NAME_PER_MIN, \
+ ENG_POUT_NAME_PER_HOUR, \
+ ENG_POUT_NAME_DCF77, \
+ ENG_POUT_NAME_POS_OK, \
+ ENG_POUT_NAME_TIME_SYNC, \
+ ENG_POUT_NAME_ALL_SYNC, \
+ ENG_POUT_NAME_TIMECODE, \
+ ENG_POUT_NAME_TIMESTR, \
+ ENG_POUT_NAME_10MHZ, \
+ ENG_POUT_NAME_DCF77_M59, \
+ ENG_POUT_NAME_SYNTH, \
+ ENG_POUT_NAME_TIME_SLOTS \
+}
+
+
+#define ENG_POUT_HINT_IDLE "Constant output level"
+#define ENG_POUT_HINT_TIMER "Switch based on configured on/off times"
+#define ENG_POUT_HINT_SINGLE_SHOT "Generate a single pulse of determined length"
+#define ENG_POUT_HINT_CYCLIC_PULSE "Generate cyclic pulses of determined length"
+#define ENG_POUT_HINT_PER_SEC "Generate pulse at beginning of new second"
+#define ENG_POUT_HINT_PER_MIN "Generate pulse at beginning of new minute"
+#define ENG_POUT_HINT_PER_HOUR "Generate pulse at beginning of new hour"
+#define ENG_POUT_HINT_DCF77 "DCF77 compatible time marks"
+#define ENG_POUT_HINT_POS_OK "Switch if receiver position has been verified"
+#define ENG_POUT_HINT_TIME_SYNC "Switch if time is synchronized"
+#define ENG_POUT_HINT_ALL_SYNC "Switch if full sync"
+#define ENG_POUT_HINT_TIMECODE "Duplicate IRIG time code signal"
+#define ENG_POUT_HINT_TIMESTR "Duplicate serial time string of specified port"
+#define ENG_POUT_HINT_10MHZ "10 MHz fixed output frequency"
+#define ENG_POUT_HINT_DCF77_M59 "DCF77 time marks with 500 ms pulse in 59th second"
+#define ENG_POUT_HINT_SYNTH "Frequency generated by programmable synthesizer"
+#define ENG_POUT_HINT_TIME_SLOTS "Output enabled during specified time slots per minute"
+
+#define DEFAULT_ENG_POUT_HINTS \
+{ \
+ ENG_POUT_HINT_IDLE, \
+ ENG_POUT_HINT_TIMER, \
+ ENG_POUT_HINT_SINGLE_SHOT, \
+ ENG_POUT_HINT_CYCLIC_PULSE, \
+ ENG_POUT_HINT_PER_SEC, \
+ ENG_POUT_HINT_PER_MIN, \
+ ENG_POUT_HINT_PER_HOUR, \
+ ENG_POUT_HINT_DCF77, \
+ ENG_POUT_HINT_POS_OK, \
+ ENG_POUT_HINT_TIME_SYNC, \
+ ENG_POUT_HINT_ALL_SYNC, \
+ ENG_POUT_HINT_TIMECODE, \
+ ENG_POUT_HINT_TIMESTR, \
+ ENG_POUT_HINT_10MHZ, \
+ ENG_POUT_HINT_DCF77_M59, \
+ ENG_POUT_HINT_SYNTH, \
+ ENG_POUT_HINT_TIME_SLOTS \
+}
+
+
+/*
+ * The definitions below are used to set up bit masks
+ * which restrict the modes which can be used with
+ * a given programmable output:
+ */
+#define MSK_POUT_IDLE ( 1UL << POUT_IDLE )
+#define MSK_POUT_TIMER ( 1UL << POUT_TIMER )
+#define MSK_POUT_SINGLE_SHOT ( 1UL << POUT_SINGLE_SHOT )
+#define MSK_POUT_CYCLIC_PULSE ( 1UL << POUT_CYCLIC_PULSE )
+#define MSK_POUT_PER_SEC ( 1UL << POUT_PER_SEC )
+#define MSK_POUT_PER_MIN ( 1UL << POUT_PER_MIN )
+#define MSK_POUT_PER_HOUR ( 1UL << POUT_PER_HOUR )
+#define MSK_POUT_DCF77 ( 1UL << POUT_DCF77 )
+#define MSK_POUT_POS_OK ( 1UL << POUT_POS_OK )
+#define MSK_POUT_TIME_SYNC ( 1UL << POUT_TIME_SYNC )
+#define MSK_POUT_ALL_SYNC ( 1UL << POUT_ALL_SYNC )
+#define MSK_POUT_TIMECODE ( 1UL << POUT_TIMECODE )
+#define MSK_POUT_TIMESTR ( 1UL << POUT_TIMESTR )
+#define MSK_POUT_10MHZ ( 1UL << POUT_10MHZ )
+#define MSK_POUT_DCF77_M59 ( 1UL << POUT_DCF77_M59 )
+#define MSK_POUT_SYNTH ( 1UL << POUT_SYNTH )
+#define MSK_POUT_TIME_SLOTS ( 1UL << POUT_TIME_SLOTS )
+
+
+/**
+ * @brief Bits used with POUT_SETTINGS::flags
+ */
+enum POUT_SETTINGS_FLAG_BITS
+{
+ POUT_BIT_INVERTED, ///< output level has to be inverted
+ POUT_BIT_IF_SYNC_ONLY, ///< disable output in holdover mode
+ POUT_BIT_TIMEBASE_UTC, ///< use %UTC, only applicable for DCF77 output
+ N_POUT_SETTINGS_FLAG_BITS ///< Number of known flag bits
+};
+
+#define POUT_INVERTED ( 1UL << POUT_BIT_INVERTED )
+#define POUT_IF_SYNC_ONLY ( 1UL << POUT_BIT_IF_SYNC_ONLY )
+#define POUT_TIMEBASE_UTC ( 1UL << POUT_BIT_TIMEBASE_UTC )
+
+
+/**
+ * @brief Configuration settings for a specific programmable pulse output
+ *
+ * This structure can be used to send configuration settings for a specific
+ * programmable output to a device.
+ * The number of supported outputs is RECEIVER_INFO::n_prg_out.
+ *
+ * @note The ::POUT_INFO_IDX structure should be read from
+ * a device to retrieve the current settings and capabilities.
+ */
+typedef struct
+{
+ uint16_t idx; ///< 0..RECEIVER_INFO::n_prg_out - 1
+ POUT_SETTINGS pout_settings;
+} POUT_SETTINGS_IDX;
+
+#define _mbg_swab_pout_settings_idx_on_set( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_pout_settings_on_set( &(_p)->pout_settings ); \
+}
+
+#define _mbg_swab_pout_settings_idx_on_get( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_pout_settings_on_get( &(_p)->pout_settings ); \
+}
+
+
+/**
+ * @brief Current settings and general capabilities of a programmable pulse output
+ *
+ * This structure should be read from the device to retrieve the
+ * current settings of a programmable pulse output plus its capabilities,
+ * e.g. the supported output modes, etc.
+ *
+ * @note The ::POUT_INFO_IDX structure should be used to read
+ * current settings and capabilities of a specific output.
+ */
+typedef struct
+{
+ POUT_SETTINGS pout_settings;
+ uint32_t supp_modes; ///< bit mask of modes supp. by this output, see ::POUT_MODES
+ uint8_t timestr_ports; ///< bit mask of COM ports supported for mode ::POUT_TIMESTR, see ::MAX_POUT_TIMESTR_PORTS
+ uint8_t reserved_0; ///< reserved for future use, currently 0
+ uint16_t reserved_1; ///< reserved for future use, currently 0
+ uint32_t flags; ///< @see POUT_INFO_FLAG_BITS
+} POUT_INFO;
+
+#define _mbg_swab_pout_info_on_get( _p ) \
+{ \
+ _mbg_swab_pout_settings_on_get( &(_p)->pout_settings ); \
+ _mbg_swab32( &(_p)->supp_modes ); \
+ _mbg_swab16( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * The max number of COM ports that can be handled by POUT_INFO::timestr_ports
+ */
+#define MAX_POUT_TIMESTR_PORTS 8
+
+
+/**
+ * @brief Bits used with POUT_INFO::flags
+ */
+enum POUT_INFO_FLAG_BITS
+{
+ POUT_BIT_SUPP_IF_SYNC_ONLY, ///< supports disabling outputs in holdover mode
+ POUT_BIT_SUPP_DCF77_UTC, ///< supports %UTC output in DCF77 mode
+ POUT_BIT_FIXED_PULSE_LEN, ///< pulse length is fixed to the value reported in settings
+ POUT_BIT_NOT_INVERTIBLE, ///< output level can not be inverted
+ N_POUT_INFO_FLAG_BITS ///< number of known flag bits
+};
+
+#define POUT_SUPP_IF_SYNC_ONLY ( 1UL << POUT_BIT_SUPP_IF_SYNC_ONLY )
+#define POUT_SUPP_DCF77_UTC ( 1UL << POUT_BIT_SUPP_DCF77_UTC )
+#define POUT_FIXED_PULSE_LEN ( 1UL << POUT_BIT_FIXED_PULSE_LEN )
+#define POUT_NOT_INVERTIBLE ( 1UL << POUT_BIT_NOT_INVERTIBLE )
+
+
+/**
+ * @brief Current settings and general capabilities of a specific serial port
+ *
+ * This structure should be read from the device to retrieve the
+ * current settings of a specific programmable output plus its capabilities,
+ * e.g. supported modes of operation, etc.
+ * The number of supported ports is RECEIVER_INFO::n_prg_out.
+ *
+ * @note The ::POUT_SETTINGS_IDX structure should be send back to
+ * the device to configure the specified programmable pulse output.
+ */
+typedef struct
+{
+ uint16_t idx; ///< 0..RECEIVER_INFO::n_prg_out - 1
+ POUT_INFO pout_info;
+} POUT_INFO_IDX;
+
+#define _mbg_swab_pout_info_idx_on_get( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_pout_info_on_get( &(_p)->pout_info ); \
+}
+
+
+/*
+ * The codes below are used with devices which support multiple
+ * ref time sources at the same time. The priorities of the
+ * supported ref time sources is configurable.
+ */
+
+
+/**
+ * @brief All possibly supported ref time sources
+ *
+ * @see MULTI_REF_TYPE_MASKS
+ */
+enum MULTI_REF_TYPES
+{
+ MULTI_REF_NONE = -1, ///< nothing, undefined
+ MULTI_REF_GPS = 0, ///< standard GPS
+ MULTI_REF_10MHZ, ///< 10 MHz input frequency
+ MULTI_REF_PPS, ///< 1 PPS input signal
+ MULTI_REF_10MHZ_PPS, ///< combined 10 MHz plus PPS
+ MULTI_REF_IRIG, ///< IRIG input
+ MULTI_REF_NTP, ///< Network Time Protocol (NTP)
+ MULTI_REF_PTP, ///< Precision Time Protocol (PTP, IEEE1588)
+ MULTI_REF_PTP_E1, ///< PTP over E1
+ MULTI_REF_FREQ, ///< fixed frequency
+ MULTI_REF_PPS_STRING, ///< PPS in addition to string
+ MULTI_REF_GPIO, ///< variable input signal via GPIO
+ MULTI_REF_INTERNAL, ///< reserved, used internally by firmware only
+ MULTI_REF_PZF, ///< DCF77 PZF providing much more accuracy than a standard LWR
+ MULTI_REF_LWR, ///< long wave receiver. e.g. DCF77 AM, WWVB, MSF, JJY
+ MULTI_REF_GRC, ///< Glonass / GPS receiver
+ MULTI_REF_HAVEQUICK, ///< HaveQuick input
+ N_MULTI_REF ///< the number of defined sources, can not exceed bit number of uint32_t - 1
+};
+
+
+/**
+ * @brief Names of supported ref time sources
+ *
+ * @see MULTI_REF_TYPES
+ */
+#define DEFAULT_MULTI_REF_NAMES \
+{ \
+ "GPS", \
+ "10 MHz freq in", \
+ "PPS in", \
+ "10 MHz + PPS in", \
+ "IRIG", \
+ "NTP", \
+ "PTP (IEEE1588)", \
+ "PTP over E1", \
+ "Fixed Freq. in", \
+ "PPS plus string", \
+ "Var. freq. via GPIO", \
+ "(reserved)", \
+ "DCF77 PZF Receiver", \
+ "Long Wave Receiver", \
+ "GLONASS/GPS Receiver", \
+ "HaveQuick Input" \
+}
+
+
+/**
+ * @brief Bit masks according to enumerated ref time sources
+ *
+ * @see MULTI_REF_TYPES
+ */
+enum MULTI_REF_TYPE_MASKS
+{
+ HAS_MULTI_REF_GPS = ( 1UL << MULTI_REF_GPS ), ///< see ::MULTI_REF_GPS
+ HAS_MULTI_REF_10MHZ = ( 1UL << MULTI_REF_10MHZ ), ///< see ::MULTI_REF_10MHZ
+ HAS_MULTI_REF_PPS = ( 1UL << MULTI_REF_PPS ), ///< see ::MULTI_REF_PPS
+ HAS_MULTI_REF_10MHZ_PPS = ( 1UL << MULTI_REF_10MHZ_PPS ), ///< see ::MULTI_REF_10MHZ_PPS
+ HAS_MULTI_REF_IRIG = ( 1UL << MULTI_REF_IRIG ), ///< see ::MULTI_REF_IRIG
+ HAS_MULTI_REF_NTP = ( 1UL << MULTI_REF_NTP ), ///< see ::MULTI_REF_NTP
+ HAS_MULTI_REF_PTP = ( 1UL << MULTI_REF_PTP ), ///< see ::MULTI_REF_PTP
+ HAS_MULTI_REF_PTP_E1 = ( 1UL << MULTI_REF_PTP_E1 ), ///< see ::MULTI_REF_PTP_E1
+
+ HAS_MULTI_REF_FREQ = ( 1UL << MULTI_REF_FREQ ), ///< see ::MULTI_REF_FREQ
+ HAS_MULTI_REF_PPS_STRING = ( 1UL << MULTI_REF_PPS_STRING ), ///< see ::MULTI_REF_PPS_STRING
+ HAS_MULTI_REF_GPIO = ( 1UL << MULTI_REF_GPIO ), ///< see ::MULTI_REF_GPIO
+ HAS_MULTI_REF_INTERNAL = ( 1UL << MULTI_REF_INTERNAL ), ///< see ::MULTI_REF_INTERNAL
+ HAS_MULTI_REF_PZF = ( 1UL << MULTI_REF_PZF ), ///< see ::MULTI_REF_PZF
+ HAS_MULTI_REF_LWR = ( 1UL << MULTI_REF_LWR ), ///< see ::MULTI_REF_LWR
+ HAS_MULTI_REF_GRC = ( 1UL << MULTI_REF_GRC ), ///< see ::MULTI_REF_GRC
+ HAS_MULTI_REF_HAVEQUICK = ( 1UL << MULTI_REF_HAVEQUICK ) ///< see ::MULTI_REF_HAVEQUICK
+};
+
+
+/*
+ * There are 2 different ways to configure multi ref support
+ * provided by some devices.
+ *
+ * Newer devices which have the GPS_FEAT_XMULTI_REF flag set
+ * in RECEIVER_INFO::features support the newer XMULTI_REF_...
+ * structures which provide a more flexible interface.
+ *
+ * Older devices which have the GPS_FEAT_MULTI_REF flag set
+ * support these MULTI_REF_... structures below where
+ * the number of supported input sources and priorities
+ * is limited to N_MULTI_REF_PRIO.
+ */
+#define N_MULTI_REF_PRIO 4
+
+
+/**
+ * @brief A structure used to configure the priority of the supported ref sources
+ *
+ * The number stored in prio[0] of the array indicates the ref time
+ * source with highest priority. If that source fails, the device
+ * falls back to the source indicated by prio[1]. Each field of
+ * the prio[] array must be set to one of the values 0..N_MULTI_REF-1,
+ * or to -1 (0xFF) if the value is not assigned.
+ */
+typedef struct
+{
+ uint8_t prio[N_MULTI_REF_PRIO];
+} MULTI_REF_SETTINGS;
+
+
+/**
+ * @brief A structure used to query MULTI_REF configuration parameters
+ *
+ * This also includes a bit mask of supported ref sources.
+ */
+typedef struct
+{
+ MULTI_REF_SETTINGS settings; ///< current settings
+ uint32_t supp_ref; ///< bit mask of supported sources, see ::MULTI_REF_TYPE_MASKS
+ uint16_t n_levels; ///< supp. levels, 0..N_MULTI_REF_PRIO-1
+ uint16_t flags; ///< reserved, currently always 0
+} MULTI_REF_INFO;
+
+
+/**
+ * @brief A data type used to query MULTI_REF status information
+ */
+typedef uint16_t MULTI_REF_STATUS; ///< @see MULTI_REF_STATUS_BITS
+
+
+/**
+ * @brief Bits and associated masks used with ::MULTI_REF_STATUS
+ */
+enum MULTI_REF_STATUS_BITS
+{
+ WRN_MODULE_MODE, ///< selected input mode was invalid, set to default
+ WRN_COLD_BOOT, ///< GPS is in cold boot mode
+ WRN_WARM_BOOT, ///< GPS is in warm boot mode
+ WRN_ANT_DISCONN, ///< antenna is disconnected
+ WRN_10MHZ_UNLOCK, ///< impossible to lock to external 10MHz reference
+ WRN_1PPS_UNLOCK, ///< impossible to lock to external 1PPS reference
+ WRN_GPS_UNLOCK, ///< impossible to lock to GPS
+ WRN_10MHZ_MISSING, ///< external 10MHz signal not available
+ WRN_1PPS_MISSING, ///< external 1PPS signal not available
+ N_MULTI_REF_STATUS_BITS ///< the number of known bits
+};
+
+#define MSK_WRN_COLD_BOOT ( 1UL << WRN_COLD_BOOT )
+#define MSK_WRN_WARM_BOOT ( 1UL << WRN_WARM_BOOT )
+#define MSK_WRN_ANT_DISCONN ( 1UL << WRN_ANT_DISCONN )
+#define MSK_WRN_10MHZ_UNLOCK ( 1UL << WRN_10MHZ_UNLOCK )
+#define MSK_WRN_1PPS_UNLOCK ( 1UL << WRN_1PPS_UNLOCK )
+#define MSK_WRN_GPS_UNLOCK ( 1UL << WRN_GPS_UNLOCK )
+#define MSK_WRN_10MHZ_MISSING ( 1UL << WRN_10MHZ_MISSING )
+#define MSK_WRN_1PPS_MISSING ( 1UL << WRN_1PPS_MISSING )
+#define MSK_WRN_MODULE_MODE ( 1UL << WRN_MODULE_MODE )
+
+
+
+/**
+ * @defgroup group_xmr_cfg Extended multiref configuration stuff
+ *
+ * If the RECEIVER_INFO::features flag GPS_FEAT_XMULTI_REF is set
+ * then the following XMULTI_REF_... data structures must be used
+ * instead of the older MULTI_REF_... structures.
+ *
+ * Those devices support a number of priority levels addressed by
+ * the priority index, starting at 0 for highest priority. A single
+ * reference time source from the set of supported sources can be
+ * assigned to each priority level.
+ *
+ * These structures are used to configure the individual
+ * time source for each priority level, and retrieve the status
+ * of the time source at each priority level.
+ *
+ * @{ */
+
+/**
+ * @brief Identifier for a reference source
+ */
+typedef struct
+{
+ uint8_t type; ///< @see MULTI_REF_TYPES
+ uint8_t instance; ///< instance number, if multiple instances are supported, else 0
+} XMULTI_REF_ID;
+
+
+
+/**
+ * @brief Reference source configuration settings
+ */
+typedef struct
+{
+ XMULTI_REF_ID id; ///< time source identifier
+ uint16_t flags; ///< reserved, currently always 0
+ NANO_TIME bias; ///< time bias, e.g. path delay
+ NANO_TIME precision; ///< precision of the time source
+ uint32_t fine_limit; ///< smooth control if below this limit
+} XMULTI_REF_SETTINGS;
+
+
+
+/**
+ * @brief Reference source configuration settings for a specific priority level
+ *
+ * @note After configuring, a structure with idx == 0xFFFF (-1) must be sent
+ * to let the changes become effective.
+ */
+typedef struct
+{
+ uint16_t idx; ///< the priority level index, highest == 0
+ XMULTI_REF_SETTINGS settings; ///< the settings configured for this level
+} XMULTI_REF_SETTINGS_IDX;
+
+
+
+/**
+ * @brief Reference source configuration settings and capabilities
+ */
+typedef struct
+{
+ XMULTI_REF_SETTINGS settings; ///< current settings
+ uint32_t supp_ref; ///< bit mask of supported sources, see ::MULTI_REF_TYPES
+ uint8_t n_supp_ref; ///< number of supported ref time sources
+ uint8_t n_prio; ///< number of supported priority levels
+ uint16_t flags; ///< currently always 0
+} XMULTI_REF_INFO;
+
+
+
+/**
+ * @brief Reference source configuration settings and capabilities for a specific priority level
+ */
+typedef struct
+{
+ uint16_t idx; ///< the priority level index, highest == 0
+ XMULTI_REF_INFO info; ///< ref source cfg and capabilities
+} XMULTI_REF_INFO_IDX;
+
+
+
+/**
+ * @brief Status information on a single ref time source
+ */
+typedef struct
+{
+ XMULTI_REF_ID id; ///< time source identifier, see ::MULTI_REF_TYPES
+ uint16_t status; ///< status bits, see ::XMR_REF_STATUS_BITS
+ NANO_TIME offset; ///< time offset from main time base
+ uint16_t flags; ///< flags, see ::XMR_REF_FLAG_BITS
+ uint8_t ssm; ///< synchronization status message (if supported by src.)
+ uint8_t soc; ///< signal outage counter (updated on loss of signal)
+} XMULTI_REF_STATUS;
+
+
+
+/**
+ * @brief Status information on a ref time source at a specific priority level
+ */
+typedef struct
+{
+ uint16_t idx; /**< the priority level index, highest == 0 */
+ XMULTI_REF_STATUS status; /**< status information */
+
+} XMULTI_REF_STATUS_IDX;
+
+
+
+/**
+ * @brief Bits and bit masks used with XMULTI_REF_STATUS::status
+ */
+enum XMR_REF_STATUS_BITS
+{
+ XMRS_BIT_NOT_SUPP, ///< ref type cfg'd for this level is not supported
+ XMRS_BIT_NO_CONN, ///< input signal is disconnected
+ XMRS_BIT_NO_SIGNAL, ///< no input signal
+ XMRS_BIT_IS_MASTER, ///< reference is master source
+ XMRS_BIT_IS_LOCKED, ///< locked to input signal
+ XMRS_BIT_IS_ACCURATE, ///< oscillator control has reached full accuracy
+ XMRS_BIT_NOT_SETTLED, ///< reference time signal not settled
+ XMRS_BIT_NOT_PHASE_LOCKED, ///< oscillator not phase locked to PPS
+ XMRS_BIT_NUM_SRC_EXC, ///< number of available sources exceeds what can be handled
+ XMRS_BIT_IS_EXTERNAL, ///< this ref source is on extension card
+ XMRS_BIT_LOW_JITTER, ///< this ref source has low jitter
+ N_XMRS_BITS ///< number of know status bits
+};
+
+#define XMRS_MSK_NOT_SUPP ( 1UL << XMRS_BIT_NOT_SUPP )
+#define XMRS_MSK_NO_CONN ( 1UL << XMRS_BIT_NO_CONN )
+#define XMRS_MSK_NO_SIGNAL ( 1UL << XMRS_BIT_NO_SIGNAL )
+#define XMRS_MSK_IS_MASTER ( 1UL << XMRS_BIT_IS_MASTER )
+#define XMRS_MSK_IS_LOCKED ( 1UL << XMRS_BIT_IS_LOCKED )
+#define XMRS_MSK_IS_ACCURATE ( 1UL << XMRS_BIT_IS_ACCURATE )
+#define XMRS_MSK_NOT_SETTLED ( 1UL << XMRS_BIT_NOT_SETTLED )
+#define XMRS_MSK_NOT_PHASE_LOCKED ( 1UL << XMRS_BIT_NOT_PHASE_LOCKED )
+#define XMRS_MSK_NUM_SRC_EXC ( 1UL << XMRS_BIT_NUM_SRC_EXC )
+#define XMRS_MSK_IS_EXTERNAL ( 1UL << XMRS_BIT_IS_EXTERNAL )
+#define XMRS_MSK_LOW_JITTER ( 1UL << XMRS_BIT_LOW_JITTER )
+
+/*
+ * Initializers for XMRS status bit strings.
+ */
+#define MBG_XMRS_STATUS_STRS \
+{ \
+ "Ref type not supported", \
+ "No connection", \
+ "No signal", \
+ "Is master", \
+ "Is locked", \
+ "Is accurate", \
+ "Not settled", \
+ "Phase not locked", \
+ "Number sources exceeds limit", \
+ "Is external", \
+ "Low jitter" \
+}
+
+
+/**
+ * @brief Bits and masks used with XMULTI_REF_STATUS::flags
+ *
+ * @note This API is only supported if bit ::GPS_FEAT_XMRS_MULT_INSTC
+ * is set in RECEIVER_INFO::features.
+ */
+enum XMR_REF_FLAG_BITS
+{
+ XMRSF_BIT_MULT_INSTC_SUPP, ///< multiple instances of the same ref type supported
+ XMRSF_BIT_IS_EXTERNAL, ///< this ref source is on extension card
+ N_XMRS_FLAGS
+};
+
+#define XMRSF_MSK_MULT_INSTC_SUPP ( 1UL << XMRSF_BIT_MULT_INSTC_SUPP )
+#define XMRSF_MSK_IS_EXTERNAL ( 1UL << XMRSF_BIT_IS_EXTERNAL )
+
+
+
+/*
+ * An initializer for a XMULTI_REF_STATUS variable
+ * with status invalid / not used
+ */
+#define XMULTI_REF_STATUS_INVALID \
+{ \
+ { (uint8_t) MULTI_REF_NONE, 0 }, /* id; instance 0 ? */ \
+ XMRS_MSK_NO_CONN | XMRS_MSK_NO_SIGNAL, /* status */ \
+ { 0 }, /* offset */ \
+ 0 /* reserved */ \
+}
+
+
+/**
+ * @brief The number of supported instances of each ref source type
+ *
+ * @note This structure is only supported if bit ::GPS_FEAT_XMRS_MULT_INSTC
+ * is set in RECEIVER_INFO::features.
+ */
+typedef struct
+{
+ uint32_t flags; ///< reserved, currently always 0
+ uint16_t n_xmr_settings; ///< number of configurable multi ref settings
+ uint8_t slot_id; ///< current slot ID of board (0..15)
+ uint8_t reserved; ///< reserved, currently always 0
+ uint8_t n_inst[32]; ///< ::N_MULTI_REF entries used, but can not exceed bit number of uint32_t - 1
+} XMULTI_REF_INSTANCES;
+
+
+/**
+ * @brief Holdover interval while switching XMR sources
+ *
+ * @note This parameter can be sent to a device to specify a holdover
+ * interval during which the sync state shall be kept when switching
+ * to a different time source.
+ */
+typedef uint32_t XMR_HOLDOVER_INTV; ///< [s] */
+
+
+/** @} group_xmr_cfg */
+
+
+
+/**
+ * @defgroup group_gpio GPIO port configuration stuff
+ *
+ * @note This is only supported if ::GPS_HAS_GPIO is set
+ * in the RECEIVER_INFO::features mask.
+ *
+ * @{ */
+
+
+/**
+ * @brief General GPIO config info to be read from a device
+ *
+ * Used to query from a device how many GPIO ports are supported
+ * by the device, then index 0..num_io-1 configuration or status
+ * records can be read from or written to the device.
+ */
+typedef struct
+{
+ uint32_t num_io; /**< number of supported GPIO ports */
+ uint32_t reserved; /**< currently always 0 */
+ uint32_t flags; /**< currently always 0 */
+
+} MBG_GPIO_CFG_LIMITS;
+
+
+
+/**
+ * @brief Enumeration of GPIO types
+ *
+ * Usually a specific GPIO port can only be either an input
+ * or an output, and supports only a single signal type.
+ * This is due to hardware limitations, i.e. input or output
+ * circuitry required for the given signal
+ */
+enum MBG_GPIO_TYPES
+{
+ MBG_GPIO_TYPE_FREQ_IN, /**< variable frequency input */
+ MBG_GPIO_TYPE_FREQ_OUT, /**< variable frequency output */
+ MBG_GPIO_TYPE_FIXED_FREQ_OUT, /**< fixed frequency output */
+ MBG_GPIO_TYPE_BITS_IN, /**< framed data stream input */
+ MBG_GPIO_TYPE_BITS_OUT, /**< framed data stream output */
+ N_MBG_GPIO_TYPES /**< number of known types */
+};
+
+
+#define DEFAULT_GPIO_TYPES_SHORT_STRS \
+{ \
+ "Freq. In", \
+ "Freq. Out", \
+ "Fixed Freq Out", \
+ "BITS In", \
+ "BITS Out" \
+}
+
+
+
+/**
+ * @brief Enumeration of signal shapes
+ *
+ * Used to specify the signal shape of an input or output
+ * frequency signal.
+ */
+enum MBG_GPIO_SIGNAL_SHAPES
+{
+ MBG_GPIO_SIGNAL_SHAPE_UNSPECIFIED, /**< unknown or unspecified signal shape */
+ MBG_GPIO_SIGNAL_SHAPE_SINE, /**< sine wave */
+ MBG_GPIO_SIGNAL_SHAPE_SQUARE, /**< square wave */
+ N_MBG_GPIO_SIGNAL_SHAPES /**< number of known signal shapes */
+};
+
+/** Bit masks of signal shapes, corresponding to enum MBG_GPIO_SIGNAL_SHAPES */
+#define MBG_GPIO_SIGNAL_SHAPE_MSK_UNSPECIFIED ( 1UL << MBG_GPIO_SIGNAL_SHAPE_UNSPECIFIED )
+#define MBG_GPIO_SIGNAL_SHAPE_MSK_SINE ( 1UL << MBG_GPIO_SIGNAL_SHAPE_SINE )
+#define MBG_GPIO_SIGNAL_SHAPE_MSK_SQUARE ( 1UL << MBG_GPIO_SIGNAL_SHAPE_SQUARE )
+
+
+
+/**
+ * @brief A structure used to specify a variable frequency
+ *
+ * Used to specify a variable frequency for GPIO input or output
+ */
+typedef struct
+{
+ uint32_t hz; /**< integral number, Hz */
+ uint32_t frac; /**< fractional part, binary */
+
+} MBG_GPIO_FREQ;
+
+
+
+/**
+ * @brief Configuration of a GPIO variable frequency input
+ *
+ * @see MBG_GPIO_TYPE_FREQ_IN
+ */
+typedef struct
+{
+ MBG_GPIO_FREQ freq; /**< frequency */
+ uint32_t csc_limit; /**< max. cycle slip [1/1000 cycle units] */
+ uint32_t shape; /**< signal shape, see ::MBG_GPIO_SIGNAL_SHAPES */
+ uint32_t reserved; /**< currently always 0 */
+ uint32_t flags; /**< currently always 0 */
+
+} MBG_GPIO_FREQ_IN_SETTINGS;
+
+
+/**
+ * @brief Supported options for a variable frequency GPIO input
+ *
+ * @see MBG_GPIO_TYPE_FREQ_IN
+ */
+typedef struct
+{
+ //##++++++++++++++++
+ uint32_t freq_min; /**< minimum output frequency [Hz] */
+ uint32_t freq_max; /**< maximum output frequency [Hz] */
+ uint32_t csc_limit_max; /**< max. milli_phase, unspecified if 0 */
+ uint32_t supp_shapes; /**< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPES */
+ uint32_t reserved; /**< currently always 0 */
+ uint32_t flags; /**< currently always 0 */
+
+} MBG_GPIO_FREQ_IN_SUPP;
+
+
+
+/**
+ * @brief Configuration of a GPIO variable frequency output
+ *
+ * @see MBG_GPIO_TYPE_FREQ_OUT
+ */
+typedef struct
+{
+ MBG_GPIO_FREQ freq; /**< frequency */
+ int32_t milli_phase; /**< phase [1/1000 degree units] */
+ uint32_t shape; /**< signal shape, see ::MBG_GPIO_SIGNAL_SHAPES */
+ uint32_t reserved; /**< currently always 0 */
+ uint32_t flags; /**< currently always 0 */
+
+} MBG_GPIO_FREQ_OUT_SETTINGS;
+
+
+
+/**
+ * @brief Supported options for a variable frequency GPIO output
+ *
+ * @see MBG_GPIO_TYPE_FREQ_OUT
+ */
+typedef struct
+{
+ uint32_t freq_min; /**< minimum output frequency [Hz] */
+ uint32_t freq_max; /**< maximum output frequency [Hz] */
+ uint32_t freq_resolution; /**< frequency resolution [Hz], unspecified if 0 */
+ uint32_t milli_phase_max; /**< max. abs. milli_phase */
+ uint32_t supp_shapes; /**< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPES */
+ uint32_t reserved; /**< currently always 0 */
+ uint32_t flags; /**< currently always 0 */
+
+} MBG_GPIO_FREQ_OUT_SUPP;
+
+
+
+/**
+ * @brief Supported fixed frequencies
+ */
+enum MBG_GPIO_FIXED_FREQ
+{
+ MBG_GPIO_FIXED_FREQ_8kHz, /**< 8kHz */
+ MBG_GPIO_FIXED_FREQ_48kHz, /**< 48kHz */
+ MBG_GPIO_FIXED_FREQ_1MHz, /**< 1MHz */
+ MBG_GPIO_FIXED_FREQ_1544kHz, /**< 1.544MHz */
+ MBG_GPIO_FIXED_FREQ_2048kHz, /**< 2.048MHz */
+ MBG_GPIO_FIXED_FREQ_5MHz, /**< 5MHz */
+ MBG_GPIO_FIXED_FREQ_10MHz, /**< 10MHz */
+ MBG_GPIO_FIXED_FREQ_19440kHz, /**< 19.44MHz */
+ N_MBG_GPIO_FIXED_FREQ /**< number of known frequencies */
+};
+
+/** Bit masks of supported fixed frequencies */
+#define MSK_MBG_GPIO_FIXED_FREQ_8kHz ( 1UL << MBG_GPIO_FIXED_FREQ_8kHz )
+#define MSK_MBG_GPIO_FIXED_FREQ_48kHz ( 1UL << MBG_GPIO_FIXED_FREQ_48kHz )
+#define MSK_MBG_GPIO_FIXED_FREQ_1MHz ( 1UL << MBG_GPIO_FIXED_FREQ_1MHz )
+#define MSK_MBG_GPIO_FIXED_FREQ_1544kHz ( 1UL << MBG_GPIO_FIXED_FREQ_1544kHz )
+#define MSK_MBG_GPIO_FIXED_FREQ_2048kHz ( 1UL << MBG_GPIO_FIXED_FREQ_2048kHz )
+#define MSK_MBG_GPIO_FIXED_FREQ_5MHz ( 1UL << MBG_GPIO_FIXED_FREQ_5MHz )
+#define MSK_MBG_GPIO_FIXED_FREQ_10MHz ( 1UL << MBG_GPIO_FIXED_FREQ_10MHz )
+#define MSK_MBG_GPIO_FIXED_FREQ_19440kHz ( 1UL << MBG_GPIO_FIXED_FREQ_19440kHz )
+
+/*
+ * Initializers for GPIO fixed frequency strings.
+ */
+#define MBG_GPIO_FIXED_FREQ_STRS \
+{ \
+ "8kHz", \
+ "48kHz", \
+ "1MHz", \
+ "1544kHz", \
+ "2048kHz", \
+ "5MHz", \
+ "10MHz", \
+ "19440kHz" \
+}
+
+
+/**
+ * @brief Configuration of a GPIO fixed frequency output
+ *
+ * @see MBG_GPIO_TYPE_FIXED_FREQ_OUT
+ */
+typedef struct
+{
+ uint32_t freq_idx; /**< fixed frequency index, see ::MBG_GPIO_FIXED_FREQ */
+ uint32_t shape; /**< signal shape, see ::MBG_GPIO_SIGNAL_SHAPES */
+ uint32_t reserved; /**< currently always 0 */
+ uint32_t flags; /**< currently always 0 */
+
+} MBG_GPIO_FIXED_FREQ_OUT_SETTINGS;
+
+
+/**
+ * @brief Supported options for a fixed frequency output
+ *
+ * @see MBG_GPIO_TYPE_FIXED_FREQ_OUT
+ */
+typedef struct
+{
+ uint32_t supp_freq; /**< bit mask of supported fixed frequencies, see ::MBG_GPIO_FIXED_FREQ */
+ uint32_t supp_shapes; /**< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPES */
+ uint32_t reserved; /**< currently always 0 */
+ uint32_t supp_flags; /**< currently always 0 */
+
+} MBG_GPIO_FIXED_FREQ_OUT_SUPP;
+
+
+
+/**
+ * @brief Definitions for MBG_GPIO_BITS::format
+ */
+enum MBG_GPIO_BITS_FORMATS
+{
+ MBG_GPIO_BITS_E1_FRAMED, /**< 2.048MBit */
+ MBG_GPIO_BITS_T1_FRAMED, /**< 1.544MBit */
+ MBG_GPIO_BITS_E1_TIMING, /**< 2.048MHz */
+ MBG_GPIO_BITS_T1_TIMING, /**< 2.048MHz */
+ N_MBG_GPIO_BITS_FORMATS /**< number of formats */
+};
+
+#define MSK_MBG_GPIO_BITS_E1_FRAMED ( 1UL << MBG_GPIO_BITS_E1_FRAMED )
+#define MSK_MBG_GPIO_BITS_T1_FRAMED ( 1UL << MBG_GPIO_BITS_T1_FRAMED )
+#define MSK_MBG_GPIO_BITS_E1_TIMING ( 1UL << MBG_GPIO_BITS_E1_TIMING )
+#define MSK_MBG_GPIO_BITS_T1_TIMING ( 1UL << MBG_GPIO_BITS_T1_TIMING )
+
+
+
+/**
+ * @brief Configuration of a GPIO as BITS input module
+ *
+ * @see MBG_GPIO_TYPE_BITS_IN
+ */
+typedef struct
+{
+ uint32_t format; /**< signal type, see ::MBG_GPIO_BITS_FORMATS */
+ uint32_t reserved;
+ uint32_t csc_limit; /**< max. cycle slip [1/1000 cycle units] */
+
+ union
+ {
+ struct
+ {
+ uint8_t ssm; /**< minimum E1 SSM ( 0...15 ) for acceptance */
+ uint8_t sa_bits; /**< Sa Bits group ( 4...8 ) carrying SSM */
+ uint16_t reserve;
+ } e1; /**< used with E1 formats */
+
+ struct
+ {
+ uint8_t min_boc;
+ uint8_t reserve_0;
+ uint16_t reserve_1;
+ } t1; /**< used with T1 formats */
+
+ uint32_t u32; /**< dummy to force at least 32 bit alignment */
+
+ } quality;
+
+ uint32_t err_msk; /**< controls which types of error can be ignored, see enum MBG_GPIO_BITS_ERR */
+ uint32_t flags; /**< currently always 0 */
+
+} MBG_GPIO_BITS_IN_SETTINGS;
+
+
+/**
+ * @brief Definitions for MBG_GPIO_BITS_IN_SETTINGS::err_msk
+ */
+enum MBG_GPIO_BITS_ERR
+{
+ MBG_GPIO_BITS_ERR_LOS, /**< loss of signal error */
+ MBG_GPIO_BITS_ERR_LOF, /**< loss of frame */
+ N_MBG_GPIO_BITS_ERR /**< number of formats */
+};
+
+#define MSK_MBG_GPIO_BITS_ERR_LOS ( 1UL << MBG_GPIO_BITS_ERR_LOS )
+#define MSK_MBG_GPIO_BITS_ERR_LOF ( 1UL << MBG_GPIO_BITS_ERR_LOF )
+
+
+
+/**
+ * @brief Supported options of a BITS GPIO input
+ *
+ * @see MBG_GPIO_TYPE_BITS_IN
+ */
+typedef struct
+{
+ uint32_t supp_fmts; ///< bit mask of supported formats, see ::MBG_GPIO_BITS_FORMATS
+ uint32_t reserved; ///< reserved, currently always 0
+
+} MBG_GPIO_BITS_IN_SUPP;
+
+
+
+/**
+ * @brief Configuration of a GPIO as BITS output module
+ *
+ * @see MBG_GPIO_TYPE_BITS_OUT
+ */
+typedef struct
+{
+ uint32_t format; /**< signal type, enum MBG_GPIO_BITS_FORMATS */
+ uint32_t flags; /**< flags for encoder control etc. */
+ uint8_t sa_bits; /**< number of SA Bit group for E1 SSM ( 4...8 ) */
+ uint8_t ssm; /**< ssm for E1 mode 0..0x0F */
+ uint8_t boc; /**< boc for T1 mode 0..0x1F */
+ uint8_t reserved_0;
+ uint32_t reserved_1;
+ uint32_t reserved_2;
+ uint32_t reserved_3;
+
+} MBG_GPIO_BITS_OUT_SETTINGS;
+
+
+/**
+ * @brief Definitions for MBG_GPIO_BITS_OUT_SETTINGS::flags
+ */
+enum MBG_GPIO_BITS_OUT_FLAG
+{
+ MBG_GPIO_BITS_OUT_FLAG_HDB3, /**< enable HDB3 encoding ( E1 mode only ) */
+ MBG_GPIO_BITS_OUT_FLAG_B8ZS, /**< enable B8ZS encoding ( T1 mode only ) */
+ N_MBG_GPIO_BITS_OUT_FLAG /**< number of flags */
+};
+
+#define MSK_MBG_GPIO_BITS_OUT_FLAG_HDB3 ( 1UL << MBG_GPIO_BITS_OUT_FLAG_HDB3 )
+#define MSK_MBG_GPIO_BITS_OUT_FLAG_B8ZS ( 1UL << MBG_GPIO_BITS_OUT_FLAG_B8ZS )
+
+
+/**
+ * @brief Supported options of a BITS GPIO output
+ *
+ * @see MBG_GPIO_TYPE_BITS_OUT
+ */
+typedef struct
+{
+ uint32_t supp_fmts; /**< bit mask of supported formats, see ::MBG_GPIO_BITS_FORMATS */
+ uint32_t reserved; /**< currently always 0 */
+} MBG_GPIO_BITS_OUT_SUPP;
+
+
+/**
+ * @brief A generic structure used to configure a GPIO port
+ */
+typedef struct
+{
+ uint32_t type; /**< GPIO type, see ::MBG_GPIO_TYPES */
+ uint32_t reserved; /**< currently always 0 */
+ uint32_t flags; /**< currently always 0 */
+
+ union /**< settings depending on the GPIO type, see ::MBG_GPIO_TYPES */
+ {
+ MBG_GPIO_FREQ_IN_SETTINGS freq_in; /**< if type is MBG_GPIO_TYPE_FREQ_IN */
+ MBG_GPIO_FREQ_OUT_SETTINGS freq_out; /**< if type is MBG_GPIO_TYPE_FREQ_OUT */
+ MBG_GPIO_FIXED_FREQ_OUT_SETTINGS ff_out; /**< if type is MBG_GPIO_TYPE_FIXED_FREQ_OUT */
+ MBG_GPIO_BITS_IN_SETTINGS bits_in; /**< if type is MBG_GPIO_TYPE_BITS_IN */
+ MBG_GPIO_BITS_OUT_SETTINGS bits_out; /**< if type is MBG_GPIO_TYPE_BITS_OUT */
+ } u;
+
+} MBG_GPIO_SETTINGS;
+
+
+
+/**
+ * @brief A generic structure used to describe a GPIO ports limiting values
+ */
+typedef struct
+{
+ uint32_t type; /**< GPIO type, see ::MBG_GPIO_TYPES */
+ uint32_t reserved; /**< currently always 0 */
+ uint32_t supp_flags; /**< supported flags */
+
+ union /**< limits depending on the GPIO type, see ::MBG_GPIO_TYPES */
+ {
+ MBG_GPIO_FREQ_IN_SUPP freq_in; /**< if type is MBG_GPIO_TYPE_FREQ_IN */
+ MBG_GPIO_FREQ_OUT_SUPP freq_out; /**< if type is MBG_GPIO_TYPE_FREQ_OUT */
+ MBG_GPIO_FIXED_FREQ_OUT_SUPP ff_out; /**< if type is MBG_GPIO_TYPE_FIXED_FREQ_OUT */
+ MBG_GPIO_BITS_IN_SUPP bits_in; /**< if type is MBG_GPIO_TYPE_BITS_IN */
+ MBG_GPIO_BITS_OUT_SUPP bits_out; /**< if type is MBG_GPIO_TYPE_BITS_OUT */
+ } u;
+
+} MBG_GPIO_LIMITS;
+
+
+
+/**
+ * @brief A structure used to configure a specific GPIO port
+ */
+typedef struct
+{
+ uint32_t idx; /**< port number, 0..(MBG_GPIO_CFG_LIMITS::num_io - 1) */
+ MBG_GPIO_SETTINGS settings; /**< configuration settings */
+
+} MBG_GPIO_SETTINGS_IDX;
+
+
+
+/**
+ * @brief A structure used query the current GPIO port settings and capabilities
+ */
+typedef struct
+{
+ MBG_GPIO_SETTINGS settings; /**< current configuration */
+ MBG_GPIO_LIMITS limits; /**< supp. and max. values */
+
+} MBG_GPIO_INFO;
+
+
+
+/**
+ * @brief A structure used to query configuration and capabilities of a specific GPIO port
+ */
+typedef struct
+{
+ uint32_t idx; /**< port number, 0..(MBG_GPIO_CFG_LIMITS::num_io - 1) */
+ MBG_GPIO_INFO info; /**< current settings and capabilities of this GPIO port */
+
+} MBG_GPIO_INFO_IDX;
+
+
+/** @} group_gpio */
+
+
+
+/**
+ * @defgroup group_havequick GPIO port configuration stuff
+ *
+ * @note This is only supported if the ::GPS_HAS_HAVEQUICK bit is set
+ * in the RECEIVER_INFO::features mask.
+ *
+ * @{ */
+
+
+/**
+ * @brief Enumeration of HaveQuick formats
+ *
+ * @see HAVEQUICK_SETTINGS::format
+ * @see HAVEQUICK_FORMAT_MASKS
+ */
+enum HAVEQUICK_FORMATS
+{
+ HQ_FMT_STANAG4246_1,
+ HQ_FMT_STANAG4246_2,
+ HQ_FMT_STANAG4246_PTTI,
+ HQ_FMT_STANAG4372_SATURN_1,
+ HQ_FMT_STANAG4372_SATURN_2,
+ HQ_FMT_STANAG4430_EXTD,
+ N_HQ_FMT ///< number of known formats
+};
+
+
+/**
+ * @brief Bit masks associated to enumerated HaveQuick formats
+ *
+ * @see HAVEQUICK_INFO::supp_formats
+ * @see HAVEQUICK_FORMATS
+ */
+enum HAVEQUICK_FORMAT_MASKS
+{
+ HQ_MSK_STANAG4246_1 = ( 1UL << HQ_FMT_STANAG4246_1 ), ///< see ::HQ_FMT_STANAG4246_1
+ HQ_MSK_STANAG4246_2 = ( 1UL << HQ_FMT_STANAG4246_2 ), ///< see ::HQ_FMT_STANAG4246_2
+ HQ_MSK_STANAG4246_PTTI = ( 1UL << HQ_FMT_STANAG4246_PTTI ), ///< see ::HQ_FMT_STANAG4246_PTTI
+ HQ_MSK_STANAG4372_SATURN_1 = ( 1UL << HQ_FMT_STANAG4372_SATURN_1 ), ///< see ::HQ_FMT_STANAG4372_SATURN_1
+ HQ_MSK_STANAG4372_SATURN_2 = ( 1UL << HQ_FMT_STANAG4372_SATURN_2 ), ///< see ::HQ_FMT_STANAG4372_SATURN_2
+ HQ_MSK_STANAG4430_EXTD = ( 1UL << HQ_FMT_STANAG4430_EXTD ) ///< see ::HQ_FMT_STANAG4430_EXTD
+};
+
+
+/**
+ * @brief Configuration settings for a HaveQuick input or output
+ */
+typedef struct
+{
+ uint16_t format; ///< see ::HAVEQUICK_FORMATS
+ uint16_t flags; ///< see ::HAVEQUICK_FLAG_MASKS
+ int32_t offset; ///< Tx: unused, Rx: offset of incoming time in [s]
+ uint32_t reserved_0; ///< reserved, currently always 0
+ uint32_t reserved_1; ///< reserved, currently always 0
+} HAVEQUICK_SETTINGS;
+
+
+/**
+ * @brief Current settings and capabilities of a HaveQuick input or output
+ */
+typedef struct
+{
+ HAVEQUICK_SETTINGS settings; ///< current settings
+ uint32_t supp_formats; ///< see ::HAVEQUICK_FORMAT_MASKS
+ uint16_t supp_flags; ///< mask of flags supported in settings, see ::HAVEQUICK_FLAG_MASKS
+ uint16_t reserved; ///< reserved, currently always 0
+} HAVEQUICK_INFO;
+
+
+/**
+ * @brief Known HaveQuick control flags
+ *
+ * @see HAVEQUICK_FLAG_MASKS
+ */
+enum HAVEQUICK_FLAG_BITS
+{
+ HQ_FLAG_TX_GEN_LOCAL_TIME,
+ HQ_FLAG_SIGNAL_INVERTED,
+ HQ_FLAG_USE_EXT_PPS,
+ N_HQ_FLAG_BITS
+};
+
+
+/**
+ * @brief Bit masks associated to HaveQuick control flags
+ *
+ * @see HQ_SETTINGS::flags
+ * @see HQ_INFO::flags
+ * @see HAVEQUICK_FLAG_BITS
+ */
+enum HAVEQUICK_FLAG_MASKS
+{
+ HQ_MSK_TX_GEN_LOCAL_TIME = ( 1UL << HQ_FLAG_TX_GEN_LOCAL_TIME ), ///< see ::HQ_FLAG_TX_GEN_LOCAL_TIME
+ HQ_MSK_SIGNAL_INVERTED = ( 1UL << HQ_FLAG_SIGNAL_INVERTED ), ///< see ::HQ_FLAG_SIGNAL_INVERTED
+ HQ_MSK_USE_EXT_PPS = ( 1UL << HQ_FLAG_USE_EXT_PPS ) ///< see ::HQ_FLAG_USE_EXT_PPS
+};
+
+
+/** @} group_havequick */
+
+
+
+/**
+ * @defgroup group_evt_log Event logging support
+ *
+ * @note This is only available if ::GPS_HAS_EVT_LOG is set in RECEIVER_INFO::features.
+ *
+ * @{ */
+
+/** @brief Number of event log entries that can be stored and yet have been saved */
+typedef struct
+{
+ uint32_t used; /**< current number of saved log entries */
+ uint32_t max; /**< max number of log entries which can be saved */
+} MBG_NUM_EVT_LOG_ENTRIES;
+
+#define _mbg_swab_mbg_num_evt_log_entries( _p ) \
+{ \
+ _mbg_swab32( &(_p)->used ); \
+ _mbg_swab32( &(_p)->max ); \
+}
+
+
+typedef uint16_t MBG_EVT_CODE;
+#define _mbg_swab_evt_code( _p ) _mbg_swab16( _p );
+
+typedef uint16_t MBG_EVT_INFO;
+#define _mbg_swab_evt_info( _p ) _mbg_swab16( _p );
+
+/**
+ * @brief An event log entry
+ */
+ typedef struct
+ {
+ uint32_t time; /**< like time_t, seconds since 1970 */
+ MBG_EVT_CODE code; /**< event ID or'ed with severity level */
+ MBG_EVT_INFO info; /**< optional event info, depending on event ID */
+ } MBG_EVT_LOG_ENTRY;
+
+#define _mbg_swab_mbg_evt_log_entry( _p ) \
+{ \
+ _mbg_swab32( &(_p)->time ); \
+ _mbg_swab_evt_code( &(_p)->code ); \
+ _mbg_swab_evt_info( &(_p)->info ); \
+}
+
+
+// MBG_EVT_LOG_ENTRY::code is a combination of some bits used for the ID,
+// plus some bits used for the severity/level. The sum of bits must not
+// exceed (8 * sizeof MBG_EVT_LOG_ENTRY::code):
+
+#define MBG_EVT_ID_BITS 13
+#define MBG_EVT_LVL_BITS 3
+
+#define MBG_EVT_ID_MASK ( (MBG_EVT_CODE) ( 1UL << MBG_EVT_ID_BITS ) - 1 )
+#define MBG_EVT_LVL_MASK ( (MBG_EVT_CODE) ( 1UL << MBG_EVT_LVL_BITS ) - 1 )
+
+
+// Combine an ID and Level to a code which can be stored
+// in the code field:
+#define _mbg_mk_evt_code( _id, _lvl ) \
+ ( (MBG_EVT_CODE) ( (MBG_EVT_CODE)(_id) | ( (MBG_EVT_CODE)(_lvl) << MBG_EVT_ID_BITS ) ) )
+
+// Extract the event ID from the code field:
+#define _mbg_get_evt_id( _code ) \
+ ( (_code) & MBG_EVT_ID_MASK )
+
+// Extract the severity level from the code field:
+#define _mbg_get_evt_lvl( _code ) \
+ ( ( (_code) >> MBG_EVT_ID_BITS ) & MBG_EVT_LVL_MASK )
+
+
+/**
+ * @brief Enumeration of event IDs
+ */
+enum MBG_EVT_IDS
+{
+ MBG_EVT_ID_NONE, /**< no event (empty entry) */
+ MBG_EVT_ID_POW_UP_RES, /**< power up reset */
+ MBG_EVT_ID_WDOG_RES, /**< watchdog reset */
+ MBG_EVT_ID_COLD_BOOT, /**< entering cold boot mode */
+ MBG_EVT_ID_WARM_BOOT, /**< entering warm boot mode */
+ MBG_EVT_ID_NORMAL_OP, /**< entering normal operation */
+ MBG_EVT_ID_ANT_DISCONN, /**< antenna disconnect detected */
+ MBG_EVT_ID_ANT_SHORT, /**< antenna short circuit detected */
+ MBG_EVT_ID_ANT_OK, /**< antenna OK after failure */
+ MBG_EVT_ID_LOW_SATS, /**< no satellites can be received though antenna not failing */
+ N_MBG_EVT_ID
+};
+
+
+#define ENG_EVT_ID_NAME_NONE "No event"
+#define ENG_EVT_ID_NAME_POW_UP_RES "Power Up Reset"
+#define ENG_EVT_ID_NAME_WDOG_RES "Watchdog Reset"
+#define ENG_EVT_ID_NAME_COLD_BOOT "Cold Boot"
+#define ENG_EVT_ID_NAME_WARM_BOOT "Warm Boot"
+#define ENG_EVT_ID_NAME_NORMAL_OP "Normal Operation"
+#define ENG_EVT_ID_NAME_ANT_DISCONN "Antenna Disconn."
+#define ENG_EVT_ID_NAME_ANT_SHORT "Ant. Short-Circ."
+#define ENG_EVT_ID_NAME_ANT_OK "Antenna OK"
+#define ENG_EVT_ID_NAME_LOW_SATS "Few Sats Only"
+
+
+#define MBG_EVT_ID_NAMES_ENG \
+{ \
+ ENG_EVT_ID_NAME_NONE, \
+ ENG_EVT_ID_NAME_POW_UP_RES, \
+ ENG_EVT_ID_NAME_WDOG_RES, \
+ ENG_EVT_ID_NAME_COLD_BOOT, \
+ ENG_EVT_ID_NAME_WARM_BOOT, \
+ ENG_EVT_ID_NAME_NORMAL_OP, \
+ ENG_EVT_ID_NAME_ANT_DISCONN, \
+ ENG_EVT_ID_NAME_ANT_SHORT, \
+ ENG_EVT_ID_NAME_ANT_OK, \
+ ENG_EVT_ID_NAME_LOW_SATS \
+}
+
+
+
+/**
+ * @brief Enumeration of event severity levels
+ */
+enum MBG_EVT_LVLS
+{
+ MBG_EVT_LVL_NONE,
+ MBG_EVT_LVL_DEBUG,
+ MBG_EVT_LVL_INFO,
+ MBG_EVT_LVL_WARN,
+ MBG_EVT_LVL_ERR,
+ MBG_EVT_LVL_CRIT,
+ N_MBG_EVT_LVL
+};
+
+
+#define ENG_EVT_LVL_NAME_NONE "None"
+#define ENG_EVT_LVL_NAME_DEBUG "Debug"
+#define ENG_EVT_LVL_NAME_INFO "Info"
+#define ENG_EVT_LVL_NAME_WARN "Warn"
+#define ENG_EVT_LVL_NAME_ERR "Err"
+#define ENG_EVT_LVL_NAME_CRIT "Crit."
+
+
+#define MBG_EVT_LVL_NAMES_ENG \
+{ \
+ ENG_EVT_LVL_NAME_NONE, \
+ ENG_EVT_LVL_NAME_DEBUG, \
+ ENG_EVT_LVL_NAME_INFO, \
+ ENG_EVT_LVL_NAME_WARN, \
+ ENG_EVT_LVL_NAME_ERR, \
+ ENG_EVT_LVL_NAME_CRIT \
+}
+
+
+/** @brief Predefined event codes with associated severity levels */
+
+#define MBG_EVT_NONE _mbg_mk_evt_code( MBG_EVT_ID_NONE, MBG_EVT_LVL_NONE )
+#define MBG_EVT_POW_UP_RES _mbg_mk_evt_code( MBG_EVT_ID_POW_UP_RES, MBG_EVT_LVL_WARN )
+#define MBG_EVT_WDOG_RES _mbg_mk_evt_code( MBG_EVT_ID_WDOG_RES, MBG_EVT_LVL_CRIT )
+#define MBG_EVT_COLD_BOOT _mbg_mk_evt_code( MBG_EVT_ID_COLD_BOOT, MBG_EVT_LVL_ERR )
+#define MBG_EVT_WARM_BOOT _mbg_mk_evt_code( MBG_EVT_ID_WARM_BOOT, MBG_EVT_LVL_ERR )
+#define MBG_EVT_NORMAL_OP _mbg_mk_evt_code( MBG_EVT_ID_NORMAL_OP, MBG_EVT_LVL_INFO )
+#define MBG_EVT_ANT_DISCONN _mbg_mk_evt_code( MBG_EVT_ID_ANT_DISCONN, MBG_EVT_LVL_CRIT )
+#define MBG_EVT_ANT_SHORT _mbg_mk_evt_code( MBG_EVT_ID_ANT_SHORT, MBG_EVT_LVL_CRIT )
+#define MBG_EVT_ANT_OK _mbg_mk_evt_code( MBG_EVT_ID_ANT_OK, MBG_EVT_LVL_INFO )
+#define MBG_EVT_LOW_SATS _mbg_mk_evt_code( MBG_EVT_ID_LOW_SATS, MBG_EVT_LVL_WARN )
+
+/** @} group_evt_log */
+
+
+
+/**
+ * @defgroup group_ims IMS support
+ *
+ * @note This is only available if ::GPS_HAS_IMS is set in RECEIVER_INFO::features.
+ *
+ * @{ */
+
+/**
+ * @brief Generic state of an IMS device
+ */
+typedef struct
+{
+ uint8_t chassis_id; /**< chassis ID, 0 if installed on the backplane */
+ uint8_t slot_id; /**< slot number on the chassis */
+ uint16_t num_sensors; /**< number of sensors provided by the device */
+ uint32_t reserved; /**< currently unused, always 0 */
+ uint32_t flags; /**< currently unused, always 0 */
+
+} MBG_IMS_STATE;
+
+#define _mbg_swab_mbg_ims_state( _p ) \
+{ \
+ _mbg_swab16( &(_p)->num_sensors ); \
+ _mbg_swab32( &(_p)->reserved ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+
+/**
+ * @brief Generic state of an IMS sensor
+ */
+typedef struct
+{
+ uint16_t type; /**< sensor type, see ::MBG_IMS_SENSORS */
+ uint16_t idx; /**< index of the sensor of this type */
+ int32_t val; /**< sensor value, in units according to the type */
+ int16_t exp; /**< 10s exponent of the sensor value */
+ uint16_t reserved; /**< currently unused, always 0 */
+ uint32_t flags; /**< currently unused, always 0 */
+
+} MBG_IMS_SENSOR_STATE;
+
+#define _mbg_swab_mbg_ims_sensor_state( _p ) \
+{ \
+ _mbg_swab16( &(_p)->type ); \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab32( &(_p)->val ); \
+ _mbg_swab16( &(_p)->exp ); \
+ _mbg_swab16( &(_p)->reserved ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Generic state of an IMS sensor, with sensor index
+ */
+typedef struct
+{
+ uint32_t idx; /**< sensor index, 0..MBG_IMS_STATE::num_sensors - 1 */
+ MBG_IMS_SENSOR_STATE state; /**< sensor state */
+
+} MBG_IMS_SENSOR_STATE_IDX;
+
+#define _mbg_swab_mbg_ims_sensor_state_idx( _p ) \
+{ \
+ _mbg_swab32( &(_p)->idx ); \
+ _mbg_swab_mbg_ims_sensor_state( &(_p)->state ); \
+}
+
+
+
+/**
+ * @brief IMS sensor types
+ */
+enum MBG_IMS_SENSORS
+{
+ MBG_IMS_SENSOR_TEMP_C, /**< temperature in degrees C */
+ MBG_IMS_SENSOR_VOLTAGE, /**< voltage in val/exp, output state in flags */
+ MBG_IMS_SENSOR_PLL, /**< control voltage in val/exp, lock state in flags */
+ N_MBG_IMS_SENSORS /**< number of supported sensor types */
+};
+
+
+
+// Definitions used with MBG_IMS_SENSOR_STATE::flags:
+
+// if MBG_IMS_SENSOR_STATE::type == MBG_IMS_SENSOR_VOLTAGE:
+#define MBG_IMS_SENSOR_VOLTAGE_OUT_ENB 0x01 // output is enabled
+#define MBG_IMS_SENSOR_VOLTAGE_OUT_OVR 0x02 // output overload
+
+// if MBG_IMS_SENSOR_STATE::type == MBG_IMS_SENSOR_PLL:
+#define MBG_IMS_SENSOR_PLL_LOCKED 0x01
+
+
+/** @} group_ims */
+
+
+
+/**
+ * @defgroup group_generic_io Generic I/O support.
+ *
+ * The definitions below are used with the GENERIC_IO API.
+ *
+ * This API is <b>NOT</b> supported by all devices, it depends on
+ * the type of the device, and the firmware version. The macro
+ * _pcps_has_generic_io() or the corresponding function
+ * mbg_dev_has_generic_io() should be used by applications to
+ * check whether a particular bus-level device supports this.
+ * @{ */
+
+
+typedef uint16_t GEN_IO_INFO_TYPE;
+
+#define _mbg_swab_gen_io_info_type( _p ) \
+ _mbg_swab16( _p )
+
+
+
+/**
+ * @brief The data structure used with the PCPS_GEN_IO_GET_INFO command
+ *
+ * type specifier in order to query from a device which of the other
+ * specified types is supported, and how many data sets are being
+ * used by the device. The GEN_IO_INFO_TYPE must be passed to the
+ * call which returns a GEN_IO_INFO structure filled by the device.
+ */
+typedef struct
+{
+ GEN_IO_INFO_TYPE type; // a PCPS_GEN_IO_GET_INFO type from the enum above
+ uint16_t num; // supported number of data sets of the specified type
+
+} GEN_IO_INFO;
+
+#define _mbg_swab_gen_io_info( _p ) \
+{ \
+ _mbg_swab_gen_io_info_type( &(_p)->type ); \
+ _mbg_swab16( &(_p)->num ); \
+}
+
+
+
+/**
+ * @brief Data types used with GEN_IO_INFO::type
+ *
+ * The first type specifier, PCPS_GEN_IO_GET_INFO, can
+ * be used to find out which of the other data types are
+ * supported, and how many data sets of the specified type
+ * are supported by a device.
+ */
+enum PCPS_GEN_IO_TYPES
+{
+ PCPS_GEN_IO_GET_INFO, /**< GEN_IO_INFO (read only) */
+ PCPS_GEN_IO_CAL_REC_IRIG_RX_COMP, /**< CAL_REC_IRIG_RX_COMP (read/write) */
+ N_PCPS_GEN_IO_TYPE /**< number of known types */
+};
+
+/** @} group_generic_io */
+
+
+/*------------------------------------------------------------------------*/
+
+/*
+ * The types below are not used with all devices:
+ */
+
+typedef uint16_t ROM_CSUM; /* The ROM checksum */
+typedef uint16_t RCV_TIMEOUT; /* [min] (only if HAS_RCV_TIMEOUT) */
+typedef uint16_t IGNORE_LOCK; /* (only if GPS_HAS_IGNORE_LOCK) */
+
+/*
+ * Originally IGNORE_LOG above has been a boolean value (equal or
+ * not equal 0) which was evaluated the same way for all ports.
+ *
+ * Due to special firmware requirements it has been changed to a
+ * bit maskable property in order to be able to specify the behaviour
+ * for individual ports.
+ *
+ * In order to keep compatibility with older versions the LSB is used
+ * to specify ignore_lock for all ports. The next higher bits are used
+ * to specify ignore_lock for an individual port, where the bit position
+ * depends on the port number, e.g. 0x02 for COM0, 0x04 for COM1, etc.
+ * The macros below can be used to simplify the code:
+ */
+
+/* return a bit mask depending on the port number */
+#define IGNORE_LOCK_FOR_ALL_PORTS 0x01
+
+#define _ignore_lock_for_all_ports() ( IGNORE_LOCK_FOR_ALL_PORTS )
+
+#define _ignore_lock_for_port( _n ) ( 0x02 << (_n) )
+
+/* check if all ports are ignore_lock'ed */
+#define _is_ignore_lock_all_ports( _il ) ( (_il) & IGNORE_LOCK_FOR_ALL_PORTS )
+
+/* check if a specific port is ignore_lock'ed */
+#define _is_ignore_lock_for_port( _il, _n ) \
+ ( (_il) & ( _ignore_lock_for_port(_n) | IGNORE_LOCK_FOR_ALL_PORTS ) )
+
+
+/*------------------------------------------------------------------------*/
+
+/*
+ * The structures below are used with the SCU multiplexer board
+ * in a redundant system:
+ */
+
+typedef struct
+{
+ uint32_t hw_id; // hardware identification
+ uint32_t fw_id; // firmware identification
+ uint16_t flags; // reserved currently 0
+ uint8_t clk0_info; // reference clock 0 type
+ uint8_t clk1_info; // reference clock 1 type
+ uint16_t epld_status; // epld status word, see defintions below
+ uint16_t epld_control; // epld control word, see defintions below
+} SCU_STAT_INFO;
+
+typedef struct
+{
+ uint16_t epld_control_mask; // control mask, determines which bit is to be changed
+ uint16_t epld_control_value; // control value, determines value of bits to be changed
+ uint32_t flags; // reserved, currently 0
+} SCU_STAT_SETTINGS;
+
+// definitions for status word bit masks
+#define MSK_EPLD_STAT_TS1 0x0001 // state of time sync signal clk_1
+#define MSK_EPLD_STAT_TS2 0x0002 // state of time sync signal clk_2
+#define MSK_EPLD_STAT_TL_ERROR 0x0004 // state of time limit error input
+#define MSK_EPLD_STAT_PSU1_OK 0x0008 // state of power supply 1 monitoring input
+#define MSK_EPLD_STAT_PSU2_OK 0x0010 // state of power supply 2 monitoring input
+#define MSK_EPLD_STAT_AUTO 0x0020 // AUTOMATIC/REMOTE or MANUAL Mode
+#define MSK_EPLD_STAT_SEL 0x0040 // select bit for output MUX, ( clk_1 = 0 )
+#define MSK_EPLD_STAT_ENA 0x0080 // enable Bit for output MUX, set if enabled
+#define MSK_EPLD_STAT_ACO 0x4000 // Access control override bit
+#define MSK_EPLD_STAT_WDOG_OK 0x8000 // WDT_OK set to zero if watchdog expired
+
+
+#define MSK_EPLD_CNTL_SEL_REM 0x0800 // remote select for output MUX ( clk_1 = 0 )
+#define MSK_EPLD_CNTL_DIS_REM 0x1000 // remote disable for output MUX
+#define MSK_EPLD_CNTL_REMOTE 0x2000 // must be set to enable remote operation
+#define MSK_EPLD_CNTL_SEL_SNMP 0x4000 // select clk for comm. ( clk1 = 0 )
+#define MSK_EPLD_CNTL_ENA_SNMP 0x8000 // connect COM0 channels to XPORT
+
+
+/**
+ * @brief Definitions for SCU_STAT_INFO::clk0_info and SCU_STAT_INFO::clk1_info
+ *
+ * Can be used to determine the reference clock type connected to the SCU input channels.
+ */
+enum SCU_CLK_INFO_TYPES
+{
+ SCU_CLK_INFO_GPS, ///< ref. clock is GPS receiver
+ SCU_CLK_INFO_DCF_PZF, ///< ref. clock is DCF77 PZF receiver
+ SCU_CLK_INFO_DCF_AM, ///< ref. clock is DCF77 AM receiver
+ SCU_CLK_INFO_TCR, ///< ref. clock is IRIG time code receiver
+ N_SCU_CLK_INFO ///< number of known types
+};
+
+
+
+/*------------------------------------------------------------------------*/
+
+/**
+ * @brief Satellite receiver modes of operation.
+ *
+ * @note Some of the code combinations are obsolete with recent
+ * satellite receivers. However, this doesn't matter since the mode
+ * is just read from the receiver.
+ */
+#define REMOTE 0x10
+#define BOOT 0x20
+
+#define TRACK ( 0x01 )
+#define AUTO_166 ( 0x02 )
+#define WARM_166 ( 0x03 | BOOT )
+#define COLD_166 ( 0x04 | BOOT )
+#define AUTO_BC ( 0x05 | REMOTE )
+#define WARM_BC ( 0x06 | REMOTE | BOOT )
+#define COLD_BC ( 0x07 | REMOTE | BOOT )
+#define UPDA_166 ( 0x08 | BOOT )
+#define UPDA_BC ( 0x09 | REMOTE | BOOT )
+
+
+
+typedef int16_t DAC_VAL;
+
+#define _mbg_swab_dac_val( _p ) \
+ _mbg_swab16( _p );
+
+
+
+/**
+ * @brief Satellite receiver status information
+ */
+typedef struct
+{
+ uint16_t mode; /**< Mode of operation, see predefined codes */
+ uint16_t good_svs; /**< Numb. of satellites that can currently be received and used */
+ uint16_t svs_in_view; /**< Numb. of satellites that should be in view according to the almanac data */
+ DAC_VAL dac_val; /**< Oscillator fine DAC value */
+ DAC_VAL dac_cal; /**< Oscillator calibration DAC value ( see #OSC_DAC_RANGE, #OSC_DAC_BIAS ) */
+} STAT_INFO;
+
+#define _mbg_swab_stat_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->mode ); \
+ _mbg_swab16( &(_p)->good_svs ); \
+ _mbg_swab16( &(_p)->svs_in_view ); \
+ _mbg_swab_dac_val( &(_p)->dac_val ); \
+ _mbg_swab_dac_val( &(_p)->dac_cal ); \
+}
+
+
+#define OSC_DAC_RANGE 4096UL
+#define OSC_DAC_BIAS ( OSC_DAC_RANGE / 2 )
+
+
+
+/**
+ * @brief An enumeration of known satellite navigation systems
+ */
+enum MBG_GNSS_TYPES
+{
+ GNSS_TYPE_GPS, ///< GPS, United States
+ GNSS_TYPE_GLONASS, ///< GLONASS, Russia
+ GNSS_TYPE_BEIDOU, ///< BEIDOU, China
+ GNSS_TYPE_GALILEO, ///< GALILEO, Europe
+ N_GNSS_TYPES ///< Number of defined codes
+};
+
+#define GNSS_TYPE_STRS \
+{ \
+ "GPS", \
+ "GLONASS", \
+ "BEIDOU" , \
+ "GALILEO" \
+}
+
+#define MBG_GNSS_TYPE_MSK_GPS ( 1UL << GNSS_TYPE_GPS )
+#define MBG_GNSS_TYPE_MSK_GLONASS ( 1UL << GNSS_TYPE_GLONASS )
+#define MBG_GNSS_TYPE_MSK_BEIDOU ( 1UL << GNSS_TYPE_BEIDOU )
+#define MBG_GNSS_TYPE_MSK_GALILEO ( 1UL << GNSS_TYPE_GALILEO )
+
+
+#define N_GNSS_MODE_PRIO 8
+
+typedef struct
+{
+ uint32_t gnss_set; /**< current set of GNSS types */
+ uint8_t prio[N_GNSS_MODE_PRIO]; /**< index 0 for highest priority, use GNSS enumeration above, init with 0xFF if not supported */
+ uint32_t flags; /**< see below */
+} MBG_GNSS_MODE_SETTINGS;
+
+#define _mbg_swab_mbg_gnss_mode_settings( _p ) \
+{ \
+ _mbg_swab32( &(_p)->gnss_set ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+
+typedef struct
+{
+ MBG_GNSS_MODE_SETTINGS settings; /**< current GNSS mode settings */
+ uint32_t supp_gnss_types; /**< bit masks of supported GNSS types */
+ uint32_t flags; /**< indicates which of the defined flags are supported by the device */
+} MBG_GNSS_MODE_INFO;
+
+#define _mbg_swab_mbg_gnss_mode_info( _p ) \
+{ \
+ _mbg_swab_mbg_gnss_mode_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->supp_gnss_types ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Flags used with MBG_GNSS_MODE_SETTINGS::flags and MBG_GNSS_MODE_INFO::flags
+ */
+enum MBG_GNSS_MODE_FLAG_BITS
+{
+ MBG_GNSS_FLAG_EXCLUSIVE, ///< (read only) only one of the supported GNSS systems can be used at the same time
+ MBG_GNSS_FLAG_HAS_PRIORITY, ///< (read only) priority can be configured using the MBG_GNSS_MODE_SETTINGS::prio field
+ N_MBG_GNSS_FLAGS
+};
+
+#define MBG_GNSS_FLAG_MSK_EXCLUSIVE ( 1UL << MBG_GNSS_FLAG_EXCLUSIVE )
+#define MBG_GNSS_FLAG_MSK_HAS_PRIORITY ( 1UL << MBG_GNSS_FLAG_HAS_PRIORITY )
+
+
+
+#define MAX_USED_SATS 32
+
+/**
+ * @brief SV information from a certain GNSS type.
+ */
+typedef struct
+{
+ uint8_t gnss_type; /**< GNSS type from the enumeration above */
+ uint8_t reserved;
+ uint16_t good_svs;
+ uint16_t svs_in_view;
+ uint8_t svs[MAX_USED_SATS];
+} GNSS_SAT_INFO;
+
+#define _mbg_swab_gnss_sat_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->good_svs ); \
+ _mbg_swab16( &(_p)->svs_in_view ); \
+}
+
+
+#ifndef _IDENT_DEFINED
+
+ typedef union
+ {
+ char c[16]; // as string which may NOT be terminated
+ int16_t wrd[8];
+ uint32_t lw[4];
+ } IDENT;
+
+ #define _IDENT_DEFINED
+#endif
+
+#define _mbg_swab_ident( _p ) \
+{ \
+ int i; \
+ for ( i = 0; i < 4; i++ ) \
+ _mbg_swab32( &(_p)->lw[i] ); \
+}
+
+/**
+ * @brief A data type used to configure the length of an antenna cable [m]
+ */
+typedef uint16_t ANT_CABLE_LEN;
+
+#define _mbg_swab_ant_cable_len( _p ) _mbg_swab16( _p )
+
+
+
+/**
+ * @defgroup group_ip4_cfg Simple configuration and status
+ * of an optional LAN interface.
+ *
+ * @note This is only supported if the flag ::GPS_HAS_LAN_IP4 is set
+ * in RECEIVER_INFO::features.
+ *
+ * @{ */
+
+
+/**
+ * @brief An IPv4 address
+ */
+typedef uint32_t IP4_ADDR;
+
+#define _mbg_swab_ip4_addr( _p ) \
+ _mbg_swab32( _p );
+
+
+/**
+ * @brief Settings of an IPv4 network interface
+ */
+typedef struct
+{
+ IP4_ADDR ip_addr; /**< the IP address */
+ IP4_ADDR netmask; /**< the network mask */
+ IP4_ADDR broad_addr; /**< the broadcast address */
+ IP4_ADDR gateway; /**< the default gateway */
+ uint16_t flags; /**< flags as specified below */
+ uint16_t vlan_cfg; /**< VLAN configuration, see below */
+
+} IP4_SETTINGS;
+
+#define _mbg_swab_ip4_settings( _p ) \
+{ \
+ _mbg_swab_ip4_addr( &(_p)->ip_addr ); \
+ _mbg_swab_ip4_addr( &(_p)->netmask ); \
+ _mbg_swab_ip4_addr( &(_p)->broad_addr ); \
+ _mbg_swab_ip4_addr( &(_p)->gateway ); \
+ _mbg_swab16( &(_p)->flags ); \
+ _mbg_swab16( &(_p)->vlan_cfg ); \
+}
+
+
+/**
+ * @brief Definitions used with IP4_SETTINGS::vlan_cfg
+ *
+ * @note IP4_SETTINGS::vlan_cfg contains a combination of
+ * a VLAN ID number plus a VLAN priority code.
+ */
+#define VLAN_ID_BITS 12 ///< number of bits to hold the ID
+#define N_VLAN_ID ( 1 << VLAN_ID_BITS ) ///< number of ID values
+#define MIN_VLAN_ID 0 ///< minimum ID value
+#define MAX_VLAN_ID ( N_VLAN_ID - 1 ) ///< maximum ID value
+
+// vlan_id = ( vlan_cfg >> VLAN_ID_SHIFT ) & VLAN_ID_MSK
+#define VLAN_ID_SHIFT 0
+#define VLAN_ID_MSK ( ( 1 << VLAN_ID_BITS ) - 1 )
+
+
+#define VLAN_PRIORITY_BITS 3 ///< number of bits to hold priority
+#define N_VLAN_PRIORITY ( 1 << VLAN_PRIORITY_BITS ) ///< number of priority values
+#define MIN_VLAN_PRIORITY 0 ///< minimum priority
+#define MAX_VLAN_PRIORITY ( N_VLAN_PRIORITY - 1 ) ///< maximum priority
+
+// vlan_priority = ( vlan_cfg >> VLAN_PRIORITY_SHIFT ) & VLAN_PRIORITY_MSK
+#define VLAN_PRIORITY_SHIFT ( ( 8 * sizeof( uint16_t ) ) - VLAN_PRIORITY_BITS )
+#define VLAN_PRIORITY_MSK ( ( 1 << VLAN_PRIORITY_BITS ) - 1 )
+
+/**
+ * @brief Macros used to encode/decode packed vlan_cfg variables
+ */
+#define _decode_vlan_id( _cfg ) ( ( (_cfg) >> VLAN_ID_SHIFT ) & VLAN_ID_MSK )
+#define _decode_vlan_priority( _cfg ) ( ( (_cfg) >> VLAN_PRIORITY_SHIFT ) & VLAN_PRIORITY_MSK )
+#define _encode_vlan_cfg( _id, _prty ) ( ( (_id) << VLAN_ID_SHIFT ) | ( (_prty) << VLAN_PRIORITY_SHIFT ) )
+
+
+#if 0 //##++ currently not used
+
+/* Misc configuration */
+
+typedef struct
+{
+ uint16_t id; /* service ID, see below */
+ uint16_t index; /* used if several same svcs must be cfg'd, e.g. DNS */
+ char host[50]; /* see below */
+
+} IP_CFG;
+
+
+
+/* Description of a service running on a device */
+
+typedef struct
+{
+ uint16_t id; /* service ID, see below */
+ uint16_t socket; /* the socket on which the service is listening */
+ uint32_t flags; /* see below */
+
+} IP_SERVICE;
+
+#endif // 0
+
+
+
+/**
+ * @brief A structure to holds the MAC address of a LAN interface
+ */
+typedef struct
+{
+ uint8_t b[6];
+} MBG_MAC_ADDR;
+
+
+
+/**
+ * @brief LAN interface information
+ *
+ * This structure can be retrieved from a device
+ * to check the device's capabilities.
+ */
+typedef struct
+{
+ uint16_t type; ///< type of LAN interface, see below
+ MBG_MAC_ADDR mac_addr; ///< MAC address
+ uint16_t ver_code; ///< version number, high byte.low byte, in hex
+ char ver_str[GPS_ID_STR_SIZE]; ///< version string
+ char sernum[GPS_ID_STR_SIZE]; ///< serial number
+ uint32_t rsvd_0; ///< reserved, currently always 0
+ uint16_t flags; ///< flags as specified below
+ uint16_t rsvd_1; ///< reserved, currently always 0
+
+} LAN_IF_INFO;
+
+#define _mbg_swab_lan_if_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->type ); \
+ _mbg_swab16( &(_p)->ver_code ); \
+ _mbg_swab32( &(_p)->rsvd_0 ); \
+ _mbg_swab16( &(_p)->flags ); \
+ _mbg_swab16( &(_p)->rsvd_1 ); \
+}
+
+
+
+/**
+ * @brief Codes used with LAN_IF_INFO::type
+ */
+enum LAN_IF_TYPES
+{
+ LAN_IF_TYPE_XPORT, ///< LAN interface on an XPORT
+ LAN_IF_TYPE_PTP, ///< LAN interface is a special PTP interface
+ N_LAN_IF_TYPE ///< number of defined LAN interface types
+};
+
+
+/**
+ * @brief Enumeration of flag bits used with IP4_SETTINGS::flags and LAN_IF_INFO::flags
+ *
+ * @see MBG_IP4_FLAG_MASKS
+ */
+enum MBG_IP4_FLAG_BITS
+{
+ IP4_BIT_DHCP, ///< DHCP supported (LAN_IF_INFO) / enabled (IP4_SETTINGS)
+ IP4_BIT_LINK, ///< used only in IP4_SETTINGS to report link state
+ IP4_BIT_VLAN, ///< VLAN supported (LAN_IF_INFO) / enabled (IP4_SETTINGS)
+ N_IP4_BIT ///< number of defined flag bits
+};
+
+/**
+ * @brief Bit masks used with IP4_SETTINGS::flags and LAN_IF_INFO::flags
+ *
+ * @see MBG_IP4_FLAG_BITS
+ */
+enum MBG_IP4_FLAG_MASKS
+{
+ IP4_MSK_DHCP = ( 1UL << IP4_BIT_DHCP ), ///< see ::IP4_BIT_DHCP
+ IP4_MSK_LINK = ( 1UL << IP4_BIT_LINK ), ///< see ::IP4_BIT_LINK
+ IP4_MSK_VLAN = ( 1UL << IP4_BIT_VLAN ), ///< see ::IP4_BIT_VLAN
+};
+
+/** @} group_ip4_cfg */
+
+
+
+/**
+ * @defgroup group_ptp Definitions used with PTP/IEEE1588
+ *
+ * @{ */
+
+/**
+ * @brief Enumeration of protocols possibly used with PTP
+ *
+ * @see PTP_NW_PROT_MASKS
+ */
+enum PTP_NW_PROTS
+{
+ PTP_NW_PROT_RESERVED, ///< reserved
+ PTP_NW_PROT_UDP_IPV4, ///< IPv4
+ PTP_NW_PROT_UDP_IPV6, ///< IPv6
+ PTP_NW_PROT_IEEE_802_3, ///< Ethernet (raw layer 2)
+ PTP_NW_PROT_DEVICE_NET, ///< DeviceNet
+ PTP_NW_PROT_CONTROL_NET, ///< ControlNet
+ PTP_NW_PROT_PROFINET, ///< ProfiNet
+ N_PTP_NW_PROT ///< number of defined protocols
+};
+
+
+/**
+ * @brief Bit masks for enumerated protocols possibly used with PTP
+ *
+ * @see PTP_NW_PROTS
+ */
+enum PTP_NW_PROT_MASKS
+{
+ PTP_NW_PROT_MSK_RESERVED = ( 1UL << PTP_NW_PROT_RESERVED ), ///< see ::PTP_NW_PROT_RESERVED
+ PTP_NW_PROT_MSK_UDP_IPV4 = ( 1UL << PTP_NW_PROT_UDP_IPV4 ), ///< see ::PTP_NW_PROT_UDP_IPV4
+ PTP_NW_PROT_MSK_UDP_IPV6 = ( 1UL << PTP_NW_PROT_UDP_IPV6 ), ///< see ::PTP_NW_PROT_UDP_IPV6
+ PTP_NW_PROT_MSK_IEEE_802_3 = ( 1UL << PTP_NW_PROT_IEEE_802_3 ), ///< see ::PTP_NW_PROT_IEEE_802_3
+ PTP_NW_PROT_MSK_DEVICE_NET = ( 1UL << PTP_NW_PROT_DEVICE_NET ), ///< see ::PTP_NW_PROT_DEVICE_NET
+ PTP_NW_PROT_MSK_CONTROL_NET = ( 1UL << PTP_NW_PROT_CONTROL_NET ), ///< see ::PTP_NW_PROT_CONTROL_NET
+ PTP_NW_PROT_MSK_PROFINET = ( 1UL << PTP_NW_PROT_PROFINET ) ///< see ::PTP_NW_PROT_PROFINET
+};
+
+
+
+/**
+ * @brief Name strings for the protocols possibly used with PTP
+ *
+ * @see PTP_NW_PROTS
+ */
+#define PTP_NW_PROT_STRS \
+{ \
+ "Reserved", \
+ "UDP/IPv4 (L3)", \
+ "UDP/IPv6 (L3)", \
+ "IEEE 802.3 (L2)", \
+ "DeviceNet", \
+ "ControlNet", \
+ "PROFINET" \
+}
+
+
+/**
+ * @brief Short name strings for the protocols possibly used with PTP
+ *
+ * @see PTP_NW_PROTS
+ */
+#define PTP_NW_PROT_STRS_SHORT \
+{ \
+ "RSV", \
+ "IP4", \
+ "IP6", \
+ "ETH", \
+ "DN", \
+ "CN", \
+ "PN" \
+}
+
+
+/**
+ * @brief Possible states of a PTP port
+ */
+enum PTP_PORT_STATES
+{
+ PTP_PORT_STATE_UNINITIALIZED, ///< uninitialized
+ PTP_PORT_STATE_INITIALIZING, ///< currently initializing
+ PTP_PORT_STATE_FAULTY, ///< faulty
+ PTP_PORT_STATE_DISABLED, ///< disabled
+ PTP_PORT_STATE_LISTENING, ///< listening for PTP packets
+ PTP_PORT_STATE_PRE_MASTER, ///< going to become master
+ PTP_PORT_STATE_MASTER, ///< master
+ PTP_PORT_STATE_PASSIVE, ///< passive
+ PTP_PORT_STATE_UNCALIBRATED, ///< uncalibrated
+ PTP_PORT_STATE_SLAVE, ///< slave
+ N_PTP_PORT_STATE ///< number of defined port states
+};
+
+
+/**
+ * @brief Name strings for the PTP port states
+ */
+#define PTP_PORT_STATE_STRS \
+{ \
+ "UNINITIALIZED", \
+ "INITIALIZING", \
+ "FAULTY", \
+ "DISABLED", \
+ "LISTENING", \
+ "PRE_MASTER", \
+ "MASTER", \
+ "PASSIVE", \
+ "UNCALIBRATED", \
+ "SLAVE" \
+}
+
+
+/**
+ * @brief An entry for a table of parameters which can not be accessed by an enumerated index
+ */
+typedef struct
+{
+ uint8_t value; ///< the parameter value
+ const char *name; ///< the parameter name
+} PTP_TABLE;
+
+
+
+/**
+ * @brief An enumeration of PTP delay mechanisms
+ *
+ * @note This is different than the numeric values specified
+ * in the published specs for IEEE1588. In addition, the specs
+ * define code 0x14 for "disabled".
+ *
+ * @see PTP_DELAY_MECH_MASKS
+ * @see PTP_DELAY_MECH_NAMES
+ */
+enum PTP_DELAY_MECHS
+{
+ PTP_DELAY_MECH_E2E, ///< End-to-End (in PTP2 specs: 0x01)
+ PTP_DELAY_MECH_P2P, ///< Peer-to-Peer (in PTP2 specs: 0x02)
+ N_PTP_DELAY_MECH ///< number of defined delay mechanisms
+};
+
+
+/**
+ * @brief Bit masks associated to enumerated PTP delay mechanisms
+ *
+ * @see PTP_DELAY_MECH_MASKS
+ */
+enum PTP_DELAY_MECH_MASKS
+{
+ PTP_DELAY_MECH_MSK_E2E = ( 1UL << PTP_DELAY_MECH_E2E ), ///< see ::PTP_DELAY_MECH_E2E
+ PTP_DELAY_MECH_MSK_P2P = ( 1UL << PTP_DELAY_MECH_E2E ) ///< see ::PTP_DELAY_MECH_E2E
+};
+
+
+#define PTP_DELAY_MECH_NAME_E2E "E2E"
+#define PTP_DELAY_MECH_NAME_P2P "P2P"
+
+/**
+ * @brief Name strings for the PTP delay mechanisms
+ *
+ * @see PTP_DELAY_MECHS
+ */
+#define PTP_DELAY_MECH_NAMES \
+{ \
+ PTP_DELAY_MECH_NAME_E2E, \
+ PTP_DELAY_MECH_NAME_P2P \
+}
+
+
+
+/**
+ * @brief An enumeration of accuracy classes used with PTP
+ *
+ * @note This enumeration does not start at 0 but with a bias
+ * specified by ::PTP_CLOCK_ACCURACY_NUM_BIAS.
+ *
+ * @see PTP_CLOCK_ACCURACY_STRS
+ */
+enum PTP_CLOCK_ACCURACIES
+{
+ PTP_CLOCK_ACCURACY_NUM_BIAS = 0x20,
+ PTP_CLOCK_ACCURACY_25ns = PTP_CLOCK_ACCURACY_NUM_BIAS,
+ PTP_CLOCK_ACCURACY_100ns,
+ PTP_CLOCK_ACCURACY_250ns,
+ PTP_CLOCK_ACCURACY_1us,
+ PTP_CLOCK_ACCURACY_2_5us,
+ PTP_CLOCK_ACCURACY_10us,
+ PTP_CLOCK_ACCURACY_25us,
+ PTP_CLOCK_ACCURACY_100us,
+ PTP_CLOCK_ACCURACY_250us,
+ PTP_CLOCK_ACCURACY_1ms,
+ PTP_CLOCK_ACCURACY_2_5ms,
+ PTP_CLOCK_ACCURACY_10ms,
+ PTP_CLOCK_ACCURACY_25ms,
+ PTP_CLOCK_ACCURACY_100ms,
+ PTP_CLOCK_ACCURACY_250ms,
+ PTP_CLOCK_ACCURACY_1s,
+ PTP_CLOCK_ACCURACY_10s,
+ PTP_CLOCK_ACCURACY_MORE_10s,
+ PTP_CLOCK_ACCURACY_RESERVED_1,
+ PTP_CLOCK_ACCURACY_RESERVED_2,
+ PTP_CLOCK_ACCURACY_RESERVED_3,
+ PTP_CLOCK_ACCURACY_RESERVED_4,
+ N_PTP_CLOCK_ACCURACY
+};
+
+
+/**
+ * @brief Name strings for PTP accuracy classes
+ *
+ * @note The enumeration does not start at 0 but with a bias
+ * specified by ::PTP_CLOCK_ACCURACY_NUM_BIAS, so this bias needs
+ * to be accounted for when accessing a string table.
+ *
+ * @see PTP_CLOCK_ACCURACIES
+ */
+#define PTP_CLOCK_ACCURACY_STRS \
+{ \
+ "< 25 ns", \
+ "< 100 ns", \
+ "< 250 ns", \
+ "< 1 us", \
+ "< 2.5 us", \
+ "< 10 us", \
+ "< 25 us", \
+ "< 100 us", \
+ "< 250 us", \
+ "< 1 ms", \
+ "< 2.5 ms", \
+ "< 10 ms", \
+ "< 25 ms", \
+ "< 100 ms", \
+ "< 250 ms", \
+ "< 1 s", \
+ "< 10 s", \
+ "more than 10 s", \
+ "reserved_1", \
+ "reserved_2", \
+ "reserved_3", \
+ "reserved_4" \
+}
+
+
+
+/**
+ * @brief Codes to specify the type of a time source used with PTP
+ *
+ * @see PTP_TIME_SOURCE_TABLE
+ */
+enum PTP_TIME_SOURCES
+{
+ PTP_TIME_SOURCE_ATOMIC_CLOCK = 0x10,
+ PTP_TIME_SOURCE_GPS = 0x20,
+ PTP_TIME_SOURCE_TERRESTRIAL_RADIO = 0x30,
+ PTP_TIME_SOURCE_PTP = 0x40,
+ PTP_TIME_SOURCE_NTP = 0x50,
+ PTP_TIME_SOURCE_HAND_SET = 0x60,
+ PTP_TIME_SOURCE_OTHER = 0x90,
+ PTP_TIME_SOURCE_INTERNAL_OSCILLATOR = 0xA0
+};
+
+
+
+/**
+ * @brief A table of PTP time source codes plus associated name strings
+ *
+ * @see PTP_TIME_SOURCES
+ */
+#define PTP_TIME_SOURCE_TABLE \
+{ \
+ { PTP_TIME_SOURCE_ATOMIC_CLOCK, "Atomic Clock" }, \
+ { PTP_TIME_SOURCE_GPS, "GPS" }, \
+ { PTP_TIME_SOURCE_TERRESTRIAL_RADIO, "Terrestrial Radio" }, \
+ { PTP_TIME_SOURCE_PTP, "PTP" }, \
+ { PTP_TIME_SOURCE_NTP, "NTP" }, \
+ { PTP_TIME_SOURCE_HAND_SET, "HAND SET" }, \
+ { PTP_TIME_SOURCE_OTHER, "OTHER" }, \
+ { PTP_TIME_SOURCE_INTERNAL_OSCILLATOR, "Internal Oscillator" }, \
+ { 0, NULL } \
+}
+
+
+/**
+ * @brief An enumeration of roles which can be taken by a PTP node
+ *
+ * @note A role in this context specifies a certain mode of operation.
+ * Depending on its specification a devices may not be able to take
+ * each of the specified roles.
+ *
+ * @see PTP_ROLE_STRS
+ * @see PTP_ROLE_STRS_SHORT
+ */
+enum PTP_ROLES
+{
+ PTP_ROLE_MULTICAST_SLAVE, ///< slave in multicast mode
+ PTP_ROLE_UNICAST_SLAVE, ///< slave in unicast mode
+ PTP_ROLE_MULTICAST_MASTER, ///< multicast master
+ PTP_ROLE_UNICAST_MASTER, ///< unicast master
+ PTP_ROLE_MULTICAST_AUTO, ///< multicast master or slave (auto selection)
+ N_PTP_ROLES ///< number of defined roles
+};
+
+#define PTP_ROLE_MSK_MULTICAST_SLAVE ( 1UL << PTP_ROLE_MULTICAST_SLAVE )
+#define PTP_ROLE_MSK_UNICAST_SLAVE ( 1UL << PTP_ROLE_UNICAST_SLAVE )
+#define PTP_ROLE_MSK_MULTICAST_MASTER ( 1UL << PTP_ROLE_MULTICAST_MASTER )
+#define PTP_ROLE_MSK_UNICAST_MASTER ( 1UL << PTP_ROLE_UNICAST_MASTER )
+#define PTP_ROLE_MSK_MULTICAST_AUTO ( 1UL << PTP_ROLE_MULTICAST_AUTO )
+
+#define PTP_ROLE_MSK_SLAVES ( PTP_ROLE_MSK_MULTICAST_SLAVE | PTP_ROLE_MSK_UNICAST_SLAVE )
+#define PTP_ROLE_MSK_MASTERS ( PTP_ROLE_MSK_MULTICAST_MASTER | PTP_ROLE_MSK_UNICAST_MASTER )
+
+
+/**
+ * @brief Name strings for defined PTP roles
+ *
+ * @see PTP_ROLES
+ * @see PTP_ROLE_STRS_SHORT
+ */
+#define PTP_ROLE_STRS \
+{ \
+ "Multicast Slave", \
+ "Unicast Slave", \
+ "Multicast Master", \
+ "Unicast Master", \
+ "Multicast (Auto)" \
+}
+
+
+/**
+ * @brief Short name strings for defined PTP roles
+ *
+ * @see PTP_ROLES
+ * @see PTP_ROLE_STRS
+ */
+#define PTP_ROLE_STRS_SHORT \
+{ \
+ "MCS", \
+ "UCS", \
+ "MCM", \
+ "UCM", \
+ "MC" \
+}
+
+
+/**
+ * @brief A PTP clock identity
+ *
+ * @note This usually consists of a 6 byte MAC address with
+ * 2 fixed bytes inserted, or all ones as wildcard.
+ */
+typedef struct
+{
+ uint8_t b[8];
+} PTP_CLOCK_ID;
+
+#define _mbg_swab_ptp_clock_id( _p ) _nop_macro_fnc() // nothing to swap
+
+#define PTP_CLOCK_ID_WILDCARD { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }
+
+
+/**
+ * @brief A PTP port ID
+ *
+ * @note This usually consists of a 6 byte MAC address with
+ * 2 fixed bytes inserted, or all ones as wildcard.
+ */
+typedef uint16_t PTP_PORT_ID;
+
+#define _mbg_swab_ptp_port_id( _p ) _mbg_swab16( _p )
+
+#define PTP_PORT_ID_WILDCARD 0xFFFF
+
+
+/**
+ * @brief An enumeration of time scales used with PTP
+ *
+ * @note The standard time scale used by PTP is TAI, which is a linear time scale.
+ * The protocol provides a %UTC offset to be able to convert TAI to compute %UTC, which
+ * can observe leap seconds. For the arbitrary time scale the %UTC offset is unspecified,
+ * so arbitrary time can be %UTC, or something else.
+ *
+ * @see PTP_TIMESCALE_NAMES
+ * @see PTP_TIMESCALE_NAMES_SHORT
+ */
+enum PTP_TIME_SCALES
+{
+ PTP_TIMESCALE_PTP, ///< PTP default, TAI
+ PTP_TIMESCALE_ARB, ///< arbitrary time scale, maybe %UTC
+ N_PTP_TIMESCALE
+};
+
+
+/**
+ * @brief Name strings for the PTP time scales
+ */
+#define PTP_TIMESCALE_NAME_PTP "PTP Standard (TAI)"
+#define PTP_TIMESCALE_NAME_ARB "Arbitrary"
+
+/**
+ * @brief Short name strings for the PTP time scales
+ */
+#define PTP_TIMESCALE_NAME_PTP_SHORT "PTP"
+#define PTP_TIMESCALE_NAME_ARB_SHORT "Arb"
+
+
+/**
+ * @brief A table of name strings for the PTP time scales
+ *
+ * @see PTP_TIME_SCALES
+ * @see PTP_TIMESCALE_NAMES_SHORT
+ */
+#define PTP_TIMESCALE_NAMES \
+{ \
+ PTP_TIMESCALE_NAME_PTP, \
+ PTP_TIMESCALE_NAME_ARB \
+}
+
+/**
+ * @brief A table of short name strings for the PTP time scales
+ *
+ * @see PTP_TIME_SCALES
+ * @see PTP_TIMESCALE_NAMES
+ */
+#define PTP_TIMESCALE_NAMES_SHORT \
+{ \
+ PTP_TIMESCALE_NAME_PTP_SHORT, \
+ PTP_TIMESCALE_NAME_ARB_SHORT \
+}
+
+
+
+/**
+ * @brief A structure to used to read the status of the PTP protocol stack
+ */
+typedef struct
+{
+ uint16_t nw_prot; ///< one of the enumerated protocols, see ::PTP_NW_PROTS
+ uint8_t ptp_prot_version; ///< PTP protocol version, 1, or 2, usually 2 for v2
+ uint8_t port_state; ///< one of the enumerated port states, see ::PTP_PORT_STATES
+ uint32_t flags; ///< see ::PTP_STATE_FLAGS
+ NANO_TIME offset; ///< estimated time offset from the upstream time source
+ NANO_TIME path_delay;
+ NANO_TIME mean_path_delay;
+ NANO_TIME delay_asymmetry;
+
+ PTP_CLOCK_ID gm_id; ///< identifier ot the upstream time source
+
+ uint16_t clock_offset_scaled_log_variance;
+ uint8_t clock_class;
+ uint8_t clock_accuracy; ///< see ::PTP_CLOCK_ACCURACIES
+
+ uint32_t reserved_1; ///< reserved, currently always 0
+ uint32_t reserved_2; ///< reserved, currently always 0
+
+ uint8_t domain_number; ///< the PTP clock domain number, 0:3
+ uint8_t time_source; ///< see ::PTP_TIME_SOURCES
+ uint8_t delay_mech; ///< see ::PTP_DELAY_MECHS
+ int8_t log_delay_req_intv;
+
+ int16_t utc_offset; ///< %UTC offset observed against TAI
+ DAC_VAL osc_dac_cal; ///< disciplination value of the oscillator
+
+ uint32_t reserved_3; ///< reserved, currently always 0
+
+} PTP_STATE;
+
+#define _mbg_swab_ptp_state( _p ) \
+{ \
+ _mbg_swab16( &(_p)->nw_prot ); \
+ _mbg_swab32( &(_p)->flags ); \
+ _mbg_swab_nano_time( &(_p)->offset ); \
+ _mbg_swab_nano_time( &(_p)->path_delay ); \
+ _mbg_swab_nano_time( &(_p)->mean_path_delay ); \
+ _mbg_swab_nano_time( &(_p)->delay_asymmetry ); \
+ _mbg_swab_ptp_clock_id( &(_p)->gm_id ); \
+ _mbg_swab16( &(_p)->clock_offset_scaled_log_variance ); \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->reserved_2 ); \
+ _mbg_swab16( &(_p)->utc_offset ); \
+ _mbg_swab_dac_val( &(_p)->osc_dac_cal ); \
+ _mbg_swab32( &(_p)->reserved_3 ); \
+}
+
+
+/**
+ * @brief Flags bits used with PTP_STATE::flags
+ *
+ * @see PTP_STATE_FLAG_MASKS
+ */
+enum PTP_STATE_FLAGS
+{
+ PTP_FLAG_SLAVE_ONLY, ///< the port can only be slave
+ PTP_FLAG_IS_SLAVE, ///< the port is currently slave
+ PTP_FLAG_TIMESCALE_IS_PTP, ///< the timescale is PTP standard, not arbitrary
+ PTP_FLAG_LS_ANN, ///< a leap second is being announced
+ PTP_FLAG_LS_ANN_NEG, ///< the announced leap second is negative
+ PTP_FLAG_IS_UNICAST, ///< the port currently operates in unicast mode
+ PTP_FLAG_UTC_VALID, ///< %UTC parameters are valid
+ N_PTP_STATE_FLAGS ///< the number of defined flag bits
+};
+
+/**
+ * @brief Flags masks used with PTP_STATE::flags
+ *
+ * @see PTP_STATE_FLAGS
+ */
+enum PTP_STATE_FLAG_MASKS
+{
+ PTP_FLAG_MSK_SLAVE_ONLY = ( 1UL << PTP_FLAG_SLAVE_ONLY ), ///< see ::PTP_FLAG_SLAVE_ONLY
+ PTP_FLAG_MSK_IS_SLAVE = ( 1UL << PTP_FLAG_IS_SLAVE ), ///< see ::PTP_FLAG_IS_SLAVE
+ PTP_FLAG_MSK_TIMESCALE_IS_PTP = ( 1UL << PTP_FLAG_TIMESCALE_IS_PTP ), ///< see ::PTP_FLAG_TIMESCALE_IS_PTP
+ PTP_FLAG_MSK_LS_ANN = ( 1UL << PTP_FLAG_LS_ANN ), ///< see ::PTP_FLAG_LS_ANN
+ PTP_FLAG_MSK_LS_ANN_NEG = ( 1UL << PTP_FLAG_LS_ANN_NEG ), ///< see ::PTP_FLAG_LS_ANN_NEG
+ PTP_FLAG_MSK_IS_UNICAST = ( 1UL << PTP_FLAG_IS_UNICAST ), ///< see ::PTP_FLAG_IS_UNICAST
+ PTP_FLAG_MSK_UTC_VALID = ( 1UL << PTP_FLAG_UTC_VALID ) ///< see ::PTP_FLAG_UTC_VALID
+};
+
+
+
+/**
+ * @brief A structure used to configure a PTP port
+ */
+typedef struct
+{
+ uint16_t nw_prot; ///< see ::PTP_NW_PROTS
+ uint8_t profile; ///< PTP profile, currently only 0 = default
+ uint8_t domain_number; ///< the PTP clock domain number, 0:3
+
+ uint8_t delay_mech; ///< see ::PTP_DELAY_MECHS
+ uint8_t ptp_role; ///< one of the supported PTP roles, see ::PTP_ROLES
+ uint8_t priority_1; ///< priority 1
+ uint8_t priority_2; ///< priority 2
+
+ uint8_t dflt_clk_class_unsync_cold; // 6:255
+ uint8_t dflt_clk_class_unsync_warm; // 6:255
+ uint8_t dflt_clk_class_sync_cold; // 6:255
+ uint8_t dflt_clk_class_sync_warm; // 6:255
+
+ uint8_t ann_rcpt_timeout; ///< announce msg. receipt timeout, see ::PTP_ANN_RCPT_TIMEOUT_LIMITS
+ uint8_t reserved_1; ///< reserved, currently always 0
+ int16_t sync_intv; ///< log2 of the sync interval [s]
+
+ int16_t ann_intv; ///< log2 of the announce interval [s]
+ int16_t delay_req_intv; ///< log2 of the delay request interval [s]
+
+ uint32_t upper_bound; ///< sync state set to false if above this limit [ns]
+ uint32_t lower_bound; ///< sync state set to true if below this limit [ns]
+
+ uint32_t reserved_2; ///< reserved, currently always 0
+ uint32_t flags; ///< see ::PTP_CFG_FLAGS
+
+} PTP_CFG_SETTINGS;
+
+#define _mbg_swab_ptp_cfg_settings( _p ) \
+{ \
+ _mbg_swab16( &(_p)->nw_prot ); \
+ _mbg_swab16( &(_p)->sync_intv ); \
+ _mbg_swab16( &(_p)->ann_intv ); \
+ _mbg_swab16( &(_p)->delay_req_intv ); \
+ _mbg_swab32( &(_p)->upper_bound ); \
+ _mbg_swab32( &(_p)->lower_bound ); \
+ _mbg_swab32( &(_p)->reserved_3 ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+
+/**
+ * @brief Possible values for PTP_CFG_SETTINGS::ann_rcpt_timeout
+ */
+enum PTP_ANN_RCPT_TIMEOUT_LIMITS
+{
+ PTP_ANN_RCPT_TIMEOUT_MIN = 2,
+ PTP_ANN_RCPT_TIMEOUT_MAX = 255,
+ DEFAULT_PTP_ANN_RCPT_TIMEOUT = 3
+};
+
+
+
+/**
+ * @brief A structure to used to query the current configuration and capabilities of a PTP port
+ */
+typedef struct
+{
+ PTP_CFG_SETTINGS settings; ///< the current configuration
+
+ uint8_t ptp_proto_version; ///< PTP protocol version, 1, or 2, usually 2 for v2
+ uint8_t reserved_1; ///< reserved, currently always 0
+ uint16_t reserved_2; ///< reserved, currently always 0
+
+ int16_t sync_intv_min; ///< log2 of minimum sync interval [s]
+ int16_t sync_intv_max; ///< log2 of maximum sync interval [s]
+ int16_t ann_intv_min; ///< log2 of minimum announce interval [s]
+ int16_t ann_intv_max; ///< log2 of maximum announce interval [s]
+ int16_t delay_req_intv_min; ///< log2 of minimum delay request interval [s]
+ int16_t delay_req_intv_max; ///< log2 of maximum delay request interval [s]
+
+ uint32_t supp_flags; ///< a bit mask of supported features, see ::PTP_CFG_FLAGS
+ uint32_t supp_nw_prot; ///< a bit mask of supported network protocols, see ::PTP_NW_PROTS
+ uint32_t supp_profiles; ///< a bit mask of supported profiles, see ::PTP_PROFILES
+ uint32_t supp_delay_mech; ///< a bit mask of supported delay mechanisms, see ::PTP_DELAY_MECHS
+
+} PTP_CFG_INFO;
+
+#define _mbg_swab_ptp_cfg_info( _p ) \
+{ \
+ _mbg_swab_ptp_cfg_settings( &(_p)->settings ); \
+ _mbg_swab16( &(_p)->reserved_2 ); \
+ _mbg_swab16( &(_p)->sync_intv_min ); \
+ _mbg_swab16( &(_p)->sync_intv_max ); \
+ _mbg_swab16( &(_p)->ann_intv_min ); \
+ _mbg_swab16( &(_p)->ann_intv_max ); \
+ _mbg_swab16( &(_p)->delay_req_intv_min ); \
+ _mbg_swab16( &(_p)->delay_req_intv_max ); \
+ _mbg_swab32( &(_p)->supp_flags ); \
+ _mbg_swab32( &(_p)->supp_nw_prot ); \
+ _mbg_swab32( &(_p)->supp_profiles ); \
+ _mbg_swab32( &(_p)->supp_delay_mech ); \
+}
+
+
+
+/**
+ * @brief Flags used with PTP_CFG_SETTINGS::flags and PTP_CFG_INFO::supp_flags
+ *
+ * @see PTP_CFG_FLAG_MASKS
+ */
+enum PTP_CFG_FLAGS
+{
+ PTP_CFG_TIME_SCALE_IS_PTP, ///< time scale is PTP/TAI, else arbitrary
+ PTP_CFG_V1_HW_COMPAT, ///< maybe required for certain NIC chips, not used by Meinberg
+ PTP_CFG_CAN_BE_UNICAST_SLAVE, ///< the PTP port can take the role of a unicast slave
+ PTP_CFG_CAN_BE_MULTICAST_MASTER, ///< the PTP port can take the role of a multicast master
+ PTP_CFG_CAN_BE_UNICAST_MASTER, ///< the PTP port can take the role of a unicast master
+ PTP_CFG_CAN_BE_MULTICAST_AUTO, ///< the PTP port can automatically become multicast master or slave
+ PTP_CFG_SUPP_UTC_VALID, ///< %UTC valid bit in PTP_STATE::flags is supported
+ N_PTP_CFG_FLAGS ///< the number of defined flags
+};
+
+
+/**
+ * @brief Bit masks associated to ::PTP_CFG_FLAGS
+ */
+enum PTP_CFG_FLAG_MASKS
+{
+ PTP_CFG_MSK_TIME_SCALE_IS_PTP = ( 1UL << PTP_CFG_TIME_SCALE_IS_PTP ), ///< see ::PTP_CFG_TIME_SCALE_IS_PTP
+ PTP_CFG_MSK_V1_HW_COMPAT = ( 1UL << PTP_CFG_V1_HW_COMPAT ), ///< see ::PTP_CFG_V1_HW_COMPAT
+ PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE = ( 1UL << PTP_CFG_CAN_BE_UNICAST_SLAVE ), ///< see ::PTP_CFG_CAN_BE_UNICAST_SLAVE
+ PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER = ( 1UL << PTP_CFG_CAN_BE_MULTICAST_MASTER ), ///< see ::PTP_CFG_CAN_BE_MULTICAST_MASTER
+ PTP_CFG_MSK_CAN_BE_UNICAST_MASTER = ( 1UL << PTP_CFG_CAN_BE_UNICAST_MASTER ), ///< see ::PTP_CFG_CAN_BE_UNICAST_MASTER
+ PTP_CFG_MSK_CAN_BE_MULTICAST_AUTO = ( 1UL << PTP_CFG_CAN_BE_MULTICAST_AUTO ), ///< see ::PTP_CFG_CAN_BE_MULTICAST_AUTO
+ PTP_CFG_MSK_SUPP_UTC_VALID = ( 1UL << PTP_CFG_SUPP_UTC_VALID ) ///< see ::PTP_CFG_SUPP_UTC_VALID
+};
+
+/** @brief A bit mask of the role bits within the flag bits */
+#define PTP_CFG_MSK_SUPPORT_PTP_ROLES ( PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE | \
+ PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER | \
+ PTP_CFG_MSK_CAN_BE_UNICAST_MASTER | \
+ PTP_CFG_MSK_CAN_BE_MULTICAST_AUTO )
+
+/** @brief A bit mask of the unicast role bits within the flag bits */
+#define PTP_CFG_MSK_SUPPORT_PTP_UNICAST ( PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE | \
+ PTP_CFG_MSK_CAN_BE_UNICAST_MASTER )
+
+/**
+ * @brief Derive a "supported PTP roles" bit mask from PTP_CFG_INFO::supp_flags
+ *
+ * There's no explicite flag to indicate that the role of a multicast slave
+ * is supported, since this role is always supported. The sequence of flags
+ * indicating that a specific optional role is supported matches the enumerated
+ * roles above, but don't start at bit 0. So we compine the optional flag bits
+ * with the LSB always set for the implicite multicast slave role to yield
+ * a bit mask which according to the enumerated roles.
+ */
+#define _get_supp_ptp_role_idx_msk( _f ) \
+ ( 1UL | ( ( (_f) & PTP_CFG_MSK_SUPPORT_PTP_ROLES ) >> ( PTP_CFG_CAN_BE_UNICAST_SLAVE - 1 ) ) )
+
+
+/**
+ * @brief Flags used with PTP_CFG_SETTINGS::profile and PTP_CFG_INFO::supp_profiles
+ *
+ * @see PTP_PROFILE_STRS
+ */
+enum PTP_PROFILES
+{
+ PTP_PROFILE_CUSTOM, ///< customizable, always supported
+ PTP_PROFILE_DFLT_E2E, ///< pure IEEE1588-2008 (PTPv2) with E2E
+ PTP_PROFILE_DFLT_P2P, ///< pure IEEE1588-2008 (PTPv2) with P2P
+ PTP_PROFILE_POWER, ///< IEEE C37.238 profile extension
+ PTP_PROFILE_TELECOM, ///< ITU-T G.8265.1 profile extension
+ N_PTP_PROFILES ///< number of supported profiles
+};
+
+
+/**
+ * @brief Flags used with PTP_CFG_SETTINGS::profile and PTP_CFG_INFO::supp_profiles
+ *
+ * @see PTP_PROFILES
+ */
+enum PTP_PROFILE_MASKS
+{
+ PTP_MSK_PROFILE_CUSTOM = ( 1UL << PTP_PROFILE_CUSTOM ), ///< see ::PTP_PROFILE_CUSTOM
+ PTP_MSK_PROFILE_DFLT_E2E = ( 1UL << PTP_PROFILE_DFLT_E2E ), ///< see ::PTP_PROFILE_DFLT_E2E
+ PTP_MSK_PROFILE_DFLT_P2P = ( 1UL << PTP_PROFILE_DFLT_P2P ), ///< see ::PTP_PROFILE_DFLT_P2P
+ PTP_MSK_PROFILE_POWER = ( 1UL << PTP_PROFILE_POWER ), ///< see ::PTP_PROFILE_POWER
+ PTP_MSK_PROFILE_TELECOM = ( 1UL << PTP_PROFILE_TELECOM ) ///< see ::PTP_PROFILE_TELECOM
+};
+
+
+/**
+ * @brief Name strings for defined PTP profiles
+ *
+ * @see PTP_PROFILES
+ */
+#define PTP_PROFILE_STRS \
+{ \
+ "Custom", \
+ "Default E2E", \
+ "Default P2P", \
+ "Power", \
+ "Telecom" \
+}
+
+
+
+/**
+ * @brief Additional parameters for Power Profile
+ */
+#define PTP_POWER_PROFILE_GM_ID_MIN 3
+#define PTP_POWER_PROFILE_GM_ID_MAX 255
+
+typedef struct
+{
+ uint32_t network_incaccuracy; ///< Pre-defined network inaccuracy from master in [ns]
+ uint8_t grandmaster_id; ///< [PTP_POWER_PROFILE_GM_ID_MIN..PTP_POWER_PROFILE_GM_ID_MAX]
+ uint8_t reserved_1;
+ uint16_t reserved_2;
+
+} PTP_POWER_PROFILE_CFG;
+
+
+
+/**
+ * @brief A host's fully qualified domain name (FQDN), or a numeric IP address string
+ *
+ * In theory each single component (host name, domain name, top level domain name)
+ * of a FQDN can have up to 63 characters, but the overall length is limited to
+ * 255 characters. We specify one more character for the trailing 0.
+ */
+typedef char MBG_HOSTNAME[256];
+
+
+/**
+ * @brief Limits to be considered when specifying PTP unicast masters
+ */
+typedef struct
+{
+ uint16_t n_supp_master; ///< number of unicast masters which can be specified
+ int16_t sync_intv_min; ///< log2 of minimum sync interval [s]
+ int16_t sync_intv_max; ///< log2 of maximum sync interval [s]
+ int16_t ann_intv_min; ///< log2 of minimum announce interval [s]
+ int16_t ann_intv_max; ///< log2 of maximum announce interval [s]
+ int16_t delay_req_intv_min; ///< log2 of minimum delay request interval [s]
+ int16_t delay_req_intv_max; ///< log2 of maximum delay request interval [s]
+ uint16_t reserved_0; ///< reserved, currently always 0
+ uint32_t supp_flags; ///< a bit mask indicating which flags are supported
+ uint32_t reserved_1; ///< reserved, currently always 0
+
+} PTP_UC_MASTER_CFG_LIMITS;
+
+#define _mbg_swab_ptp_uc_master_cfg_limits( _p ) \
+{ \
+ _mbg_swab16( &(_p)->n_supp_master ); \
+ _mbg_swab16( &(_p)->sync_intv_min ); \
+ _mbg_swab16( &(_p)->sync_intv_max ); \
+ _mbg_swab16( &(_p)->ann_intv_min ); \
+ _mbg_swab16( &(_p)->ann_intv_max ); \
+ _mbg_swab16( &(_p)->delay_req_intv_min ); \
+ _mbg_swab16( &(_p)->delay_req_intv_max ); \
+ _mbg_swab16( &(_p)->reserved_0 ); \
+ _mbg_swab32( &(_p)->supp_flags ); \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+}
+
+
+/**
+ * @brief Configuration settings specifiying how to query a PTP unicast master
+ *
+ * This structure is used on a unicast slave to specify the settings of
+ * a unicast master polled by the slave. The number of unicast masters
+ * which can be specified depends on the capabilities of the slave device
+ * and is returned in PTP_UC_MASTER_CFG_LIMITS::n_supp_master.
+ *
+ * The structure ::PTP_UC_MASTER_SETTINGS_IDX should be sent to the device
+ * to save the configuration.
+ */
+typedef struct
+{
+ MBG_HOSTNAME gm_host; ///< grandmaster's hostname or IP address
+ PTP_CLOCK_ID gm_clock_id; ///< use clock ID of master port, or ::PTP_CLOCK_ID_WILDCARD
+ PTP_PORT_ID gm_port_id; ///< use target port ID of master port (e.g. 135) or ::PTP_PORT_ID_WILDCARD
+ int16_t sync_intv; ///< sync interval [log2 s]
+ int16_t ann_intv; ///< announce interval [log2 s]
+ int16_t delay_req_intv; ///< delay request interval [log2 s]
+ int32_t fix_offset; ///< constant time offset to be compensated [ns]
+ uint16_t message_duration; ///< time period until master stops sending messages [s]
+ uint16_t reserved_0; ///< reserved, currently always 0
+ uint32_t reserved_1; ///< reserved, currently always 0
+ uint32_t flags; ///< reserved, currently always 0
+
+} PTP_UC_MASTER_SETTINGS;
+
+#define _mbg_swab_ptp_uc_master_settings( _p ) \
+{ \
+ _mbg_swab_ptp_clock_id( &(_p)->gm_clock_id ); \
+ _mbg_swab_ptp_port_id( &(_p)->gm_port_id ); \
+ _mbg_swab16( &(_p)->sync_intv ); \
+ _mbg_swab16( &(_p)->ann_intv ); \
+ _mbg_swab16( &(_p)->delay_req_intv ); \
+ _mbg_swab32( &(_p)->fix_offset ); \
+ _mbg_swab16( &(_p)->message_duration ); \
+ _mbg_swab16( &(_p)->reserved_0 ); \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Unicast PTP master message duration limits
+ *
+ * Each unicast PTP master sends messages to a unicast slave only
+ * for a given interval as requested by the particular slave, which
+ * is called message duration.
+ * These symbols define the minimum and maximum message duration
+ * configured on a slave for a specific unicast master, i.e. for
+ * PTP_UC_MASTER_SETTINGS::message_duration. The values are defined
+ * in the PTP v2 standard.
+ */
+enum PTP_UC_MSG_DURATION_LIMITS
+{
+ PTP_UC_MSG_DURATION_MIN = 10, ///< minimum message duration [s]
+ PTP_UC_MSG_DURATION_MAX = 1000 ///< maximum message duration [s]
+};
+
+
+
+/**
+ * @brief Configuration settings for a specific PTP unicast master
+ */
+typedef struct
+{
+ uint32_t idx; ///< index, 0..PTP_UC_MASTER_CFG_LIMITS::n_supp_master - 1
+ PTP_UC_MASTER_SETTINGS settings; ///< specification for the unicast master with that index
+
+} PTP_UC_MASTER_SETTINGS_IDX;
+
+#define _mbg_swab_ptp_uc_master_settings_idx( _p ) \
+{ \
+ _mbg_swab32( &(_p)->idx ); \
+ _mbg_swab_ptp_uc_master_settings( &(_p)->settings ); \
+}
+
+
+/**
+ * @brief Current settings and general capabilities of a unicast master
+ *
+ * This structure is used with a PTP unicast slave device to specify
+ * a PTP unicast master which can be queried by the slave device.
+ */
+typedef struct
+{
+ PTP_UC_MASTER_SETTINGS settings; ///< current settings
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t flags; ///< reserved, currently always 0
+
+} PTP_UC_MASTER_INFO;
+
+#define _mbg_swab_ptp_uc_master_info( _p ) \
+{ \
+ _mbg_swab_ptp_uc_master_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->reserved ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Current settings and general capabilities of a specific unicast master
+ *
+ * This structure is used with a PTP unicast slave device to specify
+ * a PTP unicast master which can be queried by the slave device.
+ *
+ * This structure should be read from the device to retrieve the
+ * current settings and capabilities. The number of supported
+ * configuration records is PTP_UC_MASTER_CFG_LIMITS::n_supp_master.
+ *
+ * @note The ::PTP_UC_MASTER_SETTINGS_IDX structure should be send back
+ * to the device to save the configuration.
+ */
+typedef struct
+{
+ uint32_t idx; ///< index, 0..PTP_UC_MASTER_CFG_LIMITS::n_supp_master - 1
+ PTP_UC_MASTER_INFO info; ///< capabilities and current settings
+
+} PTP_UC_MASTER_INFO_IDX;
+
+#define _mbg_swab_ptp_uc_master_info_idx( _p ) \
+{ \
+ _mbg_swab32( &(_p)->idx ); \
+ _mbg_swab_ptp_uc_master_info( &(_p)->info ); \
+}
+
+
+/** @} group_ptp */
+
+
+/**
+ * @defgroup group_lno Definitions used with LNO devices
+ *
+ * @{ */
+
+#define MAX_LNO_OUTPUT 4
+
+/**
+ * @brief LNO status
+ */
+typedef struct
+{
+ uint16_t sine_lvl[MAX_LNO_OUTPUT]; ///< signal levels at the outputs
+
+ uint16_t max_sine_lvl; ///< max level of an output, e.g. 1024
+ uint8_t n_outputs; ///< actual number of outputs [0..::MAX_LNO_OUTPUT-1]
+ uint8_t out_enb_state; ///< e.g. bit 0 is set if corresponding output 0 is enabled, etc.
+
+ uint16_t reserved_0; ///< reserved, currently always 0
+ uint16_t flags; ///< status flags, see ::LNO_STATE_FLAG_BITS
+
+} LNO_STATE;
+
+#define _mbg_swab_lno_state( _p ) \
+{ \
+ int i; \
+ \
+ for ( i = 0; i < MAX_LNO_OUTPUT; i++ ) \
+ _mbg_swab16( &(_p)->sine_lvl[i] ); \
+ \
+ _mbg_swab_16( &(_p)->max_sine_lvl ); \
+ _mbg_swab_16( &(_p)->reserved_0 ); \
+ _mbg_swab_16( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Flags used with LNO_STATE::flags
+ */
+enum LNO_STATE_FLAG_BITS
+{
+ LNO_FLAG_BIT_PLL_LOCKED, ///< PLL is locked
+ N_LNO_FLAG_BIT ///< number of known bits
+};
+
+#define LNO_FLAG_PLL_LOCKED ( 1UL << LNO_FLAG_BIT_PLL_LOCKED )
+
+/** @} group_lno */
+
+
+/*------------------------------------------------------------------------*/
+
+/**
+ * @brief Ephemeris parameters of one specific satellite
+ *
+ * Needed to compute the position of a satellite at a given time with
+ * high precision. Valid for an interval of 4 to 6 hours from start
+ * of transmission.
+ */
+typedef struct
+{
+ CSUM csum; ///< checksum of the remaining bytes
+ int16_t valid; ///< flag data are valid
+
+ HEALTH health; ///< health indication of transmitting SV [---]
+ IOD IODC; ///< Issue Of Data, Clock
+ IOD IODE2; ///< Issue of Data, Ephemeris (Subframe 2)
+ IOD IODE3; ///< Issue of Data, Ephemeris (Subframe 3)
+ T_GPS tt; ///< time of transmission
+ T_GPS t0c; ///< Reference Time Clock [---]
+ T_GPS t0e; ///< Reference Time Ephemeris [---]
+
+ double sqrt_A; ///< Square Root of semi-major Axis [sqrt(m)]
+ double e; ///< Eccentricity [---]
+ double M0; ///< +- Mean Anomaly at Ref. Time [rad]
+ double omega; ///< +- Argument of Perigee [rad]
+ double OMEGA0; ///< +- Longit. of Asc. Node of orbit plane [rad]
+ double OMEGADOT; ///< +- Rate of Right Ascension [rad/sec]
+ double deltan; ///< +- Mean Motion Diff. from computed value [rad/sec]
+ double i0; ///< +- Inclination Angle [rad]
+ double idot; ///< +- Rate of Inclination Angle [rad/sec]
+ double crc; ///< +- Cosine Corr. Term to Orbit Radius [m]
+ double crs; ///< +- Sine Corr. Term to Orbit Radius [m]
+ double cuc; ///< +- Cosine Corr. Term to Arg. of Latitude [rad]
+ double cus; ///< +- Sine Corr. Term to Arg. of Latitude [rad]
+ double cic; ///< +- Cosine Corr. Term to Inclination Angle [rad]
+ double cis; ///< +- Sine Corr. Term to Inclination Angle [rad]
+
+ double af0; ///< +- Clock Correction Coefficient 0 [sec]
+ double af1; ///< +- Clock Correction Coefficient 1 [sec/sec]
+ double af2; ///< +- Clock Correction Coefficient 2 [sec/sec^2]
+ double tgd; ///< +- estimated group delay differential [sec]
+
+ uint16_t URA; ///< predicted User Range Accuracy
+
+ uint8_t L2code; ///< code on L2 channel [---]
+ uint8_t L2flag; ///< L2 P data flag [---]
+} EPH;
+
+
+
+/**
+ * @brief Almanac parameters of one specific satellite
+ *
+ * A reduced precision set of parameters used to check if a satellite
+ * is in view at a given time. Valid for an interval of more than 7 days
+ * from start of transmission.
+ */
+typedef struct
+{
+ CSUM csum; ///< checksum of the remaining bytes
+ int16_t valid; ///< flag data are valid
+
+ HEALTH health; ///< [---]
+ T_GPS t0a; ///< Reference Time Almanac [sec]
+
+ double sqrt_A; ///< Square Root of semi-major Axis [sqrt(m)]
+ double e; ///< Eccentricity [---]
+
+ double M0; ///< +- Mean Anomaly at Ref. Time [rad]
+ double omega; ///< +- Argument of Perigee [rad]
+ double OMEGA0; ///< +- Longit. of Asc. Node of orbit plane [rad]
+ double OMEGADOT; ///< +- Rate of Right Ascension [rad/sec]
+ double deltai; ///< +- [rad]
+ double af0; ///< +- Clock Correction Coefficient 0 [sec]
+ double af1; ///< +- Clock Correction Coefficient 1 [sec/sec]
+} ALM;
+
+
+
+/**
+ * @brief Summary of configuration and health data of all satellites
+ */
+typedef struct
+{
+ CSUM csum; ///< checksum of the remaining bytes
+ int16_t valid; ///< flag data are valid
+
+ T_GPS tot_51; ///< time of transmission, page 51
+ T_GPS tot_63; ///< time of transmission, page 63
+ T_GPS t0a; ///< complete reference time almanac
+
+ CFG cfg[N_SVNO]; ///< SV configuration from page 63
+ HEALTH health[N_SVNO]; ///< SV health from pages 51, 63
+} CFGH;
+
+
+
+/**
+ * @brief GPS %UTC correction parameters
+ *
+ * %UTC correction parameters basically as sent by the GPS satellites.
+ *
+ * The csum field is only used by the card's firmware to check the
+ * consistency of the structure in non-volatile memory.
+ *
+ * The field labeled valid indicates if the parameter set is valid, i.e.
+ * if it contains data received from the satellites.
+ *
+ * t0t, A0 and A1 contain fractional correction parameters for the current
+ * GPS-%UTC time offset in addition to the whole seconds. This is evaluated
+ * by the receivers' firmware to convert GPS time to %UTC time.
+ *
+ * The delta_tls field contains the current full seconds offset between
+ * GPS time and %UTC, which corresponds to the number of leap seconds inserted
+ * into the %UTC time scale since GPS was put into operation in January 1980.
+ *
+ * delta_tlfs holds the number of "future" leap seconds, i.e. the %UTC offset
+ * after the next leap second event defined by WNlsf and DNt.
+ *
+ * The fields WNlsf and DNt specify the GPS week number and the day number
+ * in that week at the end of which a leap second is scheduled.
+ *
+ * @note: The satellites transmit WNlsf only as a signed 8 bit value, so it
+ * can only define a point in time which is ± 127 weeks off the current time.
+ * The firmware tries to expand this based on the current week number, but
+ * the result is ambiguous if the leap second occurs or occurred more
+ * than 127 weeks in the future or past.
+ *
+ * So the leap second date should only be evaluated if the fields delta_tls
+ * and delta_tlsf are different, in which case there is an actual leap second
+ * announcement inside the ± 127 week range.
+ */
+typedef struct
+{
+ CSUM csum; ///< Checksum of the remaining bytes
+ int16_t valid; ///< Flag indicating %UTC parameters are valid
+
+ T_GPS t0t; ///< Reference Time %UTC Parameters [wn|sec]
+ double A0; ///< +- Clock Correction Coefficient 0 [sec]
+ double A1; ///< +- Clock Correction Coefficient 1 [sec/sec]
+
+ uint16_t WNlsf; ///< Week number of nearest leap second
+ int16_t DNt; ///< The day number at the end of which a leap second occurs
+ int8_t delta_tls; ///< Current %UTC offset to GPS system time [sec]
+ int8_t delta_tlsf; ///< Future %UTC offset to GPS system time after next leap second transition [sec]
+} UTC;
+
+#define _mbg_swab_utc_parm( _p ) \
+{ \
+ _mbg_swab_csum( &(_p)->csum ); \
+ _mbg_swab16( &(_p)->valid ); \
+ _mbg_swab_t_gps( &(_p)->t0t ); \
+ _mbg_swab_double( &(_p)->A0 ); \
+ _mbg_swab_double( &(_p)->A1 ); \
+ _mbg_swab16( &(_p)->WNlsf ); \
+ _mbg_swab16( &(_p)->DNt ); \
+}
+
+
+
+/**
+ * @brief Ionospheric correction parameters
+ */
+typedef struct
+{
+ CSUM csum; ///< checksum of the remaining bytes
+ int16_t valid; ///< flag data are valid
+
+ double alpha_0; ///< Ionosph. Corr. Coeff. Alpha 0 [sec]
+ double alpha_1; ///< Ionosph. Corr. Coeff. Alpha 1 [sec/deg]
+ double alpha_2; ///< Ionosph. Corr. Coeff. Alpha 2 [sec/deg^2]
+ double alpha_3; ///< Ionosph. Corr. Coeff. Alpha 3 [sec/deg^3]
+
+ double beta_0; ///< Ionosph. Corr. Coeff. Beta 0 [sec]
+ double beta_1; ///< Ionosph. Corr. Coeff. Beta 1 [sec/deg]
+ double beta_2; ///< Ionosph. Corr. Coeff. Beta 2 [sec/deg^2]
+ double beta_3; ///< Ionosph. Corr. Coeff. Beta 3 [sec/deg^3]
+} IONO;
+
+
+
+/**
+ * @brief GPS ASCII message
+ */
+typedef struct
+{
+ CSUM csum; ///< checksum of the remaining bytes */
+ int16_t valid; ///< flag data are valid
+ char s[23]; ///< 22 chars GPS ASCII message plus trailing zero
+} ASCII_MSG;
+
+
+
+enum GPS_PLATFORMS
+{
+ GPS_PLATFORM_PORTABLE,
+ GPS_PLATFORM_FIXED,
+ GPS_PLATFORM_STATIONARY,
+ GPS_PLATFORM_PEDESTRIAN,
+ GPS_PLATFORM_AUTOMOTIVE,
+ GPS_PLATFORM_SEA,
+ GPS_PLATFORM_AIRBORNE_1G,
+ GPS_PLATFORM_AIRBORNE_2G,
+ GPS_PLATFORM_AIRBORNE_4G,
+ N_GPS_PLATFORMS
+};
+
+
+#define GPS_PLATFORM_STRS \
+{ \
+ "Portable ", \
+ "Fixed ", \
+ "Stationary ", \
+ "Pedestrian ", \
+ "Automotive ", \
+ "Sea ", \
+ "Airborne <1G", \
+ "Airborne <2G", \
+ "Airborne <4G" \
+}
+
+
+
+enum TIME_MODES
+{
+ TIME_MODE_DISABLED,
+ TIME_MODE_SURVEY_IN,
+ TIME_MODE_FIXED,
+ N_TIME_MODES
+};
+
+
+
+typedef struct
+{
+ uint32_t time_mode;
+ uint32_t survey_in_duration;
+ uint32_t survey_in_pos_var;
+ int32_t fixedPosX; // cm
+ int32_t fixedPosY; // cm
+ int32_t fixedPosZ; // cm
+ uint32_t fixedPosVar; // cm
+ uint32_t flags; // currently 0
+ uint32_t reserved; // currently 0
+} NAV_TIME_MODE_SETTINGS;
+
+
+/**
+ * Navigation Engine settings to set configuration
+ * parameters of a dynamic platform model.
+ */
+typedef struct
+{
+ uint8_t dynamic_platform;
+ uint8_t fix_mode;
+ int8_t min_elevation;
+ uint8_t static_hold_threshold;
+ int32_t fixed_altitude;
+ uint32_t fixed_altitude_variance;
+ uint32_t flags; // currently 0
+ uint32_t reserved; // currently 0
+ NAV_TIME_MODE_SETTINGS nav_time_mode_settings;
+} NAV_ENGINE_SETTINGS;
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+#endif /* _GPSDEFS_H */
diff --git a/mbglib/common/gpsutils.h b/mbglib/common/gpsutils.h
new file mode 100644
index 0000000..c2143ca
--- /dev/null
+++ b/mbglib/common/gpsutils.h
@@ -0,0 +1,84 @@
+
+/**************************************************************************
+ *
+ * $Id: gpsutils.h 1.7 2010/07/15 09:32:09Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for gpsutils.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: gpsutils.h $
+ * Revision 1.7 2010/07/15 09:32:09Z martin
+ * Use DEG character definition from pcpslstr.h.
+ * Revision 1.6 2005/02/18 10:32:33Z martin
+ * Check more predefined macros to determine if compiling for Windows.
+ * Revision 1.5 2003/02/04 09:18:48Z MARTIN
+ * Updated function prototypes.
+ * Revision 1.4 2002/12/12 16:08:11 martin
+ * Definitions for degree character.
+ * Requires mbggeo.h.
+ * Updated function prototypes.
+ * Revision 1.3 2001/02/05 09:40:42Z MARTIN
+ * New file header.
+ * Source code cleanup.
+ *
+ **************************************************************************/
+
+#ifndef _GPSUTILS_H
+#define _GPSUTILS_H
+
+
+/* Other headers to be included */
+
+#include <mbggeo.h>
+
+
+#ifdef _GPSUTILS
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ void swap_double( double *d ) ;
+ void swap_eph_doubles( EPH *ephp ) ;
+ void swap_alm_doubles( ALM *almp ) ;
+ void swap_utc_doubles( UTC *utcp ) ;
+ void swap_iono_doubles( IONO *ionop ) ;
+ void swap_pos_doubles( POS *posp ) ;
+ void sprint_dms( char *s, DMS *pdms, int prec ) ;
+ void sprint_alt( char *s, double alt ) ;
+ void sprint_pos_geo( char *s, POS *ppos, const char *sep, int prec ) ;
+ void sprint_fixed_freq( char *s, FIXED_FREQ_INFO *p_ff ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _GPSUTILS_H */
+
diff --git a/mbglib/common/lan_util.c b/mbglib/common/lan_util.c
new file mode 100644
index 0000000..cca8a0a
--- /dev/null
+++ b/mbglib/common/lan_util.c
@@ -0,0 +1,1288 @@
+
+/**************************************************************************
+ *
+ * $Id: lan_util.c 1.6 2013/03/19 10:24:51Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Utility functions useful for network programming.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: lan_util.c $
+ * Revision 1.6 2013/03/19 10:24:51Z martin
+ * Fixed bugs in get_ip4_gateway(): A skipped routing entry was
+ * taken as default route, and thus a wrong default route 0.0.0.0
+ * could be returned erraneously. Also, malloc() was used without
+ * checking the result.
+ * Added conditional debug code.
+ * Revision 1.5 2013/02/19 15:13:10 martin
+ * Added some new functions.
+ * Updated doxygen comments.
+ * Revision 1.4 2012/11/02 09:16:57 martin
+ * Fixed build under Windows.
+ * Revision 1.3 2012/10/02 18:23:28Z martin
+ * Removed obsolete code to avoid compiler warning.
+ * Revision 1.2 2012/03/09 08:49:19 martin
+ * Added some commonly used functions.
+ * Revision 1.1 2011/03/04 10:01:32Z martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#define _LAN_UTIL
+ #include <lan_util.h>
+#undef _LAN_UTIL
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined ( MBG_TGT_UNIX )
+
+ #if defined ( MBG_TGT_LINUX )
+
+ #include <linux/types.h>
+
+ // Some older versions of linux/types.h don't define u8..u64
+ // for user space applications. However, if they do they also
+ // define BITS_PER_LONG, so we use this symbol to figure out
+ // if we need to define u8..u64 by ourselves.
+ #if !defined( BITS_PER_LONG )
+ typedef uint8_t u8;
+ typedef uint16_t u16;
+ typedef uint32_t u32;
+ typedef uint64_t u64;
+ #endif
+
+ #include <linux/sockios.h>
+ #include <linux/ethtool.h>
+ #include <linux/rtnetlink.h>
+ #endif
+
+ #include <unistd.h>
+ #include <sys/ioctl.h>
+ #include <sys/errno.h>
+ #include <arpa/inet.h>
+ #include <netinet/in.h>
+
+#else
+
+ // dummy codes, the functions will report an error ...
+ #define SIOCGIFADDR 0
+ #define SIOCGIFNETMASK 0
+ #define SIOCGIFBRDADDR 0
+
+ #if defined( MBG_TGT_WIN32 )
+ #define snprintf _snprintf
+ #endif
+
+#endif
+
+
+#if !defined( DEBUG_NETLINK )
+ #define DEBUG_NETLINK ( 0 && defined( DEBUG ) && defined( MBG_TGT_LINUX ) )
+#endif
+
+
+#if DEBUG_NETLINK
+ // we need a function to output debugging information
+ #if !defined STANDALONE
+ #include <ptp2_cnf.h> // for mbglog() from the ARM PTP projects
+ #else
+ // to be provided by the application
+ extern void mbglog( int priority, const char *fmt, ... );
+ #endif
+#endif // DEBUG_NETLINK
+
+
+
+// Maximum size of an IPv4 address string in dotted quad format,
+// including a terminating 0, and thus the required minimum size
+// for a buffer to take such a string. i.e. "aaa.bbb.ccc.ddd\0".
+#define MAX_IP4_ADDR_STR_SIZE 16
+
+
+#if defined ( MBG_TGT_LINUX )
+
+struct route_info
+{
+ struct in_addr dstAddr;
+ struct in_addr srcAddr;
+ struct in_addr gateWay;
+ char ifName[IF_NAMESIZE];
+};
+
+#endif
+
+
+#if defined( __BORLANDC__ ) \
+ && ( __BORLANDC__ <= 0x410 ) // BC3.1 defines 0x410 !
+
+#include <stdarg.h>
+
+// Declare a snprintf() function if not provided by the
+// build environment, though this implementation actually
+// does not check the string length ...
+
+static /*HDR*/
+int snprintf( char *s, size_t max_len, const char *fmt, ... )
+{
+ int n;
+ va_list arg_list;
+
+ va_start( arg_list, fmt );
+ n = vsprintf( s, fmt, arg_list );
+ va_end( arg_list );
+
+ return n;
+
+} // snprintf
+
+#endif
+
+
+
+/*HDR*/
+/**
+ * @brief Count the number of sequential bits set starting from MSB
+ *
+ * E.g. for 0xC0 and 0xC1 the results are both 2 since only
+ * the 2 MSBs are sequentially set.
+ *
+ * @param p_mask The IP4 net mask
+ *
+ * @return The number of sequential MSB bits set in val
+ *
+ * @see ip4_net_mask_from_cidr
+ */
+int get_ip4_net_mask_bits( const IP4_ADDR *p_mask )
+{
+ IP4_ADDR msb_mask = IP4_MSB_MASK;
+ int i;
+
+ for ( i = 0; i < MAX_IP4_BITS; i++ )
+ {
+ if ( ( *p_mask & msb_mask ) == 0 )
+ break;
+
+ msb_mask >>= 1;
+ }
+
+ return i;
+
+} // get_ip4_net_mask_bits
+
+
+
+/*HDR*/
+/**
+ * @brief Print an IPv4 address to a dotted quad format string.
+ *
+ * @param s The string buffer into which to print
+ * @param max_len Maximum length of the string, i.e. size of the buffer
+ * @param p_addr The IPv4 address
+ * @param info An optional string which is prepended to the string, or NULL
+ *
+ * @return The overall number of characters printed to the string
+ *
+ * @see snprint_ip4_cidr_addr
+ * @see str_to_ip4_addr
+ * @see cidr_str_to_ip4_addr_and_net_mask
+ */
+int snprint_ip4_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, const char *info )
+{
+ int n = 0;
+ ulong ul = *p_addr;
+
+ if ( info )
+ n += snprintf( s, max_len, "%s", info );
+
+ // Don't use byte pointers here since this is not safe
+ // for both little and big endian targets.
+ n += snprintf( &s[n], max_len - n, "%lu.%lu.%lu.%lu",
+ BYTE_3( ul ), BYTE_2( ul ),
+ BYTE_1( ul ), BYTE_0( ul )
+ );
+ return n;
+
+} // snprint_ip4_addr
+
+
+
+/*HDR*/
+/**
+ * @brief Print an IPv4 address plus net mask to string in CIDR notation.
+ *
+ * The printed CIDR string is something like "172.16.3.250/24"
+ *
+ * @param s The string buffer into which to print
+ * @param max_len Maximum length of the string, i.e. size of the buffer
+ * @param p_addr The IPv4 address
+ * @param p_mask The IPv4 net mask
+ * @param info An optional string which is prepended to the string, or NULL
+ *
+ * @return The overall number of characters printed to the string
+ *
+ * @see snprint_ip4_addr
+ * @see str_to_ip4_addr
+ * @see cidr_str_to_ip4_addr_and_net_mask
+ */
+int snprint_ip4_cidr_addr( char *s, size_t max_len, const IP4_ADDR *p_addr,
+ const IP4_ADDR *p_mask, const char *info )
+{
+ int cidr_mask_bits;
+ IP4_ADDR normalized_addr = ip4_net_part_from_addr( p_addr, p_mask );
+
+ int n = snprint_ip4_addr( s, max_len, &normalized_addr, info );
+
+ cidr_mask_bits = get_ip4_net_mask_bits( p_mask );
+
+ if ( ( cidr_mask_bits >= MIN_IP4_CIDR_NETMASK_BITS ) &&
+ ( cidr_mask_bits <= MAX_IP4_CIDR_NETMASK_BITS ) )
+ n += snprintf( &s[n], max_len - n, "/%i", cidr_mask_bits );
+
+ return n;
+
+} // snprint_ip4_cidr_addr
+
+
+
+/*HDR*/
+/**
+ * @brief Convert a string to an IP4_ADDR.
+ *
+ * @param p_addr Pointer to the IP4_ADDR variable, or NULL, in which case this
+ * function can be used to check if the string is formally correct.
+ * @param s The string to be converted
+ *
+ * @return >= 0 on success, number of characters evaluated from the input string
+ * -1 if invalid number found in string
+ * -2 if separator is not a dot '.'
+ *
+ * @see snprint_ip4_addr
+ * @see snprint_ip4_cidr_addr
+ * @see cidr_str_to_ip4_addr_and_net_mask
+ */
+int str_to_ip4_addr( IP4_ADDR *p_addr, const char *s )
+{
+ IP4_ADDR tmp_ip4_addr = 0;
+ const char *cp;
+ int i;
+
+ for ( i = 0, cp = (char *) s; ; )
+ {
+ unsigned long ul = strtoul( (char *) cp, (char **) &cp, 10 );
+
+ if ( ul > 255 ) // invalid number
+ return -1;
+
+ tmp_ip4_addr |= ul << ( 8 * (3 - i) );
+
+ if ( ++i >= 4 )
+ break; // done
+
+ if ( *cp != '.' )
+ return -2; // invalid string format, dot expected
+
+ cp++; // skip dot
+ }
+
+ if ( p_addr )
+ *p_addr = tmp_ip4_addr;
+
+ // success: return the number of evaluated chars
+ return cp - s;
+
+} // str_to_ip4_addr
+
+
+
+/*HDR*/
+/**
+ * @brief Convert a string in CIDR notation to an IP4_ADDR and net mask.
+ *
+ * @param p_addr Pointer to an IP4_ADDR variable for the IP4 address,
+ * or NULL, in which case this function can be used
+ * to check if the string is formally correct.
+ * @param p_mask Pointer to an IP4_ADDR variable for the net mask,
+ * or NULL, in which case this function can be used
+ * to check if the string is formally correct.
+ * @param cidr_str The string to be converted, in CIDR format, e.g. "172.16.3.250/24"
+ *
+ * @return >= 0 on success, number of characters evaluated from the input string
+ * one of the ::MBG_LU_CODES on error
+ *
+ * @see snprint_ip4_addr
+ * @see snprint_ip4_cidr_addr
+ * @see str_to_ip4_addr
+ */
+int cidr_str_to_ip4_addr_and_net_mask( IP4_ADDR *p_addr, IP4_ADDR *p_mask,
+ const char *cidr_str )
+{
+ IP4_ADDR mask;
+ long cidr_mask_bits;
+ const char *cp;
+ int l;
+ int rc = str_to_ip4_addr( p_addr, cidr_str );
+
+ if ( rc < 0 ) // return current error
+ return rc;
+
+
+ l = strlen( cidr_str );
+
+ if ( l < rc ) // input string too short
+ return MBG_LU_ERR_FMT;
+
+
+ cp = &cidr_str[rc];
+
+ if ( *cp == 0 ) // end of string
+ {
+ // The string has no CIDR extension, so
+ // assume "/0", i.e. host mask 255.255.255.255;
+ mask = (IP4_ADDR) -1;
+ goto done;
+ }
+
+
+ if ( *cp != '/' )
+ return MBG_LU_ERR_FMT;
+
+
+ cp++;
+ cidr_mask_bits = strtol( (char *) cp, (char **) &cp, 10 );
+
+ if ( ( cidr_mask_bits < MIN_IP4_CIDR_NETMASK_BITS ) ||
+ ( cidr_mask_bits > MAX_IP4_CIDR_NETMASK_BITS ) )
+ return MBG_LU_ERR_RANGE;
+
+
+ mask = ip4_net_mask_from_cidr( (int) cidr_mask_bits );
+
+done:
+ if ( p_mask )
+ *p_mask = mask;
+
+ // success: return the number of evaluated chars
+ return cp - cidr_str;
+
+} // cidr_str_to_ip4_addr_and_net_mask
+
+
+
+/*HDR*/
+/**
+ * @brief Print a MAC ID or similar array of octets to a string.
+ *
+ * @param s The string buffer into which to print
+ * @param max_len Maximum length of the string, i.e. size of the buffer
+ * @param octets An array of octets
+ * @param num_octets The number of octets to be printed from the array
+ * @param sep The separator printed between the bytes, or 0
+ * @param info An optional string which is prepended to the output, or NULL
+ *
+ * @return The overall number of characters printed to the string
+ *
+ * @see snprint_mac_addr
+ * @see str_to_octets
+ * @see check_octets_not_all_zero
+ */
+int snprint_octets( char *s, size_t max_len, const uint8_t *octets,
+ int num_octets, char sep, const char *info )
+{
+ int n = 0;
+ int i;
+
+ if ( info )
+ n += snprintf( s, max_len, "%s", info );
+
+ for ( i = 0; i < num_octets; i++ )
+ {
+ if ( i && sep )
+ n += snprintf( &s[n], max_len - n, "%c", sep );
+
+ n += snprintf( &s[n], max_len - n, "%02X", octets[i] );
+ }
+
+ return n;
+
+} // snprint_octets
+
+
+
+/*HDR*/
+/**
+ * @brief Print a MAC address to a string.
+ *
+ * @param s The string buffer into which to print
+ * @param max_len Maximum length of the string, i.e. size of the buffer
+ * @param p_mac_addr The MAC address to be printed
+ *
+ * @return The overall number of characters printed to the string
+ *
+ * @see snprint_octets
+ * @see str_to_octets
+ * @see check_octets_not_all_zero
+ */
+int snprint_mac_addr( char *s, size_t max_len, const MBG_MAC_ADDR *p_mac_addr )
+{
+ return snprint_octets( s, max_len, p_mac_addr->b, sizeof( *p_mac_addr ), MAC_SEP_CHAR, NULL );
+
+} // snprint_mac_addr
+
+
+
+/*HDR*/
+/**
+ * @brief Set a MAC ID or a similar array of octets from a string.
+ *
+ * @param octets An array of octets to be set up
+ * @param num_octets The number of octets which can be stored
+ * @param s The string to be converted
+ *
+ * @return The overall number of octets decoded from the string
+ *
+ * @see snprint_octets
+ * @see snprint_mac_addr
+ * @see check_octets_not_all_zero
+ */
+int str_to_octets( uint8_t *octets, int num_octets, const char *s )
+{
+ char *cp = (char *) s;
+ int i;
+
+ // don't use strtok() since that functions modifies the original string
+ for ( i = 0; i < num_octets; )
+ {
+ octets[i] = (uint8_t) strtoul( cp, &cp, 16 );
+ i++;
+
+ if ( *cp == 0 )
+ break; // end of string
+
+ if ( ( *cp != MAC_SEP_CHAR ) && ( *cp != MAC_SEP_CHAR_ALT ) )
+ break; // invalid character
+
+ cp++;
+ }
+
+ return i;
+
+} // str_to_octets
+
+
+
+/*HDR*/
+/**
+ * @brief Check if an array of octets is valid, i.e. != 0
+ *
+ * @param octets Pointer to the array of octets
+ * @param num_octets Number of octets
+ *
+ * @return MBG_LU_SUCCESS octets are valid, i.e. not all 0
+ * MBG_LU_ERR_NOT_SET octets are invalid, i.e. all 0
+ *
+ * @see snprint_octets
+ * @see snprint_mac_addr
+ * @see str_to_octets
+ */
+int check_octets_not_all_zero( const uint8_t *octets, int num_octets )
+{
+ int i;
+
+ // check if any of the MAC adddress bytes is != 0
+ for ( i = 0; i < num_octets; i++ )
+ if ( octets[i] != 0 )
+ break;
+
+ if ( i == num_octets ) // *all* bytes are 0
+ return MBG_LU_ERR_NOT_SET;
+
+ return 0;
+
+} // check_octets_not_all_zero
+
+
+
+/*HDR*/
+/**
+ * @brief Check if an array of octets is valid, i.e. != 0
+ *
+ * @param p_addr Pointer to a MAC address
+ *
+ * @return MBG_LU_SUCCESS MAC address is valid, i.e. not all 0
+ * MBG_LU_ERR_NOT_SET MAC address is invalid, i.e. all 0
+ *
+ * @see check_octets_not_all_zero
+ */
+int check_mac_addr_not_all_zero( const MBG_MAC_ADDR *p_addr )
+{
+ return check_octets_not_all_zero( p_addr->b, sizeof( p_addr->b ) );
+
+} // check_mac_addr_not_all_zero
+
+
+
+#if defined( MBG_TGT_UNIX )
+
+/*HDR*/
+/**
+ * @brief Do a SIOCGxxx IOCTL call to read specific information from a LAN interface
+ *
+ * @param if_name Name of the interface
+ * @param ioctl_code One of the predefined system SIOCGxxx IOCTL codes
+ * @param p_ifreq Pointer to a request buffer
+ *
+ * @return one of the ::MBG_LU_CODES
+ */
+int do_siocg_ioctl( const char *if_name, int ioctl_code, struct ifreq *p_ifreq )
+{
+ int fd;
+ int rc;
+
+ if ( strlen( if_name ) > ( IFNAMSIZ - 1 ) )
+ return MBG_LU_ERR_PORT_NAME;
+
+ fd = socket( AF_INET, SOCK_DGRAM, 0 );
+
+ if ( fd < 0 )
+ return MBG_LU_ERR_SOCKET;
+
+ strcpy( p_ifreq->ifr_name, if_name );
+
+ rc = ioctl( fd, ioctl_code, p_ifreq );
+
+ if ( rc < 0 )
+ rc = MBG_LU_ERR_IOCTL;
+
+ close( fd );
+
+ return MBG_LU_SUCCESS;
+
+} // do_siocg_ioctl
+
+#endif // defined( MBG_TGT_UNIX )
+
+
+
+/*HDR*/
+/**
+ * @brief Retrieve the MAC address of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_mac_addr Pointer to the MAC address buffer to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ * on error the MAC addr is set to all 0
+ *
+ * @see get_port_mac_addr_check
+ */
+int get_port_mac_addr( const char *if_name, MBG_MAC_ADDR *p_mac_addr )
+{
+ int rc = MBG_LU_ERR_NSUPP;
+
+ #if defined( MBG_TGT_LINUX )
+ struct ifreq ifr = { { { 0 } } };
+
+ rc = do_siocg_ioctl( if_name, SIOCGIFHWADDR, &ifr );
+
+ if ( rc != MBG_LU_SUCCESS )
+ goto fail;
+
+ memcpy( p_mac_addr, ifr.ifr_hwaddr.sa_data, sizeof( *p_mac_addr ) );
+
+ return rc;
+
+fail:
+ #endif
+
+ memset( p_mac_addr, 0, sizeof( *p_mac_addr ) );
+
+ return rc;
+
+} // get_port_mac_addr
+
+
+
+/*HDR*/
+/**
+ * @brief Retrieve and check the MAC address of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_mac_addr Pointer to the MAC address buffer to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ * on error the MAC addr is set to all 0
+ *
+ * @see get_port_mac_addr
+ */
+int get_port_mac_addr_check( const char *if_name, MBG_MAC_ADDR *p_mac_addr )
+{
+ int rc = get_port_mac_addr( if_name, p_mac_addr );
+
+ if ( rc == MBG_LU_SUCCESS )
+ rc = check_octets_not_all_zero( p_mac_addr->b, sizeof( *p_mac_addr ) );
+
+ return rc;
+
+} // get_port_mac_addr_check
+
+
+
+/*HDR*/
+/**
+ * @brief Check the link state of a network interface
+ *
+ * @param if_name Name of the interface
+ *
+ * @return 1 link detected on port
+ * 0 no link detected on port
+ * one of the ::MBG_LU_CODES in case of an error
+ */
+int check_port_link( const char *if_name )
+{
+ #if defined( MBG_TGT_LINUX )
+ struct ifreq ifr = { { { 0 } } };
+ struct ethtool_value edata = { 0 };
+ int rc;
+
+ edata.cmd = ETHTOOL_GLINK; // defined in ethtool.h
+ ifr.ifr_data = (caddr_t) &edata;
+
+ rc = do_siocg_ioctl( if_name, SIOCETHTOOL, &ifr );
+
+ if ( rc == MBG_LU_SUCCESS )
+ rc = edata.data != 0;
+
+ return rc;
+
+ #else
+
+ return MBG_LU_ERR_NSUPP;
+
+ #endif
+
+} // check_port_link
+
+
+
+static /*HDR*/
+/**
+ * @brief Retrieve some IPv4 address like info from a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_addr Pointer to address field to be filled up
+ * @param sigioc_code the ioctl code associated to the address
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ */
+int get_specific_port_ip4_addr( const char *if_name, IP4_ADDR *p_addr, int sigioc_code )
+{
+ int rc = MBG_LU_ERR_NSUPP;
+
+ #if defined( MBG_TGT_LINUX )
+ struct ifreq ifr = { { { 0 } } };
+
+ rc = do_siocg_ioctl( if_name, sigioc_code, &ifr );
+
+ if ( rc != MBG_LU_SUCCESS )
+ goto fail;
+
+ *p_addr = ntohl( ( (struct sockaddr_in *) &ifr.ifr_addr )->sin_addr.s_addr );
+
+ return rc;
+
+fail:
+ #endif
+
+ *p_addr = 0; // make empty address
+
+ return rc;
+
+} // get_specific_port_ip4_addr
+
+
+
+/*HDR*/
+/**
+ * @brief Retrieve the IPv4 address of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_addr Pointer to address field to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+int get_port_ip4_addr( const char *if_name, IP4_ADDR *p_addr )
+{
+ return get_specific_port_ip4_addr( if_name, p_addr, SIOCGIFADDR );
+
+} // get_port_ip4_addr
+
+
+
+/*HDR*/
+/**
+ * @brief Retrieve the IPv4 net mask of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_addr Pointer to address field to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+int get_port_ip4_netmask( const char *if_name, IP4_ADDR *p_addr )
+{
+ return get_specific_port_ip4_addr( if_name, p_addr, SIOCGIFNETMASK );
+
+} // get_port_ip4_netmask
+
+
+
+/*HDR*/
+/**
+ * @brief Retrieve the IPv4 broadcast address of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_addr Pointer to address field to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+int get_port_ip4_broad_addr( const char *if_name, IP4_ADDR *p_addr )
+{
+ return get_specific_port_ip4_addr( if_name, p_addr, SIOCGIFBRDADDR );
+
+} // get_port_ip4_broad_addr
+
+
+
+#if defined( MBG_TGT_LINUX )
+
+static /*HDR*/
+/**
+ * @brief Read a requested message from the netlink socket
+ */
+int readNlSock( int sockFd, char *bufPtr, size_t buf_size, int seqNum, int pId )
+{
+ struct nlmsghdr *nlHdr;
+ int readLen = 0;
+ int msgLen = 0;
+
+ do
+ {
+ // receive response from the kernel, can be several chunks
+ if ( ( readLen = recv( sockFd, bufPtr, buf_size - msgLen, 0 ) ) < 0 )
+ {
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Failed to receive netlink packet: %s",
+ __func__, strerror( errno ) );
+ #endif
+ return -1;
+ }
+
+ nlHdr = (struct nlmsghdr *) bufPtr;
+
+ // check if the header is valid
+ if ( ( NLMSG_OK( nlHdr, readLen ) == 0 ) || ( nlHdr->nlmsg_type == NLMSG_ERROR ) )
+ {
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Invalid header in received netlink packet",
+ __func__ );
+ #endif
+ return -1;
+ }
+
+ // check if the its the last message
+ if ( nlHdr->nlmsg_type == NLMSG_DONE )
+ {
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Reached last message in received packet",
+ __func__ );
+ #endif
+ break;
+ }
+
+ // move the pointer to buffer appropriately
+ bufPtr += readLen;
+ msgLen += readLen;
+
+ // check if its a multi part message
+ if ( ( nlHdr->nlmsg_flags & NLM_F_MULTI ) == 0 )
+ {
+ // return if it's not a multi part message
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Received packet is not a multi part message",
+ __func__ );
+ #endif
+ break;
+ }
+
+ } while ( ( nlHdr->nlmsg_seq != seqNum ) || ( nlHdr->nlmsg_pid != pId ) );
+
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Received packet has len %i",
+ __func__, msgLen );
+ #endif
+
+ return msgLen;
+
+} // readNlSock
+
+
+
+#if DEBUG_NETLINK
+
+static /*HDR*/
+void log_netlink_bytes( const char *fnc, const char *info, const void *p, int n_bytes )
+{
+ char ws[80];
+ int n = 0;
+ int i;
+
+ for ( i = 0; i < n_bytes; i++ )
+ n += snprintf( &ws[n], sizeof( ws ) - n, " %i", BYTE_OF( *p, i ) );
+
+ mbglog( LOG_INFO, "%s: attibute %s, copying %i bytes:%s",
+ fnc, info, n_bytes, ws );
+
+} // log_netlink_bytes
+
+#endif
+
+
+
+static /*HDR*/
+int parseRoutes( struct nlmsghdr *nlHdr, struct route_info *rtInfo )
+{
+ // parse the route info returned
+ struct rtmsg *rtMsg;
+ struct rtattr *rtAttr;
+ int rtLen;
+
+ rtMsg = (struct rtmsg *) NLMSG_DATA( nlHdr );
+
+ // If the route is not for AF_INET then return.
+ // This could be also IPv6 routes.
+ if ( rtMsg->rtm_family != AF_INET )
+ {
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Route is not AF_INET (%li), but %li",
+ __func__, (long) AF_INET, (long) rtMsg->rtm_family );
+ #endif
+ return -1;
+ }
+
+ // If the route does not belong to main routing table then return.
+ if ( rtMsg->rtm_table != RT_TABLE_MAIN )
+ {
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Route does not belong to main table (%li), but %li",
+ __func__, (long) RT_TABLE_MAIN, (long) rtMsg->rtm_table );
+ #endif
+ return -1;
+ }
+
+
+ // get the rtattr field
+ rtAttr = (struct rtattr *) RTM_RTA( rtMsg );
+ rtLen = RTM_PAYLOAD( nlHdr );
+
+ for ( ; RTA_OK( rtAttr, rtLen ); rtAttr = RTA_NEXT( rtAttr, rtLen ) )
+ {
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "rtAttr at %p, %i bytes left", rtAttr, rtLen );
+ #endif
+
+ switch ( rtAttr->rta_type )
+ {
+ case RTA_OIF:
+ if_indextoname( *(int *)RTA_DATA( rtAttr ), rtInfo->ifName );
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: attibute RTA_OIF, IF name: %s",
+ __func__, rtInfo->ifName );
+ #endif
+ break;
+
+ case RTA_GATEWAY:
+ memcpy( &rtInfo->gateWay, RTA_DATA( rtAttr ), sizeof( rtInfo->gateWay ) );
+ #if DEBUG_NETLINK
+ log_netlink_bytes( __func__, "RTA_GATEWAY", &rtInfo->gateWay, sizeof( rtInfo->gateWay ) );
+ #endif
+ break;
+
+ case RTA_PREFSRC:
+ memcpy( &rtInfo->srcAddr , RTA_DATA( rtAttr ), sizeof( rtInfo->srcAddr ) );
+ #if DEBUG_NETLINK
+ log_netlink_bytes( __func__, "RTA_PREFSRC", &rtInfo->srcAddr, sizeof( rtInfo->srcAddr ) );
+ #endif
+ break;
+
+ case RTA_DST:
+ memcpy( &rtInfo->dstAddr, RTA_DATA( rtAttr ), sizeof( rtInfo->dstAddr ) );
+ #if DEBUG_NETLINK
+ log_netlink_bytes( __func__, "RTA_DST", &rtInfo->dstAddr, sizeof( rtInfo->dstAddr ) );
+ #endif
+ break;
+
+ #if DEBUG_NETLINK
+ case RTA_TABLE:
+ {
+ // The RTA_TABLE attribute was added to the kernel source in 2006 to support
+ // more than 255 routing tables. Originally the number of the routing table
+ // to which an entry belongs had been passed only in struct rtmsg::rtm_table,
+ // which is only 8 bits wide and should still hold the 8 LSBs of the full
+ // routing table number for compatibility, so this should still work for the
+ // standard routing tables, including the main table we are inspecting here.
+ //
+ // Whether this can be compiled in depends on the version of linux/rtnetlink.h
+ // used by the compiler. Unfortunately RTA_TABLE is part of an enum, so you
+ // can't simply use #ifdef RTA_TABLE to include this code conditionally.
+ uint32_t rta_table;
+ memcpy( &rta_table, RTA_DATA( rtAttr ), sizeof( rta_table ) );
+ mbglog( LOG_ERR, "%s: attibute RTA_TABLE %i (%i)",
+ __func__, rta_table, rtMsg->rtm_table );
+ }
+ break;
+
+ default:
+ mbglog( LOG_ERR, "%s: Found unknown route type %li",
+ __func__, (long) rtAttr->rta_type );
+ #endif
+ }
+ }
+
+ return 0;
+
+} // parseRoutes
+
+#endif // defined( MBG_TGT_LINUX )
+
+
+
+/*HDR*/
+/**
+ * @brief Retrieve the IPv4 gateway (default route)
+ *
+ * @param p_addr Pointer to address field to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ */
+int get_ip4_gateway( IP4_ADDR *p_addr )
+{
+ int ret_val = MBG_LU_ERR_NOT_SET;
+
+#if defined( MBG_TGT_LINUX )
+ struct nlmsghdr *nlMsg;
+ struct route_info route_info;
+ char msgBuf[8192]; // pretty large buffer
+
+ int sock;
+ int len;
+ int msgSeq = 0;
+ int idx;
+
+ // create socket
+ if ( ( sock = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE ) ) < 0 )
+ {
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Failed to create netlink socket: %s",
+ __func__, strerror( errno ) );
+ #endif
+ ret_val = MBG_LU_ERR_SOCKET;
+ goto out;
+ }
+
+
+ // initialize the buffer
+ memset( msgBuf, 0, sizeof( msgBuf ) );
+
+ // point the header and the msg structure pointers into the buffer
+ nlMsg = (struct nlmsghdr *) msgBuf;
+
+ // fill in the nlmsg header
+ nlMsg->nlmsg_len = NLMSG_LENGTH( sizeof( struct rtmsg ) ); // length of message
+ nlMsg->nlmsg_type = RTM_GETROUTE; // get the routes from kernel routing table
+
+ nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // the message is a request for dump
+ nlMsg->nlmsg_seq = msgSeq++; // sequence of the message packet
+ nlMsg->nlmsg_pid = getpid(); // PID of process sending the request
+
+ // send the request
+ if ( send( sock, nlMsg, nlMsg->nlmsg_len, 0 ) < 0 )
+ {
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Failed to write to netlink socket: %s",
+ __func__, strerror( errno ) );
+ #endif
+ ret_val = -1;
+ goto out;
+ }
+
+ // read the response
+ if ( ( len = readNlSock( sock, msgBuf, sizeof( msgBuf ), msgSeq, getpid() ) ) < 0 )
+ {
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Failed to read from netlink socket",
+ __func__ );
+ #endif
+ ret_val = -1;
+ goto out;
+ }
+
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Read %i bytes from netlink socket", __func__ );
+ #endif
+
+ // parse and print the response
+ for ( idx = 0; NLMSG_OK( nlMsg, len ); nlMsg = NLMSG_NEXT( nlMsg, len ), idx ++ )
+ {
+ memset( &route_info, 0, sizeof( route_info ) );
+
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "\nnlMsg at %p, %i bytes left", nlMsg, len );
+ #endif
+
+
+ if ( parseRoutes( nlMsg, &route_info ) < 0 )
+ continue; // don't check route_info if it has not been set up
+
+ #if DEBUG_NETLINK
+ {
+ char ws[100];
+ int l = sizeof( ws );
+ int n = 0;
+
+ // inet_ntoa() uses a static buffer which is overwritten on every call
+ n += snprintf( &ws[n], l - n, "src %s", (char *) inet_ntoa( route_info.srcAddr ) );
+ n += snprintf( &ws[n], l - n, ", dst %s", (char *) inet_ntoa( route_info.dstAddr ) );
+ n += snprintf( &ws[n], l - n, ", gw %s", (char *) inet_ntoa( route_info.gateWay ) );
+
+ mbglog( LOG_ERR, "%s: route %i: %s, if \"%s\"",
+ __func__, idx, ws, route_info.ifName );
+ }
+ #endif
+
+ // check if default IPv4 gateway
+ if ( strstr( (char *) inet_ntoa( route_info.dstAddr ), "0.0.0.0" ) )
+ {
+ *p_addr = ntohl( route_info.gateWay.s_addr );
+ ret_val = MBG_LU_SUCCESS;
+ // Actually we could stop searching now. However, in case of debug
+ // we'll continue to examine the rest of the routing message.
+ #if DEBUG_NETLINK
+ mbglog( LOG_ERR, "%s: Default gateway found: %s",
+ __func__, (char *) inet_ntoa( route_info.gateWay ) );
+ #else
+ break;
+ #endif
+ }
+ }
+
+out:
+ if ( sock >= 0 )
+ close( sock );
+
+#endif // defined( MBG_TGT_LINUX )
+
+
+ if ( ret_val != MBG_LU_SUCCESS )
+ *p_addr = 0;
+
+ return ret_val;
+
+} // get_ip4_gateway
+
+
+
+/*HDR*/
+/**
+ * @brief Retrieve the IPv4 address of a network interface as string
+ *
+ * @param if_name Name of the interface
+ * @param p_addr_buf Pointer to the string buffer to be filled up
+ * @param buf_size size of the string buffer
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+int get_port_ip4_addr_str( const char *if_name, char *p_addr_buf, int buf_size )
+{
+ IP4_ADDR addr;
+
+ int rc = get_port_ip4_addr( if_name, &addr );
+
+ snprint_ip4_addr( p_addr_buf, buf_size, &addr, NULL );
+
+ return rc;
+
+} // get_port_ip4_addr_str
+
+
+
+/*HDR*/
+/**
+ * @brief Retrieve the IPv4 net mask of a network interface as string
+ *
+ * @param if_name Name of the interface
+ * @param p_addr_buf Pointer to the string buffer to be filled up
+ * @param buf_size size of the string buffer
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+int get_port_ip4_netmask_str( const char *if_name, char *p_addr_buf, int buf_size )
+{
+ IP4_ADDR addr;
+
+ int rc = get_port_ip4_netmask( if_name, &addr );
+
+ snprint_ip4_addr( p_addr_buf, buf_size, &addr, NULL );
+
+ return rc;
+
+} // get_port_ip4_netmask_str
+
+
+
+/*HDR*/
+/**
+ * @brief Retrieve the IPv4 broadcast address of a network interface as string
+ *
+ * @param if_name Name of the interface
+ * @param p_addr_buf Pointer to the string buffer to be filled up
+ * @param buf_size size of the string buffer
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_specific_port_ip4_addr
+ */
+int get_port_ip4_broad_addr_str( const char *if_name, char *p_addr_buf, int buf_size )
+{
+ IP4_ADDR addr;
+
+ int rc = get_port_ip4_broad_addr( if_name, &addr );
+
+ snprint_ip4_addr( p_addr_buf, buf_size, &addr, NULL );
+
+ return rc;
+
+} // get_port_ip4_broad_addr_str
+
+
+
+/*HDR*/
+/**
+ * @brief Retrieve the current IPv4 settings of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p Pointer to a IP4_SETTINGS structure to be filled up
+ *
+ * @return 0 on success, < 0 on error
+ *
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+int get_port_ip4_settings( const char *if_name, IP4_SETTINGS *p )
+{
+ int link_up;
+ int ret_val = 0;
+
+ memset( p, 0, sizeof( *p ) );
+
+ if ( get_port_ip4_addr( if_name, &p->ip_addr ) )
+ ret_val = -1;
+
+ if ( get_port_ip4_netmask( if_name, &p->netmask ) )
+ ret_val = -1;
+
+ if ( get_port_ip4_broad_addr( if_name, &p->broad_addr ) )
+ ret_val = -1;
+
+ if ( get_ip4_gateway( &p->gateway ) )
+ ret_val = -1;
+
+
+ link_up = check_port_link( if_name );
+
+ if ( link_up )
+ p->flags |= IP4_MSK_LINK;
+
+#if 0 //##+++++
+ // We could also try to check VLAN and DHCP settings here,
+ // but as of now, this is specific to an application.
+
+ // ##++++ The VLAN and DHCP status info collected below
+ // just return what has been configured previously by this program,
+ // however, it does not reflect any changes which have been made
+ // manually, e.g. via the command line.
+ if ( vlan_enabled )
+ {
+ p->flags |= IP4_MSK_VLAN;
+ p->vlan_cfg = vlan_cfg;
+ }
+
+ if ( dhcp_enabled )
+ p->flags |= IP4_MSK_DHCP;
+#endif
+
+ return ret_val;
+
+} // get_port_ip4_settings
+
+
diff --git a/mbglib/common/lan_util.h b/mbglib/common/lan_util.h
new file mode 100644
index 0000000..d3e39a5
--- /dev/null
+++ b/mbglib/common/lan_util.h
@@ -0,0 +1,579 @@
+
+/**************************************************************************
+ *
+ * $Id: lan_util.h 1.4 2013/02/19 15:15:53Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for lan_util.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: lan_util.h $
+ * Revision 1.4 2013/02/19 15:15:53Z martin
+ * Added some inline functions.
+ * Redefined return codes as named enum.
+ * Updated function prototypes.
+ * Revision 1.3 2012/10/02 18:24:29 martin
+ * Added some macros to simpliy conversion to string.
+ * Revision 1.2 2012/03/09 08:51:44 martin
+ * Updated function prototypes.
+ * Revision 1.1 2011/03/04 10:01:32 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _LAN_UTIL_H
+#define _LAN_UTIL_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+#include <gpsdefs.h>
+
+#include <stdlib.h>
+
+#if defined( MBG_TGT_UNIX )
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <net/if.h>
+#else
+ // A dummy declaration to prevent from warnings due to usage
+ // of this type with function prototypes.
+ struct ifreq
+ {
+ int dummy;
+ };
+#endif
+
+
+#if defined( IFHWADDRLEN ) // usually defined in net/if.h
+ #if ( IFHWADDRLEN != 6 )
+ #error Warning: IFHWADDRLEN is not 6!
+ #endif
+#endif
+
+
+
+#ifdef _LAN_UTIL
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if !defined( MAC_SEP_CHAR )
+ #define MAC_SEP_CHAR ':' // character used to separate octets of a MAC ID
+#endif
+
+#if !defined( MAC_SEP_CHAR_ALT )
+ #define MAC_SEP_CHAR_ALT '-' // alternate character
+#endif
+
+
+/**
+ * @brief Return codes for the LAN utility functions
+ */
+enum MBG_LU_CODES
+{
+ MBG_LU_SUCCESS = 0, ///< success
+ MBG_LU_ERR_NSUPP = -1, ///< function not supported
+ MBG_LU_ERR_PORT_NAME = -2, ///< port name exceeds max length
+ MBG_LU_ERR_SOCKET = -3, ///< failed to open socket
+ MBG_LU_ERR_IOCTL = -4, ///< IOCTL call failed
+ MBG_LU_ERR_NOT_SET = -5, ///< octets are all 0
+ MBG_LU_ERR_BUFF_SZ = -6, ///< buffer size too small
+ MBG_LU_ERR_FMT = -7, ///< parameter format not correct
+ MBG_LU_ERR_RANGE = -8 ///< range for some parameter exceeded
+};
+
+
+#define MAX_IP4_BITS ( 8 * sizeof( IP4_ADDR ) )
+
+#define IP4_MSB_MASK ( 1UL << ( MAX_IP4_BITS - 1 ) )
+
+#define MIN_IP4_CIDR_NETMASK_BITS 0
+#define MAX_IP4_CIDR_NETMASK_BITS MAX_IP4_BITS
+
+
+
+/**
+ * @brief Compute an IP4 net mask according to the number of CIDR netmask bits
+ *
+ * E.g. the 24 bits mentioned in "172.16.3.250/24" result in 0xFFFFFF00,
+ * corresponding to 255.255.255.0 in dotted quad notation.
+ *
+ * @param netmask_bits Number of netmask bits from CIDR notation
+ *
+ * @return The IP4 net mask
+ *
+ * @see get_ip4_net_mask_bits()
+ */
+static __mbg_inline
+IP4_ADDR ip4_net_mask_from_cidr( int netmask_bits )
+{
+ return (IP4_ADDR) ~( ( 1UL << ( MAX_IP4_BITS - netmask_bits ) ) - 1 );
+
+} // ip4_net_mask_from_cidr
+
+
+
+/**
+ * @brief Determine the broadcast address for an IP4 address plus net mask
+ *
+ * E.g. IP 0xAC1003FA, net mask 0xFFFFFF00 yields broadcast addr 0xAC1003FF.
+ * In dotted quad notation, IP 172.16.3.250 with net mask 255.255.255.0
+ * result in broadcast address 172.16.3.255.
+ *
+ * @param p_addr The full IP4 address
+ * @param p_mask The IP4 net mask
+ *
+ * @return The determined IP4 broadcast address
+ */
+static __mbg_inline
+IP4_ADDR ip4_broad_addr_from_addr( const IP4_ADDR *p_addr, const IP4_ADDR *p_mask )
+{
+ return *p_addr | ~(*p_mask);
+
+} // ip4_broad_addr_from_addr
+
+
+
+/**
+ * @brief Determine the network part of an IP4 address based on the net mask
+ *
+ * E.g. IP 0xAC1003FA, net mask 0xFFFFFF00 yields network part 0xAC100300.
+ * In dotted quad notation, IP 172.16.3.250 with net mask 255.255.255.0
+ * results in network part 172.16.3.0.
+ *
+ * @param p_addr The full IP4 address
+ * @param p_mask The IP4 net mask
+ *
+ * @return The network part of the IP4 address
+ */
+static __mbg_inline
+IP4_ADDR ip4_net_part_from_addr( const IP4_ADDR *p_addr, const IP4_ADDR *p_mask )
+{
+ return *p_addr & *p_mask;
+
+} // ip4_net_part_from_addr
+
+
+
+/**
+ * @brief Check if two IP4 addresses have the same network part.
+ *
+ * @param p_addr1 The first IP4 address to check
+ * @param p_addr2 The second IP4 address to check
+ * @param p_mask The IP4 net mask
+ *
+ * @return true, if the network parts are matching
+ */
+static __mbg_inline
+int ip4_net_part_matches( const IP4_ADDR *p_addr1, const IP4_ADDR *p_addr2,
+ const IP4_ADDR *p_mask )
+{
+ return ip4_net_part_from_addr( p_addr1, p_mask )
+ == ip4_net_part_from_addr( p_addr2, p_mask );
+
+} // ip4_net_part_matches
+
+
+
+#define _ip4_addr_to_str( _s, _a ) \
+ snprint_ip4_addr( _s, sizeof( _s ), _a, NULL )
+
+#define _mac_addr_to_str( _s, _a ) \
+ snprint_mac_addr( _s, sizeof( _s ), _a )
+
+
+
+/* function prototypes: */
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ /**
+ * @brief Count the number of sequential bits set starting from MSB
+ *
+ * E.g. for 0xC0 and 0xC1 the results are both 2 since only
+ * the 2 MSBs are sequentially set.
+ *
+ * @param p_mask The IP4 net mask
+ *
+ * @return The number of sequential MSB bits set in val
+ *
+ * @see ip4_net_mask_from_cidr
+ */
+ int get_ip4_net_mask_bits( const IP4_ADDR *p_mask ) ;
+
+ /**
+ * @brief Print an IPv4 address to a dotted quad format string.
+ *
+ * @param s The string buffer into which to print
+ * @param max_len Maximum length of the string, i.e. size of the buffer
+ * @param p_addr The IPv4 address
+ * @param info An optional string which is prepended to the string, or NULL
+ *
+ * @return The overall number of characters printed to the string
+ *
+ * @see snprint_ip4_cidr_addr
+ * @see str_to_ip4_addr
+ * @see cidr_str_to_ip4_addr_and_net_mask
+ */
+ int snprint_ip4_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, const char *info ) ;
+
+ /**
+ * @brief Print an IPv4 address plus net mask to string in CIDR notation.
+ *
+ * The printed CIDR string is something like "172.16.3.250/24"
+ *
+ * @param s The string buffer into which to print
+ * @param max_len Maximum length of the string, i.e. size of the buffer
+ * @param p_addr The IPv4 address
+ * @param p_mask The IPv4 net mask
+ * @param info An optional string which is prepended to the string, or NULL
+ *
+ * @return The overall number of characters printed to the string
+ *
+ * @see snprint_ip4_addr
+ * @see str_to_ip4_addr
+ * @see cidr_str_to_ip4_addr_and_net_mask
+ */
+ int snprint_ip4_cidr_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, const IP4_ADDR *p_mask, const char *info ) ;
+
+ /**
+ * @brief Convert a string to an IP4_ADDR.
+ *
+ * @param p_addr Pointer to the IP4_ADDR variable, or NULL, in which case this
+ * function can be used to check if the string is formally correct.
+ * @param s The string to be converted
+ *
+ * @return >= 0 on success, number of characters evaluated from the input string
+ * -1 if invalid number found in string
+ * -2 if separator is not a dot '.'
+ *
+ * @see snprint_ip4_addr
+ * @see snprint_ip4_cidr_addr
+ * @see cidr_str_to_ip4_addr_and_net_mask
+ */
+ int str_to_ip4_addr( IP4_ADDR *p_addr, const char *s ) ;
+
+ /**
+ * @brief Convert a string in CIDR notation to an IP4_ADDR and net mask.
+ *
+ * @param p_addr Pointer to an IP4_ADDR variable for the IP4 address,
+ * or NULL, in which case this function can be used
+ * to check if the string is formally correct.
+ * @param p_mask Pointer to an IP4_ADDR variable for the net mask,
+ * or NULL, in which case this function can be used
+ * to check if the string is formally correct.
+ * @param cidr_str The string to be converted, in CIDR format, e.g. "172.16.3.250/24"
+ *
+ * @return >= 0 on success, number of characters evaluated from the input string
+ * one of the ::MBG_LU_CODES on error
+ *
+ * @see snprint_ip4_addr
+ * @see snprint_ip4_cidr_addr
+ * @see str_to_ip4_addr
+ */
+ int cidr_str_to_ip4_addr_and_net_mask( IP4_ADDR *p_addr, IP4_ADDR *p_mask, const char *cidr_str ) ;
+
+ /**
+ * @brief Print a MAC ID or similar array of octets to a string.
+ *
+ * @param s The string buffer into which to print
+ * @param max_len Maximum length of the string, i.e. size of the buffer
+ * @param octets An array of octets
+ * @param num_octets The number of octets to be printed from the array
+ * @param sep The separator printed between the bytes, or 0
+ * @param info An optional string which is prepended to the output, or NULL
+ *
+ * @return The overall number of characters printed to the string
+ *
+ * @see snprint_mac_addr
+ * @see str_to_octets
+ * @see check_octets_not_all_zero
+ */
+ int snprint_octets( char *s, size_t max_len, const uint8_t *octets, int num_octets, char sep, const char *info ) ;
+
+ /**
+ * @brief Print a MAC address to a string.
+ *
+ * @param s The string buffer into which to print
+ * @param max_len Maximum length of the string, i.e. size of the buffer
+ * @param p_mac_addr The MAC address to be printed
+ *
+ * @return The overall number of characters printed to the string
+ *
+ * @see snprint_octets
+ * @see str_to_octets
+ * @see check_octets_not_all_zero
+ */
+ int snprint_mac_addr( char *s, size_t max_len, const MBG_MAC_ADDR *p_mac_addr ) ;
+
+ /**
+ * @brief Set a MAC ID or a similar array of octets from a string.
+ *
+ * @param octets An array of octets to be set up
+ * @param num_octets The number of octets which can be stored
+ * @param s The string to be converted
+ *
+ * @return The overall number of octets decoded from the string
+ *
+ * @see snprint_octets
+ * @see snprint_mac_addr
+ * @see check_octets_not_all_zero
+ */
+ int str_to_octets( uint8_t *octets, int num_octets, const char *s ) ;
+
+ /**
+ * @brief Check if an array of octets is valid, i.e. != 0
+ *
+ * @param octets Pointer to the array of octets
+ * @param num_octets Number of octets
+ *
+ * @return MBG_LU_SUCCESS octets are valid, i.e. not all 0
+ * MBG_LU_ERR_NOT_SET octets are invalid, i.e. all 0
+ *
+ * @see snprint_octets
+ * @see snprint_mac_addr
+ * @see str_to_octets
+ */
+ int check_octets_not_all_zero( const uint8_t *octets, int num_octets ) ;
+
+ /**
+ * @brief Check if an array of octets is valid, i.e. != 0
+ *
+ * @param p_addr Pointer to a MAC address
+ *
+ * @return MBG_LU_SUCCESS MAC address is valid, i.e. not all 0
+ * MBG_LU_ERR_NOT_SET MAC address is invalid, i.e. all 0
+ *
+ * @see check_octets_not_all_zero
+ */
+ int check_mac_addr_not_all_zero( const MBG_MAC_ADDR *p_addr ) ;
+
+ /**
+ * @brief Do a SIOCGxxx IOCTL call to read specific information from a LAN interface
+ *
+ * @param if_name Name of the interface
+ * @param ioctl_code One of the predefined system SIOCGxxx IOCTL codes
+ * @param p_ifreq Pointer to a request buffer
+ *
+ * @return one of the ::MBG_LU_CODES
+ */
+ int do_siocg_ioctl( const char *if_name, int ioctl_code, struct ifreq *p_ifreq ) ;
+
+ /**
+ * @brief Retrieve the MAC address of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_mac_addr Pointer to the MAC address buffer to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ * on error the MAC addr is set to all 0
+ *
+ * @see get_port_mac_addr_check
+ */
+ int get_port_mac_addr( const char *if_name, MBG_MAC_ADDR *p_mac_addr ) ;
+
+ /**
+ * @brief Retrieve and check the MAC address of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_mac_addr Pointer to the MAC address buffer to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ * on error the MAC addr is set to all 0
+ *
+ * @see get_port_mac_addr
+ */
+ int get_port_mac_addr_check( const char *if_name, MBG_MAC_ADDR *p_mac_addr ) ;
+
+ /**
+ * @brief Check the link state of a network interface
+ *
+ * @param if_name Name of the interface
+ *
+ * @return 1 link detected on port
+ * 0 no link detected on port
+ * one of the ::MBG_LU_CODES in case of an error
+ */
+ int check_port_link( const char *if_name ) ;
+
+ /**
+ * @brief Retrieve the IPv4 address of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_addr Pointer to address field to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+ int get_port_ip4_addr( const char *if_name, IP4_ADDR *p_addr ) ;
+
+ /**
+ * @brief Retrieve the IPv4 net mask of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_addr Pointer to address field to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+ int get_port_ip4_netmask( const char *if_name, IP4_ADDR *p_addr ) ;
+
+ /**
+ * @brief Retrieve the IPv4 broadcast address of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p_addr Pointer to address field to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+ int get_port_ip4_broad_addr( const char *if_name, IP4_ADDR *p_addr ) ;
+
+ /**
+ * @brief Retrieve the IPv4 gateway (default route)
+ *
+ * @param p_addr Pointer to address field to be filled up
+ *
+ * @return one of the ::MBG_LU_CODES
+ */
+ int get_ip4_gateway( IP4_ADDR *p_addr ) ;
+
+ /**
+ * @brief Retrieve the IPv4 address of a network interface as string
+ *
+ * @param if_name Name of the interface
+ * @param p_addr_buf Pointer to the string buffer to be filled up
+ * @param buf_size size of the string buffer
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+ int get_port_ip4_addr_str( const char *if_name, char *p_addr_buf, int buf_size ) ;
+
+ /**
+ * @brief Retrieve the IPv4 net mask of a network interface as string
+ *
+ * @param if_name Name of the interface
+ * @param p_addr_buf Pointer to the string buffer to be filled up
+ * @param buf_size size of the string buffer
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+ int get_port_ip4_netmask_str( const char *if_name, char *p_addr_buf, int buf_size ) ;
+
+ /**
+ * @brief Retrieve the IPv4 broadcast address of a network interface as string
+ *
+ * @param if_name Name of the interface
+ * @param p_addr_buf Pointer to the string buffer to be filled up
+ * @param buf_size size of the string buffer
+ *
+ * @return one of the ::MBG_LU_CODES
+ *
+ * @see get_port_ip4_settings
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_specific_port_ip4_addr
+ */
+ int get_port_ip4_broad_addr_str( const char *if_name, char *p_addr_buf, int buf_size ) ;
+
+ /**
+ * @brief Retrieve the current IPv4 settings of a network interface
+ *
+ * @param if_name Name of the interface
+ * @param p Pointer to a IP4_SETTINGS structure to be filled up
+ *
+ * @return 0 on success, < 0 on error
+ *
+ * @see get_port_ip4_addr
+ * @see get_port_ip4_addr_str
+ * @see get_port_ip4_netmask
+ * @see get_port_ip4_netmask_str
+ * @see get_port_ip4_broad_addr
+ * @see get_port_ip4_broad_addr_str
+ * @see get_specific_port_ip4_addr
+ */
+ int get_port_ip4_settings( const char *if_name, IP4_SETTINGS *p ) ;
+
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _LAN_UTIL_H */
+
diff --git a/mbglib/common/mbg_arch.h b/mbglib/common/mbg_arch.h
new file mode 100644
index 0000000..4bc92fd
--- /dev/null
+++ b/mbglib/common/mbg_arch.h
@@ -0,0 +1,167 @@
+
+/**************************************************************************
+ *
+ * $Id: mbg_arch.h 1.4 2012/10/02 18:32:00Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions to support different computer hardware architectures.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbg_arch.h $
+ * Revision 1.4 2012/10/02 18:32:00Z martin
+ * Include words.h and, conditionally, stdlib.h.
+ * Use generic preprocessor symbol MBG_TGT_KERNEL.
+ * Revision 1.3 2009/06/12 13:12:37Z martin
+ * Fixed compiler warning.
+ * Revision 1.2 2009/03/19 15:14:15 martin
+ * Fixed byte swapping of doubles for SPARC architecture.
+ * Revision 1.1 2008/12/05 13:47:42 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _MBG_ARCH_H
+#define _MBG_ARCH_H
+
+#include <mbg_tgt.h>
+#include <words.h>
+
+#if !defined( MBG_TGT_KERNEL )
+ #include <stdlib.h>
+#endif
+
+
+#if defined( MBG_ARCH_SPARC )
+ #define MBG_ARCH_BIG_ENDIAN 1
+#endif
+
+
+#if !defined( MBG_ARCH_BIG_ENDIAN )
+ #define MBG_ARCH_LITTLE_ENDIAN 1
+#endif
+
+
+
+#if defined( MBG_TGT_LINUX )
+
+ #include <asm/byteorder.h>
+
+ #if defined( MBG_TGT_KERNEL )
+ #include <asm/unaligned.h>
+
+ #define _mbg_put_unaligned( _v, _p ) put_unaligned( _v, _p )
+ #define _mbg_get_unaligned( _p ) get_unaligned( _p )
+ #endif
+
+#endif
+
+
+
+// If no macros required to access unaligned data have yet been defined,
+// define some default macros assuming no special handling is required
+// to access unaligned data.
+
+#if !defined( _mbg_put_unaligned )
+ #define _mbg_put_unaligned( _v, _p ) ((void)( *(_p) = (_v) ))
+#endif
+
+#if !defined( _mbg_get_unaligned )
+ #define _mbg_get_unaligned( _p ) (*(_p))
+#endif
+
+
+
+// If no macros to convert endianess have yet been defined, define
+// some default macros assuming endianess conversion is not required.
+
+#if !defined( __le16_to_cpu )
+ #define __le16_to_cpu( _x ) (_x)
+#endif
+
+#if !defined( __le32_to_cpu )
+ #define __le32_to_cpu( _x ) (_x)
+#endif
+
+#if !defined( __le64_to_cpu )
+ #define __le64_to_cpu( _x ) (_x)
+#endif
+
+#if !defined( __cpu_to_le16 )
+ #define __cpu_to_le16( _x ) (_x)
+#endif
+
+#if !defined( __cpu_to_le32 )
+ #define __cpu_to_le32( _x ) (_x)
+#endif
+
+#if !defined( __cpu_to_le64 )
+ #define __cpu_to_le64( _x ) (_x)
+#endif
+
+
+
+// The macros below are used to convert the endianess
+// of the plug-in cards to the endianess of the host CPU
+
+#define _mbg8_to_cpu( _x ) ( _x )
+#define _mbg16_to_cpu( _x ) __le16_to_cpu( _x )
+#define _mbg32_to_cpu( _x ) __le32_to_cpu( _x )
+#define _mbg64_to_cpu( _x ) __le64_to_cpu( _x )
+
+#define _cpu_to_mbg8( _x ) ( _x )
+#define _cpu_to_mbg16( _x ) __cpu_to_le16( _x )
+#define _cpu_to_mbg32( _x ) __cpu_to_le32( _x )
+#define _cpu_to_mbg64( _x ) __cpu_to_le64( _x )
+
+
+
+// swap a double type variable bytewise e.g. to convert the endianess
+
+static __mbg_inline
+void mbg_swab_double( double *p )
+{
+#if 0 // The __swab64() may not work correctly for whatever reason ...
+ __swab64p( p );
+#else // ... so we do the swapping manually
+ double d = 0;
+ size_t i;
+
+ for ( i = 0; i < sizeof( double); i++ )
+ BYTE_OF( d, i ) = BYTE_OF( *p, ( sizeof( double) - 1 - i ) );
+
+ for ( i = 0; i < sizeof( double); i++ )
+ BYTE_OF( *p, i ) = BYTE_OF( d, i );
+#endif
+
+} // mbg_swab_double
+
+
+
+#if defined( MBG_ARCH_BIG_ENDIAN )
+
+ #define _mbg_swab16( _p ) *(_p) = __swab16( *(_p) )
+ #define _mbg_swab32( _p ) *(_p) = __swab32( *(_p) )
+
+ #define _mbg_swab_double( _p ) mbg_swab_double( _p )
+
+ #define _mbg_swab_doubles( _p, _n ) \
+ { \
+ int i; \
+ for ( i = 0; i < (_n); i++ ) \
+ _mbg_swab_double( &_p[i] ); \
+ }
+
+#else
+
+ #define _mbg_swab16( _p ) _nop_macro_fnc()
+ #define _mbg_swab32( _p ) _nop_macro_fnc()
+
+ #define _mbg_swab_double( _p ) _nop_macro_fnc()
+
+ #define _mbg_swab_doubles( _p, _n ) _nop_macro_fnc()
+
+#endif
+
+#endif /* _MBG_ARCH_H */
diff --git a/mbglib/common/mbg_tgt.h b/mbglib/common/mbg_tgt.h
new file mode 100644
index 0000000..7970e57
--- /dev/null
+++ b/mbglib/common/mbg_tgt.h
@@ -0,0 +1,566 @@
+
+/**************************************************************************
+ *
+ * $Id: mbg_tgt.h 1.29 2013/02/01 14:50:46Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Check the build environment and setup control definitions
+ * for the Meinberg library modules.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbg_tgt.h $
+ * Revision 1.29 2013/02/01 14:50:46Z martin
+ * Fixed a typo which caused an error under Borland CBuilder 5.
+ * Revision 1.28 2012/12/12 10:03:16Z martin
+ * Fix for Borland C 3.1.
+ * Revision 1.27 2012/11/29 12:03:14Z martin
+ * Moved definition of _no_macro_fnc() to words.h.
+ * Revision 1.26 2012/11/02 09:01:47Z martin
+ * Merged some stuff depending on the build environment here
+ * and cleaned up.
+ * Revision 1.25 2012/04/04 07:17:18 martin
+ * Treat QNX Neutrino as Unix target.
+ * Revision 1.24 2011/08/23 10:21:23 martin
+ * New symbol _NO_MBG_API_ATTR which can be used with functions
+ * which are going to be exported by a DLL, but actually aren't, yet.
+ * Revision 1.23 2011/08/19 10:47:00 martin
+ * Don't include stddef.h.
+ * Distinguish between different gcc target platforms.
+ * Initial support for IA64 platform.
+ * Support wchar_t for BSD.
+ * Defined _NO_USE_PACK_INTF for Sparc and IA64.
+ * Fixed typo in comment.
+ * Revision 1.22 2009/10/01 08:20:50 martin
+ * Fixed inline code support with different BC versions.
+ * Revision 1.21 2009/09/01 10:34:23Z martin
+ * Don't define __mbg_inline for CVI and undefined targets.
+ * Revision 1.20 2009/08/18 15:14:26 martin
+ * Defined default MBG_INVALID_PORT_HANDLE for non-Windows targets.
+ * Revision 1.19 2009/06/09 10:03:58 daniel
+ * Preliminary support for ARM architecture.
+ * Revision 1.18 2009/04/01 14:10:55 martin
+ * Cleanup for CVI.
+ * Revision 1.17 2009/03/19 15:21:07Z martin
+ * Conditionally define DWORD_PTR type for old MS C compilers.
+ * Revision 1.16 2008/12/08 16:42:30 martin
+ * Defined _GNU_SOURCE for Linux.
+ * Revision 1.15 2008/11/19 15:31:49 martin
+ * Added symbol MBG_ARCH_I386.
+ * Revision 1.14 2008/09/03 15:06:04 martin
+ * Support DOS protected mode target.
+ * Support SUN SPARC architecture.
+ * Specified handle types for common host environments.
+ * Added macro MBG_USE_MM_IO_FOR_PCI.
+ * Added macro _nop_macro_fnc().
+ * Revision 1.13 2008/01/30 15:52:22 martin
+ * Modified checking for availability of wchar_t.
+ * Revision 1.13 2008/01/29 15:18:07Z martin
+ * Recognize DOS target under Watcom compilers.
+ * Flag Watcom C always supports wchar_t.
+ * Revision 1.12 2008/01/17 09:38:50Z daniel
+ * Added macros to determine whether C language extensions
+ * (e.g. C94, C99) are supported by the target environment.
+ * Added macro to check whether wchar_t and friends are
+ * supported, and some compatibility stuff.
+ * Revision 1.11 2007/10/31 16:58:03 martin
+ * Fixed __mbg_inline for Borland C (DOS).
+ * Revision 1.10 2007/09/25 08:10:27Z martin
+ * Support CVI target environment.
+ * Added MBG_PORT_HANDLE type for serial ports.
+ * Added macros for unified inline code syntax.
+ * Revision 1.9 2006/12/08 12:45:54Z martin
+ * Under Windows include ntddk.h rather than windows.h
+ * if building kernel driver .
+ * Revision 1.8 2006/10/25 12:20:45Z martin
+ * Initial support for FreeBSD, NetBSD, and OpenBSD.
+ * Added definitions for generic handle types.
+ * Revision 1.7 2006/08/23 13:43:55 martin
+ * Added definition for MBG_TGT_UNIX.
+ * Minor syntax fixes.
+ * Revision 1.6 2006/01/25 14:37:06 martin
+ * Added definitions for 64 bit Windows environments.
+ * Revision 1.5 2003/12/17 16:11:41Z martin
+ * Split API modifiers into _MBG_API and _MBG_API_ATTR.
+ * Revision 1.4 2003/06/19 08:20:22Z martin
+ * Added WINAPI attribute for DLL exported functions.
+ * Revision 1.3 2003/04/09 13:37:20Z martin
+ * Added definition for _MBG_API.
+ * Revision 1.2 2003/02/24 16:08:45Z martin
+ * Don't setup for Win32 PNP if explicitely configured non-PNP.
+ * Revision 1.1 2002/02/19 13:46:20Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _MBG_TGT_H
+#define _MBG_TGT_H
+
+
+/* Other headers to be included */
+
+#ifdef _MBG_TGT
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _CVI_ )
+
+ #define MBG_TGT_CVI
+
+ #if defined( _NI_mswin_ )
+ #define MBG_TGT_WIN32
+ #else
+ #error Unsupported CVI target platform.
+ #endif
+
+#elif defined( _WIN32_WINNT )
+
+ // MS platform SDK
+ // WinNT 4.0 and above
+ #define MBG_TGT_WIN32
+
+ #if ( _WIN32_WINNT >= 0x0500 )
+ // Win2k and above
+ #if !defined( MBG_TGT_WIN32_NON_PNP )
+ // only if not explicitely disabled
+ #define MBG_TGT_WIN32_PNP
+ #endif
+ #endif
+
+#elif defined( WINVER )
+
+ // MS platform SDK
+ // Win95, WinNT 4.0 and above
+ #define MBG_TGT_WIN32
+
+ #if ( WINVER >= 0x0500 )
+ // Win98, Win2k and above
+ // #define ...
+ #endif
+
+#elif defined( __WIN32__ )
+
+ // Borland C++ Builder
+ #define MBG_TGT_WIN32
+
+#elif defined( _WIN32 )
+
+ // MS Visual C++
+ #define MBG_TGT_WIN32
+
+#elif defined( __WINDOWS_386__ )
+
+ // Watcom C/C++ for target Win32
+ #define MBG_TGT_WIN32
+
+#elif defined( __NETWARE_386__ )
+
+ // Watcom C/C++ for target NetWare
+ #define MBG_TGT_NETWARE
+
+#elif defined( __OS2__ )
+
+ // Watcom C/C++ for target OS/2
+ #define MBG_TGT_OS2
+
+#elif defined( __linux )
+
+ // GCC for target Linux
+ #define MBG_TGT_LINUX
+ #define _GNU_SOURCE 1
+
+ #if defined( __KERNEL__ )
+ #define MBG_TGT_KERNEL
+ #endif
+
+#elif defined( __FreeBSD__ )
+
+ // GCC for target FreeBSD
+ #define MBG_TGT_FREEBSD
+
+#elif defined( __NetBSD__ )
+
+ // GCC for target NetBSD
+ #define MBG_TGT_NETBSD
+
+#elif defined( __OpenBSD__ )
+
+ // GCC for target OpenBSD
+ #define MBG_TGT_OPENBSD
+
+#elif defined( __QNX__ )
+
+ // any compiler for target QNX
+ #define MBG_TGT_QNX
+
+ #if defined( __QNXNTO__ )
+ // target QNX Neutrino
+ #define MBG_TGT_QNX_NTO
+ #endif
+
+#elif defined( __MSDOS__ ) || defined( __DOS__ )
+
+ // any compiler for target DOS
+ #define MBG_TGT_DOS
+
+ #if defined( __WATCOMC__ ) && defined( __386__ )
+
+ #define MBG_TGT_DOS_PM // protected mode DOS
+
+ #endif
+
+#endif
+
+
+
+#if defined( MBG_TGT_FREEBSD ) \
+ || defined( MBG_TGT_NETBSD ) \
+ || defined( MBG_TGT_OPENBSD )
+ #define MBG_TGT_BSD
+
+ #if defined( _KERNEL )
+ #define MBG_TGT_KERNEL
+ #endif
+
+#endif
+
+#if defined( MBG_TGT_LINUX ) \
+ || defined( MBG_TGT_BSD )
+ #define MBG_TGT_UNIX
+#endif
+
+
+
+// Some definitions depending on the build environment ...
+
+#if defined( __GNUC__ )
+
+ #if defined( __i386__ )
+
+ #define MBG_ARCH_I386
+ #define MBG_ARCH_X86
+
+ #elif defined( __x86_64__ )
+
+ #define MBG_ARCH_X86_64
+ #define MBG_ARCH_X86
+
+ #elif defined( __ia64__ )
+
+ #define MBG_ARCH_IA64
+
+ #define _NO_USE_PACK_INTF
+
+ #elif defined( __sparc__ )
+
+ #define MBG_ARCH_SPARC
+ #define MBG_USE_MM_IO_FOR_PCI 1
+
+ #define _NO_USE_PACK_INTF
+
+ #elif defined( __arm__ )
+
+ #define MBG_ARCH_ARM
+
+ #endif
+
+ #if defined( MBG_TGT_LINUX )
+
+ #if defined( __KERNEL__ )
+ #include <linux/types.h>
+ #else
+ #include <sys/types.h>
+ #include <stdint.h>
+ #include <stdbool.h>
+ #endif
+
+ #elif defined( MBG_TGT_BSD )
+
+ #include <sys/types.h>
+
+ #elif defined( MBG_TGT_QNX_NTO ) // QNX 6.x (Neutrino)
+
+ #include <stdint.h>
+ #include <stdbool.h>
+
+ #else
+
+ #include <stdint.h>
+ #include <stdbool.h>
+
+ #endif
+
+ #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1
+
+ #define MBG_TGT_HAS_WCHAR_T 1
+
+ #define __mbg_inline __inline__
+
+#elif defined( _MSC_VER )
+
+ // Known predifined MS compiler version codes:
+ // 1700: MSVC++ 11.0 (Visual Studio 2012)
+ // 1600: MSVC++ 10.0 (Visual Studio 2010)
+ // 1500: MSVC++ 9.0 (Visual Studio 2008)
+ // 1400: MSVC++ 8.0 (Visual Studio 2005)
+ // 1310: MSVC++ 7.1 (Visual Studio 2003)
+ // 1300: MSVC++ 7.0
+ // 1200: MSVC++ 6.0
+ // 1100: MSVC++ 5.0
+
+ #if ( _MSC_VER >= 1600 )
+ #include <stdint.h>
+ #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1
+ #else
+ #define MBG_TGT_HAS_INT_8_16_32 1
+ #endif
+
+ // no bool support anyway
+ #define MBG_TGT_MISSING_BOOL_TYPE 1
+
+ #define MBG_TGT_HAS_WCHAR_T 1
+
+ #define __mbg_inline __forceinline
+
+#elif defined( _CVI_ )
+
+ // 1000 for CVI v10.0 (CVI 2010)
+ // 911 for CVI v9.1.1 (CVI 2009 SP1)
+ // 910 for CVI v9.1 (CVI 2009)
+ // 310 for CVI v3.1
+ // 301 for CVI v3.0.1
+ // 1 for CVI v3.0
+
+ #if ( _CVI_ >= 910 )
+ // LabWindows/CVI 2009 is the first version providing stdint.h.
+ #include <stdint.h>
+ #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1
+ #else
+ #define USE_LONG_FOR_INT32 1
+ #endif
+
+ // As of LabWindows/CVI 2010, stdbool.h is still missing.
+ #define MBG_TGT_MISSING_BOOL_TYPE 1
+
+ #define MBG_TGT_HAS_WCHAR_T 0
+
+ // Inline code is not supported, though the inline keyword
+ // is silently accepted since CVI v9.0
+
+#elif defined( __BORLANDC__ )
+
+ // 0x0570 Borland Developer Studio 2006
+ // 0x0550 Borland C/C++ 5.5 (C++ Builder 5.0)
+ // 0x0410 Borland C/C++ 3.1
+ // 0x0400 Borland C/C++ 3.0
+ // 0x0200 Borland C/C++ 2.0
+
+ #if ( __BORLANDC__ >= 0x570 )
+ // at least Borland Developer Studio 2006 supports C99
+ #include <stdint.h>
+ #include <stdbool.h>
+ #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1
+ #elif ( __BORLANDC__ >= 0x0550 )
+ #define MBG_TGT_HAS_INT_8_16_32 1
+ #define MBG_TGT_MISSING_BOOL_TYPE 1
+ #else // e.g. BC 3.1 or earlier
+ #if ( __BORLANDC__ <= 0x410 )
+ #define MBG_TGT_MISSING_64_BIT_TYPES 1
+ #define MBG_TGT_MISSING_BOOL_TYPE 1
+ #define USE_LONG_FOR_INT32 1
+ #endif
+ #endif
+
+ #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 )
+
+ #if defined( __cplusplus )
+ #define __mbg_inline inline // standard C++ syntax
+ #elif ( __BORLANDC__ > 0x410 ) // BC3.1 defines 0x410 !
+ #define __mbg_inline __inline // newer BC versions support this for C
+ #else
+ #define __mbg_inline // up to BC3.1 not supported for C
+ #endif
+
+#elif defined( __WATCOMC__ )
+
+ // 1050 v10.5
+ // 1100 v11.0
+ // 1200 Open Watcom C++ v1.0
+ // 1230 Open Watcom C++ v1.3
+ // 1270 Open Watcom C++ v1.7
+
+ #if defined( MBG_TGT_QNX ) // QNX 4.x
+
+ #include <sys/types.h>
+
+ #define MBG_TGT_MISSING_64_BIT_TYPES 1
+
+ #elif ( __WATCOMC__ > 1230 ) // Open Watcom C 1.3 and above
+
+ #include <stdint.h>
+
+ #elif !defined( __WATCOM_INT64__ ) // Watcom C 11
+
+ #define MBG_TGT_MISSING_64_BIT_TYPES 1
+
+ #endif
+
+ #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 )
+
+ #define __mbg_inline _inline
+
+#endif
+
+
+
+#if defined( MBG_TGT_WIN32 )
+
+ #if defined( _AMD64_ )
+ // This is used for AMD64 architecture and for
+ // Intel XEON CPUs with 64 bit extension.
+ #define MBG_TGT_WIN32_PNP_X64
+ #define WIN32_FLAVOR "x64"
+ #elif defined( _IA64_ )
+ #define MBG_TGT_WIN32_PNP_IA64
+ #define WIN32_FLAVOR "ia64"
+ #endif
+
+ #if defined( _KDD_ )
+ #define MBG_TGT_KERNEL
+ #include <ntddk.h>
+ #else
+ // This must not be used for kernel drivers.
+ #include <windows.h>
+ typedef HANDLE MBG_HANDLE;
+
+ #define MBG_INVALID_HANDLE INVALID_HANDLE_VALUE
+
+ #if defined( MBG_TGT_CVI )
+ // CVI uses an own set of functions to support serial ports
+ typedef int MBG_PORT_HANDLE;
+ #define MBG_INVALID_PORT_HANDLE -1
+ #else
+ typedef HANDLE MBG_PORT_HANDLE;
+ #endif
+
+ // The DWORD_PTR type is not defined in the headers shipping
+ // with VC6. However, if the SDK is installed then the SDK's
+ // headers may declare this type. This is at least the case
+ // in the Oct 2001 SDK which also defines the symbol _W64.
+ #if !defined( _W64 )
+ typedef DWORD DWORD_PTR;
+ #endif
+
+ #endif
+
+ #define _MBG_API WINAPI
+
+ #if defined( MBG_LIB_EXPORT )
+ #define _MBG_API_ATTR __declspec( dllexport )
+ #else
+ #define _MBG_API_ATTR __declspec( dllimport )
+ #endif
+
+#elif defined( MBG_TGT_UNIX )
+
+ typedef int MBG_HANDLE;
+ typedef int MBG_PORT_HANDLE;
+
+ #define MBG_INVALID_HANDLE -1
+
+#else
+
+ typedef int MBG_HANDLE;
+ typedef int MBG_PORT_HANDLE;
+
+ #define MBG_INVALID_HANDLE -1
+
+#endif
+
+
+#if !defined( _MBG_API )
+ #define _MBG_API
+#endif
+
+#if !defined( _MBG_API_ATTR )
+ #define _MBG_API_ATTR
+#endif
+
+#if !defined( _NO_MBG_API_ATTR )
+ #define _NO_MBG_API_ATTR
+#endif
+
+#if !defined( MBG_INVALID_PORT_HANDLE )
+ #define MBG_INVALID_PORT_HANDLE MBG_INVALID_HANDLE
+#endif
+
+#if !defined( MBG_USE_MM_IO_FOR_PCI )
+ #define MBG_USE_MM_IO_FOR_PCI 0
+#endif
+
+
+// The macros below are defined in order to be able to check if
+// certain C language extensions are available on the target system:
+#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199409L )
+ #define MBG_TGT_C94 1
+#else
+ #define MBG_TGT_C94 0
+#endif
+
+
+#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L )
+ #define MBG_TGT_C99 1
+#else
+ #define MBG_TGT_C99 0
+#endif
+
+// Check if wchar_t is supported
+#if !defined( MBG_TGT_HAS_WCHAR_T )
+ #define MBG_TGT_HAS_WCHAR_T ( MBG_TGT_C94 || defined( WCHAR_MAX ) )
+#endif
+
+#if !MBG_TGT_HAS_WCHAR_T
+ // Even if wchar_t is not natively supported by the target platform
+ // there may already be a compatibility define (e.g. BC3.1)
+ // However, some functions may be missing (e.g. snwprintf()).
+ #if !defined( _WCHAR_T ) /* BC3.1 */ \
+ && !defined( _WCHAR_T_DEFINED_ ) /* WC11 */
+ #define _WCHAR_T
+ #define wchar_t char
+ #endif
+#endif
+
+
+
+/* End of header body */
+
+#undef _ext
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _MBG_TGT_H */
diff --git a/mbglib/common/mbgdevio.h b/mbglib/common/mbgdevio.h
new file mode 100644
index 0000000..40aeba5
--- /dev/null
+++ b/mbglib/common/mbgdevio.h
@@ -0,0 +1,3939 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgdevio.h 1.40 2012/10/02 18:40:30Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes used with Meinberg device driver I/O.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgdevio.h $
+ * Revision 1.40 2012/10/02 18:40:30Z martin
+ * There are some g++ versions which fail to compile source code using
+ * the macros provided by Linux to define IOCTL codes. If only the API
+ * functions are called by an application then the IOCTL codes aren't
+ * required anyway, so we just avoid inclusion of mbgioctl.h.
+ * Updated doxygen comments.
+ * Updated function prototypes.
+ * Support on-board event logs.
+ * Fixed a bug which caused a crash when generic I/O calls
+ * were used under Windows.
+ * Changes for QNX.
+ * Workaround to make mbgmon (BC) build under Windows.
+ * Cleaned up CPU set support under Linux.
+ * Moved some macros here so they can be used by other modules.
+ * Support reading CORR_INFO, and reading/writing TR_DISTANCE.
+ * Cleaned up handling of pragma pack().
+ * Cleaned up inclusion of header files.
+ * Moved mutex definitions to new mbgmutex.h.
+ * Renamed mutex stuff to critical sections.
+ * Updated function prototypes to support PTP unicast configuration
+ * Made xhrt leap second check an inline function.
+ * Fixed macro to avoid compiler warning.
+ * Revision 1.39 2009/12/15 15:34:59Z daniel
+ * Support reading the raw IRIG data bits for firmware versions
+ * which support this feature.
+ * Revision 1.38.1.2 2009/12/10 09:58:53Z daniel
+ * Revision 1.38.1.1 2009/12/10 09:45:29Z daniel
+ * Revision 1.38 2009/09/29 15:06:26Z martin
+ * Updated function prototypes.
+ * Revision 1.37 2009/08/12 14:31:51 daniel
+ * New version code 306, compatibility version still 210.
+ * Revision 1.36 2009/06/19 12:20:31Z martin
+ * Updated function prototypes.
+ * Revision 1.35 2009/06/09 08:57:09 daniel
+ * New version code 305, compatibility version still 210.
+ * Revision 1.34 2009/06/08 18:20:14Z daniel
+ * Updated function prototypes.
+ * Fixes for ARM target.
+ * Revision 1.33 2009/03/19 15:36:26 martin
+ * New version code 304, compatibility version still 210.
+ * Moved some inline functions dealing with MBG_PC_CYCLES
+ * from mbgdevio.h to pcpsdev.h.
+ * Include mbg_arch.h here.
+ * Removed unused doxygen comment.
+ * Updated function prototypes.
+ * Revision 1.32 2008/12/17 10:43:30Z martin
+ * New version code 303, compatibility version still 210.
+ * Increased MBG_MAX_DEVICES from 5 to 8.
+ * Added macros to read the time stamp counter (cycles), and
+ * added an inline rdtscll() call for user space Linux.
+ * Added some inline functions to deal with cycles and timestamps.
+ * Generic support for threads and process/thread affinity controlled
+ * by symbol MBGDEVIO_USE_THREAD_API.
+ * New preprocessor symbol MBGDEVIO_HAVE_THREAD_AFFINITY.
+ * Support extrapolated time stamps controlled
+ * by symbol MBGDEVIO_XHRT_API.
+ * Removed definition of MBG_TGT_SUPP_MMAP.
+ * Updated function prototypes and doxygen comments.
+ * Revision 1.31 2008/02/26 16:57:38Z martin
+ * Updated function prototypes and doxygen comments.
+ * Revision 1.30 2008/02/04 13:33:15Z martin
+ * New preprocessor symbol MBG_TGT_SUPP_MMAP.
+ * Revision 1.29 2008/01/31 08:55:39Z daniel
+ * Renamed functions related to mapped memory support
+ * Revision 1.28 2008/01/31 08:36:22Z martin
+ * Picked up changes from 1.24.1.1:
+ * Added default preprocessor symbol MBGDEVIO_SIMPLE.
+ * Revision 1.27 2008/01/17 15:56:37Z daniel
+ * New version code 302, compatibility version still 210.
+ * Added structure MBG_MAPPED_MEM_INFO.
+ * Updated function prototypes.
+ * Revision 1.26 2007/10/16 10:11:42Z daniel
+ * New version code 301, compatibility version still 210.
+ * Revision 1.25 2007/09/26 14:10:34Z martin
+ * New version code 300, compatibility version still 210.
+ * Added MBG_MAX_DEVICES.
+ * Added enum SELECTION_MODE.
+ * Added structures MBG_DEVICE_LIST and MBG_DEVICE_NAME_LIST.
+ * Updated function prototypes.
+ * Revision 1.24 2007/03/22 10:14:16Z martin
+ * New version code 219, compatibility version still 210.
+ * Revision 1.23 2007/03/02 10:18:10Z martin
+ * Updated function prototypes due to renamed data structures.
+ * Use new definitions of generic handle types.
+ * Preliminary support for *BSD.
+ * Revision 1.22 2006/08/09 13:47:29 martin
+ * New version code 218, compatibility version still 210.
+ * Revision 1.21 2006/06/08 12:30:22Z martin
+ * New version code 217, compatibility version still 210.
+ * Revision 1.20 2006/05/02 13:14:27Z martin
+ * New version code 216, compatibility version still 210.
+ * Updated function prototypes.
+ * Revision 1.19 2006/01/11 12:14:53Z martin
+ * New version code 215, compatibility version still 210.
+ * Revision 1.18 2005/12/15 09:38:39Z martin
+ * New version 214, compatibility version still 210.
+ * Revision 1.17 2005/06/02 11:54:40Z martin
+ * Updated function prototypes.
+ * Revision 1.16 2005/02/16 15:13:00Z martin
+ * New MBGDEVIO_VERSION 0x0212.
+ * Updated function prototypes.
+ * Revision 1.15 2005/01/14 10:22:44Z martin
+ * Updated function prototypes.
+ * Revision 1.14 2004/12/09 11:24:00Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.13 2004/11/09 14:13:00Z martin
+ * Updated function prototypes.
+ * Revision 1.12 2004/08/17 11:13:46Z martin
+ * Account for renamed symbols.
+ * Revision 1.11 2004/04/14 09:34:23Z martin
+ * New definition MBGDEVIO_COMPAT_VERSION.
+ * Pack structures 1 byte aligned.
+ * Revision 1.10 2003/12/22 15:35:10Z martin
+ * New revision 2.03.
+ * Moved some definitions to pcpsdev.h.
+ * New structures to read device time together with associated
+ * PC high resolution timer cycles.
+ * Updated function prototypes.
+ * Revision 1.9 2003/06/19 08:50:05Z martin
+ * Definition of MBGDEVIO_VERSION number to allow DLL
+ * API version checking.
+ * Replaced some defines by typedefs.
+ * Renamed USE_DOS_TSR to MBG_USE_DOS_TSR.
+ * New preprocessor symbol MBG_USE_KERNEL_DRIVER which
+ * is defined only for targets which use IOCTLs.
+ * Don't include pcps_dos.h here.
+ * Updated function prototypes.
+ * Revision 1.8 2003/05/16 08:44:26 MARTIN
+ * Cleaned up inclusion of headers.
+ * Removed obsolete definitions.
+ * Changes for direct access targets.
+ * Revision 1.7 2003/04/25 10:16:00 martin
+ * Updated inclusion of headers.
+ * Made prototypes available for all targets.
+ * Revision 1.6 2003/04/15 19:38:05Z martin
+ * Updated function prototypes.
+ * Revision 1.5 2003/04/09 13:44:53Z martin
+ * Use new common IOCTL codes from mbgioctl.h.
+ * Updated function prototypes.
+ * Revision 1.4 2002/09/06 11:06:35Z martin
+ * Updated function prototypes for Win32 API..
+ * Win32 compatibility macros to use old APIs with new functions.
+ * Support targets OS/2 and NetWare.
+ * Revision 1.3 2002/02/28 10:08:54Z MARTIN
+ * Syntax cleanup for Win32.
+ * Revision 1.2 2002/02/26 14:40:47 MARTIN
+ * Source code cleanup.
+ * Changes for DOS with and without TSR.
+ * Revision 1.1 2002/02/19 13:48:21 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _MBGDEVIO_H
+#define _MBGDEVIO_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+#include <mbg_arch.h>
+#include <mbgmutex.h>
+#include <mbgerror.h>
+#include <mbggeo.h>
+#include <pcpsdev.h>
+#include <pci_asic.h>
+#include <use_pack.h>
+#include <time.h>
+
+
+#define MBGDEVIO_VERSION 0x0307
+
+#define MBGDEVIO_COMPAT_VERSION 0x0210
+
+#define MBG_MAX_DEVICES 8
+
+#if defined( MBG_TGT_WIN32 )
+
+ #if !defined( MBGDEVIO_XHRT_API )
+ #define MBGDEVIO_XHRT_API 1
+ #endif
+
+ #if !defined( MBGDEVIO_USE_THREAD_API )
+ #define MBGDEVIO_USE_THREAD_API 1
+ #endif
+
+ #if !defined( MBGDEVIO_HAVE_THREAD_AFFINITY )
+ #define MBGDEVIO_HAVE_THREAD_AFFINITY 1
+ #endif
+
+ #define MBG_USE_KERNEL_DRIVER 1
+ #include <windows.h>
+
+ #define MBGDEVIO_RET_VAL DWORD
+ #define _mbgdevio_cnv_ret_val( _v ) (_v)
+
+#elif defined( MBG_TGT_LINUX )
+
+ #if !defined( MBGDEVIO_XHRT_API )
+ #define MBGDEVIO_XHRT_API 1
+ #endif
+
+ // Thread support under Linux depends strongly on
+ // the versions of some libraries, so the symbols
+ // MBGDEVIO_USE_THREAD_API and MBGDEVIO_HAVE_THREAD_AFFINITY
+ // should be set in the project's Makefile, depending on the
+ // target envionment. Otherwise thread support is disabled
+ // as per default.
+
+ #define MBG_USE_KERNEL_DRIVER 1
+ #include <sys/ioctl.h>
+ #include <fcntl.h>
+ #include <sched.h>
+
+ #if MBGDEVIO_USE_THREAD_API
+ #include <pthread.h>
+ #endif
+
+#elif defined( MBG_TGT_BSD )
+
+ #define MBG_USE_KERNEL_DRIVER 1
+ #include <sys/ioctl.h>
+ #include <fcntl.h>
+
+#elif defined( MBG_TGT_OS2 )
+
+ #define MBG_USE_KERNEL_DRIVER 1
+
+#elif defined( MBG_TGT_QNX_NTO )
+
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+
+ #include <pcpsdrvr.h>
+
+#elif defined( MBG_TGT_DOS )
+
+ #if !defined( MBG_USE_DOS_TSR )
+ #define MBG_USE_DOS_TSR 1
+ #endif
+
+ #include <pcpsdrvr.h>
+
+#else // other target OSs which access the hardware directly
+
+ #include <pcpsdrvr.h>
+
+#endif
+
+
+#if defined( MBG_USE_KERNEL_DRIVER )
+
+ #include <stdlib.h>
+ #include <string.h>
+
+#endif
+
+
+#if !defined( MBGDEVIO_XHRT_API )
+ #define MBGDEVIO_XHRT_API 0
+#endif
+
+#if !defined( MBGDEVIO_USE_THREAD_API )
+ #define MBGDEVIO_USE_THREAD_API 0
+#endif
+
+#if !defined( MBGDEVIO_HAVE_THREAD_AFFINITY )
+ #define MBGDEVIO_HAVE_THREAD_AFFINITY 0
+#endif
+
+#ifdef _MBGDEVIO
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+
+// If MBGDEVIO_SIMPLE != 0 then some complex configuration
+// API calls are excluded from build, which would otherwise
+// require some additional mbglib modules to be linked
+// to the application.
+#if !defined( MBGDEVIO_SIMPLE )
+ #define MBGDEVIO_SIMPLE 0
+#endif
+
+
+#if defined( MBG_USE_KERNEL_DRIVER )
+
+ typedef MBG_HANDLE MBG_DEV_HANDLE;
+
+ #define MBG_INVALID_DEV_HANDLE MBG_INVALID_HANDLE
+
+#else // other target OSs which access the hardware directly
+
+ typedef PCPS_DDEV *MBG_DEV_HANDLE;
+
+ #define MBG_INVALID_DEV_HANDLE NULL
+
+#endif
+
+
+#if !defined( MBGDEVIO_RET_VAL )
+ #define MBGDEVIO_RET_VAL int
+#endif
+
+
+#if !defined( _mbgdevio_cnv_ret_val )
+ #define _mbgdevio_cnv_ret_val( _v ) \
+ ( ( (_v) < 0 ) ? (_v) : MBG_SUCCESS )
+#endif
+
+
+#define _mbgdevio_vars() \
+ MBGDEVIO_RET_VAL rc
+
+#define _mbgdevio_ret_val \
+ _mbgdevio_cnv_ret_val( rc )
+
+
+
+/**
+ The type below is used to store a unique ID for a device which
+ is made up of the device model name and its serial number, i.e.:
+ Format: [model_name]_[serial_number], e.g. "GPS170PCI_028210040670"
+ */
+typedef char MBG_HW_NAME[PCPS_CLOCK_NAME_SZ + PCPS_SN_SIZE + 1];
+
+
+
+#if defined( MBG_TGT_LINUX )
+
+ #define MBG_PROCESS_ID pid_t
+ #define _mbg_get_current_process() 0
+
+ #if defined( __cpu_set_t_defined )
+ #define MBG_CPU_SET cpu_set_t
+ #define MBG_CPU_SET_SIZE CPU_SETSIZE
+ #define _mbg_cpu_clear( _ps ) CPU_ZERO( (_ps) )
+ #define _mbg_cpu_set( _i, _ps ) CPU_SET( (_i), (_ps) )
+ #define _mbg_cpu_isset( _i, _ps ) CPU_ISSET( (_i), (_ps) )
+ #endif
+
+ #if MBGDEVIO_USE_THREAD_API
+ #define MBG_THREAD_ID pthread_t
+ #define _mbg_get_current_thread() 0
+ #define MBG_THREAD_FNC_ATTR // empty
+ #define MBG_THREAD_FNC_RET_VAL void *
+ #define _mbg_thread_exit( _v ) return (void *) (_v)
+ #endif
+
+#elif defined( MBG_TGT_WIN32 )
+
+ #define MBG_PROCESS_ID HANDLE
+ #define _mbg_get_current_process() GetCurrentProcess()
+
+ #define MBG_CPU_SET DWORD_PTR // Attention: this is not used as pointer!
+ #define MBG_CPU_SET_SIZE ( sizeof( MBG_CPU_SET ) * 8 )
+
+ #define MBG_THREAD_ID HANDLE
+ #define _mbg_get_current_thread() GetCurrentThread()
+ #define MBG_THREAD_FNC_ATTR WINAPI
+ #define MBG_THREAD_FNC_RET_VAL DWORD
+ #define _mbg_thread_exit( _v ) ExitThread( _v ); return (_v)
+
+#endif // target specific
+
+
+#if !defined( MBG_TGT_WIN32 )
+
+ #define FILETIME int // just a dummy to avoid build errors
+
+#endif
+
+
+#if !defined( MBG_PROCESS_ID )
+ #define MBG_PROCESS_ID int
+#endif
+
+#if !defined( _mbg_get_current_process )
+ #define _mbg_get_current_process() 0
+#endif
+
+#if !defined( MBG_CPU_SET )
+ #define MBG_CPU_SET int
+#endif
+
+#if !defined( MBG_CPU_SET_SIZE )
+ #define MBG_CPU_SET_SIZE ( sizeof( MBG_CPU_SET ) * 8 )
+#endif
+
+#if !defined( _mbg_cpu_clear )
+ #define _mbg_cpu_clear( _ps ) ( *(_ps) = 0 )
+#endif
+
+#if !defined( _mbg_cpu_set )
+ #define _mbg_cpu_set( _i, _ps ) ( *(_ps) |= ( 1UL << (_i) ) )
+#endif
+
+#if !defined( _mbg_cpu_isset )
+ #define _mbg_cpu_isset( _i, _ps ) ( *(_ps) & ( 1UL << (_i) ) )
+#endif
+
+
+#if !defined( MBG_THREAD_ID )
+ #define MBG_THREAD_ID int
+#endif
+
+#if !defined( _mbg_get_current_thread )
+ #define _mbg_get_current_thread() 0
+#endif
+
+#if !defined( MBG_THREAD_FNC_ATTR )
+ #define MBG_THREAD_FNC_ATTR // empty
+#endif
+
+#if !defined( MBG_THREAD_FNC_RET_VAL )
+ #define MBG_THREAD_FNC_RET_VAL void
+#endif
+
+#if !defined( _mbg_thread_exit )
+ #define _mbg_thread_exit( _v ) _nop_macro_fnc()
+#endif
+
+
+typedef struct
+{
+ MBG_THREAD_ID thread_id;
+ #if defined( MBG_TGT_WIN32 )
+ HANDLE exit_request;
+ #endif
+} MBG_THREAD_INFO;
+
+
+
+typedef struct
+{
+ PCPS_HR_TIME_CYCLES htc;
+ uint64_t pcps_hr_tstamp64;
+} MBG_XHRT_VARS;
+
+
+typedef struct
+{
+ MBG_XHRT_VARS vars;
+ MBG_XHRT_VARS prv_vars;
+ MBG_PC_CYCLES_FREQUENCY freq_hz;
+ int ioctl_status;
+ int sleep_ms;
+ MBG_CRIT_SECT crit_sect;
+ MBG_DEV_HANDLE dh;
+} MBG_XHRT_INFO;
+
+
+typedef struct
+{
+ MBG_XHRT_INFO xhrt_info;
+ MBG_THREAD_INFO ti;
+} MBG_POLL_THREAD_INFO;
+
+
+
+/**
+ Match modes to decide how to proceed if a certain
+ model type with certain serial number can not be found
+ */
+enum MBG_MATCH_MODE
+{
+ MBG_MATCH_ANY, /**< open the next available device on the system */
+ MBG_MATCH_MODEL, /**< open the next available device on the system with the same clock type */
+ MBG_MATCH_EXACTLY, /**< force opening exactly the requested device otherwise exit with failure */
+ N_MBG_MATCH_MODE /**< number of known modes */
+};
+
+
+
+typedef struct _MBG_DEVICE_LIST
+{
+ char *device_path; /**< Hardware ID depending on the calling function */
+ struct _MBG_DEVICE_LIST *next;
+
+} MBG_DEVICE_LIST;
+
+
+
+typedef struct _MBG_DEVICENAME_LIST
+{
+ char device_name[40]; /**< readable name */
+ struct _MBG_DEVICENAME_LIST *next;
+
+} MBG_DEVICENAME_LIST;
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ /**
+ Get the version number of the precompiled DLL/shared object library.
+
+ If this library is used as a DLL/shared object library then the version
+ number can be checked to see if the header files which are actually used
+ to build an application are compatible with the header files which have
+ been used to build the library, and thus the API function are called
+ in the correct way.
+
+ @return the version number
+
+ @see mbgdevio_check_version()
+ @see ::MBGDEVIO_VERSION defined in mbgdevio.h
+ */
+ _MBG_API_ATTR int _MBG_API mbgdevio_get_version( void ) ;
+
+ /**
+ @brief Check if the DLL/shared library is compatible with a given version.
+
+ If this library is used as a DLL/shared object library then the version
+ number can be checked to see if the header files which are actually used
+ to build an application are compatible with the header files which have
+ been used to build the library, and thus the API function are called
+ in the correct way.
+
+ @param header_version Version number to be checked, should be ::MBGDEVIO_VERSION
+ from the mbgdevio.h file used to build the application
+
+ @return ::MBG_SUCCESS if compatible, ::MBG_ERR_LIB_NOT_COMPATIBLE if not.
+
+ @see mbgdevio_get_version()
+ @see ::MBGDEVIO_VERSION defined in mbgdevio.h
+ */
+ _MBG_API_ATTR int _MBG_API mbgdevio_check_version( int header_version ) ;
+
+ /**
+ @brief Open a device by index, starting from 0.
+
+ This function is <b>out of date</b>, mbg_open_device_by_name()
+ should be used instead.
+
+ See the <b>note</b> for mbg_find_device() for details.
+
+ @param device_index index of the device, use 0 for the first device.
+ */
+ _MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device( unsigned int device_index ) ;
+
+ /**
+ @brief Get the number of supported devices installed on the computer.
+
+ This function is <b>out of date</b>, mbg_find_devices_with_names()
+ should be used instead.
+
+ <b>Note:</b> This function is out of date since it may not work
+ correctly for Meinberg devices which are disconnected and reconnected
+ while the system is running (e.g. USB devices). However, the function
+ will be kept for compatibility reasons and works correctly if all
+ Meinberg devices are connected at system boot and are not disconnected
+ and reconnected during operation
+
+ @return The number of devices found
+
+ @see mbg_find_devices_with_names()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_find_devices( void ) ;
+
+ /**
+ @brief Allocate memory and set up a list of installed and supported devices.
+
+ This function should be used preferably instead of mbg_find_devices().
+
+ @param device_list Pointer to a linked list of type ::MBG_DEVICENAME_LIST
+ with device names. The list will be allocated by this
+ function and has to be freed after usage by calling
+ mbg_free_device_name_list().
+ @param max_devices Maximum number of devices the function should look for
+ (can not exceed ::MBG_MAX_DEVICES).
+
+ @return number of present devices
+
+ @see ::MBG_HW_NAME for the format of the unique names
+ @see mbg_free_device_name_list()
+ @see mbg_find_devices()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_find_devices_with_names( MBG_DEVICENAME_LIST **device_list, int max_devices ) ;
+
+ /**
+ @brief Free the memory allocated for a ::MBG_DEVICENAME_LIST.
+
+ The list may have been set up and allocated before
+ by mbg_find_devices_with_names().
+
+ @param *list Linked list of type ::MBG_DEVICENAME_LIST
+
+ @see mbg_find_devices_with_names()
+ */
+ _MBG_API_ATTR void _MBG_API mbg_free_device_name_list( MBG_DEVICENAME_LIST *list) ;
+
+ /**
+ @brief Return a handle to a device with a certain unique name.
+
+ The names of the devices that are installed on the system can be retrieved by
+ the function mbg_find_devices_with_names().
+
+ This function should be used preferably instead of mbg_open_device().
+
+ @param hw_name String with the unique name of the device to be opened
+ @param selection_mode One of the enum values of ::MBG_MATCH_MODE
+
+ @return On success, the function returns a handle to the device, otherwise ::MBG_INVALID_DEV_HANDLE
+
+ @see ::MBG_HW_NAME for the format of the unique names.
+ @see ::MBG_MATCH_MODE
+ @see mbg_find_devices_with_names()
+ */
+ _MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_name( const char* hw_name, int selection_mode ) //##++++
+;
+
+ /**
+ @brief Close a handle to a device and set the handle value to ::MBG_INVALID_DEV_HANDLE.
+
+ @param dev_handle Handle to a Meinberg device.
+ */
+ _MBG_API_ATTR void _MBG_API mbg_close_device( MBG_DEV_HANDLE *dev_handle ) ;
+
+ /**
+ @brief Read information about the driver handling a given device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_DRVR_INFO structure which is filled up.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_drvr_info( MBG_DEV_HANDLE dh, PCPS_DRVR_INFO *p ) ;
+
+ /**
+ @brief Read detailed device information.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_DEV structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_device_info( MBG_DEV_HANDLE dh, PCPS_DEV *p ) ;
+
+ /**
+ @brief Read the current state of the on-board ::PCPS_STATUS_PORT.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_STATUS_PORT value to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+
+ @see \ref group_status_port "bitmask"
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_status_port( MBG_DEV_HANDLE dh, PCPS_STATUS_PORT *p ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Generic read function which writes a command code to a device
+ and reads a number of replied data to a generic buffer.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device
+ @param *p Pointer to a buffer to be filled up
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_generic_write()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_write_gps()
+ @see mbg_generic_io()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_generic_read( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Generic read function which writes a GPS command code to a device
+ and reads a number of replied data to a generic buffer.
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a device.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any GPS command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device.
+ @param *p Pointer to a buffer to be filled up
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_gps_data()
+ @see mbg_generic_write_gps()
+ @see mbg_generic_read()
+ @see mbg_generic_write()
+ @see mbg_generic_io()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_generic_read_gps( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Generic write function which writes a command code plus an
+ associated number of data bytes to a device.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device.
+ @param *p Pointer to a buffer to be written
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_generic_read()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_write_gps()
+ @see mbg_generic_io()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_generic_write( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Generic write function which writes a GPS command code plus an
+ associated number of data bytes to a device.
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a device.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any GPS command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device.
+ @param *p Pointer to a buffer to be written
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_gps_data()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_read()
+ @see mbg_generic_write()
+ @see mbg_generic_io()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_generic_write_gps( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Write and/or read generic data to/from a device.
+ The macro _pcps_has_generic_io() or the API call mbg_dev_has_generic_io()
+ check whether this call is supported by a device.
+
+ <b>Warning</b>: This call is for debugging purposes and internal use only!
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_generic_io()
+ @see mbg_generic_read()
+ @see mbg_generic_write()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_write_gps()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_generic_io( MBG_DEV_HANDLE dh, int type, const void *in_p, int in_sz, void *out_p, int out_sz ) ;
+
+ /**
+ @brief Read a ::PCPS_TIME structure returning the current date/time/status.
+
+ The returned time is local time according to the card's time zone setting,
+ with a resolution of 10 ms (i.e. 10ths of seconds).
+
+ This call is supported by any device manufactured by Meinberg.
+ However, for higher accuracy and resolution the mbg_get_hr_time..() or
+ mbg_get_fast_hr_timestamp..() group of calls should be used preferably
+ if supported by the device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time()
+ @see mbg_set_time()
+ @see mbg_get_sync_time()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ;
+
+ /**
+ @brief Set the device's on-board clock to a given date and time.
+
+ The macro _pcps_can_set_time() checks whether this call
+ is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_STIME structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_time( MBG_DEV_HANDLE dh, const PCPS_STIME *p ) ;
+
+ /**
+ @brief Read the time when the device has last recently synchronized.
+
+ Fills a ::PCPS_TIME structure with the date/time/status reporting
+ when the device was synchronized the last time to its time source,
+ e.g. the DCF77 signal, the GPS satellites, or similar.
+ The macro _pcps_has_sync_time() or the API call mbg_dev_has_sync_time()
+ check whether this call is supported by a device.
+
+ The macro _pcps_has_sync_time() checks whether this call
+ is supported by a device.
+
+ <b>Note:</b> If that information is not available on the board then
+ the value of the returned ::PCPS_TIME::sec field is set to 0xFF.
+ The macro _pcps_time_is_read() can be used to check whether the
+ returned information is valid, or not available.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_sync_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ;
+
+ /**
+ @brief Wait until the next second change, then return current time.
+
+ Returns time in a ::PCPS_TIME structure similar to mbg_get_time().
+
+ <b>Note:</b> This API call is supported under Windows only.
+ The call blocks until the kernel driver detects a second change
+ reported by the device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_time_sec_change( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ;
+
+ /**
+ @brief Read the card's current time with high resolution, plus status.
+
+ Fills up a ::PCPS_HR_TIME (High Resolution time) structure containing
+ the current %UTC time (seconds since 1970), %UTC offset, and status.
+ The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> This API call provides a higher accuracy and resolution
+ than mbg_get_time(). However, it does not account for the latency
+ which is introduced when accessing the board.
+ The mbg_get_hr_time_cycles() and mbg_get_hr_time_comp() calls
+ provide ways to account for and/or compensate the latency.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_hr_time()
+ @see mbg_get_time()
+ @see mbg_get_hr_time_cycles()
+ @see mbg_get_hr_time_comp()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_hr_time( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) ;
+
+ /* (Intentionally excluded from Doxygen )
+ Write a high resolution time stamp ::PCPS_TIME_STAMP to a device
+ to configure a %UTC time when the clock shall generate an event.
+ The macro _pcps_has_event_time() or the API call mbg_dev_has_event_time()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> This is only supported by some special firmware.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_event_time()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_event_time( MBG_DEV_HANDLE dh, const PCPS_TIME_STAMP *p ) ;
+
+ /**
+ @brief Read the serial port configuration from an old type of device.
+
+ <b>Note:</b> Direct usage of this function is obsolete.
+
+ The generic API function mbg_get_serial_settings() should be used instead
+ which fully supports the capabilities of current devices.
+
+ The macro _pcps_has_serial() checks whether this call
+ is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_SERIAL structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see \ref group_cmd_bytes
+ @see mbg_get_serial_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_serial( MBG_DEV_HANDLE dh, PCPS_SERIAL *p ) ;
+
+ /**
+ @brief Write the serial port configuration to an old type of device.
+
+ <b>Note:</b> Direct usage of this function is obsolete.
+
+ The generic API function mbg_save_serial_settings() should be used instead
+ which fully supports the capabilities of current devices.
+
+ The macro _pcps_has_serial() checks whether this call
+ is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_SERIAL structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see \ref group_cmd_bytes
+ @see mbg_save_serial_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_serial( MBG_DEV_HANDLE dh, const PCPS_SERIAL *p ) ;
+
+ /**
+ @brief Read time zone/daylight saving configuration code from a device.
+
+ The APIs using TZCODE are only supported by some simpler cards
+ and allow just a very basic configuration.
+
+ The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode()
+ check whether this call is supported by a device.
+
+ Other cards may support the mbg_get_pcps_tzdl() or mbg_get_gps_tzdl()
+ calls instead which allow for a more detailed configuration of the
+ time zone and daylight saving settings.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZCODE structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzcode()
+ @see mbg_set_tzcode()
+ @see mbg_get_pcps_tzdl()
+ @see mbg_get_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_tzcode( MBG_DEV_HANDLE dh, PCPS_TZCODE *p ) ;
+
+ /**
+ @brief Write time zone/daylight saving configuration code to a device.
+
+ The APIs using TZCODE are only supported by some simpler cards
+ and allow just a very basic configuration.
+
+ The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode()
+ check whether this call is supported by a device.
+
+ Other cards may support the mbg_set_pcps_tzdl() or mbg_set_gps_tzdl()
+ calls instead which allow for a more detailed configuration of the
+ time zone and daylight saving settings.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZCODE structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzcode()
+ @see mbg_get_tzcode()
+ @see mbg_set_pcps_tzdl()
+ @see mbg_set_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_tzcode( MBG_DEV_HANDLE dh, const PCPS_TZCODE *p ) ;
+
+ /**
+ @brief Read time zone/daylight saving parameters from a device.
+
+ This function fills up a ::PCPS_TZDL structure which supports a more
+ detailed configuration of time zone and daylight saving than the TZCODE
+ structure.
+
+ The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl()
+ check whether this call is supported by a device.
+
+ Other cards may support the mbg_get_tzcode() or mbg_get_gps_tzdl()
+ calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZDL structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pcps_tzdl()
+ @see mbg_set_pcps_tzdl()
+ @see mbg_get_tzcode()
+ @see mbg_get_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_pcps_tzdl( MBG_DEV_HANDLE dh, PCPS_TZDL *p ) ;
+
+ /**
+ @brief Write time zone/daylight saving parameters to a device.
+
+ This function passes a ::PCPS_TZDL structure to a device which supports
+ a more detailed configuration of time zone and daylight saving than the
+ TZCODE structure.
+
+ The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl()
+ check whether this call is supported by a device.
+ Other cards may support the mbg_set_tzcode() or mbg_set_gps_tzdl()
+ calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZDL structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pcps_tzdl()
+ @see mbg_get_pcps_tzdl()
+ @see mbg_set_tzcode()
+ @see mbg_set_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_pcps_tzdl( MBG_DEV_HANDLE dh, const PCPS_TZDL *p ) ;
+
+ /**
+ @brief Read the %UTC offset configuration of the reference time from a device.
+
+ This parameter is used to specify the %UTC offset of an incoming
+ reference time signal if a kind of time signal e.g. an IRIG input
+ signal) does not provide this information.
+
+ The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_REF_OFFS value to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ref_offs()
+ @see mbg_set_ref_offs()
+ @see ::PCPS_GET_REF_OFFS
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ref_offs( MBG_DEV_HANDLE dh, MBG_REF_OFFS *p ) ;
+
+ /**
+ @brief Write the %UTC offset configuration of the reference time to a device.
+
+ This parameter is used to specify the %UTC offset of an incoming
+ reference time signal if a kind of time signal e.g. an IRIG input
+ signal) does not provide this information.
+
+ The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_REF_OFFS value to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ref_offs()
+ @see mbg_get_ref_offs()
+ @see ::PCPS_SET_REF_OFFS
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_ref_offs( MBG_DEV_HANDLE dh, const MBG_REF_OFFS *p ) ;
+
+ /**
+ @brief Read a ::MBG_OPT_INFO structure containing optional settings, controlled by flags.
+
+ The ::MBG_OPT_INFO structure contains a mask of supported flags plus the current
+ settings of those flags.
+ The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_OPT_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_opt_flags()
+ @see mbg_set_opt_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_opt_info( MBG_DEV_HANDLE dh, MBG_OPT_INFO *p ) ;
+
+ /**
+ @brief Write a ::MBG_OPT_SETTINGS structure containing optional device settings.
+
+ The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags()
+ check whether this call is supported by a device.
+ The ::MBG_OPT_INFO structure should be read first to check which of the specified
+ flag is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_OPT_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_opt_flags()
+ @see mbg_get_opt_info()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_opt_settings( MBG_DEV_HANDLE dh, const MBG_OPT_SETTINGS *p ) ;
+
+ /**
+ @brief Read the current IRIG input settings plus the supported settings.
+
+ Calling this function directly is usually obsolete. The function
+ mbg_get_all_irig_rx_info() should be used instead which also reads some
+ other associated parameters affecting the behaviour of the IRIG input.
+
+ The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an ::IRIG_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_all_irig_rx_info()
+ @see mbg_set_irig_rx_settings()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_irig_rx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) ;
+
+ /**
+ @brief Write an ::IRIG_SETTINGS structure to a device to configure an IRIG input.
+
+ Calling this function directly is usually obsolete. The function
+ mbg_set_all_irig_rx_info() should be used instead which also writes some
+ other associated parameters affecting the behaviour of the IRIG input.
+
+ The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx()
+ check whether this call is supported by a device.
+ The ::IRIG_INFO structure should be read first to determine the possible
+ settings supported by this card's IRIG input.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::IRIG_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_all_irig_rx_info()
+ @see mbg_get_irig_rx_info()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_irig_rx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) ;
+
+ /**
+ @brief Read all IRIG input configuration information from a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param pdev Pointer to the device's ::PCPS_DEV structure
+ @param p_irig_info Pointer to a ::IRIG_SETTINGS structure to be written
+ @param p_ref_offs Pointer to a ::MBG_REF_OFFS structure to be written
+ @param p_opt_info Pointer to a ::MBG_OPT_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_all_irig_rx_settings()
+ @see mbg_set_irig_rx_settings()
+ @see mbg_set_ref_offs()
+ @see mbg_set_opt_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_all_irig_rx_info( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, IRIG_INFO *p_irig_info, MBG_REF_OFFS *p_ref_offs, MBG_OPT_INFO *p_opt_info ) ;
+
+ /**
+ @brief Write all IRIG input configuration settings to a device.
+
+ The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx()
+ check whether this call is supported by a device.
+ The ::IRIG_INFO structure should be read first to determine the possible
+ settings supported by this card's IRIG input.
+
+ @param dh Valid handle to a Meinberg device
+ @param pdev Pointer to the device's ::PCPS_DEV structure
+ @param p_irig_settings Pointer to a ::IRIG_SETTINGS structure to be written
+ @param p_ref_offs Pointer to a ::MBG_REF_OFFS structure to be written
+ @param p_opt_settings Pointer to a ::MBG_OPT_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_all_irig_rx_info()
+ @see mbg_set_irig_rx_settings()
+ @see mbg_set_ref_offs()
+ @see mbg_set_opt_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_save_all_irig_rx_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, const IRIG_SETTINGS *p_irig_settings, const MBG_REF_OFFS *p_ref_offs, const MBG_OPT_SETTINGS *p_opt_settings ) ;
+
+ /**
+ @brief Check if a device supports the mbg_get_irig_ctrl_bits() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_ctrl_bits()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_ctrl_bits( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read the control function bits received from an incoming IRIG signal.
+
+ This function fills a ::MBG_IRIG_CTRL_BITS structure with the control function
+ bits decoded from the incoming IRIG signal.
+
+ The meaning of these bits depends on the type of IRIG code frame format.
+
+ In some IRIG formats these bits provide some well-known information which can
+ also be evaluated by the device. For example, in IEEE 1344 or IEEE C37.118 code
+ the control function bits are used to provide the year number, UTC offset,
+ DST status, leap second warning, etc.
+
+ For most IRIG code formats, however, these bits are reserved, i.e. not used
+ at all, or application defined, depending on the configuration of the IRIG
+ generator providing the IRIG signal.
+
+ In the latter case the application has to evaluate the received control function
+ bits and can use this function to retrieve these bits from the receiver device.
+
+ The macro _pcps_has_irig_ctrl_bits() or the API call mbg_dev_has_irig_ctrl_bits()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_IRIG_CTRL_BITS type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_irig_ctrl_bits()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_irig_ctrl_bits( MBG_DEV_HANDLE dh, MBG_IRIG_CTRL_BITS *p ) ;
+
+ /**
+ @brief Check if a device supports the mbg_get_raw_irig_data() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_raw_irig_data()
+ @see mbg_get_raw_irig_data_on_sec_change()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_raw_irig_data( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read raw IRIG data from an IRIG receiver.
+
+ This function fills a ::MBG_RAW_IRIG_DATA structure with the raw data bits received
+ from the incoming IRIG signal. This enables an application itself to decode the
+ information provided by the IRIG signal.
+
+ The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_raw_irig_data()
+ @see mbg_get_raw_irig_data_on_sec_change()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) ;
+
+ /**
+ @brief Wait for second changeover then read raw IRIG data from an IRIG receiver.
+
+ This function waits until the second of the device's on-board time rolls over, and
+ then reads the last recent raw IRIG data from the device.
+
+ The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> The mbg_get_time_sec_change() function called by this function is
+ supported under Windows only, so this function can also only be used under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_raw_irig_data()
+ @see mbg_get_raw_irig_data()
+ @see mbg_get_time_sec_change()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data_on_sec_change( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) ;
+
+ /**
+ @brief Check if a device supports the mbg_get_irig_time() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_time( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read the IRIG time and day-of-year number from an IRIG receiver.
+
+ Fills up a ::PCPS_IRIG_TIME structure with the raw IRIG day-of-year number
+ and time decoded from the latest IRIG input frame. If the configured IRIG code
+ also contains the year number then the year number is also returned, otherwise
+ the returned year number is 0xFF.
+
+ The macro _pcps_has_irig_time() or the API call mbg_dev_has_irig_time()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_IRIG_TIME type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_irig_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_irig_time( MBG_DEV_HANDLE dh, PCPS_IRIG_TIME *p ) ;
+
+ /**
+ @brief Clear a device's on-board time capture FIFO buffer.
+
+ The macro _pcps_can_clr_ucap_buff() or the API call mbg_dev_can_clr_ucap_buff()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_can_clr_ucap_buff()
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_clr_ucap_buff( MBG_DEV_HANDLE dh ) ;
+
+ /**
+ @brief Read information on a device's event capture buffer.
+
+ Fills a ::PCPS_UCAP_ENTRIES structure with the number of user capture
+ events actually stored in the FIFO buffer, and the maximum number of
+ events that can be held by the buffer.
+
+ The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_UCAP_ENTRIES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ucap()
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ucap_entries( MBG_DEV_HANDLE dh, PCPS_UCAP_ENTRIES *p ) ;
+
+ /**
+ @brief Retrieve a single time capture event from the on-board FIFO buffer.
+
+ The capture event is returned in a ::PCPS_HR_TIME structure. The oldest entry
+ in the FIFO is retrieved and then removed from the FIFO.
+
+ If no capture event is available in the FIFO buffer then both the seconds
+ and the fractions of the returned timestamp are 0.
+
+ The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> This call is very much faster than the older mbg_get_gps_ucap()
+ call which is obsolete but still supported for compatibility with
+ older cards.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ucap()
+ @see mbg_get_ucap_entries()
+ @see mbg_clr_ucap_buff()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ucap_event( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) ;
+
+ /**
+ @brief Read the card's time zone/daylight saving parameters.
+
+ This function returns the time zone/daylight saving parameters
+ in a ::TZDL structure.
+
+ The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> In spite of the function name this call may also be
+ supported by non-GPS cards. Other cards may support the mbg_get_tzcode()
+ or mbg_get_pcps_tzdl() calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TZDL structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzdl()
+ @see mbg_set_gps_tzdl()
+ @see mbg_get_tzcode()
+ @see mbg_get_pcps_tzdl()
+ @see \ref group_tzdl
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_tzdl( MBG_DEV_HANDLE dh, TZDL *p ) ;
+
+ /**
+ @brief Write the card's time zone/daylight saving parameters.
+
+ This function writes the time zone/daylight saving parameters
+ in a ::TZDL structure to a device.
+
+ The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> In spite of the function name this call may also be
+ supported by non-GPS cards. Other cards may support the mbg_set_tzcode()
+ or mbg_set_pcps_tzdl() calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TZDL structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzdl()
+ @see mbg_get_gps_tzdl()
+ @see mbg_set_tzcode()
+ @see mbg_set_pcps_tzdl()
+ @see \ref group_tzdl
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *p ) ;
+
+ /**
+ @brief Retrieve the software revision of a GPS receiver.
+
+ This call is obsolete but still supported for compatibility
+ with older GPS cards.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> The function mbg_get_gps_receiver_info() should
+ be used instead, if supported by the card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SW_REV structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_is_gps()
+ @see mbg_get_gps_receiver_info()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_sw_rev( MBG_DEV_HANDLE dh, SW_REV *p ) ;
+
+ /**
+ @brief Retrieve the status of the battery buffered GPS variables.
+
+ These GPS variables hold some parameters sent by the GPS satellites
+ which are required for proper operation. If the saved set of parameters
+ is not complete then the GPS receiver stays in COLD BOOT mode until
+ all data have been received and thus all data sets are valid.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::BVAR_STAT structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_bvar_stat( MBG_DEV_HANDLE dh, BVAR_STAT *p ) ;
+
+ /**
+ @brief Read the current board time using a ::TTM structure.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> This API call is pretty slow, so the mbg_get_hr_time_..()
+ or mbg_get_fast_hr_timestamp...() group of calls should be used preferably.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TTM structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time()
+ @see mbg_get_fast_hr_timestamp()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_time( MBG_DEV_HANDLE dh, TTM *p ) ;
+
+ /**
+ @brief Set the time on a GPS receiver device.
+
+ Write a ::TTM structure to a GPS receiver in order to set the
+ on-board date and time.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TTM structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_time( MBG_DEV_HANDLE dh, const TTM *p ) ;
+
+ /**
+ @brief Read a ::PORT_PARM structure with a device's serial port configuration.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> This function is obsolete since it is only
+ supported by a certain class of devices and can handle only
+ up to 2 ports. The generic function mbg_get_serial_settings()
+ should be used instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PORT_PARM structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_serial_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_port_parm( MBG_DEV_HANDLE dh, PORT_PARM *p ) ;
+
+ /**
+ @brief Write a ::PORT_PARM structure to configure the on-board serial ports.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> This function is obsolete since it is only
+ supported by a certain class of devices and can handle only
+ up to 2 ports. The generic function mbg_save_serial_settings()
+ should be used instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PORT_PARM structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_serial_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_parm( MBG_DEV_HANDLE dh, const PORT_PARM *p ) ;
+
+ /**
+ @brief Read an ::ANT_INFO structure to retrieve an extended GPS antenna status.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> Normally the current antenna connection status can also be
+ determined by evaluation of the ::PCPS_TIME::signal or ::PCPS_HR_TIME::signal
+ fields. The "disconnected" status reported by ANT_INFO disappears only if
+ the antenna has been reconnected <b>and</b> the receiver has synchronized
+ to the GPS satellites again.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ANT_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_info( MBG_DEV_HANDLE dh, ANT_INFO *p ) ;
+
+ /**
+ @brief Read a time capture event from the on-board FIFO buffer using a ::TTM structure.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> This call is pretty slow and has been obsoleted by
+ mbg_get_ucap_event() which should be used preferably, if supported
+ by the device. Anyway, this call is still supported for compatibility
+ with older devices.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TTM structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ @see mbg_clr_ucap_buff()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_ucap( MBG_DEV_HANDLE dh, TTM *p ) ;
+
+ /**
+ @brief Read the ::ENABLE_FLAGS structure controlling when outputs are to be enabled.
+
+ The ::ENABLE_FLAGS structure controls whether certain outputs
+ shall be enabled immediately after the card's power-up, or only
+ after the card has synchronized to its input signal.
+
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> Not all of the input signals specified for the
+ ::ENABLE_FLAGS structure can be modified individually.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::ENABLE_FLAGS structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ::ENABLE_FLAGS
+ @see mbg_set_gps_enable_flags()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_enable_flags( MBG_DEV_HANDLE dh, ENABLE_FLAGS *p ) ;
+
+ /**
+ @brief Write an ENABLE_FLAGS structure to configure when outputs shall be enabled.
+
+ The ::ENABLE_FLAGS structure controls whether certain outputs
+ shall be enabled immediately after the card's power-up, or only
+ after the card has synchronized to its input signal.
+
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> Not all of the input signals specified for the
+ ENABLE_FLAGS structure can be modified individually.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ENABLE_FLAGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ENABLE_FLAGS
+ @see mbg_get_gps_enable_flags()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_enable_flags( MBG_DEV_HANDLE dh, const ENABLE_FLAGS *p ) ;
+
+ /**
+ @brief Read the extended GPS receiver status from a device.
+
+ The ::STAT_INFO structure reports the status of the GPS receiver,
+ including mode of operation and number of visible/usable satellites.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::STAT_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ::STAT_INFO
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_stat_info( MBG_DEV_HANDLE dh, STAT_INFO *p ) ;
+
+ /**
+ @brief Send a ::GPS_CMD to a GPS receiver device.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::GPS_CMD
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ::PC_GPS_CMD_BOOT, ::PC_GPS_CMD_INIT_SYS, ::PC_GPS_CMD_INIT_USER, ::PC_GPS_CMD_INIT_DAC
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_cmd( MBG_DEV_HANDLE dh, const GPS_CMD *p ) ;
+
+ /**
+ @brief Read the current geographic position from a GPS device.
+
+ The returned ::POS structure contains the current position in
+ ECEF (Earth Centered, Earth Fixed) kartesian coordinates, and in
+ geographic coordinates with different formats, using the WGS84
+ geographic datum.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::POS structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pos_xyz()
+ @see mbg_set_gps_pos_lla()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_pos( MBG_DEV_HANDLE dh, POS *p ) ;
+
+ /**
+ @brief Set the GPS receiver position using ::XYZ coordinates.
+
+ The structure ::XYZ must specify the new position in ECEF
+ (Earth Centered, Earth Fixed) kartesian coordinates.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param p Position in ::XYZ format to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pos_lla()
+ @see mbg_get_gps_pos()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_xyz( MBG_DEV_HANDLE dh, const XYZ p ) ;
+
+ /**
+ @brief Set the GPS receiver position using ::LLA coordinates.
+
+ The structure LLA must specify the new position as longitude, latitude,
+ and altitude, using the WGS84 geographic datum.
+
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param p Position in ::LLA format to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pos_xyz()
+ @see mbg_get_gps_pos()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_lla( MBG_DEV_HANDLE dh, const LLA p ) ;
+
+ /**
+ @brief Read the configured GPS antenna cable length from a device.
+
+ The antenna cable length parameter is used to compensate the propagation
+ delay of the RF signal over the antenna cable, which is about 5 ns/m.
+
+ The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::ANT_CABLE_LEN structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_cab_len()
+ @see mbg_set_gps_ant_cable_len()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_cable_len( MBG_DEV_HANDLE dh, ANT_CABLE_LEN *p ) ;
+
+ /**
+ @brief Write the GPS antenna cable length configuration to a device.
+
+ The antenna cable length parameter is used to compensate the propagation
+ delay of the RF signal over the antenna cable, which is about 5 ns/m.
+
+ The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::ANT_CABLE_LEN structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_cab_len()
+ @see mbg_get_gps_ant_cable_len()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_ant_cable_len( MBG_DEV_HANDLE dh, const ANT_CABLE_LEN *p ) ;
+
+ /**
+ @brief Read the ::RECEIVER_INFO structure from a device.
+
+ The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> Applications should call mbg_setup_receiver_info()
+ preferably, which also sets up a basic ::RECEIVER_INFO structure
+ for devices which don't provide that structure by themselves.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::RECEIVER_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_setup_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_receiver_info( MBG_DEV_HANDLE dh, RECEIVER_INFO *p ) ;
+
+ /**
+ @brief Read a ::STR_TYPE_INFO_IDX array of supported string types.
+
+ The function mbg_setup_receiver_info() must have been called before,
+ and the returned ::RECEIVER_INFO structure passed to this function.
+
+ <b>Note:</b> The function mbg_get_serial_settings() should be used preferably
+ to get retrieve the current port settings and configuration options.
+
+ @param dh Valid handle to a Meinberg device.
+ @param stii Pointer to a an array of string type information to be filled up
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info()
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_setup_receiver_info()
+ @see mbg_get_gps_all_port_info()
+ @see mbg_get_serial_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_all_str_type_info( MBG_DEV_HANDLE dh, STR_TYPE_INFO_IDX stii[], const RECEIVER_INFO *p_ri ) ;
+
+ /**
+ @brief Read a ::PORT_INFO_IDX array of supported serial port configurations.
+
+ The function mbg_setup_receiver_info() must have been called before,
+ and the returned ::RECEIVER_INFO structure passed to this function.
+
+ <b>Note:</b> The function mbg_get_serial_settings() should be used preferably
+ to get retrieve the current port settings and configuration options.
+
+ @param dh Valid handle to a Meinberg device.
+ @param pii Pointer to a an array of port configuration information to be filled up
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info()
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_setup_receiver_info()
+ @see mbg_get_gps_all_str_type_info()
+ @see mbg_get_serial_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_all_port_info( MBG_DEV_HANDLE dh, PORT_INFO_IDX pii[], const RECEIVER_INFO *p_ri ) ;
+
+ /**
+ @brief Write the configuration for a single serial port to a device.
+
+ The ::PORT_SETTINGS_IDX structure contains both the ::PORT_SETTINGS
+ and the port index value. Except for the parameter types this call is
+ equivalent to mbg_set_gps_port_settings().
+
+ The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> The function mbg_save_serial_settings() should be used preferably
+ to write new port configuration to the board.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::PORT_SETTINGS_IDX structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_serial_settings()
+ @see mbg_set_gps_port_settings()
+ @see mbg_dev_has_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings_idx( MBG_DEV_HANDLE dh, const PORT_SETTINGS_IDX *p ) ;
+
+ /**
+ @brief Write the configuration for a single serial port to a device.
+
+ The ::PORT_SETTINGS structure does not contain the port index, so the
+ the port index must be given separately. Except for the parameter types
+ this call is equivalent to mbg_set_gps_port_settings_idx().
+
+ The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info()
+ check whether this call is supported by a device.
+
+ <b>Note:</b> The function mbg_save_serial_settings() should be used preferably
+ to write new port configuration to the board.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::PORT_SETTINGS structure to be filled up
+ @param idx Index of the serial port to be configured (starting from 0 ).
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_serial_settings()
+ @see mbg_set_gps_port_settings_idx()
+ @see mbg_dev_has_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings( MBG_DEV_HANDLE dh, const PORT_SETTINGS *p, int idx ) ;
+
+ /**
+ @brief Set up a ::RECEIVER_INFO structure for a device.
+
+ If the device supports the ::RECEIVER_INFO structure then the structure
+ is read from the device, otherwise a structure is set up using
+ default values depending on the device type.
+ The function mbg_get_device_info() must have been called before,
+ and the returned PCPS_DEV structure passed to this function.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *pdev Pointer to a ::PCPS_DEV structure returned by mbg_get_device_info()
+ @param *p Pointer to a ::RECEIVER_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_device_info()
+ @see mbg_dev_has_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_setup_receiver_info( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_INFO *p ) ;
+
+ /**
+ @brief Read the version code of the on-board PCI/PCIe interface ASIC.
+
+ The macro _pcps_has_asic_version() or the API call mbg_dev_has_asic_version()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCI_ASIC_VERSION type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+
+ @see mbg_dev_has_asic_version()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_asic_version( MBG_DEV_HANDLE dh, PCI_ASIC_VERSION *p ) ;
+
+ /**
+ @brief Read the features of the on-board PCI/PCIe interface ASIC.
+
+ The macro _pcps_has_asic_features() or the API call mbg_dev_has_asic_features()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::PCI_ASIC_FEATURES type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_asic_features()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_asic_features( MBG_DEV_HANDLE dh, PCI_ASIC_FEATURES *p ) ;
+
+ /**
+ @brief Check if a device supports configurable time scales.
+
+ By default the cards return UTC and/or local time. However, some cards
+ can be configured to return raw GPS time or TAI instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time_scale_info()
+ @see mbg_set_time_scale_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_time_scale( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read the current time scale settings and which time scales are supported.
+
+ The ::MBG_TIME_SCALE_INFO structure tells which time scale settings are supported
+ by a device, and which time scale is currently configured.
+
+ The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale()
+ check whether this call is supported by a device.
+ See also the notes for mbg_dev_has_time_scale().
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_SCALE_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_time_scale_settings()
+ @see mbg_dev_has_time_scale()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_time_scale_info( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p ) ;
+
+ /**
+ @brief Write the time scale configuration to a device.
+
+ The ::MBG_TIME_SCALE_SETTINGS structure determines which time scale
+ is to be used for the time stamps which can be read from a device.
+
+ The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale()
+ check whether this call is supported by a device.
+ See also the notes for mbg_dev_has_time_scale().
+
+ The function mbg_get_time_scale_info() should have been called before
+ in order to determine which time scales are supported by the card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_SCALE_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time_scale_info()
+ @see mbg_dev_has_time_scale()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_SETTINGS *p ) ;
+
+ /**
+ @brief Check if a device support reading/writing of UTC parameters.
+
+ This API call checks if a device supports reading/writing a GPS UTC
+ parameter set via the PC bus. Reading/writing these parameters via the
+ serial port using the Meinberg binary data protocol is supported by all
+ Meinberg GPS devices.
+
+ The UTC parameter set is usually received from the satellites' broadcasts
+ and contains the current time offset between GPS time and UTC, plus information
+ on a pending leap second event.
+
+ It may be useful to overwrite them to do some tests, or for applications
+ where a card is freewheeling.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_utc_parm()
+ @see mbg_set_utc_parm()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_utc_parm( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read a ::UTC parameter structure from a device.
+
+ The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm()
+ check whether this call is supported by a device.
+ See also the notes for mbg_dev_has_utc_parm().
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::UTC structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_utc_parm()
+ @see mbg_set_utc_parm()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) ;
+
+ /**
+ @brief Write a ::UTC parameter structure to a device.
+
+ This should only be done for testing, or if a card is operated in
+ freewheeling mode. If the receiver is tracking any satellites then the settings
+ written to the device are overwritten by the parameters broadcasted
+ by the satellites.
+
+ The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm()
+ check whether this call is supported by a device.
+ See also the notes for mbg_dev_has_utc_parm().
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a valid ::UTC structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_utc_parm()
+ @see mbg_get_utc_parm()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) ;
+
+ /**
+ @brief Read the current time plus the associated PC cycles from a device.
+
+ The ::PCPS_TIME_CYCLES structure contains a ::PCPS_TIME structure
+ and a PC cycle counter value which can be used to compensate the latency
+ of the call, i.e. the program execution time until the time stamp has actually
+ been read from the board.
+
+ This call is supported for any card, similar to mbg_get_time(). However,
+ the mbg_get_hr_time_cyles() call should be used preferably if supported by
+ the device since that call provides much better accuracy than this one.
+
+ The cycle counter value corresponds to a value returned by QueryPerformanceCounter()
+ under Windows, and get_cycles() under Linux. On operating systems or targets which don't
+ provide a cycles counter the returned cycles value is always 0.
+
+ Applications should first pick up their own cycle counter value and then call
+ this function. The difference of the cycle counter values corresponds to the
+ latency of the call in units of the cycle counter clock frequency, e.g as reported
+ by QueryPerformanceFrequency() under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_CYCLES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time_cycles()
+ @see mbg_get_hr_time_comp()
+ @see mbg_get_hr_time()
+ @see mbg_get_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_time_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_CYCLES *p ) ;
+
+ /**
+ @brief Read the current high resolution time plus the associated PC cycles from a device.
+
+ The ::PCPS_HR_TIME_CYCLES structure contains a ::PCPS_HR_TIME structure
+ and a PC cycle counter value which can be used to compensate the latency
+ of the call, i.e. the program execution time until the time stamp has actually
+ been read from the board.
+
+ The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time()
+ check whether this call is supported by a device.
+
+ The cycle counter value corresponds to a value returned by QueryPerformanceCounter()
+ under Windows, and get_cycles() under Linux. On operating systems or targets which don't
+ provide a cycles counter the returned cycles value is always 0.
+
+ Applications should first pick up their own cycle counter value and then call
+ this function. The difference of the cycle counter values corresponds to the
+ latency of the call in units of the cycle counter clock frequency, e.g as reported
+ by QueryPerformanceFrequency() under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME_CYCLES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time_comp()
+ @see mbg_get_hr_time()
+ @see mbg_get_time_cycles()
+ @see mbg_get_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_cycles( MBG_DEV_HANDLE dh, PCPS_HR_TIME_CYCLES *p ) ;
+
+ /**
+ @brief Read the current high resolution time, and compensate the call's latency.
+
+ Read a ::PCPS_HR_TIME structure plus cycle counter value, and correct the
+ time stamp for the latency of the call as described for mbg_get_hr_time_cycles(),
+ then return the compensated time stamp and optionally the latency.
+
+ The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time()
+ check whether this call is supported by a device.
+
+ The cycle counter value corresponds to a value returned by QueryPerformanceCounter()
+ under Windows, and get_cycles() under Linux. On operating systems or targets which don't
+ provide a cycles counter the returned cycles value is always 0.
+
+ Applications should first pick up their own cycle counter value and then call
+ this function. The difference of the cycle counter values corresponds to the
+ latency of the call in units of the cycle counter clock frequency, e.g as reported
+ by QueryPerformanceFrequency() under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up
+ @param *hns_latency Optional pointer to an int32_t value to return
+ the latency in 100ns units. Pass NULL if not used.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time_comp()
+ @see mbg_get_hr_time()
+ @see mbg_get_time_cycles()
+ @see mbg_get_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_comp( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p, int32_t *hns_latency ) ;
+
+ /**
+ @brief Read the current IRIG output settings plus the supported settings.
+
+ The returned ::IRIG_INFO structure contains the configuration of an IRIG output
+ plus the possible settings supported by that output.
+
+ The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an ::IRIG_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_irig_tx_settings()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_irig_tx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) ;
+
+ /**
+ @brief Write an ::IRIG_SETTINGS structure to a device to configure the IRIG output.
+
+ The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an ::IRIG_INFO structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_tx_info()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_irig_tx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) ;
+
+ /**
+ @brief Read the current frequency synthesizer settings from a device.
+
+ Read a ::SYNTH structure containing the configuration of an optional
+ on-board programmable frequency synthesizer.
+
+ The macro _pcps_has_synth() or the API call mbg_dev_has_synth()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SYNTH structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_synth()
+ @see mbg_set_synth()
+ @see mbg_get_synth_state()
+ @see \ref group_synth
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_synth( MBG_DEV_HANDLE dh, SYNTH *p ) ;
+
+ /**
+ @brief Write some frequency synthesizer settings to a device.
+
+ Write a ::SYNTH structure containing the configuration of an optional
+ on-board programmable frequency synthesizer.
+
+ The macro _pcps_has_synth() or the API call mbg_dev_has_synth()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SYNTH structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_synth()
+ @see mbg_get_synth()
+ @see mbg_get_synth_state()
+ @see \ref group_synth
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_synth( MBG_DEV_HANDLE dh, const SYNTH *p ) ;
+
+ /**
+ @brief Read the current status of the on-board frequency synthesizer.
+
+ The macro _pcps_has_synth() or the API call mbg_dev_has_synth()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SYNTH_STATE structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_synth()
+ @see mbg_get_synth()
+ @see mbg_set_synth()
+ @see \ref group_synth
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_synth_state( MBG_DEV_HANDLE dh, SYNTH_STATE *p ) ;
+
+ /**
+ @brief Check if a device supports the mbg_get_fast_hr_timestamp_...() calls.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_fast_hr_timestamp_cycles()
+ @see mbg_get_fast_hr_timestamp_comp()
+ @see mbg_get_fast_hr_timestamp()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_fast_hr_timestamp( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read a high resolution ::PCPS_TIME_STAMP_CYCLES structure via memory mapped access.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP_CYCLES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_fast_hr_timestamp_comp()
+ @see mbg_get_fast_hr_timestamp()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP_CYCLES *p ) ;
+
+ /**
+ @brief Read a high resolution timestamp and compensate the latency of the call.
+
+ The retrieved ::PCPS_TIME_STAMP is read from memory mapped registers,
+ and timestamp is compensated for the call's latency before it is returned.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up
+ @param *hns_latency Optionally receive the latency in hectonanoseconds
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_fast_hr_timestamp_cycles()
+ @see mbg_get_fast_hr_timestamp()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_comp( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP *p, int32_t *hns_latency ) ;
+
+ /**
+ @brief Read a high resolution ::PCPS_TIME_STAMP structure via memory mapped access.
+
+ This function does not return or evaluate a cycles count, so the latency
+ of the call can not be determined. However, depending on the timer hardware
+ used as cycles counter it may take quite some time to read the cycles count
+ on some hardware architectures, so this call can be used to yield lower
+ latencies, under the restriction to be unable to determine the exact latency.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_fast_hr_timestamp_comp()
+ @see mbg_get_fast_hr_timestamp_cycles()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP *p ) ;
+
+ /**
+ @brief Check if a device is a GPS receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_gps( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device is a DCF77 receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_dcf( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device is a MSF receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_msf( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device is a WWVB receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_wwvb( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device is any long wave signal receiver.
+
+ Long wave receivers include e.g. DCF77, MSF, WWVB, or JJY.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_lwr( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device provides a configurable IRIG input.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_rx_info()
+ @see mbg_set_irig_rx_settings()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_has_irig()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_irig_rx( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports the HR_TIME functions.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time()
+ @see mbg_get_hr_time_cycles()
+ @see mbg_get_hr_time_comp()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_hr_time( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports configuration of antenna cable length.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_ant_cable_len()
+ @see mbg_set_gps_ant_cable_len()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_cab_len( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports timezone configuration using the ::TZDL structure.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_tzdl()
+ @see mbg_set_gps_tzdl()
+ @see mbg_dev_has_tz()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_tzdl( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports timezone configuration using the ::PCPS_TZDL structure.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_pcps_tzdl()
+ @see mbg_set_pcps_tzdl()
+ @see mbg_dev_has_tz()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_pcps_tzdl( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports timezone configuration using the ::PCPS_TZCODE type.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_tzcode()
+ @see mbg_set_tzcode()
+ @see mbg_dev_has_tz()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_tzcode( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports any kind of timezone configuration.
+
+ This can be used e.g. to check if a specifig dialog or menu has to
+ be displayed.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzdl()
+ @see mbg_dev_has_pcps_tzdl()
+ @see mbg_dev_has_tzcode()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_tz( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Check if a device supports setting an event time, i.e.
+ configure a %UTC time when the clock shall generate an event.
+
+ <b>Note:</b> This is only supported by some special firmware.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_event_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_event_time( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports the ::RECEIVER_INFO structure and related calls.
+
+ @note Older GPS devices may not support that structure.
+
+ The mbg_get_gps_receiver_info() call uses this call to decide whether a
+ ::RECEIVER_INFO can be read directly from a device, or whether a default
+ structure has to be set up using default values depending on the device type.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_receiver_info( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports the mbg_clr_ucap_buff() call.
+
+ The mbg_clr_ucap_buff() call can be used to clear a card's on-board
+ time capture FIFO buffer.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_clr_ucap_buff()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_can_clr_ucap_buff( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports the mbg_get_ucap_entries() and mbg_get_ucap_event() calls.
+
+ If the card does not but it is a GPS card then the card provides
+ a time capture FIFO buffer and the obsolete mbg_get_gps_ucap()
+ call can be used to retrieve entries from the FIFO buffer.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ @see mbg_clr_ucap_buff()
+ @see mbg_get_gps_ucap()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_ucap( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device provides a configurable IRIG output.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_tx_info()
+ @see mbg_set_irig_tx_settings()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_tx( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Check if a device provides a serial output supporting
+ higher baud rates than older cards, i.e. ::DEFAULT_BAUD_RATES_DCF_HS
+ rather than ::DEFAULT_BAUD_RATES_DCF.
+
+ The mbg_get_serial_settings() takes care of this, so applications
+ which use that call as suggested won't need to use this call directly.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_serial_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_serial_hs( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device provides the level of its inputs signal.
+
+ This is useful to display the signal level of e.g. an IRIG or longwave signal.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_signal( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device provides a modulation signal.
+
+ Modulation signals are e.g. the second marks of a DCF77 AM receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_mod( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device provides either an IRIG input or output.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig_tx()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_irig( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device provides a configurable ref time offset.
+
+ This may be required to convert the received time to %UTC, if the input
+ signal doesn't specify this (e.g. most IRIG code formats).
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ref_offs()
+ @see mbg_set_ref_offs()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_ref_offs( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports the ::MBG_OPT_INFO/::MBG_OPT_SETTINGS.
+
+ These structures containing optional settings, controlled by flags.
+ See ::MBG_OPT_SETTINGS and related definitions.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_opt_info()
+ @see mbg_set_opt_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_opt_flags( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports large configuration data structures.
+
+ Such structures have been introduced with the first Meinberg GPS receivers.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_gps_data( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device provides a programmable frequency synthesizer.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_synth()
+ @see mbg_set_synth()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_synth( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ @brief Check if a device supports the mbg_generic_io() call.
+
+ <b>Warning</b>: That call is for debugging purposes and internal use only!
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_generic_io()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_generic_io( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports the mbg_get_asic_version() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_asic_version()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_asic_version( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports the mbg_get_asic_features() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_asic_features()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_asic_features( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read current configuraton and features provided by the programmable pulse outputs.
+
+ Reads a ::POUT_INFO_IDX array of current settings and configuration
+ options of the device's programmable pulse outputs.
+
+ The function mbg_setup_receiver_info() must have been called before,
+ and the returned ::RECEIVER_INFO structure passed to this function.
+ The function should only be called if the ::RECEIVER_INFO::n_prg_out
+ field (i.e. the number of programmable outputs on the board) is not 0.
+
+ The array passed to this function to receive the returned data
+ must be able to hold at least ::RECEIVER_INFO::n_prg_out elements.
+
+ @param dh Valid handle to a Meinberg device.
+ @param pii Pointer to a an array of ::POUT_INFO_IDX structures to be filled up
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info()
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pout_settings_idx()
+ @see mbg_set_gps_pout_settings()
+ @see mbg_setup_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_all_pout_info( MBG_DEV_HANDLE dh, POUT_INFO_IDX pii[], const RECEIVER_INFO *p_ri ) ;
+
+ /**
+ @brief Write the configuration for a single programmable pulse output
+
+ The ::POUT_SETTINGS_IDX structure contains both the ::POUT_SETTINGS
+ and the output index value. Except for the parameter types this call
+ is equivalent to mbg_set_gps_pout_settings().
+
+ The function should only be called if the ::RECEIVER_INFO::n_prg_out field
+ (i.e. the number of programmable outputs on the board) is not 0, and the
+ output index value must be in the range 0..::RECEIVER_INFO::n_prg_out.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::POUT_SETTINGS_IDX structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_all_pout_info()
+ @see mbg_set_gps_pout_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings_idx( MBG_DEV_HANDLE dh, const POUT_SETTINGS_IDX *p ) ;
+
+ /**
+ @brief Write the configuration for a single programmable pulse output
+
+ The ::POUT_SETTINGS structure does not contain the index of the
+ programmable output to be configured, so the index must explicitely
+ be passed to this function. Except for the parameter types this call
+ is equivalent to mbg_set_gps_pout_settings_idx().
+
+ The function should only be called if the ::RECEIVER_INFO::n_prg_out field
+ (i.e. the number of programmable outputs on the board) is not 0, and the
+ output index value must be in the range 0..::RECEIVER_INFO::n_prg_out.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::POUT_SETTINGS structure to be written
+ @param idx Index of the programmable pulse output to be configured (starting from 0 ).
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_all_pout_info()
+ @see mbg_set_gps_pout_settings_idx()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings( MBG_DEV_HANDLE dh, const POUT_SETTINGS *p, int idx ) ;
+
+ /**
+ @brief Read a device's IRQ status information.
+
+ IRQ status information includes flags indicating whether IRQs are
+ actually enabled, and whether IRQ support by a card is possibly
+ unsafe due to the firmware and interface chip version.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_IRQ_STAT_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_irq_stat_info( MBG_DEV_HANDLE dh, PCPS_IRQ_STAT_INFO *p ) ;
+
+ /**
+ @brief Check if a device provides simple LAN interface API calls.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_state()
+ @see mbg_get_ip4_settings()
+ @see mbg_set_ip4_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_lan_intf( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read LAN interface information from a device.
+
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::LAN_IF_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_ip4_state()
+ @see mbg_get_ip4_settings()
+ @see mbg_set_ip4_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_lan_if_info( MBG_DEV_HANDLE dh, LAN_IF_INFO *p ) ;
+
+ /**
+ @brief Read LAN IPv4 state from a device.
+
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::IP4_SETTINGS variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_settings()
+ @see mbg_set_ip4_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ip4_state( MBG_DEV_HANDLE dh, IP4_SETTINGS *p ) ;
+
+ /**
+ @brief Read LAN IPv4 settings from a device.
+
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::IP4_SETTINGS variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_state()
+ @see mbg_set_ip4_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ip4_settings( MBG_DEV_HANDLE dh, IP4_SETTINGS *p ) ;
+
+ /**
+ @brief Write LAN IPv4 settings to a device.
+
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::IP4_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_ip4_settings( MBG_DEV_HANDLE dh, const IP4_SETTINGS *p ) ;
+
+ /**
+ @brief Check if a device provides PTP configuration/status calls.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_all_ptp_cfg_info
+ @see mbg_get_ptp_state
+ @see mbg_get_ptp_cfg_info
+ @see mbg_set_ptp_cfg_settings
+ @see mbg_dev_has_ptp_unicast
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_ptp( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device provides PTP unicast feature/configuration.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_all_ptp_cfg_info
+ @see mbg_get_ptp_uc_master_cfg_limits
+ @see mbg_get_all_ptp_uc_master_info
+ @see mbg_set_ptp_uc_master_settings_idx
+ @see mbg_get_ptp_state
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_ptp_unicast( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read PTP/IEEE1588 status from a device.
+
+ The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PTP_STATE variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp
+ @see mbg_get_all_ptp_cfg_info
+ @see mbg_get_ptp_cfg_info
+ @see mbg_set_ptp_cfg_settings
+ @see mbg_dev_has_ptp_unicast
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ptp_state( MBG_DEV_HANDLE dh, PTP_STATE *p ) ;
+
+ /**
+ @brief Read PTP/IEEE1588 config info and current settings from a device.
+
+ The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PTP_CFG_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp
+ @see mbg_get_all_ptp_cfg_info
+ @see mbg_get_ptp_state
+ @see mbg_set_ptp_cfg_settings
+ @see mbg_dev_has_ptp_unicast
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ptp_cfg_info( MBG_DEV_HANDLE dh, PTP_CFG_INFO *p ) ;
+
+ /**
+ @brief Write PTP/IEEE1588 configuration settings to a device.
+
+ The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::PTP_CFG_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp
+ @see mbg_get_all_ptp_cfg_info
+ @see mbg_get_ptp_state
+ @see mbg_get_ptp_cfg_info
+ @see mbg_dev_has_ptp_unicast
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_ptp_cfg_settings( MBG_DEV_HANDLE dh, const PTP_CFG_SETTINGS *p ) ;
+
+ /**
+ @brief Read PTP/IEEE1588 unicast master configuration limits from a device.
+
+ The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PTP_UC_MASTER_CFG_LIMITS variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp_unicast
+ @see mbg_get_all_ptp_cfg_info
+ @see mbg_get_all_ptp_uc_master_info
+ @see mbg_set_ptp_uc_master_settings_idx
+ @see mbg_get_ptp_state
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ptp_uc_master_cfg_limits( MBG_DEV_HANDLE dh, PTP_UC_MASTER_CFG_LIMITS *p ) ;
+
+ /**
+ @brief Read PTP Unicast master settings and configuration options.
+
+ The function mbg_setup_receiver_info() must have been called before,
+ and the returned ::RECEIVER_INFO structure passed to this function.
+ The function should only be called if the ::RECEIVER_INFO::n_prg_out
+ field (i.e. the number of programmable outputs on the board) is not 0.
+
+ The array passed to this function to receive the returned data
+ must be able to hold at least ::RECEIVER_INFO::n_prg_out elements.
+
+ @param dh Valid handle to a Meinberg device.
+ @param pii Pointer to a an array of ::PTP_UC_MASTER_INFO_IDX structures to be filled up
+ @param p_umsl Pointer to a ::PTP_UC_MASTER_CFG_LIMITS structure returned by mbg_get_ptp_uc_master_cfg_limits()
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp_unicast
+ @see mbg_get_all_ptp_cfg_info
+ @see mbg_get_ptp_uc_master_cfg_limits
+ @see mbg_set_ptp_uc_master_settings_idx
+ @see mbg_get_ptp_state
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_all_ptp_uc_master_info( MBG_DEV_HANDLE dh, PTP_UC_MASTER_INFO_IDX pii[], const PTP_UC_MASTER_CFG_LIMITS *p_umsl ) ;
+
+ /**
+ @brief Write PTP/IEEE1588 unicast configuration settings to a device.
+
+ The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::PTP_UC_MASTER_SETTINGS_IDX structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp_unicast
+ @see mbg_get_all_ptp_cfg_info
+ @see mbg_get_ptp_uc_master_cfg_limits
+ @see mbg_get_all_ptp_uc_master_info
+ @see mbg_get_ptp_state
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_ptp_uc_master_settings_idx( MBG_DEV_HANDLE dh, const PTP_UC_MASTER_SETTINGS_IDX *p ) ;
+
+ /**
+ @brief Read both system time and associated device time from the kernel driver.
+
+ The kernel driver reads the current system time plus a HR time structure
+ from a card immediately after each other. The returned info structure also
+ contains some cycles counts to be able to determine the execution times
+ required to read those time stamps.
+
+ The advantage of this call compared to mbg_get_time_info_tstamp() is
+ that this call also returns the card's status. On the other hand, reading
+ the HR time from the card may block e.g. if another application accesses
+ the board.
+
+ This call makes a mbg_get_hr_time_cycles() call internally so the macro
+ _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() can be
+ used to check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_INFO_HRT variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_hr_time()
+ @see mbg_get_time_info_tstamp()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_time_info_hrt( MBG_DEV_HANDLE dh, MBG_TIME_INFO_HRT *p ) ;
+
+ /**
+ @brief Read both system time and associated device timestamp from the kernel driver.
+
+ This call is similar to mbg_get_time_info_hrt() except that a
+ mbg_get_fast_hr_timestamp_cycles() call is made internally, so the macro
+ _pcps_has_fast_hr_timestamp() or the API call mbg_dev_has_fast_hr_timestamp()
+ can be used to check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_INFO_TSTAMP variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_time_info_hrt()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_time_info_tstamp( MBG_DEV_HANDLE dh, MBG_TIME_INFO_TSTAMP *p ) ;
+
+ /**
+ @brief Check if a device supports demodulation of the DCF77 PZF code.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_corr_info()
+ @see mbg_dev_has_tr_distance()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_pzf( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports reading correlation info.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pzf()
+ @see mbg_get_corr_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_corr_info( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Check if a device supports configurable distance from transmitter.
+
+ The distance from transmitter parameter is used to compensate
+ the RF propagation delay, mostly with long wave receivers.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pzf()
+ @see mbg_get_tr_distance()
+ @see mbg_set_tr_distance()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_tr_distance( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read PZF correlation info from a device.
+
+ The macro _pcps_has_corr_info() or the API call mbg_dev_has_corr_info()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::CORR_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pzf()
+ @see mbg_dev_has_corr_info()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_corr_info( MBG_DEV_HANDLE dh, CORR_INFO *p ) ;
+
+ /**
+ @brief Read configurable "distance from transmitter" parameter from a device.
+
+ The distance from transmitter parameter is used to compensate
+ the RF propagation delay, mostly with long wave receivers.
+
+ The macro _pcps_has_tr_distance() or the API call mbg_dev_has_tr_distance()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TR_DISTANCE variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pzf()
+ @see mbg_dev_has_tr_distance()
+ @see mbg_set_tr_distance()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_tr_distance( MBG_DEV_HANDLE dh, TR_DISTANCE *p ) ;
+
+ /**
+ @brief Write configurable "distance from transmitter" parameter to a device.
+
+ The distance from transmitter parameter is used to compensate
+ the RF propagation delay, mostly with long wave receivers.
+
+ The macro _pcps_has_tr_distance() or the API call mbg_dev_has_tr_distance()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TR_DISTANCE variable to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pzf()
+ @see mbg_dev_has_tr_distance()
+ @see mbg_get_tr_distance()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_tr_distance( MBG_DEV_HANDLE dh, const TR_DISTANCE *p ) ;
+
+ /**
+ @brief Check if a device provides a debug status word to be read.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_debug_status()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_debug_status( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Read a debug status word from a device.
+
+ This is mainly supported by IRIG timecode receiver cards, and the status
+ word is intended to provide more detailed information why a card might not
+ synchronize to the incoming timecode signal.
+
+ See ::MBG_DEBUG_STATUS and related definitions for details.
+
+ The macro _pcps_has_debug_status() or the API call mbg_dev_has_debug_status()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_DEBUG_STATUS variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_debug_status()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_debug_status( MBG_DEV_HANDLE dh, MBG_DEBUG_STATUS *p ) ;
+
+ /**
+ @brief Check if a device provides an on-board event log.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_clr_evt_log()
+ @see mbg_get_num_evt_log_entries()
+ @see mbg_get_first_evt_log_entry()
+ @see mbg_get_next_evt_log_entry()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_evt_log( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ @brief Clear the card's on-board event log.
+
+ The macro _pcps_has_evt_log() or the API call mbg_dev_has_evt_log()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_evt_log()
+ @see mbg_get_num_evt_log_entries()
+ @see mbg_get_first_evt_log_entry()
+ @see mbg_get_next_evt_log_entry()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_clr_evt_log( MBG_DEV_HANDLE dh ) ;
+
+ /**
+ @brief Read details about a device's on-board event log buffer.
+
+ The returned ::MBG_NUM_EVT_LOG_ENTRIES structure tells how many event log
+ entries which can be saved on the board, and how many entries actually
+ have been saved.
+
+ The macro _pcps_has_evt_log() or the API call mbg_dev_has_evt_log()
+ check whether this call is supported by a device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_NUM_EVT_LOG_ENTRIES variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_evt_log()
+ @see mbg_clr_evt_log()
+ @see mbg_get_first_evt_log_entry()
+ @see mbg_get_next_evt_log_entry()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_num_evt_log_entries( MBG_DEV_HANDLE dh, MBG_NUM_EVT_LOG_ENTRIES *p ) ;
+
+ /**
+ @brief Read the first (oldest) event log entry from a device.
+
+ @note Subsequent reads should be made using mbg_get_next_evt_log_entry().
+
+ The macro _pcps_has_evt_log() or the API call mbg_dev_has_evt_log()
+ check whether this call is supported by a device.
+
+ If no (more) event log entry is available on the device then
+ the returned MBG_EVT_LOG_ENTRY::code is MBG_EVT_ID_NONE.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_EVT_LOG_ENTRY variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_evt_log()
+ @see mbg_clr_evt_log()
+ @see mbg_get_num_evt_log_entries()
+ @see mbg_get_next_evt_log_entry()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_first_evt_log_entry( MBG_DEV_HANDLE dh, MBG_EVT_LOG_ENTRY *p ) ;
+
+ /**
+ @brief Read the next event log entry from a device.
+
+ @note The first read should be made using mbg_get_first_evt_log_entry()
+ to set the on-board read index to the oldest entry.
+
+ The macro _pcps_has_evt_log() or the API call mbg_dev_has_evt_log()
+ check whether this call is supported by a device.
+
+ If no (more) event log entry is available on the device then
+ the returned MBG_EVT_LOG_ENTRY::code is MBG_EVT_ID_NONE.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_EVT_LOG_ENTRY variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_evt_log()
+ @see mbg_clr_evt_log()
+ @see mbg_get_num_evt_log_entries()
+ @see mbg_get_first_evt_log_entry()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_next_evt_log_entry( MBG_DEV_HANDLE dh, MBG_EVT_LOG_ENTRY *p ) ;
+
+ /**
+ @brief Read the CPU affinity of a process.
+
+ This means on which of the available CPUs or CPU cores the process can be executed.
+
+ @param pid The process ID.
+ @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_set_process_affinity()
+ @see mbg_set_current_process_affinity_to_cpu()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) ;
+
+ /**
+ @brief Set the CPU affinity of a process.
+
+ This determines on which of the available CPUs
+ the process is allowed to be executed.
+
+ @param pid The process ID.
+ @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_get_process_affinity()
+ @see mbg_set_current_process_affinity_to_cpu()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) ;
+
+ /**
+ @brief Set the CPU affinity of a process for a single CPU only.
+
+ This means the process may only be executed on that single CPU.
+
+ @param cpu_num The number of the CPU.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_get_process_affinity()
+ @see mbg_set_process_affinity()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_current_process_affinity_to_cpu( int cpu_num ) ;
+
+ /**
+ @brief Create a new execution thread for the current process.
+
+ This function is only implemented for targets which support threads.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure to be filled up.
+ @param fnc The name of the thread function to be started.
+ @param arg A generic argument passed to the thread function.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_thread_stop()
+ @see mbg_thread_sleep_interruptible()
+ @see mbg_thread_set_affinity()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_thread_create( MBG_THREAD_INFO *p_ti, MBG_THREAD_FNC_RET_VAL (MBG_THREAD_FNC_ATTR *fnc)(void *), void *arg ) ;
+
+ /**
+ @brief Stop a thread which has been created by mbg_thread_create().
+
+ Wait until the thread has finished and release all resources.
+ This function is only implemented for targets which support threads.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_thread_create()
+ @see mbg_thread_sleep_interruptible()
+ @see mbg_thread_set_affinity()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_thread_stop( MBG_THREAD_INFO *p_ti ) ;
+
+ /**
+ @brief Let the current thread sleep for a certain interval.
+
+ The sleep is interrupted if a signal is received indicating
+ the thread should terminate.
+
+ This function is only implemented for targets which support threads.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread.
+ @param sleep_ms The number of milliseconds to sleep
+ @return 0 if the sleep interval has expired normally
+ 1 if a signal to terminate has been received
+ <0 if an error has occurred
+
+ @see mbg_thread_create()
+ @see mbg_thread_stop()
+ @see mbg_thread_set_affinity()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_thread_sleep_interruptible( MBG_THREAD_INFO *p_ti, ulong sleep_ms ) ;
+
+ /**
+ @brief Set the CPU affinity of a single thread.
+
+ This determines on which of the available CPUs the thread
+ is allowed to be executed.
+
+ This function is only implemented for targets which support thread affinity.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread.
+ @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_thread_create()
+ @see mbg_thread_stop()
+ @see mbg_thread_sleep_interruptible()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_thread_set_affinity( MBG_THREAD_INFO *p_ti, MBG_CPU_SET *p ) ;
+
+ /**
+ @brief Set up a ::MBG_POLL_THREAD_INFO structure and start a new thread.
+
+ The new thread runs the mbg_xhrt_poll_thread_fnc() function.
+
+ This function is only implemented for targets which support threads.
+
+ @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure.
+ @param dh the handle of the device to be polled.
+ @param freq_hz The initial cycles frequency, if known, in Hz.
+ @param sleep_ms the sleep interval for the poll thread function in ms.
+ If this parameter is 0 then the default sleep interval is used.
+
+ @return ::MBG_SUCCESS on success,
+ ::MBG_ERR_NOT_SUPP_BY_DEV if the device to poll does not support HR time
+ else the result of mbg_thread_create()
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_time_as_filetime()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_create( MBG_POLL_THREAD_INFO *p_pti, MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY freq_hz, int sleep_ms ) ;
+
+ /**
+ @brief Stop a polling thread started by mbg_xhrt_poll_thread_create().
+
+ This call also releases all associated resources.
+
+ @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure.
+
+ @return the result of mbg_thread_stop()
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_time_as_filetime()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_stop( MBG_POLL_THREAD_INFO *p_pti ) ;
+
+ /**
+ @brief Retrieve an extrapolated time stamp in PCPS_HR_TIME format.
+
+ The time stamp is extrapolated using the system's current cycles counter value
+ and a time stamp plus associated cycles counter value saved by the polling thread.
+ See mbg_xhrt_poll_thread_fnc() for details and limitations.
+
+ This function is only implemented for targets which support threads.
+
+ @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread.
+ @param *p_hrt Pointer to a ::PCPS_HR_TIME structure to be filled up.
+
+ @return MBG_SUCCESS or another return value from the polling thread's IOCTL call.
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_filetime()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_pcps_hr_time( MBG_XHRT_INFO *p, PCPS_HR_TIME *p_hrt ) ;
+
+ /**
+ @brief Retrieve an extrapolated time stamp in FILETIME format.
+
+ The time stamp is extrapolated using the system's current cycles counter value
+ and a time stamp plus associated cycles counter value saved by the polling thread.
+ See mbg_xhrt_poll_thread_fnc() for details and limitations.
+
+ Since FILETIME is a Windows specific type this function is only
+ implemented under Windows.
+
+ @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread.
+ @param *p_ft Pointer to a ::FILETIME structure to be filled up.
+
+ @return MBG_SUCCESS or another return value from the polling thread's IOCTL call.
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_filetime( MBG_XHRT_INFO *p, FILETIME *p_ft ) ;
+
+ /**
+ @brief Retrieve the frequency of the system's cycles counter.
+
+ The frequency is determined by the device polling thread.
+ See mbg_xhrt_poll_thread_fnc() for details and limitations.
+
+ This function is only implemented for targets which support threads.
+
+ @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread.
+ @param *p_freq_hz Pointer to a ::MBG_PC_CYCLES_FREQUENCY variable in which the frequency is returned.
+ @return a status code from the polling thread: MBG_SUCCESS or an IOCTL error code.
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_time_as_filetime()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_cycles_frequency( MBG_XHRT_INFO *p, MBG_PC_CYCLES_FREQUENCY *p_freq_hz ) ;
+
+ /**
+ @brief Retrieve the default system's cycles counter frequency from the kernel driver.
+
+ This API call can be used on systems which don't provide this information in user space.
+
+ @param dh handle of the device to which the IOCTL call is sent.
+ @param *p Pointer of a ::MBG_PC_CYCLES_FREQUENCY variable to be filled up.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_default_cycles_frequency()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_default_cycles_frequency_from_dev( MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p ) ;
+
+ /**
+ @brief Retrieve the system's default cycles counter frequency.
+
+ @note This may not be supported on all target platforms, in which case the
+ returned frequency is 0 and the mbg_get_default_cycles_frequency_from_dev()
+ call should be used.
+
+ @return the default cycles counter frequency in Hz, or 0 if the value is not available.
+
+ @see mbg_get_default_cycles_frequency_from_dev()
+*/
+ _MBG_API_ATTR MBG_PC_CYCLES_FREQUENCY _MBG_API mbg_get_default_cycles_frequency( void ) ;
+
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( MBG_TGT_WIN32 )
+
+static __mbg_inline
+MBGDEVIO_RET_VAL do_mbg_ioctl( MBG_DEV_HANDLE dh, int ioctl_code,
+ const void *in_p, int in_sz, void *out_p, int out_sz )
+{
+ DWORD ReturnedLength;
+
+ if ( !DeviceIoControl( dh, ioctl_code,
+ (LPVOID) in_p, in_sz, out_p, out_sz,
+ &ReturnedLength,
+ NULL
+ ) )
+ {
+ DWORD rc = GetLastError();
+
+#if 0 //##++++++++++++++++++++++++
+// We can't call mbgsvctl_log_mbgdevio_error() here (for now).
+// Is is defined in mbgsvctl.h, and including mbgsvc.h here,
+// or copying the prototype here results in DLL import/export
+// mismatch errors.
+
+ // do not report a USB device timeout error
+ if ( rc != _mbg_err_to_os( MBG_ERR_USB_ACCESS ) )
+ mbgsvctl_log_mbgdevio_error( ioctl_code, rc );
+#endif
+
+ return rc;
+ }
+
+ return MBG_SUCCESS;
+
+} // do_mbg_ioctl
+
+ #define _do_mbg_ioctl( _dh, _ioctl, _p, _in_sz, _out_sz ) \
+ do_mbg_ioctl( _dh, _ioctl, (LPVOID) _p, _in_sz, (LPVOID) _p, _out_sz )
+
+#elif defined( MBG_TGT_UNIX )
+
+ #define _do_mbg_ioctl( _dh, _ioctl, _p, _in_sz, _out_sz ) \
+ ioctl( _dh, _ioctl, _p )
+
+#endif
+
+
+
+// The code below depends on whether the target device is accessed via
+// IOCTLs to a device driver, or the hardware is accessed directly.
+
+#if defined( MBG_USE_KERNEL_DRIVER ) // using IOCTL to access device driver
+
+/**
+ @brief Send a generic IOCTL command to the driver.
+
+ @param dh Valid handle to a Meinberg device
+ @param info Additional information for the kernel driver depending on
+ the IOCTL code, i.e. the low level function to be called: <br>
+ one of the PCPS_... commands with IOCTL_PCPS_GENERIC_{READ|WRITE}<br>
+ one of the PC_GPS_... commands with IOCTL_PCPS_GENERIC_{READ|WRITE}_GPS<br>
+ one of the PCPS_GEN_IO_... enumeration codes with IOCTL_PCPS_GENERIC_IO
+ @param ioctl One of the IOCTL_GENERIC_... codes telling the kernel driver
+ which low level function to use, e.g. normal read or write,
+ large (GPS) data read or write, or generic I/O.
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ static __mbg_inline
+ int mbgdevio_do_gen_io( MBG_DEV_HANDLE dh, int info, unsigned int ioctl_code,
+ const void *in_p, int in_sz,
+ void *out_p, int out_sz )
+ {
+ _mbgdevio_vars();
+
+ // Generic IOCTL calls always need to pass some info beside
+ // the I/O buffers down to the driver, which usually is
+ // the command code for the device.
+ // Thus we must always use one of the control structures
+ // IOCTL_GENERIC_REQ or IOCTL_GENERIC_BUFFER, whichever
+ // is appropriate for the target OS.
+
+ #if USE_IOCTL_GENERIC_REQ
+
+ IOCTL_GENERIC_REQ req = { 0 };
+
+ req.info = info;
+ req.in_p = in_p;
+ req.in_sz = in_sz;
+ req.out_p = out_p;
+ req.out_sz = out_sz;
+
+ rc = _do_mbg_ioctl( dh, ioctl_code, &req, sizeof( req ), 0 );
+
+ #else
+
+ IOCTL_GENERIC_BUFFER *p_buff;
+ int buff_size = sizeof( p_buff->ctl )
+ + ( ( in_sz > out_sz ) ? in_sz : out_sz );
+
+ p_buff = (IOCTL_GENERIC_BUFFER *) malloc( buff_size );
+
+ if ( p_buff == NULL )
+ return _mbg_err_to_os( MBG_ERR_NO_MEM );
+
+ p_buff->ctl.info = info;
+ p_buff->ctl.data_size_in = in_sz;
+ p_buff->ctl.data_size_out = out_sz;
+
+ if ( in_p )
+ memcpy( p_buff->data, in_p, in_sz );
+
+ rc = _do_mbg_ioctl( dh, ioctl_code, p_buff,
+ sizeof( IOCTL_GENERIC_CTL ) + in_sz,
+ sizeof( IOCTL_GENERIC_CTL ) + out_sz );
+
+ if ( out_p && ( rc == MBG_SUCCESS ) )
+ memcpy( out_p, p_buff->data, out_sz );
+
+ free( p_buff );
+
+ #endif
+
+ return _mbgdevio_ret_val;
+
+ } // mbgdevio_do_gen_io
+
+
+
+ #define _do_mbgdevio_read( _dh, _cmd, _ioctl, _p, _sz ) \
+ _do_mbg_ioctl( _dh, _ioctl, _p, 0, _sz )
+
+ #define _do_mbgdevio_write( _dh, _cmd, _ioctl, _p, _sz ) \
+ _do_mbg_ioctl( _dh, _ioctl, _p, _sz, 0 )
+
+ #define _do_mbgdevio_read_gps _do_mbgdevio_read
+
+ #define _do_mbgdevio_write_gps _do_mbgdevio_write
+
+
+
+ #define _mbgdevio_read_var( _dh, _cmd, _ioctl, _p ) \
+ _do_mbgdevio_read( _dh, _cmd, _ioctl, _p, sizeof( *(_p) ) )
+
+ #define _mbgdevio_write_var( _dh, _cmd, _ioctl, _p ) \
+ _do_mbgdevio_write( _dh, _cmd, _ioctl, _p, sizeof( *(_p) ) )
+
+ #define _mbgdevio_write_cmd( _dh, _cmd, _ioctl ) \
+ _do_mbgdevio_write( _dh, _cmd, _ioctl, NULL, 0 )
+
+ #define _mbgdevio_read_gps_var _mbgdevio_read_var
+
+ #define _mbgdevio_write_gps_var _mbgdevio_write_var
+
+
+ #define _mbgdevio_gen_read( _dh, _cmd, _p, _sz ) \
+ mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_READ, NULL, 0, _p, _sz )
+
+ #define _mbgdevio_gen_write( _dh, _cmd, _p, _sz ) \
+ mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_WRITE, _p, _sz, NULL, 0 )
+
+ #define _mbgdevio_gen_io( _dh, _type, _in_p, _in_sz, _out_p, _out_sz ) \
+ mbgdevio_do_gen_io( _dh, _type, IOCTL_PCPS_GENERIC_IO, _in_p, _in_sz, _out_p, _out_sz )
+
+ #define _mbgdevio_gen_read_gps( _dh, _cmd, _p, _sz ) \
+ mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_READ_GPS, NULL, 0, _p, _sz )
+
+ #define _mbgdevio_gen_write_gps( _dh, _cmd, _p, _sz ) \
+ mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_WRITE_GPS, _p, _sz, NULL, 0 )
+
+
+#else // accessing hardware device directly
+
+ #define _mbgdevio_chk_cond( _cond ) \
+ { \
+ if ( !(_cond) ) \
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); \
+ }
+
+ #define _mbgdevio_read( _dh, _cmd, _ioctl, _p, _sz ) \
+ pcps_read_safe( _dh, _cmd, _p, _sz )
+
+ #define _mbgdevio_write( _dh, _cmd, _ioctl, _p, _sz ) \
+ pcps_write_safe( _dh, _cmd, _p, _sz )
+
+ #define _do_mbgdevio_read_gps( _dh, _cmd, _ioctl, _p, _sz ) \
+ pcps_read_gps_safe( _dh, _cmd, _p, _sz )
+
+ #define _mbgdevio_write_gps( _dh, _cmd, _ioctl, _p, _sz ) \
+ pcps_write_gps_safe( _dh, _cmd, _p, _sz )
+
+
+
+//##+++++++++++++++++++
+ #define _mbgdevio_read_var( _dh, _cmd, _ioctl, _p ) \
+ _pcps_read_var_safe( _dh, _cmd, *(_p) )
+
+ #define _mbgdevio_write_var( _dh, _cmd, _ioctl, _p ) \
+ _pcps_write_var_safe( _dh, _cmd, *(_p) )
+
+ #define _mbgdevio_write_cmd( _dh, _cmd, _ioctl ) \
+ _pcps_write_byte_safe( _dh, _cmd );
+
+ #define _mbgdevio_read_gps_var( _dh, _cmd, _ioctl, _p ) \
+ _pcps_read_gps_var_safe( _dh, _cmd, *(_p) )
+
+ #define _mbgdevio_write_gps_var( _dh, _cmd, _ioctl, _p ) \
+ _pcps_write_gps_var_safe( _dh, _cmd, *(_p) )
+
+
+ #define _mbgdevio_gen_read( _dh, _cmd, _p, _sz ) \
+ _mbgdevio_read( _dh, _cmd, -1, _p, _sz )
+
+ #define _mbgdevio_gen_write( _dh, _cmd, _p, _sz ) \
+ _mbgdevio_write( _dh, _cmd, -1, _p, _sz )
+
+ #define _mbgdevio_gen_io( _dh, _type, _in_p, _in_sz, _out_p, _out_sz ) \
+ pcps_generic_io( _dh, _type, _in_p, _in_sz, _out_p, _out_sz );
+
+ #define _mbgdevio_gen_read_gps( _dh, _cmd, _p, _sz ) \
+ _do_mbgdevio_read_gps( _dh, _cmd, -1, _p, _sz )
+
+ #define _mbgdevio_gen_write_gps( _dh, _cmd, _p, _sz ) \
+ _mbgdevio_write_gps( _dh, _cmd, -1, _p, _sz )
+
+#endif
+
+
+
+#define _mbg_generic_read_var( _dh, _cmd, _s ) \
+ mbg_generic_read( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+#define _mbg_generic_write_var( _dh, _cmd, _s ) \
+ mbg_generic_write( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+#define _mbg_generic_read_gps_var( _dh, _cmd, _s ) \
+ mbg_generic_read_gps( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+#define _mbg_generic_write_gps_var( _dh, _cmd, _s ) \
+ mbg_generic_write_gps( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+
+
+#define _mbgdevio_gen_read_var( _dh, _cmd, _s ) \
+ _mbgdevio_gen_read( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+#define _mbgdevio_gen_write_var( _dh, _cmd, _s ) \
+ _mbgdevio_gen_write( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+#define _mbgdevio_gen_read_gps_var( _dh, _cmd, _s ) \
+ _mbgdevio_gen_read_gps( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+#define _mbgdevio_gen_write_gps_var( _dh, _cmd, _s ) \
+ _mbgdevio_gen_write_gps( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+
+
+#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX )
+
+static __mbg_inline
+void mbg_chk_tstamp64_leap_sec( uint64_t *tstamp64, PCPS_TIME_STATUS_X *status )
+{
+ if ( *status & ( PCPS_LS_ANN | PCPS_LS_ENB ) )
+ {
+ time_t t = (uint32_t) ( *tstamp64 >> 32 );
+ struct tm tm = *gmtime( &t );
+
+ // Handle leap second and status
+ if ( tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0 )
+ {
+ if ( *status & PCPS_LS_ANN )
+ {
+ // Set leap second enabled flag on rollover to the leap second and clear announce flag
+ *status &= ~PCPS_LS_ANN;
+ *status |= PCPS_LS_ENB;
+
+ // Decrement interpolated second to avoid automated overflow during the leap second.
+ // Second 59 appears for the second time.
+ *tstamp64 -= PCPS_HRT_BIN_FRAC_SCALE;
+ }
+ else
+ if ( *status & PCPS_LS_ENB ) // Clear bits when leap second expires and 0:00:00 UTC is reached
+ *status &= ~( PCPS_LS_ANN | PCPS_LS_ENB );
+ }
+ }
+
+} // mbg_chk_tstamp64_leap_sec
+
+#endif // defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX )
+
+
+
+static __mbg_inline
+void mbg_init_pc_cycles_frequency( MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p )
+{
+ if ( *p == 0 )
+ mbg_get_default_cycles_frequency_from_dev( dh, p );
+
+} // mbg_init_pc_cycles_frequency
+
+
+
+#if MBG_TGT_HAS_64BIT_TYPES
+
+static __mbg_inline
+uint64_t pcps_time_stamp_to_uint64( const PCPS_TIME_STAMP *ts )
+{
+ return ( ( (uint64_t) ts->sec ) << 32 ) + ts->frac;
+
+} // pcps_time_stamp_to_uint64
+
+
+
+static __mbg_inline
+void uint64_to_pcps_time_stamp( PCPS_TIME_STAMP *ts, uint64_t n )
+{
+ ts->sec = (uint32_t) ( n >> 32 );
+ ts->frac = (uint32_t) ( n & 0xFFFFFFFFUL );
+
+} // uint64_to_pcps_time_stamp
+
+#endif
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+
+#undef _ext
+
+#endif /* _MBGDEVIO_H */
+
diff --git a/mbglib/common/mbgerror.h b/mbglib/common/mbgerror.h
new file mode 100644
index 0000000..f15878d
--- /dev/null
+++ b/mbglib/common/mbgerror.h
@@ -0,0 +1,172 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgerror.h 1.6 2012/10/02 18:42:26Z martin REL_M $
+ * $Name: $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Error codes used with Meinberg devices and drivers.
+ * The codes can be translated into an OS dependent error code.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgerror.h $
+ * Revision 1.6 2012/10/02 18:42:26Z martin
+ * New codes MBG_ERR_N_POUT_EXCEEDS_SUPP and
+ * MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP.
+ * Modified comments for doxygen.
+ * Revision 1.5 2011/03/31 10:56:17 martin
+ * Added MBG_ERR_COPY_TO_USER and MBG_ERR_COPY_FROM_USER.
+ * Revision 1.4 2008/12/05 13:28:50 martin
+ * Added new code MBG_ERR_IRQ_UNSAFE.
+ * Revision 1.3 2008/02/26 14:50:14Z daniel
+ * Added codes:
+ * MBG_ERR_NOT_SUPP_ON_OS, MBG_ERR_LIB_NOT_COMPATIBLE,
+ * MBG_ERR_N_COM_EXCEEDS_SUPP, MBG_ERR_N_STR_EXCEEDS_SUPP
+ * Added doxygen compatible comments.
+ * Revision 1.2 2007/09/27 07:26:22Z martin
+ * Define STATUS_SUCCESS for Windows if not in kernel mode.
+ * Revision 1.1 2007/09/26 08:08:54Z martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _MBGERROR_H
+#define _MBGERROR_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+
+#ifdef _MBGERROR
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+/**
+ @defgroup group_error_codes Error codes
+
+ Error codes used with Meinberg devices and drivers.
+ The codes will be translated into an OS dependent error code,
+ when they are returned to the calling function.
+
+ For Windows, these codes are made positive and or'ed with 0xE0000000 afterwards.
+
+ Example: Code -19 (#MBG_ERR_GENERIC) will be converted to 0xE0000013 under Windows.
+
+ @note Attention:
+ These error codes below must match exactly the corresponding codes that are evaluated in user space.
+ For Windows, they are located in messages.mc/.h in mbgsvctl.dll
+
+ @{
+*/
+
+
+#define MBG_SUCCESS PCPS_SUCCESS /**< 0, no error */
+
+// The codes below are defined in pcpsdefs.h and returned by the firmware:
+#define MBG_ERR_STIME PCPS_ERR_STIME /**< -1, invalid date/time/status passed */
+#define MBG_ERR_CFG PCPS_ERR_CFG /**< -2, invalid parms with a PCPS_CFG_GROUP cmd */
+
+// Codes returned by the driver's low level functions:
+#define MBG_ERR_GENERIC -19 /**< Generic error */
+#define MBG_ERR_TIMEOUT -20 /**< Timeout accessing the board */
+#define MBG_ERR_FW_ID -21 /**< Invalid firmware ID */
+#define MBG_ERR_NBYTES -22 /**< The number of parameter bytes
+ passed to the board did not match
+ the number of bytes expected. */
+#define MBG_ERR_INV_TIME -23 /**< The device's time is not valid */
+#define MBG_ERR_FIFO -24 /**< The device's FIFO is empty, though
+ it shouldn't be */
+#define MBG_ERR_NOT_READY -25 /**< Board is temporary unable to respond
+ (during initialization after RESET) */
+#define MBG_ERR_INV_TYPE -26 /**< Board did not recognize data type */
+
+
+// Codes returned by the driver's high level functions:
+#define MBG_ERR_NO_MEM -27 /**< Failed to allocate memory */
+#define MBG_ERR_CLAIM_RSRC -28 /**< Failed to claim port or mem resource */
+#define MBG_ERR_DEV_NOT_SUPP -29 /**< Specified device type not supported by driver */
+#define MBG_ERR_INV_DEV_REQUEST -30 /**< IOCTL call not supported by driver */
+#define MBG_ERR_NOT_SUPP_BY_DEV -31 /**< Cmd or feature not supported by device */
+#define MBG_ERR_USB_ACCESS -32 /**< USB access failed */
+#define MBG_ERR_CYCLIC_TIMEOUT -33 /**< Cyclic event (IRQ, etc.) didn't occur */
+#define MBG_ERR_NOT_SUPP_ON_OS -34 /**< The function is not supported on this operating system */
+#define MBG_ERR_LIB_NOT_COMPATIBLE -35 /**< The installed version of the DLL/shared object is not
+ compatible with version used to build the application */
+#define MBG_ERR_N_COM_EXCEEDS_SUPP -36 /**< The number of COM ports provided by the device
+ exceeds the maximum supported by the driver */
+#define MBG_ERR_N_STR_EXCEEDS_SUPP -37 /**< The number of string formats supported by the device
+ exceeds the maximum supported by the driver */
+#define MBG_ERR_IRQ_UNSAFE -38 /**< The enabled IRQs are unsafe with this firmware/ASIC version */
+#define MBG_ERR_N_POUT_EXCEEDS_SUPP -39 /**< The number of programmable outputs provided by the device
+ exceeds the maximum supported by the driver */
+
+// Legacy codes used with DOS TSRs only:
+#define MBG_ERR_INV_INTNO -40 /**< Invalid interrupt number */
+#define MBG_ERR_NO_DRIVER -41 /**< A driver could not be found */
+#define MBG_ERR_DRV_VERSION -42 /**< The driver is too old */
+
+
+#define MBG_ERR_COPY_TO_USER -43 /**< kernel driver failed to copy data from kernel to user space */
+#define MBG_ERR_COPY_FROM_USER -44 /**< kernel driver failed to copy data from use to kernel space */
+
+// More codes returned by the driver's high level functions:
+
+#define MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP -39 /**< The number of PTP unicast masters supported by the device
+ exceeds the maximum supported by the driver */
+/** @} group_error_codes */
+
+// Depending on the operating system, the codes above have to be converted before
+// they are sent up to user space
+#if defined( MBG_TGT_WIN32 )
+ #if !defined( STATUS_SUCCESS ) // not in kernel mode
+ #define STATUS_SUCCESS 0
+ #endif
+
+ #define _mbg_err_to_os( _c ) \
+ ( ( _c == MBG_SUCCESS ) ? STATUS_SUCCESS : ( abs( _c ) | 0xE0000000 ) )
+#endif
+
+
+// If no specific conversion has been defined
+// then use the original codes.
+#if !defined( _mbg_err_to_os )
+ #define _mbg_err_to_os( _c ) ( _c )
+#endif
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _MBGERROR_H */
diff --git a/mbglib/common/mbggeo.h b/mbglib/common/mbggeo.h
new file mode 100644
index 0000000..c3bdb40
--- /dev/null
+++ b/mbglib/common/mbggeo.h
@@ -0,0 +1,301 @@
+
+/**************************************************************************
+ *
+ * $Id: mbggeo.h 1.11 2011/06/22 10:18:10Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for mbggeo.c.
+ *
+ * Terms used:
+ *
+ * WGS84 world geodetic system of 1984
+ *
+ * XYZ WGS84 earth centered, earth fixed (ECEF) kartesian
+ * coordinates
+ *
+ * LLA longitude, latitude, altitude depending on the reference
+ * ellipsoid used.
+ *
+ * DMS degrees, minutes, seconds
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbggeo.h $
+ * Revision 1.11 2011/06/22 10:18:10Z martin
+ * Cleaned up handling of pragma pack().
+ * Revision 1.10 2008/09/03 14:54:28 martin
+ * Added macros to swap endianess of structures.
+ * Revision 1.9 2008/01/17 09:31:33 daniel
+ * Made comments compatible for doxygen parser.
+ * No sourcecode changes.
+ * Revision 1.8 2004/11/09 14:16:00Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Revision 1.7 2003/02/14 13:23:04Z martin
+ * Omit inclusion of mystd.h.
+ * Revision 1.6 2003/01/13 15:17:15 martin
+ * Structures were defined with default alignment which
+ * could result in different data sizes on different platforms.
+ * Revision 1.5 2002/12/18 14:46:41Z martin
+ * Removed variable USER_POS meinberg.
+ * Updated function prototypes.
+ * Revision 1.4 2002/12/12 12:04:25Z martin
+ * Moved some definitions here.
+ * Use standard file format.
+ *
+ **************************************************************************/
+
+#ifndef _MBGGEO_H
+#define _MBGGEO_H
+
+
+/* Other headers to be included */
+
+#include <gpsdefs.h>
+#include <use_pack.h>
+
+#ifdef _MBGGEO
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+
+/**
+ Geographic longitude or latitude in [degrees, minutes, seconds]
+ longitude East latitude North and positve, South or West angles negative
+ */
+typedef struct
+{
+ uint16_t prefix; /**< 'N', 'E', 'S' or 'W' */
+ uint16_t deg; /**< [0...90 (lat) or 0...180 (lon)] */
+ uint16_t min; /**< [0...59] */
+ double sec; /**< [0...59.999] */
+} DMS;
+
+// The corresponding macro _mbg_swab_dms() is defined in gpsdefs.h.
+#define _mbg_swab_dms( _p ) \
+{ \
+ _mbg_swab16( &(_p)->prefix ); \
+ _mbg_swab16( &(_p)->deg ); \
+ _mbg_swab16( &(_p)->min ); \
+ _mbg_swab_double( &(_p)->sec ); \
+}
+
+
+
+typedef struct
+{
+ XYZ xyz; /**< always WGS84 ECEF coordinates */
+ LLA lla; /**< depending on the ellipsoid used for reference */
+ DMS longitude; /**< longitude in degrees, minutes, seconds */
+ DMS latitude; /**< latitude in degrees, minutes, seconds */
+ int16_t ellipsoid; /**< ellipsoid used for reference */
+} POS;
+
+#define _mbg_swab_pos( _p ) \
+{ \
+ _mbg_swab_xyz( (_p)->xyz ); \
+ _mbg_swab_lla( (_p)->lla ); \
+ _mbg_swab_dms( &(_p)->longitude ); \
+ _mbg_swab_dms( &(_p)->latitude ); \
+ _mbg_swab16( &(_p)->ellipsoid ); \
+}
+
+
+
+typedef struct
+{
+ CSUM csum; /* checksum of the remaining bytes */
+ int16_t valid; /* flag data are valid */
+
+ char name[40];
+ POS pos; /* the position in WGS84 ECEF coords and LLA */
+ double det;
+
+
+/* The components below hold the results of intermediate terms */
+/* computed in complete_user_pos(). */
+
+/* The sin.., cos.., nt.. and ut.. variables are used to compute the */
+/* enu_dcos[] parameters of a SV structure in xyz_to_ead(). */
+
+/* The e_radius.. variables are used to compute the latitude, longitude */
+/* and altitude from ECEF coordinates in lla_to_xyz(). */
+
+ double sin_lat; /* sin( latitude ) */
+ double cos_lat; /* cos( latitude ) */
+ double sin_lon; /* sin( longitude ) */
+ double cos_lon; /* cos( longitude ) */
+
+ double nt1; /* -sin_lat * cos_lon */
+ double nt2; /* -sin_lat * sin_lon */
+ double utx; /* cos_lat * cos_lon */
+ double uty; /* cos_lat * sin_lon */
+
+ double e_radius; /* N */
+ double e_radius_alt; /* N + h */
+
+} USER_POS;
+
+
+
+typedef struct
+{
+ CSUM csum; /* checksum of the remaining bytes */
+ int16_t valid; /* flag data are valid */
+
+ char name[40];
+ XYZ dxyz; /* offset from the WGS84 ECEF coords */
+ double a; /* semi major axis */
+ double rcp_f; /* reciproke of flatness */
+
+/* the variables below will be computed in the init_mbggeo() function: */
+
+ double f; /* flatness */
+ double b; /* semi minor axis */
+ double sqr_e; /* square of numerical eccentricity */
+} ELLIPSOID;
+
+
+
+enum { WGS84, BESSEL, N_ELLIPSOIDS };
+
+_ext ELLIPSOID ellipsoid[N_ELLIPSOIDS]
+#ifdef _DO_INIT
+ = { { 0, 0,
+ "WGS 84",
+ { 0.0, 0.0, 0.0 },
+ 6378137.0,
+ 298.257223563
+ },
+
+ { 0, 0,
+ "Bessel",
+ { -128.0, 481.0, 664.0 },
+ 6377397.0,
+ 299.15
+ }
+
+ }
+#endif
+;
+
+
+/* WGS84 constants used */
+
+_ext double OMEGADOTe /* earth's rotation rate [rad/sec] */
+#ifdef _DO_INIT
+ = 7.2921151467e-5
+#endif
+;
+
+_ext double mue /* earth's gravitational constant [m^3/sec^2] */
+#ifdef _DO_INIT
+ = 3.986005e14
+#endif
+;
+
+
+
+_ext double vr_to_doppler;
+
+
+_ext double gps_pi
+#ifdef _DO_INIT
+ = 3.1415926535898
+#endif
+;
+
+_ext double gps_c0
+#ifdef _DO_INIT
+ = 2.99792458e8
+#endif
+;
+
+
+#ifndef PI
+ #define PI 3.1415926535897932
+#endif
+
+
+_ext double pi
+#ifdef _DO_INIT
+ = PI
+#endif
+;
+
+
+_ext double r2d
+#ifdef _DO_INIT
+ = 180.0 / PI
+#endif
+;
+
+
+_ext double d2r
+#ifdef _DO_INIT
+ = PI / 180.0
+#endif
+;
+
+
+/* variables for simplifying computations */
+
+_ext double gps_two_pi;
+_ext double sqrt_mue; /* sqrt( mue ) */
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ void dms_to_rad( const DMS *dms, double *rad ) ;
+ void rad_to_dms( const double *rad, DMS *dms, const char prefix ) ;
+ void dms_to_lla( POS *pos ) ;
+ void lla_to_dms( POS *pos ) ;
+ void lla_to_xyz( USER_POS *pos ) ;
+ void xyz_to_lla( POS *pos, void (*cyclic_func)( void ) ) ;
+ void dms_to_xyz( USER_POS *pos ) ;
+ void setup_user_pos_from_dms( USER_POS *user ) ;
+ void setup_user_pos_from_lla( USER_POS *user ) ;
+ void setup_user_pos_from_xyz( USER_POS *user, void (*cyclic_func)( void ) ) ;
+ double distance( XYZ xyz_1, XYZ xyz_2 ) ;
+ void init_mbggeo( void ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _MBGGEO_H */
+
diff --git a/mbglib/common/mbgmutex.h b/mbglib/common/mbgmutex.h
new file mode 100644
index 0000000..86fd058
--- /dev/null
+++ b/mbglib/common/mbgmutex.h
@@ -0,0 +1,259 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgmutex.h 1.2 2012/03/08 12:19:01Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Portable macros to deal with spinlocks, mutexes,
+ * and critical sections.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgmutex.h $
+ * Revision 1.2 2012/03/08 12:19:01Z martin
+ * Fixes for Linux kernel and FreeBSD.
+ * Fixed build under DOS and QNX usinc dummy defines.
+ * Don't define macros for semaphore destroy functions
+ * if not required/supported on the target OS.
+ * Revision 1.1 2011/04/15 12:26:59 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _MBGMUTEX_H
+#define _MBGMUTEX_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+#include <words.h>
+
+#ifdef _MBGMUTEX
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( MBG_TGT_KERNEL ) // definitions used in kernel space
+
+ #if defined( MBG_TGT_WIN32 ) // Windows kernel space
+
+ typedef KSPIN_LOCK MBG_SPINLOCK;
+ #define _mbg_spin_lock_init( _spl ) KeInitializeSpinLock( _spl )
+ // _mbg_spin_lock_destroy is not supported
+ #define _mbg_spin_lock_acquire( _spl ) KeAcquireSpinLockAtDpcLevel( _spl )
+ #define _mbg_spin_lock_release( _spl ) KeReleaseSpinLockFromDpcLevel( _spl )
+
+ #define _MBG_SPINLOCK_DEFINED 1
+
+
+ typedef FAST_MUTEX MBG_MUTEX;
+ #define _mbg_mutex_init( _pmtx ) ExInitializeFastMutex( _pmtx )
+ // _mbg_mutex_destroy( _pmtx ) is not supported
+ #define _mbg_mutex_acquire( _pmtx ) ExAcquireFastMutex( _pmtx )
+ #define _mbg_mutex_release( _pmtx ) ExReleaseFastMutex( _pmtx )
+
+ #define _MBG_MUTEX_DEFINED 1
+
+ #elif defined( MBG_TGT_LINUX ) // Linux kernel space
+
+ #include <linux/spinlock.h>
+ #include <linux/version.h>
+
+ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 26 ) )
+ #include <linux/semaphore.h>
+ #else
+ #include <asm/semaphore.h>
+ #endif
+
+ typedef spinlock_t MBG_SPINLOCK;
+ #define _mbg_spin_lock_init( _spl ) spin_lock_init( _spl )
+ // _mbg_spin_lock_destroy is not supported
+ #define _mbg_spin_lock_acquire( _spl ) spin_lock( _spl )
+ #define _mbg_spin_lock_release( _spl ) spin_unlock( _spl )
+
+ #define _MBG_SPINLOCK_DEFINED 1
+
+
+ typedef struct semaphore MBG_MUTEX;
+ #define _mbg_mutex_init( _pmtx ) sema_init( _pmtx, 1 )
+ // _mbg_mutex_destroy( _pmtx ) is not supported
+ #define _mbg_mutex_acquire( _pmtx ) down_interruptible( _pmtx )
+ #define _mbg_mutex_release( _pmtx ) up( _pmtx )
+
+ #define _MBG_MUTEX_DEFINED 1
+
+ #elif defined( MBG_TGT_FREEBSD ) // FreeBSD kernel space
+
+ #include <sys/lock.h>
+ #include <sys/mutex.h>
+
+ typedef struct mtx MBG_SPINLOCK;
+ #define _mbg_spin_lock_init( _spl ) mtx_init( _spl, "mbg_spin_lock", NULL, MTX_SPIN )
+ #define _mbg_spin_lock_destroy( _spl ) mtx_destroy( _spl )
+ #define _mbg_spin_lock_acquire( _spl ) mtx_lock_spin( _spl )
+ #define _mbg_spin_lock_release( _spl ) mtx_unlock_spin( _spl )
+
+ #define _MBG_SPINLOCK_DEFINED 1
+
+
+ typedef struct mtx MBG_MUTEX;
+ #define _mbg_mutex_init( _pmtx ) mtx_init( _pmtx, "mbg_mutex", NULL, MTX_DEF )
+ #define _mbg_mutex_destroy( _pmtx ) mtx_destroy( _pmtx )
+ #define _mbg_mutex_acquire( _pmtx ) mtx_lock( _pmtx )
+ #define _mbg_mutex_release( _pmtx ) mtx_unlock( _pmtx )
+
+ #define _MBG_MUTEX_DEFINED 1
+
+ #elif defined( MBG_TGT_NETBSD )
+
+ #include <sys/mutex.h>
+
+ // The API used below has been introduced in NetBSD 5.0
+ // For earlier NetBSD versions see 'man 9 lockinit'.
+
+ typedef kmutex_t MBG_SPINLOCK;
+ #define _mbg_spin_lock_init( _spl ) mutex_init( _spl, MUTEX_DEFAULT, IPL_HIGH )
+ #define _mbg_spin_lock_destroy( _spl ) mutex_destroy( _spl )
+ #define _mbg_spin_lock_acquire( _spl ) mutex_spin_enter( _spl )
+ #define _mbg_spin_lock_release( _spl ) mutex_spin_exit( _spl )
+
+ #define _MBG_SPINLOCK_DEFINED 1
+
+
+ typedef kmutex_t MBG_MUTEX;
+ #define _mbg_mutex_init( _pmtx ) mutex_init( _pmtx, MUTEX_DEFAULT, IPL_NONE )
+ #define _mbg_mutex_destroy( _spl ) mutex_destroy( _spl )
+ #define _mbg_mutex_acquire( _pmtx ) mutex_enter( _pmtx )
+ #define _mbg_mutex_release( _pmtx ) mutex_exit( _pmtx )
+
+ #define _MBG_MUTEX_DEFINED 1
+
+ #endif
+
+#else // user space applications
+
+ #if defined( MBG_TGT_WIN32 ) // Windows user space
+
+ #include <windows.h>
+
+ // definitions used with mutexes
+ typedef HANDLE MBG_MUTEX;
+ #define _mbg_mutex_init( _pm ) *(_pm) = CreateMutex( NULL, FALSE, NULL )
+ #define _mbg_mutex_destroy( _pm ) CloseHandle( *(_pm) ); *(_pm) = INVALID_HANDLE_VALUE
+ #define _mbg_mutex_acquire( _pm ) WaitForSingleObject( *(_pm), INFINITE )
+ #define _mbg_mutex_release( _pm ) ReleaseMutex( *(_pm) )
+
+ #define _MBG_MUTEX_DEFINED 1
+
+ // definitions used with critical sections
+ typedef CRITICAL_SECTION MBG_CRIT_SECT;
+ #define _mbg_crit_sect_init( _pcs ) InitializeCriticalSection( (_pcs) )
+ #define _mbg_crit_sect_destroy( _pcs ) DeleteCriticalSection( (_pcs) )
+ #define _mbg_crit_sect_enter( _pcs ) EnterCriticalSection( (_pcs) )
+ #define _mbg_crit_sect_leave( _pcs ) LeaveCriticalSection( (_pcs) )
+
+ #define _MBG_CRIT_SECT_DEFINED 1
+
+ #elif defined( MBG_TGT_UNIX ) // Unix user space use pthread library
+
+ #include <pthread.h>
+
+ // Mutex types:
+ // PTHREAD_MUTEX_INITIALIZER /* Fast */
+ // PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP /* Recursive */
+ // PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP /* Errorcheck */
+ typedef pthread_mutex_t MBG_MUTEX;
+ #define _mbg_mutex_init( _pm ) pthread_mutex_init( (_pm), NULL )
+ #define _mbg_mutex_destroy( _pm ) pthread_mutex_destroy( (_pm) )
+ #define _mbg_mutex_acquire( _pm ) pthread_mutex_lock( (_pm) )
+ #define _mbg_mutex_release( _pm ) pthread_mutex_unlock( (_pm) )
+
+ #define _MBG_MUTEX_DEFINED 1
+
+ // For critical sections use defaults specified below
+
+ #elif defined( MBG_TGT_DOS ) || defined( MBG_TGT_QNX )
+
+ typedef int MBG_MUTEX; // just a dummy declaration
+
+ #define _MBG_MUTEX_DEFINED 1
+
+ #endif
+
+#endif
+
+
+#if !defined( _MBG_SPINLOCK_DEFINED )
+
+ #define _mbg_spin_lock_init( _spl ) _nop_macro_fnc()
+ // _mbg_spin_lock_destroy is not supported
+ #define _mbg_spin_lock_acquire( _spl ) _nop_macro_fnc()
+ #define _mbg_spin_lock_release( _spl ) _nop_macro_fnc()
+
+#endif
+
+
+#if !defined( _MBG_MUTEX_DEFINED )
+
+ #define _MBG_MUTEX_DEFINED 1
+
+ typedef MBG_CRIT_SECT MBG_MUTEX;
+
+ #define _mbg_mutex_init( _pm ) _nop_macro_fnc()
+ // _mbg_mutex_destroy( _pmtx ) is not supported
+ #define _mbg_mutex_acquire( _pm ) _nop_macro_fnc()
+ #define _mbg_mutex_release( _pm ) _nop_macro_fnc()
+
+#endif
+
+
+#if !defined( _MBG_CRIT_SECT_DEFINED )
+
+ // use mutex by default, e.g. with the pthread library
+
+ #define _MBG_CRIT_SECT_DEFINED 1
+
+ typedef MBG_MUTEX MBG_CRIT_SECT;
+ #define _mbg_crit_sect_init _mbg_mutex_init
+ #if defined( _mbg_mutex_destroy )
+ #define _mbg_crit_sect_destroy _mbg_mutex_destroy
+ #endif
+ #define _mbg_crit_sect_enter _mbg_mutex_acquire
+ #define _mbg_crit_sect_leave _mbg_mutex_release
+
+#endif
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _MBGMUTEX_H */
diff --git a/mbglib/common/mbgpccyc.h b/mbglib/common/mbgpccyc.h
new file mode 100644
index 0000000..71d1235
--- /dev/null
+++ b/mbglib/common/mbgpccyc.h
@@ -0,0 +1,305 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgpccyc.h 1.2 2012/03/12 13:45:57Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Portable macros to get a machine's current cycle count.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgpccyc.h $
+ * Revision 1.2 2012/03/12 13:45:57Z martin
+ * Added cycles support for Linux/IA64, FreeBSD and NetBSD
+ * in kernel space.
+ * Use get_cycles() in Linux kernel mode if no special cycles support
+ * is provided for the given hardware platform.
+ * Revision 1.1 2011/06/23 15:36:07 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _MBGPCCYC_H
+#define _MBGPCCYC_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+#include <words.h>
+
+#if defined( MBG_TGT_NETBSD )
+ #if defined( MBG_TGT_KERNEL )
+ #include <machine/cpu.h>
+ #include <machine/cpu_counter.h> /* for cycle counter abstraction */
+ #endif
+#endif
+
+#if defined( MBG_TGT_FREEBSD )
+ #if defined( MBG_TGT_KERNEL )
+ #if defined( MBG_ARCH_X86 )
+ #include <machine/clock.h> /* for symbol 'tsc_freq' */
+ #endif
+ #endif
+#endif
+
+#if defined( MBG_TGT_LINUX )
+ #if defined( MBG_ARCH_IA64 ) && defined( MBG_TGT_KERNEL )
+ #include <asm/ia64regs.h>
+ #endif
+#endif
+
+
+#ifdef _MBGPCCYC
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+/**
+ * @brief Generic types to hold PC cycle counter values.
+ *
+ * The cycle counter value is usually derived from the PC CPU's TSC or some other
+ * timer hardware on the mainboard.
+ */
+#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX )
+
+ typedef int64_t MBG_PC_CYCLES;
+ typedef uint64_t MBG_PC_CYCLES_FREQUENCY;
+
+#else
+
+ typedef uint32_t MBG_PC_CYCLES;
+ typedef uint32_t MBG_PC_CYCLES_FREQUENCY;
+
+#endif
+
+
+// MBG_PC_CYCLES and MBG_PC_CYCLES_FREQUENCY are always read in native
+// machine endianess, so no endianess conversion is required.
+#define _mbg_swab_mbg_pc_cycles( _p ) \
+ _nop_macro_fnc()
+
+#define _mbg_swab_mbg_pc_cycles_frequency( _p ) \
+ _nop_macro_fnc()
+
+
+
+#if ( defined( MBG_TGT_LINUX ) || defined( MBG_TGT_BSD ) ) && defined( MBG_ARCH_X86 )
+
+ static __mbg_inline unsigned long long int mbg_rdtscll( void )
+ {
+ // The code below is a hack to get around issues with
+ // different versions of gcc.
+ //
+ // Normally the inline asm code could look similar to:
+ //
+ // __asm__ volatile ( "rdtsc" : "=A" (x) )
+ //
+ // which would copy the output regs edx:eax as a 64 bit
+ // number to a variable x.
+ //
+ // The "=A" expression should implicitely tell the compiler
+ // the edx and eax registers have been clobbered. However,
+ // this does not seem to work properly at least with gcc 4.1.2
+ // shipped with Centos 5.
+ //
+ // If optimization level 1 or higher is used then function
+ // parameters are also passed in registers. If the inline
+ // code above is used inside a function then the edx register
+ // is clobbered but the gcc 4.1.2 is not aware of this and
+ // assumes edx is unchanged, which may yield faulty results
+ // or even lead to segmentation faults.
+ //
+ // A possible workaround could be to mark edx explicitely as
+ // being clobbered in the asm inline code, but unfortunately
+ // other gcc versions report an error if a register which is
+ // implicitely (by "=A") known to be clobbered is also listed
+ // explicitely to be clobbered.
+ //
+ // So the code below is a workaround which tells the compiler
+ // implicitely that the eax ("=a") and edx ("=d") registers
+ // are being used and thus clobbered.
+
+ union
+ {
+ struct
+ {
+ uint32_t lo;
+ uint32_t hi;
+ } u32;
+
+ uint64_t u64;
+
+ } tsc_val;
+
+ __asm__ __volatile__( "rdtsc" : "=a" (tsc_val.u32.lo), "=d" (tsc_val.u32.hi) );
+
+ return tsc_val.u64;
+
+ } // mbg_rdtscll
+
+#endif
+
+
+
+static __mbg_inline
+void mbg_get_pc_cycles( MBG_PC_CYCLES *p )
+{
+#if !defined( OMIT_PC_CYCLES_SUPPORT )
+
+ #if defined( MBG_TGT_WIN32 )
+
+ #if defined( MBG_TGT_KERNEL ) // kernel space
+ *p = (MBG_PC_CYCLES) KeQueryPerformanceCounter( NULL ).QuadPart;
+ #else // user space
+ QueryPerformanceCounter( (LARGE_INTEGER *) p );
+ #endif
+
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+ #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_X86 )
+
+ *p = mbg_rdtscll();
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+ #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_IA64 ) && defined( MBG_TGT_KERNEL )
+
+ unsigned long result = ia64_getreg( _IA64_REG_AR_ITC );
+ ia64_barrier();
+
+ #ifdef CONFIG_ITANIUM
+ while (unlikely((__s32) result == -1)) {
+ result = ia64_getreg(_IA64_REG_AR_ITC);
+ ia64_barrier();
+ }
+ #endif
+
+ *p = result;
+
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+ #elif defined( MBG_TGT_LINUX ) && defined( MBG_TGT_KERNEL )
+
+ *p = get_cycles();
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+ #elif defined( MBG_TGT_FREEBSD ) && defined( MBG_ARCH_X86 )
+
+ *p = mbg_rdtscll();
+
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+ #elif defined( MBG_TGT_NETBSD ) && defined ( MBG_TGT_KERNEL )
+
+ *p = cpu_counter(); //##++ or cpu_counter_serializing()
+
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+ #endif
+
+#endif
+
+
+ #if !defined( MBG_PC_CYCLES_SUPPORTED )
+
+ *p = 0;
+ #define MBG_PC_CYCLES_SUPPORTED 0
+
+ #endif
+
+} // mbg_get_pc_cycles
+
+
+
+static __mbg_inline
+void mbg_get_pc_cycles_frequency( MBG_PC_CYCLES_FREQUENCY *p )
+{
+ #if defined( MBG_TGT_WIN32 )
+ LARGE_INTEGER li;
+
+ #if defined( MBG_TGT_KERNEL ) // kernel space
+ KeQueryPerformanceCounter( &li );
+ #else // user space
+ QueryPerformanceFrequency( &li );
+ #endif
+
+ *p = li.QuadPart;
+
+ #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_X86 ) && defined( MBG_TGT_KERNEL )
+
+ *p = ( cpu_khz * 1000 );
+
+ #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_IA64 )
+
+ // we probably can use
+ // ia64_sal_freq_base(unsigned long which, unsigned long *ticks_per_second,
+ // unsigned long *drift_info)
+ // However, this is not tested.
+
+ *p = 0;
+
+ #elif defined( MBG_TGT_FREEBSD ) && defined( MBG_ARCH_X86 ) && defined( MBG_TGT_KERNEL )
+
+ *p = tsc_freq;
+
+ #elif defined( MBG_TGT_NETBSD ) && defined( MBG_TGT_KERNEL )
+
+ *p = cpu_frequency( curcpu() );
+
+ #else
+
+ *p = 0;
+
+ #endif
+
+} // mbg_get_pc_cycles_frequency
+
+
+
+static __mbg_inline
+MBG_PC_CYCLES mbg_delta_pc_cycles( const MBG_PC_CYCLES *p1, const MBG_PC_CYCLES *p2 )
+{
+#if 0 && !MBG_PC_CYCLES_SUPPORTED
+ // Cycle counts not supported on this target platform.
+ // Under SPARC this may even result in bus errors
+ // due to alignment of the underlying data structures.
+ return 0;
+#else
+ return *p1 - *p2;
+#endif
+
+} // mbg_delta_pc_cycles
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _MBGPCCYC */
diff --git a/mbglib/common/mbgtime.h b/mbglib/common/mbgtime.h
new file mode 100644
index 0000000..7b9d2f4
--- /dev/null
+++ b/mbglib/common/mbgtime.h
@@ -0,0 +1,322 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgtime.h 1.18 2012/10/02 18:51:11Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for mbgtime.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgtime.h $
+ * Revision 1.18 2012/10/02 18:51:11Z martin
+ * Include <time.h> for WIN32 target and firmware only
+ * Fixed build under QNX, DOS, and FreeBSD.
+ * Revision 1.17 2010/08/06 13:03:03 martin
+ * Removed obsolete code.
+ * Revision 1.16 2010/07/16 10:22:07Z martin
+ * Moved definitions of HNS_PER_SEC and HNS_PER_MS here.
+ * Conditionally define FILETIME_1970.
+ * Defined MASK_CLOCK_T for ARM/Cortex.
+ * Revision 1.15 2009/10/23 09:55:21 martin
+ * Added MJD numbers for commonly used epochs.
+ * Revision 1.14 2009/08/12 10:28:12 daniel
+ * Added definition NSECS_PER_SEC.
+ * Revision 1.13 2009/06/12 13:31:44Z martin
+ * Fix build errors with arm-linux-gcc.
+ * Revision 1.12 2009/03/27 14:14:00 martin
+ * Cleanup for CVI.
+ * Revision 1.11 2009/03/13 09:30:06Z martin
+ * Include mystd.h in mbgtime.c rather than here. The bit type used
+ * here is now defined in words.h.
+ * Updated comments for GPS_SEC_BIAS.
+ * Revision 1.10 2008/12/11 10:45:41Z martin
+ * Added clock_t mask for gcc (GnuC).
+ * Revision 1.9 2006/08/25 09:33:46Z martin
+ * Updated function prototypes.
+ * Revision 1.8 2004/12/28 11:29:02Z martin
+ * Added macro _n_days.
+ * Updated function prototypes.
+ * Revision 1.7 2002/09/06 07:15:48Z martin
+ * Added MASK_CLOCK_T for Linux.
+ * Revision 1.6 2002/02/25 08:37:44 Andre
+ * definition MASK_CLOCK_T for ARM added
+ * Revision 1.5 2001/03/02 10:18:10Z MARTIN
+ * Added MASK_CLOCK_T for Watcom C.
+ * Revision 1.4 2000/09/15 07:57:53 MARTIN
+ * Removed outdated function prototypes.
+ * Revision 1.3 2000/07/21 14:05:18 MARTIN
+ * Defined some new constants.
+ *
+ **************************************************************************/
+
+#ifndef _MBGTIME_H
+#define _MBGTIME_H
+
+
+/* Other headers to be included */
+
+#include <gpsdefs.h>
+
+#if _IS_MBG_FIRMWARE \
+ || defined( MBG_TGT_WIN32 ) \
+ || defined( MBG_TGT_DOS ) \
+ || defined( MBG_TGT_QNX_NTO )
+ #include <time.h>
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _MBGTIME
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+// The Unix time_t epoche is usually 1970-01-01 00:00 whereas
+// the GPS epoche is 1980-01-06 00:00, so the difference is 10 years,
+// plus 2 days due to leap years (1972 and 1976), plus the difference
+// of the day-of-month (6 - 1).
+#define GPS_SEC_BIAS 315964800UL // ( ( ( 10UL * 365UL ) + 2 + 5 ) * SECS_PER_DAY )
+
+// time_t t = ( gps_week * SECS_PER_WEEK ) + sec_of_week + GPS_SEC_BIAS
+
+
+// Modified Julian Day (MJD) numbers for some commonly used epochs.
+// To compute the MJD for a given date just compute the days since epoch
+// and add the constant number of days according to the epoch, e.g.:
+// current_unix_mjd = ( time( NULL ) / SECS_PER_DAY ) + MJD_AT_UNIX_EPOCH;
+#define MJD_AT_GPS_EPOCH 44244UL // MJD at 1980-01-06
+#define MJD_AT_UNIX_EPOCH 40587UL // MJD at 1970-01-01
+#define MJD_AT_NTP_EPOCH 40587UL // MJD at 1900-01-01
+
+
+// The constant below defines the Windows FILETIME number (100 ns intervals
+// since 1601-01-01) for 1970-01-01, which is usually the epoche for the time_t
+// type used by the standard C library.
+#if !defined( FILETIME_1970 )
+ // FILETIME represents a 64 bit number, so we need to defined the
+ // constant with an appendix depending on the compiler.
+ #if MBG_TGT_C99 || defined( __GNUC__ )
+ // syntax introduced by C99 standard
+ #define FILETIME_1970 0x019db1ded53e8000ULL // Epoch offset from FILETIME to UNIX
+ #elif defined( MBG_TGT_WIN32 )
+ // MSC-specific syntax
+ #define FILETIME_1970 0x019db1ded53e8000ui64
+ #endif
+#endif
+
+
+#if defined( _C166 )
+ #if _C166 >= 50
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+ #else
+ #define MASK_CLOCK_T 0x7FFF /* time.h not shipped with compiler */
+ #endif
+#endif
+
+#if defined( __WATCOMC__ )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+#endif
+
+#if defined( _CVI ) || defined( _CVI_ )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+#endif
+
+#if defined( _MSC_VER )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+#endif
+
+#if defined( __NETWARE_386__ )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+#endif
+
+#if defined( __ARM )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+#endif
+
+#if defined( __ARMCC_VERSION )
+ #define MASK_CLOCK_T ( ( (ulong) (clock_t) -1 ) >> 1 )
+#endif
+
+#if defined( __GNUC__ )
+ #if defined( __linux )
+ #define MASK_CLOCK_T ( ( (ulong) (clock_t) -1 ) >> 1 )
+ #else // Windows / MinGW
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+ #endif
+#endif
+
+
+#if !defined( MASK_CLOCK_T )
+ #if sizeof( clock_t ) == sizeof( short )
+ #define MASK_CLOCK_T 0x7FFF
+ #elif sizeof( clock_t ) == sizeof( long )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+ #endif
+#endif
+
+typedef struct
+{
+ clock_t start;
+ clock_t stop;
+ short is_set;
+} TIMEOUT;
+
+
+#define DAYS_PER_WEEK 7
+
+#define SECS_PER_MIN 60
+#define MINS_PER_HOUR 60
+#define HOURS_PER_DAY 24
+#define DAYS_PER_WEEK 7
+
+#define MINS_PER_DAY ( MINS_PER_HOUR * HOURS_PER_DAY )
+
+#define SECS_PER_HOUR 3600
+#define SECS_PER_DAY 86400L
+#define SECS_PER_WEEK 604800L
+
+#define SEC100S_PER_SEC 100L
+#define SEC100S_PER_MIN ( SEC100S_PER_SEC * SECS_PER_MIN )
+#define SEC100S_PER_HOUR ( SEC100S_PER_SEC * SECS_PER_HOUR )
+#define SEC100S_PER_DAY ( SEC100S_PER_SEC * SECS_PER_DAY )
+
+#if !defined( MSEC_PER_SEC )
+ #define MSEC_PER_SEC 1000L
+#endif
+
+#define MSEC_PER_MIN ( MSEC_PER_SEC * SECS_PER_MIN )
+#define MSEC_PER_HOUR ( MSEC_PER_SEC * SECS_PER_HOUR )
+#define MSEC_PER_DAY ( MSEC_PER_SEC * SECS_PER_DAY )
+
+#define NSECS_PER_SEC 1000000000UL
+
+#if !defined( HNS_PER_SEC )
+ #define HNS_PER_SEC 10000000UL
+#endif
+
+#if !defined( HNS_PER_MS )
+ #define HNS_PER_MS 10000UL
+#endif
+
+
+
+_ext TM_GPS dhms;
+_ext TM_GPS datum;
+
+
+_ext const char *short_time_fmt
+#ifdef _MBGTIME
+ = "%2i:%02i"
+#endif
+;
+
+_ext const char *time_fmt
+#ifdef _MBGTIME
+ = "%2i:%02i:%02i"
+#endif
+;
+
+_ext const char *long_time_fmt
+#ifdef _MBGTIME
+ = "%2i:%02i:%02i.%02i"
+#endif
+;
+
+_ext const char *date_fmt
+#ifdef _MBGTIME
+ = "%2i.%02i.%04i"
+#endif
+;
+
+_ext const char *day_date_fmt
+#ifdef _MBGTIME
+ = "%s, %2i.%02i.%04i"
+#endif
+;
+
+_ext const char *day_name_eng[]
+#ifdef _MBGTIME
+ = { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }
+#endif
+;
+
+_ext const char *day_name_ger[]
+#ifdef _MBGTIME
+ = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" }
+#endif
+;
+
+_ext const TM_GPS init_tm
+#ifdef _MBGTIME
+ = { 1980, 1, 1, 0, 0, 0, 0, 0, 0, 0 }
+#endif
+;
+
+
+_ext char days_of_month[2][12]
+#ifdef _MBGTIME
+ = {
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+ }
+#endif
+;
+
+
+// simplify call to n_days with structures
+#define _n_days( _s ) \
+ n_days( (_s)->mday, (_s)->month, (_s)->year )
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ void set_timeout( TIMEOUT *t, clock_t clk, clock_t interval ) ;
+ void stretch_timeout( TIMEOUT *t, clock_t interval ) ;
+ bit check_timeout( TIMEOUT *t, clock_t clk ) ;
+ int err_tm( TM_GPS *tm ) ;
+ TM_GPS *clear_time( TM_GPS *tm ) ;
+ TM_GPS *wsec_to_tm( long wsec, TM_GPS *tm ) ;
+ long tm_to_wsec( TM_GPS *tm ) ;
+ int is_leap_year( int y ) ;
+ int day_of_year( int day, int month, int year ) ;
+ void date_of_year ( int year, int day_num, TM_GPS *tm ) ;
+ int day_of_week( int day, int month, int year ) ;
+ int days_to_years( long *day_num, int year ) ;
+ long n_days( ushort mday, ushort month, ushort year ) ;
+ double nano_time_to_double( const NANO_TIME *p ) ;
+ void double_to_nano_time( NANO_TIME *p, double d ) ;
+ int sprint_time( char *s, const TM_GPS *tm ) ;
+ int sprint_short_time( char *s, TM_GPS *time ) ;
+ int sprint_date( char *s, const TM_GPS *tm ) ;
+ int sprint_day_date( char *s, const TM_GPS *tm ) ;
+ int sprint_tm( char *s, const TM_GPS *tm ) ;
+ void sscan_time( char *s, TM_GPS *tm ) ;
+ void sscan_date( char *s, TM_GPS *tm ) ;
+
+/* ----- function prototypes end ----- */
+
+
+/* End of header body */
+
+
+#undef _ext
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _MBGTIME_H */
diff --git a/mbglib/common/myutil.h b/mbglib/common/myutil.h
new file mode 100644
index 0000000..52489d5
--- /dev/null
+++ b/mbglib/common/myutil.h
@@ -0,0 +1,225 @@
+
+/**************************************************************************
+ *
+ * $Id: myutil.h 1.15 2012/10/02 18:51:52Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for myutil.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: myutil.h $
+ * Revision 1.15 2012/10/02 18:51:52Z martin
+ * Updated handling of pragma pack().
+ * Revision 1.14 2011/02/16 14:02:35 martin
+ * Added STRINGIFY() macro.
+ * Revision 1.13 2010/12/13 15:59:39 martin
+ * Moved definition of macro _frac() here.
+ * Revision 1.12 2008/01/30 10:28:17Z martin
+ * Moved some macro definitions to words.h.
+ * Revision 1.11 2004/11/09 14:20:24Z martin
+ * Redefined some data types using C99 fixed-size definitions.
+ * Removed duplicate definition of macro _mask().
+ * Revision 1.10 2004/04/14 08:57:59Z martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.9 2003/05/20 10:22:25Z MARTIN
+ * Corrected endianess of union UL for CC51.
+ * Revision 1.8 2002/09/03 13:40:43 MARTIN
+ * New macros _memfill() and _memclr().
+ * Revision 1.7 2002/03/14 13:45:56 MARTIN
+ * Changed type CSUM from short to ushort.
+ * Revision 1.6 2002/03/05 14:14:21 MARTIN
+ * New macro _isdigit() to avoid inclusion of ctype.h.
+ * Revision 1.5 2002/01/25 10:54:26 MARTIN
+ * Added some useful macros.
+ * Revision 1.4 2001/03/30 09:07:52 Andre
+ * union UL byte order set to Big Endian if SH2 is used
+ * Revision 1.3 2000/08/18 07:22:07Z MARTIN
+ * Modified the _csum() macro to support far data objects.
+ * Revision 1.2 2000/07/21 13:50:49 MARTIN
+ * Added some definitions and macros.
+ *
+ **************************************************************************/
+
+#ifndef _MYUTIL_H
+#define _MYUTIL_H
+
+
+/* Other headers to be included */
+
+#include <words.h>
+#include <use_pack.h>
+
+
+// _CS_FAR should be define far if the csum of far data
+// structures must be computed
+#if !defined( _CSFAR )
+ #define _CSFAR
+#endif
+
+
+#ifdef _MYUTIL
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+
+// The two macros below can be used to define a constant string on the
+// compiler's command line, e.g. like -DVERSION_STRING="v1.0 BETA".
+// Source code like
+// const char version_string[] = VERSION_STRING;
+// may not work for every compiler since the double quotes
+// in VERSION_STRING may be removed when the definition is evaluated.
+// A proper solution is to use the STRINGIFY() macro below:
+// const char version_string[] = STRINGIFY( VERSION_STRING );
+// The XSTRINGIFY() macro is simply a helper macro which should not
+// be used alone.
+#define STRINGIFY(x) XSTRINGIFY(x)
+#define XSTRINGIFY(x) #x
+
+
+
+#if MBG_TGT_HAS_64BIT_TYPES
+ #define _frac( _x ) ( ( (_x) == 0.0 ) ? 0.0 : ( (_x) - (double) ( (int64_t) (_x) ) ) )
+#else
+ #define _frac( _x ) ( ( (_x) == 0.0 ) ? 0.0 : ( (_x) - (double) ( (long) (_x) ) ) )
+#endif
+
+
+#define _isdigit( _c ) ( (_c) >= '0' && (_c) <= '9' )
+
+#define _eos( _s ) ( &(_s)[strlen( _s )] )
+
+#define MIN( _x, _y ) ( ( (_x) < (_y) ) ? (_x) : (_y) )
+#define MAX( _x, _y ) ( ( (_x) > (_y) ) ? (_x) : (_y) )
+#define SWAP( _x, _y ) { temp = (_x); (_x) = (_y); (_y) = temp; }
+#define SQR( _x ) ( (_x) * (_x) )
+
+#define DP (double *)
+
+#define bcd_from_bin( _x ) ( ( ( (_x) / 10 ) << 4 ) | ( (_x) % 10 ) )
+#define bin_from_bcd( _x ) ( ( ( (_x) >> 4 ) * 10 ) + ( (_x) & 0x0F ) )
+
+
+typedef union
+{
+ uint32_t ul;
+
+ struct
+ {
+ #if defined( _CC51 ) || defined( _SH2 )
+ uint16_t hi; // big endian
+ uint16_t lo;
+ #else
+ uint16_t lo; // little endian
+ uint16_t hi;
+ #endif
+ } us;
+
+} UL;
+
+
+#ifndef _CSUM_DEFINED
+ typedef uint16_t CSUM;
+ #define _CSUM_DEFINED
+#endif
+
+
+// compute the csum of a structure
+#define _csum( _p ) checksum( (void _CSFAR *)(_p), sizeof( *(_p) ) )
+
+// set a structure's csum
+#define _set_csum( _p ) (_p)->csum = _csum( (_p) )
+
+// compare a structure's computed csum with its csum field
+#define _valid_csum( _p ) ( (_p)->csum == _csum( (_p) ) )
+
+// check if a value is in range
+#define _inrange( _val, _min, _max ) \
+ ( ( (_val) >= (_min) ) && ( (_val) <= (_max) ) )
+
+// Return a bit mask with (_n) LSBs set to 1
+#define _mask( _n ) \
+ ( ( 1UL << (_n) ) - 1 )
+
+// Return a bit mask with the (_i)th LSB set to 1
+#define _idx_bit( _i ) \
+ ( 1UL << (_i) )
+
+// Check if the (_i)th bit is set in a mask (_msk)
+#define _is_supported( _i, _msk ) \
+ ( ( (_msk) & _idx_bit( _i ) ) != 0 )
+
+
+/*
+ * The macro below copies a string, taking care not to
+ * write past the end of the destination buffer, and
+ * making sure the string is terminated by 0.
+ */
+#define _strncpy_0( _dst, _src ) \
+{ \
+ int n = sizeof( _dst ) - 1; \
+ \
+ strncpy( _dst, _src, n ); \
+ (_dst)[n] = 0; \
+}
+
+
+/*
+ * The macros below set a memory range used by a variable
+ * to a specified value, avoiding the need to type the name
+ * twice for base address and size.
+ */
+#define _memfill( _p, _v ) \
+ memset( _p, _v, sizeof( *(_p) ) )
+
+#define _memclr( _p ) \
+ _memfill( _p, 0 )
+
+
+
+// generate a DOS idle interrupt to release CPU time
+#define _dos_idle() geninterrupt( 0x28 )
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ void spaces_to_zeros( char *s ) ;
+ CSUM checksum( const void _CSFAR *vp, int n ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+
+#undef _ext
+
+
+#endif /* _MYUTIL_H */
diff --git a/mbglib/common/parmgps.c b/mbglib/common/parmgps.c
new file mode 100644
index 0000000..187cd4e
--- /dev/null
+++ b/mbglib/common/parmgps.c
@@ -0,0 +1,242 @@
+
+/**************************************************************************
+ *
+ * $Id: parmgps.c 1.5 2008/10/21 10:47:26Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions to handle/convert Meinberg GPS specific parameters.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: parmgps.c $
+ * Revision 1.5 2008/10/21 10:47:26Z martin
+ * Renamed check_port_info() to check_valid_port_info()
+ * to avoid naming conflicts.
+ * Revision 1.4 2008/09/15 14:11:25 martin
+ * New function check_port_info() which returns a bit mask indicating
+ * which fields of a PORT_SETTINGS structure are not valid.
+ * This is based on code taken from valid_port_info(), which now calls
+ * check_port_info() and returns a value compatible to the earlier version.
+ * Revision 1.3 2004/11/09 14:21:36 martin
+ * Redefined some data types using C99 fixed-size definitions.
+ * Revision 1.2 2002/02/19 13:30:23Z MARTIN
+ * Bug fix in port_settings_from_port_parm_mode().
+ * Revision 1.1 2002/01/30 10:30:26 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _PARMGPS
+ #include <parmgps.h>
+#undef _PARMGPS
+
+#include <myutil.h>
+#include <string.h>
+
+
+
+/*HDR*/
+int get_str_idx( const char *search,
+ const char *str_table[],
+ int n_entries )
+{
+ int i;
+
+ for ( i = 0; i < n_entries; i++ )
+ if ( strcmp( search, str_table[i] ) == 0 )
+ return i;
+
+ return -1;
+
+} // get_str_idx
+
+
+
+/*HDR*/
+int get_baud_rate_idx( BAUD_RATE baud_rate )
+{
+ int i;
+
+ for ( i = 0; i < N_MBG_BAUD_RATES; i++ )
+ if ( baud_rate == mbg_baud_rate[i] )
+ return i;
+
+ return -1;
+
+} // get_baud_rate_idx
+
+
+
+/*HDR*/
+int get_framing_idx( const char *framing )
+{
+ return get_str_idx( framing, mbg_framing_str, N_MBG_FRAMINGS );
+
+} // get_framing_idx
+
+
+
+/*HDR*/
+void port_settings_from_port_parm_mode(
+ PORT_SETTINGS *p_ps,
+ uint8_t pp_mode,
+ int str_type_cap
+ )
+{
+ if ( pp_mode >= STR_UCAP )
+ {
+ p_ps->str_type = str_type_cap;
+ p_ps->mode = ( pp_mode == STR_UCAP ) ? STR_AUTO : STR_ON_REQ;
+ }
+ else
+ {
+ p_ps->str_type = 0;
+ p_ps->mode = pp_mode;
+ }
+
+} // port_settings_from_port_parm_mode
+
+
+
+/*HDR*/
+void port_parm_mode_from_port_settings(
+ uint8_t *pp_mode,
+ const PORT_SETTINGS *p_ps,
+ int str_type_cap
+ )
+{
+ if ( p_ps->str_type == str_type_cap )
+ *pp_mode = ( p_ps->mode == STR_ON_REQ ) ? STR_UCAP_REQ : STR_UCAP;
+ else
+ *pp_mode = p_ps->mode;
+
+} // port_parm_mode_from_port_settings
+
+
+
+/*HDR*/
+void port_settings_from_port_parm(
+ PORT_SETTINGS *p_ps,
+ int port_num,
+ const PORT_PARM *p_pp,
+ int cap_str_idx
+)
+{
+ p_ps->parm = p_pp->com[port_num];
+
+ port_settings_from_port_parm_mode( p_ps, p_pp->mode[port_num],
+ cap_str_idx );
+
+} // port_info_from_port_parm
+
+
+
+/*HDR*/
+void port_parm_from_port_settings(
+ PORT_PARM *p_pp,
+ int port_num,
+ const PORT_SETTINGS *p_ps,
+ int cap_str_idx
+)
+{
+ p_pp->com[port_num] = p_ps->parm;
+
+ port_parm_mode_from_port_settings( &p_pp->mode[port_num],
+ p_ps, cap_str_idx );
+
+} // port_parm_from_port_settings
+
+
+
+/*HDR*/
+int check_valid_port_info( const PORT_INFO *p_pi,
+ const STR_TYPE_INFO_IDX str_type_info_idx[],
+ int n_str_type )
+
+{
+ const PORT_SETTINGS *p_ps = &p_pi->port_settings;
+ int idx;
+ int flags = 0;
+
+
+ if ( p_pi->supp_baud_rates & ~_mask( N_MBG_BAUD_RATES ) )
+ flags |= MBG_PS_MSK_BAUD_RATE_OVR_SW; // dev. supports more baud rates than driver
+
+ idx = get_baud_rate_idx( p_ps->parm.baud_rate );
+
+ if ( !_inrange( idx, 0, N_MBG_BAUD_RATES ) ||
+ !_is_supported( idx, p_pi->supp_baud_rates ) )
+ flags |= MBG_PS_MSK_BAUD_RATE;
+
+
+ if ( p_pi->supp_framings & ~_mask( N_MBG_FRAMINGS ) )
+ flags |= MBG_PS_MSK_FRAMING_OVR_SW; // dev. supports more framings than driver
+
+ idx = get_framing_idx( p_ps->parm.framing );
+
+ if ( !_inrange( idx, 0, N_MBG_FRAMINGS ) ||
+ !_is_supported( idx, p_pi->supp_framings ) )
+ flags |= MBG_PS_MSK_FRAMING;
+
+
+ if ( p_ps->parm.handshake >= N_COM_HS )
+ flags |= MBG_PS_MSK_HS_OVR_SW; // handshake index exceeds max.
+
+ if ( p_ps->parm.handshake != HS_NONE ) // currently no device supports any handshake
+ flags |= MBG_PS_MSK_HS; // handshake mode not supp. by dev.
+
+
+ if ( p_pi->supp_str_types & ~_mask( n_str_type ) )
+ flags |= MBG_PS_MSK_STR_TYPE_OVR_SW; // firmware error: more string types supported than reported
+
+ idx = p_ps->str_type;
+
+ if ( idx >= n_str_type )
+ flags |= MBG_PS_MSK_STR_TYPE_OVR_DEV; // string type index exceeds max.
+ else
+ {
+ if ( !_is_supported( idx, p_pi->supp_str_types ) )
+ flags |= MBG_PS_MSK_STR_TYPE; // string type not supported by this port
+ else
+ {
+ // Use the str_type index to get the supported output mode mask
+ // from the string type info table. This is required to check
+ // whether the selected mode is supported by the selected
+ // string type.
+ ulong supp_modes = str_type_info_idx[idx].str_type_info.supp_modes;
+
+ if ( supp_modes & ~_mask( N_STR_MODE ) )
+ flags |= MBG_PS_MSK_STR_MODE_OVR_SW; // dev. supports more string modes than driver
+
+ idx = p_ps->mode;
+
+ if ( idx >= N_STR_MODE ) // mode is always >= 0
+ flags |= MBG_PS_MSK_STR_MODE_OVR_SW; // string mode index exceeds max.
+ else
+ if ( !_is_supported( idx, supp_modes ) )
+ flags |= MBG_PS_MSK_STR_MODE; // string mode not supp. by this string type and port
+ }
+ }
+
+
+ if ( p_ps->flags != 0 ) /* currently always 0 */
+ flags |= MBG_PS_MSK_FLAGS_OVR_SW | MBG_PS_MSK_FLAGS;
+
+
+ return flags;
+
+} // check_valid_port_info
+
+
+
+/*HDR*/
+int valid_port_info( const PORT_INFO *p_pi,
+ const STR_TYPE_INFO_IDX str_type_info_idx[],
+ int n_str_type )
+{
+ return check_valid_port_info( p_pi, str_type_info_idx, n_str_type ) == 0;
+
+} // valid_port_info
+
+
diff --git a/mbglib/common/parmgps.h b/mbglib/common/parmgps.h
new file mode 100644
index 0000000..6f9b29b
--- /dev/null
+++ b/mbglib/common/parmgps.h
@@ -0,0 +1,142 @@
+
+/**************************************************************************
+ *
+ * $Id: parmgps.h 1.8 2012/10/15 10:06:37Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for parmgps.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: parmgps.h $
+ * Revision 1.8 2012/10/15 10:06:37Z martin
+ * Cleaned up handling of pragma pack().
+ * Revision 1.7 2011/02/16 10:12:13 martin
+ * Fixed macro syntax for _setup_default_receiver_info_gps().
+ * Revision 1.6 2008/10/21 10:41:09Z martin
+ * Renamed check_port_info() to check_valid_port_info()
+ * to avoid naming conflicts.
+ * Revision 1.5 2008/09/10 16:22:32 martin
+ * Updated function prototypes.
+ * Revision 1.4 2004/11/09 14:22:34 martin
+ * Updated function prototypes.
+ * Revision 1.3 2004/05/19 07:50:16Z martin
+ * Use symbolic constant as initializer.
+ * Revision 1.2 2004/04/14 09:21:23Z martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.1 2002/01/30 10:33:38Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PARMGPS_H
+#define _PARMGPS_H
+
+
+/* Other headers to be included */
+
+#include <gpsdefs.h>
+#include <use_pack.h>
+
+
+#ifdef _PARMGPS
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define DEFAULT_N_STR_TYPE_GPS 2
+
+#define DEFAULT_SUPP_STR_TYPES_GPS \
+ ( ( 1UL << DEFAULT_N_STR_TYPE_GPS ) - 1 )
+
+
+/*
+ * The macro below can be used to initialize a
+ * RECEIVER_INFO structure for old GPS receiver models
+ * which don't supply that structure.
+ *
+ * Parameters: (RECEIVER_INFO *) _p
+ */
+#define _setup_default_receiver_info_gps( _p ) \
+do \
+{ \
+ memset( (_p), 0, sizeof( *(_p) ) ); \
+ \
+ (_p)->ticks_per_sec = DEFAULT_GPS_TICKS_PER_SEC; \
+ (_p)->n_ucaps = 2; \
+ (_p)->n_com_ports = DEFAULT_N_COM; \
+ (_p)->n_str_type = DEFAULT_N_STR_TYPE_GPS; \
+} while ( 0 )
+
+
+_ext BAUD_RATE mbg_baud_rate[N_MBG_BAUD_RATES]
+#ifdef _DO_INIT
+ = MBG_BAUD_RATES
+#endif
+;
+
+_ext const char *mbg_baud_str[N_MBG_BAUD_RATES]
+#ifdef _DO_INIT
+ = MBG_BAUD_STRS
+#endif
+;
+
+_ext const char *mbg_framing_str[N_MBG_FRAMINGS]
+#ifdef _DO_INIT
+ = MBG_FRAMING_STRS
+#endif
+;
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ int get_str_idx( const char *search, const char *str_table[], int n_entries ) ;
+ int get_baud_rate_idx( BAUD_RATE baud_rate ) ;
+ int get_framing_idx( const char *framing ) ;
+ void port_settings_from_port_parm_mode( PORT_SETTINGS *p_ps, uint8_t pp_mode, int str_type_cap ) ;
+ void port_parm_mode_from_port_settings( uint8_t *pp_mode, const PORT_SETTINGS *p_ps, int str_type_cap ) ;
+ void port_settings_from_port_parm( PORT_SETTINGS *p_ps, int port_num, const PORT_PARM *p_pp, int cap_str_idx ) ;
+ void port_parm_from_port_settings( PORT_PARM *p_pp, int port_num, const PORT_SETTINGS *p_ps, int cap_str_idx ) ;
+ int check_valid_port_info( const PORT_INFO *p, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type ) ;
+ int valid_port_info( const PORT_INFO *p, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type ) ;
+
+/* ----- function prototypes end ----- */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _PARMGPS_H */
+
diff --git a/mbglib/common/parmpcps.c b/mbglib/common/parmpcps.c
new file mode 100644
index 0000000..1d017a2
--- /dev/null
+++ b/mbglib/common/parmpcps.c
@@ -0,0 +1,115 @@
+
+/**************************************************************************
+ *
+ * $Id: parmpcps.c 1.4 2004/11/09 14:24:15Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions to handle/convert parameters used by Meinberg plug-in
+ * radio clocks.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: parmpcps.c $
+ * Revision 1.4 2004/11/09 14:24:15Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Revision 1.3 2003/04/17 10:43:35Z martin
+ * Moved some definitions to parmpcps.h.
+ * Removed some functions which are now in mbgdevio.c.
+ * Revision 1.2 2002/03/25 09:03:43Z MARTIN
+ * Fixed a bug where the wrong framing was configured for DCF77 clocks.
+ * Revision 1.1 2002/02/19 14:00:19 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _PARMPCPS
+ #include <parmpcps.h>
+#undef _PARMPCPS
+
+#include <parmgps.h>
+#include <pcpsutil.h>
+#include <myutil.h>
+
+#include <string.h>
+
+
+static const int pcps_to_mbg_framing_tbl[N_PCPS_FR_DCF] =
+{
+ MBG_FRAMING_8N1,
+ MBG_FRAMING_7E2,
+ MBG_FRAMING_8N2,
+ MBG_FRAMING_8E1
+};
+
+
+
+/*HDR*/
+void port_info_from_pcps_serial(
+ PORT_INFO_IDX *p_pii,
+ PCPS_SERIAL pcps_serial,
+ uint32_t supp_baud_rates
+)
+{
+ PCPS_SER_PACK ser_pack;
+ PORT_INFO *p_pi;
+ PORT_SETTINGS *p_ps;
+
+ ser_pack.pack = pcps_serial;
+ pcps_unpack_serial( &ser_pack );
+
+ p_pi = &p_pii[0].port_info;
+ p_ps = &p_pi->port_settings;
+
+ p_ps->parm.baud_rate = mbg_baud_rate[ser_pack.baud];
+
+ _strncpy_0( p_ps->parm.framing,
+ mbg_framing_str[pcps_to_mbg_framing_tbl[ser_pack.frame]] );
+
+ p_ps->parm.handshake = HS_NONE;
+
+ p_ps->str_type = 0;
+ p_ps->mode = ser_pack.mode;
+
+ p_pi->supp_baud_rates = supp_baud_rates;
+ p_pi->supp_framings = DEFAULT_FRAMINGS_DCF;
+ p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_DCF;
+
+} // port_info_from_pcps_serial
+
+
+/*HDR*/
+void pcps_serial_from_port_info(
+ PCPS_SERIAL *p,
+ const PORT_INFO_IDX *p_pii
+)
+{
+ PCPS_SER_PACK ser_pack;
+ const PORT_INFO *p_pi = &p_pii[0].port_info;
+ const PORT_SETTINGS *p_ps = &p_pi->port_settings;
+ int framing_idx = get_framing_idx( p_ps->parm.framing );
+ int i;
+
+
+ ser_pack.baud = get_baud_rate_idx( p_ps->parm.baud_rate );
+
+ // Translate the common framing index to the corresponding
+ // number used with the old PCPS_SERIAL parameter.
+ // This should always return a valid result since the
+ // framing index is expected to be selected from
+ // supported framings.
+ for ( i = 0; i < N_PCPS_FR_DCF; i++ )
+ if ( pcps_to_mbg_framing_tbl[i] == framing_idx )
+ break;
+
+ ser_pack.frame = i;
+
+ ser_pack.mode = p_ps->mode;
+
+ pcps_pack_serial( &ser_pack );
+
+ *p = ser_pack.pack;
+
+} // pcps_serial_from_port_info
+
+
diff --git a/mbglib/common/parmpcps.h b/mbglib/common/parmpcps.h
new file mode 100644
index 0000000..5eb30cb
--- /dev/null
+++ b/mbglib/common/parmpcps.h
@@ -0,0 +1,163 @@
+
+/**************************************************************************
+ *
+ * $Id: parmpcps.h 1.8 2012/10/15 10:05:38Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for parmpcps.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: parmpcps.h $
+ * Revision 1.8 2012/10/15 10:05:38Z martin
+ * Cleaned up handling of pragma pack().
+ * Revision 1.7 2011/04/01 10:30:51 martin
+ * Fixed macro syntax for _setup_default_receiver_info_dcf().
+ * Revision 1.6 2011/02/16 10:13:12 martin
+ * Fixed macro syntax for _setup_default_receiver_info_pcps().
+ * Revision 1.5 2004/11/09 14:24:58Z martin
+ * Updated function prototypes.
+ * Revision 1.4 2004/05/19 07:52:25Z martin
+ * Fixed macro setting default number of string types.
+ * Revision 1.3 2004/04/14 09:21:44Z martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.2 2003/04/17 10:42:46Z martin
+ * Moved typedef RECEIVER_PORT_CFG to pcpsdev.h.
+ * Moved some definitions from parmpcps.c here.
+ * Removed some global variables.
+ * Updated function prototypes.
+ * Revision 1.1 2002/02/19 14:00:19Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PARMPCPS_H
+#define _PARMPCPS_H
+
+/* Other headers to be included */
+
+#include <pcpsdev.h>
+#include <use_pack.h>
+
+
+#ifdef _PARMPCPS
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define DEFAULT_BAUD_RATES_DCF \
+( \
+ MBG_PORT_HAS_300 | \
+ MBG_PORT_HAS_600 | \
+ MBG_PORT_HAS_1200 | \
+ MBG_PORT_HAS_2400 | \
+ MBG_PORT_HAS_4800 | \
+ MBG_PORT_HAS_9600 \
+)
+
+#define DEFAULT_BAUD_RATES_DCF_HS \
+( \
+ MBG_PORT_HAS_300 | \
+ MBG_PORT_HAS_600 | \
+ MBG_PORT_HAS_1200 | \
+ MBG_PORT_HAS_2400 | \
+ MBG_PORT_HAS_4800 | \
+ MBG_PORT_HAS_9600 | \
+ MBG_PORT_HAS_19200 | \
+ MBG_PORT_HAS_38400 \
+)
+
+
+#define DEFAULT_FRAMINGS_DCF \
+( \
+ MBG_PORT_HAS_7E2 | \
+ MBG_PORT_HAS_8N1 | \
+ MBG_PORT_HAS_8N2 | \
+ MBG_PORT_HAS_8E1 \
+)
+
+
+#define DEFAULT_N_STR_TYPE_DCF 1
+
+#define DEFAULT_SUPP_STR_TYPES_DCF \
+ ( ( 1UL << DEFAULT_N_STR_TYPE_DCF ) - 1 )
+
+
+/*
+ * The macro below can be used to initialize a
+ * RECEIVER_INFO structure for DCF77 receivers
+ * which don't supply that structure.
+ *
+ * Parameters: (RECEIVER_INFO *) _p
+ */
+#define _setup_default_receiver_info_dcf( _p, _pdev ) \
+do \
+{ \
+ memset( (_p), 0, sizeof( *(_p) ) ); \
+ \
+ (_p)->ticks_per_sec = DEFAULT_GPS_TICKS_PER_SEC; \
+ (_p)->n_ucaps = 0; \
+ (_p)->n_com_ports = _pcps_has_serial( _pdev ) ? 1 : 0; \
+ (_p)->n_str_type = ( (_p)->n_com_ports != 0 ) ? \
+ DEFAULT_N_STR_TYPE_DCF : 0; \
+} while ( 0 )
+
+
+#define DEFAULT_MAX_STR_TYPE 2 //##++ DEFAULT_N_STR_TYPE_GPS
+
+_ext STR_TYPE_INFO default_str_type_info[DEFAULT_MAX_STR_TYPE]
+#ifdef _DO_INIT
+ = {
+ { DEFAULT_STR_MODES, "Default Time String", "Time", 0 },
+ { DEFAULT_STR_MODES_UCAP, "Capture String", "Cap", 0 }
+ }
+#endif
+;
+
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ void port_info_from_pcps_serial( PORT_INFO_IDX *p_pii, PCPS_SERIAL pcps_serial, uint32_t supp_baud_rates ) ;
+ void pcps_serial_from_port_info( PCPS_SERIAL *p, const PORT_INFO_IDX *p_pii ) ;
+
+/* ----- function prototypes end ----- */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _PARMPCPS_H */
diff --git a/mbglib/common/pci_asic.h b/mbglib/common/pci_asic.h
new file mode 100644
index 0000000..8eb6371
--- /dev/null
+++ b/mbglib/common/pci_asic.h
@@ -0,0 +1,391 @@
+
+/**************************************************************************
+ *
+ * $Id: pci_asic.h 1.22 2011/10/05 09:46:12Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions for the Meinberg PCI interface ASIC.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pci_asic.h $
+ * Revision 1.22 2011/10/05 09:46:12Z martin
+ * Updated version info for GPS180PEX.
+ * Revision 1.21 2011/09/13 07:36:21Z martin
+ * Updated version info for GPS180PEX.
+ * Revision 1.20 2011/06/30 13:52:26Z martin
+ * Updated version info for GPS180PEX.
+ * Revision 1.19 2011/06/29 08:58:32Z martin
+ * Support PZF180PEX.
+ * Cleaned up handling of pragma pack().
+ * Revision 1.18 2011/04/06 12:31:48 martin
+ * Updated minor versions for PTP270PEX and GPS180PEX.
+ * Revision 1.17 2010/09/10 14:03:25Z martin
+ * Support GPS180PEX and TCR180PEX.
+ * New table initializer to simplify EPLD version checking.
+ * Revision 1.16 2010/04/16 11:12:21Z martin
+ * Updated GPS170PEX ASIC version.
+ * Revision 1.15 2009/03/27 09:39:15 martin
+ * Increased current ASIC minor number for TCR170PEX to 0x02.
+ * Renamed some symbols.
+ * Revision 1.14 2009/03/11 16:54:10Z martin
+ * Increased current ASIC minor number for TCR511PEX to 0x04.
+ * Fixed a typo.
+ * Revision 1.13 2008/12/05 12:28:18Z martin
+ * Modified syntax of macro _convert_asic_version_number().
+ * Added macros to deal with the ASIC version number.
+ * Added definition PCI_ASIC_HAS_PGMB_IRQ.
+ * Added ASIC revision numbers for PEX511, TCR511PEX, and GPS170PEX
+ * which fix an IRQ bug with these cards.
+ * Added definitions for PTP270PEX, FRC511PEX, and TCR170PEX.
+ * Revision 1.12 2008/07/21 10:30:00Z martin
+ * Added macros to convert the endianess of data types.
+ * Added PCI_ASIC_CURRENT_MINOR_... symbols.
+ * Revision 1.11 2008/06/11 09:49:43 martin
+ * Added definitions and comments how to handle version numbers
+ * of the PCI and PEX interface chips and EPLDs.
+ * Revision 1.10 2008/02/29 15:21:48Z martin
+ * Added definition PCI_ASIC_HAS_MM_IO.
+ * Revision 1.9 2008/01/17 09:51:05 daniel
+ * Added macro _convert_asic_version_number().
+ * Cleanup for PCI ASIC version and features.
+ * Revision 1.8 2006/06/14 12:59:12Z martin
+ * Added support for TCR511PCI.
+ * Revision 1.7 2006/03/10 10:47:03 martin
+ * Added support for PCI511.
+ * Revision 1.6 2005/11/03 15:30:44Z martin
+ * Added support for GPS170PCI.
+ * Revision 1.5 2004/11/09 12:51:56Z martin
+ * Redefined fixed width data types using standard C99 types.
+ * Defined some constants unsigned.
+ * Revision 1.4 2004/10/14 15:01:23 martin
+ * Added support for TCR167PCI.
+ * Revision 1.3 2003/05/13 14:38:55Z MARTIN
+ * Added ushort fields to unions PCI_ASIC_REG and
+ * PCI_ASIC_ADDON_DATA.
+ * Revision 1.2 2003/04/03 10:56:38 martin
+ * Use unions for registers.
+ * Modified BADR0 initializer due to fixed size of address decoder.
+ * Revision 1.1 2003/02/07 11:42:52 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PCI_ASIC_H
+#define _PCI_ASIC_H
+
+
+/* Other headers to be included */
+
+#include <words.h>
+#include <use_pack.h>
+
+#ifdef _PCI_ASIC
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+
+typedef struct
+{
+ uint32_t cfg_class_rev_id;
+ uint16_t cfg_badr_0;
+ uint16_t cfg_dev_id;
+} PCI_ASIC_CFG;
+
+
+typedef union
+{
+ uint32_t ul;
+ uint16_t us[2];
+ uint8_t b[4];
+} PCI_ASIC_REG;
+
+
+typedef uint32_t PCI_ASIC_VERSION;
+#define _mbg_swab_asic_version( _p ) _mbg_swab32( _p )
+
+typedef uint32_t PCI_ASIC_FEATURES;
+#define _mbg_swab_asic_features( _p ) _mbg_swab32( _p )
+
+#define PCI_ASIC_HAS_MM_IO 0x0001
+#define PCI_ASIC_HAS_PGMB_IRQ 0x0002
+
+
+typedef union
+{
+ uint32_t ul[4];
+ uint16_t us[8];
+ uint8_t b[16];
+} PCI_ASIC_ADDON_DATA;
+
+
+typedef struct
+{
+ PCI_ASIC_CFG cfg; // writeable from add-on once after power-up
+ PCI_ASIC_VERSION raw_version;
+ PCI_ASIC_FEATURES features;
+ PCI_ASIC_REG status_port;
+ PCI_ASIC_REG control_status; // codes defined below
+ PCI_ASIC_REG pci_data; // pass byte from PCI bus to add-on
+ PCI_ASIC_REG reserved_1;
+
+ PCI_ASIC_ADDON_DATA addon_data; // returns data from add-on to PCI bus
+ PCI_ASIC_ADDON_DATA reserved_2; // currently not implemented
+} PCI_ASIC;
+
+
+// The following bits are used with the control_status register.
+// All other bits are reserved for future use.
+
+// The IRQ flag for the add-on side is set whenever data is
+// written to the cmd register. It is cleared if the add-on
+// microcontroller writes this bit back to the control_status
+// register. If the bit is set, the add-on signals /ADD_ON_IRQ
+// and ADD_ON_BUSY are asserted.
+#define PCI_ASIC_ADD_ON_IRQF 0x00000001UL
+
+// The IRQ flag for the PCI bus is set whenever the add-on
+// microcontroller asserts the ASIC's /PCI_IRQ line, or the
+// add-on microcontroller sets this bit to 1. It is cleared
+// if this bit is written back from the PCI side. If the bit
+// is set, an IRQ is asserted on the PCI bus.
+#define PCI_ASIC_PCI_IRQF 0x00010000UL
+
+
+// The ASIC's address decoder always decodes 8 bits, so
+// each device must request at least that number of
+// addresses from the PCI BIOS:
+#define PCI_ASIC_ADDR_RANGE 0x100U
+
+
+// Initializers for device configurations
+
+#define PCPS_DEV_CLASS_CODE 0x08800000UL
+#define PCI_ASIC_BADR0_INIT ( ~( PCI_ASIC_ADDR_RANGE - 1 ) | 0x01 )
+
+
+#define PCI_ASIC_CFG_PCI510 \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_PCI510 ) \
+}
+
+#define PCI_ASIC_CFG_GPS169PCI \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_GPS169PCI ) \
+}
+
+#define PCI_ASIC_CFG_TCR510PCI \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_TCR510PCI ) \
+}
+
+#define PCI_ASIC_CFG_TCR167PCI \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_TCR167PCI ) \
+}
+
+#define PCI_ASIC_CFG_GPS170PCI \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_GPS170PCI ) \
+}
+
+#define PCI_ASIC_CFG_PCI511 \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_PCI511 ) \
+}
+
+#define PCI_ASIC_CFG_TCR511PCI \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_TCR511PCI ) \
+}
+
+/*
+ Handling of the version numbers of the PCI interface
+ chips has changed between the ASICs used for standard PCI
+ and the EPLDs used to configure the PEX8311 chip
+ for a specific device.
+
+ The macro below can be used to convert both types
+ of version number into the same format so that the
+ version numbers can be handled in the same way:
+*/
+#define _convert_asic_version_number( _n ) \
+ ( ( (_n) < 0x100 ) ? ( (_n) << 8 ) : (_n) )
+
+
+
+/*
+ * Macros to extract the major and minor part of an ASIC version number */
+
+#define _pcps_asic_version_major( _v ) \
+ ( ( (_v) >> 8 ) & 0xFF )
+
+#define _pcps_asic_version_minor( _v ) \
+ ( (_v) & 0xFF )
+
+
+/*
+ * Macros to check whether a version number is correct
+ * and matches a required minimum version
+ */
+#define _pcps_asic_version_greater_equal( _v, _v_major, _v_minor ) \
+ ( \
+ ( _pcps_asic_version_major( _v ) == (_v_major) ) && \
+ ( _pcps_asic_version_minor( _v ) >= (_v_minor) ) \
+ )
+
+
+/*
+ The low byte of the converted version number is handled
+ as a minor version, whereas the remaining upper bytes are
+ interpreted as a major number which may be specific
+ for a device.
+*/
+enum
+{
+ PCI_ASIC_MAJOR_PCI_0, // PCI ASIC with CRC bug
+ PCI_ASIC_MAJOR_PCI_1, // fixed version of PCI ASIC
+ PCI_ASIC_MAJOR_PEX511, // PEX EPLD for PEX511
+ PCI_ASIC_MAJOR_GPS170PEX, // PEX EPLD for GPS170PEX
+ PCI_ASIC_MAJOR_TCR511PEX, // PEX EPLD for TCR511PEX
+ PCI_ASIC_MAJOR_PTP270PEX, // PEX EPLD for PTP270PEX
+ PCI_ASIC_MAJOR_FRC511PEX, // PEX EPLD for FRC511PEX
+ PCI_ASIC_MAJOR_TCR170PEX, // PEX EPLD for TCR170PEX
+ PCI_ASIC_MAJOR_GPS180PEX, // PEX EPLD for GPS180PEX
+ PCI_ASIC_MAJOR_TCR180PEX, // PEX EPLD for TCR180PEX
+ PCI_ASIC_MAJOR_PZF180PEX, // PEX EPLD for PZF180PEX
+ N_PCI_ASIC_MAJOR // the number of known codes
+};
+
+/*
+ The minor number increases when a new EPLD image is released.
+ At least EPLD images with the following "required minor" numbers
+ should be installed for proper operation. The "current minor"
+ numbers can be used to check if a newer EPLD image is available:
+*/
+#define PCI_ASIC_CURRENT_MINOR_PEX511 0x04
+#define PCI_ASIC_REQUIRED_MINOR_PEX511 0x03
+#define PCI_ASIC_FIX_HRT_MINOR_PEX511 0x04 // increases HRT accuracy
+#define PCI_ASIC_FIX_IRQ_MINOR_PEX511 0x03 // fixes IRQ problem
+#define PCI_ASIC_HR_TIME_MINOR_PEX511 0x02 // supports HR time with PEX511
+
+#define PCI_ASIC_CURRENT_MINOR_GPS170PEX 0x05
+#define PCI_ASIC_REQUIRED_MINOR_GPS170PEX 0x03
+#define PCI_ASIC_ENH_HRT_MINOR_GPS170PEX 0x05 // enhanced MM HRT accuracy
+#define PCI_ASIC_FIX_HRT_MINOR_GPS170PEX 0x04 // increases MM HRT accuracy
+#define PCI_ASIC_FIX_IRQ_MINOR_GPS170PEX 0x03 // fixes IRQ problem
+
+#define PCI_ASIC_CURRENT_MINOR_TCR511PEX 0x04
+#define PCI_ASIC_REQUIRED_MINOR_TCR511PEX 0x03
+// 0x04 // EPLD sources shared with PEX511 0x04
+#define PCI_ASIC_FIX_IRQ_MINOR_TCR511PEX 0x03 // fixes IRQ problem, increases HRT accuracy
+
+#define PCI_ASIC_CURRENT_MINOR_PTP270PEX 0x02
+#define PCI_ASIC_REQUIRED_MINOR_PTP270PEX 0x01
+// 0x02 // increased accuracy of IRIG DCLS slopes
+// 0x01 // supports inversion of ucap slopes
+
+#define PCI_ASIC_CURRENT_MINOR_FRC511PEX 0x01
+#define PCI_ASIC_REQUIRED_MINOR_FRC511PEX 0x01
+
+#define PCI_ASIC_CURRENT_MINOR_TCR170PEX 0x03
+#define PCI_ASIC_REQUIRED_MINOR_TCR170PEX 0x02
+#define PCI_ASIC_FIX_EE_ACCESS_TCR170PEX 0x02 // fixes EE access problem after reset
+#define PCI_ASIC_FIX_FO_IN_LEVEL_TCR170PEX 0x03 // correct polarity for fiber optic input
+
+#define PCI_ASIC_CURRENT_MINOR_GPS180PEX 0x05
+#define PCI_ASIC_REQUIRED_MINOR_GPS180PEX 0x01
+// 0x01 // updated VHDL compiler and associated PCI primitives
+// 0x02 // I/O using 3.3V LVTTL
+// 0x03 // GPS TIC pulse len now 1 sample clock
+// 0x04 // Enabled PCI IRQ line which had unintentionally been disabled earlier
+// 0x05 // Increased accuracy of synthesizer output
+
+#define PCI_ASIC_CURRENT_MINOR_TCR180PEX 0x00
+#define PCI_ASIC_REQUIRED_MINOR_TCR180PEX 0x00
+
+#define PCI_ASIC_CURRENT_MINOR_PZF180PEX 0x00
+#define PCI_ASIC_REQUIRED_MINOR_PZF180PEX 0x00
+
+
+typedef struct
+{
+ unsigned int dev_type_num;
+ unsigned int major;
+ unsigned int current_minor;
+ unsigned int required_minor;
+} PCI_ASIC_VERSION_INFO;
+
+#define DEFAULT_PCI_ASIC_VERSION_INFO_TABLE \
+{ \
+ { PCPS_TYPE_PEX511, PCI_ASIC_MAJOR_PEX511, PCI_ASIC_CURRENT_MINOR_PEX511, PCI_ASIC_REQUIRED_MINOR_PEX511 }, \
+ { PCPS_TYPE_GPS170PEX, PCI_ASIC_MAJOR_GPS170PEX, PCI_ASIC_CURRENT_MINOR_GPS170PEX, PCI_ASIC_REQUIRED_MINOR_GPS170PEX }, \
+ { PCPS_TYPE_TCR511PEX, PCI_ASIC_MAJOR_TCR511PEX, PCI_ASIC_CURRENT_MINOR_TCR511PEX, PCI_ASIC_REQUIRED_MINOR_TCR511PEX }, \
+ { PCPS_TYPE_PTP270PEX, PCI_ASIC_MAJOR_PTP270PEX, PCI_ASIC_CURRENT_MINOR_PTP270PEX, PCI_ASIC_REQUIRED_MINOR_PTP270PEX }, \
+ { PCPS_TYPE_FRC511PEX, PCI_ASIC_MAJOR_FRC511PEX, PCI_ASIC_CURRENT_MINOR_FRC511PEX, PCI_ASIC_REQUIRED_MINOR_FRC511PEX }, \
+ { PCPS_TYPE_TCR170PEX, PCI_ASIC_MAJOR_TCR170PEX, PCI_ASIC_CURRENT_MINOR_TCR170PEX, PCI_ASIC_REQUIRED_MINOR_TCR170PEX }, \
+ { PCPS_TYPE_GPS180PEX, PCI_ASIC_MAJOR_GPS180PEX, PCI_ASIC_CURRENT_MINOR_GPS180PEX, PCI_ASIC_REQUIRED_MINOR_GPS180PEX }, \
+ { PCPS_TYPE_TCR180PEX, PCI_ASIC_MAJOR_TCR180PEX, PCI_ASIC_CURRENT_MINOR_TCR180PEX, PCI_ASIC_REQUIRED_MINOR_TCR180PEX }, \
+ { PCPS_TYPE_PZF180PEX, PCI_ASIC_MAJOR_PZF180PEX, PCI_ASIC_CURRENT_MINOR_PZF180PEX, PCI_ASIC_REQUIRED_MINOR_PZF180PEX }, \
+ { 0 } \
+}
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _PCI_ASIC_H */
+
diff --git a/mbglib/common/pcpsdefs.h b/mbglib/common/pcpsdefs.h
new file mode 100644
index 0000000..5726f58
--- /dev/null
+++ b/mbglib/common/pcpsdefs.h
@@ -0,0 +1,1496 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsdefs.h 1.50 2013/01/30 15:59:54Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * General definitions for Meinberg plug-in devices.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsdefs.h $
+ * Revision 1.50 2013/01/30 15:59:54Z martin
+ * Updated and fixed some doxygen comments.
+ * Revision 1.49 2012/10/02 18:53:02 martin
+ * Added structure PCPS_TIME_STATUS_X_MASKS.
+ * Added initializer for command names, useful for debugging.
+ * Revision 1.48 2011/11/25 15:02:28 martin
+ * Support on-board event logs.
+ * Revision 1.47 2011/11/25 10:22:44 martin
+ * Modified handling of pragma pack().
+ * Made command group codes obsolete. They are still supported
+ * when building firmware, though.
+ * Support PTP unicast configuration.
+ * Support GPIO configuration.
+ * Support PZF180PEX.
+ * Added commands to read CORR_INFO, read/write TR_DISTANCE,
+ * PCPS_SYNC_PZF status, and associated structures.
+ * Added an initializer for a table of GPS command code/names.
+ * Added definitions MBG_PCPS_FMT_STATUS.
+ * Updated some comments.
+ * Revision 1.46 2011/01/13 11:44:29Z martin
+ * Moved status port register definitions here.
+ * Revision 1.45 2010/09/06 07:36:24 martin
+ * Support GPS180PEX and TCR180PEX.
+ * Moved some IRIG related definitions to gpsdefs.h.
+ * Revision 1.44 2010/06/30 11:09:49 martin
+ * Added definitions for JJY longwave transmitter.
+ * Renamed MBG_RAW_IRIG_DATA::data field to data_bytes
+ * since "data" is a reserved word for C51 architecture.
+ * Revision 1.43 2010/02/09 11:20:17Z martin
+ * Renamed yet unused CORR_INFO::flags field to signal and updated comments.
+ * Revision 1.42 2010/01/12 14:02:37 daniel
+ * Added definitions to support reading the raw IRIG data bits.
+ * Revision 1.41 2009/06/19 12:16:42Z martin
+ * Added PCPS_GIVE_IRIG_TIME command and associated definitions.
+ * Revision 1.40 2009/06/08 19:29:11 daniel
+ * Support PTP configuration.
+ * Support LAN_IF configuration
+ * Added definition of PCPS_CMD_INFO.
+ * Revision 1.39 2009/03/19 08:58:09 martin
+ * Added PCPS_GET_IRIG_CTRL_BITS cmd and associated data type.
+ * Revision 1.38 2009/03/10 17:07:09 martin
+ * Support configurable time scales and GPS UTC parameters.
+ * Added ext. status flag for time scales, and PCPS_LS_ANN_NEG.
+ * Added bit mask PCPS_SCALE_MASK.
+ * Revision 1.37 2008/12/05 16:01:37Z martin
+ * Added ref types PTP, FRC, and WWVB.
+ * Added ref names MSF, PTP, FRC, and WWVB.
+ * Added device codes TCR170PEX, PTP270PEX, and FRC511PEX.
+ * Added macros to convert the endianess of structures.
+ * Moved definitions of PCPS_HRT_FRAC_SCALE and
+ * PCPS_HRT_FRAC_SCALE_FMT here.
+ * Added definitions of PCPS_HRT_FRAC_CONVERSION_TYPE
+ * and PCPS_HRT_BIN_FRAC_SCALE.
+ * Escaped '<' and '>' characters for doxygen.
+ * Modified comments for PCPS_TZDL.
+ * Removed trailing spaces and obsolete comments.
+ * Revision 1.36 2008/01/17 09:20:25Z daniel
+ * Added new REF type PCPS_REF_MSF.
+ * Revision 1.35 2008/01/17 09:18:46Z daniel
+ * Made comments compatible for doxygen parser.
+ * No sourcecode changes.
+ * Revision 1.34 2007/07/17 08:22:47Z martin
+ * Added support for TCR511PEX and GPS170PEX.
+ * Revision 1.33 2007/05/20 21:39:51Z martin
+ * Added support for PEX511.
+ * Added PCPS_GET_STATUS_PORT cmd code for devices
+ * that do not support a hardware status port.
+ * Revision 1.32 2007/03/29 12:57:32Z martin
+ * Renamed some TZCODE numbers for unique naming conventions.
+ * Added definitions of the older symbols for compatibility.
+ * Revision 1.31 2007/03/26 15:42:31Z martin
+ * Replaced PCPS_REF_OFFS and associated definitions by MBG_REF_OFFS, etc.,
+ * which are defined in gpsdefs.h.
+ * Added PCPS_GET_DEBUG_STATUS code.
+ * Revision 1.30 2006/06/29 10:13:13 martin
+ * Added some descriptive comments.
+ * Revision 1.29 2006/06/14 12:59:12Z martin
+ * Added support for TCR511PCI.
+ * Revision 1.28 2006/05/18 09:45:16 martin
+ * Added data types used with PZF receivers.
+ * Revision 1.27 2006/05/03 10:19:14Z martin
+ * Added initializers for reference source names.
+ * Revision 1.26 2006/03/10 10:24:45Z martin
+ * New definitions for PCI511.
+ * Added command codes to configure programmable pulse outputs.
+ * Revision 1.25 2005/11/03 15:05:16Z martin
+ * New definitions for GPS170PCI.
+ * New types PCPS_TIME_STATUS and PCPS_TIME_STATUS_X.
+ * Removed obsolete enumeration of PCPS_TIME fields.
+ * Revision 1.24 2005/05/03 07:56:55Z martin
+ * Added command PCPS_GET_SYNTH_STATE.
+ * Revision 1.23 2005/03/29 12:51:10Z martin
+ * New cmd code PCPS_GENERIC_IO.
+ * Revision 1.22 2004/12/09 11:03:37Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.21 2004/11/09 12:55:32Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Added workaround macros for some structure sizes because the C166
+ * compiler always reports an even structure size even if the structure
+ * size is in fact odd, which might lead to different sizes in C166 and
+ * other environments.
+ * Modifications were required in order to be able to configure IRIG
+ * settings of cards which provide both IRIG input and output.
+ * The existing codes have been renamed with .._RX.. and are used to
+ * configure the IRIG receiver (input). New codes have been defined
+ * used to configure the IRIG transmitter.
+ * Renamed PC_GPS_STAT to PC_GPS_BVAR_STAT.
+ * Use more specific data types than generic types.
+ * Revision 1.20 2004/10/14 15:01:23 martin
+ * Added support for TCR167PCI.
+ * Revision 1.19 2004/06/16 12:46:33Z martin
+ * Moved OPT_SETTINGS related definitions to gpsdefs.h,
+ * and renamed symbols from PCPS_.. to to MBG_...
+ * Revision 1.18 2004/04/26 14:27:08Z martin
+ * Added union PCPS_TIME_UNION.
+ * Revision 1.17 2003/05/27 08:50:35Z MARTIN
+ * New commands PCPS_GIVE_UCAP_ENTRIES, PCPS_GIVE_UCAP_EVENT
+ * and associated definitions which allow faster reading of
+ * user capture events and monitoring of the capture buffer
+ * fill level.
+ * Revision 1.16 2003/04/03 10:48:53 martin
+ * Support for PCI510, GPS169PCI, and TCR510PCI.
+ * New codes PCPS_GET_REF_OFFS, PCPS_SET_REF_OFFS
+ * and related structures.
+ * New codes PCPS_GET_OPT_INFO, PCPS_SET_OPT_SETTINGS
+ * and related structures.
+ * New codes PCPS_GET_IRIG_INFO, PCPS_SET_IRIG_SETTINGS.
+ * Preliminary PCPS_TZDL structure and cmd codes
+ * to read/write that structure.
+ * Revision 1.15 2002/08/08 13:24:03 MARTIN
+ * Moved definition of ref time sources here.
+ * Added new ref time source IRIG.
+ * Added new cmd to clear time capture buffer.
+ * Fixed some comments.
+ * Revision 1.14 2002/01/31 13:39:38 MARTIN
+ * Added new GPS data type codes for RECEIVER_INFO, etc.
+ * New PCPS_HR_TIME status flag PCPS_IO_BLOCKED.
+ * Moved REV_NUMs defining special features to pcpsdev.h.
+ * Removed obsolete initializer for framing string table.
+ * Updated some comments.
+ * Removed obsolete code.
+ * Revision 1.13 2001/12/03 16:15:14 martin
+ * Introduced PCPS_TIME_STAMP which allows to handle high precision
+ * time stamps.
+ * Replaced the sec/frac fields in PCPS_HR_TIME by PCPS_TIME_STAMP.
+ * This is compatible on byte level but may require source code
+ * modifications.
+ * Introduced new command PCPS_SET_EVENT_TIME which is used
+ * EXCLUSIVELY with a custom GPS firmware.
+ * Revision 1.12 2001/10/16 10:07:42 MARTIN
+ * Defined PCI509 firmware revision number which supports
+ * baud rate higher than standard.
+ * Revision 1.11 2001/03/30 13:02:39 MARTIN
+ * Control alignment of structures from new file use_pack.h.
+ * Defined initializers with valid framing parameters.
+ * Revision 1.10 2001/02/28 15:39:25 MARTIN
+ * Modified preprocessor syntax.
+ * Revision 1.9 2001/02/16 11:32:05 MARTIN
+ * Renamed "PROM" or "EPROM" in comments or and names to
+ * "FW" or firmware.
+ * This includes the cmd codes PCPS_GIVE_PROM_ID_... which have
+ * been renamed to PCPS_GIVE_FW_ID_...
+ * Renamed structure PCPS_TIME_SET to PCPS_STIME.
+ * Renamed return code PCPS_ERR_NONE to PCPS_SUCCESS.
+ * Modified some comments.
+ * Revision 1.8 2000/10/11 09:17:09 MARTIN
+ * Cleaned up comment syntax.
+ * Revision 1.7 2000/07/21 14:16:30 MARTIN
+ * Modified some comments.
+ * Added PCI definitions.
+ * Renamed PCPS_GET_GPS_DATA to PCPS_READ_GPS_DATA.
+ * Renamed PCPS_SET_GPS_DATA to PCPS_WRITE_GPS_DATA.
+ * New types PCPS_SERIAL and PCPS_TZCODE.
+ * Removed PCPS_SERIAL_BYTES and PCPS_TZCODE_BYTES, may use sizeof()
+ * the types instead.
+ * New type PCPS_TIME_SET which can be used to write date and time
+ * to the clock.
+ * Revision 1.6 2000/06/07 12:09:31 MARTIN
+ * renamed PCPS_SERIAL_GROUP to PCPS_CFG_GROUP
+ * renamed PCPS_ERR_SERIAL to PCPS_ERR_CFG
+ * modified definitions for baud rate, framing, and mode
+ * added PCPS_SN_... definitions
+ * added PCPS_GET_TZCODE and PCPS_SET_TZCODE definitions
+ * added PC_GPS_ANT_CABLE_LEN definition
+ * added RCS keywords
+ * updated some comments
+ *
+ * -----------------------------------------------------------------------
+ * Changes before put under RCS control:
+ *
+ * Revision 1.5 2000/03/24
+ * Introduced PCPS_GIVE_SERNUM
+ * Cleaned up for definitions for serial parameter byte
+ * Reviewed and updated comments.
+ *
+ * 1998/07/22
+ * Introduced PCPS_HR_TIME.
+ * Rearranged order of definitions.
+ * Reviewed and updated comments.
+ *
+ * 1997/06/12
+ * GPS definitions added.
+ *
+ * 1996/01/25
+ * PCPS_TIME redefined from an array of bytes to a structure.
+ *
+ **************************************************************************/
+
+#ifndef _PCPSDEFS_H
+#define _PCPSDEFS_H
+
+
+/* Other headers to be included */
+
+#include <words.h>
+#include <use_pack.h>
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+
+/**
+ * @brief Enumeration of the ref time signal sources used by Meinberg devices
+ */
+enum
+{
+ PCPS_REF_NONE, /**< (unknown or not defined) */
+ PCPS_REF_DCF, /**< see http://www.meinberg.de/english/info/dcf77.htm */
+ PCPS_REF_GPS, /**< see http://www.meinberg.de/english/info/gps.htm */
+ PCPS_REF_IRIG, /**< see http://www.meinberg.de/english/info/irig.htm */
+ PCPS_REF_MSF, /**< MSF Receiver (UK) */
+ PCPS_REF_PTP, /**< PTP/IEEE1588 network protocol */
+ PCPS_REF_FRC, /**< Free Running Clock */
+ PCPS_REF_WWVB, /**< WWVB Receiver (US) */
+ PCPS_REF_JJY, /**< JJY Receiver (Japan) */
+ N_PCPS_REF /**< number of valid ref time sources */
+};
+
+
+/* Initializers for the reference source names */
+
+#define PCPS_REF_NAME_NONE_ENG "unknown"
+#define PCPS_REF_NAME_NONE_GER "nicht bekannt"
+#define PCPS_REF_NAME_DCF "DCF77"
+#define PCPS_REF_NAME_GPS "GPS"
+#define PCPS_REF_NAME_IRIG "IRIG"
+#define PCPS_REF_NAME_MSF "MSF"
+#define PCPS_REF_NAME_PTP "PTP"
+#define PCPS_REF_NAME_FRC "FRC"
+#define PCPS_REF_NAME_WWVB "WWVB"
+#define PCPS_REF_NAME_JJY "JJY"
+
+
+#define PCPS_REF_NAMES_ENG \
+{ \
+ PCPS_REF_NAME_NONE_ENG, \
+ PCPS_REF_NAME_DCF, \
+ PCPS_REF_NAME_GPS, \
+ PCPS_REF_NAME_IRIG, \
+ PCPS_REF_NAME_MSF, \
+ PCPS_REF_NAME_PTP, \
+ PCPS_REF_NAME_FRC, \
+ PCPS_REF_NAME_WWVB, \
+ PCPS_REF_NAME_JJY \
+}
+
+
+#define PCPS_REF_NAMES_LSTR \
+{ \
+ { PCPS_REF_NAME_NONE_ENG, PCPS_REF_NAME_NONE_GER }, \
+ { PCPS_REF_NAME_DCF, NULL }, \
+ { PCPS_REF_NAME_GPS, NULL }, \
+ { PCPS_REF_NAME_IRIG, NULL }, \
+ { PCPS_REF_NAME_MSF, NULL }, \
+ { PCPS_REF_NAME_PTP, NULL }, \
+ { PCPS_REF_NAME_FRC, NULL }, \
+ { PCPS_REF_NAME_WWVB, NULL }, \
+ { PCPS_REF_NAME_JJY, NULL } \
+}
+
+
+
+/**
+ * @brief Meinberg PCI vendor ID (assigned by PCI SIG)
+ */
+#define PCI_VENDOR_MEINBERG 0x1360
+
+/* PCI device ID numbers (assigned by Meinberg) *
+ * High byte: type of ref time source
+ * Low Byte: enumeration of device types
+ */
+#define PCI_DEV_PCI32 ( ( PCPS_REF_DCF << 8 ) | 0x01 )
+#define PCI_DEV_PCI509 ( ( PCPS_REF_DCF << 8 ) | 0x02 )
+#define PCI_DEV_PCI510 ( ( PCPS_REF_DCF << 8 ) | 0x03 )
+#define PCI_DEV_PCI511 ( ( PCPS_REF_DCF << 8 ) | 0x04 )
+#define PCI_DEV_PEX511 ( ( PCPS_REF_DCF << 8 ) | 0x05 )
+#define PCI_DEV_PZF180PEX ( ( PCPS_REF_DCF << 8 ) | 0x06 )
+
+#define PCI_DEV_GPS167PCI ( ( PCPS_REF_GPS << 8 ) | 0x01 )
+#define PCI_DEV_GPS168PCI ( ( PCPS_REF_GPS << 8 ) | 0x02 )
+#define PCI_DEV_GPS169PCI ( ( PCPS_REF_GPS << 8 ) | 0x03 )
+#define PCI_DEV_GPS170PCI ( ( PCPS_REF_GPS << 8 ) | 0x04 )
+#define PCI_DEV_GPS170PEX ( ( PCPS_REF_GPS << 8 ) | 0x05 )
+#define PCI_DEV_GPS180PEX ( ( PCPS_REF_GPS << 8 ) | 0x06 )
+
+#define PCI_DEV_TCR510PCI ( ( PCPS_REF_IRIG << 8 ) | 0x01 )
+#define PCI_DEV_TCR167PCI ( ( PCPS_REF_IRIG << 8 ) | 0x02 )
+#define PCI_DEV_TCR511PCI ( ( PCPS_REF_IRIG << 8 ) | 0x03 )
+#define PCI_DEV_TCR511PEX ( ( PCPS_REF_IRIG << 8 ) | 0x04 )
+#define PCI_DEV_TCR170PEX ( ( PCPS_REF_IRIG << 8 ) | 0x05 )
+#define PCI_DEV_TCR180PEX ( ( PCPS_REF_IRIG << 8 ) | 0x06 )
+
+#define PCI_DEV_PTP270PEX ( ( PCPS_REF_PTP << 8 ) | 0x01 )
+
+#define PCI_DEV_FRC511PEX ( ( PCPS_REF_FRC << 8 ) | 0x01 )
+
+
+
+// definitions used for the status port register
+// (not to be intermixed with PCPS_TIME_STATUS)
+typedef uint8_t PCPS_STATUS_PORT; /**< see @ref group_status_port "Bitmask" */
+
+/**
+ * @defgroup group_status_port Bit masks of PCPS_STATUS_PORT
+ *
+ * Bit definitions used with the #PCPS_STATUS_PORT register.
+ *
+ * The flags #PCPS_ST_SEC and #PCPS_ST_MIN are cleared whenever the clock
+ * is read, so they are not very reliable in multitasking environments.
+ *
+ * @note The PCPS_ST_IRQF flag originates from old ISA cards.
+ * Some PCI cards also support this, but in case of PCI cards the
+ * associated flag of the PCI interface chip should be checked to see
+ * if a certain card has generated an IRQ on the PC bus.
+ *
+ * The macro _pcps_ddev_has_gen_irq() cares about this and should be used
+ * to determine in a portable way whether a card has generated an IRQ.
+ *
+ * @{ */
+
+#define PCPS_ST_BUSY 0x01 /**< the clock is busy filling the output FIFO */
+#define PCPS_ST_IRQF 0x02 /**< the clock has generated an IRQ on the PC bus (ISA only)*/
+#define PCPS_ST_MOD 0x20 /**< the raw demodulated DCF77 signal */
+#define PCPS_ST_SEC 0x40 /**< seconds have changed since last reading */
+#define PCPS_ST_MIN 0x80 /**< minutes have changed since last reading */
+
+/** @} group_status_port */
+
+/**
+ * A format string to be used with snprintb() which is available on some Unix
+ * systems to print information held in a bit coded variable.
+ */
+#define MBG_PCPS_FMT_STATUS \
+ "\177\20b\0FREER\0b\1DL_ENB\0b\2SYNCD\0b\3DL_ANN\0b\4UTC\0b\5LS_ANN\0b\6IFTM\0b\7INVT" \
+ "\0b\x08LS_ENB\0b\11ANT_FAIL\0b\x0aLS_ANN_NEG\0b\x0bSCALE_GPS\0b\x0cSCALE_TAI\0\0"
+
+
+
+/** @defgroup group_cmd_bytes Command bytes used to access the device
+
+ The commands described below are used to access computer peripherals
+ manufactured by Meinberg.
+
+ The header files pcpsdev.h and pcpsdrvr.h contain macros which can be
+ used to check if a detected device supports a certain feature or command.
+ If checking is required then the name of the macro is given in the
+ comments below.
+
+ Some commands expect parameters to be passed to the board. In that
+ case, the board returns the number of parameter bytes expected when
+ the command code is passed. Every parameter byte has to be supplied
+ to the board exactly like a command byte.
+ Refer to function pcps_write_data() and the macro _pcps_write_var()
+ for details.
+
+
+ - #PCPS_GIVE_TIME<br>
+ Return a PCPS_TIME structure with current date,
+ time and status. Supported by all clocks.
+
+ - #PCPS_GIVE_TIME_NOCLEAR<br>
+ Same as #PCPS_GIVE_TIME but the bits #PCPS_ST_SEC
+ and #PCPS_ST_MIN (see pcpsdev.h) of the status
+ port are not cleared.
+ Supported by all clocks except PC31/PS31 with
+ firmware version older than v3.0.
+ This is mainly used by the DOS TSR and should
+ not be used in other environments.
+
+ - #PCPS_GIVE_SYNC_TIME<br>
+ Return a ::PCPS_TIME structure with date and time
+ of last synchronization of the clock or
+ the last time set via the interface.
+ _pcps_has_sync_time() checks whether supported.
+
+ - #PCPS_GIVE_HR_TIME<br>
+ Return a PCPS_HR_TIME structure with current
+ date, time and status. This command should be
+ used to read the clock with higher resolution.
+ _pcps_has_hr_time() checks whether supported.
+
+ - #PCPS_GIVE_IRIG_TIME<br>
+ Return a PCPS_IRIG_TIME structure with day-of-year,
+ time and status as decoded from the IRIG signal.
+ _pcps_has_irig_time() checks whether supported.
+
+ - #PCPS_SET_TIME<br>
+ Set the board date, time and status. This
+ command expects sizeof( ::PCPS_STIME ) parameter
+ bytes.
+ _pcps_can_set_time() checks whether supported.
+
+ - #PCPS_SET_EVENT_TIME<br>
+ Send a high resolution time stamp to the clock to
+ configure a %UTC time when the clock shall generate
+ some event. This command expects a PCPS_TIME_STAMP
+ parameter.
+ _pcps_has_event_time() checks whether supported.
+ (requires custom GPS CERN firmware)
+
+ - #PCPS_IRQ_NONE<br>
+ Disable the board's hardware IRQ<br>
+ - #PCPS_IRQ_1_SEC<br>
+ Enable hardware IRQs once per second<br>
+ - #PCPS_IRQ_1_MIN<br>
+ Enable hardware IRQs once per minute<br>
+ - #PCPS_IRQ_10_MIN<br>
+ Enable hardware IRQs once per 10 minutes<br>
+ - #PCPS_IRQ_30_MIN<br>
+ Enable hardware IRQs once per 30 minutes<br>
+
+ - #PCPS_GET_SERIAL<br>
+ #PCPS_SET_SERIAL<br>
+ These commands read or set the configuration
+ of a clock's serial port COM0. The commands
+ expect PCPS_SERIAL_BYTES parameter bytes and
+ should be used preferably with the DCF77
+ clocks which have only one COM port.
+ _pcps_has_serial() checks whether supported.
+ Recent GPS clocks' COM ports should be cfg'd
+ using the structures RECEIVER_INFO, PORT_INFO,
+ and STR_TYPE_INFO.
+ _pcps_has_receiver_info() checks whether
+ these are supported. If they are not, then
+ the code #PC_GPS_PORT_PARM together with the
+ #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA
+ commands should be used.
+
+ - #PCPS_GET_TZCODE<br>
+ #PCPS_SET_TZCODE<br>
+ These commands read or set a DCF77 clock's
+ time zone code and should be used preferably
+ with the newer DCF77 clocks which have limited
+ support of different time zones.
+ _pcps_has_tzcode() checks whether supported.
+ A GPS clock's time zone must be cfg'd using
+ the code #PC_GPS_TZDL together with the
+ #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA
+ commands.
+
+ - #PCPS_GET_PCPS_TZDL<br>
+ #PCPS_SET_PCPS_TZDL<br>
+ These commands read or set a DCF77 clock's
+ time zone / daylight saving configuration.
+ _pcps_has_pcps_tzdl() checks whether supported.
+ A GPS clock's time zone must be cfg'd using
+ the code #PC_GPS_TZDL together with the
+ #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA
+ commands.
+
+ - #PCPS_GET_REF_OFFS<br>
+ #PCPS_SET_REF_OFFS<br>
+ These commands can be used to configure the
+ reference time offset from %UTC for clocks
+ which can't determine the offset automatically,
+ e.g. from an IRIG input signal.
+ _pcps_has_ref_offs() checks whether supported.
+
+ - #PCPS_GET_OPT_INFO<br>
+ #PCPS_SET_OPT_SETTINGS<br>
+ These commands can be used to configure some
+ optional settings, controlled by flags.
+ When reading, the clock returns a MBG_OPT_INFO
+ structure which contains the supported values,
+ plus the current settings.
+ When writing, clocks accepts a MBG_OPT_SETTINGS
+ structure only which contain the desired settings
+ of the supported flags only.
+ _pcps_has_opt_flags() checks whether supported.
+
+ - #PCPS_GET_IRIG_RX_INFO<br>
+ #PCPS_SET_IRIG_RX_SETTINGS<br>
+ #PCPS_GET_IRIG_TX_INFO<br>
+ #PCPS_SET_IRIG_TX_SETTINGS<br>
+ These commands can be used to configure IRIG
+ inputs and outputs.<br>
+ When reading, the clock returns an IRIG_INFO
+ structure which contains the supported values,
+ plus the current settings.<br>
+ When writing, clocks accepts an IRIG_SETTINGS
+ structure only which contain the desired settings
+ only. _pcps_is_irig_rx() and _pcps_is_irig_tx()
+ check whether supported.
+
+ - #PCPS_GET_IRIG_CTRL_BITS<br>
+ This command can be used to retrieve the control function
+ bits of the latest IRIG input frame. Those bits may carry
+ some well-known information as in the IEEE1344 code, but
+ may also contain some customized information, depending on
+ the IRIG frame type and the configuration of the IRIG generator.
+ So these bits are returned as-is and must be interpreted
+ by the application.
+ _pcps_has_irig_ctrl_bits() checks whether supported.
+
+ - #PCPS_GET_SYNTH<br>
+ #PCPS_SET_SYNTH<br>
+ #PCPS_GET_SYNTH_STATE<br>
+ These commands can be used to configure an on-board
+ frequency synthesizer and query the synthesizer
+ status. The commands are only supported if the board
+ supports the RECEIVER_INFO structure and the flag
+ #GPS_HAS_SYNTH is set in the RECEIVER_INFO::features.
+ _pcps_has_synth() checks whether supported.
+ The structures SYNTH and SYNTH_STATE used with these
+ commands are defined in gpsdefs.h.
+
+ - #PCPS_GIVE_FW_ID_1<br>
+ #PCPS_GIVE_FW_ID_2<br>
+ Returns the first/second block of PCPS_FIFO_SIZE
+ characters of the firmware ID string. These
+ commands can be used to check if the board
+ responds properly. This is done by the clock
+ detection functions.
+
+ - #PCPS_GIVE_SERNUM<br>
+ Returns PCPS_FIFO_SIZE characters of the
+ clock's serial number.
+ _pcps_has_sernum() checks whether supported.
+
+ - #PCPS_GENERIC_IO<br>
+ Generic I/O read and write. Can be used to query
+ specific data, e.g. a selected element of an array.
+ _pcps_has_generic_io() checks whether supported.
+
+ - #PCPS_GET_DEBUG_STATUS<br>
+ This command reads a MBG_DEBUG_STATUS structure
+ which represents the internal status of the
+ IRIG decoder and some additional debug info.
+ _pcps_has_debug_status() checks whether supported.
+
+ - #PCPS_READ_GPS_DATA<br>
+ #PCPS_WRITE_GPS_DATA<br>
+ These commands are used by the functions
+ pcps_read_gps_data() and pcps_write_gps_data()
+ to read or write large data structures to
+ Meinberg GPS plug-in clocks.
+ _pcps_is_gps() checks whether supported.
+
+ - #PCPS_CLR_UCAP_BUFF<br>
+ Clear a clock's time capture buffer.
+ _pcps_can_clr_ucap_buff() checks whether
+ supported.
+
+ - #PCPS_GIVE_UCAP_ENTRIES<br>
+ Read a PCPS_UCAP_ENTRIES structure which
+ reports the max number of entries and the
+ currently used number of entries in the
+ user capture buffer.
+ _pcps_has_ucap() checks whether supported.
+
+ - #PCPS_GIVE_UCAP_EVENT<br>
+ Read capture events using a PCPS_HR_TIME
+ structure. This is faster than reading using the
+ GPS command #PC_GPS_UCAP. If no capture event is
+ available then the structure is filled with 0s.
+ _pcps_has_ucap() checks whether supported.
+
+ - #PCPS_GET_CORR_INFO<br>
+ Read PZF correlation info using a CORR_INFO
+ structure.
+ _pcps_has_pzf() checks whether supported.
+
+ - #PCPS_GET_TR_DISTANCE<br>
+ #PCPS_SET_TR_DISTANCE<br>
+ Read or write distance from the RF transmitter.
+ This is used to compensate the RF propagation delay
+ for PZF receivers.
+ _pcps_has_tr_distance() checks whether supported.
+
+ - #PCPS_CLR_EVT_LOG<br>
+ Clear on-board event log.
+ _pcps_has_evt_log() checks whether supported.
+
+ - #PCPS_NUM_EVT_LOG_ENTRIES<br>
+ Read max number of num event log entries which can
+ be saved on the board, and how many entries actually
+ have been saved.
+ _pcps_has_evt_log() checks whether supported.
+
+ - #PCPS_FIRST_EVT_LOG_ENTRY<br>
+ - #PCPS_NEXT_EVT_LOG_ENTRY<br>
+ Read first (oldest) or next event log entry.
+ _pcps_has_evt_log() checks whether supported.
+
+ - #PCPS_FORCE_RESET<br>
+ Resets the microprocessor on the device. This is
+ for special test scenarios only and should not be
+ used by standard applications since this may lock up
+ the PC.
+
+ The command codes listed above are defined below.
+
+ @{ */
+
+
+#if _IS_MBG_FIRMWARE //##++
+
+// These group codes are obsolete and should be removed.
+// The explicite command codes defined below should be used instead.
+#define PCPS_GIVE_TIME_GROUP 0x00
+#define PCPS_SET_TIME_GROUP 0x10
+#define PCPS_IRQ_GROUP 0x20
+#define PCPS_CFG_GROUP 0x30
+#define PCPS_GIVE_DATA_GROUP 0x40
+#define PCPS_GPS_DATA_GROUP 0x50
+#define PCPS_CTRL_GROUP 0x60
+#define PCPS_CFG2_GROUP 0x70
+
+#endif
+
+
+
+#define PCPS_GIVE_TIME 0x00
+#define PCPS_GIVE_TIME_NOCLEAR 0x01
+#define PCPS_GIVE_SYNC_TIME 0x02 // only supported if _pcps_has_sync_time()
+#define PCPS_GIVE_HR_TIME 0x03 // only supported if _pcps_has_hr_time()
+#define PCPS_GIVE_IRIG_TIME 0x04 // only supported if _pcps_has_irig_time()
+
+#define PCPS_SET_TIME 0x10
+/* on error, return PCPS_ERR_STIME */
+
+/* Attention: The code below can be used EXCLUSIVELY */
+/* with a GPS167PCI with customized CERN firmware !! */
+/* _pcps_has_event_time() checks whether supported. */
+#define PCPS_SET_EVENT_TIME 0x14
+
+#define PCPS_IRQ_NONE 0x20
+#define PCPS_IRQ_1_SEC 0x21
+#define PCPS_IRQ_1_MIN 0x22
+#define PCPS_IRQ_10_MIN 0x24
+#define PCPS_IRQ_30_MIN 0x28
+
+#define PCPS_GET_SERIAL 0x30
+#define PCPS_SET_SERIAL 0x31
+/* on error, return PCPS_ERR_CFG */
+
+typedef uint8_t PCPS_SERIAL;
+
+
+#define PCPS_GET_TZCODE 0x32
+#define PCPS_SET_TZCODE 0x33
+/* on error, return PCPS_ERR_CFG */
+
+typedef uint8_t PCPS_TZCODE;
+
+/**
+ * @brief Enumeration of codes used with PCPS_TZCODE
+ */
+enum PCPS_TZCODES
+{
+ PCPS_TZCODE_CET_CEST, /* default as broadcasted by DCF77 (UTC+1h/UTC+2h) */
+ PCPS_TZCODE_CET, /* always CET (UTC+1h), discard DST */
+ PCPS_TZCODE_UTC, /* always %UTC */
+ PCPS_TZCODE_EET_EEST, /* East European Time, CET/CEST + 1h */
+ N_PCPS_TZCODE /* the number of valid codes */
+};
+
+/* the definitions below are for compatibily only: */
+#define PCPS_TZCODE_MEZMESZ PCPS_TZCODE_CET_CEST
+#define PCPS_TZCODE_MEZ PCPS_TZCODE_CET
+#define PCPS_TZCODE_OEZ PCPS_TZCODE_EET_EEST
+
+
+#define PCPS_GET_PCPS_TZDL 0x34
+#define PCPS_SET_PCPS_TZDL 0x35
+/* on error, return PCPS_ERR_CFG */
+
+
+/**
+ * The structures below can be used to configure a clock's
+ * time zone/daylight saving setting. This structure is shorter
+ * than the TZDL structure used with GPS clocks.
+ */
+typedef struct
+{
+ // The year_or_wday field below contains the full year number
+ // or 0..6 == Sun..Sat if the DL_AUTO_FLAG is set; see below.
+ uint16_t year_or_wday;
+ uint8_t month;
+ uint8_t mday;
+ uint8_t hour;
+ uint8_t min;
+} PCPS_DL_ONOFF;
+
+#define _mbg_swab_pcps_dl_onoff( _p ) \
+{ \
+ _mbg_swab16( &(_p)->year_or_wday ); \
+}
+
+/**
+ * If the field year_or_wday is or'ed with the constant DL_AUTO_FLAG
+ * defined below then this means that start and end of daylight saving
+ * time shall be computed automatically for each year. In this case
+ * the remaining bits represent the day-of-week after the specified
+ * mday/month at which the change shall occur. If that flag is not set
+ * then the field contains the full four-digit year number and the
+ * mday/month values specify the exact date of that year.
+ */
+#define DL_AUTO_FLAG 0x8000 // also defined in gpsdefs.h
+
+typedef struct
+{
+ int16_t offs; /**< offset from %UTC to local time [min] */
+ int16_t offs_dl; /**< additional offset if DST enabled [min] */
+ PCPS_DL_ONOFF tm_on; /**< date/time when daylight saving starts */
+ PCPS_DL_ONOFF tm_off; /**< date/time when daylight saving ends */
+} PCPS_TZDL;
+
+#define _mbg_swab_pcps_tzdl( _p ) \
+{ \
+ _mbg_swab16( &(_p)->offs ); \
+ _mbg_swab16( &(_p)->offs_dl ); \
+ _mbg_swab_pcps_dl_onoff( &(_p)->tm_on ); \
+ _mbg_swab_pcps_dl_onoff( &(_p)->tm_off ); \
+}
+
+
+
+#define PCPS_GET_REF_OFFS 0x36
+#define PCPS_SET_REF_OFFS 0x37
+/* on error, return PCPS_ERR_CFG */
+
+/* The associated type MBG_REF_OFFS is defined in gpsdefs.h. */
+
+
+#define PCPS_GET_OPT_INFO 0x38
+#define PCPS_SET_OPT_SETTINGS 0x39
+/* on error, return PCPS_ERR_CFG */
+
+/* The associated structures MBG_OPT_INFO and MBG_OPT_SETTINGS
+ are defined in gpsdefs.h. */
+
+
+#define PCPS_GET_IRIG_RX_INFO 0x3A
+#define PCPS_SET_IRIG_RX_SETTINGS 0x3B
+/* on error, return PCPS_ERR_CFG */
+
+#define PCPS_GET_IRIG_TX_INFO 0x3C
+#define PCPS_SET_IRIG_TX_SETTINGS 0x3D
+/* on error, return PCPS_ERR_CFG */
+
+/* The associated structures IRIG_INFO and IRIG_SETTINGS
+ are defined in gpsdefs.h. */
+
+
+#define PCPS_GET_SYNTH 0x3E
+#define PCPS_SET_SYNTH 0x3F
+/* on error, return PCPS_ERR_CFG */
+
+/* The associated structure SYNTH is defined in gpsdefs.h. */
+
+
+#define PCPS_GIVE_FW_ID_1 0x40
+#define PCPS_GIVE_FW_ID_2 0x41
+#define PCPS_GIVE_SERNUM 0x42
+#define PCPS_GENERIC_IO 0x43
+#define PCPS_GET_SYNTH_STATE 0x44
+#define PCPS_GET_IRIG_CTRL_BITS 0x45
+#define PCPS_GET_RAW_IRIG_DATA 0x46
+
+
+
+#define PCPS_GET_STATUS_PORT 0x4B
+#define PCPS_GET_DEBUG_STATUS 0x4C
+// expects sizeof( MBG_DEBUG_STATUS ) chars
+
+// Command codes 0x4D, 0x4E, and 0x4F are reserved.
+
+
+#define PCPS_READ_GPS_DATA 0x50
+#define PCPS_WRITE_GPS_DATA 0x51
+
+#define PCPS_CLR_UCAP_BUFF 0x60
+#define PCPS_GIVE_UCAP_ENTRIES 0x61
+#define PCPS_GIVE_UCAP_EVENT 0x62
+
+typedef struct
+{
+ uint32_t used; /**< the number of saved capture events */
+ uint32_t max; /**< capture buffer size */
+} PCPS_UCAP_ENTRIES;
+
+#define _mbg_swab_pcps_ucap_entries( _p ) \
+{ \
+ _mbg_swab32( &(_p)->used ); \
+ _mbg_swab32( &(_p)->max ); \
+}
+
+
+
+#define PCPS_GET_CORR_INFO 0x63 // read CORR_INFO structure, only if _pcps_has_pzf()
+#define PCPS_GET_TR_DISTANCE 0x64 // read TR_DISTANCE, only if _pcps_has_tr_distance()
+#define PCPS_SET_TR_DISTANCE 0x65 // write TR_DISTANCE, only if _pcps_has_tr_distance()
+
+
+#define PCPS_CLR_EVT_LOG 0x66 // clear on-board event log, only if _pcps_has_evt_log()
+#define PCPS_NUM_EVT_LOG_ENTRIES 0x67 // read num event log entries, only if _pcps_has_evt_log()
+#define PCPS_FIRST_EVT_LOG_ENTRY 0x68 // read first (oldest) event log entry, only if _pcps_has_evt_log()
+#define PCPS_NEXT_EVT_LOG_ENTRY 0x69 // read next event log entry, only if _pcps_has_evt_log()
+
+
+/**
+ special -- use with care !
+*/
+#define PCPS_FORCE_RESET 0x80
+
+// Command codes 0xF0 through 0xFF are reserved.
+
+/** @} group_cmd_bytes */
+
+
+#if !defined( MBG_CMD_TABLE_EXT )
+ #define MBG_CMD_TABLE_EXT { 0, NULL }
+#endif
+
+/**
+ * @brief An initializer for a table of code/name entries of non-GPS commands.
+ *
+ * This can e.g. be assigned to an array of MBG_CODE_NAME_TABLE_ENTRY elements
+ * and may be helpful when debugging.
+ */
+#define MBG_CMD_TABLE \
+{ \
+ { PCPS_GIVE_TIME, "PCPS_GIVE_TIME" }, /* 00 */ \
+ { PCPS_GIVE_TIME_NOCLEAR, "PCPS_GIVE_TIME_NOCLEAR" }, /* 01 */ \
+ { PCPS_GIVE_SYNC_TIME, "PCPS_GIVE_SYNC_TIME" }, /* 02 */ \
+ { PCPS_GIVE_HR_TIME, "PCPS_GIVE_HR_TIME" }, /* 03 */ \
+ { PCPS_GIVE_IRIG_TIME, "PCPS_GIVE_IRIG_TIME" }, /* 04 */ \
+ { PCPS_SET_TIME, "PCPS_SET_TIME" }, /* 10 */ \
+ { PCPS_SET_EVENT_TIME, "PCPS_SET_EVENT_TIME" }, /* 14 */ \
+ { PCPS_IRQ_NONE, "PCPS_IRQ_NONE" }, /* 20 */ \
+ { PCPS_IRQ_1_SEC, "PCPS_IRQ_1_SEC" }, /* 21 */ \
+ { PCPS_IRQ_1_MIN, "PCPS_IRQ_1_MIN" }, /* 22 */ \
+ { PCPS_IRQ_10_MIN, "PCPS_IRQ_10_MIN" }, /* 24 */ \
+ { PCPS_IRQ_30_MIN, "PCPS_IRQ_30_MIN" }, /* 28 */ \
+ { PCPS_GET_SERIAL, "PCPS_GET_SERIAL" }, /* 30 */ \
+ { PCPS_SET_SERIAL, "PCPS_SET_SERIAL" }, /* 31 */ \
+ { PCPS_GET_TZCODE, "PCPS_GET_TZCODE" }, /* 32 */ \
+ { PCPS_SET_TZCODE, "PCPS_SET_TZCODE" }, /* 33 */ \
+ { PCPS_GET_PCPS_TZDL, "PCPS_GET_PCPS_TZDL" }, /* 34 */ \
+ { PCPS_SET_PCPS_TZDL, "PCPS_SET_PCPS_TZDL" }, /* 35 */ \
+ { PCPS_GET_REF_OFFS, "PCPS_GET_REF_OFFS" }, /* 36 */ \
+ { PCPS_SET_REF_OFFS, "PCPS_SET_REF_OFFS" }, /* 37 */ \
+ { PCPS_GET_OPT_INFO, "PCPS_GET_OPT_INFO" }, /* 38 */ \
+ { PCPS_SET_OPT_SETTINGS, "PCPS_SET_OPT_SETTINGS" }, /* 39 */ \
+ { PCPS_GET_IRIG_RX_INFO, "PCPS_GET_IRIG_RX_INFO" }, /* 3A */ \
+ { PCPS_SET_IRIG_RX_SETTINGS, "PCPS_SET_IRIG_RX_SETTINGS" }, /* 3B */ \
+ { PCPS_GET_IRIG_TX_INFO, "PCPS_GET_IRIG_TX_INFO" }, /* 3C */ \
+ { PCPS_SET_IRIG_TX_SETTINGS, "PCPS_SET_IRIG_TX_SETTINGS" }, /* 3D */ \
+ { PCPS_GET_SYNTH, "PCPS_GET_SYNTH" }, /* 3E */ \
+ { PCPS_SET_SYNTH, "PCPS_SET_SYNTH" }, /* 3F */ \
+ { PCPS_GIVE_FW_ID_1, "PCPS_GIVE_FW_ID_1" }, /* 40 */ \
+ { PCPS_GIVE_FW_ID_2, "PCPS_GIVE_FW_ID_2" }, /* 41 */ \
+ { PCPS_GIVE_SERNUM, "PCPS_GIVE_SERNUM" }, /* 42 */ \
+ { PCPS_GENERIC_IO, "PCPS_GENERIC_IO" }, /* 43 */ \
+ { PCPS_GET_SYNTH_STATE, "PCPS_GET_SYNTH_STATE" }, /* 44 */ \
+ { PCPS_GET_IRIG_CTRL_BITS, "PCPS_GET_IRIG_CTRL_BITS" }, /* 45 */ \
+ { PCPS_GET_RAW_IRIG_DATA, "PCPS_GET_RAW_IRIG_DATA" }, /* 46 */ \
+ { PCPS_GET_STATUS_PORT, "PCPS_GET_STATUS_PORT" }, /* 4B */ \
+ { PCPS_GET_DEBUG_STATUS, "PCPS_GET_DEBUG_STATUS" }, /* 4C */ \
+ { PCPS_READ_GPS_DATA, "PCPS_READ_GPS_DATA" }, /* 50 */ \
+ { PCPS_WRITE_GPS_DATA, "PCPS_WRITE_GPS_DATA" }, /* 51 */ \
+ { PCPS_CLR_UCAP_BUFF, "PCPS_CLR_UCAP_BUFF" }, /* 60 */ \
+ { PCPS_GIVE_UCAP_ENTRIES, "PCPS_GIVE_UCAP_ENTRIES" }, /* 61 */ \
+ { PCPS_GIVE_UCAP_EVENT, "PCPS_GIVE_UCAP_EVENT" }, /* 62 */ \
+ { PCPS_GET_CORR_INFO, "PCPS_GET_CORR_INFO" }, /* 63 */ \
+ { PCPS_GET_TR_DISTANCE, "PCPS_GET_TR_DISTANCE" }, /* 64 */ \
+ { PCPS_SET_TR_DISTANCE, "PCPS_SET_TR_DISTANCE" }, /* 65 */ \
+ { PCPS_CLR_EVT_LOG, "PCPS_CLR_EVT_LOG" }, /* 66 */ \
+ { PCPS_NUM_EVT_LOG_ENTRIES, "PCPS_NUM_EVT_LOG_ENTRIES" }, /* 67 */ \
+ { PCPS_FIRST_EVT_LOG_ENTRY, "PCPS_FIRST_EVT_LOG_ENTRY" }, /* 68 */ \
+ { PCPS_NEXT_EVT_LOG_ENTRY, "PCPS_NEXT_EVT_LOG_ENTRY" }, /* 69 */ \
+ { PCPS_FORCE_RESET, "PCPS_FORCE_RESET" }, /* 80 */ \
+ MBG_CMD_TABLE_EXT, \
+ { 0, NULL } \
+}
+
+
+
+/* Codes returned when commands with parameters have been passed */
+/* to the board */
+#define PCPS_SUCCESS 0 /**< OK, no error */
+#define PCPS_ERR_STIME -1 /**< invalid date/time/status passed */
+#define PCPS_ERR_CFG -2 /**< invalid parms for a cmd writing config parameters */
+
+
+
+#ifndef BITMASK
+ #define BITMASK( b ) ( ( 1 << b ) - 1 )
+#endif
+
+
+/** The size of the plug-in card's on-board FIFO */
+#define PCPS_FIFO_SIZE 16
+
+typedef int8_t PCPS_BUFF[PCPS_FIFO_SIZE];
+
+
+#define PCPS_ID_SIZE ( 2 * PCPS_FIFO_SIZE + 1 ) /**< ASCIIZ string */
+typedef char PCPS_ID_STR[PCPS_ID_SIZE];
+
+
+#define PCPS_SN_SIZE ( PCPS_FIFO_SIZE + 1 ) /**< ASCIIZ string */
+typedef char PCPS_SN_STR[PCPS_SN_SIZE];
+
+
+/**
+ * The structure has been introduced to be able to handle
+ * high resolution time stamps.
+ */
+typedef struct
+{
+ uint32_t sec; /**< seconds since 1970 (UTC) */
+ uint32_t frac; /**< fractions of second ( 0xFFFFFFFF == 0.9999.. sec) */
+} PCPS_TIME_STAMP;
+
+#define _mbg_swab_pcps_time_stamp( _p ) \
+{ \
+ _mbg_swab32( &(_p)->sec ); \
+ _mbg_swab32( &(_p)->frac ); \
+}
+
+
+
+// Depending on the target environment define a data type
+// which can be used to convert binary fractions without
+// range overflow.
+#if defined( MBG_TGT_UNIX )
+ #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t
+#elif defined( MBG_TGT_WIN32 )
+ #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t
+#elif defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 )
+ #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t
+#else
+ #define PCPS_HRT_FRAC_CONVERSION_TYPE double
+#endif
+
+// Max value of PCPS_TIME_STAMP::frac + 1 used for scaling
+#define PCPS_HRT_BIN_FRAC_SCALE ( (PCPS_HRT_FRAC_CONVERSION_TYPE) 4294967296.0 ) // == 0x100000000
+
+
+// The scale and format to be used to print the fractions
+// of a second as returned in the PCPS_TIME_STAMP structure.
+// The function frac_sec_from_bin() can be used for
+// the conversion.
+#ifndef PCPS_HRT_FRAC_SCALE
+ #define PCPS_HRT_FRAC_SCALE 10000000UL
+#endif
+
+#ifndef PCPS_HRT_FRAC_SCALE_FMT
+ #define PCPS_HRT_FRAC_SCALE_FMT "%07lu"
+#endif
+
+
+
+typedef uint16_t PCPS_TIME_STATUS_X; /**< extended status */
+
+#define _mbg_swab_pcps_time_status_x( _p ) _mbg_swab16( _p )
+
+
+typedef struct
+{
+ PCPS_TIME_STATUS_X set_mask;
+ PCPS_TIME_STATUS_X clr_mask;
+
+} PCPS_TIME_STATUS_X_MASKS;
+
+#define _mbg_swab_pcps_time_status_x_masks( _p ) \
+{ \
+ _mbg_swab_pcps_time_status_x( &(_p)->set_mask ); \
+ _mbg_swab_pcps_time_status_x( &(_p)->clr_mask ); \
+}
+
+
+
+/**
+ * The structure has been introduced to be able to read the
+ * current time with higher resolution of fractions of seconds and
+ * more detailed information on the time zone and status.
+ * The structure is returned if the new command #PCPS_GIVE_HR_TIME
+ * is written to the board.
+ * _pcps_has_hr_time() checks whether supported.
+ *
+ * Newer GPS boards also accept the #PCPS_GIVE_UCAP_EVENT command
+ * to return user capture event times using this format. In this
+ * case, the "signal" field contains the number of the capture
+ * input line, e.g. 0 or 1.
+ * _pcps_has_ucap() checks whether supported.
+ */
+typedef struct
+{
+ PCPS_TIME_STAMP tstamp; /**< High resolution time stamp (UTC) */
+ int32_t utc_offs; /**< %UTC offs [sec] (loc_time = %UTC + utc_offs) */
+ PCPS_TIME_STATUS_X status; /**< status flags as defined below */
+ uint8_t signal; /**< for normal time, the relative RF signal level, for ucap, the channel number */
+} PCPS_HR_TIME;
+
+#define _mbg_swab_pcps_hr_time( _p ) \
+{ \
+ _mbg_swab_pcps_time_stamp( &(_p)->tstamp ); \
+ _mbg_swab32( &(_p)->utc_offs ); \
+ _mbg_swab_pcps_time_status_x( &(_p)->status ); \
+}
+
+
+typedef uint8_t PCPS_TIME_STATUS;
+
+/**
+ The standard structure used to read times from the board.
+ The time has a resultion of 10 ms.
+*/
+typedef struct PCPS_TIME_s
+{
+ uint8_t sec100; /**< hundredths of seconds, 0..99 */
+ uint8_t sec; /**< seconds, 0..59, or 60 if leap second */
+ uint8_t min; /**< minutes, 0..59 */
+ uint8_t hour; /**< hours, 0..23 */
+
+ uint8_t mday; /**< day of month, 0..31 */
+ uint8_t wday; /**< day of week, 1..7, 1 = Monday */
+ uint8_t month; /**< month, 1..12 */
+ uint8_t year; /**< year of the century, 0..99 */
+
+ PCPS_TIME_STATUS status; /**< status bits, see below */
+ uint8_t signal; /**< relative signal strength, range depends on device type */
+ int8_t offs_utc; /**< [hours], 0 if !_pcps_has_utc_offs() */
+} PCPS_TIME;
+
+
+/**
+ The structure is passed as parameter with the PCPS_SET_TIME cmd
+*/
+typedef struct PCPS_STIME_s
+{
+ uint8_t sec100; /**< hundredths of seconds, 0..99 */
+ uint8_t sec; /**< seconds, 0..59, or 60 if leap second */
+ uint8_t min; /**< minutes, 0..59 */
+ uint8_t hour; /**< hours, 0..23 */
+
+ uint8_t mday; /**< day of month, 0..31 */
+ uint8_t wday; /**< day of week, 1..7, 1 = Monday */
+ uint8_t month; /**< month, 1..12 */
+ uint8_t year; /**< year of the century, 0..99 */
+
+ PCPS_TIME_STATUS status; /**< status bits, see below */
+} PCPS_STIME;
+
+#ifdef _C166
+ // This is a workaround to specify some structure sizes. The C166 compiler
+ // always reports an even structure size although the structure size may
+ // be odd due to the number of bytes. This might lead to errors between
+ // the C166 and other build environments.
+ #define sizeof_PCPS_TIME ( sizeof( PCPS_TIME ) - 1 )
+ #define sizeof_PCPS_STIME ( sizeof( PCPS_STIME ) - 1 )
+#else
+ #define sizeof_PCPS_TIME sizeof( PCPS_TIME )
+ #define sizeof_PCPS_STIME sizeof( PCPS_STIME )
+#endif
+
+typedef union
+{
+ PCPS_TIME t;
+ PCPS_STIME stime;
+} PCPS_TIME_UNION;
+
+
+
+/**
+ The structure below can be used to read the raw IRIG time
+ from an IRIG receiver card, if the card supports this.
+ See the #PCPS_GIVE_IRIG_TIME command.
+
+ The granularity of the value in the .frac field depends on
+ the update interval of the structure as implementation
+ in the firmware. I.e. if the raw IRIG time is updated
+ only once per second, the .frac value can always be 0.
+*/
+typedef struct PCPS_IRIG_TIME_s
+{
+ PCPS_TIME_STATUS_X status; /**< status bits, see below */
+ int16_t offs_utc; /**< [minutes] */
+ uint16_t yday; /**< day of year, 1..365/366 */
+ uint16_t frac; /**< fractions of seconds, 0.1 ms units */
+ uint8_t sec; /**< seconds, 0..59, or 60 if leap second */
+ uint8_t min; /**< minutes, 0..59 */
+ uint8_t hour; /**< hours, 0..23 */
+ uint8_t year; /**< 2 digit year number, 0xFF if year not supp. by the IRIG code */
+ uint8_t signal; /**< relative signal strength, range depends on device type */
+ uint8_t reserved; /**< currently not used, always 0 */
+} PCPS_IRIG_TIME;
+
+#define _mbg_swab_pcps_irig_time( _p ) \
+{ \
+ _mbg_swab_pcps_time_status_x( &(_p)->status ); \
+ _mbg_swab16( &(_p)->offs_utc ); \
+ _mbg_swab16( &(_p)->yday ); \
+ _mbg_swab16( &(_p)->frac ); \
+}
+
+
+
+
+/**
+ * Bit masks used with both PCPS_TIME_STATUS and PCPS_TIME_STATUS_X
+ */
+#define PCPS_FREER 0x01 /**< DCF77 clock running on xtal */
+ /**< GPS receiver has not verified its position */
+
+#define PCPS_DL_ENB 0x02 /**< daylight saving enabled */
+
+#define PCPS_SYNCD 0x04 /**< clock has sync'ed at least once after pwr up */
+
+#define PCPS_DL_ANN 0x08 /**< a change in daylight saving is announced */
+
+#define PCPS_UTC 0x10 /**< a special %UTC firmware is installed */
+
+#define PCPS_LS_ANN 0x20 /**< leap second announced */
+ /**< (requires firmware rev. REV_PCPS_LS_ANN_...) */
+
+#define PCPS_IFTM 0x40 /**< the current time was set via PC */
+ /**< (requires firmware rev. REV_PCPS_IFTM_...) */
+
+#define PCPS_INVT 0x80 /**< invalid time because battery was disconn'd */
+
+
+/**
+ * Bit masks used only with PCPS_TIME_STATUS_X
+ */
+#define PCPS_LS_ENB 0x0100 /**< current second is leap second */
+#define PCPS_ANT_FAIL 0x0200 /**< antenna failure */
+#define PCPS_LS_ANN_NEG 0x0400 /**< announced leap second is negative */
+#define PCPS_SCALE_GPS 0x0800 /**< time stamp is GPS scale */
+#define PCPS_SCALE_TAI 0x1000 /**< time stamp is TAI scale */
+
+/**
+ * Bit masks used only with time stamps representing user capture events
+ */
+#define PCPS_UCAP_OVERRUN 0x2000 /**< events interval too short */
+#define PCPS_UCAP_BUFFER_FULL 0x4000 /**< events read too slow */
+
+/**
+ * Bit masks used only with time stamps representing the current board time.
+ * A DCF77 PZF receiver can set this bit if it is actually synchronized
+ * using PZF correlation and thus provides higher accuracy than AM receivers.
+ */
+#define PCPS_SYNC_PZF 0x2000 /**< same code as PCPS_UCAP_OVERRUN */
+
+/**
+ * Immediately after a clock has been accessed, subsequent accesses
+ * are blocked for up to 1.5 msec to give the clock's microprocessor
+ * some time to decode the incoming time signal.
+ * The flag below is set if a program tries to read the PCPS_HR_TIME
+ * during this interval. In this case the read function returns the
+ * proper time stamp which is taken if the command byte is written,
+ * however, the read function returns with delay.
+ * This flag is not supported by all clocks.
+ */
+#define PCPS_IO_BLOCKED 0x8000
+
+/**
+ * This bit mask can be used to extract the time scale information out
+ * of a PCPS_TIME_STATUS_X value.
+*/
+#define PCPS_SCALE_MASK ( PCPS_SCALE_TAI | PCPS_SCALE_GPS )
+
+
+/**
+ * Some DCF77 clocks have a serial interface that can be controlled
+ * using the commands PCPS_SET_SERIAL and PCPS_GET_SERIAL. Both commands
+ * use a parameter byte describing transmission speed, framing and mode
+ * of operation. The parameter byte can be build using the constants
+ * defined below, by or'ing one of the constants of each group, shifted
+ * to the right position. PCPS_GET_SERIAL expects that parameter byte
+ * and PCPS_GET_SERIAL returns the current configuration from the board.
+ * _pcps_has_serial() checks whether supported.
+ * For GPS clocks, please refer to the comments for the PCPS_GET_SERIAL
+ * command.
+ */
+
+/**
+ * Baud rate indices. The values below are obsolete and should
+ * be replaced by the codes named MBG_BAUD_RATE_... which are
+ * defined in gpsdefs.h. The resulting index numbers, however,
+ * have not changed.
+ */
+enum
+{
+ PCPS_BD_300,
+ PCPS_BD_600,
+ PCPS_BD_1200,
+ PCPS_BD_2400,
+ PCPS_BD_4800,
+ PCPS_BD_9600,
+ PCPS_BD_19200,
+ N_PCPS_BD /* number of codes */
+};
+
+#define PCPS_BD_BITS 4 /* field with in the cfg byte */
+#define PCPS_BD_SHIFT 0 /* num of bits to shift left */
+
+/*
+ * Initializers for a table of all baud rate strings
+ * and values can be found in gpsdefs.h.
+ */
+
+
+/**
+ * Unfortunately, the framing codes below can not simply be
+ * replaced by the newer MBG_FRAMING_... definitions since
+ * the order of indices does not match.
+ */
+enum
+{
+ PCPS_FR_8N1,
+ PCPS_FR_7E2,
+ PCPS_FR_8N2,
+ PCPS_FR_8E1,
+ N_PCPS_FR_DCF /* number of valid codes */
+};
+
+#define PCPS_FR_BITS 2 /* field with in the cfg byte */
+#define PCPS_FR_SHIFT PCPS_BD_BITS /* num of bits to shift left */
+
+/*
+ * An initializer for a table of framing strings is only defined for
+ * the new MBG_FRAMING_... definitions. For editing the serial port
+ * configuration, the old codes above should be translated to the new
+ * codes to unify handling inside the edit functions.
+ */
+
+/**
+ Modes of operation
+
+ * Indices for modes of operation. The values below are obsolete
+ * and should be replaced by the codes named STR_... which are
+ * defined in gpsdefs.h. The resulting index numbers, however,
+ * have not changed.
+ */
+enum
+{
+ PCPS_MOD_REQ, /* time string on request '?' only */
+ PCPS_MOD_SEC, /* time string once per second */
+ PCPS_MOD_MIN, /* time string once per minute */
+ PCPS_MOD_RSVD, /* reserved */
+ N_PCPS_MOD_DCF /* number of possible codes */
+};
+
+#define PCPS_MOD_BITS 2 /* field with in the cfg byte */
+#define PCPS_MOD_SHIFT ( PCPS_BD_BITS + PCPS_FR_BITS )
+ /* num of bits to shift left */
+
+
+/**
+ * Some definitions used with PZF receivers
+ */
+
+/* receiver distance from transmitter [km] */
+typedef uint16_t TR_DISTANCE;
+
+#define _mbg_swab_tr_distance( _p ) \
+ _mbg_swab16( _p )
+
+
+
+/* correlation status info */
+typedef struct
+{
+ uint8_t val; /**< correlation value, or check count if status == PZF_CORR_CHECK */
+ uint8_t status; /**< status codes, see below */
+ char corr_dir; /**< space, '<', or '>' */
+ uint8_t signal; /**< signal level, may always be 0 for devices which do not support this */
+} CORR_INFO;
+
+#define _mbg_swab_corr_info( _p ) \
+ _nop_macro_fnc()
+
+
+/** Codes used with CORR_INFO::status: */
+enum
+{
+ PZF_CORR_RAW, /**< trying raw correlation, combi receivers running in AM mode */
+ PZF_CORR_CHECK, /**< raw correlation achieved, doing plausibility checks */
+ PZF_CORR_FINE, /**< fine correlation achieved */
+ N_PZF_CORR_STATE
+};
+
+
+#define PZF_CORR_STATE_NAME_RAW_ENG "Searching"
+#define PZF_CORR_STATE_NAME_CHECK_ENG "Correlating"
+#define PZF_CORR_STATE_NAME_FINE_ENG "Locked"
+
+#define PZF_CORR_STATE_NAME_RAW_GER "suchen"
+#define PZF_CORR_STATE_NAME_CHECK_GER "korrelieren"
+#define PZF_CORR_STATE_NAME_FINE_GER "eingerastet"
+
+
+#define PZF_CORR_STATE_NAMES_ENG \
+{ \
+ PZF_CORR_STATE_NAME_RAW_ENG, \
+ PZF_CORR_STATE_NAME_CHECK_ENG, \
+ PZF_CORR_STATE_NAME_FINE_ENG \
+}
+
+
+#define PZF_CORR_STATE_NAMES_LSTR \
+{ \
+ { PZF_CORR_STATE_NAME_RAW_ENG, PZF_CORR_STATE_NAME_RAW_GER }, \
+ { PZF_CORR_STATE_NAME_CHECK_ENG, PZF_CORR_STATE_NAME_CHECK_GER }, \
+ { PZF_CORR_STATE_NAME_FINE_ENG, PZF_CORR_STATE_NAME_FINE_GER } \
+}
+
+
+
+/** @defgroup group_gps_cmds_bus GPS commands passed via the system bus
+
+ This enumeration defines the various types of data that can be read
+ from or written to Meinberg bus level devices which support this.
+ Access should be done using the functions pcps_read_gps_data()
+ and pcps_write_gps_data() since the size of some of the structures
+ exceeds the size of the device's I/O buffer and must therefore be
+ accessed in several blocks.
+
+ The structures to be used are defined in gpsdefs.h. Not all structures
+ are supported, yet. Check the R/W indicators for details.
+
+ * @{ */
+enum
+{ // R/W data type description
+ // system data -----------------------------------------------
+ PC_GPS_TZDL = 0, // R/W TZDL time zone / daylight saving
+ PC_GPS_SW_REV, // R/- SW_REV software revision
+ PC_GPS_BVAR_STAT, // R/- BVAR_STAT status of buffered variables
+ PC_GPS_TIME, // R/W TTM curr. time
+ PC_GPS_POS_XYZ, // -/W XYZ curr. pos. in ECEF coords
+ PC_GPS_POS_LLA, // -/W LLA curr. pos. in geogr. coords
+ PC_GPS_PORT_PARM, // R/W PORT_PARM param. of the serial ports
+ PC_GPS_ANT_INFO, // R/- ANT_INFO time diff after ant. disconn.
+ PC_GPS_UCAP, // R/- TTM user capture
+ PC_GPS_ENABLE_FLAGS, // R/W ENABLE_FLAGS controls when to enable outp.
+ PC_GPS_STAT_INFO, // R/- GPS_STAT_INFO
+ PC_GPS_CMD, // -/W GPS_CMD commands as described below
+ PC_GPS_IDENT, // R/- GPS_IDENT serial number
+ PC_GPS_POS, // R/- POS position XYZ, LLA, and DMS
+ PC_GPS_ANT_CABLE_LEN, // R/W ANT_CABLE_LEN used to compensate delay
+ // The codes below are supported by new GPS receiver boards:
+ PC_GPS_RECEIVER_INFO, // R/- RECEIVER_INFO rcvr model info
+ PC_GPS_ALL_STR_TYPE_INFO, // R/- n*STR_TYPE_INFO_IDX all string types
+ PC_GPS_ALL_PORT_INFO, // R/- n*PORT_INFO_IDX all port info
+ PC_GPS_PORT_SETTINGS_IDX, // -/W PORT_SETTINGS_IDX port settings only
+ PC_GPS_ALL_POUT_INFO, // R/- n*POUT_INFO_IDX all pout info
+ PC_GPS_POUT_SETTINGS_IDX, // -/W POUT_SETTINGS_IDX pout settings only
+ PC_GPS_TIME_SCALE, // R/W MBG_TIME_SCALE_{SETTINGS|INFO}, only if PCPS_HAS_TIME_SCALE
+ PC_GPS_LAN_IF_INFO, // R/- LAN_IF_INFO LAN interface info, only if PCPS_HAS_LAN_INTF
+ PC_GPS_IP4_STATE, // R/- IP4_SETTINGS LAN interface state, only if PCPS_HAS_LAN_INTF
+ PC_GPS_IP4_SETTINGS, // R/W IP4_SETTINGS LAN interface configuration, only if PCPS_HAS_LAN_INTF
+ PC_GPS_PTP_STATE, // R/- PTP_STATE, only if PCPS_HAS_PTP
+ PC_GPS_PTP_CFG, // R/W PTP_CFG_{SETTINGS|INFO}, only if PCPS_HAS_PTP
+ PC_GPS_PTP_UC_MASTER_CFG_LIMITS, // R/- PTP_UC_MASTER_CFG_LIMITS, only if can be unicast master
+ PC_GPS_ALL_PTP_UC_MASTER_INFO, // R/- n*PTP_UC_MASTER_INFO_IDX, only if can be unicast master
+ PC_GPS_PTP_UC_MASTER_SETTINGS_IDX, // -/W PTP_UC_MASTER_SETTINGS_IDX, only if can be unicast master
+ PC_GPS_GPIO_CFG_LIMITS, // R/- MBG_GPIO_CFG_LIMITS, only if PCPS_HAS_GPIO
+ PC_GPS_ALL_GPIO_INFO, // R/- n*MBG_GPIO_INFO, all GPIO info, only if PCPS_HAS_GPIO
+ PC_GPS_GPIO_SETTINGS_IDX, // -/W MBG_GPIO_SETTINGS_IDX, GPIO cfg for a specific port, only if PCPS_HAS_GPIO
+
+ // GPS data
+ PC_GPS_CFGH = 0x80, // -/- CFGH SVs' config. and health codes
+ PC_GPS_ALM, // -/- SV_ALM one SV's num and almanac
+ PC_GPS_EPH, // -/- SV_EPH one SV's num and ephemeris
+ PC_GPS_UTC, // R/W UTC %UTC corr. param., only if PCPS_HAS_UTC_PARM
+ PC_GPS_IONO, // -/- IONO ionospheric corr. param.
+ PC_GPS_ASCII_MSG // -/- ASCII_MSG the GPS ASCII message
+};
+
+/** @} group_gps_cmds_bus */
+
+
+
+/**
+ * @brief An initializer for a table of code/name entries of GPS commands.
+ *
+ * This can e.g. be assigned to an array of MBG_CODE_NAME_TABLE_ENTRY elements
+ * and may be helpful when debugging.
+ */
+#define MBG_PC_GPS_CMD_TABLE \
+{ \
+ { PC_GPS_TZDL, "PC_GPS_TZDL" }, \
+ { PC_GPS_SW_REV, "PC_GPS_SW_REV" }, \
+ { PC_GPS_BVAR_STAT, "PC_GPS_BVAR_STAT" }, \
+ { PC_GPS_TIME, "PC_GPS_TIME" }, \
+ { PC_GPS_POS_XYZ, "PC_GPS_POS_XYZ" }, \
+ { PC_GPS_POS_LLA, "PC_GPS_POS_LLA" }, \
+ { PC_GPS_PORT_PARM, "PC_GPS_PORT_PARM" }, \
+ { PC_GPS_ANT_INFO, "PC_GPS_ANT_INFO" }, \
+ { PC_GPS_UCAP, "PC_GPS_UCAP" }, \
+ { PC_GPS_ENABLE_FLAGS, "PC_GPS_ENABLE_FLAGS" }, \
+ { PC_GPS_STAT_INFO, "PC_GPS_STAT_INFO" }, \
+ { PC_GPS_CMD, "PC_GPS_CMD" }, \
+ { PC_GPS_IDENT, "PC_GPS_IDENT" }, \
+ { PC_GPS_POS, "PC_GPS_POS" }, \
+ { PC_GPS_ANT_CABLE_LEN, "PC_GPS_ANT_CABLE_LEN" }, \
+ { PC_GPS_RECEIVER_INFO, "PC_GPS_RECEIVER_INFO" }, \
+ { PC_GPS_ALL_STR_TYPE_INFO, "PC_GPS_ALL_STR_TYPE_INFO" }, \
+ { PC_GPS_ALL_PORT_INFO, "PC_GPS_ALL_PORT_INFO" }, \
+ { PC_GPS_PORT_SETTINGS_IDX, "PC_GPS_PORT_SETTINGS_IDX" }, \
+ { PC_GPS_ALL_POUT_INFO, "PC_GPS_ALL_POUT_INFO" }, \
+ { PC_GPS_POUT_SETTINGS_IDX, "PC_GPS_POUT_SETTINGS_IDX" }, \
+ { PC_GPS_TIME_SCALE, "PC_GPS_TIME_SCALE" }, \
+ { PC_GPS_LAN_IF_INFO, "PC_GPS_LAN_IF_INFO" }, \
+ { PC_GPS_IP4_STATE, "PC_GPS_IP4_STATE" }, \
+ { PC_GPS_IP4_SETTINGS, "PC_GPS_IP4_SETTINGS" }, \
+ { PC_GPS_PTP_STATE, "PC_GPS_PTP_STATE" }, \
+ { PC_GPS_PTP_CFG, "PC_GPS_PTP_CFG" }, \
+ { PC_GPS_PTP_UC_MASTER_CFG_LIMITS, "PC_GPS_PTP_UC_MASTER_CFG_LIMITS" }, \
+ { PC_GPS_ALL_PTP_UC_MASTER_INFO, "PC_GPS_ALL_PTP_UC_MASTER_INFO" }, \
+ { PC_GPS_PTP_UC_MASTER_SETTINGS_IDX, "PC_GPS_PTP_UC_MASTER_SETTINGS_IDX" }, \
+ { PC_GPS_GPIO_CFG_LIMITS, "PC_GPS_GPIO_CFG_LIMITS" }, \
+ { PC_GPS_ALL_GPIO_INFO, "PC_GPS_ALL_GPIO_INFO" }, \
+ { PC_GPS_GPIO_SETTINGS_IDX, "PC_GPS_GPIO_SETTINGS_IDX" }, \
+ { PC_GPS_CFGH, "PC_GPS_CFGH" }, \
+ { PC_GPS_ALM, "PC_GPS_ALM" }, \
+ { PC_GPS_EPH, "PC_GPS_EPH" }, \
+ { PC_GPS_UTC, "PC_GPS_UTC" }, \
+ { PC_GPS_IONO, "PC_GPS_IONO" }, \
+ { PC_GPS_ASCII_MSG, "PC_GPS_ASCII_MSG" }, \
+ { 0, NULL } \
+}
+
+
+
+/** codes used with PC_GPS_CMD */
+enum
+{
+ PC_GPS_CMD_BOOT = 1, /**< force the clock to boot mode */
+ PC_GPS_CMD_INIT_SYS, /**< let the clock clear its system variables */
+ PC_GPS_CMD_INIT_USER, /**< reset the clock's user parameters to defaults */
+ PC_GPS_CMD_INIT_DAC, /**< initialize the oscillator disciplining values */
+ N_PC_GPS_CMD /**< no command, just the number of known commands */
+};
+
+
+
+// The type below can be used to store an unambiguous command code.
+// In case of the standard PCPS_... commands the lower byte contains
+// the command code and the upper byte is 0.
+// In case of a GPS command the lower byte contains PCPS_READ_GPS_DATA
+// or PCPS_WRITE_GPS_DATA, as appropriate, and the upper byte contains
+// the associated PC_GPS_... type code.
+typedef uint16_t PCPS_CMD_INFO;
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+#endif /* _PCPSDEFS_H */
+
diff --git a/mbglib/common/pcpsdev.h b/mbglib/common/pcpsdev.h
new file mode 100644
index 0000000..b13d07a
--- /dev/null
+++ b/mbglib/common/pcpsdev.h
@@ -0,0 +1,1711 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsdev.h 1.51 2013/01/25 15:44:21Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions used to share information on radio clock devices
+ * between device drivers which have direct access to the hardware
+ * devices and user space programs which evaluate and present that
+ * information.
+ *
+ * At the bottom of the file there are some macros defined which
+ * should be used to access the structures to extract characteristics
+ * of an individual clock.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsdev.h $
+ * Revision 1.51 2013/01/25 15:44:21Z martin
+ * Added inline function setup_hr_time_cycles_from_timestamp_cycles() which sets
+ * up a PCPS_HR_TIME_CYCLES structure from PCPS_TIME_STAMP_CYCLES.
+ * Revision 1.50 2012/10/02 19:00:46 martin
+ * Support GPS180PEX, TCR180PEX, and PZF180PEX.
+ * Support DCF600USB, TCR600USB, MSF600USB, and WVB600USB.
+ * Runtime support for precise time API introduced with Windows 8.
+ * This does not yet for x64 builds.
+ * There are some g++ versions which fail to compile source code using
+ * the macros provided by Linux to define IOCTL codes. If only the API
+ * functions are called by an application then the IOCTL codes aren't
+ * required anyway, so we just avoid inclusion of mbgioctl.h.
+ * However, some IOCTL related definitions are required anyway, so
+ * they have been moved to this file which is always included.
+ * Bug fix: Use negative sign for delay in KeDelayExecutionThread()
+ * Support on-board event logs.
+ * Moved macro _must_do_fw_workaround_20ms() here.
+ * New macro _pcps_has_debug_status().
+ * Added some macros to test if specific stat_info stuff is supported.
+ * Moved some definitions useful for configuration tools to new file cfg_hlp.h.
+ * Moved IA64 includes from pcpsdev.h to mbgpccyc.h.
+ * Added macros _pcps_has_corr_info() and _pcps_has_tr_distance().
+ * Extended bus flag for USB v2 and macro _pcps_is_usb_v2().
+ * New feature ..._HAS_PZF and macro _pcps_has_pzf().
+ * Moved PC cycles stuff to an new extra header.
+ * Cleaned up handling of pragma pack().
+ * Introduced generic MBG_SYS_TIME with nanosecond resolution.
+ * Support struct timespec under Linux, if available.
+ * Use MBG_TGT_KERNEL instead of _KDD_.
+ * Added PTP unicast master configuration stuff.
+ * For compatibility use cpu_counter() instead of cpu_counter_serializing() under NetBSD.
+ * Optionally support timespec for sys time (USE_TIMESPEC).
+ * Support FreeBSD and NetBSD.
+ * Moved MBG_TGT_SUPP_MEM_ACC definition here.
+ * Moved status port register definitions to pcpsdefs.h.
+ * Features are now defined using enum and bit masks.
+ * Added initializer for feature names (used for debug).
+ * Added macro _pcps_features().
+ * Implemented portable mbg_get_sys_uptime() and mbg_sleep_sec()
+ * functions and associated types.
+ * Revision 1.49 2010/06/30 13:03:48 martin
+ * Use new preprocessor symbol MBG_ARCH_X86.
+ * Use ulong port addresses for all platforms but x86.
+ * Support mbg_get_pc_cycles() for IA64, but mbg_get_pc_cycles_frequency()
+ * is not yet supported.
+ * Don't pack interface structures on Sparc and IA64 architecture.
+ * Revision 1.48 2010/04/26 14:47:42 martin
+ * Define symbol MBG_PC_CYCLES_SUPPORTED if this is the case.
+ * Revision 1.47 2010/01/12 14:03:22 daniel
+ * Added definitions to support reading the raw IRIG data bits.
+ * Revision 1.46 2009/09/29 15:10:35Z martin
+ * Support generic system time, and retrieving time discipline info.
+ * Added _pcps_has_fast_hr_timestamp() macro and associated feature flag.
+ * Revision 1.45 2009/06/19 12:15:18 martin
+ * Added has_irig_time feature and associated macros.
+ * Revision 1.44 2009/06/08 19:30:48 daniel
+ * Account for new features PCPS_HAS_LAN_INTF and
+ * PCPS_HAS_PTP.
+ * Revision 1.43 2009/04/08 08:26:20 daniel
+ * Define firmware version at which the TCR511PCI starts
+ * to support IRIG control bits.
+ * Revision 1.42 2009/03/19 14:58:47Z martin
+ * Tmp. workaround in mbg_delta_pc_cycles() under SPARC which might
+ * generate bus errors due to unaligned access.
+ * Revision 1.41 2009/03/16 16:01:22 martin
+ * Support reading IRIG control function bits.
+ * Revision 1.40 2009/03/13 09:13:39 martin
+ * Support new features .._has_time_scale() and .._has_utc_parm().
+ * Moved some inline functions dealing with MBG_PC_CYCLES
+ * from mbgdevio.h here.
+ * Merged the code from _pcps_get_cycles() and _pcps_get_cycles_frequency()
+ * to the mbg_get_pc_cycles...() inline functions which now replace the
+ * _pcps_get_cycles...() macros.
+ * Fixed cycles code for non-x86 architectures.
+ * Revision 1.39 2008/12/05 16:24:24Z martin
+ * Changed MAX_PARM_STR_TYPE from 10 to 20.
+ * Added support for WWVB signal source.
+ * Support new devices PTP270PEX, FRC511PEX, TCR170PEX, and WWVB51USB.
+ * Added macros _pcps_is_ptp(), _pcps_is_frc(), and _pcps_is_wwvb().
+ * Defined firmware version numbers which fix an IRQ problem with PEX511,
+ * TCR511PEX, and GPS170PEX cards. The fix also requires specific ASIC
+ * versions specified in pci_asic.h.
+ * Defined firmware versions at which PCI511 and PEX511 start
+ * to support HR time.
+ * Support mapped I/O resources.
+ * Changed MBG_PC_CYCLES type for Windows to int64_t.
+ * Renamed MBG_VIRT_ADDR to MBG_MEM_ADDR.
+ * Added MBG_PC_CYCLES_FREQUENCY type.
+ * Added definition of PCPS_TIME_STAMP_CYCLES.
+ * Added PCPS_IRQ_STAT_INFO type and associated flags.
+ * Added macros to convert the endianess of structures.
+ * Added macros _pcps_fw_rev_num_major() and _pcps_fw_rev_num_minor().
+ * Made irq_num signed to use -1 for unassigned IRQ numbers.
+ * Revision 1.38 2008/01/17 10:12:34 daniel
+ * Added support for TCR51USB and MSF51USB.
+ * New type MBG_VIRT_ADDR to specify virtual address values.
+ * New struct PCPS_MAPPED_MEM
+ * Cleanup for PCI ASIC version and features.
+ * Added macros _pcps_is_msf(), _pcps_is_lwr(),
+ * _psps_has_asic_version(), _pcps_has_asic_features().
+ * Revision 1.37 2008/01/17 09:58:11Z daniel
+ * Made comments compatible for doxygen parser.
+ * No sourcecode changes.
+ * Revision 1.36 2007/09/26 09:34:38Z martin
+ * Added support for USB in general and new USB device USB5131.
+ * Added new types PCPS_DEV_ID and PCPS_REF_TYPE.
+ * Removed old PCPS_ERR_... codes. Use MBG_ERR_... codes
+ * from mbgerror.h instead. The old values haven't changed.
+ * Revision 1.35 2007/07/17 08:22:47Z martin
+ * Added support for TCR511PEX and GPS170PEX.
+ * Revision 1.34 2007/07/16 12:50:41Z martin
+ * Added support for PEX511.
+ * Modified/renamed some macros and symbols.
+ * Revision 1.33 2007/03/02 09:40:04Z martin
+ * Changes due to renamed library symbols.
+ * Removed obsolete inclusion of headers.
+ * Preliminary support for *BSD.
+ * Preliminary support for USB.
+ * Revision 1.32 2006/10/23 08:47:55Z martin
+ * Don't use abs() in _pcps_ref_offs_out_of_range() since this might
+ * not work properly for 16 bit integers and value 0x8000.
+ * Revision 1.31 2006/06/14 12:59:13Z martin
+ * Added support for TCR511PCI.
+ * Revision 1.30 2006/04/05 14:58:41 martin
+ * Support higher baud rates for PCI511.
+ * Revision 1.29 2006/04/03 07:29:07Z martin
+ * Added a note about the missing PCPS_ST_IRQF signal
+ * on PCI510 cards.
+ * Revision 1.28 2006/03/10 10:32:56Z martin
+ * Added support for PCI511.
+ * Added support for programmable pulse outputs.
+ * Revision 1.27 2005/11/04 08:48:00Z martin
+ * Added support for GPS170PCI.
+ * Revision 1.26 2005/06/02 08:34:38Z martin
+ * New types MBG_DBG_PORT, MBG_DBG_DATA.
+ * Revision 1.25 2005/05/03 10:04:14 martin
+ * Added macro _pcps_is_pci_amcc().
+ * Revision 1.24 2005/03/29 12:58:19Z martin
+ * Support GENERIC_IO feature.
+ * Revision 1.23 2004/12/09 11:03:37Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.22 2004/11/09 12:57:52Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Added support for TCR167PCI.
+ * New macro _pcps_has_gps_data().
+ * New type PCPS_STATUS_PORT.
+ * Removed obsolete inclusion of asm/timex.h for Linux.
+ * Revision 1.21 2004/09/06 15:19:49Z martin
+ * Support a GPS_DATA interface where sizes are specified
+ * by 16 instead of the original 8 bit quantities, thus allowing
+ * to transfer data blocks which exceed 255 bytes.
+ * Modified inclusion of header files under Linux.
+ * Modified definition of MBG_PC_CYCLES for Linux.
+ * Revision 1.20 2004/04/14 09:09:11 martin
+ * Source code cleanup.
+ * Revision 1.19 2004/04/07 09:49:14Z martin
+ * Support new feature PCPS_HAS_IRIG_TX.
+ * New macros _pcps_has_irig(), _pcps_has_irig_tx().
+ * Revision 1.18 2004/01/14 11:02:14Z MARTIN
+ * Added formal type MBG_PC_CYCLES for OS/2,
+ * though it's not really required or used.
+ * Revision 1.17 2003/12/22 15:40:16 martin
+ * Support higher baud rates for TCR510PCI and PCI510.
+ * Supports PCPS_HR_TIME for TCR510PCI.
+ * New structures used to read device time together with associated
+ * PC CPU cycles.
+ * For Win32, differentiate between kernel mode and non-kernel mode.
+ * Moved some definitions here from mbgdevio.h.
+ * New type PCPS_ASIC_VERSION.
+ * New macro _pcps_ref_offs_out_of_range().
+ * Revision 1.16 2003/06/19 09:48:30Z MARTIN
+ * Renamed symbols ..clr_cap_buffer to ..clr_ucap_buffer.
+ * New macro _pcps_has_ucap().
+ * New definitions to support cmds PCPS_GIVE_UCAP_ENTRIES
+ * and PCPS_GIVE_UCAP_EVENT.
+ * Revision 1.15 2003/04/15 09:57:25 martin
+ * New typedefs ALL_STR_TYPE_INFO, ALL_PORT_INFO,
+ * RECEIVER_PORT_CFG.
+ * Revision 1.14 2003/04/09 14:07:01Z martin
+ * Supports PCI510, GPS169PCI, and TCR510PCI,
+ * and new PCI_ASIC used by those devices.
+ * Renamed macro _pcps_is_irig() to _pcps_is_irig_rx().
+ * New macros _pcps_has_ref_offs(), _pcps_has_opt_flags().
+ * Fixed macro _pcps_has_hr_time().
+ * New type PCPS_BUS_FLAGS.
+ * Preliminary support for PCPS_TZDL.
+ * Revision 1.13 2002/08/09 07:19:49 MARTIN
+ * Moved definition of ref time sources to pcpsdefs.h.
+ * New feature PCPS_CAN_CLR_CAP_BUFF and
+ * associated macro _pcps_can_clr_cap_buff().
+ * New macros _pcps_is_irig(), _pcps_has_signal(),
+ * _pcps_has_mod().
+ * Revision 1.12 2002/02/19 09:22:53 MARTIN
+ * Added definitions for the maximum number of clocks' serial ports
+ * and string types that can be handled by the configuration programs.
+ * Revision 1.11 2002/02/01 11:36:58 MARTIN
+ * Added new definitions for GPS168PCI.
+ * Inserted definitions of firmware REV_NUMs for supported features
+ * which had previously been defined in pcpsdefs.h.
+ * Include use_pack.h.
+ * Updated comments.
+ * Source code cleanup.
+ * Revision 1.10 2001/11/30 09:52:48 martin
+ * Added support for event_time which, however, requires
+ * a custom GPS firmware.
+ * Revision 1.9 2001/10/16 10:11:14 MARTIN
+ * New Macro _pcps_has_serial_hs() which determines whether
+ * DCF77 clock supports baud rate higher than default.
+ * Re-arranged order of macro definitions.
+ * Revision 1.8 2001/09/03 07:15:05 MARTIN
+ * Added macro to access the firmware revision number.
+ * Cleaned up macro syntax.
+ * Added some comments.
+ * Revision 1.7 2001/08/30 13:20:04 MARTIN
+ * New macro to mark a PCPS_TIME variable as unread.
+ * New macro to check if a PCPS_TIME variable is unread.
+ * Revision 1.6 2001/03/15 15:45:01 MARTIN
+ * Added types PCPS_ERR_FLAGS, PCPS_BUS_NUM, PCPS_SLOT_NUM.
+ * Revision 1.5 2001/03/01 13:53:10 MARTIN
+ * Initial version for the new driver library.
+ *
+ **************************************************************************/
+
+#ifndef _PCPSDEV_H
+#define _PCPSDEV_H
+
+#include <mbg_tgt.h>
+#include <mbgtime.h>
+#include <mbgpccyc.h>
+#include <pcpsdefs.h>
+#include <gpsdefs.h>
+#include <usbdefs.h>
+#include <use_pack.h>
+
+#if !defined( MBG_TGT_KERNEL )
+ #include <string.h>
+#endif
+
+#if defined( MBG_TGT_WIN32 )
+
+ #include <mbg_w32.h>
+
+#elif defined( MBG_TGT_LINUX )
+
+ #if defined( MBG_TGT_KERNEL )
+ #include <linux/delay.h>
+ #include <linux/time.h>
+ #else
+ #include <unistd.h>
+ #include <time.h>
+ #include <sys/time.h>
+ #include <sys/sysinfo.h>
+ #endif
+
+#elif defined( MBG_TGT_FREEBSD )
+
+ #if defined( MBG_TGT_KERNEL )
+ #include <sys/sysproto.h>
+ #include <sys/pcpu.h>
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/proc.h>
+ #else
+ #include <unistd.h>
+ #include <sys/time.h>
+ #endif
+
+#elif defined( MBG_TGT_NETBSD )
+
+ #if defined( MBG_TGT_KERNEL )
+ #include <sys/param.h> // mstohz
+ #include <sys/kernel.h> // hz
+ #else
+ #include <unistd.h>
+ #include <sys/time.h>
+ #endif
+
+#elif defined( MBG_TGT_QNX_NTO )
+
+ #include <unistd.h>
+
+#elif defined( MBG_TGT_DOS )
+
+ #include <dos.h> // for delay()
+
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #if !defined( _NO_USE_PACK_INTF )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+ #endif
+#endif
+
+
+#if defined( MBG_TGT_UNIX )
+ #define USE_GENERIC_SYS_TIME 1
+#else
+ #define USE_GENERIC_SYS_TIME 0
+#endif
+
+
+#if USE_GENERIC_SYS_TIME
+
+ typedef struct
+ {
+ uint64_t sec;
+ uint64_t nsec;
+ } NANO_TIME_64;
+
+ typedef NANO_TIME_64 MBG_SYS_TIME;
+
+#endif
+
+
+
+/**
+ Define generic types to hold PC cycle counter values and system timestamps.
+ The generic types are defined using native types used by the target operating
+ systems.
+
+ The cycle counter value is usually derived from the PC CPU's TSC or some other
+ timer hardware on the mainboard.
+ */
+#if defined( MBG_TGT_WIN32 )
+
+ #define MBG_TGT_SUPP_MEM_ACC 1
+
+ typedef int64_t MBG_SYS_UPTIME; // [s]
+
+ typedef LARGE_INTEGER MBG_SYS_TIME;
+
+#elif defined( MBG_TGT_LINUX )
+
+ #define MBG_TGT_SUPP_MEM_ACC 1
+
+ typedef int64_t MBG_SYS_UPTIME; // [s]
+
+#elif defined( MBG_TGT_BSD )
+
+ #define MBG_TGT_SUPP_MEM_ACC 1
+
+ typedef int64_t MBG_SYS_UPTIME; // [s]
+
+ #if defined( MBG_TGT_NETBSD )
+ #ifdef __LP64__
+ #define MBG_MEM_ADDR uint64_t
+ #else
+ #define MBG_MEM_ADDR uint32_t
+ #endif
+ #endif
+
+#elif defined( MBG_TGT_OS2 )
+
+ typedef long MBG_SYS_UPTIME; //## dummy
+
+ typedef uint32_t MBG_SYS_TIME; //## dummy
+
+#elif defined( MBG_TGT_DOS )
+
+ #define MBG_MEM_ADDR uint32_t // 64 bit not supported, nor required.
+
+ typedef long MBG_SYS_UPTIME; //## dummy
+
+ typedef uint32_t MBG_SYS_TIME; //## dummy
+
+#else // other target OSs which access the hardware directly
+
+ typedef long MBG_SYS_UPTIME; //## dummy
+
+ typedef uint32_t MBG_SYS_TIME; //## dummy
+
+#endif
+
+
+#if !defined( MBG_TGT_SUPP_MEM_ACC )
+ #define MBG_TGT_SUPP_MEM_ACC 0
+#endif
+
+
+// MBG_SYS_TIME is always read in native machine endianess,
+// so no endianess conversion is required.
+#define _mbg_swab_mbg_sys_time( _p ) \
+ _nop_macro_fnc()
+
+
+
+/**
+ The structure holds a system timestamp in a format depending on the target OS
+ plus two cycles counter values which can be taken before and after reading
+ the system time. These cycles values can be used to determine the execution
+ time required to read the system time.
+
+ Limitations of the operating system need to be taken into account,
+ e.g. the Windows system time may increase once every ~16 ms only.
+ */
+typedef struct
+{
+ MBG_PC_CYCLES cyc_before; /**< cycles count before sys time is read */
+ MBG_PC_CYCLES cyc_after; /**< cycles count after sys time has been read */
+ MBG_SYS_TIME sys_time; /**< system time stamp */
+} MBG_SYS_TIME_CYCLES;
+
+#define _mbg_swab_mbg_sys_time_cycles( _p ) \
+{ \
+ _mbg_swab_mbg_pc_cycles( &(_p)->cyc_before ); \
+ _mbg_swab_mbg_pc_cycles( &(_p)->cyc_after ); \
+ _mbg_swab_mbg_sys_time( &(_p)->sys_time ); \
+}
+
+
+
+
+static __mbg_inline
+void mbg_get_sys_time( MBG_SYS_TIME *p )
+{
+ #if defined( MBG_TGT_WIN32 )
+
+ #if defined( MBG_TGT_KERNEL ) // kernel space
+ #if defined( MBG_TGT_WIN32_PNP ) && !defined( MBG_TGT_WIN32_PNP_X64 )
+ extern KE_QUERY_SYSTEM_TIME_FNC ke_query_system_time_fnc;
+ ke_query_system_time_fnc( p );
+ #else
+ KeQuerySystemTime( p );
+ #endif
+ #else // user space
+ {
+ FILETIME ft;
+ GetSystemTimeAsFileTime( &ft );
+ p->LowPart = ft.dwLowDateTime;
+ p->HighPart = ft.dwHighDateTime;
+ }
+ #endif
+
+ #elif defined( MBG_TGT_LINUX )
+
+ #if defined( MBG_TGT_KERNEL )
+
+ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 22 ) ) //##+++++++++++++
+ {
+ // getnstimeofday() supported
+ struct timespec ts;
+
+ getnstimeofday( &ts );
+
+ p->sec = ts.tv_sec;
+ p->nsec = ts.tv_nsec;
+ }
+ #else
+ {
+ // getnstimeofday() *not* supported
+ struct timeval tv;
+
+ do_gettimeofday( &tv );
+
+ p->sec = tv.tv_sec;
+ p->nsec = tv.tv_usec * 1000;
+ }
+ #endif
+
+ #else // Linux user space
+ {
+ struct timespec ts;
+
+ clock_gettime( CLOCK_REALTIME, &ts );
+
+ p->sec = ts.tv_sec;
+ p->nsec = ts.tv_nsec;
+ }
+ #endif
+
+ #elif defined( MBG_TGT_BSD )
+
+ struct timespec ts;
+
+ #if defined( MBG_TGT_KERNEL )
+ nanotime( &ts );
+ #else
+ #if defined( MBG_TGT_FREEBSD )
+ clock_gettime( CLOCK_REALTIME_PRECISE, &ts );
+ #else // MBG_TGT_NETBSD, ...
+ clock_gettime( CLOCK_REALTIME, &ts );
+ #endif
+ #endif
+
+ p->sec = ts.tv_sec;
+ p->nsec = ts.tv_nsec;
+
+ #else
+
+ *p = 0;
+
+ #endif
+
+} // mbg_get_sys_time
+
+
+
+static __mbg_inline
+void mbg_get_sys_uptime( MBG_SYS_UPTIME *p )
+{
+ #if defined( MBG_TGT_WIN32 )
+
+ #if defined( MBG_TGT_KERNEL ) // kernel space
+
+ ULONGLONG time_increment = KeQueryTimeIncrement();
+ LARGE_INTEGER tick_count;
+
+ KeQueryTickCount( &tick_count );
+
+ // multiplication by time_increment yields HNS units,
+ // but we need seconds
+ *p = ( tick_count.QuadPart * time_increment ) / HNS_PER_SEC;
+
+ #else // user space
+
+ DWORD tickCount;
+ DWORD timeAdjustment;
+ DWORD timeIncrement;
+ BOOL timeAdjustmentDisabled;
+
+ if ( !GetSystemTimeAdjustment( &timeAdjustment, &timeIncrement, &timeAdjustmentDisabled ) )
+ *p = -1; // failed
+
+ // ATTENTION: This is compatible with older Windows versions, but
+ // the returned tick count wraps around to zero after 49.7 days.
+ // A new GetTickCount64() call is available under Windows Vista and newer,
+ // but the function call had to be imported dynamically since otherwise
+ // programs refused to start under pre-Vista versions due to undefined DLL symbol.
+ tickCount = GetTickCount();
+
+ *p = ( ( (MBG_SYS_UPTIME) tickCount ) * timeIncrement ) / HNS_PER_SEC;
+
+ #endif
+
+ #elif defined( MBG_TGT_LINUX )
+
+ #if defined( MBG_TGT_KERNEL )
+ {
+ // Using a simple 64 bit division may result in a linker error
+ // in kernel mode due to a missing symbol __udivdi3, so we use
+ // a specific inline function do_div().
+ // Also, the jiffies counter is not set to 0 at startup but to
+ // a defined initialization value we need to account for.
+ uint64_t tmp = get_jiffies_64() - INITIAL_JIFFIES;
+ do_div( tmp, HZ );
+ *p = tmp;
+ }
+ #else
+ {
+ struct sysinfo si;
+ int rc = sysinfo( &si );
+ *p = ( rc == 0 ) ? si.uptime : -1;
+ }
+ #endif
+
+ #elif defined( MBG_TGT_BSD )
+
+ #if defined( MBG_TGT_KERNEL )
+ {
+ struct timespec ts;
+ #if 0 //##+++++++
+ {
+ struct bintime bt;
+
+ binuptime( &bt );
+ #if defined( DEBUG )
+ printf( "binuptime: %lli.%09lli\n",
+ (long long) bt.sec,
+ (long long) bt.frac );
+ #endif
+ }
+ #endif
+
+ nanouptime( &ts );
+ #if defined( DEBUG )
+ printf( "nanouptime: %lli.%09lli\n",
+ (long long) ts.tv_sec,
+ (long long) ts.tv_nsec );
+ #endif
+ *p = ts.tv_sec;
+ }
+ #elif defined( MBG_TGT_FREEBSD )
+ {
+ struct timespec ts;
+ // CLOCK_UPTIME_FAST is specific to FreeBSD
+ int rc = clock_gettime( CLOCK_UPTIME_FAST, &ts );
+ *p = ( rc == 0 ) ? ts.tv_sec : -1;
+ }
+ #else // MBG_TGT_NETBSD, ...
+
+ *p = -1; //##++ needs to be implemented
+
+ #endif
+
+ #else
+
+ *p = -1; // not supported
+
+ #endif
+
+} // mbg_get_sys_uptime
+
+
+
+static __mbg_inline
+void mbg_sleep_sec( long sec )
+{
+ #if defined( MBG_TGT_WIN32 )
+
+ #if defined( MBG_TGT_KERNEL ) // kernel space
+ LARGE_INTEGER delay;
+
+ // we need to pass a negative value to KeDelayExecutionThread()
+ // since the given time is a relative time interval, not absolute
+ // time. See the API docs for KeDelayExecutionThread().
+ delay.QuadPart = - ((LONGLONG) sec * HNS_PER_SEC);
+
+ KeDelayExecutionThread( KernelMode, FALSE, &delay );
+ #else // user space
+ // Sleep() expects milliseconds
+ Sleep( sec * 1000 );
+ #endif
+
+ #elif defined( MBG_TGT_LINUX )
+
+ #if defined( MBG_TGT_KERNEL )
+ // msleep is not defined in older kernels, so we use this
+ // only if it is surely supported.
+ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 16 ) ) //##+++++
+ msleep( sec * 1000 );
+ #else
+ {
+ DECLARE_WAIT_QUEUE_HEAD( tmp_wait );
+ wait_event_interruptible_timeout( tmp_wait, 0, sec * HZ + 1 );
+ }
+ #endif
+ #else
+ sleep( sec );
+ #endif
+
+ #elif defined( MBG_TGT_BSD )
+
+ #if defined( MBG_TGT_KERNEL )
+ #if defined( MBG_TGT_FREEBSD )
+ struct timeval tv = { 0 };
+ int ticks;
+ tv.tv_sec = sec;
+ ticks = tvtohz( &tv );
+ #if defined( DEBUG )
+ printf( "pause: %lli.%06lli (%i ticks)\n",
+ (long long) tv.tv_sec,
+ (long long) tv.tv_usec,
+ ticks );
+ #endif
+ pause( "pause", ticks );
+ #elif defined( MBG_TGT_NETBSD )
+ int timeo = mstohz( sec * 1000 );
+ #if defined( DEBUG )
+ printf( "kpause: %i s (%i ticks)\n", sec, timeo );
+ #endif
+ kpause( "pause", 1, timeo, NULL );
+ #endif
+ #else
+ sleep( sec );
+ #endif
+
+ #elif defined( MBG_TGT_QNX_NTO )
+
+ // Actually only tested under Neutrino.
+ sleep( sec );
+
+ #elif defined( MBG_TGT_DOS )
+
+ delay( (unsigned) ( sec * 1000 ) );
+
+ #else
+
+ // This needs to be implemented for the target OS
+ // and thus will probably yield a linker error.
+ do_sleep_sec( sec );
+
+ #endif
+
+} // mbg_sleep_sec
+
+
+
+#if !defined( MBG_MEM_ADDR )
+ // By default a memory address is stored
+ // as a 64 bit quantitiy.
+ #define MBG_MEM_ADDR uint64_t
+#endif
+
+
+typedef uint8_t MBG_DBG_DATA;
+typedef uint16_t MBG_DBG_PORT;
+
+
+// The following flags describe the bus types which are
+// supported by the plugin clocks.
+#define PCPS_BUS_ISA 0x0001 // IBM compatible PC/AT ISA bus
+#define PCPS_BUS_MCA 0x0002 // IBM PS/2 micro channel
+#define PCPS_BUS_PCI 0x0004 // PCI
+#define PCPS_BUS_USB 0x0008 // USB
+
+
+// The flags below are or'ed to the PC_BUS_PCI code
+// in order to indicate which PCI interface chip is used
+// on a PCI card. If no flag is set then the S5933 chip is
+// installed which has been used for the first generation
+// of Meinberg PCI cards.
+#define PCPS_BUS_PCI_CHIP_S5920 0x8000 // S5920 PCI interface chip.
+#define PCPS_BUS_PCI_CHIP_ASIC 0x4000 // Meinberg's own PCI interface chip.
+#define PCPS_BUS_PCI_CHIP_PEX8311 0x2000 // PEX8311 PCI Express interface chip
+#define PCPS_BUS_PCI_CHIP_MBGPEX 0x1000 // Meinberg's own PCI Express interface chip
+
+// The constants below combine the PCI bus flags:
+#define PCPS_BUS_PCI_S5933 ( PCPS_BUS_PCI )
+#define PCPS_BUS_PCI_S5920 ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_S5920 )
+#define PCPS_BUS_PCI_ASIC ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_ASIC )
+#define PCPS_BUS_PCI_PEX8311 ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_PEX8311 )
+#define PCPS_BUS_PCI_MBGPEX ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_MBGPEX )
+
+
+// The flags below are or'ed to the PCPS_BUS_USB code
+// in order to indicate which USB protocol version
+// is supported by the device. If no additional flag is set
+// then the device has a USB v1 interface.
+#define PCPS_BUS_USB_FLAG_V2 0x8000
+
+// The constant below combines the PCI bus flags:
+#define PCPS_BUS_USB_V2 ( PCPS_BUS_USB | PCPS_BUS_USB_FLAG_V2 )
+
+
+
+/** A list of known radio clocks. */
+enum PCPS_TYPES
+{
+ PCPS_TYPE_PC31,
+ PCPS_TYPE_PS31_OLD,
+ PCPS_TYPE_PS31,
+ PCPS_TYPE_PC32,
+ PCPS_TYPE_PCI32,
+ PCPS_TYPE_GPS167PC,
+ PCPS_TYPE_GPS167PCI,
+ PCPS_TYPE_PCI509,
+ PCPS_TYPE_GPS168PCI,
+ PCPS_TYPE_PCI510,
+ PCPS_TYPE_GPS169PCI,
+ PCPS_TYPE_TCR510PCI,
+ PCPS_TYPE_TCR167PCI,
+ PCPS_TYPE_GPS170PCI,
+ PCPS_TYPE_PCI511,
+ PCPS_TYPE_TCR511PCI,
+ PCPS_TYPE_PEX511,
+ PCPS_TYPE_TCR511PEX,
+ PCPS_TYPE_GPS170PEX,
+ PCPS_TYPE_USB5131,
+ PCPS_TYPE_TCR51USB,
+ PCPS_TYPE_MSF51USB,
+ PCPS_TYPE_PTP270PEX,
+ PCPS_TYPE_FRC511PEX,
+ PCPS_TYPE_TCR170PEX,
+ PCPS_TYPE_WWVB51USB,
+ PCPS_TYPE_GPS180PEX,
+ PCPS_TYPE_TCR180PEX,
+ PCPS_TYPE_DCF600USB,
+ PCPS_TYPE_PZF180PEX,
+ PCPS_TYPE_TCR600USB,
+ PCPS_TYPE_MSF600USB,
+ PCPS_TYPE_WVB600USB,
+ N_PCPS_DEV_TYPE
+};
+
+
+#define PCPS_CLOCK_NAME_SZ 10 // including terminating 0
+
+typedef uint16_t PCPS_DEV_ID;
+typedef uint16_t PCPS_REF_TYPE;
+typedef uint16_t PCPS_BUS_FLAGS;
+
+/**
+ The structure contains the characteristics of each
+ of the clocks listed above. These fields are always the
+ same for a single type of clock and do not change with
+ firmware version, port address, etc.
+ */
+typedef struct
+{
+ uint16_t num;
+ char name[PCPS_CLOCK_NAME_SZ];
+ PCPS_DEV_ID dev_id;
+ PCPS_REF_TYPE ref_type;
+ PCPS_BUS_FLAGS bus_flags;
+} PCPS_DEV_TYPE;
+
+
+
+#if !defined( MBG_TGT_UNIX ) || defined( MBG_ARCH_X86 )
+ typedef uint16_t PCPS_PORT_ADDR;
+#else
+ typedef uint64_t PCPS_PORT_ADDR;
+#endif
+
+
+
+/**
+ The structure below describes an I/O port resource
+ used by a clock.
+*/
+typedef struct
+{
+ PCPS_PORT_ADDR base;
+ uint16_t num;
+} PCPS_PORT_RSRC;
+
+/** The max number of I/O port resources used by a clock. */
+#define N_PCPS_PORT_RSRC 2
+
+
+
+typedef struct
+{
+ MBG_MEM_ADDR user_virtual_address;
+ #if defined( MBG_TGT_LINUX )
+ uint64_t len;
+ uint64_t pfn_offset;
+ #else
+ ulong len;
+ #endif
+} PCPS_MAPPED_MEM;
+
+
+
+typedef uint32_t PCPS_ERR_FLAGS; /**< see \ref group_err_flags "Error flags" */
+typedef uint32_t PCPS_FEATURES; /**< see \ref group_features "Features" */
+typedef uint16_t PCPS_BUS_NUM;
+typedef uint16_t PCPS_SLOT_NUM;
+
+/**
+ The structure below contains data which depends
+ on a individual instance of the clock, e.g.
+ the firmware which is currently installed, the
+ port address which has been configured, etc.
+*/
+typedef struct
+{
+ PCPS_ERR_FLAGS err_flags; /**< See \ref group_err_flags "Error flags" */
+ PCPS_BUS_NUM bus_num;
+ PCPS_SLOT_NUM slot_num;
+ PCPS_PORT_RSRC port[N_PCPS_PORT_RSRC];
+ uint16_t status_port;
+ int16_t irq_num;
+ uint32_t timeout_clk;
+ uint16_t fw_rev_num;
+ PCPS_FEATURES features; /**< See \ref group_features "Feature flags" */
+ PCPS_ID_STR fw_id;
+ PCPS_SN_STR sernum;
+} PCPS_DEV_CFG;
+
+/** @defgroup group_err_flags Error flags in PCPS_DEV_CFG
+ Flags used with PCPS_DEV_CFG::err_flags
+ @{
+*/
+#define PCPS_EF_TIMEOUT 0x00000001 /**< timeout occured */
+#define PCPS_EF_INV_EPROM_ID 0x00000002 /**< invalid EPROM ID */
+#define PCPS_EF_IO_INIT 0x00000004 /**< I/O intf not init'd */
+#define PCPS_EF_IO_CFG 0x00000008 /**< I/O intf not cfg'd */
+#define PCPS_EF_IO_ENB 0x00000010 /**< I/O intf not enabled */
+#define PCPS_EF_IO_RSRC 0x00000020 /**< I/O not registered w/ rsrcmgr */
+/** @} */
+
+/** @defgroup group_features Feature flags used with PCPS_FEATURES
+
+ Some features of the radio clocks have been introduced with
+ specific firmware versions, so depending on the firmware version
+ a clock may support a feature or not. The clock detection function
+ checks the clock model and firmware version and updates the field
+ PCPS_DEV_CFG::features accordingly. There are some macros which
+ can easily be used to query whether a clock device actually
+ supports a function, or not. The definitions define
+ the possible features.
+ @{
+*/
+enum
+{
+ PCPS_BIT_CAN_SET_TIME,
+ PCPS_BIT_HAS_SERIAL,
+ PCPS_BIT_HAS_SYNC_TIME,
+ PCPS_BIT_HAS_TZDL,
+ PCPS_BIT_HAS_IDENT,
+ PCPS_BIT_HAS_UTC_OFFS,
+ PCPS_BIT_HAS_HR_TIME,
+ PCPS_BIT_HAS_SERNUM,
+
+ PCPS_BIT_HAS_TZCODE,
+ PCPS_BIT_HAS_CABLE_LEN,
+ PCPS_BIT_HAS_EVENT_TIME, // custom GPS firmware only
+ PCPS_BIT_HAS_RECEIVER_INFO,
+ PCPS_BIT_CAN_CLR_UCAP_BUFF,
+ PCPS_BIT_HAS_PCPS_TZDL,
+ PCPS_BIT_HAS_UCAP,
+ PCPS_BIT_HAS_IRIG_TX,
+
+ PCPS_BIT_HAS_GPS_DATA_16, // use 16 bit size specifiers
+ PCPS_BIT_HAS_SYNTH,
+ PCPS_BIT_HAS_GENERIC_IO,
+ PCPS_BIT_HAS_TIME_SCALE,
+ PCPS_BIT_HAS_UTC_PARM,
+ PCPS_BIT_HAS_IRIG_CTRL_BITS,
+ PCPS_BIT_HAS_LAN_INTF,
+ PCPS_BIT_HAS_PTP,
+
+ PCPS_BIT_HAS_IRIG_TIME,
+ PCPS_BIT_HAS_FAST_HR_TSTAMP,
+ PCPS_BIT_HAS_RAW_IRIG_DATA,
+ PCPS_BIT_HAS_PZF, // can also demodulate DCF77 PZF
+ PCPS_BIT_HAS_EVT_LOG,
+
+ N_PCPS_FEATURE // must not exceed 32 !!
+};
+
+
+#define PCPS_CAN_SET_TIME ( 1UL << PCPS_BIT_CAN_SET_TIME )
+#define PCPS_HAS_SERIAL ( 1UL << PCPS_BIT_HAS_SERIAL )
+#define PCPS_HAS_SYNC_TIME ( 1UL << PCPS_BIT_HAS_SYNC_TIME )
+#define PCPS_HAS_TZDL ( 1UL << PCPS_BIT_HAS_TZDL )
+#define PCPS_HAS_IDENT ( 1UL << PCPS_BIT_HAS_IDENT )
+#define PCPS_HAS_UTC_OFFS ( 1UL << PCPS_BIT_HAS_UTC_OFFS )
+#define PCPS_HAS_HR_TIME ( 1UL << PCPS_BIT_HAS_HR_TIME )
+#define PCPS_HAS_SERNUM ( 1UL << PCPS_BIT_HAS_SERNUM )
+#define PCPS_HAS_TZCODE ( 1UL << PCPS_BIT_HAS_TZCODE )
+#define PCPS_HAS_CABLE_LEN ( 1UL << PCPS_BIT_HAS_CABLE_LEN )
+#define PCPS_HAS_EVENT_TIME ( 1UL << PCPS_BIT_HAS_EVENT_TIME )
+#define PCPS_HAS_RECEIVER_INFO ( 1UL << PCPS_BIT_HAS_RECEIVER_INFO )
+#define PCPS_CAN_CLR_UCAP_BUFF ( 1UL << PCPS_BIT_CAN_CLR_UCAP_BUFF )
+#define PCPS_HAS_PCPS_TZDL ( 1UL << PCPS_BIT_HAS_PCPS_TZDL )
+#define PCPS_HAS_UCAP ( 1UL << PCPS_BIT_HAS_UCAP )
+#define PCPS_HAS_IRIG_TX ( 1UL << PCPS_BIT_HAS_IRIG_TX )
+#define PCPS_HAS_GPS_DATA_16 ( 1UL << PCPS_BIT_HAS_GPS_DATA_16 )
+#define PCPS_HAS_SYNTH ( 1UL << PCPS_BIT_HAS_SYNTH )
+#define PCPS_HAS_GENERIC_IO ( 1UL << PCPS_BIT_HAS_GENERIC_IO )
+#define PCPS_HAS_TIME_SCALE ( 1UL << PCPS_BIT_HAS_TIME_SCALE )
+#define PCPS_HAS_UTC_PARM ( 1UL << PCPS_BIT_HAS_UTC_PARM )
+#define PCPS_HAS_IRIG_CTRL_BITS ( 1UL << PCPS_BIT_HAS_IRIG_CTRL_BITS )
+#define PCPS_HAS_LAN_INTF ( 1UL << PCPS_BIT_HAS_LAN_INTF )
+#define PCPS_HAS_PTP ( 1UL << PCPS_BIT_HAS_PTP )
+#define PCPS_HAS_IRIG_TIME ( 1UL << PCPS_BIT_HAS_IRIG_TIME )
+#define PCPS_HAS_FAST_HR_TSTAMP ( 1UL << PCPS_BIT_HAS_FAST_HR_TSTAMP )
+#define PCPS_HAS_RAW_IRIG_DATA ( 1UL << PCPS_BIT_HAS_RAW_IRIG_DATA )
+#define PCPS_HAS_PZF ( 1UL << PCPS_BIT_HAS_PZF )
+#define PCPS_HAS_EVT_LOG ( 1UL << PCPS_BIT_HAS_EVT_LOG )
+
+
+
+#define PCPS_FEATURE_NAMES \
+{ \
+ "PCPS_CAN_SET_TIME", \
+ "PCPS_HAS_SERIAL", \
+ "PCPS_HAS_SYNC_TIME", \
+ "PCPS_HAS_TZDL", \
+ "PCPS_HAS_IDENT", \
+ "PCPS_HAS_UTC_OFFS", \
+ "PCPS_HAS_HR_TIME", \
+ "PCPS_HAS_SERNUM", \
+ "PCPS_HAS_TZCODE", \
+ "PCPS_HAS_CABLE_LEN", \
+ "PCPS_HAS_EVENT_TIME", \
+ "PCPS_HAS_RECEIVER_INFO", \
+ "PCPS_CAN_CLR_UCAP_BUFF", \
+ "PCPS_HAS_PCPS_TZDL", \
+ "PCPS_HAS_UCAP", \
+ "PCPS_HAS_IRIG_TX", \
+ "PCPS_HAS_GPS_DATA_16", \
+ "PCPS_HAS_SYNTH", \
+ "PCPS_HAS_GENERIC_IO", \
+ "PCPS_HAS_TIME_SCALE", \
+ "PCPS_HAS_UTC_PARM", \
+ "PCPS_HAS_IRIG_CTRL_BITS", \
+ "PCPS_HAS_LAN_INTF", \
+ "PCPS_HAS_PTP", \
+ "PCPS_HAS_IRIG_TIME", \
+ "PCPS_HAS_FAST_HR_TSTAMP", \
+ "PCPS_HAS_RAW_IRIG_DATA", \
+ "PCPS_HAS_PZF", \
+ "PCPS_HAS_EVT_LOG" \
+}
+
+/** @} */
+
+
+
+// The constants below define those features which are available
+// in ALL firmware versions which have been shipped with a
+// specific clock.
+
+#define PCPS_FEAT_PC31PS31 0
+
+// Some of the features are available in all newer clocks,
+// so these have been put together in one definition:
+#define PCPS_FEAT_LVL2 ( PCPS_CAN_SET_TIME \
+ | PCPS_HAS_SERIAL \
+ | PCPS_HAS_SYNC_TIME \
+ | PCPS_HAS_UTC_OFFS )
+
+#define PCPS_FEAT_PC32 ( PCPS_FEAT_LVL2 )
+
+#define PCPS_FEAT_PCI32 ( PCPS_FEAT_LVL2 )
+
+#define PCPS_FEAT_PCI509 ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_TZCODE )
+
+#define PCPS_FEAT_PCI510 ( PCPS_FEAT_PCI509 )
+
+#define PCPS_FEAT_PCI511 ( PCPS_FEAT_PCI510 )
+
+#define PCPS_FEAT_GPS167PC ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_TZDL \
+ | PCPS_HAS_IDENT )
+
+#define PCPS_FEAT_GPS167PCI ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_TZDL \
+ | PCPS_HAS_IDENT \
+ | PCPS_HAS_HR_TIME )
+
+#define PCPS_FEAT_GPS168PCI ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_TZDL \
+ | PCPS_HAS_IDENT \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_HAS_CABLE_LEN \
+ | PCPS_HAS_RECEIVER_INFO )
+
+#define PCPS_FEAT_GPS169PCI ( PCPS_FEAT_GPS168PCI \
+ | PCPS_CAN_CLR_UCAP_BUFF \
+ | PCPS_HAS_UCAP )
+
+#define PCPS_FEAT_GPS170PCI ( PCPS_FEAT_GPS169PCI \
+ | PCPS_HAS_IRIG_TX \
+ | PCPS_HAS_GPS_DATA_16 \
+ | PCPS_HAS_GENERIC_IO )
+
+#define PCPS_FEAT_TCR510PCI ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_SERNUM )
+
+#define PCPS_FEAT_TCR167PCI ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_TZDL \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_HAS_RECEIVER_INFO \
+ | PCPS_CAN_CLR_UCAP_BUFF \
+ | PCPS_HAS_UCAP \
+ | PCPS_HAS_IRIG_TX \
+ | PCPS_HAS_GPS_DATA_16 \
+ | PCPS_HAS_GENERIC_IO )
+
+#define PCPS_FEAT_TCR511PCI ( PCPS_FEAT_TCR510PCI \
+ | PCPS_HAS_HR_TIME )
+
+#define PCPS_FEAT_PEX511 ( PCPS_FEAT_PCI511 )
+
+#define PCPS_FEAT_TCR511PEX ( PCPS_FEAT_TCR511PCI )
+
+#define PCPS_FEAT_GPS170PEX ( PCPS_FEAT_GPS170PCI )
+
+#define PCPS_FEAT_USB5131 ( PCPS_HAS_UTC_OFFS \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_SYNC_TIME \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_CAN_SET_TIME \
+ | PCPS_HAS_TZCODE )
+
+#define PCPS_FEAT_TCR51USB ( PCPS_HAS_UTC_OFFS \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_SYNC_TIME \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_CAN_SET_TIME )
+
+#define PCPS_FEAT_MSF51USB ( PCPS_HAS_UTC_OFFS \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_SYNC_TIME \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_CAN_SET_TIME )
+
+#define PCPS_FEAT_PTP270PEX ( PCPS_HAS_SERNUM \
+ | PCPS_HAS_SYNC_TIME \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_HAS_RECEIVER_INFO \
+ | PCPS_CAN_SET_TIME \
+ | PCPS_CAN_CLR_UCAP_BUFF \
+ | PCPS_HAS_UCAP \
+ | PCPS_HAS_GPS_DATA_16 )
+
+#define PCPS_FEAT_FRC511PEX ( PCPS_HAS_SERNUM \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_HAS_RECEIVER_INFO \
+ | PCPS_CAN_SET_TIME \
+ | PCPS_CAN_CLR_UCAP_BUFF \
+ | PCPS_HAS_UCAP \
+ | PCPS_HAS_GPS_DATA_16 )
+
+#define PCPS_FEAT_TCR170PEX ( PCPS_FEAT_TCR167PCI )
+
+#define PCPS_FEAT_WWVB51USB ( PCPS_FEAT_MSF51USB )
+
+#define PCPS_FEAT_GPS180PEX ( PCPS_FEAT_GPS170PEX | PCPS_HAS_FAST_HR_TSTAMP )
+
+#define PCPS_FEAT_TCR180PEX ( PCPS_FEAT_TCR170PEX | PCPS_HAS_FAST_HR_TSTAMP )
+
+#define PCPS_FEAT_DCF600USB ( PCPS_FEAT_USB5131 )
+
+#define PCPS_FEAT_PZF180PEX ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_TZDL \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_RECEIVER_INFO \
+ | PCPS_CAN_CLR_UCAP_BUFF \
+ | PCPS_HAS_UCAP \
+ | PCPS_HAS_GPS_DATA_16 \
+ | PCPS_HAS_GENERIC_IO \
+ | PCPS_HAS_UTC_PARM \
+ | PCPS_HAS_PZF )
+
+#define PCPS_FEAT_TCR600USB ( PCPS_FEAT_TCR51USB \
+ | PCPS_HAS_IRIG_CTRL_BITS \
+ | PCPS_HAS_IRIG_TIME \
+ | PCPS_HAS_RAW_IRIG_DATA )
+
+#define PCPS_FEAT_MSF600USB ( PCPS_FEAT_MSF51USB )
+
+#define PCPS_FEAT_WVB600USB ( PCPS_FEAT_WWVB51USB )
+
+// Some features of the API used to access Meinberg plug-in devices
+// have been implemented starting with the special firmware revision
+// numbers defined below.
+//
+// If no number is specified for a feature/clock model then the feature
+// is either always supported by that clock model, or not at all.
+
+
+// There are some versions of PCI Express cards out there which do not
+// safely support hardware IRQs. The following firmware versions are required
+// for safe IRQ operation:
+#define REV_HAS_IRQ_FIX_MINOR_PEX511 0x0106
+#define REV_HAS_IRQ_FIX_MINOR_TCR511PEX 0x0105
+#define REV_HAS_IRQ_FIX_MINOR_GPS170PEX 0x0104
+// Additionally there are certain revisions of the bus interface logic
+// required. The associated version codes are defined in pci_asic.h.
+
+// The macro below can be used to check whether the required versions are there:
+#define _pcps_pex_irq_is_safe( _curr_fw_ver, _req_fw_ver, _curr_asic_ver, \
+ _req_asic_ver_major, _req_asic_ver_minor ) \
+ ( ( (_curr_fw_ver) >= (_req_fw_ver) ) && _pcps_asic_version_greater_equal( \
+ (_curr_asic_ver), (_req_asic_ver_major), (_req_asic_ver_minor ) ) \
+ )
+
+/* command PCPS_GIVE_RAW_IRIG_DATA: */
+#define REV_HAS_RAW_IRIG_DATA_TCR511PEX 0x0111
+#define REV_HAS_RAW_IRIG_DATA_TCR511PCI 0x0111
+#define REV_HAS_RAW_IRIG_DATA_TCR51USB 0x0106
+
+/* command PCPS_GIVE_IRIG_TIME: */
+#define REV_HAS_IRIG_TIME_TCR511PEX 0x0109
+#define REV_HAS_IRIG_TIME_TCR511PCI 0x0109
+#define REV_HAS_IRIG_TIME_TCR51USB 0x0106
+
+/* command PCPS_GET_IRIG_CTRL_BITS: */
+#define REV_HAS_IRIG_CTRL_BITS_TCR511PEX 0x0107
+#define REV_HAS_IRIG_CTRL_BITS_TCR511PCI 0x0107
+#define REV_HAS_IRIG_CTRL_BITS_TCR51USB 0x0106
+
+/* This board uses the GPS_DATA interface with 16 bit buffer sizes
+ instead of the original 8 bit sizes, thus allowing to transfer
+ data blocks which exceed 255 bytes (PCPS_HAS_GPS_DATA_16) */
+#define REV_HAS_GPS_DATA_16_GPS169PCI 0x0202
+
+/* the clock supports a higher baud rate than N_PCPS_BD_DCF */
+#define REV_HAS_SERIAL_HS_PCI509 0x0104
+
+/* commands PCPS_GIVE_UCAP_ENTRIES, PCPS_GIVE_UCAP_EVENT */
+#define REV_HAS_UCAP_GPS167PCI 0x0421
+#define REV_HAS_UCAP_GPS168PCI 0x0104
+
+/* command PCPS_CLR_UCAP_BUFF */
+#define REV_CAN_CLR_UCAP_BUFF_GPS167PCI 0x0419
+#define REV_CAN_CLR_UCAP_BUFF_GPS168PCI 0x0101
+
+/* commands PCPS_READ_GPS_DATA and PCPS_WRITE_GPS_DATA with */
+/* code PC_GPS_ANT_CABLE_LEN */
+#define REV_HAS_CABLE_LEN_GPS167PCI 0x0411
+#define REV_HAS_CABLE_LEN_GPS167PC 0x0411
+
+/* command PCPS_GIVE_HR_TIME, structure PCPS_HR_TIME: */
+#define REV_HAS_HR_TIME_GPS167PC 0x0305
+#define REV_HAS_HR_TIME_TCR510PCI 0x0200
+#define REV_HAS_HR_TIME_PEX511 0x0105 // This also requires a certain ASIC version.
+#define REV_HAS_HR_TIME_PCI511 0x0103
+
+/* field offs_utc in structure PCPS_TIME: */
+#define REV_HAS_UTC_OFFS_PC31PS31 0x0300
+
+/* command PCPS_GIVE_SYNC_TIME: */
+#define REV_HAS_SYNC_TIME_PC31PS31 0x0300
+
+/* command PCPS_GET_SERIAL, PCPS_SET_SERIAL: */
+#define REV_HAS_SERIAL_PC31PS31 0x0300
+
+/* command PCPS_GIVE_TIME_NOCLEAR: */
+#define REV_GIVE_TIME_NOCLEAR_PC31PS31 0x0300
+
+/* status bit PCPS_LS_ANN: */
+#define REV_PCPS_LS_ANN_PC31PS31 0x0300
+
+/* status bit PCPS_IFTM: */
+#define REV_PCPS_IFTM_PC31PS31 0x0300
+
+/* command PCPS_SET_TIME: */
+#define REV_CAN_SET_TIME_PC31PS31 0x0240
+
+/* command PCPS_GIVE_TIME_NOCLEAR: */
+// This is supported by all clocks but PC31/PS31 with
+// firmware versions before v3.0. If such a card shall
+// be used then the firmware should be updated to the
+// last recent version.
+
+
+/**
+ The structure has been defined to pass all
+ information on a clock device from a device driver
+ to a user program. */
+typedef struct
+{
+ PCPS_DEV_TYPE type;
+ PCPS_DEV_CFG cfg;
+} PCPS_DEV;
+
+
+// The macros below simplify access to the data
+// stored in PCPS_DEV structure and should be used
+// to extract the desired information.
+// If the formal parameter is called _d then a pointer
+// to device structure PCPS_DEV is expected.
+// If the formal parameter is called _c then a pointer
+// to configuration structure PCPS_DEV_CFG is expected.
+
+// Access device type information:
+#define _pcps_type_num( _d ) ( (_d)->type.num )
+#define _pcps_type_name( _d ) ( (_d)->type.name )
+#define _pcps_dev_id( _d ) ( (_d)->type.dev_id )
+#define _pcps_ref_type( _d ) ( (_d)->type.ref_type )
+#define _pcps_bus_flags( _d ) ( (_d)->type.bus_flags )
+
+// Query device type features:
+#define _pcps_is_gps( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_GPS )
+#define _pcps_is_dcf( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_DCF )
+#define _pcps_is_msf( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_MSF )
+#define _pcps_is_wwvb( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_WWVB )
+#define _pcps_is_irig_rx( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_IRIG )
+#define _pcps_is_ptp( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_PTP )
+#define _pcps_is_frc( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_FRC )
+
+#define _pcps_is_lwr( _d ) ( _pcps_is_dcf( _d ) || _pcps_is_msf( _d ) || _pcps_is_wwvb( _d ) )
+
+// Generic bus types:
+#define _pcps_is_isa( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_ISA )
+#define _pcps_is_mca( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_MCA )
+#define _pcps_is_pci( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_PCI )
+#define _pcps_is_usb( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_USB )
+
+// Special bus types:
+#define _pcps_is_usb_v2( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_USB_V2 )
+#define _pcps_is_pci_s5933( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_S5933 )
+#define _pcps_is_pci_s5920( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_S5920 )
+#define _pcps_is_pci_amcc( _d ) ( _pcps_is_pci_s5920( _d ) || _pcps_is_pci_s5933( _d ) )
+#define _pcps_is_pci_asic( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_ASIC )
+#define _pcps_is_pci_pex8311( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_PEX8311 )
+#define _pcps_is_pci_mbgpex( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_MBGPEX )
+
+
+// Access device configuration information:
+#define _pcps_bus_num( _d ) ( (_d)->cfg.bus_num )
+#define _pcps_slot_num( _d ) ( (_d)->cfg.slot_num )
+
+#define _pcps_cfg_port_rsrc( _c, _n ) ( (_c)->port[_n] )
+#define _pcps_port_rsrc( _d, _n ) _pcps_cfg_port_rsrc( &(_d)->cfg, (_n) )
+#define _pcps_port_rsrc_unused( _d ) ( (_d)->base == 0 || (_d)->num == 0 )
+
+#define _pcps_cfg_port_base( _c, _n ) ( _pcps_cfg_port_rsrc( (_c), (_n) ).base )
+#define _pcps_port_base( _d, _n ) ( _pcps_port_rsrc( (_d), (_n) ).base )
+
+#define _pcps_cfg_irq_num( _c ) ( (_c)->irq_num )
+#define _pcps_irq_num( _d ) _pcps_cfg_irq_num( &(_d)->cfg )
+
+#define _pcps_cfg_timeout_clk( _c ) ( (_c)->timeout_clk )
+#define _pcps_timeout_clk( _d ) _pcps_cfg_timeout_clk( &(_d)->cfg )
+
+#define _pcps_fw_rev_num( _d ) ( (_d)->cfg.fw_rev_num )
+#define _pcps_features( _d ) ( (_d)->cfg.features )
+#define _pcps_fw_id( _d ) ( (_d)->cfg.fw_id )
+#define _pcps_sernum( _d ) ( (_d)->cfg.sernum )
+
+
+// The macros below handle the device's err_flags.
+#define _pcps_err_flags( _d ) ( (_d)->cfg.err_flags )
+#define _pcps_chk_err_flags( _d, _msk ) ( _pcps_err_flags( _d ) & (_msk) )
+#define _pcps_set_err_flags( _d, _msk ) ( _pcps_err_flags( _d ) |= (_msk) )
+#define _pcps_clr_err_flags( _d, _msk ) ( _pcps_err_flags( _d ) &= ~(_msk) )
+
+
+// Query whether a special feature is supported:
+#define _pcps_has_feature( _d, _f ) ( ( (_d)->cfg.features & (_f) ) != 0 )
+
+// Query whether a special feature is supported according to RECEIVER_INFO:
+#define _pcps_has_ri_feature( _p_ri, _f ) ( ( (_p_ri)->features & (_f) ) != 0 )
+
+
+#define _pcps_can_set_time( _d ) _pcps_has_feature( (_d), PCPS_CAN_SET_TIME )
+#define _pcps_has_serial( _d ) _pcps_has_feature( (_d), PCPS_HAS_SERIAL )
+#define _pcps_has_sync_time( _d ) _pcps_has_feature( (_d), PCPS_HAS_SYNC_TIME )
+#define _pcps_has_ident( _d ) _pcps_has_feature( (_d), PCPS_HAS_IDENT )
+#define _pcps_has_utc_offs( _d ) _pcps_has_feature( (_d), PCPS_HAS_UTC_OFFS )
+#define _pcps_has_hr_time( _d ) _pcps_has_feature( (_d), PCPS_HAS_HR_TIME )
+#define _pcps_has_sernum( _d ) _pcps_has_feature( (_d), PCPS_HAS_SERNUM )
+#define _pcps_has_cab_len( _d ) _pcps_has_feature( (_d), PCPS_HAS_CABLE_LEN )
+#define _pcps_has_tzdl( _d ) _pcps_has_feature( (_d), PCPS_HAS_TZDL )
+#define _pcps_has_pcps_tzdl( _d ) _pcps_has_feature( (_d), PCPS_HAS_PCPS_TZDL )
+#define _pcps_has_tzcode( _d ) _pcps_has_feature( (_d), PCPS_HAS_TZCODE )
+#define _pcps_has_tz( _d ) _pcps_has_feature( (_d), PCPS_HAS_TZDL \
+ | PCPS_HAS_PCPS_TZDL \
+ | PCPS_HAS_TZCODE )
+// The next one is supported only with a certain GPS firmware version:
+#define _pcps_has_event_time( _d ) _pcps_has_feature( (_d), PCPS_HAS_EVENT_TIME )
+#define _pcps_has_receiver_info( _d ) _pcps_has_feature( (_d), PCPS_HAS_RECEIVER_INFO )
+#define _pcps_can_clr_ucap_buff( _d ) _pcps_has_feature( (_d), PCPS_CAN_CLR_UCAP_BUFF )
+#define _pcps_has_ucap( _d ) _pcps_has_feature( (_d), PCPS_HAS_UCAP )
+#define _pcps_has_irig_tx( _d ) _pcps_has_feature( (_d), PCPS_HAS_IRIG_TX )
+
+// The macro below determines whether a DCF77 clock
+// supports a higher baud rate than standard
+#define _pcps_has_serial_hs( _d ) \
+ ( ( _pcps_type_num( _d ) == PCPS_TYPE_TCR511PEX ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_PEX511 ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_TCR511PCI ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_TCR510PCI ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_PCI511 ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_PCI510 ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_PCI509 && \
+ _pcps_fw_rev_num( _d ) >= REV_HAS_SERIAL_HS_PCI509 ) )
+
+
+#define _pcps_has_signal( _d ) \
+ ( _pcps_is_dcf( _d ) || _pcps_is_msf( _d ) || _pcps_is_wwvb( _d ) || _pcps_is_irig_rx( _d ) )
+
+#define _pcps_has_mod( _d ) \
+ ( _pcps_is_dcf( _d ) || _pcps_is_msf( _d ) || _pcps_is_wwvb( _d ) )
+
+#define _pcps_has_irig( _d ) \
+ ( _pcps_is_irig_rx( _d ) || _pcps_has_irig_tx( _d ) )
+
+#define _pcps_has_irig_ctrl_bits( _d ) \
+ _pcps_has_feature( (_d), PCPS_HAS_IRIG_CTRL_BITS )
+
+#define _pcps_has_irig_time( _d ) \
+ _pcps_has_feature( (_d), PCPS_HAS_IRIG_TIME )
+
+#define _pcps_has_raw_irig_data( _d ) \
+ _pcps_has_feature( (_d), PCPS_HAS_RAW_IRIG_DATA )
+
+#define _pcps_has_ref_offs( _d ) \
+ _pcps_is_irig_rx( _d )
+
+#define _pcps_ref_offs_out_of_range( _n ) \
+ ( ( (_n) > MBG_REF_OFFS_MAX ) || ( (_n) < -MBG_REF_OFFS_MAX ) )
+
+#define _pcps_has_opt_flags( _d ) \
+ _pcps_is_irig_rx( _d )
+
+#define _pcps_has_gps_data_16( _d ) _pcps_has_feature( (_d), PCPS_HAS_GPS_DATA_16 )
+
+#define _pcps_has_gps_data( _d ) \
+ ( _pcps_is_gps( _d ) || _pcps_has_gps_data_16( _d ) )
+
+#define _pcps_has_synth( _d ) _pcps_has_feature( (_d), PCPS_HAS_SYNTH )
+
+#define _pcps_has_generic_io( _d ) _pcps_has_feature( (_d), PCPS_HAS_GENERIC_IO )
+
+#define _pcps_has_time_scale( _d ) _pcps_has_feature( (_d), PCPS_HAS_TIME_SCALE )
+
+#define _pcps_has_utc_parm( _d ) _pcps_has_feature( (_d), PCPS_HAS_UTC_PARM )
+
+#define _pcps_has_asic_version( _d ) ( _pcps_is_pci_asic( _d ) \
+ || _pcps_is_pci_pex8311( _d ) \
+ || _pcps_is_pci_mbgpex( _d ) )
+
+#define _pcps_has_asic_features( _d ) _pcps_has_asic_version( _d )
+
+#define _pcps_has_fast_hr_timestamp( _d ) _pcps_has_feature( (_d), PCPS_HAS_FAST_HR_TSTAMP )
+
+#define _pcps_has_lan_intf( _d ) _pcps_has_feature( (_d), PCPS_HAS_LAN_INTF )
+
+#define _pcps_has_ptp( _d ) _pcps_has_feature( (_d), PCPS_HAS_PTP )
+
+#define _pcps_has_ri_ptp_unicast( _p_ri ) _pcps_has_ri_feature( (_p_ri), GPS_HAS_PTP_UNICAST )
+
+#define _pcps_has_pzf( _d ) _pcps_has_feature( (_d), PCPS_HAS_PZF )
+
+#define _pcps_has_corr_info( _d ) _pcps_has_pzf( _d )
+
+#define _pcps_has_tr_distance( _d ) _pcps_has_pzf( _d )
+
+#define _pcps_has_evt_log( _d ) _pcps_has_feature( (_d), PCPS_HAS_EVT_LOG )
+
+#define _pcps_has_debug_status( _d ) _pcps_is_irig_rx( _d )
+
+#define _pcps_has_stat_info( _d ) ( _pcps_is_gps( _d ) || _pcps_has_pzf( _d ) )
+
+#define _pcps_has_stat_info_mode( _d ) _pcps_is_gps( _d )
+
+#define _pcps_has_stat_info_svs( _d ) _pcps_is_gps( _d )
+
+
+
+// There are some versions of IRIG receiver cards which ignore the TFOM code
+// of an incoming IRIG signal even if an IRIG code has been configured which
+// supports this. In this case these cards synchronize to the incoming IRIG
+// signal even if the TFOM code reports the IRIG generator is not synchronized.
+// The intended behaviour is that the IRIG receiver card changes its status
+// to "freewheeling" in this case, unless it has been configured to ignore
+// the TFOM code of the incoming IRIG signal (see the IFLAGS_DISABLE_TFOM flag
+// defined in gpsdefs.h).
+
+// The macro below can be used to check based on the device info if a specific
+// card with a specific firmware always ignores the TFOM code:
+#define _pcps_incoming_tfom_ignored( _d ) \
+ ( ( ( _pcps_type_num( _d ) == PCPS_TYPE_TCR167PCI ) && ( _pcps_fw_rev_num( _d ) <= 0x121 ) ) \
+ || ( ( _pcps_type_num( _d ) == PCPS_TYPE_TCR170PEX ) && ( _pcps_fw_rev_num( _d ) <= 0x103 ) ) )
+
+
+// Some Meinberg PCI Express cards have a PCIe interface chip with an extra
+// PCI bridge built into the chip. Unfortunately there are some mainboards out there
+// which do not handle PCI resources behind this PCI bridge correctly. The symptom is
+// usually that both I/O address ranges of these cards get the same base address
+// assigned by the BIOS, and the efeect is that in this case a card is not accessible
+// properly, since both I/O ranges try to respond to the same I/O addresses.
+// As a consequence data read from the card is usually garbage.
+// The only known fix for this is a BIOS update for the mainboard which makes the
+// BIOS handle the card's resources properly.
+
+// The macro below can be used to test if both port base addresses assigned to a card
+// are identical, and thus the BIOS is probably faulty::
+#define _pcps_pci_cfg_err( _d ) \
+ ( _pcps_is_pci( _d ) && ( _pcps_port_base( _d, 1 ) == _pcps_port_base( _d, 0 ) ) )
+
+
+
+// There are some versions of GPS PCI firmware which may occasionally return
+// a HR time stamp which is wrong by 20 milliseconds, if the HR time is read
+// right after some GPS data. As a workaround for that bug an application
+// must wait at least 1.5 ms and then just read the PCPS_TIME structure
+// in order to re-initialize the software interface state.
+// This has been fixed in more recent versions of the affected firmware,
+// but this macro can be used to let an application determine whether it
+// must account for this bug with a given card and firmware version.
+#define _must_do_fw_workaround_20ms( _d ) \
+( \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_GPS168PCI && _pcps_fw_rev_num( _d ) < 0x0102 ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_GPS167PCI && _pcps_fw_rev_num( _d ) < 0x0420 ) \
+)
+
+
+
+/**
+ The structure is used to return info
+ on the device driver.*/
+typedef struct
+{
+ uint16_t ver_num; /**< the device driver's version number */
+ uint16_t n_devs; /**< the number of radio clocks handled by the driver */
+ PCPS_ID_STR id_str; /**< the device driver's ID string */
+} PCPS_DRVR_INFO;
+
+
+
+// The macros below can be used to mark a PCPS_TIME variable
+// as unread, i.e. its contents have not been read from the clock,
+// and to check if such a variable is marked as unread.
+#define _pcps_time_set_unread( _t ) do { (_t)->sec = 0xFF; } while ( 0 )
+#define _pcps_time_is_read( _t ) ( (uchar) (_t)->sec != 0xFF )
+
+
+
+/**
+ The structure is used to read the current time from
+ a device, combined with an associated PC cycle counter value
+ to compensate program execution time.
+ */
+typedef struct
+{
+ MBG_PC_CYCLES cycles;
+ PCPS_TIME t;
+} PCPS_TIME_CYCLES;
+
+
+
+/**
+ The structure is used to read a high resolution UTC time stamp
+ plus associated PC cycles counter value to compensate the latency.
+ */
+typedef struct
+{
+ MBG_PC_CYCLES cycles;
+ PCPS_TIME_STAMP tstamp; /**< High resolution time stamp (UTC) */
+} PCPS_TIME_STAMP_CYCLES;
+
+#define _mbg_swab_pcps_time_stamp_cycles( _p ) \
+{ \
+ _mbg_swab_mbg_pc_cycles( &(_p)->cycles ); \
+ _mbg_swab_pcps_time_stamp( &(_p)->tstamp ); \
+}
+
+
+
+/**
+ The structure is used to read the current high resolution time
+ from a device, combined with an associated PC cycle counter value
+ to compensate program execution time.
+ */
+typedef struct
+{
+ MBG_PC_CYCLES cycles;
+ PCPS_HR_TIME t;
+} PCPS_HR_TIME_CYCLES;
+
+#define _mbg_swab_pcps_hr_time_cycles( _p ) \
+{ \
+ _mbg_swab_mbg_pc_cycles( &(_p)->cycles ); \
+ _mbg_swab_pcps_hr_time( &(_p)->t ); \
+}
+
+
+
+/**
+ The structure below can be used to let the kernel driver read
+ the current system time plus the associated HR time from a plugin card
+ as close as possibly, and return the results to a user space application
+ which can then compute the time difference and latencies.
+ This structure also contains the card's status information (e.g. sync status).
+ */
+typedef struct
+{
+ PCPS_HR_TIME_CYCLES ref_hr_time_cycles; /**< HR time read from the card, plus cycles */
+ MBG_SYS_TIME_CYCLES sys_time_cycles; /**< system timestamp plus associated cycles */
+} MBG_TIME_INFO_HRT;
+
+#define _mbg_swab_mbg_time_info_hrt( _p ) \
+{ \
+ _mbg_swab_pcps_hr_time_cycles( &(_p)->ref_hr_time_cycles ); \
+ _mbg_swab_mbg_sys_time_cycles( &(_p)->sys_time_cycles ); \
+}
+
+
+
+/**
+ The structure below can be used to let the kernel driver read
+ the current system time plus an associated HR timestamp from a plugin card
+ as close as possibly, and return the results to a user space application
+ which can then compute the time difference and latencies.
+ Since the card's time stamp is usually taken using the fast memory mapped
+ access this structure does *not* contain the card's status information
+ (e.g. sync status).
+ */
+typedef struct
+{
+ PCPS_TIME_STAMP_CYCLES ref_tstamp_cycles; /**< HR timestamp from the card, plus cycles */
+ MBG_SYS_TIME_CYCLES sys_time_cycles; /**< system timestamp plus associated cycles */
+} MBG_TIME_INFO_TSTAMP;
+
+#define _mbg_swab_mbg_time_info_tstamp( _p ) \
+{ \
+ _mbg_swab_pcps_time_stamp_cycles( &(_p)->ref_tstamp_cycles ); \
+ _mbg_swab_mbg_sys_time_cycles( &(_p)->sys_time_cycles ); \
+}
+
+
+
+typedef uint32_t PCPS_IRQ_STAT_INFO;
+
+// Flags used with PCPS_IRQ_STAT_INFO:
+#define PCPS_IRQ_STAT_ENABLE_CALLED 0x01
+#define PCPS_IRQ_STAT_ENABLED 0x02
+#define PCPS_IRQ_STAT_UNSAFE 0x04 // IRQs unsafe with this firmeware version / ASIC
+
+#define PCPS_IRQ_STATE_DANGER ( PCPS_IRQ_STAT_ENABLED | PCPS_IRQ_STAT_UNSAFE )
+
+#define _pcps_fw_rev_num_major( _v ) \
+ ( ( (_v) >> 8 ) & 0xFF )
+
+#define _pcps_fw_rev_num_minor( _v ) \
+ ( (_v) & 0xFF )
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+
+// We must use native alignment here!
+
+// The structure below is used by the IOCTL_PCPS_GENERIC_... calls.
+
+#if defined( MBG_TGT_LINUX )
+ #if defined( MBG_ARCH_ARM ) || defined( MBG_ARCH_SPARC )
+ #define USE_IOCTL_GENERIC_REQ 0
+ #endif
+#endif
+
+#if defined( MBG_TGT_WIN32 )
+ // required for 32bit/64 bit compatibility
+ #define USE_IOCTL_GENERIC_REQ 0
+#endif
+
+#if !defined( USE_IOCTL_GENERIC_REQ )
+ #define USE_IOCTL_GENERIC_REQ 1
+#endif
+
+
+#if USE_IOCTL_GENERIC_REQ
+
+// This does not yet work properly under Linux/Sparc where the kernel may be 64 bit
+// while user space is 32 bit, which leads to different sizes for pointers and size_t.
+
+typedef struct
+{
+ ulong info;
+ const void *in_p;
+ size_t in_sz;
+ void *out_p;
+ size_t out_sz;
+
+} IOCTL_GENERIC_REQ;
+
+#define _MBG_IOG( _t, _n, _s ) _MBG_IOW( _t, _n, _s )
+
+#else
+
+// The structure below is used by the IOCTL_PCPS_GENERIC_... calls.
+typedef struct
+{
+ uint32_t info;
+ uint32_t data_size_in;
+ uint32_t data_size_out;
+} IOCTL_GENERIC_CTL;
+
+typedef struct
+{
+ IOCTL_GENERIC_CTL ctl;
+ uint8_t data[1];
+} IOCTL_GENERIC_BUFFER;
+
+#define _MBG_IOG( _t, _n, _s ) _MBG_IO( _t, _n )
+
+#endif
+
+
+
+#if !defined( MBG_TGT_KERNEL )
+
+static __mbg_inline
+void setup_hr_time_cycles_from_timestamp_cycles( PCPS_HR_TIME_CYCLES *p_ht_c,
+ const PCPS_TIME_STAMP_CYCLES *p_ts_c )
+{
+ memset( p_ht_c, 0, sizeof( *p_ht_c ) );
+
+ p_ht_c->t.tstamp = p_ts_c->tstamp;
+ p_ht_c->cycles = p_ts_c->cycles;
+
+} // setup_hr_time_cycles_from_timestamp_cycles
+
+#endif
+
+
+/* End of header body */
+
+#undef _ext
+
+#endif /* _PCPSDEV_H */
+
diff --git a/mbglib/common/pcpslstr.c b/mbglib/common/pcpslstr.c
new file mode 100644
index 0000000..615b716
--- /dev/null
+++ b/mbglib/common/pcpslstr.c
@@ -0,0 +1,500 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpslstr.c 1.23 2012/10/15 13:09:35Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions generating commonly used multi-language strings used
+ * with programs for Meinberg radio clocks.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpslstr.c $
+ * Revision 1.23 2012/10/15 13:09:35Z martin
+ * Added function sprint_utc_offs().
+ * Cleaned up get_tz_name().
+ * Fixed potential compiler warning for sprintf().
+ * Fixed build under FreeBSD.
+ * Revision 1.22 2010/06/25 13:57:57Z daniel
+ * Account for time zone offsets with minutes other than 0.
+ * Revision 1.21 2009/03/19 08:06:58Z daniel
+ * Added function pcps_tz_name_hr_status() to
+ * handle different time scales.
+ * Revision 1.20 2008/11/14 12:12:26Z martin
+ * Made some parameters for some functions const.
+ * Revision 1.19 2008/07/18 10:50:46Z martin
+ * Use _snwprintf with underscore for MS compilers.
+ * Revision 1.18 2008/01/30 14:51:12Z martin
+ * Fixed gcc compiler warnings.
+ * Revision 1.17 2008/01/17 09:08:12 daniel
+ * Added function pcps_date_time_wstr().
+ * Changed function pcps_tz_name() to support MSF related time zones.
+ * Exclude functions using wchar_t from build if wide chars are
+ * not supported by the target environment.
+ * Revision 1.16 2007/08/14 09:08:25Z martin
+ * Addad a workaround for older Borland compilers which don't
+ * like "const" inside structures.
+ * Revision 1.15 2007/07/20 10:55:27Z martin
+ * Some modifications to avoid compiler warnings.
+ * Revision 1.14 2007/03/30 13:23:42 martin
+ * In pcps_status_strs() handle case where time has been
+ * set manually.
+ * Revision 1.13 2007/03/29 12:58:18Z martin
+ * Moved some definitions to the header file to make them public.
+ * Revision 1.12 2006/05/04 14:56:03Z martin
+ * Strings returned by inv_str() ar surrounded by "**"s.
+ * Revision 1.11 2004/11/09 15:06:44Z martin
+ * Type cast to avoid warning with format string.
+ * Revision 1.10 2004/08/18 14:58:02 martin
+ * pcps_tz_name() now expects a flags parameter which controls
+ * the format of the output string.
+ * Revision 1.9 2004/04/28 08:06:12Z martin
+ * Append DST status to TZ names labeled "UTC+xh"
+ * in pcps_tz_name().
+ * Revision 1.8 2003/04/15 10:46:31Z martin
+ * Pass RECEIVER_INFO to pcps_serial_str().
+ * Revision 1.7 2002/12/18 09:57:03Z martin
+ * Made some vaiables and definitions global.
+ * Revision 1.6 2002/02/19 10:03:16Z MARTIN
+ * New function pcps_serial_str().
+ * Revision 1.5 2001/09/17 13:17:40 MARTIN
+ * New function pcps_tz_name_from_status() which should be used
+ * instead of pcps_tz_name() if offset from UTC is not known.
+ * New function pcps_status_strs().
+ * Enhanced language support.
+ * Don't require myutil.h anymore.
+ * Added some comments.
+ * Source code cleanup.
+ * Revision 1.4 2001/08/14 11:32:24 MARTIN
+ * Modified pcps_date_time_str() to allow for variable
+ * spacing between date, time, and time zone..
+ * Revision 1.3 2001/02/28 15:47:29 MARTIN
+ * Replaced access to some structure elements by new macro calls.
+ * Revision 1.2 2000/08/31 14:03:46 MARTIN
+ * Modified initializers for tzcode_name for non CPP-compilers.
+ * Revision 1.1 2000/07/21 12:14:01 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _PCPSLSTR
+ #include <pcpslstr.h>
+#undef _PCPSLSTR
+
+#include <pcpsutil.h>
+#include <mbgtime.h>
+#include <ctry.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#define _eos( _s ) ( &(_s)[strlen( _s )] )
+
+typedef struct
+{
+ #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0500 )
+ // old BCs don't like "const" inside the structure
+ LSTR ok;
+ LSTR err;
+ #else
+ CLSTR ok;
+ CLSTR err;
+ #endif
+} CLSTR_STATUS;
+
+
+static const char *tz_name_utc = TZ_NAME_UTC;
+static CLSTR str_dst = { "DST", "Sommerzeit" };
+
+
+
+/*HDR*/
+const char *inv_str( void )
+{
+ static CLSTR s = { "** invalid **", "** ung" LCUE "ltig **" };
+
+ return _lstr( s );
+
+} /* inv_str */
+
+
+
+/*HDR*/
+int sprint_utc_offs( char *s, const char *info, long utc_offs )
+{
+ int n = 0;
+
+ // utc_offs is in [s]
+ char utc_offs_sign = ( utc_offs < 0 ) ? '-' : '+';
+ ulong abs_utc_offs = labs( utc_offs );
+ ulong utc_offs_hours = abs_utc_offs / SECS_PER_HOUR;
+ ulong tmp = abs_utc_offs % SECS_PER_HOUR;
+ ulong utc_offs_mins = tmp / MINS_PER_HOUR;
+ ulong utc_offs_secs = tmp % MINS_PER_HOUR;
+
+ if ( info )
+ n += sprintf( &s[n], "%s", info );
+
+ n += sprintf( &s[n], "%c%lu", utc_offs_sign, utc_offs_hours );
+
+ if ( utc_offs_mins || utc_offs_secs )
+ n += sprintf( &s[n], ":%02lu", utc_offs_mins );
+
+ if ( utc_offs_secs )
+ n += sprintf( &s[n], ":%02lu", utc_offs_secs );
+
+ n += sprintf( &s[n], "h" );
+
+ return n;
+
+} // sprint_utc_offs
+
+
+
+static /*HDR*/
+const char *get_tz_name( PCPS_TIME_STATUS_X pcps_status, long utc_offs,
+ ushort flags, int is_msf )
+{
+ static char ws[40];
+ const char *cp = NULL;
+ int n = 0;
+
+ if ( ( pcps_status & PCPS_UTC ) && ( utc_offs == 0 ) )
+ return tz_name_utc; // no offset, no DST
+
+ if ( pcps_status & PCPS_DL_ENB )
+ {
+ if ( utc_offs == ( 2 * SECS_PER_HOUR ) )
+ {
+ cp = _lstr( lstr_cest );
+ goto check_flags;
+ }
+ else
+ if ( ( utc_offs == SECS_PER_HOUR ) && is_msf )
+ {
+ cp = _lstr( lstr_bst );
+ goto check_flags;
+ }
+ }
+
+ if ( !( pcps_status & PCPS_DL_ENB ) )
+ {
+ if ( utc_offs == SECS_PER_HOUR )
+ {
+ cp = _lstr( lstr_cet );
+ goto check_flags;
+ }
+ else
+ if ( ( utc_offs == 0 ) && is_msf )
+ {
+ cp = _lstr( lstr_gmt );
+ goto check_flags;
+ }
+ }
+
+ n = sprint_utc_offs( ws, tz_name_utc, utc_offs );
+
+check_flags:
+ if ( cp )
+ {
+ if ( flags == 0 )
+ return cp;
+
+ strcpy( ws, cp );
+
+ if ( flags & PCPS_TZ_NAME_FORCE_UTC_OFFS )
+ {
+ n = strlen( ws );
+ n += sprintf( &ws[n], "%*c(", pcps_time_tz_dist, ' ' );
+ n += sprint_utc_offs( &ws[n], tz_name_utc, utc_offs );
+ sprintf( &ws[n], ")" );
+ }
+ }
+
+ if ( flags & PCPS_TZ_NAME_APP_DST )
+ {
+ if ( pcps_status & PCPS_DL_ENB )
+ sprintf( _eos( ws ), ",%*c%s", pcps_time_tz_dist,
+ ' ', _lstr( str_dst ) );
+ }
+
+ return ws;
+}
+
+
+
+/*HDR*/
+const char *pcps_tz_name( const PCPS_TIME *t, ushort flags, int is_msf )
+{
+ return get_tz_name( t->status, t->offs_utc * SECS_PER_HOUR, flags, is_msf );
+
+} // pcps_tz_name
+
+
+
+/*HDR*/
+const char *pcps_tz_name_from_hr_time( const PCPS_HR_TIME *hrt, ushort flags, int is_msf )
+{
+ return get_tz_name( hrt->status, hrt->utc_offs, flags, is_msf );
+
+} // pcps_tz_name_from_hr_time
+
+
+
+// The function below can be used to build a name for
+// the time zone if the TIMESCALE, the UTC/DST status and the
+// UTC offset are known, e.g. from plug-in clocks.
+
+/*HDR*/
+const char *pcps_tz_name_hr_status( const PCPS_HR_TIME *t, ushort flags, int is_msf )
+{
+ static char ws[40];
+
+ if ( t->status & PCPS_SCALE_GPS )
+ strcpy( ws, "GPS" );
+ else
+ if ( t->status & PCPS_SCALE_TAI )
+ strcpy( ws, "TAI" );
+ else
+ return pcps_tz_name_from_hr_time( t, flags, is_msf);
+
+ return ws;
+
+} // pcps_tz_name_hr_status
+
+
+
+// The function below can be used to build a name for
+// the time zone if only the UTC/DST status is known
+// but the UTC offset is not. This is the case, for example,
+// if the Meinberg standard time string is decoded.
+
+/*HDR*/
+const char *pcps_tz_name_from_status( ushort status )
+{
+ if ( status & PCPS_UTC )
+ return tz_name_utc;
+
+ return ( status & PCPS_DL_ENB ) ? _lstr( str_dst ) : "";
+
+} // pcps_tz_name_from_status
+
+
+
+/*HDR*/
+char *pcps_date_time_str( char *s, const PCPS_TIME *t,
+ ushort year_limit, const char *tz_str )
+{
+ if ( !_pcps_time_is_read( t ) )
+ strcpy( s, str_not_avail );
+ else
+ {
+ char *cp;
+ int i;
+
+ _pcps_sprint_wday( s, t, language );
+ cp = _eos( s );
+ *cp++ = ',';
+ for ( i = 0; i < pcps_wday_date_dist; i++ )
+ *cp++ = ' ';
+ _pcps_sprint_date( cp, t, year_limit );
+ cp = _eos( s );
+ for ( i = 0; i < pcps_date_time_dist; i++ )
+ *cp++ = ' ';
+ _pcps_sprint_time_long( cp, t );
+
+ if ( tz_str )
+ {
+ cp = _eos( s );
+ for ( i = 0; i < pcps_time_tz_dist; i++ )
+ *cp++ = ' ';
+ strcpy( cp, tz_str );
+ }
+ }
+
+ return s;
+
+} // pcps_date_time_str
+
+
+
+#if MBG_TGT_HAS_WCHAR_T && defined( MBG_TGT_WIN32 )
+
+/*HDR*/
+wchar_t *pcps_date_time_wstr( wchar_t *ws, const PCPS_TIME *t,
+ ushort year_limit, const wchar_t *tz_str )
+{
+ char stemp[80];
+ wchar_t wstemp[80];
+
+ if ( !_pcps_time_is_read( t ) )
+ mbstowcs( ws, str_not_avail, 32 );
+ else
+ {
+ char *cp;
+ int i;
+
+ _pcps_sprint_wday( stemp, t, language );
+ cp = _eos( stemp );
+ *cp++ = ',';
+ for ( i = 0; i < pcps_wday_date_dist; i++ )
+ *cp++ = ' ';
+ _pcps_sprint_date( cp, t, year_limit );
+ cp = _eos( stemp );
+ for ( i = 0; i < pcps_date_time_dist; i++ )
+ *cp++ = ' ';
+ _pcps_sprint_time_long( cp, t );
+
+ mbstowcs( wstemp, stemp, sizeof( wstemp ) );
+
+ if ( tz_str )
+ _snwprintf( ws, sizeof( wstemp ) + 32, L"%s %s", wstemp, tz_str );
+ }
+
+ return ws;
+
+} // pcps_date_time_wstr
+
+#endif // MBG_TGT_HAS_WCHAR
+
+
+
+static /*HDR*/
+void pcps_setup_status_str( PCPS_STATUS_STR *pstr, int err_cond,
+ CLSTR_STATUS *pss )
+{
+ pstr->is_err = err_cond != 0;
+ pstr->cp = _lstr( pstr->is_err ? pss->err : pss->ok );
+
+} // pcps_setup_status_str
+
+
+
+// to return status strings to be displayed depending on the
+// a clocks PCPS_TIME.status.
+
+/*HDR*/
+void pcps_status_strs( ushort status, int status_is_read,
+ int is_gps, PCPS_STATUS_STRS *pstrs )
+{
+ CLSTR clstr_time_inval = DEFAULT_STR_TIME_INVAL;
+ CLSTR clstr_set_manually = DEFAULT_STR_SET_MANUALLY;
+
+ CLSTR_STATUS lstr_dcf_has_syncd =
+ { DEFAULT_STR_DCF_HAS_SYNCD, DEFAULT_STR_DCF_HAS_NOT_SYNCD };
+
+ CLSTR_STATUS lstr_gps_syncd =
+ { DEFAULT_STR_GPS_SYNCD, DEFAULT_STR_GPS_NOT_SYNCD };
+
+ CLSTR_STATUS lstr_dcf_not_free_running =
+ { DEFAULT_STR_DCF_NOT_FREE_RUNNING, DEFAULT_STR_DCF_FREE_RUNNING };
+
+ CLSTR_STATUS lstr_gps_pos =
+ { DEFAULT_STR_GPS_POS_OK, DEFAULT_STR_GPS_POS_NOT_OK };
+
+ CLSTR clstr_ann_dst = DEFAULT_STR_ANN_DST;
+ CLSTR clstr_ann_ls = DEFAULT_STR_ANN_LS;
+
+ PCPS_STATUS_STRS tmp_strs;
+ PCPS_STATUS_STR *pstr = &tmp_strs.s[0];
+
+ memset( &tmp_strs, 0, sizeof( tmp_strs ) );
+
+ if ( !status_is_read )
+ pstr->cp = str_not_avail;
+ else
+ {
+ if ( status & PCPS_INVT )
+ {
+ pstr->cp = _lstr( clstr_time_inval );
+ pstr->is_err = 1;
+ }
+ else
+ if ( status & PCPS_IFTM )
+ {
+ pstr->cp = _lstr( clstr_set_manually );
+ pstr->is_err = 1;
+ }
+ else
+ {
+ pcps_setup_status_str( pstr, ( status & PCPS_SYNCD ) == 0,
+ is_gps ? &lstr_gps_syncd : &lstr_dcf_has_syncd );
+
+ pstr++;
+
+ pcps_setup_status_str( pstr, ( status & PCPS_FREER ) != 0,
+ is_gps ? &lstr_gps_pos : &lstr_dcf_not_free_running );
+ }
+
+ pstr++;
+
+ if ( status & PCPS_DL_ANN )
+ pstr->cp = _lstr( clstr_ann_dst );
+ else
+ if ( status & PCPS_LS_ANN )
+ pstr->cp = _lstr( clstr_ann_ls );
+ }
+
+ *pstrs = tmp_strs;
+
+} // pcps_status_strs
+
+
+
+/*HDR*/
+char *pcps_port_str( char *s, const PCPS_DEV *pdev )
+{
+ ushort port = _pcps_port_base( pdev, 0 );
+
+ ushort n = sprintf( s, "%3Xh", port );
+
+ port = _pcps_port_base( pdev, 1 );
+
+ if ( port )
+ sprintf( &s[n], ", %3Xh", port );
+
+ return s;
+
+} // pcps_port_str
+
+
+
+/*HDR*/
+const char *pcps_tzcode_str( PCPS_TZCODE tzcode )
+{
+ if ( language < N_LNG && tzcode < N_PCPS_TZCODE )
+ return tzcode_name[tzcode][language];
+
+ return inv_str();
+
+} // pcps_tzcode_str
+
+
+
+/*HDR*/
+char *pcps_serial_str( char *s, int i, const RECEIVER_PORT_CFG *p,
+ const RECEIVER_INFO *p_ri, int short_strs )
+{
+ const PORT_SETTINGS *p_ps = &p->pii[i].port_info.port_settings;
+ const STR_TYPE_INFO *p_sti = &p->stii[p_ps->str_type].str_type_info;
+
+ sprintf( s, "%lu,%s", (ulong) p_ps->parm.baud_rate, p_ps->parm.framing );
+
+ if ( short_strs )
+ sprintf( _eos( s ), ",%s", short_mode_name[p_ps->mode] );
+ else
+ {
+ if ( p_ri->n_str_type > 1 )
+ sprintf( _eos( s ), ", %s", p_sti->long_name );
+
+ sprintf( _eos( s ), ", %s", _lstr( mode_name[p_ps->mode] ) );
+ }
+
+ return( s );
+
+} // pcps_serial_str
+
+
diff --git a/mbglib/common/pcpslstr.h b/mbglib/common/pcpslstr.h
new file mode 100644
index 0000000..650799d
--- /dev/null
+++ b/mbglib/common/pcpslstr.h
@@ -0,0 +1,1052 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpslstr.h 1.28 2012/10/15 13:01:23Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for pcpslstr.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpslstr.h $
+ * Revision 1.28 2012/10/15 13:01:23Z martin
+ * Include cfg_hlp.h.
+ * Made all declarations extern C.
+ * Added menu titles for PTP and PTP Unicast configuration.
+ * Added DEFAULT_OPT_NAME_TR_DISTANCE.
+ * Support time slots mode for programmable pulse outputs.
+ * Added strings for programmable output synthesizer mode.
+ * Fixed build under FreeBSD.
+ * Also use ANSI umlauts under QNX.
+ * Updated function prototypes.
+ * Revision 1.27 2010/06/28 08:28:17Z stefan
+ * Added greek character mu.
+ * Corrected a spelling mistake.
+ * Defined umlauts as hex codes.
+ * Added _pcps_sprint_vernum macro which is either _dec or _hex,
+ * depending on the target platform.
+ * Revision 1.26 2010/06/25 13:58:25 daniel
+ * Added IgnoreTFOM related language strings
+ * Revision 1.25 2010/01/28 09:02:27 martin
+ * Added menu option name for LAN interface.
+ * Added German POUT mode names for DCF77_M59.
+ * Revision 1.24 2009/03/19 08:07:45Z daniel
+ * Updated function prototypes.
+ * Revision 1.23 2008/11/14 12:12:45Z martin
+ * Updated function prototypes.
+ * Revision 1.22 2008/01/17 09:12:41Z daniel
+ * Use mbg_tgt.h, specially to care about wchar_t.
+ * Added strings for WEZ/WESZ, BST, GMT.
+ * Updated function prototypes.
+ * Revision 1.21 2007/03/30 13:24:42Z martin
+ * Added initializer for status string if time has been set manually.
+ * Revision 1.20 2007/03/29 12:59:23Z martin
+ * Moved some definitions here.
+ * Added and modified some definitions related to TZCODE.
+ * Revision 1.19 2006/10/23 15:18:15Z martin
+ * Added some configuration warning msg texts.
+ * Added definitions for uppercase umlauts.
+ * Separated English and German initializers for some strings.
+ * Revision 1.18 2006/09/26 14:57:22Z martin
+ * Added DEFAULT_OPT_NAME_POUT.
+ * Revision 1.17 2000/07/02 07:02:16Z martin
+ * Separate English and German initializers for "invalid time".
+ * Revision 1.16 2006/05/23 20:13:24Z martin
+ * Added initializers for German POUT mode strings.
+ * Revision 1.15 2005/12/20 10:30:56Z martin
+ * Made some strings start with uppercase letters.
+ * Revision 1.14 2005/08/12 12:35:34Z martin
+ * Fixed missing comma in a macro.
+ * Revision 1.13 2005/03/03 08:49:38Z martin
+ * Modified DEFAULT_OPT_NAME_SERIAL.
+ * Modified DEFAULT_OPT_NAME_IRIG_...
+ * Added default strings for synthesizer.
+ * Revision 1.12 2004/11/23 09:36:12Z martin
+ * Fixed a typo.
+ * Revision 1.11 2004/11/09 15:08:08Z martin
+ * Defined some separate strings for English and German.
+ * Modified some string contents.
+ * Revision 1.10 2004/10/26 15:03:57 martin
+ * Distinguish between IRIG RX and TX strings.
+ * Revision 1.9 2004/08/18 14:59:04Z martin
+ * Defined some flag bits to control the format of the output string
+ * generated by pcps_tz_name().
+ * Updated function prototypes.
+ * Revision 1.8 2004/04/07 12:49:06Z martin
+ * Added initializers for IRIG output cfg strings.
+ * Revision 1.7 2003/04/15 10:47:29Z martin
+ * Added initializers for IRIG menu strings.
+ * Updated function prototypes.
+ * Revision 1.6 2002/12/18 13:57:53 martin
+ * Some definitions and variables made global.
+ * Added some new macros _pcps_sprint_vernum...()
+ * and _pcps_sprint_dev_id().
+ * Revision 1.5 2002/02/19 10:01:36Z MARTIN
+ * New initializers for string mode names.
+ * New global variables mode_name and short_mode_name.
+ * Updated function prototypes.
+ * Revision 1.4 2001/09/17 13:26:16 MARTIN
+ * Added definitions for PCPS_STATUS_STRS.
+ * Added initializers for strings.
+ * Added some comments.
+ * Updated function prototypes.
+ * Revision 1.3 2001/08/14 11:35:40 MARTIN
+ * Added initializers for commonly used mulit-language
+ * text strings.
+ * Revision 1.2 2001/02/28 15:48:34 MARTIN
+ * Updated function prototypes.
+ * Modified syntax to initialize variables.
+ * Revision 1.1 2000/07/21 12:15:12 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PCPSLSTR_H
+#define _PCPSLSTR_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+#include <cfg_hlp.h>
+#include <parmpcps.h>
+#include <ctrydttm.h>
+#include <cnv_wday.h>
+
+#if MBG_TGT_HAS_WCHAR_T
+ #include <wchar.h>
+#endif
+
+#ifdef _PCPSLSTR
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// upper case 'A' umlaut
+#define ANSI_UC_A_UML '\xC4' // single char
+#define ANSI_US_A_UML "\xC4" // string
+
+// upper case 'O' umlaut
+#define ANSI_UC_O_UML '\xD6' // single char
+#define ANSI_US_O_UML "\xD6" // string
+
+// upper case 'U' umlaut
+#define ANSI_UC_U_UML '\xDC' // single char
+#define ANSI_US_U_UML "\xDC" // string
+
+// lower case 'a' umlaut
+#define ANSI_LC_A_UML '\xE4' // single char
+#define ANSI_LS_A_UML "\xE4" // string
+
+// lower case 'o' umlaut
+#define ANSI_LC_O_UML '\xF6' // single char
+#define ANSI_LS_O_UML "\xF6" // string
+
+// lower case 'u' umlaut
+#define ANSI_LC_U_UML '\xFC' // single char
+#define ANSI_LS_U_UML "\xFC" // string
+
+// 'sz' umlaut
+#define ANSI_LC_SZ_UML '\xDF' // single char
+#define ANSI_LS_SZ_UML "\xDF" // string
+
+// degree character
+#define ANSI_C_DEGREE '\xB0' // single char
+#define ANSI_S_DEGREE "\xB0" // string
+
+// greek mu character
+#define ANSI_C_MU '\xB5' //single char
+#define ANSI_S_MU "\xB5" //string
+
+#if defined( MBG_TGT_WIN32 ) \
+ || defined( MBG_TGT_UNIX ) \
+ || defined( MBG_TGT_QNX )
+ #define DEFAULT_PCPS_WDAY_DATE_DIST 1
+ #define DEFAULT_PCPS_DATE_TIME_DIST 2
+ #define DEFAULT_PCPS_TIME_TZ_DIST 1
+
+ #define UCAE ANSI_US_A_UML
+ #define UCOE ANSI_US_O_UML
+ #define UCUE ANSI_US_U_UML
+
+ #define LCAE ANSI_LS_A_UML
+ #define LCOE ANSI_LS_O_UML
+ #define LCUE ANSI_LS_U_UML
+
+ #define LCSZ ANSI_LS_SZ_UML
+ #define DEG ANSI_S_DEGREE
+ #define MU ANSI_S_MU
+#else
+ #define DEFAULT_PCPS_WDAY_DATE_DIST 1
+ #define DEFAULT_PCPS_DATE_TIME_DIST 2
+ #define DEFAULT_PCPS_TIME_TZ_DIST 1
+
+ #define UCAE "\x8E"
+ #define UCOE "\x99"
+ #define UCUE "\x9A"
+
+ #define LCAE "\x84"
+ #define LCOE "\x94"
+ #define LCUE "\x81"
+
+ #define LCSZ "\xE1"
+ #define DEG "\xF8"
+ #define MU "\xE6"
+#endif
+
+
+// The flags defined below can be passed to pcps_tz_name()
+// in order to control the generation of time zone names
+
+enum
+{
+ PCPS_TZ_NAME_BIT_FORCE_UTC_OFFS, // always print "UTC+offs"
+ PCPS_TZ_NAME_BIT_APP_DST, // append DST status
+ N_PCPS_TZ_NAME_FLAG
+};
+
+// bit masks corresponding to the flags above
+#define PCPS_TZ_NAME_FORCE_UTC_OFFS ( 1UL << PCPS_TZ_NAME_BIT_FORCE_UTC_OFFS )
+#define PCPS_TZ_NAME_APP_DST ( 1UL << PCPS_TZ_NAME_BIT_APP_DST )
+
+
+// The definitions below are used with pcps_get_status_strs().
+
+#define N_PCPS_STATUS_STR 3
+
+typedef struct
+{
+ const char *cp;
+ int is_err;
+} PCPS_STATUS_STR;
+
+typedef struct
+{
+ PCPS_STATUS_STR s[N_PCPS_STATUS_STR];
+} PCPS_STATUS_STRS;
+
+
+// initializers for commonly use multi-language strings
+// (type: CLSTR )
+
+
+// time adjustment window
+
+#define DEFAULT_STR_TIME_ADJ_STATUS \
+{ \
+ "Time Adjustment Status", \
+ "Status der Zeitkontrolle" \
+}
+
+#define DEFAULT_STR_SYS_TIME \
+{ \
+ "System Time:", \
+ "Systemzeit:" \
+}
+
+#define DEFAULT_STR_REF_TIME \
+{ \
+ "Reference Time:", \
+ "Referenzzeit:" \
+}
+
+#define DEFAULT_STR_DELTA_TIME \
+{ \
+ "Difference:", \
+ "Zeitdifferenz:" \
+}
+
+#define DEFAULT_STR_LAST_CORR \
+{ \
+ "Last Correction:", \
+ "Letzte Korrektur:" \
+}
+
+#define DEFAULT_STR_WAIT_SYNC \
+{ \
+ "Waiting for Sync After Reset ...", \
+ "Warte auf Sync. nach Reset ..." \
+}
+
+
+// ref time window
+
+#define DEFAULT_STR_REF_TIME_INFO \
+{ \
+ "Reference Time Info", \
+ "Referenzzeit" \
+}
+
+#define DEFAULT_STR_REF_SRC_LABEL \
+{ \
+ "Time Source:", \
+ "Funkuhr ID:" \
+}
+
+#define DEFAULT_STR_REF_SYNC_LABEL \
+{ \
+ "Last Sync.:", \
+ "Letzte Sync.:" \
+}
+
+
+// Clock status messages:
+
+// Time is not valid (i.e. after batt. empty).
+#define DEFAULT_STR_TIME_INVAL_EN \
+ "Ref. Time is Invalid"
+
+#define DEFAULT_STR_TIME_INVAL_DE \
+ "Referenzzeit nicht g" LCUE "ltig"
+
+#define DEFAULT_STR_TIME_INVAL \
+{ \
+ DEFAULT_STR_TIME_INVAL_EN, \
+ DEFAULT_STR_TIME_INVAL_DE \
+}
+
+// on-board time has been set manually
+#define DEFAULT_STR_SET_MANUALLY \
+{ \
+ "Time has been set manually", \
+ "Zeit wurde manuell gesetzt" \
+}
+
+// DCF77 receiver has synch'd at least once
+// after reset.
+#define DEFAULT_STR_DCF_HAS_SYNCD \
+{ \
+ "Synchronized after last RESET", \
+ "Sync. nach RESET ist erfolgt" \
+}
+
+// DCF77 receiver has not synch'd after reset.
+#define DEFAULT_STR_DCF_HAS_NOT_SYNCD \
+{ \
+ "Not synchronized after last RESET", \
+ "Sync. nach RESET noch nicht erfolgt" \
+}
+
+// DCF77 receiver currently runs on XTAL.
+#define DEFAULT_STR_DCF_FREE_RUNNING \
+{ \
+ "Clock running on Xtal oscillator", \
+ "Funkuhr l" LCAE "uft frei auf Quarzbasis" \
+}
+
+// DCF77 receiver is currently synchronized.
+#define DEFAULT_STR_DCF_NOT_FREE_RUNNING \
+{ \
+ "Clock is synchronized", \
+ "Senderf" LCUE "hrung" \
+}
+
+// GPS receiver is currently synchronized.
+#define DEFAULT_STR_GPS_SYNCD \
+{ \
+ "Time is synchronized", \
+ "Zeitsynchronisation ist erfolgt" \
+}
+
+// GPS receiver is currently synchronized.
+#define DEFAULT_STR_GPS_NOT_SYNCD \
+{ \
+ "Time not synchronized", \
+ "Zeit ist nicht synchron" \
+}
+
+// GPS receiver has verified its position.
+#define DEFAULT_STR_GPS_POS_OK \
+{ \
+ "Receiver position has been verified", \
+ "Positionbestimmung durchgef" LCUE "hrt" \
+}
+
+// GPS receiver has not verified its position.
+#define DEFAULT_STR_GPS_POS_NOT_OK \
+{ \
+ "Receiver pos. not verified", \
+ "Position nicht gepr" LCUE "ft" \
+}
+
+// Announcement of DST change.
+#define DEFAULT_STR_ANN_DST \
+{ \
+ "Change in Daylight Saving Announced", \
+ "Zeitumschaltung angek" LCUE "ndigt" \
+}
+
+// Announcement of leap second.
+#define DEFAULT_STR_ANN_LS \
+{ \
+ "Leap Second Announced", \
+ "Schaltsekunde angek" LCUE "ndigt" \
+}
+
+
+// menu option: setup (title)
+
+#define DEFAULT_OPT_NAME_SETUP_EN \
+ "Setup"
+
+#define DEFAULT_OPT_NAME_SETUP_DE \
+ "Einstellungen"
+
+#define DEFAULT_OPT_NAME_SETUP \
+{ \
+ DEFAULT_OPT_NAME_SETUP_EN, \
+ DEFAULT_OPT_NAME_SETUP_DE \
+}
+
+
+// menu option: setup date/time
+
+#define DEFAULT_OPT_NAME_SET_TIME_EN \
+ "Radio Clock's Date/Time"
+
+#define DEFAULT_OPT_NAME_SET_TIME_DE \
+ "Datum/Zeit der Funkuhr"
+
+#define DEFAULT_OPT_NAME_SET_TIME \
+{ \
+ DEFAULT_OPT_NAME_SET_TIME_EN, \
+ DEFAULT_OPT_NAME_SET_TIME_DE \
+}
+
+#define DEFAULT_STR_NEW_DATE \
+{ \
+ "New date", \
+ "Neues Datum" \
+}
+
+#define DEFAULT_STR_NEW_TIME \
+{ \
+ "New time", \
+ "Neue Zeit" \
+}
+
+
+// menu option: setup time zone
+
+#define TZ_NAME_UTC "UTC"
+
+#define TZ_NAME_MEZ "MEZ"
+#define TZ_NAME_MESZ "MESZ"
+#define TZ_NAME_CET "CET"
+#define TZ_NAME_CEST "CEST"
+
+#define TZ_NAME_OEZ "OEZ"
+#define TZ_NAME_OESZ "OESZ"
+#define TZ_NAME_EET "EET"
+#define TZ_NAME_EEST "EEST"
+
+#define TZ_NAME_WEZ "WEZ"
+#define TZ_NAME_WESZ "WESZ"
+#define TZ_NAME_GMT "GMT"
+#define TZ_NAME_BST "BST"
+
+#define DEFAULT_OPT_NAME_TZ \
+{ \
+ "Radio Clock's Time Zone", \
+ "Zeitzone der Funkuhr" \
+}
+
+
+// menu option: setup time zone
+
+#define DEFAULT_TZCODE_NAME_CET_CEST \
+{ \
+ TZ_NAME_CET "/" TZ_NAME_CEST, \
+ TZ_NAME_MEZ "/" TZ_NAME_MESZ \
+}
+
+#define DEFAULT_TZCODE_HINT_CET_CEST \
+{ \
+ "Central European Time or Summer Time, as broadcasted by DCF77", \
+ "Mitteleurop" LCAE "ische Zeit oder Sommerzeit, wie von DCF77 gesendet" \
+}
+
+#define DEFAULT_TZCODE_NAME_GMT_BST \
+{ \
+ TZ_NAME_GMT "/" TZ_NAME_BST, \
+ TZ_NAME_WEZ "/" TZ_NAME_WESZ \
+}
+
+#define DEFAULT_TZCODE_HINT_GMT_BST \
+{ \
+ "Greenwich Mean Time or British Summer Time, as broadcasted by MSF", \
+ "Westeurop" LCAE "ische Zeit oder britische Sommerzeit, wie von MSF gesendet" \
+}
+
+
+
+#define DEFAULT_TZCODE_NAME_CET \
+{ \
+ "always " TZ_NAME_CET, \
+ "immer " TZ_NAME_MEZ \
+}
+
+#define DEFAULT_TZCODE_HINT_CET \
+{ \
+ "always CET (UTC+1h), daylight saving suppressed", \
+ "immer MEZ (UTC+1h), Sommerzeit wird unterdr" LCUE "ckt" \
+}
+
+
+#define DEFAULT_TZCODE_NAME_UTC \
+{ \
+ TZ_NAME_UTC, \
+ TZ_NAME_UTC \
+}
+
+#define DEFAULT_TZCODE_HINT_UTC \
+{ \
+ "always UTC", \
+ "immer UTC" \
+}
+
+
+#define DEFAULT_TZCODE_NAME_EET_EEST \
+{ \
+ TZ_NAME_EET "/" TZ_NAME_EEST, \
+ TZ_NAME_OEZ "/" TZ_NAME_OESZ \
+}
+
+#define DEFAULT_TZCODE_HINT_EET_EEST \
+{ \
+ "East European Time, CET/CEST + 1h", \
+ "Osteurop" LCAE "ische Zeit, MEZ/MESZ + 1h" \
+}
+
+
+#define DEFAULT_TZCODE_NAMES \
+{ \
+ DEFAULT_TZCODE_NAME_CET_CEST, \
+ DEFAULT_TZCODE_NAME_CET, \
+ DEFAULT_TZCODE_NAME_UTC, \
+ DEFAULT_TZCODE_NAME_EET_EEST \
+}
+
+#define DEFAULT_TZCODE_HINTS \
+{ \
+ DEFAULT_TZCODE_HINT_CET_CEST, \
+ DEFAULT_TZCODE_HINT_CET, \
+ DEFAULT_TZCODE_HINT_UTC, \
+ DEFAULT_TZCODE_HINT_EET_EEST \
+}
+
+
+// menu option: setup serial parameters
+
+#define DEFAULT_OPT_NAME_SERIAL \
+{ \
+ "On-Board Serial Ports", \
+ "Serielle Schnittstellen der Karte" \
+}
+
+
+// menu option: setup enable flags
+
+#define DEFAULT_OPT_NAME_EF \
+{ \
+ "Enable Outputs", \
+ "Freischaltung der Ausg" LCAE "nge" \
+}
+
+
+// menu option: setup length of antenna cable
+
+#define DEFAULT_OPT_NAME_CAB_LEN \
+{ \
+ "Antenna Cable", \
+ "Antennenkabel" \
+}
+
+
+// menu option: setup distance from transmitter
+
+#define DEFAULT_OPT_NAME_TR_DISTANCE \
+{ \
+ "Distance from Transmitter", \
+ "Senderentfernung" \
+}
+
+
+// menu option: setup IRIG config
+
+#define DEFAULT_OPT_NAME_IRIG_TX_EN "IRIG Output"
+#define DEFAULT_OPT_NAME_IRIG_TX_DE "IRIG-Ausgang"
+
+#define DEFAULT_OPT_NAME_IRIG_TX \
+{ \
+ DEFAULT_OPT_NAME_IRIG_TX_EN, \
+ DEFAULT_OPT_NAME_IRIG_TX_DE \
+}
+
+
+#define DEFAULT_OPT_NAME_IRIG_RX_EN "IRIG Input"
+#define DEFAULT_OPT_NAME_IRIG_RX_DE "IRIG-Eingang"
+
+#define DEFAULT_OPT_NAME_IRIG_RX \
+{ \
+ DEFAULT_OPT_NAME_IRIG_RX_EN, \
+ DEFAULT_OPT_NAME_IRIG_RX_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_FMT_EN "IRIG Code Format"
+#define DEFAULT_STR_IRIG_FMT_DE "IRIG Code-Format"
+
+#define DEFAULT_STR_IRIG_FMT \
+{ \
+ DEFAULT_STR_IRIG_FMT_EN, \
+ DEFAULT_STR_IRIG_FMT_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_OFFS_EN "IRIG Time Offset from UTC"
+#define DEFAULT_STR_IRIG_OFFS_DE "IRIG-Zeitoffset zu UTC"
+
+#define DEFAULT_STR_IRIG_OFFS \
+{ \
+ DEFAULT_STR_IRIG_OFFS_EN, \
+ DEFAULT_STR_IRIG_OFFS_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_TIMESTR_UTC_EN "Send serial UTC"
+#define DEFAULT_STR_IRIG_TIMESTR_UTC_DE "Seriell UTC ausgeben"
+
+#define DEFAULT_STR_IRIG_TIMESTR_UTC \
+{ \
+ DEFAULT_STR_IRIG_TIMESTR_UTC_EN, \
+ DEFAULT_STR_IRIG_TIMESTR_UTC_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_OUTPUT_LOC_TM_EN "Transmit local time instead of UTC"
+#define DEFAULT_STR_IRIG_OUTPUT_LOC_TM_DE "Ortszeit statt UTC aussenden"
+
+#define DEFAULT_STR_IRIG_OUTPUT_LOC_TM \
+{ \
+ DEFAULT_STR_IRIG_OUTPUT_LOC_TM_EN, \
+ DEFAULT_STR_IRIG_OUTPUT_LOC_TM_DE \
+}
+
+#define DEFAULT_IGNORE_RX_TFOM_EN "Ignore TFOM"
+#define DEFAULT_IGNORE_RX_TFOM_DE "Ignoriere TFOM"
+
+#define DEFAULT_IGNORE_RX_TFOM \
+{ \
+ DEFAULT_IGNORE_RX_TFOM_EN, \
+ DEFAULT_IGNORE_RX_TFOM_DE \
+}
+
+#define DEFAULT_STR_TFOM_ALWAYS_SYNC_EN "Output TFOM always as 'sync'"
+#define DEFAULT_STR_TFOM_ALWAYS_SYNC_DE "TFOM immer als 'sync' ausgeben"
+
+#define DEFAULT_STR_TFOM_ALWAYS_SYNC \
+{ \
+ DEFAULT_STR_TFOM_ALWAYS_SYNC_EN, \
+ DEFAULT_STR_TFOM_ALWAYS_SYNC_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_NOT_CFGD_EN \
+ "The IRIG receiver has not yet been configured!\n" \
+ "\n" \
+ "Please make sure the correct " DEFAULT_STR_IRIG_FMT_EN " has been\n" \
+ "selected, and enter the correct " DEFAULT_STR_IRIG_OFFS_EN "\n" \
+ "according to the settings of the IRIG generator."
+
+#define DEFAULT_STR_IRIG_NOT_CFGD_DE \
+ "Der IRIG-Empf" LCAE "nger wurde noch nicht konfiguriert!\n" \
+ "\n" \
+ "Das ausgew" LCAE "hlte " DEFAULT_STR_IRIG_FMT_DE " sowie der\n" \
+ DEFAULT_STR_IRIG_OFFS_DE " m" LCUE "ssen den Einstellungen\n" \
+ "des verwendeten IRIG-Generators entsprechen."
+
+#define DEFAULT_STR_IRIG_NOT_CFGD \
+{ \
+ DEFAULT_STR_IRIG_NOT_CFGD_EN, \
+ DEFAULT_STR_IRIG_NOT_CFGD_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_INVT_EN \
+ "Please note that the IRIG receiver status may read\n" \
+ "\"" DEFAULT_STR_TIME_INVAL_EN "\" if the receiver's on-board date\n" \
+ "does not correspond to the date (day-of-year number)\n" \
+ "transmitted by the IRIG source."
+
+#define DEFAULT_STR_IRIG_INVT_DE \
+ "Wenn im Status des IRIG-Empf" LCAE "ngers \"" DEFAULT_STR_TIME_INVAL_DE "\"\n" \
+ "angezeigt wird, kann der Grund daf" LCUE "r sein, dass das Datum\n" \
+ "auf der Einsteckkarte nicht mit dem vom IRIG-Generator\n" \
+ "gesendeten Datum (bzw. dem Jahrestag) " LCUE "bereinstimmt." \
+
+#define DEFAULT_STR_IRIG_INVT \
+{ \
+ DEFAULT_STR_IRIG_INVT_EN, \
+ DEFAULT_STR_IRIG_INVT_DE \
+}
+
+
+// menu option: programmable outputs
+
+#define DEFAULT_OPT_NAME_POUT \
+{ \
+ "Programmable Pulse Outputs", \
+ "Programmierbare Schaltausg" LCAE "nge" \
+}
+
+
+// menu option: frequency synthesizer
+
+#define DEFAULT_OPT_NAME_SYNTH \
+{ \
+ "Frequency Synthesizer", \
+ "Frequenz-Synthesizer" \
+}
+
+#define DEFAULT_STR_SYNTH_FREQ \
+{ \
+ "Frequency", \
+ "Frequenz" \
+}
+
+#define DEFAULT_STR_SYNTH_PHASE \
+{ \
+ "Phase", \
+ NULL \
+}
+
+
+// menu option: LAN interface
+
+#define DEFAULT_OPT_NAME_LAN_INTF_EN "LAN Interface"
+#define DEFAULT_OPT_NAME_LAN_INTF_DE "Netzwerkschnittstelle"
+
+#define DEFAULT_OPT_NAME_LAN_INTF \
+{ \
+ DEFAULT_OPT_NAME_LAN_INTF_EN, \
+ DEFAULT_OPT_NAME_LAN_INTF_DE \
+}
+
+
+
+// menu option: PTP configuration
+
+#define DEFAULT_OPT_NAME_PTP_CFG_EN "PTP Configuration"
+#define DEFAULT_OPT_NAME_PTP_CFG_DE "PTP-Konfiguration"
+
+#define DEFAULT_OPT_NAME_PTP_CFG \
+{ \
+ DEFAULT_OPT_NAME_PTP_CFG_EN, \
+ DEFAULT_OPT_NAME_PTP_CFG_DE \
+}
+
+
+
+// menu option: PTP Unicast configuration
+
+#define DEFAULT_OPT_NAME_PTP_UC_CFG_EN "PTP Unicast Configuration"
+#define DEFAULT_OPT_NAME_PTP_UC_CFG_DE "PTP-Unicast-Konfiguration"
+
+#define DEFAULT_OPT_NAME_PTP_UC_CFG \
+{ \
+ DEFAULT_OPT_NAME_PTP_UC_CFG_EN, \
+ DEFAULT_OPT_NAME_PTP_UC_CFG_DE \
+}
+
+
+
+/*
+ * Default initializers for German mode string names.
+ * English strings are defined in in gpsdefs.h.
+ */
+#define GER_MODE_NAME_STR_ON_REQ "nur auf Anfrage '?'"
+#define GER_MODE_NAME_STR_PER_SEC "sek" LCUE "ndlich"
+#define GER_MODE_NAME_STR_PER_MIN "min" LCUE "tlich"
+#define GER_MODE_NAME_STR_AUTO "automatisch"
+#define GER_MODE_NAME_STR_ON_REQ_SEC "sek" LCUE "ndlich nach Anfrage"
+
+#define DEFAULT_MODE_NAMES \
+{ \
+ { ENG_MODE_NAME_STR_ON_REQ, GER_MODE_NAME_STR_ON_REQ }, \
+ { ENG_MODE_NAME_STR_PER_SEC, GER_MODE_NAME_STR_PER_SEC }, \
+ { ENG_MODE_NAME_STR_PER_MIN, GER_MODE_NAME_STR_PER_MIN }, \
+ { ENG_MODE_NAME_STR_AUTO, GER_MODE_NAME_STR_AUTO }, \
+ { ENG_MODE_NAME_STR_ON_REQ_SEC, GER_MODE_NAME_STR_ON_REQ_SEC } \
+}
+
+
+/*
+ * Default initializers for German pulse output mode string names.
+ * English strings are defined in in gpsdefs.h.
+ */
+#define GER_POUT_NAME_IDLE "Nicht verwendet"
+#define GER_POUT_NAME_TIMER "Zeitschaltung"
+#define GER_POUT_NAME_SINGLE_SHOT "Einzelimpuls"
+#define GER_POUT_NAME_CYCLIC_PULSE "Zyklischer Impuls"
+#define GER_POUT_NAME_PER_SEC "Sek" LCUE "ndlicher Impuls"
+#define GER_POUT_NAME_PER_MIN "Min" LCUE "tlicher Impuls"
+#define GER_POUT_NAME_PER_HOUR "St" LCUE "ndlicher Impuls"
+#define GER_POUT_NAME_DCF77 "DCF77-Zeitmarken"
+#define GER_POUT_NAME_POS_OK "Position OK"
+#define GER_POUT_NAME_TIME_SYNC "Zeit synchron"
+#define GER_POUT_NAME_ALL_SYNC "alles synchron"
+#define GER_POUT_NAME_TIMECODE "DCLS-Zeitcode"
+#define GER_POUT_NAME_TIMESTR "COM-Zeittelegramm"
+#define GER_POUT_NAME_10MHZ "Festfrequenz 10 MHz"
+#define GER_POUT_NAME_DCF77_M59 "DCF77-Zeitmarken mit 59. Impuls"
+#define GER_POUT_NAME_SYNTH "Frequenz-Synthesizer"
+#define GER_POUT_NAME_TIME_SLOTS "Zeitschlitze pro Minute"
+
+#define DEFAULT_GER_POUT_NAMES \
+{ \
+ GER_POUT_NAME_IDLE, \
+ GER_POUT_NAME_TIMER, \
+ GER_POUT_NAME_SINGLE_SHOT, \
+ GER_POUT_NAME_CYCLIC_PULSE, \
+ GER_POUT_NAME_PER_SEC, \
+ GER_POUT_NAME_PER_MIN, \
+ GER_POUT_NAME_PER_HOUR, \
+ GER_POUT_NAME_DCF77, \
+ GER_POUT_NAME_POS_OK, \
+ GER_POUT_NAME_TIME_SYNC, \
+ GER_POUT_NAME_ALL_SYNC, \
+ GER_POUT_NAME_TIMECODE, \
+ GER_POUT_NAME_TIMESTR, \
+ GER_POUT_NAME_10MHZ, \
+ GER_POUT_NAME_DCF77_M59, \
+ GER_POUT_NAME_SYNTH, \
+ GER_POUT_NAME_TIME_SLOTS \
+}
+
+/*
+ * Default initializers for German pulse output mode hints.
+ * English strings are defined in in gpsdefs.h.
+ */
+#define GER_POUT_HINT_IDLE "Konstanter Ausgangspegel"
+#define GER_POUT_HINT_TIMER "Schalten zu den angegebenen Zeiten"
+#define GER_POUT_HINT_SINGLE_SHOT "Einzelner Impuls mit angegebener L" LCAE "nge"
+#define GER_POUT_HINT_CYCLIC_PULSE "Impulse wiederholt nach angegebenem Intervall"
+#define GER_POUT_HINT_PER_SEC "Impuls zu Beginn jeder Sekunde"
+#define GER_POUT_HINT_PER_MIN "Impuls zu Beginn jeder Minute"
+#define GER_POUT_HINT_PER_HOUR "Impuls zu Beginn jeder Stunde"
+#define GER_POUT_HINT_DCF77 "DCF77-kompatible Zeitmarken"
+#define GER_POUT_HINT_POS_OK "Schalten, wenn Empf" LCAE "ngerposition " LCUE "berpr" LCUE "ft"
+#define GER_POUT_HINT_TIME_SYNC "Schalten, wenn Zeit synchron"
+#define GER_POUT_HINT_ALL_SYNC "Schalten, wenn Zeit synchron und Position " LCUE "berpr" LCUE "ft"
+#define GER_POUT_HINT_TIMECODE "Unmodulierter Zeitcode des IRIG-Ausgangs"
+#define GER_POUT_HINT_TIMESTR "Zeittelegramm der seriellen Schnittstelle der Karte duplizieren"
+#define GER_POUT_HINT_10MHZ "Feste Ausgangsfrequenz 10 MHz"
+#define GER_POUT_HINT_DCF77_M59 "Zeitmarken wie DCF77, aber mit 500 ms Impuls in 59. Sekunde"
+#define GER_POUT_HINT_SYNTH "Durch programmierbaren Synthesizer erzeugte Frequenz"
+#define GER_POUT_HINT_TIME_SLOTS "Programmierbare Zeitslots, die in jeder Minute aktiviert werden"
+
+#define DEFAULT_GER_POUT_HINTS \
+{ \
+ GER_POUT_HINT_IDLE, \
+ GER_POUT_HINT_TIMER, \
+ GER_POUT_HINT_SINGLE_SHOT, \
+ GER_POUT_HINT_CYCLIC_PULSE, \
+ GER_POUT_HINT_PER_SEC, \
+ GER_POUT_HINT_PER_MIN, \
+ GER_POUT_HINT_PER_HOUR, \
+ GER_POUT_HINT_DCF77, \
+ GER_POUT_HINT_POS_OK, \
+ GER_POUT_HINT_TIME_SYNC, \
+ GER_POUT_HINT_ALL_SYNC, \
+ GER_POUT_HINT_TIMECODE, \
+ GER_POUT_HINT_TIMESTR, \
+ GER_POUT_HINT_10MHZ, \
+ GER_POUT_HINT_DCF77_M59, \
+ GER_POUT_HINT_SYNTH, \
+ GER_POUT_HINT_TIME_SLOTS \
+}
+
+
+
+// some macros which generate proper function calls
+
+#define _pcps_sprint_vernum_dec( _s, _v ) \
+ sprintf( (_s), "v%u.%02u", \
+ ( (unsigned) (_v) ) / 100, \
+ ( (unsigned) (_v) ) % 100 )
+
+#define _pcps_sprint_vernum_hex( _s, _v ) \
+ sprintf( (_s), "v%X.%02X", \
+ ( (unsigned) (_v) ) >> 8, \
+ ( (unsigned) (_v) ) & 0xFF )
+
+#if defined( MBG_TGT_WIN32 )
+ #define _pcps_sprint_vernum _pcps_sprint_vernum_dec
+#else
+ #define _pcps_sprint_vernum _pcps_sprint_vernum_hex
+#endif
+
+
+#define _pcps_sprint_dev_id( _s, _n ) \
+ sprintf( (_s), "%04Xh", _n )
+
+
+#define _pcps_sprint_wday( _s, _t, _l ) \
+ sprint_ctry_wday( (_s), _wday_mon17_to_sun06( (_t)->wday ), (_l) )
+
+#define _pcps_sprint_date( _s, _t, _yl ) \
+ sprint_ctry_dt( (_s), (_t)->mday, (_t)->month, \
+ pcps_exp_year( (_t)->year, (_yl) ) )
+
+#define _pcps_sprint_time( _s, _t ) \
+ sprint_ctry_tm( (_s), (_t)->hour, (_t)->min, (_t)->sec )
+
+#define _pcps_sprint_time_long( _s, _t ) \
+ sprint_ctry_tm_long( (_s), (_t)->hour, (_t)->min, (_t)->sec, (_t)->sec100, 2 )
+
+
+#define _cput_pcps_date( _t, _yl ) \
+{ \
+ char s[80]; \
+ _pcps_sprint_date( s, (_t), (_yl) ); \
+ cputs( s ); \
+}
+
+#define _cput_pcps_time( _t ) \
+{ \
+ char s[80]; \
+ _pcps_sprint_time( s, (_t) ); \
+ cputs( s ); \
+}
+
+#define _cput_pcps_time_long( _t ) \
+{ \
+ char s[80]; \
+ _pcps_sprint_time_long( s, (_t) ); \
+ cputs( s ); \
+}
+
+#define _cput_pcps_date_and_time( _t, _yl, _tz ) \
+{ \
+ char s[80]; \
+ cputs( pcps_date_time_str( s, (_t), (_yl), (_tz) ) ); \
+}
+
+
+_ext const char *str_not_avail
+#ifdef _DO_INIT
+ = "N/A"
+#endif
+;
+
+
+_ext CLSTR lstr_cet
+#ifdef _DO_INIT
+ = { TZ_NAME_CET, TZ_NAME_MEZ }
+#endif
+;
+
+
+_ext CLSTR lstr_cest
+#ifdef _DO_INIT
+ = { TZ_NAME_CEST, TZ_NAME_MESZ }
+#endif
+;
+
+_ext CLSTR lstr_gmt
+#ifdef _DO_INIT
+ = { TZ_NAME_GMT, TZ_NAME_WEZ }
+#endif
+;
+
+
+_ext CLSTR lstr_bst
+#ifdef _DO_INIT
+ = { TZ_NAME_BST, TZ_NAME_WESZ }
+#endif
+;
+
+_ext CLSTR tzcode_name[N_PCPS_TZCODE]
+#ifdef _DO_INIT
+ = DEFAULT_TZCODE_NAMES
+#endif
+;
+
+
+_ext int pcps_wday_date_dist
+#ifdef _DO_INIT
+ = DEFAULT_PCPS_WDAY_DATE_DIST
+#endif
+;
+
+
+_ext int pcps_date_time_dist
+#ifdef _DO_INIT
+ = DEFAULT_PCPS_DATE_TIME_DIST
+#endif
+;
+
+
+_ext int pcps_time_tz_dist
+#ifdef _DO_INIT
+ = DEFAULT_PCPS_TIME_TZ_DIST
+#endif
+;
+
+
+_ext const char *mode_name[N_STR_MODE][N_LNG]
+#ifdef _DO_INIT
+ = DEFAULT_MODE_NAMES
+#endif
+;
+
+
+_ext const char *short_mode_name[N_STR_MODE]
+#ifdef _DO_INIT
+ = DEFAULT_SHORT_MODE_NAMES
+#endif
+;
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ const char *inv_str( void ) ;
+ int sprint_utc_offs( char *s, const char *info, long utc_offs ) ;
+ const char *pcps_tz_name( const PCPS_TIME *t, ushort flags, int is_msf ) ;
+ const char *pcps_tz_name_from_hr_time( const PCPS_HR_TIME *hrt, ushort flags, int is_msf ) ;
+ const char *pcps_tz_name_hr_status( const PCPS_HR_TIME *t, ushort flags, int is_msf ) ;
+ const char *pcps_tz_name_from_status( ushort status ) ;
+ char *pcps_date_time_str( char *s, const PCPS_TIME *t, ushort year_limit, const char *tz_str ) ;
+ wchar_t *pcps_date_time_wstr( wchar_t *ws, const PCPS_TIME *t, ushort year_limit, const wchar_t *tz_str ) ;
+ void pcps_status_strs( ushort status, int status_is_read, int is_gps, PCPS_STATUS_STRS *pstrs ) ;
+ char *pcps_port_str( char *s, const PCPS_DEV *pdev ) ;
+ const char *pcps_tzcode_str( PCPS_TZCODE tzcode ) ;
+ char *pcps_serial_str( char *s, int i, const RECEIVER_PORT_CFG *p, const RECEIVER_INFO *p_ri, int short_strs ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _PCPSLSTR_H */
+
diff --git a/mbglib/common/pcpsmktm.c b/mbglib/common/pcpsmktm.c
new file mode 100644
index 0000000..90404a8
--- /dev/null
+++ b/mbglib/common/pcpsmktm.c
@@ -0,0 +1,53 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsmktm.c 1.4 2006/12/14 15:27:49Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Function to convert PCPS_TIME to Unix time (seconds since 1970)
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsmktm.c $
+ * Revision 1.4 2006/12/14 15:27:49Z martin
+ * Include time.h.
+ * Revision 1.3 2006/08/22 09:10:03 martin
+ * Renamed function totalsec() to mbg_mktime() and moved it
+ * to a separate file mbgmktm.c.
+ * Revision 1.2 2001/08/14 11:58:08 MARTIN
+ * Included sys/time.h for time_t definition.
+ * Revision 1.1 2001/02/02 15:30:09 MARTIN
+ *
+ **************************************************************************/
+
+#define _PCPSMKTM
+ #include <pcpsmktm.h>
+#undef _PCPSMKTM
+
+#include <mbgmktm.h>
+
+#include <time.h>
+
+
+/*HDR*/
+long pcps_mktime( PCPS_TIME *tp )
+{
+ time_t secs;
+ int year = tp->year;
+
+ if ( year < 70 )
+ year += 100;
+
+ secs = mbg_mktime( year, tp->month - 1, tp->mday - 1,
+ tp->hour, tp->min, tp->sec );
+
+ if ( secs != -1 )
+ secs -= tp->offs_utc * 3600;
+
+ return( secs );
+
+} // pcps_mktime
+
+
+
diff --git a/mbglib/common/pcpsmktm.h b/mbglib/common/pcpsmktm.h
new file mode 100644
index 0000000..086be75
--- /dev/null
+++ b/mbglib/common/pcpsmktm.h
@@ -0,0 +1,62 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsmktm.h 1.1 2001/02/02 15:31:07Z MARTIN REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for pcpsmktm.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsmktm.h $
+ * Revision 1.1 2001/02/02 15:31:07Z MARTIN
+ *
+ **************************************************************************/
+
+#ifndef _PCPSMKTM_H
+#define _PCPSMKTM_H
+
+
+/* Other headers to be included */
+
+#include <pcpsdefs.h>
+
+
+#ifdef _PCPSMKTM
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+//_ext PCPS_TIME tx;
+
+/* End of header body */
+
+#undef _ext
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ long pcps_mktime( PCPS_TIME *tp ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _PCPSMKTM_H */
diff --git a/mbglib/common/pcpsutil.c b/mbglib/common/pcpsutil.c
new file mode 100644
index 0000000..91109e0
--- /dev/null
+++ b/mbglib/common/pcpsutil.c
@@ -0,0 +1,162 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsutil.c 1.14 2011/06/29 11:03:44Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Utility functions used with programs for Meinberg devices.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsutil.c $
+ * Revision 1.14 2011/06/29 11:03:44Z martin
+ * Updated a comment.
+ * Revision 1.13 2009/03/09 13:39:45 martin
+ * Made pcps_exp_year() an inline function.
+ * Revision 1.12 2008/12/10 19:59:48 martin
+ * Made frac_sec_from_bin() an inline function.
+ * Revision 1.11 2008/11/25 10:00:25 martin
+ * Use new definitions of fraction conversion type and scale
+ * from pcpsdefs.h.
+ * Revision 1.10 2006/06/29 10:38:24Z martin
+ * New function pcps_time_is_valid().
+ * Modified pcps_str_to_port(), doesn't add a 0 entry to the list anymore.
+ * Fixed a compiler warning related to type conversion.
+ * Revision 1.9 2005/01/14 10:14:31Z martin
+ * Changed type of ISA port addr to int.
+ * Revision 1.8 2004/11/09 14:29:27Z martin
+ * Rewrote functions using C99 fixed-size definitions.
+ * Revision 1.7 2003/04/17 10:08:59Z martin
+ * Added some type casts to fix compiler warnings.
+ * Revision 1.6 2001/11/28 14:39:16Z MARTIN
+ * In frac_sec_from_bin(), define the divisor as floating point
+ * constant to avoid a domain errors on 16 bit systems.
+ * Revision 1.5 2001/09/17 07:28:01 MARTIN
+ * New function frac_sec_from_bin() to convert
+ * PCPS_HR_TIME fractions.
+ * Revision 1.4 2001/03/01 14:01:09 MARTIN
+ * Modified parameters for pcps_setup_isa_ports().
+ * Revision 1.3 2000/08/31 14:05:30 MARTIN
+ * Replaced pcps_str_to_port() by pcps_setup_isa_ports().
+ * Revision 1.2 2000/07/21 13:42:54 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _PCPSUTIL
+ #include <pcpsutil.h>
+#undef _PCPSUTIL
+
+#include <stdlib.h>
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_time_is_valid()
+ *
+ * Purpose: Pack a structure with serial port parameters
+ *
+ * Input/Output: p address of a structure holding both the
+ * packed and unpacked information
+ *
+ * Ret value: --
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+int pcps_time_is_valid( const PCPS_TIME *p )
+{
+ return ( p->sec100 <= 99 )
+ && ( p->sec <= 60 ) /* allow for leap second */
+ && ( p->min <= 59 )
+ && ( p->hour <= 23 )
+ && ( p->mday >= 1 ) && ( p->mday <= 31 )
+ && ( p->wday >= 1 ) && ( p->wday <= 7 )
+ && ( p->month >= 1 ) && ( p->month <= 12 )
+ && ( p->year <= 99 );
+
+} /* pcps_time_is_valid */
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_str_to_port()
+ *
+ * Purpose: Try to convert a string to a valid port
+ * address.
+ *
+ * Input: s the string
+ *
+ * Output: --
+ *
+ * Ret value: a valid port number or 0
+ *+-------------------------------------------------------------*/
+
+/*HDR*/
+void pcps_setup_isa_ports( char *s,
+ int *port_vals,
+ int n_vals )
+{
+ ushort i;
+
+
+ for ( i = 0; i < n_vals; i++ )
+ {
+ if ( *s == 0 )
+ break;
+
+ *port_vals++ = (uint16_t) strtoul( s, &s, 16 );
+
+ if ( *s == ',' )
+ s++;
+ }
+
+} // pcps_setup_isa_ports
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_unpack_serial()
+ *
+ * Purpose: Unpack a structure with serial port parameters
+ *
+ * Input/Output: p address of a structure holding both the
+ * packed and unpacked information
+ *
+ * Ret value: --
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+void pcps_unpack_serial( PCPS_SER_PACK *p )
+{
+ uint8_t pack = p->pack;
+
+ p->baud = (uint8_t) ( pack & BITMASK( PCPS_BD_BITS ) );
+ p->frame = (uint8_t) ( ( pack >> PCPS_FR_SHIFT ) & BITMASK( PCPS_FR_BITS ) );
+ p->mode = (uint8_t) ( ( pack >> PCPS_MOD_SHIFT ) & BITMASK( PCPS_MOD_BITS ) );
+
+} // pcps_unpack_serial
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_pack_serial()
+ *
+ * Purpose: Pack a structure with serial port parameters
+ *
+ * Input/Output: p address of a structure holding both the
+ * packed and unpacked information
+ *
+ * Ret value: --
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+void pcps_pack_serial( PCPS_SER_PACK *p )
+{
+ p->pack = (uint8_t) ( ( p->baud & BITMASK( PCPS_BD_BITS ) )
+ | ( ( p->frame & BITMASK( PCPS_FR_BITS ) ) << PCPS_FR_SHIFT )
+ | ( ( p->mode & BITMASK( PCPS_MOD_BITS ) ) << PCPS_MOD_SHIFT ) );
+
+} /* pcps_pack_serial */
+
+
+
diff --git a/mbglib/common/pcpsutil.h b/mbglib/common/pcpsutil.h
new file mode 100644
index 0000000..41982df
--- /dev/null
+++ b/mbglib/common/pcpsutil.h
@@ -0,0 +1,198 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsutil.h 1.15.1.1 2013/01/24 14:42:52Z martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for pcpsutil.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsutil.h $
+ * Revision 1.15.1.1 2013/01/24 14:42:52Z martin
+ * Added dfrac_sec_from_bin().
+ * Revision 1.15 2012/10/15 09:41:32 martin
+ * Cleaned up handling of pragma pack().
+ * Revision 1.14 2009/03/09 13:39:45 martin
+ * Made pcps_exp_year() an inline function.
+ * Revision 1.13 2008/12/10 19:59:48 martin
+ * Made frac_sec_from_bin() an inline function.
+ * Revision 1.12 2008/11/25 09:59:01 martin
+ * Moved definitions of PCPS_HRT_FRAC_SCALE and
+ * PCPS_HRT_FRAC_SCALE_FMT to pcpsdefs.h.
+ * Revision 1.11 2006/06/29 10:15:02Z martin
+ * Updated function prototypes.
+ * Revision 1.10 2005/01/14 10:16:12Z martin
+ * Updated function prototypes.
+ * Revision 1.9 2004/11/09 14:30:50Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Updated function prototypes.
+ * Revision 1.8 2004/04/14 09:22:09Z martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.7 2001/11/28 14:41:25Z MARTIN
+ * Changed PCPS_HRT_FRAC_SCALE and PCPS_HRT_FRAC_SCALE_FMT
+ * to print 7 rather than 6 digits.
+ * Revision 1.6 2001/09/14 11:59:33 MARTIN
+ * Support for PCPS_HR_TIME fraction conversion.
+ * Updated function prototypes.
+ * Revision 1.5 2001/08/14 12:06:44 MARTIN
+ * Defined constants used to draw a signal bar
+ * depending on a DCF77 clock's signal value.
+ * Revision 1.4 2001/03/01 14:03:18 MARTIN
+ * Updated function prototypes.
+ * Revision 1.3 2000/08/31 14:06:05 MARTIN
+ * Updated function prototypes.
+ * Revision 1.2 2000/07/21 13:43:40 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PCPSUTIL_H
+#define _PCPSUTIL_H
+
+
+/* Other headers to be included */
+
+#include <pcpsdefs.h>
+#include <use_pack.h>
+
+
+#ifdef _PCPSUTIL
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK )
+ #pragma pack( 1 ) // set byte alignment
+ #define _USING_BYTE_ALIGNMENT
+#endif
+
+
+// The following constants are used to draw a signal bar
+// depending on a DCF77 clock's signal value:
+#define PCPS_SIG_BIAS 55
+#define PCPS_SIG_ERR 1
+#define PCPS_SIG_MIN 20
+#define PCPS_SIG_MAX 68
+
+
+// the structure below is used with a DCF77 clock's serial interface
+typedef struct
+{
+ PCPS_SERIAL pack; // this byte is passed to the board as parameter
+
+ uint8_t baud; // the other bytes can hold the unpacked values
+ uint8_t frame;
+ uint8_t mode;
+
+} PCPS_SER_PACK;
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_exp_year()
+ *
+ * Purpose: Convert a 2-digit year number to a 4-digit
+ * year number. The resulting year number is in
+ * the range [year_lim ... ( year_lim + 99 )].
+ *
+ * Input: year the 2-digit year number
+ * year_lim the smallest 4-digit year number
+ * to be returned
+ *
+ * Output: --
+ *
+ * Ret value: the calculated 4-digit year num
+ *+-------------------------------------------------------------*/
+
+static __mbg_inline
+uint16_t pcps_exp_year( uint8_t year, uint16_t year_lim )
+{
+ uint16_t lyear = (uint16_t) ( (uint16_t) year + year_lim
+ - ( year_lim % 100 ) );
+
+ if ( lyear < year_lim )
+ lyear += 100;
+
+ return lyear;
+
+} // pcps_exp_year
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ int pcps_time_is_valid( const PCPS_TIME *p ) ;
+ void pcps_setup_isa_ports( char *s, int *port_vals, int n_vals ) ;
+ void pcps_unpack_serial( PCPS_SER_PACK *p ) ;
+ void pcps_pack_serial( PCPS_SER_PACK *p ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*--------------------------------------------------------------
+ * Name: frac_sec_from_bin()
+ *
+ * Purpose: Convert a fraction of a second from binary
+ * format (as returned in a PCPS_HR_TIME structure
+ * to a decimal fraction, using a specified scale
+ * factor. See also the definitions of
+ * PCPS_HRT_FRAC_SCALE and PCPS_HRT_FRAC_SCALE_FMT
+ * in the header file.
+ *
+ * Input: b the binary fraction
+ * scale the scale factor
+ *
+ * Output: --
+ *
+ * Ret value: the calculated number
+ *+-------------------------------------------------------------*/
+
+static __mbg_inline
+uint32_t frac_sec_from_bin( uint32_t b, uint32_t scale )
+{
+ return (uint32_t) ( (PCPS_HRT_FRAC_CONVERSION_TYPE) b * scale
+ / PCPS_HRT_BIN_FRAC_SCALE );
+
+} // frac_sec_from_bin
+
+
+
+static __mbg_inline
+double dfrac_sec_from_bin( uint32_t b )
+{
+ return (double) b / (double) PCPS_HRT_BIN_FRAC_SCALE;
+
+} // dfrac_sec_from_bin
+
+
+
+#if defined( _USING_BYTE_ALIGNMENT )
+ #pragma pack() // set default alignment
+ #undef _USING_BYTE_ALIGNMENT
+#endif
+
+/* End of header body */
+
+#undef _ext
+
+
+#endif /* _PCPSUTIL_H */
diff --git a/mbglib/common/toolutil.c b/mbglib/common/toolutil.c
new file mode 100644
index 0000000..3cdd2bb
--- /dev/null
+++ b/mbglib/common/toolutil.c
@@ -0,0 +1,530 @@
+
+/**************************************************************************
+ *
+ * $Id: toolutil.c 1.4.1.4 2013/02/05 15:27:30Z martin TEST $
+ *
+ * Description:
+ * Common functions which can be used with Meinberg command line
+ * utility programs.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: toolutil.c $
+ * Revision 1.4.1.4 2013/02/05 15:27:30Z martin
+ * Revision 1.4.1.3 2013/02/05 15:24:46 martin
+ * Revision 1.4.1.2 2013/02/05 14:39:38 martin
+ * Revision 1.4.1.1 2013/02/05 14:37:56Z martin
+ * Started to supported Windows target.
+ * Revision 1.4 2012/10/15 09:33:48 martin
+ * Use common way to handle version information.
+ * Open device with O_RDWR flag.
+ * Fixed printing delta timestamps.
+ * Added function to print PCPS_TIME.
+ * Added function to show PZF correlation.
+ * Added function mbg_print_hr_time() which optionally prints hex status.
+ * Let the display functions for HR timestamps optionally show
+ * the raw (hex) timestamps.
+ * Revision 1.3 2009/06/19 12:12:14 martin
+ * Added function mbg_print_hr_timestamp().
+ * Revision 1.2 2009/02/18 09:15:55 martin
+ * Support TAI and GPS time scales in mbg_snprint_hr_time().
+ * Revision 1.1 2008/12/17 10:45:13 martin
+ * Initial revision.
+ * Revision 1.1 2008/12/15 08:35:07 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#define _TOOLUTIL
+ #include <toolutil.h>
+#undef _TOOLUTIL
+
+// include Meinberg headers
+#include <pcpsutil.h>
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static __mbg_inline
+double delta_timestamps( const PCPS_TIME_STAMP *p_ts, const PCPS_TIME_STAMP *p_prv_ts )
+{
+ uint64_t ts = pcps_time_stamp_to_uint64( p_ts );
+ uint64_t prv_ts = pcps_time_stamp_to_uint64( p_prv_ts );
+ // we divide by PCPS_HRT_BIN_FRAC_SCALE to get the correct fractions
+ // and we multiply by 1E6 to get the result in microseconds
+ return (double) ( (int64_t) ( ts - prv_ts ) ) * 1E6 / PCPS_HRT_BIN_FRAC_SCALE;
+
+} // delta_timestamps
+
+
+
+/*HDR*/
+int mbg_program_info_str( char *s, size_t max_len, const char *pname,
+ int micro_version, int first_year, int last_year )
+{
+ int n;
+
+ if ( last_year == 0 )
+ last_year = MBG_CURRENT_COPYRIGHT_YEAR;
+
+ n = snprintf( s, max_len, "%s v%i.%i.%i copyright Meinberg ", pname,
+ MBG_MAJOR_VERSION_CODE, MBG_MINOR_VERSION_CODE, micro_version );
+
+ if ( first_year != last_year )
+ n += snprintf( &s[n], max_len - n, "%04i-", first_year );
+
+ n += snprintf( &s[n], max_len - n, "%04i", last_year );
+
+ return n;
+
+} // mbg_program_info_str
+
+
+
+/*HDR*/
+void mbg_print_program_info( const char *pname, int micro_version, int first_year, int last_year )
+{
+ char ws[256];
+ #if defined( MBG_MICRO_VERSION_CODE_DEV )
+ micro_version = MBG_MICRO_VERSION_CODE_DEV;
+ #endif
+ mbg_program_info_str( ws, sizeof( ws ), pname, micro_version, first_year, last_year );
+
+ printf( "\n%s\n\n", ws );
+
+} // mbg_print_program_info
+
+
+
+/*HDR*/
+void mbg_print_usage_intro( const char *pname, const char *info )
+{
+ printf( "Usage: %s [[opt] [opt] ...] [[dev] [dev] ...]\n\n", pname );
+
+ if ( info )
+ printf( "%s\n\n", info );
+
+
+} // mbg_print_usage_intro
+
+
+
+/*HDR*/
+void mbg_print_opt_info( const char *opt_name, const char *opt_info )
+{
+ if ( opt_name == NULL )
+ opt_name = "";
+
+ if ( opt_info == NULL )
+ opt_info = "";
+
+ printf( " %8s %s\n", opt_name, opt_info );
+
+} // mbg_print_opt_info
+
+
+
+/*HDR*/
+void mbg_print_help_options( void )
+{
+ puts( "where opt is one of the options:" );
+ mbg_print_opt_info( "-? or -h", "print this usage information" );
+
+} // mbg_print_help_options
+
+
+
+/*HDR*/
+void mbg_print_device_options( void )
+{
+ puts( "\nwhere dev is the name of a device, e.g.:\n"
+ " /dev/mbgclock0"
+ );
+
+} // mbg_print_device_options
+
+
+
+/*HDR*/
+void mbg_print_default_usage( const char *pname, const char *prog_info )
+{
+ mbg_print_usage_intro( pname, prog_info );
+ mbg_print_help_options();
+ mbg_print_device_options();
+ puts( "" );
+
+} // mbg_print_default_usage
+
+
+
+// test if ioctl error and print msg if true
+
+/*HDR*/
+int mbg_ioctl_err( int rc, const char *descr )
+{
+ if ( rc < 0 )
+ {
+ fprintf( stderr, "** IOCTL error %i: ", rc );
+ perror( descr );
+ return -1;
+ }
+
+ return 0;
+
+} // mbg_ioctl_err
+
+
+
+/*HDR*/
+int mbg_get_show_dev_info( MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_dev )
+{
+ unsigned long port;
+ int irq_num;
+ int ret_val = 0;
+ int rc;
+
+ if ( dev_name )
+ printf( "%s:\n", dev_name );
+
+ // get information about the device
+ rc = mbg_get_device_info( dh, p_dev );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_device_info" ) )
+ goto fail;
+
+
+ printf( "%s", _pcps_type_name( p_dev ) );
+
+ if ( strlen( _pcps_sernum( p_dev ) ) &&
+ strcmp( _pcps_sernum( p_dev ), "N/A" ) )
+ printf( " %s", _pcps_sernum( p_dev ) );
+
+ printf( " (FW %X.%02X",
+ _pcps_fw_rev_num_major( _pcps_fw_rev_num( p_dev ) ),
+ _pcps_fw_rev_num_minor( _pcps_fw_rev_num( p_dev ) )
+ );
+
+ if ( _pcps_has_asic_version( p_dev ) )
+ {
+ PCI_ASIC_VERSION av;
+ int rc = mbg_get_asic_version( dh, &av );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ av = _convert_asic_version_number( av );
+
+ printf( ", ASIC %u.%02u",
+ _pcps_asic_version_major( av ),
+ _pcps_asic_version_minor( av )
+ );
+ }
+ }
+
+ printf( ")" );
+
+ port = _pcps_port_base( p_dev, 0 );
+
+ if ( port )
+ printf( " at port 0x%03lX", port );
+
+ port = _pcps_port_base( p_dev, 1 );
+
+ if ( port )
+ printf( "/0x%03lX", port );
+
+ irq_num = _pcps_irq_num( p_dev );
+
+ if ( irq_num != -1 )
+ printf( ", irq %i", irq_num );
+
+ goto done;
+
+fail:
+ ret_val = -1;
+
+done:
+ puts( "" );
+ return ret_val;
+
+} // mbg_get_show_dev_info
+
+
+
+/*HDR*/
+int mbg_check_device( MBG_DEV_HANDLE dh, const char *dev_name,
+ int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) )
+{
+ PCPS_DEV dev;
+ int ret_val = 0;
+
+ if ( dh == MBG_INVALID_DEV_HANDLE )
+ {
+ if ( dev_name )
+ fprintf( stderr, "%s: ", dev_name );
+
+ perror( "Unable to open device" );
+ return -1;
+ }
+
+ if ( mbg_get_show_dev_info( dh, dev_name, &dev ) < 0 )
+ goto fail;
+
+ if ( fnc )
+ ret_val = fnc( dh, &dev );
+
+ goto done;
+
+fail:
+ ret_val = -1;
+
+done:
+ mbg_close_device( &dh );
+ puts( "" );
+
+ return ret_val;
+
+} // mbg_check_device
+
+
+
+/*HDR*/
+int mbg_check_devices( int argc, char *argv[], int optind, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) )
+{
+ MBG_DEV_HANDLE dh;
+ int ret_val = 0;
+ int num_devices = argc - optind;
+
+ if ( num_devices == 0 ) // no device name given on the command line
+ {
+ // No devices specified on the command line, so
+ // try to find devices.
+ int devices = mbg_find_devices();
+
+ if ( devices == 0 )
+ {
+ printf( "No device found.\n" );
+ return 1;
+ }
+
+ // Handle only first device found.
+ dh = mbg_open_device( 0 );
+ ret_val = mbg_check_device( dh, NULL, fnc );
+ }
+ else
+ {
+ int i;
+ // One or more device names have been specified
+ // on the command line, so handle each device.
+ for ( i = optind; i < argc; i++ )
+ {
+ // Print device name only if output for several devices
+ // shall be displayed.
+ const char *fn = ( num_devices > 1 ) ? argv[i] : NULL;
+
+ #if defined( MBG_TGT_WIN32 )
+ mbg_find_devices();
+ dh = mbg_open_device_by_name( argv[i], MBG_MATCH_MODEL );
+ #else
+ dh = open( argv[i], O_RDWR );
+ #endif
+ ret_val = mbg_check_device( dh, fn, fnc );
+
+ if ( ret_val )
+ break;
+ }
+ }
+
+ return ret_val;
+
+} // mbg_check_devices
+
+
+
+/*HDR*/
+int mbg_snprint_date_time( char *s, int len_s, const PCPS_TIME *p, int verbose )
+{
+ int n = 0;
+
+ n += snprintf( s + n, len_s - n, "%04u-%02u-%02u %02u:%02u:%02u.%02u",
+ pcps_exp_year( p->year, mbg_exp_year_limit ), p->month, p->mday,
+ p->hour, p->min, p->sec, p->sec100
+ );
+
+ if ( verbose )
+ n += snprintf( s + n, len_s - n, " (UTC%+ih), st: %02Xh",
+ p->offs_utc, p->status );
+
+ return n;
+
+} // mbg_snprint_date_time
+
+
+
+/*HDR*/
+int mbg_snprint_hr_tstamp( char *s, int len_s, const PCPS_TIME_STAMP *p, int show_raw )
+{
+ int n = 0;
+
+ // We'll use the standard C library functions to convert the seconds
+ // to broken-down calendar date and time.
+ time_t t = p->sec;
+
+ // Our time stamp may be UTC, or have been converted to local time.
+ // Anyway, since we don't want to account for the system's time zone
+ // settings, we always use the gmtime() function for conversion:
+ struct tm *tmp = gmtime( &t );
+
+ if ( show_raw )
+ n += snprintf( s + n, len_s - n, "raw: 0x%08lX.%08lX, ",
+ (ulong) p->sec,
+ (ulong) p->frac );
+
+ n += snprintf( s + n, len_s - n, "%04i-%02i-%02i %02i:%02i:%02i." PCPS_HRT_FRAC_SCALE_FMT,
+ tmp->tm_year + 1900,
+ tmp->tm_mon + 1,
+ tmp->tm_mday,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec,
+ (ulong) frac_sec_from_bin( p->frac, PCPS_HRT_FRAC_SCALE )
+ );
+
+ return n;
+
+} // mbg_snprint_hr_tstamp
+
+
+
+/*HDR*/
+int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p, int show_raw )
+{
+ char ws[80];
+ PCPS_TIME_STAMP ts = p->tstamp;
+ int n;
+ const char *time_scale_name;
+ const char *cp;
+
+ // If the local time offset is not 0 then add this to the time stamp
+ // and set up a string telling the offset.
+ if ( p->utc_offs )
+ {
+ ldiv_t ldt;
+
+ ts.sec += p->utc_offs;
+
+ // The local time offset is in seconds and may be negative, so we
+ // convert to absolute hours and minutes first.
+ ldt = ldiv( labs( p->utc_offs ) / 60, 60 );
+
+ snprintf( ws, sizeof( ws ), "%c%lu:%02luh",
+ ( p->utc_offs < 0 ) ? '-' : '+',
+ ldt.quot,
+ ldt.rem
+ );
+ cp = ws;
+ }
+ else
+ cp = ""; // no local time offset
+
+
+ // Convert the local time stamp to calendar date and time.
+ n = mbg_snprint_hr_tstamp( s, len_s, &ts, show_raw );
+
+ // By default the time stamp represents UTC plus an optional local time offset.
+ time_scale_name = "UTC";
+
+ // However, some cards may be configured to output TAI or GPS time.
+ if ( p->status & PCPS_SCALE_TAI )
+ time_scale_name = "TAI"; // time stamp represents TAI
+ else
+ if ( p->status & PCPS_SCALE_GPS )
+ time_scale_name = "GPS"; // time stamp represents GPS system time
+
+ n += snprintf( s + n, len_s - n, " %s%s", time_scale_name, cp );
+
+ return n;
+
+} // mbg_snprint_hr_time
+
+
+
+/*HDR*/
+void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts,
+ int no_latency, int show_raw )
+{
+ char ws[80];
+
+ mbg_snprint_hr_tstamp( ws, sizeof( ws ), p_ts, show_raw );
+ printf( "HR time %s", ws );
+
+ if ( p_prv_ts )
+ printf( " (%+.1f us)", delta_timestamps( p_ts, p_prv_ts ) );
+
+ if ( !no_latency )
+ printf( ", latency: %.1f us", ( (double) hns_latency ) / 10 );
+
+ puts( "" );
+
+} // mbg_print_hr_timestamp
+
+
+
+/*HDR*/
+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 )
+{
+ char ws[80];
+
+ mbg_snprint_hr_time( ws, sizeof( ws ), p_ht, show_raw );
+ printf( "HR time %s", ws );
+
+ if ( p_prv_ts )
+ printf( " (%+.1f us)", delta_timestamps( &p_ht->tstamp, p_prv_ts ) );
+
+ if ( !no_latency )
+ printf( ", latency: %.1f us", ( (double) hns_latency ) / 10 );
+
+ if ( verbose )
+ printf( ", st: 0x%04lX", (ulong) p_ht->status );
+
+ puts( "" );
+
+} // mbg_print_hr_time
+
+
+
+/*HDR*/
+int mbg_show_pzf_corr_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, int show_corr_step )
+{
+ CORR_INFO ci;
+ char ws[80];
+ const char *cp;
+
+ int rc = mbg_get_corr_info( dh, &ci );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_corr_info" ) )
+ return rc;
+
+
+ if ( ci.status < N_PZF_CORR_STATE )
+ cp = pzf_corr_state_name[ci.status];
+ else
+ {
+ snprintf( ws, sizeof( ws ) - 1, "(unknown, code: 0x%02X)", ci.status );
+ ws[sizeof( ws ) - 1] = 0; // force terminating 0
+ cp = ws;
+ }
+
+ printf( "PZF correlation: %u%%, status: %s", ci.val, cp );
+
+ if ( show_corr_step )
+ if ( ci.corr_dir != ' ' )
+ printf( " Shift: %c", ci.corr_dir );
+
+ return MBG_SUCCESS;
+
+} // mbg_show_pzf_corr_info
+
+
diff --git a/mbglib/common/toolutil.h b/mbglib/common/toolutil.h
new file mode 100644
index 0000000..2f02c73
--- /dev/null
+++ b/mbglib/common/toolutil.h
@@ -0,0 +1,128 @@
+
+/**************************************************************************
+ *
+ * $Id: toolutil.h 1.3.1.1 2013/02/05 14:38:26Z martin TEST martin $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for toolutil.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: toolutil.h $
+ * Revision 1.3.1.1 2013/02/05 14:38:26Z martin
+ * Started to support Windows target.
+ * Revision 1.3 2012/10/15 09:36:22 martin
+ * Use common way to handle version information.
+ * Added string table with PZF state names.
+ * Updated function prototypes.
+ * Revision 1.2 2009/06/19 12:11:35 martin
+ * Updated function prototypes.
+ * Revision 1.1 2008/12/17 10:45:14 martin
+ * Initial revision.
+ * Revision 1.1 2008/12/15 08:35:08 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _TOOLUTIL_H
+#define _TOOLUTIL_H
+
+
+/* Other headers to be included */
+
+#include <mbgdevio.h>
+#include <mbgversion.h>
+
+#if defined( MBG_TGT_UNIX)
+
+ #include <unistd.h>
+
+#elif defined( MBG_TGT_WIN32 )
+
+ #include <io.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <wingetopt.h>
+
+ #define open _open
+ #define snprintf _snprintf
+ #define sleep( _x ) Sleep( (_x) * 1000 )
+ #define usleep( _x ) Sleep( (_x) / 1000 )
+
+#endif
+
+
+
+#ifdef _TOOLUTIL
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined( MBG_EXP_YEAR_LIMIT )
+ #define MBG_EXP_YEAR_LIMIT 1980
+#endif
+
+_ext uint16_t mbg_exp_year_limit
+#ifdef _DO_INIT
+ = MBG_EXP_YEAR_LIMIT
+#endif
+;
+
+_ext int must_print_usage;
+
+_ext const char *pzf_corr_state_name[N_PZF_CORR_STATE]
+#ifdef _DO_INIT
+ = PZF_CORR_STATE_NAMES_ENG
+#endif
+;
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ int mbg_program_info_str( char *s, size_t max_len, const char *pname, int micro_version, int first_year, int last_year ) ;
+ void mbg_print_program_info( const char *pname, int micro_version, int first_year, int last_year ) ;
+ void mbg_print_usage_intro( const char *pname, const char *info ) ;
+ void mbg_print_opt_info( const char *opt_name, const char *opt_info ) ;
+ void mbg_print_help_options( void ) ;
+ void mbg_print_device_options( void ) ;
+ void mbg_print_default_usage( const char *pname, const char *prog_info ) ;
+ int mbg_ioctl_err( int rc, const char *descr ) ;
+ int mbg_get_show_dev_info( MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_dev ) ;
+ int mbg_check_device( MBG_DEV_HANDLE dh, const char *dev_name, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) ) ;
+ int mbg_check_devices( int argc, char *argv[], int optind, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) ) ;
+ int mbg_snprint_date_time( char *s, int len_s, const PCPS_TIME *p, int verbose ) ;
+ int mbg_snprint_hr_tstamp( char *s, int len_s, const PCPS_TIME_STAMP *p, int show_raw ) ;
+ int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p, int show_raw ) ;
+ void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int no_latency, int show_raw ) ;
+ 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 ) ;
+ int mbg_show_pzf_corr_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, int show_corr_step ) ;
+
+/* ----- function prototypes end ----- */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _TOOLUTIL_H */
+
diff --git a/mbglib/common/usbdefs.h b/mbglib/common/usbdefs.h
new file mode 100644
index 0000000..40d1193
--- /dev/null
+++ b/mbglib/common/usbdefs.h
@@ -0,0 +1,151 @@
+
+/**************************************************************************
+ *
+ * $Id: usbdefs.h 1.18 2013/01/24 11:29:21Z joerg REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions used with USB devices.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: usbdefs.h $
+ * Revision 1.18 2013/01/24 11:29:21Z joerg
+ * Added class code and device ID for LNE-GB
+ * Revision 1.17 2012/08/08 07:53:29Z daniel
+ * Added class code and device ID for LIU
+ * Revision 1.16 2012/02/13 09:29:59 paul
+ * added class code for LNO180
+ * Revision 1.15 2011/10/11 06:21:04Z andre
+ * added class code for GPS180
+ * Revision 1.14 2011/10/07 10:13:25Z daniel
+ * New class code and device id for CPE
+ * Revision 1.13 2011/06/29 14:11:23Z martin
+ * Added device IDs for TCR600USB, MSF600USB, and WVB600USB.
+ * Revision 1.12 2011/05/11 07:20:37 daniel
+ * New class code and device id for fan control unit
+ * Revision 1.11 2011/04/13 07:59:11 daniel
+ * New class code and device id for external
+ * synchronization interface device.
+ * Revision 1.10 2010/11/11 09:16:33Z martin
+ * Added device ID for DCF600USB.
+ * Revision 1.9 2009/03/13 09:02:24 martin
+ * Removed definitions for timeout intervals.
+ * Revision 1.8 2009/02/18 11:08:44 daniel
+ * Added new class code and device ID for SCU_USB
+ * Revision 1.7 2008/11/28 07:45:30Z daniel
+ * Added new class code and device ID for WWVB51USB
+ * Revision 1.6 2008/01/09 10:39:18Z daniel
+ * Added new class code and device ID for MSF51USB
+ * Revision 1.5 2007/10/29 08:23:26Z daniel
+ * Added new class code and device ID for TCR51USB
+ * Revision 1.4 2007/09/25 09:59:50Z daniel
+ * Added indices for endpoint definitions.
+ * Added timeout definitions.
+ * Revision 1.3 2006/12/20 16:11:36Z daniel
+ * Added new device class and device_id for nCipher CMC-device.
+ * Revision 1.2 2006/12/07 09:10:57Z daniel
+ * Added new class code and device ID for USB5131.
+ * Revision 1.1 2006/04/21 08:14:56Z martin
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _USBDEFS_H
+#define _USBDEFS_H
+
+
+/* Other headers to be included */
+
+
+/* Start of header body */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Meinberg's USB vendor ID number (assigned by USB-IF Administration) */
+#define USB_VENDOR_MEINBERG 0x1938
+
+
+/*
+ * USB device class codes (assigned by Meinberg)
+ */
+enum
+{
+ MBG_USB_CLASS_NONE, // (unknown or not defined)
+ MBG_USB_CLASS_CPC, // Control Panel Controller
+ MBG_USB_CLASS_TSU, // Time Stamp Unit
+ MBG_USB_CLASS_DCF, // DCF77 Radio Clock
+ MBG_USB_CLASS_CMC, // nCipher Crypto Module Carrier
+ MBG_USB_CLASS_TCR, // IRIG Time Code Receiver
+ MBG_USB_CLASS_MSF, // MSF Radio Clock
+ MBG_USB_CLASS_WWVB, // WWVB Radio Clock
+ MBG_USB_CLASS_SCU, // Meinberg Signal Changeover Unit
+ MBG_USB_CLASS_ESI, // External Synchronization Interface
+ MBG_USB_CLASS_FCU, // Fan Control Unit
+ MBG_USB_CLASS_CPE, // Configurable Port Expander
+ MBG_USB_CLASS_GPS, // GPS Receiver
+ MBG_USB_CLASS_LNO, // Low Phase Noise Option
+ MBG_USB_CLASS_LIU, // Line Interface Unit
+ MBG_USB_CLASS_LNE, // LNE-GB
+ N_MBG_USB_CLASS // number of known device class codes
+};
+
+
+/*
+ * USB device ID numbers (assigned by Meinberg)
+ * High byte: USB device class as specified above
+ * Low byte: enumeration of device of a class
+ */
+#define USB_DEV_CPC_01 ( ( MBG_USB_CLASS_CPC << 8 ) | 0x01 )
+
+#define USB_DEV_TSU_01 ( ( MBG_USB_CLASS_TSU << 8 ) | 0x01 )
+
+#define USB_DEV_USB5131 ( ( MBG_USB_CLASS_DCF << 8 ) | 0x01 )
+#define USB_DEV_DCF600USB ( ( MBG_USB_CLASS_DCF << 8 ) | 0x02 )
+
+#define USB_DEV_CMC ( ( MBG_USB_CLASS_CMC << 8 ) | 0x01 )
+
+#define USB_DEV_TCR51USB ( ( MBG_USB_CLASS_TCR << 8 ) | 0x01 )
+#define USB_DEV_TCR600USB ( ( MBG_USB_CLASS_TCR << 8 ) | 0x02 )
+
+#define USB_DEV_MSF51USB ( ( MBG_USB_CLASS_MSF << 8 ) | 0x01 )
+#define USB_DEV_MSF600USB ( ( MBG_USB_CLASS_MSF << 8 ) | 0x02 )
+
+#define USB_DEV_WWVB51USB ( ( MBG_USB_CLASS_WWVB << 8 ) | 0x01 )
+#define USB_DEV_WVB600USB ( ( MBG_USB_CLASS_WWVB << 8 ) | 0x02 )
+
+#define USB_DEV_SCU_USB ( ( MBG_USB_CLASS_SCU << 8 ) | 0x01 )
+
+#define USB_DEV_ESI_01 ( ( MBG_USB_CLASS_ESI << 8 ) | 0x01 )
+
+#define USB_DEV_FCU_01 ( ( MBG_USB_CLASS_FCU << 8 ) | 0x01 )
+
+#define USB_DEV_CPE_01 ( ( MBG_USB_CLASS_CPE << 8 ) | 0x01 )
+
+#define USB_DEV_GPS180 ( ( MBG_USB_CLASS_GPS << 8 ) | 0x01 )
+
+#define USB_DEV_LNO180_01 ( ( MBG_USB_CLASS_LNO << 8 ) | 0x01 )
+
+#define USB_DEV_LIU_01 ( ( MBG_USB_CLASS_LIU << 8 ) | 0x01 )
+
+#define USB_DEV_LNE_01 ( ( MBG_USB_CLASS_LNE << 8 ) | 0x01 )
+
+enum
+{
+ MBGUSB_EP_IDX_HOST_IN, // transfers from device to host
+ MBGUSB_EP_IDX_HOST_OUT, // transfers from host to device
+ MBGUSB_EP_IDX_HOST_IN_CYCLIC, // cyclic auto-transfer to host
+ MBGUSB_MAX_ENDPOINTS // max number of supported endpoints
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of header body */
+
+#endif /* _USBDEFS_H */
diff --git a/mbglib/common/use_pack.h b/mbglib/common/use_pack.h
new file mode 100644
index 0000000..cef3d97
--- /dev/null
+++ b/mbglib/common/use_pack.h
@@ -0,0 +1,43 @@
+
+/**************************************************************************
+ *
+ * $Id: use_pack.h 1.5 2012/10/12 12:40:01Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Check the current compiler type to decide if pragma pack() is
+ * required to pack cross-platform data structures.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: use_pack.h $
+ * Revision 1.5 2012/10/12 12:40:01Z martin
+ * Removed temporary changes.
+ * Revision 1.4 2012/10/02 18:06:25 martin
+ * Temporary changes to test alignment under Linux/Sparc.
+ * Revision 1.3 2011/01/26 10:01:41 martin
+ * Provided a way to suppress packing of structures on a project base.
+ * Revision 1.2 2002/02/25 08:50:33 Andre
+ * query __ARM added, __SH2 removed
+ * Revision 1.1 2001/03/30 08:54:33Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _USE_PACK_H
+#define _USE_PACK_H
+
+#if ( !defined( _C166 ) && \
+ !defined( _CC51 ) && \
+ !defined( __ARM ) )
+
+ // _NO_USE_PACK can be defined for specific projects
+ // to avoid packing of structures.
+ #if ( !defined( _NO_USE_PACK ) )
+ #define _USE_PACK
+ #endif
+
+#endif
+
+#endif /* _USE_PACK_H */
+
diff --git a/mbglib/common/words.h b/mbglib/common/words.h
new file mode 100644
index 0000000..b840491
--- /dev/null
+++ b/mbglib/common/words.h
@@ -0,0 +1,360 @@
+
+/**************************************************************************
+ *
+ * $Id: words.h 1.31 2012/11/29 11:54:39Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions of commonly used data types.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: words.h $
+ * Revision 1.31 2012/11/29 11:54:39Z martin
+ * Removed #if sizeof() definitions which may cause build errors
+ * with some older compilers.
+ * Include stdbool.h for __ARMCC_VERSION targets.
+ * Moved _nop_macro_fnc() definition here.
+ * Revision 1.30 2012/11/02 09:12:29Z martin
+ * Moved most feature detection code to mbg_tgt.h.
+ * Tried to define missing features most flexibly and portably.
+ * Revision 1.29 2012/07/11 16:45:45Z martin
+ * New macros to access individual bytes of long constants.
+ * Revision 1.28 2012/04/05 14:36:18Z martin
+ * Support CVI 2010 compiler which provides C99 types.
+ * Revision 1.27 2011/07/18 10:21:38Z martin
+ * Added definition for MBG_CODE_NAME_TABLE_ENTRY which can
+ * be used to define tables assigning strings to numeric codes.
+ * Revision 1.26 2011/04/06 10:23:03 martin
+ * Added FBYTE_OF() and FWORD_OF() macros.
+ * Modifications required for *BSD.
+ * Revision 1.25 2010/11/17 10:23:09 martin
+ * Define _BIT_REDEFINED if bit type is redefined.
+ * Revision 1.24 2010/11/17 08:44:56Z martin
+ * If supported, use type "bool" to implement "bit".
+ * Revision 1.23 2010/05/27 08:54:30Z martin
+ * Support fixed size data types with Keil RealView compiler for ARM.
+ * Keil RealView ARM targets are always considered as firmware.
+ * Revision 1.22 2009/10/21 07:53:55 martin
+ * Undid changes introduced in 1.21 since they were not consistent
+ * across glibc and/or Linux kernel header versions.
+ * Revision 1.21 2009/10/01 14:00:17 martin
+ * Conditionally define ulong and friends also for Linux/glibc.
+ * Revision 1.20 2009/07/02 15:38:12 martin
+ * Added new macro _wswap32().
+ * Revision 1.19 2009/04/14 14:45:45Z martin
+ * Added BYTE_OF_P() and WORD_OF_P() macros.
+ * Revision 1.18 2009/03/27 14:05:18 martin
+ * Cleanup for CVI.
+ * Revision 1.17 2009/03/13 09:06:03Z martin
+ * Declared bit type for non-firmware environments.
+ * Revision 1.16 2008/12/05 12:05:41Z martin
+ * Define dummy int64_t/uint64_t types for targets
+ * which don't support 64 bit data types.
+ * Revision 1.15 2008/07/14 14:44:00Z martin
+ * Use fixed size C99 types which come with GCC and newer Borland compilers.
+ * Revision 1.14 2008/01/30 10:27:50Z martin
+ * Moved some macro definitions here.
+ * Revision 1.13 2007/03/08 15:00:30Z martin
+ * Fixed incompatibility of macro _IS_MBG_FIRMWARE.
+ * Added a workaround for _IS_MBG_FIRMWARE under CVI.
+ * Support for BSD.
+ * Revision 1.12 2006/12/15 10:45:46 martin
+ * Added macro _IS_MBG_FIRMWARE.
+ * Cleanup for Linux, QNX, and Watcom C.
+ * Include mbg_tgt.h for non-firmware targets.
+ * Revision 1.11 2004/11/10 10:45:34 martin
+ * Added C99 fixed-type handling for QNX.
+ * Revision 1.10 2004/11/09 13:12:56 martin
+ * Redefined C99 integer types with fixed sizes as standard types
+ * if required, depending on the environment.
+ * Revision 1.9 2003/02/07 11:36:54 MARTIN
+ * New macros _hilo_16() and _hilo_32() for endian conversion.
+ * Revision 1.8 2002/05/28 10:09:54 MARTIN
+ * Added new macros _var_bswap16() and _var_bswap32().
+ * Revision 1.7 2001/03/14 11:30:48 MARTIN
+ * Removed definitions for UINT8, UINT16, UINT32.
+ * Redefined preprocessor control for Win32.
+ * Revision 1.6 2001/02/28 15:43:20 MARTIN
+ * Modified preprocessor syntax.
+ * Revision 1.5 2001/02/05 10:20:53 MARTIN
+ * Include different Linux types for user space and kernel space programs.
+ * Source code cleanup.
+ * Revision 1.4 2000/09/15 08:34:11 MARTIN
+ * Exclude some definitions if compiling under Win NT.
+ * Revision 1.3 2000/08/22 15:04:28 MARTIN
+ * Added new file header.
+ * Added macros to revert endianess of 16 and 32 bit values.
+ *
+ **************************************************************************/
+
+#ifndef _WORDS_H
+#define _WORDS_H
+
+
+/* Other headers to be included */
+
+
+#if !defined( _IS_MBG_FIRMWARE )
+
+ #if defined( _C166 ) || \
+ defined( _CC51 ) || \
+ defined( __ARM ) || \
+ defined( __ARMCC_VERSION )
+ #define _IS_MBG_FIRMWARE 1
+ #else
+ #define _IS_MBG_FIRMWARE 0
+ #endif
+
+#endif
+
+
+#if !_IS_MBG_FIRMWARE
+ #include <mbg_tgt.h>
+#else
+ #if defined( __ARMCC_VERSION ) // Keil RealView Compiler for ARM
+ #include <stdint.h>
+ #include <stdbool.h>
+ #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1
+ #else
+ #define MBG_TGT_MISSING_64_BIT_TYPES 1
+ #endif
+#endif
+
+
+
+#ifdef _WORDS
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _C166 ) \
+ || defined( _CC51 )
+ #define _BIT_DEFINED 1 // these compilers natively support the "bit" type
+ #define USE_LONG_FOR_INT32 1
+#endif
+
+
+
+#if !defined( MBG_TGT_HAS_EXACT_SIZE_TYPES )
+
+ #if defined( MBG_TGT_HAS_INT_8_16_32 )
+
+ // Define C99 exact size types using non-standard exact-size types
+ typedef __int8 int8_t;
+ typedef unsigned __int8 uint8_t;
+
+ typedef __int16 int16_t;
+ typedef unsigned __int16 uint16_t;
+
+ typedef __int32 int32_t;
+ typedef unsigned __int32 uint32_t;
+
+ #else
+
+ // Assume a 16 or 32 bit compiler which doesn't
+ // support exact-size types.
+
+ typedef char int8_t;
+ typedef unsigned char uint8_t;
+
+ typedef short int16_t;
+ typedef unsigned short uint16_t;
+
+ // Using #if sizeof() to determine the size of a type may not
+ // be supported by all preprocessors, and may even result in
+ // build errors if used in a conditional preprocessor section,
+ // so we can't use this here without compatibility problems.
+
+ #if defined( USE_LONG_FOR_INT32 )
+ typedef long int32_t;
+ typedef unsigned long uint32_t;
+ #elif defined( USE_INT_FOR_INT32 )
+ typedef int int32_t;
+ typedef unsigned int uint32_t;
+ #else
+ #error Need to define int32_t and uint32_t
+ #endif
+
+ #endif
+
+ #if defined( MBG_TGT_MISSING_64_BIT_TYPES )
+
+ // The build environment does not support 64 bit types. However,
+ // 64 bit types need to be defined to avoid build errors
+ // if these types are formally used in function prototypes.
+ // We explicitely use abnormal data types to hopefully
+ // cause compiler errors in case these types are
+ // unexpectedly used to generate real code for a target
+ // platform which does not support 64 bit types.
+ typedef void *int64_t;
+ typedef void *uint64_t;
+
+ #else
+
+ // Define C99 types using non-standard exact-size types
+ // which are usually supported by build envonronments
+ // supporting 64 bit types but no C99 types.
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+
+ #endif
+
+#endif
+
+
+
+#if defined( MBG_TGT_MISSING_64_BIT_TYPES )
+
+ #define MBG_TGT_HAS_64BIT_TYPES 0
+
+#else
+
+ #define MBG_TGT_HAS_64BIT_TYPES 1
+
+#endif
+
+
+
+// Some commonly used types
+
+typedef unsigned char uchar;
+
+#if !defined( MBG_TGT_LINUX ) \
+ && !( defined ( MBG_TGT_NETBSD ) \
+ && defined ( MBG_TGT_KERNEL ) )
+ typedef unsigned short ushort;
+ typedef unsigned int uint;
+ typedef unsigned long ulong;
+#endif
+
+typedef double udouble;
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long longword;
+typedef unsigned long dword;
+
+
+#if !defined( _BIT_DEFINED )
+
+ // We need to implement a "bit" type. Preferably we use "bool"
+ // to do this, but this is only supported by C++ compilers, and
+ // by C compilers supporting the C99 standard.
+
+ #if !defined( MBG_TGT_MISSING_BOOL_TYPE ) && \
+ ( defined( __cplusplus ) || defined( __bool_true_false_are_defined ) )
+
+ typedef bool bit;
+
+ #else // C99 types not supported
+
+ // Falling back to use "int" for "bit". This prevents error
+ // messages if "bit" is used in function prototypes, but may
+ // yield unexpected results for code like:
+ // return (bit) ( val & 0x10 );
+ typedef int bit;
+
+ #endif
+
+ #define _BIT_REDEFINED 1
+
+#endif
+
+
+#define BYTE_0( _x ) ( ( (ulong) (_x) ) & 0xFF )
+#define BYTE_1( _x ) ( ( ( (ulong) (_x) ) >> 8 ) & 0xFF )
+#define BYTE_2( _x ) ( ( ( (ulong) (_x) ) >> 16 ) & 0xFF )
+#define BYTE_3( _x ) ( ( ( (ulong) (_x) ) >> 24 ) & 0xFF )
+
+
+#define HI_BYTE( _x ) ( (_x) >> 8 )
+#define LO_BYTE( _x ) ( (_x) & 0xFF )
+
+#define HI_WORD( _x ) ( (_x) >> 16 )
+#define LO_WORD( _x ) ( (_x) & 0xFFFF )
+
+// the macros below assume little endianess
+// these macros expect the name of a variable
+#define BYTE_OF( _v, _n ) *( ( (uint8_t *) &(_v) ) + (_n) )
+#define WORD_OF( _v, _n ) *( ( (uint16_t *) &(_v) ) + (_n) )
+
+#define FBYTE_OF( _v, _n ) *( ( (uint8_t far *) &(_v) ) + (_n) )
+#define FWORD_OF( _v, _n ) *( ( (uint16_t far *) &(_v) ) + (_n) )
+
+// same as above, but taking pointers
+#define BYTE_OF_P( _p, _n ) *( ( (uint8_t *) (_p) ) + (_n) )
+#define WORD_OF_P( _p, _n ) *( ( (uint16_t *) (_p) ) + (_n) )
+
+
+// a macro to swap the byte order of a 16 bit value
+#define _bswap16( _x ) \
+( \
+ ( ( ( (uint16_t) (_x) ) & 0x00FF ) << 8 ) | \
+ ( ( ( (uint16_t) (_x) ) & 0xFF00 ) >> 8 ) \
+)
+
+// a macro to swap the byte order of a 32 bit value
+#define _bswap32( _x ) \
+( \
+ ( ( ( (uint32_t) (_x) ) & 0x000000FFUL ) << 24 ) | \
+ ( ( ( (uint32_t) (_x) ) & 0x0000FF00UL ) << 8 ) | \
+ ( ( ( (uint32_t) (_x) ) & 0x00FF0000UL ) >> 8 ) | \
+ ( ( ( (uint32_t) (_x) ) & 0xFF000000UL ) >> 24 ) \
+)
+
+// a macro to swap the word order of a 32 bit value
+#define _wswap32( _x ) \
+( \
+ ( ( ( (uint32_t) (_x) ) & 0x0000FFFFUL ) << 16 ) | \
+ ( ( ( (uint32_t) (_x) ) >> 16 ) & 0x0000FFFFUL ) \
+)
+
+#define _var_bswap16( _v ) (_v) = _bswap16( _v )
+#define _var_bswap32( _v ) (_v) = _bswap32( _v )
+
+
+// The C51 compiler is big-endian, that means the most
+// significant byte of a 16 or 32 bit value is stored in
+// the lowest memory location. Most other systems are
+// little-endian, so we must use macros to adjust the
+// byte order if the C51 is used.
+
+#if defined( _CC51 )
+ #define _hilo_16( _x ) _bswap16( _x )
+ #define _hilo_32( _x ) _bswap32( _x )
+#else
+ #define _hilo_16( _x ) (_x)
+ #define _hilo_32( _x ) (_x)
+#endif
+
+
+// A macro function which can safely be used without
+// side effects as a macro doing nothing.
+// This is useful to define debug macros away in
+// release builds, etc.
+#if !defined( _nop_macro_fnc )
+ #define _nop_macro_fnc() do {} while (0)
+#endif
+
+
+/**
+ * @brief A table entry which can be used to map codes to names.
+ */
+typedef struct
+{
+ ulong code;
+ const char *name;
+} MBG_CODE_NAME_TABLE_ENTRY;
+
+
+
+/* End of header body */
+
+#undef _ext
+
+#endif /* _WORDS_H */
diff --git a/mbglib/lib/bc/mbgdevio.lib b/mbglib/lib/bc/mbgdevio.lib
new file mode 100644
index 0000000..e45f718
--- /dev/null
+++ b/mbglib/lib/bc/mbgdevio.lib
Binary files differ
diff --git a/mbglib/lib/bc/mbgsvcio.lib b/mbglib/lib/bc/mbgsvcio.lib
new file mode 100644
index 0000000..86b966f
--- /dev/null
+++ b/mbglib/lib/bc/mbgsvcio.lib
Binary files differ
diff --git a/mbglib/lib/bc/mbgsvctl.lib b/mbglib/lib/bc/mbgsvctl.lib
new file mode 100644
index 0000000..b4a0210
--- /dev/null
+++ b/mbglib/lib/bc/mbgsvctl.lib
Binary files differ
diff --git a/mbglib/lib/bc/mbgutil.lib b/mbglib/lib/bc/mbgutil.lib
new file mode 100644
index 0000000..d24e46b
--- /dev/null
+++ b/mbglib/lib/bc/mbgutil.lib
Binary files differ
diff --git a/mbglib/lib/msc/mbgdevio.lib b/mbglib/lib/msc/mbgdevio.lib
new file mode 100644
index 0000000..d273251
--- /dev/null
+++ b/mbglib/lib/msc/mbgdevio.lib
Binary files differ
diff --git a/mbglib/lib/msc/mbgsvcio.lib b/mbglib/lib/msc/mbgsvcio.lib
new file mode 100644
index 0000000..c4987be
--- /dev/null
+++ b/mbglib/lib/msc/mbgsvcio.lib
Binary files differ
diff --git a/mbglib/lib/msc/mbgsvctl.lib b/mbglib/lib/msc/mbgsvctl.lib
new file mode 100644
index 0000000..0a2f61d
--- /dev/null
+++ b/mbglib/lib/msc/mbgsvctl.lib
Binary files differ
diff --git a/mbglib/lib/msc/mbgutil.lib b/mbglib/lib/msc/mbgutil.lib
new file mode 100644
index 0000000..fe570bc
--- /dev/null
+++ b/mbglib/lib/msc/mbgutil.lib
Binary files differ
diff --git a/mbglib/lib64/msc/mbgdevio.lib b/mbglib/lib64/msc/mbgdevio.lib
new file mode 100644
index 0000000..8e443b7
--- /dev/null
+++ b/mbglib/lib64/msc/mbgdevio.lib
Binary files differ
diff --git a/mbglib/lib64/msc/mbgsvcio.lib b/mbglib/lib64/msc/mbgsvcio.lib
new file mode 100644
index 0000000..e9c4cd6
--- /dev/null
+++ b/mbglib/lib64/msc/mbgsvcio.lib
Binary files differ
diff --git a/mbglib/lib64/msc/mbgsvctl.lib b/mbglib/lib64/msc/mbgsvctl.lib
new file mode 100644
index 0000000..538e203
--- /dev/null
+++ b/mbglib/lib64/msc/mbgsvctl.lib
Binary files differ
diff --git a/mbglib/lib64/msc/mbgutil.lib b/mbglib/lib64/msc/mbgutil.lib
new file mode 100644
index 0000000..82ea1e1
--- /dev/null
+++ b/mbglib/lib64/msc/mbgutil.lib
Binary files differ
diff --git a/mbglib/win32/mbg_w32.h b/mbglib/win32/mbg_w32.h
new file mode 100644
index 0000000..ebdc119
--- /dev/null
+++ b/mbglib/win32/mbg_w32.h
@@ -0,0 +1,309 @@
+
+/**************************************************************************
+ *
+ * $Id: mbg_w32.h 1.7 2012/05/30 13:28:43Z martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * OS dependend definitions/redefinitions for Win32.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbg_w32.h $
+ * Revision 1.7 2012/05/30 13:28:43Z martin
+ * Cleanup.
+ * Revision 1.6 2012/05/29 14:39:53Z martin
+ * Runtime support for precise time API introduced with Windows 8.
+ * Revision 1.5 2009/03/26 08:32:26Z martin
+ * Added orgDeviceExtension field for non-PNP driver.
+ * Revision 1.4 2009/01/13 14:45:17Z martin
+ * Added PCPS_DDEV::RegistryPath field for non-PnP driver.
+ * Use PCPS_DDEV::irp and PCPS_DDEV::win32DeviceName also for non-PnP driver.
+ * Added PCPS_DDEV::DriverObject field.
+ * Conditionally added PCPS_DDEV fields required to support programmable IRQs.
+ * Revision 1.3 2007/09/27 10:36:25Z martin
+ * Added macro specifying Windows specific device data.
+ * Added USB support.
+ * Renamed Removed to SurpriseRemoved.
+ * Revision 1.2 2002/01/24 09:48:05Z Udo
+ * check in as lib module
+ * Revision 1.1 2001/09/13 07:12:14Z Udo
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _MBG_W32_H
+#define _MBG_W32_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+#include <words.h>
+
+#if defined( MBG_TGT_WIN32_PNP ) && defined( MBG_TGT_KERNEL )
+ #include <usb100.h>
+ #include <usbdi.h>
+ #include <usbdlib.h>
+#endif
+
+
+#ifdef _MBG_W32
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if USE_PGMB_IRQ
+
+ typedef struct
+ {
+ struct _KINTERRUPT *Object;
+ KEVENT *Event;
+ KSPIN_LOCK Spinlock;
+ KDPC *Dpc;
+ } MBG_IRQ_INFO;
+
+ #define _pgmb_irq_vars \
+ MBG_IRQ_INFO Irq;
+
+#else
+
+ #define _pgmb_irq_vars
+
+#endif
+
+
+
+/**
+ * @brief A pointer to a function returning the system time as LARGE_INTEGER.
+ *
+ * This is for kernel mode only. The function can be e.g. the standard Windows
+ * API call KeQuerySystemTime() or the KeQuerySystemTimePrecise() API
+ * call introduced with Windows 8.
+ */
+typedef VOID (*KE_QUERY_SYSTEM_TIME_FNC)(PLARGE_INTEGER CurrentTime);
+
+
+
+#if defined( MBG_TGT_KERNEL )
+
+#if !defined( NTKERNELAPI )
+ #define NTKERNELAPI
+#endif
+
+#if !defined( __in )
+ #define __in
+#endif
+
+#if !defined( _Out_ )
+ #define _Out_
+#endif
+
+
+#if 0 //##++
+ #define _x_evt_msg _evt_msg
+#else
+ #define _x_evt_msg _dbg_evt_msg
+#endif
+
+
+
+// definitions for clock() support in kernel drivers
+
+#define clock_t ulong
+
+#define clock w32_clock
+
+// KeQueryTimeIncrement() returns number of 100nsec increments per tick.
+// There are 10000000 100nsec increments per second.
+#define MBG_TICKS_PER_SEC ( 10000000 / KeQueryTimeIncrement() )
+
+
+/**
+ * @brief Get precise Windows system time as FILETIME.
+ *
+ * @note This function has been introduced with Windows 8,
+ * so it is not available on older Windows versions. Thus
+ * the API call is imported from ntoskrnl.exe at runtime.
+ *
+ * @param CurrentTime pointer to a LARGE_INTEGER to be filled
+ *
+ * @see KE_QUERY_SYSTEM_TIME_FNC
+ * @see import_kernel_precise_time_api()
+ */
+NTKERNELAPI
+VOID
+KeQuerySystemTimePrecise( _Out_ PLARGE_INTEGER CurrentTime);
+
+
+
+#if defined( MBG_TGT_WIN32_PNP )
+
+ #if !defined ( SE_CREATE_SYMBOLIC_LINK_PRIVILEGE )
+
+ // Define some KDD function types which may not be
+ // defined in older DDK headers.
+
+ typedef
+ NTSTATUS
+ IO_COMPLETION_ROUTINE (
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Context
+ );
+
+ typedef IO_COMPLETION_ROUTINE *PIO_COMPLETION_ROUTINE;
+
+
+ typedef
+ NTSTATUS
+ DRIVER_DISPATCH (
+ __in struct _DEVICE_OBJECT *DeviceObject,
+ __in struct _IRP *Irp
+ );
+
+ typedef DRIVER_DISPATCH *PDRIVER_DISPATCH;
+
+
+ typedef
+ VOID
+ DRIVER_UNLOAD (
+ __in struct _DRIVER_OBJECT *DriverObject
+ );
+
+ typedef DRIVER_UNLOAD *PDRIVER_UNLOAD;
+
+
+ typedef
+ NTSTATUS
+ DRIVER_ADD_DEVICE (
+ __in struct _DRIVER_OBJECT *DriverObject,
+ __in struct _DEVICE_OBJECT *PhysicalDeviceObject
+ );
+
+ typedef DRIVER_ADD_DEVICE *PDRIVER_ADD_DEVICE;
+
+ #endif // !defined ( SE_CREATE_SYMBOLIC_LINK_PRIVILEGE )
+
+
+
+ #define MBG_USB_MAX_NUMBER_OF_ENDPOINTS 32
+ #define MBG_USB_MAX_NUMBER_OF_INTERFACES 1
+ #define MBG_USB_DEFAULT_TIMEOUT 5000
+ #define MBG_USB_MAX_CONTROL_TRANSFER_TIMEOUT 5000
+
+
+ #pragma pack( 4 ) //##++++++ this should be obsolete
+
+ typedef struct
+ {
+ long usage_count;
+ int remove_pending;
+ KEVENT event;
+ } USB_REMOVE_LOCK;
+
+
+ typedef struct
+ {
+ int address;
+ USBD_PIPE_HANDLE handle;
+ } USB_ENDPOINT;
+
+
+ typedef struct
+ {
+ int valid;
+ int claimed;
+ USB_ENDPOINT endpoints[MBG_USB_MAX_NUMBER_OF_ENDPOINTS];
+ } USB_INTERFACE;
+
+ #pragma pack()
+
+
+
+ #define _pcps_ddev_data_win_pnp \
+ DEVICE_OBJECT *physical_device_object; \
+ USB_REMOVE_LOCK remove_lock; \
+ \
+ struct \
+ { \
+ USBD_CONFIGURATION_HANDLE handle; \
+ int value; \
+ USB_INTERFACE interfaces[MBG_USB_MAX_NUMBER_OF_INTERFACES]; \
+ } config; \
+ \
+ LONG ref_count; \
+ POWER_STATE power_state; \
+ DEVICE_POWER_STATE device_power_states[PowerSystemMaximum]; \
+ \
+ DEVICE_OBJECT *NextLowerDriver; \
+ BOOLEAN Started; \
+ BOOLEAN SurpriseRemoved; \
+ IO_REMOVE_LOCK RemoveLock; \
+ BOOLEAN PortWasMapped;
+
+#else // if !defined( MBG_TGT_WIN32_PNP )
+
+ // Don't need PNP extensions in non-PNP environment.
+ #define _pcps_ddev_data_win_pnp \
+ UNICODE_STRING *RegistryPath; \
+ PVOID orgDeviceExtension;
+
+#endif // !defined( MBG_TGT_WIN32_PNP )
+
+
+ #define _pcps_ddev_data_win \
+ DRIVER_OBJECT *DriverObject; \
+ DEVICE_OBJECT *DeviceObject; \
+ UNICODE_STRING win32DeviceName; \
+ WCHAR wcs_msg[512]; \
+ IRP *irp; \
+ _pgmb_irq_vars \
+ _pcps_ddev_data_win_pnp
+
+#endif // defined( MBG_TGT_KERNEL )
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ clock_t w32_clock( void ) ;
+ /**
+ * @brief Try to import an API function to read precise Windows system time
+ *
+ * Check if the Windows API call KeQuerySystemTimePrecise() is available
+ * in kernel mode. This function has been introduced with Windows 8, so it
+ * is not available on older Windows versions, and thus the API call is
+ * imported from ntoskrnl.exe at runtime.
+ *
+ * @param fnc address of a function pointer which is set to the imported
+ * API function, or to NULL if the API call is not supported
+ *
+ * @see KeQuerySystemTimePrecise()
+ */
+ void import_kernel_precise_time_api( KE_QUERY_SYSTEM_TIME_FNC *fnc ) ;
+
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of header body */
+
+#undef _ext
+
+#endif /* _MBG_W32_H */
+
diff --git a/mbglib/win32/wingetopt.c b/mbglib/win32/wingetopt.c
new file mode 100644
index 0000000..ed04c44
--- /dev/null
+++ b/mbglib/win32/wingetopt.c
@@ -0,0 +1,90 @@
+/*
+POSIX getopt for Windows
+
+AT&T Public License
+
+Code given out at the 1985 UNIFORUM conference in Dallas.
+*/
+
+#ifndef __GNUC__
+
+#include "wingetopt.h"
+#include <stdio.h>
+
+#if !defined( NULL )
+ #define NULL 0
+#endif
+
+#if 1 //##++ defined( MSVC )
+
+ #include <string.h>
+
+// #define strcmp _strcmp
+// #define strchr _strchr
+
+#endif
+
+
+#define EOF (-1)
+#define ERR(s, c) if(opterr){\
+ char errbuf[2];\
+ errbuf[0] = c; errbuf[1] = '\n';\
+ fputs(argv[0], stderr);\
+ fputs(s, stderr);\
+ fputc(c, stderr);}
+ //(void) write(2, argv[0], (unsigned)strlen(argv[0]));\
+ //(void) write(2, s, (unsigned)strlen(s));\
+ //(void) write(2, errbuf, 2);}
+
+int opterr = 1;
+int optind = 1;
+int optopt;
+char *optarg;
+
+int
+getopt(argc, argv, opts)
+int argc;
+char **argv, *opts;
+{
+ static int sp = 1;
+ register int c;
+ register char *cp;
+
+ if(sp == 1)
+ if(optind >= argc ||
+ argv[optind][0] != '-' || argv[optind][1] == '\0')
+ return(EOF);
+ else if(strcmp(argv[optind], "--") == 0) {
+ optind++;
+ return(EOF);
+ }
+ optopt = c = argv[optind][sp];
+ if(c == ':' || (cp=strchr(opts, c)) == NULL) {
+ ERR(": illegal option -- ", c);
+ if(argv[optind][++sp] == '\0') {
+ optind++;
+ sp = 1;
+ }
+ return('?');
+ }
+ if(*++cp == ':') {
+ if(argv[optind][sp+1] != '\0')
+ optarg = &argv[optind++][sp+1];
+ else if(++optind >= argc) {
+ ERR(": option requires an argument -- ", c);
+ sp = 1;
+ return('?');
+ } else
+ optarg = argv[optind++];
+ sp = 1;
+ } else {
+ if(argv[optind][++sp] == '\0') {
+ sp = 1;
+ optind++;
+ }
+ optarg = NULL;
+ }
+ return(c);
+}
+
+#endif /* __GNUC__ */
diff --git a/mbglib/win32/wingetopt.h b/mbglib/win32/wingetopt.h
new file mode 100644
index 0000000..f983fb3
--- /dev/null
+++ b/mbglib/win32/wingetopt.h
@@ -0,0 +1,32 @@
+/*
+POSIX getopt for Windows
+
+AT&T Public License
+
+Code given out at the 1985 UNIFORUM conference in Dallas.
+*/
+
+#ifdef __GNUC__
+#include <getopt.h>
+#endif
+#ifndef __GNUC__
+
+#ifndef _WINGETOPT_H_
+#define _WINGETOPT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int opterr;
+extern int optind;
+extern int optopt;
+extern char *optarg;
+extern int getopt(int argc, char **argv, char *opts);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H_ */
+#endif /* __GNUC__ */
diff --git a/mbgstatus/mbgstatus.c b/mbgstatus/mbgstatus.c
new file mode 100644
index 0000000..d4df10c
--- /dev/null
+++ b/mbgstatus/mbgstatus.c
@@ -0,0 +1,895 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgstatus.c 1.13.1.25 2013/02/05 14:36:47Z martin TEST martin $
+ *
+ * Description:
+ * Main file for mbgstatus program which demonstrates how to
+ * access a Meinberg device via IOCTL calls and prints device
+ * information.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgstatus.c $
+ * Revision 1.13.1.25 2013/02/05 14:36:47Z martin
+ * Revision 1.13.1.24 2012/04/11 16:26:44Z martin
+ * Revision 1.13.1.23 2012/04/10 15:56:40 martin
+ * Revision 1.13.1.22 2012/02/14 13:40:02 martin
+ * Use library function to print MAC address.
+ * Revision 1.13.1.21 2012/01/17 13:35:41 martin
+ * More control of amount of output by verbosity level.
+ * Revision 1.13.1.20 2012/01/16 16:41:25 martin
+ * Revision 1.13.1.19 2011/10/28 13:46:14 martin
+ * Revision 1.13.1.18 2011/10/28 13:05:03 martin
+ * Revision 1.13.1.17 2011/10/05 15:10:56 martin
+ * Show PZF correlation state.
+ * Revision 1.13.1.16 2011/10/05 13:03:34 martin
+ * Adapted PZF correlation/signal/status display.
+ * Revision 1.13.1.15 2011/10/05 11:57:42 martin
+ * Revision 1.13.1.14 2011/09/29 16:30:03 martin
+ * Started to support PZF.
+ * Optionally show hex status.
+ * Changed what is displayed in certain levels of verbosity.
+ * Revision 1.13.1.13 2011/09/07 15:08:55 martin
+ * Account for modified library functions which can now
+ * optionally print the raw (hex) HR time stamp.
+ * Revision 1.13.1.12 2011/07/08 11:02:47 martin
+ * Revision 1.13.1.11 2011/07/05 15:35:55 martin
+ * Modified version handling.
+ * Revision 1.13.1.10 2011/07/05 14:35:19 martin
+ * New way to maintain version information.
+ * Revision 1.13.1.9 2011/04/20 16:08:27 martin
+ * Use snprint_ip4_addr() from module lan_util.
+ * Revision 1.13.1.8 2011/03/03 10:01:23 daniel
+ * Indicate Unicast role in PTP port state
+ * Revision 1.13.1.7 2011/02/07 12:10:58 martin
+ * Use mbg_get_ptp_status() API call.
+ * Revision 1.13.1.6 2010/11/25 14:54:51 martin
+ * Revision 1.13.1.5 2010/11/05 12:54:22 martin
+ * Introduce "verbose" flag and associated command line parameter -v.
+ * Revision 1.13.1.4 2010/10/15 11:28:56 martin
+ * Display UTC offs from IRIG signal.
+ * Revision 1.13.1.3 2010/08/30 08:22:24 martin
+ * Revision 1.13.1.2 2010/08/11 15:06:49 martin
+ * Preliminarily display raw IRIG data, if supported by the device.
+ * Revision 1.13.1.1 2010/02/17 14:11:43 martin
+ * Cosmetics ...
+ * Revision 1.13 2009/09/29 15:02:16 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.12 2009/07/24 14:02:59 martin
+ * Display LAN and PTP status of PTP cards.
+ * Updated version number to 3.3.0.
+ * Revision 1.11 2009/06/19 14:20:36 martin
+ * Display raw IRIG time with TCR cards which support this.
+ * Revision 1.10 2009/06/16 08:21:08 martin
+ * Intermediate version 3.1.0a.
+ * Display IRIG debug status, if supported by the card.
+ * Revision 1.9 2009/03/20 11:35:41 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Display signal source after signal level.
+ * Display GPS UTC parameter info, if supported by the card.
+ * Display IRIG control bits, if supported by the card.
+ * Revision 1.8 2008/12/22 12:48:18 martin
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Warn if a PCI Express device with unsafe IRQ support is detected.
+ * Account for signed irq_num.
+ * Accept device name(s) on the command line.
+ * Don't use printf() without format, which migth produce warnings
+ * with newer gcc versions.
+ * Revision 1.7 2007/07/24 09:33:52 martin
+ * Fixed display of port and IRQ resources.
+ * Updated copyright to include 2007.
+ * Revision 1.6 2006/03/10 12:38:22 martin
+ * Fixed printing of sign in print_position().
+ * Revision 1.5 2004/11/08 15:41:56 martin
+ * Modified formatted printing of date/time string.
+ * Using type casts to avoid compiler warnings.
+ * Revision 1.4 2003/07/30 08:16:39 martin
+ * Also displays oscillator DAC values for GPS.
+ * Revision 1.3 2003/07/08 15:38:57 martin
+ * Call mbg_find_devices().
+ * Account for swap_doubles() now being called inside
+ * the mbgdevio API functions.
+ * Show IRQ number assigned to a device.
+ * Revision 1.2 2003/04/25 10:28:05 martin
+ * Use new functions from mbgdevio library.
+ * New program version v2.1.
+ * Revision 1.1 2001/09/17 15:08:59 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <mbgtime.h>
+#include <pcpslstr.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+#include <lan_util.h>
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#define MBG_MICRO_VERSION 0
+#define MBG_FIRST_COPYRIGHT_YEAR 2001
+#define MBG_LAST_COPYRIGHT_YEAR 0 // use current year by default
+
+static const char *pname = "mbgstatus";
+
+
+static unsigned int verbose;
+
+static const char *ref_name[N_PCPS_REF]= PCPS_REF_NAMES_ENG;
+static const char *icode_rx_names[N_ICODE_RX] = DEFAULT_ICODE_RX_NAMES;
+static const char *osc_name[N_GPS_OSC] = DEFAULT_GPS_OSC_NAMES;
+
+static int year_limit = 1990;
+
+static int max_ref_offs_h = MBG_REF_OFFS_MAX / MINS_PER_HOUR;
+static int invt_reason;
+
+LANGUAGE language;
+CTRY ctry;
+
+
+
+static /*HDR*/
+void show_invt_reason( void )
+{
+ static const char fmt[] = "\n** Warning: %s\nThe command %s.\n";
+
+ switch ( invt_reason )
+ {
+ case 2:
+ printf( fmt, DEFAULT_STR_IRIG_NOT_CFGD_EN,
+ "\"mbgirigcfg\" can be used to change the settings" );
+ break;
+
+ case 1:
+ printf( fmt, DEFAULT_STR_IRIG_INVT_EN,
+ "\"mbgctrl DATE=...\" can be used to set the on-board date" );
+ break;
+
+ } // switch
+
+} // show_invt_reason
+
+
+
+static /*HDR*/
+void print_pcps_time( const char *s, const PCPS_TIME *tp, const char *tail )
+{
+ const char *fmt = "%s";
+ char ws[256];
+
+ if ( s )
+ printf( fmt, s );
+
+ printf( fmt, pcps_date_time_str( ws, tp, year_limit, pcps_tz_name( tp, PCPS_TZ_NAME_FORCE_UTC_OFFS, 0 ) ) );
+
+ if ( ( verbose > 0 ) && _pcps_time_is_read( tp ) )
+ printf( ", st: 0x%02lX", (ulong) tp->status );
+
+ if ( tail )
+ printf( fmt, tail );
+
+} // print_pcps_time
+
+
+
+static /*HDR*/
+void print_dms( const char *s, const DMS *p, const char *tail )
+{
+ const char *fmt = "%s";
+
+ printf( "%s %c %3i deg %02i min %05.2f sec",
+ s,
+ p->prefix,
+ p->deg,
+ p->min,
+ p->sec
+ );
+
+ if ( tail )
+ printf( fmt, tail );
+
+} // print_dms
+
+
+
+static /*HDR*/
+void print_position( const char *s, const POS *p, const char *tail )
+{
+ const char *fmt = "%s";
+ double r2d = 180 / PI;
+
+
+ if ( s )
+ {
+ printf( fmt, s );
+
+ if ( verbose )
+ printf( "\n" );
+ }
+
+ if ( verbose > 1 )
+ {
+ printf( " x: %.0fm y: %.0fm z: %.0fm",
+ p->xyz[XP], p->xyz[YP], p->xyz[ZP] );
+
+ if ( tail )
+ printf( fmt, tail );
+ }
+
+ // LLA latitude and longitude are in radians, convert to degrees
+ printf( " lat: %+.4f lon: %+.4f alt: %.0fm",
+ p->lla[LAT] * r2d, p->lla[LON] * r2d, p->lla[ALT] );
+
+ if ( tail )
+ printf( fmt, tail );
+
+ if ( verbose )
+ {
+ print_dms( " latitude: ", &p->latitude, tail );
+ print_dms( " longitude:", &p->longitude, tail );
+ }
+
+} // print_position
+
+
+
+static /*HDR*/
+void show_signal( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, int signal )
+{
+ int ref_type;
+ int rc;
+
+ ref_type = _pcps_ref_type( pdev );
+
+ if ( ref_type >= N_PCPS_REF )
+ ref_type = PCPS_REF_NONE;
+
+ printf( "Signal: %u%% (%s", signal * 100 / PCPS_SIG_MAX, ref_name[ref_type] );
+
+ if ( _pcps_is_irig_rx( pdev ) )
+ {
+ IRIG_INFO irig_rx_info;
+ MBG_REF_OFFS ref_offs;
+
+ rc = mbg_get_irig_rx_info( dh, &irig_rx_info );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ int idx = irig_rx_info.settings.icode;
+
+ if ( idx < N_ICODE_RX )
+ {
+ printf( " %s", icode_rx_names[idx] );
+
+ if ( !( MSK_ICODE_RX_HAS_TZI & ( 1UL << idx ) ) )
+ {
+ if ( _pcps_has_ref_offs( pdev ) )
+ {
+ rc = mbg_get_ref_offs( dh, &ref_offs );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ int ref_offs_h = ref_offs / MINS_PER_HOUR;
+
+ if ( abs( ref_offs_h ) > max_ref_offs_h )
+ printf( ", ** UTC offs not configured **" );
+ else
+ printf( ", UTC%+ih", ref_offs_h );
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ if ( _pcps_has_pzf( pdev ) )
+ printf( "/PZF" );
+
+ printf( ")\n" );
+
+} // show_signal
+
+
+
+static /*HDR*/
+void show_time_and_status( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, const char *tail )
+{
+ const char status_fmt[] = "Status info: %s%s\n";
+ const char status_err[] = "*** ";
+ const char status_ok[] = "";
+ const char *info_err = ( _pcps_is_gps( pdev ) || _pcps_is_lwr( pdev ) ) ?
+ "ANTENNA FAULTY" : "NO INPUT SIGNAL";
+ const char info_ok[] = "Input signal available";
+ PCPS_TIME t;
+ PCPS_STATUS_STRS strs;
+ int signal;
+ int i;
+ int rc = mbg_get_time( dh, &t );
+ if ( mbg_ioctl_err( rc, "mbg_get_time" ) )
+ return;
+
+
+ print_pcps_time( "Date/time: ", &t, tail );
+
+ if ( ( verbose > 0 ) && _pcps_has_hr_time( pdev ) )
+ {
+ PCPS_HR_TIME ht;
+ char ws[80];
+
+ rc = mbg_get_hr_time( dh, &ht );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_hr_time" ) )
+ return;
+
+ mbg_snprint_hr_time( ws, sizeof( ws ), &ht, 0 ); // raw timestamp?
+ printf( "Local HR time: %s", ws );
+
+ if ( verbose > 0 )
+ printf( ", st: 0x%04lX", (ulong) ht.status );
+
+ printf( "%s", tail );
+ }
+
+ signal = t.signal - PCPS_SIG_BIAS;
+
+ if ( signal < 0 )
+ signal = 0;
+ else
+ if ( signal > PCPS_SIG_MAX )
+ signal = PCPS_SIG_MAX;
+
+ if ( _pcps_has_signal( pdev ) )
+ show_signal( dh, pdev, signal );
+
+ if ( _pcps_has_pzf( pdev ) )
+ {
+ mbg_show_pzf_corr_info( dh, pdev, 0 );
+ printf( "\n" );
+ }
+
+ if ( verbose && _pcps_has_irig_time( pdev ) )
+ {
+ PCPS_IRIG_TIME it;
+
+ rc = mbg_get_irig_time( dh, &it );
+
+ if ( !mbg_ioctl_err( rc, "mbg_get_irig_time" ) )
+ printf( "Raw IRIG time: yday %u, %02u:%02u:%02u\n",
+ it.yday, it.hour, it.min, it.sec );
+ }
+
+ printf( status_fmt,
+ ( signal < PCPS_SIG_ERR ) ? status_err : status_ok,
+ ( signal < PCPS_SIG_ERR ) ? info_err : info_ok );
+
+ // Evaluate the status code and setup status messages.
+ pcps_status_strs( t.status, _pcps_time_is_read( &t ),
+ _pcps_is_gps( pdev ), &strs );
+
+ // Print the status messages.
+ for ( i = 0; i < N_PCPS_STATUS_STR; i++ )
+ {
+ PCPS_STATUS_STR *pstr = &strs.s[i];
+ if ( pstr->cp )
+ printf( status_fmt,
+ pstr->is_err ? status_err : status_ok,
+ pstr->cp );
+ }
+
+ invt_reason = 0;
+
+ if ( _pcps_is_irig_rx( pdev ) && ( t.status & PCPS_INVT ) )
+ {
+ MBG_REF_OFFS ref_offs;
+
+ rc = mbg_get_ref_offs( dh, &ref_offs );
+
+ if ( !mbg_ioctl_err( rc, "mbg_get_ref_offs" ) )
+ {
+ if ( _pcps_ref_offs_out_of_range( ref_offs ) )
+ invt_reason = 2;
+ else
+ invt_reason = 1;
+ }
+ }
+
+} // show_time_and_status
+
+
+
+static /*HDR*/
+void show_sync_time( MBG_DEV_HANDLE dh, const char *tail )
+{
+ PCPS_TIME t;
+ int rc = mbg_get_sync_time( dh, &t );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_sync_time" ) )
+ return;
+
+ print_pcps_time( "Last sync: ", &t, tail );
+
+} // show_sync_time
+
+
+
+static /*HDR*/
+void show_ext_stat_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *tail )
+{
+ const char *fmt = "%s";
+ RECEIVER_INFO ri;
+ STAT_INFO si = { 0 };
+ char ws[80];
+ char *mode_name;
+
+ int rc = mbg_setup_receiver_info( dh, p_dev, &ri );
+
+ if ( mbg_ioctl_err( rc, "mbg_setup_receiver_info" ) )
+ return;
+
+ if ( _pcps_has_stat_info( p_dev ) )
+ {
+ rc = mbg_get_gps_stat_info( dh, &si );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_stat_info" ) )
+ return;
+
+
+ if ( _pcps_has_stat_info_mode( p_dev ) )
+ {
+ switch ( si.mode )
+ {
+ case AUTO_166: mode_name = "Normal Operation"; break;
+ case WARM_166: mode_name = "Warm Boot"; break;
+ case COLD_166: mode_name = "Cold Boot"; break;
+
+ default: // This should never happen!
+ sprintf( ws, "Unknown mode of operation: %02Xh", si.mode );
+ mode_name = ws;
+
+ } // switch
+ }
+
+ if ( _pcps_has_stat_info_svs( p_dev ) )
+ printf( "%s, %i sats in view, %i sats used\n", mode_name, si.svs_in_view, si.good_svs );
+ }
+
+ if ( verbose )
+ {
+ printf( "Osc type: %s", osc_name[( ri.osc_type < N_GPS_OSC ) ? ri.osc_type : GPS_OSC_UNKNOWN] );
+
+ if ( _pcps_has_stat_info( p_dev ) )
+ {
+ printf( ", DAC cal: %+i, fine: %+i",
+ (int) ( si.dac_cal - OSC_DAC_BIAS ),
+ (int) ( si.dac_val - OSC_DAC_BIAS ) );
+ }
+
+ puts( "" );
+ }
+
+ if ( tail )
+ printf( fmt, tail );
+
+} // show_ext_stat_info
+
+
+
+static /*HDR*/
+void show_gps_pos( MBG_DEV_HANDLE dh, const char *tail )
+{
+ POS pos;
+ int rc = mbg_get_gps_pos( dh, &pos );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_pos" ) )
+ return;
+
+ print_position( "Receiver Position:", &pos, tail );
+
+} // show_gps_pos
+
+
+
+static /*HDR*/
+void show_utc_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ UTC utc;
+
+ int rc = mbg_get_utc_parm( dh, &utc );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_utc_parm" ) )
+ return;
+
+ if ( !utc.valid )
+ {
+ puts( "** UTC parameters not valid" );
+ return;
+ }
+
+ if ( verbose > 1 )
+ {
+ //##++++ utc.delta_tls = utc.delta_tlsf - 1;
+
+ printf( "CSUM: %04X, valid: %04X\n", utc.csum, utc.valid );
+ printf( "t0t: %u|%u.%07u, A0: %g A1: %g\n",
+ utc.t0t.wn, utc.t0t.sec, utc.t0t.tick,
+ utc.A0, utc.A1 );
+ printf( "WNlsf: %u, DN: %u, offs: %i/%i\n",
+ utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf );
+ }
+
+ if ( utc.delta_tls != utc.delta_tlsf )
+ {
+ // a leap second is currently being announced
+ time_t t_ls = (time_t) utc.WNlsf * SECS_PER_WEEK
+ + (time_t) utc.DNt * SECS_PER_DAY
+ + GPS_SEC_BIAS - 1;
+
+ struct tm *tm = gmtime( &t_ls );
+
+ printf( "UTC offset transition from %is to %is due to leap second\n"
+ "%s at UTC midnight at the end of %04i-%02i-%02i.\n",
+ utc.delta_tls, utc.delta_tlsf,
+ ( utc.delta_tls < utc.delta_tlsf ) ? "insertion" : "deletion",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday
+ );
+ }
+ else
+ printf( "UTC offset parameter: %is, no leap second announced.\n", utc.delta_tls );
+
+} // show_utc_info
+
+
+
+static /*HDR*/
+void show_irig_ctrl_bits( MBG_DEV_HANDLE dh )
+{
+ MBG_IRIG_CTRL_BITS irig_ctrl_bits;
+
+ int rc = mbg_get_irig_ctrl_bits( dh, &irig_ctrl_bits );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_irig_ctrl_bits" ) )
+ return;
+
+ printf( "IRIG control bits: %08lX (hex, LSB first)", (ulong) irig_ctrl_bits );
+ printf( ", TFOM: 0x%X", _pcps_tfom_from_irig_ctrl_bits( &irig_ctrl_bits ) );
+ printf( "\n" );
+
+} // show_irig_ctrl_bits
+
+
+
+static /*HDR*/
+char *str_raw_irig_utc_offs_hours( char *s, int max_len, const MBG_RAW_IRIG_DATA *p )
+{
+ int n;
+ long offs = ( p->data_bytes[8] & 0x08 )
+ | ( ( p->data_bytes[8] >> 2 ) & 0x04 )
+ | ( ( p->data_bytes[8] >> 4 ) & 0x02 )
+ | ( ( p->data_bytes[8] >> 6 ) & 0x01 );
+
+ n = snprintf( s, max_len, "%c%li", ( p->data_bytes[8] & 0x80 ) ? '-' : '+', offs );
+
+ if ( p->data_bytes[8] & 0x02 )
+ n += snprintf( &s[n], max_len - n, "%s", ".5" );
+
+ return s;
+
+} // str_raw_irig_utc_offs_hours
+
+
+
+static /*HDR*/
+void show_raw_irig_data( MBG_DEV_HANDLE dh )
+{
+ MBG_RAW_IRIG_DATA raw_irig_data;
+ char ws[80];
+ int i;
+
+ int rc = mbg_get_raw_irig_data( dh, &raw_irig_data );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_raw_irig_data" ) )
+ return;
+
+ printf( "Raw IRIG data:" );
+
+ for ( i = 0; i < sizeof( raw_irig_data ); i++ )
+ printf( " %02X", raw_irig_data.data_bytes[i] );
+
+ printf( " (hex)" );
+ printf( ", TFOM: 0x%X", _pcps_tfom_from_raw_irig_data( &raw_irig_data ) );
+ printf( ", UTC offs: %sh", str_raw_irig_utc_offs_hours( ws, sizeof( ws ), &raw_irig_data ) );
+ printf( "\n" );
+
+} // show_raw_irig_data
+
+
+
+static /*HDR*/
+void show_irig_debug_status( MBG_DEV_HANDLE dh )
+{
+ static const char *status_str[N_MBG_DEBUG_BIT] = MBG_DEBUG_STATUS_STRS;
+
+ MBG_DEBUG_STATUS st;
+ int i;
+ int rc = _mbg_generic_read_var( dh, PCPS_GET_DEBUG_STATUS, st );
+
+ if ( mbg_ioctl_err( rc, "show_irig_debug_status" ) )
+ return;
+
+ printf( "Debug status (hex): %08lX\n", (ulong) st );
+
+ for ( i = 0; i < N_MBG_DEBUG_BIT; i++ )
+ if ( st & ( 1UL << i ) )
+ printf( " %s\n", status_str[i] );
+
+} // show_irig_debug_status
+
+
+
+static /*HDR*/
+void show_lan_intf_state( MBG_DEV_HANDLE dh )
+{
+ IP4_SETTINGS ip4_settings;
+ LAN_IF_INFO lan_if_info;
+ char ws[100];
+
+ int rc = mbg_get_ip4_state( dh, &ip4_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ip4_state" ) )
+ return;
+
+ rc = mbg_get_lan_if_info( dh, &lan_if_info );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_lan_if_info" ) )
+ return;
+
+
+ printf( "On-board LAN interface settings:\n" );
+
+ snprint_mac_addr( ws, sizeof( ws ), &lan_if_info.mac_addr );
+ printf( " MAC Address: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.ip_addr, NULL );
+ printf( " IP Address: %s%s\n", ws, ( ip4_settings.flags & IP4_MSK_DHCP ) ?
+ " (DHCP)" : "" );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.netmask, NULL );
+ printf( " Net Mask: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.broad_addr, NULL );
+ printf( " Broadcast Addr: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.gateway, NULL );
+ printf( " Gateway: %s\n", ws );
+
+ printf( " Link detected: %s\n", ( ip4_settings.flags & IP4_MSK_LINK ) ? "YES" : "NO" );
+
+} // show_lan_intf_state
+
+
+
+static /*HDR*/
+void show_ptp_state( MBG_DEV_HANDLE dh )
+{
+ static const char *ptp_stat_str[N_PTP_PORT_STATE] = PTP_PORT_STATE_STRS;
+ char ws[100];
+ const char *cp;
+ int ptp_state_available;
+ PTP_STATE ptp_state;
+ PTP_CFG_INFO ptp_info;
+
+ int rc = mbg_get_ptp_state( dh, &ptp_state );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ptp_state" ) )
+ return;
+
+ rc = mbg_get_ptp_cfg_info( dh, &ptp_info );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ptp_info" ) )
+ return;
+
+ printf( "PTP port status:\n" );
+
+ ptp_state_available = ( ptp_state.port_state == PTP_PORT_STATE_SLAVE );
+
+ printf( " Port mode: %s%s\n", ( ptp_state_available && ptp_info.settings.ptp_role == PTP_ROLE_UNICAST_SLAVE ) ? "Unicast" : "",
+ ( ptp_state.port_state < N_PTP_PORT_STATE ) ? ptp_stat_str[ptp_state.port_state] : "(undefined)" );
+
+ cp = ptp_state_available ? ws : str_not_avail;
+
+//##++++++++++
+ snprintf( ws, sizeof( ws ), "%02X-%02X-%02X-%02X-%02X-%02X",
+ ptp_state.gm_id.b[0],
+ ptp_state.gm_id.b[1],
+ ptp_state.gm_id.b[2],
+ ptp_state.gm_id.b[5],
+ ptp_state.gm_id.b[6],
+ ptp_state.gm_id.b[7]
+ );
+ printf( " Grandmaster MAC: %s\n", cp );
+
+
+ snprintf( ws, sizeof( ws ), "%c%li.%09li s",
+ _nano_time_negative( &ptp_state.path_delay ) ? '-' : '+',
+ labs( (long) ptp_state.path_delay.secs ),
+ labs( (long) ptp_state.path_delay.nano_secs )
+ );
+ printf( " PTP path delay: %s\n", cp );
+
+
+ snprintf( ws, sizeof( ws ), "%c%li.%09li s",
+ _nano_time_negative( &ptp_state.offset ) ? '-' : '+',
+ labs( (long) ptp_state.offset.secs ),
+ labs( (long) ptp_state.offset.nano_secs )
+ );
+ printf( " PTP time offset: %s\n", cp );
+
+} // show_ptp_state
+
+
+
+static /*HDR*/
+int check_irq_unsafe( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ PCPS_IRQ_STAT_INFO irq_stat_info;
+ int ret_val = 0;
+ int rc = mbg_get_irq_stat_info( dh, &irq_stat_info );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_irq_stat_info" ) )
+ return -1;
+
+ if ( irq_stat_info & PCPS_IRQ_STAT_UNSAFE )
+ {
+ static const char *warn_line = "************************************************************************************";
+
+ puts( "" );
+ puts( warn_line );
+
+ printf(
+ "** WARNING!\n"
+ "**\n"
+ "** Device %s with S/N %s has a firmware version and ASIC version\n"
+ "** which do not allow safe operation with hardware interrupts (IRQs) enabled.\n"
+ "**\n"
+ "** Please see http://www.meinberg.de/english/info/pex-upgrades.htm\n"
+ "** for information how the card can easily be upgraded, or contact\n"
+ "** Meinberg support (Email: support@meinberg.de) or your local\n"
+ "** representative.\n"
+ ,
+ _pcps_type_name( p_dev ), _pcps_sernum( p_dev )
+ );
+
+ if ( irq_stat_info & PCPS_IRQ_STAT_ENABLED )
+ {
+ printf(
+ "**\n"
+ "** Interrupts are currently enabled for this card (NTP daemon running?)\n"
+ "** so other access is inhibited to prevent the system from hanging.\n"
+ );
+
+ ret_val = -1;
+ }
+
+ puts( warn_line );
+ puts( "" );
+ }
+
+ return ret_val;
+
+} // check_irq_unsafe
+
+
+
+static /*HDR*/
+int do_mbgstatus( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ int ret_val = 0;
+
+ if ( check_irq_unsafe( dh, p_dev ) < 0 )
+ goto done;
+
+ if ( _pcps_has_gps_data( p_dev ) )
+ show_ext_stat_info( dh, p_dev, NULL );
+
+ show_time_and_status( dh, p_dev, "\n" );
+ show_sync_time( dh, "\n" );
+
+ if ( _pcps_is_gps( p_dev ) )
+ show_gps_pos( dh, "\n" );
+
+ if ( _pcps_has_utc_parm( p_dev ) && ( _pcps_is_gps( p_dev ) || ( verbose > 0 ) ) )
+ show_utc_info( dh, p_dev );
+
+ if ( verbose && _pcps_has_irig_ctrl_bits( p_dev ) )
+ show_irig_ctrl_bits( dh );
+
+ if ( verbose && _pcps_has_raw_irig_data( p_dev ) )
+ show_raw_irig_data( dh );
+
+ if ( verbose && _pcps_is_irig_rx( p_dev ) )
+ show_irig_debug_status( dh );
+
+ if ( _pcps_has_lan_intf( p_dev ) )
+ show_lan_intf_state( dh );
+
+ if ( _pcps_has_ptp( p_dev ) )
+ show_ptp_state( dh );
+
+ show_invt_reason();
+
+done:
+ return ret_val;
+
+} // do_mbgstatus
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This program prints status information for a device.\n"
+ "The displayed information depends on the type of the card."
+ );
+ mbg_print_help_options();
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int c;
+ int rc;
+
+ ctry_setup( 0 );
+ language = LNG_ENGLISH;
+ ctry.dt_fmt = DT_FMT_YYYYMMDD;
+ ctry.dt_sep = '-';
+
+ mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "vh?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'v':
+ verbose++;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+
+ if ( verbose )
+ pcps_date_time_dist = 1;
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbgstatus );
+
+ return abs( rc );
+}
diff --git a/mbgversion.h b/mbgversion.h
new file mode 100644
index 0000000..433b942
--- /dev/null
+++ b/mbgversion.h
@@ -0,0 +1,37 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgversion.h 1.3 2013/01/03 12:09:30Z martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Program version definitions for package mbgtools-lx.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgversion.h $
+ * Revision 1.3 2013/01/03 12:09:30Z martin
+ * Changed copyright year to 2013.
+ * Revision 1.2 2012/01/17 10:10:54 martin
+ * Changed current copyright year to 2012.
+ * Revision 1.1 2011/07/08 11:38:32 martin
+ * Initial revision for pre-release.
+ *
+ **************************************************************************/
+
+#define MBG_CURRENT_COPYRIGHT_YEAR 2013
+#define MBG_CURRENT_COPYRIGHT_YEAR_STR "2013"
+
+#define MBG_MAJOR_VERSION_CODE 3
+#define MBG_MINOR_VERSION_CODE 4
+
+#define MBG_MAIN_VERSION_STR "3.4"
+
+// The codes below should only fe defined in development/pre-release versions
+#define MBG_MICRO_VERSION_CODE_DEV 99
+#define MBG_MICRO_VERSION_STR_DEV "99"
+
+
+#define MBG_MAIN_VERSION_CODE ( ( MBG_MAJOR_VERSION_CODE << 8 ) | MBG_MINOR_VERSION_CODE )
+
+#define MBG_VERSION_CODE( _micro ) ( (uint16_t) ( ( MBG_MAIN_VERSION_CODE << 8 ) | (_micro) ) )
diff --git a/test/mbgcmptime/mbgcmptime.c b/test/mbgcmptime/mbgcmptime.c
new file mode 100644
index 0000000..7052048
--- /dev/null
+++ b/test/mbgcmptime/mbgcmptime.c
@@ -0,0 +1,345 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgcmptime.c 1.1.1.3 2013/03/20 11:14:14Z martin TEST $
+ *
+ * Description:
+ * Main file for mbgcmptime program which compares the time on 2 devices
+ * by reading the time plus cycles from both devices immediately after
+ * each other, and compensates the execution delay based on the returned
+ * cycles counts.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgcmptime.c $
+ * Revision 1.1.1.3 2013/03/20 11:14:14Z martin
+ * Revision 1.1.1.2 2013/02/01 16:26:50 martin
+ * Revision 1.1.1.1 2013/01/29 14:23:40 martin
+ * Tried to fix negative range overflow.
+ * Revision 1.1 2013/01/25 10:26:13 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#define MBG_MICRO_VERSION 0
+#define MBG_FIRST_COPYRIGHT_YEAR 2013
+#define MBG_LAST_COPYRIGHT_YEAR 0 // use default
+
+static const char *pname = "mbgcmptime";
+
+
+static int loops;
+static int read_fast;
+static int read_raw;
+static long sleep_secs;
+static long sleep_usecs;
+static int print_raw;
+static double warn_limit;
+static double chk_limit;
+static MBG_PC_CYCLES_FREQUENCY cyc_freq;
+
+static const char *ref_device_name;
+static MBG_DEV_HANDLE dh_ref;
+
+
+static /*HDR*/
+int do_mbgcmptime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ int supported = 0;
+ PCPS_HR_TIME_CYCLES htc1;
+ PCPS_HR_TIME_CYCLES htc2;
+ double delta_ts;
+ double delta_cyc;
+ double delta_t;
+ double prv_delta_t;
+ int prv_delta_t_avail = 0;
+ int this_loops = loops;
+ int rc;
+ int n;
+ char ws[256];
+
+ if ( read_fast )
+ {
+ rc = mbg_dev_has_fast_hr_timestamp( dh, &supported );
+
+ if ( mbg_ioctl_err( rc, "mbg_has_fast_hr_timestamp" ) )
+ goto done;
+
+ if ( !supported )
+ {
+ printf( "This device does not support fast (memory mapped) time stamps.\n" );
+ printf( "** Falling back to raw mode.\n" );
+ read_fast = 0;
+ }
+
+ rc = mbg_dev_has_fast_hr_timestamp( dh_ref, &supported );
+
+ if ( mbg_ioctl_err( rc, "mbg_has_fast_hr_timestamp" ) )
+ goto done;
+
+ if ( !supported )
+ {
+ printf( "The ref device does not support fast (memory mapped) time stamps.\n" );
+ printf( "** Falling back to raw mode.\n" );
+ read_fast = 0;
+}
+ }
+
+ rc = mbg_get_default_cycles_frequency_from_dev( dh, &cyc_freq );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_default_cycles_frequency_from_dev" ) )
+ goto done;
+
+
+
+ for (;;)
+ {
+ if ( read_fast )
+ {
+ PCPS_TIME_STAMP_CYCLES ts_c1;
+ PCPS_TIME_STAMP_CYCLES ts_c2;
+
+ rc = mbg_get_fast_hr_timestamp_cycles( dh, &ts_c1 );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp_cycles 1" ) )
+ break;
+
+ rc = mbg_get_fast_hr_timestamp_cycles( dh_ref, &ts_c2 );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp_cycles 2" ) )
+ break;
+
+ setup_hr_time_cycles_from_timestamp_cycles( &htc1, &ts_c1 );
+ setup_hr_time_cycles_from_timestamp_cycles( &htc2, &ts_c2 );
+ }
+ else
+ {
+ rc = mbg_get_hr_time_cycles( dh, &htc1 );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_hr_time_cycles 1" ) )
+ break;
+
+ rc = mbg_get_hr_time_cycles( dh_ref, &htc2 );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_hr_time_cycles 2" ) )
+ break;
+ }
+
+ n = 0;
+
+ n += mbg_snprint_hr_tstamp( &ws[n], sizeof( ws ) - n, &htc1.t.tstamp, 0 );
+
+ if ( print_raw )
+ n += snprintf( &ws[n], sizeof( ws ) - n, " (0x%08lX.%08lX)",
+ (ulong) htc1.t.tstamp.sec,
+ (ulong) htc1.t.tstamp.frac );
+
+ n += snprintf( &ws[n], sizeof( ws ) - n, ", " );
+
+ n += mbg_snprint_hr_tstamp( &ws[n], sizeof( ws ) - n, &htc2.t.tstamp, 0 );
+
+ if ( print_raw )
+ n += snprintf( &ws[n], sizeof( ws ) - n, " (0x%08lX.%08lX)",
+ (ulong) htc2.t.tstamp.sec,
+ (ulong) htc2.t.tstamp.frac );
+
+ delta_ts = (double) htc2.t.tstamp.sec + dfrac_sec_from_bin( htc2.t.tstamp.frac )
+ - (double) htc1.t.tstamp.sec - dfrac_sec_from_bin( htc1.t.tstamp.frac );
+
+ #if defined( MBG_TGT_WIN32 )
+ {
+ __int64 dt_t = htc2.cycles - htc1.cycles;
+ delta_cyc = (double) dt_t / (__int64) cyc_freq;
+ }
+ #else
+ delta_cyc = ( (double) ( htc2.cycles - htc1.cycles ) ) / cyc_freq;
+ #endif
+ delta_t = delta_ts - delta_cyc;
+
+ n += snprintf( &ws[n], sizeof( ws ) - n, " ts: %.1f us, cyc: %.1f us, delta: %+.1f us",
+ delta_ts * 1e6, delta_cyc * 1e6, delta_t * 1e6 );
+
+ if ( ( warn_limit > 0.0 ) && ( fabs( delta_t ) > warn_limit ) )
+ n += snprintf( &ws[n], sizeof( ws ) - n, " *" );
+
+ if ( prv_delta_t_avail )
+ {
+ double ddelta_t = delta_t - prv_delta_t;
+
+ if ( ( chk_limit > 0.0 ) && ( fabs( ddelta_t ) > chk_limit ) )
+ n += snprintf( &ws[n], sizeof( ws ) - n, " <<" );
+ }
+
+ #if defined( DEBUG )
+ if ( htc2.t.tstamp.sec != htc1.t.tstamp.sec )
+ n += snprintf( &ws[n], sizeof( ws ) - n, " X" );
+ #endif
+
+ printf( "%s\n", ws );
+
+ if ( this_loops > 0 )
+ this_loops--;
+
+ if ( this_loops == 0 )
+ break;
+
+ prv_delta_t = delta_t;
+ prv_delta_t_avail = 1;
+
+ if ( sleep_secs )
+ sleep( sleep_secs );
+ else
+ if ( sleep_usecs )
+ usleep( sleep_usecs );
+
+ //##++++++ printf( "\n" );
+ // if this_loops is < 0 then loop forever
+ }
+
+done:
+ mbg_close_device( &dh );
+
+ return rc;
+
+} // do_mbgcmptime
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This example program reads fast high resolution time stamps.\n"
+ "\n"
+ "This is done using memory mapped I/O in the kernel driver, so\n"
+ "this works only with cards which support memory mapped I/O."
+ );
+ mbg_print_help_options();
+ mbg_print_opt_info( "-i dev", "reference device the test card's time shall be compared" );
+ mbg_print_opt_info( "-l limit", "append a marker '*' to the output if delta exceeds limit [us]" );
+ mbg_print_opt_info( "-L limit", "append a marker '<<' to the output if delta changes [us]" );
+ mbg_print_opt_info( "-f", "read fast (memory mapped) timestamps" );
+ mbg_print_opt_info( "-c", "run continuously" );
+ mbg_print_opt_info( "-n num", "run num loops" );
+ mbg_print_opt_info( "-b", "burst read" );
+ mbg_print_opt_info( "-r", "read raw time stamps, no cycles" );
+ mbg_print_opt_info( "-s num", "sleep num seconds between calls" );
+ mbg_print_opt_info( "-u num", "sleep num microseconds between calls" );
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int rc;
+ int c;
+
+ mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "i:l:L:fcn:rs:u:h?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'i':
+ ref_device_name = optarg;
+ break;
+
+ case 'l':
+ warn_limit = (double) atoi( optarg ) / 1e6;
+ break;
+
+ case 'L':
+ chk_limit = (double) atoi( optarg ) / 1e6;
+ break;
+
+ case 'f':
+ read_fast = 1;
+ break;
+
+ case 'c':
+ loops = -1;
+ break;
+
+ case 'n':
+ loops = atoi( optarg );
+ break;
+
+ case 'r':
+ read_raw = 1;
+ break;
+
+ case 's':
+ sleep_secs = atoi( optarg );
+ break;
+
+ case 'u':
+ sleep_usecs = atoi( optarg );
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+ #if !MBG_TGT_SUPP_MEM_ACC
+ printf( "** Memory mapped access not supported on this target platform.\n\n" );
+ return 1;
+ #endif
+
+ #if !MBG_PC_CYCLES_SUPPORTED
+ printf( "** Warning: No cycles support to compute real latencies on this platform!\n" );
+ return 1;
+ #endif
+
+
+ if ( ref_device_name )
+ {
+ #if defined( MBG_TGT_WIN32 )
+ dh_ref = mbg_open_device_by_name( ref_device_name, MBG_MATCH_MODEL);
+ #else // if defined( MBG_TGT_UNIX )
+ dh_ref = open( ref_device_name, O_RDONLY );
+ #endif
+
+ if ( dh_ref < 0 )
+ {
+ fprintf( stderr, "Failed to open ref device %s, exiting.\n", ref_device_name );
+ exit( EXIT_FAILURE );
+ }
+
+ #if defined( DEBUG )
+ fprintf( stderr, "Ref device %s opened successfully.\n", ref_device_name );
+ #endif
+ }
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbgcmptime );
+
+ mbg_close_device( &dh_ref );
+
+ return abs( rc );
+}
diff --git a/vc6/mbgcmptime/mbgcmptime.dsp b/vc6/mbgcmptime/mbgcmptime.dsp
new file mode 100644
index 0000000..6ad0884
--- /dev/null
+++ b/vc6/mbgcmptime/mbgcmptime.dsp
@@ -0,0 +1,194 @@
+# Microsoft Developer Studio Project File - Name="mbgcmptime" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mbgcmptime - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mbgcmptime.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mbgcmptime.mak" CFG="mbgcmptime - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mbgcmptime - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mbgcmptime - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mbgcmptime - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbgcmptime" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbgcmptime.exe"
+
+!ELSEIF "$(CFG)" == "mbgcmptime - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbgcmptime" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbgcmptime.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "mbgcmptime - Win32 Release"
+# Name "mbgcmptime - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\test\mbgcmptime\mbgcmptime.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\gpsdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbg_arch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbg_tgt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\mbg_w32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgdevio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgerror.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbggeo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgmutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgpccyc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgtime.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbgversion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pci_asic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsdev.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\usbdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\use_pack.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\words.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib
+# End Source File
+# End Target
+# End Project
diff --git a/vc6/mbgctrl/mbgctrl.dsp b/vc6/mbgctrl/mbgctrl.dsp
new file mode 100644
index 0000000..b69af7b
--- /dev/null
+++ b/vc6/mbgctrl/mbgctrl.dsp
@@ -0,0 +1,214 @@
+# Microsoft Developer Studio Project File - Name="mbgctrl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mbgctrl - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mbgctrl.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mbgctrl.mak" CFG="mbgctrl - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mbgctrl - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mbgctrl - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mbgctrl - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbgctrl" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbgctrl.exe"
+
+!ELSEIF "$(CFG)" == "mbgctrl - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbgctrl" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbgctrl.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "mbgctrl - Win32 Release"
+# Name "mbgctrl - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\deviohlp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\lan_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbgctrl\mbgctrl.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\parmgps.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\parmpcps.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\gpsdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbg_arch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbg_tgt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\mbg_w32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgdevio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgerror.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbggeo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgmutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgpccyc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgtime.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbgversion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pci_asic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsdev.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\usbdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\use_pack.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\words.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib
+# End Source File
+# End Target
+# End Project
diff --git a/vc6/mbgfasttstamp/mbgfasttstamp.dsp b/vc6/mbgfasttstamp/mbgfasttstamp.dsp
new file mode 100644
index 0000000..b25ae74
--- /dev/null
+++ b/vc6/mbgfasttstamp/mbgfasttstamp.dsp
@@ -0,0 +1,194 @@
+# Microsoft Developer Studio Project File - Name="mbgfasttstamp" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mbgfasttstamp - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mbgfasttstamp.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mbgfasttstamp.mak" CFG="mbgfasttstamp - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mbgfasttstamp - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mbgfasttstamp - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mbgfasttstamp - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbgfasttstamp" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbgfasttstamp.exe"
+
+!ELSEIF "$(CFG)" == "mbgfasttstamp - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbgfasttstamp" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbgfasttstamp.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "mbgfasttstamp - Win32 Release"
+# Name "mbgfasttstamp - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\mbgfasttstamp\mbgfasttstamp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\gpsdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbg_arch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbg_tgt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\mbg_w32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgdevio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgerror.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbggeo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgmutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgpccyc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgtime.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbgversion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pci_asic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsdev.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\usbdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\use_pack.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\words.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib
+# End Source File
+# End Target
+# End Project
diff --git a/vc6/mbggpscap/mbggpscap.dsp b/vc6/mbggpscap/mbggpscap.dsp
new file mode 100644
index 0000000..eae5591
--- /dev/null
+++ b/vc6/mbggpscap/mbggpscap.dsp
@@ -0,0 +1,194 @@
+# Microsoft Developer Studio Project File - Name="mbggpscap" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mbggpscap - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mbggpscap.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mbggpscap.mak" CFG="mbggpscap - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mbggpscap - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mbggpscap - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mbggpscap - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbggpscap" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbggpscap.exe"
+
+!ELSEIF "$(CFG)" == "mbggpscap - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbggpscap" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbggpscap.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "mbggpscap - Win32 Release"
+# Name "mbggpscap - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\mbggpscap\mbggpscap.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\gpsdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbg_arch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbg_tgt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\mbg_w32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgdevio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgerror.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbggeo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgmutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgpccyc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgtime.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbgversion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pci_asic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsdev.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\usbdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\use_pack.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\words.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib
+# End Source File
+# End Target
+# End Project
diff --git a/vc6/mbghrtime/mbghrtime.dsp b/vc6/mbghrtime/mbghrtime.dsp
new file mode 100644
index 0000000..6d5415b
--- /dev/null
+++ b/vc6/mbghrtime/mbghrtime.dsp
@@ -0,0 +1,194 @@
+# Microsoft Developer Studio Project File - Name="mbghrtime" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mbghrtime - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mbghrtime.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mbghrtime.mak" CFG="mbghrtime - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mbghrtime - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mbghrtime - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mbghrtime - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbghrtime" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbghrtime.exe"
+
+!ELSEIF "$(CFG)" == "mbghrtime - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbghrtime" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbghrtime.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "mbghrtime - Win32 Release"
+# Name "mbghrtime - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\mbghrtime\mbghrtime.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\gpsdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbg_arch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbg_tgt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\mbg_w32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgdevio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgerror.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbggeo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgmutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgpccyc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\mbgtime.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbgversion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pci_asic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsdev.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpsutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\usbdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\use_pack.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\words.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib
+# End Source File
+# End Target
+# End Project
diff --git a/vc6/mbgstatus/mbgstatus.dsp b/vc6/mbgstatus/mbgstatus.dsp
new file mode 100644
index 0000000..a6b640e
--- /dev/null
+++ b/vc6/mbgstatus/mbgstatus.dsp
@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="mbgstatus" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mbgstatus - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mbgstatus.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mbgstatus.mak" CFG="mbgstatus - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mbgstatus - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mbgstatus - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mbgstatus - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbgstatus" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbgstatus.exe"
+
+!ELSEIF "$(CFG)" == "mbgstatus - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbgstatus" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbgstatus.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "mbgstatus - Win32 Release"
+# Name "mbgstatus - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\ctry.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\ctrydttm.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\lan_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbgstatus\mbgstatus.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\pcpslstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\common\toolutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\mbglib\win32\wingetopt.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib
+# End Source File
+# End Target
+# End Project
diff --git a/vc6/mbgtools-win.dsw b/vc6/mbgtools-win.dsw
new file mode 100644
index 0000000..d3fb367
--- /dev/null
+++ b/vc6/mbgtools-win.dsw
@@ -0,0 +1,89 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "mbgcmptime"=".\mbgcmptime\mbgcmptime.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "mbgctrl"=".\mbgctrl\mbgctrl.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "mbgfasttstamp"=".\mbgfasttstamp\mbgfasttstamp.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "mbggpscap"=".\mbggpscap\mbggpscap.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "mbghrtime"=".\mbghrtime\mbghrtime.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "mbgstatus"=".\mbgstatus\mbgstatus.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+