diff options
author | Martin Burnicki <martin.burnicki@meinberg.de> | 2009-10-07 13:00:00 +0200 |
---|---|---|
committer | Martin Burnicki <martin.burnicki@meinberg.de> | 2009-10-07 13:00:00 +0200 |
commit | cb75c0b4534db39d8d5a337795dac8e4a7ec5c19 (patch) | |
tree | ff1b65eaa046b62836ab0233928d223352312643 | |
parent | c351e44698427238658702ed6a00b0bf0c8f791b (diff) | |
download | gpsxmple-cb75c0b4534db39d8d5a337795dac8e4a7ec5c19.tar.gz gpsxmple-cb75c0b4534db39d8d5a337795dac8e4a7ec5c19.zip |
Feature updatesgpsxmple-2.2-unix
Changes due to renamed library functions.
Optionally force connection.
Read global RECEIVER_INFO after startup.
Read string type info and port info, if supported.
Fixed a typo for passwd parameter in usage().
Show SVs and DAC.
Optionally loop and wait for automatic messages.
Added a bunch of missing functions to mbgextio.c.
Use mbgserio.c.
-rw-r--r-- | gpsxmple.c | 404 | ||||
-rw-r--r-- | mbglib/common/aes128.c | 401 | ||||
-rw-r--r-- | mbglib/common/aes128.h | 20 | ||||
-rw-r--r-- | mbglib/common/gpsdefs.h | 2483 | ||||
-rw-r--r-- | mbglib/common/gpsserio.c | 132 | ||||
-rw-r--r-- | mbglib/common/gpsserio.h | 343 | ||||
-rw-r--r-- | mbglib/common/mbg_tgt.h | 214 | ||||
-rw-r--r-- | mbglib/common/mbg_tmo.c | 64 | ||||
-rw-r--r-- | mbglib/common/mbg_tmo.h | 312 | ||||
-rw-r--r-- | mbglib/common/mbgextio.c | 1287 | ||||
-rw-r--r-- | mbglib/common/mbgextio.h | 82 | ||||
-rw-r--r-- | mbglib/common/mbggeo.h | 52 | ||||
-rw-r--r-- | mbglib/common/mbgserio.c | 960 | ||||
-rw-r--r-- | mbglib/common/mbgserio.h | 213 | ||||
-rw-r--r-- | mbglib/common/pcpsdefs.h | 1222 | ||||
-rw-r--r-- | mbglib/common/words.h | 242 | ||||
-rw-r--r-- | unix/Makefile | 11 |
17 files changed, 7093 insertions, 1349 deletions
@@ -1,21 +1,21 @@ /************************************************************************** * - * $Id: gpsxmple.c 1.6 2006/10/25 12:31:54 martin REL_M $ - * $Name: GPSXMPLE_2_1 $ + * $Id: gpsxmple.c 1.7 2009/10/02 14:18:08 martin REL_M $ + * $Name: GPSXMPLE_2_2 $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: - * Sample program demonstrating how to access Meinberg GPS receivers + * Sample program demonstrating how to access Meinberg GPS receivers * via the binary data protocol. * - * Depending on the target operating system this program works - * either via serial port (the default) or via a network socket + * Depending on the target operating system this program works + * either via serial port (the default) or via a network socket * connection. * * Other modules needed to build the executable: - * mbgextio.c, gpsserio.c, gpsutils.c + * mbgextio.c, mbgserio.c, gpsserio.c, gpsutils.c * optionally aes128.c, if network socket I/O is used * * Supported target environments: @@ -24,14 +24,23 @@ * QNX 6.x / gcc (socket only) * DOS / BC3.1 (serial only) * - * For makefiles and build environment setups check the associated + * For makefiles and build environment setups check the associated * subdirectories. * - * Please send changes required for other OSs to <support@meinberg.de> + * Please send changes required for other operating systems + * or build to <support@meinberg.de> * * ----------------------------------------------------------------------- * $Log: gpsxmple.c $ - * Revision 1.6 2006/10/25 12:31:54 martin + * Revision 1.7 2009/10/02 14:18:08 martin + * Changes due to renamed library functions. + * Optionally force connection. + * Read global receiver_info after startup. + * Read string type info and port info, if supported. + * Fixed a typo for passwd parameter in usage(). + * Show SVs and DAC. + * Optionally loop and wait for automatic messages. + * Revision 1.6 2006/10/25 12:31:54Z martin * Support serial I/O under Windows. * Check return codes of API functions and print associated * messages in case of error. @@ -66,6 +75,7 @@ +// the variables below are required for communication MBG_MSG_BUFF rbuff; MBG_MSG_BUFF tbuff; @@ -76,8 +86,38 @@ MBG_MSG_CTL mctl = }; +// Define the minimum number of some resource types +// required by the software +#define N_COM_MIN 1 // minimum number of COM ports + +// Define the maximum number of some resource types +// supported by the software +#define N_COM_MAX 4 // max. number of COM ports +#define N_STR_TYPE_MAX 20 // max. number of string types +#define N_POUT_MAX 3 // max. number of programmable outputs + + + +#define _log_msg_0( _lvl, _fmt ) \ + printf( _fmt ); printf( "\n" ) + +#define _log_msg_1( _lvl, _fmt, _v1 ) \ + printf( _fmt, _v1 ); printf( "\n" ) + +#define _log_msg_2( _lvl, _fmt, _v1, _v2 ) \ + printf( _fmt, _v1, _v2 ); printf( "\n" ) + +#define _log_msg_3( _lvl, _fmt, _v1, _v2, _v3 ) \ + printf( _fmt, _v1, _v2, _v3 ); printf( "\n" ) + + + static const char *target; static int is_socket; +static int must_force_connection; +static int must_send_auto; +static RECEIVER_INFO receiver_info; +static const char *feature_names[] = DEFAULT_GPS_FEATURE_NAMES; #if !defined( DEFAULT_DEV_NAME ) #define DEFAULT_DEV_NAME NULL @@ -86,8 +126,10 @@ static int is_socket; static const char *default_target = DEFAULT_DEV_NAME; #if _USE_SERIAL_IO - static long baudrate = 19200L; - static const char *framing = "8N1"; + static uint32_t default_baudrate = 19200L; + static const char *default_framing = "8N1"; + static uint32_t baudrate; + static const char *framing; #endif #if _USE_SOCKET_IO @@ -222,7 +264,7 @@ void print_stat_info( STAT_INFO *p ) default: cp = "INVALID MODE"; }; - printf( "\r%s, %u/%u SVs, DAC: %+li/%+li\n", + printf( "%s, %u/%u SVs, DAC: %+li/%+li\n", cp, p->good_svs, p->svs_in_view, @@ -257,17 +299,127 @@ void print_time( TTM *p ) +static /*HDR*/ +void check_receiver_info( RECEIVER_INFO *p, int log ) +{ + const char *fmt_min = "Number of %s from device (%u) is less than number required (%u)"; + const char *fmt_max = "Number of %s from device (%u) exceeds number supported by the software (%u)"; + + // Check if numbers of resources provided by the device + // don't exceed numbers of resources supported by the software + + #define _check_min( _n, _min, _info ) \ + { \ + if ( (_n) < (_min) ) \ + { \ + if ( log ) \ + _log_msg_3( LOG_ERR, fmt_min, _info, _n, _min ); \ + } \ + } + + #define _check_max( _n, _max, _info ) \ + { \ + if ( (_n) > (_max) ) \ + { \ + if ( log ) \ + _log_msg_3( LOG_WARNING, fmt_max, _info, _n, _max ); \ + \ + _n = _max; \ + } \ + } + + 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" ); + } + 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 ); + } + } + + _check_min( p->n_com_ports, N_COM_MIN, "COM ports" ); + _check_max( p->n_com_ports, N_COM_MAX, "COM ports" ); + _check_max( p->n_str_type, N_STR_TYPE_MAX, "string types" ); + _check_max( p->n_prg_out, N_POUT_MAX, "progr. outputs" ); + +} // check_receiver_info + + + /*HDR*/ int get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) { - int rc = mbgextio_get_receiver_info( &mctl, p ); + int rc; + int i; + int l; + + printf( fmt, "Receiver info:" ); + + rc = mbgextio_get_receiver_info( &mctl, p ); if ( rc != TR_COMPLETE ) { - printf( "Failed to read receiver info: " ); check_rc( rc ); + + if ( rc == TR_TIMEOUT ) + { + printf( "If you are using a very old GPS model then reading the\n" + "receiver info structure may not be supported.\n" ); + } + + return rc; + } + + printf( "%s v%X.%02X", + p->model_name, + p->sw_rev.code >> 8, + p->sw_rev.code & 0xFF + ); + + l = strlen( p->sw_rev.name ); + + if ( l ) + { + // skip trailing spaces + for ( i = l - 1; i > 0; i-- ) + if ( p->sw_rev.name[i] != ' ' ) + break; + + if ( i != 0 ) + printf( " \"%s\"", p->sw_rev.name ); + + #if 0 // hex output for testing + for ( i= 0; i < l; i++ ) + printf( " %02X", p->sw_rev.name[i] ); + #endif + } + printf( ", S/N: %s", p->sernum ); + printf( "\n" ); + + // print features + printf( fmt, "" ); + printf( "Features: 0x%08lX\n", (long) p->features ); + + for ( i = 0; i < 8 * sizeof( p->features ); i++ ) + { + if ( p->features & (1UL << i) ) + { + printf( fmt, "" ); + printf( " - " ); + + if ( i < N_GPS_FEATURE ) + printf( "%s\n", feature_names[i] ); + else + printf( "Unknown feature flag 0x%08lX\n", (1UL << i) ); + } } + printf( "\n" ); + return rc; } // get_receiver_info @@ -301,7 +453,7 @@ void show_sw_rev( MBG_MSG_CTL *pmctl ) /*HDR*/ -void show_stat( MBG_MSG_CTL *pmctl ) +void show_bvar_stat( MBG_MSG_CTL *pmctl ) { BVAR_STAT bvar_stat; int rc; @@ -318,7 +470,29 @@ void show_stat( MBG_MSG_CTL *pmctl ) printf( "%04X\n", bvar_stat ); -} /* show_stat */ +} /* show_bvar_stat */ + + + +/*HDR*/ +void show_stat_info( MBG_MSG_CTL *pmctl ) +{ + STAT_INFO stat_info; + int rc; + + printf( fmt, "Receiver status:" ); + + rc = mbgextio_get_stat_info( pmctl, &stat_info ); + + if ( rc != TR_COMPLETE ) + { + check_rc( rc ); + return; + } + + print_stat_info( &stat_info ); + +} /* show_stat_info */ @@ -454,17 +628,9 @@ void show_synth( MBG_MSG_CTL *pmctl ) /*HDR*/ void set_synth( void ) { - RECEIVER_INFO receiver_info; SYNTH synth = { 0 }; int rc; - // First read receiver info to see whether the device - // provides a synthesizer. - rc = get_receiver_info( &mctl, &receiver_info ); - - if ( rc < 0 ) - return; // error msg has already been printed - if ( !( receiver_info.features & GPS_HAS_SYNTH ) ) { printf( "The device doesn't provide a synthesizer.\n" ); @@ -474,7 +640,7 @@ void set_synth( void ) // In this example we set the synthesizer frequency to // 1 kHz, and the phase to 180 degrees. // The effective frequency is: (freq/10)*(10^^range) - + synth.freq = 1000; // base frequency value in 1/10 Hz Units synth.range = 1; // multiplier 10^^range synth.phase = 1800; // phase in 1/10 degrees @@ -495,18 +661,10 @@ void set_synth( void ) /*HDR*/ void set_pout_mode( void ) { - RECEIVER_INFO receiver_info; POUT_INFO_IDX pout_info_idx; POUT_SETTINGS pout_settings = { 0 }; // new settings, init'd to 0 uint16_t pout_idx = 0; // index of the programmable output int rc; - - // First read receiver info to see whether programmable pulse outputs - // are supported by the device. - rc = get_receiver_info( &mctl, &receiver_info ); - - if ( rc < 0 ) - return; // error msg has already been printed if ( receiver_info.n_prg_out == 0 ) { @@ -516,7 +674,7 @@ void set_pout_mode( void ) // valid pout_idx numbers include 0..receiver_info.n_prg_out-1 - if ( pout_idx >= receiver_info.n_prg_out ) + if ( pout_idx >= receiver_info.n_prg_out ) { printf( "Programmable output index %u out of range (%u..%u)\n", pout_idx, 0, receiver_info.n_prg_out - 1 ); @@ -572,8 +730,6 @@ void show_port_parm( MBG_MSG_CTL *pmctl ) int i; - printf( fmt, "Serial ports:" ); - rc = mbgextio_get_port_parm( pmctl, &port_parm ); if ( rc != TR_COMPLETE ) @@ -610,6 +766,102 @@ void show_port_parm( MBG_MSG_CTL *pmctl ) +/*HDR*/ +void show_port_settings( MBG_MSG_CTL *pmctl ) +{ + const char *mode_names[N_STR_MODE] = DEFAULT_ENG_MODE_NAMES; + STR_TYPE_INFO sti[N_STR_TYPE_MAX]; + STR_TYPE_INFO_IDX stii; + PORT_INFO_IDX pii; + PORT_SETTINGS *p; + int rc; + int i; + + printf( fmt, "Serial ports:" ); + + if ( receiver_info.model_code == GPS_MODEL_UNKNOWN ) + { + // This may be an old GPS model which does not provide + // a receiver info structure. + show_port_parm( pmctl ); + return; + } + + // The number of serial ports and time string formats supported + // by this device is specified in the receiver info structure. + + // Read time string information + + for ( i = 0; i < receiver_info.n_str_type; i++ ) + { + rc = mbgextio_get_str_type_info_idx( pmctl, &stii, (uint16_t) i ); + + if ( rc != TR_COMPLETE ) + { + check_rc( rc ); + return; + } + + if ( stii.idx != i ) + { + printf( "** Info for string type %i requested, but for %i received.\n", + stii.idx, i ); + return; + } + + sti[i] = stii.str_type_info; + } + + + // Read and print port settings + + for ( i = 0; ; ) + { + rc = mbgextio_get_port_info_idx( pmctl, &pii, (uint16_t) i ); + + if ( rc != TR_COMPLETE ) + { + check_rc( rc ); + return; + } + + if ( pii.idx != i ) + { + printf( "** Info for port %i requested, but for %i received.\n", + pii.idx, i ); + return; + } + + p = &pii.port_info.port_settings; + + printf( "COM%i: %5lu Baud, %s", + i, + (ulong) p->parm.baud_rate, + p->parm.framing + ); + + // Make sure indices received from the device do not exceed + // maximum numbers supported by this program. + + if ( p->str_type >= N_STR_TYPE_MAX ) + printf( " (string type exceeds max)" ); + else + if ( p->mode >= N_STR_MODE ) + printf( " (string mode exceeds max)" ); + else + printf( ", \"%s\" string %s", sti[p->str_type].long_name, mode_names[p->mode] ); + + printf( "\n" ); + + if ( ++i >= receiver_info.n_com_ports ) + break; + + printf( fmt, "" ); + } + +} /* show_port_settings */ + + /*HDR*/ static void exit_gpsxmple( void ) @@ -640,6 +892,12 @@ int check_command_line( int argc, char *argv[] ) for ( i = 1; i < argc; i++ ) { + if ( strcmp( argv[i], "-a" ) == 0 ) + { + must_send_auto = 1; + continue; + } + if ( strcmp( argv[i], "-?" ) == 0 ) { must_print_usage = 1; @@ -696,6 +954,14 @@ int check_command_line( int argc, char *argv[] ) } #endif + #if _USE_SERIAL_IO + if ( strcmp( argv[i], "-F" ) == 0 ) + { + must_force_connection = 1; + continue; + } + #endif + if ( argv[i][0] != '-' ) target = argv[i]; else @@ -722,21 +988,20 @@ int check_command_line( int argc, char *argv[] ) #endif "\n" "Options\n" - " -? or -h Print this usage\n" + " -? or -h Print this usage\n" #if _USE_SOCKET_IO " -n Connect to network target, not serial port\n" - " -n passwd Use specified password to connect\n" - #endif - #if _USE_SERIAL_IO - " -b speed serial port baud rate, default: 19200\n" + " -p passwd Use specified password to connect\n" #endif #if _USE_SERIAL_IO - " -f xxx serial port framing, default: 8N1\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" #if _USE_SERIAL_IO - " %s Connect to serial port using 19200/8N1\n" + " %s Connect to serial port %s using %lu/%s\n" #endif #if _USE_SOCKET_IO " %s -n -p secret 172.16.1.1 Connect to the specified network host\n" @@ -744,7 +1009,14 @@ int check_command_line( int argc, char *argv[] ) "\n", argv[0] #if _USE_SERIAL_IO + , (long) default_baudrate + , framing + , (long) default_baudrate + , framing , argv[0] + , default_target + , (long) default_baudrate + , framing #endif #if _USE_SOCKET_IO , argv[0] @@ -767,6 +1039,9 @@ int main( int argc, char *argv[] ) printf( "\n\n\nExample Program Accessing Meinberg GPS Receiver\n" ); + baudrate = default_baudrate; + framing = default_framing; + if ( check_command_line( argc, argv ) < 0 ) return 1; @@ -790,8 +1065,17 @@ int main( int argc, char *argv[] ) } #endif - #if _USE_SERIAL_IO + if ( must_force_connection ) + { + printf( "Trying to force connection to 19200/8N1 ..." ); + mbgextio_force_connection( target ); + printf( "\n" ); + + baudrate = default_baudrate; + framing = default_framing; + } + rc = mbgextio_open_serial( &mctl, target, baudrate, framing ); if ( rc < 0 ) @@ -801,7 +1085,7 @@ int main( int argc, char *argv[] ) } printf( " (Using %s with %li baud, %s)\n\n", - target, baudrate, framing ); + target, (long) baudrate, framing ); goto doit; #endif @@ -817,29 +1101,37 @@ doit: // now start communication with whichever device has been opened above: + get_receiver_info( &mctl, &receiver_info ); + check_receiver_info( &receiver_info, 1 ); + /* display system specific values */ show_sw_rev( &mctl ); - - show_stat( &mctl ); - + show_bvar_stat( &mctl ); + show_stat_info( &mctl ); show_pos( &mctl ); - show_tzdl( &mctl ); - - show_port_parm( &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(); +// set_synth(); +// set_pout_mode(); if ( str_mode_0 != STR_PER_SEC ) return 0; // device will not send time automatically + if ( !must_send_auto ) + return 0; + printf( "\n" ); + // We will start to wait for automatically transmitted messages + // which require a longer timeout than we have used by default + // to wait for replies to dedicated request messages. + mbgextio_set_char_rcv_timeout( &mctl, 2000 ); // [msec] + mbgextio_set_msg_rcv_timeout( &mctl, 2000 ); // [msec] + mbgextio_xmt_cmd( &mctl, GPS_AUTO_ON ); atexit( exit_auto_off ); @@ -847,9 +1139,9 @@ doit: { MBG_MSG_BUFF *pmb; MSG_DATA *p; - - rc = mbgextio_get_data( &mctl, -1 ); + + rc = mbgextio_rcv_msg( &mctl, -1 ); if ( rc != TR_COMPLETE ) { diff --git a/mbglib/common/aes128.c b/mbglib/common/aes128.c index 6a48d24..542467b 100644 --- a/mbglib/common/aes128.c +++ b/mbglib/common/aes128.c @@ -1,109 +1,122 @@ - -/* - * FIPS-197 compliant AES implementation +/************************************************************************** + * + * $Id: aes128.c 1.2 2009/10/01 14:03:09 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * FIPS-197 compliant AES implementation * + * ----------------------------------------------------------------------- + * $Log: aes128.c $ + * Revision 1.2 2009/10/01 14:03:09 martin + * Added standard file header. + * Fixed compiler warnings. + * Support prototype generation by makehdr tool. + * Use standard fixed-size data types. + * Code cleanup. + * Revision 1.1 2004/05/25 12:36:21 andre + * Initial revision. * - */ + **************************************************************************/ + +#define _AES128 + #include <aes128.h> +#undef _AES128 -#include "aes128.h" #include <string.h> #include <stdio.h> -typedef unsigned char uchar; -typedef unsigned long ulong; + /* forward S-box & tables */ -ulong FSb[256]; -ulong FT0[256]; -ulong FT1[256]; -ulong FT2[256]; -ulong FT3[256]; +#define FTABLE_ENTRIES 256 +static ulong FSb[FTABLE_ENTRIES]; +static ulong FT0[FTABLE_ENTRIES]; +static ulong FT1[FTABLE_ENTRIES]; +static ulong FT2[FTABLE_ENTRIES]; +static ulong FT3[FTABLE_ENTRIES]; -/* round constants */ -ulong RCON[10]; +/* rounding constants */ +#define RCON_TABLE_ENTRIES 10 +ulong RCON[RCON_TABLE_ENTRIES]; /* tables generation flag */ - -int do_init = 1; +static int initialized; -#define ROTR8(x) ( ( ( x << 24 ) & 0xFFFFFFFF ) | \ - ( ( x & 0xFFFFFFFF ) >> 8 ) ) +#define ROTR8(x) ( ( ( x << 24 ) & 0xFFFFFFFFUL ) | \ + ( ( x & 0xFFFFFFFFUL ) >> 8 ) ) #define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) #define MUL(x,y) ( ( x && y ) ? pow[(log[x] + log[y]) % 255] : 0 ) + +/*HDR*/ void aes_gen_tables( void ) { - int i; - uchar x, y; - uchar pow[256]; - uchar log[256]; - - do_init = 0; - - /* compute pow and log tables over GF(2^8) */ - - for( i = 0, x = 1; i < 256; i++, x ^= XTIME( x ) ) - { - pow[i] = x; - log[x] = i; - } - - /* calculate the round constants */ + int i; + uint8_t x, y; + uint8_t pow[FTABLE_ENTRIES]; + uint8_t log[FTABLE_ENTRIES]; - for( i = 0, x = 1; i < 10; i++, x = XTIME( x ) ) - { - RCON[i] = (ulong) x << 24; - } + /* compute pow and log tables over GF(2^8) */ - /* generate the forward and reverse S-boxes */ + for ( i = 0, x = 1; i < FTABLE_ENTRIES; i++, x ^= XTIME( x ) ) + { + pow[i] = x; + log[x] = i; + } - FSb[0x00] = 0x63; + /* calculate the round constants */ - for( i = 1; i < 256; i++ ) - { - x = pow[255 - log[i]]; + for ( i = 0, x = 1; i < RCON_TABLE_ENTRIES; i++, x = XTIME( x ) ) + RCON[i] = (ulong) x << 24; - y = x; y = ( y << 1 ) | ( y >> 7 ); - x ^= y; y = ( y << 1 ) | ( y >> 7 ); - x ^= y; y = ( y << 1 ) | ( y >> 7 ); - x ^= y; y = ( y << 1 ) | ( y >> 7 ); - x ^= y ^ 0x63; + /* generate the forward and reverse S-boxes */ - FSb[i] = x; - } + FSb[0x00] = 0x63; - /* generate the forward and reverse tables */ + for ( i = 1; i < FTABLE_ENTRIES; i++ ) + { + x = pow[255 - log[i]]; - for( i = 0; i < 256; i++ ) - { + y = x; y = ( y << 1 ) | ( y >> 7 ); + x ^= y; y = ( y << 1 ) | ( y >> 7 ); + x ^= y; y = ( y << 1 ) | ( y >> 7 ); + x ^= y; y = ( y << 1 ) | ( y >> 7 ); + x ^= y ^ 0x63; - x = FSb[i]; - y = XTIME( x ); + FSb[i] = x; + } - FT0[i] = (ulong) ( x ^ y ) ^ - ( (ulong) x << 8 ) ^ - ( (ulong) x << 16 ) ^ - ( (ulong) y << 24 ); + /* generate the forward and reverse tables */ - FT0[i] &= 0xFFFFFFFF; + for ( i = 0; i < FTABLE_ENTRIES; i++ ) + { + x = (uint8_t) FSb[i]; + y = XTIME( x ); - FT1[i] = ROTR8( FT0[i] ); - FT2[i] = ROTR8( FT1[i] ); - FT3[i] = ROTR8( FT2[i] ); + FT0[i] = (ulong) ( x ^ y ) ^ + ( (ulong) x << 8 ) ^ + ( (ulong) x << 16 ) ^ + ( (ulong) y << 24 ); - } -}/*aes_gen_tables*/ + FT0[i] &= 0xFFFFFFFFUL; + FT1[i] = ROTR8( FT0[i] ); + FT2[i] = ROTR8( FT1[i] ); + FT3[i] = ROTR8( FT2[i] ); + } +} /* aes_gen_tables */ @@ -119,144 +132,153 @@ void aes_gen_tables( void ) #define PUT_ulong(n,b,i) \ { \ - (b)[(i) ] = (uchar) ( (n) >> 24 ); \ - (b)[(i) + 1] = (uchar) ( (n) >> 16 ); \ - (b)[(i) + 2] = (uchar) ( (n) >> 8 ); \ - (b)[(i) + 3] = (uchar) ( (n) ); \ + (b)[(i) ] = (uint8_t) ( (n) >> 24 ); \ + (b)[(i) + 1] = (uint8_t) ( (n) >> 16 ); \ + (b)[(i) + 2] = (uint8_t) ( (n) >> 8 ); \ + (b)[(i) + 3] = (uint8_t) ( (n) ); \ } + + + /* decryption key schedule tables */ + /* AES key scheduling routine */ -int aes128_set_key( aes128_context *ctx, unsigned char *key ) +/*HDR*/ +int aes128_set_key( aes128_context *ctx, uint8_t *key ) { - int i; - ulong *RK; + int i; + ulong *RK; - if ( do_init ){ - aes_gen_tables(); - do_init = 0; - } + if ( !initialized ) + { + aes_gen_tables(); + initialized = 1; + } - RK = ctx->erk; + RK = ctx->erk; - for( i = 0; i < 4; i++ ){ - GET_ulong( RK[i], key, i * 4 ); - } + for ( i = 0; i < 4; i++ ) + GET_ulong( RK[i], key, i * 4 ); - /* setup encryption round keys */ - for( i = 0; i < 10; i++, RK += 4 ) - { - RK[4] = RK[0] ^ RCON[i] ^ - ( FSb[ (uchar) ( RK[3] >> 16 ) ] << 24 ) ^ - ( FSb[ (uchar) ( RK[3] >> 8 ) ] << 16 ) ^ - ( FSb[ (uchar) ( RK[3] ) ] << 8 ) ^ - ( FSb[ (uchar) ( RK[3] >> 24 ) ] ); - - RK[5] = RK[1] ^ RK[4]; - RK[6] = RK[2] ^ RK[5]; - RK[7] = RK[3] ^ RK[6]; - } + /* setup encryption round keys */ + for ( i = 0; i < RCON_TABLE_ENTRIES; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( FSb[ (uint8_t) ( RK[3] >> 16 ) ] << 24 ) ^ + ( FSb[ (uint8_t) ( RK[3] >> 8 ) ] << 16 ) ^ + ( FSb[ (uint8_t) ( RK[3] ) ] << 8 ) ^ + ( FSb[ (uint8_t) ( RK[3] >> 24 ) ] ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + + return 0; + +} /* aes128_set_key */ - return( 0 ); -}/*aes128_set_key*/ /* AES 128-bit block encryption routine */ -void aes128_encrypt( aes128_context *ctx, uchar input[16], uchar output[16] ) +static /*HDR*/ +void aes128_encrypt( aes128_context *ctx, uint8_t input[16], uint8_t output[16] ) { - ulong *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + ulong *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; - RK = ctx->erk; + RK = ctx->erk; - GET_ulong( X0, input, 0 ); X0 ^= RK[0]; - GET_ulong( X1, input, 4 ); X1 ^= RK[1]; - GET_ulong( X2, input, 8 ); X2 ^= RK[2]; - GET_ulong( X3, input, 12 ); X3 ^= RK[3]; + GET_ulong( X0, input, 0 ); X0 ^= RK[0]; + GET_ulong( X1, input, 4 ); X1 ^= RK[1]; + GET_ulong( X2, input, 8 ); X2 ^= RK[2]; + GET_ulong( X3, input, 12 ); X3 ^= RK[3]; -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ + #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + { \ RK += 4; \ \ - X0 = RK[0] ^ FT0[ (uchar) ( Y0 >> 24 ) ] ^ \ - FT1[ (uchar) ( Y1 >> 16 ) ] ^ \ - FT2[ (uchar) ( Y2 >> 8 ) ] ^ \ - FT3[ (uchar) ( Y3 ) ]; \ + X0 = RK[0] ^ FT0[ (uint8_t) ( Y0 >> 24 ) ] ^ \ + FT1[ (uint8_t) ( Y1 >> 16 ) ] ^ \ + FT2[ (uint8_t) ( Y2 >> 8 ) ] ^ \ + FT3[ (uint8_t) ( Y3 ) ]; \ \ - X1 = RK[1] ^ FT0[ (uchar) ( Y1 >> 24 ) ] ^ \ - FT1[ (uchar) ( Y2 >> 16 ) ] ^ \ - FT2[ (uchar) ( Y3 >> 8 ) ] ^ \ - FT3[ (uchar) ( Y0 ) ]; \ + X1 = RK[1] ^ FT0[ (uint8_t) ( Y1 >> 24 ) ] ^ \ + FT1[ (uint8_t) ( Y2 >> 16 ) ] ^ \ + FT2[ (uint8_t) ( Y3 >> 8 ) ] ^ \ + FT3[ (uint8_t) ( Y0 ) ]; \ \ - X2 = RK[2] ^ FT0[ (uchar) ( Y2 >> 24 ) ] ^ \ - FT1[ (uchar) ( Y3 >> 16 ) ] ^ \ - FT2[ (uchar) ( Y0 >> 8 ) ] ^ \ - FT3[ (uchar) ( Y1 ) ]; \ + X2 = RK[2] ^ FT0[ (uint8_t) ( Y2 >> 24 ) ] ^ \ + FT1[ (uint8_t) ( Y3 >> 16 ) ] ^ \ + FT2[ (uint8_t) ( Y0 >> 8 ) ] ^ \ + FT3[ (uint8_t) ( Y1 ) ]; \ \ - X3 = RK[3] ^ FT0[ (uchar) ( Y3 >> 24 ) ] ^ \ - FT1[ (uchar) ( Y0 >> 16 ) ] ^ \ - FT2[ (uchar) ( Y1 >> 8 ) ] ^ \ - FT3[ (uchar) ( Y2 ) ]; \ -} + X3 = RK[3] ^ FT0[ (uint8_t) ( Y3 >> 24 ) ] ^ \ + FT1[ (uint8_t) ( Y0 >> 16 ) ] ^ \ + FT2[ (uint8_t) ( Y1 >> 8 ) ] ^ \ + FT3[ (uint8_t) ( Y2 ) ]; \ + } - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ - /* last round */ + /* last round */ - RK += 4; + RK += 4; - X0 = RK[0] ^ ( FSb[ (uchar) ( Y0 >> 24 ) ] << 24 ) ^ - ( FSb[ (uchar) ( Y1 >> 16 ) ] << 16 ) ^ - ( FSb[ (uchar) ( Y2 >> 8 ) ] << 8 ) ^ - ( FSb[ (uchar) ( Y3 ) ] ); + X0 = RK[0] ^ ( FSb[ (uint8_t) ( Y0 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8_t) ( Y1 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8_t) ( Y2 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8_t) ( Y3 ) ] ); - X1 = RK[1] ^ ( FSb[ (uchar) ( Y1 >> 24 ) ] << 24 ) ^ - ( FSb[ (uchar) ( Y2 >> 16 ) ] << 16 ) ^ - ( FSb[ (uchar) ( Y3 >> 8 ) ] << 8 ) ^ - ( FSb[ (uchar) ( Y0 ) ] ); + X1 = RK[1] ^ ( FSb[ (uint8_t) ( Y1 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8_t) ( Y2 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8_t) ( Y3 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8_t) ( Y0 ) ] ); - X2 = RK[2] ^ ( FSb[ (uchar) ( Y2 >> 24 ) ] << 24 ) ^ - ( FSb[ (uchar) ( Y3 >> 16 ) ] << 16 ) ^ - ( FSb[ (uchar) ( Y0 >> 8 ) ] << 8 ) ^ - ( FSb[ (uchar) ( Y1 ) ] ); + X2 = RK[2] ^ ( FSb[ (uint8_t) ( Y2 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8_t) ( Y3 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8_t) ( Y0 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8_t) ( Y1 ) ] ); - X3 = RK[3] ^ ( FSb[ (uchar) ( Y3 >> 24 ) ] << 24 ) ^ - ( FSb[ (uchar) ( Y0 >> 16 ) ] << 16 ) ^ - ( FSb[ (uchar) ( Y1 >> 8 ) ] << 8 ) ^ - ( FSb[ (uchar) ( Y2 ) ] ); + X3 = RK[3] ^ ( FSb[ (uint8_t) ( Y3 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8_t) ( Y0 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8_t) ( Y1 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8_t) ( Y2 ) ] ); - PUT_ulong( X0, output, 0 ); - PUT_ulong( X1, output, 4 ); - PUT_ulong( X2, output, 8 ); - PUT_ulong( X3, output, 12 ); + PUT_ulong( X0, output, 0 ); + PUT_ulong( X1, output, 4 ); + PUT_ulong( X2, output, 8 ); + PUT_ulong( X3, output, 12 ); -}/*aes128_encrypt*/ +} /* aes128_encrypt */ /* buffer size must be an integer multiple of 16 */ -int aes_encrypt_buff ( unsigned char *p_data, - unsigned char *p_key, - unsigned char *p_init, - int n ){ - +/*HDR*/ +int aes_encrypt_buff( uint8_t *p_data, + uint8_t *p_key, + uint8_t *p_init, + int n ) +{ aes128_context ctx; - unsigned char block_key[32]; + uint8_t block_key[32]; if ( n % 16 != 0 ) - return ( -1 ); + return -1; memcpy ( block_key, p_init, 16 ); @@ -264,78 +286,73 @@ int aes_encrypt_buff ( unsigned char *p_data, aes128_set_key( &ctx, p_key ); aes128_encrypt( &ctx, block_key, block_key ); - while ( n ){ - + while ( n ) + { // cipher feedback mode { int j; - for( j = 0; j < 16; j++ ) - *( ( char * ) ( p_data + j ) ) ^= block_key[j]; + for ( j = 0; j < 16; j++ ) + *( (char *) ( p_data + j ) ) ^= block_key[j]; } // encrypt 16 byte block aes128_encrypt( &ctx, p_data, block_key ); p_data += 16; - n-=16; + n -= 16; } - return ( 0 ); + return 0; -}/*aes_encrypt_buff*/ +} /* aes_encrypt_buff */ -/* buffer size must be an integer multiple of 16 */ -int aes_decrypt_buff ( unsigned char *p_data, - unsigned char *p_key, - unsigned char *p_init, - int n ){ +/* buffer size must be an integer multiple of 16 */ +/*HDR*/ +int aes_decrypt_buff ( uint8_t *p_data, + uint8_t *p_key, + uint8_t *p_init, + int n ) +{ aes128_context ctx; - unsigned char block_key[32]; - unsigned char p_tmp[32]; + uint8_t block_key[32]; + uint8_t p_tmp[32]; if ( n % 16 != 0 ) - return ( -1 ); + return -1; - memcpy ( block_key, p_init, 16 ); + memcpy( block_key, p_init, 16 ); // setup the 1st. block key aes128_set_key( &ctx, p_key ); aes128_encrypt( &ctx, block_key, block_key ); - while ( n ){ + while ( n ) + { int j; // decrypt first block and save encrypted // block for new block key calculation - for( j = 0; j < 16; j++ ){ - p_tmp[j] = *( ( char * ) ( p_data + j ) ); - *( ( char * ) ( p_data + j ) ) ^= block_key[j]; + for ( j = 0; j < 16; j++ ) + { + p_tmp[j] = *( (char *) ( p_data + j ) ); + *( (char *) ( p_data + j ) ) ^= block_key[j]; } // calculate new block key aes128_encrypt( &ctx, p_tmp, block_key ); p_data += 16; - n-=16; + n -= 16; } - return ( 0 ); - -}/*aes_decrypt_buff*/ - - - - - - - - + return 0; +} /* aes_decrypt_buff */ diff --git a/mbglib/common/aes128.h b/mbglib/common/aes128.h index 10cd0c3..c2fe912 100644 --- a/mbglib/common/aes128.h +++ b/mbglib/common/aes128.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: aes128.h 1.2 2006/08/22 15:28:11 martin REL_M $ + * $Id: aes128.h 1.3 2009/10/01 14:04:52 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,7 +10,10 @@ * * ----------------------------------------------------------------------- * $Log: aes128.h $ - * Revision 1.2 2006/08/22 15:28:11 martin + * Revision 1.3 2009/10/01 14:04:52 martin + * Code cleanup. + * Updated function prototypes. + * Revision 1.2 2006/08/22 15:28:11Z martin * Added standard file header. * Added definition for AES_BLOCK_SIZE. * @@ -21,7 +24,10 @@ /* Other headers to be included */ -#ifdef _GPSUTILS +#include <words.h> + + +#ifdef _AES128 #define _ext #define _DO_INIT #else @@ -51,10 +57,10 @@ extern "C" { /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ -void aes_gen_tables( void ); -int aes128_set_key( aes128_context *ctx, unsigned char *key ); -int aes_encrypt_buff ( unsigned char *p_data, unsigned char *p_key, unsigned char *p_init, int n ); -int aes_decrypt_buff ( unsigned char *p_data, unsigned char *p_key, unsigned char *p_init, int n ); + void aes_gen_tables( void ) ; + int aes128_set_key( aes128_context *ctx, uint8_t *key ) ; + int aes_encrypt_buff( uint8_t *p_data, uint8_t *p_key, uint8_t *p_init, int n ) ; + int aes_decrypt_buff ( uint8_t *p_data, uint8_t *p_key, uint8_t *p_init, int n ) ; /* ----- function prototypes end ----- */ diff --git a/mbglib/common/gpsdefs.h b/mbglib/common/gpsdefs.h index 47dd267..abc3977 100644 --- a/mbglib/common/gpsdefs.h +++ b/mbglib/common/gpsdefs.h @@ -1,15 +1,124 @@ /************************************************************************** * - * $Id: gpsdefs.h 1.51 2006/10/23 15:31:27 martin REL_M $ + * $Id: gpsdefs.h 1.80 2009/09/28 14:55:53 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: - * General definitions to be used with Meinberg GPS clocks. + * General definitions to be used with Meinberg clocks. + * These definitions have initially be used with GPS devices only. + * However, more and more Meinberg non-GPS devices also use some of + * these definitions. * * ----------------------------------------------------------------------- * $Log: gpsdefs.h $ + * Revision 1.80 2009/09/28 14:55:53 martin + * Support IRIG formats G002/G142 and G006/G146. + * Modified IRIG format description strings. + * Revision 1.79 2009/08/12 14:12:38 daniel + * Added definitions to support new model MGR170. + * Added definitions and commands to support configuration + * of navigation engine (currently supported by u-blox + * receivers only). + * Renamed simulation values in PTP_SETTINGS to reserved. + * Added "UNINITIALIZED" to PTP port state. + * Removed obsolete braces in initializer. + * Revision 1.78 2009/06/25 15:49:05Z martin + * Added macro _nano_time_negative(). + * Revision 1.77 2009/06/08 19:22:32Z daniel + * Added feature GPS_HAS_PTP. + * Added preliminary structures and definitions for PTP + * configuration and state. + * Added IP4_ADDR type. + * Added Bitmask IP4_MSK_DHCP. + * Added byte swapper macros for LAN and PTP structures. + * Moved LAN interface configuration definitions here. + * Moved DAC_VAL definition here. + * Changed type iof FPGA_INFO::start_addr for non-firmware applications. + * Revision 1.76 2009/04/08 08:26:56 daniel + * Added feature GPS_FEAT_IRIG_CTRL_BITS. + * Revision 1.75 2009/03/19 14:06:39Z martin + * Modified string initializer for unknown oscillator type. + * Revision 1.74 2009/03/18 13:45:53 daniel + * Added missing commas in + * MBG_DEBUG_STATUS_STRS initializer. + * Adjusted some comments for doxygen parser. + * Revision 1.73 2009/03/10 16:55:33Z martin + * Support configurable time scales GPS and TAI. + * Defined extended TM status type and associated flags. + * Added definition TM_MSK_TIME_VALID. + * Added some macros to swap endianess of structures. + * Revision 1.72 2008/11/28 09:26:21Z daniel + * Added definitions to support WWVB511 + * Revision 1.71 2008/10/31 14:31:44Z martin + * Added definitions for TCR170PEX. + * Revision 1.70 2008/09/18 11:14:39 martin + * Added definitions to support GEN170. + * Revision 1.69 2008/09/15 14:16:17 martin + * Added more macros to convert the endianess of structures. + * Added N_COM_HS to the enumeration of handshake modes. + * Added MBG_PS_... codes. + * Revision 1.68 2008/08/25 10:51:13 martin + * Added definitions for PTP270PEX and FRC511PEX. + * Revision 1.67 2008/07/17 08:54:52Z martin + * Added macros to convert the endianess of structures. + * Added multiref fixed frequency source. + * Revision 1.66 2008/05/19 14:49:07 daniel + * Renamed s_addr to start_addr in FPGA_INFO. + * Revision 1.65 2008/05/19 09:00:01Z martin + * Added definitions for GPS162. + * Added FPGA_INFO and GPS_HAS_FPGA. + * Added FPGA_START_INFO and associated definitions. + * Added new XMRS status XMRS_..._NOT_SETTLED. + * Added initializer XMULTI_REF_STATUS_INVALID. + * Revision 1.64 2008/01/17 11:50:33Z daniel + * Made IGNORE_LOCK bit maskable. + * Revision 1.63 2008/01/17 11:42:09Z daniel + * Made comments compatible for Doxygen parser. + * No sourcecode changes. + * Revision 1.62 2007/11/15 13:23:33Z martin + * Decide whether other Meinberg headers are to be included depending on whether + * CLOCK_MEINBERG is defined (as with NTP) or not. Previous versions checked + * for "PACKAGE" which is also defined by the Borland C++ build environment, though. + * Revision 1.61 2007/11/13 13:28:54 daniel + * Added definitions to support GPS170PEX. + * Revision 1.60 2007/09/13 12:37:35Z martin + * Modified and added initializers for TZDL. + * Added multiref source PTP over E1. + * Added codes for MSF511 and GRC170 devices. + * Modified XMULTI_REF_SETTINGS and XMULTI_REF_STATUS structures. + * Avoid inclusion of other Meinberg headers in non-Meinberg projects. + * Added device classification macros _mbg_rcvr_is_...(). + * Modified feature name string initializer for non-GPS devices. + * Updated some comments. + * Removed some obsolete comments. + * Revision 1.59 2007/07/19 07:41:56Z martin + * Added symbol MBG_REF_OFFS_NOT_CFGD. + * Revision 1.58 2007/05/21 15:46:44Z martin + * Fixed a typo. + * Revision 1.57 2007/03/29 12:20:43 martin + * Fixed some TZDL initializers. + * Revision 1.56 2007/02/14 14:17:10Z andre + * bug fixed in mask XMRS_MSK_NO_CONN + * Revision 1.55 2007/02/06 16:23:18Z martin + * Added definitions for AM511. + * Made SVNO unsigned. + * Added support for OPT_SETTINGS. + * Added XMULTI_REF_... definitions. + * Added string initializer DEFAULT_FREQ_RANGES. + * Revision 1.54 2007/01/04 11:39:39Z martin + * Added definitions for TCR511. + * Added definition GPS_FEAT_5_MHZ. + * Updated some comments related to duplicate features/options + * IGNORE_LOCK and EMU_SYNC. + * Revision 1.53 2006/12/13 09:31:49 martin + * Added feature flag for ignore_lock. + * Revision 1.52 2006/12/12 15:47:18 martin + * Added MBG_DEBUG_STATUS type and associated definitions. + * Added definition GPS_HAS_REF_OFFS. + * Moved PCPS_REF_OFFS and associated definitions from pcpsdefs.h here + * and renamed them to MBG_REF_OFFS, etc. * Revision 1.51 2006/10/23 15:31:27 martin * Added definitions for GPS170. * Added definitions for new multi_ref sources IRIG, NTP, and PTP. @@ -69,7 +178,7 @@ * Revision 1.31 2004/07/08 08:30:36Z martin * Added feature GPS_FEAT_RCV_TIMEOUT. * Revision 1.30 2004/06/21 13:38:42 martin - * New flag MBG_OPT_BIT_EMU_SYNC/MBG_OPT_BIT_EMU_SYNC + * New flag MBG_OPT_BIT_EMU_SYNC/MBG_OPT_FLAG_EMU_SYNC * lets the receicer emulate/pretend to be always synchronized. * Revision 1.30 2004/06/21 13:35:46Z martin * Revision 1.29 2004/06/16 12:47:53Z martin @@ -160,8 +269,18 @@ /* Other headers to be included */ -#include <words.h> -#include <use_pack.h> +#if defined( HAVE_CONFIG_H ) + // this is mainly to simplify usage in non-Meinberg projects + #include <config.h> +#endif + +// CLOCK_MEINBERG is defined in NTP's config.h if configured +// to support Meinberg clocks. +#if !defined( CLOCK_MEINBERG ) + // avoid having to use these headers in non-Meinberg projects + #include <words.h> + #include <use_pack.h> +#endif #if defined( _USE_PACK ) // set byte alignment @@ -199,7 +318,7 @@ #endif -typedef int16_t SVNO; /* the number of a SV */ +typedef uint16_t SVNO; /* the number of a SV */ typedef uint16_t HEALTH; /* a SV's health code */ typedef uint16_t CFG; /* a SV's configuration code */ typedef uint16_t IOD; /* Issue-Of-Data code */ @@ -210,30 +329,45 @@ typedef uint16_t IOD; /* Issue-Of-Data code */ #ifndef _CSUM_DEFINED typedef uint16_t CSUM; #define _CSUM_DEFINED + + #define _mbg_swab_csum( _p ) _mbg_swab16( _p ) #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. +/** + 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. +*/ typedef uint16_t GPS_CMD; +#define _mbg_swab_gps_cmd( _p ) _mbg_swab16( _p ) -/* a struct used to hold the software revision information */ +/** + A struct used to hold the software revision information + */ 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; /**< 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 */ } SW_REV; +#define _mbg_swab_sw_rev( _p ) \ +{ \ + _mbg_swab16( &(_p)->code ); \ +} -typedef uint16_t BVAR_STAT; /* holds status of battery buffered vars */ -// The bits defined below are set in BVAR_STAT if the corresponding -// parameters are NOT valid and complete: +typedef uint16_t BVAR_STAT; /**< holds status of battery buffered vars */ +#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: +*/ enum { BVAR_BIT_CFGH_INVALID, @@ -250,7 +384,7 @@ enum #define BVAR_IONO_INVALID ( 1UL << BVAR_BIT_IONO_INVALID ) #define BVAR_RCVR_POS_INVALID ( 1UL << BVAR_BIT_RCVR_POS_INVALID ) -// bit mask for all defined bits +/**< bit mask for all defined bits */ #define BVAR_MASK ( ( 1UL << N_BVAR_BIT ) - 1 ) @@ -264,6 +398,12 @@ typedef struct int16_t range; /* an optional base 10 exponent */ } FIXED_FREQ_INFO; +#define _mbg_swab_fixed_freq_info( _p ) \ +{ \ + _mbg_swab16( &(_p)->khz_val ); \ + _mbg_swab16( &(_p)->range ); \ +} + /* @@ -273,32 +413,42 @@ typedef struct * this, or may not support this at all. */ -/* +/** * The structure is ordered in a way that all fields * except chars or arrays of chars are word-aligned. */ typedef struct { - uint16_t model_code; /* identifier for receiver model */ - SW_REV sw_rev; /* software revision and ID */ - char model_name[GPS_ID_STR_SIZE]; /* ASCIIZ, name of receiver model */ - char sernum[GPS_ID_STR_SIZE]; /* ASCIIZ, serial number */ - char epld_name[GPS_EPLD_STR_SIZE]; /* ASCIIZ, file name of EPLD image */ - uint8_t n_channels; /* number of sats to be tracked simultaneously */ - uint32_t ticks_per_sec; /* resolution of fractions of seconds */ - uint32_t features; /* optional features, see below */ - FIXED_FREQ_INFO fixed_freq; /* optional non-standard fixed frequency */ - uint8_t osc_type; /* type of installed oscillator, see below */ - uint8_t osc_flags; /* oscillator flags, see below */ - uint8_t n_ucaps; /* number of user time capture inputs */ - uint8_t n_com_ports; /* number of on-board serial ports */ - uint8_t n_str_type; /* max num of string types supported by any port */ - uint8_t n_prg_out; /* number of programmable pulse outputs */ - uint16_t flags; /* additional information, see below */ + uint16_t model_code; /**< identifier for receiver model */ + SW_REV sw_rev; /**< software revision and ID */ + char model_name[GPS_ID_STR_SIZE]; /**< ASCIIZ, name of receiver model */ + char sernum[GPS_ID_STR_SIZE]; /**< ASCIIZ, serial number */ + char epld_name[GPS_EPLD_STR_SIZE]; /**< ASCIIZ, file name of EPLD image */ + uint8_t n_channels; /**< number of sats to be tracked simultaneously */ + uint32_t ticks_per_sec; /**< resolution of fractions of seconds */ + uint32_t features; /**< optional features, see below */ + FIXED_FREQ_INFO fixed_freq; /**< optional non-standard fixed frequency */ + uint8_t osc_type; /**< type of installed oscillator, see below */ + uint8_t osc_flags; /**< oscillator flags, see below */ + uint8_t n_ucaps; /**< number of user time capture inputs */ + uint8_t n_com_ports; /**< number of on-board serial ports */ + uint8_t n_str_type; /**< max num of string types supported by any port */ + uint8_t n_prg_out; /**< number of programmable pulse outputs */ + uint16_t flags; /**< additional information, see below */ } RECEIVER_INFO; +#define _mbg_swab_receiver_info( _p ) \ +{ \ + _mbg_swab16( &(_p)->model_code ); \ + _mbg_swab_sw_rev( &(_p)->sw_rev ); \ + _mbg_swab16( &(_p)->ticks_per_sec ); \ + _mbg_swab32( &(_p)->features ); \ + _mbg_swab_fixed_freq_info( &(_p)->fixed_freq ); \ + _mbg_swab16( &(_p)->flags ); \ +} -/* + +/** * Valid codes for RECEIVER_INFO.model_code: */ enum @@ -318,10 +468,28 @@ enum GPS_MODEL_GPS170PCI, GPS_MODEL_PZF511, GPS_MODEL_GPS170, + GPS_MODEL_TCR511, + GPS_MODEL_AM511, + GPS_MODEL_MSF511, + GPS_MODEL_GRC170, + GPS_MODEL_GPS170PEX, + GPS_MODEL_GPS162, + GPS_MODEL_PTP270PEX, + GPS_MODEL_FRC511PEX, + GPS_MODEL_GEN170, + GPS_MODEL_TCR170PEX, + GPS_MODEL_WWVB511, + GPS_MODEL_MGR170, N_GPS_MODEL + /* If new model codes are added then care must be taken + * to update the associated string initializers below + * accordingly, and to check whether the classification macros + * also cover the new model names. */ }; + + /* * String initializers for each of the GPS * receiver models enum'ed above: @@ -341,6 +509,18 @@ enum #define GPS_MODEL_NAME_GPS170PCI "GPS170PCI" #define GPS_MODEL_NAME_PZF511 "PZF511" #define GPS_MODEL_NAME_GPS170 "GPS170" +#define GPS_MODEL_NAME_TCR511 "TCR511" +#define GPS_MODEL_NAME_AM511 "AM511" +#define GPS_MODEL_NAME_MSF511 "MSF511" +#define GPS_MODEL_NAME_GRC170 "GRC170" +#define GPS_MODEL_NAME_GPS170PEX "GPS170PEX" +#define GPS_MODEL_NAME_GPS162 "GPS162" +#define GPS_MODEL_NAME_PTP270PEX "PTP270PEX" +#define GPS_MODEL_NAME_FRC511PEX "FRC511PEX" +#define GPS_MODEL_NAME_GEN170 "GEN170" +#define GPS_MODEL_NAME_TCR170PEX "TCR170PEX" +#define GPS_MODEL_NAME_WWVB511 "WWVB511" +#define GPS_MODEL_NAME_MGR170 "MGR170" /* @@ -365,11 +545,95 @@ enum GPS_MODEL_NAME_GPS164, \ GPS_MODEL_NAME_GPS170PCI, \ GPS_MODEL_NAME_PZF511, \ - GPS_MODEL_NAME_GPS170 \ + GPS_MODEL_NAME_GPS170, \ + GPS_MODEL_NAME_TCR511, \ + GPS_MODEL_NAME_AM511, \ + GPS_MODEL_NAME_MSF511, \ + GPS_MODEL_NAME_GRC170, \ + GPS_MODEL_NAME_GPS170PEX, \ + GPS_MODEL_NAME_GPS162, \ + GPS_MODEL_NAME_PTP270PEX, \ + GPS_MODEL_NAME_FRC511PEX, \ + GPS_MODEL_NAME_GEN170, \ + GPS_MODEL_NAME_TCR170PEX, \ + GPS_MODEL_NAME_WWVB511, \ + GPS_MODEL_NAME_MGR170 \ } /* + * The macros below can be used to classify a receiver, + * e.g. depending on the time source and/or depending on + * whether it's a plug-in card or an external device. + */ + +#define _mbg_rcvr_is_plug_in( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "PC" ) || \ + ( strstr( (_p_ri)->model_name, "PEX" ) ) + +#define _mbg_rcvr_is_gps( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "GPS" ) || \ + ( strstr( (_p_ri)->model_name, "MGR" ) ) + +#define _mbg_rcvr_is_mobile_gps( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "MGR" ) ) + +#define _mbg_rcvr_is_gps_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_gps( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_irig( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "TCR" ) ) + +#define _mbg_rcvr_is_irig_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_irig( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_dcf77_am( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "AM" ) ) + +#define _mbg_rcvr_is_dcf77_am_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_dcf77_am( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_dcf77_pzf( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "PZF" ) ) + +#define _mbg_rcvr_is_dcf77_pzf_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_dcf77_pzf( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_any_dcf77( _p_ri ) \ + ( _mbg_rcvr_is_dcf77_am( _p_ri ) || \ + _mbg_rcvr_is_dcf77_pzf( _p_ri ) ) + +#define _mbg_rcvr_is_any_dcf77_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_any_dcf77( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_msf( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "MSF" ) ) + +#define _mbg_rcvr_is_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" ) ) + +#define _mbg_rcvr_is_glonass_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_glonass( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_wwvb( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "WWVB" ) ) + +#define _mbg_rcvr_is_wwvb_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_wwvb( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + + +/** * The classification codes for oscillators below * are used with RECEIVER_INFO.osc_type. New codes * must be appended to the enumeration, so the sequence @@ -398,7 +662,7 @@ enum */ #define DEFAULT_GPS_OSC_NAMES \ { \ - "- unknown -", \ + "[unknown]", \ "TCXO LQ", \ "TCXO HQ", \ "OCXO LQ", \ @@ -440,22 +704,31 @@ enum */ -/* +/** * The codes below enumerate some features which may be * supported by a given clock, or not. */ 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 */ - N_GPS_FEATURE /* the number of valid features */ + GPS_FEAT_PPS, /**< has pulse per second output */ + GPS_FEAT_PPM, /**< has pulse per minute output */ + GPS_FEAT_SYNTH, /**< has programmable synthesizer output */ + GPS_FEAT_DCFMARKS, /**< has DCF77 compatible time mark output */ + GPS_FEAT_IRIG_TX, /**< has on-board IRIG output */ + GPS_FEAT_IRIG_RX, /**< has on-board IRIG input */ + GPS_FEAT_LAN_IP4, /**< has 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 */ }; @@ -469,7 +742,15 @@ enum "IRIG In", \ "IPv4 LAN Interface", \ "Multiple Ref. Sources", \ - "GPS receive timeout" \ + "Receive Timeout", \ + "Ignore Lock", \ + "5 MHz Output", \ + "Ext. Multiple Ref. Src. Cfg.", \ + "Supp. Optional Settings", \ + "Configurable Time Scale", \ + "Irig Control Bits", \ + "PTP/IEEE1588", \ + "Supp. Nav. Engine Settings" \ } @@ -477,15 +758,26 @@ 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_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_REF_OFFS GPS_HAS_IRIG_RX + /* * The features below are supported by default by older @@ -505,22 +797,79 @@ enum */ #define GPS_OSC_CFG_SUPP 0x0001 // GPS_OSC_CFG supported #define GPS_IRIG_FO_IN 0x0002 // IRIG input via fiber optics +#define GPS_HAS_FPGA 0x0004 // device provides on-board FPGA + + +/* + * If the GPS_HAS_FPGA flag is set in RECEIVER_INFO::flags then the card + * provides an FPGA and the following information about the FPGA is available: + */ +#define FPGA_NAME_LEN 31 // max name length +#define FPGA_NAME_SIZE ( FPGA_NAME_LEN + 1 ) // size including trailing 0 + +#define FPGA_INFO_SIZE 128 + +typedef union +{ + struct + { + CSUM csum; + uint32_t fsize; + #if _IS_MBG_FIRMWARE + uint32_t start_addr; + #else + uint8_t *start_addr; + #endif + char name[FPGA_NAME_SIZE]; + } hdr; + + char b[FPGA_INFO_SIZE]; + +} FPGA_INFO; -/* Date and time referred to the linear time scale defined by GPS. */ -/* GPS time is defined by the number of weeks since midnight from */ -/* January 5, 1980 to January 6, 1980 plus the number of seconds of */ -/* the current week plus fractions of a second. GPS time differs from */ -/* UTC because UTC is corrected with leap seconds while GPS time scale */ -/* is continuous. */ +/* + * The definitions below are used to specify where a FPGA image is located + * in the flash memory: + */ typedef struct { - uint16_t wn; /* the week number since GPS has been installed */ - uint32_t sec; /* the second of that week */ - uint32_t tick; /* fractions of a second; scale: 1/GPS_TICKS_PER_SEC */ + CSUM csum; + uint16_t fpga_start_seg; // Number of the 4k block where an FPGA image is located +} FPGA_START_INFO; + +#define DEFAULT_FPGA_START_SEG 0x60 + +#define DEFAULT_FPGA_START_INFO \ +{ \ + 0x1234 + DEFAULT_FPGA_START_SEG, \ + DEFAULT_FPGA_START_SEG \ +} + + + +/** + Date and time referred to the linear time scale defined by GPS. + GPS time is defined by the number of weeks since midnight from + January 5, 1980 to January 6, 1980 plus the number of seconds of + the current week plus fractions of a second. GPS time differs from + UTC because UTC is corrected with leap seconds while GPS time scale + is continuous. +*/ +typedef struct +{ + uint16_t wn; /**< the week number since GPS has been installed */ + uint32_t sec; /**< the second of that week */ + uint32_t tick; /**< fractions of a second; scale: 1/GPS_TICKS_PER_SEC */ } T_GPS; +#define _mbg_swab_t_gps( _p ) \ +{ \ + _mbg_swab16( &(_p)->wn ); \ + _mbg_swab32( &(_p)->sec ); \ + _mbg_swab32( &(_p)->tick ); \ +} /* Local date and time computed from GPS time. The current number */ @@ -545,6 +894,15 @@ typedef struct uint16_t status; /* flags */ } TM_GPS; +#define _mbg_swab_tm_gps( _p ) \ +{ \ + _mbg_swab16( &(_p)->year ); \ + _mbg_swab16( &(_p)->yday ); \ + _mbg_swab32( &(_p)->frac ); \ + _mbg_swab32( &(_p)->offs_from_utc ); \ + _mbg_swab16( &(_p)->status ); \ +} + /* status flag bits used with conversion from GPS time to local time */ @@ -569,36 +927,61 @@ enum TM_BIT_NO_POS /* position actually not verified, LOCK LED off */ }; +// Type of an extended TM status which is mainly used by the firmware. +typedef uint32_t TM_STATUS_EXT; // extended status, mainly used by the firmware + +// The lower 16 bits of the TM_STATUS_X type correspond to those defined above, +// and the upper bits are defined below: +enum +{ + TM_BIT_SCALE_GPS = 16, + TM_BIT_SCALE_TAI + // the remaining bits are reserved +}; + /* bit masks corresponding to the flag bits above */ -#define TM_UTC ( 1U << TM_BIT_UTC ) -#define TM_LOCAL ( 1U << TM_BIT_LOCAL ) -#define TM_DL_ANN ( 1U << TM_BIT_DL_ANN ) -#define TM_DL_ENB ( 1U << TM_BIT_DL_ENB ) -#define TM_LS_ANN ( 1U << TM_BIT_LS_ANN ) -#define TM_LS_ENB ( 1U << TM_BIT_LS_ENB ) -#define TM_LS_ANN_NEG ( 1U << TM_BIT_LS_ANN_NEG ) +#define TM_UTC ( 1UL << TM_BIT_UTC ) +#define TM_LOCAL ( 1UL << TM_BIT_LOCAL ) +#define TM_DL_ANN ( 1UL << TM_BIT_DL_ANN ) +#define TM_DL_ENB ( 1UL << TM_BIT_DL_ENB ) +#define TM_LS_ANN ( 1UL << TM_BIT_LS_ANN ) +#define TM_LS_ENB ( 1UL << TM_BIT_LS_ENB ) +#define TM_LS_ANN_NEG ( 1UL << TM_BIT_LS_ANN_NEG ) -#define TM_EXT_SYNC ( 1U << TM_BIT_EXT_SYNC ) -#define TM_HOLDOVER ( 1U << TM_BIT_HOLDOVER ) -#define TM_ANT_SHORT ( 1U << TM_BIT_ANT_SHORT ) -#define TM_NO_WARM ( 1U << TM_BIT_NO_WARM ) -#define TM_ANT_DISCONN ( 1U << TM_BIT_ANT_DISCONN ) -#define TM_SYN_FLAG ( 1U << TM_BIT_SYN_FLAG ) -#define TM_NO_SYNC ( 1U << TM_BIT_NO_SYNC ) -#define TM_NO_POS ( 1U << TM_BIT_NO_POS ) +#define TM_EXT_SYNC ( 1UL << TM_BIT_EXT_SYNC ) +#define TM_HOLDOVER ( 1UL << TM_BIT_HOLDOVER ) +#define TM_ANT_SHORT ( 1UL << TM_BIT_ANT_SHORT ) +#define TM_NO_WARM ( 1UL << TM_BIT_NO_WARM ) +#define TM_ANT_DISCONN ( 1UL << TM_BIT_ANT_DISCONN ) +#define TM_SYN_FLAG ( 1UL << TM_BIT_SYN_FLAG ) +#define TM_NO_SYNC ( 1UL << TM_BIT_NO_SYNC ) +#define TM_NO_POS ( 1UL << TM_BIT_NO_POS ) +// The following bits are only used with the TM_STATUS_X type: +#define TM_SCALE_GPS ( 1UL << TM_BIT_SCALE_GPS ) +#define TM_SCALE_TAI ( 1UL << TM_BIT_SCALE_TAI ) -/* a struct used to transmit information on date and time */ +#define TM_MSK_TIME_VALID ( TM_UTC | TM_SCALE_GPS | TM_SCALE_TAI ) +/** + This structure is used to transmit information on date and time + */ typedef struct { - int16_t channel; /* -1: the current time; 0, 1: capture 0, 1 */ - T_GPS t; /* time in GPS format */ - TM_GPS tm; /* that time converted to local time */ + int16_t channel; /**< -1: the current time; 0, 1: capture 0, 1 */ + T_GPS t; /**< time in GPS format */ + TM_GPS tm; /**< that time converted to local time */ } TTM; +#define _mbg_swab_ttm( _p ) \ +{ \ + _mbg_swab16( &(_p)->channel ); \ + _mbg_swab_t_gps( &(_p)->t ); \ + _mbg_swab_tm_gps( &(_p)->tm ); \ +} + typedef struct @@ -607,6 +990,16 @@ typedef struct int32_t secs; // [seconds] } NANO_TIME; +#define _mbg_swab_nano_time( _p ) \ +{ \ + _mbg_swab32( &(_p)->nano_secs ); \ + _mbg_swab32( &(_p)->secs ); \ +} + +// The macro below checks if a NANO_TIME value is negative. +#define _nano_time_negative( _nt ) \ + ( ( (_nt)->secs < 0 ) || ( (_nt)->nano_secs < 0 ) ) + /* Two types of variables used to store a position. Type XYZ is */ @@ -619,53 +1012,61 @@ typedef struct /* sequence and number of components of a cartesian position */ enum { XP, YP, ZP, N_XYZ }; - /* a type of array holding a cartesian position */ - typedef double XYZ[N_XYZ]; /* values are in [m] */ + /** a type of array holding a cartesian position */ + typedef double XYZ[N_XYZ]; /**< values are in [m] */ #define _XYZ_DEFINED #endif +#define _mbg_swab_xyz( _p ) _mbg_swab_doubles( _p, N_XYZ ) + #ifndef _LLA_DEFINED /* sequence and number of components of a geographic position */ enum { LAT, LON, ALT, N_LLA }; /* latitude, longitude, altitude */ - /* a type of array holding a geographic position */ - typedef double LLA[N_LLA]; /* lon, lat in [rad], alt in [m] */ + /** a type of array holding a geographic position */ + typedef double LLA[N_LLA]; /**< lon, lat in [rad], alt in [m] */ #define _LLA_DEFINED #endif +#define _mbg_swab_lla( _p ) _mbg_swab_doubles( _p, N_LLA ) -/* Synthesizer parameters. Synthesizer frequency is expressed as a */ -/* four digit decimal number (freq) to be multiplied by 0.1 Hz and an */ -/* base 10 exponent (range). If the effective frequency is less than */ -/* 10 kHz its phase is synchronized corresponding to the variable phase. */ -/* Phase may be in a range from -360 deg to +360 deg with a resolution */ -/* of 0.1 deg, so the resulting numbers to be stored are in a range of */ -/* -3600 to +3600. */ +/** + @defgroup group_synth Synthesizer parameters -/* Example: */ -/* Assume the value of freq is 2345 (decimal) and the value of phase is 900. */ -/* If range == 0 the effective frequency is 234.5 Hz with a phase of +90 deg. */ -/* If range == 1 the synthesizer will generate a 2345 Hz output frequency */ -/* and so on. */ + Synthesizer frequency is expressed as a + four digit decimal number (freq) to be multiplied by 0.1 Hz and an + base 10 exponent (range). If the effective frequency is less than + 10 kHz its phase is synchronized corresponding to the variable phase. + Phase may be in a range from -360 deg to +360 deg with a resolution + of 0.1 deg, so the resulting numbers to be stored are in a range of + -3600 to +3600. -/* Limitations: */ -/* If freq == 0 the synthesizer is disabled. If range == 0 the least */ -/* significant digit of freq is limited to 0, 3, 5 or 6. The resulting */ -/* frequency is shown in the examples below: */ -/* freq == 1230 --> 123.0 Hz */ -/* freq == 1233 --> 123 1/3 Hz (real 1/3 Hz, NOT 123.3 Hz) */ -/* freq == 1235 --> 123.5 Hz */ -/* freq == 1236 --> 123 2/3 Hz (real 2/3 Hz, NOT 123.6 Hz) */ + Example:<br> + Assume the value of freq is 2345 (decimal) and the value of phase is 900. + If range == 0 the effective frequency is 234.5 Hz with a phase of +90 deg. + If range == 1 the synthesizer will generate a 2345 Hz output frequency + and so on. -/* If range == MAX_RANGE the value of freq must not exceed 1000, so the */ -/* output frequency is limited to 10 MHz. */ + Limitations:<br> + If freq == 0 the synthesizer is disabled. If range == 0 the least + significant digit of freq is limited to 0, 3, 5 or 6. The resulting + frequency is shown in the examples below: + - freq == 1230 --> 123.0 Hz + - freq == 1233 --> 123 1/3 Hz (real 1/3 Hz, NOT 123.3 Hz) + - freq == 1235 --> 123.5 Hz + - freq == 1236 --> 123 2/3 Hz (real 2/3 Hz, NOT 123.6 Hz) -#define N_SYNTH_FREQ_DIGIT 4 /* number of digits to edit */ -#define MAX_SYNTH_FREQ 1000 /* if range == MAX_SYNTH_RANGE */ + If range == MAX_RANGE the value of freq must not exceed 1000, so the + output frequency is limited to 10 MHz. + @{ +*/ + +#define N_SYNTH_FREQ_DIGIT 4 /**< number of digits to edit */ +#define MAX_SYNTH_FREQ 1000 /**< if range == MAX_SYNTH_RANGE */ #define MIN_SYNTH_RANGE 0 #define MAX_SYNTH_RANGE 5 @@ -675,177 +1076,306 @@ typedef struct #define MAX_SYNTH_PHASE 3600 -#define MAX_SYNTH_FREQ_EDIT 9999 /* max sequence of digits when editing */ +#define MAX_SYNTH_FREQ_EDIT 9999 /**< max sequence of digits when editing */ -/* The maximum frequency that can be configured for the synthesizer */ -#define MAX_SYNTH_FREQ_VAL 10000000UL /* 10 MHz */ +/** The maximum frequency that can be configured for the synthesizer */ +#define MAX_SYNTH_FREQ_VAL 10000000UL /**< 10 MHz */ /* == MAX_SYNTH_FREQ * 10^(MAX_SYNTH_RANGE-1) */ -/* The synthesizer phase will only be synchronized if the frequency */ -/* is below this limit: */ -#define SYNTH_PHASE_SYNC_LIMIT 10000UL /* 10 kHz */ +/** + The synthesizer phase will only be synchronized if the frequency + is below this limit: */ +#define SYNTH_PHASE_SYNC_LIMIT 10000UL /**< 10 kHz */ -/* the position of the decimal point if the frequency is */ -/* printed as 4 digit value */ +/** + the position of the decimal point if the frequency is + printed as 4 digit value */ #define _synth_dp_pos_from_range( _r ) \ ( ( ( N_SYNTH_RANGE - (_r) ) % ( N_SYNTH_FREQ_DIGIT - 1 ) ) + 1 ) +/** + An initializer for commonly displayed synthesizer frequency units + (N_SYNTH_RANGE strings) */ +#define DEFAULT_FREQ_RANGES \ +{ \ + "Hz", \ + "kHz", \ + "kHz", \ + "kHz", \ + "MHz", \ + "MHz", \ +} + typedef struct { - int16_t freq; /* four digits used; scale: 0.1; e.g. 1234 -> 123.4 Hz */ - int16_t range; /* scale factor for freq; 0..MAX_SYNTH_RANGE */ - int16_t phase; /* -MAX_SYNTH_PHASE..+MAX_SYNTH_PHASE; >0 -> pulses later */ + int16_t freq; /**< four digits used; scale: 0.1; e.g. 1234 -> 123.4 Hz */ + int16_t range; /**< scale factor for freq; 0..MAX_SYNTH_RANGE */ + int16_t phase; /**< -MAX_SYNTH_PHASE..+MAX_SYNTH_PHASE; >0 -> pulses later */ } SYNTH; +#define _mbg_swab_synth( _p ) \ +{ \ + _mbg_swab16( &(_p)->freq ); \ + _mbg_swab16( &(_p)->range ); \ + _mbg_swab16( &(_p)->phase ); \ +} -/* The definitions below can be used to query the - * current synthesizer state. + +/** + The definitions below can be used to query the + current synthesizer state. */ enum { - SYNTH_DISABLED, /* disbled by cfg, i.e. freq == 0.0 */ - SYNTH_OFF, /* not enabled after power-up */ - SYNTH_FREE, /* enabled, but not synchronized */ - SYNTH_DRIFTING, /* has initially been sync'd, but now running free */ - SYNTH_SYNC, /* fully synchronized */ - N_SYNTH_STATE /* the number of known states */ + SYNTH_DISABLED, /**< disbled by cfg, i.e. freq == 0.0 */ + SYNTH_OFF, /**< not enabled after power-up */ + SYNTH_FREE, /**< enabled, but not synchronized */ + SYNTH_DRIFTING, /**< has initially been sync'd, but now running free */ + SYNTH_SYNC, /**< fully synchronized */ + N_SYNTH_STATE /**< the number of known states */ }; typedef struct { - uint8_t state; /* state code as enumerated above */ - uint8_t flags; /* reserved, currently always 0 */ + uint8_t state; /**< state code as enumerated above */ + uint8_t flags; /**< reserved, currently always 0 */ } SYNTH_STATE; +#define _mbg_swab_synth_state( _p ) _nop_macro_fnc() + #define SYNTH_FLAG_PHASE_IGNORED 0x01 +/** @} */ // endgroup -/* Time zone/daylight saving parameters. */ +/** + @defgroup group_tzdl Time zone/daylight saving parameters -/* the name of a time zone, 5 characters plus trailing zero */ + Example: <br> + For automatic daylight saving enable/disable in Central Europe, + the variables are to be set as shown below: <br> + - offs = 3600L one hour from UTC + - offs_dl = 3600L one additional hour if daylight saving enabled + - tm_on = first Sunday from March 25, 02:00:00h ( year |= DL_AUTO_FLAG ) + - tm_off = first Sunday from October 25, 03:00:00h ( year |= DL_AUTO_FLAG ) + - name[0] == "CET " name if daylight saving not enabled + - name[1] == "CEST " name if daylight saving is enabled + @{ +*/ + +/** the name of a time zone, 5 characters plus trailing zero */ typedef char TZ_NAME[6]; typedef struct { - int32_t offs; /* offset from UTC to local time [sec] */ - int32_t offs_dl; /* additional offset if daylight saving enabled [sec] */ - TM_GPS tm_on; /* date/time when daylight saving starts */ - TM_GPS tm_off; /* date/time when daylight saving ends */ - TZ_NAME name[2]; /* names without and with daylight saving enabled */ + int32_t offs; /**< offset from UTC to local time [sec] */ + int32_t offs_dl; /**< additional offset if daylight saving enabled [sec] */ + TM_GPS tm_on; /**< date/time when daylight saving starts */ + TM_GPS tm_off; /**< date/time when daylight saving ends */ + TZ_NAME name[2]; /**< names without and with daylight saving enabled */ } TZDL; -/* The constant below is defined beginning with software rev. 1.29. */ -/* If the year in tzdl.tm_on and tzdl.tm_off is or'ed with that constant, */ -/* the receiver automatically generates daylight saving year by year. */ -/* See GPSLIB.TXT for more information. */ +#define _mbg_swab_tzdl( _p ) \ +{ \ + _mbg_swab32( &(_p)->offs ); \ + _mbg_swab32( &(_p)->offs_dl ); \ + _mbg_swab_tm_gps( &(_p)->tm_on ); \ + _mbg_swab_tm_gps( &(_p)->tm_off ); \ +} + +/** + If the year in tzdl.tm_on and tzdl.tm_off is or'ed with that constant, + the receiver automatically generates daylight saving year by year. + */ #define DL_AUTO_FLAG 0x8000 -/* Example: */ -/* For automatic daylight saving enable/disable in Central Europe, */ -/* the variables are to be set as shown below: */ -/* offs = 3600L one hour from UTC */ -/* offs_dl = 3600L one additional hour if daylight saving enabled */ -/* tm_on = first Sunday from March 25, 02:00:00h ( year |= DL_AUTO_FLAG ) */ -/* tm_off = first Sunday from October 25, 03:00:00h ( year |= DL_AUTO_FLAG ) */ -/* name[0] == "CET " name if daylight saving not enabled */ -/* name[1] == "CEST " name if daylight saving is enabled */ // Below there are some initializers for commonly used TZDL configurations: +#define DEFAULT_TZDL_AUTO_YEAR ( 2007 | DL_AUTO_FLAG ) + +#define DEFAULt_TZDL_OFFS_DL 3600L /**< usually DST is +1 hour */ + + +/** + The symbol below can be used to initialize both the tm_on + and tm_off fields for time zones which do not switch to DST: + */ +#define DEFAULT_TZDL_TM_ON_OFF_NO_DST \ + { DEFAULT_TZDL_AUTO_YEAR, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 } + + +// Settings used with UTC: + #define TZ_INFO_UTC "UTC (Universal Time, Coordinated)" -#define DEFAULT_TZDL_UTC \ -{ \ - 0L, /* offs */ \ - 0L, /* offs_dl */ \ - { 1994 | DL_AUTO_FLAG, 1, 1, 0, 0, 0, 0, 0, 0L, 0L, 0 }, /* tm_on */ \ - { 1994 | DL_AUTO_FLAG, 1, 1, 0, 0, 0, 0, 0, 0L, 0L, 0 }, /* tm_off */ \ - { "UTC ", "UTC " } /* name[] */ \ + +#define DEFAULT_TZDL_NAMES_UTC { "UTC ", "UTC " } + +#define DEFAULT_TZDL_UTC \ +{ \ + 0L, /**< offs */ \ + 0L, /**< offs_dl */ \ + DEFAULT_TZDL_TM_ON_OFF_NO_DST, /**< tm_on */ \ + DEFAULT_TZDL_TM_ON_OFF_NO_DST, /**< tm_off */ \ + DEFAULT_TZDL_NAMES_UTC /**< name[] */ \ } -#define TZ_INFO_CET "CET/CEST (Central Europe)" -#define DEFAULT_TZDL_CET \ -{ \ - 3600L, /* offs */ \ - 3600L, /* offs_dl */ \ - { 1994 | DL_AUTO_FLAG, 3, 25, 0, 0, 2, 0, 0, 0L, 0L, 0 }, /* tm_on */ \ - { 1990 | DL_AUTO_FLAG, 10, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 }, /* tm_off */ \ - { "CET ", "CEST " } /* name[] */ \ + +/** + The symbols below specify beginning and end of DST for + Central Europe, as constituted by the European Parliament: + */ + +#define DEFAULT_TZDL_TM_ON_CET_CEST \ + { DEFAULT_TZDL_AUTO_YEAR, 3, 25, 0, 0, 2, 0, 0, 0L, 0L, 0 } + +#define DEFAULT_TZDL_TM_OFF_CET_CEST \ + { DEFAULT_TZDL_AUTO_YEAR, 10, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 } + + +// Settings used with Central European Time: + +#define TZ_INFO_CET_CEST_EN "CET/CEST (Central Europe)" +#define TZ_INFO_CET_CEST_DE "MEZ/MESZ (Mitteleuropa)" + +#define DEFAULT_TZDL_NAMES_CET_CEST_EN { "CET ", "CEST " } +#define DEFAULT_TZDL_NAMES_CET_CEST_DE { "MEZ ", "MESZ " } + +#define DEFAULT_TZDL_OFFS_CET 3600L + +#define DEFAULT_TZDL_CET_CEST_EN \ +{ \ + DEFAULT_TZDL_OFFS_CET, /**< offs */ \ + DEFAULt_TZDL_OFFS_DL, /**< offs_dl */ \ + DEFAULT_TZDL_TM_ON_CET_CEST, /**< tm_on */ \ + DEFAULT_TZDL_TM_OFF_CET_CEST, /**< tm_off */ \ + DEFAULT_TZDL_NAMES_CET_CEST_EN /**< name[] */ \ } +#define DEFAULT_TZDL_CET_CEST_DE \ +{ \ + DEFAULT_TZDL_OFFS_CET, /**< offs */ \ + DEFAULt_TZDL_OFFS_DL, /**< offs_dl */ \ + DEFAULT_TZDL_TM_ON_CET_CEST, /**< tm_on */ \ + DEFAULT_TZDL_TM_OFF_CET_CEST, /**< tm_off */ \ + DEFAULT_TZDL_NAMES_CET_CEST_DE /**< name[] */ \ +} + + +// The symbols below specify beginning and end of DST for +// Easter Europe, as constituted by the European Parliament: + +#define DEFAULT_TZDL_TM_ON_EET_EEST \ + { DEFAULT_TZDL_AUTO_YEAR, 3, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 } + +#define DEFAULT_TZDL_TM_OFF_EET_EEST \ + { DEFAULT_TZDL_AUTO_YEAR, 10, 25, 0, 0, 4, 0, 0, 0L, 0L, 0 } + + +// Settings used with Eastern European Time: + +#define TZ_INFO_EET_EEST_EN "EET/EEST (East Europe)" +#define TZ_INFO_EET_EEST_DE "OEZ/OEST (Osteuropa)" + +#define DEFAULT_TZDL_NAMES_EET_EEST_EN { "EET ", "EEST " } +#define DEFAULT_TZDL_NAMES_EET_EEST_DE { "OEZ ", "OESZ " } -#define TZ_INFO_EET "EET/EEST (Easter Europe)" -#define DEFAULT_TZDL_EET \ -{ \ - 7200L, /* offs */ \ - 3600L, /* offs_dl */ \ - { 1994 | DL_AUTO_FLAG, 3, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 }, /* tm_on */ \ - { 1990 | DL_AUTO_FLAG, 10, 25, 0, 0, 4, 0, 0, 0L, 0L, 0 }, /* tm_off */ \ - { "EET ", "EEST " } /* name[] */ \ +#define DEFAULT_TZDL_OFFS_EET 7200L + +#define DEFAULT_TZDL_EET_EEST_EN \ +{ \ + DEFAULT_TZDL_OFFS_EET, /* offs */ \ + DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \ + DEFAULT_TZDL_TM_ON_EET_EEST, /* tm_on */ \ + DEFAULT_TZDL_TM_OFF_EET_EEST, /* tm_off */ \ + DEFAULT_TZDL_NAMES_EET_EEST_EN /* name[] */ \ } +#define DEFAULT_TZDL_EET_EEST_DE \ +{ \ + DEFAULT_TZDL_OFFS_EET, /* offs */ \ + DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \ + DEFAULT_TZDL_TM_ON_EET_EEST, /* tm_on */ \ + DEFAULT_TZDL_TM_OFF_EET_EEST, /* tm_off */ \ + DEFAULT_TZDL_NAMES_EET_EEST_DE /* name[] */ \ +} +/** @} */ // endgroup -/* - * The structure below was defined wit GPS166 v1.31. It reflects the - * status of the antenna, the times of last disconnect/reconnect, - * and the board's clock offset after disconnection interval. +/** + * The structure below reflects the status of the antenna, + * the times of last disconnect/reconnect, and the board's + * clock offset after the disconnection interval. */ typedef struct { - int16_t status; /* current status of antenna */ - TM_GPS tm_disconn; /* time of antenna disconnect */ - TM_GPS tm_reconn; /* time of antenna reconnect */ - int32_t delta_t; /* clock offs. at reconn. time in GPS_TICKS_PER_SEC */ + int16_t status; /**< current status of antenna */ + TM_GPS tm_disconn; /**< time of antenna disconnect */ + TM_GPS tm_reconn; /**< time of antenna reconnect */ + int32_t delta_t; /**< clock offs. at reconn. time in #GPS_TICKS_PER_SEC */ } ANT_INFO; +#define _mbg_swab_ant_info( _p ) \ +{ \ + _mbg_swab16( &(_p)->status ); \ + _mbg_swab_tm_gps( &(_p)->tm_disconn ); \ + _mbg_swab_tm_gps( &(_p)->tm_reconn ); \ + _mbg_swab32( &(_p)->delta_t ); \ +} - -/* The status field may be set to one of the values below: */ - +/** + The status field may be set to one of the values below: +*/ enum { - ANT_INVALID, /* struct not set yet because ant. has not been disconn. */ - ANT_DISCONN, /* ant. now disconn., tm_reconn and delta_t not set */ - ANT_RECONN /* ant. has been disconn. and reconn., all fields valid */ + ANT_INVALID, /**< struct not set yet because ant. has not been disconn. */ + ANT_DISCONN, /**< ant. now disconn., tm_reconn and delta_t not set */ + ANT_RECONN /**< ant. has been disconn. and reconn., all fields valid */ }; +/* Defines used with ENABLE_FLAGS */ +#define EF_OFF 0x00 /**< outputs off until sync'd */ +#define EF_SERIAL_BOTH 0x03 /**< both serial ports on */ +#define EF_PULSES_BOTH 0x03 /**< both pulses P_SEC and P_MIN on */ +#define EF_FREQ_ALL 0x07 /**< all fixed freq. outputs on */ +#define EF_SYNTH 0x01 /**< synth. on */ -/* The structure below was defined in rev. 1.47. It holds some flags */ -/* which let the corresponding outputs be disabled after power-up until */ -/* the receiver has synchronized (flag == 0x00, the default) or force */ -/* the outputs to be enabled immediately after power-up. The fixed */ -/* frequency output is hard-wired to be enabled immediately after */ -/* power-up, so the code for freq must always be 0x03. */ - -#define EF_OFF 0x00 /* outputs off until sync'd */ - -#define EF_SERIAL_BOTH 0x03 /* both serial ports on */ -#define EF_PULSES_BOTH 0x03 /* both pulses P_SEC and P_MIN on */ -#define EF_FREQ_ALL 0x07 /* all fixed freq. outputs on */ -#define EF_SYNTH 0x01 /* synth. on */ - +/** + The structure holds some flags which let + the corresponding outputs be disabled after power-up until + the receiver has synchronized (flag == 0x00, the default) or force + the outputs to be enabled immediately after power-up. The fixed + frequency output is hard-wired to be enabled immediately after + power-up, so the code for freq must always be 0x03. +*/ typedef struct { - uint16_t serial; /* EF_OFF or EF_SERIAL_ON_BOTH */ - uint16_t pulses; /* EF_OFF or EF_PULSES_ON_BOTH */ - uint16_t freq; /* always EF_FREQ_ON_ALL */ - uint16_t synth; /* EF_OFF or EF_SYNTH_ON */ + uint16_t serial; /**< #EF_OFF or #EF_SERIAL_BOTH */ + uint16_t pulses; /**< #EF_OFF or #EF_PULSES_BOTH */ + uint16_t freq; /**< always #EF_FREQ_ALL */ + uint16_t synth; /**< #EF_OFF or #EF_SYNTH */ } ENABLE_FLAGS; +#define _mbg_swab_enable_flags( _p ) \ +{ \ + _mbg_swab16( &(_p)->serial ); \ + _mbg_swab16( &(_p)->pulses ); \ + _mbg_swab16( &(_p)->freq ); \ + _mbg_swab16( &(_p)->synth ); \ +} /* A struct used to hold the settings of a serial port: */ #ifndef _COM_HS_DEFINED /* types of handshake */ - enum { HS_NONE, HS_XONXOFF, HS_RTSCTS }; + enum { HS_NONE, HS_XONXOFF, HS_RTSCTS, N_COM_HS }; #define _COM_HS_DEFINED #endif @@ -865,6 +1395,13 @@ typedef struct #define _COM_PARM_DEFINED #endif +#define _mbg_swab_baud_rate( _p ) _mbg_swab32( _p ) + +#define _mbg_swab_com_parm( _p ) \ +{ \ + _mbg_swab_baud_rate( &(_p)->baud_rate ); \ + _mbg_swab16( &(_p)->handshake ); \ +} /* @@ -1055,6 +1592,57 @@ typedef struct uint32_t flags; /* reserved for future use, currently 0 */ } PORT_SETTINGS; +#define _mbg_swab_port_settings( _p ) \ +{ \ + _mbg_swab_com_parm( &(_p)->parm ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/* + * The definitions below can be used to mark specific fields of a + * PORT_SETTINGS structure, e.g. when editing build a mask indicating + * which of the fields have changed or which are not valid. + */ +enum +{ + MBG_PS_BIT_BAUD_RATE_OVR_SW, /* Baud rate index exceeds num supp by driver SW */ + MBG_PS_BIT_BAUD_RATE_OVR_DEV, /* Baud rate index exceeds num supp by device */ + MBG_PS_BIT_BAUD_RATE, /* Baud rate not supp by given port */ + MBG_PS_BIT_FRAMING_OVR_SW, /* Framing index exceeds num supp by driver SW */ + MBG_PS_BIT_FRAMING_OVR_DEV, /* Framing index exceeds num supp by device */ + MBG_PS_BIT_FRAMING, /* Framing not supp by given port */ + MBG_PS_BIT_HS_OVR_SW, /* Handshake index exceeds num supp by driver SW */ + MBG_PS_BIT_HS, /* Handshake mode not supp by given port */ + MBG_PS_BIT_STR_TYPE_OVR_SW, /* String type index exceeds num supp by driver SW */ + MBG_PS_BIT_STR_TYPE_OVR_DEV, /* String type index exceeds num supp by device */ + MBG_PS_BIT_STR_TYPE, /* String type not supp by given port */ + MBG_PS_BIT_STR_MODE_OVR_SW, /* String mode index exceeds num supp by driver SW */ + MBG_PS_BIT_STR_MODE_OVR_DEV, /* String mode index exceeds num supp by device */ + MBG_PS_BIT_STR_MODE, /* String mode not supp by given port and string type */ + MBG_PS_BIT_FLAGS_OVR_SW, /* Flags not supp by driver SW */ + MBG_PS_BIT_FLAGS, /* Flags not supp by device */ + N_MBG_PS_BIT +}; + +#define MBG_PS_MSK_BAUD_RATE_OVR_SW ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_SW ) +#define MBG_PS_MSK_BAUD_RATE_OVR_DEV ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_DEV ) +#define MBG_PS_MSK_BAUD_RATE ( 1UL << MBG_PS_BIT_BAUD_RATE ) +#define MBG_PS_MSK_FRAMING_OVR_SW ( 1UL << MBG_PS_BIT_FRAMING_OVR_SW ) +#define MBG_PS_MSK_FRAMING_OVR_DEV ( 1UL << MBG_PS_BIT_FRAMING_OVR_DEV ) +#define MBG_PS_MSK_FRAMING ( 1UL << MBG_PS_BIT_FRAMING ) +#define MBG_PS_MSK_HS_OVR_SW ( 1UL << MBG_PS_BIT_HS_OVR_SW ) +#define MBG_PS_MSK_HS ( 1UL << MBG_PS_BIT_HS ) +#define MBG_PS_MSK_STR_TYPE_OVR_SW ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_SW ) +#define MBG_PS_MSK_STR_TYPE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_DEV ) +#define MBG_PS_MSK_STR_TYPE ( 1UL << MBG_PS_BIT_STR_TYPE ) +#define MBG_PS_MSK_STR_MODE_OVR_SW ( 1UL << MBG_PS_BIT_STR_MODE_OVR_SW ) +#define MBG_PS_MSK_STR_MODE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_MODE_OVR_DEV ) +#define MBG_PS_MSK_STR_MODE ( 1UL << MBG_PS_BIT_STR_MODE ) +#define MBG_PS_MSK_FLAGS_OVR_SW ( 1UL << MBG_PS_BIT_FLAGS_OVR_SW ) +#define MBG_PS_MSK_FLAGS ( 1UL << MBG_PS_BIT_FLAGS ) + + /* * The structure below adds an index number to the structure @@ -1066,6 +1654,12 @@ typedef struct PORT_SETTINGS port_settings; } PORT_SETTINGS_IDX; +#define _mbg_swab_port_settings_idx( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_port_settings( &(_p)->port_settings ); \ +} + /* * The structure below holds the current settings @@ -1084,6 +1678,16 @@ typedef struct uint32_t flags; /* reserved for future use, currently 0 */ } PORT_INFO; +#define _mbg_swab_port_info( _p ) \ +{ \ + _mbg_swab_port_settings( &(_p)->port_settings ); \ + _mbg_swab32( &(_p)->supp_baud_rates ); \ + _mbg_swab32( &(_p)->supp_framings ); \ + _mbg_swab32( &(_p)->supp_str_types ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} + /* * The structure below adds an index number to the structure @@ -1095,6 +1699,12 @@ typedef struct PORT_INFO port_info; } PORT_INFO_IDX; +#define _mbg_swab_port_info_idx( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_port_info( &(_p)->port_info ); \ +} + /* * The structure below keeps information for a given @@ -1109,6 +1719,13 @@ typedef struct uint16_t flags; /* reserved, currently always 0 */ } STR_TYPE_INFO; +#define _mbg_swab_str_type_info( _p ) \ +{ \ + _mbg_swab32( &(_p)->supp_modes ); \ + _mbg_swab16( &(_p)->flags ); \ +} + + /* * The structure below adds an index number to the structure @@ -1120,6 +1737,12 @@ typedef struct STR_TYPE_INFO str_type_info; } STR_TYPE_INFO_IDX; +#define _mbg_swab_str_type_info_idx( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_str_type_info( &(_p)->str_type_info ); \ +} + /* * The codes below define valid modes for time strings, @@ -1200,7 +1823,7 @@ enum -/* +/** * The number of serial ports which were available * with all GPS receiver models: */ @@ -1214,16 +1837,26 @@ enum #define N_COM DEFAULT_N_COM #endif -/* - * The structure used to store the modes of both serial ports: - * (now obsolete) +/** + * The structure used to store the modes of both serial ports:<br> + * <b>(now obsolete)</b> */ typedef struct { - COM_PARM com[DEFAULT_N_COM]; /* COM0 and COM1 settings */ - uint8_t mode[DEFAULT_N_COM]; /* COM0 and COM1 output mode */ + COM_PARM com[DEFAULT_N_COM]; /**< COM0 and COM1 settings */ + uint8_t mode[DEFAULT_N_COM]; /**< COM0 and COM1 output mode */ } PORT_PARM; +#define _mbg_swab_port_parm( _p ) \ +{ \ + int i; \ + for ( i = 0; i < DEFAULT_N_COM; i++ ) \ + { \ + _mbg_swab_com_parm( &(_p)->com[i] ); \ + /* no need to swap mode byte */ \ + } \ +} + /* * The codes below were used with the obsolete @@ -1243,44 +1876,47 @@ enum -/* - * The following definitions are used to configure an optional - * on-board IRIG input or output. - * 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. - */ +/** + @defgroup group_icode Irig Codes -/* - * Supported IRIG signal code types: - * A002 1000 bps, DC shift, time-of-year - * A003 1000 bps, DC shift, time-of-year, SBS - * A132 1000 bps, 10 kHz carrier, time-of-year - * A133 1000 bps, 10 kHz carrier, time-of-year, SBS - * B002 100 bps, DC shift, time-of-year - * B003 100 bps, DC shift, time-of-year, SBS - * B122 100 bps, 1 kHz carrier, time-of-year - * B123 100 bps, 1 kHz carrier, time-of-year, SBS - * AFNOR 100 bps, 1 kHz carrier, SBS, complete date - * AFNOR DC 100 bps, DC shift, SBS, complete date - * IEEE1344 100 bps, 1 kHz carrier, time-of-year, SBS, IEEE1344 extensions (B120) - * IEEE1344 DC 100 bps, DC shift, time-of-year, SBS, IEEE1344 extensions (B000) - * B220/1344 100 bps, DC shift, manchester encoded, IEEE1344 extensions - * B222 100 bps, DC shift, manchester encoded, time-of-year - * B223 100 bps, DC shift, manchester encoded, time-of-year, SBS - * - * time-of-year: day-of-year, hours, minutes, seconds - * SBS: straight binary seconds, second-of-day - * IEEE1344 extensions: time zone info - * AFNOR: french standard AFNOR NFS-87500 + The following definitions are used to configure an optional + on-board IRIG input or output. + + 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. + + + - 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 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 B122: 100 bps, 1 kHz carrier, time-of-year + - \b B123: 100 bps, 1 kHz carrier, time-of-year, SBS + - \b AFNOR: 100 bps, 1 kHz carrier, SBS, complete date + - <b> AFNOR DC:</b> 100 bps, DC shift, 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 + + - time-of-year: day-of-year, hours, minutes, seconds + - SBS: straight binary seconds, second-of-day + - IEEE1344 extensions: time zone info + - AFNOR: french standard AFNOR NFS-87500 + + @{ */ -/* +/** * Definitions used with IRIG transmitters which generate * the same IRIG code both with and without carrier signal - * at the same time. - */ + * at the same time. */ enum { ICODE_TX_B002_B122, @@ -1293,12 +1929,14 @@ enum ICODE_TX_B222, ICODE_TX_B223, ICODE_TX_B006_B126, - ICODE_TX_B007_B127, - N_ICODE_TX /* number of code types */ + ICODE_TX_B007_B127, + ICODE_TX_G002_G142, + ICODE_TX_G006_G146, + N_ICODE_TX /**< number of code types */ }; -/* +/** * Initializers for format name strings. */ #define DEFAULT_ICODE_TX_NAMES \ @@ -1313,25 +1951,29 @@ enum "B222+B122", \ "B223+B123", \ "B006+B126", \ - "B007+B127" \ + "B007+B127", \ + "G002+G142", \ + "G006+G146" \ } -/* +/** * 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, time zone info", \ - "100 bps, DC manchester enc. or 1kHz carrier, SBS, time zone info", \ - "100 bps, DC manchester enc. or 1kHz carrier, time-of-year", \ - "100 bps, DC manchester enc. or 1kHz carrier, time-of-year, SBS", \ - "100 bps, DC or 1 kHz carrier, complete date", \ - "100 bps, DC or 1 kHz carrier, complete date, SBS" \ +#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" \ } /* @@ -1350,8 +1992,10 @@ enum #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 ) -/* +/** * A mask of IRIG formats with manchester encoded DC output: */ #define MSK_ICODE_TX_DC_MANCH \ @@ -1361,7 +2005,7 @@ enum MSK_ICODE_TX_B223 \ ) -/* +/** * A mask of IRIG formats with 1 kHz carrier: */ #define MSK_ICODE_TX_1KHZ \ @@ -1377,7 +2021,7 @@ enum MSK_ICODE_TX_B007_B127 \ ) -/* +/** * A mask of IRIG formats with 10 kHz carrier: */ #define MSK_ICODE_TX_10KHZ \ @@ -1386,7 +2030,16 @@ enum MSK_ICODE_TX_A003_A133 \ ) -/* +/** + * A mask of IRIG formats with 100 kHz carrier: + */ +#define MSK_ICODE_TX_100KHZ \ +( \ + MSK_ICODE_TX_G002_G142 | \ + MSK_ICODE_TX_G006_G146 \ +) + +/** * A mask of IRIG formats with 100 bps data rate: */ #define MSK_ICODE_TX_100BPS \ @@ -1399,7 +2052,7 @@ enum MSK_ICODE_TX_B007_B127 \ ) -/* +/** * A mask of IRIG formats with 1000 bps data rate: */ #define MSK_ICODE_TX_1000BPS \ @@ -1408,7 +2061,16 @@ enum MSK_ICODE_TX_A003_A133 \ ) -/* +/** + * A mask of IRIG formats with 10 kbps data rate: + */ +#define MSK_ICODE_TX_10000BPS \ +( \ + MSK_ICODE_TX_G002_G142 | \ + MSK_ICODE_TX_G006_G146 \ +) + +/** * A mask of IRIG formats which support TFOM: */ #define MSK_ICODE_TX_HAS_TFOM \ @@ -1416,7 +2078,7 @@ enum MSK_ICODE_TX_IEEE1344 \ ) -/* +/** * A mask of IRIG formats which support time zone information: */ #define MSK_ICODE_TX_HAS_TZI \ @@ -1424,7 +2086,7 @@ enum MSK_ICODE_TX_IEEE1344 \ ) -/* +/** * The default mask of IRIG formats supported by * IRIG transmitters: */ @@ -1441,7 +2103,7 @@ enum -/* +/** * Definitions used with IRIG receivers which decode * two similar IRIG codes * at the same time. @@ -1458,10 +2120,12 @@ enum ICODE_RX_IEEE1344_DC, ICODE_RX_B126_B127, ICODE_RX_B006_B007, + ICODE_RX_G142_G146, + ICODE_RX_G002_G006, N_ICODE_RX /* the number of valid signal code types */ }; -/* +/** * Initializers for format name strings. */ #define DEFAULT_ICODE_RX_NAMES \ @@ -1475,10 +2139,12 @@ enum "IEEE1344", \ "IEEE1344 (DC)", \ "B126/B127", \ - "B006/B007 (DC)" \ + "B006/B007 (DC)", \ + "G142/G146", \ + "G002/G006 (DC)" \ } -/* +/** * Initializers for English format description strings. */ #define DEFAULT_ICODE_RX_DESCRIPTIONS_ENG \ @@ -1492,7 +2158,9 @@ enum "100 bps, 1 kHz carrier, SBS, time zone info", \ "100 bps, DC shift, SBS, time zone info", \ "100 bps, 1 kHz carrier, complete date, SBS optionally", \ - "100 bps, DC shift, complete date, SBS optionally" \ + "100 bps, DC shift, complete date, SBS optionally", \ + "10 kbps, 100 kHz carrier, complete date optionally", \ + "10 kbps, DC shift, complete date optionally" \ } /* @@ -1508,8 +2176,10 @@ enum #define MSK_ICODE_RX_IEEE1344_DC ( 1UL << ICODE_RX_IEEE1344_DC ) #define MSK_ICODE_RX_B126_B127 ( 1UL << ICODE_RX_B126_B127 ) #define MSK_ICODE_RX_B006_B007 ( 1UL << ICODE_RX_B006_B007 ) +#define MSK_ICODE_RX_G142_G146 ( 1UL << ICODE_RX_G142_G146 ) +#define MSK_ICODE_RX_G002_G006 ( 1UL << ICODE_RX_G002_G006 ) -/* +/** * A mask of IRIG formats which have DC shift: */ #define MSK_ICODE_RX_DC \ @@ -1518,10 +2188,11 @@ enum MSK_ICODE_RX_A002_A003 | \ MSK_ICODE_RX_AFNOR_DC | \ MSK_ICODE_RX_IEEE1344_DC | \ - MSK_ICODE_RX_B006_B007 \ + MSK_ICODE_RX_B006_B007 | \ + MSK_ICODE_RX_G002_G006 \ ) -/* +/** * A mask of IRIG formats with 1 kHz carrier: */ #define MSK_ICODE_RX_1KHZ \ @@ -1532,7 +2203,7 @@ enum MSK_ICODE_RX_B126_B127 \ ) -/* +/** * A mask of IRIG formats with 10 kHz carrier: */ #define MSK_ICODE_RX_10KHZ \ @@ -1540,7 +2211,15 @@ enum MSK_ICODE_RX_A132_A133 \ ) -/* +/** + * A mask of IRIG formats with 100 kHz carrier: + */ +#define MSK_ICODE_RX_100KHZ \ +( \ + MSK_ICODE_RX_G142_G146 \ +) + +/** * A mask of IRIG formats with 100 bps data rate: */ #define MSK_ICODE_RX_100BPS \ @@ -1555,7 +2234,7 @@ enum MSK_ICODE_RX_B006_B007 \ ) -/* +/** * A mask of IRIG formats with 1000 bps data rate: */ #define MSK_ICODE_RX_1000BPS \ @@ -1564,7 +2243,15 @@ enum MSK_ICODE_RX_A002_A003 \ ) -/* +/** + * A mask of IRIG formats with 10 kbps data rate: + */ +#define MSK_ICODE_RX_10000BPS \ +( \ + MSK_ICODE_RX_G142_G146 \ +) + +/** * A mask of IRIG formats which support TFOM: */ #define MSK_ICODE_RX_HAS_TFOM \ @@ -1573,7 +2260,7 @@ enum MSK_ICODE_RX_IEEE1344_DC \ ) -/* +/** * A mask of IRIG formats which support time zone information: */ #define MSK_ICODE_RX_HAS_TZI \ @@ -1582,7 +2269,7 @@ enum MSK_ICODE_RX_IEEE1344_DC \ ) -/* +/** * The default mask of IRIG formats supported by * IRIG receivers: */ @@ -1597,53 +2284,161 @@ enum MSK_ICODE_RX_AFNOR_DC \ ) #endif +/** @} */ - -/* +/** * The structure below is used to configure an optional * on-board IRIG output: */ typedef struct { - uint16_t icode; /* IRIG signal code, as enumerated above */ - uint16_t flags; /* (codes defined below) */ + uint16_t icode; /**< IRIG signal code, see \ref group_icode */ + uint16_t flags; /**< see \ref group_irig_flags */ } IRIG_SETTINGS; +#define _mbg_swab_irig_settings( _p ) \ +{ \ + _mbg_swab16( &(_p)->icode ); \ + _mbg_swab16( &(_p)->flags ); \ +} + -/* bit masks used with IRIG_SETTINGS.flags (others are reserved): */ +/** + @defgroup group_irig_flags Bit Masks used with IRIG_SETTINGS.flags -#define IFLAGS_DISABLE_TFOM 0x0001 /* RX ignore/TX don't gen TFOM */ -#define IFLAGS_TX_GEN_LOCAL_TIME 0x0002 /* gen local time, not UTC */ + (others are reserved) +* @{ + */ +#define IFLAGS_DISABLE_TFOM 0x0001 /**< RX ignore/TX don't gen TFOM */ +#define IFLAGS_TX_GEN_LOCAL_TIME 0x0002 /**< gen local time, not UTC */ -#define IFLAGS_MASK 0x0003 /* flags above or'ed */ +#define IFLAGS_MASK 0x0003 /**< flags above or'ed */ +/** @} */ -/* - * The structure below is used to query the IRIG configuration +/** + * The structure is used to query the IRIG configuration * plus the supported codes: */ typedef struct { IRIG_SETTINGS settings; - uint32_t supp_codes; /* bit mask of supported codes */ + uint32_t supp_codes; /**< bit mask of supported codes */ } IRIG_INFO; +#define _mbg_swab_irig_info( _p ) \ +{ \ + _mbg_swab_irig_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_codes ); \ +} + + +// The type below is used to read the board's debug status +// which also include IRIG decoder status: +typedef uint32_t MBG_DEBUG_STATUS; + +// The debug status is bit coded as defined below: +enum +{ + MBG_IRIG_BIT_WARMED_UP, /**< Osc has warmed up */ + MBG_IRIG_BIT_PPS_ACTIVE, /**< PPS output is active */ + MBG_IRIG_BIT_INV_CONFIG, /**< Invalid config, e.g. data csum error */ + MBG_IRIG_BIT_MSG_DECODED, /**< IRIG msg could be decoded */ + MBG_IRIG_BIT_MSG_INCONSISTENT, /**< IRIG msg contains inconsistent data */ + MBG_IRIG_BIT_LOOP_LOCKED, /**< Decoder control loop is locked */ + MBG_IRIG_BIT_JITTER_TOO_LARGE, /**< Phase jitter too large */ + MBG_IRIG_BIT_INV_REF_OFFS, /**< UTC ref offset not configured */ + + MBG_SYS_BIT_INV_TIME, /**< Internal time not valid/set */ + MBG_SYS_BIT_TIME_SET_VIA_API, /**< On board time set externally */ + MBG_SYS_BIT_INV_RTC, /**< On board RTC invalid */ + MBG_SYS_BIT_CPU_PLL_FAILED, /**< The CPU's PLL watchdog */ + + N_MBG_DEBUG_BIT +}; + +/* + * Initializers for IRIG status bit strings. + */ +#define MBG_DEBUG_STATUS_STRS \ +{ \ + "Osc has warmed up", \ + "PPS output is active", \ + "Config set to default", \ + "IRIG msg decoded", \ + "IRIG msg not consistent", \ + "Decoder control loop locked", \ + "Phase jitter too large", \ + "Invalid ref offset", \ + \ + "Internal time not valid", \ + "On board time set via API", \ + "On board RTC invalid", \ + "CPU PLL failure, needs restart" \ +} + + + +#define MBG_IRIG_MSK_WARMED_UP ( 1UL << MBG_IRIG_BIT_WARMED_UP ) +#define MBG_IRIG_MSK_PPS_ACTIVE ( 1UL << MBG_IRIG_BIT_PPS_ACTIVE ) +#define MBG_IRIG_MSK_INV_CONFIG ( 1UL << MBG_IRIG_BIT_INV_CONFIG ) +#define MBG_IRIG_MSK_MSG_DECODED ( 1UL << MBG_IRIG_BIT_MSG_DECODED ) +#define MBG_IRIG_MSK_MSG_INCONSISTENT ( 1UL << MBG_IRIG_BIT_MSG_INCONSISTENT ) +#define MBG_IRIG_MSK_LOOP_LOCKED ( 1UL << MBG_IRIG_BIT_LOOP_LOCKED ) +#define MBG_IRIG_MSK_JITTER_TOO_LARGE ( 1UL << MBG_IRIG_BIT_JITTER_TOO_LARGE ) +#define MBG_IRIG_MSK_INV_REF_OFFS ( 1UL << MBG_IRIG_BIT_INV_REF_OFFS ) + +#define MBG_SYS_MSK_INV_TIME ( 1UL << MBG_SYS_BIT_INV_TIME ) +#define MBG_SYS_MSK_TIME_SET_VIA_API ( 1UL << MBG_SYS_BIT_TIME_SET_VIA_API ) +#define MBG_SYS_MSK_INV_RTC ( 1UL << MBG_SYS_BIT_INV_RTC ) +#define MBG_SYS_MSK_CPU_PLL_FAILED ( 1UL << MBG_SYS_BIT_CPU_PLL_FAILED ) + + + +typedef int16_t MBG_REF_OFFS; /**< -MBG_REF_OFFS_MAX..MBG_REF_OFFS_MAX */ + +#define _mbg_swab_mbg_ref_offs( _p ) _mbg_swab16( (_p) ) + + +/** the maximum allowed positive / negative offset */ +#define MBG_REF_OFFS_MAX ( ( 12L * 60 ) + 30 ) // [minutes] + +/** + * the following value is used to indicate that the ref offset + * value has not yet been configured + */ +#define MBG_REF_OFFS_NOT_CFGD 0x8000 + typedef struct { uint32_t flags; } MBG_OPT_SETTINGS; +#define _mbg_swab_mbg_opt_settings( _p ) \ +{ \ + _mbg_swab32( &(_p)->flags ); \ +} + + typedef struct { MBG_OPT_SETTINGS settings; uint32_t supp_flags; } MBG_OPT_INFO; +#define _mbg_swab_mbg_opt_info( _p ) \ +{ \ + _mbg_swab_mbg_opt_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_flags ); \ +} + + enum { - MBG_OPT_BIT_STR_UTC, // serial string contains UTC time - MBG_OPT_BIT_EMU_SYNC, // emulate/pretend to be synchronized + MBG_OPT_BIT_STR_UTC, /**< serial string contains UTC time */ + MBG_OPT_BIT_EMU_SYNC, /**< emulate/pretend to be synchronized, */ + /**< alternatively GPS_FEAT_IGNORE_LOCK may be supported */ N_MBG_OPT_BIT }; @@ -1654,6 +2449,76 @@ enum #define MBG_OPT_FLAG_EMU_SYNC ( 1UL << MBG_OPT_BIT_EMU_SYNC ) +/** + @defgroup group_scale Time Scale Configuration + + The structures and defines can be used to configure the GPS receiver's + basic time scale. By default this is UTC which can optionally + be converted to some local time. However, some applications + prefer TAI or pure GPS time. This can be configured using the + structures below if the GPS_HAS_TIME_SCALE flag is set in + RECEIVER_INFO::features. + @{ +*/ + +enum +{ + MBG_TIME_SCALE_DEFAULT, /**< UTC or local time, t_gps - deltat_ls */ + MBG_TIME_SCALE_GPS, /**< GPS time, monotonical */ + MBG_TIME_SCALE_TAI, /**< TAI, t_gps + GPS_TAI_OFFSET seconds */ + N_MBG_TIME_SCALE +}; + +#define MBG_TIME_SCALE_MSK_DEFAULT ( 1UL << MBG_TIME_SCALE_DEFAULT ) +#define MBG_TIME_SCALE_MSK_GPS ( 1UL << MBG_TIME_SCALE_GPS ) +#define MBG_TIME_SCALE_MSK_TAI ( 1UL << MBG_TIME_SCALE_TAI ) + +// See also the extended status bits TM_SCALE_GPS and TM_SCALE_TAI +// indicating the active time scale setting. + + +#define MBG_TIME_SCALE_STRS \ +{ \ + "UTC/local", \ + "GPS", \ + "TAI" \ +} + + + +/** + The fixed time offset between the GPS and TAI time scales, in seconds +*/ +#define GPS_TAI_OFFSET 19 /**< [s], TAI = GPS + GPS_TAI_OFFSET */ + + +typedef struct +{ + uint8_t scale; /**< current time scale code from the enum above */ + uint8_t flags; /**< reserved, currently always 0 */ +} MBG_TIME_SCALE_SETTINGS; + +#define _mbg_swab_mbg_time_scale_settings( _p ) \ + _nop_macro_fnc() + + +typedef struct +{ + MBG_TIME_SCALE_SETTINGS settings; /**< current settings */ + MBG_TIME_SCALE_SETTINGS max_settings; /**< numb. of scales, all supported flags */ + uint32_t supp_scales; /**< bit masks of supported scales */ +} MBG_TIME_SCALE_INFO; + +#define _mbg_swab_mbg_time_scale_info( _p ) \ +{ \ + _mbg_swab_mbg_time_scale_settings( &(_p)->settings ); \ + _mbg_swab_mbg_time_scale_settings( &(_p)->max_settings ); \ + _mbg_swab32( &(_p)->supp_scales ); \ +} + +/** @} */ // endgroup + + /* * The structures below are required to setup the programmable * pulse outputs which are provided by some GPS receivers. @@ -1661,8 +2526,8 @@ enum * receiver is reported in the RECEIVER_INFO.n_str_type field. */ -/* - * The structure below is used to define a date of year: +/** + * The structure is used to define a date of year: */ typedef struct { @@ -1671,9 +2536,14 @@ typedef struct uint16_t year; /* including century */ } MBG_DATE; +#define _mbg_swab_mbg_date( _p ) \ +{ \ + _mbg_swab16( &(_p)->year ); \ +} -/* - * The structure below is used to define a time of day: + +/** + * The structure is used to define a time of day: */ typedef struct { @@ -1683,9 +2553,12 @@ typedef struct uint8_t sec100; /* reserved, currently always 0 */ } MBG_TIME; +#define _mbg_swab_mbg_time( _p ) \ + _nop_macro_fnc() // nothing to swap -/* - * The structure below defines a single date and time + +/** + * The structure defines a single date and time * for switching operations: */ typedef struct @@ -1696,9 +2569,15 @@ typedef struct uint8_t flags; /* reserved, currently 0 */ } MBG_DATE_TIME; +#define _mbg_swab_mbg_date_time( _p ) \ +{ \ + _mbg_swab_mbg_date( &(_p)->d ); \ + _mbg_swab_mbg_time( &(_p)->t ); \ +} + -/* - * The structure below defines times and dates +/** + * The structure defines times and dates * for an on/off cycle: */ typedef struct @@ -1707,50 +2586,69 @@ typedef struct MBG_DATE_TIME off; /* time and date to switch off */ } POUT_TIME; +#define _mbg_swab_pout_time( _p ) \ +{ \ + _mbg_swab_mbg_date_time( &(_p)->on ); \ + _mbg_swab_mbg_date_time( &(_p)->off ); \ +} -/* + +/** * The number of POUT_TIMEs for each programmable pulse output */ #define N_POUT_TIMES 3 -/* - * The structure below is used to configure a single programmable +/** + * The structure is used to configure a single programmable * pulse output. */ typedef struct { - uint16_t mode; /* mode of operation, codes defined below */ - uint16_t pulse_len; /* 10 msec units, or COM port number */ - uint16_t timeout; /* [min], for dcf_mode */ - uint16_t flags; /* see below */ - POUT_TIME tm[N_POUT_TIMES]; /* switching times */ + uint16_t mode; /**< mode of operation, codes defined below */ + uint16_t pulse_len; /**< 10 msec units, or COM port number */ + uint16_t timeout; /**< [min], for dcf_mode */ + uint16_t flags; /**< see below */ + POUT_TIME tm[N_POUT_TIMES]; /**< switching times */ } POUT_SETTINGS; -#define MAX_POUT_PULSE_LEN 1000 // 10 secs, in 10 msec units -#define MAX_POUT_DCF_TIMOUT ( 48 * 60 ) // 48 hours, in minutes +#define _mbg_swab_pout_settings( _p ) \ +{ \ + int i; \ + _mbg_swab16( &(_p)->mode ); \ + _mbg_swab16( &(_p)->pulse_len ); \ + _mbg_swab32( &(_p)->timeout ); \ + _mbg_swab16( &(_p)->flags ); \ + \ + for ( i = 0; i < N_POUT_TIMES; i++ ) \ + _mbg_swab_pout_time( &(_p)->tm[i] ); \ +} -/* - * The codes below are defined for POUT_SETTINGS.mode to setup +#define MAX_POUT_PULSE_LEN 1000 /**< 10 secs, in 10 msec units */ +#define MAX_POUT_DCF_TIMOUT ( 48 * 60 ) /**< 48 hours, in minutes */ + + +/** + * These codes are defined for POUT_SETTINGS.mode to setup * the basic mode of operation for a single programmable pulse * output: */ enum { - POUT_IDLE, /* always off, or on if POUT_INVERTED */ - POUT_TIMER, /* switch on/off at configured times */ - POUT_SINGLE_SHOT, /* pulse at time POUT_SETTINGS.tm[0].on */ - POUT_CYCLIC_PULSE, /* pulse every POUT_SETTINGS.tm[0].on.t interval */ - POUT_PER_SEC, /* pulse if second changes */ - POUT_PER_MIN, /* pulse if minute changes */ - POUT_PER_HOUR, /* pulse if hour changes */ - POUT_DCF77, /* emulate DCF77 signal */ - POUT_POS_OK, /* on if pos. OK (nav_solved) */ - POUT_TIME_SYNC, /* on if time sync (time_syn) */ - POUT_ALL_SYNC, /* on if pos. OK and time sync */ - POUT_TIMECODE, /* IRIG/AFNOR DCLS output */ - POUT_TIMESTR, /* COM port number in pulse_len field */ - POUT_10MHZ, /* 10 MHz fixed frequency */ + POUT_IDLE, /**< always off, or on if POUT_INVERTED */ + POUT_TIMER, /**< switch on/off at configured times */ + POUT_SINGLE_SHOT, /**< pulse at time POUT_SETTINGS.tm[0].on */ + POUT_CYCLIC_PULSE, /**< pulse every POUT_SETTINGS.tm[0].on.t interval */ + POUT_PER_SEC, /**< pulse if second changes */ + POUT_PER_MIN, /**< pulse if minute changes */ + POUT_PER_HOUR, /**< pulse if hour changes */ + POUT_DCF77, /**< emulate DCF77 signal */ + POUT_POS_OK, /**< on if pos. OK (nav_solved) */ + POUT_TIME_SYNC, /**< on if time sync (time_syn) */ + POUT_ALL_SYNC, /**< on if pos. OK and time sync */ + POUT_TIMECODE, /**< IRIG/AFNOR DCLS output */ + POUT_TIMESTR, /**< COM port number in pulse_len field */ + POUT_10MHZ, /**< 10 MHz fixed frequency */ N_POUT_MODES }; @@ -1854,50 +2752,70 @@ enum #define POUT_INVERTED 0x0001 -/* - * Since a clock may support more than one programmable - * pulse output, setup tools must use the structure below - * to read/set pulse output configuration. - * The number of outputs supported by a receiver model - * can be queried using the RECEIVER_INFO structure. +/** + Since a clock may support more than one programmable + pulse output, setup tools must use the structure below + to read/set pulse output configuration. + The number of outputs supported by a receiver model + can be queried using the RECEIVER_INFO structure. */ typedef struct { - uint16_t idx; /* 0..RECEIVER_INFO.n_prg_out-1 */ + uint16_t idx; /**< 0..RECEIVER_INFO.n_prg_out-1 */ POUT_SETTINGS pout_settings; } POUT_SETTINGS_IDX; +#define _mbg_swab_pout_settings_idx( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_pout_settings( &(_p)->pout_settings ); \ +} -/* - * The structure below holds the current settings - * for a programmable pulse output, plus additional - * informaton on the output's capabilities. - * This can be read by setup programs to allow setup - * of supported features only. + +/** + The structure below holds the current settings + for a programmable pulse output, plus additional + informaton on the output's capabilities. + This can be read by setup programs to allow setup + of supported features only. */ typedef struct { POUT_SETTINGS pout_settings; - uint32_t supp_modes; /* bit mask of modes supp. by this output */ - uint8_t timestr_ports; /* bit mask of COM ports supported for POUT_TIMESTR */ - uint8_t reserved_0; /* reserved for future use, currently 0 */ - uint16_t reserved_1; /* reserved for future use, currently 0 */ - uint32_t flags; /* reserved for future use, currently 0 */ + uint32_t supp_modes; /**< bit mask of modes supp. by this output */ + uint8_t timestr_ports; /**< bit mask of COM ports supported for POUT_TIMESTR */ + uint8_t reserved_0; /**< reserved for future use, currently 0 */ + uint16_t reserved_1; /**< reserved for future use, currently 0 */ + uint32_t flags; /**< reserved for future use, currently 0 */ } POUT_INFO; -/* The max number of COM ports that can be handled by POUT_INFO::timestr_ports */ +#define _mbg_swab_pout_info( _p ) \ +{ \ + _mbg_swab_pout_settings( &(_p)->pout_settings ); \ + _mbg_swab32( &(_p)->supp_modes ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/** The max number of COM ports that can be handled by POUT_INFO::timestr_ports */ #define MAX_POUT_TIMESTR_PORTS 8 -/* - * The structure below adds an index number to the structure - * above to allow addressing of several instances: +/** + The structure below adds an index number to the structure + above to allow addressing of several instances: */ typedef struct { - uint16_t idx; /* 0..RECEIVER_INFO.n_prg_out-1 */ + uint16_t idx; /**< 0..RECEIVER_INFO.n_prg_out-1 */ POUT_INFO pout_info; } POUT_INFO_IDX; +#define _mbg_swab_pout_info_idx( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_pout_info( &(_p)->pout_info ); \ +} /* @@ -1912,13 +2830,16 @@ typedef struct */ enum { - MULTI_REF_GPS, // standard GPS + MULTI_REF_NONE = -1, // nothing, undefined + MULTI_REF_GPS = 0, // standard GPS MULTI_REF_10MHZ, // 10 MHz input frequency MULTI_REF_PPS, // 1 PPS input signal MULTI_REF_10MHZ_PPS, // combined 10 MHz plus PPS MULTI_REF_IRIG, // IRIG input MULTI_REF_NTP, // Network Time Protocol (NTP) MULTI_REF_PTP, // Precision Time Protocol (PTP, IEEE1588) + MULTI_REF_PTP_E1, // PTP over E1 + MULTI_REF_FREQ, // fixed frequency N_MULTI_REF // the number of defined sources }; @@ -1934,7 +2855,9 @@ enum "10 MHz + PPS in", \ "IRIG", \ "NTP", \ - "PTP (IEEE1588)" \ + "PTP (IEEE1588)", \ + "PTP over E1", \ + "Fixed Freq. in" \ } @@ -1948,23 +2871,36 @@ enum #define HAS_MULTI_REF_IRIG ( 1UL << MULTI_REF_IRIG ) #define HAS_MULTI_REF_NTP ( 1UL << MULTI_REF_NTP ) #define HAS_MULTI_REF_PTP ( 1UL << MULTI_REF_PTP ) +#define HAS_MULTI_REF_PTP_E1 ( 1UL << MULTI_REF_PTP_E1 ) +#define HAS_MULTI_REF_FREQ ( 1UL << MULTI_REF_FREQ ) /* - * Up to this number of prioritizable ref input sources are supported + * There are 2 different ways to configure multi ref support + * provided by some devices. + * + * Newer devices which have the GPS_FEAT_XMULTI_REF flag set + * in RECEIVER_INFO::features support the newer XMULTI_REF_... + * structures which provide a more flexible interface. + * + * Older devices which have the GPS_FEAT_MULTI_REF flag set + * support these MULTI_REF_... structures below where + * the number of supported input sources and priorities + * is limited to N_MULTI_REF_PRIO. */ + #define N_MULTI_REF_PRIO 4 -/* - * 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 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. +/** + 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 prio[] array must be set to one of the values 0..N_MULTI_REF-1, + or to -1 (0xFF) if the value is not assigned. */ typedef struct { @@ -1972,10 +2908,9 @@ typedef struct } MULTI_REF_SETTINGS; - -/* - * The structure below is used to query the MULTI_REF configuration, - * plus the supported ref sources. +/** + The structure below is used to query the MULTI_REF configuration, + plus the supported ref sources. */ typedef struct { @@ -1986,19 +2921,17 @@ typedef struct } MULTI_REF_INFO; - /* * The type below is used to query the MULTI_REF status information, */ typedef uint16_t MULTI_REF_STATUS; /* flag bits as defined below */ -/* +/* * The bits and associated bit masks below are used with the * MULTI_REF_STATUS type. Each bit is set if the associated * condition is true and is reset if the condition is not true: */ - enum { WRN_MODULE_MODE, /* selected input mode was invalid, set to default */ @@ -2025,6 +2958,147 @@ enum +/* + * If the RECEIVER_INFO::features flag GPS_FEAT_XMULTI_REF is set + * then the following XMULTI_REF_... data structures must be used + * instead of the older MULTI_REF_... structures above. + * + * Those devices support a number of priority levels addressed by + * the priority index, starting at 0 for highest priority. A single + * reference time source from the set of supported sources can be + * assigned to each priority level. + * + * The structures below are used to configure the individual + * time source for each priority level, and retrieve the status + * of the time source at each priority level. + */ + +typedef struct +{ + uint8_t type; /* 0..N_MULTI_REF-1 from the enum above */ + uint8_t instance; /* reserved, currently always 0 */ +} XMULTI_REF_ID; + +typedef struct +{ + XMULTI_REF_ID id; /* time source identifier */ + uint16_t flags; /* reserved, currently always 0 */ + NANO_TIME bias; /* time bias, e.g. path delay */ + NANO_TIME precision; /* precision of the time source */ + uint32_t fine_limit; /* smooth control if below this limit */ +} XMULTI_REF_SETTINGS; + + +/* + * The structure below is used to retrieve or configure the time source + * for a specific priority level. + * After configuring, a structure with idx == 0xFFFF (-1) must be sent + * to let the changes become effective. + */ +typedef struct +{ + uint16_t idx; /* the priority level index, highest == 0 */ + XMULTI_REF_SETTINGS settings; /* the settings configured for this level */ + +} XMULTI_REF_SETTINGS_IDX; + + +/* + * The structure below contains the XMULTI_REF configuration + * for a single priority level, plus information on supported + * ref time sources, and the number of supported priority levels. + */ +typedef struct +{ + XMULTI_REF_SETTINGS settings; /* current settings */ + uint32_t supp_ref; /* supp. HAS_MULTI_REF_... codes or'ed */ + uint8_t n_supp_ref; /* number of supported ref time sources */ + uint8_t n_prio; /* number of supported priority levels */ + uint16_t flags; /* reserved, currently 0, e.g. multiple instance support */ + +} XMULTI_REF_INFO; + + +/* + * The structure below is used to retrieve the XMULTI_REF configuration + * information for a specific priority level. + */ +typedef struct +{ + uint16_t idx; /* the priority level index, highest == 0 */ + XMULTI_REF_INFO info; + +} XMULTI_REF_INFO_IDX; + + +/* + * The structure below contains status information on a single + * ref time source. + */ +typedef struct +{ + XMULTI_REF_ID id; /* time source identifier */ + uint16_t status; /* flag bits as defined below */ + NANO_TIME offset; /* time offset from main time base */ + uint32_t reserved; /* reserved, currently always 0 */ + +} XMULTI_REF_STATUS; + + +/* + * The structure below is used to retrieve the the status information + * of the time source at a specific priority level. + */ +typedef struct +{ + uint16_t idx; /* the priority level index, highest == 0 */ + XMULTI_REF_STATUS status; + +} XMULTI_REF_STATUS_IDX; + + +/* + * Bits used with XMULTI_REF_STATUS. + */ +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 */ + 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 ) + + + +/* + * An initializer for a XMULTI_REF_STATUS variable + * with status invalid / not used + */ +#define XMULTI_REF_STATUS_INVALID \ +{ \ + { (uint8_t) MULTI_REF_NONE, 0 }, /* id; instance 0 ? */ \ + XMRS_MSK_NO_CONN | XMRS_MSK_NO_SIGNAL, /* status */ \ + { 0 }, /* offset */ \ + 0 /* reserved */ \ +} + + + /*------------------------------------------------------------------------*/ /* @@ -2033,8 +3107,36 @@ enum typedef uint16_t ROM_CSUM; /* The ROM checksum */ typedef uint16_t RCV_TIMEOUT; /* [min] (only if HAS_RCV_TIMEOUT) */ -typedef uint16_t IGNORE_LOCK; /* if != 0 always claim to be sync */ +typedef uint16_t IGNORE_LOCK; /* (only if GPS_HAS_IGNORE_LOCK) */ +/* + * Originally IGNORE_LOG above has been a boolean value (equal or + * not equal 0) which was evaluated the same way for all ports. + * + * Due to special firmware requirements it has been changed to a + * bit maskable property in order to be able to specify the behaviour + * for individual ports. + * + * In order to keep compatibility with older versions the LSB is used + * to specify ignore_lock for all ports. The next higher bits are used + * to specify ignore_lock for an individual port, where the bit position + * depends on the port number, e.g. 0x02 for COM0, 0x04 for COM1, etc. + * The macros below can be used to simplify the code: + */ + +/* return a bit mask depending on the port number */ +#define IGNORE_LOCK_FOR_ALL_PORTS 0x01 + +#define _ignore_lock_for_all_ports() ( IGNORE_LOCK_FOR_ALL_PORTS ) + +#define _ignore_lock_for_port( _n ) ( 0x02 << (_n) ) + +/* check if all ports are ignore_lock'ed */ +#define _is_ignore_lock_all_ports( _il ) ( (_il) & IGNORE_LOCK_FOR_ALL_PORTS ) + +/* check if a specific port is ignore_lock'ed */ +#define _is_ignore_lock_for_port( _il, _n ) \ + ( (_il) & ( _ignore_lock_for_port(_n) | IGNORE_LOCK_FOR_ALL_PORTS ) ) /*------------------------------------------------------------------------*/ @@ -2043,7 +3145,7 @@ typedef uint16_t IGNORE_LOCK; /* if != 0 always claim to be sync */ * The structures below are used with the SCU multiplexer board * in a redundant system: */ - + typedef struct { uint32_t hw_id; // hardware identification @@ -2074,7 +3176,7 @@ typedef struct #define MSK_EPLD_STAT_ACO 0x4000 // Access control override bit #define MSK_EPLD_STAT_WDOG_OK 0x8000 // WDT_OK set to zero if watchdog expired - + #define MSK_EPLD_CNTL_SEL_REM 0x0800 // remote select for output MUX ( clk_1 = 0 ) #define MSK_EPLD_CNTL_DIS_REM 0x1000 // remote disable for output MUX #define MSK_EPLD_CNTL_REMOTE 0x2000 // must be set to enable remote operation @@ -2116,18 +3218,37 @@ enum #define UPDA_166 ( 0x08 | BOOT ) #define UPDA_BC ( 0x09 | REMOTE | BOOT ) + + +typedef int16_t DAC_VAL; + +#define _mbg_swab_dac_val( _p ) \ + _mbg_swab16( _p ); + + + typedef struct { - uint16_t mode; - uint16_t good_svs; - uint16_t svs_in_view; - int16_t dac_val; - int16_t dac_cal; + uint16_t mode; /**< Mode of operation */ + uint16_t good_svs; /**< Numb. of satellites that can currently be received and used */ + uint16_t svs_in_view; /**< Numb. of satellites that should be in view according to the almanac data */ + DAC_VAL dac_val; /**< Oscillator fine DAC value */ + DAC_VAL dac_cal; /**< Oscillator calibration DAC value ( see #OSC_DAC_RANGE, #OSC_DAC_BIAS ) */ } STAT_INFO; +#define _mbg_swab_stat_info( _p ) \ +{ \ + _mbg_swab16( &(_p)->mode ); \ + _mbg_swab16( &(_p)->good_svs ); \ + _mbg_swab16( &(_p)->svs_in_view ); \ + _mbg_swab_dac_val( &(_p)->dac_val ); \ + _mbg_swab_dac_val( &(_p)->dac_cal ); \ +} + + #define OSC_DAC_RANGE 4096UL #define OSC_DAC_BIAS ( OSC_DAC_RANGE / 2 ) - + #ifndef _IDENT_DEFINED @@ -2141,13 +3262,491 @@ typedef struct #define _IDENT_DEFINED #endif +#define _mbg_swab_ident( _p ) \ +{ \ + int i; \ + for ( i = 0; i < 4; i++ ) \ + _mbg_swab32( &(_p)->lw[i] ); \ +} -/* +/** * The type below is used to configure the length of the - * antenna cable: + * antenna cable in [m]: */ typedef uint16_t ANT_CABLE_LEN; +#define _mbg_swab_ant_cable_len( _p ) _mbg_swab16( _p ) + + + +/* Configuration data for an optional LAN interface. + * + * This is only supported if the flag GPS_HAS_LAN_IP4 + * is set in RECEIVER_INFO::features. + */ + + +/* Basic network settings */ + +typedef uint32_t IP4_ADDR; + +#define _mbg_swab_ip4_addr( _p ) \ + _mbg_swab32( _p ); + + +typedef struct +{ + IP4_ADDR ip_addr; + IP4_ADDR netmask; + IP4_ADDR broad_addr; + IP4_ADDR gateway; + uint32_t flags; /* see below */ + +} IP4_SETTINGS; + +#define _mbg_swab_ip4_settings( _p ) \ +{ \ + _mbg_swab_ip4_addr( &(_p)->ip_addr ); \ + _mbg_swab_ip4_addr( &(_p)->netmask ); \ + _mbg_swab_ip4_addr( &(_p)->broad_addr ); \ + _mbg_swab_ip4_addr( &(_p)->gateway ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +#if 0 //##++ currently not used + +/* Misc configuration */ + +typedef struct +{ + uint16_t id; /* service ID, see below */ + uint16_t index; /* used if several same svcs must be cfg'd, e.g. DNS */ + char host[50]; /* see below */ + +} IP_CFG; + + + +/* Description of a service running on a device */ + +typedef struct +{ + uint16_t id; /* service ID, see below */ + uint16_t socket; /* the socket on which the service is listening */ + uint32_t flags; /* see below */ + +} IP_SERVICE; + +#endif // 0 + + + +/* LAN interface information */ + +typedef struct +{ + uint16_t type; /* codes see below */ + uint8_t mac_addr[6]; /* MAC address */ + uint16_t ver_code; /* high byte.low byte, in hex */ + char ver_str[GPS_ID_STR_SIZE]; + char sernum[GPS_ID_STR_SIZE]; + uint32_t rsvd; /* reserved, currently always 0 */ + uint32_t flags; /* 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 ); \ +} + + + +/* codes used with LAN_IF_INFO::type: */ + +enum +{ + LAN_IF_TYPE_XPORT, + LAN_IF_TYPE_PTP, + N_LAN_IF_TYPE +}; + + +/* Flags used with IP4_SETTINGS::flags and LAN_IF_INFO::flags: */ + +enum +{ + IP4_BIT_DHCP, + IP4_BIT_LINK, // used only to report state + N_IP4_BIT +}; + +#define IP4_MSK_DHCP ( 1UL << IP4_BIT_DHCP ) +#define IP4_MSK_LINK ( 1UL << IP4_BIT_LINK ) + + +enum +{ + PTP_NW_PROT_BIT_RESERVED, + PTP_NW_PROT_BIT_UDP_IPV4, + PTP_NW_PROT_BIT_UDP_IPV6, + PTP_NW_PROT_BIT_IEEE_802_3, + PTP_NW_PROT_BIT_DEVICE_NET, + PTP_NW_PROT_BIT_CONTROL_NET, + PTP_NW_PROT_BIT_PROFINET, + N_PTP_NW_PROT +}; + +#define PTP_NW_PROT_MSK_RESERVED ( 1UL << PTP_NW_PROT_BIT_RESERVED ) +#define PTP_NW_PROT_MSK_UDP_IPV4 ( 1UL << PTP_NW_PROT_BIT_UDP_IPV4 ) +#define PTP_NW_PROT_MSK_UDP_IPV6 ( 1UL << PTP_NW_PROT_BIT_UDP_IPV6 ) +#define PTP_NW_PROT_MSK_IEEE_802_3 ( 1UL << PTP_NW_PROT_BIT_IEEE_802_3 ) +#define PTP_NW_PROT_MSK_DEVICE_NET ( 1UL << PTP_NW_PROT_BIT_DEVICE_NET ) +#define PTP_NW_PROT_MSK_CONTROL_NET ( 1UL << PTP_NW_PROT_BIT_CONTROL_NET ) +#define PTP_NW_PROT_MSK_PROFINET ( 1UL << PTP_NW_PROT_BIT_PROFINET ) + +#if !defined( DEFAULT_PTP_NW_PROT_MASK ) + #define DEFAULT_PTP_NW_PROT_MASK ( PTP_NW_PROT_MSK_UDP_IPV4 | PTP_NW_PROT_MSK_IEEE_802_3 ) +#endif + +#define PTP_NW_PROT_STRS \ +{ \ + "Reserved", \ + "UDP/IPv4", \ + "UDP/IPv6", \ + "IEEE 802.3", \ + "DeviceNet", \ + "ControlNet", \ + "PROFINET" \ +} + + + +enum +{ + PTP_PORT_STATE_UNINITIALIZED, + PTP_PORT_STATE_INITIALIZING, + PTP_PORT_STATE_FAULTY, + PTP_PORT_STATE_DISABLED, + PTP_PORT_STATE_LISTENING, + PTP_PORT_STATE_PRE_MASTER, + PTP_PORT_STATE_MASTER, + PTP_PORT_STATE_PASSIVE, + PTP_PORT_STATE_UNCALIBRATED, + PTP_PORT_STATE_SLAVE, + N_PTP_PORT_STATE +}; + +#define PTP_PORT_STATE_STRS \ +{ \ + "UNINITIALIZED", \ + "INITIALIZING", \ + "FAULTY", \ + "DISABLED", \ + "LISTENING", \ + "PRE_MASTER", \ + "MASTER", \ + "PASSIVE", \ + "UNCALIBRATED", \ + "SLAVE" \ +} + + +typedef struct +{ + uint8_t value; + char *name; +} PTP_TABLE; + + +enum +{ + PTP_DELAY_MECH_BIT_E2E, // in PTP2 specs: 0x01 + PTP_DELAY_MECH_BIT_P2P, // in PTP2 specs: 0x02 + N_PTP_DELAY_MECH // additionally the specs define 0xFE for disabled +}; + +#define PTP_DELAY_MECH_MSK_E2E ( 1UL << PTP_DELAY_MECH_BIT_E2E ) +#define PTP_DELAY_MECH_MSK_P2P ( 1UL << PTP_DELAY_MECH_BIT_P2P ) + +#if !defined( DEFAULT_PTP_DELAY_MECH_MASK ) + #define DEFAULT_PTP_DELAY_MECH_MASK ( PTP_DELAY_MECH_MSK_E2E ) +#endif + +#define PTP_DELAY_MECH_NAMES \ +{ \ + "E2E", \ + "P2P" \ +} + + + +#define PTP_CLOCK_ACCURACY_RESERVED_OFFSET 0x20 + +enum +{ + PTP_CLOCK_ACCURACY_25ns = PTP_CLOCK_ACCURACY_RESERVED_OFFSET, + PTP_CLOCK_ACCURACY_100ns, + PTP_CLOCK_ACCURACY_250ns, + PTP_CLOCK_ACCURACY_1us, + PTP_CLOCK_ACCURACY_2_5us, + PTP_CLOCK_ACCURACY_10us, + PTP_CLOCK_ACCURACY_25us, + PTP_CLOCK_ACCURACY_100us, + PTP_CLOCK_ACCURACY_250us, + PTP_CLOCK_ACCURACY_1ms, + PTP_CLOCK_ACCURACY_2_5ms, + PTP_CLOCK_ACCURACY_10ms, + PTP_CLOCK_ACCURACY_25ms, + PTP_CLOCK_ACCURACY_100ms, + PTP_CLOCK_ACCURACY_250ms, + PTP_CLOCK_ACCURACY_1s, + PTP_CLOCK_ACCURACY_10s, + PTP_CLOCK_ACCURACY_MORE_10s, + PTP_CLOCK_ACCURACY_RESERVED_1, + PTP_CLOCK_ACCURACY_RESERVED_2, + PTP_CLOCK_ACCURACY_RESERVED_3, + PTP_CLOCK_ACCURACY_RESERVED_4, + N_PTP_CLOCK_ACCURACY +}; + + +// Attention: Substract offset of PTP_CLOCK_ACCURACY_RESERVED_OFFSET when +// using the enum above as index for the initializer below! +#define PTP_CLOCK_ACCURACY_STRS \ +{ \ + "< 25 ns", \ + "< 100 ns", \ + "< 250 ns", \ + "< 1 us", \ + "< 2.5 us", \ + "< 10 us", \ + "< 25 us", \ + "< 100 us", \ + "< 250 us", \ + "< 1 ms", \ + "< 2.5 ms", \ + "< 10 ms", \ + "< 25 ms", \ + "< 100 ms", \ + "< 250 ms", \ + "< 1 s", \ + "< 10 s", \ + "more than 10 s", \ + "reserved_1", \ + "reserved_2", \ + "reserved_3", \ + "reserved_4" \ +} + + + +#define PTP_TIME_SOURCE_ATOMIC_CLOCK 0x10 +#define PTP_TIME_SOURCE_GPS 0x20 +#define PTP_TIME_SOURCE_TERRESTRIAL_RADIO 0x30 +#define PTP_TIME_SOURCE_PTP 0x40 +#define PTP_TIME_SOURCE_NTP 0x50 +#define PTP_TIME_SOURCE_HAND_SET 0x60 +#define PTP_TIME_SOURCE_OTHER 0x90 +#define PTP_TIME_SOURCE_INTERNAL_OSCILLATOR 0xA0 + + + +#define PTP_TIME_SOURCE_TABLE \ +{ \ + { PTP_TIME_SOURCE_ATOMIC_CLOCK, "Atomic Clock" }, \ + { PTP_TIME_SOURCE_GPS, "GPS" }, \ + { PTP_TIME_SOURCE_TERRESTRIAL_RADIO, "Terrestrial Radio" }, \ + { PTP_TIME_SOURCE_PTP, "PTP" }, \ + { PTP_TIME_SOURCE_NTP, "NTP" }, \ + { PTP_TIME_SOURCE_HAND_SET, "HAND SET" }, \ + { PTP_TIME_SOURCE_OTHER, "OTHER" }, \ + { PTP_TIME_SOURCE_INTERNAL_OSCILLATOR, "Internal Oscillator" }, \ + { 0, NULL } \ +} + + + + +/* PTP configuration stuff */ + +typedef struct +{ + uint8_t b[8]; +} PTP_CLOCK_IDENTITY; + + + +typedef struct +{ + uint16_t network_protocol; // enum + uint8_t ptp_proto_version; // PTP v1 or v2 + uint8_t port_state; // enum + uint32_t flags; + NANO_TIME offset; + NANO_TIME path_delay; + NANO_TIME mean_path_delay; + NANO_TIME delay_asymmetry; + + PTP_CLOCK_IDENTITY gm_identity; + + uint16_t clock_offset_scaled_log_variance; + uint8_t clock_class; + uint8_t clock_accuracy; // enum + + uint32_t num_clients; + uint32_t num_masters; + + uint8_t domain_number; + uint8_t time_source; // enum + uint8_t delay_mech; + int8_t log_delay_req_intv; + + int16_t utc_offset; + DAC_VAL osc_dac_cal; + + uint32_t reserved; +} PTP_STATE; + +#define _mbg_swab_ptp_state( _p ) \ +{ \ + _mbg_swab16( &(_p)->network_protocol ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab_nano_time( &(_p)->offset ); \ + _mbg_swab_nano_time( &(_p)->path_delay ); \ + _mbg_swab_nano_time( &(_p)->mean_path_delay ); \ + _mbg_swab_nano_time( &(_p)->delay_asymmetry ); \ + _mbg_swab16( &(_p)->clock_offset_scaled_log_variance ); \ + _mbg_swab32( &(_p)->num_clients ); \ + _mbg_swab32( &(_p)->num_masters ); \ + _mbg_swab32( &(_p)->utc_offset ); \ + _mbg_swab_dac_val( &(_p)->osc_dac_cal ); \ +} + + +enum +{ + PTP_FLAG_BIT_SLAVE_ONLY, + PTP_FLAG_BIT_IS_SLAVE, + PTP_FLAG_BIT_TIMESCALE_IS_PTP, + PTP_FLAG_BIT_LS_ANN, + PTP_FLAG_BIT_LS_ANN_NEG, + N_PTP_FLAG_BIT +}; + +#define PTP_FLAG_MSK_SLAVE_ONLY ( 1UL << PTP_FLAG_BIT_SLAVE_ONLY ) +#define PTP_FLAG_MSK_IS_SLAVE ( 1UL << PTP_FLAG_BIT_IS_SLAVE ) +#define PTP_FLAG_MSK_TIMESCALE_IS_PTP ( 1UL << PTP_FLAG_BIT_TIMESCALE_IS_PTP ) +#define PTP_FLAG_MSK_LS_ANN ( 1UL << PTP_FLAG_BIT_LS_ANN ) +#define PTP_FLAG_MSK_LS_ANN_NEG ( 1UL << PTP_FLAG_BIT_LS_ANN_NEG ) + + +#define PTP_SYNC_INTERVAL_MIN -6 +#define PTP_SYNC_INTERVAL_MAX 6 + +#define PTP_DELAY_REQ_INTERVAL_MIN -6 +#define PTP_DELAY_REQ_INTERVAL_MAX 6 + + +typedef struct +{ + uint16_t network_protocol; // enum, only 1 or 3 + uint8_t profile; // currently only 0 = default + uint8_t domain_number; // 0:3 + + uint8_t delay_mechanism; // 0 (E2E) or 1 (P2P), unless disabled + uint8_t reserved_0; + uint8_t priority_1; + uint8_t priority_2; + + uint8_t dflt_clk_class_unsync_cold; // 6:255 + uint8_t dflt_clk_class_unsync_warm; // 6:255 + uint8_t dflt_clk_class_sync_cold; // 6:255 + uint8_t dflt_clk_class_sync_warm; // 6:255 + + uint8_t reserved_1; // currently always 0 + uint8_t reserved_2; // currently always 0 + int16_t sync_interval; // log 2 + + int16_t announce_interval; // log 2 + int16_t delay_request_interval; // log 2 + + uint32_t upper_bound; // [ns] sync state set to false if above this limit + uint32_t lower_bound; // [ns] sync state set to true if below this limit + + uint32_t reserved_3; // currently always 0 + uint32_t flags; // (see below) + +} PTP_CFG_SETTINGS; + +#define _mbg_swab_ptp_cfg_settings( _p ) \ +{ \ + _mbg_swab16( &(_p)->network_protocol ); \ + _mbg_swab16( &(_p)->sync_interval ); \ + _mbg_swab16( &(_p)->announce_interval ); \ + _mbg_swab16( &(_p)->delay_request_interval ); \ + _mbg_swab32( &(_p)->upper_bound ); \ + _mbg_swab32( &(_p)->lower_bound ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + + +typedef struct +{ + PTP_CFG_SETTINGS settings; + + uint8_t ptp_proto_version; // PTP v1 or v2 + uint8_t reserved_1; // currently always 0 + uint16_t reserved_2; // currently always 0 + + int16_t sync_interval_min; // log 2 + int16_t sync_interval_max; // log 2 + int16_t announce_interval_min; // log 2 + int16_t announce_interval_max; // log 2 + int16_t delay_request_interval_min; // log 2 + int16_t delay_request_interval_max; // log 2 + + uint32_t supported_flags; // (see below) + uint32_t supported_network_protocols; + uint32_t supported_profiles; + uint32_t supported_delay_mechanisms; + +} PTP_CFG_INFO; + +#define _mbg_swab_ptp_cfg_info( _p ) \ +{ \ + _mbg_swab_ptp_cfg_settings( &(_p)->settings ); \ + _mbg_swab16( &(_p)->sync_interval_min ); \ + _mbg_swab16( &(_p)->sync_interval_max ); \ + _mbg_swab16( &(_p)->announce_interval_min ); \ + _mbg_swab16( &(_p)->announce_interval_max ); \ + _mbg_swab16( &(_p)->delay_request_interval_min ); \ + _mbg_swab16( &(_p)->delay_request_interval_max ); \ + _mbg_swab32( &(_p)->supported_flags ); \ + _mbg_swab32( &(_p)->supported_profiles ); \ + _mbg_swab32( &(_p)->supported_delay_mechanisms ); \ +} + + + +// flags used with PTP_CFG_SETTINGS::flags and PTP_CFG_INFO::supported_flags: +// possibly also: can be master (i.e not slave only), v1 hw compat, ... +enum +{ + PTP_CFG_BIT_TIME_SCALE_IS_PTP, // time scale is PTP/TAI, else arbitrary + PTP_CFG_BIT_V1_HW_COMPAT, + N_PTP_CFG_BIT +}; + +#define PTP_CFG_MSK_TIME_SCALE_IS_PTP ( 1UL << PTP_CFG_BIT_TIME_SCALE_IS_PTP ) +#define PTP_CFG_MSK_V1_HW_COMPAT ( 1UL << PTP_CFG_BIT_V1_HW_COMPAT ) + + /*------------------------------------------------------------------------*/ @@ -2240,23 +3839,35 @@ typedef struct -/* UTC correction parameters */ - +/** + UTC correction parameters +*/ typedef struct { - CSUM csum; /* checksum of the remaining bytes */ - int16_t valid; /* flag data are valid */ + CSUM csum; /**< Checksum of the remaining bytes */ + int16_t valid; /**< Flag 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 [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 LS is inserted */ - int8_t delta_tls; /* */ - int8_t delta_tlsf; /* */ + 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] */ + int8_t delta_tlsf; /**< Future UTC offset to GPS system time after next leap second transition [sec] */ } UTC; +#define _mbg_swab_utc_parm( _p ) \ +{ \ + _mbg_swab_csum( &(_p)->csum ); \ + _mbg_swab16( &(_p)->valid ); \ + _mbg_swab_t_gps( &(_p)->t0t ); \ + _mbg_swab_double( &(_p)->A0 ); \ + _mbg_swab_double( &(_p)->A1 ); \ + _mbg_swab16( &(_p)->WNlsf ); \ + _mbg_swab16( &(_p)->DNt ); \ +} + /* Ionospheric correction parameters */ @@ -2289,6 +3900,78 @@ typedef struct } ASCII_MSG; + +enum +{ + GPS_PLATFORM_PORTABLE, + GPS_PLATFORM_FIXED, + GPS_PLATFORM_STATIONARY, + GPS_PLATFORM_PEDESTRIAN, + GPS_PLATFORM_AUTOMOTIVE, + GPS_PLATFORM_SEA, + GPS_PLATFORM_AIRBORNE_1G, + GPS_PLATFORM_AIRBORNE_2G, + GPS_PLATFORM_AIRBORNE_4G, + N_GPS_PLATFORMS +}; + + +#define GPS_PLATFORM_STRS \ +{ \ + "Portable ", \ + "Fixed ", \ + "Stationary ", \ + "Pedestrian ", \ + "Automotive ", \ + "Sea ", \ + "Airborne <1G", \ + "Airborne <2G", \ + "Airborne <4G" \ +} + + + +enum +{ + TIME_MODE_DISABLED, + TIME_MODE_SURVEY_IN, + TIME_MODE_FIXED +}; + + + +typedef struct +{ + uint32_t time_mode; + uint32_t survey_in_duration; + uint32_t survey_in_pos_var; + int32_t fixedPosX; // cm + int32_t fixedPosY; // cm + int32_t fixedPosZ; // cm + uint32_t fixedPosVar; // cm + uint32_t flags; // currently 0 + uint32_t reserved; // currently 0 +} NAV_TIME_MODE_SETTINGS; + + +/** + Navigation Engine settings to set configuration + parameters of a dynamic platform model. +*/ +typedef struct +{ + uint8_t dynamic_platform; + uint8_t fix_mode; + int8_t min_elevation; + uint8_t static_hold_threshold; + int32_t fixed_altitude; + uint32_t fixed_altitude_variance; + uint32_t flags; // currently 0 + uint32_t reserved; // currently 0 + NAV_TIME_MODE_SETTINGS nav_time_mode_settings; +} NAV_ENGINE_SETTINGS; + + /* End of header body */ diff --git a/mbglib/common/gpsserio.c b/mbglib/common/gpsserio.c index 56a0892..15cc808 100644 --- a/mbglib/common/gpsserio.c +++ b/mbglib/common/gpsserio.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsserio.c 1.6 2006/10/25 12:24:01 martin REL_M $ + * $Id: gpsserio.c 1.9 2009/09/01 09:51:56 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,7 +11,17 @@ * * ----------------------------------------------------------------------- * $Log: gpsserio.c $ - * Revision 1.6 2006/10/25 12:24:01 martin + * Revision 1.9 2009/09/01 09:51:56 martin + * Removed obsolete includes. + * Revision 1.8 2009/03/10 16:58:09 martin + * Fixed compiler warnings. + * Revision 1.7 2008/09/03 15:22:40 martin + * Decryption with wrong password yields garbage, still needs to be fixed. + * In xmt_tbuff() use MBG_PORT_HANDLE for serial connections. + * Some cleanup in check_transfer(). + * Fixed a VC6 compiler warning. + * Moved low level serial I/O routines to mbgserio.c. + * Revision 1.6 2006/10/25 12:24:01Z martin * Support serial I/O under Windows. * Removed obsolete code. * Revision 1.5 2006/08/24 12:57:41Z martin @@ -43,7 +53,7 @@ #if defined( MBG_TGT_UNIX ) #include <unistd.h> - #include <sys/time.h> +//##++++ #include <sys/time.h> #endif #if _USE_ENCRYPTION @@ -175,8 +185,6 @@ int chk_data_csum( MBG_MSG_BUFF *pmb ) #else - #include <sys/time.h> - static void randomize( void ) { @@ -255,7 +263,7 @@ int decrypt_message( MBG_MSG_CTL *pmctl ) if ( pmb->hdr.len < AES_BLOCK_SIZE ) return 0; - rc = aes_decrypt_buff( (char *) &pcmd->enc_msg, + rc = aes_decrypt_buff( (unsigned char *) &pcmd->enc_msg, pmctl->aes_keyvect, pcmd->aes_initvect, pmb->hdr.len - sizeof( pcmd->aes_initvect ) @@ -270,6 +278,13 @@ int decrypt_message( MBG_MSG_CTL *pmctl ) /* packet decrypted successfully. */ prctl->flags |= MBG_MSG_RCV_CTL_DECRYPTED; + // If the wrong password has been used for decryption + // then decryption may have been formally successful, + // but the decrypted message contains garbage. + // So we must check whether the decrypted packet + // also contains a valid header and data part. + //##+++ TODO + /* copy the decrypted message to head of the buffer */ memcpy( pmb, &pcmd->enc_msg, pcmd->enc_msg.enc_hdr.len + sizeof( pcmd->enc_msg.enc_hdr ) ); @@ -288,7 +303,7 @@ int decrypt_message( MBG_MSG_CTL *pmctl ) /*HDR*/ -void set_encryption_mode( MBG_MSG_CTL *pmctl, int mode, uint8_t *key ) +void set_encryption_mode( MBG_MSG_CTL *pmctl, int mode, const char *key ) { int i; @@ -366,7 +381,7 @@ int xmt_tbuff( MBG_MSG_CTL *pmctl ) #if _USE_SERIAL_IO case MBG_CONN_TYPE_SERIAL: { - MBG_HANDLE port_handle = pmctl->st.serio.port_handle; + MBG_PORT_HANDLE port_handle = pmctl->st.serio.port_handle; // Note: encrypted msgs over serial are not yet supported. @@ -500,8 +515,8 @@ int xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t us ) /*HDR*/ int check_transfer( MBG_MSG_RCV_CTL *prctl, uint8_t c ) { - MBG_MSG_BUFF *pmb; - MSG_HDR *pmh; + MBG_MSG_BUFF *pmb = prctl->pmb; + MSG_HDR *pmh = &pmb->hdr; if ( prctl->cnt == 0 ) /* not receiving yet */ { @@ -509,10 +524,7 @@ int check_transfer( MBG_MSG_RCV_CTL *prctl, uint8_t c ) return TR_WAITING; /* ignore this character */ /* initialize receiving */ - pmb = prctl->pmb; - pmh = &pmb->hdr; - prctl->pmb = pmb; - prctl->cur = (uint8_t *) pmh; /* first byte of header */ + prctl->cur = (uint8_t *) pmb; /* first byte of buffer */ prctl->cnt = sizeof( *pmh ); /* prepare to rcv msg header */ prctl->flags = 0; @@ -522,10 +534,7 @@ int check_transfer( MBG_MSG_RCV_CTL *prctl, uint8_t c ) /* SOH has already been received */ - pmb = prctl->pmb; - pmh = &pmb->hdr; - - if ( prctl->cur < &( (uint8_t *) prctl->pmb )[prctl->buf_size] ) + if ( prctl->cur < &prctl->pmb->u.bytes[prctl->buf_size] ) { *prctl->cur = c; /* save incoming character */ prctl->cur++; @@ -544,7 +553,7 @@ int check_transfer( MBG_MSG_RCV_CTL *prctl, uint8_t c ) if ( !( prctl->flags & MBG_MSG_RCV_CTL_RCVD_HDR ) ) /* header complete now */ { - int data_len; + unsigned int data_len; if ( chk_hdr_csum( pmh ) < 0 ) /* error */ { @@ -585,88 +594,3 @@ msg_complete: -#if defined( MBG_TGT_WIN32 ) - -/*HDR*/ -int mbgserio_close( MBG_HANDLE h ) -{ - CloseHandle( h ); - - return 0; - -} // mbgserio_close - - - -/*HDR*/ -int mbgserio_read( MBG_HANDLE h, void *buffer, unsigned int count ) -{ - BOOL fReadStat; - COMSTAT ComStat; - DWORD dwErrorFlags, dwLength; - - ClearCommError( h, &dwErrorFlags, &ComStat ); - - if ( dwErrorFlags ) - return 0; - - - dwLength = min( (DWORD) count, ComStat.cbInQue ); - - if ( dwLength > 0 ) - { - fReadStat = ReadFile( h, buffer, dwLength, &dwLength, NULL ); - - if ( !fReadStat ) - { - // some other error occurred - dwLength = 0 ; - return 0; - } - } - - return dwLength; - -} // mbgserio_read - - - -/*HDR*/ -int mbgserio_write( MBG_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 ) - { - #ifdef _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 ) - diff --git a/mbglib/common/gpsserio.h b/mbglib/common/gpsserio.h index 6033d40..a07b47c 100644 --- a/mbglib/common/gpsserio.h +++ b/mbglib/common/gpsserio.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsserio.h 1.21 2006/10/25 12:25:35 martin REL_M $ + * $Id: gpsserio.h 1.32 2009/08/26 09:02:21 daniel REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -31,7 +31,50 @@ * * ----------------------------------------------------------------------- * $Log: gpsserio.h $ - * Revision 1.21 2006/10/25 12:25:35 martin + * 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 + * Renamed symbol MBGEXTIO_TIMEOUT_SOCKET to MBGEXTIO_RCV_TIMEOUT_SOCKET. + * Support new timeout handling distinguishing between character timeout + * and message timeout. Timeout values are now expected in milliseconds. + * Revision 1.30 2009/07/02 09:19:31 martin + * Moved definitions related to LAN interface configuration to gpsdefs.h. + * Revision 1.29 2009/03/10 17:00:29 martin + * Support configurable time scales. + * Don't pack structure MBG_MSG_CTL but use default alignment. + * Revision 1.28 2008/09/04 12:47:10Z martin + * Moved generic serial I/O stuff to mbgserio.h. + * Preliminarily support chk_tstr. + * Revision 1.27 2008/04/07 10:49:13Z martin + * Added cmd GPS_CLR_UCAP_BUFF. + * Revision 1.26 2007/02/27 09:51:45 martin + * Modified mutex macros for Windows. + * Added type TZCODE which is used by the binary protocol but + * has a different size than PCPS_TZCODE. + * Now _USE_PCPSDEFS by default for non-firmware apps. + * Fixed comments on GPS_OPT_SETTINGS and GPS_OPT_INFO. + * Revision 1.25 2007/02/06 16:31:04Z martin + * Modified comment for PZF_PCPS_TIME which can now also + * be sent to a device. + * Added mutex support. + * Added SVNO to the buffer union. + * Added support for OPT_SETTINGS. + * Added XMULTI_REF_... definitions. + * Modified some comments. + * Revision 1.24 2006/12/21 10:54:14Z martin + * Moved macro _IS_MBG_FIRMWARE to words.h. + * Cleaned up definitions of default I/O macros. + * Revision 1.23 2006/12/12 15:53:58 martin + * Added structure LAN_IF_INFO and associated codes. + * Added cmd codes GPS_IRIG_RX_SETTINGS and GPS_IRIG_RX_INFO. + * Added new member irig_rx_info to union MSG_DATA. + * Added cmd code GPS_REF_OFFS and associated definitions. + * Added cmd code GPS_DEBUG_STATUS. + * Define MBG_HANDLE for DOS even without v24tools. + * Revision 1.22 2006/11/02 08:57:56 martin + * Added a typedef to avoid firmware build errors. + * Revision 1.21 2006/10/25 12:25:35Z martin * Support serial I/O under Windows. * Removed obsolete definitions. * Updated function prototypes. @@ -126,73 +169,86 @@ * overridden by global definitions, if required. */ -#define _IS_MBG_FIRMWARE \ -( \ - defined( _C166 ) || \ - defined( _CC51 ) || \ - defined( __ARM ) || \ - defined( _USE_GPS163 ) \ -) - -#if !_IS_MBG_FIRMWARE - #include <mbg_tgt.h> // determine the target OS - +#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_WIN32 ) - #include <windows.h> - #include <io.h> - #define _mbg_open _open - #define _mbg_close _close - #define _mbg_read _read - #define _mbg_write _write + #ifndef _USE_MUTEX + #define _USE_MUTEX 1 + #endif - #define _mbgserio_close mbgserio_close - #define _mbgserio_write mbgserio_write - #define _mbgserio_read mbgserio_read + #if _USE_MUTEX - #elif defined( MBG_TGT_UNIX ) - #include <unistd.h> + #include <windows.h> - #define _mbg_open open - #define _mbg_close close - #define _mbg_read read - #define _mbg_write write - #endif + typedef HANDLE MBG_MUTEX_HANDLE; - #if defined( _USE_V24TOOLS ) - #include <v24tools.h> + #define _mbg_mutex_init( _m ) \ + _m = CreateMutex( NULL, FALSE, NULL ) - typedef int MBG_HANDLE; + #define _mbg_mutex_lock( _m ) \ + WaitForSingleObject( _m, INFINITE ) - #define _mbgserio_open v24open - #define _mbgserio_close v24close - #define _mbgserio_read v24read - #define _mbgserio_write v24write - #else - #if !defined( _mbgserio_open ) - #define _mbgserio_open _mbg_open - #endif - #if !defined( _mbgserio_close ) - #define _mbgserio_close _mbg_close + #define _mbg_mutex_unlock( _m ) \ + ReleaseMutex( _m ) + + #define _mbg_mutex_destroy( _m ) \ + CloseHandle( _m ) #endif - #if !defined( _mbgserio_write ) - #define _mbgserio_write _mbg_write + + #elif defined( MBG_TGT_UNIX ) + + #ifndef _USE_MUTEX + #define _USE_MUTEX 1 #endif - #if !defined( _mbgserio_read ) - #define _mbgserio_read _mbg_read + + #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 #endif + #endif /* Control whether network socket communication shall be supported */ #ifndef _USE_SOCKET_IO - #define _USE_SOCKET_IO 0 // not supported by default + #define _USE_SOCKET_IO 0 // not supported by default #endif /* Control whether serial port communication shall be supported */ #ifndef _USE_SERIAL_IO - #define _USE_SERIAL_IO 1 // supported by default + #if _IS_MBG_FIRMWARE + #define _USE_SERIAL_IO 0 // Firmware provides its own serial I/O functions + #else + #define _USE_SERIAL_IO 1 // supported by default + #endif #endif /* Control inclusion of secudefs.h */ @@ -210,12 +266,22 @@ #endif #endif +#if _USE_SERIAL_IO + #include <mbgserio.h> +#endif + /* Control inclusion of pcpsdefs.h */ #ifndef _USE_PCPSDEFS - #define _USE_PCPSDEFS \ - ( \ - defined( _CC51 ) \ - ) + #if _IS_MBG_FIRMWARE + // for firmware depend on the target system + #define _USE_PCPSDEFS \ + ( \ + defined( _CC51 ) \ + ) + #else + // otherwise include it by default + #define _USE_PCPSDEFS 1 + #endif #endif /* Control inclusion of non-public declarations */ @@ -237,12 +303,6 @@ #endif #endif -#if _USE_SERIAL_IO - #if defined( MBG_TGT_UNIX ) - #include <termios.h> - #endif -#endif - #if _USE_ENCRYPTION #include <secudefs.h> #include <aes128.h> @@ -348,6 +408,18 @@ enum /* | | | */ GPS_MULTI_REF_STATUS, /* | | X | | MULTI_REF_STATUS, (only if HAS_MULTI_REF) */ GPS_RCV_TIMEOUT, /* | | X | X | RCV_TIMEOUT, [min] (only if HAS_RCV_TIMEOUT) */ GPS_IGNORE_LOCK, /* | | X | X | IGNORE_LOCK, if != 0 always claim to be sync */ + GPS_IRIG_RX_SETTINGS, /* | | X | X | IRIG_SETTINGS, (only if GPS_HAS_IRIG_RX) */ + GPS_IRIG_RX_INFO, /* | | X | | IRIG_INFO, (only if GPS_HAS_IRIG_RX) */ + GPS_REF_OFFS, /* | | X | X | MBG_REF_OFFS, (only if GPS_HAS_REF_OFFS) */ + GPS_DEBUG_STATUS, /* | | X | | MBG_DEBUG_STATUS, (only if GPS_HAS_DEBUG_STATUS) */ + GPS_XMR_SETTINGS_IDX, /* | | X | X | XMULTI_REF_SETTINGS_IDX, (only if GPS_HAS_XMULTI_REF) */ + GPS_XMR_INFO_IDX, /* | | X | | XMULTI_REF_INFO_IDX, (only if GPS_HAS_XMULTI_REF) */ + GPS_XMR_STATUS_IDX, /* | | X | | XMULTI_REF_STATUS_IDX, (only if GPS_HAS_XMULTI_REF) */ + GPS_OPT_SETTINGS, /* | | X | X | MBG_OPT_SETTINGS, (only if GPS_HAS_OPT_SETTINGS) */ + GPS_OPT_INFO, /* | | X | | MBG_OPT_INFO, (only if GPS_HAS_OPT_SETTINGS) */ + GPS_CLR_UCAP_BUFF, /* | | X | | command only, no data */ + GPS_TIME_SCALE, /* | | X | X | MBG_TIME_SCALE_{SETTINGS|INFO}, (only if GPS_HAS_TIME_SCALE) */ + GPS_NAV_ENG_SETTINGS, /* | | X | X | NAV_ENGINE_SETTINGS, (only if GPS_HAS_NAV_ENGINE_SETTINGS) */ /* GPS data */ GPS_CFGH = 0x100, /* | | X | X | CFGH, SVs' configuration and health codes */ @@ -357,8 +429,12 @@ enum /* | | | */ GPS_IONO, /* | | X | X | IONO, GPS ionospheric correction parameters */ GPS_ASCII_MSG, /* | | X | | ASCII_MSG, the GPS ASCII message */ + /* Glonass data */ + GPS_GLNS_ALM = 0x200, /* | | X | X | ** preliminary ** */ //##++ + /* Misc data */ GPS_IP4_SETTINGS = 0x800, /* | X | X | IP4_SETTINGS, cfg of optional LAN interface */ + GPS_LAN_IF_INFO, /* | X | | LAN_IF_INFO, LAN interface info */ GPS_CRYPTED_PACKET = 0x880, /* | X | X | X | encrypted binary packet */ GPS_CRYPTED_RAW_PACKET, /* | X | X | X | encrypted binary raw packet */ @@ -368,17 +444,21 @@ enum /* | | | */ GPS_SECU_PUBLIC_KEY, /* | | | | settings and password for LAN interface */ /* PZF data */ - PZF_PCPS_TIME = 0xA00, /* | | X | | PCPS_TIME, date/time/status */ + PZF_PCPS_TIME = 0xA00, /* | | X | X | PCPS_TIME, date/time/status */ PZF_TR_DISTANCE, /* | | X | X | TR_DISTANCE, dist. from transmitter [km] */ PZF_TZCODE, /* | | X | X | TZCODE, time zone code */ PZF_CORR_INFO /* | | X | | CORR_INFO, correlation info */ }; - -/* Caution: If almanac or ephemeris data are requested from the GPS rcvr */ -/* an uint16_t parameter must be supplied specifying the number of the SV */ -/* whose data is to be returned. The SV number may be 0 or MIN_SVNO to */ -/* MAX_SVNO, if the number is 0, ALL almanacs (32) are sent. */ +/* + * Caution: If GPS_ALM, GPS_EPH or a code named ..._IDX is sent to retrieve + * some data from a device then an uint16_t parameter must be also supplied + * in order to specify the index number of the data set to be returned. + * The valid index range depends on the command code. + * + * For GPS_ALM and GPS_EPH the index is the SV number which may be 0 or + * MIN_SVNO to MAX_SVNO. If the number is 0, ALL almanacs (32) are returned. + */ /* A structure holding the number of a SV and the SV's almanac. */ @@ -401,48 +481,12 @@ typedef struct -/* Configuration data for an optional LAN interface. - * - * This is only supported if the flag GPS_HAS_LAN_IP4 - * is set in RECEIVER_INFO::features. - */ - - -/* Basic network settings */ - -typedef struct -{ - uint32_t ip_addr; - uint32_t netmask; - uint32_t broad_addr; - uint32_t gateway; - uint32_t flags; /* reserved, currently 0 */ - -} IP4_SETTINGS; - - - -/* Misc configuration */ - -typedef struct -{ - uint16_t id; /* service ID, see below */ - uint16_t index; /* used if several same svcs must be cfg'd, e.g. DNS */ - char host[50]; /* see below */ - -} IP_CFG; - - - -/* Description of a service running on a device */ +#if _USE_PCPSDEFS -typedef struct -{ - uint16_t id; /* service ID, see below */ - uint16_t socket; /* the socket on which the service is listening */ - uint32_t flags; /* see below */ +/* Attention: this differs from PCPS_TZCODE defined in pcpsdefs.h */ +typedef uint16_t TZCODE; -} IP_SERVICE; +#endif @@ -467,6 +511,7 @@ typedef union /* common types */ uint16_t us; double d; + SVNO svno; /* user data */ SW_REV sw_rev; @@ -496,6 +541,18 @@ typedef union MULTI_REF_STATUS multi_ref_status; RCV_TIMEOUT rcv_timeout; IGNORE_LOCK ignore_lock; + IRIG_SETTINGS irig_rx_settings; + IRIG_INFO irig_rx_info; + MBG_REF_OFFS ref_offs; + MBG_DEBUG_STATUS debug_status; + XMULTI_REF_SETTINGS_IDX xmulti_ref_settings_idx; + XMULTI_REF_INFO_IDX xmulti_ref_info_idx; + XMULTI_REF_STATUS_IDX xmulti_ref_status_idx; + MBG_OPT_SETTINGS opt_settings; + MBG_OPT_INFO opt_info; + MBG_TIME_SCALE_INFO time_scale_info; + MBG_TIME_SCALE_SETTINGS time_scale_settings; + NAV_ENGINE_SETTINGS nav_engine_settings; /* GPS system data */ CFGH cfgh; @@ -507,11 +564,12 @@ typedef union /* Misc data */ IP4_SETTINGS ip4_settings; + LAN_IF_INFO lan_if_info; #if _USE_PCPSDEFS PCPS_TIME pcps_time; TR_DISTANCE tr_distance; - PCPS_TZCODE tzcode; + TZCODE tzcode; CORR_INFO corr_info; #endif @@ -546,12 +604,14 @@ typedef union typedef struct { MSG_HDR hdr; + #if _USE_ENCRYPTION uint8_t aes_initvect[AES_BLOCK_SIZE]; #else // In this case this structure is just a dummy to avoid // a compiler error with the function prototypes. #endif + } CRYPT_MSG_PREFIX; @@ -561,15 +621,19 @@ typedef struct typedef struct { uint8_t aes_initvect[AES_BLOCK_SIZE]; + struct { MSG_HDR enc_hdr; + union { uint8_t bytes[MAX_MSG_DATA_SIZE]; MSG_DATA msg_data; } enc_msg; + } enc_msg; + } CRYPT_MSG_DATA; #endif @@ -592,6 +656,7 @@ typedef struct #if _USE_ENCRYPTION CRYPT_MSG_DATA crypt_msg_data; #endif + } u; } MBG_MSG_BUFF; @@ -607,6 +672,12 @@ 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_CHK_TSTR + void (*chk_tstr_fnc)( char c, TIMESTR_CHECK *arg ); /* optional handler for normal, non-protocol data */ + TIMESTR_CHECK *chk_tstr_arg; + #endif + } MBG_MSG_RCV_CTL; @@ -636,6 +707,10 @@ typedef struct int buf_size; int xfer_mode; + #if _USE_MUTEX + MBG_MUTEX_HANDLE xmt_mutex; + #endif + } MBG_MSG_XMT_CTL; @@ -652,8 +727,8 @@ enum #if _USE_SOCKET_IO -#if !defined ( MBGEXTIO_TIMEOUT_SOCKET ) - #define MBGEXTIO_TIMEOUT_SOCKET 2 +#if !defined ( MBGEXTIO_RCV_TIMEOUT_SOCKET ) + #define MBGEXTIO_RCV_TIMEOUT_SOCKET 2000 // [ms] #endif #define LAN_XPT_PORT 10001 @@ -666,6 +741,7 @@ typedef struct { int sockfd; struct sockaddr_in addr; + } SOCKET_IO_STATUS; #endif // _USE_SOCKET_IO @@ -673,23 +749,15 @@ typedef struct #if _USE_SERIAL_IO -#if !defined ( MBGEXTIO_TIMEOUT_SERIAL ) - #define MBGEXTIO_TIMEOUT_SERIAL 3 -#endif +#endif // _USE_SERIAL_IO -typedef struct -{ - MBG_HANDLE port_handle; // the handle that will be used for the device - #if defined( MBG_TGT_UNIX ) - struct termios oldtio; - struct termios newtio; - #endif -} SERIAL_IO_STATUS; - -#endif // _USE_SERIAL_IO +#if defined( _USE_PACK ) // set default alignment + #pragma pack() +#endif +// For the next structure we can and should use native alignment: typedef struct { @@ -698,7 +766,8 @@ typedef struct int conn_type; int io_error; - int timeout; + ulong msg_rcv_timeout; // binary message receive timeout [ms] + ulong char_rcv_timeout; // serial character receive timeout [ms] #if _USE_ENCRYPTION uint8_t aes_initvect[AES_BLOCK_SIZE]; @@ -709,16 +778,18 @@ typedef struct SECU_SETTINGS secu_settings; #endif - union - { - #if _USE_SOCKET_IO - SOCKET_IO_STATUS sockio; - #endif - - #if _USE_SERIAL_IO - SERIAL_IO_STATUS serio; - #endif - } st; + #if _USE_SERIAL_IO || _USE_SOCKET_IO + union + { + #if _USE_SOCKET_IO + SOCKET_IO_STATUS sockio; + #endif + + #if _USE_SERIAL_IO + SERIAL_IO_STATUS serio; + #endif + } st; + #endif } MBG_MSG_CTL; @@ -750,14 +821,11 @@ enum int chk_data_csum( MBG_MSG_BUFF *pmb ) ; int encrypt_message( MBG_MSG_CTL *pmctl, CRYPT_MSG_PREFIX *pcmp, MBG_MSG_BUFF *pmb ) ; int decrypt_message( MBG_MSG_CTL *pmctl ) ; - void set_encryption_mode( MBG_MSG_CTL *pmctl, int mode, uint8_t *key ) ; + void set_encryption_mode( MBG_MSG_CTL *pmctl, int mode, const char *key ) ; int xmt_tbuff( MBG_MSG_CTL *pmctl ) ; int xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) ; int xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t us ) ; int check_transfer( MBG_MSG_RCV_CTL *prctl, uint8_t c ) ; - int mbgserio_close( MBG_HANDLE h ) ; - int mbgserio_read( MBG_HANDLE h, void *buffer, unsigned int count ) ; - int mbgserio_write( MBG_HANDLE h, const void *buffer, unsigned int count ) ; /* ----- function prototypes end ----- */ @@ -768,11 +836,6 @@ enum #undef _ext -#if defined( _USE_PACK ) // set default alignment - #pragma pack() -#endif - - #ifdef __cplusplus } #endif diff --git a/mbglib/common/mbg_tgt.h b/mbglib/common/mbg_tgt.h index f8559fe..d5aba94 100644 --- a/mbglib/common/mbg_tgt.h +++ b/mbglib/common/mbg_tgt.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbg_tgt.h 1.8 2006/10/25 12:20:45 martin REL_M $ + * $Id: mbg_tgt.h 1.22 2009/10/01 08:20:50 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,7 +11,48 @@ * * ----------------------------------------------------------------------- * $Log: mbg_tgt.h $ - * Revision 1.8 2006/10/25 12:20:45 martin + * Revision 1.22 2009/10/01 08:20:50 martin + * Fixed inline code support with different BC versions. + * Revision 1.21 2009/09/01 10:34:23Z martin + * Don't define __mbg_inline for CVI and undefined targets. + * Revision 1.20 2009/08/18 15:14:26 martin + * Defined default MBG_INVALID_PORT_HANDLE for non-Windows targets. + * Revision 1.19 2009/06/09 10:03:58 daniel + * Preliminary support for ARM architecture. + * Revision 1.18 2009/04/01 14:10:55 martin + * Cleanup for CVI. + * Revision 1.17 2009/03/19 15:21:07Z martin + * Conditionally define DWORD_PTR type for old MS C compilers. + * Revision 1.16 2008/12/08 16:42:30 martin + * Defined _GNU_SOURCE for Linux. + * Revision 1.15 2008/11/19 15:31:49 martin + * Added symbol MBG_ARCH_I386. + * Revision 1.14 2008/09/03 15:06:04 martin + * Support DOS protected mode target. + * Support SUN SPARC architecture. + * Specified handle types for common host environments. + * Added macro MBG_USE_MM_IO_FOR_PCI. + * Added macro _nop_macro_fnc(). + * Revision 1.13 2008/01/30 15:52:22 martin + * Modified checking for availability of wchar_t. + * Revision 1.13 2008/01/29 15:18:07Z martin + * Recognize DOS target under Watcom compilers. + * Flag Watcom C always supports wchar_t. + * Revision 1.12 2008/01/17 09:38:50Z daniel + * Added macros to determine whether C language extensions + * (e.g. C94, C99) are supported by the target environment. + * Added macro to check whether wchar_t and friends are + * supported, and some compatibility stuff. + * Revision 1.11 2007/10/31 16:58:03 martin + * Fixed __mbg_inline for Borland C (DOS). + * Revision 1.10 2007/09/25 08:10:27Z martin + * Support CVI target environment. + * Added MBG_PORT_HANDLE type for serial ports. + * Added macros for unified inline code syntax. + * Revision 1.9 2006/12/08 12:45:54Z martin + * Under Windows include ntddk.h rather than windows.h + * if building kernel driver . + * Revision 1.8 2006/10/25 12:20:45Z martin * Initial support for FreeBSD, NetBSD, and OpenBSD. * Added definitions for generic handle types. * Revision 1.7 2006/08/23 13:43:55 martin @@ -38,6 +79,8 @@ /* Other headers to be included */ +#include <stddef.h> + #ifdef _MBG_TGT #define _ext #else @@ -47,7 +90,12 @@ /* Start of header body */ -#if defined( _WIN32_WINNT ) +#if defined( _CVI ) || defined( _CVI_ ) + + #define MBG_TGT_WIN32 + #define MBG_TGT_CVI + +#elif defined( _WIN32_WINNT ) // MS platform SDK // WinNT 4.0 and above @@ -82,6 +130,11 @@ // MS Visual C++ #define MBG_TGT_WIN32 +#elif defined( __WINDOWS_386__ ) + + // Watcom C/C++ for target Win32 + #define MBG_TGT_WIN32 + #elif defined( __NETWARE_386__ ) // Watcom C/C++ for target NetWare @@ -96,6 +149,7 @@ // GCC for target Linux #define MBG_TGT_LINUX + #define _GNU_SOURCE 1 #elif defined( __FreeBSD__ ) @@ -122,11 +176,78 @@ #define MBG_TGT_QNX_NTO #endif -#elif defined( __MSDOS__ ) +#elif defined( __MSDOS__ ) || defined( __DOS__ ) // any compiler for target DOS #define MBG_TGT_DOS + #if defined( __WATCOMC__ ) && defined( __386__ ) + + #define MBG_TGT_DOS_PM // protected mode DOS + + #endif + +#endif + +// Some definitions which depend on the type of compiler ... + +#if defined( __GNUC__ ) + + #define __mbg_inline __inline__ + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + + #if defined( __sparc__ ) + + #define MBG_ARCH_SPARC + #define _MBG_ARCH_DEFINED + + #elif defined( __arm__ ) + + #define MBG_ARCH_ARM + #define _MBG_ARCH_DEFINED + + #endif + +#elif defined( _MSC_VER ) + + #define __mbg_inline __forceinline + + #define MBG_TGT_HAS_WCHAR_T 1 + +#elif defined( _CVI ) || defined( _CVI_ ) + + // Inline code is not supported. + + #define MBG_TGT_HAS_WCHAR_T 0 + +#elif defined( __BORLANDC__ ) + + #if defined( __cplusplus ) + #define __mbg_inline inline // standard C++ syntax + #elif ( __BORLANDC__ > 0x410 ) // BC3.1 defines 0x410 ! + #define __mbg_inline __inline // newer BC versions support this for C + #else + #define __mbg_inline // up to BC3.1 not supported for C + #endif + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + +#elif defined( __WATCOMC__ ) + + #define __mbg_inline _inline + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + +#endif + + + +// Currently we support only Sparc and i386/x86_64 architectures, +// so unless we have explicitely found sparc we assume i386. + +#if !defined( _MBG_ARCH_DEFINED ) + #define MBG_ARCH_I386 #endif @@ -156,6 +277,33 @@ #define WIN32_FLAVOR "ia64" #endif + #if defined( _KDD_ ) + #include <ntddk.h> + #else + // This must not be used for kernel drivers. + #include <windows.h> + typedef HANDLE MBG_HANDLE; + + #define MBG_INVALID_HANDLE INVALID_HANDLE_VALUE + + #if defined( MBG_TGT_CVI ) + // CVI uses an own set of functions to support serial ports + typedef int MBG_PORT_HANDLE; + #define MBG_INVALID_PORT_HANDLE -1 + #else + typedef HANDLE MBG_PORT_HANDLE; + #endif + + // The DWORD_PTR type is not defined in the headers shipping + // with VC6. However, if the SDK is installed then the SDK's + // headers may declare this type. This is at least the case + // in the Oct 2001 SDK which also defines the symbol _W64. + #if !defined( _W64 ) + typedef DWORD DWORD_PTR; + #endif + + #endif + #define _MBG_API WINAPI #if defined( MBG_LIB_EXPORT ) @@ -164,31 +312,71 @@ #define _MBG_API_ATTR __declspec( dllimport ) #endif +#elif defined( MBG_TGT_UNIX ) + + typedef int MBG_HANDLE; + typedef int MBG_PORT_HANDLE; + + #define MBG_INVALID_HANDLE -1 + #else - #define _MBG_API - #define _MBG_API_ATTR + typedef int MBG_HANDLE; + typedef int MBG_PORT_HANDLE; + + #define MBG_INVALID_HANDLE -1 #endif +#if !defined( _MBG_API ) + #define _MBG_API +#endif -#if defined( MBG_TGT_WIN32 ) +#if !defined( _MBG_API_ATTR ) + #define _MBG_API_ATTR +#endif - #include <windows.h> +#if !defined( MBG_INVALID_PORT_HANDLE ) + #define MBG_INVALID_PORT_HANDLE MBG_INVALID_HANDLE +#endif - typedef HANDLE MBG_HANDLE; +#if !defined( MBG_USE_MM_IO_FOR_PCI ) + #if ( 0 || defined( MBG_ARCH_SPARC ) ) + #define MBG_USE_MM_IO_FOR_PCI 1 + #else + #define MBG_USE_MM_IO_FOR_PCI 0 + #endif +#endif - #define MBG_INVALID_HANDLE INVALID_HANDLE_VALUE -#elif defined( MBG_TGT_UNIX ) +#if !defined( _nop_macro_fnc ) + #define _nop_macro_fnc() do {} while (0) +#endif - typedef int MBG_HANDLE; - #define MBG_INVALID_HANDLE -1 +// The macros below are defined in order to be able to check if +// certain C language extensions are available on the target system: +#define MBG_TGT_C94 ( defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199409L ) ) +#define MBG_TGT_C99 ( defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) ) +// Check if wchar_t is supported +#if !defined( MBG_TGT_HAS_WCHAR_T ) + #define MBG_TGT_HAS_WCHAR_T ( MBG_TGT_C94 || defined( WCHAR_MAX ) ) #endif +#if !MBG_TGT_HAS_WCHAR_T + // Even if wchar_t is not natively supported by the target platform + // there may already be a compatibility define (e.g. BC3.1) + // However, some functions may be missing (e.g. snwprintf()). + #if !defined( _WCHAR_T ) /* BC3.1 */ \ + && !defined( _WCHAR_T_DEFINED_ ) /* WC11 */ + //##++ #define _WCHAR_T + #define wchar_t char + #endif +#endif + + /* End of header body */ diff --git a/mbglib/common/mbg_tmo.c b/mbglib/common/mbg_tmo.c new file mode 100644 index 0000000..cec9943 --- /dev/null +++ b/mbglib/common/mbg_tmo.c @@ -0,0 +1,64 @@ + +/************************************************************************** + * + * $Id: mbg_tmo.c 1.2 2009/09/01 10:36:45 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:45 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..daf4a25 --- /dev/null +++ b/mbglib/common/mbg_tmo.h @@ -0,0 +1,312 @@ + +/************************************************************************** + * + * $Id: mbg_tmo.h 1.2 2009/09/01 10:38:21 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Inline functions for portable timeout handling. + * + * ----------------------------------------------------------------------- + * $Log: mbg_tmo.h $ + * Revision 1.2 2009/09/01 10:38:21 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 <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 > 1000000UL ) + { + t_tmo->tv_usec -= 1000000UL; + 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 ) || defined( MBG_TGT_WIN32 ) + +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 214266b..088066b 100644 --- a/mbglib/common/mbgextio.c +++ b/mbglib/common/mbgextio.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgextio.c 1.2 2006/10/25 12:18:31 martin REL_M $ + * $Id: mbgextio.c 1.9 2009/10/02 14:19:05 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,6 +11,41 @@ * * ----------------------------------------------------------------------- * $Log: mbgextio.c $ + * 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. + * Revision 1.7 2009/09/01 10:44:58 martin + * Cleanup for CVI. + * Use new portable timeout functions from mbg_tmo.h. + * Timeouts are now specified in milliseconds. + * Distinguish between character timeout and message timeout. + * Only fetch one character at a time to prevent received characters + * from being discarded after the end of one message. + * Revision 1.6 2009/03/10 17:02:08Z martin + * Added support for configurable time scales. + * Added mbgextio_get_time() call. + * Fixed some compiler warnings. + * Revision 1.5 2008/09/04 14:35:50Z martin + * Fixed opening COM port under CVI. + * Moved generic serial I/O stuff to mbgserio.c and mbgserio.h. + * Restart reception if received msg does not match expected cmd code. + * Fixed timeout value for Windows. + * New symbol _MBGEXTIO_DIRECT_RC controls whether the return code of the + * mbgextio_set_...() functions is evaluated or returned as-is. + * New functions mbgextio_set_time(), mbgextio_set_tzdl(). + * Added mbgextio_get_ucap(). This may not work with older firmware, + * see the comments in mbgextio_get_ucap(). + * Conditionally support checking of time strings. + * Revision 1.4 2007/02/27 10:35:19Z martin + * Added mutex for transmit buffer to make transmission thread-safe. + * Fixed timeout handling for serial reception. + * Renamed mbgextio_get_data() to mbgextio_rcv_msg(). + * Added some new functions. + * Temp. changes for parameter setting functions. + * Added comments on POSIX flags used when opening serial port. + * Revision 1.3 2006/12/21 10:56:17 martin + * Added function mbgextio_set_port_parm. * Revision 1.2 2006/10/25 12:18:31 martin * Support serial I/O under Windows. * Revision 1.1 2006/08/24 12:40:37Z martin @@ -19,9 +54,15 @@ **************************************************************************/ #define _MBGEXTIO - #include <mbgextio.h> + #include <mbgextio.h> + + //##++ The following lines are required + // until mbgextio becomes a DLL: + #undef _MBG_API_ATTR + #define _MBG_API_ATTR #undef _MBGEXTIO +#include <mbgserio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -30,75 +71,27 @@ #if defined( MBG_TGT_UNIX ) #include <unistd.h> #include <fcntl.h> - #include <sys/time.h> +#else + typedef int ssize_t; #endif -#if _USE_SERIAL_IO - #include <ctype.h> +#if !defined( MBGEXTIO_DIRECT_RC ) + #define _MBGEXTIO_DIRECT_RC 0 //##++ 1 #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" { +// default serial message timeout +#if !defined ( MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL ) + #define MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL 3000 // [ms] #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 -} +// default serial single character timeout +#if !defined ( MBGEXTIO_CHAR_RCV_TIMEOUT_SERIAL ) + #define MBGEXTIO_CHAR_RCV_TIMEOUT_SERIAL 200 // [ms] #endif -#endif // defined( _USE_V24TOOLS ) - -/*------------------------------------------------------------------------*/ - - -#if defined MBG_TGT_WIN32 +#if defined( MBG_TGT_WIN32 ) && _USE_SOCKET_IO static /*HDR*/ BOOL WINAPI mbgextio_on_console_event( DWORD dwCtrlType ) @@ -124,7 +117,7 @@ void mbgextio_set_console_control_handler( void ) { static int has_been_set; - if ( !has_been_set ) + if ( !has_been_set ) { SetConsoleCtrlHandler( mbgextio_on_console_event, TRUE ); has_been_set = 1; @@ -157,9 +150,9 @@ int socket_init( MBG_MSG_CTL *pmctl, const char *host ) // so try to initialize now. WORD wVersionRequested; WSADATA wsaData; - + wVersionRequested = MAKEWORD( 2, 2 ); - + rc = WSAStartup( wVersionRequested, &wsaData ); // If initialization has succeeded, try again. @@ -210,7 +203,9 @@ int comm_init( MBG_MSG_CTL *pmctl, const char *passwd ) strncpy( pss->password, passwd, sizeof( pss->password ) ); pmctl->conn_type = MBG_CONN_TYPE_SOCKET; - pmctl->timeout = MBGEXTIO_TIMEOUT_SOCKET; + pmctl->msg_rcv_timeout = MBGEXTIO_RCV_TIMEOUT_SOCKET; + // pmctl->char_rcv_timeout is not used with sockets + set_encryption_mode( pmctl, MBG_XFER_MODE_ENCRYTED, pss->password ); pmb = pmctl->xmt.pmb; @@ -219,7 +214,7 @@ int comm_init( MBG_MSG_CTL *pmctl, const char *passwd ) pmb->hdr.len = sizeof( pmb->u.msg_data.secu_settings ); xmt_tbuff( pmctl ); - rc = mbgextio_get_data( pmctl, GPS_SECU_SETTINGS ); + rc = mbgextio_rcv_msg( pmctl, GPS_SECU_SETTINGS ); if ( rc != TR_COMPLETE ) return -1; /* connection refused */ @@ -245,11 +240,15 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl, return rc; comm_init( pmctl, passwd ); - - #if defined MBG_TGT_WIN32 + + #if defined( MBG_TGT_WIN32 ) mbgextio_set_console_control_handler(); #endif + #if _USE_MUTEX + _mbg_mutex_init( pmctl->xmt.xmt_mutex ); + #endif + return rc; } // mbgextio_open_socket @@ -264,347 +263,237 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl, _MBG_API_ATTR int _MBG_API mbgextio_open_serial( MBG_MSG_CTL *pmctl, const char *dev, uint32_t baud_rate, const char *framing ) { - MBG_HANDLE port_handle; - const char *cp; + int rc; pmctl->conn_type = MBG_CONN_TYPE_SERIAL; - pmctl->timeout = MBGEXTIO_TIMEOUT_SERIAL; - - #if defined( MBG_TGT_DOS ) - #if defined( _USE_V24TOOLS ) - { - int datab = 8; - char parity = 'N'; - int stopb = 1; + pmctl->msg_rcv_timeout = MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL; + pmctl->char_rcv_timeout = MBGEXTIO_CHAR_RCV_TIMEOUT_SERIAL; - port_handle = v24open( (char *) dev, OPEN_MODE ); + rc = mbgserio_open( &pmctl->st.serio, dev ); - if ( port_handle < 0 ) - return -1; + if ( rc < 0 ) //##++ + return rc; - pmctl->st.serio.port_handle = port_handle; + mbgserio_set_parms( &pmctl->st.serio, baud_rate, framing ); - // setup framing. - for ( cp = framing; *cp; cp++ ) - { - char c = toupper( *cp ); + #if _USE_MUTEX + _mbg_mutex_init( pmctl->xmt.xmt_mutex ); + #endif - 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 -1; // invalid framing string - } - } + return 0; - v24setparams( port_handle, baud_rate, datab, parity, stopb ); +} // mbgextio_open_serial - return port_handle; - } - #else +#endif - #error This has to be rewritten for DOS without v24tools. - #endif - #elif defined( MBG_TGT_WIN32 ) +/*HDR*/ +_MBG_API_ATTR void _MBG_API mbgextio_close_connection( MBG_MSG_CTL *pmctl ) +{ + switch ( pmctl->conn_type ) { - DCB dcb; - COMMTIMEOUTS commtimeouts; - - port_handle = CreateFile( dev, GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, - NULL ); - - if ( port_handle == INVALID_HANDLE_VALUE ) - return -1; - - - pmctl->st.serio.port_handle = port_handle; - - // initialize comport buffer - 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 ) + #if _USE_SERIAL_IO + case MBG_CONN_TYPE_SERIAL: { - 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; + #if defined( MBG_TGT_UNIX ) + tcsetattr( pmctl->st.serio.port_handle, TCSANOW, &pmctl->st.serio.oldtio ); + #endif - case '2': - dcb.StopBits = TWOSTOPBITS; - break; + mbgserio_close( &pmctl->st.serio ); + } break; + #endif // _USE_SERIAL_IO - default: - return -1; // invalid framing string - } - } + #if _USE_SOCKET_IO + case MBG_CONN_TYPE_SOCKET: + { + _mbg_close( pmctl->st.sockio.sockfd ); + pmctl->st.sockio.sockfd = 0; + } break; + #endif // _USE_SOCKET_IO + }; // switch - 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; + #if _USE_MUTEX + _mbg_mutex_destroy( pmctl->xmt.xmt_mutex ); + #endif - SetCommState ( port_handle, &dcb ); +} // mbgextio_close_connection - 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 ); +#if _USE_SERIAL_IO - mbgextio_set_console_control_handler(); +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_force_connection( const char *dev ) +{ + static const char *cmd_str = "\nDFC\n"; //##++ - return 0; - } - #elif defined( MBG_TGT_UNIX ) + MBG_MSG_CTL mctl = { - tcflag_t c_cflag; + { NULL, 0 }, + { NULL, 0 } + }; - // open as not controlling TTY to prevent from being - // killed if CTRL-C is received - port_handle = _mbg_open( dev, O_RDWR | O_NOCTTY ); + int i; + int j; + int len = strlen( cmd_str ); - if ( port_handle < 0 ) - return -1; + for ( i = 0; i < N_MBG_BAUD_RATES; i++ ) + { + for ( j = 0; j < N_MBG_FRAMINGS; j++ ) + { + uint32_t baud_rate = mbg_baud_rates[i]; + const char *framing = mbg_framing_strs[j]; + int rc = mbgextio_open_serial( &mctl, dev, baud_rate, framing ); - pmctl->st.serio.port_handle = port_handle; + if ( rc != 0 ) // failed to open port + return -1; - /* save current device settings */ - tcgetattr( port_handle, &pmctl->st.serio.oldtio ); + _mbgserio_write( mctl.st.serio.port_handle, cmd_str, len ); - // atexit( port_deinit ); + #if defined( MBG_TGT_UNIX ) + tcdrain( mctl.st.serio.port_handle ); + #elif defined( MBG_TGT_CVI ) + //##++++ + #elif defined( MBG_TGT_WIN32 ) + FlushFileBuffers( mctl.st.serio.port_handle ); + #endif - // 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 -1; // invalid + mbgextio_close_connection( &mctl ); } + } + return 0; - // setup framing. - for ( cp = framing; *cp; cp++ ) - { - switch ( _toupper( *cp ) ) - { - case '7': c_cflag |= CS7; break; - case '8': c_cflag |= CS8; break; +} // mbgextio_force_connection - case 'N': break; - case 'E': c_cflag |= PARENB; break; - case 'O': c_cflag |= PARENB | PARODD; break; +#endif // _USE_SERIAL_IO - case '1': break; - case '2': c_cflag |= CSTOPB; break; - default: return -1; // invalid framing string - } - } - // setup termios control flags: - // local connection, no modem control (CLOCAL) - // no flow control (no CRTSCTS) - // enable receiving - pmctl->st.serio.newtio.c_cflag = c_cflag | CLOCAL | CREAD; +/*HDR*/ +_MBG_API_ATTR void _MBG_API mbgextio_set_char_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) +{ + pmctl->char_rcv_timeout = new_timeout; +} // mbgextio_set_char_rcv_timeout - // setup input flags: - // make terminal raw and dumb (no ICRNL) - // if parity is enabled, ignore bytes with parity errors (IGNPAR) - pmctl->st.serio.newtio.c_iflag = 0; - if ( c_cflag & PARENB ) - pmctl->st.serio.newtio.c_iflag |= IGNPAR; +/*HDR*/ +_MBG_API_ATTR ulong _MBG_API mbgextio_get_char_rcv_timeout( const MBG_MSG_CTL *pmctl ) +{ + return pmctl->char_rcv_timeout; - // setup output flags: - // raw output (no flags) - pmctl->st.serio.newtio.c_oflag = 0; +} // mbgextio_get_char_rcv_timeout - // setup local mode flags: - // don't echo characters - // don't generate signals to the calling program - pmctl->st.serio.newtio.c_lflag = 0; +/*HDR*/ +_MBG_API_ATTR void _MBG_API mbgextio_set_msg_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) +{ + pmctl->msg_rcv_timeout = new_timeout; - // setup control characters: - // blocking read until 1 char arrives - pmctl->st.serio.newtio.c_cc[VMIN] = 0; - pmctl->st.serio.newtio.c_cc[VTIME] = 0; +} // mbgextio_set_msg_rcv_timeout - // now clean the modem line and activate the settings for modem - tcflush( port_handle, TCIFLUSH ); - tcsetattr( port_handle, TCSANOW, &pmctl->st.serio.newtio ); - fflush( stdout ); - setvbuf( stdout, NULL, _IONBF, 0 ); - #if 0 - tcgetattr( STDOUT_FILENO, &oldstdtio ); - newstdtio = oldstdtio; - printf( "\nTermio Structure:\n" ); - printf( "c_iflag = %X\n", newstdtio.c_iflag ); - printf( "c_oflag = %X\n", newstdtio.c_oflag ); - printf( "c_cflag = %X\n", newstdtio.c_cflag ); - printf( "c_lflag = %X\n", newstdtio.c_lflag ); +/*HDR*/ +_MBG_API_ATTR ulong _MBG_API mbgextio_get_msg_rcv_timeout( const MBG_MSG_CTL *pmctl ) +{ + return pmctl->msg_rcv_timeout; - //for (i = 0;i < NCCS;i++) - // printf("c_cc[%d] = %X\n", i, newstdtio.c_cc[i]); +} // mbgextio_get_msg_rcv_timeout - newstdtio.c_lflag &= ~ICANON; - tcsetattr( STDOUT_FILENO, TCSANOW, &newstdtio ); - #endif - return 0; +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd, + const void *p, int n_bytes ) +{ + MBG_MSG_BUFF *pmb; - } - #else + if ( n_bytes > sizeof( pmb->u.msg_data ) ) + return -1; // bytes to send exceed buffer size - #error This target OS is not supported. + #if _USE_MUTEX + _mbg_mutex_lock( pmctl->xmt.xmt_mutex ); #endif -} // mbgextio_open_serial + pmb = pmctl->xmt.pmb; -#endif + if ( p && n_bytes ) + memcpy( pmb->u.bytes, p, n_bytes ); + pmb->hdr.len = n_bytes; + pmb->hdr.cmd = cmd; + xmt_tbuff( pmctl ); + #if _USE_MUTEX + _mbg_mutex_unlock( pmctl->xmt.xmt_mutex ); + #endif -/*HDR*/ -_MBG_API_ATTR void _MBG_API mbgextio_close_connection( MBG_MSG_CTL *pmctl ) -{ - switch ( pmctl->conn_type ) + if ( cmd & GPS_REQACK ) { - #if _USE_SERIAL_IO - case MBG_CONN_TYPE_SERIAL: - { - #if defined( MBG_TGT_UNIX ) - tcsetattr( pmctl->st.serio.port_handle, TCSANOW, &pmctl->st.serio.oldtio ); - #endif + int rc = mbgextio_rcv_msg( pmctl, (GPS_CMD) ( cmd & ~GPS_CTRL_MSK ) ); - _mbgserio_close( pmctl->st.serio.port_handle ); + if ( rc != TR_COMPLETE ) + return -2; - pmctl->st.serio.port_handle = 0; - } break; - #endif // _USE_SERIAL_IO - - #if _USE_SOCKET_IO - case MBG_CONN_TYPE_SOCKET: - { - _mbg_close( pmctl->st.sockio.sockfd ); - pmctl->st.sockio.sockfd = 0; - } break; - #endif // _USE_SOCKET_IO - - }; // switch - -} // mbgextio_close_connection + if ( pmctl->rcv.pmb->hdr.cmd & GPS_NACK ) + return -3; + if ( !pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) + return -4; + } -/*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) -{ - return xmt_cmd( pmctl, cmd ); + return 0; -} // mbgextio_xmt_cmd +} // mbgextio_xmt_msg /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) +_MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) { MBG_MSG_RCV_CTL *prctl; MBG_MSG_BUFF *pmb; + MBG_TMO_TIME msg_timeout; char buff[MBGEXTIO_READ_BUFFER_SIZE]; - int n_bytes; + ssize_t n_bytes; int rc; int i; + mbg_tmo_set_timeout_ms( &msg_timeout, pmctl->msg_rcv_timeout ); + for (;;) // loop until complete msg received { n_bytes = 0; + if ( mbg_tmo_curr_time_is_after( &msg_timeout ) ) + return TR_TIMEOUT; + #if _USE_SOCKET_IO if ( pmctl->conn_type == MBG_CONN_TYPE_SOCKET ) { - struct timeval tv; + struct timeval tv_timeout; fd_set fds; if ( pmctl->io_error ) return TR_IO_ERR; - // set timeout value - tv.tv_sec = 1; - tv.tv_usec = 0; + mbgserio_msec_to_timeval( pmctl->msg_rcv_timeout, &tv_timeout ); FD_ZERO( &fds ); FD_SET( pmctl->st.sockio.sockfd, &fds ); - rc = select( pmctl->st.sockio.sockfd + 1, &fds, NULL, NULL, &tv ); + rc = select( pmctl->st.sockio.sockfd + 1, &fds, NULL, NULL, &tv_timeout ); + + if ( rc == 0 ) // timeout + return TR_TIMEOUT; if ( rc < 0 ) // error { @@ -612,15 +501,11 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) return TR_IO_ERR; } - if ( rc == 0 ) // timeout - return TR_TIMEOUT; - - // data is available n_bytes = recv( pmctl->st.sockio.sockfd, buff, sizeof( buff ), 0 ); - if ( n_bytes < 0 ) + if ( n_bytes < 0 ) { pmctl->io_error = 1; return TR_IO_ERR; @@ -631,22 +516,16 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) #if _USE_SERIAL_IO if ( pmctl->conn_type == MBG_CONN_TYPE_SERIAL ) { - clock_t clk_now; - clock_t clk_start = clock(); - clock_t clk_timeout = clk_start + pmctl->timeout * CLOCKS_PER_SEC; + n_bytes = mbgserio_read_wait( pmctl->st.serio.port_handle, &buff[0], + sizeof( buff[0] ), pmctl->char_rcv_timeout ); - for (;;) // wait to read one new char + if ( n_bytes < 0 ) { - n_bytes = _mbgserio_read( pmctl->st.serio.port_handle, - &buff[0], sizeof( buff[0] ) ); - - if ( n_bytes > 0 ) - break; // new char has been received - - clk_now = clock(); + if ( n_bytes == MBGSERIO_TIMEOUT ) + return TR_TIMEOUT; - if ( clk_now > clk_timeout ) // error: timeout - return TR_TIMEOUT; + pmctl->io_error = 1; + return TR_IO_ERR; } } #endif // _USE_SERIAL_IO @@ -656,14 +535,22 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) for ( i = 0; i < n_bytes; i++ ) { + char c = buff[i]; + /* check if the new char belongs to a data transfer sequence */ - rc = check_transfer( prctl, buff[i] ); + rc = check_transfer( prctl, c ); switch ( rc ) { case TR_WAITING: /* no data transfer sequence in progress */ - case TR_RECEIVING: /* data transfer sequence in progress */ - continue; /* keep waiting */ + #if _USE_CHK_TSTR + if ( prctl->chk_tstr_fnc ) /* optionally handle normal, non-protocol data */ + prctl->chk_tstr_fnc( c, prctl->chk_tstr_arg ); + #endif + // intentional fall-through + + case TR_RECEIVING: /* data transfer sequence in progress, keep waiting */ + continue; case TR_COMPLETE: { @@ -691,6 +578,9 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) /* not waiting for a specific packet, so return if any packet is complete */ if ( cmd == (uint16_t) -1 ) return TR_COMPLETE; + + //##++ received a msg which does not match the expected code + prctl->cnt = 0; /* restart receiving */ } break; @@ -701,7 +591,49 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) } } -} // mbgextio_get_data +} // mbgextio_rcv_msg + + + +/*HDR*/ +_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 ); + #endif + + rc = xmt_cmd( pmctl, cmd ); + + #if _USE_MUTEX + _mbg_mutex_unlock( pmctl->xmt.xmt_mutex ); + #endif + + return rc; + +} // mbgextio_xmt_cmd + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t us ) +{ + int rc; + + #if _USE_MUTEX + _mbg_mutex_lock( pmctl->xmt.xmt_mutex ); + #endif + + rc = xmt_cmd_us( pmctl, cmd, us ); + + #if _USE_MUTEX + _mbg_mutex_unlock( pmctl->xmt.xmt_mutex ); + #endif + + return rc; + +} // mbgextio_xmt_cmd_us @@ -710,13 +642,24 @@ _MBG_API_ATTR int _MBG_API mbgextio_req_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) { xmt_cmd( pmctl, cmd ); /* request a set of data */ - return mbgextio_get_data( pmctl, cmd ); + return mbgextio_rcv_msg( pmctl, cmd ); } // mbgextio_req_data /*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_req_data_idx( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t idx ) +{ + xmt_cmd_us( pmctl, cmd, idx ); /* request a set of data */ + + return mbgextio_rcv_msg( pmctl, cmd ); + +} // mbgextio_req_data_idx + + + +/*HDR*/ _MBG_API_ATTR int _MBG_API mbgextio_get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) { int rc = mbgextio_req_data( pmctl, GPS_RECEIVER_INFO ); @@ -759,6 +702,51 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_bvar_stat( MBG_MSG_CTL *pmctl, BVAR_STAT /*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_time( MBG_MSG_CTL *pmctl, TTM *p ) +{ + int rc = mbgextio_req_data( pmctl, GPS_TIME ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.ttm; + + return rc; + +} // mbgextio_get_time + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_time( MBG_MSG_CTL *pmctl, const TTM *p ) +{ + GPS_CMD cmd = GPS_TIME; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + +#else + int rc; + + rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_time + + + +/*HDR*/ _MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl, LLA lla ) { int rc = mbgextio_req_data( pmctl, GPS_POS_LLA ); @@ -784,6 +772,37 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl, LLA lla ) /*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_pos_lla( MBG_MSG_CTL *pmctl, const LLA lla ) +{ + GPS_CMD cmd = GPS_POS_LLA; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) lla, sizeof( LLA ) ); + +#else + int rc; + + rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) lla, sizeof( LLA ) ); + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_pos_lla + + + +/*HDR*/ _MBG_API_ATTR int _MBG_API mbgextio_get_tzdl( MBG_MSG_CTL *pmctl, TZDL *p ) { int rc = mbgextio_req_data( pmctl, GPS_TZDL ); @@ -798,6 +817,89 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_tzdl( MBG_MSG_CTL *pmctl, TZDL *p ) /*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_tzdl( MBG_MSG_CTL *pmctl, const TZDL *p ) +{ + GPS_CMD cmd = GPS_TZDL; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + +#else + int rc; + + rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_get_tzdl + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_port_parm( MBG_MSG_CTL *pmctl, PORT_PARM *p ) +{ + int rc = mbgextio_req_data( pmctl, GPS_PORT_PARM ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.port_parm; + + return rc; + +} // mbgextio_get_port_parm + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_port_parm( MBG_MSG_CTL *pmctl, const PORT_PARM *p ) +{ + GPS_CMD cmd = GPS_PORT_PARM; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + +#else + + MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; + int rc; + + pmb->u.msg_data.port_parm = *p; + + pmb->hdr.len = sizeof( pmb->u.msg_data.port_parm ); + pmb->hdr.cmd = cmd | GPS_REQACK; + xmt_tbuff( pmctl ); + + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_port_parm + + + +/*HDR*/ _MBG_API_ATTR int _MBG_API mbgextio_get_synth( MBG_MSG_CTL *pmctl, SYNTH *p ) { int rc = mbgextio_req_data( pmctl, GPS_SYNTH ); @@ -814,17 +916,17 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_synth( MBG_MSG_CTL *pmctl, SYNTH *p ) /*HDR*/ _MBG_API_ATTR int _MBG_API mbgextio_set_synth( MBG_MSG_CTL *pmctl, const SYNTH *p ) { - MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; GPS_CMD cmd = GPS_SYNTH; - int rc; - pmb->u.msg_data.synth = *p; +#if _MBGEXTIO_DIRECT_RC - pmb->hdr.len = sizeof( pmb->u.msg_data.synth ); - pmb->hdr.cmd = cmd | GPS_REQACK; - xmt_tbuff( pmctl ); + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); - rc = mbgextio_get_data( pmctl, cmd ); +#else + int rc; + + rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); + rc = mbgextio_rcv_msg( pmctl, cmd ); if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) { @@ -833,24 +935,430 @@ _MBG_API_ATTR int _MBG_API mbgextio_set_synth( MBG_MSG_CTL *pmctl, const SYNTH * // transmitted before, an automatic frame (current time, capture) // has been sent before the acknowledge code. } - + return 0; +#endif + } // mbgextio_set_synth /*HDR*/ -_MBG_API_ATTR int _MBG_API mbgextio_get_port_parm( MBG_MSG_CTL *pmctl, PORT_PARM *p ) +_MBG_API_ATTR int _MBG_API mbgextio_get_ant_info( MBG_MSG_CTL *pmctl, ANT_INFO *p ) { - int rc = mbgextio_req_data( pmctl, GPS_PORT_PARM ); + int rc = mbgextio_req_data( pmctl, GPS_ANT_INFO ); if ( ( rc == TR_COMPLETE ) && p ) - *p = pmctl->rcv.pmb->u.msg_data.port_parm; + *p = pmctl->rcv.pmb->u.msg_data.ant_info; return rc; -} // mbgextio_get_port_parm +} // mbgextio_get_ant_info + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, TTM *p ) +{ + int rc; + + xmt_cmd( pmctl, GPS_UCAP ); /* request a set of data */ + + // Attention: Older firmware versions may reply with GPS_TIME + // messages instead of GPS_UCAP messages, and may not send a reply + // at all if no capture event is available in the on-board FIFO. + rc = mbgextio_rcv_msg( pmctl, GPS_UCAP ); + + if ( ( rc == TR_COMPLETE ) && p ) + { + // If the length of the msg header is 0 then the capture buffer + // is empty. This is indicated with 0xFF in the seconds field of + // the GPS time structure. + if ( pmctl->rcv.pmb->hdr.len > 0 ) + *p = pmctl->rcv.pmb->u.msg_data.ttm; + else + p->tm.sec = (int8_t) 0xFF; // no capture event available + } + + return rc; + +} // mbgextio_get_ucap + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_enable_flags( MBG_MSG_CTL *pmctl, ENABLE_FLAGS *p ) +{ + int rc = mbgextio_req_data( pmctl, GPS_ENABLE_FLAGS ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.enable_flags; + + return rc; + +} // mbgextio_get_enable_flags + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_enable_flags( MBG_MSG_CTL *pmctl, const ENABLE_FLAGS *p ) +{ + GPS_CMD cmd = GPS_ENABLE_FLAGS; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + +#else + int rc; + + rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_enable_flags + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_stat_info( MBG_MSG_CTL *pmctl, STAT_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, GPS_STAT_INFO ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.stat_info; + + return rc; + +} // mbgextio_get_stat_info + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_ant_cable_len( MBG_MSG_CTL *pmctl, ANT_CABLE_LEN *p ) +{ + int rc = mbgextio_req_data( pmctl, GPS_ANT_CABLE_LENGTH ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.ant_cable_len; + + return rc; + +} // mbgextio_get_ant_cable_len + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_ant_cable_len( MBG_MSG_CTL *pmctl, const ANT_CABLE_LEN *p ) +{ + GPS_CMD cmd = GPS_ANT_CABLE_LENGTH; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + +#else + int rc; + + rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_ant_cable_len + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_irig_tx_info( MBG_MSG_CTL *pmctl, IRIG_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, GPS_IRIG_TX_INFO ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.irig_tx_info; + + return rc; + +} // mbgextio_get_irig_tx_info + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_irig_tx_settings( MBG_MSG_CTL *pmctl, const IRIG_SETTINGS *p ) +{ + GPS_CMD cmd = GPS_IRIG_TX_SETTINGS; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + +#else + int rc; + + rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_irig_tx_settings + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_irig_rx_info( MBG_MSG_CTL *pmctl, IRIG_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, GPS_IRIG_RX_INFO ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.irig_rx_info; + + return rc; + +} // mbgextio_get_irig_rx_info + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_irig_rx_settings( MBG_MSG_CTL *pmctl, const IRIG_SETTINGS *p ) +{ + GPS_CMD cmd = GPS_IRIG_RX_SETTINGS; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + +#else + int rc; + + rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_irig_rx_settings + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_ref_offs( MBG_MSG_CTL *pmctl, MBG_REF_OFFS *p ) +{ + int rc = mbgextio_req_data( pmctl, GPS_REF_OFFS ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.ref_offs; + + return rc; + +} // mbgextio_get_ref_offs + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_ref_offs( MBG_MSG_CTL *pmctl, const MBG_REF_OFFS *p ) +{ + GPS_CMD cmd = GPS_REF_OFFS; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + +#else + int rc; + + rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_ref_offs + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_debug_status( MBG_MSG_CTL *pmctl, MBG_DEBUG_STATUS *p ) +{ + int rc = mbgextio_req_data( pmctl, GPS_DEBUG_STATUS ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.debug_status; + + return rc; + +} // mbgextio_get_debug_status + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_opt_info( MBG_MSG_CTL *pmctl, MBG_OPT_INFO *p ) +{ + int rc = mbgextio_req_data( pmctl, GPS_OPT_INFO ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.opt_info; + + return rc; + +} // mbgextio_get_opt_info + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_opt_settings( MBG_MSG_CTL *pmctl, const MBG_OPT_SETTINGS *p ) +{ + GPS_CMD cmd = GPS_OPT_SETTINGS; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + +#else + int rc; + + rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) ); + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_opt_settings + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_str_type_info_idx( MBG_MSG_CTL *pmctl, + STR_TYPE_INFO_IDX *p, uint16_t idx ) +{ + int rc; + + xmt_cmd_us( pmctl, GPS_STR_TYPE_INFO_IDX, idx ); + + rc = mbgextio_rcv_msg( pmctl, GPS_STR_TYPE_INFO_IDX ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.str_type_info_idx; + + return rc; + +} // mbgextio_get_str_type_info_idx + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_port_info_idx( MBG_MSG_CTL *pmctl, + PORT_INFO_IDX *p, uint16_t idx ) +{ + int rc; + + xmt_cmd_us( pmctl, GPS_PORT_INFO_IDX, idx ); + + rc = mbgextio_rcv_msg( pmctl, GPS_PORT_INFO_IDX ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.port_info_idx; + + return rc; + +} // mbgextio_get_port_info_idx + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_port_settings_idx( MBG_MSG_CTL *pmctl, + const PORT_SETTINGS *p, uint16_t idx ) +{ + GPS_CMD cmd = GPS_PORT_SETTINGS_IDX; + MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; + int rc; + + pmb->u.msg_data.port_settings_idx.port_settings = *p; + pmb->u.msg_data.port_settings_idx.idx = idx; + + pmb->hdr.len = sizeof( pmb->u.msg_data.port_settings_idx ); + pmb->hdr.cmd = cmd | GPS_REQACK; + rc = xmt_tbuff( pmctl ); + +#if _MBGEXTIO_DIRECT_RC + + return rc; + +#else + + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_port_settings_idx @@ -862,7 +1370,7 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_pout_info_idx( MBG_MSG_CTL *pmctl, xmt_cmd_us( pmctl, GPS_POUT_INFO_IDX, idx ); - rc = mbgextio_get_data( pmctl, GPS_POUT_INFO_IDX ); + rc = mbgextio_rcv_msg( pmctl, GPS_POUT_INFO_IDX ); if ( ( rc == TR_COMPLETE ) && p ) *p = pmctl->rcv.pmb->u.msg_data.pout_info_idx; @@ -877,8 +1385,8 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_pout_info_idx( MBG_MSG_CTL *pmctl, _MBG_API_ATTR int _MBG_API mbgextio_set_pout_settings_idx( MBG_MSG_CTL *pmctl, const POUT_SETTINGS *p, uint16_t idx ) { - MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; GPS_CMD cmd = GPS_POUT_SETTINGS_IDX; + MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; int rc; pmb->u.msg_data.pout_settings_idx.pout_settings = *p; @@ -886,9 +1394,15 @@ _MBG_API_ATTR int _MBG_API mbgextio_set_pout_settings_idx( MBG_MSG_CTL *pmctl, pmb->hdr.len = sizeof( pmb->u.msg_data.pout_settings_idx ); pmb->hdr.cmd = cmd | GPS_REQACK; - xmt_tbuff( pmctl ); + rc = xmt_tbuff( pmctl ); + +#if _MBGEXTIO_DIRECT_RC + + return rc; - rc = mbgextio_get_data( pmctl, cmd ); +#else + + rc = mbgextio_rcv_msg( pmctl, cmd ); if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) { @@ -897,9 +1411,78 @@ _MBG_API_ATTR int _MBG_API mbgextio_set_pout_settings_idx( MBG_MSG_CTL *pmctl, // transmitted before, an automatic frame (current time, capture) // has been sent before the acknowledge code. } - + return 0; +#endif + } // mbgextio_set_pout_settings_idx + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_clr_ucap_buff( MBG_MSG_CTL *pmctl ) +{ + return mbgextio_xmt_cmd( pmctl, GPS_CLR_UCAP_BUFF ); + +} // mbgextio_clr_ucap_buff + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_get_time_scale_info( MBG_MSG_CTL *pmctl, + MBG_TIME_SCALE_INFO *p ) +{ + int rc; + + xmt_cmd( pmctl, GPS_TIME_SCALE ); + + rc = mbgextio_rcv_msg( pmctl, GPS_TIME_SCALE ); + + if ( ( rc == TR_COMPLETE ) && p ) + *p = pmctl->rcv.pmb->u.msg_data.time_scale_info; + + return rc; + +} // mbgextio_get_time_scale_info + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgextio_set_time_scale_settings( MBG_MSG_CTL *pmctl, + const MBG_TIME_SCALE_SETTINGS *p ) +{ + GPS_CMD cmd = GPS_TIME_SCALE; + +#if _MBGEXTIO_DIRECT_RC + + return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) ); + +#else + + MBG_MSG_BUFF *pmb = pmctl->xmt.pmb; + int rc; + + pmb->u.msg_data.time_scale_settings = *p; + + pmb->hdr.len = sizeof( pmb->u.msg_data.time_scale_settings ); + pmb->hdr.cmd = cmd | GPS_REQACK; + xmt_tbuff( pmctl ); + + rc = mbgextio_rcv_msg( pmctl, cmd ); + + if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) ) + { + return -1; // no ack packet received + // data has not been set or, if GPS_AUTO_ON has been + // transmitted before, an automatic frame (current time, capture) + // has been sent before the acknowledge code. + } + + return 0; + +#endif + +} // mbgextio_set_time_scale_settings + + diff --git a/mbglib/common/mbgextio.h b/mbglib/common/mbgextio.h index 98262e7..dca0454 100644 --- a/mbglib/common/mbgextio.h +++ b/mbglib/common/mbgextio.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgextio.h 1.1 2006/08/24 12:40:37 martin REL_M $ + * $Id: mbgextio.h 1.7 2009/10/02 14:21:08 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,21 @@ * * ----------------------------------------------------------------------- * $Log: mbgextio.h $ + * 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. + * Revision 1.5 2009/03/10 17:03:09Z martin + * Updated function prototypes. + * Revision 1.4 2008/09/04 14:13:19Z martin + * Added macro _mbgextio_xmt_msg(). + * Updated function prototypes. + * Removed obsolete code. + * Revision 1.3 2007/02/27 10:30:06Z martin + * Added some global variables. + * Updated function prototypes. + * Revision 1.2 2006/12/21 10:56:35 martin + * Updated function prototypes. * Revision 1.1 2006/08/24 12:40:37 martin * Initial revision. * @@ -24,11 +39,6 @@ #include <gpsserio.h> #include <time.h> -#if defined( MBG_TGT_WIN32 ) - #include <windows.h> -#endif - - #ifdef _MBGEXTIO #define _ext #define _DO_INIT @@ -60,6 +70,25 @@ #endif +_ext uint32_t mbg_baud_rates[N_MBG_BAUD_RATES] +#ifdef _DO_INIT + = MBG_BAUD_RATES +#endif +; + +_ext const char *mbg_baud_rate_strs[N_MBG_BAUD_RATES] +#ifdef _DO_INIT + = MBG_BAUD_STRS +#endif +; + +_ext const char *mbg_framing_strs[N_MBG_FRAMINGS] +#ifdef _DO_INIT + = MBG_FRAMING_STRS +#endif +; + + /* function prototypes: */ @@ -75,19 +104,54 @@ extern "C" { _MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl, const char *host, const char *passwd ) ; _MBG_API_ATTR int _MBG_API mbgextio_open_serial( MBG_MSG_CTL *pmctl, const char *dev, uint32_t baud_rate, const char *framing ) ; _MBG_API_ATTR void _MBG_API mbgextio_close_connection( MBG_MSG_CTL *pmctl ) ; + _MBG_API_ATTR int _MBG_API mbgextio_force_connection( const char *dev ) ; + _MBG_API_ATTR void _MBG_API mbgextio_set_char_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) ; + _MBG_API_ATTR ulong _MBG_API mbgextio_get_char_rcv_timeout( const MBG_MSG_CTL *pmctl ) ; + _MBG_API_ATTR void _MBG_API mbgextio_set_msg_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout ) ; + _MBG_API_ATTR ulong _MBG_API mbgextio_get_msg_rcv_timeout( const MBG_MSG_CTL *pmctl ) ; + _MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd, const void *p, int n_bytes ) ; + _MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) ; _MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) ; + _MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t us ) ; _MBG_API_ATTR int _MBG_API mbgextio_req_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd ) ; + _MBG_API_ATTR int _MBG_API mbgextio_req_data_idx( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t idx ) ; _MBG_API_ATTR int _MBG_API mbgextio_get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) ; _MBG_API_ATTR int _MBG_API mbgextio_get_sw_rev( MBG_MSG_CTL *pmctl, SW_REV *p ) ; _MBG_API_ATTR int _MBG_API mbgextio_get_bvar_stat( MBG_MSG_CTL *pmctl, BVAR_STAT *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_time( MBG_MSG_CTL *pmctl, TTM *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_time( MBG_MSG_CTL *pmctl, const TTM *p ) ; _MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl, LLA lla ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_pos_lla( MBG_MSG_CTL *pmctl, const LLA lla ) ; _MBG_API_ATTR int _MBG_API mbgextio_get_tzdl( MBG_MSG_CTL *pmctl, TZDL *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_tzdl( MBG_MSG_CTL *pmctl, const TZDL *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_port_parm( MBG_MSG_CTL *pmctl, PORT_PARM *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_port_parm( MBG_MSG_CTL *pmctl, const PORT_PARM *p ) ; _MBG_API_ATTR int _MBG_API mbgextio_get_synth( MBG_MSG_CTL *pmctl, SYNTH *p ) ; _MBG_API_ATTR int _MBG_API mbgextio_set_synth( MBG_MSG_CTL *pmctl, const SYNTH *p ) ; - _MBG_API_ATTR int _MBG_API mbgextio_get_port_parm( MBG_MSG_CTL *pmctl, PORT_PARM *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_ant_info( MBG_MSG_CTL *pmctl, ANT_INFO *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, TTM *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_enable_flags( MBG_MSG_CTL *pmctl, ENABLE_FLAGS *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_enable_flags( MBG_MSG_CTL *pmctl, const ENABLE_FLAGS *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_stat_info( MBG_MSG_CTL *pmctl, STAT_INFO *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_ant_cable_len( MBG_MSG_CTL *pmctl, ANT_CABLE_LEN *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_ant_cable_len( MBG_MSG_CTL *pmctl, const ANT_CABLE_LEN *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_irig_tx_info( MBG_MSG_CTL *pmctl, IRIG_INFO *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_irig_tx_settings( MBG_MSG_CTL *pmctl, const IRIG_SETTINGS *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_irig_rx_info( MBG_MSG_CTL *pmctl, IRIG_INFO *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_irig_rx_settings( MBG_MSG_CTL *pmctl, const IRIG_SETTINGS *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_ref_offs( MBG_MSG_CTL *pmctl, MBG_REF_OFFS *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_ref_offs( MBG_MSG_CTL *pmctl, const MBG_REF_OFFS *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_debug_status( MBG_MSG_CTL *pmctl, MBG_DEBUG_STATUS *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_opt_info( MBG_MSG_CTL *pmctl, MBG_OPT_INFO *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_opt_settings( MBG_MSG_CTL *pmctl, const MBG_OPT_SETTINGS *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_str_type_info_idx( MBG_MSG_CTL *pmctl, STR_TYPE_INFO_IDX *p, uint16_t idx ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_port_info_idx( MBG_MSG_CTL *pmctl, PORT_INFO_IDX *p, uint16_t idx ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_port_settings_idx( MBG_MSG_CTL *pmctl, const PORT_SETTINGS *p, uint16_t idx ) ; _MBG_API_ATTR int _MBG_API mbgextio_get_pout_info_idx( MBG_MSG_CTL *pmctl, POUT_INFO_IDX *p, uint16_t idx ) ; _MBG_API_ATTR int _MBG_API mbgextio_set_pout_settings_idx( MBG_MSG_CTL *pmctl, const POUT_SETTINGS *p, uint16_t idx ) ; + _MBG_API_ATTR int _MBG_API mbgextio_clr_ucap_buff( MBG_MSG_CTL *pmctl ) ; + _MBG_API_ATTR int _MBG_API mbgextio_get_time_scale_info( MBG_MSG_CTL *pmctl, MBG_TIME_SCALE_INFO *p ) ; + _MBG_API_ATTR int _MBG_API mbgextio_set_time_scale_settings( MBG_MSG_CTL *pmctl, const MBG_TIME_SCALE_SETTINGS *p ) ; /* ----- function prototypes end ----- */ @@ -95,6 +159,8 @@ extern "C" { } #endif +#define _mbgextio_xmt_msg( _pmctl, _cmd, _s ) \ + mbgextio_xmt_msg( _pmctl, _cmd, _s, sizeof( *(_s) ) ) /* End of header body */ diff --git a/mbglib/common/mbggeo.h b/mbglib/common/mbggeo.h index 27bc698..c375570 100644 --- a/mbglib/common/mbggeo.h +++ b/mbglib/common/mbggeo.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbggeo.h 1.8 2004/11/09 14:16:00 martin REL_M $ + * $Id: mbggeo.h 1.10 2008/09/03 14:54:28 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -22,7 +22,12 @@ * * ----------------------------------------------------------------------- * $Log: mbggeo.h $ - * Revision 1.8 2004/11/09 14:16:00 martin + * Revision 1.10 2008/09/03 14:54:28 martin + * Added macros to swap endianess of structures. + * Revision 1.9 2008/01/17 09:31:33 daniel + * Made comments compatible for doxygen parser. + * No sourcecode changes. + * Revision 1.8 2004/11/09 14:16:00Z martin * Redefined interface data types using C99 fixed-size definitions. * Revision 1.7 2003/02/14 13:23:04Z martin * Omit inclusion of mystd.h. @@ -62,28 +67,47 @@ #endif -/* geographic longitude or latitude in [degrees, minutes, seconds] */ -/* longitude East latitude North and positve, South or West angles negative */ - +/** + Geographic longitude or latitude in [degrees, minutes, seconds] + longitude East latitude North and positve, South or West angles negative + */ typedef struct { - uint16_t prefix; /* 'N', 'E', 'S' or 'W' */ - uint16_t deg; /* [0...90 (lat) or 0...180 (lon)] */ - uint16_t min; /* [0...59] */ - double sec; /* [0...59.999] */ + uint16_t prefix; /**< 'N', 'E', 'S' or 'W' */ + uint16_t deg; /**< [0...90 (lat) or 0...180 (lon)] */ + uint16_t min; /**< [0...59] */ + double sec; /**< [0...59.999] */ } DMS; +// The corresponding macro _mbg_swab_dms() is defined in gpsdefs.h. +#define _mbg_swab_dms( _p ) \ +{ \ + _mbg_swab16( &(_p)->prefix ); \ + _mbg_swab16( &(_p)->deg ); \ + _mbg_swab16( &(_p)->min ); \ + _mbg_swab_double( &(_p)->sec ); \ +} + typedef struct { - XYZ xyz; /* always WGS84 ECEF coordinates */ - LLA lla; /* depending on the ellipsoid used for reference */ - DMS longitude; /* longitude in degrees, minutes, seconds */ - DMS latitude; /* latitude in degrees, minutes, seconds */ - int16_t ellipsoid; /* ellipsoid used for reference */ + XYZ xyz; /**< always WGS84 ECEF coordinates */ + LLA lla; /**< depending on the ellipsoid used for reference */ + DMS longitude; /**< longitude in degrees, minutes, seconds */ + DMS latitude; /**< latitude in degrees, minutes, seconds */ + int16_t ellipsoid; /**< ellipsoid used for reference */ } POS; +#define _mbg_swab_pos( _p ) \ +{ \ + _mbg_swab_xyz( (_p)->xyz ); \ + _mbg_swab_lla( (_p)->lla ); \ + _mbg_swab_dms( &(_p)->longitude ); \ + _mbg_swab_dms( &(_p)->latitude ); \ + _mbg_swab16( &(_p)->ellipsoid ); \ +} + typedef struct diff --git a/mbglib/common/mbgserio.c b/mbglib/common/mbgserio.c new file mode 100644 index 0000000..23005b7 --- /dev/null +++ b/mbglib/common/mbgserio.c @@ -0,0 +1,960 @@ + +/************************************************************************** + * + * $Id: mbgserio.c 1.3 2009/09/01 10:49:30 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:30 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..2367e14 --- /dev/null +++ b/mbglib/common/mbgserio.h @@ -0,0 +1,213 @@ + +/************************************************************************** + * + * $Id: mbgserio.h 1.4 2009/09/01 10:54:29 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:29 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..dde928b --- /dev/null +++ b/mbglib/common/pcpsdefs.h @@ -0,0 +1,1222 @@ + +/************************************************************************** + * + * $Id: pcpsdefs.h 1.41 2009/06/19 12:16:42 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * General definitions for Meinberg plug-in radio clocks + * + * ----------------------------------------------------------------------- + * $Log: pcpsdefs.h $ + * Revision 1.41 2009/06/19 12:16:42 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) */ + 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_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 \ +} + + +#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 } \ +} + + + +/** + 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_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_PTP270PEX ( ( PCPS_REF_PTP << 8 ) | 0x01 ) + +#define PCI_DEV_FRC511PEX ( ( PCPS_REF_FRC << 8 ) | 0x01 ) + +/** @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 ) + +// 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 ) + + +#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 */ + uint8_t status; /**< status codes, see below */ + char corr_dir; /**< space, '<', or '>' */ + uint8_t flags; /**< reserved, currently always 0 */ +} CORR_INFO; + +/** Codes used with CORR_INFO::status: */ +enum +{ + PZF_CORR_RAW, + PZF_CORR_CHECK, + PZF_CORR_FINE, + N_PZF_CORR_STATE +}; + + +/** + * The enumeration below defines the various types of data that can be + * read from or written to a Meinberg GPS plug-in clock. Access should be + * done using the functions pcps_read_gps_data() and pcps_write_gps_data() + * in file pcpsio.c because the size of some of the structures exceeds + * the size of the clock's on-board FIFO 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/words.h b/mbglib/common/words.h index 94cfbea..9f6f1a9 100644 --- a/mbglib/common/words.h +++ b/mbglib/common/words.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: words.h 1.11 2004/11/10 10:45:34 martin REL_M $ + * $Id: words.h 1.21 2009/10/01 14:00:17 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,31 @@ * * ----------------------------------------------------------------------- * $Log: words.h $ + * Revision 1.21 2009/10/01 14:00:17 martin + * Conditionally define ulong and friends also for Linux/glibc. + * Revision 1.20 2009/07/02 15:38:12 martin + * Added new macro _wswap32(). + * Revision 1.19 2009/04/14 14:45:45Z martin + * Added BYTE_OF_P() and WORD_OF_P() macros. + * Revision 1.18 2009/03/27 14:05:18 martin + * Cleanup for CVI. + * Revision 1.17 2009/03/13 09:06:03Z martin + * Declared bit type for non-firmware environments. + * Revision 1.16 2008/12/05 12:05:41Z martin + * Define dummy int64_t/uint64_t types for targets + * which don't support 64 bit data types. + * Revision 1.15 2008/07/14 14:44:00Z martin + * Use fixed size C99 types which come with GCC and newer Borland compilers. + * Revision 1.14 2008/01/30 10:27:50Z martin + * Moved some macro definitions here. + * Revision 1.13 2007/03/08 15:00:30Z martin + * Fixed incompatibility of macro _IS_MBG_FIRMWARE. + * Added a workaround for _IS_MBG_FIRMWARE under CVI. + * Support for BSD. + * Revision 1.12 2006/12/15 10:45:46 martin + * Added macro _IS_MBG_FIRMWARE. + * Cleanup for Linux, QNX, and Watcom C. + * Include mbg_tgt.h for non-firmware targets. * Revision 1.11 2004/11/10 10:45:34 martin * Added C99 fixed-type handling for QNX. * Revision 1.10 2004/11/09 13:12:56 martin @@ -41,6 +66,27 @@ /* Other headers to be included */ + +#if !defined( _IS_MBG_FIRMWARE ) + +#if defined( _C166 ) || \ + defined( _CC51 ) || \ + defined( __ARM ) + #define _IS_MBG_FIRMWARE 1 +#else + #define _IS_MBG_FIRMWARE 0 +#endif + + +#endif + +#if !_IS_MBG_FIRMWARE + #include <mbg_tgt.h> + + typedef unsigned char bit; +#endif + + #ifdef _WORDS #define _ext #else @@ -50,37 +96,127 @@ /* Start of header body */ -// Depending on the target environment, configure whether -// C99 fixed-size types are supported, or not. -// If they are not defined, they have to be defined using -// standard data types of appropriate size. -#if defined( __linux ) // any Linux target +// Check whether the target system supports C99 fixed-size types. + +#if defined( MBG_TGT_LINUX ) // any Linux target #if defined( __KERNEL__ ) #include <linux/types.h> - #define _C99_BIT_TYPES_DEFINED 1 #else + #include <stdint.h> #include <sys/types.h> - #define _C99_PSEUDO_BIT_TYPES_DEFINED 1 #endif - -#elif defined( __QNX__ ) // target QNX 4 or QNX 6 - #if defined( __QNXNTO__ ) // target QNX 6 (Neutrino) + #define _C99_BIT_TYPES_DEFINED 1 + +#elif defined( MBG_TGT_BSD ) + + #include <sys/types.h> + + #define _C99_BIT_TYPES_DEFINED 1 + +#elif defined( MBG_TGT_QNX ) // QNX 4.x or QNX 6.x + + #if defined( MBG_TGT_QNX_NTO ) // QNX 6.x (Neutrino) with gcc #include <stdint.h> - #else // QNX 4.25 - #include <inttypes.h> + #else // QNX 4.x with Watcom C 10.6 + #include <sys/types.h> // 64 bit types not supported #endif - - #define _C99_BIT_TYPES_DEFINED 1 - + + #define _C99_BIT_TYPES_DEFINED 1 + #endif +// If it's not yet clear whether fixed-size types are supported, +// check the build environment which may be multi-platform. + +#if !defined( _C99_BIT_TYPES_DEFINED ) + + #if defined( __WATCOMC__ ) + #if __WATCOMC__ > 1230 // Open Watcom C 1.3 and above + #include <stdint.h> + #define _C99_BIT_TYPES_DEFINED 1 + #elif defined( __WATCOM_INT64__ ) // Watcom C 11, non-QNX + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + + #define _C99_BIT_TYPES_DEFINED 1 + #endif + #endif + + #if defined( __BORLANDC__ ) + #if ( __BORLANDC__ >= 0x570 ) // at least Borland Developer Studio 2006 + #define _C99_BIT_TYPES_DEFINED 1 + #endif + #endif + + #if defined( __GNUC__ ) + #include <stdint.h> + #define _C99_BIT_TYPES_DEFINED 1 + #endif + +#endif + + +// If neither the target system nor the build environment define C99 fixed-size +// types define those types based on standard types with the proper sizes +// commonly used in 16/32 bit environments. + +#if defined( _C99_BIT_TYPES_DEFINED ) + + #define MBG_TGT_HAS_64BIT_TYPES 1 + +#else + + typedef char int8_t; + typedef unsigned char uint8_t; + + typedef short int16_t; + typedef unsigned short uint16_t; + + typedef long int32_t; + typedef unsigned long uint32_t; + + + #if defined( MBG_TGT_WIN32 ) + + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + + #define MBG_TGT_HAS_64BIT_TYPES 1 + + #else + // The types below are required to avoid build errors + // if these types are formally used in function prototypes. + // We explicitely use abnormal data types to hopefully + // cause compiler errors in case these types are + // unexpectedly used to generate real code for a target + // platform which does not support 64 bit types. + typedef void *int64_t; + typedef void *uint64_t; + #endif + +#endif + + + +#if !defined( MBG_TGT_HAS_64BIT_TYPES ) + + #define MBG_TGT_HAS_64BIT_TYPES 0 + +#endif + + + +// Some commonly used types + typedef unsigned char uchar; -#if !defined( __linux ) +#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. typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; @@ -94,57 +230,43 @@ typedef unsigned long longword; typedef unsigned long dword; +#define HI_BYTE( _x ) ( (_x) >> 8 ) +#define LO_BYTE( _x ) ( (_x) & 0xFF ) -#if !defined( _C99_BIT_TYPES_DEFINED ) - #if defined( _C99_PSEUDO_BIT_TYPES_DEFINED ) - // While the C99 standard requires names like uint8_t for unsigned integer - // types with a fixed number of bits, some implementations define types - // like u_int8_t instead, but not the required names. This is fixed here. - // Normally, the signed types have been properly defined in this case. - typedef u_int8_t uint8_t; - typedef u_int16_t uint16_t; - typedef u_int32_t uint32_t; - typedef u_int64_t uint64_t; - #else - // The lines below define some C99 types based on standard types with - // the proper sizes commonly used in 16/32 bit environments. - // The 64 bit types have not yet been used. - typedef char int8_t; - typedef unsigned char uint8_t; - - typedef short int16_t; - typedef unsigned short uint16_t; - - typedef long int32_t; - typedef unsigned long uint32_t; - - #if defined( _WIN32 ) || defined( __WIN32__ ) - typedef __int64 int64_t; - #endif - - #if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) - typedef __int64 int64_t; - #endif +#define HI_WORD( _x ) ( (_x) >> 16 ) +#define LO_WORD( _x ) ( (_x) & 0xFFFF ) - #endif -#endif +// the macros below assume little endianess +// these macros expect the name of a variable +#define BYTE_OF( _v, _n ) *( ( (uint8_t *) &(_v) ) + (_n) ) +#define WORD_OF( _v, _n ) *( ( (uint16_t *) &(_v) ) + (_n) ) +// same as above, but taking pointers +#define BYTE_OF_P( _p, _n ) *( ( (uint8_t *) (_p) ) + (_n) ) +#define WORD_OF_P( _p, _n ) *( ( (uint16_t *) (_p) ) + (_n) ) // a macro to swap the byte order of a 16 bit value -#define _bswap16( _x ) \ -( \ - ( ( ( (ushort) (_x) ) & 0x00FF ) << 8 ) | \ - ( ( ( (ushort) (_x) ) & 0xFF00 ) >> 8 ) \ +#define _bswap16( _x ) \ +( \ + ( ( ( (uint16_t) (_x) ) & 0x00FF ) << 8 ) | \ + ( ( ( (uint16_t) (_x) ) & 0xFF00 ) >> 8 ) \ ) // a macro to swap the byte order of a 32 bit value -#define _bswap32( _x ) \ -( \ - ( ( ( (ulong) (_x) ) & 0x000000FFUL ) << 24 ) | \ - ( ( ( (ulong) (_x) ) & 0x0000FF00UL ) << 8 ) | \ - ( ( ( (ulong) (_x) ) & 0x00FF0000UL ) >> 8 ) | \ - ( ( ( (ulong) (_x) ) & 0xFF000000UL ) >> 24 ) \ +#define _bswap32( _x ) \ +( \ + ( ( ( (uint32_t) (_x) ) & 0x000000FFUL ) << 24 ) | \ + ( ( ( (uint32_t) (_x) ) & 0x0000FF00UL ) << 8 ) | \ + ( ( ( (uint32_t) (_x) ) & 0x00FF0000UL ) >> 8 ) | \ + ( ( ( (uint32_t) (_x) ) & 0xFF000000UL ) >> 24 ) \ +) + +// a macro to swap the word order of a 32 bit value +#define _wswap32( _x ) \ +( \ + ( ( ( (uint32_t) (_x) ) & 0x0000FFFFUL ) << 16 ) | \ + ( ( ( (uint32_t) (_x) ) >> 16 ) & 0x0000FFFFUL ) \ ) #define _var_bswap16( _v ) (_v) = _bswap16( _v ) @@ -157,7 +279,7 @@ typedef unsigned long dword; // little-endian, so we must use macros to adjust the // byte order if the C51 is used. -#if defined _CC51 +#if defined( _CC51 ) #define _hilo_16( _x ) _bswap16( _x ) #define _hilo_32( _x ) _bswap32( _x ) #else diff --git a/unix/Makefile b/unix/Makefile index e271567..9ceee12 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -1,7 +1,7 @@ ######################################################################### # -# $Id: Makefile 1.2 2006/08/22 15:49:27 martin REL_M $ +# $Id: Makefile 1.3 2009/10/01 14:09:19 martin REL_M $ # # Description: # Makefile for gpsxmple for Unix-like systems. @@ -9,6 +9,8 @@ # # ----------------------------------------------------------------------- # $Log: Makefile $ +# Revision 1.3 2009/10/01 14:09:19 martin +# Added mbgserio.c source module. # Revision 1.2 2006/08/22 15:49:27 martin # Moved this makefile for Unix-like systems to folder unix. # This build environment now supports Linux and QNX 6.x. @@ -57,23 +59,26 @@ else endif - SRCS=../$(TARGET).c \ $(MBGLIB_COMMON)/mbgextio.c \ + $(MBGLIB_COMMON)/mbgserio.c \ $(MBGLIB_COMMON)/gpsserio.c \ $(MBGLIB_COMMON)/gpsutils.c \ $(MBGLIB_COMMON)/aes128.c -all: $(TARGET) +.PHONY: all +all: $(TARGET) $(TARGET): $(SRCS) $(MAKEFILE_LIST) $(CC) $(CFLAGS) $(SRCS) -o $@ +.PHONY: clean clean: rm -f *.o *~ core rm -f $(TARGET) +.PHONY: distclean distclean: clean |