diff options
author | Martin Burnicki <martin.burnicki@meinberg.de> | 2013-04-11 12:00:00 +0200 |
---|---|---|
committer | Martin Burnicki <martin.burnicki@meinberg.de> | 2013-04-11 12:00:00 +0200 |
commit | 912230275b4e315f35c6e6bb52746ae994a65919 (patch) | |
tree | c3bb9a38dcb705e6c55449d6360da76da18e1921 | |
download | mbgtools-win-912230275b4e315f35c6e6bb52746ae994a65919.tar.gz mbgtools-win-912230275b4e315f35c6e6bb52746ae994a65919.zip |
Initial version imported into git2013-04-11
Contains project files for VC6 only.
68 files changed, 30309 insertions, 0 deletions
diff --git a/mbgctrl/mbgctrl.c b/mbgctrl/mbgctrl.c new file mode 100644 index 0000000..edb6608 --- /dev/null +++ b/mbgctrl/mbgctrl.c @@ -0,0 +1,2460 @@ + +/************************************************************************** + * + * $Id: mbgctrl.c 1.22.1.14 2012/12/12 10:44:35Z martin TEST $ + * + * Description: + * Main file for mbgctrl program which sends commands and + * configuration parameters to a Meinberg device via IOCTL calls. + * + * ----------------------------------------------------------------------- + * $Log: mbgctrl.c $ + * Revision 1.22.1.14 2012/12/12 10:44:35Z martin + * Fixed wording of some message. + * Revision 1.22.1.13 2012/12/05 16:13:37 martin + * Chaged some faulty message texts. + * Revision 1.22.1.12 2012/10/16 10:44:20 martin + * Removed obsolete code. + * Revision 1.22.1.11 2012/07/12 08:37:47 martin + * Account for renamed structure. + * Revision 1.22.1.10 2012/06/01 18:46:21 martin + * Revision 1.22.1.9 2012/06/01 16:55:58 martin + * Account for library symbols moved to a new header. + * Revision 1.22.1.8 2011/09/26 15:58:58 martin + * Started modifications for PTP unicast master configuration. + * Warn if trying to handle serial port cfg but no serial port is supported. + * Modified program version handling. + * Use O_RDWR flag when opening a device. + * Account for modified library functions which can now + * optionally print the raw (hex) HR time stamp. + * Revision 1.22.1.7 2011/04/19 10:02:37 martin + * Syntax fix. + * Revision 1.22.1.6 2011/04/19 09:57:00 martin + * Untabbified and removed trailing spaces. + * Revision 1.22.1.5 2011/03/21 08:32:18 martin + * Fixed compiler warning. + * Revision 1.22.1.4 2011/03/03 10:01:00 daniel + * Support configuring PTP roles. + * Revision 1.22.1.3 2011/02/18 13:35:59 daniel + * Revision 1.22.1.2 2011/02/18 13:35:11 daniel + * Revision 1.22.1.1 2011/02/18 11:27:29 daniel + * Preliminary support for configuring PTP parameters incl. Unicast + * Bugfix: accept parameter keyword only when substring is found at the + * start of the parameter string. + * Revision 1.22 2009/09/29 14:58:18 martin + * Unified and simplified parameter evaluation. + * Updated version number to 3.4.0. + * Revision 1.21 2009/09/28 09:36:43 martin + * Support configuration of antenna cable length. + * Removed duplicate usage message for event time. + * Revision 1.20 2009/09/28 07:19:03 martin + * Made parameter syntax for enable_flags and LAN configuration more flexible. + * Revision 1.19 2009/08/20 14:19:29 martin + * Updated version number to 3.3.1. + * Support configuration of board's LAN interface. + * Revision 1.18 2009/07/24 09:50:08 martin + * Updated version number to 3.3.0. + * Revision 1.17 2009/06/19 12:38:51 martin + * Updated version number to 3.2.0. + * Revision 1.16 2009/06/18 15:14:53 martin + * Added command TZOFFS which can be used to set TZDL to UTC, and then + * configure the standard TZDL offset to a dedicated number of seconds, to the + * output time has a configurable UTC offset against the time derived from the + * input signal. + * Revision 1.15 2009/03/20 11:53:19 martin + * Updated version number to 3.1.0. + * Updated copyright year to include 2009. + * Support programmable time scales. + * Revision 1.14 2008/12/22 12:39:00 martin + * Updated description, copyright, revision number and string. + * Use unified functions from toolutil module. + * Accept device name(s) on the command line. + * Don't use printf() without format, which migth produce warnings + * with newer gcc versions. + * Revision 1.13 2008/11/07 10:25:49 martin + * Support modification of a card's ENABLE_FLAGS. + * Changes due to renamed library function. + * Changes due to renamed library function. + * Revision 1.12 2008/09/15 14:20:21 martin + * Support generic serial settings including string type and mode. + * Reworked evaluation of command line parameters. + * New parameter COM0= to configure an individual port. + * Account for renamed library symbols. + * Revision 1.11 2007/07/24 09:31:39 martin + * Changes due to renamed library symbols. + * Revision 1.10 2007/03/01 16:09:16 martin + * Be able to set the board date and/or time. + * Revision 1.9 2007/02/22 16:38:50 martin + * Added function to set on-board date. + * Revision 1.8 2006/08/28 10:45:50 martin + * Picked up Heiko's patch to set the GPS receiver position. + * Revision 1.7 2004/11/08 15:47:40 martin + * Using type cast to avoid compiler warning. + * Revision 1.6 2003/08/26 14:37:35 martin + * Support configuration of some standard time zones, + * also for GPS devices. + * Revision 1.5 2003/07/31 13:48:54 martin + * Added function to set COM port parms for GPS clocks. + * Usage shows which parameters are supported by a device. + * Revision 1.4 2003/04/25 10:27:58 martin + * Use new functions from mbgdevio library. + * New program version v2.1. + * Revision 1.3 2002/08/22 14:52:49 martin + * Added function to set clock's COM port parameters. + * Revision 1.2 2001/12/03 16:04:46 martin + * New program version 1.2. + * Added new function set_event_time(). + * Fixed a bug in eval of cmd line parameters. + * Revision 1.1 2001/09/17 15:07:56 martin + * + **************************************************************************/ + +// include Meinberg headers +#include <mbgdevio.h> +#include <deviohlp.h> +#include <pcpsmktm.h> +#include <pcpsutil.h> +#include <parmpcps.h> +#include <parmgps.h> +#include <myutil.h> +#include <gpsutils.h> +#include <cnv_wday.h> +#include <toolutil.h> +#include <lan_util.h> +//##+++++++++++++++++++++ #include <ptpdflts.h> + +// include system headers +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <ctype.h> + + +#define MBG_MICRO_VERSION 0 +#define MBG_FIRST_COPYRIGHT_YEAR 2001 +#define MBG_LAST_COPYRIGHT_YEAR 0 // use default + + +static const char *pname = "mbgctrl"; + +static char *dev_name; + +static int err_unicast_nsupp; +static const char str_unknown[] = "(unknown)"; + +static TZDL tzdl_utc = DEFAULT_TZDL_UTC; +static TZDL tzdl_cet_cest = DEFAULT_TZDL_CET_CEST_EN; +static TZDL tzdl_eet_eest = DEFAULT_TZDL_EET_EEST_EN; +static long max_tzdl_offs = 0x7FFFFFFFL; // max val for int32_t + +static const char tz_info_utc[] = TZ_INFO_UTC; +static const char tz_info_cet_cest[] = TZ_INFO_CET_CEST_EN; +static const char tz_info_eet_eest[] = TZ_INFO_EET_EEST_EN; + +static const char *mode_names[N_STR_MODE] = DEFAULT_ENG_MODE_NAMES; +static const char *time_scale_name[N_MBG_TIME_SCALE] = MBG_TIME_SCALE_STRS; + +#define _get_time_scale_name( _i ) \ + ( ( (_i) < N_MBG_TIME_SCALE ) ? time_scale_name[_i] : str_unknown ) + + +static const char no_gps_cmd[] = "does not support GPS commands"; +static const char no_tzdl[] = "does not support configurable time zone"; +static const char no_tz[] = "does not support time zones"; +static const char no_event_time[] = "does not support event times"; +static const char no_enable_flags[] = "does not support enable flags"; +static const char no_time_scale[] = "does not support a configurable time scale"; +static const char no_lan_intf[] = "does not provide a LAN interface"; +static const char no_ptp[] = "does not provide PTP"; +static const char no_cab_len[] = "does not support antenna signal delay compensation"; + + +typedef struct +{ + const char *name; + uint16_t *flags; + uint16_t on_flags; +} EF_INFO; + +#define N_EF_INFO 3 + +static const char ef_name_serial[] = "SERIAL"; +static const char ef_name_pulses[] = "PULSES"; +static const char ef_name_synth[] = "SYNTH"; + + +typedef struct +{ + const char *name; + IP4_ADDR *addr; +} IP4_INFO; + +#define N_IP4_INFO 4 + +static const char ip4_name_ip[] = "IP"; +static const char ip4_name_nm[] = "NM"; +static const char ip4_name_ba[] = "BA"; +static const char ip4_name_gw[] = "GW"; + +static const char ptp_name_net[] = "NP"; +static const char ptp_name_del[] = "DM"; +static const char ptp_name_dom[] = "DO"; +static const char ptp_name_v1[] = "HW"; + +static const char ptp_name_role[] = "ROLE"; + +static const char ptp_name_gmip[] = "GMIP"; +static const char ptp_name_gmid[] = "GMID"; +static const char ptp_name_pid[] = "PID"; +static const char ptp_name_smi[] = "SMI"; +static const char ptp_name_ami[] = "AMI"; +static const char ptp_name_dri[] = "DRI"; +static const char ptp_name_dur[] = "DUR"; + +//##+++++ +static const char *delay_mech[] = PTP_DELAY_MECH_NAMES; +static const char *nw_prot[] = PTP_NW_PROT_STRS; +static const char *nw_prot_short[] = PTP_NW_PROT_STRS_SHORT; + +static const char *ptp_roles[] = PTP_ROLE_STRS; +static const char *ptp_roles_short[] = PTP_ROLE_STRS_SHORT; + + +//##+++++++++++++++++++ +// If unicast is not supported for a PTP device then the device is definitely +// a multicast slave, in which case index 0 returns the correct role name. +#define _ptp_role_name( _i ) \ + ( ( (_i) < N_PTP_ROLES ) ? ptp_roles[_i] : str_unknown ) + +#define _ptp_role_name_short( _i ) \ + ( ( (_i) < N_PTP_ROLES ) ? ptp_roles_short[_i] : str_unknown ) + + + + +static /*HDR*/ +void err_msg( const PCPS_DEV *p_dev, const char *msg ) +{ + printf( "This device %s.\n", msg ); + +} // err_msg + + + +static /*HDR*/ +int set_tz_code( MBG_DEV_HANDLE dh, PCPS_TZCODE tzcode, const char *s ) +{ + int rc = mbg_set_tzcode( dh, &tzcode ); + + if ( mbg_ioctl_err( rc, "mbg_set_tzcode" ) ) + return rc; + + printf( "The clock's time zone setting has been set to %s.\n", s ); + + return MBG_SUCCESS; + +} // set_tz_code + + + +static /*HDR*/ +int set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *tzdl, const char *info ) +{ + int rc = mbg_set_gps_tzdl( dh, tzdl ); + + if ( mbg_ioctl_err( rc, "set_gps_tzdl" ) ) + return rc; + + if ( info ) + printf( "The clock's time zone setting has been set to %s.\n", info ); + + return MBG_SUCCESS; + +} // set_gps_tzdl + + + +static /*HDR*/ +int set_timezone( MBG_DEV_HANDLE dh, const char *tz_name, const PCPS_DEV *p_dev ) +{ + const char *tz_info = NULL; + TZDL *tz_tzdl = NULL; + PCPS_TZCODE tz_code = 0; + int rc = MBG_SUCCESS; + + if ( strcmp( tz_name, "UTC" ) == 0 ) + { + tz_info = tz_info_utc; + tz_tzdl = &tzdl_utc; + tz_code = PCPS_TZCODE_UTC; + } + else if ( strcmp( tz_name, "CET" ) == 0 ) + { + tz_info = tz_info_cet_cest; + tz_tzdl = &tzdl_cet_cest; + tz_code = PCPS_TZCODE_MEZMESZ; + } + else if ( strcmp( tz_name, "EET" ) == 0 ) + { + tz_info = tz_info_eet_eest; + tz_tzdl = &tzdl_eet_eest; + tz_code = PCPS_TZCODE_OEZ; + } + else + { + printf( "** Unknown timezone name %s\n", tz_name ); + rc = 1; + } + + if ( tz_info ) + { + if ( _pcps_has_tzcode( p_dev ) ) + rc = set_tz_code( dh, tz_code, tz_info ); + else + if ( _pcps_has_tzdl( p_dev ) ) + rc = set_gps_tzdl( dh, tz_tzdl, tz_info ); + else + err_msg( p_dev, no_tz ); + } + + return rc; + +} // set_timezone + + + +static /*HDR*/ +int show_tzdl_offs( MBG_DEV_HANDLE dh, const char *info ) +{ + TZDL tzdl; + int rc = mbg_get_gps_tzdl( dh, &tzdl ); + + if ( mbg_ioctl_err( rc, "mbg_get_gps_tzdl" ) ) + return rc; + + printf( "%s timezone offset: UTC%+lis", info, (long) tzdl.offs ); + + return MBG_SUCCESS; + +} // show_tzdl_offs + + + +static /*HDR*/ +int set_tzdl_offs( MBG_DEV_HANDLE dh, const char *s ) +{ + TZDL tzdl = tzdl_utc; + long tzdl_offs = atol( s ); + + if ( labs( tzdl_offs ) > max_tzdl_offs ) // max val for int32_t + { + fprintf( stderr, "** Time zone offset %li exceeds range (%li..%li)\n", + tzdl_offs, -max_tzdl_offs, max_tzdl_offs ); + return MBG_ERR_CFG; + } + + tzdl.offs = (int32_t) tzdl_offs; + + return set_gps_tzdl( dh, &tzdl, NULL ); + +} // set_tzdl_offs + + + +static /*HDR*/ +int show_lan_intf( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info ) +{ + IP4_SETTINGS ip4_settings; + char ws[256]; + + int rc = mbg_get_ip4_settings( dh, &ip4_settings ); + + if ( mbg_ioctl_err( rc, "mbg_get_ip4_settings" ) ) + return rc; + + printf( "On-board LAN interface settings:" ); + + if ( ip4_settings.flags & IP4_MSK_DHCP ) + printf( " (DHCP client)\n" ); + else + { + printf( "\n" ); + + snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.ip_addr, NULL ); + printf( " IP Address: %s\n", ws ); + + snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.netmask, NULL ); + printf( " Net Mask: %s\n", ws ); + + snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.broad_addr, NULL ); + printf( " Broadcast Addr: %s\n", ws ); + + snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.gateway, NULL ); + printf( " Gateway: %s\n", ws ); + } + + return MBG_SUCCESS; + +} // show_lan_intf + + + +static /*HDR*/ +int show_ptp_cfg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info ) +{ + ALL_PTP_CFG_INFO all_ptp_cfg_info; + char ws[256]; + int unicast_supported; + int idx; + + int rc = mbg_get_all_ptp_cfg_info( dh, &all_ptp_cfg_info ); + + if ( mbg_ioctl_err( rc, "mbg_get_all_ptp_cfg_info" ) ) + return rc; + + unicast_supported = ( all_ptp_cfg_info.ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) != 0; + + printf( "\nPTP configuration:\n"); + + idx = all_ptp_cfg_info.ptp_cfg_info.settings.ptp_role; + printf( " PTP Role : %s (%s)\n", _ptp_role_name_short( idx ), _ptp_role_name( idx ) ); + + idx = all_ptp_cfg_info.ptp_cfg_info.settings.nw_prot; + printf( " Network Protocol: %s (%s)\n", nw_prot_short[idx], nw_prot[idx] ); + + printf( " Delay Mechanism : %s\n", delay_mech[all_ptp_cfg_info.ptp_cfg_info.settings.delay_mech] ); + printf( " Domain Number : %d\n", all_ptp_cfg_info.ptp_cfg_info.settings.domain_number ); + printf( " V1 HW Compat. : %d\n", ( all_ptp_cfg_info.ptp_cfg_info.settings.flags & PTP_CFG_MSK_V1_HW_COMPAT ) ? 1 : 0 ); + + if ( unicast_supported ) + { + PTP_UC_MASTER_CFG_LIMITS *p_uc_limits = &all_ptp_cfg_info.ptp_uc_master_cfg_limits; + int i; + + for ( i = 0; i < p_uc_limits->n_supp_master; i++ ) + { + PTP_UC_MASTER_SETTINGS *p = &all_ptp_cfg_info.all_ptp_uc_master_info_idx[i].info.settings; + + printf( "\nPTP unicast master" ); + + if ( p_uc_limits->n_supp_master > 1 ) + printf( " %i", i ); + + printf( ":\n"); + + printf( " GM Host: %s\n", p->gm_host ); + + snprint_octets( ws, sizeof( ws ), p->gm_clock_id.b, sizeof( p->gm_clock_id.b ), MAC_SEP_CHAR, NULL ); + printf( " GM Clock ID: %s\n", ws ); + + printf( " GM Port ID: %d\n\n", p->gm_port_id ); + printf( " Sync Msg Interval [2^x s]: %i\n", p->sync_intv ); + printf( " Ann. Msg Interval [2^x s]: %i\n", p->ann_intv ); + printf( " DelReq Msg Interval [2^x s]: %i\n", p->delay_req_intv ); + printf( " Message Duration: %i s\n", p->message_duration ); + } + + } + + return MBG_SUCCESS; + +} // show_ptp_cfg + + + +static /*HDR*/ +/** + * @brief Lookup a string in a string table and return the table index + * + * @param s The string to be searched for in the string table + * @param tbl A table of strings to be searched + * @param n_entries The number of strings in the string table + * @param supp_mask A string with a given index is only supported if the + * corresponding bit is set in this mask. + * @param info A descriptive name of the parameter which is to be + * set to the index of the searched string + * + * @return >=0 A valid, supported table index + * <0 Unknown or unsupported parameter + */ +int get_chk_str_table_idx( const char *s, const char *tbl[], int n_entries, + uint32_t supp_mask, const char *info ) +{ + int i; + const char *cp; + + for ( i = 0; i < n_entries; i++ ) + { + cp = tbl[i]; + + if ( strncmp( s, cp, strlen( cp ) ) == 0 ) + if ( supp_mask & ( 1UL << i ) ) + return i; + } + + printf( "error: %s %s\n", + ( i == n_entries ) ? "unknown" : "unsupported", + info ); + + return -3; + +} // get_chk_str_table_idx + + + +static /*HDR*/ +/** + * @brief Lookup a parameter in an argument list and check if a colon is appended + * + * @param arg An argument list of the form: "name:val,name:val,..." + * @param s A parameter name searched for in the argument list + * @param p A pointer to a (char *) which is set to the beginning + * of the value part of a parameter string + * + * @return <0 Syntax error, i.e. missing colon + * 0 No error. If parameter has been found then *p set + * to the parameter value, else to NULL. + */ +int chk_parm_name( const char *arg, const char *id, char **p ) +{ + char *cp = strstr( arg, id ); + + if ( cp ) + { + cp += strlen( id ); + + if ( *cp != ':' ) + return -1; + + cp++; + } + + if ( p ) + *p = cp; // may be NULL + + return 0; + +} // chk_parm_name + + + +static /*HDR*/ +/** + * @brief Lookup a parameter in an argument list and check if the value string is valid + * + * This function expects that the parameter value is a known string which can + * be found in a table of known strings. A bit mask indicates if a string with + * a given table index is supported, or not. + * + * @param arg An argument list of the form: "name:val,name:val,..." + * @param id The name of the argument to be checked. + * @param tbl A table of strings with predefined parameter values + * @param n_entries The number of strings in the string table + * @param supp_mask A string with a given index is only supported if the + * corresponding bit is set in this mask. + * @param info A descriptive name of the parameter which is to be + * set to the index of the searched string + * + * @return >=0 A valid, supported table index + * -1 Parameter not found + * -2 Unknown or unsupported parameter, or syntax error + */ +int chk_tbl_parm( const char *arg, const char *id, const char *tbl[], + int n_entries, uint32_t supp_mask, const char *info ) +{ + char *cp; + int rc = chk_parm_name( arg, id, &cp ); + + if ( rc < 0 ) + return -2; + + if ( cp == NULL ) + return -1; + + rc = get_chk_str_table_idx( cp, tbl, n_entries, supp_mask, info ); + + if ( rc < 0 ) + return -2; + + return rc; + +} // chk_tbl_parm + + + +static /*HDR*/ +/** + * @brief Lookup an int16_t parameter in an argument list + * + * Check and save the numeric parameter if in a valid range. + * + * @param arg An argument list of the form: "name:val,name:val,..." + * @param id The name of the argument to be checked. + * @param p A pointer to a variable where the parameter value is + * saved if valid + * @param range_min The minimum allowed value for the parameter + * @param range_max The maximum allowed value for the parameter + * @param is_supported A flag indicating if the parameter is actually supported + * @param info A descriptive name of the parameter + * + * @return >=0 A valid, supported table index + * -1 Parameter not found, or out of range + */ +int chk_int16_parm( const char *arg, const char *id, int16_t *p, int16_t range_min, + int16_t range_max, int is_supported, const char *info ) +{ + char *cp; + int idx = chk_parm_name( arg, id, &cp ); + + if ( idx < 0 ) // parameter error + return -1; + + if ( cp ) // parameter found + { + if ( !is_supported ) + err_unicast_nsupp = 1; + else + { + int16_t tmp = atoi( cp ); + + if ( ( tmp < range_min ) || ( tmp > range_max ) ) + { + printf( "error: %s %i out of range (%i..%i)\n", info, tmp, range_min, range_max ); + return -1; + } + + *p = tmp; + printf( " setting %s: %i\n", info, tmp ); + } + } + + return 0; + +} // chk_int16_parm + + + +static /*HDR*/ +int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) +{ + ALL_PTP_CFG_INFO all_ptp_cfg_info; + ALL_PTP_CFG_INFO prv_all_ptp_cfg_info; + PTP_CFG_INFO *p_info; + PTP_CFG_SETTINGS *p_settings; + PTP_UC_MASTER_CFG_LIMITS *p_uc_limits; + PTP_UC_MASTER_INFO *p_uc_info; + PTP_UC_MASTER_SETTINGS *p_uc_settings; + uint32_t supp_mask; + IP4_ADDR ip4addr; + char ws[256]; + char *cp; + int idx; + int unicast_supported; + int uc_master_idx = 0; + int16_t tmp_int16; + + int rc = mbg_get_all_ptp_cfg_info( dh, &all_ptp_cfg_info ); + + if ( rc < 0 ) + return rc; // failed to read current settings and capabilities + + + err_unicast_nsupp = 0; + + // save a copy of the current settings + prv_all_ptp_cfg_info = all_ptp_cfg_info; + + p_info = &all_ptp_cfg_info.ptp_cfg_info; + p_settings = &p_info->settings; + unicast_supported = ( p_info->supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) != 0; + + p_uc_limits = &all_ptp_cfg_info.ptp_uc_master_cfg_limits; + // The pointers below need to be updated wnenever uc_master_idx is changed + p_uc_info = &all_ptp_cfg_info.all_ptp_uc_master_info_idx[uc_master_idx].info; + p_uc_settings = &p_uc_info->settings; + + + // Network protocol + idx = chk_tbl_parm( arg, ptp_name_net, nw_prot_short, N_PTP_NW_PROT, p_info->supp_nw_prot, "network protocol type" ); + + if ( idx >= 0 ) // valid parameter found + p_settings->nw_prot = idx; + else + if ( idx < -1 ) + goto fail; + + + // Delay Mechanism + idx = chk_tbl_parm( arg, ptp_name_del, delay_mech, N_PTP_DELAY_MECH, p_info->supp_delay_mech, "delay mechanism" ); + + if ( idx >= 0 ) // valid parameter found + p_settings->delay_mech = idx; + else + if ( idx < -1 ) + goto fail; + + + // Domain Number + idx = chk_parm_name( arg, ptp_name_dom, &cp ); + + if ( idx < 0 ) // parameter error + goto fail; + + if ( cp ) // parameter found + { + idx = atoi( cp ); + //##+++++ must check range!! + p_settings->domain_number = idx; + } + + + // V1 Hardware compatibility flag + idx = chk_parm_name( arg, ptp_name_v1, &cp ); + + if ( idx < 0 ) // parameter error + goto fail; + + if ( cp ) // parameter found + { + idx = atoi( cp ); + + switch ( idx ) + { + case 0: + p_settings->flags &= ~PTP_CFG_MSK_V1_HW_COMPAT; + break; + + case 1: + p_settings->flags |= PTP_CFG_MSK_V1_HW_COMPAT; + break; + + default: + printf( "error: No valid V1 HWC settings!\n" ); + goto fail; + } + } + + + //---- unicast stuff ---- + + // PTP role + supp_mask = _get_supp_ptp_role_idx_msk( p_info->supp_flags ); + idx = chk_tbl_parm( arg, ptp_name_role, ptp_roles_short, N_PTP_ROLES, supp_mask, "PTP role" ); + + if ( idx >= 0 ) // valid parameter found + { + if ( !unicast_supported ) + err_unicast_nsupp = 1; + else + p_settings->ptp_role = idx; + } + else + if ( idx < -1 ) // parameter error + goto fail; + + + // GM Host + idx = chk_parm_name( arg, ptp_name_gmip, &cp ); + + if ( idx < 0 ) // parameter error + goto fail; + + if ( cp ) // parameter found + { + if ( !unicast_supported ) + err_unicast_nsupp = 1; + else + { + // currently IP addresses are accepted only, so check for + // a valid IPv4 address + if ( str_to_ip4_addr( &ip4addr, cp ) ) + { + snprint_ip4_addr( ws, sizeof( ws ), &ip4addr, NULL ); + printf( " GM IP Address: %s\n", ws ); + + memset( p_uc_settings->gm_host, 0, sizeof( p_uc_settings->gm_host ) ); + strcpy( p_uc_settings->gm_host, ws ); + } + else + goto fail; + } + } + + + // GM Clock ID + idx = chk_parm_name( arg, ptp_name_gmid, &cp ); + + if ( idx < 0 ) // parameter error + goto fail; + + if ( cp ) // parameter found + { + if ( !unicast_supported ) + err_unicast_nsupp = 1; + else + { + PTP_CLOCK_ID gm_clock_id; + idx = str_to_octets( gm_clock_id.b, sizeof( gm_clock_id.b ), cp ); + + if ( idx != sizeof( gm_clock_id ) ) + { + printf( "Syntax error in specified GM clock ID\n" ); + goto fail; + } + else + { + p_uc_settings->gm_clock_id = gm_clock_id; + + snprint_octets( ws, sizeof( ws ), p_uc_settings->gm_clock_id.b, + sizeof( p_uc_settings->gm_clock_id.b ), MAC_SEP_CHAR, NULL ); + printf( " setting GM Clock ID: %s\n", ws ); + } + } + } + + + // GM Target Port ID + idx = chk_parm_name( arg, ptp_name_pid, &cp ); + + if ( idx < 0 ) // parameter error + goto fail; + + if ( cp ) // parameter found + { + if ( !unicast_supported ) + err_unicast_nsupp = 1; + else + { + p_uc_settings->gm_port_id = strtoul( cp, NULL, 0 ); + printf( " setting GM port id: %d\n", p_uc_settings->gm_port_id ); + } + } + + + // Sync Message Rate + idx = chk_int16_parm( arg, ptp_name_smi, &p_uc_settings->sync_intv, + p_uc_limits->sync_intv_min, p_uc_limits->sync_intv_max, + unicast_supported, "sync intv." ); + if ( idx < 0 ) + goto fail; + + + // Announce Message Rate + idx = chk_int16_parm( arg, ptp_name_ami, &p_uc_settings->ann_intv, + p_uc_limits->ann_intv_min, p_uc_limits->ann_intv_max, + unicast_supported, "ann. intv." ); + if ( idx < 0 ) + goto fail; + + + // Delay Message Rate + idx = chk_int16_parm( arg, ptp_name_dri, &p_uc_settings->delay_req_intv, + p_uc_limits->delay_req_intv_min, p_uc_limits->delay_req_intv_max, + unicast_supported, "delay req. intv." ); + if ( idx < 0 ) + goto fail; + + + // Message Duration //##++++ TODO: should this be added to the structure + tmp_int16 = p_uc_settings->message_duration; + idx = chk_int16_parm( arg, ptp_name_dur, &tmp_int16, + PTP_UC_MSG_DURATION_MIN, PTP_UC_MSG_DURATION_MAX, + unicast_supported, "msg. duration" ); + if ( idx < 0 ) + goto fail; + + p_uc_settings->message_duration = tmp_int16; + +#if 0 //##++++++++++++ + + cp = strstr( arg, ptp_name_dur ); + + if ( cp != NULL ) + { + l = strlen( ptp_name_dur ); + + if ( *(cp+l) != ':' ) + goto fail; // parameter syntax error: name not followed by colon + + l++; + + ptp_unicast_settings.message_duration = atoi( cp+l ); + printf( " setting message duration: %i seconds\n", ptp_unicast_settings.message_duration ); + } +#endif + + + rc = mbg_set_ptp_cfg_settings( dh, p_settings ); + + if ( mbg_ioctl_err( rc, "mbg_set_ptp_cfg_settings" ) ) + return rc; + + return MBG_SUCCESS; + + +fail: + printf( "Syntax error in argument!\n" ); + + return MBG_ERR_CFG; + +} // set_ptp_cfg + + + +static /*HDR*/ +int ip4_check_parm( const char *s, IP4_INFO *p ) +{ + int l = strlen( p->name ); + int n; + + if ( strncmp( s, p->name, l ) != 0 ) + return 0; // parameter does not match + + if ( s[l] != ':' ) + goto fail; // parameter syntax error: name not followed by colon + + l++; + + n = str_to_ip4_addr( p->addr, &s[l] ); + + if ( n < 0 ) + goto fail; // parameter syntax error: failed to convert numeric address + + return n + l; //##++++++ needs to be verified + +fail: + return MBG_ERR_CFG; + +} // ip4_check_parm + + + +static /*HDR*/ +int set_lan_intf( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) +{ + IP4_SETTINGS prv_ip4_settings; + IP4_SETTINGS ip4_settings = { 0 }; + IP4_ADDR default_broad_addr; + + IP4_INFO ip4_info[N_IP4_INFO] = + { + { ip4_name_ip, &ip4_settings.ip_addr }, + { ip4_name_nm, &ip4_settings.netmask }, + { ip4_name_ba, &ip4_settings.broad_addr }, + { ip4_name_gw, &ip4_settings.gateway } + }; + + int rc = mbg_get_ip4_settings( dh, &prv_ip4_settings ); + + if ( mbg_ioctl_err( rc, "mbg_get_ip4_settings" ) ) + return rc; + + if ( strcmp( arg, "DHCP" ) == 0 ) + { + ip4_settings = prv_ip4_settings; + ip4_settings.flags |= IP4_MSK_DHCP; + goto save; + } + + for (;;) + { + int i; + + for ( i = 0; i < N_IP4_INFO; i++ ) + { + rc = ip4_check_parm( arg, &ip4_info[i] ); + + if ( rc == 0 ) // check next + continue; + + if ( rc < 0 ) // error + goto invalid_msg; + + arg += rc; + + if ( *arg == 0 ) // end of parameter string + goto done; + + if ( *arg != ',' ) + goto invalid_msg; + + arg++; + } + } + + +done: // now check static configuration + if ( ip4_settings.ip_addr == 0 ) // no IP address specified on the command line + ip4_settings.ip_addr = prv_ip4_settings.ip_addr; // use previous IP address + + if ( ip4_settings.ip_addr == 0 ) // no IP address specified at all + { + printf( "*** Aborting: No IP address specified\n" ); + goto invalid; + } + + if ( ip4_settings.netmask == 0 ) // no network mask specified on the command line + ip4_settings.netmask = prv_ip4_settings.netmask; // use previous network mask + + if ( ip4_settings.netmask == 0 ) // no network mask specified at all + { + printf( "*** Aborting: No network mask specified\n" ); + goto invalid; + } + + // the default broadcast address is computed from the IP address and the network mask + default_broad_addr = ip4_settings.ip_addr | ~ip4_settings.netmask; + + if ( ip4_settings.broad_addr == 0 ) // no broadcast address specified on the command line + ip4_settings.broad_addr = default_broad_addr; + else + if ( ip4_settings.broad_addr != default_broad_addr ) + { + char ws1[40]; + char ws2[40]; + snprint_ip4_addr( ws1, sizeof( ws1 ), &ip4_settings.broad_addr, NULL ); + snprint_ip4_addr( ws2, sizeof( ws2 ), &default_broad_addr, NULL ); + printf( "*** Warning: Broadcast address %s does not match the default broadcast address %s\n", + ws1, ws2 ); + } + + if ( ip4_settings.gateway == 0 ) + ip4_settings.gateway = prv_ip4_settings.gateway; + + ip4_settings.flags = prv_ip4_settings.flags & ~IP4_MSK_DHCP; + // fall through to save: + +save: + rc = mbg_set_ip4_settings( dh, &ip4_settings ); + + if ( mbg_ioctl_err( rc, "mbg_set_ip4_settings" ) ) + return rc; + + return MBG_SUCCESS; + + +invalid_msg: + printf( "*** Warning: invalid LAN interface parameter syntax\n" ); + // fall through to invalid: + +invalid: + return MBG_ERR_CFG; // invalid parameter or parameter syntax error + +} // set_lan_intf + + + +static /*HDR*/ +int set_gps_pos( MBG_DEV_HANDLE dh, const char *gp ) +{ + LLA new_pos_lla; + char *cp; + int rc; + double r2d = 180 / PI; + + new_pos_lla[LAT] = strtod( gp, &cp ) / r2d; + + if ( *cp++ != ',' ) + goto invalid; + + new_pos_lla[LON] = strtod( cp, &cp ) / r2d; + + if ( *cp++ != ',' ) + goto invalid; + + new_pos_lla[ALT] = strtod( cp, &cp ); + + if ( + ( ( new_pos_lla[LAT] * r2d ) < -90 ) || + ( ( new_pos_lla[LAT] * r2d ) > +90 ) || + ( ( new_pos_lla[LON] * r2d ) < -180 ) || + ( ( new_pos_lla[LON] * r2d ) > +180 ) || + ( new_pos_lla[ALT] < -50 ) || + ( new_pos_lla[ALT] > 20000 ) + ) + goto invalid; + + + rc = mbg_set_gps_pos_lla ( dh, new_pos_lla ); + + if ( mbg_ioctl_err( rc, "mbg_set_gps_pos_lla" ) ) + return rc; + + printf( "The clock's receiver position has been set to lat=%+.4f, lon=%+.4f, alt=%.0fm\n", + new_pos_lla[LAT] * r2d, new_pos_lla[LON] * r2d, new_pos_lla[ALT] ); + + return rc; + + +invalid: + fprintf( stderr, "** Invalid GPS position parameters: %s\n", gp ); + + return MBG_ERR_CFG; + +} // set_gps_pos + + + +static /*HDR*/ +int set_date_time( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, + const char *sdate, const char *stime ) +{ + 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 ( sdate == NULL || stime == NULL ) + { + rc = mbg_get_time( dh, &u.t ); + + if ( mbg_ioctl_err( rc, "mbg_get_time" ) ) + return rc; + } + + + if ( sdate ) + { + rc = sscanf( sdate, "%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 ( stime ) + { + rc = sscanf( stime, "%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; + } + } + + // 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 ( sdate ) // 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 ( stime ) // 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 ( sdate ) // 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 ( stime ) // 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; + } + + printf( "Device date/time have been set.\n" ); + + return MBG_SUCCESS; + +} // set_date_time + + + +static /*HDR*/ +void check_setup_receiver_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, + RECEIVER_INFO *p_ri ) +{ + // Set up the RECEIVER_INFO structure only if this has not been done + // before. Check the ticks_per_sec field to see if the structure + // has already been set up or not. + if ( p_ri->ticks_per_sec == 0 ) + mbg_setup_receiver_info( dh, p_dev, p_ri ); + +} // check_setup_receiver_info + + + +static /*HDR*/ +int check_get_receiver_port_cfg( MBG_DEV_HANDLE dh, RECEIVER_PORT_CFG *p_rpcfg, + const PCPS_DEV *p_dev, RECEIVER_INFO *p_ri ) +{ + int rc = MBG_SUCCESS; + + check_setup_receiver_info( dh, p_dev, p_ri ); + + // Set up the RECEIVER_PORT_CFG structure only if this has not been done + // before. Check whether the number of ports is > 0 and the first port's + // baud rate is still 0 to see if the structure has already been set up. + if ( ( p_ri->n_com_ports > 0 ) && + ( p_rpcfg->pii[0].port_info.port_settings.parm.baud_rate == 0 ) ) + { + rc = mbg_get_serial_settings( dh, p_dev, p_rpcfg, p_ri ); + + mbg_ioctl_err( rc, "mbg_get_serial_settings" ); + } + + return rc; + +} // check_get_receiver_port_cfg + + + +static /*HDR*/ +int snprint_port_cfg( char *s, int sz, unsigned int port_num, + const RECEIVER_PORT_CFG *p_rpcfg ) +{ + const PORT_SETTINGS *p_ps = &p_rpcfg->pii[port_num].port_info.port_settings; + + int n = snprintf( s, sz, "\"%s\" %s at %lu/%s", + p_rpcfg->stii[p_ps->str_type].str_type_info.long_name, + mode_names[p_ps->mode], + (unsigned long) p_ps->parm.baud_rate, + p_ps->parm.framing + ); + + return n; + +} // snprint_port_cfg + + + +static /*HDR*/ +void show_serial_settings( MBG_DEV_HANDLE dh, const RECEIVER_PORT_CFG *p_rpcfg, + const RECEIVER_INFO *p_ri ) +{ + char ws[256]; + unsigned int i; + + for ( i = 0; i < p_ri->n_com_ports; i ++ ) + { + snprint_port_cfg( ws, sizeof( ws ), i, p_rpcfg ); + printf( "Serial port COM%u: %s.\n", i, ws ); + } + +} // show_serial_settings + + + +static /*HDR*/ +void print_port_info_errors( const char *port_name, unsigned int port_num, + int flags, const RECEIVER_PORT_CFG *p_rpcfg ) +{ + const char *msg_nsupp_drvr = "is not supported by the driver software"; + + const PORT_INFO *p_pi = &p_rpcfg->pii[port_num].port_info; + const PORT_SETTINGS *p_ps = &p_pi->port_settings; + + + if ( flags & MBG_PS_MSK_BAUD_RATE_OVR_SW ) + printf( "** Baud rate %lu %s.\n", (ulong) p_ps->parm.baud_rate, msg_nsupp_drvr ); + else + if ( flags & MBG_PS_MSK_BAUD_RATE ) + printf( "** Baud rate %lu is not supported by %s%u.\n", + (ulong) p_ps->parm.baud_rate, port_name, port_num ); + + + if ( flags & MBG_PS_MSK_FRAMING_OVR_SW ) + printf( "** Framing %s %s.\n", p_ps->parm.framing, msg_nsupp_drvr ); + else + if ( flags & MBG_PS_MSK_FRAMING ) + printf( "** Framing %s is not supported by %s%u.\n", + p_ps->parm.framing, port_name, port_num ); + + + if ( flags & MBG_PS_MSK_HS_OVR_SW ) + printf( "** Handshake mode %u %s.\n", p_ps->parm.handshake, msg_nsupp_drvr ); + else + if ( flags & MBG_PS_MSK_HS ) + printf( "** Handshake mode %u is not supported by %s%u.\n", + (unsigned int) p_ps->parm.handshake, port_name, port_num ); + + + if ( flags & MBG_PS_MSK_STR_TYPE_OVR_DEV ) + printf( "** String type index %u exceeds number of string types supp. by device.\n", + p_ps->str_type ); + else + if ( flags & MBG_PS_MSK_STR_TYPE ) + printf( "** String type \"%s\" is not supported by %s%u.\n", + p_rpcfg->stii[p_ps->str_type].str_type_info.long_name, + port_name, port_num ); + + + if ( flags & MBG_PS_MSK_STR_MODE_OVR_SW ) + printf( "** String mode index %u exceeds number of string modes supported by driver software (%u).\n", + p_ps->mode, N_STR_MODE ); + else + if ( flags & MBG_PS_MSK_STR_MODE ) + printf( "** String mode \"%s\" is not supported by string type \"%s\" via %s%u .\n", + mode_names[p_ps->mode], + p_rpcfg->stii[p_ps->str_type].str_type_info.long_name, + port_name, port_num ); + +} // print_port_info_errors + + + +static /*HDR*/ +int save_serial_settings( MBG_DEV_HANDLE dh, unsigned int port_num, const char *parm_str, + const PCPS_DEV *p_dev, const RECEIVER_INFO *p_ri ) +{ + char ws[256]; + RECEIVER_PORT_CFG rpcfg = { { { 0 } } }; + PORT_INFO *p_pi = &rpcfg.pii[port_num].port_info; + PORT_SETTINGS *p_ps = &p_pi->port_settings; + ulong ul; + const char *cp; + char *p_tail; + int rc; + int flags; + int i; + + // load current settings and supported settings + rc = mbg_get_serial_settings( dh, p_dev, &rpcfg, p_ri ); + + if ( mbg_ioctl_err( rc, "mbg_get_serial_settings" ) ) + return rc; + + + cp = parm_str; + p_ps->parm.baud_rate = strtoul( cp, &p_tail, 10 ); + + if ( p_tail == cp ) // no number found + goto invalid; + + cp = p_tail; + + if ( *cp++ != ',' ) // separator before framing missing + goto invalid; + + for ( i = 0; i < sizeof( p_ps->parm.framing ); i++ ) + { + int c = *cp; + + if ( !isalnum( c ) ) // stop copying if non-alpha and non-digit + break; + + p_ps->parm.framing[i] = *cp++; + } + + p_ps->parm.framing[i] = 0; // force terminating 0 + + p_ps->parm.handshake = HS_NONE; // this is the only supported setting + + + // get optional string type index + + if ( *cp++ != ',' ) + goto done_parm_str; + + ul = strtoul( cp, &p_tail, 10 ); + + if ( p_tail != cp ) + p_ps->str_type = ul; + + cp = p_tail; + + + // get optional string mode index + + if ( *cp++ != ',' ) + goto done_parm_str; + + ul = strtoul( cp, &p_tail, 10 ); + + if ( p_tail != cp ) + p_ps->mode = ul; + + +done_parm_str: + + // check if the new parameter set is valid + flags = check_valid_port_info( p_pi, rpcfg.stii, p_ri->n_str_type ); + + if ( flags ) // parameters not valid + { + print_port_info_errors( "COM", port_num, flags, &rpcfg ); + goto invalid; + } + + // save new parameters + rc = mbg_save_serial_settings( dh, p_dev, &rpcfg, port_num ); + + if ( mbg_ioctl_err( rc, "mbg_save_serial_settings" ) ) + return rc; + + + snprint_port_cfg( ws, sizeof( ws ), port_num, &rpcfg ); + printf( "The clock's COM%u port has been set to %s.\n", port_num, ws ); + + return MBG_SUCCESS; + + +invalid: + fprintf( stderr, "** Invalid COM port parameters: %s\n", parm_str ); + return MBG_ERR_CFG; + +} // save_serial_settings + + + +static /*HDR*/ +void printf_ef( uint16_t flag, const char *info ) +{ + printf( "%s:%u", info, ( flag == EF_OFF ) ? 0 : 1 ); + +} // printf_ef + + + +static /*HDR*/ +int show_enable_flags( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info ) +{ + ENABLE_FLAGS ef; + int rc; + + rc = mbg_get_gps_enable_flags( dh, &ef ); + + if ( mbg_ioctl_err( rc, "mbg_get_gps_enable_flags" ) ) + return rc; + + printf( "%s enable flags: ", info ); + printf_ef( ef.serial, ef_name_serial ); + printf( "," ); + printf_ef( ef.pulses, ef_name_pulses ); + + if ( _pcps_has_synth( p_dev ) ) + { + printf( "," ); + printf_ef( ef.synth, ef_name_synth ); + } + + printf( "\n" ); + + return MBG_SUCCESS; + +} // show_enable_flags + + + +static /*HDR*/ +int ef_check_parm( const char *s, EF_INFO *p ) +{ + int l = strlen( p->name ); + + if ( strncmp( s, p->name, l ) != 0 ) + return 0; // parameter does not match + + if ( s[l] != ':' ) + goto fail; // parameter syntax error: name not followed by colon + + l++; + + if ( s[l] != '0' && s[l] != '1' ) + goto fail; // parameter syntax error: colon not followed by '0' or '1' + + *p->flags = ( s[l] == '0' ) ? EF_OFF : p->on_flags; + + l++; + + return l; + + +fail: + return MBG_ERR_CFG; + +} // ef_check_parm + + + +static /*HDR*/ +int set_enable_flags( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) +{ + ENABLE_FLAGS ef; + + EF_INFO ef_parms[N_EF_INFO] = + { + { ef_name_serial, &ef.serial, EF_SERIAL_BOTH }, + { ef_name_pulses, &ef.pulses, EF_PULSES_BOTH }, + { ef_name_synth, &ef.synth, EF_SYNTH } + }; + + int rc; + + rc = mbg_get_gps_enable_flags( dh, &ef ); + + if ( mbg_ioctl_err( rc, "mbg_get_gps_enable_flags" ) ) + return rc; + + // Scan input parameters + for (;;) + { + int i; + + for ( i = 0; i < N_EF_INFO; i++ ) + { + rc = ef_check_parm( arg, &ef_parms[i] ); + + if ( rc == 0 ) // check next + continue; + + if ( rc < 0 ) // error + return rc; + + arg += rc; + + if ( *arg == 0 ) // done + goto save; + + if ( *arg != ',' ) + return MBG_ERR_CFG; // invalid parameter or parameter syntax error + + arg++; + } + } + +save: + rc = mbg_set_gps_enable_flags( dh, &ef ); + + if ( mbg_ioctl_err( rc, "mbg_set_gps_enable_flags" ) ) + return rc; + + return MBG_SUCCESS; + +} // set_enable_flags + + + +static /*HDR*/ +int send_gps_cmd( MBG_DEV_HANDLE dh, ushort cmd ) +{ + int rc = mbg_set_gps_cmd( dh, &cmd ); + + if ( mbg_ioctl_err( rc, "mbg_set_gps_cmd" ) ) + return rc; + + printf( "NOTE: the command code %u has been sent to the GPS clock.\n", cmd ); + + return MBG_SUCCESS; + +} // send_gps_cmd + + + +static /*HDR*/ +int show_ant_cable_len( MBG_DEV_HANDLE dh, const char *info ) +{ + ANT_CABLE_LEN len; + int rc = mbg_get_gps_ant_cable_len( dh, &len ); + + if ( mbg_ioctl_err( rc, "mbg_get_gps_ant_cable_len" ) ) + return rc; + + printf( "%s antenna cable length: %u meter(s)", info, len ); + + return MBG_SUCCESS; + +} // show_ant_cable_len + + + +static /*HDR*/ +int set_ant_cable_len( MBG_DEV_HANDLE dh, const char *s ) +{ + ANT_CABLE_LEN len = atol( s ); + int rc = mbg_set_gps_ant_cable_len( dh, &len ); + + if ( mbg_ioctl_err( rc, "mbg_set_gps_ant_cable_len" ) ) + return rc; + + return MBG_SUCCESS; + +} // set_ant_cable_len + + + +static /*HDR*/ +int set_event_time( MBG_DEV_HANDLE dh, const char *s ) +{ + char ws[80]; + time_t event_time; + PCPS_TIME_STAMP event_ts; + int rc; + + // set event at current system time + number of seconds + event_time = time( NULL ) + strtol( s, NULL, 10 ); + event_ts.sec = event_time; // Unix UTC seconds + event_ts.frac = 0; // fraction of second, 0xFFFFFFFF == 0.99.. sec + + rc = mbg_set_event_time( dh, &event_ts ); + + if ( mbg_ioctl_err( rc, "mbg_set_event_time" ) ) + return rc; + + mbg_snprint_hr_tstamp( ws, sizeof( ws ), &event_ts, 0 ); // raw timestamp? + printf( "Event time set to UTC %s\n", ws ); + + return MBG_SUCCESS; + +} // set_event_time + + + +static /*HDR*/ +int get_n_time_scale( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p_tsci ) +{ + MBG_TIME_SCALE_INFO tsci = { { 0 } }; + int rc; + int i; + + rc = mbg_dev_has_time_scale( dh, &i ); + + if ( ( rc != MBG_SUCCESS ) || ( i == 0 ) ) + goto done; // failed or not supported + + rc = mbg_get_time_scale_info( dh, &tsci ); + + if ( rc != MBG_SUCCESS ) + goto done; + + if ( p_tsci ) + *p_tsci = tsci; + +done: + return tsci.max_settings.scale; + +} // get_n_time_scale + + + +static /*HDR*/ +int show_time_scale( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info ) +{ + MBG_TIME_SCALE_INFO tsci = { { 0 } }; + int rc; + + rc = mbg_get_time_scale_info( dh, &tsci ); + + if ( mbg_ioctl_err( rc, "mbg_get_time_scale_info" ) ) + return rc; + + printf( "%s time scale index: %u (%s)", info, tsci.settings.scale, + _get_time_scale_name( tsci.settings.scale ) ); + + printf( "\n" ); + + return MBG_SUCCESS; + +} // show_time_scale + + + +static /*HDR*/ +int set_time_scale( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) +{ + MBG_TIME_SCALE_INFO tsci = { { 0 } }; + int rc; + + rc = mbg_get_time_scale_info( dh, &tsci ); + + if ( mbg_ioctl_err( rc, "mbg_get_time_scale_info" ) ) + return rc; + + + tsci.settings.scale = atoi( arg ); + + if ( tsci.settings.scale >= tsci.max_settings.scale ) + { + printf( "*** Error: new time scale index (%u) out of range (0..%u)\n", + tsci.settings.scale, tsci.max_settings.scale - 1 ); + return MBG_ERR_CFG; + } + + if ( !( tsci.supp_scales & ( 1UL << tsci.settings.scale ) ) ) + { + printf( "*** Warning: new time scale index (%u) not supported by device\n", + tsci.settings.scale ); + return MBG_ERR_CFG; + } + + rc = mbg_set_time_scale_settings( dh, &tsci.settings ); + + if ( mbg_ioctl_err( rc, "mbg_set_time_scale_settings" ) ) + return rc; + + return MBG_SUCCESS; + +} // set_time_scale + + + +static /*HDR*/ +void usage( MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri, + RECEIVER_PORT_CFG *p_rpcfg ) +{ + int i; + int n_time_scale; + + if ( p_dev ) + { + check_setup_receiver_info( dh, p_dev, p_ri ); + check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri ); + } + + printf( "Usage: %s cmd [dev]\n" + "\n" + "where cmd can be one of the following:\n" + " BOOT set GPS clock to boot mode\n" + " GPSPOS=x.x,y.y,z set GPS position to (lat,lon,alt)\n", + pname + ); + + + printf( " DATE=yyyy-mm-dd set on-board date to year, month, day-of-month\n" + " TIME=hh:mm:ss.hh set on-board time to hours, mins, secs, hundredths\n" + ); + + + printf( " TIMESCALE show clock's time scale setting, if supported\n" + " TIMESCALE=<n> set clock's time scale to scale with index <n>\n" + ); + + n_time_scale = p_dev ? get_n_time_scale( dh, NULL ) : N_MBG_TIME_SCALE; + + if ( n_time_scale ) + { + printf( " Known time scales:\n" ); + for ( i = 0; i < n_time_scale; i++ ) + { + printf( " %u: %s", i, _get_time_scale_name( i ) ); + + if ( i == 0 ) + printf( " (default)" ); + + printf( "\n" ); + } + } + else + printf( " (Configurable time scales not supported by this device)\n" ); + + + printf( " TZOFFS show clock's time zone offset, if supported\n" + " TZOFFS=<n> set clock's basic time zone to UTC with additional offset, in seconds\n" + ); + + printf( " TZ=UTC set time zone code to %s\n" + " TZ=CET set time zone code to %s\n" + " TZ=EET set time zone code to %s\n", + tz_info_utc, + tz_info_cet_cest, + tz_info_eet_eest + ); + + + printf( " COMPARM show clock's COM port parameters\n" + " COM<n>=<bd>,<f>[,<t>[,<m>]] set parameters of clock's port COM<n>" + ); + + printf( ", where\n" + " <bd> is one of:" ); + for ( i = 0; i < N_MBG_BAUD_RATES; i++ ) + printf( " %s", mbg_baud_str[i] ); + + printf( "\n" + " <f> is one of:" ); + for ( i = 0; i < N_MBG_FRAMINGS; i++ ) + printf( " %s", mbg_framing_str[i] ); + + printf( "\n <t> optional time string format index" ); + + if ( p_dev ) + { + printf( ":" ); + + for ( i = 0; i < p_ri->n_str_type; i ++ ) + { + const STR_TYPE_INFO *p_sti = &p_rpcfg->stii[i].str_type_info; + + printf( "\n %u: %s", i, p_sti->long_name ); + } + } + + printf( "\n <m> optional time string mode index" ); + + if ( p_dev ) + { + printf( ":" ); + + for ( i = 0; i < N_STR_MODE; i ++ ) + printf( "\n %u: %s", i, mode_names[i] ); + + printf( "\n" + " Please note not each baud rate, framing, string format and mode\n" + " must necessarily be supported by every individual serial port.\n" ); + } + + printf( "\n" ); + + printf( " EF show clock's enable flags\n" + " EF=SERIAL:0,PULSES:1,SYNTH:0 modify clock's enable flags\n" + "\n" + " SERIAL controls the serial port output\n" + " PULSES controls pulse outputs and IRIG timecode output, if available\n" + " SYNTH controls a programmable synthesizer output, if available\n" + "\n" + " 0 or 1 controls when the corresponding output signals are enabled:\n" + " 0: only after the card has synchronized to its incoming signal\n" + " 1: immediately after power-up\n" + "\n" + " Please note that not every device supports enable flags.\n" + "\n" + ); + + printf( " LAN show board's LAN interface settings\n" + " LAN=DHCP set LAN interface to be configured via DHCP\n" + " LAN=IP:<ip>[,NM:<nm>][,BA:<ba>][,GW:<gw>] set LAN interface to given static settings\n" + "\n" + " where each of <ip>,<nm>,<ba>,<gw> is an IPv4 address of the form aaa.bbb.ccc.ddd, e.g.:\n" + " IP:192.168.1.115 specifies the IP address\n" + " NM:255.255.255.0 specifies the net mask\n" + " BA:192.168.1.255 specifies the broadcast address\n" + " GW:192.168.1.1 specifies the default gateway\n" + "\n" + " If no broadcast address is specified then the default broadcast address\n" + " is computed from the IP address and the network mask.\n" + "\n" + " Please note that not every device provides a LAN interface.\n" + " Also, the IP values above are examples only. The real values to be used\n" + " depend on the settings of the network to which the card is attached.\n" + "\n" + ); + + printf( " PTP show board's PTP settings\n" + " PTP=NP:<np>[,DM:<dm>][,DO:<do>][,HW:<hw>] set general PTP protocol parameters\n" + "\n" + " where, e.g. :\n" + " NP:IP4 specifies UDP/IPv4 (Layer 3) as network protocol\n" + " NP:ETH specifies IEEE 802.3 (Layer 2) as network protocol\n" + " DM:E2E specifies end-to-end delay mechanism\n" + " DM:P2P specifies peer-to-peer delay mechanism\n" + " DO:0 specifies PTP domain number [0..255]\n" + " HW:1 specifies if the \"v1 hardware compatibility flag\" shall be set ('1') or disabled ('0')\n" + " (this is usually not required)\n" + "\n" + ); + + printf( " If the PTP device supports unicast slave mode then the following parameters\n" + " can be specified to configure a unicast master to be queried:\n" + " PTP=ROLE:<rl>[,GMIP:<ip>][,GMID:<id>][,PID:<po>][,SMI:<sr>][,AMI:<ar>][,DMI:<dr>][,DUR:<du>] set PTP unicast parameters\n" + "\n" + " where, e.g.:\n" + " ROLE:MCS specifies \"Multicast Slave\" PTP role\n" + " ROLE:UCS specifies \"Unicast Slave\" PTP role\n" + " GMIP:192.168.1.115 specifies the IP address of the grandmaster\n" + " GMID:FF:FF:FF:FF:FF:FF:FF:FF specifies the Clock ID of the grandmaster, or '*' as wildcard for all FF\n" + " PID:1 specifies the target port ID of the grandmaster port to be used, or '*' for wildcard\n" + " SMI:0 specifies the Sync message interval requested from the grandmaster in 2^x seconds [-6..6]\n" + " AMI:1 specifies the Announce message interval requested from the grandmaster in 2^x seconds [-6..6]\n" + " DMI:1 specifies the DelayRequest message interval requested from the grandmaster in 2^x seconds [-6..6]\n" + " DUR:300 specifies the duration in seconds how long the master shall send messages to the slave until a timeout or renewal occurs\n" + "\n" + ); + + printf( " ANT_CABLE_LEN show the configured antenna cable length\n" + " ANT_CABLE_LEN=<len> set the antenna cable length to be compensated to <len>, in meters.\n" + "\n" + " Please note note this parameter is only supported with cards which provide\n" + " compensation of the antenna cable signal propagation delay, i.e. GPS cards.\n" + "\n" + ); + + if ( p_dev ) + { + if ( _pcps_has_event_time( p_dev ) ) + printf( " EVENT=<n> set event time to system time + <n> seconds\n" ); + } + +} // usage + + + +static /*HDR*/ +const char *str_parm_p( const char *s, const char *keyword ) +{ + char *match = strstr( s, keyword ); + + if ( match && ( match == s ) ) + return &s[strlen( keyword )]; + else + return NULL; + +} // str_parm_p + + + +static /*HDR*/ +int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, + RECEIVER_INFO *p_ri, RECEIVER_PORT_CFG *p_rpcfg ) +{ + const char *sdate = NULL; + const char *stime = NULL; + const char *cp; + int i; + int rc = 0; + int error_occurred = 0; + + must_print_usage = 0; + + for ( i = 1; i < argc; i++ ) + { + if ( rc < 0 ) + error_occurred = 1; + + if ( rc > 0 ) + must_print_usage = 1; + + rc = 0; + + if ( ( strcmp( argv[i], "-?" ) == 0 ) || + ( strcmp( argv[i], "-h" ) == 0 ) || + ( strcmp( argv[i], "--help" ) == 0 ) ) + { + must_print_usage = 1; + continue; + } + + if ( strcmp( argv[i], "BOOT" ) == 0 ) + { + if ( p_dev ) + { + if ( _pcps_is_gps( p_dev ) ) + rc = send_gps_cmd( dh, PC_GPS_CMD_BOOT ); + else + err_msg( p_dev, no_gps_cmd ); + } + continue; + } + + + cp = str_parm_p( argv[i], "TZ=" ); + + if ( cp ) + { + if ( p_dev ) + rc = set_timezone( dh, cp, p_dev ); + + continue; + } + + + cp = str_parm_p( argv[i], "GPSPOS=" ); + + if ( cp ) + { + if ( p_dev ) + { + if ( _pcps_is_gps( p_dev ) ) + rc = set_gps_pos( dh, cp ); + else + err_msg( p_dev, no_gps_cmd ); + } + continue; + } + + + cp = str_parm_p( argv[i], "DATE=" ); + + if ( cp ) + { + sdate = cp; + continue; + } + + + cp = str_parm_p( argv[i], "TIME=" ); + + if ( cp ) + { + stime = cp; + continue; + } + + + cp = str_parm_p( argv[i], "COMPARM" ); + + if ( cp ) + { + if ( p_dev ) + { + check_setup_receiver_info( dh, p_dev, p_ri ); + if ( p_ri->n_com_ports ) + { + check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri ); + + if ( *cp != 0 ) + { + printf( "** Invalid parameter: %s\n", argv[i] ); + must_print_usage = 1; + continue; + } + + show_serial_settings( dh, p_rpcfg, p_ri ); + } + else + printf( "** This device does not provide a configurable COM port.\n" ); + } + + continue; + } + + + cp = str_parm_p( argv[i], "COM" ); + + if ( cp ) + { + if ( p_dev ) + { + char *p_tail; + ulong port_num; + + check_setup_receiver_info( dh, p_dev, p_ri ); + check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri ); + + port_num = strtoul( cp, &p_tail, 10 ); + + if ( p_tail == cp ) // no COM port number specified + { + printf( "** Invalid COM port specification: %s\n", argv[i] ); + must_print_usage = 1; + continue; + } + + cp = p_tail; + + if ( port_num >= (ulong) p_ri->n_com_ports ) + { + printf( "** COM port number %lu exceeds maximum %u\n", + port_num, p_ri->n_com_ports ); + must_print_usage = 1; + continue; + } + + if ( *cp != '=' ) + { + printf( "** Invalid COM port specification: %s\n", argv[i] ); + must_print_usage = 1; + continue; + } + + rc = save_serial_settings( dh, (unsigned) port_num, ++cp, p_dev, p_ri ); + } + continue; + } + + + cp = str_parm_p( argv[i], "EF" ); + + if ( cp ) + { + if ( p_dev ) + { + char *info = "Current"; + + if ( !_pcps_has_gps_data( p_dev ) ) + { + err_msg( p_dev, no_enable_flags ); + continue; + } + + if ( *cp == '=' ) + { + rc = set_enable_flags( dh, ++cp, p_dev ); + + if ( rc < 0 ) + { + printf( "*** Warning: invalid enable flag parameter syntax\n" ); + must_print_usage = 1; + continue; + } + + info = "New"; + } + + show_enable_flags( dh, p_dev, info ); + } + continue; + } + + + cp = str_parm_p( argv[i], "TIMESCALE" ); + + if ( cp ) + { + if ( p_dev ) + { + char *info = "Current"; + + if ( !_pcps_has_time_scale( p_dev ) ) + { + err_msg( p_dev, no_time_scale ); + continue; + } + + if ( *cp == '=' ) + { + rc = set_time_scale( dh, ++cp, p_dev ); + + if ( rc < 0 ) + { + must_print_usage = 1; + continue; + } + + info = "New"; + } + + show_time_scale( dh, p_dev, info ); + } + continue; + } + + + cp = str_parm_p( argv[i], "TZOFFS" ); + + if ( cp ) + { + if ( p_dev ) + { + char *info = "Current"; + + if ( !_pcps_has_tzdl( p_dev ) ) + { + err_msg( p_dev, no_tzdl ); + continue; + } + + if ( *cp == '=' ) + { + rc = set_tzdl_offs( dh, ++cp ); + + if ( rc < 0 ) + { + must_print_usage = 1; + continue; + } + + info = "New"; + } + + show_tzdl_offs( dh, info ); + } + continue; + } + + + cp = str_parm_p( argv[i], "LAN" ); + + if ( cp ) + { + if ( p_dev ) + { + char *info = "Current"; + + if ( !_pcps_has_lan_intf( p_dev ) ) + { + err_msg( p_dev, no_lan_intf ); + continue; + } + + if ( *cp == '=' ) + { + rc = set_lan_intf( dh, ++cp, p_dev ); + + if ( rc < 0 ) + { + must_print_usage = 1; + continue; + } + + info = "New"; + } + + show_lan_intf( dh, p_dev, info ); + } + continue; + } + + + cp = str_parm_p( argv[i], "PTP" ); + + if ( cp ) + { + if ( p_dev ) + { + char *info = "Current"; + + if ( !_pcps_has_ptp( p_dev ) ) + { + err_msg( p_dev, no_ptp ); + continue; + } + + if ( *cp == '=' ) + { + rc = set_ptp_cfg( dh, ++cp, p_dev ); + + if ( rc < 0 ) + { + must_print_usage = 1; + continue; + } + + info = "New"; + } + + show_ptp_cfg( dh, p_dev, info ); + } + continue; + } + + cp = str_parm_p( argv[i], "ANT_CABLE_LEN" ); + + if ( cp ) + { + if ( p_dev ) + { + char *info = "Current"; + + if ( !_pcps_has_cab_len( p_dev ) ) + { + err_msg( p_dev, no_cab_len ); + continue; + } + + if ( *cp == '=' ) + { + rc = set_ant_cable_len( dh, ++cp ); + + if ( rc < 0 ) + { + must_print_usage = 1; + continue; + } + + info = "New"; + } + + show_ant_cable_len( dh, info ); + } + continue; + } + + + cp = str_parm_p( argv[i], "EVENT" ); + + if ( cp ) + { + if ( p_dev ) + { + if ( _pcps_has_event_time( p_dev ) ) + { + if ( *cp == '=' ) + rc = set_event_time( dh, ++cp ); + else + rc = -1; + + if ( rc < 0 ) + printf( "*** Warning: invalid event time parameter\n" ); + } + else + err_msg( p_dev, no_event_time ); + } + continue; + } + + if ( dev_name == NULL ) + dev_name = argv[i]; + +#if 0 //##++ + else + { + printf( "** Unknown command: %s\n", argv[i] ); + must_print_usage = 1; + } +#endif + + } + + if ( p_dev ) + if ( sdate || stime ) + rc = set_date_time( dh, p_dev, sdate, stime ); + + if ( error_occurred ) + return -1; + + if ( must_print_usage ) + return 1; + + return MBG_SUCCESS; + +} // check_cmd_line + + + +int main( int argc, char *argv[] ) +{ + RECEIVER_PORT_CFG rpcfg = { { { 0 } } }; + RECEIVER_INFO ri = { 0 }; + PCPS_DEV dev = { { 0 } }; + PCPS_DEV *pdev = NULL; + MBG_DEV_HANDLE dh = MBG_INVALID_DEV_HANDLE; + int rc; + + mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); + + // If no arguments have been given, just print usage. + if ( argc < 2 ) + goto show_usage; + + // Check the command line for a device name, but don't + // pass a device handle, so commands are not evaluated. + check_cmd_line( argc, argv, dh, NULL, &ri, &rpcfg ); + + if ( dev_name ) + dh = open( dev_name, O_RDWR ); // open specific device + else + dh = mbg_open_device( 0 ); // open first device found + + if ( dh == MBG_INVALID_DEV_HANDLE ) + { + //##++++++++++++++++++++++ + if ( dev_name ) + fprintf( stderr, "%s: ", dev_name ); + + perror( "Unable to open device" ); + goto fail; + } + + // get information about the device + rc = mbg_get_show_dev_info( dh, dev_name, &dev ); + + if ( rc < 0 ) + goto fail; + + + pdev = &dev; + + rc = check_cmd_line( argc, argv, dh, pdev, &ri, &rpcfg ); + + if ( rc < 0 ) + goto fail; + + if ( rc > 0 ) + goto show_usage; + + printf( "\n" ); + + mbg_close_device( &dh ); + + return 0; + + +show_usage: + usage( dh, pdev, &ri, &rpcfg ); + return 1; + +fail: + return 2; +} diff --git a/mbgfasttstamp/mbgfasttstamp.c b/mbgfasttstamp/mbgfasttstamp.c new file mode 100644 index 0000000..c9b2d91 --- /dev/null +++ b/mbgfasttstamp/mbgfasttstamp.c @@ -0,0 +1,300 @@ + +/************************************************************************** + * + * $Id: mbgfasttstamp.c 1.6.1.8 2013/04/10 15:40:28Z martin TEST martin $ + * + * Description: + * Main file for mbgfasttstamp program which demonstrates how to access + * a Meinberg device via memory mapped I/O, if supported by the device. + * + * ----------------------------------------------------------------------- + * $Log: mbgfasttstamp.c $ + * Revision 1.6.1.8 2013/04/10 15:40:28Z martin + * Revision 1.6.1.7 2013/01/24 14:39:33Z martin + * Revision 1.6.1.6 2012/06/01 18:46:52 martin + * Added option to sleep between calls. + * Revision 1.6.1.5 2011/12/19 16:09:17 martin + * Revision 1.6.1.4 2011/09/26 16:00:51 martin + * Modified program version handling. + * Account for modified library functions which can now + * optionally print the raw (hex) HR time stamp. + * Started to support signal handler to catch CTRL-C. + * Revision 1.6.1.3 2011/01/28 12:04:07 martin + * Revision 1.6.1.2 2011/01/28 11:51:13 martin + * Revision 1.6.1.1 2011/01/28 11:17:00 martin + * Abort if MM access not supported on the target OS. + * Revision 1.6 2010/05/21 12:54:33 martin + * Print warning if no cycles supported on the target platform + * and thus latencies can not be computed. + * Revision 1.5 2009/09/29 15:02:14 martin + * Updated version number to 3.4.0. + * Revision 1.4 2009/07/24 09:50:08 martin + * Updated version number to 3.3.0. + * Revision 1.3 2009/06/19 14:01:32 martin + * Made print_hr_timestamp() to toolutil.c as mbg_print_hr_timestamp(). + * Updated version number to 3.2.0. + * Revision 1.2 2009/03/20 11:48:19 martin + * Updated version number to 3.1.0. + * Updated copyright year to include 2009. + * New parameter -r lets the program read raw timestamps + * using the new API call mbg_get_fast_hr_timestamp(). + * Revision 1.1 2008/12/22 11:45:01 martin + * Initial revision. + * Revision 1.1 2008/12/22 11:05:24 martin + * Initial revision. + * + **************************************************************************/ + +// include Meinberg headers +#include <mbgdevio.h> +#include <pcpsutil.h> +#include <toolutil.h> // common utility functions + +// include system headers +#include <stdio.h> +#include <stdlib.h> + + +#define MBG_MICRO_VERSION 0 +#define MBG_FIRST_COPYRIGHT_YEAR 2007 +#define MBG_LAST_COPYRIGHT_YEAR 0 // use default + +static const char *pname = "mbgfasttstamp"; + + +#define MAX_TS_BURST 1000 + +static int loops; +static int burst_read; +static int read_raw; +static long sleep_secs; +static long sleep_usecs; + + + +// The function below reads a number of time stamps and prints +// each timestamp immediately. This is not as fast as possible +// since printing the time stamp takes some time to execute. +// However, this can run continuously forever. + +static /*HDR*/ +int show_fast_hr_timestamp( MBG_DEV_HANDLE dh ) +{ + int this_loops = loops; + PCPS_TIME_STAMP ts; + int32_t hns_latency = 0; + + for (;;) + { + int rc = read_raw ? mbg_get_fast_hr_timestamp( dh, &ts ) : + mbg_get_fast_hr_timestamp_comp( dh, &ts, &hns_latency ); + + if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp..." ) ) + goto fail; + + mbg_print_hr_timestamp( &ts, hns_latency, NULL, read_raw, 1 ); // raw timestamp? + + if ( this_loops > 0 ) + this_loops--; + + if ( this_loops == 0 ) + break; + + if ( sleep_secs ) + sleep( sleep_secs ); + else + if ( sleep_usecs ) + usleep( sleep_usecs ); + + // if this_loops is < 0 then loop forever + } + + return 0; + +fail: + return -1; + +} // show_fast_hr_timestamp + + + +// The function below takes a number of time stamps and saves +// them to a buffer. After the time stamps have been read +// a second loop prints the time stamps from the buffer. +// This way the time stamps are read in shorter intervals. +// However, this can not run continuously forever since +// the buffer size is somewhat limited. + +static /*HDR*/ +int show_fast_hr_timestamp_burst( MBG_DEV_HANDLE dh ) +{ + PCPS_TIME_STAMP ts[MAX_TS_BURST]; + int32_t hns_latency[MAX_TS_BURST]; + int this_loops; + int i; + + this_loops = ( loops && ( loops < MAX_TS_BURST ) ) ? loops : MAX_TS_BURST; + + + if ( read_raw ) + { + for ( i = 0; i < this_loops; i++ ) + { + int rc = mbg_get_fast_hr_timestamp( dh, &ts[i] ); + + if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp" ) ) + goto fail; + } + } + else + for ( i = 0; i < this_loops; i++ ) + { + int rc = mbg_get_fast_hr_timestamp_comp( dh, &ts[i], &hns_latency[i] ); + + if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp_comp" ) ) + goto fail; + } + + for ( i = 0; i < this_loops; i++ ) + { + PCPS_TIME_STAMP *p_prv_ts = i ? &ts[i - 1] : NULL; + mbg_print_hr_timestamp( &ts[i], hns_latency[i], p_prv_ts, read_raw, 0 ); // raw timestamp? + } + + return 0; + + +fail: + return -1; + +} // show_fast_hr_timestamp_burst + + + +static /*HDR*/ +int do_mbgfasttstamp( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) +{ + int supported = 0; + int rc = mbg_dev_has_fast_hr_timestamp( dh, &supported ); + + if ( mbg_ioctl_err( rc, "mbg_has_fast_hr_timestamp" ) ) + goto done; + + if ( !supported ) + { + printf( "This device does not support fast (memory mapped) time stamps.\n" ); + goto done; + } + + if ( burst_read ) + show_fast_hr_timestamp_burst( dh ); + else + show_fast_hr_timestamp( dh ); + +done: + mbg_close_device( &dh ); + + return rc; + +} // do_mbgfasttstamp + + + +static /*HDR*/ +void usage( void ) +{ + mbg_print_usage_intro( pname, + "This example program reads fast high resolution time stamps.\n" + "\n" + "This is done using memory mapped I/O in the kernel driver, so\n" + "this works only with cards which support memory mapped I/O." + ); + mbg_print_help_options(); + mbg_print_opt_info( "-c", "run continuously" ); + mbg_print_opt_info( "-n num", "run num loops" ); + mbg_print_opt_info( "-b", "burst read" ); + mbg_print_opt_info( "-r", "read raw time stamps, no cycles" ); + mbg_print_opt_info( "-s num", "sleep num seconds between calls" ); + mbg_print_opt_info( "-u num", "sleep num microseconds between calls" ); + mbg_print_device_options(); + puts( "" ); + +} // usage + + + +int main( int argc, char *argv[] ) +{ + int rc; + int c; + + mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); + + // check command line parameters + while ( ( c = getopt( argc, argv, "bcn:rs:u:h?" ) ) != -1 ) + { + switch ( c ) + { + case 'b': + burst_read = 1; + break; + + case 'c': + loops = -1; + break; + + case 'n': + loops = atoi( optarg ); + break; + + case 'r': + read_raw = 1; + break; + + case 's': + sleep_secs = atoi( optarg ); + break; + + case 'u': + sleep_usecs = atoi( optarg ); + break; + + case 'h': + case '?': + default: + must_print_usage = 1; + } + } + + if ( must_print_usage ) + { + usage(); + return 1; + } + + #if !MBG_TGT_SUPP_MEM_ACC + printf( "** Memory mapped access not supported on this target platform.\n\n" ); + return 1; + #endif + + #if !MBG_PC_CYCLES_SUPPORTED + printf( "** Warning: No cycles support to compute real latencies on this platform!\n" ); + + if ( !read_raw ) + { + read_raw = 1; + printf( "** Falling back to raw mode.\n" ); + } + + printf( "\n" ); + #endif + + // The function below checks which devices have been specified + // on the command, and for each device + // - tries to open the device + // - shows basic device info + // - calls the function passed as last parameter + rc = mbg_check_devices( argc, argv, optind, do_mbgfasttstamp ); + + return abs( rc ); +} diff --git a/mbggpscap/mbggpscap.c b/mbggpscap/mbggpscap.c new file mode 100644 index 0000000..8dc8b53 --- /dev/null +++ b/mbggpscap/mbggpscap.c @@ -0,0 +1,412 @@ + +/************************************************************************** + * + * $Id: mbggpscap.c 1.10.1.7 2013/04/10 15:40:28Z martin TEST martin $ + * + * Description: + * Main file for mbggpscap program which demonstrates how to access + * a Meinberg device via IOCTL calls and read entries from the time + * capture FIFO buffer. + * + * Please note that this may only work with devices which provide + * time capture input(s). + * + * ----------------------------------------------------------------------- + * $Log: mbggpscap.c $ + * Revision 1.10.1.7 2013/04/10 15:40:28Z martin + * Revision 1.10.1.6 2011/09/09 08:28:22Z martin + * Revision 1.10.1.5 2011/09/07 15:12:33 martin + * New option -r which displays raw timestamps and raw status. + * New option -o which forces usage of old API. + * Fixed a bug when displaying the capture event status. TTM and PCPS_HR_TIME + * are using different sets of status flags. + * Revision 1.10.1.4 2011/07/05 15:35:54 martin + * Modified version handling. + * Revision 1.10.1.3 2011/07/05 14:35:18 martin + * New way to maintain version information. + * Revision 1.10.1.2 2010/11/12 12:27:17 martin + * Improved reading capture events arriving at a high rate. + * Support validation of capture signals arriving at a constant rate. + * Revision 1.10.1.1 2010/03/10 16:42:33 martin + * Improved code execution paths. + * Revision 1.10 2009/09/29 15:02:15 martin + * Updated version number to 3.4.0. + * Revision 1.9 2009/07/24 09:50:08 martin + * Updated version number to 3.3.0. + * Revision 1.8 2009/06/19 12:38:51 martin + * Updated version number to 3.2.0. + * Revision 1.7 2009/03/19 17:04:26 martin + * Updated version number to 3.1.0. + * Updated copyright year to include 2009. + * Revision 1.6 2008/12/22 12:00:55 martin + * Updated description, copyright, revision number and string. + * Use unified functions from toolutil module. + * Accept device name(s) on the command line. + * Don't use printf() without format, which migth produce warnings + * with newer gcc versions. + * Revision 1.5 2007/07/24 09:32:26 martin + * Updated copyright to include 2007. + * Revision 1.4 2006/02/22 15:29:17 martin + * Support new ucap API. + * Print an error message if device can't be opened. + * Revision 1.3 2004/11/08 15:47:10 martin + * Using type cast to avoid compiler warning. + * Revision 1.2 2003/04/25 10:28:05 martin + * Use new functions from mbgdevio library. + * New program version v2.1. + * Revision 1.1 2001/09/17 15:08:22 martin + * + **************************************************************************/ + +// include Meinberg headers +#include <mbgdevio.h> +#include <pcpsutil.h> +#include <toolutil.h> // common utility functions + +// include system headers +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + + +#define USLEEP_INTV 10000 // [microseconds] + + +#define MBG_MICRO_VERSION 0 +#define MBG_FIRST_COPYRIGHT_YEAR 2001 +#define MBG_LAST_COPYRIGHT_YEAR 0 // use default + +static const char *pname = "mbggpscap"; + + +static int continuous; +static double nom_cap_intv; // nominal capture interval to check [s] +static double max_cap_jitter; // max allowed jitter [s] +static int raw; +static int force_old_api; + +static int has_been_called; +static int must_check_intv; +static ulong err_cnt; +static PCPS_HR_TIME prv_ucap; + + + +static /*HDR*/ +void show_ucap_event( const PCPS_HR_TIME *ucap ) +{ + char ws[80]; + + // Print converted date and time to a string: + mbg_snprint_hr_time( ws, sizeof( ws ), ucap, raw ); + + // Print the time stamp, ucap->signal contains the channel number: + printf( "New capture: CH%i: %s", ucap->signal, ws ); + + if ( must_check_intv && has_been_called ) + { + double abs_delta; + double d = ucap->tstamp.sec - prv_ucap.tstamp.sec; + d += ( (double) ucap->tstamp.frac - prv_ucap.tstamp.frac ) / PCPS_HRT_BIN_FRAC_SCALE; + + printf( " %+.6f", d ); + + abs_delta = d - nom_cap_intv; + + if ( abs_delta < 0.0 ) + abs_delta = -abs_delta; + + if ( abs_delta > max_cap_jitter ) + err_cnt++; + + if ( err_cnt ) + printf( " ** %lu", err_cnt ); + } + + // status bit definitions can be found in pcpsdefs.h. + + if ( raw ) + printf( ", st: 0x%04X", ucap->status ); + + if ( ucap->status & PCPS_UCAP_OVERRUN ) // capture events have occurred too fast + printf( " << CAP OVR" ); + + if ( ucap->status & PCPS_UCAP_BUFFER_FULL ) // capture buffer has been full, events lost + printf( " << BUF OVR" ); + + prv_ucap = *ucap; + has_been_called = 1; + + printf( "\n" ); + +} // show_ucap_event + + + +// The function below is normally outdated, and show_ucap_event() +// above should be used if possible, together with the associated +// API calls. + +static /*HDR*/ +void show_gps_ucap( const TTM *ucap ) +{ + printf( "New capture: CH%i: %04i-%02i-%02i %2i:%02i:%02i.%07li", + ucap->channel, + ucap->tm.year, + ucap->tm.month, + ucap->tm.mday, + ucap->tm.hour, + ucap->tm.min, + ucap->tm.sec, + (ulong) ucap->tm.frac + ); + + if ( raw ) + printf( ", st: 0x%04lX", (ulong) ucap->tm.status ); + + printf( "\n" ); + +} // show_gps_ucap + + + +static /*HDR*/ +void check_serial_mode( MBG_DEV_HANDLE dh ) +{ + PORT_PARM port_parm; + int i; + int must_modify = 0; + + // read the clock's current port settings + int rc = mbg_get_gps_port_parm( dh, &port_parm ); + + if ( mbg_ioctl_err( rc, "mbg_get_gps_port_parm" ) ) + return; + + + // If one of the ports has been set to send user captures + // then the user capture buffer will most often be empty + // if we check for captures, so modify the port mode. + for ( i = 0; i < N_COM; i++ ) + { + if ( port_parm.mode[i] == STR_UCAP ) + { + port_parm.mode[i] = STR_UCAP_REQ; + must_modify = 1; + } + } + + if ( !must_modify ) + return; + + + rc = mbg_set_gps_port_parm( dh, &port_parm ); + + if ( mbg_ioctl_err( rc, "mbg_set_gps_port_parm" ) ) + return; + + printf( "NOTE: the clock's serial port mode has been changed.\n" ); + +} // check_serial_mode + + + +static /*HDR*/ +int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) +{ + int rc; + + must_check_intv = continuous && ( nom_cap_intv != 0 ); + has_been_called = 0; + err_cnt = 0; + + if ( !_pcps_has_ucap( p_dev ) && !_pcps_is_gps( p_dev ) ) + { + printf( "This device type does not provide time capture inputs.\n" ); + return 0; + } + + check_serial_mode( dh ); + + printf( "Be sure the card has been properly configured to enable capture inputs.\n" ); + + // There's an older API which has been introduced with the first GPS boards + // and uses the TTM structure to return the capture events. However, that + // API call is slow and not very flexible, so a new set of API calls has been + // introduced to handle capture events. + // The new API calls are supported by all supported by all newer boards which + // provide user capture inputs, and also for older boards with a firmware update. + + if ( !force_old_api && _pcps_has_ucap( p_dev ) ) // check if the new API is supported + { + // The new API provides the following functions: + // mbg_clr_ucap_buff() clear the on-board FIFO buffer + // mbg_get_ucap_entries() get the max number of FIFO entries, and the current number of entries + // mbg_get_ucap_event() read one entry from the FIFO + + PCPS_UCAP_ENTRIES ucap_entries; + + // retrieve and print information of the maximum number of events that can + // be stored in the on-board FIFO, and the number of events that are currently + // stored + rc = mbg_get_ucap_entries( dh, &ucap_entries ); + + if ( rc == MBG_SUCCESS ) + { + // Cards report they could save one more capture event + // than they actually do save, so adjust the reported value + // for a proper display. + if ( ucap_entries.max ) + ucap_entries.max--; + + printf( "\nOn-board FIFO: %u of %u entries used\n\n", + ucap_entries.used, ucap_entries.max ); + } + + // If the program is not to run continuously and no + // capture events are available then we're through. + if ( !continuous && ucap_entries.used == 0 ) + return 0; + + + printf( ( ucap_entries.used == 0 ) ? + "Waiting for capture events:\n" : + "Reading capture events:\n" + ); + + // Now read out all events from the FIFO and wait + // for new events if the FIFO is empty. + for (;;) + { + PCPS_HR_TIME ucap_event; + + rc = mbg_get_ucap_event( dh, &ucap_event ); + + if ( mbg_ioctl_err( rc, "mbg_get_ucap_event" ) ) + break; // an error has occurred + + // If a user capture event has been read then it + // has been removed from the card's FIFO buffer. + + // If the time stamp is not 0 then a new capture event has been retrieved. + if ( ucap_event.tstamp.sec || ucap_event.tstamp.frac ) + { + show_ucap_event( &ucap_event ); + continue; + } + + usleep( USLEEP_INTV ); // sleep, then try again + } + } + else // use the old API + { + printf( "Checking for capture events using the old API:\n" ); + + for (;;) + { + TTM ucap_ttm; + + rc = mbg_get_gps_ucap( dh, &ucap_ttm ); + + if ( mbg_ioctl_err( rc, "mbg_get_gps_ucap" ) ) + break; // an error has occurred + + + // If a user capture event has been read then it + // has been removed from the card's FIFO buffer. + + // If a new capture event has been available then + // the ucap.tm contains a time stamp. + if ( _pcps_time_is_read( &ucap_ttm.tm ) ) + show_gps_ucap( &ucap_ttm ); + + if ( !continuous ) + { + printf( "No capture event available!\n" ); + break; + } + + usleep( USLEEP_INTV ); // sleep, then try again + } + } + + return 0; + +} // do_mbggpscap + + + +static /*HDR*/ +void usage( void ) +{ + mbg_print_usage_intro( pname, + "This example program reads time capture events from a card.\n" + "This works only with cards which provide time capture inputs." + ); + mbg_print_help_options(); + mbg_print_opt_info( "-c", "run continuously" ); + mbg_print_opt_info( "-i val", "check interval between captures events [s]" ); + mbg_print_opt_info( "-j val", "max allowed jitter of capture interval [s]" ); + mbg_print_opt_info( "-r", "show raw (hex) timestamp and status)" ); + mbg_print_opt_info( "-o", "force usage of old API (for testing only)" ); + mbg_print_device_options(); + puts( "" ); + +} // usage + + + +int main( int argc, char *argv[] ) +{ + int rc; + int c; + + mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); + + // check command line parameters + while ( ( c = getopt( argc, argv, "ci:j:roh?" ) ) != -1 ) + { + switch ( c ) + { + case 'c': + continuous = 1; + break; + + case 'i': + nom_cap_intv = atof( optarg ); + break; + + case 'j': + max_cap_jitter = atof( optarg ); + break; + + case 'r': + raw = 1; + break; + + case 'o': + force_old_api = 1; + break; + + case 'h': + case '?': + default: + must_print_usage = 1; + } + } + + if ( must_print_usage ) + { + usage(); + return 1; + } + + // The function below checks which devices have been specified + // on the command, and for each device + // - tries to open the device + // - shows basic device info + // - calls the function passed as last parameter + rc = mbg_check_devices( argc, argv, optind, do_mbggpscap ); + + return abs( rc ); +} diff --git a/mbghrtime/mbghrtime.c b/mbghrtime/mbghrtime.c new file mode 100644 index 0000000..cf71778 --- /dev/null +++ b/mbghrtime/mbghrtime.c @@ -0,0 +1,323 @@ + +/************************************************************************** + * + * $Id: mbghrtime.c 1.11.1.10 2013/04/10 15:40:29Z martin TEST martin $ + * + * Description: + * Main file for mbghrtime program which demonstrates how to access + * a Meinberg device via IOCTL calls to read high resolution + * time stamps, if supported by the device. + * + * ----------------------------------------------------------------------- + * $Log: mbghrtime.c $ + * Revision 1.11.1.10 2013/04/10 15:40:29Z martin + * Revision 1.11.1.9 2011/12/19 16:13:46Z martin + * Revision 1.11.1.8 2011/09/29 16:28:34 martin + * New options -s, -u, -v. + * Print time using new function mbg_print_hr_time(). + * Revision 1.11.1.7 2011/09/07 15:08:55 martin + * Account for modified library functions which can now + * optionally print the raw (hex) HR time stamp. + * Revision 1.11.1.6 2011/07/05 15:35:54 martin + * Modified version handling. + * Revision 1.11.1.5 2011/07/05 14:35:18 martin + * New way to maintain version information. + * Revision 1.11.1.4 2011/01/28 12:04:08 martin + * Revision 1.11.1.3 2011/01/28 11:52:51 martin + * Revision 1.11.1.2 2011/01/28 11:51:13 martin + * Revision 1.11.1.1 2011/01/28 11:17:33 martin + * Starrted to support raw and burst. + * Revision 1.11 2010/05/21 12:54:33 martin + * Print warning if no cycles supported on the target platform + * and thus latencies can not be computed. + * Revision 1.10 2009/09/29 15:02:15 martin + * Updated version number to 3.4.0. + * Revision 1.9 2009/07/24 09:50:08 martin + * Updated version number to 3.3.0. + * Revision 1.8 2009/06/19 14:03:53 martin + * Use common mbg_print_hr_timestamp() for unified output format. + * Updated version number to 3.2.0. + * Revision 1.7 2009/03/20 11:45:16 martin + * Updated version number to 3.1.0. + * Updated copyright year to include 2009. + * Call mbg_get_hr_time_comp() instead of mbg_get_hr_time_cycles(). + * Revision 1.6 2008/12/22 12:02:00 martin + * Updated description, copyright, revision number and string. + * Use unified functions from toolutil module. + * Accept device name(s) on the command line. + * Revision 1.5 2007/07/24 09:32:41 martin + * Updated copyright to include 2007. + * Revision 1.4 2004/11/08 15:45:22 martin + * Modifications to support 64 bit systems in a clean way. + * Revision 1.3 2003/04/25 10:28:05 martin + * Use new functions from mbgdevio library. + * New program version v2.1. + * Revision 1.2 2001/11/30 10:01:49 martin + * Account for the modified definition of PCPS_HR_TIME which + * uses the new structure PCPS_TIME_STAMP now. + * Revision 1.1 2001/09/17 15:08:31 martin + * + **************************************************************************/ + +// include Meinberg headers +#include <mbgdevio.h> +#include <pcpsutil.h> +#include <toolutil.h> // common utility functions + +// include system headers +#include <time.h> +#include <stdio.h> +#include <stdlib.h> + + + +#define MBG_MICRO_VERSION 0 +#define MBG_FIRST_COPYRIGHT_YEAR 2001 +#define MBG_LAST_COPYRIGHT_YEAR 0 // use default + +static const char *pname = "mbghrtime"; + + +#define MAX_TS_BURST 1000 + +static int loops; +static int burst_read; +static int read_raw; +static long sleep_secs; +static long sleep_usecs; +static int verbose; + + + +// The function below reads a number of time stamps and prints +// each timestamp immediately. This is not as fast as possible +// since printing the time stamp takes some time to execute. +// However, this can run continuously forever. + +static /*HDR*/ +int show_hr_timestamp( MBG_DEV_HANDLE dh ) +{ + PCPS_HR_TIME ht = { { 0 } }; + PCPS_HR_TIME prv_ht = { { 0 } }; + PCPS_TIME_STAMP *p = NULL; + int32_t hns_latency = 0; + int this_loops = loops; + + for (;;) + { + int rc = read_raw ? mbg_get_hr_time( dh, &ht ) : + mbg_get_hr_time_comp( dh, &ht, &hns_latency ); + + if ( mbg_ioctl_err( rc, "mbg_get_hr_time_..." ) ) + goto fail; + + mbg_print_hr_time( &ht, hns_latency, p, read_raw, verbose, verbose ); + + prv_ht = ht; + p = &prv_ht.tstamp; + + if ( this_loops > 0 ) + this_loops--; + + if ( this_loops == 0 ) + break; + + if ( sleep_secs ) + sleep( sleep_secs ); + else + if ( sleep_usecs ) + usleep( sleep_usecs ); + + // if this_loops is < 0 then loop forever + } + + return 0; + +fail: + return -1; + +} // show_hr_timestamp + + + +// The function below takes a number of time stamps and saves +// them to a buffer. After the time stamps have been read +// a second loop prints the time stamps from the buffer. +// This way the time stamps are read in shorter intervals. +// However, this can not run continuously forever since +// the buffer size is somewhat limited. + +static /*HDR*/ +int show_hr_timestamp_burst( MBG_DEV_HANDLE dh ) +{ + PCPS_HR_TIME ht[MAX_TS_BURST] = { { { 0 } } }; + int32_t hns_latency[MAX_TS_BURST]; + int this_loops; + int i; + + this_loops = ( loops && ( loops < MAX_TS_BURST ) ) ? loops : MAX_TS_BURST; + + + if ( read_raw ) + { + for ( i = 0; i < this_loops; i++ ) + { + int rc = mbg_get_hr_time( dh, &ht[i] ); + + if ( mbg_ioctl_err( rc, "mbg_get_hr_time" ) ) + goto fail; + } + } + else + for ( i = 0; i < this_loops; i++ ) + { + int rc = mbg_get_hr_time_comp( dh, &ht[i], &hns_latency[i] ); + + if ( mbg_ioctl_err( rc, "mbg_get_hr_time_comp" ) ) + goto fail; + } + + for ( i = 0; i < this_loops; i++ ) + { + PCPS_HR_TIME *p_prv_ht = i ? &ht[i - 1] : NULL; + mbg_print_hr_time( &ht[i], hns_latency[i], &p_prv_ht->tstamp, read_raw, verbose, verbose ); + } + + return 0; + + +fail: + return -1; + +} // show_hr_timestamp_burst + + + +static /*HDR*/ +int do_mbghrtime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) +{ + int supported = 0; + int rc = mbg_dev_has_hr_time( dh, &supported ); + + if ( mbg_ioctl_err( rc, "mbg_dev_has_hr_time" ) ) + goto done; + + if ( !supported ) + { + printf( "High resolution time not supported by this device.\n" ); + goto done; + } + + if ( burst_read ) + show_hr_timestamp_burst( dh ); + else + show_hr_timestamp( dh ); + +done: + mbg_close_device( &dh ); + + return rc; + +} // do_mbghrtime + + + +static /*HDR*/ +void usage( void ) +{ + mbg_print_usage_intro( pname, + "This example program reads high resolution time stamps (HR time)\n" + "from a device.\n" + "This works only for devices which support high resolution time (HR time)." + ); + mbg_print_help_options(); + mbg_print_opt_info( "-c", "run continuously" ); + mbg_print_opt_info( "-n num", "run num loops" ); + mbg_print_opt_info( "-b", "burst read" ); + mbg_print_opt_info( "-r", "read raw time stamps, no cycles" ); + mbg_print_opt_info( "-s num", "sleep num seconds between calls" ); + mbg_print_opt_info( "-u num", "sleep num microseconds between calls" ); + mbg_print_opt_info( "-v", "increase verbosity" ); + mbg_print_device_options(); + puts( "" ); + +} // usage + + + +int main( int argc, char *argv[] ) +{ + int rc; + int c; + + mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); + + // check command line parameters + while ( ( c = getopt( argc, argv, "bcn:rs:u:vh?" ) ) != -1 ) + { + switch ( c ) + { + case 'b': + burst_read = 1; + break; + + case 'c': + loops = -1; + break; + + case 'n': + loops = atoi( optarg ); + break; + + case 'r': + read_raw = 1; + break; + + case 's': + sleep_secs = atoi( optarg ); + break; + + case 'u': + sleep_usecs = atoi( optarg ); + break; + + case 'v': + verbose++; + break; + + case 'h': + case '?': + default: + must_print_usage = 1; + } + } + + if ( must_print_usage ) + { + usage(); + return 1; + } + + + #if !MBG_PC_CYCLES_SUPPORTED + printf( "** Warning: No cycles support to compute real latencies on this platform!\n" ); + + if ( !read_raw ) + { + read_raw = 1; + printf( "** Falling back to raw mode.\n" ); + } + + printf( "\n" ); + #endif + + + // The function below checks which devices have been specified + // on the command, and for each device + // - tries to open the device + // - shows basic device info + // - calls the function passed as last parameter + rc = mbg_check_devices( argc, argv, optind, do_mbghrtime ); + + return abs( rc ); +} diff --git a/mbglib/common/cfg_hlp.h b/mbglib/common/cfg_hlp.h new file mode 100644 index 0000000..a485d98 --- /dev/null +++ b/mbglib/common/cfg_hlp.h @@ -0,0 +1,127 @@ + +/************************************************************************** + * + * $Id: cfg_hlp.h 1.2 2012/10/02 18:16:26Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for configuration programs. + * + * ----------------------------------------------------------------------- + * $Log: cfg_hlp.h $ + * Revision 1.2 2012/10/02 18:16:26Z martin + * Modified some typedefs to be more compliant with the underlying types. + * Revision 1.1 2011/09/21 15:59:59 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _CFG_HLP_H +#define _CFG_HLP_H + + +/* Other headers to be included */ + +#include <gpsdefs.h> + + +#ifdef _CFG_HLP + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * The definitions and types below are used to collect + * all configuration parameters of a clock's serial ports + * that can be handled by this library: + */ + + +/* + * The maximum number of clocks' serial ports and string types + * that can be handled by the configuration programs. + * WARNING: Changing these constants affects the size of the + * structures ALL_PORT_INFO ALL_STR_TYPE_INFO + */ +#define MAX_PARM_PORT 4 +#define MAX_PARM_STR_TYPE 20 + +typedef PORT_INFO_IDX ALL_PORT_INFO_IDX[MAX_PARM_PORT]; +typedef STR_TYPE_INFO_IDX ALL_STR_TYPE_INFO_IDX[MAX_PARM_STR_TYPE]; + +typedef struct +{ + ALL_PORT_INFO_IDX pii; + ALL_STR_TYPE_INFO_IDX stii; + PORT_PARM tmp_pp; + +} RECEIVER_PORT_CFG; + + +/* + * The definitions and types below are used to collect + * all configuration parameters of a clock's programmable + * pulse outputs that can be handled by this library: + */ + +#define MAX_PARM_POUT 4 + +#if 1 //##+++++++++++++++++++++++ + +typedef POUT_INFO_IDX ALL_POUT_INFO_IDX[MAX_PARM_POUT]; + +#else + +typedef struct +{ + POUT_INFO_IDX pii[MAX_PARM_POUT]; +} POUT_CFG; + +#endif + + +/* + * The definitions and types below are used to collect + * all configuration parameters of PTP device's unicast + * master specification: + */ + +#define MAX_PARM_PTP_UC_MASTER 3 + +typedef PTP_UC_MASTER_INFO_IDX ALL_PTP_UC_MASTER_INFO_IDX[MAX_PARM_PTP_UC_MASTER]; + + + + +/* function prototypes: */ + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _CFG_HLP_H */ diff --git a/mbglib/common/cnv_wday.h b/mbglib/common/cnv_wday.h new file mode 100644 index 0000000..7736135 --- /dev/null +++ b/mbglib/common/cnv_wday.h @@ -0,0 +1,100 @@ + +/***************************************************************************/ +/* */ +/* File: CNV_WDAY.H $Revision: 1.1 $ */ +/* */ +/* Project: Common C Library */ +/* */ +/* Compiler: Borland C++ and others */ +/* */ +/* Author: M. Burnicki, Meinberg Funkuhren */ +/* */ +/* */ +/* Description: */ +/* This header provides macros which can be used to convert */ +/* day-of-week codes from one convention to another. */ +/* */ +/* The conventions supported yet have been named as describrd below: */ +/* */ +/* name range assignment used with ... */ +/* ---------------------------------------------------------------- */ +/* sun06 0..6 0 = Sunday RTC72421, DOS1.10+, Novell */ +/* sun17 1..7 1 = Sunday RTC146818 */ +/* mon17 1..7 1 = Monday DCF77 */ +/* */ +/***************************************************************************/ + + +#ifndef _CNV_WDAY_H + + +/* Other headers to be included */ + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _CNV_WDAY + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + + +/* use the following macros if sure that the source value is in range */ + +#define _wday_mon17_to_mon06( d ) ( ( d ) - 1 ) +#define _wday_mon06_to_mon17( d ) ( ( d ) + 1 ) + +#define _wday_mon17_to_sun17( d ) ( ( (d) >= 7 ) ? 1 : ( (d) + 1 ) ) +#define _wday_sun17_to_mon17( d ) ( ( (d) < 2 ) ? 7 : ( (d) - 1 ) ) + +#define _wday_mon17_to_sun06( d ) ( ( (d) >= 7 ) ? 0 : (d) ) +#define _wday_sun06_to_mon17( d ) ( ( (d) < 1 ) ? 7 : (d) ) + +#define _wday_sun17_to_sun06( d ) ( (d) - 1 ) +#define _wday_sun06_to_sun17( d ) ( (d) + 1 ) + + +/* use the macros below to check for valid ranges */ + +#define _inrng( d, what, min, lt, max, gt ) ( ( (d) < (min) ) ? (lt) : ( ( (d) > (max) ) ? (gt) : (what) ) ) + /* _inrng is a local macro which does the boundary check */ + /* d the day code to be converted */ + /* what the conversion algorithm if in range */ + /* min, lt if (d) is below (min), the macro returns (lt) */ + /* max, gt if (d) is above (max), the macro returns (gt) */ + +#define _wday_chk_mon17_to_sun17( d ) _inrng( (d), _wday_mon17_to_sun17( (d) ), 1, 7, 7, 6 ) +#define _wday_chk_sun17_to_mon17( d ) _inrng( (d), _wday_sun17_to_mon17( (d) ), 1, 7, 7, 6 ) + + +#define _wday_chk_mon17_to_sun06( d ) _inrng( (d), _wday_mon17_to_sun06( (d) ), 1, 1, 7, 0 ) +#define _wday_chk_sun06_to_mon17( d ) _inrng( (d), _wday_sun06_to_mon17( (d) ), 0, 1, 6, 6 ) + +#define _wday_chk_sun17_to_sun06( d ) _inrng( (d), _wday_sun17_to_sun06( (d) ), 1, 0, 7, 6 ) +#define _wday_chk_sun06_to_sun17( d ) _inrng( (d), _wday_sun06_to_sun17( (d) ), 0, 1, 6, 7 ) + + +/* function prototypes: */ + +/* #include <CNV_WDAY.hdr> not needed yet */ + +/* End of header body */ + + +#undef _ext + +#ifdef __cplusplus +} +#endif + +#define _CNV_WDAY_H + +#endif /* _CNV_WDAY_H */ + diff --git a/mbglib/common/ctry.c b/mbglib/common/ctry.c new file mode 100644 index 0000000..c726f22 --- /dev/null +++ b/mbglib/common/ctry.c @@ -0,0 +1,176 @@ + +/************************************************************************** + * + * $Id: ctry.c 1.7 2010/07/15 08:26:57Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Functions providing support for different country settings + * and languages. + * + * Some OS dependent functions may be required which can be found + * in the OS dependent modules ctry_xxx.c. + * + * ----------------------------------------------------------------------- + * $Log: ctry.c $ + * Revision 1.7 2010/07/15 08:26:57Z martin + * Added clstr_lng() implemented by stefan returning a translated string + * by giving the different strings as function arguments. + * Revision 1.6 2007/03/29 12:21:51 martin + * New functions lstr_idx() and lstr_array_idx(). + * Revision 1.5 2004/10/26 07:39:37Z martin + * Use C99 fixed-size definitions where appropriate. + * Revision 1.4 2001/09/14 12:02:12 MARTIN + * Modified parameters for lstr_lng(). + * Revision 1.3 2000/11/27 14:09:24 MARTIN + * Replaced lstr() by lstr_lng() with takes a language paramter to allow + * retrieval of strings for another than the current language. + * A new macro _lstr() has been added to ctry.h which calls lstr_lng() + * passing the current language. + * The functions ctry_fmt_dt() and ctry_fmt_times() and associated + * definitions have been moved to a new module ctry_fmt.c/ctry_fmt.h. + * Revision 1.2 2000/07/21 10:00:08 MARTIN + * Initial revision + * + **************************************************************************/ + +#define _CTRY + #include <ctry.h> +#undef _CTRY + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + + +// Return the index of a CLSTR component for a +// certain language lng + +/*HDR*/ +int lstr_idx( CLSTR s, int lng ) +{ + if ( lng >= N_LNG ) // if lng out of range + return 0; // use default index + + // If there are duplicate strings for several languages + // then the duplicate strings may be NULL, in which case + // the string at index 0 must be used. + return s[lng] ? lng : 0; + +} // lstr_idx + + + +// Return the index of a CLSTR component for a +// certain language lng out of an array of CLSTRs. +// CLSTR s: the array of CLSTRs +// int idx: the index of the array element +// int n_lng: the number of supported languages +// int lng: the language for which the inex shall be retrieved + +/*HDR*/ +int lstr_array_idx( CLSTR s, int idx, int n_lng, int lng ) +{ + int str_idx = n_lng * idx; + return str_idx + lstr_idx( &s[str_idx], lng ); + +} // lstr_array_idx + + + +/*HDR*/ +const char *lstr_lng( CLSTR s, int lng ) +{ + return s[lstr_idx( s, lng)]; + +} // lstr_lng + + + +/*HDR*/ +void ctry_setup( CTRY_CODE code ) +{ + language = LNG_ENGLISH; + ctry.code = code; + + switch ( code ) + { + case CTRY_US: + ctry.dt_fmt = DT_FMT_MMDDYYYY; + ctry.dt_sep = DT_SEP_MINUS; + ctry.tm_fmt = TM_FMT_24H; + ctry.tm_sep = TM_SEP_COLON; + break; + + + case CTRY_UK: + ctry.dt_fmt = DT_FMT_DDMMYYYY; + ctry.dt_sep = DT_SEP_SLASH; + ctry.tm_fmt = TM_FMT_24H; + ctry.tm_sep = TM_SEP_COLON; + break; + + + default: + language = LNG_GERMAN; + ctry.code = CTRY_GERMANY; + + ctry.dt_fmt = DT_FMT_DDMMYYYY; + ctry.dt_sep = DT_SEP_DOT; + ctry.tm_fmt = TM_FMT_24H; + ctry.tm_sep = TM_SEP_COLON; + + } /* switch */ + + +} /* ctry_setup */ + + + +/*HDR*/ +void ctry_next( void ) +{ + switch ( ctry.code ) + { + case CTRY_GERMANY: + ctry_setup( CTRY_US ); + break; + + case CTRY_US: + ctry_setup( CTRY_UK ); + break; + + default: + ctry_setup( CTRY_GERMANY ); + break; + + } // switch + +} // ctry_next + + + +/*HDR*/ +const char *clstr_lng( int index, ... ) +{ + const char *ret; + const char *default_ret; + int i; + typedef char *MY_LSTR; + + va_list ap; + va_start( ap, index ); + + ret = va_arg( ap, MY_LSTR ); + default_ret = ret; + + for ( i = 1; ( i <= index ) && ( ret != NULL ); i++ ) + ret = va_arg( ap, MY_LSTR ); + + va_end( ap ); + + return ret ? ret : default_ret; + +} // clstr_lng + diff --git a/mbglib/common/ctry.h b/mbglib/common/ctry.h new file mode 100644 index 0000000..f66b817 --- /dev/null +++ b/mbglib/common/ctry.h @@ -0,0 +1,239 @@ + +/************************************************************************** + * + * $Id: ctry.h 1.13 2012/11/29 12:01:09Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for ctry.c. + * + * ----------------------------------------------------------------------- + * $Log: ctry.h $ + * Revision 1.13 2012/11/29 12:01:09Z martin + * Don't include mbg_tgt.h explicitely since this will anyway be + * included by words.h for non-firmware targets. So mbg_tgt.h + * must not necessarily be added to firmware projects. + * Revision 1.12 2011/06/22 07:37:57Z martin + * Cleaned up handling of pragma pack(). + * Revision 1.11 2010/07/15 08:33:41 martin + * Added some macros implemented by Stefan. + * Updated function prototypes. + * Revision 1.10 2007/03/29 12:21:10 martin + * Updated function prototypes. + * Revision 1.9 2004/10/26 07:38:50Z martin + * Redefined interface data types using C99 fixed-size definitions. + * Updated function prototypes. + * Revision 1.8 2004/04/14 08:47:28 martin + * Pack structures 1 byte aligned. + * Revision 1.7 2002/02/19 09:28:00Z MARTIN + * Use new header mbg_tgt.h to check the target environment. + * Revision 1.6 2001/09/14 12:04:40 MARTIN + * Modified definition for CLSTR. + * Updated function prototypes. + * Revision 1.5 2001/02/28 15:07:06 MARTIN + * Modified preprocessor syntax. + * Revision 1.4 2000/11/27 14:13:27 MARTIN + * New types CLSTR, PLSTR, and PCLSTR. + * New macro _lstr() calls lstr_lng() for the current language. + * Definitions associated with ctry_fmt_dt() and ctry_fmt_times() + * have been moved to a new file ctry_fmt.h. + * Updated function prototypes. + * Revision 1.3 2000/08/17 15:35:02 MARTIN + * No init function by default (previously DOS), + * Revision 1.2 2000/07/21 09:48:34 MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _CTRY_H +#define _CTRY_H + + +/* Other headers to be included */ + +#include <words.h> + +#if defined( MBG_TGT_NETWARE ) + #include <ctry_nw.h> +#elif defined( MBG_TGT_OS2 ) + #include <ctry_os2.h> +#elif defined( MBG_TGT_WIN32 ) + // #include <ctry_w32.h> +#elif defined( MBG_TGT_LINUX ) + // #include <ctry_lx.h> +#elif defined( MBG_TGT_DOS ) + #include <ctry_dos.h> +#else + // nothing to include for C166 etc. +#endif + +#include <use_pack.h> + + +#ifdef _CTRY + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +// the definitions below are used to support different languages: +typedef uint8_t LANGUAGE; +typedef uint16_t CTRY_CODE; + +// codes used with LANGUAGE: +#if !defined LNG_DEFINED + enum + { + LNG_ENGLISH, + LNG_GERMAN, + N_LNG + }; + + #define LNG_DEFINED +#endif + +// the type below is used to declare string variables +// for several languages +typedef char *LSTR[N_LNG]; // array of strings +typedef char **PLSTR; // pointer to array + +// same as above, but const +typedef const char * const CLSTR[N_LNG]; // array of strings +typedef const char * const *PCLSTR; // pointer to array + + +// the definitions below are used to handle date and time +// formats used by different countries: +typedef struct +{ + CTRY_CODE code; + + uint8_t dt_fmt; // (codes defined below) + uint8_t tm_fmt; // (codes defined below) + char dt_sep; // (valid chars defined below) + char tm_sep; // (valid chars defined below) +} CTRY; + + +// codes used with CTRY.code: +#define CTRY_US 1 +#define CTRY_UK 44 +#define CTRY_GERMANY 49 + + +#ifndef CTRY_DEFINED + + #define CTRY_DEFINED + + // codes used with CTRY.dt_fmt: + enum + { + DT_FMT_DDMMYYYY, + DT_FMT_MMDDYYYY, + DT_FMT_YYYYMMDD, + N_DT_FMT + }; + + // codes used with CTRY.tm_fmt: + enum + { + TM_FMT_24H, + // TM_FMT_12H, // not yet supported + N_TM_FMT + }; + + + // codes used with CTRY.dt_sep: + #define DT_SEP_DOT '.' + #define DT_SEP_MINUS '-' + #define DT_SEP_SLASH '/' + + // a zero-terminated list of valid dt_sep characters + #define DT_SEP_LIST { DT_SEP_DOT, DT_SEP_MINUS, DT_SEP_SLASH, 0 } + + + // codes used with CTRY.tm_sep: + #define TM_SEP_COLON ':' + #define TM_SEP_DOT '.' + + // a zero-terminated list of valid tm_sep characters + #define TM_SEP_LIST { TM_SEP_COLON, TM_SEP_DOT, 0 } + +#endif // CTRY_DEFINED + + +extern LANGUAGE language; +extern CTRY ctry; + + +#define _ctry_init() \ + ctry_setup( ctry_get_code() ) + + +#define _next_language() \ +{ \ + if ( ++language >= N_LNG ) \ + language = 0; \ + \ +} // next_language + + +// macro to call lstr_lng with the current language +#define _lstr( _s ) lstr_lng( (_s), language ) + +// macro to call clstr_lng with the current language, and a set of strings +#define _clstr( _s ) clstr_lng( language, _s ) + +// macros used in wxWidgets projects +#if defined( __WXWINDOWS__ ) + #define _wx_lstr( _s ) wxString::From8BitData( lstr_lng( (_s), language ) ) + #define _wx_clstr( _s ) wxString::From8BitData( clstr_lng( language, _s ) ) +#endif + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + int lstr_idx( CLSTR s, int lng ) ; + int lstr_array_idx( CLSTR s, int idx, int n_lng, int lng ) ; + const char *lstr_lng( CLSTR s, int lng ) ; + void ctry_setup( CTRY_CODE code ) ; + void ctry_next( void ) ; + const char *clstr_lng( int index, ... ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + + +#undef _ext + +#endif /* _CTRY_H */ + diff --git a/mbglib/common/ctrydttm.c b/mbglib/common/ctrydttm.c new file mode 100644 index 0000000..d846ed8 --- /dev/null +++ b/mbglib/common/ctrydttm.c @@ -0,0 +1,184 @@ + +/************************************************************************** + * + * $Id: ctrydttm.c 1.5 2008/11/24 16:15:46Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Functions converting dates and time into strings depending on + * language/country settings. + * + * ----------------------------------------------------------------------- + * $Log: ctrydttm.c $ + * Revision 1.5 2008/11/24 16:15:46Z martin + * Don't use sprintf() without format string. + * Revision 1.4 2000/11/27 10:06:27 MARTIN + * Renamed local variable wday_str to lstrs_wday. + * If macro USER_LSTR_WDAY is defined, lstrs_wday can be declared + * externally to override the defaults. + * Revision 1.3 2000/09/14 15:13:25 MARTIN + * Renamed sprint_short_ctry_dt() to sprint_ctry_dt_short() to match + * other naming conventions. + * Revision 1.2 2000/07/21 11:53:42 MARTIN + * Initial revision + * + **************************************************************************/ + +#define _CTRYDTTM + #include <ctrydttm.h> +#undef _CTRYDTTM + +#include <ctry.h> + +#include <stdio.h> + + +#ifndef DAYS_PER_WEEK + #define DAYS_PER_WEEK 7 +#endif + +#ifdef USER_LSTRS_WDAY + extern const char *lstrs_wday[N_LNG][DAYS_PER_WEEK]; +#else + static const char *lstrs_wday[N_LNG][DAYS_PER_WEEK] = + { + { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }, + { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" } + }; +#endif + +extern CTRY ctry; +extern LANGUAGE language; + + +/*HDR*/ +ushort sprint_02u( char *s, uchar uc ) +{ + return( sprintf( s, "%02u", uc ) ); + +} // sprint_02u + + + +/*HDR*/ +ushort sprint_04u( char *s, ushort us ) +{ + return( sprintf( s, "%04u", us ) ); + +} // sprint_04u + + + +/*HDR*/ +ushort sprint_ctry_wday( char *s, uchar wday, ushort language ) +{ + if ( language >= N_LNG ) + language = LNG_ENGLISH; + + return( sprintf( s, "%s", ( wday < DAYS_PER_WEEK ) ? + lstrs_wday[language][wday] : "--" ) ); + +} // sprint_ctry_wday + + + +/*HDR*/ +ushort sprint_ctry_dt_short( char *s, uchar mday, uchar month ) +{ + uchar tmp_1; + uchar tmp_2; + ushort n = 0; + + + switch( ctry.dt_fmt ) + { + case DT_FMT_YYYYMMDD: + case DT_FMT_MMDDYYYY: + tmp_1 = month; + tmp_2 = mday; + break; + + default: + tmp_1 = mday; + tmp_2 = month; + break; + + } // switch + + n = sprint_02u( s, tmp_1 ); + s[n++] = ctry.dt_sep; + n += sprint_02u( &s[n], tmp_2 ); + s[n++] = ctry.dt_sep; + s[n] = 0; + + return( n ); + +} // sprint_ctry_dt_short + + + +/*HDR*/ +ushort sprint_ctry_dt( char *s, uchar mday, uchar month, ushort year ) +{ + ushort n = 0; + + + if ( ctry.dt_fmt == DT_FMT_YYYYMMDD ) + { + n = sprint_04u( s, year ); + s[n++] = ctry.dt_sep; + } + + n += sprint_ctry_dt_short( &s[n], mday, month ); + + if ( ctry.dt_fmt == DT_FMT_YYYYMMDD ) + s[--n] = 0; + else + n += sprint_04u( &s[n], year ); + + return( n ); + +} // sprint_ctry_dt + + + +/*HDR*/ +ushort sprint_ctry_tm_short( char *s, uchar hour, uchar minute ) +{ + ushort n = sprint_02u( s, hour ); + s[n++] = ctry.tm_sep; + n += sprint_02u( &s[n], minute ); + + return( n ); + +} // sprint_ctry_tm_short + + + +/*HDR*/ +ushort sprint_ctry_tm( char *s, uchar hour, uchar minute, uchar second ) +{ + ushort n = sprint_ctry_tm_short( s, hour, minute ); + s[n++] = ctry.tm_sep; + n += sprint_02u( &s[n], second ); + + return( n ); + +} // sprint_ctry_tm + + + +/*HDR*/ +ushort sprint_ctry_tm_long( char *s, uchar hour, uchar minute, uchar second, + long frac, ushort frac_digits ) +{ + ushort n = sprint_ctry_tm( s, hour, minute, second ); + s[n++] = '.'; + n += sprintf( &s[n], "%0*lu", frac_digits, frac ); + + return( n ); + +} // sprint_ctry_tm_long + + diff --git a/mbglib/common/ctrydttm.h b/mbglib/common/ctrydttm.h new file mode 100644 index 0000000..8032d89 --- /dev/null +++ b/mbglib/common/ctrydttm.h @@ -0,0 +1,74 @@ + +/************************************************************************** + * + * $Id: ctrydttm.h 1.3 2000/09/14 15:13:45Z MARTIN REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for ctrydttm.c. + * + * ----------------------------------------------------------------------- + * $Log: ctrydttm.h $ + * Revision 1.3 2000/09/14 15:13:45Z MARTIN + * Updated function prototypes. + * Revision 1.2 2000/07/21 11:50:43 MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _CTRYDTTM_H +#define _CTRYDTTM_H + + +/* Other headers to be included */ + +#include <ctry.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _CTRYDTTM + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + + + + + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + ushort sprint_02u( char *s, uchar uc ) ; + ushort sprint_04u( char *s, ushort us ) ; + ushort sprint_ctry_wday( char *s, uchar wday, ushort language ) ; + ushort sprint_ctry_dt_short( char *s, uchar mday, uchar month ) ; + ushort sprint_ctry_dt( char *s, uchar mday, uchar month, ushort year ) ; + ushort sprint_ctry_tm_short( char *s, uchar hour, uchar minute ) ; + ushort sprint_ctry_tm( char *s, uchar hour, uchar minute, uchar second ) ; + ushort sprint_ctry_tm_long( char *s, uchar hour, uchar minute, uchar second, long frac, ushort frac_digits ) ; + +/* ----- function prototypes end ----- */ + +/* End of header body */ + + +#undef _ext + +#ifdef __cplusplus +} +#endif + + +#endif /* _CTRYDTTM_H */ + diff --git a/mbglib/common/deviohlp.c b/mbglib/common/deviohlp.c new file mode 100644 index 0000000..8de1a19 --- /dev/null +++ b/mbglib/common/deviohlp.c @@ -0,0 +1,322 @@ + +/************************************************************************** + * + * $Id: deviohlp.c 1.2 2012/10/15 13:48:35Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Device configuration helper functions. This is an extension to + * mbgdevio.c providing useful functions to simplify reading/writing + * complex device configuration structure sets. + * + * Warning: + * These functions should not be implemented in a DLL / shared library + * since the parameter sizes might vary with different versions + * of the API calls, which which would make different versions of + * precompiled libraries incompatible to each other. + * + * ----------------------------------------------------------------------- + * $Log: deviohlp.c $ + * Revision 1.2 2012/10/15 13:48:35Z martin + * Added functions mbg_get_all_ptp_cfg_info(), mbg_save_all_ptp_cfg_info(). + * Revision 1.1.1.9 2012/07/18 11:00:46 martin + * Revision 1.1.1.8 2012/07/12 09:07:36Z martin + * Revision 1.1.1.7 2012/07/12 08:38:50Z martin + * Account for renamed structure. + * Revision 1.1.1.6 2012/07/10 09:53:57 martin + * Revision 1.1.1.5 2012/04/11 15:45:10Z martin + * Updated doxygen comments. + * Revision 1.1.1.4 2011/09/21 14:45:24 martin + * Moved mbgextio support functions to new module extiohlp.c. + * Revision 1.1.1.3 2011/09/20 15:36:02 marvin + * new functions: + * mbg_get_serial_settings + * mbg_set_serial_settings + * include mbgextio.h + * Revision 1.1.1.2 2011/08/05 10:30:28 martin + * Revision 1.1.1.1 2011/08/05 09:55:52 martin + * Revision 1.1 2011/08/03 15:37:00Z martin + * Initial revision with functions moved here from mbgdevio. + * + **************************************************************************/ + +#define _DEVIOHLP + #include <deviohlp.h> +#undef _DEVIOHLP + +#include <parmpcps.h> +#include <parmgps.h> + + + +/*HDR*/ +/** + Read all serial port settings and supported configuration parameters. + + The functions mbg_get_device_info() and mbg_setup_receiver_info() + must have been called before, and the returned ::PCPS_DEV and + ::RECEIVER_INFO structures must be passed to this function. + + The complementary function mbg_save_serial_settings() should be used + to write the modified serial port configuration back to the board. + + @param dh Valid handle to a Meinberg device. + @param *pdev Pointer to a ::PCPS_DEV structure. + @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure to be filled up. + @param *p_ri Pointer to a ::RECEIVER_INFO structure. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_device_info() + @see mbg_setup_receiver_info() + @see mbg_save_serial_settings() +*/ +int mbg_get_serial_settings( MBG_DEV_HANDLE dh, + const PCPS_DEV *pdev, + RECEIVER_PORT_CFG *pcfg, + const RECEIVER_INFO *p_ri ) +{ + int rc; + int i; + + memset( pcfg, 0, sizeof( *pcfg ) ); + + if ( _pcps_has_receiver_info( pdev ) ) + { + rc = mbg_get_gps_all_port_info( dh, pcfg->pii, p_ri ); + if ( rc != MBG_SUCCESS ) + goto error; + + rc = mbg_get_gps_all_str_type_info( dh, pcfg->stii, p_ri ); + if ( rc != MBG_SUCCESS ) + goto error; + } + else + { + if ( _pcps_is_gps( pdev ) ) + { + rc = mbg_get_gps_port_parm( dh, &pcfg->tmp_pp ); + if ( rc != MBG_SUCCESS ) + goto error; + + for ( i = 0; i < p_ri->n_com_ports; i++ ) + { + PORT_INFO_IDX *p_pii = &pcfg->pii[i]; + PORT_INFO *p_pi = &p_pii->port_info; + + p_pii->idx = i; + port_settings_from_port_parm( &p_pi->port_settings, + i, &pcfg->tmp_pp, 1 ); + + p_pi->supp_baud_rates = DEFAULT_GPS_BAUD_RATES_C166; + p_pi->supp_framings = DEFAULT_GPS_FRAMINGS_C166; + p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_GPS; + } + } + else + if ( _pcps_has_serial ( pdev ) ) // Not all non-GPS clocks have a serial port! + { + PCPS_SERIAL ser_code; + + rc = mbg_get_serial( dh, &ser_code ); + if ( rc != MBG_SUCCESS ) + goto error; + + + port_info_from_pcps_serial( pcfg->pii, ser_code, + _pcps_has_serial_hs( pdev ) ? + DEFAULT_BAUD_RATES_DCF_HS : + DEFAULT_BAUD_RATES_DCF + ); + } + + for ( i = 0; i < p_ri->n_str_type; i++ ) + { + STR_TYPE_INFO_IDX *stip = &pcfg->stii[i]; + stip->idx = i; + stip->str_type_info = default_str_type_info[i]; + } + } + + return MBG_SUCCESS; + + +error: + return rc; + +} // mbg_get_serial_settings + + + +/*HDR*/ +/** + Write the configuration settings for a single serial port to the board. + + Modifications to the serial port configuration should be made only + after mbg_get_serial_settings() had been called to read all serial port + settings and supported configuration parameters. + This function has finally to be called once for every serial port + the configuration of which has been modified. + + As also required by mbg_get_serial_settings(), the functions + mbg_get_device_info() and mbg_setup_receiver_info() must have been + called before, and the returned ::PCPS_DEV and ::RECEIVER_INFO structures + must be passed to this function. + + @param dh Valid handle to a Meinberg device + @param *pdev Pointer to a ::PCPS_DEV structure + @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure + @param port_num Index of the ::serial port to be saved + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_serial_settings() + @see mbg_get_device_info() + @see mbg_setup_receiver_info() +*/ +int mbg_save_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, + RECEIVER_PORT_CFG *pcfg, int port_num ) +{ + int rc; + + if ( _pcps_has_receiver_info( pdev ) ) + { + rc = mbg_set_gps_port_settings( dh, &pcfg->pii[port_num].port_info.port_settings, port_num ); + } + else + { + if ( _pcps_is_gps( pdev ) ) + { + port_parm_from_port_settings( &pcfg->tmp_pp, port_num, + &pcfg->pii[port_num].port_info.port_settings, 1 ); + + rc = mbg_set_gps_port_parm( dh, &pcfg->tmp_pp ); + } + else + { + PCPS_SERIAL ser_code; + + pcps_serial_from_port_info( &ser_code, pcfg->pii ); + + rc = mbg_set_serial( dh, &ser_code ); + } + } + + return rc; + +} // mbg_save_serial_settings + + + +/*HDR*/ +/** + Read all PTP settings and supported configuration parameters. + + The complementary function mbg_save_all_ptp_cfg_info() should + be used to write the modified configuration back to the device. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::ALL_PTP_CFG_INFO structure. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_save_all_ptp_cfg_info() + @see mbg_get_ptp_cfg_info() + @see mbg_get_ptp_uc_master_cfg_limits() + @see mbg_get_all_ptp_uc_master_info() + @see mbg_dev_has_ptp() + @see mbg_dev_has_ptp_unicast() +*/ +int mbg_get_all_ptp_cfg_info( MBG_DEV_HANDLE dh, ALL_PTP_CFG_INFO *p ) +{ + int rc = MBG_SUCCESS; + + memset( p, 0, sizeof( *p ) ); + + rc = mbg_get_ptp_cfg_info( dh, &p->ptp_cfg_info ); + + if ( rc < 0 ) + return rc; + + if ( p->ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) + { + rc = mbg_get_ptp_uc_master_cfg_limits( dh, &p->ptp_uc_master_cfg_limits ); + + if ( rc < 0 ) + return rc; + + if ( p->ptp_uc_master_cfg_limits.n_supp_master > MAX_PARM_PTP_UC_MASTER ) + { + // The number of PTP unicast masters supported by this device + // exceeds the number of unicast masters supporterd by this driver. + return MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP; + } + + rc = mbg_get_all_ptp_uc_master_info( dh, p->all_ptp_uc_master_info_idx, + &p->ptp_uc_master_cfg_limits ); + if ( rc < 0 ) + return rc; + } + + return MBG_SUCCESS; + +} // mbg_get_all_ptp_cfg_info + + + +/*HDR*/ +/** + Write all PTP settings and supported configuration parameters + to a device. + + The complementary function mbg_get_all_ptp_cfg_info() should + have been used to read the original PTP settings and supported + configuration parameters. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::ALL_PTP_CFG_INFO structure. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_all_ptp_cfg_info() + @see mbg_set_ptp_cfg_settings() + @see mbg_set_ptp_uc_master_settings_idx() + @see mbg_dev_has_ptp() + @see mbg_dev_has_ptp_unicast() +*/ +int mbg_save_all_ptp_cfg_info( MBG_DEV_HANDLE dh, const ALL_PTP_CFG_INFO *p ) +{ + int rc = MBG_SUCCESS; + + rc = mbg_set_ptp_cfg_settings( dh, &p->ptp_cfg_info.settings ); + + if ( rc < 0 ) + return rc; + + + if ( p->ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) + { + int i; + + for ( i = 0; i < p->ptp_uc_master_cfg_limits.n_supp_master; i++ ) + { + PTP_UC_MASTER_SETTINGS_IDX s; + + memset( &s, 0, sizeof( s ) ); + + s.idx = i; + s.settings = p->all_ptp_uc_master_info_idx[i].info.settings; + + rc = mbg_set_ptp_uc_master_settings_idx( dh, &s ); + + if ( rc < 0 ) + return rc; + } + } + + return MBG_SUCCESS; + +} // mbg_save_all_ptp_cfg_info + + diff --git a/mbglib/common/deviohlp.h b/mbglib/common/deviohlp.h new file mode 100644 index 0000000..f6ed431 --- /dev/null +++ b/mbglib/common/deviohlp.h @@ -0,0 +1,168 @@ + +/************************************************************************** + * + * $Id: deviohlp.h 1.2 2012/10/15 13:51:18Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for deviohlp.c. + * + * ----------------------------------------------------------------------- + * $Log: deviohlp.h $ + * Revision 1.2 2012/10/15 13:51:18Z martin + * Include cfg_hlp.h. + * Added structure ALL_PTP_CFG_INFO. + * Updated function prototypes. + * Revision 1.1 2011/08/03 15:36:44Z martin + * Initial revision with functions moved here from mbgdevio. + * + **************************************************************************/ + +#ifndef _DEVIOHLP_H +#define _DEVIOHLP_H + + +/* Other headers to be included */ + +#include <mbgdevio.h> +#include <cfg_hlp.h> + + +#ifdef _DEVIOHLP + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct +{ + PTP_CFG_INFO ptp_cfg_info; + PTP_UC_MASTER_CFG_LIMITS ptp_uc_master_cfg_limits; + ALL_PTP_UC_MASTER_INFO_IDX all_ptp_uc_master_info_idx; + +} ALL_PTP_CFG_INFO; + + + +/* function prototypes: */ + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + Read all serial port settings and supported configuration parameters. + + The functions mbg_get_device_info() and mbg_setup_receiver_info() + must have been called before, and the returned ::PCPS_DEV and + ::RECEIVER_INFO structures must be passed to this function. + + The complementary function mbg_save_serial_settings() should be used + to write the modified serial port configuration back to the board. + + @param dh Valid handle to a Meinberg device. + @param *pdev Pointer to a ::PCPS_DEV structure. + @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure to be filled up. + @param *p_ri Pointer to a ::RECEIVER_INFO structure. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_device_info() + @see mbg_setup_receiver_info() + @see mbg_save_serial_settings() +*/ + int mbg_get_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_PORT_CFG *pcfg, const RECEIVER_INFO *p_ri ) ; + + /** + Write the configuration settings for a single serial port to the board. + + Modifications to the serial port configuration should be made only + after mbg_get_serial_settings() had been called to read all serial port + settings and supported configuration parameters. + This function has finally to be called once for every serial port + the configuration of which has been modified. + + As also required by mbg_get_serial_settings(), the functions + mbg_get_device_info() and mbg_setup_receiver_info() must have been + called before, and the returned ::PCPS_DEV and ::RECEIVER_INFO structures + must be passed to this function. + + @param dh Valid handle to a Meinberg device + @param *pdev Pointer to a ::PCPS_DEV structure + @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure + @param port_num Index of the ::serial port to be saved + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_serial_settings() + @see mbg_get_device_info() + @see mbg_setup_receiver_info() +*/ + int mbg_save_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_PORT_CFG *pcfg, int port_num ) ; + + /** + Read all PTP settings and supported configuration parameters. + + The complementary function mbg_save_all_ptp_cfg_info() should + be used to write the modified configuration back to the device. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::ALL_PTP_CFG_INFO structure. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_save_all_ptp_cfg_info() + @see mbg_get_ptp_cfg_info() + @see mbg_get_ptp_uc_master_cfg_limits() + @see mbg_get_all_ptp_uc_master_info() + @see mbg_dev_has_ptp() + @see mbg_dev_has_ptp_unicast() +*/ + int mbg_get_all_ptp_cfg_info( MBG_DEV_HANDLE dh, ALL_PTP_CFG_INFO *p ) ; + + /** + Write all PTP settings and supported configuration parameters + to a device. + + The complementary function mbg_get_all_ptp_cfg_info() should + have been used to read the original PTP settings and supported + configuration parameters. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::ALL_PTP_CFG_INFO structure. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_all_ptp_cfg_info() + @see mbg_set_ptp_cfg_settings() + @see mbg_set_ptp_uc_master_settings_idx() + @see mbg_dev_has_ptp() + @see mbg_dev_has_ptp_unicast() +*/ + int mbg_save_all_ptp_cfg_info( MBG_DEV_HANDLE dh, const ALL_PTP_CFG_INFO *p ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _DEVIOHLP_H */ diff --git a/mbglib/common/gpsdefs.h b/mbglib/common/gpsdefs.h new file mode 100644 index 0000000..25eff0f --- /dev/null +++ b/mbglib/common/gpsdefs.h @@ -0,0 +1,6801 @@ + +/************************************************************************** + * + * $Id: gpsdefs.h 1.113 2013/04/04 09:02:01Z martin REL_M Gregoire $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * General definitions to be used with Meinberg clocks. + * These definitions have initially be used with GPS devices only. + * However, more and more Meinberg non-GPS devices also use some of + * these definitions. + * + * ----------------------------------------------------------------------- + * $Log: gpsdefs.h $ + * Revision 1.113 2013/04/04 09:02:01Z martin + * Added definitions to support HaveQuick. + * Fixed a typo. + * Revision 1.112 2013/02/19 15:39:13 martin + * New PTP settings field ann_rcpt_timeout and associated + * values PTP_ANN_RCPT_TIMEOUT_LIMITS. + * Changed many defines to named enums to simplify references + * with doxygen. + * Updated doxygen comments. + * Revision 1.111 2013/02/01 15:37:36 martin + * Added and modified a huge number of doxygen comments. + * Revision 1.110 2013/01/16 15:23:25 martin + * Fixed 2 comments which were interchanged. + * Revision 1.109 2013/01/11 10:39:34 martin + * Added definitions for IMS. + * Support XMR_HOLDOVER_INTV. + * New XMRS status bit XMRS_BIT_LOW_JITTER / XMRS_MSK_LOW_JITTER. + * Added framing type 8E2, though most UARTs don't support this. + * Added enum names and updated comments for doxygen. + * Revision 1.108 2012/10/30 11:31:16 martin + * Defined PTP_UC_MSG_DURATION_MIN and PTP_UC_MSG_DURATION_MAX. + * Fixed some doxygen comments. + * Changes by andre: changed reserved field to ssm and boc in BITS_OUT settings. + * Revision 1.107 2012/10/12 07:40:12 martin + * New PTP state flags PTP_FLAG_MSK_UTC_VALID and + * PTP_CFG_MSK_SUPP_UTC_VALID. + * Revision 1.106 2012/10/02 18:22:10 martin + * Added default baud rate and framing for binary protocol. + * Added definitions for IRIG codes E002/E112 and NASA36. + * Reworked GPIO structures. + * Added definitions for GRC, LIU, DCF600RS, and DCF600HS. + * New flag POUT_FIXED_PULSE_LEN. + * New flag POUT_NOT_INVERTIBLE. + * Unified capitalization in MBG_XMRS_STATUS_STRS. + * Revision 1.105 2012/06/01 16:31:16 martin + * Some TIME_SLOT definitions added by marvin. + * Moved some PTP configuration defaults and limits to ptpdflts.h. + * Revision 1.104 2012/04/11 16:02:55Z martin + * Fixed some doxygen comments. + * Revision 1.103 2012/04/02 11:08:57Z martin + * Extended description of GPS UTC/leap second data. + * Revision 1.102 2012/03/16 11:43:31 martin + * Fixed a potential compiler warning. + * Revision 1.101 2012/03/06 16:56:01Z martin + * Added support for PTP multicast auto role. + * Merged Daniel's definitions for PTP profile support. + * Support time slot mode for programmable pulse outputs. + * Support LNO180. + * Moved definition of MBG_MAC_ADDR here. + * Use MBG_MAC_ADDR in definition of LAN_IF_INFO. + * Revision 1.100 2012/01/17 13:33:55 martin + * Added new IRIG RX delay compensation code groups for G0xx and G1xx codes. + * As a consequence the value of N_IRIG_RX_COMP has changed. + * Added definition of IRIG_RX_COMP_MAX. + * Updated IRIG code classification macros. + * Removed obsolete/unused definition of CAL_REC_INFO. + * Added some comments. + * Revision 1.99 2011/12/09 09:22:03 martin + * Fixed a typo. + * Revision 1.98 2011/11/25 14:58:34 martin + * Renamed some evt_log definitions. + * Revision 1.97 2011/11/25 10:11:17 martin + * Initializers for XMRS status bit strings added by gregoire. + * New feature GPS_FEAT_EVT_LOG. + * Added definitions used with event logs. + * Moved cal_reg and gen_io stuff here. + * Added macro _mbg_swab_debug_status(). + * Updated some comments. + * Revision 1.96 2011/10/11 13:40:46Z andre + * changed reserved field into slot_id in XMULTI_REF_INSTANCES + * Revision 1.95.1.1 2011/10/07 09:31:58Z andre + * Revision 1.95 2011/10/04 09:35:41Z martin + * Added support for ESI180. + * Changed RECEIVER_INFO::flags bit GPS_10MHZ_DISBD to a RECEIVER_INFO::features bit. + * Support MULTI_REF_INTERNAL, MULTI_REF_LWR and MULTI_REF_PZF. + * Added MBG_GPIO_BITS structure and associated definitions. + * Revision 1.94 2011/08/25 07:42:43Z martin + * Fixed a bug in macro _mbg_swab_pout_settings() where the 16 bit timeout + * field was swapped using a macro for 32 bit types. + * Use shorter names for some PTP unicast master default values. + * Revision 1.93 2011/08/10 08:19:38Z martin + * New PORT_INFO and PORT_SETTINGS flag PORT_FLAG_PORT_INVISIBLE. + * Revision 1.92 2011/07/29 09:49:35 martin + * Support PZF180PEX, MGR180, MSF600, WWVB600, JJY600, + * GPS180HS, and GPS180AMC. + * Added receiver info features GPS_FEAT_PTP_UNICAST + * and GPS_FEAT_XMRS_MULT_INSTC. + * Added receiver info flag bit GPS_10MHZ_DISBD. + * Added initializers for PTP timescale names. + * New PTP_STATE flags bit PTP_FLAG_MSK_IS_UNICAST. + * Made unused PTP_STATE fields num_clients and num_masters reserved. + * Account for different PTP roles. + * Added / renamed some definitions for PTP. + * Modified default string for PTP layer 2 protocol. + * Support PTP unicast configuration. + * Support GPIO configuration. + * Introduced XMULTI_REF_INSTANCES. + * Moved flags XMRS_..._IS_EXTERNAL and XMRS_..._INSTC_EXCEEDED + * to definitions for XMULTI_REF_STATUS::status. + * Some comments added, updated, and converted to doxygen style. + * Cleaned up handling of pragma pack(). + * Removed trailing whitespace and hard tabs. + * Revision 1.91 2011/01/31 11:23:56Z martin + * Added model type name definitions for GPS180PEX and TCR180PEX. + * Introduced synthesizer mode for programmable outputs. + * Added IRIG-RX code TXC-101 DTR-6. + * Fixed missing comma bugs in DEFAULT_GPS_MODEL_NAMES. + * Fixed missing comma bugs in some IRIG string initializers. + * Fixed AFNOR notation. + * Modified some comments for doxygen. + * Revision 1.90 2010/10/15 11:47:53 martin + * Added definitions POUT_TIMEBASE_UTC and POUT_SUPP_DCF77_UTC. + * Added receiver info feature GPS_FEAT_RAW_IRIG_TIME. + * Support IRIG format C37.118. + * Added initializers for short IRIG code names. + * Cleaned up IRIG definitions and comments. + * Revision 1.89 2010/09/06 07:40:02Z martin + * Picked up Daniel's definitions for multi GNSS support. + * Moved MBG_IRIG_CTRL_BITS, MBG_RAW_IRIG_DATA and related definitions + * from pcpsdefs.h here. + * Added macros _pcps_tfom_from_irig_ctrl_bits() + * and _pcps_tfom_from_raw_irig_data(). + * Added RI_FEATURES type. + * Revision 1.88 2010/04/21 13:47:54 daniel + * Added support for new model GLN170. + * Revision 1.87 2010/03/10 11:29:37Z martin + * Added definitions for GPS180. + * Added multiref source 1 PPS plus associated string. + * Revision 1.86 2010/02/17 14:16:42 martin + * Added definitions for PZF600 and TCR600. + * Revision 1.85 2010/02/15 11:34:36 martin + * Changed definition of PTP_TABLE::name to const char *. + * Added definitions to support new model JJY511. + * Revision 1.84 2010/02/01 13:20:50 martin + * Support programmable outputs being disabled when sync. is lost. + * Revision 1.83 2010/01/28 09:15:50 martin + * Added new POUT mode DCF77_M59 and associated definitions. + * Revision 1.82 2010/01/07 09:04:55 martin + * Added XMR status bit XMRS_BIT_NOT_PHASE_LOCKED. + * Revision 1.81 2009/11/09 09:08:24 martin + * New TM_GPS status bit TM_INVT. + * Added definitions to support VLAN. + * Changed DEFAULT_PTP_DELAY_MECH_MASK to include also + * PTP_DELAY_MECH_MSK_P2P. + * There is now only one type of TCXO supported which matches the former + * TCXO HQ, so the default name for TCXO HQ has been changed to TCXO. + * TCXO LQ and MQ names are still supported for backward compatibility. + * Revision 1.80 2009/09/28 14:55:53 martin + * Support IRIG formats G002/G142 and G006/G146. + * Modified IRIG format description strings. + * Revision 1.79 2009/08/12 14:12:38 daniel + * 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. + * Added some definitions useful when editing synth frequency. + * Revision 1.50 2006/08/25 09:29:28Z martin + * Added structure NANO_TIME. + * Revision 1.49 2006/08/09 07:06:42Z martin + * New TM_GPS status flag TM_EXT_SYNC. + * Revision 1.48 2006/08/08 12:51:20Z martin + * Added definitions for IRIG codes B006/B126 and B007/B127. + * Revision 1.47 2006/07/06 08:41:45Z martin + * Added definition of MEINBERG_MAGIC. + * Revision 1.46 2006/06/21 14:08:53Z martin + * Added masks of IRIG codes which contain time zone information. + * Revision 1.45 2006/06/15 12:13:32Z martin + * Added MULTI_REF_STATUS and associated flags. + * Added ROM_CSUM, RCV_TIMEOUT, and IGNORE_LOCK types. + * Revision 1.44 2006/05/18 09:34:41Z martin + * Added definitions for POUT max. pulse_len and max timeout. + * Changed comment for POUT_SETTINGS::timeout. + * Units are minutes, not seconds. + * Added definition for MAX_POUT_TIME_STR_PORTS. + * Added definitions for POUT mode 10MHz. + * Added hint strings for POUT modes. + * Added definitions for PZF511. + * Revision 1.43 2006/01/24 07:53:29Z martin + * New TM_GPS status flag TM_HOLDOVER. + * Revision 1.42 2005/11/24 14:53:22Z martin + * Added definitions for manchester encoded DC IRIG frames. + * Added POUT_TIMESTR and related definitions. + * Revision 1.41 2005/11/03 15:06:59Z martin + * Added definitions to support GPS170PCI. + * Revision 1.40 2005/10/28 08:58:29Z martin + * Added definitions for OCXO_DHQ. + * Revision 1.39 2005/09/08 14:06:00Z martin + * Added definition SYNTH_PHASE_SYNC_LIMIT. + * Revision 1.38 2005/08/18 10:27:35 andre + * added definitions for GPS164, + * added POUT_TIMECODE, + * struct SCU_STAT changed, + * ulong flags changed into two byte clk_info and ushort flags + * Revision 1.37 2005/05/02 14:44:55Z martin + * Added structure SYNTH_STATE and associated definitions. + * Revision 1.36 2005/03/29 12:44:07Z martin + * New RECEIVER_INFO::flags code: GPS_IRIG_FO_IN + * Revision 1.35 2004/12/09 14:04:38Z martin + * Changed max synth freq from 12 MHz to 10 MHz. + * Revision 1.34 2004/11/23 16:20:09Z martin + * Added bit definitions for the existing TTM status bit masks. + * Revision 1.33 2004/11/09 12:39:59Z martin + * Redefined interface data types using C99 fixed-size definitions. + * Added model code and name for TCR167PCI. + * New type GPS_CMD. + * Defined type BVAR_STAT and associated flags. + * Revision 1.32 2004/09/20 12:46:25 andre + * Added structures and definitions for SCU board. + * Revision 1.31 2004/07/08 08:30:36Z martin + * Added feature GPS_FEAT_RCV_TIMEOUT. + * Revision 1.30 2004/06/21 13:38:42 martin + * New flag MBG_OPT_BIT_EMU_SYNC/MBG_OPT_FLAG_EMU_SYNC + * lets the receicer emulate/pretend to be always synchronized. + * Revision 1.30 2004/06/21 13:35:46Z martin + * Revision 1.29 2004/06/16 12:47:53Z martin + * Moved OPT_SETTINGS related definitions from pcpsdefs.h + * here and renamed symbols from PCPS_.. to to MBG_... + * Revision 1.28 2004/03/26 10:37:00Z martin + * Added definitions to support multiple ref sources. + * Added definitions OSC_DAC_RANGE, OSC_DAC_BIAS. + * Revision 1.27 2004/03/08 14:06:45Z martin + * New model code and name for GPS169PCI. + * Existing feature GPS_FEAT_IRIG has been + * renamed to GPS_FEAT_IRIG_TX. + * Added feature GPS_FEAT_IRIG_RX. + * Added IPv4 LAN interface feature flags. + * Renamed IFLAGS_IGNORE_TFOM to IFLAGS_DISABLE_TFOM. + * Revision 1.26 2003/12/05 12:28:20Z martin + * Added some codes used with IRIG cfg. + * Revision 1.25 2003/10/29 16:18:14Z martin + * Added 7N2 to DEFAULT_GPS_FRAMINGS_GP2021. + * Revision 1.24 2003/09/30 08:49:48Z martin + * New flag TM_LS_ANN_NEG which is set in addition to + * TM_LS_ANN if next leap second is negative. + * Revision 1.23 2003/08/26 14:32:33Z martin + * Added some initializers for commonly used + * TZDL configurations. + * Revision 1.22 2003/04/25 10:18:11 martin + * Fixed typo inside an IRIG name string initializer. + * Revision 1.21 2003/04/15 09:18:48 martin + * New typedef ANT_CABLE_LEN. + * Revision 1.20 2003/04/03 11:03:44Z martin + * Extended definitions for IRIG support. + * Revision 1.19 2003/01/31 13:38:20 MARTIN + * Modified type of RECEIVER_INFO::fixed_freq field. + * Revision 1.18 2002/10/28 09:24:07 MARTIN + * Added/renamed some POUT related symbols. + * Revision 1.17 2002/09/05 10:58:39 MARTIN + * Renamed some symbols related to programmable outputs. + * Revision 1.16 2002/08/29 08:04:47 martin + * Renamed structure POUT_PROG to POUT_SETTINGS. + * New structures POUT_SETTINGS_IDX, POUT_INFO, + * POUT_INFO_IDX and associated definitions. + * Updated some comments. + * Revision 1.15 2002/07/17 07:39:39Z Andre + * comma added in definition DEFAULT_GPS_OSC_NAMES + * Revision 1.14 2002/06/27 12:17:29Z MARTIN + * Added new oscillator code TCXO_MQ. + * Added initializer for oscillator names. + * Added initializer for oscillator list ordered by quality. + * Revision 1.13 2002/05/08 08:16:03 MARTIN + * Added GPS_OSC_CFG_SUPP for RECEIVER_INFO::flags. + * Fixed some comments. + * Revision 1.12 2002/03/14 13:45:56 MARTIN + * Changed type CSUM from short to ushort. + * Revision 1.11 2002/03/01 12:29:30 Andre + * Added GPS_MODEL_GPS161 and GPS_MODEL_NAME_GPS161. + * Revision 1.10 2002/02/25 08:02:33Z MARTIN + * Added array of chars to union IDENT. + * Revision 1.9 2002/01/29 15:21:46 MARTIN + * Added new field "reserved" to struct SW_REV to fix C166 data + * alignment/structure size. Converted structure IDENT to a union. + * The changes above should not affect existing monitoring programs. + * New status flag TM_ANT_SHORT. + * New structure RECEIVER_INFO and associated definitions to + * enhance control from monitoring programs. + * New structures PORT_INFO, STR_TYPE_INFO, and associated + * definitions to simplify and unify configuration from external programs. + * New structures IRIG_INFO and POUT_PROG_IDX to configure an + * optional IRIG interface and programmable pulse outputs. + * Modified some comments. + * Revision 1.8 2001/03/30 11:44:11 MARTIN + * Control alignment of structures from new file use_pack.h. + * Defined initializers with valid baud rate and framing parameters. + * Modified some comments. + * Revision 1.7 2001/03/01 08:09:22 MARTIN + * Modified preprocessor syntax. + * Revision 1.6 2000/07/21 14:04:33 MARTIN + * Added som #if directives to protect structures against being multiply + * defined. + * Modified some comments. + * Comments using characters for +/- and degree now include ASCII + * characters only. + * + **************************************************************************/ + +#ifndef _GPSDEFS_H +#define _GPSDEFS_H + + +/* Other headers to be included */ + +#if defined( HAVE_CONFIG_H ) + // this is mainly to simplify usage in non-Meinberg projects + #include <config.h> +#endif + +// CLOCK_MEINBERG is defined in NTP's config.h if configured +// to support Meinberg clocks. +#if !defined( CLOCK_MEINBERG ) + // avoid having to use these headers in non-Meinberg projects + #include <words.h> + #include <use_pack.h> +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + + +/* "magic" number */ +#define MEINBERG_MAGIC 0x6AAC + +#define MIN_SVNO 1 /* min. SV number */ +#define MAX_SVNO 32 /* max. SV number */ +#define N_SVNO ( MAX_SVNO - MIN_SVNO + 1) /* number of possibly active SVs */ + + +#define GPS_ID_STR_LEN 16 +#define GPS_ID_STR_SIZE ( GPS_ID_STR_LEN + 1 ) + +#define GPS_EPLD_STR_LEN 8 +#define GPS_EPLD_STR_SIZE ( GPS_EPLD_STR_LEN + 1 ) + + +#define DEFAULT_GPS_TICKS_PER_SEC 10000000L ///< system time base, see ::GPS_TICKS_PER_SEC + +#if !defined( GPS_TICKS_PER_SEC ) + /* + * The actual ticks per seconds may vary for different + * GPS receiver models. If this is the case, the receiver + * model support the RECEIVER_INFO structure which contains + * the actual value. + */ + #define GPS_TICKS_PER_SEC DEFAULT_GPS_TICKS_PER_SEC ///< @see DEFAULT_GPS_TICKS_PER_SEC + +#endif + + +typedef uint16_t SVNO; ///< the number of an SV (Space Vehicle, i.e. satellite) +typedef uint16_t HEALTH; ///< an SV's health code +typedef uint16_t CFG; ///< an SV's configuration code +typedef uint16_t IOD; ///< Issue-Of-Data code + + +/* the type of various checksums */ + +#ifndef _CSUM_DEFINED + typedef uint16_t CSUM; ///< checksum used by some structures stored in non-volatile memory + #define _CSUM_DEFINED + + #define _mbg_swab_csum( _p ) _mbg_swab16( _p ) +#endif + + +/** + * @brief The type of a GPS command code + * + * These command codes can be passed via + * @ref group_gps_cmds_serial "serial port" (see @file gpsserio.h), or + * @ref group_gps_cmds_bus "system bus" (see @file pcpsdefs.h). + */ +typedef uint16_t GPS_CMD; + +#define _mbg_swab_gps_cmd( _p ) _mbg_swab16( _p ) + + +/** + * @brief Software revision information + * + * Contains a software revision code, plus an optional + * identifier for a customized version. + */ +typedef struct +{ + uint16_t code; ///< Version number, e.g. 0x0120 means v1.20 + char name[GPS_ID_STR_SIZE]; ///< Optional string identifying a customized version + uint8_t reserved; ///< Reserved field to yield even structure size +} SW_REV; + +#define _mbg_swab_sw_rev( _p ) \ +{ \ + _mbg_swab16( &(_p)->code ); \ +} + + + +/** + * @defgroup group_bvar_stat BVAR_STAT status of buffered GPS data + * + * Status word, associated bit numbers and bit masks indicating + * whether certain data from the GPS satellites are + * available and valid. + * + * These bits defined are set in ::BVAR_STAT if the corresponding + * parameters are NOT valid and complete. + * + * @{ */ + +/** + * @brief Status flags of battery buffered data received + * from GPS satellites. + * + * All '0' means OK, single bits set to '1' indicate + * the associated type of GPS data is not available. + */ +typedef uint16_t BVAR_STAT; + +#define _mbg_swab_bvar_stat( _p ) _mbg_swab16( (_p) ) + + +/** + * @brief Enumeration of bits used with BVAR_STAT + * + * For each bit which is set this means the associated data set in + * non-volatile memory is not available or incomplete. + * Most data sets will just be re-collected from the data streams sent + * by the satellites. However, the receiver position has usually been + * computed earlier during normal operation, and will be re-computed + * when a sufficient number of satellites can be received. + */ +enum BVAR_BITS +{ + BVAR_BIT_CFGH_INVALID, ///< Satellite configuration and health parameters incomplete + BVAR_BIT_ALM_NOT_COMPLETE, ///< Almanac parameters incomplete + BVAR_BIT_UTC_INVALID, ///< %UTC offset parameters incomplete + BVAR_BIT_IONO_INVALID, ///< Ionospheric correction parameters incomplete + BVAR_BIT_RCVR_POS_INVALID, ///< No valid receiver position available + N_BVAR_BIT ///< number of defined ::BVAR_STAT bits +}; + +#define BVAR_CFGH_INVALID ( 1UL << BVAR_BIT_CFGH_INVALID ) ///< Configuration and health data (::CFGH) not valid +#define BVAR_ALM_NOT_COMPLETE ( 1UL << BVAR_BIT_ALM_NOT_COMPLETE ) ///< Almanach data (::ALM) not complete +#define BVAR_UTC_INVALID ( 1UL << BVAR_BIT_UTC_INVALID ) ///< ::UTC data not valid +#define BVAR_IONO_INVALID ( 1UL << BVAR_BIT_IONO_INVALID ) ///< Ionospheric correction data (::IONO) not valid +#define BVAR_RCVR_POS_INVALID ( 1UL << BVAR_BIT_RCVR_POS_INVALID ) ///< Receiver position (::POS) not valid + +#define BVAR_MASK ( ( 1UL << N_BVAR_BIT ) - 1 ) ///< Bit mask for all defined bits + +/** @} group_bvar_stat */ + + + +/** + * @brief A structure used to hold a fixed frequency value + * + * @note frequ[kHz] = khz_val * 10^range + */ +typedef struct +{ + uint16_t khz_val; ///< the base frequency in [kHz] + int16_t range; ///< an optional base 10 exponent +} FIXED_FREQ_INFO; + +#define _mbg_swab_fixed_freq_info( _p ) \ +{ \ + _mbg_swab16( &(_p)->khz_val ); \ + _mbg_swab16( &(_p)->range ); \ +} + + +/** + * @brief A data type to specify feature flags within ::RECEIVER_INFO + */ +typedef uint32_t RI_FEATURES; ///< @see GPS_FEATURE_MASKS + + + +/** + * @brief A structure used to identify a device type and supported features + * + * @note This may not be supported by some very old devices. + */ +typedef struct +{ + uint16_t model_code; ///< identifier for receiver model, see ::GPS_MODEL_CODES + SW_REV sw_rev; ///< software revision and ID + char model_name[GPS_ID_STR_SIZE]; ///< ASCIIZ, name of receiver model + char sernum[GPS_ID_STR_SIZE]; ///< ASCIIZ, serial number + char epld_name[GPS_EPLD_STR_SIZE]; ///< ASCIIZ, file name of EPLD image + uint8_t n_channels; ///< number of satellites which can be tracked simultaneously + uint32_t ticks_per_sec; ///< resolution of fractions of seconds, see ::GPS_TICKS_PER_SEC + RI_FEATURES features; ///< optional features, see ::GPS_FEATURE_MASKS + FIXED_FREQ_INFO fixed_freq; ///< optional non-standard fixed frequency + uint8_t osc_type; ///< type of installed oscillator, see ::GPS_OSC_TYPES + uint8_t osc_flags; ///< oscillator flags, actually not used and always 0 + uint8_t n_ucaps; ///< number of user time capture inputs + uint8_t n_com_ports; ///< number of on-board serial ports + uint8_t n_str_type; ///< max num of string types supported by any port + uint8_t n_prg_out; ///< number of programmable pulse outputs + uint16_t flags; ///< additional information, see ::RECEIVER_INFO_FLAG_BITS +} RECEIVER_INFO; + +#define _mbg_swab_receiver_info( _p ) \ +{ \ + _mbg_swab16( &(_p)->model_code ); \ + _mbg_swab_sw_rev( &(_p)->sw_rev ); \ + _mbg_swab16( &(_p)->ticks_per_sec ); \ + _mbg_swab32( &(_p)->features ); \ + _mbg_swab_fixed_freq_info( &(_p)->fixed_freq ); \ + _mbg_swab16( &(_p)->flags ); \ +} + + +/** + * @brief Known device ID codes for RECEIVER_INFO::model_code + */ +enum GPS_MODEL_CODES +{ + GPS_MODEL_UNKNOWN, + GPS_MODEL_GPS166, + GPS_MODEL_GPS167, + GPS_MODEL_GPS167SV, + GPS_MODEL_GPS167PC, + GPS_MODEL_GPS167PCI, + GPS_MODEL_GPS163, + GPS_MODEL_GPS168PCI, + GPS_MODEL_GPS161, + GPS_MODEL_GPS169PCI, + GPS_MODEL_TCR167PCI, + GPS_MODEL_GPS164, + GPS_MODEL_GPS170PCI, + GPS_MODEL_PZF511, + GPS_MODEL_GPS170, + GPS_MODEL_TCR511, + GPS_MODEL_AM511, + GPS_MODEL_MSF511, + GPS_MODEL_GRC170, + GPS_MODEL_GPS170PEX, + GPS_MODEL_GPS162, + GPS_MODEL_PTP270PEX, + GPS_MODEL_FRC511PEX, + GPS_MODEL_GEN170, + GPS_MODEL_TCR170PEX, + GPS_MODEL_WWVB511, + GPS_MODEL_MGR170, + GPS_MODEL_JJY511, + GPS_MODEL_PZF600, + GPS_MODEL_TCR600, + GPS_MODEL_GPS180, + GPS_MODEL_GLN170, + GPS_MODEL_GPS180PEX, + GPS_MODEL_TCR180PEX, + GPS_MODEL_PZF180PEX, + GPS_MODEL_MGR180, + GPS_MODEL_MSF600, + GPS_MODEL_WWVB600, + GPS_MODEL_JJY600, + GPS_MODEL_GPS180HS, + GPS_MODEL_GPS180AMC, + GPS_MODEL_ESI180, + GPS_MODEL_CPE180, + GPS_MODEL_LNO180, + GPS_MODEL_GRC180, + GPS_MODEL_LIU, + GPS_MODEL_DCF600HS, + GPS_MODEL_DCF600RS, + 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: + */ +#define GPS_MODEL_NAME_UNKNOWN "(unknown)" +#define GPS_MODEL_NAME_GPS166 "GPS166" +#define GPS_MODEL_NAME_GPS167 "GPS167" +#define GPS_MODEL_NAME_GPS167SV "GPS167SV" +#define GPS_MODEL_NAME_GPS167PC "GPS167PC" +#define GPS_MODEL_NAME_GPS167PCI "GPS167PCI" +#define GPS_MODEL_NAME_GPS163 "GPS163" +#define GPS_MODEL_NAME_GPS168PCI "GPS168PCI" +#define GPS_MODEL_NAME_GPS161 "GPS161" +#define GPS_MODEL_NAME_GPS169PCI "GPS169PCI" +#define GPS_MODEL_NAME_TCR167PCI "TCR167PCI" +#define GPS_MODEL_NAME_GPS164 "GPS164" +#define GPS_MODEL_NAME_GPS170PCI "GPS170PCI" +#define GPS_MODEL_NAME_PZF511 "PZF511" +#define GPS_MODEL_NAME_GPS170 "GPS170" +#define GPS_MODEL_NAME_TCR511 "TCR511" +#define GPS_MODEL_NAME_AM511 "AM511" +#define GPS_MODEL_NAME_MSF511 "MSF511" +#define GPS_MODEL_NAME_GRC170 "GRC170" +#define GPS_MODEL_NAME_GPS170PEX "GPS170PEX" +#define GPS_MODEL_NAME_GPS162 "GPS162" +#define GPS_MODEL_NAME_PTP270PEX "PTP270PEX" +#define GPS_MODEL_NAME_FRC511PEX "FRC511PEX" +#define GPS_MODEL_NAME_GEN170 "GEN170" +#define GPS_MODEL_NAME_TCR170PEX "TCR170PEX" +#define GPS_MODEL_NAME_WWVB511 "WWVB511" +#define GPS_MODEL_NAME_MGR170 "MGR170" +#define GPS_MODEL_NAME_JJY511 "JJY511" +#define GPS_MODEL_NAME_PZF600 "PZF600" +#define GPS_MODEL_NAME_TCR600 "TCR600" +#define GPS_MODEL_NAME_GPS180 "GPS180" +#define GPS_MODEL_NAME_GLN170 "GLN170" +#define GPS_MODEL_NAME_GPS180PEX "GPS180PEX" +#define GPS_MODEL_NAME_TCR180PEX "TCR180PEX" +#define GPS_MODEL_NAME_PZF180PEX "PZF180PEX" +#define GPS_MODEL_NAME_MGR180 "MGR180" +#define GPS_MODEL_NAME_MSF600 "MSF600" +#define GPS_MODEL_NAME_WWVB600 "WWVB600" +#define GPS_MODEL_NAME_JJY600 "JJY600" +#define GPS_MODEL_NAME_GPS180HS "GPS180HS" +#define GPS_MODEL_NAME_GPS180AMC "GPS180AMC" +#define GPS_MODEL_NAME_ESI180 "ESI180" +#define GPS_MODEL_NAME_CPE180 "CPE180" +#define GPS_MODEL_NAME_LNO180 "LNO180" +#define GPS_MODEL_NAME_GRC180 "GRC180" +#define GPS_MODEL_NAME_LIU "LIU" +#define GPS_MODEL_NAME_DCF600HS "DCF600HS" +#define GPS_MODEL_NAME_DCF600RS "DCF600RS" + +/* + * The definition below can be used to initialize + * an array of N_GPS_MODEL type name strings. + * Including the trailing 0, each name must not + * exceed GPS_ID_STR_SIZE chars. + */ +#define DEFAULT_GPS_MODEL_NAMES \ +{ \ + GPS_MODEL_NAME_UNKNOWN, \ + GPS_MODEL_NAME_GPS166, \ + GPS_MODEL_NAME_GPS167, \ + GPS_MODEL_NAME_GPS167SV, \ + GPS_MODEL_NAME_GPS167PC, \ + GPS_MODEL_NAME_GPS167PCI, \ + GPS_MODEL_NAME_GPS163, \ + GPS_MODEL_NAME_GPS168PCI, \ + GPS_MODEL_NAME_GPS161, \ + GPS_MODEL_NAME_GPS169PCI, \ + GPS_MODEL_NAME_TCR167PCI, \ + GPS_MODEL_NAME_GPS164, \ + GPS_MODEL_NAME_GPS170PCI, \ + GPS_MODEL_NAME_PZF511, \ + GPS_MODEL_NAME_GPS170, \ + GPS_MODEL_NAME_TCR511, \ + GPS_MODEL_NAME_AM511, \ + GPS_MODEL_NAME_MSF511, \ + GPS_MODEL_NAME_GRC170, \ + GPS_MODEL_NAME_GPS170PEX, \ + GPS_MODEL_NAME_GPS162, \ + GPS_MODEL_NAME_PTP270PEX, \ + GPS_MODEL_NAME_FRC511PEX, \ + GPS_MODEL_NAME_GEN170, \ + GPS_MODEL_NAME_TCR170PEX, \ + GPS_MODEL_NAME_WWVB511, \ + GPS_MODEL_NAME_MGR170, \ + GPS_MODEL_NAME_JJY511, \ + GPS_MODEL_NAME_PZF600, \ + GPS_MODEL_NAME_TCR600, \ + GPS_MODEL_NAME_GPS180, \ + GPS_MODEL_NAME_GLN170, \ + GPS_MODEL_NAME_GPS180PEX, \ + GPS_MODEL_NAME_TCR180PEX, \ + GPS_MODEL_NAME_PZF180PEX, \ + GPS_MODEL_NAME_MGR180, \ + GPS_MODEL_NAME_MSF600, \ + GPS_MODEL_NAME_WWVB600, \ + GPS_MODEL_NAME_JJY600, \ + GPS_MODEL_NAME_GPS180HS, \ + GPS_MODEL_NAME_GPS180AMC, \ + GPS_MODEL_NAME_ESI180, \ + GPS_MODEL_NAME_CPE180, \ + GPS_MODEL_NAME_LNO180, \ + GPS_MODEL_NAME_GRC180, \ + GPS_MODEL_NAME_LIU, \ + GPS_MODEL_NAME_DCF600HS, \ + GPS_MODEL_NAME_DCF600RS \ +} + + +/* + * The macros below can be used to classify a receiver, + * e.g. depending on the time source and/or depending on + * whether it's a plug-in card or an external device. + */ + +#define _mbg_rcvr_is_plug_in( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "PC" ) || \ + ( strstr( (_p_ri)->model_name, "PEX" ) ) + +#define _mbg_rcvr_is_gps( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "GPS" ) || \ + ( strstr( (_p_ri)->model_name, "MGR" ) ) + +#define _mbg_rcvr_is_mobile_gps( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "MGR" ) ) + +#define _mbg_rcvr_is_gps_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_gps( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_irig( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "TCR" ) ) + +#define _mbg_rcvr_is_irig_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_irig( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_dcf77_am( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "AM" ) ) + +#define _mbg_rcvr_is_dcf77_am_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_dcf77_am( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_dcf77_pzf( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "PZF" ) ) + +#define _mbg_rcvr_is_dcf77_pzf_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_dcf77_pzf( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_any_dcf77( _p_ri ) \ + ( _mbg_rcvr_is_dcf77_am( _p_ri ) || \ + _mbg_rcvr_is_dcf77_pzf( _p_ri ) ) + +#define _mbg_rcvr_is_any_dcf77_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_any_dcf77( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_msf( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "MSF" ) ) + +#define _mbg_rcvr_is_jjy( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "JJY" ) ) + +#define _mbg_rcvr_is_msf_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_msf( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_glonass( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "GRC" ) || \ + ( strstr( (_p_ri)->model_name, "GLN" ) ) + +#define _mbg_rcvr_is_glonass_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_glonass( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + +#define _mbg_rcvr_is_wwvb( _p_ri ) \ + ( strstr( (_p_ri)->model_name, "WWVB" ) ) + +#define _mbg_rcvr_is_wwvb_plug_in( _p_ri ) \ + ( _mbg_rcvr_is_wwvb( _p_ri ) && \ + _mbg_rcvr_is_plug_in( _p_ri ) ) + + +/** + * @brief Oscillator classification codes used with RECEIVER_INFO::osc_type + * + * New codes will just be appended to the enumeration, so the sequence + * of codes does NOT reflect the order of quality. + */ +enum GPS_OSC_TYPES +{ + GPS_OSC_UNKNOWN, + GPS_OSC_TCXO_LQ, + GPS_OSC_TCXO_HQ, + GPS_OSC_OCXO_LQ, + GPS_OSC_OCXO_MQ, + GPS_OSC_OCXO_HQ, + GPS_OSC_OCXO_XHQ, + GPS_OSC_RUBIDIUM, + GPS_OSC_TCXO_MQ, + GPS_OSC_OCXO_DHQ, + N_GPS_OSC +}; + + +/* + * The sequence and number of oscillator names + * listed below must correspond to the enumeration + * above: + */ +#define DEFAULT_GPS_OSC_NAMES \ +{ \ + "[unknown]", \ + "TCXO LQ", \ + "TCXO", \ + "OCXO LQ", \ + "OCXO MQ", \ + "OCXO HQ", \ + "OCXO XHQ", \ + "RUBIDIUM", \ + "TCXO MQ", \ + "OCXO DHQ" \ +} + + +/* + * The initializer below can be used to initialize + * an array (e.g. "int osc_quality_idx[N_GPS_OSC]") + * which allows to display the oscillator types + * ordered by quality: + */ +#define DEFAULT_GPS_OSC_QUALITY_IDX \ +{ \ + GPS_OSC_UNKNOWN, \ + GPS_OSC_TCXO_LQ, \ + GPS_OSC_TCXO_MQ, \ + GPS_OSC_TCXO_HQ, \ + GPS_OSC_OCXO_LQ, \ + GPS_OSC_OCXO_MQ, \ + GPS_OSC_OCXO_HQ, \ + GPS_OSC_OCXO_DHQ, \ + GPS_OSC_OCXO_XHQ, \ + GPS_OSC_RUBIDIUM \ +} + + + +/** + * @brief Enumeration of device features flags reported in RECEIVER_INFO::features + * + * Each flags indicates if a device supports the associated feature. + */ +enum GPS_FEATURE_BITS +{ + GPS_FEAT_PPS, ///< has pulse per second output + GPS_FEAT_PPM, ///< has pulse per minute output + GPS_FEAT_SYNTH, ///< has programmable synthesizer output + GPS_FEAT_DCFMARKS, ///< has DCF77 compatible time mark output + GPS_FEAT_IRIG_TX, ///< has on-board IRIG output + GPS_FEAT_IRIG_RX, ///< has on-board IRIG input + GPS_FEAT_LAN_IP4, ///< has 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", MBG_OPT_BIT_EMU_SYNC can be set alternatively + GPS_FEAT_5_MHZ, ///< output 5 MHz rather than 100 kHz + GPS_FEAT_XMULTI_REF, ///< has extended multiple input source configuration + GPS_FEAT_OPT_SETTINGS, ///< supports MBG_OPT_SETTINGS + GPS_FEAT_TIME_SCALE, ///< supports configurable time scale (%UTC, TAI, GPS, ...) + GPS_FEAT_IRIG_CTRL_BITS, ///< supports IRIG control bits + GPS_FEAT_PTP, ///< has PTP support + + GPS_FEAT_NAV_ENGINE_SETTINGS, ///< supports navigation engine configuration + GPS_FEAT_RAW_IRIG_DATA, ///< supports reading raw IRIG input data + GPS_FEAT_RAW_IRIG_TIME, ///< supports reading decoded IRIG time + GPS_FEAT_PTP_UNICAST, ///< has PTP Unicast support + GPS_FEAT_GPIO, ///< has general purpose in/outputs + GPS_FEAT_XMRS_MULT_INSTC, ///< multiple XMRS instances of the same ref type supported, see ::XMRSF_BIT_MULT_INSTC_SUPP + GPS_FEAT_10MHZ_DISBD, ///< 10 MHz output is always disabled + GPS_FEAT_EVT_LOG, ///< Event logging supported + + GPS_FEAT_IMS, ///< Support IMS data structures + GPS_FEAT_HAVEQUICK, ///< Support HaveQuick structures + + N_GPS_FEATURE ///< the number of valid features + /* + * If new features are added then care must be taken to update the associated + * definitions below accordingly, e.g. string initializers and bit masks. + */ +}; + + +/** + * @brief Names of device features + * + * @see GPS_FEATURE_BITS + */ +#define DEFAULT_GPS_FEATURE_NAMES \ +{ \ + "Pulse Per Second", \ + "Pulse Per Minute", \ + "Programmable Synth.", \ + "DCF77 Time Marks", \ + "IRIG Out", \ + "IRIG In", \ + "IPv4 LAN Interface", \ + "Multiple Ref. Sources", \ + "Receive Timeout", \ + "Ignore Lock", \ + "5 MHz Output", \ + "Ext. Multiple Ref. Src. Cfg.", \ + "Optional Settings", \ + "Configurable Time Scale", \ + "IRIG Control Bits", \ + "PTP/IEEE1588", \ + "Nav. Engine Settings", \ + "Raw IRIG Data", \ + "Raw IRIG Time", \ + "PTP/IEEE1588 Unicast", \ + "General Purpose I/O", \ + "Multiple XMRS Instances", \ + "10 MHz Output Disabled", \ + "Event Logging", \ + "IMS data", \ + "HaveQuick" \ +} + + +/** + * @brief Bit masks used with RECEIVER_INFO::features + * + * @see GPS_FEATURE_BITS + */ +enum GPS_FEATURE_MASKS +{ + GPS_HAS_PPS = ( 1UL << GPS_FEAT_PPS ), ///< see ::GPS_FEAT_PPS + GPS_HAS_PPM = ( 1UL << GPS_FEAT_PPM ), ///< see ::GPS_FEAT_PPM + GPS_HAS_SYNTH = ( 1UL << GPS_FEAT_SYNTH ), ///< see ::GPS_FEAT_SYNTH + GPS_HAS_DCFMARKS = ( 1UL << GPS_FEAT_DCFMARKS ), ///< see ::GPS_FEAT_DCFMARKS + GPS_HAS_IRIG_TX = ( 1UL << GPS_FEAT_IRIG_TX ), ///< see ::GPS_FEAT_IRIG_TX + GPS_HAS_IRIG_RX = ( 1UL << GPS_FEAT_IRIG_RX ), ///< see ::GPS_FEAT_IRIG_RX + GPS_HAS_LAN_IP4 = ( 1UL << GPS_FEAT_LAN_IP4 ), ///< see ::GPS_FEAT_LAN_IP4 + GPS_HAS_MULTI_REF = ( 1UL << GPS_FEAT_MULTI_REF ), ///< see ::GPS_FEAT_MULTI_REF + + GPS_HAS_RCV_TIMEOUT = ( 1UL << GPS_FEAT_RCV_TIMEOUT ), ///< see ::GPS_FEAT_RCV_TIMEOUT + GPS_HAS_IGNORE_LOCK = ( 1UL << GPS_FEAT_IGNORE_LOCK ), ///< see ::GPS_FEAT_IGNORE_LOCK + GPS_HAS_5_MHZ = ( 1UL << GPS_FEAT_5_MHZ ), ///< see ::GPS_FEAT_5_MHZ + GPS_HAS_XMULTI_REF = ( 1UL << GPS_FEAT_XMULTI_REF ), ///< see ::GPS_FEAT_XMULTI_REF + GPS_HAS_OPT_SETTINGS = ( 1UL << GPS_FEAT_OPT_SETTINGS ), ///< see ::GPS_FEAT_OPT_SETTINGS + GPS_HAS_TIME_SCALE = ( 1UL << GPS_FEAT_TIME_SCALE ), ///< see ::GPS_FEAT_TIME_SCALE + GPS_HAS_IRIG_CTRL_BITS = ( 1UL << GPS_FEAT_IRIG_CTRL_BITS ), ///< see ::GPS_FEAT_IRIG_CTRL_BITS + GPS_HAS_PTP = ( 1UL << GPS_FEAT_PTP ), ///< see ::GPS_FEAT_PTP + + GPS_HAS_NAV_ENGINE_SETTINGS = ( 1UL << GPS_FEAT_NAV_ENGINE_SETTINGS ), ///< see ::GPS_FEAT_NAV_ENGINE_SETTINGS + GPS_HAS_RAW_IRIG_DATA = ( 1UL << GPS_FEAT_RAW_IRIG_DATA ), ///< see ::GPS_FEAT_RAW_IRIG_DATA + GPS_HAS_RAW_IRIG_TIME = ( 1UL << GPS_FEAT_RAW_IRIG_TIME ), ///< see ::GPS_FEAT_RAW_IRIG_TIME + GPS_HAS_PTP_UNICAST = ( 1UL << GPS_FEAT_PTP_UNICAST ), ///< see ::GPS_FEAT_PTP_UNICAST + GPS_HAS_GPIO = ( 1UL << GPS_FEAT_GPIO ), ///< see ::GPS_FEAT_GPIO + GPS_HAS_XMRS_MULT_INSTC = ( 1UL << GPS_FEAT_XMRS_MULT_INSTC ), ///< see ::GPS_FEAT_XMRS_MULT_INSTC + GPS_HAS_10MHZ_DISBD = ( 1UL << GPS_FEAT_10MHZ_DISBD ), ///< see ::GPS_FEAT_10MHZ_DISBD + GPS_HAS_EVT_LOG = ( 1UL << GPS_FEAT_EVT_LOG ), ///< see ::GPS_FEAT_EVT_LOG + + GPS_HAS_IMS = ( 1UL << GPS_FEAT_IMS ), ///< see ::GPS_FEAT_IMS + GPS_HAS_HAVEQUICK = ( 1UL << GPS_FEAT_HAVEQUICK ), ///< see ::GPS_FEAT_HAVEQUICK + + // the next ones are special since they just shadow another flag: + GPS_HAS_REF_OFFS = GPS_HAS_IRIG_RX, ///< always supported with IRIG inputs, see ::GPS_HAS_IRIG_RX + GPS_HAS_DEBUG_INFO = GPS_HAS_IRIG_RX ///< always supported with IRIG inputs, see ::GPS_HAS_IRIG_RX +}; + + +/* + * The features below are supported by default by older + * C166 based GPS receivers: + */ +#define DEFAULT_GPS_FEATURES_C166 \ +{ \ + GPS_HAS_PPS | \ + GPS_HAS_PPM | \ + GPS_HAS_SYNTH | \ + GPS_HAS_DCFMARKS \ +} + + +/** + * @brief Bits to be used with RECEIVER_INFO::flags + */ +enum RECEIVER_INFO_FLAG_BITS +{ + GPS_BIT_OSC_CFG_SUPP, ///< oscillator cfg is supported, see ::RECEIVER_INFO::osc_type + GPS_BIT_IRIG_FO_IN, ///< IRIG input via fiber optics + GPS_BIT_HAS_FPGA, ///< device provides on-board FPGA + N_RECEIVER_INFO_FLAG_BITS ///< number of known bits +}; + +#define GPS_OSC_CFG_SUPP ( 1UL << GPS_BIT_OSC_CFG_SUPP ) +#define GPS_IRIG_FO_IN ( 1UL << GPS_BIT_IRIG_FO_IN ) +#define GPS_HAS_FPGA ( 1UL << GPS_BIT_HAS_FPGA ) + + + +/* + * If the GPS_HAS_FPGA flag is set in RECEIVER_INFO::flags then the card + * provides an FPGA and the following information about the FPGA is available: + */ +#define FPGA_NAME_LEN 31 // max name length +#define FPGA_NAME_SIZE ( FPGA_NAME_LEN + 1 ) // size including trailing 0 + +#define FPGA_INFO_SIZE 128 + +typedef union +{ + struct + { + CSUM csum; + uint32_t fsize; + #if _IS_MBG_FIRMWARE + uint32_t start_addr; + #else + uint8_t *start_addr; + #endif + char name[FPGA_NAME_SIZE]; + } hdr; + + char b[FPGA_INFO_SIZE]; + +} FPGA_INFO; + + + +/* + * The definitions below are used to specify where a FPGA image is located + * in the flash memory: + */ +typedef struct +{ + CSUM csum; + uint16_t fpga_start_seg; // Number of the 4k block where an FPGA image is located +} FPGA_START_INFO; + +#define DEFAULT_FPGA_START_SEG 0x60 + +#define DEFAULT_FPGA_START_INFO \ +{ \ + 0x1234 + DEFAULT_FPGA_START_SEG, \ + DEFAULT_FPGA_START_SEG \ +} + + + +/** + * @brief A structure used to hold time in GPS format + * + * Date and time refer to the linear time scale defined by GPS, with + * the epoch starting at %UTC midnight at the beginning of January 6, 1980. + * + * GPS time is counted by the week numbers since the epoch, plus second + * of the week, plus fraction of the second. The week number transmitted + * by the satellites rolls over from 1023 to 0, but Meinberg devices + * just continue to count the weeks beyond the 1024 week limit to keep + * the receiver's internal time. + * + * %UTC time differs from GPS time since a number of leap seconds have + * been inserted in the %UTC time scale after the GPS epoche. The number + * of leap seconds is disseminated by the satellites using the ::UTC + * parameter set, which also provides info on pending leap seconds. + */ +typedef struct +{ + uint16_t wn; ///< the week number since GPS has been installed + uint32_t sec; ///< the second of that week + uint32_t tick; ///< fractions of a second; scale: 1/::RECEIVER_INFO::ticks_per_sec +} T_GPS; + +#define _mbg_swab_t_gps( _p ) \ +{ \ + _mbg_swab16( &(_p)->wn ); \ + _mbg_swab32( &(_p)->sec ); \ + _mbg_swab32( &(_p)->tick ); \ +} + + +/** + * @brief Local date and time computed from GPS time + * + * The current number of leap seconds have to be added to get %UTC + * from GPS time. Additional corrections could have been made according + * to the time zone/daylight saving parameters ::TZDL defined by the user. + * The status field can be checked to see which corrections + * have actually been applied. + * + * @note Conversion from GPS time to %UTC and/or local time can only be + * done if some valid ::UTC correction parameters are available in the + * receiver's non-volatile memory. + */ +typedef struct +{ + int16_t year; ///< year number, 0..9999 + int8_t month; ///< month, 1..12 + int8_t mday; ///< day of month, 1..31 + int16_t yday; ///< day of year, 1..366 + int8_t wday; ///< day of week, 0..6 == Sun..Sat + int8_t hour; ///< hours, 0..23 + int8_t min; ///< minutes, 0..59 + int8_t sec; ///< seconds, 0..59 + int32_t frac; ///< fractions of a second; scale: 1/::RECEIVER_INFO::ticks_per_sec + int32_t offs_from_utc; ///< local time's offset from %UTC + uint16_t status; ///< status flags, see ::TM_GPS_STATUS_BITS +} TM_GPS; + +#define _mbg_swab_tm_gps( _p ) \ +{ \ + _mbg_swab16( &(_p)->year ); \ + _mbg_swab16( &(_p)->yday ); \ + _mbg_swab32( &(_p)->frac ); \ + _mbg_swab32( &(_p)->offs_from_utc ); \ + _mbg_swab16( &(_p)->status ); \ +} + + +/** + * @brief Status flags used with TM_GPS::status + * + * These bits report info on the time conversion from GPS time to %UTC + * and/or local time as well as device status info. + */ +enum TM_GPS_STATUS_BITS +{ + TM_BIT_UTC, ///< %UTC correction has been made + TM_BIT_LOCAL, ///< %UTC has been converted to local time according to ::TZDL settings + TM_BIT_DL_ANN, ///< state of daylight saving is going to change + TM_BIT_DL_ENB, ///< daylight saving is in effect + TM_BIT_LS_ANN, ///< leap second pending + TM_BIT_LS_ENB, ///< current second is leap second + TM_BIT_LS_ANN_NEG, ///< set in addition to ::TM_BIT_LS_ANN if leap sec is negative + TM_BIT_INVT, ///< invalid time, e.g. if RTC battery bas been empty + + TM_BIT_EXT_SYNC, ///< synchronized externally + TM_BIT_HOLDOVER, ///< in holdover mode after previous synchronization + TM_BIT_ANT_SHORT, ///< antenna cable short circuited + TM_BIT_NO_WARM, ///< OCXO has not warmed up + TM_BIT_ANT_DISCONN, ///< antenna currently disconnected + TM_BIT_SYN_FLAG, ///< TIME_SYN output is low + TM_BIT_NO_SYNC, ///< time sync actually not verified + TM_BIT_NO_POS ///< position actually not verified, LOCK LED off +}; + +// bit masks corresponding to the flag bits above +#define TM_UTC ( 1UL << TM_BIT_UTC ) +#define TM_LOCAL ( 1UL << TM_BIT_LOCAL ) +#define TM_DL_ANN ( 1UL << TM_BIT_DL_ANN ) +#define TM_DL_ENB ( 1UL << TM_BIT_DL_ENB ) +#define TM_LS_ANN ( 1UL << TM_BIT_LS_ANN ) +#define TM_LS_ENB ( 1UL << TM_BIT_LS_ENB ) +#define TM_LS_ANN_NEG ( 1UL << TM_BIT_LS_ANN_NEG ) +#define TM_INVT ( 1UL << TM_BIT_INVT ) + +#define TM_EXT_SYNC ( 1UL << TM_BIT_EXT_SYNC ) +#define TM_HOLDOVER ( 1UL << TM_BIT_HOLDOVER ) +#define TM_ANT_SHORT ( 1UL << TM_BIT_ANT_SHORT ) +#define TM_NO_WARM ( 1UL << TM_BIT_NO_WARM ) +#define TM_ANT_DISCONN ( 1UL << TM_BIT_ANT_DISCONN ) +#define TM_SYN_FLAG ( 1UL << TM_BIT_SYN_FLAG ) +#define TM_NO_SYNC ( 1UL << TM_BIT_NO_SYNC ) +#define TM_NO_POS ( 1UL << TM_BIT_NO_POS ) + + +/** + * @brief Type of an extended TM status which is mainly used inside the firmware + */ +typedef uint32_t TM_STATUS_EXT; + +/** + * @brief Enumeration of extended status bits used with TM_STATUS_EXT + * + * @note The lower 16 bits correspond to ::TM_GPS_STATUS_BITS + */ +enum TM_GPS_STATUS_BITS_EX +{ + TM_BIT_SCALE_GPS = 16, ///< time scale configured to return GPS time + TM_BIT_SCALE_TAI ///< time scale configured to return TAI + // the remaining bits are reserved +}; + +// The following bits are only used with the TM_STATUS_X type: +#define TM_SCALE_GPS ( 1UL << TM_BIT_SCALE_GPS ) +#define TM_SCALE_TAI ( 1UL << TM_BIT_SCALE_TAI ) + +#define TM_MSK_TIME_VALID ( TM_UTC | TM_SCALE_GPS | TM_SCALE_TAI ) + + +/** + * @brief A structure used to transmit information on date and time + * + * This structure can be used to transfer the current time, in which + * case the channel field has to be set to -1, or an event capture time + * retrieved from the on-board FIFO, in which case the channel field + * contains the index of the time capture input, e.g. 0 or 1. + */ +typedef struct +{ + int16_t channel; ///< -1: the current on-board time; >= 0 the capture channel number + T_GPS t; ///< time in GPS scale and format + TM_GPS tm; ///< time converted to %UTC and/or local time according to ::TZDL settings +} TTM; + +#define _mbg_swab_ttm( _p ) \ +{ \ + _mbg_swab16( &(_p)->channel ); \ + _mbg_swab_t_gps( &(_p)->t ); \ + _mbg_swab_tm_gps( &(_p)->tm ); \ +} + + + +/** + * @brief A timestamp with nanosecond resolution + */ +typedef struct +{ + int32_t nano_secs; ///< [nanoseconds] + int32_t secs; ///< [seconds] +} NANO_TIME; + +#define _mbg_swab_nano_time( _p ) \ +{ \ + _mbg_swab32( &(_p)->nano_secs ); \ + _mbg_swab32( &(_p)->secs ); \ +} + +// The macro below checks if a NANO_TIME value is negative. +#define _nano_time_negative( _nt ) \ + ( ( (_nt)->secs < 0 ) || ( (_nt)->nano_secs < 0 ) ) + + + +/* Two types of variables used to store a position. Type XYZ is */ +/* used with a position in earth centered, earth fixed (ECEF) */ +/* coordinates whereas type LLA holds such a position converted */ +/* to geographic coordinates as defined by WGS84 (World Geodetic */ +/* System from 1984). */ + +#ifndef _XYZ_DEFINED + /** + * @brief Sequence and number of components of a cartesian position + */ + enum XYZ_FIELDS { XP, YP, ZP, N_XYZ }; // x, y, z + + /** + * @brief An array holding a cartesian position + */ + typedef double XYZ[N_XYZ]; ///< values are in [m], see ::XYZ_FIELDS + + #define _XYZ_DEFINED +#endif + +#define _mbg_swab_xyz( _p ) _mbg_swab_doubles( _p, N_XYZ ) + + +#ifndef _LLA_DEFINED + /** + * @brief Sequence and number of components of a geographic position + */ + enum LLA_FIELDS { LAT, LON, ALT, N_LLA }; /* latitude, longitude, altitude */ + + /** + * @brief An array holding a geographic position + */ + typedef double LLA[N_LLA]; ///< lon, lat in [rad], alt in [m], see ::LLA_FIELDS + + #define _LLA_DEFINED +#endif + +#define _mbg_swab_lla( _p ) _mbg_swab_doubles( _p, N_LLA ) + + +/** + @defgroup group_synth Synthesizer parameters + + Synthesizer frequency is expressed as a + four digit decimal number (freq) to be multiplied by 0.1 Hz and an + base 10 exponent (range). If the effective frequency is less than + 10 kHz its phase is synchronized corresponding to the variable phase. + Phase may be in a range from -360 deg to +360 deg with a resolution + of 0.1 deg, so the resulting numbers to be stored are in a range of + -3600 to +3600. + + Example:<br> + Assume the value of freq is 2345 (decimal) and the value of phase is 900. + If range == 0 the effective frequency is 234.5 Hz with a phase of +90 deg. + If range == 1 the synthesizer will generate a 2345 Hz output frequency + and so on. + + Limitations:<br> + If freq == 0 the synthesizer is disabled. If range == 0 the least + significant digit of freq is limited to 0, 3, 5 or 6. The resulting + frequency is shown in the examples below: + - freq == 1230 --> 123.0 Hz + - freq == 1233 --> 123 1/3 Hz (real 1/3 Hz, NOT 123.3 Hz) + - freq == 1235 --> 123.5 Hz + - freq == 1236 --> 123 2/3 Hz (real 2/3 Hz, NOT 123.6 Hz) + + If range == MAX_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 +#define N_SYNTH_RANGE ( MAX_SYNTH_RANGE - MIN_SYNTH_RANGE + 1 ) + +#define N_SYNTH_PHASE_DIGIT 4 +#define MAX_SYNTH_PHASE 3600 + + +#define MAX_SYNTH_FREQ_EDIT 9999 ///< max sequence of digits when editing + +/** + * @brief The maximum frequency that can be configured for the synthesizer + */ +#define MAX_SYNTH_FREQ_VAL 10000000UL ///< 10 MHz +/* == MAX_SYNTH_FREQ * 10^(MAX_SYNTH_RANGE-1) */ + +/** + * @brief The synthesizer's phase is only be synchronized if the frequency is below this limit + */ +#define SYNTH_PHASE_SYNC_LIMIT 10000UL ///< 10 kHz + +/** + * A Macro used to determine the position of the decimal point + * when printing the synthesizer frequency as 4 digit value + */ +#define _synth_dp_pos_from_range( _r ) \ + ( ( ( N_SYNTH_RANGE - (_r) ) % ( N_SYNTH_FREQ_DIGIT - 1 ) ) + 1 ) + +/** + * @brief Synthesizer frequency units + * + * An initializer for commonly displayed synthesizer frequency units + * (N_SYNTH_RANGE strings) + */ +#define DEFAULT_FREQ_RANGES \ +{ \ + "Hz", \ + "kHz", \ + "kHz", \ + "kHz", \ + "MHz", \ + "MHz", \ +} + + + +/** + * @brief Synthesizer configuration parameters + */ +typedef struct +{ + int16_t freq; ///< four digits used; scale: 0.1; e.g. 1234 -> 123.4 Hz + int16_t range; ///< scale factor for freq; 0..::MAX_SYNTH_RANGE + int16_t phase; ///< -::MAX_SYNTH_PHASE..+::MAX_SYNTH_PHASE; >0 -> pulses later +} SYNTH; + +#define _mbg_swab_synth( _p ) \ +{ \ + _mbg_swab16( &(_p)->freq ); \ + _mbg_swab16( &(_p)->range ); \ + _mbg_swab16( &(_p)->phase ); \ +} + + +/** + * @brief Enumeration of synthesizer states + */ +enum SYNTH_STATES +{ + SYNTH_DISABLED, ///< disbled by cfg, i.e. freq == 0.0 + SYNTH_OFF, ///< not enabled after power-up + SYNTH_FREE, ///< enabled, but not synchronized + SYNTH_DRIFTING, ///< has initially been sync'd, but now running free + SYNTH_SYNC, ///< fully synchronized + N_SYNTH_STATE ///< the number of known states +}; + + +/** + * @brief A structure used to report the synthesizer state + */ +typedef struct +{ + uint8_t state; ///< state code as enumerated in ::SYNTH_STATES + uint8_t flags; ///< reserved, currently always 0 +} SYNTH_STATE; + +#define _mbg_swab_synth_state( _p ) _nop_macro_fnc() + +#define SYNTH_FLAG_PHASE_IGNORED 0x01 + +/** @} group_synth */ + +/** + * @defgroup group_tzdl Time zone/daylight saving parameters + * + * Example: <br> + * For automatic daylight saving enable/disable in Central Europe, + * the variables are to be set as shown below: <br> + * - offs = 3600L one hour from %UTC + * - offs_dl = 3600L one additional hour if daylight saving enabled + * - tm_on = first Sunday from March 25, 02:00:00h ( year |= DL_AUTO_FLAG ) + * - tm_off = first Sunday from October 25, 03:00:00h ( year |= DL_AUTO_FLAG ) + * - name[0] == "CET " name if daylight saving not enabled + * - name[1] == "CEST " name if daylight saving is enabled + * @{ + */ + +/** + * @brief The name of a time zone + * + * @note Up to 5 printable characters plus trailing zero + */ +typedef char TZ_NAME[6]; + +/** + * @brief Time zone / daylight saving parameters + * + * This structure is used to specify how a device is to convert + * on-board %UTC to local time, including computation of beginning + * and end of daylight saving time (DST), if required. + */ +typedef struct +{ + int32_t offs; ///< standard offset from %UTC to local time [sec] + int32_t offs_dl; ///< additional offset if daylight saving enabled [sec] + TM_GPS tm_on; ///< date/time when daylight saving starts + TM_GPS tm_off; ///< date/time when daylight saving ends + TZ_NAME name[2]; ///< names without and with daylight saving enabled +} TZDL; + +#define _mbg_swab_tzdl( _p ) \ +{ \ + _mbg_swab32( &(_p)->offs ); \ + _mbg_swab32( &(_p)->offs_dl ); \ + _mbg_swab_tm_gps( &(_p)->tm_on ); \ + _mbg_swab_tm_gps( &(_p)->tm_off ); \ +} + + +/** + * @brief A flag indicating automatic computation of DST + * + * If this flag is or'ed to the year numbers in TZDL::tm_on and TZDL::tm_off + * then daylight saving is computed automatically year by year. + */ +#define DL_AUTO_FLAG 0x8000 + + + +// Below there are some initializers for commonly used TZDL configurations: + +#define DEFAULT_TZDL_AUTO_YEAR ( 2007 | DL_AUTO_FLAG ) + +#define DEFAULt_TZDL_OFFS_DL 3600L /**< usually DST is +1 hour */ + + +/** + * An initializer for TZDL::tm_on and TZDL::tm_off for time zones + * which do not observe DST. + */ +#define DEFAULT_TZDL_TM_ON_OFF_NO_DST \ + { DEFAULT_TZDL_AUTO_YEAR, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 } + + +// Settings used with %UTC: + +#define TZ_INFO_UTC "UTC (Universal Time, Coordinated)" + +#define DEFAULT_TZDL_NAMES_UTC { "UTC ", "UTC " } + +#define DEFAULT_TZDL_UTC \ +{ \ + 0L, /**< offs */ \ + 0L, /**< offs_dl */ \ + DEFAULT_TZDL_TM_ON_OFF_NO_DST, /**< tm_on */ \ + DEFAULT_TZDL_TM_ON_OFF_NO_DST, /**< tm_off */ \ + DEFAULT_TZDL_NAMES_UTC /**< name[] */ \ +} + + +/** + * @brief An initializer for TZDL::tm_on according to the rules for Central Europe + */ +#define DEFAULT_TZDL_TM_ON_CET_CEST \ + { DEFAULT_TZDL_AUTO_YEAR, 3, 25, 0, 0, 2, 0, 0, 0L, 0L, 0 } + +/** + * @brief An initializer for TZDL::tm_off according to the rules for Central Europe + */ +#define DEFAULT_TZDL_TM_OFF_CET_CEST \ + { DEFAULT_TZDL_AUTO_YEAR, 10, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 } + + +// Settings used with Central European Time: + +#define TZ_INFO_CET_CEST_EN "CET/CEST (Central Europe)" +#define TZ_INFO_CET_CEST_DE "MEZ/MESZ (Mitteleuropa)" + +#define DEFAULT_TZDL_NAMES_CET_CEST_EN { "CET ", "CEST " } +#define DEFAULT_TZDL_NAMES_CET_CEST_DE { "MEZ ", "MESZ " } + +#define DEFAULT_TZDL_OFFS_CET 3600L + +#define DEFAULT_TZDL_CET_CEST_EN \ +{ \ + DEFAULT_TZDL_OFFS_CET, /**< offs */ \ + DEFAULt_TZDL_OFFS_DL, /**< offs_dl */ \ + DEFAULT_TZDL_TM_ON_CET_CEST, /**< tm_on */ \ + DEFAULT_TZDL_TM_OFF_CET_CEST, /**< tm_off */ \ + DEFAULT_TZDL_NAMES_CET_CEST_EN /**< name[] */ \ +} + +#define DEFAULT_TZDL_CET_CEST_DE \ +{ \ + DEFAULT_TZDL_OFFS_CET, /**< offs */ \ + DEFAULt_TZDL_OFFS_DL, /**< offs_dl */ \ + DEFAULT_TZDL_TM_ON_CET_CEST, /**< tm_on */ \ + DEFAULT_TZDL_TM_OFF_CET_CEST, /**< tm_off */ \ + DEFAULT_TZDL_NAMES_CET_CEST_DE /**< name[] */ \ +} + + +// The symbols below specify beginning and end of DST for +// Easter Europe, as constituted by the European Parliament: + +#define DEFAULT_TZDL_TM_ON_EET_EEST \ + { DEFAULT_TZDL_AUTO_YEAR, 3, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 } + +#define DEFAULT_TZDL_TM_OFF_EET_EEST \ + { DEFAULT_TZDL_AUTO_YEAR, 10, 25, 0, 0, 4, 0, 0, 0L, 0L, 0 } + + +// Settings used with Eastern European Time: + +#define TZ_INFO_EET_EEST_EN "EET/EEST (East Europe)" +#define TZ_INFO_EET_EEST_DE "OEZ/OEST (Osteuropa)" + +#define DEFAULT_TZDL_NAMES_EET_EEST_EN { "EET ", "EEST " } +#define DEFAULT_TZDL_NAMES_EET_EEST_DE { "OEZ ", "OESZ " } + +#define DEFAULT_TZDL_OFFS_EET 7200L + +#define DEFAULT_TZDL_EET_EEST_EN \ +{ \ + DEFAULT_TZDL_OFFS_EET, /* offs */ \ + DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \ + DEFAULT_TZDL_TM_ON_EET_EEST, /* tm_on */ \ + DEFAULT_TZDL_TM_OFF_EET_EEST, /* tm_off */ \ + DEFAULT_TZDL_NAMES_EET_EEST_EN /* name[] */ \ +} + +#define DEFAULT_TZDL_EET_EEST_DE \ +{ \ + DEFAULT_TZDL_OFFS_EET, /* offs */ \ + DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \ + DEFAULT_TZDL_TM_ON_EET_EEST, /* tm_on */ \ + DEFAULT_TZDL_TM_OFF_EET_EEST, /* tm_off */ \ + DEFAULT_TZDL_NAMES_EET_EEST_DE /* name[] */ \ +} + +/** @} group_tzdl */ + + + +/** + * @brief Antenna status information + * + * The structure below reflects the status of the antenna, + * the times of last disconnect/reconnect, and the board's + * clock offset after the disconnection interval. + * + * @note ANT_INFO::status changes back to ::ANT_RECONN only + * after the antenna has been reconnected <b>and</b> the + * receiver has re-synchronized to the satellite signal. + * In this case ANT_INFO::delta_t reports the time offset + * before resynchronization, i.e. how much the internal + * time has drifted while the antenna was disconnected. + */ +typedef struct +{ + int16_t status; ///< current status of antenna, see ::ANT_STATUS_CODES + TM_GPS tm_disconn; ///< time of antenna disconnect + TM_GPS tm_reconn; ///< time of antenna reconnect + int32_t delta_t; ///< clock offs at reconn. time in 1/::RECEIVER_INFO::ticks_per_sec +} ANT_INFO; + +#define _mbg_swab_ant_info( _p ) \ +{ \ + _mbg_swab16( &(_p)->status ); \ + _mbg_swab_tm_gps( &(_p)->tm_disconn ); \ + _mbg_swab_tm_gps( &(_p)->tm_reconn ); \ + _mbg_swab32( &(_p)->delta_t ); \ +} + + +/** + * @brief Status code used with ANT_INFO::status + */ +enum ANT_STATUS_CODES +{ + ANT_INVALID, ///< No other fields valid since antenna has not yet been disconnected + ANT_DISCONN, ///< Antenna is disconnected, tm_reconn and delta_t not yet set + ANT_RECONN, ///< Antenna has been disconnect, and receiver sync. after reconnect, so all fields valid + N_ANT_STATUS_CODES ///< the number of known status codes +}; + + +/* 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 */ + +/** + * @brief A structure controlling when output signals are enabled + * + * The structure holds some flags which let the corresponding outputs + * be disabled after power-up until the receiver has synchronized + * (flag == ::EF_OFF, the default) or force the outputs to be enabled + * immediately after power-up. The fixed frequency output is hard-wired + * to be enabled immediately after power-up, so ENABLE_FLAGS::freq must + * always be set to ::EF_FREQ_ALL. + */ +typedef struct +{ + uint16_t serial; ///< ::EF_OFF or ::EF_SERIAL_BOTH + uint16_t pulses; ///< ::EF_OFF or ::EF_PULSES_BOTH + uint16_t freq; ///< always ::EF_FREQ_ALL + uint16_t synth; ///< ::EF_OFF or ::EF_SYNTH +} ENABLE_FLAGS; + +#define _mbg_swab_enable_flags( _p ) \ +{ \ + _mbg_swab16( &(_p)->serial ); \ + _mbg_swab16( &(_p)->pulses ); \ + _mbg_swab16( &(_p)->freq ); \ + _mbg_swab16( &(_p)->synth ); \ +} + + +/* A struct used to hold the settings of a serial port: */ + +#ifndef _COM_HS_DEFINED + /** + * @brief Enumeration of handshake modes + */ + enum COM_HANSHAKE_MODES { HS_NONE, HS_XONXOFF, HS_RTSCTS, N_COM_HS }; + #define _COM_HS_DEFINED +#endif + +#ifndef _COM_PARM_DEFINED + /** + * @brief A data type to configure a baud rate + */ + typedef int32_t BAUD_RATE; + + /** + * @brief Indices used to identify a parameter in the framing string + */ + enum { F_DBITS, F_PRTY, F_STBITS }; + + /** + * @brief A structure to store the configuration of a serial port + */ + typedef struct + { + BAUD_RATE baud_rate; ///< transmission speed, e.g. 19200L + char framing[4]; ///< ASCIIZ framing string, e.g. "8N1" or "7E2" + int16_t handshake; ///< handshake mode, yet only ::HS_NONE supported + + } COM_PARM; + + #define _COM_PARM_DEFINED +#endif + +#define _mbg_swab_baud_rate( _p ) _mbg_swab32( _p ) + +#define _mbg_swab_com_parm( _p ) \ +{ \ + _mbg_swab_baud_rate( &(_p)->baud_rate ); \ + _mbg_swab16( &(_p)->handshake ); \ +} + + +/** + * @brief Indices of any supported serial port baud rates + * + * @note Most clock models and/or serial ports don't support all defined baud rates. + */ +enum MBG_BAUD_RATE_CODES +{ + MBG_BAUD_RATE_300, + MBG_BAUD_RATE_600, + MBG_BAUD_RATE_1200, + MBG_BAUD_RATE_2400, + MBG_BAUD_RATE_4800, + MBG_BAUD_RATE_9600, + MBG_BAUD_RATE_19200, + MBG_BAUD_RATE_38400, + N_MBG_BAUD_RATES /**< the number of supported baud rates */ +}; + +/* + * An initializer for a table of baud rate values. + * The values must correspond to the enumeration above. + */ +#define MBG_BAUD_RATES \ +{ \ + 300L, \ + 600L, \ + 1200L, \ + 2400L, \ + 4800L, \ + 9600L, \ + 19200L, \ + 38400L \ +} + +/* + * An initializer for a table of baud rate strings. + * The values must correspond to the enumeration above. + */ +#define MBG_BAUD_STRS \ +{ \ + "300", \ + "600", \ + "1200", \ + "2400", \ + "4800", \ + "9600", \ + "19200", \ + "38400" \ +} + +/* + * The bit masks below can be used to determine which baud rates + * are supported by a serial port. This may vary between + * different ports of the same device since different + * types of UART are used which must not necessarily support + * each baud rate: + */ +#define MBG_PORT_HAS_300 ( 1UL << MBG_BAUD_RATE_300 ) +#define MBG_PORT_HAS_600 ( 1UL << MBG_BAUD_RATE_600 ) +#define MBG_PORT_HAS_1200 ( 1UL << MBG_BAUD_RATE_1200 ) +#define MBG_PORT_HAS_2400 ( 1UL << MBG_BAUD_RATE_2400 ) +#define MBG_PORT_HAS_4800 ( 1UL << MBG_BAUD_RATE_4800 ) +#define MBG_PORT_HAS_9600 ( 1UL << MBG_BAUD_RATE_9600 ) +#define MBG_PORT_HAS_19200 ( 1UL << MBG_BAUD_RATE_19200 ) +#define MBG_PORT_HAS_38400 ( 1UL << MBG_BAUD_RATE_38400 ) + + +/** + * @brief Indices of any supported serial port framings. + * + * @note Most clock models and/or serial ports don't support all defined framing types. + */ +enum MBG_FRAMING_CODES +{ + MBG_FRAMING_7N2, + MBG_FRAMING_7E1, + MBG_FRAMING_7E2, + MBG_FRAMING_8N1, + MBG_FRAMING_8N2, + MBG_FRAMING_8E1, + MBG_FRAMING_7O1, + MBG_FRAMING_7O2, + MBG_FRAMING_8O1, + MBG_FRAMING_8E2, /**< @note: Most serial ports don't support this! */ + N_MBG_FRAMINGS /**< the number of supported framings */ +}; + +/* + * An initializer for a table of framing strings. + * The values must correspond to the enumeration above. + */ +#define MBG_FRAMING_STRS \ +{ \ + "7N2", \ + "7E1", \ + "7E2", \ + "8N1", \ + "8N2", \ + "8E1", \ + "7O1", \ + "7O2", \ + "8O1", \ + "8E2" \ +} + +/* + * The bit masks below can be used to determine which framings + * are supported by a serial port. This may vary between + * different ports of the same device since different + * types of UART are used which must not necessarily support + * each framing type: + */ +#define MBG_PORT_HAS_7N2 ( 1UL << MBG_FRAMING_7N2 ) +#define MBG_PORT_HAS_7E1 ( 1UL << MBG_FRAMING_7E1 ) +#define MBG_PORT_HAS_7E2 ( 1UL << MBG_FRAMING_7E2 ) +#define MBG_PORT_HAS_8N1 ( 1UL << MBG_FRAMING_8N1 ) +#define MBG_PORT_HAS_8N2 ( 1UL << MBG_FRAMING_8N2 ) +#define MBG_PORT_HAS_8E1 ( 1UL << MBG_FRAMING_8E1 ) +#define MBG_PORT_HAS_7O1 ( 1UL << MBG_FRAMING_7O1 ) +#define MBG_PORT_HAS_7O2 ( 1UL << MBG_FRAMING_7O2 ) +#define MBG_PORT_HAS_8O1 ( 1UL << MBG_FRAMING_8O1 ) +#define MBG_PORT_HAS_8E2 ( 1UL << MBG_FRAMING_8E2 ) + + +// Default port settings to be used +// with the binary protocol +#define MBG_DEFAULT_BAUDRATE 19200L +#define MBG_DEFAULT_FRAMING "8N1" + + + +/* + * By default, the baud rates and framings below + * are supported by the UARTs integrated into + * the C166 microcontroller: + */ +#define DEFAULT_GPS_BAUD_RATES_C166 \ +( \ + MBG_PORT_HAS_300 | \ + MBG_PORT_HAS_600 | \ + MBG_PORT_HAS_1200 | \ + MBG_PORT_HAS_2400 | \ + MBG_PORT_HAS_4800 | \ + MBG_PORT_HAS_9600 | \ + MBG_PORT_HAS_19200 \ +) + +#define DEFAULT_GPS_FRAMINGS_C166 \ +( \ + MBG_PORT_HAS_7N2 | \ + MBG_PORT_HAS_7E1 | \ + MBG_PORT_HAS_7E2 | \ + MBG_PORT_HAS_8N1 | \ + MBG_PORT_HAS_8N2 | \ + MBG_PORT_HAS_8E1 \ +) + + +/* + * By default, the baud rates and framings below + * are supported by the UARTs integrated into + * the GP2021 chipset: + */ +#define DEFAULT_GPS_BAUD_RATES_GP2021 \ +( \ + MBG_PORT_HAS_300 | \ + MBG_PORT_HAS_600 | \ + MBG_PORT_HAS_1200 | \ + MBG_PORT_HAS_2400 | \ + MBG_PORT_HAS_4800 | \ + MBG_PORT_HAS_9600 | \ + MBG_PORT_HAS_19200 \ +) + +#define DEFAULT_GPS_FRAMINGS_GP2021 \ +( \ + MBG_PORT_HAS_7N2 | \ + MBG_PORT_HAS_7E2 | \ + MBG_PORT_HAS_8N1 | \ + MBG_PORT_HAS_8E1 | \ + MBG_PORT_HAS_8O1 \ +) + + +/** + * @brief Configuration settings of a serial port + * + * @note This should be used preferably instead of + * ::PORT_PARM, which is deprecated. + */ +typedef struct +{ + COM_PARM parm; ///< transmission speed, framing, etc. + uint8_t mode; ///< string mode, see ::STR_MODES + uint8_t str_type; ///< index of the supported time string formats, see ::STR_TYPE_INFO_IDX + uint32_t flags; ///< @see COM_CFG_STATUS_BITS +} PORT_SETTINGS; + +#define _mbg_swab_port_settings( _p ) \ +{ \ + _mbg_swab_com_parm( &(_p)->parm ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/** + * @brief Flag bits used to marks individual ::PORT_SETTINGS fields + * + * These definitions can be used to mark specific fields of a + * PORT_SETTINGS structure, e.g. which fields have changed when + * editing, or which fields have settings which are not valid. + */ +enum MBG_COM_CFG_STATUS_BITS +{ + MBG_PS_BIT_BAUD_RATE_OVR_SW, ///< Baud rate index exceeds num supp by driver SW + MBG_PS_BIT_BAUD_RATE_OVR_DEV, ///< Baud rate index exceeds num supp by device + MBG_PS_BIT_BAUD_RATE, ///< Baud rate not supp by given port + MBG_PS_BIT_FRAMING_OVR_SW, ///< Framing index exceeds num supp by driver SW + MBG_PS_BIT_FRAMING_OVR_DEV, ///< Framing index exceeds num supp by device + MBG_PS_BIT_FRAMING, ///< Framing not supp by given port + MBG_PS_BIT_HS_OVR_SW, ///< Handshake index exceeds num supp by driver SW + MBG_PS_BIT_HS, ///< Handshake mode not supp by given port + MBG_PS_BIT_STR_TYPE_OVR_SW, ///< String type index exceeds num supp by driver SW + MBG_PS_BIT_STR_TYPE_OVR_DEV, ///< String type index exceeds num supp by device + MBG_PS_BIT_STR_TYPE, ///< String type not supp by given port + MBG_PS_BIT_STR_MODE_OVR_SW, ///< String mode index exceeds num supp by driver SW + MBG_PS_BIT_STR_MODE_OVR_DEV, ///< String mode index exceeds num supp by device + MBG_PS_BIT_STR_MODE, ///< String mode not supp by given port and string type + MBG_PS_BIT_FLAGS_OVR_SW, ///< Flags not supp by driver SW + MBG_PS_BIT_FLAGS, ///< Flags not supp by device + N_MBG_PS_BIT +}; + +#define MBG_PS_MSK_BAUD_RATE_OVR_SW ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_SW ) +#define MBG_PS_MSK_BAUD_RATE_OVR_DEV ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_DEV ) +#define MBG_PS_MSK_BAUD_RATE ( 1UL << MBG_PS_BIT_BAUD_RATE ) +#define MBG_PS_MSK_FRAMING_OVR_SW ( 1UL << MBG_PS_BIT_FRAMING_OVR_SW ) +#define MBG_PS_MSK_FRAMING_OVR_DEV ( 1UL << MBG_PS_BIT_FRAMING_OVR_DEV ) +#define MBG_PS_MSK_FRAMING ( 1UL << MBG_PS_BIT_FRAMING ) +#define MBG_PS_MSK_HS_OVR_SW ( 1UL << MBG_PS_BIT_HS_OVR_SW ) +#define MBG_PS_MSK_HS ( 1UL << MBG_PS_BIT_HS ) +#define MBG_PS_MSK_STR_TYPE_OVR_SW ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_SW ) +#define MBG_PS_MSK_STR_TYPE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_DEV ) +#define MBG_PS_MSK_STR_TYPE ( 1UL << MBG_PS_BIT_STR_TYPE ) +#define MBG_PS_MSK_STR_MODE_OVR_SW ( 1UL << MBG_PS_BIT_STR_MODE_OVR_SW ) +#define MBG_PS_MSK_STR_MODE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_MODE_OVR_DEV ) +#define MBG_PS_MSK_STR_MODE ( 1UL << MBG_PS_BIT_STR_MODE ) +#define MBG_PS_MSK_FLAGS_OVR_SW ( 1UL << MBG_PS_BIT_FLAGS_OVR_SW ) +#define MBG_PS_MSK_FLAGS ( 1UL << MBG_PS_BIT_FLAGS ) + + + +/** + * @brief Configuration settings of a specific serial port + * + * This structure should be sent to a device to configure + * a specific serial port. The number of supported ports + * is RECEIVER_INFO::n_com_port. + * + * @note The ::PORT_INFO_IDX structure should be read from + * a device to retrieve the current settings and capabilities. + * + * @see STR_TYPE_INFO + */ +typedef struct +{ + uint16_t idx; ///< port index, 0..RECEIVER_INFO::n_com_port - 1 + PORT_SETTINGS port_settings; +} PORT_SETTINGS_IDX; + +#define _mbg_swab_port_settings_idx( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_port_settings( &(_p)->port_settings ); \ +} + + +/** + * @brief Current settings and general capabilities of a serial port + * + * @note This structure should be read from a device to retrieve + * the current settings of a serial port plus its capabilities, + * e.g. supported baud rates, supported string formats, etc. + * + * @see STR_TYPE_INFO + */ +typedef struct +{ + PORT_SETTINGS port_settings; ///< current configuration of the port + uint32_t supp_baud_rates; ///< bit mask of baud rates supp. by this port, see ::MBG_BAUD_RATE_CODES + uint32_t supp_framings; ///< bit mask of framings supp. by this port, see ::MBG_FRAMING_CODES + uint32_t supp_str_types; ///< bit mask of string types supp. by this port, i.e. bit 0 set if str_type[0] is supp. + uint32_t reserved; ///< reserved for future use, currently always 0 + uint32_t flags; ///< @see COM_CFG_STATUS_BITS +} PORT_INFO; + +#define _mbg_swab_port_info( _p ) \ +{ \ + _mbg_swab_port_settings( &(_p)->port_settings ); \ + _mbg_swab32( &(_p)->supp_baud_rates ); \ + _mbg_swab32( &(_p)->supp_framings ); \ + _mbg_swab32( &(_p)->supp_str_types ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/** + * @brief Flags used with PORT_SETTINGS::flags and PORT_INFO::flags + */ +enum COM_CFG_STATUS_BITS +{ + PORT_FLAG_BIT_PORT_INVISIBLE, ///< port is used internally and should not be displayed by config apps + N_PORT_FLAGS ///< the number of defined bits +}; + +#define PORT_FLAG_PORT_INVISIBLE ( 1UL << PORT_FLAG_BIT_PORT_INVISIBLE ) + + + +/** + * @brief Current settings and general capabilities of a specific serial port + * + * This structure should be read from the device to retrieve the + * current settings of a specific serial port plus its capabilities, + * e.g. supported baud rates, supported string formats, etc. + * The number of supported ports is RECEIVER_INFO::n_com_port. + * + * @note The ::PORT_SETTINGS_IDX structure should be send back to + * the device to configure the specified serial port. + */ +typedef struct +{ + uint16_t idx; ///< port index, 0..RECEIVER_INFO::n_com_port - 1 + PORT_INFO port_info; +} PORT_INFO_IDX; + +#define _mbg_swab_port_info_idx( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_port_info( &(_p)->port_info ); \ +} + + +/** + * @brief Information on a supported string format + * + * Information includes the name of the string format, which + * transmission modes are supported, etc. + * + * The number of string types, and which string types are supported + * depends on the device type and firmware version. + * + * @note The structure ::STR_TYPE_INFO_IDX should be read repeatedly + * to retrieve all supported string types. + */ +typedef struct +{ + uint32_t supp_modes; ///< bit mask of modes supp. for this string type + char long_name[23]; ///< long name of the string format + char short_name[11]; ///< short name of the string format + uint16_t flags; ///< reserved, currently always 0 +} STR_TYPE_INFO; + +#define _mbg_swab_str_type_info( _p ) \ +{ \ + _mbg_swab32( &(_p)->supp_modes ); \ + _mbg_swab16( &(_p)->flags ); \ +} + + + +/** + * @brief Information on a specific supported string format + * + * This structure should be read from a device to retrieve information + * on a specific supported time string type from an array of supported + * string types. The number of supported string types is returned + * in RECEIVER_INFO::n_str_type. + * + * A selected index number can be saved in PORT_SETTINGS::str_type to + * configure the selected string type for the specific serial port. + */ +typedef struct +{ + uint16_t idx; ///< string type index, 0..RECEIVER_INFO::n_str_type - 1 + STR_TYPE_INFO str_type_info; +} STR_TYPE_INFO_IDX; + +#define _mbg_swab_str_type_info_idx( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_str_type_info( &(_p)->str_type_info ); \ +} + + +/** + * @brief Modes supported for time string transmission + * + * This determines e.g. at which point in time a string starts + * to be transmitted via the serial port. + */ +enum STR_MODES +{ + STR_ON_REQ, ///< transmission on request by received '?' only + STR_PER_SEC, ///< transmission automatically if second changes + STR_PER_MIN, ///< transmission automatically if minute changes + STR_AUTO, ///< transmission automatically if required, e.g. on capture event + STR_ON_REQ_SEC, ///< transmission if second changes and a request has been received before + N_STR_MODE ///< the number of known modes +}; + + +#define DEFAULT_SHORT_MODE_NAMES \ +{ \ + "'?'", \ + "1 sec", \ + "1 min", \ + "auto", \ + "'?' sec" \ +} + + +/* + * Default initializers for English mode string names. Initializers + * for multi-language strings can be found in pcpslstr.h. + */ +#define ENG_MODE_NAME_STR_ON_REQ "on request '?' only" +#define ENG_MODE_NAME_STR_PER_SEC "per second" +#define ENG_MODE_NAME_STR_PER_MIN "per minute" +#define ENG_MODE_NAME_STR_AUTO "automatically" +#define ENG_MODE_NAME_STR_ON_REQ_SEC "sec after request" + +#define DEFAULT_ENG_MODE_NAMES \ +{ \ + ENG_MODE_NAME_STR_ON_REQ, \ + ENG_MODE_NAME_STR_PER_SEC, \ + ENG_MODE_NAME_STR_PER_MIN, \ + ENG_MODE_NAME_STR_AUTO, \ + ENG_MODE_NAME_STR_ON_REQ_SEC \ +} + +/* + * The definitions below are used to set up bit masks + * which restrict the modes which can be used with + * a given string type: + */ +#define MSK_STR_ON_REQ ( 1UL << STR_ON_REQ ) +#define MSK_STR_PER_SEC ( 1UL << STR_PER_SEC ) +#define MSK_STR_PER_MIN ( 1UL << STR_PER_MIN ) +#define MSK_STR_AUTO ( 1UL << STR_AUTO ) +#define MSK_STR_ON_REQ_SEC ( 1UL << STR_ON_REQ_SEC ) + + +/* + * The modes below are supported by most string types: + */ +#define DEFAULT_STR_MODES \ +( \ + MSK_STR_ON_REQ | \ + MSK_STR_PER_SEC | \ + MSK_STR_PER_MIN \ +) + + +/* + * The modes below can be used with the capture string: + */ +#define DEFAULT_STR_MODES_UCAP \ +( \ + MSK_STR_ON_REQ | \ + MSK_STR_AUTO \ +) + + + +/** + * The number of serial ports which are at least available + * even with very old GPS receiver models + */ +#define DEFAULT_N_COM 2 + +/* + * By default that's also the number of ports + * currently available: + */ +#ifndef N_COM + #define N_COM DEFAULT_N_COM +#endif + +/** + * @brief A The structure used to store the configuration of both serial ports + * + * @deprecated This structure is deprecated, ::PORT_SETTINGS and related structures + * should be used instead, if supported by the device. + */ +typedef struct +{ + COM_PARM com[DEFAULT_N_COM]; /**< COM0 and COM1 settings */ + uint8_t mode[DEFAULT_N_COM]; /**< COM0 and COM1 output mode */ +} PORT_PARM; + +#define _mbg_swab_port_parm( _p ) \ +{ \ + int i; \ + for ( i = 0; i < DEFAULT_N_COM; i++ ) \ + { \ + _mbg_swab_com_parm( &(_p)->com[i] ); \ + /* no need to swap mode byte */ \ + } \ +} + + +/* + * The codes below were used with the obsolete + * PORT_PARM.mode above. They are defined for + * compatibility with older devices only: + */ +enum +{ + /* STR_ON_REQ, defined above */ + /* STR_PER_SEC, defined above */ + /* STR_PER_MIN, defined above */ + N_STR_MODE_0 = STR_AUTO, /* COM0 and COM1 */ + STR_UCAP = N_STR_MODE_0, + STR_UCAP_REQ, + N_STR_MODE_1 /* COM1 only */ +}; + + + +/** + @defgroup group_icode IRIG codes + + The following definitions are used to configure an optional + on-board IRIG input or output. Which frame types are supported + by a device depends on the device type, and may eventually + depend on the device's firmware version. + + All IRIG frames transport the day-of-year number plus the time-of-day, + and include a control field segment which can transport user defined + information. + + Some newer IRIG frames are compatible with older frame types but support + well defined extensions like the year number, local time offset, DST status, + etc., in the control fields: + + - Supported IRIG signal code types: + - \b A002: 1000 bps, DCLS, time-of-year + - \b A003: 1000 bps, DCLS, time-of-year, SBS + - \b A132: 1000 bps, 10 kHz carrier, time-of-year + - \b A133: 1000 bps, 10 kHz carrier, time-of-year, SBS + - \b B002: 100 bps, DCLS, time-of-year + - \b B003: 100 bps, DCLS, time-of-year, SBS + - \b B122: 100 bps, 1 kHz carrier, time-of-year + - \b B123: 100 bps, 1 kHz carrier, time-of-year, SBS + - \b B006: 100 bps, DCLS, complete date + - \b B007: 100 bps, DCLS, complete date, SBS + - \b B126: 100 bps, 1 kHz carrier, complete date + - \b B127: 100 bps, 1 kHz carrier, complete date, SBS + - \b B220/1344: 100 bps, DCLS, manchester encoded, IEEE1344 extensions + - \b B222: 100 bps, DCLS, manchester encoded, time-of-year + - \b B223: 100 bps, DCLS, manchester encoded, time-of-year, SBS + - \b G002: 10 kbps, DCLS, time-of-year + - \b G142: 10 kbps, 100 kHz carrier, time-of-year + - \b G006: 10 kbps, DCLS, complete date + - \b G146: 10 kbps, 100 kHz carrier, complete date + - \b AFNOR: 100 bps, 1 kHz carrier, SBS, complete date + - <b> AFNOR DC:</b> 100 bps, DCLS, SBS, complete date + - \b IEEE1344: 100 bps, 1 kHz carrier, time-of-year, SBS, IEEE1344 extensions (B120) + - <b> IEEE1344 DC:</b> 100 bps, DCLS, time-of-year, SBS, IEEE1344 extensions (B000) + - \b C37.118: like IEEE1344, but %UTC offset with reversed sign + - \b C37.118 DC: like IEEE1344 DC, but %UTC offset with reversed sign + + - time-of-year: day-of-year, hours, minutes, seconds + - complete date: time-of-year plus year number + - SBS: straight binary seconds, second-of-day + + AFNOR codes are based on the french standard AFNOR NF S87-500 + + IEEE1344 codes are defined in IEEE standard 1344-1995. The code frame is compatible + with B002/B122 but provides some well defined extensions in the control field which + include a quality indicator (time figure of merit, TFOM), year number, DST and leap + second status, and local time offset from %UTC. + + C37.118 codes are defined in IEEE standard C37.118-2005 which includes a revised version + of the IEEE 1344 standard from 1995. These codes provide the same extensions as IEEE 1344 + but unfortunately define the %UTC offset with reversed sign. + + @note There are 3rd party IRIG devices out there which apply the %UTC offset as specified + in C37.118, but claim to be compatible with IEEE 1344. So if local time is transmitted + by the IRIG signal then care must be taken that the %UTC offset is evaluated by the IRIG + receiver in the same way as computed by the IRIG generator. Otherwise the %UTC + time computed by the receiver may be <b>wrong</b>. + @{ + */ + +/** + * @brief Known IRIG TX code formats + * + * Definitions used with IRIG transmitters which usually output both + * the unmodulated and the modulated IRIG signals at the same time. + */ +enum ICODE_TX_CODES +{ + ICODE_TX_B002_B122, + ICODE_TX_B003_B123, + ICODE_TX_A002_A132, + ICODE_TX_A003_A133, + ICODE_TX_AFNOR, + ICODE_TX_IEEE1344, + ICODE_TX_B2201344, ///< DCLS only + ICODE_TX_B222, ///< DCLS only + ICODE_TX_B223, ///< DCLS only + ICODE_TX_B006_B126, + ICODE_TX_B007_B127, + ICODE_TX_G002_G142, + ICODE_TX_G006_G146, + ICODE_TX_C37118, + ICODE_TX_TXC101, + ICODE_TX_E002_E112, + ICODE_TX_NASA36, + N_ICODE_TX ///< number of known codes +}; + + +/** + * Initializers for format name strings. + */ +#define DEFAULT_ICODE_TX_NAMES \ +{ \ + "B002+B122", \ + "B003+B123", \ + "A002+A132", \ + "A003+A133", \ + "AFNOR NF S87-500", \ + "IEEE1344", \ + "B220(1344) DCLS", \ + "B222 DCLS", \ + "B223 DCLS", \ + "B006+B126", \ + "B007+B127", \ + "G002+G142", \ + "G006+G146", \ + "C37.118", \ + "TXC-101 DTR-6", \ + "E002+E112", \ + "NASA 36" \ +} + +/** + * Initializers for short name strings which must not + * be longer than 10 printable characters. + */ +#define DEFAULT_ICODE_TX_NAMES_SHORT \ +{ \ + "B002+B122", \ + "B003+B123", \ + "A002+A132", \ + "A003+A133", \ + "AFNOR NF-S", \ + "IEEE1344", \ + "B220/1344", \ + "B222 DC", \ + "B223 DC", \ + "B006+B126", \ + "B007+B127", \ + "G002+G142", \ + "G006+G146", \ + "C37.118", \ + "TXC-101", \ + "E002+E112", \ + "NASA 36" \ +} + + +/** + * Initializers for English format description strings. + */ +#define DEFAULT_ICODE_TX_DESCRIPTIONS_ENG \ +{ \ + "100 bps, DCLS or 1 kHz carrier", \ + "100 bps, DCLS or 1 kHz carrier, SBS", \ + "1000 bps, DCLS or 10 kHz carrier", \ + "1000 bps, DCLS or 10 kHz carrier, SBS", \ + "100 bps, DCLS or 1 kHz carrier, SBS, complete date", \ + "100 bps, DCLS or 1 kHz carrier, SBS, complete date, time zone info", \ + "100 bps, Manchester enc., DCLS only, SBS, complete date, time zone info", \ + "100 bps, Manchester enc., DCLS only", \ + "100 bps, Manchester enc., DCLS only, SBS", \ + "100 bps, DCLS or 1 kHz carrier, complete date", \ + "100 bps, DCLS or 1 kHz carrier, complete date, SBS", \ + "10 kbps, DCLS or 100 kHz carrier", \ + "10 kbps, DCLS or 100 kHz carrier, complete date", \ + "like IEEE1344, but UTC offset with reversed sign", \ + "code from TV time sync device TXC-101 DTR-6", \ + "10 bps, DCLS or 100 Hz carrier", \ + "100 bps, DCLS or 1 kHz carrier" \ +} + +/* + * The definitions below are used to set up bit masks + * which restrict the IRIG formats which are supported + * by a given IRIG transmitter device: + */ +#define MSK_ICODE_TX_B002_B122 ( 1UL << ICODE_TX_B002_B122 ) +#define MSK_ICODE_TX_B003_B123 ( 1UL << ICODE_TX_B003_B123 ) +#define MSK_ICODE_TX_A002_A132 ( 1UL << ICODE_TX_A002_A132 ) +#define MSK_ICODE_TX_A003_A133 ( 1UL << ICODE_TX_A003_A133 ) +#define MSK_ICODE_TX_AFNOR ( 1UL << ICODE_TX_AFNOR ) +#define MSK_ICODE_TX_IEEE1344 ( 1UL << ICODE_TX_IEEE1344 ) +#define MSK_ICODE_TX_B2201344 ( 1UL << ICODE_TX_B2201344 ) +#define MSK_ICODE_TX_B222 ( 1UL << ICODE_TX_B222 ) +#define MSK_ICODE_TX_B223 ( 1UL << ICODE_TX_B223 ) +#define MSK_ICODE_TX_B006_B126 ( 1UL << ICODE_TX_B006_B126 ) +#define MSK_ICODE_TX_B007_B127 ( 1UL << ICODE_TX_B007_B127 ) +#define MSK_ICODE_TX_G002_G142 ( 1UL << ICODE_TX_G002_G142 ) +#define MSK_ICODE_TX_G006_G146 ( 1UL << ICODE_TX_G006_G146 ) +#define MSK_ICODE_TX_C37118 ( 1UL << ICODE_TX_C37118 ) +#define MSK_ICODE_TX_TXC101 ( 1UL << ICODE_TX_TXC101 ) +#define MSK_ICODE_TX_E002_E112 ( 1UL << ICODE_TX_E002_E112 ) +#define MSK_ICODE_TX_NASA36 ( 1UL << ICODE_TX_NASA36 ) + +/** + * A mask of IRIG formats with manchester encoded DC output: + */ +#define MSK_ICODE_TX_DC_MANCH \ +( \ + MSK_ICODE_TX_B2201344 | \ + MSK_ICODE_TX_B222 | \ + MSK_ICODE_TX_B223 \ +) + +/** + * A mask of IRIG formats with 100 Hz carrier: + */ +#define MSK_ICODE_TX_100HZ \ +( \ + MSK_ICODE_TX_E002_E112 \ +) + +/** + * A mask of IRIG formats with 1 kHz carrier: + */ +#define MSK_ICODE_TX_1KHZ \ +( \ + MSK_ICODE_TX_B002_B122 | \ + MSK_ICODE_TX_B003_B123 | \ + MSK_ICODE_TX_AFNOR | \ + MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_B2201344 | \ + MSK_ICODE_TX_B222 | \ + MSK_ICODE_TX_B223 | \ + MSK_ICODE_TX_B006_B126 | \ + MSK_ICODE_TX_B007_B127 | \ + MSK_ICODE_TX_C37118 | \ + MSK_ICODE_TX_NASA36 \ +) + +/** + * A mask of IRIG formats with 10 kHz carrier: + */ +#define MSK_ICODE_TX_10KHZ \ +( \ + MSK_ICODE_TX_A002_A132 | \ + 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 10 bps data rate: + */ +#define MSK_ICODE_TX_10BPS \ +( \ + MSK_ICODE_TX_E002_E112 \ +) + +/** + * A mask of IRIG formats with 100 bps data rate: + */ +#define MSK_ICODE_TX_100BPS \ +( \ + MSK_ICODE_TX_B002_B122 | \ + MSK_ICODE_TX_B003_B123 | \ + MSK_ICODE_TX_AFNOR | \ + MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_B006_B126 | \ + MSK_ICODE_TX_B007_B127 | \ + MSK_ICODE_TX_C37118 \ +) + +/** + * A mask of IRIG formats with 1000 bps data rate: + */ +#define MSK_ICODE_TX_1000BPS \ +( \ + MSK_ICODE_TX_A002_A132 | \ + MSK_ICODE_TX_A003_A133 \ +) + +/** + * 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 \ +( \ + MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_C37118 \ +) + +/** + * A mask of IRIG formats which support time zone information: + */ +#define MSK_ICODE_TX_HAS_TZI \ +( \ + MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_C37118 \ +) + +/** + * The default mask of IRIG formats supported by + * IRIG transmitters: + */ +#if !defined( SUPP_MSK_ICODE_TX ) + #define SUPP_MSK_ICODE_TX \ + ( \ + MSK_ICODE_TX_B002_B122 | \ + MSK_ICODE_TX_B003_B123 | \ + MSK_ICODE_TX_A002_A132 | \ + MSK_ICODE_TX_A003_A133 | \ + MSK_ICODE_TX_AFNOR \ + ) +#endif + + + +/** + * @brief Known IRIG RX code formats + * + * Definitions used with IRIG receivers which decode + * two similar IRIG codes (with or without SBS) + * at the same time. + */ +enum ICODE_RX_CODES +{ + ICODE_RX_B122_B123, ///< modulated + ICODE_RX_A132_A133, ///< modulated + ICODE_RX_B002_B003, ///< DCLS + ICODE_RX_A002_A003, ///< DCLS + ICODE_RX_AFNOR, ///< modulated + ICODE_RX_AFNOR_DC, ///< DCLS + ICODE_RX_IEEE1344, ///< modulated + ICODE_RX_IEEE1344_DC, ///< DCLS + ICODE_RX_B126_B127, ///< modulated + ICODE_RX_B006_B007, ///< DCLS + ICODE_RX_G142_G146, ///< modulated + ICODE_RX_G002_G006, ///< DCLS + ICODE_RX_C37118, ///< modulated + ICODE_RX_C37118_DC, ///< DCLS + ICODE_RX_TXC101, ///< modulated + ICODE_RX_TXC101_DC, ///< DCLS + ICODE_RX_E112, ///< modulated + ICODE_RX_E002, ///< DCLS + ICODE_RX_NASA36, ///< modulated + ICODE_RX_NASA36_DC, ///< DCLS + N_ICODE_RX ///< the number of known codes +}; + +/** + * Initializers for format name strings. + */ +#define DEFAULT_ICODE_RX_NAMES \ +{ \ + "B122/B123", \ + "A132/A133", \ + "B002/B003 (DCLS)", \ + "A002/A003 (DCLS)", \ + "AFNOR NF S87-500", \ + "AFNOR NF S87-500 (DCLS)", \ + "IEEE1344", \ + "IEEE1344 (DCLS)", \ + "B126/B127", \ + "B006/B007 (DCLS)", \ + "G142/G146", \ + "G002/G006 (DCLS)", \ + "C37.118", \ + "C37.118 (DCLS)", \ + "TXC-101 DTR-6", \ + "TXC-101 DTR-6 (DCLS)", \ + "E112", \ + "E002 (DCLS)", \ + "NASA-36", \ + "NASA-36 (DCLS)" \ +} + +/** + * Initializers for short name strings which must not + * be longer than 11 printable characters. + */ +#define DEFAULT_ICODE_RX_NAMES_SHORT \ +{ \ + "B122/B123", \ + "A132/A133", \ + "B002/B003", \ + "A002/A003", \ + "AFNOR NF-S", \ + "AFNOR DC", \ + "IEEE1344", \ + "IEEE1344 DC", \ + "B126/B127", \ + "B006/B007", \ + "G142/G146", \ + "G002/G006", \ + "C37.118", \ + "C37.118 DC", \ + "TXC-101", \ + "TXC-101 DC", \ + "E112", \ + "E002 DC", \ + "NASA-36", \ + "NASA-36 DC" \ +} + + +/** + * Initializers for English format description strings. + */ +#define DEFAULT_ICODE_RX_DESCRIPTIONS_ENG \ +{ \ + "100 bps, 1 kHz carrier, SBS optionally", \ + "1000 bps, 10 kHz carrier, SBS optionally", \ + "100 bps, DCLS, SBS optionally", \ + "1000 bps, DCLS, SBS optionally", \ + "100 bps, 1 kHz carrier, SBS, complete date", \ + "100 bps, DCLS, SBS, complete date", \ + "100 bps, 1 kHz carrier, SBS, time zone info", \ + "100 bps, DCLS, SBS, time zone info", \ + "100 bps, 1 kHz carrier, complete date, SBS optionally", \ + "100 bps, DCLS, complete date, SBS optionally", \ + "10 kbps, 100 kHz carrier, complete date optionally", \ + "10 kbps, DCLS, complete date optionally", \ + "like IEEE1344, but UTC offset with reversed sign", \ + "like IEEE1344 DC, but UTC offset with reversed sign", \ + "code from TV time sync device TXC-101 DTR-6", \ + "DC code from TV time sync device TXC-101 DTR-6", \ + "10 bps, 100 Hz carrier", \ + "10 bps, DCLS", \ + "100 bps, 1 kHz carrier", \ + "100 bps, DCLS" \ +} + +/* + * Bit masks corresponding to the enumeration above: + */ +#define MSK_ICODE_RX_B122_B123 ( 1UL << ICODE_RX_B122_B123 ) +#define MSK_ICODE_RX_A132_A133 ( 1UL << ICODE_RX_A132_A133 ) +#define MSK_ICODE_RX_B002_B003 ( 1UL << ICODE_RX_B002_B003 ) +#define MSK_ICODE_RX_A002_A003 ( 1UL << ICODE_RX_A002_A003 ) +#define MSK_ICODE_RX_AFNOR ( 1UL << ICODE_RX_AFNOR ) +#define MSK_ICODE_RX_AFNOR_DC ( 1UL << ICODE_RX_AFNOR_DC ) +#define MSK_ICODE_RX_IEEE1344 ( 1UL << ICODE_RX_IEEE1344 ) +#define MSK_ICODE_RX_IEEE1344_DC ( 1UL << ICODE_RX_IEEE1344_DC ) +#define MSK_ICODE_RX_B126_B127 ( 1UL << ICODE_RX_B126_B127 ) +#define MSK_ICODE_RX_B006_B007 ( 1UL << ICODE_RX_B006_B007 ) +#define MSK_ICODE_RX_G142_G146 ( 1UL << ICODE_RX_G142_G146 ) +#define MSK_ICODE_RX_G002_G006 ( 1UL << ICODE_RX_G002_G006 ) +#define MSK_ICODE_RX_C37118 ( 1UL << ICODE_RX_C37118 ) +#define MSK_ICODE_RX_C37118_DC ( 1UL << ICODE_RX_C37118_DC ) +#define MSK_ICODE_RX_TXC101 ( 1UL << ICODE_RX_TXC101 ) +#define MSK_ICODE_RX_TXC101_DC ( 1UL << ICODE_RX_TXC101_DC ) +#define MSK_ICODE_RX_E112 ( 1UL << ICODE_RX_E112 ) +#define MSK_ICODE_RX_E002 ( 1UL << ICODE_RX_E002 ) +#define MSK_ICODE_RX_NASA36 ( 1UL << ICODE_RX_NASA36 ) +#define MSK_ICODE_RX_NASA36_DC ( 1UL << ICODE_RX_NASA36_DC ) + +/** + * A mask of IRIG DCLS formats: + */ +#define MSK_ICODE_RX_DC \ +( \ + MSK_ICODE_RX_B002_B003 | \ + MSK_ICODE_RX_A002_A003 | \ + MSK_ICODE_RX_AFNOR_DC | \ + MSK_ICODE_RX_IEEE1344_DC | \ + MSK_ICODE_RX_B006_B007 | \ + MSK_ICODE_RX_G002_G006 | \ + MSK_ICODE_RX_C37118_DC | \ + MSK_ICODE_RX_TXC101_DC | \ + MSK_ICODE_RX_E002 | \ + MSK_ICODE_RX_NASA36_DC \ +) + +/** + * A mask of IRIG formats with 100 Hz carrier: + */ +#define MSK_ICODE_RX_100HZ \ +( \ + MSK_ICODE_RX_E112 | \ + MSK_ICODE_RX_E002 \ +) + +/** + * A mask of IRIG formats with 1 kHz carrier: + */ +#define MSK_ICODE_RX_1KHZ \ +( \ + MSK_ICODE_RX_B122_B123 | \ + MSK_ICODE_RX_AFNOR | \ + MSK_ICODE_RX_IEEE1344 | \ + MSK_ICODE_RX_B126_B127 | \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_TXC101 | \ + MSK_ICODE_RX_NASA36 \ +) + +/** + * A mask of IRIG formats with 10 kHz carrier: + */ +#define MSK_ICODE_RX_10KHZ \ +( \ + 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 10 bps data rate: + */ +#define MSK_ICODE_RX_10BPS \ +( \ + MSK_ICODE_RX_E002_E112 | \ + MSK_ICODE_RX_E002_E002 \ +) + +/** + * A mask of IRIG formats with 100 bps data rate: + */ +#define MSK_ICODE_RX_100BPS \ +( \ + MSK_ICODE_RX_B122_B123 | \ + MSK_ICODE_RX_B002_B003 | \ + MSK_ICODE_RX_AFNOR | \ + MSK_ICODE_RX_AFNOR_DC | \ + MSK_ICODE_RX_IEEE1344 | \ + MSK_ICODE_RX_IEEE1344_DC | \ + MSK_ICODE_RX_B126_B127 | \ + MSK_ICODE_RX_B006_B007 | \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_C37118_DC | \ + MSK_ICODE_RX_TXC101 | \ + MSK_ICODE_RX_TXC101_DC | \ + MSK_ICODE_RX_NASA36 | \ + MSK_ICODE_RX_NASA36_DC \ +) + +/** + * A mask of IRIG formats with 1000 bps data rate: + */ +#define MSK_ICODE_RX_1000BPS \ +( \ + MSK_ICODE_RX_A132_A133 | \ + MSK_ICODE_RX_A002_A003 \ +) + +/** + * A mask of IRIG formats with 10 kbps data rate: + */ +#define MSK_ICODE_RX_10000BPS \ +( \ + MSK_ICODE_RX_G142_G146 | \ + MSK_ICODE_RX_G002_G006 \ +) + +/** + * A mask of IRIG formats which support TFOM: + */ +#define MSK_ICODE_RX_HAS_TFOM \ +( \ + MSK_ICODE_RX_IEEE1344 | \ + MSK_ICODE_RX_IEEE1344_DC | \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_C37118_DC \ +) + +/** + * A mask of IRIG formats which support time zone information: + */ +#define MSK_ICODE_RX_HAS_TZI \ +( \ + MSK_ICODE_RX_IEEE1344 | \ + MSK_ICODE_RX_IEEE1344_DC | \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_C37118_DC \ +) + +/** + * The default mask of IRIG formats supported by + * IRIG receivers: + */ +#if !defined( SUPP_MSK_ICODE_RX ) + #define SUPP_MSK_ICODE_RX \ + ( \ + MSK_ICODE_RX_B122_B123 | \ + MSK_ICODE_RX_A132_A133 | \ + MSK_ICODE_RX_B002_B003 | \ + MSK_ICODE_RX_A002_A003 | \ + MSK_ICODE_RX_AFNOR | \ + MSK_ICODE_RX_AFNOR_DC \ + ) +#endif + +/** @} group_icode */ + + + +/** + * @brief Configuration settings of an IRIG input or output + * + * @see group_icode + */ +typedef struct +{ + uint16_t icode; ///< IRIG signal code, see ::ICODE_RX_CODES + uint16_t flags; ///< see ::IFLAGS_BITS +} IRIG_SETTINGS; + +#define _mbg_swab_irig_settings( _p ) \ +{ \ + _mbg_swab16( &(_p)->icode ); \ + _mbg_swab16( &(_p)->flags ); \ +} + + + +/** + * @brief Bits used with IRIG_SETTINGS::flags + * + * @note The presence or absence of the ::IFLAGS_BIT_DISABLE_TFOM flag for the IRIG RX + * settings of some PCI cards may not be evaluated correctly by some firmware + * versions for those cards, even if an IRIG code has been configured which supports + * this flag. See the comments near the declaration of the _pcps_incoming_tfom_ignored() + * macro in pcpsdev.h for details. + */ +enum IFLAGS_BITS +{ + IFLAGS_BIT_DISABLE_TFOM, ///< for RX ignore, for TX don't generate TFOM flag + IFLAGS_BIT_TX_GEN_LOCAL_TIME, ///< TX output local time, not %UTC + N_IFLAGS_BITS ///< number of known bits +}; + +#define IFLAGS_DISABLE_TFOM ( 1UL << IFLAGS_BIT_DISABLE_TFOM ) +#define IFLAGS_TX_GEN_LOCAL_TIME ( 1UL << IFLAGS_BIT_TX_GEN_LOCAL_TIME ) + +#define IFLAGS_MASK ( ( 1UL << N_IFLAGS_BITS ) - 1 ) ///< mask of all known flags + + + +/** + * @brief Current IRIG settings and supported codes + * + * Used to query the current IRIG settings + * plus a mask of supported codes. + */ +typedef struct +{ + IRIG_SETTINGS settings; ///< current settings + uint32_t supp_codes; ///< bit mask of supported codes +} IRIG_INFO; + +#define _mbg_swab_irig_info( _p ) \ +{ \ + _mbg_swab_irig_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_codes ); \ +} + + +/** + * @defgroup group_irig_comp IRIG input delay compensation + * + * These definitions are used with IRIG RX delay compensation + * which is supported by some IRIG receivers. Delay compensation + * depends on the basic frame type, so there are different records + * required for the different frame type groups. + * @{ */ + +/** + * The number of coefficients of a compensation record + * for a single frame type group, and the structure + * which contains those coefficients. + */ +#define N_IRIG_RX_COMP_VAL 4 + +/** + * @brief A structure used to store compensation values + */ +typedef struct +{ + /** + * @brief Delay compensation values [100 ns units] + * + * @note Only the first value is actually used to compensate + * a delay, so the remaining values should be 0. + */ + int16_t c[N_IRIG_RX_COMP_VAL]; + +} IRIG_RX_COMP; + +#define _mbg_swab_irig_rx_comp( _p ) \ +{ \ + int i; \ + for ( i = 0; i < N_IRIG_RX_COMP_VAL; i++ ) \ + _mbg_swab16( &(_p)->c[i] ); \ +} + + +/** The absolute value of the maximum compensation value accepted by a device */ +#define IRIG_RX_COMP_MAX 999 // [100 ns units], i.e. valid range is +/-99.9 us + + + +/** + * @brief Structure used to retrieve the number of records for a given type + */ +typedef struct +{ + uint16_t type; ///< record type @see CAL_REC_TYPES + uint16_t idx; ///< index if several records of same type are supported, see ::IRIG_RX_COMP_GROUPS +} CAL_REC_HDR; + +#define _mbg_swab_cal_rec_hdr( _p ) \ +{ \ + _mbg_swab16( &(_p)->type ); \ + _mbg_swab16( &(_p)->idx ); \ +} + + +/** + * @brief Types to be used with CAL_REC_HDR::type + */ +enum CAL_REC_TYPES +{ + CAL_REC_TYPE_UNDEF, ///< undefined type + CAL_REC_TYPE_IRIG_RX_COMP, ///< IRIG receiver delay compensation + N_CAL_REC_TYPE ///< number of known types +}; + + +/** + * @brief Types to be used with CAL_REC_HDR::idx + * + * IRIG frame type groups to be distinguished for delay compensation. + */ +enum IRIG_RX_COMP_GROUPS +{ + IRIG_RX_COMP_B1, ///< codes B1xx, AFNOR, IEEE1344 + IRIG_RX_COMP_A1, ///< code A1xx + IRIG_RX_COMP_B0, ///< codes B0xx, AFNOR DC, IEEE1344 DC + IRIG_RX_COMP_A0, ///< code A0xx + IRIG_RX_COMP_G1, ///< code G14x + IRIG_RX_COMP_G0, ///< code G00x + N_IRIG_RX_COMP ///< number of compensation values +}; + + +/** + * @brief Initializers for format name strings + */ +#define DEFAULT_IRIG_RX_COMP_NAMES \ +{ \ + "B1xx/AFNOR/IEEE1344", \ + "A1xx", \ + "B0xx/AFNOR DC/IEEE1344 DC", \ + "A0xx", \ + "G14X", \ + "G00X", \ +} + + + +/** + * @brief Structure used to transfer calibration records + */ +typedef struct +{ + CAL_REC_HDR hdr; + IRIG_RX_COMP comp_data; ///< IRIG receiver delay compensation + +} CAL_REC_IRIG_RX_COMP; + +#define _mbg_swab_cal_rec_irig_rx_comp( _p ) \ +{ \ + _mbg_swab_cal_rec_hdr( &(_p)->hdr ); \ + _mbg_swab_irig_rx_comp( &(_p)->comp_data ); \ +} + +/** @} group_irig_comp */ + + + +/** + * @brief A data type used to read the board's debug status + * + * @note This also include IRIG decoder status. + */ +typedef uint32_t MBG_DEBUG_STATUS; ///< @see MBG_DEBUG_STATUS_BITS + +#define _mbg_swab_debug_status( _p ) \ + _mbg_swab32( _p ) + + + +/** + * @brief Enumeration of bits used with ::MBG_DEBUG_STATUS + */ +enum MBG_DEBUG_STATUS_BITS +{ + MBG_IRIG_BIT_WARMED_UP, /**< Osc has warmed up */ + MBG_IRIG_BIT_PPS_ACTIVE, /**< PPS output is active */ + MBG_IRIG_BIT_INV_CONFIG, /**< Invalid config, e.g. data csum error */ + MBG_IRIG_BIT_MSG_DECODED, /**< IRIG msg could be decoded */ + MBG_IRIG_BIT_MSG_INCONSISTENT, /**< IRIG msg contains inconsistent data */ + MBG_IRIG_BIT_LOOP_LOCKED, /**< Decoder control loop is locked */ + MBG_IRIG_BIT_JITTER_TOO_LARGE, /**< Phase jitter too large */ + MBG_IRIG_BIT_INV_REF_OFFS, /**< %UTC ref offset not configured */ + + MBG_SYS_BIT_INV_TIME, /**< Internal time not valid/set */ + MBG_SYS_BIT_TIME_SET_VIA_API, /**< On board time set externally */ + MBG_SYS_BIT_INV_RTC, /**< On board RTC invalid */ + MBG_SYS_BIT_CPU_PLL_FAILED, /**< The CPU's PLL watchdog */ + + N_MBG_DEBUG_BIT +}; + +/** + * @brief Initializers for debug 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 ) + + + +/** + * @brief A data type used to configure the ref offset + * + * The ref offset if the offset of the incoming reference time from %UTC. + * For some types of signal (e.g. most IRIG frame formats) this can't be + * determined automatically. + * + * @note There's a special flag ::MBG_REF_OFFS_NOT_CFGD indicating that + * this parameter is unconfigured + */ +typedef int16_t MBG_REF_OFFS; ///< -::MBG_REF_OFFS_MAX..::MBG_REF_OFFS_MAX, or ::MBG_REF_OFFS_NOT_CFGD + +#define _mbg_swab_mbg_ref_offs( _p ) _mbg_swab16( (_p) ) + + +/** + * @brief The maximum allowed positive / negative ref offset + */ +#define MBG_REF_OFFS_MAX ( ( 12L * 60 ) + 30 ) // [minutes] + +/** + * @brief A flag indicating that the ref offset has not yet been configured + * + * If this flag is set in ::MBG_REF_OFFS this means the ref offset + * (time offset from %UTC) has not yet been configured. This is usually + * the case for IRIG receiver devices right after they have been shipped. + */ +#define MBG_REF_OFFS_NOT_CFGD 0x8000 + + +/** + * @brief A structure used to configure optional settings + * + * Optional settings are a generic way to configure some extended settings. + */ +typedef struct +{ + uint32_t flags; ///< @see MBG_OPT_BITS +} MBG_OPT_SETTINGS; + +#define _mbg_swab_mbg_opt_settings( _p ) \ +{ \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/** + * @brief A structure used to configure optional settings + * + * This structure includes the current settings, and a bit mask + * indicating which flags are supported. + */ +typedef struct +{ + MBG_OPT_SETTINGS settings; + uint32_t supp_flags; ///< bit mask of supported flags, see ::MBG_OPT_BITS +} 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_BITS +{ + MBG_OPT_BIT_STR_UTC, /**< serial string contains %UTC time */ + MBG_OPT_BIT_EMU_SYNC, /**< emulate/pretend to be synchronized, alternatively + ::GPS_FEAT_IGNORE_LOCK may be supported */ + N_MBG_OPT_BIT +}; + +/* + * Bit masks corresponding to the enumeration above: + */ +#define MBG_OPT_FLAG_STR_UTC ( 1UL << MBG_OPT_BIT_STR_UTC ) +#define MBG_OPT_FLAG_EMU_SYNC ( 1UL << MBG_OPT_BIT_EMU_SYNC ) + + + +/** + * @brief Bit coded return type for ::PCPS_GET_IRIG_CTRL_BITS + * + * This type returns the control bits an IRIG receiver has decoded + * from an incoming time code signal. + */ +typedef uint32_t MBG_IRIG_CTRL_BITS; + +#define _mbg_swab_irig_ctrl_bits( _p ) _mbg_swab32( _p ) + + +// The following macro extracts the 4 bit TFOM code from the +// IRIG control bits read from a card. This only works if the received +// IRIG code is a code which supports TFOM, this is currently +// only IEEE1344. +#define _pcps_tfom_from_irig_ctrl_bits( _p ) \ + ( ( ( *(_p) ) >> 24 ) & 0x0F ) + + + +#define RAW_IRIG_SIZE 16 + +/** + * @brief A buffer used to read raw IRIG data bits from an IRIG receiver + * + * Used to get the raw data bits from the IRIG decoder. A maximum number + * of ::RAW_IRIG_SIZE bytes can be filled up, depending on the IRIG code. + * If less bytes are used then the rest of the bytes are filled with zeros. + * + * @note The first IRIG bit received from the transmitter is saved + * in the MSB (bit 7) of data_bytes[0], etc. + */ +typedef struct +{ + uint8_t data_bytes[RAW_IRIG_SIZE]; +} MBG_RAW_IRIG_DATA; + +// The following macro extracts the 4 bit TFOM code from the raw +// data bits read from a card. This only works if the received +// IRIG code is a code which supports TFOM, this is currently +// only IEEE1344. +#define _pcps_tfom_from_raw_irig_data( _p ) \ + ( ( ( (_p)->data_bytes[9] >> 2 ) & 0x08 ) \ + | ( ( (_p)->data_bytes[9] >> 4 ) & 0x04 ) \ + | ( ( (_p)->data_bytes[9] >> 6 ) & 0x02 ) \ + | ( ( (_p)->data_bytes[8] & 0x01 ) ) ) + + + +/** + @defgroup group_time_scale Time Scale Configuration + + 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. + @{ +*/ + +/** + * @brief Known time scales + * + * @note See also the extended status bits ::TM_SCALE_GPS + * and ::TM_SCALE_TAI indicating the active time scale setting + */ +enum MBG_TIME_SCALES +{ + MBG_TIME_SCALE_DEFAULT, ///< %UTC or local time according to ::UTC parameters and ::TZDL configuration + MBG_TIME_SCALE_GPS, ///< GPS time as sent by the satellites, monotonical + MBG_TIME_SCALE_TAI, ///< TAI, i.e. GPS time plus constant offset (::GPS_TAI_OFFSET) + N_MBG_TIME_SCALE +}; + +#define MBG_TIME_SCALE_MSK_DEFAULT ( 1UL << MBG_TIME_SCALE_DEFAULT ) +#define MBG_TIME_SCALE_MSK_GPS ( 1UL << MBG_TIME_SCALE_GPS ) +#define MBG_TIME_SCALE_MSK_TAI ( 1UL << MBG_TIME_SCALE_TAI ) + + +#define MBG_TIME_SCALE_STRS \ +{ \ + "UTC/local", \ + "GPS", \ + "TAI" \ +} + + + +/** + * @brief The constant time offset between the GPS and TAI time scales, in seconds + */ +#define GPS_TAI_OFFSET 19 ///< [s], TAI = GPS + GPS_TAI_OFFSET + + +/** + * @brief Time scale configuration settings + */ +typedef struct +{ + uint8_t scale; ///< current time scale code from enum MBG_TIME_SCALES + uint8_t flags; ///< reserved, currently always 0 +} MBG_TIME_SCALE_SETTINGS; + +#define _mbg_swab_mbg_time_scale_settings( _p ) \ + _nop_macro_fnc() + + +/** + * @brief Time scale configuration settings plus capabilities + */ +typedef struct +{ + MBG_TIME_SCALE_SETTINGS settings; ///< current settings + MBG_TIME_SCALE_SETTINGS max_settings; ///< numb. of scales, all supported flags + uint32_t supp_scales; ///< bit masks of supported scales +} MBG_TIME_SCALE_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 ); \ +} + +/** @} group_time_scale */ + + +/* + * The structures below are required to setup the programmable + * pulse outputs which are provided by some GPS receivers. + * The number of programmable pulse outputs supported by a GPS + * receiver is reported in the RECEIVER_INFO::n_str_type field. + */ + +/** + * @brief A calendar date including full year number + */ +typedef struct +{ + uint8_t mday; ///< 1..28,29,30,31 + uint8_t month; ///< 1..12 + uint16_t year; ///< including century +} MBG_DATE; + +#define _mbg_swab_mbg_date( _p ) \ +{ \ + _mbg_swab16( &(_p)->year ); \ +} + + +/** + * @brief The time of day including hundredths of seconds + */ +typedef struct +{ + uint8_t hour; ///< 0..23 + uint8_t min; ///< 0..59 + uint8_t sec; ///< 0..59,60 + uint8_t sec100; ///< reserved, currently always 0 +} MBG_TIME; + +#define _mbg_swab_mbg_time( _p ) \ + _nop_macro_fnc() // nothing to swap + + +/** + * @brief Date and time specification for switching operations + */ +typedef struct +{ + MBG_DATE d; ///< date to switch + MBG_TIME t; ///< time to switch + uint8_t wday; ///< reserved, currently always 0 + uint8_t flags; ///< reserved, currently 0 +} MBG_DATE_TIME; + +#define _mbg_swab_mbg_date_time( _p ) \ +{ \ + _mbg_swab_mbg_date( &(_p)->d ); \ + _mbg_swab_mbg_time( &(_p)->t ); \ +} + + +/** + * @brief A structure to define on/off cycle times + */ +typedef struct +{ + MBG_DATE_TIME on; ///< date and time to switch on + MBG_DATE_TIME off; ///< date and time to switch off +} POUT_TIME; + +#define _mbg_swab_pout_time( _p ) \ +{ \ + _mbg_swab_mbg_date_time( &(_p)->on ); \ + _mbg_swab_mbg_date_time( &(_p)->off ); \ +} + + +/** + * @brief The number of ::POUT_TIME settings for each programmable pulse output + * + * @note This can't be changed without breaking compatibility of the API + */ +#define N_POUT_TIMES 3 + +/** + * @brief Configuration settings for a single programmable pulse output + */ +typedef struct +{ + uint16_t mode; ///< mode of operation, see ::POUT_MODES + uint16_t pulse_len; ///< 10 msec units, or COM port number + uint16_t timeout; ///< [min], for DCF77 emulation mode only + uint16_t flags; ///< @see POUT_SETTINGS_FLAG_BITS + POUT_TIME tm[N_POUT_TIMES]; ///< switching times, or other data, see ::POUT_DATA +} POUT_SETTINGS; + +/** + * @brief A Generic data field for programmable output settings + * + * If the mode is set to ::POUT_TIME_SLOTS then POUT_SETTINGS::tm must be + * interpreted as ::POUT_DATA, i.e. just an array of bytes. We can not change + * the type of the tm field to a union for compatibility reasons ... :( + */ +typedef union +{ + uint8_t b[N_POUT_TIMES * sizeof( POUT_TIME )]; +} POUT_DATA; + +// When reading data from a device we first need to correct the endianess +// of the mode first, and correct the endianess of the tm field only +// if the tm field is not interpreted as POUT_DATA. +#define _mbg_swab_pout_settings_on_get( _p ) \ +{ \ + _mbg_swab16( &(_p)->mode ); \ + _mbg_swab16( &(_p)->pulse_len ); \ + _mbg_swab16( &(_p)->timeout ); \ + _mbg_swab16( &(_p)->flags ); \ + \ + if ( (_p)->mode != POUT_TIME_SLOTS ) \ + { \ + int i; \ + \ + for ( i = 0; i < N_POUT_TIMES; i++ ) \ + _mbg_swab_pout_time( &(_p)->tm[i] ); \ + } \ +} + +// When writing data to a device we first need to check the mode, +// and correct the endianess of the tm field only if the tm field +// is not interpreted as POUT_DATA. Finally we can also correct +// the endianess of the mode field. +#define _mbg_swab_pout_settings_on_set( _p ) \ +{ \ + if ( (_p)->mode != POUT_TIME_SLOTS ) \ + { \ + int i; \ + \ + for ( i = 0; i < N_POUT_TIMES; i++ ) \ + _mbg_swab_pout_time( &(_p)->tm[i] ); \ + } \ + \ + _mbg_swab16( &(_p)->mode ); \ + _mbg_swab16( &(_p)->pulse_len ); \ + _mbg_swab16( &(_p)->timeout ); \ + _mbg_swab16( &(_p)->flags ); \ +} + + + +// In POUT_TIME_SLOTS mode the number of time slots per minute is stored +// in the pulse_len field. Valid numbers all numbers n in the range 1..60 +// for which the remainder of 60 / n is 0. +#define MIN_TIME_SLOTS_PER_MINUTE 1 +#define MAX_TIME_SLOTS_PER_MINUTE 60 +#define TIME_SLOT_REGISTER_IN_SEC 60 + +#define TIMEOUT_DIVIDED_BY 10 +#define TIME_SLOT_SWITCH_OFF_BUFFER_MIN 50 / TIMEOUT_DIVIDED_BY +#define TIME_SLOT_SWITCH_OFF_BUFFER_MAX 500 / TIMEOUT_DIVIDED_BY +#define TIME_SLOT_SWITCH_OFF_BUFFER_STD 500 / TIMEOUT_DIVIDED_BY +#define TIME_SLOT_SWITCH_OFF_BUFFER_STEP_SIZE 50 / TIMEOUT_DIVIDED_BY + +#define _valid_time_slots_per_minute( _n ) \ + ( ( (_n) >= MIN_TIME_SLOTS_PER_MINUTE ) && \ + ( (_n) <= MAX_TIME_SLOTS_PER_MINUTE ) && \ + ( ( 60 % (_n) ) == 0 ) \ + ) + + +#define MAX_POUT_PULSE_LEN 1000 ///< 10 secs, in 10 msec units +#define MAX_POUT_DCF_TIMOUT ( 48 * 60 ) ///< 48 hours, in minutes + + +/** + * @brief Operation modes for a programmable pulse output + * + * These codes are used with POUT_SETTINGS::mode. + * + * @note Not every programmable pulse output supports all modes. + */ +enum POUT_MODES +{ + POUT_IDLE, ///< always off, or on if ::POUT_INVERTED flag is set + POUT_TIMER, ///< switch on/off at configured times + POUT_SINGLE_SHOT, ///< pulse at time POUT_SETTINGS::tm[0].on + POUT_CYCLIC_PULSE, ///< pulse every POUT_SETTINGS::tm[0].on.t interval + POUT_PER_SEC, ///< pulse if second changes + POUT_PER_MIN, ///< pulse if minute changes + POUT_PER_HOUR, ///< pulse if hour changes + POUT_DCF77, ///< emulate DCF77 signal + POUT_POS_OK, ///< on if pos. OK (nav_solved) + POUT_TIME_SYNC, ///< on if time sync (time_syn) + POUT_ALL_SYNC, ///< on if pos. OK and time sync + POUT_TIMECODE, ///< IRIG/AFNOR DCLS output + POUT_TIMESTR, ///< COM port number in pulse_len field + POUT_10MHZ, ///< 10 MHz fixed frequency + POUT_DCF77_M59, ///< DCF77-like signal with 500 ms pulse in 59th second + POUT_SYNTH, ///< programmable synthesizer frequency + POUT_TIME_SLOTS, ///< programmable time slots during each minute + N_POUT_MODES ///< the number of known modes +}; + + +/* + * Default initializers for English pulse mode names. Initializers + * for multi-language strings can be found in pcpslstr.h. + */ +#define ENG_POUT_NAME_IDLE "Idle" +#define ENG_POUT_NAME_TIMER "Timer" +#define ENG_POUT_NAME_SINGLE_SHOT "Single Shot" +#define ENG_POUT_NAME_CYCLIC_PULSE "Cyclic Pulse" +#define ENG_POUT_NAME_PER_SEC "Pulse Per Second" +#define ENG_POUT_NAME_PER_MIN "Pulse Per Min" +#define ENG_POUT_NAME_PER_HOUR "Pulse Per Hour" +#define ENG_POUT_NAME_DCF77 "DCF77 Marks" +#define ENG_POUT_NAME_POS_OK "Position OK" +#define ENG_POUT_NAME_TIME_SYNC "Time Sync" +#define ENG_POUT_NAME_ALL_SYNC "All Sync" +#define ENG_POUT_NAME_TIMECODE "DCLS Time Code" +#define ENG_POUT_NAME_TIMESTR "COM Time String" +#define ENG_POUT_NAME_10MHZ "10 MHz Frequency" +#define ENG_POUT_NAME_DCF77_M59 "DCF77-like M59" +#define ENG_POUT_NAME_SYNTH "Synthesizer Frequency" +#define ENG_POUT_NAME_TIME_SLOTS "Time Slots per Minute" + +#define DEFAULT_ENG_POUT_NAMES \ +{ \ + ENG_POUT_NAME_IDLE, \ + ENG_POUT_NAME_TIMER, \ + ENG_POUT_NAME_SINGLE_SHOT, \ + ENG_POUT_NAME_CYCLIC_PULSE, \ + ENG_POUT_NAME_PER_SEC, \ + ENG_POUT_NAME_PER_MIN, \ + ENG_POUT_NAME_PER_HOUR, \ + ENG_POUT_NAME_DCF77, \ + ENG_POUT_NAME_POS_OK, \ + ENG_POUT_NAME_TIME_SYNC, \ + ENG_POUT_NAME_ALL_SYNC, \ + ENG_POUT_NAME_TIMECODE, \ + ENG_POUT_NAME_TIMESTR, \ + ENG_POUT_NAME_10MHZ, \ + ENG_POUT_NAME_DCF77_M59, \ + ENG_POUT_NAME_SYNTH, \ + ENG_POUT_NAME_TIME_SLOTS \ +} + + +#define ENG_POUT_HINT_IDLE "Constant output level" +#define ENG_POUT_HINT_TIMER "Switch based on configured on/off times" +#define ENG_POUT_HINT_SINGLE_SHOT "Generate a single pulse of determined length" +#define ENG_POUT_HINT_CYCLIC_PULSE "Generate cyclic pulses of determined length" +#define ENG_POUT_HINT_PER_SEC "Generate pulse at beginning of new second" +#define ENG_POUT_HINT_PER_MIN "Generate pulse at beginning of new minute" +#define ENG_POUT_HINT_PER_HOUR "Generate pulse at beginning of new hour" +#define ENG_POUT_HINT_DCF77 "DCF77 compatible time marks" +#define ENG_POUT_HINT_POS_OK "Switch if receiver position has been verified" +#define ENG_POUT_HINT_TIME_SYNC "Switch if time is synchronized" +#define ENG_POUT_HINT_ALL_SYNC "Switch if full sync" +#define ENG_POUT_HINT_TIMECODE "Duplicate IRIG time code signal" +#define ENG_POUT_HINT_TIMESTR "Duplicate serial time string of specified port" +#define ENG_POUT_HINT_10MHZ "10 MHz fixed output frequency" +#define ENG_POUT_HINT_DCF77_M59 "DCF77 time marks with 500 ms pulse in 59th second" +#define ENG_POUT_HINT_SYNTH "Frequency generated by programmable synthesizer" +#define ENG_POUT_HINT_TIME_SLOTS "Output enabled during specified time slots per minute" + +#define DEFAULT_ENG_POUT_HINTS \ +{ \ + ENG_POUT_HINT_IDLE, \ + ENG_POUT_HINT_TIMER, \ + ENG_POUT_HINT_SINGLE_SHOT, \ + ENG_POUT_HINT_CYCLIC_PULSE, \ + ENG_POUT_HINT_PER_SEC, \ + ENG_POUT_HINT_PER_MIN, \ + ENG_POUT_HINT_PER_HOUR, \ + ENG_POUT_HINT_DCF77, \ + ENG_POUT_HINT_POS_OK, \ + ENG_POUT_HINT_TIME_SYNC, \ + ENG_POUT_HINT_ALL_SYNC, \ + ENG_POUT_HINT_TIMECODE, \ + ENG_POUT_HINT_TIMESTR, \ + ENG_POUT_HINT_10MHZ, \ + ENG_POUT_HINT_DCF77_M59, \ + ENG_POUT_HINT_SYNTH, \ + ENG_POUT_HINT_TIME_SLOTS \ +} + + +/* + * The definitions below are used to set up bit masks + * which restrict the modes which can be used with + * a given programmable output: + */ +#define MSK_POUT_IDLE ( 1UL << POUT_IDLE ) +#define MSK_POUT_TIMER ( 1UL << POUT_TIMER ) +#define MSK_POUT_SINGLE_SHOT ( 1UL << POUT_SINGLE_SHOT ) +#define MSK_POUT_CYCLIC_PULSE ( 1UL << POUT_CYCLIC_PULSE ) +#define MSK_POUT_PER_SEC ( 1UL << POUT_PER_SEC ) +#define MSK_POUT_PER_MIN ( 1UL << POUT_PER_MIN ) +#define MSK_POUT_PER_HOUR ( 1UL << POUT_PER_HOUR ) +#define MSK_POUT_DCF77 ( 1UL << POUT_DCF77 ) +#define MSK_POUT_POS_OK ( 1UL << POUT_POS_OK ) +#define MSK_POUT_TIME_SYNC ( 1UL << POUT_TIME_SYNC ) +#define MSK_POUT_ALL_SYNC ( 1UL << POUT_ALL_SYNC ) +#define MSK_POUT_TIMECODE ( 1UL << POUT_TIMECODE ) +#define MSK_POUT_TIMESTR ( 1UL << POUT_TIMESTR ) +#define MSK_POUT_10MHZ ( 1UL << POUT_10MHZ ) +#define MSK_POUT_DCF77_M59 ( 1UL << POUT_DCF77_M59 ) +#define MSK_POUT_SYNTH ( 1UL << POUT_SYNTH ) +#define MSK_POUT_TIME_SLOTS ( 1UL << POUT_TIME_SLOTS ) + + +/** + * @brief Bits used with POUT_SETTINGS::flags + */ +enum POUT_SETTINGS_FLAG_BITS +{ + POUT_BIT_INVERTED, ///< output level has to be inverted + POUT_BIT_IF_SYNC_ONLY, ///< disable output in holdover mode + POUT_BIT_TIMEBASE_UTC, ///< use %UTC, only applicable for DCF77 output + N_POUT_SETTINGS_FLAG_BITS ///< Number of known flag bits +}; + +#define POUT_INVERTED ( 1UL << POUT_BIT_INVERTED ) +#define POUT_IF_SYNC_ONLY ( 1UL << POUT_BIT_IF_SYNC_ONLY ) +#define POUT_TIMEBASE_UTC ( 1UL << POUT_BIT_TIMEBASE_UTC ) + + +/** + * @brief Configuration settings for a specific programmable pulse output + * + * This structure can be used to send configuration settings for a specific + * programmable output to a device. + * The number of supported outputs is RECEIVER_INFO::n_prg_out. + * + * @note The ::POUT_INFO_IDX structure should be read from + * a device to retrieve the current settings and capabilities. + */ +typedef struct +{ + uint16_t idx; ///< 0..RECEIVER_INFO::n_prg_out - 1 + POUT_SETTINGS pout_settings; +} POUT_SETTINGS_IDX; + +#define _mbg_swab_pout_settings_idx_on_set( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_pout_settings_on_set( &(_p)->pout_settings ); \ +} + +#define _mbg_swab_pout_settings_idx_on_get( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_pout_settings_on_get( &(_p)->pout_settings ); \ +} + + +/** + * @brief Current settings and general capabilities of a programmable pulse output + * + * This structure should be read from the device to retrieve the + * current settings of a programmable pulse output plus its capabilities, + * e.g. the supported output modes, etc. + * + * @note The ::POUT_INFO_IDX structure should be used to read + * current settings and capabilities of a specific output. + */ +typedef struct +{ + POUT_SETTINGS pout_settings; + uint32_t supp_modes; ///< bit mask of modes supp. by this output, see ::POUT_MODES + uint8_t timestr_ports; ///< bit mask of COM ports supported for mode ::POUT_TIMESTR, see ::MAX_POUT_TIMESTR_PORTS + uint8_t reserved_0; ///< reserved for future use, currently 0 + uint16_t reserved_1; ///< reserved for future use, currently 0 + uint32_t flags; ///< @see POUT_INFO_FLAG_BITS +} POUT_INFO; + +#define _mbg_swab_pout_info_on_get( _p ) \ +{ \ + _mbg_swab_pout_settings_on_get( &(_p)->pout_settings ); \ + _mbg_swab32( &(_p)->supp_modes ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/** + * The max number of COM ports that can be handled by POUT_INFO::timestr_ports + */ +#define MAX_POUT_TIMESTR_PORTS 8 + + +/** + * @brief Bits used with POUT_INFO::flags + */ +enum POUT_INFO_FLAG_BITS +{ + POUT_BIT_SUPP_IF_SYNC_ONLY, ///< supports disabling outputs in holdover mode + POUT_BIT_SUPP_DCF77_UTC, ///< supports %UTC output in DCF77 mode + POUT_BIT_FIXED_PULSE_LEN, ///< pulse length is fixed to the value reported in settings + POUT_BIT_NOT_INVERTIBLE, ///< output level can not be inverted + N_POUT_INFO_FLAG_BITS ///< number of known flag bits +}; + +#define POUT_SUPP_IF_SYNC_ONLY ( 1UL << POUT_BIT_SUPP_IF_SYNC_ONLY ) +#define POUT_SUPP_DCF77_UTC ( 1UL << POUT_BIT_SUPP_DCF77_UTC ) +#define POUT_FIXED_PULSE_LEN ( 1UL << POUT_BIT_FIXED_PULSE_LEN ) +#define POUT_NOT_INVERTIBLE ( 1UL << POUT_BIT_NOT_INVERTIBLE ) + + +/** + * @brief Current settings and general capabilities of a specific serial port + * + * This structure should be read from the device to retrieve the + * current settings of a specific programmable output plus its capabilities, + * e.g. supported modes of operation, etc. + * The number of supported ports is RECEIVER_INFO::n_prg_out. + * + * @note The ::POUT_SETTINGS_IDX structure should be send back to + * the device to configure the specified programmable pulse output. + */ +typedef struct +{ + uint16_t idx; ///< 0..RECEIVER_INFO::n_prg_out - 1 + POUT_INFO pout_info; +} POUT_INFO_IDX; + +#define _mbg_swab_pout_info_idx_on_get( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_pout_info_on_get( &(_p)->pout_info ); \ +} + + +/* + * The codes below are used with devices which support multiple + * ref time sources at the same time. The priorities of the + * supported ref time sources is configurable. + */ + + +/** + * @brief All possibly supported ref time sources + * + * @see MULTI_REF_TYPE_MASKS + */ +enum MULTI_REF_TYPES +{ + MULTI_REF_NONE = -1, ///< nothing, undefined + MULTI_REF_GPS = 0, ///< standard GPS + MULTI_REF_10MHZ, ///< 10 MHz input frequency + MULTI_REF_PPS, ///< 1 PPS input signal + MULTI_REF_10MHZ_PPS, ///< combined 10 MHz plus PPS + MULTI_REF_IRIG, ///< IRIG input + MULTI_REF_NTP, ///< Network Time Protocol (NTP) + MULTI_REF_PTP, ///< Precision Time Protocol (PTP, IEEE1588) + MULTI_REF_PTP_E1, ///< PTP over E1 + MULTI_REF_FREQ, ///< fixed frequency + MULTI_REF_PPS_STRING, ///< PPS in addition to string + MULTI_REF_GPIO, ///< variable input signal via GPIO + MULTI_REF_INTERNAL, ///< reserved, used internally by firmware only + MULTI_REF_PZF, ///< DCF77 PZF providing much more accuracy than a standard LWR + MULTI_REF_LWR, ///< long wave receiver. e.g. DCF77 AM, WWVB, MSF, JJY + MULTI_REF_GRC, ///< Glonass / GPS receiver + MULTI_REF_HAVEQUICK, ///< HaveQuick input + N_MULTI_REF ///< the number of defined sources, can not exceed bit number of uint32_t - 1 +}; + + +/** + * @brief Names of supported ref time sources + * + * @see MULTI_REF_TYPES + */ +#define DEFAULT_MULTI_REF_NAMES \ +{ \ + "GPS", \ + "10 MHz freq in", \ + "PPS in", \ + "10 MHz + PPS in", \ + "IRIG", \ + "NTP", \ + "PTP (IEEE1588)", \ + "PTP over E1", \ + "Fixed Freq. in", \ + "PPS plus string", \ + "Var. freq. via GPIO", \ + "(reserved)", \ + "DCF77 PZF Receiver", \ + "Long Wave Receiver", \ + "GLONASS/GPS Receiver", \ + "HaveQuick Input" \ +} + + +/** + * @brief Bit masks according to enumerated ref time sources + * + * @see MULTI_REF_TYPES + */ +enum MULTI_REF_TYPE_MASKS +{ + HAS_MULTI_REF_GPS = ( 1UL << MULTI_REF_GPS ), ///< see ::MULTI_REF_GPS + HAS_MULTI_REF_10MHZ = ( 1UL << MULTI_REF_10MHZ ), ///< see ::MULTI_REF_10MHZ + HAS_MULTI_REF_PPS = ( 1UL << MULTI_REF_PPS ), ///< see ::MULTI_REF_PPS + HAS_MULTI_REF_10MHZ_PPS = ( 1UL << MULTI_REF_10MHZ_PPS ), ///< see ::MULTI_REF_10MHZ_PPS + HAS_MULTI_REF_IRIG = ( 1UL << MULTI_REF_IRIG ), ///< see ::MULTI_REF_IRIG + HAS_MULTI_REF_NTP = ( 1UL << MULTI_REF_NTP ), ///< see ::MULTI_REF_NTP + HAS_MULTI_REF_PTP = ( 1UL << MULTI_REF_PTP ), ///< see ::MULTI_REF_PTP + HAS_MULTI_REF_PTP_E1 = ( 1UL << MULTI_REF_PTP_E1 ), ///< see ::MULTI_REF_PTP_E1 + + HAS_MULTI_REF_FREQ = ( 1UL << MULTI_REF_FREQ ), ///< see ::MULTI_REF_FREQ + HAS_MULTI_REF_PPS_STRING = ( 1UL << MULTI_REF_PPS_STRING ), ///< see ::MULTI_REF_PPS_STRING + HAS_MULTI_REF_GPIO = ( 1UL << MULTI_REF_GPIO ), ///< see ::MULTI_REF_GPIO + HAS_MULTI_REF_INTERNAL = ( 1UL << MULTI_REF_INTERNAL ), ///< see ::MULTI_REF_INTERNAL + HAS_MULTI_REF_PZF = ( 1UL << MULTI_REF_PZF ), ///< see ::MULTI_REF_PZF + HAS_MULTI_REF_LWR = ( 1UL << MULTI_REF_LWR ), ///< see ::MULTI_REF_LWR + HAS_MULTI_REF_GRC = ( 1UL << MULTI_REF_GRC ), ///< see ::MULTI_REF_GRC + HAS_MULTI_REF_HAVEQUICK = ( 1UL << MULTI_REF_HAVEQUICK ) ///< see ::MULTI_REF_HAVEQUICK +}; + + +/* + * 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 + + +/** + * @brief A structure used to configure the priority of the supported ref sources + * + * The number stored in prio[0] of the array indicates the ref time + * source with highest priority. If that source fails, the device + * falls back to the source indicated by prio[1]. Each field of + * the prio[] array 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 +{ + uint8_t prio[N_MULTI_REF_PRIO]; +} MULTI_REF_SETTINGS; + + +/** + * @brief A structure used to query MULTI_REF configuration parameters + * + * This also includes a bit mask of supported ref sources. + */ +typedef struct +{ + MULTI_REF_SETTINGS settings; ///< current settings + uint32_t supp_ref; ///< bit mask of supported sources, see ::MULTI_REF_TYPE_MASKS + uint16_t n_levels; ///< supp. levels, 0..N_MULTI_REF_PRIO-1 + uint16_t flags; ///< reserved, currently always 0 +} MULTI_REF_INFO; + + +/** + * @brief A data type used to query MULTI_REF status information + */ +typedef uint16_t MULTI_REF_STATUS; ///< @see MULTI_REF_STATUS_BITS + + +/** + * @brief Bits and associated masks used with ::MULTI_REF_STATUS + */ +enum MULTI_REF_STATUS_BITS +{ + WRN_MODULE_MODE, ///< selected input mode was invalid, set to default + WRN_COLD_BOOT, ///< GPS is in cold boot mode + WRN_WARM_BOOT, ///< GPS is in warm boot mode + WRN_ANT_DISCONN, ///< antenna is disconnected + WRN_10MHZ_UNLOCK, ///< impossible to lock to external 10MHz reference + WRN_1PPS_UNLOCK, ///< impossible to lock to external 1PPS reference + WRN_GPS_UNLOCK, ///< impossible to lock to GPS + WRN_10MHZ_MISSING, ///< external 10MHz signal not available + WRN_1PPS_MISSING, ///< external 1PPS signal not available + N_MULTI_REF_STATUS_BITS ///< the number of known bits +}; + +#define MSK_WRN_COLD_BOOT ( 1UL << WRN_COLD_BOOT ) +#define MSK_WRN_WARM_BOOT ( 1UL << WRN_WARM_BOOT ) +#define MSK_WRN_ANT_DISCONN ( 1UL << WRN_ANT_DISCONN ) +#define MSK_WRN_10MHZ_UNLOCK ( 1UL << WRN_10MHZ_UNLOCK ) +#define MSK_WRN_1PPS_UNLOCK ( 1UL << WRN_1PPS_UNLOCK ) +#define MSK_WRN_GPS_UNLOCK ( 1UL << WRN_GPS_UNLOCK ) +#define MSK_WRN_10MHZ_MISSING ( 1UL << WRN_10MHZ_MISSING ) +#define MSK_WRN_1PPS_MISSING ( 1UL << WRN_1PPS_MISSING ) +#define MSK_WRN_MODULE_MODE ( 1UL << WRN_MODULE_MODE ) + + + +/** + * @defgroup group_xmr_cfg Extended multiref configuration stuff + * + * 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. + * + * 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. + * + * These structures are used to configure the individual + * time source for each priority level, and retrieve the status + * of the time source at each priority level. + * + * @{ */ + +/** + * @brief Identifier for a reference source + */ +typedef struct +{ + uint8_t type; ///< @see MULTI_REF_TYPES + uint8_t instance; ///< instance number, if multiple instances are supported, else 0 +} XMULTI_REF_ID; + + + +/** + * @brief Reference source configuration settings + */ +typedef struct +{ + XMULTI_REF_ID id; ///< 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; + + + +/** + * @brief Reference source configuration settings for a specific priority level + * + * @note 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; + + + +/** + * @brief Reference source configuration settings and capabilities + */ +typedef struct +{ + XMULTI_REF_SETTINGS settings; ///< current settings + uint32_t supp_ref; ///< bit mask of supported sources, see ::MULTI_REF_TYPES + uint8_t n_supp_ref; ///< number of supported ref time sources + uint8_t n_prio; ///< number of supported priority levels + uint16_t flags; ///< currently always 0 +} XMULTI_REF_INFO; + + + +/** + * @brief Reference source configuration settings and capabilities for a specific priority level + */ +typedef struct +{ + uint16_t idx; ///< the priority level index, highest == 0 + XMULTI_REF_INFO info; ///< ref source cfg and capabilities +} XMULTI_REF_INFO_IDX; + + + +/** + * @brief Status information on a single ref time source + */ +typedef struct +{ + XMULTI_REF_ID id; ///< time source identifier, see ::MULTI_REF_TYPES + uint16_t status; ///< status bits, see ::XMR_REF_STATUS_BITS + NANO_TIME offset; ///< time offset from main time base + uint16_t flags; ///< flags, see ::XMR_REF_FLAG_BITS + uint8_t ssm; ///< synchronization status message (if supported by src.) + uint8_t soc; ///< signal outage counter (updated on loss of signal) +} XMULTI_REF_STATUS; + + + +/** + * @brief Status information on a ref time source at a specific priority level + */ +typedef struct +{ + uint16_t idx; /**< the priority level index, highest == 0 */ + XMULTI_REF_STATUS status; /**< status information */ + +} XMULTI_REF_STATUS_IDX; + + + +/** + * @brief Bits and bit masks used with XMULTI_REF_STATUS::status + */ +enum XMR_REF_STATUS_BITS +{ + XMRS_BIT_NOT_SUPP, ///< ref type cfg'd for this level is not supported + XMRS_BIT_NO_CONN, ///< input signal is disconnected + XMRS_BIT_NO_SIGNAL, ///< no input signal + XMRS_BIT_IS_MASTER, ///< reference is master source + XMRS_BIT_IS_LOCKED, ///< locked to input signal + XMRS_BIT_IS_ACCURATE, ///< oscillator control has reached full accuracy + XMRS_BIT_NOT_SETTLED, ///< reference time signal not settled + XMRS_BIT_NOT_PHASE_LOCKED, ///< oscillator not phase locked to PPS + XMRS_BIT_NUM_SRC_EXC, ///< number of available sources exceeds what can be handled + XMRS_BIT_IS_EXTERNAL, ///< this ref source is on extension card + XMRS_BIT_LOW_JITTER, ///< this ref source has low jitter + N_XMRS_BITS ///< number of know status bits +}; + +#define XMRS_MSK_NOT_SUPP ( 1UL << XMRS_BIT_NOT_SUPP ) +#define XMRS_MSK_NO_CONN ( 1UL << XMRS_BIT_NO_CONN ) +#define XMRS_MSK_NO_SIGNAL ( 1UL << XMRS_BIT_NO_SIGNAL ) +#define XMRS_MSK_IS_MASTER ( 1UL << XMRS_BIT_IS_MASTER ) +#define XMRS_MSK_IS_LOCKED ( 1UL << XMRS_BIT_IS_LOCKED ) +#define XMRS_MSK_IS_ACCURATE ( 1UL << XMRS_BIT_IS_ACCURATE ) +#define XMRS_MSK_NOT_SETTLED ( 1UL << XMRS_BIT_NOT_SETTLED ) +#define XMRS_MSK_NOT_PHASE_LOCKED ( 1UL << XMRS_BIT_NOT_PHASE_LOCKED ) +#define XMRS_MSK_NUM_SRC_EXC ( 1UL << XMRS_BIT_NUM_SRC_EXC ) +#define XMRS_MSK_IS_EXTERNAL ( 1UL << XMRS_BIT_IS_EXTERNAL ) +#define XMRS_MSK_LOW_JITTER ( 1UL << XMRS_BIT_LOW_JITTER ) + +/* + * Initializers for XMRS status bit strings. + */ +#define MBG_XMRS_STATUS_STRS \ +{ \ + "Ref type not supported", \ + "No connection", \ + "No signal", \ + "Is master", \ + "Is locked", \ + "Is accurate", \ + "Not settled", \ + "Phase not locked", \ + "Number sources exceeds limit", \ + "Is external", \ + "Low jitter" \ +} + + +/** + * @brief Bits and masks used with XMULTI_REF_STATUS::flags + * + * @note This API is only supported if bit ::GPS_FEAT_XMRS_MULT_INSTC + * is set in RECEIVER_INFO::features. + */ +enum XMR_REF_FLAG_BITS +{ + XMRSF_BIT_MULT_INSTC_SUPP, ///< multiple instances of the same ref type supported + XMRSF_BIT_IS_EXTERNAL, ///< this ref source is on extension card + N_XMRS_FLAGS +}; + +#define XMRSF_MSK_MULT_INSTC_SUPP ( 1UL << XMRSF_BIT_MULT_INSTC_SUPP ) +#define XMRSF_MSK_IS_EXTERNAL ( 1UL << XMRSF_BIT_IS_EXTERNAL ) + + + +/* + * An initializer for a XMULTI_REF_STATUS variable + * with status invalid / not used + */ +#define XMULTI_REF_STATUS_INVALID \ +{ \ + { (uint8_t) MULTI_REF_NONE, 0 }, /* id; instance 0 ? */ \ + XMRS_MSK_NO_CONN | XMRS_MSK_NO_SIGNAL, /* status */ \ + { 0 }, /* offset */ \ + 0 /* reserved */ \ +} + + +/** + * @brief The number of supported instances of each ref source type + * + * @note This structure is only supported if bit ::GPS_FEAT_XMRS_MULT_INSTC + * is set in RECEIVER_INFO::features. + */ +typedef struct +{ + uint32_t flags; ///< reserved, currently always 0 + uint16_t n_xmr_settings; ///< number of configurable multi ref settings + uint8_t slot_id; ///< current slot ID of board (0..15) + uint8_t reserved; ///< reserved, currently always 0 + uint8_t n_inst[32]; ///< ::N_MULTI_REF entries used, but can not exceed bit number of uint32_t - 1 +} XMULTI_REF_INSTANCES; + + +/** + * @brief Holdover interval while switching XMR sources + * + * @note This parameter can be sent to a device to specify a holdover + * interval during which the sync state shall be kept when switching + * to a different time source. + */ +typedef uint32_t XMR_HOLDOVER_INTV; ///< [s] */ + + +/** @} group_xmr_cfg */ + + + +/** + * @defgroup group_gpio GPIO port configuration stuff + * + * @note This is only supported if ::GPS_HAS_GPIO is set + * in the RECEIVER_INFO::features mask. + * + * @{ */ + + +/** + * @brief General GPIO config info to be read from a device + * + * Used to query from a device how many GPIO ports are supported + * by the device, then index 0..num_io-1 configuration or status + * records can be read from or written to the device. + */ +typedef struct +{ + uint32_t num_io; /**< number of supported GPIO ports */ + uint32_t reserved; /**< currently always 0 */ + uint32_t flags; /**< currently always 0 */ + +} MBG_GPIO_CFG_LIMITS; + + + +/** + * @brief Enumeration of GPIO types + * + * Usually a specific GPIO port can only be either an input + * or an output, and supports only a single signal type. + * This is due to hardware limitations, i.e. input or output + * circuitry required for the given signal + */ +enum MBG_GPIO_TYPES +{ + MBG_GPIO_TYPE_FREQ_IN, /**< variable frequency input */ + MBG_GPIO_TYPE_FREQ_OUT, /**< variable frequency output */ + MBG_GPIO_TYPE_FIXED_FREQ_OUT, /**< fixed frequency output */ + MBG_GPIO_TYPE_BITS_IN, /**< framed data stream input */ + MBG_GPIO_TYPE_BITS_OUT, /**< framed data stream output */ + N_MBG_GPIO_TYPES /**< number of known types */ +}; + + +#define DEFAULT_GPIO_TYPES_SHORT_STRS \ +{ \ + "Freq. In", \ + "Freq. Out", \ + "Fixed Freq Out", \ + "BITS In", \ + "BITS Out" \ +} + + + +/** + * @brief Enumeration of signal shapes + * + * Used to specify the signal shape of an input or output + * frequency signal. + */ +enum MBG_GPIO_SIGNAL_SHAPES +{ + MBG_GPIO_SIGNAL_SHAPE_UNSPECIFIED, /**< unknown or unspecified signal shape */ + MBG_GPIO_SIGNAL_SHAPE_SINE, /**< sine wave */ + MBG_GPIO_SIGNAL_SHAPE_SQUARE, /**< square wave */ + N_MBG_GPIO_SIGNAL_SHAPES /**< number of known signal shapes */ +}; + +/** Bit masks of signal shapes, corresponding to enum MBG_GPIO_SIGNAL_SHAPES */ +#define MBG_GPIO_SIGNAL_SHAPE_MSK_UNSPECIFIED ( 1UL << MBG_GPIO_SIGNAL_SHAPE_UNSPECIFIED ) +#define MBG_GPIO_SIGNAL_SHAPE_MSK_SINE ( 1UL << MBG_GPIO_SIGNAL_SHAPE_SINE ) +#define MBG_GPIO_SIGNAL_SHAPE_MSK_SQUARE ( 1UL << MBG_GPIO_SIGNAL_SHAPE_SQUARE ) + + + +/** + * @brief A structure used to specify a variable frequency + * + * Used to specify a variable frequency for GPIO input or output + */ +typedef struct +{ + uint32_t hz; /**< integral number, Hz */ + uint32_t frac; /**< fractional part, binary */ + +} MBG_GPIO_FREQ; + + + +/** + * @brief Configuration of a GPIO variable frequency input + * + * @see MBG_GPIO_TYPE_FREQ_IN + */ +typedef struct +{ + MBG_GPIO_FREQ freq; /**< frequency */ + uint32_t csc_limit; /**< max. cycle slip [1/1000 cycle units] */ + uint32_t shape; /**< signal shape, see ::MBG_GPIO_SIGNAL_SHAPES */ + uint32_t reserved; /**< currently always 0 */ + uint32_t flags; /**< currently always 0 */ + +} MBG_GPIO_FREQ_IN_SETTINGS; + + +/** + * @brief Supported options for a variable frequency GPIO input + * + * @see MBG_GPIO_TYPE_FREQ_IN + */ +typedef struct +{ + //##++++++++++++++++ + uint32_t freq_min; /**< minimum output frequency [Hz] */ + uint32_t freq_max; /**< maximum output frequency [Hz] */ + uint32_t csc_limit_max; /**< max. milli_phase, unspecified if 0 */ + uint32_t supp_shapes; /**< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPES */ + uint32_t reserved; /**< currently always 0 */ + uint32_t flags; /**< currently always 0 */ + +} MBG_GPIO_FREQ_IN_SUPP; + + + +/** + * @brief Configuration of a GPIO variable frequency output + * + * @see MBG_GPIO_TYPE_FREQ_OUT + */ +typedef struct +{ + MBG_GPIO_FREQ freq; /**< frequency */ + int32_t milli_phase; /**< phase [1/1000 degree units] */ + uint32_t shape; /**< signal shape, see ::MBG_GPIO_SIGNAL_SHAPES */ + uint32_t reserved; /**< currently always 0 */ + uint32_t flags; /**< currently always 0 */ + +} MBG_GPIO_FREQ_OUT_SETTINGS; + + + +/** + * @brief Supported options for a variable frequency GPIO output + * + * @see MBG_GPIO_TYPE_FREQ_OUT + */ +typedef struct +{ + uint32_t freq_min; /**< minimum output frequency [Hz] */ + uint32_t freq_max; /**< maximum output frequency [Hz] */ + uint32_t freq_resolution; /**< frequency resolution [Hz], unspecified if 0 */ + uint32_t milli_phase_max; /**< max. abs. milli_phase */ + uint32_t supp_shapes; /**< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPES */ + uint32_t reserved; /**< currently always 0 */ + uint32_t flags; /**< currently always 0 */ + +} MBG_GPIO_FREQ_OUT_SUPP; + + + +/** + * @brief Supported fixed frequencies + */ +enum MBG_GPIO_FIXED_FREQ +{ + MBG_GPIO_FIXED_FREQ_8kHz, /**< 8kHz */ + MBG_GPIO_FIXED_FREQ_48kHz, /**< 48kHz */ + MBG_GPIO_FIXED_FREQ_1MHz, /**< 1MHz */ + MBG_GPIO_FIXED_FREQ_1544kHz, /**< 1.544MHz */ + MBG_GPIO_FIXED_FREQ_2048kHz, /**< 2.048MHz */ + MBG_GPIO_FIXED_FREQ_5MHz, /**< 5MHz */ + MBG_GPIO_FIXED_FREQ_10MHz, /**< 10MHz */ + MBG_GPIO_FIXED_FREQ_19440kHz, /**< 19.44MHz */ + N_MBG_GPIO_FIXED_FREQ /**< number of known frequencies */ +}; + +/** Bit masks of supported fixed frequencies */ +#define MSK_MBG_GPIO_FIXED_FREQ_8kHz ( 1UL << MBG_GPIO_FIXED_FREQ_8kHz ) +#define MSK_MBG_GPIO_FIXED_FREQ_48kHz ( 1UL << MBG_GPIO_FIXED_FREQ_48kHz ) +#define MSK_MBG_GPIO_FIXED_FREQ_1MHz ( 1UL << MBG_GPIO_FIXED_FREQ_1MHz ) +#define MSK_MBG_GPIO_FIXED_FREQ_1544kHz ( 1UL << MBG_GPIO_FIXED_FREQ_1544kHz ) +#define MSK_MBG_GPIO_FIXED_FREQ_2048kHz ( 1UL << MBG_GPIO_FIXED_FREQ_2048kHz ) +#define MSK_MBG_GPIO_FIXED_FREQ_5MHz ( 1UL << MBG_GPIO_FIXED_FREQ_5MHz ) +#define MSK_MBG_GPIO_FIXED_FREQ_10MHz ( 1UL << MBG_GPIO_FIXED_FREQ_10MHz ) +#define MSK_MBG_GPIO_FIXED_FREQ_19440kHz ( 1UL << MBG_GPIO_FIXED_FREQ_19440kHz ) + +/* + * Initializers for GPIO fixed frequency strings. + */ +#define MBG_GPIO_FIXED_FREQ_STRS \ +{ \ + "8kHz", \ + "48kHz", \ + "1MHz", \ + "1544kHz", \ + "2048kHz", \ + "5MHz", \ + "10MHz", \ + "19440kHz" \ +} + + +/** + * @brief Configuration of a GPIO fixed frequency output + * + * @see MBG_GPIO_TYPE_FIXED_FREQ_OUT + */ +typedef struct +{ + uint32_t freq_idx; /**< fixed frequency index, see ::MBG_GPIO_FIXED_FREQ */ + uint32_t shape; /**< signal shape, see ::MBG_GPIO_SIGNAL_SHAPES */ + uint32_t reserved; /**< currently always 0 */ + uint32_t flags; /**< currently always 0 */ + +} MBG_GPIO_FIXED_FREQ_OUT_SETTINGS; + + +/** + * @brief Supported options for a fixed frequency output + * + * @see MBG_GPIO_TYPE_FIXED_FREQ_OUT + */ +typedef struct +{ + uint32_t supp_freq; /**< bit mask of supported fixed frequencies, see ::MBG_GPIO_FIXED_FREQ */ + uint32_t supp_shapes; /**< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPES */ + uint32_t reserved; /**< currently always 0 */ + uint32_t supp_flags; /**< currently always 0 */ + +} MBG_GPIO_FIXED_FREQ_OUT_SUPP; + + + +/** + * @brief Definitions for MBG_GPIO_BITS::format + */ +enum MBG_GPIO_BITS_FORMATS +{ + MBG_GPIO_BITS_E1_FRAMED, /**< 2.048MBit */ + MBG_GPIO_BITS_T1_FRAMED, /**< 1.544MBit */ + MBG_GPIO_BITS_E1_TIMING, /**< 2.048MHz */ + MBG_GPIO_BITS_T1_TIMING, /**< 2.048MHz */ + N_MBG_GPIO_BITS_FORMATS /**< number of formats */ +}; + +#define MSK_MBG_GPIO_BITS_E1_FRAMED ( 1UL << MBG_GPIO_BITS_E1_FRAMED ) +#define MSK_MBG_GPIO_BITS_T1_FRAMED ( 1UL << MBG_GPIO_BITS_T1_FRAMED ) +#define MSK_MBG_GPIO_BITS_E1_TIMING ( 1UL << MBG_GPIO_BITS_E1_TIMING ) +#define MSK_MBG_GPIO_BITS_T1_TIMING ( 1UL << MBG_GPIO_BITS_T1_TIMING ) + + + +/** + * @brief Configuration of a GPIO as BITS input module + * + * @see MBG_GPIO_TYPE_BITS_IN + */ +typedef struct +{ + uint32_t format; /**< signal type, see ::MBG_GPIO_BITS_FORMATS */ + uint32_t reserved; + uint32_t csc_limit; /**< max. cycle slip [1/1000 cycle units] */ + + union + { + struct + { + uint8_t ssm; /**< minimum E1 SSM ( 0...15 ) for acceptance */ + uint8_t sa_bits; /**< Sa Bits group ( 4...8 ) carrying SSM */ + uint16_t reserve; + } e1; /**< used with E1 formats */ + + struct + { + uint8_t min_boc; + uint8_t reserve_0; + uint16_t reserve_1; + } t1; /**< used with T1 formats */ + + uint32_t u32; /**< dummy to force at least 32 bit alignment */ + + } quality; + + uint32_t err_msk; /**< controls which types of error can be ignored, see enum MBG_GPIO_BITS_ERR */ + uint32_t flags; /**< currently always 0 */ + +} MBG_GPIO_BITS_IN_SETTINGS; + + +/** + * @brief Definitions for MBG_GPIO_BITS_IN_SETTINGS::err_msk + */ +enum MBG_GPIO_BITS_ERR +{ + MBG_GPIO_BITS_ERR_LOS, /**< loss of signal error */ + MBG_GPIO_BITS_ERR_LOF, /**< loss of frame */ + N_MBG_GPIO_BITS_ERR /**< number of formats */ +}; + +#define MSK_MBG_GPIO_BITS_ERR_LOS ( 1UL << MBG_GPIO_BITS_ERR_LOS ) +#define MSK_MBG_GPIO_BITS_ERR_LOF ( 1UL << MBG_GPIO_BITS_ERR_LOF ) + + + +/** + * @brief Supported options of a BITS GPIO input + * + * @see MBG_GPIO_TYPE_BITS_IN + */ +typedef struct +{ + uint32_t supp_fmts; ///< bit mask of supported formats, see ::MBG_GPIO_BITS_FORMATS + uint32_t reserved; ///< reserved, currently always 0 + +} MBG_GPIO_BITS_IN_SUPP; + + + +/** + * @brief Configuration of a GPIO as BITS output module + * + * @see MBG_GPIO_TYPE_BITS_OUT + */ +typedef struct +{ + uint32_t format; /**< signal type, enum MBG_GPIO_BITS_FORMATS */ + uint32_t flags; /**< flags for encoder control etc. */ + uint8_t sa_bits; /**< number of SA Bit group for E1 SSM ( 4...8 ) */ + uint8_t ssm; /**< ssm for E1 mode 0..0x0F */ + uint8_t boc; /**< boc for T1 mode 0..0x1F */ + uint8_t reserved_0; + uint32_t reserved_1; + uint32_t reserved_2; + uint32_t reserved_3; + +} MBG_GPIO_BITS_OUT_SETTINGS; + + +/** + * @brief Definitions for MBG_GPIO_BITS_OUT_SETTINGS::flags + */ +enum MBG_GPIO_BITS_OUT_FLAG +{ + MBG_GPIO_BITS_OUT_FLAG_HDB3, /**< enable HDB3 encoding ( E1 mode only ) */ + MBG_GPIO_BITS_OUT_FLAG_B8ZS, /**< enable B8ZS encoding ( T1 mode only ) */ + N_MBG_GPIO_BITS_OUT_FLAG /**< number of flags */ +}; + +#define MSK_MBG_GPIO_BITS_OUT_FLAG_HDB3 ( 1UL << MBG_GPIO_BITS_OUT_FLAG_HDB3 ) +#define MSK_MBG_GPIO_BITS_OUT_FLAG_B8ZS ( 1UL << MBG_GPIO_BITS_OUT_FLAG_B8ZS ) + + +/** + * @brief Supported options of a BITS GPIO output + * + * @see MBG_GPIO_TYPE_BITS_OUT + */ +typedef struct +{ + uint32_t supp_fmts; /**< bit mask of supported formats, see ::MBG_GPIO_BITS_FORMATS */ + uint32_t reserved; /**< currently always 0 */ +} MBG_GPIO_BITS_OUT_SUPP; + + +/** + * @brief A generic structure used to configure a GPIO port + */ +typedef struct +{ + uint32_t type; /**< GPIO type, see ::MBG_GPIO_TYPES */ + uint32_t reserved; /**< currently always 0 */ + uint32_t flags; /**< currently always 0 */ + + union /**< settings depending on the GPIO type, see ::MBG_GPIO_TYPES */ + { + MBG_GPIO_FREQ_IN_SETTINGS freq_in; /**< if type is MBG_GPIO_TYPE_FREQ_IN */ + MBG_GPIO_FREQ_OUT_SETTINGS freq_out; /**< if type is MBG_GPIO_TYPE_FREQ_OUT */ + MBG_GPIO_FIXED_FREQ_OUT_SETTINGS ff_out; /**< if type is MBG_GPIO_TYPE_FIXED_FREQ_OUT */ + MBG_GPIO_BITS_IN_SETTINGS bits_in; /**< if type is MBG_GPIO_TYPE_BITS_IN */ + MBG_GPIO_BITS_OUT_SETTINGS bits_out; /**< if type is MBG_GPIO_TYPE_BITS_OUT */ + } u; + +} MBG_GPIO_SETTINGS; + + + +/** + * @brief A generic structure used to describe a GPIO ports limiting values + */ +typedef struct +{ + uint32_t type; /**< GPIO type, see ::MBG_GPIO_TYPES */ + uint32_t reserved; /**< currently always 0 */ + uint32_t supp_flags; /**< supported flags */ + + union /**< limits depending on the GPIO type, see ::MBG_GPIO_TYPES */ + { + MBG_GPIO_FREQ_IN_SUPP freq_in; /**< if type is MBG_GPIO_TYPE_FREQ_IN */ + MBG_GPIO_FREQ_OUT_SUPP freq_out; /**< if type is MBG_GPIO_TYPE_FREQ_OUT */ + MBG_GPIO_FIXED_FREQ_OUT_SUPP ff_out; /**< if type is MBG_GPIO_TYPE_FIXED_FREQ_OUT */ + MBG_GPIO_BITS_IN_SUPP bits_in; /**< if type is MBG_GPIO_TYPE_BITS_IN */ + MBG_GPIO_BITS_OUT_SUPP bits_out; /**< if type is MBG_GPIO_TYPE_BITS_OUT */ + } u; + +} MBG_GPIO_LIMITS; + + + +/** + * @brief A structure used to configure a specific GPIO port + */ +typedef struct +{ + uint32_t idx; /**< port number, 0..(MBG_GPIO_CFG_LIMITS::num_io - 1) */ + MBG_GPIO_SETTINGS settings; /**< configuration settings */ + +} MBG_GPIO_SETTINGS_IDX; + + + +/** + * @brief A structure used query the current GPIO port settings and capabilities + */ +typedef struct +{ + MBG_GPIO_SETTINGS settings; /**< current configuration */ + MBG_GPIO_LIMITS limits; /**< supp. and max. values */ + +} MBG_GPIO_INFO; + + + +/** + * @brief A structure used to query configuration and capabilities of a specific GPIO port + */ +typedef struct +{ + uint32_t idx; /**< port number, 0..(MBG_GPIO_CFG_LIMITS::num_io - 1) */ + MBG_GPIO_INFO info; /**< current settings and capabilities of this GPIO port */ + +} MBG_GPIO_INFO_IDX; + + +/** @} group_gpio */ + + + +/** + * @defgroup group_havequick GPIO port configuration stuff + * + * @note This is only supported if the ::GPS_HAS_HAVEQUICK bit is set + * in the RECEIVER_INFO::features mask. + * + * @{ */ + + +/** + * @brief Enumeration of HaveQuick formats + * + * @see HAVEQUICK_SETTINGS::format + * @see HAVEQUICK_FORMAT_MASKS + */ +enum HAVEQUICK_FORMATS +{ + HQ_FMT_STANAG4246_1, + HQ_FMT_STANAG4246_2, + HQ_FMT_STANAG4246_PTTI, + HQ_FMT_STANAG4372_SATURN_1, + HQ_FMT_STANAG4372_SATURN_2, + HQ_FMT_STANAG4430_EXTD, + N_HQ_FMT ///< number of known formats +}; + + +/** + * @brief Bit masks associated to enumerated HaveQuick formats + * + * @see HAVEQUICK_INFO::supp_formats + * @see HAVEQUICK_FORMATS + */ +enum HAVEQUICK_FORMAT_MASKS +{ + HQ_MSK_STANAG4246_1 = ( 1UL << HQ_FMT_STANAG4246_1 ), ///< see ::HQ_FMT_STANAG4246_1 + HQ_MSK_STANAG4246_2 = ( 1UL << HQ_FMT_STANAG4246_2 ), ///< see ::HQ_FMT_STANAG4246_2 + HQ_MSK_STANAG4246_PTTI = ( 1UL << HQ_FMT_STANAG4246_PTTI ), ///< see ::HQ_FMT_STANAG4246_PTTI + HQ_MSK_STANAG4372_SATURN_1 = ( 1UL << HQ_FMT_STANAG4372_SATURN_1 ), ///< see ::HQ_FMT_STANAG4372_SATURN_1 + HQ_MSK_STANAG4372_SATURN_2 = ( 1UL << HQ_FMT_STANAG4372_SATURN_2 ), ///< see ::HQ_FMT_STANAG4372_SATURN_2 + HQ_MSK_STANAG4430_EXTD = ( 1UL << HQ_FMT_STANAG4430_EXTD ) ///< see ::HQ_FMT_STANAG4430_EXTD +}; + + +/** + * @brief Configuration settings for a HaveQuick input or output + */ +typedef struct +{ + uint16_t format; ///< see ::HAVEQUICK_FORMATS + uint16_t flags; ///< see ::HAVEQUICK_FLAG_MASKS + int32_t offset; ///< Tx: unused, Rx: offset of incoming time in [s] + uint32_t reserved_0; ///< reserved, currently always 0 + uint32_t reserved_1; ///< reserved, currently always 0 +} HAVEQUICK_SETTINGS; + + +/** + * @brief Current settings and capabilities of a HaveQuick input or output + */ +typedef struct +{ + HAVEQUICK_SETTINGS settings; ///< current settings + uint32_t supp_formats; ///< see ::HAVEQUICK_FORMAT_MASKS + uint16_t supp_flags; ///< mask of flags supported in settings, see ::HAVEQUICK_FLAG_MASKS + uint16_t reserved; ///< reserved, currently always 0 +} HAVEQUICK_INFO; + + +/** + * @brief Known HaveQuick control flags + * + * @see HAVEQUICK_FLAG_MASKS + */ +enum HAVEQUICK_FLAG_BITS +{ + HQ_FLAG_TX_GEN_LOCAL_TIME, + HQ_FLAG_SIGNAL_INVERTED, + HQ_FLAG_USE_EXT_PPS, + N_HQ_FLAG_BITS +}; + + +/** + * @brief Bit masks associated to HaveQuick control flags + * + * @see HQ_SETTINGS::flags + * @see HQ_INFO::flags + * @see HAVEQUICK_FLAG_BITS + */ +enum HAVEQUICK_FLAG_MASKS +{ + HQ_MSK_TX_GEN_LOCAL_TIME = ( 1UL << HQ_FLAG_TX_GEN_LOCAL_TIME ), ///< see ::HQ_FLAG_TX_GEN_LOCAL_TIME + HQ_MSK_SIGNAL_INVERTED = ( 1UL << HQ_FLAG_SIGNAL_INVERTED ), ///< see ::HQ_FLAG_SIGNAL_INVERTED + HQ_MSK_USE_EXT_PPS = ( 1UL << HQ_FLAG_USE_EXT_PPS ) ///< see ::HQ_FLAG_USE_EXT_PPS +}; + + +/** @} group_havequick */ + + + +/** + * @defgroup group_evt_log Event logging support + * + * @note This is only available if ::GPS_HAS_EVT_LOG is set in RECEIVER_INFO::features. + * + * @{ */ + +/** @brief Number of event log entries that can be stored and yet have been saved */ +typedef struct +{ + uint32_t used; /**< current number of saved log entries */ + uint32_t max; /**< max number of log entries which can be saved */ +} MBG_NUM_EVT_LOG_ENTRIES; + +#define _mbg_swab_mbg_num_evt_log_entries( _p ) \ +{ \ + _mbg_swab32( &(_p)->used ); \ + _mbg_swab32( &(_p)->max ); \ +} + + +typedef uint16_t MBG_EVT_CODE; +#define _mbg_swab_evt_code( _p ) _mbg_swab16( _p ); + +typedef uint16_t MBG_EVT_INFO; +#define _mbg_swab_evt_info( _p ) _mbg_swab16( _p ); + +/** + * @brief An event log entry + */ + typedef struct + { + uint32_t time; /**< like time_t, seconds since 1970 */ + MBG_EVT_CODE code; /**< event ID or'ed with severity level */ + MBG_EVT_INFO info; /**< optional event info, depending on event ID */ + } MBG_EVT_LOG_ENTRY; + +#define _mbg_swab_mbg_evt_log_entry( _p ) \ +{ \ + _mbg_swab32( &(_p)->time ); \ + _mbg_swab_evt_code( &(_p)->code ); \ + _mbg_swab_evt_info( &(_p)->info ); \ +} + + +// MBG_EVT_LOG_ENTRY::code is a combination of some bits used for the ID, +// plus some bits used for the severity/level. The sum of bits must not +// exceed (8 * sizeof MBG_EVT_LOG_ENTRY::code): + +#define MBG_EVT_ID_BITS 13 +#define MBG_EVT_LVL_BITS 3 + +#define MBG_EVT_ID_MASK ( (MBG_EVT_CODE) ( 1UL << MBG_EVT_ID_BITS ) - 1 ) +#define MBG_EVT_LVL_MASK ( (MBG_EVT_CODE) ( 1UL << MBG_EVT_LVL_BITS ) - 1 ) + + +// Combine an ID and Level to a code which can be stored +// in the code field: +#define _mbg_mk_evt_code( _id, _lvl ) \ + ( (MBG_EVT_CODE) ( (MBG_EVT_CODE)(_id) | ( (MBG_EVT_CODE)(_lvl) << MBG_EVT_ID_BITS ) ) ) + +// Extract the event ID from the code field: +#define _mbg_get_evt_id( _code ) \ + ( (_code) & MBG_EVT_ID_MASK ) + +// Extract the severity level from the code field: +#define _mbg_get_evt_lvl( _code ) \ + ( ( (_code) >> MBG_EVT_ID_BITS ) & MBG_EVT_LVL_MASK ) + + +/** + * @brief Enumeration of event IDs + */ +enum MBG_EVT_IDS +{ + MBG_EVT_ID_NONE, /**< no event (empty entry) */ + MBG_EVT_ID_POW_UP_RES, /**< power up reset */ + MBG_EVT_ID_WDOG_RES, /**< watchdog reset */ + MBG_EVT_ID_COLD_BOOT, /**< entering cold boot mode */ + MBG_EVT_ID_WARM_BOOT, /**< entering warm boot mode */ + MBG_EVT_ID_NORMAL_OP, /**< entering normal operation */ + MBG_EVT_ID_ANT_DISCONN, /**< antenna disconnect detected */ + MBG_EVT_ID_ANT_SHORT, /**< antenna short circuit detected */ + MBG_EVT_ID_ANT_OK, /**< antenna OK after failure */ + MBG_EVT_ID_LOW_SATS, /**< no satellites can be received though antenna not failing */ + N_MBG_EVT_ID +}; + + +#define ENG_EVT_ID_NAME_NONE "No event" +#define ENG_EVT_ID_NAME_POW_UP_RES "Power Up Reset" +#define ENG_EVT_ID_NAME_WDOG_RES "Watchdog Reset" +#define ENG_EVT_ID_NAME_COLD_BOOT "Cold Boot" +#define ENG_EVT_ID_NAME_WARM_BOOT "Warm Boot" +#define ENG_EVT_ID_NAME_NORMAL_OP "Normal Operation" +#define ENG_EVT_ID_NAME_ANT_DISCONN "Antenna Disconn." +#define ENG_EVT_ID_NAME_ANT_SHORT "Ant. Short-Circ." +#define ENG_EVT_ID_NAME_ANT_OK "Antenna OK" +#define ENG_EVT_ID_NAME_LOW_SATS "Few Sats Only" + + +#define MBG_EVT_ID_NAMES_ENG \ +{ \ + ENG_EVT_ID_NAME_NONE, \ + ENG_EVT_ID_NAME_POW_UP_RES, \ + ENG_EVT_ID_NAME_WDOG_RES, \ + ENG_EVT_ID_NAME_COLD_BOOT, \ + ENG_EVT_ID_NAME_WARM_BOOT, \ + ENG_EVT_ID_NAME_NORMAL_OP, \ + ENG_EVT_ID_NAME_ANT_DISCONN, \ + ENG_EVT_ID_NAME_ANT_SHORT, \ + ENG_EVT_ID_NAME_ANT_OK, \ + ENG_EVT_ID_NAME_LOW_SATS \ +} + + + +/** + * @brief Enumeration of event severity levels + */ +enum MBG_EVT_LVLS +{ + MBG_EVT_LVL_NONE, + MBG_EVT_LVL_DEBUG, + MBG_EVT_LVL_INFO, + MBG_EVT_LVL_WARN, + MBG_EVT_LVL_ERR, + MBG_EVT_LVL_CRIT, + N_MBG_EVT_LVL +}; + + +#define ENG_EVT_LVL_NAME_NONE "None" +#define ENG_EVT_LVL_NAME_DEBUG "Debug" +#define ENG_EVT_LVL_NAME_INFO "Info" +#define ENG_EVT_LVL_NAME_WARN "Warn" +#define ENG_EVT_LVL_NAME_ERR "Err" +#define ENG_EVT_LVL_NAME_CRIT "Crit." + + +#define MBG_EVT_LVL_NAMES_ENG \ +{ \ + ENG_EVT_LVL_NAME_NONE, \ + ENG_EVT_LVL_NAME_DEBUG, \ + ENG_EVT_LVL_NAME_INFO, \ + ENG_EVT_LVL_NAME_WARN, \ + ENG_EVT_LVL_NAME_ERR, \ + ENG_EVT_LVL_NAME_CRIT \ +} + + +/** @brief Predefined event codes with associated severity levels */ + +#define MBG_EVT_NONE _mbg_mk_evt_code( MBG_EVT_ID_NONE, MBG_EVT_LVL_NONE ) +#define MBG_EVT_POW_UP_RES _mbg_mk_evt_code( MBG_EVT_ID_POW_UP_RES, MBG_EVT_LVL_WARN ) +#define MBG_EVT_WDOG_RES _mbg_mk_evt_code( MBG_EVT_ID_WDOG_RES, MBG_EVT_LVL_CRIT ) +#define MBG_EVT_COLD_BOOT _mbg_mk_evt_code( MBG_EVT_ID_COLD_BOOT, MBG_EVT_LVL_ERR ) +#define MBG_EVT_WARM_BOOT _mbg_mk_evt_code( MBG_EVT_ID_WARM_BOOT, MBG_EVT_LVL_ERR ) +#define MBG_EVT_NORMAL_OP _mbg_mk_evt_code( MBG_EVT_ID_NORMAL_OP, MBG_EVT_LVL_INFO ) +#define MBG_EVT_ANT_DISCONN _mbg_mk_evt_code( MBG_EVT_ID_ANT_DISCONN, MBG_EVT_LVL_CRIT ) +#define MBG_EVT_ANT_SHORT _mbg_mk_evt_code( MBG_EVT_ID_ANT_SHORT, MBG_EVT_LVL_CRIT ) +#define MBG_EVT_ANT_OK _mbg_mk_evt_code( MBG_EVT_ID_ANT_OK, MBG_EVT_LVL_INFO ) +#define MBG_EVT_LOW_SATS _mbg_mk_evt_code( MBG_EVT_ID_LOW_SATS, MBG_EVT_LVL_WARN ) + +/** @} group_evt_log */ + + + +/** + * @defgroup group_ims IMS support + * + * @note This is only available if ::GPS_HAS_IMS is set in RECEIVER_INFO::features. + * + * @{ */ + +/** + * @brief Generic state of an IMS device + */ +typedef struct +{ + uint8_t chassis_id; /**< chassis ID, 0 if installed on the backplane */ + uint8_t slot_id; /**< slot number on the chassis */ + uint16_t num_sensors; /**< number of sensors provided by the device */ + uint32_t reserved; /**< currently unused, always 0 */ + uint32_t flags; /**< currently unused, always 0 */ + +} MBG_IMS_STATE; + +#define _mbg_swab_mbg_ims_state( _p ) \ +{ \ + _mbg_swab16( &(_p)->num_sensors ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + + +/** + * @brief Generic state of an IMS sensor + */ +typedef struct +{ + uint16_t type; /**< sensor type, see ::MBG_IMS_SENSORS */ + uint16_t idx; /**< index of the sensor of this type */ + int32_t val; /**< sensor value, in units according to the type */ + int16_t exp; /**< 10s exponent of the sensor value */ + uint16_t reserved; /**< currently unused, always 0 */ + uint32_t flags; /**< currently unused, always 0 */ + +} MBG_IMS_SENSOR_STATE; + +#define _mbg_swab_mbg_ims_sensor_state( _p ) \ +{ \ + _mbg_swab16( &(_p)->type ); \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab32( &(_p)->val ); \ + _mbg_swab16( &(_p)->exp ); \ + _mbg_swab16( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/** + * @brief Generic state of an IMS sensor, with sensor index + */ +typedef struct +{ + uint32_t idx; /**< sensor index, 0..MBG_IMS_STATE::num_sensors - 1 */ + MBG_IMS_SENSOR_STATE state; /**< sensor state */ + +} MBG_IMS_SENSOR_STATE_IDX; + +#define _mbg_swab_mbg_ims_sensor_state_idx( _p ) \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_mbg_ims_sensor_state( &(_p)->state ); \ +} + + + +/** + * @brief IMS sensor types + */ +enum MBG_IMS_SENSORS +{ + MBG_IMS_SENSOR_TEMP_C, /**< temperature in degrees C */ + MBG_IMS_SENSOR_VOLTAGE, /**< voltage in val/exp, output state in flags */ + MBG_IMS_SENSOR_PLL, /**< control voltage in val/exp, lock state in flags */ + N_MBG_IMS_SENSORS /**< number of supported sensor types */ +}; + + + +// Definitions used with MBG_IMS_SENSOR_STATE::flags: + +// if MBG_IMS_SENSOR_STATE::type == MBG_IMS_SENSOR_VOLTAGE: +#define MBG_IMS_SENSOR_VOLTAGE_OUT_ENB 0x01 // output is enabled +#define MBG_IMS_SENSOR_VOLTAGE_OUT_OVR 0x02 // output overload + +// if MBG_IMS_SENSOR_STATE::type == MBG_IMS_SENSOR_PLL: +#define MBG_IMS_SENSOR_PLL_LOCKED 0x01 + + +/** @} group_ims */ + + + +/** + * @defgroup group_generic_io Generic I/O support. + * + * The definitions below are used with the GENERIC_IO API. + * + * This API is <b>NOT</b> supported by all devices, it depends on + * the type of the device, and the firmware version. The macro + * _pcps_has_generic_io() or the corresponding function + * mbg_dev_has_generic_io() should be used by applications to + * check whether a particular bus-level device supports this. + * @{ */ + + +typedef uint16_t GEN_IO_INFO_TYPE; + +#define _mbg_swab_gen_io_info_type( _p ) \ + _mbg_swab16( _p ) + + + +/** + * @brief The data structure used with the PCPS_GEN_IO_GET_INFO command + * + * type specifier in order to query from a device which of the other + * specified types is supported, and how many data sets are being + * used by the device. The GEN_IO_INFO_TYPE must be passed to the + * call which returns a GEN_IO_INFO structure filled by the device. + */ +typedef struct +{ + GEN_IO_INFO_TYPE type; // a PCPS_GEN_IO_GET_INFO type from the enum above + uint16_t num; // supported number of data sets of the specified type + +} GEN_IO_INFO; + +#define _mbg_swab_gen_io_info( _p ) \ +{ \ + _mbg_swab_gen_io_info_type( &(_p)->type ); \ + _mbg_swab16( &(_p)->num ); \ +} + + + +/** + * @brief Data types used with GEN_IO_INFO::type + * + * The first type specifier, PCPS_GEN_IO_GET_INFO, can + * be used to find out which of the other data types are + * supported, and how many data sets of the specified type + * are supported by a device. + */ +enum PCPS_GEN_IO_TYPES +{ + PCPS_GEN_IO_GET_INFO, /**< GEN_IO_INFO (read only) */ + PCPS_GEN_IO_CAL_REC_IRIG_RX_COMP, /**< CAL_REC_IRIG_RX_COMP (read/write) */ + N_PCPS_GEN_IO_TYPE /**< number of known types */ +}; + +/** @} group_generic_io */ + + +/*------------------------------------------------------------------------*/ + +/* + * The types below are not used with all devices: + */ + +typedef uint16_t ROM_CSUM; /* The ROM checksum */ +typedef uint16_t RCV_TIMEOUT; /* [min] (only if HAS_RCV_TIMEOUT) */ +typedef uint16_t IGNORE_LOCK; /* (only if GPS_HAS_IGNORE_LOCK) */ + +/* + * Originally IGNORE_LOG above has been a boolean value (equal or + * not equal 0) which was evaluated the same way for all ports. + * + * Due to special firmware requirements it has been changed to a + * bit maskable property in order to be able to specify the behaviour + * for individual ports. + * + * In order to keep compatibility with older versions the LSB is used + * to specify ignore_lock for all ports. The next higher bits are used + * to specify ignore_lock for an individual port, where the bit position + * depends on the port number, e.g. 0x02 for COM0, 0x04 for COM1, etc. + * The macros below can be used to simplify the code: + */ + +/* return a bit mask depending on the port number */ +#define IGNORE_LOCK_FOR_ALL_PORTS 0x01 + +#define _ignore_lock_for_all_ports() ( IGNORE_LOCK_FOR_ALL_PORTS ) + +#define _ignore_lock_for_port( _n ) ( 0x02 << (_n) ) + +/* check if all ports are ignore_lock'ed */ +#define _is_ignore_lock_all_ports( _il ) ( (_il) & IGNORE_LOCK_FOR_ALL_PORTS ) + +/* check if a specific port is ignore_lock'ed */ +#define _is_ignore_lock_for_port( _il, _n ) \ + ( (_il) & ( _ignore_lock_for_port(_n) | IGNORE_LOCK_FOR_ALL_PORTS ) ) + + +/*------------------------------------------------------------------------*/ + +/* + * The structures below are used with the SCU multiplexer board + * in a redundant system: + */ + +typedef struct +{ + uint32_t hw_id; // hardware identification + uint32_t fw_id; // firmware identification + uint16_t flags; // reserved currently 0 + uint8_t clk0_info; // reference clock 0 type + uint8_t clk1_info; // reference clock 1 type + uint16_t epld_status; // epld status word, see defintions below + uint16_t epld_control; // epld control word, see defintions below +} SCU_STAT_INFO; + +typedef struct +{ + uint16_t epld_control_mask; // control mask, determines which bit is to be changed + uint16_t epld_control_value; // control value, determines value of bits to be changed + uint32_t flags; // reserved, currently 0 +} SCU_STAT_SETTINGS; + +// definitions for status word bit masks +#define MSK_EPLD_STAT_TS1 0x0001 // state of time sync signal clk_1 +#define MSK_EPLD_STAT_TS2 0x0002 // state of time sync signal clk_2 +#define MSK_EPLD_STAT_TL_ERROR 0x0004 // state of time limit error input +#define MSK_EPLD_STAT_PSU1_OK 0x0008 // state of power supply 1 monitoring input +#define MSK_EPLD_STAT_PSU2_OK 0x0010 // state of power supply 2 monitoring input +#define MSK_EPLD_STAT_AUTO 0x0020 // AUTOMATIC/REMOTE or MANUAL Mode +#define MSK_EPLD_STAT_SEL 0x0040 // select bit for output MUX, ( clk_1 = 0 ) +#define MSK_EPLD_STAT_ENA 0x0080 // enable Bit for output MUX, set if enabled +#define MSK_EPLD_STAT_ACO 0x4000 // Access control override bit +#define MSK_EPLD_STAT_WDOG_OK 0x8000 // WDT_OK set to zero if watchdog expired + + +#define MSK_EPLD_CNTL_SEL_REM 0x0800 // remote select for output MUX ( clk_1 = 0 ) +#define MSK_EPLD_CNTL_DIS_REM 0x1000 // remote disable for output MUX +#define MSK_EPLD_CNTL_REMOTE 0x2000 // must be set to enable remote operation +#define MSK_EPLD_CNTL_SEL_SNMP 0x4000 // select clk for comm. ( clk1 = 0 ) +#define MSK_EPLD_CNTL_ENA_SNMP 0x8000 // connect COM0 channels to XPORT + + +/** + * @brief Definitions for SCU_STAT_INFO::clk0_info and SCU_STAT_INFO::clk1_info + * + * Can be used to determine the reference clock type connected to the SCU input channels. + */ +enum SCU_CLK_INFO_TYPES +{ + SCU_CLK_INFO_GPS, ///< ref. clock is GPS receiver + SCU_CLK_INFO_DCF_PZF, ///< ref. clock is DCF77 PZF receiver + SCU_CLK_INFO_DCF_AM, ///< ref. clock is DCF77 AM receiver + SCU_CLK_INFO_TCR, ///< ref. clock is IRIG time code receiver + N_SCU_CLK_INFO ///< number of known types +}; + + + +/*------------------------------------------------------------------------*/ + +/** + * @brief Satellite receiver modes of operation. + * + * @note Some of the code combinations are obsolete with recent + * satellite receivers. However, this doesn't matter since the mode + * is just read from the receiver. + */ +#define REMOTE 0x10 +#define BOOT 0x20 + +#define TRACK ( 0x01 ) +#define AUTO_166 ( 0x02 ) +#define WARM_166 ( 0x03 | BOOT ) +#define COLD_166 ( 0x04 | BOOT ) +#define AUTO_BC ( 0x05 | REMOTE ) +#define WARM_BC ( 0x06 | REMOTE | BOOT ) +#define COLD_BC ( 0x07 | REMOTE | BOOT ) +#define UPDA_166 ( 0x08 | BOOT ) +#define UPDA_BC ( 0x09 | REMOTE | BOOT ) + + + +typedef int16_t DAC_VAL; + +#define _mbg_swab_dac_val( _p ) \ + _mbg_swab16( _p ); + + + +/** + * @brief Satellite receiver status information + */ +typedef struct +{ + uint16_t mode; /**< Mode of operation, see predefined codes */ + 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 ) + + + +/** + * @brief An enumeration of known satellite navigation systems + */ +enum MBG_GNSS_TYPES +{ + GNSS_TYPE_GPS, ///< GPS, United States + GNSS_TYPE_GLONASS, ///< GLONASS, Russia + GNSS_TYPE_BEIDOU, ///< BEIDOU, China + GNSS_TYPE_GALILEO, ///< GALILEO, Europe + N_GNSS_TYPES ///< Number of defined codes +}; + +#define GNSS_TYPE_STRS \ +{ \ + "GPS", \ + "GLONASS", \ + "BEIDOU" , \ + "GALILEO" \ +} + +#define MBG_GNSS_TYPE_MSK_GPS ( 1UL << GNSS_TYPE_GPS ) +#define MBG_GNSS_TYPE_MSK_GLONASS ( 1UL << GNSS_TYPE_GLONASS ) +#define MBG_GNSS_TYPE_MSK_BEIDOU ( 1UL << GNSS_TYPE_BEIDOU ) +#define MBG_GNSS_TYPE_MSK_GALILEO ( 1UL << GNSS_TYPE_GALILEO ) + + +#define N_GNSS_MODE_PRIO 8 + +typedef struct +{ + uint32_t gnss_set; /**< current set of GNSS types */ + uint8_t prio[N_GNSS_MODE_PRIO]; /**< index 0 for highest priority, use GNSS enumeration above, init with 0xFF if not supported */ + uint32_t flags; /**< see below */ +} MBG_GNSS_MODE_SETTINGS; + +#define _mbg_swab_mbg_gnss_mode_settings( _p ) \ +{ \ + _mbg_swab32( &(_p)->gnss_set ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + + +typedef struct +{ + MBG_GNSS_MODE_SETTINGS settings; /**< current GNSS mode settings */ + uint32_t supp_gnss_types; /**< bit masks of supported GNSS types */ + uint32_t flags; /**< indicates which of the defined flags are supported by the device */ +} MBG_GNSS_MODE_INFO; + +#define _mbg_swab_mbg_gnss_mode_info( _p ) \ +{ \ + _mbg_swab_mbg_gnss_mode_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_gnss_types ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/** + * @brief Flags used with MBG_GNSS_MODE_SETTINGS::flags and MBG_GNSS_MODE_INFO::flags + */ +enum MBG_GNSS_MODE_FLAG_BITS +{ + MBG_GNSS_FLAG_EXCLUSIVE, ///< (read only) only one of the supported GNSS systems can be used at the same time + MBG_GNSS_FLAG_HAS_PRIORITY, ///< (read only) priority can be configured using the MBG_GNSS_MODE_SETTINGS::prio field + N_MBG_GNSS_FLAGS +}; + +#define MBG_GNSS_FLAG_MSK_EXCLUSIVE ( 1UL << MBG_GNSS_FLAG_EXCLUSIVE ) +#define MBG_GNSS_FLAG_MSK_HAS_PRIORITY ( 1UL << MBG_GNSS_FLAG_HAS_PRIORITY ) + + + +#define MAX_USED_SATS 32 + +/** + * @brief SV information from a certain GNSS type. + */ +typedef struct +{ + uint8_t gnss_type; /**< GNSS type from the enumeration above */ + uint8_t reserved; + uint16_t good_svs; + uint16_t svs_in_view; + uint8_t svs[MAX_USED_SATS]; +} GNSS_SAT_INFO; + +#define _mbg_swab_gnss_sat_info( _p ) \ +{ \ + _mbg_swab16( &(_p)->good_svs ); \ + _mbg_swab16( &(_p)->svs_in_view ); \ +} + + +#ifndef _IDENT_DEFINED + + typedef union + { + char c[16]; // as string which may NOT be terminated + int16_t wrd[8]; + uint32_t lw[4]; + } IDENT; + + #define _IDENT_DEFINED +#endif + +#define _mbg_swab_ident( _p ) \ +{ \ + int i; \ + for ( i = 0; i < 4; i++ ) \ + _mbg_swab32( &(_p)->lw[i] ); \ +} + +/** + * @brief A data type used to configure the length of an antenna cable [m] + */ +typedef uint16_t ANT_CABLE_LEN; + +#define _mbg_swab_ant_cable_len( _p ) _mbg_swab16( _p ) + + + +/** + * @defgroup group_ip4_cfg Simple configuration and status + * of an optional LAN interface. + * + * @note This is only supported if the flag ::GPS_HAS_LAN_IP4 is set + * in RECEIVER_INFO::features. + * + * @{ */ + + +/** + * @brief An IPv4 address + */ +typedef uint32_t IP4_ADDR; + +#define _mbg_swab_ip4_addr( _p ) \ + _mbg_swab32( _p ); + + +/** + * @brief Settings of an IPv4 network interface + */ +typedef struct +{ + IP4_ADDR ip_addr; /**< the IP address */ + IP4_ADDR netmask; /**< the network mask */ + IP4_ADDR broad_addr; /**< the broadcast address */ + IP4_ADDR gateway; /**< the default gateway */ + uint16_t flags; /**< flags as specified below */ + uint16_t vlan_cfg; /**< VLAN configuration, 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_swab16( &(_p)->flags ); \ + _mbg_swab16( &(_p)->vlan_cfg ); \ +} + + +/** + * @brief Definitions used with IP4_SETTINGS::vlan_cfg + * + * @note IP4_SETTINGS::vlan_cfg contains a combination of + * a VLAN ID number plus a VLAN priority code. + */ +#define VLAN_ID_BITS 12 ///< number of bits to hold the ID +#define N_VLAN_ID ( 1 << VLAN_ID_BITS ) ///< number of ID values +#define MIN_VLAN_ID 0 ///< minimum ID value +#define MAX_VLAN_ID ( N_VLAN_ID - 1 ) ///< maximum ID value + +// vlan_id = ( vlan_cfg >> VLAN_ID_SHIFT ) & VLAN_ID_MSK +#define VLAN_ID_SHIFT 0 +#define VLAN_ID_MSK ( ( 1 << VLAN_ID_BITS ) - 1 ) + + +#define VLAN_PRIORITY_BITS 3 ///< number of bits to hold priority +#define N_VLAN_PRIORITY ( 1 << VLAN_PRIORITY_BITS ) ///< number of priority values +#define MIN_VLAN_PRIORITY 0 ///< minimum priority +#define MAX_VLAN_PRIORITY ( N_VLAN_PRIORITY - 1 ) ///< maximum priority + +// vlan_priority = ( vlan_cfg >> VLAN_PRIORITY_SHIFT ) & VLAN_PRIORITY_MSK +#define VLAN_PRIORITY_SHIFT ( ( 8 * sizeof( uint16_t ) ) - VLAN_PRIORITY_BITS ) +#define VLAN_PRIORITY_MSK ( ( 1 << VLAN_PRIORITY_BITS ) - 1 ) + +/** + * @brief Macros used to encode/decode packed vlan_cfg variables + */ +#define _decode_vlan_id( _cfg ) ( ( (_cfg) >> VLAN_ID_SHIFT ) & VLAN_ID_MSK ) +#define _decode_vlan_priority( _cfg ) ( ( (_cfg) >> VLAN_PRIORITY_SHIFT ) & VLAN_PRIORITY_MSK ) +#define _encode_vlan_cfg( _id, _prty ) ( ( (_id) << VLAN_ID_SHIFT ) | ( (_prty) << VLAN_PRIORITY_SHIFT ) ) + + +#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 + + + +/** + * @brief A structure to holds the MAC address of a LAN interface + */ +typedef struct +{ + uint8_t b[6]; +} MBG_MAC_ADDR; + + + +/** + * @brief LAN interface information + * + * This structure can be retrieved from a device + * to check the device's capabilities. + */ +typedef struct +{ + uint16_t type; ///< type of LAN interface, see below + MBG_MAC_ADDR mac_addr; ///< MAC address + uint16_t ver_code; ///< version number, high byte.low byte, in hex + char ver_str[GPS_ID_STR_SIZE]; ///< version string + char sernum[GPS_ID_STR_SIZE]; ///< serial number + uint32_t rsvd_0; ///< reserved, currently always 0 + uint16_t flags; ///< flags as specified below + uint16_t rsvd_1; ///< reserved, currently always 0 + +} LAN_IF_INFO; + +#define _mbg_swab_lan_if_info( _p ) \ +{ \ + _mbg_swab16( &(_p)->type ); \ + _mbg_swab16( &(_p)->ver_code ); \ + _mbg_swab32( &(_p)->rsvd_0 ); \ + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab16( &(_p)->rsvd_1 ); \ +} + + + +/** + * @brief Codes used with LAN_IF_INFO::type + */ +enum LAN_IF_TYPES +{ + LAN_IF_TYPE_XPORT, ///< LAN interface on an XPORT + LAN_IF_TYPE_PTP, ///< LAN interface is a special PTP interface + N_LAN_IF_TYPE ///< number of defined LAN interface types +}; + + +/** + * @brief Enumeration of flag bits used with IP4_SETTINGS::flags and LAN_IF_INFO::flags + * + * @see MBG_IP4_FLAG_MASKS + */ +enum MBG_IP4_FLAG_BITS +{ + IP4_BIT_DHCP, ///< DHCP supported (LAN_IF_INFO) / enabled (IP4_SETTINGS) + IP4_BIT_LINK, ///< used only in IP4_SETTINGS to report link state + IP4_BIT_VLAN, ///< VLAN supported (LAN_IF_INFO) / enabled (IP4_SETTINGS) + N_IP4_BIT ///< number of defined flag bits +}; + +/** + * @brief Bit masks used with IP4_SETTINGS::flags and LAN_IF_INFO::flags + * + * @see MBG_IP4_FLAG_BITS + */ +enum MBG_IP4_FLAG_MASKS +{ + IP4_MSK_DHCP = ( 1UL << IP4_BIT_DHCP ), ///< see ::IP4_BIT_DHCP + IP4_MSK_LINK = ( 1UL << IP4_BIT_LINK ), ///< see ::IP4_BIT_LINK + IP4_MSK_VLAN = ( 1UL << IP4_BIT_VLAN ), ///< see ::IP4_BIT_VLAN +}; + +/** @} group_ip4_cfg */ + + + +/** + * @defgroup group_ptp Definitions used with PTP/IEEE1588 + * + * @{ */ + +/** + * @brief Enumeration of protocols possibly used with PTP + * + * @see PTP_NW_PROT_MASKS + */ +enum PTP_NW_PROTS +{ + PTP_NW_PROT_RESERVED, ///< reserved + PTP_NW_PROT_UDP_IPV4, ///< IPv4 + PTP_NW_PROT_UDP_IPV6, ///< IPv6 + PTP_NW_PROT_IEEE_802_3, ///< Ethernet (raw layer 2) + PTP_NW_PROT_DEVICE_NET, ///< DeviceNet + PTP_NW_PROT_CONTROL_NET, ///< ControlNet + PTP_NW_PROT_PROFINET, ///< ProfiNet + N_PTP_NW_PROT ///< number of defined protocols +}; + + +/** + * @brief Bit masks for enumerated protocols possibly used with PTP + * + * @see PTP_NW_PROTS + */ +enum PTP_NW_PROT_MASKS +{ + PTP_NW_PROT_MSK_RESERVED = ( 1UL << PTP_NW_PROT_RESERVED ), ///< see ::PTP_NW_PROT_RESERVED + PTP_NW_PROT_MSK_UDP_IPV4 = ( 1UL << PTP_NW_PROT_UDP_IPV4 ), ///< see ::PTP_NW_PROT_UDP_IPV4 + PTP_NW_PROT_MSK_UDP_IPV6 = ( 1UL << PTP_NW_PROT_UDP_IPV6 ), ///< see ::PTP_NW_PROT_UDP_IPV6 + PTP_NW_PROT_MSK_IEEE_802_3 = ( 1UL << PTP_NW_PROT_IEEE_802_3 ), ///< see ::PTP_NW_PROT_IEEE_802_3 + PTP_NW_PROT_MSK_DEVICE_NET = ( 1UL << PTP_NW_PROT_DEVICE_NET ), ///< see ::PTP_NW_PROT_DEVICE_NET + PTP_NW_PROT_MSK_CONTROL_NET = ( 1UL << PTP_NW_PROT_CONTROL_NET ), ///< see ::PTP_NW_PROT_CONTROL_NET + PTP_NW_PROT_MSK_PROFINET = ( 1UL << PTP_NW_PROT_PROFINET ) ///< see ::PTP_NW_PROT_PROFINET +}; + + + +/** + * @brief Name strings for the protocols possibly used with PTP + * + * @see PTP_NW_PROTS + */ +#define PTP_NW_PROT_STRS \ +{ \ + "Reserved", \ + "UDP/IPv4 (L3)", \ + "UDP/IPv6 (L3)", \ + "IEEE 802.3 (L2)", \ + "DeviceNet", \ + "ControlNet", \ + "PROFINET" \ +} + + +/** + * @brief Short name strings for the protocols possibly used with PTP + * + * @see PTP_NW_PROTS + */ +#define PTP_NW_PROT_STRS_SHORT \ +{ \ + "RSV", \ + "IP4", \ + "IP6", \ + "ETH", \ + "DN", \ + "CN", \ + "PN" \ +} + + +/** + * @brief Possible states of a PTP port + */ +enum PTP_PORT_STATES +{ + PTP_PORT_STATE_UNINITIALIZED, ///< uninitialized + PTP_PORT_STATE_INITIALIZING, ///< currently initializing + PTP_PORT_STATE_FAULTY, ///< faulty + PTP_PORT_STATE_DISABLED, ///< disabled + PTP_PORT_STATE_LISTENING, ///< listening for PTP packets + PTP_PORT_STATE_PRE_MASTER, ///< going to become master + PTP_PORT_STATE_MASTER, ///< master + PTP_PORT_STATE_PASSIVE, ///< passive + PTP_PORT_STATE_UNCALIBRATED, ///< uncalibrated + PTP_PORT_STATE_SLAVE, ///< slave + N_PTP_PORT_STATE ///< number of defined port states +}; + + +/** + * @brief Name strings for the PTP port states + */ +#define PTP_PORT_STATE_STRS \ +{ \ + "UNINITIALIZED", \ + "INITIALIZING", \ + "FAULTY", \ + "DISABLED", \ + "LISTENING", \ + "PRE_MASTER", \ + "MASTER", \ + "PASSIVE", \ + "UNCALIBRATED", \ + "SLAVE" \ +} + + +/** + * @brief An entry for a table of parameters which can not be accessed by an enumerated index + */ +typedef struct +{ + uint8_t value; ///< the parameter value + const char *name; ///< the parameter name +} PTP_TABLE; + + + +/** + * @brief An enumeration of PTP delay mechanisms + * + * @note This is different than the numeric values specified + * in the published specs for IEEE1588. In addition, the specs + * define code 0x14 for "disabled". + * + * @see PTP_DELAY_MECH_MASKS + * @see PTP_DELAY_MECH_NAMES + */ +enum PTP_DELAY_MECHS +{ + PTP_DELAY_MECH_E2E, ///< End-to-End (in PTP2 specs: 0x01) + PTP_DELAY_MECH_P2P, ///< Peer-to-Peer (in PTP2 specs: 0x02) + N_PTP_DELAY_MECH ///< number of defined delay mechanisms +}; + + +/** + * @brief Bit masks associated to enumerated PTP delay mechanisms + * + * @see PTP_DELAY_MECH_MASKS + */ +enum PTP_DELAY_MECH_MASKS +{ + PTP_DELAY_MECH_MSK_E2E = ( 1UL << PTP_DELAY_MECH_E2E ), ///< see ::PTP_DELAY_MECH_E2E + PTP_DELAY_MECH_MSK_P2P = ( 1UL << PTP_DELAY_MECH_E2E ) ///< see ::PTP_DELAY_MECH_E2E +}; + + +#define PTP_DELAY_MECH_NAME_E2E "E2E" +#define PTP_DELAY_MECH_NAME_P2P "P2P" + +/** + * @brief Name strings for the PTP delay mechanisms + * + * @see PTP_DELAY_MECHS + */ +#define PTP_DELAY_MECH_NAMES \ +{ \ + PTP_DELAY_MECH_NAME_E2E, \ + PTP_DELAY_MECH_NAME_P2P \ +} + + + +/** + * @brief An enumeration of accuracy classes used with PTP + * + * @note This enumeration does not start at 0 but with a bias + * specified by ::PTP_CLOCK_ACCURACY_NUM_BIAS. + * + * @see PTP_CLOCK_ACCURACY_STRS + */ +enum PTP_CLOCK_ACCURACIES +{ + PTP_CLOCK_ACCURACY_NUM_BIAS = 0x20, + PTP_CLOCK_ACCURACY_25ns = PTP_CLOCK_ACCURACY_NUM_BIAS, + PTP_CLOCK_ACCURACY_100ns, + PTP_CLOCK_ACCURACY_250ns, + PTP_CLOCK_ACCURACY_1us, + PTP_CLOCK_ACCURACY_2_5us, + PTP_CLOCK_ACCURACY_10us, + PTP_CLOCK_ACCURACY_25us, + PTP_CLOCK_ACCURACY_100us, + PTP_CLOCK_ACCURACY_250us, + PTP_CLOCK_ACCURACY_1ms, + PTP_CLOCK_ACCURACY_2_5ms, + PTP_CLOCK_ACCURACY_10ms, + PTP_CLOCK_ACCURACY_25ms, + PTP_CLOCK_ACCURACY_100ms, + PTP_CLOCK_ACCURACY_250ms, + PTP_CLOCK_ACCURACY_1s, + PTP_CLOCK_ACCURACY_10s, + PTP_CLOCK_ACCURACY_MORE_10s, + PTP_CLOCK_ACCURACY_RESERVED_1, + PTP_CLOCK_ACCURACY_RESERVED_2, + PTP_CLOCK_ACCURACY_RESERVED_3, + PTP_CLOCK_ACCURACY_RESERVED_4, + N_PTP_CLOCK_ACCURACY +}; + + +/** + * @brief Name strings for PTP accuracy classes + * + * @note The enumeration does not start at 0 but with a bias + * specified by ::PTP_CLOCK_ACCURACY_NUM_BIAS, so this bias needs + * to be accounted for when accessing a string table. + * + * @see PTP_CLOCK_ACCURACIES + */ +#define PTP_CLOCK_ACCURACY_STRS \ +{ \ + "< 25 ns", \ + "< 100 ns", \ + "< 250 ns", \ + "< 1 us", \ + "< 2.5 us", \ + "< 10 us", \ + "< 25 us", \ + "< 100 us", \ + "< 250 us", \ + "< 1 ms", \ + "< 2.5 ms", \ + "< 10 ms", \ + "< 25 ms", \ + "< 100 ms", \ + "< 250 ms", \ + "< 1 s", \ + "< 10 s", \ + "more than 10 s", \ + "reserved_1", \ + "reserved_2", \ + "reserved_3", \ + "reserved_4" \ +} + + + +/** + * @brief Codes to specify the type of a time source used with PTP + * + * @see PTP_TIME_SOURCE_TABLE + */ +enum PTP_TIME_SOURCES +{ + PTP_TIME_SOURCE_ATOMIC_CLOCK = 0x10, + PTP_TIME_SOURCE_GPS = 0x20, + PTP_TIME_SOURCE_TERRESTRIAL_RADIO = 0x30, + PTP_TIME_SOURCE_PTP = 0x40, + PTP_TIME_SOURCE_NTP = 0x50, + PTP_TIME_SOURCE_HAND_SET = 0x60, + PTP_TIME_SOURCE_OTHER = 0x90, + PTP_TIME_SOURCE_INTERNAL_OSCILLATOR = 0xA0 +}; + + + +/** + * @brief A table of PTP time source codes plus associated name strings + * + * @see PTP_TIME_SOURCES + */ +#define PTP_TIME_SOURCE_TABLE \ +{ \ + { PTP_TIME_SOURCE_ATOMIC_CLOCK, "Atomic Clock" }, \ + { PTP_TIME_SOURCE_GPS, "GPS" }, \ + { PTP_TIME_SOURCE_TERRESTRIAL_RADIO, "Terrestrial Radio" }, \ + { PTP_TIME_SOURCE_PTP, "PTP" }, \ + { PTP_TIME_SOURCE_NTP, "NTP" }, \ + { PTP_TIME_SOURCE_HAND_SET, "HAND SET" }, \ + { PTP_TIME_SOURCE_OTHER, "OTHER" }, \ + { PTP_TIME_SOURCE_INTERNAL_OSCILLATOR, "Internal Oscillator" }, \ + { 0, NULL } \ +} + + +/** + * @brief An enumeration of roles which can be taken by a PTP node + * + * @note A role in this context specifies a certain mode of operation. + * Depending on its specification a devices may not be able to take + * each of the specified roles. + * + * @see PTP_ROLE_STRS + * @see PTP_ROLE_STRS_SHORT + */ +enum PTP_ROLES +{ + PTP_ROLE_MULTICAST_SLAVE, ///< slave in multicast mode + PTP_ROLE_UNICAST_SLAVE, ///< slave in unicast mode + PTP_ROLE_MULTICAST_MASTER, ///< multicast master + PTP_ROLE_UNICAST_MASTER, ///< unicast master + PTP_ROLE_MULTICAST_AUTO, ///< multicast master or slave (auto selection) + N_PTP_ROLES ///< number of defined roles +}; + +#define PTP_ROLE_MSK_MULTICAST_SLAVE ( 1UL << PTP_ROLE_MULTICAST_SLAVE ) +#define PTP_ROLE_MSK_UNICAST_SLAVE ( 1UL << PTP_ROLE_UNICAST_SLAVE ) +#define PTP_ROLE_MSK_MULTICAST_MASTER ( 1UL << PTP_ROLE_MULTICAST_MASTER ) +#define PTP_ROLE_MSK_UNICAST_MASTER ( 1UL << PTP_ROLE_UNICAST_MASTER ) +#define PTP_ROLE_MSK_MULTICAST_AUTO ( 1UL << PTP_ROLE_MULTICAST_AUTO ) + +#define PTP_ROLE_MSK_SLAVES ( PTP_ROLE_MSK_MULTICAST_SLAVE | PTP_ROLE_MSK_UNICAST_SLAVE ) +#define PTP_ROLE_MSK_MASTERS ( PTP_ROLE_MSK_MULTICAST_MASTER | PTP_ROLE_MSK_UNICAST_MASTER ) + + +/** + * @brief Name strings for defined PTP roles + * + * @see PTP_ROLES + * @see PTP_ROLE_STRS_SHORT + */ +#define PTP_ROLE_STRS \ +{ \ + "Multicast Slave", \ + "Unicast Slave", \ + "Multicast Master", \ + "Unicast Master", \ + "Multicast (Auto)" \ +} + + +/** + * @brief Short name strings for defined PTP roles + * + * @see PTP_ROLES + * @see PTP_ROLE_STRS + */ +#define PTP_ROLE_STRS_SHORT \ +{ \ + "MCS", \ + "UCS", \ + "MCM", \ + "UCM", \ + "MC" \ +} + + +/** + * @brief A PTP clock identity + * + * @note This usually consists of a 6 byte MAC address with + * 2 fixed bytes inserted, or all ones as wildcard. + */ +typedef struct +{ + uint8_t b[8]; +} PTP_CLOCK_ID; + +#define _mbg_swab_ptp_clock_id( _p ) _nop_macro_fnc() // nothing to swap + +#define PTP_CLOCK_ID_WILDCARD { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } } + + +/** + * @brief A PTP port ID + * + * @note This usually consists of a 6 byte MAC address with + * 2 fixed bytes inserted, or all ones as wildcard. + */ +typedef uint16_t PTP_PORT_ID; + +#define _mbg_swab_ptp_port_id( _p ) _mbg_swab16( _p ) + +#define PTP_PORT_ID_WILDCARD 0xFFFF + + +/** + * @brief An enumeration of time scales used with PTP + * + * @note The standard time scale used by PTP is TAI, which is a linear time scale. + * The protocol provides a %UTC offset to be able to convert TAI to compute %UTC, which + * can observe leap seconds. For the arbitrary time scale the %UTC offset is unspecified, + * so arbitrary time can be %UTC, or something else. + * + * @see PTP_TIMESCALE_NAMES + * @see PTP_TIMESCALE_NAMES_SHORT + */ +enum PTP_TIME_SCALES +{ + PTP_TIMESCALE_PTP, ///< PTP default, TAI + PTP_TIMESCALE_ARB, ///< arbitrary time scale, maybe %UTC + N_PTP_TIMESCALE +}; + + +/** + * @brief Name strings for the PTP time scales + */ +#define PTP_TIMESCALE_NAME_PTP "PTP Standard (TAI)" +#define PTP_TIMESCALE_NAME_ARB "Arbitrary" + +/** + * @brief Short name strings for the PTP time scales + */ +#define PTP_TIMESCALE_NAME_PTP_SHORT "PTP" +#define PTP_TIMESCALE_NAME_ARB_SHORT "Arb" + + +/** + * @brief A table of name strings for the PTP time scales + * + * @see PTP_TIME_SCALES + * @see PTP_TIMESCALE_NAMES_SHORT + */ +#define PTP_TIMESCALE_NAMES \ +{ \ + PTP_TIMESCALE_NAME_PTP, \ + PTP_TIMESCALE_NAME_ARB \ +} + +/** + * @brief A table of short name strings for the PTP time scales + * + * @see PTP_TIME_SCALES + * @see PTP_TIMESCALE_NAMES + */ +#define PTP_TIMESCALE_NAMES_SHORT \ +{ \ + PTP_TIMESCALE_NAME_PTP_SHORT, \ + PTP_TIMESCALE_NAME_ARB_SHORT \ +} + + + +/** + * @brief A structure to used to read the status of the PTP protocol stack + */ +typedef struct +{ + uint16_t nw_prot; ///< one of the enumerated protocols, see ::PTP_NW_PROTS + uint8_t ptp_prot_version; ///< PTP protocol version, 1, or 2, usually 2 for v2 + uint8_t port_state; ///< one of the enumerated port states, see ::PTP_PORT_STATES + uint32_t flags; ///< see ::PTP_STATE_FLAGS + NANO_TIME offset; ///< estimated time offset from the upstream time source + NANO_TIME path_delay; + NANO_TIME mean_path_delay; + NANO_TIME delay_asymmetry; + + PTP_CLOCK_ID gm_id; ///< identifier ot the upstream time source + + uint16_t clock_offset_scaled_log_variance; + uint8_t clock_class; + uint8_t clock_accuracy; ///< see ::PTP_CLOCK_ACCURACIES + + uint32_t reserved_1; ///< reserved, currently always 0 + uint32_t reserved_2; ///< reserved, currently always 0 + + uint8_t domain_number; ///< the PTP clock domain number, 0:3 + uint8_t time_source; ///< see ::PTP_TIME_SOURCES + uint8_t delay_mech; ///< see ::PTP_DELAY_MECHS + int8_t log_delay_req_intv; + + int16_t utc_offset; ///< %UTC offset observed against TAI + DAC_VAL osc_dac_cal; ///< disciplination value of the oscillator + + uint32_t reserved_3; ///< reserved, currently always 0 + +} PTP_STATE; + +#define _mbg_swab_ptp_state( _p ) \ +{ \ + _mbg_swab16( &(_p)->nw_prot ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab_nano_time( &(_p)->offset ); \ + _mbg_swab_nano_time( &(_p)->path_delay ); \ + _mbg_swab_nano_time( &(_p)->mean_path_delay ); \ + _mbg_swab_nano_time( &(_p)->delay_asymmetry ); \ + _mbg_swab_ptp_clock_id( &(_p)->gm_id ); \ + _mbg_swab16( &(_p)->clock_offset_scaled_log_variance ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab16( &(_p)->utc_offset ); \ + _mbg_swab_dac_val( &(_p)->osc_dac_cal ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ +} + + +/** + * @brief Flags bits used with PTP_STATE::flags + * + * @see PTP_STATE_FLAG_MASKS + */ +enum PTP_STATE_FLAGS +{ + PTP_FLAG_SLAVE_ONLY, ///< the port can only be slave + PTP_FLAG_IS_SLAVE, ///< the port is currently slave + PTP_FLAG_TIMESCALE_IS_PTP, ///< the timescale is PTP standard, not arbitrary + PTP_FLAG_LS_ANN, ///< a leap second is being announced + PTP_FLAG_LS_ANN_NEG, ///< the announced leap second is negative + PTP_FLAG_IS_UNICAST, ///< the port currently operates in unicast mode + PTP_FLAG_UTC_VALID, ///< %UTC parameters are valid + N_PTP_STATE_FLAGS ///< the number of defined flag bits +}; + +/** + * @brief Flags masks used with PTP_STATE::flags + * + * @see PTP_STATE_FLAGS + */ +enum PTP_STATE_FLAG_MASKS +{ + PTP_FLAG_MSK_SLAVE_ONLY = ( 1UL << PTP_FLAG_SLAVE_ONLY ), ///< see ::PTP_FLAG_SLAVE_ONLY + PTP_FLAG_MSK_IS_SLAVE = ( 1UL << PTP_FLAG_IS_SLAVE ), ///< see ::PTP_FLAG_IS_SLAVE + PTP_FLAG_MSK_TIMESCALE_IS_PTP = ( 1UL << PTP_FLAG_TIMESCALE_IS_PTP ), ///< see ::PTP_FLAG_TIMESCALE_IS_PTP + PTP_FLAG_MSK_LS_ANN = ( 1UL << PTP_FLAG_LS_ANN ), ///< see ::PTP_FLAG_LS_ANN + PTP_FLAG_MSK_LS_ANN_NEG = ( 1UL << PTP_FLAG_LS_ANN_NEG ), ///< see ::PTP_FLAG_LS_ANN_NEG + PTP_FLAG_MSK_IS_UNICAST = ( 1UL << PTP_FLAG_IS_UNICAST ), ///< see ::PTP_FLAG_IS_UNICAST + PTP_FLAG_MSK_UTC_VALID = ( 1UL << PTP_FLAG_UTC_VALID ) ///< see ::PTP_FLAG_UTC_VALID +}; + + + +/** + * @brief A structure used to configure a PTP port + */ +typedef struct +{ + uint16_t nw_prot; ///< see ::PTP_NW_PROTS + uint8_t profile; ///< PTP profile, currently only 0 = default + uint8_t domain_number; ///< the PTP clock domain number, 0:3 + + uint8_t delay_mech; ///< see ::PTP_DELAY_MECHS + uint8_t ptp_role; ///< one of the supported PTP roles, see ::PTP_ROLES + uint8_t priority_1; ///< priority 1 + uint8_t priority_2; ///< priority 2 + + uint8_t dflt_clk_class_unsync_cold; // 6:255 + uint8_t dflt_clk_class_unsync_warm; // 6:255 + uint8_t dflt_clk_class_sync_cold; // 6:255 + uint8_t dflt_clk_class_sync_warm; // 6:255 + + uint8_t ann_rcpt_timeout; ///< announce msg. receipt timeout, see ::PTP_ANN_RCPT_TIMEOUT_LIMITS + uint8_t reserved_1; ///< reserved, currently always 0 + int16_t sync_intv; ///< log2 of the sync interval [s] + + int16_t ann_intv; ///< log2 of the announce interval [s] + int16_t delay_req_intv; ///< log2 of the delay request interval [s] + + uint32_t upper_bound; ///< sync state set to false if above this limit [ns] + uint32_t lower_bound; ///< sync state set to true if below this limit [ns] + + uint32_t reserved_2; ///< reserved, currently always 0 + uint32_t flags; ///< see ::PTP_CFG_FLAGS + +} PTP_CFG_SETTINGS; + +#define _mbg_swab_ptp_cfg_settings( _p ) \ +{ \ + _mbg_swab16( &(_p)->nw_prot ); \ + _mbg_swab16( &(_p)->sync_intv ); \ + _mbg_swab16( &(_p)->ann_intv ); \ + _mbg_swab16( &(_p)->delay_req_intv ); \ + _mbg_swab32( &(_p)->upper_bound ); \ + _mbg_swab32( &(_p)->lower_bound ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + + +/** + * @brief Possible values for PTP_CFG_SETTINGS::ann_rcpt_timeout + */ +enum PTP_ANN_RCPT_TIMEOUT_LIMITS +{ + PTP_ANN_RCPT_TIMEOUT_MIN = 2, + PTP_ANN_RCPT_TIMEOUT_MAX = 255, + DEFAULT_PTP_ANN_RCPT_TIMEOUT = 3 +}; + + + +/** + * @brief A structure to used to query the current configuration and capabilities of a PTP port + */ +typedef struct +{ + PTP_CFG_SETTINGS settings; ///< the current configuration + + uint8_t ptp_proto_version; ///< PTP protocol version, 1, or 2, usually 2 for v2 + uint8_t reserved_1; ///< reserved, currently always 0 + uint16_t reserved_2; ///< reserved, currently always 0 + + int16_t sync_intv_min; ///< log2 of minimum sync interval [s] + int16_t sync_intv_max; ///< log2 of maximum sync interval [s] + int16_t ann_intv_min; ///< log2 of minimum announce interval [s] + int16_t ann_intv_max; ///< log2 of maximum announce interval [s] + int16_t delay_req_intv_min; ///< log2 of minimum delay request interval [s] + int16_t delay_req_intv_max; ///< log2 of maximum delay request interval [s] + + uint32_t supp_flags; ///< a bit mask of supported features, see ::PTP_CFG_FLAGS + uint32_t supp_nw_prot; ///< a bit mask of supported network protocols, see ::PTP_NW_PROTS + uint32_t supp_profiles; ///< a bit mask of supported profiles, see ::PTP_PROFILES + uint32_t supp_delay_mech; ///< a bit mask of supported delay mechanisms, see ::PTP_DELAY_MECHS + +} PTP_CFG_INFO; + +#define _mbg_swab_ptp_cfg_info( _p ) \ +{ \ + _mbg_swab_ptp_cfg_settings( &(_p)->settings ); \ + _mbg_swab16( &(_p)->reserved_2 ); \ + _mbg_swab16( &(_p)->sync_intv_min ); \ + _mbg_swab16( &(_p)->sync_intv_max ); \ + _mbg_swab16( &(_p)->ann_intv_min ); \ + _mbg_swab16( &(_p)->ann_intv_max ); \ + _mbg_swab16( &(_p)->delay_req_intv_min ); \ + _mbg_swab16( &(_p)->delay_req_intv_max ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + _mbg_swab32( &(_p)->supp_nw_prot ); \ + _mbg_swab32( &(_p)->supp_profiles ); \ + _mbg_swab32( &(_p)->supp_delay_mech ); \ +} + + + +/** + * @brief Flags used with PTP_CFG_SETTINGS::flags and PTP_CFG_INFO::supp_flags + * + * @see PTP_CFG_FLAG_MASKS + */ +enum PTP_CFG_FLAGS +{ + PTP_CFG_TIME_SCALE_IS_PTP, ///< time scale is PTP/TAI, else arbitrary + PTP_CFG_V1_HW_COMPAT, ///< maybe required for certain NIC chips, not used by Meinberg + PTP_CFG_CAN_BE_UNICAST_SLAVE, ///< the PTP port can take the role of a unicast slave + PTP_CFG_CAN_BE_MULTICAST_MASTER, ///< the PTP port can take the role of a multicast master + PTP_CFG_CAN_BE_UNICAST_MASTER, ///< the PTP port can take the role of a unicast master + PTP_CFG_CAN_BE_MULTICAST_AUTO, ///< the PTP port can automatically become multicast master or slave + PTP_CFG_SUPP_UTC_VALID, ///< %UTC valid bit in PTP_STATE::flags is supported + N_PTP_CFG_FLAGS ///< the number of defined flags +}; + + +/** + * @brief Bit masks associated to ::PTP_CFG_FLAGS + */ +enum PTP_CFG_FLAG_MASKS +{ + PTP_CFG_MSK_TIME_SCALE_IS_PTP = ( 1UL << PTP_CFG_TIME_SCALE_IS_PTP ), ///< see ::PTP_CFG_TIME_SCALE_IS_PTP + PTP_CFG_MSK_V1_HW_COMPAT = ( 1UL << PTP_CFG_V1_HW_COMPAT ), ///< see ::PTP_CFG_V1_HW_COMPAT + PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE = ( 1UL << PTP_CFG_CAN_BE_UNICAST_SLAVE ), ///< see ::PTP_CFG_CAN_BE_UNICAST_SLAVE + PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER = ( 1UL << PTP_CFG_CAN_BE_MULTICAST_MASTER ), ///< see ::PTP_CFG_CAN_BE_MULTICAST_MASTER + PTP_CFG_MSK_CAN_BE_UNICAST_MASTER = ( 1UL << PTP_CFG_CAN_BE_UNICAST_MASTER ), ///< see ::PTP_CFG_CAN_BE_UNICAST_MASTER + PTP_CFG_MSK_CAN_BE_MULTICAST_AUTO = ( 1UL << PTP_CFG_CAN_BE_MULTICAST_AUTO ), ///< see ::PTP_CFG_CAN_BE_MULTICAST_AUTO + PTP_CFG_MSK_SUPP_UTC_VALID = ( 1UL << PTP_CFG_SUPP_UTC_VALID ) ///< see ::PTP_CFG_SUPP_UTC_VALID +}; + +/** @brief A bit mask of the role bits within the flag bits */ +#define PTP_CFG_MSK_SUPPORT_PTP_ROLES ( PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE | \ + PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER | \ + PTP_CFG_MSK_CAN_BE_UNICAST_MASTER | \ + PTP_CFG_MSK_CAN_BE_MULTICAST_AUTO ) + +/** @brief A bit mask of the unicast role bits within the flag bits */ +#define PTP_CFG_MSK_SUPPORT_PTP_UNICAST ( PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE | \ + PTP_CFG_MSK_CAN_BE_UNICAST_MASTER ) + +/** + * @brief Derive a "supported PTP roles" bit mask from PTP_CFG_INFO::supp_flags + * + * There's no explicite flag to indicate that the role of a multicast slave + * is supported, since this role is always supported. The sequence of flags + * indicating that a specific optional role is supported matches the enumerated + * roles above, but don't start at bit 0. So we compine the optional flag bits + * with the LSB always set for the implicite multicast slave role to yield + * a bit mask which according to the enumerated roles. + */ +#define _get_supp_ptp_role_idx_msk( _f ) \ + ( 1UL | ( ( (_f) & PTP_CFG_MSK_SUPPORT_PTP_ROLES ) >> ( PTP_CFG_CAN_BE_UNICAST_SLAVE - 1 ) ) ) + + +/** + * @brief Flags used with PTP_CFG_SETTINGS::profile and PTP_CFG_INFO::supp_profiles + * + * @see PTP_PROFILE_STRS + */ +enum PTP_PROFILES +{ + PTP_PROFILE_CUSTOM, ///< customizable, always supported + PTP_PROFILE_DFLT_E2E, ///< pure IEEE1588-2008 (PTPv2) with E2E + PTP_PROFILE_DFLT_P2P, ///< pure IEEE1588-2008 (PTPv2) with P2P + PTP_PROFILE_POWER, ///< IEEE C37.238 profile extension + PTP_PROFILE_TELECOM, ///< ITU-T G.8265.1 profile extension + N_PTP_PROFILES ///< number of supported profiles +}; + + +/** + * @brief Flags used with PTP_CFG_SETTINGS::profile and PTP_CFG_INFO::supp_profiles + * + * @see PTP_PROFILES + */ +enum PTP_PROFILE_MASKS +{ + PTP_MSK_PROFILE_CUSTOM = ( 1UL << PTP_PROFILE_CUSTOM ), ///< see ::PTP_PROFILE_CUSTOM + PTP_MSK_PROFILE_DFLT_E2E = ( 1UL << PTP_PROFILE_DFLT_E2E ), ///< see ::PTP_PROFILE_DFLT_E2E + PTP_MSK_PROFILE_DFLT_P2P = ( 1UL << PTP_PROFILE_DFLT_P2P ), ///< see ::PTP_PROFILE_DFLT_P2P + PTP_MSK_PROFILE_POWER = ( 1UL << PTP_PROFILE_POWER ), ///< see ::PTP_PROFILE_POWER + PTP_MSK_PROFILE_TELECOM = ( 1UL << PTP_PROFILE_TELECOM ) ///< see ::PTP_PROFILE_TELECOM +}; + + +/** + * @brief Name strings for defined PTP profiles + * + * @see PTP_PROFILES + */ +#define PTP_PROFILE_STRS \ +{ \ + "Custom", \ + "Default E2E", \ + "Default P2P", \ + "Power", \ + "Telecom" \ +} + + + +/** + * @brief Additional parameters for Power Profile + */ +#define PTP_POWER_PROFILE_GM_ID_MIN 3 +#define PTP_POWER_PROFILE_GM_ID_MAX 255 + +typedef struct +{ + uint32_t network_incaccuracy; ///< Pre-defined network inaccuracy from master in [ns] + uint8_t grandmaster_id; ///< [PTP_POWER_PROFILE_GM_ID_MIN..PTP_POWER_PROFILE_GM_ID_MAX] + uint8_t reserved_1; + uint16_t reserved_2; + +} PTP_POWER_PROFILE_CFG; + + + +/** + * @brief A host's fully qualified domain name (FQDN), or a numeric IP address string + * + * In theory each single component (host name, domain name, top level domain name) + * of a FQDN can have up to 63 characters, but the overall length is limited to + * 255 characters. We specify one more character for the trailing 0. + */ +typedef char MBG_HOSTNAME[256]; + + +/** + * @brief Limits to be considered when specifying PTP unicast masters + */ +typedef struct +{ + uint16_t n_supp_master; ///< number of unicast masters which can be specified + int16_t sync_intv_min; ///< log2 of minimum sync interval [s] + int16_t sync_intv_max; ///< log2 of maximum sync interval [s] + int16_t ann_intv_min; ///< log2 of minimum announce interval [s] + int16_t ann_intv_max; ///< log2 of maximum announce interval [s] + int16_t delay_req_intv_min; ///< log2 of minimum delay request interval [s] + int16_t delay_req_intv_max; ///< log2 of maximum delay request interval [s] + uint16_t reserved_0; ///< reserved, currently always 0 + uint32_t supp_flags; ///< a bit mask indicating which flags are supported + uint32_t reserved_1; ///< reserved, currently always 0 + +} PTP_UC_MASTER_CFG_LIMITS; + +#define _mbg_swab_ptp_uc_master_cfg_limits( _p ) \ +{ \ + _mbg_swab16( &(_p)->n_supp_master ); \ + _mbg_swab16( &(_p)->sync_intv_min ); \ + _mbg_swab16( &(_p)->sync_intv_max ); \ + _mbg_swab16( &(_p)->ann_intv_min ); \ + _mbg_swab16( &(_p)->ann_intv_max ); \ + _mbg_swab16( &(_p)->delay_req_intv_min ); \ + _mbg_swab16( &(_p)->delay_req_intv_max ); \ + _mbg_swab16( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ +} + + +/** + * @brief Configuration settings specifiying how to query a PTP unicast master + * + * This structure is used on a unicast slave to specify the settings of + * a unicast master polled by the slave. The number of unicast masters + * which can be specified depends on the capabilities of the slave device + * and is returned in PTP_UC_MASTER_CFG_LIMITS::n_supp_master. + * + * The structure ::PTP_UC_MASTER_SETTINGS_IDX should be sent to the device + * to save the configuration. + */ +typedef struct +{ + MBG_HOSTNAME gm_host; ///< grandmaster's hostname or IP address + PTP_CLOCK_ID gm_clock_id; ///< use clock ID of master port, or ::PTP_CLOCK_ID_WILDCARD + PTP_PORT_ID gm_port_id; ///< use target port ID of master port (e.g. 135) or ::PTP_PORT_ID_WILDCARD + int16_t sync_intv; ///< sync interval [log2 s] + int16_t ann_intv; ///< announce interval [log2 s] + int16_t delay_req_intv; ///< delay request interval [log2 s] + int32_t fix_offset; ///< constant time offset to be compensated [ns] + uint16_t message_duration; ///< time period until master stops sending messages [s] + uint16_t reserved_0; ///< reserved, currently always 0 + uint32_t reserved_1; ///< reserved, currently always 0 + uint32_t flags; ///< reserved, currently always 0 + +} PTP_UC_MASTER_SETTINGS; + +#define _mbg_swab_ptp_uc_master_settings( _p ) \ +{ \ + _mbg_swab_ptp_clock_id( &(_p)->gm_clock_id ); \ + _mbg_swab_ptp_port_id( &(_p)->gm_port_id ); \ + _mbg_swab16( &(_p)->sync_intv ); \ + _mbg_swab16( &(_p)->ann_intv ); \ + _mbg_swab16( &(_p)->delay_req_intv ); \ + _mbg_swab32( &(_p)->fix_offset ); \ + _mbg_swab16( &(_p)->message_duration ); \ + _mbg_swab16( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/** + * @brief Unicast PTP master message duration limits + * + * Each unicast PTP master sends messages to a unicast slave only + * for a given interval as requested by the particular slave, which + * is called message duration. + * These symbols define the minimum and maximum message duration + * configured on a slave for a specific unicast master, i.e. for + * PTP_UC_MASTER_SETTINGS::message_duration. The values are defined + * in the PTP v2 standard. + */ +enum PTP_UC_MSG_DURATION_LIMITS +{ + PTP_UC_MSG_DURATION_MIN = 10, ///< minimum message duration [s] + PTP_UC_MSG_DURATION_MAX = 1000 ///< maximum message duration [s] +}; + + + +/** + * @brief Configuration settings for a specific PTP unicast master + */ +typedef struct +{ + uint32_t idx; ///< index, 0..PTP_UC_MASTER_CFG_LIMITS::n_supp_master - 1 + PTP_UC_MASTER_SETTINGS settings; ///< specification for the unicast master with that index + +} PTP_UC_MASTER_SETTINGS_IDX; + +#define _mbg_swab_ptp_uc_master_settings_idx( _p ) \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ptp_uc_master_settings( &(_p)->settings ); \ +} + + +/** + * @brief Current settings and general capabilities of a unicast master + * + * This structure is used with a PTP unicast slave device to specify + * a PTP unicast master which can be queried by the slave device. + */ +typedef struct +{ + PTP_UC_MASTER_SETTINGS settings; ///< current settings + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< reserved, currently always 0 + +} PTP_UC_MASTER_INFO; + +#define _mbg_swab_ptp_uc_master_info( _p ) \ +{ \ + _mbg_swab_ptp_uc_master_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} + + +/** + * @brief Current settings and general capabilities of a specific unicast master + * + * This structure is used with a PTP unicast slave device to specify + * a PTP unicast master which can be queried by the slave device. + * + * This structure should be read from the device to retrieve the + * current settings and capabilities. The number of supported + * configuration records is PTP_UC_MASTER_CFG_LIMITS::n_supp_master. + * + * @note The ::PTP_UC_MASTER_SETTINGS_IDX structure should be send back + * to the device to save the configuration. + */ +typedef struct +{ + uint32_t idx; ///< index, 0..PTP_UC_MASTER_CFG_LIMITS::n_supp_master - 1 + PTP_UC_MASTER_INFO info; ///< capabilities and current settings + +} PTP_UC_MASTER_INFO_IDX; + +#define _mbg_swab_ptp_uc_master_info_idx( _p ) \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ptp_uc_master_info( &(_p)->info ); \ +} + + +/** @} group_ptp */ + + +/** + * @defgroup group_lno Definitions used with LNO devices + * + * @{ */ + +#define MAX_LNO_OUTPUT 4 + +/** + * @brief LNO status + */ +typedef struct +{ + uint16_t sine_lvl[MAX_LNO_OUTPUT]; ///< signal levels at the outputs + + uint16_t max_sine_lvl; ///< max level of an output, e.g. 1024 + uint8_t n_outputs; ///< actual number of outputs [0..::MAX_LNO_OUTPUT-1] + uint8_t out_enb_state; ///< e.g. bit 0 is set if corresponding output 0 is enabled, etc. + + uint16_t reserved_0; ///< reserved, currently always 0 + uint16_t flags; ///< status flags, see ::LNO_STATE_FLAG_BITS + +} LNO_STATE; + +#define _mbg_swab_lno_state( _p ) \ +{ \ + int i; \ + \ + for ( i = 0; i < MAX_LNO_OUTPUT; i++ ) \ + _mbg_swab16( &(_p)->sine_lvl[i] ); \ + \ + _mbg_swab_16( &(_p)->max_sine_lvl ); \ + _mbg_swab_16( &(_p)->reserved_0 ); \ + _mbg_swab_16( &(_p)->flags ); \ +} + + +/** + * @brief Flags used with LNO_STATE::flags + */ +enum LNO_STATE_FLAG_BITS +{ + LNO_FLAG_BIT_PLL_LOCKED, ///< PLL is locked + N_LNO_FLAG_BIT ///< number of known bits +}; + +#define LNO_FLAG_PLL_LOCKED ( 1UL << LNO_FLAG_BIT_PLL_LOCKED ) + +/** @} group_lno */ + + +/*------------------------------------------------------------------------*/ + +/** + * @brief Ephemeris parameters of one specific satellite + * + * Needed to compute the position of a satellite at a given time with + * high precision. Valid for an interval of 4 to 6 hours from start + * of transmission. + */ +typedef struct +{ + CSUM csum; ///< checksum of the remaining bytes + int16_t valid; ///< flag data are valid + + HEALTH health; ///< health indication of transmitting SV [---] + IOD IODC; ///< Issue Of Data, Clock + IOD IODE2; ///< Issue of Data, Ephemeris (Subframe 2) + IOD IODE3; ///< Issue of Data, Ephemeris (Subframe 3) + T_GPS tt; ///< time of transmission + T_GPS t0c; ///< Reference Time Clock [---] + T_GPS t0e; ///< Reference Time Ephemeris [---] + + double sqrt_A; ///< Square Root of semi-major Axis [sqrt(m)] + double e; ///< Eccentricity [---] + double M0; ///< +- Mean Anomaly at Ref. Time [rad] + double omega; ///< +- Argument of Perigee [rad] + double OMEGA0; ///< +- Longit. of Asc. Node of orbit plane [rad] + double OMEGADOT; ///< +- Rate of Right Ascension [rad/sec] + double deltan; ///< +- Mean Motion Diff. from computed value [rad/sec] + double i0; ///< +- Inclination Angle [rad] + double idot; ///< +- Rate of Inclination Angle [rad/sec] + double crc; ///< +- Cosine Corr. Term to Orbit Radius [m] + double crs; ///< +- Sine Corr. Term to Orbit Radius [m] + double cuc; ///< +- Cosine Corr. Term to Arg. of Latitude [rad] + double cus; ///< +- Sine Corr. Term to Arg. of Latitude [rad] + double cic; ///< +- Cosine Corr. Term to Inclination Angle [rad] + double cis; ///< +- Sine Corr. Term to Inclination Angle [rad] + + double af0; ///< +- Clock Correction Coefficient 0 [sec] + double af1; ///< +- Clock Correction Coefficient 1 [sec/sec] + double af2; ///< +- Clock Correction Coefficient 2 [sec/sec^2] + double tgd; ///< +- estimated group delay differential [sec] + + uint16_t URA; ///< predicted User Range Accuracy + + uint8_t L2code; ///< code on L2 channel [---] + uint8_t L2flag; ///< L2 P data flag [---] +} EPH; + + + +/** + * @brief Almanac parameters of one specific satellite + * + * A reduced precision set of parameters used to check if a satellite + * is in view at a given time. Valid for an interval of more than 7 days + * from start of transmission. + */ +typedef struct +{ + CSUM csum; ///< checksum of the remaining bytes + int16_t valid; ///< flag data are valid + + HEALTH health; ///< [---] + T_GPS t0a; ///< Reference Time Almanac [sec] + + double sqrt_A; ///< Square Root of semi-major Axis [sqrt(m)] + double e; ///< Eccentricity [---] + + double M0; ///< +- Mean Anomaly at Ref. Time [rad] + double omega; ///< +- Argument of Perigee [rad] + double OMEGA0; ///< +- Longit. of Asc. Node of orbit plane [rad] + double OMEGADOT; ///< +- Rate of Right Ascension [rad/sec] + double deltai; ///< +- [rad] + double af0; ///< +- Clock Correction Coefficient 0 [sec] + double af1; ///< +- Clock Correction Coefficient 1 [sec/sec] +} ALM; + + + +/** + * @brief Summary of configuration and health data of all satellites + */ +typedef struct +{ + CSUM csum; ///< checksum of the remaining bytes + int16_t valid; ///< flag data are valid + + T_GPS tot_51; ///< time of transmission, page 51 + T_GPS tot_63; ///< time of transmission, page 63 + T_GPS t0a; ///< complete reference time almanac + + CFG cfg[N_SVNO]; ///< SV configuration from page 63 + HEALTH health[N_SVNO]; ///< SV health from pages 51, 63 +} CFGH; + + + +/** + * @brief GPS %UTC correction parameters + * + * %UTC correction parameters basically as sent by the GPS satellites. + * + * The csum field is only used by the card's firmware to check the + * consistency of the structure in non-volatile memory. + * + * The field labeled valid indicates if the parameter set is valid, i.e. + * if it contains data received from the satellites. + * + * t0t, A0 and A1 contain fractional correction parameters for the current + * GPS-%UTC time offset in addition to the whole seconds. This is evaluated + * by the receivers' firmware to convert GPS time to %UTC time. + * + * The delta_tls field contains the current full seconds offset between + * GPS time and %UTC, which corresponds to the number of leap seconds inserted + * into the %UTC time scale since GPS was put into operation in January 1980. + * + * delta_tlfs holds the number of "future" leap seconds, i.e. the %UTC offset + * after the next leap second event defined by WNlsf and DNt. + * + * The fields WNlsf and DNt specify the GPS week number and the day number + * in that week at the end of which a leap second is scheduled. + * + * @note: The satellites transmit WNlsf only as a signed 8 bit value, so it + * can only define a point in time which is ± 127 weeks off the current time. + * The firmware tries to expand this based on the current week number, but + * the result is ambiguous if the leap second occurs or occurred more + * than 127 weeks in the future or past. + * + * So the leap second date should only be evaluated if the fields delta_tls + * and delta_tlsf are different, in which case there is an actual leap second + * announcement inside the ± 127 week range. + */ +typedef struct +{ + CSUM csum; ///< Checksum of the remaining bytes + int16_t valid; ///< Flag indicating %UTC parameters are valid + + T_GPS t0t; ///< Reference Time %UTC Parameters [wn|sec] + double A0; ///< +- Clock Correction Coefficient 0 [sec] + double A1; ///< +- Clock Correction Coefficient 1 [sec/sec] + + uint16_t WNlsf; ///< Week number of nearest leap second + int16_t DNt; ///< The day number at the end of which a leap second occurs + int8_t delta_tls; ///< Current %UTC offset to GPS system time [sec] + int8_t delta_tlsf; ///< Future %UTC offset to GPS system time after next leap second transition [sec] +} UTC; + +#define _mbg_swab_utc_parm( _p ) \ +{ \ + _mbg_swab_csum( &(_p)->csum ); \ + _mbg_swab16( &(_p)->valid ); \ + _mbg_swab_t_gps( &(_p)->t0t ); \ + _mbg_swab_double( &(_p)->A0 ); \ + _mbg_swab_double( &(_p)->A1 ); \ + _mbg_swab16( &(_p)->WNlsf ); \ + _mbg_swab16( &(_p)->DNt ); \ +} + + + +/** + * @brief Ionospheric correction parameters + */ +typedef struct +{ + CSUM csum; ///< checksum of the remaining bytes + int16_t valid; ///< flag data are valid + + double alpha_0; ///< Ionosph. Corr. Coeff. Alpha 0 [sec] + double alpha_1; ///< Ionosph. Corr. Coeff. Alpha 1 [sec/deg] + double alpha_2; ///< Ionosph. Corr. Coeff. Alpha 2 [sec/deg^2] + double alpha_3; ///< Ionosph. Corr. Coeff. Alpha 3 [sec/deg^3] + + double beta_0; ///< Ionosph. Corr. Coeff. Beta 0 [sec] + double beta_1; ///< Ionosph. Corr. Coeff. Beta 1 [sec/deg] + double beta_2; ///< Ionosph. Corr. Coeff. Beta 2 [sec/deg^2] + double beta_3; ///< Ionosph. Corr. Coeff. Beta 3 [sec/deg^3] +} IONO; + + + +/** + * @brief GPS ASCII message + */ +typedef struct +{ + CSUM csum; ///< checksum of the remaining bytes */ + int16_t valid; ///< flag data are valid + char s[23]; ///< 22 chars GPS ASCII message plus trailing zero +} ASCII_MSG; + + + +enum GPS_PLATFORMS +{ + GPS_PLATFORM_PORTABLE, + GPS_PLATFORM_FIXED, + GPS_PLATFORM_STATIONARY, + GPS_PLATFORM_PEDESTRIAN, + GPS_PLATFORM_AUTOMOTIVE, + GPS_PLATFORM_SEA, + GPS_PLATFORM_AIRBORNE_1G, + GPS_PLATFORM_AIRBORNE_2G, + GPS_PLATFORM_AIRBORNE_4G, + N_GPS_PLATFORMS +}; + + +#define GPS_PLATFORM_STRS \ +{ \ + "Portable ", \ + "Fixed ", \ + "Stationary ", \ + "Pedestrian ", \ + "Automotive ", \ + "Sea ", \ + "Airborne <1G", \ + "Airborne <2G", \ + "Airborne <4G" \ +} + + + +enum TIME_MODES +{ + TIME_MODE_DISABLED, + TIME_MODE_SURVEY_IN, + TIME_MODE_FIXED, + N_TIME_MODES +}; + + + +typedef struct +{ + uint32_t time_mode; + uint32_t survey_in_duration; + uint32_t survey_in_pos_var; + int32_t fixedPosX; // cm + int32_t fixedPosY; // cm + int32_t fixedPosZ; // cm + uint32_t fixedPosVar; // cm + uint32_t flags; // currently 0 + uint32_t reserved; // currently 0 +} NAV_TIME_MODE_SETTINGS; + + +/** + * Navigation Engine settings to set configuration + * parameters of a dynamic platform model. + */ +typedef struct +{ + uint8_t dynamic_platform; + uint8_t fix_mode; + int8_t min_elevation; + uint8_t static_hold_threshold; + int32_t fixed_altitude; + uint32_t fixed_altitude_variance; + uint32_t flags; // currently 0 + uint32_t reserved; // currently 0 + NAV_TIME_MODE_SETTINGS nav_time_mode_settings; +} NAV_ENGINE_SETTINGS; + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + +#endif /* _GPSDEFS_H */ diff --git a/mbglib/common/gpsutils.h b/mbglib/common/gpsutils.h new file mode 100644 index 0000000..c2143ca --- /dev/null +++ b/mbglib/common/gpsutils.h @@ -0,0 +1,84 @@ + +/************************************************************************** + * + * $Id: gpsutils.h 1.7 2010/07/15 09:32:09Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for gpsutils.c. + * + * ----------------------------------------------------------------------- + * $Log: gpsutils.h $ + * Revision 1.7 2010/07/15 09:32:09Z martin + * Use DEG character definition from pcpslstr.h. + * Revision 1.6 2005/02/18 10:32:33Z martin + * Check more predefined macros to determine if compiling for Windows. + * Revision 1.5 2003/02/04 09:18:48Z MARTIN + * Updated function prototypes. + * Revision 1.4 2002/12/12 16:08:11 martin + * Definitions for degree character. + * Requires mbggeo.h. + * Updated function prototypes. + * Revision 1.3 2001/02/05 09:40:42Z MARTIN + * New file header. + * Source code cleanup. + * + **************************************************************************/ + +#ifndef _GPSUTILS_H +#define _GPSUTILS_H + + +/* Other headers to be included */ + +#include <mbggeo.h> + + +#ifdef _GPSUTILS + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + void swap_double( double *d ) ; + void swap_eph_doubles( EPH *ephp ) ; + void swap_alm_doubles( ALM *almp ) ; + void swap_utc_doubles( UTC *utcp ) ; + void swap_iono_doubles( IONO *ionop ) ; + void swap_pos_doubles( POS *posp ) ; + void sprint_dms( char *s, DMS *pdms, int prec ) ; + void sprint_alt( char *s, double alt ) ; + void sprint_pos_geo( char *s, POS *ppos, const char *sep, int prec ) ; + void sprint_fixed_freq( char *s, FIXED_FREQ_INFO *p_ff ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _GPSUTILS_H */ + diff --git a/mbglib/common/lan_util.c b/mbglib/common/lan_util.c new file mode 100644 index 0000000..cca8a0a --- /dev/null +++ b/mbglib/common/lan_util.c @@ -0,0 +1,1288 @@ + +/************************************************************************** + * + * $Id: lan_util.c 1.6 2013/03/19 10:24:51Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Utility functions useful for network programming. + * + * ----------------------------------------------------------------------- + * $Log: lan_util.c $ + * Revision 1.6 2013/03/19 10:24:51Z martin + * Fixed bugs in get_ip4_gateway(): A skipped routing entry was + * taken as default route, and thus a wrong default route 0.0.0.0 + * could be returned erraneously. Also, malloc() was used without + * checking the result. + * Added conditional debug code. + * Revision 1.5 2013/02/19 15:13:10 martin + * Added some new functions. + * Updated doxygen comments. + * Revision 1.4 2012/11/02 09:16:57 martin + * Fixed build under Windows. + * Revision 1.3 2012/10/02 18:23:28Z martin + * Removed obsolete code to avoid compiler warning. + * Revision 1.2 2012/03/09 08:49:19 martin + * Added some commonly used functions. + * Revision 1.1 2011/03/04 10:01:32Z martin + * Initial revision. + * + **************************************************************************/ + +#define _LAN_UTIL + #include <lan_util.h> +#undef _LAN_UTIL + +#include <stdio.h> +#include <string.h> + +#if defined ( MBG_TGT_UNIX ) + + #if defined ( MBG_TGT_LINUX ) + + #include <linux/types.h> + + // Some older versions of linux/types.h don't define u8..u64 + // for user space applications. However, if they do they also + // define BITS_PER_LONG, so we use this symbol to figure out + // if we need to define u8..u64 by ourselves. + #if !defined( BITS_PER_LONG ) + typedef uint8_t u8; + typedef uint16_t u16; + typedef uint32_t u32; + typedef uint64_t u64; + #endif + + #include <linux/sockios.h> + #include <linux/ethtool.h> + #include <linux/rtnetlink.h> + #endif + + #include <unistd.h> + #include <sys/ioctl.h> + #include <sys/errno.h> + #include <arpa/inet.h> + #include <netinet/in.h> + +#else + + // dummy codes, the functions will report an error ... + #define SIOCGIFADDR 0 + #define SIOCGIFNETMASK 0 + #define SIOCGIFBRDADDR 0 + + #if defined( MBG_TGT_WIN32 ) + #define snprintf _snprintf + #endif + +#endif + + +#if !defined( DEBUG_NETLINK ) + #define DEBUG_NETLINK ( 0 && defined( DEBUG ) && defined( MBG_TGT_LINUX ) ) +#endif + + +#if DEBUG_NETLINK + // we need a function to output debugging information + #if !defined STANDALONE + #include <ptp2_cnf.h> // for mbglog() from the ARM PTP projects + #else + // to be provided by the application + extern void mbglog( int priority, const char *fmt, ... ); + #endif +#endif // DEBUG_NETLINK + + + +// Maximum size of an IPv4 address string in dotted quad format, +// including a terminating 0, and thus the required minimum size +// for a buffer to take such a string. i.e. "aaa.bbb.ccc.ddd\0". +#define MAX_IP4_ADDR_STR_SIZE 16 + + +#if defined ( MBG_TGT_LINUX ) + +struct route_info +{ + struct in_addr dstAddr; + struct in_addr srcAddr; + struct in_addr gateWay; + char ifName[IF_NAMESIZE]; +}; + +#endif + + +#if defined( __BORLANDC__ ) \ + && ( __BORLANDC__ <= 0x410 ) // BC3.1 defines 0x410 ! + +#include <stdarg.h> + +// Declare a snprintf() function if not provided by the +// build environment, though this implementation actually +// does not check the string length ... + +static /*HDR*/ +int snprintf( char *s, size_t max_len, const char *fmt, ... ) +{ + int n; + va_list arg_list; + + va_start( arg_list, fmt ); + n = vsprintf( s, fmt, arg_list ); + va_end( arg_list ); + + return n; + +} // snprintf + +#endif + + + +/*HDR*/ +/** + * @brief Count the number of sequential bits set starting from MSB + * + * E.g. for 0xC0 and 0xC1 the results are both 2 since only + * the 2 MSBs are sequentially set. + * + * @param p_mask The IP4 net mask + * + * @return The number of sequential MSB bits set in val + * + * @see ip4_net_mask_from_cidr + */ +int get_ip4_net_mask_bits( const IP4_ADDR *p_mask ) +{ + IP4_ADDR msb_mask = IP4_MSB_MASK; + int i; + + for ( i = 0; i < MAX_IP4_BITS; i++ ) + { + if ( ( *p_mask & msb_mask ) == 0 ) + break; + + msb_mask >>= 1; + } + + return i; + +} // get_ip4_net_mask_bits + + + +/*HDR*/ +/** + * @brief Print an IPv4 address to a dotted quad format string. + * + * @param s The string buffer into which to print + * @param max_len Maximum length of the string, i.e. size of the buffer + * @param p_addr The IPv4 address + * @param info An optional string which is prepended to the string, or NULL + * + * @return The overall number of characters printed to the string + * + * @see snprint_ip4_cidr_addr + * @see str_to_ip4_addr + * @see cidr_str_to_ip4_addr_and_net_mask + */ +int snprint_ip4_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, const char *info ) +{ + int n = 0; + ulong ul = *p_addr; + + if ( info ) + n += snprintf( s, max_len, "%s", info ); + + // Don't use byte pointers here since this is not safe + // for both little and big endian targets. + n += snprintf( &s[n], max_len - n, "%lu.%lu.%lu.%lu", + BYTE_3( ul ), BYTE_2( ul ), + BYTE_1( ul ), BYTE_0( ul ) + ); + return n; + +} // snprint_ip4_addr + + + +/*HDR*/ +/** + * @brief Print an IPv4 address plus net mask to string in CIDR notation. + * + * The printed CIDR string is something like "172.16.3.250/24" + * + * @param s The string buffer into which to print + * @param max_len Maximum length of the string, i.e. size of the buffer + * @param p_addr The IPv4 address + * @param p_mask The IPv4 net mask + * @param info An optional string which is prepended to the string, or NULL + * + * @return The overall number of characters printed to the string + * + * @see snprint_ip4_addr + * @see str_to_ip4_addr + * @see cidr_str_to_ip4_addr_and_net_mask + */ +int snprint_ip4_cidr_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, + const IP4_ADDR *p_mask, const char *info ) +{ + int cidr_mask_bits; + IP4_ADDR normalized_addr = ip4_net_part_from_addr( p_addr, p_mask ); + + int n = snprint_ip4_addr( s, max_len, &normalized_addr, info ); + + cidr_mask_bits = get_ip4_net_mask_bits( p_mask ); + + if ( ( cidr_mask_bits >= MIN_IP4_CIDR_NETMASK_BITS ) && + ( cidr_mask_bits <= MAX_IP4_CIDR_NETMASK_BITS ) ) + n += snprintf( &s[n], max_len - n, "/%i", cidr_mask_bits ); + + return n; + +} // snprint_ip4_cidr_addr + + + +/*HDR*/ +/** + * @brief Convert a string to an IP4_ADDR. + * + * @param p_addr Pointer to the IP4_ADDR variable, or NULL, in which case this + * function can be used to check if the string is formally correct. + * @param s The string to be converted + * + * @return >= 0 on success, number of characters evaluated from the input string + * -1 if invalid number found in string + * -2 if separator is not a dot '.' + * + * @see snprint_ip4_addr + * @see snprint_ip4_cidr_addr + * @see cidr_str_to_ip4_addr_and_net_mask + */ +int str_to_ip4_addr( IP4_ADDR *p_addr, const char *s ) +{ + IP4_ADDR tmp_ip4_addr = 0; + const char *cp; + int i; + + for ( i = 0, cp = (char *) s; ; ) + { + unsigned long ul = strtoul( (char *) cp, (char **) &cp, 10 ); + + if ( ul > 255 ) // invalid number + return -1; + + tmp_ip4_addr |= ul << ( 8 * (3 - i) ); + + if ( ++i >= 4 ) + break; // done + + if ( *cp != '.' ) + return -2; // invalid string format, dot expected + + cp++; // skip dot + } + + if ( p_addr ) + *p_addr = tmp_ip4_addr; + + // success: return the number of evaluated chars + return cp - s; + +} // str_to_ip4_addr + + + +/*HDR*/ +/** + * @brief Convert a string in CIDR notation to an IP4_ADDR and net mask. + * + * @param p_addr Pointer to an IP4_ADDR variable for the IP4 address, + * or NULL, in which case this function can be used + * to check if the string is formally correct. + * @param p_mask Pointer to an IP4_ADDR variable for the net mask, + * or NULL, in which case this function can be used + * to check if the string is formally correct. + * @param cidr_str The string to be converted, in CIDR format, e.g. "172.16.3.250/24" + * + * @return >= 0 on success, number of characters evaluated from the input string + * one of the ::MBG_LU_CODES on error + * + * @see snprint_ip4_addr + * @see snprint_ip4_cidr_addr + * @see str_to_ip4_addr + */ +int cidr_str_to_ip4_addr_and_net_mask( IP4_ADDR *p_addr, IP4_ADDR *p_mask, + const char *cidr_str ) +{ + IP4_ADDR mask; + long cidr_mask_bits; + const char *cp; + int l; + int rc = str_to_ip4_addr( p_addr, cidr_str ); + + if ( rc < 0 ) // return current error + return rc; + + + l = strlen( cidr_str ); + + if ( l < rc ) // input string too short + return MBG_LU_ERR_FMT; + + + cp = &cidr_str[rc]; + + if ( *cp == 0 ) // end of string + { + // The string has no CIDR extension, so + // assume "/0", i.e. host mask 255.255.255.255; + mask = (IP4_ADDR) -1; + goto done; + } + + + if ( *cp != '/' ) + return MBG_LU_ERR_FMT; + + + cp++; + cidr_mask_bits = strtol( (char *) cp, (char **) &cp, 10 ); + + if ( ( cidr_mask_bits < MIN_IP4_CIDR_NETMASK_BITS ) || + ( cidr_mask_bits > MAX_IP4_CIDR_NETMASK_BITS ) ) + return MBG_LU_ERR_RANGE; + + + mask = ip4_net_mask_from_cidr( (int) cidr_mask_bits ); + +done: + if ( p_mask ) + *p_mask = mask; + + // success: return the number of evaluated chars + return cp - cidr_str; + +} // cidr_str_to_ip4_addr_and_net_mask + + + +/*HDR*/ +/** + * @brief Print a MAC ID or similar array of octets to a string. + * + * @param s The string buffer into which to print + * @param max_len Maximum length of the string, i.e. size of the buffer + * @param octets An array of octets + * @param num_octets The number of octets to be printed from the array + * @param sep The separator printed between the bytes, or 0 + * @param info An optional string which is prepended to the output, or NULL + * + * @return The overall number of characters printed to the string + * + * @see snprint_mac_addr + * @see str_to_octets + * @see check_octets_not_all_zero + */ +int snprint_octets( char *s, size_t max_len, const uint8_t *octets, + int num_octets, char sep, const char *info ) +{ + int n = 0; + int i; + + if ( info ) + n += snprintf( s, max_len, "%s", info ); + + for ( i = 0; i < num_octets; i++ ) + { + if ( i && sep ) + n += snprintf( &s[n], max_len - n, "%c", sep ); + + n += snprintf( &s[n], max_len - n, "%02X", octets[i] ); + } + + return n; + +} // snprint_octets + + + +/*HDR*/ +/** + * @brief Print a MAC address to a string. + * + * @param s The string buffer into which to print + * @param max_len Maximum length of the string, i.e. size of the buffer + * @param p_mac_addr The MAC address to be printed + * + * @return The overall number of characters printed to the string + * + * @see snprint_octets + * @see str_to_octets + * @see check_octets_not_all_zero + */ +int snprint_mac_addr( char *s, size_t max_len, const MBG_MAC_ADDR *p_mac_addr ) +{ + return snprint_octets( s, max_len, p_mac_addr->b, sizeof( *p_mac_addr ), MAC_SEP_CHAR, NULL ); + +} // snprint_mac_addr + + + +/*HDR*/ +/** + * @brief Set a MAC ID or a similar array of octets from a string. + * + * @param octets An array of octets to be set up + * @param num_octets The number of octets which can be stored + * @param s The string to be converted + * + * @return The overall number of octets decoded from the string + * + * @see snprint_octets + * @see snprint_mac_addr + * @see check_octets_not_all_zero + */ +int str_to_octets( uint8_t *octets, int num_octets, const char *s ) +{ + char *cp = (char *) s; + int i; + + // don't use strtok() since that functions modifies the original string + for ( i = 0; i < num_octets; ) + { + octets[i] = (uint8_t) strtoul( cp, &cp, 16 ); + i++; + + if ( *cp == 0 ) + break; // end of string + + if ( ( *cp != MAC_SEP_CHAR ) && ( *cp != MAC_SEP_CHAR_ALT ) ) + break; // invalid character + + cp++; + } + + return i; + +} // str_to_octets + + + +/*HDR*/ +/** + * @brief Check if an array of octets is valid, i.e. != 0 + * + * @param octets Pointer to the array of octets + * @param num_octets Number of octets + * + * @return MBG_LU_SUCCESS octets are valid, i.e. not all 0 + * MBG_LU_ERR_NOT_SET octets are invalid, i.e. all 0 + * + * @see snprint_octets + * @see snprint_mac_addr + * @see str_to_octets + */ +int check_octets_not_all_zero( const uint8_t *octets, int num_octets ) +{ + int i; + + // check if any of the MAC adddress bytes is != 0 + for ( i = 0; i < num_octets; i++ ) + if ( octets[i] != 0 ) + break; + + if ( i == num_octets ) // *all* bytes are 0 + return MBG_LU_ERR_NOT_SET; + + return 0; + +} // check_octets_not_all_zero + + + +/*HDR*/ +/** + * @brief Check if an array of octets is valid, i.e. != 0 + * + * @param p_addr Pointer to a MAC address + * + * @return MBG_LU_SUCCESS MAC address is valid, i.e. not all 0 + * MBG_LU_ERR_NOT_SET MAC address is invalid, i.e. all 0 + * + * @see check_octets_not_all_zero + */ +int check_mac_addr_not_all_zero( const MBG_MAC_ADDR *p_addr ) +{ + return check_octets_not_all_zero( p_addr->b, sizeof( p_addr->b ) ); + +} // check_mac_addr_not_all_zero + + + +#if defined( MBG_TGT_UNIX ) + +/*HDR*/ +/** + * @brief Do a SIOCGxxx IOCTL call to read specific information from a LAN interface + * + * @param if_name Name of the interface + * @param ioctl_code One of the predefined system SIOCGxxx IOCTL codes + * @param p_ifreq Pointer to a request buffer + * + * @return one of the ::MBG_LU_CODES + */ +int do_siocg_ioctl( const char *if_name, int ioctl_code, struct ifreq *p_ifreq ) +{ + int fd; + int rc; + + if ( strlen( if_name ) > ( IFNAMSIZ - 1 ) ) + return MBG_LU_ERR_PORT_NAME; + + fd = socket( AF_INET, SOCK_DGRAM, 0 ); + + if ( fd < 0 ) + return MBG_LU_ERR_SOCKET; + + strcpy( p_ifreq->ifr_name, if_name ); + + rc = ioctl( fd, ioctl_code, p_ifreq ); + + if ( rc < 0 ) + rc = MBG_LU_ERR_IOCTL; + + close( fd ); + + return MBG_LU_SUCCESS; + +} // do_siocg_ioctl + +#endif // defined( MBG_TGT_UNIX ) + + + +/*HDR*/ +/** + * @brief Retrieve the MAC address of a network interface + * + * @param if_name Name of the interface + * @param p_mac_addr Pointer to the MAC address buffer to be filled up + * + * @return one of the ::MBG_LU_CODES + * on error the MAC addr is set to all 0 + * + * @see get_port_mac_addr_check + */ +int get_port_mac_addr( const char *if_name, MBG_MAC_ADDR *p_mac_addr ) +{ + int rc = MBG_LU_ERR_NSUPP; + + #if defined( MBG_TGT_LINUX ) + struct ifreq ifr = { { { 0 } } }; + + rc = do_siocg_ioctl( if_name, SIOCGIFHWADDR, &ifr ); + + if ( rc != MBG_LU_SUCCESS ) + goto fail; + + memcpy( p_mac_addr, ifr.ifr_hwaddr.sa_data, sizeof( *p_mac_addr ) ); + + return rc; + +fail: + #endif + + memset( p_mac_addr, 0, sizeof( *p_mac_addr ) ); + + return rc; + +} // get_port_mac_addr + + + +/*HDR*/ +/** + * @brief Retrieve and check the MAC address of a network interface + * + * @param if_name Name of the interface + * @param p_mac_addr Pointer to the MAC address buffer to be filled up + * + * @return one of the ::MBG_LU_CODES + * on error the MAC addr is set to all 0 + * + * @see get_port_mac_addr + */ +int get_port_mac_addr_check( const char *if_name, MBG_MAC_ADDR *p_mac_addr ) +{ + int rc = get_port_mac_addr( if_name, p_mac_addr ); + + if ( rc == MBG_LU_SUCCESS ) + rc = check_octets_not_all_zero( p_mac_addr->b, sizeof( *p_mac_addr ) ); + + return rc; + +} // get_port_mac_addr_check + + + +/*HDR*/ +/** + * @brief Check the link state of a network interface + * + * @param if_name Name of the interface + * + * @return 1 link detected on port + * 0 no link detected on port + * one of the ::MBG_LU_CODES in case of an error + */ +int check_port_link( const char *if_name ) +{ + #if defined( MBG_TGT_LINUX ) + struct ifreq ifr = { { { 0 } } }; + struct ethtool_value edata = { 0 }; + int rc; + + edata.cmd = ETHTOOL_GLINK; // defined in ethtool.h + ifr.ifr_data = (caddr_t) &edata; + + rc = do_siocg_ioctl( if_name, SIOCETHTOOL, &ifr ); + + if ( rc == MBG_LU_SUCCESS ) + rc = edata.data != 0; + + return rc; + + #else + + return MBG_LU_ERR_NSUPP; + + #endif + +} // check_port_link + + + +static /*HDR*/ +/** + * @brief Retrieve some IPv4 address like info from a network interface + * + * @param if_name Name of the interface + * @param p_addr Pointer to address field to be filled up + * @param sigioc_code the ioctl code associated to the address + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + */ +int get_specific_port_ip4_addr( const char *if_name, IP4_ADDR *p_addr, int sigioc_code ) +{ + int rc = MBG_LU_ERR_NSUPP; + + #if defined( MBG_TGT_LINUX ) + struct ifreq ifr = { { { 0 } } }; + + rc = do_siocg_ioctl( if_name, sigioc_code, &ifr ); + + if ( rc != MBG_LU_SUCCESS ) + goto fail; + + *p_addr = ntohl( ( (struct sockaddr_in *) &ifr.ifr_addr )->sin_addr.s_addr ); + + return rc; + +fail: + #endif + + *p_addr = 0; // make empty address + + return rc; + +} // get_specific_port_ip4_addr + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 address of a network interface + * + * @param if_name Name of the interface + * @param p_addr Pointer to address field to be filled up + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ +int get_port_ip4_addr( const char *if_name, IP4_ADDR *p_addr ) +{ + return get_specific_port_ip4_addr( if_name, p_addr, SIOCGIFADDR ); + +} // get_port_ip4_addr + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 net mask of a network interface + * + * @param if_name Name of the interface + * @param p_addr Pointer to address field to be filled up + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ +int get_port_ip4_netmask( const char *if_name, IP4_ADDR *p_addr ) +{ + return get_specific_port_ip4_addr( if_name, p_addr, SIOCGIFNETMASK ); + +} // get_port_ip4_netmask + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 broadcast address of a network interface + * + * @param if_name Name of the interface + * @param p_addr Pointer to address field to be filled up + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ +int get_port_ip4_broad_addr( const char *if_name, IP4_ADDR *p_addr ) +{ + return get_specific_port_ip4_addr( if_name, p_addr, SIOCGIFBRDADDR ); + +} // get_port_ip4_broad_addr + + + +#if defined( MBG_TGT_LINUX ) + +static /*HDR*/ +/** + * @brief Read a requested message from the netlink socket + */ +int readNlSock( int sockFd, char *bufPtr, size_t buf_size, int seqNum, int pId ) +{ + struct nlmsghdr *nlHdr; + int readLen = 0; + int msgLen = 0; + + do + { + // receive response from the kernel, can be several chunks + if ( ( readLen = recv( sockFd, bufPtr, buf_size - msgLen, 0 ) ) < 0 ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Failed to receive netlink packet: %s", + __func__, strerror( errno ) ); + #endif + return -1; + } + + nlHdr = (struct nlmsghdr *) bufPtr; + + // check if the header is valid + if ( ( NLMSG_OK( nlHdr, readLen ) == 0 ) || ( nlHdr->nlmsg_type == NLMSG_ERROR ) ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Invalid header in received netlink packet", + __func__ ); + #endif + return -1; + } + + // check if the its the last message + if ( nlHdr->nlmsg_type == NLMSG_DONE ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Reached last message in received packet", + __func__ ); + #endif + break; + } + + // move the pointer to buffer appropriately + bufPtr += readLen; + msgLen += readLen; + + // check if its a multi part message + if ( ( nlHdr->nlmsg_flags & NLM_F_MULTI ) == 0 ) + { + // return if it's not a multi part message + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Received packet is not a multi part message", + __func__ ); + #endif + break; + } + + } while ( ( nlHdr->nlmsg_seq != seqNum ) || ( nlHdr->nlmsg_pid != pId ) ); + + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Received packet has len %i", + __func__, msgLen ); + #endif + + return msgLen; + +} // readNlSock + + + +#if DEBUG_NETLINK + +static /*HDR*/ +void log_netlink_bytes( const char *fnc, const char *info, const void *p, int n_bytes ) +{ + char ws[80]; + int n = 0; + int i; + + for ( i = 0; i < n_bytes; i++ ) + n += snprintf( &ws[n], sizeof( ws ) - n, " %i", BYTE_OF( *p, i ) ); + + mbglog( LOG_INFO, "%s: attibute %s, copying %i bytes:%s", + fnc, info, n_bytes, ws ); + +} // log_netlink_bytes + +#endif + + + +static /*HDR*/ +int parseRoutes( struct nlmsghdr *nlHdr, struct route_info *rtInfo ) +{ + // parse the route info returned + struct rtmsg *rtMsg; + struct rtattr *rtAttr; + int rtLen; + + rtMsg = (struct rtmsg *) NLMSG_DATA( nlHdr ); + + // If the route is not for AF_INET then return. + // This could be also IPv6 routes. + if ( rtMsg->rtm_family != AF_INET ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Route is not AF_INET (%li), but %li", + __func__, (long) AF_INET, (long) rtMsg->rtm_family ); + #endif + return -1; + } + + // If the route does not belong to main routing table then return. + if ( rtMsg->rtm_table != RT_TABLE_MAIN ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Route does not belong to main table (%li), but %li", + __func__, (long) RT_TABLE_MAIN, (long) rtMsg->rtm_table ); + #endif + return -1; + } + + + // get the rtattr field + rtAttr = (struct rtattr *) RTM_RTA( rtMsg ); + rtLen = RTM_PAYLOAD( nlHdr ); + + for ( ; RTA_OK( rtAttr, rtLen ); rtAttr = RTA_NEXT( rtAttr, rtLen ) ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "rtAttr at %p, %i bytes left", rtAttr, rtLen ); + #endif + + switch ( rtAttr->rta_type ) + { + case RTA_OIF: + if_indextoname( *(int *)RTA_DATA( rtAttr ), rtInfo->ifName ); + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: attibute RTA_OIF, IF name: %s", + __func__, rtInfo->ifName ); + #endif + break; + + case RTA_GATEWAY: + memcpy( &rtInfo->gateWay, RTA_DATA( rtAttr ), sizeof( rtInfo->gateWay ) ); + #if DEBUG_NETLINK + log_netlink_bytes( __func__, "RTA_GATEWAY", &rtInfo->gateWay, sizeof( rtInfo->gateWay ) ); + #endif + break; + + case RTA_PREFSRC: + memcpy( &rtInfo->srcAddr , RTA_DATA( rtAttr ), sizeof( rtInfo->srcAddr ) ); + #if DEBUG_NETLINK + log_netlink_bytes( __func__, "RTA_PREFSRC", &rtInfo->srcAddr, sizeof( rtInfo->srcAddr ) ); + #endif + break; + + case RTA_DST: + memcpy( &rtInfo->dstAddr, RTA_DATA( rtAttr ), sizeof( rtInfo->dstAddr ) ); + #if DEBUG_NETLINK + log_netlink_bytes( __func__, "RTA_DST", &rtInfo->dstAddr, sizeof( rtInfo->dstAddr ) ); + #endif + break; + + #if DEBUG_NETLINK + case RTA_TABLE: + { + // The RTA_TABLE attribute was added to the kernel source in 2006 to support + // more than 255 routing tables. Originally the number of the routing table + // to which an entry belongs had been passed only in struct rtmsg::rtm_table, + // which is only 8 bits wide and should still hold the 8 LSBs of the full + // routing table number for compatibility, so this should still work for the + // standard routing tables, including the main table we are inspecting here. + // + // Whether this can be compiled in depends on the version of linux/rtnetlink.h + // used by the compiler. Unfortunately RTA_TABLE is part of an enum, so you + // can't simply use #ifdef RTA_TABLE to include this code conditionally. + uint32_t rta_table; + memcpy( &rta_table, RTA_DATA( rtAttr ), sizeof( rta_table ) ); + mbglog( LOG_ERR, "%s: attibute RTA_TABLE %i (%i)", + __func__, rta_table, rtMsg->rtm_table ); + } + break; + + default: + mbglog( LOG_ERR, "%s: Found unknown route type %li", + __func__, (long) rtAttr->rta_type ); + #endif + } + } + + return 0; + +} // parseRoutes + +#endif // defined( MBG_TGT_LINUX ) + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 gateway (default route) + * + * @param p_addr Pointer to address field to be filled up + * + * @return one of the ::MBG_LU_CODES + */ +int get_ip4_gateway( IP4_ADDR *p_addr ) +{ + int ret_val = MBG_LU_ERR_NOT_SET; + +#if defined( MBG_TGT_LINUX ) + struct nlmsghdr *nlMsg; + struct route_info route_info; + char msgBuf[8192]; // pretty large buffer + + int sock; + int len; + int msgSeq = 0; + int idx; + + // create socket + if ( ( sock = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE ) ) < 0 ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Failed to create netlink socket: %s", + __func__, strerror( errno ) ); + #endif + ret_val = MBG_LU_ERR_SOCKET; + goto out; + } + + + // initialize the buffer + memset( msgBuf, 0, sizeof( msgBuf ) ); + + // point the header and the msg structure pointers into the buffer + nlMsg = (struct nlmsghdr *) msgBuf; + + // fill in the nlmsg header + nlMsg->nlmsg_len = NLMSG_LENGTH( sizeof( struct rtmsg ) ); // length of message + nlMsg->nlmsg_type = RTM_GETROUTE; // get the routes from kernel routing table + + nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // the message is a request for dump + nlMsg->nlmsg_seq = msgSeq++; // sequence of the message packet + nlMsg->nlmsg_pid = getpid(); // PID of process sending the request + + // send the request + if ( send( sock, nlMsg, nlMsg->nlmsg_len, 0 ) < 0 ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Failed to write to netlink socket: %s", + __func__, strerror( errno ) ); + #endif + ret_val = -1; + goto out; + } + + // read the response + if ( ( len = readNlSock( sock, msgBuf, sizeof( msgBuf ), msgSeq, getpid() ) ) < 0 ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Failed to read from netlink socket", + __func__ ); + #endif + ret_val = -1; + goto out; + } + + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Read %i bytes from netlink socket", __func__ ); + #endif + + // parse and print the response + for ( idx = 0; NLMSG_OK( nlMsg, len ); nlMsg = NLMSG_NEXT( nlMsg, len ), idx ++ ) + { + memset( &route_info, 0, sizeof( route_info ) ); + + #if DEBUG_NETLINK + mbglog( LOG_ERR, "\nnlMsg at %p, %i bytes left", nlMsg, len ); + #endif + + + if ( parseRoutes( nlMsg, &route_info ) < 0 ) + continue; // don't check route_info if it has not been set up + + #if DEBUG_NETLINK + { + char ws[100]; + int l = sizeof( ws ); + int n = 0; + + // inet_ntoa() uses a static buffer which is overwritten on every call + n += snprintf( &ws[n], l - n, "src %s", (char *) inet_ntoa( route_info.srcAddr ) ); + n += snprintf( &ws[n], l - n, ", dst %s", (char *) inet_ntoa( route_info.dstAddr ) ); + n += snprintf( &ws[n], l - n, ", gw %s", (char *) inet_ntoa( route_info.gateWay ) ); + + mbglog( LOG_ERR, "%s: route %i: %s, if \"%s\"", + __func__, idx, ws, route_info.ifName ); + } + #endif + + // check if default IPv4 gateway + if ( strstr( (char *) inet_ntoa( route_info.dstAddr ), "0.0.0.0" ) ) + { + *p_addr = ntohl( route_info.gateWay.s_addr ); + ret_val = MBG_LU_SUCCESS; + // Actually we could stop searching now. However, in case of debug + // we'll continue to examine the rest of the routing message. + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Default gateway found: %s", + __func__, (char *) inet_ntoa( route_info.gateWay ) ); + #else + break; + #endif + } + } + +out: + if ( sock >= 0 ) + close( sock ); + +#endif // defined( MBG_TGT_LINUX ) + + + if ( ret_val != MBG_LU_SUCCESS ) + *p_addr = 0; + + return ret_val; + +} // get_ip4_gateway + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 address of a network interface as string + * + * @param if_name Name of the interface + * @param p_addr_buf Pointer to the string buffer to be filled up + * @param buf_size size of the string buffer + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ +int get_port_ip4_addr_str( const char *if_name, char *p_addr_buf, int buf_size ) +{ + IP4_ADDR addr; + + int rc = get_port_ip4_addr( if_name, &addr ); + + snprint_ip4_addr( p_addr_buf, buf_size, &addr, NULL ); + + return rc; + +} // get_port_ip4_addr_str + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 net mask of a network interface as string + * + * @param if_name Name of the interface + * @param p_addr_buf Pointer to the string buffer to be filled up + * @param buf_size size of the string buffer + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ +int get_port_ip4_netmask_str( const char *if_name, char *p_addr_buf, int buf_size ) +{ + IP4_ADDR addr; + + int rc = get_port_ip4_netmask( if_name, &addr ); + + snprint_ip4_addr( p_addr_buf, buf_size, &addr, NULL ); + + return rc; + +} // get_port_ip4_netmask_str + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 broadcast address of a network interface as string + * + * @param if_name Name of the interface + * @param p_addr_buf Pointer to the string buffer to be filled up + * @param buf_size size of the string buffer + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_specific_port_ip4_addr + */ +int get_port_ip4_broad_addr_str( const char *if_name, char *p_addr_buf, int buf_size ) +{ + IP4_ADDR addr; + + int rc = get_port_ip4_broad_addr( if_name, &addr ); + + snprint_ip4_addr( p_addr_buf, buf_size, &addr, NULL ); + + return rc; + +} // get_port_ip4_broad_addr_str + + + +/*HDR*/ +/** + * @brief Retrieve the current IPv4 settings of a network interface + * + * @param if_name Name of the interface + * @param p Pointer to a IP4_SETTINGS structure to be filled up + * + * @return 0 on success, < 0 on error + * + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ +int get_port_ip4_settings( const char *if_name, IP4_SETTINGS *p ) +{ + int link_up; + int ret_val = 0; + + memset( p, 0, sizeof( *p ) ); + + if ( get_port_ip4_addr( if_name, &p->ip_addr ) ) + ret_val = -1; + + if ( get_port_ip4_netmask( if_name, &p->netmask ) ) + ret_val = -1; + + if ( get_port_ip4_broad_addr( if_name, &p->broad_addr ) ) + ret_val = -1; + + if ( get_ip4_gateway( &p->gateway ) ) + ret_val = -1; + + + link_up = check_port_link( if_name ); + + if ( link_up ) + p->flags |= IP4_MSK_LINK; + +#if 0 //##+++++ + // We could also try to check VLAN and DHCP settings here, + // but as of now, this is specific to an application. + + // ##++++ The VLAN and DHCP status info collected below + // just return what has been configured previously by this program, + // however, it does not reflect any changes which have been made + // manually, e.g. via the command line. + if ( vlan_enabled ) + { + p->flags |= IP4_MSK_VLAN; + p->vlan_cfg = vlan_cfg; + } + + if ( dhcp_enabled ) + p->flags |= IP4_MSK_DHCP; +#endif + + return ret_val; + +} // get_port_ip4_settings + + diff --git a/mbglib/common/lan_util.h b/mbglib/common/lan_util.h new file mode 100644 index 0000000..d3e39a5 --- /dev/null +++ b/mbglib/common/lan_util.h @@ -0,0 +1,579 @@ + +/************************************************************************** + * + * $Id: lan_util.h 1.4 2013/02/19 15:15:53Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for lan_util.c. + * + * ----------------------------------------------------------------------- + * $Log: lan_util.h $ + * Revision 1.4 2013/02/19 15:15:53Z martin + * Added some inline functions. + * Redefined return codes as named enum. + * Updated function prototypes. + * Revision 1.3 2012/10/02 18:24:29 martin + * Added some macros to simpliy conversion to string. + * Revision 1.2 2012/03/09 08:51:44 martin + * Updated function prototypes. + * Revision 1.1 2011/03/04 10:01:32 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _LAN_UTIL_H +#define _LAN_UTIL_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> +#include <gpsdefs.h> + +#include <stdlib.h> + +#if defined( MBG_TGT_UNIX ) + #include <sys/types.h> + #include <sys/socket.h> + #include <net/if.h> +#else + // A dummy declaration to prevent from warnings due to usage + // of this type with function prototypes. + struct ifreq + { + int dummy; + }; +#endif + + +#if defined( IFHWADDRLEN ) // usually defined in net/if.h + #if ( IFHWADDRLEN != 6 ) + #error Warning: IFHWADDRLEN is not 6! + #endif +#endif + + + +#ifdef _LAN_UTIL + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +#if !defined( MAC_SEP_CHAR ) + #define MAC_SEP_CHAR ':' // character used to separate octets of a MAC ID +#endif + +#if !defined( MAC_SEP_CHAR_ALT ) + #define MAC_SEP_CHAR_ALT '-' // alternate character +#endif + + +/** + * @brief Return codes for the LAN utility functions + */ +enum MBG_LU_CODES +{ + MBG_LU_SUCCESS = 0, ///< success + MBG_LU_ERR_NSUPP = -1, ///< function not supported + MBG_LU_ERR_PORT_NAME = -2, ///< port name exceeds max length + MBG_LU_ERR_SOCKET = -3, ///< failed to open socket + MBG_LU_ERR_IOCTL = -4, ///< IOCTL call failed + MBG_LU_ERR_NOT_SET = -5, ///< octets are all 0 + MBG_LU_ERR_BUFF_SZ = -6, ///< buffer size too small + MBG_LU_ERR_FMT = -7, ///< parameter format not correct + MBG_LU_ERR_RANGE = -8 ///< range for some parameter exceeded +}; + + +#define MAX_IP4_BITS ( 8 * sizeof( IP4_ADDR ) ) + +#define IP4_MSB_MASK ( 1UL << ( MAX_IP4_BITS - 1 ) ) + +#define MIN_IP4_CIDR_NETMASK_BITS 0 +#define MAX_IP4_CIDR_NETMASK_BITS MAX_IP4_BITS + + + +/** + * @brief Compute an IP4 net mask according to the number of CIDR netmask bits + * + * E.g. the 24 bits mentioned in "172.16.3.250/24" result in 0xFFFFFF00, + * corresponding to 255.255.255.0 in dotted quad notation. + * + * @param netmask_bits Number of netmask bits from CIDR notation + * + * @return The IP4 net mask + * + * @see get_ip4_net_mask_bits() + */ +static __mbg_inline +IP4_ADDR ip4_net_mask_from_cidr( int netmask_bits ) +{ + return (IP4_ADDR) ~( ( 1UL << ( MAX_IP4_BITS - netmask_bits ) ) - 1 ); + +} // ip4_net_mask_from_cidr + + + +/** + * @brief Determine the broadcast address for an IP4 address plus net mask + * + * E.g. IP 0xAC1003FA, net mask 0xFFFFFF00 yields broadcast addr 0xAC1003FF. + * In dotted quad notation, IP 172.16.3.250 with net mask 255.255.255.0 + * result in broadcast address 172.16.3.255. + * + * @param p_addr The full IP4 address + * @param p_mask The IP4 net mask + * + * @return The determined IP4 broadcast address + */ +static __mbg_inline +IP4_ADDR ip4_broad_addr_from_addr( const IP4_ADDR *p_addr, const IP4_ADDR *p_mask ) +{ + return *p_addr | ~(*p_mask); + +} // ip4_broad_addr_from_addr + + + +/** + * @brief Determine the network part of an IP4 address based on the net mask + * + * E.g. IP 0xAC1003FA, net mask 0xFFFFFF00 yields network part 0xAC100300. + * In dotted quad notation, IP 172.16.3.250 with net mask 255.255.255.0 + * results in network part 172.16.3.0. + * + * @param p_addr The full IP4 address + * @param p_mask The IP4 net mask + * + * @return The network part of the IP4 address + */ +static __mbg_inline +IP4_ADDR ip4_net_part_from_addr( const IP4_ADDR *p_addr, const IP4_ADDR *p_mask ) +{ + return *p_addr & *p_mask; + +} // ip4_net_part_from_addr + + + +/** + * @brief Check if two IP4 addresses have the same network part. + * + * @param p_addr1 The first IP4 address to check + * @param p_addr2 The second IP4 address to check + * @param p_mask The IP4 net mask + * + * @return true, if the network parts are matching + */ +static __mbg_inline +int ip4_net_part_matches( const IP4_ADDR *p_addr1, const IP4_ADDR *p_addr2, + const IP4_ADDR *p_mask ) +{ + return ip4_net_part_from_addr( p_addr1, p_mask ) + == ip4_net_part_from_addr( p_addr2, p_mask ); + +} // ip4_net_part_matches + + + +#define _ip4_addr_to_str( _s, _a ) \ + snprint_ip4_addr( _s, sizeof( _s ), _a, NULL ) + +#define _mac_addr_to_str( _s, _a ) \ + snprint_mac_addr( _s, sizeof( _s ), _a ) + + + +/* function prototypes: */ + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + * @brief Count the number of sequential bits set starting from MSB + * + * E.g. for 0xC0 and 0xC1 the results are both 2 since only + * the 2 MSBs are sequentially set. + * + * @param p_mask The IP4 net mask + * + * @return The number of sequential MSB bits set in val + * + * @see ip4_net_mask_from_cidr + */ + int get_ip4_net_mask_bits( const IP4_ADDR *p_mask ) ; + + /** + * @brief Print an IPv4 address to a dotted quad format string. + * + * @param s The string buffer into which to print + * @param max_len Maximum length of the string, i.e. size of the buffer + * @param p_addr The IPv4 address + * @param info An optional string which is prepended to the string, or NULL + * + * @return The overall number of characters printed to the string + * + * @see snprint_ip4_cidr_addr + * @see str_to_ip4_addr + * @see cidr_str_to_ip4_addr_and_net_mask + */ + int snprint_ip4_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, const char *info ) ; + + /** + * @brief Print an IPv4 address plus net mask to string in CIDR notation. + * + * The printed CIDR string is something like "172.16.3.250/24" + * + * @param s The string buffer into which to print + * @param max_len Maximum length of the string, i.e. size of the buffer + * @param p_addr The IPv4 address + * @param p_mask The IPv4 net mask + * @param info An optional string which is prepended to the string, or NULL + * + * @return The overall number of characters printed to the string + * + * @see snprint_ip4_addr + * @see str_to_ip4_addr + * @see cidr_str_to_ip4_addr_and_net_mask + */ + int snprint_ip4_cidr_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, const IP4_ADDR *p_mask, const char *info ) ; + + /** + * @brief Convert a string to an IP4_ADDR. + * + * @param p_addr Pointer to the IP4_ADDR variable, or NULL, in which case this + * function can be used to check if the string is formally correct. + * @param s The string to be converted + * + * @return >= 0 on success, number of characters evaluated from the input string + * -1 if invalid number found in string + * -2 if separator is not a dot '.' + * + * @see snprint_ip4_addr + * @see snprint_ip4_cidr_addr + * @see cidr_str_to_ip4_addr_and_net_mask + */ + int str_to_ip4_addr( IP4_ADDR *p_addr, const char *s ) ; + + /** + * @brief Convert a string in CIDR notation to an IP4_ADDR and net mask. + * + * @param p_addr Pointer to an IP4_ADDR variable for the IP4 address, + * or NULL, in which case this function can be used + * to check if the string is formally correct. + * @param p_mask Pointer to an IP4_ADDR variable for the net mask, + * or NULL, in which case this function can be used + * to check if the string is formally correct. + * @param cidr_str The string to be converted, in CIDR format, e.g. "172.16.3.250/24" + * + * @return >= 0 on success, number of characters evaluated from the input string + * one of the ::MBG_LU_CODES on error + * + * @see snprint_ip4_addr + * @see snprint_ip4_cidr_addr + * @see str_to_ip4_addr + */ + int cidr_str_to_ip4_addr_and_net_mask( IP4_ADDR *p_addr, IP4_ADDR *p_mask, const char *cidr_str ) ; + + /** + * @brief Print a MAC ID or similar array of octets to a string. + * + * @param s The string buffer into which to print + * @param max_len Maximum length of the string, i.e. size of the buffer + * @param octets An array of octets + * @param num_octets The number of octets to be printed from the array + * @param sep The separator printed between the bytes, or 0 + * @param info An optional string which is prepended to the output, or NULL + * + * @return The overall number of characters printed to the string + * + * @see snprint_mac_addr + * @see str_to_octets + * @see check_octets_not_all_zero + */ + int snprint_octets( char *s, size_t max_len, const uint8_t *octets, int num_octets, char sep, const char *info ) ; + + /** + * @brief Print a MAC address to a string. + * + * @param s The string buffer into which to print + * @param max_len Maximum length of the string, i.e. size of the buffer + * @param p_mac_addr The MAC address to be printed + * + * @return The overall number of characters printed to the string + * + * @see snprint_octets + * @see str_to_octets + * @see check_octets_not_all_zero + */ + int snprint_mac_addr( char *s, size_t max_len, const MBG_MAC_ADDR *p_mac_addr ) ; + + /** + * @brief Set a MAC ID or a similar array of octets from a string. + * + * @param octets An array of octets to be set up + * @param num_octets The number of octets which can be stored + * @param s The string to be converted + * + * @return The overall number of octets decoded from the string + * + * @see snprint_octets + * @see snprint_mac_addr + * @see check_octets_not_all_zero + */ + int str_to_octets( uint8_t *octets, int num_octets, const char *s ) ; + + /** + * @brief Check if an array of octets is valid, i.e. != 0 + * + * @param octets Pointer to the array of octets + * @param num_octets Number of octets + * + * @return MBG_LU_SUCCESS octets are valid, i.e. not all 0 + * MBG_LU_ERR_NOT_SET octets are invalid, i.e. all 0 + * + * @see snprint_octets + * @see snprint_mac_addr + * @see str_to_octets + */ + int check_octets_not_all_zero( const uint8_t *octets, int num_octets ) ; + + /** + * @brief Check if an array of octets is valid, i.e. != 0 + * + * @param p_addr Pointer to a MAC address + * + * @return MBG_LU_SUCCESS MAC address is valid, i.e. not all 0 + * MBG_LU_ERR_NOT_SET MAC address is invalid, i.e. all 0 + * + * @see check_octets_not_all_zero + */ + int check_mac_addr_not_all_zero( const MBG_MAC_ADDR *p_addr ) ; + + /** + * @brief Do a SIOCGxxx IOCTL call to read specific information from a LAN interface + * + * @param if_name Name of the interface + * @param ioctl_code One of the predefined system SIOCGxxx IOCTL codes + * @param p_ifreq Pointer to a request buffer + * + * @return one of the ::MBG_LU_CODES + */ + int do_siocg_ioctl( const char *if_name, int ioctl_code, struct ifreq *p_ifreq ) ; + + /** + * @brief Retrieve the MAC address of a network interface + * + * @param if_name Name of the interface + * @param p_mac_addr Pointer to the MAC address buffer to be filled up + * + * @return one of the ::MBG_LU_CODES + * on error the MAC addr is set to all 0 + * + * @see get_port_mac_addr_check + */ + int get_port_mac_addr( const char *if_name, MBG_MAC_ADDR *p_mac_addr ) ; + + /** + * @brief Retrieve and check the MAC address of a network interface + * + * @param if_name Name of the interface + * @param p_mac_addr Pointer to the MAC address buffer to be filled up + * + * @return one of the ::MBG_LU_CODES + * on error the MAC addr is set to all 0 + * + * @see get_port_mac_addr + */ + int get_port_mac_addr_check( const char *if_name, MBG_MAC_ADDR *p_mac_addr ) ; + + /** + * @brief Check the link state of a network interface + * + * @param if_name Name of the interface + * + * @return 1 link detected on port + * 0 no link detected on port + * one of the ::MBG_LU_CODES in case of an error + */ + int check_port_link( const char *if_name ) ; + + /** + * @brief Retrieve the IPv4 address of a network interface + * + * @param if_name Name of the interface + * @param p_addr Pointer to address field to be filled up + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ + int get_port_ip4_addr( const char *if_name, IP4_ADDR *p_addr ) ; + + /** + * @brief Retrieve the IPv4 net mask of a network interface + * + * @param if_name Name of the interface + * @param p_addr Pointer to address field to be filled up + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ + int get_port_ip4_netmask( const char *if_name, IP4_ADDR *p_addr ) ; + + /** + * @brief Retrieve the IPv4 broadcast address of a network interface + * + * @param if_name Name of the interface + * @param p_addr Pointer to address field to be filled up + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ + int get_port_ip4_broad_addr( const char *if_name, IP4_ADDR *p_addr ) ; + + /** + * @brief Retrieve the IPv4 gateway (default route) + * + * @param p_addr Pointer to address field to be filled up + * + * @return one of the ::MBG_LU_CODES + */ + int get_ip4_gateway( IP4_ADDR *p_addr ) ; + + /** + * @brief Retrieve the IPv4 address of a network interface as string + * + * @param if_name Name of the interface + * @param p_addr_buf Pointer to the string buffer to be filled up + * @param buf_size size of the string buffer + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ + int get_port_ip4_addr_str( const char *if_name, char *p_addr_buf, int buf_size ) ; + + /** + * @brief Retrieve the IPv4 net mask of a network interface as string + * + * @param if_name Name of the interface + * @param p_addr_buf Pointer to the string buffer to be filled up + * @param buf_size size of the string buffer + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ + int get_port_ip4_netmask_str( const char *if_name, char *p_addr_buf, int buf_size ) ; + + /** + * @brief Retrieve the IPv4 broadcast address of a network interface as string + * + * @param if_name Name of the interface + * @param p_addr_buf Pointer to the string buffer to be filled up + * @param buf_size size of the string buffer + * + * @return one of the ::MBG_LU_CODES + * + * @see get_port_ip4_settings + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_specific_port_ip4_addr + */ + int get_port_ip4_broad_addr_str( const char *if_name, char *p_addr_buf, int buf_size ) ; + + /** + * @brief Retrieve the current IPv4 settings of a network interface + * + * @param if_name Name of the interface + * @param p Pointer to a IP4_SETTINGS structure to be filled up + * + * @return 0 on success, < 0 on error + * + * @see get_port_ip4_addr + * @see get_port_ip4_addr_str + * @see get_port_ip4_netmask + * @see get_port_ip4_netmask_str + * @see get_port_ip4_broad_addr + * @see get_port_ip4_broad_addr_str + * @see get_specific_port_ip4_addr + */ + int get_port_ip4_settings( const char *if_name, IP4_SETTINGS *p ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + + +#undef _ext +#undef _DO_INIT + +#endif /* _LAN_UTIL_H */ + diff --git a/mbglib/common/mbg_arch.h b/mbglib/common/mbg_arch.h new file mode 100644 index 0000000..4bc92fd --- /dev/null +++ b/mbglib/common/mbg_arch.h @@ -0,0 +1,167 @@ + +/************************************************************************** + * + * $Id: mbg_arch.h 1.4 2012/10/02 18:32:00Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions to support different computer hardware architectures. + * + * ----------------------------------------------------------------------- + * $Log: mbg_arch.h $ + * Revision 1.4 2012/10/02 18:32:00Z martin + * Include words.h and, conditionally, stdlib.h. + * Use generic preprocessor symbol MBG_TGT_KERNEL. + * Revision 1.3 2009/06/12 13:12:37Z martin + * Fixed compiler warning. + * Revision 1.2 2009/03/19 15:14:15 martin + * Fixed byte swapping of doubles for SPARC architecture. + * Revision 1.1 2008/12/05 13:47:42 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBG_ARCH_H +#define _MBG_ARCH_H + +#include <mbg_tgt.h> +#include <words.h> + +#if !defined( MBG_TGT_KERNEL ) + #include <stdlib.h> +#endif + + +#if defined( MBG_ARCH_SPARC ) + #define MBG_ARCH_BIG_ENDIAN 1 +#endif + + +#if !defined( MBG_ARCH_BIG_ENDIAN ) + #define MBG_ARCH_LITTLE_ENDIAN 1 +#endif + + + +#if defined( MBG_TGT_LINUX ) + + #include <asm/byteorder.h> + + #if defined( MBG_TGT_KERNEL ) + #include <asm/unaligned.h> + + #define _mbg_put_unaligned( _v, _p ) put_unaligned( _v, _p ) + #define _mbg_get_unaligned( _p ) get_unaligned( _p ) + #endif + +#endif + + + +// If no macros required to access unaligned data have yet been defined, +// define some default macros assuming no special handling is required +// to access unaligned data. + +#if !defined( _mbg_put_unaligned ) + #define _mbg_put_unaligned( _v, _p ) ((void)( *(_p) = (_v) )) +#endif + +#if !defined( _mbg_get_unaligned ) + #define _mbg_get_unaligned( _p ) (*(_p)) +#endif + + + +// If no macros to convert endianess have yet been defined, define +// some default macros assuming endianess conversion is not required. + +#if !defined( __le16_to_cpu ) + #define __le16_to_cpu( _x ) (_x) +#endif + +#if !defined( __le32_to_cpu ) + #define __le32_to_cpu( _x ) (_x) +#endif + +#if !defined( __le64_to_cpu ) + #define __le64_to_cpu( _x ) (_x) +#endif + +#if !defined( __cpu_to_le16 ) + #define __cpu_to_le16( _x ) (_x) +#endif + +#if !defined( __cpu_to_le32 ) + #define __cpu_to_le32( _x ) (_x) +#endif + +#if !defined( __cpu_to_le64 ) + #define __cpu_to_le64( _x ) (_x) +#endif + + + +// The macros below are used to convert the endianess +// of the plug-in cards to the endianess of the host CPU + +#define _mbg8_to_cpu( _x ) ( _x ) +#define _mbg16_to_cpu( _x ) __le16_to_cpu( _x ) +#define _mbg32_to_cpu( _x ) __le32_to_cpu( _x ) +#define _mbg64_to_cpu( _x ) __le64_to_cpu( _x ) + +#define _cpu_to_mbg8( _x ) ( _x ) +#define _cpu_to_mbg16( _x ) __cpu_to_le16( _x ) +#define _cpu_to_mbg32( _x ) __cpu_to_le32( _x ) +#define _cpu_to_mbg64( _x ) __cpu_to_le64( _x ) + + + +// swap a double type variable bytewise e.g. to convert the endianess + +static __mbg_inline +void mbg_swab_double( double *p ) +{ +#if 0 // The __swab64() may not work correctly for whatever reason ... + __swab64p( p ); +#else // ... so we do the swapping manually + double d = 0; + size_t i; + + for ( i = 0; i < sizeof( double); i++ ) + BYTE_OF( d, i ) = BYTE_OF( *p, ( sizeof( double) - 1 - i ) ); + + for ( i = 0; i < sizeof( double); i++ ) + BYTE_OF( *p, i ) = BYTE_OF( d, i ); +#endif + +} // mbg_swab_double + + + +#if defined( MBG_ARCH_BIG_ENDIAN ) + + #define _mbg_swab16( _p ) *(_p) = __swab16( *(_p) ) + #define _mbg_swab32( _p ) *(_p) = __swab32( *(_p) ) + + #define _mbg_swab_double( _p ) mbg_swab_double( _p ) + + #define _mbg_swab_doubles( _p, _n ) \ + { \ + int i; \ + for ( i = 0; i < (_n); i++ ) \ + _mbg_swab_double( &_p[i] ); \ + } + +#else + + #define _mbg_swab16( _p ) _nop_macro_fnc() + #define _mbg_swab32( _p ) _nop_macro_fnc() + + #define _mbg_swab_double( _p ) _nop_macro_fnc() + + #define _mbg_swab_doubles( _p, _n ) _nop_macro_fnc() + +#endif + +#endif /* _MBG_ARCH_H */ diff --git a/mbglib/common/mbg_tgt.h b/mbglib/common/mbg_tgt.h new file mode 100644 index 0000000..7970e57 --- /dev/null +++ b/mbglib/common/mbg_tgt.h @@ -0,0 +1,566 @@ + +/************************************************************************** + * + * $Id: mbg_tgt.h 1.29 2013/02/01 14:50:46Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Check the build environment and setup control definitions + * for the Meinberg library modules. + * + * ----------------------------------------------------------------------- + * $Log: mbg_tgt.h $ + * Revision 1.29 2013/02/01 14:50:46Z martin + * Fixed a typo which caused an error under Borland CBuilder 5. + * Revision 1.28 2012/12/12 10:03:16Z martin + * Fix for Borland C 3.1. + * Revision 1.27 2012/11/29 12:03:14Z martin + * Moved definition of _no_macro_fnc() to words.h. + * Revision 1.26 2012/11/02 09:01:47Z martin + * Merged some stuff depending on the build environment here + * and cleaned up. + * Revision 1.25 2012/04/04 07:17:18 martin + * Treat QNX Neutrino as Unix target. + * Revision 1.24 2011/08/23 10:21:23 martin + * New symbol _NO_MBG_API_ATTR which can be used with functions + * which are going to be exported by a DLL, but actually aren't, yet. + * Revision 1.23 2011/08/19 10:47:00 martin + * Don't include stddef.h. + * Distinguish between different gcc target platforms. + * Initial support for IA64 platform. + * Support wchar_t for BSD. + * Defined _NO_USE_PACK_INTF for Sparc and IA64. + * Fixed typo in comment. + * Revision 1.22 2009/10/01 08:20:50 martin + * Fixed inline code support with different BC versions. + * Revision 1.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 + * Added definition for MBG_TGT_UNIX. + * Minor syntax fixes. + * Revision 1.6 2006/01/25 14:37:06 martin + * Added definitions for 64 bit Windows environments. + * Revision 1.5 2003/12/17 16:11:41Z martin + * Split API modifiers into _MBG_API and _MBG_API_ATTR. + * Revision 1.4 2003/06/19 08:20:22Z martin + * Added WINAPI attribute for DLL exported functions. + * Revision 1.3 2003/04/09 13:37:20Z martin + * Added definition for _MBG_API. + * Revision 1.2 2003/02/24 16:08:45Z martin + * Don't setup for Win32 PNP if explicitely configured non-PNP. + * Revision 1.1 2002/02/19 13:46:20Z MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _MBG_TGT_H +#define _MBG_TGT_H + + +/* Other headers to be included */ + +#ifdef _MBG_TGT + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _CVI_ ) + + #define MBG_TGT_CVI + + #if defined( _NI_mswin_ ) + #define MBG_TGT_WIN32 + #else + #error Unsupported CVI target platform. + #endif + +#elif defined( _WIN32_WINNT ) + + // MS platform SDK + // WinNT 4.0 and above + #define MBG_TGT_WIN32 + + #if ( _WIN32_WINNT >= 0x0500 ) + // Win2k and above + #if !defined( MBG_TGT_WIN32_NON_PNP ) + // only if not explicitely disabled + #define MBG_TGT_WIN32_PNP + #endif + #endif + +#elif defined( WINVER ) + + // MS platform SDK + // Win95, WinNT 4.0 and above + #define MBG_TGT_WIN32 + + #if ( WINVER >= 0x0500 ) + // Win98, Win2k and above + // #define ... + #endif + +#elif defined( __WIN32__ ) + + // Borland C++ Builder + #define MBG_TGT_WIN32 + +#elif defined( _WIN32 ) + + // 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 + #define MBG_TGT_NETWARE + +#elif defined( __OS2__ ) + + // Watcom C/C++ for target OS/2 + #define MBG_TGT_OS2 + +#elif defined( __linux ) + + // GCC for target Linux + #define MBG_TGT_LINUX + #define _GNU_SOURCE 1 + + #if defined( __KERNEL__ ) + #define MBG_TGT_KERNEL + #endif + +#elif defined( __FreeBSD__ ) + + // GCC for target FreeBSD + #define MBG_TGT_FREEBSD + +#elif defined( __NetBSD__ ) + + // GCC for target NetBSD + #define MBG_TGT_NETBSD + +#elif defined( __OpenBSD__ ) + + // GCC for target OpenBSD + #define MBG_TGT_OPENBSD + +#elif defined( __QNX__ ) + + // any compiler for target QNX + #define MBG_TGT_QNX + + #if defined( __QNXNTO__ ) + // target QNX Neutrino + #define MBG_TGT_QNX_NTO + #endif + +#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 + + + +#if defined( MBG_TGT_FREEBSD ) \ + || defined( MBG_TGT_NETBSD ) \ + || defined( MBG_TGT_OPENBSD ) + #define MBG_TGT_BSD + + #if defined( _KERNEL ) + #define MBG_TGT_KERNEL + #endif + +#endif + +#if defined( MBG_TGT_LINUX ) \ + || defined( MBG_TGT_BSD ) + #define MBG_TGT_UNIX +#endif + + + +// Some definitions depending on the build environment ... + +#if defined( __GNUC__ ) + + #if defined( __i386__ ) + + #define MBG_ARCH_I386 + #define MBG_ARCH_X86 + + #elif defined( __x86_64__ ) + + #define MBG_ARCH_X86_64 + #define MBG_ARCH_X86 + + #elif defined( __ia64__ ) + + #define MBG_ARCH_IA64 + + #define _NO_USE_PACK_INTF + + #elif defined( __sparc__ ) + + #define MBG_ARCH_SPARC + #define MBG_USE_MM_IO_FOR_PCI 1 + + #define _NO_USE_PACK_INTF + + #elif defined( __arm__ ) + + #define MBG_ARCH_ARM + + #endif + + #if defined( MBG_TGT_LINUX ) + + #if defined( __KERNEL__ ) + #include <linux/types.h> + #else + #include <sys/types.h> + #include <stdint.h> + #include <stdbool.h> + #endif + + #elif defined( MBG_TGT_BSD ) + + #include <sys/types.h> + + #elif defined( MBG_TGT_QNX_NTO ) // QNX 6.x (Neutrino) + + #include <stdint.h> + #include <stdbool.h> + + #else + + #include <stdint.h> + #include <stdbool.h> + + #endif + + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + + #define MBG_TGT_HAS_WCHAR_T 1 + + #define __mbg_inline __inline__ + +#elif defined( _MSC_VER ) + + // Known predifined MS compiler version codes: + // 1700: MSVC++ 11.0 (Visual Studio 2012) + // 1600: MSVC++ 10.0 (Visual Studio 2010) + // 1500: MSVC++ 9.0 (Visual Studio 2008) + // 1400: MSVC++ 8.0 (Visual Studio 2005) + // 1310: MSVC++ 7.1 (Visual Studio 2003) + // 1300: MSVC++ 7.0 + // 1200: MSVC++ 6.0 + // 1100: MSVC++ 5.0 + + #if ( _MSC_VER >= 1600 ) + #include <stdint.h> + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #else + #define MBG_TGT_HAS_INT_8_16_32 1 + #endif + + // no bool support anyway + #define MBG_TGT_MISSING_BOOL_TYPE 1 + + #define MBG_TGT_HAS_WCHAR_T 1 + + #define __mbg_inline __forceinline + +#elif defined( _CVI_ ) + + // 1000 for CVI v10.0 (CVI 2010) + // 911 for CVI v9.1.1 (CVI 2009 SP1) + // 910 for CVI v9.1 (CVI 2009) + // 310 for CVI v3.1 + // 301 for CVI v3.0.1 + // 1 for CVI v3.0 + + #if ( _CVI_ >= 910 ) + // LabWindows/CVI 2009 is the first version providing stdint.h. + #include <stdint.h> + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #else + #define USE_LONG_FOR_INT32 1 + #endif + + // As of LabWindows/CVI 2010, stdbool.h is still missing. + #define MBG_TGT_MISSING_BOOL_TYPE 1 + + #define MBG_TGT_HAS_WCHAR_T 0 + + // Inline code is not supported, though the inline keyword + // is silently accepted since CVI v9.0 + +#elif defined( __BORLANDC__ ) + + // 0x0570 Borland Developer Studio 2006 + // 0x0550 Borland C/C++ 5.5 (C++ Builder 5.0) + // 0x0410 Borland C/C++ 3.1 + // 0x0400 Borland C/C++ 3.0 + // 0x0200 Borland C/C++ 2.0 + + #if ( __BORLANDC__ >= 0x570 ) + // at least Borland Developer Studio 2006 supports C99 + #include <stdint.h> + #include <stdbool.h> + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #elif ( __BORLANDC__ >= 0x0550 ) + #define MBG_TGT_HAS_INT_8_16_32 1 + #define MBG_TGT_MISSING_BOOL_TYPE 1 + #else // e.g. BC 3.1 or earlier + #if ( __BORLANDC__ <= 0x410 ) + #define MBG_TGT_MISSING_64_BIT_TYPES 1 + #define MBG_TGT_MISSING_BOOL_TYPE 1 + #define USE_LONG_FOR_INT32 1 + #endif + #endif + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + + #if defined( __cplusplus ) + #define __mbg_inline inline // standard C++ syntax + #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 + +#elif defined( __WATCOMC__ ) + + // 1050 v10.5 + // 1100 v11.0 + // 1200 Open Watcom C++ v1.0 + // 1230 Open Watcom C++ v1.3 + // 1270 Open Watcom C++ v1.7 + + #if defined( MBG_TGT_QNX ) // QNX 4.x + + #include <sys/types.h> + + #define MBG_TGT_MISSING_64_BIT_TYPES 1 + + #elif ( __WATCOMC__ > 1230 ) // Open Watcom C 1.3 and above + + #include <stdint.h> + + #elif !defined( __WATCOM_INT64__ ) // Watcom C 11 + + #define MBG_TGT_MISSING_64_BIT_TYPES 1 + + #endif + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + + #define __mbg_inline _inline + +#endif + + + +#if defined( MBG_TGT_WIN32 ) + + #if defined( _AMD64_ ) + // This is used for AMD64 architecture and for + // Intel XEON CPUs with 64 bit extension. + #define MBG_TGT_WIN32_PNP_X64 + #define WIN32_FLAVOR "x64" + #elif defined( _IA64_ ) + #define MBG_TGT_WIN32_PNP_IA64 + #define WIN32_FLAVOR "ia64" + #endif + + #if defined( _KDD_ ) + #define MBG_TGT_KERNEL + #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 ) + #define _MBG_API_ATTR __declspec( dllexport ) + #else + #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 + + 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_API_ATTR ) + #define _MBG_API_ATTR +#endif + +#if !defined( _NO_MBG_API_ATTR ) + #define _NO_MBG_API_ATTR +#endif + +#if !defined( MBG_INVALID_PORT_HANDLE ) + #define MBG_INVALID_PORT_HANDLE MBG_INVALID_HANDLE +#endif + +#if !defined( MBG_USE_MM_IO_FOR_PCI ) + #define MBG_USE_MM_IO_FOR_PCI 0 +#endif + + +// The macros below are defined in order to be able to check if +// certain C language extensions are available on the target system: +#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199409L ) + #define MBG_TGT_C94 1 +#else + #define MBG_TGT_C94 0 +#endif + + +#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) + #define MBG_TGT_C99 1 +#else + #define MBG_TGT_C99 0 +#endif + +// Check if wchar_t is supported +#if !defined( MBG_TGT_HAS_WCHAR_T ) + #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 */ + +#undef _ext + + +/* 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 + + +#endif /* _MBG_TGT_H */ diff --git a/mbglib/common/mbgdevio.h b/mbglib/common/mbgdevio.h new file mode 100644 index 0000000..40aeba5 --- /dev/null +++ b/mbglib/common/mbgdevio.h @@ -0,0 +1,3939 @@ + +/************************************************************************** + * + * $Id: mbgdevio.h 1.40 2012/10/02 18:40:30Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes used with Meinberg device driver I/O. + * + * ----------------------------------------------------------------------- + * $Log: mbgdevio.h $ + * Revision 1.40 2012/10/02 18:40:30Z martin + * There are some g++ versions which fail to compile source code using + * the macros provided by Linux to define IOCTL codes. If only the API + * functions are called by an application then the IOCTL codes aren't + * required anyway, so we just avoid inclusion of mbgioctl.h. + * Updated doxygen comments. + * Updated function prototypes. + * Support on-board event logs. + * Fixed a bug which caused a crash when generic I/O calls + * were used under Windows. + * Changes for QNX. + * Workaround to make mbgmon (BC) build under Windows. + * Cleaned up CPU set support under Linux. + * Moved some macros here so they can be used by other modules. + * Support reading CORR_INFO, and reading/writing TR_DISTANCE. + * Cleaned up handling of pragma pack(). + * Cleaned up inclusion of header files. + * Moved mutex definitions to new mbgmutex.h. + * Renamed mutex stuff to critical sections. + * Updated function prototypes to support PTP unicast configuration + * Made xhrt leap second check an inline function. + * Fixed macro to avoid compiler warning. + * Revision 1.39 2009/12/15 15:34:59Z daniel + * Support reading the raw IRIG data bits for firmware versions + * which support this feature. + * Revision 1.38.1.2 2009/12/10 09:58:53Z daniel + * Revision 1.38.1.1 2009/12/10 09:45:29Z daniel + * Revision 1.38 2009/09/29 15:06:26Z martin + * Updated function prototypes. + * Revision 1.37 2009/08/12 14:31:51 daniel + * New version code 306, compatibility version still 210. + * Revision 1.36 2009/06/19 12:20:31Z martin + * Updated function prototypes. + * Revision 1.35 2009/06/09 08:57:09 daniel + * New version code 305, compatibility version still 210. + * Revision 1.34 2009/06/08 18:20:14Z daniel + * Updated function prototypes. + * Fixes for ARM target. + * Revision 1.33 2009/03/19 15:36:26 martin + * New version code 304, compatibility version still 210. + * Moved some inline functions dealing with MBG_PC_CYCLES + * from mbgdevio.h to pcpsdev.h. + * Include mbg_arch.h here. + * Removed unused doxygen comment. + * Updated function prototypes. + * Revision 1.32 2008/12/17 10:43:30Z martin + * New version code 303, compatibility version still 210. + * Increased MBG_MAX_DEVICES from 5 to 8. + * Added macros to read the time stamp counter (cycles), and + * added an inline rdtscll() call for user space Linux. + * Added some inline functions to deal with cycles and timestamps. + * Generic support for threads and process/thread affinity controlled + * by symbol MBGDEVIO_USE_THREAD_API. + * New preprocessor symbol MBGDEVIO_HAVE_THREAD_AFFINITY. + * Support extrapolated time stamps controlled + * by symbol MBGDEVIO_XHRT_API. + * Removed definition of MBG_TGT_SUPP_MMAP. + * Updated function prototypes and doxygen comments. + * Revision 1.31 2008/02/26 16:57:38Z martin + * Updated function prototypes and doxygen comments. + * Revision 1.30 2008/02/04 13:33:15Z martin + * New preprocessor symbol MBG_TGT_SUPP_MMAP. + * Revision 1.29 2008/01/31 08:55:39Z daniel + * Renamed functions related to mapped memory support + * Revision 1.28 2008/01/31 08:36:22Z martin + * Picked up changes from 1.24.1.1: + * Added default preprocessor symbol MBGDEVIO_SIMPLE. + * Revision 1.27 2008/01/17 15:56:37Z daniel + * New version code 302, compatibility version still 210. + * Added structure MBG_MAPPED_MEM_INFO. + * Updated function prototypes. + * Revision 1.26 2007/10/16 10:11:42Z daniel + * New version code 301, compatibility version still 210. + * Revision 1.25 2007/09/26 14:10:34Z martin + * New version code 300, compatibility version still 210. + * Added MBG_MAX_DEVICES. + * Added enum SELECTION_MODE. + * Added structures MBG_DEVICE_LIST and MBG_DEVICE_NAME_LIST. + * Updated function prototypes. + * Revision 1.24 2007/03/22 10:14:16Z martin + * New version code 219, compatibility version still 210. + * Revision 1.23 2007/03/02 10:18:10Z martin + * Updated function prototypes due to renamed data structures. + * Use new definitions of generic handle types. + * Preliminary support for *BSD. + * Revision 1.22 2006/08/09 13:47:29 martin + * New version code 218, compatibility version still 210. + * Revision 1.21 2006/06/08 12:30:22Z martin + * New version code 217, compatibility version still 210. + * Revision 1.20 2006/05/02 13:14:27Z martin + * New version code 216, compatibility version still 210. + * Updated function prototypes. + * Revision 1.19 2006/01/11 12:14:53Z martin + * New version code 215, compatibility version still 210. + * Revision 1.18 2005/12/15 09:38:39Z martin + * New version 214, compatibility version still 210. + * Revision 1.17 2005/06/02 11:54:40Z martin + * Updated function prototypes. + * Revision 1.16 2005/02/16 15:13:00Z martin + * New MBGDEVIO_VERSION 0x0212. + * Updated function prototypes. + * Revision 1.15 2005/01/14 10:22:44Z martin + * Updated function prototypes. + * Revision 1.14 2004/12/09 11:24:00Z martin + * Support configuration of on-board frequency synthesizer. + * Revision 1.13 2004/11/09 14:13:00Z martin + * Updated function prototypes. + * Revision 1.12 2004/08/17 11:13:46Z martin + * Account for renamed symbols. + * Revision 1.11 2004/04/14 09:34:23Z martin + * New definition MBGDEVIO_COMPAT_VERSION. + * Pack structures 1 byte aligned. + * Revision 1.10 2003/12/22 15:35:10Z martin + * New revision 2.03. + * Moved some definitions to pcpsdev.h. + * New structures to read device time together with associated + * PC high resolution timer cycles. + * Updated function prototypes. + * Revision 1.9 2003/06/19 08:50:05Z martin + * Definition of MBGDEVIO_VERSION number to allow DLL + * API version checking. + * Replaced some defines by typedefs. + * Renamed USE_DOS_TSR to MBG_USE_DOS_TSR. + * New preprocessor symbol MBG_USE_KERNEL_DRIVER which + * is defined only for targets which use IOCTLs. + * Don't include pcps_dos.h here. + * Updated function prototypes. + * Revision 1.8 2003/05/16 08:44:26 MARTIN + * Cleaned up inclusion of headers. + * Removed obsolete definitions. + * Changes for direct access targets. + * Revision 1.7 2003/04/25 10:16:00 martin + * Updated inclusion of headers. + * Made prototypes available for all targets. + * Revision 1.6 2003/04/15 19:38:05Z martin + * Updated function prototypes. + * Revision 1.5 2003/04/09 13:44:53Z martin + * Use new common IOCTL codes from mbgioctl.h. + * Updated function prototypes. + * Revision 1.4 2002/09/06 11:06:35Z martin + * Updated function prototypes for Win32 API.. + * Win32 compatibility macros to use old APIs with new functions. + * Support targets OS/2 and NetWare. + * Revision 1.3 2002/02/28 10:08:54Z MARTIN + * Syntax cleanup for Win32. + * Revision 1.2 2002/02/26 14:40:47 MARTIN + * Source code cleanup. + * Changes for DOS with and without TSR. + * Revision 1.1 2002/02/19 13:48:21 MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _MBGDEVIO_H +#define _MBGDEVIO_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> +#include <mbg_arch.h> +#include <mbgmutex.h> +#include <mbgerror.h> +#include <mbggeo.h> +#include <pcpsdev.h> +#include <pci_asic.h> +#include <use_pack.h> +#include <time.h> + + +#define MBGDEVIO_VERSION 0x0307 + +#define MBGDEVIO_COMPAT_VERSION 0x0210 + +#define MBG_MAX_DEVICES 8 + +#if defined( MBG_TGT_WIN32 ) + + #if !defined( MBGDEVIO_XHRT_API ) + #define MBGDEVIO_XHRT_API 1 + #endif + + #if !defined( MBGDEVIO_USE_THREAD_API ) + #define MBGDEVIO_USE_THREAD_API 1 + #endif + + #if !defined( MBGDEVIO_HAVE_THREAD_AFFINITY ) + #define MBGDEVIO_HAVE_THREAD_AFFINITY 1 + #endif + + #define MBG_USE_KERNEL_DRIVER 1 + #include <windows.h> + + #define MBGDEVIO_RET_VAL DWORD + #define _mbgdevio_cnv_ret_val( _v ) (_v) + +#elif defined( MBG_TGT_LINUX ) + + #if !defined( MBGDEVIO_XHRT_API ) + #define MBGDEVIO_XHRT_API 1 + #endif + + // Thread support under Linux depends strongly on + // the versions of some libraries, so the symbols + // MBGDEVIO_USE_THREAD_API and MBGDEVIO_HAVE_THREAD_AFFINITY + // should be set in the project's Makefile, depending on the + // target envionment. Otherwise thread support is disabled + // as per default. + + #define MBG_USE_KERNEL_DRIVER 1 + #include <sys/ioctl.h> + #include <fcntl.h> + #include <sched.h> + + #if MBGDEVIO_USE_THREAD_API + #include <pthread.h> + #endif + +#elif defined( MBG_TGT_BSD ) + + #define MBG_USE_KERNEL_DRIVER 1 + #include <sys/ioctl.h> + #include <fcntl.h> + +#elif defined( MBG_TGT_OS2 ) + + #define MBG_USE_KERNEL_DRIVER 1 + +#elif defined( MBG_TGT_QNX_NTO ) + + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> + + #include <pcpsdrvr.h> + +#elif defined( MBG_TGT_DOS ) + + #if !defined( MBG_USE_DOS_TSR ) + #define MBG_USE_DOS_TSR 1 + #endif + + #include <pcpsdrvr.h> + +#else // other target OSs which access the hardware directly + + #include <pcpsdrvr.h> + +#endif + + +#if defined( MBG_USE_KERNEL_DRIVER ) + + #include <stdlib.h> + #include <string.h> + +#endif + + +#if !defined( MBGDEVIO_XHRT_API ) + #define MBGDEVIO_XHRT_API 0 +#endif + +#if !defined( MBGDEVIO_USE_THREAD_API ) + #define MBGDEVIO_USE_THREAD_API 0 +#endif + +#if !defined( MBGDEVIO_HAVE_THREAD_AFFINITY ) + #define MBGDEVIO_HAVE_THREAD_AFFINITY 0 +#endif + +#ifdef _MBGDEVIO + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + + +// If MBGDEVIO_SIMPLE != 0 then some complex configuration +// API calls are excluded from build, which would otherwise +// require some additional mbglib modules to be linked +// to the application. +#if !defined( MBGDEVIO_SIMPLE ) + #define MBGDEVIO_SIMPLE 0 +#endif + + +#if defined( MBG_USE_KERNEL_DRIVER ) + + typedef MBG_HANDLE MBG_DEV_HANDLE; + + #define MBG_INVALID_DEV_HANDLE MBG_INVALID_HANDLE + +#else // other target OSs which access the hardware directly + + typedef PCPS_DDEV *MBG_DEV_HANDLE; + + #define MBG_INVALID_DEV_HANDLE NULL + +#endif + + +#if !defined( MBGDEVIO_RET_VAL ) + #define MBGDEVIO_RET_VAL int +#endif + + +#if !defined( _mbgdevio_cnv_ret_val ) + #define _mbgdevio_cnv_ret_val( _v ) \ + ( ( (_v) < 0 ) ? (_v) : MBG_SUCCESS ) +#endif + + +#define _mbgdevio_vars() \ + MBGDEVIO_RET_VAL rc + +#define _mbgdevio_ret_val \ + _mbgdevio_cnv_ret_val( rc ) + + + +/** + The type below is used to store a unique ID for a device which + is made up of the device model name and its serial number, i.e.: + Format: [model_name]_[serial_number], e.g. "GPS170PCI_028210040670" + */ +typedef char MBG_HW_NAME[PCPS_CLOCK_NAME_SZ + PCPS_SN_SIZE + 1]; + + + +#if defined( MBG_TGT_LINUX ) + + #define MBG_PROCESS_ID pid_t + #define _mbg_get_current_process() 0 + + #if defined( __cpu_set_t_defined ) + #define MBG_CPU_SET cpu_set_t + #define MBG_CPU_SET_SIZE CPU_SETSIZE + #define _mbg_cpu_clear( _ps ) CPU_ZERO( (_ps) ) + #define _mbg_cpu_set( _i, _ps ) CPU_SET( (_i), (_ps) ) + #define _mbg_cpu_isset( _i, _ps ) CPU_ISSET( (_i), (_ps) ) + #endif + + #if MBGDEVIO_USE_THREAD_API + #define MBG_THREAD_ID pthread_t + #define _mbg_get_current_thread() 0 + #define MBG_THREAD_FNC_ATTR // empty + #define MBG_THREAD_FNC_RET_VAL void * + #define _mbg_thread_exit( _v ) return (void *) (_v) + #endif + +#elif defined( MBG_TGT_WIN32 ) + + #define MBG_PROCESS_ID HANDLE + #define _mbg_get_current_process() GetCurrentProcess() + + #define MBG_CPU_SET DWORD_PTR // Attention: this is not used as pointer! + #define MBG_CPU_SET_SIZE ( sizeof( MBG_CPU_SET ) * 8 ) + + #define MBG_THREAD_ID HANDLE + #define _mbg_get_current_thread() GetCurrentThread() + #define MBG_THREAD_FNC_ATTR WINAPI + #define MBG_THREAD_FNC_RET_VAL DWORD + #define _mbg_thread_exit( _v ) ExitThread( _v ); return (_v) + +#endif // target specific + + +#if !defined( MBG_TGT_WIN32 ) + + #define FILETIME int // just a dummy to avoid build errors + +#endif + + +#if !defined( MBG_PROCESS_ID ) + #define MBG_PROCESS_ID int +#endif + +#if !defined( _mbg_get_current_process ) + #define _mbg_get_current_process() 0 +#endif + +#if !defined( MBG_CPU_SET ) + #define MBG_CPU_SET int +#endif + +#if !defined( MBG_CPU_SET_SIZE ) + #define MBG_CPU_SET_SIZE ( sizeof( MBG_CPU_SET ) * 8 ) +#endif + +#if !defined( _mbg_cpu_clear ) + #define _mbg_cpu_clear( _ps ) ( *(_ps) = 0 ) +#endif + +#if !defined( _mbg_cpu_set ) + #define _mbg_cpu_set( _i, _ps ) ( *(_ps) |= ( 1UL << (_i) ) ) +#endif + +#if !defined( _mbg_cpu_isset ) + #define _mbg_cpu_isset( _i, _ps ) ( *(_ps) & ( 1UL << (_i) ) ) +#endif + + +#if !defined( MBG_THREAD_ID ) + #define MBG_THREAD_ID int +#endif + +#if !defined( _mbg_get_current_thread ) + #define _mbg_get_current_thread() 0 +#endif + +#if !defined( MBG_THREAD_FNC_ATTR ) + #define MBG_THREAD_FNC_ATTR // empty +#endif + +#if !defined( MBG_THREAD_FNC_RET_VAL ) + #define MBG_THREAD_FNC_RET_VAL void +#endif + +#if !defined( _mbg_thread_exit ) + #define _mbg_thread_exit( _v ) _nop_macro_fnc() +#endif + + +typedef struct +{ + MBG_THREAD_ID thread_id; + #if defined( MBG_TGT_WIN32 ) + HANDLE exit_request; + #endif +} MBG_THREAD_INFO; + + + +typedef struct +{ + PCPS_HR_TIME_CYCLES htc; + uint64_t pcps_hr_tstamp64; +} MBG_XHRT_VARS; + + +typedef struct +{ + MBG_XHRT_VARS vars; + MBG_XHRT_VARS prv_vars; + MBG_PC_CYCLES_FREQUENCY freq_hz; + int ioctl_status; + int sleep_ms; + MBG_CRIT_SECT crit_sect; + MBG_DEV_HANDLE dh; +} MBG_XHRT_INFO; + + +typedef struct +{ + MBG_XHRT_INFO xhrt_info; + MBG_THREAD_INFO ti; +} MBG_POLL_THREAD_INFO; + + + +/** + Match modes to decide how to proceed if a certain + model type with certain serial number can not be found + */ +enum MBG_MATCH_MODE +{ + MBG_MATCH_ANY, /**< open the next available device on the system */ + MBG_MATCH_MODEL, /**< open the next available device on the system with the same clock type */ + MBG_MATCH_EXACTLY, /**< force opening exactly the requested device otherwise exit with failure */ + N_MBG_MATCH_MODE /**< number of known modes */ +}; + + + +typedef struct _MBG_DEVICE_LIST +{ + char *device_path; /**< Hardware ID depending on the calling function */ + struct _MBG_DEVICE_LIST *next; + +} MBG_DEVICE_LIST; + + + +typedef struct _MBG_DEVICENAME_LIST +{ + char device_name[40]; /**< readable name */ + struct _MBG_DEVICENAME_LIST *next; + +} MBG_DEVICENAME_LIST; + + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + Get the version number of the precompiled DLL/shared object library. + + If this library is used as a DLL/shared object library then the version + number can be checked to see if the header files which are actually used + to build an application are compatible with the header files which have + been used to build the library, and thus the API function are called + in the correct way. + + @return the version number + + @see mbgdevio_check_version() + @see ::MBGDEVIO_VERSION defined in mbgdevio.h + */ + _MBG_API_ATTR int _MBG_API mbgdevio_get_version( void ) ; + + /** + @brief Check if the DLL/shared library is compatible with a given version. + + If this library is used as a DLL/shared object library then the version + number can be checked to see if the header files which are actually used + to build an application are compatible with the header files which have + been used to build the library, and thus the API function are called + in the correct way. + + @param header_version Version number to be checked, should be ::MBGDEVIO_VERSION + from the mbgdevio.h file used to build the application + + @return ::MBG_SUCCESS if compatible, ::MBG_ERR_LIB_NOT_COMPATIBLE if not. + + @see mbgdevio_get_version() + @see ::MBGDEVIO_VERSION defined in mbgdevio.h + */ + _MBG_API_ATTR int _MBG_API mbgdevio_check_version( int header_version ) ; + + /** + @brief Open a device by index, starting from 0. + + This function is <b>out of date</b>, mbg_open_device_by_name() + should be used instead. + + See the <b>note</b> for mbg_find_device() for details. + + @param device_index index of the device, use 0 for the first device. + */ + _MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device( unsigned int device_index ) ; + + /** + @brief Get the number of supported devices installed on the computer. + + This function is <b>out of date</b>, mbg_find_devices_with_names() + should be used instead. + + <b>Note:</b> This function is out of date since it may not work + correctly for Meinberg devices which are disconnected and reconnected + while the system is running (e.g. USB devices). However, the function + will be kept for compatibility reasons and works correctly if all + Meinberg devices are connected at system boot and are not disconnected + and reconnected during operation + + @return The number of devices found + + @see mbg_find_devices_with_names() + */ + _MBG_API_ATTR int _MBG_API mbg_find_devices( void ) ; + + /** + @brief Allocate memory and set up a list of installed and supported devices. + + This function should be used preferably instead of mbg_find_devices(). + + @param device_list Pointer to a linked list of type ::MBG_DEVICENAME_LIST + with device names. The list will be allocated by this + function and has to be freed after usage by calling + mbg_free_device_name_list(). + @param max_devices Maximum number of devices the function should look for + (can not exceed ::MBG_MAX_DEVICES). + + @return number of present devices + + @see ::MBG_HW_NAME for the format of the unique names + @see mbg_free_device_name_list() + @see mbg_find_devices() + */ + _MBG_API_ATTR int _MBG_API mbg_find_devices_with_names( MBG_DEVICENAME_LIST **device_list, int max_devices ) ; + + /** + @brief Free the memory allocated for a ::MBG_DEVICENAME_LIST. + + The list may have been set up and allocated before + by mbg_find_devices_with_names(). + + @param *list Linked list of type ::MBG_DEVICENAME_LIST + + @see mbg_find_devices_with_names() + */ + _MBG_API_ATTR void _MBG_API mbg_free_device_name_list( MBG_DEVICENAME_LIST *list) ; + + /** + @brief Return a handle to a device with a certain unique name. + + The names of the devices that are installed on the system can be retrieved by + the function mbg_find_devices_with_names(). + + This function should be used preferably instead of mbg_open_device(). + + @param hw_name String with the unique name of the device to be opened + @param selection_mode One of the enum values of ::MBG_MATCH_MODE + + @return On success, the function returns a handle to the device, otherwise ::MBG_INVALID_DEV_HANDLE + + @see ::MBG_HW_NAME for the format of the unique names. + @see ::MBG_MATCH_MODE + @see mbg_find_devices_with_names() + */ + _MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_name( const char* hw_name, int selection_mode ) //##++++ +; + + /** + @brief Close a handle to a device and set the handle value to ::MBG_INVALID_DEV_HANDLE. + + @param dev_handle Handle to a Meinberg device. + */ + _MBG_API_ATTR void _MBG_API mbg_close_device( MBG_DEV_HANDLE *dev_handle ) ; + + /** + @brief Read information about the driver handling a given device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_DRVR_INFO structure which is filled up. + + @return ::MBG_SUCCESS or error code returned by device I/O control function + */ + _MBG_API_ATTR int _MBG_API mbg_get_drvr_info( MBG_DEV_HANDLE dh, PCPS_DRVR_INFO *p ) ; + + /** + @brief Read detailed device information. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_DEV structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function + */ + _MBG_API_ATTR int _MBG_API mbg_get_device_info( MBG_DEV_HANDLE dh, PCPS_DEV *p ) ; + + /** + @brief Read the current state of the on-board ::PCPS_STATUS_PORT. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_STATUS_PORT value to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function + + @see \ref group_status_port "bitmask" + */ + _MBG_API_ATTR int _MBG_API mbg_get_status_port( MBG_DEV_HANDLE dh, PCPS_STATUS_PORT *p ) ; + + /* (Intentionally excluded from Doxygen) + Generic read function which writes a command code to a device + and reads a number of replied data to a generic buffer. + + <b>Warning</b>: This is for debugging purposes only! + The specialized API calls should be used preferably. + A specific device may not support any command code. + + @param dh Valid handle to a Meinberg device + @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device + @param *p Pointer to a buffer to be filled up + @param size Size of the buffer *p + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_generic_write() + @see mbg_generic_read_gps() + @see mbg_generic_write_gps() + @see mbg_generic_io() + */ + _MBG_API_ATTR int _MBG_API mbg_generic_read( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) ; + + /* (Intentionally excluded from Doxygen) + Generic read function which writes a GPS command code to a device + and reads a number of replied data to a generic buffer. + The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() + check whether this call is supported by a device. + + <b>Warning</b>: This is for debugging purposes only! + The specialized API calls should be used preferably. + A specific device may not support any GPS command code. + + @param dh Valid handle to a Meinberg device + @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device. + @param *p Pointer to a buffer to be filled up + @param size Size of the buffer *p + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_gps_data() + @see mbg_generic_write_gps() + @see mbg_generic_read() + @see mbg_generic_write() + @see mbg_generic_io() + */ + _MBG_API_ATTR int _MBG_API mbg_generic_read_gps( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) ; + + /* (Intentionally excluded from Doxygen) + Generic write function which writes a command code plus an + associated number of data bytes to a device. + + <b>Warning</b>: This is for debugging purposes only! + The specialized API calls should be used preferably. + A specific device may not support any command code. + + @param dh Valid handle to a Meinberg device + @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device. + @param *p Pointer to a buffer to be written + @param size Size of the buffer *p + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_generic_read() + @see mbg_generic_read_gps() + @see mbg_generic_write_gps() + @see mbg_generic_io() + */ + _MBG_API_ATTR int _MBG_API mbg_generic_write( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) ; + + /* (Intentionally excluded from Doxygen) + Generic write function which writes a GPS command code plus an + associated number of data bytes to a device. + The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() + check whether this call is supported by a device. + + <b>Warning</b>: This is for debugging purposes only! + The specialized API calls should be used preferably. + A specific device may not support any GPS command code. + + @param dh Valid handle to a Meinberg device + @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device. + @param *p Pointer to a buffer to be written + @param size Size of the buffer *p + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_gps_data() + @see mbg_generic_read_gps() + @see mbg_generic_read() + @see mbg_generic_write() + @see mbg_generic_io() + */ + _MBG_API_ATTR int _MBG_API mbg_generic_write_gps( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) ; + + /* (Intentionally excluded from Doxygen) + Write and/or read generic data to/from a device. + The macro _pcps_has_generic_io() or the API call mbg_dev_has_generic_io() + check whether this call is supported by a device. + + <b>Warning</b>: This call is for debugging purposes and internal use only! + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_generic_io() + @see mbg_generic_read() + @see mbg_generic_write() + @see mbg_generic_read_gps() + @see mbg_generic_write_gps() + */ + _MBG_API_ATTR int _MBG_API mbg_generic_io( MBG_DEV_HANDLE dh, int type, const void *in_p, int in_sz, void *out_p, int out_sz ) ; + + /** + @brief Read a ::PCPS_TIME structure returning the current date/time/status. + + The returned time is local time according to the card's time zone setting, + with a resolution of 10 ms (i.e. 10ths of seconds). + + This call is supported by any device manufactured by Meinberg. + However, for higher accuracy and resolution the mbg_get_hr_time..() or + mbg_get_fast_hr_timestamp..() group of calls should be used preferably + if supported by the device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TIME structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_hr_time() + @see mbg_set_time() + @see mbg_get_sync_time() + */ + _MBG_API_ATTR int _MBG_API mbg_get_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ; + + /** + @brief Set the device's on-board clock to a given date and time. + + The macro _pcps_can_set_time() checks whether this call + is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_STIME structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_time() + */ + _MBG_API_ATTR int _MBG_API mbg_set_time( MBG_DEV_HANDLE dh, const PCPS_STIME *p ) ; + + /** + @brief Read the time when the device has last recently synchronized. + + Fills a ::PCPS_TIME structure with the date/time/status reporting + when the device was synchronized the last time to its time source, + e.g. the DCF77 signal, the GPS satellites, or similar. + The macro _pcps_has_sync_time() or the API call mbg_dev_has_sync_time() + check whether this call is supported by a device. + + The macro _pcps_has_sync_time() checks whether this call + is supported by a device. + + <b>Note:</b> If that information is not available on the board then + the value of the returned ::PCPS_TIME::sec field is set to 0xFF. + The macro _pcps_time_is_read() can be used to check whether the + returned information is valid, or not available. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TIME structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_time() + */ + _MBG_API_ATTR int _MBG_API mbg_get_sync_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ; + + /** + @brief Wait until the next second change, then return current time. + + Returns time in a ::PCPS_TIME structure similar to mbg_get_time(). + + <b>Note:</b> This API call is supported under Windows only. + The call blocks until the kernel driver detects a second change + reported by the device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TIME structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_time() + */ + _MBG_API_ATTR int _MBG_API mbg_get_time_sec_change( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ; + + /** + @brief Read the card's current time with high resolution, plus status. + + Fills up a ::PCPS_HR_TIME (High Resolution time) structure containing + the current %UTC time (seconds since 1970), %UTC offset, and status. + The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() + check whether this call is supported by a device. + + <b>Note:</b> This API call provides a higher accuracy and resolution + than mbg_get_time(). However, it does not account for the latency + which is introduced when accessing the board. + The mbg_get_hr_time_cycles() and mbg_get_hr_time_comp() calls + provide ways to account for and/or compensate the latency. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_hr_time() + @see mbg_get_time() + @see mbg_get_hr_time_cycles() + @see mbg_get_hr_time_comp() + */ + _MBG_API_ATTR int _MBG_API mbg_get_hr_time( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) ; + + /* (Intentionally excluded from Doxygen ) + Write a high resolution time stamp ::PCPS_TIME_STAMP to a device + to configure a %UTC time when the clock shall generate an event. + The macro _pcps_has_event_time() or the API call mbg_dev_has_event_time() + check whether this call is supported by a device. + + <b>Note:</b> This is only supported by some special firmware. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TIME_STAMP structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_event_time() + */ + _MBG_API_ATTR int _MBG_API mbg_set_event_time( MBG_DEV_HANDLE dh, const PCPS_TIME_STAMP *p ) ; + + /** + @brief Read the serial port configuration from an old type of device. + + <b>Note:</b> Direct usage of this function is obsolete. + + The generic API function mbg_get_serial_settings() should be used instead + which fully supports the capabilities of current devices. + + The macro _pcps_has_serial() checks whether this call + is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_SERIAL structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see \ref group_cmd_bytes + @see mbg_get_serial_settings() + */ + _MBG_API_ATTR int _MBG_API mbg_get_serial( MBG_DEV_HANDLE dh, PCPS_SERIAL *p ) ; + + /** + @brief Write the serial port configuration to an old type of device. + + <b>Note:</b> Direct usage of this function is obsolete. + + The generic API function mbg_save_serial_settings() should be used instead + which fully supports the capabilities of current devices. + + The macro _pcps_has_serial() checks whether this call + is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_SERIAL structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see \ref group_cmd_bytes + @see mbg_save_serial_settings() + */ + _MBG_API_ATTR int _MBG_API mbg_set_serial( MBG_DEV_HANDLE dh, const PCPS_SERIAL *p ) ; + + /** + @brief Read time zone/daylight saving configuration code from a device. + + The APIs using TZCODE are only supported by some simpler cards + and allow just a very basic configuration. + + The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode() + check whether this call is supported by a device. + + Other cards may support the mbg_get_pcps_tzdl() or mbg_get_gps_tzdl() + calls instead which allow for a more detailed configuration of the + time zone and daylight saving settings. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TZCODE structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_tzcode() + @see mbg_set_tzcode() + @see mbg_get_pcps_tzdl() + @see mbg_get_gps_tzdl() + @see \ref group_cmd_bytes + */ + _MBG_API_ATTR int _MBG_API mbg_get_tzcode( MBG_DEV_HANDLE dh, PCPS_TZCODE *p ) ; + + /** + @brief Write time zone/daylight saving configuration code to a device. + + The APIs using TZCODE are only supported by some simpler cards + and allow just a very basic configuration. + + The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode() + check whether this call is supported by a device. + + Other cards may support the mbg_set_pcps_tzdl() or mbg_set_gps_tzdl() + calls instead which allow for a more detailed configuration of the + time zone and daylight saving settings. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TZCODE structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_tzcode() + @see mbg_get_tzcode() + @see mbg_set_pcps_tzdl() + @see mbg_set_gps_tzdl() + @see \ref group_cmd_bytes + */ + _MBG_API_ATTR int _MBG_API mbg_set_tzcode( MBG_DEV_HANDLE dh, const PCPS_TZCODE *p ) ; + + /** + @brief Read time zone/daylight saving parameters from a device. + + This function fills up a ::PCPS_TZDL structure which supports a more + detailed configuration of time zone and daylight saving than the TZCODE + structure. + + The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl() + check whether this call is supported by a device. + + Other cards may support the mbg_get_tzcode() or mbg_get_gps_tzdl() + calls instead. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TZDL structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_pcps_tzdl() + @see mbg_set_pcps_tzdl() + @see mbg_get_tzcode() + @see mbg_get_gps_tzdl() + @see \ref group_cmd_bytes + */ + _MBG_API_ATTR int _MBG_API mbg_get_pcps_tzdl( MBG_DEV_HANDLE dh, PCPS_TZDL *p ) ; + + /** + @brief Write time zone/daylight saving parameters to a device. + + This function passes a ::PCPS_TZDL structure to a device which supports + a more detailed configuration of time zone and daylight saving than the + TZCODE structure. + + The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl() + check whether this call is supported by a device. + Other cards may support the mbg_set_tzcode() or mbg_set_gps_tzdl() + calls instead. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TZDL structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_pcps_tzdl() + @see mbg_get_pcps_tzdl() + @see mbg_set_tzcode() + @see mbg_set_gps_tzdl() + @see \ref group_cmd_bytes + */ + _MBG_API_ATTR int _MBG_API mbg_set_pcps_tzdl( MBG_DEV_HANDLE dh, const PCPS_TZDL *p ) ; + + /** + @brief Read the %UTC offset configuration of the reference time from a device. + + This parameter is used to specify the %UTC offset of an incoming + reference time signal if a kind of time signal e.g. an IRIG input + signal) does not provide this information. + + The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_REF_OFFS value to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_ref_offs() + @see mbg_set_ref_offs() + @see ::PCPS_GET_REF_OFFS + */ + _MBG_API_ATTR int _MBG_API mbg_get_ref_offs( MBG_DEV_HANDLE dh, MBG_REF_OFFS *p ) ; + + /** + @brief Write the %UTC offset configuration of the reference time to a device. + + This parameter is used to specify the %UTC offset of an incoming + reference time signal if a kind of time signal e.g. an IRIG input + signal) does not provide this information. + + The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_REF_OFFS value to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_ref_offs() + @see mbg_get_ref_offs() + @see ::PCPS_SET_REF_OFFS + */ + _MBG_API_ATTR int _MBG_API mbg_set_ref_offs( MBG_DEV_HANDLE dh, const MBG_REF_OFFS *p ) ; + + /** + @brief Read a ::MBG_OPT_INFO structure containing optional settings, controlled by flags. + + The ::MBG_OPT_INFO structure contains a mask of supported flags plus the current + settings of those flags. + The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_OPT_INFO structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_opt_flags() + @see mbg_set_opt_settings() + */ + _MBG_API_ATTR int _MBG_API mbg_get_opt_info( MBG_DEV_HANDLE dh, MBG_OPT_INFO *p ) ; + + /** + @brief Write a ::MBG_OPT_SETTINGS structure containing optional device settings. + + The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags() + check whether this call is supported by a device. + The ::MBG_OPT_INFO structure should be read first to check which of the specified + flag is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_OPT_SETTINGS structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_opt_flags() + @see mbg_get_opt_info() + */ + _MBG_API_ATTR int _MBG_API mbg_set_opt_settings( MBG_DEV_HANDLE dh, const MBG_OPT_SETTINGS *p ) ; + + /** + @brief Read the current IRIG input settings plus the supported settings. + + Calling this function directly is usually obsolete. The function + mbg_get_all_irig_rx_info() should be used instead which also reads some + other associated parameters affecting the behaviour of the IRIG input. + + The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an ::IRIG_INFO structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_all_irig_rx_info() + @see mbg_set_irig_rx_settings() + @see mbg_dev_is_irig_rx() + @see mbg_dev_has_irig_tx() + @see mbg_dev_has_irig() + @see \ref group_icode + */ + _MBG_API_ATTR int _MBG_API mbg_get_irig_rx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) ; + + /** + @brief Write an ::IRIG_SETTINGS structure to a device to configure an IRIG input. + + Calling this function directly is usually obsolete. The function + mbg_set_all_irig_rx_info() should be used instead which also writes some + other associated parameters affecting the behaviour of the IRIG input. + + The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx() + check whether this call is supported by a device. + The ::IRIG_INFO structure should be read first to determine the possible + settings supported by this card's IRIG input. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::IRIG_SETTINGS structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_set_all_irig_rx_info() + @see mbg_get_irig_rx_info() + @see mbg_dev_is_irig_rx() + @see mbg_dev_has_irig_tx() + @see mbg_dev_has_irig() + @see \ref group_icode + */ + _MBG_API_ATTR int _MBG_API mbg_set_irig_rx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) ; + + /** + @brief Read all IRIG input configuration information from a device. + + @param dh Valid handle to a Meinberg device + @param pdev Pointer to the device's ::PCPS_DEV structure + @param p_irig_info Pointer to a ::IRIG_SETTINGS structure to be written + @param p_ref_offs Pointer to a ::MBG_REF_OFFS structure to be written + @param p_opt_info Pointer to a ::MBG_OPT_SETTINGS structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_save_all_irig_rx_settings() + @see mbg_set_irig_rx_settings() + @see mbg_set_ref_offs() + @see mbg_set_opt_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_all_irig_rx_info( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, IRIG_INFO *p_irig_info, MBG_REF_OFFS *p_ref_offs, MBG_OPT_INFO *p_opt_info ) ; + + /** + @brief Write all IRIG input configuration settings to a device. + + The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx() + check whether this call is supported by a device. + The ::IRIG_INFO structure should be read first to determine the possible + settings supported by this card's IRIG input. + + @param dh Valid handle to a Meinberg device + @param pdev Pointer to the device's ::PCPS_DEV structure + @param p_irig_settings Pointer to a ::IRIG_SETTINGS structure to be written + @param p_ref_offs Pointer to a ::MBG_REF_OFFS structure to be written + @param p_opt_settings Pointer to a ::MBG_OPT_SETTINGS structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_all_irig_rx_info() + @see mbg_set_irig_rx_settings() + @see mbg_set_ref_offs() + @see mbg_set_opt_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_save_all_irig_rx_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, const IRIG_SETTINGS *p_irig_settings, const MBG_REF_OFFS *p_ref_offs, const MBG_OPT_SETTINGS *p_opt_settings ) ; + + /** + @brief Check if a device supports the mbg_get_irig_ctrl_bits() call. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_irig_ctrl_bits() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_ctrl_bits( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read the control function bits received from an incoming IRIG signal. + + This function fills a ::MBG_IRIG_CTRL_BITS structure with the control function + bits decoded from the incoming IRIG signal. + + The meaning of these bits depends on the type of IRIG code frame format. + + In some IRIG formats these bits provide some well-known information which can + also be evaluated by the device. For example, in IEEE 1344 or IEEE C37.118 code + the control function bits are used to provide the year number, UTC offset, + DST status, leap second warning, etc. + + For most IRIG code formats, however, these bits are reserved, i.e. not used + at all, or application defined, depending on the configuration of the IRIG + generator providing the IRIG signal. + + In the latter case the application has to evaluate the received control function + bits and can use this function to retrieve these bits from the receiver device. + + The macro _pcps_has_irig_ctrl_bits() or the API call mbg_dev_has_irig_ctrl_bits() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_IRIG_CTRL_BITS type to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_irig_ctrl_bits() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_irig_ctrl_bits( MBG_DEV_HANDLE dh, MBG_IRIG_CTRL_BITS *p ) ; + + /** + @brief Check if a device supports the mbg_get_raw_irig_data() call. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_raw_irig_data() + @see mbg_get_raw_irig_data_on_sec_change() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_raw_irig_data( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read raw IRIG data from an IRIG receiver. + + This function fills a ::MBG_RAW_IRIG_DATA structure with the raw data bits received + from the incoming IRIG signal. This enables an application itself to decode the + information provided by the IRIG signal. + + The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_raw_irig_data() + @see mbg_get_raw_irig_data_on_sec_change() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) ; + + /** + @brief Wait for second changeover then read raw IRIG data from an IRIG receiver. + + This function waits until the second of the device's on-board time rolls over, and + then reads the last recent raw IRIG data from the device. + + The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data() + check whether this call is supported by a device. + + <b>Note:</b> The mbg_get_time_sec_change() function called by this function is + supported under Windows only, so this function can also only be used under Windows. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_raw_irig_data() + @see mbg_get_raw_irig_data() + @see mbg_get_time_sec_change() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data_on_sec_change( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) ; + + /** + @brief Check if a device supports the mbg_get_irig_time() call. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_irig_time() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_time( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read the IRIG time and day-of-year number from an IRIG receiver. + + Fills up a ::PCPS_IRIG_TIME structure with the raw IRIG day-of-year number + and time decoded from the latest IRIG input frame. If the configured IRIG code + also contains the year number then the year number is also returned, otherwise + the returned year number is 0xFF. + + The macro _pcps_has_irig_time() or the API call mbg_dev_has_irig_time() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_IRIG_TIME type to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_irig_time() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_irig_time( MBG_DEV_HANDLE dh, PCPS_IRIG_TIME *p ) ; + + /** + @brief Clear a device's on-board time capture FIFO buffer. + + The macro _pcps_can_clr_ucap_buff() or the API call mbg_dev_can_clr_ucap_buff() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_can_clr_ucap_buff() + @see mbg_get_ucap_entries() + @see mbg_get_ucap_event() + */ + _MBG_API_ATTR int _MBG_API mbg_clr_ucap_buff( MBG_DEV_HANDLE dh ) ; + + /** + @brief Read information on a device's event capture buffer. + + Fills a ::PCPS_UCAP_ENTRIES structure with the number of user capture + events actually stored in the FIFO buffer, and the maximum number of + events that can be held by the buffer. + + The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_UCAP_ENTRIES structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_ucap() + @see mbg_get_ucap_entries() + @see mbg_get_ucap_event() + */ + _MBG_API_ATTR int _MBG_API mbg_get_ucap_entries( MBG_DEV_HANDLE dh, PCPS_UCAP_ENTRIES *p ) ; + + /** + @brief Retrieve a single time capture event from the on-board FIFO buffer. + + The capture event is returned in a ::PCPS_HR_TIME structure. The oldest entry + in the FIFO is retrieved and then removed from the FIFO. + + If no capture event is available in the FIFO buffer then both the seconds + and the fractions of the returned timestamp are 0. + + The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap() + check whether this call is supported by a device. + + <b>Note:</b> This call is very much faster than the older mbg_get_gps_ucap() + call which is obsolete but still supported for compatibility with + older cards. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_ucap() + @see mbg_get_ucap_entries() + @see mbg_clr_ucap_buff() + */ + _MBG_API_ATTR int _MBG_API mbg_get_ucap_event( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) ; + + /** + @brief Read the card's time zone/daylight saving parameters. + + This function returns the time zone/daylight saving parameters + in a ::TZDL structure. + + The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl() + check whether this call is supported by a device. + + <b>Note:</b> In spite of the function name this call may also be + supported by non-GPS cards. Other cards may support the mbg_get_tzcode() + or mbg_get_pcps_tzdl() calls instead. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::TZDL structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_tzdl() + @see mbg_set_gps_tzdl() + @see mbg_get_tzcode() + @see mbg_get_pcps_tzdl() + @see \ref group_tzdl + */ + _MBG_API_ATTR int _MBG_API mbg_get_gps_tzdl( MBG_DEV_HANDLE dh, TZDL *p ) ; + + /** + @brief Write the card's time zone/daylight saving parameters. + + This function writes the time zone/daylight saving parameters + in a ::TZDL structure to a device. + + The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl() + check whether this call is supported by a device. + + <b>Note:</b> In spite of the function name this call may also be + supported by non-GPS cards. Other cards may support the mbg_set_tzcode() + or mbg_set_pcps_tzdl() calls instead. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::TZDL structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_tzdl() + @see mbg_get_gps_tzdl() + @see mbg_set_tzcode() + @see mbg_set_pcps_tzdl() + @see \ref group_tzdl + */ + _MBG_API_ATTR int _MBG_API mbg_set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *p ) ; + + /** + @brief Retrieve the software revision of a GPS receiver. + + This call is obsolete but still supported for compatibility + with older GPS cards. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + <b>Note:</b> The function mbg_get_gps_receiver_info() should + be used instead, if supported by the card. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::SW_REV structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_is_gps() + @see mbg_get_gps_receiver_info() + */ + _MBG_API_ATTR int _MBG_API mbg_get_gps_sw_rev( MBG_DEV_HANDLE dh, SW_REV *p ) ; + + /** + @brief Retrieve the status of the battery buffered GPS variables. + + These GPS variables hold some parameters sent by the GPS satellites + which are required for proper operation. If the saved set of parameters + is not complete then the GPS receiver stays in COLD BOOT mode until + all data have been received and thus all data sets are valid. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::BVAR_STAT structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_bvar_stat( MBG_DEV_HANDLE dh, BVAR_STAT *p ) ; + + /** + @brief Read the current board time using a ::TTM structure. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + <b>Note:</b> This API call is pretty slow, so the mbg_get_hr_time_..() + or mbg_get_fast_hr_timestamp...() group of calls should be used preferably. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::TTM structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_hr_time() + @see mbg_get_fast_hr_timestamp() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_time( MBG_DEV_HANDLE dh, TTM *p ) ; + + /** + @brief Set the time on a GPS receiver device. + + Write a ::TTM structure to a GPS receiver in order to set the + on-board date and time. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::TTM structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_time( MBG_DEV_HANDLE dh, const TTM *p ) ; + + /** + @brief Read a ::PORT_PARM structure with a device's serial port configuration. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + <b>Note:</b> This function is obsolete since it is only + supported by a certain class of devices and can handle only + up to 2 ports. The generic function mbg_get_serial_settings() + should be used instead. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PORT_PARM structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_serial_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_port_parm( MBG_DEV_HANDLE dh, PORT_PARM *p ) ; + + /** + @brief Write a ::PORT_PARM structure to configure the on-board serial ports. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + <b>Note:</b> This function is obsolete since it is only + supported by a certain class of devices and can handle only + up to 2 ports. The generic function mbg_save_serial_settings() + should be used instead. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PORT_PARM structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_save_serial_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_port_parm( MBG_DEV_HANDLE dh, const PORT_PARM *p ) ; + + /** + @brief Read an ::ANT_INFO structure to retrieve an extended GPS antenna status. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + <b>Note:</b> Normally the current antenna connection status can also be + determined by evaluation of the ::PCPS_TIME::signal or ::PCPS_HR_TIME::signal + fields. The "disconnected" status reported by ANT_INFO disappears only if + the antenna has been reconnected <b>and</b> the receiver has synchronized + to the GPS satellites again. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ANT_INFO structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_info( MBG_DEV_HANDLE dh, ANT_INFO *p ) ; + + /** + @brief Read a time capture event from the on-board FIFO buffer using a ::TTM structure. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + <b>Note:</b> This call is pretty slow and has been obsoleted by + mbg_get_ucap_event() which should be used preferably, if supported + by the device. Anyway, this call is still supported for compatibility + with older devices. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::TTM structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_ucap_entries() + @see mbg_get_ucap_event() + @see mbg_clr_ucap_buff() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_ucap( MBG_DEV_HANDLE dh, TTM *p ) ; + + /** + @brief Read the ::ENABLE_FLAGS structure controlling when outputs are to be enabled. + + The ::ENABLE_FLAGS structure controls whether certain outputs + shall be enabled immediately after the card's power-up, or only + after the card has synchronized to its input signal. + + The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() + check whether this call is supported by a device. + + <b>Note:</b> Not all of the input signals specified for the + ::ENABLE_FLAGS structure can be modified individually. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::ENABLE_FLAGS structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see ::ENABLE_FLAGS + @see mbg_set_gps_enable_flags() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_enable_flags( MBG_DEV_HANDLE dh, ENABLE_FLAGS *p ) ; + + /** + @brief Write an ENABLE_FLAGS structure to configure when outputs shall be enabled. + + The ::ENABLE_FLAGS structure controls whether certain outputs + shall be enabled immediately after the card's power-up, or only + after the card has synchronized to its input signal. + + The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() + check whether this call is supported by a device. + + <b>Note:</b> Not all of the input signals specified for the + ENABLE_FLAGS structure can be modified individually. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ENABLE_FLAGS structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see ENABLE_FLAGS + @see mbg_get_gps_enable_flags() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_enable_flags( MBG_DEV_HANDLE dh, const ENABLE_FLAGS *p ) ; + + /** + @brief Read the extended GPS receiver status from a device. + + The ::STAT_INFO structure reports the status of the GPS receiver, + including mode of operation and number of visible/usable satellites. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::STAT_INFO structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see ::STAT_INFO +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_stat_info( MBG_DEV_HANDLE dh, STAT_INFO *p ) ; + + /** + @brief Send a ::GPS_CMD to a GPS receiver device. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::GPS_CMD + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see ::PC_GPS_CMD_BOOT, ::PC_GPS_CMD_INIT_SYS, ::PC_GPS_CMD_INIT_USER, ::PC_GPS_CMD_INIT_DAC +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_cmd( MBG_DEV_HANDLE dh, const GPS_CMD *p ) ; + + /** + @brief Read the current geographic position from a GPS device. + + The returned ::POS structure contains the current position in + ECEF (Earth Centered, Earth Fixed) kartesian coordinates, and in + geographic coordinates with different formats, using the WGS84 + geographic datum. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::POS structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_set_gps_pos_xyz() + @see mbg_set_gps_pos_lla() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_pos( MBG_DEV_HANDLE dh, POS *p ) ; + + /** + @brief Set the GPS receiver position using ::XYZ coordinates. + + The structure ::XYZ must specify the new position in ECEF + (Earth Centered, Earth Fixed) kartesian coordinates. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device. + @param p Position in ::XYZ format to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_set_gps_pos_lla() + @see mbg_get_gps_pos() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_xyz( MBG_DEV_HANDLE dh, const XYZ p ) ; + + /** + @brief Set the GPS receiver position using ::LLA coordinates. + + The structure LLA must specify the new position as longitude, latitude, + and altitude, using the WGS84 geographic datum. + + The macro _pcps_is_gps() or the API call mbg_dev_is_gps() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device. + @param p Position in ::LLA format to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_set_gps_pos_xyz() + @see mbg_get_gps_pos() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_lla( MBG_DEV_HANDLE dh, const LLA p ) ; + + /** + @brief Read the configured GPS antenna cable length from a device. + + The antenna cable length parameter is used to compensate the propagation + delay of the RF signal over the antenna cable, which is about 5 ns/m. + + The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device. + @param *p ::ANT_CABLE_LEN structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_cab_len() + @see mbg_set_gps_ant_cable_len() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_cable_len( MBG_DEV_HANDLE dh, ANT_CABLE_LEN *p ) ; + + /** + @brief Write the GPS antenna cable length configuration to a device. + + The antenna cable length parameter is used to compensate the propagation + delay of the RF signal over the antenna cable, which is about 5 ns/m. + + The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device. + @param *p ::ANT_CABLE_LEN structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_cab_len() + @see mbg_get_gps_ant_cable_len() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_ant_cable_len( MBG_DEV_HANDLE dh, const ANT_CABLE_LEN *p ) ; + + /** + @brief Read the ::RECEIVER_INFO structure from a device. + + The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info() + check whether this call is supported by a device. + + <b>Note:</b> Applications should call mbg_setup_receiver_info() + preferably, which also sets up a basic ::RECEIVER_INFO structure + for devices which don't provide that structure by themselves. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::RECEIVER_INFO structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_setup_receiver_info() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_receiver_info( MBG_DEV_HANDLE dh, RECEIVER_INFO *p ) ; + + /** + @brief Read a ::STR_TYPE_INFO_IDX array of supported string types. + + The function mbg_setup_receiver_info() must have been called before, + and the returned ::RECEIVER_INFO structure passed to this function. + + <b>Note:</b> The function mbg_get_serial_settings() should be used preferably + to get retrieve the current port settings and configuration options. + + @param dh Valid handle to a Meinberg device. + @param stii Pointer to a an array of string type information to be filled up + @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info() + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_setup_receiver_info() + @see mbg_get_gps_all_port_info() + @see mbg_get_serial_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_all_str_type_info( MBG_DEV_HANDLE dh, STR_TYPE_INFO_IDX stii[], const RECEIVER_INFO *p_ri ) ; + + /** + @brief Read a ::PORT_INFO_IDX array of supported serial port configurations. + + The function mbg_setup_receiver_info() must have been called before, + and the returned ::RECEIVER_INFO structure passed to this function. + + <b>Note:</b> The function mbg_get_serial_settings() should be used preferably + to get retrieve the current port settings and configuration options. + + @param dh Valid handle to a Meinberg device. + @param pii Pointer to a an array of port configuration information to be filled up + @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info() + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_setup_receiver_info() + @see mbg_get_gps_all_str_type_info() + @see mbg_get_serial_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_all_port_info( MBG_DEV_HANDLE dh, PORT_INFO_IDX pii[], const RECEIVER_INFO *p_ri ) ; + + /** + @brief Write the configuration for a single serial port to a device. + + The ::PORT_SETTINGS_IDX structure contains both the ::PORT_SETTINGS + and the port index value. Except for the parameter types this call is + equivalent to mbg_set_gps_port_settings(). + + The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info() + check whether this call is supported by a device. + + <b>Note:</b> The function mbg_save_serial_settings() should be used preferably + to write new port configuration to the board. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::PORT_SETTINGS_IDX structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_save_serial_settings() + @see mbg_set_gps_port_settings() + @see mbg_dev_has_receiver_info() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings_idx( MBG_DEV_HANDLE dh, const PORT_SETTINGS_IDX *p ) ; + + /** + @brief Write the configuration for a single serial port to a device. + + The ::PORT_SETTINGS structure does not contain the port index, so the + the port index must be given separately. Except for the parameter types + this call is equivalent to mbg_set_gps_port_settings_idx(). + + The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info() + check whether this call is supported by a device. + + <b>Note:</b> The function mbg_save_serial_settings() should be used preferably + to write new port configuration to the board. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::PORT_SETTINGS structure to be filled up + @param idx Index of the serial port to be configured (starting from 0 ). + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_save_serial_settings() + @see mbg_set_gps_port_settings_idx() + @see mbg_dev_has_receiver_info() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings( MBG_DEV_HANDLE dh, const PORT_SETTINGS *p, int idx ) ; + + /** + @brief Set up a ::RECEIVER_INFO structure for a device. + + If the device supports the ::RECEIVER_INFO structure then the structure + is read from the device, otherwise a structure is set up using + default values depending on the device type. + The function mbg_get_device_info() must have been called before, + and the returned PCPS_DEV structure passed to this function. + + @param dh Valid handle to a Meinberg device. + @param *pdev Pointer to a ::PCPS_DEV structure returned by mbg_get_device_info() + @param *p Pointer to a ::RECEIVER_INFO structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_device_info() + @see mbg_dev_has_receiver_info() +*/ + _MBG_API_ATTR int _MBG_API mbg_setup_receiver_info( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_INFO *p ) ; + + /** + @brief Read the version code of the on-board PCI/PCIe interface ASIC. + + The macro _pcps_has_asic_version() or the API call mbg_dev_has_asic_version() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCI_ASIC_VERSION type to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function + + @see mbg_dev_has_asic_version() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_asic_version( MBG_DEV_HANDLE dh, PCI_ASIC_VERSION *p ) ; + + /** + @brief Read the features of the on-board PCI/PCIe interface ASIC. + + The macro _pcps_has_asic_features() or the API call mbg_dev_has_asic_features() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::PCI_ASIC_FEATURES type to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_asic_features() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_asic_features( MBG_DEV_HANDLE dh, PCI_ASIC_FEATURES *p ) ; + + /** + @brief Check if a device supports configurable time scales. + + By default the cards return UTC and/or local time. However, some cards + can be configured to return raw GPS time or TAI instead. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_time_scale_info() + @see mbg_set_time_scale_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_time_scale( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read the current time scale settings and which time scales are supported. + + The ::MBG_TIME_SCALE_INFO structure tells which time scale settings are supported + by a device, and which time scale is currently configured. + + The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale() + check whether this call is supported by a device. + See also the notes for mbg_dev_has_time_scale(). + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_TIME_SCALE_INFO structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_set_time_scale_settings() + @see mbg_dev_has_time_scale() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_time_scale_info( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p ) ; + + /** + @brief Write the time scale configuration to a device. + + The ::MBG_TIME_SCALE_SETTINGS structure determines which time scale + is to be used for the time stamps which can be read from a device. + + The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale() + check whether this call is supported by a device. + See also the notes for mbg_dev_has_time_scale(). + + The function mbg_get_time_scale_info() should have been called before + in order to determine which time scales are supported by the card. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_TIME_SCALE_SETTINGS structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_time_scale_info() + @see mbg_dev_has_time_scale() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_SETTINGS *p ) ; + + /** + @brief Check if a device support reading/writing of UTC parameters. + + This API call checks if a device supports reading/writing a GPS UTC + parameter set via the PC bus. Reading/writing these parameters via the + serial port using the Meinberg binary data protocol is supported by all + Meinberg GPS devices. + + The UTC parameter set is usually received from the satellites' broadcasts + and contains the current time offset between GPS time and UTC, plus information + on a pending leap second event. + + It may be useful to overwrite them to do some tests, or for applications + where a card is freewheeling. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_utc_parm() + @see mbg_set_utc_parm() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_utc_parm( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read a ::UTC parameter structure from a device. + + The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm() + check whether this call is supported by a device. + See also the notes for mbg_dev_has_utc_parm(). + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::UTC structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_utc_parm() + @see mbg_set_utc_parm() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) ; + + /** + @brief Write a ::UTC parameter structure to a device. + + This should only be done for testing, or if a card is operated in + freewheeling mode. If the receiver is tracking any satellites then the settings + written to the device are overwritten by the parameters broadcasted + by the satellites. + + The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm() + check whether this call is supported by a device. + See also the notes for mbg_dev_has_utc_parm(). + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a valid ::UTC structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_utc_parm() + @see mbg_get_utc_parm() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) ; + + /** + @brief Read the current time plus the associated PC cycles from a device. + + The ::PCPS_TIME_CYCLES structure contains a ::PCPS_TIME structure + and a PC cycle counter value which can be used to compensate the latency + of the call, i.e. the program execution time until the time stamp has actually + been read from the board. + + This call is supported for any card, similar to mbg_get_time(). However, + the mbg_get_hr_time_cyles() call should be used preferably if supported by + the device since that call provides much better accuracy than this one. + + The cycle counter value corresponds to a value returned by QueryPerformanceCounter() + under Windows, and get_cycles() under Linux. On operating systems or targets which don't + provide a cycles counter the returned cycles value is always 0. + + Applications should first pick up their own cycle counter value and then call + this function. The difference of the cycle counter values corresponds to the + latency of the call in units of the cycle counter clock frequency, e.g as reported + by QueryPerformanceFrequency() under Windows. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TIME_CYCLES structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_hr_time_cycles() + @see mbg_get_hr_time_comp() + @see mbg_get_hr_time() + @see mbg_get_time() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_time_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_CYCLES *p ) ; + + /** + @brief Read the current high resolution time plus the associated PC cycles from a device. + + The ::PCPS_HR_TIME_CYCLES structure contains a ::PCPS_HR_TIME structure + and a PC cycle counter value which can be used to compensate the latency + of the call, i.e. the program execution time until the time stamp has actually + been read from the board. + + The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() + check whether this call is supported by a device. + + The cycle counter value corresponds to a value returned by QueryPerformanceCounter() + under Windows, and get_cycles() under Linux. On operating systems or targets which don't + provide a cycles counter the returned cycles value is always 0. + + Applications should first pick up their own cycle counter value and then call + this function. The difference of the cycle counter values corresponds to the + latency of the call in units of the cycle counter clock frequency, e.g as reported + by QueryPerformanceFrequency() under Windows. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_HR_TIME_CYCLES structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_hr_time_comp() + @see mbg_get_hr_time() + @see mbg_get_time_cycles() + @see mbg_get_time() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_hr_time_cycles( MBG_DEV_HANDLE dh, PCPS_HR_TIME_CYCLES *p ) ; + + /** + @brief Read the current high resolution time, and compensate the call's latency. + + Read a ::PCPS_HR_TIME structure plus cycle counter value, and correct the + time stamp for the latency of the call as described for mbg_get_hr_time_cycles(), + then return the compensated time stamp and optionally the latency. + + The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() + check whether this call is supported by a device. + + The cycle counter value corresponds to a value returned by QueryPerformanceCounter() + under Windows, and get_cycles() under Linux. On operating systems or targets which don't + provide a cycles counter the returned cycles value is always 0. + + Applications should first pick up their own cycle counter value and then call + this function. The difference of the cycle counter values corresponds to the + latency of the call in units of the cycle counter clock frequency, e.g as reported + by QueryPerformanceFrequency() under Windows. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up + @param *hns_latency Optional pointer to an int32_t value to return + the latency in 100ns units. Pass NULL if not used. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_hr_time_comp() + @see mbg_get_hr_time() + @see mbg_get_time_cycles() + @see mbg_get_time() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_hr_time_comp( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p, int32_t *hns_latency ) ; + + /** + @brief Read the current IRIG output settings plus the supported settings. + + The returned ::IRIG_INFO structure contains the configuration of an IRIG output + plus the possible settings supported by that output. + + The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an ::IRIG_INFO structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_set_irig_tx_settings() + @see mbg_dev_has_irig_tx() + @see mbg_dev_is_irig_rx() + @see mbg_dev_has_irig() + @see \ref group_icode +*/ + _MBG_API_ATTR int _MBG_API mbg_get_irig_tx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) ; + + /** + @brief Write an ::IRIG_SETTINGS structure to a device to configure the IRIG output. + + The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an ::IRIG_INFO structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_irig_tx_info() + @see mbg_dev_has_irig_tx() + @see mbg_dev_is_irig_rx() + @see mbg_dev_has_irig() + @see \ref group_icode +*/ + _MBG_API_ATTR int _MBG_API mbg_set_irig_tx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) ; + + /** + @brief Read the current frequency synthesizer settings from a device. + + Read a ::SYNTH structure containing the configuration of an optional + on-board programmable frequency synthesizer. + + The macro _pcps_has_synth() or the API call mbg_dev_has_synth() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::SYNTH structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_synth() + @see mbg_set_synth() + @see mbg_get_synth_state() + @see \ref group_synth +*/ + _MBG_API_ATTR int _MBG_API mbg_get_synth( MBG_DEV_HANDLE dh, SYNTH *p ) ; + + /** + @brief Write some frequency synthesizer settings to a device. + + Write a ::SYNTH structure containing the configuration of an optional + on-board programmable frequency synthesizer. + + The macro _pcps_has_synth() or the API call mbg_dev_has_synth() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::SYNTH structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_synth() + @see mbg_get_synth() + @see mbg_get_synth_state() + @see \ref group_synth +*/ + _MBG_API_ATTR int _MBG_API mbg_set_synth( MBG_DEV_HANDLE dh, const SYNTH *p ) ; + + /** + @brief Read the current status of the on-board frequency synthesizer. + + The macro _pcps_has_synth() or the API call mbg_dev_has_synth() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::SYNTH_STATE structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_synth() + @see mbg_get_synth() + @see mbg_set_synth() + @see \ref group_synth +*/ + _MBG_API_ATTR int _MBG_API mbg_get_synth_state( MBG_DEV_HANDLE dh, SYNTH_STATE *p ) ; + + /** + @brief Check if a device supports the mbg_get_fast_hr_timestamp_...() calls. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_fast_hr_timestamp_cycles() + @see mbg_get_fast_hr_timestamp_comp() + @see mbg_get_fast_hr_timestamp() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_fast_hr_timestamp( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read a high resolution ::PCPS_TIME_STAMP_CYCLES structure via memory mapped access. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TIME_STAMP_CYCLES structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_fast_hr_timestamp() + @see mbg_get_fast_hr_timestamp_comp() + @see mbg_get_fast_hr_timestamp() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP_CYCLES *p ) ; + + /** + @brief Read a high resolution timestamp and compensate the latency of the call. + + The retrieved ::PCPS_TIME_STAMP is read from memory mapped registers, + and timestamp is compensated for the call's latency before it is returned. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up + @param *hns_latency Optionally receive the latency in hectonanoseconds + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_fast_hr_timestamp() + @see mbg_get_fast_hr_timestamp_cycles() + @see mbg_get_fast_hr_timestamp() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_comp( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP *p, int32_t *hns_latency ) ; + + /** + @brief Read a high resolution ::PCPS_TIME_STAMP structure via memory mapped access. + + This function does not return or evaluate a cycles count, so the latency + of the call can not be determined. However, depending on the timer hardware + used as cycles counter it may take quite some time to read the cycles count + on some hardware architectures, so this call can be used to yield lower + latencies, under the restriction to be unable to determine the exact latency. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_fast_hr_timestamp() + @see mbg_get_fast_hr_timestamp_comp() + @see mbg_get_fast_hr_timestamp_cycles() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP *p ) ; + + /** + @brief Check if a device is a GPS receiver. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_is_gps( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device is a DCF77 receiver. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_is_dcf( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device is a MSF receiver. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_is_msf( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device is a WWVB receiver. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_is_wwvb( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device is any long wave signal receiver. + + Long wave receivers include e.g. DCF77, MSF, WWVB, or JJY. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_is_lwr( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device provides a configurable IRIG input. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_irig_rx_info() + @see mbg_set_irig_rx_settings() + @see mbg_dev_has_irig_tx() + @see mbg_dev_has_irig() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_is_irig_rx( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports the HR_TIME functions. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_hr_time() + @see mbg_get_hr_time_cycles() + @see mbg_get_hr_time_comp() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_hr_time( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports configuration of antenna cable length. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_gps_ant_cable_len() + @see mbg_set_gps_ant_cable_len() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_cab_len( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports timezone configuration using the ::TZDL structure. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_gps_tzdl() + @see mbg_set_gps_tzdl() + @see mbg_dev_has_tz() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_tzdl( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports timezone configuration using the ::PCPS_TZDL structure. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_pcps_tzdl() + @see mbg_set_pcps_tzdl() + @see mbg_dev_has_tz() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_pcps_tzdl( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports timezone configuration using the ::PCPS_TZCODE type. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_tzcode() + @see mbg_set_tzcode() + @see mbg_dev_has_tz() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_tzcode( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports any kind of timezone configuration. + + This can be used e.g. to check if a specifig dialog or menu has to + be displayed. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_tzdl() + @see mbg_dev_has_pcps_tzdl() + @see mbg_dev_has_tzcode() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_tz( MBG_DEV_HANDLE dh, int *p ) ; + + /* (Intentionally excluded from Doxygen) + Check if a device supports setting an event time, i.e. + configure a %UTC time when the clock shall generate an event. + + <b>Note:</b> This is only supported by some special firmware. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_set_event_time() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_event_time( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports the ::RECEIVER_INFO structure and related calls. + + @note Older GPS devices may not support that structure. + + The mbg_get_gps_receiver_info() call uses this call to decide whether a + ::RECEIVER_INFO can be read directly from a device, or whether a default + structure has to be set up using default values depending on the device type. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_gps_receiver_info() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_receiver_info( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports the mbg_clr_ucap_buff() call. + + The mbg_clr_ucap_buff() call can be used to clear a card's on-board + time capture FIFO buffer. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_clr_ucap_buff() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_can_clr_ucap_buff( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports the mbg_get_ucap_entries() and mbg_get_ucap_event() calls. + + If the card does not but it is a GPS card then the card provides + a time capture FIFO buffer and the obsolete mbg_get_gps_ucap() + call can be used to retrieve entries from the FIFO buffer. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_ucap_entries() + @see mbg_get_ucap_event() + @see mbg_clr_ucap_buff() + @see mbg_get_gps_ucap() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_ucap( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device provides a configurable IRIG output. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_irig_tx_info() + @see mbg_set_irig_tx_settings() + @see mbg_dev_is_irig_rx() + @see mbg_dev_has_irig() + @see \ref group_icode + +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_tx( MBG_DEV_HANDLE dh, int *p ) ; + + /* (Intentionally excluded from Doxygen) + Check if a device provides a serial output supporting + higher baud rates than older cards, i.e. ::DEFAULT_BAUD_RATES_DCF_HS + rather than ::DEFAULT_BAUD_RATES_DCF. + + The mbg_get_serial_settings() takes care of this, so applications + which use that call as suggested won't need to use this call directly. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_serial_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_serial_hs( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device provides the level of its inputs signal. + + This is useful to display the signal level of e.g. an IRIG or longwave signal. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_signal( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device provides a modulation signal. + + Modulation signals are e.g. the second marks of a DCF77 AM receiver. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_mod( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device provides either an IRIG input or output. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_is_irig_rx() + @see mbg_dev_has_irig_tx() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_irig( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device provides a configurable ref time offset. + + This may be required to convert the received time to %UTC, if the input + signal doesn't specify this (e.g. most IRIG code formats). + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_ref_offs() + @see mbg_set_ref_offs() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_ref_offs( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports the ::MBG_OPT_INFO/::MBG_OPT_SETTINGS. + + These structures containing optional settings, controlled by flags. + See ::MBG_OPT_SETTINGS and related definitions. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_opt_info() + @see mbg_set_opt_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_opt_flags( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports large configuration data structures. + + Such structures have been introduced with the first Meinberg GPS receivers. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_gps_data( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device provides a programmable frequency synthesizer. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_synth() + @see mbg_set_synth() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_synth( MBG_DEV_HANDLE dh, int *p ) ; + + /* (Intentionally excluded from Doxygen) + @brief Check if a device supports the mbg_generic_io() call. + + <b>Warning</b>: That call is for debugging purposes and internal use only! + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_generic_io() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_generic_io( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports the mbg_get_asic_version() call. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_asic_version() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_asic_version( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports the mbg_get_asic_features() call. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_asic_features() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_asic_features( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read current configuraton and features provided by the programmable pulse outputs. + + Reads a ::POUT_INFO_IDX array of current settings and configuration + options of the device's programmable pulse outputs. + + The function mbg_setup_receiver_info() must have been called before, + and the returned ::RECEIVER_INFO structure passed to this function. + The function should only be called if the ::RECEIVER_INFO::n_prg_out + field (i.e. the number of programmable outputs on the board) is not 0. + + The array passed to this function to receive the returned data + must be able to hold at least ::RECEIVER_INFO::n_prg_out elements. + + @param dh Valid handle to a Meinberg device. + @param pii Pointer to a an array of ::POUT_INFO_IDX structures to be filled up + @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info() + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_set_gps_pout_settings_idx() + @see mbg_set_gps_pout_settings() + @see mbg_setup_receiver_info() +*/ + _MBG_API_ATTR int _MBG_API mbg_get_gps_all_pout_info( MBG_DEV_HANDLE dh, POUT_INFO_IDX pii[], const RECEIVER_INFO *p_ri ) ; + + /** + @brief Write the configuration for a single programmable pulse output + + The ::POUT_SETTINGS_IDX structure contains both the ::POUT_SETTINGS + and the output index value. Except for the parameter types this call + is equivalent to mbg_set_gps_pout_settings(). + + The function should only be called if the ::RECEIVER_INFO::n_prg_out field + (i.e. the number of programmable outputs on the board) is not 0, and the + output index value must be in the range 0..::RECEIVER_INFO::n_prg_out. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::POUT_SETTINGS_IDX structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_gps_all_pout_info() + @see mbg_set_gps_pout_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings_idx( MBG_DEV_HANDLE dh, const POUT_SETTINGS_IDX *p ) ; + + /** + @brief Write the configuration for a single programmable pulse output + + The ::POUT_SETTINGS structure does not contain the index of the + programmable output to be configured, so the index must explicitely + be passed to this function. Except for the parameter types this call + is equivalent to mbg_set_gps_pout_settings_idx(). + + The function should only be called if the ::RECEIVER_INFO::n_prg_out field + (i.e. the number of programmable outputs on the board) is not 0, and the + output index value must be in the range 0..::RECEIVER_INFO::n_prg_out. + + @param dh Valid handle to a Meinberg device. + @param *p Pointer to a ::POUT_SETTINGS structure to be written + @param idx Index of the programmable pulse output to be configured (starting from 0 ). + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_gps_all_pout_info() + @see mbg_set_gps_pout_settings_idx() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings( MBG_DEV_HANDLE dh, const POUT_SETTINGS *p, int idx ) ; + + /** + @brief Read a device's IRQ status information. + + IRQ status information includes flags indicating whether IRQs are + actually enabled, and whether IRQ support by a card is possibly + unsafe due to the firmware and interface chip version. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PCPS_IRQ_STAT_INFO variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + */ + _MBG_API_ATTR int _MBG_API mbg_get_irq_stat_info( MBG_DEV_HANDLE dh, PCPS_IRQ_STAT_INFO *p ) ; + + /** + @brief Check if a device provides simple LAN interface API calls. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_lan_if_info() + @see mbg_get_ip4_state() + @see mbg_get_ip4_settings() + @see mbg_set_ip4_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_lan_intf( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read LAN interface information from a device. + + The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::LAN_IF_INFO variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_lan_intf() + @see mbg_get_ip4_state() + @see mbg_get_ip4_settings() + @see mbg_set_ip4_settings() + */ + _MBG_API_ATTR int _MBG_API mbg_get_lan_if_info( MBG_DEV_HANDLE dh, LAN_IF_INFO *p ) ; + + /** + @brief Read LAN IPv4 state from a device. + + The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::IP4_SETTINGS variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_lan_intf() + @see mbg_get_lan_if_info() + @see mbg_get_ip4_settings() + @see mbg_set_ip4_settings() + */ + _MBG_API_ATTR int _MBG_API mbg_get_ip4_state( MBG_DEV_HANDLE dh, IP4_SETTINGS *p ) ; + + /** + @brief Read LAN IPv4 settings from a device. + + The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::IP4_SETTINGS variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_lan_intf() + @see mbg_get_lan_if_info() + @see mbg_get_ip4_state() + @see mbg_set_ip4_settings() + */ + _MBG_API_ATTR int _MBG_API mbg_get_ip4_settings( MBG_DEV_HANDLE dh, IP4_SETTINGS *p ) ; + + /** + @brief Write LAN IPv4 settings to a device. + + The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device. + @param *p ::IP4_SETTINGS structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_lan_intf() + @see mbg_get_lan_if_info() + @see mbg_get_ip4_settings() +*/ + _MBG_API_ATTR int _MBG_API mbg_set_ip4_settings( MBG_DEV_HANDLE dh, const IP4_SETTINGS *p ) ; + + /** + @brief Check if a device provides PTP configuration/status calls. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_all_ptp_cfg_info + @see mbg_get_ptp_state + @see mbg_get_ptp_cfg_info + @see mbg_set_ptp_cfg_settings + @see mbg_dev_has_ptp_unicast +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_ptp( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device provides PTP unicast feature/configuration. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_all_ptp_cfg_info + @see mbg_get_ptp_uc_master_cfg_limits + @see mbg_get_all_ptp_uc_master_info + @see mbg_set_ptp_uc_master_settings_idx + @see mbg_get_ptp_state +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_ptp_unicast( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read PTP/IEEE1588 status from a device. + + The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PTP_STATE variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_ptp + @see mbg_get_all_ptp_cfg_info + @see mbg_get_ptp_cfg_info + @see mbg_set_ptp_cfg_settings + @see mbg_dev_has_ptp_unicast + */ + _MBG_API_ATTR int _MBG_API mbg_get_ptp_state( MBG_DEV_HANDLE dh, PTP_STATE *p ) ; + + /** + @brief Read PTP/IEEE1588 config info and current settings from a device. + + The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PTP_CFG_INFO variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_ptp + @see mbg_get_all_ptp_cfg_info + @see mbg_get_ptp_state + @see mbg_set_ptp_cfg_settings + @see mbg_dev_has_ptp_unicast + */ + _MBG_API_ATTR int _MBG_API mbg_get_ptp_cfg_info( MBG_DEV_HANDLE dh, PTP_CFG_INFO *p ) ; + + /** + @brief Write PTP/IEEE1588 configuration settings to a device. + + The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device. + @param *p ::PTP_CFG_SETTINGS structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_ptp + @see mbg_get_all_ptp_cfg_info + @see mbg_get_ptp_state + @see mbg_get_ptp_cfg_info + @see mbg_dev_has_ptp_unicast +*/ + _MBG_API_ATTR int _MBG_API mbg_set_ptp_cfg_settings( MBG_DEV_HANDLE dh, const PTP_CFG_SETTINGS *p ) ; + + /** + @brief Read PTP/IEEE1588 unicast master configuration limits from a device. + + The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::PTP_UC_MASTER_CFG_LIMITS variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_ptp_unicast + @see mbg_get_all_ptp_cfg_info + @see mbg_get_all_ptp_uc_master_info + @see mbg_set_ptp_uc_master_settings_idx + @see mbg_get_ptp_state + */ + _MBG_API_ATTR int _MBG_API mbg_get_ptp_uc_master_cfg_limits( MBG_DEV_HANDLE dh, PTP_UC_MASTER_CFG_LIMITS *p ) ; + + /** + @brief Read PTP Unicast master settings and configuration options. + + The function mbg_setup_receiver_info() must have been called before, + and the returned ::RECEIVER_INFO structure passed to this function. + The function should only be called if the ::RECEIVER_INFO::n_prg_out + field (i.e. the number of programmable outputs on the board) is not 0. + + The array passed to this function to receive the returned data + must be able to hold at least ::RECEIVER_INFO::n_prg_out elements. + + @param dh Valid handle to a Meinberg device. + @param pii Pointer to a an array of ::PTP_UC_MASTER_INFO_IDX structures to be filled up + @param p_umsl Pointer to a ::PTP_UC_MASTER_CFG_LIMITS structure returned by mbg_get_ptp_uc_master_cfg_limits() + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_ptp_unicast + @see mbg_get_all_ptp_cfg_info + @see mbg_get_ptp_uc_master_cfg_limits + @see mbg_set_ptp_uc_master_settings_idx + @see mbg_get_ptp_state +*/ + _MBG_API_ATTR int _MBG_API mbg_get_all_ptp_uc_master_info( MBG_DEV_HANDLE dh, PTP_UC_MASTER_INFO_IDX pii[], const PTP_UC_MASTER_CFG_LIMITS *p_umsl ) ; + + /** + @brief Write PTP/IEEE1588 unicast configuration settings to a device. + + The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device. + @param *p ::PTP_UC_MASTER_SETTINGS_IDX structure to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_ptp_unicast + @see mbg_get_all_ptp_cfg_info + @see mbg_get_ptp_uc_master_cfg_limits + @see mbg_get_all_ptp_uc_master_info + @see mbg_get_ptp_state +*/ + _MBG_API_ATTR int _MBG_API mbg_set_ptp_uc_master_settings_idx( MBG_DEV_HANDLE dh, const PTP_UC_MASTER_SETTINGS_IDX *p ) ; + + /** + @brief Read both system time and associated device time from the kernel driver. + + The kernel driver reads the current system time plus a HR time structure + from a card immediately after each other. The returned info structure also + contains some cycles counts to be able to determine the execution times + required to read those time stamps. + + The advantage of this call compared to mbg_get_time_info_tstamp() is + that this call also returns the card's status. On the other hand, reading + the HR time from the card may block e.g. if another application accesses + the board. + + This call makes a mbg_get_hr_time_cycles() call internally so the macro + _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() can be + used to check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_TIME_INFO_HRT variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_hr_time() + @see mbg_get_time_info_tstamp() + */ + _MBG_API_ATTR int _MBG_API mbg_get_time_info_hrt( MBG_DEV_HANDLE dh, MBG_TIME_INFO_HRT *p ) ; + + /** + @brief Read both system time and associated device timestamp from the kernel driver. + + This call is similar to mbg_get_time_info_hrt() except that a + mbg_get_fast_hr_timestamp_cycles() call is made internally, so the macro + _pcps_has_fast_hr_timestamp() or the API call mbg_dev_has_fast_hr_timestamp() + can be used to check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_TIME_INFO_TSTAMP variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_fast_hr_timestamp() + @see mbg_get_time_info_hrt() + */ + _MBG_API_ATTR int _MBG_API mbg_get_time_info_tstamp( MBG_DEV_HANDLE dh, MBG_TIME_INFO_TSTAMP *p ) ; + + /** + @brief Check if a device supports demodulation of the DCF77 PZF code. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_corr_info() + @see mbg_dev_has_tr_distance() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_pzf( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports reading correlation info. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_pzf() + @see mbg_get_corr_info() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_corr_info( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Check if a device supports configurable distance from transmitter. + + The distance from transmitter parameter is used to compensate + the RF propagation delay, mostly with long wave receivers. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_pzf() + @see mbg_get_tr_distance() + @see mbg_set_tr_distance() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_tr_distance( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read PZF correlation info from a device. + + The macro _pcps_has_corr_info() or the API call mbg_dev_has_corr_info() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::CORR_INFO variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_pzf() + @see mbg_dev_has_corr_info() + */ + _MBG_API_ATTR int _MBG_API mbg_get_corr_info( MBG_DEV_HANDLE dh, CORR_INFO *p ) ; + + /** + @brief Read configurable "distance from transmitter" parameter from a device. + + The distance from transmitter parameter is used to compensate + the RF propagation delay, mostly with long wave receivers. + + The macro _pcps_has_tr_distance() or the API call mbg_dev_has_tr_distance() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::TR_DISTANCE variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_pzf() + @see mbg_dev_has_tr_distance() + @see mbg_set_tr_distance() + */ + _MBG_API_ATTR int _MBG_API mbg_get_tr_distance( MBG_DEV_HANDLE dh, TR_DISTANCE *p ) ; + + /** + @brief Write configurable "distance from transmitter" parameter to a device. + + The distance from transmitter parameter is used to compensate + the RF propagation delay, mostly with long wave receivers. + + The macro _pcps_has_tr_distance() or the API call mbg_dev_has_tr_distance() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::TR_DISTANCE variable to be written + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_pzf() + @see mbg_dev_has_tr_distance() + @see mbg_get_tr_distance() + */ + _MBG_API_ATTR int _MBG_API mbg_set_tr_distance( MBG_DEV_HANDLE dh, const TR_DISTANCE *p ) ; + + /** + @brief Check if a device provides a debug status word to be read. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_debug_status() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_debug_status( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Read a debug status word from a device. + + This is mainly supported by IRIG timecode receiver cards, and the status + word is intended to provide more detailed information why a card might not + synchronize to the incoming timecode signal. + + See ::MBG_DEBUG_STATUS and related definitions for details. + + The macro _pcps_has_debug_status() or the API call mbg_dev_has_debug_status() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_DEBUG_STATUS variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_debug_status() + */ + _MBG_API_ATTR int _MBG_API mbg_get_debug_status( MBG_DEV_HANDLE dh, MBG_DEBUG_STATUS *p ) ; + + /** + @brief Check if a device provides an on-board event log. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_clr_evt_log() + @see mbg_get_num_evt_log_entries() + @see mbg_get_first_evt_log_entry() + @see mbg_get_next_evt_log_entry() +*/ + _MBG_API_ATTR int _MBG_API mbg_dev_has_evt_log( MBG_DEV_HANDLE dh, int *p ) ; + + /** + @brief Clear the card's on-board event log. + + The macro _pcps_has_evt_log() or the API call mbg_dev_has_evt_log() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_evt_log() + @see mbg_get_num_evt_log_entries() + @see mbg_get_first_evt_log_entry() + @see mbg_get_next_evt_log_entry() + */ + _MBG_API_ATTR int _MBG_API mbg_clr_evt_log( MBG_DEV_HANDLE dh ) ; + + /** + @brief Read details about a device's on-board event log buffer. + + The returned ::MBG_NUM_EVT_LOG_ENTRIES structure tells how many event log + entries which can be saved on the board, and how many entries actually + have been saved. + + The macro _pcps_has_evt_log() or the API call mbg_dev_has_evt_log() + check whether this call is supported by a device. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_NUM_EVT_LOG_ENTRIES variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_evt_log() + @see mbg_clr_evt_log() + @see mbg_get_first_evt_log_entry() + @see mbg_get_next_evt_log_entry() + */ + _MBG_API_ATTR int _MBG_API mbg_get_num_evt_log_entries( MBG_DEV_HANDLE dh, MBG_NUM_EVT_LOG_ENTRIES *p ) ; + + /** + @brief Read the first (oldest) event log entry from a device. + + @note Subsequent reads should be made using mbg_get_next_evt_log_entry(). + + The macro _pcps_has_evt_log() or the API call mbg_dev_has_evt_log() + check whether this call is supported by a device. + + If no (more) event log entry is available on the device then + the returned MBG_EVT_LOG_ENTRY::code is MBG_EVT_ID_NONE. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_EVT_LOG_ENTRY variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_evt_log() + @see mbg_clr_evt_log() + @see mbg_get_num_evt_log_entries() + @see mbg_get_next_evt_log_entry() + */ + _MBG_API_ATTR int _MBG_API mbg_get_first_evt_log_entry( MBG_DEV_HANDLE dh, MBG_EVT_LOG_ENTRY *p ) ; + + /** + @brief Read the next event log entry from a device. + + @note The first read should be made using mbg_get_first_evt_log_entry() + to set the on-board read index to the oldest entry. + + The macro _pcps_has_evt_log() or the API call mbg_dev_has_evt_log() + check whether this call is supported by a device. + + If no (more) event log entry is available on the device then + the returned MBG_EVT_LOG_ENTRY::code is MBG_EVT_ID_NONE. + + @param dh Valid handle to a Meinberg device + @param *p Pointer to a ::MBG_EVT_LOG_ENTRY variable to be filled up + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_dev_has_evt_log() + @see mbg_clr_evt_log() + @see mbg_get_num_evt_log_entries() + @see mbg_get_first_evt_log_entry() + */ + _MBG_API_ATTR int _MBG_API mbg_get_next_evt_log_entry( MBG_DEV_HANDLE dh, MBG_EVT_LOG_ENTRY *p ) ; + + /** + @brief Read the CPU affinity of a process. + + This means on which of the available CPUs or CPU cores the process can be executed. + + @param pid The process ID. + @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + + @return ::MBG_SUCCESS or error code returned by the system call. + + @see mbg_set_process_affinity() + @see mbg_set_current_process_affinity_to_cpu() + */ + _MBG_API_ATTR int _MBG_API mbg_get_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) ; + + /** + @brief Set the CPU affinity of a process. + + This determines on which of the available CPUs + the process is allowed to be executed. + + @param pid The process ID. + @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + + @return ::MBG_SUCCESS or error code returned by the system call. + + @see mbg_get_process_affinity() + @see mbg_set_current_process_affinity_to_cpu() + */ + _MBG_API_ATTR int _MBG_API mbg_set_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) ; + + /** + @brief Set the CPU affinity of a process for a single CPU only. + + This means the process may only be executed on that single CPU. + + @param cpu_num The number of the CPU. + + @return ::MBG_SUCCESS or error code returned by the system call. + + @see mbg_get_process_affinity() + @see mbg_set_process_affinity() + */ + _MBG_API_ATTR int _MBG_API mbg_set_current_process_affinity_to_cpu( int cpu_num ) ; + + /** + @brief Create a new execution thread for the current process. + + This function is only implemented for targets which support threads. + + @param p_ti Pointer to a ::MBG_THREAD_INFO structure to be filled up. + @param fnc The name of the thread function to be started. + @param arg A generic argument passed to the thread function. + + @return ::MBG_SUCCESS or error code returned by the system call. + + @see mbg_thread_stop() + @see mbg_thread_sleep_interruptible() + @see mbg_thread_set_affinity() + */ + _MBG_API_ATTR int _MBG_API mbg_thread_create( MBG_THREAD_INFO *p_ti, MBG_THREAD_FNC_RET_VAL (MBG_THREAD_FNC_ATTR *fnc)(void *), void *arg ) ; + + /** + @brief Stop a thread which has been created by mbg_thread_create(). + + Wait until the thread has finished and release all resources. + This function is only implemented for targets which support threads. + + @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. + + @return ::MBG_SUCCESS or error code returned by the system call. + + @see mbg_thread_create() + @see mbg_thread_sleep_interruptible() + @see mbg_thread_set_affinity() + */ + _MBG_API_ATTR int _MBG_API mbg_thread_stop( MBG_THREAD_INFO *p_ti ) ; + + /** + @brief Let the current thread sleep for a certain interval. + + The sleep is interrupted if a signal is received indicating + the thread should terminate. + + This function is only implemented for targets which support threads. + + @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. + @param sleep_ms The number of milliseconds to sleep + @return 0 if the sleep interval has expired normally + 1 if a signal to terminate has been received + <0 if an error has occurred + + @see mbg_thread_create() + @see mbg_thread_stop() + @see mbg_thread_set_affinity() + */ + _MBG_API_ATTR int _MBG_API mbg_thread_sleep_interruptible( MBG_THREAD_INFO *p_ti, ulong sleep_ms ) ; + + /** + @brief Set the CPU affinity of a single thread. + + This determines on which of the available CPUs the thread + is allowed to be executed. + + This function is only implemented for targets which support thread affinity. + + @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. + @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + + @return ::MBG_SUCCESS or error code returned by the system call. + + @see mbg_thread_create() + @see mbg_thread_stop() + @see mbg_thread_sleep_interruptible() + */ + _MBG_API_ATTR int _MBG_API mbg_thread_set_affinity( MBG_THREAD_INFO *p_ti, MBG_CPU_SET *p ) ; + + /** + @brief Set up a ::MBG_POLL_THREAD_INFO structure and start a new thread. + + The new thread runs the mbg_xhrt_poll_thread_fnc() function. + + This function is only implemented for targets which support threads. + + @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure. + @param dh the handle of the device to be polled. + @param freq_hz The initial cycles frequency, if known, in Hz. + @param sleep_ms the sleep interval for the poll thread function in ms. + If this parameter is 0 then the default sleep interval is used. + + @return ::MBG_SUCCESS on success, + ::MBG_ERR_NOT_SUPP_BY_DEV if the device to poll does not support HR time + else the result of mbg_thread_create() + + @see mbg_xhrt_poll_thread_fnc() + @see mbg_xhrt_poll_thread_stop() + @see mbg_get_xhrt_time_as_pcps_hr_time() + @see mbg_get_xhrt_time_as_filetime() + @see mbg_get_xhrt_cycles_frequency() + */ + _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_create( MBG_POLL_THREAD_INFO *p_pti, MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY freq_hz, int sleep_ms ) ; + + /** + @brief Stop a polling thread started by mbg_xhrt_poll_thread_create(). + + This call also releases all associated resources. + + @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure. + + @return the result of mbg_thread_stop() + + @see mbg_xhrt_poll_thread_fnc() + @see mbg_xhrt_poll_thread_create() + @see mbg_get_xhrt_time_as_pcps_hr_time() + @see mbg_get_xhrt_time_as_filetime() + @see mbg_get_xhrt_cycles_frequency() + */ + _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_stop( MBG_POLL_THREAD_INFO *p_pti ) ; + + /** + @brief Retrieve an extrapolated time stamp in PCPS_HR_TIME format. + + The time stamp is extrapolated using the system's current cycles counter value + and a time stamp plus associated cycles counter value saved by the polling thread. + See mbg_xhrt_poll_thread_fnc() for details and limitations. + + This function is only implemented for targets which support threads. + + @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. + @param *p_hrt Pointer to a ::PCPS_HR_TIME structure to be filled up. + + @return MBG_SUCCESS or another return value from the polling thread's IOCTL call. + + @see mbg_xhrt_poll_thread_fnc() + @see mbg_xhrt_poll_thread_create() + @see mbg_xhrt_poll_thread_stop() + @see mbg_get_xhrt_time_as_filetime() + @see mbg_get_xhrt_cycles_frequency() + */ + _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_pcps_hr_time( MBG_XHRT_INFO *p, PCPS_HR_TIME *p_hrt ) ; + + /** + @brief Retrieve an extrapolated time stamp in FILETIME format. + + The time stamp is extrapolated using the system's current cycles counter value + and a time stamp plus associated cycles counter value saved by the polling thread. + See mbg_xhrt_poll_thread_fnc() for details and limitations. + + Since FILETIME is a Windows specific type this function is only + implemented under Windows. + + @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. + @param *p_ft Pointer to a ::FILETIME structure to be filled up. + + @return MBG_SUCCESS or another return value from the polling thread's IOCTL call. + + @see mbg_xhrt_poll_thread_fnc() + @see mbg_xhrt_poll_thread_create() + @see mbg_xhrt_poll_thread_stop() + @see mbg_get_xhrt_time_as_pcps_hr_time() + @see mbg_get_xhrt_cycles_frequency() + */ + _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_filetime( MBG_XHRT_INFO *p, FILETIME *p_ft ) ; + + /** + @brief Retrieve the frequency of the system's cycles counter. + + The frequency is determined by the device polling thread. + See mbg_xhrt_poll_thread_fnc() for details and limitations. + + This function is only implemented for targets which support threads. + + @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. + @param *p_freq_hz Pointer to a ::MBG_PC_CYCLES_FREQUENCY variable in which the frequency is returned. + @return a status code from the polling thread: MBG_SUCCESS or an IOCTL error code. + + @see mbg_xhrt_poll_thread_fnc() + @see mbg_xhrt_poll_thread_create() + @see mbg_xhrt_poll_thread_stop() + @see mbg_get_xhrt_time_as_pcps_hr_time() + @see mbg_get_xhrt_time_as_filetime() + */ + _MBG_API_ATTR int _MBG_API mbg_get_xhrt_cycles_frequency( MBG_XHRT_INFO *p, MBG_PC_CYCLES_FREQUENCY *p_freq_hz ) ; + + /** + @brief Retrieve the default system's cycles counter frequency from the kernel driver. + + This API call can be used on systems which don't provide this information in user space. + + @param dh handle of the device to which the IOCTL call is sent. + @param *p Pointer of a ::MBG_PC_CYCLES_FREQUENCY variable to be filled up. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. + + @see mbg_get_default_cycles_frequency() + */ + _MBG_API_ATTR int _MBG_API mbg_get_default_cycles_frequency_from_dev( MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p ) ; + + /** + @brief Retrieve the system's default cycles counter frequency. + + @note This may not be supported on all target platforms, in which case the + returned frequency is 0 and the mbg_get_default_cycles_frequency_from_dev() + call should be used. + + @return the default cycles counter frequency in Hz, or 0 if the value is not available. + + @see mbg_get_default_cycles_frequency_from_dev() +*/ + _MBG_API_ATTR MBG_PC_CYCLES_FREQUENCY _MBG_API mbg_get_default_cycles_frequency( void ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#if defined( MBG_TGT_WIN32 ) + +static __mbg_inline +MBGDEVIO_RET_VAL do_mbg_ioctl( MBG_DEV_HANDLE dh, int ioctl_code, + const void *in_p, int in_sz, void *out_p, int out_sz ) +{ + DWORD ReturnedLength; + + if ( !DeviceIoControl( dh, ioctl_code, + (LPVOID) in_p, in_sz, out_p, out_sz, + &ReturnedLength, + NULL + ) ) + { + DWORD rc = GetLastError(); + +#if 0 //##++++++++++++++++++++++++ +// We can't call mbgsvctl_log_mbgdevio_error() here (for now). +// Is is defined in mbgsvctl.h, and including mbgsvc.h here, +// or copying the prototype here results in DLL import/export +// mismatch errors. + + // do not report a USB device timeout error + if ( rc != _mbg_err_to_os( MBG_ERR_USB_ACCESS ) ) + mbgsvctl_log_mbgdevio_error( ioctl_code, rc ); +#endif + + return rc; + } + + return MBG_SUCCESS; + +} // do_mbg_ioctl + + #define _do_mbg_ioctl( _dh, _ioctl, _p, _in_sz, _out_sz ) \ + do_mbg_ioctl( _dh, _ioctl, (LPVOID) _p, _in_sz, (LPVOID) _p, _out_sz ) + +#elif defined( MBG_TGT_UNIX ) + + #define _do_mbg_ioctl( _dh, _ioctl, _p, _in_sz, _out_sz ) \ + ioctl( _dh, _ioctl, _p ) + +#endif + + + +// The code below depends on whether the target device is accessed via +// IOCTLs to a device driver, or the hardware is accessed directly. + +#if defined( MBG_USE_KERNEL_DRIVER ) // using IOCTL to access device driver + +/** + @brief Send a generic IOCTL command to the driver. + + @param dh Valid handle to a Meinberg device + @param info Additional information for the kernel driver depending on + the IOCTL code, i.e. the low level function to be called: <br> + one of the PCPS_... commands with IOCTL_PCPS_GENERIC_{READ|WRITE}<br> + one of the PC_GPS_... commands with IOCTL_PCPS_GENERIC_{READ|WRITE}_GPS<br> + one of the PCPS_GEN_IO_... enumeration codes with IOCTL_PCPS_GENERIC_IO + @param ioctl One of the IOCTL_GENERIC_... codes telling the kernel driver + which low level function to use, e.g. normal read or write, + large (GPS) data read or write, or generic I/O. + @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + + @return ::MBG_SUCCESS or error code returned by device I/O control function. +*/ + static __mbg_inline + int mbgdevio_do_gen_io( MBG_DEV_HANDLE dh, int info, unsigned int ioctl_code, + const void *in_p, int in_sz, + void *out_p, int out_sz ) + { + _mbgdevio_vars(); + + // Generic IOCTL calls always need to pass some info beside + // the I/O buffers down to the driver, which usually is + // the command code for the device. + // Thus we must always use one of the control structures + // IOCTL_GENERIC_REQ or IOCTL_GENERIC_BUFFER, whichever + // is appropriate for the target OS. + + #if USE_IOCTL_GENERIC_REQ + + IOCTL_GENERIC_REQ req = { 0 }; + + req.info = info; + req.in_p = in_p; + req.in_sz = in_sz; + req.out_p = out_p; + req.out_sz = out_sz; + + rc = _do_mbg_ioctl( dh, ioctl_code, &req, sizeof( req ), 0 ); + + #else + + IOCTL_GENERIC_BUFFER *p_buff; + int buff_size = sizeof( p_buff->ctl ) + + ( ( in_sz > out_sz ) ? in_sz : out_sz ); + + p_buff = (IOCTL_GENERIC_BUFFER *) malloc( buff_size ); + + if ( p_buff == NULL ) + return _mbg_err_to_os( MBG_ERR_NO_MEM ); + + p_buff->ctl.info = info; + p_buff->ctl.data_size_in = in_sz; + p_buff->ctl.data_size_out = out_sz; + + if ( in_p ) + memcpy( p_buff->data, in_p, in_sz ); + + rc = _do_mbg_ioctl( dh, ioctl_code, p_buff, + sizeof( IOCTL_GENERIC_CTL ) + in_sz, + sizeof( IOCTL_GENERIC_CTL ) + out_sz ); + + if ( out_p && ( rc == MBG_SUCCESS ) ) + memcpy( out_p, p_buff->data, out_sz ); + + free( p_buff ); + + #endif + + return _mbgdevio_ret_val; + + } // mbgdevio_do_gen_io + + + + #define _do_mbgdevio_read( _dh, _cmd, _ioctl, _p, _sz ) \ + _do_mbg_ioctl( _dh, _ioctl, _p, 0, _sz ) + + #define _do_mbgdevio_write( _dh, _cmd, _ioctl, _p, _sz ) \ + _do_mbg_ioctl( _dh, _ioctl, _p, _sz, 0 ) + + #define _do_mbgdevio_read_gps _do_mbgdevio_read + + #define _do_mbgdevio_write_gps _do_mbgdevio_write + + + + #define _mbgdevio_read_var( _dh, _cmd, _ioctl, _p ) \ + _do_mbgdevio_read( _dh, _cmd, _ioctl, _p, sizeof( *(_p) ) ) + + #define _mbgdevio_write_var( _dh, _cmd, _ioctl, _p ) \ + _do_mbgdevio_write( _dh, _cmd, _ioctl, _p, sizeof( *(_p) ) ) + + #define _mbgdevio_write_cmd( _dh, _cmd, _ioctl ) \ + _do_mbgdevio_write( _dh, _cmd, _ioctl, NULL, 0 ) + + #define _mbgdevio_read_gps_var _mbgdevio_read_var + + #define _mbgdevio_write_gps_var _mbgdevio_write_var + + + #define _mbgdevio_gen_read( _dh, _cmd, _p, _sz ) \ + mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_READ, NULL, 0, _p, _sz ) + + #define _mbgdevio_gen_write( _dh, _cmd, _p, _sz ) \ + mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_WRITE, _p, _sz, NULL, 0 ) + + #define _mbgdevio_gen_io( _dh, _type, _in_p, _in_sz, _out_p, _out_sz ) \ + mbgdevio_do_gen_io( _dh, _type, IOCTL_PCPS_GENERIC_IO, _in_p, _in_sz, _out_p, _out_sz ) + + #define _mbgdevio_gen_read_gps( _dh, _cmd, _p, _sz ) \ + mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_READ_GPS, NULL, 0, _p, _sz ) + + #define _mbgdevio_gen_write_gps( _dh, _cmd, _p, _sz ) \ + mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_WRITE_GPS, _p, _sz, NULL, 0 ) + + +#else // accessing hardware device directly + + #define _mbgdevio_chk_cond( _cond ) \ + { \ + if ( !(_cond) ) \ + return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); \ + } + + #define _mbgdevio_read( _dh, _cmd, _ioctl, _p, _sz ) \ + pcps_read_safe( _dh, _cmd, _p, _sz ) + + #define _mbgdevio_write( _dh, _cmd, _ioctl, _p, _sz ) \ + pcps_write_safe( _dh, _cmd, _p, _sz ) + + #define _do_mbgdevio_read_gps( _dh, _cmd, _ioctl, _p, _sz ) \ + pcps_read_gps_safe( _dh, _cmd, _p, _sz ) + + #define _mbgdevio_write_gps( _dh, _cmd, _ioctl, _p, _sz ) \ + pcps_write_gps_safe( _dh, _cmd, _p, _sz ) + + + +//##+++++++++++++++++++ + #define _mbgdevio_read_var( _dh, _cmd, _ioctl, _p ) \ + _pcps_read_var_safe( _dh, _cmd, *(_p) ) + + #define _mbgdevio_write_var( _dh, _cmd, _ioctl, _p ) \ + _pcps_write_var_safe( _dh, _cmd, *(_p) ) + + #define _mbgdevio_write_cmd( _dh, _cmd, _ioctl ) \ + _pcps_write_byte_safe( _dh, _cmd ); + + #define _mbgdevio_read_gps_var( _dh, _cmd, _ioctl, _p ) \ + _pcps_read_gps_var_safe( _dh, _cmd, *(_p) ) + + #define _mbgdevio_write_gps_var( _dh, _cmd, _ioctl, _p ) \ + _pcps_write_gps_var_safe( _dh, _cmd, *(_p) ) + + + #define _mbgdevio_gen_read( _dh, _cmd, _p, _sz ) \ + _mbgdevio_read( _dh, _cmd, -1, _p, _sz ) + + #define _mbgdevio_gen_write( _dh, _cmd, _p, _sz ) \ + _mbgdevio_write( _dh, _cmd, -1, _p, _sz ) + + #define _mbgdevio_gen_io( _dh, _type, _in_p, _in_sz, _out_p, _out_sz ) \ + pcps_generic_io( _dh, _type, _in_p, _in_sz, _out_p, _out_sz ); + + #define _mbgdevio_gen_read_gps( _dh, _cmd, _p, _sz ) \ + _do_mbgdevio_read_gps( _dh, _cmd, -1, _p, _sz ) + + #define _mbgdevio_gen_write_gps( _dh, _cmd, _p, _sz ) \ + _mbgdevio_write_gps( _dh, _cmd, -1, _p, _sz ) + +#endif + + + +#define _mbg_generic_read_var( _dh, _cmd, _s ) \ + mbg_generic_read( _dh, _cmd, &(_s), sizeof( (_s) ) ) + +#define _mbg_generic_write_var( _dh, _cmd, _s ) \ + mbg_generic_write( _dh, _cmd, &(_s), sizeof( (_s) ) ) + +#define _mbg_generic_read_gps_var( _dh, _cmd, _s ) \ + mbg_generic_read_gps( _dh, _cmd, &(_s), sizeof( (_s) ) ) + +#define _mbg_generic_write_gps_var( _dh, _cmd, _s ) \ + mbg_generic_write_gps( _dh, _cmd, &(_s), sizeof( (_s) ) ) + + + +#define _mbgdevio_gen_read_var( _dh, _cmd, _s ) \ + _mbgdevio_gen_read( _dh, _cmd, &(_s), sizeof( (_s) ) ) + +#define _mbgdevio_gen_write_var( _dh, _cmd, _s ) \ + _mbgdevio_gen_write( _dh, _cmd, &(_s), sizeof( (_s) ) ) + +#define _mbgdevio_gen_read_gps_var( _dh, _cmd, _s ) \ + _mbgdevio_gen_read_gps( _dh, _cmd, &(_s), sizeof( (_s) ) ) + +#define _mbgdevio_gen_write_gps_var( _dh, _cmd, _s ) \ + _mbgdevio_gen_write_gps( _dh, _cmd, &(_s), sizeof( (_s) ) ) + + + +#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX ) + +static __mbg_inline +void mbg_chk_tstamp64_leap_sec( uint64_t *tstamp64, PCPS_TIME_STATUS_X *status ) +{ + if ( *status & ( PCPS_LS_ANN | PCPS_LS_ENB ) ) + { + time_t t = (uint32_t) ( *tstamp64 >> 32 ); + struct tm tm = *gmtime( &t ); + + // Handle leap second and status + if ( tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0 ) + { + if ( *status & PCPS_LS_ANN ) + { + // Set leap second enabled flag on rollover to the leap second and clear announce flag + *status &= ~PCPS_LS_ANN; + *status |= PCPS_LS_ENB; + + // Decrement interpolated second to avoid automated overflow during the leap second. + // Second 59 appears for the second time. + *tstamp64 -= PCPS_HRT_BIN_FRAC_SCALE; + } + else + if ( *status & PCPS_LS_ENB ) // Clear bits when leap second expires and 0:00:00 UTC is reached + *status &= ~( PCPS_LS_ANN | PCPS_LS_ENB ); + } + } + +} // mbg_chk_tstamp64_leap_sec + +#endif // defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX ) + + + +static __mbg_inline +void mbg_init_pc_cycles_frequency( MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p ) +{ + if ( *p == 0 ) + mbg_get_default_cycles_frequency_from_dev( dh, p ); + +} // mbg_init_pc_cycles_frequency + + + +#if MBG_TGT_HAS_64BIT_TYPES + +static __mbg_inline +uint64_t pcps_time_stamp_to_uint64( const PCPS_TIME_STAMP *ts ) +{ + return ( ( (uint64_t) ts->sec ) << 32 ) + ts->frac; + +} // pcps_time_stamp_to_uint64 + + + +static __mbg_inline +void uint64_to_pcps_time_stamp( PCPS_TIME_STAMP *ts, uint64_t n ) +{ + ts->sec = (uint32_t) ( n >> 32 ); + ts->frac = (uint32_t) ( n & 0xFFFFFFFFUL ); + +} // uint64_to_pcps_time_stamp + +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + + +#undef _ext + +#endif /* _MBGDEVIO_H */ + diff --git a/mbglib/common/mbgerror.h b/mbglib/common/mbgerror.h new file mode 100644 index 0000000..f15878d --- /dev/null +++ b/mbglib/common/mbgerror.h @@ -0,0 +1,172 @@ + +/************************************************************************** + * + * $Id: mbgerror.h 1.6 2012/10/02 18:42:26Z martin REL_M $ + * $Name: $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Error codes used with Meinberg devices and drivers. + * The codes can be translated into an OS dependent error code. + * + * ----------------------------------------------------------------------- + * $Log: mbgerror.h $ + * Revision 1.6 2012/10/02 18:42:26Z martin + * New codes MBG_ERR_N_POUT_EXCEEDS_SUPP and + * MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP. + * Modified comments for doxygen. + * Revision 1.5 2011/03/31 10:56:17 martin + * Added MBG_ERR_COPY_TO_USER and MBG_ERR_COPY_FROM_USER. + * Revision 1.4 2008/12/05 13:28:50 martin + * Added new code MBG_ERR_IRQ_UNSAFE. + * Revision 1.3 2008/02/26 14:50:14Z daniel + * Added codes: + * MBG_ERR_NOT_SUPP_ON_OS, MBG_ERR_LIB_NOT_COMPATIBLE, + * MBG_ERR_N_COM_EXCEEDS_SUPP, MBG_ERR_N_STR_EXCEEDS_SUPP + * Added doxygen compatible comments. + * Revision 1.2 2007/09/27 07:26:22Z martin + * Define STATUS_SUCCESS for Windows if not in kernel mode. + * Revision 1.1 2007/09/26 08:08:54Z martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBGERROR_H +#define _MBGERROR_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> + +#ifdef _MBGERROR + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +/** + @defgroup group_error_codes Error codes + + Error codes used with Meinberg devices and drivers. + The codes will be translated into an OS dependent error code, + when they are returned to the calling function. + + For Windows, these codes are made positive and or'ed with 0xE0000000 afterwards. + + Example: Code -19 (#MBG_ERR_GENERIC) will be converted to 0xE0000013 under Windows. + + @note Attention: + These error codes below must match exactly the corresponding codes that are evaluated in user space. + For Windows, they are located in messages.mc/.h in mbgsvctl.dll + + @{ +*/ + + +#define MBG_SUCCESS PCPS_SUCCESS /**< 0, no error */ + +// The codes below are defined in pcpsdefs.h and returned by the firmware: +#define MBG_ERR_STIME PCPS_ERR_STIME /**< -1, invalid date/time/status passed */ +#define MBG_ERR_CFG PCPS_ERR_CFG /**< -2, invalid parms with a PCPS_CFG_GROUP cmd */ + +// Codes returned by the driver's low level functions: +#define MBG_ERR_GENERIC -19 /**< Generic error */ +#define MBG_ERR_TIMEOUT -20 /**< Timeout accessing the board */ +#define MBG_ERR_FW_ID -21 /**< Invalid firmware ID */ +#define MBG_ERR_NBYTES -22 /**< The number of parameter bytes + passed to the board did not match + the number of bytes expected. */ +#define MBG_ERR_INV_TIME -23 /**< The device's time is not valid */ +#define MBG_ERR_FIFO -24 /**< The device's FIFO is empty, though + it shouldn't be */ +#define MBG_ERR_NOT_READY -25 /**< Board is temporary unable to respond + (during initialization after RESET) */ +#define MBG_ERR_INV_TYPE -26 /**< Board did not recognize data type */ + + +// Codes returned by the driver's high level functions: +#define MBG_ERR_NO_MEM -27 /**< Failed to allocate memory */ +#define MBG_ERR_CLAIM_RSRC -28 /**< Failed to claim port or mem resource */ +#define MBG_ERR_DEV_NOT_SUPP -29 /**< Specified device type not supported by driver */ +#define MBG_ERR_INV_DEV_REQUEST -30 /**< IOCTL call not supported by driver */ +#define MBG_ERR_NOT_SUPP_BY_DEV -31 /**< Cmd or feature not supported by device */ +#define MBG_ERR_USB_ACCESS -32 /**< USB access failed */ +#define MBG_ERR_CYCLIC_TIMEOUT -33 /**< Cyclic event (IRQ, etc.) didn't occur */ +#define MBG_ERR_NOT_SUPP_ON_OS -34 /**< The function is not supported on this operating system */ +#define MBG_ERR_LIB_NOT_COMPATIBLE -35 /**< The installed version of the DLL/shared object is not + compatible with version used to build the application */ +#define MBG_ERR_N_COM_EXCEEDS_SUPP -36 /**< The number of COM ports provided by the device + exceeds the maximum supported by the driver */ +#define MBG_ERR_N_STR_EXCEEDS_SUPP -37 /**< The number of string formats supported by the device + exceeds the maximum supported by the driver */ +#define MBG_ERR_IRQ_UNSAFE -38 /**< The enabled IRQs are unsafe with this firmware/ASIC version */ +#define MBG_ERR_N_POUT_EXCEEDS_SUPP -39 /**< The number of programmable outputs provided by the device + exceeds the maximum supported by the driver */ + +// Legacy codes used with DOS TSRs only: +#define MBG_ERR_INV_INTNO -40 /**< Invalid interrupt number */ +#define MBG_ERR_NO_DRIVER -41 /**< A driver could not be found */ +#define MBG_ERR_DRV_VERSION -42 /**< The driver is too old */ + + +#define MBG_ERR_COPY_TO_USER -43 /**< kernel driver failed to copy data from kernel to user space */ +#define MBG_ERR_COPY_FROM_USER -44 /**< kernel driver failed to copy data from use to kernel space */ + +// More codes returned by the driver's high level functions: + +#define MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP -39 /**< The number of PTP unicast masters supported by the device + exceeds the maximum supported by the driver */ +/** @} group_error_codes */ + +// Depending on the operating system, the codes above have to be converted before +// they are sent up to user space +#if defined( MBG_TGT_WIN32 ) + #if !defined( STATUS_SUCCESS ) // not in kernel mode + #define STATUS_SUCCESS 0 + #endif + + #define _mbg_err_to_os( _c ) \ + ( ( _c == MBG_SUCCESS ) ? STATUS_SUCCESS : ( abs( _c ) | 0xE0000000 ) ) +#endif + + +// If no specific conversion has been defined +// then use the original codes. +#if !defined( _mbg_err_to_os ) + #define _mbg_err_to_os( _c ) ( _c ) +#endif + + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + +/* (no header definitions found) */ + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBGERROR_H */ diff --git a/mbglib/common/mbggeo.h b/mbglib/common/mbggeo.h new file mode 100644 index 0000000..c3bdb40 --- /dev/null +++ b/mbglib/common/mbggeo.h @@ -0,0 +1,301 @@ + +/************************************************************************** + * + * $Id: mbggeo.h 1.11 2011/06/22 10:18:10Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for mbggeo.c. + * + * Terms used: + * + * WGS84 world geodetic system of 1984 + * + * XYZ WGS84 earth centered, earth fixed (ECEF) kartesian + * coordinates + * + * LLA longitude, latitude, altitude depending on the reference + * ellipsoid used. + * + * DMS degrees, minutes, seconds + * + * ----------------------------------------------------------------------- + * $Log: mbggeo.h $ + * Revision 1.11 2011/06/22 10:18:10Z martin + * Cleaned up handling of pragma pack(). + * Revision 1.10 2008/09/03 14:54:28 martin + * Added macros to swap endianess of structures. + * Revision 1.9 2008/01/17 09:31:33 daniel + * 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. + * Revision 1.6 2003/01/13 15:17:15 martin + * Structures were defined with default alignment which + * could result in different data sizes on different platforms. + * Revision 1.5 2002/12/18 14:46:41Z martin + * Removed variable USER_POS meinberg. + * Updated function prototypes. + * Revision 1.4 2002/12/12 12:04:25Z martin + * Moved some definitions here. + * Use standard file format. + * + **************************************************************************/ + +#ifndef _MBGGEO_H +#define _MBGGEO_H + + +/* Other headers to be included */ + +#include <gpsdefs.h> +#include <use_pack.h> + +#ifdef _MBGGEO + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + + +/** + 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] */ +} 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 */ +} 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 +{ + CSUM csum; /* checksum of the remaining bytes */ + int16_t valid; /* flag data are valid */ + + char name[40]; + POS pos; /* the position in WGS84 ECEF coords and LLA */ + double det; + + +/* The components below hold the results of intermediate terms */ +/* computed in complete_user_pos(). */ + +/* The sin.., cos.., nt.. and ut.. variables are used to compute the */ +/* enu_dcos[] parameters of a SV structure in xyz_to_ead(). */ + +/* The e_radius.. variables are used to compute the latitude, longitude */ +/* and altitude from ECEF coordinates in lla_to_xyz(). */ + + double sin_lat; /* sin( latitude ) */ + double cos_lat; /* cos( latitude ) */ + double sin_lon; /* sin( longitude ) */ + double cos_lon; /* cos( longitude ) */ + + double nt1; /* -sin_lat * cos_lon */ + double nt2; /* -sin_lat * sin_lon */ + double utx; /* cos_lat * cos_lon */ + double uty; /* cos_lat * sin_lon */ + + double e_radius; /* N */ + double e_radius_alt; /* N + h */ + +} USER_POS; + + + +typedef struct +{ + CSUM csum; /* checksum of the remaining bytes */ + int16_t valid; /* flag data are valid */ + + char name[40]; + XYZ dxyz; /* offset from the WGS84 ECEF coords */ + double a; /* semi major axis */ + double rcp_f; /* reciproke of flatness */ + +/* the variables below will be computed in the init_mbggeo() function: */ + + double f; /* flatness */ + double b; /* semi minor axis */ + double sqr_e; /* square of numerical eccentricity */ +} ELLIPSOID; + + + +enum { WGS84, BESSEL, N_ELLIPSOIDS }; + +_ext ELLIPSOID ellipsoid[N_ELLIPSOIDS] +#ifdef _DO_INIT + = { { 0, 0, + "WGS 84", + { 0.0, 0.0, 0.0 }, + 6378137.0, + 298.257223563 + }, + + { 0, 0, + "Bessel", + { -128.0, 481.0, 664.0 }, + 6377397.0, + 299.15 + } + + } +#endif +; + + +/* WGS84 constants used */ + +_ext double OMEGADOTe /* earth's rotation rate [rad/sec] */ +#ifdef _DO_INIT + = 7.2921151467e-5 +#endif +; + +_ext double mue /* earth's gravitational constant [m^3/sec^2] */ +#ifdef _DO_INIT + = 3.986005e14 +#endif +; + + + +_ext double vr_to_doppler; + + +_ext double gps_pi +#ifdef _DO_INIT + = 3.1415926535898 +#endif +; + +_ext double gps_c0 +#ifdef _DO_INIT + = 2.99792458e8 +#endif +; + + +#ifndef PI + #define PI 3.1415926535897932 +#endif + + +_ext double pi +#ifdef _DO_INIT + = PI +#endif +; + + +_ext double r2d +#ifdef _DO_INIT + = 180.0 / PI +#endif +; + + +_ext double d2r +#ifdef _DO_INIT + = PI / 180.0 +#endif +; + + +/* variables for simplifying computations */ + +_ext double gps_two_pi; +_ext double sqrt_mue; /* sqrt( mue ) */ + + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + void dms_to_rad( const DMS *dms, double *rad ) ; + void rad_to_dms( const double *rad, DMS *dms, const char prefix ) ; + void dms_to_lla( POS *pos ) ; + void lla_to_dms( POS *pos ) ; + void lla_to_xyz( USER_POS *pos ) ; + void xyz_to_lla( POS *pos, void (*cyclic_func)( void ) ) ; + void dms_to_xyz( USER_POS *pos ) ; + void setup_user_pos_from_dms( USER_POS *user ) ; + void setup_user_pos_from_lla( USER_POS *user ) ; + void setup_user_pos_from_xyz( USER_POS *user, void (*cyclic_func)( void ) ) ; + double distance( XYZ xyz_1, XYZ xyz_2 ) ; + void init_mbggeo( void ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBGGEO_H */ + diff --git a/mbglib/common/mbgmutex.h b/mbglib/common/mbgmutex.h new file mode 100644 index 0000000..86fd058 --- /dev/null +++ b/mbglib/common/mbgmutex.h @@ -0,0 +1,259 @@ + +/************************************************************************** + * + * $Id: mbgmutex.h 1.2 2012/03/08 12:19:01Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Portable macros to deal with spinlocks, mutexes, + * and critical sections. + * + * ----------------------------------------------------------------------- + * $Log: mbgmutex.h $ + * Revision 1.2 2012/03/08 12:19:01Z martin + * Fixes for Linux kernel and FreeBSD. + * Fixed build under DOS and QNX usinc dummy defines. + * Don't define macros for semaphore destroy functions + * if not required/supported on the target OS. + * Revision 1.1 2011/04/15 12:26:59 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBGMUTEX_H +#define _MBGMUTEX_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> +#include <words.h> + +#ifdef _MBGMUTEX + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( MBG_TGT_KERNEL ) // definitions used in kernel space + + #if defined( MBG_TGT_WIN32 ) // Windows kernel space + + typedef KSPIN_LOCK MBG_SPINLOCK; + #define _mbg_spin_lock_init( _spl ) KeInitializeSpinLock( _spl ) + // _mbg_spin_lock_destroy is not supported + #define _mbg_spin_lock_acquire( _spl ) KeAcquireSpinLockAtDpcLevel( _spl ) + #define _mbg_spin_lock_release( _spl ) KeReleaseSpinLockFromDpcLevel( _spl ) + + #define _MBG_SPINLOCK_DEFINED 1 + + + typedef FAST_MUTEX MBG_MUTEX; + #define _mbg_mutex_init( _pmtx ) ExInitializeFastMutex( _pmtx ) + // _mbg_mutex_destroy( _pmtx ) is not supported + #define _mbg_mutex_acquire( _pmtx ) ExAcquireFastMutex( _pmtx ) + #define _mbg_mutex_release( _pmtx ) ExReleaseFastMutex( _pmtx ) + + #define _MBG_MUTEX_DEFINED 1 + + #elif defined( MBG_TGT_LINUX ) // Linux kernel space + + #include <linux/spinlock.h> + #include <linux/version.h> + + #if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 26 ) ) + #include <linux/semaphore.h> + #else + #include <asm/semaphore.h> + #endif + + typedef spinlock_t MBG_SPINLOCK; + #define _mbg_spin_lock_init( _spl ) spin_lock_init( _spl ) + // _mbg_spin_lock_destroy is not supported + #define _mbg_spin_lock_acquire( _spl ) spin_lock( _spl ) + #define _mbg_spin_lock_release( _spl ) spin_unlock( _spl ) + + #define _MBG_SPINLOCK_DEFINED 1 + + + typedef struct semaphore MBG_MUTEX; + #define _mbg_mutex_init( _pmtx ) sema_init( _pmtx, 1 ) + // _mbg_mutex_destroy( _pmtx ) is not supported + #define _mbg_mutex_acquire( _pmtx ) down_interruptible( _pmtx ) + #define _mbg_mutex_release( _pmtx ) up( _pmtx ) + + #define _MBG_MUTEX_DEFINED 1 + + #elif defined( MBG_TGT_FREEBSD ) // FreeBSD kernel space + + #include <sys/lock.h> + #include <sys/mutex.h> + + typedef struct mtx MBG_SPINLOCK; + #define _mbg_spin_lock_init( _spl ) mtx_init( _spl, "mbg_spin_lock", NULL, MTX_SPIN ) + #define _mbg_spin_lock_destroy( _spl ) mtx_destroy( _spl ) + #define _mbg_spin_lock_acquire( _spl ) mtx_lock_spin( _spl ) + #define _mbg_spin_lock_release( _spl ) mtx_unlock_spin( _spl ) + + #define _MBG_SPINLOCK_DEFINED 1 + + + typedef struct mtx MBG_MUTEX; + #define _mbg_mutex_init( _pmtx ) mtx_init( _pmtx, "mbg_mutex", NULL, MTX_DEF ) + #define _mbg_mutex_destroy( _pmtx ) mtx_destroy( _pmtx ) + #define _mbg_mutex_acquire( _pmtx ) mtx_lock( _pmtx ) + #define _mbg_mutex_release( _pmtx ) mtx_unlock( _pmtx ) + + #define _MBG_MUTEX_DEFINED 1 + + #elif defined( MBG_TGT_NETBSD ) + + #include <sys/mutex.h> + + // The API used below has been introduced in NetBSD 5.0 + // For earlier NetBSD versions see 'man 9 lockinit'. + + typedef kmutex_t MBG_SPINLOCK; + #define _mbg_spin_lock_init( _spl ) mutex_init( _spl, MUTEX_DEFAULT, IPL_HIGH ) + #define _mbg_spin_lock_destroy( _spl ) mutex_destroy( _spl ) + #define _mbg_spin_lock_acquire( _spl ) mutex_spin_enter( _spl ) + #define _mbg_spin_lock_release( _spl ) mutex_spin_exit( _spl ) + + #define _MBG_SPINLOCK_DEFINED 1 + + + typedef kmutex_t MBG_MUTEX; + #define _mbg_mutex_init( _pmtx ) mutex_init( _pmtx, MUTEX_DEFAULT, IPL_NONE ) + #define _mbg_mutex_destroy( _spl ) mutex_destroy( _spl ) + #define _mbg_mutex_acquire( _pmtx ) mutex_enter( _pmtx ) + #define _mbg_mutex_release( _pmtx ) mutex_exit( _pmtx ) + + #define _MBG_MUTEX_DEFINED 1 + + #endif + +#else // user space applications + + #if defined( MBG_TGT_WIN32 ) // Windows user space + + #include <windows.h> + + // definitions used with mutexes + typedef HANDLE MBG_MUTEX; + #define _mbg_mutex_init( _pm ) *(_pm) = CreateMutex( NULL, FALSE, NULL ) + #define _mbg_mutex_destroy( _pm ) CloseHandle( *(_pm) ); *(_pm) = INVALID_HANDLE_VALUE + #define _mbg_mutex_acquire( _pm ) WaitForSingleObject( *(_pm), INFINITE ) + #define _mbg_mutex_release( _pm ) ReleaseMutex( *(_pm) ) + + #define _MBG_MUTEX_DEFINED 1 + + // definitions used with critical sections + typedef CRITICAL_SECTION MBG_CRIT_SECT; + #define _mbg_crit_sect_init( _pcs ) InitializeCriticalSection( (_pcs) ) + #define _mbg_crit_sect_destroy( _pcs ) DeleteCriticalSection( (_pcs) ) + #define _mbg_crit_sect_enter( _pcs ) EnterCriticalSection( (_pcs) ) + #define _mbg_crit_sect_leave( _pcs ) LeaveCriticalSection( (_pcs) ) + + #define _MBG_CRIT_SECT_DEFINED 1 + + #elif defined( MBG_TGT_UNIX ) // Unix user space use pthread library + + #include <pthread.h> + + // Mutex types: + // PTHREAD_MUTEX_INITIALIZER /* Fast */ + // PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP /* Recursive */ + // PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP /* Errorcheck */ + typedef pthread_mutex_t MBG_MUTEX; + #define _mbg_mutex_init( _pm ) pthread_mutex_init( (_pm), NULL ) + #define _mbg_mutex_destroy( _pm ) pthread_mutex_destroy( (_pm) ) + #define _mbg_mutex_acquire( _pm ) pthread_mutex_lock( (_pm) ) + #define _mbg_mutex_release( _pm ) pthread_mutex_unlock( (_pm) ) + + #define _MBG_MUTEX_DEFINED 1 + + // For critical sections use defaults specified below + + #elif defined( MBG_TGT_DOS ) || defined( MBG_TGT_QNX ) + + typedef int MBG_MUTEX; // just a dummy declaration + + #define _MBG_MUTEX_DEFINED 1 + + #endif + +#endif + + +#if !defined( _MBG_SPINLOCK_DEFINED ) + + #define _mbg_spin_lock_init( _spl ) _nop_macro_fnc() + // _mbg_spin_lock_destroy is not supported + #define _mbg_spin_lock_acquire( _spl ) _nop_macro_fnc() + #define _mbg_spin_lock_release( _spl ) _nop_macro_fnc() + +#endif + + +#if !defined( _MBG_MUTEX_DEFINED ) + + #define _MBG_MUTEX_DEFINED 1 + + typedef MBG_CRIT_SECT MBG_MUTEX; + + #define _mbg_mutex_init( _pm ) _nop_macro_fnc() + // _mbg_mutex_destroy( _pmtx ) is not supported + #define _mbg_mutex_acquire( _pm ) _nop_macro_fnc() + #define _mbg_mutex_release( _pm ) _nop_macro_fnc() + +#endif + + +#if !defined( _MBG_CRIT_SECT_DEFINED ) + + // use mutex by default, e.g. with the pthread library + + #define _MBG_CRIT_SECT_DEFINED 1 + + typedef MBG_MUTEX MBG_CRIT_SECT; + #define _mbg_crit_sect_init _mbg_mutex_init + #if defined( _mbg_mutex_destroy ) + #define _mbg_crit_sect_destroy _mbg_mutex_destroy + #endif + #define _mbg_crit_sect_enter _mbg_mutex_acquire + #define _mbg_crit_sect_leave _mbg_mutex_release + +#endif + + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + +/* (no header definitions found) */ + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBGMUTEX_H */ diff --git a/mbglib/common/mbgpccyc.h b/mbglib/common/mbgpccyc.h new file mode 100644 index 0000000..71d1235 --- /dev/null +++ b/mbglib/common/mbgpccyc.h @@ -0,0 +1,305 @@ + +/************************************************************************** + * + * $Id: mbgpccyc.h 1.2 2012/03/12 13:45:57Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Portable macros to get a machine's current cycle count. + * + * ----------------------------------------------------------------------- + * $Log: mbgpccyc.h $ + * Revision 1.2 2012/03/12 13:45:57Z martin + * Added cycles support for Linux/IA64, FreeBSD and NetBSD + * in kernel space. + * Use get_cycles() in Linux kernel mode if no special cycles support + * is provided for the given hardware platform. + * Revision 1.1 2011/06/23 15:36:07 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBGPCCYC_H +#define _MBGPCCYC_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> +#include <words.h> + +#if defined( MBG_TGT_NETBSD ) + #if defined( MBG_TGT_KERNEL ) + #include <machine/cpu.h> + #include <machine/cpu_counter.h> /* for cycle counter abstraction */ + #endif +#endif + +#if defined( MBG_TGT_FREEBSD ) + #if defined( MBG_TGT_KERNEL ) + #if defined( MBG_ARCH_X86 ) + #include <machine/clock.h> /* for symbol 'tsc_freq' */ + #endif + #endif +#endif + +#if defined( MBG_TGT_LINUX ) + #if defined( MBG_ARCH_IA64 ) && defined( MBG_TGT_KERNEL ) + #include <asm/ia64regs.h> + #endif +#endif + + +#ifdef _MBGPCCYC + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +/** + * @brief Generic types to hold PC cycle counter values. + * + * The cycle counter value is usually derived from the PC CPU's TSC or some other + * timer hardware on the mainboard. + */ +#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX ) + + typedef int64_t MBG_PC_CYCLES; + typedef uint64_t MBG_PC_CYCLES_FREQUENCY; + +#else + + typedef uint32_t MBG_PC_CYCLES; + typedef uint32_t MBG_PC_CYCLES_FREQUENCY; + +#endif + + +// MBG_PC_CYCLES and MBG_PC_CYCLES_FREQUENCY are always read in native +// machine endianess, so no endianess conversion is required. +#define _mbg_swab_mbg_pc_cycles( _p ) \ + _nop_macro_fnc() + +#define _mbg_swab_mbg_pc_cycles_frequency( _p ) \ + _nop_macro_fnc() + + + +#if ( defined( MBG_TGT_LINUX ) || defined( MBG_TGT_BSD ) ) && defined( MBG_ARCH_X86 ) + + static __mbg_inline unsigned long long int mbg_rdtscll( void ) + { + // The code below is a hack to get around issues with + // different versions of gcc. + // + // Normally the inline asm code could look similar to: + // + // __asm__ volatile ( "rdtsc" : "=A" (x) ) + // + // which would copy the output regs edx:eax as a 64 bit + // number to a variable x. + // + // The "=A" expression should implicitely tell the compiler + // the edx and eax registers have been clobbered. However, + // this does not seem to work properly at least with gcc 4.1.2 + // shipped with Centos 5. + // + // If optimization level 1 or higher is used then function + // parameters are also passed in registers. If the inline + // code above is used inside a function then the edx register + // is clobbered but the gcc 4.1.2 is not aware of this and + // assumes edx is unchanged, which may yield faulty results + // or even lead to segmentation faults. + // + // A possible workaround could be to mark edx explicitely as + // being clobbered in the asm inline code, but unfortunately + // other gcc versions report an error if a register which is + // implicitely (by "=A") known to be clobbered is also listed + // explicitely to be clobbered. + // + // So the code below is a workaround which tells the compiler + // implicitely that the eax ("=a") and edx ("=d") registers + // are being used and thus clobbered. + + union + { + struct + { + uint32_t lo; + uint32_t hi; + } u32; + + uint64_t u64; + + } tsc_val; + + __asm__ __volatile__( "rdtsc" : "=a" (tsc_val.u32.lo), "=d" (tsc_val.u32.hi) ); + + return tsc_val.u64; + + } // mbg_rdtscll + +#endif + + + +static __mbg_inline +void mbg_get_pc_cycles( MBG_PC_CYCLES *p ) +{ +#if !defined( OMIT_PC_CYCLES_SUPPORT ) + + #if defined( MBG_TGT_WIN32 ) + + #if defined( MBG_TGT_KERNEL ) // kernel space + *p = (MBG_PC_CYCLES) KeQueryPerformanceCounter( NULL ).QuadPart; + #else // user space + QueryPerformanceCounter( (LARGE_INTEGER *) p ); + #endif + + #define MBG_PC_CYCLES_SUPPORTED 1 + + #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_X86 ) + + *p = mbg_rdtscll(); + #define MBG_PC_CYCLES_SUPPORTED 1 + + #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_IA64 ) && defined( MBG_TGT_KERNEL ) + + unsigned long result = ia64_getreg( _IA64_REG_AR_ITC ); + ia64_barrier(); + + #ifdef CONFIG_ITANIUM + while (unlikely((__s32) result == -1)) { + result = ia64_getreg(_IA64_REG_AR_ITC); + ia64_barrier(); + } + #endif + + *p = result; + + #define MBG_PC_CYCLES_SUPPORTED 1 + + #elif defined( MBG_TGT_LINUX ) && defined( MBG_TGT_KERNEL ) + + *p = get_cycles(); + #define MBG_PC_CYCLES_SUPPORTED 1 + + #elif defined( MBG_TGT_FREEBSD ) && defined( MBG_ARCH_X86 ) + + *p = mbg_rdtscll(); + + #define MBG_PC_CYCLES_SUPPORTED 1 + + #elif defined( MBG_TGT_NETBSD ) && defined ( MBG_TGT_KERNEL ) + + *p = cpu_counter(); //##++ or cpu_counter_serializing() + + #define MBG_PC_CYCLES_SUPPORTED 1 + + #endif + +#endif + + + #if !defined( MBG_PC_CYCLES_SUPPORTED ) + + *p = 0; + #define MBG_PC_CYCLES_SUPPORTED 0 + + #endif + +} // mbg_get_pc_cycles + + + +static __mbg_inline +void mbg_get_pc_cycles_frequency( MBG_PC_CYCLES_FREQUENCY *p ) +{ + #if defined( MBG_TGT_WIN32 ) + LARGE_INTEGER li; + + #if defined( MBG_TGT_KERNEL ) // kernel space + KeQueryPerformanceCounter( &li ); + #else // user space + QueryPerformanceFrequency( &li ); + #endif + + *p = li.QuadPart; + + #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_X86 ) && defined( MBG_TGT_KERNEL ) + + *p = ( cpu_khz * 1000 ); + + #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_IA64 ) + + // we probably can use + // ia64_sal_freq_base(unsigned long which, unsigned long *ticks_per_second, + // unsigned long *drift_info) + // However, this is not tested. + + *p = 0; + + #elif defined( MBG_TGT_FREEBSD ) && defined( MBG_ARCH_X86 ) && defined( MBG_TGT_KERNEL ) + + *p = tsc_freq; + + #elif defined( MBG_TGT_NETBSD ) && defined( MBG_TGT_KERNEL ) + + *p = cpu_frequency( curcpu() ); + + #else + + *p = 0; + + #endif + +} // mbg_get_pc_cycles_frequency + + + +static __mbg_inline +MBG_PC_CYCLES mbg_delta_pc_cycles( const MBG_PC_CYCLES *p1, const MBG_PC_CYCLES *p2 ) +{ +#if 0 && !MBG_PC_CYCLES_SUPPORTED + // Cycle counts not supported on this target platform. + // Under SPARC this may even result in bus errors + // due to alignment of the underlying data structures. + return 0; +#else + return *p1 - *p2; +#endif + +} // mbg_delta_pc_cycles + + + +/* 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 /* _MBGPCCYC */ diff --git a/mbglib/common/mbgtime.h b/mbglib/common/mbgtime.h new file mode 100644 index 0000000..7b9d2f4 --- /dev/null +++ b/mbglib/common/mbgtime.h @@ -0,0 +1,322 @@ + +/************************************************************************** + * + * $Id: mbgtime.h 1.18 2012/10/02 18:51:11Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for mbgtime.c. + * + * ----------------------------------------------------------------------- + * $Log: mbgtime.h $ + * Revision 1.18 2012/10/02 18:51:11Z martin + * Include <time.h> for WIN32 target and firmware only + * Fixed build under QNX, DOS, and FreeBSD. + * Revision 1.17 2010/08/06 13:03:03 martin + * Removed obsolete code. + * Revision 1.16 2010/07/16 10:22:07Z martin + * Moved definitions of HNS_PER_SEC and HNS_PER_MS here. + * Conditionally define FILETIME_1970. + * Defined MASK_CLOCK_T for ARM/Cortex. + * Revision 1.15 2009/10/23 09:55:21 martin + * Added MJD numbers for commonly used epochs. + * Revision 1.14 2009/08/12 10:28:12 daniel + * Added definition NSECS_PER_SEC. + * Revision 1.13 2009/06/12 13:31:44Z martin + * Fix build errors with arm-linux-gcc. + * Revision 1.12 2009/03/27 14:14:00 martin + * Cleanup for CVI. + * Revision 1.11 2009/03/13 09:30:06Z martin + * Include mystd.h in mbgtime.c rather than here. The bit type used + * here is now defined in words.h. + * Updated comments for GPS_SEC_BIAS. + * Revision 1.10 2008/12/11 10:45:41Z martin + * Added clock_t mask for gcc (GnuC). + * Revision 1.9 2006/08/25 09:33:46Z martin + * Updated function prototypes. + * Revision 1.8 2004/12/28 11:29:02Z martin + * Added macro _n_days. + * Updated function prototypes. + * Revision 1.7 2002/09/06 07:15:48Z martin + * Added MASK_CLOCK_T for Linux. + * Revision 1.6 2002/02/25 08:37:44 Andre + * definition MASK_CLOCK_T for ARM added + * Revision 1.5 2001/03/02 10:18:10Z MARTIN + * Added MASK_CLOCK_T for Watcom C. + * Revision 1.4 2000/09/15 07:57:53 MARTIN + * Removed outdated function prototypes. + * Revision 1.3 2000/07/21 14:05:18 MARTIN + * Defined some new constants. + * + **************************************************************************/ + +#ifndef _MBGTIME_H +#define _MBGTIME_H + + +/* Other headers to be included */ + +#include <gpsdefs.h> + +#if _IS_MBG_FIRMWARE \ + || defined( MBG_TGT_WIN32 ) \ + || defined( MBG_TGT_DOS ) \ + || defined( MBG_TGT_QNX_NTO ) + #include <time.h> +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _MBGTIME + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + + +// The Unix time_t epoche is usually 1970-01-01 00:00 whereas +// the GPS epoche is 1980-01-06 00:00, so the difference is 10 years, +// plus 2 days due to leap years (1972 and 1976), plus the difference +// of the day-of-month (6 - 1). +#define GPS_SEC_BIAS 315964800UL // ( ( ( 10UL * 365UL ) + 2 + 5 ) * SECS_PER_DAY ) + +// time_t t = ( gps_week * SECS_PER_WEEK ) + sec_of_week + GPS_SEC_BIAS + + +// Modified Julian Day (MJD) numbers for some commonly used epochs. +// To compute the MJD for a given date just compute the days since epoch +// and add the constant number of days according to the epoch, e.g.: +// current_unix_mjd = ( time( NULL ) / SECS_PER_DAY ) + MJD_AT_UNIX_EPOCH; +#define MJD_AT_GPS_EPOCH 44244UL // MJD at 1980-01-06 +#define MJD_AT_UNIX_EPOCH 40587UL // MJD at 1970-01-01 +#define MJD_AT_NTP_EPOCH 40587UL // MJD at 1900-01-01 + + +// The constant below defines the Windows FILETIME number (100 ns intervals +// since 1601-01-01) for 1970-01-01, which is usually the epoche for the time_t +// type used by the standard C library. +#if !defined( FILETIME_1970 ) + // FILETIME represents a 64 bit number, so we need to defined the + // constant with an appendix depending on the compiler. + #if MBG_TGT_C99 || defined( __GNUC__ ) + // syntax introduced by C99 standard + #define FILETIME_1970 0x019db1ded53e8000ULL // Epoch offset from FILETIME to UNIX + #elif defined( MBG_TGT_WIN32 ) + // MSC-specific syntax + #define FILETIME_1970 0x019db1ded53e8000ui64 + #endif +#endif + + +#if defined( _C166 ) + #if _C166 >= 50 + #define MASK_CLOCK_T 0x7FFFFFFFL + #else + #define MASK_CLOCK_T 0x7FFF /* time.h not shipped with compiler */ + #endif +#endif + +#if defined( __WATCOMC__ ) + #define MASK_CLOCK_T 0x7FFFFFFFL +#endif + +#if defined( _CVI ) || defined( _CVI_ ) + #define MASK_CLOCK_T 0x7FFFFFFFL +#endif + +#if defined( _MSC_VER ) + #define MASK_CLOCK_T 0x7FFFFFFFL +#endif + +#if defined( __NETWARE_386__ ) + #define MASK_CLOCK_T 0x7FFFFFFFL +#endif + +#if defined( __ARM ) + #define MASK_CLOCK_T 0x7FFFFFFFL +#endif + +#if defined( __ARMCC_VERSION ) + #define MASK_CLOCK_T ( ( (ulong) (clock_t) -1 ) >> 1 ) +#endif + +#if defined( __GNUC__ ) + #if defined( __linux ) + #define MASK_CLOCK_T ( ( (ulong) (clock_t) -1 ) >> 1 ) + #else // Windows / MinGW + #define MASK_CLOCK_T 0x7FFFFFFFL + #endif +#endif + + +#if !defined( MASK_CLOCK_T ) + #if sizeof( clock_t ) == sizeof( short ) + #define MASK_CLOCK_T 0x7FFF + #elif sizeof( clock_t ) == sizeof( long ) + #define MASK_CLOCK_T 0x7FFFFFFFL + #endif +#endif + +typedef struct +{ + clock_t start; + clock_t stop; + short is_set; +} TIMEOUT; + + +#define DAYS_PER_WEEK 7 + +#define SECS_PER_MIN 60 +#define MINS_PER_HOUR 60 +#define HOURS_PER_DAY 24 +#define DAYS_PER_WEEK 7 + +#define MINS_PER_DAY ( MINS_PER_HOUR * HOURS_PER_DAY ) + +#define SECS_PER_HOUR 3600 +#define SECS_PER_DAY 86400L +#define SECS_PER_WEEK 604800L + +#define SEC100S_PER_SEC 100L +#define SEC100S_PER_MIN ( SEC100S_PER_SEC * SECS_PER_MIN ) +#define SEC100S_PER_HOUR ( SEC100S_PER_SEC * SECS_PER_HOUR ) +#define SEC100S_PER_DAY ( SEC100S_PER_SEC * SECS_PER_DAY ) + +#if !defined( MSEC_PER_SEC ) + #define MSEC_PER_SEC 1000L +#endif + +#define MSEC_PER_MIN ( MSEC_PER_SEC * SECS_PER_MIN ) +#define MSEC_PER_HOUR ( MSEC_PER_SEC * SECS_PER_HOUR ) +#define MSEC_PER_DAY ( MSEC_PER_SEC * SECS_PER_DAY ) + +#define NSECS_PER_SEC 1000000000UL + +#if !defined( HNS_PER_SEC ) + #define HNS_PER_SEC 10000000UL +#endif + +#if !defined( HNS_PER_MS ) + #define HNS_PER_MS 10000UL +#endif + + + +_ext TM_GPS dhms; +_ext TM_GPS datum; + + +_ext const char *short_time_fmt +#ifdef _MBGTIME + = "%2i:%02i" +#endif +; + +_ext const char *time_fmt +#ifdef _MBGTIME + = "%2i:%02i:%02i" +#endif +; + +_ext const char *long_time_fmt +#ifdef _MBGTIME + = "%2i:%02i:%02i.%02i" +#endif +; + +_ext const char *date_fmt +#ifdef _MBGTIME + = "%2i.%02i.%04i" +#endif +; + +_ext const char *day_date_fmt +#ifdef _MBGTIME + = "%s, %2i.%02i.%04i" +#endif +; + +_ext const char *day_name_eng[] +#ifdef _MBGTIME + = { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" } +#endif +; + +_ext const char *day_name_ger[] +#ifdef _MBGTIME + = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" } +#endif +; + +_ext const TM_GPS init_tm +#ifdef _MBGTIME + = { 1980, 1, 1, 0, 0, 0, 0, 0, 0, 0 } +#endif +; + + +_ext char days_of_month[2][12] +#ifdef _MBGTIME + = { + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } + } +#endif +; + + +// simplify call to n_days with structures +#define _n_days( _s ) \ + n_days( (_s)->mday, (_s)->month, (_s)->year ) + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + void set_timeout( TIMEOUT *t, clock_t clk, clock_t interval ) ; + void stretch_timeout( TIMEOUT *t, clock_t interval ) ; + bit check_timeout( TIMEOUT *t, clock_t clk ) ; + int err_tm( TM_GPS *tm ) ; + TM_GPS *clear_time( TM_GPS *tm ) ; + TM_GPS *wsec_to_tm( long wsec, TM_GPS *tm ) ; + long tm_to_wsec( TM_GPS *tm ) ; + int is_leap_year( int y ) ; + int day_of_year( int day, int month, int year ) ; + void date_of_year ( int year, int day_num, TM_GPS *tm ) ; + int day_of_week( int day, int month, int year ) ; + int days_to_years( long *day_num, int year ) ; + long n_days( ushort mday, ushort month, ushort year ) ; + double nano_time_to_double( const NANO_TIME *p ) ; + void double_to_nano_time( NANO_TIME *p, double d ) ; + int sprint_time( char *s, const TM_GPS *tm ) ; + int sprint_short_time( char *s, TM_GPS *time ) ; + int sprint_date( char *s, const TM_GPS *tm ) ; + int sprint_day_date( char *s, const TM_GPS *tm ) ; + int sprint_tm( char *s, const TM_GPS *tm ) ; + void sscan_time( char *s, TM_GPS *tm ) ; + void sscan_date( char *s, TM_GPS *tm ) ; + +/* ----- function prototypes end ----- */ + + +/* End of header body */ + + +#undef _ext + +#ifdef __cplusplus +} +#endif + + +#endif /* _MBGTIME_H */ diff --git a/mbglib/common/myutil.h b/mbglib/common/myutil.h new file mode 100644 index 0000000..52489d5 --- /dev/null +++ b/mbglib/common/myutil.h @@ -0,0 +1,225 @@ + +/************************************************************************** + * + * $Id: myutil.h 1.15 2012/10/02 18:51:52Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for myutil.c. + * + * ----------------------------------------------------------------------- + * $Log: myutil.h $ + * Revision 1.15 2012/10/02 18:51:52Z martin + * Updated handling of pragma pack(). + * Revision 1.14 2011/02/16 14:02:35 martin + * Added STRINGIFY() macro. + * Revision 1.13 2010/12/13 15:59:39 martin + * Moved definition of macro _frac() here. + * Revision 1.12 2008/01/30 10:28:17Z martin + * Moved some macro definitions to words.h. + * Revision 1.11 2004/11/09 14:20:24Z martin + * Redefined some data types using C99 fixed-size definitions. + * Removed duplicate definition of macro _mask(). + * Revision 1.10 2004/04/14 08:57:59Z martin + * Pack structures 1 byte aligned. + * Revision 1.9 2003/05/20 10:22:25Z MARTIN + * Corrected endianess of union UL for CC51. + * Revision 1.8 2002/09/03 13:40:43 MARTIN + * New macros _memfill() and _memclr(). + * Revision 1.7 2002/03/14 13:45:56 MARTIN + * Changed type CSUM from short to ushort. + * Revision 1.6 2002/03/05 14:14:21 MARTIN + * New macro _isdigit() to avoid inclusion of ctype.h. + * Revision 1.5 2002/01/25 10:54:26 MARTIN + * Added some useful macros. + * Revision 1.4 2001/03/30 09:07:52 Andre + * union UL byte order set to Big Endian if SH2 is used + * Revision 1.3 2000/08/18 07:22:07Z MARTIN + * Modified the _csum() macro to support far data objects. + * Revision 1.2 2000/07/21 13:50:49 MARTIN + * Added some definitions and macros. + * + **************************************************************************/ + +#ifndef _MYUTIL_H +#define _MYUTIL_H + + +/* Other headers to be included */ + +#include <words.h> +#include <use_pack.h> + + +// _CS_FAR should be define far if the csum of far data +// structures must be computed +#if !defined( _CSFAR ) + #define _CSFAR +#endif + + +#ifdef _MYUTIL + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + + +// The two macros below can be used to define a constant string on the +// compiler's command line, e.g. like -DVERSION_STRING="v1.0 BETA". +// Source code like +// const char version_string[] = VERSION_STRING; +// may not work for every compiler since the double quotes +// in VERSION_STRING may be removed when the definition is evaluated. +// A proper solution is to use the STRINGIFY() macro below: +// const char version_string[] = STRINGIFY( VERSION_STRING ); +// The XSTRINGIFY() macro is simply a helper macro which should not +// be used alone. +#define STRINGIFY(x) XSTRINGIFY(x) +#define XSTRINGIFY(x) #x + + + +#if MBG_TGT_HAS_64BIT_TYPES + #define _frac( _x ) ( ( (_x) == 0.0 ) ? 0.0 : ( (_x) - (double) ( (int64_t) (_x) ) ) ) +#else + #define _frac( _x ) ( ( (_x) == 0.0 ) ? 0.0 : ( (_x) - (double) ( (long) (_x) ) ) ) +#endif + + +#define _isdigit( _c ) ( (_c) >= '0' && (_c) <= '9' ) + +#define _eos( _s ) ( &(_s)[strlen( _s )] ) + +#define MIN( _x, _y ) ( ( (_x) < (_y) ) ? (_x) : (_y) ) +#define MAX( _x, _y ) ( ( (_x) > (_y) ) ? (_x) : (_y) ) +#define SWAP( _x, _y ) { temp = (_x); (_x) = (_y); (_y) = temp; } +#define SQR( _x ) ( (_x) * (_x) ) + +#define DP (double *) + +#define bcd_from_bin( _x ) ( ( ( (_x) / 10 ) << 4 ) | ( (_x) % 10 ) ) +#define bin_from_bcd( _x ) ( ( ( (_x) >> 4 ) * 10 ) + ( (_x) & 0x0F ) ) + + +typedef union +{ + uint32_t ul; + + struct + { + #if defined( _CC51 ) || defined( _SH2 ) + uint16_t hi; // big endian + uint16_t lo; + #else + uint16_t lo; // little endian + uint16_t hi; + #endif + } us; + +} UL; + + +#ifndef _CSUM_DEFINED + typedef uint16_t CSUM; + #define _CSUM_DEFINED +#endif + + +// compute the csum of a structure +#define _csum( _p ) checksum( (void _CSFAR *)(_p), sizeof( *(_p) ) ) + +// set a structure's csum +#define _set_csum( _p ) (_p)->csum = _csum( (_p) ) + +// compare a structure's computed csum with its csum field +#define _valid_csum( _p ) ( (_p)->csum == _csum( (_p) ) ) + +// check if a value is in range +#define _inrange( _val, _min, _max ) \ + ( ( (_val) >= (_min) ) && ( (_val) <= (_max) ) ) + +// Return a bit mask with (_n) LSBs set to 1 +#define _mask( _n ) \ + ( ( 1UL << (_n) ) - 1 ) + +// Return a bit mask with the (_i)th LSB set to 1 +#define _idx_bit( _i ) \ + ( 1UL << (_i) ) + +// Check if the (_i)th bit is set in a mask (_msk) +#define _is_supported( _i, _msk ) \ + ( ( (_msk) & _idx_bit( _i ) ) != 0 ) + + +/* + * The macro below copies a string, taking care not to + * write past the end of the destination buffer, and + * making sure the string is terminated by 0. + */ +#define _strncpy_0( _dst, _src ) \ +{ \ + int n = sizeof( _dst ) - 1; \ + \ + strncpy( _dst, _src, n ); \ + (_dst)[n] = 0; \ +} + + +/* + * The macros below set a memory range used by a variable + * to a specified value, avoiding the need to type the name + * twice for base address and size. + */ +#define _memfill( _p, _v ) \ + memset( _p, _v, sizeof( *(_p) ) ) + +#define _memclr( _p ) \ + _memfill( _p, 0 ) + + + +// generate a DOS idle interrupt to release CPU time +#define _dos_idle() geninterrupt( 0x28 ) + + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + void spaces_to_zeros( char *s ) ; + CSUM checksum( const void _CSFAR *vp, int n ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + + +#undef _ext + + +#endif /* _MYUTIL_H */ diff --git a/mbglib/common/parmgps.c b/mbglib/common/parmgps.c new file mode 100644 index 0000000..187cd4e --- /dev/null +++ b/mbglib/common/parmgps.c @@ -0,0 +1,242 @@ + +/************************************************************************** + * + * $Id: parmgps.c 1.5 2008/10/21 10:47:26Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Functions to handle/convert Meinberg GPS specific parameters. + * + * ----------------------------------------------------------------------- + * $Log: parmgps.c $ + * Revision 1.5 2008/10/21 10:47:26Z martin + * Renamed check_port_info() to check_valid_port_info() + * to avoid naming conflicts. + * Revision 1.4 2008/09/15 14:11:25 martin + * New function check_port_info() which returns a bit mask indicating + * which fields of a PORT_SETTINGS structure are not valid. + * This is based on code taken from valid_port_info(), which now calls + * check_port_info() and returns a value compatible to the earlier version. + * Revision 1.3 2004/11/09 14:21:36 martin + * Redefined some data types using C99 fixed-size definitions. + * Revision 1.2 2002/02/19 13:30:23Z MARTIN + * Bug fix in port_settings_from_port_parm_mode(). + * Revision 1.1 2002/01/30 10:30:26 MARTIN + * Initial revision + * + **************************************************************************/ + +#define _PARMGPS + #include <parmgps.h> +#undef _PARMGPS + +#include <myutil.h> +#include <string.h> + + + +/*HDR*/ +int get_str_idx( const char *search, + const char *str_table[], + int n_entries ) +{ + int i; + + for ( i = 0; i < n_entries; i++ ) + if ( strcmp( search, str_table[i] ) == 0 ) + return i; + + return -1; + +} // get_str_idx + + + +/*HDR*/ +int get_baud_rate_idx( BAUD_RATE baud_rate ) +{ + int i; + + for ( i = 0; i < N_MBG_BAUD_RATES; i++ ) + if ( baud_rate == mbg_baud_rate[i] ) + return i; + + return -1; + +} // get_baud_rate_idx + + + +/*HDR*/ +int get_framing_idx( const char *framing ) +{ + return get_str_idx( framing, mbg_framing_str, N_MBG_FRAMINGS ); + +} // get_framing_idx + + + +/*HDR*/ +void port_settings_from_port_parm_mode( + PORT_SETTINGS *p_ps, + uint8_t pp_mode, + int str_type_cap + ) +{ + if ( pp_mode >= STR_UCAP ) + { + p_ps->str_type = str_type_cap; + p_ps->mode = ( pp_mode == STR_UCAP ) ? STR_AUTO : STR_ON_REQ; + } + else + { + p_ps->str_type = 0; + p_ps->mode = pp_mode; + } + +} // port_settings_from_port_parm_mode + + + +/*HDR*/ +void port_parm_mode_from_port_settings( + uint8_t *pp_mode, + const PORT_SETTINGS *p_ps, + int str_type_cap + ) +{ + if ( p_ps->str_type == str_type_cap ) + *pp_mode = ( p_ps->mode == STR_ON_REQ ) ? STR_UCAP_REQ : STR_UCAP; + else + *pp_mode = p_ps->mode; + +} // port_parm_mode_from_port_settings + + + +/*HDR*/ +void port_settings_from_port_parm( + PORT_SETTINGS *p_ps, + int port_num, + const PORT_PARM *p_pp, + int cap_str_idx +) +{ + p_ps->parm = p_pp->com[port_num]; + + port_settings_from_port_parm_mode( p_ps, p_pp->mode[port_num], + cap_str_idx ); + +} // port_info_from_port_parm + + + +/*HDR*/ +void port_parm_from_port_settings( + PORT_PARM *p_pp, + int port_num, + const PORT_SETTINGS *p_ps, + int cap_str_idx +) +{ + p_pp->com[port_num] = p_ps->parm; + + port_parm_mode_from_port_settings( &p_pp->mode[port_num], + p_ps, cap_str_idx ); + +} // port_parm_from_port_settings + + + +/*HDR*/ +int check_valid_port_info( const PORT_INFO *p_pi, + const STR_TYPE_INFO_IDX str_type_info_idx[], + int n_str_type ) + +{ + const PORT_SETTINGS *p_ps = &p_pi->port_settings; + int idx; + int flags = 0; + + + if ( p_pi->supp_baud_rates & ~_mask( N_MBG_BAUD_RATES ) ) + flags |= MBG_PS_MSK_BAUD_RATE_OVR_SW; // dev. supports more baud rates than driver + + idx = get_baud_rate_idx( p_ps->parm.baud_rate ); + + if ( !_inrange( idx, 0, N_MBG_BAUD_RATES ) || + !_is_supported( idx, p_pi->supp_baud_rates ) ) + flags |= MBG_PS_MSK_BAUD_RATE; + + + if ( p_pi->supp_framings & ~_mask( N_MBG_FRAMINGS ) ) + flags |= MBG_PS_MSK_FRAMING_OVR_SW; // dev. supports more framings than driver + + idx = get_framing_idx( p_ps->parm.framing ); + + if ( !_inrange( idx, 0, N_MBG_FRAMINGS ) || + !_is_supported( idx, p_pi->supp_framings ) ) + flags |= MBG_PS_MSK_FRAMING; + + + if ( p_ps->parm.handshake >= N_COM_HS ) + flags |= MBG_PS_MSK_HS_OVR_SW; // handshake index exceeds max. + + if ( p_ps->parm.handshake != HS_NONE ) // currently no device supports any handshake + flags |= MBG_PS_MSK_HS; // handshake mode not supp. by dev. + + + if ( p_pi->supp_str_types & ~_mask( n_str_type ) ) + flags |= MBG_PS_MSK_STR_TYPE_OVR_SW; // firmware error: more string types supported than reported + + idx = p_ps->str_type; + + if ( idx >= n_str_type ) + flags |= MBG_PS_MSK_STR_TYPE_OVR_DEV; // string type index exceeds max. + else + { + if ( !_is_supported( idx, p_pi->supp_str_types ) ) + flags |= MBG_PS_MSK_STR_TYPE; // string type not supported by this port + else + { + // Use the str_type index to get the supported output mode mask + // from the string type info table. This is required to check + // whether the selected mode is supported by the selected + // string type. + ulong supp_modes = str_type_info_idx[idx].str_type_info.supp_modes; + + if ( supp_modes & ~_mask( N_STR_MODE ) ) + flags |= MBG_PS_MSK_STR_MODE_OVR_SW; // dev. supports more string modes than driver + + idx = p_ps->mode; + + if ( idx >= N_STR_MODE ) // mode is always >= 0 + flags |= MBG_PS_MSK_STR_MODE_OVR_SW; // string mode index exceeds max. + else + if ( !_is_supported( idx, supp_modes ) ) + flags |= MBG_PS_MSK_STR_MODE; // string mode not supp. by this string type and port + } + } + + + if ( p_ps->flags != 0 ) /* currently always 0 */ + flags |= MBG_PS_MSK_FLAGS_OVR_SW | MBG_PS_MSK_FLAGS; + + + return flags; + +} // check_valid_port_info + + + +/*HDR*/ +int valid_port_info( const PORT_INFO *p_pi, + const STR_TYPE_INFO_IDX str_type_info_idx[], + int n_str_type ) +{ + return check_valid_port_info( p_pi, str_type_info_idx, n_str_type ) == 0; + +} // valid_port_info + + diff --git a/mbglib/common/parmgps.h b/mbglib/common/parmgps.h new file mode 100644 index 0000000..6f9b29b --- /dev/null +++ b/mbglib/common/parmgps.h @@ -0,0 +1,142 @@ + +/************************************************************************** + * + * $Id: parmgps.h 1.8 2012/10/15 10:06:37Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for parmgps.c. + * + * ----------------------------------------------------------------------- + * $Log: parmgps.h $ + * Revision 1.8 2012/10/15 10:06:37Z martin + * Cleaned up handling of pragma pack(). + * Revision 1.7 2011/02/16 10:12:13 martin + * Fixed macro syntax for _setup_default_receiver_info_gps(). + * Revision 1.6 2008/10/21 10:41:09Z martin + * Renamed check_port_info() to check_valid_port_info() + * to avoid naming conflicts. + * Revision 1.5 2008/09/10 16:22:32 martin + * Updated function prototypes. + * Revision 1.4 2004/11/09 14:22:34 martin + * Updated function prototypes. + * Revision 1.3 2004/05/19 07:50:16Z martin + * Use symbolic constant as initializer. + * Revision 1.2 2004/04/14 09:21:23Z martin + * Pack structures 1 byte aligned. + * Revision 1.1 2002/01/30 10:33:38Z MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _PARMGPS_H +#define _PARMGPS_H + + +/* Other headers to be included */ + +#include <gpsdefs.h> +#include <use_pack.h> + + +#ifdef _PARMGPS + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define DEFAULT_N_STR_TYPE_GPS 2 + +#define DEFAULT_SUPP_STR_TYPES_GPS \ + ( ( 1UL << DEFAULT_N_STR_TYPE_GPS ) - 1 ) + + +/* + * The macro below can be used to initialize a + * RECEIVER_INFO structure for old GPS receiver models + * which don't supply that structure. + * + * Parameters: (RECEIVER_INFO *) _p + */ +#define _setup_default_receiver_info_gps( _p ) \ +do \ +{ \ + memset( (_p), 0, sizeof( *(_p) ) ); \ + \ + (_p)->ticks_per_sec = DEFAULT_GPS_TICKS_PER_SEC; \ + (_p)->n_ucaps = 2; \ + (_p)->n_com_ports = DEFAULT_N_COM; \ + (_p)->n_str_type = DEFAULT_N_STR_TYPE_GPS; \ +} while ( 0 ) + + +_ext BAUD_RATE mbg_baud_rate[N_MBG_BAUD_RATES] +#ifdef _DO_INIT + = MBG_BAUD_RATES +#endif +; + +_ext const char *mbg_baud_str[N_MBG_BAUD_RATES] +#ifdef _DO_INIT + = MBG_BAUD_STRS +#endif +; + +_ext const char *mbg_framing_str[N_MBG_FRAMINGS] +#ifdef _DO_INIT + = MBG_FRAMING_STRS +#endif +; + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + int get_str_idx( const char *search, const char *str_table[], int n_entries ) ; + int get_baud_rate_idx( BAUD_RATE baud_rate ) ; + int get_framing_idx( const char *framing ) ; + void port_settings_from_port_parm_mode( PORT_SETTINGS *p_ps, uint8_t pp_mode, int str_type_cap ) ; + void port_parm_mode_from_port_settings( uint8_t *pp_mode, const PORT_SETTINGS *p_ps, int str_type_cap ) ; + void port_settings_from_port_parm( PORT_SETTINGS *p_ps, int port_num, const PORT_PARM *p_pp, int cap_str_idx ) ; + void port_parm_from_port_settings( PORT_PARM *p_pp, int port_num, const PORT_SETTINGS *p_ps, int cap_str_idx ) ; + int check_valid_port_info( const PORT_INFO *p, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type ) ; + int valid_port_info( const PORT_INFO *p, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type ) ; + +/* ----- function prototypes end ----- */ + + +#ifdef __cplusplus +} +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _PARMGPS_H */ + diff --git a/mbglib/common/parmpcps.c b/mbglib/common/parmpcps.c new file mode 100644 index 0000000..1d017a2 --- /dev/null +++ b/mbglib/common/parmpcps.c @@ -0,0 +1,115 @@ + +/************************************************************************** + * + * $Id: parmpcps.c 1.4 2004/11/09 14:24:15Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Functions to handle/convert parameters used by Meinberg plug-in + * radio clocks. + * + * ----------------------------------------------------------------------- + * $Log: parmpcps.c $ + * Revision 1.4 2004/11/09 14:24:15Z martin + * Redefined interface data types using C99 fixed-size definitions. + * Revision 1.3 2003/04/17 10:43:35Z martin + * Moved some definitions to parmpcps.h. + * Removed some functions which are now in mbgdevio.c. + * Revision 1.2 2002/03/25 09:03:43Z MARTIN + * Fixed a bug where the wrong framing was configured for DCF77 clocks. + * Revision 1.1 2002/02/19 14:00:19 MARTIN + * Initial revision + * + **************************************************************************/ + +#define _PARMPCPS + #include <parmpcps.h> +#undef _PARMPCPS + +#include <parmgps.h> +#include <pcpsutil.h> +#include <myutil.h> + +#include <string.h> + + +static const int pcps_to_mbg_framing_tbl[N_PCPS_FR_DCF] = +{ + MBG_FRAMING_8N1, + MBG_FRAMING_7E2, + MBG_FRAMING_8N2, + MBG_FRAMING_8E1 +}; + + + +/*HDR*/ +void port_info_from_pcps_serial( + PORT_INFO_IDX *p_pii, + PCPS_SERIAL pcps_serial, + uint32_t supp_baud_rates +) +{ + PCPS_SER_PACK ser_pack; + PORT_INFO *p_pi; + PORT_SETTINGS *p_ps; + + ser_pack.pack = pcps_serial; + pcps_unpack_serial( &ser_pack ); + + p_pi = &p_pii[0].port_info; + p_ps = &p_pi->port_settings; + + p_ps->parm.baud_rate = mbg_baud_rate[ser_pack.baud]; + + _strncpy_0( p_ps->parm.framing, + mbg_framing_str[pcps_to_mbg_framing_tbl[ser_pack.frame]] ); + + p_ps->parm.handshake = HS_NONE; + + p_ps->str_type = 0; + p_ps->mode = ser_pack.mode; + + p_pi->supp_baud_rates = supp_baud_rates; + p_pi->supp_framings = DEFAULT_FRAMINGS_DCF; + p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_DCF; + +} // port_info_from_pcps_serial + + +/*HDR*/ +void pcps_serial_from_port_info( + PCPS_SERIAL *p, + const PORT_INFO_IDX *p_pii +) +{ + PCPS_SER_PACK ser_pack; + const PORT_INFO *p_pi = &p_pii[0].port_info; + const PORT_SETTINGS *p_ps = &p_pi->port_settings; + int framing_idx = get_framing_idx( p_ps->parm.framing ); + int i; + + + ser_pack.baud = get_baud_rate_idx( p_ps->parm.baud_rate ); + + // Translate the common framing index to the corresponding + // number used with the old PCPS_SERIAL parameter. + // This should always return a valid result since the + // framing index is expected to be selected from + // supported framings. + for ( i = 0; i < N_PCPS_FR_DCF; i++ ) + if ( pcps_to_mbg_framing_tbl[i] == framing_idx ) + break; + + ser_pack.frame = i; + + ser_pack.mode = p_ps->mode; + + pcps_pack_serial( &ser_pack ); + + *p = ser_pack.pack; + +} // pcps_serial_from_port_info + + diff --git a/mbglib/common/parmpcps.h b/mbglib/common/parmpcps.h new file mode 100644 index 0000000..5eb30cb --- /dev/null +++ b/mbglib/common/parmpcps.h @@ -0,0 +1,163 @@ + +/************************************************************************** + * + * $Id: parmpcps.h 1.8 2012/10/15 10:05:38Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for parmpcps.c. + * + * ----------------------------------------------------------------------- + * $Log: parmpcps.h $ + * Revision 1.8 2012/10/15 10:05:38Z martin + * Cleaned up handling of pragma pack(). + * Revision 1.7 2011/04/01 10:30:51 martin + * Fixed macro syntax for _setup_default_receiver_info_dcf(). + * Revision 1.6 2011/02/16 10:13:12 martin + * Fixed macro syntax for _setup_default_receiver_info_pcps(). + * Revision 1.5 2004/11/09 14:24:58Z martin + * Updated function prototypes. + * Revision 1.4 2004/05/19 07:52:25Z martin + * Fixed macro setting default number of string types. + * Revision 1.3 2004/04/14 09:21:44Z martin + * Pack structures 1 byte aligned. + * Revision 1.2 2003/04/17 10:42:46Z martin + * Moved typedef RECEIVER_PORT_CFG to pcpsdev.h. + * Moved some definitions from parmpcps.c here. + * Removed some global variables. + * Updated function prototypes. + * Revision 1.1 2002/02/19 14:00:19Z MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _PARMPCPS_H +#define _PARMPCPS_H + +/* Other headers to be included */ + +#include <pcpsdev.h> +#include <use_pack.h> + + +#ifdef _PARMPCPS + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define DEFAULT_BAUD_RATES_DCF \ +( \ + MBG_PORT_HAS_300 | \ + MBG_PORT_HAS_600 | \ + MBG_PORT_HAS_1200 | \ + MBG_PORT_HAS_2400 | \ + MBG_PORT_HAS_4800 | \ + MBG_PORT_HAS_9600 \ +) + +#define DEFAULT_BAUD_RATES_DCF_HS \ +( \ + MBG_PORT_HAS_300 | \ + MBG_PORT_HAS_600 | \ + MBG_PORT_HAS_1200 | \ + MBG_PORT_HAS_2400 | \ + MBG_PORT_HAS_4800 | \ + MBG_PORT_HAS_9600 | \ + MBG_PORT_HAS_19200 | \ + MBG_PORT_HAS_38400 \ +) + + +#define DEFAULT_FRAMINGS_DCF \ +( \ + MBG_PORT_HAS_7E2 | \ + MBG_PORT_HAS_8N1 | \ + MBG_PORT_HAS_8N2 | \ + MBG_PORT_HAS_8E1 \ +) + + +#define DEFAULT_N_STR_TYPE_DCF 1 + +#define DEFAULT_SUPP_STR_TYPES_DCF \ + ( ( 1UL << DEFAULT_N_STR_TYPE_DCF ) - 1 ) + + +/* + * The macro below can be used to initialize a + * RECEIVER_INFO structure for DCF77 receivers + * which don't supply that structure. + * + * Parameters: (RECEIVER_INFO *) _p + */ +#define _setup_default_receiver_info_dcf( _p, _pdev ) \ +do \ +{ \ + memset( (_p), 0, sizeof( *(_p) ) ); \ + \ + (_p)->ticks_per_sec = DEFAULT_GPS_TICKS_PER_SEC; \ + (_p)->n_ucaps = 0; \ + (_p)->n_com_ports = _pcps_has_serial( _pdev ) ? 1 : 0; \ + (_p)->n_str_type = ( (_p)->n_com_ports != 0 ) ? \ + DEFAULT_N_STR_TYPE_DCF : 0; \ +} while ( 0 ) + + +#define DEFAULT_MAX_STR_TYPE 2 //##++ DEFAULT_N_STR_TYPE_GPS + +_ext STR_TYPE_INFO default_str_type_info[DEFAULT_MAX_STR_TYPE] +#ifdef _DO_INIT + = { + { DEFAULT_STR_MODES, "Default Time String", "Time", 0 }, + { DEFAULT_STR_MODES_UCAP, "Capture String", "Cap", 0 } + } +#endif +; + + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + void port_info_from_pcps_serial( PORT_INFO_IDX *p_pii, PCPS_SERIAL pcps_serial, uint32_t supp_baud_rates ) ; + void pcps_serial_from_port_info( PCPS_SERIAL *p, const PORT_INFO_IDX *p_pii ) ; + +/* ----- function prototypes end ----- */ + + +#ifdef __cplusplus +} +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + + +#undef _ext +#undef _DO_INIT + +#endif /* _PARMPCPS_H */ diff --git a/mbglib/common/pci_asic.h b/mbglib/common/pci_asic.h new file mode 100644 index 0000000..8eb6371 --- /dev/null +++ b/mbglib/common/pci_asic.h @@ -0,0 +1,391 @@ + +/************************************************************************** + * + * $Id: pci_asic.h 1.22 2011/10/05 09:46:12Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions for the Meinberg PCI interface ASIC. + * + * ----------------------------------------------------------------------- + * $Log: pci_asic.h $ + * Revision 1.22 2011/10/05 09:46:12Z martin + * Updated version info for GPS180PEX. + * Revision 1.21 2011/09/13 07:36:21Z martin + * Updated version info for GPS180PEX. + * Revision 1.20 2011/06/30 13:52:26Z martin + * Updated version info for GPS180PEX. + * Revision 1.19 2011/06/29 08:58:32Z martin + * Support PZF180PEX. + * Cleaned up handling of pragma pack(). + * Revision 1.18 2011/04/06 12:31:48 martin + * Updated minor versions for PTP270PEX and GPS180PEX. + * Revision 1.17 2010/09/10 14:03:25Z martin + * Support GPS180PEX and TCR180PEX. + * New table initializer to simplify EPLD version checking. + * Revision 1.16 2010/04/16 11:12:21Z martin + * Updated GPS170PEX ASIC version. + * Revision 1.15 2009/03/27 09:39:15 martin + * Increased current ASIC minor number for TCR170PEX to 0x02. + * Renamed some symbols. + * Revision 1.14 2009/03/11 16:54:10Z martin + * Increased current ASIC minor number for TCR511PEX to 0x04. + * Fixed a typo. + * Revision 1.13 2008/12/05 12:28:18Z martin + * Modified syntax of macro _convert_asic_version_number(). + * Added macros to deal with the ASIC version number. + * Added definition PCI_ASIC_HAS_PGMB_IRQ. + * Added ASIC revision numbers for PEX511, TCR511PEX, and GPS170PEX + * which fix an IRQ bug with these cards. + * Added definitions for PTP270PEX, FRC511PEX, and TCR170PEX. + * Revision 1.12 2008/07/21 10:30:00Z martin + * Added macros to convert the endianess of data types. + * Added PCI_ASIC_CURRENT_MINOR_... symbols. + * Revision 1.11 2008/06/11 09:49:43 martin + * Added definitions and comments how to handle version numbers + * of the PCI and PEX interface chips and EPLDs. + * Revision 1.10 2008/02/29 15:21:48Z martin + * Added definition PCI_ASIC_HAS_MM_IO. + * Revision 1.9 2008/01/17 09:51:05 daniel + * Added macro _convert_asic_version_number(). + * Cleanup for PCI ASIC version and features. + * Revision 1.8 2006/06/14 12:59:12Z martin + * Added support for TCR511PCI. + * Revision 1.7 2006/03/10 10:47:03 martin + * Added support for PCI511. + * Revision 1.6 2005/11/03 15:30:44Z martin + * Added support for GPS170PCI. + * Revision 1.5 2004/11/09 12:51:56Z martin + * Redefined fixed width data types using standard C99 types. + * Defined some constants unsigned. + * Revision 1.4 2004/10/14 15:01:23 martin + * Added support for TCR167PCI. + * Revision 1.3 2003/05/13 14:38:55Z MARTIN + * Added ushort fields to unions PCI_ASIC_REG and + * PCI_ASIC_ADDON_DATA. + * Revision 1.2 2003/04/03 10:56:38 martin + * Use unions for registers. + * Modified BADR0 initializer due to fixed size of address decoder. + * Revision 1.1 2003/02/07 11:42:52 MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _PCI_ASIC_H +#define _PCI_ASIC_H + + +/* Other headers to be included */ + +#include <words.h> +#include <use_pack.h> + +#ifdef _PCI_ASIC + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + + +typedef struct +{ + uint32_t cfg_class_rev_id; + uint16_t cfg_badr_0; + uint16_t cfg_dev_id; +} PCI_ASIC_CFG; + + +typedef union +{ + uint32_t ul; + uint16_t us[2]; + uint8_t b[4]; +} PCI_ASIC_REG; + + +typedef uint32_t PCI_ASIC_VERSION; +#define _mbg_swab_asic_version( _p ) _mbg_swab32( _p ) + +typedef uint32_t PCI_ASIC_FEATURES; +#define _mbg_swab_asic_features( _p ) _mbg_swab32( _p ) + +#define PCI_ASIC_HAS_MM_IO 0x0001 +#define PCI_ASIC_HAS_PGMB_IRQ 0x0002 + + +typedef union +{ + uint32_t ul[4]; + uint16_t us[8]; + uint8_t b[16]; +} PCI_ASIC_ADDON_DATA; + + +typedef struct +{ + PCI_ASIC_CFG cfg; // writeable from add-on once after power-up + PCI_ASIC_VERSION raw_version; + PCI_ASIC_FEATURES features; + PCI_ASIC_REG status_port; + PCI_ASIC_REG control_status; // codes defined below + PCI_ASIC_REG pci_data; // pass byte from PCI bus to add-on + PCI_ASIC_REG reserved_1; + + PCI_ASIC_ADDON_DATA addon_data; // returns data from add-on to PCI bus + PCI_ASIC_ADDON_DATA reserved_2; // currently not implemented +} PCI_ASIC; + + +// The following bits are used with the control_status register. +// All other bits are reserved for future use. + +// The IRQ flag for the add-on side is set whenever data is +// written to the cmd register. It is cleared if the add-on +// microcontroller writes this bit back to the control_status +// register. If the bit is set, the add-on signals /ADD_ON_IRQ +// and ADD_ON_BUSY are asserted. +#define PCI_ASIC_ADD_ON_IRQF 0x00000001UL + +// The IRQ flag for the PCI bus is set whenever the add-on +// microcontroller asserts the ASIC's /PCI_IRQ line, or the +// add-on microcontroller sets this bit to 1. It is cleared +// if this bit is written back from the PCI side. If the bit +// is set, an IRQ is asserted on the PCI bus. +#define PCI_ASIC_PCI_IRQF 0x00010000UL + + +// The ASIC's address decoder always decodes 8 bits, so +// each device must request at least that number of +// addresses from the PCI BIOS: +#define PCI_ASIC_ADDR_RANGE 0x100U + + +// Initializers for device configurations + +#define PCPS_DEV_CLASS_CODE 0x08800000UL +#define PCI_ASIC_BADR0_INIT ( ~( PCI_ASIC_ADDR_RANGE - 1 ) | 0x01 ) + + +#define PCI_ASIC_CFG_PCI510 \ +{ \ + _hilo_32( PCPS_DEV_CLASS_CODE ), \ + _hilo_16( PCI_ASIC_BADR0_INIT ), \ + _hilo_16( PCI_DEV_PCI510 ) \ +} + +#define PCI_ASIC_CFG_GPS169PCI \ +{ \ + _hilo_32( PCPS_DEV_CLASS_CODE ), \ + _hilo_16( PCI_ASIC_BADR0_INIT ), \ + _hilo_16( PCI_DEV_GPS169PCI ) \ +} + +#define PCI_ASIC_CFG_TCR510PCI \ +{ \ + _hilo_32( PCPS_DEV_CLASS_CODE ), \ + _hilo_16( PCI_ASIC_BADR0_INIT ), \ + _hilo_16( PCI_DEV_TCR510PCI ) \ +} + +#define PCI_ASIC_CFG_TCR167PCI \ +{ \ + _hilo_32( PCPS_DEV_CLASS_CODE ), \ + _hilo_16( PCI_ASIC_BADR0_INIT ), \ + _hilo_16( PCI_DEV_TCR167PCI ) \ +} + +#define PCI_ASIC_CFG_GPS170PCI \ +{ \ + _hilo_32( PCPS_DEV_CLASS_CODE ), \ + _hilo_16( PCI_ASIC_BADR0_INIT ), \ + _hilo_16( PCI_DEV_GPS170PCI ) \ +} + +#define PCI_ASIC_CFG_PCI511 \ +{ \ + _hilo_32( PCPS_DEV_CLASS_CODE ), \ + _hilo_16( PCI_ASIC_BADR0_INIT ), \ + _hilo_16( PCI_DEV_PCI511 ) \ +} + +#define PCI_ASIC_CFG_TCR511PCI \ +{ \ + _hilo_32( PCPS_DEV_CLASS_CODE ), \ + _hilo_16( PCI_ASIC_BADR0_INIT ), \ + _hilo_16( PCI_DEV_TCR511PCI ) \ +} + +/* + Handling of the version numbers of the PCI interface + chips has changed between the ASICs used for standard PCI + and the EPLDs used to configure the PEX8311 chip + for a specific device. + + The macro below can be used to convert both types + of version number into the same format so that the + version numbers can be handled in the same way: +*/ +#define _convert_asic_version_number( _n ) \ + ( ( (_n) < 0x100 ) ? ( (_n) << 8 ) : (_n) ) + + + +/* + * Macros to extract the major and minor part of an ASIC version number */ + +#define _pcps_asic_version_major( _v ) \ + ( ( (_v) >> 8 ) & 0xFF ) + +#define _pcps_asic_version_minor( _v ) \ + ( (_v) & 0xFF ) + + +/* + * Macros to check whether a version number is correct + * and matches a required minimum version + */ +#define _pcps_asic_version_greater_equal( _v, _v_major, _v_minor ) \ + ( \ + ( _pcps_asic_version_major( _v ) == (_v_major) ) && \ + ( _pcps_asic_version_minor( _v ) >= (_v_minor) ) \ + ) + + +/* + The low byte of the converted version number is handled + as a minor version, whereas the remaining upper bytes are + interpreted as a major number which may be specific + for a device. +*/ +enum +{ + PCI_ASIC_MAJOR_PCI_0, // PCI ASIC with CRC bug + PCI_ASIC_MAJOR_PCI_1, // fixed version of PCI ASIC + PCI_ASIC_MAJOR_PEX511, // PEX EPLD for PEX511 + PCI_ASIC_MAJOR_GPS170PEX, // PEX EPLD for GPS170PEX + PCI_ASIC_MAJOR_TCR511PEX, // PEX EPLD for TCR511PEX + PCI_ASIC_MAJOR_PTP270PEX, // PEX EPLD for PTP270PEX + PCI_ASIC_MAJOR_FRC511PEX, // PEX EPLD for FRC511PEX + PCI_ASIC_MAJOR_TCR170PEX, // PEX EPLD for TCR170PEX + PCI_ASIC_MAJOR_GPS180PEX, // PEX EPLD for GPS180PEX + PCI_ASIC_MAJOR_TCR180PEX, // PEX EPLD for TCR180PEX + PCI_ASIC_MAJOR_PZF180PEX, // PEX EPLD for PZF180PEX + N_PCI_ASIC_MAJOR // the number of known codes +}; + +/* + The minor number increases when a new EPLD image is released. + At least EPLD images with the following "required minor" numbers + should be installed for proper operation. The "current minor" + numbers can be used to check if a newer EPLD image is available: +*/ +#define PCI_ASIC_CURRENT_MINOR_PEX511 0x04 +#define PCI_ASIC_REQUIRED_MINOR_PEX511 0x03 +#define PCI_ASIC_FIX_HRT_MINOR_PEX511 0x04 // increases HRT accuracy +#define PCI_ASIC_FIX_IRQ_MINOR_PEX511 0x03 // fixes IRQ problem +#define PCI_ASIC_HR_TIME_MINOR_PEX511 0x02 // supports HR time with PEX511 + +#define PCI_ASIC_CURRENT_MINOR_GPS170PEX 0x05 +#define PCI_ASIC_REQUIRED_MINOR_GPS170PEX 0x03 +#define PCI_ASIC_ENH_HRT_MINOR_GPS170PEX 0x05 // enhanced MM HRT accuracy +#define PCI_ASIC_FIX_HRT_MINOR_GPS170PEX 0x04 // increases MM HRT accuracy +#define PCI_ASIC_FIX_IRQ_MINOR_GPS170PEX 0x03 // fixes IRQ problem + +#define PCI_ASIC_CURRENT_MINOR_TCR511PEX 0x04 +#define PCI_ASIC_REQUIRED_MINOR_TCR511PEX 0x03 +// 0x04 // EPLD sources shared with PEX511 0x04 +#define PCI_ASIC_FIX_IRQ_MINOR_TCR511PEX 0x03 // fixes IRQ problem, increases HRT accuracy + +#define PCI_ASIC_CURRENT_MINOR_PTP270PEX 0x02 +#define PCI_ASIC_REQUIRED_MINOR_PTP270PEX 0x01 +// 0x02 // increased accuracy of IRIG DCLS slopes +// 0x01 // supports inversion of ucap slopes + +#define PCI_ASIC_CURRENT_MINOR_FRC511PEX 0x01 +#define PCI_ASIC_REQUIRED_MINOR_FRC511PEX 0x01 + +#define PCI_ASIC_CURRENT_MINOR_TCR170PEX 0x03 +#define PCI_ASIC_REQUIRED_MINOR_TCR170PEX 0x02 +#define PCI_ASIC_FIX_EE_ACCESS_TCR170PEX 0x02 // fixes EE access problem after reset +#define PCI_ASIC_FIX_FO_IN_LEVEL_TCR170PEX 0x03 // correct polarity for fiber optic input + +#define PCI_ASIC_CURRENT_MINOR_GPS180PEX 0x05 +#define PCI_ASIC_REQUIRED_MINOR_GPS180PEX 0x01 +// 0x01 // updated VHDL compiler and associated PCI primitives +// 0x02 // I/O using 3.3V LVTTL +// 0x03 // GPS TIC pulse len now 1 sample clock +// 0x04 // Enabled PCI IRQ line which had unintentionally been disabled earlier +// 0x05 // Increased accuracy of synthesizer output + +#define PCI_ASIC_CURRENT_MINOR_TCR180PEX 0x00 +#define PCI_ASIC_REQUIRED_MINOR_TCR180PEX 0x00 + +#define PCI_ASIC_CURRENT_MINOR_PZF180PEX 0x00 +#define PCI_ASIC_REQUIRED_MINOR_PZF180PEX 0x00 + + +typedef struct +{ + unsigned int dev_type_num; + unsigned int major; + unsigned int current_minor; + unsigned int required_minor; +} PCI_ASIC_VERSION_INFO; + +#define DEFAULT_PCI_ASIC_VERSION_INFO_TABLE \ +{ \ + { PCPS_TYPE_PEX511, PCI_ASIC_MAJOR_PEX511, PCI_ASIC_CURRENT_MINOR_PEX511, PCI_ASIC_REQUIRED_MINOR_PEX511 }, \ + { PCPS_TYPE_GPS170PEX, PCI_ASIC_MAJOR_GPS170PEX, PCI_ASIC_CURRENT_MINOR_GPS170PEX, PCI_ASIC_REQUIRED_MINOR_GPS170PEX }, \ + { PCPS_TYPE_TCR511PEX, PCI_ASIC_MAJOR_TCR511PEX, PCI_ASIC_CURRENT_MINOR_TCR511PEX, PCI_ASIC_REQUIRED_MINOR_TCR511PEX }, \ + { PCPS_TYPE_PTP270PEX, PCI_ASIC_MAJOR_PTP270PEX, PCI_ASIC_CURRENT_MINOR_PTP270PEX, PCI_ASIC_REQUIRED_MINOR_PTP270PEX }, \ + { PCPS_TYPE_FRC511PEX, PCI_ASIC_MAJOR_FRC511PEX, PCI_ASIC_CURRENT_MINOR_FRC511PEX, PCI_ASIC_REQUIRED_MINOR_FRC511PEX }, \ + { PCPS_TYPE_TCR170PEX, PCI_ASIC_MAJOR_TCR170PEX, PCI_ASIC_CURRENT_MINOR_TCR170PEX, PCI_ASIC_REQUIRED_MINOR_TCR170PEX }, \ + { PCPS_TYPE_GPS180PEX, PCI_ASIC_MAJOR_GPS180PEX, PCI_ASIC_CURRENT_MINOR_GPS180PEX, PCI_ASIC_REQUIRED_MINOR_GPS180PEX }, \ + { PCPS_TYPE_TCR180PEX, PCI_ASIC_MAJOR_TCR180PEX, PCI_ASIC_CURRENT_MINOR_TCR180PEX, PCI_ASIC_REQUIRED_MINOR_TCR180PEX }, \ + { PCPS_TYPE_PZF180PEX, PCI_ASIC_MAJOR_PZF180PEX, PCI_ASIC_CURRENT_MINOR_PZF180PEX, PCI_ASIC_REQUIRED_MINOR_PZF180PEX }, \ + { 0 } \ +} + + +/* 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 + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _PCI_ASIC_H */ + diff --git a/mbglib/common/pcpsdefs.h b/mbglib/common/pcpsdefs.h new file mode 100644 index 0000000..5726f58 --- /dev/null +++ b/mbglib/common/pcpsdefs.h @@ -0,0 +1,1496 @@ + +/************************************************************************** + * + * $Id: pcpsdefs.h 1.50 2013/01/30 15:59:54Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * General definitions for Meinberg plug-in devices. + * + * ----------------------------------------------------------------------- + * $Log: pcpsdefs.h $ + * Revision 1.50 2013/01/30 15:59:54Z martin + * Updated and fixed some doxygen comments. + * Revision 1.49 2012/10/02 18:53:02 martin + * Added structure PCPS_TIME_STATUS_X_MASKS. + * Added initializer for command names, useful for debugging. + * Revision 1.48 2011/11/25 15:02:28 martin + * Support on-board event logs. + * Revision 1.47 2011/11/25 10:22:44 martin + * Modified handling of pragma pack(). + * Made command group codes obsolete. They are still supported + * when building firmware, though. + * Support PTP unicast configuration. + * Support GPIO configuration. + * Support PZF180PEX. + * Added commands to read CORR_INFO, read/write TR_DISTANCE, + * PCPS_SYNC_PZF status, and associated structures. + * Added an initializer for a table of GPS command code/names. + * Added definitions MBG_PCPS_FMT_STATUS. + * Updated some comments. + * Revision 1.46 2011/01/13 11:44:29Z martin + * Moved status port register definitions here. + * Revision 1.45 2010/09/06 07:36:24 martin + * Support GPS180PEX and TCR180PEX. + * Moved some IRIG related definitions to gpsdefs.h. + * Revision 1.44 2010/06/30 11:09:49 martin + * Added definitions for JJY longwave transmitter. + * Renamed MBG_RAW_IRIG_DATA::data field to data_bytes + * since "data" is a reserved word for C51 architecture. + * Revision 1.43 2010/02/09 11:20:17Z martin + * Renamed yet unused CORR_INFO::flags field to signal and updated comments. + * Revision 1.42 2010/01/12 14:02:37 daniel + * Added definitions to support reading the raw IRIG data bits. + * Revision 1.41 2009/06/19 12:16:42Z martin + * Added PCPS_GIVE_IRIG_TIME command and associated definitions. + * Revision 1.40 2009/06/08 19:29:11 daniel + * Support PTP configuration. + * Support LAN_IF configuration + * Added definition of PCPS_CMD_INFO. + * Revision 1.39 2009/03/19 08:58:09 martin + * Added PCPS_GET_IRIG_CTRL_BITS cmd and associated data type. + * Revision 1.38 2009/03/10 17:07:09 martin + * Support configurable time scales and GPS UTC parameters. + * Added ext. status flag for time scales, and PCPS_LS_ANN_NEG. + * Added bit mask PCPS_SCALE_MASK. + * Revision 1.37 2008/12/05 16:01:37Z martin + * Added ref types PTP, FRC, and WWVB. + * Added ref names MSF, PTP, FRC, and WWVB. + * Added device codes TCR170PEX, PTP270PEX, and FRC511PEX. + * Added macros to convert the endianess of structures. + * Moved definitions of PCPS_HRT_FRAC_SCALE and + * PCPS_HRT_FRAC_SCALE_FMT here. + * Added definitions of PCPS_HRT_FRAC_CONVERSION_TYPE + * and PCPS_HRT_BIN_FRAC_SCALE. + * Escaped '<' and '>' characters for doxygen. + * Modified comments for PCPS_TZDL. + * Removed trailing spaces and obsolete comments. + * Revision 1.36 2008/01/17 09:20:25Z daniel + * Added new REF type PCPS_REF_MSF. + * Revision 1.35 2008/01/17 09:18:46Z daniel + * Made comments compatible for doxygen parser. + * No sourcecode changes. + * Revision 1.34 2007/07/17 08:22:47Z martin + * Added support for TCR511PEX and GPS170PEX. + * Revision 1.33 2007/05/20 21:39:51Z martin + * Added support for PEX511. + * Added PCPS_GET_STATUS_PORT cmd code for devices + * that do not support a hardware status port. + * Revision 1.32 2007/03/29 12:57:32Z martin + * Renamed some TZCODE numbers for unique naming conventions. + * Added definitions of the older symbols for compatibility. + * Revision 1.31 2007/03/26 15:42:31Z martin + * Replaced PCPS_REF_OFFS and associated definitions by MBG_REF_OFFS, etc., + * which are defined in gpsdefs.h. + * Added PCPS_GET_DEBUG_STATUS code. + * Revision 1.30 2006/06/29 10:13:13 martin + * Added some descriptive comments. + * Revision 1.29 2006/06/14 12:59:12Z martin + * Added support for TCR511PCI. + * Revision 1.28 2006/05/18 09:45:16 martin + * Added data types used with PZF receivers. + * Revision 1.27 2006/05/03 10:19:14Z martin + * Added initializers for reference source names. + * Revision 1.26 2006/03/10 10:24:45Z martin + * New definitions for PCI511. + * Added command codes to configure programmable pulse outputs. + * Revision 1.25 2005/11/03 15:05:16Z martin + * New definitions for GPS170PCI. + * New types PCPS_TIME_STATUS and PCPS_TIME_STATUS_X. + * Removed obsolete enumeration of PCPS_TIME fields. + * Revision 1.24 2005/05/03 07:56:55Z martin + * Added command PCPS_GET_SYNTH_STATE. + * Revision 1.23 2005/03/29 12:51:10Z martin + * New cmd code PCPS_GENERIC_IO. + * Revision 1.22 2004/12/09 11:03:37Z martin + * Support configuration of on-board frequency synthesizer. + * Revision 1.21 2004/11/09 12:55:32Z martin + * Redefined interface data types using C99 fixed-size definitions. + * Added workaround macros for some structure sizes because the C166 + * compiler always reports an even structure size even if the structure + * size is in fact odd, which might lead to different sizes in C166 and + * other environments. + * Modifications were required in order to be able to configure IRIG + * settings of cards which provide both IRIG input and output. + * The existing codes have been renamed with .._RX.. and are used to + * configure the IRIG receiver (input). New codes have been defined + * used to configure the IRIG transmitter. + * Renamed PC_GPS_STAT to PC_GPS_BVAR_STAT. + * Use more specific data types than generic types. + * Revision 1.20 2004/10/14 15:01:23 martin + * Added support for TCR167PCI. + * Revision 1.19 2004/06/16 12:46:33Z martin + * Moved OPT_SETTINGS related definitions to gpsdefs.h, + * and renamed symbols from PCPS_.. to to MBG_... + * Revision 1.18 2004/04/26 14:27:08Z martin + * Added union PCPS_TIME_UNION. + * Revision 1.17 2003/05/27 08:50:35Z MARTIN + * New commands PCPS_GIVE_UCAP_ENTRIES, PCPS_GIVE_UCAP_EVENT + * and associated definitions which allow faster reading of + * user capture events and monitoring of the capture buffer + * fill level. + * Revision 1.16 2003/04/03 10:48:53 martin + * Support for PCI510, GPS169PCI, and TCR510PCI. + * New codes PCPS_GET_REF_OFFS, PCPS_SET_REF_OFFS + * and related structures. + * New codes PCPS_GET_OPT_INFO, PCPS_SET_OPT_SETTINGS + * and related structures. + * New codes PCPS_GET_IRIG_INFO, PCPS_SET_IRIG_SETTINGS. + * Preliminary PCPS_TZDL structure and cmd codes + * to read/write that structure. + * Revision 1.15 2002/08/08 13:24:03 MARTIN + * Moved definition of ref time sources here. + * Added new ref time source IRIG. + * Added new cmd to clear time capture buffer. + * Fixed some comments. + * Revision 1.14 2002/01/31 13:39:38 MARTIN + * Added new GPS data type codes for RECEIVER_INFO, etc. + * New PCPS_HR_TIME status flag PCPS_IO_BLOCKED. + * Moved REV_NUMs defining special features to pcpsdev.h. + * Removed obsolete initializer for framing string table. + * Updated some comments. + * Removed obsolete code. + * Revision 1.13 2001/12/03 16:15:14 martin + * Introduced PCPS_TIME_STAMP which allows to handle high precision + * time stamps. + * Replaced the sec/frac fields in PCPS_HR_TIME by PCPS_TIME_STAMP. + * This is compatible on byte level but may require source code + * modifications. + * Introduced new command PCPS_SET_EVENT_TIME which is used + * EXCLUSIVELY with a custom GPS firmware. + * Revision 1.12 2001/10/16 10:07:42 MARTIN + * Defined PCI509 firmware revision number which supports + * baud rate higher than standard. + * Revision 1.11 2001/03/30 13:02:39 MARTIN + * Control alignment of structures from new file use_pack.h. + * Defined initializers with valid framing parameters. + * Revision 1.10 2001/02/28 15:39:25 MARTIN + * Modified preprocessor syntax. + * Revision 1.9 2001/02/16 11:32:05 MARTIN + * Renamed "PROM" or "EPROM" in comments or and names to + * "FW" or firmware. + * This includes the cmd codes PCPS_GIVE_PROM_ID_... which have + * been renamed to PCPS_GIVE_FW_ID_... + * Renamed structure PCPS_TIME_SET to PCPS_STIME. + * Renamed return code PCPS_ERR_NONE to PCPS_SUCCESS. + * Modified some comments. + * Revision 1.8 2000/10/11 09:17:09 MARTIN + * Cleaned up comment syntax. + * Revision 1.7 2000/07/21 14:16:30 MARTIN + * Modified some comments. + * Added PCI definitions. + * Renamed PCPS_GET_GPS_DATA to PCPS_READ_GPS_DATA. + * Renamed PCPS_SET_GPS_DATA to PCPS_WRITE_GPS_DATA. + * New types PCPS_SERIAL and PCPS_TZCODE. + * Removed PCPS_SERIAL_BYTES and PCPS_TZCODE_BYTES, may use sizeof() + * the types instead. + * New type PCPS_TIME_SET which can be used to write date and time + * to the clock. + * Revision 1.6 2000/06/07 12:09:31 MARTIN + * renamed PCPS_SERIAL_GROUP to PCPS_CFG_GROUP + * renamed PCPS_ERR_SERIAL to PCPS_ERR_CFG + * modified definitions for baud rate, framing, and mode + * added PCPS_SN_... definitions + * added PCPS_GET_TZCODE and PCPS_SET_TZCODE definitions + * added PC_GPS_ANT_CABLE_LEN definition + * added RCS keywords + * updated some comments + * + * ----------------------------------------------------------------------- + * Changes before put under RCS control: + * + * Revision 1.5 2000/03/24 + * Introduced PCPS_GIVE_SERNUM + * Cleaned up for definitions for serial parameter byte + * Reviewed and updated comments. + * + * 1998/07/22 + * Introduced PCPS_HR_TIME. + * Rearranged order of definitions. + * Reviewed and updated comments. + * + * 1997/06/12 + * GPS definitions added. + * + * 1996/01/25 + * PCPS_TIME redefined from an array of bytes to a structure. + * + **************************************************************************/ + +#ifndef _PCPSDEFS_H +#define _PCPSDEFS_H + + +/* Other headers to be included */ + +#include <words.h> +#include <use_pack.h> + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + + +/** + * @brief Enumeration of the ref time signal sources used by Meinberg devices + */ +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/IEEE1588 network protocol */ + PCPS_REF_FRC, /**< Free Running Clock */ + PCPS_REF_WWVB, /**< WWVB Receiver (US) */ + PCPS_REF_JJY, /**< JJY Receiver (Japan) */ + N_PCPS_REF /**< number of valid ref time sources */ +}; + + +/* Initializers for the reference source names */ + +#define PCPS_REF_NAME_NONE_ENG "unknown" +#define PCPS_REF_NAME_NONE_GER "nicht bekannt" +#define PCPS_REF_NAME_DCF "DCF77" +#define PCPS_REF_NAME_GPS "GPS" +#define PCPS_REF_NAME_IRIG "IRIG" +#define PCPS_REF_NAME_MSF "MSF" +#define PCPS_REF_NAME_PTP "PTP" +#define PCPS_REF_NAME_FRC "FRC" +#define PCPS_REF_NAME_WWVB "WWVB" +#define PCPS_REF_NAME_JJY "JJY" + + +#define PCPS_REF_NAMES_ENG \ +{ \ + PCPS_REF_NAME_NONE_ENG, \ + PCPS_REF_NAME_DCF, \ + PCPS_REF_NAME_GPS, \ + PCPS_REF_NAME_IRIG, \ + PCPS_REF_NAME_MSF, \ + PCPS_REF_NAME_PTP, \ + PCPS_REF_NAME_FRC, \ + PCPS_REF_NAME_WWVB, \ + PCPS_REF_NAME_JJY \ +} + + +#define PCPS_REF_NAMES_LSTR \ +{ \ + { PCPS_REF_NAME_NONE_ENG, PCPS_REF_NAME_NONE_GER }, \ + { PCPS_REF_NAME_DCF, NULL }, \ + { PCPS_REF_NAME_GPS, NULL }, \ + { PCPS_REF_NAME_IRIG, NULL }, \ + { PCPS_REF_NAME_MSF, NULL }, \ + { PCPS_REF_NAME_PTP, NULL }, \ + { PCPS_REF_NAME_FRC, NULL }, \ + { PCPS_REF_NAME_WWVB, NULL }, \ + { PCPS_REF_NAME_JJY, NULL } \ +} + + + +/** + * @brief Meinberg PCI vendor ID (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_PZF180PEX ( ( PCPS_REF_DCF << 8 ) | 0x06 ) + +#define PCI_DEV_GPS167PCI ( ( PCPS_REF_GPS << 8 ) | 0x01 ) +#define PCI_DEV_GPS168PCI ( ( PCPS_REF_GPS << 8 ) | 0x02 ) +#define PCI_DEV_GPS169PCI ( ( PCPS_REF_GPS << 8 ) | 0x03 ) +#define PCI_DEV_GPS170PCI ( ( PCPS_REF_GPS << 8 ) | 0x04 ) +#define PCI_DEV_GPS170PEX ( ( PCPS_REF_GPS << 8 ) | 0x05 ) +#define PCI_DEV_GPS180PEX ( ( PCPS_REF_GPS << 8 ) | 0x06 ) + +#define PCI_DEV_TCR510PCI ( ( PCPS_REF_IRIG << 8 ) | 0x01 ) +#define PCI_DEV_TCR167PCI ( ( PCPS_REF_IRIG << 8 ) | 0x02 ) +#define PCI_DEV_TCR511PCI ( ( PCPS_REF_IRIG << 8 ) | 0x03 ) +#define PCI_DEV_TCR511PEX ( ( PCPS_REF_IRIG << 8 ) | 0x04 ) +#define PCI_DEV_TCR170PEX ( ( PCPS_REF_IRIG << 8 ) | 0x05 ) +#define PCI_DEV_TCR180PEX ( ( PCPS_REF_IRIG << 8 ) | 0x06 ) + +#define PCI_DEV_PTP270PEX ( ( PCPS_REF_PTP << 8 ) | 0x01 ) + +#define PCI_DEV_FRC511PEX ( ( PCPS_REF_FRC << 8 ) | 0x01 ) + + + +// definitions used for the status port register +// (not to be intermixed with PCPS_TIME_STATUS) +typedef uint8_t PCPS_STATUS_PORT; /**< see @ref group_status_port "Bitmask" */ + +/** + * @defgroup group_status_port Bit masks of PCPS_STATUS_PORT + * + * Bit definitions used with the #PCPS_STATUS_PORT register. + * + * The flags #PCPS_ST_SEC and #PCPS_ST_MIN are cleared whenever the clock + * is read, so they are not very reliable in multitasking environments. + * + * @note The PCPS_ST_IRQF flag originates from old ISA cards. + * Some PCI cards also support this, but in case of PCI cards the + * associated flag of the PCI interface chip should be checked to see + * if a certain card has generated an IRQ on the PC bus. + * + * The macro _pcps_ddev_has_gen_irq() cares about this and should be used + * to determine in a portable way whether a card has generated an IRQ. + * + * @{ */ + +#define PCPS_ST_BUSY 0x01 /**< the clock is busy filling the output FIFO */ +#define PCPS_ST_IRQF 0x02 /**< the clock has generated an IRQ on the PC bus (ISA only)*/ +#define PCPS_ST_MOD 0x20 /**< the raw demodulated DCF77 signal */ +#define PCPS_ST_SEC 0x40 /**< seconds have changed since last reading */ +#define PCPS_ST_MIN 0x80 /**< minutes have changed since last reading */ + +/** @} group_status_port */ + +/** + * A format string to be used with snprintb() which is available on some Unix + * systems to print information held in a bit coded variable. + */ +#define MBG_PCPS_FMT_STATUS \ + "\177\20b\0FREER\0b\1DL_ENB\0b\2SYNCD\0b\3DL_ANN\0b\4UTC\0b\5LS_ANN\0b\6IFTM\0b\7INVT" \ + "\0b\x08LS_ENB\0b\11ANT_FAIL\0b\x0aLS_ANN_NEG\0b\x0bSCALE_GPS\0b\x0cSCALE_TAI\0\0" + + + +/** @defgroup group_cmd_bytes Command bytes used to access the device + + The commands described below are used to access computer peripherals + manufactured by Meinberg. + + The header files pcpsdev.h and pcpsdrvr.h contain macros which can be + used to check if a detected device supports a certain feature or command. + If checking is required then the name of the macro is given in the + comments 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_GET_CORR_INFO<br> + Read PZF correlation info using a CORR_INFO + structure. + _pcps_has_pzf() checks whether supported. + + - #PCPS_GET_TR_DISTANCE<br> + #PCPS_SET_TR_DISTANCE<br> + Read or write distance from the RF transmitter. + This is used to compensate the RF propagation delay + for PZF receivers. + _pcps_has_tr_distance() checks whether supported. + + - #PCPS_CLR_EVT_LOG<br> + Clear on-board event log. + _pcps_has_evt_log() checks whether supported. + + - #PCPS_NUM_EVT_LOG_ENTRIES<br> + Read max number of num event log entries which can + be saved on the board, and how many entries actually + have been saved. + _pcps_has_evt_log() checks whether supported. + + - #PCPS_FIRST_EVT_LOG_ENTRY<br> + - #PCPS_NEXT_EVT_LOG_ENTRY<br> + Read first (oldest) or next event log entry. + _pcps_has_evt_log() checks whether supported. + + - #PCPS_FORCE_RESET<br> + Resets the microprocessor on the device. This is + for special test scenarios only and should not be + used by standard applications since this may lock up + the PC. + + The command codes listed above are defined below. + + @{ */ + + +#if _IS_MBG_FIRMWARE //##++ + +// These group codes are obsolete and should be removed. +// The explicite command codes defined below should be used instead. +#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 + +#endif + + + +#define PCPS_GIVE_TIME 0x00 +#define PCPS_GIVE_TIME_NOCLEAR 0x01 +#define PCPS_GIVE_SYNC_TIME 0x02 // only supported if _pcps_has_sync_time() +#define PCPS_GIVE_HR_TIME 0x03 // only supported if _pcps_has_hr_time() +#define PCPS_GIVE_IRIG_TIME 0x04 // only supported if _pcps_has_irig_time() + +#define PCPS_SET_TIME 0x10 +/* 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 0x14 + +#define PCPS_IRQ_NONE 0x20 +#define PCPS_IRQ_1_SEC 0x21 +#define PCPS_IRQ_1_MIN 0x22 +#define PCPS_IRQ_10_MIN 0x24 +#define PCPS_IRQ_30_MIN 0x28 + +#define PCPS_GET_SERIAL 0x30 +#define PCPS_SET_SERIAL 0x31 +/* on error, return PCPS_ERR_CFG */ + +typedef uint8_t PCPS_SERIAL; + + +#define PCPS_GET_TZCODE 0x32 +#define PCPS_SET_TZCODE 0x33 +/* on error, return PCPS_ERR_CFG */ + +typedef uint8_t PCPS_TZCODE; + +/** + * @brief Enumeration of codes used with PCPS_TZCODE + */ +enum PCPS_TZCODES +{ + 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 0x34 +#define PCPS_SET_PCPS_TZDL 0x35 +/* on error, return PCPS_ERR_CFG */ + + +/** + * The structures below can be used to configure a clock's + * time zone/daylight saving setting. This structure is shorter + * than the TZDL structure used with GPS clocks. + */ +typedef struct +{ + // The year_or_wday field below contains the full year number + // or 0..6 == Sun..Sat if the DL_AUTO_FLAG is set; see below. + uint16_t year_or_wday; + uint8_t month; + uint8_t mday; + uint8_t hour; + uint8_t min; +} PCPS_DL_ONOFF; + +#define _mbg_swab_pcps_dl_onoff( _p ) \ +{ \ + _mbg_swab16( &(_p)->year_or_wday ); \ +} + +/** + * If the field year_or_wday is or'ed with the constant DL_AUTO_FLAG + * defined below then this means that start and end of daylight saving + * time shall be computed automatically for each year. In this case + * the remaining bits represent the day-of-week after the specified + * mday/month at which the change shall occur. If that flag is not set + * then the field contains the full four-digit year number and the + * mday/month values specify the exact date of that year. + */ +#define DL_AUTO_FLAG 0x8000 // also defined in gpsdefs.h + +typedef struct +{ + int16_t offs; /**< offset from %UTC to local time [min] */ + int16_t offs_dl; /**< additional offset if DST enabled [min] */ + PCPS_DL_ONOFF tm_on; /**< date/time when daylight saving starts */ + PCPS_DL_ONOFF tm_off; /**< date/time when daylight saving ends */ +} PCPS_TZDL; + +#define _mbg_swab_pcps_tzdl( _p ) \ +{ \ + _mbg_swab16( &(_p)->offs ); \ + _mbg_swab16( &(_p)->offs_dl ); \ + _mbg_swab_pcps_dl_onoff( &(_p)->tm_on ); \ + _mbg_swab_pcps_dl_onoff( &(_p)->tm_off ); \ +} + + + +#define PCPS_GET_REF_OFFS 0x36 +#define PCPS_SET_REF_OFFS 0x37 +/* on error, return PCPS_ERR_CFG */ + +/* The associated type MBG_REF_OFFS is defined in gpsdefs.h. */ + + +#define PCPS_GET_OPT_INFO 0x38 +#define PCPS_SET_OPT_SETTINGS 0x39 +/* 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 0x3A +#define PCPS_SET_IRIG_RX_SETTINGS 0x3B +/* on error, return PCPS_ERR_CFG */ + +#define PCPS_GET_IRIG_TX_INFO 0x3C +#define PCPS_SET_IRIG_TX_SETTINGS 0x3D +/* on error, return PCPS_ERR_CFG */ + +/* The associated structures IRIG_INFO and IRIG_SETTINGS + are defined in gpsdefs.h. */ + + +#define PCPS_GET_SYNTH 0x3E +#define PCPS_SET_SYNTH 0x3F +/* on error, return PCPS_ERR_CFG */ + +/* The associated structure SYNTH is defined in gpsdefs.h. */ + + +#define PCPS_GIVE_FW_ID_1 0x40 +#define PCPS_GIVE_FW_ID_2 0x41 +#define PCPS_GIVE_SERNUM 0x42 +#define PCPS_GENERIC_IO 0x43 +#define PCPS_GET_SYNTH_STATE 0x44 +#define PCPS_GET_IRIG_CTRL_BITS 0x45 +#define PCPS_GET_RAW_IRIG_DATA 0x46 + + + +#define PCPS_GET_STATUS_PORT 0x4B +#define PCPS_GET_DEBUG_STATUS 0x4C +// expects sizeof( MBG_DEBUG_STATUS ) chars + +// Command codes 0x4D, 0x4E, and 0x4F are reserved. + + +#define PCPS_READ_GPS_DATA 0x50 +#define PCPS_WRITE_GPS_DATA 0x51 + +#define PCPS_CLR_UCAP_BUFF 0x60 +#define PCPS_GIVE_UCAP_ENTRIES 0x61 +#define PCPS_GIVE_UCAP_EVENT 0x62 + +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 ); \ +} + + + +#define PCPS_GET_CORR_INFO 0x63 // read CORR_INFO structure, only if _pcps_has_pzf() +#define PCPS_GET_TR_DISTANCE 0x64 // read TR_DISTANCE, only if _pcps_has_tr_distance() +#define PCPS_SET_TR_DISTANCE 0x65 // write TR_DISTANCE, only if _pcps_has_tr_distance() + + +#define PCPS_CLR_EVT_LOG 0x66 // clear on-board event log, only if _pcps_has_evt_log() +#define PCPS_NUM_EVT_LOG_ENTRIES 0x67 // read num event log entries, only if _pcps_has_evt_log() +#define PCPS_FIRST_EVT_LOG_ENTRY 0x68 // read first (oldest) event log entry, only if _pcps_has_evt_log() +#define PCPS_NEXT_EVT_LOG_ENTRY 0x69 // read next event log entry, only if _pcps_has_evt_log() + + +/** + special -- use with care ! +*/ +#define PCPS_FORCE_RESET 0x80 + +// Command codes 0xF0 through 0xFF are reserved. + +/** @} group_cmd_bytes */ + + +#if !defined( MBG_CMD_TABLE_EXT ) + #define MBG_CMD_TABLE_EXT { 0, NULL } +#endif + +/** + * @brief An initializer for a table of code/name entries of non-GPS commands. + * + * This can e.g. be assigned to an array of MBG_CODE_NAME_TABLE_ENTRY elements + * and may be helpful when debugging. + */ +#define MBG_CMD_TABLE \ +{ \ + { PCPS_GIVE_TIME, "PCPS_GIVE_TIME" }, /* 00 */ \ + { PCPS_GIVE_TIME_NOCLEAR, "PCPS_GIVE_TIME_NOCLEAR" }, /* 01 */ \ + { PCPS_GIVE_SYNC_TIME, "PCPS_GIVE_SYNC_TIME" }, /* 02 */ \ + { PCPS_GIVE_HR_TIME, "PCPS_GIVE_HR_TIME" }, /* 03 */ \ + { PCPS_GIVE_IRIG_TIME, "PCPS_GIVE_IRIG_TIME" }, /* 04 */ \ + { PCPS_SET_TIME, "PCPS_SET_TIME" }, /* 10 */ \ + { PCPS_SET_EVENT_TIME, "PCPS_SET_EVENT_TIME" }, /* 14 */ \ + { PCPS_IRQ_NONE, "PCPS_IRQ_NONE" }, /* 20 */ \ + { PCPS_IRQ_1_SEC, "PCPS_IRQ_1_SEC" }, /* 21 */ \ + { PCPS_IRQ_1_MIN, "PCPS_IRQ_1_MIN" }, /* 22 */ \ + { PCPS_IRQ_10_MIN, "PCPS_IRQ_10_MIN" }, /* 24 */ \ + { PCPS_IRQ_30_MIN, "PCPS_IRQ_30_MIN" }, /* 28 */ \ + { PCPS_GET_SERIAL, "PCPS_GET_SERIAL" }, /* 30 */ \ + { PCPS_SET_SERIAL, "PCPS_SET_SERIAL" }, /* 31 */ \ + { PCPS_GET_TZCODE, "PCPS_GET_TZCODE" }, /* 32 */ \ + { PCPS_SET_TZCODE, "PCPS_SET_TZCODE" }, /* 33 */ \ + { PCPS_GET_PCPS_TZDL, "PCPS_GET_PCPS_TZDL" }, /* 34 */ \ + { PCPS_SET_PCPS_TZDL, "PCPS_SET_PCPS_TZDL" }, /* 35 */ \ + { PCPS_GET_REF_OFFS, "PCPS_GET_REF_OFFS" }, /* 36 */ \ + { PCPS_SET_REF_OFFS, "PCPS_SET_REF_OFFS" }, /* 37 */ \ + { PCPS_GET_OPT_INFO, "PCPS_GET_OPT_INFO" }, /* 38 */ \ + { PCPS_SET_OPT_SETTINGS, "PCPS_SET_OPT_SETTINGS" }, /* 39 */ \ + { PCPS_GET_IRIG_RX_INFO, "PCPS_GET_IRIG_RX_INFO" }, /* 3A */ \ + { PCPS_SET_IRIG_RX_SETTINGS, "PCPS_SET_IRIG_RX_SETTINGS" }, /* 3B */ \ + { PCPS_GET_IRIG_TX_INFO, "PCPS_GET_IRIG_TX_INFO" }, /* 3C */ \ + { PCPS_SET_IRIG_TX_SETTINGS, "PCPS_SET_IRIG_TX_SETTINGS" }, /* 3D */ \ + { PCPS_GET_SYNTH, "PCPS_GET_SYNTH" }, /* 3E */ \ + { PCPS_SET_SYNTH, "PCPS_SET_SYNTH" }, /* 3F */ \ + { PCPS_GIVE_FW_ID_1, "PCPS_GIVE_FW_ID_1" }, /* 40 */ \ + { PCPS_GIVE_FW_ID_2, "PCPS_GIVE_FW_ID_2" }, /* 41 */ \ + { PCPS_GIVE_SERNUM, "PCPS_GIVE_SERNUM" }, /* 42 */ \ + { PCPS_GENERIC_IO, "PCPS_GENERIC_IO" }, /* 43 */ \ + { PCPS_GET_SYNTH_STATE, "PCPS_GET_SYNTH_STATE" }, /* 44 */ \ + { PCPS_GET_IRIG_CTRL_BITS, "PCPS_GET_IRIG_CTRL_BITS" }, /* 45 */ \ + { PCPS_GET_RAW_IRIG_DATA, "PCPS_GET_RAW_IRIG_DATA" }, /* 46 */ \ + { PCPS_GET_STATUS_PORT, "PCPS_GET_STATUS_PORT" }, /* 4B */ \ + { PCPS_GET_DEBUG_STATUS, "PCPS_GET_DEBUG_STATUS" }, /* 4C */ \ + { PCPS_READ_GPS_DATA, "PCPS_READ_GPS_DATA" }, /* 50 */ \ + { PCPS_WRITE_GPS_DATA, "PCPS_WRITE_GPS_DATA" }, /* 51 */ \ + { PCPS_CLR_UCAP_BUFF, "PCPS_CLR_UCAP_BUFF" }, /* 60 */ \ + { PCPS_GIVE_UCAP_ENTRIES, "PCPS_GIVE_UCAP_ENTRIES" }, /* 61 */ \ + { PCPS_GIVE_UCAP_EVENT, "PCPS_GIVE_UCAP_EVENT" }, /* 62 */ \ + { PCPS_GET_CORR_INFO, "PCPS_GET_CORR_INFO" }, /* 63 */ \ + { PCPS_GET_TR_DISTANCE, "PCPS_GET_TR_DISTANCE" }, /* 64 */ \ + { PCPS_SET_TR_DISTANCE, "PCPS_SET_TR_DISTANCE" }, /* 65 */ \ + { PCPS_CLR_EVT_LOG, "PCPS_CLR_EVT_LOG" }, /* 66 */ \ + { PCPS_NUM_EVT_LOG_ENTRIES, "PCPS_NUM_EVT_LOG_ENTRIES" }, /* 67 */ \ + { PCPS_FIRST_EVT_LOG_ENTRY, "PCPS_FIRST_EVT_LOG_ENTRY" }, /* 68 */ \ + { PCPS_NEXT_EVT_LOG_ENTRY, "PCPS_NEXT_EVT_LOG_ENTRY" }, /* 69 */ \ + { PCPS_FORCE_RESET, "PCPS_FORCE_RESET" }, /* 80 */ \ + MBG_CMD_TABLE_EXT, \ + { 0, NULL } \ +} + + + +/* 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 for a cmd writing config parameters */ + + + +#ifndef BITMASK + #define BITMASK( b ) ( ( 1 << b ) - 1 ) +#endif + + +/** The size of the plug-in card'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 ) + + +typedef struct +{ + PCPS_TIME_STATUS_X set_mask; + PCPS_TIME_STATUS_X clr_mask; + +} PCPS_TIME_STATUS_X_MASKS; + +#define _mbg_swab_pcps_time_status_x_masks( _p ) \ +{ \ + _mbg_swab_pcps_time_status_x( &(_p)->set_mask ); \ + _mbg_swab_pcps_time_status_x( &(_p)->clr_mask ); \ +} + + + +/** + * The structure has been introduced to be able to read the + * current time with higher resolution of fractions of seconds and + * more detailed information on the time zone and status. + * The structure is returned if the new command #PCPS_GIVE_HR_TIME + * is written to the board. + * _pcps_has_hr_time() checks whether supported. + * + * Newer GPS boards also accept the #PCPS_GIVE_UCAP_EVENT command + * to return user capture event times using this format. In this + * case, the "signal" field contains the number of the capture + * input line, e.g. 0 or 1. + * _pcps_has_ucap() checks whether supported. + */ +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 */ + +/** + * Bit masks used only with time stamps representing user capture events + */ +#define PCPS_UCAP_OVERRUN 0x2000 /**< events interval too short */ +#define PCPS_UCAP_BUFFER_FULL 0x4000 /**< events read too slow */ + +/** + * Bit masks used only with time stamps representing the current board time. + * A DCF77 PZF receiver can set this bit if it is actually synchronized + * using PZF correlation and thus provides higher accuracy than AM receivers. + */ +#define PCPS_SYNC_PZF 0x2000 /**< same code as PCPS_UCAP_OVERRUN */ + +/** + * 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 */ + + +/** + * Some definitions used with PZF receivers + */ + +/* receiver distance from transmitter [km] */ +typedef uint16_t TR_DISTANCE; + +#define _mbg_swab_tr_distance( _p ) \ + _mbg_swab16( _p ) + + + +/* correlation status info */ +typedef struct +{ + uint8_t val; /**< correlation value, or check count if status == PZF_CORR_CHECK */ + uint8_t status; /**< status codes, see below */ + char corr_dir; /**< space, '<', or '>' */ + uint8_t signal; /**< signal level, may always be 0 for devices which do not support this */ +} CORR_INFO; + +#define _mbg_swab_corr_info( _p ) \ + _nop_macro_fnc() + + +/** Codes used with CORR_INFO::status: */ +enum +{ + PZF_CORR_RAW, /**< trying raw correlation, combi receivers running in AM mode */ + PZF_CORR_CHECK, /**< raw correlation achieved, doing plausibility checks */ + PZF_CORR_FINE, /**< fine correlation achieved */ + N_PZF_CORR_STATE +}; + + +#define PZF_CORR_STATE_NAME_RAW_ENG "Searching" +#define PZF_CORR_STATE_NAME_CHECK_ENG "Correlating" +#define PZF_CORR_STATE_NAME_FINE_ENG "Locked" + +#define PZF_CORR_STATE_NAME_RAW_GER "suchen" +#define PZF_CORR_STATE_NAME_CHECK_GER "korrelieren" +#define PZF_CORR_STATE_NAME_FINE_GER "eingerastet" + + +#define PZF_CORR_STATE_NAMES_ENG \ +{ \ + PZF_CORR_STATE_NAME_RAW_ENG, \ + PZF_CORR_STATE_NAME_CHECK_ENG, \ + PZF_CORR_STATE_NAME_FINE_ENG \ +} + + +#define PZF_CORR_STATE_NAMES_LSTR \ +{ \ + { PZF_CORR_STATE_NAME_RAW_ENG, PZF_CORR_STATE_NAME_RAW_GER }, \ + { PZF_CORR_STATE_NAME_CHECK_ENG, PZF_CORR_STATE_NAME_CHECK_GER }, \ + { PZF_CORR_STATE_NAME_FINE_ENG, PZF_CORR_STATE_NAME_FINE_GER } \ +} + + + +/** @defgroup group_gps_cmds_bus GPS commands passed via the system bus + + This enumeration defines the various types of data that can be read + from or written to Meinberg bus level devices which support this. + Access should be done using the functions pcps_read_gps_data() + and pcps_write_gps_data() since the size of some of the structures + exceeds the size of the device's I/O buffer and must therefore be + accessed in several blocks. + + The structures to be used are defined in gpsdefs.h. Not all structures + are supported, 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 + PC_GPS_PTP_UC_MASTER_CFG_LIMITS, // R/- PTP_UC_MASTER_CFG_LIMITS, only if can be unicast master + PC_GPS_ALL_PTP_UC_MASTER_INFO, // R/- n*PTP_UC_MASTER_INFO_IDX, only if can be unicast master + PC_GPS_PTP_UC_MASTER_SETTINGS_IDX, // -/W PTP_UC_MASTER_SETTINGS_IDX, only if can be unicast master + PC_GPS_GPIO_CFG_LIMITS, // R/- MBG_GPIO_CFG_LIMITS, only if PCPS_HAS_GPIO + PC_GPS_ALL_GPIO_INFO, // R/- n*MBG_GPIO_INFO, all GPIO info, only if PCPS_HAS_GPIO + PC_GPS_GPIO_SETTINGS_IDX, // -/W MBG_GPIO_SETTINGS_IDX, GPIO cfg for a specific port, only if PCPS_HAS_GPIO + + // 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 +}; + +/** @} group_gps_cmds_bus */ + + + +/** + * @brief An initializer for a table of code/name entries of GPS commands. + * + * This can e.g. be assigned to an array of MBG_CODE_NAME_TABLE_ENTRY elements + * and may be helpful when debugging. + */ +#define MBG_PC_GPS_CMD_TABLE \ +{ \ + { PC_GPS_TZDL, "PC_GPS_TZDL" }, \ + { PC_GPS_SW_REV, "PC_GPS_SW_REV" }, \ + { PC_GPS_BVAR_STAT, "PC_GPS_BVAR_STAT" }, \ + { PC_GPS_TIME, "PC_GPS_TIME" }, \ + { PC_GPS_POS_XYZ, "PC_GPS_POS_XYZ" }, \ + { PC_GPS_POS_LLA, "PC_GPS_POS_LLA" }, \ + { PC_GPS_PORT_PARM, "PC_GPS_PORT_PARM" }, \ + { PC_GPS_ANT_INFO, "PC_GPS_ANT_INFO" }, \ + { PC_GPS_UCAP, "PC_GPS_UCAP" }, \ + { PC_GPS_ENABLE_FLAGS, "PC_GPS_ENABLE_FLAGS" }, \ + { PC_GPS_STAT_INFO, "PC_GPS_STAT_INFO" }, \ + { PC_GPS_CMD, "PC_GPS_CMD" }, \ + { PC_GPS_IDENT, "PC_GPS_IDENT" }, \ + { PC_GPS_POS, "PC_GPS_POS" }, \ + { PC_GPS_ANT_CABLE_LEN, "PC_GPS_ANT_CABLE_LEN" }, \ + { PC_GPS_RECEIVER_INFO, "PC_GPS_RECEIVER_INFO" }, \ + { PC_GPS_ALL_STR_TYPE_INFO, "PC_GPS_ALL_STR_TYPE_INFO" }, \ + { PC_GPS_ALL_PORT_INFO, "PC_GPS_ALL_PORT_INFO" }, \ + { PC_GPS_PORT_SETTINGS_IDX, "PC_GPS_PORT_SETTINGS_IDX" }, \ + { PC_GPS_ALL_POUT_INFO, "PC_GPS_ALL_POUT_INFO" }, \ + { PC_GPS_POUT_SETTINGS_IDX, "PC_GPS_POUT_SETTINGS_IDX" }, \ + { PC_GPS_TIME_SCALE, "PC_GPS_TIME_SCALE" }, \ + { PC_GPS_LAN_IF_INFO, "PC_GPS_LAN_IF_INFO" }, \ + { PC_GPS_IP4_STATE, "PC_GPS_IP4_STATE" }, \ + { PC_GPS_IP4_SETTINGS, "PC_GPS_IP4_SETTINGS" }, \ + { PC_GPS_PTP_STATE, "PC_GPS_PTP_STATE" }, \ + { PC_GPS_PTP_CFG, "PC_GPS_PTP_CFG" }, \ + { PC_GPS_PTP_UC_MASTER_CFG_LIMITS, "PC_GPS_PTP_UC_MASTER_CFG_LIMITS" }, \ + { PC_GPS_ALL_PTP_UC_MASTER_INFO, "PC_GPS_ALL_PTP_UC_MASTER_INFO" }, \ + { PC_GPS_PTP_UC_MASTER_SETTINGS_IDX, "PC_GPS_PTP_UC_MASTER_SETTINGS_IDX" }, \ + { PC_GPS_GPIO_CFG_LIMITS, "PC_GPS_GPIO_CFG_LIMITS" }, \ + { PC_GPS_ALL_GPIO_INFO, "PC_GPS_ALL_GPIO_INFO" }, \ + { PC_GPS_GPIO_SETTINGS_IDX, "PC_GPS_GPIO_SETTINGS_IDX" }, \ + { PC_GPS_CFGH, "PC_GPS_CFGH" }, \ + { PC_GPS_ALM, "PC_GPS_ALM" }, \ + { PC_GPS_EPH, "PC_GPS_EPH" }, \ + { PC_GPS_UTC, "PC_GPS_UTC" }, \ + { PC_GPS_IONO, "PC_GPS_IONO" }, \ + { PC_GPS_ASCII_MSG, "PC_GPS_ASCII_MSG" }, \ + { 0, NULL } \ +} + + + +/** 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( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + +#endif /* _PCPSDEFS_H */ + diff --git a/mbglib/common/pcpsdev.h b/mbglib/common/pcpsdev.h new file mode 100644 index 0000000..b13d07a --- /dev/null +++ b/mbglib/common/pcpsdev.h @@ -0,0 +1,1711 @@ + +/************************************************************************** + * + * $Id: pcpsdev.h 1.51 2013/01/25 15:44:21Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions used to share information on radio clock devices + * between device drivers which have direct access to the hardware + * devices and user space programs which evaluate and present that + * information. + * + * At the bottom of the file there are some macros defined which + * should be used to access the structures to extract characteristics + * of an individual clock. + * + * ----------------------------------------------------------------------- + * $Log: pcpsdev.h $ + * Revision 1.51 2013/01/25 15:44:21Z martin + * Added inline function setup_hr_time_cycles_from_timestamp_cycles() which sets + * up a PCPS_HR_TIME_CYCLES structure from PCPS_TIME_STAMP_CYCLES. + * Revision 1.50 2012/10/02 19:00:46 martin + * Support GPS180PEX, TCR180PEX, and PZF180PEX. + * Support DCF600USB, TCR600USB, MSF600USB, and WVB600USB. + * Runtime support for precise time API introduced with Windows 8. + * This does not yet for x64 builds. + * There are some g++ versions which fail to compile source code using + * the macros provided by Linux to define IOCTL codes. If only the API + * functions are called by an application then the IOCTL codes aren't + * required anyway, so we just avoid inclusion of mbgioctl.h. + * However, some IOCTL related definitions are required anyway, so + * they have been moved to this file which is always included. + * Bug fix: Use negative sign for delay in KeDelayExecutionThread() + * Support on-board event logs. + * Moved macro _must_do_fw_workaround_20ms() here. + * New macro _pcps_has_debug_status(). + * Added some macros to test if specific stat_info stuff is supported. + * Moved some definitions useful for configuration tools to new file cfg_hlp.h. + * Moved IA64 includes from pcpsdev.h to mbgpccyc.h. + * Added macros _pcps_has_corr_info() and _pcps_has_tr_distance(). + * Extended bus flag for USB v2 and macro _pcps_is_usb_v2(). + * New feature ..._HAS_PZF and macro _pcps_has_pzf(). + * Moved PC cycles stuff to an new extra header. + * Cleaned up handling of pragma pack(). + * Introduced generic MBG_SYS_TIME with nanosecond resolution. + * Support struct timespec under Linux, if available. + * Use MBG_TGT_KERNEL instead of _KDD_. + * Added PTP unicast master configuration stuff. + * For compatibility use cpu_counter() instead of cpu_counter_serializing() under NetBSD. + * Optionally support timespec for sys time (USE_TIMESPEC). + * Support FreeBSD and NetBSD. + * Moved MBG_TGT_SUPP_MEM_ACC definition here. + * Moved status port register definitions to pcpsdefs.h. + * Features are now defined using enum and bit masks. + * Added initializer for feature names (used for debug). + * Added macro _pcps_features(). + * Implemented portable mbg_get_sys_uptime() and mbg_sleep_sec() + * functions and associated types. + * Revision 1.49 2010/06/30 13:03:48 martin + * Use new preprocessor symbol MBG_ARCH_X86. + * Use ulong port addresses for all platforms but x86. + * Support mbg_get_pc_cycles() for IA64, but mbg_get_pc_cycles_frequency() + * is not yet supported. + * Don't pack interface structures on Sparc and IA64 architecture. + * Revision 1.48 2010/04/26 14:47:42 martin + * Define symbol MBG_PC_CYCLES_SUPPORTED if this is the case. + * Revision 1.47 2010/01/12 14:03:22 daniel + * Added definitions to support reading the raw IRIG data bits. + * Revision 1.46 2009/09/29 15:10:35Z martin + * Support generic system time, and retrieving time discipline info. + * Added _pcps_has_fast_hr_timestamp() macro and associated feature flag. + * Revision 1.45 2009/06/19 12:15:18 martin + * Added has_irig_time feature and associated macros. + * Revision 1.44 2009/06/08 19:30:48 daniel + * Account for new features PCPS_HAS_LAN_INTF and + * PCPS_HAS_PTP. + * Revision 1.43 2009/04/08 08:26:20 daniel + * Define firmware version at which the TCR511PCI starts + * to support IRIG control bits. + * Revision 1.42 2009/03/19 14:58:47Z martin + * Tmp. workaround in mbg_delta_pc_cycles() under SPARC which might + * generate bus errors due to unaligned access. + * Revision 1.41 2009/03/16 16:01:22 martin + * Support reading IRIG control function bits. + * Revision 1.40 2009/03/13 09:13:39 martin + * Support new features .._has_time_scale() and .._has_utc_parm(). + * Moved some inline functions dealing with MBG_PC_CYCLES + * from mbgdevio.h here. + * Merged the code from _pcps_get_cycles() and _pcps_get_cycles_frequency() + * to the mbg_get_pc_cycles...() inline functions which now replace the + * _pcps_get_cycles...() macros. + * Fixed cycles code for non-x86 architectures. + * Revision 1.39 2008/12/05 16:24:24Z martin + * Changed MAX_PARM_STR_TYPE from 10 to 20. + * Added support for WWVB signal source. + * Support new devices PTP270PEX, FRC511PEX, TCR170PEX, and WWVB51USB. + * Added macros _pcps_is_ptp(), _pcps_is_frc(), and _pcps_is_wwvb(). + * Defined firmware version numbers which fix an IRQ problem with PEX511, + * TCR511PEX, and GPS170PEX cards. The fix also requires specific ASIC + * versions specified in pci_asic.h. + * Defined firmware versions at which PCI511 and PEX511 start + * to support HR time. + * Support mapped I/O resources. + * Changed MBG_PC_CYCLES type for Windows to int64_t. + * Renamed MBG_VIRT_ADDR to MBG_MEM_ADDR. + * Added MBG_PC_CYCLES_FREQUENCY type. + * Added definition of PCPS_TIME_STAMP_CYCLES. + * Added PCPS_IRQ_STAT_INFO type and associated flags. + * Added macros to convert the endianess of structures. + * Added macros _pcps_fw_rev_num_major() and _pcps_fw_rev_num_minor(). + * Made irq_num signed to use -1 for unassigned IRQ numbers. + * Revision 1.38 2008/01/17 10:12:34 daniel + * Added support for TCR51USB and MSF51USB. + * New type MBG_VIRT_ADDR to specify virtual address values. + * New struct PCPS_MAPPED_MEM + * Cleanup for PCI ASIC version and features. + * Added macros _pcps_is_msf(), _pcps_is_lwr(), + * _psps_has_asic_version(), _pcps_has_asic_features(). + * Revision 1.37 2008/01/17 09:58:11Z daniel + * Made comments compatible for doxygen parser. + * No sourcecode changes. + * Revision 1.36 2007/09/26 09:34:38Z martin + * Added support for USB in general and new USB device USB5131. + * Added new types PCPS_DEV_ID and PCPS_REF_TYPE. + * Removed old PCPS_ERR_... codes. Use MBG_ERR_... codes + * from mbgerror.h instead. The old values haven't changed. + * Revision 1.35 2007/07/17 08:22:47Z martin + * Added support for TCR511PEX and GPS170PEX. + * Revision 1.34 2007/07/16 12:50:41Z martin + * Added support for PEX511. + * Modified/renamed some macros and symbols. + * Revision 1.33 2007/03/02 09:40:04Z martin + * Changes due to renamed library symbols. + * Removed obsolete inclusion of headers. + * Preliminary support for *BSD. + * Preliminary support for USB. + * Revision 1.32 2006/10/23 08:47:55Z martin + * Don't use abs() in _pcps_ref_offs_out_of_range() since this might + * not work properly for 16 bit integers and value 0x8000. + * Revision 1.31 2006/06/14 12:59:13Z martin + * Added support for TCR511PCI. + * Revision 1.30 2006/04/05 14:58:41 martin + * Support higher baud rates for PCI511. + * Revision 1.29 2006/04/03 07:29:07Z martin + * Added a note about the missing PCPS_ST_IRQF signal + * on PCI510 cards. + * Revision 1.28 2006/03/10 10:32:56Z martin + * Added support for PCI511. + * Added support for programmable pulse outputs. + * Revision 1.27 2005/11/04 08:48:00Z martin + * Added support for GPS170PCI. + * Revision 1.26 2005/06/02 08:34:38Z martin + * New types MBG_DBG_PORT, MBG_DBG_DATA. + * Revision 1.25 2005/05/03 10:04:14 martin + * Added macro _pcps_is_pci_amcc(). + * Revision 1.24 2005/03/29 12:58:19Z martin + * Support GENERIC_IO feature. + * Revision 1.23 2004/12/09 11:03:37Z martin + * Support configuration of on-board frequency synthesizer. + * Revision 1.22 2004/11/09 12:57:52Z martin + * Redefined interface data types using C99 fixed-size definitions. + * Added support for TCR167PCI. + * New macro _pcps_has_gps_data(). + * New type PCPS_STATUS_PORT. + * Removed obsolete inclusion of asm/timex.h for Linux. + * Revision 1.21 2004/09/06 15:19:49Z martin + * Support a GPS_DATA interface where sizes are specified + * by 16 instead of the original 8 bit quantities, thus allowing + * to transfer data blocks which exceed 255 bytes. + * Modified inclusion of header files under Linux. + * Modified definition of MBG_PC_CYCLES for Linux. + * Revision 1.20 2004/04/14 09:09:11 martin + * Source code cleanup. + * Revision 1.19 2004/04/07 09:49:14Z martin + * Support new feature PCPS_HAS_IRIG_TX. + * New macros _pcps_has_irig(), _pcps_has_irig_tx(). + * Revision 1.18 2004/01/14 11:02:14Z MARTIN + * Added formal type MBG_PC_CYCLES for OS/2, + * though it's not really required or used. + * Revision 1.17 2003/12/22 15:40:16 martin + * Support higher baud rates for TCR510PCI and PCI510. + * Supports PCPS_HR_TIME for TCR510PCI. + * New structures used to read device time together with associated + * PC CPU cycles. + * For Win32, differentiate between kernel mode and non-kernel mode. + * Moved some definitions here from mbgdevio.h. + * New type PCPS_ASIC_VERSION. + * New macro _pcps_ref_offs_out_of_range(). + * Revision 1.16 2003/06/19 09:48:30Z MARTIN + * Renamed symbols ..clr_cap_buffer to ..clr_ucap_buffer. + * New macro _pcps_has_ucap(). + * New definitions to support cmds PCPS_GIVE_UCAP_ENTRIES + * and PCPS_GIVE_UCAP_EVENT. + * Revision 1.15 2003/04/15 09:57:25 martin + * New typedefs ALL_STR_TYPE_INFO, ALL_PORT_INFO, + * RECEIVER_PORT_CFG. + * Revision 1.14 2003/04/09 14:07:01Z martin + * Supports PCI510, GPS169PCI, and TCR510PCI, + * and new PCI_ASIC used by those devices. + * Renamed macro _pcps_is_irig() to _pcps_is_irig_rx(). + * New macros _pcps_has_ref_offs(), _pcps_has_opt_flags(). + * Fixed macro _pcps_has_hr_time(). + * New type PCPS_BUS_FLAGS. + * Preliminary support for PCPS_TZDL. + * Revision 1.13 2002/08/09 07:19:49 MARTIN + * Moved definition of ref time sources to pcpsdefs.h. + * New feature PCPS_CAN_CLR_CAP_BUFF and + * associated macro _pcps_can_clr_cap_buff(). + * New macros _pcps_is_irig(), _pcps_has_signal(), + * _pcps_has_mod(). + * Revision 1.12 2002/02/19 09:22:53 MARTIN + * Added definitions for the maximum number of clocks' serial ports + * and string types that can be handled by the configuration programs. + * Revision 1.11 2002/02/01 11:36:58 MARTIN + * Added new definitions for GPS168PCI. + * Inserted definitions of firmware REV_NUMs for supported features + * which had previously been defined in pcpsdefs.h. + * Include use_pack.h. + * Updated comments. + * Source code cleanup. + * Revision 1.10 2001/11/30 09:52:48 martin + * Added support for event_time which, however, requires + * a custom GPS firmware. + * Revision 1.9 2001/10/16 10:11:14 MARTIN + * New Macro _pcps_has_serial_hs() which determines whether + * DCF77 clock supports baud rate higher than default. + * Re-arranged order of macro definitions. + * Revision 1.8 2001/09/03 07:15:05 MARTIN + * Added macro to access the firmware revision number. + * Cleaned up macro syntax. + * Added some comments. + * Revision 1.7 2001/08/30 13:20:04 MARTIN + * New macro to mark a PCPS_TIME variable as unread. + * New macro to check if a PCPS_TIME variable is unread. + * Revision 1.6 2001/03/15 15:45:01 MARTIN + * Added types PCPS_ERR_FLAGS, PCPS_BUS_NUM, PCPS_SLOT_NUM. + * Revision 1.5 2001/03/01 13:53:10 MARTIN + * Initial version for the new driver library. + * + **************************************************************************/ + +#ifndef _PCPSDEV_H +#define _PCPSDEV_H + +#include <mbg_tgt.h> +#include <mbgtime.h> +#include <mbgpccyc.h> +#include <pcpsdefs.h> +#include <gpsdefs.h> +#include <usbdefs.h> +#include <use_pack.h> + +#if !defined( MBG_TGT_KERNEL ) + #include <string.h> +#endif + +#if defined( MBG_TGT_WIN32 ) + + #include <mbg_w32.h> + +#elif defined( MBG_TGT_LINUX ) + + #if defined( MBG_TGT_KERNEL ) + #include <linux/delay.h> + #include <linux/time.h> + #else + #include <unistd.h> + #include <time.h> + #include <sys/time.h> + #include <sys/sysinfo.h> + #endif + +#elif defined( MBG_TGT_FREEBSD ) + + #if defined( MBG_TGT_KERNEL ) + #include <sys/sysproto.h> + #include <sys/pcpu.h> + #include <sys/param.h> + #include <sys/systm.h> + #include <sys/proc.h> + #else + #include <unistd.h> + #include <sys/time.h> + #endif + +#elif defined( MBG_TGT_NETBSD ) + + #if defined( MBG_TGT_KERNEL ) + #include <sys/param.h> // mstohz + #include <sys/kernel.h> // hz + #else + #include <unistd.h> + #include <sys/time.h> + #endif + +#elif defined( MBG_TGT_QNX_NTO ) + + #include <unistd.h> + +#elif defined( MBG_TGT_DOS ) + + #include <dos.h> // for delay() + +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #if !defined( _NO_USE_PACK_INTF ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT + #endif +#endif + + +#if defined( MBG_TGT_UNIX ) + #define USE_GENERIC_SYS_TIME 1 +#else + #define USE_GENERIC_SYS_TIME 0 +#endif + + +#if USE_GENERIC_SYS_TIME + + typedef struct + { + uint64_t sec; + uint64_t nsec; + } NANO_TIME_64; + + typedef NANO_TIME_64 MBG_SYS_TIME; + +#endif + + + +/** + Define generic types to hold PC cycle counter values and system timestamps. + The generic types are defined using native types used by the target operating + systems. + + The cycle counter value is usually derived from the PC CPU's TSC or some other + timer hardware on the mainboard. + */ +#if defined( MBG_TGT_WIN32 ) + + #define MBG_TGT_SUPP_MEM_ACC 1 + + typedef int64_t MBG_SYS_UPTIME; // [s] + + typedef LARGE_INTEGER MBG_SYS_TIME; + +#elif defined( MBG_TGT_LINUX ) + + #define MBG_TGT_SUPP_MEM_ACC 1 + + typedef int64_t MBG_SYS_UPTIME; // [s] + +#elif defined( MBG_TGT_BSD ) + + #define MBG_TGT_SUPP_MEM_ACC 1 + + typedef int64_t MBG_SYS_UPTIME; // [s] + + #if defined( MBG_TGT_NETBSD ) + #ifdef __LP64__ + #define MBG_MEM_ADDR uint64_t + #else + #define MBG_MEM_ADDR uint32_t + #endif + #endif + +#elif defined( MBG_TGT_OS2 ) + + typedef long MBG_SYS_UPTIME; //## dummy + + typedef uint32_t MBG_SYS_TIME; //## dummy + +#elif defined( MBG_TGT_DOS ) + + #define MBG_MEM_ADDR uint32_t // 64 bit not supported, nor required. + + typedef long MBG_SYS_UPTIME; //## dummy + + typedef uint32_t MBG_SYS_TIME; //## dummy + +#else // other target OSs which access the hardware directly + + typedef long MBG_SYS_UPTIME; //## dummy + + typedef uint32_t MBG_SYS_TIME; //## dummy + +#endif + + +#if !defined( MBG_TGT_SUPP_MEM_ACC ) + #define MBG_TGT_SUPP_MEM_ACC 0 +#endif + + +// MBG_SYS_TIME is always read in native machine endianess, +// so no endianess conversion is required. +#define _mbg_swab_mbg_sys_time( _p ) \ + _nop_macro_fnc() + + + +/** + The structure holds a system timestamp in a format depending on the target OS + plus two cycles counter values which can be taken before and after reading + the system time. These cycles values can be used to determine the execution + time required to read the system time. + + Limitations of the operating system need to be taken into account, + e.g. the Windows system time may increase once every ~16 ms only. + */ +typedef struct +{ + MBG_PC_CYCLES cyc_before; /**< cycles count before sys time is read */ + MBG_PC_CYCLES cyc_after; /**< cycles count after sys time has been read */ + MBG_SYS_TIME sys_time; /**< system time stamp */ +} MBG_SYS_TIME_CYCLES; + +#define _mbg_swab_mbg_sys_time_cycles( _p ) \ +{ \ + _mbg_swab_mbg_pc_cycles( &(_p)->cyc_before ); \ + _mbg_swab_mbg_pc_cycles( &(_p)->cyc_after ); \ + _mbg_swab_mbg_sys_time( &(_p)->sys_time ); \ +} + + + + +static __mbg_inline +void mbg_get_sys_time( MBG_SYS_TIME *p ) +{ + #if defined( MBG_TGT_WIN32 ) + + #if defined( MBG_TGT_KERNEL ) // kernel space + #if defined( MBG_TGT_WIN32_PNP ) && !defined( MBG_TGT_WIN32_PNP_X64 ) + extern KE_QUERY_SYSTEM_TIME_FNC ke_query_system_time_fnc; + ke_query_system_time_fnc( p ); + #else + KeQuerySystemTime( p ); + #endif + #else // user space + { + FILETIME ft; + GetSystemTimeAsFileTime( &ft ); + p->LowPart = ft.dwLowDateTime; + p->HighPart = ft.dwHighDateTime; + } + #endif + + #elif defined( MBG_TGT_LINUX ) + + #if defined( MBG_TGT_KERNEL ) + + #if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 22 ) ) //##+++++++++++++ + { + // getnstimeofday() supported + struct timespec ts; + + getnstimeofday( &ts ); + + p->sec = ts.tv_sec; + p->nsec = ts.tv_nsec; + } + #else + { + // getnstimeofday() *not* supported + struct timeval tv; + + do_gettimeofday( &tv ); + + p->sec = tv.tv_sec; + p->nsec = tv.tv_usec * 1000; + } + #endif + + #else // Linux user space + { + struct timespec ts; + + clock_gettime( CLOCK_REALTIME, &ts ); + + p->sec = ts.tv_sec; + p->nsec = ts.tv_nsec; + } + #endif + + #elif defined( MBG_TGT_BSD ) + + struct timespec ts; + + #if defined( MBG_TGT_KERNEL ) + nanotime( &ts ); + #else + #if defined( MBG_TGT_FREEBSD ) + clock_gettime( CLOCK_REALTIME_PRECISE, &ts ); + #else // MBG_TGT_NETBSD, ... + clock_gettime( CLOCK_REALTIME, &ts ); + #endif + #endif + + p->sec = ts.tv_sec; + p->nsec = ts.tv_nsec; + + #else + + *p = 0; + + #endif + +} // mbg_get_sys_time + + + +static __mbg_inline +void mbg_get_sys_uptime( MBG_SYS_UPTIME *p ) +{ + #if defined( MBG_TGT_WIN32 ) + + #if defined( MBG_TGT_KERNEL ) // kernel space + + ULONGLONG time_increment = KeQueryTimeIncrement(); + LARGE_INTEGER tick_count; + + KeQueryTickCount( &tick_count ); + + // multiplication by time_increment yields HNS units, + // but we need seconds + *p = ( tick_count.QuadPart * time_increment ) / HNS_PER_SEC; + + #else // user space + + DWORD tickCount; + DWORD timeAdjustment; + DWORD timeIncrement; + BOOL timeAdjustmentDisabled; + + if ( !GetSystemTimeAdjustment( &timeAdjustment, &timeIncrement, &timeAdjustmentDisabled ) ) + *p = -1; // failed + + // ATTENTION: This is compatible with older Windows versions, but + // the returned tick count wraps around to zero after 49.7 days. + // A new GetTickCount64() call is available under Windows Vista and newer, + // but the function call had to be imported dynamically since otherwise + // programs refused to start under pre-Vista versions due to undefined DLL symbol. + tickCount = GetTickCount(); + + *p = ( ( (MBG_SYS_UPTIME) tickCount ) * timeIncrement ) / HNS_PER_SEC; + + #endif + + #elif defined( MBG_TGT_LINUX ) + + #if defined( MBG_TGT_KERNEL ) + { + // Using a simple 64 bit division may result in a linker error + // in kernel mode due to a missing symbol __udivdi3, so we use + // a specific inline function do_div(). + // Also, the jiffies counter is not set to 0 at startup but to + // a defined initialization value we need to account for. + uint64_t tmp = get_jiffies_64() - INITIAL_JIFFIES; + do_div( tmp, HZ ); + *p = tmp; + } + #else + { + struct sysinfo si; + int rc = sysinfo( &si ); + *p = ( rc == 0 ) ? si.uptime : -1; + } + #endif + + #elif defined( MBG_TGT_BSD ) + + #if defined( MBG_TGT_KERNEL ) + { + struct timespec ts; + #if 0 //##+++++++ + { + struct bintime bt; + + binuptime( &bt ); + #if defined( DEBUG ) + printf( "binuptime: %lli.%09lli\n", + (long long) bt.sec, + (long long) bt.frac ); + #endif + } + #endif + + nanouptime( &ts ); + #if defined( DEBUG ) + printf( "nanouptime: %lli.%09lli\n", + (long long) ts.tv_sec, + (long long) ts.tv_nsec ); + #endif + *p = ts.tv_sec; + } + #elif defined( MBG_TGT_FREEBSD ) + { + struct timespec ts; + // CLOCK_UPTIME_FAST is specific to FreeBSD + int rc = clock_gettime( CLOCK_UPTIME_FAST, &ts ); + *p = ( rc == 0 ) ? ts.tv_sec : -1; + } + #else // MBG_TGT_NETBSD, ... + + *p = -1; //##++ needs to be implemented + + #endif + + #else + + *p = -1; // not supported + + #endif + +} // mbg_get_sys_uptime + + + +static __mbg_inline +void mbg_sleep_sec( long sec ) +{ + #if defined( MBG_TGT_WIN32 ) + + #if defined( MBG_TGT_KERNEL ) // kernel space + LARGE_INTEGER delay; + + // we need to pass a negative value to KeDelayExecutionThread() + // since the given time is a relative time interval, not absolute + // time. See the API docs for KeDelayExecutionThread(). + delay.QuadPart = - ((LONGLONG) sec * HNS_PER_SEC); + + KeDelayExecutionThread( KernelMode, FALSE, &delay ); + #else // user space + // Sleep() expects milliseconds + Sleep( sec * 1000 ); + #endif + + #elif defined( MBG_TGT_LINUX ) + + #if defined( MBG_TGT_KERNEL ) + // msleep is not defined in older kernels, so we use this + // only if it is surely supported. + #if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 16 ) ) //##+++++ + msleep( sec * 1000 ); + #else + { + DECLARE_WAIT_QUEUE_HEAD( tmp_wait ); + wait_event_interruptible_timeout( tmp_wait, 0, sec * HZ + 1 ); + } + #endif + #else + sleep( sec ); + #endif + + #elif defined( MBG_TGT_BSD ) + + #if defined( MBG_TGT_KERNEL ) + #if defined( MBG_TGT_FREEBSD ) + struct timeval tv = { 0 }; + int ticks; + tv.tv_sec = sec; + ticks = tvtohz( &tv ); + #if defined( DEBUG ) + printf( "pause: %lli.%06lli (%i ticks)\n", + (long long) tv.tv_sec, + (long long) tv.tv_usec, + ticks ); + #endif + pause( "pause", ticks ); + #elif defined( MBG_TGT_NETBSD ) + int timeo = mstohz( sec * 1000 ); + #if defined( DEBUG ) + printf( "kpause: %i s (%i ticks)\n", sec, timeo ); + #endif + kpause( "pause", 1, timeo, NULL ); + #endif + #else + sleep( sec ); + #endif + + #elif defined( MBG_TGT_QNX_NTO ) + + // Actually only tested under Neutrino. + sleep( sec ); + + #elif defined( MBG_TGT_DOS ) + + delay( (unsigned) ( sec * 1000 ) ); + + #else + + // This needs to be implemented for the target OS + // and thus will probably yield a linker error. + do_sleep_sec( sec ); + + #endif + +} // mbg_sleep_sec + + + +#if !defined( MBG_MEM_ADDR ) + // By default a memory address is stored + // as a 64 bit quantitiy. + #define MBG_MEM_ADDR uint64_t +#endif + + +typedef uint8_t MBG_DBG_DATA; +typedef uint16_t MBG_DBG_PORT; + + +// The following flags describe the bus types which are +// supported by the plugin clocks. +#define PCPS_BUS_ISA 0x0001 // IBM compatible PC/AT ISA bus +#define PCPS_BUS_MCA 0x0002 // IBM PS/2 micro channel +#define PCPS_BUS_PCI 0x0004 // PCI +#define PCPS_BUS_USB 0x0008 // USB + + +// The flags below are or'ed to the PC_BUS_PCI code +// in order to indicate which PCI interface chip is used +// on a PCI card. If no flag is set then the S5933 chip is +// installed which has been used for the first generation +// of Meinberg PCI cards. +#define PCPS_BUS_PCI_CHIP_S5920 0x8000 // S5920 PCI interface chip. +#define PCPS_BUS_PCI_CHIP_ASIC 0x4000 // Meinberg's own PCI interface chip. +#define PCPS_BUS_PCI_CHIP_PEX8311 0x2000 // PEX8311 PCI Express interface chip +#define PCPS_BUS_PCI_CHIP_MBGPEX 0x1000 // Meinberg's own PCI Express interface chip + +// The constants below combine the PCI bus flags: +#define PCPS_BUS_PCI_S5933 ( PCPS_BUS_PCI ) +#define PCPS_BUS_PCI_S5920 ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_S5920 ) +#define PCPS_BUS_PCI_ASIC ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_ASIC ) +#define PCPS_BUS_PCI_PEX8311 ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_PEX8311 ) +#define PCPS_BUS_PCI_MBGPEX ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_MBGPEX ) + + +// The flags below are or'ed to the PCPS_BUS_USB code +// in order to indicate which USB protocol version +// is supported by the device. If no additional flag is set +// then the device has a USB v1 interface. +#define PCPS_BUS_USB_FLAG_V2 0x8000 + +// The constant below combines the PCI bus flags: +#define PCPS_BUS_USB_V2 ( PCPS_BUS_USB | PCPS_BUS_USB_FLAG_V2 ) + + + +/** A list of known radio clocks. */ +enum PCPS_TYPES +{ + PCPS_TYPE_PC31, + PCPS_TYPE_PS31_OLD, + PCPS_TYPE_PS31, + PCPS_TYPE_PC32, + PCPS_TYPE_PCI32, + PCPS_TYPE_GPS167PC, + PCPS_TYPE_GPS167PCI, + PCPS_TYPE_PCI509, + PCPS_TYPE_GPS168PCI, + PCPS_TYPE_PCI510, + PCPS_TYPE_GPS169PCI, + PCPS_TYPE_TCR510PCI, + PCPS_TYPE_TCR167PCI, + PCPS_TYPE_GPS170PCI, + PCPS_TYPE_PCI511, + PCPS_TYPE_TCR511PCI, + PCPS_TYPE_PEX511, + PCPS_TYPE_TCR511PEX, + PCPS_TYPE_GPS170PEX, + PCPS_TYPE_USB5131, + PCPS_TYPE_TCR51USB, + PCPS_TYPE_MSF51USB, + PCPS_TYPE_PTP270PEX, + PCPS_TYPE_FRC511PEX, + PCPS_TYPE_TCR170PEX, + PCPS_TYPE_WWVB51USB, + PCPS_TYPE_GPS180PEX, + PCPS_TYPE_TCR180PEX, + PCPS_TYPE_DCF600USB, + PCPS_TYPE_PZF180PEX, + PCPS_TYPE_TCR600USB, + PCPS_TYPE_MSF600USB, + PCPS_TYPE_WVB600USB, + N_PCPS_DEV_TYPE +}; + + +#define PCPS_CLOCK_NAME_SZ 10 // including terminating 0 + +typedef uint16_t PCPS_DEV_ID; +typedef uint16_t PCPS_REF_TYPE; +typedef uint16_t PCPS_BUS_FLAGS; + +/** + The structure contains the characteristics of each + of the clocks listed above. These fields are always the + same for a single type of clock and do not change with + firmware version, port address, etc. + */ +typedef struct +{ + uint16_t num; + char name[PCPS_CLOCK_NAME_SZ]; + PCPS_DEV_ID dev_id; + PCPS_REF_TYPE ref_type; + PCPS_BUS_FLAGS bus_flags; +} PCPS_DEV_TYPE; + + + +#if !defined( MBG_TGT_UNIX ) || defined( MBG_ARCH_X86 ) + typedef uint16_t PCPS_PORT_ADDR; +#else + typedef uint64_t PCPS_PORT_ADDR; +#endif + + + +/** + The structure below describes an I/O port resource + used by a clock. +*/ +typedef struct +{ + PCPS_PORT_ADDR base; + uint16_t num; +} PCPS_PORT_RSRC; + +/** The max number of I/O port resources used by a clock. */ +#define N_PCPS_PORT_RSRC 2 + + + +typedef struct +{ + MBG_MEM_ADDR user_virtual_address; + #if defined( MBG_TGT_LINUX ) + uint64_t len; + uint64_t pfn_offset; + #else + ulong len; + #endif +} PCPS_MAPPED_MEM; + + + +typedef uint32_t PCPS_ERR_FLAGS; /**< see \ref group_err_flags "Error flags" */ +typedef uint32_t PCPS_FEATURES; /**< see \ref group_features "Features" */ +typedef uint16_t PCPS_BUS_NUM; +typedef uint16_t PCPS_SLOT_NUM; + +/** + The structure below contains data which depends + on a individual instance of the clock, e.g. + the firmware which is currently installed, the + port address which has been configured, etc. +*/ +typedef struct +{ + PCPS_ERR_FLAGS err_flags; /**< See \ref group_err_flags "Error flags" */ + PCPS_BUS_NUM bus_num; + PCPS_SLOT_NUM slot_num; + PCPS_PORT_RSRC port[N_PCPS_PORT_RSRC]; + uint16_t status_port; + int16_t irq_num; + uint32_t timeout_clk; + uint16_t fw_rev_num; + PCPS_FEATURES features; /**< See \ref group_features "Feature flags" */ + PCPS_ID_STR fw_id; + PCPS_SN_STR sernum; +} PCPS_DEV_CFG; + +/** @defgroup group_err_flags Error flags in PCPS_DEV_CFG + Flags used with PCPS_DEV_CFG::err_flags + @{ +*/ +#define PCPS_EF_TIMEOUT 0x00000001 /**< timeout occured */ +#define PCPS_EF_INV_EPROM_ID 0x00000002 /**< invalid EPROM ID */ +#define PCPS_EF_IO_INIT 0x00000004 /**< I/O intf not init'd */ +#define PCPS_EF_IO_CFG 0x00000008 /**< I/O intf not cfg'd */ +#define PCPS_EF_IO_ENB 0x00000010 /**< I/O intf not enabled */ +#define PCPS_EF_IO_RSRC 0x00000020 /**< I/O not registered w/ rsrcmgr */ +/** @} */ + +/** @defgroup group_features Feature flags used with PCPS_FEATURES + + Some features of the radio clocks have been introduced with + specific firmware versions, so depending on the firmware version + a clock may support a feature or not. The clock detection function + checks the clock model and firmware version and updates the field + PCPS_DEV_CFG::features accordingly. There are some macros which + can easily be used to query whether a clock device actually + supports a function, or not. The definitions define + the possible features. + @{ +*/ +enum +{ + PCPS_BIT_CAN_SET_TIME, + PCPS_BIT_HAS_SERIAL, + PCPS_BIT_HAS_SYNC_TIME, + PCPS_BIT_HAS_TZDL, + PCPS_BIT_HAS_IDENT, + PCPS_BIT_HAS_UTC_OFFS, + PCPS_BIT_HAS_HR_TIME, + PCPS_BIT_HAS_SERNUM, + + PCPS_BIT_HAS_TZCODE, + PCPS_BIT_HAS_CABLE_LEN, + PCPS_BIT_HAS_EVENT_TIME, // custom GPS firmware only + PCPS_BIT_HAS_RECEIVER_INFO, + PCPS_BIT_CAN_CLR_UCAP_BUFF, + PCPS_BIT_HAS_PCPS_TZDL, + PCPS_BIT_HAS_UCAP, + PCPS_BIT_HAS_IRIG_TX, + + PCPS_BIT_HAS_GPS_DATA_16, // use 16 bit size specifiers + PCPS_BIT_HAS_SYNTH, + PCPS_BIT_HAS_GENERIC_IO, + PCPS_BIT_HAS_TIME_SCALE, + PCPS_BIT_HAS_UTC_PARM, + PCPS_BIT_HAS_IRIG_CTRL_BITS, + PCPS_BIT_HAS_LAN_INTF, + PCPS_BIT_HAS_PTP, + + PCPS_BIT_HAS_IRIG_TIME, + PCPS_BIT_HAS_FAST_HR_TSTAMP, + PCPS_BIT_HAS_RAW_IRIG_DATA, + PCPS_BIT_HAS_PZF, // can also demodulate DCF77 PZF + PCPS_BIT_HAS_EVT_LOG, + + N_PCPS_FEATURE // must not exceed 32 !! +}; + + +#define PCPS_CAN_SET_TIME ( 1UL << PCPS_BIT_CAN_SET_TIME ) +#define PCPS_HAS_SERIAL ( 1UL << PCPS_BIT_HAS_SERIAL ) +#define PCPS_HAS_SYNC_TIME ( 1UL << PCPS_BIT_HAS_SYNC_TIME ) +#define PCPS_HAS_TZDL ( 1UL << PCPS_BIT_HAS_TZDL ) +#define PCPS_HAS_IDENT ( 1UL << PCPS_BIT_HAS_IDENT ) +#define PCPS_HAS_UTC_OFFS ( 1UL << PCPS_BIT_HAS_UTC_OFFS ) +#define PCPS_HAS_HR_TIME ( 1UL << PCPS_BIT_HAS_HR_TIME ) +#define PCPS_HAS_SERNUM ( 1UL << PCPS_BIT_HAS_SERNUM ) +#define PCPS_HAS_TZCODE ( 1UL << PCPS_BIT_HAS_TZCODE ) +#define PCPS_HAS_CABLE_LEN ( 1UL << PCPS_BIT_HAS_CABLE_LEN ) +#define PCPS_HAS_EVENT_TIME ( 1UL << PCPS_BIT_HAS_EVENT_TIME ) +#define PCPS_HAS_RECEIVER_INFO ( 1UL << PCPS_BIT_HAS_RECEIVER_INFO ) +#define PCPS_CAN_CLR_UCAP_BUFF ( 1UL << PCPS_BIT_CAN_CLR_UCAP_BUFF ) +#define PCPS_HAS_PCPS_TZDL ( 1UL << PCPS_BIT_HAS_PCPS_TZDL ) +#define PCPS_HAS_UCAP ( 1UL << PCPS_BIT_HAS_UCAP ) +#define PCPS_HAS_IRIG_TX ( 1UL << PCPS_BIT_HAS_IRIG_TX ) +#define PCPS_HAS_GPS_DATA_16 ( 1UL << PCPS_BIT_HAS_GPS_DATA_16 ) +#define PCPS_HAS_SYNTH ( 1UL << PCPS_BIT_HAS_SYNTH ) +#define PCPS_HAS_GENERIC_IO ( 1UL << PCPS_BIT_HAS_GENERIC_IO ) +#define PCPS_HAS_TIME_SCALE ( 1UL << PCPS_BIT_HAS_TIME_SCALE ) +#define PCPS_HAS_UTC_PARM ( 1UL << PCPS_BIT_HAS_UTC_PARM ) +#define PCPS_HAS_IRIG_CTRL_BITS ( 1UL << PCPS_BIT_HAS_IRIG_CTRL_BITS ) +#define PCPS_HAS_LAN_INTF ( 1UL << PCPS_BIT_HAS_LAN_INTF ) +#define PCPS_HAS_PTP ( 1UL << PCPS_BIT_HAS_PTP ) +#define PCPS_HAS_IRIG_TIME ( 1UL << PCPS_BIT_HAS_IRIG_TIME ) +#define PCPS_HAS_FAST_HR_TSTAMP ( 1UL << PCPS_BIT_HAS_FAST_HR_TSTAMP ) +#define PCPS_HAS_RAW_IRIG_DATA ( 1UL << PCPS_BIT_HAS_RAW_IRIG_DATA ) +#define PCPS_HAS_PZF ( 1UL << PCPS_BIT_HAS_PZF ) +#define PCPS_HAS_EVT_LOG ( 1UL << PCPS_BIT_HAS_EVT_LOG ) + + + +#define PCPS_FEATURE_NAMES \ +{ \ + "PCPS_CAN_SET_TIME", \ + "PCPS_HAS_SERIAL", \ + "PCPS_HAS_SYNC_TIME", \ + "PCPS_HAS_TZDL", \ + "PCPS_HAS_IDENT", \ + "PCPS_HAS_UTC_OFFS", \ + "PCPS_HAS_HR_TIME", \ + "PCPS_HAS_SERNUM", \ + "PCPS_HAS_TZCODE", \ + "PCPS_HAS_CABLE_LEN", \ + "PCPS_HAS_EVENT_TIME", \ + "PCPS_HAS_RECEIVER_INFO", \ + "PCPS_CAN_CLR_UCAP_BUFF", \ + "PCPS_HAS_PCPS_TZDL", \ + "PCPS_HAS_UCAP", \ + "PCPS_HAS_IRIG_TX", \ + "PCPS_HAS_GPS_DATA_16", \ + "PCPS_HAS_SYNTH", \ + "PCPS_HAS_GENERIC_IO", \ + "PCPS_HAS_TIME_SCALE", \ + "PCPS_HAS_UTC_PARM", \ + "PCPS_HAS_IRIG_CTRL_BITS", \ + "PCPS_HAS_LAN_INTF", \ + "PCPS_HAS_PTP", \ + "PCPS_HAS_IRIG_TIME", \ + "PCPS_HAS_FAST_HR_TSTAMP", \ + "PCPS_HAS_RAW_IRIG_DATA", \ + "PCPS_HAS_PZF", \ + "PCPS_HAS_EVT_LOG" \ +} + +/** @} */ + + + +// The constants below define those features which are available +// in ALL firmware versions which have been shipped with a +// specific clock. + +#define PCPS_FEAT_PC31PS31 0 + +// Some of the features are available in all newer clocks, +// so these have been put together in one definition: +#define PCPS_FEAT_LVL2 ( PCPS_CAN_SET_TIME \ + | PCPS_HAS_SERIAL \ + | PCPS_HAS_SYNC_TIME \ + | PCPS_HAS_UTC_OFFS ) + +#define PCPS_FEAT_PC32 ( PCPS_FEAT_LVL2 ) + +#define PCPS_FEAT_PCI32 ( PCPS_FEAT_LVL2 ) + +#define PCPS_FEAT_PCI509 ( PCPS_FEAT_LVL2 \ + | PCPS_HAS_SERNUM \ + | PCPS_HAS_TZCODE ) + +#define PCPS_FEAT_PCI510 ( PCPS_FEAT_PCI509 ) + +#define PCPS_FEAT_PCI511 ( PCPS_FEAT_PCI510 ) + +#define PCPS_FEAT_GPS167PC ( PCPS_FEAT_LVL2 \ + | PCPS_HAS_TZDL \ + | PCPS_HAS_IDENT ) + +#define PCPS_FEAT_GPS167PCI ( PCPS_FEAT_LVL2 \ + | PCPS_HAS_TZDL \ + | PCPS_HAS_IDENT \ + | PCPS_HAS_HR_TIME ) + +#define PCPS_FEAT_GPS168PCI ( PCPS_FEAT_LVL2 \ + | PCPS_HAS_TZDL \ + | PCPS_HAS_IDENT \ + | PCPS_HAS_HR_TIME \ + | PCPS_HAS_CABLE_LEN \ + | PCPS_HAS_RECEIVER_INFO ) + +#define PCPS_FEAT_GPS169PCI ( PCPS_FEAT_GPS168PCI \ + | PCPS_CAN_CLR_UCAP_BUFF \ + | PCPS_HAS_UCAP ) + +#define PCPS_FEAT_GPS170PCI ( PCPS_FEAT_GPS169PCI \ + | PCPS_HAS_IRIG_TX \ + | PCPS_HAS_GPS_DATA_16 \ + | PCPS_HAS_GENERIC_IO ) + +#define PCPS_FEAT_TCR510PCI ( PCPS_FEAT_LVL2 \ + | PCPS_HAS_SERNUM ) + +#define PCPS_FEAT_TCR167PCI ( PCPS_FEAT_LVL2 \ + | PCPS_HAS_SERNUM \ + | PCPS_HAS_TZDL \ + | PCPS_HAS_HR_TIME \ + | PCPS_HAS_RECEIVER_INFO \ + | PCPS_CAN_CLR_UCAP_BUFF \ + | PCPS_HAS_UCAP \ + | PCPS_HAS_IRIG_TX \ + | PCPS_HAS_GPS_DATA_16 \ + | PCPS_HAS_GENERIC_IO ) + +#define PCPS_FEAT_TCR511PCI ( PCPS_FEAT_TCR510PCI \ + | PCPS_HAS_HR_TIME ) + +#define PCPS_FEAT_PEX511 ( PCPS_FEAT_PCI511 ) + +#define PCPS_FEAT_TCR511PEX ( PCPS_FEAT_TCR511PCI ) + +#define PCPS_FEAT_GPS170PEX ( PCPS_FEAT_GPS170PCI ) + +#define PCPS_FEAT_USB5131 ( PCPS_HAS_UTC_OFFS \ + | PCPS_HAS_SERNUM \ + | PCPS_HAS_SYNC_TIME \ + | PCPS_HAS_HR_TIME \ + | PCPS_CAN_SET_TIME \ + | PCPS_HAS_TZCODE ) + +#define PCPS_FEAT_TCR51USB ( PCPS_HAS_UTC_OFFS \ + | PCPS_HAS_SERNUM \ + | PCPS_HAS_SYNC_TIME \ + | PCPS_HAS_HR_TIME \ + | PCPS_CAN_SET_TIME ) + +#define PCPS_FEAT_MSF51USB ( PCPS_HAS_UTC_OFFS \ + | PCPS_HAS_SERNUM \ + | PCPS_HAS_SYNC_TIME \ + | PCPS_HAS_HR_TIME \ + | PCPS_CAN_SET_TIME ) + +#define PCPS_FEAT_PTP270PEX ( PCPS_HAS_SERNUM \ + | PCPS_HAS_SYNC_TIME \ + | PCPS_HAS_HR_TIME \ + | PCPS_HAS_RECEIVER_INFO \ + | PCPS_CAN_SET_TIME \ + | PCPS_CAN_CLR_UCAP_BUFF \ + | PCPS_HAS_UCAP \ + | PCPS_HAS_GPS_DATA_16 ) + +#define PCPS_FEAT_FRC511PEX ( PCPS_HAS_SERNUM \ + | PCPS_HAS_HR_TIME \ + | PCPS_HAS_RECEIVER_INFO \ + | PCPS_CAN_SET_TIME \ + | PCPS_CAN_CLR_UCAP_BUFF \ + | PCPS_HAS_UCAP \ + | PCPS_HAS_GPS_DATA_16 ) + +#define PCPS_FEAT_TCR170PEX ( PCPS_FEAT_TCR167PCI ) + +#define PCPS_FEAT_WWVB51USB ( PCPS_FEAT_MSF51USB ) + +#define PCPS_FEAT_GPS180PEX ( PCPS_FEAT_GPS170PEX | PCPS_HAS_FAST_HR_TSTAMP ) + +#define PCPS_FEAT_TCR180PEX ( PCPS_FEAT_TCR170PEX | PCPS_HAS_FAST_HR_TSTAMP ) + +#define PCPS_FEAT_DCF600USB ( PCPS_FEAT_USB5131 ) + +#define PCPS_FEAT_PZF180PEX ( PCPS_FEAT_LVL2 \ + | PCPS_HAS_TZDL \ + | PCPS_HAS_HR_TIME \ + | PCPS_HAS_SERNUM \ + | PCPS_HAS_RECEIVER_INFO \ + | PCPS_CAN_CLR_UCAP_BUFF \ + | PCPS_HAS_UCAP \ + | PCPS_HAS_GPS_DATA_16 \ + | PCPS_HAS_GENERIC_IO \ + | PCPS_HAS_UTC_PARM \ + | PCPS_HAS_PZF ) + +#define PCPS_FEAT_TCR600USB ( PCPS_FEAT_TCR51USB \ + | PCPS_HAS_IRIG_CTRL_BITS \ + | PCPS_HAS_IRIG_TIME \ + | PCPS_HAS_RAW_IRIG_DATA ) + +#define PCPS_FEAT_MSF600USB ( PCPS_FEAT_MSF51USB ) + +#define PCPS_FEAT_WVB600USB ( PCPS_FEAT_WWVB51USB ) + +// Some features of the API used to access Meinberg plug-in devices +// have been implemented starting with the special firmware revision +// numbers defined below. +// +// If no number is specified for a feature/clock model then the feature +// is either always supported by that clock model, or not at all. + + +// There are some versions of PCI Express cards out there which do not +// safely support hardware IRQs. The following firmware versions are required +// for safe IRQ operation: +#define REV_HAS_IRQ_FIX_MINOR_PEX511 0x0106 +#define REV_HAS_IRQ_FIX_MINOR_TCR511PEX 0x0105 +#define REV_HAS_IRQ_FIX_MINOR_GPS170PEX 0x0104 +// Additionally there are certain revisions of the bus interface logic +// required. The associated version codes are defined in pci_asic.h. + +// The macro below can be used to check whether the required versions are there: +#define _pcps_pex_irq_is_safe( _curr_fw_ver, _req_fw_ver, _curr_asic_ver, \ + _req_asic_ver_major, _req_asic_ver_minor ) \ + ( ( (_curr_fw_ver) >= (_req_fw_ver) ) && _pcps_asic_version_greater_equal( \ + (_curr_asic_ver), (_req_asic_ver_major), (_req_asic_ver_minor ) ) \ + ) + +/* command PCPS_GIVE_RAW_IRIG_DATA: */ +#define REV_HAS_RAW_IRIG_DATA_TCR511PEX 0x0111 +#define REV_HAS_RAW_IRIG_DATA_TCR511PCI 0x0111 +#define REV_HAS_RAW_IRIG_DATA_TCR51USB 0x0106 + +/* command PCPS_GIVE_IRIG_TIME: */ +#define REV_HAS_IRIG_TIME_TCR511PEX 0x0109 +#define REV_HAS_IRIG_TIME_TCR511PCI 0x0109 +#define REV_HAS_IRIG_TIME_TCR51USB 0x0106 + +/* command PCPS_GET_IRIG_CTRL_BITS: */ +#define REV_HAS_IRIG_CTRL_BITS_TCR511PEX 0x0107 +#define REV_HAS_IRIG_CTRL_BITS_TCR511PCI 0x0107 +#define REV_HAS_IRIG_CTRL_BITS_TCR51USB 0x0106 + +/* This board uses the GPS_DATA interface with 16 bit buffer sizes + instead of the original 8 bit sizes, thus allowing to transfer + data blocks which exceed 255 bytes (PCPS_HAS_GPS_DATA_16) */ +#define REV_HAS_GPS_DATA_16_GPS169PCI 0x0202 + +/* the clock supports a higher baud rate than N_PCPS_BD_DCF */ +#define REV_HAS_SERIAL_HS_PCI509 0x0104 + +/* commands PCPS_GIVE_UCAP_ENTRIES, PCPS_GIVE_UCAP_EVENT */ +#define REV_HAS_UCAP_GPS167PCI 0x0421 +#define REV_HAS_UCAP_GPS168PCI 0x0104 + +/* command PCPS_CLR_UCAP_BUFF */ +#define REV_CAN_CLR_UCAP_BUFF_GPS167PCI 0x0419 +#define REV_CAN_CLR_UCAP_BUFF_GPS168PCI 0x0101 + +/* commands PCPS_READ_GPS_DATA and PCPS_WRITE_GPS_DATA with */ +/* code PC_GPS_ANT_CABLE_LEN */ +#define REV_HAS_CABLE_LEN_GPS167PCI 0x0411 +#define REV_HAS_CABLE_LEN_GPS167PC 0x0411 + +/* command PCPS_GIVE_HR_TIME, structure PCPS_HR_TIME: */ +#define REV_HAS_HR_TIME_GPS167PC 0x0305 +#define REV_HAS_HR_TIME_TCR510PCI 0x0200 +#define REV_HAS_HR_TIME_PEX511 0x0105 // This also requires a certain ASIC version. +#define REV_HAS_HR_TIME_PCI511 0x0103 + +/* field offs_utc in structure PCPS_TIME: */ +#define REV_HAS_UTC_OFFS_PC31PS31 0x0300 + +/* command PCPS_GIVE_SYNC_TIME: */ +#define REV_HAS_SYNC_TIME_PC31PS31 0x0300 + +/* command PCPS_GET_SERIAL, PCPS_SET_SERIAL: */ +#define REV_HAS_SERIAL_PC31PS31 0x0300 + +/* command PCPS_GIVE_TIME_NOCLEAR: */ +#define REV_GIVE_TIME_NOCLEAR_PC31PS31 0x0300 + +/* status bit PCPS_LS_ANN: */ +#define REV_PCPS_LS_ANN_PC31PS31 0x0300 + +/* status bit PCPS_IFTM: */ +#define REV_PCPS_IFTM_PC31PS31 0x0300 + +/* command PCPS_SET_TIME: */ +#define REV_CAN_SET_TIME_PC31PS31 0x0240 + +/* command PCPS_GIVE_TIME_NOCLEAR: */ +// This is supported by all clocks but PC31/PS31 with +// firmware versions before v3.0. If such a card shall +// be used then the firmware should be updated to the +// last recent version. + + +/** + The structure has been defined to pass all + information on a clock device from a device driver + to a user program. */ +typedef struct +{ + PCPS_DEV_TYPE type; + PCPS_DEV_CFG cfg; +} PCPS_DEV; + + +// The macros below simplify access to the data +// stored in PCPS_DEV structure and should be used +// to extract the desired information. +// If the formal parameter is called _d then a pointer +// to device structure PCPS_DEV is expected. +// If the formal parameter is called _c then a pointer +// to configuration structure PCPS_DEV_CFG is expected. + +// Access device type information: +#define _pcps_type_num( _d ) ( (_d)->type.num ) +#define _pcps_type_name( _d ) ( (_d)->type.name ) +#define _pcps_dev_id( _d ) ( (_d)->type.dev_id ) +#define _pcps_ref_type( _d ) ( (_d)->type.ref_type ) +#define _pcps_bus_flags( _d ) ( (_d)->type.bus_flags ) + +// Query device type features: +#define _pcps_is_gps( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_GPS ) +#define _pcps_is_dcf( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_DCF ) +#define _pcps_is_msf( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_MSF ) +#define _pcps_is_wwvb( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_WWVB ) +#define _pcps_is_irig_rx( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_IRIG ) +#define _pcps_is_ptp( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_PTP ) +#define _pcps_is_frc( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_FRC ) + +#define _pcps_is_lwr( _d ) ( _pcps_is_dcf( _d ) || _pcps_is_msf( _d ) || _pcps_is_wwvb( _d ) ) + +// Generic bus types: +#define _pcps_is_isa( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_ISA ) +#define _pcps_is_mca( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_MCA ) +#define _pcps_is_pci( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_PCI ) +#define _pcps_is_usb( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_USB ) + +// Special bus types: +#define _pcps_is_usb_v2( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_USB_V2 ) +#define _pcps_is_pci_s5933( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_S5933 ) +#define _pcps_is_pci_s5920( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_S5920 ) +#define _pcps_is_pci_amcc( _d ) ( _pcps_is_pci_s5920( _d ) || _pcps_is_pci_s5933( _d ) ) +#define _pcps_is_pci_asic( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_ASIC ) +#define _pcps_is_pci_pex8311( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_PEX8311 ) +#define _pcps_is_pci_mbgpex( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_MBGPEX ) + + +// Access device configuration information: +#define _pcps_bus_num( _d ) ( (_d)->cfg.bus_num ) +#define _pcps_slot_num( _d ) ( (_d)->cfg.slot_num ) + +#define _pcps_cfg_port_rsrc( _c, _n ) ( (_c)->port[_n] ) +#define _pcps_port_rsrc( _d, _n ) _pcps_cfg_port_rsrc( &(_d)->cfg, (_n) ) +#define _pcps_port_rsrc_unused( _d ) ( (_d)->base == 0 || (_d)->num == 0 ) + +#define _pcps_cfg_port_base( _c, _n ) ( _pcps_cfg_port_rsrc( (_c), (_n) ).base ) +#define _pcps_port_base( _d, _n ) ( _pcps_port_rsrc( (_d), (_n) ).base ) + +#define _pcps_cfg_irq_num( _c ) ( (_c)->irq_num ) +#define _pcps_irq_num( _d ) _pcps_cfg_irq_num( &(_d)->cfg ) + +#define _pcps_cfg_timeout_clk( _c ) ( (_c)->timeout_clk ) +#define _pcps_timeout_clk( _d ) _pcps_cfg_timeout_clk( &(_d)->cfg ) + +#define _pcps_fw_rev_num( _d ) ( (_d)->cfg.fw_rev_num ) +#define _pcps_features( _d ) ( (_d)->cfg.features ) +#define _pcps_fw_id( _d ) ( (_d)->cfg.fw_id ) +#define _pcps_sernum( _d ) ( (_d)->cfg.sernum ) + + +// The macros below handle the device's err_flags. +#define _pcps_err_flags( _d ) ( (_d)->cfg.err_flags ) +#define _pcps_chk_err_flags( _d, _msk ) ( _pcps_err_flags( _d ) & (_msk) ) +#define _pcps_set_err_flags( _d, _msk ) ( _pcps_err_flags( _d ) |= (_msk) ) +#define _pcps_clr_err_flags( _d, _msk ) ( _pcps_err_flags( _d ) &= ~(_msk) ) + + +// Query whether a special feature is supported: +#define _pcps_has_feature( _d, _f ) ( ( (_d)->cfg.features & (_f) ) != 0 ) + +// Query whether a special feature is supported according to RECEIVER_INFO: +#define _pcps_has_ri_feature( _p_ri, _f ) ( ( (_p_ri)->features & (_f) ) != 0 ) + + +#define _pcps_can_set_time( _d ) _pcps_has_feature( (_d), PCPS_CAN_SET_TIME ) +#define _pcps_has_serial( _d ) _pcps_has_feature( (_d), PCPS_HAS_SERIAL ) +#define _pcps_has_sync_time( _d ) _pcps_has_feature( (_d), PCPS_HAS_SYNC_TIME ) +#define _pcps_has_ident( _d ) _pcps_has_feature( (_d), PCPS_HAS_IDENT ) +#define _pcps_has_utc_offs( _d ) _pcps_has_feature( (_d), PCPS_HAS_UTC_OFFS ) +#define _pcps_has_hr_time( _d ) _pcps_has_feature( (_d), PCPS_HAS_HR_TIME ) +#define _pcps_has_sernum( _d ) _pcps_has_feature( (_d), PCPS_HAS_SERNUM ) +#define _pcps_has_cab_len( _d ) _pcps_has_feature( (_d), PCPS_HAS_CABLE_LEN ) +#define _pcps_has_tzdl( _d ) _pcps_has_feature( (_d), PCPS_HAS_TZDL ) +#define _pcps_has_pcps_tzdl( _d ) _pcps_has_feature( (_d), PCPS_HAS_PCPS_TZDL ) +#define _pcps_has_tzcode( _d ) _pcps_has_feature( (_d), PCPS_HAS_TZCODE ) +#define _pcps_has_tz( _d ) _pcps_has_feature( (_d), PCPS_HAS_TZDL \ + | PCPS_HAS_PCPS_TZDL \ + | PCPS_HAS_TZCODE ) +// The next one is supported only with a certain GPS firmware version: +#define _pcps_has_event_time( _d ) _pcps_has_feature( (_d), PCPS_HAS_EVENT_TIME ) +#define _pcps_has_receiver_info( _d ) _pcps_has_feature( (_d), PCPS_HAS_RECEIVER_INFO ) +#define _pcps_can_clr_ucap_buff( _d ) _pcps_has_feature( (_d), PCPS_CAN_CLR_UCAP_BUFF ) +#define _pcps_has_ucap( _d ) _pcps_has_feature( (_d), PCPS_HAS_UCAP ) +#define _pcps_has_irig_tx( _d ) _pcps_has_feature( (_d), PCPS_HAS_IRIG_TX ) + +// The macro below determines whether a DCF77 clock +// supports a higher baud rate than standard +#define _pcps_has_serial_hs( _d ) \ + ( ( _pcps_type_num( _d ) == PCPS_TYPE_TCR511PEX ) || \ + ( _pcps_type_num( _d ) == PCPS_TYPE_PEX511 ) || \ + ( _pcps_type_num( _d ) == PCPS_TYPE_TCR511PCI ) || \ + ( _pcps_type_num( _d ) == PCPS_TYPE_TCR510PCI ) || \ + ( _pcps_type_num( _d ) == PCPS_TYPE_PCI511 ) || \ + ( _pcps_type_num( _d ) == PCPS_TYPE_PCI510 ) || \ + ( _pcps_type_num( _d ) == PCPS_TYPE_PCI509 && \ + _pcps_fw_rev_num( _d ) >= REV_HAS_SERIAL_HS_PCI509 ) ) + + +#define _pcps_has_signal( _d ) \ + ( _pcps_is_dcf( _d ) || _pcps_is_msf( _d ) || _pcps_is_wwvb( _d ) || _pcps_is_irig_rx( _d ) ) + +#define _pcps_has_mod( _d ) \ + ( _pcps_is_dcf( _d ) || _pcps_is_msf( _d ) || _pcps_is_wwvb( _d ) ) + +#define _pcps_has_irig( _d ) \ + ( _pcps_is_irig_rx( _d ) || _pcps_has_irig_tx( _d ) ) + +#define _pcps_has_irig_ctrl_bits( _d ) \ + _pcps_has_feature( (_d), PCPS_HAS_IRIG_CTRL_BITS ) + +#define _pcps_has_irig_time( _d ) \ + _pcps_has_feature( (_d), PCPS_HAS_IRIG_TIME ) + +#define _pcps_has_raw_irig_data( _d ) \ + _pcps_has_feature( (_d), PCPS_HAS_RAW_IRIG_DATA ) + +#define _pcps_has_ref_offs( _d ) \ + _pcps_is_irig_rx( _d ) + +#define _pcps_ref_offs_out_of_range( _n ) \ + ( ( (_n) > MBG_REF_OFFS_MAX ) || ( (_n) < -MBG_REF_OFFS_MAX ) ) + +#define _pcps_has_opt_flags( _d ) \ + _pcps_is_irig_rx( _d ) + +#define _pcps_has_gps_data_16( _d ) _pcps_has_feature( (_d), PCPS_HAS_GPS_DATA_16 ) + +#define _pcps_has_gps_data( _d ) \ + ( _pcps_is_gps( _d ) || _pcps_has_gps_data_16( _d ) ) + +#define _pcps_has_synth( _d ) _pcps_has_feature( (_d), PCPS_HAS_SYNTH ) + +#define _pcps_has_generic_io( _d ) _pcps_has_feature( (_d), PCPS_HAS_GENERIC_IO ) + +#define _pcps_has_time_scale( _d ) _pcps_has_feature( (_d), PCPS_HAS_TIME_SCALE ) + +#define _pcps_has_utc_parm( _d ) _pcps_has_feature( (_d), PCPS_HAS_UTC_PARM ) + +#define _pcps_has_asic_version( _d ) ( _pcps_is_pci_asic( _d ) \ + || _pcps_is_pci_pex8311( _d ) \ + || _pcps_is_pci_mbgpex( _d ) ) + +#define _pcps_has_asic_features( _d ) _pcps_has_asic_version( _d ) + +#define _pcps_has_fast_hr_timestamp( _d ) _pcps_has_feature( (_d), PCPS_HAS_FAST_HR_TSTAMP ) + +#define _pcps_has_lan_intf( _d ) _pcps_has_feature( (_d), PCPS_HAS_LAN_INTF ) + +#define _pcps_has_ptp( _d ) _pcps_has_feature( (_d), PCPS_HAS_PTP ) + +#define _pcps_has_ri_ptp_unicast( _p_ri ) _pcps_has_ri_feature( (_p_ri), GPS_HAS_PTP_UNICAST ) + +#define _pcps_has_pzf( _d ) _pcps_has_feature( (_d), PCPS_HAS_PZF ) + +#define _pcps_has_corr_info( _d ) _pcps_has_pzf( _d ) + +#define _pcps_has_tr_distance( _d ) _pcps_has_pzf( _d ) + +#define _pcps_has_evt_log( _d ) _pcps_has_feature( (_d), PCPS_HAS_EVT_LOG ) + +#define _pcps_has_debug_status( _d ) _pcps_is_irig_rx( _d ) + +#define _pcps_has_stat_info( _d ) ( _pcps_is_gps( _d ) || _pcps_has_pzf( _d ) ) + +#define _pcps_has_stat_info_mode( _d ) _pcps_is_gps( _d ) + +#define _pcps_has_stat_info_svs( _d ) _pcps_is_gps( _d ) + + + +// There are some versions of IRIG receiver cards which ignore the TFOM code +// of an incoming IRIG signal even if an IRIG code has been configured which +// supports this. In this case these cards synchronize to the incoming IRIG +// signal even if the TFOM code reports the IRIG generator is not synchronized. +// The intended behaviour is that the IRIG receiver card changes its status +// to "freewheeling" in this case, unless it has been configured to ignore +// the TFOM code of the incoming IRIG signal (see the IFLAGS_DISABLE_TFOM flag +// defined in gpsdefs.h). + +// The macro below can be used to check based on the device info if a specific +// card with a specific firmware always ignores the TFOM code: +#define _pcps_incoming_tfom_ignored( _d ) \ + ( ( ( _pcps_type_num( _d ) == PCPS_TYPE_TCR167PCI ) && ( _pcps_fw_rev_num( _d ) <= 0x121 ) ) \ + || ( ( _pcps_type_num( _d ) == PCPS_TYPE_TCR170PEX ) && ( _pcps_fw_rev_num( _d ) <= 0x103 ) ) ) + + +// Some Meinberg PCI Express cards have a PCIe interface chip with an extra +// PCI bridge built into the chip. Unfortunately there are some mainboards out there +// which do not handle PCI resources behind this PCI bridge correctly. The symptom is +// usually that both I/O address ranges of these cards get the same base address +// assigned by the BIOS, and the efeect is that in this case a card is not accessible +// properly, since both I/O ranges try to respond to the same I/O addresses. +// As a consequence data read from the card is usually garbage. +// The only known fix for this is a BIOS update for the mainboard which makes the +// BIOS handle the card's resources properly. + +// The macro below can be used to test if both port base addresses assigned to a card +// are identical, and thus the BIOS is probably faulty:: +#define _pcps_pci_cfg_err( _d ) \ + ( _pcps_is_pci( _d ) && ( _pcps_port_base( _d, 1 ) == _pcps_port_base( _d, 0 ) ) ) + + + +// There are some versions of GPS PCI firmware which may occasionally return +// a HR time stamp which is wrong by 20 milliseconds, if the HR time is read +// right after some GPS data. As a workaround for that bug an application +// must wait at least 1.5 ms and then just read the PCPS_TIME structure +// in order to re-initialize the software interface state. +// This has been fixed in more recent versions of the affected firmware, +// but this macro can be used to let an application determine whether it +// must account for this bug with a given card and firmware version. +#define _must_do_fw_workaround_20ms( _d ) \ +( \ + ( _pcps_type_num( _d ) == PCPS_TYPE_GPS168PCI && _pcps_fw_rev_num( _d ) < 0x0102 ) || \ + ( _pcps_type_num( _d ) == PCPS_TYPE_GPS167PCI && _pcps_fw_rev_num( _d ) < 0x0420 ) \ +) + + + +/** + The structure is used to return info + on the device driver.*/ +typedef struct +{ + uint16_t ver_num; /**< the device driver's version number */ + uint16_t n_devs; /**< the number of radio clocks handled by the driver */ + PCPS_ID_STR id_str; /**< the device driver's ID string */ +} PCPS_DRVR_INFO; + + + +// The macros below can be used to mark a PCPS_TIME variable +// as unread, i.e. its contents have not been read from the clock, +// and to check if such a variable is marked as unread. +#define _pcps_time_set_unread( _t ) do { (_t)->sec = 0xFF; } while ( 0 ) +#define _pcps_time_is_read( _t ) ( (uchar) (_t)->sec != 0xFF ) + + + +/** + The structure is used to read the current time from + a device, combined with an associated PC cycle counter value + to compensate program execution time. + */ +typedef struct +{ + MBG_PC_CYCLES cycles; + PCPS_TIME t; +} PCPS_TIME_CYCLES; + + + +/** + The structure is used to read a high resolution UTC time stamp + plus associated PC cycles counter value to compensate the latency. + */ +typedef struct +{ + MBG_PC_CYCLES cycles; + PCPS_TIME_STAMP tstamp; /**< High resolution time stamp (UTC) */ +} PCPS_TIME_STAMP_CYCLES; + +#define _mbg_swab_pcps_time_stamp_cycles( _p ) \ +{ \ + _mbg_swab_mbg_pc_cycles( &(_p)->cycles ); \ + _mbg_swab_pcps_time_stamp( &(_p)->tstamp ); \ +} + + + +/** + The structure is used to read the current high resolution time + from a device, combined with an associated PC cycle counter value + to compensate program execution time. + */ +typedef struct +{ + MBG_PC_CYCLES cycles; + PCPS_HR_TIME t; +} PCPS_HR_TIME_CYCLES; + +#define _mbg_swab_pcps_hr_time_cycles( _p ) \ +{ \ + _mbg_swab_mbg_pc_cycles( &(_p)->cycles ); \ + _mbg_swab_pcps_hr_time( &(_p)->t ); \ +} + + + +/** + The structure below can be used to let the kernel driver read + the current system time plus the associated HR time from a plugin card + as close as possibly, and return the results to a user space application + which can then compute the time difference and latencies. + This structure also contains the card's status information (e.g. sync status). + */ +typedef struct +{ + PCPS_HR_TIME_CYCLES ref_hr_time_cycles; /**< HR time read from the card, plus cycles */ + MBG_SYS_TIME_CYCLES sys_time_cycles; /**< system timestamp plus associated cycles */ +} MBG_TIME_INFO_HRT; + +#define _mbg_swab_mbg_time_info_hrt( _p ) \ +{ \ + _mbg_swab_pcps_hr_time_cycles( &(_p)->ref_hr_time_cycles ); \ + _mbg_swab_mbg_sys_time_cycles( &(_p)->sys_time_cycles ); \ +} + + + +/** + The structure below can be used to let the kernel driver read + the current system time plus an associated HR timestamp from a plugin card + as close as possibly, and return the results to a user space application + which can then compute the time difference and latencies. + Since the card's time stamp is usually taken using the fast memory mapped + access this structure does *not* contain the card's status information + (e.g. sync status). + */ +typedef struct +{ + PCPS_TIME_STAMP_CYCLES ref_tstamp_cycles; /**< HR timestamp from the card, plus cycles */ + MBG_SYS_TIME_CYCLES sys_time_cycles; /**< system timestamp plus associated cycles */ +} MBG_TIME_INFO_TSTAMP; + +#define _mbg_swab_mbg_time_info_tstamp( _p ) \ +{ \ + _mbg_swab_pcps_time_stamp_cycles( &(_p)->ref_tstamp_cycles ); \ + _mbg_swab_mbg_sys_time_cycles( &(_p)->sys_time_cycles ); \ +} + + + +typedef uint32_t PCPS_IRQ_STAT_INFO; + +// Flags used with PCPS_IRQ_STAT_INFO: +#define PCPS_IRQ_STAT_ENABLE_CALLED 0x01 +#define PCPS_IRQ_STAT_ENABLED 0x02 +#define PCPS_IRQ_STAT_UNSAFE 0x04 // IRQs unsafe with this firmeware version / ASIC + +#define PCPS_IRQ_STATE_DANGER ( PCPS_IRQ_STAT_ENABLED | PCPS_IRQ_STAT_UNSAFE ) + +#define _pcps_fw_rev_num_major( _v ) \ + ( ( (_v) >> 8 ) & 0xFF ) + +#define _pcps_fw_rev_num_minor( _v ) \ + ( (_v) & 0xFF ) + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + + +// We must use native alignment here! + +// The structure below is used by the IOCTL_PCPS_GENERIC_... calls. + +#if defined( MBG_TGT_LINUX ) + #if defined( MBG_ARCH_ARM ) || defined( MBG_ARCH_SPARC ) + #define USE_IOCTL_GENERIC_REQ 0 + #endif +#endif + +#if defined( MBG_TGT_WIN32 ) + // required for 32bit/64 bit compatibility + #define USE_IOCTL_GENERIC_REQ 0 +#endif + +#if !defined( USE_IOCTL_GENERIC_REQ ) + #define USE_IOCTL_GENERIC_REQ 1 +#endif + + +#if USE_IOCTL_GENERIC_REQ + +// This does not yet work properly under Linux/Sparc where the kernel may be 64 bit +// while user space is 32 bit, which leads to different sizes for pointers and size_t. + +typedef struct +{ + ulong info; + const void *in_p; + size_t in_sz; + void *out_p; + size_t out_sz; + +} IOCTL_GENERIC_REQ; + +#define _MBG_IOG( _t, _n, _s ) _MBG_IOW( _t, _n, _s ) + +#else + +// The structure below is used by the IOCTL_PCPS_GENERIC_... calls. +typedef struct +{ + uint32_t info; + uint32_t data_size_in; + uint32_t data_size_out; +} IOCTL_GENERIC_CTL; + +typedef struct +{ + IOCTL_GENERIC_CTL ctl; + uint8_t data[1]; +} IOCTL_GENERIC_BUFFER; + +#define _MBG_IOG( _t, _n, _s ) _MBG_IO( _t, _n ) + +#endif + + + +#if !defined( MBG_TGT_KERNEL ) + +static __mbg_inline +void setup_hr_time_cycles_from_timestamp_cycles( PCPS_HR_TIME_CYCLES *p_ht_c, + const PCPS_TIME_STAMP_CYCLES *p_ts_c ) +{ + memset( p_ht_c, 0, sizeof( *p_ht_c ) ); + + p_ht_c->t.tstamp = p_ts_c->tstamp; + p_ht_c->cycles = p_ts_c->cycles; + +} // setup_hr_time_cycles_from_timestamp_cycles + +#endif + + +/* End of header body */ + +#undef _ext + +#endif /* _PCPSDEV_H */ + diff --git a/mbglib/common/pcpslstr.c b/mbglib/common/pcpslstr.c new file mode 100644 index 0000000..615b716 --- /dev/null +++ b/mbglib/common/pcpslstr.c @@ -0,0 +1,500 @@ + +/************************************************************************** + * + * $Id: pcpslstr.c 1.23 2012/10/15 13:09:35Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Functions generating commonly used multi-language strings used + * with programs for Meinberg radio clocks. + * + * ----------------------------------------------------------------------- + * $Log: pcpslstr.c $ + * Revision 1.23 2012/10/15 13:09:35Z martin + * Added function sprint_utc_offs(). + * Cleaned up get_tz_name(). + * Fixed potential compiler warning for sprintf(). + * Fixed build under FreeBSD. + * Revision 1.22 2010/06/25 13:57:57Z daniel + * Account for time zone offsets with minutes other than 0. + * Revision 1.21 2009/03/19 08:06:58Z daniel + * Added function pcps_tz_name_hr_status() to + * handle different time scales. + * Revision 1.20 2008/11/14 12:12:26Z martin + * Made some parameters for some functions const. + * Revision 1.19 2008/07/18 10:50:46Z martin + * Use _snwprintf with underscore for MS compilers. + * Revision 1.18 2008/01/30 14:51:12Z martin + * Fixed gcc compiler warnings. + * Revision 1.17 2008/01/17 09:08:12 daniel + * Added function pcps_date_time_wstr(). + * Changed function pcps_tz_name() to support MSF related time zones. + * Exclude functions using wchar_t from build if wide chars are + * not supported by the target environment. + * Revision 1.16 2007/08/14 09:08:25Z martin + * Addad a workaround for older Borland compilers which don't + * like "const" inside structures. + * Revision 1.15 2007/07/20 10:55:27Z martin + * Some modifications to avoid compiler warnings. + * Revision 1.14 2007/03/30 13:23:42 martin + * In pcps_status_strs() handle case where time has been + * set manually. + * Revision 1.13 2007/03/29 12:58:18Z martin + * Moved some definitions to the header file to make them public. + * Revision 1.12 2006/05/04 14:56:03Z martin + * Strings returned by inv_str() ar surrounded by "**"s. + * Revision 1.11 2004/11/09 15:06:44Z martin + * Type cast to avoid warning with format string. + * Revision 1.10 2004/08/18 14:58:02 martin + * pcps_tz_name() now expects a flags parameter which controls + * the format of the output string. + * Revision 1.9 2004/04/28 08:06:12Z martin + * Append DST status to TZ names labeled "UTC+xh" + * in pcps_tz_name(). + * Revision 1.8 2003/04/15 10:46:31Z martin + * Pass RECEIVER_INFO to pcps_serial_str(). + * Revision 1.7 2002/12/18 09:57:03Z martin + * Made some vaiables and definitions global. + * Revision 1.6 2002/02/19 10:03:16Z MARTIN + * New function pcps_serial_str(). + * Revision 1.5 2001/09/17 13:17:40 MARTIN + * New function pcps_tz_name_from_status() which should be used + * instead of pcps_tz_name() if offset from UTC is not known. + * New function pcps_status_strs(). + * Enhanced language support. + * Don't require myutil.h anymore. + * Added some comments. + * Source code cleanup. + * Revision 1.4 2001/08/14 11:32:24 MARTIN + * Modified pcps_date_time_str() to allow for variable + * spacing between date, time, and time zone.. + * Revision 1.3 2001/02/28 15:47:29 MARTIN + * Replaced access to some structure elements by new macro calls. + * Revision 1.2 2000/08/31 14:03:46 MARTIN + * Modified initializers for tzcode_name for non CPP-compilers. + * Revision 1.1 2000/07/21 12:14:01 MARTIN + * Initial revision + * + **************************************************************************/ + +#define _PCPSLSTR + #include <pcpslstr.h> +#undef _PCPSLSTR + +#include <pcpsutil.h> +#include <mbgtime.h> +#include <ctry.h> + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +#define _eos( _s ) ( &(_s)[strlen( _s )] ) + +typedef struct +{ + #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0500 ) + // old BCs don't like "const" inside the structure + LSTR ok; + LSTR err; + #else + CLSTR ok; + CLSTR err; + #endif +} CLSTR_STATUS; + + +static const char *tz_name_utc = TZ_NAME_UTC; +static CLSTR str_dst = { "DST", "Sommerzeit" }; + + + +/*HDR*/ +const char *inv_str( void ) +{ + static CLSTR s = { "** invalid **", "** ung" LCUE "ltig **" }; + + return _lstr( s ); + +} /* inv_str */ + + + +/*HDR*/ +int sprint_utc_offs( char *s, const char *info, long utc_offs ) +{ + int n = 0; + + // utc_offs is in [s] + char utc_offs_sign = ( utc_offs < 0 ) ? '-' : '+'; + ulong abs_utc_offs = labs( utc_offs ); + ulong utc_offs_hours = abs_utc_offs / SECS_PER_HOUR; + ulong tmp = abs_utc_offs % SECS_PER_HOUR; + ulong utc_offs_mins = tmp / MINS_PER_HOUR; + ulong utc_offs_secs = tmp % MINS_PER_HOUR; + + if ( info ) + n += sprintf( &s[n], "%s", info ); + + n += sprintf( &s[n], "%c%lu", utc_offs_sign, utc_offs_hours ); + + if ( utc_offs_mins || utc_offs_secs ) + n += sprintf( &s[n], ":%02lu", utc_offs_mins ); + + if ( utc_offs_secs ) + n += sprintf( &s[n], ":%02lu", utc_offs_secs ); + + n += sprintf( &s[n], "h" ); + + return n; + +} // sprint_utc_offs + + + +static /*HDR*/ +const char *get_tz_name( PCPS_TIME_STATUS_X pcps_status, long utc_offs, + ushort flags, int is_msf ) +{ + static char ws[40]; + const char *cp = NULL; + int n = 0; + + if ( ( pcps_status & PCPS_UTC ) && ( utc_offs == 0 ) ) + return tz_name_utc; // no offset, no DST + + if ( pcps_status & PCPS_DL_ENB ) + { + if ( utc_offs == ( 2 * SECS_PER_HOUR ) ) + { + cp = _lstr( lstr_cest ); + goto check_flags; + } + else + if ( ( utc_offs == SECS_PER_HOUR ) && is_msf ) + { + cp = _lstr( lstr_bst ); + goto check_flags; + } + } + + if ( !( pcps_status & PCPS_DL_ENB ) ) + { + if ( utc_offs == SECS_PER_HOUR ) + { + cp = _lstr( lstr_cet ); + goto check_flags; + } + else + if ( ( utc_offs == 0 ) && is_msf ) + { + cp = _lstr( lstr_gmt ); + goto check_flags; + } + } + + n = sprint_utc_offs( ws, tz_name_utc, utc_offs ); + +check_flags: + if ( cp ) + { + if ( flags == 0 ) + return cp; + + strcpy( ws, cp ); + + if ( flags & PCPS_TZ_NAME_FORCE_UTC_OFFS ) + { + n = strlen( ws ); + n += sprintf( &ws[n], "%*c(", pcps_time_tz_dist, ' ' ); + n += sprint_utc_offs( &ws[n], tz_name_utc, utc_offs ); + sprintf( &ws[n], ")" ); + } + } + + if ( flags & PCPS_TZ_NAME_APP_DST ) + { + if ( pcps_status & PCPS_DL_ENB ) + sprintf( _eos( ws ), ",%*c%s", pcps_time_tz_dist, + ' ', _lstr( str_dst ) ); + } + + return ws; +} + + + +/*HDR*/ +const char *pcps_tz_name( const PCPS_TIME *t, ushort flags, int is_msf ) +{ + return get_tz_name( t->status, t->offs_utc * SECS_PER_HOUR, flags, is_msf ); + +} // pcps_tz_name + + + +/*HDR*/ +const char *pcps_tz_name_from_hr_time( const PCPS_HR_TIME *hrt, ushort flags, int is_msf ) +{ + return get_tz_name( hrt->status, hrt->utc_offs, flags, is_msf ); + +} // pcps_tz_name_from_hr_time + + + +// The function below can be used to build a name for +// the time zone if the TIMESCALE, the UTC/DST status and the +// UTC offset are known, e.g. from plug-in clocks. + +/*HDR*/ +const char *pcps_tz_name_hr_status( const PCPS_HR_TIME *t, ushort flags, int is_msf ) +{ + static char ws[40]; + + if ( t->status & PCPS_SCALE_GPS ) + strcpy( ws, "GPS" ); + else + if ( t->status & PCPS_SCALE_TAI ) + strcpy( ws, "TAI" ); + else + return pcps_tz_name_from_hr_time( t, flags, is_msf); + + return ws; + +} // pcps_tz_name_hr_status + + + +// The function below can be used to build a name for +// the time zone if only the UTC/DST status is known +// but the UTC offset is not. This is the case, for example, +// if the Meinberg standard time string is decoded. + +/*HDR*/ +const char *pcps_tz_name_from_status( ushort status ) +{ + if ( status & PCPS_UTC ) + return tz_name_utc; + + return ( status & PCPS_DL_ENB ) ? _lstr( str_dst ) : ""; + +} // pcps_tz_name_from_status + + + +/*HDR*/ +char *pcps_date_time_str( char *s, const PCPS_TIME *t, + ushort year_limit, const char *tz_str ) +{ + if ( !_pcps_time_is_read( t ) ) + strcpy( s, str_not_avail ); + else + { + char *cp; + int i; + + _pcps_sprint_wday( s, t, language ); + cp = _eos( s ); + *cp++ = ','; + for ( i = 0; i < pcps_wday_date_dist; i++ ) + *cp++ = ' '; + _pcps_sprint_date( cp, t, year_limit ); + cp = _eos( s ); + for ( i = 0; i < pcps_date_time_dist; i++ ) + *cp++ = ' '; + _pcps_sprint_time_long( cp, t ); + + if ( tz_str ) + { + cp = _eos( s ); + for ( i = 0; i < pcps_time_tz_dist; i++ ) + *cp++ = ' '; + strcpy( cp, tz_str ); + } + } + + return s; + +} // pcps_date_time_str + + + +#if MBG_TGT_HAS_WCHAR_T && defined( MBG_TGT_WIN32 ) + +/*HDR*/ +wchar_t *pcps_date_time_wstr( wchar_t *ws, const PCPS_TIME *t, + ushort year_limit, const wchar_t *tz_str ) +{ + char stemp[80]; + wchar_t wstemp[80]; + + if ( !_pcps_time_is_read( t ) ) + mbstowcs( ws, str_not_avail, 32 ); + else + { + char *cp; + int i; + + _pcps_sprint_wday( stemp, t, language ); + cp = _eos( stemp ); + *cp++ = ','; + for ( i = 0; i < pcps_wday_date_dist; i++ ) + *cp++ = ' '; + _pcps_sprint_date( cp, t, year_limit ); + cp = _eos( stemp ); + for ( i = 0; i < pcps_date_time_dist; i++ ) + *cp++ = ' '; + _pcps_sprint_time_long( cp, t ); + + mbstowcs( wstemp, stemp, sizeof( wstemp ) ); + + if ( tz_str ) + _snwprintf( ws, sizeof( wstemp ) + 32, L"%s %s", wstemp, tz_str ); + } + + return ws; + +} // pcps_date_time_wstr + +#endif // MBG_TGT_HAS_WCHAR + + + +static /*HDR*/ +void pcps_setup_status_str( PCPS_STATUS_STR *pstr, int err_cond, + CLSTR_STATUS *pss ) +{ + pstr->is_err = err_cond != 0; + pstr->cp = _lstr( pstr->is_err ? pss->err : pss->ok ); + +} // pcps_setup_status_str + + + +// to return status strings to be displayed depending on the +// a clocks PCPS_TIME.status. + +/*HDR*/ +void pcps_status_strs( ushort status, int status_is_read, + int is_gps, PCPS_STATUS_STRS *pstrs ) +{ + CLSTR clstr_time_inval = DEFAULT_STR_TIME_INVAL; + CLSTR clstr_set_manually = DEFAULT_STR_SET_MANUALLY; + + CLSTR_STATUS lstr_dcf_has_syncd = + { DEFAULT_STR_DCF_HAS_SYNCD, DEFAULT_STR_DCF_HAS_NOT_SYNCD }; + + CLSTR_STATUS lstr_gps_syncd = + { DEFAULT_STR_GPS_SYNCD, DEFAULT_STR_GPS_NOT_SYNCD }; + + CLSTR_STATUS lstr_dcf_not_free_running = + { DEFAULT_STR_DCF_NOT_FREE_RUNNING, DEFAULT_STR_DCF_FREE_RUNNING }; + + CLSTR_STATUS lstr_gps_pos = + { DEFAULT_STR_GPS_POS_OK, DEFAULT_STR_GPS_POS_NOT_OK }; + + CLSTR clstr_ann_dst = DEFAULT_STR_ANN_DST; + CLSTR clstr_ann_ls = DEFAULT_STR_ANN_LS; + + PCPS_STATUS_STRS tmp_strs; + PCPS_STATUS_STR *pstr = &tmp_strs.s[0]; + + memset( &tmp_strs, 0, sizeof( tmp_strs ) ); + + if ( !status_is_read ) + pstr->cp = str_not_avail; + else + { + if ( status & PCPS_INVT ) + { + pstr->cp = _lstr( clstr_time_inval ); + pstr->is_err = 1; + } + else + if ( status & PCPS_IFTM ) + { + pstr->cp = _lstr( clstr_set_manually ); + pstr->is_err = 1; + } + else + { + pcps_setup_status_str( pstr, ( status & PCPS_SYNCD ) == 0, + is_gps ? &lstr_gps_syncd : &lstr_dcf_has_syncd ); + + pstr++; + + pcps_setup_status_str( pstr, ( status & PCPS_FREER ) != 0, + is_gps ? &lstr_gps_pos : &lstr_dcf_not_free_running ); + } + + pstr++; + + if ( status & PCPS_DL_ANN ) + pstr->cp = _lstr( clstr_ann_dst ); + else + if ( status & PCPS_LS_ANN ) + pstr->cp = _lstr( clstr_ann_ls ); + } + + *pstrs = tmp_strs; + +} // pcps_status_strs + + + +/*HDR*/ +char *pcps_port_str( char *s, const PCPS_DEV *pdev ) +{ + ushort port = _pcps_port_base( pdev, 0 ); + + ushort n = sprintf( s, "%3Xh", port ); + + port = _pcps_port_base( pdev, 1 ); + + if ( port ) + sprintf( &s[n], ", %3Xh", port ); + + return s; + +} // pcps_port_str + + + +/*HDR*/ +const char *pcps_tzcode_str( PCPS_TZCODE tzcode ) +{ + if ( language < N_LNG && tzcode < N_PCPS_TZCODE ) + return tzcode_name[tzcode][language]; + + return inv_str(); + +} // pcps_tzcode_str + + + +/*HDR*/ +char *pcps_serial_str( char *s, int i, const RECEIVER_PORT_CFG *p, + const RECEIVER_INFO *p_ri, int short_strs ) +{ + const PORT_SETTINGS *p_ps = &p->pii[i].port_info.port_settings; + const STR_TYPE_INFO *p_sti = &p->stii[p_ps->str_type].str_type_info; + + sprintf( s, "%lu,%s", (ulong) p_ps->parm.baud_rate, p_ps->parm.framing ); + + if ( short_strs ) + sprintf( _eos( s ), ",%s", short_mode_name[p_ps->mode] ); + else + { + if ( p_ri->n_str_type > 1 ) + sprintf( _eos( s ), ", %s", p_sti->long_name ); + + sprintf( _eos( s ), ", %s", _lstr( mode_name[p_ps->mode] ) ); + } + + return( s ); + +} // pcps_serial_str + + diff --git a/mbglib/common/pcpslstr.h b/mbglib/common/pcpslstr.h new file mode 100644 index 0000000..650799d --- /dev/null +++ b/mbglib/common/pcpslstr.h @@ -0,0 +1,1052 @@ + +/************************************************************************** + * + * $Id: pcpslstr.h 1.28 2012/10/15 13:01:23Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for pcpslstr.c. + * + * ----------------------------------------------------------------------- + * $Log: pcpslstr.h $ + * Revision 1.28 2012/10/15 13:01:23Z martin + * Include cfg_hlp.h. + * Made all declarations extern C. + * Added menu titles for PTP and PTP Unicast configuration. + * Added DEFAULT_OPT_NAME_TR_DISTANCE. + * Support time slots mode for programmable pulse outputs. + * Added strings for programmable output synthesizer mode. + * Fixed build under FreeBSD. + * Also use ANSI umlauts under QNX. + * Updated function prototypes. + * Revision 1.27 2010/06/28 08:28:17Z stefan + * Added greek character mu. + * Corrected a spelling mistake. + * Defined umlauts as hex codes. + * Added _pcps_sprint_vernum macro which is either _dec or _hex, + * depending on the target platform. + * Revision 1.26 2010/06/25 13:58:25 daniel + * Added IgnoreTFOM related language strings + * Revision 1.25 2010/01/28 09:02:27 martin + * Added menu option name for LAN interface. + * Added German POUT mode names for DCF77_M59. + * Revision 1.24 2009/03/19 08:07:45Z daniel + * Updated function prototypes. + * Revision 1.23 2008/11/14 12:12:45Z martin + * Updated function prototypes. + * Revision 1.22 2008/01/17 09:12:41Z daniel + * Use mbg_tgt.h, specially to care about wchar_t. + * Added strings for WEZ/WESZ, BST, GMT. + * Updated function prototypes. + * Revision 1.21 2007/03/30 13:24:42Z martin + * Added initializer for status string if time has been set manually. + * Revision 1.20 2007/03/29 12:59:23Z martin + * Moved some definitions here. + * Added and modified some definitions related to TZCODE. + * Revision 1.19 2006/10/23 15:18:15Z martin + * Added some configuration warning msg texts. + * Added definitions for uppercase umlauts. + * Separated English and German initializers for some strings. + * Revision 1.18 2006/09/26 14:57:22Z martin + * Added DEFAULT_OPT_NAME_POUT. + * Revision 1.17 2000/07/02 07:02:16Z martin + * Separate English and German initializers for "invalid time". + * Revision 1.16 2006/05/23 20:13:24Z martin + * Added initializers for German POUT mode strings. + * Revision 1.15 2005/12/20 10:30:56Z martin + * Made some strings start with uppercase letters. + * Revision 1.14 2005/08/12 12:35:34Z martin + * Fixed missing comma in a macro. + * Revision 1.13 2005/03/03 08:49:38Z martin + * Modified DEFAULT_OPT_NAME_SERIAL. + * Modified DEFAULT_OPT_NAME_IRIG_... + * Added default strings for synthesizer. + * Revision 1.12 2004/11/23 09:36:12Z martin + * Fixed a typo. + * Revision 1.11 2004/11/09 15:08:08Z martin + * Defined some separate strings for English and German. + * Modified some string contents. + * Revision 1.10 2004/10/26 15:03:57 martin + * Distinguish between IRIG RX and TX strings. + * Revision 1.9 2004/08/18 14:59:04Z martin + * Defined some flag bits to control the format of the output string + * generated by pcps_tz_name(). + * Updated function prototypes. + * Revision 1.8 2004/04/07 12:49:06Z martin + * Added initializers for IRIG output cfg strings. + * Revision 1.7 2003/04/15 10:47:29Z martin + * Added initializers for IRIG menu strings. + * Updated function prototypes. + * Revision 1.6 2002/12/18 13:57:53 martin + * Some definitions and variables made global. + * Added some new macros _pcps_sprint_vernum...() + * and _pcps_sprint_dev_id(). + * Revision 1.5 2002/02/19 10:01:36Z MARTIN + * New initializers for string mode names. + * New global variables mode_name and short_mode_name. + * Updated function prototypes. + * Revision 1.4 2001/09/17 13:26:16 MARTIN + * Added definitions for PCPS_STATUS_STRS. + * Added initializers for strings. + * Added some comments. + * Updated function prototypes. + * Revision 1.3 2001/08/14 11:35:40 MARTIN + * Added initializers for commonly used mulit-language + * text strings. + * Revision 1.2 2001/02/28 15:48:34 MARTIN + * Updated function prototypes. + * Modified syntax to initialize variables. + * Revision 1.1 2000/07/21 12:15:12 MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _PCPSLSTR_H +#define _PCPSLSTR_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> +#include <cfg_hlp.h> +#include <parmpcps.h> +#include <ctrydttm.h> +#include <cnv_wday.h> + +#if MBG_TGT_HAS_WCHAR_T + #include <wchar.h> +#endif + +#ifdef _PCPSLSTR + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + +// upper case 'A' umlaut +#define ANSI_UC_A_UML '\xC4' // single char +#define ANSI_US_A_UML "\xC4" // string + +// upper case 'O' umlaut +#define ANSI_UC_O_UML '\xD6' // single char +#define ANSI_US_O_UML "\xD6" // string + +// upper case 'U' umlaut +#define ANSI_UC_U_UML '\xDC' // single char +#define ANSI_US_U_UML "\xDC" // string + +// lower case 'a' umlaut +#define ANSI_LC_A_UML '\xE4' // single char +#define ANSI_LS_A_UML "\xE4" // string + +// lower case 'o' umlaut +#define ANSI_LC_O_UML '\xF6' // single char +#define ANSI_LS_O_UML "\xF6" // string + +// lower case 'u' umlaut +#define ANSI_LC_U_UML '\xFC' // single char +#define ANSI_LS_U_UML "\xFC" // string + +// 'sz' umlaut +#define ANSI_LC_SZ_UML '\xDF' // single char +#define ANSI_LS_SZ_UML "\xDF" // string + +// degree character +#define ANSI_C_DEGREE '\xB0' // single char +#define ANSI_S_DEGREE "\xB0" // string + +// greek mu character +#define ANSI_C_MU '\xB5' //single char +#define ANSI_S_MU "\xB5" //string + +#if defined( MBG_TGT_WIN32 ) \ + || defined( MBG_TGT_UNIX ) \ + || defined( MBG_TGT_QNX ) + #define DEFAULT_PCPS_WDAY_DATE_DIST 1 + #define DEFAULT_PCPS_DATE_TIME_DIST 2 + #define DEFAULT_PCPS_TIME_TZ_DIST 1 + + #define UCAE ANSI_US_A_UML + #define UCOE ANSI_US_O_UML + #define UCUE ANSI_US_U_UML + + #define LCAE ANSI_LS_A_UML + #define LCOE ANSI_LS_O_UML + #define LCUE ANSI_LS_U_UML + + #define LCSZ ANSI_LS_SZ_UML + #define DEG ANSI_S_DEGREE + #define MU ANSI_S_MU +#else + #define DEFAULT_PCPS_WDAY_DATE_DIST 1 + #define DEFAULT_PCPS_DATE_TIME_DIST 2 + #define DEFAULT_PCPS_TIME_TZ_DIST 1 + + #define UCAE "\x8E" + #define UCOE "\x99" + #define UCUE "\x9A" + + #define LCAE "\x84" + #define LCOE "\x94" + #define LCUE "\x81" + + #define LCSZ "\xE1" + #define DEG "\xF8" + #define MU "\xE6" +#endif + + +// The flags defined below can be passed to pcps_tz_name() +// in order to control the generation of time zone names + +enum +{ + PCPS_TZ_NAME_BIT_FORCE_UTC_OFFS, // always print "UTC+offs" + PCPS_TZ_NAME_BIT_APP_DST, // append DST status + N_PCPS_TZ_NAME_FLAG +}; + +// bit masks corresponding to the flags above +#define PCPS_TZ_NAME_FORCE_UTC_OFFS ( 1UL << PCPS_TZ_NAME_BIT_FORCE_UTC_OFFS ) +#define PCPS_TZ_NAME_APP_DST ( 1UL << PCPS_TZ_NAME_BIT_APP_DST ) + + +// The definitions below are used with pcps_get_status_strs(). + +#define N_PCPS_STATUS_STR 3 + +typedef struct +{ + const char *cp; + int is_err; +} PCPS_STATUS_STR; + +typedef struct +{ + PCPS_STATUS_STR s[N_PCPS_STATUS_STR]; +} PCPS_STATUS_STRS; + + +// initializers for commonly use multi-language strings +// (type: CLSTR ) + + +// time adjustment window + +#define DEFAULT_STR_TIME_ADJ_STATUS \ +{ \ + "Time Adjustment Status", \ + "Status der Zeitkontrolle" \ +} + +#define DEFAULT_STR_SYS_TIME \ +{ \ + "System Time:", \ + "Systemzeit:" \ +} + +#define DEFAULT_STR_REF_TIME \ +{ \ + "Reference Time:", \ + "Referenzzeit:" \ +} + +#define DEFAULT_STR_DELTA_TIME \ +{ \ + "Difference:", \ + "Zeitdifferenz:" \ +} + +#define DEFAULT_STR_LAST_CORR \ +{ \ + "Last Correction:", \ + "Letzte Korrektur:" \ +} + +#define DEFAULT_STR_WAIT_SYNC \ +{ \ + "Waiting for Sync After Reset ...", \ + "Warte auf Sync. nach Reset ..." \ +} + + +// ref time window + +#define DEFAULT_STR_REF_TIME_INFO \ +{ \ + "Reference Time Info", \ + "Referenzzeit" \ +} + +#define DEFAULT_STR_REF_SRC_LABEL \ +{ \ + "Time Source:", \ + "Funkuhr ID:" \ +} + +#define DEFAULT_STR_REF_SYNC_LABEL \ +{ \ + "Last Sync.:", \ + "Letzte Sync.:" \ +} + + +// Clock status messages: + +// Time is not valid (i.e. after batt. empty). +#define DEFAULT_STR_TIME_INVAL_EN \ + "Ref. Time is Invalid" + +#define DEFAULT_STR_TIME_INVAL_DE \ + "Referenzzeit nicht g" LCUE "ltig" + +#define DEFAULT_STR_TIME_INVAL \ +{ \ + DEFAULT_STR_TIME_INVAL_EN, \ + DEFAULT_STR_TIME_INVAL_DE \ +} + +// on-board time has been set manually +#define DEFAULT_STR_SET_MANUALLY \ +{ \ + "Time has been set manually", \ + "Zeit wurde manuell gesetzt" \ +} + +// DCF77 receiver has synch'd at least once +// after reset. +#define DEFAULT_STR_DCF_HAS_SYNCD \ +{ \ + "Synchronized after last RESET", \ + "Sync. nach RESET ist erfolgt" \ +} + +// DCF77 receiver has not synch'd after reset. +#define DEFAULT_STR_DCF_HAS_NOT_SYNCD \ +{ \ + "Not synchronized after last RESET", \ + "Sync. nach RESET noch nicht erfolgt" \ +} + +// DCF77 receiver currently runs on XTAL. +#define DEFAULT_STR_DCF_FREE_RUNNING \ +{ \ + "Clock running on Xtal oscillator", \ + "Funkuhr l" LCAE "uft frei auf Quarzbasis" \ +} + +// DCF77 receiver is currently synchronized. +#define DEFAULT_STR_DCF_NOT_FREE_RUNNING \ +{ \ + "Clock is synchronized", \ + "Senderf" LCUE "hrung" \ +} + +// GPS receiver is currently synchronized. +#define DEFAULT_STR_GPS_SYNCD \ +{ \ + "Time is synchronized", \ + "Zeitsynchronisation ist erfolgt" \ +} + +// GPS receiver is currently synchronized. +#define DEFAULT_STR_GPS_NOT_SYNCD \ +{ \ + "Time not synchronized", \ + "Zeit ist nicht synchron" \ +} + +// GPS receiver has verified its position. +#define DEFAULT_STR_GPS_POS_OK \ +{ \ + "Receiver position has been verified", \ + "Positionbestimmung durchgef" LCUE "hrt" \ +} + +// GPS receiver has not verified its position. +#define DEFAULT_STR_GPS_POS_NOT_OK \ +{ \ + "Receiver pos. not verified", \ + "Position nicht gepr" LCUE "ft" \ +} + +// Announcement of DST change. +#define DEFAULT_STR_ANN_DST \ +{ \ + "Change in Daylight Saving Announced", \ + "Zeitumschaltung angek" LCUE "ndigt" \ +} + +// Announcement of leap second. +#define DEFAULT_STR_ANN_LS \ +{ \ + "Leap Second Announced", \ + "Schaltsekunde angek" LCUE "ndigt" \ +} + + +// menu option: setup (title) + +#define DEFAULT_OPT_NAME_SETUP_EN \ + "Setup" + +#define DEFAULT_OPT_NAME_SETUP_DE \ + "Einstellungen" + +#define DEFAULT_OPT_NAME_SETUP \ +{ \ + DEFAULT_OPT_NAME_SETUP_EN, \ + DEFAULT_OPT_NAME_SETUP_DE \ +} + + +// menu option: setup date/time + +#define DEFAULT_OPT_NAME_SET_TIME_EN \ + "Radio Clock's Date/Time" + +#define DEFAULT_OPT_NAME_SET_TIME_DE \ + "Datum/Zeit der Funkuhr" + +#define DEFAULT_OPT_NAME_SET_TIME \ +{ \ + DEFAULT_OPT_NAME_SET_TIME_EN, \ + DEFAULT_OPT_NAME_SET_TIME_DE \ +} + +#define DEFAULT_STR_NEW_DATE \ +{ \ + "New date", \ + "Neues Datum" \ +} + +#define DEFAULT_STR_NEW_TIME \ +{ \ + "New time", \ + "Neue Zeit" \ +} + + +// menu option: setup time zone + +#define TZ_NAME_UTC "UTC" + +#define TZ_NAME_MEZ "MEZ" +#define TZ_NAME_MESZ "MESZ" +#define TZ_NAME_CET "CET" +#define TZ_NAME_CEST "CEST" + +#define TZ_NAME_OEZ "OEZ" +#define TZ_NAME_OESZ "OESZ" +#define TZ_NAME_EET "EET" +#define TZ_NAME_EEST "EEST" + +#define TZ_NAME_WEZ "WEZ" +#define TZ_NAME_WESZ "WESZ" +#define TZ_NAME_GMT "GMT" +#define TZ_NAME_BST "BST" + +#define DEFAULT_OPT_NAME_TZ \ +{ \ + "Radio Clock's Time Zone", \ + "Zeitzone der Funkuhr" \ +} + + +// menu option: setup time zone + +#define DEFAULT_TZCODE_NAME_CET_CEST \ +{ \ + TZ_NAME_CET "/" TZ_NAME_CEST, \ + TZ_NAME_MEZ "/" TZ_NAME_MESZ \ +} + +#define DEFAULT_TZCODE_HINT_CET_CEST \ +{ \ + "Central European Time or Summer Time, as broadcasted by DCF77", \ + "Mitteleurop" LCAE "ische Zeit oder Sommerzeit, wie von DCF77 gesendet" \ +} + +#define DEFAULT_TZCODE_NAME_GMT_BST \ +{ \ + TZ_NAME_GMT "/" TZ_NAME_BST, \ + TZ_NAME_WEZ "/" TZ_NAME_WESZ \ +} + +#define DEFAULT_TZCODE_HINT_GMT_BST \ +{ \ + "Greenwich Mean Time or British Summer Time, as broadcasted by MSF", \ + "Westeurop" LCAE "ische Zeit oder britische Sommerzeit, wie von MSF gesendet" \ +} + + + +#define DEFAULT_TZCODE_NAME_CET \ +{ \ + "always " TZ_NAME_CET, \ + "immer " TZ_NAME_MEZ \ +} + +#define DEFAULT_TZCODE_HINT_CET \ +{ \ + "always CET (UTC+1h), daylight saving suppressed", \ + "immer MEZ (UTC+1h), Sommerzeit wird unterdr" LCUE "ckt" \ +} + + +#define DEFAULT_TZCODE_NAME_UTC \ +{ \ + TZ_NAME_UTC, \ + TZ_NAME_UTC \ +} + +#define DEFAULT_TZCODE_HINT_UTC \ +{ \ + "always UTC", \ + "immer UTC" \ +} + + +#define DEFAULT_TZCODE_NAME_EET_EEST \ +{ \ + TZ_NAME_EET "/" TZ_NAME_EEST, \ + TZ_NAME_OEZ "/" TZ_NAME_OESZ \ +} + +#define DEFAULT_TZCODE_HINT_EET_EEST \ +{ \ + "East European Time, CET/CEST + 1h", \ + "Osteurop" LCAE "ische Zeit, MEZ/MESZ + 1h" \ +} + + +#define DEFAULT_TZCODE_NAMES \ +{ \ + DEFAULT_TZCODE_NAME_CET_CEST, \ + DEFAULT_TZCODE_NAME_CET, \ + DEFAULT_TZCODE_NAME_UTC, \ + DEFAULT_TZCODE_NAME_EET_EEST \ +} + +#define DEFAULT_TZCODE_HINTS \ +{ \ + DEFAULT_TZCODE_HINT_CET_CEST, \ + DEFAULT_TZCODE_HINT_CET, \ + DEFAULT_TZCODE_HINT_UTC, \ + DEFAULT_TZCODE_HINT_EET_EEST \ +} + + +// menu option: setup serial parameters + +#define DEFAULT_OPT_NAME_SERIAL \ +{ \ + "On-Board Serial Ports", \ + "Serielle Schnittstellen der Karte" \ +} + + +// menu option: setup enable flags + +#define DEFAULT_OPT_NAME_EF \ +{ \ + "Enable Outputs", \ + "Freischaltung der Ausg" LCAE "nge" \ +} + + +// menu option: setup length of antenna cable + +#define DEFAULT_OPT_NAME_CAB_LEN \ +{ \ + "Antenna Cable", \ + "Antennenkabel" \ +} + + +// menu option: setup distance from transmitter + +#define DEFAULT_OPT_NAME_TR_DISTANCE \ +{ \ + "Distance from Transmitter", \ + "Senderentfernung" \ +} + + +// menu option: setup IRIG config + +#define DEFAULT_OPT_NAME_IRIG_TX_EN "IRIG Output" +#define DEFAULT_OPT_NAME_IRIG_TX_DE "IRIG-Ausgang" + +#define DEFAULT_OPT_NAME_IRIG_TX \ +{ \ + DEFAULT_OPT_NAME_IRIG_TX_EN, \ + DEFAULT_OPT_NAME_IRIG_TX_DE \ +} + + +#define DEFAULT_OPT_NAME_IRIG_RX_EN "IRIG Input" +#define DEFAULT_OPT_NAME_IRIG_RX_DE "IRIG-Eingang" + +#define DEFAULT_OPT_NAME_IRIG_RX \ +{ \ + DEFAULT_OPT_NAME_IRIG_RX_EN, \ + DEFAULT_OPT_NAME_IRIG_RX_DE \ +} + + +#define DEFAULT_STR_IRIG_FMT_EN "IRIG Code Format" +#define DEFAULT_STR_IRIG_FMT_DE "IRIG Code-Format" + +#define DEFAULT_STR_IRIG_FMT \ +{ \ + DEFAULT_STR_IRIG_FMT_EN, \ + DEFAULT_STR_IRIG_FMT_DE \ +} + + +#define DEFAULT_STR_IRIG_OFFS_EN "IRIG Time Offset from UTC" +#define DEFAULT_STR_IRIG_OFFS_DE "IRIG-Zeitoffset zu UTC" + +#define DEFAULT_STR_IRIG_OFFS \ +{ \ + DEFAULT_STR_IRIG_OFFS_EN, \ + DEFAULT_STR_IRIG_OFFS_DE \ +} + + +#define DEFAULT_STR_IRIG_TIMESTR_UTC_EN "Send serial UTC" +#define DEFAULT_STR_IRIG_TIMESTR_UTC_DE "Seriell UTC ausgeben" + +#define DEFAULT_STR_IRIG_TIMESTR_UTC \ +{ \ + DEFAULT_STR_IRIG_TIMESTR_UTC_EN, \ + DEFAULT_STR_IRIG_TIMESTR_UTC_DE \ +} + + +#define DEFAULT_STR_IRIG_OUTPUT_LOC_TM_EN "Transmit local time instead of UTC" +#define DEFAULT_STR_IRIG_OUTPUT_LOC_TM_DE "Ortszeit statt UTC aussenden" + +#define DEFAULT_STR_IRIG_OUTPUT_LOC_TM \ +{ \ + DEFAULT_STR_IRIG_OUTPUT_LOC_TM_EN, \ + DEFAULT_STR_IRIG_OUTPUT_LOC_TM_DE \ +} + +#define DEFAULT_IGNORE_RX_TFOM_EN "Ignore TFOM" +#define DEFAULT_IGNORE_RX_TFOM_DE "Ignoriere TFOM" + +#define DEFAULT_IGNORE_RX_TFOM \ +{ \ + DEFAULT_IGNORE_RX_TFOM_EN, \ + DEFAULT_IGNORE_RX_TFOM_DE \ +} + +#define DEFAULT_STR_TFOM_ALWAYS_SYNC_EN "Output TFOM always as 'sync'" +#define DEFAULT_STR_TFOM_ALWAYS_SYNC_DE "TFOM immer als 'sync' ausgeben" + +#define DEFAULT_STR_TFOM_ALWAYS_SYNC \ +{ \ + DEFAULT_STR_TFOM_ALWAYS_SYNC_EN, \ + DEFAULT_STR_TFOM_ALWAYS_SYNC_DE \ +} + + +#define DEFAULT_STR_IRIG_NOT_CFGD_EN \ + "The IRIG receiver has not yet been configured!\n" \ + "\n" \ + "Please make sure the correct " DEFAULT_STR_IRIG_FMT_EN " has been\n" \ + "selected, and enter the correct " DEFAULT_STR_IRIG_OFFS_EN "\n" \ + "according to the settings of the IRIG generator." + +#define DEFAULT_STR_IRIG_NOT_CFGD_DE \ + "Der IRIG-Empf" LCAE "nger wurde noch nicht konfiguriert!\n" \ + "\n" \ + "Das ausgew" LCAE "hlte " DEFAULT_STR_IRIG_FMT_DE " sowie der\n" \ + DEFAULT_STR_IRIG_OFFS_DE " m" LCUE "ssen den Einstellungen\n" \ + "des verwendeten IRIG-Generators entsprechen." + +#define DEFAULT_STR_IRIG_NOT_CFGD \ +{ \ + DEFAULT_STR_IRIG_NOT_CFGD_EN, \ + DEFAULT_STR_IRIG_NOT_CFGD_DE \ +} + + +#define DEFAULT_STR_IRIG_INVT_EN \ + "Please note that the IRIG receiver status may read\n" \ + "\"" DEFAULT_STR_TIME_INVAL_EN "\" if the receiver's on-board date\n" \ + "does not correspond to the date (day-of-year number)\n" \ + "transmitted by the IRIG source." + +#define DEFAULT_STR_IRIG_INVT_DE \ + "Wenn im Status des IRIG-Empf" LCAE "ngers \"" DEFAULT_STR_TIME_INVAL_DE "\"\n" \ + "angezeigt wird, kann der Grund daf" LCUE "r sein, dass das Datum\n" \ + "auf der Einsteckkarte nicht mit dem vom IRIG-Generator\n" \ + "gesendeten Datum (bzw. dem Jahrestag) " LCUE "bereinstimmt." \ + +#define DEFAULT_STR_IRIG_INVT \ +{ \ + DEFAULT_STR_IRIG_INVT_EN, \ + DEFAULT_STR_IRIG_INVT_DE \ +} + + +// menu option: programmable outputs + +#define DEFAULT_OPT_NAME_POUT \ +{ \ + "Programmable Pulse Outputs", \ + "Programmierbare Schaltausg" LCAE "nge" \ +} + + +// menu option: frequency synthesizer + +#define DEFAULT_OPT_NAME_SYNTH \ +{ \ + "Frequency Synthesizer", \ + "Frequenz-Synthesizer" \ +} + +#define DEFAULT_STR_SYNTH_FREQ \ +{ \ + "Frequency", \ + "Frequenz" \ +} + +#define DEFAULT_STR_SYNTH_PHASE \ +{ \ + "Phase", \ + NULL \ +} + + +// menu option: LAN interface + +#define DEFAULT_OPT_NAME_LAN_INTF_EN "LAN Interface" +#define DEFAULT_OPT_NAME_LAN_INTF_DE "Netzwerkschnittstelle" + +#define DEFAULT_OPT_NAME_LAN_INTF \ +{ \ + DEFAULT_OPT_NAME_LAN_INTF_EN, \ + DEFAULT_OPT_NAME_LAN_INTF_DE \ +} + + + +// menu option: PTP configuration + +#define DEFAULT_OPT_NAME_PTP_CFG_EN "PTP Configuration" +#define DEFAULT_OPT_NAME_PTP_CFG_DE "PTP-Konfiguration" + +#define DEFAULT_OPT_NAME_PTP_CFG \ +{ \ + DEFAULT_OPT_NAME_PTP_CFG_EN, \ + DEFAULT_OPT_NAME_PTP_CFG_DE \ +} + + + +// menu option: PTP Unicast configuration + +#define DEFAULT_OPT_NAME_PTP_UC_CFG_EN "PTP Unicast Configuration" +#define DEFAULT_OPT_NAME_PTP_UC_CFG_DE "PTP-Unicast-Konfiguration" + +#define DEFAULT_OPT_NAME_PTP_UC_CFG \ +{ \ + DEFAULT_OPT_NAME_PTP_UC_CFG_EN, \ + DEFAULT_OPT_NAME_PTP_UC_CFG_DE \ +} + + + +/* + * Default initializers for German mode string names. + * English strings are defined in in gpsdefs.h. + */ +#define GER_MODE_NAME_STR_ON_REQ "nur auf Anfrage '?'" +#define GER_MODE_NAME_STR_PER_SEC "sek" LCUE "ndlich" +#define GER_MODE_NAME_STR_PER_MIN "min" LCUE "tlich" +#define GER_MODE_NAME_STR_AUTO "automatisch" +#define GER_MODE_NAME_STR_ON_REQ_SEC "sek" LCUE "ndlich nach Anfrage" + +#define DEFAULT_MODE_NAMES \ +{ \ + { ENG_MODE_NAME_STR_ON_REQ, GER_MODE_NAME_STR_ON_REQ }, \ + { ENG_MODE_NAME_STR_PER_SEC, GER_MODE_NAME_STR_PER_SEC }, \ + { ENG_MODE_NAME_STR_PER_MIN, GER_MODE_NAME_STR_PER_MIN }, \ + { ENG_MODE_NAME_STR_AUTO, GER_MODE_NAME_STR_AUTO }, \ + { ENG_MODE_NAME_STR_ON_REQ_SEC, GER_MODE_NAME_STR_ON_REQ_SEC } \ +} + + +/* + * Default initializers for German pulse output mode string names. + * English strings are defined in in gpsdefs.h. + */ +#define GER_POUT_NAME_IDLE "Nicht verwendet" +#define GER_POUT_NAME_TIMER "Zeitschaltung" +#define GER_POUT_NAME_SINGLE_SHOT "Einzelimpuls" +#define GER_POUT_NAME_CYCLIC_PULSE "Zyklischer Impuls" +#define GER_POUT_NAME_PER_SEC "Sek" LCUE "ndlicher Impuls" +#define GER_POUT_NAME_PER_MIN "Min" LCUE "tlicher Impuls" +#define GER_POUT_NAME_PER_HOUR "St" LCUE "ndlicher Impuls" +#define GER_POUT_NAME_DCF77 "DCF77-Zeitmarken" +#define GER_POUT_NAME_POS_OK "Position OK" +#define GER_POUT_NAME_TIME_SYNC "Zeit synchron" +#define GER_POUT_NAME_ALL_SYNC "alles synchron" +#define GER_POUT_NAME_TIMECODE "DCLS-Zeitcode" +#define GER_POUT_NAME_TIMESTR "COM-Zeittelegramm" +#define GER_POUT_NAME_10MHZ "Festfrequenz 10 MHz" +#define GER_POUT_NAME_DCF77_M59 "DCF77-Zeitmarken mit 59. Impuls" +#define GER_POUT_NAME_SYNTH "Frequenz-Synthesizer" +#define GER_POUT_NAME_TIME_SLOTS "Zeitschlitze pro Minute" + +#define DEFAULT_GER_POUT_NAMES \ +{ \ + GER_POUT_NAME_IDLE, \ + GER_POUT_NAME_TIMER, \ + GER_POUT_NAME_SINGLE_SHOT, \ + GER_POUT_NAME_CYCLIC_PULSE, \ + GER_POUT_NAME_PER_SEC, \ + GER_POUT_NAME_PER_MIN, \ + GER_POUT_NAME_PER_HOUR, \ + GER_POUT_NAME_DCF77, \ + GER_POUT_NAME_POS_OK, \ + GER_POUT_NAME_TIME_SYNC, \ + GER_POUT_NAME_ALL_SYNC, \ + GER_POUT_NAME_TIMECODE, \ + GER_POUT_NAME_TIMESTR, \ + GER_POUT_NAME_10MHZ, \ + GER_POUT_NAME_DCF77_M59, \ + GER_POUT_NAME_SYNTH, \ + GER_POUT_NAME_TIME_SLOTS \ +} + +/* + * Default initializers for German pulse output mode hints. + * English strings are defined in in gpsdefs.h. + */ +#define GER_POUT_HINT_IDLE "Konstanter Ausgangspegel" +#define GER_POUT_HINT_TIMER "Schalten zu den angegebenen Zeiten" +#define GER_POUT_HINT_SINGLE_SHOT "Einzelner Impuls mit angegebener L" LCAE "nge" +#define GER_POUT_HINT_CYCLIC_PULSE "Impulse wiederholt nach angegebenem Intervall" +#define GER_POUT_HINT_PER_SEC "Impuls zu Beginn jeder Sekunde" +#define GER_POUT_HINT_PER_MIN "Impuls zu Beginn jeder Minute" +#define GER_POUT_HINT_PER_HOUR "Impuls zu Beginn jeder Stunde" +#define GER_POUT_HINT_DCF77 "DCF77-kompatible Zeitmarken" +#define GER_POUT_HINT_POS_OK "Schalten, wenn Empf" LCAE "ngerposition " LCUE "berpr" LCUE "ft" +#define GER_POUT_HINT_TIME_SYNC "Schalten, wenn Zeit synchron" +#define GER_POUT_HINT_ALL_SYNC "Schalten, wenn Zeit synchron und Position " LCUE "berpr" LCUE "ft" +#define GER_POUT_HINT_TIMECODE "Unmodulierter Zeitcode des IRIG-Ausgangs" +#define GER_POUT_HINT_TIMESTR "Zeittelegramm der seriellen Schnittstelle der Karte duplizieren" +#define GER_POUT_HINT_10MHZ "Feste Ausgangsfrequenz 10 MHz" +#define GER_POUT_HINT_DCF77_M59 "Zeitmarken wie DCF77, aber mit 500 ms Impuls in 59. Sekunde" +#define GER_POUT_HINT_SYNTH "Durch programmierbaren Synthesizer erzeugte Frequenz" +#define GER_POUT_HINT_TIME_SLOTS "Programmierbare Zeitslots, die in jeder Minute aktiviert werden" + +#define DEFAULT_GER_POUT_HINTS \ +{ \ + GER_POUT_HINT_IDLE, \ + GER_POUT_HINT_TIMER, \ + GER_POUT_HINT_SINGLE_SHOT, \ + GER_POUT_HINT_CYCLIC_PULSE, \ + GER_POUT_HINT_PER_SEC, \ + GER_POUT_HINT_PER_MIN, \ + GER_POUT_HINT_PER_HOUR, \ + GER_POUT_HINT_DCF77, \ + GER_POUT_HINT_POS_OK, \ + GER_POUT_HINT_TIME_SYNC, \ + GER_POUT_HINT_ALL_SYNC, \ + GER_POUT_HINT_TIMECODE, \ + GER_POUT_HINT_TIMESTR, \ + GER_POUT_HINT_10MHZ, \ + GER_POUT_HINT_DCF77_M59, \ + GER_POUT_HINT_SYNTH, \ + GER_POUT_HINT_TIME_SLOTS \ +} + + + +// some macros which generate proper function calls + +#define _pcps_sprint_vernum_dec( _s, _v ) \ + sprintf( (_s), "v%u.%02u", \ + ( (unsigned) (_v) ) / 100, \ + ( (unsigned) (_v) ) % 100 ) + +#define _pcps_sprint_vernum_hex( _s, _v ) \ + sprintf( (_s), "v%X.%02X", \ + ( (unsigned) (_v) ) >> 8, \ + ( (unsigned) (_v) ) & 0xFF ) + +#if defined( MBG_TGT_WIN32 ) + #define _pcps_sprint_vernum _pcps_sprint_vernum_dec +#else + #define _pcps_sprint_vernum _pcps_sprint_vernum_hex +#endif + + +#define _pcps_sprint_dev_id( _s, _n ) \ + sprintf( (_s), "%04Xh", _n ) + + +#define _pcps_sprint_wday( _s, _t, _l ) \ + sprint_ctry_wday( (_s), _wday_mon17_to_sun06( (_t)->wday ), (_l) ) + +#define _pcps_sprint_date( _s, _t, _yl ) \ + sprint_ctry_dt( (_s), (_t)->mday, (_t)->month, \ + pcps_exp_year( (_t)->year, (_yl) ) ) + +#define _pcps_sprint_time( _s, _t ) \ + sprint_ctry_tm( (_s), (_t)->hour, (_t)->min, (_t)->sec ) + +#define _pcps_sprint_time_long( _s, _t ) \ + sprint_ctry_tm_long( (_s), (_t)->hour, (_t)->min, (_t)->sec, (_t)->sec100, 2 ) + + +#define _cput_pcps_date( _t, _yl ) \ +{ \ + char s[80]; \ + _pcps_sprint_date( s, (_t), (_yl) ); \ + cputs( s ); \ +} + +#define _cput_pcps_time( _t ) \ +{ \ + char s[80]; \ + _pcps_sprint_time( s, (_t) ); \ + cputs( s ); \ +} + +#define _cput_pcps_time_long( _t ) \ +{ \ + char s[80]; \ + _pcps_sprint_time_long( s, (_t) ); \ + cputs( s ); \ +} + +#define _cput_pcps_date_and_time( _t, _yl, _tz ) \ +{ \ + char s[80]; \ + cputs( pcps_date_time_str( s, (_t), (_yl), (_tz) ) ); \ +} + + +_ext const char *str_not_avail +#ifdef _DO_INIT + = "N/A" +#endif +; + + +_ext CLSTR lstr_cet +#ifdef _DO_INIT + = { TZ_NAME_CET, TZ_NAME_MEZ } +#endif +; + + +_ext CLSTR lstr_cest +#ifdef _DO_INIT + = { TZ_NAME_CEST, TZ_NAME_MESZ } +#endif +; + +_ext CLSTR lstr_gmt +#ifdef _DO_INIT + = { TZ_NAME_GMT, TZ_NAME_WEZ } +#endif +; + + +_ext CLSTR lstr_bst +#ifdef _DO_INIT + = { TZ_NAME_BST, TZ_NAME_WESZ } +#endif +; + +_ext CLSTR tzcode_name[N_PCPS_TZCODE] +#ifdef _DO_INIT + = DEFAULT_TZCODE_NAMES +#endif +; + + +_ext int pcps_wday_date_dist +#ifdef _DO_INIT + = DEFAULT_PCPS_WDAY_DATE_DIST +#endif +; + + +_ext int pcps_date_time_dist +#ifdef _DO_INIT + = DEFAULT_PCPS_DATE_TIME_DIST +#endif +; + + +_ext int pcps_time_tz_dist +#ifdef _DO_INIT + = DEFAULT_PCPS_TIME_TZ_DIST +#endif +; + + +_ext const char *mode_name[N_STR_MODE][N_LNG] +#ifdef _DO_INIT + = DEFAULT_MODE_NAMES +#endif +; + + +_ext const char *short_mode_name[N_STR_MODE] +#ifdef _DO_INIT + = DEFAULT_SHORT_MODE_NAMES +#endif +; + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + const char *inv_str( void ) ; + int sprint_utc_offs( char *s, const char *info, long utc_offs ) ; + const char *pcps_tz_name( const PCPS_TIME *t, ushort flags, int is_msf ) ; + const char *pcps_tz_name_from_hr_time( const PCPS_HR_TIME *hrt, ushort flags, int is_msf ) ; + const char *pcps_tz_name_hr_status( const PCPS_HR_TIME *t, ushort flags, int is_msf ) ; + const char *pcps_tz_name_from_status( ushort status ) ; + char *pcps_date_time_str( char *s, const PCPS_TIME *t, ushort year_limit, const char *tz_str ) ; + wchar_t *pcps_date_time_wstr( wchar_t *ws, const PCPS_TIME *t, ushort year_limit, const wchar_t *tz_str ) ; + void pcps_status_strs( ushort status, int status_is_read, int is_gps, PCPS_STATUS_STRS *pstrs ) ; + char *pcps_port_str( char *s, const PCPS_DEV *pdev ) ; + const char *pcps_tzcode_str( PCPS_TZCODE tzcode ) ; + char *pcps_serial_str( char *s, int i, const RECEIVER_PORT_CFG *p, const RECEIVER_INFO *p_ri, int short_strs ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _PCPSLSTR_H */ + diff --git a/mbglib/common/pcpsmktm.c b/mbglib/common/pcpsmktm.c new file mode 100644 index 0000000..90404a8 --- /dev/null +++ b/mbglib/common/pcpsmktm.c @@ -0,0 +1,53 @@ + +/************************************************************************** + * + * $Id: pcpsmktm.c 1.4 2006/12/14 15:27:49Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Function to convert PCPS_TIME to Unix time (seconds since 1970) + * + * ----------------------------------------------------------------------- + * $Log: pcpsmktm.c $ + * Revision 1.4 2006/12/14 15:27:49Z martin + * Include time.h. + * Revision 1.3 2006/08/22 09:10:03 martin + * Renamed function totalsec() to mbg_mktime() and moved it + * to a separate file mbgmktm.c. + * Revision 1.2 2001/08/14 11:58:08 MARTIN + * Included sys/time.h for time_t definition. + * Revision 1.1 2001/02/02 15:30:09 MARTIN + * + **************************************************************************/ + +#define _PCPSMKTM + #include <pcpsmktm.h> +#undef _PCPSMKTM + +#include <mbgmktm.h> + +#include <time.h> + + +/*HDR*/ +long pcps_mktime( PCPS_TIME *tp ) +{ + time_t secs; + int year = tp->year; + + if ( year < 70 ) + year += 100; + + secs = mbg_mktime( year, tp->month - 1, tp->mday - 1, + tp->hour, tp->min, tp->sec ); + + if ( secs != -1 ) + secs -= tp->offs_utc * 3600; + + return( secs ); + +} // pcps_mktime + + + diff --git a/mbglib/common/pcpsmktm.h b/mbglib/common/pcpsmktm.h new file mode 100644 index 0000000..086be75 --- /dev/null +++ b/mbglib/common/pcpsmktm.h @@ -0,0 +1,62 @@ + +/************************************************************************** + * + * $Id: pcpsmktm.h 1.1 2001/02/02 15:31:07Z MARTIN REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for pcpsmktm.c. + * + * ----------------------------------------------------------------------- + * $Log: pcpsmktm.h $ + * Revision 1.1 2001/02/02 15:31:07Z MARTIN + * + **************************************************************************/ + +#ifndef _PCPSMKTM_H +#define _PCPSMKTM_H + + +/* Other headers to be included */ + +#include <pcpsdefs.h> + + +#ifdef _PCPSMKTM + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + +//_ext PCPS_TIME tx; + +/* End of header body */ + +#undef _ext + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + long pcps_mktime( PCPS_TIME *tp ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#endif /* _PCPSMKTM_H */ diff --git a/mbglib/common/pcpsutil.c b/mbglib/common/pcpsutil.c new file mode 100644 index 0000000..91109e0 --- /dev/null +++ b/mbglib/common/pcpsutil.c @@ -0,0 +1,162 @@ + +/************************************************************************** + * + * $Id: pcpsutil.c 1.14 2011/06/29 11:03:44Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Utility functions used with programs for Meinberg devices. + * + * ----------------------------------------------------------------------- + * $Log: pcpsutil.c $ + * Revision 1.14 2011/06/29 11:03:44Z martin + * Updated a comment. + * Revision 1.13 2009/03/09 13:39:45 martin + * Made pcps_exp_year() an inline function. + * Revision 1.12 2008/12/10 19:59:48 martin + * Made frac_sec_from_bin() an inline function. + * Revision 1.11 2008/11/25 10:00:25 martin + * Use new definitions of fraction conversion type and scale + * from pcpsdefs.h. + * Revision 1.10 2006/06/29 10:38:24Z martin + * New function pcps_time_is_valid(). + * Modified pcps_str_to_port(), doesn't add a 0 entry to the list anymore. + * Fixed a compiler warning related to type conversion. + * Revision 1.9 2005/01/14 10:14:31Z martin + * Changed type of ISA port addr to int. + * Revision 1.8 2004/11/09 14:29:27Z martin + * Rewrote functions using C99 fixed-size definitions. + * Revision 1.7 2003/04/17 10:08:59Z martin + * Added some type casts to fix compiler warnings. + * Revision 1.6 2001/11/28 14:39:16Z MARTIN + * In frac_sec_from_bin(), define the divisor as floating point + * constant to avoid a domain errors on 16 bit systems. + * Revision 1.5 2001/09/17 07:28:01 MARTIN + * New function frac_sec_from_bin() to convert + * PCPS_HR_TIME fractions. + * Revision 1.4 2001/03/01 14:01:09 MARTIN + * Modified parameters for pcps_setup_isa_ports(). + * Revision 1.3 2000/08/31 14:05:30 MARTIN + * Replaced pcps_str_to_port() by pcps_setup_isa_ports(). + * Revision 1.2 2000/07/21 13:42:54 MARTIN + * Initial revision + * + **************************************************************************/ + +#define _PCPSUTIL + #include <pcpsutil.h> +#undef _PCPSUTIL + +#include <stdlib.h> + + +/*-------------------------------------------------------------- + * Name: pcps_time_is_valid() + * + * Purpose: Pack a structure with serial port parameters + * + * Input/Output: p address of a structure holding both the + * packed and unpacked information + * + * Ret value: -- + *-------------------------------------------------------------*/ + +/*HDR*/ +int pcps_time_is_valid( const PCPS_TIME *p ) +{ + return ( p->sec100 <= 99 ) + && ( p->sec <= 60 ) /* allow for leap second */ + && ( p->min <= 59 ) + && ( p->hour <= 23 ) + && ( p->mday >= 1 ) && ( p->mday <= 31 ) + && ( p->wday >= 1 ) && ( p->wday <= 7 ) + && ( p->month >= 1 ) && ( p->month <= 12 ) + && ( p->year <= 99 ); + +} /* pcps_time_is_valid */ + + + +/*-------------------------------------------------------------- + * Name: pcps_str_to_port() + * + * Purpose: Try to convert a string to a valid port + * address. + * + * Input: s the string + * + * Output: -- + * + * Ret value: a valid port number or 0 + *+-------------------------------------------------------------*/ + +/*HDR*/ +void pcps_setup_isa_ports( char *s, + int *port_vals, + int n_vals ) +{ + ushort i; + + + for ( i = 0; i < n_vals; i++ ) + { + if ( *s == 0 ) + break; + + *port_vals++ = (uint16_t) strtoul( s, &s, 16 ); + + if ( *s == ',' ) + s++; + } + +} // pcps_setup_isa_ports + + + +/*-------------------------------------------------------------- + * Name: pcps_unpack_serial() + * + * Purpose: Unpack a structure with serial port parameters + * + * Input/Output: p address of a structure holding both the + * packed and unpacked information + * + * Ret value: -- + *-------------------------------------------------------------*/ + +/*HDR*/ +void pcps_unpack_serial( PCPS_SER_PACK *p ) +{ + uint8_t pack = p->pack; + + p->baud = (uint8_t) ( pack & BITMASK( PCPS_BD_BITS ) ); + p->frame = (uint8_t) ( ( pack >> PCPS_FR_SHIFT ) & BITMASK( PCPS_FR_BITS ) ); + p->mode = (uint8_t) ( ( pack >> PCPS_MOD_SHIFT ) & BITMASK( PCPS_MOD_BITS ) ); + +} // pcps_unpack_serial + + + +/*-------------------------------------------------------------- + * Name: pcps_pack_serial() + * + * Purpose: Pack a structure with serial port parameters + * + * Input/Output: p address of a structure holding both the + * packed and unpacked information + * + * Ret value: -- + *-------------------------------------------------------------*/ + +/*HDR*/ +void pcps_pack_serial( PCPS_SER_PACK *p ) +{ + p->pack = (uint8_t) ( ( p->baud & BITMASK( PCPS_BD_BITS ) ) + | ( ( p->frame & BITMASK( PCPS_FR_BITS ) ) << PCPS_FR_SHIFT ) + | ( ( p->mode & BITMASK( PCPS_MOD_BITS ) ) << PCPS_MOD_SHIFT ) ); + +} /* pcps_pack_serial */ + + + diff --git a/mbglib/common/pcpsutil.h b/mbglib/common/pcpsutil.h new file mode 100644 index 0000000..41982df --- /dev/null +++ b/mbglib/common/pcpsutil.h @@ -0,0 +1,198 @@ + +/************************************************************************** + * + * $Id: pcpsutil.h 1.15.1.1 2013/01/24 14:42:52Z martin TEST $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for pcpsutil.c. + * + * ----------------------------------------------------------------------- + * $Log: pcpsutil.h $ + * Revision 1.15.1.1 2013/01/24 14:42:52Z martin + * Added dfrac_sec_from_bin(). + * Revision 1.15 2012/10/15 09:41:32 martin + * Cleaned up handling of pragma pack(). + * Revision 1.14 2009/03/09 13:39:45 martin + * Made pcps_exp_year() an inline function. + * Revision 1.13 2008/12/10 19:59:48 martin + * Made frac_sec_from_bin() an inline function. + * Revision 1.12 2008/11/25 09:59:01 martin + * Moved definitions of PCPS_HRT_FRAC_SCALE and + * PCPS_HRT_FRAC_SCALE_FMT to pcpsdefs.h. + * Revision 1.11 2006/06/29 10:15:02Z martin + * Updated function prototypes. + * Revision 1.10 2005/01/14 10:16:12Z martin + * Updated function prototypes. + * Revision 1.9 2004/11/09 14:30:50Z martin + * Redefined interface data types using C99 fixed-size definitions. + * Updated function prototypes. + * Revision 1.8 2004/04/14 09:22:09Z martin + * Pack structures 1 byte aligned. + * Revision 1.7 2001/11/28 14:41:25Z MARTIN + * Changed PCPS_HRT_FRAC_SCALE and PCPS_HRT_FRAC_SCALE_FMT + * to print 7 rather than 6 digits. + * Revision 1.6 2001/09/14 11:59:33 MARTIN + * Support for PCPS_HR_TIME fraction conversion. + * Updated function prototypes. + * Revision 1.5 2001/08/14 12:06:44 MARTIN + * Defined constants used to draw a signal bar + * depending on a DCF77 clock's signal value. + * Revision 1.4 2001/03/01 14:03:18 MARTIN + * Updated function prototypes. + * Revision 1.3 2000/08/31 14:06:05 MARTIN + * Updated function prototypes. + * Revision 1.2 2000/07/21 13:43:40 MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _PCPSUTIL_H +#define _PCPSUTIL_H + + +/* Other headers to be included */ + +#include <pcpsdefs.h> +#include <use_pack.h> + + +#ifdef _PCPSUTIL + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + + +// The following constants are used to draw a signal bar +// depending on a DCF77 clock's signal value: +#define PCPS_SIG_BIAS 55 +#define PCPS_SIG_ERR 1 +#define PCPS_SIG_MIN 20 +#define PCPS_SIG_MAX 68 + + +// the structure below is used with a DCF77 clock's serial interface +typedef struct +{ + PCPS_SERIAL pack; // this byte is passed to the board as parameter + + uint8_t baud; // the other bytes can hold the unpacked values + uint8_t frame; + uint8_t mode; + +} PCPS_SER_PACK; + + + +/*-------------------------------------------------------------- + * Name: pcps_exp_year() + * + * Purpose: Convert a 2-digit year number to a 4-digit + * year number. The resulting year number is in + * the range [year_lim ... ( year_lim + 99 )]. + * + * Input: year the 2-digit year number + * year_lim the smallest 4-digit year number + * to be returned + * + * Output: -- + * + * Ret value: the calculated 4-digit year num + *+-------------------------------------------------------------*/ + +static __mbg_inline +uint16_t pcps_exp_year( uint8_t year, uint16_t year_lim ) +{ + uint16_t lyear = (uint16_t) ( (uint16_t) year + year_lim + - ( year_lim % 100 ) ); + + if ( lyear < year_lim ) + lyear += 100; + + return lyear; + +} // pcps_exp_year + + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + int pcps_time_is_valid( const PCPS_TIME *p ) ; + void pcps_setup_isa_ports( char *s, int *port_vals, int n_vals ) ; + void pcps_unpack_serial( PCPS_SER_PACK *p ) ; + void pcps_pack_serial( PCPS_SER_PACK *p ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/*-------------------------------------------------------------- + * Name: frac_sec_from_bin() + * + * Purpose: Convert a fraction of a second from binary + * format (as returned in a PCPS_HR_TIME structure + * to a decimal fraction, using a specified scale + * factor. See also the definitions of + * PCPS_HRT_FRAC_SCALE and PCPS_HRT_FRAC_SCALE_FMT + * in the header file. + * + * Input: b the binary fraction + * scale the scale factor + * + * Output: -- + * + * Ret value: the calculated number + *+-------------------------------------------------------------*/ + +static __mbg_inline +uint32_t frac_sec_from_bin( uint32_t b, uint32_t scale ) +{ + return (uint32_t) ( (PCPS_HRT_FRAC_CONVERSION_TYPE) b * scale + / PCPS_HRT_BIN_FRAC_SCALE ); + +} // frac_sec_from_bin + + + +static __mbg_inline +double dfrac_sec_from_bin( uint32_t b ) +{ + return (double) b / (double) PCPS_HRT_BIN_FRAC_SCALE; + +} // dfrac_sec_from_bin + + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + +#undef _ext + + +#endif /* _PCPSUTIL_H */ diff --git a/mbglib/common/toolutil.c b/mbglib/common/toolutil.c new file mode 100644 index 0000000..3cdd2bb --- /dev/null +++ b/mbglib/common/toolutil.c @@ -0,0 +1,530 @@ + +/************************************************************************** + * + * $Id: toolutil.c 1.4.1.4 2013/02/05 15:27:30Z martin TEST $ + * + * Description: + * Common functions which can be used with Meinberg command line + * utility programs. + * + * ----------------------------------------------------------------------- + * $Log: toolutil.c $ + * Revision 1.4.1.4 2013/02/05 15:27:30Z martin + * Revision 1.4.1.3 2013/02/05 15:24:46 martin + * Revision 1.4.1.2 2013/02/05 14:39:38 martin + * Revision 1.4.1.1 2013/02/05 14:37:56Z martin + * Started to supported Windows target. + * Revision 1.4 2012/10/15 09:33:48 martin + * Use common way to handle version information. + * Open device with O_RDWR flag. + * Fixed printing delta timestamps. + * Added function to print PCPS_TIME. + * Added function to show PZF correlation. + * Added function mbg_print_hr_time() which optionally prints hex status. + * Let the display functions for HR timestamps optionally show + * the raw (hex) timestamps. + * Revision 1.3 2009/06/19 12:12:14 martin + * Added function mbg_print_hr_timestamp(). + * Revision 1.2 2009/02/18 09:15:55 martin + * Support TAI and GPS time scales in mbg_snprint_hr_time(). + * Revision 1.1 2008/12/17 10:45:13 martin + * Initial revision. + * Revision 1.1 2008/12/15 08:35:07 martin + * Initial revision. + * + **************************************************************************/ + +#define _TOOLUTIL + #include <toolutil.h> +#undef _TOOLUTIL + +// include Meinberg headers +#include <pcpsutil.h> + +// include system headers +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +static __mbg_inline +double delta_timestamps( const PCPS_TIME_STAMP *p_ts, const PCPS_TIME_STAMP *p_prv_ts ) +{ + uint64_t ts = pcps_time_stamp_to_uint64( p_ts ); + uint64_t prv_ts = pcps_time_stamp_to_uint64( p_prv_ts ); + // we divide by PCPS_HRT_BIN_FRAC_SCALE to get the correct fractions + // and we multiply by 1E6 to get the result in microseconds + return (double) ( (int64_t) ( ts - prv_ts ) ) * 1E6 / PCPS_HRT_BIN_FRAC_SCALE; + +} // delta_timestamps + + + +/*HDR*/ +int mbg_program_info_str( char *s, size_t max_len, const char *pname, + int micro_version, int first_year, int last_year ) +{ + int n; + + if ( last_year == 0 ) + last_year = MBG_CURRENT_COPYRIGHT_YEAR; + + n = snprintf( s, max_len, "%s v%i.%i.%i copyright Meinberg ", pname, + MBG_MAJOR_VERSION_CODE, MBG_MINOR_VERSION_CODE, micro_version ); + + if ( first_year != last_year ) + n += snprintf( &s[n], max_len - n, "%04i-", first_year ); + + n += snprintf( &s[n], max_len - n, "%04i", last_year ); + + return n; + +} // mbg_program_info_str + + + +/*HDR*/ +void mbg_print_program_info( const char *pname, int micro_version, int first_year, int last_year ) +{ + char ws[256]; + #if defined( MBG_MICRO_VERSION_CODE_DEV ) + micro_version = MBG_MICRO_VERSION_CODE_DEV; + #endif + mbg_program_info_str( ws, sizeof( ws ), pname, micro_version, first_year, last_year ); + + printf( "\n%s\n\n", ws ); + +} // mbg_print_program_info + + + +/*HDR*/ +void mbg_print_usage_intro( const char *pname, const char *info ) +{ + printf( "Usage: %s [[opt] [opt] ...] [[dev] [dev] ...]\n\n", pname ); + + if ( info ) + printf( "%s\n\n", info ); + + +} // mbg_print_usage_intro + + + +/*HDR*/ +void mbg_print_opt_info( const char *opt_name, const char *opt_info ) +{ + if ( opt_name == NULL ) + opt_name = ""; + + if ( opt_info == NULL ) + opt_info = ""; + + printf( " %8s %s\n", opt_name, opt_info ); + +} // mbg_print_opt_info + + + +/*HDR*/ +void mbg_print_help_options( void ) +{ + puts( "where opt is one of the options:" ); + mbg_print_opt_info( "-? or -h", "print this usage information" ); + +} // mbg_print_help_options + + + +/*HDR*/ +void mbg_print_device_options( void ) +{ + puts( "\nwhere dev is the name of a device, e.g.:\n" + " /dev/mbgclock0" + ); + +} // mbg_print_device_options + + + +/*HDR*/ +void mbg_print_default_usage( const char *pname, const char *prog_info ) +{ + mbg_print_usage_intro( pname, prog_info ); + mbg_print_help_options(); + mbg_print_device_options(); + puts( "" ); + +} // mbg_print_default_usage + + + +// test if ioctl error and print msg if true + +/*HDR*/ +int mbg_ioctl_err( int rc, const char *descr ) +{ + if ( rc < 0 ) + { + fprintf( stderr, "** IOCTL error %i: ", rc ); + perror( descr ); + return -1; + } + + return 0; + +} // mbg_ioctl_err + + + +/*HDR*/ +int mbg_get_show_dev_info( MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_dev ) +{ + unsigned long port; + int irq_num; + int ret_val = 0; + int rc; + + if ( dev_name ) + printf( "%s:\n", dev_name ); + + // get information about the device + rc = mbg_get_device_info( dh, p_dev ); + + if ( mbg_ioctl_err( rc, "mbg_get_device_info" ) ) + goto fail; + + + printf( "%s", _pcps_type_name( p_dev ) ); + + if ( strlen( _pcps_sernum( p_dev ) ) && + strcmp( _pcps_sernum( p_dev ), "N/A" ) ) + printf( " %s", _pcps_sernum( p_dev ) ); + + printf( " (FW %X.%02X", + _pcps_fw_rev_num_major( _pcps_fw_rev_num( p_dev ) ), + _pcps_fw_rev_num_minor( _pcps_fw_rev_num( p_dev ) ) + ); + + if ( _pcps_has_asic_version( p_dev ) ) + { + PCI_ASIC_VERSION av; + int rc = mbg_get_asic_version( dh, &av ); + + if ( rc == MBG_SUCCESS ) + { + av = _convert_asic_version_number( av ); + + printf( ", ASIC %u.%02u", + _pcps_asic_version_major( av ), + _pcps_asic_version_minor( av ) + ); + } + } + + printf( ")" ); + + port = _pcps_port_base( p_dev, 0 ); + + if ( port ) + printf( " at port 0x%03lX", port ); + + port = _pcps_port_base( p_dev, 1 ); + + if ( port ) + printf( "/0x%03lX", port ); + + irq_num = _pcps_irq_num( p_dev ); + + if ( irq_num != -1 ) + printf( ", irq %i", irq_num ); + + goto done; + +fail: + ret_val = -1; + +done: + puts( "" ); + return ret_val; + +} // mbg_get_show_dev_info + + + +/*HDR*/ +int mbg_check_device( MBG_DEV_HANDLE dh, const char *dev_name, + int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) ) +{ + PCPS_DEV dev; + int ret_val = 0; + + if ( dh == MBG_INVALID_DEV_HANDLE ) + { + if ( dev_name ) + fprintf( stderr, "%s: ", dev_name ); + + perror( "Unable to open device" ); + return -1; + } + + if ( mbg_get_show_dev_info( dh, dev_name, &dev ) < 0 ) + goto fail; + + if ( fnc ) + ret_val = fnc( dh, &dev ); + + goto done; + +fail: + ret_val = -1; + +done: + mbg_close_device( &dh ); + puts( "" ); + + return ret_val; + +} // mbg_check_device + + + +/*HDR*/ +int mbg_check_devices( int argc, char *argv[], int optind, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) ) +{ + MBG_DEV_HANDLE dh; + int ret_val = 0; + int num_devices = argc - optind; + + if ( num_devices == 0 ) // no device name given on the command line + { + // No devices specified on the command line, so + // try to find devices. + int devices = mbg_find_devices(); + + if ( devices == 0 ) + { + printf( "No device found.\n" ); + return 1; + } + + // Handle only first device found. + dh = mbg_open_device( 0 ); + ret_val = mbg_check_device( dh, NULL, fnc ); + } + else + { + int i; + // One or more device names have been specified + // on the command line, so handle each device. + for ( i = optind; i < argc; i++ ) + { + // Print device name only if output for several devices + // shall be displayed. + const char *fn = ( num_devices > 1 ) ? argv[i] : NULL; + + #if defined( MBG_TGT_WIN32 ) + mbg_find_devices(); + dh = mbg_open_device_by_name( argv[i], MBG_MATCH_MODEL ); + #else + dh = open( argv[i], O_RDWR ); + #endif + ret_val = mbg_check_device( dh, fn, fnc ); + + if ( ret_val ) + break; + } + } + + return ret_val; + +} // mbg_check_devices + + + +/*HDR*/ +int mbg_snprint_date_time( char *s, int len_s, const PCPS_TIME *p, int verbose ) +{ + int n = 0; + + n += snprintf( s + n, len_s - n, "%04u-%02u-%02u %02u:%02u:%02u.%02u", + pcps_exp_year( p->year, mbg_exp_year_limit ), p->month, p->mday, + p->hour, p->min, p->sec, p->sec100 + ); + + if ( verbose ) + n += snprintf( s + n, len_s - n, " (UTC%+ih), st: %02Xh", + p->offs_utc, p->status ); + + return n; + +} // mbg_snprint_date_time + + + +/*HDR*/ +int mbg_snprint_hr_tstamp( char *s, int len_s, const PCPS_TIME_STAMP *p, int show_raw ) +{ + int n = 0; + + // We'll use the standard C library functions to convert the seconds + // to broken-down calendar date and time. + time_t t = p->sec; + + // Our time stamp may be UTC, or have been converted to local time. + // Anyway, since we don't want to account for the system's time zone + // settings, we always use the gmtime() function for conversion: + struct tm *tmp = gmtime( &t ); + + if ( show_raw ) + n += snprintf( s + n, len_s - n, "raw: 0x%08lX.%08lX, ", + (ulong) p->sec, + (ulong) p->frac ); + + n += snprintf( s + n, len_s - n, "%04i-%02i-%02i %02i:%02i:%02i." PCPS_HRT_FRAC_SCALE_FMT, + tmp->tm_year + 1900, + tmp->tm_mon + 1, + tmp->tm_mday, + tmp->tm_hour, + tmp->tm_min, + tmp->tm_sec, + (ulong) frac_sec_from_bin( p->frac, PCPS_HRT_FRAC_SCALE ) + ); + + return n; + +} // mbg_snprint_hr_tstamp + + + +/*HDR*/ +int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p, int show_raw ) +{ + char ws[80]; + PCPS_TIME_STAMP ts = p->tstamp; + int n; + const char *time_scale_name; + const char *cp; + + // If the local time offset is not 0 then add this to the time stamp + // and set up a string telling the offset. + if ( p->utc_offs ) + { + ldiv_t ldt; + + ts.sec += p->utc_offs; + + // The local time offset is in seconds and may be negative, so we + // convert to absolute hours and minutes first. + ldt = ldiv( labs( p->utc_offs ) / 60, 60 ); + + snprintf( ws, sizeof( ws ), "%c%lu:%02luh", + ( p->utc_offs < 0 ) ? '-' : '+', + ldt.quot, + ldt.rem + ); + cp = ws; + } + else + cp = ""; // no local time offset + + + // Convert the local time stamp to calendar date and time. + n = mbg_snprint_hr_tstamp( s, len_s, &ts, show_raw ); + + // By default the time stamp represents UTC plus an optional local time offset. + time_scale_name = "UTC"; + + // However, some cards may be configured to output TAI or GPS time. + if ( p->status & PCPS_SCALE_TAI ) + time_scale_name = "TAI"; // time stamp represents TAI + else + if ( p->status & PCPS_SCALE_GPS ) + time_scale_name = "GPS"; // time stamp represents GPS system time + + n += snprintf( s + n, len_s - n, " %s%s", time_scale_name, cp ); + + return n; + +} // mbg_snprint_hr_time + + + +/*HDR*/ +void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, + int no_latency, int show_raw ) +{ + char ws[80]; + + mbg_snprint_hr_tstamp( ws, sizeof( ws ), p_ts, show_raw ); + printf( "HR time %s", ws ); + + if ( p_prv_ts ) + printf( " (%+.1f us)", delta_timestamps( p_ts, p_prv_ts ) ); + + if ( !no_latency ) + printf( ", latency: %.1f us", ( (double) hns_latency ) / 10 ); + + puts( "" ); + +} // mbg_print_hr_timestamp + + + +/*HDR*/ +void mbg_print_hr_time( PCPS_HR_TIME *p_ht, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, + int no_latency, int show_raw, int verbose ) +{ + char ws[80]; + + mbg_snprint_hr_time( ws, sizeof( ws ), p_ht, show_raw ); + printf( "HR time %s", ws ); + + if ( p_prv_ts ) + printf( " (%+.1f us)", delta_timestamps( &p_ht->tstamp, p_prv_ts ) ); + + if ( !no_latency ) + printf( ", latency: %.1f us", ( (double) hns_latency ) / 10 ); + + if ( verbose ) + printf( ", st: 0x%04lX", (ulong) p_ht->status ); + + puts( "" ); + +} // mbg_print_hr_time + + + +/*HDR*/ +int mbg_show_pzf_corr_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, int show_corr_step ) +{ + CORR_INFO ci; + char ws[80]; + const char *cp; + + int rc = mbg_get_corr_info( dh, &ci ); + + if ( mbg_ioctl_err( rc, "mbg_get_corr_info" ) ) + return rc; + + + if ( ci.status < N_PZF_CORR_STATE ) + cp = pzf_corr_state_name[ci.status]; + else + { + snprintf( ws, sizeof( ws ) - 1, "(unknown, code: 0x%02X)", ci.status ); + ws[sizeof( ws ) - 1] = 0; // force terminating 0 + cp = ws; + } + + printf( "PZF correlation: %u%%, status: %s", ci.val, cp ); + + if ( show_corr_step ) + if ( ci.corr_dir != ' ' ) + printf( " Shift: %c", ci.corr_dir ); + + return MBG_SUCCESS; + +} // mbg_show_pzf_corr_info + + diff --git a/mbglib/common/toolutil.h b/mbglib/common/toolutil.h new file mode 100644 index 0000000..2f02c73 --- /dev/null +++ b/mbglib/common/toolutil.h @@ -0,0 +1,128 @@ + +/************************************************************************** + * + * $Id: toolutil.h 1.3.1.1 2013/02/05 14:38:26Z martin TEST martin $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for toolutil.c. + * + * ----------------------------------------------------------------------- + * $Log: toolutil.h $ + * Revision 1.3.1.1 2013/02/05 14:38:26Z martin + * Started to support Windows target. + * Revision 1.3 2012/10/15 09:36:22 martin + * Use common way to handle version information. + * Added string table with PZF state names. + * Updated function prototypes. + * Revision 1.2 2009/06/19 12:11:35 martin + * Updated function prototypes. + * Revision 1.1 2008/12/17 10:45:14 martin + * Initial revision. + * Revision 1.1 2008/12/15 08:35:08 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _TOOLUTIL_H +#define _TOOLUTIL_H + + +/* Other headers to be included */ + +#include <mbgdevio.h> +#include <mbgversion.h> + +#if defined( MBG_TGT_UNIX) + + #include <unistd.h> + +#elif defined( MBG_TGT_WIN32 ) + + #include <io.h> + #include <fcntl.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <wingetopt.h> + + #define open _open + #define snprintf _snprintf + #define sleep( _x ) Sleep( (_x) * 1000 ) + #define usleep( _x ) Sleep( (_x) / 1000 ) + +#endif + + + +#ifdef _TOOLUTIL + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined( MBG_EXP_YEAR_LIMIT ) + #define MBG_EXP_YEAR_LIMIT 1980 +#endif + +_ext uint16_t mbg_exp_year_limit +#ifdef _DO_INIT + = MBG_EXP_YEAR_LIMIT +#endif +; + +_ext int must_print_usage; + +_ext const char *pzf_corr_state_name[N_PZF_CORR_STATE] +#ifdef _DO_INIT + = PZF_CORR_STATE_NAMES_ENG +#endif +; + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + int mbg_program_info_str( char *s, size_t max_len, const char *pname, int micro_version, int first_year, int last_year ) ; + void mbg_print_program_info( const char *pname, int micro_version, int first_year, int last_year ) ; + void mbg_print_usage_intro( const char *pname, const char *info ) ; + void mbg_print_opt_info( const char *opt_name, const char *opt_info ) ; + void mbg_print_help_options( void ) ; + void mbg_print_device_options( void ) ; + void mbg_print_default_usage( const char *pname, const char *prog_info ) ; + int mbg_ioctl_err( int rc, const char *descr ) ; + int mbg_get_show_dev_info( MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_dev ) ; + int mbg_check_device( MBG_DEV_HANDLE dh, const char *dev_name, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) ) ; + int mbg_check_devices( int argc, char *argv[], int optind, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) ) ; + int mbg_snprint_date_time( char *s, int len_s, const PCPS_TIME *p, int verbose ) ; + int mbg_snprint_hr_tstamp( char *s, int len_s, const PCPS_TIME_STAMP *p, int show_raw ) ; + int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p, int show_raw ) ; + void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int no_latency, int show_raw ) ; + void mbg_print_hr_time( PCPS_HR_TIME *p_ht, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int no_latency, int show_raw, int verbose ) ; + int mbg_show_pzf_corr_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, int show_corr_step ) ; + +/* ----- function prototypes end ----- */ + + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _TOOLUTIL_H */ + diff --git a/mbglib/common/usbdefs.h b/mbglib/common/usbdefs.h new file mode 100644 index 0000000..40d1193 --- /dev/null +++ b/mbglib/common/usbdefs.h @@ -0,0 +1,151 @@ + +/************************************************************************** + * + * $Id: usbdefs.h 1.18 2013/01/24 11:29:21Z joerg REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions used with USB devices. + * + * ----------------------------------------------------------------------- + * $Log: usbdefs.h $ + * Revision 1.18 2013/01/24 11:29:21Z joerg + * Added class code and device ID for LNE-GB + * Revision 1.17 2012/08/08 07:53:29Z daniel + * Added class code and device ID for LIU + * Revision 1.16 2012/02/13 09:29:59 paul + * added class code for LNO180 + * Revision 1.15 2011/10/11 06:21:04Z andre + * added class code for GPS180 + * Revision 1.14 2011/10/07 10:13:25Z daniel + * New class code and device id for CPE + * Revision 1.13 2011/06/29 14:11:23Z martin + * Added device IDs for TCR600USB, MSF600USB, and WVB600USB. + * Revision 1.12 2011/05/11 07:20:37 daniel + * New class code and device id for fan control unit + * Revision 1.11 2011/04/13 07:59:11 daniel + * New class code and device id for external + * synchronization interface device. + * Revision 1.10 2010/11/11 09:16:33Z martin + * Added device ID for DCF600USB. + * Revision 1.9 2009/03/13 09:02:24 martin + * Removed definitions for timeout intervals. + * Revision 1.8 2009/02/18 11:08:44 daniel + * Added new class code and device ID for SCU_USB + * Revision 1.7 2008/11/28 07:45:30Z daniel + * Added new class code and device ID for WWVB51USB + * Revision 1.6 2008/01/09 10:39:18Z daniel + * Added new class code and device ID for MSF51USB + * Revision 1.5 2007/10/29 08:23:26Z daniel + * Added new class code and device ID for TCR51USB + * Revision 1.4 2007/09/25 09:59:50Z daniel + * Added indices for endpoint definitions. + * Added timeout definitions. + * Revision 1.3 2006/12/20 16:11:36Z daniel + * Added new device class and device_id for nCipher CMC-device. + * Revision 1.2 2006/12/07 09:10:57Z daniel + * Added new class code and device ID for USB5131. + * Revision 1.1 2006/04/21 08:14:56Z martin + * Initial revision + * + **************************************************************************/ + +#ifndef _USBDEFS_H +#define _USBDEFS_H + + +/* Other headers to be included */ + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Meinberg's USB vendor ID number (assigned by USB-IF Administration) */ +#define USB_VENDOR_MEINBERG 0x1938 + + +/* + * USB device class codes (assigned by Meinberg) + */ +enum +{ + MBG_USB_CLASS_NONE, // (unknown or not defined) + MBG_USB_CLASS_CPC, // Control Panel Controller + MBG_USB_CLASS_TSU, // Time Stamp Unit + MBG_USB_CLASS_DCF, // DCF77 Radio Clock + MBG_USB_CLASS_CMC, // nCipher Crypto Module Carrier + MBG_USB_CLASS_TCR, // IRIG Time Code Receiver + MBG_USB_CLASS_MSF, // MSF Radio Clock + MBG_USB_CLASS_WWVB, // WWVB Radio Clock + MBG_USB_CLASS_SCU, // Meinberg Signal Changeover Unit + MBG_USB_CLASS_ESI, // External Synchronization Interface + MBG_USB_CLASS_FCU, // Fan Control Unit + MBG_USB_CLASS_CPE, // Configurable Port Expander + MBG_USB_CLASS_GPS, // GPS Receiver + MBG_USB_CLASS_LNO, // Low Phase Noise Option + MBG_USB_CLASS_LIU, // Line Interface Unit + MBG_USB_CLASS_LNE, // LNE-GB + N_MBG_USB_CLASS // number of known device class codes +}; + + +/* + * USB device ID numbers (assigned by Meinberg) + * High byte: USB device class as specified above + * Low byte: enumeration of device of a class + */ +#define USB_DEV_CPC_01 ( ( MBG_USB_CLASS_CPC << 8 ) | 0x01 ) + +#define USB_DEV_TSU_01 ( ( MBG_USB_CLASS_TSU << 8 ) | 0x01 ) + +#define USB_DEV_USB5131 ( ( MBG_USB_CLASS_DCF << 8 ) | 0x01 ) +#define USB_DEV_DCF600USB ( ( MBG_USB_CLASS_DCF << 8 ) | 0x02 ) + +#define USB_DEV_CMC ( ( MBG_USB_CLASS_CMC << 8 ) | 0x01 ) + +#define USB_DEV_TCR51USB ( ( MBG_USB_CLASS_TCR << 8 ) | 0x01 ) +#define USB_DEV_TCR600USB ( ( MBG_USB_CLASS_TCR << 8 ) | 0x02 ) + +#define USB_DEV_MSF51USB ( ( MBG_USB_CLASS_MSF << 8 ) | 0x01 ) +#define USB_DEV_MSF600USB ( ( MBG_USB_CLASS_MSF << 8 ) | 0x02 ) + +#define USB_DEV_WWVB51USB ( ( MBG_USB_CLASS_WWVB << 8 ) | 0x01 ) +#define USB_DEV_WVB600USB ( ( MBG_USB_CLASS_WWVB << 8 ) | 0x02 ) + +#define USB_DEV_SCU_USB ( ( MBG_USB_CLASS_SCU << 8 ) | 0x01 ) + +#define USB_DEV_ESI_01 ( ( MBG_USB_CLASS_ESI << 8 ) | 0x01 ) + +#define USB_DEV_FCU_01 ( ( MBG_USB_CLASS_FCU << 8 ) | 0x01 ) + +#define USB_DEV_CPE_01 ( ( MBG_USB_CLASS_CPE << 8 ) | 0x01 ) + +#define USB_DEV_GPS180 ( ( MBG_USB_CLASS_GPS << 8 ) | 0x01 ) + +#define USB_DEV_LNO180_01 ( ( MBG_USB_CLASS_LNO << 8 ) | 0x01 ) + +#define USB_DEV_LIU_01 ( ( MBG_USB_CLASS_LIU << 8 ) | 0x01 ) + +#define USB_DEV_LNE_01 ( ( MBG_USB_CLASS_LNE << 8 ) | 0x01 ) + +enum +{ + MBGUSB_EP_IDX_HOST_IN, // transfers from device to host + MBGUSB_EP_IDX_HOST_OUT, // transfers from host to device + MBGUSB_EP_IDX_HOST_IN_CYCLIC, // cyclic auto-transfer to host + MBGUSB_MAX_ENDPOINTS // max number of supported endpoints +}; + + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#endif /* _USBDEFS_H */ diff --git a/mbglib/common/use_pack.h b/mbglib/common/use_pack.h new file mode 100644 index 0000000..cef3d97 --- /dev/null +++ b/mbglib/common/use_pack.h @@ -0,0 +1,43 @@ + +/************************************************************************** + * + * $Id: use_pack.h 1.5 2012/10/12 12:40:01Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Check the current compiler type to decide if pragma pack() is + * required to pack cross-platform data structures. + * + * ----------------------------------------------------------------------- + * $Log: use_pack.h $ + * Revision 1.5 2012/10/12 12:40:01Z martin + * Removed temporary changes. + * Revision 1.4 2012/10/02 18:06:25 martin + * Temporary changes to test alignment under Linux/Sparc. + * Revision 1.3 2011/01/26 10:01:41 martin + * Provided a way to suppress packing of structures on a project base. + * Revision 1.2 2002/02/25 08:50:33 Andre + * query __ARM added, __SH2 removed + * Revision 1.1 2001/03/30 08:54:33Z MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _USE_PACK_H +#define _USE_PACK_H + +#if ( !defined( _C166 ) && \ + !defined( _CC51 ) && \ + !defined( __ARM ) ) + + // _NO_USE_PACK can be defined for specific projects + // to avoid packing of structures. + #if ( !defined( _NO_USE_PACK ) ) + #define _USE_PACK + #endif + +#endif + +#endif /* _USE_PACK_H */ + diff --git a/mbglib/common/words.h b/mbglib/common/words.h new file mode 100644 index 0000000..b840491 --- /dev/null +++ b/mbglib/common/words.h @@ -0,0 +1,360 @@ + +/************************************************************************** + * + * $Id: words.h 1.31 2012/11/29 11:54:39Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions of commonly used data types. + * + * ----------------------------------------------------------------------- + * $Log: words.h $ + * Revision 1.31 2012/11/29 11:54:39Z martin + * Removed #if sizeof() definitions which may cause build errors + * with some older compilers. + * Include stdbool.h for __ARMCC_VERSION targets. + * Moved _nop_macro_fnc() definition here. + * Revision 1.30 2012/11/02 09:12:29Z martin + * Moved most feature detection code to mbg_tgt.h. + * Tried to define missing features most flexibly and portably. + * Revision 1.29 2012/07/11 16:45:45Z martin + * New macros to access individual bytes of long constants. + * Revision 1.28 2012/04/05 14:36:18Z martin + * Support CVI 2010 compiler which provides C99 types. + * Revision 1.27 2011/07/18 10:21:38Z martin + * Added definition for MBG_CODE_NAME_TABLE_ENTRY which can + * be used to define tables assigning strings to numeric codes. + * Revision 1.26 2011/04/06 10:23:03 martin + * Added FBYTE_OF() and FWORD_OF() macros. + * Modifications required for *BSD. + * Revision 1.25 2010/11/17 10:23:09 martin + * Define _BIT_REDEFINED if bit type is redefined. + * Revision 1.24 2010/11/17 08:44:56Z martin + * If supported, use type "bool" to implement "bit". + * Revision 1.23 2010/05/27 08:54:30Z martin + * Support fixed size data types with Keil RealView compiler for ARM. + * Keil RealView ARM targets are always considered as firmware. + * Revision 1.22 2009/10/21 07:53:55 martin + * Undid changes introduced in 1.21 since they were not consistent + * across glibc and/or Linux kernel header versions. + * Revision 1.21 2009/10/01 14:00:17 martin + * Conditionally define ulong and friends also for Linux/glibc. + * Revision 1.20 2009/07/02 15:38:12 martin + * Added new macro _wswap32(). + * 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 + * Redefined C99 integer types with fixed sizes as standard types + * if required, depending on the environment. + * Revision 1.9 2003/02/07 11:36:54 MARTIN + * New macros _hilo_16() and _hilo_32() for endian conversion. + * Revision 1.8 2002/05/28 10:09:54 MARTIN + * Added new macros _var_bswap16() and _var_bswap32(). + * Revision 1.7 2001/03/14 11:30:48 MARTIN + * Removed definitions for UINT8, UINT16, UINT32. + * Redefined preprocessor control for Win32. + * Revision 1.6 2001/02/28 15:43:20 MARTIN + * Modified preprocessor syntax. + * Revision 1.5 2001/02/05 10:20:53 MARTIN + * Include different Linux types for user space and kernel space programs. + * Source code cleanup. + * Revision 1.4 2000/09/15 08:34:11 MARTIN + * Exclude some definitions if compiling under Win NT. + * Revision 1.3 2000/08/22 15:04:28 MARTIN + * Added new file header. + * Added macros to revert endianess of 16 and 32 bit values. + * + **************************************************************************/ + +#ifndef _WORDS_H +#define _WORDS_H + + +/* Other headers to be included */ + + +#if !defined( _IS_MBG_FIRMWARE ) + + #if defined( _C166 ) || \ + defined( _CC51 ) || \ + defined( __ARM ) || \ + defined( __ARMCC_VERSION ) + #define _IS_MBG_FIRMWARE 1 + #else + #define _IS_MBG_FIRMWARE 0 + #endif + +#endif + + +#if !_IS_MBG_FIRMWARE + #include <mbg_tgt.h> +#else + #if defined( __ARMCC_VERSION ) // Keil RealView Compiler for ARM + #include <stdint.h> + #include <stdbool.h> + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #else + #define MBG_TGT_MISSING_64_BIT_TYPES 1 + #endif +#endif + + + +#ifdef _WORDS + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _C166 ) \ + || defined( _CC51 ) + #define _BIT_DEFINED 1 // these compilers natively support the "bit" type + #define USE_LONG_FOR_INT32 1 +#endif + + + +#if !defined( MBG_TGT_HAS_EXACT_SIZE_TYPES ) + + #if defined( MBG_TGT_HAS_INT_8_16_32 ) + + // Define C99 exact size types using non-standard exact-size types + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; + + typedef __int16 int16_t; + typedef unsigned __int16 uint16_t; + + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; + + #else + + // Assume a 16 or 32 bit compiler which doesn't + // support exact-size types. + + typedef char int8_t; + typedef unsigned char uint8_t; + + typedef short int16_t; + typedef unsigned short uint16_t; + + // Using #if sizeof() to determine the size of a type may not + // be supported by all preprocessors, and may even result in + // build errors if used in a conditional preprocessor section, + // so we can't use this here without compatibility problems. + + #if defined( USE_LONG_FOR_INT32 ) + typedef long int32_t; + typedef unsigned long uint32_t; + #elif defined( USE_INT_FOR_INT32 ) + typedef int int32_t; + typedef unsigned int uint32_t; + #else + #error Need to define int32_t and uint32_t + #endif + + #endif + + #if defined( MBG_TGT_MISSING_64_BIT_TYPES ) + + // The build environment does not support 64 bit types. However, + // 64 bit types need to be defined to avoid build errors + // if these types are formally used in function prototypes. + // We explicitely use abnormal data types to hopefully + // cause compiler errors in case these types are + // 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; + + #else + + // Define C99 types using non-standard exact-size types + // which are usually supported by build envonronments + // supporting 64 bit types but no C99 types. + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + + #endif + +#endif + + + +#if defined( MBG_TGT_MISSING_64_BIT_TYPES ) + + #define MBG_TGT_HAS_64BIT_TYPES 0 + +#else + + #define MBG_TGT_HAS_64BIT_TYPES 1 + +#endif + + + +// Some commonly used types + +typedef unsigned char uchar; + +#if !defined( MBG_TGT_LINUX ) \ + && !( defined ( MBG_TGT_NETBSD ) \ + && defined ( MBG_TGT_KERNEL ) ) + typedef unsigned short ushort; + typedef unsigned int uint; + typedef unsigned long ulong; +#endif + +typedef double udouble; + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long longword; +typedef unsigned long dword; + + +#if !defined( _BIT_DEFINED ) + + // We need to implement a "bit" type. Preferably we use "bool" + // to do this, but this is only supported by C++ compilers, and + // by C compilers supporting the C99 standard. + + #if !defined( MBG_TGT_MISSING_BOOL_TYPE ) && \ + ( defined( __cplusplus ) || defined( __bool_true_false_are_defined ) ) + + typedef bool bit; + + #else // C99 types not supported + + // Falling back to use "int" for "bit". This prevents error + // messages if "bit" is used in function prototypes, but may + // yield unexpected results for code like: + // return (bit) ( val & 0x10 ); + typedef int bit; + + #endif + + #define _BIT_REDEFINED 1 + +#endif + + +#define BYTE_0( _x ) ( ( (ulong) (_x) ) & 0xFF ) +#define BYTE_1( _x ) ( ( ( (ulong) (_x) ) >> 8 ) & 0xFF ) +#define BYTE_2( _x ) ( ( ( (ulong) (_x) ) >> 16 ) & 0xFF ) +#define BYTE_3( _x ) ( ( ( (ulong) (_x) ) >> 24 ) & 0xFF ) + + +#define HI_BYTE( _x ) ( (_x) >> 8 ) +#define LO_BYTE( _x ) ( (_x) & 0xFF ) + +#define HI_WORD( _x ) ( (_x) >> 16 ) +#define LO_WORD( _x ) ( (_x) & 0xFFFF ) + +// 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) ) + +#define FBYTE_OF( _v, _n ) *( ( (uint8_t far *) &(_v) ) + (_n) ) +#define FWORD_OF( _v, _n ) *( ( (uint16_t far *) &(_v) ) + (_n) ) + +// same as above, but taking pointers +#define BYTE_OF_P( _p, _n ) *( ( (uint8_t *) (_p) ) + (_n) ) +#define WORD_OF_P( _p, _n ) *( ( (uint16_t *) (_p) ) + (_n) ) + + +// a macro to swap the byte order of a 16 bit value +#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 ) \ +( \ + ( ( ( (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 ) +#define _var_bswap32( _v ) (_v) = _bswap32( _v ) + + +// The C51 compiler is big-endian, that means the most +// significant byte of a 16 or 32 bit value is stored in +// the lowest memory location. Most other systems are +// little-endian, so we must use macros to adjust the +// byte order if the C51 is used. + +#if defined( _CC51 ) + #define _hilo_16( _x ) _bswap16( _x ) + #define _hilo_32( _x ) _bswap32( _x ) +#else + #define _hilo_16( _x ) (_x) + #define _hilo_32( _x ) (_x) +#endif + + +// A macro function which can safely be used without +// side effects as a macro doing nothing. +// This is useful to define debug macros away in +// release builds, etc. +#if !defined( _nop_macro_fnc ) + #define _nop_macro_fnc() do {} while (0) +#endif + + +/** + * @brief A table entry which can be used to map codes to names. + */ +typedef struct +{ + ulong code; + const char *name; +} MBG_CODE_NAME_TABLE_ENTRY; + + + +/* End of header body */ + +#undef _ext + +#endif /* _WORDS_H */ diff --git a/mbglib/lib/bc/mbgdevio.lib b/mbglib/lib/bc/mbgdevio.lib Binary files differnew file mode 100644 index 0000000..e45f718 --- /dev/null +++ b/mbglib/lib/bc/mbgdevio.lib diff --git a/mbglib/lib/bc/mbgsvcio.lib b/mbglib/lib/bc/mbgsvcio.lib Binary files differnew file mode 100644 index 0000000..86b966f --- /dev/null +++ b/mbglib/lib/bc/mbgsvcio.lib diff --git a/mbglib/lib/bc/mbgsvctl.lib b/mbglib/lib/bc/mbgsvctl.lib Binary files differnew file mode 100644 index 0000000..b4a0210 --- /dev/null +++ b/mbglib/lib/bc/mbgsvctl.lib diff --git a/mbglib/lib/bc/mbgutil.lib b/mbglib/lib/bc/mbgutil.lib Binary files differnew file mode 100644 index 0000000..d24e46b --- /dev/null +++ b/mbglib/lib/bc/mbgutil.lib diff --git a/mbglib/lib/msc/mbgdevio.lib b/mbglib/lib/msc/mbgdevio.lib Binary files differnew file mode 100644 index 0000000..d273251 --- /dev/null +++ b/mbglib/lib/msc/mbgdevio.lib diff --git a/mbglib/lib/msc/mbgsvcio.lib b/mbglib/lib/msc/mbgsvcio.lib Binary files differnew file mode 100644 index 0000000..c4987be --- /dev/null +++ b/mbglib/lib/msc/mbgsvcio.lib diff --git a/mbglib/lib/msc/mbgsvctl.lib b/mbglib/lib/msc/mbgsvctl.lib Binary files differnew file mode 100644 index 0000000..0a2f61d --- /dev/null +++ b/mbglib/lib/msc/mbgsvctl.lib diff --git a/mbglib/lib/msc/mbgutil.lib b/mbglib/lib/msc/mbgutil.lib Binary files differnew file mode 100644 index 0000000..fe570bc --- /dev/null +++ b/mbglib/lib/msc/mbgutil.lib diff --git a/mbglib/lib64/msc/mbgdevio.lib b/mbglib/lib64/msc/mbgdevio.lib Binary files differnew file mode 100644 index 0000000..8e443b7 --- /dev/null +++ b/mbglib/lib64/msc/mbgdevio.lib diff --git a/mbglib/lib64/msc/mbgsvcio.lib b/mbglib/lib64/msc/mbgsvcio.lib Binary files differnew file mode 100644 index 0000000..e9c4cd6 --- /dev/null +++ b/mbglib/lib64/msc/mbgsvcio.lib diff --git a/mbglib/lib64/msc/mbgsvctl.lib b/mbglib/lib64/msc/mbgsvctl.lib Binary files differnew file mode 100644 index 0000000..538e203 --- /dev/null +++ b/mbglib/lib64/msc/mbgsvctl.lib diff --git a/mbglib/lib64/msc/mbgutil.lib b/mbglib/lib64/msc/mbgutil.lib Binary files differnew file mode 100644 index 0000000..82ea1e1 --- /dev/null +++ b/mbglib/lib64/msc/mbgutil.lib diff --git a/mbglib/win32/mbg_w32.h b/mbglib/win32/mbg_w32.h new file mode 100644 index 0000000..ebdc119 --- /dev/null +++ b/mbglib/win32/mbg_w32.h @@ -0,0 +1,309 @@ + +/************************************************************************** + * + * $Id: mbg_w32.h 1.7 2012/05/30 13:28:43Z martin TEST $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * OS dependend definitions/redefinitions for Win32. + * + * ----------------------------------------------------------------------- + * $Log: mbg_w32.h $ + * Revision 1.7 2012/05/30 13:28:43Z martin + * Cleanup. + * Revision 1.6 2012/05/29 14:39:53Z martin + * Runtime support for precise time API introduced with Windows 8. + * Revision 1.5 2009/03/26 08:32:26Z martin + * Added orgDeviceExtension field for non-PNP driver. + * Revision 1.4 2009/01/13 14:45:17Z martin + * Added PCPS_DDEV::RegistryPath field for non-PnP driver. + * Use PCPS_DDEV::irp and PCPS_DDEV::win32DeviceName also for non-PnP driver. + * Added PCPS_DDEV::DriverObject field. + * Conditionally added PCPS_DDEV fields required to support programmable IRQs. + * Revision 1.3 2007/09/27 10:36:25Z martin + * Added macro specifying Windows specific device data. + * Added USB support. + * Renamed Removed to SurpriseRemoved. + * Revision 1.2 2002/01/24 09:48:05Z Udo + * check in as lib module + * Revision 1.1 2001/09/13 07:12:14Z Udo + * Initial revision + * + **************************************************************************/ + +#ifndef _MBG_W32_H +#define _MBG_W32_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> +#include <words.h> + +#if defined( MBG_TGT_WIN32_PNP ) && defined( MBG_TGT_KERNEL ) + #include <usb100.h> + #include <usbdi.h> + #include <usbdlib.h> +#endif + + +#ifdef _MBG_W32 + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if USE_PGMB_IRQ + + typedef struct + { + struct _KINTERRUPT *Object; + KEVENT *Event; + KSPIN_LOCK Spinlock; + KDPC *Dpc; + } MBG_IRQ_INFO; + + #define _pgmb_irq_vars \ + MBG_IRQ_INFO Irq; + +#else + + #define _pgmb_irq_vars + +#endif + + + +/** + * @brief A pointer to a function returning the system time as LARGE_INTEGER. + * + * This is for kernel mode only. The function can be e.g. the standard Windows + * API call KeQuerySystemTime() or the KeQuerySystemTimePrecise() API + * call introduced with Windows 8. + */ +typedef VOID (*KE_QUERY_SYSTEM_TIME_FNC)(PLARGE_INTEGER CurrentTime); + + + +#if defined( MBG_TGT_KERNEL ) + +#if !defined( NTKERNELAPI ) + #define NTKERNELAPI +#endif + +#if !defined( __in ) + #define __in +#endif + +#if !defined( _Out_ ) + #define _Out_ +#endif + + +#if 0 //##++ + #define _x_evt_msg _evt_msg +#else + #define _x_evt_msg _dbg_evt_msg +#endif + + + +// definitions for clock() support in kernel drivers + +#define clock_t ulong + +#define clock w32_clock + +// KeQueryTimeIncrement() returns number of 100nsec increments per tick. +// There are 10000000 100nsec increments per second. +#define MBG_TICKS_PER_SEC ( 10000000 / KeQueryTimeIncrement() ) + + +/** + * @brief Get precise Windows system time as FILETIME. + * + * @note This function has been introduced with Windows 8, + * so it is not available on older Windows versions. Thus + * the API call is imported from ntoskrnl.exe at runtime. + * + * @param CurrentTime pointer to a LARGE_INTEGER to be filled + * + * @see KE_QUERY_SYSTEM_TIME_FNC + * @see import_kernel_precise_time_api() + */ +NTKERNELAPI +VOID +KeQuerySystemTimePrecise( _Out_ PLARGE_INTEGER CurrentTime); + + + +#if defined( MBG_TGT_WIN32_PNP ) + + #if !defined ( SE_CREATE_SYMBOLIC_LINK_PRIVILEGE ) + + // Define some KDD function types which may not be + // defined in older DDK headers. + + typedef + NTSTATUS + IO_COMPLETION_ROUTINE ( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context + ); + + typedef IO_COMPLETION_ROUTINE *PIO_COMPLETION_ROUTINE; + + + typedef + NTSTATUS + DRIVER_DISPATCH ( + __in struct _DEVICE_OBJECT *DeviceObject, + __in struct _IRP *Irp + ); + + typedef DRIVER_DISPATCH *PDRIVER_DISPATCH; + + + typedef + VOID + DRIVER_UNLOAD ( + __in struct _DRIVER_OBJECT *DriverObject + ); + + typedef DRIVER_UNLOAD *PDRIVER_UNLOAD; + + + typedef + NTSTATUS + DRIVER_ADD_DEVICE ( + __in struct _DRIVER_OBJECT *DriverObject, + __in struct _DEVICE_OBJECT *PhysicalDeviceObject + ); + + typedef DRIVER_ADD_DEVICE *PDRIVER_ADD_DEVICE; + + #endif // !defined ( SE_CREATE_SYMBOLIC_LINK_PRIVILEGE ) + + + + #define MBG_USB_MAX_NUMBER_OF_ENDPOINTS 32 + #define MBG_USB_MAX_NUMBER_OF_INTERFACES 1 + #define MBG_USB_DEFAULT_TIMEOUT 5000 + #define MBG_USB_MAX_CONTROL_TRANSFER_TIMEOUT 5000 + + + #pragma pack( 4 ) //##++++++ this should be obsolete + + typedef struct + { + long usage_count; + int remove_pending; + KEVENT event; + } USB_REMOVE_LOCK; + + + typedef struct + { + int address; + USBD_PIPE_HANDLE handle; + } USB_ENDPOINT; + + + typedef struct + { + int valid; + int claimed; + USB_ENDPOINT endpoints[MBG_USB_MAX_NUMBER_OF_ENDPOINTS]; + } USB_INTERFACE; + + #pragma pack() + + + + #define _pcps_ddev_data_win_pnp \ + DEVICE_OBJECT *physical_device_object; \ + USB_REMOVE_LOCK remove_lock; \ + \ + struct \ + { \ + USBD_CONFIGURATION_HANDLE handle; \ + int value; \ + USB_INTERFACE interfaces[MBG_USB_MAX_NUMBER_OF_INTERFACES]; \ + } config; \ + \ + LONG ref_count; \ + POWER_STATE power_state; \ + DEVICE_POWER_STATE device_power_states[PowerSystemMaximum]; \ + \ + DEVICE_OBJECT *NextLowerDriver; \ + BOOLEAN Started; \ + BOOLEAN SurpriseRemoved; \ + IO_REMOVE_LOCK RemoveLock; \ + BOOLEAN PortWasMapped; + +#else // if !defined( MBG_TGT_WIN32_PNP ) + + // Don't need PNP extensions in non-PNP environment. + #define _pcps_ddev_data_win_pnp \ + UNICODE_STRING *RegistryPath; \ + PVOID orgDeviceExtension; + +#endif // !defined( MBG_TGT_WIN32_PNP ) + + + #define _pcps_ddev_data_win \ + DRIVER_OBJECT *DriverObject; \ + DEVICE_OBJECT *DeviceObject; \ + UNICODE_STRING win32DeviceName; \ + WCHAR wcs_msg[512]; \ + IRP *irp; \ + _pgmb_irq_vars \ + _pcps_ddev_data_win_pnp + +#endif // defined( MBG_TGT_KERNEL ) + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + clock_t w32_clock( void ) ; + /** + * @brief Try to import an API function to read precise Windows system time + * + * Check if the Windows API call KeQuerySystemTimePrecise() is available + * in kernel mode. This function has been introduced with Windows 8, so it + * is not available on older Windows versions, and thus the API call is + * imported from ntoskrnl.exe at runtime. + * + * @param fnc address of a function pointer which is set to the imported + * API function, or to NULL if the API call is not supported + * + * @see KeQuerySystemTimePrecise() + */ + void import_kernel_precise_time_api( KE_QUERY_SYSTEM_TIME_FNC *fnc ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext + +#endif /* _MBG_W32_H */ + diff --git a/mbglib/win32/wingetopt.c b/mbglib/win32/wingetopt.c new file mode 100644 index 0000000..ed04c44 --- /dev/null +++ b/mbglib/win32/wingetopt.c @@ -0,0 +1,90 @@ +/* +POSIX getopt for Windows + +AT&T Public License + +Code given out at the 1985 UNIFORUM conference in Dallas. +*/ + +#ifndef __GNUC__ + +#include "wingetopt.h" +#include <stdio.h> + +#if !defined( NULL ) + #define NULL 0 +#endif + +#if 1 //##++ defined( MSVC ) + + #include <string.h> + +// #define strcmp _strcmp +// #define strchr _strchr + +#endif + + +#define EOF (-1) +#define ERR(s, c) if(opterr){\ + char errbuf[2];\ + errbuf[0] = c; errbuf[1] = '\n';\ + fputs(argv[0], stderr);\ + fputs(s, stderr);\ + fputc(c, stderr);} + //(void) write(2, argv[0], (unsigned)strlen(argv[0]));\ + //(void) write(2, s, (unsigned)strlen(s));\ + //(void) write(2, errbuf, 2);} + +int opterr = 1; +int optind = 1; +int optopt; +char *optarg; + +int +getopt(argc, argv, opts) +int argc; +char **argv, *opts; +{ + static int sp = 1; + register int c; + register char *cp; + + if(sp == 1) + if(optind >= argc || + argv[optind][0] != '-' || argv[optind][1] == '\0') + return(EOF); + else if(strcmp(argv[optind], "--") == 0) { + optind++; + return(EOF); + } + optopt = c = argv[optind][sp]; + if(c == ':' || (cp=strchr(opts, c)) == NULL) { + ERR(": illegal option -- ", c); + if(argv[optind][++sp] == '\0') { + optind++; + sp = 1; + } + return('?'); + } + if(*++cp == ':') { + if(argv[optind][sp+1] != '\0') + optarg = &argv[optind++][sp+1]; + else if(++optind >= argc) { + ERR(": option requires an argument -- ", c); + sp = 1; + return('?'); + } else + optarg = argv[optind++]; + sp = 1; + } else { + if(argv[optind][++sp] == '\0') { + sp = 1; + optind++; + } + optarg = NULL; + } + return(c); +} + +#endif /* __GNUC__ */ diff --git a/mbglib/win32/wingetopt.h b/mbglib/win32/wingetopt.h new file mode 100644 index 0000000..f983fb3 --- /dev/null +++ b/mbglib/win32/wingetopt.h @@ -0,0 +1,32 @@ +/* +POSIX getopt for Windows + +AT&T Public License + +Code given out at the 1985 UNIFORUM conference in Dallas. +*/ + +#ifdef __GNUC__ +#include <getopt.h> +#endif +#ifndef __GNUC__ + +#ifndef _WINGETOPT_H_ +#define _WINGETOPT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int opterr; +extern int optind; +extern int optopt; +extern char *optarg; +extern int getopt(int argc, char **argv, char *opts); + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H_ */ +#endif /* __GNUC__ */ diff --git a/mbgstatus/mbgstatus.c b/mbgstatus/mbgstatus.c new file mode 100644 index 0000000..d4df10c --- /dev/null +++ b/mbgstatus/mbgstatus.c @@ -0,0 +1,895 @@ + +/************************************************************************** + * + * $Id: mbgstatus.c 1.13.1.25 2013/02/05 14:36:47Z martin TEST martin $ + * + * Description: + * Main file for mbgstatus program which demonstrates how to + * access a Meinberg device via IOCTL calls and prints device + * information. + * + * ----------------------------------------------------------------------- + * $Log: mbgstatus.c $ + * Revision 1.13.1.25 2013/02/05 14:36:47Z martin + * Revision 1.13.1.24 2012/04/11 16:26:44Z martin + * Revision 1.13.1.23 2012/04/10 15:56:40 martin + * Revision 1.13.1.22 2012/02/14 13:40:02 martin + * Use library function to print MAC address. + * Revision 1.13.1.21 2012/01/17 13:35:41 martin + * More control of amount of output by verbosity level. + * Revision 1.13.1.20 2012/01/16 16:41:25 martin + * Revision 1.13.1.19 2011/10/28 13:46:14 martin + * Revision 1.13.1.18 2011/10/28 13:05:03 martin + * Revision 1.13.1.17 2011/10/05 15:10:56 martin + * Show PZF correlation state. + * Revision 1.13.1.16 2011/10/05 13:03:34 martin + * Adapted PZF correlation/signal/status display. + * Revision 1.13.1.15 2011/10/05 11:57:42 martin + * Revision 1.13.1.14 2011/09/29 16:30:03 martin + * Started to support PZF. + * Optionally show hex status. + * Changed what is displayed in certain levels of verbosity. + * Revision 1.13.1.13 2011/09/07 15:08:55 martin + * Account for modified library functions which can now + * optionally print the raw (hex) HR time stamp. + * Revision 1.13.1.12 2011/07/08 11:02:47 martin + * Revision 1.13.1.11 2011/07/05 15:35:55 martin + * Modified version handling. + * Revision 1.13.1.10 2011/07/05 14:35:19 martin + * New way to maintain version information. + * Revision 1.13.1.9 2011/04/20 16:08:27 martin + * Use snprint_ip4_addr() from module lan_util. + * Revision 1.13.1.8 2011/03/03 10:01:23 daniel + * Indicate Unicast role in PTP port state + * Revision 1.13.1.7 2011/02/07 12:10:58 martin + * Use mbg_get_ptp_status() API call. + * Revision 1.13.1.6 2010/11/25 14:54:51 martin + * Revision 1.13.1.5 2010/11/05 12:54:22 martin + * Introduce "verbose" flag and associated command line parameter -v. + * Revision 1.13.1.4 2010/10/15 11:28:56 martin + * Display UTC offs from IRIG signal. + * Revision 1.13.1.3 2010/08/30 08:22:24 martin + * Revision 1.13.1.2 2010/08/11 15:06:49 martin + * Preliminarily display raw IRIG data, if supported by the device. + * Revision 1.13.1.1 2010/02/17 14:11:43 martin + * Cosmetics ... + * Revision 1.13 2009/09/29 15:02:16 martin + * Updated version number to 3.4.0. + * Revision 1.12 2009/07/24 14:02:59 martin + * Display LAN and PTP status of PTP cards. + * Updated version number to 3.3.0. + * Revision 1.11 2009/06/19 14:20:36 martin + * Display raw IRIG time with TCR cards which support this. + * Revision 1.10 2009/06/16 08:21:08 martin + * Intermediate version 3.1.0a. + * Display IRIG debug status, if supported by the card. + * Revision 1.9 2009/03/20 11:35:41 martin + * Updated version number to 3.1.0. + * Updated copyright year to include 2009. + * Display signal source after signal level. + * Display GPS UTC parameter info, if supported by the card. + * Display IRIG control bits, if supported by the card. + * Revision 1.8 2008/12/22 12:48:18 martin + * Updated description, copyright, revision number and string. + * Use unified functions from toolutil module. + * Warn if a PCI Express device with unsafe IRQ support is detected. + * Account for signed irq_num. + * Accept device name(s) on the command line. + * Don't use printf() without format, which migth produce warnings + * with newer gcc versions. + * Revision 1.7 2007/07/24 09:33:52 martin + * Fixed display of port and IRQ resources. + * Updated copyright to include 2007. + * Revision 1.6 2006/03/10 12:38:22 martin + * Fixed printing of sign in print_position(). + * Revision 1.5 2004/11/08 15:41:56 martin + * Modified formatted printing of date/time string. + * Using type casts to avoid compiler warnings. + * Revision 1.4 2003/07/30 08:16:39 martin + * Also displays oscillator DAC values for GPS. + * Revision 1.3 2003/07/08 15:38:57 martin + * Call mbg_find_devices(). + * Account for swap_doubles() now being called inside + * the mbgdevio API functions. + * Show IRQ number assigned to a device. + * Revision 1.2 2003/04/25 10:28:05 martin + * Use new functions from mbgdevio library. + * New program version v2.1. + * Revision 1.1 2001/09/17 15:08:59 martin + * + **************************************************************************/ + +// include Meinberg headers +#include <mbgdevio.h> +#include <mbgtime.h> +#include <pcpslstr.h> +#include <pcpsutil.h> +#include <toolutil.h> // common utility functions +#include <lan_util.h> + +// include system headers +#include <stdio.h> +#include <stdlib.h> + + +#define MBG_MICRO_VERSION 0 +#define MBG_FIRST_COPYRIGHT_YEAR 2001 +#define MBG_LAST_COPYRIGHT_YEAR 0 // use current year by default + +static const char *pname = "mbgstatus"; + + +static unsigned int verbose; + +static const char *ref_name[N_PCPS_REF]= PCPS_REF_NAMES_ENG; +static const char *icode_rx_names[N_ICODE_RX] = DEFAULT_ICODE_RX_NAMES; +static const char *osc_name[N_GPS_OSC] = DEFAULT_GPS_OSC_NAMES; + +static int year_limit = 1990; + +static int max_ref_offs_h = MBG_REF_OFFS_MAX / MINS_PER_HOUR; +static int invt_reason; + +LANGUAGE language; +CTRY ctry; + + + +static /*HDR*/ +void show_invt_reason( void ) +{ + static const char fmt[] = "\n** Warning: %s\nThe command %s.\n"; + + switch ( invt_reason ) + { + case 2: + printf( fmt, DEFAULT_STR_IRIG_NOT_CFGD_EN, + "\"mbgirigcfg\" can be used to change the settings" ); + break; + + case 1: + printf( fmt, DEFAULT_STR_IRIG_INVT_EN, + "\"mbgctrl DATE=...\" can be used to set the on-board date" ); + break; + + } // switch + +} // show_invt_reason + + + +static /*HDR*/ +void print_pcps_time( const char *s, const PCPS_TIME *tp, const char *tail ) +{ + const char *fmt = "%s"; + char ws[256]; + + if ( s ) + printf( fmt, s ); + + printf( fmt, pcps_date_time_str( ws, tp, year_limit, pcps_tz_name( tp, PCPS_TZ_NAME_FORCE_UTC_OFFS, 0 ) ) ); + + if ( ( verbose > 0 ) && _pcps_time_is_read( tp ) ) + printf( ", st: 0x%02lX", (ulong) tp->status ); + + if ( tail ) + printf( fmt, tail ); + +} // print_pcps_time + + + +static /*HDR*/ +void print_dms( const char *s, const DMS *p, const char *tail ) +{ + const char *fmt = "%s"; + + printf( "%s %c %3i deg %02i min %05.2f sec", + s, + p->prefix, + p->deg, + p->min, + p->sec + ); + + if ( tail ) + printf( fmt, tail ); + +} // print_dms + + + +static /*HDR*/ +void print_position( const char *s, const POS *p, const char *tail ) +{ + const char *fmt = "%s"; + double r2d = 180 / PI; + + + if ( s ) + { + printf( fmt, s ); + + if ( verbose ) + printf( "\n" ); + } + + if ( verbose > 1 ) + { + printf( " x: %.0fm y: %.0fm z: %.0fm", + p->xyz[XP], p->xyz[YP], p->xyz[ZP] ); + + if ( tail ) + printf( fmt, tail ); + } + + // LLA latitude and longitude are in radians, convert to degrees + printf( " lat: %+.4f lon: %+.4f alt: %.0fm", + p->lla[LAT] * r2d, p->lla[LON] * r2d, p->lla[ALT] ); + + if ( tail ) + printf( fmt, tail ); + + if ( verbose ) + { + print_dms( " latitude: ", &p->latitude, tail ); + print_dms( " longitude:", &p->longitude, tail ); + } + +} // print_position + + + +static /*HDR*/ +void show_signal( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, int signal ) +{ + int ref_type; + int rc; + + ref_type = _pcps_ref_type( pdev ); + + if ( ref_type >= N_PCPS_REF ) + ref_type = PCPS_REF_NONE; + + printf( "Signal: %u%% (%s", signal * 100 / PCPS_SIG_MAX, ref_name[ref_type] ); + + if ( _pcps_is_irig_rx( pdev ) ) + { + IRIG_INFO irig_rx_info; + MBG_REF_OFFS ref_offs; + + rc = mbg_get_irig_rx_info( dh, &irig_rx_info ); + + if ( rc == MBG_SUCCESS ) + { + int idx = irig_rx_info.settings.icode; + + if ( idx < N_ICODE_RX ) + { + printf( " %s", icode_rx_names[idx] ); + + if ( !( MSK_ICODE_RX_HAS_TZI & ( 1UL << idx ) ) ) + { + if ( _pcps_has_ref_offs( pdev ) ) + { + rc = mbg_get_ref_offs( dh, &ref_offs ); + + if ( rc == MBG_SUCCESS ) + { + int ref_offs_h = ref_offs / MINS_PER_HOUR; + + if ( abs( ref_offs_h ) > max_ref_offs_h ) + printf( ", ** UTC offs not configured **" ); + else + printf( ", UTC%+ih", ref_offs_h ); + } + } + } + } + } + } + else + if ( _pcps_has_pzf( pdev ) ) + printf( "/PZF" ); + + printf( ")\n" ); + +} // show_signal + + + +static /*HDR*/ +void show_time_and_status( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, const char *tail ) +{ + const char status_fmt[] = "Status info: %s%s\n"; + const char status_err[] = "*** "; + const char status_ok[] = ""; + const char *info_err = ( _pcps_is_gps( pdev ) || _pcps_is_lwr( pdev ) ) ? + "ANTENNA FAULTY" : "NO INPUT SIGNAL"; + const char info_ok[] = "Input signal available"; + PCPS_TIME t; + PCPS_STATUS_STRS strs; + int signal; + int i; + int rc = mbg_get_time( dh, &t ); + if ( mbg_ioctl_err( rc, "mbg_get_time" ) ) + return; + + + print_pcps_time( "Date/time: ", &t, tail ); + + if ( ( verbose > 0 ) && _pcps_has_hr_time( pdev ) ) + { + PCPS_HR_TIME ht; + char ws[80]; + + rc = mbg_get_hr_time( dh, &ht ); + + if ( mbg_ioctl_err( rc, "mbg_get_hr_time" ) ) + return; + + mbg_snprint_hr_time( ws, sizeof( ws ), &ht, 0 ); // raw timestamp? + printf( "Local HR time: %s", ws ); + + if ( verbose > 0 ) + printf( ", st: 0x%04lX", (ulong) ht.status ); + + printf( "%s", tail ); + } + + signal = t.signal - PCPS_SIG_BIAS; + + if ( signal < 0 ) + signal = 0; + else + if ( signal > PCPS_SIG_MAX ) + signal = PCPS_SIG_MAX; + + if ( _pcps_has_signal( pdev ) ) + show_signal( dh, pdev, signal ); + + if ( _pcps_has_pzf( pdev ) ) + { + mbg_show_pzf_corr_info( dh, pdev, 0 ); + printf( "\n" ); + } + + if ( verbose && _pcps_has_irig_time( pdev ) ) + { + PCPS_IRIG_TIME it; + + rc = mbg_get_irig_time( dh, &it ); + + if ( !mbg_ioctl_err( rc, "mbg_get_irig_time" ) ) + printf( "Raw IRIG time: yday %u, %02u:%02u:%02u\n", + it.yday, it.hour, it.min, it.sec ); + } + + printf( status_fmt, + ( signal < PCPS_SIG_ERR ) ? status_err : status_ok, + ( signal < PCPS_SIG_ERR ) ? info_err : info_ok ); + + // Evaluate the status code and setup status messages. + pcps_status_strs( t.status, _pcps_time_is_read( &t ), + _pcps_is_gps( pdev ), &strs ); + + // Print the status messages. + for ( i = 0; i < N_PCPS_STATUS_STR; i++ ) + { + PCPS_STATUS_STR *pstr = &strs.s[i]; + if ( pstr->cp ) + printf( status_fmt, + pstr->is_err ? status_err : status_ok, + pstr->cp ); + } + + invt_reason = 0; + + if ( _pcps_is_irig_rx( pdev ) && ( t.status & PCPS_INVT ) ) + { + MBG_REF_OFFS ref_offs; + + rc = mbg_get_ref_offs( dh, &ref_offs ); + + if ( !mbg_ioctl_err( rc, "mbg_get_ref_offs" ) ) + { + if ( _pcps_ref_offs_out_of_range( ref_offs ) ) + invt_reason = 2; + else + invt_reason = 1; + } + } + +} // show_time_and_status + + + +static /*HDR*/ +void show_sync_time( MBG_DEV_HANDLE dh, const char *tail ) +{ + PCPS_TIME t; + int rc = mbg_get_sync_time( dh, &t ); + + if ( mbg_ioctl_err( rc, "mbg_get_sync_time" ) ) + return; + + print_pcps_time( "Last sync: ", &t, tail ); + +} // show_sync_time + + + +static /*HDR*/ +void show_ext_stat_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *tail ) +{ + const char *fmt = "%s"; + RECEIVER_INFO ri; + STAT_INFO si = { 0 }; + char ws[80]; + char *mode_name; + + int rc = mbg_setup_receiver_info( dh, p_dev, &ri ); + + if ( mbg_ioctl_err( rc, "mbg_setup_receiver_info" ) ) + return; + + if ( _pcps_has_stat_info( p_dev ) ) + { + rc = mbg_get_gps_stat_info( dh, &si ); + + if ( mbg_ioctl_err( rc, "mbg_get_gps_stat_info" ) ) + return; + + + if ( _pcps_has_stat_info_mode( p_dev ) ) + { + switch ( si.mode ) + { + case AUTO_166: mode_name = "Normal Operation"; break; + case WARM_166: mode_name = "Warm Boot"; break; + case COLD_166: mode_name = "Cold Boot"; break; + + default: // This should never happen! + sprintf( ws, "Unknown mode of operation: %02Xh", si.mode ); + mode_name = ws; + + } // switch + } + + if ( _pcps_has_stat_info_svs( p_dev ) ) + printf( "%s, %i sats in view, %i sats used\n", mode_name, si.svs_in_view, si.good_svs ); + } + + if ( verbose ) + { + printf( "Osc type: %s", osc_name[( ri.osc_type < N_GPS_OSC ) ? ri.osc_type : GPS_OSC_UNKNOWN] ); + + if ( _pcps_has_stat_info( p_dev ) ) + { + printf( ", DAC cal: %+i, fine: %+i", + (int) ( si.dac_cal - OSC_DAC_BIAS ), + (int) ( si.dac_val - OSC_DAC_BIAS ) ); + } + + puts( "" ); + } + + if ( tail ) + printf( fmt, tail ); + +} // show_ext_stat_info + + + +static /*HDR*/ +void show_gps_pos( MBG_DEV_HANDLE dh, const char *tail ) +{ + POS pos; + int rc = mbg_get_gps_pos( dh, &pos ); + + if ( mbg_ioctl_err( rc, "mbg_get_gps_pos" ) ) + return; + + print_position( "Receiver Position:", &pos, tail ); + +} // show_gps_pos + + + +static /*HDR*/ +void show_utc_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) +{ + UTC utc; + + int rc = mbg_get_utc_parm( dh, &utc ); + + if ( mbg_ioctl_err( rc, "mbg_get_utc_parm" ) ) + return; + + if ( !utc.valid ) + { + puts( "** UTC parameters not valid" ); + return; + } + + if ( verbose > 1 ) + { + //##++++ utc.delta_tls = utc.delta_tlsf - 1; + + printf( "CSUM: %04X, valid: %04X\n", utc.csum, utc.valid ); + printf( "t0t: %u|%u.%07u, A0: %g A1: %g\n", + utc.t0t.wn, utc.t0t.sec, utc.t0t.tick, + utc.A0, utc.A1 ); + printf( "WNlsf: %u, DN: %u, offs: %i/%i\n", + utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf ); + } + + if ( utc.delta_tls != utc.delta_tlsf ) + { + // a leap second is currently being announced + time_t t_ls = (time_t) utc.WNlsf * SECS_PER_WEEK + + (time_t) utc.DNt * SECS_PER_DAY + + GPS_SEC_BIAS - 1; + + struct tm *tm = gmtime( &t_ls ); + + printf( "UTC offset transition from %is to %is due to leap second\n" + "%s at UTC midnight at the end of %04i-%02i-%02i.\n", + utc.delta_tls, utc.delta_tlsf, + ( utc.delta_tls < utc.delta_tlsf ) ? "insertion" : "deletion", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday + ); + } + else + printf( "UTC offset parameter: %is, no leap second announced.\n", utc.delta_tls ); + +} // show_utc_info + + + +static /*HDR*/ +void show_irig_ctrl_bits( MBG_DEV_HANDLE dh ) +{ + MBG_IRIG_CTRL_BITS irig_ctrl_bits; + + int rc = mbg_get_irig_ctrl_bits( dh, &irig_ctrl_bits ); + + if ( mbg_ioctl_err( rc, "mbg_get_irig_ctrl_bits" ) ) + return; + + printf( "IRIG control bits: %08lX (hex, LSB first)", (ulong) irig_ctrl_bits ); + printf( ", TFOM: 0x%X", _pcps_tfom_from_irig_ctrl_bits( &irig_ctrl_bits ) ); + printf( "\n" ); + +} // show_irig_ctrl_bits + + + +static /*HDR*/ +char *str_raw_irig_utc_offs_hours( char *s, int max_len, const MBG_RAW_IRIG_DATA *p ) +{ + int n; + long offs = ( p->data_bytes[8] & 0x08 ) + | ( ( p->data_bytes[8] >> 2 ) & 0x04 ) + | ( ( p->data_bytes[8] >> 4 ) & 0x02 ) + | ( ( p->data_bytes[8] >> 6 ) & 0x01 ); + + n = snprintf( s, max_len, "%c%li", ( p->data_bytes[8] & 0x80 ) ? '-' : '+', offs ); + + if ( p->data_bytes[8] & 0x02 ) + n += snprintf( &s[n], max_len - n, "%s", ".5" ); + + return s; + +} // str_raw_irig_utc_offs_hours + + + +static /*HDR*/ +void show_raw_irig_data( MBG_DEV_HANDLE dh ) +{ + MBG_RAW_IRIG_DATA raw_irig_data; + char ws[80]; + int i; + + int rc = mbg_get_raw_irig_data( dh, &raw_irig_data ); + + if ( mbg_ioctl_err( rc, "mbg_get_raw_irig_data" ) ) + return; + + printf( "Raw IRIG data:" ); + + for ( i = 0; i < sizeof( raw_irig_data ); i++ ) + printf( " %02X", raw_irig_data.data_bytes[i] ); + + printf( " (hex)" ); + printf( ", TFOM: 0x%X", _pcps_tfom_from_raw_irig_data( &raw_irig_data ) ); + printf( ", UTC offs: %sh", str_raw_irig_utc_offs_hours( ws, sizeof( ws ), &raw_irig_data ) ); + printf( "\n" ); + +} // show_raw_irig_data + + + +static /*HDR*/ +void show_irig_debug_status( MBG_DEV_HANDLE dh ) +{ + static const char *status_str[N_MBG_DEBUG_BIT] = MBG_DEBUG_STATUS_STRS; + + MBG_DEBUG_STATUS st; + int i; + int rc = _mbg_generic_read_var( dh, PCPS_GET_DEBUG_STATUS, st ); + + if ( mbg_ioctl_err( rc, "show_irig_debug_status" ) ) + return; + + printf( "Debug status (hex): %08lX\n", (ulong) st ); + + for ( i = 0; i < N_MBG_DEBUG_BIT; i++ ) + if ( st & ( 1UL << i ) ) + printf( " %s\n", status_str[i] ); + +} // show_irig_debug_status + + + +static /*HDR*/ +void show_lan_intf_state( MBG_DEV_HANDLE dh ) +{ + IP4_SETTINGS ip4_settings; + LAN_IF_INFO lan_if_info; + char ws[100]; + + int rc = mbg_get_ip4_state( dh, &ip4_settings ); + + if ( mbg_ioctl_err( rc, "mbg_get_ip4_state" ) ) + return; + + rc = mbg_get_lan_if_info( dh, &lan_if_info ); + + if ( mbg_ioctl_err( rc, "mbg_get_lan_if_info" ) ) + return; + + + printf( "On-board LAN interface settings:\n" ); + + snprint_mac_addr( ws, sizeof( ws ), &lan_if_info.mac_addr ); + printf( " MAC Address: %s\n", ws ); + + snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.ip_addr, NULL ); + printf( " IP Address: %s%s\n", ws, ( ip4_settings.flags & IP4_MSK_DHCP ) ? + " (DHCP)" : "" ); + + snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.netmask, NULL ); + printf( " Net Mask: %s\n", ws ); + + snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.broad_addr, NULL ); + printf( " Broadcast Addr: %s\n", ws ); + + snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.gateway, NULL ); + printf( " Gateway: %s\n", ws ); + + printf( " Link detected: %s\n", ( ip4_settings.flags & IP4_MSK_LINK ) ? "YES" : "NO" ); + +} // show_lan_intf_state + + + +static /*HDR*/ +void show_ptp_state( MBG_DEV_HANDLE dh ) +{ + static const char *ptp_stat_str[N_PTP_PORT_STATE] = PTP_PORT_STATE_STRS; + char ws[100]; + const char *cp; + int ptp_state_available; + PTP_STATE ptp_state; + PTP_CFG_INFO ptp_info; + + int rc = mbg_get_ptp_state( dh, &ptp_state ); + + if ( mbg_ioctl_err( rc, "mbg_get_ptp_state" ) ) + return; + + rc = mbg_get_ptp_cfg_info( dh, &ptp_info ); + + if ( mbg_ioctl_err( rc, "mbg_get_ptp_info" ) ) + return; + + printf( "PTP port status:\n" ); + + ptp_state_available = ( ptp_state.port_state == PTP_PORT_STATE_SLAVE ); + + printf( " Port mode: %s%s\n", ( ptp_state_available && ptp_info.settings.ptp_role == PTP_ROLE_UNICAST_SLAVE ) ? "Unicast" : "", + ( ptp_state.port_state < N_PTP_PORT_STATE ) ? ptp_stat_str[ptp_state.port_state] : "(undefined)" ); + + cp = ptp_state_available ? ws : str_not_avail; + +//##++++++++++ + snprintf( ws, sizeof( ws ), "%02X-%02X-%02X-%02X-%02X-%02X", + ptp_state.gm_id.b[0], + ptp_state.gm_id.b[1], + ptp_state.gm_id.b[2], + ptp_state.gm_id.b[5], + ptp_state.gm_id.b[6], + ptp_state.gm_id.b[7] + ); + printf( " Grandmaster MAC: %s\n", cp ); + + + snprintf( ws, sizeof( ws ), "%c%li.%09li s", + _nano_time_negative( &ptp_state.path_delay ) ? '-' : '+', + labs( (long) ptp_state.path_delay.secs ), + labs( (long) ptp_state.path_delay.nano_secs ) + ); + printf( " PTP path delay: %s\n", cp ); + + + snprintf( ws, sizeof( ws ), "%c%li.%09li s", + _nano_time_negative( &ptp_state.offset ) ? '-' : '+', + labs( (long) ptp_state.offset.secs ), + labs( (long) ptp_state.offset.nano_secs ) + ); + printf( " PTP time offset: %s\n", cp ); + +} // show_ptp_state + + + +static /*HDR*/ +int check_irq_unsafe( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) +{ + PCPS_IRQ_STAT_INFO irq_stat_info; + int ret_val = 0; + int rc = mbg_get_irq_stat_info( dh, &irq_stat_info ); + + if ( mbg_ioctl_err( rc, "mbg_get_irq_stat_info" ) ) + return -1; + + if ( irq_stat_info & PCPS_IRQ_STAT_UNSAFE ) + { + static const char *warn_line = "************************************************************************************"; + + puts( "" ); + puts( warn_line ); + + printf( + "** WARNING!\n" + "**\n" + "** Device %s with S/N %s has a firmware version and ASIC version\n" + "** which do not allow safe operation with hardware interrupts (IRQs) enabled.\n" + "**\n" + "** Please see http://www.meinberg.de/english/info/pex-upgrades.htm\n" + "** for information how the card can easily be upgraded, or contact\n" + "** Meinberg support (Email: support@meinberg.de) or your local\n" + "** representative.\n" + , + _pcps_type_name( p_dev ), _pcps_sernum( p_dev ) + ); + + if ( irq_stat_info & PCPS_IRQ_STAT_ENABLED ) + { + printf( + "**\n" + "** Interrupts are currently enabled for this card (NTP daemon running?)\n" + "** so other access is inhibited to prevent the system from hanging.\n" + ); + + ret_val = -1; + } + + puts( warn_line ); + puts( "" ); + } + + return ret_val; + +} // check_irq_unsafe + + + +static /*HDR*/ +int do_mbgstatus( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) +{ + int ret_val = 0; + + if ( check_irq_unsafe( dh, p_dev ) < 0 ) + goto done; + + if ( _pcps_has_gps_data( p_dev ) ) + show_ext_stat_info( dh, p_dev, NULL ); + + show_time_and_status( dh, p_dev, "\n" ); + show_sync_time( dh, "\n" ); + + if ( _pcps_is_gps( p_dev ) ) + show_gps_pos( dh, "\n" ); + + if ( _pcps_has_utc_parm( p_dev ) && ( _pcps_is_gps( p_dev ) || ( verbose > 0 ) ) ) + show_utc_info( dh, p_dev ); + + if ( verbose && _pcps_has_irig_ctrl_bits( p_dev ) ) + show_irig_ctrl_bits( dh ); + + if ( verbose && _pcps_has_raw_irig_data( p_dev ) ) + show_raw_irig_data( dh ); + + if ( verbose && _pcps_is_irig_rx( p_dev ) ) + show_irig_debug_status( dh ); + + if ( _pcps_has_lan_intf( p_dev ) ) + show_lan_intf_state( dh ); + + if ( _pcps_has_ptp( p_dev ) ) + show_ptp_state( dh ); + + show_invt_reason(); + +done: + return ret_val; + +} // do_mbgstatus + + + +static /*HDR*/ +void usage( void ) +{ + mbg_print_usage_intro( pname, + "This program prints status information for a device.\n" + "The displayed information depends on the type of the card." + ); + mbg_print_help_options(); + mbg_print_device_options(); + puts( "" ); + +} // usage + + + +int main( int argc, char *argv[] ) +{ + int c; + int rc; + + ctry_setup( 0 ); + language = LNG_ENGLISH; + ctry.dt_fmt = DT_FMT_YYYYMMDD; + ctry.dt_sep = '-'; + + mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); + + // check command line parameters + while ( ( c = getopt( argc, argv, "vh?" ) ) != -1 ) + { + switch ( c ) + { + case 'v': + verbose++; + break; + + case 'h': + case '?': + default: + must_print_usage = 1; + } + } + + if ( must_print_usage ) + { + usage(); + return 1; + } + + + if ( verbose ) + pcps_date_time_dist = 1; + + // The function below checks which devices have been specified + // on the command, and for each device + // - tries to open the device + // - shows basic device info + // - calls the function passed as last parameter + rc = mbg_check_devices( argc, argv, optind, do_mbgstatus ); + + return abs( rc ); +} diff --git a/mbgversion.h b/mbgversion.h new file mode 100644 index 0000000..433b942 --- /dev/null +++ b/mbgversion.h @@ -0,0 +1,37 @@ + +/************************************************************************** + * + * $Id: mbgversion.h 1.3 2013/01/03 12:09:30Z martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Program version definitions for package mbgtools-lx. + * + * ----------------------------------------------------------------------- + * $Log: mbgversion.h $ + * Revision 1.3 2013/01/03 12:09:30Z martin + * Changed copyright year to 2013. + * Revision 1.2 2012/01/17 10:10:54 martin + * Changed current copyright year to 2012. + * Revision 1.1 2011/07/08 11:38:32 martin + * Initial revision for pre-release. + * + **************************************************************************/ + +#define MBG_CURRENT_COPYRIGHT_YEAR 2013 +#define MBG_CURRENT_COPYRIGHT_YEAR_STR "2013" + +#define MBG_MAJOR_VERSION_CODE 3 +#define MBG_MINOR_VERSION_CODE 4 + +#define MBG_MAIN_VERSION_STR "3.4" + +// The codes below should only fe defined in development/pre-release versions +#define MBG_MICRO_VERSION_CODE_DEV 99 +#define MBG_MICRO_VERSION_STR_DEV "99" + + +#define MBG_MAIN_VERSION_CODE ( ( MBG_MAJOR_VERSION_CODE << 8 ) | MBG_MINOR_VERSION_CODE ) + +#define MBG_VERSION_CODE( _micro ) ( (uint16_t) ( ( MBG_MAIN_VERSION_CODE << 8 ) | (_micro) ) ) diff --git a/test/mbgcmptime/mbgcmptime.c b/test/mbgcmptime/mbgcmptime.c new file mode 100644 index 0000000..7052048 --- /dev/null +++ b/test/mbgcmptime/mbgcmptime.c @@ -0,0 +1,345 @@ + +/************************************************************************** + * + * $Id: mbgcmptime.c 1.1.1.3 2013/03/20 11:14:14Z martin TEST $ + * + * Description: + * Main file for mbgcmptime program which compares the time on 2 devices + * by reading the time plus cycles from both devices immediately after + * each other, and compensates the execution delay based on the returned + * cycles counts. + * + * ----------------------------------------------------------------------- + * $Log: mbgcmptime.c $ + * Revision 1.1.1.3 2013/03/20 11:14:14Z martin + * Revision 1.1.1.2 2013/02/01 16:26:50 martin + * Revision 1.1.1.1 2013/01/29 14:23:40 martin + * Tried to fix negative range overflow. + * Revision 1.1 2013/01/25 10:26:13 martin + * Initial revision. + * + **************************************************************************/ + +// include Meinberg headers +#include <mbgdevio.h> +#include <pcpsutil.h> +#include <toolutil.h> // common utility functions + +// include system headers +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#define MBG_MICRO_VERSION 0 +#define MBG_FIRST_COPYRIGHT_YEAR 2013 +#define MBG_LAST_COPYRIGHT_YEAR 0 // use default + +static const char *pname = "mbgcmptime"; + + +static int loops; +static int read_fast; +static int read_raw; +static long sleep_secs; +static long sleep_usecs; +static int print_raw; +static double warn_limit; +static double chk_limit; +static MBG_PC_CYCLES_FREQUENCY cyc_freq; + +static const char *ref_device_name; +static MBG_DEV_HANDLE dh_ref; + + +static /*HDR*/ +int do_mbgcmptime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) +{ + int supported = 0; + PCPS_HR_TIME_CYCLES htc1; + PCPS_HR_TIME_CYCLES htc2; + double delta_ts; + double delta_cyc; + double delta_t; + double prv_delta_t; + int prv_delta_t_avail = 0; + int this_loops = loops; + int rc; + int n; + char ws[256]; + + if ( read_fast ) + { + rc = mbg_dev_has_fast_hr_timestamp( dh, &supported ); + + if ( mbg_ioctl_err( rc, "mbg_has_fast_hr_timestamp" ) ) + goto done; + + if ( !supported ) + { + printf( "This device does not support fast (memory mapped) time stamps.\n" ); + printf( "** Falling back to raw mode.\n" ); + read_fast = 0; + } + + rc = mbg_dev_has_fast_hr_timestamp( dh_ref, &supported ); + + if ( mbg_ioctl_err( rc, "mbg_has_fast_hr_timestamp" ) ) + goto done; + + if ( !supported ) + { + printf( "The ref device does not support fast (memory mapped) time stamps.\n" ); + printf( "** Falling back to raw mode.\n" ); + read_fast = 0; +} + } + + rc = mbg_get_default_cycles_frequency_from_dev( dh, &cyc_freq ); + + if ( mbg_ioctl_err( rc, "mbg_get_default_cycles_frequency_from_dev" ) ) + goto done; + + + + for (;;) + { + if ( read_fast ) + { + PCPS_TIME_STAMP_CYCLES ts_c1; + PCPS_TIME_STAMP_CYCLES ts_c2; + + rc = mbg_get_fast_hr_timestamp_cycles( dh, &ts_c1 ); + + if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp_cycles 1" ) ) + break; + + rc = mbg_get_fast_hr_timestamp_cycles( dh_ref, &ts_c2 ); + + if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp_cycles 2" ) ) + break; + + setup_hr_time_cycles_from_timestamp_cycles( &htc1, &ts_c1 ); + setup_hr_time_cycles_from_timestamp_cycles( &htc2, &ts_c2 ); + } + else + { + rc = mbg_get_hr_time_cycles( dh, &htc1 ); + + if ( mbg_ioctl_err( rc, "mbg_get_hr_time_cycles 1" ) ) + break; + + rc = mbg_get_hr_time_cycles( dh_ref, &htc2 ); + + if ( mbg_ioctl_err( rc, "mbg_get_hr_time_cycles 2" ) ) + break; + } + + n = 0; + + n += mbg_snprint_hr_tstamp( &ws[n], sizeof( ws ) - n, &htc1.t.tstamp, 0 ); + + if ( print_raw ) + n += snprintf( &ws[n], sizeof( ws ) - n, " (0x%08lX.%08lX)", + (ulong) htc1.t.tstamp.sec, + (ulong) htc1.t.tstamp.frac ); + + n += snprintf( &ws[n], sizeof( ws ) - n, ", " ); + + n += mbg_snprint_hr_tstamp( &ws[n], sizeof( ws ) - n, &htc2.t.tstamp, 0 ); + + if ( print_raw ) + n += snprintf( &ws[n], sizeof( ws ) - n, " (0x%08lX.%08lX)", + (ulong) htc2.t.tstamp.sec, + (ulong) htc2.t.tstamp.frac ); + + delta_ts = (double) htc2.t.tstamp.sec + dfrac_sec_from_bin( htc2.t.tstamp.frac ) + - (double) htc1.t.tstamp.sec - dfrac_sec_from_bin( htc1.t.tstamp.frac ); + + #if defined( MBG_TGT_WIN32 ) + { + __int64 dt_t = htc2.cycles - htc1.cycles; + delta_cyc = (double) dt_t / (__int64) cyc_freq; + } + #else + delta_cyc = ( (double) ( htc2.cycles - htc1.cycles ) ) / cyc_freq; + #endif + delta_t = delta_ts - delta_cyc; + + n += snprintf( &ws[n], sizeof( ws ) - n, " ts: %.1f us, cyc: %.1f us, delta: %+.1f us", + delta_ts * 1e6, delta_cyc * 1e6, delta_t * 1e6 ); + + if ( ( warn_limit > 0.0 ) && ( fabs( delta_t ) > warn_limit ) ) + n += snprintf( &ws[n], sizeof( ws ) - n, " *" ); + + if ( prv_delta_t_avail ) + { + double ddelta_t = delta_t - prv_delta_t; + + if ( ( chk_limit > 0.0 ) && ( fabs( ddelta_t ) > chk_limit ) ) + n += snprintf( &ws[n], sizeof( ws ) - n, " <<" ); + } + + #if defined( DEBUG ) + if ( htc2.t.tstamp.sec != htc1.t.tstamp.sec ) + n += snprintf( &ws[n], sizeof( ws ) - n, " X" ); + #endif + + printf( "%s\n", ws ); + + if ( this_loops > 0 ) + this_loops--; + + if ( this_loops == 0 ) + break; + + prv_delta_t = delta_t; + prv_delta_t_avail = 1; + + if ( sleep_secs ) + sleep( sleep_secs ); + else + if ( sleep_usecs ) + usleep( sleep_usecs ); + + //##++++++ printf( "\n" ); + // if this_loops is < 0 then loop forever + } + +done: + mbg_close_device( &dh ); + + return rc; + +} // do_mbgcmptime + + + +static /*HDR*/ +void usage( void ) +{ + mbg_print_usage_intro( pname, + "This example program reads fast high resolution time stamps.\n" + "\n" + "This is done using memory mapped I/O in the kernel driver, so\n" + "this works only with cards which support memory mapped I/O." + ); + mbg_print_help_options(); + mbg_print_opt_info( "-i dev", "reference device the test card's time shall be compared" ); + mbg_print_opt_info( "-l limit", "append a marker '*' to the output if delta exceeds limit [us]" ); + mbg_print_opt_info( "-L limit", "append a marker '<<' to the output if delta changes [us]" ); + mbg_print_opt_info( "-f", "read fast (memory mapped) timestamps" ); + mbg_print_opt_info( "-c", "run continuously" ); + mbg_print_opt_info( "-n num", "run num loops" ); + mbg_print_opt_info( "-b", "burst read" ); + mbg_print_opt_info( "-r", "read raw time stamps, no cycles" ); + mbg_print_opt_info( "-s num", "sleep num seconds between calls" ); + mbg_print_opt_info( "-u num", "sleep num microseconds between calls" ); + mbg_print_device_options(); + puts( "" ); + +} // usage + + + +int main( int argc, char *argv[] ) +{ + int rc; + int c; + + mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); + + // check command line parameters + while ( ( c = getopt( argc, argv, "i:l:L:fcn:rs:u:h?" ) ) != -1 ) + { + switch ( c ) + { + case 'i': + ref_device_name = optarg; + break; + + case 'l': + warn_limit = (double) atoi( optarg ) / 1e6; + break; + + case 'L': + chk_limit = (double) atoi( optarg ) / 1e6; + break; + + case 'f': + read_fast = 1; + break; + + case 'c': + loops = -1; + break; + + case 'n': + loops = atoi( optarg ); + break; + + case 'r': + read_raw = 1; + break; + + case 's': + sleep_secs = atoi( optarg ); + break; + + case 'u': + sleep_usecs = atoi( optarg ); + break; + + case 'h': + case '?': + default: + must_print_usage = 1; + } + } + + if ( must_print_usage ) + { + usage(); + return 1; + } + + #if !MBG_TGT_SUPP_MEM_ACC + printf( "** Memory mapped access not supported on this target platform.\n\n" ); + return 1; + #endif + + #if !MBG_PC_CYCLES_SUPPORTED + printf( "** Warning: No cycles support to compute real latencies on this platform!\n" ); + return 1; + #endif + + + if ( ref_device_name ) + { + #if defined( MBG_TGT_WIN32 ) + dh_ref = mbg_open_device_by_name( ref_device_name, MBG_MATCH_MODEL); + #else // if defined( MBG_TGT_UNIX ) + dh_ref = open( ref_device_name, O_RDONLY ); + #endif + + if ( dh_ref < 0 ) + { + fprintf( stderr, "Failed to open ref device %s, exiting.\n", ref_device_name ); + exit( EXIT_FAILURE ); + } + + #if defined( DEBUG ) + fprintf( stderr, "Ref device %s opened successfully.\n", ref_device_name ); + #endif + } + + // The function below checks which devices have been specified + // on the command, and for each device + // - tries to open the device + // - shows basic device info + // - calls the function passed as last parameter + rc = mbg_check_devices( argc, argv, optind, do_mbgcmptime ); + + mbg_close_device( &dh_ref ); + + return abs( rc ); +} diff --git a/vc6/mbgcmptime/mbgcmptime.dsp b/vc6/mbgcmptime/mbgcmptime.dsp new file mode 100644 index 0000000..6ad0884 --- /dev/null +++ b/vc6/mbgcmptime/mbgcmptime.dsp @@ -0,0 +1,194 @@ +# Microsoft Developer Studio Project File - Name="mbgcmptime" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mbgcmptime - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mbgcmptime.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mbgcmptime.mak" CFG="mbgcmptime - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mbgcmptime - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mbgcmptime - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mbgcmptime - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbgcmptime" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbgcmptime.exe" + +!ELSEIF "$(CFG)" == "mbgcmptime - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbgcmptime" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbgcmptime.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mbgcmptime - Win32 Release" +# Name "mbgcmptime - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\test\mbgcmptime\mbgcmptime.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\mbglib\common\gpsdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbg_arch.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbg_tgt.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\mbg_w32.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgdevio.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgerror.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbggeo.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgmutex.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgpccyc.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgtime.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbgversion.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pci_asic.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsdev.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\usbdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\use_pack.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\words.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib +# End Source File +# End Target +# End Project diff --git a/vc6/mbgctrl/mbgctrl.dsp b/vc6/mbgctrl/mbgctrl.dsp new file mode 100644 index 0000000..b69af7b --- /dev/null +++ b/vc6/mbgctrl/mbgctrl.dsp @@ -0,0 +1,214 @@ +# Microsoft Developer Studio Project File - Name="mbgctrl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mbgctrl - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mbgctrl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mbgctrl.mak" CFG="mbgctrl - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mbgctrl - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mbgctrl - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mbgctrl - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbgctrl" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbgctrl.exe" + +!ELSEIF "$(CFG)" == "mbgctrl - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbgctrl" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbgctrl.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mbgctrl - Win32 Release" +# Name "mbgctrl - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\mbglib\common\deviohlp.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\lan_util.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbgctrl\mbgctrl.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\parmgps.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\parmpcps.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsutil.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\mbglib\common\gpsdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbg_arch.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbg_tgt.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\mbg_w32.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgdevio.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgerror.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbggeo.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgmutex.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgpccyc.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgtime.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbgversion.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pci_asic.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsdev.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\usbdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\use_pack.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\words.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib +# End Source File +# End Target +# End Project diff --git a/vc6/mbgfasttstamp/mbgfasttstamp.dsp b/vc6/mbgfasttstamp/mbgfasttstamp.dsp new file mode 100644 index 0000000..b25ae74 --- /dev/null +++ b/vc6/mbgfasttstamp/mbgfasttstamp.dsp @@ -0,0 +1,194 @@ +# Microsoft Developer Studio Project File - Name="mbgfasttstamp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mbgfasttstamp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mbgfasttstamp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mbgfasttstamp.mak" CFG="mbgfasttstamp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mbgfasttstamp - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mbgfasttstamp - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mbgfasttstamp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbgfasttstamp" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbgfasttstamp.exe" + +!ELSEIF "$(CFG)" == "mbgfasttstamp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbgfasttstamp" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbgfasttstamp.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mbgfasttstamp - Win32 Release" +# Name "mbgfasttstamp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\mbgfasttstamp\mbgfasttstamp.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\mbglib\common\gpsdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbg_arch.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbg_tgt.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\mbg_w32.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgdevio.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgerror.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbggeo.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgmutex.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgpccyc.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgtime.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbgversion.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pci_asic.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsdev.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\usbdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\use_pack.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\words.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib +# End Source File +# End Target +# End Project diff --git a/vc6/mbggpscap/mbggpscap.dsp b/vc6/mbggpscap/mbggpscap.dsp new file mode 100644 index 0000000..eae5591 --- /dev/null +++ b/vc6/mbggpscap/mbggpscap.dsp @@ -0,0 +1,194 @@ +# Microsoft Developer Studio Project File - Name="mbggpscap" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mbggpscap - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mbggpscap.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mbggpscap.mak" CFG="mbggpscap - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mbggpscap - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mbggpscap - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mbggpscap - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbggpscap" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbggpscap.exe" + +!ELSEIF "$(CFG)" == "mbggpscap - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbggpscap" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbggpscap.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mbggpscap - Win32 Release" +# Name "mbggpscap - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\mbggpscap\mbggpscap.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\mbglib\common\gpsdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbg_arch.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbg_tgt.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\mbg_w32.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgdevio.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgerror.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbggeo.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgmutex.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgpccyc.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgtime.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbgversion.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pci_asic.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsdev.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\usbdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\use_pack.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\words.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib +# End Source File +# End Target +# End Project diff --git a/vc6/mbghrtime/mbghrtime.dsp b/vc6/mbghrtime/mbghrtime.dsp new file mode 100644 index 0000000..6d5415b --- /dev/null +++ b/vc6/mbghrtime/mbghrtime.dsp @@ -0,0 +1,194 @@ +# Microsoft Developer Studio Project File - Name="mbghrtime" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mbghrtime - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mbghrtime.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mbghrtime.mak" CFG="mbghrtime - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mbghrtime - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mbghrtime - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mbghrtime - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbghrtime" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbghrtime.exe" + +!ELSEIF "$(CFG)" == "mbghrtime - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbghrtime" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbghrtime.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mbghrtime - Win32 Release" +# Name "mbghrtime - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\mbghrtime\mbghrtime.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\mbglib\common\gpsdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbg_arch.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbg_tgt.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\mbg_w32.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgdevio.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgerror.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbggeo.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgmutex.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgpccyc.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\mbgtime.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbgversion.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pci_asic.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsdev.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpsutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\usbdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\use_pack.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.h +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\words.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib +# End Source File +# End Target +# End Project diff --git a/vc6/mbgstatus/mbgstatus.dsp b/vc6/mbgstatus/mbgstatus.dsp new file mode 100644 index 0000000..a6b640e --- /dev/null +++ b/vc6/mbgstatus/mbgstatus.dsp @@ -0,0 +1,130 @@ +# Microsoft Developer Studio Project File - Name="mbgstatus" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mbgstatus - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mbgstatus.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mbgstatus.mak" CFG="mbgstatus - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mbgstatus - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mbgstatus - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mbgstatus - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I "..\..\mbgstatus" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/Release/mbgstatus.exe" + +!ELSEIF "$(CFG)" == "mbgstatus - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\mbgstatus" /I "..\..\mbglib\common" /I "..\..\mbglib\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/Debug/mbgstatus.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mbgstatus - Win32 Release" +# Name "mbgstatus - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\mbglib\common\ctry.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\ctrydttm.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\lan_util.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbgstatus\mbgstatus.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\pcpslstr.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\common\toolutil.c +# End Source File +# Begin Source File + +SOURCE=..\..\mbglib\win32\wingetopt.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\mbglib\lib\msc\mbgdevio.lib +# End Source File +# End Target +# End Project diff --git a/vc6/mbgtools-win.dsw b/vc6/mbgtools-win.dsw new file mode 100644 index 0000000..d3fb367 --- /dev/null +++ b/vc6/mbgtools-win.dsw @@ -0,0 +1,89 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "mbgcmptime"=".\mbgcmptime\mbgcmptime.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "mbgctrl"=".\mbgctrl\mbgctrl.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "mbgfasttstamp"=".\mbgfasttstamp\mbgfasttstamp.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "mbggpscap"=".\mbggpscap\mbggpscap.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "mbghrtime"=".\mbghrtime\mbghrtime.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "mbgstatus"=".\mbgstatus\mbgstatus.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + |