diff options
author | Martin Burnicki <martin.burnicki@meinberg.de> | 2009-01-22 12:01:00 +0100 |
---|---|---|
committer | Martin Burnicki <martin.burnicki@meinberg.de> | 2009-01-22 12:01:00 +0100 |
commit | d2cb34a07d87f9c4876b03c43c830c8509589523 (patch) | |
tree | a51d74629e886efad95a965b882cd2b07563fb82 | |
parent | fd4cbd96b62f656c2328fa9e902993c7a2b0d0a6 (diff) | |
download | mbgsdk-win-d2cb34a07d87f9c4876b03c43c830c8509589523.tar.gz mbgsdk-win-d2cb34a07d87f9c4876b03c43c830c8509589523.zip |
Update mbgdevio demo C files
-rw-r--r-- | c/demo/mbgdevio/hrtime.c | 41 | ||||
-rw-r--r-- | c/demo/mbgdevio/mbgdevio_demo.c | 92 | ||||
-rw-r--r-- | c/demo/mbgdevio/xhrtime.c | 134 | ||||
-rw-r--r-- | c/demo/mbgdevio/xhrtime.exe | bin | 49152 -> 0 bytes |
4 files changed, 195 insertions, 72 deletions
diff --git a/c/demo/mbgdevio/hrtime.c b/c/demo/mbgdevio/hrtime.c index d76846c..94eea4b 100644 --- a/c/demo/mbgdevio/hrtime.c +++ b/c/demo/mbgdevio/hrtime.c @@ -1,13 +1,14 @@ /************************************************************************** * - * $Id: hrtime.c 1.4 2009/01/07 15:22:36Z daniel TRASH $ - * $Name: $ + * $Id: hrtime.c 1.5 2009/01/23 08:31:28Z daniel REL_M $ + * $Name: MBGDEVIO_HRTIME_100 $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * ----------------------------------------------------------------------- * $Log: hrtime.c $ + * Revision 1.5 2009/01/23 08:31:28Z daniel * Revision 1.4 2009/01/07 15:22:36Z daniel * Cleaned up source code. * Revision 1.3 2008/01/16 08:48:24Z daniel @@ -17,11 +18,47 @@ * **************************************************************************/ +/*! \defgroup group_hrt Getting high resolution time stamps + + The structure PCPS_HR_TIME is read using + the mbg_get_hr_time() call and contains the system time in seconds since + 1970 (standard time_t format), the fractions of a second, plus status + and UTC offset. + + The device driver checks whether a particular feature like HR time is + supported by a particular device and returns an error if it is not. + Also the latest driver software should be used since older + versions of the driver don't check for HR time support. + + With our GPS cards, the effictive resolution of the HR time is better + than 1 microsecond. For the IRIG receivers, the resolution is 400 + microseconds which is still much better than 10/15 milliseconds provided + by the Windows system clock. + + To get most accuracy for time stamps, a program can read the PC's + performance counter, and then call mbg_get_time_cycles() which returns + the HR time plus the performance counter value which matches that HR + time stamp. The difference between the two performance counter values + can be used to compensate the program execution time delay. + + The way to access the time on the board is to write a command to the + board's microcontroller which in turn makes the requested data available + for reading. The advantage of this is that the interface is very + flexible, but the disadvantage is that the on-board microcontroller is + involved in any access to the board. In order to prevent applications + from overruning the on-board microcontroller by countinuous accesses to + the board the card has a limitation which limits the time between two + accesses to 200 microseconds and 1 millisecond depending on the device. + +*/ + /** \file Example program to read the high resolution time from Meinberg computer peripherals using the mbgdevio (Meinberg Device I/O) DLL. + + \copydoc group_hrt Build environment settings: diff --git a/c/demo/mbgdevio/mbgdevio_demo.c b/c/demo/mbgdevio/mbgdevio_demo.c index 7039f6b..0df7655 100644 --- a/c/demo/mbgdevio/mbgdevio_demo.c +++ b/c/demo/mbgdevio/mbgdevio_demo.c @@ -1,25 +1,16 @@ /************************************************************************** * - * $Id: mbgdevio_demo.c 1.5 2009/01/08 07:52:59Z daniel TRASH $ - * $Name: $ + * $Id: mbgdevio_demo.c 1.7 2009/01/23 08:31:28Z daniel REL_M $ + * $Name: MBGDEVIO_DEMO_100 $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * - * Description: - * Example program to access Meinberg computer peripherals - * using the mbgdevio (Meinberg Device I/O) DLL. - * - * Build environment settings: - * Add "mbglib\include" directory to the include search path. - * Link the main file plus the required import libraries, - * in this case mbgdevio.lib and mbgutil.lib. - * The import libraries are located: - * in mbglib\lib\msc for Microsoft C compilers - * in mbglib\lib\bc for Inprise/Borland compilers - * * ----------------------------------------------------------------------- * $Log: mbgdevio_demo.c $ + * Revision 1.7 2009/01/23 08:31:28Z daniel + * Revision 1.6 2009/01/20 11:13:26Z daniel + * Added comments. * Revision 1.5 2009/01/08 07:52:59Z daniel * Code cleanup * Revision 1.4 2008/12/04 13:39:04Z daniel @@ -31,6 +22,26 @@ * Initial revision * **************************************************************************/ + +/** + \file + Example program to access Meinberg computer peripherals + using the mbgdevio (Meinberg Device I/O) DLL.<br> + The program checks first whether a certain feature like high + resolution time, Memory Mapped I/O or user capture is + supported by the device. + + Build environment settings: + + Add "mbglib\include" directory to the include search path. + Link the main file plus the required import libraries, + in this case mbgdevio.lib and mbgutil.lib. + + The import libraries are located:<br> + <B>"mbglib\lib\msc"</B> for Microsoft C compilers<br> + <B>"mbglib\lib\bc"</B> for Inprise/Borland compilers + */ + #include <mbgdevio.h> #include <mbgutil.h> @@ -38,9 +49,10 @@ #include <stdio.h> -static int n_sec_change = 10; +static int n_sec_change = 0; + +#define MAX_MEM_MAPPED_CNT 20 /** Number of memory mapped time reads */ -#define MAX_MEM_MAPPED_CNT 20 static /*HDR*/ void err_msg( const char *msg ) @@ -132,6 +144,7 @@ void print_date_time_status( MBG_DEV_HANDLE dh ) PCPS_TIME t; + // Read a simple time stamp with 10 ms resolution. if ( PCPS_SUCCESS == mbg_get_time( dh, &t ) ) { print_date_time( &t, " " ); @@ -194,6 +207,7 @@ void print_hr_time( MBG_DEV_HANDLE dh ) printf( " HR time (raw): %s, latency: %i hns\n", sprint_hr_time( ws, &hr_t ), latency ); + // Format function taken from mbgutil.h mbg_str_pcps_hr_tstamp_utc( ws, sizeof( ws ), &hr_t ); printf( " HR time (utc): %s, latency=%i hns\n", ws, latency ); } @@ -223,6 +237,7 @@ void print_sec_changes( MBG_DEV_HANDLE dh ) PCPS_TIME t; BOOL rc; + // This IOCTL call blocks until a second change is detected. rc = mbg_get_time_sec_change( dh, &t ); if ( rc == PCPS_SUCCESS ) @@ -284,6 +299,35 @@ void print_sv_info( MBG_DEV_HANDLE dh ) static /*HDR*/ +/** + There are 3 functions to deal with the capture events: + + \li mbg_clr_ucap_buff() clears the on-board FIFO buffer + \li mbg_get_ucap_entries() returns the maximum number of entries + and the currently saved number of entries in the buffer + \li mbg_get_ucap_event() retrieves a capture event from the + on-board FIFO, or 0000.0000 if the FIFO buffer is empty. + + When using the time capture inputs the following hints might be helpful: + + \li The corresponding DIP switches on the card must be set to the "ON" + position in order to wire the input pins to the capture circuitry. See + the user manual for the correct DIP switches. + \li Capture events are stored in the on-board FIFO, and entries can be + retrieved from the FIFO in different ways. Once an entry has been + retrieved it is removed from the FIFO, so if several ways or + applications are used at the same time to retrieve capture events from + the FIFO then capture events may be missed by one application since they + have already been retrieved by another application. + \li The card provides 2 physical serial interfaces either of which may + have been configured to send a serial ASCII string automatically + whenever a capture event has occurred. Of course this would also remove + those capture events from the FIFO buffer. So the settings of both + serial ports should be checked to make sure none of the serial ports + have been configured to send the capture string automatically. This has + to be done only once for a card since the setting is saved in + non-volatile memory. +*/ void check_user_captures( MBG_DEV_HANDLE dh, PCPS_DEV *pdev ) { unsigned int ucaps_read = 0; @@ -461,30 +505,36 @@ int main( int argc, char* argv[] ) check_user_captures( dh, &dev ); } + //*********** - // Loop some seconds to wait for second changes + // Loop some seconds waiting for second to change // Uncomment the line below if required: // print_sec_changes( dh ); //*********** - // Check if device has memory mapped I/O support - // and read fast HR timestamps. + + // Check if device has support for memory mapped I/O + // and read a couple of time stamps. if ( _pcps_has_asic_version( &dev ) ) { PCI_ASIC_FEATURES asic_features; rc = mbg_get_asic_features( dh, &asic_features ); - if ( rc == PCPS_SUCCESS && asic_features >= 1 ) + if ( rc == PCPS_SUCCESS && asic_features >= PCI_ASIC_HAS_MM_IO ) { PCPS_HR_TIME hrtime[MAX_MEM_MAPPED_CNT] = { 0 }; uint32_t latency[MAX_MEM_MAPPED_CNT]; - + + // Read some memory mapped time stamps + // as fast as possible for(j = 0; j < MAX_MEM_MAPPED_CNT; j++) mbg_get_fast_hr_timestamp_comp( dh, &hrtime[j].tstamp, &latency[j] ); + + // Print time stamps for(j = 0; j < MAX_MEM_MAPPED_CNT; j++) { char ws[200]; diff --git a/c/demo/mbgdevio/xhrtime.c b/c/demo/mbgdevio/xhrtime.c index 89d64e8..f71c869 100644 --- a/c/demo/mbgdevio/xhrtime.c +++ b/c/demo/mbgdevio/xhrtime.c @@ -1,44 +1,78 @@ /************************************************************************** * - * $Id: xhrtime.c 1.2 2009/01/15 15:59:09Z daniel TRASH $ - * - * Description: - * Main file for mbgxhrtime program which demonstrates how to retrieve - * fast and accurate timestamps. - * - * This program starts a polling thread which reads a high resolution - * time stamp and associated CPU cycles counter value once per second - * and saves that data pair. - * - * Current time stamps are then computed by taking the current CPU - * cycles value and extrapolating the time from the last data pair. - * - * This is very much faster than accessing the PCI card for every - * single time stamp. - * - * Notes: - * - * 1.) This approach works / makes sense only with cards which support - * high resolution time stamps (HR time). If a card doesn't support - * that then this program prints a warning. - * - * 2.) Extrapolation is done using the time stamp counter (TSC) registers - * provided by Pentium CPUs and newer/compatible - * types as the cycles counter. On SMP / multicore CPUs those - * counters may not be synchronized, so this works only correctly - * if all cycles counter values are taken from the same CPU. - * To achieve this the process CPU affinity is by default set to - * the first CPU at program start, which means all threads of this - * process are executed only on that CPU. + * $Id: xhrtime.c 1.4 2009/01/23 08:31:28Z daniel REL_M $ * * ----------------------------------------------------------------------- * $Log: xhrtime.c $ + * Revision 1.4 2009/01/23 08:31:28Z daniel + * Revision 1.3 2009/01/20 11:13:26Z daniel + * Added comments. * Revision 1.2 2009/01/15 15:59:09Z daniel * Revision 1.1 2009/01/07 15:21:48Z daniel * Initial revision * **************************************************************************/ +/*! \defgroup group_xhrt Getting extrapolated high resolution time stamps + + To retrieve extrapolated time stamps a polling thread + inside the mbgdevio.dll is started which + reads a high resolution time stamp and an associated CPU cycles counter + value once per second and saves that data pair. + + Current time stamps are then computed by taking the current CPU + cycles value and extrapolating the time from the last data pair. + + This is very much faster than accessing the device for every + single time stamp. + + On systems where the cycles counter is implemented by a CPU's time stamp + counter (TSC) it maybe required to set the thread or process affinity to a + single CPU to get reliable cycles counts. In this case also care should be + taken that the CPU's clock frequency is not stepped up and down e.g. due + to power saving mechanisms (e.g. Intel SpeedStep, or AMD Cool'n'Quiet). + Otherwise time interpolation may be messed up. + + <b>Notes:</b> + \li This approach works / makes sense only with cards which support + high resolution time stamps (PCPS_HR_TIME). If a card doesn't support + that then this program prints a warning. + + \li Extrapolation is done using the time stamp counter (TSC) registers + provided by Pentium CPUs and newer/compatible + types as the cycles counter. On SMP / multicore CPUs those + counters may not be synchronized, so this works only correctly + if all cycles counter values are taken from the same CPU. + To achieve this the process CPU affinity is by default set to + the first CPU at program start, which means all threads of this + process are executed only on that CPU. + + Associated functions: + + \li mbg_xhrt_poll_thread_create() + \li mbg_get_xhrt_cycles_frequency() + \li mbg_get_xhrt_time_as_pcps_hr_time() + \li mbg_get_xhrt_time_as_filetime() + \li mbg_xhrt_poll_thread_stop() + + */ + + /** + \file + \copydoc group_xhrt + + Build environment settings: + + Add "mbglib\include" directory to the include search path. + Link the main file plus the required import libraries, + in this case mbgdevio.lib and mbgutil.lib. + + The import libraries are located:<br> + <B>"mbglib\lib\msc"</B> for Microsoft C compilers<br> + <B>"mbglib\lib\bc"</B> for Inprise/Borland compilers + + */ + #include <mbgdevio.h> #include <mbgutil.h> @@ -47,12 +81,16 @@ // Configuration -#define N_LOOPS 30 // Number of time stamps -#define USE_PCPS_HR_TIME 1 // if 1, use PCPS_HR_TIME as output format, if 0, use FILETIME. +#define N_LOOPS 30 /** Number of time stamps */ +#define USE_PCPS_HR_TIME 1 /** Select 1 to use PCPS_HR_TIME as output format. Select 0 to use Windows FILETIME. */ +/** + Union to do a simple conversion between + a Windows FILETIME to a 64 Bit value. +*/ typedef union { - FILETIME ft; + FILETIME ft; DWORDLONG dwl; } FT_DWL; @@ -79,7 +117,6 @@ void print_drvr_info( void ) exit( 1 ); } - rc = mbg_get_drvr_info( dh, &drvr_info ); mbg_close_device( &dh ); @@ -114,12 +151,12 @@ void print_dev_info( MBG_DEV_HANDLE dh, if ( rc == PCPS_SUCCESS ) { _pcps_port_base( p_dev, 0 ) ? - printf( " %s at port %03Xh\n", - _pcps_fw_id( p_dev ), + printf( " %s, SN: %s at port %03Xh\n", + _pcps_fw_id( p_dev ), _pcps_sernum( p_dev ), _pcps_port_base( p_dev, 0 ) ) : - printf( " %s\n", - _pcps_fw_id( p_dev ) + printf( " %s, SN: %s\n", + _pcps_fw_id( p_dev ), _pcps_sernum( p_dev ) ); } else @@ -187,15 +224,15 @@ int main( int argc, char* argv[] ) printf( "\n" ); - // Only clocks with HR time support the extrapolation feature + // Start a polling thread and get extrapolated time stamps from the DLL. + // Only devices which support PCPS_HR_TIME support the extrapolation feature. if ( _pcps_has_hr_time( &dev ) ) { int rc; int this_loops = N_LOOPS; MBG_POLL_THREAD_INFO poll_thread_info = { { { { 0 } } } }; - - // Try to start the polling thread in mbgdevio.dll + // Start the polling thread. rc = mbg_xhrt_poll_thread_create( &poll_thread_info, dh, 0, 0 ); if ( rc != MBG_SUCCESS ) @@ -218,7 +255,8 @@ int main( int argc, char* argv[] ) TIME_ZONE_INFORMATION tzi; #endif - // The frequency of the PC's cycles counter has to be computed. + // Calculate the cycles frequency with high accuracy with the help + // of the reference clock. rc = mbg_get_xhrt_cycles_frequency( &poll_thread_info.xhrt_info, &freq_hz ); if ( rc != MBG_SUCCESS ) @@ -244,13 +282,11 @@ int main( int argc, char* argv[] ) printf( "\n" ); has_printed_msg = 0; } - - // Now the frequency is computed, we can start to get the time stamps. - - // Get an extrapolated time stamp bracketed by - // mbg_get_pc_cycles() calls to compute the access time + + // Get PC cycles to compute the access time. mbg_get_pc_cycles( &cyc_1 ); + // Request a time stamp #if USE_PCPS_HR_TIME rc = mbg_get_xhrt_time_as_pcps_hr_time( &poll_thread_info.xhrt_info, &hrt ); #else @@ -262,12 +298,12 @@ int main( int argc, char* argv[] ) if ( rc != MBG_SUCCESS ) goto fail; - // compute the access_time + // Compute the access_time access_time = ( (double) cyc_2 - (double) cyc_1 ) / (double) ( (int64_t) freq_hz ) * (double) 1E6; #if USE_PCPS_HR_TIME - // Convert PCPS_HR_TIME into a readable timestamp with fractions as local time. + // Convert PCPS_HR_TIME into a readable time stamp with fractions as local time. mbg_str_pcps_hr_tstamp_utc( ws, sizeof( ws ), &hrt ); printf( "Extrapolated ref time (UTC) : %s (%.3f us)\n", ws, access_time ); diff --git a/c/demo/mbgdevio/xhrtime.exe b/c/demo/mbgdevio/xhrtime.exe Binary files differdeleted file mode 100644 index 2aafa3a..0000000 --- a/c/demo/mbgdevio/xhrtime.exe +++ /dev/null |