summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Burnicki <martin.burnicki@meinberg.de>2015-05-11 12:00:00 +0200
committerMartin Burnicki <martin.burnicki@meinberg.de>2015-05-11 12:00:00 +0200
commit410110dc4388f33ecb4d9e30f2627df00e5ba7d5 (patch)
tree521471a235a7186b8c3d01dadcf84e5a7f2c86f7
parent753f5617f666edb989500b2d9aab3656328f18c3 (diff)
downloadntptest-410110dc4388f33ecb4d9e30f2627df00e5ba7d5.tar.gz
ntptest-410110dc4388f33ecb4d9e30f2627df00e5ba7d5.zip
Fix a bug and support continuous monitoring1.1
Fix a bug where the xmt/rcv packets were interchanged when printed. Support continuous monitoring (-Z), e.g. for leap second tests. Account for updated library files.
-rwxr-xr-xREADME95
-rwxr-xr-xmbglib/common/gpsdefs.h10872
-rwxr-xr-xmbglib/common/mbg_ntp_test_util.c365
-rwxr-xr-xmbglib/common/mbg_ntp_test_util.h204
-rwxr-xr-xmbglib/common/mbg_tgt.h99
-rwxr-xr-xmbglib/common/mbgntp.h291
-rwxr-xr-xmbglib/common/use_pack.h43
-rwxr-xr-xmbglib/common/words.h90
-rwxr-xr-xntptest.c116
9 files changed, 11937 insertions, 238 deletions
diff --git a/README b/README
index 063f3f1..6940ea3 100755
--- a/README
+++ b/README
@@ -1,12 +1,18 @@
-$Id: README 1.1 2014/04/01 15:13:58 martin REL_M $
+$Id: README 1.2 2015/05/11 12:38:59 martin REL_M $
This is the README file for the ntptest tool which is similar to ntpdate
which comes with the NTP software package. It sends an NTP request packet
to an NTP server, receives the response packet, and evaluates the returned
information.
-Just unpack the tar.gz source code archive, cd into the extracted directory
-and run "make" to build the executable.
+Beside these basic functions ntptest supports a monitoring mode which can
+be enabled with -Z. In monitoring mode 4 req/s are sent to a server and
+the status as well as offset *changes* from the initial offset are printed
+in 1 line. This is useful e.g. for leap second monitoring of remote devices.
+
+
+To build the executable just unpack the tar.gz source code archive, cd into
+the extracted directory, and run "make".
Then type "./ntptest -?" to get some usage information.
@@ -16,7 +22,7 @@ specified on the command line, e.g.:
------------------------------------------------------------------------------
#ntptest> ./ntptest 172.16.100.43
-ntptest v1.0, (c) Meinberg 2014, contact: <martin.burnicki@meinberg.de>
+ntptest v1.1, (c) Meinberg 2014-2015, contact: <martin.burnicki@meinberg.de>
Host 172.16.100.43
Request packet:
@@ -27,24 +33,24 @@ Request packet:
Ref time: 00000000.00000000 1900-01-01 00:00:00.000000000
Org time (T1): 00000000.00000000 1900-01-01 00:00:00.000000000
Rcv time (T2): 00000000.00000000 1900-01-01 00:00:00.000000000
- Xmt time (T3): D6E541C5.A4A2B11A 2014-04-01 13:46:45.643107479
- Curr time (T4): D6E541C5.A4A2B11A 2014-04-01 13:46:45.643107479
+ Xmt time (T3): D8FB20A9.28DD1D49 2015-05-11 12:35:53.159623937
+ Curr time (T4): D8FB20A9.28DD1D49 2015-05-11 12:35:53.159623937
Response packet:
mode 4, version 4, leap_ind 0, stratum 1, poll 6, prec 237
root delay: 00000000 (0.0000 s)
- root dispersion: 00000008 (0.0001 s/s)
- reference id: 0053524D (MRS)
- Ref time: D6E541C4.09622D44 2014-04-01 13:46:44.036654309
- Org time (T1): D6E541C5.A4A2B11A 2014-04-01 13:46:45.643107479
- Rcv time (T2): D6E541C5.A4AEDE9B 2014-04-01 13:46:45.643293297
- Xmt time (T3): D6E541C5.A4B2FEF1 2014-04-01 13:46:45.643356260
- Curr time (T4): D6E541C5.A4BF6278 2014-04-01 13:46:45.643545297
-
-turnaround: 437.818 (437.818..437.818) us (T4 - T1)
-server latency: 62.963 (0.000..62.963) us (T3 - T2)
-computed delay: 374.855 (374.855..374.855) us ((T4 – T1) – (T3 – T2))
-computed offset: -1.610 (-1.610..-1.610) us (((T2 – T1) + (T3 – T4)) / 2)
+ root dispersion: 0000001B (0.0004 s/s)
+ reference id: 00535050 (PPS)
+ Ref time: D8FB209C.5420AD42 2015-05-11 12:35:40.328623608
+ Org time (T1): D8FB20A9.28DD1D49 2015-05-11 12:35:53.159623937
+ Rcv time (T2): D8FB20A9.28E01E8F 2015-05-11 12:35:53.159669790
+ Xmt time (T3): D8FB20A9.28E213DE 2015-05-11 12:35:53.159699670
+ Curr time (T4): D8FB20A9.28EF8182 2015-05-11 12:35:53.159904569
+
+turnaround: 280.632 (280.632..280.632) us (T4 - T1)
+server latency: 29.880 (29.880..29.880) us (T3 - T2)
+computed delay: 250.752 (250.752..250.752) us ((T4 - T1) - (T3 - T2))
+computed offset: -79.524 (-79.524..-79.524) us (((T2 - T1) + (T3 - T4)) / 2)
------------------------------------------------------------------------------
The output shows the contents of the request packet sent to the NTP server,
@@ -101,3 +107,56 @@ Please note:
to at least 64 seconds (-s 64), which is the minimum polling interval
used by the NTP reference implementation.
+
+Monitoring offset and status
+----------------------------
+
+The -Z option can be used to monitor how the offset and leap status of a
+remote NTP node changes over time. In the example below the ntptest program
+runs on a system which doesn't observe a leap second and monitors a remote
+Linux system which inserts a leap second by stepping the time back by -1 s
+at the beginning of the leap second, so the displayed offset step from ~0 ms
+to ~-1000 ms.
+
+-----------------------------------------------------------------------------------
+#ntptest> ./ntptest 172.16.100.44
+
+ntptest v1.1, (c) Meinberg 2014-2015, contact: <martin.burnicki@meinberg.de>
+
+Host 172.16.100.44, running continuously
+...
+...
+D93DABFD.3C940F7A 2015-06-30 23:59:57.236634223, st 1, leap 1, offs[ms]: -0.066
+D93DABFD.7CBF93CB 2015-06-30 23:59:57.487298237, st 1, leap 1, offs[ms]: -0.054
+D93DABFD.BCEABA70 2015-06-30 23:59:57.737956669, st 1, leap 1, offs[ms]: -0.030
+D93DABFD.FD785D4F 2015-06-30 23:59:57.990117866, st 1, leap 1, offs[ms]: -0.079
+
+D93DABFE.3DAAF300 2015-06-30 23:59:58.240889728, st 1, leap 1, offs[ms]: -0.049
+D93DABFE.7DD24649 2015-06-30 23:59:58.491489785, st 1, leap 1, offs[ms]: -0.062
+D93DABFE.BDF982C1 2015-06-30 23:59:58.742088482, st 1, leap 1, offs[ms]: -0.047
+D93DABFE.FE291448 2015-06-30 23:59:58.992814319, st 1, leap 1, offs[ms]: -0.058
+
+D93DABFF.3E533E34 2015-06-30 23:59:59.243457687, st 1, leap 1, offs[ms]: -0.065
+D93DABFF.7E7DFE72 2015-06-30 23:59:59.494110014, st 1, leap 1, offs[ms]: -0.117
+D93DABFF.BEAD838E 2015-06-30 23:59:59.744835111, st 1, leap 1, offs[ms]: -0.053
+D93DABFF.FED45A02 2015-06-30 23:59:59.995427728, st 1, leap 1, offs[ms]: -0.070
+
+D93DABFF.3F00B222 2015-06-30 23:59:59.246104367, st 1, leap 1, offs[ms]: -1000.079 <-- leap second
+D93DABFF.7F31D91A 2015-06-30 23:59:59.496854370, st 1, leap 1, offs[ms]: -1000.068 <-- leap second
+D93DABFF.BF59FF26 2015-06-30 23:59:59.747466990, st 1, leap 1, offs[ms]: -1000.073 <-- leap second
+D93DABFF.FF80E16F 2015-06-30 23:59:59.998060311, st 1, leap 1, offs[ms]: -1000.070 <-- leap second
+
+D93DAC00.3FC6AA4F 2015-07-01 00:00:00.249125141, st 1, leap 1, offs[ms]: -1000.093
+D93DAC00.800046AE 2015-07-01 00:00:00.500004212, st 1, leap 1, offs[ms]: -1000.074
+D93DAC00.C02F7195 2015-07-01 00:00:00.750723933, st 1, leap 0, offs[ms]: -1000.086
+
+D93DAC01.008052E2 2015-07-01 00:00:01.001958065, st 1, leap 0, offs[ms]: -1000.088
+D93DAC01.40B4429D 2015-07-01 00:00:01.252750552, st 1, leap 0, offs[ms]: -1000.085
+D93DAC01.80F0F7A7 2015-07-01 00:00:01.503676870, st 1, leap 0, offs[ms]: -1000.097
+D93DAC01.C124AAC3 2015-07-01 00:00:01.754465744, st 1, leap 0, offs[ms]: -1000.111
+
+D93DAC02.0155AB27 2015-07-01 00:00:02.005213448, st 1, leap 0, offs[ms]: -1000.095
+D93DAC02.4189C881 2015-07-01 00:00:02.256008655, st 1, leap 0, offs[ms]: -1000.101
+D93DAC02.81C3CDCF 2015-07-01 00:00:02.506893981, st 1, leap 0, offs[ms]: -1000.077
+-----------------------------------------------------------------------------------
+
diff --git a/mbglib/common/gpsdefs.h b/mbglib/common/gpsdefs.h
new file mode 100755
index 0000000..9a3e1e1
--- /dev/null
+++ b/mbglib/common/gpsdefs.h
@@ -0,0 +1,10872 @@
+
+/**************************************************************************
+ *
+ * $Id: gpsdefs.h 1.122 2014/07/29 08:57:44 martin REL_M $
+ *
+ * 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.122 2014/07/29 08:57:44 martin
+ * Updated doxygen comments.
+ * Revision 1.121 2014/07/17 09:41:50 martin
+ * Introduced XMR_HOLDOVER_STATUS, MBG_GPIO_STATUS,
+ * and associated definitions.
+ * Huge update and cleanup on doxygen comments.
+ * Revision 1.120 2014/05/27 08:34:40 martin
+ * Fixed braces in some _mbg_rcvr_is_..() macros.
+ * Definitions used with extended network cfg, VST, and SHS.
+ * Introduced XMR_HOLDOVER_STATUS.
+ * Introduced programmable output mode POUT_GPIO.
+ * Introduced oscillator type OCXO_SQ.
+ * Defined some new baud rates.
+ * Defines for IEEE C37.118.1-2011 CTQ.
+ * Support for new model SCG by paul.
+ * Support new model PPG180.
+ * New SCU control masks.
+ * New GNSS flag MBG_GNSS_FLAG_SAT_INFO_IDX_SUPP_SER.
+ * DEFAULT_MULTI_REF_NAMES_SHORT added by udo.
+ * Definitions used for NTP configuration by thomas-b and marvin.
+ * MBG_NET_ADDR structures changed to MBG_IP_ADDR, and
+ * associated symbols defined by marvin.
+ * Huge rework of comments in doxygen format.
+ * Revision 1.119 2013/12/05 10:13:13 daniel
+ * Support new PTP_CFG_FLAGS for 1-step-L2 and 1-step-P2P support
+ * Revision 1.118 2013/11/19 13:38:35 martin
+ * Added LAN_IF_TYPE_RSC.
+ * Revision 1.117 2013/11/18 14:13:39 martin
+ * Support model LNE_GB.
+ * Revision 1.116 2013/11/11 09:46:11 martin
+ * New PTP configuration flags PTP_CFG_SUPP_MCAST_SLAVE_FLAG and
+ * PTP_CFG_CAN_BE_MULTICAST_SLAVE, plus associated bit masks.
+ * New XMR_INST_FLAGS and XMR_INST_FLAG_MASKS defined by andre.
+ * Fixes for big-endian targets.
+ * Updated doxygen comments.
+ * Revision 1.115 2013/10/02 15:19:28 martin
+ * Changed PTP_CFG_SETTINGS::vlan_cfg back to a reserved field,
+ * and removed associated flag and flag mask.
+ * Revision 1.114 2013/09/25 11:02:10 martin
+ * Support models MRI, BPE, GLN180PEX, N2X, RSC180.
+ * Added feature bit GPS_FEAT_NTP.
+ * Enhanced VLAN configuration structures.
+ * Started to support IPv6.
+ * Renamed PTP_CFG_SETTINGS field "profile" to "selected_presets".
+ * Renamed PTP_CFG_INFO field "supp_profiles" to "supp_opt_ext".
+ * New PTP role PTP_ROLE_BOTH_MASTER.
+ * New PTP flag PTP_FLAG_ONE_STEP.
+ * Added some new PTP_CFG_FLAGS flags.
+ * Added PTP_OPT_EXTS and associated definitions.
+ * Added PTP_PRESETS and associated definitions.
+ * Added "tzdl" field to PTP_POWER_PROFILE_CFG.
+ * Made reserved PTP_CFG_SETTINGS field to "opt_ext" field.
+ * Made reserved PTP_CFG_SETTINGS field to "vlan_cfg" field.
+ * Made reserved PTP_STATE field to "parent_clock_class" and "parent_clock_accuracy".
+ * Definitions for MULTI_REF_EXT_OSC added by Andre.
+ * String initializers for supported HaveQuick formats added by Gregoire.
+ * Lots of doxygen changes.
+ * 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 multi ref 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 multi ref 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 multi ref 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
+
+/**
+ * @brief GNSS satellite numbers
+ *
+ * @todo: Check if MAX_SVNO_GLN is 94 instead of 95, and thus
+ * N_SVNO_GLN is 30 instead of 31, as reported by Wikipedia.
+ */
+enum GNSS_SVNOS
+{
+ MIN_SVNO_GPS = 1, ///< min. GPS satellite PRN number
+ MAX_SVNO_GPS = 32, ///< max. GPS satellite PRN number
+ N_SVNO_GPS = 32, ///< max. number of active GPS satellites
+
+ MIN_SVNO_WAAS = 33, ///< min. WAAS satellite number
+ MAX_SVNO_WAAS = 64, ///< max. WAAS satellite number
+ N_SVNO_WAAS = 32, ///< max. number of active WAAS satellites
+
+ MIN_SVNO_GLONASS = 65, ///< min. Glonass satellite number (64 + sat slot ID)
+ MAX_SVNO_GLONASS = 95, ///< max. Glonass satellite number (64 + sat slot ID)
+ N_SVNO_GLONASS = 31 ///< max. number of active Glonass satellites
+};
+
+// for compatibility with GPS-only software:
+#define MIN_SVNO MIN_SVNO_GPS ///< min. SV number
+#define MAX_SVNO MAX_SVNO_GPS ///< max. SV number
+#define N_SVNO N_SVNO_GPS ///< 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
+ *
+ * @see ::GPS_CMD_CODES
+ * @see ::PC_GPS_CMD_CODES
+ */
+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 Status of buffered (non-volatile) 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
+ *
+ * Related to data received from the satellites, or data derived thereof.
+ *
+ * All '0' means OK, single bits set to '1' indicate
+ * the associated type of GPS data is not available.
+ *
+ * @see ::BVAR_FLAGS
+ */
+typedef uint16_t BVAR_STAT;
+
+#define _mbg_swab_bvar_stat( _p ) _mbg_swab16( (_p) )
+
+
+/**
+ * @brief Enumeration of flag bits used to define ::BVAR_FLAGS
+ *
+ * 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.
+ *
+ * @see ::BVAR_STAT
+ * @see ::BVAR_FLAGS
+ * @see ::BVAR_FLAG_NAMES
+ */
+enum BVAR_FLAG_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
+};
+
+
+/**
+ * @brief Bit masks associated with ::BVAR_FLAG_BITS
+ *
+ * Used with ::BVAR_STAT.
+ *
+ * @see ::BVAR_STAT
+ * @see ::BVAR_FLAG_BITS
+ * @see ::BVAR_FLAG_NAMES
+ */
+enum BVAR_FLAGS
+{
+ BVAR_CFGH_INVALID = ( 1UL << BVAR_BIT_CFGH_INVALID ), ///< see ::BVAR_BIT_CFGH_INVALID
+ BVAR_ALM_NOT_COMPLETE = ( 1UL << BVAR_BIT_ALM_NOT_COMPLETE ), ///< see ::BVAR_BIT_ALM_NOT_COMPLETE
+ BVAR_UTC_INVALID = ( 1UL << BVAR_BIT_UTC_INVALID ), ///< see ::BVAR_BIT_UTC_INVALID
+ BVAR_IONO_INVALID = ( 1UL << BVAR_BIT_IONO_INVALID ), ///< see ::BVAR_BIT_IONO_INVALID
+ BVAR_RCVR_POS_INVALID = ( 1UL << BVAR_BIT_RCVR_POS_INVALID ), ///< see ::BVAR_BIT_RCVR_POS_INVALID
+};
+
+#define BVAR_MASK ( ( 1UL << N_BVAR_BIT ) - 1 ) ///< Bit mask for all defined bits
+
+
+/**
+ * @brief String initializer for ::BVAR_STAT flag names
+ *
+ * @see ::BVAR_STAT
+ * @see ::BVAR_FLAG_BITS
+ * @see ::BVAR_FLAGS
+ */
+#define BVAR_FLAG_NAMES \
+{ \
+ "Sat. config and health", \
+ "Almanac", \
+ "UTC offset", \
+ "Ionospheric correction", \
+ "Receiver position" \
+}
+
+/** @} defgroup 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 @ref 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 (optional)
+ 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 @ref GPS_FEATURE_MASKS
+ FIXED_FREQ_INFO fixed_freq; ///< optional non-standard fixed frequency, may be 0 if not supported
+ 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
+ *
+ * @see @ref GPS_MODEL_NAMES
+ * @see ::DEFAULT_GPS_MODEL_NAMES
+ */
+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,
+ GPS_MODEL_MRI,
+ GPS_MODEL_BPE,
+ GPS_MODEL_GLN180PEX,
+ GPS_MODEL_N2X,
+ GPS_MODEL_RSC180,
+ GPS_MODEL_LNE_GB,
+ GPS_MODEL_PPG180,
+ GPS_MODEL_SCG,
+ N_GPS_MODEL
+ /* If new model codes are added then care must be taken
+ * to update the associated string initializers GPS_MODEL_NAMES
+ * and GPS_MODEL_NAME_TABLE accordingly, and to check whether
+ * the classification macros also cover the new model names.
+ */
+};
+
+
+
+/**
+ * @brief Model name strings used with Meinberg devices
+ *
+ * String initializers for each of the device models
+ * enumerated in ::GPS_MODEL_CODES.
+ *
+ * @see ::GPS_MODEL_CODES
+ * @see ::DEFAULT_GPS_MODEL_NAMES
+ *
+ * @anchor GPS_MODEL_NAMES @{ */
+
+#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"
+#define GPS_MODEL_NAME_MRI "MRI"
+#define GPS_MODEL_NAME_BPE "BPE"
+#define GPS_MODEL_NAME_GLN180PEX "GLN180PEX"
+#define GPS_MODEL_NAME_N2X "N2X"
+#define GPS_MODEL_NAME_RSC180 "RSC180"
+#define GPS_MODEL_NAME_LNE_GB "LNE_GB"
+#define GPS_MODEL_NAME_PPG180 "PPG180"
+#define GPS_MODEL_NAME_SCG "SCG"
+
+/** @} anchor GPS_MODEL_NAMES */
+
+
+
+/**
+ * @brief An initializer for a table of device names
+ *
+ * Can be used to initialize an array of ::N_GPS_MODEL
+ * type name strings.
+ *
+ * @note Including the trailing 0, each name must not
+ * exceed ::GPS_ID_STR_SIZE chars.
+ *
+ * @see ::GPS_MODEL_CODES
+ * @see @ref GPS_MODEL_NAMES
+ */
+#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, \
+ GPS_MODEL_NAME_MRI, \
+ GPS_MODEL_NAME_BPE, \
+ GPS_MODEL_NAME_GLN180PEX, \
+ GPS_MODEL_NAME_N2X, \
+ GPS_MODEL_NAME_RSC180, \
+ GPS_MODEL_NAME_LNE_GB, \
+ GPS_MODEL_NAME_PPG180, \
+ GPS_MODEL_NAME_SCG \
+}
+
+
+
+/**
+ * @brief Definitions used to classify devices and built-in features
+ *
+ * @see ::GPS_MODEL_CODES
+ * @see ::GPS_BUILTIN_FEATURE_BITS
+ * @see @ref GPS_BUILTIN_FEATURE_MASKS
+ *
+ * @anchor GPS_BUILTIN_FEATURE_DEFS @{ */
+
+
+/**
+ * @brief Enumeration of classifiers and built-in features
+ *
+ * @see ::GPS_MODEL_CODES
+ * @see @ref GPS_BUILTIN_FEATURE_MASKS
+ */
+enum GPS_BUILTIN_FEATURE_BITS
+{
+ GPS_BIT_MODEL_IS_GPS,
+ GPS_BIT_MODEL_IS_GNSS,
+ GPS_BIT_MODEL_IS_TCR,
+ GPS_BIT_MODEL_IS_DCF_AM,
+ GPS_BIT_MODEL_IS_DCF_PZF,
+ GPS_BIT_MODEL_IS_MSF,
+ GPS_BIT_MODEL_IS_JJY,
+ GPS_BIT_MODEL_IS_WWV,
+
+ GPS_BIT_MODEL_IS_LNO,
+ GPS_BIT_MODEL_IS_SCU,
+
+ GPS_BIT_MODEL_HAS_BVAR_STAT,
+ GPS_BIT_MODEL_HAS_POS_XYZ,
+ GPS_BIT_MODEL_HAS_POS_LLA,
+ GPS_BIT_MODEL_HAS_TZDL,
+ GPS_BIT_MODEL_HAS_ANT_INFO,
+ GPS_BIT_MODEL_HAS_ENABLE_FLAGS,
+ GPS_BIT_MODEL_HAS_STAT_INFO,
+ GPS_BIT_MODEL_HAS_ANT_CABLE_LENGTH,
+ GPS_BIT_MODEL_HAS_GPS_IGNORE_LOCK,
+ GPS_BIT_MODEL_HAS_XMR_HOLDOVER_INTV,
+ GPS_BIT_MODEL_HAS_GNSS_MODE,
+
+ N_GPS_BIT_MODEL
+};
+
+
+
+/**
+ * @brief Bit masks associated with classifiers and built-in features
+ *
+ * @see ::GPS_MODEL_CODES
+ * @see ::GPS_BUILTIN_FEATURE_BITS
+ *
+ * @anchor GPS_BUILTIN_FEATURE_MASKS @{ */
+
+#define GPS_MODEL_IS_GPS ( 1UL << GPS_BIT_MODEL_IS_GPS ) ///< see ::GPS_BIT_MODEL_IS_GPS
+#define GPS_MODEL_IS_GNSS ( 1UL << GPS_BIT_MODEL_IS_GNSS ) ///< see ::GPS_BIT_MODEL_IS_GNSS
+#define GPS_MODEL_IS_TCR ( 1UL << GPS_BIT_MODEL_IS_TCR ) ///< see ::GPS_BIT_MODEL_IS_TCR
+#define GPS_MODEL_IS_DCF_AM ( 1UL << GPS_BIT_MODEL_IS_DCF_AM ) ///< see ::GPS_BIT_MODEL_IS_DCF_AM
+#define GPS_MODEL_IS_DCF_PZF ( 1UL << GPS_BIT_MODEL_IS_DCF_PZF ) ///< see ::GPS_BIT_MODEL_IS_DCF_PZF
+#define GPS_MODEL_IS_MSF ( 1UL << GPS_BIT_MODEL_IS_MSF ) ///< see ::GPS_BIT_MODEL_IS_MSF
+#define GPS_MODEL_IS_JJY ( 1UL << GPS_BIT_MODEL_IS_JJY ) ///< see ::GPS_BIT_MODEL_IS_JJY
+#define GPS_MODEL_IS_WWV ( 1UL << GPS_BIT_MODEL_IS_WWV ) ///< see ::GPS_BIT_MODEL_IS_WWV
+
+#define GPS_MODEL_IS_LNO ( 1UL << GPS_BIT_MODEL_IS_LNO ) ///< see ::GPS_BIT_MODEL_IS_LNO
+#define GPS_MODEL_IS_SCU ( 1UL << GPS_BIT_MODEL_IS_SCU ) ///< see ::GPS_BIT_MODEL_IS_SCU
+
+#define GPS_MODEL_HAS_BVAR_STAT ( 1UL << GPS_BIT_MODEL_HAS_BVAR_STAT ) ///< see ::GPS_BIT_MODEL_HAS_BVAR_STAT
+#define GPS_MODEL_HAS_POS_XYZ ( 1UL << GPS_BIT_MODEL_HAS_POS_XYZ ) ///< see ::GPS_BIT_MODEL_HAS_POS_XYZ
+#define GPS_MODEL_HAS_POS_LLA ( 1UL << GPS_BIT_MODEL_HAS_POS_LLA ) ///< see ::GPS_BIT_MODEL_HAS_POS_LLA
+#define GPS_MODEL_HAS_TZDL ( 1UL << GPS_BIT_MODEL_HAS_TZDL ) ///< see ::GPS_BIT_MODEL_HAS_TZDL
+#define GPS_MODEL_HAS_ANT_INFO ( 1UL << GPS_BIT_MODEL_HAS_ANT_INFO ) ///< see ::GPS_BIT_MODEL_HAS_ANT_INFO
+#define GPS_MODEL_HAS_ENABLE_FLAGS ( 1UL << GPS_BIT_MODEL_HAS_ENABLE_FLAGS ) ///< see ::GPS_BIT_MODEL_HAS_ENABLE_FLAGS
+#define GPS_MODEL_HAS_STAT_INFO ( 1UL << GPS_BIT_MODEL_HAS_STAT_INFO ) ///< see ::GPS_BIT_MODEL_HAS_STAT_INFO
+#define GPS_MODEL_HAS_ANT_CABLE_LENGTH ( 1UL << GPS_BIT_MODEL_HAS_ANT_CABLE_LENGTH ) ///< see ::GPS_BIT_MODEL_HAS_ANT_CABLE_LENGTH
+#define GPS_MODEL_HAS_GPS_IGNORE_LOCK ( 1UL << GPS_BIT_MODEL_HAS_GPS_IGNORE_LOCK ) ///< see ::GPS_BIT_MODEL_HAS_GPS_IGNORE_LOCK
+#define GPS_MODEL_HAS_XMR_HOLDOVER_INTV ( 1UL << GPS_BIT_MODEL_HAS_XMR_HOLDOVER_INTV ) ///< see ::GPS_BIT_MODEL_HAS_XMR_HOLDOVER_INTV
+
+#define GPS_MODEL_HAS_GNSS_MODE ( 1UL << GPS_BIT_MODEL_HAS_GNSS_MODE ) ///< see ::GPS_BIT_MODEL_HAS_GNSS_MODE
+
+//##+++++ TODO: should we use an extra flag?
+#define GPS_MODEL_HAS_POS ( GPS_MODEL_HAS_POS_XYZ | GPS_MODEL_HAS_POS_LLA )
+
+/** @} anchor GPS_BUILTIN_FEATURE_MASKS */
+
+
+#if 0 //##++ more potential builtin features and classifiers
+
+ GPS_MODEL_HAS_CFGH | \
+ GPS_MODEL_HAS_ALM | \
+ GPS_MODEL_HAS_EPH | \
+ GPS_MODEL_HAS_UTC | \
+ GPS_MODEL_HAS_IONO \
+
+#define GPS_MODEL_HAS_AUTO_ON // --
+#define GPS_MODEL_HAS_AUTO_OFF // --
+#define GPS_MODEL_HAS_SW_REV // deprecated, use only if ri not supported
+#define GPS_MODEL_HAS_BVAR_STAT // req
+#define GPS_MODEL_HAS_TIME // ?
+#define GPS_MODEL_HAS_POS_XYZ // GPS_MODEL_IS_GPS, GPS_MODEL_HAS_POS, GPS_MODEL_HAS_POS_XYZ ?
+#define GPS_MODEL_HAS_POS_LLA // GPS_MODEL_IS_GPS, GPS_MODEL_HAS_POS, GPS_MODEL_HAS_POS_LLA ?
+#define GPS_MODEL_HAS_TZDL // req
+#define GPS_MODEL_HAS_PORT_PARM // deprecated, use only if ri not supported
+#define GPS_MODEL_HAS_SYNTH // ri GPS_HAS_SYNTH
+#define GPS_MODEL_HAS_ANT_INFO // GPS_MODEL_IS_GPS, also GNSS, or req?
+#define GPS_MODEL_HAS_UCAP // ri n_ucap
+#define GPS_MODEL_HAS_ENABLE_FLAGS // req
+#define GPS_MODEL_HAS_STAT_INFO // req
+#define GPS_MODEL_HAS_SWITCH_PARMS // deprecated, use ...
+#define GPS_MODEL_HAS_STRING_PARMS // deprecated, use ...
+#define GPS_MODEL_HAS_ANT_CABLE_LENGTH // GPS_MODEL_IS_GPS, also GNSS, or req?
+#define GPS_MODEL_HAS_SYNC_OUTAGE_DELAY // custom
+#define GPS_MODEL_HAS_PULSE_INFO // custom
+#define GPS_MODEL_HAS_OPT_FEATURES // deprecated, use ri
+#define GPS_MODEL_HAS_IRIG_TX_SETTINGS // ri GPS_HAS_IRIG_TX
+#define GPS_MODEL_HAS_RECEIVER_INFO // --
+#define GPS_MODEL_HAS_STR_TYPE_INFO_IDX // ri n_str_type
+#define GPS_MODEL_HAS_PORT_INFO_IDX // ri n_com
+#define GPS_MODEL_HAS_PORT_SETTINGS_IDX // ri n_com
+#define GPS_MODEL_HAS_POUT_INFO_IDX // ri n_pout
+#define GPS_MODEL_HAS_POUT_SETTINGS_IDX // ri n_pout
+#define GPS_MODEL_HAS_IRIG_TX_INFO // ri GPS_HAS_IRIG_TX
+#define GPS_MODEL_HAS_MULTI_REF_SETTINGS // ri GPS_HAS_MULTI_REF
+#define GPS_MODEL_HAS_MULTI_REF_INFO // ri GPS_HAS_MULTI_REF
+#define GPS_MODEL_HAS_ROM_CSUM // ?
+#define GPS_MODEL_HAS_MULTI_REF_STATUS // ri ...
+#define GPS_MODEL_HAS_RCV_TIMEOUT // ri ...
+#define GPS_MODEL_HAS_IGNORE_LOCK // ?
+#define GPS_MODEL_HAS_IRIG_RX_SETTINGS // ri ...
+#define GPS_MODEL_HAS_IRIG_RX_INFO // ri ...
+#define GPS_MODEL_HAS_REF_OFFS // ri ...
+#define GPS_MODEL_HAS_DEBUG_STATUS //
+#define GPS_MODEL_HAS_XMR_SETTINGS_IDX //
+#define GPS_MODEL_HAS_XMR_INFO_IDX //
+#define GPS_MODEL_HAS_XMR_STATUS_IDX //
+#define GPS_MODEL_HAS_OPT_SETTINGS //
+#define GPS_MODEL_HAS_OPT_INFO //
+#define GPS_MODEL_HAS_CLR_UCAP_BUFF //
+#define GPS_MODEL_HAS_TIME_SCALE //
+#define GPS_MODEL_HAS_NAV_ENG_SETTINGS //
+#define GPS_MODEL_HAS_RAW_IRIG_DATA //
+#define GPS_MODEL_HAS_GPIO_CFG_LIMITS //
+#define GPS_MODEL_HAS_GPIO_INFO_IDX //
+#define GPS_MODEL_HAS_GPIO_SETTINGS_IDX //
+#define GPS_MODEL_HAS_XMR_INSTANCES //
+#define GPS_MODEL_HAS_CLR_EVT_LOG //
+#define GPS_MODEL_HAS_NUM_EVT_LOG_ENTRIES //
+#define GPS_MODEL_HAS_FIRST_EVT_LOG_ENTRY //
+#define GPS_MODEL_HAS_NEXT_EVT_LOG_ENTRY //
+#define GPS_MODEL_HAS_LNO_STATUS //
+#define GPS_MODEL_HAS_IMS_STATE //
+#define GPS_MODEL_HAS_IMS_SENSOR_STATE_IDX //
+#define GPS_MODEL_HAS_XMR_HOLDOVER_INTV //
+#define GPS_MODEL_HAS_HAVEQUICK_RX_SETTINGS //
+#define GPS_MODEL_HAS_HAVEQUICK_RX_INFO //
+#define GPS_MODEL_HAS_HAVEQUICK_TX_SETTINGS //
+#define GPS_MODEL_HAS_HAVEQUICK_TX_INFO //
+#define GPS_MODEL_HAS_PTP_CFG //
+#define GPS_MODEL_HAS_PTP_STATE //
+#define GPS_MODEL_HAS_PTP_UC_MASTER_CFG_LIMITS //
+#define GPS_MODEL_HAS_PTP_UC_MASTER_CFG //
+#define GPS_MODEL_HAS_NTP_GLB_CFG //
+#define GPS_MODEL_HAS_NTP_CLNT_MODE_CFG //
+#define GPS_MODEL_HAS_NTP_SRV_MODE_CFG //
+#define GPS_MODEL_HAS_NTP_PEER_SETTINGS_IDX //
+#define GPS_MODEL_HAS_NTP_SYS_STATE //
+#define GPS_MODEL_HAS_NTP_PEER_STATE_IDX //
+#define GPS_MODEL_HAS_SHS //
+#define GPS_MODEL_HAS_SHS_STATUS //
+#define GPS_MODEL_HAS_NET_GLB_CFG //
+#define GPS_MODEL_HAS_NET_DNS_SRVR //
+#define GPS_MODEL_HAS_NET_DNS_SRC_DOM //
+#define GPS_MODEL_HAS_NET_STAT_DNS_SRVR //
+#define GPS_MODEL_HAS_NET_STAT_DNS_SRC_DOM //
+#define GPS_MODEL_HAS_GNSS_SAT_INFO_IDX //
+
+#define GPS_MODEL_HAS_CFGH //
+#define GPS_MODEL_HAS_ALM //
+#define GPS_MODEL_HAS_EPH //
+#define GPS_MODEL_HAS_UTC //
+#define GPS_MODEL_HAS_IONO //
+#define GPS_MODEL_HAS_ASCII_MSG //
+
+#define GPS_MODEL_HAS_GLNS_ALM //
+#define GPS_MODEL_HAS_GNSS_SAT_INFO //
+#define GPS_MODEL_HAS_GNSS_MODE //
+
+#define GPS_MODEL_HAS_IP4_SETTINGS //
+#define GPS_MODEL_HAS_LAN_IF_INFO //
+#define GPS_MODEL_HAS_IP4_STATE //
+
+#define GPS_MODEL_HAS_SCU_STAT //
+
+#define GPS_MODEL_HAS_CRYPTED_PACKET //
+#define GPS_MODEL_HAS_CRYPTED_RAW_PACKET //
+
+#define GPS_MODEL_HAS_SECU_INFO //
+#define GPS_MODEL_HAS_SECU_SETTINGS //
+#define GPS_MODEL_HAS_SECU_PUBLIC_KEY //
+
+#endif //##++ more potential builtin features and classifiers
+
+
+
+/**
+ * @brief Common builtin features of all GPS receivers
+ */
+#define BUILTIN_FEAT_GPS \
+( \
+ GPS_MODEL_IS_GPS | \
+ GPS_MODEL_HAS_BVAR_STAT | \
+ GPS_MODEL_HAS_POS_XYZ | \
+ GPS_MODEL_HAS_POS_LLA | \
+ GPS_MODEL_HAS_TZDL | \
+ GPS_MODEL_HAS_ANT_INFO | \
+ GPS_MODEL_HAS_ENABLE_FLAGS | \
+ GPS_MODEL_HAS_STAT_INFO | \
+ GPS_MODEL_HAS_ANT_CABLE_LENGTH \
+)
+
+
+/**
+ * @brief Common builtin features of all GNSS receivers
+ *
+ * GNSS includes GPS but optionally other satellite systems,
+ * and the associated API.
+ */
+#define BUILTIN_FEAT_GNSS \
+( \
+ BUILTIN_FEAT_GPS | \
+ GPS_MODEL_IS_GNSS | \
+ GPS_MODEL_HAS_GNSS_MODE \
+)
+
+
+
+/**
+ * @brief Definitions of builtin features per device type
+ *
+ * @see ::GPS_MODEL_CODES
+ * @see @ref GPS_MODEL_BUILTIN_FEATURES
+ *
+ * @anchor GPS_MODEL_BUILTIN_FEATURE_MASKS @{ */
+
+#define BUILTIN_FEAT_GPS166 ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS167 ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS167SV ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS167PC ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS167PCI ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS163 ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS168PCI ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS161 ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS169PCI ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_TCR167PCI ( 0 )
+#define BUILTIN_FEAT_GPS164 ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS170PCI ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_PZF511 ( 0 )
+#define BUILTIN_FEAT_GPS170 ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_TCR511 ( 0 )
+#define BUILTIN_FEAT_AM511 ( 0 )
+#define BUILTIN_FEAT_MSF511 ( 0 )
+#define BUILTIN_FEAT_GRC170 ( 0 )
+#define BUILTIN_FEAT_GPS170PEX ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS162 ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_PTP270PEX ( 0 )
+#define BUILTIN_FEAT_FRC511PEX ( 0 )
+#define BUILTIN_FEAT_GEN170 ( 0 )
+#define BUILTIN_FEAT_TCR170PEX ( 0 )
+#define BUILTIN_FEAT_WWVB511 ( 0 )
+#define BUILTIN_FEAT_MGR170 ( 0 )
+#define BUILTIN_FEAT_JJY511 ( 0 )
+#define BUILTIN_FEAT_PZF600 ( 0 )
+#define BUILTIN_FEAT_TCR600 ( 0 )
+#define BUILTIN_FEAT_GPS180 ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GLN170 ( 0 )
+#define BUILTIN_FEAT_GPS180PEX ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_TCR180PEX ( 0 )
+#define BUILTIN_FEAT_PZF180PEX ( 0 )
+#define BUILTIN_FEAT_MGR180 ( 0 )
+#define BUILTIN_FEAT_MSF600 ( 0 )
+#define BUILTIN_FEAT_WWVB600 ( 0 )
+#define BUILTIN_FEAT_JJY600 ( 0 )
+#define BUILTIN_FEAT_GPS180HS ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_GPS180AMC ( BUILTIN_FEAT_GPS )
+#define BUILTIN_FEAT_ESI180 ( 0 )
+#define BUILTIN_FEAT_CPE180 ( 0 )
+#define BUILTIN_FEAT_LNO180 ( 0 )
+#define BUILTIN_FEAT_GRC180 ( 0 )
+#define BUILTIN_FEAT_LIU ( 0 )
+#define BUILTIN_FEAT_DCF600HS ( 0 )
+#define BUILTIN_FEAT_DCF600RS ( 0 )
+#define BUILTIN_FEAT_MRI ( 0 )
+#define BUILTIN_FEAT_BPE ( 0 )
+#define BUILTIN_FEAT_GLN180PEX ( BUILTIN_FEAT_GNSS )
+#define BUILTIN_FEAT_N2X ( 0 )
+#define BUILTIN_FEAT_RSC180 ( 0 )
+#define BUILTIN_FEAT_LNE_GB ( 0 )
+#define BUILTIN_FEAT_PPG180 ( 0 )
+#define BUILTIN_FEAT_SCG ( 0 )
+
+/** @} anchor GPS_MODEL_BUILTIN_FEATURE_MASKS */
+
+
+
+/**
+ * @brief Initializer for a table of built-in features per device
+ *
+ * Last entry is all zero to indicated end of table.
+ *
+ * @see ::GPS_MODEL_CODES
+ * @see @ref GPS_MODEL_BUILTIN_FEATURE_MASKS
+ */
+#define GPS_MODEL_BUILTIN_FEATURES \
+{ \
+ { GPS_MODEL_GPS166, BUILTIN_FEAT_GPS166 }, \
+ { GPS_MODEL_GPS167, BUILTIN_FEAT_GPS167 }, \
+ { GPS_MODEL_GPS167SV, BUILTIN_FEAT_GPS167SV }, \
+ { GPS_MODEL_GPS167PC, BUILTIN_FEAT_GPS167PC }, \
+ { GPS_MODEL_GPS167PCI, BUILTIN_FEAT_GPS167PCI }, \
+ { GPS_MODEL_GPS163, BUILTIN_FEAT_GPS163 }, \
+ { GPS_MODEL_GPS168PCI, BUILTIN_FEAT_GPS168PCI }, \
+ { GPS_MODEL_GPS161, BUILTIN_FEAT_GPS161 }, \
+ { GPS_MODEL_GPS169PCI, BUILTIN_FEAT_GPS169PCI }, \
+ { GPS_MODEL_TCR167PCI, BUILTIN_FEAT_TCR167PCI }, \
+ { GPS_MODEL_GPS164, BUILTIN_FEAT_GPS164 }, \
+ { GPS_MODEL_GPS170PCI, BUILTIN_FEAT_GPS170PCI }, \
+ { GPS_MODEL_PZF511, BUILTIN_FEAT_PZF511 }, \
+ { GPS_MODEL_GPS170, BUILTIN_FEAT_GPS170 }, \
+ { GPS_MODEL_TCR511, BUILTIN_FEAT_TCR511 }, \
+ { GPS_MODEL_AM511, BUILTIN_FEAT_AM511 }, \
+ { GPS_MODEL_MSF511, BUILTIN_FEAT_MSF511 }, \
+ { GPS_MODEL_GRC170, BUILTIN_FEAT_GRC170 }, \
+ { GPS_MODEL_GPS170PEX, BUILTIN_FEAT_GPS170PEX }, \
+ { GPS_MODEL_GPS162, BUILTIN_FEAT_GPS162 }, \
+ { GPS_MODEL_PTP270PEX, BUILTIN_FEAT_PTP270PEX }, \
+ { GPS_MODEL_FRC511PEX, BUILTIN_FEAT_FRC511PEX }, \
+ { GPS_MODEL_GEN170, BUILTIN_FEAT_GEN170 }, \
+ { GPS_MODEL_TCR170PEX, BUILTIN_FEAT_TCR170PEX }, \
+ { GPS_MODEL_WWVB511, BUILTIN_FEAT_WWVB511 }, \
+ { GPS_MODEL_MGR170, BUILTIN_FEAT_MGR170 }, \
+ { GPS_MODEL_JJY511, BUILTIN_FEAT_JJY511 }, \
+ { GPS_MODEL_PZF600, BUILTIN_FEAT_PZF600 }, \
+ { GPS_MODEL_TCR600, BUILTIN_FEAT_TCR600 }, \
+ { GPS_MODEL_GPS180, BUILTIN_FEAT_GPS180 }, \
+ { GPS_MODEL_GLN170, BUILTIN_FEAT_GLN170 }, \
+ { GPS_MODEL_GPS180PEX, BUILTIN_FEAT_GPS180PEX }, \
+ { GPS_MODEL_TCR180PEX, BUILTIN_FEAT_TCR180PEX }, \
+ { GPS_MODEL_PZF180PEX, BUILTIN_FEAT_PZF180PEX }, \
+ { GPS_MODEL_MGR180, BUILTIN_FEAT_MGR180 }, \
+ { GPS_MODEL_MSF600, BUILTIN_FEAT_MSF600 }, \
+ { GPS_MODEL_WWVB600, BUILTIN_FEAT_WWVB600 }, \
+ { GPS_MODEL_JJY600, BUILTIN_FEAT_JJY600 }, \
+ { GPS_MODEL_GPS180HS, BUILTIN_FEAT_GPS180HS }, \
+ { GPS_MODEL_GPS180AMC, BUILTIN_FEAT_GPS180AMC }, \
+ { GPS_MODEL_ESI180, BUILTIN_FEAT_ESI180 }, \
+ { GPS_MODEL_CPE180, BUILTIN_FEAT_CPE180 }, \
+ { GPS_MODEL_LNO180, BUILTIN_FEAT_LNO180 }, \
+ { GPS_MODEL_GRC180, BUILTIN_FEAT_GRC180 }, \
+ { GPS_MODEL_LIU, BUILTIN_FEAT_LIU }, \
+ { GPS_MODEL_DCF600HS, BUILTIN_FEAT_DCF600HS }, \
+ { GPS_MODEL_DCF600RS, BUILTIN_FEAT_DCF600RS }, \
+ { GPS_MODEL_MRI, BUILTIN_FEAT_MRI }, \
+ { GPS_MODEL_BPE, BUILTIN_FEAT_BPE }, \
+ { GPS_MODEL_GLN180PEX, BUILTIN_FEAT_GLN180PEX }, \
+ { GPS_MODEL_N2X, BUILTIN_FEAT_N2X }, \
+ { GPS_MODEL_RSC180, BUILTIN_FEAT_RSC180 }, \
+ { GPS_MODEL_LNE_GB, BUILTIN_FEAT_LNE_GB }, \
+ { GPS_MODEL_PPG180, BUILTIN_FEAT_PPG180 }, \
+ { GPS_MODEL_SCG, BUILTIN_FEAT_SCG }, \
+ { 0, 0 } \
+}
+
+/** @} anchor GPS_BUILTIN_FEATURE_DEFS */
+
+
+
+/*
+ * 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 Known oscillator types used with ::RECEIVER_INFO::osc_type
+ *
+ * The sequence of codes does NOT reflect the order of quality.
+ * New oscillator type codes will just be appended to the enumeration.
+ *
+ * @see ::DEFAULT_GPS_OSC_NAMES
+ * @see ::DEFAULT_GPS_OSC_QUALITY_IDX
+ */
+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,
+ GPS_OSC_OCXO_SQ,
+ N_GPS_OSC
+};
+
+
+/**
+ * @brief Oscillator type name string initializer
+ *
+ * The sequence and number of oscillator names has to
+ * correspond to the enumeration in ::GPS_OSC_TYPES
+ *
+ * @see ::GPS_OSC_TYPES
+ * @see ::DEFAULT_GPS_OSC_QUALITY_IDX
+ */
+#define DEFAULT_GPS_OSC_NAMES \
+{ \
+ "[unknown]", \
+ "TCXO LQ", \
+ "TCXO", \
+ "OCXO LQ", \
+ "OCXO MQ", \
+ "OCXO HQ", \
+ "OCXO XHQ", \
+ "RUBIDIUM", \
+ "TCXO MQ", \
+ "OCXO DHQ", \
+ "OCXO SQ" \
+}
+
+
+/**
+ * @brief Oscillator quality index
+ *
+ * Can be used to initialize a index array
+ * (e.g. "int osc_quality_idx[N_GPS_OSC];")
+ * allowing to display the oscillator types
+ * ordered by quality
+ *
+ * @see ::GPS_OSC_TYPES
+ * @see ::DEFAULT_GPS_OSC_NAMES
+ */
+#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_SQ, \
+ 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 simple LAN IPv4 interface, superseded by ::GPS_FEAT_NET_CFG
+ GPS_FEAT_MULTI_REF, ///< has multiple input sources with priorities, superseded by ::GPS_FEAT_XMULTI_REF
+
+ 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, supersedes ::GPS_FEAT_MULTI_REF
+ 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 (::MBG_IRIG_CTRL_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 (::MBG_RAW_IRIG_DATA)
+ GPS_FEAT_RAW_IRIG_TIME, ///< supports reading decoded IRIG time (::PCPS_IRIG_TIME)
+ GPS_FEAT_PTP_UNICAST, ///< has PTP Unicast support
+ GPS_FEAT_GPIO, ///< has general purpose inputs/outputs
+ GPS_FEAT_XMRS_MULT_INSTC, ///< multiple XMRS instances of the same ref type supported (::XMULTI_REF_INSTANCES)
+ GPS_FEAT_10MHZ_DISBD, ///< 10 MHz output is always disabled
+ GPS_FEAT_EVT_LOG, ///< Event logging supported
+
+ GPS_FEAT_IMS, ///< supports IMS data structures
+ GPS_FEAT_HAVEQUICK, ///< supports HaveQuick structures
+ GPS_FEAT_NTP, ///< supports NTP structures
+ GPS_FEAT_NET_CFG, ///< supports extended network interface configuration, supersedes ::GPS_FEAT_LAN_IP4
+ GPS_FEAT_VST, ///< supports VST (Versatile Storage) API and structures
+ GPS_FEAT_SHS, ///< supports SHS (Secure Hybrid System) API and 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", \
+ "NTP", \
+ "Ext. Network Config", \
+ "Versatile Storage", \
+ "SHS" \
+}
+
+
+/**
+ * @brief Bit masks used with ::RECEIVER_INFO::features
+ *
+ * @see ::GPS_FEATURE_BITS
+ *
+ * @anchor GPS_FEATURE_MASKS @{ */
+
+#define GPS_HAS_PPS ( 1UL << GPS_FEAT_PPS ) ///< see ::GPS_FEAT_PPS
+#define GPS_HAS_PPM ( 1UL << GPS_FEAT_PPM ) ///< see ::GPS_FEAT_PPM
+#define GPS_HAS_SYNTH ( 1UL << GPS_FEAT_SYNTH ) ///< see ::GPS_FEAT_SYNTH
+#define GPS_HAS_DCFMARKS ( 1UL << GPS_FEAT_DCFMARKS ) ///< see ::GPS_FEAT_DCFMARKS
+#define GPS_HAS_IRIG_TX ( 1UL << GPS_FEAT_IRIG_TX ) ///< see ::GPS_FEAT_IRIG_TX
+#define GPS_HAS_IRIG_RX ( 1UL << GPS_FEAT_IRIG_RX ) ///< see ::GPS_FEAT_IRIG_RX
+#define GPS_HAS_LAN_IP4 ( 1UL << GPS_FEAT_LAN_IP4 ) ///< see ::GPS_FEAT_LAN_IP4
+#define GPS_HAS_MULTI_REF ( 1UL << GPS_FEAT_MULTI_REF ) ///< see ::GPS_FEAT_MULTI_REF
+
+#define GPS_HAS_RCV_TIMEOUT ( 1UL << GPS_FEAT_RCV_TIMEOUT ) ///< see ::GPS_FEAT_RCV_TIMEOUT
+#define GPS_HAS_IGNORE_LOCK ( 1UL << GPS_FEAT_IGNORE_LOCK ) ///< see ::GPS_FEAT_IGNORE_LOCK
+#define GPS_HAS_5_MHZ ( 1UL << GPS_FEAT_5_MHZ ) ///< see ::GPS_FEAT_5_MHZ
+#define GPS_HAS_XMULTI_REF ( 1UL << GPS_FEAT_XMULTI_REF ) ///< see ::GPS_FEAT_XMULTI_REF
+#define GPS_HAS_OPT_SETTINGS ( 1UL << GPS_FEAT_OPT_SETTINGS ) ///< see ::GPS_FEAT_OPT_SETTINGS
+#define GPS_HAS_TIME_SCALE ( 1UL << GPS_FEAT_TIME_SCALE ) ///< see ::GPS_FEAT_TIME_SCALE
+#define GPS_HAS_IRIG_CTRL_BITS ( 1UL << GPS_FEAT_IRIG_CTRL_BITS ) ///< see ::GPS_FEAT_IRIG_CTRL_BITS
+#define GPS_HAS_PTP ( 1UL << GPS_FEAT_PTP ) ///< see ::GPS_FEAT_PTP
+
+#define GPS_HAS_NAV_ENGINE_SETTINGS ( 1UL << GPS_FEAT_NAV_ENGINE_SETTINGS ) ///< see ::GPS_FEAT_NAV_ENGINE_SETTINGS
+#define GPS_HAS_RAW_IRIG_DATA ( 1UL << GPS_FEAT_RAW_IRIG_DATA ) ///< see ::GPS_FEAT_RAW_IRIG_DATA
+#define GPS_HAS_RAW_IRIG_TIME ( 1UL << GPS_FEAT_RAW_IRIG_TIME ) ///< see ::GPS_FEAT_RAW_IRIG_TIME
+#define GPS_HAS_PTP_UNICAST ( 1UL << GPS_FEAT_PTP_UNICAST ) ///< see ::GPS_FEAT_PTP_UNICAST
+#define GPS_HAS_GPIO ( 1UL << GPS_FEAT_GPIO ) ///< see ::GPS_FEAT_GPIO
+#define GPS_HAS_XMRS_MULT_INSTC ( 1UL << GPS_FEAT_XMRS_MULT_INSTC ) ///< see ::GPS_FEAT_XMRS_MULT_INSTC
+#define GPS_HAS_10MHZ_DISBD ( 1UL << GPS_FEAT_10MHZ_DISBD ) ///< see ::GPS_FEAT_10MHZ_DISBD
+#define GPS_HAS_EVT_LOG ( 1UL << GPS_FEAT_EVT_LOG ) ///< see ::GPS_FEAT_EVT_LOG
+
+#define GPS_HAS_IMS ( 1UL << GPS_FEAT_IMS ) ///< see ::GPS_FEAT_IMS
+#define GPS_HAS_HAVEQUICK ( 1UL << GPS_FEAT_HAVEQUICK ) ///< see ::GPS_FEAT_HAVEQUICK
+#define GPS_HAS_NTP ( 1UL << GPS_FEAT_NTP ) ///< see ::GPS_FEAT_NTP
+#define GPS_HAS_NET_CFG ( 1UL << GPS_FEAT_NET_CFG ) ///< see ::GPS_FEAT_NET_CFG
+#define GPS_HAS_VST ( 1UL << GPS_FEAT_VST ) ///< see ::GPS_FEAT_VST
+#define GPS_HAS_SHS ( 1UL << GPS_FEAT_SHS ) ///< see ::GPS_FEAT_SHS
+
+
+// the next ones are special since they just shadow another flag:
+#define GPS_HAS_REF_OFFS GPS_HAS_IRIG_RX ///< always supported with IRIG inputs, see ::GPS_HAS_IRIG_RX
+#define GPS_HAS_DEBUG_STATUS GPS_HAS_IRIG_RX ///< always supported with IRIG inputs, see ::GPS_HAS_IRIG_RX
+
+/** @} anchor GPS_FEATURE_MASKS */
+
+
+/*
+ * 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 used to define ::RECEIVER_INFO_FLAG_MASKS
+ */
+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
+};
+
+
+/**
+ * @brief Bit masks to be used with ::RECEIVER_INFO::flags
+ */
+enum RECEIVER_INFO_FLAG_MASKS
+{
+ GPS_OSC_CFG_SUPP = ( 1UL << GPS_BIT_OSC_CFG_SUPP ), ///< see ::GPS_BIT_OSC_CFG_SUPP
+ GPS_IRIG_FO_IN = ( 1UL << GPS_BIT_IRIG_FO_IN ), ///< see ::GPS_BIT_IRIG_FO_IN
+ GPS_HAS_FPGA = ( 1UL << GPS_BIT_HAS_FPGA ) ///< see ::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, 1/::RECEIVER_INFO::ticks_per_sec units
+
+} 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..365, or 366 in case of leap year
+ 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, or 60 in case of inserted leap second
+ int32_t frac; ///< fractions of a second, 1/::RECEIVER_INFO::ticks_per_sec units
+ int32_t offs_from_utc; ///< local time's offset from %UTC
+ uint16_t status; ///< status flags, see ::TM_GPS_STATUS_BIT_MASKS
+
+} 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 flag bits used to define ::TM_GPS_STATUS_BIT_MASKS
+ *
+ * These bits report info on the time conversion from GPS time to %UTC
+ * and/or local time as well as device status info.
+ *
+ * @see ::TM_GPS_STATUS_BIT_MASKS
+ */
+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
+};
+
+
+/**
+ * @brief Status flag masks 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.
+ *
+ * @see ::TM_GPS_STATUS_BITS
+ */
+enum TM_GPS_STATUS_BIT_MASKS
+{
+ TM_UTC = ( 1UL << TM_BIT_UTC ), ///< see ::TM_BIT_UTC
+ TM_LOCAL = ( 1UL << TM_BIT_LOCAL ), ///< see ::TM_BIT_LOCAL
+ TM_DL_ANN = ( 1UL << TM_BIT_DL_ANN ), ///< see ::TM_BIT_DL_ANN
+ TM_DL_ENB = ( 1UL << TM_BIT_DL_ENB ), ///< see ::TM_BIT_DL_ENB
+ TM_LS_ANN = ( 1UL << TM_BIT_LS_ANN ), ///< see ::TM_BIT_LS_ANN
+ TM_LS_ENB = ( 1UL << TM_BIT_LS_ENB ), ///< see ::TM_BIT_LS_ENB
+ TM_LS_ANN_NEG = ( 1UL << TM_BIT_LS_ANN_NEG ), ///< see ::TM_BIT_LS_ANN_NEG
+ TM_INVT = ( 1UL << TM_BIT_INVT ), ///< see ::TM_BIT_INVT
+
+ TM_EXT_SYNC = ( 1UL << TM_BIT_EXT_SYNC ), ///< see ::TM_BIT_EXT_SYNC
+ TM_HOLDOVER = ( 1UL << TM_BIT_HOLDOVER ), ///< see ::TM_BIT_HOLDOVER
+ TM_ANT_SHORT = ( 1UL << TM_BIT_ANT_SHORT ), ///< see ::TM_BIT_ANT_SHORT
+ TM_NO_WARM = ( 1UL << TM_BIT_NO_WARM ), ///< see ::TM_BIT_NO_WARM
+ TM_ANT_DISCONN = ( 1UL << TM_BIT_ANT_DISCONN ), ///< see ::TM_BIT_ANT_DISCONN
+ TM_SYN_FLAG = ( 1UL << TM_BIT_SYN_FLAG ), ///< see ::TM_BIT_SYN_FLAG
+ TM_NO_SYNC = ( 1UL << TM_BIT_NO_SYNC ), ///< see ::TM_BIT_NO_SYNC
+ TM_NO_POS = ( 1UL << TM_BIT_NO_POS ) ///< see ::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 ) )
+
+
+
+#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 A position in cartesian coordinates
+ *
+ * Usually earth centered, earth fixed (ECEF) coordinates.
+ */
+ 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 A geographic position based on latitude, longitude, and altitude
+ *
+ * The geographic position associated to specific cartesian coordinates
+ * depends on the characteristics of the ellipsoid used for the computation,
+ * the so-called geographic datum. GPS uses the WGS84 (World Geodetic System
+ * from 1984) ellipsoid by default.
+ */
+ 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_SYNTH_RANGE the value of freq must not exceed 1000, so
+ * the output frequency is limited to 10 MHz (see ::MAX_SYNTH_FREQ_VAL).
+ *
+ * @{ */
+
+#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 Hz; 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
+
+/** @} defgroup 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 */ \
+}
+
+/** @} defgroup group_tzdl */
+
+
+
+/**
+ * @brief Antenna status and error at reconnect information
+ *
+ * The structure below reflects the status of the antenna,
+ * the times of last disconnect/reconnect, and the board's
+ * clock offset when it has synchronized again 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 units
+
+} 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
+};
+
+
+
+/**
+ * @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
+ * (flags == ::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 ); \
+}
+
+
+/**
+ * @brief Codes used with ::ENABLE_FLAGS
+ **/
+enum ENABLE_FLAGS_CODES
+{
+ EF_OFF = 0x00, ///< associated outputs off until synchronized
+
+ EF_SERIAL_BOTH = 0x03, ///< both serial ports on, use with ::ENABLE_FLAGS::serial
+ EF_PULSES_BOTH = 0x03, ///< both pulses P_SEC and P_MIN on, use with ::ENABLE_FLAGS::pulses
+ EF_FREQ_ALL = 0x07, ///< all fixed freq. outputs on, use with ::ENABLE_FLAGS::freq
+ EF_SYNTH = 0x01 ///< synthesizer on, use with ::ENABLE_FLAGS::synth
+};
+
+
+
+#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 serial port's baud rate
+ *
+ * @see ::MBG_BAUD_RATES
+ */
+ typedef int32_t BAUD_RATE;
+
+ /**
+ * @brief Indices used to identify a parameter in the framing string
+ *
+ * @see ::MBG_FRAMING_STRS
+ */
+ enum MBG_FRAMING_STR_IDXS { 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, see ::MBG_BAUD_RATES
+ char framing[4]; ///< ASCIIZ framing string, e.g. "8N1" or "7E2", see ::MBG_FRAMING_STRS
+ 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 Enumeration of serial port baud rates
+ *
+ * @note Most clock models and/or serial ports don't support all defined baud rates.
+ *
+ * @see ::MBG_BAUD_RATES
+ * @see ::MBG_BAUD_RATE_MASKS
+ */
+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,
+ MBG_BAUD_RATE_57600,
+ MBG_BAUD_RATE_115200,
+ MBG_BAUD_RATE_230400,
+ MBG_BAUD_RATE_460800,
+ MBG_BAUD_RATE_921600,
+ N_MBG_BAUD_RATES ///< the number of known baud rates
+};
+
+/**
+ * @brief An initializer for a table of baud rate values
+ *
+ * These values can be used with ::COM_PARM::baud_rate, if the device
+ * supports the particular baud rate.
+ *
+ * The values must correspond to the enumeration ::MBG_BAUD_RATE_CODES
+ *
+ * @see ::MBG_BAUD_RATE_CODES
+ */
+#define MBG_BAUD_RATES \
+{ \
+ 300L, \
+ 600L, \
+ 1200L, \
+ 2400L, \
+ 4800L, \
+ 9600L, \
+ 19200L, \
+ 38400L, \
+ 57600L, \
+ 115200L, \
+ 230400L, \
+ 460800L, \
+ 921600L \
+}
+
+/**
+ * @brief An initializer for a table of baud rate strings
+ *
+ * The values must correspond to the enumeration ::MBG_BAUD_RATE_CODES
+ *
+ * @see ::MBG_BAUD_RATE_CODES
+ */
+#define MBG_BAUD_STRS \
+{ \
+ "300", \
+ "600", \
+ "1200", \
+ "2400", \
+ "4800", \
+ "9600", \
+ "19200", \
+ "38400", \
+ "57600", \
+ "115200", \
+ "230400", \
+ "460800", \
+ "921600" \
+}
+
+/**
+ * @brief Bit masks associated with baud rates enumerated in ::MBG_BAUD_RATE_CODES
+ *
+ * These bit masks are used e.g. with ::PORT_INFO::supp_baud_rates to
+ * determine which baud rates are supported by a particular serial port.
+ *
+ * @see ::MBG_BAUD_RATE_CODES
+ * @see ::MBG_FRAMING_MASKS
+ */
+enum MBG_BAUD_RATE_MASKS
+{
+ MBG_PORT_HAS_300 = ( 1UL << MBG_BAUD_RATE_300 ), ///< see ::MBG_BAUD_RATE_300
+ MBG_PORT_HAS_600 = ( 1UL << MBG_BAUD_RATE_600 ), ///< see ::MBG_BAUD_RATE_600
+ MBG_PORT_HAS_1200 = ( 1UL << MBG_BAUD_RATE_1200 ), ///< see ::MBG_BAUD_RATE_1200
+ MBG_PORT_HAS_2400 = ( 1UL << MBG_BAUD_RATE_2400 ), ///< see ::MBG_BAUD_RATE_2400
+ MBG_PORT_HAS_4800 = ( 1UL << MBG_BAUD_RATE_4800 ), ///< see ::MBG_BAUD_RATE_4800
+ MBG_PORT_HAS_9600 = ( 1UL << MBG_BAUD_RATE_9600 ), ///< see ::MBG_BAUD_RATE_9600
+ MBG_PORT_HAS_19200 = ( 1UL << MBG_BAUD_RATE_19200 ), ///< see ::MBG_BAUD_RATE_19200
+ MBG_PORT_HAS_38400 = ( 1UL << MBG_BAUD_RATE_38400 ), ///< see ::MBG_BAUD_RATE_38400
+ MBG_PORT_HAS_57600 = ( 1UL << MBG_BAUD_RATE_57600 ), ///< see ::MBG_BAUD_RATE_57600
+ MBG_PORT_HAS_115200 = ( 1UL << MBG_BAUD_RATE_115200 ), ///< see ::MBG_BAUD_RATE_115200
+ MBG_PORT_HAS_230400 = ( 1UL << MBG_BAUD_RATE_230400 ), ///< see ::MBG_BAUD_RATE_230400
+ MBG_PORT_HAS_460800 = ( 1UL << MBG_BAUD_RATE_460800 ), ///< see ::MBG_BAUD_RATE_460800
+ MBG_PORT_HAS_921600 = ( 1UL << MBG_BAUD_RATE_921600 ) ///< see ::MBG_BAUD_RATE_921600
+};
+
+
+/**
+ * @brief Enumeration of all known serial port framings
+ *
+ * @note Most clock models and/or serial ports don't support all defined framing types.
+ *
+ * @see ::MBG_FRAMING_STRS
+ */
+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 known framings
+};
+
+/**
+ * @brief An initializer for a table of known framing strings
+ *
+ * These values can be used with ::COM_PARM::framing, if the device
+ * supports the particular framing.
+ *
+ * The values must correspond to the enumeration ::MBG_FRAMING_CODES
+ *
+ * @see ::MBG_FRAMING_CODES
+ * @see ::MBG_FRAMING_MASKS
+ * @see ::MBG_FRAMING_STR_IDXS
+ */
+#define MBG_FRAMING_STRS \
+{ \
+ "7N2", \
+ "7E1", \
+ "7E2", \
+ "8N1", \
+ "8N2", \
+ "8E1", \
+ "7O1", \
+ "7O2", \
+ "8O1", \
+ "8E2" \
+}
+
+/**
+ * @brief Bit masks associated with framings enumerated in ::MBG_FRAMING_CODES
+ *
+ * These bit masks are used e.g. with ::PORT_INFO::supp_framings to
+ * determine which framings are supported by a particular serial port.
+ *
+ * @see ::MBG_FRAMING_CODES
+ * @see ::MBG_FRAMING_STRS
+ */
+enum MBG_FRAMING_MASKS
+{
+ MBG_PORT_HAS_7N2 = ( 1UL << MBG_FRAMING_7N2 ), ///< see ::MBG_FRAMING_7N2
+ MBG_PORT_HAS_7E1 = ( 1UL << MBG_FRAMING_7E1 ), ///< see ::MBG_FRAMING_7E1
+ MBG_PORT_HAS_7E2 = ( 1UL << MBG_FRAMING_7E2 ), ///< see ::MBG_FRAMING_7E2
+ MBG_PORT_HAS_8N1 = ( 1UL << MBG_FRAMING_8N1 ), ///< see ::MBG_FRAMING_8N1
+ MBG_PORT_HAS_8N2 = ( 1UL << MBG_FRAMING_8N2 ), ///< see ::MBG_FRAMING_8N2
+ MBG_PORT_HAS_8E1 = ( 1UL << MBG_FRAMING_8E1 ), ///< see ::MBG_FRAMING_8E1
+ MBG_PORT_HAS_7O1 = ( 1UL << MBG_FRAMING_7O1 ), ///< see ::MBG_FRAMING_7O1
+ MBG_PORT_HAS_7O2 = ( 1UL << MBG_FRAMING_7O2 ), ///< see ::MBG_FRAMING_7O2
+ MBG_PORT_HAS_8O1 = ( 1UL << MBG_FRAMING_8O1 ), ///< see ::MBG_FRAMING_8O1
+ MBG_PORT_HAS_8E2 = ( 1UL << MBG_FRAMING_8E2 ) ///< see ::MBG_FRAMING_8E2
+};
+
+
+
+/**
+ * @brief Definitions used with the Meinberg binary protocol
+ *
+ * @anchor GPS_BIN_PROT_DEFS @{ */
+
+/**
+ * @brief Framing used with the binary protocol
+ *
+ * Different data length, or parity settings would corrupt
+ * the binary data.
+ */
+#define MBG_DEFAULT_FRAMING "8N1"
+
+/**
+ * @brief The standard baud rate used for the binary protocol
+ *
+ * This is supported by most devices. Some new devices may also
+ * support ::MBG_DEFAULT_BAUDRATE_HS
+ */
+#define MBG_DEFAULT_BAUDRATE 19200L
+
+/**
+ * @brief The high speed baud rate used for the binary protocol
+ *
+ * This is not supported by older devices which work
+ * with ::MBG_DEFAULT_BAUDRATE only.
+ */
+#define MBG_DEFAULT_BAUDRATE_HS 115200L
+
+
+/**
+ * @brief Strings used to force connection settings for the binary protocol
+ *
+ * If a device supports this and receives one of these ASCII strings
+ * then it temporarily switches the serial port to some well-known
+ * baud rate and framing appropriate for the binary protocol.
+ *
+ * @anchor GPS_BIN_PROT_CMD_STRS @{ */
+
+#define MBG_FORCE_CONN_CMD_STR "\nDFC\n" ///< switch to ::MBG_DEFAULT_BAUDRATE
+#define MBG_FORCE_CONN_HS_CMD_STR "\nDFCHS\n" ///< switch to ::MBG_DEFAULT_BAUDRATE_HS
+
+/** @} anchor GPS_BIN_PROT_CMD_STRS */
+
+/** @} anchor GPS_BIN_PROT_DEFS */
+
+
+
+/*
+ * 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; ///< reserved, don't use, currently 0
+
+} PORT_SETTINGS;
+
+#define _mbg_swab_port_settings( _p ) \
+{ \
+ _mbg_swab_com_parm( &(_p)->parm ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Flag bits used to mark 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
+};
+
+/**
+ * @brief Flag bit masks associated with ::MBG_COM_CFG_STATUS_BITS
+ *
+ * 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.
+ *
+ * @anchor MBG_COM_CFG_STATUS_MASKS @{ */
+
+#define MBG_PS_MSK_BAUD_RATE_OVR_SW ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_SW ) ///< see ::MBG_PS_BIT_BAUD_RATE_OVR_SW
+#define MBG_PS_MSK_BAUD_RATE_OVR_DEV ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_DEV ) ///< see ::MBG_PS_BIT_BAUD_RATE_OVR_DEV
+#define MBG_PS_MSK_BAUD_RATE ( 1UL << MBG_PS_BIT_BAUD_RATE ) ///< see ::MBG_PS_BIT_BAUD_RATE
+#define MBG_PS_MSK_FRAMING_OVR_SW ( 1UL << MBG_PS_BIT_FRAMING_OVR_SW ) ///< see ::MBG_PS_BIT_FRAMING_OVR_SW
+#define MBG_PS_MSK_FRAMING_OVR_DEV ( 1UL << MBG_PS_BIT_FRAMING_OVR_DEV ) ///< see ::MBG_PS_BIT_FRAMING_OVR_DEV
+#define MBG_PS_MSK_FRAMING ( 1UL << MBG_PS_BIT_FRAMING ) ///< see ::MBG_PS_BIT_FRAMING
+#define MBG_PS_MSK_HS_OVR_SW ( 1UL << MBG_PS_BIT_HS_OVR_SW ) ///< see ::MBG_PS_BIT_HS_OVR_SW
+#define MBG_PS_MSK_HS ( 1UL << MBG_PS_BIT_HS ) ///< see ::MBG_PS_BIT_HS
+#define MBG_PS_MSK_STR_TYPE_OVR_SW ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_SW ) ///< see ::MBG_PS_BIT_STR_TYPE_OVR_SW
+#define MBG_PS_MSK_STR_TYPE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_DEV ) ///< see ::MBG_PS_BIT_STR_TYPE_OVR_DEV
+#define MBG_PS_MSK_STR_TYPE ( 1UL << MBG_PS_BIT_STR_TYPE ) ///< see ::MBG_PS_BIT_STR_TYPE
+#define MBG_PS_MSK_STR_MODE_OVR_SW ( 1UL << MBG_PS_BIT_STR_MODE_OVR_SW ) ///< see ::MBG_PS_BIT_STR_MODE_OVR_SW
+#define MBG_PS_MSK_STR_MODE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_MODE_OVR_DEV ) ///< see ::MBG_PS_BIT_STR_MODE_OVR_DEV
+#define MBG_PS_MSK_STR_MODE ( 1UL << MBG_PS_BIT_STR_MODE ) ///< see ::MBG_PS_BIT_STR_MODE
+#define MBG_PS_MSK_FLAGS_OVR_SW ( 1UL << MBG_PS_BIT_FLAGS_OVR_SW ) ///< see ::MBG_PS_BIT_FLAGS_OVR_SW
+#define MBG_PS_MSK_FLAGS ( 1UL << MBG_PS_BIT_FLAGS ) ///< see ::MBG_PS_BIT_FLAGS
+
+/** @} anchor MBG_COM_CFG_STATUS_MASKS */
+
+
+
+/**
+ * @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_ports.
+ *
+ * @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_ports-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_MASKS
+ uint32_t supp_framings; ///< bit mask of framings supp. by this port, see ::MBG_FRAMING_MASKS
+ 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 ::PORT_INFO_FLAGS
+
+} 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 bits used to define ::PORT_INFO_FLAGS
+ *
+ * @see ::PORT_INFO_FLAGS
+ */
+enum PORT_INFO_FLAG_BITS
+{
+ PORT_INFO_FLAG_BIT_PORT_INVISIBLE, ///< port is used internally and should not be displayed by config apps
+ PORT_INFO_FLAG_BIT_BIN_PROT_HS, ///< port supports binary protocol at high speed, see ::MBG_DEFAULT_BAUDRATE_HS
+ N_PORT_INFO_FLAG_BITS ///< the number of defined bits
+};
+
+
+/**
+ * @brief Bit masks used with ::PORT_INFO::flags
+ *
+ * @see ::PORT_INFO_FLAG_BITS
+ */
+enum PORT_INFO_FLAGS
+{
+ PORT_INFO_FLAG_PORT_INVISIBLE = ( 1UL << PORT_INFO_FLAG_BIT_PORT_INVISIBLE ), ///< see ::PORT_INFO_FLAG_BIT_PORT_INVISIBLE
+ PORT_INFO_FLAG_BIN_PROT_HS = ( 1UL << PORT_INFO_FLAG_BIT_BIN_PROT_HS ) ///< see ::PORT_INFO_FLAG_BIT_BIN_PROT_HS
+};
+
+
+/**
+ * @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_ports.
+ *
+ * @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_ports-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 Multiple structures ::STR_TYPE_INFO_IDX should be read
+ * to retrieve all supported string types.
+ */
+typedef struct
+{
+ uint32_t supp_modes; ///< bit mask of modes supp. for this string type, see ::STR_MODE_MASKS
+ 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 Enumeration of 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.
+ * Used with ::PORT_SETTINGS::mode.
+ *
+ * @see ::STR_MODE_MASKS
+ */
+enum STR_MODES
+{
+ STR_ON_REQ, ///< transmission on request by received '?' character 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
+};
+
+
+/**
+ * @brief Bit masks associated with ::STR_MODES
+ *
+ * Used with ::STR_TYPE_INFO::supp_modes to indicate which
+ * transmission modes are supported by the particular string type.
+ *
+ * @see ::STR_MODES
+ */
+enum STR_MODE_MASKS
+{
+ MSK_STR_ON_REQ = ( 1UL << STR_ON_REQ ), ///< see ::STR_ON_REQ
+ MSK_STR_PER_SEC = ( 1UL << STR_PER_SEC ), ///< see ::STR_PER_SEC
+ MSK_STR_PER_MIN = ( 1UL << STR_PER_MIN ), ///< see ::STR_PER_MIN
+ MSK_STR_AUTO = ( 1UL << STR_AUTO ), ///< see ::STR_AUTO
+ MSK_STR_ON_REQ_SEC = ( 1UL << STR_ON_REQ_SEC ) ///< see ::STR_ON_REQ_SEC
+};
+
+
+/**
+ * @brief Initializer for short name strings associated with ::STR_MODES
+ *
+ * @see ::STR_MODES
+ */
+#define DEFAULT_SHORT_MODE_NAMES \
+{ \
+ "'?'", \
+ "1 sec", \
+ "1 min", \
+ "auto", \
+ "'?' sec" \
+}
+
+
+/**
+ * @brief Default initializers for English mode name strings
+ *
+ * Initializers for multi-language strings can be found in pcpslstr.h.
+ *
+ * @see ::STR_MODES
+ */
+#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"
+
+
+/**
+ * @brief Initializer for an English mode name string table
+ *
+ * Initializers for multi-language strings can be found in pcpslstr.h.
+ *
+ * @see ::STR_MODES
+ */
+#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 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. For devices providing
+ * a ::RECEIVER_INFO structure the number of provided COM ports
+ * is available in ::RECEIVER_INFO::n_com_ports.
+ */
+#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 two 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 */ \
+ } \
+}
+
+
+/**
+ * @brief Deprecated codes for mode of operation
+ *
+ * @deprecated These codes have been used with the
+ * deprecated ::PORT_PARM::mode. They are only still
+ * defined for compatibility with older devices.
+ *
+ * @see ::STR_MODES
+ */
+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 time 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:
+ *
+ * - Known 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: 100 bps, DCLS, SBS, complete date
+ * - \b IEEE1344: 100 bps, 1 kHz carrier, time-of-year, SBS, IEEE 1344 extensions (B120)
+ * - \b IEEE1344 DC: 100 bps, DCLS, time-of-year, SBS, IEEE 1344 extensions (B000)
+ * - \b C37.118: like IEEE 1344, but %UTC offset applied with reversed sign
+ * - \b C37.118 DC: like IEEE 1344 DC, but %UTC offset applied 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
+ *
+ * IEEE 1344 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.
+ *
+ * IEEE 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 determine that the %UTC offset has to be applied with reversed sign.
+ *
+ * For example, if a -6 hours UTC offset is transmitted in the time code:<br>
+ * IEEE 1344: (IRIG time 14:43:27 h) - (offs -6 h) = (UTC 20:43:27)<br>
+ * IEEE C37.118: (IRIG time 14:43:27 h) + (offs -6 h) = (UTC 08:43:27)<br>
+ *
+ * @see @ref MSK_ICODE_RX_UTC_OFFS_ADD and @ref MSK_ICODE_RX_UTC_OFFS_SUB
+ *
+ * @note There are 3rd party IRIG devices out there which apply the %UTC offset as specified
+ * in IEEE C37.118-2005, but claim to be compatible with IEEE 1344. So if local time is transmitted
+ * by the timecode then care must be taken that the %UTC offset is evaluated by the timecode
+ * receiver in the same way as computed by the timecode generator. Otherwise the %UTC
+ * time computed by the receiver may be <b>wrong</b>.
+ *
+ * @{ */
+
+/**
+ * @brief Known IRIG TX code formats
+ *
+ * Used with ::IRIG_SETTINGS::icode for IRIG transmitters.
+ * For IRIG receivers see ::ICODE_RX_CODES.
+ *
+ * Meinberg timecode transmitters always generate the unmodulated (DCLS)
+ * and usually the modulated timecode signals internally at the same time,
+ * so the code definitions always refer to both.
+ *
+ * @note Not all device may provide both the modulated and unmodulated
+ * signal externally.
+ */
+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
+};
+
+
+/**
+ * @brief Initializers for timecode format name strings
+ *
+ * @see ::ICODE_TX_CODES
+ */
+#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" \
+}
+
+/**
+ * @brief Initializers for short timecode format name strings
+ *
+ * @note Must not be longer than 10 printable characters
+ *
+ * @see ::ICODE_TX_CODES
+ */
+#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" \
+}
+
+
+/**
+ * @brief Initializers for English format description strings
+ *
+ * @see ::ICODE_TX_CODES
+ */
+#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" \
+}
+
+
+/**
+ * @brief Bit masks used with ::IRIG_INFO::supp_codes
+ *
+ * These bit masks are used with timecode receivers only
+ *
+ * @see @ref ICODE_TX_CODES
+ * @see @ref ICODE_RX_CODES
+ * @see @ref ICODE_RX_MASKS
+ *
+ * @anchor ICODE_TX_MASKS @{ */
+
+#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 )
+
+/** @} anchor ICODE_TX_MASKS */
+
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief A mask of IRIG formats with 100 Hz carrier
+ */
+#define MSK_ICODE_TX_100HZ \
+( \
+ MSK_ICODE_TX_E002_E112 \
+)
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief A mask of IRIG formats with 10 kHz carrier
+ */
+#define MSK_ICODE_TX_10KHZ \
+( \
+ MSK_ICODE_TX_A002_A132 | \
+ MSK_ICODE_TX_A003_A133 \
+)
+
+/**
+ * @brief A mask of IRIG formats with 100 kHz carrier
+ */
+#define MSK_ICODE_TX_100KHZ \
+( \
+ MSK_ICODE_TX_G002_G142 | \
+ MSK_ICODE_TX_G006_G146 \
+)
+
+/**
+ * @brief A mask of IRIG formats with 10 bps data rate
+ */
+#define MSK_ICODE_TX_10BPS \
+( \
+ MSK_ICODE_TX_E002_E112 \
+)
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting 10ths of seconds
+ */
+#define MSK_ICODE_TX_HAS_SEC10THS \
+( \
+ MSK_ICODE_TX_A002_A132 | \
+ MSK_ICODE_TX_A003_A133 | \
+ MSK_ICODE_TX_G002_G142 | \
+ MSK_ICODE_TX_G006_G146 \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting 100ths of seconds
+ */
+#define MSK_ICODE_TX_HAS_SEC100THS \
+( \
+ MSK_ICODE_TX_G002_G142 | \
+ MSK_ICODE_TX_G006_G146 \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting a 2 digit year number
+ */
+#define MSK_ICODE_TX_HAS_SHORT_YEAR \
+( \
+ MSK_ICODE_TX_AFNOR | \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_B006_B126 | \
+ MSK_ICODE_TX_B007_B127 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting TFOM
+ */
+#define MSK_ICODE_TX_HAS_TFOM \
+( \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting CTQ continuous time quality
+ *
+ * This has been introduced in IEEE C37.118.1-2011
+ */
+#define MSK_ICODE_TX_HAS_CTQ \
+( \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting time zone information
+ */
+#define MSK_ICODE_TX_HAS_TZI \
+( \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * @brief IRIG formats where UTC offset must be subtracted to yield UTC
+ *
+ * A mask of IRIG formats where the decoded UTC offset must be
+ * subtracted from the time decoded from the IRIG signal to yield UTC, e.g.:<br>
+ * (IRIG time 14:43:27 h) - (offs -6 h) = (UTC 20:43:27)
+ */
+#define MSK_ICODE_TX_UTC_OFFS_SUB \
+( \
+ MSK_ICODE_TX_IEEE1344 \
+)
+
+/**
+ * @brief IRIG formats where UTC offset must be added to yield UTC
+ *
+ * A mask of IRIG formats where the decoded UTC offset must be
+ * added to the time decoded from the IRIG signal to yield UTC, e.g.:<br>
+ * (IRIG time 14:43:27 h) + (offs -6 h) = (UTC 08:43:27)
+ */
+#define MSK_ICODE_TX_UTC_OFFS_ADD \
+( \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting a day of week number
+ */
+#define MSK_ICODE_TX_HAS_AFNOR_WDAY \
+( \
+ MSK_ICODE_TX_AFNOR | \
+ MSK_ICODE_TX_AFNOR_DC \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting a date (day-of-month, month)
+ */
+#define MSK_ICODE_TX_HAS_AFNOR_DATE \
+( \
+ MSK_ICODE_TX_AFNOR | \
+ MSK_ICODE_TX_AFNOR_DC \
+)
+
+
+/**
+ * @brief The default mask of IRIG formats supported by IRIG transmitters
+ *
+ * @note The formats which are actually supported should be retrieved
+ * from the device
+ */
+#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
+ *
+ * Used with ::IRIG_SETTINGS::icode for IRIG receivers.
+ * For IRIG transmitters see ::ICODE_TX_CODES.
+ *
+ * The SBS value is redundant and can easily by computed
+ * from the time-of-day, so Meinberg time code receivers
+ * usually don't evaluate the SBS field anyway, and thus
+ * it makes no difference if a code with or withour SBS
+ * is supplied.
+ */
+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
+};
+
+/**
+ * @brief Initializers for timecode format name strings
+ *
+ * @see ::ICODE_RX_CODES
+ */
+#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)" \
+}
+
+/**
+ * @brief Initializers for short timecode format name strings
+ *
+ * @note Must not be longer than 11 printable characters
+ *
+ * @see ::ICODE_RX_CODES
+ */
+#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" \
+}
+
+
+/**
+ * @brief Initializers for English format description strings
+ *
+ * @see ::ICODE_RX_CODES
+ */
+#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" \
+}
+
+/**
+ * @brief Bit masks used with ::IRIG_INFO::supp_codes
+ *
+ * These bit masks are used with timecode receivers only
+ *
+ * @see @ref ICODE_RX_CODES
+ * @see @ref ICODE_TX_CODES
+ * @see @ref ICODE_TX_MASKS
+ *
+ * @anchor ICODE_RX_MASKS @{ */
+
+#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 )
+
+/** @} anchor ICODE_RX_MASKS */
+
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief A mask of IRIG formats with 100 Hz carrier
+ */
+#define MSK_ICODE_RX_100HZ \
+( \
+ MSK_ICODE_RX_E112 | \
+ MSK_ICODE_RX_E002 \
+)
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief A mask of IRIG formats with 10 kHz carrier
+ */
+#define MSK_ICODE_RX_10KHZ \
+( \
+ MSK_ICODE_RX_A132_A133 \
+)
+
+/**
+ * @brief A mask of IRIG formats with 100 kHz carrier
+ */
+#define MSK_ICODE_RX_100KHZ \
+( \
+ MSK_ICODE_RX_G142_G146 \
+)
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief 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 \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting 10ths of seconds
+ */
+#define MSK_ICODE_RX_HAS_SEC10THS \
+( \
+ MSK_ICODE_RX_A132_A133 | \
+ MSK_ICODE_RX_A002_A003 | \
+ MSK_ICODE_RX_G142_G146 | \
+ MSK_ICODE_RX_G002_G006 \
+)
+
+/**
+ * @brief A mask of IRIG formats which support 100ths of seconds
+ */
+#define MSK_ICODE_RX_HAS_SEC100THS \
+( \
+ MSK_ICODE_RX_G142_G146 | \
+ MSK_ICODE_RX_G002_G006 \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting a 2 digit year number
+ */
+#define MSK_ICODE_RX_HAS_SHORT_YEAR \
+( \
+ 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 \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting TFOM time quality indicator
+ */
+#define MSK_ICODE_RX_HAS_TFOM \
+( \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_IEEE1344_DC | \
+ MSK_ICODE_RX_C37118 | \
+ MSK_ICODE_RX_C37118_DC \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting CTQ continuous time quality
+ *
+ * This has been introduced in IEEE C37.118.1-2011
+ */
+#define MSK_ICODE_RX_HAS_CTQ \
+( \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_IEEE1344_DC | \
+ MSK_ICODE_RX_C37118 | \
+ MSK_ICODE_RX_C37118_DC \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting 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 \
+)
+
+/**
+ * @brief IRIG formats where UTC offset must be subtracted to yield UTC
+ *
+ * A mask of IRIG formats where the decoded UTC offset must be
+ * subtracted from the time decoded from the IRIG signal to yield UTC, e.g.:<br>
+ * (IRIG time 14:43:27 h) - (offs -6 h) = (UTC 20:43:27)
+ */
+#define MSK_ICODE_RX_UTC_OFFS_SUB \
+( \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_IEEE1344_DC \
+)
+
+/**
+ * @brief IRIG formats where UTC offset must be added to yield UTC
+ *
+ * A mask of IRIG formats where the decoded UTC offset must be
+ * added to the time decoded from the IRIG signal to yield UTC, e.g.:<br>
+ * (IRIG time 14:43:27 h) + (offs -6 h) = (UTC 08:43:27)
+ */
+#define MSK_ICODE_RX_UTC_OFFS_ADD \
+( \
+ MSK_ICODE_RX_C37118 | \
+ MSK_ICODE_RX_C37118_DC \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting a day of week number
+ */
+#define MSK_ICODE_RX_HAS_AFNOR_WDAY \
+( \
+ MSK_ICODE_RX_AFNOR | \
+ MSK_ICODE_RX_AFNOR_DC \
+)
+
+/**
+ * @brief A mask of IRIG formats supporting a date (day-of-month, month)
+ */
+#define MSK_ICODE_RX_HAS_AFNOR_DATE \
+( \
+ MSK_ICODE_RX_AFNOR | \
+ MSK_ICODE_RX_AFNOR_DC \
+)
+
+
+/**
+ * @brief The default mask of IRIG formats supported by IRIG receivers
+ *
+ * @note The formats which are actually supported should be retrieved
+ * from the device
+ */
+#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
+
+/** @} defgroup group_icode */
+
+
+
+/**
+ * @brief Configuration settings of an IRIG input or output
+ *
+ * @see @ref group_icode
+ */
+typedef struct
+{
+ uint16_t icode; ///< IRIG signal code, see ::ICODE_RX_CODES and ::ICODE_TX_CODES
+ uint16_t flags; ///< see ::IFLAGS_BIT_MASKS
+
+} IRIG_SETTINGS;
+
+#define _mbg_swab_irig_settings( _p ) \
+{ \
+ _mbg_swab16( &(_p)->icode ); \
+ _mbg_swab16( &(_p)->flags ); \
+}
+
+
+
+/**
+ * @brief Flag bits used to define ::IFLAGS_BIT_MASKS
+ *
+ * @see ::IFLAGS_BIT_MASKS
+ */
+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 instead of %UTC
+ N_IFLAGS_BITS ///< number of known bits
+};
+
+
+/**
+ * @brief Bit masks used with ::IRIG_SETTINGS::flags
+ *
+ * @note The presence or absence of the ::IFLAGS_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.
+ *
+ * @see ::IFLAGS_BITS
+ */
+enum IFLAGS_BIT_MASKS
+{
+ IFLAGS_DISABLE_TFOM = ( 1UL << IFLAGS_BIT_DISABLE_TFOM ), ///< see ::IFLAGS_BIT_DISABLE_TFOM
+ IFLAGS_TX_GEN_LOCAL_TIME = ( 1UL << IFLAGS_BIT_TX_GEN_LOCAL_TIME ), ///< see ::IFLAGS_BIT_TX_GEN_LOCAL_TIME
+
+ 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; ///< see @ref ICODE_TX_MASKS and @ref ICODE_RX_MASKS
+
+} 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; ///< data header
+ 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 ); \
+}
+
+/** @} defgroup group_irig_comp */
+
+
+
+/**
+ * @brief A data type used to read the board's debug status
+ *
+ * @note This also includes IRIG decoder status.
+ *
+ * @see @ref MBG_DEBUG_STATUS_BIT_MASKS
+ */
+typedef uint32_t MBG_DEBUG_STATUS;
+
+#define _mbg_swab_debug_status( _p ) \
+ _mbg_swab32( _p )
+
+
+
+/**
+ * @brief Enumeration of flag bits used for debug status
+ *
+ * @see @ref MBG_DEBUG_STATUS_BIT_MASKS
+ */
+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 ///< The number of known bits
+};
+
+/**
+ * @brief Initializers for debug status bit strings
+ *
+ * @see ::MBG_DEBUG_STATUS_BITS
+ */
+#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" \
+}
+
+
+/**
+ * @brief Bit masks used with ::MBG_DEBUG_STATUS
+ *
+ * @see ::MBG_DEBUG_STATUS_BITS
+ *
+ * @anchor MBG_DEBUG_STATUS_BIT_MASKS @{ */
+
+#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 )
+
+/** @} anchor MBG_DEBUG_STATUS_BIT_MASKS */
+
+
+/**
+ * @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.
+ *
+ * Valid range: -::MBG_REF_OFFS_MAX..::MBG_REF_OFFS_MAX, or ::MBG_REF_OFFS_NOT_CFGD
+ *
+ * @note There's a special flag ::MBG_REF_OFFS_NOT_CFGD indicating that
+ * this parameter is unconfigured, in which case a Meinberg time code
+ * receiver refuses to synchronize to the time code signal unless a time
+ * code frame has been configured which provides the UTC offset (namely
+ * IEEE 1344 or IEEE C37.118).
+ */
+typedef int16_t MBG_REF_OFFS;
+
+#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_FLAGS
+
+} 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; ///< current settings
+ uint32_t supp_flags; ///< bit mask of supported flags, see ::MBG_OPT_FLAGS
+
+} MBG_OPT_INFO;
+
+#define _mbg_swab_mbg_opt_info( _p ) \
+{ \
+ _mbg_swab_mbg_opt_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->supp_flags ); \
+}
+
+
+/**
+ * @brief Enumeration of flag bits used to define ::MBG_OPT_FLAGS
+ */
+enum MBG_OPT_BITS
+{
+ MBG_OPT_BIT_STR_UTC, ///< serial time string contains %UTC time
+ MBG_OPT_BIT_EMU_SYNC, ///< always pretend to be synchronized, alternatively ::GPS_FEAT_IGNORE_LOCK may be supported
+ N_MBG_OPT_BIT
+};
+
+
+/**
+ * @brief Bit masks according to ::MBG_OPT_BITS
+ *
+ * Used with ::MBG_OPT_SETTINGS::flags and ::MBG_OPT_INFO::supp_flags.
+ */
+enum MBG_OPT_FLAGS
+{
+ MBG_OPT_FLAG_STR_UTC = ( 1UL << MBG_OPT_BIT_STR_UTC ), ///< see ::MBG_OPT_BIT_STR_UTC
+ MBG_OPT_FLAG_EMU_SYNC = ( 1UL << MBG_OPT_BIT_EMU_SYNC ) ///< see ::MBG_OPT_BIT_EMU_SYNC
+};
+
+
+
+/**
+ * @brief Bit coded return type for ::PCPS_GET_IRIG_CTRL_BITS
+ *
+ * The control bits a time code receiver has decoded from
+ * the incoming time code signal.
+ *
+ * @note ::MBG_RAW_IRIG_DATA is more versatile and should
+ * be used preferably, if supported.
+ *
+ * @see ::MBG_RAW_IRIG_DATA
+ */
+typedef uint32_t MBG_IRIG_CTRL_BITS;
+
+#define _mbg_swab_irig_ctrl_bits( _p ) _mbg_swab32( _p )
+
+
+/**
+ * @brief Extract the TFOM code from ::MBG_IRIG_CTRL_BITS
+ *
+ * The resulting code is only valid if the configured IRIG code frame format
+ * supports this. See @ref MSK_ICODE_TX_HAS_TFOM and @ref MSK_ICODE_RX_HAS_TFOM
+ *
+ * As specified in the IEEE 1344 standard as "Time Quality", the TFOM code is
+ * the range 0x0 (locked, maximum accuracy) to 0xF (failed, data unreliable).
+ */
+#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;
+
+#define _mbg_swab_mbg_raw_irig_data( _p ) _nop_macro_fnc()
+
+/**
+ * @brief Extract the TFOM code from ::MBG_RAW_IRIG_DATA
+ *
+ * The resulting code is only valid if the configured IRIG code frame format
+ * supports this. See @ref MSK_ICODE_TX_HAS_TFOM and @ref MSK_ICODE_RX_HAS_TFOM
+ *
+ * As specified in the IEEE 1344 standard as "Time Quality", the TFOM code is
+ * the range 0x0 (locked, maximum accuracy) to 0xF (failed, data unreliable).
+ */
+#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
+ *
+ * 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
+ *
+ * @see ::MBG_TIME_SCALE_MASKS
+ * @see ::TM_SCALE_GPS
+ * @see ::TM_SCALE_TAI
+ */
+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 (see ::GPS_TAI_OFFSET)
+ N_MBG_TIME_SCALE
+};
+
+/**
+ * @brief Bit masks for known time scales
+ *
+ * @see ::MBG_TIME_SCALES
+ */
+enum MBG_TIME_SCALE_MASKS
+{
+ MBG_TIME_SCALE_MSK_DEFAULT = ( 1UL << MBG_TIME_SCALE_DEFAULT ), ///< see ::MBG_TIME_SCALE_DEFAULT
+ MBG_TIME_SCALE_MSK_GPS = ( 1UL << MBG_TIME_SCALE_GPS ), ///< see ::MBG_TIME_SCALE_GPS
+ MBG_TIME_SCALE_MSK_TAI = ( 1UL << MBG_TIME_SCALE_TAI ) ///< see ::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, see ::MBG_TIME_SCALES
+ uint8_t flags; ///< reserved, don't use, 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; ///< number of scales, all supported flags
+ uint32_t supp_scales; ///< bit masks of supported scales, see ::MBG_TIME_SCALE_MASKS
+
+} 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 ); \
+}
+
+/** @} defgroup 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 mode_param; ///< depending on the mode, e.g. pulse length, or index of a signal source
+ uint16_t timeout; ///< timeout after which output signal is disabled [min], used with ::POUT_DCF77 and ::POUT_DCF77_M59 only, see ::MAX_POUT_DCF_TIMOUT
+ uint16_t flags; ///< @see ::POUT_SETTINGS_FLAGS
+ 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;
+
+
+/**
+ * @brief Convert ::POUT_SETTINGS endianess after reading from a device
+ *
+ * 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)->mode_param ); \
+ _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] ); \
+ } \
+}
+
+/**
+ * @brief Convert ::POUT_SETTINGS endianess before writing to a device
+ *
+ * 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)->mode_param ); \
+ _mbg_swab16( &(_p)->timeout ); \
+ _mbg_swab16( &(_p)->flags ); \
+}
+
+
+
+/**
+ * @brief Definitions used with ::POUT_TIME_SLOTS mode
+ *
+ * If ::POUT_SETTINGS::mode is set to ::POUT_TIME_SLOTS then the number
+ * of time slots per minute is stored in ::POUT_SETTINGS::mode_param.
+ * Valid numbers are all numbers n in the range ::MIN_TIME_SLOTS_PER_MINUTE
+ * to ::MAX_TIME_SLOTS_PER_MINUTE for which the remainder of 60 / n is 0.
+ *
+ * @anchor POUT_TIME_SLOTS_MODE_DEFS @{ */
+
+#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 ) \
+ )
+
+/** @} anchor POUT_TIME_SLOTS_MODE_DEFS */
+
+
+
+#define MAX_POUT_PULSE_LEN 1000 ///< 10 secs, in 10 msec units
+#define MAX_POUT_DCF_TIMOUT ( 48 * 60 ) ///< 48 hours, in minutes
+
+
+
+/**
+ * @brief Enumeration of known operation modes for programmable pulse outputs
+ *
+ * These codes are used with ::POUT_SETTINGS::mode. One or more of
+ * the remaining fields in ::POUT_SETTINGS are evaluated depending
+ * on the selected mode.
+ *
+ * Unless ::POUT_NOT_INVERTIBLE is set in ::POUT_INFO::flags
+ * the output signal level can be inverted if ::POUT_INVERTED
+ * is set in ::POUT_SETTINGS::flags.
+ *
+ * @note Not every programmable pulse output supports all modes.
+ *
+ * @see @ref POUT_MODE_MASKS
+ */
+enum POUT_MODES
+{
+ POUT_IDLE, ///< always off, or on if ::POUT_INVERTED flag is set
+ POUT_TIMER, ///< switch on/off at times specified in ::POUT_SETTINGS::tm
+ POUT_SINGLE_SHOT, ///< pulse at time POUT_SETTINGS::tm[0].on, pulse length in ::POUT_SETTINGS::mode_param [10 ms units], see ::MAX_POUT_PULSE_LEN
+ POUT_CYCLIC_PULSE, ///< pulse every POUT_SETTINGS::tm[0].on.t interval, pulse length in ::POUT_SETTINGS::mode_param [10 ms units], see ::MAX_POUT_PULSE_LEN
+ POUT_PER_SEC, ///< pulse if second changes, pulse length in ::POUT_SETTINGS::mode_param [10 ms units], see ::MAX_POUT_PULSE_LEN
+ POUT_PER_MIN, ///< pulse if minute changes, pulse length in ::POUT_SETTINGS::mode_param [10 ms units], see ::MAX_POUT_PULSE_LEN
+ POUT_PER_HOUR, ///< pulse if hour changes, pulse length in ::POUT_SETTINGS::mode_param [10 ms units], see ::MAX_POUT_PULSE_LEN
+ POUT_DCF77, ///< emulate DCF77 signal, uses ::POUT_SETTINGS::timeout, see ::MAX_POUT_DCF_TIMOUT
+ POUT_POS_OK, ///< on if receiver position verified (nav_solved)
+ POUT_TIME_SYNC, ///< on if time synchronized (time_syn)
+ POUT_ALL_SYNC, ///< on if position verified and time synchronized
+ POUT_TIMECODE, ///< IRIG/AFNOR DCLS signal output
+ POUT_TIMESTR, ///< serial time string, ::POUT_SETTINGS::mode_param contains the number of the COM port, see ::MAX_POUT_TIMESTR_PORTS
+ POUT_10MHZ, ///< 10 MHz fixed frequency
+ POUT_DCF77_M59, ///< DCF77-like signal with 500 ms pulse in 59th second, uses ::POUT_SETTINGS::timeout, see ::MAX_POUT_DCF_TIMOUT
+ POUT_SYNTH, ///< programmable frequency synthesizer output signal
+ POUT_TIME_SLOTS, ///< programmable time slots during each minute, uses ::POUT_DATA, ::POUT_SETTINGS::mode_param contains time slots per minute
+ POUT_GPIO, ///< GPIO input or output signal, ::POUT_SETTINGS::mode_param specifies the GPIO number, see ::MBG_GPIO_CFG_LIMITS::num_io
+ // New modes have to be added here at the end of the enumeration, and
+ // the POUT_MODE_MASKS and string initializers (also in pcpslstr.h)
+ // have to be updated accordingly.
+ N_POUT_MODES ///< the number of known modes
+};
+
+
+/**
+ * @brief Bit masks associated with ::POUT_MODES
+ *
+ * Used with ::POUT_INFO::supp_modes to specify which ::POUT_MODES
+ * are supported for a particular programmable output.
+ *
+ * @see ::POUT_MODES
+ *
+ * @anchor POUT_MODE_MASKS @{ */
+
+#define MSK_POUT_IDLE ( 1UL << POUT_IDLE ) ///< see ::POUT_IDLE
+#define MSK_POUT_TIMER ( 1UL << POUT_TIMER ) ///< see ::POUT_TIMER
+#define MSK_POUT_SINGLE_SHOT ( 1UL << POUT_SINGLE_SHOT ) ///< see ::POUT_SINGLE_SHOT
+#define MSK_POUT_CYCLIC_PULSE ( 1UL << POUT_CYCLIC_PULSE ) ///< see ::POUT_CYCLIC_PULSE
+#define MSK_POUT_PER_SEC ( 1UL << POUT_PER_SEC ) ///< see ::POUT_PER_SEC
+#define MSK_POUT_PER_MIN ( 1UL << POUT_PER_MIN ) ///< see ::POUT_PER_MIN
+#define MSK_POUT_PER_HOUR ( 1UL << POUT_PER_HOUR ) ///< see ::POUT_PER_HOUR
+#define MSK_POUT_DCF77 ( 1UL << POUT_DCF77 ) ///< see ::POUT_DCF77
+#define MSK_POUT_POS_OK ( 1UL << POUT_POS_OK ) ///< see ::POUT_POS_OK
+#define MSK_POUT_TIME_SYNC ( 1UL << POUT_TIME_SYNC ) ///< see ::POUT_TIME_SYNC
+#define MSK_POUT_ALL_SYNC ( 1UL << POUT_ALL_SYNC ) ///< see ::POUT_ALL_SYNC
+#define MSK_POUT_TIMECODE ( 1UL << POUT_TIMECODE ) ///< see ::POUT_TIMECODE
+#define MSK_POUT_TIMESTR ( 1UL << POUT_TIMESTR ) ///< see ::POUT_TIMESTR
+#define MSK_POUT_10MHZ ( 1UL << POUT_10MHZ ) ///< see ::POUT_10MHZ
+#define MSK_POUT_DCF77_M59 ( 1UL << POUT_DCF77_M59 ) ///< see ::POUT_DCF77_M59
+#define MSK_POUT_SYNTH ( 1UL << POUT_SYNTH ) ///< see ::POUT_SYNTH
+#define MSK_POUT_TIME_SLOTS ( 1UL << POUT_TIME_SLOTS ) ///< see ::POUT_TIME_SLOTS
+#define MSK_POUT_GPIO ( 1UL << POUT_GPIO ) ///< see ::POUT_GPIO
+
+/** @} anchor POUT_MODE_MASKS */
+
+
+/*
+ * 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 "Serial 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 ENG_POUT_NAME_GPIO "GPIO Signal"
+
+#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, \
+ ENG_POUT_NAME_GPIO \
+}
+
+
+#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 ENG_POUT_HINT_GPIO "Duplicated signal of the specified GPIO input or output"
+
+#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, \
+ ENG_POUT_HINT_GPIO \
+}
+
+
+
+/**
+ * @brief Flag bits used to define ::POUT_SETTINGS_FLAGS
+ *
+ * @see ::POUT_SETTINGS_FLAGS
+ */
+enum POUT_SETTINGS_FLAG_BITS
+{
+ POUT_BIT_INVERTED, ///< output level is inverted, use only if ::POUT_NOT_INVERTIBLE not set
+ POUT_BIT_IF_SYNC_ONLY, ///< disable output in holdover mode, use only if ::POUT_SUPP_IF_SYNC_ONLY is set
+ POUT_BIT_TIMEBASE_UTC, ///< output %UTC if mode is ::POUT_DCF77 or ::POUT_DCF77_M59, use only if ::POUT_SUPP_DCF77_UTC is set
+ N_POUT_SETTINGS_FLAG_BITS ///< Number of known flag bits
+};
+
+
+/**
+ * @brief Flag bit masks used with ::POUT_SETTINGS::flags
+ *
+ * @see ::POUT_SETTINGS_FLAG_BITS
+ */
+enum POUT_SETTINGS_FLAGS
+{
+ POUT_INVERTED = ( 1UL << POUT_BIT_INVERTED ), ///< see ::POUT_BIT_INVERTED, ::POUT_NOT_INVERTIBLE
+ POUT_IF_SYNC_ONLY = ( 1UL << POUT_BIT_IF_SYNC_ONLY ), ///< see ::POUT_BIT_IF_SYNC_ONLY, ::POUT_SUPP_IF_SYNC_ONLY
+ POUT_TIMEBASE_UTC = ( 1UL << POUT_BIT_TIMEBASE_UTC ) ///< see ::POUT_BIT_TIMEBASE_UTC, ::POUT_SUPP_DCF77_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 @ref POUT_MODE_MASKS
+ 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 unused and always 0
+ uint16_t reserved_1; ///< reserved for future use, currently unused and always 0
+ uint32_t flags; ///< @see ::POUT_INFO_FLAG_MASKS
+
+} 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 ); \
+}
+
+
+#define MAX_POUT_TIMESTR_PORTS 8 ///< The max number of COM ports that can be handled by ::POUT_INFO::timestr_ports
+
+
+
+/**
+ * @brief Flag bits used to define ::POUT_INFO_FLAG_MASKS
+ *
+ * @see ::POUT_INFO_FLAG_MASKS
+ */
+enum POUT_INFO_FLAG_BITS
+{
+ POUT_BIT_SUPP_IF_SYNC_ONLY, ///< ::POUT_IF_SYNC_ONLY is supported for this output
+ POUT_BIT_SUPP_DCF77_UTC, ///< ::POUT_SUPP_DCF77_UTC is supported for this output
+ POUT_BIT_FIXED_PULSE_LEN, ///< pulse length is limited to the value ::POUT_SETTINGS::mode_param
+ POUT_BIT_NOT_INVERTIBLE, ///< output level can't be inverted, thus ::POUT_INVERTED is not supported for this output
+ N_POUT_INFO_FLAG_BITS ///< number of known flag bits
+};
+
+
+/**
+ * @brief Flag bit masks used with ::POUT_INFO::flags
+ *
+ * @see ::POUT_INFO_FLAG_BITS
+ */
+enum POUT_INFO_FLAG_MASKS
+{
+ POUT_SUPP_IF_SYNC_ONLY = ( 1UL << POUT_BIT_SUPP_IF_SYNC_ONLY ), ///< see ::POUT_BIT_SUPP_IF_SYNC_ONLY, ::POUT_IF_SYNC_ONLY
+ POUT_SUPP_DCF77_UTC = ( 1UL << POUT_BIT_SUPP_DCF77_UTC ), ///< see ::POUT_BIT_SUPP_DCF77_UTC, ::POUT_SUPP_DCF77_UTC
+ POUT_FIXED_PULSE_LEN = ( 1UL << POUT_BIT_FIXED_PULSE_LEN ), ///< see ::POUT_BIT_FIXED_PULSE_LEN
+ POUT_NOT_INVERTIBLE = ( 1UL << POUT_BIT_NOT_INVERTIBLE ) ///< see ::POUT_BIT_NOT_INVERTIBLE, ::POUT_INVERTED
+};
+
+
+
+/**
+ * @brief Current settings and general capabilities of a specific programmable pulse output
+ *
+ * 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 ); \
+}
+
+
+
+/**
+ * @defgroup group_multi_ref_all Support for multiple reference time sources
+ *
+ * Some devices can evaluate and synchronize to several different types
+ * of input signal, and eventually even several signals of the same type,
+ * e.g. several 1 PPS input signals.
+ *
+ * There are two different ways to configure multi ref devices.
+ *
+ * Newer devices which have the ::GPS_HAS_XMULTI_REF flag set in
+ * ::RECEIVER_INFO::features support the newer XMULTI_REF_... structures
+ * which provide a more flexible API, see @ref group_multi_ref_ext
+ *
+ * Older devices may have the ::GPS_FEAT_MULTI_REF flag set in which
+ * case an older API is supported, see @ref group_multi_ref_old
+ *
+ * Symbols defined in @ref group_multi_ref_common can be used
+ * with both APIs.
+ *
+ * @see @ref group_multi_ref_common
+ * @see @ref group_multi_ref_old
+ * @see @ref group_multi_ref_ext
+ * @{ */
+
+/**
+ * @defgroup group_multi_ref_common Common multi ref definitions
+ *
+ * Common definitions used with both the old and the extended
+ * multi ref API.
+ *
+ * @{ */
+
+/**
+ * @brief Enumeration of all known types of reference time source
+ *
+ * All known types of input signals which may possibly be supported
+ * by devices which support several different input signals, i.e.
+ * have the ::GPS_HAS_MULTI_REF or ::GPS_HAS_XMULTI_REF bit set
+ * in ::RECEIVER_INFO::features. Not all devices support each known
+ * type of input signal.
+ *
+ * @see @ref group_multi_ref_all
+ * @see ::DEFAULT_MULTI_REF_NAMES
+ * @see ::DEFAULT_MULTI_REF_NAMES_SHORT
+ * @see @ref MULTI_REF_TYPE_MASKS
+ */
+enum MULTI_REF_TYPES
+{
+ /// This ref type must not be used as index, but marks particular
+ /// ::XMULTI_REF_SETTINGS structures as "unused". It is only
+ /// supported if bit ::XMRIF_BIT_MRF_NONE_SUPP is set
+ MULTI_REF_NONE = -1,
+
+ 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, ///< 1 PPS in addition to time 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
+ MULTI_REF_EXT_OSC, ///< external oscillator disciplined and looped back via 1 PPS I/O
+ N_MULTI_REF ///< the number of defined sources, must not exceed ::MAX_N_MULTI_REF_TYPES
+};
+
+/**
+ * @brief Theoretical maximum number of multi ref input signal types
+ *
+ * Actually only ::N_MULTI_REF types have been defined, but ::N_MULTI_REF
+ * must not exceed the number of bits which can be hold by a uint32_t type.
+ */
+#define MAX_N_MULTI_REF_TYPES 32
+
+
+/**
+ * @brief Names of known 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", \
+ "ext. Osc." \
+}
+
+/**
+ * @brief Short names of supported ref time sources
+ *
+ * Used e.g. to configure a particular input signal type
+ *
+ * @see ::MULTI_REF_TYPES
+ */
+#define DEFAULT_MULTI_REF_NAMES_SHORT \
+{ \
+ "GPS", \
+ "FRQ", \
+ "PPS", \
+ "10MHZ+PPS", \
+ "TCR", \
+ "NTP", \
+ "PTP hq", \
+ "PTP E1", \
+ "Fixed in", \
+ "STR in", \
+ "GPIO in", \
+ "(reserved)", \
+ "PZF", \
+ "LWR", \
+ "GGR", \
+ "HQI", \
+ "EXT" \
+}
+
+
+/**
+ * @brief Bit masks associated with multi ref types
+ *
+ * Used to indicate which multi ref types are supported, e.g.
+ * in ::XMULTI_REF_INFO::supp_ref or ::MULTI_REF_INFO::supp_ref.
+ *
+ * @see ::MULTI_REF_TYPES
+ *
+ * @anchor MULTI_REF_TYPE_MASKS @{ */
+
+#define HAS_MULTI_REF_GPS ( 1UL << MULTI_REF_GPS ) ///< see ::MULTI_REF_GPS
+#define HAS_MULTI_REF_10MHZ ( 1UL << MULTI_REF_10MHZ ) ///< see ::MULTI_REF_10MHZ
+#define HAS_MULTI_REF_PPS ( 1UL << MULTI_REF_PPS ) ///< see ::MULTI_REF_PPS
+#define HAS_MULTI_REF_10MHZ_PPS ( 1UL << MULTI_REF_10MHZ_PPS ) ///< see ::MULTI_REF_10MHZ_PPS
+#define HAS_MULTI_REF_IRIG ( 1UL << MULTI_REF_IRIG ) ///< see ::MULTI_REF_IRIG
+#define HAS_MULTI_REF_NTP ( 1UL << MULTI_REF_NTP ) ///< see ::MULTI_REF_NTP
+#define HAS_MULTI_REF_PTP ( 1UL << MULTI_REF_PTP ) ///< see ::MULTI_REF_PTP
+#define HAS_MULTI_REF_PTP_E1 ( 1UL << MULTI_REF_PTP_E1 ) ///< see ::MULTI_REF_PTP_E1
+
+#define HAS_MULTI_REF_FREQ ( 1UL << MULTI_REF_FREQ ) ///< see ::MULTI_REF_FREQ
+#define HAS_MULTI_REF_PPS_STRING ( 1UL << MULTI_REF_PPS_STRING ) ///< see ::MULTI_REF_PPS_STRING
+#define HAS_MULTI_REF_GPIO ( 1UL << MULTI_REF_GPIO ) ///< see ::MULTI_REF_GPIO
+#define HAS_MULTI_REF_INTERNAL ( 1UL << MULTI_REF_INTERNAL ) ///< see ::MULTI_REF_INTERNAL
+#define HAS_MULTI_REF_PZF ( 1UL << MULTI_REF_PZF ) ///< see ::MULTI_REF_PZF
+#define HAS_MULTI_REF_LWR ( 1UL << MULTI_REF_LWR ) ///< see ::MULTI_REF_LWR
+#define HAS_MULTI_REF_GRC ( 1UL << MULTI_REF_GRC ) ///< see ::MULTI_REF_GRC
+#define HAS_MULTI_REF_HAVEQUICK ( 1UL << MULTI_REF_HAVEQUICK ) ///< see ::MULTI_REF_HAVEQUICK
+
+#define HAS_MULTI_REF_EXT_OSC ( 1UL << MULTI_REF_EXT_OSC ) ///< see ::MULTI_REF_EXT_OSC
+
+/** @} anchor MULTI_REF_TYPE_MASKS */
+
+/** @} defgroup group_multi_ref_common */
+
+
+
+/**
+ * @defgroup group_multi_ref_old Definitions used with the old multi ref API
+ *
+ * This API has been deprecated by a newer one which should be used preferably.
+ *
+ * @see @ref group_multi_ref_ext
+ *
+ * @{ */
+
+/**
+ * @brief Maximum number of input sources
+ *
+ * The number of supported input sources and priorities is
+ * limited to this value if the old API is used, i.e. if only
+ * the ::GPS_FEAT_MULTI_REF flag is set.
+ */
+#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 has to be set to one of the values 0..::N_MULTI_REF-1,
+ * or to ::MULTI_REF_NONE if no time source is specified.
+ */
+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 @ref MULTI_REF_TYPE_MASKS
+ uint16_t n_levels; ///< supported priority 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
+ *
+ * @see ::MULTI_REF_STATUS_BIT_MASKS
+ */
+typedef uint16_t MULTI_REF_STATUS;
+
+
+/**
+ * @brief Enumeration of multi ref status bits
+ *
+ * @see ::MULTI_REF_STATUS_BIT_MASKS
+ */
+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 10 MHz reference
+ WRN_1PPS_UNLOCK, ///< impossible to lock to external 1 PPS reference
+ WRN_GPS_UNLOCK, ///< impossible to lock to GPS
+ WRN_10MHZ_MISSING, ///< external 10 MHz signal not available
+ WRN_1PPS_MISSING, ///< external 1 PPS signal not available
+ N_MULTI_REF_STATUS_BITS ///< the number of known bits
+};
+
+
+/**
+ * @brief Bit masks associated with ::MULTI_REF_STATUS_BITS
+ *
+ * Used with ::MULTI_REF_STATUS.
+ *
+ * @see ::MULTI_REF_STATUS_BITS
+ */
+enum MULTI_REF_STATUS_BIT_MASKS
+{
+ MSK_WRN_COLD_BOOT = ( 1UL << WRN_COLD_BOOT ), ///< see ::WRN_COLD_BOOT
+ MSK_WRN_WARM_BOOT = ( 1UL << WRN_WARM_BOOT ), ///< see ::WRN_WARM_BOOT
+ MSK_WRN_ANT_DISCONN = ( 1UL << WRN_ANT_DISCONN ), ///< see ::WRN_ANT_DISCONN
+ MSK_WRN_10MHZ_UNLOCK = ( 1UL << WRN_10MHZ_UNLOCK ), ///< see ::WRN_10MHZ_UNLOCK
+ MSK_WRN_1PPS_UNLOCK = ( 1UL << WRN_1PPS_UNLOCK ), ///< see ::WRN_1PPS_UNLOCK
+ MSK_WRN_GPS_UNLOCK = ( 1UL << WRN_GPS_UNLOCK ), ///< see ::WRN_GPS_UNLOCK
+ MSK_WRN_10MHZ_MISSING = ( 1UL << WRN_10MHZ_MISSING ), ///< see ::WRN_10MHZ_MISSING
+ MSK_WRN_1PPS_MISSING = ( 1UL << WRN_1PPS_MISSING ), ///< see ::WRN_1PPS_MISSING
+ MSK_WRN_MODULE_MODE = ( 1UL << WRN_MODULE_MODE ) ///< see ::WRN_MODULE_MODE
+};
+
+/** @} defgroup group_multi_ref_old */
+
+
+
+/**
+ * @defgroup group_multi_ref_ext Extended multi ref definitions
+ *
+ * If the ::GPS_HAS_XMULTI_REF feature is set in ::RECEIVER_INFO::features then
+ * the XMULTI_REF (extended multi ref, XMR) feature and API are supported and
+ * must be used in favor of the older multi ref API (see @ref group_multi_ref_old).
+ *
+ * Devices supporting the XMULTI_REF feature provide 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.
+ *
+ * If ::GPS_HAS_XMRS_MULT_INSTC is also set in ::RECEIVER_INFO::features then
+ * ::XMULTI_REF_INSTANCES can be used to find out which types of input source
+ * are supported (::XMULTI_REF_INSTANCES::n_inst array entries != 0), and
+ * how many priority levels are supported to get an input source assigned
+ * (::XMULTI_REF_INSTANCES::n_xmr_settings).
+ *
+ * If ::XMRIF_MSK_HOLDOVER_STATUS_SUPP is set in ::XMULTI_REF_INSTANCES::flags
+ * then ::XMR_HOLDOVER_STATUS can be used to monitor the switching between
+ * different time sources when they become available or unavailable.
+ *
+ * If an XMR time source at a high priority level becomes unavailable the
+ * XMR control function tries to find and switch to a different time source
+ * at a lower level of the priority list, which is still available.
+ *
+ * On the other hand, if a time source at a higher priority level becomes
+ * available again, the XMR control function switches over to the time source
+ * at the higher priority even if the current time source is still available.
+ *
+ * If the accuracy of the time source at the next priority level is better than
+ * the accuracy of the time source at the current priority level then switching
+ * can be done immediately. However, if the next time source is worse than
+ * the current one it makes more sense to switch only after a certain holdover
+ * interval.
+ *
+ * The holdover interval is computed so that the time error due to the expected
+ * drift of the previously disciplined time base grows until it reaches the
+ * accuracy level of the next available reference time source.
+ *
+ * Only if the time source at the current priority level is still unavailable
+ * when the holdover interval expires the reference time source is switched
+ * to the time source at the next available priority level.
+ *
+ * @{ */
+
+
+/**
+ * @brief Identifier for a reference source
+ */
+typedef struct
+{
+ uint8_t type; ///< see ::MULTI_REF_TYPES, and note for ::XMRIF_BIT_MRF_NONE_SUPP
+ 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; ///< reference time source identifier
+ uint16_t flags; ///< reserved, currently always 0
+ NANO_TIME bias; ///< time bias, e.g. path delay @todo specify sign vs. earlier/later
+ NANO_TIME precision; ///< precision of the time source
+ uint32_t reserved; ///< reserved, currently always 0
+
+} XMULTI_REF_SETTINGS;
+
+
+
+/**
+ * @brief Reference source configuration for a specific priority level
+ *
+ * @note After all other ::XMULTI_REF_SETTINGS_IDX configuration structures
+ * have been sent to a device, an additional structure with idx == -1 (0xFFFF)
+ * has to be sent to let the new settings come into effect.
+ */
+typedef struct
+{
+ uint16_t idx; ///< the priority level index (highest == 0), 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1
+ XMULTI_REF_SETTINGS settings; ///< the settings configured for this level
+
+} XMULTI_REF_SETTINGS_IDX;
+
+
+
+/**
+ * @brief Reference source capabilities and current configuration
+ */
+typedef struct
+{
+ XMULTI_REF_SETTINGS settings; ///< current settings
+
+ /**
+ * @deprecated Deprecated by ::XMULTI_REF_INSTANCES::n_inst.
+ * If ::GPS_HAS_XMRS_MULT_INSTC is *not* set then this field provides
+ * a bit mask of supported sources (see @ref MULTI_REF_TYPE_MASKS),
+ * and only a single instance of each source signal type is supported.
+ */
+ uint32_t supp_ref;
+
+ /**
+ * @deprecated Deprecated by ::XMULTI_REF_INSTANCES::n_xmr_settings.
+ * If ::GPS_HAS_XMRS_MULT_INSTC is *not* set then this field
+ * reports the number of priority levels supported by the device.
+ */
+ uint8_t n_supp_ref;
+
+ uint8_t reserved; ///< reserved, don't use, currently always 0
+ uint16_t flags; ///< reserved, don't use, currently always 0
+
+} XMULTI_REF_INFO;
+
+
+
+/**
+ * @brief Reference source capabilities and current configuration for a specific priority level
+ */
+typedef struct
+{
+ uint16_t idx; ///< the priority level index (highest == 0), 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1
+ XMULTI_REF_INFO info; ///< ref source configuration and capabilities
+
+} XMULTI_REF_INFO_IDX;
+
+
+
+/**
+ * @brief Status information on a single ref time source
+ */
+typedef struct
+{
+ XMULTI_REF_ID id; ///< time source identifier
+ uint16_t status; ///< status bits, see @ref XMR_REF_STATUS_BIT_MASKS
+ NANO_TIME offset; ///< time offset from main time base @todo specify sign vs. earlier/later
+ uint16_t flags; ///< flags, currently unused
+ uint8_t ssm; ///< synchronization status message, if supported by signal source
+ uint8_t soc; ///< signal outage counter, incremented 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), 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1
+ XMULTI_REF_STATUS status; ///< status information
+
+} XMULTI_REF_STATUS_IDX;
+
+
+
+/**
+ * @brief XMULTI_REF status bits
+ */
+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
+};
+
+
+/**
+ * @brief Bit masks associated with ::XMR_REF_STATUS_BITS
+ *
+ * Used with ::XMULTI_REF_STATUS::status.
+ *
+ * @see ::XMR_REF_STATUS_BITS
+ *
+ * @anchor XMR_REF_STATUS_BIT_MASKS @{ */
+
+#define XMRS_MSK_NOT_SUPP ( 1UL << XMRS_BIT_NOT_SUPP ) ///< see ::XMRS_BIT_NOT_SUPP
+#define XMRS_MSK_NO_CONN ( 1UL << XMRS_BIT_NO_CONN ) ///< see ::XMRS_BIT_NO_CONN
+#define XMRS_MSK_NO_SIGNAL ( 1UL << XMRS_BIT_NO_SIGNAL ) ///< see ::XMRS_BIT_NO_SIGNAL
+#define XMRS_MSK_IS_MASTER ( 1UL << XMRS_BIT_IS_MASTER ) ///< see ::XMRS_BIT_IS_MASTER
+#define XMRS_MSK_IS_LOCKED ( 1UL << XMRS_BIT_IS_LOCKED ) ///< see ::XMRS_BIT_IS_LOCKED
+#define XMRS_MSK_IS_ACCURATE ( 1UL << XMRS_BIT_IS_ACCURATE ) ///< see ::XMRS_BIT_IS_ACCURATE
+#define XMRS_MSK_NOT_SETTLED ( 1UL << XMRS_BIT_NOT_SETTLED ) ///< see ::XMRS_BIT_NOT_SETTLED
+#define XMRS_MSK_NOT_PHASE_LOCKED ( 1UL << XMRS_BIT_NOT_PHASE_LOCKED ) ///< see ::XMRS_BIT_NOT_PHASE_LOCKED
+#define XMRS_MSK_NUM_SRC_EXC ( 1UL << XMRS_BIT_NUM_SRC_EXC ) ///< see ::XMRS_BIT_NUM_SRC_EXC
+#define XMRS_MSK_IS_EXTERNAL ( 1UL << XMRS_BIT_IS_EXTERNAL ) ///< see ::XMRS_BIT_IS_EXTERNAL
+#define XMRS_MSK_LOW_JITTER ( 1UL << XMRS_BIT_LOW_JITTER ) ///< see ::XMRS_BIT_LOW_JITTER
+
+/** @} anchor XMR_REF_STATUS_BIT_MASKS */
+
+
+/**
+ * @brief XMRS status bit name strings
+ *
+ * @see ::XMR_REF_STATUS_BITS
+ */
+#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" \
+}
+
+
+/*
+ * 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 General info on supported XMR sources and instances
+ *
+ * @note This structure is only supported if ::GPS_HAS_XMRS_MULT_INSTC
+ * is set in ::RECEIVER_INFO::features.
+ *
+ * The field ::XMULTI_REF_INSTANCES::n_xmr_settings reports the maximum number
+ * of entries that can be held by the input source table provided by this device.
+ * The input source table entry with the lowest index has the highest priority,
+ * and values 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1 can be used as index
+ * when reading ::XMULTI_REF_INFO_IDX or ::XMULTI_REF_STATUS_IDX from the device,
+ * or when writing ::XMULTI_REF_SETTINGS_IDX to the device to configure
+ * the priority/order of input sources.
+ *
+ * An input source table entry is empty if ::XMULTI_REF_ID::type is set to
+ * ::MULTI_REF_NONE in ::XMULTI_REF_SETTINGS::id, and accordingly
+ * in ::XMULTI_REF_STATUS::id.
+ *
+ * The array ::XMULTI_REF_INSTANCES::n_inst reports how many instances are supported
+ * for every known reference type. For example, if 2 PPS input signals were supported
+ * then ::XMULTI_REF_INSTANCES::n_inst[::MULTI_REF_PPS] was set to 2. Even though
+ * this array can hold up to ::MAX_N_MULTI_REF_TYPES entries, the number entries
+ * which are actually used is ::N_MULTI_REF, according to the number of known
+ * reference signal types, which is less or equal than ::MAX_N_MULTI_REF_TYPES.
+ */
+typedef struct
+{
+ uint32_t flags; ///< see ::XMR_INST_FLAG_BIT_MASKS
+ uint16_t n_xmr_settings; ///< number of entries in the input source priority table
+ uint8_t slot_id; ///< ID of the slot in which this device is installed, 0 or up to 15, if multiple slots not supported
+ uint8_t reserved; ///< reserved, don't use, currently always 0
+ uint8_t n_inst[MAX_N_MULTI_REF_TYPES]; ///< the number of supported instances of each input signal type
+
+} XMULTI_REF_INSTANCES;
+
+
+
+/**
+ * @brief Enumeration of flag bits used with XMULTI_REF instances
+ *
+ * @see ::XMR_INST_FLAG_BIT_MASKS
+ */
+enum XMR_INST_FLAGS
+{
+ /// This flag indicates that configuration programs may set
+ /// ::XMULTI_REF_ID::type to ::MULTI_REF_NONE in ::XMULTI_REF_SETTINGS::id
+ /// for unused priority levels, and that this will be reflected in
+ /// ::XMULTI_REF_STATUS::id accordingly. With some older firmware versions
+ /// this was not supported.
+ XMRIF_BIT_MRF_NONE_SUPP,
+
+ XMRIF_BIT_HOLDOVER_STATUS_SUPP, ///< ::XMR_HOLDOVER_STATUS and associated types supported
+
+ N_XMRIF_BITS ///< number of known flag bits
+};
+
+
+/**
+ * @brief Bit masks associated with ::XMR_INST_FLAGS
+ *
+ * Used with ::XMULTI_REF_INSTANCES::flags.
+ *
+ * @see ::XMR_INST_FLAGS
+ */
+enum XMR_INST_FLAG_BIT_MASKS
+{
+ XMRIF_MSK_MRF_NONE_SUPP = ( 1UL << XMRIF_BIT_MRF_NONE_SUPP ), ///< see ::XMRIF_BIT_MRF_NONE_SUPP
+ XMRIF_MSK_HOLDOVER_STATUS_SUPP = ( 1UL << XMRIF_BIT_HOLDOVER_STATUS_SUPP ) ///< see ::XMRIF_BIT_HOLDOVER_STATUS_SUPP
+};
+
+
+/**
+ * @brief XMR holdover interval, or elapsed holdover time, in [s]
+ */
+typedef uint32_t XMR_HOLDOVER_INTV;
+
+#define _mbg_swab_xmr_holdover_intv( _p ) \
+ _mbg_swab32( _p );
+
+
+
+/**
+ * @brief A code used to indicate that a input source table index is unspecified
+ */
+#define XMR_PRIO_LVL_UNSPEC -1
+
+
+/**
+ * @brief XMR holdover status
+ *
+ * Only supported if ::XMRIF_MSK_HOLDOVER_STATUS_SUPP is set in ::XMULTI_REF_INSTANCES::flags
+ *
+ * Reports the current holdover status including the elapsed holdover time
+ * and the currently active holdover interval, as well as the indices of the
+ * current and next XMR time source.
+ *
+ * The flag ::XMR_HLDOVR_MSK_IN_HOLDOVER is set if holdover mode is currently active.
+ *
+ * The fields ::XMR_HOLDOVER_STATUS::curr_prio and ::XMR_HOLDOVER_STATUS::nxt_prio
+ * specify the current or next priority level which can be in the range
+ * 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1, or ::XMR_PRIO_LVL_UNSPEC if the
+ * index is undefined, e.g. because no input source is available to which can
+ * be switched after the holdover interval.
+ *
+ * The ::XMR_HOLDOVER_STATUS::mode field indicates the current XMR/holdover mode
+ * which is usually ::XMR_HLDOVR_AUTONOMOUS. However, in certain applications
+ * XMR switching is controlled remotely, in which case ::XMR_HOLDOVER_STATUS::mode
+ * is set to ::XMR_HLDOVR_REMOTE.
+ *
+ * If the device is in remote mode and needs to switch XMR sources then mode changes
+ * to ::XMR_HLDOVR_PRE_AUTONOMOUS, and the ::XMR_HOLDOVER_STATUS::remote_watchdog
+ * starts to count down. If the watchdog expires before a remote switch command
+ * has been received the device switches to ::XMR_HLDOVR_AUTONOMOUS.
+ */
+typedef struct
+{
+ uint8_t mode; ///< XMR/holdover mode, see ::XMR_HOLDOVER_STATUS_MODES
+ int8_t curr_prio; ///< current priority level, 0..::XMULTI_REF_INSTANCES::n_xmr_settings, or ::XMR_PRIO_LVL_UNSPEC
+ int8_t nxt_prio; ///< next priority level after holdover, 0..::XMULTI_REF_INSTANCES::n_xmr_settings, or ::XMR_PRIO_LVL_UNSPEC
+ uint8_t remote_watchdog; ///< counts down in ::XMR_HLDOVR_PRE_AUTONOMOUS mode
+ uint32_t reserved; ///< reserved, don't use, currently 0
+ XMR_HOLDOVER_INTV elapsed; ///< elapsed time in holdover mode, only valid if ::XMR_HLDOVR_MSK_IN_HOLDOVER is set
+ XMR_HOLDOVER_INTV interval; ///< current holdover interval, only valid if ::XMR_HLDOVR_MSK_IN_HOLDOVER is set
+ uint32_t flags; ///< holdover status flags, see ::XMR_HOLDOVER_STATUS_FLAG_MASKS
+
+} XMR_HOLDOVER_STATUS;
+
+
+/**
+ * @brief XMR holdover status modes
+ *
+ * Used with ::XMR_HOLDOVER_STATUS::mode.
+ *
+ * @see ::XMR_HOLDOVER_STATUS_MODE_NAMES
+ */
+enum XMR_HOLDOVER_STATUS_MODES
+{
+ XMR_HLDOVR_AUTONOMOUS, ///< autonomous mode, XMR sources are selected automatically by the device
+ XMR_HLDOVR_PRE_AUTONOMOUS, ///< going to switch to autonomous mode when ::XMR_HOLDOVER_STATUS::remote_watchdog reaches 0
+ XMR_HLDOVR_REMOTE, ///< remote mode, XMR switching done by external command/control
+ N_XMR_HOLDOVER_STATUS_MODES ///< the number of known modes
+};
+
+
+/**
+ * @brief String initializers for XMR holdover status mode
+ *
+ * @see ::XMR_HOLDOVER_STATUS_MODES
+ */
+#define XMR_HOLDOVER_STATUS_MODE_NAMES \
+{ \
+ "autonomous", \
+ "pre-autonomous", \
+ "remote" \
+}
+
+
+
+/**
+ * @brief XMR holdover status flag bits
+ *
+ * Used to define ::XMR_HOLDOVER_STATUS_FLAG_MASKS.
+ */
+enum XMR_HOLDOVER_STATUS_FLAG_BITS
+{
+ XMR_HLDOVR_BIT_IN_HOLDOVER, ///< the device is currently in holdover mode
+ XMR_HLDOVR_BIT_TRANSITION_ENBD, ///< timebase is in transition (being slewed) after sources have been switched
+ XMR_HLDOVR_BIT_IN_TRANSITION, ///< transition is currently active, slewing in progress
+ N_XMR_HOLDOVER_STATUS_FLAG_BITS ///< the number of known status flags
+};
+
+
+/**
+ * @brief XMR holdover status flag masks
+ *
+ * Used with ::XMR_HOLDOVER_STATUS::flags.
+ */
+enum XMR_HOLDOVER_STATUS_FLAG_MASKS
+{
+ XMR_HLDOVR_MSK_IN_HOLDOVER = ( 1UL << XMR_HLDOVR_BIT_IN_HOLDOVER ), ///< see ::XMR_HLDOVR_BIT_IN_HOLDOVER
+ XMR_HLDOVR_MSK_TRANSITION_ENBD = ( 1UL << XMR_HLDOVR_BIT_TRANSITION_ENBD ), ///< see ::XMR_HLDOVR_BIT_TRANSITION_ENBD
+ XMR_HLDOVR_MSK_IN_TRANSITION = ( 1UL << XMR_HLDOVR_BIT_IN_TRANSITION ) ///< see ::XMR_HLDOVR_BIT_IN_TRANSITION
+};
+
+
+/** @} defgroup group_multi_ref_ext */
+
+/** @} defgroup group_multi_ref_all */
+
+
+
+/**
+ * @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..::MBG_GPIO_CFG_LIMITS::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; ///< reserved, currently always 0
+ uint32_t flags; ///< see ::MBG_GPIO_CFG_LIMIT_FLAG_MASKS
+
+} MBG_GPIO_CFG_LIMITS;
+
+#define _mbg_swab_gpio_cfg_limits( p ) \
+{ \
+ _mbg_swab32( &(_p)->num_io ); \
+ _mbg_swab32( &(_p)->reserved ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+
+/**
+ * @brief GPIO limits flag bits uded to define ::MBG_GPIO_CFG_LIMIT_FLAG_MASKS
+ *
+ * @see ::MBG_GPIO_CFG_LIMIT_FLAG_MASKS
+ */
+enum MBG_GPIO_CFG_LIMIT_FLAG_BITS
+{
+ MBG_GPIO_CFG_LIMIT_FLAG_BIT_STATUS_SUPP, ///< indicates that ::MBG_GPIO_STATUS is supported
+ N_MBG_GPIO_CFG_LIMIT_FLAG_BITS
+};
+
+
+
+/**
+ * @brief GPIO limits flag masks associated with ::MBG_GPIO_CFG_LIMIT_FLAG_BITS
+ *
+ * Used with ::MBG_GPIO_CFG_LIMITS::flags
+ *
+ * @see ::MBG_GPIO_CFG_LIMIT_FLAG_BITS
+ */
+enum MBG_GPIO_CFG_LIMIT_FLAG_MASKS
+{
+ MBG_GPIO_CFG_LIMIT_FLAG_MASK_STATUS_SUPP = ( 1UL << MBG_GPIO_CFG_LIMIT_FLAG_BIT_STATUS_SUPP ), ///< see ::MBG_GPIO_CFG_LIMIT_FLAG_BIT_STATUS_SUPP
+};
+
+
+
+/**
+ * @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.
+ *
+ * @see ::DEFAULT_GPIO_TYPES_SHORT_STRS
+ */
+enum MBG_GPIO_TYPES
+{
+ MBG_GPIO_TYPE_FREQ_IN, ///< variable frequency input, freq == 0 if input not used
+ 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 known signal shapes
+ *
+ * Used to specify the signal shape of an input or output
+ * frequency signal.
+ *
+ * @see ::MBG_GPIO_SIGNAL_SHAPE_MASKS
+ * @see ::DEFAULT_GPIO_SIGNAL_SHAPE_NAMES
+ */
+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
+};
+
+
+/**
+ * @brief Bit masks associated with ::MBG_GPIO_SIGNAL_SHAPES
+ *
+ * Used e.g. with ::MBG_GPIO_FREQ_IN_SUPP::supp_shapes,
+ * ::MBG_GPIO_FREQ_OUT_SUPP::supp_shapes,
+ * and ::MBG_GPIO_FIXED_FREQ_OUT_SUPP::supp_shapes.
+ *
+ * @see ::MBG_GPIO_SIGNAL_SHAPES
+ */
+enum MBG_GPIO_SIGNAL_SHAPE_MASKS
+{
+ MBG_GPIO_SIGNAL_SHAPE_MSK_UNSPECIFIED = ( 1UL << MBG_GPIO_SIGNAL_SHAPE_UNSPECIFIED ), ///< see ::MBG_GPIO_SIGNAL_SHAPE_UNSPECIFIED
+ MBG_GPIO_SIGNAL_SHAPE_MSK_SINE = ( 1UL << MBG_GPIO_SIGNAL_SHAPE_SINE ), ///< see ::MBG_GPIO_SIGNAL_SHAPE_SINE
+ MBG_GPIO_SIGNAL_SHAPE_MSK_SQUARE = ( 1UL << MBG_GPIO_SIGNAL_SHAPE_SQUARE ) ///< see ::MBG_GPIO_SIGNAL_SHAPE_SQUARE
+};
+
+
+
+/**
+ * @brief String initializers for GPIO signal shapes
+ *
+ * @see ::MBG_GPIO_SIGNAL_SHAPES
+ */
+#define DEFAULT_GPIO_SIGNAL_SHAPE_NAMES \
+{ \
+ "(unspec. shape)", \
+ "Sine wave", \
+ "Rectangle Pulse" \
+}
+
+
+
+/**
+ * @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 (0x80000000 --> 0.5, 0xFFFFFFFF --> 0.9999999...)
+
+} MBG_GPIO_FREQ;
+
+
+
+/**
+ * @brief Configuration of a GPIO variable frequency input
+ *
+ * Used as sub-structure of ::MBG_GPIO_SETTINGS.
+ *
+ * @see ::MBG_GPIO_TYPE_FREQ_IN
+ * @see ::MBG_GPIO_SETTINGS
+ */
+typedef struct
+{
+ MBG_GPIO_FREQ freq; ///< frequency in range ::MBG_GPIO_FREQ_IN_SUPP::freq_min..::MBG_GPIO_FREQ_IN_SUPP::freq_max, or 0 if input is not used
+ uint32_t csc_limit; ///< max. cycle slip [1/1000 cycle units], see ::MBG_GPIO_FREQ_IN_SUPP::csc_limit_max
+ uint32_t shape; ///< selected signal shape, see ::MBG_GPIO_SIGNAL_SHAPES
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t flags; ///< reserved, currently always 0
+
+} MBG_GPIO_FREQ_IN_SETTINGS;
+
+
+/**
+ * @brief Supported options for a variable frequency GPIO input
+ *
+ * Used as sub-structure of ::MBG_GPIO_LIMITS.
+ *
+ * @see ::MBG_GPIO_TYPE_FREQ_IN
+ * @see ::MBG_GPIO_LIMITS
+ */
+typedef struct
+{
+ uint32_t freq_min; ///< minimum output frequency [Hz]
+ uint32_t freq_max; ///< maximum output frequency [Hz]
+ uint32_t csc_limit_max; ///< 1/1000 units of the signal period, limited due to 10 ns sampling interval, see ::MBG_GPIO_FREQ_IN_SETTINGS::csc_limit //##++++++++++++++++
+ uint32_t supp_shapes; ///< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPE_MASKS
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t flags; ///< reserved, currently always 0
+
+} MBG_GPIO_FREQ_IN_SUPP;
+
+
+
+/**
+ * @brief Configuration of a GPIO variable frequency output
+ *
+ * Used as sub-structure of ::MBG_GPIO_SETTINGS.
+ *
+ * @see ::MBG_GPIO_TYPE_FREQ_OUT
+ * @see ::MBG_GPIO_SETTINGS
+ */
+typedef struct
+{
+ MBG_GPIO_FREQ freq; ///< frequency, see ::MBG_GPIO_FREQ_OUT_SUPP::freq_min and ::MBG_GPIO_FREQ_OUT_SUPP::freq_max
+ int32_t milli_phase; ///< phase [1/1000 degree units], see ::MBG_GPIO_FREQ_OUT_SUPP::milli_phase_max
+ uint32_t shape; ///< selected signal shape, see ::MBG_GPIO_SIGNAL_SHAPES
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t flags; ///< reserved, currently always 0
+
+} MBG_GPIO_FREQ_OUT_SETTINGS;
+
+
+
+/**
+ * @brief Supported options for a variable frequency GPIO output
+ *
+ * Used as sub-structure of ::MBG_GPIO_LIMITS.
+ *
+ * @see ::MBG_GPIO_TYPE_FREQ_OUT
+ * @see ::MBG_GPIO_LIMITS
+ */
+typedef struct
+{
+ uint32_t freq_min; ///< minimum output frequency [Hz], see ::MBG_GPIO_FREQ_OUT_SETTINGS::freq
+ uint32_t freq_max; ///< maximum output frequency [Hz], see ::MBG_GPIO_FREQ_OUT_SETTINGS::freq
+ uint32_t freq_resolution; ///< frequency resolution [Hz], unspecified if 0
+ uint32_t milli_phase_max; ///< max. abs. milli_phase, see ::MBG_GPIO_FREQ_OUT_SETTINGS::milli_phase
+ uint32_t supp_shapes; ///< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPE_MASKS
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t flags; ///< reserved, currently always 0
+
+} MBG_GPIO_FREQ_OUT_SUPP;
+
+
+
+/**
+ * @brief Enumeration of predefined fixed frequencies
+ *
+ * @see ::MBG_GPIO_FIXED_FREQ_MASKS
+ * @see ::MBG_GPIO_FIXED_FREQ_STRS
+ */
+enum MBG_GPIO_FIXED_FREQS
+{
+ MBG_GPIO_FIXED_FREQ_8kHz, ///< 8 kHz
+ MBG_GPIO_FIXED_FREQ_48kHz, ///< 48 kHz
+ MBG_GPIO_FIXED_FREQ_1MHz, ///< 1 MHz
+ MBG_GPIO_FIXED_FREQ_1544kHz, ///< 1.544 MHz
+ MBG_GPIO_FIXED_FREQ_2048kHz, ///< 2.048 MHz
+ MBG_GPIO_FIXED_FREQ_5MHz, ///< 5 MHz
+ MBG_GPIO_FIXED_FREQ_10MHz, ///< 10 MHz
+ MBG_GPIO_FIXED_FREQ_19440kHz, ///< 19.44 MHz
+ N_MBG_GPIO_FIXED_FREQ ///< number of predefined fixed frequencies
+};
+
+/**
+ * @brief Bit masks associated with ::MBG_GPIO_FIXED_FREQS
+ *
+ * @see ::MBG_GPIO_FIXED_FREQS
+ * @see ::MBG_GPIO_FIXED_FREQ_STRS
+ */
+enum MBG_GPIO_FIXED_FREQ_MASKS
+{
+ MSK_MBG_GPIO_FIXED_FREQ_8kHz = ( 1UL << MBG_GPIO_FIXED_FREQ_8kHz ), ///< see ::MBG_GPIO_FIXED_FREQ_8kHz
+ MSK_MBG_GPIO_FIXED_FREQ_48kHz = ( 1UL << MBG_GPIO_FIXED_FREQ_48kHz ), ///< see ::MBG_GPIO_FIXED_FREQ_48kHz
+ MSK_MBG_GPIO_FIXED_FREQ_1MHz = ( 1UL << MBG_GPIO_FIXED_FREQ_1MHz ), ///< see ::MBG_GPIO_FIXED_FREQ_1MHz
+ MSK_MBG_GPIO_FIXED_FREQ_1544kHz = ( 1UL << MBG_GPIO_FIXED_FREQ_1544kHz ), ///< see ::MBG_GPIO_FIXED_FREQ_1544kHz
+ MSK_MBG_GPIO_FIXED_FREQ_2048kHz = ( 1UL << MBG_GPIO_FIXED_FREQ_2048kHz ), ///< see ::MBG_GPIO_FIXED_FREQ_2048kHz
+ MSK_MBG_GPIO_FIXED_FREQ_5MHz = ( 1UL << MBG_GPIO_FIXED_FREQ_5MHz ), ///< see ::MBG_GPIO_FIXED_FREQ_5MHz
+ MSK_MBG_GPIO_FIXED_FREQ_10MHz = ( 1UL << MBG_GPIO_FIXED_FREQ_10MHz ), ///< see ::MBG_GPIO_FIXED_FREQ_10MHz
+ MSK_MBG_GPIO_FIXED_FREQ_19440kHz = ( 1UL << MBG_GPIO_FIXED_FREQ_19440kHz ) ///< see ::MBG_GPIO_FIXED_FREQ_19440kHz
+};
+
+
+/**
+ * @brief Initializers for an array of GPIO fixed frequency name strings
+ *
+ * @see ::MBG_GPIO_FIXED_FREQS
+ * @see ::MBG_GPIO_FIXED_FREQ_MASKS
+ */
+#define MBG_GPIO_FIXED_FREQ_STRS \
+{ \
+ "8 kHz", \
+ "48 kHz", \
+ "1 MHz", \
+ "1544 kHz", \
+ "2048 kHz", \
+ "5 MHz", \
+ "10 MHz", \
+ "19440 kHz" \
+}
+
+
+/**
+ * @brief Configuration of a GPIO fixed frequency output
+ *
+ * Used as sub-structure of ::MBG_GPIO_SETTINGS.
+ *
+ * @see ::MBG_GPIO_TYPE_FIXED_FREQ_OUT
+ * @see ::MBG_GPIO_SETTINGS
+ */
+typedef struct
+{
+ uint32_t freq_idx; ///< fixed frequency index, see ::MBG_GPIO_FIXED_FREQS
+ uint32_t shape; ///< selected signal shape, see ::MBG_GPIO_SIGNAL_SHAPES
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t flags; ///< reserved, currently always 0
+
+} MBG_GPIO_FIXED_FREQ_OUT_SETTINGS;
+
+
+/**
+ * @brief Supported options for a fixed frequency output
+ *
+ * Used as sub-structure of ::MBG_GPIO_LIMITS.
+ *
+ * @see ::MBG_GPIO_TYPE_FIXED_FREQ_OUT
+ * @see ::MBG_GPIO_LIMITS
+ */
+typedef struct
+{
+ uint32_t supp_freq; ///< bit mask of supported fixed frequencies, see ::MBG_GPIO_FIXED_FREQ_MASKS
+ uint32_t supp_shapes; ///< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPE_MASKS
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t supp_flags; ///< reserved, currently always 0
+
+} MBG_GPIO_FIXED_FREQ_OUT_SUPP;
+
+
+
+/**
+ * @brief Enumeration of BITS signal formats
+ *
+ * Used with ::MBG_GPIO_BITS_IN_SETTINGS::format and ::MBG_GPIO_BITS_OUT_SETTINGS::format
+ *
+ * @see ::MBG_GPIO_BITS_FORMAT_MASKS
+ */
+enum MBG_GPIO_BITS_FORMATS
+{
+ MBG_GPIO_BITS_E1_FRAMED, ///< 2.048 MBit
+ MBG_GPIO_BITS_T1_FRAMED, ///< 1.544 MBit
+ MBG_GPIO_BITS_E1_TIMING, ///< 2.048 MHz
+ MBG_GPIO_BITS_T1_TIMING, ///< 2.048 MHz
+ N_MBG_GPIO_BITS_FORMATS ///< number of defined formats
+};
+
+/**
+ * @brief Bit masks associated with ::MBG_GPIO_BITS_FORMATS
+ *
+ * Used with ::MBG_GPIO_BITS_IN_SUPP::supp_fmts and ::MBG_GPIO_BITS_OUT_SUPP::supp_fmts.
+ *
+ * @see ::MBG_GPIO_BITS_FORMATS
+ */
+enum MBG_GPIO_BITS_FORMAT_MASKS
+{
+ MSK_MBG_GPIO_BITS_E1_FRAMED = ( 1UL << MBG_GPIO_BITS_E1_FRAMED ), ///< see ::MBG_GPIO_BITS_E1_FRAMED
+ MSK_MBG_GPIO_BITS_T1_FRAMED = ( 1UL << MBG_GPIO_BITS_T1_FRAMED ), ///< see ::MBG_GPIO_BITS_T1_FRAMED
+ MSK_MBG_GPIO_BITS_E1_TIMING = ( 1UL << MBG_GPIO_BITS_E1_TIMING ), ///< see ::MBG_GPIO_BITS_E1_TIMING
+ MSK_MBG_GPIO_BITS_T1_TIMING = ( 1UL << MBG_GPIO_BITS_T1_TIMING ) ///< see ::MBG_GPIO_BITS_T1_TIMING
+};
+
+
+
+/**
+ * @brief Minimum and maximum known SSM values
+ *
+ * Values according to ITU G.704-1998
+ *
+ * Used with ::MBG_GPIO_BITS_IN_SETTINGS::quality::e1.ssm
+ * and ::MBG_GPIO_BITS_OUT_SETTINGS::ssm.
+ */
+enum GPIO_SSM_VALS
+{
+ GPIO_SSM_UNKNOWN, ///< Quality unknown, existing synchronization network
+ GPIO_SSM_RSVD_1, ///< (reserved)
+ GPIO_SSM_G_811, ///< Rec. G.811
+ GPIO_SSM_RSVD_3, ///< (reserved)
+ GPIO_SSM_SSU_A, ///< SSU-A
+ GPIO_SSM_RSVD_5, ///< (reserved)
+ GPIO_SSM_RSVD_6, ///< (reserved)
+ GPIO_SSM_RSVD_7, ///< (reserved)
+ GPIO_SSM_SSU_B, ///< SSU-B
+ GPIO_SSM_RSVD_9, ///< (reserved)
+ GPIO_SSM_RSVD_10, ///< (reserved)
+ GPIO_SSM_RSVD_SETS, ///< Synchronous Equipment Timing Source (SETS)
+ GPIO_SSM_RSVD_12, ///< (reserved)
+ GPIO_SSM_RSVD_13, ///< (reserved)
+ GPIO_SSM_RSVD_14, ///< (reserved)
+ GPIO_SSM_DONT_USE, ///< don't use
+ N_GPIO_SSM_VALS
+};
+
+
+
+/**
+ * @brief Minimum and maximum SA BITS groups
+ *
+ * Used with ::MBG_GPIO_BITS_IN_SETTINGS::quality::e1::sa_bits
+ * and ::MBG_GPIO_BITS_OUT_SETTINGS::sa_bits.
+ */
+enum GPIO_SA_BITS_GROUPS
+{
+ MIN_SA_BITS_GROUP = 4,
+ MAX_SA_BITS_GROUP = 8
+};
+
+
+/**
+ * @brief Configuration of a GPIO as BITS input module
+ *
+ * Used as sub-structure of ::MBG_GPIO_SETTINGS.
+ *
+ * @see ::MBG_GPIO_TYPE_BITS_IN
+ * @see ::MBG_GPIO_SETTINGS
+ */
+typedef struct
+{
+ uint32_t format; ///< signal format, see ::MBG_GPIO_BITS_FORMATS
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t csc_limit; ///< max. cycle slip [1/1000 cycle units]
+
+ union quality
+ {
+ struct e1
+ {
+ uint8_t ssm; ///< minimum E1 SSM for acceptance, 0..::N_GPIO_SSM_VALS-1
+ uint8_t sa_bits; ///< sa bits group carrying SSM, ::MIN_SA_BITS_GROUP..::MAX_SA_BITS_GROUP
+ uint16_t reserved; ///< reserved, currently always 0
+ } e1; ///< used with E1 formats
+
+ struct t1
+ {
+ uint8_t min_boc;
+ uint8_t reserved_0; ///< reserved, currently always 0
+ uint16_t reserved_1; ///< reserved, currently always 0
+ } 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 ::MBG_GPIO_BITS_ERR_MASKS
+ uint32_t flags; ///< reserved, currently always 0
+
+} MBG_GPIO_BITS_IN_SETTINGS;
+
+
+
+/**
+ * @brief Enumeration of BITS input error conditions
+ */
+enum MBG_GPIO_BITS_ERRS
+{
+ MBG_GPIO_BITS_ERR_LOS, ///< loss of signal
+ MBG_GPIO_BITS_ERR_LOF, ///< loss of frame
+ N_MBG_GPIO_BITS_ERRS ///< number of known errors
+};
+
+/**
+ * @brief Bit masks associated with BITS input error conditions
+ *
+ * Used with ::MBG_GPIO_BITS_IN_SETTINGS::err_msk
+ *
+ * @see ::MBG_GPIO_BITS_ERRS
+ */
+enum MBG_GPIO_BITS_ERR_MASKS
+{
+ MSK_MBG_GPIO_BITS_ERR_LOS = ( 1UL << MBG_GPIO_BITS_ERR_LOS ), ///< see ::MBG_GPIO_BITS_ERR_LOS
+ MSK_MBG_GPIO_BITS_ERR_LOF = ( 1UL << MBG_GPIO_BITS_ERR_LOF ) ///< see ::MBG_GPIO_BITS_ERR_LOF
+};
+
+
+/**
+ * @brief Supported options of a BITS GPIO input
+ *
+ * Used as sub-structure of ::MBG_GPIO_LIMITS.
+ *
+ * @see ::MBG_GPIO_TYPE_BITS_IN
+ * @see ::MBG_GPIO_LIMITS
+ */
+typedef struct
+{
+ uint32_t supp_fmts; ///< bit mask of supported formats, see ::MBG_GPIO_BITS_FORMAT_MASKS
+ uint32_t reserved; ///< reserved, currently always 0
+
+} MBG_GPIO_BITS_IN_SUPP;
+
+
+
+/**
+ * @brief Configuration of a GPIO as BITS output module
+ *
+ * Used as sub-structure of ::MBG_GPIO_SETTINGS.
+ *
+ * @see ::MBG_GPIO_TYPE_BITS_OUT
+ * @see ::MBG_GPIO_SETTINGS
+ */
+typedef struct
+{
+ uint32_t format; ///< signal format, see ::MBG_GPIO_BITS_FORMATS
+ uint32_t flags; ///< flags for encoder control etc., see ::MBG_GPIO_BITS_OUT_FLAG_MASKS
+ uint8_t sa_bits; ///< number of SA bit group for E1 SSM, ::MIN_SA_BITS_GROUP..::MAX_SA_BITS_GROUP
+ uint8_t ssm; ///< ssm for E1 mode, 0..::N_GPIO_SSM_VALS-1
+ uint8_t boc; ///< boc for T1 mode, 0..0x1F //##++++++++++++++
+ uint8_t reserved_0; ///< reserved, currently always 0
+ uint32_t reserved_1; ///< reserved, currently always 0
+ uint32_t reserved_2; ///< reserved, currently always 0
+ uint32_t reserved_3; ///< reserved, currently always 0
+
+} MBG_GPIO_BITS_OUT_SETTINGS;
+
+
+/**
+ * @brief Enumeration of flags used with BITS type GPIO outputs
+ */
+enum MBG_GPIO_BITS_OUT_FLAGS
+{
+ 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_FLAGS ///< number of known flags
+};
+
+/**
+ * @brief Bit masks associated with ::MBG_GPIO_BITS_OUT_FLAGS
+ *
+ * Used with ::MBG_GPIO_BITS_OUT_SETTINGS::flags
+ *
+ * @see ::MBG_GPIO_BITS_OUT_FLAGS
+ */
+enum MBG_GPIO_BITS_OUT_FLAG_MASKS
+{
+ MSK_MBG_GPIO_BITS_OUT_FLAG_HDB3 = ( 1UL << MBG_GPIO_BITS_OUT_FLAG_HDB3 ), ///< see ::MBG_GPIO_BITS_OUT_FLAG_HDB3
+ MSK_MBG_GPIO_BITS_OUT_FLAG_B8ZS = ( 1UL << MBG_GPIO_BITS_OUT_FLAG_B8ZS ) ///< see ::MBG_GPIO_BITS_OUT_FLAG_B8ZS
+};
+
+
+/**
+ * @brief Supported options of a BITS type GPIO output
+ *
+ * Used as sub-structure of ::MBG_GPIO_LIMITS.
+ *
+ * @see ::MBG_GPIO_TYPE_BITS_OUT
+ * @see ::MBG_GPIO_LIMITS
+ */
+typedef struct
+{
+ uint32_t supp_fmts; ///< bit mask of supported formats, see ::MBG_GPIO_BITS_FORMAT_MASKS
+ uint32_t reserved; ///< reserved, currently always 0
+
+} MBG_GPIO_BITS_OUT_SUPP;
+
+
+
+/**
+ * @brief A generic structure used to hold a GPIO port's settings
+ */
+typedef struct
+{
+ uint32_t type; ///< GPIO type, see ::MBG_GPIO_TYPES
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t flags; ///< reserved, currently always 0
+
+ /// settings depending on the GPIO type, see ::MBG_GPIO_TYPES
+ union
+ {
+ MBG_GPIO_FREQ_IN_SETTINGS freq_in; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_FREQ_IN
+ MBG_GPIO_FREQ_OUT_SETTINGS freq_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_FREQ_OUT
+ MBG_GPIO_FIXED_FREQ_OUT_SETTINGS ff_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_FIXED_FREQ_OUT
+ MBG_GPIO_BITS_IN_SETTINGS bits_in; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_BITS_IN
+ MBG_GPIO_BITS_OUT_SETTINGS bits_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_BITS_OUT
+ } u;
+
+} MBG_GPIO_SETTINGS;
+
+
+
+/**
+ * @brief A GPIO port's current settings, plus port index
+ */
+typedef struct
+{
+ uint32_t idx; ///< port index, 0..::MBG_GPIO_CFG_LIMITS::num_io-1
+ MBG_GPIO_SETTINGS settings; ///< current settings
+
+} MBG_GPIO_SETTINGS_IDX;
+
+
+
+/**
+ * @brief A generic structure used to specify a GPIO port's limits
+ */
+typedef struct
+{
+ uint32_t type; ///< GPIO type, see ::MBG_GPIO_TYPES
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t supp_flags; ///< supported flags //##++++++++++++ which?
+
+ /// limits depending on the GPIO type, see ::MBG_GPIO_TYPES
+ union
+ {
+ 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 GPIO port's current settings and limits
+ */
+typedef struct
+{
+ MBG_GPIO_SETTINGS settings; ///< current settings
+ MBG_GPIO_LIMITS limits; ///< limits of this GPIO port
+
+} MBG_GPIO_INFO;
+
+
+
+/**
+ * @brief A GPIO port's current settings and limits, plus port index
+ */
+typedef struct
+{
+ uint32_t idx; ///< port index, 0..::MBG_GPIO_CFG_LIMITS::num_io-1
+ MBG_GPIO_INFO info; ///< limits and current settings of this GPIO port
+
+} MBG_GPIO_INFO_IDX;
+
+
+
+/**
+ * @brief Status information on a single GPIO port
+ */
+typedef struct
+{
+ uint8_t port_state; ///< see ::MBG_GPIO_PORT_STATES
+ uint8_t reserved_0; ///< reserved, currently unused and always 0
+ uint16_t reserved_1; ///< reserved, currently unused and always 0
+ uint32_t reserved_2; ///< reserved, currently unused and always 0
+ uint32_t reserved_3; ///< reserved, currently unused and always 0
+
+} MBG_GPIO_STATUS;
+
+
+
+/**
+ * @brief Status information on a specific GPIO port
+ */
+typedef struct
+{
+ uint16_t idx; ///< port index, 0..::MBG_GPIO_CFG_LIMITS::num_io-1
+ MBG_GPIO_STATUS status; ///< status information
+
+} MBG_GPIO_STATUS_IDX;
+
+
+
+/**
+ * @brief GPIO port states
+ *
+ * Used with ::MBG_GPIO_STATUS::port_state
+ *
+ * @see ::DEFAULT_GPIO_PORT_STATE_NAMES
+ */
+enum MBG_GPIO_PORT_STATES
+{
+ MBG_GPIO_PORT_UNUSED, ///< configured as unused input
+ MBG_GPIO_PORT_OUTPUT_ENBD, ///< configured output signal enabled
+ MBG_GPIO_INPUT_SIG_AVAIL, ///< input signal is available
+ N_MBG_GPIO_PORT_STATES ///< number of known port states
+};
+
+
+
+/**
+ * @brief String initializers for GPIO port state names
+ *
+ * @see ::MBG_GPIO_PORT_STATES
+ */
+#define DEFAULT_GPIO_PORT_STATE_NAMES \
+{ \
+ "unused", \
+ "output enabled", \
+ "input signal available" \
+}
+
+
+/** @} defgroup group_gpio */
+
+
+
+/**
+ * @defgroup group_havequick HaveQuick definitions
+ *
+ * @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 with the 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
+};
+
+/*
+ * String initializers for each Havequick format
+ */
+#define HQ_FMT_NAME_STANAG4246_1 "STANAG4246 1"
+#define HQ_FMT_NAME_STANAG4246_2 "STANAG4246 2"
+#define HQ_FMT_NAME_STANAG4246_PTTI "STANAG4246 PTTI"
+#define HQ_FMT_NAME_STANAG4372_SATURN_1 "STANAG4372 SATURN 1"
+#define HQ_FMT_NAME_STANAG4372_SATURN_2 "STANAG4372 SATURN 2"
+#define HQ_FMT_NAME_STANAG4430_EXTD "STANAG4430 EXTD"
+
+#define HQ_FMT_SHRT_NAME_STANAG4246_1 "STG4246 1"
+#define HQ_FMT_SHRT_NAME_STANAG4246_2 "STG4246 2"
+#define HQ_FMT_SHRT_NAME_STANAG4246_PTTI "STG4246 PTTI"
+#define HQ_FMT_SHRT_NAME_STANAG4372_SATURN_1 "STG4372 SATURN1"
+#define HQ_FMT_SHRT_NAME_STANAG4372_SATURN_2 "STG4372 SATURN2"
+#define HQ_FMT_SHRT_NAME_STANAG4430_EXTD "STG4430 EXTD"
+
+/*
+ * The definition below can be used to initialize
+ * an array of ::N_HQ_FMT name strings.
+ */
+#define DEFAULT_HQ_FMT_NAMES \
+{ \
+ HQ_FMT_NAME_STANAG4246_1, \
+ HQ_FMT_NAME_STANAG4246_2, \
+ HQ_FMT_NAME_STANAG4246_PTTI, \
+ HQ_FMT_NAME_STANAG4372_SATURN_1, \
+ HQ_FMT_NAME_STANAG4372_SATURN_2, \
+ HQ_FMT_NAME_STANAG4430_EXTD \
+}
+
+#define DEFAULT_HQ_SHRT_FMT_NAMES \
+{ \
+ HQ_FMT_SHRT_NAME_STANAG4246_1, \
+ HQ_FMT_SHRT_NAME_STANAG4246_2, \
+ HQ_FMT_SHRT_NAME_STANAG4246_PTTI, \
+ HQ_FMT_SHRT_NAME_STANAG4372_SATURN_1, \
+ HQ_FMT_SHRT_NAME_STANAG4372_SATURN_2, \
+ HQ_FMT_SHRT_NAME_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;
+
+#define _mbg_swab_havequick_settings( _p ) \
+{ \
+ _mbg_swab16( &(_p)->format ); \
+ _mbg_swab16( &(_p)->flags ); \
+ _mbg_swab32( &(_p)->offset ); \
+ _mbg_swab32( &(_p)->reserved_0 ); \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+}
+
+/**
+ * @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;
+
+#define _mbg_swab_havequick_info( _p ) \
+{ \
+ _mbg_swab_havequick_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->supp_formats ); \
+ _mbg_swab16( &(_p)->supp_flags ); \
+ _mbg_swab16( &(_p)->reserved ); \
+}
+
+
+/**
+ * @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 with HaveQuick control flags
+ *
+ * @see ::HAVEQUICK_SETTINGS::flags
+ * @see ::HAVEQUICK_INFO::supp_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
+};
+
+/** @} defgroup 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, see @ref MBG_EVENT_CODES
+ 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
+ *
+ * @see @ref MBG_EVENT_CODES
+ * @see @ref MBG_EVT_ID_BITS
+ * @see @ref MBG_EVT_LVL_BITS
+ */
+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
+ *
+ * @see @ref MBG_EVENT_CODES
+ * @see @ref MBG_EVT_ID_BITS
+ * @see @ref MBG_EVT_LVL_BITS
+ */
+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
+ *
+ * @see ::MBG_EVT_IDS
+ * @see ::MBG_EVT_LVLS
+ *
+ * @anchor MBG_EVENT_CODES @{ */
+
+#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 )
+
+/** @} anchor MBG_EVENT_CODES */
+
+/** @} defgroup group_evt_log */
+
+
+
+/**
+ * @defgroup group_ims IMS support
+ *
+ * @note This is only supported 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; ///< reserved, currently always 0
+ uint32_t flags; ///< unused, currently 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 Celsius
+ 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
+
+
+/** @} defgroup 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
+ *
+ * Used to determine how many data sets of a specific type are supported
+ * by the device.
+ */
+typedef struct
+{
+ GEN_IO_INFO_TYPE type; // see ::PCPS_GEN_IO_TYPES
+ 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
+};
+
+/** @} defgroup group_generic_io */
+
+
+
+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 ) )
+
+
+
+/**
+ * @defgroup group_scu Definitions used with SCU devices
+ *
+ * The structures below are used with the SCU multiplexer board
+ * in a redundant system.
+ *
+ * @see ::GPS_MODEL_IS_SCU
+ *
+ * @{ */
+
+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 ::SCU_STAT_MASKS
+ uint16_t epld_control; ///< EPLD control word, see ::SCU_CTRL_MASKS
+
+} SCU_STAT_INFO;
+
+
+typedef struct
+{
+ uint16_t epld_control_mask; ///< control mask, determines which bit is to be changed, see ::SCU_CTRL_MASKS
+ uint16_t epld_control_value; ///< control value, determines value of bits to be changed, see ::SCU_CTRL_MASKS
+ uint32_t flags; ///< reserved, currently 0
+
+} SCU_STAT_SETTINGS;
+
+
+/**
+ * @brief Bit masks used to check the SCU EPLD status
+ *
+ * Used with ::SCU_STAT_INFO::epld_status
+ */
+enum SCU_STAT_MASKS
+{
+ MSK_EPLD_STAT_TS1 = 0x0001, ///< state of time sync signal clk_1
+ MSK_EPLD_STAT_TS2 = 0x0002, ///< state of time sync signal clk_2
+ MSK_EPLD_STAT_TL_ERROR = 0x0004, ///< state of time limit error input
+ MSK_EPLD_STAT_PSU1_OK = 0x0008, ///< state of power supply 1 monitoring input
+ MSK_EPLD_STAT_PSU2_OK = 0x0010, ///< state of power supply 2 monitoring input
+ MSK_EPLD_STAT_AUTO = 0x0020, ///< AUTOMATIC/REMOTE or MANUAL Mode
+ MSK_EPLD_STAT_SEL = 0x0040, ///< select bit for output MUX, ( clk_1 = 0 )
+ MSK_EPLD_STAT_ENA = 0x0080, ///< enable Bit for output MUX, set if enabled
+
+ MSK_EPLD_STAT_ACO = 0x4000, ///< Access control override bit
+ MSK_EPLD_STAT_WDOG_OK = 0x8000 ///< WDT_OK set to zero if watchdog expired
+};
+
+
+
+/**
+ * @brief Bit masks used to control the SCU EPLD
+ *
+ * Used with ::SCU_STAT_INFO::epld_control, ::SCU_STAT_SETTINGS::epld_control_mask,
+ * and ::SCU_STAT_SETTINGS::epld_control_value.
+ */
+enum SCU_CTRL_MASKS
+{
+ MSK_EPLD_CTL_DISB_SERIAL = 0x0001, ///< disable serial output on error
+ MSK_EPLD_CTL_DISB_PPS = 0x0002, ///< disable PPS output on error
+ MSK_EPLD_CTL_DISB_10MHZ = 0x0004, ///< disable 10 MHz output on error
+
+ MSK_EPLD_CNTL_SEL_REM = 0x0800, ///< remote select for output MUX (clk_1 = 0)
+ MSK_EPLD_CNTL_DIS_REM = 0x1000, ///< remote disable for output MUX
+ MSK_EPLD_CNTL_REMOTE = 0x2000, ///< must be set to enable remote operation
+ MSK_EPLD_CNTL_SEL_SNMP = 0x4000, ///< select clk for comm. (clk1 = 0)
+ 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
+};
+
+/** @} defgroup group_scu */
+
+
+
+/*------------------------------------------------------------------------*/
+
+#define REMOTE 0x10
+#define BOOT 0x20
+
+/**
+ * @brief Satellite receiver modes of operation.
+ *
+ * @note Some of the code combinations are deprecated with recent
+ * satellite receivers. However, this doesn't matter since the mode
+ * is just read from the receiver.
+ */
+enum RECEIVER_MODES
+{
+ TRACK = ( 0x01 ),
+ AUTO_166 = ( 0x02 ),
+ WARM_166 = ( 0x03 | BOOT ),
+ COLD_166 = ( 0x04 | BOOT ),
+ AUTO_BC = ( 0x05 | REMOTE ),
+ WARM_BC = ( 0x06 | REMOTE | BOOT ),
+ COLD_BC = ( 0x07 | REMOTE | BOOT ),
+ UPDA_166 = ( 0x08 | BOOT ),
+ 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 ::RECEIVER_MODES
+ 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 visible above the horizon
+ 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
+ *
+ * @see ::MBG_GNSS_TYPE_MASKS
+ * @see ::GNSS_TYPE_STRS
+ */
+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
+ GNSS_TYPE_WAAS, ///< WAAS, Wide Area Augmentation System
+ GNSS_TYPE_EGNOS, ///< EGNOS, European Geostationary Navigation Overlay Service
+ N_GNSS_TYPES ///< Number of defined codes
+};
+
+
+/**
+ * @brief Bit masks associated with ::MBG_GNSS_TYPES
+ *
+ * @see ::MBG_GNSS_TYPES
+ */
+enum MBG_GNSS_TYPE_MASKS
+{
+ MBG_GNSS_TYPE_MSK_GPS = ( 1UL << GNSS_TYPE_GPS ), ///< see ::GNSS_TYPE_GPS
+ MBG_GNSS_TYPE_MSK_GLONASS = ( 1UL << GNSS_TYPE_GLONASS ), ///< see ::GNSS_TYPE_GLONASS
+ MBG_GNSS_TYPE_MSK_BEIDOU = ( 1UL << GNSS_TYPE_BEIDOU ), ///< see ::GNSS_TYPE_BEIDOU
+ MBG_GNSS_TYPE_MSK_GALILEO = ( 1UL << GNSS_TYPE_GALILEO ), ///< see ::GNSS_TYPE_GALILEO
+ MBG_GNSS_TYPE_MSK_WAAS = ( 1UL << GNSS_TYPE_WAAS ), ///< see ::GNSS_TYPE_WAAS
+ MBG_GNSS_TYPE_MSK_EGNOS = ( 1UL << GNSS_TYPE_EGNOS ) ///< see ::GNSS_TYPE_EGNOS
+};
+
+
+/**
+ * @brief Name strings for the the known satellite navigation systems
+ *
+ * @see ::MBG_GNSS_TYPES
+ */
+#define GNSS_TYPE_STRS \
+{ \
+ "GPS", \
+ "GLONASS", \
+ "BEIDOU", \
+ "GALILEO", \
+ "WAAS", \
+ "EGNOS" \
+}
+
+
+#define N_GNSS_MODE_PRIO 8
+
+/**
+ * @brief GNSS mode settings
+ *
+ * @see ::MBG_GNSS_TYPES
+ */
+typedef struct
+{
+ uint32_t gnss_set; ///< bit mask of currently used GNSS systems, see ::MBG_GNSS_TYPE_MASKS
+ uint8_t prio[N_GNSS_MODE_PRIO]; ///< see ::MBG_GNSS_TYPES, unused fields set to 0xFF, idx 0 is highest prio
+ uint32_t flags; ///< see ::MBG_GNSS_MODE_FLAG_MASKS
+
+} 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, see ::MBG_GNSS_TYPE_MASKS
+ uint32_t flags; ///< indicates which flags are supported for settings::flags, see ::MBG_GNSS_MODE_FLAG_MASKS
+
+} 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 Flag bits used with ::MBG_GNSS_MODE_SETTINGS and ::MBG_GNSS_MODE_INFO
+ *
+ * @see ::MBG_GNSS_MODE_FLAG_MASKS
+ */
+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
+ MBG_GNSS_FLAG_SAT_INFO_IDX_SUPP_SER, ///< (read only)
+ N_MBG_GNSS_FLAGS
+};
+
+
+/**
+ * @brief Flag masks used with MBG_GNSS_MODE_SETTINGS::flags and MBG_GNSS_MODE_INFO::flags
+ *
+ * @see ::MBG_GNSS_MODE_FLAG_BITS
+ */
+enum MBG_GNSS_MODE_FLAG_MASKS
+{
+ MBG_GNSS_FLAG_MSK_EXCLUSIVE = ( 1UL << MBG_GNSS_FLAG_EXCLUSIVE ), ///< see ::MBG_GNSS_FLAG_EXCLUSIVE
+ MBG_GNSS_FLAG_MSK_HAS_PRIORITY = ( 1UL << MBG_GNSS_FLAG_HAS_PRIORITY ), ///< see ::MBG_GNSS_FLAG_HAS_PRIORITY
+ MBG_GNSS_FLAG_MSK_SAT_INFO_IDX_SUPP_SER = ( 1UL << MBG_GNSS_FLAG_SAT_INFO_IDX_SUPP_SER ) ///< see ::MBG_GNSS_FLAG_SAT_INFO_IDX_SUPP_SER
+};
+
+
+
+
+#define MAX_USED_SATS 32
+
+/**
+ * @brief Satellite information for a particular GNSS type.
+ */
+typedef struct
+{
+ uint8_t gnss_type; ///< GNSS type as enumerated in ::MBG_GNSS_TYPES
+ uint8_t reserved; ///< Reserved, currently always 0
+ uint16_t good_svs; ///< Num. of satellites that can currently be received and used
+ uint16_t svs_in_view; ///< Num. of satellites that should be visible above the horizon
+ uint8_t svs[MAX_USED_SATS]; ///< IDs of the satellites actually used for navigation, 0 == not used
+
+} GNSS_SAT_INFO;
+
+#define _mbg_swab_gnss_sat_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->good_svs ); \
+ _mbg_swab16( &(_p)->svs_in_view ); \
+}
+
+
+
+/**
+ * @brief One of several sets of satellite information for a particular GNSS type.
+ *
+ *
+ */
+typedef struct
+{
+ uint16_t idx; ///< GNSS system type index
+ GNSS_SAT_INFO gnss_sat_info; ///< see ::GNSS_SAT_INFO
+
+} GNSS_SAT_INFO_IDX;
+
+#define _mbg_swab_gnss_sat_info_idx( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_gnss_sat_info( &(_p)->gnss_sat_info ); \
+}
+
+
+
+
+#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_net_cfg Network configuration stuff
+ *
+ * @{ */
+
+/**
+ * @defgroup group_net_basic_types Basic network parameter types
+ *
+ * @{ */
+
+/**
+ * @brief The MAC address of a network interface
+ */
+typedef struct
+{
+ uint8_t b[6];
+
+} MBG_MAC_ADDR;
+
+
+
+/**
+ * @brief An IPv4 address
+ */
+typedef uint32_t IP4_ADDR;
+
+#define _mbg_swab_ip4_addr( _p ) \
+ _mbg_swab32( _p );
+
+
+
+/** @brief The number of bits used for an IPv6 address */
+#define IP6_ADDR_BITS 128
+
+/** @brief The number of bytes used for an IPv6 address */
+#define IP6_ADDR_BYTES ( IP6_ADDR_BITS / 8 ) // == 16
+
+/**
+ * @brief An IPv6 address
+ */
+typedef struct
+{
+ uint8_t b[IP6_ADDR_BYTES]; ///< bytes holding the address bits, b[0] == LSBs
+
+} IP6_ADDR;
+
+
+
+/** @brief The max number of chars required for an IPv6 address string */
+#define MAX_IP6_ADDR_STR_LEN 43 ///< e.g. 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/128
+
+/** @brief Buffer size required to store an IPv6 address string */
+#define IP6_ADDR_STR_SIZE ( MAX_IP6_ADDR_STR_LEN + 1 ) ///< ::MAX_IP6_ADDR_STR_LEN + terminating 0
+
+/** @brief A buffer for an IPv6 address string */
+typedef char IP6_ADDR_STR[IP6_ADDR_STR_SIZE];
+
+
+/**
+ * @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]; ///< ASCIIZ format
+
+/** @} defgroup group_net_basic_types */
+
+
+
+/**
+ * @defgroup group_vlan_cfg Definitions used with VLAN configuration
+ *
+ * @{ */
+
+/**
+ * @brief VLAN configuration
+ *
+ * @note This is a combination of a VLAN ID number plus a VLAN priority code.
+ */
+typedef uint16_t MBG_VLAN_CFG;
+
+#define _mbg_swab_mbg_vlan_cfg( _p ) _mbg_swab16( _p );
+
+#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( MBG_VLAN_CFG ) ) - 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 ) )
+
+/** @} defgroup group_vlan_cfg */
+
+
+
+/**
+ * @defgroup group_ip4_cfg Simple IPv4-only configuration or status
+ *
+ * This is only supported if the flag ::GPS_HAS_LAN_IP4 is set
+ * in ::RECEIVER_INFO::features.
+ * @see @ref group_ext_net_cfg Extended network configuration and status
+ *
+ * @{ */
+
+/**
+ * @brief Settings of an IPv4-only 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; ///< see ::MBG_IP4_FLAG_MASKS
+ MBG_VLAN_CFG vlan_cfg; ///< VLAN configuration
+
+} 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_swab_mbg_vlan_cfg( &(_p)->vlan_cfg ); \
+}
+
+
+
+/**
+ * @brief Simple LAN interface information
+ *
+ * This structure can be retrieved from a device
+ * to check the device's capabilities.
+ *
+ * It is only supported if the flag ::GPS_HAS_LAN_IP4 is set
+ * in ::RECEIVER_INFO::features.
+ *
+ * @see @ref group_ext_net_cfg Extended network configuration and status
+ */
+typedef struct
+{
+ uint16_t type; ///< type of LAN interface, see ::LAN_IF_TYPES
+ MBG_MAC_ADDR mac_addr; ///< MAC address
+ uint16_t ver_code; ///< version number (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; ///< see ::MBG_IP4_FLAG_MASKS
+ 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, superseded by RSC devices
+ LAN_IF_TYPE_PTP, ///< LAN interface is a special PTP interface
+ LAN_IF_TYPE_RSC, ///< RSC device, supersedes XPORT
+ 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, ///< only used 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
+};
+
+/** @} defgroup group_ip4_cfg */
+
+
+
+/**
+ * @defgroup group_ext_net_cfg_types Types used for extended network configuration and status
+ *
+ * @{ */
+
+/**
+ * @brief Enumeration of types used with ::MBG_IP_ADDR::type
+ */
+enum MBG_IP_ADDR_TYPES
+{
+ MBG_IP_ADDR_TYPE_UNKNOWN,
+ MBG_IP_ADDR_TYPE_IP4,
+ MBG_IP_ADDR_TYPE_IP6
+};
+
+/*
+ * Default initializers for English mode string names. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+#define MBG_IP_ADDR_TYPE_STR_ENG_UNKNOWN "unknown"
+#define MBG_IP_ADDR_TYPE_STR_ENG_IP4 "IPv4"
+#define MBG_IP_ADDR_TYPE_STR_ENG_IP6 "IPv6"
+
+#define MBG_IP_ADDR_TYPE_NAMES_ENG \
+{ \
+ MBG_IP_ADDR_TYPE_STR_ENG_UNKNOWN, \
+ MBG_IP_ADDR_TYPE_STR_ENG_IP4, \
+ MBG_IP_ADDR_TYPE_STR_ENG_IP6 \
+}
+
+
+/**
+ * @brief Network link speed modes
+ *
+ * @see ::MBG_NET_LINK_MODE_MASKS
+ *
+ * Note: Half duplex is not supported for 10GBit
+ */
+enum MBG_NET_LINK_MODES
+{
+ MBG_NET_LINK_MODE_AUTONEG, ///< auto negotiation
+ MBG_NET_LINK_MODE_10_BT_H, ///< 10 MBit half duplex
+ MBG_NET_LINK_MODE_10_BT_F, ///< 10 MBit full duplex
+ MBG_NET_LINK_MODE_100_BT_H, ///< 100 MBit half duplex
+ MBG_NET_LINK_MODE_100_BT_F, ///< 100 MBit full duplex
+ MBG_NET_LINK_MODE_1000_BT_H, ///< 1 GBit half duplex
+ MBG_NET_LINK_MODE_1000_BT_F, ///< 1 GBit full duplex
+ MBG_NET_LINK_MODE_10000_BT_F, ///< 10 GBit Full Duplex
+ N_MBG_NET_LINK_MODES
+};
+
+
+/**
+ * @brief Network link speed mode masks
+ *
+ * @see ::MBG_NET_LINK_MODES
+ */
+enum MBG_NET_LINK_MODE_MASKS
+{
+ MBG_NET_LINK_MODE_MASK_AUTONEG = ( 1UL << MBG_NET_LINK_MODE_AUTONEG ), ///< see ::MBG_NET_LINK_MODE_AUTONEG
+ MBG_NET_LINK_MODE_MASK_10_BT_H = ( 1UL << MBG_NET_LINK_MODE_10_BT_H ), ///< see ::MBG_NET_LINK_MODE_10_BT_H
+ MBG_NET_LINK_MODE_MASK_10_BT_F = ( 1UL << MBG_NET_LINK_MODE_10_BT_F ), ///< see ::MBG_NET_LINK_MODE_10_BT_F
+ MBG_NET_LINK_MODE_MASK_100_BT_H = ( 1UL << MBG_NET_LINK_MODE_100_BT_H ), ///< see ::MBG_NET_LINK_MODE_100_BT_H
+ MBG_NET_LINK_MODE_MASK_100_BT_F = ( 1UL << MBG_NET_LINK_MODE_100_BT_F ), ///< see ::MBG_NET_LINK_MODE_100_BT_F
+ MBG_NET_LINK_MODE_MASK_1000_BT_H = ( 1UL << MBG_NET_LINK_MODE_1000_BT_H ), ///< see ::MBG_NET_LINK_MODE_1000_BT_H
+ MBG_NET_LINK_MODE_MASK_1000_BT_F = ( 1UL << MBG_NET_LINK_MODE_1000_BT_F ), ///< see ::MBG_NET_LINK_MODE_1000_BT_F
+ MBG_NET_LINK_MODE_MASK_10000_BT_F = ( 1UL << MBG_NET_LINK_MODE_10000_BT_F ) ///< see ::MBG_NET_LINK_MODE_10000_BT_F
+};
+
+
+
+/**
+ * @brief Network link port types
+ *
+ * @see ::MBG_NET_LINK_PORT_MASKS
+ */
+enum MBG_NET_LINK_PORTS
+{
+ MBG_NET_LINK_PORT_AUTO, ///< auto detection
+ MBG_NET_LINK_PORT_TP, ///< Twisted Pair (TP)
+ MBG_NET_LINK_PORT_AUI, ///< Attachment Unit Interface (AUI), externel transceiver
+ MBG_NET_LINK_PORT_MII, ///< Media Independent Interface (MII), external receiver
+ MBG_NET_LINK_PORT_FIBRE, ///< fibre optic
+ MBG_NET_LINK_PORT_BNC, ///< coaxial cable
+ N_MBG_NET_LINK_PORTS
+};
+
+
+/**
+ * @brief Network link port type masks
+ *
+ * @see ::MBG_NET_LINK_PORTS
+ */
+enum MBG_NET_LINK_PORT_MASKS
+{
+ MBG_NET_LINK_PORT_MASK_AUTO = ( 1UL << MBG_NET_LINK_PORT_AUTO ), ///< see ::MBG_NET_LINK_PORT_AUTO
+ MBG_NET_LINK_PORT_MASK_TP = ( 1UL << MBG_NET_LINK_PORT_TP ), ///< see ::MBG_NET_LINK_PORT_TP
+ MBG_NET_LINK_PORT_MASK_AUI = ( 1UL << MBG_NET_LINK_PORT_AUI ), ///< see ::MBG_NET_LINK_PORT_AUI
+ MBG_NET_LINK_PORT_MASK_MII = ( 1UL << MBG_NET_LINK_PORT_MII ), ///< see ::MBG_NET_LINK_PORT_MII
+ MBG_NET_LINK_PORT_MASK_FIBRE = ( 1UL << MBG_NET_LINK_PORT_FIBRE ), ///< see ::MBG_NET_LINK_PORT_FIBRE
+ MBG_NET_LINK_PORT_MASK_BNC = ( 1UL << MBG_NET_LINK_PORT_BNC ) ///< see ::MBG_NET_LINK_PORT_BNC
+};
+
+
+
+/**
+ * @brief Network link state bits
+ *
+ * @see ::MBG_NET_LINK_STATE_MASKS
+ *
+ * @note See official Linux kernel documentation
+ * https://www.kernel.org/doc/Documentation/networking/operstates.txt
+ * for states below and explanations. Windows supports this in nearly the same way
+ * using similar names struct IP_ADAPTER_ADDRESSES which is explained at
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/aa366058%28v=vs.85%29.aspx
+ */
+enum MBG_NET_LINK_STATE_BITS
+{
+ MBG_NET_LINK_STATE_BIT_UP,
+ MBG_NET_LINK_STATE_BIT_BROADCAST,
+ MBG_NET_LINK_STATE_BIT_LOOPBACK,
+ MBG_NET_LINK_STATE_BIT_P2P,
+ MBG_NET_LINK_STATE_BIT_RUNNING,
+ MBG_NET_LINK_STATE_BIT_NO_ARP,
+ MBG_NET_LINK_STATE_BIT_PROMISC,
+ MBG_NET_LINK_STATE_BIT_MASTER,
+ MBG_NET_LINK_STATE_BIT_SLAVE,
+ MBG_NET_LINK_STATE_BIT_MULTICAST,
+ MBG_NET_LINK_STATE_BIT_LOWER_UP,
+ MBG_NET_LINK_STATE_BIT_DORMANT,
+ MBG_NET_LINK_STATE_BIT_ECHO,
+ N_MBG_NET_LINK_STATE_BITS
+};
+
+
+/**
+ * @brief Network link state masks
+ *
+ * @see ::MBG_NET_LINK_STATE_BITS (reclined to Linux' if.h, Windows is similiar)
+ */
+enum MBG_NET_LINK_STATE_MASKS
+{
+ MBG_NET_LINK_STATE_MASK_UP = ( 1UL << MBG_NET_LINK_STATE_BIT_UP ), ///< see ::MBG_NET_LINK_STATE_BIT_UP
+ MBG_NET_LINK_STATE_MASK_BROADCAST = ( 1UL << MBG_NET_LINK_STATE_BIT_BROADCAST ), ///< see ::MBG_NET_LINK_STATE_BIT_BROADCAST
+ MBG_NET_LINK_STATE_MASK_LOOPBACK = ( 1UL << MBG_NET_LINK_STATE_BIT_LOOPBACK ), ///< see ::MBG_NET_LINK_STATE_BIT_LOOPBACK
+ MBG_NET_LINK_STATE_MASK_P2P = ( 1UL << MBG_NET_LINK_STATE_BIT_P2P ), ///< see ::MBG_NET_LINK_STATE_BIT_P2P
+ MBG_NET_LINK_STATE_MASK_RUNNING = ( 1UL << MBG_NET_LINK_STATE_BIT_RUNNING ), ///< see ::MBG_NET_LINK_STATE_BIT_RUNNING
+ MBG_NET_LINK_STATE_MASK_NO_ARP = ( 1UL << MBG_NET_LINK_STATE_BIT_NO_ARP ), ///< see ::MBG_NET_LINK_STATE_BIT_NO_ARP
+ MBG_NET_LINK_STATE_MASK_PROMISC = ( 1UL << MBG_NET_LINK_STATE_BIT_PROMISC ), ///< see ::MBG_NET_LINK_STATE_BIT_PROMISC
+ MBG_NET_LINK_STATE_MASK_MASTER = ( 1UL << MBG_NET_LINK_STATE_BIT_MASTER ), ///< see ::MBG_NET_LINK_STATE_BIT_MASTER
+ MBG_NET_LINK_STATE_MASK_SLAVE = ( 1UL << MBG_NET_LINK_STATE_BIT_SLAVE ), ///< see ::MBG_NET_LINK_STATE_BIT_SLAVE
+ MBG_NET_LINK_STATE_MASK_MULTICAST = ( 1UL << MBG_NET_LINK_STATE_BIT_MULTICAST ), ///< see ::MBG_NET_LINK_STATE_BIT_MULTICAST
+ MBG_NET_LINK_STATE_MASK_LOWER_UP = ( 1UL << MBG_NET_LINK_STATE_BIT_LOWER_UP ), ///< see ::MBG_NET_LINK_STATE_BIT_LOWER_UP
+ MBG_NET_LINK_STATE_MASK_DORMANT = ( 1UL << MBG_NET_LINK_STATE_BIT_DORMANT ), ///< see ::MBG_NET_LINK_STATE_BIT_DORMANT
+ MBG_NET_LINK_STATE_MASK_ECHO = ( 1UL << MBG_NET_LINK_STATE_BIT_ECHO ) ///< see ::MBG_NET_LINK_STATE_BIT_ECHO
+};
+
+
+
+/**
+ * @brief Network link option bits
+ *
+ * @see ::MBG_NET_LINK_OPT_MASKS
+ */
+enum MBG_NET_LINK_OPTS
+{
+ MBG_NET_LINK_OPT_CAN_SET_MAC,
+ MBG_NET_LINK_OPT_CAN_BOND,
+ N_MBG_NET_LINK_OPTS
+};
+
+
+/**
+ * @brief Network link option masks
+ *
+ * @see ::MBG_NET_LINK_OPTS
+ */
+enum MBG_NET_LINK_OPT_MASKS
+{
+ MBG_NET_LINK_OPT_MASK_CAN_SET_MAC = ( 1UL << MBG_NET_LINK_OPT_CAN_SET_MAC ), ///< see ::MBG_NET_LINK_OPT_CAN_SET_MAC
+ MBG_NET_LINK_OPT_MASK_CAN_BOND = ( 1UL << MBG_NET_LINK_OPT_CAN_BOND ) ///< see ::MBG_NET_LINK_OPT_CAN_BOND
+};
+
+
+
+/**
+ * @brief Network link roles
+ *
+ * Used with ::MBG_NET_LINK_SETTINGS::role to determine
+ * if a network link operates in normal mode, or in
+ * a special mode, e.g. as part of a higher level pseudo
+ * interface (bonding, etc.)
+ */
+enum MBG_NET_LINK_ROLES
+{
+ MBG_NET_LINK_ROLE_UNKNOWN, ///< role can't be determined
+ MBG_NET_LINK_ROLE_NORMAL, ///< link is normal physical interface
+ MBG_NET_LINK_ROLE_MASTER, ///< link is master (e.g. bonding)
+ MBG_NET_LINK_ROLE_SLAVE, ///< link is slave (e.g. bonding)
+ N_MBG_NET_LINK_ROLES
+};
+//##++++++++++++++++ TODO define masks?
+
+
+
+/**
+ * @brief Network link bonding bits
+ *
+ * @see SIOCGIFPFLAGS under Linux, found no hint under Windows
+ */
+enum MBG_NET_LINK_ROLE_BITS
+{
+ MBG_NET_LINK_ROLE_BIT_BONDING, ///< Bonding master
+ MBG_NET_LINK_ROLE_BIT_BOND_SLAVE_INACTIVE, ///< Bonding slave is not active
+ MBG_NET_LINK_ROLE_BIT_BOND_MASTER_8023AD, ///< 802.3ad bonding master
+ MBG_NET_LINK_ROLE_BIT_BOND_MASTER_ALB, ///< Balanced-alb bonding master
+ N_MBG_NET_LINK_ROLE_BITS
+};
+
+
+/**
+ * @brief Network link role masks
+ *
+ * @see ::MBG_NET_LINK_ROLE_BITS
+ */
+enum MBG_NET_LINK_ROLE_MASKS
+{
+ MBG_NET_LINK_ROLE_MASK_BONDING = ( 1UL << MBG_NET_LINK_ROLE_BIT_BONDING ), ///< see ::MBG_NET_LINK_ROLE_BIT_BONDING
+ MBG_NET_LINK_ROLE_MASK_BOND_SLAVE_INACTIVE = ( 1UL << MBG_NET_LINK_ROLE_BIT_BOND_SLAVE_INACTIVE ), ///< see ::MBG_NET_LINK_ROLE_BIT_BOND_SLAVE_INACTIVE
+ MBG_NET_LINK_ROLE_MASK_BOND_MASTER_8023AD = ( 1UL << MBG_NET_LINK_ROLE_BIT_BOND_MASTER_8023AD ), ///< see ::MBG_NET_LINK_ROLE_BIT_BOND_MASTER_8023AD
+ MBG_NET_LINK_ROLE_MASK_BOND_MASTER_ALB = ( 1UL << MBG_NET_LINK_ROLE_BIT_BOND_MASTER_ALB ), ///< see ::MBG_NET_LINK_ROLE_BIT_BOND_MASTER_ALB
+ N_MBG_NET_LINK_ROLE_MASKS
+};
+
+
+
+/**
+ * @brief Network link bonding mode
+ *
+ * Used with ::MBG_NET_LINK_SETTINGS::role_value
+ *
+ * @note if_bonding.h contains bonding modes under Linux, found no hint under Windows.
+ * BUT: Something similiar (concerning naming) can be configured under Windows
+ * via GUI in device manager, if supported.
+ */
+enum MBG_NET_LINK_BOND_MODES
+{
+ MBG_NET_LINK_BOND_MODE_UNKNOWN,
+ MBG_NET_LINK_BOND_MODE_ROUNDROBIN,
+ MBG_NET_LINK_BOND_MODE_ACTIVEBACKUP,
+ MBG_NET_LINK_BOND_MODE_XOR,
+ MBG_NET_LINK_BOND_MODE_BROADCAST,
+ MBG_NET_LINK_BOND_MODE_8023AD,
+ MBG_NET_LINK_BOND_MODE_TLB,
+ MBG_NET_LINK_BOND_MODE_ALB,
+ N_MBG_NET_LINK_BOND_MODES
+};
+
+
+/**
+ * @brief Network logical interface commands
+ *
+ * Used with ::MBG_NET_INTF_SETTINGS::cmd
+ */
+enum MBG_NET_LOG_INTF_CMDS
+{
+ MBG_NET_LOG_CMD_NONE,
+ MBG_NET_LOG_CMD_ADD_UPDATE,
+ MBG_NET_LOG_CMD_REMOVE,
+ N_MBG_NET_LOG_CMDS
+};
+
+
+/**
+ * @brief Network logical interface roles
+ *
+ * Used with ::MBG_NET_INTF_SETTINGS::role
+ */
+enum MBG_NET_LOG_INTF_ROLES
+{
+ MBG_NET_LOG_ROLE_STANDARD,
+ MBG_NET_LOG_ROLE_BOND,
+ MBG_NET_LOG_ROLE_VLAN,
+ N_MBG_NET_INTF_ROLE
+};
+
+
+/**
+ * @brief Network interface bits
+ *
+ * @see ::MBG_NET_INTF_MASKS
+ *
+ * Used with ::MBG_NET_INTF_INFO::supp_flags
+ */
+enum MBG_NET_INTF_BITS
+{
+ MBG_NET_INTF_BIT_EXT_ROUTING,
+ N_MBG_NET_INTF_BITS
+};
+
+
+/**
+ * @brief Network interface masks
+ *
+ * @see ::MBG_NET_INTF_BITS
+ */
+enum MBG_NET_INTF_MASKS
+{
+ MBG_NET_INTF_MASK_EXT_ROUTING = ( 1UL << MBG_NET_INTF_BIT_EXT_ROUTING ) ///< see ::MBG_NET_INTF_BIT_EXT_ROUTING
+};
+
+/** @} defgroup group_ext_net_cfg_types */
+
+
+
+/**
+ * @defgroup group_ext_net_cfg Extended network configuration and status
+ *
+ * This is only supported if the flag ::GPS_HAS_NET_CFG is set
+ * in ::RECEIVER_INFO::features.
+ *
+ * @{ */
+
+/**
+ * @brief Global network configuration settings
+ */
+typedef struct
+{
+ MBG_HOSTNAME hostname; ///< hostname, eventually FQDN including domain name
+ uint32_t reserved; ///< currently reserved, always 0
+ uint32_t flags; ///< currently reserved, always 0
+ //##++++ TODO: flags could control IPv6, enable forwarding, etc.
+
+} MBG_NET_GLB_CFG_SETTINGS;
+
+#define _mbg_swab_net_glb_cfg_settings( _p ) \
+{ \
+ _mbg_swab32( &(_p)->reserved ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Global current network settings and supported features
+ */
+typedef struct
+{
+ MBG_NET_GLB_CFG_SETTINGS glb_settings;
+ uint16_t num_link; ///< max. supported links (physical interfaces), see ::MBG_NET_LINK_SETTINGS_IDX, ::MBG_NET_LINK_INFO_IDX
+ uint16_t num_intf; ///< max. logical (including virtual) interfaces, see ::MBG_NET_INTF_SETTINGS_IDX, ::MBG_NET_INTF_INFO_IDX
+ uint16_t num_dns_srvr; ///< max. configurable DNS server addresses, using ::MBG_IP_ADDR_IDX records
+ uint16_t num_dns_srch_dom; ///< max. configurable DNS search domain records, using ::MBG_NET_NAME_IDX records
+ uint16_t num_static_routes; ///< max. configurable static routes
+ uint16_t max_hostname_len; ///< max. length of hostname including trailing 0; if set to 0, max. length is 256 (see rfc1123)
+ uint32_t reserved_1; ///< currently reserved, always 0
+ uint32_t reserved_2; ///< currently reserved, always 0
+ uint32_t flags_1; ///< currently reserved, always 0
+ uint32_t flags_2; ///< currently reserved, always 0
+
+} MBG_NET_GLB_CFG_INFO;
+
+#define _mbg_swab_net_glb_cfg_info( _p ) \
+{ \
+ _mbg_swab_net_glb_cfg_settings( &(_p)->glb_settings ); \
+ _mbg_swab16( &(_p)->num_link ); \
+ _mbg_swab16( &(_p)->num_intf ); \
+ _mbg_swab16( &(_p)->num_dns_srvr ); \
+ _mbg_swab16( &(_p)->num_dns_srch_dom ); \
+ _mbg_swab16( &(_p)->num_static_routes ); \
+ _mbg_swab16( &(_p)->max_hostname_len ); \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->reserved_2 ); \
+ _mbg_swab32( &(_p)->flags_1 ); \
+ _mbg_swab32( &(_p)->flags_2 ); \
+}
+
+
+/**
+ * @brief An IPv4 or IPv6 network address
+ */
+typedef struct
+{
+ uint8_t type; ///< see ::MBG_IP_ADDR_TYPES
+ uint8_t reserved_1; ///< reserved, currently always 0 @todo Do we need this as scope indicator?
+ uint16_t reserved_2; ///< reserved, currently always 0
+
+ union
+ {
+ IP4_ADDR ip4_addr; ///< IPv4 address if ::MBG_IP_ADDR::type == MBG_IP_ADDR_TYPE_IP4
+ IP6_ADDR ip6_addr; ///< IPv6 address if ::MBG_IP_ADDR::type == MBG_IP_ADDR_TYPE_IP6
+ } u_addr;
+
+} MBG_IP_ADDR;
+
+
+/**
+ * @brief An IPv4 or IPv6 network address, plus index
+ */
+typedef struct
+{
+ uint16_t idx;
+ MBG_IP_ADDR addr; ///< network address
+
+} MBG_IP_ADDR_IDX;
+
+
+/**
+ * @brief Network host or domain name
+ */
+typedef struct
+{
+ MBG_HOSTNAME name;
+
+} MBG_NET_NAME;
+
+
+/**
+ * @brief Network host or domain name, plus index
+ */
+typedef struct
+{
+ uint16_t idx;
+ MBG_NET_NAME net_name;
+
+} MBG_NET_NAME_IDX;
+
+
+
+/**
+ * @brief Link (physical interface) specific settings
+ */
+typedef struct
+{
+ MBG_MAC_ADDR mac_addr; ///< Physical hardware address
+ MBG_MAC_ADDR broadcast; ///< Physical broadcast address
+ uint32_t mtu; ///< Max. packet size in bytes
+ uint32_t states; ///< see ::MBG_NET_LINK_STATE_BITS
+ uint32_t flags; ///< Reserved, currently 0
+ uint32_t reserved_1; ///< Reserved, currently 0
+ uint32_t reserved_2; ///< Reserved, currently 0
+ uint16_t bond_idx; ///< Current primary slave link index in ::MBG_NET_LINK_ROLE_MASTER role,
+ ///< current bonding master link index in ::MBG_NET_LINK_ROLE_SLAVE role,
+ ///< otherwise reserved and usually 0.
+ uint8_t speed_mode; ///< see ::MBG_NET_LINK_MODES
+ uint8_t port; ///< see ::MBG_NET_LINK_PORTS
+ uint8_t role; ///< see ::MBG_NET_LINK_ROLES
+ uint8_t reserved[3]; ///< Alignment. Can be used in future for usefull stuff.
+//##+++++ TODO check reserved above
+ uint32_t role_flags; ///< see ::MBG_NET_LINK_ROLE_BITS
+ uint32_t role_value; ///< Additional role parameters depending on role and role_flags,
+ ///< e.g. if role is master and flags contain bonding.
+ ///< See ::MBG_NET_LINK_BOND_MODES.
+} MBG_NET_LINK_SETTINGS;
+
+#define _mbg_swab_net_link_settings( _p ) \
+{ \
+ _mbg_swab32( &(_p)->mtu ); \
+ _mbg_swab32( &(_p)->states ); \
+ _mbg_swab32( &(_p)->flags ); \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->reserved_2 ); \
+ _mbg_swab16( &(_p)->bond_idx ); \
+ _mbg_swab32( &(_p)->role_flags ); \
+ _mbg_swab32( &(_p)->role_value ); \
+}
+
+/**
+ * @brief Link (physical interface) specific settings, plus index
+ */
+typedef struct
+{
+ uint16_t idx; ///< 0..::MBG_NET_GLB_CFG_INFO::num_link-1
+ MBG_NET_LINK_SETTINGS settings;
+
+} MBG_NET_LINK_SETTINGS_IDX;
+
+
+/**
+ * @brief Link (physical interface) specific settings, flags and supported features
+ */
+typedef struct
+{
+ MBG_NET_LINK_SETTINGS link_settings; ///< see ::MBG_NET_LINK_SETTINGS
+ uint32_t supp_opts; ///< see ::MBG_NET_LINK_OPT_MASKS
+ uint32_t supp_speed_modes; ///< see ::MBG_NET_LINK_MODE_MASKS
+ uint32_t supp_link_ports; ///< see ::MBG_NET_LINK_PORT_MASKS
+ uint32_t supp_states; ///< see ::MBG_NET_LINK_STATE_MASKS
+ uint32_t reserved_2;
+ uint32_t reserved_3;
+
+} MBG_NET_LINK_INFO;
+
+#define _mbg_swab_net_link_info( _p ) \
+{ \
+ _mbg_swab_net_link_settings( &(_p)->link_settings ); \
+ _mbg_swab32( &(_p)->supp_opts ); \
+ _mbg_swab32( &(_p)->supp_speed_modes ); \
+ _mbg_swab32( &(_p)->supp_link_ports ); \
+ _mbg_swab32( &(_p)->supp_states ); \
+ _mbg_swab32( &(_p)->reserved_2 ); \
+ _mbg_swab32( &(_p)->reserved_3 ); \
+}
+
+
+/**
+ * @brief Query MBG_NET_LINK_INFO by its index
+ */
+typedef struct
+{
+ uint16_t idx; ///< 0..::MBG_NET_GLB_CFG_INFO::num_link-1
+ MBG_NET_LINK_INFO info;
+
+} MBG_NET_LINK_INFO_IDX;
+
+
+/**
+ * @brief Interface specific settings, flags and supported features
+ *
+ * @note Use link_mac and role to identify uniquely its associated network link.
+ */
+typedef struct
+{
+ uint8_t cmd; ///< see ::MBG_NET_LOG_INTF_CMDS
+ uint8_t role; ///< see ::MBG_NET_LOG_INTF_ROLES
+ uint16_t reserved_1; ///< Reserved, currently 0
+ uint32_t role_value; ///< Role specific value. E.g. VLAN ID
+ uint32_t flags; ///< Reserved, currently 0
+ uint32_t reserved_2; ///< Reserved, currently 0
+ MBG_IP_ADDR ip; ///< IP address associated with this interface
+ MBG_IP_ADDR gateway; ///< Interface specific. Reserved for future use. see ::MBG_IP_ADDR and ::MBG_NET_INTF_BIT_EXT_ROUTING
+ MBG_MAC_ADDR link_mac; ///< Unique identifier for related link (physical) interface
+ uint8_t prefix; ///< Subnet mask bits for CIDR notation, e.g. /24
+ uint8_t reserved_3; ///< Reserved, currently 0
+
+} MBG_NET_INTF_SETTINGS;
+
+
+/**
+ * @brief Query MBG_NET_INTF_INFO by its index
+ */
+typedef struct
+{
+ uint16_t idx; ///< 0..::MBG_NET_GLB_CFG_INFO::num_intf-1
+ MBG_NET_INTF_SETTINGS settings;
+
+} MBG_NET_INTF_SETTINGS_IDX;
+
+
+/**
+ * @brief Interface specific settings, flags and supported features
+ */
+typedef struct
+{
+ MBG_NET_INTF_SETTINGS intf_settings;
+ uint32_t supp_flags; ///< see ::MBG_NET_INTF_MASKS
+ uint32_t reserved_1; ///< Reserved, currently 0
+ uint32_t reserved_2; ///< Reserved, currently 0
+
+} MBG_NET_INTF_INFO;
+
+
+/**
+ * @brief Query MBG_NET_INTF_INFO by its index
+ */
+typedef struct
+{
+ uint16_t idx; ///< 0..::MBG_NET_GLB_CFG_INFO::num_intf-1
+ MBG_NET_INTF_INFO info;
+
+} MBG_NET_INTF_INFO_IDX;
+
+
+/**
+ * @brief An IPv4 or IPv6 network address plus UDP or TCP port number
+ */
+typedef struct
+{
+ MBG_IP_ADDR addr; ///< see ::MBG_IP_ADDR
+
+ uint16_t port; ///< UDP or TCP port
+ uint16_t flags; ///< currently always 0
+ //##+++++ TODO should the flags field indicate if the port is UDP and/or TCP?
+
+} MBG_IP_ADDR_PORT;
+
+
+
+#if 0 //##++++++++++++++++++++++
+
+/**
+ * @brief Network service configuration
+ *
+ * Used to configure known services, e.g SSH, FTP, etc.
+ */
+typedef struct
+{
+ uint16_t svc_type; ///< see ::MBG_NET_SVC_TYPES
+ uint16_t reserved; ///< reserved, currently always 0
+ MBG_IP_ADDR_PORT settings; ///< The network address and port a service listens on
+ uint32_t flags; ///< reserved, currently always 0
+
+} MBG_NET_INTF_CFG;
+
+
+
+/**
+ * @brief
+ */
+typedef struct
+{
+ uint8_t b[IP6_ADDR_BYTES]; ///< bytes holding the address bits, b[0] == LSBs
+//##+++ uint8_t cidr_net_mask; ///< number of CIDR net mask bits, 0..::IP6_ADDR_BITS
+// uint8_t reserved; ///< not yet used, always 0
+// uint16_t flags; ///< not yet used, always 0
+
+} MBG_NET_INTF_CFG;
+
+#endif
+
+/** @} defgroup group_ext_net_cfg */
+
+/** @} defgroup group_net_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 with 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_P2P ) ///< see ::PTP_DELAY_MECH_P2P
+};
+
+
+#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
+ *
+ * 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.
+ *
+ * @note: A device in MULTICAST_AUTO role can be either master or slave,
+ * so the port state needs to be checked to determine the current
+ * mode of operation.
+ *
+ * @see ::PTP_ROLE_MASKS
+ * @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)
+ PTP_ROLE_BOTH_MASTER, ///< simultanous multicast and unicast master
+ N_PTP_ROLES ///< number of defined roles
+};
+
+
+/**
+ * @brief Bit mask associated with ::PTP_ROLES
+ *
+ * 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.
+ *
+ * @note: A device in MULTICAST_AUTO role can be either master or slave,
+ * so the port state needs to be checked to determine the current
+ * mode of operation.
+ *
+ * @see ::PTP_ROLES
+ * @see ::get_supp_ptp_role_mask
+ */
+enum PTP_ROLE_MASKS
+{
+ PTP_ROLE_MSK_MULTICAST_SLAVE = ( 1UL << PTP_ROLE_MULTICAST_SLAVE ), ///< see ::PTP_ROLE_MULTICAST_SLAVE
+ PTP_ROLE_MSK_UNICAST_SLAVE = ( 1UL << PTP_ROLE_UNICAST_SLAVE ), ///< see ::PTP_ROLE_UNICAST_SLAVE
+ PTP_ROLE_MSK_MULTICAST_MASTER = ( 1UL << PTP_ROLE_MULTICAST_MASTER ), ///< see ::PTP_ROLE_MULTICAST_MASTER
+ PTP_ROLE_MSK_UNICAST_MASTER = ( 1UL << PTP_ROLE_UNICAST_MASTER ), ///< see ::PTP_ROLE_UNICAST_MASTER
+ PTP_ROLE_MSK_MULTICAST_AUTO = ( 1UL << PTP_ROLE_MULTICAST_AUTO ), ///< see ::PTP_ROLE_MULTICAST_AUTO
+ PTP_ROLE_MSK_BOTH_MASTER = ( 1UL << PTP_ROLE_BOTH_MASTER ) ///< see ::PTP_ROLE_BOTH_MASTER
+};
+
+
+#define PTP_ROLE_MSK_SLAVES ( PTP_ROLE_MSK_MULTICAST_SLAVE \
+ | PTP_ROLE_MSK_UNICAST_SLAVE \
+ | PTP_ROLE_MSK_MULTICAST_AUTO )
+
+#define PTP_ROLE_MSK_MASTERS ( PTP_ROLE_MSK_MULTICAST_MASTER \
+ | PTP_ROLE_MSK_UNICAST_MASTER \
+ | PTP_ROLE_MSK_MULTICAST_AUTO \
+ | PTP_ROLE_BOTH_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)", \
+ "UC+MC Master" \
+}
+
+
+/**
+ * @brief Short name strings for defined PTP roles
+ *
+ * @see ::PTP_ROLES
+ * @see ::PTP_ROLE_STRS
+ */
+#define PTP_ROLE_STRS_SHORT \
+{ \
+ "MCS", \
+ "UCS", \
+ "MCM", \
+ "UCM", \
+ "MCA", \
+ "UMM" \
+}
+
+
+/**
+ * @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
+ */
+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
+
+ uint8_t parent_clock_class; ///< clock class of the parent node
+ uint8_t parent_clock_accuracy; ///< clock accuracy of the parent node, see ::PTP_CLOCK_ACCURACIES
+
+ uint16_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_swab16( &(_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
+ PTP_FLAG_ONE_STEP, ///< One-Step Clock active
+ 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
+ PTP_FLAG_MSK_ONE_STEP = ( 1UL << PTP_FLAG_ONE_STEP ) ///< see ::PTP_FLAG_ONE_STEP
+};
+
+
+
+/**
+ * @brief A structure used to configure a PTP port
+ */
+typedef struct
+{
+ uint16_t nw_prot; ///< see ::PTP_NW_PROTS
+ uint8_t selected_presets; ///< selected PTP presets, see ::PTP_PRESETS
+ 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 opt_ext; ///< optional configuration extension, see ::PTP_OPT_EXTS
+ 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; ///< reserved, currently always 0
+ uint32_t flags; ///< see ::PTP_CFG_FLAG_MASKS
+
+} 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 ); \
+ _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_FLAG_MASKS
+ uint32_t supp_nw_prot; ///< a bit mask of supported network protocols, see ::PTP_NW_PROT_MASKS
+ uint32_t supp_opt_ext; ///< a bit mask of supported optional extensions, see ::PTP_OPT_EXT_MASKS
+ uint32_t supp_delay_mech; ///< a bit mask of supported delay mechanisms, see ::PTP_DELAY_MECH_MASKS
+
+} 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_opt_ext ); \
+ _mbg_swab32( &(_p)->supp_delay_mech ); \
+}
+
+
+
+/**
+ * @brief Flags bits used with PTP configuration
+ *
+ * Flags labeled [R/-] can only be used with ::PTP_CFG_INFO::supp_flags
+ * to indicate that the associated feature is supported in general.
+ *
+ * If a flag labeled [R/W] is set in ::PTP_CFG_INFO::supp_flags then
+ * this flag can also be used with ::PTP_CFG_SETTINGS::flags to control
+ * the associated feature.
+ *
+ * @note Originally, all devices supported the multicast slave role, so
+ * there was no extra flag to indicate this. However, some newer devices
+ * may not support the multicast slave role, so two new flags have been
+ * introduced to cope with this:
+ * If ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG is set then a different flag
+ * ::PTP_CFG_CAN_BE_MULTICAST_SLAVE needs to be checked to tell if
+ * the multicast slave role is supported, or not.
+ * If ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG is not set then the device
+ * definitely supports the multicast slave role.
+ *
+ * @see ::PTP_CFG_FLAG_MASKS
+ */
+enum PTP_CFG_FLAGS
+{
+ PTP_CFG_TIME_SCALE_IS_PTP, ///< [R/W] time scale is PTP/TAI, else arbitrary
+ PTP_CFG_V1_HW_COMPAT, ///< [R/W] maybe required for certain NIC chips, not used by Meinberg
+ PTP_CFG_CAN_BE_UNICAST_SLAVE, ///< [R/-] supports unicast slave role, see ::PTP_ROLE_UNICAST_SLAVE
+ PTP_CFG_CAN_BE_MULTICAST_MASTER, ///< [R/-] supports multicast master role, see ::PTP_ROLE_MULTICAST_MASTER
+ PTP_CFG_CAN_BE_UNICAST_MASTER, ///< [R/-] supports unicast master, see ::PTP_ROLE_UNICAST_MASTER
+ PTP_CFG_CAN_BE_MULTICAST_AUTO, ///< [R/-] can automatically become multicast master or slave, see ::PTP_CFG_CAN_BE_MULTICAST_AUTO
+ PTP_CFG_SUPP_UTC_VALID, ///< [R/-] ::PTP_FLAG_UTC_VALID bit in ::PTP_STATE::flags is supported
+ PTP_CFG_CAN_BE_BOTH_MASTER, ///< [R/-] supports unicast and multicast master role at the same time, see ::PTP_CFG_CAN_BE_BOTH_MASTER
+
+ PTP_CFG_HYBRID_MASTER, ///< [R/W] supports hybrid mode in master roles
+ PTP_CFG_HYBRID_SLAVE, ///< [R/W] supports hybrid mode in slave roles
+ PTP_CFG_ONE_STEP_MASTER, ///< [R/W] supports one-step mode in master roles
+ PTP_CFG_MNGMNT_MSGS_DISB, ///< [R/W] supports disabling of PTP management messages
+ PTP_CFG_SUPP_MCAST_SLAVE_FLAG, ///< [R/-] indicates that ::PTP_CFG_CAN_BE_MULTICAST_SLAVE flag is supported and can be checked
+ PTP_CFG_CAN_BE_MULTICAST_SLAVE, ///< [R/-] if ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG bit set, indicates if multicast slave role is supported
+ PTP_CFG_ONE_STEP_L2, ///< [R/-] supports the combination of One-Step and Layer2 mode
+ PTP_CFG_ONE_STEP_P2P, ///< [R/-] supports the combination of One-Step and P2P Delay Mechanism
+
+ N_PTP_CFG_FLAGS ///< the number of defined flags
+};
+
+
+/**
+ * @brief Bit masks used with ::PTP_CFG_INFO::supp_flags and ::PTP_CFG_SETTINGS::flags
+ *
+ * @see ::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
+ PTP_CFG_MSK_CAN_BE_BOTH_MASTER = ( 1UL << PTP_CFG_CAN_BE_BOTH_MASTER ), ///< see ::PTP_CFG_CAN_BE_BOTH_MASTER
+
+ PTP_CFG_MSK_HYBRID_MASTER = ( 1UL << PTP_CFG_HYBRID_MASTER ), ///< see ::PTP_CFG_HYBRID_MASTER
+ PTP_CFG_MSK_HYBRID_SLAVE = ( 1UL << PTP_CFG_HYBRID_SLAVE ), ///< see ::PTP_CFG_HYBRID_SLAVE
+ PTP_CFG_MSK_ONE_STEP_MASTER = ( 1UL << PTP_CFG_ONE_STEP_MASTER ), ///< see ::PTP_CFG_ONE_STEP_MASTER
+ PTP_CFG_MSK_MNGMNT_MSGS_DISB = ( 1UL << PTP_CFG_MNGMNT_MSGS_DISB ), ///< see ::PTP_CFG_MNGMNT_MSGS_DISB
+ PTP_CFG_MSK_SUPP_MCAST_SLAVE_FLAG = ( 1UL << PTP_CFG_SUPP_MCAST_SLAVE_FLAG ), ///< see ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG
+ PTP_CFG_MSK_CAN_BE_MULTICAST_SLAVE = ( 1UL << PTP_CFG_CAN_BE_MULTICAST_SLAVE ), ///< see ::PTP_CFG_CAN_BE_MULTICAST_SLAVE
+ PTP_CFG_MSK_ONE_STEP_L2 = ( 1UL << PTP_CFG_ONE_STEP_L2 ), ///< see ::PTP_CFG_ONE_STEP_L2
+ PTP_CFG_MSK_ONE_STEP_P2P = ( 1UL << PTP_CFG_ONE_STEP_P2P ), ///< see ::PTP_CFG_ONE_STEP_P2P
+};
+
+
+
+/** @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 Known optional PTP protocol extensions, see ::PTP_CFG_SETTINGS::opt_ext
+ *
+ * @see ::PTP_OPT_EXT_MASKS
+ */
+enum PTP_OPT_EXTS
+{
+ PTP_OPT_EXT_NONE, ///< no extension used
+ PTP_OPT_EXT_POWER, ///< IEEE C37.238 profile extension
+ PTP_OPT_EXT_TELECOM, ///< ITU-T G.8265.1 profile extension
+ N_PTP_OPT_EXT ///< number of known optional extension
+};
+
+
+/**
+ * @brief Flag masks used with ::PTP_CFG_INFO::supp_opt_ext
+ *
+ * @see ::PTP_OPT_EXTS
+ */
+enum PTP_OPT_EXT_MASKS
+{
+ PTP_MSK_OPT_EXT_NONE = ( 1UL << PTP_OPT_EXT_NONE ), ///< this is actually not used, see ::PTP_OPT_EXT_NONE
+ PTP_MSK_OPT_EXT_POWER = ( 1UL << PTP_OPT_EXT_POWER ), ///< see ::PTP_OPT_EXT_POWER
+ PTP_MSK_OPT_EXT_TELECOM = ( 1UL << PTP_OPT_EXT_TELECOM ) ///< see ::PTP_OPT_EXT_TELECOM
+};
+
+
+
+/**
+ * @brief Enumeration of PTP cfg presets used with ::PTP_CFG_SETTINGS::selected_presets
+ *
+ * This can be used by configuration programs to determine
+ * the last recently selected presets.
+ *
+ * @see ::PTP_PRESETS_STRS
+ * @see ::PTP_PRESETS_MASKS
+ */
+enum PTP_PRESETS
+{
+ PTP_PRESETS_CUSTOM, ///< customizable, always supported
+ PTP_PRESETS_DFLT_E2E, ///< pure IEEE1588-2008 (PTPv2) with E2E
+ PTP_PRESETS_DFLT_P2P, ///< pure IEEE1588-2008 (PTPv2) with P2P
+ PTP_PRESETS_POWER, ///< IEEE C37.238 profile extension, only if ::PTP_MSK_OPT_EXT_POWER is set
+ PTP_PRESETS_TELECOM, ///< ITU-T G.8265.1 profile extension, only if ::PTP_MSK_OPT_EXT_TELECOM is set
+ N_PTP_PRESETS ///< number of supported profiles
+};
+
+
+/**
+ * @brief Flag masks used with ::PTP_CFG_INFO::supp_opt_ext
+ *
+ * @see ::PTP_PRESETS
+ */
+enum PTP_PRESETS_MASKS
+{
+ PTP_MSK_PRESETS_CUSTOM = ( 1UL << PTP_PRESETS_CUSTOM ), ///< see ::PTP_PRESETS_CUSTOM
+ PTP_MSK_PRESETS_DFLT_E2E = ( 1UL << PTP_PRESETS_DFLT_E2E ), ///< see ::PTP_PRESETS_DFLT_E2E
+ PTP_MSK_PRESETS_DFLT_P2P = ( 1UL << PTP_PRESETS_DFLT_P2P ), ///< see ::PTP_PRESETS_DFLT_P2P
+ PTP_MSK_PRESETS_POWER = ( 1UL << PTP_PRESETS_POWER ), ///< see ::PTP_PRESETS_POWER
+ PTP_MSK_PRESETS_TELECOM = ( 1UL << PTP_PRESETS_TELECOM ) ///< see ::PTP_PRESETS_TELECOM
+};
+
+
+/**
+ * @brief Name strings for defined PTP presets
+ *
+ * @see ::PTP_PRESETS
+ */
+#define PTP_PRESETS_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;
+ TZDL tzdl;
+
+} PTP_POWER_PROFILE_CFG;
+
+#define _mbg_swab_ptp_power_profile_cfg( _p ) \
+{ \
+ _mbg_swab32( &(_p)->network_incaccuracy ); \
+ _mbg_swab8( &(_p)->grandmaster_id ); \
+ _mbg_swab8( &(_p)->reserved_1 ); \
+ _mbg_swab16( &(_p)->reserved_2 ); \
+ _mbg_swab_tzdl( &(_p)->tzdl ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @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 ); \
+}
+
+/** @} defgroup group_ptp */
+
+
+
+/**
+ * @defgroup group_ntp Definitions used with NTP
+ *
+ * @{ */
+
+
+/**
+ * @brief Enumeration of known NTP roles
+ *
+ * @see ::NTP_GLB_SETTINGS::ntp_role
+ */
+enum NTP_ROLES
+{
+ NTP_ROLE_NONE = 0, ///< NTP services disabled
+ NTP_ROLE_CLIENT, ///< NTP client
+ NTP_ROLE_SERVER, ///< NTP server
+ NTP_ROLE_CLIENT_SERVER, ///< both NTP client and server
+ N_NTP_ROLES ///< number of supported roles
+};
+
+
+/**
+ * @brief Flag masks associated with NTP roles
+ *
+ * @see ::NTP_GLB_INFO::supp_ntp_roles
+ */
+enum NTP_ROLE_MASKS
+{
+ NTP_MSK_ROLE_NONE = ( 1UL << NTP_ROLE_NONE ), ///< see ::NTP_ROLE_NONE
+ NTP_MSK_ROLE_CLIENT = ( 1UL << NTP_ROLE_CLIENT ), ///< see ::NTP_ROLE_CLIENT
+ NTP_MSK_ROLE_SERVER = ( 1UL << NTP_ROLE_SERVER ), ///< see ::NTP_ROLE_SERVER
+ NTP_MSK_ROLE_CLIENT_SERVER = ( 1UL << NTP_ROLE_CLIENT_SERVER ), ///< see ::NTP_ROLE_CLIENT_SERVER
+};
+
+
+/**
+ * @brief Enumeration of global NTP flags
+ *
+ * @see ::NTP_FLAG_MASKS
+ */
+enum NTP_FLAGS
+{
+ NTP_IPV4, ///< NTP via IPv4/UDP
+ NTP_IPV6, ///< NTP via IPv6/UDP
+ NTP_SYMM_KEYS, ///< support symmetric key authentication (MD5)
+ NTP_AUTOKEY, ///< include authentication fields encrypted using the autokey scheme
+ NTP_BURST, ///< send a burst of eight packets at each polling cycle
+ NTP_IBURST, ///< send a burst of eight packets at the first polling cycle
+ NTP_NO_SELECT, ///< marks a server as not to be selected for time synchronization
+ NTP_PREEMPT, ///< specifies the association as preemptable rather than the default persistent
+ NTP_PREFER, ///< marks a server as preferred peer for time synchronization
+ NTP_TRUE, ///< force the association to assume truechimer status; always survive the selection and clustering algorithms
+ NTP_BROADCAST, ///< transmission via broadcast, point to multipoint
+ NTP_MULTICAST, ///< transmission via multicast, point to multipoint
+ NTP_MANYCAST, ///< transmission via manycast, point to multipoint
+ NTP_POOL, ///< peer shall be treated as a pool server
+ N_NTP_FLAGS
+};
+
+
+/**
+ * @brief Flag masks associated with ::NTP_FLAGS
+ *
+ * Used with ::NTP_GLB_INFO::supp_flags, ::NTP_GLB_SETTINGS::flags, NTP_CLNT_MODE_INFO::supp_flags,
+ * ::NTP_CLNT_MODE_INFO::supp_peer_flags, ::NTP_CLNT_MODE_SETTINGS::flags, ::NTP_PEER_SETTINGS::flags,
+ * ::NTP_SRV_MODE_SETTINGS::flags, and ::NTP_SRV_MODE_INFO::supp_flags.
+ *
+ * @todo We may need structures to configure symmetric keys, and autokey certificates.
+ *
+ * @see ::NTP_FLAGS
+ */
+enum NTP_FLAG_MASKS
+{
+ NTP_MSK_IPV4 = ( 1UL << NTP_IPV4 ), ///< see ::NTP_IPV4
+ NTP_MSK_IPV6 = ( 1UL << NTP_IPV6 ), ///< see ::NTP_IPV6
+ NTP_MSK_SYMM_KEYS = ( 1UL << NTP_SYMM_KEYS ), ///< see ::NTP_SYMM_KEYS
+ NTP_MSK_AUTOKEY = ( 1UL << NTP_AUTOKEY ), ///< see ::NTP_AUTOKEY
+ NTP_MSK_BURST = ( 1UL << NTP_BURST ), ///< see ::NTP_BURST
+ NTP_MSK_IBURST = ( 1UL << NTP_IBURST ), ///< see ::NTP_IBURST
+ NTP_MSK_NO_SELECT = ( 1UL << NTP_NO_SELECT ), ///< see ::NTP_NO_SELECT
+ NTP_MSK_PREEMPT = ( 1UL << NTP_PREEMPT ), ///< see ::NTP_PREEMPT
+ NTP_MSK_PREFER = ( 1UL << NTP_PREFER ), ///< see ::NTP_PREFER
+ NTP_MSK_TRUE = ( 1UL << NTP_TRUE ), ///< see ::NTP_TRUE
+ NTP_MSK_BROADCAST = ( 1UL << NTP_BROADCAST ), ///< see ::NTP_BROADCAST
+ NTP_MSK_MULTICAST = ( 1UL << NTP_MULTICAST ), ///< see ::NTP_MULTICAST
+ NTP_MSK_MANYCAST = ( 1UL << NTP_MANYCAST ), ///< see ::NTP_MANYCAST
+ NTP_MSK_POOL = ( 1UL << NTP_POOL ) ///< see ::NTP_POOL
+};
+
+
+/**
+ * @brief Global configuration settings of an NTP device (client/server)
+ *
+ * This structure should be sent to an NTP device to configure global settings
+ */
+typedef struct
+{
+ uint8_t ntp_role; ///< one of the supported NTP roles, see ::NTP_ROLES
+ uint8_t reserved_1; ///< reserved, currently 0
+ uint16_t reserved_2; ///< reserved, currently 0
+
+ uint32_t reserved_3; ///< reserved, currently 0
+ uint32_t reserved_4; ///< reserved, currently 0
+
+ uint32_t flags; ///< NTP flags, see ::NTP_FLAG_MASKS
+
+} NTP_GLB_SETTINGS;
+
+#define _mbg_swab_ntp_glb_settings( _p ) \
+{ \
+ _mbg_swab16( &(_p)->reserved_2 ); \
+ _mbg_swab32( &(_p)->reserved_3 ); \
+ _mbg_swab32( &(_p)->reserved_4 ); \
+ _mbg_swab32( &(_p)->cfg_flags ); \
+}
+
+
+
+/**
+ * @brief Global configuration info of an NTP device (client/server)
+ *
+ * This structure can be used to determine possible configurations of an NTP device
+ */
+typedef struct
+{
+ NTP_GLB_SETTINGS settings; ///< current configuration settings
+
+ uint32_t reserved_1; ///< reserved, currently 0
+ uint32_t reserved_2; ///< reserved, currently 0
+
+ uint32_t supp_ntp_roles; ///< supported NTP roles, see ::NTP_ROLE_MASKS
+ uint32_t supp_flags; ///< supported NTP flags, see ::NTP_FLAG_MASKS
+
+} NTP_GLB_INFO;
+
+#define _mbg_swab_ntp_glb_info( _p ) \
+{ \
+ _mbg_swab_ntp_glb_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->reserved_2 ); \
+ _mbg_swab32( &(_p)->supp_ntp_roles ); \
+ _mbg_swab32( &(_p)->supp_flags ); \
+}
+
+
+/**
+ * @brief Client settings of an NTP device
+ *
+ * This structure should be sent to an NTP client to configure client parameters
+ */
+typedef struct
+{
+ uint32_t reserved_1; ///< reserved, currently 0
+ uint32_t reserved_2; ///< reserved, currently 0
+
+ uint32_t flags; ///< NTP flags, see ::NTP_FLAG_MASKS
+
+} NTP_CLNT_MODE_SETTINGS;
+
+#define _mbg_swab_ntp_clnt_mode_settings( _p ) \
+{ \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->reserved_2 ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Client settings info of an NTP device
+ *
+ * This structure can be used to determine possible NTP client settings and the current configuration
+ */
+typedef struct
+{
+ NTP_CLNT_MODE_SETTINGS settings;
+
+ uint8_t n_supp_peers; ///< maximal number of configurable peers
+ uint8_t n_supp_pref_peers; ///< maximal number of configurable preferred ref sources
+ uint8_t poll_intv_min; ///< minimal supported NTP polling interval
+ uint8_t poll_intv_max; ///< maximal supported NTP polling interval
+
+ uint32_t reserved_1; ///< reserved, currently 0
+ uint32_t reserved_2; ///< reserved, currently 0
+
+ uint32_t supp_flags; ///< supported NTP flags, see ::NTP_FLAG_MASKS
+ uint32_t supp_peer_flags; ///< supported NTP flags for peers, see ::NTP_FLAG_MASKS
+
+} NTP_CLNT_MODE_INFO;
+
+#define _mbg_swab_ntp_clnt_mode_info( _p ) \
+{ \
+ _mbg_swab_ntp_clnt_mode_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->reserved_2 ); \
+ _mbg_swab32( &(_p)->supp_flags ); \
+ _mbg_swab32( &(_p)->supp_peer_flags ); \
+}
+
+
+/**
+ * @brief Peer settings for NTP devices to configure an upload NTP server
+ *
+ * This structure should be read from the NTP client device to retrieve the
+ * current settings and capabilities. The number of supported peers is
+ * ::NTP_CLNT_MODE_INFO::n_supp_peers.
+ *
+ * @note The ::NTP_PEER_SETTINGS_IDX structure should be send back
+ * to the device to save the configuration.
+ */
+typedef struct
+{
+ MBG_HOSTNAME hostname; ///< hostname or IP address of the peer
+
+ uint8_t min_poll; ///< minimal configurable NTP polling interval
+ uint8_t max_poll; ///< maximal configurable NTP polling interval
+ uint8_t ttl; ///< time-to-live to use with broadcast/multicast/manycast
+ uint8_t reserved_1; ///< reserved, currently 0
+
+ uint32_t reserved_2; ///< reserved, currently 0
+ uint32_t reserved_3; ///< reserved, currently 0
+ uint32_t reserved_4; ///< reserved, currently 0
+
+ uint32_t flags; ///< additional options configured, see ::NTP_FLAG_MASKS
+
+} NTP_PEER_SETTINGS;
+
+#define _mbg_swab_ntp_peer_settings( _p ) \
+{ \
+ _mbg_swab32( &(_p)->reserved_2 ); \
+ _mbg_swab32( &(_p)->reserved_3 ); \
+ _mbg_swab32( &(_p)->reserved_4 ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+/**
+ * @brief Peer settings for NTP devices
+ *
+ * @see ::NTP_PEER_SETTINGS
+ */
+typedef struct
+{
+ uint32_t idx;
+ NTP_PEER_SETTINGS peer_settings;
+
+} NTP_PEER_SETTINGS_IDX;
+
+#define _mbg_swab_ntp_peer_settings_idx( _p ) \
+{ \
+ _mbg_swab32( &(_p)->idx ); \
+ _mbg_swab_ntp_peer_settings( &(_p)->peer_settings ); \
+}
+
+#ifdef DEBUG
+/**
+ * @brief Dummy structure for later NTP server implementations, not used, yet
+ */
+typedef struct
+{
+ uint32_t reserved_1; ///< reserved, currently 0
+ uint32_t reserved_2; ///< reserved, currently 0
+
+ uint32_t flags; ///< NTP flags, see ::NTP_FLAG_MASKS
+
+} NTP_SRV_MODE_SETTINGS;
+
+#define _mbg_swab_ntp_srv_mode_settings( _p ) \
+{ \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->reserved_2 ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/**
+ * @brief Dummy structure for later NTP server implementations
+ */
+typedef struct
+{
+ NTP_SRV_MODE_SETTINGS settings;
+
+ uint32_t reserved_1; ///< reserved, currently 0
+ uint32_t reserved_2; ///< reserved, currently 0
+
+ uint32_t supp_flags; ///< supported NTP flags, see ::NTP_FLAG_MASKS
+
+} NTP_SRV_MODE_INFO;
+
+#define _mbg_swab_ntp_srv_mode_info( _p ) \
+{ \
+ _mbg_swab_ntp_srv_mode_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->reserved_2 ); \
+ _mbg_swab32( &(_p)->supp_flags ); \
+}
+#endif // DEBUG
+
+
+/**
+ * @brief Structure that represents a timestamp in NTP Short Format
+ *
+ * Maximal value for seconds is 65535.
+ * Resolution of fractions is 15 microseconds.
+ */
+typedef struct
+{
+ uint16_t seconds;
+ uint16_t fractions;
+
+} NTP_SHORT_TSTAMP;
+
+#define _mbg_swab_ntp_short_tstamp( _p ) \
+{ \
+ _mbg_swab16( &(_p)->seconds ); \
+ _mbg_swab16( &(_p)->fractions ); \
+}
+
+
+/**
+ * @brief Structure that represents a timestamp in NTP Timestamp Format
+ */
+typedef struct
+{
+ uint32_t seconds; ///< seconds since NTP epoch, see ::NTP_SEC_BIAS
+ uint32_t fractions; ///< binary fractional part of a second, 0xFFFFFFFF -> 0.9999999... s (resolution 2^-32s =~ 233 ps)
+
+} NTP_TSTAMP;
+
+#define _mbg_swab_ntp_tstamp( _p ) \
+{ \
+ _mbg_swab32( &(_p)->seconds ); \
+ _mbg_swab32( &(_p)->fractions ); \
+}
+
+
+/**
+ * @brief Enumeration of known NTP implementations
+ *
+ * Used with ::NTP_SYS_STATE::impl_type
+ */
+enum NTP_IMPL
+{
+ NTP_IMPL_UNKNOWN = 0, ///< Unknown NTP implementation
+ NTP_IMPL_NTPD, ///< Network Time Protocol daemon (ntpd)
+ NTP_IMPL_NTPDATE, ///< NTP client only (ntpdate)
+ NTP_IMPL_SNTP, ///< Simple Network Time Protocol (sntp)
+ NTP_IMPL_W32TIME, ///< Windows time service (w32time)
+ NTP_IMPL_MBGNTP, ///< Meinberg NTP implementation (mbgntp)
+ N_NTP_IMPLS
+};
+
+/*
+ * Default initializers for English leapsecond string names. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+#define MBG_NTP_IMPL_STR_ENG "Implemetation Type:"
+#define MBG_NTP_IMPL_STR_ENG_UNKNOWN "Unknown NTP implementation"
+#define MBG_NTP_IMPL_STR_ENG_NTPD "Network Time Protocol daemon (ntpd)"
+#define MBG_NTP_IMPL_STR_ENG_NTPDATE "NTP client only (ntpdate)"
+#define MBG_NTP_IMPL_STR_ENG_SNTP "Simple Network Time Protocol (sntp)"
+#define MBG_NTP_IMPL_STR_ENG_W32TIME "Windows time service (w32time)"
+#define MBG_NTP_IMPL_STR_ENG_MBGNTP "Meinberg NTP implementation (mbgntp)"
+
+
+#define MBG_NTP_IMPL_NAMES_ENG \
+{ \
+ MBG_NTP_IMPL_STR_ENG_UNKNOWN, \
+ MBG_NTP_IMPL_STR_ENG_NTPD, \
+ MBG_NTP_IMPL_STR_ENG_NTPDATE, \
+ MBG_NTP_IMPL_STR_ENG_SNTP, \
+ MBG_NTP_IMPL_STR_ENG_W32TIME, \
+ MBG_NTP_IMPL_STR_ENG_MBGNTP \
+}
+
+
+/**
+ * @brief Enumeration of CPU types using NTP
+ *
+ * Used with ::NTP_SYS_STATE::cpu_type
+ */
+enum NTP_CPU_TYPES
+{
+ NTP_CPU_TYPE_UNKNOWN = 0,
+ NTP_CPU_TYPE_X86,
+ NTP_CPU_TYPE_I386,
+ NTP_CPU_TYPE_I486,
+ NTP_CPU_TYPE_I586,
+ NTP_CPU_TYPE_I686,
+ NTP_CPU_TYPE_X64,
+ NTP_CPU_TYPE_X86_64,
+ NTP_CPU_TYPE_AMD64,
+ NTP_CPU_TYPE_SUN4U,
+ NTP_CPU_TYPE_ARM,
+ N_NTP_CPU_TYPES
+};
+
+
+/**
+ * @brief Name strings for known CPU types using NTP
+ *
+ * @see ::NTP_CPU_TYPES
+ */
+#define NTP_CPU_TYPES_STRS \
+{ \
+ "Unknown", \
+ "x86", \
+ "i386", \
+ "i486", \
+ "i586", \
+ "i686", \
+ "x64", \
+ "x86_64", \
+ "amd64", \
+ "sun4u", \
+ "arm" \
+}
+
+
+/**
+ * @brief Enumeration of operating systems using NTP
+ *
+ * Used with ::NTP_SYS_STATE::system
+*/
+enum NTP_SYSTEMS
+{
+ NTP_SYSTEM_UNKNOWN = 0,
+ NTP_SYSTEM_NONE,
+ NTP_SYSTEM_WINDOWS,
+ NTP_SYSTEM_LINUX,
+ NTP_SYSTEM_BSD,
+ NTP_SYSTEM_SOLARIS,
+ N_NTP_SYSTEMS
+};
+
+
+/**
+ * @brief Name strings for operating systens using NTP
+ *
+ * @see ::NTP_SYSTEMS
+ */
+#define NTP_SYSTEMS_STRS \
+{ \
+ "Unknown", \
+ "No OS", \
+ "Windows", \
+ "Linux", \
+ "BSD", \
+ "Solaris" \
+}
+
+
+/**
+ * @brief Enumeration of NTP leap indication bits
+ *
+ * Used with ::NTP_SYS_STATE::leap_ind
+ *
+ */
+enum NTP_LI_BITS
+{
+ NTP_LEAP_NONE = 0, ///< normal synchronized state
+ NTP_LEAP_ADD_SEC, ///< insert second after 23:59:59 of the current day
+ NTP_LEAP_DEL_SEC, ///< delete second 23:59:59 of the current day
+ NTP_LEAP_ALARM, ///< never synchronized
+ N_NTP_LI_BITS
+};
+
+/*
+ * Default initializers for English leapsecond string names. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+#define MBG_NTP_LEAP_STR_ENG "Leapsecond indication:"
+#define MBG_NTP_LEAP_STR_ENG_NONE "None"
+#define MBG_NTP_LEAP_STR_ENG_ADD_SEC "Insert second"
+#define MBG_NTP_LEAP_STR_ENG_DEL_SEC "Delete second"
+#define MBG_NTP_LEAP_STR_ENG_ALARM "Alarm"
+
+#define MBG_NTP_LEAP_NAMES_ENG \
+{ \
+ MBG_NTP_LEAP_STR_ENG_NONE, \
+ MBG_NTP_LEAP_STR_ENG_ADD_SEC, \
+ MBG_NTP_LEAP_STR_ENG_DEL_SEC, \
+ MBG_NTP_LEAP_STR_ENG_ALARM \
+}
+
+
+/**
+ * @brief Enumeration of NTP synchronization source bits
+ *
+ * Used with ::NTP_SYS_STATE::sys_sync_src
+ *
+ */
+enum NTP_SYNC_SRC_BITS
+{
+ NTP_SYNC_SRC_UNSPEC = 0, ///< not yet synchronized
+ NTP_SYNC_SRC_PPS, ///< pulse-per-second signal (Cs, Ru, GPS, etc.)
+ NTP_SYNC_SRC_LF_RADIO, ///< VLF/LF radio (WWVB, DCF77, etc.)
+ NTP_SYNC_SRC_HF_RADIO, ///< MF/HF radio (WWV, etc.)
+ NTP_SYNC_SRC_UHF_RADIO, ///< VHF/UHF radio/satellite (GPS, Galileo, etc.)
+ NTP_SYNC_SRC_LOCAL, ///< local timecode (IRIG, LOCAL driver, etc.)
+ NTP_SYNC_SRC_NTP, ///< NTP
+ NTP_SYNC_SRC_OTHER, ///< other (IEEE 1588, openntp, crony, etc.)
+ NTP_SYNC_SRC_WRISTWATCH, ///< eyeball and wristwatch
+ NTP_SYNC_SRC_TELEPHONE, ///< telephone modem (ACTS, PTB, etc.)
+ N_NTP_SYNC_SRC_BITS
+};
+
+/*
+ * Default initializers for English sync source string names. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+#define MBG_NTP_SYNC_SRC_STR_ENG_LABEL "Sync Source:"
+#define MBG_NTP_SYNC_SRC_STR_ENG_UNSPEC "Not yet synchronized"
+#define MBG_NTP_SYNC_SRC_STR_ENG_PPS "Pulse per second signal"
+#define MBG_NTP_SYNC_SRC_STR_ENG_LF_RADIO "VLF/LF radio"
+#define MBG_NTP_SYNC_SRC_STR_ENG_HF_RADIO "MF/HF radio"
+#define MBG_NTP_SYNC_SRC_STR_ENG_UHF_RADIO "VHF/UHF radio/satellite"
+#define MBG_NTP_SYNC_SRC_STR_ENG_LOCAL "local timecode"
+#define MBG_NTP_SYNC_SRC_STR_ENG_NTP "NTP"
+#define MBG_NTP_SYNC_SRC_STR_ENG_OTHER "other"
+#define MBG_NTP_SYNC_SRC_STR_ENG_WRISTWATCH "eyeball and wristwatch"
+#define MBG_NTP_SYNC_SRC_STR_ENG_TELEPHONE "telephone modem"
+
+#define MBG_NTP_SYNC_SRC_NAMES_ENG \
+{ \
+ MBG_NTP_SYNC_SRC_STR_ENG_UNSPEC, \
+ MBG_NTP_SYNC_SRC_STR_ENG_PPS, \
+ MBG_NTP_SYNC_SRC_STR_ENG_LF_RADIO, \
+ MBG_NTP_SYNC_SRC_STR_ENG_HF_RADIO, \
+ MBG_NTP_SYNC_SRC_STR_ENG_UHF_RADIO, \
+ MBG_NTP_SYNC_SRC_STR_ENG_LOCAL, \
+ MBG_NTP_SYNC_SRC_STR_ENG_NTP, \
+ MBG_NTP_SYNC_SRC_STR_ENG_OTHER, \
+ MBG_NTP_SYNC_SRC_STR_ENG_WRISTWATCH, \
+ MBG_NTP_SYNC_SRC_STR_ENG_TELEPHONE \
+}
+
+
+/**
+ * @brief Enumeration of NTP system event message bits
+ *
+ * Used with ::NTP_SYS_STATE::sys_rec_evt
+ *
+ */
+enum NTP_SYS_EVT_BITS
+{
+ NTP_SYS_EVT_UNSPEC = 0, ///< unspecified NTP event
+ NTP_SYS_EVT_FREQ_NOT_SET, ///< frequency file not available
+ NTP_SYS_EVT_FREQ_SET, ///< frequency set from frequency file
+ NTP_SYS_EVT_SPIKE_DETECT, ///< spike detected
+ NTP_SYS_EVT_FREQ_MODE, ///< initial frequency training mode
+ NTP_SYS_EVT_CLOCK_SYNC, ///< clock synchronized
+ NTP_SYS_EVT_RESTART, ///< program restart
+ NTP_SYS_EVT_PANIC_STOP, ///< clock error more than 600 s
+ NTP_SYS_EVT_NO_SYSTEM_PEER, ///< no system peer
+ NTP_SYS_EVT_LEAP_ARMED, ///< leap second armed from file or autokey
+ NTP_SYS_EVT_LEAP_DISARMED, ///< leap second disarmed
+ NTP_SYS_EVT_LEAP_EVENT, ///< leap event
+ NTP_SYS_EVT_CLOCK_STEP, ///< clock stepped
+ NTP_SYS_EVT_KERNEL, ///< kernel information message
+ NTP_SYS_EVT_TAI, ///< leapsecond values update from file
+ NTP_SYS_EVT_STALE_LS_VALUES, ///< new NIST leapseconds file needed
+ N_NTP_SYS_EVT_BITS
+};
+
+/*
+ * Default initializers for English sync source string names. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+#define MBG_NTP_SYS_EVT_STR_ENG_CNT_LABEL "System Event Counter:"
+#define MBG_NTP_SYS_EVT_STR_ENG_MSG_LABEL "System Event Message:"
+#define MBG_NTP_SYS_EVT_STR_ENG_UNSPEC "Unspecified NTP event"
+#define MBG_NTP_SYS_EVT_STR_ENG_FREQ_NOT_SET "Frequency file not available"
+#define MBG_NTP_SYS_EVT_STR_ENG_FREQ_SET "Frequency set from frequency file"
+#define MBG_NTP_SYS_EVT_STR_ENG_SPIKE_DETECT "Spike detected"
+#define MBG_NTP_SYS_EVT_STR_ENG_FREQ_MODE "Initial frequency training mode"
+#define MBG_NTP_SYS_EVT_STR_ENG_CLOCK_SYNC "Clock synchronized"
+#define MBG_NTP_SYS_EVT_STR_ENG_RESTART "Program restart"
+#define MBG_NTP_SYS_EVT_STR_ENG_PANIC_STOP "Clock error more than 600 s"
+#define MBG_NTP_SYS_EVT_STR_ENG_NO_SYSTEM_PEER "No system peer"
+#define MBG_NTP_SYS_EVT_STR_ENG_LEAP_ARMED "Leap second armed from file or autokey"
+#define MBG_NTP_SYS_EVT_STR_ENG_LEAP_DISARMED "Leap second disarmed"
+#define MBG_NTP_SYS_EVT_STR_ENG_LEAP_EVENT "Leap event"
+#define MBG_NTP_SYS_EVT_STR_ENG_CLOCK_STEP "Clock stepped"
+#define MBG_NTP_SYS_EVT_STR_ENG_KERNEL "Kernel information message"
+#define MBG_NTP_SYS_EVT_STR_ENG_TAI "Leap second values update from file"
+#define MBG_NTP_SYS_EVT_STR_ENG_STALE_LS_VALUES "New NIST leapseconds file needed"
+
+
+#define MBG_NTP_SYS_EVT_NAMES_ENG \
+{ \
+ MBG_NTP_SYS_EVT_STR_ENG_UNSPEC, \
+ MBG_NTP_SYS_EVT_STR_ENG_FREQ_NOT_SET, \
+ MBG_NTP_SYS_EVT_STR_ENG_FREQ_SET, \
+ MBG_NTP_SYS_EVT_STR_ENG_SPIKE_DETECT, \
+ MBG_NTP_SYS_EVT_STR_ENG_FREQ_MODE, \
+ MBG_NTP_SYS_EVT_STR_ENG_CLOCK_SYNC, \
+ MBG_NTP_SYS_EVT_STR_ENG_RESTART, \
+ MBG_NTP_SYS_EVT_STR_ENG_PANIC_STOP, \
+ MBG_NTP_SYS_EVT_STR_ENG_NO_SYSTEM_PEER, \
+ MBG_NTP_SYS_EVT_STR_ENG_LEAP_ARMED, \
+ MBG_NTP_SYS_EVT_STR_ENG_LEAP_DISARMED, \
+ MBG_NTP_SYS_EVT_STR_ENG_LEAP_EVENT, \
+ MBG_NTP_SYS_EVT_STR_ENG_CLOCK_STEP, \
+ MBG_NTP_SYS_EVT_STR_ENG_KERNEL, \
+ MBG_NTP_SYS_EVT_STR_ENG_TAI, \
+ MBG_NTP_SYS_EVT_STR_ENG_STALE_LS_VALUES \
+}
+
+/**
+ * @brief Enumeration of supported NTP system state values
+ *
+ * @see ::NTP_SYS_STATE_SUPP_FLAG_MASKS
+ */
+enum NTP_SYS_STATE_SUPP_FLAGS
+{
+ NTP_SYS_STATE_SUPP_STD = 0, ///< supports standard values of ::NTP_SYS_STATE, all fields except below and reserved
+ NTP_SYS_STATE_SUPP_EVENTS, ///< supports sys state events (::NTP_SYS_STATE::sys_evt_cnt, ::NTP_SYS_STATE::sys_rec_evt)
+ NTP_SYS_STATE_SUPP_PRECISION, ///< supports precision indication, see ::NTP_SYS_STATE::precision
+ NTP_SYS_STATE_SUPP_ROOT_DELAY, ///< supports root delay to syspeer, see ::NTP_SYS_STATE::root_delay
+ NTP_SYS_STATE_SUPP_ROOT_DISP, ///< supports root dispersion, see ::NTP_SYS_STATE::root_disp
+ NTP_SYS_STATE_SUPP_FREQ, ///< supports frequency offset, see ::NTP_SYS_STATE::freq
+ NTP_SYS_STATE_SUPP_SYS_JITTER, ///< supports combined jitter, see ::NTP_SYS_STATE::sys_jitter
+ NTP_SYS_STATE_SUPP_CLK_JITTER, ///< supports clock jitter, see ::NTP_SYS_STATE::clk_jitter
+ NTP_SYS_STATE_SUPP_CLK_WANDER, ///< supports clock wander, see ::NTP_SYS_STATE::clk_wander
+ N_NTP_SYS_STATE_SUPP_FLAGS
+};
+
+
+/**
+ * @brief Flag masks for NTP_SYS_STATE_SUPP_FLAGS
+ *
+ * Used with ::NTP_SYS_STATE::supp_flags
+ *
+ * @see ::NTP_SYS_STATE_SUPP_FLAGS
+ */
+enum NTP_SYS_STATE_SUPP_FLAG_MASKS
+{
+ NTP_SYS_STATE_SUPP_STD_MSK = ( 1UL << NTP_SYS_STATE_SUPP_STD ), ///< see ::NTP_SYS_STATE_SUPP_STD
+ NTP_SYS_STATE_SUPP_EVENTS_MSK = ( 1UL << NTP_SYS_STATE_SUPP_EVENTS ), ///< see ::NTP_SYS_STATE_SUPP_EVENTS
+ NTP_SYS_STATE_SUPP_PRECISION_MSK = ( 1UL << NTP_SYS_STATE_SUPP_PRECISION ), ///< see ::NTP_SYS_STATE_SUPP_PRECISION
+ NTP_SYS_STATE_SUPP_ROOT_DELAY_MSK = ( 1UL << NTP_SYS_STATE_SUPP_ROOT_DELAY ), ///< see ::NTP_SYS_STATE_SUPP_ROOT_DELAY
+ NTP_SYS_STATE_SUPP_ROOT_DISP_MSK = ( 1UL << NTP_SYS_STATE_SUPP_ROOT_DISP ), ///< see ::NTP_SYS_STATE_SUPP_ROOT_DISP
+ NTP_SYS_STATE_SUPP_FREQ_MSK = ( 1UL << NTP_SYS_STATE_SUPP_FREQ ), ///< see ::NTP_SYS_STATE_SUPP_FREQ
+ NTP_SYS_STATE_SUPP_SYS_JITTER_MSK = ( 1UL << NTP_SYS_STATE_SUPP_SYS_JITTER ), ///< see ::NTP_SYS_STATE_SUPP_SYS_JITTER
+ NTP_SYS_STATE_SUPP_CLK_JITTER_MSK = ( 1UL << NTP_SYS_STATE_SUPP_CLK_JITTER ), ///< see ::NTP_SYS_STATE_SUPP_CLK_JITTER
+ NTP_SYS_STATE_SUPP_CLK_WANDER_MSK = ( 1UL << NTP_SYS_STATE_SUPP_CLK_WANDER ) ///< see ::NTP_SYS_STATE_SUPP_CLK_WANDER
+};
+
+
+/**
+ * @brief Structure that represents the current system status of an NTP device
+ *
+ * This structure can be requested from a monitoring program to determine the device system status
+ */
+typedef struct
+{
+ uint32_t supp_flags; ///< Supported NTP system state values, see ::NTP_SYS_STATE_SUPP_FLAG_MASKS
+
+ uint8_t leap_ind; ///< Leap indicator, see ::NTP_LI_BITS
+ uint8_t sys_sync_src; ///< Current synchronization source, see ::NTP_SYNC_SRC_BITS
+ uint8_t sys_evt_cnt; ///< Number of events, since the last time the event code changed
+ uint8_t sys_rec_evt; ///< Most recent event message, see ::NTP_SYS_EVT_BITS
+
+ uint8_t impl_type; ///< NTP implementation type, see ::NTP_IMPL
+ uint8_t major_version; ///< Major version number
+ uint8_t minor_version; ///< Minor version number
+ uint8_t micro_version; ///< Micro version number
+
+ uint16_t patch_lvl; ///< Patch level number
+ uint8_t cpu_type; ///< Processor type, see ::NTP_CPU_TYPES
+ uint8_t system; ///< Operating system, see ::NTP_SYSTEMS
+
+ uint8_t stratum; ///< Current stratum level of the system
+ int8_t precision; ///< Precision of the system clock (2^precision)
+ uint16_t reserved_1; ///< Reserved, currently always 0
+
+ int32_t root_delay; ///< [us] Total roundtrip delay to the system peer
+ int32_t root_disp; ///< [us] Total dispersion to the system peer
+
+ MBG_IP_ADDR ref_id; ///< Reference ID of the current system peer, see ::MBG_IP_ADDR
+
+ NTP_TSTAMP ref_time; ///< Last time the system time has been adjusted, see ::NTP_TSTAMP
+ NTP_TSTAMP sys_time; ///< Current system time, see ::NTP_TSTAMP
+
+ uint16_t sys_peer; ///< Assocation ID of the current system peer
+ uint8_t poll; ///< Current polling interval for the system peer (tc)
+ uint8_t minpoll; ///< Minimal polling interval for the system peer (mintc)
+
+ int64_t offset; ///< [ns] Combined offset to the system peer
+
+ int32_t freq; ///< [ppb] Frequency offset relative to hardware clock
+ int32_t sys_jitter; ///< [us] Combined jitter of the system
+ int32_t clk_jitter; ///< [us] Jitter of the clock
+ int32_t clk_wander; ///< [ppb] Frequency wander of the clock
+
+ uint32_t reserved_2; ///< Reserved, currently always 0
+ uint32_t reserved_3; ///< Reserved, currently always 0
+
+} NTP_SYS_STATE;
+
+
+/**
+ * @brief Enumeration of NTP mode bits
+ *
+ * Used with ::NTP_PEER_STATE::host_mode and ::NTP_PEER_STATE::peer_mode
+ *
+ */
+enum NTP_MODE_BITS
+{
+ NTP_MODE_RESERVED = 0,
+ NTP_MODE_SYMM_ACT,
+ NTP_MODE_SYMM_PASS,
+ NTP_MODE_CLIENT,
+ NTP_MODE_SERVER,
+ NTP_MODE_BROADCAST,
+ NTP_MODE_CONTROL,
+ NTP_MODE_PRIVATE,
+ N_NTP_MODE_BITS
+};
+
+/*
+ * Default initializers for English NTP peer mode string names. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+#define MBG_NTP_MODE_STR_ENG_HOST_LABEL "Host Mode:"
+#define MBG_NTP_MODE_STR_ENG_PEER_LABEL "Peer Mode:"
+
+#define MBG_NTP_PEER_MODE_STR_ENG_RESERVED "Reserved"
+#define MBG_NTP_PEER_MODE_STR_ENG_SYMM_ACT "Symm Act"
+#define MBG_NTP_PEER_MODE_STR_ENG_SYMM_PASS "Symm Pass"
+#define MBG_NTP_PEER_MODE_STR_ENG_CLIENT "Client"
+#define MBG_NTP_PEER_MODE_STR_ENG_SERVER "Server"
+#define MBG_NTP_PEER_MODE_STR_ENG_BROADCAST "Broadcast"
+#define MBG_NTP_PEER_MODE_STR_ENG_CONTROL "Control"
+#define MBG_NTP_PEER_MODE_STR_ENG_PRIVATE "Private"
+
+#define MBG_NTP_MODE_STAT_NAMES_ENG \
+{ \
+ MBG_NTP_PEER_MODE_STR_ENG_RESERVED, \
+ MBG_NTP_PEER_MODE_STR_ENG_SYMM_ACT, \
+ MBG_NTP_PEER_MODE_STR_ENG_SYMM_PASS, \
+ MBG_NTP_PEER_MODE_STR_ENG_CLIENT, \
+ MBG_NTP_PEER_MODE_STR_ENG_SERVER, \
+ MBG_NTP_PEER_MODE_STR_ENG_BROADCAST, \
+ MBG_NTP_PEER_MODE_STR_ENG_CONTROL, \
+ MBG_NTP_PEER_MODE_STR_ENG_PRIVATE \
+}
+
+
+/**
+ * @brief Enumeration of NTP peer reach status
+ *
+ * Used with ::NTP_PEER_STATE::peer_reach_stat
+ */
+enum NTP_REACH_STAT_BITS
+{
+ NTP_REACH_STAT_UNKNOWN = 0, ///< unknown reach status
+ NTP_REACH_STAT_NO_LINK, ///< no network connection
+ NTP_REACH_STAT_DNS_UNREACH, ///< DNS server could not be reached
+ NTP_REACH_STAT_DNS_UNRESOLVED, ///< DNS name could not be resolved
+ NTP_REACH_STAT_PEER_UNREACH, ///< peer could not be reached
+ NTP_REACH_STAT_PEER_NOT_SYNC, ///< peer is not sync (leap alarm, stratum 16)
+ NTP_REACH_STAT_PEER_BAD_QUALITY, ///< peer has bad quality (dispersion, ...)
+ NTP_REACH_STAT_OK, ///< reach status is fine
+ N_NTP_REACH_STAT_BITS
+};
+
+/*
+ * Default initializers for English reach status string names. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+#define MBG_NTP_PEER_REACH_STAT_STR_ENG_LABEL "Reach State:"
+
+#define MBG_NTP_PEER_REACH_STAT_STR_ENG_UNKNOWN "Unknown"
+#define MBG_NTP_PEER_REACH_STAT_STR_ENG_NO_LINK "No link"
+#define MBG_NTP_PEER_REACH_STAT_STR_ENG_DNS_UNREACH "DNS Server unreached"
+#define MBG_NTP_PEER_REACH_STAT_STR_ENG_DNS_UNRESOLVED "DNS name not resolved"
+#define MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_UNREACH "Peer not reached"
+#define MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_NOT_SYNC "Peer not sync"
+#define MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_BAD_QUALITY "Peer has bad quality"
+#define MBG_NTP_PEER_REACH_STAT_STR_ENG_OK "Good"
+
+#define MBG_NTP_PEER_REACH_STAT_NAMES_ENG \
+{ \
+ MBG_NTP_PEER_REACH_STAT_STR_ENG_UNKNOWN, \
+ MBG_NTP_PEER_REACH_STAT_STR_ENG_NO_LINK, \
+ MBG_NTP_PEER_REACH_STAT_STR_ENG_DNS_UNREACH, \
+ MBG_NTP_PEER_REACH_STAT_STR_ENG_DNS_UNRESOLVED, \
+ MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_UNREACH, \
+ MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_NOT_SYNC, \
+ MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_BAD_QUALITY, \
+ MBG_NTP_PEER_REACH_STAT_STR_ENG_OK \
+}
+
+
+/**
+ * @brief Enumeration of NTP peer selection status
+ *
+ * Used with ::NTP_PEER_STATE::peer_sel_stat
+ *
+ */
+enum NTP_PEER_SEL_STATUS_BITS
+{
+ NTP_PEER_SEL_REJECT = 0, ///< discarded as not valid (TEST10-TEST13)
+ NTP_PEER_SEL_FALSETICK, ///< discarded by intersection algorithm
+ NTP_PEER_SEL_EXCESS, ///< discarded by table overflow (not used)
+ NTP_PEER_SEL_OUTLYER, ///< discarded by the cluster algorithm
+ NTP_PEER_SEL_CANDIDATE, ///< included by the combine algorithm
+ NTP_PEER_SEL_BACKUP, ///< backup (more than tos maxclock sources)
+ NTP_PEER_SEL_SYS_PEER, ///< system peer
+ NTP_PEER_SEL_PPS_PEER, ///< PPS peer (when the prefer peer is valid)
+ N_NTP_PEER_SEL_STATUS_BITS
+};
+
+/*
+ * Default initializers for English peer select status string names. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_LABEL "Selected Status:"
+
+#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_REJECT "Not valid"
+#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_FALSETICK "Falsetick"
+#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_EXCESS "Excess"
+#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_OUTLYER "Outlyer"
+#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_CANDIDATE "Candidate"
+#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_BACKUP "Backup"
+#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_SYS_PEER "System Peer"
+#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_PPS_PEER "PPS Peer"
+
+#define MBG_NTP_PEER_SEL_STATUS_NAMES_ENG \
+{ \
+ MBG_NTP_PEER_SEL_STATUS_STR_ENG_REJECT, \
+ MBG_NTP_PEER_SEL_STATUS_STR_ENG_FALSETICK, \
+ MBG_NTP_PEER_SEL_STATUS_STR_ENG_EXCESS, \
+ MBG_NTP_PEER_SEL_STATUS_STR_ENG_OUTLYER, \
+ MBG_NTP_PEER_SEL_STATUS_STR_ENG_CANDIDATE, \
+ MBG_NTP_PEER_SEL_STATUS_STR_ENG_BACKUP, \
+ MBG_NTP_PEER_SEL_STATUS_STR_ENG_SYS_PEER, \
+ MBG_NTP_PEER_SEL_STATUS_STR_ENG_PPS_PEER \
+}
+
+
+/**
+ * @brief Enumeration of NTP peer status codes
+ *
+ * @see ::NTP_PEER_STATUS_FLAG_MASKS
+ *
+ */
+enum NTP_PEER_STATUS_FLAGS
+{
+ NTP_PEER_STATUS_BCST = 0, ///< broadcast association
+ NTP_PEER_STATUS_REACH, ///< host reachable
+ NTP_PEER_STATUS_AUTHENB, ///< authentication enabled
+ NTP_PEER_STATUS_AUTH, ///< authentication ok
+ NTP_PEER_STATUS_CONFIG, ///< persistent association
+ N_NTP_PEER_STATUS_FLAGS
+};
+
+
+/**
+ * @brief Flag masks for NTP_PEER_STATUS_FLAGS
+ *
+ * Used with ::NTP_PEER_STATE::peer_status_flags
+ *
+ * @see ::NTP_PEER_STATUS_FLAGS
+ */
+enum NTP_PEER_STATUS_FLAG_MASKS
+{
+ NTP_PEER_STATUS_BCST_MSK = ( 1UL << NTP_PEER_STATUS_BCST ), ///< see ::NTP_PEER_STATUS_BCST
+ NTP_PEER_STATUS_REACH_MSK = ( 1UL << NTP_PEER_STATUS_REACH ), ///< see ::NTP_PEER_STATUS_REACH
+ NTP_PEER_STATUS_AUTHENB_MSK = ( 1UL << NTP_PEER_STATUS_AUTHENB ), ///< see ::NTP_PEER_STATUS_AUTHENB
+ NTP_PEER_STATUS_AUTH_MSK = ( 1UL << NTP_PEER_STATUS_AUTH ), ///< see ::NTP_PEER_STATUS_AUTH
+ NTP_PEER_STATUS_CONFIG_MSK = ( 1UL << NTP_PEER_STATUS_CONFIG ), ///< see ::NTP_PEER_STATUS_CONFIG
+};
+
+
+/*
+ * Default initializers for English peer status string names. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+#define MBG_NTP_PEER_STATUS_STR_ENG_LABEL "Peer Status:"
+#define MBG_NTP_PEER_STATUS_STR_ENG_BCST "Broadcast association"
+#define MBG_NTP_PEER_STATUS_STR_ENG_REACH "Host reachable"
+#define MBG_NTP_PEER_STATUS_STR_ENG_AUTHENB "Authentication enabled"
+#define MBG_NTP_PEER_STATUS_STR_ENG_CONFIG "Persistant assosiation"
+
+#define MBG_NTP_PEER_STATUS_NAMES_ENG \
+{ \
+ MBG_NTP_PEER_STATUS_STR_ENG_BCST, \
+ MBG_NTP_PEER_STATUS_STR_ENG_REACH, \
+ MBG_NTP_PEER_STATUS_STR_ENG_REACH, \
+ MBG_NTP_PEER_STATUS_STR_ENG_AUTHENB, \
+ MBG_NTP_PEER_STATUS_STR_ENG_CONFIG \
+}
+
+
+/**
+ * @brief Enumeration of NTP peer event message codes
+ *
+ * Used with ::NTP_PEER_STATE::peer_rec_evt
+ *
+ */
+enum NTP_PEER_EVT_BITS
+{
+ NTP_PEER_EVT_UNSPEC = 0, ///< unspecified NTP event
+ NTP_PEER_EVT_MOBILIZE, ///< association mobilized
+ NTP_PEER_EVT_DEMOBILIZE, ///< association demobilized
+ NTP_PEER_EVT_UNREACHABLE, ///< server unreachable
+ NTP_PEER_EVT_REACHABLE, ///< server reachable
+ NTP_PEER_EVT_RESTART, ///< association restart
+ NTP_PEER_EVT_NO_REPLY, ///< no server found (ntpdate mode)
+ NTP_PEER_EVT_RATE_EXCEEDED, ///< rate exceeded (kiss code RATE)
+ NTP_PEER_EVT_ACCESS_DENIED, ///< access denied (kiss code DENY)
+ NTP_PEER_EVT_LEAP_ARMED, ///< leap armed from server LI code
+ NTP_PEER_EVT_SYS_PEER, ///< become system peer
+ NTP_PEER_EVT_CLOCK_EVENT, ///< see clock status word
+ NTP_PEER_EVT_BAD_AUTH, ///< authentication failure
+ NTP_PEER_EVT_POPCORN, ///< popcorn spike suppressor
+ NTP_PEER_EVT_INTERLEAVE_MODE, ///< entering interleave mode
+ NTP_PEER_EVT_INTERLEAVE_ERROR, ///< interleave error (recovered)
+ N_NTP_PEER_EVT_BITS
+};
+
+/*
+ * Default initializers for English event message codes. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+#define MBG_NTP_PEER_EVT_STR_ENG_CNT_LABEL "Peer Event Counter:"
+#define MBG_NTP_PEER_EVT_STR_ENG_MSG_LABEL "Peer Event Message:"
+#define MBG_NTP_PEER_EVT_STR_ENG_UNSPEC "Unspecified NTP event"
+#define MBG_NTP_PEER_EVT_STR_ENG_MOBILIZE "Association mobilized"
+#define MBG_NTP_PEER_EVT_STR_ENG_DEMOBILIZE "Association demobilized"
+#define MBG_NTP_PEER_EVT_STR_ENG_UNREACHABLE "Server unreachable"
+#define MBG_NTP_PEER_EVT_STR_ENG_REACHABLE "Server reachable"
+#define MBG_NTP_PEER_EVT_STR_ENG_RESTART "Association restart"
+#define MBG_NTP_PEER_EVT_STR_ENG_NO_REPLY "No server found"
+#define MBG_NTP_PEER_EVT_STR_ENG_RATE_EXCEEDED "Rate exceeded"
+#define MBG_NTP_PEER_EVT_STR_ENG_ACCESS_DENIED "Access denied"
+#define MBG_NTP_PEER_EVT_STR_ENG_LEAP_ARMED "Leap second armed from LI code"
+#define MBG_NTP_PEER_EVT_STR_ENG_SYS_PEER "Become system Peer"
+#define MBG_NTP_PEER_EVT_STR_ENG_CLOCK_EVENT "Clock event"
+#define MBG_NTP_PEER_EVT_STR_ENG_BAD_AUTH "Authentication failure"
+#define MBG_NTP_PEER_EVT_STR_ENG_POPCORN "Popcorn Spike suspressor"
+#define MBG_NTP_PEER_EVT_STR_ENG_INTERLEAVE_MODE "Entering Interleave mode"
+#define MBG_NTP_PEER_EVT_STR_ENG_INTERLEAVE_ERROR "Interleave error"
+
+
+#define MBG_NTP_PEER_EVT_NAMES_ENG \
+{ \
+ MBG_NTP_PEER_EVT_STR_ENG_UNSPEC, \
+ MBG_NTP_PEER_EVT_STR_ENG_MOBILIZE, \
+ MBG_NTP_PEER_EVT_STR_ENG_DEMOBILIZE, \
+ MBG_NTP_PEER_EVT_STR_ENG_UNREACHABLE, \
+ MBG_NTP_PEER_EVT_STR_ENG_REACHABLE, \
+ MBG_NTP_PEER_EVT_STR_ENG_RESTART, \
+ MBG_NTP_PEER_EVT_STR_ENG_NO_REPLY, \
+ MBG_NTP_PEER_EVT_STR_ENG_RATE_EXCEEDED, \
+ MBG_NTP_PEER_EVT_STR_ENG_ACCESS_DENIED, \
+ MBG_NTP_PEER_EVT_STR_ENG_LEAP_ARMED, \
+ MBG_NTP_PEER_EVT_STR_ENG_SYS_PEER, \
+ MBG_NTP_PEER_EVT_STR_ENG_CLOCK_EVENT, \
+ MBG_NTP_PEER_EVT_STR_ENG_BAD_AUTH, \
+ MBG_NTP_PEER_EVT_STR_ENG_POPCORN, \
+ MBG_NTP_PEER_EVT_STR_ENG_INTERLEAVE_MODE, \
+ MBG_NTP_PEER_EVT_STR_ENG_INTERLEAVE_ERROR \
+}
+
+
+/**
+ * @brief Enumeration of NTP flash status bit codes
+ *
+ * @see ::NTP_FLASH_STAT_FLAG_MASKS
+ *
+ */
+enum NTP_FLASH_STAT_FLAGS
+{
+ NTP_FLASH_STAT_PKT_DUP = 0, ///< duplicate packet
+ NTP_FLASH_STAT_PKT_BOGUS, ///< bogus packet
+ NTP_FLASH_STAT_PKT_UNSYNC, ///< server not synchronized
+ NTP_FLASH_STAT_PKT_DENIED, ///< access denied
+ NTP_FLASH_STAT_PKT_AUTH, ///< authentication failure
+ NTP_FLASH_STAT_PKT_STRATUM, ///< invalid leap or stratum
+ NTP_FLASH_STAT_PKT_HEADER, ///< header distance exceeded
+ NTP_FLASH_STAT_PKT_AUTOKEY, ///< Autokey sequence error
+ NTP_FLASH_STAT_PKT_CRYPTO, ///< Autokey protocol error
+ NTP_FLASH_STAT_PEER_STRATUM, ///< invalid header or stratum
+ NTP_FLASH_STAT_PEER_DIST, ///< distance threshold exceeded
+ NTP_FLASH_STAT_PEER_LOOP, ///< synchronization loop
+ NTP_FLASH_STAT_PEER_UNREACH, ///< unreachable or nonselect
+ N_NTP_FLASH_STAT_FLAGS
+};
+
+
+/**
+ * @brief Flag masks for ::NTP_FLASH_STAT_FLAGS
+ *
+ * Used with ::NTP_PEER_STATE::flash_stat_flags
+ *
+ * @see ::NTP_FLASH_STAT_FLAGS
+ */
+enum NTP_FLASH_STAT_FLAG_MASKS
+{
+ NTP_FLASH_STAT_PKT_DUP_MSK = ( 1UL << NTP_FLASH_STAT_PKT_DUP ), ///< see ::NTP_FLASH_STAT_PKT_DUP
+ NTP_FLASH_STAT_PKT_BOGUS_MSK = ( 1UL << NTP_FLASH_STAT_PKT_BOGUS ), ///< see ::NTP_FLASH_STAT_PKT_BOGUS
+ NTP_FLASH_STAT_PKT_UNSYNC_MSK = ( 1UL << NTP_FLASH_STAT_PKT_UNSYNC ), ///< see ::NTP_FLASH_STAT_PKT_UNSYNC
+ NTP_FLASH_STAT_PKT_DENIED_MSK = ( 1UL << NTP_FLASH_STAT_PKT_DENIED ), ///< see ::NTP_FLASH_STAT_PKT_DENIED
+ NTP_FLASH_STAT_PKT_AUTH_MSK = ( 1UL << NTP_FLASH_STAT_PKT_AUTH ), ///< see ::NTP_FLASH_STAT_PKT_AUTH
+ NTP_FLASH_STAT_PKT_STRATUM_MSK = ( 1UL << NTP_FLASH_STAT_PKT_STRATUM ), ///< see ::NTP_FLASH_STAT_PKT_STRATUM
+ NTP_FLASH_STAT_PKT_HEADER_MSK = ( 1UL << NTP_FLASH_STAT_PKT_HEADER ), ///< see ::NTP_FLASH_STAT_PKT_HEADER
+ NTP_FLASH_STAT_PKT_AUTOKEY_MSK = ( 1UL << NTP_FLASH_STAT_PKT_AUTOKEY ), ///< see ::NTP_FLASH_STAT_PKT_AUTOKEY
+ NTP_FLASH_STAT_PKT_CRYPTO_MSK = ( 1UL << NTP_FLASH_STAT_PKT_CRYPTO ), ///< see ::NTP_FLASH_STAT_PKT_CRYPTO
+ NTP_FLASH_STAT_PEER_STRATUM_MSK = ( 1UL << NTP_FLASH_STAT_PEER_STRATUM ), ///< see ::NTP_FLASH_STAT_PEER_STRATUM
+ NTP_FLASH_STAT_PEER_DIST_MSK = ( 1UL << NTP_FLASH_STAT_PEER_DIST ), ///< see ::NTP_FLASH_STAT_PEER_DIST
+ NTP_FLASH_STAT_PEER_LOOP_MSK = ( 1UL << NTP_FLASH_STAT_PEER_LOOP ), ///< see ::NTP_FLASH_STAT_PEER_LOOP
+ NTP_FLASH_STAT_PEER_UNREACH_MSK = ( 1UL << NTP_FLASH_STAT_PEER_UNREACH ), ///< see ::NTP_FLASH_STAT_PEER_UNREACH
+};
+
+/*
+ * Default initializers for English ntp flash state mask. Initializers
+ * for multi-language strings can be found in tmonlstr.h.
+ */
+
+#define MBG_NTP_FLASH_STR_ENG_LABEL "Flash Status:"
+#define MBG_NTP_FLASH_STR_ENG_PKT_DUP "Duplicate packet"
+#define MBG_NTP_FLASH_STR_ENG_PKT_BOGUS "Bogus packet"
+#define MBG_NTP_FLASH_STR_ENG_PKT_UNSYNC "Server not synchronized"
+#define MBG_NTP_FLASH_STR_ENG_PKT_DENIED "Access denied"
+#define MBG_NTP_FLASH_STR_ENG_PKT_AUTH "Authentication failure"
+#define MBG_NTP_FLASH_STR_ENG_PKT_STRATUM "Invalid leap or stratum"
+#define MBG_NTP_FLASH_STR_ENG_PKT_HEADER "Header distance exceeded"
+#define MBG_NTP_FLASH_STR_ENG_PKT_AUTOKEY "Autokey sequence error"
+#define MBG_NTP_FLASH_STR_ENG_PKT_CRYPTO "Autokey protocol error"
+#define MBG_NTP_FLASH_STR_ENG_PEER_STRATUM "Invalid header or stratum"
+#define MBG_NTP_FLASH_STR_ENG_PEER_DIST "Distance threshold exceeded"
+#define MBG_NTP_FLASH_STR_ENG_PEER_LOOP "Synchronization loop"
+#define MBG_NTP_FLASH_STR_ENG_PEER_UNREACH "Unreachable or nonselect"
+
+
+#define MBG_NTP_FLASH_NAMES_ENG \
+{ \
+ MBG_NTP_FLASH_STR_ENG_PKT_DUP, \
+ MBG_NTP_FLASH_STR_ENG_PKT_BOGUS, \
+ MBG_NTP_FLASH_STR_ENG_PKT_UNSYNC, \
+ MBG_NTP_FLASH_STR_ENG_PKT_DENIED, \
+ MBG_NTP_FLASH_STR_ENG_PKT_AUTH, \
+ MBG_NTP_FLASH_STR_ENG_PKT_STRATUM, \
+ MBG_NTP_FLASH_STR_ENG_PKT_HEADER, \
+ MBG_NTP_FLASH_STR_ENG_PKT_AUTOKEY, \
+ MBG_NTP_FLASH_STR_ENG_PKT_CRYPTO, \
+ MBG_NTP_FLASH_STR_ENG_PEER_STRATUM, \
+ MBG_NTP_FLASH_STR_ENG_PEER_DIST, \
+ MBG_NTP_FLASH_STR_ENG_PEER_LOOP, \
+ MBG_NTP_FLASH_STR_ENG_PEER_UNREACH \
+}
+
+
+/**
+ * @brief Enumeration of supported NTP peer state values
+ *
+ * @see ::NTP_PEER_STATE_SUPP_FLAG_MASKS
+ */
+enum NTP_PEER_STATE_SUPP_FLAGS
+{
+ NTP_PEER_STATE_SUPP_STD = 0, ///< supports standard values of ::NTP_PEER_STATE, all fields except below and reserved
+ NTP_PEER_STATE_SUPP_ASS_ID, ///< supports association ID, see ::NTP_PEER_STATE::ass_id
+ NTP_PEER_STATE_SUPP_EVENTS, ///< supports peer state events (NTP_PEER_STATE::peer_evt_cnt, NTP_PEER_STATE::peer_rec_evt)
+ NTP_PEER_STATE_SUPP_REACH_STAT, ///< supports peer reach status, see ::NTP_PEER_STATE::peer_reach_stat
+ NTP_PEER_STATE_SUPP_PRECISION, ///< supports precision indication, see ::NTP_PEER_STATE::precision
+ NTP_PEER_STATE_SUPP_ROOT_DELAY, ///< supports root delay to syspeer, see ::NTP_PEER_STATE::root_delay
+ NTP_PEER_STATE_SUPP_ROOT_DISP, ///< supports root dispersion, see ::NTP_PEER_STATE::root_disp
+ NTP_PEER_STATE_SUPP_HEADWAY, ///< supports headway, see ::NTP_PEER_STATE::headway
+ NTP_PEER_STATE_SUPP_FLASH_STAT, ///< supports flash status word, see ::NTP_PEER_STATE::flash_stat_flags
+ NTP_PEER_STATE_SUPP_KEY_ID, ///< supports symmetric key id, see ::NTP_PEER_STATE::key_id
+ NTP_PEER_STATE_SUPP_DISP, ///< supports filter dispersion, see ::NTP_PEER_STATE::disp
+ NTP_PEER_STATE_SUPP_JITTER, ///< supports filter jitter, see ::NTP_PEER_STATE::jitter
+ NTP_PEER_STATE_SUPP_XLEAVE, ///< supports interleave delay, see ::NTP_PEER_STATE::xleave
+ N_NTP_PEER_STATE_SUPP_FLAGS
+};
+
+
+/**
+ * @brief Flag masks for NTP_PEER_STATE_SUPP_FLAGS
+ *
+ * Used with ::NTP_PEER_STATE::supp_flags
+ *
+ * @see ::NTP_PEER_STATE_SUPP_FLAGS
+ */
+enum NTP_PEER_STATE_SUPP_FLAG_MASKS
+{
+ NTP_PEER_STATE_SUPP_STD_MSK = ( 1UL << NTP_PEER_STATE_SUPP_STD ), ///< see ::NTP_PEER_STATE_SUPP_STD
+ NTP_PEER_STATE_SUPP_ASS_ID_MSK = ( 1UL << NTP_PEER_STATE_SUPP_ASS_ID ), ///< see ::NTP_PEER_STATE_SUPP_ASS_ID
+ NTP_PEER_STATE_SUPP_EVENTS_MSK = ( 1UL << NTP_PEER_STATE_SUPP_EVENTS ), ///< see ::NTP_PEER_STATE_SUPP_EVENTS
+ NTP_PEER_STATE_SUPP_REACH_STAT_MSK = ( 1UL << NTP_PEER_STATE_SUPP_REACH_STAT ), ///< see ::NTP_PEER_STATE_SUPP_REACH_STAT
+ NTP_PEER_STATE_SUPP_PRECISION_MSK = ( 1UL << NTP_PEER_STATE_SUPP_PRECISION ), ///< see ::NTP_PEER_STATE_SUPP_PRECISION
+ NTP_PEER_STATE_SUPP_ROOT_DELAY_MSK = ( 1UL << NTP_PEER_STATE_SUPP_ROOT_DELAY ), ///< see ::NTP_PEER_STATE_SUPP_ROOT_DELAY
+ NTP_PEER_STATE_SUPP_ROOT_DISP_MSK = ( 1UL << NTP_PEER_STATE_SUPP_ROOT_DISP ), ///< see ::NTP_PEER_STATE_SUPP_ROOT_DISP
+ NTP_PEER_STATE_SUPP_HEADWAY_MSK = ( 1UL << NTP_PEER_STATE_SUPP_HEADWAY ), ///< see ::NTP_PEER_STATE_SUPP_HEADWAY
+ NTP_PEER_STATE_SUPP_FLASH_STAT_MSK = ( 1UL << NTP_PEER_STATE_SUPP_FLASH_STAT ), ///< see ::NTP_PEER_STATE_SUPP_FLASH_STAT
+ NTP_PEER_STATE_SUPP_KEY_ID_MSK = ( 1UL << NTP_PEER_STATE_SUPP_KEY_ID ), ///< see ::NTP_PEER_STATE_SUPP_KEY_ID
+ NTP_PEER_STATE_SUPP_DISP_MSK = ( 1UL << NTP_PEER_STATE_SUPP_DISP ), ///< see ::NTP_PEER_STATE_SUPP_DISP
+ NTP_PEER_STATE_SUPP_JITTER_MSK = ( 1UL << NTP_PEER_STATE_SUPP_JITTER ), ///< see ::NTP_PEER_STATE_SUPP_JITTER
+ NTP_PEER_STATE_SUPP_XLEAVE_MSK = ( 1UL << NTP_PEER_STATE_SUPP_XLEAVE ), ///< see ::NTP_PEER_STATE_SUPP_XLEAVE
+};
+
+
+/**
+ * @brief Structure that represents the status of an NTP peer
+ *
+ * This structure should be requested via ::NTP_PEER_STATE_IDX
+ *
+ * @see ::NTP_PEER_STATE_IDX
+ */
+typedef struct
+{
+ uint32_t supp_flags; ///< Supported NTP peer state values, see ::NTP_PEER_STATE_SUPP_FLAG_MASKS
+
+ uint16_t ass_id; ///< Association ID of the peer
+ uint16_t peer_status_flags; ///< Peer status flags, see ::NTP_PEER_STATUS_FLAG_MASKS
+
+ uint8_t leap_ind; ///< Leap indicator, see ::NTP_LI_BITS
+ uint8_t peer_sel_stat; ///< Current selection status of the peer, see ::NTP_PEER_SEL_STATUS_BITS
+ uint8_t peer_evt_cnt; ///< Number of events, since the last time the event code changed
+ uint8_t peer_rec_evt; ///< Most recent event message, see ::NTP_PEER_EVT_BITS
+
+ uint8_t peer_reach_stat; ///< Current reach status of the peer, see ::NTP_REACH_STAT_BITS
+ uint8_t reserved_1; ///< Reserved, currently always 0
+ uint16_t reserved_2; ///< Reserved, currently always 0
+
+ MBG_IP_ADDR_PORT src_addr; ///< Source address of the NTP peer, see ::MBG_IP_ADDR_PORT
+ MBG_IP_ADDR_PORT dst_addr; ///< Destination address of the NTP peer, see ::MBG_IP_ADDR_PORT
+
+ uint8_t stratum; ///< Current stratum level of the NTP peer
+ int8_t precision; ///< Precision of the peer clock (2^precision)
+ uint16_t reserved_3; ///< Reserved, currently always 0
+
+ int32_t root_delay; ///< [us] Total roundtrip delay to the system peer of the NTP peer
+ int32_t root_disp; ///< [us] Total dispersion to the system peer of the NTP peer
+
+ MBG_IP_ADDR ref_id; ///< Reference ID of the NTP peer, see ::MBG_IP_ADDR
+
+ NTP_TSTAMP ref_time; ///< Last time the NTP peers time has been adjusted, see ::NTP_TSTAMP
+ NTP_TSTAMP rec_time; ///< Current system time of the NTP peer, see ::NTP_TSTAMP
+
+ uint8_t reach; ///< Shift register for the last 8 polling intervals
+ uint8_t reserved_4; ///< Reserved, currently always 0
+ uint16_t unreach; ///< Counter for the number of unsuccessful polling intervals
+
+ uint8_t host_mode; ///< NTP mode of the requesting host, see ::NTP_MODE_BITS
+ uint8_t peer_mode; ///< NTP mode of the peer, see ::NTP_MODE_BITS
+ uint8_t host_poll; ///< Host NTP polling interval
+ uint8_t peer_poll; ///< Peer NTP polling interval
+
+ uint8_t headway; ///< Indicator for the KoD packet, TODO: further investigation
+ uint8_t reserved_5; ///< Reserved, currently always 0
+ uint16_t flash_stat_flags; ///< Flash status flags, see ::NTP_FLASH_STAT_FLAG_MASKS
+
+ uint16_t key_id; ///< ID of symmetric authentication key
+ uint16_t reserved_6; ///< Reserved, currently always 0
+
+ int64_t offset; ///< [ns] filter offset to this NTP peer
+ int64_t delay; ///< [ns] filter delay to this NTP peer
+
+ int32_t disp; ///< [us] filter dispersion of the NTP peer
+ int32_t jitter; ///< [us] filter jitter of the NTP peer
+
+ uint32_t xleave; ///< [ns] interleave delay of the NTP peer
+
+ uint8_t n_filter_values; ///< Number of filter values available, currently always 0
+ uint8_t reserved_7; ///< Reserved, currently always 0
+ uint16_t reserved_8; ///< Reserved, currently always 0
+
+ uint32_t reserved_9; ///< Reserved, currently always 0
+
+} NTP_PEER_STATE;
+
+
+/**
+ * @brief Structure that contains an index value and the NTP peer state
+ *
+ * This structure can be requested by a monitoring program to observe the status of configured NTP peers
+ *
+ * @see ::NTP_PEER_STATE
+ */
+typedef struct
+{
+ uint32_t idx; ///< The index of the observed NTP peer
+ NTP_PEER_STATE peer_state; ///< Peer state, see ::NTP_PEER_STATE
+
+} NTP_PEER_STATE_IDX;
+
+/** @} defgroup group_ntp */
+
+
+
+/**
+ * @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 )
+
+/** @} defgroup group_lno */
+
+
+
+/**
+ * @defgroup group_vst Definitions used with Versatile Storage
+ *
+ * Versatile storage is used to store binary data on a device where the storage
+ * device must not necessarily know about the data structure. It just stores
+ * a piece of data, and retrieves it on demand.
+ *
+ * The structures and associated API calls are only supported if the
+ * ::GPS_HAS_VST bit is set in ::RECEIVER_INFO::features.
+ *
+ * @{ */
+
+/**
+ * @brief Known common VST data types
+ */
+enum VST_DATA_TYPES
+{
+ VST_DATA_TYPE_MAC_ADDR, //##++++++++++++ This is just an example. More to be added.
+ N_VST_DATA_TYPES
+};
+
+
+/**
+ * @brief
+ */
+typedef struct
+{
+ uint16_t data_type; ///< data type identifier, see ::VST_DATA_TYPES for common types
+ uint16_t idx; ///< Index for several sets of the same type
+ uint16_t data_len; ///< length of the data set appended to the header
+ uint16_t reserved; ///< reserved, currently always 0
+
+} VST_HEADER;
+
+#define _mbg_swab_vst_header( _p ) \
+{ \
+ _mbg_swab16( &(_p)->data_type ); \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab16( &(_p)->data_len ); \
+ _mbg_swab16( &(_p)->reserved ); \
+}
+
+/** @} defgroup group_vst */
+
+
+
+/**
+ * @defgroup group_shs Definitions used with SHS devices
+ *
+ * An SHS (Secure Hybrid System) device compares the times from 2 sources
+ * and eventually sets an alarm (warning and/or error) flag if the difference
+ * between the 2 time sources exceeds a configurable limit.
+ *
+ * These structures and associated definitions are used to query the SHS
+ * capabilities, configure the SHS device according to its capabilities,
+ * and query the SHS status.
+ *
+ * The structures and associated API calls are only supported if the
+ * ::GPS_HAS_SHS bit is set in ::RECEIVER_INFO::features.
+ *
+ * The ::SHS_INFO structure can be read to retrieve the capabilities and
+ * current settings of the device. The ::SHS_SETTINGS structure can then
+ * be set up according to the capabilities, and be written back to configure
+ * the device.
+ *
+ * If ::SHS_SETTINGS::err_limit and/or ::SHS_SETTINGS::warn_limit are
+ * not 0 then the SHS device checks if the time difference between the
+ * 2 clocks exceeds these limits and sets ::SHS_STATUS::shs_state
+ * as appropriate.
+ *
+ * If indicated by ::SHS_INFO::supp_flags the SHS device can also take
+ * certain actions if the time difference exceeds the error limit.
+ * If this happens then the same flags are set in ::SHS_STATUS::flags
+ * to indicate the action has been taken.
+ *
+ * @{ */
+
+/**
+ * @brief Current configuration of an SHS controller
+ *
+ * @see ::SHS_INFO
+ * @see ::SHS_STATUS
+ */
+typedef struct
+{
+ NANO_TIME err_limit; ///< time difference limit above which an error is indicated
+ NANO_TIME warn_limit; ///< time difference limit above which a warning is indicated
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t flags; ///< see ::SHS_FLAG_MASKS
+
+} SHS_SETTINGS;
+
+#define _mbg_swab_shs_settings( _p ) \
+{ \
+ _mbg_swab_nano_time( &(_p)->err_limit ); \
+ _mbg_swab_nano_time( &(_p)->warn_limit ); \
+ _mbg_swab32( &(_p)->reserved ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+
+/**
+ * @brief Current SHS settings and general SHS capabilities
+ *
+ * @see ::SHS_SETTINGS
+ * @see ::SHS_STATUS
+ */
+typedef struct
+{
+ SHS_SETTINGS settings; ///< current configuration settings
+ NANO_TIME max_limit; ///< if not 0, the max. allowed value for ::SHS_SETTINGS::err_limit and ::SHS_SETTINGS::warn_limit
+ uint32_t reserved; ///< reserved, currently always 0
+ uint32_t supp_flags; ///< indicates which flags are supported for ::SHS_SETTINGS::flags, see ::SHS_FLAG_MASKS
+
+} SHS_INFO;
+
+#define _mbg_swab_shs_info( _p ) \
+{ \
+ _mbg_swab_shs_settings( &(_p)->settings ); \
+ _mbg_swab_nano_time( &(_p)->max_limit ); \
+ _mbg_swab32( &(_p)->reserved ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+
+/**
+ * @brief Current SHS status
+ */
+typedef struct
+{
+ NANO_TIME time_diff; ///< current time difference between the 2 clocks
+ TM_STATUS_EXT clk_status_1; ///< status of first clock
+ TM_STATUS_EXT clk_status_2; ///< status of second clock
+ uint8_t shs_state; ///< see ::SHS_STATES
+ uint8_t reserved_1; ///< reserved, currently always 0
+ uint16_t reserved_2; ///< reserved, currently always 0
+ uint32_t flags; ///< see ::SHS_FLAG_MASKS
+
+} SHS_STATUS;
+
+#define _mbg_swab_shs_status( _p ) \
+{ \
+ _mbg_swab_nano_time( &(_p)->time_diff ); \
+ _mbg_swab32( &(_p)->clk_status_1 ); \
+ _mbg_swab32( &(_p)->clk_status_2 ); \
+ _mbg_swab16( &(_p)->reserved_2 ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+
+/**
+ * @brief SHS configuration flag bits
+ *
+ * Codes used with ::SHS_STATUS::shs_state
+ */
+enum SHS_STATES
+{
+ SHS_STATE_DISABLED, ///< time difference not checked, eventually no limits configured
+ SHS_STATE_OK, ///< time difference OK, below warning limit
+ SHS_STATE_WARNING, ///< time difference exceeds warning limit
+ SHS_STATE_ERROR, ///< time difference exceeds error limit
+ SHS_STATE_FATAL, ///< one or both time sources disconnected
+ N_SHS_STATES
+};
+
+
+
+/**
+ * @brief SHS flag bits
+ *
+ * @see ::SHS_FLAG_MASKS
+ */
+enum SHS_FLAG_BITS
+{
+ SHS_FLAG_BIT_DISB_SERIAL, ///< disable serial output in state ::SHS_STATE_ERROR
+ SHS_FLAG_BIT_DISB_PPS, ///< disable PPS output in state ::SHS_STATE_ERROR
+ SHS_FLAG_BIT_DISB_10MHZ, ///< disable 10 MHz output in state ::SHS_STATE_ERROR
+ N_SHS_FLAG_BITS
+};
+
+
+/**
+ * @brief SHS flag masks
+ *
+ * With ::SHS_INFO::supp_flags these flags indicate what is supported
+ * by the SHS controller, e.g. what action can be taken automatically.
+ * Each bit set in ::SHS_INFO::supp_flags can be set by a configuration
+ * tool in ::SHS_SETTINGS::flags to enable the associated feature.
+ * If a corresponding bit is set in ::SHS_STATUS::flags this means the
+ * associated feature has been enabled, e.g. an action has been taken.
+ *
+ * @see ::SHS_FLAG_BITS
+ */
+enum SHS_FLAG_MASKS
+{
+ SHS_FLAG_DISB_SERIAL = ( 1UL << SHS_FLAG_BIT_DISB_SERIAL ), ///< see ::SHS_FLAG_BIT_DISB_SERIAL
+ SHS_FLAG_DISB_PPS = ( 1UL << SHS_FLAG_BIT_DISB_PPS ), ///< see ::SHS_FLAG_BIT_DISB_PPS
+ SHS_FLAG_DISB_10MHZ = ( 1UL << SHS_FLAG_BIT_DISB_10MHZ ) ///< see ::SHS_FLAG_BIT_DISB_10MHZ
+};
+
+/** @} defgroup group_shs */
+
+
+
+/*------------------------------------------------------------------------*/
+
+/**
+ * @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_GPS]; ///< SV configuration from page 63
+ HEALTH health[N_SVNO_GPS]; ///< 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/mbg_ntp_test_util.c b/mbglib/common/mbg_ntp_test_util.c
index 59e6bcc..9ae3d47 100755
--- a/mbglib/common/mbg_ntp_test_util.c
+++ b/mbglib/common/mbg_ntp_test_util.c
@@ -1,7 +1,7 @@
/**************************************************************************
*
- * $Id: mbg_ntp_test_util.c 1.1 2014/04/01 13:02:21 martin REL_M $
+ * $Id: mbg_ntp_test_util.c 1.2 2014/09/24 09:25:44 martin REL_M $
*
* Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
*
@@ -10,6 +10,13 @@
*
* -----------------------------------------------------------------------
* $Log: mbg_ntp_test_util.c $
+ * Revision 1.2 2014/09/24 09:25:44 martin
+ * Account for modified NTP_PACKET definition.
+ * Account for changed NTP_TSTAMP field names.
+ * Fixed some compiler warnings.
+ * Avoid using MINLONG.
+ * Added some functions.
+ * Added and updated doxygen comments.
* Revision 1.1 2014/04/01 13:02:21 martin
* Initial revision.
*
@@ -29,11 +36,19 @@
/*HDR*/
+/**
+ * @brief Reset query statistics
+ *
+ * @param[out] p Statistics structure to be cleared.
+ */
void reset_query_stats( QUERY_STATS *p )
{
memset( p, 0, sizeof( *p ) );
+
p->turnaround.min = MAXLONG;
- p->turnaround.max = MINLONG;
+ p->turnaround.max = -MAXLONG;
+ p->latency.min = MAXDOUBLE;
+ p->latency.max = -MAXDOUBLE;
p->ntp_delay.min = MAXDOUBLE;
p->ntp_delay.max = -MAXDOUBLE;
p->ntp_offs.min = MAXDOUBLE;
@@ -44,6 +59,17 @@ void reset_query_stats( QUERY_STATS *p )
/*HDR*/
+/**
+ * @brief Print a statistics value of type "double"
+ *
+ * @param[in] info Optional text string printed at beginning of line, or NULL.
+ * @param[in] info_width Width of the info text field.
+ * @param[in] curr Current statistics parameter.
+ * @param[in] curr_width With of the printed field containing the current parameter value.
+ * @param[in] scale Scale for the parameter values before they are printed.
+ * @param[in] p Optional minimum and maximum values of this parameter, or NULL.
+ * @param[in] hint Optional hint text appended at the end of the line, or NULL.
+ */
void print_stats_double( const char *info, int info_width,
double curr, int curr_width, double scale,
const MIN_MAX_DOUBLE *p, const char *hint )
@@ -66,6 +92,11 @@ void print_stats_double( const char *info, int info_width,
/*HDR*/
+/**
+ * @brief Print a "struct timespec" as calendar date and time
+ *
+ * @param[in] p_ts The time stamp to be printed, in struct timespec format.
+ */
void print_timespec_date_time( const struct timespec *p_ts )
{
time_t t = p_ts->tv_sec;
@@ -84,6 +115,8 @@ void print_timespec_date_time( const struct timespec *p_ts )
/*HDR*/
/**
* @brief Print date and time of an NTP time stamp
+ *
+ * @param[in] t_ntp The time stamp to be printed, in NTP format.
*/
void print_ntp_date_time( const NTP_TSTAMP *t_ntp )
{
@@ -98,31 +131,41 @@ void print_ntp_date_time( const NTP_TSTAMP *t_ntp )
/*HDR*/
/**
- * @brief Print an NTP timestamp and optionally converted date and time
+ * @brief Print a raw NTP timestamp, and optionally the derived date and time
+ *
+ * @param[in] msg Text string printed at the beginning of the line.
+ * @param[in] t Time stamp, in NTP format.
+ * @param[in] tail Optional text appended to the output, or NULL.
+ * @param[in] print_date_time If not 0, print also the derived date and time.
*/
-void print_ntp_time( const char *msg, const NTP_TSTAMP *t, const char *tail )
+void print_ntp_time( const char *msg, const NTP_TSTAMP *t, const char *tail, int print_date_time )
{
- printf( "%s%08lX.%08lX", msg, (long) (uint32_t) t->integer, (long) (uint32_t) t->fraction );
+ printf( "%s%08lX.%08lX", msg, (ulong) t->seconds, (ulong) t->fractions );
- printf( " " );
- print_ntp_date_time( t );
+ if ( print_date_time )
+ {
+ printf( " " );
+ print_ntp_date_time( t );
+ }
if ( tail )
- printf( tail );
+ printf( "%s", tail );
} // print_ntp_time
-//
-// print contents of an NTP packet
-//
/*HDR*/
/**
- * @brief Print contents of an NTP packet
+ * @brief Print contents of an NTP packet on several lines
+ *
+ * @param[in] msg Header text to be printed on first line.
+ * @param[in] p An ::NTP_PACKET_INFO structure containing the NTP packet plus some additional information.
+ * @param[in] print_date_time If not 0, print also the date and time derived from the NTP time stamps.
*/
-void print_ntp_packet( const char *msg, const NTP_PACKET *p, const NTP_TSTAMP *t_rcv )
+void print_ntp_packet( const char *msg, const NTP_PACKET_INFO *p, int print_date_time )
{
+ const NTP_BASE_PACKET *pbp = &p->packet.base;
int i;
char ref_id_str[80];
char *cp = ref_id_str;
@@ -133,32 +176,31 @@ void print_ntp_packet( const char *msg, const NTP_PACKET *p, const NTP_TSTAMP *t
"mode %u, version %u, leap_ind %u, "
"stratum %u, poll %u, prec %u\n"
,
- p->packet.flags.mode,
- p->packet.flags.version,
- p->packet.flags.leap_ind,
- p->packet.flags.stratum,
- p->packet.flags.poll,
- p->packet.flags.precision
+ pbp->flags.mode,
+ pbp->flags.version,
+ pbp->flags.leap_ind,
+ pbp->flags.stratum,
+ pbp->flags.poll,
+ pbp->flags.precision
);
for ( i = 0; ; )
{
- unsigned char uc;
- uc = BYTE_OF( p->packet.reference_id, i );
+ unsigned char uc = BYTE_OF( pbp->reference_id, i );
if ( !isdigit( uc ) )
{
sprintf( ref_id_str, "%.*s",
- (int) sizeof( p->packet.reference_id ),
- (char *) &p->packet.reference_id
- );
+ (int) sizeof( pbp->reference_id ),
+ (char *) &pbp->reference_id
+ );
break;
}
cp += sprintf( cp, "%u", uc );
- if ( ++i >= sizeof( p->packet.reference_id ) )
+ if ( ++i >= sizeof( pbp->reference_id ) )
{
*cp = 0;
break;
@@ -172,20 +214,49 @@ void print_ntp_packet( const char *msg, const NTP_PACKET *p, const NTP_TSTAMP *t
INDENT "root dispersion: %08lX (%.4f s/s)\n"
INDENT "reference id: %08lX (%s)\n"
,
- (long) p->packet.root_delay, _u_fp_to_d( p->packet.root_delay ),
- (long) p->packet.root_dispersion, _u_fp_to_d( p->packet.root_dispersion ),
- (long) p->packet.reference_id,
+ (long) pbp->root_delay, _u_fp_to_d( pbp->root_delay ),
+ (long) pbp->root_dispersion, _u_fp_to_d( pbp->root_dispersion ),
+ (long) pbp->reference_id,
ref_id_str
);
- print_ntp_time( INDENT "Ref time: ", &p->packet.reference_time, newline );
- print_ntp_time( INDENT "Org time (T1): ", &p->packet.originate_time, newline );
- print_ntp_time( INDENT "Rcv time (T2): ", &p->packet.receive_time, newline );
- print_ntp_time( INDENT "Xmt time (T3): ", &p->packet.transmit_time, newline );
+ print_ntp_time( INDENT "Ref time: ", &pbp->reference_time, newline, print_date_time );
+ print_ntp_time( INDENT "Org time (T1): ", &pbp->originate_time, newline, print_date_time );
+ print_ntp_time( INDENT "Rcv time (T2): ", &pbp->receive_time, newline, print_date_time );
+ print_ntp_time( INDENT "Xmt time (T3): ", &pbp->transmit_time, newline, print_date_time );
+
+
+ if ( timespec_is_set( &p->tsr ) )
+ {
+ // We could also print the timespec directly but actually convert
+ // it to NTP format first to have the same output formatting.
+ NTP_TSTAMP ts;
+ timespec_to_ntp_tstamp( &ts, &p->tsr );
+ print_ntp_time( INDENT "Curr time (T4): ", &ts, newline, print_date_time );
+ }
+
+ if ( packet_has_mac( p ) )
+ {
+ const NTP_MAC *pm = &p->packet.mac;
+ size_t digest_len = get_digest_len( p );
+
+ printf( INDENT "Auth key ID: %08X", pm->key_id );
+
+ if ( pm->key_id == 0 && digest_len == 0 )
+ printf( " (crypto NACK)" );
+ printf( "\n" );
- if ( t_rcv )
- print_ntp_time( INDENT "Curr time (T4): ", t_rcv, newline );
+ if ( digest_len > 0 )
+ {
+ printf( INDENT "Auth digest: " );
+
+ for ( i = 0; i < digest_len; i++ )
+ printf( "%02X", pm->digest[i] );
+ }
+
+ printf( "\n" );
+ }
printf( "\n" );
@@ -194,89 +265,149 @@ void print_ntp_packet( const char *msg, const NTP_PACKET *p, const NTP_TSTAMP *t
/*HDR*/
+/**
+ * @brief Initialize a basic NTP packet
+ *
+ * @param[in] p The ::NTP_PACKET to be initialized.
+ * @param[in] req_mode Initalizer for the packet's mode field, e.g. ::MODE_CLIENT.
+ * @param[in] prot_version Initalizer for the packet's version field, e.g. ::DEFAULT_REQ_NTP_VERSION.
+ */
void init_ntp_req_packet( NTP_PACKET *p, int req_mode, int prot_version )
{
+ NTP_BASE_PACKET *pbp = &p->base;
+
memset( p, 0, sizeof( *p ) );
- p->packet.flags.mode = req_mode;
- p->packet.flags.version = prot_version;
- p->packet.flags.leap_ind = 3;
- p->packet.flags.stratum = 0;
- p->packet.flags.poll = 6;
- p->packet.flags.precision = 238;
+ pbp->flags.mode = req_mode;
+ pbp->flags.version = prot_version;
+ pbp->flags.leap_ind = 3;
+ pbp->flags.stratum = 0;
+ pbp->flags.poll = 6;
+ pbp->flags.precision = 238;
} // init_ntp_req_packet
/*HDR*/
-int eval_ntp_packet( NTP_PACKET *p_rcv_packet, NTP_PACKET *p_req_packet,
- const struct timespec *p_tsr_rcv, const struct timespec *p_tsr_req,
- const NTP_TSTAMP *p_t_req_ntp, QUERY_STATS *p_stats )
+/**
+ * @brief Evaluate the time stamps from an NTP packet received from a server
+ *
+ * @note The packet must already have been converted to host byte order.
+ *
+ * @param[out] p_rslt ::NTP_RESULTS structure to take up the results of the computations.
+ * @param[in] p_rcv The ::NTP_PACKET_INFO containing the packet received from the server, in host byte order.
+ *
+ * @see ::eval_ntp_packet
+ * @see ::update_query_stats
+ */
+void get_ntp_results( NTP_RESULTS *p_rslt, const NTP_PACKET_INFO *p_rcv )
{
- double turnaround;
- double latency;
- double ntp_delay;
- double ntp_offs;
- double t34;
- double t21;
- NTP_TSTAMP t_rcv; // *p_tv_rcv converted to NTP format
+ const NTP_BASE_PACKET *pbp = &p_rcv->packet.base;
+
+ // T4 is the packet receive time which is not part of
+ // the NTP base packet but passed via the NTP_PACKET_INFO
+ // structure. Save the timespec converted to NTP format
+ // in the result record.
+ timespec_to_ntp_tstamp( &p_rslt->t_rcv, &p_rcv->tsr );
- timespec_to_ntp_tstamp( &t_rcv, p_tsr_rcv );
+ // delay = (T4 - T1) - (T3 - T2)
+ p_rslt->turnaround = delta_tstamps( &p_rslt->t_rcv, &pbp->originate_time ); // (T4 - T1), our own clock domain
+ p_rslt->latency = delta_tstamps( &pbp->transmit_time, &pbp->receive_time ); // (T3 - T2), server's clock domain
+ p_rslt->ntp_delay = p_rslt->turnaround - p_rslt->latency; // (T4 - T1) - (T3 - T2)
- ntoh_ntp_packet( p_req_packet );
- ntoh_ntp_packet( p_rcv_packet );
+ // offset = ((T2 - T1) + (T3 - T4)) / 2
+ p_rslt->t21 = delta_tstamps( &pbp->receive_time, &pbp->originate_time ); // (T2 - T1)
+ p_rslt->t34 = delta_tstamps( &pbp->transmit_time, &p_rslt->t_rcv ); // (T3 - T4)
+ p_rslt->ntp_offs = ( p_rslt->t21 + p_rslt->t34 ) / 2.0; // ((T2 - T1) + (T3 - T4)) / 2
+} // get_ntp_results
- // delay = (T4 – T1) – (T3 – T2)
- // offset = ((T2 – T1) + (T3 – T4)) / 2
- turnaround = delta_tstamps( &t_rcv, &p_rcv_packet->packet.originate_time ); // (T4 - T1)
- latency = delta_tstamps( &p_rcv_packet->packet.transmit_time, &p_rcv_packet->packet.receive_time ); // (T3 - T2)
- ntp_delay = turnaround - latency;
- t21 = delta_tstamps( &p_rcv_packet->packet.receive_time, &p_rcv_packet->packet.originate_time ); // (T2 - T1)
- t34 = delta_tstamps( &p_rcv_packet->packet.transmit_time, &t_rcv ); // (T3 - T4)
- ntp_offs = ( t21 + t34 ) / 2.0;
+/*HDR*/
+/**
+ * @brief Update query statistics with the results from the last query
+ *
+ * @param[in,out] p_stats A ::QUERY_STATS structure to be updated.
+ * @param[in] p_rslt ::NTP_RESULTS structure eventually set up by ::get_ntp_results.
+ * @param[in] new_queries number of queries sent to yield the latest results (usually 1).
+ *
+ * @see ::get_ntp_results
+ */
+void update_query_stats( QUERY_STATS *p_stats, const NTP_RESULTS *p_rslt, int new_queries )
+{
+ p_stats->replies += new_queries;
+
+ update_min_max_double( p_rslt->turnaround, &p_stats->turnaround );
+ update_min_max_double( p_rslt->latency, &p_stats->latency );
+ update_min_max_double( p_rslt->ntp_offs, &p_stats->ntp_offs );
+ update_min_max_double( p_rslt->ntp_delay, &p_stats->ntp_delay );
+
+} // update_query_stats
- // update statistics begins
- p_stats->replies++;
+/*HDR*/
+/**
+ * @brief Print query statistics
+ *
+ * @param[in] p_rslt ::NTP_RESULTS structure eventually set up by ::get_ntp_results.
+ * @param[in] p_stats Optional ::QUERY_STATS structure, or NULL.
+ * @param[in] info_width Field with of the info strings.
+ * @param[in] val_width Field width for the values.
+ * @param[in] scale Scale for the values.
+ */
+void print_query_stats( const NTP_RESULTS *p_rslt, const QUERY_STATS *p_stats,
+ int info_width, int val_width, double scale )
+{
+ print_stats_double( "turnaround: ", info_width, p_rslt->turnaround, val_width, scale,
+ p_stats ? &p_stats->turnaround : NULL, " us (T4 - T1)" );
- update_min_max_double( turnaround, &p_stats->turnaround );
- update_min_max_double( latency, &p_stats->latency );
- update_min_max_double( ntp_offs, &p_stats->ntp_offs );
- update_min_max_double( ntp_delay, &p_stats->ntp_delay );
+ print_stats_double( "server latency: ", info_width, p_rslt->latency, val_width, scale,
+ p_stats ? &p_stats->latency : NULL, " us (T3 - T2)" );
- // update statistics ended
+ print_stats_double( "computed delay: ", info_width, p_rslt->ntp_delay, val_width, scale,
+ p_stats ? &p_stats->ntp_delay : NULL, " us ((T4 - T1) - (T3 - T2))" );
+ print_stats_double( "computed offset: ", info_width, p_rslt->ntp_offs, val_width, scale,
+ p_stats ? &p_stats->ntp_offs : NULL, " us (((T2 - T1) + (T3 - T4)) / 2)" );
- // print results, if appropriate
+} // print_query_stats
- print_ntp_packet( "Request packet:", p_req_packet, p_t_req_ntp );
- print_ntp_packet( "Response packet:", p_rcv_packet, &t_rcv );
- {
- int info_width = 17;
- int val_width = 10;
- double scale = 1e6;
+/*HDR*/
+/**
+ * @brief Evaluate an NTP packet received from a server
+ *
+ * @note The packet to be evaluated must be in network byte order
+ * and is converted to host byte order.
+ *
+ * @param[out] p_rslt Optional ::NTP_RESULTS structure to take up the results of the computations, or NULL.
+ * @param[in,out] p_rcv The ::NTP_PACKET to be evaluated, in network byte order.
+ * @param[in,out] p_stats A ::QUERY_STATS structure to be updated.
+ *
+ * @see ::ntoh_ntp_packet
+ * @see ::get_ntp_results
+ * @see ::update_query_stats
+ */
+int eval_ntp_packet( NTP_RESULTS *p_rslt, NTP_PACKET_INFO *p_rcv,
+ QUERY_STATS *p_stats )
+{
+ NTP_RESULTS rslt;
- print_stats_double( "turnaround: ", info_width, turnaround, val_width, scale,
- &p_stats->turnaround, " us (T4 - T1)" );
+ if ( p_rslt == NULL ) // optional parameter not passed
+ p_rslt = &rslt;
- print_stats_double( "server latency: ", info_width, latency, val_width, scale,
- &p_stats->latency, " us (T3 - T2)" );
+ // Message authentication code (MAC) should be checked here, if supported.
- print_stats_double( "computed delay: ", info_width, ntp_delay, val_width, scale,
- &p_stats->ntp_delay, " us ((T4 – T1) – (T3 – T2))" );
+ ntoh_ntp_packet( p_rcv );
- print_stats_double( "computed offset: ", info_width, ntp_offs, val_width, scale,
- &p_stats->ntp_offs, " us (((T2 – T1) + (T3 – T4)) / 2)" );
- }
+ get_ntp_results( p_rslt, p_rcv );
- printf( "\n" );
+ if ( p_stats )
+ update_query_stats( p_stats, p_rslt, 1 );
return 1;
@@ -284,3 +415,67 @@ int eval_ntp_packet( NTP_PACKET *p_rcv_packet, NTP_PACKET *p_req_packet,
+/*HDR*/
+/**
+ * @brief Eval NTP packet and update statistics without returning results
+ *
+ * @param[in,out] p_rcv The ::NTP_PACKET to be evaluated, in network byte order.
+ * @param[in,out] p_stats A ::QUERY_STATS structure to be updated.
+ *
+ * @see ::eval_ntp_packet
+ */
+int update_ntp_stats( NTP_PACKET_INFO *p_rcv, QUERY_STATS *p_stats )
+{
+ return eval_ntp_packet( NULL, p_rcv, p_stats );
+
+} // update_ntp_stats
+
+
+
+/*HDR*/
+/**
+ * @brief Print NTP results
+ *
+ * @param[in] p_rslt ::NTP_RESULTS structure eventually set up by ::eval_ntp_packet, or NULL.
+ * @param[in] p_req The ::NTP_PACKET_INFO containing the request packet sent to the server, in host byte order, or NULL.
+ * @param[in] p_rcv The ::NTP_PACKET_INFO containing the packet received from the server, in host byte order, or NULL.
+ * @param[in] p_stats A ::QUERY_STATS structure to be printed, or NULL.
+ * @param[in] print_date_time Controls if ::print_ntp_packet also prints broken down date and time
+ * @param[in] verbose Also prints a line with auth result if auth is not used at all
+ *
+ * @see ::eval_ntp_packet
+ */
+void print_ntp_results( const NTP_RESULTS *p_rslt, const NTP_PACKET_INFO *p_req,
+ const NTP_PACKET_INFO *p_rcv, const QUERY_STATS *p_stats,
+ int print_date_time, int verbose )
+{
+ if ( p_req )
+ print_ntp_packet( "Request packet:", p_req, print_date_time );
+
+ if ( p_rcv )
+ print_ntp_packet( "Response packet:", p_rcv, print_date_time );
+
+ if ( p_rslt ) // p_stats may be NULL
+ {
+ const char *cp = NULL;
+
+ switch ( p_rslt->auth_code )
+ {
+ case MBG_NTP_AUTH_NONE: cp = verbose ? "not used" : NULL; break;
+ case MBG_NTP_AUTH_OK: cp = "OK"; break;
+ case MBG_NTP_AUTH_NACK: cp = "received crypto NACK"; break;
+ case MBG_NTP_AUTH_FAIL: cp = "*** failed ***"; break;
+ }
+
+ if ( cp )
+ printf( "Authentication: %s\n\n", cp );
+
+ print_query_stats( p_rslt, p_stats, 17, 10, 1e6 );
+ }
+
+ printf( "\n" );
+
+} // print_ntp_results
+
+
+
diff --git a/mbglib/common/mbg_ntp_test_util.h b/mbglib/common/mbg_ntp_test_util.h
index 2ef6241..4fc380e 100755
--- a/mbglib/common/mbg_ntp_test_util.h
+++ b/mbglib/common/mbg_ntp_test_util.h
@@ -1,15 +1,20 @@
/**************************************************************************
*
- * $Id: mbg_ntp_test_util.h 1.1 2014/04/01 13:02:21 martin REL_M $
+ * $Id: mbg_ntp_test_util.h 1.2 2014/09/24 11:12:20 martin REL_M $
*
* Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
*
* Description:
- * Definitions and prototypes used with mbg_ntp_test_util.h
+ * Definitions and prototypes used with mbg_ntp_test_util.c
*
* -----------------------------------------------------------------------
* $Log: mbg_ntp_test_util.h $
+ * Revision 1.2 2014/09/24 11:12:20 martin
+ * New structure NTP_RESULTS.
+ * Account for changed NTP_TSTAMP field names.
+ * Added and updated doxygen comments.
+ * Updated function prototypes.
* Revision 1.1 2014/04/01 13:02:21 martin
* Initial revision.
*
@@ -24,6 +29,9 @@
#include <mbg_tgt.h>
#include <mbgntp.h>
+#include <time.h>
+
+
#if defined( MBG_TGT_POSIX )
#include <syslog.h>
#include <arpa/inet.h>
@@ -88,6 +96,21 @@ typedef struct
+typedef struct
+{
+ NTP_TSTAMP t_rcv; ///< packet receive time in NTP format
+ double turnaround;
+ double latency;
+ double ntp_delay;
+ double ntp_offs;
+ double t34;
+ double t21;
+ int auth_code; ///< see ::MBG_NTP_AUTH_CODES
+
+} NTP_RESULTS;
+
+
+
static __mbg_inline /*HDR*/
void update_min_max_double( double curr, MIN_MAX_DOUBLE *p )
{
@@ -104,7 +127,7 @@ void update_min_max_double( double curr, MIN_MAX_DOUBLE *p )
static __mbg_inline /*HDR*/
double ntp_tstamp_to_double( const NTP_TSTAMP *t )
{
- return (double) t->integer + ( ( (double) t->fraction ) / NTP_FRAC_PER_SEC );
+ return (double) t->seconds + ( ( (double) t->fractions ) / NTP_FRAC_PER_SEC );
} // ntp_tstamp_to_double
@@ -145,8 +168,8 @@ uint32_t nsec_to_ntp_frac( ulong nsec )
static __mbg_inline /*HDR*/
void timespec_to_ntp_tstamp( NTP_TSTAMP *t_ntp, const struct timespec *t_ts )
{
- t_ntp->integer = t_ts->tv_sec + NTP_OFFS;
- t_ntp->fraction = nsec_to_ntp_frac( t_ts->tv_nsec );
+ t_ntp->seconds = t_ts->tv_sec + NTP_SEC_BIAS;
+ t_ntp->fractions = nsec_to_ntp_frac( t_ts->tv_nsec );
} // timespec_to_ntp_tstamp
@@ -155,53 +178,19 @@ void timespec_to_ntp_tstamp( NTP_TSTAMP *t_ntp, const struct timespec *t_ts )
static __mbg_inline /*HDR*/
void ntp_tstamp_to_timespec( struct timespec *t_ts, const NTP_TSTAMP *t_ntp )
{
- t_ts->tv_sec = ( (uint32_t) t_ntp->integer ) - NTP_OFFS;
- t_ts->tv_nsec = ntp_frac_to_nsec( t_ntp->fraction );
+ t_ts->tv_sec = t_ntp->seconds - NTP_SEC_BIAS;
+ t_ts->tv_nsec = ntp_frac_to_nsec( t_ntp->fractions );
} // ntp_tstamp_to_timespec
-//
-// convert the byte order of an NTP time stamp
-// from net to host
-//
static __mbg_inline /*HDR*/
-void ntoh_ntp_time( NTP_TSTAMP *t )
+int timespec_is_set( const struct timespec *p )
{
- t->integer = ntohl( t->integer );
- t->fraction = ntohl( t->fraction );
+ return p->tv_sec != 0 || p->tv_nsec != 0;
-} // ntoh_ntp_time
-
-
-//
-// convert the byte order of an NTP packet
-// from net to host
-//
-static __mbg_inline /*HDR*/
-void ntoh_ntp_packet( NTP_PACKET *p )
-{
- ntoh_ntp_time( &p->packet.reference_time );
- ntoh_ntp_time( &p->packet.originate_time );
- ntoh_ntp_time( &p->packet.receive_time );
- ntoh_ntp_time( &p->packet.transmit_time );
-
- p->packet.root_delay = ntohl( p->packet.root_delay );
- p->packet.root_dispersion = ntohl( p->packet.root_dispersion );
-
-} // ntoh_ntp_packet
-
-
-
-static __mbg_inline /*HDR*/
-double delta_tstamps( const NTP_TSTAMP *t,
- const NTP_TSTAMP *t_ref )
-{
- return ( (double) t->integer - (double) t_ref->integer )
- + ( (double) t->fraction - (double) t_ref->fraction ) / NTP_FRAC_PER_SEC;
-
-} // delta_tstamps
+} // timespec_is_set
@@ -247,26 +236,143 @@ int check_bounds( int opt_val, int min_val, int max_val, int default_val )
/* This section was generated automatically */
/* by MAKEHDR, do not remove the comments. */
+ /**
+ * @brief Reset query statistics
+ *
+ * @param[out] p Statistics structure to be cleared.
+ */
void reset_query_stats( QUERY_STATS *p ) ;
+
+ /**
+ * @brief Print a statistics value of type "double"
+ *
+ * @param[in] info Optional text string printed at beginning of line, or NULL.
+ * @param[in] info_width Width of the info text field.
+ * @param[in] curr Current statistics parameter.
+ * @param[in] curr_width With of the printed field containing the current parameter value.
+ * @param[in] scale Scale for the parameter values before they are printed.
+ * @param[in] p Optional minimum and maximum values of this parameter, or NULL.
+ * @param[in] hint Optional hint text appended at the end of the line, or NULL.
+ */
void print_stats_double( const char *info, int info_width, double curr, int curr_width, double scale, const MIN_MAX_DOUBLE *p, const char *hint ) ;
+
+ /**
+ * @brief Print a "struct timespec" as calendar date and time
+ *
+ * @param[in] p_ts The time stamp to be printed, in struct timespec format.
+ */
void print_timespec_date_time( const struct timespec *p_ts ) ;
+
/**
* @brief Print date and time of an NTP time stamp
+ *
+ * @param[in] t_ntp The time stamp to be printed, in NTP format.
*/
void print_ntp_date_time( const NTP_TSTAMP *t_ntp ) ;
/**
- * @brief Print an NTP timestamp and optionally converted date and time
+ * @brief Print a raw NTP timestamp, and optionally the derived date and time
+ *
+ * @param[in] msg Text string printed at the beginning of the line.
+ * @param[in] t Time stamp, in NTP format.
+ * @param[in] tail Optional text appended to the output, or NULL.
+ * @param[in] print_date_time If not 0, print also the derived date and time.
*/
- void print_ntp_time( const char *msg, const NTP_TSTAMP *t, const char *tail ) ;
+ void print_ntp_time( const char *msg, const NTP_TSTAMP *t, const char *tail, int print_date_time ) ;
/**
- * @brief Print contents of an NTP packet
+ * @brief Print contents of an NTP packet on several lines
+ *
+ * @param[in] msg Header text to be printed on first line.
+ * @param[in] p An ::NTP_PACKET_INFO structure containing the NTP packet plus some additional information.
+ * @param[in] print_date_time If not 0, print also the date and time derived from the NTP time stamps.
*/
- void print_ntp_packet( const char *msg, const NTP_PACKET *p, const NTP_TSTAMP *t_rcv ) ;
+ void print_ntp_packet( const char *msg, const NTP_PACKET_INFO *p, int print_date_time ) ;
+ /**
+ * @brief Initialize a basic NTP packet
+ *
+ * @param[in] p The ::NTP_PACKET to be initialized.
+ * @param[in] req_mode Initalizer for the packet's mode field, e.g. ::MODE_CLIENT.
+ * @param[in] prot_version Initalizer for the packet's version field, e.g. ::DEFAULT_REQ_NTP_VERSION.
+ */
void init_ntp_req_packet( NTP_PACKET *p, int req_mode, int prot_version ) ;
- int eval_ntp_packet( NTP_PACKET *p_rcv_packet, NTP_PACKET *p_req_packet, const struct timespec *p_tsr_rcv, const struct timespec *p_tsr_req, const NTP_TSTAMP *p_t_req_ntp, QUERY_STATS *p_stats ) ;
+
+ /**
+ * @brief Evaluate the time stamps from an NTP packet received from a server
+ *
+ * @note The packet must already have been converted to host byte order.
+ *
+ * @param[out] p_rslt ::NTP_RESULTS structure to take up the results of the computations.
+ * @param[in] p_rcv The ::NTP_PACKET_INFO containing the packet received from the server, in host byte order.
+ *
+ * @see ::eval_ntp_packet
+ * @see ::update_query_stats
+ */
+ void get_ntp_results( NTP_RESULTS *p_rslt, const NTP_PACKET_INFO *p_rcv ) ;
+
+ /**
+ * @brief Update query statistics with the results from the last query
+ *
+ * @param[in,out] p_stats A ::QUERY_STATS structure to be updated.
+ * @param[in] p_rslt ::NTP_RESULTS structure eventually set up by ::get_ntp_results.
+ * @param[in] new_queries number of queries sent to yield the latest results (usually 1).
+ *
+ * @see ::get_ntp_results
+ */
+ void update_query_stats( QUERY_STATS *p_stats, const NTP_RESULTS *p_rslt, int new_queries ) ;
+
+ /**
+ * @brief Print query statistics
+ *
+ * @param[in] p_rslt ::NTP_RESULTS structure eventually set up by ::get_ntp_results.
+ * @param[in] p_stats Optional ::QUERY_STATS structure, or NULL.
+ * @param[in] info_width Field with of the info strings.
+ * @param[in] val_width Field width for the values.
+ * @param[in] scale Scale for the values.
+ */
+ void print_query_stats( const NTP_RESULTS *p_rslt, const QUERY_STATS *p_stats, int info_width, int val_width, double scale ) ;
+
+ /**
+ * @brief Evaluate an NTP packet received from a server
+ *
+ * @note The packet to be evaluated must be in network byte order
+ * and is converted to host byte order.
+ *
+ * @param[out] p_rslt Optional ::NTP_RESULTS structure to take up the results of the computations, or NULL.
+ * @param[in,out] p_rcv The ::NTP_PACKET to be evaluated, in network byte order.
+ * @param[in,out] p_stats A ::QUERY_STATS structure to be updated.
+ *
+ * @see ::ntoh_ntp_packet
+ * @see ::get_ntp_results
+ * @see ::update_query_stats
+ */
+ int eval_ntp_packet( NTP_RESULTS *p_rslt, NTP_PACKET_INFO *p_rcv, QUERY_STATS *p_stats ) ;
+
+ /**
+ * @brief Eval NTP packet and update statistics without returning results
+ *
+ * @param[in,out] p_rcv The ::NTP_PACKET to be evaluated, in network byte order.
+ * @param[in,out] p_stats A ::QUERY_STATS structure to be updated.
+ *
+ * @see ::eval_ntp_packet
+ */
+ int update_ntp_stats( NTP_PACKET_INFO *p_rcv, QUERY_STATS *p_stats ) ;
+
+ /**
+ * @brief Print NTP results
+ *
+ * @param[in] p_rslt ::NTP_RESULTS structure eventually set up by ::eval_ntp_packet, or NULL.
+ * @param[in] p_req The ::NTP_PACKET_INFO containing the request packet sent to the server, in host byte order, or NULL.
+ * @param[in] p_rcv The ::NTP_PACKET_INFO containing the packet received from the server, in host byte order, or NULL.
+ * @param[in] p_stats A ::QUERY_STATS structure to be printed, or NULL.
+ * @param[in] print_date_time Controls if ::print_ntp_packet also prints broken down date and time
+ * @param[in] verbose Also prints a line with auth result if auth is not used at all
+ *
+ * @see ::eval_ntp_packet
+ */
+ void print_ntp_results( const NTP_RESULTS *p_rslt, const NTP_PACKET_INFO *p_req, const NTP_PACKET_INFO *p_rcv, const QUERY_STATS *p_stats, int print_date_time, int verbose ) ;
+
/* ----- function prototypes end ----- */
diff --git a/mbglib/common/mbg_tgt.h b/mbglib/common/mbg_tgt.h
index 91b4d09..3c18952 100755
--- a/mbglib/common/mbg_tgt.h
+++ b/mbglib/common/mbg_tgt.h
@@ -1,7 +1,7 @@
/**************************************************************************
*
- * $Id: mbg_tgt.h 1.30 2014/04/01 12:55:58 martin REL_M $
+ * $Id: mbg_tgt.h 1.34 2015/03/03 13:32:49 martin REL_M $
*
* Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
*
@@ -11,6 +11,18 @@
*
* -----------------------------------------------------------------------
* $Log: mbg_tgt.h $
+ * Revision 1.34 2015/03/03 13:32:49 martin
+ * Provide __func__ for MS Visual Studio.
+ * Revision 1.33 2015/03/02 11:27:59Z martin
+ * Windows only:
+ * Define _CRT_SECURE_NO_WARNINGS to quiet compiler warnings.
+ * Define WIN32_LEAN_AND_MEAN only if it hasn't been defined before.
+ * Revision 1.32 2014/06/24 09:21:44 martin
+ * Update for newer C++Builder versions.
+ * Revision 1.31 2014/05/27 10:23:33 martin
+ * Finer control of which types are required for or already
+ * available on particular target systems.
+ * First definitions to support SunOS/Solaris.
* Revision 1.30 2014/04/01 12:55:58 martin
* Define MBG_TGT_WIN32 also for MS resource compiler.
* New target MBG_TGT_POSIX.
@@ -205,6 +217,23 @@
// GCC for target OpenBSD
#define MBG_TGT_OPENBSD
+#elif defined( __sun ) // Oracle Solaris or other SunOS derived operating system
+
+ // __SUNPRO_C Oracle Solaris Studio C compiler, __SUNPRO_C value is the version number
+ // __SUNPRO_CC Oracle Solaris Studio C++ compiler, __SUNPRO_CC value is the version number
+ // __sparc generate code for SPARC (R) architecture (32-bit or 64-bit)
+ // __sparcv9 generate code for 64-bit SPARC architecture
+ // __i386 generate code for 32-bit x86 architecture
+ // __amd64 generate code for 64-bit x64 architecture
+
+ #define MBG_TGT_SUNOS
+
+ #define __mbg_inline __inline__
+
+ #include <stdint.h>
+ #include <stdbool.h>
+ #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1
+
#elif defined( __QNX__ )
// any compiler for target QNX
@@ -242,7 +271,8 @@
#endif
#if defined( MBG_TGT_LINUX ) \
- || defined( MBG_TGT_BSD )
+ || defined( MBG_TGT_BSD ) \
+ || defined( MBG_TGT_SUNOS )
#define MBG_TGT_POSIX
#define MBG_TGT_UNIX
#endif
@@ -285,11 +315,28 @@
#if defined( MBG_TGT_LINUX )
#if defined( __KERNEL__ )
+
#include <linux/types.h>
+ #include <linux/version.h>
+
+ #if ( LINUX_VERSION_CODE <= KERNEL_VERSION( 2, 6, 4 ) )
+ #define _ULONG_DEFINED 1
+ #define _USHORT_DEFINED 1
+ #define _UINT_DEFINED 1
+ #endif
+
#else
+
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
+
+ #if defined( __u_char_defined )
+ #define _ULONG_DEFINED 1
+ #define _USHORT_DEFINED 1
+ #define _UINT_DEFINED 1
+ #endif
+
#endif
#elif defined( MBG_TGT_BSD )
@@ -340,6 +387,11 @@
#define __mbg_inline __forceinline
+ // At least up to VS2008 the builtin symbol __func__
+ // is not supported, but __FUNCTION__ returns the name
+ // of the current function instead.
+ #define __func__ __FUNCTION__
+
#elif defined( _CVI_ )
// 1000 for CVI v10.0 (CVI 2010)
@@ -365,19 +417,39 @@
// Inline code is not supported, though the inline keyword
// is silently accepted since CVI v9.0
-#elif defined( __BORLANDC__ )
+#elif defined( __BORLANDC__ ) // or __CODEGEARC__ in newer versions
- // 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
+ // 0x0400 Borland C/C++ 3.0
+ // 0x0410 Borland C/C++ 3.1
+ // 0x0550 Borland C/C++ 5.5 (C++Builder 5.0)
+
+ // Next codes are in addition defined as __CODEGEARC__
+ // See http://docwiki.embarcadero.com
+
+ // 0x0570 for Borland Developer Studio 2006 (BDS 2006)
+ // 0x0590 for C++Builder 2007
+ // 0x0591 for update 1 to C++Builder 2007
+ // 0x0592 for RAD Studio 2007
+ // 0x0593 for the December update to RAD Studio 2007
+ // 0x0610 for C++Builder 2009 and for C++Builder 2009 Update 1
+ // 0x0620 for C++Builder 2010 and for C++Builder 2010 Update 1
+ // 0x0621 for C++Builder 2010 Update 2
+ // 0x0630 for C++Builder XE
+ // 0x0631 for C++Builder XE Update 1
+ // 0x0640 for C++Builder XE2
+ // 0x0650 for C++Builder XE3
+
+ #if ( __BORLANDC__ >= 0x630 )
+ // C++Builder XE starts to provide stdbool.h
#include <stdint.h>
#include <stdbool.h>
#define MBG_TGT_HAS_EXACT_SIZE_TYPES 1
+ #elif ( __BORLANDC__ >= 0x570 )
+ // at least BDS 2006 starts to provide stdint.h
+ #include <stdint.h>
+ #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1
+ #define MBG_TGT_MISSING_BOOL_TYPE 1
#elif ( __BORLANDC__ >= 0x0550 )
#define MBG_TGT_HAS_INT_8_16_32 1
#define MBG_TGT_MISSING_BOOL_TYPE 1
@@ -437,6 +509,8 @@
#if defined( MBG_TGT_WIN32 )
+ #define _CRT_SECURE_NO_WARNINGS
+
#if defined( _AMD64_ )
// This is used for AMD64 architecture and for
// Intel XEON CPUs with 64 bit extension.
@@ -452,7 +526,10 @@
#include <ntddk.h>
#else
// This must not be used for kernel drivers.
- #define WIN32_LEAN_AND_MEAN 1
+ #if !defined( WIN32_LEAN_AND_MEAN )
+ #define WIN32_LEAN_AND_MEAN 1
+ #endif
+
#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
#include <winsock2.h>
#include <windows.h>
diff --git a/mbglib/common/mbgntp.h b/mbglib/common/mbgntp.h
index a464b59..c703822 100755
--- a/mbglib/common/mbgntp.h
+++ b/mbglib/common/mbgntp.h
@@ -1,7 +1,7 @@
/**************************************************************************
*
- * $Id: mbgntp.h 1.4 2014/04/01 12:30:30 martin REL_M $
+ * $Id: mbgntp.h 1.7 2014/10/28 08:52:33 martin REL_M $
*
* Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
*
@@ -10,6 +10,24 @@
*
* -----------------------------------------------------------------------
* $Log: mbgntp.h $
+ * Revision 1.7 2014/10/28 08:52:33 martin
+ * Made definition of NSECS_PER_SEC the same as in mbgtime.h to
+ * avoid compiler warnings in projects using both header files.
+ * Added/updated some comments.
+ * Revision 1.6 2014/09/24 11:18:39 martin
+ * Modified NTP_PACKET definition which now always includes the base
+ * packet and the maximum sized message authentication code (MAC).
+ * New structure NTP_PACKET_INFO which includes an NTP_PACKET plus
+ * the current packet length, depending on the MAC usage, plus the
+ * transmit or receive time stamp in struct timespec format.
+ * Inline functions can be used to tell if a packet actually includes
+ * a MAC field with or without digest, return its length, extract its
+ * key ID, etc.
+ * Renamed NTP_OFFS to NTP_SEC_BIAS.
+ * Added or modified some doxygen comments.
+ * Reordered some code.
+ * Revision 1.5 2014/05/06 11:03:47 martin
+ * Use NTP_TSTAMP from gpsdefs.h.
* Revision 1.4 2014/04/01 12:30:30 martin
* Include mbg_tgt.h.
* MD5 auth support disabled by default.
@@ -24,7 +42,7 @@
* Initial revision
*
**************************************************************************/
-
+
#ifndef _MBGNTP_H
#define _MBGNTP_H
@@ -33,6 +51,10 @@
#include <mbg_tgt.h>
#include <words.h>
+#include <gpsdefs.h>
+
+#include <arpa/inet.h> // ntohl()
+
#ifdef _MBGNTP
#define _ext
@@ -44,23 +66,36 @@
/* Start of header body */
-#ifndef MBG_MD5_AUTH
- #define MBG_MD5_AUTH 0
-#endif
-
+/**
+ * @brief The IANA-assigned network port used by NTP
+ */
#define NTP_PORT 123
-#define NTP_OFFS 2208988800UL
+
+
+/**
+ * @brief NTP epoch bias from ordinary time_t epoch
+ *
+ * The Unix time_t epoch is usually 1970-01-01 00:00 whereas
+ * the NTP epoch is 1900-01-01 00:00, so the difference is
+ * a constant number of seconds:<br>
+ *
+ * time_t t = ntp_time - ::NTP_SEC_BIAS
+ */
+#define NTP_SEC_BIAS 2208988800UL
+
+
+#define NSECS_PER_SEC 1000000000UL
#define NTP_FRAC_PER_SEC (uint64_t) 4294967296.0
-#define NSECS_PER_SEC 1000000000L
#define MIN_REQ_NTP_VERSION 3
#define MAX_REQ_NTP_VERSION 4
#define DEFAULT_REQ_NTP_VERSION MAX_REQ_NTP_VERSION
+
// From NTP's ntp.h:
#define MODE_UNSPEC 0 /* unspecified (old version) */
#define MODE_ACTIVE 1 /* symmetric active mode */
@@ -69,17 +104,24 @@
#define MODE_SERVER 4 /* server mode */
#define MODE_BROADCAST 5 /* broadcast mode */
-#define DEFAULT_REQ_NTP_MODE MODE_CLIENT
-typedef struct
+/**
+ * @brief Codes returned by functions generating or checking NTP authentication
+ */
+enum MBG_NTP_AUTH_CODES
{
- int32_t integer;
- uint32_t fraction;
-} NTP_TSTAMP;
+ MBG_NTP_AUTH_NONE, ///< Auth. not used or supported
+ MBG_NTP_AUTH_OK, ///< Auth. checking on receive was OK, try auth on send
+ MBG_NTP_AUTH_NACK, ///< Received a crypto NACK (i.e. key ID == 0)
+ MBG_NTP_AUTH_FAIL, ///< Auth. checking on receive failed, must send crypto NACK
+ N_MBG_NTP_AUTH_CODES ///< Number of known codes
+};
+
+// types and conversion functions stolen from NTP
typedef int32_t NTP_S_FP; // signed floating point in integer representation
typedef uint32_t NTP_U_FP; // unsigned floating point in integer representation
@@ -88,9 +130,11 @@ typedef uint32_t NTP_U_FP; // unsigned floating point in integer representation
/*
* s_fp/double and u_fp/double conversions
*/
-#define FRIC 65536 /* 2^16 as a double */
-#if 1
+#define FRIC 65536.0 ///< 2^16 as double
+
+
+#if 1 // use inline functions for conversion
static __mbg_inline /*HDR*/
NTP_S_FP d_to_s_fp( double d )
@@ -116,13 +160,12 @@ double u_fp_to_d( NTP_U_FP u_fp )
return (double) u_fp / FRIC;
}
-
#define _d_to_s_fp( _r ) d_to_s_fp( _r )
#define _d_to_u_fp( _r ) d_to_u_fp( _r )
#define _s_fp_to_d( _r ) s_fp_to_d( _r )
#define _u_fp_to_d( _r ) u_fp_to_d( _r )
-#else
+#else // use conversion macros as defined in the NTP source code
#define _d_to_s_fp( _r ) ( (NTP_S_FP) ( (_r) * FRIC ) )
#define _d_to_u_fp( _r ) ( (NTP_U_FP) ( (_r) * FRIC ) )
@@ -131,18 +174,40 @@ double u_fp_to_d( NTP_U_FP u_fp )
#endif
+
+
+/**
+ * @brief The flags field of an ::NTP_BASE_PACKET
+ *
+ * This is a bit-coded 32 bit wide field.
+ */
typedef struct
{
unsigned int mode : 3;
- unsigned int version : 3;
+ unsigned int version : 3; ///< see ::MIN_REQ_NTP_VERSION, ::MAX_REQ_NTP_VERSION, ::DEFAULT_REQ_NTP_VERSION
unsigned int leap_ind : 2;
unsigned int stratum : 8;
unsigned int poll : 8;
unsigned int precision : 8;
+
} NTP_FLAGS;
+/**
+ * @brief The NTP base packet
+ *
+ * If authentication is used an ::NTP_MAC field can be appended to the packet,
+ * and the length of the MAC field depends on the type of authentication.
+ * Also, the packet doesn't include a time stamp when the packet has been received,
+ * so the ::NTP_PACKET_INFO structure has been introduced which contains the base
+ * packet, plus its actual length, plus a receive or transmit time stamp, and thus
+ * simplifies handling of the packet by the implementation.
+ *
+ * @see ::NTP_MAC
+ * @see ::NTP_PACKET
+ * @see ::NTP_PACKET_INFO
+ */
typedef struct
{
NTP_FLAGS flags;
@@ -153,32 +218,202 @@ typedef struct
NTP_TSTAMP originate_time;
NTP_TSTAMP receive_time;
NTP_TSTAMP transmit_time;
+
} NTP_BASE_PACKET;
+#define NTP_BASE_PACKET_SIZE sizeof( NTP_BASE_PACKET )
+
+
+/**
+ * @brief The key ID field of an ::NTP_MAC
+ */
+typedef uint32_t NTP_KEY_ID;
+
+
+
+/**
+ * @brief The maximum length of a message digest (hash)
+ *
+ * The number of bytes actually used depends on the type of the key
+ * (MD5, etc.) the ID of which has been specified in the ::NTP_KEY_ID.
+ */
+#define MAX_NTP_DIGEST_BYTES 20
-#if MBG_MD5_AUTH
-#define N_NTP_MAC_BYTES 16
+/**
+ * @brief NTP Message authentication code
+ */
typedef struct
{
- uint32_t key_id;
- uint8_t mac[N_NTP_MAC_BYTES]; // message authenticator
-} NTP_AUTH_INFO;
+ /// The ID of the key to be used to generate the ::NTP_MAC::digest.
+ NTP_KEY_ID key_id;
+
+ /// The message digest, usually 16 or 20 bytes, depending on key type.
+ uint8_t digest[MAX_NTP_DIGEST_BYTES];
+
+} NTP_MAC;
-#endif
+/**
+ * @brief An NTP packet including maximum sized MAC
+ */
typedef struct
{
- NTP_BASE_PACKET packet;
- #if MBG_MD5_AUTH
- NTP_AUTH_INFO auth_info;
- #endif
+ NTP_BASE_PACKET base; ///< The base NTP packet
+ NTP_MAC mac; ///< The variable length MAC, depending on used authentication
+
} NTP_PACKET;
+/**
+ * @brief An NTP packet including additional information
+ */
+typedef struct
+{
+ size_t len; ///< The actual length of the ::NTP_PACKET_INFO::packet
+ struct timespec tsr; ///< A time stamp (CLOCK_REALTIME) when packet has been sent or received
+ NTP_PACKET packet; ///< the packet to be sent, or which has been received
+
+} NTP_PACKET_INFO;
+
+
+
+
+/**
+ * @brief Return the length of an NTP packet's MAC
+ *
+ * @param[in] p The ::NTP_PACKET_INFO containing the packet and the actual packet length
+ *
+ * @return The actual length of the packet's ::NTP_MAC field
+ */
+static __mbg_inline /*HDR*/
+size_t get_mac_len( const NTP_PACKET_INFO *p )
+{
+ size_t mac_len = p->len - NTP_BASE_PACKET_SIZE;
+
+ // don't return negative values
+ return ( mac_len < 0 ) ? 0 : mac_len;
+
+} // get_mac_len
+
+
+
+/**
+ * @brief Return the length of an NTP packet's message digest
+ *
+ * @param[in] p The ::NTP_PACKET_INFO containing the packet and the actual packet length
+ *
+ * @return The actual length of the packet's message digest
+ */
+static __mbg_inline /*HDR*/
+size_t get_digest_len( const NTP_PACKET_INFO *p )
+{
+ size_t digest_len = get_mac_len( p ) - sizeof( NTP_KEY_ID );
+
+ // don't return negative values
+ return ( digest_len < 0 ) ? 0 : digest_len;
+
+} // get_mac_len
+
+
+
+/**
+ * @brief Check if an NTP packet has a MAC
+ *
+ * @param[in] p The ::NTP_PACKET_INFO containing the packet and the actual packet length
+ *
+ * @return != 0 if the packet has a MAC, else 0
+ */
+static __mbg_inline /*HDR*/
+int packet_has_mac( const NTP_PACKET_INFO *p )
+{
+ return get_mac_len( p ) >= sizeof( NTP_KEY_ID );
+
+} // packet_has_mac
+
+
+
+/**
+ * @brief Check if an NTP packet has a message digest
+ *
+ * @param[in] p The ::NTP_PACKET_INFO containing the packet and the actual packet length
+ *
+ * @return != 0 if the packet has a digest, else 0
+ */
+static __mbg_inline /*HDR*/
+int packet_has_digest( const NTP_PACKET_INFO *p )
+{
+ return get_mac_len( p ) > sizeof( NTP_KEY_ID );
+
+} // packet_has_digest
+
+
+
+/**
+ * @brief Convert an ::NTP_TSTAMP's byte order from net to host
+ *
+ * @param[in,out] t The time stamp top be converted
+ */
+static __mbg_inline /*HDR*/
+void ntoh_ntp_time( NTP_TSTAMP *t )
+{
+ t->seconds = ntohl( t->seconds );
+ t->fractions = ntohl( t->fractions );
+
+} // ntoh_ntp_time
+
+
+
+/**
+ * @brief Convert an ::NTP_PACKET's byte order from net to host
+ *
+ * @param[in,out] p The ::NTP_PACKET_INFO containing the packet to be converted, and the actual packet length
+ */
+static __mbg_inline /*HDR*/
+void ntoh_ntp_packet( NTP_PACKET_INFO *p )
+{
+ NTP_BASE_PACKET *pbp = &p->packet.base;
+
+ ntoh_ntp_time( &pbp->reference_time );
+ ntoh_ntp_time( &pbp->originate_time );
+ ntoh_ntp_time( &pbp->receive_time );
+ ntoh_ntp_time( &pbp->transmit_time );
+
+ pbp->root_delay = ntohl( pbp->root_delay );
+ pbp->root_dispersion = ntohl( pbp->root_dispersion );
+
+ if ( packet_has_mac( p ) )
+ {
+ p->packet.mac.key_id = ntohl( p->packet.mac.key_id );
+ // No need to convert the digest part, if available.
+ }
+
+} // ntoh_ntp_packet
+
+
+
+/**
+ * @brief Compute the difference of two time stamps in ::NTP_TSTAMP format
+ *
+ * @param[in] t The original time stamp
+ * @param[in] t_ref The time stamp to be subtracted
+ *
+ * @return The time difference, in seconds
+ */
+static __mbg_inline /*HDR*/
+double delta_tstamps( const NTP_TSTAMP *t,
+ const NTP_TSTAMP *t_ref )
+{
+ return ( (double) t->seconds - (double) t_ref->seconds )
+ + ( (double) t->fractions - (double) t_ref->fractions ) / NTP_FRAC_PER_SEC;
+
+} // delta_tstamps
+
+
+
/* function prototypes: */
#ifdef __cplusplus
diff --git a/mbglib/common/use_pack.h b/mbglib/common/use_pack.h
new file mode 100755
index 0000000..5edcdfe
--- /dev/null
+++ b/mbglib/common/use_pack.h
@@ -0,0 +1,43 @@
+
+/**************************************************************************
+ *
+ * $Id: use_pack.h 1.5 2012/10/12 12:40:01 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:01 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
index 5047f16..c298755 100755
--- a/mbglib/common/words.h
+++ b/mbglib/common/words.h
@@ -1,7 +1,7 @@
/**************************************************************************
*
- * $Id: words.h 1.32 2014/01/07 15:43:52 martin REL_M $
+ * $Id: words.h 1.34 2014/10/20 12:31:20 martin REL_M $
*
* Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
*
@@ -10,6 +10,12 @@
*
* -----------------------------------------------------------------------
* $Log: words.h $
+ * Revision 1.34 2014/10/20 12:31:20 martin
+ * Moved macro _isdigit() here.
+ * Revision 1.33 2014/05/27 10:18:35Z martin
+ * Finer control of which types are required for or already
+ * available on particular target systems.
+ * Added macros helpful to simplify declarations of code/name tables.
* Revision 1.32 2014/01/07 15:43:52 martin
* Define __mbg_inline for ARM firmware targets.
* Revision 1.31 2012/11/29 11:54:39Z martin
@@ -225,22 +231,50 @@
// Some commonly used types
-typedef unsigned char uchar;
+#if !defined( _UCHAR_DEFINED )
+ typedef unsigned char uchar;
+ #define uchar uchar
+#endif
-#if !defined( MBG_TGT_LINUX ) \
- && !( defined ( MBG_TGT_NETBSD ) \
- && defined ( MBG_TGT_KERNEL ) )
+#if !defined( _USHORT_DEFINED )
typedef unsigned short ushort;
+ #define ushort ushort
+#endif
+
+#if !defined( _UINT_DEFINED )
typedef unsigned int uint;
+ #define uint uint
+#endif
+
+#if !defined( _ULONG_DEFINED )
typedef unsigned long ulong;
+ #define ulong ulong
+#endif
+
+#if !defined( _UDOUBLE_DEFINED )
+ typedef double udouble;
+ #define udouble udouble
+#endif
+
+#if !defined( _BYTE_DEFINED )
+ typedef unsigned char byte;
+ #define byte byte
#endif
-typedef double udouble;
+#if !defined( _WORD_DEFINED )
+ typedef unsigned short word;
+ #define word word
+#endif
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long longword;
-typedef unsigned long dword;
+#if !defined( _LONGWORD_DEFINED )
+ typedef unsigned long longword;
+ #define longword longword
+#endif
+
+#if !defined( _DWORD_DEFINED )
+// typedef unsigned long dword;
+// #define dword dword
+#endif
#if !defined( _BIT_DEFINED )
@@ -253,6 +287,7 @@ typedef unsigned long dword;
( defined( __cplusplus ) || defined( __bool_true_false_are_defined ) )
typedef bool bit;
+ #define bit bit
#else // C99 types not supported
@@ -261,6 +296,7 @@ typedef unsigned long dword;
// yield unexpected results for code like:
// return (bit) ( val & 0x10 );
typedef int bit;
+ #define bit bit
#endif
@@ -269,17 +305,17 @@ typedef unsigned long dword;
#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 BYTE_0( _x ) ( (uint8_t ) ( (_x) & 0xFF ) )
+#define BYTE_1( _x ) ( (uint8_t ) ( ( ( (uint16_t) (_x) ) >> 8 ) & 0xFF ) )
+#define BYTE_2( _x ) ( (uint8_t ) ( ( ( (uint32_t) (_x) ) >> 16 ) & 0xFF ) )
+#define BYTE_3( _x ) ( (uint8_t ) ( ( ( (uint32_t) (_x) ) >> 24 ) & 0xFF ) )
-#define HI_BYTE( _x ) ( (_x) >> 8 )
-#define LO_BYTE( _x ) ( (_x) & 0xFF )
+#define HI_BYTE( _x ) ( (uint8_t ) ( (_x) >> 8 ) )
+#define LO_BYTE( _x ) ( (uint8_t ) ( (_x) & 0xFF ) )
-#define HI_WORD( _x ) ( (_x) >> 16 )
-#define LO_WORD( _x ) ( (_x) & 0xFFFF )
+#define HI_WORD( _x ) ( (uint16_t ) ( (_x) >> 16 ) )
+#define LO_WORD( _x ) ( (uint16_t ) ( (_x) & 0xFFFF ) )
// the macros below assume little endianess
// these macros expect the name of a variable
@@ -336,6 +372,9 @@ typedef unsigned long dword;
#endif
+#define _isdigit( _c ) ( (_c) >= '0' && (_c) <= '9' )
+
+
// 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
@@ -354,6 +393,21 @@ typedef struct
const char *name;
} MBG_CODE_NAME_TABLE_ENTRY;
+/**
+ * @brief A macro defining a ::MBG_CODE_NAME_TABLE_ENTRY
+ *
+ * The stringified parameter is used for the name.
+ *
+ * @param _n The symbolic name of the numeric code
+ */
+#define _mbg_cn_table_entry( _n ) { _n, #_n }
+
+/**
+ * @brief A macro defining an empty ::MBG_CODE_NAME_TABLE_ENTRY
+ *
+ * This is used to terminate a table.
+ */
+#define _mbg_cn_table_end() { 0, NULL }
/* End of header body */
diff --git a/ntptest.c b/ntptest.c
index 1066b08..7f1dfbe 100755
--- a/ntptest.c
+++ b/ntptest.c
@@ -1,7 +1,7 @@
/**************************************************************************
*
- * $Id: ntptest.c 1.1 2014/04/01 13:02:21 martin REL_M $
+ * $Id: ntptest.c 1.4 2015/05/11 11:12:51 martin REL_M $
*
* Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
*
@@ -12,6 +12,12 @@
*
* -----------------------------------------------------------------------
* $Log: ntptest.c $
+ * Revision 1.4 2015/05/11 11:12:51 martin
+ * Support continuous monitoring (-Z), e.g. for leap second tests.
+ * Revision 1.3 2015/02/27 13:10:31 martin
+ * Fixed a bug where the xmt/rcv packets were interchanged when printed.
+ * Revision 1.2 2014/09/16 15:54:09 martin
+ * Account for updated library files.
* Revision 1.1 2014/04/01 13:02:21 martin
* Initial revision.
*
@@ -31,8 +37,8 @@
static const char program_name[] = "ntptest";
-static const char program_version[] = "v1.0";
-static const char program_copyright[] = "(c) Meinberg 2014";
+static const char program_version[] = "v1.1";
+static const char program_copyright[] = "(c) Meinberg 2014-2015";
static const char program_contact[] = "contact: <martin.burnicki@meinberg.de>";
@@ -43,10 +49,13 @@ static const char program_contact[] = "contact: <martin.burnicki@meinberg.de>";
// parameters which can to some extent be modified via command
// line options to control the program's behaviour
-static int run_continuously; // -c
+static int run_continuously; // -c, -Z
static int sleep_intv = 1; // -s, [sec], sleep interval between requests, default 1
+static int usleep_intv; // -u, -Z [usec], sleep interval between requests
static int prot_version; // -V, protocol version to be used
static unsigned long rcv_timeout; // -T, [msec] receive timeout after request sent
+static int verbose; // -v print full packet details
+static int compensate_initial_offset; // -Z, compensate initial time offset to server
static const char *tgt_host; // target hostname or IP address
static struct sockaddr_in tgt_addr; // target address
@@ -84,14 +93,9 @@ void do_ntp_queries( void )
{
fd_set read_set;
struct timeval tv_timeout;
- struct timespec tsr_req; // time stamp when request was sent
- struct timespec tsr_rcv; // time stamp when response arrived
- NTP_TSTAMP t_req_ntp; // tv_req converted to NTP format
- NTP_PACKET ntp_req_packet; // set up from template
- NTP_PACKET rcv_buffer;
- void *req_packet;
- int req_packet_size;
- ssize_t rcv_packet_size;
+ NTP_PACKET_INFO req_info; // set up from template
+ NTP_PACKET_INFO reply_info;
+ NTP_RESULTS rslt;
int sockfd;
int rc;
struct sockaddr_in si_src;
@@ -107,23 +111,23 @@ void do_ntp_queries( void )
}
- ntp_req_packet = default_ntp_req_packet;
+ req_info.packet = default_ntp_req_packet;
for (;;)
{
// get time stamp when request packet was sent
- clock_gettime( CLOCK_REALTIME, &tsr_req );
+ clock_gettime( CLOCK_REALTIME, &req_info.tsr );
- timespec_to_ntp_tstamp( &t_req_ntp, &tsr_req );
+ // convert to NTP format and save in request packet
+ timespec_to_ntp_tstamp( &req_info.packet.base.transmit_time, &req_info.tsr );
+ ntoh_ntp_time( &req_info.packet.base.transmit_time );
- ntp_req_packet.packet.transmit_time = t_req_ntp;
- ntoh_ntp_time( &ntp_req_packet.packet.transmit_time );
-
- req_packet = &ntp_req_packet;
- req_packet_size = sizeof( ntp_req_packet );
+ // message authentication not yet supported, so only the base
+ // packet is sent
+ req_info.len = NTP_BASE_PACKET_SIZE;
// send request packet
- if ( sendto( sockfd, req_packet, req_packet_size, 0,
+ if ( sendto( sockfd, &req_info.packet, req_info.len, 0,
(__const__ struct sockaddr *) &tgt_addr,
sizeof( tgt_addr ) ) < 0 )
{
@@ -156,25 +160,59 @@ void do_ntp_queries( void )
// read response packet
slen_src = sizeof( si_src ) ;
- rcv_packet_size = recvfrom( sockfd, &rcv_buffer, sizeof( rcv_buffer ), 0,
+ reply_info.len = recvfrom( sockfd, &reply_info.packet, sizeof( reply_info.packet ), 0,
(struct sockaddr *) &si_src, &slen_src );
- if ( rcv_packet_size < 0 )
+ if ( reply_info.len < 0 )
{
mbglog( LOG_ERR, "Failed to receive from UDP socket in %s: %s", __func__, strerror( errno ) );
continue;
}
// get time stamp when response was received
- clock_gettime( CLOCK_REALTIME, &tsr_rcv );
+ clock_gettime( CLOCK_REALTIME, &reply_info.tsr );
+
+ eval_ntp_packet( &rslt, &reply_info, &glb_query_stats );
+ ntoh_ntp_packet( &req_info );
+
+ if ( verbose )
+ print_ntp_results( &rslt, &req_info, &reply_info, &glb_query_stats, 1, 1 );
+ else
+ {
+ static double initial_delta_t;
+ static int has_been_called;
+
+ NTP_PACKET *p = &reply_info.packet;
- rc = eval_ntp_packet( &rcv_buffer, &ntp_req_packet, &tsr_rcv,
- &tsr_req, &t_req_ntp, &glb_query_stats );
+ print_ntp_time( "", &p->base.transmit_time, NULL, 1 );
+
+ if ( !has_been_called )
+ {
+ // Compute and save the initial delta t.
+ // The system time when the packet has been received is
+ // available in tv_rcv and t_rcv.
+
+ initial_delta_t = delta_tstamps( &p->base.transmit_time, &rslt.t_rcv );
+ has_been_called = 1;
+ }
+
+ if ( compensate_initial_offset )
+ rslt.ntp_offs -= initial_delta_t;
+
+ printf( ", st %u, leap %u, offs[ms]: %+.3f\n",
+ p->base.flags.stratum,
+ p->base.flags.leap_ind,
+ rslt.ntp_offs * 1000 );
+ fflush( NULL );
+ }
if ( !run_continuously )
break;
- sleep( sleep_intv );
+ if ( usleep_intv )
+ usleep( usleep_intv );
+ else
+ sleep( sleep_intv );
}
close( sockfd );
@@ -194,11 +232,14 @@ void usage( void )
"and evaluate the results.\n" );
printf( "\n" );
printf( "[OPTION] can be one of the following:\n" );
- printf( " -c run continuously\n" );
+ printf( " -c run continuously, print summary output unless verbose\n" );
printf( " -s n n seconds delay between queries, default: %i s\n", sleep_intv );
+ printf( " -v verbose, print full packets even in continuous mode\n" );
printf( " -V n NTP protocol version, %i..%i, default: %i\n",
MIN_REQ_NTP_VERSION, MAX_REQ_NTP_VERSION, DEFAULT_REQ_NTP_VERSION );
printf( " -T n packet receive timeout [ms], default: %u\n", RCV_TIMEOUT );
+ printf( " -Z send 4 req/s to server, print time, offset changes and status summary,\n" );
+ printf( " e.g. for leap second tests\n" );
printf( " -?, -h print this usage information\n"
"\n" );
@@ -211,7 +252,7 @@ void check_options( int argc, char *argv[] )
{
char c;
- while ( ( c = getopt( argc, argv, "cs:V:T:h?" ) ) != -1 )
+ while ( ( c = getopt( argc, argv, "cs:vV:T:Zh?" ) ) != -1 )
{
switch ( c )
{
@@ -229,6 +270,11 @@ void check_options( int argc, char *argv[] )
break;
+ case 'v':
+ verbose++;
+ break;
+
+
case 'V':
prot_version = strtol( optarg, NULL, 10 );
break;
@@ -238,6 +284,15 @@ void check_options( int argc, char *argv[] )
rcv_timeout = strtoul( optarg, NULL, 10 );
break;
+
+ case 'Z': // quick settings for leap second test
+ run_continuously = 1;
+ usleep_intv = 250000L; // 4 req/s
+ verbose = 0;
+ compensate_initial_offset = 1;
+ break;
+
+
case 'h':
case '?':
default:
@@ -258,6 +313,9 @@ int main( int argc, char *argv[] )
check_options( argc, argv );
+ if ( !run_continuously )
+ verbose = 1;
+
if ( rcv_timeout == 0 )
rcv_timeout = RCV_TIMEOUT;