diff options
author | Martin Burnicki <martin.burnicki@meinberg.de> | 2011-04-18 12:00:00 +0200 |
---|---|---|
committer | Martin Burnicki <martin.burnicki@meinberg.de> | 2011-04-18 12:00:00 +0200 |
commit | f8f66e249cd7246b3f7d864748e8a49dbda105d7 (patch) | |
tree | 45946e5a40924f6050d70720dc0b328d121fc0ef | |
parent | 65232611c8d9151691909912345435f05ad28e77 (diff) | |
download | gpsxmple-2.3-dos-win.tar.gz gpsxmple-2.3-dos-win.zip |
Feature updatesgpsxmple-2.3-dos-win
Optionally poll for user capture events.
Update library functions, e.g. mbgextio_get_ucap() has been
modified to account for different device behaviour.
-rwxr-xr-x | dos/gpsxmple.exe | bin | 68080 -> 68752 bytes | |||
-rw-r--r--[-rwxr-xr-x] | dos/gpsxmple.prj | bin | 8433 -> 8433 bytes | |||
-rw-r--r-- | gpsxmple.c | 168 | ||||
-rw-r--r-- | mbglib/common/gpsdefs.h | 912 | ||||
-rw-r--r-- | mbglib/common/gpsserio.h | 222 | ||||
-rw-r--r-- | mbglib/common/mbg_tgt.h | 1 | ||||
-rw-r--r-- | mbglib/common/mbg_tmo.c | 64 | ||||
-rw-r--r-- | mbglib/common/mbg_tmo.h | 317 | ||||
-rw-r--r-- | mbglib/common/mbgextio.c | 52 | ||||
-rw-r--r-- | mbglib/common/mbgextio.h | 14 | ||||
-rw-r--r-- | mbglib/common/mbgmutex.h | 239 | ||||
-rw-r--r-- | mbglib/common/mbgserio.c | 960 | ||||
-rw-r--r-- | mbglib/common/mbgserio.h | 213 | ||||
-rw-r--r-- | mbglib/common/pcpsdefs.h | 1273 | ||||
-rw-r--r-- | mbglib/common/use_pack.h | 18 | ||||
-rw-r--r-- | mbglib/common/words.h | 61 | ||||
-rw-r--r--[-rwxr-xr-x] | windows/gpsxmple.dsp | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | windows/gpsxmple.dsw | 0 |
18 files changed, 4143 insertions, 371 deletions
diff --git a/dos/gpsxmple.exe b/dos/gpsxmple.exe Binary files differindex adaeb77..ac3dcc9 100755 --- a/dos/gpsxmple.exe +++ b/dos/gpsxmple.exe diff --git a/dos/gpsxmple.prj b/dos/gpsxmple.prj Binary files differindex f349f0a..f349f0a 100755..100644 --- a/dos/gpsxmple.prj +++ b/dos/gpsxmple.prj @@ -1,14 +1,14 @@ /************************************************************************** * - * $Id: gpsxmple.c 1.7 2009/10/02 14:18:08Z martin REL_M $ - * $Name: GPSXMPLE_2_2 $ + * $Id: gpsxmple.c 1.8 2011/04/15 13:04:14Z martin REL_M $ + * $Name: GPSXMPLE_2_3 $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: - * Sample program demonstrating how to access Meinberg GPS receivers - * via the binary data protocol. + * Sample program demonstrating how to access Meinberg devices + * using the binary data protocol. * * Depending on the target operating system this program works * either via serial port (the default) or via a network socket @@ -24,14 +24,17 @@ * QNX 6.x / gcc (socket only) * DOS / BC3.1 (serial only) * - * For makefiles and build environment setups check the associated - * subdirectories. + * For makefiles and build environment setups check the + * corresponding subdirectories. * - * Please send changes required for other operating systems + * Please send changes required for other operating systems * or build to <support@meinberg.de> * * ----------------------------------------------------------------------- * $Log: gpsxmple.c $ + * Revision 1.8 2011/04/15 13:04:14Z martin + * Optionally poll for user capture events. + * Under Unix catch signals to terminate properly. * Revision 1.7 2009/10/02 14:18:08Z martin * Changes due to renamed library functions. * Optionally force connection. @@ -67,10 +70,15 @@ #include <string.h> #include <ctype.h> +#if defined( MBG_TGT_UNIX ) + #include <signal.h> +#endif + #if defined( MBG_TGT_DOS ) #include <conio.h> + #define done kbhit() #else - #define kbhit() 0 + static int done; #endif @@ -96,6 +104,7 @@ MBG_MSG_CTL mctl = #define N_STR_TYPE_MAX 20 // max. number of string types #define N_POUT_MAX 3 // max. number of programmable outputs +#define IDLE_SLEEP_MS 200 #define _log_msg_0( _lvl, _fmt ) \ @@ -116,6 +125,7 @@ static const char *target; static int is_socket; static int must_force_connection; static int must_send_auto; +static int must_poll_ucap; static RECEIVER_INFO receiver_info; static const char *feature_names[] = DEFAULT_GPS_FEATURE_NAMES; @@ -146,10 +156,28 @@ static const char *dow_str[] = static /*HDR*/ +void mbg_sleep_msec( long msec ) +{ + #if defined( MBG_TGT_UNIX ) + usleep( msec * 1000 ); + #elif defined( MBG_TGT_WIN32 ) + Sleep( msec ); + #elif defined( MBG_TGT_DOS ) + delay( msec ); + #endif + +} // mbg_sleep_msec + + + +static /*HDR*/ int check_rc( int rc ) { const char *cp = NULL; + if ( done ) + return 0; // we are going to exit + switch ( rc ) { case TR_COMPLETE: @@ -330,14 +358,16 @@ void check_receiver_info( RECEIVER_INFO *p, int log ) if ( p->model_code == GPS_MODEL_UNKNOWN ) { - _log_msg_0( LOG_ERR, "Refclock model_code not set: maybe receiver_info has not been received correctly" ); + _log_msg_0( LOG_ERR, "Refclock model_code not set: maybe receiver_info " + "has not been received correctly" ); } else if ( log ) { if ( p->model_code >= N_GPS_MODEL ) { - _log_msg_2( LOG_WARNING, "Unsupported refclock model_code %u (name: %s)", p->model_code, p->model_name ); + _log_msg_2( LOG_WARNING, "Unsupported refclock model_code %u (name: %s)", + p->model_code, p->model_name ); } } @@ -397,6 +427,7 @@ int get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) printf( " %02X", p->sw_rev.name[i] ); #endif } + printf( ", S/N: %s", p->sernum ); printf( "\n" ); @@ -864,12 +895,51 @@ void show_port_settings( MBG_MSG_CTL *pmctl ) /*HDR*/ static -void exit_gpsxmple( void ) +int check_ucap_poll( void ) +{ + int rc; + + + printf( "Polling for user capture events:\n" ); + + do + { + TTM ttm; + memset( &ttm, 0, sizeof( ttm ) ); + rc = mbgextio_get_ucap( &mctl, &ttm ); + + if ( _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, + ttm.tm.hour,ttm.tm.min, ttm.tm.sec, ttm.tm.frac ); + printf( ", Status: %04X (hex)", ttm.tm.status ); + printf( "\n" ); + } + else + { + // No capture event available. We wait some time + // and then retry. + mbg_sleep_msec( IDLE_SLEEP_MS ); + } + + } while ( !done ); + + return 0; + +} // check_ucap_poll + + + +/*HDR*/ static +void exit_close_connection( void ) { mbgextio_close_connection( &mctl ); - printf( "\n\n" ); -} /* exit_gpsxmple */ + printf( "Connection closed.\n" ); + printf( "\n" ); + +} /* exit_close_connection */ @@ -878,11 +948,47 @@ void exit_auto_off( void ) { mbgextio_xmt_cmd( &mctl, GPS_AUTO_OFF ); + #if defined( DEBUG ) + printf( "AUTO mode turned off.\n" ); + #endif + } /* exit_auto_off */ -// Do a very simple processing of command line parameters: +/*HDR*/ static +void set_auto_mode( void ) +{ + mbgextio_xmt_cmd( &mctl, GPS_AUTO_ON ); + + #if defined( DEBUG ) + printf( "AUTO mode turned on.\n" ); + #endif + + atexit( exit_auto_off ); + +} // set_auto_mode + + + +#if defined( MBG_TGT_UNIX ) + +static /*HDR*/ +void sighandler( int sig ) +{ + #if defined( DEBUG ) + printf( "Caught signal %i, exiting.\n", sig ); + #endif + + done = 1; + +} // sighandler + +#endif + + + +// Do a very simple processing of command line parameters: static /*HDR*/ int check_command_line( int argc, char *argv[] ) @@ -898,6 +1004,12 @@ int check_command_line( int argc, char *argv[] ) continue; } + if ( strcmp( argv[i], "-u" ) == 0 ) + { + must_poll_ucap = 1; + continue; + } + if ( strcmp( argv[i], "-?" ) == 0 ) { must_print_usage = 1; @@ -989,14 +1101,16 @@ int check_command_line( int argc, char *argv[] ) "\n" "Options\n" " -? or -h Print this usage\n" + " -a Set auto mode\n" + " -u Poll user capture events\n" #if _USE_SOCKET_IO " -n Connect to network target, not serial port\n" " -p passwd Use specified password to connect\n" #endif #if _USE_SERIAL_IO - " -b speed serial port baud rate, default: %lu\n" - " -f xxx serial port framing, default: %s\n" - " -F force serial connection to %lu/%s\n" + " -b speed Serial port baud rate, default: %lu\n" + " -f xxx Serial port framing, default: %s\n" + " -F Force serial connection to %lu/%s\n" #endif "\n" "Example:\n" @@ -1034,10 +1148,9 @@ int check_command_line( int argc, char *argv[] ) int main( int argc, char *argv[] ) { - int str_mode_0; int rc; - printf( "\n\n\nExample Program Accessing Meinberg GPS Receiver\n" ); + printf( "\n\n\nExample Program Accessing a Meinberg Device via Binary Protocol\n" ); baudrate = default_baudrate; framing = default_framing; @@ -1045,6 +1158,10 @@ int main( int argc, char *argv[] ) if ( check_command_line( argc, argv ) < 0 ) return 1; + #if defined( MBG_TGT_UNIX ) + signal( SIGTERM, sighandler ); + signal( SIGINT, sighandler ); + #endif #if _USE_SOCKET_IO if ( is_socket ) @@ -1097,7 +1214,7 @@ int main( int argc, char *argv[] ) doit: - atexit( exit_gpsxmple ); + atexit( exit_close_connection ); // now start communication with whichever device has been opened above: @@ -1111,14 +1228,13 @@ doit: show_pos( &mctl ); show_tzdl( &mctl ); show_port_settings( &mctl ); - str_mode_0 = mctl.rcv.pmb->u.msg_data.port_parm.mode[0]; show_synth( &mctl ); // set_synth(); // set_pout_mode(); - if ( str_mode_0 != STR_PER_SEC ) - return 0; // device will not send time automatically + if ( must_poll_ucap ) + return check_ucap_poll(); if ( !must_send_auto ) return 0; @@ -1132,8 +1248,7 @@ doit: mbgextio_set_char_rcv_timeout( &mctl, 2000 ); // [msec] mbgextio_set_msg_rcv_timeout( &mctl, 2000 ); // [msec] - mbgextio_xmt_cmd( &mctl, GPS_AUTO_ON ); - atexit( exit_auto_off ); + set_auto_mode(); do { @@ -1163,6 +1278,7 @@ doit: { mbgextio_xmt_cmd( &mctl, GPS_AUTO_ON ); mbgextio_xmt_cmd( &mctl, GPS_STAT_INFO ); + mbgextio_xmt_cmd( &mctl, GPS_UCAP ); } break; @@ -1172,7 +1288,7 @@ doit: } /* switch */ - } while ( !kbhit() ); + } while ( !done ); return 0; diff --git a/mbglib/common/gpsdefs.h b/mbglib/common/gpsdefs.h index 0745a54..03d867c 100644 --- a/mbglib/common/gpsdefs.h +++ b/mbglib/common/gpsdefs.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsdefs.h 1.80 2009/09/28 14:55:53Z martin REL_M $ + * $Id: gpsdefs.h 1.91 2011/01/31 11:23:56Z martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -13,7 +13,52 @@ * * ----------------------------------------------------------------------- * $Log: gpsdefs.h $ - * Revision 1.80 2009/09/28 14:55:53Z martin + * Revision 1.91 2011/01/31 11:23:56Z martin + * Added model type name definitions for GPS180PEX and TCR180PEX. + * Introduced synthesizer mode for programmable outputs. + * Added IRIG-RX code TXC-101 DTR-6. + * Fixed missing comma bugs in DEFAULT_GPS_MODEL_NAMES. + * Fixed missing comma bugs in some IRIG string initializers. + * Fixed AFNOR notation. + * Modified some comments for doxygen. + * Revision 1.90 2010/10/15 11:47:53 martin + * Added definitions POUT_TIMEBASE_UTC and POUT_SUPP_DCF77_UTC. + * Added receiver info feature GPS_FEAT_RAW_IRIG_TIME. + * Support IRIG format C37.118. + * Added initializers for short IRIG code names. + * Cleaned up IRIG definitions and comments. + * Revision 1.89 2010/09/06 07:40:02Z martin + * Picked up Daniel's definitions for multi GNSS support. + * Moved MBG_IRIG_CTRL_BITS, MBG_RAW_IRIG_DATA and related definitions + * from pcpsdefs.h here. + * Added macros _pcps_tfom_from_irig_ctrl_bits() + * and _pcps_tfom_from_raw_irig_data(). + * Added RI_FEATURES type. + * Revision 1.88 2010/04/21 13:47:54 daniel + * Added support for new model GLN170. + * Revision 1.87 2010/03/10 11:29:37Z martin + * Added definitions for GPS180. + * Added multiref source 1 PPS plus associated string. + * Revision 1.86 2010/02/17 14:16:42 martin + * Added definitions for PZF600 and TCR600. + * Revision 1.85 2010/02/15 11:34:36 martin + * Changed definition of PTP_TABLE::name to const char *. + * Added definitions to support new model JJY511. + * Revision 1.84 2010/02/01 13:20:50 martin + * Support programmable outputs being disabled when sync. is lost. + * Revision 1.83 2010/01/28 09:15:50 martin + * Added new POUT mode DCF77_M59 and associated definitions. + * Revision 1.82 2010/01/07 09:04:55 martin + * Added XMR status bit XMRS_BIT_NOT_PHASE_LOCKED. + * Revision 1.81 2009/11/09 09:08:24 martin + * New TM_GPS status bit TM_INVT. + * Added definitions to support VLAN. + * Changed DEFAULT_PTP_DELAY_MECH_MASK to include also + * PTP_DELAY_MECH_MSK_P2P. + * There is now only one type of TCXO supported which matches the former + * TCXO HQ, so the default name for TCXO HQ has been changed to TCXO. + * TCXO LQ and MQ names are still supported for backward compatibility. + * Revision 1.80 2009/09/28 14:55:53 martin * Support IRIG formats G002/G142 and G006/G146. * Modified IRIG format description strings. * Revision 1.79 2009/08/12 14:12:38 daniel @@ -228,7 +273,7 @@ * Added initializer for oscillator names. * Added initializer for oscillator list ordered by quality. * Revision 1.13 2002/05/08 08:16:03 MARTIN - * Added GPS_OSC_CFG_SUPP for RECEIVER_INFO.flags. + * Added GPS_OSC_CFG_SUPP for RECEIVER_INFO::flags. * Fixed some comments. * Revision 1.12 2002/03/14 13:45:56 MARTIN * Changed type CSUM from short to ushort. @@ -334,23 +379,29 @@ typedef uint16_t IOD; /* Issue-Of-Data code */ #endif -/** - The type which is used to pass a cmd code via serial port, or bus. - The cmd codes are defined in gpsserio.h and pcpsdefs.h. -*/ +/** + * @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). + */ typedef uint16_t GPS_CMD; #define _mbg_swab_gps_cmd( _p ) _mbg_swab16( _p ) -/** - A struct used to hold the software revision information - */ +/** + * @brief Software revision information + * + * Contains a software revision code, plus an optional + * identifier for a customized version. + */ typedef struct { - uint16_t code; /**< e.g. 0x0120 means rev. 1.20 */ - char name[GPS_ID_STR_SIZE]; /**< used to identify customized versions */ - uint8_t reserved; /**< 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 ) \ @@ -360,14 +411,31 @@ typedef struct -typedef uint16_t BVAR_STAT; /**< holds status of battery buffered vars */ +/** + * @defgroup bvar_stat BVAR_STAT status of buffered GPS data + * + * Status word, associated bit numbers and bit masks indicating + * whether certain data from the GPS satellites are + * available and valid. + * + * These bits defined are set in ::BVAR_STAT if the corresponding + * parameters are NOT valid and complete. + * + * @{ */ + +/** + * @brief Status flags of battery buffered data received + * from GPS satellites. + * + * All '0' means OK, single bits set to '1' indicate + * the associated type of GPS data is not available. + */ +typedef uint16_t BVAR_STAT; #define _mbg_swab_bvar_stat( _p ) _mbg_swab16( (_p) ) -/** - The bits defined below are set in BVAR_STAT if the corresponding - parameters are NOT valid and complete: -*/ + +/** @brief Enumeration of bits used with BVAR_STAT */ enum { BVAR_BIT_CFGH_INVALID, @@ -375,22 +443,25 @@ enum BVAR_BIT_UTC_INVALID, BVAR_BIT_IONO_INVALID, BVAR_BIT_RCVR_POS_INVALID, - N_BVAR_BIT // number of defined bits + N_BVAR_BIT /**< @brief number of defined ::BVAR_STAT bits */ }; -#define BVAR_CFGH_INVALID ( 1UL << BVAR_BIT_CFGH_INVALID ) -#define BVAR_ALM_NOT_COMPLETE ( 1UL << BVAR_BIT_ALM_NOT_COMPLETE ) -#define BVAR_UTC_INVALID ( 1UL << BVAR_BIT_UTC_INVALID ) -#define BVAR_IONO_INVALID ( 1UL << BVAR_BIT_IONO_INVALID ) -#define BVAR_RCVR_POS_INVALID ( 1UL << BVAR_BIT_RCVR_POS_INVALID ) +#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 */ -/**< bit mask for all defined bits */ -#define BVAR_MASK ( ( 1UL << N_BVAR_BIT ) - 1 ) +#define BVAR_MASK ( ( 1UL << N_BVAR_BIT ) - 1 ) /**< @brief Bit mask for all defined bits */ +/** @} */ -/* a struct used to hold a fixed frequency value */ -/* frequ[kHz] = khz_val * 10^range */ + +/** + A structure used to hold a fixed frequency value. + frequ[kHz] = khz_val * 10^range +*/ typedef struct { @@ -405,6 +476,8 @@ typedef struct } +typedef uint32_t RI_FEATURES; // type of RECEIVER_INFO::features field + /* * The following code defines features and properties @@ -426,7 +499,7 @@ typedef struct 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 */ - uint32_t features; /**< optional features, see below */ + 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 */ @@ -480,6 +553,13 @@ enum GPS_MODEL_TCR170PEX, GPS_MODEL_WWVB511, GPS_MODEL_MGR170, + GPS_MODEL_JJY511, + GPS_MODEL_PZF600, + GPS_MODEL_TCR600, + GPS_MODEL_GPS180, + GPS_MODEL_GLN170, + GPS_MODEL_GPS180PEX, + GPS_MODEL_TCR180PEX, N_GPS_MODEL /* If new model codes are added then care must be taken * to update the associated string initializers below @@ -521,6 +601,13 @@ enum #define GPS_MODEL_NAME_TCR170PEX "TCR170PEX" #define GPS_MODEL_NAME_WWVB511 "WWVB511" #define GPS_MODEL_NAME_MGR170 "MGR170" +#define GPS_MODEL_NAME_JJY511 "JJY511" +#define GPS_MODEL_NAME_PZF600 "PZF600" +#define GPS_MODEL_NAME_TCR600 "TCR600" +#define GPS_MODEL_NAME_GPS180 "GPS180" +#define GPS_MODEL_NAME_GLN170 "GLN170" +#define GPS_MODEL_NAME_GPS180PEX "GPS180PEX" +#define GPS_MODEL_NAME_TCR180PEX "TCR180PEX" /* @@ -557,7 +644,14 @@ enum GPS_MODEL_NAME_GEN170, \ GPS_MODEL_NAME_TCR170PEX, \ GPS_MODEL_NAME_WWVB511, \ - GPS_MODEL_NAME_MGR170 \ + GPS_MODEL_NAME_MGR170, \ + GPS_MODEL_NAME_JJY511, \ + GPS_MODEL_NAME_PZF600, \ + GPS_MODEL_NAME_TCR600, \ + GPS_MODEL_NAME_GPS180, \ + GPS_MODEL_NAME_GLN170, \ + GPS_MODEL_NAME_GPS180PEX, \ + GPS_MODEL_NAME_TCR180PEX \ } @@ -614,12 +708,16 @@ enum #define _mbg_rcvr_is_msf( _p_ri ) \ ( strstr( (_p_ri)->model_name, "MSF" ) ) +#define _mbg_rcvr_is_jjy( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "JJY" ) ) + #define _mbg_rcvr_is_msf_plug_in( _p_ri ) \ ( _mbg_rcvr_is_msf( _p_ri ) && \ _mbg_rcvr_is_plug_in( _p_ri ) ) #define _mbg_rcvr_is_glonass( _p_ri ) \ - ( strstr( (_p_ri)->model_name, "GRC" ) ) + ( strstr( (_p_ri)->model_name, "GRC" ) || \ + ( strstr( (_p_ri)->model_name, "GLN" ) ) #define _mbg_rcvr_is_glonass_plug_in( _p_ri ) \ ( _mbg_rcvr_is_glonass( _p_ri ) && \ @@ -664,7 +762,7 @@ enum { \ "[unknown]", \ "TCXO LQ", \ - "TCXO HQ", \ + "TCXO", \ "OCXO LQ", \ "OCXO MQ", \ "OCXO HQ", \ @@ -710,25 +808,27 @@ enum */ enum { - 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_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 */ - N_GPS_FEATURE /**< the number of valid features */ + 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 */ }; @@ -746,11 +846,13 @@ enum "Ignore Lock", \ "5 MHz Output", \ "Ext. Multiple Ref. Src. Cfg.", \ - "Supp. Optional Settings", \ + "Optional Settings", \ "Configurable Time Scale", \ - "Irig Control Bits", \ + "IRIG Control Bits", \ "PTP/IEEE1588", \ - "Supp. Nav. Engine Settings" \ + "Nav. Engine Settings", \ + "Raw IRIG Data", \ + "Raw IRIG Time" \ } @@ -758,25 +860,27 @@ enum * 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_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 +#define GPS_HAS_REF_OFFS GPS_HAS_IRIG_RX /* @@ -793,7 +897,7 @@ enum /* - * Codes to be used with RECEIVER_INFO.flags: + * Codes 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 @@ -872,26 +976,27 @@ 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. */ - +/** + 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. +*/ typedef struct { - int16_t year; /* 0..9999 */ - int8_t month; /* 1..12 */ - int8_t mday; /* 1..31 */ - int16_t yday; /* 1..366 */ - int8_t wday; /* 0..6 == Sun..Sat */ - int8_t hour; /* 0..23 */ - int8_t min; /* 0..59 */ - int8_t sec; /* 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; /* 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..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 */ } TM_GPS; #define _mbg_swab_tm_gps( _p ) \ @@ -915,9 +1020,9 @@ enum 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 */ - /* Bit 7 is reserved and not used, yet. */ + TM_BIT_INVT, /* invalid time, e.g. if RTC battery empty */ - TM_BIT_EXT_SYNC = 8, /* sync'd externally */ + 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 */ @@ -949,6 +1054,7 @@ enum #define TM_LS_ANN ( 1UL << TM_BIT_LS_ANN ) #define TM_LS_ENB ( 1UL << TM_BIT_LS_ENB ) #define TM_LS_ANN_NEG ( 1UL << TM_BIT_LS_ANN_NEG ) +#define TM_INVT ( 1UL << TM_BIT_INVT ) #define TM_EXT_SYNC ( 1UL << TM_BIT_EXT_SYNC ) #define TM_HOLDOVER ( 1UL << TM_BIT_HOLDOVER ) @@ -1877,46 +1983,74 @@ enum /** - @defgroup group_icode Irig Codes + @defgroup group_icode IRIG Codes The following definitions are used to configure an optional - on-board IRIG input or output. + 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. - A GPS device can generate an IRIG output signal if the bit - #GPS_HAS_IRIG_TX is set in the RECEIVER_INFO.features field. - If a device has an optional IRIG input then the bit - #GPS_HAS_IRIG_RX is set. + 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, DC shift, time-of-year - - \b A003: 1000 bps, DC shift, time-of-year, SBS + - \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, DC shift, time-of-year - - \b B003: 100 bps, DC shift, time-of-year, SBS + - \b B002: 100 bps, DCLS, time-of-year + - \b B003: 100 bps, DCLS, time-of-year, SBS - \b B122: 100 bps, 1 kHz carrier, time-of-year - \b B123: 100 bps, 1 kHz carrier, time-of-year, SBS + - \b B006: 100 bps, DCLS, complete date + - \b B007: 100 bps, DCLS, complete date, SBS + - \b B126: 100 bps, 1 kHz carrier, complete date + - \b B127: 100 bps, 1 kHz carrier, complete date, SBS + - \b B220/1344: 100 bps, DCLS, manchester encoded, IEEE1344 extensions + - \b B222: 100 bps, DCLS, manchester encoded, time-of-year + - \b B223: 100 bps, DCLS, manchester encoded, time-of-year, SBS + - \b G002: 10 kbps, DCLS, time-of-year + - \b G142: 10 kbps, 100 kHz carrier, time-of-year + - \b G006: 10 kbps, DCLS, complete date + - \b G146: 10 kbps, 100 kHz carrier, complete date - \b AFNOR: 100 bps, 1 kHz carrier, SBS, complete date - - <b> AFNOR DC:</b> 100 bps, DC shift, SBS, complete date + - <b> AFNOR DC:</b> 100 bps, DCLS, SBS, complete date - \b IEEE1344: 100 bps, 1 kHz carrier, time-of-year, SBS, IEEE1344 extensions (B120) - - <b> IEEE1344 DC:</b> 100 bps, DC shift, time-of-year, SBS, IEEE1344 extensions (B000) - - \b B220/1344: 100 bps, DC shift, manchester encoded, IEEE1344 extensions - - \b B222: 100 bps, DC shift, manchester encoded, time-of-year - - \b B223: 100 bps, DC shift, manchester encoded, time-of-year, SBS - + - <b> IEEE1344 DC:</b> 100 bps, DCLS, time-of-year, SBS, IEEE1344 extensions (B000) + - \b C37.118: like IEEE1344, but UTC offset with reversed sign + - \b C37.118 DC: like IEEE1344 DC, but UTC offset with reversed sign + - time-of-year: day-of-year, hours, minutes, seconds + - complete date: time-of-year plus year number - SBS: straight binary seconds, second-of-day - - IEEE1344 extensions: time zone info - - AFNOR: french standard AFNOR NFS-87500 - + + 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. + + <b>ATTENTION:</b> 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 generate - * the same IRIG code both with and without carrier signal - * at the same time. */ + * Definitions used with IRIG transmitters which usually output both + * the unmodulated and the modulated IRIG signals at the same time: */ enum { ICODE_TX_B002_B122, @@ -1925,13 +2059,14 @@ enum ICODE_TX_A003_A133, ICODE_TX_AFNOR, ICODE_TX_IEEE1344, - ICODE_TX_B220_1344, - ICODE_TX_B222, - ICODE_TX_B223, + 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 */ }; @@ -1945,35 +2080,60 @@ enum "B003+B123", \ "A002+A132", \ "A003+A133", \ - "AFNOR NFS-87500", \ + "AFNOR NF S87-500", \ "IEEE1344", \ - "B220/1344+IEEE1344", \ - "B222+B122", \ - "B223+B123", \ + "B220(1344) DCLS", \ + "B222 DCLS", \ + "B223 DCLS", \ "B006+B126", \ "B007+B127", \ "G002+G142", \ - "G006+G146" \ + "G006+G146", \ + "C37.118" \ } /** + * Initializers for short name strings which must not + * be longer than 10 printable characters. + */ +#define DEFAULT_ICODE_TX_NAMES_SHORT \ +{ \ + "B002+B122", \ + "B003+B123", \ + "A002+A132", \ + "A003+A133", \ + "AFNOR NF-S", \ + "IEEE1344", \ + "B220/1344", \ + "B222 DC", \ + "B223 DC", \ + "B006+B126", \ + "B007+B127", \ + "G002+G142", \ + "G006+G146", \ + "C37.118" \ +} + + +/** * Initializers for English format description strings. */ #define DEFAULT_ICODE_TX_DESCRIPTIONS_ENG \ { \ - "100 bps, DC or 1 kHz carrier", \ - "100 bps, DC or 1 kHz carrier, SBS", \ - "1000 bps, DC or 10 kHz carrier", \ - "1000 bps, DC or 10 kHz carrier, SBS", \ - "100 bps, DC or 1 kHz carrier, SBS, complete date", \ - "100 bps, DC or 1 kHz carrier, SBS, complete date, time zone info", \ - "100 bps, DC manchester enc. or 1 kHz carrier, SBS, complete date, time zone info", \ - "100 bps, DC manchester enc. or 1 kHz carrier", \ - "100 bps, DC manchester enc. or 1 kHz carrier, SBS", \ - "100 bps, DC or 1 kHz carrier, complete date", \ - "100 bps, DC or 1 kHz carrier, complete date, SBS", \ - "10 kbps, DC or 100 kHz carrier", \ - "10 kbps, DC or 100 kHz carrier, complete date" \ + "100 bps, DCLS or 1 kHz carrier", \ + "100 bps, DCLS or 1 kHz carrier, SBS", \ + "1000 bps, DCLS or 10 kHz carrier", \ + "1000 bps, DCLS or 10 kHz carrier, SBS", \ + "100 bps, DCLS or 1 kHz carrier, SBS, complete date", \ + "100 bps, DCLS or 1 kHz carrier, SBS, complete date, time zone info", \ + "100 bps, Manchester enc., DCLS only, SBS, complete date, time zone info", \ + "100 bps, Manchester enc., DCLS only", \ + "100 bps, Manchester enc., DCLS only, SBS", \ + "100 bps, DCLS or 1 kHz carrier, complete date", \ + "100 bps, DCLS or 1 kHz carrier, complete date, SBS", \ + "10 kbps, DCLS or 100 kHz carrier", \ + "10 kbps, DCLS or 100 kHz carrier, complete date", \ + "like IEEE1344, but UTC offset with reversed sign" \ } /* @@ -1987,21 +2147,22 @@ enum #define MSK_ICODE_TX_A003_A133 ( 1UL << ICODE_TX_A003_A133 ) #define MSK_ICODE_TX_AFNOR ( 1UL << ICODE_TX_AFNOR ) #define MSK_ICODE_TX_IEEE1344 ( 1UL << ICODE_TX_IEEE1344 ) -#define MSK_ICODE_TX_B220_1344 ( 1UL << ICODE_TX_B220_1344 ) +#define MSK_ICODE_TX_B2201344 ( 1UL << ICODE_TX_B2201344 ) #define MSK_ICODE_TX_B222 ( 1UL << ICODE_TX_B222 ) #define MSK_ICODE_TX_B223 ( 1UL << ICODE_TX_B223 ) #define MSK_ICODE_TX_B006_B126 ( 1UL << ICODE_TX_B006_B126 ) #define MSK_ICODE_TX_B007_B127 ( 1UL << ICODE_TX_B007_B127 ) #define MSK_ICODE_TX_G002_G142 ( 1UL << ICODE_TX_G002_G142 ) #define MSK_ICODE_TX_G006_G146 ( 1UL << ICODE_TX_G006_G146 ) +#define MSK_ICODE_TX_C37118 ( 1UL << ICODE_TX_C37118 ) /** * A mask of IRIG formats with manchester encoded DC output: */ #define MSK_ICODE_TX_DC_MANCH \ ( \ - MSK_ICODE_TX_B220_1344 | \ - MSK_ICODE_TX_B222 | \ + MSK_ICODE_TX_B2201344 | \ + MSK_ICODE_TX_B222 | \ MSK_ICODE_TX_B223 \ ) @@ -2014,11 +2175,12 @@ enum MSK_ICODE_TX_B003_B123 | \ MSK_ICODE_TX_AFNOR | \ MSK_ICODE_TX_IEEE1344 | \ - MSK_ICODE_TX_B220_1344 | \ + MSK_ICODE_TX_B2201344 | \ MSK_ICODE_TX_B222 | \ MSK_ICODE_TX_B223 | \ MSK_ICODE_TX_B006_B126 | \ - MSK_ICODE_TX_B007_B127 \ + MSK_ICODE_TX_B007_B127 | \ + MSK_ICODE_TX_C37118 \ ) /** @@ -2049,7 +2211,8 @@ enum MSK_ICODE_TX_AFNOR | \ MSK_ICODE_TX_IEEE1344 | \ MSK_ICODE_TX_B006_B126 | \ - MSK_ICODE_TX_B007_B127 \ + MSK_ICODE_TX_B007_B127 | \ + MSK_ICODE_TX_C37118 \ ) /** @@ -2075,7 +2238,8 @@ enum */ #define MSK_ICODE_TX_HAS_TFOM \ ( \ - MSK_ICODE_TX_IEEE1344 \ + MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_C37118 \ ) /** @@ -2083,7 +2247,8 @@ enum */ #define MSK_ICODE_TX_HAS_TZI \ ( \ - MSK_ICODE_TX_IEEE1344 \ + MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_C37118 \ ) /** @@ -2105,23 +2270,27 @@ enum /** * Definitions used with IRIG receivers which decode - * two similar IRIG codes + * two similar IRIG codes (with or without SBS) * at the same time. */ enum { - ICODE_RX_B122_B123, - ICODE_RX_A132_A133, - ICODE_RX_B002_B003, - ICODE_RX_A002_A003, - ICODE_RX_AFNOR, - ICODE_RX_AFNOR_DC, - ICODE_RX_IEEE1344, - ICODE_RX_IEEE1344_DC, - ICODE_RX_B126_B127, - ICODE_RX_B006_B007, - ICODE_RX_G142_G146, - ICODE_RX_G002_G006, + 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 */ }; @@ -2132,35 +2301,68 @@ enum { \ "B122/B123", \ "A132/A133", \ - "B002/B003 (DC)", \ - "A002/A003 (DC)", \ - "AFNOR NFS-87500", \ - "AFNOR NFS-87500 (DC)", \ + "B002/B003 (DCLS)", \ + "A002/A003 (DCLS)", \ + "AFNOR NF S87-500", \ + "AFNOR NF S87-500 (DCLS)", \ "IEEE1344", \ - "IEEE1344 (DC)", \ + "IEEE1344 (DCLS)", \ "B126/B127", \ - "B006/B007 (DC)", \ + "B006/B007 (DCLS)", \ "G142/G146", \ - "G002/G006 (DC)" \ + "G002/G006 (DCLS)", \ + "C37.118", \ + "C37.118 (DCLS)", \ + "TXC-101 DTR-6", \ + "TXC-101 DTR-6 (DCLS)" \ } /** + * Initializers for short name strings which must not + * be longer than 11 printable characters. + */ +#define DEFAULT_ICODE_RX_NAMES_SHORT \ +{ \ + "B122/B123", \ + "A132/A133", \ + "B002/B003", \ + "A002/A003", \ + "AFNOR NF-S", \ + "AFNOR DC", \ + "IEEE1344", \ + "IEEE1344 DC", \ + "B126/B127", \ + "B006/B007", \ + "G142/G146", \ + "G002/G006", \ + "C37.118", \ + "C37.118 DC", \ + "TXC-101", \ + "TXC-101 DC" \ +} + + +/** * Initializers for English format description strings. */ #define DEFAULT_ICODE_RX_DESCRIPTIONS_ENG \ { \ "100 bps, 1 kHz carrier, SBS optionally", \ "1000 bps, 10 kHz carrier, SBS optionally", \ - "100 bps, DC shift, SBS optionally", \ - "1000 bps, DC shift, SBS optionally", \ + "100 bps, DCLS, SBS optionally", \ + "1000 bps, DCLS, SBS optionally", \ "100 bps, 1 kHz carrier, SBS, complete date", \ - "100 bps, DC shift, SBS, complete date", \ + "100 bps, DCLS, SBS, complete date", \ "100 bps, 1 kHz carrier, SBS, time zone info", \ - "100 bps, DC shift, SBS, time zone info", \ + "100 bps, DCLS, SBS, time zone info", \ "100 bps, 1 kHz carrier, complete date, SBS optionally", \ - "100 bps, DC shift, complete date, SBS optionally", \ + "100 bps, DCLS, complete date, SBS optionally", \ "10 kbps, 100 kHz carrier, complete date optionally", \ - "10 kbps, DC shift, complete date optionally" \ + "10 kbps, DCLS, complete date optionally", \ + "like IEEE1344, but UTC offset with reversed sign", \ + "like IEEE1344 DC, but UTC offset with reversed sign", \ + "code from TV time sync device TXC-101 DTR-6", \ + "DC code from TV time sync device TXC-101 DTR-6" \ } /* @@ -2178,18 +2380,23 @@ enum #define MSK_ICODE_RX_B006_B007 ( 1UL << ICODE_RX_B006_B007 ) #define MSK_ICODE_RX_G142_G146 ( 1UL << ICODE_RX_G142_G146 ) #define MSK_ICODE_RX_G002_G006 ( 1UL << ICODE_RX_G002_G006 ) +#define MSK_ICODE_RX_C37118 ( 1UL << ICODE_RX_C37118 ) +#define MSK_ICODE_RX_C37118_DC ( 1UL << ICODE_RX_C37118_DC ) +#define MSK_ICODE_RX_TXC_101 ( 1UL << ICODE_RX_TXC_101 ) +#define MSK_ICODE_RX_TXC_101_DC ( 1UL << ICODE_RX_TXC_101_DC ) /** - * A mask of IRIG formats which have DC shift: + * A mask of IRIG DCLS formats: */ -#define MSK_ICODE_RX_DC \ -( \ - MSK_ICODE_RX_B002_B003 | \ - MSK_ICODE_RX_A002_A003 | \ - MSK_ICODE_RX_AFNOR_DC | \ - MSK_ICODE_RX_IEEE1344_DC | \ - MSK_ICODE_RX_B006_B007 | \ - MSK_ICODE_RX_G002_G006 \ +#define MSK_ICODE_RX_DC \ +( \ + MSK_ICODE_RX_B002_B003 | \ + MSK_ICODE_RX_A002_A003 | \ + MSK_ICODE_RX_AFNOR_DC | \ + MSK_ICODE_RX_IEEE1344_DC | \ + MSK_ICODE_RX_B006_B007 | \ + MSK_ICODE_RX_G002_G006 | \ + MSK_ICODE_RX_C37118_DC \ ) /** @@ -2200,7 +2407,8 @@ enum MSK_ICODE_RX_B122_B123 | \ MSK_ICODE_RX_AFNOR | \ MSK_ICODE_RX_IEEE1344 | \ - MSK_ICODE_RX_B126_B127 \ + MSK_ICODE_RX_B126_B127 | \ + MSK_ICODE_RX_C37118 \ ) /** @@ -2224,14 +2432,16 @@ enum */ #define MSK_ICODE_RX_100BPS \ ( \ - MSK_ICODE_RX_B122_B123 | \ - MSK_ICODE_RX_B002_B003 | \ - MSK_ICODE_RX_AFNOR | \ - MSK_ICODE_RX_AFNOR_DC | \ - MSK_ICODE_RX_IEEE1344 | \ - MSK_ICODE_RX_IEEE1344_DC | \ - MSK_ICODE_RX_B126_B127 | \ - MSK_ICODE_RX_B006_B007 \ + MSK_ICODE_RX_B122_B123 | \ + MSK_ICODE_RX_B002_B003 | \ + MSK_ICODE_RX_AFNOR | \ + MSK_ICODE_RX_AFNOR_DC | \ + MSK_ICODE_RX_IEEE1344 | \ + MSK_ICODE_RX_IEEE1344_DC | \ + MSK_ICODE_RX_B126_B127 | \ + MSK_ICODE_RX_B006_B007 | \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_C37118_DC \ ) /** @@ -2256,17 +2466,21 @@ enum */ #define MSK_ICODE_RX_HAS_TFOM \ ( \ - MSK_ICODE_RX_IEEE1344 | \ - MSK_ICODE_RX_IEEE1344_DC \ + MSK_ICODE_RX_IEEE1344 | \ + MSK_ICODE_RX_IEEE1344_DC | \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_C37118_DC \ ) /** * A mask of IRIG formats which support time zone information: */ -#define MSK_ICODE_RX_HAS_TZI \ -( \ - MSK_ICODE_RX_IEEE1344 | \ - MSK_ICODE_RX_IEEE1344_DC \ +#define MSK_ICODE_RX_HAS_TZI \ +( \ + MSK_ICODE_RX_IEEE1344 | \ + MSK_ICODE_RX_IEEE1344_DC | \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_C37118_DC \ ) /** @@ -2286,6 +2500,8 @@ enum #endif /** @} */ + + /** * The structure below is used to configure an optional * on-board IRIG output: @@ -2304,7 +2520,7 @@ typedef struct /** - @defgroup group_irig_flags Bit Masks used with IRIG_SETTINGS.flags + @defgroup group_irig_flags Bit Masks used with IRIG_SETTINGS::flags (others are reserved) * @{ @@ -2314,11 +2530,19 @@ typedef struct #define IFLAGS_MASK 0x0003 /**< flags above or'ed */ +// 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. + /** @} */ /** - * The structure is used to query the IRIG configuration - * plus the supported codes: + * @brief Current IRIG settings and supported codes + * + * Used to query the IRIG current IRIG settings + * plus a mask of supported codes. */ typedef struct { @@ -2449,6 +2673,50 @@ enum #define MBG_OPT_FLAG_EMU_SYNC ( 1UL << MBG_OPT_BIT_EMU_SYNC ) + +// bit coded return type for PCPS_GET_IRIG_CTRL_BITS +typedef uint32_t MBG_IRIG_CTRL_BITS; + +#define _mbg_swab_irig_ctrl_bits( _p ) _mbg_swab32( _p ) + + +// The following macro extracts the 4 bit TFOM code from the +// IRIG control bits read from a card. This only works if the received +// IRIG code is a code which supports TFOM, this is currently +// only IEEE1344. +#define _pcps_tfom_from_irig_ctrl_bits( _p ) \ + ( ( ( *(_p) ) >> 24 ) & 0x0F ) + + + +#define RAW_IRIG_SIZE 16 + +/** + 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 +{ + uint8_t data_bytes[RAW_IRIG_SIZE]; +} MBG_RAW_IRIG_DATA; + +// The following macro extracts the 4 bit TFOM code from the raw +// data bits read from a card. This only works if the received +// IRIG code is a code which supports TFOM, this is currently +// only IEEE1344. +#define _pcps_tfom_from_raw_irig_data( _p ) \ + ( ( ( (_p)->data_bytes[9] >> 2 ) & 0x08 ) \ + | ( ( (_p)->data_bytes[9] >> 4 ) & 0x04 ) \ + | ( ( (_p)->data_bytes[9] >> 6 ) & 0x02 ) \ + | ( ( (_p)->data_bytes[8] & 0x01 ) ) ) + + + /** @defgroup group_scale Time Scale Configuration @@ -2649,6 +2917,8 @@ enum 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 }; @@ -2671,6 +2941,8 @@ enum #define ENG_POUT_NAME_TIMECODE "DCLS Time Code" #define ENG_POUT_NAME_TIMESTR "COM Time String" #define ENG_POUT_NAME_10MHZ "10 MHz Frequency" +#define ENG_POUT_NAME_DCF77_M59 "DCF77-like M59" +#define ENG_POUT_NAME_SYNTH "Synthesizer Frequency" #define DEFAULT_ENG_POUT_NAMES \ { \ @@ -2687,7 +2959,9 @@ enum ENG_POUT_NAME_ALL_SYNC, \ ENG_POUT_NAME_TIMECODE, \ ENG_POUT_NAME_TIMESTR, \ - ENG_POUT_NAME_10MHZ \ + ENG_POUT_NAME_10MHZ, \ + ENG_POUT_NAME_DCF77_M59, \ + ENG_POUT_NAME_SYNTH \ } @@ -2705,6 +2979,8 @@ enum #define ENG_POUT_HINT_TIMECODE "Duplicate IRIG time code signal" #define ENG_POUT_HINT_TIMESTR "Duplicate serial time string of specified port" #define ENG_POUT_HINT_10MHZ "10 MHz fixed output frequency" +#define ENG_POUT_HINT_DCF77_M59 "DCF77 time marks with 500 ms pulse in 59th second" +#define ENG_POUT_HINT_SYNTH "Frequency generated by programmable synthesizer" #define DEFAULT_ENG_POUT_HINTS \ { \ @@ -2721,7 +2997,9 @@ enum ENG_POUT_HINT_ALL_SYNC, \ ENG_POUT_HINT_TIMECODE, \ ENG_POUT_HINT_TIMESTR, \ - ENG_POUT_HINT_10MHZ \ + ENG_POUT_HINT_10MHZ, \ + ENG_POUT_HINT_DCF77_M59, \ + ENG_POUT_HINT_SYNTH \ } @@ -2744,12 +3022,16 @@ enum #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 ) /* - * The codes below are used with POUT_SETTINGS.flags: + * The codes below are used with POUT_SETTINGS::flags: */ -#define POUT_INVERTED 0x0001 +#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 /** @@ -2786,7 +3068,7 @@ typedef struct 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; /**< reserved for future use, currently 0 */ + uint32_t flags; /**< see below */ } POUT_INFO; #define _mbg_swab_pout_info( _p ) \ @@ -2801,6 +3083,14 @@ typedef struct /** The max number of COM ports that can be handled by POUT_INFO::timestr_ports */ #define MAX_POUT_TIMESTR_PORTS 8 + +/* + * The codes below are used with POUT_INFO::flags: + */ +#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 + + /** The structure below adds an index number to the structure above to allow addressing of several instances: @@ -2840,7 +3130,8 @@ enum MULTI_REF_PTP, // Precision Time Protocol (PTP, IEEE1588) MULTI_REF_PTP_E1, // PTP over E1 MULTI_REF_FREQ, // fixed frequency - N_MULTI_REF // the number of defined sources + MULTI_REF_PPS_STRING, // 1 PPS in addition to string + N_MULTI_REF // the number of defined sources }; @@ -2857,7 +3148,8 @@ enum "NTP", \ "PTP (IEEE1588)", \ "PTP over E1", \ - "Fixed Freq. in" \ + "Fixed Freq. in", \ + "PPS plus string" \ } @@ -2873,6 +3165,7 @@ enum #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 ) /* @@ -2893,12 +3186,12 @@ enum /** - The structure below is used to configure the priority of + The structure below is 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 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. */ @@ -3062,26 +3355,28 @@ typedef struct */ enum { - 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_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 }; /* 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_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 ) @@ -3250,6 +3545,106 @@ typedef struct #define OSC_DAC_BIAS ( OSC_DAC_RANGE / 2 ) + +/* + The enumeration below lists all + known satellite navigation systems +*/ +enum +{ + GNSS_TYPE_GPS, + GNSS_TYPE_GLONASS, + GNSS_TYPE_BEIDOU, + GNSS_TYPE_GALILEO, + N_GNSS_TYPES +}; + + + +#define GNSS_TYPE_STRS \ +{ \ + "GPS", \ + "GLONASS", \ + "BEIDOU" , \ + "GALILEO" \ +} + + + +#define MBG_GNSS_TYPE_MSK_GPS ( 1UL << GNSS_TYPE_GPS ) +#define MBG_GNSS_TYPE_MSK_GLONASS ( 1UL << GNSS_TYPE_GLONASS ) +#define MBG_GNSS_TYPE_MSK_BEIDOU ( 1UL << GNSS_TYPE_BEIDOU ) +#define MBG_GNSS_TYPE_MSK_GALILEO ( 1UL << GNSS_TYPE_GALILEO ) + + +#define N_GNSS_MODE_PRIO 8 + +typedef struct +{ + uint32_t gnss_set; /**< current set of GNSS types */ + uint8_t prio[N_GNSS_MODE_PRIO]; /**< index 0 for highest priority, use GNSS enumeration above, init with 0xFF if not supported */ + uint32_t flags; /**< see below */ +} MBG_GNSS_MODE_SETTINGS; + +#define _mbg_swab_mbg_gnss_mode_settings( _p ) \ +{ \ + _mbg_swab32( &(_p)->gnss_set ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + + +typedef struct +{ + MBG_GNSS_MODE_SETTINGS settings; /**< current GNSS mode settings */ + uint32_t supp_gnss_types; /**< bit masks of supported GNSS types */ + uint32_t flags; /**< indicates which of the defined flags are supported by the device */ +} MBG_GNSS_MODE_INFO; + +#define _mbg_swab_mbg_gnss_mode_info( _p ) \ +{ \ + _mbg_swab_mbg_gnss_mode_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_gnss_types ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/* Flags used with MBG_GNSS_MODE_SETTINGS::flags and MBG_GNSS_MODE_INFO::flags: */ + +enum +{ + MBG_GNSS_FLAG_EXCLUSIVE, /**< (read only) only one of the supported GNSS systems can be used at the same time */ + MBG_GNSS_FLAG_HAS_PRIORITY, /**< (read only) priority can be configured using the MBG_GNSS_MODE_SETTINGS::prio field */ + N_MBG_GNSS_FLAGS +}; + +#define MBG_GNSS_FLAG_MSK_EXCLUSIVE ( 1UL << MBG_GNSS_FLAG_EXCLUSIVE ) +#define MBG_GNSS_FLAG_MSK_HAS_PRIORITY ( 1UL << MBG_GNSS_FLAG_HAS_PRIORITY ) + + + +#define MAX_USED_SATS 32 + +/* + 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; + +#define _mbg_swab_gnss_sat_info( _p ) \ +{ \ + _mbg_swab16( &(_p)->good_svs ); \ + _mbg_swab16( &(_p)->svs_in_view ); \ +} + + #ifndef _IDENT_DEFINED typedef union @@ -3300,7 +3695,8 @@ typedef struct IP4_ADDR netmask; IP4_ADDR broad_addr; IP4_ADDR gateway; - uint32_t flags; /* see below */ + uint16_t flags; /* see below */ + uint16_t vlan_cfg; /* see below */ } IP4_SETTINGS; @@ -3310,10 +3706,40 @@ typedef struct _mbg_swab_ip4_addr( &(_p)->netmask ); \ _mbg_swab_ip4_addr( &(_p)->broad_addr ); \ _mbg_swab_ip4_addr( &(_p)->gateway ); \ - _mbg_swab32( &(_p)->flags ); \ + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab16( &(_p)->vlan_cfg ); \ } +// 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 ) + + +#define VLAN_PRIORITY_BITS 3 // number of bits to hold priority +#define N_VLAN_PRIORITY ( 1 << VLAN_PRIORITY_BITS ) // number of priority values +#define MIN_VLAN_PRIORITY 0 // minimum priority +#define MAX_VLAN_PRIORITY ( N_VLAN_PRIORITY - 1 ) // maximum priority + +// vlan_priority = ( vlan_cfg >> VLAN_PRIORITY_SHIFT ) & VLAN_PRIORITY_MSK +#define VLAN_PRIORITY_SHIFT ( ( 8 * sizeof( uint16_t ) ) - VLAN_PRIORITY_BITS ) +#define VLAN_PRIORITY_MSK ( ( 1 << VLAN_PRIORITY_BITS ) - 1 ) + +// 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 ) ) + + #if 0 //##++ currently not used /* Misc configuration */ @@ -3351,16 +3777,18 @@ typedef struct 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; /* reserved, currently always 0 */ - uint32_t flags; /* reserved, currently always 0 */ + uint32_t rsvd_0; /* reserved, currently always 0 */ + uint16_t flags; /* see below */ + uint16_t rsvd_1; /* reserved, currently always 0 */ } LAN_IF_INFO; #define _mbg_swab_lan_if_info( _p ) \ { \ _mbg_swab16( &(_p)->type ); \ _mbg_swab16( &(_p)->ver_code ); \ - _mbg_swab32( &(_p)->rsvd ); \ - _mbg_swab32( &(_p)->flags ); \ + _mbg_swab32( &(_p)->rsvd_0 ); \ + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab16( &(_p)->rsvd_1 ); \ } @@ -3379,13 +3807,15 @@ enum enum { - IP4_BIT_DHCP, - IP4_BIT_LINK, // used only to report state + 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 }; #define IP4_MSK_DHCP ( 1UL << IP4_BIT_DHCP ) #define IP4_MSK_LINK ( 1UL << IP4_BIT_LINK ) +#define IP4_MSK_VLAN ( 1UL << IP4_BIT_VLAN ) enum @@ -3458,7 +3888,7 @@ enum typedef struct { uint8_t value; - char *name; + const char *name; } PTP_TABLE; @@ -3473,7 +3903,7 @@ enum #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 ) + #define DEFAULT_PTP_DELAY_MECH_MASK ( PTP_DELAY_MECH_MSK_E2E | PTP_DELAY_MECH_MSK_P2P ) #endif #define PTP_DELAY_MECH_NAMES \ @@ -3678,7 +4108,7 @@ typedef struct uint32_t lower_bound; // [ns] sync state set to true if below this limit uint32_t reserved_3; // currently always 0 - uint32_t flags; // (see below) + uint32_t flags; // (see below) } PTP_CFG_SETTINGS; @@ -3840,20 +4270,20 @@ typedef struct /** - UTC correction parameters + @brief GPS UTC correction parameters */ 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 [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 leap second is inserted */ - int8_t delta_tls; /**< Current UTC offset to GPS system time [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; diff --git a/mbglib/common/gpsserio.h b/mbglib/common/gpsserio.h index b6473b9..de5fa04 100644 --- a/mbglib/common/gpsserio.h +++ b/mbglib/common/gpsserio.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsserio.h 1.32 2009/08/26 09:02:21Z daniel REL_M $ + * $Id: gpsserio.h 1.34 2011/04/15 13:12:02Z martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -31,7 +31,13 @@ * * ----------------------------------------------------------------------- * $Log: gpsserio.h $ - * Revision 1.32 2009/08/26 09:02:21Z daniel + * Revision 1.34 2011/04/15 13:12:02Z martin + * Added initializer for command name table. + * Unified mutex stuff using macros from mbgmutex.h. + * Revision 1.33 2010/09/07 07:18:08 daniel + * New codes and structures for multi GNSS support. + * Defines to support reading raw IRIG data. + * Revision 1.32 2009/08/26 09:02:21 daniel * Added new commands GPS_NAV_ENG_SETTINGS and * GPS_GLNS_ALM. * Revision 1.31 2009/08/24 13:32:33Z martin @@ -163,9 +169,9 @@ #include <use_pack.h> -/* - * The following macros control parts of the build process. - * The default values are suitable for most cases but can be +/* + * The following macros control parts of the build process. + * The default values are suitable for most cases but can be * overridden by global definitions, if required. */ @@ -173,67 +179,20 @@ // This handle type in not used by the firmware. // However, we define it to avoid build errors. typedef int MBG_HANDLE; -#else - #if defined( MBG_TGT_WIN32 ) - - #ifndef _USE_MUTEX - #define _USE_MUTEX 1 - #endif - - #if _USE_MUTEX - - #include <windows.h> - typedef HANDLE MBG_MUTEX_HANDLE; - - #define _mbg_mutex_init( _m ) \ - _m = CreateMutex( NULL, FALSE, NULL ) - - #define _mbg_mutex_lock( _m ) \ - WaitForSingleObject( _m, INFINITE ) +#endif - #define _mbg_mutex_unlock( _m ) \ - ReleaseMutex( _m ) - - #define _mbg_mutex_destroy( _m ) \ - CloseHandle( _m ) - #endif +#ifndef _USE_MUTEX + #if defined( MBG_TGT_WIN32 ) + #define _USE_MUTEX 1 #elif defined( MBG_TGT_UNIX ) - - #ifndef _USE_MUTEX - #define _USE_MUTEX 1 - #endif - - #if _USE_MUTEX - - #include <pthread.h> - - typedef pthread_mutex_t MBG_MUTEX_HANDLE; - - // Mutex types: - // PTHREAD_MUTEX_INITIALIZER /* Fast */ - // PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP /* Recursive */ - // PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP /* Errorcheck */ - #define _mbg_mutex_init( _m ) \ - pthread_mutex_init( &(_m), NULL ) - - #define _mbg_mutex_lock( _m ) \ - pthread_mutex_lock( &(_m) ) - - #define _mbg_mutex_unlock( _m ) \ - pthread_mutex_unlock( &(_m) ) - - #define _mbg_mutex_destroy( _m ) \ - pthread_mutex_destroy( &(_m) ) - #endif - - #endif - - #ifndef _USE_MUTEX - #define _USE_MUTEX 0 + #define _USE_MUTEX 1 #endif +#endif +#ifndef _USE_MUTEX + #define _USE_MUTEX 0 // not used by default #endif @@ -266,18 +225,15 @@ #endif #endif -#if _USE_SERIAL_IO - #include <mbgserio.h> -#endif - /* Control inclusion of pcpsdefs.h */ #ifndef _USE_PCPSDEFS #if _IS_MBG_FIRMWARE // for firmware depend on the target system - #define _USE_PCPSDEFS \ - ( \ - defined( _CC51 ) \ - ) + #if defined( _CC51 ) + #define _USE_PCPSDEFS 1 + #else + #define _USE_PCPSDEFS 0 + #endif #else // otherwise include it by default #define _USE_PCPSDEFS 1 @@ -293,9 +249,21 @@ /* Control inclusion of function prototypes */ #ifndef _USE_GPSSERIO_FNC /* by default don't include if building a firmware */ - #define _USE_GPSSERIO_FNC ( ! _IS_MBG_FIRMWARE ) + #define _USE_GPSSERIO_FNC ( !_IS_MBG_FIRMWARE ) #endif +#ifndef _USE_RCV_TSTAMP + #define _USE_RCV_TSTAMP ( !_IS_MBG_FIRMWARE ) +#endif + + +#if _USE_MUTEX + #include <mbgmutex.h> +#endif + +#if _USE_SERIAL_IO + #include <mbgserio.h> +#endif #if _USE_SOCKET_IO #if defined( MBG_TGT_UNIX ) @@ -316,6 +284,10 @@ #include <gpspriv.h> #endif +#if _USE_RCV_TSTAMP + #include <mbg_tmo.h> +#endif + #ifdef __cplusplus @@ -365,9 +337,11 @@ extern "C" { #define GPS_CTRL_MSK 0xF000 /* masks control code from command */ -/* The codes below specify commands/types of data to be supplied to */ -/* the GPS receiver: */ - +/**< @defgroup gps_cmds_serial GPS commands passed via serial port + * + * These codes specify commands/types of data to be supplied to + * the GPS receiver: + */ /* clock auto-message to host */ /* | host request, clock response */ /* | | host download to clock */ @@ -419,7 +393,8 @@ enum /* | | | */ 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_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 data */ GPS_CFGH = 0x100, /* | | X | X | CFGH, SVs' configuration and health codes */ @@ -431,6 +406,8 @@ enum /* | | | */ /* 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 */ /* Misc data */ GPS_IP4_SETTINGS = 0x800, /* | X | X | IP4_SETTINGS, cfg of optional LAN interface */ @@ -461,6 +438,95 @@ enum /* | | | */ */ +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 } \ +} + + /* A structure holding the number of a SV and the SV's almanac. */ typedef struct @@ -553,6 +619,10 @@ typedef union MBG_TIME_SCALE_INFO time_scale_info; MBG_TIME_SCALE_SETTINGS time_scale_settings; NAV_ENGINE_SETTINGS nav_engine_settings; + MBG_RAW_IRIG_DATA raw_irig_data; + GNSS_SAT_INFO gnss_sat_info; //##++++++ + MBG_GNSS_MODE_INFO gnss_mode_info; //##++++++ + MBG_GNSS_MODE_SETTINGS gnss_mode_settings; //##++++++ /* GPS system data */ CFGH cfgh; @@ -672,7 +742,9 @@ typedef struct 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 */ - + #if _USE_RCV_TSTAMP + MBG_TMO_TIME tstamp; + #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; @@ -708,7 +780,7 @@ typedef struct int xfer_mode; #if _USE_MUTEX - MBG_MUTEX_HANDLE xmt_mutex; + MBG_MUTEX xmt_mutex; #endif } MBG_MSG_XMT_CTL; diff --git a/mbglib/common/mbg_tgt.h b/mbglib/common/mbg_tgt.h index f10f53f..06e9a86 100644 --- a/mbglib/common/mbg_tgt.h +++ b/mbglib/common/mbg_tgt.h @@ -13,6 +13,7 @@ * $Log: mbg_tgt.h $ * Revision 1.22 2009/10/01 08:20:50Z 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 diff --git a/mbglib/common/mbg_tmo.c b/mbglib/common/mbg_tmo.c new file mode 100644 index 0000000..b62231b --- /dev/null +++ b/mbglib/common/mbg_tmo.c @@ -0,0 +1,64 @@ + +/************************************************************************** + * + * $Id: mbg_tmo.c 1.2 2009/09/01 10:36:45Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Functions to implement portable timeout handling. + * These functions are normally implemented as inline functions, or + * as preprocessor macros, if inline code is not supported. + * + * However, due to their nature the functions below can not be + * implemented as macros, so they need to be implemented as normal + * functions for targets which do not support inline functions. + * + * This currently applies only to the CVI build environment. + * + * ----------------------------------------------------------------------- + * $Log: mbg_tmo.c $ + * Revision 1.2 2009/09/01 10:36:45Z martin + * Implement legacy functions only if __mbg_inline is not defined. + * Revision 1.1 2009/08/25 11:28:47 martin + * Initial revision. + * + **************************************************************************/ + +#define _MBG_TMO + #include <mbg_tmo.h> +#undef _MBG_TMO + + +#if !defined( __mbg_inline ) + + +int mbg_tmo_curr_time_is_after( const MBG_TMO_TIME *tmo ) +{ + MBG_TMO_TIME t_now; + + mbg_tmo_get_time( &t_now ); + + return mbg_tmo_time_is_after( &t_now, tmo ); + +} // mbg_tmo_curr_time_is_after + + + +// The function below can be used to set up a timeout for select(). + +#if defined( MBG_TGT_CVI ) + +void mbgserio_msec_to_timeval( ulong msec, struct timeval *tv ) +{ + tv->tv_sec = msec / 1000; + tv->tv_usec = ( msec % 1000 ) * 1000; + +} // mbgserio_msec_to_timeval + +#endif // defined( MBG_TGT_CVI ) + + +#endif // !defined( __mbg_inline ) + + diff --git a/mbglib/common/mbg_tmo.h b/mbglib/common/mbg_tmo.h new file mode 100644 index 0000000..60399b9 --- /dev/null +++ b/mbglib/common/mbg_tmo.h @@ -0,0 +1,317 @@ + +/************************************************************************** + * + * $Id: mbg_tmo.h 1.4 2011/01/26 16:55:33Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Inline functions for portable timeout handling. + * + * ----------------------------------------------------------------------- + * $Log: mbg_tmo.h $ + * 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. + * Revision 1.2 2009/09/01 10:38:21Z martin + * Cleanup for CVI and other targets which don't support inline code. + * Revision 1.1 2009/08/24 13:08:56 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBG_TMO_H +#define _MBG_TMO_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> +#include <words.h> + +#ifdef _MBG_TMO + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( MBG_TGT_UNIX ) + + #include <stdlib.h> + #include <sys/time.h> + + typedef struct timeval MBG_TMO_TIME; + +#elif defined( MBG_TGT_WIN32 ) + + typedef union + { + FILETIME ft; + uint64_t u64; + + } MBG_TMO_TIME; + +#else // DOS, ... + + #include <time.h> + + #define MBG_TMO_TIME clock_t + +#endif + + + +#if defined( __mbg_inline ) + +static __mbg_inline +void mbg_tmo_get_time( MBG_TMO_TIME *t ) +{ + #if defined( MBG_TGT_UNIX ) + + gettimeofday( t, NULL ); + + #elif defined( MBG_TGT_WIN32 ) + + GetSystemTimeAsFileTime( &t->ft ); + + #else // DOS, ... + + *t = clock(); + + #endif + +} // mbg_tmo_get_time + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_get_time( _t ) \ + GetSystemTimeAsFileTime( &(_t)->ft ) + +#else // DOS, ... + + #define mbg_tmo_get_time( _t ) \ + *(_t) = clock(); + +#endif + + +#if defined( __mbg_inline ) + +static __mbg_inline +int mbg_tmo_time_is_set( const MBG_TMO_TIME *t ) +{ + #if defined( MBG_TGT_UNIX ) + + return ( t->tv_sec != 0 ) || ( t->tv_usec != 0 ); + + #elif defined( MBG_TGT_WIN32 ) + + return ( t->u64 != 0 ); + + #else // DOS, ... + + return ( *t != 0 ); + + #endif + +} // mbg_tmo_time_is_set + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_time_is_set( _t ) \ + ( (_t)->u64 != 0 ) + +#else // DOS, ... + + #define mbg_tmo_time_is_set( _t ) \ + ( *(_t) != 0 ) + +#endif + + +#if defined( __mbg_inline ) + +static __mbg_inline +void mbg_tmo_set_timeout_ms( MBG_TMO_TIME *t_tmo, ulong msec ) +{ + mbg_tmo_get_time( t_tmo ); + + #if defined( MBG_TGT_UNIX ) + + t_tmo->tv_usec += msec * 1000; + + while ( t_tmo->tv_usec > 1000000L ) + { + t_tmo->tv_usec -= 1000000L; + t_tmo->tv_sec++; + } + + #elif defined( MBG_TGT_WIN32 ) + + t_tmo->u64 += ( (uint64_t) msec ) * 10000; + + #else // DOS, ... + + *t_tmo += (clock_t) ( ( (double) msec * CLOCKS_PER_SEC ) / 1000 ); + + #endif + +} // mbg_tmo_set_timeout + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_set_timeout_ms( _t, _msec ) \ + mbg_tmo_get_time( (_t) ); \ + (_t)->u64 += ( (uint64_t) (_msec) ) * 10000 + +#else // DOS, ... + + #define mbg_tmo_set_timeout_ms( _t, _msec ) \ + mbg_tmo_get_time( (_t) ); \ + *(_t) += (clock_t) ( ( (double) (_msec) * CLOCKS_PER_SEC ) / 1000 ); +#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 ) + + return ( t->tv_sec - t0->tv_sec ) * 1000 + + ( t->tv_usec - t0->tv_usec ) / 1000; + + #elif defined( MBG_TGT_WIN32 ) + + return (long) ( ( t->u64 - t0->u64 ) / 10000 ); + + #else // DOS, ... + + return (long) ( (double) ( ( *t - *t0 ) * 1000 ) / CLOCKS_PER_SEC ); + + #endif + +} // mbg_tmo_time_diff_ms + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_time_diff_ms( _t, _t0 ) \ + (long) ( ( (_t)->u64 - (_t0)->u64 ) / 10000 ) + +#else // DOS, ... + + #define mbg_tmo_time_diff_ms( _t, _t0 ) \ + (long) ( (double) ( ( *(_t) - *(_t0) ) * 1000 ) / 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 ) + + return ( ( t_now->tv_sec > tmo->tv_sec ) || + ( ( t_now->tv_sec == tmo->tv_sec ) && ( t_now->tv_usec > tmo->tv_usec ) ) ); + + #elif defined( MBG_TGT_WIN32 ) + + return ( t_now->u64 > tmo->u64 ); + + #else // DOS, ... + + return ( *t_now > *tmo ); + + #endif + +} // mbg_tmo_time_is_after + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_time_is_after( _t, _tmo ) \ + ( (_t)->u64 > (_tmo)->u64 ) + +#else // DOS, ... + + #define mbg_tmo_time_is_after( _t, _tmo ) \ + ( *(_t) > *(_tmo) ) + +#endif + + +#if defined( __mbg_inline ) + +static __mbg_inline +int mbg_tmo_curr_time_is_after( const MBG_TMO_TIME *tmo ) +{ + MBG_TMO_TIME t_now; + + mbg_tmo_get_time( &t_now ); + + return mbg_tmo_time_is_after( &t_now, tmo ); + +} // mbg_tmo_curr_time_is_after + +#else + + // needs to be implemented as non-inline function in mbg_tmo.c + int mbg_tmo_curr_time_is_after( const MBG_TMO_TIME *tmo ); + +#endif + + + +// The function below can be used to set up a timeout for select(). + +// check for CVI first since this is a special case of WIN32 +#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 ); + +#elif defined( MBG_TGT_UNIX ) + +static __mbg_inline +void mbgserio_msec_to_timeval( ulong msec, struct timeval *tv ) +{ + tv->tv_sec = msec / 1000; + tv->tv_usec = ( msec % 1000 ) * 1000; + +} // mbgserio_msec_to_timeval + +#endif // defined( MBG_TGT_UNIX ) || defined( MBG_TGT_WIN32 ) + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + +/* (no header definitions found) */ + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBG_TMO_H */ diff --git a/mbglib/common/mbgextio.c b/mbglib/common/mbgextio.c index 4623e32..17322b0 100644 --- a/mbglib/common/mbgextio.c +++ b/mbglib/common/mbgextio.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgextio.c 1.9 2009/10/02 14:19:05Z martin REL_M $ + * $Id: mbgextio.c 1.11 2011/04/15 13:17:14Z martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,7 +11,12 @@ * * ----------------------------------------------------------------------- * $Log: mbgextio.c $ - * Revision 1.9 2009/10/02 14:19:05Z martin + * Revision 1.11 2011/04/15 13:17:14Z martin + * Use common mutex support macros from mbgmutex.h. + * Revision 1.10 2011/04/08 11:28:24 martin + * Modified mbgextio_get_ucap() to account for different device behaviour. + * Added missing braces. + * Revision 1.9 2009/10/02 14:19:05 martin * Added a bunch of missing functions. * Revision 1.8 2009/10/01 11:10:51 martin * Added functions to set/retrieve char and msg rcv timeout. @@ -246,7 +251,7 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl, #endif #if _USE_MUTEX - _mbg_mutex_init( pmctl->xmt.xmt_mutex ); + _mbg_mutex_init( &pmctl->xmt.xmt_mutex ); #endif return rc; @@ -277,7 +282,7 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_serial( MBG_MSG_CTL *pmctl, const char mbgserio_set_parms( &pmctl->st.serio, baud_rate, framing ); #if _USE_MUTEX - _mbg_mutex_init( pmctl->xmt.xmt_mutex ); + _mbg_mutex_init( &pmctl->xmt.xmt_mutex ); #endif return 0; @@ -315,7 +320,7 @@ _MBG_API_ATTR void _MBG_API mbgextio_close_connection( MBG_MSG_CTL *pmctl ) }; // switch #if _USE_MUTEX - _mbg_mutex_destroy( pmctl->xmt.xmt_mutex ); + _mbg_mutex_destroy( &pmctl->xmt.xmt_mutex ); #endif } // mbgextio_close_connection @@ -419,7 +424,7 @@ _MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd, #if _USE_MUTEX - _mbg_mutex_lock( pmctl->xmt.xmt_mutex ); + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); #endif pmb = pmctl->xmt.pmb; @@ -432,7 +437,7 @@ _MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd, xmt_tbuff( pmctl ); #if _USE_MUTEX - _mbg_mutex_unlock( pmctl->xmt.xmt_mutex ); + _mbg_mutex_release( &pmctl->xmt.xmt_mutex ); #endif if ( cmd & GPS_REQACK ) @@ -445,7 +450,7 @@ _MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd, if ( pmctl->rcv.pmb->hdr.cmd & GPS_NACK ) return -3; - if ( !pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) + if ( !(pmctl->rcv.pmb->hdr.cmd & GPS_ACK) ) return -4; } @@ -601,13 +606,13 @@ _MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) int rc; #if _USE_MUTEX - _mbg_mutex_lock( pmctl->xmt.xmt_mutex ); + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); #endif rc = xmt_cmd( pmctl, cmd ); #if _USE_MUTEX - _mbg_mutex_unlock( pmctl->xmt.xmt_mutex ); + _mbg_mutex_release( &pmctl->xmt.xmt_mutex ); #endif return rc; @@ -622,13 +627,13 @@ _MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, int rc; #if _USE_MUTEX - _mbg_mutex_lock( pmctl->xmt.xmt_mutex ); + _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex ); #endif rc = xmt_cmd_us( pmctl, cmd, us ); #if _USE_MUTEX - _mbg_mutex_unlock( pmctl->xmt.xmt_mutex ); + _mbg_mutex_release( &pmctl->xmt.xmt_mutex ); #endif return rc; @@ -968,9 +973,26 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, TTM *p ) // 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. - rc = mbgextio_rcv_msg( pmctl, GPS_UCAP ); + for (;;) + { + rc = mbgextio_rcv_msg( pmctl, -1 ); - if ( ( rc == TR_COMPLETE ) && p ) + if ( rc < 0 ) + break; + + if ( rc != TR_COMPLETE ) + continue; + + 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 @@ -978,7 +1000,7 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, TTM *p ) if ( pmctl->rcv.pmb->hdr.len > 0 ) *p = pmctl->rcv.pmb->u.msg_data.ttm; else - p->tm.sec = (int8_t) 0xFF; // no capture event available + _ttm_time_set_unavail( p ); // no capture event available } return rc; diff --git a/mbglib/common/mbgextio.h b/mbglib/common/mbgextio.h index 5696e23..53a21e6 100644 --- a/mbglib/common/mbgextio.h +++ b/mbglib/common/mbgextio.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgextio.h 1.7 2009/10/02 14:21:08Z martin REL_M $ + * $Id: mbgextio.h 1.8 2011/04/08 11:26:09Z martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,7 +10,9 @@ * * ----------------------------------------------------------------------- * $Log: mbgextio.h $ - * Revision 1.7 2009/10/02 14:21:08Z martin + * Revision 1.8 2011/04/08 11:26:09Z martin + * New macros _ttm_time_set_unavail() and _ttm_time_is_avail(). + * Revision 1.7 2009/10/02 14:21:08 martin * Updated function prototypes. * Revision 1.6 2009/10/01 11:13:42Z martin * Updated function prototypes. @@ -50,6 +52,14 @@ /* Start of header body */ +// The macros below can be used to set a TTM variable to a state +// indicating "time not available", and to check this state. +// This can be used for example to indicate if a capture event +// could have been read from a device, or not. +#define _ttm_time_set_unavail( _t ) do { (_t)->tm.sec = (uint8_t) 0xFF; } while ( 0 ) +#define _ttm_time_is_avail( _t ) ( (uint8_t) (_t)->tm.sec != (uint8_t) 0xFF ) + + #if _USE_SERIAL_IO #if !defined( DEFAULT_DEV_NAME ) #if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_DOS ) diff --git a/mbglib/common/mbgmutex.h b/mbglib/common/mbgmutex.h new file mode 100644 index 0000000..0a35494 --- /dev/null +++ b/mbglib/common/mbgmutex.h @@ -0,0 +1,239 @@ + +/************************************************************************** + * + * $Id: mbgmutex.h 1.1 2011/04/15 12:26:59Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Portable macros to deal with spinlocks, mutexes, + * and critical sections. + * + * ----------------------------------------------------------------------- + * $Log: mbgmutex.h $ + * Revision 1.1 2011/04/15 12:26:59Z martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBGMUTEX_H +#define _MBGMUTEX_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> +#include <words.h> + +#ifdef _MBGMUTEX + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( MBG_TGT_KERNEL ) // definitions used in kernel space + + #if defined( MBG_TGT_WIN32 ) // Windows kernel space + + typedef KSPIN_LOCK MBG_SPINLOCK; + #define _mbg_spin_lock_init( _spl ) KeInitializeSpinLock( _spl ) + #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 ) + + #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() + #define _mbg_mutex_acquire( _pmtx ) ExAcquireFastMutex( _pmtx ) + #define _mbg_mutex_release( _pmtx ) ExReleaseFastMutex( _pmtx ) + + #define _MBG_MUTEX_DEFINED 1 + + #elif defined( MBG_TGT_LINUX ) // Linux kernel space + + #include <linux/spinlock.h> + #include <asm/semaphore.h> + + typedef spinlock_t MBG_SPINLOCK; + #define _mbg_spin_lock_init( _spl ) spin_lock_init( _spl ) + #define _mbg_spin_lock_destroy( _spl ) _nop_macro_fnc() + #define _mbg_spin_lock_acquire( _spl ) spin_lock( _spl ) + #define _mbg_spin_lock_release( _spl ) spin_unlock( _spl ) + + #define MBG_SPINLOCK_DEFINED 1 + + + typedef struct semaphore MBG_MUTEX; + #define _mbg_mutex_init( _pmtx ) sema_init( _pmtx, 1 ) + #define _mbg_mutex_destroy( _pmtx ) _nop_macro_fnc() + #define _mbg_mutex_acquire( _pmtx ) down_interruptible( _pmtx ) + #define _mbg_mutex_release( _pmtx ) up( _pmtx ) + + #define _MBG_MUTEX_DEFINED 1 + + #elif defined( MBG_TGT_FREEBSD ) // FreeBSD kernel space + + #include <sys/mutex.h> + + typedef struct mtx MBG_SPINLOCK; + #define _mbg_spin_lock_init( _spl ) mtx_init( _spl, "mbg_spin_lock", NULL, MTX_SPIN ) + #define _mbg_spin_lock_destroy( _spl ) mtx_destroy( _spl ) + #define _mbg_spin_lock_acquire( _spl ) mtx_lock_spin( _spl ) + #define _mbg_spin_lock_release( _spl ) mtx_unlock_spin( _spl ) + + #define MBG_SPINLOCK_DEFINED 1 + + + typedef struct mtx MBG_MUTEX; + #define _mbg_mutex_init( _pmtx ) mtx_init( _pmtx, "mbg_mutex", NULL, MTX_DEF ) + #define _mbg_mutex_destroy( _pmtx ) mtx_destroy( _pmtx ) + #define _mbg_mutex_acquire( _pmtx ) mtx_lock( _pmtx ) + #define _mbg_mutex_release( _pmtx ) mtx_unlock( _pmtx ) + + #define _MBG_MUTEX_DEFINED 1 + + #elif defined( MBG_TGT_NETBSD ) + + #include <sys/mutex.h> + + // The API used below has been introduced in NetBSD 5.0 + // For earlier NetBSD versions see 'man 9 lockinit'. + + typedef kmutex_t MBG_SPINLOCK; + #define _mbg_spin_lock_init( _spl ) mutex_init( _spl, MUTEX_DEFAULT, IPL_HIGH ) + #define _mbg_spin_lock_destroy( _spl ) mutex_destroy( _spl ) + #define _mbg_spin_lock_acquire( _spl ) mutex_spin_enter( _spl ) + #define _mbg_spin_lock_release( _spl ) mutex_spin_exit( _spl ) + + #define MBG_SPINLOCK_DEFINED 1 + + + typedef kmutex_t MBG_MUTEX; + #define _mbg_mutex_init( _pmtx ) mutex_init( _pmtx, MUTEX_DEFAULT, IPL_NONE ) + #define _mbg_mutex_destroy( _spl ) mutex_destroy( _spl ) + #define _mbg_mutex_acquire( _pmtx ) mutex_enter( _pmtx ) + #define _mbg_mutex_release( _pmtx ) mutex_exit( _pmtx ) + + #define _MBG_MUTEX_DEFINED 1 + + #endif + +#else // user space applications + + #if defined( MBG_TGT_WIN32 ) // Windows user space + + #include <windows.h> + + // definitions used with mutexes + typedef HANDLE MBG_MUTEX; + #define _mbg_mutex_init( _pm ) *(_pm) = CreateMutex( NULL, FALSE, NULL ) + #define _mbg_mutex_destroy( _pm ) CloseHandle( *(_pm) ); *(_pm) = INVALID_HANDLE_VALUE + #define _mbg_mutex_acquire( _pm ) WaitForSingleObject( *(_pm), INFINITE ) + #define _mbg_mutex_release( _pm ) ReleaseMutex( *(_pm) ) + + #define _MBG_MUTEX_DEFINED 1 + + // definitions used with critical sections + typedef CRITICAL_SECTION MBG_CRIT_SECT; + #define _mbg_crit_sect_init( _pcs ) InitializeCriticalSection( (_pcs) ) + #define _mbg_crit_sect_destroy( _pcs ) DeleteCriticalSection( (_pcs) ) + #define _mbg_crit_sect_enter( _pcs ) EnterCriticalSection( (_pcs) ) + #define _mbg_crit_sect_leave( _pcs ) LeaveCriticalSection( (_pcs) ) + + #define _MBG_CRIT_SECT_DEFINED 1 + + #elif defined( MBG_TGT_UNIX ) // Unix user space use pthread library + + #include <pthread.h> + + // Mutex types: + // PTHREAD_MUTEX_INITIALIZER /* Fast */ + // PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP /* Recursive */ + // PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP /* Errorcheck */ + typedef pthread_mutex_t MBG_MUTEX; + #define _mbg_mutex_init( _pm ) pthread_mutex_init( (_pm), NULL ) + #define _mbg_mutex_destroy( _pm ) pthread_mutex_destroy( (_pm) ) + #define _mbg_mutex_acquire( _pm ) pthread_mutex_lock( (_pm) ) + #define _mbg_mutex_release( _pm ) pthread_mutex_unlock( (_pm) ) + + #define _MBG_MUTEX_DEFINED 1 + + // For critical sections use defaults specified below + + #endif + +#endif + + +#if !defined( MBG_SPINLOCK_DEFINED ) + + #define _mbg_spin_lock_init( _spl ) _nop_macro_fnc() + #define _mbg_spin_lock_destroy( _spl ) _nop_macro_fnc() + #define _mbg_spin_lock_acquire( _spl ) _nop_macro_fnc() + #define _mbg_spin_lock_release( _spl ) _nop_macro_fnc() + +#endif + + +#if !defined( _MBG_MUTEX_DEFINED ) + + #define _MBG_MUTEX_DEFINED 1 + + typedef MBG_CRIT_SECT MBG_MUTEX; + + #define _mbg_mutex_init( _pm ) _nop_macro_fnc() + #define _mbg_mutex_destroy( _pm ) _nop_macro_fnc() + #define _mbg_mutex_acquire( _pm ) _nop_macro_fnc() + #define _mbg_mutex_release( _pm ) _nop_macro_fnc() + +#endif + + +#if !defined( _MBG_CRIT_SECT_DEFINED ) + + // use mutex by default, e.g. with the pthread library + + #define _MBG_CRIT_SECT_DEFINED 1 + + typedef MBG_MUTEX MBG_CRIT_SECT; + #define _mbg_crit_sect_init _mbg_mutex_init + #define _mbg_crit_sect_destroy _mbg_mutex_destroy + #define _mbg_crit_sect_enter _mbg_mutex_acquire + #define _mbg_crit_sect_leave _mbg_mutex_release + +#endif + + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + +/* (no header definitions found) */ + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBGMUTEX_H */ diff --git a/mbglib/common/mbgserio.c b/mbglib/common/mbgserio.c new file mode 100644 index 0000000..04dc045 --- /dev/null +++ b/mbglib/common/mbgserio.c @@ -0,0 +1,960 @@ + +/************************************************************************** + * + * $Id: mbgserio.c 1.3 2009/09/01 10:49:30Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Meinberg serial I/O functions. + * + * ----------------------------------------------------------------------- + * $Log: mbgserio.c $ + * Revision 1.3 2009/09/01 10:49:30Z martin + * Cleanup for CVI. + * Use new portable timeout functions from mbg_tmo.h. + * Timeouts are now specified in milliseconds. + * Set DOS/v24tools low level receive timeout to minimum on open. + * Let functions return predefined codes. + * Revision 1.2 2008/09/04 15:34:18Z martin + * Moved support for different target environments from other files here. + * Added mbgserio_set_parms() and don't set parms when opening a port. + * Fixed bugs in timeout calculations in mbgserio_read_wait(). + * Preliminary support for port device lists. + * Revision 1.1 2007/11/12 16:48:02 martin + * Initial revision. + * + **************************************************************************/ + +#define _MBGSERIO + #include <mbgserio.h> + + //##++ The following lines are required + // until mbgserio becomes a DLL: + #undef _MBG_API_ATTR + #define _MBG_API_ATTR + +#undef _MBGSERIO + +#include <stdio.h> +#include <ctype.h> +#include <time.h> + +#if defined( MBG_TGT_UNIX ) + #include <unistd.h> + #include <fcntl.h> +#endif + + + +#if defined( _USE_V24TOOLS ) + +/*------------------------------------------------------------------------ + * The definitions in this block and all v24...() functions are part of a + * third-party library called V.24 Tools Plus by Langner Expertensysteme. + * + * This library may no be distributed freely, so the v24..() functions + * must be replaced by user-written functions or some library available + * to the user of this demo. + *-----------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +int v24open( char *portname, int mode ); +/* Open a port with specified name (e.g. "COM1"). The functions return a + * handle to be used with the other functions. If the handle is < 0, the + * 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 OPEN_MODE ( O_DIRECT | O_HIGHPRIO ) + + +int v24setparams( int port, long speed, int dbits, int parity, int stopbits ); +/* Set the port's transmission speed, number of data bits, parity and + * number of stop bits. Returns 0 on success. + */ + +int v24qempty( int port, int which ); +/* Returns 1 if the receive buffer is empty, 0 if it is not, or an other + * value on error. + */ + +int v24getch( int port ); +/* Return a character from the receive buffer. + */ + +int v24putc( int port, char c ); +/* Write a character to the port. + */ + +int v24close( int port ); +/* Close the port + */ + +#ifdef __cplusplus +} +#endif + +#endif // defined( _USE_V24TOOLS ) + +/*------------------------------------------------------------------------*/ + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev ) +{ + MBG_PORT_HANDLE port_handle; + + #if defined( MBG_TGT_CVI ) + { + int data_bits = 8; //##++ + int parity_code = 0; + int baud_rate = 19200; + int stop_bits = 1; + int i; + int len; + int rc; + + // 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 + + + port_handle = atoi( &dev[i] ); + + rc = OpenComConfig (port_handle, NULL, baud_rate, parity_code, data_bits, stop_bits, 8192, 1024); //##++ + if ( rc < 0 ) + goto fail; + + pst->port_handle = port_handle; + + SetComTime( port_handle, 1.0 ); //##++ + SetXMode( port_handle, 0 ); + } + #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; + + + pst->port_handle = port_handle; + + // save original settings + pst->old_dcb.DCBlength = sizeof( pst->old_dcb ); + GetCommState( port_handle, &pst->old_dcb ); + GetCommTimeouts( port_handle, &pst->old_commtimeouts ); + + // configure our settings + 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 ); + #endif + + PurgeComm( port_handle, PURGE_TXABORT|PURGE_TXCLEAR ); + PurgeComm( port_handle, PURGE_RXABORT|PURGE_RXCLEAR ); + + //##++ mbgextio_set_console_control_handler(); + } + #elif defined( MBG_TGT_UNIX ) + { + // 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 ); + + //##++ 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 ( port_handle < 0 ) // check errno for the reason + goto fail; + + + pst->port_handle = port_handle; + + /* save current device settings */ + tcgetattr( port_handle, &pst->oldtio ); + + // atexit( port_deinit ); + + fflush( stdout ); //##++ + setvbuf( stdout, NULL, _IONBF, 0 ); + } + #elif defined( MBG_TGT_DOS ) + #if defined( _USE_V24TOOLS ) + { + port_handle = v24open( (char *) dev, OPEN_MODE ); + + if ( port_handle < 0 ) + goto fail; + + pst->port_handle = port_handle; + v24settimeout( port_handle, 1 ); + } + #else + + #error Target DOS requires v24tools for serial I/O. + + #endif + + #else + + #error This target OS is not supported. + + #endif + + return 0; + + +fail: + pst->port_handle = MBG_INVALID_PORT_HANDLE; + return MBGSERIO_FAIL; + +} // mbgserio_open + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgserio_close( SERIAL_IO_STATUS *pst ) +{ + if ( pst->port_handle != MBG_INVALID_PORT_HANDLE ) + { + MBG_PORT_HANDLE port_handle = pst->port_handle; + + #if defined( MBG_TGT_CVI ) + + CloseCom( port_handle ); + + #elif defined( MBG_TGT_WIN32 ) + + SetCommState( port_handle, &pst->old_dcb ); + SetCommTimeouts( port_handle, &pst->old_commtimeouts ); + CloseHandle( port_handle ); + + #elif defined( MBG_TGT_UNIX ) + + tcsetattr( port_handle, TCSANOW, &pst->oldtio ); + close( port_handle ); + + #elif defined( MBG_TGT_DOS ) + #if defined( _USE_V24TOOLS ) + + v24close( port_handle ); + + #else + + #error Target DOS requires v24tools for serial I/O. + + #endif + + #else + + #error This target OS is not supported. + + #endif + + pst->port_handle = MBG_INVALID_PORT_HANDLE; + } + + return 0; + +} // mbgserio_close + + + +/*HDR*/ +_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; + int i = 0; + + (*list) = (MBG_STR_LIST *) malloc( sizeof( **list ) ); + memset( (*list), 0, sizeof( **list ) ); + + list_head = (*list); + + for ( i = 0; i < max_devs; i++ ) + { + SERIAL_IO_STATUS iost; + char dev_name[100] = { 0 }; + int rc; + + #if defined( MBG_TGT_WIN32 ) + sprintf( dev_name, "COM%i", i + 1 ); + #elif defined( MBG_TGT_LINUX ) + sprintf( dev_name, "/dev/ttyS%i", i ); + #endif + + rc = mbgserio_open( &iost, dev_name ); + + if ( rc < 0 ) + continue; + + mbgserio_close( &iost ); + + (*list)->s = (char *) malloc( strlen( dev_name ) + 1 ); + strcpy( (*list)->s, dev_name ); + + (*list)->next = (MBG_STR_LIST *) malloc( sizeof( **list ) ); + (*list) = (*list)->next; + + memset( (*list), 0, sizeof( **list ) ); + n++; + +// if ( ++i >= MBG_MAX_DEVICES ) +// break; + } + + if ( n == 0 ) + { + free( *list ); + list_head = NULL; + } + + *list = list_head; + + return n; + +} // mbgserio_setup_port_str_list + + + +/*HDR*/ +_MBG_API_ATTR void _MBG_API _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list ) +{ + int i = 0; + + while ( i < 1000 ) //##++ + { + if ( list ) + { + if ( list->s ) + { + free( list->s ); + list->s = NULL; + } + + if ( list->next ) + { + MBG_STR_LIST *next = list->next; + free( list ); + list = next; + } + else + { + if ( list ) + { + free( list ); + list = NULL; + } + break; + } + } + else + break; + + i++; + } + +} // mbgserio_free_str_list + + + +/*HDR*/ +_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; + + #if defined( MBG_TGT_CVI ) + { + int data_bits = 8; + int parity_code = 0; + int stop_bits = 1; + int rc; + + // setup framing. + for ( cp = framing; *cp; cp++ ) + { + char c = toupper( *cp ); + + switch ( c ) + { + case '7': + case '8': + data_bits = c - '0'; + break; + + case 'N': + parity_code = 0; + break; + + case 'E': + parity_code = 2; + break; + + case 'O': + parity_code = 1; + break; + + case '1': + case '2': + stop_bits = c - '0'; + break; + + default: + return MBGSERIO_INV_CFG; // invalid framing string + } + } + + rc = OpenComConfig( port_handle, NULL, baud_rate, parity_code, + data_bits, stop_bits, 8192, 1024 ); + if ( rc < 0 ) + return rc; + + SetComTime( port_handle, 1.0 ); //##++ + SetXMode( port_handle, 0 ); + } + #elif defined( MBG_TGT_WIN32 ) + { + DCB dcb; + + dcb.DCBlength = sizeof( DCB ) ; + GetCommState( port_handle, &dcb ) ; + dcb.BaudRate = baud_rate; + + + // setup framing. + for ( cp = framing; *cp; cp++ ) + { + char c = toupper( *cp ); + + switch ( c ) + { + case '7': + case '8': + dcb.ByteSize = c - '0'; + break; + + case 'N': + dcb.Parity = NOPARITY; + break; + + case 'E': + dcb.Parity = EVENPARITY; + break; + + case 'O': + dcb.Parity = ODDPARITY; + break; + + case '1': + dcb.StopBits = ONESTOPBIT; + break; + + case '2': + dcb.StopBits = TWOSTOPBITS; + break; + + default: + return MBGSERIO_INV_CFG; // invalid framing string + } + } + + + 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 ); + } + #elif defined( MBG_TGT_UNIX ) + { + tcflag_t c_cflag = 0; + struct termios tio; + + tcgetattr( port_handle, &tio ); + + // setup transmission speed + switch( baud_rate ) + { + case 300: c_cflag = B300; break; + case 600: c_cflag = B600; break; + case 1200: c_cflag = B1200; break; + case 2400: c_cflag = B2400; break; + case 4800: c_cflag = B4800; break; + case 9600: c_cflag = B9600; break; + case 19200: c_cflag = B19200; break; + case 38400: c_cflag = B38400; break; + case 57600: c_cflag = B57600; break; + + default: return MBGSERIO_INV_CFG; // invalid + } + + #if 0 //##++ This should be used preferably for portability reasons + int cfsetispeed( struct termios *termios_p, speed_t speed ); + int cfsetospeed( struct termios *termios_p, speed_t speed ); + #endif + + // setup framing. + for ( cp = framing; *cp; cp++ ) + { + switch ( _toupper( *cp ) ) + { + case '7': c_cflag |= CS7; break; + case '8': c_cflag |= CS8; break; + + case 'N': break; + case 'E': c_cflag |= PARENB; break; + case 'O': c_cflag |= PARENB | PARODD; break; + + case '1': break; + case '2': c_cflag |= CSTOPB; break; + + default: return MBGSERIO_INV_CFG; // invalid framing string + } + } + + + // Setup control flags. The following flags are defined: + // CBAUD (not in POSIX) Baud speed mask (4+1 bits). + // CBAUDEX (not in POSIX) Extra baud speed mask (1 bit), included in CBAUD. + // (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, + // 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. + // CREAD Enable receiver. + // PARENB Enable parity generation on output and parity checking for input. + // PARODD Parity for input and output is odd. + // HUPCL Lower modem control lines after last process closes the device (hang up). + // CLOCAL Ignore modem control lines. + // LOBLK (not in POSIX) Block output from a noncurrent shell layer. + // (For use by shl) + // CIBAUD (not in POSIX) Mask for input speeds. The values for the CIBAUD bits are + // the same as the values for the CBAUD bits, shifted left IBSHIFT bits. + // CRTSCTS (not in POSIX) Enable RTS/CTS (hardware) flow control. + + // local connection, no modem control (CLOCAL) + // no flow control (no CRTSCTS) + // enable receiving + tio.c_cflag = c_cflag | CLOCAL | CREAD; + + + // 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 + // queues to be flushed, and if the terminal is the controlling + // 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 + // is set, read a character with a parity error or framing error as \0. + // INPCK Enable input parity checking. + // ISTRIP Strip off eighth bit. + // INLCR Translate NL to CR on input. + // IGNCR Ignore carriage return on input. + // ICRNL Translate carriage return to newline on input (unless IGNCR is set). + // IUCLC (not in POSIX) Map uppercase characters to lowercase on input. + // IXON Enable XON/XOFF flow control on output. + // IXANY (not in POSIX.1; XSI) Enable any character to restart output. + // IXOFF Enable XON/XOFF flow control on input. + // IMAXBEL (not in POSIX) Ring bell when input queue is full. Linux does not + // implement this bit, and acts as if it is always set. + tio.c_iflag = 0; + + #if 0 //##++ + if ( c_cflag & PARENB ) + tio.c_iflag |= IGNPAR; //##++ this also ignores framing errors + #endif + + + // Setup output flags. The following flags are defined: + // OPOST Enable implementation-defined output processing. + // The remaining c_oflag flag constants are defined in POSIX 1003.1-2001, + // unless marked otherwise. + // OLCUC (not in POSIX) Map lowercase characters to uppercase on output. + // ONLCR (XSI) Map NL to CR-NL on output. + // OCRNL Map CR to NL on output. + // 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, + // 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 + // spaces (with tab stops every eight columns). + // 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. + tio.c_oflag = 0; + + + // Setup local mode flags. The following flags are defined: + // ISIG When any of the characters INTR, QUIT, SUSP, or DSUSP are + // received, generate the corresponding signal. + // ICANON Enable canonical mode. This enables the special characters + // 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 + // characters are converted to uppercase. + // ECHO Echo input characters. + // 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 + // signal. For example, character 0x08 (BS) is echoed as ^H. + // 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 + // 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 + // 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. + // (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, + // 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 + // 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, + // 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 + // 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, + // which signifies end-of-file. Recognized when ICANON is set, and + // then not passed as input. + // VMIN Minimum number of characters for non-canonical read. + // VEOL (0, NUL) Additional end-of-line character. Recognized when ICANON is set. + // VTIME Timeout in deciseconds for non-canonical read. + // VEOL2 (not in POSIX; 0, NUL) Yet another end-of-line character. + // Recognized when ICANON is set. + // VSWTCH (not in POSIX; not supported under Linux; 0, NUL) Switch character. + // (Used by shl only.) + // VSTART (021, DC1, Ctrl-Q) Start character. Restarts output stopped by the Stop + // character. Recognized when IXON is set, and then not passed as input. + // VSTOP (023, DC3, Ctrl-S) Stop character. Stop output until Start character + // 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 + // suspend character: send SIGTSTP signal when the character is read by + // 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 + // when IEXTEN is set, and then not passed as input. + // VWERASE (not in POSIX; 027, ETB, Ctrl-W) Word erase. Recognized when ICANON + // 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: + // 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 + // 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 + // 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 + // time between two characters exceeds TIME. The timer is restarted + // 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 + // fcntl(fd, F_SETFL, FNDELAY); before reading to get the same result. + + // setup control characters for non-blocking read + tio.c_cc[VMIN] = 0; + 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 ); + + fflush( stdout ); + setvbuf( stdout, NULL, _IONBF, 0 ); + } + #elif defined( MBG_TGT_DOS ) + #if defined( _USE_V24TOOLS ) + { + int datab = 8; + char parity = 'N'; + int stopb = 1; + + // setup framing. + for ( cp = framing; *cp; cp++ ) + { + char c = toupper( *cp ); + + switch ( c ) + { + case '7': + case '8': + datab = c - '0'; + break; + + case 'N': + case 'E': + case 'O': + parity = *cp; + break; + + case '1': + case '2': + stopb = c - '0'; + break; + + default: + return MBGSERIO_INV_CFG; // invalid framing string + } + } + + v24setparams( port_handle, baud_rate, datab, parity, stopb ); + } + #else + + #error This has to be modified for DOS without v24tools. + + #endif + + #else + + #error This target OS is not supported. + + #endif + + return 0; + +} // 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 ) +{ + BOOL fReadStat; + COMSTAT ComStat; + DWORD dwErrorFlags; + DWORD dwLength; + + ClearCommError( h, &dwErrorFlags, &ComStat ); + + if ( dwErrorFlags ) // transmission error (parity, framing, etc.) + return MBGSERIO_FAIL; + + + dwLength = min( (DWORD) count, ComStat.cbInQue ); + + if ( dwLength ) + { + fReadStat = ReadFile( h, buffer, dwLength, &dwLength, NULL ); + + if ( !fReadStat ) + return MBGSERIO_FAIL; + } + + return dwLength; + +} // mbgserio_read + + + +/*HDR*/ +_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; + + while ( dwTotalBytesWritten < (DWORD) count ) + { + dwThisBytesWritten = 0; + + fWriteStat = WriteFile( h, ( (char *) buffer ) + dwTotalBytesWritten, + count - dwTotalBytesWritten, + &dwThisBytesWritten, NULL ); + if ( !fWriteStat ) + { + #if defined( _DEBUG ) + DWORD dw = GetLastError(); + #endif + break; //##++ Error: Unable to write + } + + dwTotalBytesWritten += dwThisBytesWritten; + + ClearCommError( h, &dwErrorFlags, &ComStat ); + + if ( dwErrorFlags ) + break; //#++ Error: Check flags + } + + return dwTotalBytesWritten; + +} // mbgserio_write + +#endif // defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_CVI ) + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, + uint count, ulong char_timeout ) +{ + int n_bytes; + + #if _USE_SELECT_FOR_SERIAL_IO + + struct timeval tv_char_timeout; + fd_set fds; + int rc; + + mbgserio_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 ( rc < 0 ) // error + goto fail; + + if ( rc == 0 ) // timeout + goto timeout; + + // data is available + n_bytes = _mbgserio_read( h, buffer, count ); + + #else + MBG_TMO_TIME tmo; + + mbg_tmo_set_timeout_ms( &tmo, char_timeout ); + + for (;;) // wait to read one new char + { + n_bytes = _mbgserio_read( h, buffer, count ); + + if ( n_bytes > 0 ) // new char(s) received + break; + + if ( n_bytes < 0 ) // error + goto fail; + + if ( mbg_tmo_curr_time_is_after( &tmo ) ) + goto timeout; + + #if defined( MBG_TGT_UNIX ) + usleep( 10 * 1000 ); + #endif + } + #endif + + return n_bytes; + +timeout: + return MBGSERIO_TIMEOUT; + +fail: + return MBGSERIO_FAIL; + +} // mbgserio_read_wait + + + diff --git a/mbglib/common/mbgserio.h b/mbglib/common/mbgserio.h new file mode 100644 index 0000000..28afa96 --- /dev/null +++ b/mbglib/common/mbgserio.h @@ -0,0 +1,213 @@ + +/************************************************************************** + * + * $Id: mbgserio.h 1.4 2009/09/01 10:54:29Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for mbgserio.c. + * + * ----------------------------------------------------------------------- + * $Log: mbgserio.h $ + * Revision 1.4 2009/09/01 10:54:29Z martin + * Include mbg_tmo.h for the new portable timeout functions. + * Added symbols for return codes in case of an error. + * Code cleanup. + * Revision 1.3 2009/04/01 14:17:31 martin + * Cleanup for CVI. + * Revision 1.2 2008/09/04 15:11:36Z martin + * Preliminary support for device lists. + * Updated function prototypes. + * Revision 1.1 2007/11/12 16:48:02 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBGSERIO_H +#define _MBGSERIO_H + + +/* Other headers to be included */ + +#include <mbg_tmo.h> + +#include <stdlib.h> +#include <string.h> + +#if defined( MBG_TGT_UNIX ) + #include <termios.h> +#endif + +#if _USE_CHK_TSTR + #include <chk_tstr.h> +#endif + +#if !defined( _USE_SELECT_FOR_SERIAL_IO ) + #if defined( MBG_TGT_UNIX ) + #define _USE_SELECT_FOR_SERIAL_IO 1 + #else + #define _USE_SELECT_FOR_SERIAL_IO 0 + #endif +#endif + + +#ifdef _MBGSERIO + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* 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" + #elif defined( MBG_TGT_LINUX ) + #define DEFAULT_DEV_NAME "/dev/ttyS0" + #endif +#endif + + +/* + * The following macros control parts of the build process. + * The default values are suitable for most cases but can be + * overridden by global definitions, if required. + */ + +#if _IS_MBG_FIRMWARE + + // This handle type in not used by the firmware. + // However, we define it to avoid build errors. + typedef int MBG_HANDLE; + +#else + + #if defined( MBG_TGT_CVI ) + + #include <rs232.h> + + #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 <windows.h> + #include <io.h> + + #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 <unistd.h> + + #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 <v24tools.h> + + #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 + + + +typedef struct _MBG_STR_LIST +{ + char *s; + struct _MBG_STR_LIST *next; + +} MBG_STR_LIST; + + + +typedef struct +{ + MBG_PORT_HANDLE port_handle; // the handle that will be used for the device + + #if defined( MBG_TGT_WIN32 ) + DCB old_dcb; + COMMTIMEOUTS old_commtimeouts; + #endif + #if defined( MBG_TGT_UNIX ) + struct termios oldtio; + //##++ struct termios newtio; + #endif + +} SERIAL_IO_STATUS; + + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* 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 ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBGSERIO_H */ diff --git a/mbglib/common/pcpsdefs.h b/mbglib/common/pcpsdefs.h new file mode 100644 index 0000000..c30bffd --- /dev/null +++ b/mbglib/common/pcpsdefs.h @@ -0,0 +1,1273 @@ + +/************************************************************************** + * + * $Id: pcpsdefs.h 1.46 2011/01/13 11:44:29Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * General definitions for Meinberg plug-in radio clocks + * + * ----------------------------------------------------------------------- + * $Log: pcpsdefs.h $ + * Revision 1.46 2011/01/13 11:44:29Z martin + * Moved status port register definitions here. + * Revision 1.45 2010/09/06 07:36:24 martin + * Support GPS180PEX and TCR180PEX. + * Moved some IRIG related definitions to gpsdefs.h. + * Revision 1.44 2010/06/30 11:09:49 martin + * Added definitions for JJY longwave transmitter. + * Renamed MBG_RAW_IRIG_DATA::data field to data_bytes + * since "data" is a reserved word for C51 architecture. + * Revision 1.43 2010/02/09 11:20:17Z martin + * Renamed yet unused CORR_INFO::flags field to signal and updated comments. + * Revision 1.42 2010/01/12 14:02:37 daniel + * Added definitions to support reading the raw IRIG data bits. + * Revision 1.41 2009/06/19 12:16:42Z martin + * Added PCPS_GIVE_IRIG_TIME command and associated definitions. + * Revision 1.40 2009/06/08 19:29:11 daniel + * Support PTP configuration. + * Support LAN_IF configuration + * Added definition of PCPS_CMD_INFO. + * Revision 1.39 2009/03/19 08:58:09 martin + * Added PCPS_GET_IRIG_CTRL_BITS cmd and associated data type. + * Revision 1.38 2009/03/10 17:07:09 martin + * Support configurable time scales and GPS UTC parameters. + * Added ext. status flag for time scales, and PCPS_LS_ANN_NEG. + * Added bit mask PCPS_SCALE_MASK. + * Revision 1.37 2008/12/05 16:01:37Z martin + * Added ref types PTP, FRC, and WWVB. + * Added ref names MSF, PTP, FRC, and WWVB. + * Added device codes TCR170PEX, PTP270PEX, and FRC511PEX. + * Added macros to convert the endianess of structures. + * Moved definitions of PCPS_HRT_FRAC_SCALE and + * PCPS_HRT_FRAC_SCALE_FMT here. + * Added definitions of PCPS_HRT_FRAC_CONVERSION_TYPE + * and PCPS_HRT_BIN_FRAC_SCALE. + * Escaped '<' and '>' characters for doxygen. + * Modified comments for PCPS_TZDL. + * Removed trailing spaces and obsolete comments. + * Revision 1.36 2008/01/17 09:20:25Z daniel + * Added new REF type PCPS_REF_MSF. + * Revision 1.35 2008/01/17 09:18:46Z daniel + * Made comments compatible for doxygen parser. + * No sourcecode changes. + * Revision 1.34 2007/07/17 08:22:47Z martin + * Added support for TCR511PEX and GPS170PEX. + * Revision 1.33 2007/05/20 21:39:51Z martin + * Added support for PEX511. + * Added PCPS_GET_STATUS_PORT cmd code for devices + * that do not support a hardware status port. + * Revision 1.32 2007/03/29 12:57:32Z martin + * Renamed some TZCODE numbers for unique naming conventions. + * Added definitions of the older symbols for compatibility. + * Revision 1.31 2007/03/26 15:42:31Z martin + * Replaced PCPS_REF_OFFS and associated definitions by MBG_REF_OFFS, etc., + * which are defined in gpsdefs.h. + * Added PCPS_GET_DEBUG_STATUS code. + * Revision 1.30 2006/06/29 10:13:13 martin + * Added some descriptive comments. + * Revision 1.29 2006/06/14 12:59:12Z martin + * Added support for TCR511PCI. + * Revision 1.28 2006/05/18 09:45:16 martin + * Added data types used with PZF receivers. + * Revision 1.27 2006/05/03 10:19:14Z martin + * Added initializers for reference source names. + * Revision 1.26 2006/03/10 10:24:45Z martin + * New definitions for PCI511. + * Added command codes to configure programmable pulse outputs. + * Revision 1.25 2005/11/03 15:05:16Z martin + * New definitions for GPS170PCI. + * New types PCPS_TIME_STATUS and PCPS_TIME_STATUS_X. + * Removed obsolete enumeration of PCPS_TIME fields. + * Revision 1.24 2005/05/03 07:56:55Z martin + * Added command PCPS_GET_SYNTH_STATE. + * Revision 1.23 2005/03/29 12:51:10Z martin + * New cmd code PCPS_GENERIC_IO. + * Revision 1.22 2004/12/09 11:03:37Z martin + * Support configuration of on-board frequency synthesizer. + * Revision 1.21 2004/11/09 12:55:32Z martin + * Redefined interface data types using C99 fixed-size definitions. + * Added workaround macros for some structure sizes because the C166 + * compiler always reports an even structure size even if the structure + * size is in fact odd, which might lead to different sizes in C166 and + * other environments. + * Modifications were required in order to be able to configure IRIG + * settings of cards which provide both IRIG input and output. + * The existing codes have been renamed with .._RX.. and are used to + * configure the IRIG receiver (input). New codes have been defined + * used to configure the IRIG transmitter. + * Renamed PC_GPS_STAT to PC_GPS_BVAR_STAT. + * Use more specific data types than generic types. + * Revision 1.20 2004/10/14 15:01:23 martin + * Added support for TCR167PCI. + * Revision 1.19 2004/06/16 12:46:33Z martin + * Moved OPT_SETTINGS related definitions to gpsdefs.h, + * and renamed symbols from PCPS_.. to to MBG_... + * Revision 1.18 2004/04/26 14:27:08Z martin + * Added union PCPS_TIME_UNION. + * Revision 1.17 2003/05/27 08:50:35Z MARTIN + * New commands PCPS_GIVE_UCAP_ENTRIES, PCPS_GIVE_UCAP_EVENT + * and associated definitions which allow faster reading of + * user capture events and monitoring of the capture buffer + * fill level. + * Revision 1.16 2003/04/03 10:48:53 martin + * Support for PCI510, GPS169PCI, and TCR510PCI. + * New codes PCPS_GET_REF_OFFS, PCPS_SET_REF_OFFS + * and related structures. + * New codes PCPS_GET_OPT_INFO, PCPS_SET_OPT_SETTINGS + * and related structures. + * New codes PCPS_GET_IRIG_INFO, PCPS_SET_IRIG_SETTINGS. + * Preliminary PCPS_TZDL structure and cmd codes + * to read/write that structure. + * Revision 1.15 2002/08/08 13:24:03 MARTIN + * Moved definition of ref time sources here. + * Added new ref time source IRIG. + * Added new cmd to clear time capture buffer. + * Fixed some comments. + * Revision 1.14 2002/01/31 13:39:38 MARTIN + * Added new GPS data type codes for RECEIVER_INFO, etc. + * New PCPS_HR_TIME status flag PCPS_IO_BLOCKED. + * Moved REV_NUMs defining special features to pcpsdev.h. + * Removed obsolete initializer for framing string table. + * Updated some comments. + * Removed obsolete code. + * Revision 1.13 2001/12/03 16:15:14 martin + * Introduced PCPS_TIME_STAMP which allows to handle high precision + * time stamps. + * Replaced the sec/frac fields in PCPS_HR_TIME by PCPS_TIME_STAMP. + * This is compatible on byte level but may require source code + * modifications. + * Introduced new command PCPS_SET_EVENT_TIME which is used + * EXCLUSIVELY with a custom GPS firmware. + * Revision 1.12 2001/10/16 10:07:42 MARTIN + * Defined PCI509 firmware revision number which supports + * baud rate higher than standard. + * Revision 1.11 2001/03/30 13:02:39 MARTIN + * Control alignment of structures from new file use_pack.h. + * Defined initializers with valid framing parameters. + * Revision 1.10 2001/02/28 15:39:25 MARTIN + * Modified preprocessor syntax. + * Revision 1.9 2001/02/16 11:32:05 MARTIN + * Renamed "PROM" or "EPROM" in comments or and names to + * "FW" or firmware. + * This includes the cmd codes PCPS_GIVE_PROM_ID_... which have + * been renamed to PCPS_GIVE_FW_ID_... + * Renamed structure PCPS_TIME_SET to PCPS_STIME. + * Renamed return code PCPS_ERR_NONE to PCPS_SUCCESS. + * Modified some comments. + * Revision 1.8 2000/10/11 09:17:09 MARTIN + * Cleaned up comment syntax. + * Revision 1.7 2000/07/21 14:16:30 MARTIN + * Modified some comments. + * Added PCI definitions. + * Renamed PCPS_GET_GPS_DATA to PCPS_READ_GPS_DATA. + * Renamed PCPS_SET_GPS_DATA to PCPS_WRITE_GPS_DATA. + * New types PCPS_SERIAL and PCPS_TZCODE. + * Removed PCPS_SERIAL_BYTES and PCPS_TZCODE_BYTES, may use sizeof() + * the types instead. + * New type PCPS_TIME_SET which can be used to write date and time + * to the clock. + * Revision 1.6 2000/06/07 12:09:31 MARTIN + * renamed PCPS_SERIAL_GROUP to PCPS_CFG_GROUP + * renamed PCPS_ERR_SERIAL to PCPS_ERR_CFG + * modified definitions for baud rate, framing, and mode + * added PCPS_SN_... definitions + * added PCPS_GET_TZCODE and PCPS_SET_TZCODE definitions + * added PC_GPS_ANT_CABLE_LEN definition + * added RCS keywords + * updated some comments + * + * ----------------------------------------------------------------------- + * Changes before put under RCS control: + * + * Revision 1.5 2000/03/24 + * Introduced PCPS_GIVE_SERNUM + * Cleaned up for definitions for serial parameter byte + * Reviewed and updated comments. + * + * 1998/07/22 + * Introduced PCPS_HR_TIME. + * Rearranged order of definitions. + * Reviewed and updated comments. + * + * 1997/06/12 + * GPS definitions added. + * + * 1996/01/25 + * PCPS_TIME redefined from an array of bytes to a structure. + * + **************************************************************************/ + +#ifndef _PCPSDEFS_H +#define _PCPSDEFS_H + + +/* Other headers to be included */ + +#include <words.h> +#include <use_pack.h> + + +/* Start of header body */ + +#if defined( _USE_PACK ) // set byte alignment + #pragma pack( 1 ) +#endif + + +/** + * The following codes enumerate the ref time sources + * from which the clocks receive the reference time. + */ +enum +{ + PCPS_REF_NONE, /**< (unknown or not defined) */ + PCPS_REF_DCF, /**< see http://www.meinberg.de/english/info/dcf77.htm */ + PCPS_REF_GPS, /**< see http://www.meinberg.de/english/info/gps.htm */ + PCPS_REF_IRIG, /**< see http://www.meinberg.de/english/info/irig.htm */ + PCPS_REF_MSF, /**< MSF Receiver (UK) */ + PCPS_REF_PTP, /**< PTP 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 */ +}; + + +/* Initializers for the reference source names */ + +#define PCPS_REF_NAME_NONE_ENG "unknown" +#define PCPS_REF_NAME_NONE_GER "nicht bekannt" +#define PCPS_REF_NAME_DCF "DCF77" +#define PCPS_REF_NAME_GPS "GPS" +#define PCPS_REF_NAME_IRIG "IRIG" +#define PCPS_REF_NAME_MSF "MSF" +#define PCPS_REF_NAME_PTP "PTP" +#define PCPS_REF_NAME_FRC "FRC" +#define PCPS_REF_NAME_WWVB "WWVB" +#define PCPS_REF_NAME_JJY "JJY" + + +#define PCPS_REF_NAMES_ENG \ +{ \ + PCPS_REF_NAME_NONE_ENG, \ + PCPS_REF_NAME_DCF, \ + PCPS_REF_NAME_GPS, \ + PCPS_REF_NAME_IRIG, \ + PCPS_REF_NAME_MSF, \ + PCPS_REF_NAME_PTP, \ + PCPS_REF_NAME_FRC, \ + PCPS_REF_NAME_WWVB, \ + PCPS_REF_NAME_JJY \ +} + + +#define PCPS_REF_NAMES_LSTR \ +{ \ + { PCPS_REF_NAME_NONE_ENG, PCPS_REF_NAME_NONE_GER }, \ + { PCPS_REF_NAME_DCF, NULL }, \ + { PCPS_REF_NAME_GPS, NULL }, \ + { PCPS_REF_NAME_IRIG, NULL }, \ + { PCPS_REF_NAME_MSF, NULL }, \ + { PCPS_REF_NAME_PTP, NULL }, \ + { PCPS_REF_NAME_FRC, NULL }, \ + { PCPS_REF_NAME_WWVB, NULL }, \ + { PCPS_REF_NAME_JJY, NULL } \ +} + + + +/** + PCI vendor ID number (assigned by PCI SIG) +*/ +#define PCI_VENDOR_MEINBERG 0x1360 + +/* PCI device ID numbers (assigned by Meinberg) * + * High byte: type of ref time source + * Low Byte: enumeration of device types + */ +#define PCI_DEV_PCI32 ( ( PCPS_REF_DCF << 8 ) | 0x01 ) +#define PCI_DEV_PCI509 ( ( PCPS_REF_DCF << 8 ) | 0x02 ) +#define PCI_DEV_PCI510 ( ( PCPS_REF_DCF << 8 ) | 0x03 ) +#define PCI_DEV_PCI511 ( ( PCPS_REF_DCF << 8 ) | 0x04 ) +#define PCI_DEV_PEX511 ( ( PCPS_REF_DCF << 8 ) | 0x05 ) + +#define PCI_DEV_GPS167PCI ( ( PCPS_REF_GPS << 8 ) | 0x01 ) +#define PCI_DEV_GPS168PCI ( ( PCPS_REF_GPS << 8 ) | 0x02 ) +#define PCI_DEV_GPS169PCI ( ( PCPS_REF_GPS << 8 ) | 0x03 ) +#define PCI_DEV_GPS170PCI ( ( PCPS_REF_GPS << 8 ) | 0x04 ) +#define PCI_DEV_GPS170PEX ( ( PCPS_REF_GPS << 8 ) | 0x05 ) +#define PCI_DEV_GPS180PEX ( ( PCPS_REF_GPS << 8 ) | 0x06 ) + +#define PCI_DEV_TCR510PCI ( ( PCPS_REF_IRIG << 8 ) | 0x01 ) +#define PCI_DEV_TCR167PCI ( ( PCPS_REF_IRIG << 8 ) | 0x02 ) +#define PCI_DEV_TCR511PCI ( ( PCPS_REF_IRIG << 8 ) | 0x03 ) +#define PCI_DEV_TCR511PEX ( ( PCPS_REF_IRIG << 8 ) | 0x04 ) +#define PCI_DEV_TCR170PEX ( ( PCPS_REF_IRIG << 8 ) | 0x05 ) +#define PCI_DEV_TCR180PEX ( ( PCPS_REF_IRIG << 8 ) | 0x06 ) + +#define PCI_DEV_PTP270PEX ( ( PCPS_REF_PTP << 8 ) | 0x01 ) + +#define PCI_DEV_FRC511PEX ( ( PCPS_REF_FRC << 8 ) | 0x01 ) + + + +// definitions used for the status port register +// (not to be intermixed with PCPS_TIME_STATUS) +typedef uint8_t PCPS_STATUS_PORT; /**< see \ref group_status_port "Bitmask" */ + +/** @defgroup group_status_port Bit masks of PCPS_STATUS_PORT + + Bit definitions used with the #PCPS_STATUS_PORT register. + + The flags #PCPS_ST_SEC and #PCPS_ST_MIN are cleared whenever the clock + is read, so they are not very reliable in multitasking environments. + + <b>NOTE</b>: The PCPS_ST_IRQF flag originates from old ISA cards. + Some PCI cards also support this, but in case of PCI cards the + associated flag of the PCI interface chip should be checked to see + if a certain card has generated an IRQ on the PC bus. + + The macro _pcps_ddev_has_gen_irq() cares about this and should be used + to determine in a portable way whether a card has generated an IRQ. + + * @{ + */ + +#define PCPS_ST_BUSY 0x01 /**< the clock is busy filling the output FIFO */ +#define PCPS_ST_IRQF 0x02 /**< the clock has generated an IRQ on the PC bus (ISA only)*/ +#define PCPS_ST_MOD 0x20 /**< the raw demodulated DCF77 signal */ +#define PCPS_ST_SEC 0x40 /**< seconds have changed since last reading */ +#define PCPS_ST_MIN 0x80 /**< minutes have changed since last reading */ + +/** @} */ + + + +/** @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<br> + Return a PCPS_TIME structure with current date, + time and status. Supported by all clocks. + + - #PCPS_GIVE_TIME_NOCLEAR<br> + Same as #PCPS_GIVE_TIME but the bits #PCPS_ST_SEC + and #PCPS_ST_MIN (see pcpsdev.h) of the status + port are not cleared. + Supported by all clocks except PC31/PS31 with + firmware version older than v3.0. + This is mainly used by the DOS TSR and should + not be used in other environments. + + - #PCPS_GIVE_SYNC_TIME<br> + Return a ::PCPS_TIME structure with date and time + of last synchronization of the clock or + the last time set via the interface. + _pcps_has_sync_time() checks whether supported. + + - #PCPS_GIVE_HR_TIME<br> + Return a PCPS_HR_TIME structure with current + date, time and status. This command should be + used to read the clock with higher resolution. + _pcps_has_hr_time() checks whether supported. + + - #PCPS_GIVE_IRIG_TIME<br> + Return a PCPS_IRIG_TIME structure with day-of-year, + time and status as decoded from the IRIG signal. + _pcps_has_irig_time() checks whether supported. + + - #PCPS_SET_TIME<br> + Set the board date, time and status. This + command expects sizeof( ::PCPS_STIME ) parameter + bytes. + _pcps_can_set_time() checks whether supported. + + - #PCPS_SET_EVENT_TIME<br> + Send a high resolution time stamp to the clock to + configure a UTC time when the clock shall generate + some event. This command expects a PCPS_TIME_STAMP + parameter. + _pcps_has_event_time() checks whether supported. + (requires custom GPS CERN firmware) + + - #PCPS_IRQ_NONE<br> + Disable the board's hardware IRQ<br> + - #PCPS_IRQ_1_SEC<br> + Enable hardware IRQs once per second<br> + - #PCPS_IRQ_1_MIN<br> + Enable hardware IRQs once per minute<br> + - #PCPS_IRQ_10_MIN<br> + Enable hardware IRQs once per 10 minutes<br> + - #PCPS_IRQ_30_MIN<br> + Enable hardware IRQs once per 30 minutes<br> + + - #PCPS_GET_SERIAL<br> + #PCPS_SET_SERIAL<br> + These commands read or set the configuration + of a clock's serial port COM0. The commands + expect PCPS_SERIAL_BYTES parameter bytes and + should be used preferably with the DCF77 + clocks which have only one COM port. + _pcps_has_serial() checks whether supported. + Recent GPS clocks' COM ports should be cfg'd + using the structures RECEIVER_INFO, PORT_INFO, + and STR_TYPE_INFO. + _pcps_has_receiver_info() checks whether + these are supported. If they are not, then + the code #PC_GPS_PORT_PARM together with the + #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA + commands should be used. + + - #PCPS_GET_TZCODE<br> + #PCPS_SET_TZCODE<br> + These commands read or set a DCF77 clock's + time zone code and should be used preferably + with the newer DCF77 clocks which have limited + support of different time zones. + _pcps_has_tzcode() checks whether supported. + A GPS clock's time zone must be cfg'd using + the code #PC_GPS_TZDL together with the + #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA + commands. + + - #PCPS_GET_PCPS_TZDL<br> + #PCPS_SET_PCPS_TZDL<br> + These commands read or set a DCF77 clock's + time zone / daylight saving configuration. + _pcps_has_pcps_tzdl() checks whether supported. + A GPS clock's time zone must be cfg'd using + the code #PC_GPS_TZDL together with the + #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA + commands. + + - #PCPS_GET_REF_OFFS<br> + #PCPS_SET_REF_OFFS<br> + These commands can be used to configure the + reference time offset from UTC for clocks + which can't determine the offset automatically, + e.g. from an IRIG input signal. + _pcps_has_ref_offs() checks whether supported. + + - #PCPS_GET_OPT_INFO<br> + #PCPS_SET_OPT_SETTINGS<br> + These commands can be used to configure some + optional settings, controlled by flags. + When reading, the clock returns a MBG_OPT_INFO + structure which contains the supported values, + plus the current settings. + When writing, clocks accepts a MBG_OPT_SETTINGS + structure only which contain the desired settings + of the supported flags only. + _pcps_has_opt_flags() checks whether supported. + + - #PCPS_GET_IRIG_RX_INFO<br> + #PCPS_SET_IRIG_RX_SETTINGS<br> + #PCPS_GET_IRIG_TX_INFO<br> + #PCPS_SET_IRIG_TX_SETTINGS<br> + These commands can be used to configure IRIG + inputs and outputs.<br> + When reading, the clock returns an IRIG_INFO + structure which contains the supported values, + plus the current settings.<br> + When writing, clocks accepts an IRIG_SETTINGS + structure only which contain the desired settings + only. _pcps_is_irig_rx() and _pcps_is_irig_tx() + check whether supported. + + - #PCPS_GET_IRIG_CTRL_BITS<br> + This command can be used to retrieve the control function + bits of the latest IRIG input frame. Those bits may carry + some well-known information as in the IEEE1344 code, but + may also contain some customized information, depending on + the IRIG frame type and the configuration of the IRIG generator. + So these bits are returned as-is and must be interpreted + by the application. + _pcps_has_irig_ctrl_bits() checks whether supported. + + - #PCPS_GET_SYNTH<br> + #PCPS_SET_SYNTH<br> + #PCPS_GET_SYNTH_STATE<br> + These commands can be used to configure an on-board + frequency synthesizer and query the synthesizer + status. The commands are only supported if the board + supports the RECEIVER_INFO structure and the flag + #GPS_HAS_SYNTH is set in the RECEIVER_INFO::features. + _pcps_has_synth() checks whether supported. + The structures SYNTH and SYNTH_STATE used with these + commands are defined in gpsdefs.h. + + - #PCPS_GIVE_FW_ID_1<br> + #PCPS_GIVE_FW_ID_2<br> + Returns the first/second block of PCPS_FIFO_SIZE + characters of the firmware ID string. These + commands can be used to check if the board + responds properly. This is done by the clock + detection functions. + + - #PCPS_GIVE_SERNUM<br> + Returns PCPS_FIFO_SIZE characters of the + clock's serial number. + _pcps_has_sernum() checks whether supported. + + - #PCPS_GENERIC_IO<br> + Generic I/O read and write. Can be used to query + specific data, e.g. a selected element of an array. + _pcps_has_generic_io() checks whether supported. + + - #PCPS_GET_DEBUG_STATUS<br> + This command reads a MBG_DEBUG_STATUS structure + which represents the internal status of the + IRIG decoder and some additional debug info. + _pcps_has_debug_status() checks whether supported. + + - #PCPS_READ_GPS_DATA<br> + #PCPS_WRITE_GPS_DATA<br> + These commands are used by the functions + pcps_read_gps_data() and pcps_write_gps_data() + to read or write large data structures to + Meinberg GPS plug-in clocks. + _pcps_is_gps() checks whether supported. + + - #PCPS_CLR_UCAP_BUFF<br> + Clear a clock's time capture buffer. + _pcps_can_clr_ucap_buff() checks whether + supported. + + - #PCPS_GIVE_UCAP_ENTRIES<br> + Read a PCPS_UCAP_ENTRIES structure which + reports the max number of entries and the + currently used number of entries in the + user capture buffer. + _pcps_has_ucap() checks whether supported. + + - #PCPS_GIVE_UCAP_EVENT<br> + Read capture events using a PCPS_HR_TIME + structure. This is faster than reading using the + GPS command #PC_GPS_UCAP. If no capture event is + available then the structure is filled with 0s. + _pcps_has_ucap() checks whether supported. + + - #PCPS_FORCE_RESET<br> + 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 + + +/* 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() + + +/* 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 ) + + +/* 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 ) + + +/* PCPS_CFG_GROUP */ + +#define PCPS_GET_SERIAL ( PCPS_CFG_GROUP | 0x0 ) +#define PCPS_SET_SERIAL ( PCPS_CFG_GROUP | 0x1 ) +/* 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 ) +/* 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 ) +/* 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 ( PCPS_CFG_GROUP | 0x6 ) +#define PCPS_SET_REF_OFFS ( PCPS_CFG_GROUP | 0x7 ) +/* on error, return PCPS_ERR_CFG */ + +/* The associated type MBG_REF_OFFS is defined in gpsdefs.h. */ + + +#define PCPS_GET_OPT_INFO ( PCPS_CFG_GROUP | 0x8 ) +#define PCPS_SET_OPT_SETTINGS ( PCPS_CFG_GROUP | 0x9 ) +/* on error, return PCPS_ERR_CFG */ + +/* The associated structures MBG_OPT_INFO and MBG_OPT_SETTINGS + are defined in gpsdefs.h. */ + + +#define PCPS_GET_IRIG_RX_INFO ( PCPS_CFG_GROUP | 0xA ) +#define PCPS_SET_IRIG_RX_SETTINGS ( PCPS_CFG_GROUP | 0xB ) +/* on error, return PCPS_ERR_CFG */ + +#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 */ + +/* The associated structures IRIG_INFO and IRIG_SETTINGS + are defined in gpsdefs.h. */ + + +#define PCPS_GET_SYNTH ( PCPS_CFG_GROUP | 0xE ) +#define PCPS_SET_SYNTH ( PCPS_CFG_GROUP | 0xF ) +/* on error, return PCPS_ERR_CFG */ + +/* The associated structure SYNTH is defined in gpsdefs.h. */ + + + +/* 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 ) + + + +#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 + +// PCPS_GIVE_DATA_GROUP codes 0x0D, 0x0E, and 0x0F are reserved. + + +/* PCPS_GPS_DATA_GROUP */ +#define PCPS_READ_GPS_DATA ( PCPS_GPS_DATA_GROUP | 0x0 ) +#define PCPS_WRITE_GPS_DATA ( PCPS_GPS_DATA_GROUP | 0x1 ) + + +/* 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; + +#define _mbg_swab_pcps_ucap_entries( _p ) \ +{ \ + _mbg_swab32( &(_p)->used ); \ + _mbg_swab32( &(_p)->max ); \ +} + + + +/** + special -- use with care ! +*/ +#define PCPS_FORCE_RESET 0x80 + +/** @} */ + +/* 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 */ + + + +#ifndef BITMASK + #define BITMASK( b ) ( ( 1 << b ) - 1 ) +#endif + + +/** The size of the plug-in radio clock's on-board FIFO: */ +#define PCPS_FIFO_SIZE 16 + +typedef int8_t PCPS_BUFF[PCPS_FIFO_SIZE]; + + +#define PCPS_ID_SIZE ( 2 * PCPS_FIFO_SIZE + 1 ) /**< ASCIIZ string */ +typedef char PCPS_ID_STR[PCPS_ID_SIZE]; + + +#define PCPS_SN_SIZE ( PCPS_FIFO_SIZE + 1 ) /**< ASCIIZ string */ +typedef char PCPS_SN_STR[PCPS_SN_SIZE]; + + +/** + * The structure has been introduced to be able to handle + * high resolution time stamps. + */ +typedef struct +{ + uint32_t sec; /**< seconds since 1970 (UTC) */ + uint32_t frac; /**< fractions of second ( 0xFFFFFFFF == 0.9999.. sec) */ +} PCPS_TIME_STAMP; + +#define _mbg_swab_pcps_time_stamp( _p ) \ +{ \ + _mbg_swab32( &(_p)->sec ); \ + _mbg_swab32( &(_p)->frac ); \ +} + + + +// Depending on the target environment define a data type +// which can be used to convert binary fractions without +// range overflow. +#if defined( MBG_TGT_UNIX ) + #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t +#elif defined( MBG_TGT_WIN32 ) + #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t +#elif defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) + #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t +#else + #define PCPS_HRT_FRAC_CONVERSION_TYPE double +#endif + +// Max value of PCPS_TIME_STAMP::frac + 1 used for scaling +#define PCPS_HRT_BIN_FRAC_SCALE ( (PCPS_HRT_FRAC_CONVERSION_TYPE) 4294967296.0 ) // == 0x100000000 + + +// The scale and format to be used to print the fractions +// of a second as returned in the PCPS_TIME_STAMP structure. +// The function frac_sec_from_bin() can be used for +// the conversion. +#ifndef PCPS_HRT_FRAC_SCALE + #define PCPS_HRT_FRAC_SCALE 10000000UL +#endif + +#ifndef PCPS_HRT_FRAC_SCALE_FMT + #define PCPS_HRT_FRAC_SCALE_FMT "%07lu" +#endif + + + +typedef uint16_t PCPS_TIME_STATUS_X; /**< extended status */ + +#define _mbg_swab_pcps_time_status_x( _p ) _mbg_swab16( _p ) + + +/** + * The structure has been introduced to be able to read the + * current time with higher resolution of fractions of seconds and + * more detailed information on the time zone and status. + * The structure is returned if the new command #PCPS_GIVE_HR_TIME + * is written to the board. + * _pcps_has_hr_time() checks whether supported. + * + * Newer GPS boards also accept the #PCPS_GIVE_UCAP_EVENT command + * to return user capture event times using this format. In this + * case, the "signal" field contains the number of the capture + * input line, e.g. 0 or 1. + * _pcps_has_ucap() checks whether supported. + */ +typedef struct +{ + PCPS_TIME_STAMP tstamp; /**< High resolution time stamp (UTC) */ + int32_t utc_offs; /**< UTC offs [sec] (loc_time = UTC + utc_offs) */ + PCPS_TIME_STATUS_X status; /**< status flags as defined below */ + uint8_t signal; /**< for normal time, the relative RF signal level, for ucap, the channel number */ +} PCPS_HR_TIME; + +#define _mbg_swab_pcps_hr_time( _p ) \ +{ \ + _mbg_swab_pcps_time_stamp( &(_p)->tstamp ); \ + _mbg_swab32( &(_p)->utc_offs ); \ + _mbg_swab_pcps_time_status_x( &(_p)->status ); \ +} + + +typedef uint8_t PCPS_TIME_STATUS; + +/** + The standard structure used to read times from the board. + The time has a resultion of 10 ms. +*/ +typedef struct PCPS_TIME_s +{ + uint8_t sec100; /**< hundredths of seconds, 0..99 */ + uint8_t sec; /**< seconds, 0..59, or 60 if leap second */ + uint8_t min; /**< minutes, 0..59 */ + uint8_t hour; /**< hours, 0..23 */ + + uint8_t mday; /**< day of month, 0..31 */ + uint8_t wday; /**< day of week, 1..7, 1 = Monday */ + uint8_t month; /**< month, 1..12 */ + uint8_t year; /**< year of the century, 0..99 */ + + PCPS_TIME_STATUS status; /**< status bits, see below */ + uint8_t signal; /**< relative signal strength, range depends on device type */ + int8_t offs_utc; /**< [hours], 0 if !_pcps_has_utc_offs() */ +} PCPS_TIME; + + +/** + The structure is passed as parameter with the PCPS_SET_TIME cmd +*/ +typedef struct PCPS_STIME_s +{ + uint8_t sec100; /**< hundredths of seconds, 0..99 */ + uint8_t sec; /**< seconds, 0..59, or 60 if leap second */ + uint8_t min; /**< minutes, 0..59 */ + uint8_t hour; /**< hours, 0..23 */ + + uint8_t mday; /**< day of month, 0..31 */ + uint8_t wday; /**< day of week, 1..7, 1 = Monday */ + uint8_t month; /**< month, 1..12 */ + uint8_t year; /**< year of the century, 0..99 */ + + PCPS_TIME_STATUS status; /**< status bits, see below */ +} PCPS_STIME; + +#ifdef _C166 + // This is a workaround to specify some structure sizes. The C166 compiler + // always reports an even structure size although the structure size may + // be odd due to the number of bytes. This might lead to errors between + // the C166 and other build environments. + #define sizeof_PCPS_TIME ( sizeof( PCPS_TIME ) - 1 ) + #define sizeof_PCPS_STIME ( sizeof( PCPS_STIME ) - 1 ) +#else + #define sizeof_PCPS_TIME sizeof( PCPS_TIME ) + #define sizeof_PCPS_STIME sizeof( PCPS_STIME ) +#endif + +typedef union +{ + PCPS_TIME t; + PCPS_STIME stime; +} PCPS_TIME_UNION; + + + +/** + The structure below can be used to read the raw IRIG time + from an IRIG receiver card, if the card supports this. + See the #PCPS_GIVE_IRIG_TIME command. + + The granularity of the value in the .frac field depends on + the update interval of the structure as implementation + in the firmware. I.e. if the raw IRIG time is updated + only once per second, the .frac value can always be 0. +*/ +typedef struct PCPS_IRIG_TIME_s +{ + PCPS_TIME_STATUS_X status; /**< status bits, see below */ + int16_t offs_utc; /**< [minutes] */ + uint16_t yday; /**< day of year, 1..365/366 */ + uint16_t frac; /**< fractions of seconds, 0.1 ms units */ + uint8_t sec; /**< seconds, 0..59, or 60 if leap second */ + uint8_t min; /**< minutes, 0..59 */ + uint8_t hour; /**< hours, 0..23 */ + uint8_t year; /**< 2 digit year number, 0xFF if year not supp. by the IRIG code */ + uint8_t signal; /**< relative signal strength, range depends on device type */ + uint8_t reserved; /**< currently not used, always 0 */ +} PCPS_IRIG_TIME; + +#define _mbg_swab_pcps_irig_time( _p ) \ +{ \ + _mbg_swab_pcps_time_status_x( &(_p)->status ); \ + _mbg_swab16( &(_p)->offs_utc ); \ + _mbg_swab16( &(_p)->yday ); \ + _mbg_swab16( &(_p)->frac ); \ +} + + + + +/* Bit masks used with both PCPS_TIME_STATUS and PCPS_TIME_STATUS_X */ + +#define PCPS_FREER 0x01 /**< DCF77 clock running on xtal */ + /**< GPS receiver has not verified its position */ + +#define PCPS_DL_ENB 0x02 /**< daylight saving enabled */ + +#define PCPS_SYNCD 0x04 /**< clock has sync'ed at least once after pwr up */ + +#define PCPS_DL_ANN 0x08 /**< a change in daylight saving is announced */ + +#define PCPS_UTC 0x10 /**< a special UTC firmware is installed */ + +#define PCPS_LS_ANN 0x20 /**< leap second announced */ + /**< (requires firmware rev. REV_PCPS_LS_ANN_...) */ + +#define PCPS_IFTM 0x40 /**< the current time was set via PC */ + /**< (requires firmware rev. REV_PCPS_IFTM_...) */ + +#define PCPS_INVT 0x80 /**< invalid time because battery was disconn'd */ + + +/* Bit masks used only with PCPS_TIME_STATUS_X */ + +#define PCPS_LS_ENB 0x0100 /**< current second is leap second */ +#define PCPS_ANT_FAIL 0x0200 /**< antenna failure */ +#define PCPS_LS_ANN_NEG 0x0400 /**< announced leap second is negative */ +#define PCPS_SCALE_GPS 0x0800 /**< time stamp is GPS scale */ +#define PCPS_SCALE_TAI 0x1000 /**< time stamp is TAI scale */ + +/* 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 ) + + +/** + * Some DCF77 clocks have a serial interface that can be controlled + * using the commands PCPS_SET_SERIAL and PCPS_GET_SERIAL. Both commands + * use a parameter byte describing transmission speed, framing and mode + * of operation. The parameter byte can be build using the constants + * defined below, by or'ing one of the constants of each group, shifted + * to the right position. PCPS_GET_SERIAL expects that parameter byte + * and PCPS_GET_SERIAL returns the current configuration from the board. + * _pcps_has_serial() checks whether supported. + * For GPS clocks, please refer to the comments for the PCPS_GET_SERIAL + * command. + */ + +/** + * Baud rate indices. The values below are obsolete and should + * be replaced by the codes named MBG_BAUD_RATE_... which are + * defined in gpsdefs.h. The resulting index numbers, however, + * have not changed. + */ +enum +{ + PCPS_BD_300, + PCPS_BD_600, + PCPS_BD_1200, + PCPS_BD_2400, + PCPS_BD_4800, + PCPS_BD_9600, + PCPS_BD_19200, + N_PCPS_BD /* number of codes */ +}; + +#define PCPS_BD_BITS 4 /* field with in the cfg byte */ +#define PCPS_BD_SHIFT 0 /* num of bits to shift left */ + +/* + * Initializers for a table of all baud rate strings + * and values can be found in gpsdefs.h. + */ + + +/** + * Unfortunately, the framing codes below can not simply be + * replaced by the newer MBG_FRAMING_... definitions since + * the order of indices does not match. + */ +enum +{ + PCPS_FR_8N1, + PCPS_FR_7E2, + PCPS_FR_8N2, + PCPS_FR_8E1, + N_PCPS_FR_DCF /* number of valid codes */ +}; + +#define PCPS_FR_BITS 2 /* field with in the cfg byte */ +#define PCPS_FR_SHIFT PCPS_BD_BITS /* num of bits to shift left */ + +/* + * An initializer for a table of framing strings is only defined for + * the new MBG_FRAMING_... definitions. For editing the serial port + * configuration, the old codes above should be translated to the new + * codes to unify handling inside the edit functions. + */ + +/** + Modes of operation + + * Indices for modes of operation. The values below are obsolete + * and should be replaced by the codes named STR_... which are + * defined in gpsdefs.h. The resulting index numbers, however, + * have not changed. + */ +enum +{ + PCPS_MOD_REQ, /* time string on request '?' only */ + PCPS_MOD_SEC, /* time string once per second */ + PCPS_MOD_MIN, /* time string once per minute */ + PCPS_MOD_RSVD, /* reserved */ + N_PCPS_MOD_DCF /* number of possible codes */ +}; + +#define PCPS_MOD_BITS 2 /* field with in the cfg byte */ +#define PCPS_MOD_SHIFT ( PCPS_BD_BITS + PCPS_FR_BITS ) + /* num of bits to shift left */ + +/** + * The fixed-length standard time string being sent on the serial + * output is described below: + * + * \<STX\>D:dd.mm.yy;T:d;U:hh.mm.ss;uvwx\<ETX\> + * + * where \<STX\> and \<ETX\> 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 + */ + + + +/** + * Some definitions used with PZF receivers + */ + +/* receiver distance from transmitter [km] */ +typedef uint16_t TR_DISTANCE; + +/* correlation status info */ +typedef struct +{ + uint8_t val; /**< correlation value, or check count if status == PZF_CORR_CHECK */ + uint8_t status; /**< status codes, see below */ + char corr_dir; /**< space, '<', or '>' */ + uint8_t signal; /**< signal level, may always be 0 for devices which do not support this */ +} CORR_INFO; + +/** Codes used with CORR_INFO::status: */ +enum +{ + PZF_CORR_RAW, /**< trying raw correlation, combi receivers running in AM mode */ + PZF_CORR_CHECK, /**< raw correlation achieved, doing plausibility checks */ + PZF_CORR_FINE, /**< fine correlation achieved */ + N_PZF_CORR_STATE +}; + + +/** + * @defgroup gps_cmds_bus GPS commands passed via the system bus + * + * This enumeration defines the various types of data that can be read + * from or written to Meinberg bus level devices which support this. + * Access should be done using the functions ::pcps_read_gps_data() + * and ::pcps_write_gps_data() since the size of some of the structures + * exceeds the size of the devices's I/O buffer and must therefore be + * accessed in several portions. + * + * The structures to be used are defined in gpsdefs.h. Not all structures + * are supportet, yet. Check the R/W indicators for details. + */ +enum +{ // R/W data type description + // system data ----------------------------------------------- + PC_GPS_TZDL = 0, // R/W TZDL time zone / daylight saving + PC_GPS_SW_REV, // R/- SW_REV software revision + PC_GPS_BVAR_STAT, // R/- BVAR_STAT status of buffered variables + PC_GPS_TIME, // R/W TTM curr. time + PC_GPS_POS_XYZ, // -/W XYZ curr. pos. in ECEF coords + PC_GPS_POS_LLA, // -/W LLA curr. pos. in geogr. coords + PC_GPS_PORT_PARM, // R/W PORT_PARM param. of the serial ports + PC_GPS_ANT_INFO, // R/- ANT_INFO time diff after ant. disconn. + PC_GPS_UCAP, // R/- TTM user capture + PC_GPS_ENABLE_FLAGS, // R/W ENABLE_FLAGS controls when to enable outp. + PC_GPS_STAT_INFO, // R/- GPS_STAT_INFO + PC_GPS_CMD, // -/W GPS_CMD commands as described below + PC_GPS_IDENT, // R/- GPS_IDENT serial number + PC_GPS_POS, // R/- POS position XYZ, LLA, and DMS + PC_GPS_ANT_CABLE_LEN, // R/W ANT_CABLE_LEN used to compensate delay + // The codes below are supported by new GPS receiver boards: + PC_GPS_RECEIVER_INFO, // R/- RECEIVER_INFO rcvr model info + PC_GPS_ALL_STR_TYPE_INFO, // R/- n*STR_TYPE_INFO_IDX all string types + PC_GPS_ALL_PORT_INFO, // R/- n*PORT_INFO_IDX all port info + PC_GPS_PORT_SETTINGS_IDX, // -/W PORT_SETTINGS_IDX port settings only + PC_GPS_ALL_POUT_INFO, // R/- n*POUT_INFO_IDX all pout info + PC_GPS_POUT_SETTINGS_IDX, // -/W POUT_SETTINGS_IDX pout settings only + PC_GPS_TIME_SCALE, // R/W MBG_TIME_SCALE_{SETTINGS|INFO}, only if PCPS_HAS_TIME_SCALE + PC_GPS_LAN_IF_INFO, // R/- LAN_IF_INFO LAN interface info, only if PCPS_HAS_LAN_INTF + PC_GPS_IP4_STATE, // R/- IP4_SETTINGS LAN interface state, only if PCPS_HAS_LAN_INTF + PC_GPS_IP4_SETTINGS, // R/W IP4_SETTINGS LAN interface configuration, only if PCPS_HAS_LAN_INTF + PC_GPS_PTP_STATE, // R/- PTP_STATE, only if PCPS_HAS_PTP + PC_GPS_PTP_CFG, // R/W PTP_CFG_{SETTINGS|INFO}, only if PCPS_HAS_PTP + + // 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 +}; + + +/** codes used with PC_GPS_CMD */ +enum +{ + PC_GPS_CMD_BOOT = 1, /**< force the clock to boot mode */ + PC_GPS_CMD_INIT_SYS, /**< let the clock clear its system variables */ + PC_GPS_CMD_INIT_USER, /**< reset the clock's user parameters to defaults */ + PC_GPS_CMD_INIT_DAC, /**< initialize the oscillator disciplining values */ + N_PC_GPS_CMD /**< no command, just the number of known commands */ +}; + +// The type below can be used to store an unambiguous command code. +// In case of the standard PCPS_... commands the lower byte contains +// the command code and the upper byte is 0. +// In case of a GPS command the lower byte contains PCPS_READ_GPS_DATA +// or PCPS_WRITE_GPS_DATA, as appropriate, and the upper byte contains +// the associated PC_GPS_... type code. +typedef uint16_t PCPS_CMD_INFO; + +#if defined( _USE_PACK ) // set default alignment + #pragma pack() +#endif + +/* End of header body */ + +#endif /* _PCPSDEFS_H */ + diff --git a/mbglib/common/use_pack.h b/mbglib/common/use_pack.h index b162014..16950fa 100644 --- a/mbglib/common/use_pack.h +++ b/mbglib/common/use_pack.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: use_pack.h 1.2 2002/02/25 08:50:33Z Andre REL_M $ + * $Id: use_pack.h 1.3 2011/01/26 10:01:41Z martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,7 +11,9 @@ * * ----------------------------------------------------------------------- * $Log: use_pack.h $ - * Revision 1.2 2002/02/25 08:50:33Z Andre + * Revision 1.3 2011/01/26 10:01:41Z martin + * Provided a way to suppress packing of structures on a project base. + * Revision 1.2 2002/02/25 08:50:33 Andre * query __ARM added, __SH2 removed * Revision 1.1 2001/03/30 08:54:33Z MARTIN * Initial revision @@ -21,8 +23,16 @@ #ifndef _USE_PACK_H #define _USE_PACK_H -#if ( !defined( _C166 ) && !defined( _CC51 ) && !defined( __ARM ) ) - #define _USE_PACK +#if ( !defined( _C166 ) && \ + !defined( _CC51 ) && \ + !defined( __ARM ) ) + + // _NO_USE_PACK can be defined for specific projects + // to avoid packing of structures. + #if ( !defined( _NO_USE_PACK ) ) + #define _USE_PACK + #endif + #endif #endif /* _USE_PACK_H */ diff --git a/mbglib/common/words.h b/mbglib/common/words.h index 6ec5eaf..cdb8ab3 100644 --- a/mbglib/common/words.h +++ b/mbglib/common/words.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: words.h 1.21 2009/10/01 14:00:17Z martin REL_M $ + * $Id: words.h 1.26 2011/04/06 10:23:03Z martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,7 +10,20 @@ * * ----------------------------------------------------------------------- * $Log: words.h $ - * Revision 1.21 2009/10/01 14:00:17Z martin + * Revision 1.26 2011/04/06 10:23:03Z martin + * Added FBYTE_OF() and FWORD_OF() macros. + * Modifications required for *BSD. + * Revision 1.25 2010/11/17 10:23:09 martin + * Define _BIT_REDEFINED if bit type is redefined. + * Revision 1.24 2010/11/17 08:44:56Z martin + * If supported, use type "bool" to implement "bit". + * Revision 1.23 2010/05/27 08:54:30Z martin + * Support fixed size data types with Keil RealView compiler for ARM. + * Keil RealView ARM targets are always considered as firmware. + * Revision 1.22 2009/10/21 07:53:55 martin + * Undid changes introduced in 1.21 since they were not consistent + * across glibc and/or Linux kernel header versions. + * Revision 1.21 2009/10/01 14:00:17 martin * Conditionally define ulong and friends also for Linux/glibc. * Revision 1.20 2009/07/02 15:38:12 martin * Added new macro _wswap32(). @@ -71,7 +84,8 @@ #if defined( _C166 ) || \ defined( _CC51 ) || \ - defined( __ARM ) + defined( __ARM ) || \ + defined( __ARMCC_VERSION ) #define _IS_MBG_FIRMWARE 1 #else #define _IS_MBG_FIRMWARE 0 @@ -82,8 +96,6 @@ #if !_IS_MBG_FIRMWARE #include <mbg_tgt.h> - - typedef unsigned char bit; #endif @@ -97,6 +109,14 @@ /* Start of header body */ +// The compilers below support native bit types. + +#if defined( _C166 ) || defined( _CC51 ) + #define _BIT_DEFINED 1 +#endif + + + // Check whether the target system supports C99 fixed-size types. #if defined( MBG_TGT_LINUX ) // any Linux target @@ -116,6 +136,10 @@ #define _C99_BIT_TYPES_DEFINED 1 + // 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 @@ -129,6 +153,7 @@ #endif + // If it's not yet clear whether fixed-size types are supported, // check the build environment which may be multi-platform. @@ -157,6 +182,11 @@ #define _C99_BIT_TYPES_DEFINED 1 #endif + #if defined( __ARMCC_VERSION ) // Keil RealView Compiler for ARM + #include <stdint.h> + #define _C99_BIT_TYPES_DEFINED 1 + #endif + #endif @@ -214,9 +244,7 @@ typedef unsigned char uchar; -#if !defined( MBG_TGT_LINUX ) || !defined( __USE_MISC ) - // The glibc headers define the types below if __USE_MISC is - // defined, otherwise we need to define them here. +#if !defined( MBG_TGT_LINUX ) && !( defined ( MBG_TGT_NETBSD ) && defined ( MBG_TGT_KERNEL ) ) typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; @@ -229,6 +257,20 @@ typedef unsigned short word; typedef unsigned long longword; typedef unsigned long dword; +#if !defined( _BIT_DEFINED ) + + #if _C99_BIT_TYPES_DEFINED + #include <stdbool.h> + + typedef bool bit; + #else + typedef int bit; + #endif + + #define _BIT_REDEFINED 1 + +#endif + #define HI_BYTE( _x ) ( (_x) >> 8 ) #define LO_BYTE( _x ) ( (_x) & 0xFF ) @@ -241,6 +283,9 @@ typedef unsigned long dword; #define BYTE_OF( _v, _n ) *( ( (uint8_t *) &(_v) ) + (_n) ) #define WORD_OF( _v, _n ) *( ( (uint16_t *) &(_v) ) + (_n) ) +#define FBYTE_OF( _v, _n ) *( ( (uint8_t far *) &(_v) ) + (_n) ) +#define FWORD_OF( _v, _n ) *( ( (uint16_t far *) &(_v) ) + (_n) ) + // same as above, but taking pointers #define BYTE_OF_P( _p, _n ) *( ( (uint8_t *) (_p) ) + (_n) ) #define WORD_OF_P( _p, _n ) *( ( (uint16_t *) (_p) ) + (_n) ) diff --git a/windows/gpsxmple.dsp b/windows/gpsxmple.dsp index 13579dd..13579dd 100755..100644 --- a/windows/gpsxmple.dsp +++ b/windows/gpsxmple.dsp diff --git a/windows/gpsxmple.dsw b/windows/gpsxmple.dsw index 6c6ca62..6c6ca62 100755..100644 --- a/windows/gpsxmple.dsw +++ b/windows/gpsxmple.dsw |