From 50a3df765f20c6ea5adfa5af266f80b0d3dabd34 Mon Sep 17 00:00:00 2001 From: Martin Burnicki Date: Sat, 25 Jul 2015 13:00:00 +0200 Subject: Severe API changes. All device 'open' functions and the device close function now expect the address of an (MBG_MSG_CTL *). the 'open' functions allocate a structure and set it up, and the close function frees the allocated memory and sets the (MBG_MSG_CTL *) to NULL. The MBG_MSG_CTL structure should be considered opaque, just like a (FILE *). API functions now return common, portable MBG_ERR_... codes instead of TR_COMPLETE and friends to allow for common error handling. Support new XBP addressing for potential sub-devices. mbgextio_setup_receiver_info() sets up a RECEIVER_INFO structure for legacy devices, so it is used in favour of mbgextio_get_receiver_info() Preliminary function gpsxmple::set_date_time(). Source code in gpsxmple.c still needs cleanup. --- gpsxmple.c | 813 +++- mbglib/common/aes128.c | 77 +- mbglib/common/aes128.h | 8 +- mbglib/common/cfg_hlp.h | 431 ++ mbglib/common/extiohlp.c | 275 ++ mbglib/common/extiohlp.h | 158 + mbglib/common/gpsdefs.h | 11529 +++++++++++++++++++++++++++++++++++++-------- mbglib/common/gpsserio.c | 613 ++- mbglib/common/gpsserio.h | 1225 +++-- mbglib/common/gpsutils.c | 143 +- mbglib/common/gpsutils.h | 23 +- mbglib/common/mbg_arch.h | 181 + mbglib/common/mbg_tgt.h | 360 +- mbglib/common/mbg_tmo.h | 80 +- mbglib/common/mbgerror.c | 413 ++ mbglib/common/mbgerror.h | 326 ++ mbglib/common/mbgextio.c | 5613 +++++++++++++++++++--- mbglib/common/mbgextio.h | 2105 ++++++++- mbglib/common/mbggeo.h | 14 +- mbglib/common/mbgmutex.h | 67 +- mbglib/common/mbgserio.c | 929 +++- mbglib/common/mbgserio.h | 114 +- mbglib/common/pcpsdefs.h | 1936 +++++--- mbglib/common/use_pack.h | 6 +- mbglib/common/words.h | 312 +- unix/Makefile | 43 +- 26 files changed, 23127 insertions(+), 4667 deletions(-) create mode 100644 mbglib/common/cfg_hlp.h create mode 100644 mbglib/common/extiohlp.c create mode 100644 mbglib/common/extiohlp.h create mode 100644 mbglib/common/mbg_arch.h create mode 100644 mbglib/common/mbgerror.c create mode 100644 mbglib/common/mbgerror.h diff --git a/gpsxmple.c b/gpsxmple.c index 08ec1dd..30e70e3 100644 --- a/gpsxmple.c +++ b/gpsxmple.c @@ -1,14 +1,14 @@ /************************************************************************** * - * $Id: gpsxmple.c 1.8 2011/04/15 13:04:14 martin REL_M $ - * $Name: GPSXMPLE_2_3 $ + * $Id: gpsxmple.c 1.10.1.8 2015/07/25 15:28:12 martin TEST $ + * $Name: $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: * Sample program demonstrating how to access Meinberg devices - * using the binary data protocol. + * using the serial binary data protocol. * * Depending on the target operating system this program works * either via serial port (the default) or via a network socket @@ -32,6 +32,26 @@ * * ----------------------------------------------------------------------- * $Log: gpsxmple.c $ + * Revision 1.10.1.8 2015/07/25 15:28:12 martin + * Revision 1.10.1.7 2015/07/24 13:47:32Z martin + * Revision 1.10.1.6 2015/07/14 13:01:02 martin + * Revision 1.10.1.5 2014/11/04 11:32:25 martin + * Started to support XBP addressing. + * Revision 1.10.1.4 2014/10/30 13:49:38 martin + * Revision 1.10.1.3 2013/02/01 16:11:59 martin + * Revision 1.10.1.2 2012/03/13 16:27:44 martin + * Revision 1.10.1.1 2012/03/13 11:48:35Z martin + * Revision 1.10 2012/01/12 09:57:04 martin + * Support selection of SCU port. + * Preliminary code to send PCPS_TIME via binary protocol. + * Debug code to test TX flushing problems under Windows. + * GPSXMPLE code disabled by default to build mbgevlog. + * Revision 1.9 2011/12/15 14:35:49Z martin + * Started to migrate to opaque stuctures. + * Made more functions static. + * Added code to show / clear GPS event log. + * Used this module for the mbgevlog program and disabled + * some GPSXMPLE code using preprocessor symbol. * Revision 1.8 2011/04/15 13:04:14 martin * Optionally poll for user capture events. * Under Unix catch signals to terminate properly. @@ -45,7 +65,7 @@ * Optionally loop and wait for automatic messages. * Revision 1.6 2006/10/25 12:31:54Z martin * Support serial I/O under Windows. - * Check return codes of API functions and print associated + * Check return codes of API functions and print associated * messages in case of error. * Revision 1.5 2006/08/24 13:36:38Z martin * Conditional support for network socket I/O. @@ -62,7 +82,9 @@ **************************************************************************/ #include +#include #include +#include #include #include @@ -82,16 +104,13 @@ #endif +const char pname[] = "gpsxmple"; +const char pversion[] = "2.5"; +const char pdescr[] = "Example Program Accessing a Meinberg Device via Binary Protocol"; -// the variables below are required for communication -MBG_MSG_BUFF rbuff; -MBG_MSG_BUFF tbuff; -MBG_MSG_CTL mctl = -{ - { &rbuff, sizeof( rbuff ) }, - { &tbuff, sizeof( tbuff ) } -}; +// the variables below are required for communication +MBG_MSG_CTL *pmctlx; // Define the minimum number of some resource types @@ -101,9 +120,11 @@ MBG_MSG_CTL mctl = // Define the maximum number of some resource types // supported by the software #define N_COM_MAX 4 // max. number of COM ports -#define N_STR_TYPE_MAX 20 // max. number of string types +// #define N_STR_TYPE_MAX 20 // max. number of string types #define N_POUT_MAX 3 // max. number of programmable outputs +#define N_SCU_PORT 2 + #define IDLE_SLEEP_MS 200 @@ -124,8 +145,14 @@ MBG_MSG_CTL mctl = static const char *target; static int is_socket; static int must_force_connection; + +static const char *str_new_date; +static const char *str_new_time; + static int must_send_auto; static int must_poll_ucap; + +static int must_clear_event_log; static RECEIVER_INFO receiver_info; static const char *feature_names[] = DEFAULT_GPS_FEATURE_NAMES; @@ -144,6 +171,8 @@ static const char *default_target = DEFAULT_DEV_NAME; #if _USE_SOCKET_IO static const char *password; + static int scu_port; + static int must_set_scu_port; #endif @@ -155,6 +184,84 @@ static const char *dow_str[] = +#if defined( DEBUG ) + +static /*HDR*/ +void print_original_serial_settings( FILE *fp, SERIAL_IO_STATUS *p ) +{ + #if defined( MBG_TGT_WIN32 ) + DCB *dcb = &p->old_dcb; + COMMTIMEOUTS *tmo = &p->old_commtimeouts; + COMMPROP *prop = &p->comm_prop; + + fprintf( fp, "Comm Properties:\n" ); + fprintf( fp, " wPacketLength: %u\n", prop->wPacketLength ); + fprintf( fp, " wPacketVersion: %u\n", prop->wPacketVersion ); + fprintf( fp, " dwServiceMask: %u (%u)\n", prop->dwServiceMask, SP_SERIALCOMM ); + fprintf( fp, " dwReserved1: %u\n", prop->dwReserved1 ); + fprintf( fp, " dwMaxTxQueue: %u\n", prop->dwMaxTxQueue ); + fprintf( fp, " dwMaxRxQueue: %u\n", prop->dwMaxRxQueue ); + fprintf( fp, " dwMaxBaud: %u\n", prop->dwMaxBaud ); + fprintf( fp, " dwProvSubType: %u\n", prop->dwProvSubType ); + fprintf( fp, " dwProvCapabilities: %u\n", prop->dwProvCapabilities ); + fprintf( fp, " dwSettableParams: 0x%2X\n", prop->dwSettableParams ); + fprintf( fp, " dwSettableBaud: 0x%2X\n", prop->dwSettableBaud ); + fprintf( fp, " wSettableData: 0x%2X\n", prop->wSettableData ); + fprintf( fp, " wSettableStopParity: 0x%2X\n", prop->wSettableStopParity ); + fprintf( fp, " dwCurrentTxQueue: %u\n", prop->dwCurrentTxQueue ); + fprintf( fp, " dwCurrentRxQueue: %u\n", prop->dwCurrentRxQueue ); + fprintf( fp, " dwProvSpec1: %u\n", prop->dwProvSpec1 ); + fprintf( fp, " dwProvSpec2: %u\n", prop->dwProvSpec2 ); + // fprintf( fp, " wcProvChar: %c\n", prop->wcProvChar[0] ); // wchar!! + fprintf( fp, "\n" ); + + fprintf( fp, "Original serial DCB settings:\n" ); + fprintf( fp, " DCBlength: %u\n", dcb->DCBlength ); + fprintf( fp, " BaudRate: %u\n", dcb->BaudRate ); + fprintf( fp, " fBinary: %u\n", dcb->fBinary ); + fprintf( fp, " fParity: %u\n", dcb->fParity ); + fprintf( fp, " fOutxCtsFlow: %u\n", dcb->fOutxCtsFlow ); + fprintf( fp, " fOutxDsrFlow: %u\n", dcb->fOutxDsrFlow ); + fprintf( fp, " fDtrControl: %u\n", dcb->fDtrControl ); + fprintf( fp, " fDsrSensitivity: %u\n", dcb->fDsrSensitivity ); + fprintf( fp, " fTXContinueOnXoff: %u\n", dcb->fTXContinueOnXoff ); + fprintf( fp, " fOutX: %u\n", dcb->fOutX ); + fprintf( fp, " fInX: %u\n", dcb->fInX ); + fprintf( fp, " fErrorChar: %u\n", dcb->fErrorChar ); + fprintf( fp, " fNull: %u\n", dcb->fNull ); + fprintf( fp, " fRtsControl: %u\n", dcb->fRtsControl ); + fprintf( fp, " fAbortOnError: %u\n", dcb->fAbortOnError ); + fprintf( fp, " fDummy2: %u\n", dcb->fDummy2 ); + fprintf( fp, " wReserved: %u\n", dcb->wReserved ); + fprintf( fp, " XonLim: %u\n", dcb->XonLim ); + fprintf( fp, " XoffLim: %u\n", dcb->XoffLim ); + fprintf( fp, " ByteSize: %u\n", dcb->ByteSize ); + fprintf( fp, " Parity: %u\n", dcb->Parity ); + fprintf( fp, " StopBits: %u\n", dcb->StopBits ); + fprintf( fp, " XonChar: %u\n", dcb->XonChar ); + fprintf( fp, " XoffChar: %u\n", dcb->XoffChar ); + fprintf( fp, " ErrorChar: %u\n", dcb->ErrorChar ); + fprintf( fp, " EofChar: %u\n", dcb->EofChar ); + fprintf( fp, " EvtChar: %u\n", dcb->EvtChar ); + fprintf( fp, " wReserved1: %u\n", dcb->wReserved1 ); + fprintf( fp, "\n" ); + + fprintf( fp, "Original serial comm timeout settings:\n" ); + fprintf( fp, " ReadIntervalTimeout: %u\n", tmo->ReadIntervalTimeout ); + fprintf( fp, " ReadTotalTimeoutMultiplier: %u\n", tmo->ReadTotalTimeoutMultiplier ); + fprintf( fp, " ReadTotalTimeoutConstant: %u\n", tmo->ReadTotalTimeoutConstant ); + fprintf( fp, " WriteTotalTimeoutMultiplier: %u\n", tmo->WriteTotalTimeoutMultiplier ); + fprintf( fp, " WriteTotalTimeoutConstant: %u\n", tmo->WriteTotalTimeoutConstant ); + fprintf( fp, "\n" ); + + #endif + +} // print_original_serial_settings + +#endif // defined( DEBUG ) + + + static /*HDR*/ void mbg_sleep_msec( long msec ) { @@ -163,13 +270,35 @@ void mbg_sleep_msec( long msec ) #elif defined( MBG_TGT_WIN32 ) Sleep( msec ); #elif defined( MBG_TGT_DOS ) - delay( msec ); + delay( (unsigned int) msec ); #endif } // mbg_sleep_msec +static /*HDR*/ +int set_scu_port( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, int port ) +{ + // Yet this is preliminary/untested. + SCU_STAT_SETTINGS scu_stat_settings = { 0 }; + int rc; + + scu_stat_settings.epld_control_mask = MSK_EPLD_CNTL_ENA_SNMP | MSK_EPLD_CNTL_SEL_SNMP; + + scu_stat_settings.epld_control_value = MSK_EPLD_CNTL_ENA_SNMP; + + if ( port ) // else leave 0 + scu_stat_settings.epld_control_value |= MSK_EPLD_CNTL_SEL_SNMP; + + rc = mbgextio_xmt_msg( pmctl, p_addr, GPS_SCU_STAT, &scu_stat_settings, sizeof( scu_stat_settings ) ); + + return rc; + +} // set_scu_port + + + static /*HDR*/ int check_rc( int rc ) { @@ -180,43 +309,31 @@ int check_rc( int rc ) switch ( rc ) { - case TR_COMPLETE: + case MBG_SUCCESS: cp = "Data received completely."; break; - case TR_RECEIVING: - cp = "Received data not complete."; - break; - - case TR_WAITING: - cp = "Waiting for data."; - break; - - case TR_TIMEOUT: + case MBG_ERR_TIMEOUT: cp = "Timeout receiving data"; break; - case TR_CSUM_HDR: + case MBG_ERR_HDR_CSUM: cp = "Header checksum error in received data."; break; - case TR_CSUM_DATA: + case MBG_ERR_DATA_CSUM: cp = "Data checksum error in received data."; break; - case TR_DECRYPTION: + case MBG_ERR_DECRYPT: cp = "Failed to decrypt received data."; break; - case TR_OPEN_ERR: - cp = "Failed to establish connection."; - break; - - case TR_IO_ERR: + case MBG_ERR_IO: cp = "I/O error receiving data"; break; - case TR_AUTH_ERR: + case MBG_ERR_AUTH: cp = "Authentication error"; break; @@ -233,7 +350,7 @@ int check_rc( int rc ) -/*HDR*/ +static /*HDR*/ void sprint_tm( char *s, TM_GPS *tm, int print_frac ) { int n = 0; @@ -258,7 +375,7 @@ void sprint_tm( char *s, TM_GPS *tm, int print_frac ) -/*HDR*/ +static /*HDR*/ void sprint_lla( char *s, LLA lla ) { static const double r2d = 180 / PI; @@ -273,7 +390,7 @@ void sprint_lla( char *s, LLA lla ) -/*HDR*/ +static /*HDR*/ void print_stat_info( STAT_INFO *p ) { const char *cp; @@ -304,7 +421,7 @@ void print_stat_info( STAT_INFO *p ) -/*HDR*/ +static /*HDR*/ void print_time( TTM *p ) { static const char *s[] = @@ -333,7 +450,7 @@ void check_receiver_info( RECEIVER_INFO *p, int log ) const char *fmt_min = "Number of %s from device (%u) is less than number required (%u)"; const char *fmt_max = "Number of %s from device (%u) exceeds number supported by the software (%u)"; - // Check if numbers of resources provided by the device + // Check if numbers of resources provided by the device // don't exceed numbers of resources supported by the software #define _check_min( _n, _min, _info ) \ @@ -373,15 +490,15 @@ void check_receiver_info( RECEIVER_INFO *p, int log ) _check_min( p->n_com_ports, N_COM_MIN, "COM ports" ); _check_max( p->n_com_ports, N_COM_MAX, "COM ports" ); - _check_max( p->n_str_type, N_STR_TYPE_MAX, "string types" ); + _check_max( p->n_str_type, MAX_PARM_PORT, "string types" ); _check_max( p->n_prg_out, N_POUT_MAX, "progr. outputs" ); } // check_receiver_info -/*HDR*/ -int get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) +static /*HDR*/ +int get_receiver_info( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, RECEIVER_INFO *p ) { int rc; int i; @@ -389,13 +506,13 @@ int get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) printf( fmt, "Receiver info:" ); - rc = mbgextio_get_receiver_info( &mctl, p ); + rc = mbgextio_setup_receiver_info( pmctl, p_addr, p ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); - if ( rc == TR_TIMEOUT ) + if ( rc == MBG_ERR_TIMEOUT ) { printf( "If you are using a very old GPS model then reading the\n" "receiver info structure may not be supported.\n" ); @@ -457,17 +574,17 @@ int get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) -/*HDR*/ -void show_sw_rev( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_sw_rev( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { SW_REV sw_rev; int rc; printf( fmt, "Software Revision:" ); - rc = mbgextio_get_sw_rev( pmctl, &sw_rev ); + rc = mbgextio_get_sw_rev( pmctl, p_addr, &sw_rev ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -483,17 +600,17 @@ void show_sw_rev( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void show_bvar_stat( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_bvar_stat( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { BVAR_STAT bvar_stat; int rc; printf( fmt, "BVAR status:" ); - rc = mbgextio_get_bvar_stat( pmctl, &bvar_stat ); + rc = mbgextio_get_bvar_stat( pmctl, p_addr, &bvar_stat ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -505,17 +622,17 @@ void show_bvar_stat( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void show_stat_info( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_stat_info( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { STAT_INFO stat_info; int rc; printf( fmt, "Receiver status:" ); - rc = mbgextio_get_stat_info( pmctl, &stat_info ); + rc = mbgextio_get_stat_info( pmctl, p_addr, &stat_info ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -527,17 +644,17 @@ void show_stat_info( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void show_pos( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_pos( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { LLA lla; // Position as logitude, latitude, altitude int rc; printf( fmt, "Receiver Position:" ); - rc = mbgextio_get_pos_lla( pmctl, lla ); + rc = mbgextio_get_pos_lla( pmctl, p_addr, lla ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -550,17 +667,17 @@ void show_pos( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void show_tzdl( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_tzdl( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { TZDL tzdl; int rc; printf( fmt, "Time Zone:" ); - rc = mbgextio_get_tzdl( pmctl, &tzdl ); + rc = mbgextio_get_tzdl( pmctl, p_addr, &tzdl ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -603,8 +720,8 @@ void show_tzdl( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void show_synth( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_synth( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { SYNTH synth; double f; @@ -612,9 +729,9 @@ void show_synth( MBG_MSG_CTL *pmctl ) printf( fmt, "Synthesizer:" ); - rc = mbgextio_get_synth( pmctl, &synth ); + rc = mbgextio_get_synth( pmctl, p_addr, &synth ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -629,7 +746,7 @@ void show_synth( MBG_MSG_CTL *pmctl ) if ( synth.range == 0 ) { - // freq field is in 0.1 Hz units, so if + // freq field is in 0.1 Hz units, so if // the range is 0 we must divide by 10 // to yield the correct result f = (double) synth.freq / 10.0; @@ -656,8 +773,8 @@ void show_synth( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void set_synth( void ) +static /*HDR*/ +void set_synth( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { SYNTH synth = { 0 }; int rc; @@ -673,10 +790,10 @@ void set_synth( void ) // The effective frequency is: (freq/10)*(10^^range) synth.freq = 1000; // base frequency value in 1/10 Hz Units - synth.range = 1; // multiplier 10^^range + synth.range = 1; // multiplier 10^^range synth.phase = 1800; // phase in 1/10 degrees - rc = mbgextio_set_synth( &mctl, &synth ); + rc = mbgextio_set_synth( pmctl, p_addr, &synth ); if ( rc < 0 ) printf( "Failed to set synthesizer output, code: %i\n", rc ); @@ -689,8 +806,8 @@ void set_synth( void ) // set programmable output mode -/*HDR*/ -void set_pout_mode( void ) +static /*HDR*/ +void set_pout_mode( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { POUT_INFO_IDX pout_info_idx; POUT_SETTINGS pout_settings = { 0 }; // new settings, init'd to 0 @@ -712,12 +829,12 @@ void set_pout_mode( void ) return; } - // OK, now get the current settings, and see which modes are + // OK, now get the current settings, and see which modes are // supported by the selected programmable pulse output. - rc = mbgextio_get_pout_info_idx( &mctl, &pout_info_idx, pout_idx ); + rc = mbgextio_get_pout_info_idx( pmctl, p_addr, &pout_info_idx, pout_idx ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -740,9 +857,9 @@ void set_pout_mode( void ) pout_settings.tm[0].on.t.hour = 0; pout_settings.tm[0].on.t.min = 20; pout_settings.tm[0].on.t.sec = 0; - pout_settings.pulse_len = 30; // 10 millisecond units +// pout_settings.pulse_len = 30; // 10 millisecond units - rc = mbgextio_set_pout_settings_idx( &mctl, &pout_settings, pout_idx ); + rc = mbgextio_set_pout_settings_idx( pmctl, p_addr, &pout_settings, pout_idx ); if ( rc < 0 ) printf( "Failed to set programmable pulse output mode, code: %i\n", rc ); @@ -753,7 +870,9 @@ void set_pout_mode( void ) -/*HDR*/ +#if 0 //##++++++++++++++++ + +static /*HDR*/ void show_port_parm( MBG_MSG_CTL *pmctl ) { PORT_PARM port_parm; @@ -763,7 +882,7 @@ void show_port_parm( MBG_MSG_CTL *pmctl ) rc = mbgextio_get_port_parm( pmctl, &port_parm ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -795,75 +914,45 @@ void show_port_parm( MBG_MSG_CTL *pmctl ) } /* show_port_parm */ +#endif + -/*HDR*/ -void show_port_settings( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_port_settings( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { const char *mode_names[N_STR_MODE] = DEFAULT_ENG_MODE_NAMES; - STR_TYPE_INFO sti[N_STR_TYPE_MAX]; - STR_TYPE_INFO_IDX stii; - PORT_INFO_IDX pii; - PORT_SETTINGS *p; + RECEIVER_PORT_CFG rpcfg; int rc; int i; printf( fmt, "Serial ports:" ); - if ( receiver_info.model_code == GPS_MODEL_UNKNOWN ) + rc = mbgextio_get_serial_settings( pmctl, p_addr, &rpcfg, &receiver_info ); + + if ( rc != MBG_SUCCESS ) { - // This may be an old GPS model which does not provide - // a receiver info structure. - show_port_parm( pmctl ); + check_rc( rc ); return; } + // The number of serial ports and time string formats supported // by this device is specified in the receiver info structure. - // Read time string information +#if 0 //##++ TODO: possibly print supported string types for ( i = 0; i < receiver_info.n_str_type; i++ ) { - rc = mbgextio_get_str_type_info_idx( pmctl, &stii, (uint16_t) i ); - - if ( rc != TR_COMPLETE ) - { - check_rc( rc ); - return; - } - - if ( stii.idx != i ) - { - printf( "** Info for string type %i requested, but for %i received.\n", - stii.idx, i ); - return; - } - sti[i] = stii.str_type_info; } +#endif - - // Read and print port settings + // print port settings for ( i = 0; ; ) { - rc = mbgextio_get_port_info_idx( pmctl, &pii, (uint16_t) i ); - - if ( rc != TR_COMPLETE ) - { - check_rc( rc ); - return; - } - - if ( pii.idx != i ) - { - printf( "** Info for port %i requested, but for %i received.\n", - pii.idx, i ); - return; - } - - p = &pii.port_info.port_settings; + PORT_SETTINGS *p = &rpcfg.pii[i].port_info.port_settings; printf( "COM%i: %5lu Baud, %s", i, @@ -874,13 +963,13 @@ void show_port_settings( MBG_MSG_CTL *pmctl ) // Make sure indices received from the device do not exceed // maximum numbers supported by this program. - if ( p->str_type >= N_STR_TYPE_MAX ) + if ( p->str_type >= MAX_PARM_STR_TYPE ) printf( " (string type exceeds max)" ); else if ( p->mode >= N_STR_MODE ) printf( " (string mode exceeds max)" ); else - printf( ", \"%s\" string %s", sti[p->str_type].long_name, mode_names[p->mode] ); + printf( ", \"%s\" string %s", rpcfg.stii[p->str_type].str_type_info.long_name, mode_names[p->mode] ); printf( "\n" ); @@ -894,8 +983,68 @@ void show_port_settings( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_event_log( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) +{ + static const char *evt_id_names[N_MBG_EVT_ID] = MBG_EVT_ID_NAMES_ENG; + + MBG_NUM_EVT_LOG_ENTRIES log_entries; + MBG_EVT_LOG_ENTRY evt_log_entry; + time_t t; + struct tm *mytime; + int n_evt = 0; + int event_id = -1; + + if ( mbgextio_get_num_evt_log_entries( pmctl, p_addr, &log_entries ) ) + printf( "\nEvent Log (%i/%i entries used):\n", log_entries.used, log_entries.max ); + else + { + printf( "Failed to read event log entries\n" ); + return; + } + + if ( mbgextio_get_first_evt_log_entry( pmctl, p_addr, &evt_log_entry ) ) + { + unsigned int i; + + for ( i = 0; i < log_entries.max; i++ ) + { + event_id = _mbg_get_evt_id( evt_log_entry.code ); + + if ( event_id == 0 ) + break; + + n_evt++; + + t = evt_log_entry.time; + mytime = gmtime( &t ); + + printf( "%04i-%02i-%02i %02i:%02i:%02i ", + mytime->tm_year + 1900, mytime->tm_mon + 1, mytime->tm_mday, + mytime->tm_hour, mytime->tm_min, mytime->tm_sec ); + + if ( event_id < N_MBG_EVT_ID ) + printf( "%s\n", evt_id_names[event_id] ); + else + printf( "Unknown event ID %u", event_id ); + + mbgextio_get_next_evt_log_entry( pmctl, p_addr, &evt_log_entry ); + } + } + else + fprintf( stderr, "** ERROR: failed to read event log\n" ); + + if ( n_evt == 0 ) + fprintf( stderr, "event log is empty\n" ); + + printf( "\n" ); + +} // show_event_log + + + /*HDR*/ static -int check_ucap_poll( void ) +int check_ucap_poll( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { int rc; @@ -906,9 +1055,9 @@ int check_ucap_poll( void ) { TTM ttm; memset( &ttm, 0, sizeof( ttm ) ); - rc = mbgextio_get_ucap( &mctl, &ttm ); + rc = mbgextio_get_ucap( pmctl, p_addr, &ttm ); - if ( _ttm_time_is_avail( &ttm ) ) + if ( ( rc == MBG_SUCCESS ) && _ttm_time_is_avail( &ttm ) ) { printf( "CAP%i: %04u-%02u-%02u %02u:%02u:%02u.%07u", ttm.channel, ttm.tm.year, ttm.tm.month, ttm.tm.mday, @@ -931,10 +1080,219 @@ int check_ucap_poll( void ) +static /*HDR*/ +int set_date_time( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, + const char *str_new_date, const char *str_new_time ) +{ + PCPS_TIME_UNION u = { { 0 } }; + TTM ttm = { 0 }; + unsigned int year = 0; + unsigned int month = 0; + unsigned int mday = 0; + unsigned int hour = 0; + unsigned int min = 0; + unsigned int sec = 0; + unsigned int sec100 = 0; + int rc; + + // Either a date string, a time string, or both + // may have been passed to this function. + // If either of them is NULL read the current date/time + // as default values. + if ( str_new_date == NULL || str_new_time == NULL ) + { +#if 1 //##+++++++++++++ + return -1; +#else + rc = mbg_get_time( dh, &u.t ); + + if ( mbg_ioctl_err( rc, "mbg_get_time" ) ) + return rc; +#endif + } + + + if ( str_new_date ) + { + rc = sscanf( str_new_date, "%u-%u-%u", &year, &month, &mday ); + + if ( ( rc < 3 ) + || ( month < 1 ) || ( month > 12 ) + || ( mday < 1 ) || ( mday > 31 ) ) + { + printf( "** Invalid date: %04u-%02u-%02u\n", year, month, mday ); + return MBG_ERR_CFG; + } + } + + + if ( str_new_time ) + { + rc = sscanf( str_new_time, "%u:%u:%u.%u", &hour, &min, &sec, &sec100 ); + + if ( ( rc < 2 ) // at least hours and minutes are required + || ( hour > 23 ) + || ( min > 59 ) + || ( sec > 60 ) + || ( sec100 > 99 ) ) + { + printf( "** Invalid time: %02u:%02u:%02u.%02u\n", hour, min, sec, sec100 ); + return MBG_ERR_CFG; + } + } + +#if 0 //##++++++++++++++++ + // GPS and non-GPS cards require different API calls which use + // different structures to set the on-board date and time, + // so we have to distinguish. + + if ( _pcps_is_gps( p_dev ) ) // is a GPS card + { + ttm.channel = -1; + + if ( str_new_date ) // new date + { + ttm.tm.year = year; + ttm.tm.month = month; + ttm.tm.mday = mday; + } + else // copy current date as default + { + ttm.tm.year = u.t.year + 2000; + ttm.tm.month = u.t.month; + ttm.tm.mday = u.t.mday; + } + + if ( str_new_time ) // new time + { + ttm.tm.hour = hour; + ttm.tm.min = min; + ttm.tm.sec = sec; + ttm.tm.frac = sec100; + } + else // copy current time as default + { + ttm.tm.hour = u.t.hour; + ttm.tm.min = u.t.min; + ttm.tm.sec = u.t.sec; + ttm.tm.frac = u.t.sec100; + } + + ttm.tm.frac *= 100000; // fracs are in 100 ns units + + #if 0 + // Existing versions of the GPS cards just take + // TTM.tm as local time without accounting for + // the status flags, or UTC offset. + // Instead, the TTM::tm time is converted on-board + // to UTC depending on the local TZDL configuration. + // This works if the system time and the + ttm.tm.offs_from_utc = 7200; + ttm.tm.status |= TM_UTC | TM_LOCAL; + ttm.tm.status |= TM_DL_ENB; + #endif + + rc = mbg_set_gps_time( dh, &ttm ); + + if ( mbg_ioctl_err( rc, "mbg_set_gps_time" ) ) + return rc; + } + else // is not a GPS card + { + if ( str_new_date ) // new date + { + // determine the day-of-week for the given date + struct tm tm = { 0 }; + + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = mday; + tm.tm_hour = 12; + tm.tm_isdst = -1; + mktime( &tm ); + + u.stime.year = year % 100; + u.stime.month = month; + u.stime.mday = mday; + u.stime.wday = _wday_sun06_to_mon17( tm.tm_wday ); + } + + if ( str_new_time ) // new time + { + u.stime.hour = hour; + u.stime.min = min; + u.stime.sec = sec; + u.stime.sec100 = sec100; + } + + if ( u.stime.wday == 0 ) + u.stime.wday = 1; // dummy + + rc = mbg_set_time( dh, &u.stime ); + + if ( mbg_ioctl_err( rc, "mbg_set_time" ) ) + return rc; + } +#else + { + // + PCPS_TIME t = { 0 }; + + // determine the day-of-week for the given date + struct tm tm = { 0 }; + + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = mday; + tm.tm_hour = 12; + tm.tm_isdst = -1; + mktime( &tm ); + + t.year = year % 100; + t.month = month; + t.mday = mday; + t.wday = ( tm.tm_wday == 0 ) ? 7 : tm.tm_wday; + t.hour = hour; + t.min = min; + t.sec = sec; + t.sec100 = sec100; + +#if 0 //##+++++++++++++++++ + { + MBG_PORT_HANDLE port_handle = pmctl->st.serio.port_handle; + const char tmp[] = "\xFF\xFF\xFF\xFF"; + + // Note: encrypted msgs over serial are not yet supported. + + // _mbgserio_write( port_handle, &tmp, strlen( tmp ) ); + // _swab_pcps_time( &t ); + rc = mbgextio_xmt_msg( pmctl, PZF_PCPS_TIME, &t, sizeof( t ) ); + + // _mbgserio_write( port_handle, &tmp, strlen( tmp ) ); + } +#else + // _swab_pcps_time( &t ); + rc = mbgextio_xmt_msg( pmctl, p_addr, PZF_PCPS_TIME, &t, sizeof( t ) ); +#endif + + if ( rc < 0 ) + printf( "Failed to set date/time, rc: %i\n", rc ); + } + +#endif + printf( "\n\nDevice date/time have been set to %04u-%02u-%02u %02u:%02u:%02u.%02u\n\n", + year, month, mday, hour, min, sec, sec100 ); + + return MBG_SUCCESS; + +} // set_date_time + + + /*HDR*/ static void exit_close_connection( void ) { - mbgextio_close_connection( &mctl ); + mbgextio_close_connection( &pmctlx ); printf( "Connection closed.\n" ); printf( "\n" ); @@ -946,7 +1304,7 @@ void exit_close_connection( void ) /*HDR*/ static void exit_auto_off( void ) { - mbgextio_xmt_cmd( &mctl, GPS_AUTO_OFF ); + mbgextio_xmt_cmd( pmctlx, NULL, GPS_AUTO_OFF ); //##++++++ TODO: NULL? #if defined( DEBUG ) printf( "AUTO mode turned off.\n" ); @@ -957,9 +1315,9 @@ void exit_auto_off( void ) /*HDR*/ static -void set_auto_mode( void ) +void set_auto_mode( MBG_MSG_CTL *pmctl ) { - mbgextio_xmt_cmd( &mctl, GPS_AUTO_ON ); + mbgextio_xmt_cmd( pmctl, NULL, GPS_AUTO_ON ); //##++++++ TODO: NULL? #if defined( DEBUG ) printf( "AUTO mode turned on.\n" ); @@ -998,32 +1356,32 @@ int check_command_line( int argc, char *argv[] ) for ( i = 1; i < argc; i++ ) { - if ( strcmp( argv[i], "-a" ) == 0 ) + if ( strcmp( argv[i], "-a" ) == 0 ) { must_send_auto = 1; continue; } - if ( strcmp( argv[i], "-u" ) == 0 ) + if ( strcmp( argv[i], "-u" ) == 0 ) { must_poll_ucap = 1; continue; } - if ( strcmp( argv[i], "-?" ) == 0 ) + if ( strcmp( argv[i], "-?" ) == 0 ) { must_print_usage = 1; continue; } - if ( strcmp( argv[i], "-h" ) == 0 ) + if ( strcmp( argv[i], "-h" ) == 0 ) { must_print_usage = 1; continue; } #if _USE_SOCKET_IO - if ( strcmp( argv[i], "-n" ) == 0 ) + if ( strcmp( argv[i], "-n" ) == 0 ) { is_socket = 1; continue; @@ -1032,7 +1390,7 @@ int check_command_line( int argc, char *argv[] ) #if _USE_SOCKET_IO if ( strcmp( argv[i], "-p" ) == 0 ) - { + { if ( ++i < argc ) password = argv[i]; else @@ -1044,7 +1402,7 @@ int check_command_line( int argc, char *argv[] ) #if _USE_SERIAL_IO if ( strcmp( argv[i], "-b" ) == 0 ) - { + { if ( ++i < argc ) baudrate = strtoul( argv[i], NULL, 10 ); else @@ -1056,7 +1414,7 @@ int check_command_line( int argc, char *argv[] ) #if _USE_SERIAL_IO if ( strcmp( argv[i], "-f" ) == 0 ) - { + { if ( ++i < argc ) framing = argv[i]; else @@ -1074,6 +1432,52 @@ int check_command_line( int argc, char *argv[] ) } #endif + if ( strcmp( argv[i], "-c" ) == 0 ) + { + must_clear_event_log = 1; + continue; + } + + + #if _USE_SOCKET_IO + if ( strcmp( argv[i], "-P" ) == 0 ) + { + if ( ++i < argc ) + { + scu_port = atoi( argv[i] ); + + if ( ( scu_port >= 0 ) && ( scu_port < N_SCU_PORT ) ) + { + must_set_scu_port = 1; + continue; + } + } + + fprintf( stderr, "** invalid parameter for \"-P\"\n" ); + must_print_usage = 1; + continue; + } + #endif + + + if ( strcmp( argv[i], "-d" ) == 0 ) + { + if ( ++i < argc ) + str_new_date = argv[i]; + + continue; + } + + + if ( strcmp( argv[i], "-t" ) == 0 ) + { + if ( ++i < argc ) + str_new_time = argv[i]; + + continue; + } + + if ( argv[i][0] != '-' ) target = argv[i]; else @@ -1112,6 +1516,10 @@ int check_command_line( int argc, char *argv[] ) " -f xxx Serial port framing, default: %s\n" " -F Force serial connection to %lu/%s\n" #endif + " -c clear event log (if supported)\n" + #if _USE_SOCKET_IO + " -P scu_port Select clock at SCU port 0 or 1 (only with SCU over LAN)\n" + #endif "\n" "Example:\n" #if _USE_SERIAL_IO @@ -1148,9 +1556,10 @@ int check_command_line( int argc, char *argv[] ) int main( int argc, char *argv[] ) { + XBP_ADDR *p_addr = NULL; int rc; - printf( "\n\n\nExample Program Accessing a Meinberg Device via Binary Protocol\n" ); + fprintf( stderr, "\n\n\n%s v%s %s\n", pname, pversion, pdescr ); baudrate = default_baudrate; framing = default_framing; @@ -1166,16 +1575,12 @@ int main( int argc, char *argv[] ) #if _USE_SOCKET_IO if ( is_socket ) { - rc = mbgextio_open_socket( &mctl, target, password ); + rc = mbgextio_open_socket( target, &pmctlx, password ); - if ( rc < 0 ) + if ( rc != MBG_SUCCESS ) { - if ( rc == TR_OPEN_ERR ) - perror( "Error connecting" ); - else - fprintf( stderr, "mbgextio_open_socket returned %i", rc ); - - exit( 1 ); + printf( "Failed to connect to %s, rc: %i\n", target, rc ); + return 1; // Error ... } goto doit; @@ -1186,21 +1591,25 @@ int main( int argc, char *argv[] ) if ( must_force_connection ) { printf( "Trying to force connection to 19200/8N1 ..." ); - mbgextio_force_connection( target ); + mbgextio_force_conn_serial( target ); printf( "\n" ); baudrate = default_baudrate; framing = default_framing; } - rc = mbgextio_open_serial( &mctl, target, baudrate, framing ); + rc = mbgextio_open_serial( target, &pmctlx, baudrate, framing ); - if ( rc < 0 ) + if ( rc != MBG_SUCCESS ) { printf( "Error using port %s.\n", target ); - return -1; // Error ... + return 1; // Error ... } + #if defined( DEBUG ) + print_original_serial_settings( stdout, &pmctlx->st.serio ); + #endif + printf( " (Using %s with %li baud, %s)\n\n", target, (long) baudrate, framing ); @@ -1218,23 +1627,77 @@ doit: // now start communication with whichever device has been opened above: - get_receiver_info( &mctl, &receiver_info ); + // TODO: make sure xbp is supported. + mbgextio_setup_xbp_node_list( pmctlx, p_addr ); + + #if _USE_SOCKET_IO + if ( must_set_scu_port ) + { + int rc = set_scu_port( pmctlx, p_addr, scu_port ); + + if ( rc == MBG_SUCCESS ) + printf( "\nSCU switched to port %i (clock #%i)\n\n", + scu_port, scu_port + 1 ); + else + printf( "\nFailed to switch SCU to port %i (clock #%i)\n\n", + scu_port, scu_port + 1 ); + } + #endif + + if ( must_send_auto ) + set_auto_mode( pmctlx ); + + +#if 1 //##+++++++++++++ + get_receiver_info( pmctlx, p_addr, &receiver_info ); +#else + printf( "\n(Skipped getting receiver info)\n\n" ); +#endif + + if ( str_new_date && str_new_time ) + { + set_date_time( pmctlx, p_addr, str_new_date, str_new_time ); + return 0; + } + check_receiver_info( &receiver_info, 1 ); /* display system specific values */ - show_sw_rev( &mctl ); - show_bvar_stat( &mctl ); - show_stat_info( &mctl ); - show_pos( &mctl ); - show_tzdl( &mctl ); - show_port_settings( &mctl ); - show_synth( &mctl ); + show_sw_rev( pmctlx, p_addr ); + show_bvar_stat( pmctlx, p_addr ); + show_stat_info( pmctlx, p_addr ); + show_pos( pmctlx, p_addr ); + show_tzdl( pmctlx, p_addr ); + show_port_settings( pmctlx, p_addr ); + show_synth( pmctlx, p_addr ); + + if ( must_clear_event_log ) + { + if ( receiver_info.features & GPS_HAS_EVT_LOG ) + { + int ret = mbgextio_clr_evt_log( pmctlx, p_addr ); + + if ( ret != 0 ) + fprintf( stderr, "Failed to clear event log, rc: %i\n", ret ); + else + fprintf( stderr, "event log has been cleared\n" ); + } + else + fprintf( stderr, "This device does not support an event log\n" ); + } + + if ( receiver_info.features & GPS_HAS_EVT_LOG ) + show_event_log( pmctlx, p_addr ); + else + if ( !must_clear_event_log ) + printf( "** Warning: this device does not support an event log!\n" ); + // set_synth(); // set_pout_mode(); if ( must_poll_ucap ) - return check_ucap_poll(); + return check_ucap_poll( pmctlx, p_addr ); if ( !must_send_auto ) return 0; @@ -1245,10 +1708,10 @@ doit: // We will start to wait for automatically transmitted messages // which require a longer timeout than we have used by default // to wait for replies to dedicated request messages. - mbgextio_set_char_rcv_timeout( &mctl, 2000 ); // [msec] - mbgextio_set_msg_rcv_timeout( &mctl, 2000 ); // [msec] + mbgextio_set_char_rcv_timeout( pmctlx, 2000 ); // [msec] + mbgextio_set_msg_rcv_timeout( pmctlx, 2000 ); // [msec] - set_auto_mode(); + set_auto_mode( pmctlx ); do { @@ -1256,17 +1719,17 @@ doit: MSG_DATA *p; - rc = mbgextio_rcv_msg( &mctl, -1 ); + rc = mbgextio_rcv_msg( pmctlx, p_addr, -1 ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); break; } - mbgextio_xmt_cmd( &mctl, GPS_AUTO_ON ); + mbgextio_xmt_cmd( pmctlx, p_addr, GPS_AUTO_ON ); - pmb = mctl.rcv.pmb; + pmb = pmctlx->rcv.pmb; p = &pmb->u.msg_data; switch ( pmb->hdr.cmd ) @@ -1276,9 +1739,9 @@ doit: if ( p->ttm.channel == -1 ) { - mbgextio_xmt_cmd( &mctl, GPS_AUTO_ON ); - mbgextio_xmt_cmd( &mctl, GPS_STAT_INFO ); - mbgextio_xmt_cmd( &mctl, GPS_UCAP ); + mbgextio_xmt_cmd( pmctlx, p_addr, GPS_AUTO_ON ); + mbgextio_xmt_cmd( pmctlx, p_addr, GPS_STAT_INFO ); + mbgextio_xmt_cmd( pmctlx, p_addr, GPS_UCAP ); } break; diff --git a/mbglib/common/aes128.c b/mbglib/common/aes128.c index 542467b..fb6a71e 100644 --- a/mbglib/common/aes128.c +++ b/mbglib/common/aes128.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: aes128.c 1.2 2009/10/01 14:03:09 martin REL_M $ + * $Id: aes128.c 1.2.1.1 2009/12/22 12:23:00 martin TRASH $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,8 @@ * * ----------------------------------------------------------------------- * $Log: aes128.c $ + * Revision 1.2.1.1 2009/12/22 12:23:00 martin + * Started to fix possible 32/64 bit issues. * Revision 1.2 2009/10/01 14:03:09 martin * Added standard file header. * Fixed compiler warnings. @@ -36,26 +38,28 @@ #define FTABLE_ENTRIES 256 -static ulong FSb[FTABLE_ENTRIES]; -static ulong FT0[FTABLE_ENTRIES]; -static ulong FT1[FTABLE_ENTRIES]; -static ulong FT2[FTABLE_ENTRIES]; -static ulong FT3[FTABLE_ENTRIES]; +static uint32_t FSb[FTABLE_ENTRIES]; +static uint32_t FT0[FTABLE_ENTRIES]; +static uint32_t FT1[FTABLE_ENTRIES]; +static uint32_t FT2[FTABLE_ENTRIES]; +static uint32_t FT3[FTABLE_ENTRIES]; /* rounding constants */ #define RCON_TABLE_ENTRIES 10 -ulong RCON[RCON_TABLE_ENTRIES]; +uint32_t RCON[RCON_TABLE_ENTRIES]; /* tables generation flag */ static int initialized; -#define ROTR8(x) ( ( ( x << 24 ) & 0xFFFFFFFFUL ) | \ - ( ( x & 0xFFFFFFFFUL ) >> 8 ) ) -#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) -#define MUL(x,y) ( ( x && y ) ? pow[(log[x] + log[y]) % 255] : 0 ) +#define ROTR8( _x ) ( ( ( (_x) << 24 ) & 0xFFFFFFFFUL ) | \ + ( ( (_x) & 0xFFFFFFFFUL ) >> 8 ) ) + +#define XTIME( _x ) ( ( (_x) << 1 ) ^ ( ( (_x) & 0x80 ) ? 0x1B : 0x00 ) ) + +#define MUL( _x, _y ) ( ( (_x) && (_y) ) ? pow[(log[_x] + log[_y]) % 255] : 0 ) @@ -63,7 +67,8 @@ static int initialized; void aes_gen_tables( void ) { int i; - uint8_t x, y; + uint8_t x; + uint8_t y; uint8_t pow[FTABLE_ENTRIES]; uint8_t log[FTABLE_ENTRIES]; @@ -78,7 +83,7 @@ void aes_gen_tables( void ) /* calculate the round constants */ for ( i = 0, x = 1; i < RCON_TABLE_ENTRIES; i++, x = XTIME( x ) ) - RCON[i] = (ulong) x << 24; + RCON[i] = (uint32_t) x << 24; /* generate the forward and reverse S-boxes */ @@ -104,10 +109,10 @@ void aes_gen_tables( void ) x = (uint8_t) FSb[i]; y = XTIME( x ); - FT0[i] = (ulong) ( x ^ y ) ^ - ( (ulong) x << 8 ) ^ - ( (ulong) x << 16 ) ^ - ( (ulong) y << 24 ); + FT0[i] = (uint32_t) ( x ^ y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) y << 24 ); FT0[i] &= 0xFFFFFFFFUL; @@ -122,20 +127,20 @@ void aes_gen_tables( void ) /* platform-independant 32-bit integer manipulation macros */ -#define GET_ulong(n,b,i) \ -{ \ - (n) = ( (ulong) (b)[(i) ] << 24 ) \ - | ( (ulong) (b)[(i) + 1] << 16 ) \ - | ( (ulong) (b)[(i) + 2] << 8 ) \ - | ( (ulong) (b)[(i) + 3] ); \ +#define GET_ulong( _n, _b, _i ) \ +{ \ + (_n) = ( (uint32_t) (_b)[(_i) ] << 24 ) \ + | ( (uint32_t) (_b)[(_i) + 1] << 16 ) \ + | ( (uint32_t) (_b)[(_i) + 2] << 8 ) \ + | ( (uint32_t) (_b)[(_i) + 3] ); \ } -#define PUT_ulong(n,b,i) \ -{ \ - (b)[(i) ] = (uint8_t) ( (n) >> 24 ); \ - (b)[(i) + 1] = (uint8_t) ( (n) >> 16 ); \ - (b)[(i) + 2] = (uint8_t) ( (n) >> 8 ); \ - (b)[(i) + 3] = (uint8_t) ( (n) ); \ +#define PUT_ulong( _n, _b, _i ) \ +{ \ + (_b)[(_i) ] = (uint8_t) ( (_n) >> 24 ); \ + (_b)[(_i) + 1] = (uint8_t) ( (_n) >> 16 ); \ + (_b)[(_i) + 2] = (uint8_t) ( (_n) >> 8 ); \ + (_b)[(_i) + 3] = (uint8_t) ( (_n) ); \ } @@ -150,7 +155,7 @@ void aes_gen_tables( void ) int aes128_set_key( aes128_context *ctx, uint8_t *key ) { int i; - ulong *RK; + uint32_t *RK; if ( !initialized ) { @@ -188,7 +193,7 @@ int aes128_set_key( aes128_context *ctx, uint8_t *key ) static /*HDR*/ void aes128_encrypt( aes128_context *ctx, uint8_t input[16], uint8_t output[16] ) { - ulong *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; RK = ctx->erk; @@ -199,23 +204,23 @@ void aes128_encrypt( aes128_context *ctx, uint8_t input[16], uint8_t output[16] #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ { \ - RK += 4; \ - \ + RK += 4; \ + \ X0 = RK[0] ^ FT0[ (uint8_t) ( Y0 >> 24 ) ] ^ \ FT1[ (uint8_t) ( Y1 >> 16 ) ] ^ \ FT2[ (uint8_t) ( Y2 >> 8 ) ] ^ \ FT3[ (uint8_t) ( Y3 ) ]; \ - \ + \ X1 = RK[1] ^ FT0[ (uint8_t) ( Y1 >> 24 ) ] ^ \ FT1[ (uint8_t) ( Y2 >> 16 ) ] ^ \ FT2[ (uint8_t) ( Y3 >> 8 ) ] ^ \ FT3[ (uint8_t) ( Y0 ) ]; \ - \ + \ X2 = RK[2] ^ FT0[ (uint8_t) ( Y2 >> 24 ) ] ^ \ FT1[ (uint8_t) ( Y3 >> 16 ) ] ^ \ FT2[ (uint8_t) ( Y0 >> 8 ) ] ^ \ FT3[ (uint8_t) ( Y1 ) ]; \ - \ + \ X3 = RK[3] ^ FT0[ (uint8_t) ( Y3 >> 24 ) ] ^ \ FT1[ (uint8_t) ( Y0 >> 16 ) ] ^ \ FT2[ (uint8_t) ( Y1 >> 8 ) ] ^ \ diff --git a/mbglib/common/aes128.h b/mbglib/common/aes128.h index c2fe912..fc49929 100644 --- a/mbglib/common/aes128.h +++ b/mbglib/common/aes128.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: aes128.h 1.3 2009/10/01 14:04:52 martin REL_M $ + * $Id: aes128.h 1.3.1.1 2009/12/22 12:23:09 martin TRASH $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,8 @@ * * ----------------------------------------------------------------------- * $Log: aes128.h $ + * Revision 1.3.1.1 2009/12/22 12:23:09 martin + * Started to fix possible 32/64 bit issues. * Revision 1.3 2009/10/01 14:04:52 martin * Code cleanup. * Updated function prototypes. @@ -42,8 +44,8 @@ typedef struct { - unsigned long erk[64]; /* encryption round keys */ - unsigned long drk[64]; /* decryption round keys */ + uint32_t erk[64]; /* encryption round keys */ + uint32_t drk[64]; /* decryption round keys */ } aes128_context; /* function prototypes: */ diff --git a/mbglib/common/cfg_hlp.h b/mbglib/common/cfg_hlp.h new file mode 100644 index 0000000..0aa085f --- /dev/null +++ b/mbglib/common/cfg_hlp.h @@ -0,0 +1,431 @@ + +/************************************************************************** + * + * $Id: cfg_hlp.h 1.3.1.19 2014/10/29 16:25:31 martin TEST $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for configuration programs. + * + * WARNING: Changing the constants defined here affects the size of + * the related structures and arrays, and thus would break compatibility + * if used in DLLs / shared object libraries. + * + * Care must be taken that the number of objects supported by + * any particular device (which can be only determined at runtime) + * does not exceed the max. number of objects specified here + * for the configuration programs. + * + * ----------------------------------------------------------------------- + * $Log: cfg_hlp.h $ + * Revision 1.3.1.19 2014/10/29 16:25:31 martin + * Moved some functions and structures to more convenient files. + * Revision 1.3.1.18 2014/10/29 16:00:37 martin + * Revision 1.3.1.17 2014/10/29 14:21:55 martin + * Revision 1.3.1.16 2014/09/26 11:43:24 martin + * Revision 1.3.1.15 2014/07/22 13:05:35 martin + * Revision 1.3.1.14 2014/07/14 15:42:45Z martin + * Revision 1.3.1.13 2014/06/25 15:15:20 martin + * Revision 1.3.1.12 2014/06/25 08:51:36Z martin + * Support GPIO status. + * Revision 1.3.1.11 2014/05/22 16:15:16Z martin + * Revision 1.3.1.10 2014/05/14 12:43:53 martin + * Revision 1.3.1.9 2014/05/13 08:23:24 martin + * Revision 1.3.1.8 2014/05/13 08:19:34Z martin + * Revision 1.3.1.7 2014/04/28 12:33:09 martin + * Revision 1.3.1.6 2014/04/28 12:04:32 martin + * Revision 1.3.1.5 2014/04/25 09:16:38 martin + * Updated function prototypes. + * Revision 1.3.1.4 2013/12/18 14:51:37 martin + * Moved inline function num_bits_set() here. + * Revision 1.3.1.3 2013/11/13 10:00:09 martin + * Revision 1.3.1.2 2013/11/12 12:12:40 marvin + * Changed calls for NTP info and settings. + * Revision 1.3.1.1 2013/09/25 10:14:38Z martin + * Started to support NTP configuration. + * Revision 1.3 2013/09/25 10:02:15 martin + * Added ALL_PTP_CFG_INFO, ALL_GNSS_SAT_INFO_IDX and + * related definitions. + * Added doxygen comments. + * Revision 1.2 2012/10/02 18:16:26 martin + * Modified some typedefs to be more compliant with the underlying types. + * Revision 1.1 2011/09/21 15:59:59 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _CFG_HLP_H +#define _CFG_HLP_H + + +/* Other headers to be included */ + +#include + + +#ifdef _CFG_HLP + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + +/// @brief The max number of serial ports supported by configuration programs +#define MAX_PARM_PORT 4 + +/// @brief An array of configuration settings for all serial ports +typedef PORT_INFO_IDX ALL_PORT_INFO_IDX[MAX_PARM_PORT]; + + +/// @brief The max number of serial string types supported by configuration programs +#define MAX_PARM_STR_TYPE 20 + +/// @brief An array of configuration settings for all serial string types +typedef STR_TYPE_INFO_IDX ALL_STR_TYPE_INFO_IDX[MAX_PARM_STR_TYPE]; + +/** + * @brief All configuration parameters for all serial ports + * + * Used to collect all configuration parameters of a clock's serial ports + * that can be handled by a configuration program. + * + * @see ::RECEIVER_INFO::n_com_ports + * @see ::RECEIVER_INFO::n_str_type + */ +typedef struct +{ + ALL_PORT_INFO_IDX pii; ///< all serial port configuration settings + ALL_STR_TYPE_INFO_IDX stii; ///< all supported serial string types + PORT_PARM tmp_pp; ///< used internally only, for compatibility + +} RECEIVER_PORT_CFG; + + + +/// @brief The max number of programmable pulse outputs supported by configuration programs +#define MAX_PARM_POUT 4 + +/** + * @brief An array of configuration settings for all programmable pulse outputs + * + * Used to collect all configuration parameters of a clock's programmable pulse outputs + * that can be handled by a configuration program. + * + * @see ::RECEIVER_INFO::n_prg_out + */ +typedef POUT_INFO_IDX ALL_POUT_INFO_IDX[MAX_PARM_POUT]; + + + +/// @brief The max number of PTP unicast masters supported by configuration programs +#define MAX_PARM_PTP_UC_MASTER 3 + +/// @brief Configuration settings for all unicast master specifications +typedef PTP_UC_MASTER_INFO_IDX ALL_PTP_UC_MASTER_INFO_IDX[MAX_PARM_PTP_UC_MASTER]; + +/** + * @brief All PTP configuration parameters + * + * Used to collect all configuration parameters for a PTP daemon + * that can be handled by a configuration program. + * + * @see ::GPS_HAS_PTP + * @see ::PTP_UC_MASTER_CFG_LIMITS::n_supp_master + */ +typedef struct +{ + PTP_CFG_INFO ptp_cfg_info; + PTP_UC_MASTER_CFG_LIMITS ptp_uc_master_cfg_limits; + ALL_PTP_UC_MASTER_INFO_IDX all_ptp_uc_master_info_idx; + +} ALL_PTP_CFG_INFO; + + + +/// @brief The max number of GNSS settings supported by configuration programs +#define MAX_PARM_GNSS_SAT N_GNSS_TYPES + +/** + * @brief An array of configuration settings for all programmable pulse outputs + * + * Used to collect all configuration parameters of a clock's programmable pulse outputs + * that can be handled by a configuration program. + */ +typedef GNSS_SAT_INFO_IDX ALL_GNSS_SAT_INFO_IDX[MAX_PARM_GNSS_SAT]; + + + +/// @brief The max number of NTP server associations to be handled by configuration programs +#define MAX_EXTERNAL_SERVER 20 + +/// @brief Configuration settings for all NTP server associatioions +typedef NTP_PEER_SETTINGS ALL_NTP_PEER_SETTINGS[MAX_EXTERNAL_SERVER]; + +/** + * @brief All NTP configuration parameters + * + * Used to collect all configuration parameters for an NTP daemon + * that can be handled by a configuration program. + * + * @see ::GPS_HAS_NTP + */ +typedef struct +{ + ALL_NTP_PEER_SETTINGS all_ntp_peer_settings; + +} NTP_CLIENT_CFG_PEER_SETTINGS; + + + + +/// @brief The max number of GPIO ports supported by configuration programs +#define MAX_PARM_GPIO 10 + +/// @brief Configuration settings for all GPIO ports +typedef MBG_GPIO_INFO_IDX ALL_GPIO_INFO_IDX[MAX_PARM_GPIO]; + +/// @brief Status information on all GPIO ports +typedef MBG_GPIO_STATUS_IDX ALL_GPIO_STATUS_IDX[MAX_PARM_GPIO]; + + + + +/// @brief The max number of XMR sources supported by configuration programs +#define MAX_PARM_XMR 10 + +/// @brief Status of all XMR inputs +typedef XMULTI_REF_STATUS_IDX ALL_XMULTI_REF_STATUS_IDX[MAX_PARM_XMR]; + +/// @brief Configuration settings for all XMR inputs +typedef XMULTI_REF_INFO_IDX ALL_XMULTI_REF_INFO_IDX[MAX_PARM_XMR]; + + + + +/** + * @brief A mode specifying how to interpret a ::PCPS_SIG_VAL + * + * Used with ::PCPS_TIME_EXT::comp_sig_mode. Depending on this mode + * a signal value can be interpreted e.g. as signal strength (with + * long wave or IRIG time code receivers), or as indicator whether an + * antenna is connected (satellite receivers), or a network link is + * available (PTP slaves) or not, and an appropriate status message + * can be displayed. + * + * @see @ref PCPS_SIG_VAL_DEFS + */ +enum COMP_SIG_MODES +{ + COMP_SIG_MODE_NONE, ///< signal value not used + COMP_SIG_MODE_SIGNAL, ///< input signal strength + COMP_SIG_MODE_ANT_CONN, ///< antenna connection state + COMP_SIG_MODE_PORT_LINK, ///< port link state + N_CONN_SIG_MODES +}; + + +/** + * @brief Flag bits indicating if some extended status is available + * + * @see ::PCPS_TIME_EXT_FLAGS + */ +enum PCPS_TIME_EXT_FLAG_BITS +{ + PCPS_TIME_EXT_FLAG_BIT_UTC_VALID, ///< ::PCPS_TIME_EXT::utc_offs field is valid + N_PCPS_TIME_EXT_FLAG_BITS +}; + + +/** + * @brief Flag masks used with ::PCPS_TIME_EXT::flags + * + * @see ::PCPS_TIME_EXT_FLAG_BITS + */ +enum PCPS_TIME_EXT_FLAGS +{ + PCPS_TIME_EXT_FLAG_UTC_VALID = ( 1UL << PCPS_TIME_EXT_FLAG_BIT_UTC_VALID ) ///< see ::PCPS_TIME_EXT_FLAG_BIT_UTC_VALID +}; + + + +_ext const char *str_unknown +#ifdef _DO_INIT + = "unknown" +#endif +; + + +_ext const char *str_undefined +#ifdef _DO_INIT + = "(undefined)" +#endif +; + + +_ext const char *str_not_spc +#ifdef _DO_INIT + = "not " +#endif +; + + + +_ext const char *mbg_gpio_type_names[N_MBG_GPIO_TYPES] +#ifdef _DO_INIT + = DEFAULT_GPIO_TYPES_SHORT_STRS +#endif +; + +#define _get_gpio_type_name( _i ) \ + ( ( (_i) < N_MBG_GPIO_TYPES ) ? mbg_gpio_type_names[_i] : str_unknown ) + + + +_ext const char *mbg_gpio_port_state_names[N_MBG_GPIO_PORT_STATES] +#ifdef _DO_INIT + = DEFAULT_GPIO_PORT_STATE_NAMES +#endif +; + +#define _get_gpio_port_state_name( _i ) \ + ( ( (_i) < N_MBG_GPIO_PORT_STATES ) ? mbg_gpio_port_state_names[_i] : str_unknown ) + + + +_ext const char *mbg_gpio_signal_shape_names[N_MBG_GPIO_SIGNAL_SHAPES] +#ifdef _DO_INIT + = DEFAULT_GPIO_SIGNAL_SHAPE_NAMES +#endif +; + +#define _get_gpio_signal_shape_name( _i ) \ + ( ( (_i) < N_MBG_GPIO_SIGNAL_SHAPES ) ? mbg_gpio_signal_shape_names[_i] : str_unknown ) + + + +_ext const char *mbg_gpio_fixed_freq_strs[N_MBG_GPIO_FIXED_FREQ] +#ifdef _DO_INIT + = MBG_GPIO_FIXED_FREQ_STRS +#endif +; + +#define _get_gpio_fixed_freq_str( _i ) \ + ( ( (_i) < N_MBG_GPIO_FIXED_FREQ ) ? mbg_gpio_fixed_freq_strs[_i] : str_unknown ) + + + +_ext const char *xmr_holdover_status_mode_names[N_XMR_HOLDOVER_STATUS_MODES] +#ifdef _DO_INIT + = XMR_HOLDOVER_STATUS_MODE_NAMES +#endif +; + +#define _get_xmr_holdover_status_mode_name( _i ) \ + ( ( (_i) < N_XMR_HOLDOVER_STATUS_MODES ) ? xmr_holdover_status_mode_names[_i] : str_unknown ) + + + +/** + * @brief Count the number of bits which are not 0 + * + * @param[in] val Value to be tested + * + * @return The number of non-zero bits in val + */ +static __mbg_inline +int num_bits_set( long val ) +{ + int bits_set = 0; + int i; + + for ( i = 0; i < ( 8 * sizeof( val ) ); i++ ) + { + if ( val & 1 ) + bits_set++; + + val >>= 1; + } + + return bits_set; + +} // num_bits_set + + + +/* function prototypes: */ + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + * @brief Trim whitespace at the end of a string + * + * @param[in,out] s The string to be trimmed + */ + void trim_trailing_whitespace( char *s ) ; + + /** + * @brief Trim whitespace at the beginning of a string + * + * @param[in,out] s The string to be trimmed + */ + void trim_leading_whitespace( char *s ) ; + + /** + * @brief Trim both leading and trailing whitespace from a string + * + * @param[in,out] s The string to be trimmed + */ + void trim_whitespace( char *s ) ; + + /** + * @brief Print nano time into string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] len Size of the string buffer, i.e. max length + * @param[in] nt The ::NANO_TIME to be printed + */ + int snprint_nano_time( char *s, int len, const NANO_TIME *nt ) ; + + /** + * @brief Check if a software revision name should be displayed + * + * The software revision name is usually empty, except if the + * firmware is a customized version, in which case the field + * contains an identifier string. + * + * There are some standard firmware versions where this string + * is not empty but padded with spaces, etc., so we try to + * clean this up and display the string properly, if appropriate. + * + * @param[in,out] p The ::SW_REV name to check + * @param[in] verbose The app's verbosity level + * + * @return != 0 if SW name should be displayed + */ + int chk_sw_rev_name( SW_REV *p, int verbose ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _CFG_HLP_H */ diff --git a/mbglib/common/extiohlp.c b/mbglib/common/extiohlp.c new file mode 100644 index 0000000..8fa84c6 --- /dev/null +++ b/mbglib/common/extiohlp.c @@ -0,0 +1,275 @@ + +/************************************************************************** + * + * $Id: extiohlp.c 1.3.1.4.1.2 2015/01/21 13:24:44 marvin TEST $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Device configuration helper functions. This is an extension to + * mbgextio.c providing useful functions to simplify reading/writing + * complex device configuration structure sets. + * + * Warning: + * These functions should not be implemented in a DLL / shared library + * since the parameter sizes might vary with different versions + * of the API calls, which which would make different versions of + * precompiled libraries incompatible to each other. + * + * ----------------------------------------------------------------------- + * $Log: extiohlp.c $ + * Revision 1.3.1.4.1.2 2015/01/21 13:24:44 marvin + * Added XBP Adress specifier to mbgextio functions. + * Revision 1.3.1.4.1.1 2014/10/31 12:04:45Z martin + * Started to support XBP addressing. + * Revision 1.3.1.4 2014/10/30 14:50:00 martin + * Generally return Meinberg error codes only. + * Updated doxygen stuff. + * Updated function prototypes. + * Revision 1.3.1.3 2013/12/19 09:20:12 martin + * Revision 1.3.1.2 2013/12/17 14:57:48Z martin + * Revision 1.3.1.1 2013/09/25 11:10:49Z marvin + * Added function for all_ptp_cfg_info. + * Revision 1.3 2013/02/01 15:49:59Z martin + * Updated doxygen comments. + * Cleanup. + * Revision 1.2 2012/03/09 08:32:58Z martin + * Cleanup. + * Revision 1.1 2011/09/21 15:59:59 martin + * Initial revision. + * + **************************************************************************/ + +#define _EXTIOHLP + #include +#undef _EXTIOHLP + +#include + + + +/*HDR*/ +/** + * @brief Read all serial port settings and supported configuration parameters + * + * @note The function mbgextio_setup_receiver_info() must have been called before, + * and the returned ::RECEIVER_INFO has to be passed to this function. + * + * The complementary function mbgextio_save_serial_settings() should + * be used to write a modified port configuration back to the device. + * + * @param pmctl Pointer to a valid message control structure + * @param p_addr Pointer to XBP address specifier + * @param p_cfg Pointer to a ::RECEIVER_PORT_CFG structure to be set up + * @param p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_save_serial_settings + * @see ::mbgextio_get_receiver_info + */ +int mbgextio_get_serial_settings( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, + RECEIVER_PORT_CFG *p_cfg, const RECEIVER_INFO *p_ri ) +{ + int rc = 0; + + memset( p_cfg, 0, sizeof( *p_cfg ) ); + + if ( p_ri->model_code != GPS_MODEL_UNKNOWN ) + { + rc = mbgextio_get_all_port_info( pmctl, p_addr, p_cfg->pii, p_ri ); + + if ( rc != MBG_SUCCESS ) + goto out; + + rc = mbgextio_get_all_str_type_info( pmctl, p_addr, p_cfg->stii, p_ri ); + } + else + { + #if 0 // TODO ##+++++++ provide some symbols + uint16_t i; + + rc = mbgextio_get_port_parm( pmctl, p_addr, &p_cfg->tmp_pp ); + + if ( rc != MBG_SUCCESS ) + goto out; + + for ( i = 0; i < p_ri->n_com_ports; i++ ) + { + PORT_INFO_IDX *p_pii = &p_cfg->pii[i]; + PORT_INFO *p_pi = &p_pii->port_info; + + p_pii->idx = i; + port_settings_from_port_parm( &p_pi->port_settings, + i, &p_cfg->tmp_pp, 1 ); + + p_pi->supp_baud_rates = DEFAULT_GPS_BAUD_RATES_C166; + p_pi->supp_framings = DEFAULT_GPS_FRAMINGS_C166; + p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_GPS; + } + + for ( i = 0; i < p_ri->n_str_type; i++ ) + { + STR_TYPE_INFO_IDX *stip = &p_cfg->stii[i]; + stip->idx = i; + stip->str_type_info = default_str_type_info[i]; + } + + rc = MBG_SUCCESS; + #endif + } + +out: + return rc; + +} // mbgextio_get_serial_settings + + + +/*HDR*/ +/** + * @brief Send the configuration settings for a single serial port to a device + * + * @note The function mbgextio_setup_receiver_info() must have been called before, + * and the returned ::RECEIVER_INFO has to be passed to this function as well as + * to mbgextio_get_serial_settings() which should have been called before to read + * the current settings and supported features for each port. + * + * @param pmctl Pointer to a valid message control structure + * @param p_addr Pointer to XBP address specifier + * @param pcfg Pointer to a ::RECEIVER_PORT_CFG structure + * @param port_idx Index of the serial port to be saved + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_serial_settings + * @see ::mbgextio_get_receiver_info + */ +int mbgextio_save_serial_settings( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, + const RECEIVER_PORT_CFG *pcfg, uint16_t port_idx ) +{ + int rc; + + rc = mbgextio_set_port_settings_idx( pmctl, p_addr, + &pcfg->pii[port_idx].port_info.port_settings, port_idx ); + + return rc; //##++ MBG_SUCCESS or < 0 on error + +} // mbgextio_save_serial_settings + + + +/*HDR*/ +/** + * @brief Read all PTP configuration in ::ALL_PTP_CFG_INFO format + * + * @note Only supported if ::GPS_HAS_PTP + * + * @param pmctl Pointer to a valid message control structure + * @param p_addr Pointer to XBP address specifier + * @param p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##++++++++++++++++++++++++++++++ + * @see ::mbgextio_get_receiver_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_ptp_cfg_info( MBG_MSG_CTL *pmctl, + XBP_ADDR *p_addr, + ALL_PTP_CFG_INFO *p ) +{ + int rc = mbgextio_get_ptp_cfg_info( pmctl, p_addr, &p->ptp_cfg_info ); + + if ( rc != MBG_SUCCESS ) + goto out; + + if ( p->ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) + { + rc = mbgextio_get_ptp_uc_master_cfg_limits( pmctl, p_addr, + &p->ptp_uc_master_cfg_limits ); + + if ( rc != MBG_SUCCESS ) + goto out; + + if ( p->ptp_uc_master_cfg_limits.n_supp_master > MAX_PARM_PTP_UC_MASTER ) + { + // The number of PTP unicast masters supported by this device + // exceeds the number of unicast masters supporterd by this driver. + rc = MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP; + goto out; + } + + rc = mbgextio_get_all_ptp_uc_master_info( pmctl, p_addr, + p->all_ptp_uc_master_info_idx, &p->ptp_uc_master_cfg_limits ); + + if ( rc != MBG_SUCCESS ) + goto out; + } + +out: + return rc; + +} // mbgextio_get_all_ptp_cfg_info + + +//#warning mbgextio_save_all_ptp_cfg_settings missing + + +/*HDR*/ +/** + * @brief Convert a mathematical angle [rad] to a geographic angle [degree, minute, second] + * + * @note This has been copied from mbggeo.c, so mbggeo.h should + * provide the same prototype. + */ +void rad_to_dms( const double *rad, DMS *dms, const char prefix ) +{ + static const double r2d = 180.0 / PI; + + double r; + + if ( prefix == 'E' ) + dms->prefix = ( *rad < 0.0 ) ? 'W' : 'E'; + else + dms->prefix = ( *rad < 0.0 ) ? 'S' : 'N'; + + r = *rad * r2d; + + if ( r < 0 ) + r = -r; + + dms->deg = (int) r; + + r -= dms->deg; + r *= 60; + + dms->min = (int) r; + + r -= dms->min; + r *= 60; + + dms->sec = r; + +} /* rad_to_dms */ + + + +/*HDR*/ +/** + * @brief Convert mathematic coords to to geographic coords + * + * Mathematic coords are (longitude, latitude in [rad]), geographic coords + * are (longitude, latitude in [degree, minute, second]) + * + * @note This has been copied from mbggeo.c, so mbggeo.h should + * provide the same prototype. + */ +void lla_to_dms( POS *pos ) +{ + rad_to_dms( &pos->lla[LON], &pos->longitude, 'E' ); + rad_to_dms( &pos->lla[LAT], &pos->latitude, 'N' ); + +} /* lla_to_dms */ + + + diff --git a/mbglib/common/extiohlp.h b/mbglib/common/extiohlp.h new file mode 100644 index 0000000..2f4f26f --- /dev/null +++ b/mbglib/common/extiohlp.h @@ -0,0 +1,158 @@ + +/************************************************************************** + * + * $Id: extiohlp.h 1.3.1.5.1.2 2015/01/21 13:24:47 marvin TEST $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for extiohlp.c. + * + * ----------------------------------------------------------------------- + * $Log: extiohlp.h $ + * Revision 1.3.1.5.1.2 2015/01/21 13:24:47 marvin + * Added XBP Adress specifier to mbgextio functions. + * Revision 1.3.1.5.1.1 2014/10/31 12:03:34Z martin + * Started to support XBP addressing. + * Revision 1.3.1.5 2014/03/18 11:17:00 gregoire + * Revision 1.3.1.4 2014/03/17 14:51:50Z martin + * Revision 1.3.1.3 2013/12/19 09:20:12Z martin + * Revision 1.3.1.2 2013/12/17 14:57:49Z martin + * Revision 1.3.1.1 2013/09/25 11:10:56Z marvin + * Added function for all_ptp_cfg_info. + * Revision 1.3 2013/02/01 15:52:16Z martin + * Updated function prototypes. + * Revision 1.2 2012/03/09 08:35:51Z martin + * Updated function prototypes. + * Revision 1.1 2011/09/21 15:59:59 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _EXTIOHLP_H +#define _EXTIOHLP_H + + +/* Other headers to be included */ + +#include + +#include +#include + + +#ifdef _EXTIOHLP + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + + + + +/* function prototypes: */ + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + * @brief Read all serial port settings and supported configuration parameters + * + * @note The function mbgextio_setup_receiver_info() must have been called before, + * and the returned ::RECEIVER_INFO has to be passed to this function. + * + * The complementary function mbgextio_save_serial_settings() should + * be used to write a modified port configuration back to the device. + * + * @param pmctl Pointer to a valid message control structure + * @param p_addr Pointer to XBP address specifier + * @param p_cfg Pointer to a ::RECEIVER_PORT_CFG structure to be set up + * @param p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_save_serial_settings + * @see ::mbgextio_get_receiver_info + */ + int mbgextio_get_serial_settings( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, RECEIVER_PORT_CFG *p_cfg, const RECEIVER_INFO *p_ri ) ; + + /** + * @brief Send the configuration settings for a single serial port to a device + * + * @note The function mbgextio_setup_receiver_info() must have been called before, + * and the returned ::RECEIVER_INFO has to be passed to this function as well as + * to mbgextio_get_serial_settings() which should have been called before to read + * the current settings and supported features for each port. + * + * @param pmctl Pointer to a valid message control structure + * @param p_addr Pointer to XBP address specifier + * @param pcfg Pointer to a ::RECEIVER_PORT_CFG structure + * @param port_idx Index of the serial port to be saved + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_serial_settings + * @see ::mbgextio_get_receiver_info + */ + int mbgextio_save_serial_settings( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, const RECEIVER_PORT_CFG *pcfg, uint16_t port_idx ) ; + + /** + * @brief Read all PTP configuration in ::ALL_PTP_CFG_INFO format + * + * @note Only supported if ::GPS_HAS_PTP + * + * @param pmctl Pointer to a valid message control structure + * @param p_addr Pointer to XBP address specifier + * @param p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##++++++++++++++++++++++++++++++ + * @see ::mbgextio_get_receiver_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_ptp_cfg_info( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, ALL_PTP_CFG_INFO *p ) ; + + /** + * @brief Convert a mathematical angle [rad] to a geographic angle [degree, minute, second] + * + * @note This has been copied from mbggeo.c, so mbggeo.h should + * provide the same prototype. + */ + void rad_to_dms( const double *rad, DMS *dms, const char prefix ) ; + + /** + * @brief Convert mathematic coords to to geographic coords + * + * Mathematic coords are (longitude, latitude in [rad]), geographic coords + * are (longitude, latitude in [degree, minute, second]) + * + * @note This has been copied from mbggeo.c, so mbggeo.h should + * provide the same prototype. + */ + void lla_to_dms( POS *pos ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _EXTIOHLP_H */ diff --git a/mbglib/common/gpsdefs.h b/mbglib/common/gpsdefs.h index d7156fd..1ad290f 100644 --- a/mbglib/common/gpsdefs.h +++ b/mbglib/common/gpsdefs.h @@ -1,19 +1,199 @@ /************************************************************************** * - * $Id: gpsdefs.h 1.91 2011/01/31 11:23:56 martin REL_M $ + * $Id: gpsdefs.h 1.124 2015/07/14 14:22:46 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 + * However, more and more Meinberg non-GPS devices also use some of * these definitions. * * ----------------------------------------------------------------------- * $Log: gpsdefs.h $ - * Revision 1.91 2011/01/31 11:23:56 martin + * Revision 1.124 2015/07/14 14:22:46 martin + * Doxygen fix. + * Revision 1.123 2015/07/06 13:00:10 martin + * Added definitions for VSG180, MSF180, WWVB180, and CPC180. + * Added definitions for PZF180. + * Definitions for SDI and MDU300 added by stephan. + * Definitions for HPS100 added by daniel. + * FDM180 and associated definitions added by paul. + * Started to support eXtended Binary Protocol (XBP). + * Merged daniel and gregoire's changes from the 1.120.2.x branch. + * Defines for IPv6 multicast scopes added by gregoire. + * XMR_EXT_SRC_INFO and associated XMR_SETTINGS_FLAG_MSKS flags + * defined by andre. + * Support XMULTI_REF_INFO::n_prio field again. + * Fixed _mbg_swab_gpio_cfg_limits() macro. + * Added MBG_NET_LINK_OPT_MASK_CAN_SYNCE to MBG_NET_LINK_OPT_MASKS. + * New PTP_ROLE_MASKS PTP_ROLE_NTP_SERVER and PTP_ROLE_NTP_CLIENT. + * Some PTP profile extensions added by daniel. + * Added missing defines for SPT. + * Added definitions for REL1000. + * Moved structure NANO_TIME_64 here. + * Revision 1.122 2014/07/29 08:57:44Z 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. @@ -38,7 +218,7 @@ * Added support for new model GLN170. * Revision 1.87 2010/03/10 11:29:37Z martin * Added definitions for GPS180. - * Added multiref source 1 PPS plus associated string. + * 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 @@ -53,10 +233,10 @@ * 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 + * 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 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. @@ -73,7 +253,7 @@ * 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 + * Added preliminary structures and definitions for PTP * configuration and state. * Added IP4_ADDR type. * Added Bitmask IP4_MSK_DHCP. @@ -86,7 +266,7 @@ * 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 + * 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 @@ -108,7 +288,7 @@ * Added definitions for PTP270PEX and FRC511PEX. * Revision 1.67 2008/07/17 08:54:52Z martin * Added macros to convert the endianess of structures. - * Added multiref fixed frequency source. + * 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 @@ -130,7 +310,7 @@ * Added definitions to support GPS170PEX. * Revision 1.60 2007/09/13 12:37:35Z martin * Modified and added initializers for TZDL. - * Added multiref source PTP over E1. + * Added 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. @@ -162,7 +342,7 @@ * 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 + * 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. @@ -183,7 +363,7 @@ * 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: + * 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. @@ -234,7 +414,7 @@ * 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 + * 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. @@ -256,7 +436,7 @@ * 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. + * 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 @@ -319,7 +499,7 @@ #include #endif -// CLOCK_MEINBERG is defined in NTP's config.h if configured +// 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 @@ -328,19 +508,44 @@ #endif -#if defined( _USE_PACK ) // set byte alignment - #pragma pack( 1 ) +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT #endif -/* Start of header body */ /* "magic" number */ #define MEINBERG_MAGIC 0x6AAC -#define MIN_SVNO 1 /* min. SV number */ -#define MAX_SVNO 32 /* max. SV number */ -#define N_SVNO ( MAX_SVNO - MIN_SVNO + 1) /* number of possibly active SVs */ +/** + * @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 @@ -350,29 +555,30 @@ #define GPS_EPLD_STR_SIZE ( GPS_EPLD_STR_LEN + 1 ) -#define DEFAULT_GPS_TICKS_PER_SEC 10000000L /* system time base */ +#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 + * model support the ::RECEIVER_INFO structure which contains * the actual value. */ - #define GPS_TICKS_PER_SEC DEFAULT_GPS_TICKS_PER_SEC + #define GPS_TICKS_PER_SEC DEFAULT_GPS_TICKS_PER_SEC ///< see ::DEFAULT_GPS_TICKS_PER_SEC + #endif -typedef uint16_t SVNO; /* the number of a SV */ -typedef uint16_t HEALTH; /* a SV's health code */ -typedef uint16_t CFG; /* a SV's configuration code */ -typedef uint16_t IOD; /* Issue-Of-Data code */ +typedef uint16_t SVNO; ///< the number of an SV (Space Vehicle, i.e. satellite) +typedef uint16_t HEALTH; ///< an SV's 6 bit health code +typedef uint16_t CFG; ///< an SV's 4 bit configuration code +typedef uint16_t IOD; ///< Issue-Of-Data code /* the type of various checksums */ #ifndef _CSUM_DEFINED - typedef uint16_t CSUM; + 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 ) @@ -382,9 +588,8 @@ typedef uint16_t IOD; /* Issue-Of-Data code */ /** * @brief The type of a GPS command code * - * These command codes can be passed via - * @ref gps_cmds_serial "serial port" (see @file gpsserio.h), or - * @ref gps_cmds_bus "system bus" (see @file pcpsdefs.h). + * @see ::GPS_CMD_CODES + * @see ::PC_GPS_CMD_CODES */ typedef uint16_t GPS_CMD; @@ -399,9 +604,10 @@ typedef uint16_t GPS_CMD; */ 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 */ + 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 ) \ @@ -412,7 +618,7 @@ typedef struct /** - * @defgroup bvar_stat BVAR_STAT status of buffered GPS data + * @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 @@ -424,49 +630,96 @@ typedef struct * @{ */ /** - * @brief Status flags of battery buffered data received - * from GPS satellites. + * @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 bits used with BVAR_STAT */ -enum +/** + * @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, - BVAR_BIT_ALM_NOT_COMPLETE, - BVAR_BIT_UTC_INVALID, - BVAR_BIT_IONO_INVALID, - BVAR_BIT_RCVR_POS_INVALID, - N_BVAR_BIT /**< @brief number of defined ::BVAR_STAT bits */ + BVAR_BIT_CFGH_INVALID, ///< Satellite configuration and health parameters incomplete + BVAR_BIT_ALM_NOT_COMPLETE, ///< Almanac parameters incomplete + BVAR_BIT_UTC_INVALID, ///< %UTC offset parameters incomplete + BVAR_BIT_IONO_INVALID, ///< Ionospheric correction parameters incomplete + BVAR_BIT_RCVR_POS_INVALID, ///< No valid receiver position available + N_BVAR_BIT ///< number of defined ::BVAR_STAT bits }; -#define BVAR_CFGH_INVALID ( 1UL << BVAR_BIT_CFGH_INVALID ) /**< @brief ::CFGH not valid*/ -#define BVAR_ALM_NOT_COMPLETE ( 1UL << BVAR_BIT_ALM_NOT_COMPLETE ) /**< @brief ::ALM not complete */ -#define BVAR_UTC_INVALID ( 1UL << BVAR_BIT_UTC_INVALID ) /**< @brief UTC data not valid */ -#define BVAR_IONO_INVALID ( 1UL << BVAR_BIT_IONO_INVALID ) /**< @brief IONO data not valid */ -#define BVAR_RCVR_POS_INVALID ( 1UL << BVAR_BIT_RCVR_POS_INVALID ) /**< @brief ::POS not valid */ -#define BVAR_MASK ( ( 1UL << N_BVAR_BIT ) - 1 ) /**< @brief Bit mask for all defined 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 /** - A structure used to hold a fixed frequency value. - frequ[kHz] = khz_val * 10^range -*/ + * @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 */ + 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 ) \ @@ -476,38 +729,37 @@ typedef struct } -typedef uint32_t RI_FEATURES; // type of RECEIVER_INFO::features field +/** + * @brief A data type to specify feature flags within ::RECEIVER_INFO + */ +typedef uint32_t RI_FEATURES; ///< see @ref GPS_FEATURE_MASKS + -/* - * The following code defines features and properties - * of the various GPS receivers. Older GPS receivers - * may require a recent firmvare version to support - * this, or may not support this at all. - */ - -/** - * The structure is ordered in a way that all fields - * except chars or arrays of chars are word-aligned. - */ -typedef struct -{ - uint16_t model_code; /**< identifier for receiver model */ - SW_REV sw_rev; /**< software revision and ID */ - char model_name[GPS_ID_STR_SIZE]; /**< ASCIIZ, name of receiver model */ - char sernum[GPS_ID_STR_SIZE]; /**< ASCIIZ, serial number */ - char epld_name[GPS_EPLD_STR_SIZE]; /**< ASCIIZ, file name of EPLD image */ - uint8_t n_channels; /**< number of sats to be tracked simultaneously */ - uint32_t ticks_per_sec; /**< resolution of fractions of seconds */ - RI_FEATURES features; /**< optional features, see below */ - FIXED_FREQ_INFO fixed_freq; /**< optional non-standard fixed frequency */ - uint8_t osc_type; /**< type of installed oscillator, see below */ - uint8_t osc_flags; /**< oscillator flags, see below */ - 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 below */ +/** + * @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 ) \ @@ -522,9 +774,12 @@ typedef struct /** - * Valid codes for RECEIVER_INFO.model_code: + * @brief Known device ID codes for ::RECEIVER_INFO::model_code + * + * @see @ref GPS_MODEL_NAMES + * @see ::DEFAULT_GPS_MODEL_NAMES */ -enum +enum GPS_MODEL_CODES { GPS_MODEL_UNKNOWN, GPS_MODEL_GPS166, @@ -560,20 +815,60 @@ enum 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, + GPS_MODEL_MDU300, + GPS_MODEL_SDI, + GPS_MODEL_FDM180, + GPS_MODEL_SPT, + GPS_MODEL_PZF180, + GPS_MODEL_REL1000, + GPS_MODEL_HPS100, + GPS_MODEL_VSG180, + GPS_MODEL_MSF180, + GPS_MODEL_WWVB180, + GPS_MODEL_CPC180, N_GPS_MODEL - /* If new model codes are added then care must be taken - * to update the associated string initializers below - * accordingly, and to check whether the classification macros - * also cover the new model names. */ + /* 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 @{ */ -/* - * String initializers for each of the GPS - * receiver models enum'ed above: - */ #define GPS_MODEL_NAME_UNKNOWN "(unknown)" #define GPS_MODEL_NAME_GPS166 "GPS166" #define GPS_MODEL_NAME_GPS167 "GPS167" @@ -608,13 +903,55 @@ enum #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" +#define GPS_MODEL_NAME_MDU300 "MDU300" +#define GPS_MODEL_NAME_SDI "SDI" +#define GPS_MODEL_NAME_FDM180 "FDM180" +#define GPS_MODEL_NAME_SPT "SPT" +#define GPS_MODEL_NAME_PZF180 "PZF180" +#define GPS_MODEL_NAME_REL1000 "REL1000" +#define GPS_MODEL_NAME_HPS100 "HPS100" +#define GPS_MODEL_NAME_VSG180 "VSG180" +#define GPS_MODEL_NAME_MSF180 "MSF180" +#define GPS_MODEL_NAME_WWVB180 "WWVB180" +#define GPS_MODEL_NAME_CPC180 "CPC180" + +/** @} anchor GPS_MODEL_NAMES */ -/* - * The definition below can be used to initialize - * an array of N_GPS_MODEL type name strings. - * Including the trailing 0, each name must not - * exceed GPS_ID_STR_SIZE chars. + +/** + * @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 \ { \ @@ -651,23 +988,455 @@ enum GPS_MODEL_NAME_GPS180, \ GPS_MODEL_NAME_GLN170, \ GPS_MODEL_NAME_GPS180PEX, \ - GPS_MODEL_NAME_TCR180PEX \ + 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, \ + GPS_MODEL_NAME_MDU300, \ + GPS_MODEL_NAME_SDI, \ + GPS_MODEL_NAME_FDM180, \ + GPS_MODEL_NAME_SPT, \ + GPS_MODEL_NAME_PZF180, \ + GPS_MODEL_NAME_REL1000, \ + GPS_MODEL_NAME_HPS100, \ + GPS_MODEL_NAME_VSG180, \ + GPS_MODEL_NAME_MSF180, \ + GPS_MODEL_NAME_WWVB180, \ + GPS_MODEL_NAME_CPC180 \ +} + + + +/** + * @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_SRCH_DOM // +#define GPS_MODEL_HAS_NET_STAT_DNS_SRVR // +#define GPS_MODEL_HAS_NET_STAT_DNS_SRCH_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 ) +#define BUILTIN_FEAT_MDU300 ( 0 ) +#define BUILTIN_FEAT_SDI ( 0 ) +#define BUILTIN_FEAT_FDM180 ( 0 ) +#define BUILTIN_FEAT_SPT ( 0 ) +#define BUILTIN_FEAT_PZF180 ( 0 ) +#define BUILTIN_FEAT_REL1000 ( 0 ) +#define BUILTIN_FEAT_HPS100 ( 0 ) +#define BUILTIN_FEAT_VSG180 ( 0 ) +#define BUILTIN_FEAT_MSF180 ( 0 ) +#define BUILTIN_FEAT_WWVB180 ( 0 ) +#define BUILTIN_FEAT_CPC180 ( 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 }, \ + { GPS_MODEL_MDU300, BUILTIN_FEAT_MDU300 }, \ + { GPS_MODEL_SDI, BUILTIN_FEAT_SDI }, \ + { GPS_MODEL_FDM180, BUILTIN_FEAT_FDM180 }, \ + { GPS_MODEL_SPT, BUILTIN_FEAT_SPT }, \ + { GPS_MODEL_PZF180, BUILTIN_FEAT_PZF180 }, \ + { GPS_MODEL_REL1000, BUILTIN_FEAT_REL1000 }, \ + { GPS_MODEL_HPS100, BUILTIN_FEAT_HPS100 }, \ + { GPS_MODEL_VSG180, BUILTIN_FEAT_VSG180 }, \ + { GPS_MODEL_MSF180, BUILTIN_FEAT_MSF180 }, \ + { GPS_MODEL_WWVB180, BUILTIN_FEAT_WWVB180 }, \ + { GPS_MODEL_CPC180, BUILTIN_FEAT_CPC180 }, \ + { 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 + * 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" ) ) + 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" ) ) + strstr( (_p_ri)->model_name, "MGR" ) ) #define _mbg_rcvr_is_mobile_gps( _p_ri ) \ ( strstr( (_p_ri)->model_name, "MGR" ) ) @@ -717,7 +1486,7 @@ enum #define _mbg_rcvr_is_glonass( _p_ri ) \ ( strstr( (_p_ri)->model_name, "GRC" ) || \ - ( strstr( (_p_ri)->model_name, "GLN" ) ) + strstr( (_p_ri)->model_name, "GLN" ) ) #define _mbg_rcvr_is_glonass_plug_in( _p_ri ) \ ( _mbg_rcvr_is_glonass( _p_ri ) && \ @@ -731,13 +1500,17 @@ enum _mbg_rcvr_is_plug_in( _p_ri ) ) + /** - * The classification codes for oscillators below - * are used with RECEIVER_INFO.osc_type. New codes - * must be appended to the enumeration, so the sequence - * of codes does NOT reflect the order of quality: + * @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 +enum GPS_OSC_TYPES { GPS_OSC_UNKNOWN, GPS_OSC_TCXO_LQ, @@ -749,14 +1522,19 @@ enum GPS_OSC_RUBIDIUM, GPS_OSC_TCXO_MQ, GPS_OSC_OCXO_DHQ, + GPS_OSC_OCXO_SQ, N_GPS_OSC }; -/* - * The sequence and number of oscillator names - * listed below must correspond to the enumeration - * above: +/** + * @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 \ { \ @@ -769,15 +1547,21 @@ enum "OCXO XHQ", \ "RUBIDIUM", \ "TCXO MQ", \ - "OCXO DHQ" \ + "OCXO DHQ", \ + "OCXO SQ" \ } -/* - * The initializer below can be used to initialize - * an array (e.g. "int osc_quality_idx[N_GPS_OSC]") - * which allows to display the oscillator types - * ordered by quality: +/** + * @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 \ { \ @@ -786,6 +1570,7 @@ enum 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, \ @@ -795,43 +1580,62 @@ enum -/* - * Codes to be used with RECEIVER_INFO.osc_flags - * are not yet used/required, so they are reserved - * for future use. - */ - - /** - * The codes below enumerate some features which may be - * supported by a given clock, or not. + * @brief Enumeration of device features flags reported in ::RECEIVER_INFO::features + * + * Each flags indicates if a device supports the associated feature. */ -enum +enum GPS_FEATURE_BITS { - GPS_FEAT_PPS, /**< has pulse per second output */ - GPS_FEAT_PPM, /**< has pulse per minute output */ - GPS_FEAT_SYNTH, /**< has programmable synthesizer output */ - GPS_FEAT_DCFMARKS, /**< has DCF77 compatible time mark output */ - GPS_FEAT_IRIG_TX, /**< has on-board IRIG output */ - GPS_FEAT_IRIG_RX, /**< has on-board IRIG input */ - GPS_FEAT_LAN_IP4, /**< has LAN IPv4 interface */ - GPS_FEAT_MULTI_REF, /**< has multiple input sources with priorities */ - GPS_FEAT_RCV_TIMEOUT, /**< timeout after GPS reception has stopped */ - GPS_FEAT_IGNORE_LOCK, /**< supports "ignore lock", alternatively */ - /**< MBG_OPT_BIT_EMU_SYNC may be supported */ - GPS_FEAT_5_MHZ, /**< output 5 MHz rather than 100 kHz */ - GPS_FEAT_XMULTI_REF, /**< has extended multiple input source configuration */ - GPS_FEAT_OPT_SETTINGS, /**< supports MBG_OPT_SETTINGS */ - GPS_FEAT_TIME_SCALE, /**< supports configurable time scale (UTC, TAI, GPS, ...) */ - GPS_FEAT_IRIG_CTRL_BITS, /**< supports IRIG control bits */ - GPS_FEAT_PTP, /**< has PTP support */ - GPS_FEAT_NAV_ENGINE_SETTINGS, /**< supports navigation engine configuration */ - GPS_FEAT_RAW_IRIG_DATA, /**< supports reading raw IRIG input data */ - GPS_FEAT_RAW_IRIG_TIME, /**< supports reading decoded IRIG time */ - N_GPS_FEATURE /**< the number of valid features */ + 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 + GPS_FEAT_XBP, ///< supports XBP (eXtended Binary Protocol) API and structures, see @ref group_xbp + // WARNING: There are no more unassigned feature bits available here. + // The MSB has to be reserved to indicate that a new, extended feature + // reporting scheme is supported, which still has to be defined. + + N_GPS_FEATURE ///< the number of known 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", \ @@ -852,35 +1656,69 @@ enum "PTP/IEEE1588", \ "Nav. Engine Settings", \ "Raw IRIG Data", \ - "Raw IRIG Time" \ + "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", \ + "Extended Binary Protocol" \ } -/* - * Bit masks used with RECEIVER_INFO.features - * (others are reserved): - */ -#define GPS_HAS_PPS ( 1UL << GPS_FEAT_PPS ) -#define GPS_HAS_PPM ( 1UL << GPS_FEAT_PPM ) -#define GPS_HAS_SYNTH ( 1UL << GPS_FEAT_SYNTH ) -#define GPS_HAS_DCFMARKS ( 1UL << GPS_FEAT_DCFMARKS ) -#define GPS_HAS_IRIG_TX ( 1UL << GPS_FEAT_IRIG_TX ) -#define GPS_HAS_IRIG_RX ( 1UL << GPS_FEAT_IRIG_RX ) -#define GPS_HAS_LAN_IP4 ( 1UL << GPS_FEAT_LAN_IP4 ) -#define GPS_HAS_MULTI_REF ( 1UL << GPS_FEAT_MULTI_REF ) -#define GPS_HAS_RCV_TIMEOUT ( 1UL << GPS_FEAT_RCV_TIMEOUT ) -#define GPS_HAS_IGNORE_LOCK ( 1UL << GPS_FEAT_IGNORE_LOCK ) -#define GPS_HAS_5_MHZ ( 1UL << GPS_FEAT_5_MHZ ) -#define GPS_HAS_XMULTI_REF ( 1UL << GPS_FEAT_XMULTI_REF ) -#define GPS_HAS_OPT_SETTINGS ( 1UL << GPS_FEAT_OPT_SETTINGS ) -#define GPS_HAS_TIME_SCALE ( 1UL << GPS_FEAT_TIME_SCALE ) -#define GPS_HAS_IRIG_CTRL_BITS ( 1UL << GPS_FEAT_IRIG_CTRL_BITS ) -#define GPS_HAS_PTP ( 1UL << GPS_FEAT_PTP ) -#define GPS_HAS_NAV_ENGINE_SETTINGS ( 1UL << GPS_FEAT_NAV_ENGINE_SETTINGS ) -#define GPS_HAS_RAW_IRIG_DATA ( 1UL << GPS_FEAT_RAW_IRIG_DATA ) -#define GPS_HAS_RAW_IRIG_TIME ( 1UL << GPS_FEAT_RAW_IRIG_TIME ) - -#define GPS_HAS_REF_OFFS GPS_HAS_IRIG_RX +/** + * @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 +#define GPS_HAS_XBP ( 1UL << GPS_FEAT_XBP ) ///< see ::GPS_FEAT_XBP + +// 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 */ /* @@ -896,16 +1734,32 @@ enum } -/* - * Codes to be used with RECEIVER_INFO::flags: +/** + * @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 */ -#define GPS_OSC_CFG_SUPP 0x0001 // GPS_OSC_CFG supported -#define GPS_IRIG_FO_IN 0x0002 // IRIG input via fiber optics -#define GPS_HAS_FPGA 0x0004 // device provides on-board FPGA +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 + * 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 @@ -941,6 +1795,7 @@ 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 @@ -953,19 +1808,29 @@ typedef struct -/** - Date and time referred to the linear time scale defined by GPS. - GPS time is defined by the number of weeks since midnight from - January 5, 1980 to January 6, 1980 plus the number of seconds of - the current week plus fractions of a second. GPS time differs from - UTC because UTC is corrected with leap seconds while GPS time scale - is continuous. -*/ +/** + * @brief A structure used to hold time in GPS format + * + * Date and time refer to the linear time scale defined by GPS, with + * the epoch starting at %UTC midnight at the beginning of January 6, 1980. + * + * GPS time is counted by the week numbers since the epoch, plus second + * of the week, plus fraction of the second. The week number transmitted + * by the satellites rolls over from 1023 to 0, but Meinberg devices + * just continue to count the weeks beyond the 1024 week limit to keep + * the receiver's internal time. + * + * %UTC time differs from GPS time since a number of leap seconds have + * been inserted in the %UTC time scale after the GPS epoche. The number + * of leap seconds is disseminated by the satellites using the ::UTC + * parameter set, which also provides info on pending leap seconds. + */ typedef struct { - uint16_t wn; /**< the week number since GPS has been installed */ - uint32_t sec; /**< the second of that week */ - uint32_t tick; /**< fractions of a second; scale: 1/GPS_TICKS_PER_SEC */ + 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 ) \ @@ -977,26 +1842,32 @@ typedef struct /** - 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, see below) defined - by the user. The status field can be checked to see which corrections - have been applied. -*/ + * @brief Local date and time computed from GPS time + * + * The current number of leap seconds have to be added to get %UTC + * from GPS time. Additional corrections could have been made according + * to the time zone/daylight saving parameters ::TZDL defined by the user. + * The status field can be checked to see which corrections + * have actually been applied. + * + * @note Conversion from GPS time to %UTC and/or local time can only be + * done if some valid ::UTC correction parameters are available in the + * receiver's non-volatile memory. + */ typedef struct { - int16_t year; /**< year number, 0..9999 */ - int8_t month; /**< month, 1..12 */ - int8_t mday; /**< day of month, 1..31 */ - int16_t yday; /**< day of year, 1..366 */ - int8_t wday; /**< day of week, 0..6 == Sun..Sat */ - int8_t hour; /**< hours, 0..23 */ - int8_t min; /**< minutes, 0..59 */ - int8_t sec; /**< seconds, 0..59 */ - int32_t frac; /**< fractions of a second; scale: 1/GPS_TICKS_PER_SEC */ - int32_t offs_from_utc; /**< local time's offset from UTC */ - uint16_t status; /**< status flags */ + 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 offset from %UTC [sec] + uint16_t status; ///< status flags, see ::TM_GPS_STATUS_BIT_MASKS + } TM_GPS; #define _mbg_swab_tm_gps( _p ) \ @@ -1009,76 +1880,105 @@ typedef struct } -/* status flag bits used with conversion from GPS time to local time */ - -enum +/** + * @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 */ - TM_BIT_DL_ANN, /* state of daylight saving is going to change */ - TM_BIT_DL_ENB, /* daylight saving is enabled */ - TM_BIT_LS_ANN, /* leap second will be inserted */ - TM_BIT_LS_ENB, /* current second is leap second */ - TM_BIT_LS_ANN_NEG, /* set in addition to TM_LS_ANN if leap sec negative */ - TM_BIT_INVT, /* invalid time, e.g. if RTC battery empty */ - - TM_BIT_EXT_SYNC, /* sync'd externally */ - TM_BIT_HOLDOVER, /* holdover mode after previous sync. */ - 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 */ -}; - -// Type of an extended TM status which is mainly used by the firmware. -typedef uint32_t TM_STATUS_EXT; // extended status, mainly used by the firmware - -// The lower 16 bits of the TM_STATUS_X type correspond to those defined above, -// and the upper bits are defined below: -enum + 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_BIT_SCALE_GPS = 16, - TM_BIT_SCALE_TAI - // the remaining bits are reserved + 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 }; -/* bit masks corresponding to the flag bits above */ -#define TM_UTC ( 1UL << TM_BIT_UTC ) -#define TM_LOCAL ( 1UL << TM_BIT_LOCAL ) -#define TM_DL_ANN ( 1UL << TM_BIT_DL_ANN ) -#define TM_DL_ENB ( 1UL << TM_BIT_DL_ENB ) -#define TM_LS_ANN ( 1UL << TM_BIT_LS_ANN ) -#define TM_LS_ENB ( 1UL << TM_BIT_LS_ENB ) -#define TM_LS_ANN_NEG ( 1UL << TM_BIT_LS_ANN_NEG ) -#define TM_INVT ( 1UL << TM_BIT_INVT ) +/** + * @brief Type of an extended TM status which is mainly used inside the firmware + */ +typedef uint32_t TM_STATUS_EXT; -#define TM_EXT_SYNC ( 1UL << TM_BIT_EXT_SYNC ) -#define TM_HOLDOVER ( 1UL << TM_BIT_HOLDOVER ) -#define TM_ANT_SHORT ( 1UL << TM_BIT_ANT_SHORT ) -#define TM_NO_WARM ( 1UL << TM_BIT_NO_WARM ) -#define TM_ANT_DISCONN ( 1UL << TM_BIT_ANT_DISCONN ) -#define TM_SYN_FLAG ( 1UL << TM_BIT_SYN_FLAG ) -#define TM_NO_SYNC ( 1UL << TM_BIT_NO_SYNC ) -#define TM_NO_POS ( 1UL << TM_BIT_NO_POS ) +/** + * @brief 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: +// 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 ) + /** - This structure is used to transmit information on date and time + * @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 time; 0, 1: capture 0, 1 */ - T_GPS t; /**< time in GPS format */ - TM_GPS tm; /**< that time converted to local time */ + 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 ) \ @@ -1090,10 +1990,24 @@ typedef struct +/** + * @brief A timestamp with nanosecond resolution + * + * @note The secs field will roll over on 2038-01-19 03:14:07 + * if used for the number of seconds since 1970-01-01, just like + * 32 bit POSIX time_t. + * + * @see ::NANO_TIME_64 + */ typedef struct { - int32_t nano_secs; // [nanoseconds] - int32_t secs; // [seconds] + // ATTENTION: + // This structure is and has has been used in public API calls for a long time, + // so even though the order of member fields is different than in NANO_TIME_64 + // this must *NOT* be changed, or API compatibility will get lost! + int32_t nano_secs; ///< [nanoseconds] + int32_t secs; ///< [seconds] + } NANO_TIME; #define _mbg_swab_nano_time( _p ) \ @@ -1102,24 +2016,48 @@ typedef struct _mbg_swab32( &(_p)->secs ); \ } -// The macro below checks if a NANO_TIME value is negative. +// The macro below checks if a ::NANO_TIME value is negative. #define _nano_time_negative( _nt ) \ ( ( (_nt)->secs < 0 ) || ( (_nt)->nano_secs < 0 ) ) -/* Two types of variables used to store a position. Type XYZ is */ -/* used with a position in earth centered, earth fixed (ECEF) */ -/* coordinates whereas type LLA holds such a position converted */ -/* to geographic coordinates as defined by WGS84 (World Geodetic */ -/* System from 1984). */ +/** + * @brief A timestamp with nanosecond resolution, but 64 bit size + * + * @see ::NANO_TIME + */ +typedef struct +{ + // ATTENTION: + // This structure is and has been used in public API calls for a long time, + // so even though the order of member fields is different than in NANO_TIME + // this must *NOT* be changed, or API compatibility will get lost! + uint64_t secs; ///< [seconds] + uint64_t nano_secs; ///< [nanoseconds] + +} NANO_TIME_64; + +#define _mbg_swab_nano_time_64( _p ) \ +{ \ + _mbg_swab64( &(_p)->secs ); \ + _mbg_swab64( &(_p)->nano_secs ); \ +} + + #ifndef _XYZ_DEFINED - /* sequence and number of components of a cartesian position */ - enum { XP, YP, ZP, N_XYZ }; + /** + * @brief Sequence and number of components of a cartesian position + */ + enum XYZ_FIELDS { XP, YP, ZP, N_XYZ }; // x, y, z - /** a type of array holding a cartesian position */ - typedef double XYZ[N_XYZ]; /**< values are in [m] */ + /** + * @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 @@ -1128,11 +2066,20 @@ typedef struct #ifndef _LLA_DEFINED - /* sequence and number of components of a geographic position */ - enum { LAT, LON, ALT, N_LLA }; /* latitude, longitude, altitude */ - - /** a type of array holding a geographic position */ - typedef double LLA[N_LLA]; /**< lon, lat in [rad], alt in [m] */ + /** + * @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 @@ -1141,67 +2088,74 @@ typedef struct /** - @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:
- 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:
- If freq == 0 the synthesizer is disabled. If range == 0 the least - significant digit of freq is limited to 0, 3, 5 or 6. The resulting - frequency is shown in the examples below: - - freq == 1230 --> 123.0 Hz - - freq == 1233 --> 123 1/3 Hz (real 1/3 Hz, NOT 123.3 Hz) - - freq == 1235 --> 123.5 Hz - - freq == 1236 --> 123 2/3 Hz (real 2/3 Hz, NOT 123.6 Hz) - - If range == MAX_RANGE the value of freq must not exceed 1000, so the - output frequency is limited to 10 MHz. - @{ -*/ + * @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:
+ * 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:
+ * 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 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 N_SYNTH_PHASE_DIGIT 4 +#define MAX_SYNTH_PHASE 3600 + +#define MAX_SYNTH_FREQ_EDIT 9999 ///< max sequence of digits when editing -#define MAX_SYNTH_FREQ_EDIT 9999 /**< max sequence of digits when editing */ -/** The maximum frequency that can be configured for the synthesizer */ -#define MAX_SYNTH_FREQ_VAL 10000000UL /**< 10 MHz */ +/** + * @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) */ -/** - The synthesizer phase will only be synchronized if the frequency - is below this limit: */ -#define SYNTH_PHASE_SYNC_LIMIT 10000UL /**< 10 kHz */ +/** + * @brief The synthesizer's phase is only be synchronized if the frequency is below this limit + */ +#define SYNTH_PHASE_SYNC_LIMIT 10000UL ///< 10 kHz -/** - the position of the decimal point if the frequency is - printed as 4 digit value */ +/** + * 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 ) -/** - An initializer for commonly displayed synthesizer frequency units - (N_SYNTH_RANGE strings) */ +/** + * @brief Synthesizer frequency units + * + * An initializer for commonly displayed synthesizer frequency units + * (::N_SYNTH_RANGE strings) + */ #define DEFAULT_FREQ_RANGES \ { \ "Hz", \ @@ -1214,11 +2168,15 @@ typedef struct +/** + * @brief Synthesizer configuration parameters + */ typedef struct { - int16_t freq; /**< four digits used; scale: 0.1; e.g. 1234 -> 123.4 Hz */ - int16_t range; /**< scale factor for freq; 0..MAX_SYNTH_RANGE */ - int16_t phase; /**< -MAX_SYNTH_PHASE..+MAX_SYNTH_PHASE; >0 -> pulses later */ + 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 ) \ @@ -1229,57 +2187,81 @@ typedef struct } -/** - The definitions below can be used to query the - current synthesizer state. +/** + * @brief Enumeration of synthesizer states */ -enum +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 */ + 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 above */ - uint8_t flags; /**< reserved, currently always 0 */ + 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 -/** @} */ // endgroup +/** @} defgroup group_synth */ -/** - @defgroup group_tzdl Time zone/daylight saving parameters - Example:
- For automatic daylight saving enable/disable in Central Europe, - the variables are to be set as shown below:
- - 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 - @{ -*/ -/** the name of a time zone, 5 characters plus trailing zero */ +/** + * @defgroup group_tzdl Time zone / daylight saving parameters + * + * Example:
+ * For automatic daylight saving enable/disable in Central Europe, + * the variables are to be set as shown below:
+ * - 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]; -typedef struct -{ - int32_t offs; /**< 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 */ +/** + * @brief Time zone / daylight saving parameters + * + * This structure is used to specify how a device converts on-board %UTC + * to local time, including computation of beginning and end of daylight + * saving time (DST), if required. + * + * @note The ::TZDL structure contains members of type ::TM_GPS to specify + * the times for beginning and end of DST. However, the ::TM_GPS::frac, + * ::TM_GPS::offs_from_utc, and ::TM_GPS::status fields of these ::TZDL::tm_on + * and ::TZDL::tm_off members are ignored for the conversion to local time, + * and thus should be 0. + */ +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 ) \ @@ -1292,8 +2274,10 @@ typedef struct /** - If the year in tzdl.tm_on and tzdl.tm_off is or'ed with that constant, - the receiver automatically generates daylight saving year by year. + * @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 @@ -1303,18 +2287,18 @@ typedef struct #define DEFAULT_TZDL_AUTO_YEAR ( 2007 | DL_AUTO_FLAG ) -#define DEFAULt_TZDL_OFFS_DL 3600L /**< usually DST is +1 hour */ +#define DEFAULt_TZDL_OFFS_DL 3600L ///< usually DST is +1 hour -/** - The symbol below can be used to initialize both the tm_on - and tm_off fields for time zones which do not switch to DST: +/** + * 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: +// Settings used with %UTC: #define TZ_INFO_UTC "UTC (Universal Time, Coordinated)" @@ -1322,22 +2306,23 @@ typedef struct #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[] */ \ + 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 */ \ } -/** - The symbols below specify beginning and end of DST for - Central Europe, as constituted by the European Parliament: - */ - +/** + * @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 } @@ -1347,27 +2332,27 @@ typedef struct #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_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[] */ \ + 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[] */ \ + 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 */ \ } @@ -1386,8 +2371,8 @@ typedef struct #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_NAMES_EET_EEST_EN { "EET ", "EEST " } +#define DEFAULT_TZDL_NAMES_EET_EEST_DE { "OEZ ", "OESZ " } #define DEFAULT_TZDL_OFFS_EET 7200L @@ -1397,7 +2382,7 @@ typedef struct 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[] */ \ + DEFAULT_TZDL_NAMES_EET_EEST_EN /* name */ \ } #define DEFAULT_TZDL_EET_EEST_DE \ @@ -1406,22 +2391,35 @@ typedef struct 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[] */ \ + DEFAULT_TZDL_NAMES_EET_EEST_DE /* name */ \ } -/** @} */ // endgroup +/** @} defgroup group_tzdl */ + + /** - * The structure below reflects the status of the antenna, + * @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 after the disconnection interval. + * 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 and 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 */ - 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 #GPS_TICKS_PER_SEC */ + 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 ) \ @@ -1433,39 +2431,36 @@ typedef struct } -/** - The status field may be set to one of the values below: -*/ -enum +/** + * @brief Status code used with ::ANT_INFO::status + */ +enum ANT_STATUS_CODES { - ANT_INVALID, /**< struct not set yet because ant. has not been disconn. */ - ANT_DISCONN, /**< ant. now disconn., tm_reconn and delta_t not set */ - ANT_RECONN /**< ant. has been disconn. and reconn., all fields valid */ + ANT_INVALID, ///< No other fields valid since antenna has not yet been disconnected + ANT_DISCONN, ///< Antenna is disconnected, tm_reconn and delta_t not yet set + ANT_RECONN, ///< Antenna has been disconnect, and receiver sync. after reconnect, so all fields valid + N_ANT_STATUS_CODES ///< the number of known status codes }; -/* Defines used with ENABLE_FLAGS */ - -#define EF_OFF 0x00 /**< outputs off until sync'd */ -#define EF_SERIAL_BOTH 0x03 /**< both serial ports on */ -#define EF_PULSES_BOTH 0x03 /**< both pulses P_SEC and P_MIN on */ -#define EF_FREQ_ALL 0x07 /**< all fixed freq. outputs on */ -#define EF_SYNTH 0x01 /**< synth. on */ -/** - The structure holds some flags which let - the corresponding outputs be disabled after power-up until - the receiver has synchronized (flag == 0x00, 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 the code for freq must always be 0x03. -*/ +/** + * @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 */ + 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 ) \ @@ -1477,25 +2472,53 @@ typedef struct } -/* A struct used to hold the settings of a serial port: */ +/** + * @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 - /* types of handshake */ - enum { HS_NONE, HS_XONXOFF, HS_RTSCTS, N_COM_HS }; + /** + * @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; - /* indices used to identify a parameter in the framing string */ - enum { F_DBITS, F_PRTY, F_STBITS }; + /** + * @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; /* e.g. 19200L */ - char framing[4]; /* e.g. "8N1" */ - int16_t handshake; /* a numeric value, only HS_NONE supported yet */ + 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 @@ -1510,12 +2533,15 @@ typedef struct } -/* - * Indices of any supported baud rates. - * Note that not each baud rate must be supported by - * any clock model and/or port: +/** + * @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 +enum MBG_BAUD_RATE_CODES { MBG_BAUD_RATE_300, MBG_BAUD_RATE_600, @@ -1525,12 +2551,23 @@ enum MBG_BAUD_RATE_9600, MBG_BAUD_RATE_19200, MBG_BAUD_RATE_38400, - N_MBG_BAUD_RATES /* the number of supported baud rates */ + 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 }; -/* - * An initializer for a table of baud rate values. - * The values must correspond to the enumeration above. +/** + * @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 \ { \ @@ -1541,12 +2578,20 @@ enum 4800L, \ 9600L, \ 19200L, \ - 38400L \ + 38400L, \ + 57600L, \ + 115200L, \ + 230400L, \ + 460800L, \ + 921600L \ } -/* - * An initializer for a table of baud rate strings. - * The values must correspond to the enumeration above. +/** + * @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 \ { \ @@ -1557,32 +2602,49 @@ enum "4800", \ "9600", \ "19200", \ - "38400" \ + "38400", \ + "57600", \ + "115200", \ + "230400", \ + "460800", \ + "921600" \ } -/* - * The bit masks below can be used to determine which baud rates - * are supported by a serial port. This may vary between - * different ports of the same radio clock since different - * types of UART are used which must not necessarily support - * each baud rate: - */ -#define MBG_PORT_HAS_300 ( 1UL << MBG_BAUD_RATE_300 ) -#define MBG_PORT_HAS_600 ( 1UL << MBG_BAUD_RATE_600 ) -#define MBG_PORT_HAS_1200 ( 1UL << MBG_BAUD_RATE_1200 ) -#define MBG_PORT_HAS_2400 ( 1UL << MBG_BAUD_RATE_2400 ) -#define MBG_PORT_HAS_4800 ( 1UL << MBG_BAUD_RATE_4800 ) -#define MBG_PORT_HAS_9600 ( 1UL << MBG_BAUD_RATE_9600 ) -#define MBG_PORT_HAS_19200 ( 1UL << MBG_BAUD_RATE_19200 ) -#define MBG_PORT_HAS_38400 ( 1UL << MBG_BAUD_RATE_38400 ) +/** + * @brief 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 +}; -/* - * Indices of any supported framings. - * Note that not each framing must be supported by - * any clock model and/or port: +/** + * @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 +enum MBG_FRAMING_CODES { MBG_FRAMING_7N2, MBG_FRAMING_7E1, @@ -1593,12 +2655,21 @@ enum MBG_FRAMING_7O1, MBG_FRAMING_7O2, MBG_FRAMING_8O1, - N_MBG_FRAMINGS /* the number of supported framings */ + MBG_FRAMING_8E2, ///< Note: most serial ports don't support this! + N_MBG_FRAMINGS ///< the number of known framings }; -/* - * An initializer for a table of framing strings. - * The values must correspond to the enumeration above. +/** + * @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 \ { \ @@ -1610,25 +2681,80 @@ enum "8E1", \ "7O1", \ "7O2", \ - "8O1" \ + "8O1", \ + "8E2" \ } -/* - * The bit masks below can be used to determine which framings - * are supported by a serial port. This may vary between - * different ports of the same radio clock since different - * types of UART are used which must not necessarily support - * each framing type: +/** + * @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_PORT_HAS_7N2 ( 1UL << MBG_FRAMING_7N2 ) -#define MBG_PORT_HAS_7E1 ( 1UL << MBG_FRAMING_7E1 ) -#define MBG_PORT_HAS_7E2 ( 1UL << MBG_FRAMING_7E2 ) -#define MBG_PORT_HAS_8N1 ( 1UL << MBG_FRAMING_8N1 ) -#define MBG_PORT_HAS_8N2 ( 1UL << MBG_FRAMING_8N2 ) -#define MBG_PORT_HAS_8E1 ( 1UL << MBG_FRAMING_8E1 ) -#define MBG_PORT_HAS_7O1 ( 1UL << MBG_FRAMING_7O1 ) -#define MBG_PORT_HAS_7O2 ( 1UL << MBG_FRAMING_7O2 ) -#define MBG_PORT_HAS_8O1 ( 1UL << MBG_FRAMING_8O1 ) +#define MBG_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 */ @@ -1685,17 +2811,19 @@ enum ) -/* - * The structure below is more flexible if different receiver - * models have different numbers of serial ports, so the old - * structure PORT_PARM will become obsolete. +/** + * @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; /* speed, framing, etc. */ - uint8_t mode; /* per second, per minute, etc. */ - uint8_t str_type; /* type of the output string */ - uint32_t flags; /* reserved for future use, currently 0 */ + 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 ) \ @@ -1705,59 +2833,81 @@ typedef struct } -/* - * The definitions below can be used to mark specific fields of a - * PORT_SETTINGS structure, e.g. when editing build a mask indicating - * which of the fields have changed or which are not valid. +/** + * @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 +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 */ + MBG_PS_BIT_BAUD_RATE_OVR_SW, ///< Baud rate index exceeds num supp by driver SW + MBG_PS_BIT_BAUD_RATE_OVR_DEV, ///< Baud rate index exceeds num supp by device + MBG_PS_BIT_BAUD_RATE, ///< Baud rate not supp by given port + MBG_PS_BIT_FRAMING_OVR_SW, ///< Framing index exceeds num supp by driver SW + MBG_PS_BIT_FRAMING_OVR_DEV, ///< Framing index exceeds num supp by device + MBG_PS_BIT_FRAMING, ///< Framing not supp by given port + MBG_PS_BIT_HS_OVR_SW, ///< Handshake index exceeds num supp by driver SW + MBG_PS_BIT_HS, ///< Handshake mode not supp by given port + MBG_PS_BIT_STR_TYPE_OVR_SW, ///< String type index exceeds num supp by driver SW + MBG_PS_BIT_STR_TYPE_OVR_DEV, ///< String type index exceeds num supp by device + MBG_PS_BIT_STR_TYPE, ///< String type not supp by given port + MBG_PS_BIT_STR_MODE_OVR_SW, ///< String mode index exceeds num supp by driver SW + MBG_PS_BIT_STR_MODE_OVR_DEV, ///< String mode index exceeds num supp by device + MBG_PS_BIT_STR_MODE, ///< String mode not supp by given port and string type + MBG_PS_BIT_FLAGS_OVR_SW, ///< Flags not supp by driver SW + MBG_PS_BIT_FLAGS, ///< Flags not supp by device N_MBG_PS_BIT }; -#define MBG_PS_MSK_BAUD_RATE_OVR_SW ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_SW ) -#define MBG_PS_MSK_BAUD_RATE_OVR_DEV ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_DEV ) -#define MBG_PS_MSK_BAUD_RATE ( 1UL << MBG_PS_BIT_BAUD_RATE ) -#define MBG_PS_MSK_FRAMING_OVR_SW ( 1UL << MBG_PS_BIT_FRAMING_OVR_SW ) -#define MBG_PS_MSK_FRAMING_OVR_DEV ( 1UL << MBG_PS_BIT_FRAMING_OVR_DEV ) -#define MBG_PS_MSK_FRAMING ( 1UL << MBG_PS_BIT_FRAMING ) -#define MBG_PS_MSK_HS_OVR_SW ( 1UL << MBG_PS_BIT_HS_OVR_SW ) -#define MBG_PS_MSK_HS ( 1UL << MBG_PS_BIT_HS ) -#define MBG_PS_MSK_STR_TYPE_OVR_SW ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_SW ) -#define MBG_PS_MSK_STR_TYPE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_DEV ) -#define MBG_PS_MSK_STR_TYPE ( 1UL << MBG_PS_BIT_STR_TYPE ) -#define MBG_PS_MSK_STR_MODE_OVR_SW ( 1UL << MBG_PS_BIT_STR_MODE_OVR_SW ) -#define MBG_PS_MSK_STR_MODE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_MODE_OVR_DEV ) -#define MBG_PS_MSK_STR_MODE ( 1UL << MBG_PS_BIT_STR_MODE ) -#define MBG_PS_MSK_FLAGS_OVR_SW ( 1UL << MBG_PS_BIT_FLAGS_OVR_SW ) -#define MBG_PS_MSK_FLAGS ( 1UL << MBG_PS_BIT_FLAGS ) +/** + * @brief 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 */ -/* - * The structure below adds an index number to the structure - * above to allow addressing of several instances: + + +/** + * @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; /* 0..RECEIVER_INFO.n_com_port-1 */ + 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 ) \ @@ -1767,21 +2917,24 @@ typedef struct } -/* - * The structure below holds the current settings - * for a port, plus additional informaton on the - * port's capabilities. This can be read by setup - * programs to allow setup of supported features - * only. +/** + * @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; /* COM port settings as defined above */ - uint32_t supp_baud_rates; /* bit mask of baud rates supp. by this port */ - uint32_t supp_framings; /* bit mask of framings supp. by this port */ - uint32_t supp_str_types; /* bit mask, bit 0 set if str_type[0] supp. */ - uint32_t reserved; /* reserved for future use, currently 0 */ - uint32_t flags; /* reserved for future use, currently 0 */ + 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 ) \ @@ -1795,14 +2948,47 @@ typedef struct } -/* - * The structure below adds an index number to the structure - * above to allow addressing of several instances: +/** + * @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; /* 0..RECEIVER_INFO.n_com_port-1 */ + 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 ) \ @@ -1812,17 +2998,25 @@ typedef struct } -/* - * The structure below keeps information for a given - * string type, e.g. which modes can be used with that - * string type: +/** + * @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. with this string type */ - char long_name[23]; /* long name of the string format */ - char short_name[11]; /* short name of the string format */ - uint16_t flags; /* reserved, currently always 0 */ + 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 ) \ @@ -1833,14 +3027,22 @@ typedef struct -/* - * The structure below adds an index number to the structure - * above to allow addressing of several instances: +/** + * @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; /* 0..RECEIVER_INFO.n_str_type-1 */ + 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 ) \ @@ -1850,22 +3052,49 @@ typedef struct } -/* - * The codes below define valid modes for time strings, - * i.e. the condition when a string is being sent - * via the serial port: +/** + * @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 +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 { - STR_ON_REQ, /* on request only */ - STR_PER_SEC, /* automatically if second changes */ - STR_PER_MIN, /* automatically if minute changes */ - STR_AUTO, /* automatically if required, e.g. on capture event */ - STR_ON_REQ_SEC, /* if second changes and a request has been received */ - N_STR_MODE /* the number of valid modes */ + 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 \ { \ "'?'", \ @@ -1876,9 +3105,12 @@ enum } -/* - * Default initializers for English mode string names. Initializers - * for multi-language strings can be found in pcpslstr.h. +/** + * @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" @@ -1886,6 +3118,14 @@ enum #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, \ @@ -1895,17 +3135,6 @@ enum ENG_MODE_NAME_STR_ON_REQ_SEC \ } -/* - * The definitions below are used to set up bit masks - * which restrict the modes which can be used with - * a given string type: - */ -#define MSK_STR_ON_REQ ( 1UL << STR_ON_REQ ) -#define MSK_STR_PER_SEC ( 1UL << STR_PER_SEC ) -#define MSK_STR_PER_MIN ( 1UL << STR_PER_MIN ) -#define MSK_STR_AUTO ( 1UL << STR_AUTO ) -#define MSK_STR_ON_REQ_SEC ( 1UL << STR_ON_REQ_SEC ) - /* * The modes below are supported by most string types: @@ -1929,9 +3158,11 @@ enum -/** - * The number of serial ports which were available - * with all GPS receiver models: +/* + * 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 @@ -1944,13 +3175,16 @@ enum #endif /** - * The structure used to store the modes of both serial ports:
- * (now obsolete) + * @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 */ + 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 ) \ @@ -1964,10 +3198,14 @@ typedef struct } -/* - * The codes below were used with the obsolete - * PORT_PARM.mode above. They are defined for - * compatibility with older devices only: +/** + * @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 { @@ -1983,75 +3221,91 @@ enum /** - @defgroup group_icode IRIG Codes - - The following definitions are used to configure an optional - on-board IRIG input or output. Which frame types are supported - by a device depends on the device type, and may eventually - depend on the device's firmware version. - - All IRIG frames transport the day-of-year number plus the time-of-day, - and include a control field segment which can transport user defined - information. - - Some newer IRIG frames are compatible with older frame types but support - well defined extensions like the year number, local time offset, DST status, - etc., in the control fields: - - - Supported IRIG signal code types: - - \b A002: 1000 bps, DCLS, time-of-year - - \b A003: 1000 bps, DCLS, time-of-year, SBS - - \b A132: 1000 bps, 10 kHz carrier, time-of-year - - \b A133: 1000 bps, 10 kHz carrier, time-of-year, SBS - - \b B002: 100 bps, DCLS, time-of-year - - \b B003: 100 bps, DCLS, time-of-year, SBS - - \b B122: 100 bps, 1 kHz carrier, time-of-year - - \b B123: 100 bps, 1 kHz carrier, time-of-year, SBS - - \b B006: 100 bps, DCLS, complete date - - \b B007: 100 bps, DCLS, complete date, SBS - - \b B126: 100 bps, 1 kHz carrier, complete date - - \b B127: 100 bps, 1 kHz carrier, complete date, SBS - - \b B220/1344: 100 bps, DCLS, manchester encoded, IEEE1344 extensions - - \b B222: 100 bps, DCLS, manchester encoded, time-of-year - - \b B223: 100 bps, DCLS, manchester encoded, time-of-year, SBS - - \b G002: 10 kbps, DCLS, time-of-year - - \b G142: 10 kbps, 100 kHz carrier, time-of-year - - \b G006: 10 kbps, DCLS, complete date - - \b G146: 10 kbps, 100 kHz carrier, complete date - - \b AFNOR: 100 bps, 1 kHz carrier, SBS, complete date - - AFNOR DC: 100 bps, DCLS, SBS, complete date - - \b IEEE1344: 100 bps, 1 kHz carrier, time-of-year, SBS, IEEE1344 extensions (B120) - - IEEE1344 DC: 100 bps, DCLS, time-of-year, SBS, IEEE1344 extensions (B000) - - \b C37.118: like IEEE1344, but UTC offset with reversed sign - - \b C37.118 DC: like IEEE1344 DC, but UTC offset with reversed sign - - - time-of-year: day-of-year, hours, minutes, seconds - - complete date: time-of-year plus year number - - SBS: straight binary seconds, second-of-day - - AFNOR codes are based on the french standard AFNOR NF S87-500 - - IEEE1344 codes are defined in IEEE standard 1344-1995. The code frame is compatible - with B002/B122 but provides some welldefined extensions in the control field which - include a quality indicator (time figure of merit, TFOM), year number, DST and leap - second status, and local time offset from UTC. - - C37.118 codes are defined in IEEE standard C37.118-2005 which includes a revised version - of the IEEE1344 standard from 1995. These codes provide the same extensions as IEEE1344 - but unfortunately define the UTC offset with reversed sign. - - ATTENTION: There are 3rd party IRIG devices out there which apply the UTC offset - as specified in C37.118, but claim to be compatible with IEEE1344. So if local time is - transmitted in the IRIG signal then care must be taken that the UTC offset is evaluated - by the IRIG receiver in the same way as output by the IRIG generator. Otherwise the UTC - time computed by the receiver may be wrong. - @{ - */ - -/** - * Definitions used with IRIG transmitters which usually output both - * the unmodulated and the modulated IRIG signals at the same time: */ -enum + * @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:
+ * IEEE 1344: (IRIG time 14:43:27 h) - (offs -6 h) = (UTC 20:43:27)
+ * IEEE C37.118: (IRIG time 14:43:27 h) + (offs -6 h) = (UTC 08:43:27)
+ * + * @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 wrong. + * + * @{ */ + +/** + * @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, @@ -2059,20 +3313,25 @@ enum 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_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, - N_ICODE_TX /**< number of code types */ + ICODE_TX_TXC101, + ICODE_TX_E002_E112, + ICODE_TX_NASA36, + N_ICODE_TX ///< number of known codes }; /** - * Initializers for format name strings. + * @brief Initializers for timecode format name strings + * + * @see ::ICODE_TX_CODES */ #define DEFAULT_ICODE_TX_NAMES \ { \ @@ -2089,12 +3348,18 @@ enum "B007+B127", \ "G002+G142", \ "G006+G146", \ - "C37.118" \ + "C37.118", \ + "TXC-101 DTR-6", \ + "E002+E112", \ + "NASA 36" \ } /** - * Initializers for short name strings which must not - * be longer than 10 printable characters. + * @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 \ { \ @@ -2102,7 +3367,7 @@ enum "B003+B123", \ "A002+A132", \ "A003+A133", \ - "AFNOR NF-S", \ + "AFNOR NF S", \ "IEEE1344", \ "B220/1344", \ "B222 DC", \ @@ -2111,12 +3376,17 @@ enum "B007+B127", \ "G002+G142", \ "G006+G146", \ - "C37.118" \ + "C37.118", \ + "TXC-101", \ + "E002+E112", \ + "NASA 36" \ } /** - * Initializers for English format description strings. + * @brief Initializers for English format description strings + * + * @see ::ICODE_TX_CODES */ #define DEFAULT_ICODE_TX_DESCRIPTIONS_ENG \ { \ @@ -2133,14 +3403,24 @@ enum "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" \ + "like IEEE1344, but UTC offset with reversed sign", \ + "code from TV time sync device TXC-101 DTR-6", \ + "10 bps, DCLS or 100 Hz carrier", \ + "100 bps, DCLS or 1 kHz carrier" \ } -/* - * The definitions below are used to set up bit masks - * which restrict the IRIG formats which are supported - * by a given IRIG transmitter device: - */ + +/** + * @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 ) @@ -2155,19 +3435,33 @@ enum #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 */ + /** - * A mask of IRIG formats with manchester encoded DC output: + * @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_B2201344 | \ + MSK_ICODE_TX_B222 | \ MSK_ICODE_TX_B223 \ ) /** - * A mask of IRIG formats with 1 kHz carrier: + * @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 \ ( \ @@ -2180,11 +3474,12 @@ enum MSK_ICODE_TX_B223 | \ MSK_ICODE_TX_B006_B126 | \ MSK_ICODE_TX_B007_B127 | \ - MSK_ICODE_TX_C37118 \ + MSK_ICODE_TX_C37118 | \ + MSK_ICODE_TX_NASA36 \ ) /** - * A mask of IRIG formats with 10 kHz carrier: + * @brief A mask of IRIG formats with 10 kHz carrier */ #define MSK_ICODE_TX_10KHZ \ ( \ @@ -2193,74 +3488,170 @@ enum ) /** - * A mask of IRIG formats with 100 kHz carrier: + * @brief A mask of IRIG formats with 100 kHz carrier */ #define MSK_ICODE_TX_100KHZ \ ( \ - MSK_ICODE_TX_G002_G142 | \ + MSK_ICODE_TX_G002_G142 | \ MSK_ICODE_TX_G006_G146 \ ) /** - * A mask of IRIG formats with 100 bps data rate: + * @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_B002_B122 | \ + MSK_ICODE_TX_B003_B123 | \ + MSK_ICODE_TX_AFNOR | \ + MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_B006_B126 | \ + MSK_ICODE_TX_B007_B127 | \ MSK_ICODE_TX_C37118 \ ) /** - * A mask of IRIG formats with 1000 bps data rate: + * @brief A mask of IRIG formats with 1000 bps data rate */ #define MSK_ICODE_TX_1000BPS \ ( \ - MSK_ICODE_TX_A002_A132 | \ + MSK_ICODE_TX_A002_A132 | \ MSK_ICODE_TX_A003_A133 \ ) /** - * A mask of IRIG formats with 10 kbps data rate: + * @brief A mask of IRIG formats with 10 kbps data rate */ #define MSK_ICODE_TX_10000BPS \ ( \ - MSK_ICODE_TX_G002_G142 | \ + MSK_ICODE_TX_G002_G142 | \ MSK_ICODE_TX_G006_G146 \ ) /** - * A mask of IRIG formats which support TFOM: + * @brief A mask of IRIG formats supporting 10ths of seconds */ -#define MSK_ICODE_TX_HAS_TFOM \ -( \ - MSK_ICODE_TX_IEEE1344 | \ - MSK_ICODE_TX_C37118 \ +#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 \ ) /** - * A mask of IRIG formats which support time zone information: + * @brief A mask of IRIG formats supporting 100ths of seconds */ -#define MSK_ICODE_TX_HAS_TZI \ -( \ - MSK_ICODE_TX_IEEE1344 | \ - MSK_ICODE_TX_C37118 \ +#define MSK_ICODE_TX_HAS_SEC100THS \ +( \ + MSK_ICODE_TX_G002_G142 | \ + MSK_ICODE_TX_G006_G146 \ ) /** - * The default mask of IRIG formats supported by - * IRIG transmitters: + * @brief A mask of IRIG formats supporting a 2 digit year number */ -#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 | \ +#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.:
+ * (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.:
+ * (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 \ ) @@ -2269,33 +3660,46 @@ enum /** - * Definitions used with IRIG receivers which decode - * two similar IRIG codes (with or without SBS) - * at the same time. + * @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 +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_TXC_101, // modulated - ICODE_RX_TXC_101_DC, // DCLS - N_ICODE_RX /* the number of valid signal code types */ + ICODE_RX_B122_B123, ///< modulated + ICODE_RX_A132_A133, ///< modulated + ICODE_RX_B002_B003, ///< DCLS + ICODE_RX_A002_A003, ///< DCLS + ICODE_RX_AFNOR, ///< modulated + ICODE_RX_AFNOR_DC, ///< DCLS + ICODE_RX_IEEE1344, ///< modulated + ICODE_RX_IEEE1344_DC, ///< DCLS + ICODE_RX_B126_B127, ///< modulated + ICODE_RX_B006_B007, ///< DCLS + ICODE_RX_G142_G146, ///< modulated + ICODE_RX_G002_G006, ///< DCLS + ICODE_RX_C37118, ///< modulated + ICODE_RX_C37118_DC, ///< DCLS + ICODE_RX_TXC101, ///< modulated + ICODE_RX_TXC101_DC, ///< DCLS + ICODE_RX_E112, ///< modulated + ICODE_RX_E002, ///< DCLS + ICODE_RX_NASA36, ///< modulated + ICODE_RX_NASA36_DC, ///< DCLS + N_ICODE_RX ///< the number of known codes }; /** - * Initializers for format name strings. + * @brief Initializers for timecode format name strings + * + * @see ::ICODE_RX_CODES */ #define DEFAULT_ICODE_RX_NAMES \ { \ @@ -2314,12 +3718,19 @@ enum "C37.118", \ "C37.118 (DCLS)", \ "TXC-101 DTR-6", \ - "TXC-101 DTR-6 (DCLS)" \ + "TXC-101 DTR-6 (DCLS)", \ + "E112", \ + "E002 (DCLS)", \ + "NASA-36", \ + "NASA-36 (DCLS)" \ } /** - * Initializers for short name strings which must not - * be longer than 11 printable characters. + * @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 \ { \ @@ -2327,7 +3738,7 @@ enum "A132/A133", \ "B002/B003", \ "A002/A003", \ - "AFNOR NF-S", \ + "AFNOR NF S", \ "AFNOR DC", \ "IEEE1344", \ "IEEE1344 DC", \ @@ -2338,12 +3749,18 @@ enum "C37.118", \ "C37.118 DC", \ "TXC-101", \ - "TXC-101 DC" \ + "TXC-101 DC", \ + "E112", \ + "E002 DC", \ + "NASA-36", \ + "NASA-36 DC" \ } /** - * Initializers for English format description strings. + * @brief Initializers for English format description strings + * + * @see ::ICODE_RX_CODES */ #define DEFAULT_ICODE_RX_DESCRIPTIONS_ENG \ { \ @@ -2362,12 +3779,24 @@ enum "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" \ + "DC code from TV time sync device TXC-101 DTR-6", \ + "10 bps, 100 Hz carrier", \ + "10 bps, DCLS", \ + "100 bps, 1 kHz carrier", \ + "100 bps, DCLS" \ } -/* - * Bit masks corresponding to the enumeration above: - */ +/** + * @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 ) @@ -2382,11 +3811,18 @@ enum #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_TXC_101 ( 1UL << ICODE_RX_TXC_101 ) -#define MSK_ICODE_RX_TXC_101_DC ( 1UL << ICODE_RX_TXC_101_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 */ + /** - * A mask of IRIG DCLS formats: + * @brief A mask of IRIG DCLS formats */ #define MSK_ICODE_RX_DC \ ( \ @@ -2396,11 +3832,23 @@ enum MSK_ICODE_RX_IEEE1344_DC | \ MSK_ICODE_RX_B006_B007 | \ MSK_ICODE_RX_G002_G006 | \ - MSK_ICODE_RX_C37118_DC \ + 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 \ ) /** - * A mask of IRIG formats with 1 kHz carrier: + * @brief A mask of IRIG formats with 1 kHz carrier */ #define MSK_ICODE_RX_1KHZ \ ( \ @@ -2408,11 +3856,13 @@ enum MSK_ICODE_RX_AFNOR | \ MSK_ICODE_RX_IEEE1344 | \ MSK_ICODE_RX_B126_B127 | \ - MSK_ICODE_RX_C37118 \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_TXC101 | \ + MSK_ICODE_RX_NASA36 \ ) /** - * A mask of IRIG formats with 10 kHz carrier: + * @brief A mask of IRIG formats with 10 kHz carrier */ #define MSK_ICODE_RX_10KHZ \ ( \ @@ -2420,7 +3870,7 @@ enum ) /** - * A mask of IRIG formats with 100 kHz carrier: + * @brief A mask of IRIG formats with 100 kHz carrier */ #define MSK_ICODE_RX_100KHZ \ ( \ @@ -2428,7 +3878,16 @@ enum ) /** - * A mask of IRIG formats with 100 bps data rate: + * @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 \ ( \ @@ -2441,28 +3900,68 @@ enum MSK_ICODE_RX_B126_B127 | \ MSK_ICODE_RX_B006_B007 | \ MSK_ICODE_RX_C37118 | \ - MSK_ICODE_RX_C37118_DC \ + MSK_ICODE_RX_C37118_DC | \ + MSK_ICODE_RX_TXC101 | \ + MSK_ICODE_RX_TXC101_DC | \ + MSK_ICODE_RX_NASA36 | \ + MSK_ICODE_RX_NASA36_DC \ ) /** - * A mask of IRIG formats with 1000 bps data rate: + * @brief A mask of IRIG formats with 1000 bps data rate */ #define MSK_ICODE_RX_1000BPS \ ( \ - MSK_ICODE_RX_A132_A133 | \ + MSK_ICODE_RX_A132_A133 | \ MSK_ICODE_RX_A002_A003 \ ) /** - * A mask of IRIG formats with 10 kbps data rate: + * @brief A mask of IRIG formats with 10 kbps data rate */ #define MSK_ICODE_RX_10000BPS \ ( \ - MSK_ICODE_RX_G142_G146 \ + 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 \ ) /** - * A mask of IRIG formats which support TFOM: + * @brief A mask of IRIG formats supporting TFOM time quality indicator */ #define MSK_ICODE_RX_HAS_TFOM \ ( \ @@ -2473,7 +3972,20 @@ enum ) /** - * A mask of IRIG formats which support time zone information: + * @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 \ ( \ @@ -2484,8 +3996,55 @@ enum ) /** - * The default mask of IRIG formats supported by - * IRIG receivers: + * @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.:
+ * (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.:
+ * (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 \ @@ -2498,18 +4057,21 @@ enum MSK_ICODE_RX_AFNOR_DC \ ) #endif -/** @} */ + +/** @} defgroup group_icode */ /** - * The structure below is used to configure an optional - * on-board IRIG output: + * @brief Configuration settings of an IRIG input or output + * + * @see @ref group_icode */ typedef struct { - uint16_t icode; /**< IRIG signal code, see \ref group_icode */ - uint16_t flags; /**< see \ref group_irig_flags */ + 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 ) \ @@ -2519,35 +4081,51 @@ typedef struct } -/** - @defgroup group_irig_flags Bit Masks used with IRIG_SETTINGS::flags - (others are reserved) -* @{ +/** + * @brief Flag bits used to define ::IFLAGS_BIT_MASKS + * + * @see ::IFLAGS_BIT_MASKS */ -#define IFLAGS_DISABLE_TFOM 0x0001 /**< RX ignore/TX don't gen TFOM */ -#define IFLAGS_TX_GEN_LOCAL_TIME 0x0002 /**< gen local time, not UTC */ +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 +}; + -#define IFLAGS_MASK 0x0003 /**< flags above or'ed */ +/** + * @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 -// 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. + IFLAGS_MASK = ( ( 1UL << N_IFLAGS_BITS ) - 1 ) ///< mask of all known flags +}; -/** @} */ /** * @brief Current IRIG settings and supported codes * - * Used to query the IRIG current IRIG settings + * Used to query the current IRIG settings * plus a mask of supported codes. */ typedef struct { - IRIG_SETTINGS settings; - uint32_t supp_codes; /**< bit mask of supported codes */ + 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 ) \ @@ -2557,32 +4135,173 @@ typedef struct } -// The type below is used to read the board's debug status -// which also include IRIG decoder status: -typedef uint32_t MBG_DEBUG_STATUS; +/** + * @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 debug status is bit coded as defined below: -enum +/** + * 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 { - 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 */ + CAL_REC_TYPE_UNDEF, ///< undefined type + CAL_REC_TYPE_IRIG_RX_COMP, ///< IRIG receiver delay compensation + N_CAL_REC_TYPE ///< number of known types +}; - MBG_SYS_BIT_INV_TIME, /**< Internal time not valid/set */ - MBG_SYS_BIT_TIME_SET_VIA_API, /**< On board time set externally */ - MBG_SYS_BIT_INV_RTC, /**< On board RTC invalid */ - MBG_SYS_BIT_CPU_PLL_FAILED, /**< The CPU's PLL watchdog */ - N_MBG_DEBUG_BIT +/** + * @brief 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 }; -/* - * Initializers for IRIG status bit strings. + +/** + * @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 \ { \ @@ -2602,6 +4321,12 @@ enum } +/** + * @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 ) @@ -2617,26 +4342,54 @@ enum #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 */ -typedef int16_t MBG_REF_OFFS; /**< -MBG_REF_OFFS_MAX..MBG_REF_OFFS_MAX */ +/** + * @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) ) -/** the maximum allowed positive / negative offset */ +/** + * @brief The maximum allowed positive / negative ref offset + */ #define MBG_REF_OFFS_MAX ( ( 12L * 60 ) + 30 ) // [minutes] /** - * the following value is used to indicate that the ref offset - * value has not yet been configured + * @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; + uint32_t flags; ///< @see ::MBG_OPT_FLAGS + } MBG_OPT_SETTINGS; #define _mbg_swab_mbg_opt_settings( _p ) \ @@ -2645,10 +4398,17 @@ typedef struct } +/** + * @brief A structure used to configure optional settings + * + * This structure includes the current settings, and a bit mask + * indicating which flags are supported. + */ typedef struct { - MBG_OPT_SETTINGS settings; - uint32_t supp_flags; + 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 ) \ @@ -2658,33 +4418,56 @@ typedef struct } -enum +/** + * @brief Enumeration of flag bits used to define ::MBG_OPT_FLAGS + */ +enum MBG_OPT_BITS { - MBG_OPT_BIT_STR_UTC, /**< serial string contains UTC time */ - MBG_OPT_BIT_EMU_SYNC, /**< emulate/pretend to be synchronized, */ - /**< alternatively GPS_FEAT_IGNORE_LOCK may be supported */ + 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 }; -/* - * Bit masks corresponding to the enumeration above: + +/** + * @brief Bit masks according to ::MBG_OPT_BITS + * + * Used with ::MBG_OPT_SETTINGS::flags and ::MBG_OPT_INFO::supp_flags. */ -#define MBG_OPT_FLAG_STR_UTC ( 1UL << MBG_OPT_BIT_STR_UTC ) -#define MBG_OPT_FLAG_EMU_SYNC ( 1UL << MBG_OPT_BIT_EMU_SYNC ) +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 +}; -// bit coded return type for PCPS_GET_IRIG_CTRL_BITS -typedef uint32_t MBG_IRIG_CTRL_BITS; +/** + * @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 ) -// The following macro extracts the 4 bit TFOM code from the -// IRIG control bits read from a card. This only works if the received -// IRIG code is a code which supports TFOM, this is currently -// only IEEE1344. -#define _pcps_tfom_from_irig_ctrl_bits( _p ) \ +/** + * @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 ) @@ -2692,24 +4475,33 @@ typedef uint32_t MBG_IRIG_CTRL_BITS; #define RAW_IRIG_SIZE 16 /** - The buffer below can be used to get the raw data bits - from the IRIG decoder. A maximum number of RAW_IRIG_SIZE - bytes can be filled. If less bytes are used then the rest - of the bytes are filled with zeros. - - The first IRIG bit received from the transmitter is saved - in the MSB (bit 7) of data_bytes[0], etc. -*/ -typedef struct + * @brief A buffer used to read raw IRIG data bits from an IRIG receiver + * + * Used to get the raw data bits from the IRIG decoder. A maximum number + * of ::RAW_IRIG_SIZE bytes can be filled up, depending on the IRIG code. + * If less bytes are used then the rest of the bytes are filled with zeros. + * + * @note The first IRIG bit received from the transmitter is saved + * in the MSB (bit 7) of data_bytes[0], etc. + */ +typedef struct { uint8_t data_bytes[RAW_IRIG_SIZE]; + } MBG_RAW_IRIG_DATA; -// The following macro extracts the 4 bit TFOM code from the raw -// data bits read from a card. This only works if the received -// IRIG code is a code which supports TFOM, this is currently -// only IEEE1344. -#define _pcps_tfom_from_raw_irig_data( _p ) \ +#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 ) \ @@ -2717,33 +4509,44 @@ typedef struct -/** - @defgroup group_scale Time Scale Configuration - - The structures and defines can be used to configure the GPS receiver's - basic time scale. By default this is UTC which can optionally - be converted to some local time. However, some applications - prefer TAI or pure GPS time. This can be configured using the - structures below if the GPS_HAS_TIME_SCALE flag is set in - RECEIVER_INFO::features. - @{ -*/ +/** + * @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. + * + * @{ */ -enum +/** + * @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, t_gps - deltat_ls */ - MBG_TIME_SCALE_GPS, /**< GPS time, monotonical */ - MBG_TIME_SCALE_TAI, /**< TAI, t_gps + GPS_TAI_OFFSET seconds */ + 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 }; -#define MBG_TIME_SCALE_MSK_DEFAULT ( 1UL << MBG_TIME_SCALE_DEFAULT ) -#define MBG_TIME_SCALE_MSK_GPS ( 1UL << MBG_TIME_SCALE_GPS ) -#define MBG_TIME_SCALE_MSK_TAI ( 1UL << MBG_TIME_SCALE_TAI ) - -// See also the extended status bits TM_SCALE_GPS and TM_SCALE_TAI -// indicating the active time scale setting. - +/** + * @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 \ { \ @@ -2754,27 +4557,35 @@ enum -/** - The fixed time offset between the GPS and TAI time scales, in seconds -*/ -#define GPS_TAI_OFFSET 19 /**< [s], TAI = GPS + GPS_TAI_OFFSET */ +/** + * @brief The constant time offset between the GPS and TAI time scales, in seconds + */ +#define GPS_TAI_OFFSET 19 ///< [s], TAI = GPS + GPS_TAI_OFFSET +/** + * @brief Time scale configuration settings + */ typedef struct { - uint8_t scale; /**< current time scale code from the enum above */ - uint8_t flags; /**< reserved, currently always 0 */ + 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; /**< numb. of scales, all supported flags */ - uint32_t supp_scales; /**< bit masks of supported scales */ + 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 ) \ @@ -2784,24 +4595,25 @@ typedef struct _mbg_swab32( &(_p)->supp_scales ); \ } -/** @} */ // endgroup +/** @} 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. + * receiver is reported in the RECEIVER_INFO::n_str_type field. */ /** - * The structure is used to define a date of year: + * @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 */ + 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 ) \ @@ -2811,14 +4623,15 @@ typedef struct /** - * The structure is used to define a time of day: + * @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 */ + 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 ) \ @@ -2826,15 +4639,15 @@ typedef struct /** - * The structure defines a single date and time - * for switching operations: + * @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 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 ) \ @@ -2845,13 +4658,13 @@ typedef struct /** - * The structure defines times and dates - * for an on/off cycle: + * @brief A structure to define on/off cycle times */ typedef struct { - MBG_DATE_TIME on; /* time and date to switch on */ - MBG_DATE_TIME off; /* time and date to switch off */ + 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 ) \ @@ -2862,67 +4675,197 @@ typedef struct /** - * The number of POUT_TIMEs for each programmable pulse output + * @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 +#define N_POUT_TIMES 3 /** - * The structure is used to configure a single programmable - * pulse output. + * @brief Configuration settings for a single programmable pulse output */ typedef struct { - uint16_t mode; /**< mode of operation, codes defined below */ - uint16_t pulse_len; /**< 10 msec units, or COM port number */ - uint16_t timeout; /**< [min], for dcf_mode */ - uint16_t flags; /**< see below */ - POUT_TIME tm[N_POUT_TIMES]; /**< switching times */ + 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; -#define _mbg_swab_pout_settings( _p ) \ -{ \ - int i; \ - _mbg_swab16( &(_p)->mode ); \ - _mbg_swab16( &(_p)->pulse_len ); \ - _mbg_swab32( &(_p)->timeout ); \ - _mbg_swab16( &(_p)->flags ); \ - \ - for ( i = 0; i < N_POUT_TIMES; i++ ) \ - _mbg_swab_pout_time( &(_p)->tm[i] ); \ +/** + * @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 ); \ } -#define MAX_POUT_PULSE_LEN 1000 /**< 10 secs, in 10 msec units */ -#define MAX_POUT_DCF_TIMOUT ( 48 * 60 ) /**< 48 hours, in minutes */ + +/** + * @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 + /** - * These codes are defined for POUT_SETTINGS.mode to setup - * the basic mode of operation for a single programmable pulse - * output: + * @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 +enum POUT_MODES { - POUT_IDLE, /**< always off, or on if POUT_INVERTED */ - POUT_TIMER, /**< switch on/off at configured times */ - POUT_SINGLE_SHOT, /**< pulse at time POUT_SETTINGS.tm[0].on */ - POUT_CYCLIC_PULSE, /**< pulse every POUT_SETTINGS.tm[0].on.t interval */ - POUT_PER_SEC, /**< pulse if second changes */ - POUT_PER_MIN, /**< pulse if minute changes */ - POUT_PER_HOUR, /**< pulse if hour changes */ - POUT_DCF77, /**< emulate DCF77 signal */ - POUT_POS_OK, /**< on if pos. OK (nav_solved) */ - POUT_TIME_SYNC, /**< on if time sync (time_syn) */ - POUT_ALL_SYNC, /**< on if pos. OK and time sync */ - POUT_TIMECODE, /**< IRIG/AFNOR DCLS output */ - POUT_TIMESTR, /**< COM port number in pulse_len field */ - POUT_10MHZ, /**< 10 MHz fixed frequency */ - POUT_DCF77_M59, /**< DCF77-like signal with 500 ms pulse in 59th second */ - POUT_SYNTH, /**< programmable synthesizer frequency */ - N_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. @@ -2939,10 +4882,12 @@ enum #define ENG_POUT_NAME_TIME_SYNC "Time Sync" #define ENG_POUT_NAME_ALL_SYNC "All Sync" #define ENG_POUT_NAME_TIMECODE "DCLS Time Code" -#define ENG_POUT_NAME_TIMESTR "COM Time String" +#define ENG_POUT_NAME_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 \ { \ @@ -2961,7 +4906,9 @@ enum ENG_POUT_NAME_TIMESTR, \ ENG_POUT_NAME_10MHZ, \ ENG_POUT_NAME_DCF77_M59, \ - ENG_POUT_NAME_SYNTH \ + ENG_POUT_NAME_SYNTH, \ + ENG_POUT_NAME_TIME_SLOTS, \ + ENG_POUT_NAME_GPIO \ } @@ -2981,6 +4928,8 @@ enum #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 \ { \ @@ -2999,144 +4948,247 @@ enum ENG_POUT_HINT_TIMESTR, \ ENG_POUT_HINT_10MHZ, \ ENG_POUT_HINT_DCF77_M59, \ - ENG_POUT_HINT_SYNTH \ + ENG_POUT_HINT_SYNTH, \ + ENG_POUT_HINT_TIME_SLOTS, \ + ENG_POUT_HINT_GPIO \ } -/* - * The definitions below are used to set up bit masks - * which restrict the modes which can be used with - * a given programmable output: - */ -#define MSK_POUT_IDLE ( 1UL << POUT_IDLE ) -#define MSK_POUT_TIMER ( 1UL << POUT_TIMER ) -#define MSK_POUT_SINGLE_SHOT ( 1UL << POUT_SINGLE_SHOT ) -#define MSK_POUT_CYCLIC_PULSE ( 1UL << POUT_CYCLIC_PULSE ) -#define MSK_POUT_PER_SEC ( 1UL << POUT_PER_SEC ) -#define MSK_POUT_PER_MIN ( 1UL << POUT_PER_MIN ) -#define MSK_POUT_PER_HOUR ( 1UL << POUT_PER_HOUR ) -#define MSK_POUT_DCF77 ( 1UL << POUT_DCF77 ) -#define MSK_POUT_POS_OK ( 1UL << POUT_POS_OK ) -#define MSK_POUT_TIME_SYNC ( 1UL << POUT_TIME_SYNC ) -#define MSK_POUT_ALL_SYNC ( 1UL << POUT_ALL_SYNC ) -#define MSK_POUT_TIMECODE ( 1UL << POUT_TIMECODE ) -#define MSK_POUT_TIMESTR ( 1UL << POUT_TIMESTR ) -#define MSK_POUT_10MHZ ( 1UL << POUT_10MHZ ) -#define MSK_POUT_DCF77_M59 ( 1UL << POUT_DCF77_M59 ) -#define MSK_POUT_SYNTH ( 1UL << POUT_SYNTH ) + +/** + * @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 +}; -/* - * The codes below are used with POUT_SETTINGS::flags: +/** + * @brief Flag bit masks used with ::POUT_SETTINGS::flags + * + * @see ::POUT_SETTINGS_FLAG_BITS */ -#define POUT_INVERTED 0x0001 // invert output level -#define POUT_IF_SYNC_ONLY 0x0002 // disable in holdover mode -#define POUT_TIMEBASE_UTC 0x0004 // use UTC, only applicable for DCF77 output +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 +}; + /** - Since a clock may support more than one programmable - pulse output, setup tools must use the structure below - to read/set pulse output configuration. - The number of outputs supported by a receiver model - can be queried using the RECEIVER_INFO structure. + * @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 */ + uint16_t idx; ///< 0..::RECEIVER_INFO::n_prg_out-1 POUT_SETTINGS pout_settings; + } POUT_SETTINGS_IDX; -#define _mbg_swab_pout_settings_idx( _p ) \ -{ \ - _mbg_swab16( &(_p)->idx ); \ - _mbg_swab_pout_settings( &(_p)->pout_settings ); \ +#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 ); \ } /** - The structure below holds the current settings - for a programmable pulse output, plus additional - informaton on the output's capabilities. - This can be read by setup programs to allow setup - of supported features only. + * @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 */ - uint8_t timestr_ports; /**< bit mask of COM ports supported for POUT_TIMESTR */ - uint8_t reserved_0; /**< reserved for future use, currently 0 */ - uint16_t reserved_1; /**< reserved for future use, currently 0 */ - uint32_t flags; /**< see below */ + 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( _p ) \ -{ \ - _mbg_swab_pout_settings( &(_p)->pout_settings ); \ - _mbg_swab32( &(_p)->supp_modes ); \ - _mbg_swab16( &(_p)->reserved_1 ); \ - _mbg_swab32( &(_p)->flags ); \ +#define _mbg_swab_pout_info_on_get( _p ) \ +{ \ + _mbg_swab_pout_settings_on_get( &(_p)->pout_settings ); \ + _mbg_swab32( &(_p)->supp_modes ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->flags ); \ } -/** The max number of COM ports that can be handled by POUT_INFO::timestr_ports */ -#define MAX_POUT_TIMESTR_PORTS 8 +#define MAX_POUT_TIMESTR_PORTS 8 ///< The max number of COM ports that can be handled by ::POUT_INFO::timestr_ports -/* - * The codes below are used with POUT_INFO::flags: + +/** + * @brief Flag bits used to define ::POUT_INFO_FLAG_MASKS + * + * @see ::POUT_INFO_FLAG_MASKS */ -#define POUT_SUPP_IF_SYNC_ONLY 0x0001 // supports disabling outputs in holdover mode -#define POUT_SUPP_DCF77_UTC 0x0002 // supports UTC output in DCF77 mode +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 +}; + /** - The structure below adds an index number to the structure - above to allow addressing of several instances: + * @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 */ + uint16_t idx; ///< 0..::RECEIVER_INFO::n_prg_out-1 POUT_INFO pout_info; + } POUT_INFO_IDX; -#define _mbg_swab_pout_info_idx( _p ) \ -{ \ - _mbg_swab16( &(_p)->idx ); \ - _mbg_swab_pout_info( &(_p)->pout_info ); \ +#define _mbg_swab_pout_info_idx_on_get( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_pout_info_on_get( &(_p)->pout_info ); \ } -/* - * The codes below are used with devices which support multiple - * ref time sources at the same time. The priorities of the - * supported ref time sources is configurable. - */ +/** + * @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. + * + * @{ */ -/* - * All possibly supported ref time sources +/** + * @brief Enumeration of all known types of reference time source + * + * All known types of input signal 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 +enum MULTI_REF_TYPES { - MULTI_REF_NONE = -1, // nothing, undefined - MULTI_REF_GPS = 0, // standard GPS - MULTI_REF_10MHZ, // 10 MHz input frequency - MULTI_REF_PPS, // 1 PPS input signal - MULTI_REF_10MHZ_PPS, // combined 10 MHz plus PPS - MULTI_REF_IRIG, // IRIG input - MULTI_REF_NTP, // Network Time Protocol (NTP) - MULTI_REF_PTP, // Precision Time Protocol (PTP, IEEE1588) - MULTI_REF_PTP_E1, // PTP over E1 - MULTI_REF_FREQ, // fixed frequency - MULTI_REF_PPS_STRING, // 1 PPS in addition to string - N_MULTI_REF // the number of defined sources + /// 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 + -/* - * Names of supported ref time sources +/** + * @brief Names of known ref time sources + * + * @see ::MULTI_REF_TYPES */ #define DEFAULT_MULTI_REF_NAMES \ { \ @@ -3149,1142 +5201,6849 @@ enum "PTP (IEEE1588)", \ "PTP over E1", \ "Fixed Freq. in", \ - "PPS plus string" \ + "PPS plus string", \ + "Var. freq. via GPIO", \ + "(reserved)", \ + "DCF77 PZF Receiver", \ + "Long Wave Receiver", \ + "GLONASS/GPS Receiver", \ + "HaveQuick Input", \ + "ext. Osc." \ } - -/* - * Bit masks used to indicate supported reference sources +/** + * @brief Short names of supported ref time sources + * + * Used e.g. to configure a particular input signal type + * + * @see ::MULTI_REF_TYPES */ -#define HAS_MULTI_REF_GPS ( 1UL << MULTI_REF_GPS ) -#define HAS_MULTI_REF_10MHZ ( 1UL << MULTI_REF_10MHZ ) -#define HAS_MULTI_REF_PPS ( 1UL << MULTI_REF_PPS ) -#define HAS_MULTI_REF_10MHZ_PPS ( 1UL << MULTI_REF_10MHZ_PPS ) -#define HAS_MULTI_REF_IRIG ( 1UL << MULTI_REF_IRIG ) -#define HAS_MULTI_REF_NTP ( 1UL << MULTI_REF_NTP ) -#define HAS_MULTI_REF_PTP ( 1UL << MULTI_REF_PTP ) -#define HAS_MULTI_REF_PTP_E1 ( 1UL << MULTI_REF_PTP_E1 ) -#define HAS_MULTI_REF_FREQ ( 1UL << MULTI_REF_FREQ ) -#define HAS_MULTI_REF_PPS_STRING ( 1UL << MULTI_REF_PPS_STRING ) +#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" \ +} -/* - * There are 2 different ways to configure multi ref support - * provided by some devices. +/** + * @brief Bit masks associated with multi ref types * - * Newer devices which have the GPS_FEAT_XMULTI_REF flag set - * in RECEIVER_INFO::features support the newer XMULTI_REF_... - * structures which provide a more flexible interface. + * Used to indicate which multi ref types are supported, e.g. + * in ::XMULTI_REF_INFO::supp_ref or ::MULTI_REF_INFO::supp_ref. * - * Older devices which have the GPS_FEAT_MULTI_REF flag set - * support these MULTI_REF_... structures below where - * the number of supported input sources and priorities - * is limited to N_MULTI_REF_PRIO. - */ + * @see ::MULTI_REF_TYPES + * + * @anchor MULTI_REF_TYPE_MASKS @{ */ -#define N_MULTI_REF_PRIO 4 +#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 + * + * @{ */ /** - The structure below is used to configure the priority of - the supported ref sources. + * @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 + - The number stored in prio[0] of the array indicates the ref time - source with highest priority. If that source fails, the device - falls back to the source indicated by prio[1]. Each field of - the prio[] array must be set to one of the values 0..N_MULTI_REF-1, - or to -1 (0xFF) if the value is not assigned. +/** + * @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; /** - The structure below is used to query the MULTI_REF configuration, - plus the supported ref sources. + * @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; /* supp. HAS_MULTI_REF_... codes or'ed */ - uint16_t n_levels; /* supp. levels, 0..N_MULTI_REF_PRIO */ - uint16_t flags; /* reserved, currently 0 */ + 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; -/* - * The type below is used to query the MULTI_REF status information, +/** + * @brief A data type used to query MULTI_REF status information + * + * @see ::MULTI_REF_STATUS_BIT_MASKS */ -typedef uint16_t MULTI_REF_STATUS; /* flag bits as defined below */ +typedef uint16_t MULTI_REF_STATUS; -/* - * The bits and associated bit masks below are used with the - * MULTI_REF_STATUS type. Each bit is set if the associated - * condition is true and is reset if the condition is not true: +/** + * @brief Enumeration of multi ref status bits + * + * @see ::MULTI_REF_STATUS_BIT_MASKS */ -enum +enum MULTI_REF_STATUS_BITS { - WRN_MODULE_MODE, /* selected input mode was invalid, set to default */ - WRN_COLD_BOOT, /* GPS is in cold boot mode */ - WRN_WARM_BOOT, /* GPS is in warm boot mode */ - WRN_ANT_DISCONN, /* antenna is disconnected */ - WRN_10MHZ_UNLOCK, /* impossible to lock to external 10MHz reference */ - WRN_1PPS_UNLOCK, /* impossible to lock to external 1PPS reference */ - WRN_GPS_UNLOCK, /* impossible to lock to GPS */ - WRN_10MHZ_MISSING, /* external 10MHz signal not available */ - WRN_1PPS_MISSING, /* external 1PPS signal not available */ - N_MULTI_REF_STATUS_BITS + 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 }; -#define MSK_WRN_COLD_BOOT ( 1UL << WRN_COLD_BOOT ) -#define MSK_WRN_WARM_BOOT ( 1UL << WRN_WARM_BOOT ) -#define MSK_WRN_ANT_DISCONN ( 1UL << WRN_ANT_DISCONN ) -#define MSK_WRN_10MHZ_UNLOCK ( 1UL << WRN_10MHZ_UNLOCK ) -#define MSK_WRN_1PPS_UNLOCK ( 1UL << WRN_1PPS_UNLOCK ) -#define MSK_WRN_GPS_UNLOCK ( 1UL << WRN_GPS_UNLOCK ) -#define MSK_WRN_10MHZ_MISSING ( 1UL << WRN_10MHZ_MISSING ) -#define MSK_WRN_1PPS_MISSING ( 1UL << WRN_1PPS_MISSING ) -#define MSK_WRN_MODULE_MODE ( 1UL << WRN_MODULE_MODE ) - - -/* - * If the RECEIVER_INFO::features flag GPS_FEAT_XMULTI_REF is set - * then the following XMULTI_REF_... data structures must be used - * instead of the older MULTI_REF_... structures above. +/** + * @brief Bit masks associated with ::MULTI_REF_STATUS_BITS + * + * Used with ::MULTI_REF_STATUS. * - * Those devices support a number of priority levels addressed by - * the priority index, starting at 0 for highest priority. A single - * reference time source from the set of supported sources can be - * assigned to each priority level. - * - * The structures below are used to configure the individual - * time source for each priority level, and retrieve the status - * of the time source at each priority level. + * @see ::MULTI_REF_STATUS_BITS */ - -typedef struct +enum MULTI_REF_STATUS_BIT_MASKS { - uint8_t type; /* 0..N_MULTI_REF-1 from the enum above */ - uint8_t instance; /* reserved, currently always 0 */ -} XMULTI_REF_ID; + 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 +}; -typedef struct -{ - XMULTI_REF_ID id; /* time source identifier */ - uint16_t flags; /* reserved, currently always 0 */ - NANO_TIME bias; /* time bias, e.g. path delay */ - NANO_TIME precision; /* precision of the time source */ - uint32_t fine_limit; /* smooth control if below this limit */ -} XMULTI_REF_SETTINGS; +/** @} defgroup group_multi_ref_old */ -/* - * The structure below is used to retrieve or configure the time source - * for a specific priority level. - * After configuring, a structure with idx == 0xFFFF (-1) must be sent - * to let the changes become effective. - */ -typedef struct -{ - uint16_t idx; /* the priority level index, highest == 0 */ - XMULTI_REF_SETTINGS settings; /* the settings configured for this level */ -} XMULTI_REF_SETTINGS_IDX; +/** + * @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 + * have to 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 which an input source can be + * 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. + * + * @{ */ -/* - * The structure below contains the XMULTI_REF configuration - * for a single priority level, plus information on supported - * ref time sources, and the number of supported priority levels. +/** + * @brief Identifier for a reference source */ typedef struct { - XMULTI_REF_SETTINGS settings; /* current settings */ - uint32_t supp_ref; /* supp. HAS_MULTI_REF_... codes or'ed */ - uint8_t n_supp_ref; /* number of supported ref time sources */ - uint8_t n_prio; /* number of supported priority levels */ - uint16_t flags; /* reserved, currently 0, e.g. multiple instance support */ + 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_INFO; +} XMULTI_REF_ID; -/* - * The structure below is used to retrieve the XMULTI_REF configuration - * information for a specific priority level. + +/** + * @brief Reference source configuration settings */ typedef struct { - uint16_t idx; /* the priority level index, highest == 0 */ - XMULTI_REF_INFO info; + XMULTI_REF_ID id; ///< reference time source identifier + uint16_t flags; ///< see ::XMR_SETTINGS_FLAG_MSKS and ::XMR_EXT_SRC_INFO::supp_flags + 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_INFO_IDX; +} XMULTI_REF_SETTINGS; -/* - * The structure below contains status information on a single - * ref time source. + +/** + * @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 { - XMULTI_REF_ID id; /* time source identifier */ - uint16_t status; /* flag bits as defined below */ - NANO_TIME offset; /* time offset from main time base */ - uint32_t reserved; /* reserved, currently always 0 */ + 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_STATUS; +} XMULTI_REF_SETTINGS_IDX; -/* - * The structure below is used to retrieve the the status information - * of the time source at a specific priority level. + +/** + * @brief Bit masks used to define ::XMR_SETTINGS_FLAG_MSKS */ -typedef struct +enum XMR_SETTINGS_FLAG_BITS { - uint16_t idx; /* the priority level index, highest == 0 */ - XMULTI_REF_STATUS status; - -} XMULTI_REF_STATUS_IDX; + XMRSF_BIT_AUTO_BIAS_MASTER, ///< src is allowed to operate as zero asymmetry master + XMRSF_BIT_AUTO_BIAS_SLAVE, ///< accept static bias correction from zero asymmetry master + XMRSF_BIT_ASYMMETRY_STEP_DETECTION, ///< static bias auto correction in case of step + N_XMRSF_BITS ///< number of know status bits +}; -/* - * Bits used with XMULTI_REF_STATUS. +/** + * @brief Bit masks used with ::XMULTI_REF_SETTINGS::flags and ::XMR_EXT_SRC_INFO::supp_flags */ -enum +enum XMR_SETTINGS_FLAG_MSKS { - 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 */ - N_XMRS_BITS + XMRSF_MSK_AUTO_BIAS_MASTER = ( 1UL << XMRSF_BIT_AUTO_BIAS_MASTER ), ///< see ::XMRSF_BIT_AUTO_BIAS_MASTER + XMRSF_MSK_AUTO_BIAS_SLAVE = ( 1UL << XMRSF_BIT_AUTO_BIAS_SLAVE ), ///< see ::XMRSF_BIT_AUTO_BIAS_SLAVE + XMRSF_MSK_ASYMMETRY_STEP_DETECTION = ( 1UL << XMRSF_BIT_ASYMMETRY_STEP_DETECTION ) ///< see ::XMRSF_BIT_ASYMMETRY_STEP_DETECTION }; -/* bit masks corresponding to the flag bits above */ - -#define XMRS_MSK_NOT_SUPP ( 1UL << XMRS_BIT_NOT_SUPP ) -#define XMRS_MSK_NO_CONN ( 1UL << XMRS_BIT_NO_CONN ) -#define XMRS_MSK_NO_SIGNAL ( 1UL << XMRS_BIT_NO_SIGNAL ) -#define XMRS_MSK_IS_MASTER ( 1UL << XMRS_BIT_IS_MASTER ) -#define XMRS_MSK_IS_LOCKED ( 1UL << XMRS_BIT_IS_LOCKED ) -#define XMRS_MSK_IS_ACCURATE ( 1UL << XMRS_BIT_IS_ACCURATE ) -#define XMRS_MSK_NOT_SETTLED ( 1UL << XMRS_BIT_NOT_SETTLED ) -#define XMRS_MSK_NOT_PHASE_LOCKED ( 1UL << XMRS_BIT_NOT_PHASE_LOCKED ) - - -/* - * An initializer for a XMULTI_REF_STATUS variable - * with status invalid / not used +/** + * @brief Reference source capabilities and current configuration */ -#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 */ \ -} +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 n_prio; ///< reserved, don't use, currently always 0 //##++++ TODO: check which devices support/use this field + uint16_t flags; ///< reserved, don't use, currently always 0 -/* - * The types below are not used with all devices: - */ +} XMULTI_REF_INFO; -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: + +/** + * @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 -/* return a bit mask depending on the port number */ -#define IGNORE_LOCK_FOR_ALL_PORTS 0x01 +} XMULTI_REF_INFO_IDX; -#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 ) +/** + * @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 -/* 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 ) ) +} XMULTI_REF_STATUS; -/*------------------------------------------------------------------------*/ -/* - * The structures below are used with the SCU multiplexer board - * in a redundant system: +/** + * @brief Status information on a ref time source at a specific priority level */ - typedef struct { - uint32_t hw_id; // hardware identification - uint32_t fw_id; // firmware identification - uint16_t flags; // reserved currently 0 - uint8_t clk0_info; // reference clock 0 type - uint8_t clk1_info; // reference clock 1 type - uint16_t epld_status; // epld status word, see defintions below - uint16_t epld_control; // epld control word, see defintions below -} SCU_STAT_INFO; - -typedef struct -{ - uint16_t epld_control_mask; // control mask, determines which bit is to be changed - uint16_t epld_control_value; // control value, determines value of bits to be changed - uint32_t flags; // reserved, currently 0 -} SCU_STAT_SETTINGS; - -// definitions for status word bit masks -#define MSK_EPLD_STAT_TS1 0x0001 // state of time sync signal clk_1 -#define MSK_EPLD_STAT_TS2 0x0002 // state of time sync signal clk_2 -#define MSK_EPLD_STAT_TL_ERROR 0x0004 // state of time limit error input -#define MSK_EPLD_STAT_PSU1_OK 0x0008 // state of power supply 1 monitoring input -#define MSK_EPLD_STAT_PSU2_OK 0x0010 // state of power supply 2 monitoring input -#define MSK_EPLD_STAT_AUTO 0x0020 // AUTOMATIC/REMOTE or MANUAL Mode -#define MSK_EPLD_STAT_SEL 0x0040 // select bit for output MUX, ( clk_1 = 0 ) -#define MSK_EPLD_STAT_ENA 0x0080 // enable Bit for output MUX, set if enabled -#define MSK_EPLD_STAT_ACO 0x4000 // Access control override bit -#define MSK_EPLD_STAT_WDOG_OK 0x8000 // WDT_OK set to zero if watchdog expired + 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; -#define MSK_EPLD_CNTL_SEL_REM 0x0800 // remote select for output MUX ( clk_1 = 0 ) -#define MSK_EPLD_CNTL_DIS_REM 0x1000 // remote disable for output MUX -#define MSK_EPLD_CNTL_REMOTE 0x2000 // must be set to enable remote operation -#define MSK_EPLD_CNTL_SEL_SNMP 0x4000 // connect COM0 channels to XPORT -#define MSK_EPLD_CNTL_ENA_SNMP 0x8000 // select clk for comm. ( clk1 = 0 ) -/* - * Definitions for clk0_info and clk1_info, can be used to determine - * the reference clock type connected to SCU input channel 0 and 1: +/** + * @brief XMULTI_REF status bits */ -enum +enum XMR_REF_STATUS_BITS { - 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 + 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 */ -/* - * GPS receiver modes of operation. Some of the codes combinations - * are obsolete with recent GPS receivers. However, that doesn't - * matter since the mode is just read from the receiver: + +/** + * @brief XMRS status bit name strings + * + * @see ::XMR_REF_STATUS_BITS */ -#define REMOTE 0x10 -#define BOOT 0x20 +#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" \ +} -#define TRACK ( 0x01 ) -#define AUTO_166 ( 0x02 ) -#define WARM_166 ( 0x03 | BOOT ) -#define COLD_166 ( 0x04 | BOOT ) -#define AUTO_BC ( 0x05 | REMOTE ) -#define WARM_BC ( 0x06 | REMOTE | BOOT ) -#define COLD_BC ( 0x07 | REMOTE | BOOT ) -#define UPDA_166 ( 0x08 | BOOT ) -#define UPDA_BC ( 0x09 | REMOTE | BOOT ) +/* + * 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 */ \ +} -typedef int16_t DAC_VAL; +/** + * @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 ::XMULTI_REF_INFO_IDX or ::XMULTI_REF_STATUS_IDX which can be retrieved + 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 -#define _mbg_swab_dac_val( _p ) \ - _mbg_swab16( _p ); +} XMULTI_REF_INSTANCES; -typedef struct +/** + * @brief Enumeration of flag bits used with XMULTI_REF instances + * + * @see ::XMR_INST_FLAG_BIT_MASKS + */ +enum XMR_INST_FLAGS { - uint16_t mode; /**< Mode of operation */ - uint16_t good_svs; /**< Numb. of satellites that can currently be received and used */ - uint16_t svs_in_view; /**< Numb. of satellites that should be in view according to the almanac data */ - DAC_VAL dac_val; /**< Oscillator fine DAC value */ - DAC_VAL dac_cal; /**< Oscillator calibration DAC value ( see #OSC_DAC_RANGE, #OSC_DAC_BIAS ) */ -} STAT_INFO; - -#define _mbg_swab_stat_info( _p ) \ -{ \ - _mbg_swab16( &(_p)->mode ); \ - _mbg_swab16( &(_p)->good_svs ); \ - _mbg_swab16( &(_p)->svs_in_view ); \ - _mbg_swab_dac_val( &(_p)->dac_val ); \ - _mbg_swab_dac_val( &(_p)->dac_cal ); \ -} + /// 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 -#define OSC_DAC_RANGE 4096UL -#define OSC_DAC_BIAS ( OSC_DAC_RANGE / 2 ) + XMRIF_BIT_EXT_SRC_INFO_SUPP, ///< ::XMR_EXT_SRC_INFO structure supported + N_XMRIF_BITS ///< number of known flag bits +}; -/* - The enumeration below lists all - known satellite navigation systems -*/ -enum +/** + * @brief Bit masks associated with ::XMR_INST_FLAGS + * + * Used with ::XMULTI_REF_INSTANCES::flags. + * + * @see ::XMR_INST_FLAGS + */ +enum XMR_INST_FLAG_BIT_MASKS { - GNSS_TYPE_GPS, - GNSS_TYPE_GLONASS, - GNSS_TYPE_BEIDOU, - GNSS_TYPE_GALILEO, - N_GNSS_TYPES + 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 + XMRIF_MSK_EXT_SRC_INFO_SUPP = ( 1UL << XMRIF_BIT_EXT_SRC_INFO_SUPP ) ///< see ::XMRIF_BIT_EXT_SRC_INFO_SUPP }; +/** + * @brief XMR holdover interval, or elapsed holdover time, in [s] + */ +typedef uint32_t XMR_HOLDOVER_INTV; -#define GNSS_TYPE_STRS \ -{ \ - "GPS", \ - "GLONASS", \ - "BEIDOU" , \ - "GALILEO" \ -} - +#define _mbg_swab_xmr_holdover_intv( _p ) \ + _mbg_swab32( _p ); -#define MBG_GNSS_TYPE_MSK_GPS ( 1UL << GNSS_TYPE_GPS ) -#define MBG_GNSS_TYPE_MSK_GLONASS ( 1UL << GNSS_TYPE_GLONASS ) -#define MBG_GNSS_TYPE_MSK_BEIDOU ( 1UL << GNSS_TYPE_BEIDOU ) -#define MBG_GNSS_TYPE_MSK_GALILEO ( 1UL << GNSS_TYPE_GALILEO ) +/** + * @brief A code used to indicate that a input source table index is unspecified + */ +#define XMR_PRIO_LVL_UNSPEC -1 -#define N_GNSS_MODE_PRIO 8 +/** + * @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 { - uint32_t gnss_set; /**< current set of GNSS types */ - uint8_t prio[N_GNSS_MODE_PRIO]; /**< index 0 for highest priority, use GNSS enumeration above, init with 0xFF if not supported */ - uint32_t flags; /**< see below */ -} MBG_GNSS_MODE_SETTINGS; - -#define _mbg_swab_mbg_gnss_mode_settings( _p ) \ -{ \ - _mbg_swab32( &(_p)->gnss_set ); \ - _mbg_swab32( &(_p)->flags ); \ -} + 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; -typedef struct +/** + * @brief XMR holdover status modes + * + * Used with ::XMR_HOLDOVER_STATUS::mode. + * + * @see ::XMR_HOLDOVER_STATUS_MODE_NAMES + */ +enum XMR_HOLDOVER_STATUS_MODES { - MBG_GNSS_MODE_SETTINGS settings; /**< current GNSS mode settings */ - uint32_t supp_gnss_types; /**< bit masks of supported GNSS types */ - uint32_t flags; /**< indicates which of the defined flags are supported by the device */ -} MBG_GNSS_MODE_INFO; + 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 +}; -#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 String initializers for XMR holdover status mode + * + * @see ::XMR_HOLDOVER_STATUS_MODES + */ +#define XMR_HOLDOVER_STATUS_MODE_NAMES \ +{ \ + "autonomous", \ + "pre-autonomous", \ + "remote" \ } -/* Flags used with MBG_GNSS_MODE_SETTINGS::flags and MBG_GNSS_MODE_INFO::flags: */ -enum +/** + * @brief XMR holdover status flag bits + * + * Used to define ::XMR_HOLDOVER_STATUS_FLAG_MASKS. + */ +enum XMR_HOLDOVER_STATUS_FLAG_BITS { - MBG_GNSS_FLAG_EXCLUSIVE, /**< (read only) only one of the supported GNSS systems can be used at the same time */ - MBG_GNSS_FLAG_HAS_PRIORITY, /**< (read only) priority can be configured using the MBG_GNSS_MODE_SETTINGS::prio field */ - N_MBG_GNSS_FLAGS + 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 }; -#define MBG_GNSS_FLAG_MSK_EXCLUSIVE ( 1UL << MBG_GNSS_FLAG_EXCLUSIVE ) -#define MBG_GNSS_FLAG_MSK_HAS_PRIORITY ( 1UL << MBG_GNSS_FLAG_HAS_PRIORITY ) +typedef struct +{ + uint16_t supp_flags; ///< indicates which flags are supported by ::XMULTI_REF_SETTINGS::flags, see ::XMR_SETTINGS_FLAG_MSKS + uint16_t reserved_0; + uint32_t reserved_1; +} XMR_EXT_SRC_INFO; -#define MAX_USED_SATS 32 -/* - The structure below allos to transfer - SV information from a certain GNSS type. -*/ typedef struct { - uint8_t gnss_type; /**< GNSS type from the enumeration above */ - uint8_t reserved; - uint16_t good_svs; - uint16_t svs_in_view; - uint8_t svs[MAX_USED_SATS]; -} GNSS_SAT_INFO; + uint16_t idx; // + XMR_EXT_SRC_INFO info; // -#define _mbg_swab_gnss_sat_info( _p ) \ -{ \ - _mbg_swab16( &(_p)->good_svs ); \ - _mbg_swab16( &(_p)->svs_in_view ); \ -} +} XMR_EXT_SRC_INFO_IDX; // -#ifndef _IDENT_DEFINED +/** @} defgroup group_multi_ref_ext */ - typedef union - { - char c[16]; // as string which may NOT be terminated - int16_t wrd[8]; - uint32_t lw[4]; - } IDENT; +/** @} defgroup group_multi_ref_all */ - #define _IDENT_DEFINED -#endif -#define _mbg_swab_ident( _p ) \ -{ \ - int i; \ - for ( i = 0; i < 4; i++ ) \ - _mbg_swab32( &(_p)->lw[i] ); \ -} /** - * The type below is used to configure the length of the - * antenna cable in [m]: + * @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 uint16_t ANT_CABLE_LEN; +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 -#define _mbg_swab_ant_cable_len( _p ) _mbg_swab16( _p ) +} MBG_GPIO_CFG_LIMITS; + +#define _mbg_swab_mbg_gpio_cfg_limits( _p ) \ +{ \ + _mbg_swab32( &(_p)->num_io ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} -/* Configuration data for an optional LAN interface. +/** + * @brief GPIO limits flag bits used to define ::MBG_GPIO_CFG_LIMIT_FLAG_MASKS * - * This is only supported if the flag GPS_HAS_LAN_IP4 - * is set in RECEIVER_INFO::features. + * @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 +}; -/* Basic network settings */ -typedef uint32_t IP4_ADDR; +/** + * @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 +}; -#define _mbg_swab_ip4_addr( _p ) \ - _mbg_swab32( _p ); -typedef struct +/** + * @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 { - IP4_ADDR ip_addr; - IP4_ADDR netmask; - IP4_ADDR broad_addr; - IP4_ADDR gateway; - uint16_t flags; /* see below */ - uint16_t vlan_cfg; /* see below */ + 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 +}; -} IP4_SETTINGS; -#define _mbg_swab_ip4_settings( _p ) \ -{ \ - _mbg_swab_ip4_addr( &(_p)->ip_addr ); \ - _mbg_swab_ip4_addr( &(_p)->netmask ); \ - _mbg_swab_ip4_addr( &(_p)->broad_addr ); \ - _mbg_swab_ip4_addr( &(_p)->gateway ); \ - _mbg_swab16( &(_p)->flags ); \ - _mbg_swab16( &(_p)->vlan_cfg ); \ +#define DEFAULT_GPIO_TYPES_SHORT_STRS \ +{ \ + "Freq. In", \ + "Freq. Out", \ + "Fixed Freq Out", \ + "BITS In", \ + "BITS Out" \ } -// IP4_SETTINGS::vlan_cfg contains a combination of -// a VLAN ID number plus a VLAN priiority code. -// Definitions used with IP4_SETTINGS::vlan_cfg: - -#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 ) +/** + * @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 +}; -#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 +/** + * @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 +}; -// vlan_priority = ( vlan_cfg >> VLAN_PRIORITY_SHIFT ) & VLAN_PRIORITY_MSK -#define VLAN_PRIORITY_SHIFT ( ( 8 * sizeof( uint16_t ) ) - VLAN_PRIORITY_BITS ) -#define VLAN_PRIORITY_MSK ( ( 1 << VLAN_PRIORITY_BITS ) - 1 ) -// The macros below can be 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 ) ) +/** + * @brief String initializers for GPIO signal shapes + * + * @see ::MBG_GPIO_SIGNAL_SHAPES + */ +#define DEFAULT_GPIO_SIGNAL_SHAPE_NAMES \ +{ \ + "(unspec. shape)", \ + "Sine wave", \ + "Rectangle Pulse" \ +} -#if 0 //##++ currently not used -/* Misc configuration */ +/** + * @brief A structure used to specify a variable frequency + * + * Used to specify a variable frequency for GPIO input or output + */ typedef struct { - uint16_t id; /* service ID, see below */ - uint16_t index; /* used if several same svcs must be cfg'd, e.g. DNS */ - char host[50]; /* see below */ + uint32_t hz; ///< integral number [Hz] + uint32_t frac; ///< fractional part, binary (0x80000000 --> 0.5, 0xFFFFFFFF --> 0.9999999...) -} IP_CFG; +} MBG_GPIO_FREQ; +#define _mbg_swab_mbg_gpio_freq( _p ) \ +{ \ + _mbg_swab32( &(_p)->hz ); \ + _mbg_swab32( &(_p)->frac); \ +} -/* Description of a service running on a device */ +/** + * @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 { - uint16_t id; /* service ID, see below */ - uint16_t socket; /* the socket on which the service is listening */ - uint32_t flags; /* see below */ - -} IP_SERVICE; - -#endif // 0 + 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; -/* LAN interface information */ +/** + * @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; ///< see ::MBG_IMS_STATE_FLAG_MASKS + +} MBG_IMS_STATE; + +#define _mbg_swab_mbg_ims_state( _p ) \ +{ \ + _mbg_swab16( &(_p)->num_sensors ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + + +/** + * @brief Enumeration of bits used to define ::MBG_IMS_STATE_FLAG_MASKS + * + * @see ::MBG_IMS_STATE_FLAG_MASKS + */ +enum MBG_IMS_STATE_FLAG_BITS +{ + MBG_IMS_STATE_FLAG_BIT_HAS_FDM, ///< device supports FDM API + N_MBG_IMS_STATE_FLAG_BITS +}; + + +/** + * @brief Bit masks used with ::MBG_IMS_STATE::flags + * + * @see ::MBG_IMS_STATE_FLAG_BITS + */ +enum MBG_IMS_STATE_FLAG_MASKS +{ + MBG_IMS_STATE_FLAG_MSK_HAS_FDM = ( 1UL << MBG_IMS_STATE_FLAG_BIT_HAS_FDM ) ///< see ::MBG_IMS_STATE_FLAG_BIT_HAS_FDM +}; + + + +/** + * @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 + * + * Used with ::MBG_IMS_SENSOR_STATE::type + */ +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 +}; + + + +/** + * @brief IMS sensor state flags for voltage + * + * Used with ::MBG_IMS_SENSOR_STATE::flags in case ::MBG_IMS_SENSOR_STATE::type + * is ::MBG_IMS_SENSOR_VOLTAGE. + */ +enum MBG_IMS_SENSOR_STATE_FLAG_MASK_VOLTAGE +{ + MBG_IMS_SENSOR_VOLTAGE_OUT_ENB = 0x01, ///< output is enabled + MBG_IMS_SENSOR_VOLTAGE_OUT_OVR = 0x02 ///< output overload +}; + + +/** + * @brief IMS sensor state flags for PLL + * + * Used with ::MBG_IMS_SENSOR_STATE::flags in case ::MBG_IMS_SENSOR_STATE::type + * is ::MBG_IMS_SENSOR_PLL. + */ +enum MBG_IMS_SENSOR_STATE_FLAG_MASK_PLL +{ + MBG_IMS_SENSOR_PLL_LOCKED = 0x01 ///< PLL is locked +}; + + + +/** + * @brief DAC limit specs + */ +typedef struct +{ + int32_t dac_val_min; ///< min. possible DAC Value, positive or negative + int32_t dac_val_max; ///< max. possible DAC Value, positive or negative + + int32_t u_min; ///< min. possible real voltage range, positive or negative, depending on ::MBG_DAC_SPECS::dac_val_min + int32_t u_max; ///< max. possible real voltage range, positive or negative, depending on ::MBG_DAC_SPECS::dac_val_max + + uint32_t reserved_0; ///< reserved, currently always 0 + uint32_t reserved_1; ///< reserved, currently always 0 + +} MBG_DAC_SPECS; + +#define _mbg_swab_mbg_dac_specs( _p ) \ +{ \ + _mbg_swab32( &(_p)->dac_val_min ); \ + _mbg_swab32( &(-p)->dac_val_max ); \ + _mbg_swab32( &(_P)->u_min ); \ + _mbg_swab32( &(_p)->u_max ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ +} + + + +/** + * @brief Output state of FDM device. + * + * @note This is only supported if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + */ +typedef struct +{ + int32_t dac_val; ///< current DAC value, positive or negative + uint32_t mode; ///< current output mode, see ::MBG_IMS_FDM_OUTPUT_MODES + + MBG_DAC_SPECS dac_specs; ///< DAC specific limits + + uint32_t reserved_0; ///< reserved, currently always 0 + uint32_t reserved_1; ///< reserved, currently always 0 + +} MBG_IMS_FDM_OUTPUT_STATE; + +#define _mbg_swab_mbg_ims_fdm_output_state( _p ) \ +{ \ + _mbg_swab32( &(_p)->dac_val ); \ + _mbg_swab32( &(_p)->mode ); \ + _mbg_swab_mbg_dac_specs( &(_p)->dac_specs ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ +} + + +/** + * @brief Output state of FDM device plus index. + */ +typedef struct +{ + uint32_t idx; + MBG_IMS_FDM_OUTPUT_STATE state; + +} MBG_IMS_FDM_OUTPUT_STATE_IDX; + +#define _mbg_swab_mbg_ims_fdm_output_state_idx( _p ) \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_mbg_ims_fdm_output_state( &(_p)->state ); \ +} + + + +/** + * @brief Output settings of FDM device + * + * @note This is only supported if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + */ +typedef struct +{ + uint32_t mode; ///< mode, see ::MBG_IMS_FDM_OUTPUT_MODES + uint32_t reserved; ///< reserved, currently always 0 + +} MBG_IMS_FDM_OUTPUT_SETTINGS; + +#define _mbg_swab_mbg_ims_fdm_output_settings( _p ) \ +{ \ + _mbg_swab32( &(_p)->mode ); \ + _mbg_swab32( &(_p)->reserved ); \ +} + + +/** + * @brief Output settings for FDM devices plus index. + */ +typedef struct +{ + uint32_t idx; + MBG_IMS_FDM_OUTPUT_SETTINGS settings; + +} MBG_IMS_FDM_OUTPUT_SETTINGS_IDX; + +#define _mbg_swab_mbg_ims_fdm_output_settings_idx( _p ) \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_mbg_ims_fdm_output_settings( &(_p)->settings ); \ +} + + + +/** + * @brief Specific output settings and limits. + */ +typedef struct +{ + MBG_IMS_FDM_OUTPUT_SETTINGS settings; ///< current settings + uint32_t supp_modes; ///< supported modes, see ::MBG_IMS_FDM_OUTPUT_MODE_MASKS + MBG_DAC_SPECS dac_specs; ///< DAC specific limits + +} MBG_IMS_FDM_OUTPUT_INFO; + +#define _mbg_swab_mbg_ims_fdm_output_info( _p ) \ +{ \ + _mbg_swab_mbg_ims_fdm_output_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_modes ); \ + _mbg_swab_mbg_dac_specs( &(_p)->dac_specs ); \ +} + + +/** + * @brief Specific output settings and limits, plus index. + */ +typedef struct +{ + uint32_t idx; + MBG_IMS_FDM_OUTPUT_INFO info; + +} MBG_IMS_FDM_OUTPUT_INFO_IDX; + +#define _mbg_swab_mbg_ims_fdm_output_info_idx( _p ) \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_mbg_ims_fdm_output_info( &(_p)->info ); \ +} + + + +/** + * @brief Enumeration of known output modes + * + * Used with ::MBG_IMS_FDM_OUTPUT_STATE::mode + * + * @see ::MBG_IMS_FDM_OUTPUT_MODE_MASKS + */ +enum MBG_IMS_FDM_OUTPUT_MODES +{ + MBG_IMS_FDM_OUTPUT_MODE_FD, ///< Analog output reflects frequency deviation + MBG_IMS_FDM_OUTPUT_MODE_TD, ///< Analog output reflects time deviation + N_MBG_IMS_FDM_OUTPUT_MODES ///< Number of known output modes +}; + + +/** + * @brief Bit masks used with ::MBG_IMS_FDM_OUTPUT_STATE::mode + * + * @see ::MBG_IMS_FDM_OUTPUT_MODES + */ +enum MBG_IMS_FDM_OUTPUT_MODE_MASKS +{ + MBG_IMS_FDM_OUTPUT_MODE_MSK_FD = ( 1UL << MBG_IMS_FDM_OUTPUT_MODE_FD ), ///< see ::MBG_IMS_FDM_OUTPUT_MODE_FD + MBG_IMS_FDM_OUTPUT_MODE_MSK_TD = ( 1UL << MBG_IMS_FDM_OUTPUT_MODE_TD ) ///< see ::MBG_IMS_FDM_OUTPUT_MODE_TD +}; + + + +/** + * @brief A generic structure used to specify FDM limits + */ +typedef struct +{ + uint8_t n_outputs; ///< number of outputs per module + uint8_t reserved_0; ///< reserved, currently always 0 + uint16_t reserved_1; ///< reserved, currently always 0 + + uint32_t fd_min; ///< min. frequency deviation limit, 1/::MBG_IMS_FDM_LIMITS::fd_scale Hz units + uint32_t fd_max; ///< max. frequency deviation limit, 1/::MBG_IMS_FDM_LIMITS::fd_scale Hz units + uint32_t fd_scale; ///< scale for ::MBG_IMS_FDM_LIMITS::fd_min and ::MBG_IMS_FDM_LIMITS::fd_max + + uint32_t td_min; ///< min. time deviation limit, 1/::MBG_IMS_FDM_LIMITS::td_scale s units + uint32_t td_max; ///< max. time deviation limit, 1/::MBG_IMS_FDM_LIMITS::td_scale s units + uint32_t td_scale; ///< scale for ::MBG_IMS_FDM_LIMITS::td_min and ::MBG_IMS_FDM_LIMITS::td_max + + uint32_t reserved_2; ///< reserved, currently always 0 + +} MBG_IMS_FDM_LIMITS; + +#define _mbg_swab_mbg_ims_fdm_limits( _p ) \ +{ \ + _mbg_swab8( &(_p)->n_outputs ); \ + _mbg_swab8( &(_p)->reserved_0 ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->fd_min ); \ + _mbg_swab32( &(_p)->fd_max ); \ + _mbg_swab32( &(_p)->td_min ); \ + _mbg_swab32( &(_p)->td_max ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ +} + + + +/** + * @brief State of FDM device + * + * @note This is only supported if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags. + * + */ +typedef struct +{ + MBG_GPIO_FREQ freq; ///< Current frequency + + NANO_TIME_64 t_ref; ///< Current reference time + NANO_TIME_64 t_plt; ///< Current power line time + NANO_TIME_64 t_sync; ///< Last sync Time (reference time) + + uint32_t line_freq; ///< Nominal line frequency, see ::MBG_IMS_FDM_LINE_FREQS + uint32_t flags; ///< Flags, see ::MBG_IMS_FDM_STATE_FLAG_MASKS + uint32_t reserved; ///< Reserved, currently always 0 + +} MBG_IMS_FDM_STATE; + +#define _mbg_swab_mbg_ims_fdm_state( _p ) \ +{ \ + _mbg_swab_mbg_gpio_freq( &(_p)->freq ); \ + _mbg_swab_nano_time_64( &(_p)->t_ref ); \ + _mbg_swab_nano_time_64( &(_p)->t_plt ); \ + _mbg_swab_nano_time_64( &(_p)->t_sync ); \ + _mbg_swab32( &(_p)->line_freq ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab32( &(_p)->reserved ); \ +} + + + +/** + * @brief Enumeration known line frequencies + * + * Used with ::MBG_IMS_FDM_STATE::line_freq + * + * @see ::MBG_IMS_FDM_LINE_FREQ_MASKS + */ +enum MBG_IMS_FDM_LINE_FREQS +{ + MBG_IMS_FDM_LINE_FREQ_AUTO, ///< Auto detect line frequency + MBG_IMS_FDM_LINE_FREQ_50HZ, ///< 50Hz line frequency + MBG_IMS_FDM_LINE_FREQ_60HZ, ///< 60Hz line frequency + N_MBG_IMS_FDM_LINE_FREQS ///< number of known line frequencies +}; + + +/** + * @brief Bit masks corresponding to defined line frequencies + * + * @see ::MBG_IMS_FDM_LINE_FREQS + */ +enum MBG_IMS_FDM_LINE_FREQ_MASKS +{ + MBG_IMS_FDM_LINE_FREQ_MSK_AUTO = ( 1UL << MBG_IMS_FDM_LINE_FREQ_AUTO ), ///< see ::MBG_IMS_FDM_LINE_FREQ_AUTO + MBG_IMS_FDM_LINE_FREQ_MSK_50HZ = ( 1UL << MBG_IMS_FDM_LINE_FREQ_50HZ ), ///< see ::MBG_IMS_FDM_LINE_FREQ_50HZ + MBG_IMS_FDM_LINE_FREQ_MSK_60HZ = ( 1UL << MBG_IMS_FDM_LINE_FREQ_60HZ ) ///< see ::MBG_IMS_FDM_LINE_FREQ_60HZ +}; + + + +/** + * @brief Enumeration of flag bits used to define ::MBG_IMS_FDM_STATE_FLAG_MASKS + */ +enum MBG_IMS_FDM_STATE_FLAG_BITS +{ + MBG_IMS_FDM_STATE_FLAG_BIT_SYNC_AFTER_RESET, ///< if sync'ed after reset + MBG_IMS_FDM_STATE_FLAG_BIT_PLT_IS_LOCKED, ///< Power Line Time is locked + MBG_IMS_FDM_STATE_FLAG_BIT_FD_OVERFLOW, ///< Frequency deviation overflow occurred + MBG_IMS_FDM_STATE_FLAG_BIT_TD_OVERFLOW, ///< Time deviation overflow occurred + N_MBG_IMS_FDM_STATE_FLAG_BITS ///< number of known state flag bits +}; + + +/** + * @brief Bit masks used with ::MBG_IMS_FDM_STATE::flags + * + * @see ::MBG_IMS_FDM_STATE_FLAG_BITS + */ +enum MBG_IMS_FDM_STATE_FLAG_MASKS +{ + MBG_IMS_FDM_STATE_FLAG_MSK_SYNC_AFTER_RESET = ( 1UL << MBG_IMS_FDM_STATE_FLAG_BIT_SYNC_AFTER_RESET ), ///< see ::MBG_IMS_FDM_STATE_FLAG_BIT_SYNC_AFTER_RESET + MBG_IMS_FDM_STATE_FLAG_MSK_PLT_IS_LOCKED = ( 1UL << MBG_IMS_FDM_STATE_FLAG_BIT_PLT_IS_LOCKED ), ///< see ::MBG_IMS_FDM_STATE_FLAG_BIT_PLT_IS_LOCKED + MBG_IMS_FDM_STATE_FLAG_MSK_FD_OVERFLOW = ( 1UL << MBG_IMS_FDM_STATE_FLAG_BIT_FD_OVERFLOW ), ///< see ::MBG_IMS_FDM_STATE_FLAG_BIT_FD_OVERFLOW + MBG_IMS_FDM_STATE_FLAG_MSK_TD_OVERFLOW = ( 1UL << MBG_IMS_FDM_STATE_FLAG_BIT_TD_OVERFLOW ) ///< see ::MBG_IMS_FDM_STATE_FLAG_BIT_TD_OVERFLOW +}; + + + +/** + * @brief FDM device settings + * + * @note This is only supported if ::MBG_IMS_STATE_FLAG_BIT_HAS_FDM is set in ::MBG_IMS_STATE::flags. + * + */ +typedef struct +{ + uint32_t fd_min; ///< min. frequency deviation limit in 100 uHz steps + uint32_t fd_max; ///< max. frequency deviation limit in 100 uHz steps + + uint32_t td_min; ///< min. time deviation limit in 100 us steps + uint32_t td_max; ///< max. time deviation limit in 100 us steps + + uint32_t line_freq; ///< nominal line frequency, see ::MBG_IMS_FDM_LINE_FREQS + uint32_t reserved; ///< reserved, currently always 0 + +} MBG_IMS_FDM_SETTINGS; + +#define _mbg_swab_mbg_ims_fdm_settings( _p ) \ +{ \ + _mbg_swab32( &(_p)->fd_min ); \ + _mbg_swab32( &(_p)->fd_max ); \ + _mbg_swab32( &(_p)->td_min ); \ + _mbg_swab32( &(_p)->td_max ); \ + _mbg_swab32( &(_p)->mode ); \ + _mbg_swab32( &(_p)->reserved ); \ +} + + +/** +* @brief Specific FDM settings and limits. +*/ +typedef struct +{ + MBG_IMS_FDM_SETTINGS settings; + uint32_t supp_line_freqs; ///< Bit mask of supported line frequencies, see ::MBG_IMS_FDM_LINE_FREQ_MASKS + uint32_t reserved; ///< Reserved, currently always 0 + uint32_t flags; ///< Flags, currently always 0 + +} MBG_IMS_FDM_INFO; + +#define _mbg_swab_mbg_ims_fdm_info( _p ) \ +{ \ + _mbg_swab_mbg_ims_fdm_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_line_freqs ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} + +/** @} defgroup group_ims */ + + + +/** + * @defgroup group_generic_io Generic I/O support. + * + * The definitions below are used with the GENERIC_IO API. + * + * This API is NOT 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 (not the string notation), b[0] == LSBs + +} IP6_ADDR; + + + +/** + * @brief An IPv6 address plus number of netmask bits + */ +typedef struct +{ + IP6_ADDR addr; ///< bit mask of the bytes holding the address bits, b[0] == LSBs + uint8_t prefix; ///< Number of subnet mask bits for CIDR notation, e.g. 24 for /24 + uint8_t reserved[3]; ///< Reserved, alignment, currently 0 + +} IP6_ADDR_CIDR; + + + +/** @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 Possible IPv6 Multicast Scopes + * + * If the first (most significant) byte of an IPv6 address is 0xFF this + * indicates that the address is a multicast address, and in this case + * the second byte determines the scope for which the specified address + * is valid. These scope ID numbers are assigned in RFC 7346 which + * supersedes RFC 4291. + * + * @see ::IPV6_MULTICAST_SCOPE_NAME_TABLE_ENTRIES + */ +enum IPV6_MULTICAST_SCOPES +{ + IPV6_MULTICAST_SCOPE_INTF_LOCAL = 0x01, ///< Interface-Local scope + IPV6_MULTICAST_SCOPE_LINK_LOCAL, ///< Link-Local scope + IPV6_MULTICAST_SCOPE_REALM_LOCAL, ///< Realm-Local scope + IPV6_MULTICAST_SCOPE_ADMIN_LOCAL, ///< Admin-Local scope + IPV6_MULTICAST_SCOPE_SITE_LOCAL, ///< Site-Local scope + IPV6_MULTICAST_SCOPE_ORGA_LOCAL = 0x08, ///< Organization-Local scope + IPV6_MULTICAST_SCOPE_GLOBAL_SCOPE = 0x0E ///< Global scope +}; + + +/** + * @brief Name strings for IPv6 multicast scopes + * + * This can e.g. be used to initialize an array of ::MBG_CODE_NAME_TABLE_ENTRY elements. + * + * @see ::IPV6_MULTICAST_SCOPES + */ +#define IPV6_MULTICAST_SCOPE_NAME_TABLE_ENTRIES \ +{ \ + { IPV6_MULTICAST_SCOPE_INTF_LOCAL, "FF01 - Interface-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_LINK_LOCAL, "FF02 - Link-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_REALM_LOCAL, "FF03 - Realm-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_ADMIN_LOCAL, "FF04 - Admin-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_SITE_LOCAL, "FF05 - Site-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_ORGA_LOCAL, "FF08 - Organization-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_GLOBAL_SCOPE, "FF0E - Global Scope" }, \ + { 0, NULL } \ +} + + + +/** + * @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 +{ + /// In ::LAN_IF_INFO::flags this reports if DHCP is supported by the device. + /// If supported then it can also be used with ::IP4_SETTINGS::flags to enable + /// or disable DHCP for the network interface. + IP4_BIT_DHCP, + + /// Only used with ::IP4_SETTINGS::flags. Set if port link has been established. + IP4_BIT_LINK, + + /// In ::LAN_IF_INFO::flags this reports if VLAN is supported by the device. + /// If supported then it can also be used with ::IP4_SETTINGS::flags to enable + /// or disable VLAN for the network interface. + IP4_BIT_VLAN, + + 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, + MBG_NET_LINK_OPT_CAN_SYNCE, + 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 + MBG_NET_LINK_OPT_MASK_CAN_SYNCE = ( 1UL << MBG_NET_LINK_OPT_CAN_SYNCE ) ///< see ::MBG_NET_LINK_OPT_CAN_SYNCE +}; + + + +/** + * @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; ///< Number of subnet mask bits for CIDR notation, e.g. 24 for /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 + //##++++ TODO: Add a code for 0xFE (unknown), or eventually + // redesign the lookup of associated strings completely. +}; + + +/** + * @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 + PTP_ROLE_NTP_SERVER, ///< NTP Unicast Server + PTP_ROLE_NTP_CLIENT, ///< NTP Unicast Client + 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 + PTP_ROLE_MSK_NTP_SERVER = ( 1UL << PTP_ROLE_NTP_SERVER ), ///< see ::PTP_ROLE_NTP_SERVER + PTP_ROLE_MSK_NTP_CLIENT = ( 1UL << PTP_ROLE_NTP_CLIENT ) ///< see ::PTP_ROLE_NTP_CLIENT +}; + + +#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", \ + "NTP Server", \ + "NTP Client" \ +} + + +/** + * @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", \ + "NSV", \ + "NCL" \ +} + + +/** + * @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 @ref 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 @ref 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 @ref 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 + + PTP_CFG_TSU_RESET, ///< [R/-] supports TSU reset via register cmd + PTP_CFG_NTP_HW_TS_MASTER, ///< [R/-] supports the NTP HW time stamping in Master mode + PTP_CFG_NTP_HW_TS_SLAVE, ///< [R/-] supports the NTP HW time stamping in Slave mode + PTP_CFG_SYNCE_MASTER, ///< [R/-] Hardware supports Synchronous Ethernet Out + PTP_CFG_SYNCE_SLAVE, ///< [R/-] Hardware supports Synchronous Ethernet In + PTP_CFG_HAS_MUX, ///< [R/-] Hardware supports multiplexed signal outputs + + N_PTP_CFG_FLAGS ///< the number of defined flags +}; + + +/** + * @defgroup group_PTP_CFG_FLAG_MASKS Bit masks used with ::PTP_CFG_INFO::supp_flags and ::PTP_CFG_SETTINGS::flags + * + * @see ::PTP_CFG_FLAGS + * + * @anchor PTP_CFG_FLAG_MASKS + * + * @{ */ + +#define PTP_CFG_MSK_TIME_SCALE_IS_PTP ( 1UL << PTP_CFG_TIME_SCALE_IS_PTP ) ///< see ::PTP_CFG_TIME_SCALE_IS_PTP +#define PTP_CFG_MSK_V1_HW_COMPAT ( 1UL << PTP_CFG_V1_HW_COMPAT ) ///< see ::PTP_CFG_V1_HW_COMPAT +#define PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE ( 1UL << PTP_CFG_CAN_BE_UNICAST_SLAVE ) ///< see ::PTP_CFG_CAN_BE_UNICAST_SLAVE +#define PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER ( 1UL << PTP_CFG_CAN_BE_MULTICAST_MASTER ) ///< see ::PTP_CFG_CAN_BE_MULTICAST_MASTER +#define PTP_CFG_MSK_CAN_BE_UNICAST_MASTER ( 1UL << PTP_CFG_CAN_BE_UNICAST_MASTER ) ///< see ::PTP_CFG_CAN_BE_UNICAST_MASTER +#define PTP_CFG_MSK_CAN_BE_MULTICAST_AUTO ( 1UL << PTP_CFG_CAN_BE_MULTICAST_AUTO ) ///< see ::PTP_CFG_CAN_BE_MULTICAST_AUTO +#define PTP_CFG_MSK_SUPP_UTC_VALID ( 1UL << PTP_CFG_SUPP_UTC_VALID ) ///< see ::PTP_CFG_SUPP_UTC_VALID +#define PTP_CFG_MSK_CAN_BE_BOTH_MASTER ( 1UL << PTP_CFG_CAN_BE_BOTH_MASTER ) ///< see ::PTP_CFG_CAN_BE_BOTH_MASTER + +#define PTP_CFG_MSK_HYBRID_MASTER ( 1UL << PTP_CFG_HYBRID_MASTER ) ///< see ::PTP_CFG_HYBRID_MASTER +#define PTP_CFG_MSK_HYBRID_SLAVE ( 1UL << PTP_CFG_HYBRID_SLAVE ) ///< see ::PTP_CFG_HYBRID_SLAVE +#define PTP_CFG_MSK_ONE_STEP_MASTER ( 1UL << PTP_CFG_ONE_STEP_MASTER ) ///< see ::PTP_CFG_ONE_STEP_MASTER +#define PTP_CFG_MSK_MNGMNT_MSGS_DISB ( 1UL << PTP_CFG_MNGMNT_MSGS_DISB ) ///< see ::PTP_CFG_MNGMNT_MSGS_DISB +#define PTP_CFG_MSK_SUPP_MCAST_SLAVE_FLAG ( 1UL << PTP_CFG_SUPP_MCAST_SLAVE_FLAG ) ///< see ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG +#define PTP_CFG_MSK_CAN_BE_MULTICAST_SLAVE ( 1UL << PTP_CFG_CAN_BE_MULTICAST_SLAVE ) ///< see ::PTP_CFG_CAN_BE_MULTICAST_SLAVE +#define PTP_CFG_MSK_ONE_STEP_L2 ( 1UL << PTP_CFG_ONE_STEP_L2 ) ///< see ::PTP_CFG_ONE_STEP_L2 +#define PTP_CFG_MSK_ONE_STEP_P2P ( 1UL << PTP_CFG_ONE_STEP_P2P ) ///< see ::PTP_CFG_ONE_STEP_P2P + +#define PTP_CFG_MSK_TSU_RESET ( 1UL << PTP_CFG_TSU_RESET ) ///< see ::PTP_CFG_TSU_RESET +#define PTP_CFG_MSK_NTP_HW_TS_MASTER ( 1UL << PTP_CFG_NTP_HW_TS_MASTER ) ///< see ::PTP_CFG_NTP_HW_TS_MASTER +#define PTP_CFG_MSK_NTP_HW_TS_SLAVE ( 1UL << PTP_CFG_NTP_HW_TS_SLAVE) ///< see ::PTP_CFG_NTP_HW_TS_SLAVE +#define PTP_CFG_MSK_SYNCE_MASTER ( 1UL << PTP_CFG_SYNCE_MASTER ) ///< see ::PTP_CFG_SYNCE_MASTER +#define PTP_CFG_MSK_SYNCE_SLAVE ( 1UL << PTP_CFG_SYNCE_SLAVE ) ///< see ::PTP_CFG_SYNCE_SLAVE +#define PTP_CFG_MSK_HAS_MUX ( 1UL << PTP_CFG_HAS_MUX ) ///< see ::PTP_CFG_HAS_MUX + +/** @} defgroup group_PTP_CFG_FLAG_MASKS */ + + + +/** @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 Register in TSU-GbE FPGA to determine board features of the current TSU board revision + */ +typedef uint16_t PTP_HW_FEATURES; + + + +/** + * @brief Bits used to define ::PTP_HW_FEAT_MASKS + */ +enum PTP_HW_FEAT_BITS +{ + PTP_FEAT_SYNCE_EXT_MUX, ///< [R] supports SyncE and external signal multiplexer + N_PTP_HW_FEAT ///< the number of defined features +}; + + +// TODO fix comment linkage +/** + * @brief Bit masks used with ::PTP_HW_FEATURES + * + * @see ::PTP_HW_FEAT_BITS + */ +enum PTP_HW_FEAT_MASKS +{ + PTP_HW_FEAT_MSK_SYNCE_EXT_MUX = ( 1UL << PTP_FEAT_SYNCE_EXT_MUX ) ///< see ::PTP_FEAT_SYNCE_EXT_MUX +}; + + + +/** + * @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 + PTP_OPT_EXT_TELECOM_PHASE, ///< ITU-T G.8275.1 profile extension + PTP_OPT_EXT_SMPTE, ///< SMPTE ST 2059-2 profile extension + N_PTP_OPT_EXT ///< number of known optional extensions +}; + + +/** + * @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 + PTP_MSK_OPT_EXT_TELECOM_PHASE = ( 1UL << PTP_OPT_EXT_TELECOM_PHASE ), ///< see ::PTP_OPT_EXT_TELECOM_PHASE + PTP_MSK_OPT_EXT_SMPTE = ( 1UL << PTP_OPT_EXT_SMPTE ) ///< see ::PTP_OPT_EXT_SMPTE +}; + + + +/** + * @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 + PTP_PRESETS_TELECOM_PHASE, ///< ITU-T G.8275.1 profile extension, only if ::PTP_MSK_OPT_EXT_TELECOM_PHASE is set + PTP_PRESETS_SMPTE, ///< SMPTE ST 2059-2 profile extension, only if ::PTP_MSK_OPT_EXT_SMPTE is set + N_PTP_PRESETS ///< number of supported presets +}; + + +/** + * @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 + PTP_MSK_PRESETS_TELECOM_PHASE = ( 1UL << PTP_PRESETS_TELECOM_PHASE ), ///< see ::PTP_PRESETS_TELECOM_PHASE + PTP_MSK_PRESETS_SMPTE = ( 1UL << PTP_PRESETS_SMPTE ) ///< see ::PTP_PRESETS_SMPTE +}; + + +/** + * @brief Name strings for defined PTP presets + * + * @see ::PTP_PRESETS + */ +#define PTP_PRESETS_STRS \ +{ \ + "Custom", \ + "Default E2E IEEE1588-2008", \ + "Default P2P IEEE1588-2008", \ + "Power IEEE C37.238", \ + "Telecom ITU-T G.8265.1", \ + "Telecom ITU-T G.8275.1", \ + "SMPTE ST 2059-2" \ +} + + + +/** + * @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 ); \ +} + + + + +#if 1 // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +// TODO: These definitions are preliminary and maybe subject to changes. + + +/** + * @brief SMPTE System Frame Rates according to SMPTE ST 2059-2 + * + * @see ::XXX + */ +enum SMPTE_SYSTEM_FRAME_RATES +{ + SMPTE_23_98HZ, + SMPTE_24HZ, + SMPTE_25HZ, + SMPTE_29_97HZ, + SMPTE_50HZ, + SMPTE_59_94HZ, + N_SMPTE_SYSTEM_FRAME_RATES +}; + + +#define SMPTE_SYSTEM_FRAME_RATE_STR \ +{ \ + "24Hz (23.98)", \ + "24Hz", \ + "25Hz", \ + "30Hz (29.97)", \ + "50Hz", \ + "60Hz (59.94)" \ +} + + +#define SMPTE_FRAME_RATE_NUM \ +{ \ + 24000, \ + 24000, \ + 25000, \ + 30000, \ + 50000, \ + 60000, \ +} + +#define SMPTE_FRAME_RATE_DENUM \ +{ \ + 1001, \ + 1000, \ + 1000, \ + 1001, \ + 1000, \ + 1001, \ +} + + +/** + * @brief Additional parameters for SMPTE ST 2059-2 profile + * + * This stucture holds the synchronization metadata required for the SMPTE profile. + * This structure is only used for internal storage of the data. The data is + * distributed through a network by using management messages and the dedicated + * organization extension TLV defined in the SMPTE profile. + */ +typedef struct +{ + /// Default system frame rate + /// Default video frame rate of the slave system as a lowest term rational. + /// The data type shall be composed of a pair of unsigned Int32 values coded + /// in big-endian form where the first shall be the numerator and the second + /// shall be the denominator. The denominator shall be the smallest value + /// that represents the frame rate denominator. + /// For example, 29.97 Hz: (30000/1001) or 25 Hz: (25/1). + uint32_t defaultSystemFrameRateNum; + uint32_t defaultSystemFrameRateDenum; + + /// Master locking status + /// Complementary information to clockClass (0: Not in use, 1: Free Run, + /// 2: Cold Locking, 3: Warm Locking, 4: Locked) + uint8_t masterLockingStatus; + + /// Time Address Flags + /// Indicates the intended ST 12-1 flags. + /// Bit 0: Drop frame (0: Non-drop-frame, 1: Drop-frame) + /// Bit 1: Color Frame Identification (0: Not in use, 1: In use) + /// Bits 2-7: Reserved + uint8_t timeAddressFlags; + + /// Current local offset + /// Offset in seconds of Local Time from PTP time. For example, if Local + /// Time is Eastern Standard Time (North America) UTC-5 and the number of + /// leap seconds is 35, the value will be -18035 (decimal). + int32_t currentLocalOffset; + + /// Jump seconds + /// The size of the next discontinuity, in seconds, of Local Time. A value + /// of zero indicates that no discontinuity is expected. A positive value + /// indicates that the discontinuity will cause the currentLocalOffset to increase. + int32_t jumpSeconds; + + /// Time of next jump + /// The value of the seconds portion of the master PTP time at the time + /// that the next discontinuity of the currentLocalOffset will occur. The + /// discontinuity occurs at the start of the second indicated + uint8_t timeOfNextJump[6]; + + /// Daily jam + /// Daily point in Local Time (in ten-minute intervals since midnight) for + /// jamming ST 12-1 time address to Local Time. 255: Daily jam not in use + /// 1-143: Daily Jam Time offset since midnight in number of ten-minute + /// intervals since midnight. A value 0 indicated midnight; 143 indicates + /// ten minutes to next midnight. 144 and 254: Reserved + uint8_t dailyJamTime; + + /// Previous daily jam + /// Point in Local Time (in ten-minute intervals since midnight) of previous + /// jam of ST 12-1 time address to Local Time. This item shall be updated in + /// the message immediately following a jam event. Value definition as daily + /// Jam Time + uint8_t previousDailyJamTime; + + /// Previous jam local offset + /// The value of currentLocalOffset at the previous daily jam time. + /// If a discontinuity of Local Time occurs at the jam time, this parameter + /// reflects the offset after the discontinuity + int32_t previousJamLocalOffset; + + /// Daylight saving + /// Bit 0: Current Daylight Saving (0: Not in effect, 1: In effect) + /// Bit 1: Daylight Saving at next discontinuity (0: Not in effect, 1: In effect) + /// Bit 2: Daylight Saving at previous daily jam time (0: Not in effect, 1: In effect) + /// Bits 3-7: Reserved + uint8_t daylightSaving; + +} PTP_SMPTE_PROFILE_CFG; + + + +/** + * @brief Additional parameters for Telecom8275.1 profile + */ +typedef struct +{ + uint8_t use_alternate_multicast_address; + +} PTP_TELECOMG8275_PROFILE_CFG; + +#define _mbg_swab_ptp_telecom8275_profile_cfg( _p ) \ +{ \ + _mbg_swab8( &(_p)->use_alternate_multicast_mac_address ); \ +} + + + +/** + * @brief A type which holds one of the ITU-T SSM codes + * + * @see ::ITU_SSM_CODES + */ +typedef uint16_t ITU_SSM_CODE; + + + +/** + * @brief ITU-T SSM codes acc. to Recommendation G.781 + * + * @see ::ITU_SSM_CODE + */ +enum ITU_SSM_CODES +{ + ITU_SSM_CODE_STU_UKN, + ITU_SSM_CODE_PRS, + ITU_SSM_CODE_PRC, + ITU_SSM_CODE_INV3, + ITU_SSM_CODE_SSU_A_TNC, + ITU_SSM_CODE_INV5, + ITU_SSM_CODE_INV6, + ITU_SSM_CODE_ST2, + ITU_SSM_CODE_SSU_B, + ITU_SSM_CODE_INV9, + ITU_SSM_CODE_ST3, + ITU_SSM_CODE_SEC, + ITU_SSM_CODE_SMC, + ITU_SSM_CODE_ST3E, + ITU_SSM_CODE_PROV, + ITU_SSM_CODE_DNU_DUS, + N_ITU_SSM_CODES +}; + + +#define N_SSM_CODES_OPTION_1 5 +#define N_SSM_CODES_OPTION_2 9 + + +/** + * @brief Name strings for SSM codes, network option I + * + * @see ::ITU_SSM_CODES + */ +#define ITU_SSM_CODE_OPT_1_STRS \ +{ \ + "", \ + "", \ + "QL-PRC", \ + "", \ + "QL-SSU-A", \ + "", \ + "", \ + "", \ + "QL-SSU-B", \ + "", \ + "", \ + "QL-SEC", \ + "", \ + "", \ + "", \ + "QL-DNU" \ +} + + + +/** + * @brief Name strings for SSM codes, network option II + * + * @see ::ITU_SSM_CODES + */ +#define ITU_SSM_CODE_OPT_2_STRS \ +{ \ + "QL-STU", \ + "QL-PRS", \ + "", \ + "", \ + "QL-TNC", \ + "", \ + "", \ + "QL-ST2", \ + "", \ + "", \ + "QL-ST3", \ + "", \ + "QL-SMC", \ + "QL-ST3E", \ + "QL-PROV", \ + "QL-DUS" \ +} + + + +/** + * @brief Name strings for SSM codes, option I and II combined + * + * @see ::ITU_SSM_CODES + */ +#define ITU_SSM_CODE_STRS_COMBINED \ +{ \ + "QL-STU/UKN", \ + "QL-PRS", \ + "QL-PRC", \ + "QL-INV3", \ + "QL-SSU-A/TNC", \ + "QL-INV5", \ + "QL-INV6", \ + "QL-ST2", \ + "QL-SSU-B", \ + "QL-INV9", \ + "QL-EEC2/ST3", \ + "QL-EEC1/SEC", \ + "QL-SMC", \ + "QL-ST3E", \ + "QL-PROV", \ + "QL-DNU/DUS", \ +} + + +/** + * @brief SDH network options + * + * @see ::SDH_NETWORK_OPTION_MASKS + */ +enum SDH_NETWORK_OPTION +{ + SDH_NETWORK_OPTION_1, + SDH_NETWORK_OPTION_2, + N_SDH_NETWORK_OPTIONS + +}; + + + +/** + * @brief Flag masks used with ::MBG_SYNC_E_INFO::supp_sdh_network_opts + * + * @see ::SDH_NETWORK_OPTION + */ +enum SDH_NETWORK_OPTION_MASKS +{ + SDH_NETWORK_OPTION_1_MSK = ( 1UL << SDH_NETWORK_OPTION_1 ), ///< see ::SDH_NETWORK_OPTION_1_MSK + SDH_NETWORK_OPTION_2_MSK = ( 1UL << SDH_NETWORK_OPTION_2 ), ///< see ::SDH_NETWORK_OPTION_2_MSK +}; + + + +/** + * @brief Name strings for SDH network options + * + * @see ::SDH_NETWORK_OPTION + */ +#define SDH_NETWORK_OPTION_STRS \ +{ \ + "SDH Network Opt. 1", \ + "SDH Network Opt. 2", \ +} + + + +//##++++ TODO: shouldn't this be merged with / replaced by MBG_NET_LINK_MODES? +/** + * @brief Link modes for SyncE on a 1000BASE-T interface + * + * @see ::GBIT_LINK_COPPER_MODE_MASKS + */ +enum GBIT_LINK_COPPER_MODE +{ + GBIT_LINK_COPPER_AUTO, // valid if synce is disabled + GBIT_LINK_COPPER_FORCE_SYNCE_AUTO, + GBIT_LINK_COPPER_FORCE_OR_IS_MASTER, // Used in both structures, settings and status + GBIT_LINK_COPPER_FORCE_OR_IS_SLAVE, // Used in both structures, settings and status + GBIT_LINK_COPPER_PREFER_MASTER, + GBIT_LINK_COPPER_PREFER_SLAVE, + N_GBIT_LINK_COPPER_MODES +}; + + + +/** + * @brief Flag masks used with ::MBG_SYNC_E_INFO::supp_gbit_link_copper_modes + * + * @see ::GBIT_LINK_COPPER_MODE + */ +enum GBIT_LINK_COPPER_MODE_MASKS +{ + GBIT_LINK_COPPER_AUTO_MSK = ( 1UL << GBIT_LINK_COPPER_AUTO ), ///< see ::GBIT_LINK_COPPER_AUTO_MSK + GBIT_LINK_COPPER_FORCE_SYNCE_AUTO_MSK = ( 1UL << GBIT_LINK_COPPER_FORCE_SYNCE_AUTO ), ///< see ::GBIT_LINK_COPPER_FORCE_SYNCE_AUTO + GBIT_LINK_COPPER_FORCE_OR_IS_MASTER_MSK = ( 1UL << GBIT_LINK_COPPER_FORCE_OR_IS_MASTER ), ///< see ::GBIT_LINK_COPPER_FORCE_OR_IS_MASTER + GBIT_LINK_COPPER_FORCE_OR_IS_SLAVE_MSK = ( 1UL << GBIT_LINK_COPPER_FORCE_OR_IS_SLAVE ), ///< see ::GBIT_LINK_COPPER_FORCE_OR_IS_SLAVE + GBIT_LINK_COPPER_PREFER_MASTER_MSK = ( 1UL << GBIT_LINK_COPPER_PREFER_MASTER ), ///< see ::GBIT_LINK_COPPER_PREFER_MASTER + GBIT_LINK_COPPER_PREFER_SLAVE_MSK = ( 1UL << GBIT_LINK_COPPER_PREFER_SLAVE ) ///< see ::GBIT_LINK_COPPER_PREFER_SLAVE +}; + + + +//##++++ TODO: shouldn't this be merged with MBG_NET_LINK_ROLE_BITS / MBG_NET_LINK_ROLE_MASKS? +/** + * @brief Link status for SyncE on a 1000BASE-T interface + * + * @see ::XXX + */ +enum GBIT_LINK_STATUS +{ + GBIT_LINK_COPPER_IS_MASTER, ///< GBIT Link is currently clock master + GBIT_LINK_COPPER_IS_SLAVE, ///< GBIT Link is currently clock slave + GBIT_LINK_COPPER_CFG_FAULT, ///< GBIT Link has a configruation fault (conflict with link partner + GBIT_LINK_COPPER_IS_FE, ///< Link is running on Fast Ethernet (no MASTER/SLAVE decision) + GBIT_LINK_DOWN, ///< Currently no link + GBIT_LINK_FIBER, ///< GBIT Linkup on SFP interface + N_GBIT_LINK_STATUS +}; + + +#define GBIT_LINK_STATUS_STRS \ +{ \ + "MASTER (1000BASE-T)", \ + "SLAVE (1000BASE-T)", \ + "CFG FAULT", \ + "AUTO (100BASE-TX)", \ + "LINK DOWN", \ + "AUTO (SFP LINK UP)", \ +} + + +/** + * @brief Bits used to define ::MBG_SYNCE_FLAG_MASKS + */ +enum MBG_SYNCE_FLAGS +{ + SYNCE_FLAG_ACTIVE_SYNC_MASTER, + N_SYNCE_FLAGS // number of defined bits +}; + + + +/** + * @brief Flag masks used with ::MBG_SYNC_E_SETTINGS::flags + * + * @see ::MBG_SYNCE_FLAGS + */ +enum MBG_SYNCE_FLAG_MASKS +{ + SYNCE_FLAG_ACTIVE_SYNC_MASTER_MSK = ( 1UL << SYNCE_FLAG_ACTIVE_SYNC_MASTER ) ///< see ::SYNCE_FLAG_ACTIVE_SYNC_MASTER +}; + + + +/** + * @brief Settings for a Synchronous Ethernet interface + * + * @see ::XXX + */ +typedef struct +{ + uint8_t synce_enabled; ///< SyncE is activated for the specific interface + uint8_t ql_selection_enabled; ///< Quality Level is determined automatically + uint8_t sdh_network_option; ///< see ::SDH_NETWORK_OPTION + uint8_t local_priority; ///< user defined priority value for selected port + uint8_t local_network_sync_level_ssm; ///< automatically assigend quality level for SyncE output + uint8_t fixed_output_ssm; ///< Fixed SSM output override + uint8_t fixed_input_ssm; ///< Assumed SSM value for SyncE Input (0xFF if taken from network) + uint8_t gbit_link_copper_mode; ///< see ::GBIT_LINK_COPPER_MODE + uint8_t reserved_1; + uint8_t reserved_2; + uint32_t reserved_3; + uint32_t flags; ///< see ::MBG_SYNCE_FLAG_MASKS + +} MBG_SYNC_E_SETTINGS; + + + +typedef struct +{ + MBG_SYNC_E_SETTINGS settings; + uint32_t supp_sdh_network_opts; + uint32_t supp_gbit_link_copper_modes; + uint32_t supp_flags; + uint32_t reserved; + +} MBG_SYNC_E_INFO; + + + +typedef struct +{ + uint8_t synce_enabled; + uint8_t output_ssm; + uint8_t input_ssm; + uint8_t gbit_link_status; ///< see ::GBIT_LINK_STATUS + uint8_t reserved_1; + uint8_t reserved_2; + uint32_t reserved_3; + uint32_t flags; ///< MBG_SYNCE_FLAG_MASKS + +} MBG_SYNC_E_STATUS; + +#endif // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + +/** + * @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)->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 { - uint16_t type; /* codes see below */ - uint8_t mac_addr[6]; /* MAC address */ - uint16_t ver_code; /* high byte.low byte, in hex */ - char ver_str[GPS_ID_STR_SIZE]; - char sernum[GPS_ID_STR_SIZE]; - uint32_t rsvd_0; /* reserved, currently always 0 */ - uint16_t flags; /* see below */ - uint16_t rsvd_1; /* reserved, currently always 0 */ -} LAN_IF_INFO; + uint32_t supp_flags; ///< Supported NTP system state values, see ::NTP_SYS_STATE_SUPP_FLAG_MASKS -#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 ); \ + 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 \ +} -/* codes used with LAN_IF_INFO::type: */ -enum +/** + * @brief Enumeration of NTP peer selection status + * + * Used with ::NTP_PEER_STATE::peer_sel_stat + * + */ +enum NTP_PEER_SEL_STATUS_BITS { - LAN_IF_TYPE_XPORT, - LAN_IF_TYPE_PTP, - N_LAN_IF_TYPE + 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 \ +} -/* Flags used with IP4_SETTINGS::flags and LAN_IF_INFO::flags: */ -enum +/** + * @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 { - IP4_BIT_DHCP, // DHCP supported (LAN_IF_INFO) / enabled (IP4_SETTINGS) - IP4_BIT_LINK, // used only in IP4_SETTINGS to report link state - IP4_BIT_VLAN, // VLAN supported (LAN_IF_INFO) / enabled (IP4_SETTINGS) - N_IP4_BIT + 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 }; -#define IP4_MSK_DHCP ( 1UL << IP4_BIT_DHCP ) -#define IP4_MSK_LINK ( 1UL << IP4_BIT_LINK ) -#define IP4_MSK_VLAN ( 1UL << IP4_BIT_VLAN ) +/* + * 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 \ +} -enum + +/** + * @brief Enumeration of NTP peer event message codes + * + * Used with ::NTP_PEER_STATE::peer_rec_evt + * + */ +enum NTP_PEER_EVT_BITS { - PTP_NW_PROT_BIT_RESERVED, - PTP_NW_PROT_BIT_UDP_IPV4, - PTP_NW_PROT_BIT_UDP_IPV6, - PTP_NW_PROT_BIT_IEEE_802_3, - PTP_NW_PROT_BIT_DEVICE_NET, - PTP_NW_PROT_BIT_CONTROL_NET, - PTP_NW_PROT_BIT_PROFINET, - N_PTP_NW_PROT -}; - -#define PTP_NW_PROT_MSK_RESERVED ( 1UL << PTP_NW_PROT_BIT_RESERVED ) -#define PTP_NW_PROT_MSK_UDP_IPV4 ( 1UL << PTP_NW_PROT_BIT_UDP_IPV4 ) -#define PTP_NW_PROT_MSK_UDP_IPV6 ( 1UL << PTP_NW_PROT_BIT_UDP_IPV6 ) -#define PTP_NW_PROT_MSK_IEEE_802_3 ( 1UL << PTP_NW_PROT_BIT_IEEE_802_3 ) -#define PTP_NW_PROT_MSK_DEVICE_NET ( 1UL << PTP_NW_PROT_BIT_DEVICE_NET ) -#define PTP_NW_PROT_MSK_CONTROL_NET ( 1UL << PTP_NW_PROT_BIT_CONTROL_NET ) -#define PTP_NW_PROT_MSK_PROFINET ( 1UL << PTP_NW_PROT_BIT_PROFINET ) - -#if !defined( DEFAULT_PTP_NW_PROT_MASK ) - #define DEFAULT_PTP_NW_PROT_MASK ( PTP_NW_PROT_MSK_UDP_IPV4 | PTP_NW_PROT_MSK_IEEE_802_3 ) -#endif + 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 +}; -#define PTP_NW_PROT_STRS \ -{ \ - "Reserved", \ - "UDP/IPv4", \ - "UDP/IPv6", \ - "IEEE 802.3", \ - "DeviceNet", \ - "ControlNet", \ - "PROFINET" \ +/* + * 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 +}; -enum + +/** + * @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 { - PTP_PORT_STATE_UNINITIALIZED, - PTP_PORT_STATE_INITIALIZING, - PTP_PORT_STATE_FAULTY, - PTP_PORT_STATE_DISABLED, - PTP_PORT_STATE_LISTENING, - PTP_PORT_STATE_PRE_MASTER, - PTP_PORT_STATE_MASTER, - PTP_PORT_STATE_PASSIVE, - PTP_PORT_STATE_UNCALIBRATED, - PTP_PORT_STATE_SLAVE, - N_PTP_PORT_STATE + 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 }; -#define PTP_PORT_STATE_STRS \ -{ \ - "UNINITIALIZED", \ - "INITIALIZING", \ - "FAULTY", \ - "DISABLED", \ - "LISTENING", \ - "PRE_MASTER", \ - "MASTER", \ - "PASSIVE", \ - "UNCALIBRATED", \ - "SLAVE" \ +/* + * 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 { - uint8_t value; - const char *name; -} PTP_TABLE; + 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 -enum + 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 { - PTP_DELAY_MECH_BIT_E2E, // in PTP2 specs: 0x01 - PTP_DELAY_MECH_BIT_P2P, // in PTP2 specs: 0x02 - N_PTP_DELAY_MECH // additionally the specs define 0xFE for disabled + LNO_FLAG_BIT_PLL_LOCKED, ///< PLL is locked + N_LNO_FLAG_BIT ///< number of known bits }; -#define PTP_DELAY_MECH_MSK_E2E ( 1UL << PTP_DELAY_MECH_BIT_E2E ) -#define PTP_DELAY_MECH_MSK_P2P ( 1UL << PTP_DELAY_MECH_BIT_P2P ) - -#if !defined( DEFAULT_PTP_DELAY_MECH_MASK ) - #define DEFAULT_PTP_DELAY_MECH_MASK ( PTP_DELAY_MECH_MSK_E2E | PTP_DELAY_MECH_MSK_P2P ) -#endif +#define LNO_FLAG_PLL_LOCKED ( 1UL << LNO_FLAG_BIT_PLL_LOCKED ) -#define PTP_DELAY_MECH_NAMES \ -{ \ - "E2E", \ - "P2P" \ -} +/** @} defgroup group_lno */ -#define PTP_CLOCK_ACCURACY_RESERVED_OFFSET 0x20 +/** + * @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. + * + * @{ */ -enum +/** + * @brief Known common VST data types + */ +enum VST_DATA_TYPES { - PTP_CLOCK_ACCURACY_25ns = PTP_CLOCK_ACCURACY_RESERVED_OFFSET, - 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 + VST_DATA_TYPE_MAC_ADDR, //##++++++++++++ This is just an example. More to be added. + N_VST_DATA_TYPES }; -// Attention: Substract offset of PTP_CLOCK_ACCURACY_RESERVED_OFFSET when -// using the enum above as index for the initializer below! -#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 + */ +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 ); \ +} -#define PTP_TIME_SOURCE_ATOMIC_CLOCK 0x10 -#define PTP_TIME_SOURCE_GPS 0x20 -#define PTP_TIME_SOURCE_TERRESTRIAL_RADIO 0x30 -#define PTP_TIME_SOURCE_PTP 0x40 -#define PTP_TIME_SOURCE_NTP 0x50 -#define PTP_TIME_SOURCE_HAND_SET 0x60 -#define PTP_TIME_SOURCE_OTHER 0x90 -#define PTP_TIME_SOURCE_INTERNAL_OSCILLATOR 0xA0 +/** @} defgroup group_vst */ -#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 } \ -} +/** + * @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 ); \ +} -/* PTP configuration stuff */ +/** + * @brief Current SHS settings and general SHS capabilities + * + * @see ::SHS_SETTINGS + * @see ::SHS_STATUS + */ typedef struct { - uint8_t b[8]; -} PTP_CLOCK_IDENTITY; + 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 { - uint16_t network_protocol; // enum - uint8_t ptp_proto_version; // PTP v1 or v2 - uint8_t port_state; // enum - uint32_t flags; - NANO_TIME offset; - NANO_TIME path_delay; - NANO_TIME mean_path_delay; - NANO_TIME delay_asymmetry; + 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 - PTP_CLOCK_IDENTITY gm_identity; +} SHS_STATUS; - uint16_t clock_offset_scaled_log_variance; - uint8_t clock_class; - uint8_t clock_accuracy; // enum +#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 ); \ +} - uint32_t num_clients; - uint32_t num_masters; - uint8_t domain_number; - uint8_t time_source; // enum - uint8_t delay_mech; - int8_t log_delay_req_intv; - int16_t utc_offset; - DAC_VAL osc_dac_cal; +/** + * @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 +}; + - uint32_t reserved; -} PTP_STATE; -#define _mbg_swab_ptp_state( _p ) \ -{ \ - _mbg_swab16( &(_p)->network_protocol ); \ - _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_swab16( &(_p)->clock_offset_scaled_log_variance ); \ - _mbg_swab32( &(_p)->num_clients ); \ - _mbg_swab32( &(_p)->num_masters ); \ - _mbg_swab32( &(_p)->utc_offset ); \ - _mbg_swab_dac_val( &(_p)->osc_dac_cal ); \ -} +/** + * @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 +}; -enum +/** + * @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 { - PTP_FLAG_BIT_SLAVE_ONLY, - PTP_FLAG_BIT_IS_SLAVE, - PTP_FLAG_BIT_TIMESCALE_IS_PTP, - PTP_FLAG_BIT_LS_ANN, - PTP_FLAG_BIT_LS_ANN_NEG, - N_PTP_FLAG_BIT + 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 }; -#define PTP_FLAG_MSK_SLAVE_ONLY ( 1UL << PTP_FLAG_BIT_SLAVE_ONLY ) -#define PTP_FLAG_MSK_IS_SLAVE ( 1UL << PTP_FLAG_BIT_IS_SLAVE ) -#define PTP_FLAG_MSK_TIMESCALE_IS_PTP ( 1UL << PTP_FLAG_BIT_TIMESCALE_IS_PTP ) -#define PTP_FLAG_MSK_LS_ANN ( 1UL << PTP_FLAG_BIT_LS_ANN ) -#define PTP_FLAG_MSK_LS_ANN_NEG ( 1UL << PTP_FLAG_BIT_LS_ANN_NEG ) +/** @} defgroup group_shs */ + + + +/** + * @defgroup group_xbp eXtended Binary Protocol definitions + * + * @note These structures are only supported if ::GPS_HAS_XBP is set + * in ::RECEIVER_INFO::features. + * + * @{ */ + +/** + * @brief An identifier used to mark an XBP port unused + */ +#define XBP_PORT_RESERVED ( (uint8_t) 255 ) +/** + * @brief An XBP port specifier + * + * Each controller can provide up to 255 ports with numbers 0..254. + * XBP port number ::XBP_PORT_RESERVED is reserved to mark unused ports. + */ +typedef uint8_t XBP_PORT; -#define PTP_SYNC_INTERVAL_MIN -6 -#define PTP_SYNC_INTERVAL_MAX 6 -#define PTP_DELAY_REQ_INTERVAL_MIN -6 -#define PTP_DELAY_REQ_INTERVAL_MAX 6 +/** + * @brief Maximum XBP bus/controller cascading level + * + * Should be 7 so the total size of ::XBP_ADDR is 8 bytes. + */ +#define MAX_XBP_CASC_LVL 7 +/** + * @brief An XBP address specifier + * + * A generic scheme to address devices connected to cascaded controllers. + */ typedef struct { - uint16_t network_protocol; // enum, only 1 or 3 - uint8_t profile; // currently only 0 = default - uint8_t domain_number; // 0:3 + uint8_t hop_count; ///< Used as index to the addr array + XBP_PORT addr[MAX_XBP_CASC_LVL]; ///< An array of port numbers on cascaded controllers - uint8_t delay_mechanism; // 0 (E2E) or 1 (P2P), unless disabled - uint8_t reserved_0; - uint8_t priority_1; - uint8_t priority_2; +} XBP_ADDR; - 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 reserved_1; // currently always 0 - uint8_t reserved_2; // currently always 0 - int16_t sync_interval; // log 2 - int16_t announce_interval; // log 2 - int16_t delay_request_interval; // log 2 +/** + * @brief A structure used to report XBP features and limits + */ +typedef struct +{ + uint32_t features; ///< Mask of XBP features, see ::XBP_FEAT_MASKS + uint32_t flags; ///< XBP flags, currently not used + uint32_t reserved[4]; ///< reserved, currently not used - uint32_t upper_bound; // [ns] sync state set to false if above this limit - uint32_t lower_bound; // [ns] sync state set to true if below this limit +} XBP_LIMITS; - uint32_t reserved_3; // currently always 0 - uint32_t flags; // (see below) -} PTP_CFG_SETTINGS; -#define _mbg_swab_ptp_cfg_settings( _p ) \ -{ \ - _mbg_swab16( &(_p)->network_protocol ); \ - _mbg_swab16( &(_p)->sync_interval ); \ - _mbg_swab16( &(_p)->announce_interval ); \ - _mbg_swab16( &(_p)->delay_request_interval ); \ - _mbg_swab32( &(_p)->upper_bound ); \ - _mbg_swab32( &(_p)->lower_bound ); \ - _mbg_swab32( &(_p)->reserved_1 ); \ - _mbg_swab32( &(_p)->flags ); \ -} +/** + * @brief Enumeration of bits used to define ::XBP_FEAT_MASKS + */ +enum XBP_FEAT_BITS +{ + XBP_FEAT_BIT_NODES, ///< Supports ::XBP_NODE_LIMITS and associated structures + N_XBP_FEAT_BITS +}; + + +/** + * @brief XBP feature masks used with ::XBP_LIMITS::features + * + * @see ::XBP_FEAT_BITS + */ +enum XBP_FEAT_MASKS +{ + XBP_FEAT_MASK_NODES = ( 1UL << XBP_FEAT_BIT_NODES ) ///< See ::XBP_FEAT_BIT_NODES +}; +/** + * @brief Information on available XBP nodes + * + * Only supported if ::XBP_FEAT_MASK_NODES is set in ::XBP_LIMITS::features. + */ typedef struct { - PTP_CFG_SETTINGS settings; + uint32_t node_count; ///< Number of XBP nodes available in the system + uint32_t reserved_0; ///< Currently reserved, always 0 + uint32_t reserved_1; ///< Currently reserved, always 0 + // TODO: do we need additional fields here? - uint8_t ptp_proto_version; // PTP v1 or v2 - uint8_t reserved_1; // currently always 0 - uint16_t reserved_2; // currently always 0 +} XBP_NODE_LIMITS; - int16_t sync_interval_min; // log 2 - int16_t sync_interval_max; // log 2 - int16_t announce_interval_min; // log 2 - int16_t announce_interval_max; // log 2 - int16_t delay_request_interval_min; // log 2 - int16_t delay_request_interval_max; // log 2 - uint32_t supported_flags; // (see below) - uint32_t supported_network_protocols; - uint32_t supported_profiles; - uint32_t supported_delay_mechanisms; -} PTP_CFG_INFO; +/** + * @brief Possible states of an XBP device + * + * Used with ::XBP_NODE_INFO::state. + */ +enum XBP_DEVICE_STATES +{ + XBP_DEVICE_STATE_UNKNOWN, + XBP_DEVICE_STATE_NOT_AVAILABLE, + XBP_DEVICE_STATE_INITIALIZING, + XBP_DEVICE_STATE_AVAILABLE, + XBP_DEVICE_STATE_DISCONNECTED, + N_XBP_DEVICE_STATES +}; + -#define _mbg_swab_ptp_cfg_info( _p ) \ -{ \ - _mbg_swab_ptp_cfg_settings( &(_p)->settings ); \ - _mbg_swab16( &(_p)->sync_interval_min ); \ - _mbg_swab16( &(_p)->sync_interval_max ); \ - _mbg_swab16( &(_p)->announce_interval_min ); \ - _mbg_swab16( &(_p)->announce_interval_max ); \ - _mbg_swab16( &(_p)->delay_request_interval_min ); \ - _mbg_swab16( &(_p)->delay_request_interval_max ); \ - _mbg_swab32( &(_p)->supported_flags ); \ - _mbg_swab32( &(_p)->supported_profiles ); \ - _mbg_swab32( &(_p)->supported_delay_mechanisms ); \ -} +/** + * @brief Information on a specific XBP node + * + * Only supported if ::XBP_FEAT_MASK_NODES is set in ::XBP_LIMITS::features. + * The number of instances supported by a device is specified + * in ::XBP_NODE_LIMITS::node_count. + */ +typedef struct +{ + XBP_ADDR addr; ///< The address of the specific node + /// ::RECEIVER_INFO of the device connected to this node. + /// If no device is available then ::RECEIVER_INFO::model_code + /// is set to ::GPS_MODEL_UNKNOWN (== 0). + RECEIVER_INFO ri; -// flags used with PTP_CFG_SETTINGS::flags and PTP_CFG_INFO::supported_flags: -// possibly also: can be master (i.e not slave only), v1 hw compat, ... -enum + uint8_t state; ///< The device state, see ::XBP_DEVICE_STATES + uint8_t reserved; ///< Currently reserved, always 0 + uint32_t flags; ///< Currently reserved, always 0 + +} XBP_NODE_INFO; + + +/** + * @brief Information on an XBP node with specific index + * + * Only supported if ::XBP_FEAT_MASK_NODES is set in ::XBP_LIMITS::features. + */ +typedef struct { - PTP_CFG_BIT_TIME_SCALE_IS_PTP, // time scale is PTP/TAI, else arbitrary - PTP_CFG_BIT_V1_HW_COMPAT, - N_PTP_CFG_BIT -}; + uint32_t idx; ///< node index, 0..::XBP_NODE_LIMITS::node_count-1 + XBP_NODE_INFO node_info; ///< ::RECEIVER_INFO of the device behind this node -#define PTP_CFG_MSK_TIME_SCALE_IS_PTP ( 1UL << PTP_CFG_BIT_TIME_SCALE_IS_PTP ) -#define PTP_CFG_MSK_V1_HW_COMPAT ( 1UL << PTP_CFG_BIT_V1_HW_COMPAT ) +} XBP_NODE_INFO_IDX; + +/** @} defgroup group_xbp */ /*------------------------------------------------------------------------*/ -/* Ephemeris parameters of one specific SV. 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 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; -/* Almanac parameters of one specific SV. 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. */ +/** + * @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 */ + CSUM csum; ///< checksum of the remaining bytes + int16_t valid; ///< flag data are valid - HEALTH health; /* [---] */ - T_GPS t0a; /* Reference Time Almanac [sec] */ + HEALTH health; ///< [---] + T_GPS t0a; ///< Reference Time Almanac [sec] - double sqrt_A; /* Square Root of semi-major Axis [sqrt(m)] */ - double e; /* Eccentricity [---] */ + 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; + 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; -/* Summary of configuration and health data of all SVs. */ +/** + * @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 */ + 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 - 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]; ///< 4 bit SV configuration code from page 63 + HEALTH health[N_SVNO_GPS]; ///< 6 bit SV health codes from pages 51, 63 - CFG cfg[N_SVNO]; /* SV configuration from page 63 */ - HEALTH health[N_SVNO]; /* SV health from pages 51, 63 */ } CFGH; /** - @brief GPS UTC correction parameters -*/ + * @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 for the end of which a leap second has been 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 and displayed + * in a user interface if the fields delta_tls and delta_tlsf have + * different values, in which case there is indeed a 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 */ + 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] - 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] - 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 ) \ @@ -4300,38 +12059,42 @@ typedef struct -/* Ionospheric correction parameters */ - +/** + * @brief Ionospheric correction parameters + */ typedef struct { - CSUM csum; /* checksum of the remaining bytes */ - int16_t valid; /* flag data are valid */ + 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 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; + 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; -/* GPS ASCII message */ +/** + * @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 */ + 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 +enum GPS_PLATFORMS { GPS_PLATFORM_PORTABLE, GPS_PLATFORM_FIXED, @@ -4344,7 +12107,7 @@ enum GPS_PLATFORM_AIRBORNE_4G, N_GPS_PLATFORMS }; - + #define GPS_PLATFORM_STRS \ { \ @@ -4361,15 +12124,16 @@ enum -enum +enum TIME_MODES { TIME_MODE_DISABLED, TIME_MODE_SURVEY_IN, - TIME_MODE_FIXED + TIME_MODE_FIXED, + N_TIME_MODES }; - + typedef struct { uint32_t time_mode; @@ -4379,17 +12143,18 @@ typedef struct int32_t fixedPosY; // cm int32_t fixedPosZ; // cm uint32_t fixedPosVar; // cm - uint32_t flags; // currently 0 - uint32_t reserved; // currently 0 + 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. -*/ +/** + * 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; @@ -4399,15 +12164,15 @@ typedef struct uint32_t flags; // currently 0 uint32_t reserved; // currently 0 NAV_TIME_MODE_SETTINGS nav_time_mode_settings; -} NAV_ENGINE_SETTINGS; - -/* End of header body */ +} NAV_ENGINE_SETTINGS; -#if defined( _USE_PACK ) // set default alignment - #pragma pack() +#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/gpsserio.c b/mbglib/common/gpsserio.c index 15cc808..0943281 100644 --- a/mbglib/common/gpsserio.c +++ b/mbglib/common/gpsserio.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsserio.c 1.9 2009/09/01 09:51:56 martin REL_M $ + * $Id: gpsserio.c 1.13.1.3 2015/07/24 11:07:17 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,6 +11,23 @@ * * ----------------------------------------------------------------------- * $Log: gpsserio.c $ + * Revision 1.13.1.3 2015/07/24 11:07:17 martin + * Revision 1.13.1.2 2015/05/20 12:21:23 martin + * Revision 1.13.1.1 2015/05/19 13:20:21 daniel + * Preliminary support for USB_DIRECT_IO + * Revision 1.13 2015/05/13 13:47:52 martin + * Support new libusb v1.0 and newer which is not compatible with v0.1x. + * Use preprocessor symbol MBG_TGT_POSIX. + * Use Meinberg error codes from mbgerror.h. + * Support XBP addressing. + * Updated doxygen-style comments. + * Revision 1.12 2012/03/08 12:09:38 martin + * Removed an obsolete printf(). + * Revision 1.11 2012/03/06 15:41:24Z martin + * Use mbgserio_read/write functions rather than macros. + * Save system timestamp on start of incoming binary packet. + * Revision 1.10 2011/07/29 09:53:43Z daniel + * Account for communication via USB if _USE_USB_IO is defined * Revision 1.9 2009/09/01 09:51:56 martin * Removed obsolete includes. * Revision 1.8 2009/03/10 16:58:09 martin @@ -47,13 +64,14 @@ #include #undef _GPSSERIO +#include + #include #include #include -#if defined( MBG_TGT_UNIX ) +#if defined( MBG_TGT_POSIX ) #include -//##++++ #include #endif #if _USE_ENCRYPTION @@ -62,23 +80,65 @@ -/*-------------------------------------------------------------- - * Name: msg_csum_update() - * - * Purpose: Compute a checksum about a number of bytes - * starting with a given initial value. - * - * Input: CSUM csum the initial value - * uint8_t *p address of the first byte - * int n the number of bytes +#if _USE_SERIAL_IO_FTDI + +/*HDR*/ +/** + * @brief Translate a FTDI API status code to one of the @ref MBG_ERROR_CODES * - * Output: -- + * @param[in] status A status code defined by the FTDI API interface * - * Ret val: the checksum - *+------------------------------------------------------------*/ + * @return One of the @ref MBG_RETURN_CODES + */ +int mbg_ftdi_ft_status_to_mbg( FT_STATUS status ) +{ + switch ( status ) + { + case FT_OK: return MBG_SUCCESS; + case FT_INVALID_HANDLE: return MBG_ERR_INV_HANDLE; + case FT_DEVICE_NOT_FOUND: return MBG_ERR_NO_DEV; + case FT_DEVICE_NOT_OPENED: return MBG_ERR_INV_HANDLE; + case FT_IO_ERROR: return MBG_ERR_IO; + // case FT_INSUFFICIENT_RESOURCES: return ; + case FT_INVALID_PARAMETER: return MBG_ERR_INV_PARM; + case FT_INVALID_BAUD_RATE: return MBG_ERR_INV_PARM; + + // case FT_DEVICE_NOT_OPENED_FOR_ERASE: return ; + // case FT_DEVICE_NOT_OPENED_FOR_WRITE: return ; + // case FT_FAILED_TO_WRITE_DEVICE: return ; + case FT_EEPROM_READ_FAILED: return MBG_ERR_IO; + case FT_EEPROM_WRITE_FAILED: return MBG_ERR_IO; + // case FT_EEPROM_ERASE_FAILED: return ; + // case FT_EEPROM_NOT_PRESENT: return ; + // case FT_EEPROM_NOT_PROGRAMMED: return ; + case FT_INVALID_ARGS: return MBG_ERR_INV_PARM; + case FT_NOT_SUPPORTED: return MBG_ERR_NOT_SUPP_BY_DEV; + case FT_OTHER_ERROR: return MBG_ERR_UNSPEC; + case FT_DEVICE_LIST_NOT_READY: return MBG_ERR_NO_DEV; + } + + return MBG_ERR_UNSPEC; + +} // mbg_ftdi_ft_status_to_mbg + +#endif // _USE_SERIAL_IO_FTDI + + /*HDR*/ -CSUM msg_csum_update( CSUM csum, uint8_t *p, int n ) +/** + * @brief Compute a simple binary checksum + * + * Compute a checksum about a number of bytes starting + * with a given initial value. + * + * @param[in] csum the initial value + * @param[in] p pointer to a buffer of data bytes + * @param[in] n the number of bytes in the buffer + * + * @return the computed checksum + */ +CSUM msg_csum_update( CSUM csum, const uint8_t *p, int n ) { int i; @@ -91,26 +151,19 @@ CSUM msg_csum_update( CSUM csum, uint8_t *p, int n ) -/*-------------------------------------------------------------- - * Name: msg_csum() - * - * Purpose: Compute a message checksum over a number - * of bytes. - * - * ATTENTION: This function differs from the - * checksum() function which is used to compute - * the checksum of battery-buffered variables! +/*HDR*/ +/** + * @brief Compute a checksum for a binary message * - * Input: uint8_t *p address of the first byte - * int n the number of bytes + * @note This function differs from the checksum() function + * used to compute the checksum of battery-buffered variables. * - * Output: -- + * @param[in] p pointer to a buffer of data bytes + * @param[in] n the number of bytes in the buffer * - * Ret val: the checksum - *+------------------------------------------------------------*/ - -/*HDR*/ -CSUM msg_csum( uint8_t *p, int n ) + * @return the computed checksum + */ +CSUM msg_csum( const uint8_t *p, int n ) { return msg_csum_update( 0, p, n ); @@ -118,22 +171,17 @@ CSUM msg_csum( uint8_t *p, int n ) -/*-------------------------------------------------------------- - * Name: msg_hdr_csum() - * - * Purpose: Compute the checksum of a message header. - * - * Input: MSG_HDR *pmh pointer to a message header +/*HDR*/ +/** + * @brief Compute the checksum of a binary message header * - * Output: -- + * @param[in] pmh pointer to a binary message header * - * Ret val: the checksum - *+------------------------------------------------------------*/ - -/*HDR*/ -CSUM msg_hdr_csum( MSG_HDR *pmh ) + * @return the computed checksum + */ +CSUM msg_hdr_csum( const MSG_HDR *pmh ) { - return msg_csum( (uint8_t *) pmh, + return msg_csum( (uint8_t *) pmh, sizeof( *pmh ) - sizeof( pmh->hdr_csum ) ); } /* msg_hdr_csum */ @@ -141,28 +189,42 @@ CSUM msg_hdr_csum( MSG_HDR *pmh ) /*HDR*/ -int chk_hdr_csum( MSG_HDR *pmh ) +/** + * @brief Check if the header checksum of a binary message is valid + * + * @param[in] pmh pointer to a binary message header + * + * @return ::MBG_SUCCESS or ::MBG_ERR_HDR_CSUM + */ +int chk_hdr_csum( const MSG_HDR *pmh ) { CSUM calc_csum = msg_hdr_csum( pmh ); if ( calc_csum != pmh->hdr_csum ) - return -1; /* error */ + return MBG_ERR_HDR_CSUM; /* error */ - return 0; + return MBG_SUCCESS; } /* chk_hdr_csum */ /*HDR*/ -int chk_data_csum( MBG_MSG_BUFF *pmb ) +/** + * @brief Check if the data checksum of a binary message is valid + * + * @param[in] pmb pointer to a binary message buffer + * + * @return ::MBG_SUCCESS or ::MBG_ERR_DATA_CSUM + */ +int chk_data_csum( const MBG_MSG_BUFF *pmb ) { CSUM calc_csum = msg_csum( pmb->u.bytes, pmb->hdr.len ); if ( calc_csum != pmb->hdr.data_csum ) - return -1; /* error */ + return MBG_ERR_DATA_CSUM; /* error */ - return 0; + return MBG_SUCCESS; } /* chk_data_csum */ @@ -198,51 +260,46 @@ int chk_data_csum( MBG_MSG_BUFF *pmb ) #endif -//---------------------------------------------------------------------- -// in encrypted mode data packets are packed into a new encrypted packet -// where InitVect, XMSG_BUFF and Fill bytes form the new data section -// -// Format : [MSG_HDR][InitVect][XMSG_BUFF][FillBytes] -// |<-HDR->|<----------- DATA ------------>| -// |<-- plaintext -->|<---- encrypted ---->| -// -// - MSG_HDR : Standard Binary Message Handler with -// cmd = GPS_CRYPTED_PACKET, len is size of complete -// block, data_csum calculated over complete block -// ( InitVect, XMSG_BUFF and FILL_BYTES ) -// - InitVect : random number for AES128 CFM initialization -// - XMSG_BUFF : Message buffer as prepared for unencrypted transfer -// consists of MSG_HEADER and DATA, will be completely -// encrypted before transmission -// - FillBytes : Bytes to fill up for the next 128Bit/16Byte boundary -//---------------------------------------------------------------------- /*HDR*/ +/** + * @brief Encrypt a binary message + * + * In encryption mode the original packet is encrypted and put + * as data portion into an envelope package. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in,out] pcmp Pointer to encryption settings + * @param[in,out] pmb Pointer to a binary message buffer + * + * @return the number of bytes of the encrypted message, or one of the @ref MBG_ERROR_CODES + */ int encrypt_message( MBG_MSG_CTL *pmctl, CRYPT_MSG_PREFIX *pcmp, MBG_MSG_BUFF *pmb ) { - int n_bytes = pmb->hdr.len + sizeof( pmb->hdr ); /* size of unencrypted msg */ + int n_bytes = pmb->hdr.len + sizeof( pmb->hdr ); // size of unencrypted msg int rc; - /* correct original msg size for 16 byte boundary */ + // align original msg size with 16 byte boundary n_bytes += AES_BLOCK_SIZE - ( n_bytes % AES_BLOCK_SIZE ); - /* encrypt original message */ + // encrypt original message rc = aes_encrypt_buff( (uint8_t *) pmb, pmctl->aes_keyvect, pmctl->aes_initvect, n_bytes ); - if ( rc < 0 ) - return rc; // encryption failed + if ( rc < 0 ) // -1 on error + return MBG_ERR_ENCRYPT; // encryption failed - /* copy AES init vector into encrypted message */ + // copy AES init vector into encrypted message + //##++ check types of aes_initvect fields memcpy( pcmp->aes_initvect, pmctl->aes_initvect, sizeof( pcmp->aes_initvect ) ); pcmp->hdr.cmd = GPS_CRYPTED_PACKET; - pcmp->hdr.len = n_bytes + sizeof( pcmp->aes_initvect ); + pcmp->hdr.len = (uint16_t) ( n_bytes + sizeof( pcmp->aes_initvect ) ); pcmp->hdr.data_csum = msg_csum( pcmp->aes_initvect, sizeof( pcmp->aes_initvect ) ); - pcmp->hdr.data_csum = msg_csum_update( pcmp->hdr.data_csum, - (uint8_t *) pmb, n_bytes ); + pcmp->hdr.data_csum = msg_csum_update( pcmp->hdr.data_csum, + (uint8_t *) pmb, n_bytes ); pcmp->hdr.hdr_csum = msg_hdr_csum( &pcmp->hdr ); @@ -253,56 +310,84 @@ int encrypt_message( MBG_MSG_CTL *pmctl, CRYPT_MSG_PREFIX *pcmp, MBG_MSG_BUFF *p /*HDR*/ +/** + * @brief Decrypt an encrypted binary message + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return One of the @ref MBG_RETURN_CODES + */ int decrypt_message( MBG_MSG_CTL *pmctl ) { MBG_MSG_RCV_CTL *prctl = &pmctl->rcv; MBG_MSG_BUFF *pmb = prctl->pmb; CRYPT_MSG_DATA *pcmd = &pmb->u.crypt_msg_data; int rc; + int len; if ( pmb->hdr.len < AES_BLOCK_SIZE ) return 0; - rc = aes_decrypt_buff( (unsigned char *) &pcmd->enc_msg, - pmctl->aes_keyvect, + rc = aes_decrypt_buff( (uint8_t *) &pcmd->std_msg, + pmctl->aes_keyvect, pcmd->aes_initvect, pmb->hdr.len - sizeof( pcmd->aes_initvect ) - ); + ); - if ( rc < 0 ) /* decryption error */ + if ( rc < 0 ) // decryption error { prctl->flags |= MBG_MSG_RCV_CTL_DECRYPT_ERR; - return TR_DECRYPTION; + return MBG_ERR_DECRYPT; } - /* packet decrypted successfully. */ + // packet decrypted successfully. prctl->flags |= MBG_MSG_RCV_CTL_DECRYPTED; - // If the wrong password has been used for decryption - // then decryption may have been formally successful, + // If the wrong password has been used for decryption + // then decryption may have been formally successful, // but the decrypted message contains garbage. // So we must check whether the decrypted packet // also contains a valid header and data part. - //##+++ TODO + //##+++++++++ TODO + // A potential problem arises if the garbage data len exceeds + // the buffer size and the data csum is computed using + // that length, which goes beyond the buffer limit. + // also, me must not copy more than the sizeof MBG_STD_MSG + // bytes to avoid a buffer overflow. + // We should really check the decrypted header here. - /* copy the decrypted message to head of the buffer */ - memcpy( pmb, &pcmd->enc_msg, pcmd->enc_msg.enc_hdr.len + sizeof( pcmd->enc_msg.enc_hdr ) ); + len = pcmd->std_msg.hdr.len + sizeof( pcmd->std_msg.hdr ); - /* now check the csums of the decrypted packet */ + if ( len > sizeof( MBG_STD_MSG ) ) + len = sizeof( MBG_STD_MSG ); - if ( chk_hdr_csum( &pmb->hdr ) < 0 ) /* error */ - return TR_CSUM_DATA; /* invalid header checksum received */ + // copy the decrypted message to the head of the buffer + memcpy( pmb, &pcmd->std_msg, len ); - if ( chk_data_csum( pmb ) < 0 ) /* error */ - return TR_CSUM_DATA; /* invalid header checksum received */ - return 0; + // now check the CSUMs of the decrypted packet + //##++++ TODO: which error code to return? This was actually the data portion of the encrypted msg + + if ( chk_hdr_csum( &pmb->hdr ) != MBG_SUCCESS ) + return MBG_ERR_DECRYPT; // invalid header checksum due to faulty decryption + + if ( chk_data_csum( pmb ) != MBG_SUCCESS ) + return MBG_ERR_DECRYPT; // invalid data checksum due to faulty decryption + + return MBG_SUCCESS; } /* decrypt_message */ /*HDR*/ +/** + * @brief Set communication channel to specified encryption mode + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] mode Encryption mode, usually ::MBG_XFER_MODE_ENCRYPTED + * @param[in] key The crypto key (password) to be used + */ void set_encryption_mode( MBG_MSG_CTL *pmctl, int mode, const char *key ) { int i; @@ -323,59 +408,104 @@ void set_encryption_mode( MBG_MSG_CTL *pmctl, int mode, const char *key ) -/*-------------------------------------------------------------- - * Name: xmt_tbuff() +static /*HDR*/ +/** + * @brief Copy array of bytes in reverse order * - * Purpose: Compute checksums and complete the message - * header, then transmit both header and data. - * The caller must have copied the data to be - * sent to the data field of the transmit buffer - * and have set up the cmd field and the - * len field of pm->hdr. + * Can be used if the destination address is in the same buffer + * behind the source address, so the source address would be + * overwritten by a normal memcpy(). * - * Input: MBG_MSG_BUFF *pm pointer to the message buffer - * - * Output: -- - * - * Ret val: -- - *+------------------------------------------------------------*/ + * @param[out] dst Destination address behind the source address + * @param[in] src Source address + * @param[in] n_bytes Number of bytes to copy + */ +void memcpy_reverse( void *dst, const void *src, int n_bytes ) +{ + if ( n_bytes ) // just to be sure it isn't 0 + { + uint8_t *dstp = ( (uint8_t *) dst ) + n_bytes; + uint8_t *srcp = ( (uint8_t *) src ) + n_bytes; + + while ( --n_bytes ) + *(--dstp) = *(--srcp); + } + +} // memcpy_reverse + + /*HDR*/ -int xmt_tbuff( MBG_MSG_CTL *pmctl ) +/** + * @brief Complete message header and transmit message + * + * Compute checksums and complete the message header, + * then transmit both header and data. The caller must + * have copied the data to be sent to the data field + * of the transmit buffer and have set up the cmd and + * len fields of the message header. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to XBP address specifier + * + * @return one of the @ref MBG_RETURN_CODES + */ +int xmt_tbuff( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr ) { static const char soh = START_OF_HEADER; MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; - int n_bytes = pmb->hdr.len + sizeof( pmb->hdr ); - #if _USE_ENCRYPTION || _USE_SOCKET_IO - int rc; - #endif + int msg_len = sizeof( pmb->hdr ) + pmb->hdr.len; + int rc = MBG_ERR_UNSPEC; #if _USE_ENCRYPTION - CRYPT_MSG_PREFIX cm_pfx = { { 0 } }; + CRYPT_MSG_PREFIX cm_pfx; #endif // Set up the checksums of the unencrypted packet. pmb->hdr.data_csum = msg_csum( pmb->u.bytes, pmb->hdr.len ); pmb->hdr.hdr_csum = msg_hdr_csum( &pmb->hdr ); + // If an XBP address has been specified we convert + // the original msg into an XBP msg. + if ( p_addr ) + { + // Move the original msg to the data part of an XBP msg + // don't just use memcpy here since the destination memory area + // overlaps the source memory area. + memcpy_reverse( &pmb->u.xbp_msg_data.std_msg.hdr, &pmb->hdr, msg_len ); + + // Fill in the specified XBP address. + pmb->u.xbp_msg_data.xbp_addr = *p_addr; + + // Set up the new msg header as XPB msg. + pmb->hdr.cmd = GPS_XBP_PACKET; + msg_len += sizeof( pmb->u.xbp_msg_data.xbp_addr ); + pmb->hdr.len = msg_len; + pmb->hdr.data_csum = msg_csum( pmb->u.bytes, pmb->hdr.len ); + pmb->hdr.hdr_csum = msg_hdr_csum( &pmb->hdr ); + msg_len += sizeof( pmb->hdr ); + } + #if _USE_ENCRYPTION - if ( pmctl->xmt.xfer_mode == MBG_XFER_MODE_ENCRYTED ) + if ( pmctl->xmt.xfer_mode == MBG_XFER_MODE_ENCRYPTED ) { + memset( &cm_pfx, 0, sizeof( cm_pfx ) ); + rc = encrypt_message( pmctl, &cm_pfx, pmb ); + // on error, one of the MBG_ERROR_CODES, else number of bytes encrypted - if ( rc < 0 ) - return rc; // an error occurred + if ( rc < 0 ) // error + goto out; - n_bytes = rc; + msg_len = rc; } #endif - // n_bytes now contains the original msg data len which may - // possibly have been rounded up by the encryption routine. + // msg_len now contains the original msg data len which may + // possibly have been rounded up by the encryption routine. // - // The full msg consists of the CRYPT_MSG_PREFIX (if the msg - // has been encrypted), the msg header, and n_bytes of data. - + // The full msg consists of the CRYPT_MSG_PREFIX (if the msg + // has been encrypted), the msg header, and msg_len of data. switch ( pmctl->conn_type ) { #if _USE_SERIAL_IO @@ -385,103 +515,218 @@ int xmt_tbuff( MBG_MSG_CTL *pmctl ) // Note: encrypted msgs over serial are not yet supported. - _mbgserio_write( port_handle, &soh, sizeof( soh ) ); - _mbgserio_write( port_handle, pmb, n_bytes ); + rc = mbgserio_write( port_handle, &soh, sizeof( soh ) ); + + if ( rc < 0 ) // error + goto out; + + if ( rc != sizeof( soh ) ) + goto out_write_failed; + + rc = mbgserio_write( port_handle, pmb, msg_len ); + + if ( rc < 0 ) // error + goto out; + + if ( rc != msg_len ) // error + goto out_write_failed; + } break; #endif // _USE_SERIAL_IO + #if _USE_SERIAL_IO_FTDI + case MBG_CONN_TYPE_SERIAL_FTDI: + { + // Yet this is anyway supported under Windows only, so we can + // safely use Windows-specific types as expected by the FTDI API. + DWORD bytes_written; + FT_HANDLE port_handle = pmctl->st.ftdiio.port_handle; + FT_STATUS status; + + // Note: encrypted msgs over serial are not yet supported. + status = FT_Write( port_handle, (LPVOID) &soh, sizeof( soh ), &bytes_written ); + + if ( status != FT_OK ) + { + rc = mbg_ftdi_ft_status_to_mbg( status ); + goto out; + } + + if ( bytes_written != sizeof( soh ) ) + goto out_write_failed; + + status = FT_Write( port_handle, pmb, msg_len, &bytes_written ); + + if ( status != FT_OK ) + { + rc = mbg_ftdi_ft_status_to_mbg( status ); + goto out; + } + + if ( bytes_written != (DWORD) msg_len ) + goto out_write_failed; + + } break; + #endif // _USE_SERIAL_IO_FTDI + #if _USE_SOCKET_IO case MBG_CONN_TYPE_SOCKET: { - uint8_t net_xmt_buffer[sizeof( MBG_MSG_BUFF ) + 1] = { 0 }; - uint8_t *p = net_xmt_buffer; + uint8_t sock_xmt_buffer[sizeof( MBG_MSG_BUFF ) + 1]; + uint8_t *p = sock_xmt_buffer; + + #if defined( DEBUG ) + memset( sock_xmt_buffer, 0, sizeof( sock_xmt_buffer ) ); // only to simplify debugging + #endif *p++ = soh; - rc = n_bytes; // save the value of n_bytes + rc = msg_len; // save the value of msg_len #if _USE_ENCRYPTION - if ( pmctl->xmt.xfer_mode == MBG_XFER_MODE_ENCRYTED ) + if ( pmctl->xmt.xfer_mode == MBG_XFER_MODE_ENCRYPTED ) { memcpy( p, &cm_pfx, sizeof( cm_pfx ) ); p += sizeof( cm_pfx ); - n_bytes += sizeof( cm_pfx ); + msg_len += sizeof( cm_pfx ); } #endif memcpy( p, pmb, rc ); p += rc; - n_bytes++; // also account for SOH + msg_len += sizeof( soh ); // also account for SOH - rc = sendto( pmctl->st.sockio.sockfd, net_xmt_buffer, n_bytes, 0, - (const struct sockaddr *) &pmctl->st.sockio.addr, + rc = sendto( pmctl->st.sockio.sockfd, sock_xmt_buffer, msg_len, 0, + (const struct sockaddr *) &pmctl->st.sockio.addr, sizeof( pmctl->st.sockio.addr ) ); - if ( rc < 0 ) - goto fail; + if ( rc < 0 ) // on error: -1 on Linux, SOCKET_ERROR == -1 on Windows + { + rc = mbg_get_last_socket_error( "sendto failed in xmt_tbuff" ); + goto out; + } + + if ( rc != msg_len ) + goto out_write_failed; } break; #endif // _USE_SOCKET_IO + #if _USE_USB_IO + case MBG_CONN_TYPE_USB: + { + uint8_t usb_xmt_buffer[sizeof( MBG_MSG_BUFF ) + 1]; + uint8_t *p = usb_xmt_buffer; + + #if defined( DEBUG ) + memset( usb_xmt_buffer, 0, sizeof( usb_xmt_buffer ) ); // only to simplify debugging + #endif + + *p = soh; + memcpy( p + 1, pmb, msg_len ); + msg_len++; // also account for SOH + + // Note: encrypted msgs over USB are not yet supported. + rc = mbgusbio_write( &pmctl->st.usbio, p, msg_len, 1000 ); + + if ( rc < 0 ) // error + goto out; + + if ( rc != msg_len ) + goto out_write_failed; + + } break; + #endif // _USE_USB_IO + + #if _USE_USB_DIRECT_IO + case MBG_CONN_TYPE_USB_DIRECT_IO: + { + ssize_t bytes; + uint8_t usb_xmt_buffer[sizeof( MBG_MSG_BUFF ) + 1]; + uint8_t *p = usb_xmt_buffer; + + #if defined( DEBUG ) + memset( usb_xmt_buffer, 0, sizeof( usb_xmt_buffer ) ); // only to simplify debugging + #endif + + *p = soh; + memcpy( p + 1, pmb, msg_len ); + msg_len++; // also account for SOH + + // Note: encrypted msgs over direct USB I/O are not yet supported. + bytes = write( pmctl->st.usbdio.usbdiofd, p, msg_len ); + + if ( bytes < 0 ) // error + { + rc = mbg_get_last_error( "write failed for USB direct I/O" ); + goto out; + } + + if ( bytes != msg_len ) + goto out_write_failed; + + } break; + #endif + default: - goto fail; + rc = MBG_ERR_NOT_SUPP_ON_OS; + goto out; + + } // switch - } /* switch */ + rc = MBG_SUCCESS; + goto out; - return 0; +out_write_failed: + rc = MBG_ERR_BYTES_WRITTEN; -fail: - return -1; //##++ +out: + return rc; } /* xmt_tbuff */ -/*-------------------------------------------------------------- - * Name: xmt_cmd() - * - * Purpose: Send a command without parameters +/*HDR*/ +/** + * @brief Send a binary command message without parameters * - * Input: MBG_MSG_BUFF *pm pointer to the message buffer - * ushort cmd the command code + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to XBP address specifier + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES * - * Output: -- + * @return One of the @ref MBG_RETURN_CODES * - * Ret val: -- - *+------------------------------------------------------------*/ - -/*HDR*/ -int xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) + * @see ::xmt_cmd_us + */ +int xmt_cmd( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd ) { MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; pmb->hdr.len = 0; pmb->hdr.cmd = cmd; - return xmt_tbuff( pmctl ); + return xmt_tbuff( pmctl, p_addr ); } /* xmt_cmd */ -/*-------------------------------------------------------------- - * Name: xmt_cmd_us() - * - * Purpose: Send a command that needs one parameter with - * type ushort. +/*HDR*/ +/** + * @brief Send a binary command message with ushort (16 bit) parameter * - * Input: MBG_MSG_BUFF *pm pointer to the message buffer - * ushort cmd the command code - * ushort us the parameter + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to XBP address specifier + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * @param[in] us The 16 bit message parameter (data) * - * Output: -- + * @return One of the @ref MBG_RETURN_CODES * - * Ret val: -- - *+------------------------------------------------------------*/ - -/*HDR*/ -int xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t us ) + * @see ::xmt_cmd + */ +int xmt_cmd_us( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd, uint16_t us ) { MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; @@ -489,30 +734,26 @@ int xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t us ) pmb->hdr.len = sizeof( pmb->u.msg_data.us ); pmb->hdr.cmd = cmd; - return xmt_tbuff( pmctl ); + return xmt_tbuff( pmctl, p_addr ); } /* xmt_cmd_us */ -/*-------------------------------------------------------------- - * Name: check_transfer() - * - * Purpose: Check the sequence of incoming characters for - * blocks of binary data. Blocks of data are - * saved in a MBG_MSG_BUFF variable and the - * caller checks the return value to get the - * receive status. +/*HDR*/ +/** + * @brief Check an incoming data stream for a binary message * - * Input: MSG_RCV_CTL *pctl pointer to rcv ctrl structure - * uint8_t c the latest char that came in + * Check the sequence of incoming characters for blocks of + * binary message data. Binary messages are saved in a buffer + * which is part of the ::MBG_MSG_RCV_CTL structure and the + * caller checks the return value to get the receive status. * - * Output: -- + * @param[in,out] prctl Pointer to a valid receive control structure + * @param[in] c A byte from the incoming data stream * - * Ret val: see header file for valid codes - *+------------------------------------------------------------*/ - -/*HDR*/ + * @return One of the ::TR_STATUS_CODES + */ int check_transfer( MBG_MSG_RCV_CTL *prctl, uint8_t c ) { MBG_MSG_BUFF *pmb = prctl->pmb; @@ -524,6 +765,7 @@ int check_transfer( MBG_MSG_RCV_CTL *prctl, uint8_t c ) return TR_WAITING; /* ignore this character */ /* initialize receiving */ + mbg_tmo_get_time( &prctl->tstamp ); prctl->cur = (uint8_t *) pmb; /* first byte of buffer */ prctl->cnt = sizeof( *pmh ); /* prepare to rcv msg header */ prctl->flags = 0; @@ -593,4 +835,3 @@ msg_complete: - diff --git a/mbglib/common/gpsserio.h b/mbglib/common/gpsserio.h index 494f125..a3d5c3a 100644 --- a/mbglib/common/gpsserio.h +++ b/mbglib/common/gpsserio.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsserio.h 1.34 2011/04/15 13:12:02 martin REL_M $ + * $Id: gpsserio.h 1.48.1.1 2015/07/24 11:07:39 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -31,6 +31,62 @@ * * ----------------------------------------------------------------------- * $Log: gpsserio.h $ + * Revision 1.48.1.1 2015/07/24 11:07:39 martin + * Revision 1.48 2015/07/06 15:23:51 martin + * Updated function prototypes. + * Revision 1.47 2015/05/13 13:52:57 martin + * Support XBP addressing. + * Fixed misspelled MBG_XFER_MODE_ENCRYPTED. + * Renamed some GPS cmd codes to more intuitive names. + * Added GPS cmd CMD codes for FDM. + * New cmd code GPS_XMR_EXT_SRC_INFO_IDX. + * Removed trailing whitespace. + * Updated doxygen-style comments. + * Updated function prototypes. + * Revision 1.46 2014/07/17 09:47:21 martin + * New command codes GPS_GPIO_STATUS_IDX + * and GPS_XMR_HOLDOVER_STATUS. + * Updated doxygen comments. + * Revision 1.45 2014/05/27 08:58:47 martin + * Defined a some new command codes and added + * associated fields to MSG_DATA union. + * Introduced MBG_SOCK_FD type. + * Use new preprocessor symbol MBG_TGT_POSIX. + * Support new libusb. + * Conditional FTDI serial interface support. + * Account for definitions renamed elsewhere. + * Simplified declaration of code/name tables. + * Conditionally use new CHK_TSTR_FNC type. + * Huge rework of comments in doxygen format. + * Revision 1.44 2013/04/04 09:03:29Z martin + * Support HaveQuick configuration. + * Revision 1.43 2013/01/30 16:07:49 martin + * Changed definition of transfer status codes to an enum + * with appropriate comments. + * Added union TZCODE_UNION. + * Fixed some doxygen comments. + * Revision 1.42 2013/01/16 11:48:36Z martin + * Support IMS and XMR_HOLDOVER_INTV. + * Revision 1.41 2012/10/30 16:25:15 martin + * Added GPS_WILDCARD cmd code. + * Account for changed chk_tstr_func return code. + * Added completion codes TR_COMPLETE_TSTR and TR_RCVD_NACK. + * Revision 1.40 2012/04/11 16:03:29 martin + * Fixed some doxygen stuff. + * Revision 1.39 2012/03/08 15:34:18Z martin + * Added default setting for _USE_USB_IO. + * Revision 1.38 2012/03/06 15:33:43 martin + * Added support for SCU and LNO. + * Account for modified chk_tstr() parameters. + * Revision 1.37 2011/11/25 14:59:17Z martin + * Account for some renamed evt_log library symbols. + * Revision 1.36 2011/11/25 10:37:10 martin + * Added commands and data structures to support log events. + * Revision 1.35 2011/07/29 09:46:54 daniel + * Use native alignment only. + * Added command code GPS_XMR_INSTANCES. + * Support GPIO configuration. + * Support for USB. * Revision 1.34 2011/04/15 13:12:02 martin * Added initializer for command name table. * Unified mutex stuff using macros from mbgmutex.h. @@ -61,7 +117,7 @@ * Now _USE_PCPSDEFS by default for non-firmware apps. * Fixed comments on GPS_OPT_SETTINGS and GPS_OPT_INFO. * Revision 1.25 2007/02/06 16:31:04Z martin - * Modified comment for PZF_PCPS_TIME which can now also + * Modified comment for PZF_PCPS_TIME which can now also * be sent to a device. * Added mutex support. * Added SVNO to the buffer union. @@ -91,7 +147,7 @@ * Revision 1.19 2006/06/15 10:39:49Z martin * Added some special types to the MSG_DATA union which have * previously been defined as generic uint16_t types. - * Removed MBG_OPT_SETTINGS and MBG_OPT_INFO from + * Removed MBG_OPT_SETTINGS and MBG_OPT_INFO from * the MSG_DATA union since those types are not used with * the binary protocol. * Revision 1.18 2006/05/18 09:43:35Z martin @@ -100,7 +156,7 @@ * Renamed IRIG_... symbols to IRIG_TX_... in order to distinguish * from IRIG input configuration which might be available in the future. * Added some fields to the MSG_DATA union. - * Renamed MSG_BUFF field "data" to "msg_data" in order to avoid + * Renamed MSG_BUFF field "data" to "msg_data" in order to avoid * conflict with reserved word in some environments. * Rewrote inclusion control macros. * Replace control of inclusion of function prototypes by new symbol @@ -124,7 +180,7 @@ * Don't include function prototypes by default if compiling firmware. * Conditionally support private data structures, automatically include * those definitions if compiling firmware. - * The data portion of MSG_BUFF is now a union whose maximum size + * The data portion of MSG_BUFF is now a union whose maximum size * can be overridden by a preprocessor value. * Added MBG_OPT_SETTINGS and MBG_OPT_INFO to the buffer union. * Updated function prototypes. @@ -186,7 +242,7 @@ #ifndef _USE_MUTEX #if defined( MBG_TGT_WIN32 ) #define _USE_MUTEX 1 - #elif defined( MBG_TGT_UNIX ) + #elif defined( MBG_TGT_POSIX ) #define _USE_MUTEX 1 #endif #endif @@ -204,24 +260,52 @@ /* Control whether serial port communication shall be supported */ #ifndef _USE_SERIAL_IO #if _IS_MBG_FIRMWARE - #define _USE_SERIAL_IO 0 // Firmware provides its own serial I/O functions + #define _USE_SERIAL_IO 0 // firmware provides its own serial I/O functions #else - #define _USE_SERIAL_IO 1 // supported by default + #define _USE_SERIAL_IO 1 // supported by default + #endif +#endif + +#ifndef _USE_SERIAL_IO_FTDI + // FTDI D2xx USB-To-Serial converters accessed via a proprietary DLL + #define _USE_SERIAL_IO_FTDI 0 // not supported by default +#endif + +/* Control whether USB communication shall be supported */ +#if defined( MBG_TGT_LINUX ) + #ifndef _USE_USB_IO // may be overridden by project settings + #define _USE_USB_IO 0 // not supported by default #endif +#else + // USB I/O requires libusb and is currently only supported under Linux. + // So for non-Linux targets force _USE_USB_IO to 0. + #define _USE_USB_IO 0 // not supported by default +#endif + +/* + * Control whether direct USB I/O communication is supported + * for example via "/dev/mbgims" in case there is an appropriate + * channel to do so. + */ +#if defined( MBG_TGT_LINUX ) + #ifndef _USE_USB_DIRECT_IO + #define _USE_USB_DIRECT_IO 0 // Not supported by default + #endif +#else + // Not supported by other platforms + #define _USE_USB_DIRECT_IO 0 // Not supported by default #endif /* Control inclusion of secudefs.h */ #if _USE_SOCKET_IO // Network socket I/O always requires secudefs, so make sure // this is defined correctly. - #ifdef _USE_ENCRYPTION - #undef _USE_ENCRYPTION - #endif - #define _USE_ENCRYPTION 1 + #undef _USE_ENCRYPTION + #define _USE_ENCRYPTION 1 #else // If no socket I/O is used then secudefs aren't required, either. #ifndef _USE_ENCRYPTION - #define _USE_ENCRYPTION 0 + #define _USE_ENCRYPTION 0 #endif #endif @@ -265,8 +349,19 @@ #include #endif +#if _USE_SERIAL_IO_FTDI + #include // interface for ftd2xx.dll +#else + // just to avoid build errors if FTDI API is not supported + #define FT_STATUS int +#endif + +#if _USE_USB_IO + #include +#endif + #if _USE_SOCKET_IO - #if defined( MBG_TGT_UNIX ) + #if defined( MBG_TGT_POSIX ) #include #endif #endif @@ -289,246 +384,387 @@ #endif - -#ifdef __cplusplus -extern "C" { -#endif - #ifdef _GPSSERIO #define _ext #else #define _ext extern #endif -#if defined( _USE_PACK ) // set byte alignment - #pragma pack( 1 ) -#endif +/* Start of header body */ +// We don't use pragma pack() here but native alignment. -/* Start of header body */ +#ifdef __cplusplus +extern "C" { +#endif -/* Status codes of check_transfer() function. */ +/** + * @brief Status codes returned by the check_transfer() function. + */ +enum TR_STATUS_CODES +{ + TR_COMPLETE_TSTR = 3, ///< The optional time string check has detected a valid time string + TR_COMPLETE = 2, ///< A binary message has been received successfully + TR_RECEIVING = 1, ///< Binary reception in progress, i.e. after START_OF_HEADER received + TR_WAITING = 0, ///< Waiting for a binary message, i.e. no START_OF_HEADER received, yet + TR_TIMEOUT = -1, ///< No data received during the timeout interval + TR_CSUM_HDR = -2, ///< The header checksum of a received message is invalid + TR_CSUM_DATA = -3, ///< The data checksum of a received message is invalid + TR_DECRYPTION = -4, ///< A binary message received over LAN could not be decrypted. + TR_OPEN_ERR = -5, ///< Failed to open connection. + TR_IO_ERR = -6, ///< I/O error for the specified connection + TR_AUTH_ERR = -7, ///< Authentication error for the specified LAN connection + TR_RCVD_NACK = -8 ///< Received Negative Acknowledge from a device (prev. msg not accepted or not supported) +}; -#define TR_COMPLETE 2 -#define TR_RECEIVING 1 -#define TR_WAITING 0 -#define TR_TIMEOUT -1 -#define TR_CSUM_HDR -2 -#define TR_CSUM_DATA -3 -#define TR_DECRYPTION -4 -#define TR_OPEN_ERR -5 -#define TR_IO_ERR -6 -#define TR_AUTH_ERR -7 -/* The code below is sent before a message header. */ +/** + * @brief The start of header code sent before a binary message header + */ +#define START_OF_HEADER 0x01 ///< ASCII SOH -#define START_OF_HEADER 0x01 /* ASCII SOH */ +/** + * @brief Control codes to be or'ed with a particular command/type code + */ +enum GPS_CMD_CTRL_CODES +{ + GPS_REQACK = 0x8000, ///< to device: request acknowledge + GPS_ACK = 0x4000, ///< from device: acknowledge a command + GPS_NACK = 0x2000, ///< from device: error evaluating a command +}; -/* The control codes defined below are to be or'ed with a command/type code. */ +#define GPS_CTRL_MSK 0xF000 ///< bit mask of all ::GPS_CMD_CTRL_CODES -#define GPS_REQACK 0x8000 /* to GPS rcvr: request acknowledge */ -#define GPS_ACK 0x4000 /* from GPS rcvr: acknowledge a command */ -#define GPS_NACK 0x2000 /* from GPS rcvr: error receiving command */ -#define GPS_CTRL_MSK 0xF000 /* masks control code from command */ +/** + * @brief A wildcard command code + * + * This code can be passed to a receive routine to wait for any type + * of binary packet rather than for a specific packet. + */ +#define GPS_WILDCARD ( (GPS_CMD) -1 ) -/**< @defgroup gps_cmds_serial GPS commands passed via serial port +/** + * @brief Command codes for the binary protocol + * + * These codes specify commands and associated data types used by Meinberg's + * binary protocol to exchange data with a device via serial port, direct USB, + * or socket I/O. + * + * Some commands and associated data structures can be read (r) from a device, others + * can be written (w) to the device, and some can also be sent automatically (a) by + * a device after a ::GPS_AUTO_ON command has been sent to the device. + * The individual command codes are marked with (rwa) accordingly, where '-' is used + * to indicate that a particular mode is not supported. * - * These codes specify commands/types of data to be supplied to - * the GPS receiver: + * @note Not all command code are supported by all devices. + * See the hints for a particular command. + * + * @note If ::GPS_ALM, ::GPS_EPH or a code named ..._IDX is sent to retrieve + * some data from a device then an uint16_t parameter must be also supplied + * in order to specify the index number of the data set to be returned. + * The valid index range depends on the command code. + * For ::GPS_ALM and ::GPS_EPH the index is the SV number which may be 0 or + * ::MIN_SVNO_GPS to ::MAX_SVNO_GPS. If the number is 0 then all ::N_SVNO_GPS + * almanacs or ephemeris data structures are returned. + * + * @see ::GPS_CMD_CODES_TABLE */ -/* clock auto-message to host */ -/* | host request, clock response */ -/* | | host download to clock */ -/* | | | */ -enum /* | | | */ +enum GPS_CMD_CODES { /* system data */ - GPS_AUTO_ON = 0x000, /* | | | X | no param, enable auto-msgs from GPS rcvr */ - GPS_AUTO_OFF, /* | | | X | no param, disable auto-msgs from GPS rcvr */ - GPS_SW_REV, /* | | X | | SW_REV, software revision */ - GPS_BVAR_STAT, /* | | X | | BVAR_STAT, status of buffered variables */ - GPS_TIME, /* | X | | X | TTM, current time or capture, or init board time */ - GPS_POS_XYZ, /* | | X | X | XYZ, current position in ECEF coords */ - GPS_POS_LLA, /* | | X | X | LLA, current position in geographic coords */ - GPS_TZDL, /* | | X | X | TZDL, time zone / daylight saving */ - GPS_PORT_PARM, /* | | X | X | PORT_PARM, (obsolete, use PORT_SETTINGS etc. ) */ - GPS_SYNTH, /* | | X | X | SYNTH synthesizer's frequency and phase */ - GPS_ANT_INFO, /* | X | X | | ANT_INFO, time diff after antenna disconnect */ - GPS_UCAP, /* | X | X | | TTM, user capture events */ - GPS_ENABLE_FLAGS, /* | | X | X | ENABLE_FLAGS, when to enable serial, pulses, and synth */ - GPS_STAT_INFO, /* | | X | | STAT_INFO, request SV, mode and DAC info */ - GPS_SWITCH_PARMS, /* | | X | X | (obsolete, use GPS_POUT_PROG_IDX) */ - GPS_STRING_PARMS, /* | | X | X | (obsolete, use GPS_PORT_INFO/GPS_PORT_SETTINGS */ - GPS_ANT_CABLE_LENGTH, /* | | X | X | ANT_CABLE_LEN, length of antenna cable */ - GPS_SYNC_OUTAGE_DELAY, /* | | X | X | (customized firmware only) */ - GPS_PULSE_INFO, /* | | X | X | (customized firmware only) */ - GPS_OPT_FEATURES, /* | | X | | (obsolete, use GPS_RECEIVER_INFO) */ - GPS_IRIG_TX_SETTINGS, /* | | X | X | IRIG_SETTINGS, (only if GPS_HAS_IRIG_TX) */ - GPS_RECEIVER_INFO, /* | | X | | RECEIVER_INFO, model specific info */ - GPS_STR_TYPE_INFO_IDX, /* | | X | | STR_TYPE_INFO_IDX, names and modes of supp. string types */ - GPS_PORT_INFO_IDX, /* | | X | | PORT_INFO_IDX, port settings + additional info */ - GPS_PORT_SETTINGS_IDX, /* | | X | X | PORT_SETTINGS_IDX, settings for specified port */ - GPS_POUT_INFO_IDX, /* | | X | | POUT_INFO_IDX, pout settings + additional info */ - GPS_POUT_SETTINGS_IDX, /* | | X | X | POUT_SETTINGS_IDX, programmable pulse output cfg */ - GPS_IRIG_TX_INFO, /* | | X | | IRIG_INFO, (only if GPS_HAS_IRIG_TX) */ - GPS_MULTI_REF_SETTINGS,/* | | X | X | MULTI_REF_SETTINGS, (only if HAS_MULTI_REF) */ - GPS_MULTI_REF_INFO, /* | | X | | MULTI_REF_INFO, (only if HAS_MULTI_REF) */ - GPS_ROM_CSUM, /* | | X | | ROM_CSUM, (not supported by all devices) */ - GPS_MULTI_REF_STATUS, /* | | X | | MULTI_REF_STATUS, (only if HAS_MULTI_REF) */ - GPS_RCV_TIMEOUT, /* | | X | X | RCV_TIMEOUT, [min] (only if HAS_RCV_TIMEOUT) */ - GPS_IGNORE_LOCK, /* | | X | X | IGNORE_LOCK, if != 0 always claim to be sync */ - GPS_IRIG_RX_SETTINGS, /* | | X | X | IRIG_SETTINGS, (only if GPS_HAS_IRIG_RX) */ - GPS_IRIG_RX_INFO, /* | | X | | IRIG_INFO, (only if GPS_HAS_IRIG_RX) */ - GPS_REF_OFFS, /* | | X | X | MBG_REF_OFFS, (only if GPS_HAS_REF_OFFS) */ - GPS_DEBUG_STATUS, /* | | X | | MBG_DEBUG_STATUS, (only if GPS_HAS_DEBUG_STATUS) */ - GPS_XMR_SETTINGS_IDX, /* | | X | X | XMULTI_REF_SETTINGS_IDX, (only if GPS_HAS_XMULTI_REF) */ - GPS_XMR_INFO_IDX, /* | | X | | XMULTI_REF_INFO_IDX, (only if GPS_HAS_XMULTI_REF) */ - GPS_XMR_STATUS_IDX, /* | | X | | XMULTI_REF_STATUS_IDX, (only if GPS_HAS_XMULTI_REF) */ - GPS_OPT_SETTINGS, /* | | X | X | MBG_OPT_SETTINGS, (only if GPS_HAS_OPT_SETTINGS) */ - GPS_OPT_INFO, /* | | X | | MBG_OPT_INFO, (only if GPS_HAS_OPT_SETTINGS) */ - GPS_CLR_UCAP_BUFF, /* | | X | | command only, no data */ - GPS_TIME_SCALE, /* | | X | X | MBG_TIME_SCALE_{SETTINGS|INFO}, (only if GPS_HAS_TIME_SCALE) */ - GPS_NAV_ENG_SETTINGS, /* | | X | X | NAV_ENGINE_SETTINGS, (only if GPS_HAS_NAV_ENGINE_SETTINGS) */ - GPS_RAW_IRIG_DATA, /* | | X | | MBG_RAW_IRIG_DATA, (only if GPS_HAS_RAW_IRIG_DATA) */ + GPS_AUTO_ON = 0x000, ///< (-w-) no data, enable auto-msgs from device + GPS_AUTO_OFF, ///< (-w-) no data, disable auto-msgs from device + GPS_SW_REV, ///< (r--) deprecated, ::SW_REV, software revision, use only if ::GPS_RECEIVER_INFO not supp. + GPS_BVAR_STAT, ///< (r--) ::BVAR_STAT, status of buffered variables, only if ::GPS_MODEL_HAS_BVAR_STAT + GPS_TIME, ///< (-wa) ::TTM, current time or capture, or init board time + GPS_POS_XYZ, ///< (rw-) ::XYZ, current position in ECEF coordinates, only if ::GPS_MODEL_HAS_POS_XYZ + GPS_POS_LLA, ///< (rw-) ::LLA, current position in geographic coordinates, only if ::GPS_MODEL_HAS_POS_LLA + GPS_TZDL, ///< (rw-) ::TZDL, time zone / daylight saving, only if ::GPS_MODEL_HAS_TZDL + GPS_PORT_PARM, ///< (rw-) deprecated, ::PORT_PARM, use ::PORT_SETTINGS etc. if ::GPS_RECEIVER_INFO supported + GPS_SYNTH, ///< (rw-) ::SYNTH, synthesizer settings, only if ::GPS_HAS_SYNTH + GPS_ANT_INFO, ///< (r-a) ::ANT_INFO, time diff after antenna disconnect, only if ::GPS_MODEL_HAS_ANT_INFO + GPS_UCAP, ///< (r-a) ::TTM, user capture events, only if ::RECEIVER_INFO::n_ucaps > 0 + GPS_ENABLE_FLAGS, ///< (rw-) ::ENABLE_FLAGS, when to enable serial, pulses, and synth, only if ::GPS_MODEL_HAS_ENABLE_FLAGS + GPS_STAT_INFO, ///< (r--) ::STAT_INFO, satellite info, mode of operation, and DAC info, only if ::GPS_MODEL_HAS_STAT_INFO + GPS_SWITCH_PARMS, ///< (rw-) deprecated, use ::GPS_POUT_INFO_IDX/::GPS_POUT_SETTINGS_IDX + GPS_STRING_PARMS, ///< (rw-) deprecated, use ::GPS_PORT_INFO_IDX/::GPS_PORT_SETTINGS_IDX + GPS_ANT_CABLE_LENGTH, ///< (rw-) ::ANT_CABLE_LEN, length of antenna cable, only if ::GPS_MODEL_HAS_ANT_CABLE_LENGTH + GPS_SYNC_OUTAGE_DELAY, ///< (rw-) (customized firmware only) + GPS_PULSE_INFO, ///< (rw-) (customized firmware only) + GPS_OPT_FEATURES, ///< (r--) deprecated, use ::GPS_RECEIVER_INFO + GPS_IRIG_TX_SETTINGS, ///< (rw-) ::IRIG_SETTINGS, only if ::GPS_HAS_IRIG_TX + GPS_RECEIVER_INFO, ///< (r--) ::RECEIVER_INFO, model specific info, not supported by *very* old devices + GPS_STR_TYPE_INFO_IDX, ///< (r--) ::STR_TYPE_INFO_IDX, names and capabilities of supp. string types, only if ::RECEIVER_INFO::n_str_type > 0 + GPS_PORT_INFO_IDX, ///< (r--) ::PORT_INFO_IDX, serial port settings and capabilities, only if ::RECEIVER_INFO::n_com_ports > 0 + GPS_PORT_SETTINGS_IDX, ///< (rw-) ::PORT_SETTINGS_IDX, settings for specified serial port, only if ::RECEIVER_INFO::n_com_ports > 0 + GPS_POUT_INFO_IDX, ///< (r--) ::POUT_INFO_IDX, programmable pulse output settings and capabilities, only if ::RECEIVER_INFO::n_prg_out > 0 + GPS_POUT_SETTINGS_IDX, ///< (rw-) ::POUT_SETTINGS_IDX, programmable pulse output settings, only if ::RECEIVER_INFO::n_prg_out > 0 + GPS_IRIG_TX_INFO, ///< (r--) ::IRIG_INFO, only if ::GPS_HAS_IRIG_TX + GPS_MULTI_REF_SETTINGS, ///< (rw-) ::MULTI_REF_SETTINGS, only if ::GPS_HAS_MULTI_REF + GPS_MULTI_REF_INFO, ///< (r--) ::MULTI_REF_INFO, only if ::GPS_HAS_MULTI_REF + GPS_ROM_CSUM, ///< (r--) ::ROM_CSUM, not supported by all devices + GPS_MULTI_REF_STATUS, ///< (r--) ::MULTI_REF_STATUS, only if ::GPS_HAS_MULTI_REF + GPS_RCV_TIMEOUT, ///< (rw-) ::RCV_TIMEOUT, [min], only if ::GPS_HAS_RCV_TIMEOUT + GPS_IGNORE_LOCK, ///< (rw-) ::IGNORE_LOCK, if != 0 always claim to be sync, only if ::GPS_MODEL_HAS_GPS_IGNORE_LOCK + GPS_IRIG_RX_SETTINGS, ///< (rw-) ::IRIG_SETTINGS, only if ::GPS_HAS_IRIG_RX + GPS_IRIG_RX_INFO, ///< (r--) ::IRIG_INFO, only if ::GPS_HAS_IRIG_RX + GPS_REF_OFFS, ///< (rw-) ::MBG_REF_OFFS, only if ::GPS_HAS_REF_OFFS + GPS_DEBUG_STATUS, ///< (r--) ::MBG_DEBUG_STATUS, only if ::GPS_HAS_DEBUG_STATUS + GPS_XMR_SETTINGS_IDX, ///< (rw-) ::XMULTI_REF_SETTINGS_IDX, idx 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1, only if ::GPS_HAS_XMULTI_REF + GPS_XMR_INFO_IDX, ///< (r--) ::XMULTI_REF_INFO_IDX, idx 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1, only if ::GPS_HAS_XMULTI_REF + GPS_XMR_STATUS_IDX, ///< (r--) ::XMULTI_REF_STATUS_IDX, idx 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1, only if ::GPS_HAS_XMULTI_REF + GPS_OPT_SETTINGS, ///< (rw-) ::MBG_OPT_SETTINGS, only if ::GPS_HAS_OPT_SETTINGS + GPS_OPT_INFO, ///< (r--) ::MBG_OPT_INFO, only if ::GPS_HAS_OPT_SETTINGS + GPS_CLR_UCAP_BUFF, ///< (-w-) no data, only if ::RECEIVER_INFO::n_ucaps > 0 + GPS_TIME_SCALE, ///< (rw-) ::MBG_TIME_SCALE_SETTINGS/::MBG_TIME_SCALE_INFO, only if ::GPS_HAS_TIME_SCALE + GPS_NAV_ENG_SETTINGS, ///< (rw-) ::NAV_ENGINE_SETTINGS, only if ::GPS_HAS_NAV_ENGINE_SETTINGS + GPS_RAW_IRIG_DATA, ///< (r--) ::MBG_RAW_IRIG_DATA, only if ::GPS_HAS_RAW_IRIG_DATA + GPS_GPIO_CFG_LIMITS, ///< (r--) ::MBG_GPIO_CFG_LIMITS, only if ::GPS_HAS_GPIO + GPS_GPIO_INFO_IDX, ///< (r--) ::MBG_GPIO_INFO_IDX, settings and capabilities, only if ::GPS_HAS_GPIO + GPS_GPIO_SETTINGS_IDX, ///< (rw-) ::MBG_GPIO_SETTINGS_IDX, settings of a specific port, only if ::GPS_HAS_GPIO + GPS_XMR_INSTANCES, ///< (r--) ::XMULTI_REF_INSTANCES, only if ::GPS_HAS_XMRS_MULT_INSTC + GPS_CLR_EVT_LOG, ///< (-w-) no data, clear event log command, only if ::GPS_HAS_EVT_LOG + GPS_NUM_EVT_LOG_ENTRIES, ///< (r--) ::MBG_NUM_EVT_LOG_ENTRIES, num. of log entries, only if ::GPS_HAS_EVT_LOG + GPS_FIRST_EVT_LOG_ENTRY, ///< (r--) first/oldest ::MBG_EVT_LOG_ENTRY, only if ::GPS_HAS_EVT_LOG + GPS_NEXT_EVT_LOG_ENTRY, ///< (r--) next ::MBG_EVT_LOG_ENTRY, only if ::GPS_HAS_EVT_LOG + GPS_LNO_STATUS, ///< (r--) ::LNO_STATE, only if ::GPS_MODEL_IS_LNO + GPS_IMS_STATE, ///< (r--) ::MBG_IMS_STATE, only if ::GPS_HAS_IMS + GPS_IMS_SENSOR_STATE_IDX, ///< (r--) ::MBG_IMS_SENSOR_STATE_IDX, only if ::GPS_HAS_IMS + GPS_XMR_HOLDOVER_INTV, ///< (rw-) ::XMR_HOLDOVER_INTV, only if ::GPS_MODEL_HAS_XMR_HOLDOVER_INTV, see also ::GPS_XMR_HOLDOVER_STATUS + GPS_HAVEQUICK_RX_SETTINGS, ///< (rw-) ::HAVEQUICK_SETTINGS for input, only if ::GPS_HAS_HAVEQUICK + GPS_HAVEQUICK_RX_INFO, ///< (r--) ::HAVEQUICK_INFO for input, only if ::GPS_HAS_HAVEQUICK + GPS_HAVEQUICK_TX_SETTINGS, ///< (rw-) ::HAVEQUICK_SETTINGS for output, only if ::GPS_HAS_HAVEQUICK + GPS_HAVEQUICK_TX_INFO, ///< (r--) ::HAVEQUICK_INFO for output, only if ::GPS_HAS_HAVEQUICK + GPS_PTP_CFG, ///< (rw-) ::PTP_CFG_INFO/::PTP_CFG_SETTINGS, only if ::GPS_HAS_PTP + GPS_PTP_STATE, ///< (r--) ::PTP_STATE, current PTP status, only if ::GPS_HAS_PTP + GPS_PTP_UC_MASTER_CFG_LIMITS, ///< (r--) ::PTP_UC_MASTER_CFG_LIMITS, only if ::PTP_CFG_CAN_BE_UNICAST_SLAVE + GPS_PTP_UC_MASTER_CFG, ///< (rw-) ::PTP_UC_MASTER_INFO_IDX/::PTP_UC_MASTER_SETTINGS_IDX, only if ::PTP_CFG_CAN_BE_UNICAST_SLAVE + GPS_NTP_GLB_CFG, ///< (rw-) ::NTP_GLB_INFO/::NTP_GLB_SETTINGS, only if ::GPS_HAS_NTP + GPS_NTP_CLNT_MODE_CFG, ///< (rw-) ::NTP_CLNT_MODE_INFO/::NTP_CLNT_MODE_SETTINGS, only if ::NTP_MSK_ROLE_CLIENT + GPS_NTP_SRV_MODE_CFG, ///< (rw-) ::NTP_SRV_MODE_INFO/::NTP_SRV_MODE_SETTINGS, only if ::NTP_MSK_ROLE_SERVER + GPS_NTP_PEER_SETTINGS_IDX, ///< (rw-) ::NTP_PEER_SETTINGS_IDX, only if ??? + GPS_NTP_SYS_STATE, ///< (r--) ::NTP_SYS_STATE, only if ??? + GPS_NTP_PEER_STATE_IDX, ///< (r--) ::NTP_PEER_STATE_IDX, only if ??? + GPS_SHS, ///< (rw-) ::SHS_INFO/::SHS_SETTINGS, only if ::GPS_HAS_SHS + GPS_SHS_STATUS, ///< (r--) ::SHS_STATUS, only if ::GPS_HAS_SHS + GPS_NET_GLB_CFG, ///< (rw-) ::MBG_NET_GLB_CFG_INFO/::MBG_NET_GLB_CFG_SETTINGS, only if ::GPS_HAS_NET_CFG + GPS_NET_DNS_SRVR, ///< (rw-) ::MBG_IP_ADDR_IDX, DNS cfg., only if ::MBG_NET_GLB_CFG_INFO::num_dns_srvr > 0 + GPS_NET_DNS_SRCH_DOM, ///< (rw-) ::MBG_NET_NAME_IDX, DNS cfg., only if ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom > 0 + GPS_NET_STAT_DNS_SRVR, ///< (r--) ::MBG_IP_ADDR_IDX, DNS status, only if ::MBG_NET_GLB_CFG_INFO::num_dns_srvr > 0 + GPS_NET_STAT_DNS_SRCH_DOM, ///< (r--) ::MBG_NET_NAME_IDX, DNS status, only if ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom > 0 + GPS_GNSS_SAT_INFO_IDX, ///< (r--) ::GNSS_SAT_INFO_IDX, only if ::MBG_GNSS_FLAG_SAT_INFO_IDX_SUPP_SER, deprecates ::GPS_GNSS_SAT_INFO + GPS_XMR_HOLDOVER_ELAPSED, ///< (r--) ::XMR_HOLDOVER_INTV, elapsed time in holdover mode, only if ::GPS_MODEL_HAS_XMR_HOLDOVER_INTV, deprecated by ::GPS_XMR_HOLDOVER_STATUS + GPS_GPIO_STATUS_IDX, ///< (r--) ::MBG_GPIO_STATUS_IDX, only if ::MBG_GPIO_CFG_LIMIT_FLAG_MASK_STATUS_SUPP + GPS_XMR_HOLDOVER_STATUS, ///< (r--) ::XMR_HOLDOVER_STATUS, only if ::XMRIF_MSK_HOLDOVER_STATUS_SUPP, deprecates ::GPS_XMR_HOLDOVER_ELAPSED and partially ::GPS_XMR_HOLDOVER_INTV + GPS_XBP_LIMITS, ///< (r--) ::XBP_LIMITS, only if ::GPS_HAS_XBP + GPS_XBP_NODE_LIMITS, ///< (r--) ::XBP_NODE_LIMITS, only if ::XBP_FEAT_MASK_NODES is set in ::XBP_LIMITS::features + GPS_XBP_NODE_INFO_IDX, ///< (r--) ::XBP_NODE_INFO_IDX, 0..::XBP_NODE_LIMITS::node_count-1 instances can be retrieved + GPS_FDM_OUTPUT_STATE_IDX, ///< (r--) ::MBG_IMS_FDM_OUTPUT_STATE_IDX, only if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + GPS_FDM_OUTPUT_SETTINGS_IDX, ///< (rw-) ::MBG_IMS_FDM_OUTPUT_SETTINGS_IDX, only if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + GPS_FDM_OUTPUT_INFO_IDX, ///< (r--) ::MBG_IMS_FDM_OUTPUT_INFO, only if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + GPS_FDM_LIMITS, ///< (r--) ::MBG_IMS_FDM_LIMITS, only if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + GPS_FDM_STATE, ///< (r--) ::MBG_IMS_FDM_STATE, only if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + GPS_FDM_SETTINGS, ///< (rw-) ::MBG_IMS_FDM_SETTINGS, only if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + GPS_FDM_INFO, ///< (r--) ::MBG_IMS_FDM_INFO, only if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + GPS_XMR_EXT_SRC_INFO_IDX, ///< (r--) ::XMR_EXT_SRC_INFO_IDX, only if ::XMRIF_MSK_EXT_SRC_INFO_SUPP /* GPS data */ - GPS_CFGH = 0x100, /* | | X | X | CFGH, SVs' configuration and health codes */ - GPS_ALM, /* | | X | X | req: uint16_t SV num, SV_ALM, one SV's almanac */ - GPS_EPH, /* | | X | X | req: uint16_t SV num, SV_EPH, one SV's ephemeris */ - GPS_UTC, /* | | X | X | UTC, GPS UTC correction parameters */ - GPS_IONO, /* | | X | X | IONO, GPS ionospheric correction parameters */ - GPS_ASCII_MSG, /* | | X | | ASCII_MSG, the GPS ASCII message */ + GPS_CFGH = 0x100, ///< (rw-) ::CFGH, SVs' configuration and health codes + GPS_ALM, ///< (rw-) req: uint16_t SV num, ::SV_ALM, one SV's almanac + GPS_EPH, ///< (rw-) req: uint16_t SV num, ::SV_EPH, one SV's ephemeris + GPS_UTC, ///< (rw-) ::UTC, GPS %UTC correction parameters + GPS_IONO, ///< (rw-) ::IONO, GPS ionospheric correction parameters + GPS_ASCII_MSG, ///< (r--) ::ASCII_MSG, the GPS ASCII message /* Glonass data */ - GPS_GLNS_ALM = 0x200, /* | | X | X | ** preliminary ** */ //##++ - GPS_GNSS_SAT_INFO, /* | | X | | GNSS_SAT_INFO, request SVs */ - GPS_GNSS_MODE, /* | | X | X | MBG_GNSS_MODE_{SETTINGS|INFO}, GNSS operation mode */ + GPS_GLNS_ALM = 0x200, ///< (rw-) ** preliminary ** //##++ + GPS_GNSS_SAT_INFO, ///< (r--) ::GNSS_SAT_INFO, Glonass-only sat. info (deprecated by ::GPS_GNSS_SAT_INFO_IDX) + GPS_GNSS_MODE, ///< (rw-) ::MBG_GNSS_MODE_SETTINGS/::MBG_GNSS_MODE_INFO}, GNSS operation mode + // Warning: + // The next numbers in range 0x200 are reserved /* Misc data */ - GPS_IP4_SETTINGS = 0x800, /* | X | X | IP4_SETTINGS, cfg of optional LAN interface */ - GPS_LAN_IF_INFO, /* | X | | LAN_IF_INFO, LAN interface info */ + GPS_IP4_SETTINGS = 0x800, ///< (rw-) ::IP4_SETTINGS, only if ::GPS_HAS_LAN_IP4 + GPS_LAN_IF_INFO, ///< (r--) ::LAN_IF_INFO, only if ::GPS_HAS_LAN_IP4 + GPS_IP4_STATE, ///< (r--) ::IP4_SETTINGS, only if ::GPS_HAS_LAN_IP4 + + /* misc data (SCU) */ + GPS_SCU_STAT = 0x820, ///< (rwa) ::SCU_STAT_SETTINGS/::SCU_STAT_INFO, SCU board control, only if ::GPS_MODEL_IS_SCU - GPS_CRYPTED_PACKET = 0x880, /* | X | X | X | encrypted binary packet */ - GPS_CRYPTED_RAW_PACKET, /* | X | X | X | encrypted binary raw packet */ + GPS_CRYPTED_PACKET = 0x880, ///< (rwa) encrypted binary packet + GPS_CRYPTED_RAW_PACKET, ///< (rwa) encrypted binary raw packet + GPS_XBP_PACKET, ///< (rwa) eXtended Binary Packet, only if ::GPS_HAS_XBP, see @ref group_xbp - GPS_SECU_INFO = 0x900, /* | | X | | encryption method for LAN interface */ - GPS_SECU_SETTINGS, /* | | X | X | reserved for public key LAN interface */ - GPS_SECU_PUBLIC_KEY, /* | | | | settings and password for LAN interface */ + GPS_SECU_INFO = 0x900, ///< (r--) encryption method for LAN interface + GPS_SECU_SETTINGS, ///< (rw-) reserved for public key LAN interface + GPS_SECU_PUBLIC_KEY, ///< (---) settings and password for LAN interface /* PZF data */ - PZF_PCPS_TIME = 0xA00, /* | | X | X | PCPS_TIME, date/time/status */ - PZF_TR_DISTANCE, /* | | X | X | TR_DISTANCE, dist. from transmitter [km] */ - PZF_TZCODE, /* | | X | X | TZCODE, time zone code */ - PZF_CORR_INFO /* | | X | | CORR_INFO, correlation info */ + PZF_PCPS_TIME = 0xA00, ///< (rw-) ::PCPS_TIME, date/time/status, only if ::GPS_MODEL_IS_DCF_PZF + PZF_TR_DISTANCE, ///< (rw-) ::TR_DISTANCE, dist. from transmitter [km], only if ::GPS_MODEL_IS_DCF_PZF + PZF_TZCODE, ///< (rw-) ::TZCODE, time zone code, only if ::GPS_MODEL_IS_DCF_PZF + PZF_CORR_INFO ///< (r--) ::CORR_INFO, correlation info, only if ::GPS_MODEL_IS_DCF_PZF }; -/* - * Caution: If GPS_ALM, GPS_EPH or a code named ..._IDX is sent to retrieve - * some data from a device then an uint16_t parameter must be also supplied - * in order to specify the index number of the data set to be returned. - * The valid index range depends on the command code. - * - * For GPS_ALM and GPS_EPH the index is the SV number which may be 0 or - * MIN_SVNO to MAX_SVNO. If the number is 0, ALL almanacs (32) are returned. - */ -typedef struct -{ - GPS_CMD cmd_code; - const char *cmd_name; -} GPS_CMD_NAME_TABLE_ENTRY; - -#define GPS_CMD_NAME_TABLE_ENTRIES \ -{ \ - { GPS_AUTO_ON, "GPS_AUTO_ON" }, \ - { GPS_AUTO_OFF, "GPS_AUTO_OFF" }, \ - { GPS_SW_REV, "GPS_SW_REV" }, \ - { GPS_BVAR_STAT, "GPS_BVAR_STAT" }, \ - { GPS_TIME, "GPS_TIME" }, \ - { GPS_POS_XYZ, "GPS_POS_XYZ" }, \ - { GPS_POS_LLA, "GPS_POS_LLA" }, \ - { GPS_TZDL, "GPS_TZDL" }, \ - { GPS_PORT_PARM, "GPS_PORT_PARM" }, \ - { GPS_SYNTH, "GPS_SYNTH" }, \ - { GPS_ANT_INFO, "GPS_ANT_INFO" }, \ - { GPS_UCAP, "GPS_UCAP" }, \ - { GPS_ENABLE_FLAGS, "GPS_ENABLE_FLAGS" }, \ - { GPS_STAT_INFO, "GPS_STAT_INFO" }, \ - { GPS_SWITCH_PARMS, "GPS_SWITCH_PARMS" }, \ - { GPS_STRING_PARMS, "GPS_STRING_PARMS" }, \ - { GPS_ANT_CABLE_LENGTH, "GPS_ANT_CABLE_LENGTH" }, \ - { GPS_SYNC_OUTAGE_DELAY, "GPS_SYNC_OUTAGE_DELAY" }, \ - { GPS_PULSE_INFO, "GPS_PULSE_INFO" }, \ - { GPS_OPT_FEATURES, "GPS_OPT_FEATURES" }, \ - { GPS_IRIG_TX_SETTINGS, "GPS_IRIG_TX_SETTINGS" }, \ - { GPS_RECEIVER_INFO, "GPS_RECEIVER_INFO" }, \ - { GPS_STR_TYPE_INFO_IDX, "GPS_STR_TYPE_INFO_IDX" }, \ - { GPS_PORT_INFO_IDX, "GPS_PORT_INFO_IDX" }, \ - { GPS_PORT_SETTINGS_IDX, "GPS_PORT_SETTINGS_IDX" }, \ - { GPS_POUT_INFO_IDX, "GPS_POUT_INFO_IDX" }, \ - { GPS_POUT_SETTINGS_IDX, "GPS_POUT_SETTINGS_IDX" }, \ - { GPS_IRIG_TX_INFO, "GPS_IRIG_TX_INFO" }, \ - { GPS_MULTI_REF_SETTINGS, "GPS_MULTI_REF_SETTINGS" }, \ - { GPS_MULTI_REF_INFO, "GPS_MULTI_REF_INFO" }, \ - { GPS_ROM_CSUM, "GPS_ROM_CSUM" }, \ - { GPS_MULTI_REF_STATUS, "GPS_MULTI_REF_STATUS" }, \ - { GPS_RCV_TIMEOUT, "GPS_RCV_TIMEOUT" }, \ - { GPS_IGNORE_LOCK, "GPS_IGNORE_LOCK" }, \ - { GPS_IRIG_RX_SETTINGS, "GPS_IRIG_RX_SETTINGS" }, \ - { GPS_IRIG_RX_INFO, "GPS_IRIG_RX_INFO" }, \ - { GPS_REF_OFFS, "GPS_REF_OFFS" }, \ - { GPS_DEBUG_STATUS, "GPS_DEBUG_STATUS" }, \ - { GPS_XMR_SETTINGS_IDX, "GPS_XMR_SETTINGS_IDX" }, \ - { GPS_XMR_INFO_IDX, "GPS_XMR_INFO_IDX" }, \ - { GPS_XMR_STATUS_IDX, "GPS_XMR_STATUS_IDX" }, \ - { GPS_OPT_SETTINGS, "GPS_OPT_SETTINGS" }, \ - { GPS_OPT_INFO, "GPS_OPT_INFO" }, \ - { GPS_CLR_UCAP_BUFF, "GPS_CLR_UCAP_BUFF" }, \ - { GPS_TIME_SCALE, "GPS_TIME_SCALE" }, \ - { GPS_NAV_ENG_SETTINGS, "GPS_NAV_ENG_SETTINGS" }, \ - { GPS_RAW_IRIG_DATA, "GPS_RAW_IRIG_DATA" }, \ - \ - /* GPS data */ \ - { GPS_CFGH, "GPS_CFGH" }, \ - { GPS_ALM, "GPS_ALM" }, \ - { GPS_EPH, "GPS_EPH" }, \ - { GPS_UTC, "GPS_UTC" }, \ - { GPS_IONO, "GPS_IONO" }, \ - { GPS_ASCII_MSG, "GPS_ASCII_MSG" }, \ - \ - /* Glonass data */ \ - { GPS_GLNS_ALM, "GPS_GLNS_ALM" }, \ - { GPS_GNSS_SAT_INFO, "GPS_GNSS_SAT_INFO" }, \ - { GPS_GNSS_MODE, "GPS_GNSS_MODE" }, \ - \ - /* Misc data */ \ - { GPS_IP4_SETTINGS, "GPS_IP4_SETTINGS" }, \ - { GPS_LAN_IF_INFO, "GPS_LAN_IF_INFO" }, \ - \ - { GPS_CRYPTED_PACKET, "GPS_CRYPTED_PACKET" }, \ - { GPS_CRYPTED_RAW_PACKET, "GPS_CRYPTED_RAW_PACKET" }, \ - \ - { GPS_SECU_INFO, "GPS_SECU_INFO" }, \ - { GPS_SECU_SETTINGS, "GPS_SECU_SETTINGS" }, \ - { GPS_SECU_PUBLIC_KEY, "GPS_SECU_PUBLIC_KEY" }, \ - \ - /* PZF data */ \ - { PZF_PCPS_TIME, "PZF_PCPS_TIME" }, \ - { PZF_TR_DISTANCE, "PZF_TR_DISTANCE" }, \ - { PZF_TZCODE, "PZF_TZCODE" }, \ - { PZF_CORR_INFO, "PZF_CORR_INFO" }, \ - { 0, NULL } \ +#if !defined( MBG_TGT_DOS ) + +/** + * @brief An initializer for a table of code/name entries of ::GPS_CMD_CODES + * + * This can e.g. be assigned to an array of ::MBG_CODE_NAME_TABLE_ENTRY elements + * and may be helpful when debugging. + * + * @see ::GPS_CMD_CODES + */ +#define GPS_CMD_CODES_TABLE \ +{ \ + _mbg_cn_table_entry( GPS_WILDCARD ), \ + _mbg_cn_table_entry( GPS_AUTO_ON ), \ + _mbg_cn_table_entry( GPS_AUTO_OFF ), \ + _mbg_cn_table_entry( GPS_SW_REV ), \ + _mbg_cn_table_entry( GPS_BVAR_STAT ), \ + _mbg_cn_table_entry( GPS_TIME ), \ + _mbg_cn_table_entry( GPS_POS_XYZ ), \ + _mbg_cn_table_entry( GPS_POS_LLA ), \ + _mbg_cn_table_entry( GPS_TZDL ), \ + _mbg_cn_table_entry( GPS_PORT_PARM ), \ + _mbg_cn_table_entry( GPS_SYNTH ), \ + _mbg_cn_table_entry( GPS_ANT_INFO ), \ + _mbg_cn_table_entry( GPS_UCAP ), \ + _mbg_cn_table_entry( GPS_ENABLE_FLAGS ), \ + _mbg_cn_table_entry( GPS_STAT_INFO ), \ + _mbg_cn_table_entry( GPS_SWITCH_PARMS ), \ + _mbg_cn_table_entry( GPS_STRING_PARMS ), \ + _mbg_cn_table_entry( GPS_ANT_CABLE_LENGTH ), \ + _mbg_cn_table_entry( GPS_SYNC_OUTAGE_DELAY ), \ + _mbg_cn_table_entry( GPS_PULSE_INFO ), \ + _mbg_cn_table_entry( GPS_OPT_FEATURES ), \ + _mbg_cn_table_entry( GPS_IRIG_TX_SETTINGS ), \ + _mbg_cn_table_entry( GPS_RECEIVER_INFO ), \ + _mbg_cn_table_entry( GPS_STR_TYPE_INFO_IDX ), \ + _mbg_cn_table_entry( GPS_PORT_INFO_IDX ), \ + _mbg_cn_table_entry( GPS_PORT_SETTINGS_IDX ), \ + _mbg_cn_table_entry( GPS_POUT_INFO_IDX ), \ + _mbg_cn_table_entry( GPS_POUT_SETTINGS_IDX ), \ + _mbg_cn_table_entry( GPS_IRIG_TX_INFO ), \ + _mbg_cn_table_entry( GPS_MULTI_REF_SETTINGS ), \ + _mbg_cn_table_entry( GPS_MULTI_REF_INFO ), \ + _mbg_cn_table_entry( GPS_ROM_CSUM ), \ + _mbg_cn_table_entry( GPS_MULTI_REF_STATUS ), \ + _mbg_cn_table_entry( GPS_RCV_TIMEOUT ), \ + _mbg_cn_table_entry( GPS_IGNORE_LOCK ), \ + _mbg_cn_table_entry( GPS_IRIG_RX_SETTINGS ), \ + _mbg_cn_table_entry( GPS_IRIG_RX_INFO ), \ + _mbg_cn_table_entry( GPS_REF_OFFS ), \ + _mbg_cn_table_entry( GPS_DEBUG_STATUS ), \ + _mbg_cn_table_entry( GPS_XMR_SETTINGS_IDX ), \ + _mbg_cn_table_entry( GPS_XMR_INFO_IDX ), \ + _mbg_cn_table_entry( GPS_XMR_STATUS_IDX ), \ + _mbg_cn_table_entry( GPS_OPT_SETTINGS ), \ + _mbg_cn_table_entry( GPS_OPT_INFO ), \ + _mbg_cn_table_entry( GPS_CLR_UCAP_BUFF ), \ + _mbg_cn_table_entry( GPS_TIME_SCALE ), \ + _mbg_cn_table_entry( GPS_NAV_ENG_SETTINGS ), \ + _mbg_cn_table_entry( GPS_RAW_IRIG_DATA ), \ + _mbg_cn_table_entry( GPS_GPIO_CFG_LIMITS ), \ + _mbg_cn_table_entry( GPS_GPIO_INFO_IDX ), \ + _mbg_cn_table_entry( GPS_GPIO_SETTINGS_IDX ), \ + _mbg_cn_table_entry( GPS_XMR_INSTANCES ), \ + _mbg_cn_table_entry( GPS_CLR_EVT_LOG ), \ + _mbg_cn_table_entry( GPS_NUM_EVT_LOG_ENTRIES ), \ + _mbg_cn_table_entry( GPS_FIRST_EVT_LOG_ENTRY ), \ + _mbg_cn_table_entry( GPS_NEXT_EVT_LOG_ENTRY ), \ + _mbg_cn_table_entry( GPS_LNO_STATUS ), \ + _mbg_cn_table_entry( GPS_IMS_STATE ), \ + _mbg_cn_table_entry( GPS_IMS_SENSOR_STATE_IDX ), \ + _mbg_cn_table_entry( GPS_XMR_HOLDOVER_INTV ), \ + _mbg_cn_table_entry( GPS_HAVEQUICK_RX_SETTINGS ), \ + _mbg_cn_table_entry( GPS_HAVEQUICK_RX_INFO ), \ + _mbg_cn_table_entry( GPS_HAVEQUICK_TX_SETTINGS ), \ + _mbg_cn_table_entry( GPS_HAVEQUICK_TX_INFO ), \ + _mbg_cn_table_entry( GPS_PTP_CFG ), \ + _mbg_cn_table_entry( GPS_PTP_STATE ), \ + _mbg_cn_table_entry( GPS_PTP_UC_MASTER_CFG_LIMITS ), \ + _mbg_cn_table_entry( GPS_PTP_UC_MASTER_CFG ), \ + _mbg_cn_table_entry( GPS_NTP_GLB_CFG ), \ + _mbg_cn_table_entry( GPS_NTP_CLNT_MODE_CFG ), \ + _mbg_cn_table_entry( GPS_NTP_SRV_MODE_CFG ), \ + _mbg_cn_table_entry( GPS_NTP_PEER_SETTINGS_IDX ), \ + _mbg_cn_table_entry( GPS_NTP_SYS_STATE ), \ + _mbg_cn_table_entry( GPS_NTP_PEER_STATE_IDX ), \ + _mbg_cn_table_entry( GPS_SHS ), \ + _mbg_cn_table_entry( GPS_SHS_STATUS ), \ + _mbg_cn_table_entry( GPS_NET_GLB_CFG ), \ + _mbg_cn_table_entry( GPS_NET_DNS_SRVR ), \ + _mbg_cn_table_entry( GPS_NET_DNS_SRCH_DOM ), \ + _mbg_cn_table_entry( GPS_NET_STAT_DNS_SRVR ), \ + _mbg_cn_table_entry( GPS_NET_STAT_DNS_SRCH_DOM ), \ + _mbg_cn_table_entry( GPS_GNSS_SAT_INFO_IDX ), \ + _mbg_cn_table_entry( GPS_XMR_HOLDOVER_ELAPSED ), \ + _mbg_cn_table_entry( GPS_GPIO_STATUS_IDX ), \ + _mbg_cn_table_entry( GPS_XMR_HOLDOVER_STATUS ), \ + _mbg_cn_table_entry( GPS_XBP_LIMITS ), \ + _mbg_cn_table_entry( GPS_XBP_NODE_LIMITS ), \ + _mbg_cn_table_entry( GPS_XBP_NODE_INFO_IDX ), \ + _mbg_cn_table_entry( GPS_FDM_OUTPUT_STATE_IDX ), \ + _mbg_cn_table_entry( GPS_FDM_OUTPUT_SETTINGS_IDX ), \ + _mbg_cn_table_entry( GPS_FDM_OUTPUT_INFO_IDX ), \ + _mbg_cn_table_entry( GPS_FDM_LIMITS ), \ + _mbg_cn_table_entry( GPS_FDM_STATE ), \ + _mbg_cn_table_entry( GPS_FDM_SETTINGS ), \ + _mbg_cn_table_entry( GPS_FDM_INFO ), \ + _mbg_cn_table_entry( GPS_XMR_EXT_SRC_INFO_IDX ), \ + \ + /* GPS data */ \ + _mbg_cn_table_entry( GPS_CFGH ), \ + _mbg_cn_table_entry( GPS_ALM ), \ + _mbg_cn_table_entry( GPS_EPH ), \ + _mbg_cn_table_entry( GPS_UTC ), \ + _mbg_cn_table_entry( GPS_IONO ), \ + _mbg_cn_table_entry( GPS_ASCII_MSG ), \ + \ + /* Glonass data */ \ + _mbg_cn_table_entry( GPS_GLNS_ALM ), \ + _mbg_cn_table_entry( GPS_GNSS_SAT_INFO ), \ + _mbg_cn_table_entry( GPS_GNSS_MODE ), \ + \ + /* Misc data */ \ + _mbg_cn_table_entry( GPS_IP4_SETTINGS ), \ + _mbg_cn_table_entry( GPS_LAN_IF_INFO ), \ + _mbg_cn_table_entry( GPS_IP4_STATE ), \ + \ + /* misc data (SCU) */ \ + _mbg_cn_table_entry( GPS_SCU_STAT ), \ + \ + _mbg_cn_table_entry( GPS_CRYPTED_PACKET ), \ + _mbg_cn_table_entry( GPS_CRYPTED_RAW_PACKET ), \ + _mbg_cn_table_entry( GPS_XBP_PACKET ), \ + \ + _mbg_cn_table_entry( GPS_SECU_INFO ), \ + _mbg_cn_table_entry( GPS_SECU_SETTINGS ), \ + _mbg_cn_table_entry( GPS_SECU_PUBLIC_KEY ), \ + \ + /* PZF data */ \ + _mbg_cn_table_entry( PZF_PCPS_TIME ), \ + _mbg_cn_table_entry( PZF_TR_DISTANCE ), \ + _mbg_cn_table_entry( PZF_TZCODE ), \ + _mbg_cn_table_entry( PZF_CORR_INFO ), \ + _mbg_cn_table_end() \ } +#endif // !defined( MBG_TGT_DOS ) -/* A structure holding the number of a SV and the SV's almanac. */ +/** + * @brief An SV number plus the SV's almanac data + */ typedef struct { SVNO svno; @@ -536,9 +772,9 @@ typedef struct } SV_ALM; - -/* A structure holding the number of a SV and the SV's ephemeris. */ - +/** + * @brief An SV number plus the SV's ephemeris data + */ typedef struct { SVNO svno; @@ -549,37 +785,63 @@ typedef struct #if _USE_PCPSDEFS -/* Attention: this differs from PCPS_TZCODE defined in pcpsdefs.h */ +/** + * @brief Type of variable to hold a TZ code + * + * This is used with the binary protocol but differs from ::PCPS_TZCODE + * which is used with the PCI interface. + * + * @see ::PCPS_TZCODE + * @see ::TZCODE_UNION + */ typedef uint16_t TZCODE; -#endif +#define _mbg_swab_tzcode( _p ) \ + _mbg_swab16( _p ); + + +/** + * @brief A union holding different types of a TZ code + * + * This is used with the binary protocol but differs from ::PCPS_TZCODE + * which is used with the PCI interface. + * + * @see ::TZCODE + * @see ::PCPS_TZCODE + */ +typedef union +{ + TZCODE ser; ///< code retrieved via serial binary protocol + PCPS_TZCODE pci; ///< code retrieved via PCI bus + +} TZCODE_UNION; +#endif -/* The message header */ +/** + * @brief The header of a binary message. + */ typedef struct { - GPS_CMD cmd; - uint16_t len; - CSUM data_csum; - CSUM hdr_csum; -} MSG_HDR; + GPS_CMD cmd; ///< see ::GPS_CMD_CODES and ::GPS_CMD_CTRL_CODES + uint16_t len; ///< length of the data portion appended after the header + CSUM data_csum; ///< checksum of the data portion appended after the header + CSUM hdr_csum; ///< checksum of the preceding header bytes +} MSG_HDR; -/* A union combining all kinds of parameters to be read from or written */ -/* to the GPS receiver. The size of the union corresponds to the maximum */ -/* size of the data part of a message. */ +/** + * @brief A union of all data types used with the binary protocol. + */ typedef union { - /* common types */ uint16_t us; double d; SVNO svno; - - /* user data */ SW_REV sw_rev; BVAR_STAT bvar_stat; TTM ttm; @@ -623,8 +885,59 @@ typedef union GNSS_SAT_INFO gnss_sat_info; //##++++++ MBG_GNSS_MODE_INFO gnss_mode_info; //##++++++ MBG_GNSS_MODE_SETTINGS gnss_mode_settings; //##++++++ + MBG_GPIO_CFG_LIMITS gpio_cfg_limits; + MBG_GPIO_INFO_IDX gpio_info_idx; + MBG_GPIO_SETTINGS_IDX gpio_settings_idx; + XMULTI_REF_INSTANCES xmulti_ref_instances; + MBG_NUM_EVT_LOG_ENTRIES num_evt_log_entries; + MBG_EVT_LOG_ENTRY evt_log_entry; + LNO_STATE lno_state; + MBG_IMS_STATE ims_state; + MBG_IMS_SENSOR_STATE_IDX ims_sensor_state_idx; + XMR_HOLDOVER_INTV xmr_holdover_intv; + HAVEQUICK_SETTINGS havequick_settings; + HAVEQUICK_INFO havequick_info; + PTP_CFG_INFO ptp_cfg_info; + PTP_CFG_SETTINGS ptp_cfg_settings; + PTP_STATE ptp_state; + PTP_UC_MASTER_CFG_LIMITS ptp_uc_master_cfg_limits; + PTP_UC_MASTER_INFO_IDX ptp_uc_master_info_idx; + PTP_UC_MASTER_SETTINGS_IDX ptp_uc_master_settings_idx; + NTP_GLB_INFO ntp_glb_info; + NTP_GLB_SETTINGS ntp_glb_settings; + NTP_CLNT_MODE_INFO ntp_clnt_mode_info; + NTP_CLNT_MODE_SETTINGS ntp_clnt_mode_settings; + #if defined( DEBUG ) + NTP_SRV_MODE_INFO ntp_srv_mode_info; + NTP_SRV_MODE_INFO ntp_srv_mode_settings; + #endif + NTP_PEER_SETTINGS_IDX ntp_peer_settings_idx; + NTP_SYS_STATE ntp_sys_state; + NTP_PEER_STATE_IDX ntp_peer_state_idx; + SHS_INFO shs_info; + SHS_SETTINGS shs_settings; + SHS_STATUS shs_status; + MBG_NET_GLB_CFG_INFO net_glb_cfg_info; + MBG_NET_GLB_CFG_SETTINGS net_glb_cfg_settings; + MBG_IP_ADDR_IDX ip_addr_idx; + MBG_NET_NAME_IDX net_name_idx; + GNSS_SAT_INFO_IDX gnss_sat_info_idx; + MBG_GPIO_STATUS_IDX gpio_status_idx; + XMR_HOLDOVER_STATUS xmr_holdover_status; + XBP_LIMITS xbp_limits; + XBP_NODE_LIMITS xbp_node_limits; + XBP_NODE_INFO_IDX xbp_node_info_idx; + MBG_IMS_FDM_OUTPUT_STATE_IDX fdm_output_state_idx; + MBG_IMS_FDM_OUTPUT_SETTINGS_IDX fdm_output_settings_idx; + MBG_IMS_FDM_OUTPUT_INFO_IDX fdm_output_info_idx; + MBG_IMS_FDM_LIMITS fdm_limits; + MBG_IMS_FDM_STATE fdm_state; + MBG_IMS_FDM_SETTINGS fdm_settings; + MBG_IMS_FDM_INFO fdm_info; + XMR_EXT_SRC_INFO_IDX xmr_ext_src_info_idx; + + //##++ PTP_POWER_PROFILE_CFG ptp_power_profile_cfg; // no cmd code, yet. - /* GPS system data */ CFGH cfgh; SV_ALM sv_alm; SV_EPH sv_eph; @@ -632,10 +945,12 @@ typedef union IONO iono; ASCII_MSG ascii_msg; - /* Misc data */ IP4_SETTINGS ip4_settings; LAN_IF_INFO lan_if_info; + SCU_STAT_INFO scu_stat_info; + SCU_STAT_SETTINGS scu_stat_settings; + #if _USE_PCPSDEFS PCPS_TIME pcps_time; TR_DISTANCE tr_distance; @@ -654,6 +969,7 @@ typedef union } MSG_DATA; +/// The maximum number of bytes required for a ::MSG_DATA buffer #ifndef MAX_MSG_DATA_SIZE #ifndef ADD_MSG_DATA_SIZE #if _USE_ENCRYPTION @@ -667,10 +983,66 @@ typedef union #endif +/** + * @brief A union of all data types used with the binary protocol, or array of bytes. + * + * This union can be used to implement a buffer which can hold either a known data structure + * or an array of bytes which can be read from or written to a device. + */ +typedef union +{ + MSG_DATA msg_data; ///< union of known structures + uint8_t bytes[MAX_MSG_DATA_SIZE]; + +} STD_MSG_DATA_BUFF; + -/* The structures below define parts of a binary message packet which */ -/* are used with encrypted messages, */ +/** + * @brief The format of a standard binary message. + */ +typedef struct +{ + MSG_HDR hdr; ///< Message header containing the command code and length of the data portion + STD_MSG_DATA_BUFF data_buf; ///< Data portion using the number of bytes specified in the header + +} MBG_STD_MSG; + + + +/** + * @brief The data portion of an XBP message. + */ +typedef struct +{ + XBP_ADDR xbp_addr; ///< XBP address of the transmitter or receiver + MBG_STD_MSG std_msg; ///< Encapsulated standard binary message + +} XBP_MSG_DATA; + + + +/** + * @brief A message header for the eXtended Binary Protocol (XBP) + * + * The data portion of such message is a standard binary message. + * The ::MSG_HDR::len field in ::XBP_MSG_HDR::xbp_hdr must contain + * the number of bytes following the xbp_hdr field, i.e. the length + * of the whole encapsulated binary message plus the size of the + * xbp_addr field. + */ +typedef struct +{ + MSG_HDR xbp_hdr; + XBP_ADDR xpb_addr; + +} XBP_MSG_HDR; + + + +/** + * @brief A message prefix used for encrypted messages + */ typedef struct { MSG_HDR hdr; @@ -678,7 +1050,7 @@ typedef struct #if _USE_ENCRYPTION uint8_t aes_initvect[AES_BLOCK_SIZE]; #else - // In this case this structure is just a dummy to avoid + // In this case this structure is just a dummy to avoid // a compiler error with the function prototypes. #endif @@ -688,21 +1060,13 @@ typedef struct #if _USE_ENCRYPTION +/** + * @brief A message data block used for encrypted messages + */ typedef struct { uint8_t aes_initvect[AES_BLOCK_SIZE]; - - struct - { - MSG_HDR enc_hdr; - - union - { - uint8_t bytes[MAX_MSG_DATA_SIZE]; - MSG_DATA msg_data; - } enc_msg; - - } enc_msg; + MBG_STD_MSG std_msg; } CRYPT_MSG_DATA; @@ -710,21 +1074,25 @@ typedef struct -/* A buffer holding a message header plus data part of a message */ -/* For portability reasons the CMSG_BUFF structure defined below */ -/* should be preferred for coding. */ - +/** + * @brief A buffer for a message header plus data part + * + * The data part has to be interpreted depending on the command code + * in the message header field, hdr. + */ typedef struct { - MSG_HDR hdr; + MSG_HDR hdr; ///< The message header union { - uint8_t bytes[MAX_MSG_DATA_SIZE]; - MSG_DATA msg_data; + uint8_t bytes[MAX_MSG_DATA_SIZE]; ///< Data part as a number of bytes + MSG_DATA msg_data; ///< Standard message data structures + MBG_STD_MSG std_msg; ///< Encapsulated standard message + XBP_MSG_DATA xbp_msg_data; ///< XBP address field plus encapsulated standard message #if _USE_ENCRYPTION - CRYPT_MSG_DATA crypt_msg_data; + CRYPT_MSG_DATA crypt_msg_data; ///< Encryption data plus encrypted standard message #endif } u; @@ -733,30 +1101,34 @@ typedef struct -/* The structure below is used to control the reception of messages */ - +/** + * @brief A structure used to control the reception of binary messages + */ typedef struct { - MBG_MSG_BUFF *pmb; /* points to unencrypted message buffer */ - int buf_size; /* size of buffer, including header */ - uint8_t *cur; /* points to current pos inside receive buffer */ - int cnt; /* the number of bytes to receive */ - ulong flags; /* flags if header already completed */ + MBG_MSG_BUFF *pmb; ///< points to unencrypted message buffer + int buf_size; ///< size of buffer, including header + uint8_t *cur; ///< points to current pos inside receive buffer + int cnt; ///< the number of bytes to be received + ulong flags; ///< flags if header already completed, etc., see ::MBG_MSG_RCV_CTL_MASKS #if _USE_RCV_TSTAMP - MBG_TMO_TIME tstamp; + MBG_TMO_TIME tstamp; ///< time when the first byte of the packet was received #endif #if _USE_CHK_TSTR - void (*chk_tstr_fnc)( char c, TIMESTR_CHECK *arg ); /* optional handler for normal, non-protocol data */ - TIMESTR_CHECK *chk_tstr_arg; + CHK_TSTR_FNC chk_tstr_fnc; ///< optional handler for normal, non-protocol data + CHK_TSTR_ARG *chk_tstr_arg; ///< arguments for the non-protocol data handler #endif } MBG_MSG_RCV_CTL; -/* The flag bits below and the corresponding bit masks are used - for MBG_MSG_RCV_CTL::flags: */ -enum +/** + * @brief Receive control bits used to define ::MBG_MSG_RCV_CTL_MASKS + * + * @see ::MBG_MSG_RCV_CTL_MASKS + */ +enum MBG_MSG_RCV_CTL_BITS { MBG_MSG_RCV_CTL_BIT_RCVD_HDR, MBG_MSG_RCV_CTL_BIT_MSG_TOO_LONG, @@ -766,32 +1138,50 @@ enum N_MBG_MSG_RCV_CTL_BIT }; -#define MBG_MSG_RCV_CTL_RCVD_HDR ( 1UL << MBG_MSG_RCV_CTL_BIT_RCVD_HDR ) -#define MBG_MSG_RCV_CTL_MSG_TOO_LONG ( 1UL << MBG_MSG_RCV_CTL_BIT_MSG_TOO_LONG ) -#define MBG_MSG_RCV_CTL_OVERFLOW ( 1UL << MBG_MSG_RCV_CTL_BIT_OVERFLOW ) -#define MBG_MSG_RCV_CTL_DECRYPT_ERR ( 1UL << MBG_MSG_RCV_CTL_BIT_DECRYPT_ERR ) -#define MBG_MSG_RCV_CTL_DECRYPTED ( 1UL << MBG_MSG_RCV_CTL_BIT_DECRYPTED ) +/** + * @brief Receive control bit masks + * + * Used with ::MBG_MSG_RCV_CTL::flags + * + * @see ::MBG_MSG_RCV_CTL_BITS + */ +enum MBG_MSG_RCV_CTL_MASKS +{ + MBG_MSG_RCV_CTL_RCVD_HDR = ( 1UL << MBG_MSG_RCV_CTL_BIT_RCVD_HDR ), ///< see ::MBG_MSG_RCV_CTL_BIT_RCVD_HDR + MBG_MSG_RCV_CTL_MSG_TOO_LONG = ( 1UL << MBG_MSG_RCV_CTL_BIT_MSG_TOO_LONG ), ///< see ::MBG_MSG_RCV_CTL_BIT_MSG_TOO_LONG + MBG_MSG_RCV_CTL_OVERFLOW = ( 1UL << MBG_MSG_RCV_CTL_BIT_OVERFLOW ), ///< see ::MBG_MSG_RCV_CTL_BIT_OVERFLOW + MBG_MSG_RCV_CTL_DECRYPT_ERR = ( 1UL << MBG_MSG_RCV_CTL_BIT_DECRYPT_ERR ), ///< see ::MBG_MSG_RCV_CTL_BIT_DECRYPT_ERR + MBG_MSG_RCV_CTL_DECRYPTED = ( 1UL << MBG_MSG_RCV_CTL_BIT_DECRYPTED ) ///< see ::MBG_MSG_RCV_CTL_BIT_DECRYPTED +}; + -typedef struct +/** + * @brief A structure used to control the transmission of binary messages + */ +typedef struct { - MBG_MSG_BUFF *pmb; - int buf_size; - int xfer_mode; + MBG_MSG_BUFF *pmb; ///< points to unencrypted message buffer + int buf_size; ///< size of buffer, including header + int xfer_mode; ///< transfer mode, see ::MBG_XFER_MODES #if _USE_MUTEX - MBG_MUTEX xmt_mutex; + MBG_MUTEX xmt_mutex; ///< mutex to serialize transmission #endif } MBG_MSG_XMT_CTL; -// codes used with MBG_MSG_CTL::xfer_mode: -enum +/** + * @brief Binary message transfer modes + * + * Used with ::MBG_MSG_XMT_CTL::xfer_mode + */ +enum MBG_XFER_MODES { - MBG_XFER_MODE_NORMAL, - MBG_XFER_MODE_ENCRYTED, + MBG_XFER_MODE_NORMAL, ///< normal, unencrypted transmission + MBG_XFER_MODE_ENCRYPTED, ///< encrypted transmission, usually over network N_MBG_XFER_MODE }; @@ -805,13 +1195,47 @@ enum #define LAN_XPT_PORT 10001 -#ifndef INVALID_SOCKET - #define INVALID_SOCKET -1 + +/** + * @brief A socket file descriptor type + */ +#if defined( MBG_TGT_WIN32 ) + typedef SOCKET MBG_SOCK_FD; // usually evaluates to (unsigned int), or (unsigned __int64) +#elif defined( MBG_TGT_POSIX ) + typedef int MBG_SOCK_FD; #endif + +/** + * @brief A value to mark an ::MBG_SOCK_FD as invalid + */ +#if defined( MBG_TGT_WIN32 ) + #define MBG_INVALID_SOCK_FD INVALID_SOCKET // usually evaluates to (SOCKET)(~0) since SOCKET is unsigned +#elif defined( MBG_TGT_POSIX ) + #define MBG_INVALID_SOCK_FD -1 +#endif + +#if defined( MBG_TGT_WIN32 ) + #define socklen_t int +#elif defined( MBG_TGT_POSIX ) + #define socklen_t socklen_t +#endif + + +/** + * @brief The return code of socket functions in case of error + */ +#if defined( MBG_TGT_WIN32 ) + #define MBG_SOCKET_ERR_RETVAL SOCKET_ERROR // usually evaluates to -1 +#elif defined( MBG_TGT_POSIX ) + #define MBG_SOCKET_ERR_RETVAL -1 +#endif + + + typedef struct { - int sockfd; + MBG_SOCK_FD sockfd; struct sockaddr_in addr; } SOCKET_IO_STATUS; @@ -819,27 +1243,50 @@ typedef struct #endif // _USE_SOCKET_IO -#if _USE_SERIAL_IO +#if _USE_SERIAL_IO_FTDI + +typedef struct +{ + FT_HANDLE port_handle; + +} FTDI_IO_STATUS; -#endif // _USE_SERIAL_IO +#endif // _USE_SERIAL_IO_FTDI -#if defined( _USE_PACK ) // set default alignment - #pragma pack() + +#if _USE_USB_DIRECT_IO + +typedef int MBG_USB_DIRECT_IO_FD; + +#if !defined (MBG_USB_DIRECT_IO_INVALID_FD) + #define MBG_USB_DIRECT_IO_INVALID_FD -1 #endif +#if !defined ( MBGEXTIO_RCV_TIMEOUT_USB_DIRECT_IO ) + #define MBGEXTIO_RCV_TIMEOUT_USB_DIRECT_IO 1000 // [ms] +#endif + +typedef struct +{ + MBG_USB_DIRECT_IO_FD usbdiofd; +}USB_DIRECT_IO_STATUS; -// For the next structure we can and should use native alignment: +#endif // _USE_USB_DIRECT_IO -typedef struct + + +/** + * @brief A generic message send and receive control structure + */ +typedef struct { MBG_MSG_RCV_CTL rcv; MBG_MSG_XMT_CTL xmt; int conn_type; - int io_error; - ulong msg_rcv_timeout; // binary message receive timeout [ms] - ulong char_rcv_timeout; // serial character receive timeout [ms] + ulong msg_rcv_timeout; ///< binary message receive timeout [ms] + ulong char_rcv_timeout; ///< serial character receive timeout [ms] #if _USE_ENCRYPTION uint8_t aes_initvect[AES_BLOCK_SIZE]; @@ -850,7 +1297,11 @@ typedef struct SECU_SETTINGS secu_settings; #endif - #if _USE_SERIAL_IO || _USE_SOCKET_IO + #if _USE_SERIAL_IO || \ + _USE_SERIAL_IO_FTDI || \ + _USE_SOCKET_IO || \ + _USE_USB_IO || \ + _USE_USB_DIRECT_IO union { #if _USE_SOCKET_IO @@ -860,18 +1311,36 @@ typedef struct #if _USE_SERIAL_IO SERIAL_IO_STATUS serio; #endif + + #if _USE_SERIAL_IO_FTDI + FTDI_IO_STATUS ftdiio; + #endif + + #if _USE_USB_IO + USB_IO_STATUS usbio; + #endif + + #if _USE_USB_DIRECT_IO + USB_DIRECT_IO_STATUS usbdio; + #endif } st; #endif } MBG_MSG_CTL; -// codes used with MBG_MSG_CTL::conn_type: - -enum +/** + * @brief Binary message connection types + * + * Used with ::MBG_MSG_CTL::conn_type + */ +enum MBG_CONN_TYPES { - MBG_CONN_TYPE_SERIAL, - MBG_CONN_TYPE_SOCKET, + MBG_CONN_TYPE_SERIAL, ///< connection via serial port + MBG_CONN_TYPE_SOCKET, ///< connection via network socket + MBG_CONN_TYPE_USB, ///< connection via direct USB + MBG_CONN_TYPE_SERIAL_FTDI, ///< connection via FTDI D2xx USB-To-Serial converter + MBG_CONN_TYPE_USB_DIRECT_IO, ///< connection via direct USB I/O operation N_MBG_CONN_TYPE }; @@ -886,19 +1355,160 @@ enum /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ - CSUM msg_csum_update( CSUM csum, uint8_t *p, int n ) ; - CSUM msg_csum( uint8_t *p, int n ) ; - CSUM msg_hdr_csum( MSG_HDR *pmh ) ; - int chk_hdr_csum( MSG_HDR *pmh ) ; - int chk_data_csum( MBG_MSG_BUFF *pmb ) ; + /** + * @brief Translate a FTDI API status code to one of the @ref MBG_ERROR_CODES + * + * @param[in] status A status code defined by the FTDI API interface + * + * @return One of the @ref MBG_RETURN_CODES + */ + int mbg_ftdi_ft_status_to_mbg( FT_STATUS status ) ; + + /** + * @brief Compute a simple binary checksum + * + * Compute a checksum about a number of bytes starting + * with a given initial value. + * + * @param[in] csum the initial value + * @param[in] p pointer to a buffer of data bytes + * @param[in] n the number of bytes in the buffer + * + * @return the computed checksum + */ + CSUM msg_csum_update( CSUM csum, const uint8_t *p, int n ) ; + + /** + * @brief Compute a checksum for a binary message + * + * @note This function differs from the checksum() function + * used to compute the checksum of battery-buffered variables. + * + * @param[in] p pointer to a buffer of data bytes + * @param[in] n the number of bytes in the buffer + * + * @return the computed checksum + */ + CSUM msg_csum( const uint8_t *p, int n ) ; + + /** + * @brief Compute the checksum of a binary message header + * + * @param[in] pmh pointer to a binary message header + * + * @return the computed checksum + */ + CSUM msg_hdr_csum( const MSG_HDR *pmh ) ; + + /** + * @brief Check if the header checksum of a binary message is valid + * + * @param[in] pmh pointer to a binary message header + * + * @return ::MBG_SUCCESS or ::MBG_ERR_HDR_CSUM + */ + int chk_hdr_csum( const MSG_HDR *pmh ) ; + + /** + * @brief Check if the data checksum of a binary message is valid + * + * @param[in] pmb pointer to a binary message buffer + * + * @return ::MBG_SUCCESS or ::MBG_ERR_DATA_CSUM + */ + int chk_data_csum( const MBG_MSG_BUFF *pmb ) ; + + /** + * @brief Encrypt a binary message + * + * In encryption mode the original packet is encrypted and put + * as data portion into an envelope package. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in,out] pcmp Pointer to encryption settings + * @param[in,out] pmb Pointer to a binary message buffer + * + * @return the number of bytes of the encrypted message, or one of the @ref MBG_ERROR_CODES + */ int encrypt_message( MBG_MSG_CTL *pmctl, CRYPT_MSG_PREFIX *pcmp, MBG_MSG_BUFF *pmb ) ; + + /** + * @brief Decrypt an encrypted binary message + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return One of the @ref MBG_RETURN_CODES + */ int decrypt_message( MBG_MSG_CTL *pmctl ) ; + + /** + * @brief Set communication channel to specified encryption mode + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] mode Encryption mode, usually ::MBG_XFER_MODE_ENCRYPTED + * @param[in] key The crypto key (password) to be used + */ void set_encryption_mode( MBG_MSG_CTL *pmctl, int mode, const char *key ) ; - int xmt_tbuff( MBG_MSG_CTL *pmctl ) ; - int xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) ; - int xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t us ) ; + + /** + * @brief Complete message header and transmit message + * + * Compute checksums and complete the message header, + * then transmit both header and data. The caller must + * have copied the data to be sent to the data field + * of the transmit buffer and have set up the cmd and + * len fields of the message header. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to XBP address specifier + * + * @return one of the @ref MBG_RETURN_CODES + */ + int xmt_tbuff( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr ) ; + + /** + * @brief Send a binary command message without parameters + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to XBP address specifier + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::xmt_cmd_us + */ + int xmt_cmd( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd ) ; + + /** + * @brief Send a binary command message with ushort ( 16 bit) parameter + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to XBP address specifier + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * @param[in] us The 16 bit message parameter (data) + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::xmt_cmd + */ + int xmt_cmd_us( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd, uint16_t us ) ; + + /** + * @brief Check an incoming data stream for a binary message + * + * Check the sequence of incoming characters for blocks of + * binary message data. Binary messages are saved in a buffer + * which is part of the ::MBG_MSG_RCV_CTL structure and the + * caller checks the return value to get the receive status. + * + * @param[in,out] prctl Pointer to a valid receive control structure + * @param[in] c A byte from the incoming data stream + * + * @return One of the ::TR_STATUS_CODES + */ int check_transfer( MBG_MSG_RCV_CTL *prctl, uint8_t c ) ; + /* ----- function prototypes end ----- */ #endif // _USE_GPSSERIO_FNC @@ -914,3 +1524,4 @@ enum #endif /* _GPSSERIO_H */ + diff --git a/mbglib/common/gpsutils.c b/mbglib/common/gpsutils.c index 225a03e..c5083ef 100644 --- a/mbglib/common/gpsutils.c +++ b/mbglib/common/gpsutils.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsutils.c 1.4.1.2 2004/11/09 14:42:36 martin REL_M $ + * $Id: gpsutils.c 1.9 2013/01/30 16:10:08 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,10 +10,18 @@ * * ----------------------------------------------------------------------- * $Log: gpsutils.c $ - * Revision 1.4.1.2 2004/11/09 14:42:36 martin - * Use C99 fixed-size types in swap_double(). - * Revision 1.4.1.1 2003/05/16 08:36:27 MARTIN - * Fixed sprint_dms() to work correctly under QNX. + * Revision 1.9 2013/01/30 16:10:08 martin + * Exclude some code from compiling by default, and + * thus don't require pcpslstr.h by default. + * Revision 1.8 2012/10/15 14:27:05Z martin + * Exclude sprint_fixed_freq() from build except for Borland C / Windows. + * Revision 1.7 2010/07/15 09:32:09 martin + * Use DEG character definition from pcpslstr.h. + * Revision 1.6 2004/12/28 11:21:26Z martin + * Omit trap if fixed_freq is 0. + * Use C99 fixed-size data types were required. + * Revision 1.5 2003/02/04 09:20:04Z MARTIN + * New functions sprint_alt(), sprint_fixed_freq(). * Revision 1.4 2003/01/31 13:45:19 MARTIN * sprint_pos_geo() returns N/A if position not valid. * Revision 1.3 2002/12/12 16:07:04 martin @@ -30,9 +38,17 @@ #include #undef _GPSUTILS +#if !defined( USE_SPRINTF ) + #define USE_SPRINTF 0 +#endif + +#if USE_SPRINTF + #include +#endif + #include #include - +#include #define _eos( _s ) ( &(_s)[strlen( _s )] ) @@ -155,13 +171,14 @@ void swap_pos_doubles( POS *posp ) +#if USE_SPRINTF + /*HDR*/ void sprint_dms( char *s, DMS *pdms, int prec ) { - sprintf( s, "%c %i%c%02i'%02.*f\"", + sprintf( s, "%c %i" DEG "%02i'%02.*f\"", pdms->prefix, pdms->deg, - C_DEGREE, pdms->min, prec, pdms->sec @@ -171,6 +188,15 @@ void sprint_dms( char *s, DMS *pdms, int prec ) +/*HDR*/ +void sprint_alt( char *s, double alt ) +{ + sprintf( s, "%.0fm", alt ); + +} /* sprint_dms */ + + + /*HDR*/ void sprint_pos_geo( char *s, POS *ppos, const char *sep, int prec ) { @@ -180,12 +206,111 @@ void sprint_pos_geo( char *s, POS *ppos, const char *sep, int prec ) strcat( s, sep ); sprint_dms( _eos( s ), &ppos->longitude, prec ); strcat( s, sep ); - sprintf( _eos( s ), "%.0fm", ppos->lla[ALT] ); + sprint_alt( _eos( s ), ppos->lla[ALT] ); } else strcpy( s, "N/A" ); } /* sprint_pos_geo */ +#endif + + + +#if defined( MBG_TGT_WIN32 ) && defined( __BORLANDC__ ) + +/*HDR*/ +void sprint_fixed_freq( char *s, FIXED_FREQ_INFO *p_ff ) +{ + double freq; + int range; + ushort unit; + ushort format; + + // Before re-calculating frequency, range is the base 10 exponent + // to the frequency value which is represented in kHz. + // After calculating range from real frequency, range is represented + // as follows: + // range display format divisor format index calculation + // -3 100mHz 1.000 [/1e-3] -3 % 3 = -3 + 3 = 0 % 3 = 0 + // -2 100mHz 10.00 [/1e-3] -2 % 3 = -2 + 3 = 1 % 3 = 1 + // -1 100mHz 100.0 [/1e-3] -1 % 3 = -1 + 3 = 2 % 3 = 2 + // 0 1Hz 1.000 [/1e0] 0 % 3 = 0 + 3 = 3 % 3 = 0 + // 1 10Hz 10.00 [/1e0] 1 % 3 = 1 + 3 = 1 % 3 = 1 + // 2 100Hz 100.0 [/1e0] 2 % 3 = 2 + 3 = 2 % 3 = 2 + // 3 1kHz 1.000 [/1e3] 3 % 3 = 0 + 3 = 3 % 3 = 0 + // 4 10kHz 10.00 [/1e3] 4 % 3 = 1 + 3 = 4 % 3 = 1 + // 5 100kHz 100.0 [/1e3] 5 % 3 = 2 + 3 = 5 % 3 = 2 + // 6 1MHz 1.000 [/1e6] 6 % 3 = 0 + 3 = 3 % 3 = 0 + // 7 10MHz 10.00 [/1e6] 7 % 3 = 1 + 3 = 4 % 3 = 1 + // 8 100MHz 100.0 [/1e6] 8 % 3 = 2 + 3 = 5 % 3 = 2 + + // format string for fp output + static const char *fmt_str[] = + { + "%4.3lf%s", + "%4.2lf%s", + "%4.1lf%s", + }; + + // Unit index and divisor are calculated as follows: + // range unit index calculation divisor calculation + // -3 mHz ( int )( ( -3 + 3 ) / 3 ) = 0 + // -2 mHz ( int )( ( -2 + 3 ) / 3 ) = 0 + // -1 mHz ( int )( ( -1 + 3 ) / 3 ) = 0 / 10e-3 = 10e( 3 * 0 - 3 ) + // 0 Hz ( int )( ( 0 + 3 ) / 3 ) = 1 + // 1 Hz ( int )( ( 1 + 3 ) / 3 ) = 1 + // 2 Hz ( int )( ( 2 + 3 ) / 3 ) = 1 / 1e0 = 10e( 3 * 1 - 3 ) + // 3 kHz ( int )( ( 3 + 3 ) / 3 ) = 2 + // 4 kHz ( int )( ( 4 + 3 ) / 3 ) = 2 + // 5 kHz ( int )( ( 5 + 3 ) / 3 ) = 2 / 10e3 = 10e( 3 * 2 - 3 ) + // 6 MHz ( int )( ( 6 + 3 ) / 3 ) = 3 + // 7 MHz ( int )( ( 7 + 3 ) / 3 ) = 3 + // 8 MHz ( int )( ( 8 + 3 ) / 3 ) = 3 / 10e6 =10e( 3 * 3 - 3 ) + + // unit string + static const char *unit_str[] = + { + "mHz", + "Hz", + "kHz", + "MHz" + }; + + + if ( p_ff->khz_val ) + { + // calculate frequency in Hz + freq = ( double ) p_ff->khz_val * pow( 10, ( p_ff->range + 3 ) ); + + // calculate decimal exponent + range = ( ( int ) log10( freq ) ); + + // check whether range is in the allowed range + // if so display frequency in broken format + if ( ( range >= -3 ) && ( range <= 8 ) ) + { + // calculate format index ( see above ) + format = ( ( ( range % 3 ) + 3 ) % 3 ); + + // calculate unit index + unit = ( ushort )( range + 3 ) / 3; + + // calculate display value + freq = freq / pow( 10, ( ( 3 * unit ) - 3 ) ); + sprintf( s, fmt_str[format], freq, unit_str[unit] ); + return; + } + else + { + // out of range display fequency in Hz + sprintf( s, "%lfHz", freq ); + } + } + else + strcpy( s, "N/A" ); + +} /* sprint_fixed_freq */ +#endif // defined( MBG_TGT_WIN32 ) && defined( __BORLANDC__ ) diff --git a/mbglib/common/gpsutils.h b/mbglib/common/gpsutils.h index 5876ffa..fdac213 100644 --- a/mbglib/common/gpsutils.h +++ b/mbglib/common/gpsutils.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsutils.h 1.4.1.1 2003/05/15 09:40:25 martin REL_M $ + * $Id: gpsutils.h 1.7 2010/07/15 09:32:09 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,8 +10,12 @@ * * ----------------------------------------------------------------------- * $Log: gpsutils.h $ - * Revision 1.4.1.1 2003/05/15 09:40:25 martin - * Changed degree string/char for QNX. + * Revision 1.7 2010/07/15 09:32:09 martin + * Use DEG character definition from pcpslstr.h. + * Revision 1.6 2005/02/18 10:32:33Z martin + * Check more predefined macros to determine if compiling for Windows. + * Revision 1.5 2003/02/04 09:18:48Z MARTIN + * Updated function prototypes. * Revision 1.4 2002/12/12 16:08:11 martin * Definitions for degree character. * Requires mbggeo.h. @@ -41,17 +45,6 @@ /* Start of header body */ -#define ANSI_C_DEGREE '°' // single char -#define ANSI_S_DEGREE "°" // string - -#if defined( _Windows ) || defined( __linux ) || defined( __QNX__ ) - #define C_DEGREE ANSI_C_DEGREE - #define S_DEGREE ANSI_S_DEGREE -#else - #define C_DEGREE 'ø' - #define S_DEGREE "ø" -#endif - /* function prototypes: */ @@ -71,7 +64,9 @@ extern "C" { void swap_iono_doubles( IONO *ionop ) ; void swap_pos_doubles( POS *posp ) ; void sprint_dms( char *s, DMS *pdms, int prec ) ; + void sprint_alt( char *s, double alt ) ; void sprint_pos_geo( char *s, POS *ppos, const char *sep, int prec ) ; + void sprint_fixed_freq( char *s, FIXED_FREQ_INFO *p_ff ) ; /* ----- function prototypes end ----- */ diff --git a/mbglib/common/mbg_arch.h b/mbglib/common/mbg_arch.h new file mode 100644 index 0000000..00d8d5a --- /dev/null +++ b/mbglib/common/mbg_arch.h @@ -0,0 +1,181 @@ + +/************************************************************************** + * + * $Id: mbg_arch.h 1.5.1.1 2014/10/29 14:21:17 martin TEST $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions to support different computer hardware architectures. + * + * For a good summary of predefined macros which can be used to determine + * the build environment, the target environment, and architecture, see: + * http://sourceforge.net/p/predef/wiki/Home/ + * + * ----------------------------------------------------------------------- + * $Log: mbg_arch.h $ + * Revision 1.5.1.1 2014/10/29 14:21:17 martin + * Revision 1.5 2014/03/11 16:01:55 martin + * Added a comment. + * Revision 1.4 2012/10/02 18:32:00 martin + * Include words.h and, conditionally, stdlib.h. + * Use generic preprocessor symbol MBG_TGT_KERNEL. + * Revision 1.3 2009/06/12 13:12:37Z martin + * Fixed compiler warning. + * Revision 1.2 2009/03/19 15:14:15 martin + * Fixed byte swapping of doubles for SPARC architecture. + * Revision 1.1 2008/12/05 13:47:42 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBG_ARCH_H +#define _MBG_ARCH_H + +#include +#include + +#if !defined( MBG_TGT_KERNEL ) + #include +#endif + + +#if defined( MBG_ARCH_SPARC ) + #define MBG_ARCH_BIG_ENDIAN 1 +#endif + + +#if !defined( MBG_ARCH_BIG_ENDIAN ) + #define MBG_ARCH_LITTLE_ENDIAN 1 +#endif + + + +#if defined( MBG_TGT_LINUX ) + + #include + + #if defined( MBG_TGT_KERNEL ) + #include + + #define _mbg_put_unaligned( _v, _p ) put_unaligned( _v, _p ) + #define _mbg_get_unaligned( _p ) get_unaligned( _p ) + #endif + +#endif + + + +// If no macros required to access unaligned data have yet been defined, +// define some default macros assuming no special handling is required +// to access unaligned data. + +#if !defined( _mbg_put_unaligned ) + #define _mbg_put_unaligned( _v, _p ) ((void)( *(_p) = (_v) )) +#endif + +#if !defined( _mbg_get_unaligned ) + #define _mbg_get_unaligned( _p ) (*(_p)) +#endif + + + +// If no macros to convert endianess have yet been defined, define +// some default macros assuming endianess conversion is not required. + +#if !defined( __le16_to_cpu ) + #define __le16_to_cpu( _x ) (_x) +#endif + +#if !defined( __le32_to_cpu ) + #define __le32_to_cpu( _x ) (_x) +#endif + +#if !defined( __le64_to_cpu ) + #define __le64_to_cpu( _x ) (_x) +#endif + +#if !defined( __cpu_to_le16 ) + #define __cpu_to_le16( _x ) (_x) +#endif + +#if !defined( __cpu_to_le32 ) + #define __cpu_to_le32( _x ) (_x) +#endif + +#if !defined( __cpu_to_le64 ) + #define __cpu_to_le64( _x ) (_x) +#endif + + + +// The macros below are used to convert the endianess +// of the plug-in cards to the endianess of the host CPU + +#define _mbg8_to_cpu( _x ) ( _x ) +#define _mbg16_to_cpu( _x ) __le16_to_cpu( _x ) +#define _mbg32_to_cpu( _x ) __le32_to_cpu( _x ) +#define _mbg64_to_cpu( _x ) __le64_to_cpu( _x ) + +#define _cpu_to_mbg8( _x ) ( _x ) +#define _cpu_to_mbg16( _x ) __cpu_to_le16( _x ) +#define _cpu_to_mbg32( _x ) __cpu_to_le32( _x ) +#define _cpu_to_mbg64( _x ) __cpu_to_le64( _x ) + + + +// swap a double type variable bytewise e.g. to convert the endianess + +static __mbg_inline +void mbg_swab_double( double *p ) +{ +#if 0 // The __swab64() may not work correctly for whatever reason ... + __swab64p( p ); +#else // ... so we do the swapping manually + double d = 0; + size_t i; + + for ( i = 0; i < sizeof( double); i++ ) + BYTE_OF( d, i ) = BYTE_OF( *p, ( sizeof( double) - 1 - i ) ); + + for ( i = 0; i < sizeof( double); i++ ) + BYTE_OF( *p, i ) = BYTE_OF( d, i ); +#endif + +} // mbg_swab_double + + + +#if defined( MBG_ARCH_BIG_ENDIAN ) + + #define _mbg_swab16( _p ) *(_p) = __swab16( *(_p) ) + #define _mbg_swab32( _p ) *(_p) = __swab32( *(_p) ) + + #define _mbg_swab_double( _p ) mbg_swab_double( _p ) + + #define _mbg_swab_doubles( _p, _n ) \ + { \ + int i; \ + for ( i = 0; i < (_n); i++ ) \ + _mbg_swab_double( &_p[i] ); \ + } + +#else + + #define _mbg_swab16( _p ) _nop_macro_fnc() + #define _mbg_swab32( _p ) _nop_macro_fnc() + + #define _mbg_swab_double( _p ) _nop_macro_fnc() + + #define _mbg_swab_doubles( _p, _n ) _nop_macro_fnc() + +#endif + + + +//##++++++++++++ +/// @brief A placeholder for yet missing _mbg_swab_..() macros +#define _mbg_swab_dummy( _x ) _nop_macro_fnc() + + +#endif /* _MBG_ARCH_H */ diff --git a/mbglib/common/mbg_tgt.h b/mbglib/common/mbg_tgt.h index 708d76a..3c18952 100644 --- a/mbglib/common/mbg_tgt.h +++ b/mbglib/common/mbg_tgt.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbg_tgt.h 1.22 2009/10/01 08:20:50 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,9 +11,47 @@ * * ----------------------------------------------------------------------- * $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. + * Always include winsock2.h and windows.h for MBG_TGT_WIN32. + * Always include unistd.h for MBG_TGT_POSIX. + * Define empty __attribute__ macro for non-gcc environments. + * Revision 1.29 2013/02/01 14:50:46 martin + * Fixed a typo which caused an error under Borland CBuilder 5. + * Revision 1.28 2012/12/12 10:03:16Z martin + * Fix for Borland C 3.1. + * Revision 1.27 2012/11/29 12:03:14Z martin + * Moved definition of _no_macro_fnc() to words.h. + * Revision 1.26 2012/11/02 09:01:47Z martin + * Merged some stuff depending on the build environment here + * and cleaned up. + * Revision 1.25 2012/04/04 07:17:18 martin + * Treat QNX Neutrino as Unix target. + * Revision 1.24 2011/08/23 10:21:23 martin + * New symbol _NO_MBG_API_ATTR which can be used with functions + * which are going to be exported by a DLL, but actually aren't, yet. + * Revision 1.23 2011/08/19 10:47:00 martin + * Don't include stddef.h. + * Distinguish between different gcc target platforms. + * Initial support for IA64 platform. + * Support wchar_t for BSD. + * Defined _NO_USE_PACK_INTF for Sparc and IA64. + * Fixed typo in comment. * Revision 1.22 2009/10/01 08:20:50 martin * Fixed inline code support with different BC versions. - * Revision 1.1 2009/11/20 12:24:05 philipp * Revision 1.21 2009/09/01 10:34:23Z martin * Don't define __mbg_inline for CVI and undefined targets. * Revision 1.20 2009/08/18 15:14:26 martin @@ -80,8 +118,6 @@ /* Other headers to be included */ -#include - #ifdef _MBG_TGT #define _ext #else @@ -91,11 +127,16 @@ /* Start of header body */ -#if defined( _CVI ) || defined( _CVI_ ) +#if defined( _CVI_ ) - #define MBG_TGT_WIN32 #define MBG_TGT_CVI + #if defined( _NI_mswin_ ) + #define MBG_TGT_WIN32 + #else + #error Unsupported CVI target platform. + #endif + #elif defined( _WIN32_WINNT ) // MS platform SDK @@ -131,6 +172,11 @@ // MS Visual C++ #define MBG_TGT_WIN32 +#elif defined( RC_INVOKED ) + + //MS resource compiler + #define MBG_TGT_WIN32 + #elif defined( __WINDOWS_386__ ) // Watcom C/C++ for target Win32 @@ -152,6 +198,10 @@ #define MBG_TGT_LINUX #define _GNU_SOURCE 1 + #if defined( __KERNEL__ ) + #define MBG_TGT_KERNEL + #endif + #elif defined( __FreeBSD__ ) // GCC for target FreeBSD @@ -164,9 +214,26 @@ #elif defined( __OpenBSD__ ) - // GCC for target FreeBSD + // 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 + #include + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #elif defined( __QNX__ ) // any compiler for target QNX @@ -190,39 +257,211 @@ #endif -// Some definitions which depend on the type of compiler ... + + +#if defined( MBG_TGT_FREEBSD ) \ + || defined( MBG_TGT_NETBSD ) \ + || defined( MBG_TGT_OPENBSD ) + #define MBG_TGT_BSD + + #if defined( _KERNEL ) + #define MBG_TGT_KERNEL + #endif + +#endif + +#if defined( MBG_TGT_LINUX ) \ + || defined( MBG_TGT_BSD ) \ + || defined( MBG_TGT_SUNOS ) + #define MBG_TGT_POSIX + #define MBG_TGT_UNIX +#endif + + + +// Some definitions depending on the build environment ... #if defined( __GNUC__ ) - #define __mbg_inline __inline__ + #if defined( __i386__ ) - #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + #define MBG_ARCH_I386 + #define MBG_ARCH_X86 - #if defined( __sparc__ ) + #elif defined( __x86_64__ ) + + #define MBG_ARCH_X86_64 + #define MBG_ARCH_X86 + + #elif defined( __ia64__ ) + + #define MBG_ARCH_IA64 + + #define _NO_USE_PACK_INTF + + #elif defined( __sparc__ ) #define MBG_ARCH_SPARC - #define _MBG_ARCH_DEFINED + #define MBG_USE_MM_IO_FOR_PCI 1 + + #define _NO_USE_PACK_INTF #elif defined( __arm__ ) #define MBG_ARCH_ARM - #define _MBG_ARCH_DEFINED #endif + #if defined( MBG_TGT_LINUX ) + + #if defined( __KERNEL__ ) + + #include + #include + + #if ( LINUX_VERSION_CODE <= KERNEL_VERSION( 2, 6, 4 ) ) + #define _ULONG_DEFINED 1 + #define _USHORT_DEFINED 1 + #define _UINT_DEFINED 1 + #endif + + #else + + #include + #include + #include + + #if defined( __u_char_defined ) + #define _ULONG_DEFINED 1 + #define _USHORT_DEFINED 1 + #define _UINT_DEFINED 1 + #endif + + #endif + + #elif defined( MBG_TGT_BSD ) + + #include + + #elif defined( MBG_TGT_QNX_NTO ) // QNX 6.x (Neutrino) + + #include + #include + + #else + + #include + #include + + #endif + + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + + #define MBG_TGT_HAS_WCHAR_T 1 + + #define __mbg_inline __inline__ + #elif defined( _MSC_VER ) + // Known predifined MS compiler version codes: + // 1700: MSVC++ 11.0 (Visual Studio 2012) + // 1600: MSVC++ 10.0 (Visual Studio 2010) + // 1500: MSVC++ 9.0 (Visual Studio 2008) + // 1400: MSVC++ 8.0 (Visual Studio 2005) + // 1310: MSVC++ 7.1 (Visual Studio 2003) + // 1300: MSVC++ 7.0 + // 1200: MSVC++ 6.0 + // 1100: MSVC++ 5.0 + + #if ( _MSC_VER >= 1600 ) + #include + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #else + #define MBG_TGT_HAS_INT_8_16_32 1 + #endif + + // no bool support anyway + #define MBG_TGT_MISSING_BOOL_TYPE 1 + + #define MBG_TGT_HAS_WCHAR_T 1 + #define __mbg_inline __forceinline - #define MBG_TGT_HAS_WCHAR_T 1 + // 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 ) || defined( _CVI_ ) +#elif defined( _CVI_ ) - // Inline code is not supported. + // 1000 for CVI v10.0 (CVI 2010) + // 911 for CVI v9.1.1 (CVI 2009 SP1) + // 910 for CVI v9.1 (CVI 2009) + // 310 for CVI v3.1 + // 301 for CVI v3.0.1 + // 1 for CVI v3.0 - #define MBG_TGT_HAS_WCHAR_T 0 + #if ( _CVI_ >= 910 ) + // LabWindows/CVI 2009 is the first version providing stdint.h. + #include + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #else + #define USE_LONG_FOR_INT32 1 + #endif -#elif defined( __BORLANDC__ ) + // As of LabWindows/CVI 2010, stdbool.h is still missing. + #define MBG_TGT_MISSING_BOOL_TYPE 1 + + #define MBG_TGT_HAS_WCHAR_T 0 + + // Inline code is not supported, though the inline keyword + // is silently accepted since CVI v9.0 + +#elif defined( __BORLANDC__ ) // or __CODEGEARC__ in newer versions + + // 0x0200 Borland C/C++ 2.0 + // 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 + #include + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #elif ( __BORLANDC__ >= 0x570 ) + // at least BDS 2006 starts to provide stdint.h + #include + #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 + #else // e.g. BC 3.1 or earlier + #if ( __BORLANDC__ <= 0x410 ) + #define MBG_TGT_MISSING_64_BIT_TYPES 1 + #define MBG_TGT_MISSING_BOOL_TYPE 1 + #define USE_LONG_FOR_INT32 1 + #endif + #endif + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) #if defined( __cplusplus ) #define __mbg_inline inline // standard C++ syntax @@ -232,42 +471,46 @@ #define __mbg_inline // up to BC3.1 not supported for C #endif - #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) - #elif defined( __WATCOMC__ ) - #define __mbg_inline _inline + // 1050 v10.5 + // 1100 v11.0 + // 1200 Open Watcom C++ v1.0 + // 1230 Open Watcom C++ v1.3 + // 1270 Open Watcom C++ v1.7 - #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + #if defined( MBG_TGT_QNX ) // QNX 4.x -#endif + #include + #define MBG_TGT_MISSING_64_BIT_TYPES 1 + #elif ( __WATCOMC__ > 1230 ) // Open Watcom C 1.3 and above -// Currently we support only Sparc and i386/x86_64 architectures, -// so unless we have explicitely found sparc we assume i386. + #include -#if !defined( _MBG_ARCH_DEFINED ) - #define MBG_ARCH_I386 -#endif + #elif !defined( __WATCOM_INT64__ ) // Watcom C 11 + #define MBG_TGT_MISSING_64_BIT_TYPES 1 -#if defined( MBG_TGT_FREEBSD ) \ - || defined( MBG_TGT_NETBSD ) \ - || defined( MBG_TGT_OPENBSD ) - #define MBG_TGT_BSD -#endif + #endif + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + + #define __mbg_inline _inline -#if defined( MBG_TGT_LINUX ) \ - || defined( MBG_TGT_BSD ) \ - || defined( MBG_TGT_QNX_NTO ) - #define MBG_TGT_UNIX #endif +#if !defined( __GNUC__ ) && !defined( __attribute__ ) + #define __attribute__( _x ) +#endif + #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. @@ -279,10 +522,18 @@ #endif #if defined( _KDD_ ) + #define MBG_TGT_KERNEL #include #else // This must not be used for kernel drivers. + #if !defined( WIN32_LEAN_AND_MEAN ) + #define WIN32_LEAN_AND_MEAN 1 + #endif + + #define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */ + #include #include + typedef HANDLE MBG_HANDLE; #define MBG_INVALID_HANDLE INVALID_HANDLE_VALUE @@ -313,7 +564,11 @@ #define _MBG_API_ATTR __declspec( dllimport ) #endif -#elif defined( MBG_TGT_UNIX ) +#elif defined( MBG_TGT_POSIX ) + + #if !defined( MBG_TGT_KERNEL ) + #include + #endif typedef int MBG_HANDLE; typedef int MBG_PORT_HANDLE; @@ -338,28 +593,33 @@ #define _MBG_API_ATTR #endif +#if !defined( _NO_MBG_API_ATTR ) + #define _NO_MBG_API_ATTR +#endif + #if !defined( MBG_INVALID_PORT_HANDLE ) #define MBG_INVALID_PORT_HANDLE MBG_INVALID_HANDLE #endif #if !defined( MBG_USE_MM_IO_FOR_PCI ) - #if ( 0 || defined( MBG_ARCH_SPARC ) ) - #define MBG_USE_MM_IO_FOR_PCI 1 - #else - #define MBG_USE_MM_IO_FOR_PCI 0 - #endif + #define MBG_USE_MM_IO_FOR_PCI 0 #endif -#if !defined( _nop_macro_fnc ) - #define _nop_macro_fnc() do {} while (0) +// The macros below are defined in order to be able to check if +// certain C language extensions are available on the target system: +#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199409L ) + #define MBG_TGT_C94 1 +#else + #define MBG_TGT_C94 0 #endif -// The macros below are defined in order to be able to check if -// certain C language extensions are available on the target system: -#define MBG_TGT_C94 ( defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199409L ) ) -#define MBG_TGT_C99 ( defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) ) +#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) + #define MBG_TGT_C99 1 +#else + #define MBG_TGT_C99 0 +#endif // Check if wchar_t is supported #if !defined( MBG_TGT_HAS_WCHAR_T ) @@ -372,7 +632,7 @@ // However, some functions may be missing (e.g. snwprintf()). #if !defined( _WCHAR_T ) /* BC3.1 */ \ && !defined( _WCHAR_T_DEFINED_ ) /* WC11 */ - //##++ #define _WCHAR_T + #define _WCHAR_T #define wchar_t char #endif #endif diff --git a/mbglib/common/mbg_tmo.h b/mbglib/common/mbg_tmo.h index 18c365d..b76f9af 100644 --- a/mbglib/common/mbg_tmo.h +++ b/mbglib/common/mbg_tmo.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbg_tmo.h 1.4 2011/01/26 16:55:33 martin REL_M $ + * $Id: mbg_tmo.h 1.8.1.3 2014/03/06 13:51:39 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,7 +10,20 @@ * * ----------------------------------------------------------------------- * $Log: mbg_tmo.h $ - * Revision 1.4 2011/01/26 16:55:33 martin + * Revision 1.8.1.3 2014/03/06 13:51:39 martin + * Renamed mbgserio_msec_to_timeval to mbg_msec_to_timeval. + * Revision 1.8.1.2 2014/03/04 12:08:11 martin + * Revision 1.8.1.1 2014/01/08 17:20:51Z martin + * MBG_TGT_POSIX + * Revision 1.8 2013/12/11 12:08:29 martin + * Fixed Windows build. + * Revision 1.7 2012/11/02 09:04:36Z martin + * Fix to have struct timeval defined under Windows. + * Revision 1.6 2012/03/16 11:56:23 martin + * Added mbg_tmo_delta_t(). + * Revision 1.5 2011/11/28 15:26:47 martin + * Enabled mbgserio_msec_to_timeval() for Windows. + * Revision 1.4 2011/01/26 16:55:33Z martin * Fixed compiler warnings with gcc/Linux. * Revision 1.3 2010/06/02 12:29:44 daniel * Excluded mbgserio_msec_to_timeval() from build under WIN32 targets. @@ -40,8 +53,9 @@ /* Start of header body */ -#if defined( MBG_TGT_UNIX ) +#if defined( MBG_TGT_POSIX ) + // TODO: eventually use timespec, if available #include #include @@ -71,7 +85,7 @@ static __mbg_inline void mbg_tmo_get_time( MBG_TMO_TIME *t ) { - #if defined( MBG_TGT_UNIX ) + #if defined( MBG_TGT_POSIX ) gettimeofday( t, NULL ); @@ -100,12 +114,13 @@ void mbg_tmo_get_time( MBG_TMO_TIME *t ) #endif + #if defined( __mbg_inline ) static __mbg_inline int mbg_tmo_time_is_set( const MBG_TMO_TIME *t ) { - #if defined( MBG_TGT_UNIX ) + #if defined( MBG_TGT_POSIX ) return ( t->tv_sec != 0 ) || ( t->tv_usec != 0 ); @@ -134,6 +149,7 @@ int mbg_tmo_time_is_set( const MBG_TMO_TIME *t ) #endif + #if defined( __mbg_inline ) static __mbg_inline @@ -141,7 +157,7 @@ void mbg_tmo_set_timeout_ms( MBG_TMO_TIME *t_tmo, ulong msec ) { mbg_tmo_get_time( t_tmo ); - #if defined( MBG_TGT_UNIX ) + #if defined( MBG_TGT_POSIX ) t_tmo->tv_usec += msec * 1000; @@ -177,12 +193,13 @@ void mbg_tmo_set_timeout_ms( MBG_TMO_TIME *t_tmo, ulong msec ) #endif + #if defined( __mbg_inline ) static __mbg_inline long mbg_tmo_time_diff_ms( const MBG_TMO_TIME *t, const MBG_TMO_TIME *t0 ) { - #if defined( MBG_TGT_UNIX ) + #if defined( MBG_TGT_POSIX ) return ( t->tv_sec - t0->tv_sec ) * 1000 + ( t->tv_usec - t0->tv_usec ) / 1000; @@ -212,12 +229,49 @@ long mbg_tmo_time_diff_ms( const MBG_TMO_TIME *t, const MBG_TMO_TIME *t0 ) #endif + +#if defined( __mbg_inline ) + +static __mbg_inline +double mbg_tmo_delta_t( const MBG_TMO_TIME *t, const MBG_TMO_TIME *t0 ) +{ + #if defined( MBG_TGT_POSIX ) + + return (double) ( t->tv_sec - t0->tv_sec ) + + (double) ( t->tv_usec - t0->tv_usec ) / 1e6; + + #elif defined( MBG_TGT_WIN32 ) + + return ( (double) (int64_t) ( t->u64 - t0->u64 ) ) / 1e7; + + #else // DOS, ... + + return (double) ( *t - *t0 ) / (double) CLOCKS_PER_SEC; + + #endif + +} // mbg_tmo_delta_t + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_delta_t( _t, _t0 ) \ + ( (double) ( (_t)->u64 - (_t0)->u64 ) / (double) CLOCKS_PER_SEC ) + +#else // DOS, ... + + #define mbg_tmo_delta_t( _t, _t0 ) \ + ( (double) ( *(_t) - *(_t0) ) / (double) CLOCKS_PER_SEC ) + +#endif + + + #if defined( __mbg_inline ) static __mbg_inline int mbg_tmo_time_is_after( const MBG_TMO_TIME *t_now, const MBG_TMO_TIME *tmo ) { - #if defined( MBG_TGT_UNIX ) + #if defined( MBG_TGT_POSIX ) return ( ( t_now->tv_sec > tmo->tv_sec ) || ( ( t_now->tv_sec == tmo->tv_sec ) && ( t_now->tv_usec > tmo->tv_usec ) ) ); @@ -275,19 +329,19 @@ int mbg_tmo_curr_time_is_after( const MBG_TMO_TIME *tmo ) #if defined( MBG_TGT_CVI ) // needs to be implemented as non-inline function in mbg_tmo.c - void mbgserio_msec_to_timeval( ulong msec, struct timeval *tv ); + void mbg_msec_to_timeval( ulong msec, struct timeval *tv ); -#elif defined( MBG_TGT_UNIX ) +#elif defined( MBG_TGT_POSIX ) || defined( MBG_TGT_WIN32 ) static __mbg_inline -void mbgserio_msec_to_timeval( ulong msec, struct timeval *tv ) +void mbg_msec_to_timeval( ulong msec, struct timeval *tv ) { tv->tv_sec = msec / 1000; tv->tv_usec = ( msec % 1000 ) * 1000; -} // mbgserio_msec_to_timeval +} // mbg_msec_to_timeval -#endif // defined( MBG_TGT_UNIX ) || defined( MBG_TGT_WIN32 ) +#endif // defined( MBG_TGT_POSIX ) || defined( MBG_TGT_WIN32 ) /* function prototypes: */ diff --git a/mbglib/common/mbgerror.c b/mbglib/common/mbgerror.c new file mode 100644 index 0000000..3e8b121 --- /dev/null +++ b/mbglib/common/mbgerror.c @@ -0,0 +1,413 @@ + +/************************************************************************** + * + * $Id: mbgerror.c 1.1.1.10 2015/05/20 12:34:03 martin TEST $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Meinberg Library to communicate with USB devices from user space + * + * ----------------------------------------------------------------------- + * $Log: mbgerror.c $ + * Revision 1.1.1.10 2015/05/20 12:34:03 martin + * Revision 1.1.1.9 2014/10/28 15:19:17 martin + * Revision 1.1.1.8 2014/05/27 12:44:33Z martin + * Revision 1.1.1.7 2014/05/09 11:39:17 marvin + * Added access denied error to win32_to_mbg error handling. + * Revision 1.1.1.6 2014/03/18 11:25:54Z gregoire + * Fixed build errors fopr CVI, but this needs + * to be tested / improved. + * Revision 1.1.1.5 2014/03/12 09:01:56Z martin + * Revision 1.1.1.4 2014/03/11 14:12:29 martin + * Revision 1.1.1.3 2014/03/11 14:08:55Z martin + * Revision 1.1.1.2 2014/03/10 16:57:15Z martin + * Revision 1.1.1.1 2014/03/07 13:20:26 martin + * Tmp. saved changes. + * Revision 1.1 2014/03/07 12:08:14 martin + * Initial revision. + * +**************************************************************************/ + +#define _MBGERROR + #include +#undef _MBGERROR + +#include + +#include +#include + +#if defined( MBG_TGT_POSIX ) + #include + #include +#endif + + + +#if defined( MBG_TGT_WIN32 ) + +/*HDR*/ +/** + * @brief Translate a Windows non-socket API error code to one of the @ref MBG_ERROR_CODES + * + * @param last_err A Windows non-socket API error code as returned by GetLastError() + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_win32_last_err_to_mbg( DWORD last_err, const char *info ) +{ + #if DEBUG + if ( info ) + fprintf( stderr, "%s, wsa_err: 0x%08lX\n", info, (long) last_err ); + #endif + + //##++++++++++++++++ TODO check codes + switch ( last_err ) // codes usually defined in winerror.h + { + case ERROR_SUCCESS: return MBG_SUCCESS; + case ERROR_ACCESS_DENIED: return MBG_ERR_ACCESS; + + case ERROR_PRIVILEGE_NOT_HELD: return MBG_ERR_PERM; + + #if 0 + case ERROR_INVALID_HANDLE: + + case ERROR_NOT_ENOUGH_MEMORY: + case ERROR_OUTOFMEMORY: + + case ERROR_WRITE_PROTECT: + case ERROR_BAD_UNIT: + case ERROR_NOT_READY: + case ERROR_WRITE_FAULT: + case ERROR_READ_FAULT: + case ERROR_GEN_FAILURE: + case ERROR_SHARING_VIOLATION: + case ERROR_LOCK_VIOLATION: + case ERROR_NOT_SUPPORTED: + + case ERROR_DUP_NAME: + case ERROR_BAD_DEV_TYPE: + case ERROR_BUFFER_OVERFLOW: + + case ERROR_BUSY: + case ERROR_NOACCESS: + #endif + } + + return MBG_ERR_UNSPEC; + +} // mbg_win32_last_err_to_mbg + + + +/*HDR*/ +/** + * @brief Translate a Windows socket API error code to one of the @ref MBG_ERROR_CODES + * + * @param wsa_err A Windows socket API error code as returned by WSAGetLastError() + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_win32_wsa_err_to_mbg( DWORD wsa_err, const char *info ) +{ + #if DEBUG + if ( info ) + fprintf( stderr, "%s, wsa_err: 0x%08lX\n", info, (long) wsa_err ); + #endif + + //##++++++++++++++++ TODO check codes + switch ( wsa_err ) + { + case WSAENOTSOCK: + return MBG_ERR_NOT_A_SOCKET; + + case WSANOTINITIALISED: + return MBG_ERR_SOCK_INIT; + + case WSAEFAULT: + case WSAENETDOWN: + case WSAEINVAL: + case WSAEINTR: + case WSAEINPROGRESS: + return MBG_ERR_SOCK_INIT; + + case WSAEAFNOSUPPORT: + case WSAEMFILE: + case WSAEINVALIDPROVIDER: + case WSAEINVALIDPROCTABLE: + case WSAENOBUFS: + case WSAEPROTONOSUPPORT: + case WSAEPROTOTYPE: + case WSAEPROVIDERFAILEDINIT: + case WSAESOCKTNOSUPPORT: + return MBG_ERR_INV_SOCK_FD; //##++++++++++++++++ + +#if 0 + case WSAEALREADY: + case WSAEISCONN: + case WSAENETUNREACH: + return MBG_ERR_SOCKET_CFG; //##+++++ + break; +#endif + } + + return MBG_ERR_UNSPEC; + +} // mbg_win32_wsa_err_to_mbg + +#endif // defined( MBG_TGT_WIN32 ) + + + +#if defined( MBG_TGT_POSIX ) + +/*HDR*/ +/** + * @brief Translate a POSIX errno error code to one of the @ref MBG_ERROR_CODES + * + * @param posix_errno A POSIX error code as usually defined in errno.h + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_posix_errno_to_mbg( int posix_errno, const char *info ) +{ + #if DEBUG + if ( info ) + fprintf( stderr, "%s: %s (errno: %i)\n", info, + strerror( posix_errno ), posix_errno ); + #endif + + switch ( posix_errno ) + { + case EPERM: return MBG_ERR_PERM; + case EINTR: return MBG_ERR_INTR; + case EIO: return MBG_ERR_IO; + case ENXIO: return MBG_ERR_NOT_FOUND; + case ENOMEM: return MBG_ERR_NO_MEM; + case EACCES: return MBG_ERR_ACCESS; + case EBUSY: return MBG_ERR_BUSY; + case ENODEV: return MBG_ERR_NO_DEV; + case EINVAL: return MBG_ERR_INV_PARM; + case EPIPE: return MBG_ERR_PIPE; + case EOVERFLOW: return MBG_ERR_OVERFLOW; + case ENOTSOCK: return MBG_ERR_NOT_A_SOCKET; + default: break; + } + + return MBG_ERR_UNSPEC; + +} // mbg_posix_errno_to_mbg + + +/*HDR*/ +/** + * @brief Translate a POSIX h_errno error code to one of the @ref MBG_ERROR_CODES + * + * This function is specific to translate error codes returned by + * gethostbyname() and gethostbyaddr(). In case of error these functions + * don't set errno but h_errno to a specific value. + * + * The functions gethostbyname() and gethostbyaddr() are obsolete, + * and getaddressinfo() should be used preferably. + * + * @param posix_h_errno An error code as usually defined in netdb.h + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_posix_h_errno_to_mbg( int posix_h_errno, const char *info ) +{ + #if DEBUG + if ( info ) + fprintf( stderr, "%s: %s (h_errno: %i)\n", info, + hstrerror( posix_h_errno ), posix_h_errno ); + #endif + + switch ( posix_h_errno ) + { + case HOST_NOT_FOUND: // The specified host is unknown + + // case NO_ADDRESS: // Usually same numeric value as NO_DATA + case NO_DATA: // The requested name is valid but does not have an IP address + + case NO_RECOVERY: // A nonrecoverable name server error occurred + + case TRY_AGAIN: // A temporary error occurred on an authoritative name server. Try again later. + return MBG_ERR_UNSPEC; //##++++++++++++++++++++++++ + } + + return MBG_ERR_UNSPEC; + +} // mbg_posix_h_errno_to_mbg + +#endif // defined( MBG_TGT_POSIX ) + + + +/*HDR*/ +/** + * @brief Get and translate last error after non-socket function call + * + * Retrieve the "last error" code after a non-socket function has been called + * and translate to one of the @ref MBG_ERROR_CODES. + * + * On POSIX systems the "last error" code is always stored in errno, but + * e.g. under Windows the "last error" code after a socket function + * has to be retrieved by calling WSAGetLastError(), whereas the "last error" + * code from non-socket POSIX-like functions has to be retrieved + * by calling GetLastError(). + * + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_get_last_error( const char *info ) +{ + #if defined( MBG_TGT_WIN32 ) + + // Under Windows the "last error" code after a non-socket function + // has to be retrieved by calling GetLastError(), whereas + // the "last error" code from POSIX-like socket functions + // is retrieved by calling WSAGetLastError(). + return mbg_win32_wsa_err_to_mbg( GetLastError(), info ); + + #elif defined( MBG_TGT_POSIX ) + + // On POSIX systems the "last error" code is always stored in errno. + return mbg_posix_errno_to_mbg( errno, info ); + + #else + + #error This function is not supported for this target. + + #endif + +} // mbg_get_last_error + + + +/*HDR*/ +/** + * @brief Get and translate last error after socket function call + * + * Retrieve the "last error" code after a socket function has been called + * and translate to one of the @ref MBG_ERROR_CODES. + * + * On POSIX systems the "last error" code is always stored in errno, but + * e.g. under Windows the "last error" code after a socket function + * has to be retrieved by calling WSAGetLastError, whereas the "last error" + * code from non-socket POSIX-like functions is stored in errno as usual. + * + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_get_last_socket_error( const char *info ) +{ + #if defined( MBG_TGT_CVI ) + + #warning This needs to be implemented for CVI + return MBG_ERR_UNSPEC; + + #elif defined( MBG_TGT_WIN32 ) + + // Under Windows the "last error" code after a socket function + // has to be retrieved by calling WSAGetLastError, whereas + // the "last error" code from non-socket POSIX-like functions + // is stored in errno as usual. + return mbg_win32_wsa_err_to_mbg( WSAGetLastError(), info ); + + #elif defined( MBG_TGT_POSIX ) + + // On POSIX systems the "last error" code is always stored in errno. + return mbg_posix_errno_to_mbg( errno, info ); + + #else + + #error This function is not supported for this target. + + #endif + +} // mbg_get_last_socket_error + + + +/*HDR*/ +/** + * @brief Retrieve and convert last error after gethostbyname() + * + * This function is specific to retrieve and translate error codes + * returned by gethostbyname() and gethostbyaddr(). In case of error + * these functions don't set errno but h_errno on POSIX systems, but + * under Windows the error code can be retrieved by WSAGetLastError() + * as usual. + * + * The functions gethostbyname() and gethostbyaddr() are obsolete, + * and getaddressinfo() should be used preferably. + * + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_get_gethostbyname_error( const char *info ) +{ + #if defined( MBG_TGT_CVI ) + + #warning This needs to be implemented for CVI + return MBG_ERR_UNSPEC; + + #elif defined( MBG_TGT_WIN32 ) + + return mbg_win32_wsa_err_to_mbg( WSAGetLastError(), info ); + + #elif defined( MBG_TGT_POSIX ) + + return mbg_posix_h_errno_to_mbg( h_errno, info ); + + #else + + #error This function is not supported for this target. + + #endif + +} // mbg_get_gethostbyname_error + + + +#if 0 // not yet finished +// error handler for getaddressinfo() +/* + * Handle specific error returned by getaddressinfo() + */ + /*HDR*/ +int mbg_gai_error( int rc, const char *info ) +{ + #if defined( MBG_TGT_CVI ) + + #warning This needs to be implemented for CVI + return MBG_ERR_UNSPEC; + + #elif defined( MBG_TGT_WIN32 ) + + return mbg_win32_wsa_err_to_mbg( WSAGetLastError(), info ); + + #elif defined( MBG_TGT_POSIX ) + + return mbg_posix_h_errno_to_mbg( h_errno, info ); + + #else + + return MBG_ERR_UNSPEC; + + #endif + +} // mbg_get_gai_error + +#endif + + + diff --git a/mbglib/common/mbgerror.h b/mbglib/common/mbgerror.h new file mode 100644 index 0000000..d8bb5e4 --- /dev/null +++ b/mbglib/common/mbgerror.h @@ -0,0 +1,326 @@ + +/************************************************************************** + * + * $Id: mbgerror.h 1.7.1.6 2015/05/20 12:33:17 martin TEST $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Error codes used with Meinberg devices and drivers. + * The codes can be translated into an OS dependent error code. + * + * ----------------------------------------------------------------------- + * $Log: mbgerror.h $ + * Revision 1.7.1.6 2015/05/20 12:33:17 martin + * Revision 1.7.1.5 2015/05/13 13:53:23 martin + * Revision 1.7.1.4 2014/10/30 11:15:36 martin + * Revision 1.7.1.3 2014/10/28 15:19:17 martin + * Revision 1.7.1.2 2014/09/26 11:45:34Z martin + * Revision 1.7.1.1 2014/06/25 08:52:50 martin + * Re-enabled some symbols which have been commented out.. + * Revision 1.7 2014/05/27 13:32:47Z martin + * Defined additional common error codes which can be + * translated from OS specific codes. + * Function prototypes from new module mbgerror.c. + * Comments in doxygen style. + * Revision 1.6 2012/10/02 18:42:26Z martin + * New codes MBG_ERR_N_POUT_EXCEEDS_SUPP and + * MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP. + * Modified comments for doxygen. + * Revision 1.5 2011/03/31 10:56:17 martin + * Added MBG_ERR_COPY_TO_USER and MBG_ERR_COPY_FROM_USER. + * Revision 1.4 2008/12/05 13:28:50 martin + * Added new code MBG_ERR_IRQ_UNSAFE. + * Revision 1.3 2008/02/26 14:50:14Z daniel + * Added codes: + * MBG_ERR_NOT_SUPP_ON_OS, MBG_ERR_LIB_NOT_COMPATIBLE, + * MBG_ERR_N_COM_EXCEEDS_SUPP, MBG_ERR_N_STR_EXCEEDS_SUPP + * Added doxygen compatible comments. + * Revision 1.2 2007/09/27 07:26:22Z martin + * Define STATUS_SUCCESS for Windows if not in kernel mode. + * Revision 1.1 2007/09/26 08:08:54Z martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBGERROR_H +#define _MBGERROR_H + + +/* Other headers to be included */ + +#include + +#ifdef _MBGERROR + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if !defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_KERNEL ) + //##++++ Surprisingly we need this also for Windows + // in kernel mode. This should be fixed. + #define DWORD uint32_t // just to avoid compiler errors +#endif + + +/** + * @brief Error codes used with Meinberg devices and drivers + * + * Some of the codes have to match codes which are defined in pcpsdefs.h + * and returned by the firmware of bus-level devices. + * + * The codes will be translated into an OS dependent error code + * when returned to the calling function. + * + * For Windows, these codes are made positive and or'ed with 0xE0000000 afterwards. + * + * Example: Code -19 (#MBG_ERR_GENERIC) will be converted to 0xE0000013 under Windows. + * + * @note Attention: + * The error codes below must match exactly the corresponding codes that are evaluated in user space. + * For Windows, they are located in messages.mc/.h in mbgsvctl.dll + * + * @anchor MBG_RETURN_CODES @{ */ + +#define MBG_SUCCESS 0 ///< no error, must match ::PCPS_SUCCESS + + /** @anchor MBG_ERROR_CODES @{ */ + +// Other codes which have to match codes defined in pcpsdefs.h returned by bus-level devices +#define MBG_ERR_STIME -1 ///< invalid date/time/status passed, must match ::PCPS_ERR_STIME +#define MBG_ERR_CFG -2 ///< invalid params with a configuration cmd, must match ::PCPS_ERR_CFG + + +// Codes returned by low level functions of the bus-level device driver +#define MBG_ERR_GENERIC -19 ///< generic error +#define MBG_ERR_TIMEOUT -20 ///< timeout accessing the device +#define MBG_ERR_FW_ID -21 ///< invalid firmware ID +#define MBG_ERR_NBYTES -22 ///< the number of parameter bytes passed to the device did not + ///< match the number of bytes expected by the device + +#define MBG_ERR_INV_TIME -23 ///< the device doesn't have valid time +#define MBG_ERR_FIFO -24 ///< the data FIFO of a bus-level device is empty, though it shouldn't be +#define MBG_ERR_NOT_READY -25 ///< bus-level device is temp. unable to respond e.g. during init. after RESET +#define MBG_ERR_INV_TYPE -26 ///< bus-level device didn't recognize data type + + +// Codes returned by the high level API functions +#define MBG_ERR_NO_MEM -27 ///< failed to allocate memory +#define MBG_ERR_CLAIM_RSRC -28 ///< failed to claim port or mem resource +#define MBG_ERR_DEV_NOT_SUPP -29 ///< specified device type not supported by driver +#define MBG_ERR_INV_DEV_REQUEST -30 ///< IOCTL call not supported by driver +#define MBG_ERR_NOT_SUPP_BY_DEV -31 ///< cmd or feature not supported by device +#define MBG_ERR_USB_ACCESS -32 ///< USB access failed +#define MBG_ERR_CYCLIC_TIMEOUT -33 ///< cyclic event (IRQ, etc.) didn't occur +#define MBG_ERR_NOT_SUPP_ON_OS -34 ///< function is not supported under this operating system +#define MBG_ERR_LIB_NOT_COMPATIBLE -35 ///< installed shared lib. version not compat. with version used at build time +#define MBG_ERR_N_COM_EXCEEDS_SUPP -36 ///< num. COM ports of the device exceeds max. supp. by driver +#define MBG_ERR_N_STR_EXCEEDS_SUPP -37 ///< num. string formats of the device exceeds max. supp. by driver +#define MBG_ERR_IRQ_UNSAFE -38 ///< enabled IRQ of bus-level device is unsafe with this firmware/ASIC version +#define MBG_ERR_N_POUT_EXCEEDS_SUPP -39 ///< num. prog. outputs of the device exceeds max. supp. by driver + +// Legacy codes used with DOS TSRs only: +#define MBG_ERR_INV_INTNO -40 ///< invalid interrupt number +#define MBG_ERR_NO_DRIVER -41 ///< a driver could not be found +#define MBG_ERR_DRV_VERSION -42 ///< the driver is too old + + +#define MBG_ERR_COPY_TO_USER -43 ///< kernel driver failed to copy data from kernel to user space +#define MBG_ERR_COPY_FROM_USER -44 ///< kernel driver failed to copy data from use to kernel space + + +// More codes returned by the driver's high level functions: +#define MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP -45 ///< num. PTP unicast masters of the device exceeds max. supp. by driver +#define MBG_ERR_N_GNSS_EXCEEDS_SUPP -46 ///< num. of GNSS systems supp. by device exceeds max. supp. by driver +#define MBG_ERR_N_GPIO_EXCEEDS_SUPP -47 ///< num. of GPIO ports supp. by device exceeds max. supp. by driver +#define MBG_ERR_N_XMR_EXCEEDS_SUPP -48 ///< num. of XMR sources supp. by device exceeds max. supp. by driver + +#define MBG_ERR_UNSPEC -60 ///< unspecified error + +#define MBG_ERR_HDR_CSUM -61 ///< binary protocol header checksum error +#define MBG_ERR_DATA_CSUM -62 ///< binary protocol data checksum error +#define MBG_ERR_RCVD_NACK -63 ///< binary protocol received reply msg with a NACK code +#define MBG_ERR_RCVD_NO_ACK -64 ///< binary protocol received reply msg without expected ACK code +#define MBG_ERR_CONN_TYPE -65 ///< binary protocol no valid/supported connection type specified +#define MBG_ERR_BYTES_WRITTEN -66 ///< binary protocol failed to write all bytes +#define MBG_ERR_AUTH -67 ///< binary protocol failed authentication + +#define MBG_ERR_SOCK_INIT -68 ///< socket interface not initialized, or failed to initialize +#define MBG_ERR_INV_SOCK_FD -69 ///< invalid socket when tried to open network socket +#define MBG_ERR_NOT_A_SOCKET -70 ///< socket descriptor is not a socket +#define MBG_ERR_NBLOCK_WAIT_SLCT -71 ///< select timed out when waiting for non-blocking network port to become ready +#define MBG_ERR_NBLOCK_WAIT_WR_FD -72 ///< write fd not set after select when waiting for non-blocking network port to become ready + +#define MBG_ERR_IO -73 ///< generic I/O error +#define MBG_ERR_INV_PARM -74 ///< invalid parameter +#define MBG_ERR_NO_DEV -75 ///< specified device not found +#define MBG_ERR_NOT_FOUND -76 ///< specified item not found + +#define MBG_ERR_OVERFLOW -77 ///< buffer overflow +#define MBG_ERR_PIPE -78 ///< pipe error +#define MBG_ERR_INTR -79 ///< interrupted system call +#define MBG_ERR_ACCESS -80 ///< access denied, e.g. when trying to access a device +#define MBG_ERR_PERM -81 ///< operation not permitted, e.g. when trying to set the system time +#define MBG_ERR_BUSY -82 ///< device busy +#define MBG_ERR_INV_HANDLE -83 ///< invalid file/device handle specified + +#define MBG_ERR_XBP_CASC_LVL -84 ///< too many XBP cascading levels +#define MBG_ERR_ENCRYPT -85 ///< encryption failed +#define MBG_ERR_DECRYPT -86 ///< decryption failed + +/** @} anchor MBG_ERROR_CODES */ + +/** @} anchor MBG_RETURN_CODES */ + + + +// Depending on the operating system, the codes above have to be converted before +// they are sent up to user space +#if defined( MBG_TGT_WIN32 ) + #if !defined( STATUS_SUCCESS ) // not in kernel mode + #define STATUS_SUCCESS 0 + #endif + + #define _mbg_err_to_os( _c ) \ + ( ( _c == MBG_SUCCESS ) ? STATUS_SUCCESS : ( abs( _c ) | 0xE0000000 ) ) +#endif + + +// If no specific conversion has been defined +// then use the original codes. +#if !defined( _mbg_err_to_os ) + #define _mbg_err_to_os( _c ) ( _c ) +#endif + + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + * @brief Translate a Windows non-socket API error code to one of the @ref MBG_ERROR_CODES + * + * @param wsa_err A Windows non-socket API error code as returned by GetLastError() + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_win32_last_err_to_mbg( DWORD wsa_err, const char *info ) ; + + /** + * @brief Translate a Windows socket API error code to one of the @ref MBG_ERROR_CODES + * + * @param wsa_err A Windows socket API error code as returned by WSAGetLastError() + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_win32_wsa_err_to_mbg( DWORD wsa_err, const char *info ) ; + + /** + * @brief Translate a POSIX errno error code to one of the @ref MBG_ERROR_CODES + * + * @param posix_errno A POSIX error code as usually defined in errno.h + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_posix_errno_to_mbg( int posix_errno, const char *info ) ; + + /** + * @brief Translate a POSIX h_errno error code to one of the @ref MBG_ERROR_CODES + * + * This function is specific to translate error codes returned by + * gethostbyname() and gethostbyaddr(). In case of error these functions + * don't set errno but h_errno to a specific value. + * + * The functions gethostbyname() and gethostbyaddr() are obsolete, + * and getaddressinfo() should be used preferably. + * + * @param posix_h_errno An error code as usually defined in netdb.h + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_posix_h_errno_to_mbg( int posix_h_errno, const char *info ) ; + + /** + * @brief Get and translate last error after non-socket function call + * + * Retrieve the "last error" code after a non-socket function has been called + * and translate to one of the @ref MBG_ERROR_CODES. + * + * On POSIX systems the "last error" code is always stored in errno, but + * e.g. under Windows the "last error" code after a socket function + * has to be retrieved by calling WSAGetLastError(), whereas the "last error" + * code from non-socket POSIX-like functions has to be retrieved + * by calling GetLastError(). + * + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_get_last_error( const char *info ) ; + + /** + * @brief Get and translate last error after socket function call + * + * Retrieve the "last error" code after a socket function has been called + * and translate to one of the @ref MBG_ERROR_CODES. + * + * On POSIX systems the "last error" code is always stored in errno, but + * e.g. under Windows the "last error" code after a socket function + * has to be retrieved by calling WSAGetLastError, whereas the "last error" + * code from non-socket POSIX-like functions is stored in errno as usual. + * + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_get_last_socket_error( const char *info ) ; + + /** + * @brief Retrieve and convert last error after gethostbyname() + * + * This function is specific to retrieve and translate error codes + * returned by gethostbyname() and gethostbyaddr(). In case of error + * these functions don't set errno but h_errno on POSIX systems, but + * under Windows the error code can be retrieved by WSAGetLastError() + * as usual. + * + * The functions gethostbyname() and gethostbyaddr() are obsolete, + * and getaddressinfo() should be used preferably. + * + * @param info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_get_gethostbyname_error( const char *info ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBGERROR_H */ diff --git a/mbglib/common/mbgextio.c b/mbglib/common/mbgextio.c index 53b2486..5bb57ff 100644 --- a/mbglib/common/mbgextio.c +++ b/mbglib/common/mbgextio.c @@ -1,16 +1,110 @@ /************************************************************************** * - * $Id: mbgextio.c 1.11 2011/04/15 13:17:14 martin REL_M $ + * $Id: mbgextio.c 1.20.1.19 2015/07/22 16:02:07 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: * Meinberg extended I/O functions for the binary data protocol - * via serial communication and network socket I/O. + * via serial communication, network socket I/O, or direct USB I/O. + * + * These functions can *not* be used to access LANTIME NTP servers, + * or the modules assembled within a LANTIME since LANTIMEs are using + * this kind of communication only internally. + * + * Also, standalone USB devices are usually handled by the driver + * software package for the given operating system and thus can be + * accessed in the same way as PCI cards, using the API functions + * provided by the mbgdevio library. + * + * These functions can be used, however, with standalone devices + * which are accessible either directly via a serial port, or via a + * special serial-to-LAN converter like the meinberg LAN_XPT module. * * ----------------------------------------------------------------------- * $Log: mbgextio.c $ + * Revision 1.20.1.19 2015/07/22 16:02:07 martin + * Started to support variable USB endpoint numbers. + * Revision 1.20.1.18 2015/07/14 15:08:43 martin + * Unified parameter naming and updated doxygen comments. + * Revision 1.20.1.17 2015/07/14 14:05:55 martin + * Support XBP addressing. + * Added functions to read/send UTC parameters. + * Support for USB_DIRECT_IO + * Fixed dealloc_msg_ctl() where not all memory was freed. + * Reworked mbgextio_force_conn_serial_ftdi(). + * Revision 1.20.1.16 2014/10/30 16:03:05 martin + * Doxygen fixes. + * Revision 1.20.1.15 2014/10/30 14:45:55 martin + * Generally return Meinberg error codes only. + * Do not use GPS_REQACK for secu_settings. + * Added FTDI support functions. + * Reworked "force connection" functions, also supporting high speed now. + * Updated libusb support. + * Many new API functions. + * Revision 1.20.1.14 2013/11/28 15:51:45Z marvin + * Added mbgextio_get_ntp_peer_state_idx. + * Revision 1.20.1.13 2013/11/26 16:06:43Z marvin + * Added mbgextio_get_ntp_sys_state. + * Revision 1.20.1.12 2013/11/21 07:46:44Z marvin + * Added mbgextio_xmt_secu_settings. + * Cleanup for socket port. + * Revision 1.20.1.11 2013/11/15 12:17:30Z marvin + * Added error return for TGT_LINUX if socket_opt_error detected. + * Revision 1.20.1.10 2013/11/15 11:49:12Z marvin + * Fixed: return 0 if non_blocking_socket is OK. + * check if received GPS_NACK for encryption mode (socket connection). + * Revision 1.20.1.9 2013/11/13 16:30:10Z martin + * Revision 1.20.1.8 2013/11/13 16:13:26 martin + * Revision 1.20.1.7 2013/11/13 16:05:52 marvin + * Revision 1.20.1.6 2013/11/13 15:14:17Z martin + * Cleaned up socket connection code. + * Revision 1.20.1.5 2013/11/12 12:12:02 marvin + * Changed calls for NTP info and settings. + * Revision 1.20.1.4 2013/11/11 11:30:27Z marvin + * Changed socket connection. + * Revision 1.20.1.3 2013/11/05 15:53:11Z marvin + * Changed connecting via socket. + * Revision 1.20.1.2 2013/10/14 08:54:19Z marvin + * Added mbgextio_set_ntp_clnt_mode_cfg. + * Revision 1.20.1.1 2013/09/25 11:09:53Z marvin + * Added NTP support and new support for PTP. + * Revision 1.20 2013/09/10 08:56:35Z marvin + * Changed Doxygen comments. + * Revision 1.19 2013/09/05 15:10:39Z marvin + * Added support for LAN interface setup + * Added support for PTP state + * Added support for XMR. + * Revision 1.18 2013/09/02 15:16:48Z marvin + * Added support for XMR (get multi ref info, set multi ref settings) + * Revision 1.17 2013/08/28 11:01:41Z marvin + * Added read and set tr_distance and gnss_mode. + * Revision 1.16.1.1 2013/06/05 09:17:54Z marvin + * Changed close_connection for socket. + * Revision 1.16 2013/04/11 14:18:33Z Gregoire + * new calls for sending havequick rx and tx settings to clock + * Revision 1.15 2013/02/14 14:42:13Z martin + * Fixed syntax err due to unintentionally pasted word. + * Revision 1.14 2013/02/06 15:43:54 martin + * Updated doxygen comments. + * Revision 1.13 2013/02/01 15:58:43 martin + * In mbgextio_force_connection() for Windows wait until all chars + * must have been sent since flushing output buffer doesn't work reliably. + * Added a number of new functions. + * Added doxygen comments. + * Revision 1.12 2012/10/30 16:17:30 martin + * Started to migrate to opaque stuctures. + * Conditionally let xmt routines request for ACK packet, + * though this is by default disabled. + * Support receiving NACK status. + * Support big endian target platforms. + * Merged and adapted Daniel's USB support functions. + * Support event log entries. + * Syntax workaround which is required until this module becomes a DLL. + * Added some new functions. + * Updated doxygen comments. + * Huge cleanup. * Revision 1.11 2011/04/15 13:17:14 martin * Use common mutex support macros from mbgmutex.h. * Revision 1.10 2011/04/08 11:28:24 martin @@ -36,7 +130,7 @@ * Moved generic serial I/O stuff to mbgserio.c and mbgserio.h. * Restart reception if received msg does not match expected cmd code. * Fixed timeout value for Windows. - * New symbol _MBGEXTIO_DIRECT_RC controls whether the return code of the + * New symbol _MBGEXTIO_DIRECT_RC controls whether the return code of the * mbgextio_set_...() functions is evaluated or returned as-is. * New functions mbgextio_set_time(), mbgextio_set_tzdl(). * Added mbgextio_get_ucap(). This may not work with older firmware, @@ -60,30 +154,47 @@ #define _MBGEXTIO #include - - //##++ The following lines are required - // until mbgextio becomes a DLL: - #undef _MBG_API_ATTR - #define _MBG_API_ATTR #undef _MBGEXTIO #include +#include #include #include #include #include +#include -#if defined( MBG_TGT_UNIX ) - #include +#if defined( MBG_TGT_POSIX ) #include + #include #else typedef int ssize_t; #endif -#if !defined( MBGEXTIO_DIRECT_RC ) - #define _MBGEXTIO_DIRECT_RC 0 //##++ 1 +#if _USE_USB_IO + #include +#endif + +#if _USE_USB_DIRECT_IO + #include +#endif + +#if !defined( _MBGEXTIO_REQ_ACK ) + // If _MBGEXTIO_REQ_ACK is != 0 then mbgextio_...() functions writing + // configuration parameters send the cmd code with the ACK request bit set + // which lets mbgextio_xmt_msg() try to receive a response from the device + // after the parameters have been sent. + #define _MBGEXTIO_REQ_ACK 0 +#endif + +#if _MBGEXTIO_REQ_ACK + #define OPT_GPS_ACK_CODE GPS_REQACK +#else + #define OPT_GPS_ACK_CODE 0 // dummy #endif +#define DEBUG_SOCK_IO ( 1 && defined( DEBUG ) ) + // default serial message timeout #if !defined ( MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL ) @@ -96,6 +207,134 @@ #endif + +static const char force_conn_cmd_str[] = MBG_FORCE_CONN_CMD_STR; +static const char force_conn_hs_cmd_str[] = MBG_FORCE_CONN_HS_CMD_STR; + + +typedef struct +{ + int model_code; + long feature_mask; + +} BUILTIN_FEATURE_TABLE_ENTRY; + +static BUILTIN_FEATURE_TABLE_ENTRY builtin_feature_table[] = GPS_MODEL_BUILTIN_FEATURES; + + + +static /*HDR*/ +/** + * @brief Deallocate a message control structure + * + * Free the memory allocated for a message control structure + * and set the pointer to NULL. + * + * @param[in,out] ppmctl Address of a pointer to a message control structure + * + * @see ::alloc_msg_ctl + */ +void dealloc_msg_ctl( MBG_MSG_CTL **ppmctl ) +{ + MBG_MSG_CTL *pmctl = *ppmctl; + + if ( pmctl ) + { + if ( pmctl->rcv.pmb ) + { + free( pmctl->rcv.pmb ); + pmctl->rcv.pmb = NULL; + } + + pmctl->rcv.buf_size = 0; + + if ( pmctl->xmt.pmb ) + { + free( pmctl->xmt.pmb ); + pmctl->xmt.pmb = NULL; + } + + pmctl->xmt.buf_size = 0; + + free( pmctl ); + *ppmctl = NULL; + } + +} // dealloc_msg_ctl + + + +static /*HDR*/ +/** + * @brief Allocate a message control structure + * + * Allocate memory for a message control structure and associated + * message receive and transmit buffers. + * + * @param[out] ppmctl Address of a pointer to a message control structure to be allocated, set to NULL on error + * + * @return ::MBG_SUCCESS or one of the @ref MBG_ERROR_CODES + * + * @see ::dealloc_msg_ctl + */ +int alloc_msg_ctl( MBG_MSG_CTL **ppmctl ) +{ + int rc = MBG_ERR_UNSPEC; + + MBG_MSG_CTL *pmctl = malloc( sizeof( *pmctl ) ); + + if ( pmctl == NULL ) + { + #if defined( DEBUG ) + fprintf( stderr, "failed to malloc control block in %s\n", __func__ ); + #endif + goto fail; + } + + memset( pmctl, 0, sizeof( *pmctl ) ); + + // allocate receive buffer + pmctl->rcv.buf_size = sizeof( *(pmctl->rcv.pmb) ); + pmctl->rcv.pmb = malloc( pmctl->rcv.buf_size ); + + if ( pmctl->rcv.pmb == NULL ) + { + #if defined( DEBUG ) + fprintf( stderr, "failed to malloc rcv buffer in %s\n", __func__ ); + #endif + goto fail; + } + + // allocate transmit buffer + pmctl->xmt.buf_size = sizeof( *(pmctl->xmt.pmb) ); + pmctl->xmt.pmb = malloc( pmctl->xmt.buf_size ); + + if ( pmctl->xmt.pmb == NULL ) + { + #if defined( DEBUG ) + fprintf( stderr, "failed to malloc xmt buffer in %s\n", __func__ ); + #endif + goto fail; + } + + + // buffers allocated successfully + rc = MBG_SUCCESS; + goto out; + + +fail: // if not all memory blocks could be allocated, clean up + dealloc_msg_ctl( &pmctl ); // also sets pmctl to NULL + rc = MBG_ERR_NO_MEM; + +out: + *ppmctl = pmctl; + return rc; + +} // alloc_msg_ctl + + + #if defined( MBG_TGT_WIN32 ) && _USE_SOCKET_IO static /*HDR*/ @@ -134,25 +373,299 @@ void mbgextio_set_console_control_handler( void ) - #if _USE_SOCKET_IO static /*HDR*/ +/** + * @brief Set the blocking mode of a network socket + * + * @param[in] sock_fd The socket descriptor + * @param[in] blocking Blocking mode, 0: non-blocking, else blocking + * + * @return One of the @ref MBG_RETURN_CODES + */ +int set_socket_blocking_mode( MBG_SOCK_FD sock_fd, int blocking ) +{ + int rc = MBG_ERR_UNSPEC; + + if ( sock_fd == MBG_INVALID_SOCK_FD ) + { + rc = MBG_ERR_INV_SOCK_FD; + goto out; + } + + #if defined( MBG_TGT_WIN32 ) + { + u_long mode = blocking ? 0 : 1; // ioctlsocket expects an (u_long *) + + rc = ioctlsocket( sock_fd, FIONBIO, &mode ); // returns 0 on success + + if ( rc != 0 ) // error + { + rc = mbg_get_last_socket_error( "ioctlsocket(FIONBIO) failed in set_socket_blocking_mode" ); + goto out; + } + } + #elif defined( MBG_TGT_POSIX ) + { + int val = fcntl( sock_fd, F_GETFL, 0 ); // returns -1 on error + + if ( val == -1 ) + { + rc = mbg_get_last_socket_error( "fcntl(F_GETFL) failed in set_socket_blocking_mode" ); + goto out; + } + + if ( blocking ) + val &= ~O_NONBLOCK; + else + val |= O_NONBLOCK; + + rc = fcntl( sock_fd, F_SETFL, val ); // returns -1 on error + + if ( rc == -1 ) + { + rc = mbg_get_last_socket_error( "fcntl(F_SETFL) failed in set_socket_blocking_mode" ); + goto out; + } + } + #else + { + rc = MBG_ERR_NOT_SUPP_ON_OS; + goto out; + } + #endif + + rc = MBG_SUCCESS; + +out: + return rc; + +} // set_socket_blocking_mode + + + +static /*HDR*/ +/** + * @brief Get last socket error code converted to @ref MBG_RETURN_CODES + * + * @param[in] sock_fd The socket descriptor + * + * @return One of the @ref MBG_RETURN_CODES + */ +int get_sock_error( MBG_SOCK_FD sock_fd ) +{ + int so_err = 0; + socklen_t so_err_sz = sizeof( so_err ); + int rc = getsockopt( sock_fd, SOL_SOCKET, SO_ERROR, (void *) &so_err, &so_err_sz ); // returns 0 on success + + if ( rc != 0 ) // error + { + rc = mbg_get_last_socket_error( "getsockopt SO_ERROR failed in get_sock_error" ); + goto out; + } + + if ( so_err_sz != sizeof( so_err ) ) // might have been modified by getsockopt() + { + fprintf( stderr, "Warning: getsockopt option size changed in get_sock_error: %li -> %li", + (long) sizeof( so_err ), (long) so_err_sz ); + rc = MBG_ERR_UNSPEC; + goto out; + } + + if ( so_err != 0 ) // error + { + #if defined( MBG_TGT_WIN32 ) + rc = mbg_win32_wsa_err_to_mbg( so_err, "wait failed in wait_nonblocking_socket_ready" ); + #elif defined( MBG_TGT_POSIX ) + rc = mbg_posix_errno_to_mbg( so_err, "wait failed in wait_nonblocking_socket_ready" ); + #else + #error This function is not supported for this target. + #endif + goto out; + } + + rc = MBG_SUCCESS; + +out: + return rc; + +} // get_sock_error + + + +static /*HDR*/ +/** + * @brief Wait for a non-blocking socket to get ready after a connect() call + * + * A connect() call to a socket which is not available can fail + * after a pretty long timeout which usually can't be changed. + * + * A workaround is to switch the socket to non-blocking mode, + * then call connect(), then do a select() with specified timeout, + * and finally switch the socket back to blocking mode. + * + * @param[in] sock_fd The socket descriptor + * + * @return One of the @ref MBG_RETURN_CODES + */ +int wait_nonblocking_socket_ready( MBG_SOCK_FD sock_fd, long timeout_msec ) +{ + // At least under Windows a select call can set except_fds if + // the non-blocking attempt to connect fails. + // See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx + // Linux and FreeBSD suggest to use write_fds only. + #define USE_EXCEPT_FDS_WITH_CONNECT ( 1 || defined( MBG_TGT_WIN32 ) ) //##+++++++++++++++++++++++++++ + + fd_set write_fds; + #if USE_EXCEPT_FDS_WITH_CONNECT + fd_set except_fds; + #endif + int max_fd; + struct timeval tv_timeout; + int rc = MBG_ERR_UNSPEC; + + mbg_msec_to_timeval( timeout_msec, &tv_timeout ); + + FD_ZERO( &write_fds ); + FD_SET( sock_fd, &write_fds ); + + #if defined( MBG_TGT_WIN32 ) + // Under Windows an fd is a handle which can't simply + // be converted to an int, but the first argument of + // select() is ignored under Windows anyway, so we just + // set max_fd to 0. + max_fd = 0; + #else + max_fd = sock_fd; + #endif + + #if USE_EXCEPT_FDS_WITH_CONNECT + FD_ZERO( &except_fds ); + FD_SET( sock_fd, &except_fds ); + rc = select( max_fd + 1, NULL, &write_fds, &except_fds, &tv_timeout ); + #else + rc = select( max_fd + 1, NULL, &write_fds, NULL, &tv_timeout ); + #endif + + if ( rc == MBG_SOCKET_ERR_RETVAL ) // < 0, error + { + rc = mbg_get_last_socket_error( "select failed in wait_nonblocking_socket_ready" ); + goto out; + } + + if ( rc == 0 ) // timeout + { + #if DEBUG_SOCK_IO + fprintf( stderr, "select timed out in wait_nonblocking_socket_ready" ); + #endif + rc = MBG_ERR_NBLOCK_WAIT_SLCT; + goto out; + } + + #if USE_EXCEPT_FDS_WITH_CONNECT + // The except_fds might be set if no connection could be + // established if e.g. the target socket is already busy. + if ( FD_ISSET( sock_fd, &except_fds ) ) + { + rc = get_sock_error( sock_fd ); + goto out; + } + #endif + + // Usually the write_fds are checked to see if the + // non-blocking connect() call completed successfully, + // in which case the associated descriptor is set. + if ( !FD_ISSET( sock_fd, &write_fds ) ) + { + #if DEBUG_SOCK_IO + fprintf( stderr, "write_fd is not set after select in wait_nonblocking_socket_ready" ); + #endif + rc = MBG_ERR_NBLOCK_WAIT_WR_FD; + goto out; + } + + #if defined( MBG_TGT_LINUX ) + // From the connect(2) man page: + // After select(2) indicates writability, use getsockopt(2) to read + // the SO_ERROR option at level SOL_SOCKET to determine whether connect() + // completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR + // is one of the usual error codes, explaining the reason for the failure). + rc = get_sock_error( sock_fd ); + goto out; + #endif + + rc = MBG_SUCCESS; + +out: + return rc; + +} // wait_nonblocking_socket_ready + + + +static /*HDR*/ +/** + * @brief Close a socket and make the socket descriptor invalid + * + * @param[in,out] pmctl Pointer to a valid message control structure containing the socket descriptor + * + * @return One of the @ref MBG_RETURN_CODES + */ +int socket_close( MBG_MSG_CTL *pmctl ) +{ + int rc; + + #if defined( MBG_TGT_CVI ) || defined( MBG_TGT_WIN32 ) + rc = closesocket( pmctl->st.sockio.sockfd ); // returns 0 on success + #elif defined( MBG_TGT_POSIX ) + rc = close( pmctl->st.sockio.sockfd ); // returns 0 on success + #else + #error close socket needs to be implemented for this target + #endif + + pmctl->st.sockio.sockfd = MBG_INVALID_SOCK_FD; + + if ( rc != 0 ) + { + rc = mbg_get_last_socket_error( "failed to close socket socket_close" ); + goto out; + } + + rc = MBG_SUCCESS; + +out: + return rc; + +} // socket_close + + + +static /*HDR*/ +/** + * @brief Initialize a socket connection to a specified host + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] host Host name or IP address of the target system + * + * @return One of the @ref MBG_RETURN_CODES + */ int socket_init( MBG_MSG_CTL *pmctl, const char *host ) { struct hostent *hp; struct sockaddr_in *paddr; const struct sockaddr *p; int sz; - int rc; + int rc = MBG_ERR_UNSPEC; + //##++++++++ should use getaddrinfo() preferably hp = gethostbyname( host ); #if defined( MBG_TGT_WIN32 ) + // Under Windows the winsock2.dll may not yet have been initialized, + // so initialize now and try once more. if ( hp == NULL ) { - // The winsock2.dll may not yet have been initialized, - // so try to initialize now. WORD wVersionRequested; WSADATA wsaData; @@ -160,22 +673,37 @@ int socket_init( MBG_MSG_CTL *pmctl, const char *host ) rc = WSAStartup( wVersionRequested, &wsaData ); - // If initialization has succeeded, try again. + // If initialization has succeeded, try once more. if ( rc == 0 ) hp = gethostbyname( host ); } #endif // defined( MBG_TGT_WIN32 ) - if ( hp == NULL ) - return TR_OPEN_ERR; - + if ( hp == NULL ) // error + { + rc = mbg_get_gethostbyname_error( "gethostbyname failed in socket_init" ); + goto out; + } - // create socket on which to send. + // Create socket on which to send. pmctl->st.sockio.sockfd = socket( PF_INET, SOCK_STREAM, 0 ); - if ( pmctl->st.sockio.sockfd == INVALID_SOCKET ) - return TR_OPEN_ERR; + if ( pmctl->st.sockio.sockfd == MBG_INVALID_SOCK_FD ) + { + rc = mbg_get_last_socket_error( "failed to create socket in socket_init" ); + goto out; + } + + // Set the socket to nonblocking mode to be able to + // reduce the timeout when connecting to a socket + // which is offline. + rc = set_socket_blocking_mode( pmctl->st.sockio.sockfd, 0 ); + + if ( rc != MBG_SUCCESS ) + goto out_close; + + // Now try to connect to the socket. paddr = &pmctl->st.sockio.addr; memset( paddr, 0, sizeof( *paddr ) ); @@ -186,65 +714,174 @@ int socket_init( MBG_MSG_CTL *pmctl, const char *host ) p = (const struct sockaddr *) paddr; sz = sizeof( *paddr ); - rc = connect( pmctl->st.sockio.sockfd, p, sz ); + rc = connect( pmctl->st.sockio.sockfd, p, sz ); // returns 0 on success on Windows and Linux - if ( rc < 0 ) - return TR_OPEN_ERR; + // In nonblocking mode connect() might complete successfully + // if the destination socket is on the same machine (localhost) + // However, for remote connections the call usually returns + // immediately with WSAEWOULDBLOCK on Windows, or EINPROGRESS or + // EALREADY on POSIX systems. In the latter cases we need to wait + // and see if the connection can be established successfully. + + if ( rc != 0 ) // eventually not (yet) completed in non-blocking mode + { + #if defined( MBG_TGT_WIN32 ) + DWORD wsa_err = WSAGetLastError(); + + // WSAEWOULDBLOCK is actually not an error in non-blocking mode + if ( wsa_err != WSAEWOULDBLOCK ) + { + rc = mbg_win32_wsa_err_to_mbg( wsa_err, "connect failed in socket_init" ); + goto out_close; + } + #else // POSIX ... + int posix_errno = errno; + + // EINPROGRESS and EALREADY are actually not errors in non-blocking mode + if ( ( posix_errno != EINPROGRESS ) && ( posix_errno != EALREADY ) ) + { + rc = mbg_posix_errno_to_mbg( posix_errno, "connect failed in socket_init" ); + goto out_close; + } + #endif + + rc = wait_nonblocking_socket_ready( pmctl->st.sockio.sockfd, 1500 ); //##++++++++++++ + + if ( rc != MBG_SUCCESS ) + goto out_close; + } + + // Set the socket back to blocking mode. + rc = set_socket_blocking_mode( pmctl->st.sockio.sockfd, 1 ); + + if ( rc == MBG_SUCCESS ) + goto out; + + // error, fall through and close socket - return 0; +out_close: + socket_close( pmctl ); + +out: + return rc; } // socket_init -static /*HDR*/ -int comm_init( MBG_MSG_CTL *pmctl, const char *passwd ) +/*HDR*/ +/** + * @brief Send security settings for the socket connection + * + * If new_passwd is not a NULL pointer, the old_passwd + * will be overwritten by the new_passwd. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] old_passwd Pointer to the current LAN port password of the device + * @param[in] new_passwd Pointer to the new LAN port password for the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_socket + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_secu_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, + const char *old_passwd, const char *new_passwd ) { - SECU_SETTINGS *pss = &pmctl->secu_settings; MBG_MSG_BUFF *pmb; - int rc; + SECU_SETTINGS *pss = &pmctl->secu_settings; + GPS_CMD cmd = GPS_SECU_SETTINGS; // GPS_REQACK is not supported by LAN_XPT, so omit it + int rc = MBG_ERR_UNSPEC; memset( pss, 0, sizeof *pss ); - strncpy( pss->password, passwd, sizeof( pss->password ) ); + strncpy( pss->password, old_passwd, sizeof( pss->password ) ); - pmctl->conn_type = MBG_CONN_TYPE_SOCKET; - pmctl->msg_rcv_timeout = MBGEXTIO_RCV_TIMEOUT_SOCKET; - // pmctl->char_rcv_timeout is not used with sockets + set_encryption_mode( pmctl, MBG_XFER_MODE_ENCRYPTED, pss->password ); + + if ( new_passwd ) + { + if ( strlen( new_passwd ) > 0 ) + strncpy( pss->new_password, new_passwd, sizeof( pss->new_password ) ); - set_encryption_mode( pmctl, MBG_XFER_MODE_ENCRYTED, pss->password ); + pss->flags |= MSK_FLAG_CHANGE_PASSWORD; + } pmb = pmctl->xmt.pmb; pmb->u.msg_data.secu_settings = *pss; - pmb->hdr.cmd = GPS_SECU_SETTINGS; + pmb->hdr.cmd = cmd; pmb->hdr.len = sizeof( pmb->u.msg_data.secu_settings ); - xmt_tbuff( pmctl ); - rc = mbgextio_rcv_msg( pmctl, GPS_SECU_SETTINGS ); + rc = xmt_tbuff( pmctl, NULL ); //##++++++++++++++ TODO Use mbgextio_req_data instead? Is NULL OK? + + if ( rc != MBG_SUCCESS ) // error + goto out; + + rc = mbgextio_rcv_msg( pmctl, NULL, cmd ); //##++++++++++++++ TODO Is NULL OK? - if ( rc != TR_COMPLETE ) - return -1; /* connection refused */ + // With some devices a timeout may also occur + // if a wrong password has been used. + if ( rc != MBG_SUCCESS ) // error + goto out; - pmb = pmctl->rcv.pmb; + cmd = pmctl->rcv.pmb->hdr.cmd; - if ( !( pmb->hdr.cmd & GPS_ACK ) ) - return -2; /* authentication failed */ + // If we either received a reply with GPS_NACK, or + // without GPS_ACK, the password was definitely wrong. + if ( ( cmd & GPS_NACK ) || !( cmd & GPS_ACK ) ) + { + rc = MBG_ERR_AUTH; + goto out; + } - return 0; + rc = MBG_SUCCESS; + +out: + return rc; -} // comm_init +} // mbgextio_xmt_secu_settings /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl, - const char *host, const char *passwd ) +/** + * @brief Open a binary communication channel via a LAN/socket connection + * + * @param[in] host DNS name or IP address of the target device + * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure + * allocated and set up by this call. + * Pointer is set to NULL on error. + * @param[in] passwd Password string for the encrypted communication + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_serial + * @see ::mbgextio_open_serial_ftdi + * @see ::mbgextio_open_usb + * @see ::mbgextio_open_usb_direct_io + * @see ::mbgextio_close_connection + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_open_socket( const char *host, MBG_MSG_CTL **ppmctl, const char *passwd ) { - int rc = socket_init( pmctl, host ); + MBG_MSG_CTL *pmctl; + int rc = alloc_msg_ctl( &pmctl ); - if ( rc < 0 ) - return rc; + if ( rc != MBG_SUCCESS ) + goto out; + + + pmctl->conn_type = MBG_CONN_TYPE_SOCKET; + pmctl->msg_rcv_timeout = MBGEXTIO_RCV_TIMEOUT_SOCKET; + // pmctl->char_rcv_timeout is not used with sockets + + rc = socket_init( pmctl, host ); + + if ( rc != MBG_SUCCESS ) + goto fail_free; + + rc = mbgextio_xmt_secu_settings( pmctl, NULL, passwd, NULL ); - comm_init( pmctl, passwd ); + if ( rc != MBG_SUCCESS ) + goto fail_close; #if defined( MBG_TGT_WIN32 ) mbgextio_set_console_control_handler(); @@ -254,6 +891,18 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl, _mbg_mutex_init( &pmctl->xmt.xmt_mutex ); #endif + rc = MBG_SUCCESS; + goto out; + +fail_close: + socket_close( pmctl ); + +fail_free: + dealloc_msg_ctl( &pmctl ); + +out: + *ppmctl = pmctl; + return rc; } // mbgextio_open_socket @@ -265,10 +914,39 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl, #if _USE_SERIAL_IO /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_open_serial( MBG_MSG_CTL *pmctl, const char *dev, - uint32_t baud_rate, const char *framing ) +/** + * @brief Open a binary communication channel using direct serial I/O + * + * Commonly used serial parameters are 19200/8N1, see + * ::MBG_DEFAULT_BAUDRATE and ::MBG_DEFAULT_FRAMING. + * Some newer devices may also support ::MBG_DEFAULT_BAUDRATE_HS. + * + * @param[in] dev Name of the serial port to which the device is connected, + * depending on the naming conventions of the host system. + * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure + * allocated and set up by this call. Set to NULL on error. + * @param[in] baud_rate Baud rate used for serial communication + * @param[in] framing Framing used for serial communication + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_force_conn_serial + * @see ::mbgextio_open_serial_ftdi + * @see ::mbgextio_force_conn_serial_ftdi + * @see ::mbgextio_open_socket + * @see ::mbgextio_open_usb + * @see ::mbgextio_open_usb_direct_io + * @see ::mbgextio_close_connection + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_open_serial( const char *dev, MBG_MSG_CTL **ppmctl, + uint32_t baud_rate, const char *framing ) { - int rc; + MBG_MSG_CTL *pmctl; + int rc = alloc_msg_ctl( &pmctl ); + + if ( rc != MBG_SUCCESS ) + goto out; + pmctl->conn_type = MBG_CONN_TYPE_SERIAL; pmctl->msg_rcv_timeout = MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL; @@ -276,16 +954,28 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_serial( MBG_MSG_CTL *pmctl, const char rc = mbgserio_open( &pmctl->st.serio, dev ); - if ( rc < 0 ) //##++ - return rc; + if ( rc != MBG_SUCCESS ) + goto fail_free; + + rc = mbgserio_set_parms( &pmctl->st.serio, baud_rate, framing ); - mbgserio_set_parms( &pmctl->st.serio, baud_rate, framing ); + if ( rc != MBG_SUCCESS ) + goto fail_free; #if _USE_MUTEX _mbg_mutex_init( &pmctl->xmt.xmt_mutex ); #endif - return 0; + rc = MBG_SUCCESS; + goto out; + +fail_free: + dealloc_msg_ctl( &pmctl ); + +out: + *ppmctl = pmctl; + + return rc; } // mbgextio_open_serial @@ -293,1218 +983,4611 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_serial( MBG_MSG_CTL *pmctl, const char +#if _USE_SERIAL_IO_FTDI + /*HDR*/ -_MBG_API_ATTR void _MBG_API mbgextio_close_connection( MBG_MSG_CTL *pmctl ) +/** + * @brief Get the port handle of a serial FTDI device + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return the port handle retrieved from the message control structure + */ +_NO_MBG_API_ATTR FT_HANDLE _MBG_API mbgextio_get_serial_ftdi_port_handle( MBG_MSG_CTL *pmctl ) { - switch ( pmctl->conn_type ) - { - #if _USE_SERIAL_IO - case MBG_CONN_TYPE_SERIAL: - { - #if defined( MBG_TGT_UNIX ) - tcsetattr( pmctl->st.serio.port_handle, TCSANOW, &pmctl->st.serio.oldtio ); - #endif + return pmctl->st.ftdiio.port_handle; - mbgserio_close( &pmctl->st.serio ); - } break; - #endif // _USE_SERIAL_IO +} // mbgextio_get_serial_ftdi_port_handle - #if _USE_SOCKET_IO - case MBG_CONN_TYPE_SOCKET: - { - _mbg_close( pmctl->st.sockio.sockfd ); - pmctl->st.sockio.sockfd = 0; - } break; - #endif // _USE_SOCKET_IO - }; // switch - #if _USE_MUTEX - _mbg_mutex_destroy( &pmctl->xmt.xmt_mutex ); - #endif +/*HDR*/ +/** + * @brief Open a binary communication channel using serial FTDI D2xx port + * + * Commonly used serial parameters are 19200/8N1, see + * ::MBG_DEFAULT_BAUDRATE and ::MBG_DEFAULT_FRAMING. + * Some newer devices may also support ::MBG_DEFAULT_BAUDRATE_HS. + * + * @param[in] device_num device number from a list set up by FT_ListDevices() + * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure + * allocated and set up by this call. Set to NULL on error. + * @param[in] baud_rate Baud rate used for serial communication + * @param[in] framing Framing used for serial communication + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_force_conn_serial_ftdi + * @see ::mbgextio_open_serial + * @see ::mbgextio_force_conn_serial + * @see ::mbgextio_open_socket + * @see ::mbgextio_open_usb + * @see ::mbgextio_open_usb_direct_io + * @see ::mbgextio_close_connection + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_open_serial_ftdi( int device_num, + MBG_MSG_CTL **ppmctl, uint32_t baud_rate, const char *framing ) +{ + FT_STATUS status; + ULONG ft_baud; + UCHAR ft_data_bits; + UCHAR ft_stopbits; + UCHAR ft_parity; + const char *cp; + MBG_MSG_CTL *pmctl; + int rc = alloc_msg_ctl( &pmctl ); -} // mbgextio_close_connection + if ( rc != MBG_SUCCESS ) + goto out; + pmctl->conn_type = MBG_CONN_TYPE_SERIAL_FTDI; + pmctl->msg_rcv_timeout = MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL; + pmctl->char_rcv_timeout = MBGEXTIO_CHAR_RCV_TIMEOUT_SERIAL; + + status = FT_Open( device_num, &pmctl->st.ftdiio.port_handle ); -#if _USE_SERIAL_IO + if ( status != FT_OK ) + goto ft_fail_free; -/*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_force_connection( const char *dev ) -{ - static const char *cmd_str = "\nDFC\n"; //##++ - MBG_MSG_CTL mctl = + // setup transmission speed + switch( baud_rate ) { - { NULL, 0 }, - { NULL, 0 } - }; + case 300: ft_baud = FT_BAUD_300; break; + case 600: ft_baud = FT_BAUD_600; break; + case 1200: ft_baud = FT_BAUD_1200; break; + case 2400: ft_baud = FT_BAUD_2400; break; + case 4800: ft_baud = FT_BAUD_4800; break; + case 9600: ft_baud = FT_BAUD_9600; break; + case 14400: ft_baud = FT_BAUD_14400; break; + case 19200: ft_baud = FT_BAUD_19200; break; + case 38400: ft_baud = FT_BAUD_38400; break; + case 57600: ft_baud = FT_BAUD_57600; break; + case 115200: ft_baud = FT_BAUD_115200; break; + case 230400: ft_baud = FT_BAUD_230400; break; + case 460800: ft_baud = FT_BAUD_460800; break; + case 921600: ft_baud = FT_BAUD_921600; break; + + default: + rc = MBG_ERR_INV_PARM; + goto fail_free; + } - int i; - int j; - int len = strlen( cmd_str ); - for ( i = 0; i < N_MBG_BAUD_RATES; i++ ) + // setup framing + for ( cp = framing; *cp; cp++ ) { - for ( j = 0; j < N_MBG_FRAMINGS; j++ ) - { - uint32_t baud_rate = mbg_baud_rates[i]; - const char *framing = mbg_framing_strs[j]; - int rc = mbgextio_open_serial( &mctl, dev, baud_rate, framing ); + char c = toupper( *cp ); - if ( rc != 0 ) // failed to open port - return -1; + switch ( c ) + { + case '7': ft_data_bits = FT_BITS_7; break; + case '8': ft_data_bits = FT_BITS_8; break; - _mbgserio_write( mctl.st.serio.port_handle, cmd_str, len ); + case 'N': ft_parity = FT_PARITY_NONE; break; + case 'E': ft_parity = FT_PARITY_EVEN; break; + case 'O': ft_parity = FT_PARITY_ODD; break; + // FT_PARITY_MARK and FT_PARITY_SPACE not supp. by Meinberg API - #if defined( MBG_TGT_UNIX ) - tcdrain( mctl.st.serio.port_handle ); - #elif defined( MBG_TGT_CVI ) - //##++++ - #elif defined( MBG_TGT_WIN32 ) - FlushFileBuffers( mctl.st.serio.port_handle ); - #endif + case '1': ft_stopbits = FT_STOP_BITS_1; break; + case '2': ft_stopbits = FT_STOP_BITS_2; break; - mbgextio_close_connection( &mctl ); + default: + rc = MBG_ERR_INV_PARM; + goto fail_free; } } - return 0; -} // mbgextio_force_connection + status = FT_SetBaudRate( pmctl->st.ftdiio.port_handle, ft_baud ); -#endif // _USE_SERIAL_IO + if ( status != FT_OK ) + goto ft_fail_free; + status = FT_SetDataCharacteristics( pmctl->st.ftdiio.port_handle, + ft_data_bits, ft_stopbits, ft_parity ); + if ( status != FT_OK ) + goto ft_fail_free; -/*HDR*/ -_MBG_API_ATTR void _MBG_API mbgextio_set_char_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) -{ - pmctl->char_rcv_timeout = new_timeout; -} // mbgextio_set_char_rcv_timeout + #if _USE_MUTEX + _mbg_mutex_init( &pmctl->xmt.xmt_mutex ); + #endif + rc = MBG_SUCCESS; + goto out; -/*HDR*/ -_MBG_API_ATTR ulong _MBG_API mbgextio_get_char_rcv_timeout( const MBG_MSG_CTL *pmctl ) -{ - return pmctl->char_rcv_timeout; +ft_fail_free: + rc = mbg_ftdi_ft_status_to_mbg( status ); -} // mbgextio_get_char_rcv_timeout +fail_free: + dealloc_msg_ctl( &pmctl ); +out: + *ppmctl = pmctl; + return rc; -/*HDR*/ -_MBG_API_ATTR void _MBG_API mbgextio_set_msg_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) -{ - pmctl->msg_rcv_timeout = new_timeout; +} // mbgextio_open_serial_ftdi -} // mbgextio_set_msg_rcv_timeout +#endif +#if _USE_USB_IO + /*HDR*/ -_MBG_API_ATTR ulong _MBG_API mbgextio_get_msg_rcv_timeout( const MBG_MSG_CTL *pmctl ) +/** + * @brief Open a binary communication channel using direct USB I/O + * + * @param[in] usbdev The USB device to communicate with. + * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure + * allocated and set up by this call. Set to NULL on error. + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_socket + * @see ::mbgextio_open_serial + * @see ::mbgextio_open_serial_ftdi + * @see ::mbgextio_close_connection + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_open_usb( const MBG_USB_DEVICE *usbdev, MBG_MSG_CTL **ppmctl ) { - return pmctl->msg_rcv_timeout; + MBG_MSG_CTL *pmctl; + int rc = alloc_msg_ctl( &pmctl ); -} // mbgextio_get_msg_rcv_timeout + if ( rc != MBG_SUCCESS ) + goto out; + pmctl->conn_type = MBG_CONN_TYPE_USB; + pmctl->msg_rcv_timeout = MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL; + pmctl->char_rcv_timeout = MBGEXTIO_CHAR_RCV_TIMEOUT_SERIAL; -/*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd, - const void *p, int n_bytes ) -{ - MBG_MSG_BUFF *pmb; + pmctl->st.usbio = usbdev->iost; - if ( n_bytes > sizeof( pmb->u.msg_data ) ) - return -1; // bytes to send exceed buffer size + rc = mbgusbio_open( &pmctl->st.usbio ); + if ( rc != MBG_SUCCESS ) + goto fail_free; #if _USE_MUTEX - _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + _mbg_mutex_init( &pmctl->xmt.xmt_mutex ); #endif - pmb = pmctl->xmt.pmb; + rc = MBG_SUCCESS; + goto out; - if ( p && n_bytes ) - memcpy( pmb->u.bytes, p, n_bytes ); - pmb->hdr.len = n_bytes; - pmb->hdr.cmd = cmd; - xmt_tbuff( pmctl ); +fail_free: + dealloc_msg_ctl( &pmctl ); - #if _USE_MUTEX - _mbg_mutex_release( &pmctl->xmt.xmt_mutex ); - #endif +out: + *ppmctl = pmctl; - if ( cmd & GPS_REQACK ) - { - int rc = mbgextio_rcv_msg( pmctl, (GPS_CMD) ( cmd & ~GPS_CTRL_MSK ) ); + return rc; - if ( rc != TR_COMPLETE ) - return -2; +} // mbgextio_open_usb - if ( pmctl->rcv.pmb->hdr.cmd & GPS_NACK ) - return -3; +#endif - if ( !(pmctl->rcv.pmb->hdr.cmd & GPS_ACK) ) - return -4; + + +#if _USE_USB_DIRECT_IO + +/*HDR*/ +/** + * @brief Open a binary communication channel using direct USB I/O + * + * Currently it is only supported by Linux systems since a file like + * USB device (e.g. "/dev/mbgims") is required and needs to support + * basic I/O operations like write, read, etc... + * + * @param[in] dev Path to file like USB device + * @param[in] flags Bitwise OR flags of access modes like W,RW,RO,etc. + * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure + * allocated and set up by this call. Set to NULL on error. + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_socket + * @see ::mbgextio_open_serial + * @see ::mbgextio_open_serial_ftdi + * @see ::mbgextio_open_usb + * @see ::mbgextio_open_usb_direct_io + * @see ::mbgextio_close_connection + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_open_usb_direct_io( const char *dev, int flags, MBG_MSG_CTL **ppmctl ) +{ + MBG_MSG_CTL *pmctl; + int rc; + + if ( dev == NULL ) + return MBG_ERR_NO_DEV; + + rc = alloc_msg_ctl( &pmctl ); + if ( rc != MBG_SUCCESS ) + goto out; + + pmctl->conn_type = MBG_CONN_TYPE_USB_DIRECT_IO; + pmctl->msg_rcv_timeout = MBGEXTIO_RCV_TIMEOUT_USB_DIRECT_IO; + + pmctl->st.usbdio.usbdiofd = open(dev, flags); + + if ( pmctl->st.usbdio.usbdiofd == MBG_USB_DIRECT_IO_INVALID_FD ) + { + rc = mbg_get_last_error( "failed to open direct USB I/O device" ); + goto fail_free; } + rc = MBG_SUCCESS; + goto out; - return 0; +fail_free: + dealloc_msg_ctl( &pmctl ); -} // mbgextio_xmt_msg +out: + *ppmctl = pmctl; + + return rc; + +} // mbgextio_open_usb_direct_io + +#endif /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) +/** + * @brief Close a binary communication channel and release resources + * + * Closes a binary communication channel which has been opened by one + * of the mbgextio_open_...() functions and releases the buffers which + * have been allocated when the channel was opened. + * + * The pointer to the message control structure passed by address is set + * to NULL after the channel has been closed and the resources have + * been released. + * + * @param[in,out] ppmctl Address of a pointer to a message control structure + * created when the communication channel was opened + * by one of the mbgextio_open_...() calls. + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_socket + * @see ::mbgextio_open_serial + * @see ::mbgextio_open_serial_ftdi + * @see ::mbgextio_open_usb + * @see ::mbgextio_open_usb_direct_io + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_close_connection( MBG_MSG_CTL **ppmctl ) { - MBG_MSG_RCV_CTL *prctl; - MBG_MSG_BUFF *pmb; - MBG_TMO_TIME msg_timeout; - char buff[MBGEXTIO_READ_BUFFER_SIZE]; - ssize_t n_bytes; - int rc; - int i; + MBG_MSG_CTL *pmctl = *ppmctl; + int rc = MBG_ERR_UNSPEC; - mbg_tmo_set_timeout_ms( &msg_timeout, pmctl->msg_rcv_timeout ); - - for (;;) // loop until complete msg received + switch ( pmctl->conn_type ) { - n_bytes = 0; + #if _USE_SERIAL_IO + case MBG_CONN_TYPE_SERIAL: + rc = mbgserio_close( &pmctl->st.serio ); + break; + #endif // _USE_SERIAL_IO - if ( mbg_tmo_curr_time_is_after( &msg_timeout ) ) - return TR_TIMEOUT; + #if _USE_SERIAL_IO_FTDI + case MBG_CONN_TYPE_SERIAL_FTDI: + { + FT_STATUS status = FT_Close( pmctl->st.ftdiio.port_handle ); + pmctl->st.ftdiio.port_handle = MBG_INVALID_PORT_HANDLE; + rc = mbg_ftdi_ft_status_to_mbg( status ); + } break; + #endif // _USE_SERIAL_IO_FTDI #if _USE_SOCKET_IO - if ( pmctl->conn_type == MBG_CONN_TYPE_SOCKET ) - { - struct timeval tv_timeout; - fd_set fds; + case MBG_CONN_TYPE_SOCKET: + rc = socket_close( pmctl ); + break; + #endif // _USE_SOCKET_IO - if ( pmctl->io_error ) - return TR_IO_ERR; + #if _USE_USB_IO + case MBG_CONN_TYPE_USB: + rc = mbgusbio_close( &pmctl->st.usbio ); + break; + #endif // _USE_USB_IO - mbgserio_msec_to_timeval( pmctl->msg_rcv_timeout, &tv_timeout ); + #if _USE_USB_DIRECT_IO + case MBG_CONN_TYPE_USB_DIRECT_IO: + if ( pmctl->st.usbdio.usbdiofd == MBG_USB_DIRECT_IO_INVALID_FD ) + { + rc = MBG_SUCCESS; + break; + } - FD_ZERO( &fds ); - FD_SET( pmctl->st.sockio.sockfd, &fds ); + rc = close( pmctl->st.usbdio.usbdiofd ); - rc = select( pmctl->st.sockio.sockfd + 1, &fds, NULL, NULL, &tv_timeout ); + if ( rc < 0 ) + rc = mbg_get_last_error( "failed to close direct USB I/O device" ); + else + rc = MBG_SUCCESS; + #endif // _USE_USB_DIRECT_IO - if ( rc == 0 ) // timeout - return TR_TIMEOUT; + default: + rc = MBG_ERR_CONN_TYPE; - if ( rc < 0 ) // error - { - pmctl->io_error = 1; - return TR_IO_ERR; - } + } // switch - // data is available + #if _USE_MUTEX + _mbg_mutex_destroy( &pmctl->xmt.xmt_mutex ); + #endif - n_bytes = recv( pmctl->st.sockio.sockfd, buff, sizeof( buff ), 0 ); + dealloc_msg_ctl( ppmctl ); - if ( n_bytes < 0 ) - { - pmctl->io_error = 1; - return TR_IO_ERR; - } - } - #endif // _USE_SOCKET_IO + return rc; - #if _USE_SERIAL_IO - if ( pmctl->conn_type == MBG_CONN_TYPE_SERIAL ) - { - n_bytes = mbgserio_read_wait( pmctl->st.serio.port_handle, &buff[0], - sizeof( buff[0] ), pmctl->char_rcv_timeout ); +} // mbgextio_close_connection - if ( n_bytes < 0 ) - { - if ( n_bytes == MBGSERIO_TIMEOUT ) - return TR_TIMEOUT; - pmctl->io_error = 1; - return TR_IO_ERR; - } - } - #endif // _USE_SERIAL_IO - prctl = &pmctl->rcv; - pmb = prctl->pmb; +#if _USE_SERIAL_IO - for ( i = 0; i < n_bytes; i++ ) +static /*HDR*/ +int do_force_conn_serial( const char *dev, const char *cmd_str, BAUD_RATE expected_baudrate ) +{ + int i; + int j; + MBG_MSG_CTL *pmctl; + int len = (int) strlen( cmd_str ); + int rc = MBG_ERR_UNSPEC; + + for ( i = 0; i < N_MBG_BAUD_RATES; i++ ) + { + for ( j = 0; j < N_MBG_FRAMINGS; j++ ) { - char c = buff[i]; + uint32_t baud_rate = mbg_baud_rates[i]; + const char *framing = mbg_framing_strs[j]; - /* check if the new char belongs to a data transfer sequence */ - rc = check_transfer( prctl, c ); + rc = mbgextio_open_serial( dev, &pmctl, baud_rate, framing ); - switch ( rc ) - { - case TR_WAITING: /* no data transfer sequence in progress */ - #if _USE_CHK_TSTR - if ( prctl->chk_tstr_fnc ) /* optionally handle normal, non-protocol data */ - prctl->chk_tstr_fnc( c, prctl->chk_tstr_arg ); - #endif - // intentional fall-through + if ( rc != MBG_SUCCESS ) // failed to open port + goto out; - case TR_RECEIVING: /* data transfer sequence in progress, keep waiting */ - continue; + mbgserio_write( pmctl->st.serio.port_handle, cmd_str, len ); + // should we check rc here or just continue? - case TR_COMPLETE: - { - uint16_t rcvd_cmd = pmb->hdr.cmd & ~GPS_CTRL_MSK; + #ifdef MBG_TGT_WIN32 + // Flushing the output when the serial port is closed doesn't + // always work correctly under Windows, so we insert a delay + // here to make sure the string has been set. + // The required delay depends on the number of characters to + // send, and on the transmission speed (baud rate). + Sleep( ( ( 10 * 1000 * len ) / baud_rate ) + 1 ); + #endif - if ( rcvd_cmd == cmd ) /* the received packet is what we've been waiting for */ - return TR_COMPLETE; + mbgextio_close_connection( &pmctl ); + } + } - #if _USE_ENCRYPTION - /* if an encrypted packet has been received then decrypt it */ - if ( rcvd_cmd == GPS_CRYPTED_PACKET ) - { - rc = decrypt_message( pmctl ); + rc = mbgextio_open_serial( dev, &pmctl, expected_baudrate, MBG_DEFAULT_FRAMING ); - if ( rc < 0 ) /* decryption error */ - return rc; + if ( rc != MBG_SUCCESS ) // failed to open port + goto out; - rcvd_cmd = pmb->hdr.cmd & ~GPS_CTRL_MSK; + rc = mbgextio_get_receiver_info( pmctl, NULL, NULL ); - if ( rcvd_cmd == cmd ) /* the received packet is what we've been waiting for */ - return TR_COMPLETE; - } - #endif + mbgextio_close_connection( &pmctl); - /* not waiting for a specific packet, so return if any packet is complete */ - if ( cmd == (uint16_t) -1 ) - return TR_COMPLETE; +out: + return rc; - //##++ received a msg which does not match the expected code - prctl->cnt = 0; /* restart receiving */ - } - break; +} // do_force_conn_serial - default: /* any error condition */ - return rc; - } /* switch */ + +/*HDR*/ +/** + * @brief Try to force a serial connection to a device + * + * A device's serial port may have been configured to work by default + * in a way which is not appropriate for binary communication, e.g. using + * a low communication speed, or some framing like "7E2" which messes up + * binary data since the parity bit overrides a data bit. + * + * This function sends a special ASCII string to a device which lets the device + * temporarily switch to a specific baud rate and 8N1 framing which is usually + * used for binary communication, see ::MBG_DEFAULT_BAUDRATE, + * ::MBG_DEFAULT_BAUDRATE_HS, and ::MBG_DEFAULT_FRAMING. + * + * Since the current settings of the device's serial port are unknown this + * this command is sent in all common combinations of baud rates and + * framings. + * + * If the connected device supports this it should be possible to open + * the serial communication channel using the default parameters after + * this function has finished. + * + * @param[in] dev Name of the serial port to which the device is connected, + * depending on the naming conventions of the target system + * + * @return One of the negative @ref MBG_ERROR_CODES on error, + * else the determined baud rate. + * + * @see ::mbgextio_open_serial + * @see ::mbgextio_open_serial_ftdi + */ +_NO_MBG_API_ATTR long _MBG_API mbgextio_force_conn_serial( const char *dev ) +{ + long rc = do_force_conn_serial( dev, force_conn_hs_cmd_str, MBG_DEFAULT_BAUDRATE_HS ); + + if ( rc == MBG_SUCCESS ) + return MBG_DEFAULT_BAUDRATE_HS; + + rc = do_force_conn_serial( dev, force_conn_cmd_str, MBG_DEFAULT_BAUDRATE ); + + if ( rc == MBG_SUCCESS ) + return MBG_DEFAULT_BAUDRATE; + + return rc; + +} // mbgextio_force_conn_serial + +#endif // _USE_SERIAL_IO + + + +#if _USE_SERIAL_IO_FTDI + +static /*HDR*/ +int do_force_conn_serial_ftdi( int device_num, const char *cmd_str, BAUD_RATE expected_baudrate ) +{ + int i; + int j; + MBG_MSG_CTL *pmctl; + int len = (int) strlen( force_conn_cmd_str ); + long rc = MBG_ERR_UNSPEC; + + for ( i = 0; i < N_MBG_BAUD_RATES; i++ ) + { + for ( j = 0; j < N_MBG_FRAMINGS; j++ ) + { + uint32_t baud_rate = mbg_baud_rates[i]; + const char *framing = mbg_framing_strs[j]; + DWORD bytes_written; + FT_HANDLE port_handle; + FT_STATUS status; + + rc = mbgextio_open_serial_ftdi( device_num, &pmctl, baud_rate, framing ); + + if ( rc != MBG_SUCCESS ) // failed to open port + goto out; + + port_handle = pmctl->st.ftdiio.port_handle; + + status = FT_Write( port_handle, (LPVOID) force_conn_cmd_str, len, &bytes_written ); + + #if 0 //##+++++++++++ do we need some error checking here? + if ( status != FT_OK ) + { + rc = mbg_ftdi_ft_status_to_mbg( status ); + goto out; + } + + if ( bytes_written != sizeof( len ) ) + goto out_write_failed; + #endif + + #ifdef MBG_TGT_WIN32 + #if 1 + // TODO Check if this works as expected + status = FT_Purge( port_handle, FT_PURGE_TX ); + #else + + // Flushing the output when the serial port is closed doesn't + // always work correctly under Windows, so we insert a delay + // here to make sure the string has been set. + // The required delay depends on the number of characters to + // send, and on the transmission speed (baud rate). + Sleep( ( ( 10 * 1000 * len ) / baud_rate ) + 1 ); + #endif + #endif + + mbgextio_close_connection( &pmctl ); } } -} // mbgextio_rcv_msg + rc = mbgextio_open_serial_ftdi( device_num, &pmctl, expected_baudrate, MBG_DEFAULT_FRAMING ); + if ( rc != MBG_SUCCESS ) // failed to open port + goto out; + rc = mbgextio_get_receiver_info( pmctl, NULL, NULL ); -/*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) + mbgextio_close_connection( &pmctl ); + +out: + return rc; + +} // do_force_conn_serial_ftdi + + + +/*HDR*/ +/** + * @brief Try to force a serial connection to a device via the FTDI API + * + * A device's serial port may have been configured to work by default + * in a way which is not appropriate for binary communication, e.g. using + * a low communication speed, or some framing like "7E2" which messes up + * binary data since the parity bit overrides a data bit. + * + * This function sends a special ASCII string to a device which lets the device + * temporarily switch to a specific baud rate and 8N1 framing which is usually + * used for binary communication, see ::MBG_DEFAULT_BAUDRATE, + * ::MBG_DEFAULT_BAUDRATE_HS, and ::MBG_DEFAULT_FRAMING. + * + * Since the current settings of the device's serial port are unknown this + * this command is sent in all common combinations of baud rates and + * framings. + * + * If the connected device supports this it should be possible to open + * the serial communication channel using the default parameters after + * this function has finished. + * + * @param[in] device_num device number from a list set up by FT_ListDevices() + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_serial_ftdi + */ +_NO_MBG_API_ATTR long _MBG_API mbgextio_force_conn_serial_ftdi( int device_num ) +{ + long rc = do_force_conn_serial_ftdi( device_num, force_conn_hs_cmd_str, MBG_DEFAULT_BAUDRATE_HS ); + + if ( rc == MBG_SUCCESS ) + return MBG_DEFAULT_BAUDRATE_HS; + + rc = do_force_conn_serial_ftdi( device_num, force_conn_cmd_str, MBG_DEFAULT_BAUDRATE ); + + if ( rc == MBG_SUCCESS ) + return MBG_DEFAULT_BAUDRATE; + + return rc; + +} // mbgextio_force_conn_serial_ftdi + +#endif // _USE_SERIAL_IO_FTDI + + + +/*HDR*/ +/** + * @brief Retrieve address of the allocated receive buffer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Address of the allocated receive buffer + * + * @see ::mbgextio_get_rcv_buffer_size + * @see ::mbgextio_get_xmt_buffer_addr + * @see ::mbgextio_get_xmt_buffer_size + */ +_NO_MBG_API_ATTR MBG_MSG_BUFF * _MBG_API mbgextio_get_rcv_buffer_addr( MBG_MSG_CTL *pmctl ) +{ + if ( pmctl == NULL ) + return NULL; + + return pmctl->rcv.pmb; + +} // mbgextio_get_rcv_buffer_addr + + + +/*HDR*/ +/** + * @brief Retrieve size of the allocated receive buffer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Size of the allocated receive buffer + * + * @see ::mbgextio_get_rcv_buffer_addr + * @see ::mbgextio_get_xmt_buffer_addr + * @see ::mbgextio_get_xmt_buffer_size + */ +_NO_MBG_API_ATTR size_t _MBG_API mbgextio_get_rcv_buffer_size( MBG_MSG_CTL *pmctl ) +{ + if ( pmctl == NULL ) + return 0; + + return sizeof( *pmctl->rcv.pmb ); + +} // mbgextio_get_rcv_buffer_size + + + +/*HDR*/ +/** + * @brief Retrieve address of the allocated transmit buffer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Address of the allocated transmit buffer + * + * @see ::mbgextio_get_rcv_buffer_addr + * @see ::mbgextio_get_rcv_buffer_size + * @see ::mbgextio_get_xmt_buffer_size + */ +_NO_MBG_API_ATTR MBG_MSG_BUFF * _MBG_API mbgextio_get_xmt_buffer_addr( MBG_MSG_CTL *pmctl ) +{ + if ( pmctl == NULL ) + return NULL; + + return pmctl->xmt.pmb; + +} // mbgextio_get_xmt_buffer_addr + + + +/*HDR*/ +/** + * @brief Retrieve size of the allocated transmit buffer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Size of the allocated transmit buffer + * + * @see ::mbgextio_get_rcv_buffer_addr + * @see ::mbgextio_get_rcv_buffer_size + * @see ::mbgextio_get_xmt_buffer_addr + */ +_NO_MBG_API_ATTR size_t _MBG_API mbgextio_get_xmt_buffer_size( MBG_MSG_CTL *pmctl ) +{ + if ( pmctl == NULL ) + return 0; + + return sizeof( *pmctl->xmt.pmb ); + +} // mbgextio_get_xmt_buffer_size + + + +/*HDR*/ +/** + * @brief Set character receive timeout value + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] new_timeout New timeout value [ms] + * + * @see ::mbgextio_get_char_rcv_timeout + * @see ::mbgextio_set_msg_rcv_timeout + * @see ::mbgextio_get_msg_rcv_timeout + */ +_NO_MBG_API_ATTR void _MBG_API mbgextio_set_char_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) +{ + pmctl->char_rcv_timeout = new_timeout; + +} // mbgextio_set_char_rcv_timeout + + + +/*HDR*/ +/** + * @brief Get character receive timeout value + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Current timeout value [ms] + * + * @see ::mbgextio_set_char_rcv_timeout + * @see ::mbgextio_set_msg_rcv_timeout + * @see ::mbgextio_get_msg_rcv_timeout + */ +_NO_MBG_API_ATTR ulong _MBG_API mbgextio_get_char_rcv_timeout( const MBG_MSG_CTL *pmctl ) +{ + return pmctl->char_rcv_timeout; + +} // mbgextio_get_char_rcv_timeout + + + +/*HDR*/ +/** + * @brief Set message receive timeout value + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] new_timeout New timeout value [ms] + * + * @see ::mbgextio_set_char_rcv_timeout + * @see ::mbgextio_get_char_rcv_timeout + * @see ::mbgextio_get_msg_rcv_timeout + */ +_NO_MBG_API_ATTR void _MBG_API mbgextio_set_msg_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) +{ + pmctl->msg_rcv_timeout = new_timeout; + +} // mbgextio_set_msg_rcv_timeout + + + +/*HDR*/ +/** + * @brief Get message receive timeout value + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Current timeout value [ms] + * + * @see ::mbgextio_set_char_rcv_timeout + * @see ::mbgextio_get_char_rcv_timeout + * @see ::mbgextio_set_msg_rcv_timeout + */ +_NO_MBG_API_ATTR ulong _MBG_API mbgextio_get_msg_rcv_timeout( const MBG_MSG_CTL *pmctl ) +{ + return pmctl->msg_rcv_timeout; + +} // mbgextio_get_msg_rcv_timeout + + + +/*HDR*/ +/** + * @brief Generic reception of a binary message + * + * @note A certain message type to be waited for can be specified by + * passing one of the ::GPS_CMD_CODES. + * If the special cmd code ::GPS_WILDCARD is specified the function returns + * successfully after *any* type of binary message has been received. + * + * //##++ TODO: callback function to handle asynchronous spontaneous messages + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES, or ::GPS_WILDCARD + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_rcv_msg + * @see ::mbgextio_xmt_msg //##++++ + * @see ::mbgextio_xmt_cmd + * @see ::mbgextio_req_data + * @see ::mbgextio_xmt_cmd_us + * @see ::mbgextio_req_data_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd ) +{ + MBG_MSG_RCV_CTL *prctl; + MBG_MSG_BUFF *pmb; + MBG_TMO_TIME msg_timeout; + char buff[MBGEXTIO_READ_BUFFER_SIZE]; + ssize_t n_bytes = 0; + int rc = MBG_ERR_UNSPEC; + int i; + + mbg_tmo_set_timeout_ms( &msg_timeout, pmctl->msg_rcv_timeout ); + + for (;;) // loop until complete msg received + { + n_bytes = 0; + + if ( mbg_tmo_curr_time_is_after( &msg_timeout ) ) + { + rc = MBG_ERR_TIMEOUT; + goto out; + } + + switch ( pmctl->conn_type ) + { + #if _USE_SOCKET_IO + case MBG_CONN_TYPE_SOCKET: + { + struct timeval tv_timeout; + fd_set fds; + int max_fd; + + mbg_msec_to_timeval( pmctl->msg_rcv_timeout, &tv_timeout ); + + FD_ZERO( &fds ); + FD_SET( pmctl->st.sockio.sockfd, &fds ); + + #if defined( MBG_TGT_WIN32 ) + // Under Windows an fd is a handle which can't simply + // be converted to an int, but the first argument of + // select() is ignored under Windows anyway, so we just + // set max_fd to 0. + max_fd = 0; + #else + max_fd = pmctl->st.sockio.sockfd; + #endif + + rc = select( max_fd + 1, &fds, NULL, NULL, &tv_timeout ); + + if ( rc == MBG_SOCKET_ERR_RETVAL ) // < 0, error + { + rc = mbg_get_last_socket_error( "select failed in mbgextio_rcv_msg" ); + goto out; + } + + if ( rc == 0 ) // timeout + { + rc = MBG_ERR_TIMEOUT; + goto out; + } + + // data is available + + n_bytes = recv( pmctl->st.sockio.sockfd, buff, sizeof( buff ), 0 ); + + if ( n_bytes < 0 ) + { + rc = mbg_get_last_socket_error( "recv failed in mbgextio_rcv_msg" ); + goto out; + } + + } break; + #endif // _USE_SOCKET_IO + + #if _USE_SERIAL_IO + case MBG_CONN_TYPE_SERIAL: + { + n_bytes = mbgserio_read_wait( pmctl->st.serio.port_handle, &buff[0], + sizeof( buff[0] ), pmctl->char_rcv_timeout ); + + if ( n_bytes < 0 ) + { + rc = n_bytes; + goto out; + } + + } break; + #endif // _USE_SERIAL_IO + + #if _USE_SERIAL_IO_FTDI + case MBG_CONN_TYPE_SERIAL_FTDI: + { + DWORD bytes_read; + FT_STATUS status; + + //##++++++ pmctl->char_rcv_timeout, + status = FT_Read( pmctl->st.ftdiio.port_handle, &buff[0], + sizeof( buff[0] ), &bytes_read ); + + if ( status != FT_OK ) + { + rc = mbg_ftdi_ft_status_to_mbg( status ); + goto out; + } + + n_bytes = bytes_read; + + } break; + #endif // _USE_SERIAL_IO_FTDI + + #if _USE_USB_IO + case MBG_CONN_TYPE_USB: + { + rc = mbgusbio_read( &pmctl->st.usbio, (uint8_t *) buff, sizeof( buff ), 1000 ); + + if ( rc < 0 ) + goto out; + + // data is available + + n_bytes = rc; + + } break; + #endif // _USE_USB_IO + + #if _USE_USB_DIRECT_IO + case MBG_CONN_TYPE_USB_DIRECT_IO: + { + struct pollfd pfd; + + pfd.fd = pmctl->st.usbdio.usbdiofd; + pfd.events = POLLIN | POLLRDNORM | POLLRDBAND; + pfd.revents = 0; + + rc = poll( &pfd, 1, pmctl->msg_rcv_timeout); + + if ( rc == 0 ) // timeout + { + rc = MBG_ERR_TIMEOUT; + goto out; + } + + if ( rc < 0 ) // error + { + rc = mbg_get_last_error( "failed to poll direct USB I/O" ); + goto out; + } + + // Other stuff? + if ( pfd.revents & ( POLLERR | POLLHUP | POLLNVAL ) ) + { + rc = MBG_ERR_UNSPEC; + goto out; + } + + // Read data? + if ( pfd.revents & ( POLLIN | POLLRDNORM | POLLRDBAND ) ) + { + rc = read( pmctl->st.usbdio.usbdiofd, (void*)buff, sizeof(buff) ); + + if ( rc < 0 ) + { + rc = mbg_get_last_error( "failed to read direct USB I/O" ); + goto out; + } + + n_bytes = rc; + } + } break; + #endif + + default: + rc = MBG_ERR_CONN_TYPE; + goto out; + + } // switch + + prctl = &pmctl->rcv; + pmb = prctl->pmb; + + for ( i = 0; i < n_bytes; i++ ) + { + char c = buff[i]; + + /* check if the new char belongs to a data transfer sequence */ + rc = check_transfer( prctl, c ); + + switch ( rc ) + { + case TR_WAITING: /* no data transfer sequence in progress */ + #if _USE_CHK_TSTR + if ( prctl->chk_tstr_fnc ) /* optionally handle normal, non-protocol data */ + { + int tstr_rc = prctl->chk_tstr_fnc( c, prctl->chk_tstr_arg ); + + if ( tstr_rc > 0 ) // a valid time string has been received + { + // return only if the caller does not wait for a specific packet type + if ( cmd == GPS_WILDCARD ) + return TR_COMPLETE_TSTR; //##++++++++++++++++++++ TODO better way to detect string + } + } + #endif + // intentional fall-through + + case TR_RECEIVING: /* data transfer sequence in progress, keep waiting */ + continue; + + case TR_COMPLETE: + { + GPS_CMD rcvd_cmd; + + #if _USE_CHK_TSTR + //##+++++++++++++++++ + // If a valid binary packet has been received then discard + // a partial time string possibly received before. + #endif + + rcvd_cmd = pmb->hdr.cmd & ~GPS_CTRL_MSK; + + if ( rcvd_cmd == cmd ) /* the received packet is what we've been waiting for */ + { + if ( pmb->hdr.cmd & GPS_NACK ) + { + rc = MBG_ERR_RCVD_NACK; + goto out; + } + + rc = MBG_SUCCESS; + goto out; + } + + #if _USE_ENCRYPTION + /* if an encrypted packet has been received then decrypt it */ + if ( rcvd_cmd == GPS_CRYPTED_PACKET ) + { + rc = decrypt_message( pmctl ); + + if ( rc < 0 ) /* decryption error */ + goto out; + + rcvd_cmd = pmb->hdr.cmd & ~GPS_CTRL_MSK; + + if ( pmb->hdr.cmd & GPS_NACK ) + { + rc = MBG_ERR_RCVD_NACK; + goto out; + } + + if ( rcvd_cmd == cmd ) /* the received packet is what we've been waiting for */ + { + rc = MBG_SUCCESS; + goto out; + } + } + #endif + + /* not waiting for a specific packet, so return if any packet is complete */ + if ( cmd == GPS_WILDCARD ) + { + rc = MBG_SUCCESS; + goto out; + } + + //##++ received a msg which does not match the expected code + prctl->cnt = 0; /* restart receiving */ + } + break; + + case TR_CSUM_HDR: + rc = MBG_ERR_HDR_CSUM; + goto out; + + case TR_CSUM_DATA: + rc = MBG_ERR_DATA_CSUM; + goto out; + + default: /* any error condition */ + rc = MBG_ERR_UNSPEC; //##+++++++++++++++++++++ use detailed rc + goto out; + + } /* switch */ + } + } + +out: + return rc; + +} // mbgextio_rcv_msg + + + +/*HDR*/ +/** + * @brief Set up and send a generic binary message + * + * @note This function should preferably be used only as low level function + * called from within more specific functions used to send specific data. + * If this function is called directly with a buffer to be sent then the + * transmit mutex is acquired by this function. However, other (higher level) + * API functions which set up the transmit buffer directly have to acquire + * the transmit mutex by themselves before they set up the transmit buffer, + * and pass a NULL pointer to indicate the transmit buffer has already been + * set up. The correct number of bytes to send (n_bytes) has to be specified + * anyway, though. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * @param[in] p Address of a data structure according to the specified cmd parameter, or NULL + * @param[in] n_bytes Size of the data structure addressed by parameter p + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, + GPS_CMD cmd, const void *p, uint16_t n_bytes ) +{ + MBG_MSG_BUFF *pmb; + int rc = MBG_ERR_UNSPEC; + + if ( n_bytes > sizeof( pmb->u.msg_data ) ) + { + rc = MBG_ERR_OVERFLOW; // bytes to send exceed transmit buffer size + goto out; + } + + + pmb = pmctl->xmt.pmb; + + if ( p ) + { + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + memcpy( pmb->u.bytes, p, n_bytes ); + } + + pmb->hdr.len = n_bytes; + pmb->hdr.cmd = cmd; + rc = xmt_tbuff( pmctl, p_addr ); + + #if _USE_MUTEX + _mbg_mutex_release( &pmctl->xmt.xmt_mutex ); + #endif + + if ( rc != MBG_SUCCESS ) // error + goto out; + + + // If an acknowledge has been requested + // wait for a reply and check it. + if ( cmd & GPS_REQACK ) + { + rc = mbgextio_rcv_msg( pmctl, p_addr, (GPS_CMD) ( cmd & ~GPS_CTRL_MSK ) ); + + if ( rc != MBG_SUCCESS ) + { + //##++++++++++ rc = ... eventually return a different error code + goto out; + } + + if ( pmctl->rcv.pmb->hdr.cmd & GPS_NACK ) + { + rc = MBG_ERR_RCVD_NACK; + goto out; + } + + if ( !(pmctl->rcv.pmb->hdr.cmd & GPS_ACK) ) + rc = MBG_ERR_RCVD_NO_ACK; + } + +out: + return rc; + +} // mbgextio_xmt_msg + + + +/*HDR*/ +/** + * @brief Transmit a command-only message without additional data. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_xmt_msg + * @see ::mbgextio_rcv_msg + * @see ::mbgextio_req_data + * @see ::mbgextio_xmt_cmd_us + * @see ::mbgextio_req_data_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd ) +{ + int rc; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + rc = xmt_cmd( pmctl, p_addr, cmd ); + + #if _USE_MUTEX + _mbg_mutex_release( &pmctl->xmt.xmt_mutex ); + #endif + + return rc; + +} // mbgextio_xmt_cmd + + + +/*HDR*/ +/** + * @brief Transmit a message without a single ushort (uint16_t) parameter + * + * The ushort parameter is often used to send an index value when requesting + * a certain element of an array of same data structures. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * @param[in] us The ushort parameter for the command code + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_xmt_msg + * @see ::mbgextio_rcv_msg + * @see ::mbgextio_xmt_cmd + * @see ::mbgextio_req_data + * @see ::mbgextio_req_data_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd, uint16_t us ) +{ + int rc; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + rc = xmt_cmd_us( pmctl, p_addr, cmd, us ); + + #if _USE_MUTEX + _mbg_mutex_release( &pmctl->xmt.xmt_mutex ); + #endif + + return rc; + +} // mbgextio_xmt_cmd_us + + + +/*HDR*/ +/** + * @brief Transmit a message without a single ushort (16 bit) parameter + * + * The ushort parameter is often used to send an index value when requesting + * a specific element of an array of data structures. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_xmt_msg + * @see ::mbgextio_rcv_msg + * @see ::mbgextio_xmt_cmd + * @see ::mbgextio_xmt_cmd_us + * @see ::mbgextio_req_data_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_req_data( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd ) +{ + int rc = xmt_cmd( pmctl, p_addr, cmd ); /* request a set of data */ + + if ( rc != MBG_SUCCESS ) // error + goto out; + + rc = mbgextio_rcv_msg( pmctl, p_addr, cmd ); + +out: + return rc; + +} // mbgextio_req_data + + + +/*HDR*/ +/** + * @brief Read a specific element of an array of data structures + * + * The type of data is implicitely associated with the cmd parameter. + * Usually the number of supported array elements has to be determined + * by some other means, e.g. from a field in the ::RECEIVER_INFO structure. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * @param[in] idx The index of the array element to read + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_xmt_msg + * @see ::mbgextio_rcv_msg + * @see ::mbgextio_xmt_cmd + * @see ::mbgextio_req_data + * @see ::mbgextio_xmt_cmd_us + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_req_data_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, + GPS_CMD cmd, uint16_t idx ) +{ + int rc = xmt_cmd_us( pmctl, p_addr, cmd, idx ); // send a request for a set of data + + if ( rc < 0 ) // error + goto out; + + rc = mbgextio_rcv_msg( pmctl, p_addr, cmd ); // wait for the reply + +out: + return rc; + +} // mbgextio_req_data_idx + + + + +/*HDR*/ +/** + * @brief Read a receiver info structure + * + * The ::RECEIVER_INFO should be read at first to identify the connected + * device and determine the basic features supported by the device. + * + * @note Some very old devices may not provide a ::RECEIVER_INFO, + * so ::mbgextio_setup_receiver_info should be called preferably + * to read the receiver info using this function, if supported, + * or set up a default structure for devices which don't provide + * a receiver info. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_setup_receiver_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_receiver_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, RECEIVER_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_RECEIVER_INFO ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.receiver_info; + _mbg_swab_receiver_info( p ); + } + + return rc; + +} // mbgextio_get_receiver_info + + + +/*HDR*/ +/** + * @brief Setup a receiver info structure + * + * The ::RECEIVER_INFO should be read at first to identify the connected + * device and determine the basic features supported by the device. + * + * @note Some very old devices may not provide a ::RECEIVER_INFO. + * This function tries to read the ::RECEIVER_INFO from the device, + * and sets up a default structure if the device doesn't support this. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_receiver_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_setup_receiver_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, RECEIVER_INFO *p ) +{ + int rc = mbgextio_get_receiver_info( pmctl, p_addr, p ); + + if ( rc == MBG_SUCCESS ) //##++++++++++++++ or in all cases except of MBG_ERR_TIMEOUT ? + goto out; + + //##+++++++++++++ TODO try to read SW_REV, etc., evt. depending on p_addr == NULL or not + +out: + return rc; + +} // mbgextio_setup_receiver_info + + + +/*HDR*/ +/** + * @brief Read the software revision + * + * @deprecated This function is deprecated since the ::SW_REV structure + * is also a member of the ::RECEIVER_INFO. This call may be required, + * though, for very old devices which don't support the ::RECEIVER_INFO. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_setup_receiver_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_sw_rev( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, SW_REV *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_SW_REV ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.sw_rev; + _mbg_swab_sw_rev( p ); + } + + return rc; + +} // mbgextio_get_sw_rev + + + +/*HDR*/ +/** + * @brief Read the status of buffered variables + * + * @note Only supported if ::GPS_MODEL_HAS_BVAR_STAT + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_bvar_stat( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, BVAR_STAT *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_BVAR_STAT ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.bvar_stat; + _mbg_swab_bvar_stat( p ); + } + + return rc; + +} // mbgextio_get_bvar_stat + + + +/*HDR*/ +/** + * @brief Read the current time as ::TTM strucure + * + * @note This function is only supported by GPS receivers. + * + * The returned time is not very accurate since the response time + * transmission delay can't be determmined. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_time( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, TTM *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_TIME ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ttm; + _mbg_swab_ttm( p ); + } + + return rc; + +} // mbgextio_get_time + + + +/*HDR*/ +/** + * @brief Set the device's time by sending a ::TTM strucure + * + * @note The function is not supported by all devices. Time has to be + * passed as local time according to the device's ::TZDL settings. + * New time is only set with some tens of ms accuracy. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_time( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const TTM *p ) +{ + GPS_CMD cmd = GPS_TIME | OPT_GPS_ACK_CODE; + TTM *p_data = &pmctl->xmt.pmb->u.msg_data.ttm; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_ttm( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_time + + + +/*HDR*/ +/** + * @brief Set the device's position by sending an ::LLA array + * + * @note This function is only supported by GPS receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] lla Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_pos_lla( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const LLA lla ) +{ + GPS_CMD cmd = GPS_POS_LLA | OPT_GPS_ACK_CODE; + double *p_lla = pmctl->xmt.pmb->u.msg_data.lla; + int i; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + for ( i = 0; i < N_LLA; i++ ) + { + p_lla[i] = lla[i]; + swap_double( &p_lla[i] ); + _mbg_swab_double( &p_lla[i] ); + } + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( LLA ) ); + +} // mbgextio_set_pos_lla + + + +/*HDR*/ +/** + * @brief Read the current receiver position as ::LLA array + * + * @note This function is only supported by GPS receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] lla Pointer to the data array to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, LLA lla ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_POS_LLA ); + + if ( ( rc == MBG_SUCCESS ) && lla ) + { + MSG_DATA *pmb = &pmctl->rcv.pmb->u.msg_data; + int i; + + for ( i = 0; i < N_LLA; i++ ) + { + swap_double( &pmb->lla[i] ); + lla[i] = pmb->lla[i]; + } + } + + return rc; + +} // mbgextio_get_pos_lla + + + +/*HDR*/ +/** + * @brief Read the current receiver position as ::XYZ array + * + * @note This function is only supported by GPS receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] xyz Pointer to the data array to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_pos_xyz( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, XYZ xyz ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_POS_XYZ ); + + if ( ( rc == MBG_SUCCESS ) && xyz ) + { + MSG_DATA *pmb = &pmctl->rcv.pmb->u.msg_data; + int i; + + for ( i = 0; i < N_XYZ; i++ ) + { + swap_double( &pmb->xyz[i] ); + xyz[i] = pmb->xyz[i]; + } + } + + return rc; + +} // mbgextio_get_pos_xyz + + + +/*HDR*/ +/** + * @brief Read the current receiver position as ::POS structure + * + * @note This function is only supported by GPS receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p_pos Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_pos( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, POS *p_pos ) +{ + int rc = mbgextio_get_pos_xyz( pmctl, p_addr, p_pos->xyz ); + + if ( rc != MBG_SUCCESS ) + goto out; + + + rc = mbgextio_get_pos_lla( pmctl, p_addr, p_pos->lla ); + + if ( rc != MBG_SUCCESS ) + goto out; + + lla_to_dms( p_pos ); + +out: + return rc; + +} // mbgextio_get_pos + + + +/*HDR*/ +/** + * @brief Read the local time conversion parameters in ::TZDL format + * + * @note Some devices may not support ::TZDL settings + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_tzdl( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, TZDL *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_TZDL ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.tzdl; + _mbg_swab_tzdl( p ); + } + + return rc; + +} // mbgextio_get_tzdl + + + +/*HDR*/ +/** + * @brief Set the local time conversion parameters in ::TZDL format + * + * @note Some devices may not support ::TZDL settings + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_tzdl( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const TZDL *p ) +{ + GPS_CMD cmd = GPS_TZDL | OPT_GPS_ACK_CODE; + TZDL *p_data = &pmctl->xmt.pmb->u.msg_data.tzdl; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_tzdl( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_tzdl + + + +/*HDR*/ +/** + * @brief Read serial port parameters in ::PORT_PARM format + * + * @deprecated This function is deprecated since the ::PORT_PARM structure + * supports only 2 serial ports, and does not not support configuration + * of a string type. The function ::mbgextio_get_serial_settings should + * be used instead. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_serial_settings + * @see ::mbgextio_save_serial_settings + * @see ::mbgextio_set_port_parm + * @see ::mbgextio_setup_receiver_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_port_parm( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, PORT_PARM *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_PORT_PARM ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.port_parm; + _mbg_swab_port_parm( p ); + } + + return rc; + +} // mbgextio_get_port_parm + + + +/*HDR*/ +/** + * @brief Send serial port parameters in ::PORT_PARM format + * + * @deprecated This function is deprecated since the ::PORT_PARM structure + * supports only 2 serial ports, and does not not support configuration + * of a string type. The function ::mbgextio_save_serial_settings should + * be used instead. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_serial_settings + * @see ::mbgextio_save_serial_settings + * @see ::mbgextio_get_port_parm + * @see ::mbgextio_setup_receiver_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_port_parm( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const PORT_PARM *p ) +{ + GPS_CMD cmd = GPS_PORT_PARM | OPT_GPS_ACK_CODE; + PORT_PARM *p_data = &pmctl->xmt.pmb->u.msg_data.port_parm; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_port_parm( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_port_parm + + + +/*HDR*/ +/** + * @brief Read the frequency synthesizer settings + * + * @note Some devices may not provide a frequency synthesizer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_synth + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_synth( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, SYNTH *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_SYNTH ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.synth; + _mbg_swab_synth( p ); + } + + return rc; + +} // mbgextio_get_synth + + + +/*HDR*/ +/** + * @brief Write the frequency synthesizer settings + * + * @note Some devices may not provide a frequency synthesizer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_synth + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_synth( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const SYNTH *p ) +{ + GPS_CMD cmd = GPS_SYNTH | OPT_GPS_ACK_CODE; + SYNTH *p_data = &pmctl->xmt.pmb->u.msg_data.synth; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_synth( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_synth + + + +/*HDR*/ +/** + * @brief Read the GPS antenna info structure + * + * @note This is only supported by GPS receivers. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ant_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, ANT_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_ANT_INFO ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ant_info; + _mbg_swab_ant_info( p ); + } + + return rc; + +} // mbgextio_get_ant_info + + + +/*HDR*/ +/** + * @brief Read a user capture event in ::TTM format + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_clr_ucap_buff + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, TTM *p ) +{ + int rc = xmt_cmd( pmctl, p_addr, GPS_UCAP ); /* request a set of data */ + + if ( rc != MBG_SUCCESS ) + goto out; + + // Attention: Older firmware versions may reply with GPS_TIME + // messages instead of GPS_UCAP messages, and may not send a reply + // at all if no capture event is available in the on-board FIFO. + for (;;) + { + rc = mbgextio_rcv_msg( pmctl, p_addr, -1 ); + + if ( rc != MBG_SUCCESS ) + goto out; + + if ( pmctl->rcv.pmb->hdr.cmd == GPS_UCAP ) + break; + + if ( pmctl->rcv.pmb->hdr.cmd == GPS_TIME ) + if ( pmctl->rcv.pmb->hdr.len > 0 ) + if ( pmctl->rcv.pmb->u.msg_data.ttm.channel >= 0 ) + break; + } + + if ( p ) + { + // If the length of the msg header is 0 then the capture buffer + // is empty. This is indicated with 0xFF in the seconds field of + // the GPS time structure. + if ( pmctl->rcv.pmb->hdr.len > 0 ) + { + *p = pmctl->rcv.pmb->u.msg_data.ttm; + _mbg_swab_ttm( p ); + } + else + _ttm_time_set_unavail( p ); // no capture event available + } + +out: + return rc; + +} // mbgextio_get_ucap + + + +/*HDR*/ +/** + * @brief Read the enable flags controlling when output signals are enabled + * + * @note Some devices may not support ::ENABLE_FLAGS + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_enable_flags + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_enable_flags( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, ENABLE_FLAGS *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_ENABLE_FLAGS ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.enable_flags; + _mbg_swab_enable_flags( p ); + } + + return rc; + +} // mbgextio_get_enable_flags + + + +/*HDR*/ +/** + * @brief Send the enable flags controlling when output signals are enabled + * + * @note Some devices may not support ::ENABLE_FLAGS + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_enable_flags + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_enable_flags( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const ENABLE_FLAGS *p ) +{ + GPS_CMD cmd = GPS_ENABLE_FLAGS | OPT_GPS_ACK_CODE; + ENABLE_FLAGS *p_data = &pmctl->xmt.pmb->u.msg_data.enable_flags; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_enable_flags( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_enable_flags + + + +/*HDR*/ +/** + * @brief Read GPS status info + * + * @note This is only supported by GPS receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_stat_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, STAT_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_STAT_INFO ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.stat_info; + _mbg_swab_stat_info( p ); + } + + return rc; + +} // mbgextio_get_stat_info + + + +/*HDR*/ +/** + * @brief Read the configured length of the antenna cable + * + * This is only supported by GPS/GNSS receivers, check ::GPS_MODEL_HAS_ANT_CABLE_LENGTH + * + * @note Some older devices may not reply to this request unless + * the application has registered itself as terminal application + * (GPS_AUTO_ON is not sufficient). + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_ant_cable_len + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ant_cable_len( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, ANT_CABLE_LEN *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_ANT_CABLE_LENGTH ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ant_cable_len; + _mbg_swab_ant_cable_len( p ); + } + + return rc; + +} // mbgextio_get_ant_cable_len + + + +/*HDR*/ +/** + * @brief Send the GPS antenna cable length configuration + * + * This is only supported by GPS/GNSS receivers, check ::GPS_MODEL_HAS_ANT_CABLE_LENGTH + + * @note Different devices may accept different maximum values, so the + * written value should be re-read using ::mbgextio_get_ant_cable_len + * to check if the parameter has been accepted. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ant_cable_len + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ant_cable_len( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const ANT_CABLE_LEN *p ) +{ + GPS_CMD cmd = GPS_ANT_CABLE_LENGTH | OPT_GPS_ACK_CODE; + ANT_CABLE_LEN *p_data = &pmctl->xmt.pmb->u.msg_data.ant_cable_len; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_ant_cable_len( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_ant_cable_len + + + +/*HDR*/ +/** + * @brief Read configuration info and supported features of the device's IRIG output + * + * @note This is only supported if ::GPS_HAS_IRIG_TX is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_irig_tx_settings + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_irig_tx_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, IRIG_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_IRIG_TX_INFO ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.irig_tx_info; + _mbg_swab_irig_info( p ); + } + + return rc; + +} // mbgextio_get_irig_tx_info + + + +/*HDR*/ +/** + * @brief Send new configuration settings for the device's IRIG output + * + * @note This is only supported if ::GPS_HAS_IRIG_TX is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_irig_tx_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_irig_tx_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const IRIG_SETTINGS *p ) +{ + GPS_CMD cmd = GPS_IRIG_TX_SETTINGS | OPT_GPS_ACK_CODE; + IRIG_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.irig_tx_settings; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_irig_settings( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_irig_tx_settings + + + +/*HDR*/ +/** + * @brief Read configuration info and supported features for the device's IRIG input + * + * @note This is only supported if ::GPS_HAS_IRIG_RX is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_irig_rx_settings + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_irig_rx_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, IRIG_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_IRIG_RX_INFO ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.irig_rx_info; + _mbg_swab_irig_info( p ); + } + + return rc; + +} // mbgextio_get_irig_rx_info + + + +/*HDR*/ +/** + * @brief Send new configuration settings for the device's IRIG input + * + * @note This is only supported if ::GPS_HAS_IRIG_RX is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_irig_rx_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_irig_rx_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const IRIG_SETTINGS *p ) +{ + GPS_CMD cmd = GPS_IRIG_RX_SETTINGS | OPT_GPS_ACK_CODE; + IRIG_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.irig_rx_settings; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_irig_settings( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_irig_rx_settings + + + +/*HDR*/ +/** + * @brief Read current ref offset to %UTC configuration + * + * @note This is only supported if ::GPS_HAS_REF_OFFS is set in ::RECEIVER_INFO::features, + * usually with IRIG receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_ref_offs + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ref_offs( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_REF_OFFS *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_REF_OFFS ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ref_offs; + _mbg_swab_mbg_ref_offs( p ); + } + + return rc; + +} // mbgextio_get_ref_offs + + + +/*HDR*/ +/** + * @brief Send new ref offset to %UTC settings + * + * @note This is only supported if ::GPS_HAS_REF_OFFS is set in ::RECEIVER_INFO::features, + * usually with IRIG receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ref_offs + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ref_offs( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const MBG_REF_OFFS *p ) +{ + GPS_CMD cmd = GPS_REF_OFFS | OPT_GPS_ACK_CODE; + MBG_REF_OFFS *p_data = &pmctl->xmt.pmb->u.msg_data.ref_offs; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_mbg_ref_offs( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_ref_offs + + + +/*HDR*/ +/** + * @brief Read current debug status + * + * @note This is only supported if ::GPS_HAS_DEBUG_STATUS is set in ::RECEIVER_INFO::features, + * usually with IRIG receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_debug_status( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_DEBUG_STATUS *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_DEBUG_STATUS ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.debug_status; + _mbg_swab_debug_status( p ); + } + + return rc; + +} // mbgextio_get_debug_status + + + +/*HDR*/ +/** + * @brief Read current optional settings and supported options + * + * @note This is only supported if ::GPS_HAS_OPT_SETTINGS is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_opt_settings + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_opt_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_OPT_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_OPT_INFO ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.opt_info; + _mbg_swab_mbg_opt_info( p ); + } + + return rc; + +} // mbgextio_get_opt_info + + + +/*HDR*/ +/** + * @brief Send new optional settings flags + * + * @note This is only supported if ::GPS_HAS_OPT_SETTINGS is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_opt_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_opt_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const MBG_OPT_SETTINGS *p ) +{ + GPS_CMD cmd = GPS_OPT_SETTINGS | OPT_GPS_ACK_CODE; + MBG_OPT_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.opt_settings; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_mbg_opt_settings( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_opt_settings + + + +/*HDR*/ +/** + * @brief Read information on a specific supported string format + * + * Retrieve a single entry from an array of supported string types. + * The number of supported string types is specified in ::RECEIVER_INFO::n_str_type. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::RECEIVER_INFO::n_str_type - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_all_str_type_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_str_type_info_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, STR_TYPE_INFO_IDX *p, uint16_t idx ) +{ + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_STR_TYPE_INFO_IDX, idx ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.str_type_info_idx; + _mbg_swab_str_type_info_idx( p ); + + #if 0 //##++ TODO: check if received idx matches requested idx + if ( pii.idx != i ) + { + printf( "** Info for port %i requested, but for %i received.\n", + pii.idx, i ); + rc = ...; + } + #endif + } + + return rc; + +} // mbgextio_get_str_type_info_idx + + + +/*HDR*/ +/** + * @brief Read an array of all supported string types + * + * The number of supported string types is specified in ::RECEIVER_INFO::n_str_type. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] stii An array which can hold at least ::RECEIVER_INFO::n_str_type entries + * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_str_type_info_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_str_type_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, STR_TYPE_INFO_IDX stii[], + const RECEIVER_INFO *p_ri ) +{ + int rc = MBG_SUCCESS; + uint16_t i; + + for ( i = 0; i < p_ri->n_str_type; i++ ) + { + rc = mbgextio_get_str_type_info_idx( pmctl, p_addr, &stii[i], i ); + + if ( rc != MBG_SUCCESS ) + break; + } + + return rc; + +} // mbgextio_get_all_str_type_info + + + +/*HDR*/ +/** + * @brief Read current settings and capabilities of a specific serial port + * + * The number of serial ports provided by the device is specified in ::RECEIVER_INFO::n_com_ports. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::RECEIVER_INFO::n_com_ports - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_all_port_info + * @see ::mbgextio_set_port_settings_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_port_info_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, PORT_INFO_IDX *p, uint16_t idx ) +{ + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_PORT_INFO_IDX, idx ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.port_info_idx; + _mbg_swab_port_info_idx( p ); + + #if 0 //##++ TODO: check if received idx matches requested idx + if ( pii.idx != i ) + { + printf( "** Info for port %i requested, but for %i received.\n", + pii.idx, i ); + rc = ...; + } + #endif + } + + return rc; + +} // mbgextio_get_port_info_idx + + + +/*HDR*/ +/** + * @brief Read an array of current settings and capabilities of all serial ports + * + * The number of serial ports provided by the device is specified in ::RECEIVER_INFO::n_com_ports. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] pii An array which can hold at least ::RECEIVER_INFO::n_com_ports entries + * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_port_info_idx + * @see ::mbgextio_set_port_settings_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_port_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, PORT_INFO_IDX pii[], + const RECEIVER_INFO *p_ri ) +{ + int rc = MBG_SUCCESS; + uint16_t i; + + for ( i = 0; i < p_ri->n_com_ports; i++ ) + { + rc = mbgextio_get_port_info_idx( pmctl, p_addr, &pii[i], i ); + + if ( rc != MBG_SUCCESS ) + break; + } + + return rc; + +} // mbgextio_get_all_port_info + + + +/*HDR*/ +/** + * @brief Send configuration settings for a specific serial port + * + * The number of serial ports provided by the device is specified in ::RECEIVER_INFO::n_com_ports. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * @param[in] idx Index of the serial port to be configured, 0..::RECEIVER_INFO::n_com_ports - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_port_info_idx + * @see ::mbgextio_get_all_port_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_port_settings_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const PORT_SETTINGS *p, uint16_t idx ) +{ + GPS_CMD cmd = GPS_PORT_SETTINGS_IDX | OPT_GPS_ACK_CODE; + PORT_SETTINGS_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.port_settings_idx; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + p_data->port_settings = *p; + p_data->idx = idx; + _mbg_swab_port_settings_idx( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_port_settings_idx + + + +/*HDR*/ +/** + * @brief Read current settings and capabilities of a specific programmable pulse output + * + * The number of supported pulse outputs is specified in ::RECEIVER_INFO::n_prg_out. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::RECEIVER_INFO::n_prg_out - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_all_pout_info + * @see ::mbgextio_set_pout_settings_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_pout_info_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, POUT_INFO_IDX *p, uint16_t idx ) +{ + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_POUT_INFO_IDX, idx ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.pout_info_idx; + _mbg_swab_pout_info_idx_on_get( p ); + + #if 0 //##++ TODO: check if received idx matches requested idx + if ( pii.idx != i ) + { + printf( "** Info for port %i requested, but for %i received.\n", + pii.idx, i ); + rc = ...; + } + #endif + } + + return rc; + +} // mbgextio_get_pout_info_idx + + + +/*HDR*/ +/** + * @brief Read an array of current settings and capabilities of all programmable pulse outputs + * + * The number of supported pulse outputs is specified in ::RECEIVER_INFO::n_prg_out. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] pii An array which can hold at least ::RECEIVER_INFO::n_prg_out entries + * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_pout_info_idx + * @see ::mbgextio_set_pout_settings_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_pout_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, + POUT_INFO_IDX *pii, const RECEIVER_INFO *p_ri ) +{ + int rc = MBG_SUCCESS; + uint16_t i; + + memset( pii, 0, p_ri->n_prg_out * sizeof( *pii ) ); + + for ( i = 0; i < p_ri->n_prg_out; i++ ) + { + rc = mbgextio_get_pout_info_idx( pmctl, p_addr, &pii[i], i ); + + if ( rc != MBG_SUCCESS ) + break; + } + + return rc; + +} // mbgextio_get_all_pout_info + + + +/*HDR*/ +/** + * @brief Send configuration settings for a specific programmable pulse output + * + * The number of supported pulse outputs is specified in ::RECEIVER_INFO::n_prg_out. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * @param[in] idx Index of the pulse output to be configured, 0..RECEIVER_INFO::n_prg_out - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_pout_info_idx + * @see ::mbgextio_get_all_pout_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_pout_settings_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const POUT_SETTINGS *p, uint16_t idx ) +{ + GPS_CMD cmd = GPS_POUT_SETTINGS_IDX | OPT_GPS_ACK_CODE; + POUT_SETTINGS_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.pout_settings_idx; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + p_data->pout_settings = *p; + p_data->idx = idx; + _mbg_swab_pout_settings_idx_on_set( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_pout_settings_idx + + + +/*HDR*/ +/** + * @brief Clear the user capture event buffer on-board the device + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ucap + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_clr_ucap_buff( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr ) +{ + return mbgextio_xmt_cmd( pmctl, p_addr, GPS_CLR_UCAP_BUFF ); + +} // mbgextio_clr_ucap_buff + + + +/*HDR*/ +/** + * @brief Read time scale configuration parameters + * + * @note Some devices may not support a configurable time scale + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_time_scale_settings + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_time_scale_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_TIME_SCALE_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_TIME_SCALE ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.time_scale_info; + _mbg_swab_mbg_time_scale_info( p ); + } + + return rc; + +} // mbgextio_get_time_scale_info + + + +/*HDR*/ +/** + * @brief Send new time scale configuration settings + * + * @note Some devices may not support a configurable time scale + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_time_scale_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_time_scale_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const MBG_TIME_SCALE_SETTINGS *p ) +{ + GPS_CMD cmd = GPS_TIME_SCALE | OPT_GPS_ACK_CODE; + MBG_TIME_SCALE_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.time_scale_settings; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_mbg_time_scale_settings( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_time_scale_settings + + + +/*HDR*/ +/** + * @brief Clear the on-board event log + * + * @note Some devices don't provide an on-board event log + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_num_evt_log_entries + * @see ::mbgextio_get_first_evt_log_entry + * @see ::mbgextio_get_next_evt_log_entry + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_clr_evt_log( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr ) +{ + return mbgextio_xmt_cmd( pmctl, p_addr, GPS_CLR_EVT_LOG ); + +} // mbgextio_clr_evt_log + + + +/*HDR*/ +/** + * @brief Read the current number of entries in the on-board event log + * + * @note Some devices don't provide an on-board event log + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_clr_evt_log + * @see ::mbgextio_get_first_evt_log_entry + * @see ::mbgextio_get_next_evt_log_entry + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_num_evt_log_entries( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_NUM_EVT_LOG_ENTRIES *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_NUM_EVT_LOG_ENTRIES ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.num_evt_log_entries; + _mbg_swab_mbg_num_evt_log_entries( p ); + } + + return rc; + +} // mbgextio_get_num_evt_log_entries + + + +/*HDR*/ +/** + * @brief Return the first entry from the on-board event log + * + * This resets an internal counter, so subsequent calls to + * ::mbgextio_get_next_evt_log_entry will retrieve the following entries. + * + * @note Some devices don't provide an on-board event log + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_clr_evt_log + * @see ::mbgextio_get_num_evt_log_entries + * @see ::mbgextio_get_next_evt_log_entry + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_first_evt_log_entry( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_EVT_LOG_ENTRY *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_FIRST_EVT_LOG_ENTRY ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.evt_log_entry; + _mbg_swab_mbg_evt_log_entry( p ); + } + + return rc; + +} // mbgextio_get_first_evt_log_entry + + + +/*HDR*/ +/** + * @brief Return the next entry from the on-board event log + * + * This increments an internal counter, so subsequent calls will + * return subsequent entries. ::mbgextio_get_first_evt_log_entry + * should be called first to reset the counter and retrieve the + * oldest log entry. + * + * @note Some devices don't provide an on-board event log + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_clr_evt_log + * @see ::mbgextio_get_num_evt_log_entries + * @see ::mbgextio_get_first_evt_log_entry + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_next_evt_log_entry( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_EVT_LOG_ENTRY *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_NEXT_EVT_LOG_ENTRY ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.evt_log_entry; + _mbg_swab_mbg_evt_log_entry( p ); + } + + return rc; + +} // mbgextio_get_next_evt_log_entry + + + +/*HDR*/ +/** + * @brief Read the current IMS state and supported IMS features + * + * @note This is only supported if ::GPS_HAS_IMS is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ims_sensor_state_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ims_state( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_IMS_STATE *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_IMS_STATE ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ims_state; + _mbg_swab_mbg_ims_state( p ); + } + + return rc; + +} // mbgextio_get_ims_state + + + +/*HDR*/ +/** + * @brief Read sensor values from a specified sensor on the device + * + * Info on supported sensors can be retrieved using ::mbgextio_get_ims_state. + * Valid range for the sensor index is [0..::MBG_IMS_STATE::num_sensors - 1]. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx The index of the array element to read + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ims_state + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ims_sensor_state_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_IMS_SENSOR_STATE_IDX *p, uint16_t idx ) +{ + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_IMS_SENSOR_STATE_IDX, idx ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ims_sensor_state_idx; + _mbg_swab_mbg_ims_sensor_state_idx( p ); + } + + return rc; + +} // mbgextio_get_ims_sensor_state_idx + + + +/*HDR*/ +/** + * @brief Set the XMR holdover interval + * + * @todo In which case is this supported? + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_holdover_interval_counter + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_holdover_interval( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const XMR_HOLDOVER_INTV *p ) +{ + GPS_CMD cmd = GPS_XMR_HOLDOVER_INTV | OPT_GPS_ACK_CODE; + XMR_HOLDOVER_INTV *p_data = &pmctl->xmt.pmb->u.msg_data.xmr_holdover_intv; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_xmr_holdover_intv( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_holdover_interval + + + +/*HDR*/ +/** + * @brief Read the XMR holdover interval counter + * + * @todo In which case is this supported? + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_holdover_interval + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_holdover_interval_counter( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, XMR_HOLDOVER_INTV *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_XMR_HOLDOVER_INTV ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.xmr_holdover_intv; + _mbg_swab_xmr_holdover_intv( p ); + } + + return rc; + +} // mbgextio_get_holdover_interval_counter + + + +/*HDR*/ +/** + * @brief Read the local time conversion configuration in ::TZCODE format + * + * @note Some devices may not support ::TZCODE configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_tzcode + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_tzcode( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, TZCODE *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, PZF_TZCODE ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.tzcode; + _mbg_swab_tzcode( p ); + } + + return rc; + +} // mbgextio_get_tzcode + + + +/*HDR*/ +/** + * @brief Set the local time conversion configuration in ::TZCODE format + * + * @note Some devices may not support ::TZCODE configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_tzcode + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_tzcode( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const TZCODE *p ) +{ + GPS_CMD cmd = PZF_TZCODE | OPT_GPS_ACK_CODE; + TZCODE *p_data = &pmctl->xmt.pmb->u.msg_data.tzcode; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif + + *p_data = *p; + _mbg_swab_tzcode( p_data ); + + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_tzcode + + + +/*HDR*/ +/** + * @brief Send new configuration settings for the device's HAVEQUICK output + * + * @note This is only supported if ::GPS_HAS_HAVEQUICK is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_hq_tx_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, HAVEQUICK_SETTINGS *p ) { - int rc; + GPS_CMD cmd = GPS_HAVEQUICK_TX_SETTINGS | OPT_GPS_ACK_CODE; + HAVEQUICK_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.havequick_settings; #if _USE_MUTEX _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); #endif - rc = xmt_cmd( pmctl, cmd ); - - #if _USE_MUTEX - _mbg_mutex_release( &pmctl->xmt.xmt_mutex ); - #endif + *p_data = *p; + _mbg_swab_havequick_settings( p_data ); - return rc; + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); -} // mbgextio_xmt_cmd +} // mbgextio_set_hq_tx_settings /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t us ) +/** + * @brief Send new configuration settings for the device's HAVEQUICK input + * + * @note This is only supported if ::MULTI_REF_HAVEQUICK is > 0 in ::XMULTI_REF_INSTANCES::n_inst //##+++++++++++++++++++++++ ??? + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_hq_rx_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, HAVEQUICK_SETTINGS *p ) { - int rc; + GPS_CMD cmd = GPS_HAVEQUICK_RX_SETTINGS | OPT_GPS_ACK_CODE; + HAVEQUICK_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.havequick_settings; #if _USE_MUTEX _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); #endif - rc = xmt_cmd_us( pmctl, cmd, us ); - - #if _USE_MUTEX - _mbg_mutex_release( &pmctl->xmt.xmt_mutex ); - #endif + *p_data = *p; + _mbg_swab_havequick_settings( p_data ); - return rc; + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); -} // mbgextio_xmt_cmd_us +} // mbgextio_set_hq_rx_settings /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_req_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) +/** + * @brief Read the distance from transmitter ::TR_DISTANCE format + * + * @note Some devices may not support ::TR_DISTANCE configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_tr_distance + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_tr_distance( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, TR_DISTANCE *p ) { - xmt_cmd( pmctl, cmd ); /* request a set of data */ + int rc = mbgextio_req_data( pmctl, p_addr, PZF_TR_DISTANCE ); + + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.tr_distance; + _mbg_swab_tr_distance( p ); + } - return mbgextio_rcv_msg( pmctl, cmd ); + return rc; -} // mbgextio_req_data +} // mbgextio_get_tr_distance /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_req_data_idx( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t idx ) +/** + * @brief Set the transmitter distance (km) in ::TR_DISTANCE format + * + * @note Some devices may not support ::TR_DISTANCE configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_tr_distance + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_tr_distance( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const TR_DISTANCE *p ) { - xmt_cmd_us( pmctl, cmd, idx ); /* request a set of data */ + GPS_CMD cmd = PZF_TR_DISTANCE | OPT_GPS_ACK_CODE; + TR_DISTANCE *p_data = &pmctl->xmt.pmb->u.msg_data.tr_distance; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return mbgextio_rcv_msg( pmctl, cmd ); + *p_data = *p; + _mbg_swab_tr_distance( p_data ); -} // mbgextio_req_data_idx + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_tr_distance /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) +/** + * @brief Read current GNSS mode settings and supported features + * + * @note Some devices may not support GNSS configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to a ::MBG_GNSS_MODE_INFO structure to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_gnss_mode_settings + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_gnss_mode_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_GNSS_MODE_INFO *p ) { - int rc = mbgextio_req_data( pmctl, GPS_RECEIVER_INFO ); + int rc = mbgextio_req_data( pmctl, p_addr, GPS_GNSS_MODE ); - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.receiver_info; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.gnss_mode_info; + _mbg_swab_dummy( p ); + } return rc; -} // mbgextio_get_receiver_info +} // mbgextio_get_gnss_mode_info /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_sw_rev( MBG_MSG_CTL *pmctl, SW_REV *p ) +/** + * @brief Write GNSS mode settings + * + * @note Some devices may not support GNSS configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] p Pointer to a ::MBG_GNSS_MODE_SETTINGS structure to be sent + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_gnss_mode_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_gnss_mode_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const MBG_GNSS_MODE_SETTINGS *p ) { - int rc = mbgextio_req_data( pmctl, GPS_SW_REV ); + GPS_CMD cmd = GPS_GNSS_MODE | OPT_GPS_ACK_CODE; + MBG_GNSS_MODE_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.gnss_mode_settings; - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.sw_rev; + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return rc; + *p_data = *p; + _mbg_swab_dummy( p_data ); -} // mbgextio_get_sw_rev + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_gnss_mode_settings /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_bvar_stat( MBG_MSG_CTL *pmctl, BVAR_STAT *p ) +/** + * @brief Read an array of all supported string types //##+++++++++++++++++++++++++++++++++++++++++++++++ TODO + * + * The number of supported string types is specified in ::RECEIVER_INFO::n_str_type. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] stii An array which can hold at least ::RECEIVER_INFO::n_str_type entries + * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_str_type_info_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_gnss_sat_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, STR_TYPE_INFO_IDX stii[], + const RECEIVER_INFO *p_ri ) { - int rc = mbgextio_req_data( pmctl, GPS_BVAR_STAT ); + int rc = MBG_SUCCESS; + uint16_t i; - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.bvar_stat; + for ( i = 0; i < p_ri->n_str_type; i++ ) + { + rc = mbgextio_get_str_type_info_idx( pmctl, p_addr, &stii[i], i ); + + if ( rc != MBG_SUCCESS ) + break; + } return rc; -} // mbgextio_get_bvar_stat +} // mbgextio_get_all_gnss_sat_info /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_time( MBG_MSG_CTL *pmctl, TTM *p ) +/** + * @brief Fill up a GNSS info structure //##+++++++++++++++++++++++++++++++++++++++++++++++ TODO + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[out] p_si Pointer to a ::STAT_INFO the data structure to return the received data + * @param[out] p_gmi Index of the NTP peer state to be configured, 0..::NTP_CLNT_MODE_INFO::n_supp_peers - 1 + * @param[out] p_gsii Blah ... //##++++++++++ TODO + * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_sys_state + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_get_ntp_clnt_mode_info + */ +int mbgextio_chk_get_gnss_info( MBG_MSG_CTL *pmctl, STAT_INFO *p_si, + MBG_GNSS_MODE_INFO *p_gmi, GNSS_SAT_INFO_IDX *p_gsii, + const RECEIVER_INFO *p_ri ) { - int rc = mbgextio_req_data( pmctl, GPS_TIME ); - - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.ttm; + int n_gnss_supp = 0; + int rc = -1; +#if 0 + int i = -1; + +#if 0 //##++++++++++++++ + if ( !_pcps_has_stat_info( p_dev ) ) + return 0; +#endif - return rc; + rc = mbgextio_get_stat_info( pmctl, p_si ); -} // mbgextio_get_time + if ( rc < 0 ) + goto fail; +//##+++++++++++++ if ( _pcps_is_gnss( p_dev ) ) + { + if ( ( rc = mbgextio_get_gnss_mode_info( pmctl, p_gmi ) ) < 0 ) + goto fail; -/*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_time( MBG_MSG_CTL *pmctl, const TTM *p ) -{ - GPS_CMD cmd = GPS_TIME; +// mbgextio_get_all_gnss_sat_info + for ( i = 0; i < p_gmi-> ; i++ ) + rc = mbgextio_get_all_gnss_sat_info( pmctl, p_gsii, p_gmi ); -#if _MBGEXTIO_DIRECT_RC + if ( rc < 0 ) + goto fail; + } +//##++++ else + { +//##++++ if ( _pcps_has_stat_info_svs( p_dev ) ) // GPS is supported + { + GNSS_SAT_INFO *p_gsi; - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + // setup GNSS info from stat_info so we can use the same printing routine + p_gmi->supp_gnss_types = MBG_GNSS_TYPE_MSK_GPS; + p_gmi->settings.gnss_set = p_gmi->supp_gnss_types; -#else - int rc; + p_gsi = &p_gsii->gnss_sat_info; + p_gsi->gnss_type = GNSS_TYPE_GPS; + p_gsi->svs_in_view = p_si->svs_in_view; + p_gsi->good_svs = p_si->good_svs; + } + } - rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); - rc = mbgextio_rcv_msg( pmctl, cmd ); + n_gnss_supp = num_bits_set( p_gmi->supp_gnss_types ); - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + if ( n_gnss_supp > N_GNSS_TYPES ) { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. + //##++++ show warning: device supports more GNSS types than this program + n_gnss_supp = N_GNSS_TYPES; } - return 0; + return n_gnss_supp; + +fail: #endif + return rc; -} // mbgextio_set_time +} // mbg_chk_get_gnss_info /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl, LLA lla ) +/** + * @brief Read the supported XMR features in ::XMULTI_REF_INFO_IDX format + * + * Only if ::GPS_HAS_XMULTI_REF is set in ::RECEIVER_INFO::features. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_xmr_info_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_xmr_info_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, XMULTI_REF_INFO_IDX *p ) { - int rc = mbgextio_req_data( pmctl, GPS_POS_LLA ); + uint16_t idx = p->idx; + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_XMR_INFO_IDX, idx ); - if ( rc == TR_COMPLETE ) + if ( ( rc == MBG_SUCCESS ) && p ) { - MSG_DATA *pmb = &pmctl->rcv.pmb->u.msg_data; - int i; - - for ( i = 0; i < N_LLA; i++ ) - { - swap_double( &pmb->lla[i] ); - - if ( lla ) - lla[i] = pmb->lla[i]; - } + *p = pmctl->rcv.pmb->u.msg_data.xmulti_ref_info_idx; + _mbg_swab_dummy( p ); //##++++++ _mbg_xmr_info_idx( p ); } return rc; -} // mbgextio_get_pos_lla +} // mbgextio_get_xmr_info_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_pos_lla( MBG_MSG_CTL *pmctl, const LLA lla ) +/** + * @brief Read the supported XMR features ::XMULTI_REF_STATUS_IDX format + * + * @note Only for devices which supports Multi references + * @note GPS_HAS_XMULTI_REF feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_xmr_info_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_xmr_status_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, XMULTI_REF_STATUS_IDX *p ) { - GPS_CMD cmd = GPS_POS_LLA; - -#if _MBGEXTIO_DIRECT_RC - - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) lla, sizeof( LLA ) ); - -#else - int rc; - - rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) lla, sizeof( LLA ) ); - rc = mbgextio_rcv_msg( pmctl, cmd ); + uint16_t idx = p->idx; + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_XMR_STATUS_IDX, idx ); - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + if ( ( rc == MBG_SUCCESS ) && p ) { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. + *p = pmctl->rcv.pmb->u.msg_data.xmulti_ref_status_idx; + //##++++++ _mbg_xmr_status_idx( p ); } - return 0; - -#endif + return rc; -} // mbgextio_set_pos_lla +} // mbgextio_get_xmr_status_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_tzdl( MBG_MSG_CTL *pmctl, TZDL *p ) +/** + * @brief Save the supported XMR features ::XMULTI_REF_INFO_IDX format + * + * @note Some devices may not support Multi Refernce Sources + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_xmr_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const XMULTI_REF_SETTINGS_IDX *p ) { - int rc = mbgextio_req_data( pmctl, GPS_TZDL ); + GPS_CMD cmd = GPS_XMR_SETTINGS_IDX | OPT_GPS_ACK_CODE; + XMULTI_REF_SETTINGS_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.xmulti_ref_settings_idx; - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.tzdl; + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return rc; + *p_data = *p; + //##++++++ _mbg_swab_xmr_settings( p_data ); -} // mbgextio_get_tzdl + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_xmr_settings /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_tzdl( MBG_MSG_CTL *pmctl, const TZDL *p ) +/** + * @brief Read the lan interface configuration ::LAN_IF_INFO format + * + * @note ptp or xmr with ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_lan_if_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, LAN_IF_INFO *p ) { - GPS_CMD cmd = GPS_TZDL; - -#if _MBGEXTIO_DIRECT_RC - - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); - -#else int rc; + rc = mbgextio_req_data( pmctl, p_addr, GPS_LAN_IF_INFO ); - rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); - rc = mbgextio_rcv_msg( pmctl, cmd ); - - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + if ( ( rc == MBG_SUCCESS ) && p ) { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. + *p = pmctl->rcv.pmb->u.msg_data.lan_if_info; + //##++++++ _mbg_xmr_status_idx( p ); } - return 0; - -#endif + return rc; -} // mbgextio_get_tzdl +} // mbgextio_get_lan_if_info /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_port_parm( MBG_MSG_CTL *pmctl, PORT_PARM *p ) +/** + * @brief Read the lan ipv4 configuration state ::IP4_SETTINGS format + * + * @note ptp or xmr with ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ip4_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, IP4_SETTINGS *p ) { - int rc = mbgextio_req_data( pmctl, GPS_PORT_PARM ); + int rc = mbgextio_req_data( pmctl, p_addr, GPS_IP4_SETTINGS ); - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.port_parm; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ip4_settings; + //##++++++ _mbg_xmr_status_idx( p ); + } return rc; -} // mbgextio_get_port_parm +} // mbgextio_get_ip4_settings /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_port_parm( MBG_MSG_CTL *pmctl, const PORT_PARM *p ) +/** + * @brief Save the current ipv4 settings ::IP4_SETTINGS format + * + * @note ptp or xmr with ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ip4_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const IP4_SETTINGS *p ) { - GPS_CMD cmd = GPS_PORT_PARM; + GPS_CMD cmd = GPS_IP4_SETTINGS | OPT_GPS_ACK_CODE; + IP4_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.ip4_settings; -#if _MBGEXTIO_DIRECT_RC + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + *p_data = *p; + //##++++++ _mbg_swab_xmr_settings( p_data ); -#else + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); - MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; - int rc; +} // mbgextio_set_ip4_settings - pmb->u.msg_data.port_parm = *p; - pmb->hdr.len = sizeof( pmb->u.msg_data.port_parm ); - pmb->hdr.cmd = cmd | GPS_REQACK; - xmt_tbuff( pmctl ); - rc = mbgextio_rcv_msg( pmctl, cmd ); +/*HDR*/ +/** + * @brief Read the current lan ipv4 state ::IP4_SETTINGS format + * + * @note ptp or xmr with ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ip4_state( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, IP4_SETTINGS *p ) +{ + int rc = mbgextio_req_data( pmctl, p_addr, GPS_IP4_STATE ); - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + if ( ( rc == MBG_SUCCESS ) && p ) { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. + *p = pmctl->rcv.pmb->u.msg_data.ip4_settings; + //##++++++ _mbg_xmr_status_idx( p ); } - return 0; - -#endif + return rc; -} // mbgextio_set_port_parm +} // mbgextio_get_ip4_state /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_synth( MBG_MSG_CTL *pmctl, SYNTH *p ) +/** + * @brief Read the current state of PTP device ::PTP_STATE format + * + * @note ptp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ptp_state( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, PTP_STATE *p ) { - int rc = mbgextio_req_data( pmctl, GPS_SYNTH ); + int rc = mbgextio_req_data( pmctl, p_addr, GPS_PTP_STATE); - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.synth; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ptp_state; + } return rc; -} // mbgextio_get_synth +} // mbgextio_get_ptp_state /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_synth( MBG_MSG_CTL *pmctl, const SYNTH *p ) +/** + * @brief Read the ptp configuration ::PTP_CFG_INFO format + * + * @note ptp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ptp_cfg_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, PTP_CFG_INFO *p ) { - GPS_CMD cmd = GPS_SYNTH; - -#if _MBGEXTIO_DIRECT_RC - - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); - -#else - int rc; + int rc = mbgextio_req_data( pmctl, p_addr, GPS_PTP_CFG ); - rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); - rc = mbgextio_rcv_msg( pmctl, cmd ); - - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + if ( ( rc == MBG_SUCCESS ) && p ) { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. + *p = pmctl->rcv.pmb->u.msg_data.ptp_cfg_info; } - return 0; - -#endif + return rc; -} // mbgextio_set_synth +} // mbgextio_get_ptp_cfg_info /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_ant_info( MBG_MSG_CTL *pmctl, ANT_INFO *p ) +/** + * @brief Read the ptp configuration ::PTP_UC_MASTER_CFG_LIMITS format + * + * @note ptp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ptp_uc_master_cfg_limits( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, PTP_UC_MASTER_CFG_LIMITS *p ) { - int rc = mbgextio_req_data( pmctl, GPS_ANT_INFO ); + int rc = mbgextio_req_data( pmctl, p_addr, GPS_PTP_UC_MASTER_CFG_LIMITS ); - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.ant_info; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ptp_uc_master_cfg_limits; + } return rc; -} // mbgextio_get_ant_info +} // mbgextio_get_ptp_uc_master_cfg_limits /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, TTM *p ) +/** + * @brief Read the ptp configuration ::ALL_PTP_UC_MASTER_INFO_IDX format + * + * @note ptp feature must set and read number of ptp unicast masters before. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] ptp_uc_master_info_idx Pointer to an array of ::PTP_UC_MASTER_INFO_IDX structures to be filled up + * @param[in] ptp_uc_master_cfg_limits Pointer to a ::PTP_UC_MASTER_CFG_LIMITS structure read before + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ TODO + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_ptp_uc_master_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, PTP_UC_MASTER_INFO_IDX *ptp_uc_master_info_idx, + const PTP_UC_MASTER_CFG_LIMITS *ptp_uc_master_cfg_limits ) { - int rc; + int rc= MBG_SUCCESS; + uint16_t i; - xmt_cmd( pmctl, GPS_UCAP ); /* request a set of data */ - - // Attention: Older firmware versions may reply with GPS_TIME - // messages instead of GPS_UCAP messages, and may not send a reply - // at all if no capture event is available in the on-board FIFO. - for (;;) + for ( i = 0; i < ptp_uc_master_cfg_limits->n_supp_master; i++ ) { - rc = mbgextio_rcv_msg( pmctl, -1 ); - - if ( rc < 0 ) - break; + xmt_cmd_us( pmctl, p_addr, GPS_PTP_UC_MASTER_CFG, i ); - if ( rc != TR_COMPLETE ) - continue; + rc = mbgextio_rcv_msg( pmctl, p_addr, GPS_PTP_UC_MASTER_CFG ); //##+++++++++++++++++++++++++ - if ( pmctl->rcv.pmb->hdr.cmd == GPS_UCAP ) - break; - - if ( pmctl->rcv.pmb->hdr.cmd == GPS_TIME ) - if ( pmctl->rcv.pmb->hdr.len > 0 ) - if ( pmctl->rcv.pmb->u.msg_data.ttm.channel >= 0 ) - break; - } - - if ( p ) - { - // If the length of the msg header is 0 then the capture buffer - // is empty. This is indicated with 0xFF in the seconds field of - // the GPS time structure. - if ( pmctl->rcv.pmb->hdr.len > 0 ) - *p = pmctl->rcv.pmb->u.msg_data.ttm; + if ( ( rc == MBG_SUCCESS ) && ptp_uc_master_info_idx ) + { + PTP_UC_MASTER_INFO_IDX *p = &ptp_uc_master_info_idx[i]; + *p = pmctl->rcv.pmb->u.msg_data.ptp_uc_master_info_idx; + _mbg_swab_dummy( p ); + } else - _ttm_time_set_unavail( p ); // no capture event available + break; } return rc; -} // mbgextio_get_ucap +} // mbgextio_get_all_ptp_uc_master_info /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_enable_flags( MBG_MSG_CTL *pmctl, ENABLE_FLAGS *p ) +/** + * @brief Send configuration settings for PTP + * + * @note This is only supported by PTP devices + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ptp_cfg_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ptp_cfg_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const PTP_CFG_SETTINGS *p ) { - int rc = mbgextio_req_data( pmctl, GPS_ENABLE_FLAGS ); + GPS_CMD cmd = GPS_PTP_CFG | OPT_GPS_ACK_CODE; + PTP_CFG_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.ptp_cfg_settings; - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.enable_flags; + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return rc; + *p_data = *p; + _mbg_swab_ptp_cfg_settings( p_data ); -} // mbgextio_get_enable_flags + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_ptp_cfg_settings /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_enable_flags( MBG_MSG_CTL *pmctl, const ENABLE_FLAGS *p ) +/** + * @brief Read the ntp global information ::NTP_GLB_INFO format + * + * @note ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_clnt_mode_info + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_set_ntp_peer_settings_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_glb_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, NTP_GLB_INFO *p ) { - GPS_CMD cmd = GPS_ENABLE_FLAGS; + int rc = mbgextio_req_data( pmctl, p_addr, GPS_NTP_GLB_CFG ); -#if _MBGEXTIO_DIRECT_RC + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ntp_glb_info; + } - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + return rc; + +} // mbgextio_get_ntp_glb_info -#else - int rc; - rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); - rc = mbgextio_rcv_msg( pmctl, cmd ); - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) - { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. - } +/*HDR*/ +/** + * @brief Send the NTP global configuration + * + * @note This is only supported by NTP devices + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ant_cable_len + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ntp_glb_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const NTP_GLB_SETTINGS *p ) +{ + GPS_CMD cmd = GPS_NTP_GLB_CFG | OPT_GPS_ACK_CODE; + NTP_GLB_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.ntp_glb_settings; + + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return 0; + *p_data = *p; + _mbg_swab_ntp_glb_settings( p_data ); -#endif + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); -} // mbgextio_set_enable_flags +} // mbgextio_set_ntp_glb_info /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_stat_info( MBG_MSG_CTL *pmctl, STAT_INFO *p ) +/** + * @brief Read the ntp global information ::NTP_CLNT_MODE_INFO format + * + * @note ntp feature must set + * @note ntp client mode must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_glb_info + * @see ::mbgextio_set_ntp_clnt_mode_cfg + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_set_ntp_peer_settings_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_clnt_mode_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, NTP_CLNT_MODE_INFO *p ) { - int rc = mbgextio_req_data( pmctl, GPS_STAT_INFO ); + int rc = mbgextio_req_data( pmctl, p_addr, GPS_NTP_CLNT_MODE_CFG ); - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.stat_info; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ntp_clnt_mode_info; + } return rc; -} // mbgextio_get_stat_info +} // mbgextio_get_ntp_clnt_mode_info /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_ant_cable_len( MBG_MSG_CTL *pmctl, ANT_CABLE_LEN *p ) +/** + * @brief Send the NTP client mode configuration + * + * @note This is only supported by NTP devices + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_glb_info + * @see ::mbgextio_get_ntp_clnt_mode_info + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_set_ntp_peer_settings_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ntp_clnt_mode_cfg( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const NTP_CLNT_MODE_SETTINGS *p ) { - int rc = mbgextio_req_data( pmctl, GPS_ANT_CABLE_LENGTH ); + GPS_CMD cmd = GPS_NTP_CLNT_MODE_CFG | OPT_GPS_ACK_CODE; + NTP_CLNT_MODE_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.ntp_clnt_mode_settings; - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.ant_cable_len; + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return rc; + *p_data = *p; + _mbg_swab_ntp_clnt_mode_settings( p_data ); -} // mbgextio_get_ant_cable_len + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_ntp_clnt_mode_cfg /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_ant_cable_len( MBG_MSG_CTL *pmctl, const ANT_CABLE_LEN *p ) +/** + * @brief Read the ntp peer settings of current idx ::NTP_PEER_SETTINGS format + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the NTP peer settings to be configured, 0 ... NTP_CLNT_MODE_INFO::n_supp_peers - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_glb_info + * @see ::mbgextio_set_ntp_peer_settings_idx + * @see ::mbgextio_get_ntp_clnt_mode_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_peer_settings_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, NTP_PEER_SETTINGS_IDX *p, uint16_t idx ) { - GPS_CMD cmd = GPS_ANT_CABLE_LENGTH; - -#if _MBGEXTIO_DIRECT_RC - - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); - -#else int rc; + rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NTP_PEER_SETTINGS_IDX, idx ); - rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); - rc = mbgextio_rcv_msg( pmctl, cmd ); - - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + if ( ( rc == MBG_SUCCESS ) && p ) { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. + *p = pmctl->rcv.pmb->u.msg_data.ntp_peer_settings_idx; } - return 0; - -#endif + return rc; -} // mbgextio_set_ant_cable_len +} // mbgextio_get_ntp_peer_settings_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_irig_tx_info( MBG_MSG_CTL *pmctl, IRIG_INFO *p ) +/** + * @brief Send configuration settings for a specific NTP peer + * + * The number of supported NTP peers is specified in ::NTP_CLNT_MODE_INFO::n_supp_peers -1. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * @param[in] idx Index of the NTP peer to be configured, 0 ... NTP_CLNT_MODE_INFO::n_supp_peers - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_glb_info + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_get_ntp_clnt_mode_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ntp_peer_settings_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const NTP_PEER_SETTINGS *p, uint16_t idx ) { - int rc = mbgextio_req_data( pmctl, GPS_IRIG_TX_INFO ); + GPS_CMD cmd = GPS_NTP_PEER_SETTINGS_IDX | OPT_GPS_ACK_CODE; + NTP_PEER_SETTINGS_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.ntp_peer_settings_idx; - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.irig_tx_info; + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return rc; + p_data->peer_settings = *p; + p_data->idx = idx; + _mbg_swab_ntp_peer_settings_idx( p_data ); -} // mbgextio_get_irig_tx_info + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); + +} // mbgextio_set_ntp_peer_settings_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_irig_tx_settings( MBG_MSG_CTL *pmctl, const IRIG_SETTINGS *p ) +/** + * @brief Read the current system state of ntp device ::NTP_SYS_STATE format + * + * @note ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_ntp_clnt_mode_cfg + * @see ::mbgextio_get_ntp_glb_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_sys_state( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, NTP_SYS_STATE *p ) { - GPS_CMD cmd = GPS_IRIG_TX_SETTINGS; - -#if _MBGEXTIO_DIRECT_RC - - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + int rc = mbgextio_req_data( pmctl, p_addr, GPS_NTP_SYS_STATE); -#else - int rc; - - rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); - rc = mbgextio_rcv_msg( pmctl, cmd ); - - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + if ( ( rc == MBG_SUCCESS ) && p ) { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. + *p = pmctl->rcv.pmb->u.msg_data.ntp_sys_state; + //##++++++ _mbg_xmr_status_idx( p ); } - return 0; - -#endif + return rc; -} // mbgextio_set_irig_tx_settings +} // mbgextio_get_ntp_sys_state /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_irig_rx_info( MBG_MSG_CTL *pmctl, IRIG_INFO *p ) +/** + * @brief Read the NTP peer state of current idx ::NTP_PEER_STATE format + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the NTP peer state to be configured, 0 ... NTP_CLNT_MODE_INFO::n_supp_peers - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_sys_state + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_get_ntp_clnt_mode_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_peer_state_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, NTP_PEER_STATE_IDX *p, uint16_t idx ) { - int rc = mbgextio_req_data( pmctl, GPS_IRIG_RX_INFO ); + int rc; + rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NTP_PEER_STATE_IDX, idx ); - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.irig_rx_info; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ntp_peer_state_idx; + } return rc; -} // mbgextio_get_irig_rx_info - +} // mbgextio_get_ntp_peer_state_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_irig_rx_settings( MBG_MSG_CTL *pmctl, const IRIG_SETTINGS *p ) +/** + * @brief Read the network global config information ::MBG_NET_GLB_CFG_INFO format + * + * @note GPS_HAS_NET_CFG must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_net_glb_cfg_settings + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_glb_cfg_info( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_NET_GLB_CFG_INFO *p ) { - GPS_CMD cmd = GPS_IRIG_RX_SETTINGS; + int rc = mbgextio_req_data( pmctl, p_addr, GPS_NET_GLB_CFG); -#if _MBGEXTIO_DIRECT_RC + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.net_glb_cfg_info; + _mbg_swab_dummy( p ); + } - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + return rc; -#else - int rc; +} // mbgextio_get_net_glb_cfg_info - rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); - rc = mbgextio_rcv_msg( pmctl, cmd ); +/*HDR*/ +/** + * @brief Set the device's global network configuration settings + * + * @note The function is not supported by all devices. //##++++++++++++ + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_net_glb_cfg_info + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_net_glb_cfg_settings( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const MBG_NET_GLB_CFG_SETTINGS *p ) +{ + GPS_CMD cmd = GPS_NET_GLB_CFG | OPT_GPS_ACK_CODE; + MBG_NET_GLB_CFG_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.net_glb_cfg_settings; - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) - { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. - } + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return 0; + *p_data = *p; + _mbg_swab_dummy( p ); -#endif + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); -} // mbgextio_set_irig_rx_settings +} // mbgextio_set_net_glb_cfg_settings /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_ref_offs( MBG_MSG_CTL *pmctl, MBG_REF_OFFS *p ) +/** + * @brief Read the network dns server ::MBG_IP_ADDR_IDX format + * + * The number of DNS server provided by the device is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srvr + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srvr - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_net_dns_srvr_idx + * @see ::mbgextio_get_net_stat_dns_srvr_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_dns_srvr_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_IP_ADDR_IDX *p, uint16_t idx ) { - int rc = mbgextio_req_data( pmctl, GPS_REF_OFFS ); + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NET_DNS_SRVR, idx ); - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.ref_offs; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.ip_addr_idx; + _mbg_swab_dummy( p ); + } return rc; -} // mbgextio_get_ref_offs +} // mbgextio_get_net_dns_srvr_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_ref_offs( MBG_MSG_CTL *pmctl, const MBG_REF_OFFS *p ) +/** + * @brief Send the network DNS server address in ::MBG_IP_ADDR format + * + * The number of DNS search domains supported by the device + * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * @param[in] idx Index of the serial port to be configured, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srvr - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_net_dns_srvr_idx + * @see ::mbgextio_get_net_stat_dns_srvr_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_net_dns_srvr_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const MBG_IP_ADDR *p, uint16_t idx ) { - GPS_CMD cmd = GPS_REF_OFFS; - -#if _MBGEXTIO_DIRECT_RC - - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); - -#else - int rc; + GPS_CMD cmd = GPS_NET_DNS_SRVR | OPT_GPS_ACK_CODE; + MBG_IP_ADDR_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.ip_addr_idx; - rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); - rc = mbgextio_rcv_msg( pmctl, cmd ); - - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) - { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. - } + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return 0; + p_data->addr = *p; + p_data->idx = idx; + _mbg_swab_dummy( p_data ); -#endif + return mbgextio_xmt_msg( pmctl, p_addr, cmd, p_data, sizeof( *p_data ) ); -} // mbgextio_set_ref_offs +} // mbgextio_set_net_dns_srvr_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_debug_status( MBG_MSG_CTL *pmctl, MBG_DEBUG_STATUS *p ) +/** + * @brief Read the network DNS search domain in ::MBG_NET_NAME_IDX format + * + * The number of DNS search domains supported by the device + * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_net_dns_srch_dom_idx + * @see ::mbgextio_get_net_stat_dns_srch_dom_stat_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_dns_srch_dom_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_NET_NAME_IDX *p, uint16_t idx ) { - int rc = mbgextio_req_data( pmctl, GPS_DEBUG_STATUS ); + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NET_DNS_SRCH_DOM, idx ); - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.debug_status; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.net_name_idx; + _mbg_swab_dummy( p ); + } return rc; -} // mbgextio_get_debug_status +} // mbgextio_get_net_dns_srch_dom_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_opt_info( MBG_MSG_CTL *pmctl, MBG_OPT_INFO *p ) +/** + * @brief Send the network DNS search domain in ::MBG_NET_NAME format + * + * The number of DNS search domains supported by the device + * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * @param[in] idx Index of the serial port to be configured, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_net_dns_srch_dom_idx + * @see ::mbgextio_get_net_stat_dns_srch_dom_stat_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_net_dns_srch_dom_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, const MBG_NET_NAME *p, uint16_t idx ) { - int rc = mbgextio_req_data( pmctl, GPS_OPT_INFO ); + GPS_CMD cmd = GPS_NET_DNS_SRCH_DOM | OPT_GPS_ACK_CODE; + MBG_NET_NAME_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.net_name_idx; - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.opt_info; + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return rc; + p_data->net_name = *p; + p_data->idx = idx; + _mbg_swab_dummy( p_data ); -} // mbgextio_get_opt_info + return mbgextio_xmt_msg( pmctl, p_addr, cmd, p_data, sizeof( *p_data ) ); + +} // mbgextio_set_net_dns_srch_dom_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_opt_settings( MBG_MSG_CTL *pmctl, const MBG_OPT_SETTINGS *p ) +/** + * @brief Read the current network DNS server in ::MBG_IP_ADDR_IDX format + * + * The number of DNS servers supported by the device + * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srvr + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srvr - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_net_dns_srvr_idx + * @see ::mbgextio_set_net_dns_srvr_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_stat_dns_srvr_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_IP_ADDR_IDX *p, uint16_t idx ) { - GPS_CMD cmd = GPS_OPT_SETTINGS; - -#if _MBGEXTIO_DIRECT_RC + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NET_STAT_DNS_SRVR, idx ); - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); - -#else - int rc; - - rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); - rc = mbgextio_rcv_msg( pmctl, cmd ); - - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + if ( ( rc == MBG_SUCCESS ) && p ) { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. + *p = pmctl->rcv.pmb->u.msg_data.ip_addr_idx; + _mbg_swab_dummy( p ); } - return 0; - -#endif + return rc; -} // mbgextio_set_opt_settings +} // mbgextio_get_net_stat_dns_srvr_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_str_type_info_idx( MBG_MSG_CTL *pmctl, - STR_TYPE_INFO_IDX *p, uint16_t idx ) +/** + * @brief Read the current network DNS search domain in ::MBG_NET_NAME_IDX format + * + * The number of DNS search domains supported by the device + * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_net_dns_srch_dom_idx + * @see ::mbgextio_get_net_dns_srch_dom_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_stat_dns_srch_dom_stat_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, MBG_NET_NAME_IDX *p, uint16_t idx ) { - int rc; - - xmt_cmd_us( pmctl, GPS_STR_TYPE_INFO_IDX, idx ); - - rc = mbgextio_rcv_msg( pmctl, GPS_STR_TYPE_INFO_IDX ); + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NET_STAT_DNS_SRCH_DOM, idx ); - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.str_type_info_idx; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.net_name_idx; + _mbg_swab_dummy( p ); + } return rc; -} // mbgextio_get_str_type_info_idx +} // mbgextio_get_net_stat_dns_srch_dom_stat_idx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_port_info_idx( MBG_MSG_CTL *pmctl, - PORT_INFO_IDX *p, uint16_t idx ) +/** + * @brief Read the ::XBP_LIMITS to check which XBP features are supported + * + * @note Only supported if ::GPS_HAS_XBP is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_xbp_node_limits + * @see ::mbgextio_get_xbp_node_info_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_xbp_limits( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, XBP_LIMITS *p ) { - int rc; - - xmt_cmd_us( pmctl, GPS_PORT_INFO_IDX, idx ); + int rc = mbgextio_req_data( pmctl, p_addr, GPS_XBP_LIMITS ); - rc = mbgextio_rcv_msg( pmctl, GPS_PORT_INFO_IDX ); - - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.port_info_idx; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.xbp_limits; + _mbg_swab_dummy( p ); + } return rc; -} // mbgextio_get_port_info_idx - +} // mbgextio_get_xbp_limits /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_port_settings_idx( MBG_MSG_CTL *pmctl, - const PORT_SETTINGS *p, uint16_t idx ) +/** + * @brief Read the ::XBP_NODE_LIMITS to check how many ports are provided + * + * @note Only supported if ::XBP_FEAT_MASK_NODES is set in ::XBP_LIMITS::features. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_xbp_limits + * @see ::mbgextio_get_xbp_node_info_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_xbp_node_limits( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, XBP_NODE_LIMITS *p ) { - GPS_CMD cmd = GPS_PORT_SETTINGS_IDX; - MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; - int rc; - - pmb->u.msg_data.port_settings_idx.port_settings = *p; - pmb->u.msg_data.port_settings_idx.idx = idx; + int rc = mbgextio_req_data( pmctl, p_addr, GPS_XBP_NODE_LIMITS ); - pmb->hdr.len = sizeof( pmb->u.msg_data.port_settings_idx ); - pmb->hdr.cmd = cmd | GPS_REQACK; - rc = xmt_tbuff( pmctl ); - -#if _MBGEXTIO_DIRECT_RC + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.xbp_node_limits; + _mbg_swab_dummy( p ); + } return rc; -#else +} // mbgextio_get_xbp_node_limits - rc = mbgextio_rcv_msg( pmctl, cmd ); - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) +/*HDR*/ +/** + * @brief Read the ::XBP_NODE_INFO for a specific node in ::XBP_NODE_INFO_IDX format + * + * The supported number of nodes is provided by ::XBP_NODE_LIMITS::node_count. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::XBP_NODE_LIMITS::node_count-1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_xbp_limits + * @see ::mbgextio_get_xbp_node_limits + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_xbp_node_info_idx( MBG_MSG_CTL *pmctl, + const XBP_ADDR *p_addr, XBP_NODE_INFO_IDX *p, uint16_t idx ) +{ + int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_XBP_NODE_INFO_IDX, idx ); + + if ( ( rc == MBG_SUCCESS ) && p ) { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. + *p = pmctl->rcv.pmb->u.msg_data.xbp_node_info_idx; + _mbg_swab_dummy( p ); } - return 0; - -#endif + return rc; -} // mbgextio_set_port_settings_idx +} // mbgextio_get_xbp_node_info_idx -/*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_pout_info_idx( MBG_MSG_CTL *pmctl, - POUT_INFO_IDX *p, uint16_t idx ) +static /*HDR*/ +void handle_xbp_node( XBP_NODE_INFO *p_ni, long idx ) { - int rc; + XBP_ADDR * p_addr = &p_ni->addr; + RECEIVER_INFO *p_ri = &p_ni->ri; + int i; - xmt_cmd_us( pmctl, GPS_POUT_INFO_IDX, idx ); + printf( "Node info %li:", idx ); - rc = mbgextio_rcv_msg( pmctl, GPS_POUT_INFO_IDX ); + printf( " addr %02X:", p_addr->hop_count ); - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.pout_info_idx; + for ( i = 0; i < MAX_XBP_CASC_LVL; i++ ) + printf( "%02X ", p_addr->addr[i] ); - return rc; + printf( ", state: %i", p_ni->state ); -} // mbgextio_get_pout_info_idx + printf( ", name: \"%s\"", p_ri->model_name ); + + printf( "\n" ); + +} // handle_xbp_node /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_pout_settings_idx( MBG_MSG_CTL *pmctl, - const POUT_SETTINGS *p, uint16_t idx ) +/** + * @brief Read the ::XBP_NODE_INFO for a specific node in ::XBP_NODE_INFO_IDX format + * //##+++++++++++++++++++++++++ + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_setup_xbp_node_list( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr ) { - GPS_CMD cmd = GPS_POUT_SETTINGS_IDX; - MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; - int rc; - - pmb->u.msg_data.pout_settings_idx.pout_settings = *p; - pmb->u.msg_data.pout_settings_idx.idx = idx; + static int recursion_count; - pmb->hdr.len = sizeof( pmb->u.msg_data.pout_settings_idx ); - pmb->hdr.cmd = cmd | GPS_REQACK; - rc = xmt_tbuff( pmctl ); + XBP_NODE_LIMITS node_limits; + int rc = MBG_SUCCESS; + int16_t i; -#if _MBGEXTIO_DIRECT_RC + // This function can be called recursively, so first of all check the recursion level. + if ( recursion_count > MAX_XBP_CASC_LVL ) //##++++ TODO: or even ">=" ?? + { + // This should never happen, but we check this anyway. + rc = MBG_ERR_XBP_CASC_LVL; + goto out; + } - return rc; + recursion_count++; -#else + rc = mbgextio_get_xbp_node_limits( pmctl, p_addr, &node_limits ); - rc = mbgextio_rcv_msg( pmctl, cmd ); + if ( rc != MBG_SUCCESS ) + goto out_dec; - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + for ( i = 0; i < node_limits.node_count; i++ ) { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. - } + XBP_NODE_INFO_IDX node_info_idx; - return 0; + rc = mbgextio_get_xbp_node_info_idx( pmctl, p_addr, &node_info_idx, i ); -#endif + if ( rc != MBG_SUCCESS ) + break; -} // mbgextio_set_pout_settings_idx + #if 1 && DEBUG + if ( (ulong) node_info_idx.idx != (ulong) i ) + printf( "** Warning: received XBP index %li for idx %li in %s\n", + (ulong) node_info_idx.idx, (ulong) i, __func__ ); + #endif + handle_xbp_node( &node_info_idx.node_info, node_info_idx.idx ); + } +out_dec: + if ( recursion_count > 0 ) + recursion_count--; + else + { + // recursion count is unexpectedly 0 + } -/*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_clr_ucap_buff( MBG_MSG_CTL *pmctl ) -{ - return mbgextio_xmt_cmd( pmctl, GPS_CLR_UCAP_BUFF ); +out: + return rc; -} // mbgextio_clr_ucap_buff +} // mbgextio_setup_xbp_node_list /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_time_scale_info( MBG_MSG_CTL *pmctl, - MBG_TIME_SCALE_INFO *p ) +/** + * @brief Read a ::UTC parameter structure from a device. + * + * The ::UTC parameter structure contains the current UTC/GPS time offset + * as well as information on an eventually upcoming leap second. + * + * @note Only supported by GPS/GNSS and some PZF receivers //##+++++++ TODO Associated feature flag? + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_utc_param + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_get_utc_param( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, UTC *p ) { - int rc; - - xmt_cmd( pmctl, GPS_TIME_SCALE ); + int rc = mbgextio_req_data( pmctl, p_addr, GPS_UTC ); - rc = mbgextio_rcv_msg( pmctl, GPS_TIME_SCALE ); - - if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.time_scale_info; + if ( ( rc == MBG_SUCCESS ) && p ) + { + *p = pmctl->rcv.pmb->u.msg_data.utc; + _mbg_swab_utc_parm( p ); + } return rc; -} // mbgextio_get_time_scale_info +} // mbgextio_get_utc_param /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_set_time_scale_settings( MBG_MSG_CTL *pmctl, - const MBG_TIME_SCALE_SETTINGS *p ) +/** + * @brief Write a ::UTC parameter structure to a device. + * + * The ::UTC parameter structure contains the current UTC/GPS time offset + * as well as information on an eventually upcoming leap second. + * + * @note Only supported by GPS/GNSS and some PZF receivers //##+++++++ TODO Associated feature flag? + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_utc_param + */ +_NO_MBG_API_ATTR int _MBG_API mbgextio_set_utc_param( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, const UTC *p ) { - GPS_CMD cmd = GPS_TIME_SCALE; + GPS_CMD cmd = GPS_UTC | OPT_GPS_ACK_CODE; + UTC *p_data = &pmctl->xmt.pmb->u.msg_data.utc; -#if _MBGEXTIO_DIRECT_RC - - return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); - -#else - - MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; - int rc; - - pmb->u.msg_data.time_scale_settings = *p; - - pmb->hdr.len = sizeof( pmb->u.msg_data.time_scale_settings ); - pmb->hdr.cmd = cmd | GPS_REQACK; - xmt_tbuff( pmctl ); - - rc = mbgextio_rcv_msg( pmctl, cmd ); - - if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) - { - return -1; // no ack packet received - // data has not been set or, if GPS_AUTO_ON has been - // transmitted before, an automatic frame (current time, capture) - // has been sent before the acknowledge code. - } + #if _USE_MUTEX + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); + #endif - return 0; + *p_data = *p; + _mbg_swab_utc_parm( p_data ); -#endif + return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) ); -} // mbgextio_set_time_scale_settings +} // mbgextio_set_utc_param diff --git a/mbglib/common/mbgextio.h b/mbglib/common/mbgextio.h index bbe6be9..adb0154 100644 --- a/mbglib/common/mbgextio.h +++ b/mbglib/common/mbgextio.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgextio.h 1.8 2011/04/08 11:26:09 martin REL_M $ + * $Id: mbgextio.h 1.16.1.11 2015/07/22 16:02:08 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,68 @@ * * ----------------------------------------------------------------------- * $Log: mbgextio.h $ + * Revision 1.16.1.11 2015/07/22 16:02:08 martin + * Started to support variable USB endpoint numbers. + * Revision 1.16.1.10 2015/07/14 15:10:27 martin + * Updated function prototypes. + * Revision 1.16.1.9 2015/07/14 13:24:59 martin + * Updated function prototypes. + * Revision 1.16.1.8.1.10 2015/05/27 09:23:57 daniel + * Fixed USB_DIRECT_IO stuff + * Revision 1.16.1.8.1.9 2015/05/21 11:01:00 martin + * Updated function prototypes. + * Revision 1.16.1.8.1.8 2015/05/19 13:20:59 daniel + * Preliminary support for USB_DIRECT_IO + * Revision 1.16.1.8.1.6 2015/05/13 09:50:51 martin + * Added mbgextio_xmt_ack() and mbgextio_xmt_nack(). + * Revision 1.16.1.8.1.5 2015/04/15 15:36:19 martin + * Doxygen fixes. + * Revision 1.16.1.8.1.4 2015/03/03 10:14:50 martin + * Updated function prototypes. + * Revision 1.16.1.8.1.3 2014/11/04 15:09:37 martin + * More XBP stuff. + * Revision 1.16.1.8.1.2 2014/11/04 11:31:17 martin + * Revision 1.16.1.8.1.1 2014/10/30 16:14:07 martin + * Started to support XBP addressing. + * Revision 1.16.1.8 2014/10/30 16:03:09 martin + * Doxygen fixes. + * Revision 1.16.1.7 2014/10/30 14:47:06 martin + * Support FTDI devices. + * Updated USB support. + * Updated function prototypes. + * Revision 1.16.1.6 2013/11/28 15:51:48Z marvin + * Added mbgextio_get_ntp_peer_state_idx. + * Revision 1.16.1.5 2013/11/26 16:06:48Z marvin + * Added mbgextio_get_ntp_sys_state. + * Revision 1.16.1.4 2013/11/21 07:46:52Z marvin + * Added mbgextio_xmt_secu_settings. + * Revision 1.16.1.3 2013/11/12 12:12:05Z marvin + * Changed calls for NTP info and settings. + * Revision 1.16.1.2 2013/10/14 08:54:22Z marvin + * Added mbgextio_set_ntp_clnt_mode_cfg. + * Revision 1.16.1.1 2013/09/25 11:10:10Z marvin + * Added support for NTP and PTP. + * Revision 1.16 2013/09/10 08:56:35Z marvin + * Changed Doxygen comments. + * Revision 1.15 2013/09/05 15:11:40Z marvin + * Added support for LAN interface setup. + * Added support for PTP state. + * Added support for XMR. + * Added support for NTP info. + * Revision 1.14 2013/09/02 15:16:49Z marvin + * Added support for XMR (get multi ref info, set multi ref settings) + * Revision 1.13 2013/08/28 11:01:42Z marvin + * Added read and set tr_distance and gnss_mode. + * Revision 1.12 2013/04/11 14:18:47Z Gregoire + * new prototypes for sending havequick rx and tx settings to clock + * Revision 1.11 2013/02/06 15:44:57Z martin + * Updated function prototypes. + * Revision 1.10 2013/02/01 15:59:42 martin + * Updated function prototypes. + * Revision 1.9 2012/10/30 16:19:19 martin + * Support USB I/O. + * Started to migrate to opaque stuctures. + * Updated function prototypes. * Revision 1.8 2011/04/08 11:26:09 martin * New macros _ttm_time_set_unavail() and _ttm_time_is_avail(). * Revision 1.7 2009/10/02 14:21:08 martin @@ -38,7 +100,10 @@ /* Other headers to be included */ +#include #include +#include + #include #ifdef _MBGEXTIO @@ -48,7 +113,6 @@ #define _ext extern #endif - /* Start of header body */ @@ -71,11 +135,34 @@ #endif // _USE_SERIAL_IO +#if !_USE_SERIAL_IO_FTDI + // just to avoid build errors if USB not supported + #define FT_STATUS int + #define FT_HANDLE int +#endif + + +#if !_USE_USB_IO + // just to avoid build errors if USB not supported + struct usb_device + { + int dummy; + }; + + typedef int MBG_USB_DEVICE; + +#endif + + #if !defined MBGEXTIO_READ_BUFFER_SIZE - #if _USE_SOCKET_IO + #if _USE_SOCKET_IO || _USE_USB_IO #define MBGEXTIO_READ_BUFFER_SIZE 1000 #else - #define MBGEXTIO_READ_BUFFER_SIZE 10 + #if defined _USE_USB_DIRECT_IO + #define MBGEXTIO_READ_BUFFER_SIZE 512 // Max. USB transfer buffer size + #else + #define MBGEXTIO_READ_BUFFER_SIZE 10 + #endif #endif #endif @@ -111,57 +198,1965 @@ extern "C" { /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ - _MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl, const char *host, const char *passwd ) ; - _MBG_API_ATTR int _MBG_API mbgextio_open_serial( MBG_MSG_CTL *pmctl, const char *dev, uint32_t baud_rate, const char *framing ) ; - _MBG_API_ATTR void _MBG_API mbgextio_close_connection( MBG_MSG_CTL *pmctl ) ; - _MBG_API_ATTR int _MBG_API mbgextio_force_connection( const char *dev ) ; - _MBG_API_ATTR void _MBG_API mbgextio_set_char_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) ; - _MBG_API_ATTR ulong _MBG_API mbgextio_get_char_rcv_timeout( const MBG_MSG_CTL *pmctl ) ; - _MBG_API_ATTR void _MBG_API mbgextio_set_msg_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) ; - _MBG_API_ATTR ulong _MBG_API mbgextio_get_msg_rcv_timeout( const MBG_MSG_CTL *pmctl ) ; - _MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd, const void *p, int n_bytes ) ; - _MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) ; - _MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) ; - _MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t us ) ; - _MBG_API_ATTR int _MBG_API mbgextio_req_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) ; - _MBG_API_ATTR int _MBG_API mbgextio_req_data_idx( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t idx ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_sw_rev( MBG_MSG_CTL *pmctl, SW_REV *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_bvar_stat( MBG_MSG_CTL *pmctl, BVAR_STAT *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_time( MBG_MSG_CTL *pmctl, TTM *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_time( MBG_MSG_CTL *pmctl, const TTM *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl, LLA lla ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_pos_lla( MBG_MSG_CTL *pmctl, const LLA lla ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_tzdl( MBG_MSG_CTL *pmctl, TZDL *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_tzdl( MBG_MSG_CTL *pmctl, const TZDL *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_port_parm( MBG_MSG_CTL *pmctl, PORT_PARM *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_port_parm( MBG_MSG_CTL *pmctl, const PORT_PARM *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_synth( MBG_MSG_CTL *pmctl, SYNTH *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_synth( MBG_MSG_CTL *pmctl, const SYNTH *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_ant_info( MBG_MSG_CTL *pmctl, ANT_INFO *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, TTM *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_enable_flags( MBG_MSG_CTL *pmctl, ENABLE_FLAGS *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_enable_flags( MBG_MSG_CTL *pmctl, const ENABLE_FLAGS *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_stat_info( MBG_MSG_CTL *pmctl, STAT_INFO *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_ant_cable_len( MBG_MSG_CTL *pmctl, ANT_CABLE_LEN *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_ant_cable_len( MBG_MSG_CTL *pmctl, const ANT_CABLE_LEN *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_irig_tx_info( MBG_MSG_CTL *pmctl, IRIG_INFO *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_irig_tx_settings( MBG_MSG_CTL *pmctl, const IRIG_SETTINGS *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_irig_rx_info( MBG_MSG_CTL *pmctl, IRIG_INFO *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_irig_rx_settings( MBG_MSG_CTL *pmctl, const IRIG_SETTINGS *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_ref_offs( MBG_MSG_CTL *pmctl, MBG_REF_OFFS *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_ref_offs( MBG_MSG_CTL *pmctl, const MBG_REF_OFFS *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_debug_status( MBG_MSG_CTL *pmctl, MBG_DEBUG_STATUS *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_opt_info( MBG_MSG_CTL *pmctl, MBG_OPT_INFO *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_opt_settings( MBG_MSG_CTL *pmctl, const MBG_OPT_SETTINGS *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_str_type_info_idx( MBG_MSG_CTL *pmctl, STR_TYPE_INFO_IDX *p, uint16_t idx ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_port_info_idx( MBG_MSG_CTL *pmctl, PORT_INFO_IDX *p, uint16_t idx ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_port_settings_idx( MBG_MSG_CTL *pmctl, const PORT_SETTINGS *p, uint16_t idx ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_pout_info_idx( MBG_MSG_CTL *pmctl, POUT_INFO_IDX *p, uint16_t idx ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_pout_settings_idx( MBG_MSG_CTL *pmctl, const POUT_SETTINGS *p, uint16_t idx ) ; - _MBG_API_ATTR int _MBG_API mbgextio_clr_ucap_buff( MBG_MSG_CTL *pmctl ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_time_scale_info( MBG_MSG_CTL *pmctl, MBG_TIME_SCALE_INFO *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_set_time_scale_settings( MBG_MSG_CTL *pmctl, const MBG_TIME_SCALE_SETTINGS *p ) ; + /** + * @brief Send security settings for the socket connection + * + * If new_passwd is not a NULL pointer, the old_passwd + * will be overwritten by the new_passwd. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] old_passwd Pointer to the current LAN port password of the device + * @param[in] new_passwd Pointer to the new LAN port password for the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_socket + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_secu_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const char *old_passwd, const char *new_passwd ) ; + + /** + * @brief Open a binary communication channel via a LAN/socket connection + * + * @param[in] host DNS name or IP address of the target device + * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure + * allocated and set up by this call. + * Pointer is set to NULL on error. + * @param[in] passwd Password string for the encrypted communication + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_serial + * @see ::mbgextio_open_serial_ftdi + * @see ::mbgextio_open_usb + * @see ::mbgextio_open_usb_direct_io + * @see ::mbgextio_close_connection + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_open_socket( const char *host, MBG_MSG_CTL **ppmctl, const char *passwd ) ; + + /** + * @brief Open a binary communication channel using direct serial I/O + * + * Commonly used serial parameters are 19200/8N1, see + * ::MBG_DEFAULT_BAUDRATE and ::MBG_DEFAULT_FRAMING. + * Some newer devices may also support ::MBG_DEFAULT_BAUDRATE_HS. + * + * @param[in] dev Name of the serial port to which the device is connected, + * depending on the naming conventions of the host system. + * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure + * allocated and set up by this call. Set to NULL on error. + * @param[in] baud_rate Baud rate used for serial communication + * @param[in] framing Framing used for serial communication + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_force_conn_serial + * @see ::mbgextio_open_serial_ftdi + * @see ::mbgextio_force_conn_serial_ftdi + * @see ::mbgextio_open_socket + * @see ::mbgextio_open_usb + * @see ::mbgextio_open_usb_direct_io + * @see ::mbgextio_close_connection + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_open_serial( const char *dev, MBG_MSG_CTL **ppmctl, uint32_t baud_rate, const char *framing ) ; + + /** + * @brief Get the port handle of a serial FTDI device + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return the port handle retrieved from the message control structure + */ + _NO_MBG_API_ATTR FT_HANDLE _MBG_API mbgextio_get_serial_ftdi_port_handle( MBG_MSG_CTL *pmctl ) ; + + /** + * @brief Open a binary communication channel using serial FTDI D2xx port + * + * Commonly used serial parameters are 19200/8N1, see + * ::MBG_DEFAULT_BAUDRATE and ::MBG_DEFAULT_FRAMING. + * Some newer devices may also support ::MBG_DEFAULT_BAUDRATE_HS. + * + * @param[in] device_num device number from a list set up by FT_ListDevices() + * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure + * allocated and set up by this call. Set to NULL on error. + * @param[in] baud_rate Baud rate used for serial communication + * @param[in] framing Framing used for serial communication + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_force_conn_serial_ftdi + * @see ::mbgextio_open_serial + * @see ::mbgextio_force_conn_serial + * @see ::mbgextio_open_socket + * @see ::mbgextio_open_usb + * @see ::mbgextio_open_usb_direct_io + * @see ::mbgextio_close_connection + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_open_serial_ftdi( int device_num, MBG_MSG_CTL **ppmctl, uint32_t baud_rate, const char *framing ) ; + + /** + * @brief Open a binary communication channel using direct USB I/O + * + * @param[in] usbdev The USB device to communicate with. + * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure + * allocated and set up by this call. Set to NULL on error. + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_socket + * @see ::mbgextio_open_serial + * @see ::mbgextio_open_serial_ftdi + * @see ::mbgextio_close_connection + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_open_usb( const MBG_USB_DEVICE *usbdev, MBG_MSG_CTL **ppmctl ) ; + + /** + * @brief Open a binary communication channel using direct USB I/O + * + * Currently it is only supported by Linux systems since a file like + * USB device (e.g. "/dev/mbgims") is required and needs to support + * basic I/O operations like write, read, etc... + * + * @param[in] dev Path to file like USB device + * @param[in] flags Bitwise OR flags of access modes like W,RW,RO,etc. + * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure + * allocated and set up by this call. Set to NULL on error. + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_socket + * @see ::mbgextio_open_serial + * @see ::mbgextio_open_serial_ftdi + * @see ::mbgextio_open_usb + * @see ::mbgextio_open_usb_direct_io + * @see ::mbgextio_close_connection + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_open_usb_direct_io( const char *dev, int flags, MBG_MSG_CTL **ppmctl ) ; + + /** + * @brief Close a binary communication channel and release resources + * + * Closes a binary communication channel which has been opened by one + * of the mbgextio_open_...() functions and releases the buffers which + * have been allocated when the channel was opened. + * + * The pointer to the message control structure passed by address is set + * to NULL after the channel has been closed and the resources have + * been released. + * + * @param[in,out] ppmctl Address of a pointer to a message control structure + * created when the communication channel was opened + * by one of the mbgextio_open_...() calls. + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_socket + * @see ::mbgextio_open_serial + * @see ::mbgextio_open_serial_ftdi + * @see ::mbgextio_open_usb + * @see ::mbgextio_open_usb_direct_io + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_close_connection( MBG_MSG_CTL **ppmctl ) ; + + /** + * @brief Try to force a serial connection to a device + * + * A device's serial port may have been configured to work by default + * in a way which is not appropriate for binary communication, e.g. using + * a low communication speed, or some framing like "7E2" which messes up + * binary data since the parity bit overrides a data bit. + * + * This function sends a special ASCII string to a device which lets the device + * temporarily switch to a specific baud rate and 8N1 framing which is usually + * used for binary communication, see ::MBG_DEFAULT_BAUDRATE, + * ::MBG_DEFAULT_BAUDRATE_HS, and ::MBG_DEFAULT_FRAMING. + * + * Since the current settings of the device's serial port are unknown this + * this command is sent in all common combinations of baud rates and + * framings. + * + * If the connected device supports this it should be possible to open + * the serial communication channel using the default parameters after + * this function has finished. + * + * @param[in] dev Name of the serial port to which the device is connected, + * depending on the naming conventions of the target system + * + * @return One of the negative @ref MBG_ERROR_CODES on error, + * else the determined baud rate. + * + * @see ::mbgextio_open_serial + * @see ::mbgextio_open_serial_ftdi + */ + _NO_MBG_API_ATTR long _MBG_API mbgextio_force_conn_serial( const char *dev ) ; + + /** + * @brief Try to force a serial connection to a device via the FTDI API + * + * A device's serial port may have been configured to work by default + * in a way which is not appropriate for binary communication, e.g. using + * a low communication speed, or some framing like "7E2" which messes up + * binary data since the parity bit overrides a data bit. + * + * This function sends a special ASCII string to a device which lets the device + * temporarily switch to a specific baud rate and 8N1 framing which is usually + * used for binary communication, see ::MBG_DEFAULT_BAUDRATE, + * ::MBG_DEFAULT_BAUDRATE_HS, and ::MBG_DEFAULT_FRAMING. + * + * Since the current settings of the device's serial port are unknown this + * this command is sent in all common combinations of baud rates and + * framings. + * + * If the connected device supports this it should be possible to open + * the serial communication channel using the default parameters after + * this function has finished. + * + * @param[in] device_num device number from a list set up by FT_ListDevices() + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_open_serial_ftdi + */ + _NO_MBG_API_ATTR long _MBG_API mbgextio_force_conn_serial_ftdi( int device_num ) ; + + /** + * @brief Retrieve address of the allocated receive buffer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Address of the allocated receive buffer + * + * @see ::mbgextio_get_rcv_buffer_size + * @see ::mbgextio_get_xmt_buffer_addr + * @see ::mbgextio_get_xmt_buffer_size + */ + _NO_MBG_API_ATTR MBG_MSG_BUFF * _MBG_API mbgextio_get_rcv_buffer_addr( MBG_MSG_CTL *pmctl ) ; + + /** + * @brief Retrieve size of the allocated receive buffer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Size of the allocated receive buffer + * + * @see ::mbgextio_get_rcv_buffer_addr + * @see ::mbgextio_get_xmt_buffer_addr + * @see ::mbgextio_get_xmt_buffer_size + */ + _NO_MBG_API_ATTR size_t _MBG_API mbgextio_get_rcv_buffer_size( MBG_MSG_CTL *pmctl ) ; + + /** + * @brief Retrieve address of the allocated transmit buffer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Address of the allocated transmit buffer + * + * @see ::mbgextio_get_rcv_buffer_addr + * @see ::mbgextio_get_rcv_buffer_size + * @see ::mbgextio_get_xmt_buffer_size + */ + _NO_MBG_API_ATTR MBG_MSG_BUFF * _MBG_API mbgextio_get_xmt_buffer_addr( MBG_MSG_CTL *pmctl ) ; + + /** + * @brief Retrieve size of the allocated transmit buffer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Size of the allocated transmit buffer + * + * @see ::mbgextio_get_rcv_buffer_addr + * @see ::mbgextio_get_rcv_buffer_size + * @see ::mbgextio_get_xmt_buffer_addr + */ + _NO_MBG_API_ATTR size_t _MBG_API mbgextio_get_xmt_buffer_size( MBG_MSG_CTL *pmctl ) ; + + /** + * @brief Set character receive timeout value + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] new_timeout New timeout value [ms] + * + * @see ::mbgextio_get_char_rcv_timeout + * @see ::mbgextio_set_msg_rcv_timeout + * @see ::mbgextio_get_msg_rcv_timeout + */ + _NO_MBG_API_ATTR void _MBG_API mbgextio_set_char_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) ; + + /** + * @brief Get character receive timeout value + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Current timeout value [ms] + * + * @see ::mbgextio_set_char_rcv_timeout + * @see ::mbgextio_set_msg_rcv_timeout + * @see ::mbgextio_get_msg_rcv_timeout + */ + _NO_MBG_API_ATTR ulong _MBG_API mbgextio_get_char_rcv_timeout( const MBG_MSG_CTL *pmctl ) ; + + /** + * @brief Set message receive timeout value + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] new_timeout New timeout value [ms] + * + * @see ::mbgextio_set_char_rcv_timeout + * @see ::mbgextio_get_char_rcv_timeout + * @see ::mbgextio_get_msg_rcv_timeout + */ + _NO_MBG_API_ATTR void _MBG_API mbgextio_set_msg_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) ; + + /** + * @brief Get message receive timeout value + * + * @param[in,out] pmctl Pointer to a valid message control structure + * + * @return Current timeout value [ms] + * + * @see ::mbgextio_set_char_rcv_timeout + * @see ::mbgextio_get_char_rcv_timeout + * @see ::mbgextio_set_msg_rcv_timeout + */ + _NO_MBG_API_ATTR ulong _MBG_API mbgextio_get_msg_rcv_timeout( const MBG_MSG_CTL *pmctl ) ; + + /** + * @brief Generic reception of a binary message + * + * @note A certain message type to be waited for can be specified by + * passing one of the ::GPS_CMD_CODES. + * If the special cmd code ::GPS_WILDCARD is specified the function returns + * successfully after *any* type of binary message has been received. + * + * //##++ TODO: callback function to handle asynchronous spontaneous messages + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES, or ::GPS_WILDCARD + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_rcv_msg + * @see ::mbgextio_xmt_msg //##++++ + * @see ::mbgextio_xmt_cmd + * @see ::mbgextio_req_data + * @see ::mbgextio_xmt_cmd_us + * @see ::mbgextio_req_data_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd ) ; + + /** + * @brief Set up and send a generic binary message + * + * @note This function should preferably be used only as low level function + * called from within more specific functions used to send specific data. + * If this function is called directly with a buffer to be sent then the + * transmit mutex is acquired by this function. However, other (higher level) + * API functions which set up the transmit buffer directly have to acquire + * the transmit mutex by themselves before they set up the transmit buffer, + * and pass a NULL pointer to indicate the transmit buffer has already been + * set up. The correct number of bytes to send (n_bytes) has to be specified + * anyway, though. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * @param[in] p Address of a data structure according to the specified cmd parameter, or NULL + * @param[in] n_bytes Size of the data structure addressed by parameter p + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd, const void *p, uint16_t n_bytes ) ; + + /** + * @brief Transmit a command-only message without additional data. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_xmt_msg + * @see ::mbgextio_rcv_msg + * @see ::mbgextio_req_data + * @see ::mbgextio_xmt_cmd_us + * @see ::mbgextio_req_data_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd ) ; + + /** + * @brief Transmit a message without a single ushort (uint16_t) parameter + * + * The ushort parameter is often used to send an index value when requesting + * a certain element of an array of same data structures. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * @param[in] us The ushort parameter for the command code + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_xmt_msg + * @see ::mbgextio_rcv_msg + * @see ::mbgextio_xmt_cmd + * @see ::mbgextio_req_data + * @see ::mbgextio_req_data_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd, uint16_t us ) ; + + /** + * @brief Transmit a message without a single ushort (16 bit) parameter + * + * The ushort parameter is often used to send an index value when requesting + * a specific element of an array of data structures. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_xmt_msg + * @see ::mbgextio_rcv_msg + * @see ::mbgextio_xmt_cmd + * @see ::mbgextio_xmt_cmd_us + * @see ::mbgextio_req_data_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_req_data( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd ) ; + + /** + * @brief Read a specific element of an array of data structures + * + * The type of data is implicitely associated with the cmd parameter. + * Usually the number of supported array elements has to be determined + * by some other means, e.g. from a field in the ::RECEIVER_INFO structure. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES + * @param[in] idx The index of the array element to read + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_xmt_msg + * @see ::mbgextio_rcv_msg + * @see ::mbgextio_xmt_cmd + * @see ::mbgextio_req_data + * @see ::mbgextio_xmt_cmd_us + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_req_data_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd, uint16_t idx ) ; + + /** + * @brief Read a receiver info structure + * + * The ::RECEIVER_INFO should be read at first to identify the connected + * device and determine the basic features supported by the device. + * + * @note Some very old devices may not provide a ::RECEIVER_INFO, + * so ::mbgextio_setup_receiver_info should be called preferably + * to read the receiver info using this function, if supported, + * or set up a default structure for devices which don't provide + * a receiver info. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_setup_receiver_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_receiver_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, RECEIVER_INFO *p ) ; + + /** + * @brief Setup a receiver info structure + * + * The ::RECEIVER_INFO should be read at first to identify the connected + * device and determine the basic features supported by the device. + * + * @note Some very old devices may not provide a ::RECEIVER_INFO. + * This function tries to read the ::RECEIVER_INFO from the device, + * and sets up a default structure if the device doesn't support this. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_receiver_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_setup_receiver_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, RECEIVER_INFO *p ) ; + + /** + * @brief Read the software revision + * + * @deprecated This function is deprecated since the ::SW_REV structure + * is also a member of the ::RECEIVER_INFO. This call may be required, + * though, for very old devices which don't support the ::RECEIVER_INFO. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_setup_receiver_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_sw_rev( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, SW_REV *p ) ; + + /** + * @brief Read the status of buffered variables + * + * @note Only supported if ::GPS_MODEL_HAS_BVAR_STAT + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_bvar_stat( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, BVAR_STAT *p ) ; + + /** + * @brief Read the current time as ::TTM strucure + * + * @note This function is only supported by GPS receivers. + * + * The returned time is not very accurate since the response time + * transmission delay can't be determmined. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_time( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, TTM *p ) ; + + /** + * @brief Set the device's time by sending a ::TTM strucure + * + * @note The function is not supported by all devices. Time has to be + * passed as local time according to the device's ::TZDL settings. + * New time is only set with some tens of ms accuracy. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_time( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const TTM *p ) ; + + /** + * @brief Set the device's position by sending an ::LLA array + * + * @note This function is only supported by GPS receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] lla Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_pos_lla( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const LLA lla ) ; + + /** + * @brief Read the current receiver position as ::LLA array + * + * @note This function is only supported by GPS receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] lla Pointer to the data array to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, LLA lla ) ; + + /** + * @brief Read the current receiver position as ::XYZ array + * + * @note This function is only supported by GPS receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] xyz Pointer to the data array to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_pos_xyz( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, XYZ xyz ) ; + + /** + * @brief Read the current receiver position as ::POS structure + * + * @note This function is only supported by GPS receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p_pos Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_pos( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, POS *p_pos ) ; + + /** + * @brief Read the local time conversion parameters in ::TZDL format + * + * @note Some devices may not support ::TZDL settings + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_tzdl( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, TZDL *p ) ; + + /** + * @brief Set the local time conversion parameters in ::TZDL format + * + * @note Some devices may not support ::TZDL settings + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_tzdl( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const TZDL *p ) ; + + /** + * @brief Read serial port parameters in ::PORT_PARM format + * + * @deprecated This function is deprecated since the ::PORT_PARM structure + * supports only 2 serial ports, and does not not support configuration + * of a string type. The function ::mbgextio_get_serial_settings should + * be used instead. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_serial_settings + * @see ::mbgextio_save_serial_settings + * @see ::mbgextio_set_port_parm + * @see ::mbgextio_setup_receiver_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_port_parm( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, PORT_PARM *p ) ; + + /** + * @brief Send serial port parameters in ::PORT_PARM format + * + * @deprecated This function is deprecated since the ::PORT_PARM structure + * supports only 2 serial ports, and does not not support configuration + * of a string type. The function ::mbgextio_save_serial_settings should + * be used instead. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_serial_settings + * @see ::mbgextio_save_serial_settings + * @see ::mbgextio_get_port_parm + * @see ::mbgextio_setup_receiver_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_port_parm( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const PORT_PARM *p ) ; + + /** + * @brief Read the frequency synthesizer settings + * + * @note Some devices may not provide a frequency synthesizer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_synth + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_synth( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, SYNTH *p ) ; + + /** + * @brief Write the frequency synthesizer settings + * + * @note Some devices may not provide a frequency synthesizer + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_synth + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_synth( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const SYNTH *p ) ; + + /** + * @brief Read the GPS antenna info structure + * + * @note This is only supported by GPS receivers. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ant_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, ANT_INFO *p ) ; + + /** + * @brief Read a user capture event in ::TTM format + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_clr_ucap_buff + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, TTM *p ) ; + + /** + * @brief Read the enable flags controlling when output signals are enabled + * + * @note Some devices may not support ::ENABLE_FLAGS + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_enable_flags + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_enable_flags( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, ENABLE_FLAGS *p ) ; + + /** + * @brief Send the enable flags controlling when output signals are enabled + * + * @note Some devices may not support ::ENABLE_FLAGS + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_enable_flags + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_enable_flags( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const ENABLE_FLAGS *p ) ; + + /** + * @brief Read GPS status info + * + * @note This is only supported by GPS receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_stat_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, STAT_INFO *p ) ; + + /** + * @brief Read the configured length of the antenna cable + * + * This is only supported by GPS/GNSS receivers, check ::GPS_MODEL_HAS_ANT_CABLE_LENGTH + * + * @note Some older devices may not reply to this request unless + * the application has registered itself as terminal application + * (GPS_AUTO_ON is not sufficient). + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_ant_cable_len + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ant_cable_len( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, ANT_CABLE_LEN *p ) ; + + /** + * @brief Send the GPS antenna cable length configuration + * + * This is only supported by GPS/GNSS receivers, check ::GPS_MODEL_HAS_ANT_CABLE_LENGTH + + * @note Different devices may accept different maximum values, so the + * written value should be re-read using ::mbgextio_get_ant_cable_len + * to check if the parameter has been accepted. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ant_cable_len + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_ant_cable_len( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const ANT_CABLE_LEN *p ) ; + + /** + * @brief Read configuration info and supported features of the device's IRIG output + * + * @note This is only supported if ::GPS_HAS_IRIG_TX is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_irig_tx_settings + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_irig_tx_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, IRIG_INFO *p ) ; + + /** + * @brief Send new configuration settings for the device's IRIG output + * + * @note This is only supported if ::GPS_HAS_IRIG_TX is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_irig_tx_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_irig_tx_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const IRIG_SETTINGS *p ) ; + + /** + * @brief Read configuration info and supported features for the device's IRIG input + * + * @note This is only supported if ::GPS_HAS_IRIG_RX is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_irig_rx_settings + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_irig_rx_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, IRIG_INFO *p ) ; + + /** + * @brief Send new configuration settings for the device's IRIG input + * + * @note This is only supported if ::GPS_HAS_IRIG_RX is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_irig_rx_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_irig_rx_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const IRIG_SETTINGS *p ) ; + + /** + * @brief Read current ref offset to %UTC configuration + * + * @note This is only supported if ::GPS_HAS_REF_OFFS is set in ::RECEIVER_INFO::features, + * usually with IRIG receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_ref_offs + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ref_offs( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_REF_OFFS *p ) ; + + /** + * @brief Send new ref offset to %UTC settings + * + * @note This is only supported if ::GPS_HAS_REF_OFFS is set in ::RECEIVER_INFO::features, + * usually with IRIG receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ref_offs + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_ref_offs( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const MBG_REF_OFFS *p ) ; + + /** + * @brief Read current debug status + * + * @note This is only supported if ::GPS_HAS_DEBUG_STATUS is set in ::RECEIVER_INFO::features, + * usually with IRIG receivers + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_debug_status( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_DEBUG_STATUS *p ) ; + + /** + * @brief Read current optional settings and supported options + * + * @note This is only supported if ::GPS_HAS_OPT_SETTINGS is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_opt_settings + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_opt_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_OPT_INFO *p ) ; + + /** + * @brief Send new optional settings flags + * + * @note This is only supported if ::GPS_HAS_OPT_SETTINGS is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_opt_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_opt_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const MBG_OPT_SETTINGS *p ) ; + + /** + * @brief Read information on a specific supported string format + * + * Retrieve a single entry from an array of supported string types. + * The number of supported string types is specified in ::RECEIVER_INFO::n_str_type. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::RECEIVER_INFO::n_str_type - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_all_str_type_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_str_type_info_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, STR_TYPE_INFO_IDX *p, uint16_t idx ) ; + + /** + * @brief Read an array of all supported string types + * + * The number of supported string types is specified in ::RECEIVER_INFO::n_str_type. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] stii An array which can hold at least ::RECEIVER_INFO::n_str_type entries + * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_str_type_info_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_str_type_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, STR_TYPE_INFO_IDX stii[], const RECEIVER_INFO *p_ri ) ; + + /** + * @brief Read current settings and capabilities of a specific serial port + * + * The number of serial ports provided by the device is specified in ::RECEIVER_INFO::n_com_ports. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::RECEIVER_INFO::n_com_ports - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_all_port_info + * @see ::mbgextio_set_port_settings_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_port_info_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, PORT_INFO_IDX *p, uint16_t idx ) ; + + /** + * @brief Read an array of current settings and capabilities of all serial ports + * + * The number of serial ports provided by the device is specified in ::RECEIVER_INFO::n_com_ports. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] pii An array which can hold at least ::RECEIVER_INFO::n_com_ports entries + * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_port_info_idx + * @see ::mbgextio_set_port_settings_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_port_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, PORT_INFO_IDX pii[], const RECEIVER_INFO *p_ri ) ; + + /** + * @brief Send configuration settings for a specific serial port + * + * The number of serial ports provided by the device is specified in ::RECEIVER_INFO::n_com_ports. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * @param[in] idx Index of the serial port to be configured, 0..::RECEIVER_INFO::n_com_ports - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_port_info_idx + * @see ::mbgextio_get_all_port_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_port_settings_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const PORT_SETTINGS *p, uint16_t idx ) ; + + /** + * @brief Read current settings and capabilities of a specific programmable pulse output + * + * The number of supported pulse outputs is specified in ::RECEIVER_INFO::n_prg_out. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::RECEIVER_INFO::n_prg_out - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_all_pout_info + * @see ::mbgextio_set_pout_settings_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_pout_info_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, POUT_INFO_IDX *p, uint16_t idx ) ; + + /** + * @brief Read an array of current settings and capabilities of all programmable pulse outputs + * + * The number of supported pulse outputs is specified in ::RECEIVER_INFO::n_prg_out. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] pii An array which can hold at least ::RECEIVER_INFO::n_prg_out entries + * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_pout_info_idx + * @see ::mbgextio_set_pout_settings_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_pout_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, POUT_INFO_IDX *pii, const RECEIVER_INFO *p_ri ) ; + + /** + * @brief Send configuration settings for a specific programmable pulse output + * + * The number of supported pulse outputs is specified in ::RECEIVER_INFO::n_prg_out. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * @param[in] idx Index of the pulse output to be configured, 0..RECEIVER_INFO::n_prg_out - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_pout_info_idx + * @see ::mbgextio_get_all_pout_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_pout_settings_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const POUT_SETTINGS *p, uint16_t idx ) ; + + /** + * @brief Clear the user capture event buffer on-board the device + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ucap + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_clr_ucap_buff( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr ) ; + + /** + * @brief Read time scale configuration parameters + * + * @note Some devices may not support a configurable time scale + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_time_scale_settings + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_time_scale_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_TIME_SCALE_INFO *p ) ; + + /** + * @brief Send new time scale configuration settings + * + * @note Some devices may not support a configurable time scale + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_time_scale_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_time_scale_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const MBG_TIME_SCALE_SETTINGS *p ) ; + + /** + * @brief Clear the on-board event log + * + * @note Some devices don't provide an on-board event log + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_num_evt_log_entries + * @see ::mbgextio_get_first_evt_log_entry + * @see ::mbgextio_get_next_evt_log_entry + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_clr_evt_log( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr ) ; + + /** + * @brief Read the current number of entries in the on-board event log + * + * @note Some devices don't provide an on-board event log + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_clr_evt_log + * @see ::mbgextio_get_first_evt_log_entry + * @see ::mbgextio_get_next_evt_log_entry + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_num_evt_log_entries( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_NUM_EVT_LOG_ENTRIES *p ) ; + + /** + * @brief Return the first entry from the on-board event log + * + * This resets an internal counter, so subsequent calls to + * ::mbgextio_get_next_evt_log_entry will retrieve the following entries. + * + * @note Some devices don't provide an on-board event log + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_clr_evt_log + * @see ::mbgextio_get_num_evt_log_entries + * @see ::mbgextio_get_next_evt_log_entry + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_first_evt_log_entry( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_EVT_LOG_ENTRY *p ) ; + + /** + * @brief Return the next entry from the on-board event log + * + * This increments an internal counter, so subsequent calls will + * return subsequent entries. ::mbgextio_get_first_evt_log_entry + * should be called first to reset the counter and retrieve the + * oldest log entry. + * + * @note Some devices don't provide an on-board event log + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_clr_evt_log + * @see ::mbgextio_get_num_evt_log_entries + * @see ::mbgextio_get_first_evt_log_entry + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_next_evt_log_entry( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_EVT_LOG_ENTRY *p ) ; + + /** + * @brief Read the current IMS state and supported IMS features + * + * @note This is only supported if ::GPS_HAS_IMS is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ims_sensor_state_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ims_state( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_IMS_STATE *p ) ; + + /** + * @brief Read sensor values from a specified sensor on the device + * + * Info on supported sensors can be retrieved using ::mbgextio_get_ims_state. + * Valid range for the sensor index is [0..::MBG_IMS_STATE::num_sensors - 1]. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx The index of the array element to read + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ims_state + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ims_sensor_state_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_IMS_SENSOR_STATE_IDX *p, uint16_t idx ) ; + + /** + * @brief Set the XMR holdover interval + * + * @todo In which case is this supported? + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_holdover_interval_counter + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_holdover_interval( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const XMR_HOLDOVER_INTV *p ) ; + + /** + * @brief Read the XMR holdover interval counter + * + * @todo In which case is this supported? + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_holdover_interval + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_holdover_interval_counter( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, XMR_HOLDOVER_INTV *p ) ; + + /** + * @brief Read the local time conversion configuration in ::TZCODE format + * + * @note Some devices may not support ::TZCODE configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_tzcode + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_tzcode( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, TZCODE *p ) ; + + /** + * @brief Set the local time conversion configuration in ::TZCODE format + * + * @note Some devices may not support ::TZCODE configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_tzcode + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_tzcode( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const TZCODE *p ) ; + + /** + * @brief Send new configuration settings for the device's HAVEQUICK output + * + * @note This is only supported if ::GPS_HAS_HAVEQUICK is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_hq_tx_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, HAVEQUICK_SETTINGS *p ) ; + + /** + * @brief Send new configuration settings for the device's HAVEQUICK input + * + * @note This is only supported if ::MULTI_REF_HAVEQUICK is > 0 in ::XMULTI_REF_INSTANCES::n_inst //##+++++++++++++++++++++++ ??? + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_hq_rx_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, HAVEQUICK_SETTINGS *p ) ; + + /** + * @brief Read the distance from transmitter ::TR_DISTANCE format + * + * @note Some devices may not support ::TR_DISTANCE configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_tr_distance + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_tr_distance( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, TR_DISTANCE *p ) ; + + /** + * @brief Set the transmitter distance (km) in ::TR_DISTANCE format + * + * @note Some devices may not support ::TR_DISTANCE configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_tr_distance + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_tr_distance( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const TR_DISTANCE *p ) ; + + /** + * @brief Read current GNSS mode settings and supported features + * + * @note Some devices may not support GNSS configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to a ::MBG_GNSS_MODE_INFO structure to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_gnss_mode_settings + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_gnss_mode_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_GNSS_MODE_INFO *p ) ; + + /** + * @brief Write GNSS mode settings + * + * @note Some devices may not support GNSS configuration + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[in] p Pointer to a ::MBG_GNSS_MODE_SETTINGS structure to be sent + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_gnss_mode_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_gnss_mode_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const MBG_GNSS_MODE_SETTINGS *p ) ; + + /** + * @brief Read an array of all supported string types //##+++++++++++++++++++++++++++++++++++++++++++++++ TODO + * + * The number of supported string types is specified in ::RECEIVER_INFO::n_str_type. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] stii An array which can hold at least ::RECEIVER_INFO::n_str_type entries + * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_str_type_info_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_gnss_sat_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, STR_TYPE_INFO_IDX stii[], const RECEIVER_INFO *p_ri ) ; + + /** + * @brief Fill up a GNSS info structure //##+++++++++++++++++++++++++++++++++++++++++++++++ TODO + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[out] p_si Pointer to a ::STAT_INFO the data structure to return the received data + * @param[out] p_gmi Index of the NTP peer state to be configured, 0..::NTP_CLNT_MODE_INFO::n_supp_peers - 1 + * @param[out] p_gsii Blah ... //##++++++++++ TODO + * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_sys_state + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_get_ntp_clnt_mode_info + */ + int mbgextio_chk_get_gnss_info( MBG_MSG_CTL *pmctl, STAT_INFO *p_si, MBG_GNSS_MODE_INFO *p_gmi, GNSS_SAT_INFO_IDX *p_gsii, const RECEIVER_INFO *p_ri ) ; + + /** + * @brief Read the supported XMR features in ::XMULTI_REF_INFO_IDX format + * + * Only if ::GPS_HAS_XMULTI_REF is set in ::RECEIVER_INFO::features. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_xmr_info_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_xmr_info_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, XMULTI_REF_INFO_IDX *p ) ; + + /** + * @brief Read the supported XMR features ::XMULTI_REF_STATUS_IDX format + * + * @note Only for devices which supports Multi references + * @note GPS_HAS_XMULTI_REF feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_xmr_info_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_xmr_status_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, XMULTI_REF_STATUS_IDX *p ) ; + + /** + * @brief Save the supported XMR features ::XMULTI_REF_INFO_IDX format + * + * @note Some devices may not support Multi Refernce Sources + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_xmr_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const XMULTI_REF_SETTINGS_IDX *p ) ; + + /** + * @brief Read the lan interface configuration ::LAN_IF_INFO format + * + * @note ptp or xmr with ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_lan_if_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, LAN_IF_INFO *p ) ; + + /** + * @brief Read the lan ipv4 configuration state ::IP4_SETTINGS format + * + * @note ptp or xmr with ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ip4_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, IP4_SETTINGS *p ) ; + + /** + * @brief Save the current ipv4 settings ::IP4_SETTINGS format + * + * @note ptp or xmr with ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_ip4_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const IP4_SETTINGS *p ) ; + + /** + * @brief Read the current lan ipv4 state ::IP4_SETTINGS format + * + * @note ptp or xmr with ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ip4_state( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, IP4_SETTINGS *p ) ; + + /** + * @brief Read the current state of PTP device ::PTP_STATE format + * + * @note ptp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ptp_state( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, PTP_STATE *p ) ; + + /** + * @brief Read the ptp configuration ::PTP_CFG_INFO format + * + * @note ptp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ptp_cfg_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, PTP_CFG_INFO *p ) ; + + /** + * @brief Read the ptp configuration ::PTP_UC_MASTER_CFG_LIMITS format + * + * @note ptp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ptp_uc_master_cfg_limits( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, PTP_UC_MASTER_CFG_LIMITS *p ) ; + + /** + * @brief Read the ptp configuration ::ALL_PTP_UC_MASTER_INFO_IDX format + * + * @note ptp feature must set and read number of ptp unicast masters before. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] ptp_uc_master_info_idx Pointer to an array of ::PTP_UC_MASTER_INFO_IDX structures to be filled up + * @param[in] ptp_uc_master_cfg_limits Pointer to a ::PTP_UC_MASTER_CFG_LIMITS structure read before + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see //##+++++++++++++ TODO + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_ptp_uc_master_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, PTP_UC_MASTER_INFO_IDX *ptp_uc_master_info_idx, const PTP_UC_MASTER_CFG_LIMITS *ptp_uc_master_cfg_limits ) ; + + /** + * @brief Send configuration settings for PTP + * + * @note This is only supported by PTP devices + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ptp_cfg_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_ptp_cfg_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const PTP_CFG_SETTINGS *p ) ; + + /** + * @brief Read the ntp global information ::NTP_GLB_INFO format + * + * @note ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_clnt_mode_info + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_set_ntp_peer_settings_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_glb_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, NTP_GLB_INFO *p ) ; + + /** + * @brief Send the NTP global configuration + * + * @note This is only supported by NTP devices + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ant_cable_len + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_ntp_glb_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const NTP_GLB_SETTINGS *p ) ; + + /** + * @brief Read the ntp global information ::NTP_CLNT_MODE_INFO format + * + * @note ntp feature must set + * @note ntp client mode must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_glb_info + * @see ::mbgextio_set_ntp_clnt_mode_cfg + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_set_ntp_peer_settings_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_clnt_mode_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, NTP_CLNT_MODE_INFO *p ) ; + + /** + * @brief Send the NTP client mode configuration + * + * @note This is only supported by NTP devices + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_glb_info + * @see ::mbgextio_get_ntp_clnt_mode_info + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_set_ntp_peer_settings_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_ntp_clnt_mode_cfg( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const NTP_CLNT_MODE_SETTINGS *p ) ; + + /** + * @brief Read the ntp peer settings of current idx ::NTP_PEER_SETTINGS format + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the NTP peer settings to be configured, 0 ... NTP_CLNT_MODE_INFO::n_supp_peers - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_glb_info + * @see ::mbgextio_set_ntp_peer_settings_idx + * @see ::mbgextio_get_ntp_clnt_mode_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_peer_settings_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, NTP_PEER_SETTINGS_IDX *p, uint16_t idx ) ; + + /** + * @brief Send configuration settings for a specific NTP peer + * + * The number of supported NTP peers is specified in ::NTP_CLNT_MODE_INFO::n_supp_peers -1. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * @param[in] idx Index of the NTP peer to be configured, 0 ... NTP_CLNT_MODE_INFO::n_supp_peers - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_glb_info + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_get_ntp_clnt_mode_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_ntp_peer_settings_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const NTP_PEER_SETTINGS *p, uint16_t idx ) ; + + /** + * @brief Read the current system state of ntp device ::NTP_SYS_STATE format + * + * @note ntp feature must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_ntp_clnt_mode_cfg + * @see ::mbgextio_get_ntp_glb_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_sys_state( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, NTP_SYS_STATE *p ) ; + + /** + * @brief Read the NTP peer state of current idx ::NTP_PEER_STATE format + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the NTP peer state to be configured, 0 ... NTP_CLNT_MODE_INFO::n_supp_peers - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_ntp_sys_state + * @see ::mbgextio_get_ntp_peer_settings_idx + * @see ::mbgextio_get_ntp_clnt_mode_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_peer_state_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, NTP_PEER_STATE_IDX *p, uint16_t idx ) ; + + /** + * @brief Read the network global config information ::MBG_NET_GLB_CFG_INFO format + * + * @note GPS_HAS_NET_CFG must set + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_net_glb_cfg_settings + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_glb_cfg_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_NET_GLB_CFG_INFO *p ) ; + + /** + * @brief Set the device's global network configuration settings + * + * @note The function is not supported by all devices. //##++++++++++++ + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_net_glb_cfg_info + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_net_glb_cfg_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const MBG_NET_GLB_CFG_SETTINGS *p ) ; + + /** + * @brief Read the network dns server ::MBG_IP_ADDR_IDX format + * + * The number of DNS server provided by the device is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srvr + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srvr - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_net_dns_srvr_idx + * @see ::mbgextio_get_net_stat_dns_srvr_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_dns_srvr_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_IP_ADDR_IDX *p, uint16_t idx ) ; + + /** + * @brief Send the network DNS server address in ::MBG_IP_ADDR format + * + * The number of DNS search domains supported by the device + * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * @param[in] idx Index of the serial port to be configured, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srvr - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_net_dns_srvr_idx + * @see ::mbgextio_get_net_stat_dns_srvr_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_net_dns_srvr_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const MBG_IP_ADDR *p, uint16_t idx ) ; + + /** + * @brief Read the network DNS search domain in ::MBG_NET_NAME_IDX format + * + * The number of DNS search domains supported by the device + * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_net_dns_srch_dom_idx + * @see ::mbgextio_get_net_stat_dns_srch_dom_stat_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_dns_srch_dom_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_NET_NAME_IDX *p, uint16_t idx ) ; + + /** + * @brief Send the network DNS search domain in ::MBG_NET_NAME format + * + * The number of DNS search domains supported by the device + * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * @param[in] idx Index of the serial port to be configured, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_net_dns_srch_dom_idx + * @see ::mbgextio_get_net_stat_dns_srch_dom_stat_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_net_dns_srch_dom_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, const MBG_NET_NAME *p, uint16_t idx ) ; + + /** + * @brief Read the current network DNS server in ::MBG_IP_ADDR_IDX format + * + * The number of DNS servers supported by the device + * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srvr + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srvr - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_net_dns_srvr_idx + * @see ::mbgextio_set_net_dns_srvr_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_stat_dns_srvr_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_IP_ADDR_IDX *p, uint16_t idx ) ; + + /** + * @brief Read the current network DNS search domain in ::MBG_NET_NAME_IDX format + * + * The number of DNS search domains supported by the device + * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom - 1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_net_dns_srch_dom_idx + * @see ::mbgextio_get_net_dns_srch_dom_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_stat_dns_srch_dom_stat_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, MBG_NET_NAME_IDX *p, uint16_t idx ) ; + + /** + * @brief Read the ::XBP_LIMITS to check which XBP features are supported + * + * @note Only supported if ::GPS_HAS_XBP is set in ::RECEIVER_INFO::features + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_xbp_node_limits + * @see ::mbgextio_get_xbp_node_info_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_xbp_limits( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, XBP_LIMITS *p ) ; + + /** + * @brief Read the ::XBP_NODE_LIMITS to check how many ports are provided + * + * @note Only supported if ::XBP_FEAT_MASK_NODES is set in ::XBP_LIMITS::features. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_xbp_limits + * @see ::mbgextio_get_xbp_node_info_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_xbp_node_limits( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, XBP_NODE_LIMITS *p ) ; + + /** + * @brief Read the ::XBP_NODE_INFO for a specific node in ::XBP_NODE_INFO_IDX format + * + * The supported number of nodes is provided by ::XBP_NODE_LIMITS::node_count. + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * @param[in] idx Index of the array element to be retrieved, 0..::XBP_NODE_LIMITS::node_count-1 + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_xbp_limits + * @see ::mbgextio_get_xbp_node_limits + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_xbp_node_info_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, XBP_NODE_INFO_IDX *p, uint16_t idx ) ; + + /** + * @brief Read the ::XBP_NODE_INFO for a specific node in ::XBP_NODE_INFO_IDX format + * //##+++++++++++++++++++++++++ + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_setup_xbp_node_list( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr ) ; + + /** + * @brief Read a ::UTC parameter structure from a device. + * + * The ::UTC parameter structure contains the current UTC/GPS time offset + * as well as information on an eventually upcoming leap second. + * + * @note Only supported by GPS/GNSS and some PZF receivers //##+++++++ TODO Associated feature flag? + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to return the received data + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_set_utc_param + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_get_utc_param( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, UTC *p ) ; + + /** + * @brief Write a ::UTC parameter structure to a device. + * + * The ::UTC parameter structure contains the current UTC/GPS time offset + * as well as information on an eventually upcoming leap second. + * + * @note Only supported by GPS/GNSS and some PZF receivers //##+++++++ TODO Associated feature flag? + * + * @param[in,out] pmctl Pointer to a valid message control structure + * @param[in] p_addr Pointer to an XBP address specifier, or NULL + * @param[out] p Pointer to the data structure to be sent to the device + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_get_utc_param + */ + _NO_MBG_API_ATTR int _MBG_API mbgextio_set_utc_param( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, const UTC *p ) ; + /* ----- function prototypes end ----- */ diff --git a/mbglib/common/mbggeo.h b/mbglib/common/mbggeo.h index c375570..415064a 100644 --- a/mbglib/common/mbggeo.h +++ b/mbglib/common/mbggeo.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbggeo.h 1.10 2008/09/03 14:54:28 martin REL_M $ + * $Id: mbggeo.h 1.11 2011/06/22 10:18:10 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -22,6 +22,8 @@ * * ----------------------------------------------------------------------- * $Log: mbggeo.h $ + * Revision 1.11 2011/06/22 10:18:10 martin + * Cleaned up handling of pragma pack(). * Revision 1.10 2008/09/03 14:54:28 martin * Added macros to swap endianess of structures. * Revision 1.9 2008/01/17 09:31:33 daniel @@ -62,8 +64,9 @@ /* Start of header body */ -#if defined( _USE_PACK ) // set byte alignment - #pragma pack( 1 ) +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT #endif @@ -284,8 +287,9 @@ extern "C" { #endif -#if defined( _USE_PACK ) // set default alignment - #pragma pack() +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT #endif /* End of header body */ diff --git a/mbglib/common/mbgmutex.h b/mbglib/common/mbgmutex.h index e9f8a51..b8e1ae8 100644 --- a/mbglib/common/mbgmutex.h +++ b/mbglib/common/mbgmutex.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgmutex.h 1.1 2011/04/15 12:26:59 martin REL_M $ + * $Id: mbgmutex.h 1.3.1.2 2014/03/04 12:08:12 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,6 +11,16 @@ * * ----------------------------------------------------------------------- * $Log: mbgmutex.h $ + * Revision 1.3.1.2 2014/03/04 12:08:12 martin + * Revision 1.3.1.1 2014/01/08 17:20:57Z martin + * MBG_TGT_POSIX + * Revision 1.3 2013/04/11 13:46:58 martin + * Use non-specific spinlock function under Windows. + * Revision 1.2 2012/03/08 12:19:01Z martin + * Fixes for Linux kernel and FreeBSD. + * Fixed build under DOS and QNX usinc dummy defines. + * Don't define macros for semaphore destroy functions + * if not required/supported on the target OS. * Revision 1.1 2011/04/15 12:26:59 martin * Initial revision. * @@ -41,16 +51,16 @@ typedef KSPIN_LOCK MBG_SPINLOCK; #define _mbg_spin_lock_init( _spl ) KeInitializeSpinLock( _spl ) - #define _mbg_spin_lock_destroy( _spl ) _nop_macro_fnc() - #define _mbg_spin_lock_acquire( _spl ) KeAcquireSpinLockAtDpcLevel( _spl ) - #define _mbg_spin_lock_release( _spl ) KeReleaseSpinLockFromDpcLevel( _spl ) + // _mbg_spin_lock_destroy is not supported + #define _mbg_spin_lock_acquire( _spl ) KeAcquireSpinLock( _spl, &OldIrql ) + #define _mbg_spin_lock_release( _spl ) KeReleaseSpinLock( _spl, OldIrql ) - #define MBG_SPINLOCK_DEFINED 1 + #define _MBG_SPINLOCK_DEFINED 1 typedef FAST_MUTEX MBG_MUTEX; #define _mbg_mutex_init( _pmtx ) ExInitializeFastMutex( _pmtx ) - #define _mbg_mutex_destroy( _pmtx ) _nop_macro_fnc() + // _mbg_mutex_destroy( _pmtx ) is not supported #define _mbg_mutex_acquire( _pmtx ) ExAcquireFastMutex( _pmtx ) #define _mbg_mutex_release( _pmtx ) ExReleaseFastMutex( _pmtx ) @@ -59,20 +69,26 @@ #elif defined( MBG_TGT_LINUX ) // Linux kernel space #include - #include + #include + + #if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 26 ) ) + #include + #else + #include + #endif typedef spinlock_t MBG_SPINLOCK; #define _mbg_spin_lock_init( _spl ) spin_lock_init( _spl ) - #define _mbg_spin_lock_destroy( _spl ) _nop_macro_fnc() + // _mbg_spin_lock_destroy is not supported #define _mbg_spin_lock_acquire( _spl ) spin_lock( _spl ) #define _mbg_spin_lock_release( _spl ) spin_unlock( _spl ) - #define MBG_SPINLOCK_DEFINED 1 + #define _MBG_SPINLOCK_DEFINED 1 typedef struct semaphore MBG_MUTEX; #define _mbg_mutex_init( _pmtx ) sema_init( _pmtx, 1 ) - #define _mbg_mutex_destroy( _pmtx ) _nop_macro_fnc() + // _mbg_mutex_destroy( _pmtx ) is not supported #define _mbg_mutex_acquire( _pmtx ) down_interruptible( _pmtx ) #define _mbg_mutex_release( _pmtx ) up( _pmtx ) @@ -80,6 +96,7 @@ #elif defined( MBG_TGT_FREEBSD ) // FreeBSD kernel space + #include #include typedef struct mtx MBG_SPINLOCK; @@ -88,7 +105,7 @@ #define _mbg_spin_lock_acquire( _spl ) mtx_lock_spin( _spl ) #define _mbg_spin_lock_release( _spl ) mtx_unlock_spin( _spl ) - #define MBG_SPINLOCK_DEFINED 1 + #define _MBG_SPINLOCK_DEFINED 1 typedef struct mtx MBG_MUTEX; @@ -112,7 +129,7 @@ #define _mbg_spin_lock_acquire( _spl ) mutex_spin_enter( _spl ) #define _mbg_spin_lock_release( _spl ) mutex_spin_exit( _spl ) - #define MBG_SPINLOCK_DEFINED 1 + #define _MBG_SPINLOCK_DEFINED 1 typedef kmutex_t MBG_MUTEX; @@ -129,8 +146,6 @@ #if defined( MBG_TGT_WIN32 ) // Windows user space - #include - // definitions used with mutexes typedef HANDLE MBG_MUTEX; #define _mbg_mutex_init( _pm ) *(_pm) = CreateMutex( NULL, FALSE, NULL ) @@ -149,7 +164,7 @@ #define _MBG_CRIT_SECT_DEFINED 1 - #elif defined( MBG_TGT_UNIX ) // Unix user space use pthread library + #elif defined( MBG_TGT_POSIX ) // Unix user space use pthread library #include @@ -167,15 +182,21 @@ // For critical sections use defaults specified below + #elif defined( MBG_TGT_DOS ) || defined( MBG_TGT_QNX ) + + typedef int MBG_MUTEX; // just a dummy declaration + + #define _MBG_MUTEX_DEFINED 1 + #endif #endif -#if !defined( MBG_SPINLOCK_DEFINED ) +#if !defined( _MBG_SPINLOCK_DEFINED ) #define _mbg_spin_lock_init( _spl ) _nop_macro_fnc() - #define _mbg_spin_lock_destroy( _spl ) _nop_macro_fnc() + // _mbg_spin_lock_destroy is not supported #define _mbg_spin_lock_acquire( _spl ) _nop_macro_fnc() #define _mbg_spin_lock_release( _spl ) _nop_macro_fnc() @@ -189,7 +210,7 @@ typedef MBG_CRIT_SECT MBG_MUTEX; #define _mbg_mutex_init( _pm ) _nop_macro_fnc() - #define _mbg_mutex_destroy( _pm ) _nop_macro_fnc() + // _mbg_mutex_destroy( _pmtx ) is not supported #define _mbg_mutex_acquire( _pm ) _nop_macro_fnc() #define _mbg_mutex_release( _pm ) _nop_macro_fnc() @@ -203,10 +224,12 @@ #define _MBG_CRIT_SECT_DEFINED 1 typedef MBG_MUTEX MBG_CRIT_SECT; - #define _mbg_crit_sect_init _mbg_mutex_init - #define _mbg_crit_sect_destroy _mbg_mutex_destroy - #define _mbg_crit_sect_enter _mbg_mutex_acquire - #define _mbg_crit_sect_leave _mbg_mutex_release + #define _mbg_crit_sect_init _mbg_mutex_init + #if defined( _mbg_mutex_destroy ) + #define _mbg_crit_sect_destroy _mbg_mutex_destroy + #endif + #define _mbg_crit_sect_enter _mbg_mutex_acquire + #define _mbg_crit_sect_leave _mbg_mutex_release #endif diff --git a/mbglib/common/mbgserio.c b/mbglib/common/mbgserio.c index 23005b7..ccb8130 100644 --- a/mbglib/common/mbgserio.c +++ b/mbglib/common/mbgserio.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgserio.c 1.3 2009/09/01 10:49:30 martin REL_M $ + * $Id: mbgserio.c 1.6.1.17 2015/07/22 16:02:52 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,51 @@ * * ----------------------------------------------------------------------- * $Log: mbgserio.c $ + * Revision 1.6.1.17 2015/07/22 16:02:52 martin + * Cleanup. + * Removed trailing whitespace. + * Revision 1.6.1.16 2014/05/27 11:26:24 martin + * Revision 1.6.1.15 2014/05/09 11:40:41 marvin + * Fixed port_str_list if current port already opened. + * Revision 1.6.1.14 2014/03/27 11:48:47Z martin + * Revision 1.6.1.13 2014/03/18 10:37:52 martin + * Revision 1.6.1.12 2014/03/14 15:41:58Z martin + * Revision 1.6.1.11 2014/03/13 14:31:44Z martin + * Fixed compiler warnings related to select() call. + * Revision 1.6.1.10 2014/03/11 14:08:57Z martin + * Revision 1.6.1.9 2014/03/07 13:20:55Z martin + * Tmp. saved changes. + * Revision 1.6.1.8 2014/03/06 15:25:19 martin + * Revision 1.6.1.7 2014/03/04 12:08:12 martin + * Revision 1.6.1.6 2014/03/04 11:56:33Z martin + * Revision 1.6.1.5 2014/01/31 08:49:00Z marvin + * Replaced MBG_ERR_CONNECT_DEF by MBG_ERR_OPEN. + * Revision 1.6.1.4 2014/01/08 17:19:41Z martin + * MBG_TGT_POSIX + * New libusb + * Revision 1.6.1.3 2014/01/07 17:00:18 martin + * Use common Meinberg error codes. + * Revision 1.6.1.2 2013/12/16 10:11:34 marvin + * Changed mbgerror return code. + * Revision 1.6.1.1 2013/12/13 13:08:19Z marvin + * Changed error codes. Get error codes from mbgerror.h + * Revision 1.6 2013/04/18 13:50:58Z udo + * use O_CLOEXEC on open serial port if defined + * Revision 1.5 2013/02/01 16:06:33 martin + * Always use mbgserio_read/write rather than the macros. + * Got rid of _mbg_open/close/read/write() macros. + * Check return code of tcgetattr() when opening port under Linux. + * Set up DCB under Windows when opening the port, + * not when setting parameters. + * Fixed setting up COM port list under Windows. + * Flush output on close. + * Debug code to test flush under Windows (doesn't seem + * to work properly). + * New code trying different ways to detect existing ports + * reliably under Linux. + * Syntax workaround which is required until this module becomes a DLL. + * Revision 1.4 2011/07/29 10:12:15 martin + * Allow baud rates 115200 and 230400 under Linux, if supported by the OS version. * Revision 1.3 2009/09/01 10:49:30 martin * Cleanup for CVI. * Use new portable timeout functions from mbg_tmo.h. @@ -28,21 +73,23 @@ #define _MBGSERIO #include - - //##++ The following lines are required - // until mbgserio becomes a DLL: - #undef _MBG_API_ATTR - #define _MBG_API_ATTR - #undef _MBGSERIO #include #include #include +#include -#if defined( MBG_TGT_UNIX ) - #include +#if defined( MBG_TGT_POSIX ) #include + #include + #include +#endif + + + +#if defined( MBG_TGT_POSIX ) + static const char dev_dir[] = "/dev"; #endif @@ -68,8 +115,8 @@ int v24open( char *portname, int mode ); * port could not be opened. */ -#define O_DIRECT 0x0100 /* Schnittstelle fuer direkten Hardware-Zugriff oeffnen */ -#define O_HIGHPRIO 0x2000 /* Schnittstelle mit hoher Prioritaet oeffnen (fastopen) */ +#define O_DIRECT 0x0100 /* open port with direct access to the hardware */ +#define O_HIGHPRIO 0x2000 /* open port with high priority (fastopen) */ #define OPEN_MODE ( O_DIRECT | O_HIGHPRIO ) @@ -106,14 +153,156 @@ int v24close( int port ); +#if defined( MBG_TGT_WIN32 ) + +static /*HDR*/ +/** + * @brief + * + * @return One of the @ref MBG_RETURN_CODES + */ +int win32_create_file( const char *dev, HANDLE *ph ) +{ + static const char prefix[] = "\\\\.\\"; + + size_t len = strlen( prefix ) + strlen( dev ) + 1; + char *tmp_name; + int rc = MBG_ERR_UNSPEC; + + tmp_name = (char *) malloc( len ); + + if ( tmp_name == NULL ) // unable to allocate memory + { + rc = MBG_ERR_NO_MEM; + goto out; + } + + strcpy( tmp_name, prefix ); + strcat( tmp_name, dev ); + + *ph = CreateFile( tmp_name, GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, //##++++++++++++++ | FILE_FLAG_WRITE_THROUGH, + NULL ); + + if ( *ph == INVALID_HANDLE_VALUE ) + { + rc = mbg_win32_last_err_to_mbg( GetLastError(), "CreateFile failed in win32_create_file" ); + goto out_free; + } + + rc = MBG_SUCCESS; + +out_free: + free( tmp_name ); + +out: + return rc; + +} // win32_create_file + +#endif // defined( MBG_TGT_WIN32 ) + + + +static /*HDR*/ +/** + * @brief + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgserio_close_port_by_handle( MBG_PORT_HANDLE *p ) +{ + if ( *p != MBG_INVALID_PORT_HANDLE ) + { + #if defined( MBG_TGT_CVI ) + + CloseCom( *p ); + + #elif defined( MBG_TGT_WIN32 ) + + CloseHandle( *p ); + + #elif defined( MBG_TGT_POSIX ) + + close( *p ); + + #elif defined( MBG_TGT_DOS ) + #if defined( _USE_V24TOOLS ) + + v24close( *p ); + + #else + + #error Target DOS requires v24tools for serial I/O. + + #endif + + #else + + #error This target OS is not supported. + + #endif + + *p = MBG_INVALID_PORT_HANDLE; + } + + return MBG_SUCCESS; + +} // mbgserio_close_port_by_handle + + + /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev ) +/** + * @brief + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgserio_close( SERIAL_IO_STATUS *pst ) { - MBG_PORT_HANDLE port_handle; + if ( pst->port_handle != MBG_INVALID_PORT_HANDLE ) + { + MBG_PORT_HANDLE port_handle = pst->port_handle; + + mbgserio_flush_tx( port_handle ); + + #if defined( MBG_TGT_WIN32 ) + + SetCommState( port_handle, &pst->old_dcb ); + SetCommTimeouts( port_handle, &pst->old_commtimeouts ); + + #elif defined( MBG_TGT_POSIX ) + + tcsetattr( port_handle, TCSANOW, &pst->old_tio ); + + #endif + + return mbgserio_close_port_by_handle( &pst->port_handle ); + } + + return MBG_SUCCESS; + +} // mbgserio_close + + + +/*HDR*/ +/** + * @brief + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev ) +{ + MBG_PORT_HANDLE port_handle = MBG_INVALID_PORT_HANDLE; + int rc = MBG_ERR_UNSPEC; #if defined( MBG_TGT_CVI ) { - int data_bits = 8; //##++ + int data_bits = 8; //##+++++++++++++++ int parity_code = 0; int baud_rate = 19200; int stop_bits = 1; @@ -124,102 +313,173 @@ _MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev // Under CVI the port handle passed to OpenComConfig and used furtheron // corresponds to the COM port number, e.g. 1 for COM1, so we extract // the number from the device name passed as parameter. - port_handle = 0; len = strlen( dev ); for ( i = 0; i < len; i++ ) { char c = dev[i]; + if ( c >= '0' && c <= '9' ) break; } if ( i == len ) - return MBGSERIO_INV_CFG; // no numeric substring found - + { + rc = MBG_ERR_INV_PARM; // no numeric substring found + goto out; + } port_handle = atoi( &dev[i] ); - rc = OpenComConfig (port_handle, NULL, baud_rate, parity_code, data_bits, stop_bits, 8192, 1024); //##++ + rc = OpenComConfig( port_handle, NULL, baud_rate, parity_code, data_bits, stop_bits, 8192, 1024 ); //##++ + if ( rc < 0 ) - goto fail; + { + port_handle = MBG_INVALID_PORT_HANDLE; + rc = MBG_ERR_UNSPEC; // translate rc ? + goto out; + } - pst->port_handle = port_handle; + rc = SetComTime( port_handle, 1.0 ); //##+++++++ WTF? - SetComTime( port_handle, 1.0 ); //##++ - SetXMode( port_handle, 0 ); + if ( rc < 0 ) + { + rc = MBG_ERR_UNSPEC; //##+++++ translate rc ? + goto out_close; + } + + rc = SetXMode( port_handle, 0 ); + + if ( rc < 0 ) + { + rc = MBG_ERR_UNSPEC; //##+++++ translate rc ? + goto out_close; + } } #elif defined( MBG_TGT_WIN32 ) { - static const char *prefix = "\\\\.\\"; - COMMTIMEOUTS commtimeouts; - int len = strlen( prefix ) + strlen( dev ) + 1; - char *tmp_name = (char *) malloc( len ); - - if ( tmp_name == NULL ) // unable to allocate memory - goto fail; - - - strcpy( tmp_name, prefix ); - strcat( tmp_name, dev ); - - port_handle = CreateFile( tmp_name, GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, - NULL ); - - free( tmp_name ); - - if ( port_handle == INVALID_HANDLE_VALUE ) - goto fail; + DCB dcb; + rc = win32_create_file( dev, &port_handle ); - pst->port_handle = port_handle; + if ( rc != MBG_SUCCESS ) + goto out; - // save original settings + // save settings found at startup pst->old_dcb.DCBlength = sizeof( pst->old_dcb ); GetCommState( port_handle, &pst->old_dcb ); GetCommTimeouts( port_handle, &pst->old_commtimeouts ); + GetCommProperties( port_handle, &pst->comm_prop ); + + #if 0 // fields provided by the Windows DCB structure + DWORD DCBlength; /* sizeof(DCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ + #endif // configure our settings + dcb = pst->old_dcb; // current settings as default + dcb.fOutxCtsFlow = FALSE; // CTS output flow control + dcb.fOutxDsrFlow = FALSE; // DSR output flow control + dcb.fDtrControl = DTR_CONTROL_ENABLE; // enable DTR + dcb.fDsrSensitivity = FALSE; // don't require DSR input active + //##++ TODO: more missing here + dcb.fRtsControl = RTS_CONTROL_ENABLE; // enable RTS for C28COM + dcb.fOutX = FALSE; + + if ( !SetCommState( port_handle, &dcb ) ) + { + rc = mbg_get_last_error( "SetCommState failed in mbgserio_open" ); + goto out_close; + } + memset( &commtimeouts, 0, sizeof( commtimeouts ) ); - SetCommTimeouts( port_handle, &commtimeouts ); - #if defined( MBGSERIO_IN_BUFFER_SIZE ) && defined( MBGSERIO_OUT_BUFFER_SIZE ) - SetupComm( port_handle, MBGSERIO_IN_BUFFER_SIZE, MBGSERIO_OUT_BUFFER_SIZE ); + if ( !SetCommTimeouts( port_handle, &commtimeouts ) ) + { + rc = mbg_get_last_error( "SetCommTimeout failed in mbgserio_open" ); + goto out_close; + } + + #if !defined( MBGSERIO_IN_BUFFER_SIZE ) + #define MBGSERIO_IN_BUFFER_SIZE 2048 + #endif + + #if !defined( MBGSERIO_OUT_BUFFER_SIZE ) + #define MBGSERIO_OUT_BUFFER_SIZE 2048 #endif - PurgeComm( port_handle, PURGE_TXABORT|PURGE_TXCLEAR ); - PurgeComm( port_handle, PURGE_RXABORT|PURGE_RXCLEAR ); + if ( !SetupComm( port_handle, MBGSERIO_IN_BUFFER_SIZE, MBGSERIO_OUT_BUFFER_SIZE ) ) + { + rc = mbg_get_last_error( "SetupComm failed in mbgserio_open" ); + goto out_close; + } - //##++ mbgextio_set_console_control_handler(); + PurgeComm( port_handle, PURGE_TXABORT | PURGE_TXCLEAR ); + PurgeComm( port_handle, PURGE_RXABORT | PURGE_RXCLEAR ); + + //##++ TODO: mbgextio_set_console_control_handler() ? } - #elif defined( MBG_TGT_UNIX ) + #elif defined( MBG_TGT_POSIX ) { // Open as not controlling TTY to prevent from being // killed if CTRL-C is received. // O_NONBLOCK is the same as O_NDELAY. - port_handle = _mbg_open( dev, O_RDWR | O_NOCTTY | O_NONBLOCK ); + int flags = O_RDWR | O_NOCTTY | O_NONBLOCK; - //##++ TODO: Under Unix a serial port can by default be opened - // by several processes. However, we don't want that, so we - // should care about this using a lock file for the device - // and/or setting the TIOCEXCL flag (which unfortunately - // is not an atomic operation with open()). + #if defined( O_CLOEXEC ) + flags |= O_CLOEXEC; + #endif - if ( port_handle < 0 ) // check errno for the reason - goto fail; + port_handle = open( dev, flags ); // returns -1 on error + if ( port_handle < 0 ) + { + rc = mbg_get_last_error( "open failed in mbgserio_open" ); + port_handle = MBG_INVALID_PORT_HANDLE; + goto out; + } - pst->port_handle = port_handle; + //##++ TODO: Under Unix a serial port can by default be opened + // by several processes. However, we don't want that, so we + // should care about this using a lock file for the device + // and/or setting the TIOCEXCL flag (which unfortunately + // is not an atomic operation with open()). /* save current device settings */ - tcgetattr( port_handle, &pst->oldtio ); + if ( tcgetattr( port_handle, &pst->old_tio ) < 0 ) + { + rc = mbg_get_last_error( "tcgetattr failed in mbgserio_open" ); + goto out_close; + } - // atexit( port_deinit ); + //##++ atexit( port_deinit ); fflush( stdout ); //##++ setvbuf( stdout, NULL, _IONBF, 0 ); @@ -230,9 +490,11 @@ _MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev port_handle = v24open( (char *) dev, OPEN_MODE ); if ( port_handle < 0 ) - goto fail; + { + rc = MBG_ERR_UNSPEC; // translate rc ? + goto out; + } - pst->port_handle = port_handle; v24settimeout( port_handle, 1 ); } #else @@ -247,67 +509,81 @@ _MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev #endif - return 0; + rc = MBG_SUCCESS; + goto out; +out_close: + mbgserio_close_port_by_handle( &port_handle ); // also sets port handle invalid -fail: - pst->port_handle = MBG_INVALID_PORT_HANDLE; - return MBGSERIO_FAIL; +out: + pst->port_handle = port_handle; + return rc; } // mbgserio_open -/*HDR*/ -_MBG_API_ATTR int _MBG_API mbgserio_close( SERIAL_IO_STATUS *pst ) +#if 0 && defined( MBG_TGT_POSIX ) + +static /*HDR*/ +int scandir_filter_serial_port( const struct dirent *pde ) { - if ( pst->port_handle != MBG_INVALID_PORT_HANDLE ) - { - MBG_PORT_HANDLE port_handle = pst->port_handle; + static const char dev_name_1[] = "ttyS"; + static const char dev_name_2[] = "ttyUSB"; + char tmp_str[100]; + SERIAL_IO_STATUS iost; + int rc; - #if defined( MBG_TGT_CVI ) + int l; - CloseCom( port_handle ); + l = strlen( dev_name_1 ); - #elif defined( MBG_TGT_WIN32 ) + if ( strncmp( pde->d_name, dev_name_1, l ) == 0 ) + goto check; - SetCommState( port_handle, &pst->old_dcb ); - SetCommTimeouts( port_handle, &pst->old_commtimeouts ); - CloseHandle( port_handle ); - #elif defined( MBG_TGT_UNIX ) + l = strlen( dev_name_2 ); - tcsetattr( port_handle, TCSANOW, &pst->oldtio ); - close( port_handle ); + if ( strncmp( pde->d_name, dev_name_2, l ) == 0 ) + goto check; - #elif defined( MBG_TGT_DOS ) - #if defined( _USE_V24TOOLS ) + return 0; - v24close( port_handle ); +check: + // if the first character after the search string is not a digit + // then the search result is not what we want + if ( pde->d_name[l] < '0' || pde->d_name[l] > '9' ) + return 0; - #else + snprintf( tmp_str, sizeof( tmp_str ), "%s/%s", dev_dir, pde->d_name ); - #error Target DOS requires v24tools for serial I/O. + rc = mbgserio_open( &iost, tmp_str ); - #endif + if ( rc < 0 ) + { + #if defined( DEBUG ) + fprintf( stderr, "failed to open %s: %i\n", tmp_str, rc ); + #endif - #else + return 0; + } - #error This target OS is not supported. + #if defined( DEBUG ) + fprintf( stderr, "port %s opened successfully\n", tmp_str ); + #endif - #endif + mbgserio_close( &iost ); - pst->port_handle = MBG_INVALID_PORT_HANDLE; - } + return 1; - return 0; +} // scandir_filter_serial_port -} // mbgserio_close +#endif // defined( MBG_TGT_POSIX ) /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, int max_devs ) +_NO_MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, int max_devs ) { MBG_STR_LIST *list_head; int n = 0; @@ -318,24 +594,94 @@ _MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, in list_head = (*list); + +#if 0 && defined( MBG_TGT_POSIX ) + + struct dirent **namelist; + + n = scandir( dev_dir, &namelist, scandir_filter_serial_port, versionsort ); + + if ( n < 0 ) + perror( "scandir" ); + else + { + for ( i = 0; i < n; i++ ) + { + printf( "%s/%s\n", dev_dir, namelist[i]->d_name ); + free( namelist[i] ); + } + + free( namelist ); + } + +#elif 0 && defined( MBG_TGT_POSIX ) + + DIR *pd = opendir( dev_dir ); + + if ( pd ) + { + struct dirent *pde; + + while ( ( pde = readdir( pd ) ) != NULL ) + { + if ( strncmp( pde->d_name, "ttyS", 4 ) == 0 ) + goto found; + + if ( strncmp( pde->d_name, "ttyUSB", 6 ) == 0 ) + goto found; + + continue; + +found: + fprintf( stderr, "found /dev/%s\n", pde->d_name ); + } + + closedir( pd ); + } + +#else + for ( i = 0; i < max_devs; i++ ) { - SERIAL_IO_STATUS iost; char dev_name[100] = { 0 }; int rc; #if defined( MBG_TGT_WIN32 ) + + HANDLE h = INVALID_HANDLE_VALUE; + sprintf( dev_name, "COM%i", i + 1 ); + rc = win32_create_file( dev_name, &h ); + + // If access is denied then the port exists but is in use + if ( rc != MBG_SUCCESS && rc != MBG_ERR_ACCESS ) + continue; // memory allocation error + + if ( h != INVALID_HANDLE_VALUE ) + CloseHandle( h ); + #elif defined( MBG_TGT_LINUX ) + + SERIAL_IO_STATUS iost; sprintf( dev_name, "/dev/ttyS%i", i ); - #endif + rc = mbgserio_open( &iost, dev_name ); - rc = mbgserio_open( &iost, dev_name ); + if ( rc < 0 ) + { + sprintf( dev_name, "/dev/ttyUSB%i", i ); + + rc = mbgserio_open( &iost, dev_name ); + + if ( rc < 0 ) + continue; + } + + mbgserio_close( &iost ); + + #endif - if ( rc < 0 ) - continue; - mbgserio_close( &iost ); + // add the device name to the list (*list)->s = (char *) malloc( strlen( dev_name ) + 1 ); strcpy( (*list)->s, dev_name ); @@ -355,6 +701,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, in free( *list ); list_head = NULL; } +#endif *list = list_head; @@ -365,7 +712,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, in /*HDR*/ -_MBG_API_ATTR void _MBG_API _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list ) +_NO_MBG_API_ATTR void _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list ) { int i = 0; @@ -406,18 +753,23 @@ _MBG_API_ATTR void _MBG_API _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, +/** + * @brief + * + * @return One of the @ref MBG_RETURN_CODES + */ +_NO_MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, uint32_t baud_rate, const char *framing ) { MBG_PORT_HANDLE port_handle = pst->port_handle; const char *cp; + int rc = MBG_ERR_UNSPEC; #if defined( MBG_TGT_CVI ) { int data_bits = 8; - int parity_code = 0; + int parity_code = 0; int stop_bits = 1; - int rc; // setup framing. for ( cp = framing; *cp; cp++ ) @@ -449,24 +801,31 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, break; default: - return MBGSERIO_INV_CFG; // invalid framing string + rc = MBG_ERR_INV_PARM; // invalid framing string + goto out; } } - rc = OpenComConfig( port_handle, NULL, baud_rate, parity_code, - data_bits, stop_bits, 8192, 1024 ); + rc = OpenComConfig( port_handle, NULL, baud_rate, parity_code, + data_bits, stop_bits, 8192, 1024 ); if ( rc < 0 ) - return rc; + { + rc = MBG_ERR_INV_PARM; + goto out; + } - SetComTime( port_handle, 1.0 ); //##++ + SetComTime( port_handle, 1.0 ); //##++++++++ check rc ? SetXMode( port_handle, 0 ); } #elif defined( MBG_TGT_WIN32 ) { DCB dcb; - dcb.DCBlength = sizeof( DCB ) ; - GetCommState( port_handle, &dcb ) ; + // get current settings + dcb.DCBlength = sizeof( DCB ); + GetCommState( port_handle, &dcb ); //##++++++++++++++++ check rc? + + // update changed settings dcb.BaudRate = baud_rate; @@ -503,27 +862,19 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, break; default: - return MBGSERIO_INV_CFG; // invalid framing string + rc = MBG_ERR_INV_PARM; // invalid framing string + goto out; } } - - dcb.fOutxCtsFlow = FALSE; // CTS output flow control - dcb.fOutxDsrFlow = FALSE; // DSR output flow control - dcb.fDtrControl = DTR_CONTROL_ENABLE; // enable DTR for C28COM - dcb.fDsrSensitivity = FALSE; // don't require DSR input active - //##++ more missing here - dcb.fRtsControl = RTS_CONTROL_ENABLE; // enable RTS for C28COM - dcb.fOutX = FALSE; - - SetCommState ( port_handle, &dcb ); + SetCommState( port_handle, &dcb ); //##++++++++ check rc } - #elif defined( MBG_TGT_UNIX ) + #elif defined( MBG_TGT_POSIX ) { tcflag_t c_cflag = 0; struct termios tio; - tcgetattr( port_handle, &tio ); + rc = tcgetattr( port_handle, &tio ); //##+++++++++++++++++ check rc // setup transmission speed switch( baud_rate ) @@ -537,8 +888,16 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, case 19200: c_cflag = B19200; break; case 38400: c_cflag = B38400; break; case 57600: c_cflag = B57600; break; + #if defined( B115200 ) + case 115200: c_cflag = B115200; break; + #endif + #if defined( B230400 ) + case 230400: c_cflag = B230400; break; + #endif - default: return MBGSERIO_INV_CFG; // invalid + default: + rc = MBG_ERR_INV_PARM; // invalid + goto out; } #if 0 //##++ This should be used preferably for portability reasons @@ -549,7 +908,9 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, // setup framing. for ( cp = framing; *cp; cp++ ) { - switch ( _toupper( *cp ) ) + char c = toupper( *cp ); + + switch ( c ) { case '7': c_cflag |= CS7; break; case '8': c_cflag |= CS8; break; @@ -561,7 +922,9 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, case '1': break; case '2': c_cflag |= CSTOPB; break; - default: return MBGSERIO_INV_CFG; // invalid framing string + default: + rc = MBG_ERR_INV_PARM; // invalid + goto out; } } @@ -572,7 +935,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, // (POSIX says that the baud speed is stored in the termios structure // without specifying where precisely, and provides cfgetispeed() and // cfsetispeed() for getting at it. Some systems use bits selected - // by CBAUD in c_cflag, other systems use separate fields, + // by CBAUD in c_cflag, other systems use separate fields, // e.g. sg_ispeed and sg_ospeed.) // CSIZE Character size mask. Values are CS5, CS6, CS7, or CS8. // CSTOPB Set two stop bits, rather than one. @@ -595,17 +958,17 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, // Setup input flags. The following flags are defined: // IGNBRK Ignore BREAK condition on input - // BRKINT If IGNBRK is set, a BREAK is ignored. If it is not set - // but BRKINT is set, then a BREAK causes the input and output + // BRKINT If IGNBRK is set, a BREAK is ignored. If it is not set + // but BRKINT is set, then a BREAK causes the input and output // queues to be flushed, and if the terminal is the controlling - // terminal of a foreground process group, it will cause a + // terminal of a foreground process group, it will cause a // SIGINT to be sent to this foreground process group. When // neither IGNBRK nor BRKINT are set, a BREAK reads as a NUL // character, except when PARMRK is set, in which case it reads // as the sequence \377 \0 \0. // IGNPAR Ignore framing errors and parity errors. - // PARMRK If IGNPAR is not set, prefix a character with a parity error - // framing error with \377 \0. If neither IGNPAR nor PARMRK or + // PARMRK If IGNPAR is not set, prefix a character with a parity error + // framing error with \377 \0. If neither IGNPAR nor PARMRK or // is set, read a character with a parity error or framing error as \0. // INPCK Enable input parity checking. // ISTRIP Strip off eighth bit. @@ -636,14 +999,14 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, // ONOCR Don't output CR at column 0. // ONLRET Don't output CR. // OFILL Send fill characters for a delay, rather than using a timed delay. - // OFDEL (not in POSIX) Fill character is ASCII DEL (0177). If unset, + // OFDEL (not in POSIX) Fill character is ASCII DEL (0177). If unset, // fill character is ASCII NUL. // NLDLY Newline delay mask. Values are NL0 and NL1. // CRDLY Carriage return delay mask. Values are CR0, CR1, CR2, or CR3. - // TABDLY Horizontal tab delay mask. Values are TAB0, TAB1, TAB2, TAB3 - // (or XTABS). A value of TAB3, that is, XTABS, expands tabs to + // TABDLY Horizontal tab delay mask. Values are TAB0, TAB1, TAB2, TAB3 + // (or XTABS). A value of TAB3, that is, XTABS, expands tabs to // spaces (with tab stops every eight columns). - // BSDLY Backspace delay mask. Values are BS0 or BS1. + // BSDLY Backspace delay mask. Values are BS0 or BS1. // (Has never been implemented.) // VTDLY Vertical tab delay mask. Values are VT0 or VT1. // FFDLY Form feed delay mask. Values are FF0 or FF1. @@ -657,53 +1020,53 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, // EOF, EOL, EOL2, ERASE, KILL, LNEXT, REPRINT, STATUS, and // WERASE, and buffers by lines. // XCASE (not in POSIX; not supported under Linux) If ICANON is also - // set, terminal is uppercase only. Input is converted to - // lowercase, except for characters preceded by \. On output, - // uppercase characters are preceded by \ and lowercase + // set, terminal is uppercase only. Input is converted to + // lowercase, except for characters preceded by \. On output, + // uppercase characters are preceded by \ and lowercase // characters are converted to uppercase. // ECHO Echo input characters. - // ECHOE If ICANON is also set, the ERASE character erases the preceding + // ECHOE If ICANON is also set, the ERASE character erases the preceding // input character, and WERASE erases the preceding word. // ECHOK If ICANON is also set, the KILL character erases the current line. // ECHONL If ICANON is also set, echo the NL character even if ECHO is not set. // ECHOCTL (not in POSIX) If ECHO is also set, ASCII control signals // other than TAB, NL, START, and STOP are echoed as ^X, where - // X is the character with ASCII code 0x40 greater than the control + // X is the character with ASCII code 0x40 greater than the control // signal. For example, character 0x08 (BS) is echoed as ^H. - // ECHOPRT (not in POSIX) If ICANON and IECHO are also set, characters are + // ECHOPRT (not in POSIX) If ICANON and IECHO are also set, characters are // printed as they are being erased. - // ECHOKE (not in POSIX) If ICANON is also set, KILL is echoed by erasing + // ECHOKE (not in POSIX) If ICANON is also set, KILL is echoed by erasing // each character on the line, as specified by ECHOE and ECHOPRT. // DEFECHO (not in POSIX) Echo only when a process is reading. // FLUSHO (not in POSIX; not supported under Linux) Output is being flushed. // This flag is toggled by typing the DISCARD character. // NOFLSH Disable flushing the input and output queues when generating the // SIGINT, SIGQUIT and SIGSUSP signals. - // TOSTOP Send the SIGTTOU signal to the process group of a background + // TOSTOP Send the SIGTTOU signal to the process group of a background // process which tries to write to its controlling terminal. // PENDIN (not in POSIX; not supported under Linux) All characters in the - // input queue are reprinted when the next character is read. + // input queue are reprinted when the next character is read. // (bash handles typeahead this way.) // IEXTEN Enable implementation-defined input processing. This flag, as - // well as ICANON must be enabled for the special characters EOL2, + // well as ICANON must be enabled for the special characters EOL2, // LNEXT, REPRINT, WERASE to be interpreted, and for the IUCLC flag // to be effective. tio.c_lflag = 0; // VINTR (003, ETX, Ctrl-C, or also 0177, DEL, rubout) Interrupt character. - // Send a SIGINT signal. Recognized when ISIG is set, and then not + // Send a SIGINT signal. Recognized when ISIG is set, and then not // passed as input. // VQUIT (034, FS, Ctrl-\) Quit character. Send SIGQUIT signal. Recognized // when ISIG is set, and then not passed as input. // VERASE (0177, DEL, rubout, or 010, BS, Ctrl-H, or also #) Erase character. // This erases the previous not-yet-erased character, but does not erase - // past EOF or beginning-of-line. Recognized when ICANON is set, + // past EOF or beginning-of-line. Recognized when ICANON is set, // and then not passed as input. // VKILL (025, NAK, Ctrl-U, or Ctrl-X, or also @) Kill character. This erases // the input since the last EOF or beginning-of-line. Recognized when // ICANON is set, and then not passed as input. - // VEOF (004, EOT, Ctrl-D) End-of-file character. More precisely: this + // VEOF (004, EOT, Ctrl-D) End-of-file character. More precisely: this // character causes the pending tty buffer to be sent to the waiting // user program without waiting for end-of-line. If it is the first // character of the line, the read() in the user program returns 0, @@ -722,9 +1085,9 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, // typed. Recognized when IXON is set, and then not passed as input. // VSUSP (032, SUB, Ctrl-Z) Suspend character. Send SIGTSTP signal. Recognized // when ISIG is set, and then not passed as input. - // VDSUSP (not in POSIX; not supported under Linux; 031, EM, Ctrl-Y) Delayed + // VDSUSP (not in POSIX; not supported under Linux; 031, EM, Ctrl-Y) Delayed // suspend character: send SIGTSTP signal when the character is read by - // the user program. Recognized when IEXTEN and ISIG are set, and the + // the user program. Recognized when IEXTEN and ISIG are set, and the // system supports job control, and then not passed as input. // VLNEXT (not in POSIX; 026, SYN, Ctrl-V) Literal next. Quotes the next input // character, depriving it of a possible special meaning. Recognized @@ -733,18 +1096,18 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, // and IEXTEN are set, and then not passed as input. // VREPRINT (not in POSIX; 022, DC2, Ctrl-R) Reprint unread characters. Recognized // when ICANON and IEXTEN are set, and then not passed as input. - // VDISCARD (not in POSIX; not supported under Linux; 017, SI, Ctrl-O) Toggle: + // VDISCARD (not in POSIX; not supported under Linux; 017, SI, Ctrl-O) Toggle: // start/stop discarding pending output. Recognized when IEXTEN is set, // and then not passed as input. // VSTATUS (not in POSIX; not supported under Linux; status request: 024, DC4, Ctrl-T). // Setting up c_cc[VMIN] and c_cc[VTIME]: - // If MIN > 0 and TIME = 0, MIN sets the number of characters to receive before + // If MIN > 0 and TIME = 0, MIN sets the number of characters to receive before // the read is satisfied. As TIME is zero, the timer is not used. // If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will be - // satisfied if a single character is read, or TIME is exceeded - // (t = TIME *0.1 s). If TIME is exceeded, no character will be + // satisfied if a single character is read, or TIME is exceeded + // (t = TIME *0.1 s). If TIME is exceeded, no character will be // returned. // If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The // read will be satisfied if MIN characters are received, or the @@ -752,8 +1115,8 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, // every time a character is received and only becomes active after // the first character has been received. // If MIN = 0 and TIME = 0, read will be satisfied immediately. The number of - // characters currently available, or the number of characters - // requested will be returned. You could issue a + // characters currently available, or the number of characters + // requested will be returned. You could issue a // fcntl(fd, F_SETFL, FNDELAY); before reading to get the same result. // setup control characters for non-blocking read @@ -761,8 +1124,8 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, tio.c_cc[VTIME] = 0; // now clean the modem line and activate the settings for modem - tcflush( port_handle, TCIFLUSH ); - tcsetattr( port_handle, TCSANOW, &tio ); + rc = tcflush( port_handle, TCIFLUSH ); + rc = tcsetattr( port_handle, TCSANOW, &tio ); //##+++++++++ check rc ? fflush( stdout ); setvbuf( stdout, NULL, _IONBF, 0 ); @@ -789,7 +1152,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, case 'N': case 'E': case 'O': - parity = *cp; + parity = c; break; case '1': @@ -798,11 +1161,12 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, break; default: - return MBGSERIO_INV_CFG; // invalid framing string + rc = MBG_ERR_INV_PARM; // invalid framing string + goto out; } } - v24setparams( port_handle, baud_rate, datab, parity, stopb ); + v24setparams( port_handle, baud_rate, datab, parity, stopb ); //##++++++++++++++ check rc? } #else @@ -816,87 +1180,199 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, #endif - return 0; + rc = MBG_SUCCESS; -} // mbgserio_set_parms +out: + return rc; +} // mbgserio_set_parms -#if defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_CVI ) /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgserio_read( MBG_PORT_HANDLE h, void *buffer, unsigned int count ) +_NO_MBG_API_ATTR int _MBG_API mbgserio_read( MBG_PORT_HANDLE h, void *buffer, unsigned int count ) { - BOOL fReadStat; - COMSTAT ComStat; - DWORD dwErrorFlags; - DWORD dwLength; + #if defined( MBG_TGT_CVI ) - ClearCommError( h, &dwErrorFlags, &ComStat ); + return ComRd( h, (char *) buffer, count ); - if ( dwErrorFlags ) // transmission error (parity, framing, etc.) - return MBGSERIO_FAIL; + #elif defined( MBG_TGT_WIN32 ) + BOOL fReadStat; + COMSTAT ComStat; + DWORD dwErrorFlags; + DWORD dwLength; - dwLength = min( (DWORD) count, ComStat.cbInQue ); + ClearCommError( h, &dwErrorFlags, &ComStat ); - if ( dwLength ) - { - fReadStat = ReadFile( h, buffer, dwLength, &dwLength, NULL ); + if ( dwErrorFlags ) // transmission error (parity, framing, etc.) + return MBG_ERR_IO; //##+++++++++++++++++++++++++ - if ( !fReadStat ) - return MBGSERIO_FAIL; - } - return dwLength; + dwLength = min( (DWORD) count, ComStat.cbInQue ); -} // mbgserio_read + if ( dwLength ) + { + fReadStat = ReadFile( h, buffer, dwLength, &dwLength, NULL ); + + if ( !fReadStat ) + return MBG_ERR_IO; //##++++++++++++++ + } + + return dwLength; + #elif defined( MBG_TGT_POSIX ) + + return read( h, buffer, count ); + + #elif defined( MBG_TGT_DOS ) && defined( _USE_V24TOOLS ) + + return v24read( h, buffer, count ); + + #else + + #error mbgserio_read() not implemented for this target + + #endif + +} // mbgserio_read +/* //##+++++++++++++++++ need to check all targets + * @return one of the MBG_ERROR_CODES on error, else number of bytes written + */ /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgserio_write( MBG_PORT_HANDLE h, const void *buffer, unsigned int count ) +_NO_MBG_API_ATTR int _MBG_API mbgserio_write( MBG_PORT_HANDLE h, const void *buffer, unsigned int count ) { - BOOL fWriteStat; - COMSTAT ComStat; - DWORD dwErrorFlags; - DWORD dwThisBytesWritten; - DWORD dwTotalBytesWritten = 0; + #if defined( MBG_TGT_CVI ) - while ( dwTotalBytesWritten < (DWORD) count ) - { - dwThisBytesWritten = 0; + return ComWrt( h, (char *) buffer, count ); + + #elif defined( MBG_TGT_WIN32 ) - fWriteStat = WriteFile( h, ( (char *) buffer ) + dwTotalBytesWritten, - count - dwTotalBytesWritten, - &dwThisBytesWritten, NULL ); - if ( !fWriteStat ) + BOOL fWriteStat; + COMSTAT ComStat; + DWORD dwErrorFlags; + DWORD dwThisBytesWritten; + DWORD dwTotalBytesWritten = 0; + + while ( dwTotalBytesWritten < (DWORD) count ) { - #if defined( _DEBUG ) - DWORD dw = GetLastError(); - #endif - break; //##++ Error: Unable to write + dwThisBytesWritten = 0; + + fWriteStat = WriteFile( h, ( (char *) buffer ) + dwTotalBytesWritten, + count - dwTotalBytesWritten, + &dwThisBytesWritten, NULL ); + if ( !fWriteStat ) + return mbg_get_last_error( "write failed in mbgserio_write" ); + + dwTotalBytesWritten += dwThisBytesWritten; + + ClearCommError( h, &dwErrorFlags, &ComStat ); + + if ( dwErrorFlags ) + { + // Possible errors: + // + // CE_RXOVER 0x0001 // Receive Queue overflow + // CE_OVERRUN 0x0002 // Receive Overrun Error, next character(s) lost + // CE_RXPARITY 0x0004 // Receive Parity Error + // CE_FRAME 0x0008 // Receive Framing error + // CE_BREAK 0x0010 // Break Detected + // CE_TXFULL 0x0100 // TX Queue is full + // CE_PTO 0x0200 // LPTx Timeout + // CE_IOE 0x0400 // LPTx I/O Error + // CE_DNS 0x0800 // LPTx Device not selected + // CE_OOP 0x1000 // LPTx Out-Of-Paper + // CE_MODE 0x8000 // Requested mode unsupported + // + // Except CE_TXFULL these are usually RX error flags, + // so we just ignore them. + } } - dwTotalBytesWritten += dwThisBytesWritten; + return dwTotalBytesWritten; - ClearCommError( h, &dwErrorFlags, &ComStat ); + #elif defined( MBG_TGT_POSIX ) - if ( dwErrorFlags ) - break; //#++ Error: Check flags - } + int rc = write( h, buffer, count ); // returns -1 on error, else number of byte written - return dwTotalBytesWritten; + if ( rc == -1 ) + return mbg_get_last_error( "write failed in mbgserio_write" ); + + return rc; + + #elif defined( MBG_TGT_DOS ) && defined( _USE_V24TOOLS ) + + return v24write( h, buffer, count ); + + #else + + #error mbgserio_write() not implemented for this target + + #endif } // mbgserio_write -#endif // defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_CVI ) + + +/*HDR*/ +_NO_MBG_API_ATTR void _MBG_API mbgserio_flush_tx( MBG_PORT_HANDLE h ) +{ + #if defined( MBG_TGT_CVI ) + + FlushOutQ( h ); + + #elif defined( MBG_TGT_WIN32 ) + + #if defined( DEBUG ) + printf( "Flushing TX buffers ...\n" ); + #endif + + FlushFileBuffers( h ); + + #if ( 1 && defined( DEBUG ) ) //##++++++++++++++ + { + COMSTAT ComStat; + DWORD dwErrorFlags; + + for (;;) + { + ClearCommError( h, &dwErrorFlags, &ComStat ); + + printf( "ErrFlags: %04X, out queue: %u\n", dwErrorFlags, ComStat.cbOutQue ); + + if ( ComStat.cbOutQue == 0 ) + break; + + Sleep( 1 ); + } + } + #endif + + //##++++ Sleep( 500 ); + + #elif defined( MBG_TGT_POSIX ) + + tcdrain( h ); + + #elif defined( MBG_TGT_DOS ) && defined( _USE_V24TOOLS ) + + v24flush( h, SND ); + + #else + + #error mbgserio_flush_tx() not implemented for this target + + #endif + +} // mbgserio_flush_tx /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, - uint count, ulong char_timeout ) +_NO_MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, + uint count, ulong char_timeout ) { int n_bytes; @@ -904,14 +1380,25 @@ _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, struct timeval tv_char_timeout; fd_set fds; + int max_fd; int rc; - mbgserio_msec_to_timeval( char_timeout, &tv_char_timeout ); + mbg_msec_to_timeval( char_timeout, &tv_char_timeout ); FD_ZERO( &fds ); FD_SET( h, &fds ); - rc = select( h + 1, &fds, NULL, NULL, &tv_char_timeout ); + #if defined( MBG_TGT_WIN32 ) + // Under Windows an fd is a handle which can't simply + // be converted to an int, but the first argument of + // select() is ignored under Windows anyway, so we just + // set max_fd to 0. + max_fd = 0; + #else + max_fd = h; + #endif + + rc = select( max_fd + 1, &fds, NULL, NULL, &tv_char_timeout ); if ( rc < 0 ) // error goto fail; @@ -920,7 +1407,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, goto timeout; // data is available - n_bytes = _mbgserio_read( h, buffer, count ); + n_bytes = mbgserio_read( h, buffer, count ); #else MBG_TMO_TIME tmo; @@ -929,7 +1416,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, for (;;) // wait to read one new char { - n_bytes = _mbgserio_read( h, buffer, count ); + n_bytes = mbgserio_read( h, buffer, count ); if ( n_bytes > 0 ) // new char(s) received break; @@ -940,7 +1427,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, if ( mbg_tmo_curr_time_is_after( &tmo ) ) goto timeout; - #if defined( MBG_TGT_UNIX ) + #if defined( MBG_TGT_POSIX ) usleep( 10 * 1000 ); #endif } @@ -949,10 +1436,10 @@ _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, return n_bytes; timeout: - return MBGSERIO_TIMEOUT; + return MBG_ERR_TIMEOUT; fail: - return MBGSERIO_FAIL; + return MBG_ERR_IO; } // mbgserio_read_wait diff --git a/mbglib/common/mbgserio.h b/mbglib/common/mbgserio.h index 2367e14..ac76534 100644 --- a/mbglib/common/mbgserio.h +++ b/mbglib/common/mbgserio.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgserio.h 1.4 2009/09/01 10:54:29 martin REL_M $ + * $Id: mbgserio.h 1.7.1.4 2014/03/11 12:26:46 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,22 @@ * * ----------------------------------------------------------------------- * $Log: mbgserio.h $ + * Revision 1.7.1.4 2014/03/11 12:26:46 martin + * Revision 1.7.1.3 2014/03/04 12:08:13 martin + * Revision 1.7.1.2 2014/01/08 17:19:42Z martin + * MBG_TGT_POSIX + * New libusb + * Revision 1.7.1.1 2014/01/07 17:00:29 martin + * Use common Meinberg error codes. + * Revision 1.7 2013/02/01 16:10:45 martin + * Got rid of _mbg_open/close/read/write() macros. + * Functions are now used instead. + * Updated function prototypes. + * Revision 1.6 2011/08/23 10:15:25Z martin + * Updated function prototypes. + * Revision 1.5 2011/08/04 09:48:55 martin + * Support flushing output. + * Re-ordered some definitions. * Revision 1.4 2009/09/01 10:54:29 martin * Include mbg_tmo.h for the new portable timeout functions. * Added symbols for return codes in case of an error. @@ -30,12 +46,14 @@ /* Other headers to be included */ +#include #include +#include #include #include -#if defined( MBG_TGT_UNIX ) +#if defined( MBG_TGT_POSIX ) #include #endif @@ -44,7 +62,7 @@ #endif #if !defined( _USE_SELECT_FOR_SERIAL_IO ) - #if defined( MBG_TGT_UNIX ) + #if defined( MBG_TGT_POSIX ) #define _USE_SELECT_FOR_SERIAL_IO 1 #else #define _USE_SELECT_FOR_SERIAL_IO 0 @@ -62,11 +80,6 @@ /* Start of header body */ -#define MBGSERIO_FAIL -1 // Generic I/O error -#define MBGSERIO_TIMEOUT -2 // timeout -#define MBGSERIO_INV_CFG -3 // invalid configuration parameters - - #if !defined( DEFAULT_DEV_NAME ) #if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_DOS ) #define DEFAULT_DEV_NAME "COM1" @@ -94,61 +107,18 @@ #include - #define _mbg_open _open - #define _mbg_close _close - #define _mbg_read _read - #define _mbg_write _write - - #define _mbgserio_write( _dh, _p, _sz ) \ - ComWrt( _dh, (char *) (_p), _sz ) - - #define _mbgserio_read( _dh, _p, _sz ) \ - ComRd( _dh, (char *) (_p), _sz ) - #elif defined( MBG_TGT_WIN32 ) - #include #include - #define _mbg_open _open - #define _mbg_close _close - #define _mbg_read _read - #define _mbg_write _write - - #define _mbgserio_write mbgserio_write - #define _mbgserio_read mbgserio_read - - #elif defined( MBG_TGT_UNIX ) - - #include - - #define _mbg_open open - #define _mbg_close close - #define _mbg_read read - #define _mbg_write write - #elif defined( MBG_TGT_DOS ) #if defined( _USE_V24TOOLS ) #include - - #define _mbgserio_open v24open - #define _mbgserio_read v24read - #define _mbgserio_write v24write #endif #endif - #if !defined( _mbgserio_open ) - #define _mbgserio_open _mbg_open - #endif - #if !defined( _mbgserio_write ) - #define _mbgserio_write _mbg_write - #endif - #if !defined( _mbgserio_read ) - #define _mbgserio_read _mbg_read - #endif - #endif @@ -169,10 +139,11 @@ typedef struct #if defined( MBG_TGT_WIN32 ) DCB old_dcb; COMMTIMEOUTS old_commtimeouts; + COMMPROP comm_prop; #endif - #if defined( MBG_TGT_UNIX ) - struct termios oldtio; - //##++ struct termios newtio; + + #if defined( MBG_TGT_POSIX ) + struct termios old_tio; #endif } SERIAL_IO_STATUS; @@ -190,14 +161,33 @@ extern "C" { /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ - _MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev ) ; - _MBG_API_ATTR int _MBG_API mbgserio_close( SERIAL_IO_STATUS *pst ) ; - _MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, int max_devs ) ; - _MBG_API_ATTR void _MBG_API _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list ) ; - _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, uint32_t baud_rate, const char *framing ) ; - _MBG_API_ATTR int _MBG_API mbgserio_read( MBG_PORT_HANDLE h, void *buffer, unsigned int count ) ; - _MBG_API_ATTR int _MBG_API mbgserio_write( MBG_PORT_HANDLE h, const void *buffer, unsigned int count ) ; - _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, uint count, ulong char_timeout ) ; + /** + * @brief + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgserio_close( SERIAL_IO_STATUS *pst ) ; + + /** + * @brief + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev ) ; + + _NO_MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, int max_devs ) ; + _NO_MBG_API_ATTR void _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list ) ; + /** + * @brief + * + * @return One of the @ref MBG_RETURN_CODES + */ + _NO_MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, uint32_t baud_rate, const char *framing ) ; + + _NO_MBG_API_ATTR int _MBG_API mbgserio_read( MBG_PORT_HANDLE h, void *buffer, unsigned int count ) ; + _NO_MBG_API_ATTR int _MBG_API mbgserio_write( MBG_PORT_HANDLE h, const void *buffer, unsigned int count ) ; + _NO_MBG_API_ATTR void _MBG_API mbgserio_flush_tx( MBG_PORT_HANDLE h ) ; + _NO_MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, uint count, ulong char_timeout ) ; /* ----- function prototypes end ----- */ diff --git a/mbglib/common/pcpsdefs.h b/mbglib/common/pcpsdefs.h index a5b4b94..56ab821 100644 --- a/mbglib/common/pcpsdefs.h +++ b/mbglib/common/pcpsdefs.h @@ -1,16 +1,54 @@ /************************************************************************** * - * $Id: pcpsdefs.h 1.46 2011/01/13 11:44:29 martin REL_M $ + * $Id: pcpsdefs.h 1.55.1.2 2014/10/17 13:28:29 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: - * General definitions for Meinberg plug-in radio clocks + * General definitions for Meinberg plug-in devices. * * ----------------------------------------------------------------------- * $Log: pcpsdefs.h $ - * Revision 1.46 2011/01/13 11:44:29 martin + * Revision 1.55.1.2 2014/10/17 13:28:29 martin + * Revision 1.55.1.1 2014/10/17 11:36:44 martin + * Updated doxygen comments. + * Revision 1.55 2014/07/17 10:52:24 martin + * Increased safety of firmware builds. + * Revision 1.54 2014/07/17 09:54:19 martin + * New command codes PC_GPS_XMR_HOLDOVER_STATUS + * and PC_GPS_ALL_GPIO_STATUS. + * Huge update and cleanup on doxygen comments. + * Revision 1.53 2014/05/27 10:13:20 martin + * Support GPS180AMC. + * Moved some signal constant definitions to pcpsdefs.h. + * Simplified declaration of code/name tables. + * Huge rework of comments in doxygen format. + * Revision 1.52 2013/09/26 09:02:52Z martin + * Support GNSS API. + * Updated doxygen comments. + * Revision 1.51 2013/06/25 09:51:39 martin + * Support GLN180PEX. + * Revision 1.50 2013/01/30 15:59:54 martin + * Updated and fixed some doxygen comments. + * Revision 1.49 2012/10/02 18:53:02 martin + * Added structure PCPS_TIME_STATUS_X_MASKS. + * Added initializer for command names, useful for debugging. + * Revision 1.48 2011/11/25 15:02:28 martin + * Support on-board event logs. + * Revision 1.47 2011/11/25 10:22:44 martin + * Modified handling of pragma pack(). + * Made command group codes obsolete. They are still supported + * when building firmware, though. + * Support PTP unicast configuration. + * Support GPIO configuration. + * Support PZF180PEX. + * Added commands to read CORR_INFO, read/write TR_DISTANCE, + * PCPS_SYNC_PZF status, and associated structures. + * Added an initializer for a table of GPS command code/names. + * Added definitions MBG_PCPS_FMT_STATUS. + * Updated some comments. + * Revision 1.46 2011/01/13 11:44:29Z martin * Moved status port register definitions here. * Revision 1.45 2010/09/06 07:36:24 martin * Support GPS180PEX and TCR180PEX. @@ -182,8 +220,8 @@ * Changes before put under RCS control: * * Revision 1.5 2000/03/24 - * Introduced PCPS_GIVE_SERNUM - * Cleaned up for definitions for serial parameter byte + * Introduced PCPS_GIVE_SERNUM. + * Cleaned up for definitions for serial parameter byte. * Reviewed and updated comments. * * 1998/07/22 @@ -192,7 +230,7 @@ * Reviewed and updated comments. * * 1997/06/12 - * GPS definitions added. + * Added GPS definitions. * * 1996/01/25 * PCPS_TIME redefined from an array of bytes to a structure. @@ -208,37 +246,49 @@ #include #include +#ifndef _USE_PCPSPRIV + #define _USE_PCPSPRIV _IS_MBG_FIRMWARE +#endif + +#if _USE_PCPSPRIV + #include +#endif -/* Start of header body */ +/* Start of header body */ -#if defined( _USE_PACK ) // set byte alignment - #pragma pack( 1 ) +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT #endif /** - * The following codes enumerate the ref time sources - * from which the clocks receive the reference time. + * @brief Enumeration of the ref time signal sources used by Meinberg devices */ -enum +enum PCPS_REF_TYPES { - PCPS_REF_NONE, /**< (unknown or not defined) */ - PCPS_REF_DCF, /**< see http://www.meinberg.de/english/info/dcf77.htm */ - PCPS_REF_GPS, /**< see http://www.meinberg.de/english/info/gps.htm */ - PCPS_REF_IRIG, /**< see http://www.meinberg.de/english/info/irig.htm */ - PCPS_REF_MSF, /**< MSF Receiver (UK) */ - PCPS_REF_PTP, /**< PTP Timestamp card */ - PCPS_REF_FRC, /**< Free Running Clock */ - PCPS_REF_WWVB, /**< WWVB Receiver (US) */ - PCPS_REF_JJY, /**< JJY Receiver (Japan) */ - N_PCPS_REF /**< number of valid ref time sources */ + PCPS_REF_NONE, ///< unknown, or not defined + PCPS_REF_DCF, ///< DCF77 long wave signal (Germany), see http://www.meinberg.de/english/info/dcf77.htm + PCPS_REF_GPS, ///< GPS satellite system, see http://www.meinberg.de/english/info/gps.htm + PCPS_REF_IRIG, ///< IRIG or similar time code, see http://www.meinberg.de/english/info/irig.htm + PCPS_REF_MSF, ///< MSF long wave signal (UK) + PCPS_REF_PTP, ///< PTP/IEEE1588 network protocol + PCPS_REF_FRC, ///< Free Running Clock + PCPS_REF_WWVB, ///< WWVB long wave signal (U.S.) + PCPS_REF_JJY, ///< JJY long wave signal (Japan) + N_PCPS_REF ///< number of defined ref time sources }; -/* Initializers for the reference source names */ +/** + * @defgroup group_pcps_ref_type_names Reference type names + * + * @see ::PCPS_REF_TYPES + * + * @{ */ -#define PCPS_REF_NAME_NONE_ENG "unknown" -#define PCPS_REF_NAME_NONE_GER "nicht bekannt" +#define PCPS_REF_NAME_NONE_ENG "unknown" +#define PCPS_REF_NAME_NONE_GER "nicht bekannt" #define PCPS_REF_NAME_DCF "DCF77" #define PCPS_REF_NAME_GPS "GPS" #define PCPS_REF_NAME_IRIG "IRIG" @@ -248,7 +298,14 @@ enum #define PCPS_REF_NAME_WWVB "WWVB" #define PCPS_REF_NAME_JJY "JJY" +/** @} @defgroup group_pcps_ref_type_names */ + +/** + * @brief Initializer for an array of English reference type names + * + * @see ::PCPS_REF_TYPES + */ #define PCPS_REF_NAMES_ENG \ { \ PCPS_REF_NAME_NONE_ENG, \ @@ -263,6 +320,11 @@ enum } +/** + * @brief Initializer for a multi-language array of reference type names + * + * @see ::PCPS_REF_TYPES + */ #define PCPS_REF_NAMES_LSTR \ { \ { PCPS_REF_NAME_NONE_ENG, PCPS_REF_NAME_NONE_GER }, \ @@ -278,20 +340,30 @@ enum -/** - PCI vendor ID number (assigned by PCI SIG) -*/ +/** + * @brief Meinberg PCI vendor ID (assigned by the PCI SIG) + * + * @see @ref MEINBERG_PCI_DEVICE_IDS + */ #define PCI_VENDOR_MEINBERG 0x1360 -/* PCI device ID numbers (assigned by Meinberg) * - * High byte: type of ref time source - * Low Byte: enumeration of device types - */ + +/** + * @brief PCI device IDs assigned by Meinberg + * + * High byte: type of ref time source, see ::PCPS_REF_TYPES + * Low Byte: enumeration of device types + * + * @see ::PCI_VENDOR_MEINBERG + * + * @anchor MEINBERG_PCI_DEVICE_IDS @{ */ + #define PCI_DEV_PCI32 ( ( PCPS_REF_DCF << 8 ) | 0x01 ) #define PCI_DEV_PCI509 ( ( PCPS_REF_DCF << 8 ) | 0x02 ) #define PCI_DEV_PCI510 ( ( PCPS_REF_DCF << 8 ) | 0x03 ) #define PCI_DEV_PCI511 ( ( PCPS_REF_DCF << 8 ) | 0x04 ) #define PCI_DEV_PEX511 ( ( PCPS_REF_DCF << 8 ) | 0x05 ) +#define PCI_DEV_PZF180PEX ( ( PCPS_REF_DCF << 8 ) | 0x06 ) #define PCI_DEV_GPS167PCI ( ( PCPS_REF_GPS << 8 ) | 0x01 ) #define PCI_DEV_GPS168PCI ( ( PCPS_REF_GPS << 8 ) | 0x02 ) @@ -299,6 +371,8 @@ enum #define PCI_DEV_GPS170PCI ( ( PCPS_REF_GPS << 8 ) | 0x04 ) #define PCI_DEV_GPS170PEX ( ( PCPS_REF_GPS << 8 ) | 0x05 ) #define PCI_DEV_GPS180PEX ( ( PCPS_REF_GPS << 8 ) | 0x06 ) +#define PCI_DEV_GLN180PEX ( ( PCPS_REF_GPS << 8 ) | 0x07 ) +#define PCI_DEV_GPS180AMC ( ( PCPS_REF_GPS << 8 ) | 0x08 ) #define PCI_DEV_TCR510PCI ( ( PCPS_REF_IRIG << 8 ) | 0x01 ) #define PCI_DEV_TCR167PCI ( ( PCPS_REF_IRIG << 8 ) | 0x02 ) @@ -311,511 +385,556 @@ enum #define PCI_DEV_FRC511PEX ( ( PCPS_REF_FRC << 8 ) | 0x01 ) +/** @} anchor MEINBERG_PCI_DEVICE_IDS */ -// definitions used for the status port register -// (not to be intermixed with PCPS_TIME_STATUS) -typedef uint8_t PCPS_STATUS_PORT; /**< see \ref group_status_port "Bitmask" */ -/** @defgroup group_status_port Bit masks of PCPS_STATUS_PORT +/** + * @defgroup group_status_port Definitions used with the status port + * + * The status port register on bus-level cards reflects some hardware + * signals (e.g. DCF-77 modulation), and flags used for communication + * with the card (e.g. the BUSY flag, ::PCPS_ST_BUSY). + * + * @note Must not be confused with ::PCPS_TIME_STATUS which returns + * the synchronization status and associated information + * + * @{ */ - Bit definitions used with the #PCPS_STATUS_PORT register. +/** + * @brief Type of the status register port + */ +typedef uint8_t PCPS_STATUS_PORT; ///< see @ref PCPS_STATUS_PORT_BIT_MASKS - The flags #PCPS_ST_SEC and #PCPS_ST_MIN are cleared whenever the clock - is read, so they are not very reliable in multitasking environments. - NOTE: The PCPS_ST_IRQF flag originates from old ISA cards. - Some PCI cards also support this, but in case of PCI cards the - associated flag of the PCI interface chip should be checked to see - if a certain card has generated an IRQ on the PC bus. +/** + * @brief Bit masks used with ::PCPS_STATUS_PORT + * + * The flags ::PCPS_ST_SEC and ::PCPS_ST_MIN are cleared whenever the clock + * is read, so they are not very reliable in multitasking environments. + * + * The ::PCPS_ST_IRQF flag originates from old ISA cards. + * Some PCI cards also support this, but in case of PCI cards the + * associated flag of the PCI interface chip should be checked to see + * if a particular card has generated an IRQ on the PC bus. + * + * The macro _pcps_ddev_has_gen_irq() cares about this and should be used + * to determine in a portable way whether a card has generated an IRQ. + * + * @anchor PCPS_STATUS_PORT_BIT_MASKS @{ */ - The macro _pcps_ddev_has_gen_irq() cares about this and should be used - to determine in a portable way whether a card has generated an IRQ. +#define PCPS_ST_BUSY 0x01 ///< the clock is busy filling the output FIFO +#define PCPS_ST_IRQF 0x02 ///< the clock has generated an IRQ on the PC bus (ISA cards only) +#define PCPS_ST_MOD 0x20 ///< the raw demodulated DCF77 signal +#define PCPS_ST_SEC 0x40 ///< seconds have changed since last reading +#define PCPS_ST_MIN 0x80 ///< minutes have changed since last reading - * @{ - */ +/** @} anchor PCPS_STATUS_PORT_BIT_MASKS */ -#define PCPS_ST_BUSY 0x01 /**< the clock is busy filling the output FIFO */ -#define PCPS_ST_IRQF 0x02 /**< the clock has generated an IRQ on the PC bus (ISA only)*/ -#define PCPS_ST_MOD 0x20 /**< the raw demodulated DCF77 signal */ -#define PCPS_ST_SEC 0x40 /**< seconds have changed since last reading */ -#define PCPS_ST_MIN 0x80 /**< minutes have changed since last reading */ - -/** @} */ - - - -/** @defgroup group_cmd_bytes Command bytes used to access the device - - The commands described below can be used to access the Meinberg - computer peripherals. However, some of the commands have not been - implemented with older clock models, or firmware versions. - - The device driver library contains functions which detect the clocks - and check which features are supported by a given clock model/firmware - The header files pcpsdev.h and pcpsdrvr.h contain macros which can be - used to query whether a detected clock supports a feature. - If checking is required, the name of the macro is given in the - comments below. - - Some commands expect parameters to be passed to the board. In that - case, the board returns the number of parameter bytes expected when - the command code is passed. Every parameter byte has to be supplied - to the board exactly like a command byte. - Refer to function pcps_write_data() and the macro _pcps_write_var() - for details. - - - - #PCPS_GIVE_TIME
- Return a PCPS_TIME structure with current date, - time and status. Supported by all clocks. - - - #PCPS_GIVE_TIME_NOCLEAR
- Same as #PCPS_GIVE_TIME but the bits #PCPS_ST_SEC - and #PCPS_ST_MIN (see pcpsdev.h) of the status - port are not cleared. - Supported by all clocks except PC31/PS31 with - firmware version older than v3.0. - This is mainly used by the DOS TSR and should - not be used in other environments. - - - #PCPS_GIVE_SYNC_TIME
- Return a ::PCPS_TIME structure with date and time - of last synchronization of the clock or - the last time set via the interface. - _pcps_has_sync_time() checks whether supported. - - - #PCPS_GIVE_HR_TIME
- Return a PCPS_HR_TIME structure with current - date, time and status. This command should be - used to read the clock with higher resolution. - _pcps_has_hr_time() checks whether supported. - - - #PCPS_GIVE_IRIG_TIME
- Return a PCPS_IRIG_TIME structure with day-of-year, - time and status as decoded from the IRIG signal. - _pcps_has_irig_time() checks whether supported. - - - #PCPS_SET_TIME
- Set the board date, time and status. This - command expects sizeof( ::PCPS_STIME ) parameter - bytes. - _pcps_can_set_time() checks whether supported. - - - #PCPS_SET_EVENT_TIME
- Send a high resolution time stamp to the clock to - configure a UTC time when the clock shall generate - some event. This command expects a PCPS_TIME_STAMP - parameter. - _pcps_has_event_time() checks whether supported. - (requires custom GPS CERN firmware) - - - #PCPS_IRQ_NONE
- Disable the board's hardware IRQ
- - #PCPS_IRQ_1_SEC
- Enable hardware IRQs once per second
- - #PCPS_IRQ_1_MIN
- Enable hardware IRQs once per minute
- - #PCPS_IRQ_10_MIN
- Enable hardware IRQs once per 10 minutes
- - #PCPS_IRQ_30_MIN
- Enable hardware IRQs once per 30 minutes
- - - #PCPS_GET_SERIAL
- #PCPS_SET_SERIAL
- These commands read or set the configuration - of a clock's serial port COM0. The commands - expect PCPS_SERIAL_BYTES parameter bytes and - should be used preferably with the DCF77 - clocks which have only one COM port. - _pcps_has_serial() checks whether supported. - Recent GPS clocks' COM ports should be cfg'd - using the structures RECEIVER_INFO, PORT_INFO, - and STR_TYPE_INFO. - _pcps_has_receiver_info() checks whether - these are supported. If they are not, then - the code #PC_GPS_PORT_PARM together with the - #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA - commands should be used. - - - #PCPS_GET_TZCODE
- #PCPS_SET_TZCODE
- These commands read or set a DCF77 clock's - time zone code and should be used preferably - with the newer DCF77 clocks which have limited - support of different time zones. - _pcps_has_tzcode() checks whether supported. - A GPS clock's time zone must be cfg'd using - the code #PC_GPS_TZDL together with the - #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA - commands. - - - #PCPS_GET_PCPS_TZDL
- #PCPS_SET_PCPS_TZDL
- These commands read or set a DCF77 clock's - time zone / daylight saving configuration. - _pcps_has_pcps_tzdl() checks whether supported. - A GPS clock's time zone must be cfg'd using - the code #PC_GPS_TZDL together with the - #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA - commands. - - - #PCPS_GET_REF_OFFS
- #PCPS_SET_REF_OFFS
- These commands can be used to configure the - reference time offset from UTC for clocks - which can't determine the offset automatically, - e.g. from an IRIG input signal. - _pcps_has_ref_offs() checks whether supported. - - - #PCPS_GET_OPT_INFO
- #PCPS_SET_OPT_SETTINGS
- These commands can be used to configure some - optional settings, controlled by flags. - When reading, the clock returns a MBG_OPT_INFO - structure which contains the supported values, - plus the current settings. - When writing, clocks accepts a MBG_OPT_SETTINGS - structure only which contain the desired settings - of the supported flags only. - _pcps_has_opt_flags() checks whether supported. - - - #PCPS_GET_IRIG_RX_INFO
- #PCPS_SET_IRIG_RX_SETTINGS
- #PCPS_GET_IRIG_TX_INFO
- #PCPS_SET_IRIG_TX_SETTINGS
- These commands can be used to configure IRIG - inputs and outputs.
- When reading, the clock returns an IRIG_INFO - structure which contains the supported values, - plus the current settings.
- When writing, clocks accepts an IRIG_SETTINGS - structure only which contain the desired settings - only. _pcps_is_irig_rx() and _pcps_is_irig_tx() - check whether supported. - - - #PCPS_GET_IRIG_CTRL_BITS
- This command can be used to retrieve the control function - bits of the latest IRIG input frame. Those bits may carry - some well-known information as in the IEEE1344 code, but - may also contain some customized information, depending on - the IRIG frame type and the configuration of the IRIG generator. - So these bits are returned as-is and must be interpreted - by the application. - _pcps_has_irig_ctrl_bits() checks whether supported. - - - #PCPS_GET_SYNTH
- #PCPS_SET_SYNTH
- #PCPS_GET_SYNTH_STATE
- These commands can be used to configure an on-board - frequency synthesizer and query the synthesizer - status. The commands are only supported if the board - supports the RECEIVER_INFO structure and the flag - #GPS_HAS_SYNTH is set in the RECEIVER_INFO::features. - _pcps_has_synth() checks whether supported. - The structures SYNTH and SYNTH_STATE used with these - commands are defined in gpsdefs.h. - - - #PCPS_GIVE_FW_ID_1
- #PCPS_GIVE_FW_ID_2
- Returns the first/second block of PCPS_FIFO_SIZE - characters of the firmware ID string. These - commands can be used to check if the board - responds properly. This is done by the clock - detection functions. - - - #PCPS_GIVE_SERNUM
- Returns PCPS_FIFO_SIZE characters of the - clock's serial number. - _pcps_has_sernum() checks whether supported. - - - #PCPS_GENERIC_IO
- Generic I/O read and write. Can be used to query - specific data, e.g. a selected element of an array. - _pcps_has_generic_io() checks whether supported. - - - #PCPS_GET_DEBUG_STATUS
- This command reads a MBG_DEBUG_STATUS structure - which represents the internal status of the - IRIG decoder and some additional debug info. - _pcps_has_debug_status() checks whether supported. - - - #PCPS_READ_GPS_DATA
- #PCPS_WRITE_GPS_DATA
- These commands are used by the functions - pcps_read_gps_data() and pcps_write_gps_data() - to read or write large data structures to - Meinberg GPS plug-in clocks. - _pcps_is_gps() checks whether supported. - - - #PCPS_CLR_UCAP_BUFF
- Clear a clock's time capture buffer. - _pcps_can_clr_ucap_buff() checks whether - supported. - - - #PCPS_GIVE_UCAP_ENTRIES
- Read a PCPS_UCAP_ENTRIES structure which - reports the max number of entries and the - currently used number of entries in the - user capture buffer. - _pcps_has_ucap() checks whether supported. - - - #PCPS_GIVE_UCAP_EVENT
- Read capture events using a PCPS_HR_TIME - structure. This is faster than reading using the - GPS command #PC_GPS_UCAP. If no capture event is - available then the structure is filled with 0s. - _pcps_has_ucap() checks whether supported. - - - #PCPS_FORCE_RESET
- Resets the microprocessor on the radio clock - board. This is for debug purposes only and - should not be used by standard applications. - - The command codes listed above are defined below. The commands are - grouped for bytes having the same high nibble: - @{ -*/ -#define PCPS_GIVE_TIME_GROUP 0x00 -#define PCPS_SET_TIME_GROUP 0x10 -#define PCPS_IRQ_GROUP 0x20 -#define PCPS_CFG_GROUP 0x30 -#define PCPS_GIVE_DATA_GROUP 0x40 -#define PCPS_GPS_DATA_GROUP 0x50 -#define PCPS_CTRL_GROUP 0x60 -#define PCPS_CFG2_GROUP 0x70 +/** @} defgroup group_status_port */ -/* PCPS_GIVE_TIME_GROUP */ -#define PCPS_GIVE_TIME ( PCPS_GIVE_TIME_GROUP | 0x0 ) -#define PCPS_GIVE_TIME_NOCLEAR ( PCPS_GIVE_TIME_GROUP | 0x1 ) -#define PCPS_GIVE_SYNC_TIME ( PCPS_GIVE_TIME_GROUP | 0x2 ) // only supported if _pcps_has_sync_time() -#define PCPS_GIVE_HR_TIME ( PCPS_GIVE_TIME_GROUP | 0x3 ) // only supported if _pcps_has_hr_time() -#define PCPS_GIVE_IRIG_TIME ( PCPS_GIVE_TIME_GROUP | 0x4 ) // only supported if _pcps_has_irig_time() +/** + * A format string to be used with snprintb() which is available on some Unix + * systems to print information held in a bit coded variable. + */ +#define MBG_PCPS_FMT_STATUS \ + "\177\20b\0FREER\0b\1DL_ENB\0b\2SYNCD\0b\3DL_ANN\0b\4UTC\0b\5LS_ANN\0b\6IFTM\0b\7INVT" \ + "\0b\x08LS_ENB\0b\11ANT_FAIL\0b\x0aLS_ANN_NEG\0b\x0bSCALE_GPS\0b\x0cSCALE_TAI\0\0" -/* PCPS_SET_TIME_GROUP */ -#define PCPS_SET_TIME ( PCPS_SET_TIME_GROUP | 0x0 ) -/* on error, return PCPS_ERR_STIME */ -/* Attention: The code below can be used EXCLUSIVELY */ -/* with a GPS167PCI with customized CERN firmware !! */ -/* _pcps_has_event_time() checks whether supported. */ -#define PCPS_SET_EVENT_TIME ( PCPS_SET_TIME_GROUP | 0x4 ) +/** + * @brief Command codes used to communicate with bus level devices + * + * These commands are used for low level access to bus-level devices + * manufactured by Meinberg. + * + * Applications should instead use the API functions declared in mbgdevio.h. + * + * The header files pcpsdev.h and pcpsdrvr.h contain macros which can be + * used to check if a detected device supports a certain feature or command. + * If checking is required then the name of the macro is given in the + * comments associated with the command codes. + * + * Some commands expect parameters to be passed to the board. In that + * case, the board returns the number of parameter bytes expected when + * the command code is passed. Every parameter byte has to be supplied + * to the board exactly like a command byte. + * + * Refer to function pcps_write_data() and the macro _pcps_write_var() + * for details. + * + * - #PCPS_GIVE_TIME
+ * Return a PCPS_TIME structure with current date, + * time and status. Supported by all clocks. + * + * - #PCPS_GIVE_TIME_NOCLEAR
+ * Same as #PCPS_GIVE_TIME but the bits #PCPS_ST_SEC + * and #PCPS_ST_MIN (see pcpsdev.h) of the status + * port are not cleared. + * Supported by all clocks except PC31/PS31 with + * firmware version older than v3.0. + * This is mainly used by the DOS TSR and should + * not be used in other environments. + * + * - #PCPS_GIVE_SYNC_TIME
+ * Return a ::PCPS_TIME structure with date and time + * of last synchronization of the clock or + * the last time set via the interface. + * _pcps_has_sync_time() checks whether supported. + * + * - #PCPS_GIVE_HR_TIME
+ * Return a PCPS_HR_TIME structure with current + * date, time and status. This command should be + * used to read the clock with higher resolution. + * _pcps_has_hr_time() checks whether supported. + * + * - #PCPS_GIVE_IRIG_TIME
+ * Return a PCPS_IRIG_TIME structure with day-of-year, + * time and status as decoded from the IRIG signal. + * _pcps_has_irig_time() checks whether supported. + * + * - #PCPS_SET_TIME
+ * Set the board date, time and status. This + * command expects sizeof( ::PCPS_STIME ) parameter + * bytes. + * _pcps_can_set_time() checks whether supported. + * + * - #PCPS_SET_EVENT_TIME
+ * Send a high resolution time stamp to the clock to + * configure a %UTC time when the clock shall generate + * some event. This command expects a PCPS_TIME_STAMP + * parameter. + * _pcps_has_event_time() checks whether supported. + * (requires custom GPS CERN firmware) + * + * - #PCPS_IRQ_NONE
+ * Disable the board's hardware IRQ
+ * - #PCPS_IRQ_1_SEC
+ * Enable hardware IRQs once per second
+ * - #PCPS_IRQ_1_MIN
+ * Enable hardware IRQs once per minute
+ * - #PCPS_IRQ_10_MIN
+ * Enable hardware IRQs once per 10 minutes
+ * - #PCPS_IRQ_30_MIN
+ * Enable hardware IRQs once per 30 minutes
+ * + * - #PCPS_GET_SERIAL
+ * #PCPS_SET_SERIAL
+ * These commands read or set the configuration + * of a clock's serial port COM0. The commands + * expect PCPS_SERIAL_BYTES parameter bytes and + * should be used preferably with the DCF77 + * clocks which have only one COM port. + * _pcps_has_serial() checks whether supported. + * Recent GPS clocks' COM ports should be cfg'd + * using the structures RECEIVER_INFO, PORT_INFO, + * and STR_TYPE_INFO. + * _pcps_has_receiver_info() checks whether + * these are supported. If they are not, then + * the code #PC_GPS_PORT_PARM together with the + * #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA + * commands should be used. + * + * - #PCPS_GET_TZCODE
+ * #PCPS_SET_TZCODE
+ * These commands read or set a DCF77 clock's + * time zone code and should be used preferably + * with the newer DCF77 clocks which have limited + * support of different time zones. + * _pcps_has_tzcode() checks whether supported. + * A GPS clock's time zone must be cfg'd using + * the code #PC_GPS_TZDL together with the + * #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA + * commands. + * + * - #PCPS_GET_PCPS_TZDL
+ * #PCPS_SET_PCPS_TZDL
+ * These commands read or set a DCF77 clock's + * time zone / daylight saving configuration. + * _pcps_has_pcps_tzdl() checks whether supported. + * A GPS clock's time zone must be cfg'd using + * the code #PC_GPS_TZDL together with the + * #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA + * commands. + * + * - #PCPS_GET_REF_OFFS
+ * #PCPS_SET_REF_OFFS
+ * These commands can be used to configure the + * reference time offset from %UTC for clocks + * which can't determine the offset automatically, + * e.g. from an IRIG input signal. + * _pcps_has_ref_offs() checks whether supported. + * + * - #PCPS_GET_OPT_INFO
+ * #PCPS_SET_OPT_SETTINGS
+ * These commands can be used to configure some + * optional settings, controlled by flags. + * When reading, the clock returns a MBG_OPT_INFO + * structure which contains the supported values, + * plus the current settings. + * When writing, clocks accepts a MBG_OPT_SETTINGS + * structure only which contain the desired settings + * of the supported flags only. + * _pcps_has_opt_flags() checks whether supported. + * + * - #PCPS_GET_IRIG_RX_INFO
+ * #PCPS_SET_IRIG_RX_SETTINGS
+ * #PCPS_GET_IRIG_TX_INFO
+ * #PCPS_SET_IRIG_TX_SETTINGS
+ * These commands can be used to configure IRIG + * inputs and outputs.
+ * When reading, the clock returns an IRIG_INFO + * structure which contains the supported values, + * plus the current settings.
+ * When writing, clocks accepts an IRIG_SETTINGS + * structure only which contain the desired settings + * only. _pcps_is_irig_rx() and _pcps_is_irig_tx() + * check whether supported. + * + * - #PCPS_GET_IRIG_CTRL_BITS
+ * This command can be used to retrieve the control function + * bits of the latest IRIG input frame. Those bits may carry + * some well-known information as in the IEEE1344 code, but + * may also contain some customized information, depending on + * the IRIG frame type and the configuration of the IRIG generator. + * So these bits are returned as-is and must be interpreted + * by the application. + * _pcps_has_irig_ctrl_bits() checks whether supported. + * + * - #PCPS_GET_SYNTH
+ * #PCPS_SET_SYNTH
+ * #PCPS_GET_SYNTH_STATE
+ * These commands can be used to configure an on-board + * frequency synthesizer and query the synthesizer + * status. The commands are only supported if the board + * supports the RECEIVER_INFO structure and the flag + * #GPS_HAS_SYNTH is set in the RECEIVER_INFO::features. + * _pcps_has_synth() checks whether supported. + * The structures SYNTH and SYNTH_STATE used with these + * commands are defined in gpsdefs.h. + * + * - #PCPS_GIVE_FW_ID_1
+ * #PCPS_GIVE_FW_ID_2
+ * Returns the first/second block of PCPS_FIFO_SIZE + * characters of the firmware ID string. These + * commands can be used to check if the board + * responds properly. This is done by the clock + * detection functions. + * + * - #PCPS_GIVE_SERNUM
+ * Returns PCPS_FIFO_SIZE characters of the + * clock's serial number. + * _pcps_has_sernum() checks whether supported. + * + * - #PCPS_GENERIC_IO
+ * Generic I/O read and write. Can be used to query + * specific data, e.g. a selected element of an array. + * _pcps_has_generic_io() checks whether supported. + * + * - #PCPS_GET_DEBUG_STATUS
+ * This command reads a MBG_DEBUG_STATUS structure + * which represents the internal status of the + * IRIG decoder and some additional debug info. + * _pcps_has_debug_status() checks whether supported. + * + * - #PCPS_READ_GPS_DATA
+ * #PCPS_WRITE_GPS_DATA
+ * These commands are used by the functions + * pcps_read_gps_data() and pcps_write_gps_data() + * to read or write large data structures to + * Meinberg GPS plug-in clocks. + * _pcps_is_gps() checks whether supported. + * + * - #PCPS_CLR_UCAP_BUFF
+ * Clear a clock's time capture buffer. + * _pcps_can_clr_ucap_buff() checks whether + * supported. + * + * - #PCPS_GIVE_UCAP_ENTRIES
+ * Read a PCPS_UCAP_ENTRIES structure which + * reports the max number of entries and the + * currently used number of entries in the + * user capture buffer. + * _pcps_has_ucap() checks whether supported. + * + * - #PCPS_GIVE_UCAP_EVENT
+ * Read capture events using a PCPS_HR_TIME + * structure. This is faster than reading using the + * GPS command #PC_GPS_UCAP. If no capture event is + * available then the structure is filled with 0s. + * _pcps_has_ucap() checks whether supported. + * + * - #PCPS_GET_CORR_INFO
+ * Read PZF correlation info using a CORR_INFO + * structure. + * _pcps_has_pzf() checks whether supported. + * + * - #PCPS_GET_TR_DISTANCE
+ * #PCPS_SET_TR_DISTANCE
+ * Read or write distance from the RF transmitter. + * This is used to compensate the RF propagation delay + * for PZF receivers. + * _pcps_has_tr_distance() checks whether supported. + * + * - #PCPS_CLR_EVT_LOG
+ * Clear on-board event log. + * _pcps_has_evt_log() checks whether supported. + * + * - #PCPS_NUM_EVT_LOG_ENTRIES
+ * Read max number of num event log entries which can + * be saved on the board, and how many entries actually + * have been saved. + * _pcps_has_evt_log() checks whether supported. + * + * - #PCPS_FIRST_EVT_LOG_ENTRY
+ * - #PCPS_NEXT_EVT_LOG_ENTRY
+ * Read first (oldest) or next event log entry. + * _pcps_has_evt_log() checks whether supported. + * + * - #PCPS_FORCE_RESET
+ * Resets the microprocessor on the device. This is + * for special test scenarios only and should not be + * used by standard applications since this may lock up + * the computer. + * + * @anchor PCPS_CMD_CODES @{ */ +#define PCPS_GIVE_TIME 0x00 ///< (r-) read current time in ::PCPS_TIME format +#define PCPS_GIVE_TIME_NOCLEAR 0x01 ///< (r-) read current time in ::PCPS_TIME format, don't clear sec and min flags +#define PCPS_GIVE_SYNC_TIME 0x02 ///< (r-) read last sync time as ::PCPS_TIME, only if ::_pcps_has_sync_time() +#define PCPS_GIVE_HR_TIME 0x03 ///< (r-) read high res. time as ::PCPS_HR_TIME, only if ::_pcps_has_hr_time() +#define PCPS_GIVE_IRIG_TIME 0x04 ///< (r-) read raw IRIG time as ::PCPS_IRIG_TIME, only if ::_pcps_has_irig_time() -/* PCPS_IRQ_GROUP */ -#define PCPS_IRQ_NONE ( PCPS_IRQ_GROUP | 0x0 ) -#define PCPS_IRQ_1_SEC ( PCPS_IRQ_GROUP | 0x1 ) -#define PCPS_IRQ_1_MIN ( PCPS_IRQ_GROUP | 0x2 ) -#define PCPS_IRQ_10_MIN ( PCPS_IRQ_GROUP | 0x4 ) -#define PCPS_IRQ_30_MIN ( PCPS_IRQ_GROUP | 0x8 ) +#define PCPS_SET_TIME 0x10 ///< (-w) set on-board time, see ::PCPS_STIME +/* on error, return PCPS_ERR_STIME */ +#define PCPS_SET_EVENT_TIME 0x14 ///< (-w) write event time as ::PCPS_TIME_STAMP, only if ::_pcps_has_event_time() -/* PCPS_CFG_GROUP */ +#define PCPS_IRQ_NONE 0x20 ///< (-w) disable IRQs +#define PCPS_IRQ_1_SEC 0x21 ///< (-w) enable IRQ per 1 second +#define PCPS_IRQ_1_MIN 0x22 ///< (-w) enable IRQ per 1 minute (deprecated) +#define PCPS_IRQ_10_MIN 0x24 ///< (-w) enable IRQ per 10 minutes (deprecated) +#define PCPS_IRQ_30_MIN 0x28 ///< (-w) enable IRQ per 10 minutes (deprecated) -#define PCPS_GET_SERIAL ( PCPS_CFG_GROUP | 0x0 ) -#define PCPS_SET_SERIAL ( PCPS_CFG_GROUP | 0x1 ) +#define PCPS_GET_SERIAL 0x30 ///< (r-) read serial settings as ::PCPS_SERIAL, superseded by ::PC_GPS_ALL_PORT_INFO +#define PCPS_SET_SERIAL 0x31 ///< (-w) write serial settings as ::PCPS_SERIAL, superseded by ::PC_GPS_PORT_SETTINGS_IDX /* on error, return PCPS_ERR_CFG */ -typedef uint8_t PCPS_SERIAL; - - -#define PCPS_GET_TZCODE ( PCPS_CFG_GROUP | 0x2 ) -#define PCPS_SET_TZCODE ( PCPS_CFG_GROUP | 0x3 ) +#define PCPS_GET_TZCODE 0x32 ///< (r-) read ::PCPS_TZCODE, only if ::_pcps_has_tzcode() +#define PCPS_SET_TZCODE 0x33 ///< (-w) write ::PCPS_TZCODE, only if ::_pcps_has_tzcode() /* on error, return PCPS_ERR_CFG */ -typedef uint8_t PCPS_TZCODE; - -/* the following codes are used with the PCPS_TZCODE parameter: */ -enum -{ - PCPS_TZCODE_CET_CEST, /* default as broadcasted by DCF77 (UTC+1h/UTC+2h) */ - PCPS_TZCODE_CET, /* always CET (UTC+1h), discard DST */ - PCPS_TZCODE_UTC, /* always UTC */ - PCPS_TZCODE_EET_EEST, /* East European Time, CET/CEST + 1h */ - N_PCPS_TZCODE /* the number of valid codes */ -}; - -/* the definitions below are for compatibily only: */ -#define PCPS_TZCODE_MEZMESZ PCPS_TZCODE_CET_CEST -#define PCPS_TZCODE_MEZ PCPS_TZCODE_CET -#define PCPS_TZCODE_OEZ PCPS_TZCODE_EET_EEST - - -#define PCPS_GET_PCPS_TZDL ( PCPS_CFG_GROUP | 0x4 ) -#define PCPS_SET_PCPS_TZDL ( PCPS_CFG_GROUP | 0x5 ) +#define PCPS_GET_PCPS_TZDL 0x34 ///< (r-) read ::PCPS_TZDL, only if ::_pcps_has_pcps_tzdl() +#define PCPS_SET_PCPS_TZDL 0x35 ///< (-w) write ::PCPS_TZDL, only if ::_pcps_has_pcps_tzdl() /* on error, return PCPS_ERR_CFG */ -/** - * The structures below can be used to configure a clock's - * time zone/daylight saving setting. This structure is shorter - * than the TZDL structure used with GPS clocks. - */ -typedef struct -{ - // The year_or_wday field below contains the full year number - // or 0..6 == Sun..Sat if the DL_AUTO_FLAG is set; see below. - uint16_t year_or_wday; - uint8_t month; - uint8_t mday; - uint8_t hour; - uint8_t min; -} PCPS_DL_ONOFF; - -#define _mbg_swab_pcps_dl_onoff( _p ) \ -{ \ - _mbg_swab16( &(_p)->year_or_wday ); \ -} - -/** - * If the field year_or_wday is or'ed with the constant DL_AUTO_FLAG - * defined below then this means that start and end of daylight saving - * time shall be computed automatically for each year. In this case - * the remaining bits represent the day-of-week after the specified - * mday/month at which the change shall occur. If that flag is not set - * then the field contains the full four-digit year number and the - * mday/month values specify the exact date of that year. - */ -#define DL_AUTO_FLAG 0x8000 // also defined in gpsdefs.h - -typedef struct -{ - int16_t offs; /**< offset from UTC to local time [min] */ - int16_t offs_dl; /**< additional offset if DST enabled [min] */ - PCPS_DL_ONOFF tm_on; /**< date/time when daylight saving starts */ - PCPS_DL_ONOFF tm_off; /**< date/time when daylight saving ends */ -} PCPS_TZDL; - -#define _mbg_swab_pcps_tzdl( _p ) \ -{ \ - _mbg_swab16( &(_p)->offs ); \ - _mbg_swab16( &(_p)->offs_dl ); \ - _mbg_swab_pcps_dl_onoff( &(_p)->tm_on ); \ - _mbg_swab_pcps_dl_onoff( &(_p)->tm_off ); \ -} - - +#define PCPS_GET_REF_OFFS 0x36 ///< (r-) read ::MBG_REF_OFFS, only if ::_pcps_has_ref_offs() +#define PCPS_SET_REF_OFFS 0x37 ///< (-w) write ::MBG_REF_OFFS, only if ::_pcps_has_ref_offs() +/* on error, return PCPS_ERR_CFG */ -#define PCPS_GET_REF_OFFS ( PCPS_CFG_GROUP | 0x6 ) -#define PCPS_SET_REF_OFFS ( PCPS_CFG_GROUP | 0x7 ) +#define PCPS_GET_OPT_INFO 0x38 ///< (r-) read ::MBG_OPT_INFO, only if ::_pcps_has_opt_flags() +#define PCPS_SET_OPT_SETTINGS 0x39 ///< (-w) write ::MBG_OPT_SETTINGS, only if ::_pcps_has_opt_flags() /* on error, return PCPS_ERR_CFG */ -/* The associated type MBG_REF_OFFS is defined in gpsdefs.h. */ +#define PCPS_GET_IRIG_RX_INFO 0x3A ///< (r-) read ::IRIG_INFO, only if ::_pcps_is_irig_rx() +#define PCPS_SET_IRIG_RX_SETTINGS 0x3B ///< (-w) write ::IRIG_SETTINGS, only if ::_pcps_is_irig_rx() +/* on error, return PCPS_ERR_CFG */ +#define PCPS_GET_IRIG_TX_INFO 0x3C ///< (r-) read ::IRIG_INFO, only if ::_pcps_has_irig_tx() +#define PCPS_SET_IRIG_TX_SETTINGS 0x3D ///< (-w) write ::IRIG_SETTINGS, only if ::_pcps_has_irig_tx() +/* on error, return PCPS_ERR_CFG */ -#define PCPS_GET_OPT_INFO ( PCPS_CFG_GROUP | 0x8 ) -#define PCPS_SET_OPT_SETTINGS ( PCPS_CFG_GROUP | 0x9 ) +#define PCPS_GET_SYNTH 0x3E ///< (r-) read ::SYNTH, only if ::_pcps_has_synth() +#define PCPS_SET_SYNTH 0x3F ///< (-w) write ::SYNTH, only if ::_pcps_has_synth() /* on error, return PCPS_ERR_CFG */ -/* The associated structures MBG_OPT_INFO and MBG_OPT_SETTINGS - are defined in gpsdefs.h. */ +#define PCPS_GIVE_FW_ID_1 0x40 ///< (r-) get first ::PCPS_FIFO_SIZE chars of firmware ID +#define PCPS_GIVE_FW_ID_2 0x41 ///< (r-) get last ::PCPS_FIFO_SIZE chars of firmware ID +#define PCPS_GIVE_SERNUM 0x42 ///< (r-) read serial number as ::PCPS_SN_STR, only if _pcps_has_sernum() +#define PCPS_GENERIC_IO 0x43 ///< (rw) see pcps_generic_io() or _mbgdevio_gen_io() +#define PCPS_GET_SYNTH_STATE 0x44 ///< (r-) read ::SYNTH_STATE, only if _pcps_has_synth() +#define PCPS_GET_IRIG_CTRL_BITS 0x45 ///< (r-) read ::MBG_IRIG_CTRL_BITS, only if ::_pcps_has_irig_ctrl_bits() +#define PCPS_GET_RAW_IRIG_DATA 0x46 ///< (r-) read ::MBG_RAW_IRIG_DATA, only if ::_pcps_has_raw_irig_data() +#define PCPS_GET_STATUS_PORT 0x4B ///< (r-) read ::PCPS_STATUS_PORT +#define PCPS_GET_DEBUG_STATUS 0x4C ///< (r-) read ::MBG_DEBUG_STATUS, only if _pcps_has_debug_status() -#define PCPS_GET_IRIG_RX_INFO ( PCPS_CFG_GROUP | 0xA ) -#define PCPS_SET_IRIG_RX_SETTINGS ( PCPS_CFG_GROUP | 0xB ) -/* on error, return PCPS_ERR_CFG */ +// Command codes 0x4D, 0x4E, and 0x4F are reserved. -#define PCPS_GET_IRIG_TX_INFO ( PCPS_CFG_GROUP | 0xC ) -#define PCPS_SET_IRIG_TX_SETTINGS ( PCPS_CFG_GROUP | 0xD ) -/* on error, return PCPS_ERR_CFG */ +#define PCPS_READ_GPS_DATA 0x50 ///< (r-) read large data structure, see ::PC_GPS_CMD_CODES +#define PCPS_WRITE_GPS_DATA 0x51 ///< (-w) write large data structure, see ::PC_GPS_CMD_CODES -/* The associated structures IRIG_INFO and IRIG_SETTINGS - are defined in gpsdefs.h. */ +#define PCPS_CLR_UCAP_BUFF 0x60 ///< (-w) no param., clear on-board capture FIFO, only if ::_pcps_has_ucap() +#define PCPS_GIVE_UCAP_ENTRIES 0x61 ///< (r-) read ::PCPS_UCAP_ENTRIES, only if ::_pcps_has_ucap() +#define PCPS_GIVE_UCAP_EVENT 0x62 ///< (r-) return oldes event as ::PCPS_HR_TIME, only if ::_pcps_has_ucap() +#define PCPS_GET_CORR_INFO 0x63 ///< (r-) read ::CORR_INFO structure, only if _pcps_has_pzf() +#define PCPS_GET_TR_DISTANCE 0x64 ///< (r-) read ::TR_DISTANCE, only if _pcps_has_tr_distance() +#define PCPS_SET_TR_DISTANCE 0x65 ///< (-w) write ::TR_DISTANCE, only if _pcps_has_tr_distance() -#define PCPS_GET_SYNTH ( PCPS_CFG_GROUP | 0xE ) -#define PCPS_SET_SYNTH ( PCPS_CFG_GROUP | 0xF ) -/* on error, return PCPS_ERR_CFG */ +#define PCPS_CLR_EVT_LOG 0x66 ///< (-w) write clear on-board event log, only if _pcps_has_evt_log() +#define PCPS_NUM_EVT_LOG_ENTRIES 0x67 ///< (r-) read ::MBG_NUM_EVT_LOG_ENTRIES, only if _pcps_has_evt_log() +#define PCPS_FIRST_EVT_LOG_ENTRY 0x68 ///< (r-) read first (oldest) ::MBG_EVT_LOG_ENTRY, only if _pcps_has_evt_log() +#define PCPS_NEXT_EVT_LOG_ENTRY 0x69 ///< (r-) read next ::MBG_EVT_LOG_ENTRY, only if _pcps_has_evt_log() -/* The associated structure SYNTH is defined in gpsdefs.h. */ +#define PCPS_FORCE_RESET 0x80 ///< (-w) no param., reset the device (this can lockup the computer!!) +/// @note Command codes 0xF0 through 0xFF are reserved. +/** @} anchor PCPS_CMD_CODES */ -/* PCPS_GIVE_DATA_GROUP */ -#define PCPS_GIVE_FW_ID_1 ( PCPS_GIVE_DATA_GROUP | 0x0 ) -#define PCPS_GIVE_FW_ID_2 ( PCPS_GIVE_DATA_GROUP | 0x1 ) -#define PCPS_GIVE_SERNUM ( PCPS_GIVE_DATA_GROUP | 0x2 ) -#define PCPS_GENERIC_IO ( PCPS_GIVE_DATA_GROUP | 0x3 ) -#define PCPS_GET_SYNTH_STATE ( PCPS_GIVE_DATA_GROUP | 0x4 ) -#define PCPS_GET_IRIG_CTRL_BITS ( PCPS_GIVE_DATA_GROUP | 0x5 ) -#define PCPS_GET_RAW_IRIG_DATA ( PCPS_GIVE_DATA_GROUP | 0x6 ) +#if _IS_MBG_FIRMWARE -#define PCPS_GET_STATUS_PORT ( PCPS_GIVE_DATA_GROUP | 0xB ) -#define PCPS_GET_DEBUG_STATUS ( PCPS_GIVE_DATA_GROUP | 0xC ) -// expects sizeof( MBG_DEBUG_STATUS ) chars +/** + * @brief Deprecated command group codes + * + * @deprecated These group codes are deprecated. + * They should not be used anymore but removed + * from existing source code. The explicite command + * codes @ref PCPS_CMD_CODES should be used instead. + * + * @anchor PCPS_CMD_GROUP_CODES @{ */ -// PCPS_GIVE_DATA_GROUP codes 0x0D, 0x0E, and 0x0F are reserved. +#define PCPS_GIVE_TIME_GROUP 0x00 +#define PCPS_SET_TIME_GROUP 0x10 +#define PCPS_IRQ_GROUP 0x20 +#define PCPS_CFG_GROUP 0x30 +#define PCPS_GIVE_DATA_GROUP 0x40 +#define PCPS_GPS_DATA_GROUP 0x50 +#define PCPS_CTRL_GROUP 0x60 +#define PCPS_CFG2_GROUP 0x70 +/** @} anchor PCPS_CMD_GROUP_CODES */ -/* PCPS_GPS_DATA_GROUP */ -#define PCPS_READ_GPS_DATA ( PCPS_GPS_DATA_GROUP | 0x0 ) -#define PCPS_WRITE_GPS_DATA ( PCPS_GPS_DATA_GROUP | 0x1 ) +#endif // _IS_MBG_FIRMWARE -/* PCPS_CTRL_GROUP */ -#define PCPS_CLR_UCAP_BUFF ( PCPS_CTRL_GROUP | 0x0 ) -#define PCPS_GIVE_UCAP_ENTRIES ( PCPS_CTRL_GROUP | 0x1 ) -#define PCPS_GIVE_UCAP_EVENT ( PCPS_CTRL_GROUP | 0x2 ) -typedef struct -{ - uint32_t used; /**< the number of saved capture events */ - uint32_t max; /**< capture buffer size */ -} PCPS_UCAP_ENTRIES; +#if !defined( MBG_CMD_TABLE_EXT ) + #define MBG_CMD_TABLE_EXT _mbg_cn_table_end() +#endif -#define _mbg_swab_pcps_ucap_entries( _p ) \ -{ \ - _mbg_swab32( &(_p)->used ); \ - _mbg_swab32( &(_p)->max ); \ +/** + * @brief An initializer for a table of code/name entries of non-GPS commands. + * + * This can e.g. initialize an array of ::MBG_CODE_NAME_TABLE_ENTRY elements + * and may be helpful when debugging. + * + * @see @ref PCPS_CMD_CODES + */ +#define PCPS_CMD_CODES_TABLE \ +{ \ + _mbg_cn_table_entry( PCPS_GIVE_TIME ), /* 0x00 */ \ + _mbg_cn_table_entry( PCPS_GIVE_TIME_NOCLEAR ), /* 0x01 */ \ + _mbg_cn_table_entry( PCPS_GIVE_SYNC_TIME ), /* 0x02 */ \ + _mbg_cn_table_entry( PCPS_GIVE_HR_TIME ), /* 0x03 */ \ + _mbg_cn_table_entry( PCPS_GIVE_IRIG_TIME ), /* 0x04 */ \ + _mbg_cn_table_entry( PCPS_SET_TIME ), /* 0x10 */ \ + _mbg_cn_table_entry( PCPS_SET_EVENT_TIME ), /* 0x14 */ \ + _mbg_cn_table_entry( PCPS_IRQ_NONE ), /* 0x20 */ \ + _mbg_cn_table_entry( PCPS_IRQ_1_SEC ), /* 0x21 */ \ + _mbg_cn_table_entry( PCPS_IRQ_1_MIN ), /* 0x22 */ \ + _mbg_cn_table_entry( PCPS_IRQ_10_MIN ), /* 0x24 */ \ + _mbg_cn_table_entry( PCPS_IRQ_30_MIN ), /* 0x28 */ \ + _mbg_cn_table_entry( PCPS_GET_SERIAL ), /* 0x30 */ \ + _mbg_cn_table_entry( PCPS_SET_SERIAL ), /* 0x31 */ \ + _mbg_cn_table_entry( PCPS_GET_TZCODE ), /* 0x32 */ \ + _mbg_cn_table_entry( PCPS_SET_TZCODE ), /* 0x33 */ \ + _mbg_cn_table_entry( PCPS_GET_PCPS_TZDL ), /* 0x34 */ \ + _mbg_cn_table_entry( PCPS_SET_PCPS_TZDL ), /* 0x35 */ \ + _mbg_cn_table_entry( PCPS_GET_REF_OFFS ), /* 0x36 */ \ + _mbg_cn_table_entry( PCPS_SET_REF_OFFS ), /* 0x37 */ \ + _mbg_cn_table_entry( PCPS_GET_OPT_INFO ), /* 0x38 */ \ + _mbg_cn_table_entry( PCPS_SET_OPT_SETTINGS ), /* 0x39 */ \ + _mbg_cn_table_entry( PCPS_GET_IRIG_RX_INFO ), /* 0x3A */ \ + _mbg_cn_table_entry( PCPS_SET_IRIG_RX_SETTINGS ), /* 0x3B */ \ + _mbg_cn_table_entry( PCPS_GET_IRIG_TX_INFO ), /* 0x3C */ \ + _mbg_cn_table_entry( PCPS_SET_IRIG_TX_SETTINGS ), /* 0x3D */ \ + _mbg_cn_table_entry( PCPS_GET_SYNTH ), /* 0x3E */ \ + _mbg_cn_table_entry( PCPS_SET_SYNTH ), /* 0x3F */ \ + _mbg_cn_table_entry( PCPS_GIVE_FW_ID_1 ), /* 0x40 */ \ + _mbg_cn_table_entry( PCPS_GIVE_FW_ID_2 ), /* 0x41 */ \ + _mbg_cn_table_entry( PCPS_GIVE_SERNUM ), /* 0x42 */ \ + _mbg_cn_table_entry( PCPS_GENERIC_IO ), /* 0x43 */ \ + _mbg_cn_table_entry( PCPS_GET_SYNTH_STATE ), /* 0x44 */ \ + _mbg_cn_table_entry( PCPS_GET_IRIG_CTRL_BITS ), /* 0x45 */ \ + _mbg_cn_table_entry( PCPS_GET_RAW_IRIG_DATA ), /* 0x46 */ \ + _mbg_cn_table_entry( PCPS_GET_STATUS_PORT ), /* 0x4B */ \ + _mbg_cn_table_entry( PCPS_GET_DEBUG_STATUS ), /* 0x4C */ \ + _mbg_cn_table_entry( PCPS_READ_GPS_DATA ), /* 0x50 */ \ + _mbg_cn_table_entry( PCPS_WRITE_GPS_DATA ), /* 0x51 */ \ + _mbg_cn_table_entry( PCPS_CLR_UCAP_BUFF ), /* 0x60 */ \ + _mbg_cn_table_entry( PCPS_GIVE_UCAP_ENTRIES ), /* 0x61 */ \ + _mbg_cn_table_entry( PCPS_GIVE_UCAP_EVENT ), /* 0x62 */ \ + _mbg_cn_table_entry( PCPS_GET_CORR_INFO ), /* 0x63 */ \ + _mbg_cn_table_entry( PCPS_GET_TR_DISTANCE ), /* 0x64 */ \ + _mbg_cn_table_entry( PCPS_SET_TR_DISTANCE ), /* 0x65 */ \ + _mbg_cn_table_entry( PCPS_CLR_EVT_LOG ), /* 0x66 */ \ + _mbg_cn_table_entry( PCPS_NUM_EVT_LOG_ENTRIES ), /* 0x67 */ \ + _mbg_cn_table_entry( PCPS_FIRST_EVT_LOG_ENTRY ), /* 0x68 */ \ + _mbg_cn_table_entry( PCPS_NEXT_EVT_LOG_ENTRY ), /* 0x69 */ \ + _mbg_cn_table_entry( PCPS_FORCE_RESET ), /* 0x80 */ \ + MBG_CMD_TABLE_EXT, \ + _mbg_cn_table_end() \ } /** - special -- use with care ! -*/ -#define PCPS_FORCE_RESET 0x80 + * @brief Bus level command return codes + * + * @deprecated These codes are deprecated and @ref MBG_RETURN_CODES should be used + * instead which provide corresponding symbols with same numeric values. + * + * @anchor PCPS_LEVEL_CMD_RETURN_CODES @{ */ -/** @} */ +#define PCPS_SUCCESS 0 ///< OK, no error (see ::MBG_SUCCESS) +#define PCPS_ERR_STIME -1 ///< invalid date/time/status passed (see ::MBG_ERR_STIME) +#define PCPS_ERR_CFG -2 ///< invalid parms for a cmd writing config parameters (see ::MBG_ERR_CFG) -/* Codes returned when commands with parameters have been passed */ -/* to the board */ -#define PCPS_SUCCESS 0 /**< OK, no error */ -#define PCPS_ERR_STIME -1 /**< invalid date/time/status passed */ -#define PCPS_ERR_CFG -2 /**< invalid parms with a PCPS_CFG_GROUP cmd */ +/** @} anchor PCPS_LEVEL_CMD_RETURN_CODES */ -#ifndef BITMASK +#if !defined( BITMASK ) #define BITMASK( b ) ( ( 1 << b ) - 1 ) #endif -/** The size of the plug-in radio clock's on-board FIFO: */ +/** @brief The size of a bus level device's command/data FIFO */ #define PCPS_FIFO_SIZE 16 +/** @brief A data buffer for a bus level device's command/data */ typedef int8_t PCPS_BUFF[PCPS_FIFO_SIZE]; -#define PCPS_ID_SIZE ( 2 * PCPS_FIFO_SIZE + 1 ) /**< ASCIIZ string */ +/** @brief The maximum length of an ID string, including terminating 0 */ +#define PCPS_ID_SIZE ( 2 * PCPS_FIFO_SIZE + 1 ) ///< ASCIIZ string + +/** @brief A buffer for an ID string, including terminating 0 */ typedef char PCPS_ID_STR[PCPS_ID_SIZE]; -#define PCPS_SN_SIZE ( PCPS_FIFO_SIZE + 1 ) /**< ASCIIZ string */ +/** @brief The maximum length of a serial number string, including terminating 0 */ +#define PCPS_SN_SIZE ( PCPS_FIFO_SIZE + 1 ) ///< ASCIIZ string + +/** @brief A buffer for a serial number string, including terminating 0 */ typedef char PCPS_SN_STR[PCPS_SN_SIZE]; + /** - * The structure has been introduced to be able to handle - * high resolution time stamps. + * @brief A high resolution time stamp */ typedef struct { - uint32_t sec; /**< seconds since 1970 (UTC) */ - uint32_t frac; /**< fractions of second ( 0xFFFFFFFF == 0.9999.. sec) */ + uint32_t sec; ///< seconds since 1970, usually %UTC scale + uint32_t frac; ///< binary fractions of second (0x80000000 == 0.5 s, 0xFFFFFFFF == 0.9999999.. s) + } PCPS_TIME_STAMP; #define _mbg_swab_pcps_time_stamp( _p ) \ @@ -829,59 +948,123 @@ typedef struct // Depending on the target environment define a data type // which can be used to convert binary fractions without // range overflow. -#if defined( MBG_TGT_UNIX ) - #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t -#elif defined( MBG_TGT_WIN32 ) - #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t -#elif defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) - #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t -#else +#if defined( MBG_TGT_MISSING_64_BIT_TYPES ) #define PCPS_HRT_FRAC_CONVERSION_TYPE double +#else + #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t #endif -// Max value of PCPS_TIME_STAMP::frac + 1 used for scaling +/** + * @brief Constant used to convert ::PCPS_TIME_STAMP::frac values + * + * Max value of ::PCPS_TIME_STAMP::frac + 1, used for scaling + */ #define PCPS_HRT_BIN_FRAC_SCALE ( (PCPS_HRT_FRAC_CONVERSION_TYPE) 4294967296.0 ) // == 0x100000000 -// The scale and format to be used to print the fractions -// of a second as returned in the PCPS_TIME_STAMP structure. -// The function frac_sec_from_bin() can be used for -// the conversion. #ifndef PCPS_HRT_FRAC_SCALE + /** + * @brief Scale to be used to print ::PCPS_TIME_STAMP::frac values + * + * The function ::frac_sec_from_bin can be used for the conversion. + * + * @see ::PCPS_HRT_FRAC_SCALE_FMT + */ #define PCPS_HRT_FRAC_SCALE 10000000UL #endif #ifndef PCPS_HRT_FRAC_SCALE_FMT + /** + * @brief Format specifier used to print ::PCPS_TIME_STAMP::frac values + * + * Used to print values scaled with ::frac_sec_from_bin called + * with ::PCPS_HRT_FRAC_SCALE. + * + * @see ::PCPS_HRT_FRAC_SCALE + */ #define PCPS_HRT_FRAC_SCALE_FMT "%07lu" #endif -typedef uint16_t PCPS_TIME_STATUS_X; /**< extended status */ +/** + * @brief Extended status code + * + * Low byte corresponds to ::PCPS_TIME_STATUS, high byte + * contains additional flags. + * + * @see ::PCPS_TIME_STATUS + * @see @ref PCPS_TIME_STATUS_FLAGS + */ +typedef uint16_t PCPS_TIME_STATUS_X; #define _mbg_swab_pcps_time_status_x( _p ) _mbg_swab16( _p ) +typedef struct +{ + PCPS_TIME_STATUS_X set_mask; + PCPS_TIME_STATUS_X clr_mask; + +} PCPS_TIME_STATUS_X_MASKS; + +#define _mbg_swab_pcps_time_status_x_masks( _p ) \ +{ \ + _mbg_swab_pcps_time_status_x( &(_p)->set_mask ); \ + _mbg_swab_pcps_time_status_x( &(_p)->clr_mask ); \ +} + + + /** - * The structure has been introduced to be able to read the - * current time with higher resolution of fractions of seconds and - * more detailed information on the time zone and status. - * The structure is returned if the new command #PCPS_GIVE_HR_TIME - * is written to the board. - * _pcps_has_hr_time() checks whether supported. - * - * Newer GPS boards also accept the #PCPS_GIVE_UCAP_EVENT command - * to return user capture event times using this format. In this - * case, the "signal" field contains the number of the capture - * input line, e.g. 0 or 1. - * _pcps_has_ucap() checks whether supported. + * @brief Definitions used to report a signal strength + * + * @anchor PCPS_SIG_VAL_DEFS @{ */ + +/** + * @brief A data type used to report the signal value + */ +typedef uint8_t PCPS_SIG_VAL; + +// The following constants are used to draw a signal bar +// depending on a DCF77 clock's signal value: +#define PCPS_SIG_BIAS 55 +#define PCPS_SIG_ERR 1 +#define PCPS_SIG_MIN 20 +#define PCPS_SIG_MAX 68 + +// These constants are used by non-DCF77 devices to indicate +// if an input signal is available or not: +#define PCPS_SIG_LVL_SIG_NOT_AVAIL 0 +#define PCPS_SIG_LVL_SIG_AVAIL 128 + +/** @} anchor PCPS_SIG_VAL_DEFS */ + + + +/** + * @brief High resolution time including status and local time offset + * + * Used to read time with high resolution of fractions of seconds and + * more detailed information on the local time offset and status. + * Should be prefered over ::PCPS_TIME. + * + * ::_pcps_has_hr_time checks whether the command ::PCPS_GIVE_TIME is + * supported to read a device's current time using this format. + * + * Newer devices providing time capture input may also accept the + * ::PCPS_GIVE_UCAP_EVENT command to read user capture event times + * using this format. In this case, the "signal" field contains + * the number of the capture input line, e.g. 0 or 1. + * ::_pcps_has_ucap checks whether this is supported. */ typedef struct { - PCPS_TIME_STAMP tstamp; /**< High resolution time stamp (UTC) */ - int32_t utc_offs; /**< UTC offs [sec] (loc_time = UTC + utc_offs) */ - PCPS_TIME_STATUS_X status; /**< status flags as defined below */ - uint8_t signal; /**< for normal time, the relative RF signal level, for ucap, the channel number */ + PCPS_TIME_STAMP tstamp; ///< High resolution time stamp (%UTC) + int32_t utc_offs; ///< %UTC offs [sec] (loc_time = tstamp + utc_offs) + PCPS_TIME_STATUS_X status; ///< status bits, see @ref PCPS_TIME_STATUS_FLAGS + PCPS_SIG_VAL signal; ///< signal strength, see @ref PCPS_SIG_VAL_DEFS, or capture input channel number + } PCPS_HR_TIME; #define _mbg_swab_pcps_hr_time( _p ) \ @@ -892,46 +1075,73 @@ typedef struct } +/** + * @brief Time synchronization status + * + * Used by legacy API calls. New API calls provide + * an extended status word ::PCPS_TIME_STATUS_X. + * + * @see ::PCPS_TIME_STATUS_FLAGS_COMMON + * @see ::PCPS_TIME_STATUS_X + */ typedef uint8_t PCPS_TIME_STATUS; -/** - The standard structure used to read times from the board. - The time has a resultion of 10 ms. -*/ -typedef struct PCPS_TIME_s + + +/** + * @brief Local calendar date and time, plus sync status + * + * This legacy structure is supported by all bus level devices but + * has a time resultion of 10 ms only. For more accurate time stamps + * the structures ::PCPS_HR_TIME and ::PCPS_TIME_STAMP should be + * used preferably. + * + * @see ::PCPS_HR_TIME + * @see ::PCPS_TIME_STAMP + * @see ::PCPS_STIME + */ +typedef struct { - uint8_t sec100; /**< hundredths of seconds, 0..99 */ - uint8_t sec; /**< seconds, 0..59, or 60 if leap second */ - uint8_t min; /**< minutes, 0..59 */ - uint8_t hour; /**< hours, 0..23 */ - - uint8_t mday; /**< day of month, 0..31 */ - uint8_t wday; /**< day of week, 1..7, 1 = Monday */ - uint8_t month; /**< month, 1..12 */ - uint8_t year; /**< year of the century, 0..99 */ - - PCPS_TIME_STATUS status; /**< status bits, see below */ - uint8_t signal; /**< relative signal strength, range depends on device type */ - int8_t offs_utc; /**< [hours], 0 if !_pcps_has_utc_offs() */ + uint8_t sec100; ///< hundredths of seconds, 0..99, 10 ms resolution + uint8_t sec; ///< seconds, 0..59, or 60 if leap second + uint8_t min; ///< minutes, 0..59 + uint8_t hour; ///< hours, 0..23 + + uint8_t mday; ///< day of month, 0..31 + uint8_t wday; ///< day of week, 1..7, 1 = Monday + uint8_t month; ///< month, 1..12 + uint8_t year; ///< year of the century, 0..99 + + PCPS_TIME_STATUS status; ///< status bits, see ::PCPS_TIME_STATUS_FLAGS_COMMON + PCPS_SIG_VAL signal; ///< signal strength, see @ref PCPS_SIG_VAL_DEFS + int8_t offs_utc; ///< [hours], 0 if not ::_pcps_has_utc_offs + } PCPS_TIME; -/** - The structure is passed as parameter with the PCPS_SET_TIME cmd -*/ -typedef struct PCPS_STIME_s + +/** + * @brief Date time and status used with the ::PCPS_SET_TIME command + * + * Similar to ::PCPS_TIME, but missing the ::PCPS_TIME::signal + * and ::PCPS_TIME::offs_utc fields. + * + * @see ::PCPS_TIME + */ +typedef struct { - uint8_t sec100; /**< hundredths of seconds, 0..99 */ - uint8_t sec; /**< seconds, 0..59, or 60 if leap second */ - uint8_t min; /**< minutes, 0..59 */ - uint8_t hour; /**< hours, 0..23 */ + uint8_t sec100; ///< hundredths of seconds, 0..99, 10 ms resolution + uint8_t sec; ///< seconds, 0..59, or 60 if leap second + uint8_t min; ///< minutes, 0..59 + uint8_t hour; ///< hours, 0..23 + + uint8_t mday; ///< day of month, 0..31 + uint8_t wday; ///< day of week, 1..7, 1 = Monday + uint8_t month; ///< month, 1..12 + uint8_t year; ///< year of the century, 0..99 - uint8_t mday; /**< day of month, 0..31 */ - uint8_t wday; /**< day of week, 1..7, 1 = Monday */ - uint8_t month; /**< month, 1..12 */ - uint8_t year; /**< year of the century, 0..99 */ + PCPS_TIME_STATUS status; ///< status bits, see ::PCPS_TIME_STATUS_FLAGS_COMMON - PCPS_TIME_STATUS status; /**< status bits, see below */ } PCPS_STIME; #ifdef _C166 @@ -950,32 +1160,35 @@ typedef union { PCPS_TIME t; PCPS_STIME stime; + } PCPS_TIME_UNION; /** - The structure below can be used to read the raw IRIG time - from an IRIG receiver card, if the card supports this. - See the #PCPS_GIVE_IRIG_TIME command. - - The granularity of the value in the .frac field depends on - the update interval of the structure as implementation - in the firmware. I.e. if the raw IRIG time is updated - only once per second, the .frac value can always be 0. -*/ -typedef struct PCPS_IRIG_TIME_s + * @brief Raw IRIG time + * + * Used to read the raw IRIG time from an IRIG receiver card, if the card + * supports this. See the ::PCPS_GIVE_IRIG_TIME command. + * + * The granularity of the value in the ::PCPS_IRIG_TIME::frac field + * depends on the update interval at which the structure is updated + * by the firmeware. I.e., if the raw IRIG time is updated only + * once per second, the ::PCPS_IRIG_TIME::frac value can always be 0. + */ +typedef struct { - PCPS_TIME_STATUS_X status; /**< status bits, see below */ - int16_t offs_utc; /**< [minutes] */ - uint16_t yday; /**< day of year, 1..365/366 */ - uint16_t frac; /**< fractions of seconds, 0.1 ms units */ - uint8_t sec; /**< seconds, 0..59, or 60 if leap second */ - uint8_t min; /**< minutes, 0..59 */ - uint8_t hour; /**< hours, 0..23 */ - uint8_t year; /**< 2 digit year number, 0xFF if year not supp. by the IRIG code */ - uint8_t signal; /**< relative signal strength, range depends on device type */ - uint8_t reserved; /**< currently not used, always 0 */ + PCPS_TIME_STATUS_X status; ///< status bits, see @ref PCPS_TIME_STATUS_FLAGS + int16_t offs_utc; ///< [minutes], 0 unless supported by the code format, see ::ICODE_RX_CODES and @ref group_icode + uint16_t yday; ///< day of year, 1..365/366 + uint16_t frac; ///< fractions of seconds, 0.1 ms units + uint8_t sec; ///< seconds, 0..59, or 60 if leap second + uint8_t min; ///< minutes, 0..59 + uint8_t hour; ///< hours, 0..23 + uint8_t year; ///< 2 digit year number, 0xFF if year not supp. by the time code, see ::ICODE_RX_CODES and @ref group_icode + PCPS_SIG_VAL signal; ///< signal strength, see @ref PCPS_SIG_VAL_DEFS + uint8_t reserved; ///< currently not used, always 0 + } PCPS_IRIG_TIME; #define _mbg_swab_pcps_irig_time( _p ) \ @@ -988,81 +1201,120 @@ typedef struct PCPS_IRIG_TIME_s +/** + * @brief Time status flags + * + * @anchor PCPS_TIME_STATUS_FLAGS @{ */ -/* Bit masks used with both PCPS_TIME_STATUS and PCPS_TIME_STATUS_X */ - -#define PCPS_FREER 0x01 /**< DCF77 clock running on xtal */ - /**< GPS receiver has not verified its position */ - -#define PCPS_DL_ENB 0x02 /**< daylight saving enabled */ - -#define PCPS_SYNCD 0x04 /**< clock has sync'ed at least once after pwr up */ +/** + * @brief Legacy time status flags + * + * Bit masks used with both ::PCPS_TIME_STATUS and ::PCPS_TIME_STATUS_X + */ +enum PCPS_TIME_STATUS_FLAGS_COMMON +{ + PCPS_FREER = 0x01, ///< long wave or time code receiver running on xtal, satellite receiver has not verified its position + PCPS_DL_ENB = 0x02, ///< daylight saving currently enabled + PCPS_SYNCD = 0x04, ///< long wave or time code receiver has sync'ed at least once after pwr up, sat receiver is synchronized + PCPS_DL_ANN = 0x08, ///< a change in daylight saving status is announced + PCPS_UTC = 0x10, ///< returned time is always %UTC instead of some local time + PCPS_LS_ANN = 0x20, ///< leap second announced, for *very* old clocks see ::REV_PCPS_LS_ANN_PC31PS31 + PCPS_IFTM = 0x40, ///< the current time has been set by an API call, for *very* old clocks see ::REV_PCPS_IFTM_PC31PS31 + PCPS_INVT = 0x80 ///< invalid time because battery had been disconnected, or absolute time can't be decoded safely +}; -#define PCPS_DL_ANN 0x08 /**< a change in daylight saving is announced */ -#define PCPS_UTC 0x10 /**< a special UTC firmware is installed */ +/** + * @brief Extended time status flags + * + * Bit masks used with ::PCPS_TIME_STATUS_X only + */ +enum PCPS_TIME_STATUS_FLAGS_EXT +{ + PCPS_LS_ENB = 0x0100, ///< current second is leap second + PCPS_ANT_FAIL = 0x0200, ///< antenna failure + PCPS_LS_ANN_NEG = 0x0400, ///< announced leap second is negative + PCPS_SCALE_GPS = 0x0800, ///< time stamp is GPS scale + PCPS_SCALE_TAI = 0x1000, ///< time stamp is TAI scale + + PCPS_UCAP_OVERRUN = 0x2000, ///< events interval too short (capture events only) + PCPS_UCAP_BUFFER_FULL = 0x4000, ///< events read too slow (capture events only) + + /** + * Bit masks used only with time stamps representing the current board time. + * A DCF77 PZF receiver can set this bit if it is actually synchronized + * using PZF correlation and thus provides higher accuracy than AM receivers. + * Same numeric code as ::PCPS_UCAP_OVERRUN + */ + PCPS_SYNC_PZF = 0x2000, + + /** + * Immediately after a clock has been accessed, subsequent accesses + * may be blocked for up to 1.5 msec to give the clock's microprocessor + * some time to decode the incoming time signal. + * The flag below is eventually set if a program tries to read ::PCPS_HR_TIME + * during this interval. In this case the read function returns the + * proper time stamp which is taken if the command byte is written, + * however, the read function returns with delay. + * This flag is not supported by all clocks. + */ + PCPS_IO_BLOCKED = 0x8000 +}; -#define PCPS_LS_ANN 0x20 /**< leap second announced */ - /**< (requires firmware rev. REV_PCPS_LS_ANN_...) */ -#define PCPS_IFTM 0x40 /**< the current time was set via PC */ - /**< (requires firmware rev. REV_PCPS_IFTM_...) */ -#define PCPS_INVT 0x80 /**< invalid time because battery was disconn'd */ +/** + * This bit mask can be used to extract the time scale information out + * of a PCPS_TIME_STATUS_X value. + */ +#define PCPS_SCALE_MASK ( PCPS_SCALE_TAI | PCPS_SCALE_GPS ) -/* Bit masks used only with PCPS_TIME_STATUS_X */ +/** @} anchor PCPS_TIME_STATUS_FLAGS */ -#define PCPS_LS_ENB 0x0100 /**< current second is leap second */ -#define PCPS_ANT_FAIL 0x0200 /**< antenna failure */ -#define PCPS_LS_ANN_NEG 0x0400 /**< announced leap second is negative */ -#define PCPS_SCALE_GPS 0x0800 /**< time stamp is GPS scale */ -#define PCPS_SCALE_TAI 0x1000 /**< time stamp is TAI scale */ -/* The next two bits are used only if the structure */ -/* PCPS_HR_TIME contains a user capture event */ -#define PCPS_UCAP_OVERRUN 0x2000 /**< events interval too short */ -#define PCPS_UCAP_BUFFER_FULL 0x4000 /**< events read too slow */ /** - * Immediately after a clock has been accessed, subsequent accesses - * are blocked for up to 1.5 msec to give the clock's microprocessor - * some time to decode the incoming time signal. - * The flag below is set if a program tries to read the PCPS_HR_TIME - * during this interval. In this case the read function returns the - * proper time stamp which is taken if the command byte is written, - * however, the read function returns with delay. - * This flag is not supported by all clocks. - */ -#define PCPS_IO_BLOCKED 0x8000 - -/** - This bit mask can be used to extract the time scale information out - of a PCPS_TIME_STATUS_X value. -*/ -#define PCPS_SCALE_MASK ( PCPS_SCALE_TAI | PCPS_SCALE_GPS ) - + * @brief Legacy definitions used to configure a device's serial port + * + * @deprecated This structure and the associated command codes + * are deprecated. ::PORT_SETTINGS, ::PORT_INFO and associated + * definitions should be used instead, if supported. + * + * @anchor PCPS_OLD_SERIAL_CFG @{ */ /** - * Some DCF77 clocks have a serial interface that can be controlled - * using the commands PCPS_SET_SERIAL and PCPS_GET_SERIAL. Both commands - * use a parameter byte describing transmission speed, framing and mode - * of operation. The parameter byte can be build using the constants - * defined below, by or'ing one of the constants of each group, shifted - * to the right position. PCPS_GET_SERIAL expects that parameter byte - * and PCPS_GET_SERIAL returns the current configuration from the board. + * @brief Configuration information for a device's serial port + * + * Used with ::PCPS_GET_SERIAL and ::PCPS_SET_SERIAL + * + * The serial interface on some old DCF77 clocks can be configured + * using the commands ::PCPS_SET_SERIAL and ::PCPS_GET_SERIAL. + * Both commands use a parameter byte describing transmission speed, + * framing and mode of operation. The parameter byte can be assembled + * using the constants defined in ::PCPS_BD_CODES, ::PCPS_FR_CODES, + * and ::PCPS_MOD_CODES, by or'ing one of the constants of each group, + * shifted to the right position. ::PCPS_GET_SERIAL expects that parameter + * byte and ::PCPS_GET_SERIAL returns the current configuration from + * the board. * _pcps_has_serial() checks whether supported. - * For GPS clocks, please refer to the comments for the PCPS_GET_SERIAL + * For old GPS clocks refer to the comments for the ::PCPS_GET_SERIAL * command. */ +typedef uint8_t PCPS_SERIAL; + /** - * Baud rate indices. The values below are obsolete and should - * be replaced by the codes named MBG_BAUD_RATE_... which are - * defined in gpsdefs.h. The resulting index numbers, however, - * have not changed. + * @brief Deprecated baud rate indices + * + * @deprecated These values are deprecated. + * ::MBG_BAUD_RATE_CODES and associated structures + * should be used preferably. + * + * The sequence of codes matches the sequence + * defined in ::MBG_BAUD_RATE_CODES. */ -enum +enum PCPS_BD_CODES { PCPS_BD_300, PCPS_BD_600, @@ -1071,202 +1323,428 @@ enum PCPS_BD_4800, PCPS_BD_9600, PCPS_BD_19200, - N_PCPS_BD /* number of codes */ + N_PCPS_BD ///< number of codes }; -#define PCPS_BD_BITS 4 /* field with in the cfg byte */ -#define PCPS_BD_SHIFT 0 /* num of bits to shift left */ +#define PCPS_BD_BITS 4 ///< field with in the cfg byte +#define PCPS_BD_SHIFT 0 ///< num of bits to shift left -/* - * Initializers for a table of all baud rate strings - * and values can be found in gpsdefs.h. - */ /** - * Unfortunately, the framing codes below can not simply be - * replaced by the newer MBG_FRAMING_... definitions since - * the order of indices does not match. + * @brief Deprecated framing code indices + * + * @deprecated These values are deprecated. + * ::MBG_FRAMING_CODES and associated structures + * should be used preferably. + * + * Unfortunately, these framing codes can *not* simply + * be replaced by the newer MBG_FRAMING_... definitions + * since the order of indices doesn't match. */ -enum +enum PCPS_FR_CODES { PCPS_FR_8N1, PCPS_FR_7E2, PCPS_FR_8N2, PCPS_FR_8E1, - N_PCPS_FR_DCF /* number of valid codes */ + N_PCPS_FR_DCF ///< number of valid codes }; -#define PCPS_FR_BITS 2 /* field with in the cfg byte */ -#define PCPS_FR_SHIFT PCPS_BD_BITS /* num of bits to shift left */ +#define PCPS_FR_BITS 2 ///< field with in the cfg byte +#define PCPS_FR_SHIFT PCPS_BD_BITS ///< num of bits to shift left + + -/* - * An initializer for a table of framing strings is only defined for - * the new MBG_FRAMING_... definitions. For editing the serial port - * configuration, the old codes above should be translated to the new - * codes to unify handling inside the edit functions. +/** + * @brief Deprecated codes for modes of operation + * + * @deprecated These values are deprecated. + * ::STR_MODES and associated structures + * should be used preferably. + * + * The sequence of codes matches the sequence + * defined in ::STR_MODES. */ +enum PCPS_MOD_CODES +{ + PCPS_MOD_REQ, ///< time string on request '?' only + PCPS_MOD_SEC, ///< time string once per second + PCPS_MOD_MIN, ///< time string once per minute + PCPS_MOD_RSVD, ///< reserved + N_PCPS_MOD_DCF ///< number of possible codes +}; + +#define PCPS_MOD_BITS 2 ///< field with in the cfg byte +#define PCPS_MOD_SHIFT ( PCPS_BD_BITS + PCPS_FR_BITS ) ///< num of bits to shift left -/** - Modes of operation +/** @} anchor PCPS_OLD_SERIAL_CFG */ - * Indices for modes of operation. The values below are obsolete - * and should be replaced by the codes named STR_... which are - * defined in gpsdefs.h. The resulting index numbers, however, - * have not changed. + + +/** + * @brief Type of variable to hold a TZ code + * + * This is used with the PCI interface but differs from ::TZCODE + * which is used with the binary protocol. + * + * @see ::TZCODE + * @see ::TZCODE_UNION */ -enum +typedef uint8_t PCPS_TZCODE; + + +/** + * @brief Enumeration of codes used with PCPS_TZCODE + */ +enum PCPS_TZCODES { - PCPS_MOD_REQ, /* time string on request '?' only */ - PCPS_MOD_SEC, /* time string once per second */ - PCPS_MOD_MIN, /* time string once per minute */ - PCPS_MOD_RSVD, /* reserved */ - N_PCPS_MOD_DCF /* number of possible codes */ + PCPS_TZCODE_CET_CEST, ///< default as broadcasted by DCF77 (UTC+1h/UTC+2h) + PCPS_TZCODE_CET, ///< always CET (UTC+1h), discard DST + PCPS_TZCODE_UTC, ///< always %UTC + PCPS_TZCODE_EET_EEST, ///< East European Time, CET/CEST + 1h + N_PCPS_TZCODE ///< the number of valid codes }; -#define PCPS_MOD_BITS 2 /* field with in the cfg byte */ -#define PCPS_MOD_SHIFT ( PCPS_BD_BITS + PCPS_FR_BITS ) - /* num of bits to shift left */ +/* the definitions below are for compatibily only: */ +#define PCPS_TZCODE_MEZMESZ PCPS_TZCODE_CET_CEST +#define PCPS_TZCODE_MEZ PCPS_TZCODE_CET +#define PCPS_TZCODE_OEZ PCPS_TZCODE_EET_EEST + + +/** + * @brief Daylight changeover specification + * + * Used as member field of ::PCPS_TZDL only. Most devices supporting + * conversion to local time support the ::TZDL structure instead. + * + * @see ::TZDL + */ +typedef struct +{ + uint16_t year_or_wday; ///< The full year number, or 0..6 == Sun..Sat if the ::DL_AUTO_FLAG is set + uint8_t month; ///< [1..12] + uint8_t mday; ///< [1..31] + uint8_t hour; ///< [0..23] + uint8_t min; ///< [0..59] + +} PCPS_DL_ONOFF; + +#define _mbg_swab_pcps_dl_onoff( _p ) \ +{ \ + _mbg_swab16( &(_p)->year_or_wday ); \ +} + +/** + * @brief A flag indicating if DST changeovers are to be computed automatically + * + * If ::PCPS_DL_ONOFF::year_or_wday is or'ed with the constant ::DL_AUTO_FLAG + * then start and end of daylight saving time shall be computed automatically + * for each year. In this case the remaining bits represent the day-of-week + * after the specified mday/month at which the change shall occur. + * If that flag is not set then the field contains the full four-digit year number + * and the ::PCPS_DL_ONOFF::mday and ::PCPS_DL_ONOFF::month values specify + * the exact date of that year. Most devices supporting conversion to local time + * support the ::TZDL structure instead. + * + * @see ::TZDL + * @see ::PCPS_TZDL + */ +#define DL_AUTO_FLAG 0x8000 // also defined in gpsdefs.h + /** - * The fixed-length standard time string being sent on the serial - * output is described below: - * - * \D:dd.mm.yy;T:d;U:hh.mm.ss;uvwx\ - * - * where \ and \ represent the ASCII codes 0x02 and 0x03, - * 'dd.mm.yy' is the format of the current date, 'd' is the current - * day of week (1..7, 1 == Monday ) and 'hh.mm.ss' is the format of - * the current time. The characters 'uvwx' reflect the clock's status: - * - * u clock status character: - * '#' clock has not synchronized after reset - * ' ' (space, 20h) clock has synchronized after reset - * - * v clock status character, different for DCF77 or GPS receivers: - * '*' DCF77 clock currently runs on XTAL - * GPS receiver has not checked its position - * ' ' (space, 20h): - * DCF77 clock is syncronized with transmitter - * GPS receiver has determined its position - * - * x time zone indicator: - * 'U' UTC Universal Time, Coordinated - * ' ' MEZ European Standard Time, daylight saving disabled - * 'S' MESZ European Summertime, daylight saving enabled - * - * y anouncement of discontinuity of time, enabled during last hour - * before discontinuity comes in effect: - * '!' announcement of start or end of daylight saving - * 'A' announcement of leap second insertion - * ' ' (space, 20h): nothing announced + * @brief Specification of a local time zone + * + * Most devices supporting conversion to local time support + * the ::TZDL structure instead. + * + * @see ::DL_AUTO_FLAG + * @see ::TZDL */ +typedef struct +{ + int16_t offs; ///< offset from %UTC to local time [min] (local time = %UTC + offs) + int16_t offs_dl; ///< additional offset if DST enabled [min] (DST time = local time + offs_dl) + PCPS_DL_ONOFF tm_on; ///< date/time when daylight saving starts + PCPS_DL_ONOFF tm_off; ///< date/time when daylight saving ends + +} PCPS_TZDL; + +#define _mbg_swab_pcps_tzdl( _p ) \ +{ \ + _mbg_swab16( &(_p)->offs ); \ + _mbg_swab16( &(_p)->offs_dl ); \ + _mbg_swab_pcps_dl_onoff( &(_p)->tm_on ); \ + _mbg_swab_pcps_dl_onoff( &(_p)->tm_off ); \ +} + + + +/** + * @brief Status of the time capture FIFO buffer + * + * Only supported if ::RECEIVER_INFO::n_ucaps > 0. + */ +typedef struct +{ + uint32_t used; ///< the number of saved capture events + uint32_t max; ///< capture buffer size + +} PCPS_UCAP_ENTRIES; + +#define _mbg_swab_pcps_ucap_entries( _p ) \ +{ \ + _mbg_swab32( &(_p)->used ); \ + _mbg_swab32( &(_p)->max ); \ +} + +/** + * @defgroup group_pzf_supp Definitions used with PZF receivers + * + * @{ */ /** - * Some definitions used with PZF receivers + * @brief Receiver distance from transmitter [km] */ +typedef uint16_t TR_DISTANCE; ///< Range may vary with receiver type + +#define _mbg_swab_tr_distance( _p ) \ + _mbg_swab16( _p ) -/* receiver distance from transmitter [km] */ -typedef uint16_t TR_DISTANCE; -/* correlation status info */ +/** + * @brief PZF correlation status info + */ typedef struct { - uint8_t val; /**< correlation value, or check count if status == PZF_CORR_CHECK */ - uint8_t status; /**< status codes, see below */ - char corr_dir; /**< space, '<', or '>' */ - uint8_t signal; /**< signal level, may always be 0 for devices which do not support this */ + uint8_t val; ///< correlation value, or check count if status ==:: PZF_CORR_CHECK + uint8_t status; ///< status codes, see ::PZF_CORR_STATES + char corr_dir; ///< space, '<', or '>', just for information + PCPS_SIG_VAL signal; ///< signal strength, see @ref PCPS_SIG_VAL_DEFS + } CORR_INFO; -/** Codes used with CORR_INFO::status: */ -enum +#define _mbg_swab_corr_info( _p ) \ + _nop_macro_fnc() + + +/** + * @brief Codes used with ::CORR_INFO::status + */ +enum PZF_CORR_STATES { - PZF_CORR_RAW, /**< trying raw correlation, combi receivers running in AM mode */ - PZF_CORR_CHECK, /**< raw correlation achieved, doing plausibility checks */ - PZF_CORR_FINE, /**< fine correlation achieved */ + PZF_CORR_RAW, ///< trying raw correlation, combi receivers running in AM mode + PZF_CORR_CHECK, ///< raw correlation achieved, doing plausibility checks + PZF_CORR_FINE, ///< fine correlation achieved N_PZF_CORR_STATE }; +#define PZF_CORR_STATE_NAME_RAW_ENG "Searching" +#define PZF_CORR_STATE_NAME_CHECK_ENG "Correlating" +#define PZF_CORR_STATE_NAME_FINE_ENG "Locked" + +#define PZF_CORR_STATE_NAME_RAW_GER "suchen" +#define PZF_CORR_STATE_NAME_CHECK_GER "korrelieren" +#define PZF_CORR_STATE_NAME_FINE_GER "eingerastet" + + +#define PZF_CORR_STATE_NAMES_ENG \ +{ \ + PZF_CORR_STATE_NAME_RAW_ENG, \ + PZF_CORR_STATE_NAME_CHECK_ENG, \ + PZF_CORR_STATE_NAME_FINE_ENG \ +} + + +#define PZF_CORR_STATE_NAMES_LSTR \ +{ \ + { PZF_CORR_STATE_NAME_RAW_ENG, PZF_CORR_STATE_NAME_RAW_GER }, \ + { PZF_CORR_STATE_NAME_CHECK_ENG, PZF_CORR_STATE_NAME_CHECK_GER }, \ + { PZF_CORR_STATE_NAME_FINE_ENG, PZF_CORR_STATE_NAME_FINE_GER } \ +} + +/** @} defgroup group_pzf_supp */ + + + /** - * @defgroup gps_cmds_bus GPS commands passed via the system bus + * @brief GPS Command codes passed via the system bus * - * This enumeration defines the various types of data that can be read - * from or written to Meinberg bus level devices which support this. - * Access should be done using the functions ::pcps_read_gps_data() - * and ::pcps_write_gps_data() since the size of some of the structures - * exceeds the size of the devices's I/O buffer and must therefore be - * accessed in several portions. + * Codes specifying various types of data that can be read from or + * written to Meinberg bus level devices which support this. + * Access is done using the low level functions ::pcps_read_gps + * and ::pcps_write_gps since the size of some of the structures + * exceeds the size of the device's I/O buffer and must therefore be + * accessed in several blocks. + * + * Applications should instead use the API functions declared in mbgdevio.h. * * The structures to be used are defined in gpsdefs.h. Not all structures - * are supportet, yet. Check the R/W indicators for details. + * are supported, yet. Check the r/w indicators for details. + * + * @see @ref PCPS_CMD_CODES + * @see ::PC_GPS_CMD_CODES_TABLE */ -enum -{ // R/W data type description - // system data ----------------------------------------------- - PC_GPS_TZDL = 0, // R/W TZDL time zone / daylight saving - PC_GPS_SW_REV, // R/- SW_REV software revision - PC_GPS_BVAR_STAT, // R/- BVAR_STAT status of buffered variables - PC_GPS_TIME, // R/W TTM curr. time - PC_GPS_POS_XYZ, // -/W XYZ curr. pos. in ECEF coords - PC_GPS_POS_LLA, // -/W LLA curr. pos. in geogr. coords - PC_GPS_PORT_PARM, // R/W PORT_PARM param. of the serial ports - PC_GPS_ANT_INFO, // R/- ANT_INFO time diff after ant. disconn. - PC_GPS_UCAP, // R/- TTM user capture - PC_GPS_ENABLE_FLAGS, // R/W ENABLE_FLAGS controls when to enable outp. - PC_GPS_STAT_INFO, // R/- GPS_STAT_INFO - PC_GPS_CMD, // -/W GPS_CMD commands as described below - PC_GPS_IDENT, // R/- GPS_IDENT serial number - PC_GPS_POS, // R/- POS position XYZ, LLA, and DMS - PC_GPS_ANT_CABLE_LEN, // R/W ANT_CABLE_LEN used to compensate delay - // The codes below are supported by new GPS receiver boards: - PC_GPS_RECEIVER_INFO, // R/- RECEIVER_INFO rcvr model info - PC_GPS_ALL_STR_TYPE_INFO, // R/- n*STR_TYPE_INFO_IDX all string types - PC_GPS_ALL_PORT_INFO, // R/- n*PORT_INFO_IDX all port info - PC_GPS_PORT_SETTINGS_IDX, // -/W PORT_SETTINGS_IDX port settings only - PC_GPS_ALL_POUT_INFO, // R/- n*POUT_INFO_IDX all pout info - PC_GPS_POUT_SETTINGS_IDX, // -/W POUT_SETTINGS_IDX pout settings only - PC_GPS_TIME_SCALE, // R/W MBG_TIME_SCALE_{SETTINGS|INFO}, only if PCPS_HAS_TIME_SCALE - PC_GPS_LAN_IF_INFO, // R/- LAN_IF_INFO LAN interface info, only if PCPS_HAS_LAN_INTF - PC_GPS_IP4_STATE, // R/- IP4_SETTINGS LAN interface state, only if PCPS_HAS_LAN_INTF - PC_GPS_IP4_SETTINGS, // R/W IP4_SETTINGS LAN interface configuration, only if PCPS_HAS_LAN_INTF - PC_GPS_PTP_STATE, // R/- PTP_STATE, only if PCPS_HAS_PTP - PC_GPS_PTP_CFG, // R/W PTP_CFG_{SETTINGS|INFO}, only if PCPS_HAS_PTP +enum PC_GPS_CMD_CODES +{ + // system data + PC_GPS_TZDL = 0, ///< (r/w) ::TZDL, time zone / daylight saving, only if ::GPS_MODEL_HAS_TZDL + PC_GPS_SW_REV, ///< (r/-) ::SW_REV, software revision, deprecated by ::PC_GPS_RECEIVER_INFO + PC_GPS_BVAR_STAT, ///< (r/-) ::BVAR_STAT, status of buffered variables, only if ::GPS_MODEL_HAS_BVAR_STAT + PC_GPS_TIME, ///< (r/w) ::TTM, current time, deprecated by ::PCPS_GIVE_HR_TIME + PC_GPS_POS_XYZ, ///< (-/w) ::XYZ, current position in ECEF coordinates, only if ::GPS_MODEL_HAS_POS_XYZ + PC_GPS_POS_LLA, ///< (-/w) ::LLA, current position in geographic coordinates, only if ::GPS_MODEL_HAS_POS_LLA + PC_GPS_PORT_PARM, ///< (r/w) ::PORT_PARM, param. of the serial ports, deprecated by ::PC_GPS_ALL_PORT_INFO + PC_GPS_ANT_INFO, ///< (r/-) ::ANT_INFO, time diff at sync. after antenna had been disconn., only if ::GPS_MODEL_HAS_ANT_INFO + PC_GPS_UCAP, ///< (r/-) ::TTM, user capture events, deprecated by ::PCPS_GIVE_UCAP_EVENT + PC_GPS_ENABLE_FLAGS, ///< (r/w) ::ENABLE_FLAGS, when to enable serial, pulses, and synth, only if ::GPS_MODEL_HAS_ENABLE_FLAGS + PC_GPS_STAT_INFO, ///< (r/-) ::GPS_STAT_INFO, satellite info, mode of operation, and DAC info, only if ::GPS_MODEL_HAS_STAT_INFO + PC_GPS_CMD, ///< (-/w) ::GPS_CMD, send one of the ::PC_GPS_COMMANDS + PC_GPS_IDENT, ///< (r/-) ::IDENT, serial number, deprecated by ::PC_GPS_RECEIVER_INFO + PC_GPS_POS, ///< (r/-) ::POS, position ::XYZ, ::LLA, and ::DMS combined, only if ::GPS_MODEL_HAS_POS + PC_GPS_ANT_CABLE_LEN, ///< (r/w) ::ANT_CABLE_LEN, length of antenna cable, only if ::GPS_MODEL_HAS_ANT_CABLE_LENGTH + PC_GPS_RECEIVER_INFO, ///< (r/-) ::RECEIVER_INFO, rcvr model info, only if ::PCPS_HAS_RECEIVER_INFO + PC_GPS_ALL_STR_TYPE_INFO, ///< (r/-) n * ::STR_TYPE_INFO_IDX, names and capabilities of all supp. string types, only if ::RECEIVER_INFO::n_str_type > 0 + PC_GPS_ALL_PORT_INFO, ///< (r/-) n * ::PORT_INFO_IDX, settings and capabilities of all serial ports, only if ::RECEIVER_INFO::n_com_ports > 0 + PC_GPS_PORT_SETTINGS_IDX, ///< (-/w) ::PORT_SETTINGS_IDX, settings for specified serial port, only if ::RECEIVER_INFO::n_com_ports > 0 + + PC_GPS_ALL_POUT_INFO, ///< (r/-) n * ::POUT_INFO_IDX, all programmable output info + PC_GPS_POUT_SETTINGS_IDX, ///< (-/w) ::POUT_SETTINGS_IDX, settings for one programmable output + PC_GPS_TIME_SCALE, ///< (r/w) ::MBG_TIME_SCALE_SETTINGS / ::MBG_TIME_SCALE_INFO, only if ::PCPS_HAS_TIME_SCALE + PC_GPS_LAN_IF_INFO, ///< (r/-) ::LAN_IF_INFO, LAN interface info, only if ::PCPS_HAS_LAN_INTF + PC_GPS_IP4_STATE, ///< (r/-) ::IP4_SETTINGS, LAN interface state, only if ::PCPS_HAS_LAN_INTF + PC_GPS_IP4_SETTINGS, ///< (r/w) ::IP4_SETTINGS, LAN interface configuration, only if ::PCPS_HAS_LAN_INTF + PC_GPS_PTP_STATE, ///< (r/-) ::PTP_STATE, only if ::PCPS_HAS_PTP + PC_GPS_PTP_CFG, ///< (r/w) ::PTP_CFG_SETTINGS / ::PTP_CFG_INFO, only if ::PCPS_HAS_PTP + PC_GPS_PTP_UC_MASTER_CFG_LIMITS, ///< (r/-) ::PTP_UC_MASTER_CFG_LIMITS, only if ::PTP_CFG_MSK_SUPPORT_PTP_UNICAST + PC_GPS_ALL_PTP_UC_MASTER_INFO, ///< (r/-) n * ::PTP_UC_MASTER_INFO_IDX, only if ::PTP_CFG_MSK_SUPPORT_PTP_UNICAST + PC_GPS_PTP_UC_MASTER_SETTINGS_IDX, ///< (-/w) ::PTP_UC_MASTER_SETTINGS_IDX, only if ::PTP_CFG_MSK_SUPPORT_PTP_UNICAST + PC_GPS_GPIO_CFG_LIMITS, ///< (r/-) ::MBG_GPIO_CFG_LIMITS, only if ::GPS_HAS_GPIO + PC_GPS_ALL_GPIO_INFO, ///< (r/-) n * ::MBG_GPIO_INFO_IDX, all GPIO info, only if ::GPS_HAS_GPIO + PC_GPS_GPIO_SETTINGS_IDX, ///< (-/w) ::MBG_GPIO_SETTINGS_IDX, settings for a specific port, only if ::GPS_HAS_GPIO + PC_GPS_GNSS_MODE, ///< (r/w) ::MBG_GNSS_MODE_INFO / ::MBG_GNSS_MODE_SETTINGS, only if ::PCPS_IS_GNSS + PC_GPS_ALL_GNSS_SAT_INFO, ///< (r/-) n * ::GNSS_SAT_INFO_IDX, satellite info, only if ::PCPS_IS_GNSS + PC_GPS_XMR_INSTANCES, ///< (r/-) ::XMULTI_REF_INSTANCES, only if ::GPS_HAS_XMULTI_REF and ::GPS_HAS_XMRS_MULT_INSTC + PC_GPS_XMR_SETTINGS_IDX, ///< (-/w) ::XMULTI_REF_SETTINGS_IDX, idx 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1, only if ::GPS_HAS_XMULTI_REF + PC_GPS_ALL_XMR_INFO, ///< (r/-) n * ::XMULTI_REF_INFO_IDX, where n == ::XMULTI_REF_INSTANCES::n_xmr_settings, only if ::GPS_HAS_XMULTI_REF + PC_GPS_ALL_XMR_STATUS, ///< (r/w) n * ::XMULTI_REF_STATUS_IDX, where n == ::XMULTI_REF_INSTANCES::n_xmr_settings, one structure on write, only if ::GPS_HAS_XMULTI_REF + PC_GPS_XMR_HOLDOVER_STATUS, ///< (r/-) ::XMR_HOLDOVER_STATUS, only if ::XMRIF_MSK_HOLDOVER_STATUS_SUPP + PC_GPS_ALL_GPIO_STATUS, ///< (r/-) n * ::MBG_GPIO_STATUS_IDX, where n == ::MBG_GPIO_CFG_LIMITS::num_io, only if ::MBG_GPIO_CFG_LIMIT_FLAG_MASK_STATUS_SUPP // GPS data - PC_GPS_CFGH = 0x80, // -/- CFGH SVs' config. and health codes - PC_GPS_ALM, // -/- SV_ALM one SV's num and almanac - PC_GPS_EPH, // -/- SV_EPH one SV's num and ephemeris - PC_GPS_UTC, // R/W UTC UTC corr. param., only if PCPS_HAS_UTC_PARM - PC_GPS_IONO, // -/- IONO ionospheric corr. param. - PC_GPS_ASCII_MSG // -/- ASCII_MSG the GPS ASCII message + PC_GPS_CFGH = 0x80, ///< (-/-) ::CFGH, SVs' config. and health codes (yet not used) + PC_GPS_ALM, ///< (-/-) ::SV_ALM, one SV's num and almanac (yet not used) + PC_GPS_EPH, ///< (-/-) ::SV_EPH, one SV's num and ephemeris (yet not used) + PC_GPS_UTC, ///< (r/w) ::UTC, %UTC corr. param., only if ::PCPS_HAS_UTC_PARM + PC_GPS_IONO, ///< (-/-) ::IONO, ionospheric corr. param. (yet not used) + PC_GPS_ASCII_MSG ///< (-/-) ::ASCII_MSG, the GPS ASCII message (yet not used) }; -/** codes used with PC_GPS_CMD */ -enum + +/** + * @brief An initializer for a table of code/name entries of GPS commands. + * + * This can e.g. be assigned to an array of ::MBG_CODE_NAME_TABLE_ENTRY elements + * and may be helpful when debugging. + * + * @see ::PC_GPS_CMD_CODES + */ +#define PC_GPS_CMD_CODES_TABLE \ +{ \ + _mbg_cn_table_entry( PC_GPS_TZDL ), \ + _mbg_cn_table_entry( PC_GPS_SW_REV ), \ + _mbg_cn_table_entry( PC_GPS_BVAR_STAT ), \ + _mbg_cn_table_entry( PC_GPS_TIME ), \ + _mbg_cn_table_entry( PC_GPS_POS_XYZ ), \ + _mbg_cn_table_entry( PC_GPS_POS_LLA ), \ + _mbg_cn_table_entry( PC_GPS_PORT_PARM ), \ + _mbg_cn_table_entry( PC_GPS_ANT_INFO ), \ + _mbg_cn_table_entry( PC_GPS_UCAP ), \ + _mbg_cn_table_entry( PC_GPS_ENABLE_FLAGS ), \ + _mbg_cn_table_entry( PC_GPS_STAT_INFO ), \ + _mbg_cn_table_entry( PC_GPS_CMD ), \ + _mbg_cn_table_entry( PC_GPS_IDENT ), \ + _mbg_cn_table_entry( PC_GPS_POS ), \ + _mbg_cn_table_entry( PC_GPS_ANT_CABLE_LEN ), \ + _mbg_cn_table_entry( PC_GPS_RECEIVER_INFO ), \ + _mbg_cn_table_entry( PC_GPS_ALL_STR_TYPE_INFO ), \ + _mbg_cn_table_entry( PC_GPS_ALL_PORT_INFO ), \ + _mbg_cn_table_entry( PC_GPS_PORT_SETTINGS_IDX ), \ + _mbg_cn_table_entry( PC_GPS_ALL_POUT_INFO ), \ + _mbg_cn_table_entry( PC_GPS_POUT_SETTINGS_IDX ), \ + _mbg_cn_table_entry( PC_GPS_TIME_SCALE ), \ + _mbg_cn_table_entry( PC_GPS_LAN_IF_INFO ), \ + _mbg_cn_table_entry( PC_GPS_IP4_STATE ), \ + _mbg_cn_table_entry( PC_GPS_IP4_SETTINGS ), \ + _mbg_cn_table_entry( PC_GPS_PTP_STATE ), \ + _mbg_cn_table_entry( PC_GPS_PTP_CFG ), \ + _mbg_cn_table_entry( PC_GPS_PTP_UC_MASTER_CFG_LIMITS ), \ + _mbg_cn_table_entry( PC_GPS_ALL_PTP_UC_MASTER_INFO ), \ + _mbg_cn_table_entry( PC_GPS_PTP_UC_MASTER_SETTINGS_IDX ), \ + _mbg_cn_table_entry( PC_GPS_GPIO_CFG_LIMITS ), \ + _mbg_cn_table_entry( PC_GPS_ALL_GPIO_INFO ), \ + _mbg_cn_table_entry( PC_GPS_GPIO_SETTINGS_IDX ), \ + _mbg_cn_table_entry( PC_GPS_GNSS_MODE ), \ + _mbg_cn_table_entry( PC_GPS_ALL_GNSS_SAT_INFO ), \ + _mbg_cn_table_entry( PC_GPS_XMR_INSTANCES ), \ + _mbg_cn_table_entry( PC_GPS_XMR_SETTINGS_IDX ), \ + _mbg_cn_table_entry( PC_GPS_ALL_XMR_INFO ), \ + _mbg_cn_table_entry( PC_GPS_ALL_XMR_STATUS ), \ + _mbg_cn_table_entry( PC_GPS_XMR_HOLDOVER_STATUS ), \ + _mbg_cn_table_entry( PC_GPS_ALL_GPIO_STATUS ), \ + _mbg_cn_table_entry( PC_GPS_CFGH ), \ + _mbg_cn_table_entry( PC_GPS_ALM ), \ + _mbg_cn_table_entry( PC_GPS_EPH ), \ + _mbg_cn_table_entry( PC_GPS_UTC ), \ + _mbg_cn_table_entry( PC_GPS_IONO ), \ + _mbg_cn_table_entry( PC_GPS_ASCII_MSG ), \ + _mbg_cn_table_end() \ +} + + + +/** + * @brief Codes used with ::PC_GPS_CMD + * + * @note These commands should only used with care, in very rare cases! + */ +enum PC_GPS_COMMANDS //##++++++++++++++ { - PC_GPS_CMD_BOOT = 1, /**< force the clock to boot mode */ - PC_GPS_CMD_INIT_SYS, /**< let the clock clear its system variables */ - PC_GPS_CMD_INIT_USER, /**< reset the clock's user parameters to defaults */ - PC_GPS_CMD_INIT_DAC, /**< initialize the oscillator disciplining values */ - N_PC_GPS_CMD /**< no command, just the number of known commands */ + PC_GPS_CMD_BOOT = 1, ///< force a GPS receiver to boot mode + PC_GPS_CMD_INIT_SYS, ///< let the clock clear its system variables + PC_GPS_CMD_INIT_USER, ///< reset the clock's user parameters to defaults + PC_GPS_CMD_INIT_DAC, ///< initialize the oscillator disciplining values + N_PC_GPS_CMD_CODES ///< no command, just the number of known commands }; -// The type below can be used to store an unambiguous command code. -// In case of the standard PCPS_... commands the lower byte contains -// the command code and the upper byte is 0. -// In case of a GPS command the lower byte contains PCPS_READ_GPS_DATA -// or PCPS_WRITE_GPS_DATA, as appropriate, and the upper byte contains -// the associated PC_GPS_... type code. + + +/** + * @brief A type used to store an unambiguous command code + * + * In case of the standard @ref PCPS_CMD_CODES the lower byte contains + * the command code and the upper byte is 0. + * In case of a GPS command the lower byte contains ::PCPS_READ_GPS_DATA + * or ::PCPS_WRITE_GPS_DATA, as appropriate, and the upper byte contains + * the associated type code from ::PC_GPS_CMD_CODES. + * + * Used internally by the firmware only. + */ typedef uint16_t PCPS_CMD_INFO; -#if defined( _USE_PACK ) // set default alignment - #pragma pack() + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT #endif +#define _PCPSDEFS_H_INCLUDED + /* End of header body */ #endif /* _PCPSDEFS_H */ diff --git a/mbglib/common/use_pack.h b/mbglib/common/use_pack.h index aaacd42..5edcdfe 100644 --- a/mbglib/common/use_pack.h +++ b/mbglib/common/use_pack.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: use_pack.h 1.3 2011/01/26 10:01:41 martin REL_M $ + * $Id: use_pack.h 1.5 2012/10/12 12:40:01 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,6 +11,10 @@ * * ----------------------------------------------------------------------- * $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 diff --git a/mbglib/common/words.h b/mbglib/common/words.h index 4216e17..c298755 100644 --- a/mbglib/common/words.h +++ b/mbglib/common/words.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: words.h 1.26 2011/04/06 10:23:03 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,29 @@ * * ----------------------------------------------------------------------- * $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 + * Removed #if sizeof() definitions which may cause build errors + * with some older compilers. + * Include stdbool.h for __ARMCC_VERSION targets. + * Moved _nop_macro_fnc() definition here. + * Revision 1.30 2012/11/02 09:12:29Z martin + * Moved most feature detection code to mbg_tgt.h. + * Tried to define missing features most flexibly and portably. + * Revision 1.29 2012/07/11 16:45:45Z martin + * New macros to access individual bytes of long constants. + * Revision 1.28 2012/04/05 14:36:18Z martin + * Support CVI 2010 compiler which provides C99 types. + * Revision 1.27 2011/07/18 10:21:38Z martin + * Added definition for MBG_CODE_NAME_TABLE_ENTRY which can + * be used to define tables assigning strings to numeric codes. * Revision 1.26 2011/04/06 10:23:03 martin * Added FBYTE_OF() and FWORD_OF() macros. * Modifications required for *BSD. @@ -82,23 +105,33 @@ #if !defined( _IS_MBG_FIRMWARE ) -#if defined( _C166 ) || \ - defined( _CC51 ) || \ - defined( __ARM ) || \ - defined( __ARMCC_VERSION ) - #define _IS_MBG_FIRMWARE 1 -#else - #define _IS_MBG_FIRMWARE 0 -#endif - + #if defined( _C166 ) || \ + defined( _CC51 ) || \ + defined( __ARM ) || \ + defined( __ARMCC_VERSION ) + #define _IS_MBG_FIRMWARE 1 + #else + #define _IS_MBG_FIRMWARE 0 + #endif #endif + #if !_IS_MBG_FIRMWARE #include +#else + #if defined( __ARMCC_VERSION ) // Keil RealView Compiler for ARM + #define __mbg_inline __inline + #include + #include + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #else + #define MBG_TGT_MISSING_64_BIT_TYPES 1 + #endif #endif + #ifdef _WORDS #define _ext #else @@ -108,117 +141,60 @@ /* Start of header body */ - -// The compilers below support native bit types. - -#if defined( _C166 ) || defined( _CC51 ) - #define _BIT_DEFINED 1 +#if defined( _C166 ) \ + || defined( _CC51 ) + #define _BIT_DEFINED 1 // these compilers natively support the "bit" type + #define USE_LONG_FOR_INT32 1 #endif -// Check whether the target system supports C99 fixed-size types. - -#if defined( MBG_TGT_LINUX ) // any Linux target - - #if defined( __KERNEL__ ) - #include - #else - #include - #include - #endif - - #define _C99_BIT_TYPES_DEFINED 1 - -#elif defined( MBG_TGT_BSD ) +#if !defined( MBG_TGT_HAS_EXACT_SIZE_TYPES ) - #include + #if defined( MBG_TGT_HAS_INT_8_16_32 ) - #define _C99_BIT_TYPES_DEFINED 1 + // Define C99 exact size types using non-standard exact-size types + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; - // avoid inclusion of stdbool.h later - #define bit int - #define _BIT_DEFINED 1 - -#elif defined( MBG_TGT_QNX ) // QNX 4.x or QNX 6.x - - #if defined( MBG_TGT_QNX_NTO ) // QNX 6.x (Neutrino) with gcc - #include - #else // QNX 4.x with Watcom C 10.6 - #include // 64 bit types not supported - #endif - - #define _C99_BIT_TYPES_DEFINED 1 - -#endif + typedef __int16 int16_t; + typedef unsigned __int16 uint16_t; + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; + #else -// If it's not yet clear whether fixed-size types are supported, -// check the build environment which may be multi-platform. + // Assume a 16 or 32 bit compiler which doesn't + // support exact-size types. -#if !defined( _C99_BIT_TYPES_DEFINED ) + typedef char int8_t; + typedef unsigned char uint8_t; - #if defined( __WATCOMC__ ) - #if __WATCOMC__ > 1230 // Open Watcom C 1.3 and above - #include - #define _C99_BIT_TYPES_DEFINED 1 - #elif defined( __WATCOM_INT64__ ) // Watcom C 11, non-QNX - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; + typedef short int16_t; + typedef unsigned short uint16_t; - #define _C99_BIT_TYPES_DEFINED 1 - #endif - #endif + // Using #if sizeof() to determine the size of a type may not + // be supported by all preprocessors, and may even result in + // build errors if used in a conditional preprocessor section, + // so we can't use this here without compatibility problems. - #if defined( __BORLANDC__ ) - #if ( __BORLANDC__ >= 0x570 ) // at least Borland Developer Studio 2006 - #define _C99_BIT_TYPES_DEFINED 1 + #if defined( USE_LONG_FOR_INT32 ) + typedef long int32_t; + typedef unsigned long uint32_t; + #elif defined( USE_INT_FOR_INT32 ) + typedef int int32_t; + typedef unsigned int uint32_t; + #else + #error Need to define int32_t and uint32_t #endif - #endif - - #if defined( __GNUC__ ) - #include - #define _C99_BIT_TYPES_DEFINED 1 - #endif - #if defined( __ARMCC_VERSION ) // Keil RealView Compiler for ARM - #include - #define _C99_BIT_TYPES_DEFINED 1 #endif -#endif - - -// If neither the target system nor the build environment define C99 fixed-size -// types define those types based on standard types with the proper sizes -// commonly used in 16/32 bit environments. - -#if defined( _C99_BIT_TYPES_DEFINED ) - - #define MBG_TGT_HAS_64BIT_TYPES 1 - -#else - - typedef char int8_t; - typedef unsigned char uint8_t; - - typedef short int16_t; - typedef unsigned short uint16_t; - - typedef long int32_t; - typedef unsigned long uint32_t; + #if defined( MBG_TGT_MISSING_64_BIT_TYPES ) - - #if defined( MBG_TGT_WIN32 ) - - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; - - #define MBG_TGT_HAS_64BIT_TYPES 1 - - #else - // The types below are required to avoid build errors + // The build environment does not support 64 bit types. However, + // 64 bit types need to be defined to avoid build errors // if these types are formally used in function prototypes. // We explicitely use abnormal data types to hopefully // cause compiler errors in case these types are @@ -226,45 +202,102 @@ // platform which does not support 64 bit types. typedef void *int64_t; typedef void *uint64_t; + + #else + + // Define C99 types using non-standard exact-size types + // which are usually supported by build envonronments + // supporting 64 bit types but no C99 types. + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + #endif #endif -#if !defined( MBG_TGT_HAS_64BIT_TYPES ) +#if defined( MBG_TGT_MISSING_64_BIT_TYPES ) #define MBG_TGT_HAS_64BIT_TYPES 0 +#else + + #define MBG_TGT_HAS_64BIT_TYPES 1 + #endif // Some commonly used types -typedef unsigned char uchar; +#if !defined( _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 + +#if !defined( _WORD_DEFINED ) + typedef unsigned short word; + #define word word #endif -typedef double udouble; +#if !defined( _LONGWORD_DEFINED ) + typedef unsigned long longword; + #define longword longword +#endif + +#if !defined( _DWORD_DEFINED ) +// typedef unsigned long dword; +// #define dword dword +#endif -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned long longword; -typedef unsigned long dword; #if !defined( _BIT_DEFINED ) - #if _C99_BIT_TYPES_DEFINED - #include + // We need to implement a "bit" type. Preferably we use "bool" + // to do this, but this is only supported by C++ compilers, and + // by C compilers supporting the C99 standard. + + #if !defined( MBG_TGT_MISSING_BOOL_TYPE ) && \ + ( defined( __cplusplus ) || defined( __bool_true_false_are_defined ) ) typedef bool bit; - #else + #define bit bit + + #else // C99 types not supported + + // Falling back to use "int" for "bit". This prevents error + // messages if "bit" is used in function prototypes, but may + // yield unexpected results for code like: + // return (bit) ( val & 0x10 ); typedef int bit; + #define bit bit + #endif #define _BIT_REDEFINED 1 @@ -272,11 +305,17 @@ typedef unsigned long dword; #endif -#define HI_BYTE( _x ) ( (_x) >> 8 ) -#define LO_BYTE( _x ) ( (_x) & 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_WORD( _x ) ( (_x) >> 16 ) -#define LO_WORD( _x ) ( (_x) & 0xFFFF ) + +#define HI_BYTE( _x ) ( (uint8_t ) ( (_x) >> 8 ) ) +#define LO_BYTE( _x ) ( (uint8_t ) ( (_x) & 0xFF ) ) + +#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 @@ -332,6 +371,45 @@ typedef unsigned long dword; #define _hilo_32( _x ) (_x) #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 +// release builds, etc. +#if !defined( _nop_macro_fnc ) + #define _nop_macro_fnc() do {} while (0) +#endif + + +/** + * @brief A table entry which can be used to map codes to names. + */ +typedef struct +{ + ulong code; + const char *name; +} MBG_CODE_NAME_TABLE_ENTRY; + +/** + * @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 */ #undef _ext diff --git a/unix/Makefile b/unix/Makefile index 0e27cc1..ffe9d6c 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -1,7 +1,7 @@ ######################################################################### # -# $Id: Makefile 1.4 2011/04/18 08:08:41 martin REL_M $ +# $Id: Makefile 1.7 2014/10/30 13:50:04 martin TRASH $ # # Description: # Makefile for gpsxmple for Unix-like systems. @@ -9,6 +9,12 @@ # # ----------------------------------------------------------------------- # $Log: Makefile $ +# Revision 1.7 2014/10/30 13:50:04 martin +# Added module mbgerror.o. +# Revision 1.6 2013/02/01 16:11:27 martin +# Added extiohlp module to the list of object files. +# Revision 1.5 2011/08/19 07:26:40 martin +# Modified the way to define targets etc. # Revision 1.4 2011/04/18 08:08:41 martin # Modified DEBUG handling. # Revision 1.3 2009/10/01 14:09:19 martin @@ -28,8 +34,19 @@ TARGET = gpsxmple MBGLIB = ../mbglib -MBGLIB_COMMON=$(MBGLIB)/common -LOC_INCL = -I. -I $(MBGLIB_COMMON) +MBGLIB_DIRS += common + +VPATH += .. +VPATH += $(foreach dir,$(MBGLIB_DIRS),$(MBGLIB)/$(dir)) + +OBJS = $(TARGET).o +OBJS += extiohlp.o +OBJS += mbgextio.o +OBJS += mbgserio.o +OBJS += gpsserio.o +OBJS += gpsutils.o +OBJS += aes128.o +OBJS += mbgerror.o # Try to determine whether the OS is QNX @@ -38,7 +55,7 @@ OS_IS_QNX := $(shell uname | grep -i QNX && echo "QNX" ) # set up the compiler flags -CFLAGS = -Wall +CFLAGS += -Wall ifdef DEBUG # build with debugging enabled @@ -48,12 +65,14 @@ else CFLAGS += -O2 endif -CFLAGS += $(LOC_INCL) CFLAGS += -D_USE_SOCKET_IO=1 +CFLAGS += -I. +CFLAGS += $(foreach dir,$(MBGLIB_DIRS),-I$(MBGLIB)/$(dir)) + ifneq ($(OS_IS_QNX),) # for QNX we must link the socket library explicitely - CFLAGS += -lsocket + LDFLAGS += -lsocket # we don't yet support serial I/O under QNX CFLAGS += -D_USE_SERIAL_IO=0 else @@ -61,19 +80,13 @@ else endif -SRCS=../$(TARGET).c \ - $(MBGLIB_COMMON)/mbgextio.c \ - $(MBGLIB_COMMON)/mbgserio.c \ - $(MBGLIB_COMMON)/gpsserio.c \ - $(MBGLIB_COMMON)/gpsutils.c \ - $(MBGLIB_COMMON)/aes128.c - +LD = $(CC) .PHONY: all all: $(TARGET) -$(TARGET): $(SRCS) $(MAKEFILE_LIST) - $(CC) $(CFLAGS) $(SRCS) -o $@ +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) .PHONY: clean -- cgit v1.2.3