diff options
Diffstat (limited to 'gpsxmple.c')
-rw-r--r-- | gpsxmple.c | 813 |
1 files changed, 638 insertions, 175 deletions
@@ -1,14 +1,14 @@ /************************************************************************** * - * $Id: gpsxmple.c 1.8 2011/04/15 13:04:14 martin REL_M $ - * $Name: GPSXMPLE_2_3 $ + * $Id: gpsxmple.c 1.10.1.8 2015/07/25 15:28:12 martin TEST $ + * $Name: $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: * Sample program demonstrating how to access Meinberg devices - * using the binary data protocol. + * using the serial binary data protocol. * * Depending on the target operating system this program works * either via serial port (the default) or via a network socket @@ -32,6 +32,26 @@ * * ----------------------------------------------------------------------- * $Log: gpsxmple.c $ + * Revision 1.10.1.8 2015/07/25 15:28:12 martin + * Revision 1.10.1.7 2015/07/24 13:47:32Z martin + * Revision 1.10.1.6 2015/07/14 13:01:02 martin + * Revision 1.10.1.5 2014/11/04 11:32:25 martin + * Started to support XBP addressing. + * Revision 1.10.1.4 2014/10/30 13:49:38 martin + * Revision 1.10.1.3 2013/02/01 16:11:59 martin + * Revision 1.10.1.2 2012/03/13 16:27:44 martin + * Revision 1.10.1.1 2012/03/13 11:48:35Z martin + * Revision 1.10 2012/01/12 09:57:04 martin + * Support selection of SCU port. + * Preliminary code to send PCPS_TIME via binary protocol. + * Debug code to test TX flushing problems under Windows. + * GPSXMPLE code disabled by default to build mbgevlog. + * Revision 1.9 2011/12/15 14:35:49Z martin + * Started to migrate to opaque stuctures. + * Made more functions static. + * Added code to show / clear GPS event log. + * Used this module for the mbgevlog program and disabled + * some GPSXMPLE code using preprocessor symbol. * Revision 1.8 2011/04/15 13:04:14 martin * Optionally poll for user capture events. * Under Unix catch signals to terminate properly. @@ -45,7 +65,7 @@ * Optionally loop and wait for automatic messages. * Revision 1.6 2006/10/25 12:31:54Z martin * Support serial I/O under Windows. - * Check return codes of API functions and print associated + * Check return codes of API functions and print associated * messages in case of error. * Revision 1.5 2006/08/24 13:36:38Z martin * Conditional support for network socket I/O. @@ -62,7 +82,9 @@ **************************************************************************/ #include <mbgextio.h> +#include <extiohlp.h> #include <gpsutils.h> +#include <pcpsdefs.h> #include <stdio.h> #include <stdlib.h> @@ -82,16 +104,13 @@ #endif +const char pname[] = "gpsxmple"; +const char pversion[] = "2.5"; +const char pdescr[] = "Example Program Accessing a Meinberg Device via Binary Protocol"; -// the variables below are required for communication -MBG_MSG_BUFF rbuff; -MBG_MSG_BUFF tbuff; -MBG_MSG_CTL mctl = -{ - { &rbuff, sizeof( rbuff ) }, - { &tbuff, sizeof( tbuff ) } -}; +// the variables below are required for communication +MBG_MSG_CTL *pmctlx; // Define the minimum number of some resource types @@ -101,9 +120,11 @@ MBG_MSG_CTL mctl = // Define the maximum number of some resource types // supported by the software #define N_COM_MAX 4 // max. number of COM ports -#define N_STR_TYPE_MAX 20 // max. number of string types +// #define N_STR_TYPE_MAX 20 // max. number of string types #define N_POUT_MAX 3 // max. number of programmable outputs +#define N_SCU_PORT 2 + #define IDLE_SLEEP_MS 200 @@ -124,8 +145,14 @@ MBG_MSG_CTL mctl = static const char *target; static int is_socket; static int must_force_connection; + +static const char *str_new_date; +static const char *str_new_time; + static int must_send_auto; static int must_poll_ucap; + +static int must_clear_event_log; static RECEIVER_INFO receiver_info; static const char *feature_names[] = DEFAULT_GPS_FEATURE_NAMES; @@ -144,6 +171,8 @@ static const char *default_target = DEFAULT_DEV_NAME; #if _USE_SOCKET_IO static const char *password; + static int scu_port; + static int must_set_scu_port; #endif @@ -155,6 +184,84 @@ static const char *dow_str[] = +#if defined( DEBUG ) + +static /*HDR*/ +void print_original_serial_settings( FILE *fp, SERIAL_IO_STATUS *p ) +{ + #if defined( MBG_TGT_WIN32 ) + DCB *dcb = &p->old_dcb; + COMMTIMEOUTS *tmo = &p->old_commtimeouts; + COMMPROP *prop = &p->comm_prop; + + fprintf( fp, "Comm Properties:\n" ); + fprintf( fp, " wPacketLength: %u\n", prop->wPacketLength ); + fprintf( fp, " wPacketVersion: %u\n", prop->wPacketVersion ); + fprintf( fp, " dwServiceMask: %u (%u)\n", prop->dwServiceMask, SP_SERIALCOMM ); + fprintf( fp, " dwReserved1: %u\n", prop->dwReserved1 ); + fprintf( fp, " dwMaxTxQueue: %u\n", prop->dwMaxTxQueue ); + fprintf( fp, " dwMaxRxQueue: %u\n", prop->dwMaxRxQueue ); + fprintf( fp, " dwMaxBaud: %u\n", prop->dwMaxBaud ); + fprintf( fp, " dwProvSubType: %u\n", prop->dwProvSubType ); + fprintf( fp, " dwProvCapabilities: %u\n", prop->dwProvCapabilities ); + fprintf( fp, " dwSettableParams: 0x%2X\n", prop->dwSettableParams ); + fprintf( fp, " dwSettableBaud: 0x%2X\n", prop->dwSettableBaud ); + fprintf( fp, " wSettableData: 0x%2X\n", prop->wSettableData ); + fprintf( fp, " wSettableStopParity: 0x%2X\n", prop->wSettableStopParity ); + fprintf( fp, " dwCurrentTxQueue: %u\n", prop->dwCurrentTxQueue ); + fprintf( fp, " dwCurrentRxQueue: %u\n", prop->dwCurrentRxQueue ); + fprintf( fp, " dwProvSpec1: %u\n", prop->dwProvSpec1 ); + fprintf( fp, " dwProvSpec2: %u\n", prop->dwProvSpec2 ); + // fprintf( fp, " wcProvChar: %c\n", prop->wcProvChar[0] ); // wchar!! + fprintf( fp, "\n" ); + + fprintf( fp, "Original serial DCB settings:\n" ); + fprintf( fp, " DCBlength: %u\n", dcb->DCBlength ); + fprintf( fp, " BaudRate: %u\n", dcb->BaudRate ); + fprintf( fp, " fBinary: %u\n", dcb->fBinary ); + fprintf( fp, " fParity: %u\n", dcb->fParity ); + fprintf( fp, " fOutxCtsFlow: %u\n", dcb->fOutxCtsFlow ); + fprintf( fp, " fOutxDsrFlow: %u\n", dcb->fOutxDsrFlow ); + fprintf( fp, " fDtrControl: %u\n", dcb->fDtrControl ); + fprintf( fp, " fDsrSensitivity: %u\n", dcb->fDsrSensitivity ); + fprintf( fp, " fTXContinueOnXoff: %u\n", dcb->fTXContinueOnXoff ); + fprintf( fp, " fOutX: %u\n", dcb->fOutX ); + fprintf( fp, " fInX: %u\n", dcb->fInX ); + fprintf( fp, " fErrorChar: %u\n", dcb->fErrorChar ); + fprintf( fp, " fNull: %u\n", dcb->fNull ); + fprintf( fp, " fRtsControl: %u\n", dcb->fRtsControl ); + fprintf( fp, " fAbortOnError: %u\n", dcb->fAbortOnError ); + fprintf( fp, " fDummy2: %u\n", dcb->fDummy2 ); + fprintf( fp, " wReserved: %u\n", dcb->wReserved ); + fprintf( fp, " XonLim: %u\n", dcb->XonLim ); + fprintf( fp, " XoffLim: %u\n", dcb->XoffLim ); + fprintf( fp, " ByteSize: %u\n", dcb->ByteSize ); + fprintf( fp, " Parity: %u\n", dcb->Parity ); + fprintf( fp, " StopBits: %u\n", dcb->StopBits ); + fprintf( fp, " XonChar: %u\n", dcb->XonChar ); + fprintf( fp, " XoffChar: %u\n", dcb->XoffChar ); + fprintf( fp, " ErrorChar: %u\n", dcb->ErrorChar ); + fprintf( fp, " EofChar: %u\n", dcb->EofChar ); + fprintf( fp, " EvtChar: %u\n", dcb->EvtChar ); + fprintf( fp, " wReserved1: %u\n", dcb->wReserved1 ); + fprintf( fp, "\n" ); + + fprintf( fp, "Original serial comm timeout settings:\n" ); + fprintf( fp, " ReadIntervalTimeout: %u\n", tmo->ReadIntervalTimeout ); + fprintf( fp, " ReadTotalTimeoutMultiplier: %u\n", tmo->ReadTotalTimeoutMultiplier ); + fprintf( fp, " ReadTotalTimeoutConstant: %u\n", tmo->ReadTotalTimeoutConstant ); + fprintf( fp, " WriteTotalTimeoutMultiplier: %u\n", tmo->WriteTotalTimeoutMultiplier ); + fprintf( fp, " WriteTotalTimeoutConstant: %u\n", tmo->WriteTotalTimeoutConstant ); + fprintf( fp, "\n" ); + + #endif + +} // print_original_serial_settings + +#endif // defined( DEBUG ) + + + static /*HDR*/ void mbg_sleep_msec( long msec ) { @@ -163,7 +270,7 @@ void mbg_sleep_msec( long msec ) #elif defined( MBG_TGT_WIN32 ) Sleep( msec ); #elif defined( MBG_TGT_DOS ) - delay( msec ); + delay( (unsigned int) msec ); #endif } // mbg_sleep_msec @@ -171,6 +278,28 @@ void mbg_sleep_msec( long msec ) static /*HDR*/ +int set_scu_port( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, int port ) +{ + // Yet this is preliminary/untested. + SCU_STAT_SETTINGS scu_stat_settings = { 0 }; + int rc; + + scu_stat_settings.epld_control_mask = MSK_EPLD_CNTL_ENA_SNMP | MSK_EPLD_CNTL_SEL_SNMP; + + scu_stat_settings.epld_control_value = MSK_EPLD_CNTL_ENA_SNMP; + + if ( port ) // else leave 0 + scu_stat_settings.epld_control_value |= MSK_EPLD_CNTL_SEL_SNMP; + + rc = mbgextio_xmt_msg( pmctl, p_addr, GPS_SCU_STAT, &scu_stat_settings, sizeof( scu_stat_settings ) ); + + return rc; + +} // set_scu_port + + + +static /*HDR*/ int check_rc( int rc ) { const char *cp = NULL; @@ -180,43 +309,31 @@ int check_rc( int rc ) switch ( rc ) { - case TR_COMPLETE: + case MBG_SUCCESS: cp = "Data received completely."; break; - case TR_RECEIVING: - cp = "Received data not complete."; - break; - - case TR_WAITING: - cp = "Waiting for data."; - break; - - case TR_TIMEOUT: + case MBG_ERR_TIMEOUT: cp = "Timeout receiving data"; break; - case TR_CSUM_HDR: + case MBG_ERR_HDR_CSUM: cp = "Header checksum error in received data."; break; - case TR_CSUM_DATA: + case MBG_ERR_DATA_CSUM: cp = "Data checksum error in received data."; break; - case TR_DECRYPTION: + case MBG_ERR_DECRYPT: cp = "Failed to decrypt received data."; break; - case TR_OPEN_ERR: - cp = "Failed to establish connection."; - break; - - case TR_IO_ERR: + case MBG_ERR_IO: cp = "I/O error receiving data"; break; - case TR_AUTH_ERR: + case MBG_ERR_AUTH: cp = "Authentication error"; break; @@ -233,7 +350,7 @@ int check_rc( int rc ) -/*HDR*/ +static /*HDR*/ void sprint_tm( char *s, TM_GPS *tm, int print_frac ) { int n = 0; @@ -258,7 +375,7 @@ void sprint_tm( char *s, TM_GPS *tm, int print_frac ) -/*HDR*/ +static /*HDR*/ void sprint_lla( char *s, LLA lla ) { static const double r2d = 180 / PI; @@ -273,7 +390,7 @@ void sprint_lla( char *s, LLA lla ) -/*HDR*/ +static /*HDR*/ void print_stat_info( STAT_INFO *p ) { const char *cp; @@ -304,7 +421,7 @@ void print_stat_info( STAT_INFO *p ) -/*HDR*/ +static /*HDR*/ void print_time( TTM *p ) { static const char *s[] = @@ -333,7 +450,7 @@ void check_receiver_info( RECEIVER_INFO *p, int log ) const char *fmt_min = "Number of %s from device (%u) is less than number required (%u)"; const char *fmt_max = "Number of %s from device (%u) exceeds number supported by the software (%u)"; - // Check if numbers of resources provided by the device + // Check if numbers of resources provided by the device // don't exceed numbers of resources supported by the software #define _check_min( _n, _min, _info ) \ @@ -373,15 +490,15 @@ void check_receiver_info( RECEIVER_INFO *p, int log ) _check_min( p->n_com_ports, N_COM_MIN, "COM ports" ); _check_max( p->n_com_ports, N_COM_MAX, "COM ports" ); - _check_max( p->n_str_type, N_STR_TYPE_MAX, "string types" ); + _check_max( p->n_str_type, MAX_PARM_PORT, "string types" ); _check_max( p->n_prg_out, N_POUT_MAX, "progr. outputs" ); } // check_receiver_info -/*HDR*/ -int get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) +static /*HDR*/ +int get_receiver_info( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, RECEIVER_INFO *p ) { int rc; int i; @@ -389,13 +506,13 @@ int get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) printf( fmt, "Receiver info:" ); - rc = mbgextio_get_receiver_info( &mctl, p ); + rc = mbgextio_setup_receiver_info( pmctl, p_addr, p ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); - if ( rc == TR_TIMEOUT ) + if ( rc == MBG_ERR_TIMEOUT ) { printf( "If you are using a very old GPS model then reading the\n" "receiver info structure may not be supported.\n" ); @@ -457,17 +574,17 @@ int get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p ) -/*HDR*/ -void show_sw_rev( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_sw_rev( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { SW_REV sw_rev; int rc; printf( fmt, "Software Revision:" ); - rc = mbgextio_get_sw_rev( pmctl, &sw_rev ); + rc = mbgextio_get_sw_rev( pmctl, p_addr, &sw_rev ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -483,17 +600,17 @@ void show_sw_rev( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void show_bvar_stat( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_bvar_stat( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { BVAR_STAT bvar_stat; int rc; printf( fmt, "BVAR status:" ); - rc = mbgextio_get_bvar_stat( pmctl, &bvar_stat ); + rc = mbgextio_get_bvar_stat( pmctl, p_addr, &bvar_stat ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -505,17 +622,17 @@ void show_bvar_stat( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void show_stat_info( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_stat_info( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { STAT_INFO stat_info; int rc; printf( fmt, "Receiver status:" ); - rc = mbgextio_get_stat_info( pmctl, &stat_info ); + rc = mbgextio_get_stat_info( pmctl, p_addr, &stat_info ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -527,17 +644,17 @@ void show_stat_info( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void show_pos( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_pos( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { LLA lla; // Position as logitude, latitude, altitude int rc; printf( fmt, "Receiver Position:" ); - rc = mbgextio_get_pos_lla( pmctl, lla ); + rc = mbgextio_get_pos_lla( pmctl, p_addr, lla ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -550,17 +667,17 @@ void show_pos( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void show_tzdl( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_tzdl( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { TZDL tzdl; int rc; printf( fmt, "Time Zone:" ); - rc = mbgextio_get_tzdl( pmctl, &tzdl ); + rc = mbgextio_get_tzdl( pmctl, p_addr, &tzdl ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -603,8 +720,8 @@ void show_tzdl( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void show_synth( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_synth( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { SYNTH synth; double f; @@ -612,9 +729,9 @@ void show_synth( MBG_MSG_CTL *pmctl ) printf( fmt, "Synthesizer:" ); - rc = mbgextio_get_synth( pmctl, &synth ); + rc = mbgextio_get_synth( pmctl, p_addr, &synth ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -629,7 +746,7 @@ void show_synth( MBG_MSG_CTL *pmctl ) if ( synth.range == 0 ) { - // freq field is in 0.1 Hz units, so if + // freq field is in 0.1 Hz units, so if // the range is 0 we must divide by 10 // to yield the correct result f = (double) synth.freq / 10.0; @@ -656,8 +773,8 @@ void show_synth( MBG_MSG_CTL *pmctl ) -/*HDR*/ -void set_synth( void ) +static /*HDR*/ +void set_synth( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { SYNTH synth = { 0 }; int rc; @@ -673,10 +790,10 @@ void set_synth( void ) // The effective frequency is: (freq/10)*(10^^range) synth.freq = 1000; // base frequency value in 1/10 Hz Units - synth.range = 1; // multiplier 10^^range + synth.range = 1; // multiplier 10^^range synth.phase = 1800; // phase in 1/10 degrees - rc = mbgextio_set_synth( &mctl, &synth ); + rc = mbgextio_set_synth( pmctl, p_addr, &synth ); if ( rc < 0 ) printf( "Failed to set synthesizer output, code: %i\n", rc ); @@ -689,8 +806,8 @@ void set_synth( void ) // set programmable output mode -/*HDR*/ -void set_pout_mode( void ) +static /*HDR*/ +void set_pout_mode( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { POUT_INFO_IDX pout_info_idx; POUT_SETTINGS pout_settings = { 0 }; // new settings, init'd to 0 @@ -712,12 +829,12 @@ void set_pout_mode( void ) return; } - // OK, now get the current settings, and see which modes are + // OK, now get the current settings, and see which modes are // supported by the selected programmable pulse output. - rc = mbgextio_get_pout_info_idx( &mctl, &pout_info_idx, pout_idx ); + rc = mbgextio_get_pout_info_idx( pmctl, p_addr, &pout_info_idx, pout_idx ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -740,9 +857,9 @@ void set_pout_mode( void ) pout_settings.tm[0].on.t.hour = 0; pout_settings.tm[0].on.t.min = 20; pout_settings.tm[0].on.t.sec = 0; - pout_settings.pulse_len = 30; // 10 millisecond units +// pout_settings.pulse_len = 30; // 10 millisecond units - rc = mbgextio_set_pout_settings_idx( &mctl, &pout_settings, pout_idx ); + rc = mbgextio_set_pout_settings_idx( pmctl, p_addr, &pout_settings, pout_idx ); if ( rc < 0 ) printf( "Failed to set programmable pulse output mode, code: %i\n", rc ); @@ -753,7 +870,9 @@ void set_pout_mode( void ) -/*HDR*/ +#if 0 //##++++++++++++++++ + +static /*HDR*/ void show_port_parm( MBG_MSG_CTL *pmctl ) { PORT_PARM port_parm; @@ -763,7 +882,7 @@ void show_port_parm( MBG_MSG_CTL *pmctl ) rc = mbgextio_get_port_parm( pmctl, &port_parm ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); return; @@ -795,75 +914,45 @@ void show_port_parm( MBG_MSG_CTL *pmctl ) } /* show_port_parm */ +#endif + -/*HDR*/ -void show_port_settings( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_port_settings( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { const char *mode_names[N_STR_MODE] = DEFAULT_ENG_MODE_NAMES; - STR_TYPE_INFO sti[N_STR_TYPE_MAX]; - STR_TYPE_INFO_IDX stii; - PORT_INFO_IDX pii; - PORT_SETTINGS *p; + RECEIVER_PORT_CFG rpcfg; int rc; int i; printf( fmt, "Serial ports:" ); - if ( receiver_info.model_code == GPS_MODEL_UNKNOWN ) + rc = mbgextio_get_serial_settings( pmctl, p_addr, &rpcfg, &receiver_info ); + + if ( rc != MBG_SUCCESS ) { - // This may be an old GPS model which does not provide - // a receiver info structure. - show_port_parm( pmctl ); + check_rc( rc ); return; } + // The number of serial ports and time string formats supported // by this device is specified in the receiver info structure. - // Read time string information +#if 0 //##++ TODO: possibly print supported string types for ( i = 0; i < receiver_info.n_str_type; i++ ) { - rc = mbgextio_get_str_type_info_idx( pmctl, &stii, (uint16_t) i ); - - if ( rc != TR_COMPLETE ) - { - check_rc( rc ); - return; - } - - if ( stii.idx != i ) - { - printf( "** Info for string type %i requested, but for %i received.\n", - stii.idx, i ); - return; - } - sti[i] = stii.str_type_info; } +#endif - - // Read and print port settings + // print port settings for ( i = 0; ; ) { - rc = mbgextio_get_port_info_idx( pmctl, &pii, (uint16_t) i ); - - if ( rc != TR_COMPLETE ) - { - check_rc( rc ); - return; - } - - if ( pii.idx != i ) - { - printf( "** Info for port %i requested, but for %i received.\n", - pii.idx, i ); - return; - } - - p = &pii.port_info.port_settings; + PORT_SETTINGS *p = &rpcfg.pii[i].port_info.port_settings; printf( "COM%i: %5lu Baud, %s", i, @@ -874,13 +963,13 @@ void show_port_settings( MBG_MSG_CTL *pmctl ) // Make sure indices received from the device do not exceed // maximum numbers supported by this program. - if ( p->str_type >= N_STR_TYPE_MAX ) + if ( p->str_type >= MAX_PARM_STR_TYPE ) printf( " (string type exceeds max)" ); else if ( p->mode >= N_STR_MODE ) printf( " (string mode exceeds max)" ); else - printf( ", \"%s\" string %s", sti[p->str_type].long_name, mode_names[p->mode] ); + printf( ", \"%s\" string %s", rpcfg.stii[p->str_type].str_type_info.long_name, mode_names[p->mode] ); printf( "\n" ); @@ -894,8 +983,68 @@ void show_port_settings( MBG_MSG_CTL *pmctl ) +static /*HDR*/ +void show_event_log( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) +{ + static const char *evt_id_names[N_MBG_EVT_ID] = MBG_EVT_ID_NAMES_ENG; + + MBG_NUM_EVT_LOG_ENTRIES log_entries; + MBG_EVT_LOG_ENTRY evt_log_entry; + time_t t; + struct tm *mytime; + int n_evt = 0; + int event_id = -1; + + if ( mbgextio_get_num_evt_log_entries( pmctl, p_addr, &log_entries ) ) + printf( "\nEvent Log (%i/%i entries used):\n", log_entries.used, log_entries.max ); + else + { + printf( "Failed to read event log entries\n" ); + return; + } + + if ( mbgextio_get_first_evt_log_entry( pmctl, p_addr, &evt_log_entry ) ) + { + unsigned int i; + + for ( i = 0; i < log_entries.max; i++ ) + { + event_id = _mbg_get_evt_id( evt_log_entry.code ); + + if ( event_id == 0 ) + break; + + n_evt++; + + t = evt_log_entry.time; + mytime = gmtime( &t ); + + printf( "%04i-%02i-%02i %02i:%02i:%02i ", + mytime->tm_year + 1900, mytime->tm_mon + 1, mytime->tm_mday, + mytime->tm_hour, mytime->tm_min, mytime->tm_sec ); + + if ( event_id < N_MBG_EVT_ID ) + printf( "%s\n", evt_id_names[event_id] ); + else + printf( "Unknown event ID %u", event_id ); + + mbgextio_get_next_evt_log_entry( pmctl, p_addr, &evt_log_entry ); + } + } + else + fprintf( stderr, "** ERROR: failed to read event log\n" ); + + if ( n_evt == 0 ) + fprintf( stderr, "event log is empty\n" ); + + printf( "\n" ); + +} // show_event_log + + + /*HDR*/ static -int check_ucap_poll( void ) +int check_ucap_poll( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr ) { int rc; @@ -906,9 +1055,9 @@ int check_ucap_poll( void ) { TTM ttm; memset( &ttm, 0, sizeof( ttm ) ); - rc = mbgextio_get_ucap( &mctl, &ttm ); + rc = mbgextio_get_ucap( pmctl, p_addr, &ttm ); - if ( _ttm_time_is_avail( &ttm ) ) + if ( ( rc == MBG_SUCCESS ) && _ttm_time_is_avail( &ttm ) ) { printf( "CAP%i: %04u-%02u-%02u %02u:%02u:%02u.%07u", ttm.channel, ttm.tm.year, ttm.tm.month, ttm.tm.mday, @@ -931,10 +1080,219 @@ int check_ucap_poll( void ) +static /*HDR*/ +int set_date_time( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, + const char *str_new_date, const char *str_new_time ) +{ + PCPS_TIME_UNION u = { { 0 } }; + TTM ttm = { 0 }; + unsigned int year = 0; + unsigned int month = 0; + unsigned int mday = 0; + unsigned int hour = 0; + unsigned int min = 0; + unsigned int sec = 0; + unsigned int sec100 = 0; + int rc; + + // Either a date string, a time string, or both + // may have been passed to this function. + // If either of them is NULL read the current date/time + // as default values. + if ( str_new_date == NULL || str_new_time == NULL ) + { +#if 1 //##+++++++++++++ + return -1; +#else + rc = mbg_get_time( dh, &u.t ); + + if ( mbg_ioctl_err( rc, "mbg_get_time" ) ) + return rc; +#endif + } + + + if ( str_new_date ) + { + rc = sscanf( str_new_date, "%u-%u-%u", &year, &month, &mday ); + + if ( ( rc < 3 ) + || ( month < 1 ) || ( month > 12 ) + || ( mday < 1 ) || ( mday > 31 ) ) + { + printf( "** Invalid date: %04u-%02u-%02u\n", year, month, mday ); + return MBG_ERR_CFG; + } + } + + + if ( str_new_time ) + { + rc = sscanf( str_new_time, "%u:%u:%u.%u", &hour, &min, &sec, &sec100 ); + + if ( ( rc < 2 ) // at least hours and minutes are required + || ( hour > 23 ) + || ( min > 59 ) + || ( sec > 60 ) + || ( sec100 > 99 ) ) + { + printf( "** Invalid time: %02u:%02u:%02u.%02u\n", hour, min, sec, sec100 ); + return MBG_ERR_CFG; + } + } + +#if 0 //##++++++++++++++++ + // GPS and non-GPS cards require different API calls which use + // different structures to set the on-board date and time, + // so we have to distinguish. + + if ( _pcps_is_gps( p_dev ) ) // is a GPS card + { + ttm.channel = -1; + + if ( str_new_date ) // new date + { + ttm.tm.year = year; + ttm.tm.month = month; + ttm.tm.mday = mday; + } + else // copy current date as default + { + ttm.tm.year = u.t.year + 2000; + ttm.tm.month = u.t.month; + ttm.tm.mday = u.t.mday; + } + + if ( str_new_time ) // new time + { + ttm.tm.hour = hour; + ttm.tm.min = min; + ttm.tm.sec = sec; + ttm.tm.frac = sec100; + } + else // copy current time as default + { + ttm.tm.hour = u.t.hour; + ttm.tm.min = u.t.min; + ttm.tm.sec = u.t.sec; + ttm.tm.frac = u.t.sec100; + } + + ttm.tm.frac *= 100000; // fracs are in 100 ns units + + #if 0 + // Existing versions of the GPS cards just take + // TTM.tm as local time without accounting for + // the status flags, or UTC offset. + // Instead, the TTM::tm time is converted on-board + // to UTC depending on the local TZDL configuration. + // This works if the system time and the + ttm.tm.offs_from_utc = 7200; + ttm.tm.status |= TM_UTC | TM_LOCAL; + ttm.tm.status |= TM_DL_ENB; + #endif + + rc = mbg_set_gps_time( dh, &ttm ); + + if ( mbg_ioctl_err( rc, "mbg_set_gps_time" ) ) + return rc; + } + else // is not a GPS card + { + if ( str_new_date ) // new date + { + // determine the day-of-week for the given date + struct tm tm = { 0 }; + + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = mday; + tm.tm_hour = 12; + tm.tm_isdst = -1; + mktime( &tm ); + + u.stime.year = year % 100; + u.stime.month = month; + u.stime.mday = mday; + u.stime.wday = _wday_sun06_to_mon17( tm.tm_wday ); + } + + if ( str_new_time ) // new time + { + u.stime.hour = hour; + u.stime.min = min; + u.stime.sec = sec; + u.stime.sec100 = sec100; + } + + if ( u.stime.wday == 0 ) + u.stime.wday = 1; // dummy + + rc = mbg_set_time( dh, &u.stime ); + + if ( mbg_ioctl_err( rc, "mbg_set_time" ) ) + return rc; + } +#else + { + // + PCPS_TIME t = { 0 }; + + // determine the day-of-week for the given date + struct tm tm = { 0 }; + + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = mday; + tm.tm_hour = 12; + tm.tm_isdst = -1; + mktime( &tm ); + + t.year = year % 100; + t.month = month; + t.mday = mday; + t.wday = ( tm.tm_wday == 0 ) ? 7 : tm.tm_wday; + t.hour = hour; + t.min = min; + t.sec = sec; + t.sec100 = sec100; + +#if 0 //##+++++++++++++++++ + { + MBG_PORT_HANDLE port_handle = pmctl->st.serio.port_handle; + const char tmp[] = "\xFF\xFF\xFF\xFF"; + + // Note: encrypted msgs over serial are not yet supported. + + // _mbgserio_write( port_handle, &tmp, strlen( tmp ) ); + // _swab_pcps_time( &t ); + rc = mbgextio_xmt_msg( pmctl, PZF_PCPS_TIME, &t, sizeof( t ) ); + + // _mbgserio_write( port_handle, &tmp, strlen( tmp ) ); + } +#else + // _swab_pcps_time( &t ); + rc = mbgextio_xmt_msg( pmctl, p_addr, PZF_PCPS_TIME, &t, sizeof( t ) ); +#endif + + if ( rc < 0 ) + printf( "Failed to set date/time, rc: %i\n", rc ); + } + +#endif + printf( "\n\nDevice date/time have been set to %04u-%02u-%02u %02u:%02u:%02u.%02u\n\n", + year, month, mday, hour, min, sec, sec100 ); + + return MBG_SUCCESS; + +} // set_date_time + + + /*HDR*/ static void exit_close_connection( void ) { - mbgextio_close_connection( &mctl ); + mbgextio_close_connection( &pmctlx ); printf( "Connection closed.\n" ); printf( "\n" ); @@ -946,7 +1304,7 @@ void exit_close_connection( void ) /*HDR*/ static void exit_auto_off( void ) { - mbgextio_xmt_cmd( &mctl, GPS_AUTO_OFF ); + mbgextio_xmt_cmd( pmctlx, NULL, GPS_AUTO_OFF ); //##++++++ TODO: NULL? #if defined( DEBUG ) printf( "AUTO mode turned off.\n" ); @@ -957,9 +1315,9 @@ void exit_auto_off( void ) /*HDR*/ static -void set_auto_mode( void ) +void set_auto_mode( MBG_MSG_CTL *pmctl ) { - mbgextio_xmt_cmd( &mctl, GPS_AUTO_ON ); + mbgextio_xmt_cmd( pmctl, NULL, GPS_AUTO_ON ); //##++++++ TODO: NULL? #if defined( DEBUG ) printf( "AUTO mode turned on.\n" ); @@ -998,32 +1356,32 @@ int check_command_line( int argc, char *argv[] ) for ( i = 1; i < argc; i++ ) { - if ( strcmp( argv[i], "-a" ) == 0 ) + if ( strcmp( argv[i], "-a" ) == 0 ) { must_send_auto = 1; continue; } - if ( strcmp( argv[i], "-u" ) == 0 ) + if ( strcmp( argv[i], "-u" ) == 0 ) { must_poll_ucap = 1; continue; } - if ( strcmp( argv[i], "-?" ) == 0 ) + if ( strcmp( argv[i], "-?" ) == 0 ) { must_print_usage = 1; continue; } - if ( strcmp( argv[i], "-h" ) == 0 ) + if ( strcmp( argv[i], "-h" ) == 0 ) { must_print_usage = 1; continue; } #if _USE_SOCKET_IO - if ( strcmp( argv[i], "-n" ) == 0 ) + if ( strcmp( argv[i], "-n" ) == 0 ) { is_socket = 1; continue; @@ -1032,7 +1390,7 @@ int check_command_line( int argc, char *argv[] ) #if _USE_SOCKET_IO if ( strcmp( argv[i], "-p" ) == 0 ) - { + { if ( ++i < argc ) password = argv[i]; else @@ -1044,7 +1402,7 @@ int check_command_line( int argc, char *argv[] ) #if _USE_SERIAL_IO if ( strcmp( argv[i], "-b" ) == 0 ) - { + { if ( ++i < argc ) baudrate = strtoul( argv[i], NULL, 10 ); else @@ -1056,7 +1414,7 @@ int check_command_line( int argc, char *argv[] ) #if _USE_SERIAL_IO if ( strcmp( argv[i], "-f" ) == 0 ) - { + { if ( ++i < argc ) framing = argv[i]; else @@ -1074,6 +1432,52 @@ int check_command_line( int argc, char *argv[] ) } #endif + if ( strcmp( argv[i], "-c" ) == 0 ) + { + must_clear_event_log = 1; + continue; + } + + + #if _USE_SOCKET_IO + if ( strcmp( argv[i], "-P" ) == 0 ) + { + if ( ++i < argc ) + { + scu_port = atoi( argv[i] ); + + if ( ( scu_port >= 0 ) && ( scu_port < N_SCU_PORT ) ) + { + must_set_scu_port = 1; + continue; + } + } + + fprintf( stderr, "** invalid parameter for \"-P\"\n" ); + must_print_usage = 1; + continue; + } + #endif + + + if ( strcmp( argv[i], "-d" ) == 0 ) + { + if ( ++i < argc ) + str_new_date = argv[i]; + + continue; + } + + + if ( strcmp( argv[i], "-t" ) == 0 ) + { + if ( ++i < argc ) + str_new_time = argv[i]; + + continue; + } + + if ( argv[i][0] != '-' ) target = argv[i]; else @@ -1112,6 +1516,10 @@ int check_command_line( int argc, char *argv[] ) " -f xxx Serial port framing, default: %s\n" " -F Force serial connection to %lu/%s\n" #endif + " -c clear event log (if supported)\n" + #if _USE_SOCKET_IO + " -P scu_port Select clock at SCU port 0 or 1 (only with SCU over LAN)\n" + #endif "\n" "Example:\n" #if _USE_SERIAL_IO @@ -1148,9 +1556,10 @@ int check_command_line( int argc, char *argv[] ) int main( int argc, char *argv[] ) { + XBP_ADDR *p_addr = NULL; int rc; - printf( "\n\n\nExample Program Accessing a Meinberg Device via Binary Protocol\n" ); + fprintf( stderr, "\n\n\n%s v%s %s\n", pname, pversion, pdescr ); baudrate = default_baudrate; framing = default_framing; @@ -1166,16 +1575,12 @@ int main( int argc, char *argv[] ) #if _USE_SOCKET_IO if ( is_socket ) { - rc = mbgextio_open_socket( &mctl, target, password ); + rc = mbgextio_open_socket( target, &pmctlx, password ); - if ( rc < 0 ) + if ( rc != MBG_SUCCESS ) { - if ( rc == TR_OPEN_ERR ) - perror( "Error connecting" ); - else - fprintf( stderr, "mbgextio_open_socket returned %i", rc ); - - exit( 1 ); + printf( "Failed to connect to %s, rc: %i\n", target, rc ); + return 1; // Error ... } goto doit; @@ -1186,21 +1591,25 @@ int main( int argc, char *argv[] ) if ( must_force_connection ) { printf( "Trying to force connection to 19200/8N1 ..." ); - mbgextio_force_connection( target ); + mbgextio_force_conn_serial( target ); printf( "\n" ); baudrate = default_baudrate; framing = default_framing; } - rc = mbgextio_open_serial( &mctl, target, baudrate, framing ); + rc = mbgextio_open_serial( target, &pmctlx, baudrate, framing ); - if ( rc < 0 ) + if ( rc != MBG_SUCCESS ) { printf( "Error using port %s.\n", target ); - return -1; // Error ... + return 1; // Error ... } + #if defined( DEBUG ) + print_original_serial_settings( stdout, &pmctlx->st.serio ); + #endif + printf( " (Using %s with %li baud, %s)\n\n", target, (long) baudrate, framing ); @@ -1218,23 +1627,77 @@ doit: // now start communication with whichever device has been opened above: - get_receiver_info( &mctl, &receiver_info ); + // TODO: make sure xbp is supported. + mbgextio_setup_xbp_node_list( pmctlx, p_addr ); + + #if _USE_SOCKET_IO + if ( must_set_scu_port ) + { + int rc = set_scu_port( pmctlx, p_addr, scu_port ); + + if ( rc == MBG_SUCCESS ) + printf( "\nSCU switched to port %i (clock #%i)\n\n", + scu_port, scu_port + 1 ); + else + printf( "\nFailed to switch SCU to port %i (clock #%i)\n\n", + scu_port, scu_port + 1 ); + } + #endif + + if ( must_send_auto ) + set_auto_mode( pmctlx ); + + +#if 1 //##+++++++++++++ + get_receiver_info( pmctlx, p_addr, &receiver_info ); +#else + printf( "\n(Skipped getting receiver info)\n\n" ); +#endif + + if ( str_new_date && str_new_time ) + { + set_date_time( pmctlx, p_addr, str_new_date, str_new_time ); + return 0; + } + check_receiver_info( &receiver_info, 1 ); /* display system specific values */ - show_sw_rev( &mctl ); - show_bvar_stat( &mctl ); - show_stat_info( &mctl ); - show_pos( &mctl ); - show_tzdl( &mctl ); - show_port_settings( &mctl ); - show_synth( &mctl ); + show_sw_rev( pmctlx, p_addr ); + show_bvar_stat( pmctlx, p_addr ); + show_stat_info( pmctlx, p_addr ); + show_pos( pmctlx, p_addr ); + show_tzdl( pmctlx, p_addr ); + show_port_settings( pmctlx, p_addr ); + show_synth( pmctlx, p_addr ); + + if ( must_clear_event_log ) + { + if ( receiver_info.features & GPS_HAS_EVT_LOG ) + { + int ret = mbgextio_clr_evt_log( pmctlx, p_addr ); + + if ( ret != 0 ) + fprintf( stderr, "Failed to clear event log, rc: %i\n", ret ); + else + fprintf( stderr, "event log has been cleared\n" ); + } + else + fprintf( stderr, "This device does not support an event log\n" ); + } + + if ( receiver_info.features & GPS_HAS_EVT_LOG ) + show_event_log( pmctlx, p_addr ); + else + if ( !must_clear_event_log ) + printf( "** Warning: this device does not support an event log!\n" ); + // set_synth(); // set_pout_mode(); if ( must_poll_ucap ) - return check_ucap_poll(); + return check_ucap_poll( pmctlx, p_addr ); if ( !must_send_auto ) return 0; @@ -1245,10 +1708,10 @@ doit: // We will start to wait for automatically transmitted messages // which require a longer timeout than we have used by default // to wait for replies to dedicated request messages. - mbgextio_set_char_rcv_timeout( &mctl, 2000 ); // [msec] - mbgextio_set_msg_rcv_timeout( &mctl, 2000 ); // [msec] + mbgextio_set_char_rcv_timeout( pmctlx, 2000 ); // [msec] + mbgextio_set_msg_rcv_timeout( pmctlx, 2000 ); // [msec] - set_auto_mode(); + set_auto_mode( pmctlx ); do { @@ -1256,17 +1719,17 @@ doit: MSG_DATA *p; - rc = mbgextio_rcv_msg( &mctl, -1 ); + rc = mbgextio_rcv_msg( pmctlx, p_addr, -1 ); - if ( rc != TR_COMPLETE ) + if ( rc != MBG_SUCCESS ) { check_rc( rc ); break; } - mbgextio_xmt_cmd( &mctl, GPS_AUTO_ON ); + mbgextio_xmt_cmd( pmctlx, p_addr, GPS_AUTO_ON ); - pmb = mctl.rcv.pmb; + pmb = pmctlx->rcv.pmb; p = &pmb->u.msg_data; switch ( pmb->hdr.cmd ) @@ -1276,9 +1739,9 @@ doit: if ( p->ttm.channel == -1 ) { - mbgextio_xmt_cmd( &mctl, GPS_AUTO_ON ); - mbgextio_xmt_cmd( &mctl, GPS_STAT_INFO ); - mbgextio_xmt_cmd( &mctl, GPS_UCAP ); + mbgextio_xmt_cmd( pmctlx, p_addr, GPS_AUTO_ON ); + mbgextio_xmt_cmd( pmctlx, p_addr, GPS_STAT_INFO ); + mbgextio_xmt_cmd( pmctlx, p_addr, GPS_UCAP ); } break; |