diff options
author | Martin Burnicki <martin.burnicki@meinberg.de> | 2011-05-19 12:00:00 +0200 |
---|---|---|
committer | Martin Burnicki <martin.burnicki@meinberg.de> | 2011-05-19 12:00:00 +0200 |
commit | 9444a60b913b8c5ff6946d58087fbe6cee8ce887 (patch) | |
tree | 7d7b2c1f443f9bdaa2ee05d76633b82546b7dcd4 | |
parent | 384267346c5824f02bac7265e45f8937c9a7b48b (diff) | |
download | mbgsdk-win-MeinbergAPIC#Wrapper.tar.gz mbgsdk-win-MeinbergAPIC#Wrapper.zip |
Add an example C# wrapper for mbgdevioMeinbergAPIC#Wrapper
The code was provided by a customer
-rw-r--r-- | c#/demo/mbgdevio/Constants.cs | 85 | ||||
-rw-r--r-- | c#/demo/mbgdevio/Interop.cs | 239 | ||||
-rw-r--r-- | c#/demo/mbgdevio/MeinbergAPI.csproj | 69 | ||||
-rw-r--r-- | c#/demo/mbgdevio/MeinbergDevice.cs | 291 | ||||
-rw-r--r-- | c#/demo/mbgdevio/MeinbergDeviceManager.cs | 90 | ||||
-rw-r--r-- | c#/demo/mbgdevio/Properties/AssemblyInfo.cs | 36 | ||||
-rw-r--r-- | c#/demo/mbgdevio/Structures.cs | 170 |
7 files changed, 980 insertions, 0 deletions
diff --git a/c#/demo/mbgdevio/Constants.cs b/c#/demo/mbgdevio/Constants.cs new file mode 100644 index 0000000..d781352 --- /dev/null +++ b/c#/demo/mbgdevio/Constants.cs @@ -0,0 +1,85 @@ +using System; + +namespace MeinbergAPI +{ + public partial class Interop + { + + // Please note: + // IRIG receiver cards may set the PCPS_INVT bit also if the card//s ref time offset + // to UTC has not yet been configured, or if the on-board date does not match the + // day-of-year number of the incoming IRIG signal. The reason for this is to avoid + // accepting wrong times from the IRIG signal due to the ambiguity of the time and + // day-of-year from the IRIG signal. + + /// <summary> + /// This value is returned by the API functions on success + /// </summary> + public const short PCPS_SUCCESS = 0; + + #region Bit masks used with both the status fields of the PCPS_TIME structure and the PCPS_HR_TIME structure + + /// <summary> + /// GPS receiver has not verified its position + /// </summary> + public const short PCPS_FREER = 0x1; + + /// <summary> + /// Daylight saving enabled + /// </summary> + public const short PCPS_DL_ENB = 0x2; + + /// <summary> + /// Clock has synced at least once after power up + /// </summary> + public const short PCPS_SYNCD = 0x4; + + /// <summary> + /// A change in daylight saving is announced + /// </summary> + public const short PCPS_DL_ANN = 0x8; + + /// <summary> + /// The returned time is UTC + /// </summary> + public const short PCPS_UTC = 0x10; + + /// <summary> + /// Leap second is announced + /// </summary> + public const short PCPS_LS_ANN = 0x20; + + /// <summary> + /// The current time was set via PC interface + /// </summary> + public const short PCPS_IFTM = 0x40; + + /// <summary> + /// Invalid time because battery was disconnected. + /// </summary> + public const short PCPS_INVT = 0x80; + + #endregion + + #region Bit masks used with the status fields of the PCPS_HR_TIME structure only + + /// <summary> + /// current second is leap second + /// </summary> + public const short PCPS_LS_ENB = 0x100; + + /// <summary> + /// Antenna failure + /// </summary> + public const short PCPS_ANT_FAIL = 0x200; + + #endregion + + #region These bits are used only if the PCPS_HR_TIME structure PCPS_HR_TIME contains a user capture event + + public const short PCPS_UCAP_OVERRUN = 0x2000; // events interval too short + public const short PCPS_UCAP_BUFFER_FULL = 0x4000; // events read too slow + + #endregion + } +} diff --git a/c#/demo/mbgdevio/Interop.cs b/c#/demo/mbgdevio/Interop.cs new file mode 100644 index 0000000..1d5b2a4 --- /dev/null +++ b/c#/demo/mbgdevio/Interop.cs @@ -0,0 +1,239 @@ +using System; +using System.Runtime.InteropServices; + +namespace MeinbergAPI +{ + /// <summary> + /// Not all API calls included below are supported by any Meinberg + /// plug-in card. Calls to functions which are not supported by a device + /// don't do any harm, they just return an error code to the application. + /// However, every API call to an unsupported function results in a log entry + /// in the Windows application event log, so an application should first check + /// whether such an API call is supported by the specific device. API calls + /// which are not supported by each device are commented accordingly. + /// </summary> + public partial class Interop + { + #region General functions supported by all Meinberg devices + + /// <summary> + /// Returns the number of radio clock devices detected + /// If this function returns 0, then no devices has been detected. + /// </summary> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_find_devices", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_find_devices(); + + /// <summary> + /// Opens the device with given index and retrieve a handle to the device + /// E.g. if n devices have been found, valid indices are 0..n-1 + /// </summary> + /// <param name="i">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <returns>The opened device's handle.</returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_open_device", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_open_device(int i); + + /// <summary> + /// Closes the device and release the device handle. + /// The device handle value will be set to 0. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <returns>Will always return 0.</returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_close_device", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_close_device(ref int h); + + /// <summary> + /// Reads date, time, and status from the device referenced by handle h. + /// This function is supported by all Meinberg plug-in boards and returns + /// date and time in human readable format (calendar date and time). + /// However, the resolution of time is limited to 10 milliseconds. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <param name="t">The device's current time.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_get_time", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_get_time(int h, ref PCPS_TIME t); + + #endregion + + /// <summary> + /// The functions below read high resolution time plus status from the device + /// referenced by handle h. + /// These functions are NOT supported by all Meinberg plug-in boards, and the + /// effective resolution of the HR time depends on the characteristics of the + /// specific device. + /// </summary> + #region Functions for high-resolution time + + /// <summary> + /// Checks whether the device referenced by handle h supports HR time. + /// If it does then the value returned for f is not 0. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <param name="f">0 if not supported. If any other value, then supported.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_dev_has_hr_time", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_dev_has_hr_time(int h, ref int f); + + /// <summary> + /// Reads a HR time stamp from the board. The returned time stamp may be biased + /// by a latency due to the IOCTL call performed by the function. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <param name="t">The HR timestamp to set.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_get_hr_time", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_get_hr_time(int h, ref PCPS_HR_TIME t); + + /// <summary> + /// Reads a HR time stamp from the board plus a performance counter value + /// associated to that time stamp. The performance counter value can be used + /// by the application to compensate the latency mentioned above. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <param name="p">The performance counter to set.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_get_hr_time_cycles", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_get_hr_time_cycles(int h, ref PCPS_HR_TIME_CYCLES p); + + /// <summary> + /// Reads a HR time stamp from the board and compensates for the specified latency. Return the compensated + /// time stamp, and optionally also return the latency value in 100 nanosecond units. + /// If the application does not need the latency value then a null pointer may be passed + /// for parameter l. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <param name="t">The compensated timestamp to set.</param> + /// <param name="l">The latency. Can be nulled if not required.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_get_hr_time_comp", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_get_hr_time_comp(int h, ref PCPS_HR_TIME t, ref int l); + + #endregion + + /// <summary> + /// The functions below can be used with the capture buffer available on some cards. + /// These functions are NOT supported by all Meinberg plug-in boards, and the + /// effective accuracy of the time capture events depends on the characteristics + /// of the specific device. + /// </summary> + #region Functions for the event buffer + + /// <summary> + /// Check whether the device referenced by handle h provides support for + /// user capture events. + /// If it does then the value returned for f is not 0. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <param name="f">0 if not supported. If any other value, then supported.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_dev_has_ucap", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_dev_has_ucap(int h, ref int f); + + /// <summary> + /// Clear the on-board user capture FIFO buffer + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_clr_ucap_buff", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_clr_ucap_buff(int h); + + /// <summary> + /// Retrieve the maximum number of events that can be stored in the on-board + /// FIFO buffer, and the number of events currently saved in the buffer. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <param name="p">The maximum number of entries.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_get_ucap_entries", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_get_ucap_entries(int h, ref PCPS_UCAP_ENTRIES p); + + /// <summary> + /// Retrieve an entry from the on-board user capture FIFO buffer. The returned entry + /// is removed from the buffer. If no event is available in the buffer, i.e. the buffer + /// is empty, then both the seconds and fractions of the returned time stamp are 0. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <param name="t">The returned entry.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_get_ucap_event", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_get_ucap_event(int h, ref PCPS_HR_TIME t); + + #endregion + + /// <summary> + /// The functions below can be used to read the receiver position from GPS add-in + /// cards. This is NOT supported by non-GPS add-in cards, so there's another + /// function which checks whether a specific device is a GPS receiver. + /// </summary> + #region Functions for position + /// <summary> + /// Check whether the device referenced by handle h is a GPS receiver. + /// If it is then the value returned for f is not 0. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <param name="f">0 if not supported. If any other value, then supported.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_dev_is_gps", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_dev_is_gps(int h, ref int f); + + /// <summary> + /// Read the current receiver position. + /// </summary> + /// <param name="h">The device handle as returned by <see cref="mbg_find_devices"/>.</param> + /// <param name="p">The receiver's current position.</param> + /// <returns></returns> + [DllImport("mbgdevio.dll", EntryPoint = "mbg_get_gps_pos", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_get_gps_pos(int h, ref MBG_RCVR_POS p); + #endregion + + #region Service Functions + + /// <summary> + /// Returns the version number of the DLL + /// <returns>The version number.</returns> + /// </summary> + [DllImport("mbgsvcio.dll", EntryPoint = "mbg_get_gps_pos", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbgsvcio_get_version(); + + /// <summary> + /// Checks that the DLL interface specification version is compatible with the + /// DLL version. Pass the MBGSVCIO_VERSION code from <see cref="mbgsvcio_get_version"/> as parameter. + /// <returns>PCPS_SUCCESS on success.</returns> + /// </summary> + [DllImport("mbgsvcio.dll", EntryPoint = "mbgsvcio_check_version", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbgsvcio_check_version(); + + /// <summary> + /// Checks if the Meinberg time adjustment service is active. + /// <returns>a positive value if the service is active + /// 0 if the service is not active</returns> + [DllImport("mbgsvcio.dll", EntryPoint = "mbg_time_adjustment_active", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_time_adjustment_active(); + + /// <summary> + /// Checks if the ref time source (e.g. radio clock) used by the Meinberg + /// time adjustment service is accessible. This should be always the case + /// with PCI plug-in boards, but this can also fail with an external clock + /// if for example the serial connection is broken or the device is powered + /// off. + /// <returns>a positive value if the ref time source is accessible + /// 0 if the ref time source is not accessible + /// a negative number if the status could not be determined.</returns> + /// </summary> + [DllImport("mbgsvcio.dll", EntryPoint = "mbg_ref_time_accessible", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_ref_time_accessible(); + + /// <summary> + /// Queries the status of the ref time source (e.g. radio clock) used by the + /// Meinberg time adjustment service. + /// <returns>a positive value if the ref time source is accessible + /// 0 if the ref time source is not accessible + /// a negative number if the status could not be determined.</returns> + /// </summary> + [DllImport("mbgsvcio.dll", EntryPoint = "mbg_get_ref_time_status", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern int mbg_get_ref_time_status(); + + #endregion + } +} diff --git a/c#/demo/mbgdevio/MeinbergAPI.csproj b/c#/demo/mbgdevio/MeinbergAPI.csproj new file mode 100644 index 0000000..bd7a2b4 --- /dev/null +++ b/c#/demo/mbgdevio/MeinbergAPI.csproj @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>8.0.30703</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{86FE288D-4091-4CB7-8431-DF82B78BD79B}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>MeinbergAPI</RootNamespace> + <AssemblyName>MeinbergAPI</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <SccProjectName>SAK</SccProjectName> + <SccLocalPath>SAK</SccLocalPath> + <SccAuxPath>SAK</SccAuxPath> + <SccProvider>SAK</SccProvider> + <TargetFrameworkProfile /> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Constants.cs" /> + <Compile Include="MeinbergDevice.cs" /> + <Compile Include="Interop.cs" /> + <Compile Include="MeinbergDeviceManager.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Structures.cs" /> + </ItemGroup> + <ItemGroup> + <Content Include="mbgdevio.dll" /> + <Content Include="mbgsvcio.dll" /> + <Content Include="mbgsvctl.dll" /> + <Content Include="mbgutil.dll" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/c#/demo/mbgdevio/MeinbergDevice.cs b/c#/demo/mbgdevio/MeinbergDevice.cs new file mode 100644 index 0000000..49a03d5 --- /dev/null +++ b/c#/demo/mbgdevio/MeinbergDevice.cs @@ -0,0 +1,291 @@ +using System; + +namespace MeinbergAPI +{ + public class MeinbergDevice + { + #region Private Properties + + private int _DeviceHandle; + private bool _SupportsHRTime; + private bool _SupportsUserCaptureEvents; + private bool _IsGpsReceiver; + + #endregion + + #region Public Properties + + /// <summary> + /// The device's handle. + /// </summary> + public int DeviceHandle + { + get { return _DeviceHandle; } + set { _DeviceHandle = value; } + } + + /// <summary> + /// Specifies whether the device supports HR time. + /// </summary> + public bool SupportsHRTime + { + get { return _SupportsHRTime; } + set { _SupportsHRTime = value; } + } + + /// <summary> + /// Specified whether the device supports User Capture Events. + /// </summary> + public bool SupportsUserCaptureEvents + { + get { return _SupportsUserCaptureEvents; } + set + { + _SupportsUserCaptureEvents = value; + } + } + + /// <summary> + /// Specifies whether the device is a GPS receiver. + /// </summary> + public bool IsGpsReceiver + { + get { return _IsGpsReceiver; } + set + { + _IsGpsReceiver = value; + } + } + + public bool CapabilitiesChecked = false; + + #endregion + + #region Constructors & Destructors + + /// <summary> + /// Initializes an instance of the MeinbergDevice class. + /// </summary> + /// <param name="deviceHandle">The device's handle.</param> + public MeinbergDevice(int deviceHandle) + { + _DeviceHandle = deviceHandle; + } + + /// <summary> + /// Initializes an instance of the MeinbergDevice class. + /// </summary> + /// <param name="deviceHandle">The device's handle.</param> + /// <param name="initializeCapabilities">Specify whether to initialize the class with the device's capabilities.</param> + public MeinbergDevice(int deviceHandle, bool initializeCapabilities) + { + _DeviceHandle = deviceHandle; + if (initializeCapabilities) CheckCapabilities(); + } + + #endregion + + #region Public Methods + + public void CheckCapabilities() + { + int supportsHRTime = -1; + Interop.mbg_dev_has_hr_time(DeviceHandle, ref supportsHRTime); + SupportsHRTime = supportsHRTime != 0; + + int supportsUCETime = -1; + Interop.mbg_dev_has_ucap(DeviceHandle, ref supportsUCETime); + SupportsUserCaptureEvents = supportsUCETime != 0; + + int supportsGps = -1; + Interop.mbg_dev_is_gps(DeviceHandle, ref supportsGps); + IsGpsReceiver = supportsGps != 0; + + CapabilitiesChecked = true; + + } + + public bool Open() + { + return Interop.mbg_open_device(this._DeviceHandle) == this._DeviceHandle; + } + + public bool Close() + { + return Interop.mbg_close_device(ref this._DeviceHandle) == 0; + } + + /// <summary> + /// Gets the time from the device. + /// </summary> + /// <param name="successful">Specifies whether the operation was successful.</param> + /// <returns></returns> + public Interop.PCPS_TIME GetTime(out bool successful) + { + var time = new Interop.PCPS_TIME(); + successful = Interop.mbg_get_time(this._DeviceHandle, ref time) == Interop.PCPS_SUCCESS; + if (successful) + return time; + else + return new Interop.PCPS_TIME(); + } + + /// <summary> + /// Gets high-resolution time from the device. + /// </summary> + /// <param name="successful">Specifies whether the operation was successful.</param> + /// <returns>Returns the time.</returns> + public Interop.PCPS_HR_TIME GetHRTime(out bool successful) + { + if (CapabilitiesChecked) + throw new Exception("Before accessing extended functions, you first have to check the device's capabilities by calling CheckCapabilities."); + + if (!SupportsHRTime) + throw new NotSupportedException("This device does not support high-resolution time."); + + var time = new Interop.PCPS_HR_TIME(); + successful = Interop.mbg_get_hr_time(this._DeviceHandle, ref time) == Interop.PCPS_SUCCESS; + if (successful) + return time; + else + return new Interop.PCPS_HR_TIME(); + } + + /// <summary> + /// Reads a HR time stamp from the board plus a performance counter value + /// associated to that time stamp. + /// </summary> + /// <param name="successful">Specifies whether the operation was successful.</param> + /// <returns>Returns the high-resolution time.</returns> + public Interop.PCPS_HR_TIME_CYCLES GetHRTimeCycles(out bool successful) + { + if (CapabilitiesChecked) + throw new Exception("Before accessing extended functions, you first have to check the device's capabilities by calling CheckCapabilities."); + + if (!SupportsHRTime) + throw new NotSupportedException("This device does not support high-resolution time."); + + var time = new Interop.PCPS_HR_TIME_CYCLES(); + successful = Interop.mbg_get_hr_time_cycles(this._DeviceHandle, ref time) == Interop.PCPS_SUCCESS; + if (successful) + return time; + else + return new Interop.PCPS_HR_TIME_CYCLES(); + } + + /// <summary> + /// Reads a HR time stamp from the board and compensates for the specified latency. + /// </summary> + /// <param name="successful">Specifies whether the operation was successful.</param> + /// <param name="latency">The latency to compensate for (Nullable)</param> + /// <returns>Returns the compensated time stamp, and optionally also return the latency + /// value in 100 nanosecond units.</returns> + public Interop.PCPS_HR_TIME GetHRTimeCycles(out bool successful, out int latency) + { + if (CapabilitiesChecked) + throw new Exception("Before accessing extended functions, you first have to check the device's capabilities by calling CheckCapabilities."); + + if (!SupportsHRTime) + throw new NotSupportedException("This device does not support high-resolution time."); + + var time = new Interop.PCPS_HR_TIME(); + int l = -1; + + successful = Interop.mbg_get_hr_time_comp(this._DeviceHandle, ref time, ref l) == Interop.PCPS_SUCCESS; + if (successful) + { + latency = l; + return time; + } + else + { + latency = -1; + return new Interop.PCPS_HR_TIME(); + } + } + + /// <summary> + /// + /// </summary> + /// <returns>Returns whether the operation was successful.</returns> + public bool ClearOnboardBuffers() + { + if (CapabilitiesChecked) + throw new Exception("Before accessing extended functions, you first have to check the device's capabilities by calling CheckCapabilities."); + + if (!SupportsHRTime) + throw new NotSupportedException("This device does not support user events."); + + return Interop.mbg_clr_ucap_buff(this._DeviceHandle) == Interop.PCPS_SUCCESS; + } + + /// <summary> + /// Retrieve the maximum number of events that can be stored in the on-board FIFO buffer, + /// and the number of events currently saved in the buffer. + /// </summary> + /// <param name="successful">Specifies whether the operation was successful.</param> + /// <returns>Returns the entries in the buffer. </returns> + public Interop.PCPS_UCAP_ENTRIES GetEvents(out bool successful) + { + if (CapabilitiesChecked) + throw new Exception("Before accessing extended functions, you first have to check the device's capabilities by calling CheckCapabilities."); + + if (!SupportsHRTime) + throw new NotSupportedException("This device does not support user events."); + + var allEvents = new Interop.PCPS_UCAP_ENTRIES(); + successful = Interop.mbg_get_ucap_entries(this._DeviceHandle, ref allEvents) == Interop.PCPS_SUCCESS; + if (successful) + return allEvents; + else + return new Interop.PCPS_UCAP_ENTRIES(); + } + + /// <summary> + /// Retrieve an entry from the on-board user capture FIFO buffer. The returned entry + /// is removed from the buffer. + /// </summary> + /// <param name="successful">Specifies whether the operation was successful.</param> + /// <returns>Returns the entry requested. If no event is available in the buffer, i.e. the buffer + /// is empty, then both the seconds and fractions of the returned time stamp are 0.</returns> + public Interop.PCPS_HR_TIME GetEvent(out bool successful) + { + if (CapabilitiesChecked) + throw new Exception("Before accessing extended functions, you first have to check the device's capabilities by calling CheckCapabilities."); + + if (!SupportsHRTime) + throw new NotSupportedException("This device does not support user events."); + + var singleEvent = new Interop.PCPS_HR_TIME(); + successful = Interop.mbg_get_ucap_event(this._DeviceHandle, ref singleEvent) == Interop.PCPS_SUCCESS; + if (successful) + return singleEvent; + else + return new Interop.PCPS_HR_TIME(); + } + + /// <summary> + /// Gets the device's current GPS position. + /// </summary> + /// <param name="successful">Specifies whether the operation was successful.</param> + /// <returns>Returns the GPS position.</returns> + public Interop.MBG_RCVR_POS GetDeviceGPSPosition(out bool successful) + { + if (CapabilitiesChecked) + throw new Exception("Before accessing extended functions, you first have to check the device's capabilities by calling CheckCapabilities."); + + if (!SupportsHRTime) + throw new NotSupportedException("This device does not support GPS functionality."); + + var gpsPosition = new Interop.MBG_RCVR_POS(); + successful = Interop.mbg_get_gps_pos(this._DeviceHandle, ref gpsPosition) == Interop.PCPS_SUCCESS; + if (successful) + return gpsPosition; + else + return new Interop.MBG_RCVR_POS(); + } + + #endregion + + } +} diff --git a/c#/demo/mbgdevio/MeinbergDeviceManager.cs b/c#/demo/mbgdevio/MeinbergDeviceManager.cs new file mode 100644 index 0000000..da1e570 --- /dev/null +++ b/c#/demo/mbgdevio/MeinbergDeviceManager.cs @@ -0,0 +1,90 @@ +using System; +using System.Linq; +using System.Collections.Generic; + +namespace MeinbergAPI +{ + public class MeinbergDeviceManager + { + #region Private Properties + + private List<MeinbergDevice> _Devices; + + #endregion + + #region Public Properties + + /// <summary> + /// The devices currently attached to the system. + /// </summary> + public List<MeinbergDevice> Devices + { + get { return _Devices; } + } + + #endregion + + #region Constructors & Destructors + + /// <summary> + /// Initializes an instance of the MeinbergDeviceManager. + /// Devices are loaded and capabilities for each device is checked during + /// instantiation. + /// </summary> + public MeinbergDeviceManager() + { + //TODO: check dll version + LoadDevices(); + } + + #endregion + + #region Private Methods + + private void LoadDevices() + { + _Devices = new List<MeinbergDevice>(); + + int noOfDevices = Interop.mbg_find_devices(); + + for (int i = 0; i < noOfDevices - 1; i++) + { + Devices.Add(new MeinbergDevice(Interop.mbg_open_device(i), true)); + Devices[i].Close(); + } + } + + #endregion + + #region Public Methods + + /// <summary> + /// Gets all the Meinberg devices supporting GPS functionality. + /// </summary> + /// <returns>A list of Meinberg devices supporting GPS functionality.</returns> + public List<MeinbergDevice> GetDevicesSupportingGPS() + { + return (from device in _Devices where device.IsGpsReceiver select device).ToList(); + } + + /// <summary> + /// Gets all the Meinberg devices supporting high-resolution time. + /// </summary> + /// <returns>A list of Meinberg devices supporting high-resolution time.</returns> + public List<MeinbergDevice> GetDevicesSupportingHRTime() + { + return (from device in _Devices where device.SupportsHRTime select device).ToList(); + } + + /// <summary> + /// Gets all the Meinberg devices supporting user events. + /// </summary> + /// <returns>A list of Meinberg devices supporting user events.</returns> + public List<MeinbergDevice> GetDevicesSupportingUserEvents() + { + return (from device in _Devices where device.SupportsUserCaptureEvents select device).ToList(); + } + + #endregion + } +} diff --git a/c#/demo/mbgdevio/Properties/AssemblyInfo.cs b/c#/demo/mbgdevio/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ce048c9 --- /dev/null +++ b/c#/demo/mbgdevio/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MeinbergAPI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Inivit Systems Pty. Ltd.")] +[assembly: AssemblyProduct("MeinbergAPI")] +[assembly: AssemblyCopyright("Copyright © Inivit Systems Pty. Ltd. 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("1c4cfb7c-0ae6-4033-b512-1bbde7522833")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/c#/demo/mbgdevio/Structures.cs b/c#/demo/mbgdevio/Structures.cs new file mode 100644 index 0000000..a8afb21 --- /dev/null +++ b/c#/demo/mbgdevio/Structures.cs @@ -0,0 +1,170 @@ +using System; +using System.Runtime.InteropServices; + +namespace MeinbergAPI +{ + public partial class Interop + { + #region Time Structures + + /// <summary> + /// The DLL version required by this interface specification + /// </summary> + public const short MBGDEVIO_VERSION = 0x212; + + /// <summary> + /// This structure is passed to the function mbg_get_time to read date, time, and status + /// </summary> + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct PCPS_TIME + { + // 0..99 + public byte sec100; + // 0..59, 60 if leap second + public byte sec; + // 0..59 + public byte min; + // 0..23 + public byte hour; + // 1..31 + public byte mday; + // 1..7, 1 = Monday + public byte wday; + // 1..12 + public byte month; + // 0..99 (year modulo 100) + public byte year; + // flag bits, see below + public byte status; + // 0..255 + public byte signal; + // [h] signed!! (UTC = t - offs_utc) + public byte offs_utc; + } + + /// <summary> + /// This structure has been introduced to be able to handle high resolution time stamps. + /// </summary> + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct PCPS_TIME_STAMP + { + // UInt32, seconds since 1970 (UTC) + public int sec; + // UInt32, fractions of second ( &HFFFFFFFF == 0.9999.. sec) + public int frac; + } + + /// <summary> + /// This structure holds a HR time stamp, plus UTC offset and status info + /// </summary> + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct PCPS_HR_TIME + { + public PCPS_TIME_STAMP tstamp; + // [sec] signed!! (local time = tstamp + offs_utc) + public int utc_offs; + // flag bits, see below + public short status; + // 0..255 + public byte signal; + } + + /// <summary> + /// This structure holds a HR time plus an associated Windows + /// performance counter value which can be used to relate performance + /// counter values to the current time. Please note that an application + /// must also determine the Windows performance counter frequency in order + /// to convert differences of performance counter values to time intervals. + /// </summary> + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct PCPS_HR_TIME_CYCLES + { + // UInt64, performance counter value + public long cycles; + // associated HR time + public PCPS_HR_TIME t; + } + + /// <summary> + /// This structure contains the maximum number of entries of an on-board + /// user capture FIFO buffer plus the number of currently used entries. + /// </summary> + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct PCPS_UCAP_ENTRIES + { + // the number of saved capture events + public int used; + // capture buffer size + public int max; + } + + #endregion + + #region Structures for Geographic Position + + /// <summary> + /// This type is used to hold a geographic position in cartesian coordinates. + /// </summary> + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct MBG_POS_XYZ + { + // x coordinate, in meters + public double x; + // y coordinate, in meters + public double y; + // z coordinate, in maters + public double z; + } + + /// <summary> + /// This type is used to pass a geographic position in raw geographic coordinates. + /// </summary> + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct MBG_POS_LLA + { + // latitude, in radians + public double lat; + // longitude, in radians + public double lon; + // altitude (height above ellipsoid), in meters + public double alt; + } + + /// <summary> + /// This type is used in conjuction with <see cref="MBG_RCVR_POS" /> to aid in + /// storing the receiver position in a human readable format + /// </summary> + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct MBG_DMS + { + // ASCII code of 'N', 'E', 'S' or 'W' + public short prefix; + // [0...90 (lat) or 0...180 (lon)] + public short deg; + // [0...59] + public short min; + // [0...59.999] + public double sec; + } + + /// <summary> + /// This type is used to store a geographic coordinate in broken-down (human readable) format. + /// </summary> + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct MBG_RCVR_POS + { + // always WGS84 ECEF coordinates + public MBG_POS_XYZ xyz; + // depending on the ellipsoid used for reference + public MBG_POS_LLA lla; + // longitude in degrees, minutes, seconds + public MBG_DMS longitude; + // latitude in degrees, minutes, seconds + public MBG_DMS latitude; + // ellipsoid used for reference + public short ellipsoid; + } + + #endregion + } +} |