Big changes

This commit is contained in:
Duc
2025-03-13 12:04:22 -07:00
parent c689fcb7f9
commit ffa9905494
748 changed files with 199255 additions and 3743 deletions

View File

@@ -0,0 +1,512 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using Automation.BDaq;
using NLog;
using Raytheon.Common;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
/// <summary>
/// A class that implements a Context DIO card
/// </summary>
public class DIOAdvantech : IGeneralIO, IDisposable
{
#region PrivateClassMembers
private InstantDiCtrl _inputCtrl;
private InstantDoCtrl _outputCtrl;
private string _name;
private readonly int _deviceNum;
private readonly SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
private ErrorCode errorCode = ErrorCode.Success;
private int _numChannelPerPort = 8;
private int _channelStartIndex = 0;
private int _numInputChannels;
private int _numOutputChannels;
private bool _shallWeInitializeOutput = false;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#endregion
#region PrivateClassFunctions
~DIOAdvantech()
{
Dispose(false);
}
private static bool BioFailed(ErrorCode err)
{
return err < ErrorCode.Success && err >= ErrorCode.ErrorHandleNotValid;
}
/// <summary>
/// Dispose the object's resources
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
if (_state == State.Ready)
{
Shutdown();
_state = State.Uninitialized;
}
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
/// <summary>
/// Because the user has to define each channel number in the config file, some people will use 0 or 1 start their starting channel number
/// Whether the user prefers 0 or 1 as their starting channel number, this function will then calculate the port index and bit index that the
/// driver API needs to be able to drive/read the signal
/// <param name="signalName"></param>
/// <param name="portIndex">portIndex will range from 0..N</param>
/// <param name="bitIndex">bitIndex will range from 0..M</param>
/// </summary>
private void GetPortIndexAndBitIndex(string signalName, out int portIndex, out int bitIndex)
{
portIndex = (int)(Math.Ceiling((double)((int)_signalNameToChannelMap[signalName].channelNumber + Math.Abs(_channelStartIndex - 1)) / (double)_numChannelPerPort) - 1.0);
int multiplier = ((int)_signalNameToChannelMap[signalName].channelNumber + _numChannelPerPort) / _numChannelPerPort;
bitIndex = (((int)_signalNameToChannelMap[signalName].channelNumber + _numChannelPerPort) - (_numChannelPerPort * multiplier)) - _channelStartIndex;
if (bitIndex < 0)
{
bitIndex = _numChannelPerPort - 1;
}
}
/// <summary>
/// Invert Contec DIO bits.
/// </summary>
private byte InvertBit(byte bitValue)
{
if (bitValue == 0)
{
return 1;
}
else if (bitValue == 1)
{
return 0;
}
else
{
throw new Exception("Unexpected input value: " + bitValue.ToString());
}
}
private void ReadBit(int port, int bitNum, out byte data)
{
_inputCtrl.ReadBit(port, bitNum, out data);
}
private void WriteBit(int port, int bitNum, byte bitState)
{
errorCode = _outputCtrl.WriteBit(port, bitNum, bitState);
if (BioFailed(errorCode))
{
throw new Exception("call to WriteBit returned error: " + errorCode.ToString() + " on card: " + _name); ;
}
}
#endregion
#region PublicClassFunctions
/// <summary>
/// DIOAdvantech factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOAdvantech(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
if (!Path.IsPathRooted(dioModuleDefPath))
dioModuleDefPath = Path.GetFullPath(Path.Combine(assemblyFolder, dioModuleDefPath));
IConfigurationFile dioModuleConfig = new ConfigurationFile(dioModuleDefPath);
Boolean.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.SHALL_WE_DRIVE_OUTPUT_UPON_INITIALIZATION.ToString()), out _shallWeInitializeOutput);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.DEVICE_NUMBER.ToString()), out _deviceNum);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_INPUT_CHANNELS.ToString()), out _numInputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_OUTPUT_CHANNELS.ToString()), out _numOutputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_CHANNELS_PER_PORT.ToString()), out _numChannelPerPort);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.CHANNEL_START_INDEX.ToString()), out _channelStartIndex);
if (!(_channelStartIndex == 0 || _channelStartIndex == 1))
{
throw new Exception($"The value for key {ConfigIni.CHANNEL_START_INDEX.ToString()} in section {Name} must be 0 or 1 in {dioModuleDefPath}");
}
List<string> outputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.OUTPUT_SIGNALS}");
List<string> intputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.INPUT_SIGNALS}");
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
string[] infoTokens = iniLine.Split('|');
if (infoTokens.Length != 2)
{
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} does not contain 2 tokens");
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
}
_state = State.Uninitialized;
_selfTestResult = SelfTestResult.Unknown;
}
/// <summary>
///
/// </summary>
public DIOAdvantech(string deviceName, int deviceNum)
{
_deviceNum = deviceNum;
_name = deviceName;
_logger = LogManager.GetCurrentClassLogger();
_state = State.Uninitialized;
_selfTestResult = SelfTestResult.Unknown;
}
public bool ClearErrors()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
//_outputCtrl.SelectedDevice; Need to see what the card returns for this
return "This is a Advantech DIO Card " + _name;
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels+_channelStartIndex} on card " + _name);
}
GetPortIndexAndBitIndex(signalName, out int portIndex, out int bitIndex);
ReadBit(portIndex, bitIndex, out byte data);
return (IODatatypes.BitState)(data);
}
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
//@@@ do we need both of these? DO can read and write. Read may be for internal read back
_inputCtrl = new InstantDiCtrl();
_outputCtrl = new InstantDoCtrl();
_inputCtrl.SelectedDevice = new DeviceInformation(_deviceNum);
_outputCtrl.SelectedDevice = new DeviceInformation(_deviceNum);
if (_shallWeInitializeOutput)
{
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelMap)
{
if (item.Value.initialValue != -1)
{
SetBit(item.Key, (IODatatypes.BitState)item.Value.initialValue);
}
}
}
_state = State.Ready;
}
else
{
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
/// Return list of signal names
/// </summary>
public List<string> GetSignalNames()
{
return new List<string>(_signalNameToChannelMap.Keys);
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
// card does not support self test
//throw new NotImplementedException("card does not support self test" + " on card " + _name);
throw new NotImplementedException();
}
}
public void Reset()
{
lock (_syncObj)
{
Shutdown();
Initialize();
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <param name="state"> high(open) or low(closed) </param>
///
public void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels +_channelStartIndex} on card " + _name);
}
GetPortIndexAndBitIndex(signalName, out int portIndex, out int bitIndex);
WriteBit(portIndex, bitIndex, (byte)state);
}
}
public void SetTristate(string signalName)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
public void Shutdown()
{
lock (_syncObj)
{
if (_state == State.Ready)
{
_outputCtrl.Dispose();
_inputCtrl.Dispose();
_state = State.Uninitialized;
}
}
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
#endregion
}
}

View File

@@ -0,0 +1,139 @@
// **********************************************************************************************************
// DIOAdvantechFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOAdvantechFactory")]
public class DIOAdvantechFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public DIOAdvantechFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOAdvantechFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOAdvantech(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
else
return new DIOAdvantech(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.DIOAdventech</AssemblyName>
<Product>DIO Adventech implementation</Product>
<Description>Digital IO Adventech implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
<PackageReference Include="Raytheon.Instruments.GeneralIO.Contracts" Version="1.7.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DIOSim\DIOSim.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Automation.BDaq4">
<HintPath>..\..\Common\COTS\Advantech\Automation.BDaq4.dll</HintPath>
</Reference>
</ItemGroup>
<!-- Copy all *.dlls and *.pdb in the output folder to a temp folder -->
<Target Name="CopyFiles" AfterTargets="AfterBuild">
<ItemGroup>
<FILES_1 Include="$(OutDir)*.dll" />
<FILES_2 Include="$(OutDir)*.pdb" />
</ItemGroup>
<Copy SourceFiles="@(FILES_1)" DestinationFolder="$(HalTempFolder)" />
<Copy SourceFiles="@(FILES_2)" DestinationFolder="$(HalTempFolder)" />
</Target>
</Project>

View File

@@ -0,0 +1,718 @@
//============================================================-
// CDIOCS.CS
// Class file for CONTEC Digital I/O device
// CONTEC.Co.,Ltd.
//============================================================-
using System;
using System.Runtime.InteropServices;
public enum CdioConst
{
//-------------------------------------------------
// Type definition
//-------------------------------------------------
DEVICE_TYPE_ISA = 0, // ISA or C bus
DEVICE_TYPE_PC = 1, // PCI bus
DEVICE_TYPE_PCMCIA = 2, // PCMCIA
DEVICE_TYPE_USB = 3, // USB
DEVICE_TYPE_FIT = 4, // FIT
DEVICE_TYPE_CARDBUS = 5, // CardBus
//-------------------------------------------------
// Parameters
//-------------------------------------------------
// I/O(for Sample)
DIO_MAX_ACCS_PORTS = 256,
// DioNotifyInt:Logic
DIO_INT_NONE = 0,
DIO_INT_RISE = 1,
DIO_INT_FALL = 2,
// DioNotifyTrg:TrgKind
DIO_TRG_RISE = 1,
DIO_TRG_FALL = 2,
// Message
DIOM_INTERRUPT = 0x1300,
DIOM_TRIGGER = 0x1340,
DIO_DMM_STOP = 0x1350,
DIO_DMM_COUNT = 0x1360,
// Device Information
IDIO_DEVICE_TYPE = 0, // device type. Param1:short
IDIO_NUMBER_OF_8255 = 1, // Number of 8255 chip. Param1:int
IDIO_IS_8255_BOARD = 2, // Is 8255 board? Param1:BOOL(True/False)
IDIO_NUMBER_OF_DI_BIT = 3, // Number of digital input bit. Param1:int
IDIO_NUMBER_OF_DO_BIT = 4, // Number of digital outout bit. Param1:int
IDIO_NUMBER_OF_DI_PORT = 5, // Number of digital input port. Param1:int
IDIO_NUMBER_OF_DO_PORT = 6, // Number of digital output port. Param1:int
IDIO_IS_POSITIVE_LOGIC = 7, // Is positive logic? Param1:BOOL(True/False)
IDIO_IS_ECHO_BACK = 8, // Can echo back output port? Param1:BOOL(True/False)
IDIO_IS_DIRECTION = 9, // Can DioSetIoDirection function be used? Param1:int(1:true, 0:false)
IDIO_IS_FILTER = 10, // Can digital filter be used? Param1:int(1:true, 0:false)
IDIO_NUMBER_OF_INT_BIT = 11, // Number of interrupt bit. Param1:short
// DM
// Direction
PI_32 = 1,
PO_32 = 2,
PIO_1616 = 3,
DIODM_DIR_IN = 0x1,
DIODM_DIR_OUT = 0x2,
// Start
DIODM_START_SOFT = 1,
DIODM_START_EXT_RISE = 2,
DIODM_START_EXT_FALL = 3,
DIODM_START_PATTERN = 4,
DIODM_START_EXTSIG_1 = 5,
DIODM_START_EXTSIG_2 = 6,
DIODM_START_EXTSIG_3 = 7,
// Clock
DIODM_CLK_CLOCK = 1,
DIODM_CLK_EXT_TRG = 2,
DIODM_CLK_HANDSHAKE = 3,
DIODM_CLK_EXTSIG_1 = 4,
DIODM_CLK_EXTSIG_2 = 5,
DIODM_CLK_EXTSIG_3 = 6,
// Internal Clock
DIODM_TIM_UNIT_S = 1,
DIODM_TIM_UNIT_MS = 2,
DIODM_TIM_UNIT_US = 3,
DIODM_TIM_UNIT_NS = 4,
// Stop
DIODM_STOP_SOFT = 1,
DIODM_STOP_EXT_RISE = 2,
DIODM_STOP_EXT_FALL = 3,
DIODM_STOP_NUM = 4,
DIODM_STOP_EXTSIG_1 = 5,
DIODM_STOP_EXTSIG_2 = 6,
DIODM_STOP_EXTSIG_3 = 7,
// ExtSig
DIODM_EXT_START_SOFT_IN = 1,
DIODM_EXT_STOP_SOFT_IN = 2,
DIODM_EXT_CLOCK_IN = 3,
DIODM_EXT_EXT_TRG_IN = 4,
DIODM_EXT_START_EXT_RISE_IN = 5,
DIODM_EXT_START_EXT_FALL_IN = 6,
DIODM_EXT_START_PATTERN_IN = 7,
DIODM_EXT_STOP_EXT_RISE_IN = 8,
DIODM_EXT_STOP_EXT_FALL_IN = 9,
DIODM_EXT_CLOCK_ERROR_IN = 10,
DIODM_EXT_HANDSHAKE_IN = 11,
DIODM_EXT_TRNSNUM_IN = 12,
DIODM_EXT_START_SOFT_OUT = 101,
DIODM_EXT_STOP_SOFT_OUT = 102,
DIODM_EXT_CLOCK_OUT = 103,
DIODM_EXT_EXT_TRG_OUT = 104,
DIODM_EXT_START_EXT_RISE_OUT= 105,
DIODM_EXT_START_EXT_FALL_OUT= 106,
DIODM_EXT_STOP_EXT_RISE_OUT = 107,
DIODM_EXT_STOP_EXT_FALL_OUT = 108,
DIODM_EXT_CLOCK_ERROR_OUT = 109,
DIODM_EXT_HANDSHAKE_OUT = 110,
DIODM_EXT_TRNSNUM_OUT = 111,
// Status
DIODM_STATUS_BMSTOP = 0x1,
DIODM_STATUS_PIOSTART = 0x2,
DIODM_STATUS_PIOSTOP = 0x4,
DIODM_STATUS_TRGIN = 0x8,
DIODM_STATUS_OVERRUN = 0x10,
// Error
DIODM_STATUS_FIFOEMPTY = 0x1,
DIODM_STATUS_FIFOFULL = 0x2,
DIODM_STATUS_SGOVERIN = 0x4,
DIODM_STATUS_TRGERR = 0x8,
DIODM_STATUS_CLKERR = 0x10,
DIODM_STATUS_SLAVEHALT = 0x20,
DIODM_STATUS_MASTERHALT = 0x40,
// Reset
DIODM_RESET_FIFO_IN = 0x02,
DIODM_RESET_FIFO_OUT = 0x04,
// Buffer Ring
DIODM_WRITE_ONCE = 0,
DIODM_WRITE_RING = 1,
//-------------------------------------------------
// Error codes
//-------------------------------------------------
// Initialize Error
// Common
DIO_ERR_SUCCESS = 0, // normal completed
DIO_ERR_INI_RESOURCE = 1, // invalid resource reference specified
DIO_ERR_INI_INTERRUPT = 2, // invalid interrupt routine registered
DIO_ERR_INI_MEMORY = 3, // invalid memory allocationed
DIO_ERR_INI_REGISTRY = 4, // invalid registry accesse
DIO_ERR_SYS_RECOVERED_FROM_STANDBY = 7, // Execute DioResetDevice function because the device has recovered from standby mode.
DIO_ERR_INI_NOT_FOUND_SYS_FILE = 8, // Because the Cdio.sys file is not found, it is not possible to initialize it.
DIO_ERR_INI_DLL_FILE_VERSION = 9, // Because version information on the Cdio.dll file cannot be acquired, it is not possible to initialize it.
DIO_ERR_INI_SYS_FILE_VERSION = 10, // Because version information on the Cdio.sys file cannot be acquired, it is not possible to initialize it.
DIO_ERR_INI_NO_MATCH_DRV_VERSION = 11, // Because version information on Cdio.dll and Cdio.sys is different, it is not possible to initialize it.
// DLL Error
// Common
DIO_ERR_DLL_DEVICE_NAME = 10000, // invalid device name specified.
DIO_ERR_DLL_INVALID_ID = 10001, // invalid ID specified.
DIO_ERR_DLL_CALL_DRIVER = 10002, // not call the driver.(Invalid device I/O controller)
DIO_ERR_DLL_CREATE_FILE = 10003, // not create the file.(Invalid CreateFile)
DIO_ERR_DLL_CLOSE_FILE = 10004, // not close the file.(Invalid CloseFile)
DIO_ERR_DLL_CREATE_THREAD = 10005, // not create the thread.(Invalid CreateThread)
DIO_ERR_INFO_INVALID_DEVICE = 10050, // invalid device infomation specified .Please check the spell.
DIO_ERR_INFO_NOT_FIND_DEVICE = 10051, // not find the available device
DIO_ERR_INFO_INVALID_INFOTYPE = 10052, // specified device infomation type beyond the limit
// DIO
DIO_ERR_DLL_BUFF_ADDRESS = 10100, // invalid data buffer address
DIO_ERR_DLL_HWND = 10200, // window handle beyond the limit
DIO_ERR_DLL_TRG_KIND = 10300, // trigger kind beyond the limit
// SYS Error
// Common
DIO_ERR_SYS_MEMORY = 20000, // not secure memory
DIO_ERR_SYS_NOT_SUPPORTED = 20001, // this board couldn't use this function
DIO_ERR_SYS_BOARD_EXECUTING = 20002, // board is behaving, not execute
DIO_ERR_SYS_USING_OTHER_PROCESS = 20003, // other process is using the device, not execute
STATUS_SYS_USB_CRC = 20020, // the last data packet received from end point exist CRC error
STATUS_SYS_USB_BTSTUFF = 20021, // the last data packet received from end point exist bit stuffing offense error
STATUS_SYS_USB_DATA_TOGGLE_MISMATCH = 20022, // the last data packet received from end point exist toggle packet mismatch error
STATUS_SYS_USB_STALL_PID = 20023, // end point return STALL packet identifier
STATUS_SYS_USB_DEV_NOT_RESPONDING = 20024, // device don't respond to token(IN), don't support handshake
STATUS_SYS_USB_PID_CHECK_FAILURE = 20025,
STATUS_SYS_USB_UNEXPECTED_PID = 20026, // invalid packet identifier received
STATUS_SYS_USB_DATA_OVERRUN = 20027, // end point return data quantity overrun
STATUS_SYS_USB_DATA_UNDERRUN = 20028, // end point return data quantity underrun
STATUS_SYS_USB_BUFFER_OVERRUN = 20029, // IN transmit specified buffer overrun
STATUS_SYS_USB_BUFFER_UNDERRUN = 20030, // OUT transmit specified buffer underrun
STATUS_SYS_USB_ENDPOINT_HALTED = 20031, // end point status is STALL, not transmit
STATUS_SYS_USB_NOT_FOUND_DEVINFO = 20032, // not found device infomation
STATUS_SYS_USB_ACCESS_DENIED = 20033, // Access denied
STATUS_SYS_USB_INVALID_HANDLE = 20034, // Invalid handle
// DIO
DIO_ERR_SYS_PORT_NO = 20100, // board No. beyond the limit
DIO_ERR_SYS_PORT_NUM = 20101, // board number beyond the limit
DIO_ERR_SYS_BIT_NO = 20102, // bit No. beyond the limit
DIO_ERR_SYS_BIT_NUM = 20103, // bit number beyond the limit
DIO_ERR_SYS_BIT_DATA = 20104, // bit data beyond the limit of 0 to 1
DIO_ERR_SYS_INT_BIT = 20200, // interrupt bit beyond the limit
DIO_ERR_SYS_INT_LOGIC = 20201, // interrupt logic beyond the limit
DIO_ERR_SYS_TIM = 20300, // timer value beyond the limit
DIO_ERR_SYS_FILTER = 20400, // filter number beyond the limit
DIO_ERR_SYS_IODIRECTION = 20500, // Direction value is out of range
// DM
DIO_ERR_SYS_SIGNAL = 21000, // Usable signal is outside the setting range.
DIO_ERR_SYS_START = 21001, // Usable start conditions are outside the setting range.
DIO_ERR_SYS_CLOCK = 21002, // Clock conditions are outside the setting range.
DIO_ERR_SYS_CLOCK_VAL = 21003, // Clock value is outside the setting range.
DIO_ERR_SYS_CLOCK_UNIT = 21004, // Clock value unit is outside the setting range.
DIO_ERR_SYS_STOP = 21005, // Stop conditions are outside the setting range.
DIO_ERR_SYS_STOP_NUM = 21006, // Stop number is outside the setting range.
DIO_ERR_SYS_RESET = 21007, // Contents of reset are outside the setting range.
DIO_ERR_SYS_LEN = 21008, // Data number is outside the setting range.
DIO_ERR_SYS_RING = 21009, // Buffer repetition use setup is outside the setting range.
DIO_ERR_SYS_COUNT = 21010, // Data transmission number is outside the setting range.
DIO_ERR_DM_BUFFER = 21100, // Buffer was too large and has not secured.
DIO_ERR_DM_LOCK_MEMORY = 21101, // Memory has not been locked.
DIO_ERR_DM_PARAM = 21102, // Parameter error
DIO_ERR_DM_SEQUENCE = 21103 // Procedure error of execution
}
namespace CdioCs
{
//unsafe public delegate void PINTCALLBACK(short Id, int wParam, int lParam, void *Param);
//unsafe public delegate void PTRGCALLBACK(short Id, int wParam, int lParam, void *Param);
//unsafe public delegate void PDMCOUNTCALLBACK(short Id, int wParam, int lParam, void *Param);
//unsafe public delegate void PDMSTOPCALLBACK(short Id, int wParam, int lParam, void *Param);
public class Cdio
{
// Definition of common functions
[DllImport("cdio.dll")] static extern int DioInit(string DeviceName, ref short Id);
[DllImport("cdio.dll")] static extern int DioExit(short Id);
[DllImport("cdio.dll")] static extern int DioResetDevice(short Id);
[DllImport("cdio.dll")] static extern int DioGetErrorString(int ErrorCode, System.Text.StringBuilder ErrorString);
// Digital filter functions
[DllImport("cdio.dll")] static extern int DioSetDigitalFilter(short Id, short FilterValue);
[DllImport("cdio.dll")] static extern int DioGetDigitalFilter(short Id, ref short FilterValue);
// I/O Direction functions
[DllImport("cdio.dll")] static extern int DioSetIoDirection(short Id, uint dwDir);
[DllImport("cdio.dll")] static extern int DioGetIoDirection(short Id, ref uint dwDir);
[DllImport("cdio.dll")] static extern int DioSetIoDirectionEx(short Id, uint dwDir);
[DllImport("cdio.dll")] static extern int DioGetIoDirectionEx(short Id, ref uint dwDir);
[DllImport("cdio.dll")] static extern int DioSet8255Mode(short Id, short ChipNo, short CtrlWord);
[DllImport("cdio.dll")] static extern int DioGet8255Mode(short Id, short ChipNo, ref short CtrlWord);
// Simple I/O functions
[DllImport("cdio.dll")] static extern int DioInpByte(short Id, short PortNo, ref byte Data);
[DllImport("cdio.dll")] static extern int DioInpBit(short Id, short BitNo, ref byte Data);
[DllImport("cdio.dll")] static extern int DioOutByte(short Id, short PortNo, byte Data);
[DllImport("cdio.dll")] static extern int DioOutBit(short Id, short BitNo, byte Data);
[DllImport("cdio.dll")] static extern int DioEchoBackByte(short Id, short PortNo, ref byte Data);
[DllImport("cdio.dll")] static extern int DioEchoBackBit(short Id, short BitNo, ref byte Data);
// Multiple I/O functions
[DllImport("cdio.dll")] static extern int DioInpMultiByte(short Id, [MarshalAs(UnmanagedType.LPArray)] short[] PortNo, short PortNum, [MarshalAs(UnmanagedType.LPArray)] byte[] Data);
[DllImport("cdio.dll")] static extern int DioInpMultiBit(short Id, [MarshalAs(UnmanagedType.LPArray)] short[] BitNo, short BitNum, [MarshalAs(UnmanagedType.LPArray)] byte[] Data);
[DllImport("cdio.dll")] static extern int DioOutMultiByte(short Id, [MarshalAs(UnmanagedType.LPArray)] short[] PortNo, short PortNum, [MarshalAs(UnmanagedType.LPArray)] byte[] Data);
[DllImport("cdio.dll")] static extern int DioOutMultiBit(short Id, [MarshalAs(UnmanagedType.LPArray)] short[] BitNo, short BitNum, [MarshalAs(UnmanagedType.LPArray)] byte[] Data);
[DllImport("cdio.dll")] static extern int DioEchoBackMultiByte(short Id, [MarshalAs(UnmanagedType.LPArray)] short[] PortNo, short PortNum, [MarshalAs(UnmanagedType.LPArray)] byte[] Data);
[DllImport("cdio.dll")] static extern int DioEchoBackMultiBit(short Id, [MarshalAs(UnmanagedType.LPArray)] short[] BitNo, short BitNum, [MarshalAs(UnmanagedType.LPArray)] byte[] Data);
// Interrupt functions
[DllImport("cdio.dll")] static extern int DioNotifyInterrupt(short Id, short IntBit, short Logic, int hWnd);
//[DllImport("cdio.dll")] unsafe static extern int DioSetInterruptCallBackProc(short Id, PINTCALLBACK pIntCallBack, void *Param);
// Trigger functions
[DllImport("cdio.dll")] static extern int DioNotifyTrg(short Id, short TrgBit, short TrgKind, int Tim, int hWnd);
[DllImport("cdio.dll")] static extern int DioStopNotifyTrg(short Id, short TrgBit);
//[DllImport("cdio.dll")] static extern int DioSetTrgCallBackProc(short Id, PTRGCALLBACK CallBackProc, ref int Param);
// Information functions
[DllImport("cdio.dll")] static extern int DioGetDeviceInfo(string Device, short InfoType, ref int Param1, ref int Param2, ref int Param3);
[DllImport("cdio.dll")] static extern int DioQueryDeviceName(short Index, System.Text.StringBuilder DeviceName, System.Text.StringBuilder Device);
[DllImport("cdio.dll")] static extern int DioGetDeviceType(string Device, ref short DeviceType);
[DllImport("cdio.dll")] static extern int DioGetMaxPorts(short Id, ref short InPortNum, ref short OutPortNum);
//dm functions
[DllImport("cdio.DLL")] static extern int DioDmSetDirection(short Id, short Direction);
[DllImport("cdio.DLL")] static extern int DioDmGetDirection(short Id, ref short Direction);
[DllImport("cdio.DLL")] static extern int DioDmSetStandAlone(short Id);
[DllImport("cdio.DLL")] static extern int DioDmSetMaster(short Id, short ExtSig1, short ExtSig2, short ExtSig3, short MasterHalt, short SlaveHalt);
[DllImport("cdio.DLL")] static extern int DioDmSetSlave(short Id, short ExtSig1, short ExtSig2, short ExtSig3, short MasterHalt, short SlaveHalt);
[DllImport("cdio.DLL")] static extern int DioDmSetStartTrigger(short Id, short Direction, short Start);
[DllImport("cdio.DLL")] static extern int DioDmSetStartPattern(short Id, uint Pattern, uint Mask);
[DllImport("cdio.DLL")] static extern int DioDmSetClockTrigger(short Id, short Direction, short Clock);
[DllImport("cdio.DLL")] static extern int DioDmSetInternalClock(short Id, short Direction, uint Clock, short Unit);
[DllImport("cdio.DLL")] static extern int DioDmSetStopTrigger(short Id, short Direction, short Stop);
[DllImport("cdio.DLL")] static extern int DioDmSetStopNumber(short Id, short Direction, uint StopNumber);
[DllImport("cdio.DLL")] static extern int DioDmFifoReset(short Id, short Reset);
[DllImport("cdio.DLL")] static extern int DioDmSetBuffer(short Id, short Direction, IntPtr Buffer, uint Length, short IsRing);
[DllImport("cdio.DLL")] static extern int DioDmSetTransferStartWait(short Id, short Time);
[DllImport("cdio.DLL")] static extern int DioDmTransferStart(short Id, short Direction);
[DllImport("cdio.DLL")] static extern int DioDmTransferStop(short Id, short Direction);
[DllImport("cdio.DLL")] static extern int DioDmGetStatus(short Id, short Direction, ref uint Status, ref uint Err);
[DllImport("cdio.DLL")] static extern int DioDmGetCount(short Id, short Direction, ref uint Count, ref uint Carry);
[DllImport("cdio.DLL")] static extern int DioDmGetWritePointer(short Id, short Direction, ref uint WritePointer, ref uint Count, ref uint Carry);
[DllImport("cdio.DLL")] static extern int DioDmSetStopEvent(short Id, short Direction, int hWnd);
//[DllImport("cdio.DLL")] unsafe static extern int DioDmSetStopCallBackProc(short Id, PDMSTOPCALLBACK CallBackProc, void *Param);
[DllImport("cdio.DLL")] static extern int DioDmSetCountEvent(short Id, short Direction, uint Count, int hWnd);
//[DllImport("cdio.DLL")] unsafe static extern int DioDmSetCountCallBackProc(short Id, PDMCOUNTCALLBACK CallBackProc, void *Param);
// Demo Device I/O functions
[DllImport("cdio.dll")] static extern int DioSetDemoByte(short Id, short PortNo, byte Data);
[DllImport("cdio.dll")] static extern int DioSetDemoBit(short Id, short BitNo, byte Data);
// Constructor
public Cdio()
{
}
// Description of common functions
public int Init(string DeviceName, out short Id)
{
Id = 0;
int ret = DioInit(DeviceName, ref Id);
return ret;
}
public int Exit(short Id)
{
int ret = DioExit(Id);
return ret;
}
public int ResetDevice(short Id)
{
int ret = DioResetDevice(Id);
return ret;
}
public int GetErrorString(int ErrorCode, out string ErrorString)
{
ErrorString = new String('0', 1);
System.Text.StringBuilder errorstring = new System.Text.StringBuilder(256);
int ret = DioGetErrorString(ErrorCode, errorstring);
if(ret == 0)
{
ErrorString = errorstring.ToString();
}
return ret;
}
// Digital filter functions
public int SetDigitalFilter(short Id, short FilterValue)
{
int ret = DioSetDigitalFilter(Id, FilterValue);
return ret;
}
public int GetDigitalFilter(short Id, out short FilterValue)
{
FilterValue = 0;
int ret = DioGetDigitalFilter(Id, ref FilterValue);
return ret;
}
// I/O Direction functions
public int SetIoDirection(short Id, uint dwDir)
{
int ret = DioSetIoDirection(Id, dwDir);
return ret;
}
public int GetIoDirection(short Id, out uint dwDir)
{
dwDir = 0;
int ret = DioGetIoDirection(Id, ref dwDir);
return ret;
}
public int Set8255Mode(short Id, short ChipNo, short CtrlWord)
{
int ret = DioSet8255Mode(Id, ChipNo, CtrlWord);
return ret;
}
public int Get8255Mode(short Id, short ChipNo, out short CtrlWord)
{
CtrlWord = 0;
int ret = DioGet8255Mode(Id, ChipNo, ref CtrlWord);
return ret;
}
public int SetIoDirectionEx(short Id, uint dwDir)
{
int ret = DioSetIoDirectionEx(Id, dwDir);
return ret;
}
public int GetIoDirectionEx(short Id, out uint dwDir)
{
dwDir = 0;
int ret = DioGetIoDirectionEx(Id, ref dwDir);
return ret;
}
// Simple I/O functions
public int InpByte(short Id, short PortNo, out byte Data)
{
Data = 0;
int ret = DioInpByte(Id, PortNo, ref Data);
return ret;
}
public int InpBit(short Id, short BitNo, out byte Data)
{
Data = 0;
int ret = DioInpBit(Id, BitNo, ref Data);
return ret;
}
public int OutByte(short Id, short PortNo, byte Data)
{
int ret = DioOutByte(Id, PortNo, Data);
return ret;
}
public int OutBit(short Id, short BitNo, byte Data)
{
int ret = DioOutBit(Id, BitNo, Data);
return ret;
}
public int EchoBackByte(short Id, short PortNo, out byte Data)
{
Data = 0;
int ret = DioEchoBackByte(Id, PortNo, ref Data);
return ret;
}
public int EchoBackBit(short Id, short BitNo, out byte Data)
{
Data = 0;
int ret = DioEchoBackBit(Id, BitNo, ref Data);
return ret;
}
// Multiple I/O functions
public int InpMultiByte(short Id, short[] PortNo, short PortNum, byte[] Data)
{
int ret = DioInpMultiByte(Id, PortNo, PortNum, Data);
return ret;
}
public int InpMultiBit(short Id, short[] BitNo, short BitNum, byte[] Data)
{
int ret = DioInpMultiBit(Id, BitNo, BitNum, Data);
return ret;
}
public int OutMultiByte(short Id, short[] PortNo, short PortNum, byte[] Data)
{
int ret = DioOutMultiByte(Id, PortNo, PortNum, Data);
return ret;
}
public int OutMultiBit(short Id, short[] BitNo, short BitNum, byte[] Data)
{
int ret = DioOutMultiBit(Id, BitNo, BitNum, Data);
return ret;
}
public int EchoBackMultiByte(short Id, short[] PortNo, short PortNum, byte[] Data)
{
int ret = DioEchoBackMultiByte(Id, PortNo, PortNum, Data);
return ret;
}
public int EchoBackMultiBit(short Id, short[] BitNo, short BitNum, byte[] Data)
{
int ret = DioEchoBackMultiBit(Id, BitNo, BitNum, Data);
return ret;
}
// Interrupt functions
public int NotifyInterrupt(short Id, short IntBit, short Logic, int hWnd)
{
int ret = DioNotifyInterrupt(Id, IntBit, Logic, hWnd);
return ret;
}
//unsafe public int SetInterruptCallBackProc(short Id, PINTCALLBACK pIntCallBack, void *Param)
//{
// int ret = DioSetInterruptCallBackProc(Id, pIntCallBack, Param);
// return ret;
//}
// Trigger functions
public int NotifyTrg(short Id, short TrgBit, short TrgKind, int Tim, int hWnd)
{
int ret = DioNotifyTrg(Id, TrgBit, TrgKind, Tim, hWnd);
return ret;
}
public int StopNotifyTrg(short Id, short TrgBit)
{
int ret = DioStopNotifyTrg(Id, TrgBit);
return ret;
}
//public int SetTrgCallBackProc(short Id, PTRGCALLBACK CallBackProc, out int Param)
//{
// Param = 0;
// int ret = DioSetTrgCallBackProc(Id, CallBackProc, ref Param);
// return ret;
//}
// Information functions
public int GetDeviceInfo(string Device, short InfoType, out int Param1, out int Param2, out int Param3)
{
Param1 = 0;
Param2 = 0;
Param3 = 0;
int ret = DioGetDeviceInfo(Device, InfoType, ref Param1, ref Param2, ref Param3);
return ret;
}
public int QueryDeviceName(short Index, out string DeviceName, out string Device)
{
DeviceName = new String('0', 1);
Device = new String('0', 1);
System.Text.StringBuilder devicename = new System.Text.StringBuilder(256);
System.Text.StringBuilder device = new System.Text.StringBuilder(256);
int ret = DioQueryDeviceName(Index, devicename, device);
if(ret == 0)
{
DeviceName = devicename.ToString();
Device = device.ToString();
}
return ret;
}
public int GetDeviceType(string Device, out short DeviceType)
{
DeviceType = 0;
int ret = DioGetDeviceType(Device, ref DeviceType);
return ret;
}
public int GetMaxPorts(short Id, out short InPortNum, out short OutPortNum)
{
InPortNum = 0;
OutPortNum = 0;
int ret = DioGetMaxPorts(Id, ref InPortNum, ref OutPortNum);
return ret;
}
public int DmSetDirection(short Id, short Direction)
{
int ret = DioDmSetDirection(Id, Direction);
return ret;
}
public int DmGetDirection(short Id, out short Direction)
{
Direction = 0;
int ret = DioDmGetDirection(Id, ref Direction);
return ret;
}
public int DmSetStandAlone(short Id)
{
int ret = DioDmSetStandAlone(Id);
return ret;
}
public int DmSetMaster(short Id, short ExtSig1, short ExtSig2, short ExtSig3, short MasterHalt, short SlaveHalt)
{
int ret = DioDmSetMaster(Id, ExtSig1, ExtSig2, ExtSig3, MasterHalt, SlaveHalt);
return ret;
}
public int DmSetSlave(short Id, short ExtSig1, short ExtSig2, short ExtSig3, short MasterHalt, short SlaveHalt)
{
int ret = DioDmSetSlave(Id, ExtSig1, ExtSig2, ExtSig3, MasterHalt, SlaveHalt);
return ret;
}
public int DmSetStartTrigger(short Id, short Direction, short Start)
{
int ret = DioDmSetStartTrigger(Id, Direction, Start);
return ret;
}
public int DmSetStartPattern(short Id, uint Pattern, uint Mask)
{
int ret = DioDmSetStartPattern(Id, Pattern, Mask);
return ret;
}
public int DmSetClockTrigger(short Id, short Direction, short Clock)
{
int ret = DioDmSetClockTrigger(Id, Direction, Clock);
return ret;
}
public int DmSetInternalClock(short Id, short Direction, uint Clock, short Unit)
{
int ret = DioDmSetInternalClock(Id, Direction, Clock, Unit);
return ret;
}
public int DmSetStopTrigger(short Id, short Direction, short Stop)
{
int ret = DioDmSetStopTrigger(Id, Direction, Stop);
return ret;
}
public int DmSetStopNumber(short Id, short Direction, uint StopNumber)
{
int ret = DioDmSetStopNumber(Id, Direction, StopNumber);
return ret;
}
public int DmFifoReset(short Id, short Reset)
{
int ret = DioDmFifoReset(Id, Reset);
return ret;
}
public int DmSetBuffer(short Id, short Direction, IntPtr Buffer, uint Length, short IsRing)
{
int ret = DioDmSetBuffer(Id, Direction, Buffer, Length, IsRing);
return ret;
}
public int DmSetTransferStartWait(short Id, short Time)
{
int ret = DioDmSetTransferStartWait(Id, Time);
return ret;
}
public int DmTransferStart(short Id, short Direction)
{
int ret = DioDmTransferStart(Id, Direction);
return ret;
}
public int DmTransferStop(short Id, short Direction)
{
int ret = DioDmTransferStop(Id, Direction);
return ret;
}
public int DmGetStatus(short Id, short Direction, out uint Status, out uint Err)
{
Status = 0;
Err = 0;
int ret = DioDmGetStatus(Id, Direction, ref Status, ref Err);
return ret;
}
public int DmGetCount(short Id, short Direction, out uint Count, out uint Carry)
{
Count = 0;
Carry = 0;
int ret = DioDmGetCount(Id, Direction, ref Count, ref Carry);
return ret;
}
public int DmGetWritePointer(short Id, short Direction, out uint WritePointer, out uint Count, out uint Carry)
{
WritePointer = 0;
Count = 0;
Carry = 0;
int ret = DioDmGetWritePointer(Id, Direction, ref WritePointer, ref Count, ref Carry);
return ret;
}
public int DmSetStopEvent(short Id, short Direction, int hWnd)
{
int ret = DioDmSetStopEvent(Id, Direction, hWnd);
return ret;
}
//unsafe public int DmSetStopCallBackProc(short Id, PDMSTOPCALLBACK CallBackProc, void *Param)
//{
// int ret = DioDmSetStopCallBackProc(Id, CallBackProc, Param);
// return ret;
//}
public int DmSetCountEvent(short Id, short Direction, uint Count, int hWnd)
{
int ret = DioDmSetCountEvent(Id, Direction, Count, hWnd);
return ret;
}
//unsafe public int DmSetCountCallBackProc(short Id, PDMCOUNTCALLBACK CallBackProc, void *Param)
//{
// int ret = DioDmSetCountCallBackProc(Id, CallBackProc, Param);
// return ret;
//}
public int SetDemoByte(short Id, short PortNo, byte Data)
{
int ret = DioSetDemoByte(Id, PortNo, Data);
return ret;
}
public int SetDemoBit(short Id, short BitNo, byte Data)
{
int ret = DioSetDemoBit(Id, BitNo, Data);
return ret;
}
}
}

View File

@@ -0,0 +1,613 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using CdioCs;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using NLog;
using Raytheon.Common;
using System.ComponentModel.Composition.Primitives;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
/// <summary>
/// A class that implements a Contec DIO card
/// </summary>
public class DIOContec : IGeneralIO, IDisposable
{
#region PrivateClassMembers
private Cdio _dio;
private short _id;
private string _name;
private string _address;
private SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
private int _numChannelPerPort = 8;
private int _channelStartIndex = 0;
private int _numInputChannels;
private int _numOutputChannels;
private bool _shallWeInitializeOutput = false;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#endregion
#region PrivateClassFunctions
/// <summary>
/// Dispose of this object's resources
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
if (_state == State.Ready)
{
Reset();
_dio.Exit(_id);
_state = State.Uninitialized;
}
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
/// <summary>
/// Invert Contec DIO bits.
/// </summary>
private byte InvertBit(byte bitValue)
{
if (bitValue == 0)
{
return 1;
}
else if (bitValue == 1)
{
return 0;
}
else
{
throw new Exception("Unexpected input value: " + bitValue.ToString());
}
}
#endregion
#region PublicClassFunctions
/// <summary>
/// DIOContec factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOContec(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
_address = _configuration.GetConfigurationValue("DIOContec", "Address", "");
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
if (!Path.IsPathRooted(dioModuleDefPath))
dioModuleDefPath = Path.GetFullPath(Path.Combine(assemblyFolder, dioModuleDefPath));
IConfigurationFile dioModuleConfig = new ConfigurationFile(dioModuleDefPath);
Boolean.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.SHALL_WE_DRIVE_OUTPUT_UPON_INITIALIZATION.ToString()), out _shallWeInitializeOutput);
_address = dioModuleConfig.ReadValue(Name, ConfigIni.DIO_ADDRESS.ToString());
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_INPUT_CHANNELS.ToString()), out _numInputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_OUTPUT_CHANNELS.ToString()), out _numOutputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_CHANNELS_PER_PORT.ToString()), out _numChannelPerPort);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.CHANNEL_START_INDEX.ToString()), out _channelStartIndex);
if (!(_channelStartIndex == 0 || _channelStartIndex == 1))
{
throw new Exception($"The value for key {ConfigIni.CHANNEL_START_INDEX.ToString()} in section {Name} must be 0 or 1 in {dioModuleDefPath}");
}
List<string> outputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.OUTPUT_SIGNALS}");
List<string> intputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.INPUT_SIGNALS}");
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
string[] infoTokens = iniLine.Split('|');
if (infoTokens.Length != 2)
{
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} does not contain 2 tokens");
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
}
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
// set in Initialize()
_dio = null;
_id = -1;
}
/// <summary>
/// Constructor which opens a handle to the DIO instrument and resets it.
/// Note that all signals on the Contec DIO card are inverted.
/// This class masks the inversion so that the caller does not have to deal with it.
/// </summary>
public DIOContec(string name, string address, List<uint> inputPins, List<uint> outputPins)
{
_name = name;
_address = address;
_logger = LogManager.GetCurrentClassLogger();
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
// set in Initialize()
_dio = null;
_id = -1;
}
/// <summary>
/// The finalizer.
/// </summary>
~DIOContec()
{
Dispose(false);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is a Contec DIO Card " + _name;
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object's resources.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
byte dioData = 0;
int ret = _dio.InpBit(_id, (short)bitIndex, out dioData);
if (ret != 0)
{
string errorString = "";
_dio.GetErrorString(ret, out errorString);
throw new Exception("call to InpBit returned error: " + ret.ToString() + ", " + errorString + " on card " + _name);
}
return (IODatatypes.BitState)InvertBit(dioData);
}
}
/// <summary>
/// Get state of an output signal. The contec DIO states are inverted.
/// This function masks the inversion before returning.
/// </summary>
/// <param name="bitno">The bit number of the signal.</param>
/// <returns>The state of the signal. 0 for low, 1 for high.</returns>
/*public DioMeasurementInstruments.SignalState GetOutputSignalState(uint bitno)
{
byte dioData = 0;
int ret = _dio.EchoBackBit(_id, (short)bitno, out dioData);
if (ret != 0)
{
string errorString = "";
_dio.GetErrorString(ret, out errorString);
throw new Exception("call to EchoBackBit returned error: " + ret.ToString() + ", " + errorString);
}
dioData = InvertBit(dioData);
if (dioData == 0)
{
return DioMeasurementInstruments.SignalState.LOW;
}
else
{
return DioMeasurementInstruments.SignalState.HIGH;
}
}*/
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
_dio = new Cdio();
int ret = _dio.Init(_address, out _id);
if (ret != 0)
{
string errorString = "";
_dio.GetErrorString(ret, out errorString);
throw new Exception("call to Init returned error: " + ret.ToString() + ", " + errorString + " on card " + _name);
}
Reset();
if (_shallWeInitializeOutput)
{
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelMap)
{
if (item.Value.initialValue != -1)
{
SetBit(item.Key, (IODatatypes.BitState)item.Value.initialValue);
}
}
}
_state = State.Ready;
}
else
{
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
/// Return list of signal names
/// </summary>
public List<string> GetSignalNames()
{
return new List<string>(_signalNameToChannelMap.Keys);
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
// card does not support self test
throw new NotImplementedException("card does not support self test" + " on card " + _name);
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
int ret = _dio.ResetDevice(_id);
if (ret != 0)
{
string errorString = "";
_dio.GetErrorString(ret, out errorString);
throw new Exception("call to ResetDevice returned error: " + ret.ToString() + ", " + errorString + " on card " + _name);
}
}
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <param name="state"> high(open) or low(closed) </param>
///
public void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
int ret = _dio.OutBit(_id, (short)bitIndex, InvertBit((byte)state));
if (ret != 0)
{
string errorString = "";
_dio.GetErrorString(ret, out errorString);
throw new Exception("call to OutBit returned error: " + ret.ToString() + ", " + errorString + " on card " + _name);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void SetTristate(string signalName)
{
lock (_syncObj)
{
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <param name="frequencyInHz"></param>
/// <param name="dutyCylePercentage"></param>
public void StartClock(uint bit, double frequencyInHz, double dutyCylePercentage)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void StopClock(uint bit)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
if (_state == State.Ready)
{
Reset();
_dio.Exit(_id);
_state = State.Uninitialized;
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.DIOContec</AssemblyName>
<Product>DIO Contec implementation</Product>
<Description>Digital IO Contec implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
<PackageReference Include="Raytheon.Instruments.GeneralIO.Contracts" Version="1.7.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DIOSim\DIOSim.csproj" />
</ItemGroup>
<!-- Copy all *.dlls and *.pdb in the output folder to a temp folder -->
<Target Name="CopyFiles" AfterTargets="AfterBuild">
<ItemGroup>
<FILES_1 Include="$(OutDir)*.dll" />
<FILES_2 Include="$(OutDir)*.pdb" />
</ItemGroup>
<Copy SourceFiles="@(FILES_1)" DestinationFolder="$(HalTempFolder)" />
<Copy SourceFiles="@(FILES_2)" DestinationFolder="$(HalTempFolder)" />
</Target>
</Project>

View File

@@ -0,0 +1,141 @@
// **********************************************************************************************************
// DIOContecFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
// Ignore Spelling: Contec
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOContecFactory")]
public class DIOContecFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public DIOContecFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOContecFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOContec(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
else
return new DIOContec(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1,482 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using Raytheon.Common;
using NLog;
using Pickering.Lxi.Communication;
using Pickering.Lxi.Piplx;
using Pickering.Lxi;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
/// <summary>
/// A class that implements a Pickering DIO card
/// </summary>
public class DIOPickering40x : IGeneralIO, IDisposable
{
#region PrivateClassMembers
private string _name;
private readonly int _pxiCardSlotIndex;
private SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
private PiplxCard _dioCard;
private int _numChannelPerPort = 8;
private int _channelStartIndex = 0;
private int _numInputChannels;
private int _numOutputChannels;
private bool _shallWeInitializeOutput = false;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#endregion
#region PrivateClassFunctions
/// <summary>
/// The finalizer.
/// </summary>
~DIOPickering40x()
{
Dispose(false);
}
/// <summary>
/// Dispose of this object.
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
// nothing to do here
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
#endregion
#region PublicClassFunctions
/// <summary>
/// DIOPickering40x factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOPickering40x(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
if (!Path.IsPathRooted(dioModuleDefPath))
dioModuleDefPath = Path.GetFullPath(Path.Combine(assemblyFolder, dioModuleDefPath));
IConfigurationFile dioModuleConfig = new ConfigurationFile(dioModuleDefPath);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.PXI_CARD_SLOT_INDEX.ToString()), out _pxiCardSlotIndex);
Boolean.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.SHALL_WE_DRIVE_OUTPUT_UPON_INITIALIZATION.ToString()), out _shallWeInitializeOutput);
List<string> outputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.OUTPUT_SIGNALS}");
List<string> intputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.INPUT_SIGNALS}");
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_CHANNELS_PER_PORT.ToString()), out _numChannelPerPort);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.CHANNEL_START_INDEX.ToString()), out _channelStartIndex);
if (!(_channelStartIndex == 0 || _channelStartIndex == 1))
{
throw new Exception($"The value for key {ConfigIni.CHANNEL_START_INDEX.ToString()} in section {Name} must be 0 or 1 in {dioModuleDefPath}");
}
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
string[] infoTokens = iniLine.Split('|');
if (infoTokens.Length != 2)
{
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} does not contain 2 tokens");
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
}
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
}
/// <summary>
/// Initialize the card
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
PiplxManager manager = new PiplxManager("");
_dioCard = (PiplxCard)manager.Cards[_pxiCardSlotIndex];
PiplxCardInfo info = (PiplxCardInfo)_dioCard.Info;
_numInputChannels = info.InputSubunitsCount * _numChannelPerPort;
_numOutputChannels = info.OutputSubunitsCount * _numChannelPerPort;
_dioCard.Open();
if (_shallWeInitializeOutput)
{
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelMap)
{
if (item.Value.initialValue != -1)
{
SetBit(item.Key, (IODatatypes.BitState)item.Value.initialValue);
}
}
}
_state = State.Ready;
}
else
{
throw new Exception("Expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
/// Return list of signal names
/// </summary>
public List<string> GetSignalNames()
{
return new List<string>(_signalNameToChannelMap.Keys);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is a Pickering DIO Card " + _name;
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <param name="state"></param>
public void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels +_channelStartIndex} on card " + _name);
}
GetPortIndexAndBitIndex(signalName, out int portIndex, out int bitIndex);
DigitalInputOutputSubunit subunit = (DigitalInputOutputSubunit)_dioCard.OutputSubunits[portIndex];
subunit[bitIndex+1] = state != 0;
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels+_channelStartIndex} on card " + _name);
}
GetPortIndexAndBitIndex(signalName, out int portIndex, out int bitIndex);
DigitalInputOutputSubunit subunit = (DigitalInputOutputSubunit)_dioCard.InputSubunits[portIndex];
return (IODatatypes.BitState)(subunit[bitIndex+1] ? 1:0);
}
}
/// <summary>
/// Because the user has to define each channel number in the config file, some people will use 0 or 1 start their starting channel number
/// Whether the user prefers 0 or 1 as their starting channel number, this function will then calculate the port index and bit index that the
/// driver API needs to be able to drive/read the signal
/// <param name="signalName"></param>
/// <param name="portIndex">portIndex will range from 0..N</param>
/// <param name="bitIndex">bitIndex will range from 0..M</param>
/// </summary>
private void GetPortIndexAndBitIndex(string signalName, out int portIndex, out int bitIndex)
{
portIndex = (int)(Math.Ceiling((double)((int)_signalNameToChannelMap[signalName].channelNumber + Math.Abs(_channelStartIndex - 1)) / (double)_numChannelPerPort) - 1.0);
int multiplier = ((int)_signalNameToChannelMap[signalName].channelNumber + _numChannelPerPort) / _numChannelPerPort;
bitIndex = (((int)_signalNameToChannelMap[signalName].channelNumber + _numChannelPerPort) - (_numChannelPerPort * multiplier)) - _channelStartIndex;
if (bitIndex < 0)
{
bitIndex = _numChannelPerPort - 1;
}
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
Shutdown();
Initialize();
}
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void SetTristate(string signalName)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
_state = State.Uninitialized;
}
}
#endregion
}
}

View File

@@ -0,0 +1,45 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.DIOPickering40x</AssemblyName>
<Product>DIO Sim implementation</Product>
<Description>DIO Sim implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
<PackageReference Include="Raytheon.Instruments.GeneralIO.Contracts" Version="1.7.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DIOSim\DIOSim.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Pickering.Lxi.Communication">
<HintPath>..\..\Common\COTS\Pickering\Pickering.Lxi.Communication.dll</HintPath>
</Reference>
<Reference Include="Pickering.Lxi.Piplx">
<HintPath>..\..\Common\COTS\Pickering\Pickering.Lxi.Piplx.dll</HintPath>
</Reference>
</ItemGroup>
<!-- Copy all *.dlls and *.pdb in the output folder to a temp folder -->
<Target Name="CopyFiles" AfterTargets="AfterBuild">
<ItemGroup>
<FILES_1 Include="$(OutDir)*.dll" />
<FILES_2 Include="$(OutDir)*.pdb" />
</ItemGroup>
<Copy SourceFiles="@(FILES_1)" DestinationFolder="$(HalTempFolder)" />
<Copy SourceFiles="@(FILES_2)" DestinationFolder="$(HalTempFolder)" />
</Target>
</Project>

View File

@@ -0,0 +1,139 @@
// **********************************************************************************************************
// DIOPickering40xFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOPickering40xFactory")]
public class DIOPickering40xFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public DIOPickering40xFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOPickering40xFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOPickering40x(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
else
return new DIOPickering40x(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1,141 @@
using System;
using System.Runtime.InteropServices;
namespace CP210xRuntime_DLL
{
internal class CP210xRuntime
{
public const int CP210x_MAX_MAXPOWER = 250;
//GetPartNumber()
public const byte CP210x_CP2108_VERSION = ((Byte)(0xFF & 0x08));
// GetProductString() function flags
public const byte CP210x_RETURN_SERIAL_NUMBER = 0x00;
public const byte CP210x_RETURN_DESCRIPTION = 0x01;
public const byte CP210x_RETURN_FULL_PATH = 0x02;
// GetDeviceVersion() return codes Deprecated
//public const byte CP210x_USBXPRESS_EFM8 = 0x80;
//public const byte CP210x_USBXPRESS_EFM32 = 0x81;
//public const byte CP210x_CP2101_VERSION = 0x01;
//public const byte CP210x_CP2102_VERSION = 0x02;
//public const byte CP210x_CP2103_VERSION = 0x03;
//public const byte CP210x_CP2104_VERSION = 0x04;
//public const byte CP210x_CP2105_VERSION = 0x05;
//public const byte CP210x_CP2108_VERSION = 0x08;
//public const byte CP210x_CP2109_VERSION = 0x09;
//public const byte CP210x_CP2102N_QFN28_VERSION = 0x20;
//public const byte CP210x_CP2102N_QFN24_VERSION = 0x21;
//public const byte CP210x_CP2102N_QFN20_VERSION = 0x22;
// Return codes
public const byte CP210x_SUCCESS = 0x00;
public const byte CP210x_DEVICE_NOT_FOUND = 0xFF;
public const byte CP210x_INVALID_HANDLE = 0x01;
public const byte CP210x_INVALID_PARAMETER = 0x02;
public const byte CP210x_DEVICE_IO_FAILED = 0x03;
public const byte CP210x_FUNCTION_NOT_SUPPORTED = 0x04;
public const byte CP210x_GLOBAL_DATA_ERROR = 0x05;
public const byte CP210x_FILE_ERROR = 0x06;
public const byte CP210x_COMMAND_FAILED = 0x08;
public const byte CP210x_INVALID_ACCESS_TYPE = 0x09;
// Buffer size limits
//public const int CP2108_MAX_PRODUCT_STRLEN = 126;
//public const int CP2108_MAX_SERIAL_STRLEN = 63;
// Type Definitions
//readonly char CP210x_PRODUCT_STRING[] = new char[CP2108_MAX_PRODUCT_STRLEN]();
//char CP210x_SERIAL_STRING[CP2108_MAX_SERIAL_STRLEN];
// Mask and Latch value bit definitions
public const UInt32 CP210x_GPIO_0 = 0x0001; // (1<<0)
public const UInt32 CP210x_GPIO_1 = 0x0002; // (1<<1)
public const UInt32 CP210x_GPIO_2 = 0x0004; // (1<<2)
public const UInt32 CP210x_GPIO_3 = 0x0008;// etc.
public const UInt32 CP210x_GPIO_4 = 0x0010;
public const UInt32 CP210x_GPIO_5 = 0x0020;
public const UInt32 CP210x_GPIO_6 = 0x0040;
public const UInt32 CP210x_GPIO_7 = 0x0080;
public const UInt32 CP210x_GPIO_8 = 0x0100;
public const UInt32 CP210x_GPIO_9 = 0x0200;
public const UInt32 CP210x_GPIO_10 = 0x0400;
public const UInt32 CP210x_GPIO_11 = 0x0800;
public const UInt32 CP210x_GPIO_12 = 0x1000;
public const UInt32 CP210x_GPIO_13 = 0x2000;
public const UInt32 CP210x_GPIO_14 = 0x4000;
public const UInt32 CP210x_GPIO_15 = 0x8000;
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_GetNumDevices(
ref uint lpdwNumDevices
);
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_Open(
uint deviceIndex,
ref IntPtr pcyHandle
);
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_Close(
IntPtr cyHandle
);
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_ReadLatch(
IntPtr cyHandle,
ref ushort lpwLatch
);
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_WriteLatch(
IntPtr cyHandle,
ushort Mask,
ushort Latch
);
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_GetPartNumber(
IntPtr cyHandle,
ref byte lpbPartNum
);
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_GetDeviceProductString(
IntPtr cyHandle,
[Out] byte[] lpProduct,
ref byte lpbLength,
bool bConvertToASCII
);
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_GetDeviceSerialNumber(
IntPtr cyHandle,
[Out] byte[] lpSerialNumberString,
ref byte lpbLength,
bool bConvertToASCII
);
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_GetDeviceInterfaceString(
IntPtr cyHandle,
[Out] byte[] lpInterfaceString,
ref byte lpbLength,
bool bConvertToASCII
);
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_GetReceiverMaxTimeout(
IntPtr cyHandle,
ref UInt16 maxTimeout
);
[DllImport("CP210xRuntime.dll")]
public static extern int CP210xRT_SetReceiverMaxTimeout(
IntPtr cyHandle,
UInt16 maxTimeout
);
}
}

View File

@@ -0,0 +1,664 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using CP210xRuntime_DLL;
using NLog;
using Raytheon.Common;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
/// <summary>
/// Class for controlling a Silicon Labs CP2108 UART GPIO device
/// </summary>
public class DIOSiCp210x : IGeneralIO, IDisposable
{
#region PrivateClassMembers
protected IntPtr _handle;
protected uint _deviceNum;
protected State _state;
protected string _name;
protected IConfigurationFile _dioModuleConfig;
protected SelfTestResult _selfTestResult;
protected object _syncObj = new Object();
protected int _numChannelPerPort = 8;
protected int _channelStartIndex = 0;
protected int _numInputChannels;
protected int _numOutputChannels;
protected bool _shallWeInitializeOutput = false;
protected Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
protected const ushort CP210x_GPIO_0 = 0x0001;
protected const ushort CP210x_GPIO_1 = 0x0002;
protected const ushort CP210x_GPIO_2 = 0x0004;
protected const ushort CP210x_GPIO_3 = 0x0008;
protected const ushort CP210x_GPIO_4 = 0x0010;
protected const ushort CP210x_GPIO_5 = 0x0020;
protected const ushort CP210x_GPIO_6 = 0x0040;
protected const ushort CP210x_GPIO_7 = 0x0080;
protected const ushort CP210x_GPIO_8 = 0x0100;
protected const ushort CP210x_GPIO_9 = 0x0200;
protected const ushort CP210x_GPIO_10 = 0x0400;
protected const ushort CP210x_GPIO_11 = 0x0800;
protected const ushort CP210x_GPIO_12 = 0x1000;
protected const ushort CP210x_GPIO_13 = 0x2000;
protected const ushort CP210x_GPIO_14 = 0x4000;
protected const ushort CP210x_GPIO_15 = 0x8000;
// Return codes
public const byte SI_SUCCESS = 0x00;
public const byte SI_DEVICE_NOT_FOUND = 0xFF;
public const byte SI_INVALID_HANDLE = 0x01;
public const byte SI_READ_ERROR = 0x02;
public const byte SI_RX_QUEUE_NOT_READY = 0x03;
public const byte SI_WRITE_ERROR = 0x04;
public const byte SI_RESET_ERROR = 0x05;
public const byte SI_INVALID_PARAMETER = 0x06;
public const byte SI_INVALID_REQUEST_LENGTH = 0x07;
public const byte SI_DEVICE_IO_FAILED = 0x08;
public const byte SI_INVALID_BAUDRATE = 0x09;
public const byte SI_FUNCTION_NOT_SUPPORTED = 0x0a;
public const byte SI_GLOBAL_DATA_ERROR = 0x0b;
public const byte SI_SYSTEM_ERROR_CODE = 0x0c;
public const byte SI_READ_TIMED_OUT = 0x0d;
public const byte SI_WRITE_TIMED_OUT = 0x0e;
public const byte SI_IO_PENDING = 0x0f;
public const byte SI_NOTHING_TO_CANCEL = 0xa0;
/// <summary>
/// NLog logger
/// </summary>
protected ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
protected readonly IConfigurationManager _configurationManager;
protected readonly IConfiguration _configuration;
#endregion
#region PrivateClassFunctions
~DIOSiCp210x()
{
Dispose(false);
}
/// <summary>
///
/// </summary>
protected void Close()
{
int ret = CP210xRuntime.CP210xRT_Close(_handle);
if (ret != SI_SUCCESS)
{
throw new Exception("call to close returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
/// Dispose the object's resources
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
if (_state == State.Ready)
{
Close();
_state = State.Uninitialized;
}
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
/// <summary>
///
/// </summary>
/// <param name="product"></param>
/// <param name="length"></param>
/// <param name="convertToAscii"></param>
protected void GetDeviceProductString(ref byte[] product, ref byte length, bool convertToAscii)
{
int ret = CP210xRuntime.CP210xRT_GetDeviceProductString(_handle, product, ref length, convertToAscii);
if (ret != SI_SUCCESS)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
protected void GetNumDevices(ref uint numDevices)
{
int ret = CP210xRuntime.CP210xRT_GetNumDevices(ref numDevices);
if (ret != SI_SUCCESS)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="partNumber"></param>
protected void GetPartNumber(ref byte partNumber)
{
int ret = CP210xRuntime.CP210xRT_GetPartNumber(_handle, ref partNumber);
if (ret != SI_SUCCESS)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
protected void Open()
{
int ret = CP210xRuntime.CP210xRT_Open(_deviceNum, ref _handle);
if (ret != SI_SUCCESS)
{
throw new Exception("call to open returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="latch"></param>
/// <returns></returns>
protected virtual void ReadLatch(ref ushort latch)
{
int ret = CP210xRuntime.CP210xRT_ReadLatch(_handle, ref latch);
if (ret != SI_SUCCESS)
{
throw new Exception("call to read latch returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="mask"></param>
/// <param name="latch"></param>
/// <returns></returns>
protected virtual void WriteLatch(ushort mask, ushort latch)
{
int ret = CP210xRuntime.CP210xRT_WriteLatch(_handle, mask, latch);
if (ret != SI_SUCCESS)
{
throw new Exception("call to write latch returned error: " + ret.ToString() + " on card: " + _name);
}
}
#endregion
#region PublicClassFunctions
/// <summary>
/// DIOSiCp210x factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOSiCp210x(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
if (!Path.IsPathRooted(dioModuleDefPath))
dioModuleDefPath = Path.GetFullPath(Path.Combine(assemblyFolder, dioModuleDefPath));
_dioModuleConfig = new ConfigurationFile(dioModuleDefPath);
Boolean.TryParse(_dioModuleConfig.ReadValue(Name, ConfigIni.SHALL_WE_DRIVE_OUTPUT_UPON_INITIALIZATION.ToString()), out _shallWeInitializeOutput);
UInt32.TryParse(_dioModuleConfig.ReadValue(Name, ConfigIni.DEVICE_NUMBER.ToString()), out _deviceNum);
Int32.TryParse(_dioModuleConfig.ReadValue(Name, ConfigIni.NUM_INPUT_CHANNELS.ToString()), out _numInputChannels);
Int32.TryParse(_dioModuleConfig.ReadValue(Name, ConfigIni.NUM_OUTPUT_CHANNELS.ToString()), out _numOutputChannels);
Int32.TryParse(_dioModuleConfig.ReadValue(Name, ConfigIni.NUM_CHANNELS_PER_PORT.ToString()), out _numChannelPerPort);
Int32.TryParse(_dioModuleConfig.ReadValue(Name, ConfigIni.CHANNEL_START_INDEX.ToString()), out _channelStartIndex);
if (!(_channelStartIndex == 0 || _channelStartIndex == 1))
{
throw new Exception($"The value for key {ConfigIni.CHANNEL_START_INDEX.ToString()} in section {Name} must be 0 or 1 in {dioModuleDefPath}");
}
List<string> outputSignalNames = _dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.OUTPUT_SIGNALS}");
List<string> intputSignalNames = _dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.INPUT_SIGNALS}");
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = _dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
string[] infoTokens = iniLine.Split('|');
if (infoTokens.Length != 2)
{
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} does not contain 2 tokens");
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = _dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
}
_handle = IntPtr.Zero;
_state = State.Uninitialized;
_selfTestResult = SelfTestResult.Unknown;
}
/// <summary>
///
/// </summary>
/// <param name="deviceName"></param>
/// <param name="deviceNum"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public DIOSiCp210x(string deviceName, uint deviceNum)
{
_deviceNum = deviceNum;
_name = deviceName;
_handle = IntPtr.Zero;
_state = State.Uninitialized;
_selfTestResult = SelfTestResult.Unknown;
_logger = LogManager.GetCurrentClassLogger();
//for(int i = 0; i < inputPins.Count; i++)
//{
// inputPins[i] = Convert.ToUInt32(Math.Pow(2, Convert.ToDouble(inputPins[i])));
//}
//@@@ Do we need to pass in more args to configure the DIO (Baud?)
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
//could use this to cancel IO and flush the buffers
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
byte arrSize = 255;
byte[] deviceStringArray = new byte[arrSize];
GetDeviceProductString(ref deviceStringArray, ref arrSize, true);
return "This is a Silicon Labs CP2108 device: " + deviceStringArray.ToString();
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <returns></returns>
public virtual IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
ushort latchValue = 0;
ushort mask = (ushort)(0x1 << (int)bitIndex);
ReadLatch(ref latchValue);
return (IODatatypes.BitState)(latchValue & mask);
}
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
//@@@ call the other setup functions..Baud? Flow? Timeout? Others?
Open();
if (_shallWeInitializeOutput)
{
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelMap)
{
if (item.Value.initialValue != -1)
{
SetBit(item.Key, (IODatatypes.BitState)item.Value.initialValue);
}
}
}
_state = State.Ready;
}
else
{
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
/// Return list of signal names
/// </summary>
public List<string> GetSignalNames()
{
return new List<string>(_signalNameToChannelMap.Keys);
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
// card does not support self test
//throw new NotImplementedException("card does not support self test" + " on card " + _name);
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
Close();
Open();
}
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <param name="state"> high(open) or low(closed) </param>
///
public virtual void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
ushort mask = (ushort)(0x1 << (int)bitIndex);
if (state == IODatatypes.BitState.High)
{
WriteLatch(mask, mask);
}
else
{
WriteLatch(mask, 0);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void SetTristate(string signalName)
{
lock (_syncObj)
{
//@@@@ Is there a way to do this?
}
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
if (_state == State.Ready)
{
Close();
_state = State.Uninitialized;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <param name="frequencyInHz"></param>
/// <param name="dutyCylePercentage"></param>
public void StartClock(uint bit, double frequencyInHz, double dutyCylePercentage)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public void StopClock(uint bit)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
#endregion
}
}

View File

@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.DIOSiCp2010x</AssemblyName>
<Product>DIO SiCp 210x implementation</Product>
<Description>Digital IO SiCp 210x implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
<PackageReference Include="Raytheon.Instruments.GeneralIO.Contracts" Version="1.7.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DIOSim\DIOSim.csproj" />
</ItemGroup>
<!-- Copy all *.dlls and *.pdb in the output folder to a temp folder -->
<Target Name="CopyFiles" AfterTargets="AfterBuild">
<ItemGroup>
<FILES_1 Include="$(OutDir)*.dll" />
<FILES_2 Include="$(OutDir)*.pdb" />
</ItemGroup>
<Copy SourceFiles="@(FILES_1)" DestinationFolder="$(HalTempFolder)" />
<Copy SourceFiles="@(FILES_2)" DestinationFolder="$(HalTempFolder)" />
</Target>
</Project>

View File

@@ -0,0 +1,139 @@
// **********************************************************************************************************
// DIOSiCp210xFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOSiCp210xFactory")]
public class DIOSiCp210xFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public DIOSiCp210xFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOSiCp210xFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOSiCp210x(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
else
return new DIOSiCp210x(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using Win_API;
using Raytheon.Instruments.GeneralIO;
using CP210xRuntime_DLL;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
/// <summary>
///
/// </summary>
public class ECPDIOSiCp210x : DIOSiCp210x
{
private string _comPort = string.Empty;
/// <summary>
/// ECPDIOSiCp210x factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public ECPDIOSiCp210x(string deviceName, IConfigurationManager configurationManager, ILogger logger)
: base(deviceName, configurationManager, logger)
{
_comPort = _dioModuleConfig.ReadValue(Name, ConfigIni.COM_PORT.ToString());
}
/// <summary>
///
/// </summary>
/// <param name="deviceName"></param>
/// <param name="deviceNum"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public ECPDIOSiCp210x(string deviceName, uint deviceNum)
: base(deviceName, deviceNum)
{ }
/// <summary>
///
/// </summary>
/// <param name="deviceName"></param>
/// <param name="comPort"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public ECPDIOSiCp210x(string deviceName, string comPort)
: base(deviceName, 0)
{
_comPort = comPort;
}
/// <summary>
///
/// </summary>
/// <param name="comPort"></param>
public void SetComPort(string comPort)
{
_comPort = comPort;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private IntPtr GetHandle()
{
var comString = $"\\\\.\\{_comPort}";
var securityAttbs = NativeMethods.InitWithDefaultAttributes();
//Open a handle the device specified
IntPtr hDevice = NativeMethods.CreateFileA(comString,
NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE,
0,
ref securityAttbs,
3,
NativeMethods.FILE_ATTRIBUTE_NORMAL | NativeMethods.FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
if (hDevice != NativeMethods.INVALID_HANDLE_VALUE)
{
return hDevice;
}
else
{
throw new Exception($"Unable to get a valid handle using COM port {_comPort}");
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public ushort ReadLatch()
{
var handle = GetHandle();
ushort latch = 0;
var errCode = CP210xRuntime.CP210xRT_ReadLatch(handle, ref latch);
NativeMethods.CloseHandle(handle);
if (errCode == SI_SUCCESS)
{
return latch;
}
else
{
throw new Exception($"Error when reading CP210X latch. Error code returned: {errCode}");
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <returns></returns>
public override IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
ushort mask = (ushort)(0x1 << (int)bitIndex);
var latch = ReadLatch();
return (IODatatypes.BitState)(latch & mask);
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <param name="state"></param>
public override void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
ushort mask = (ushort)(0x1 << (int)bitIndex);
if (state == IODatatypes.BitState.High)
{
WriteLatch(mask, mask);
}
else
{
WriteLatch(mask, 0);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="mask"></param>
/// <param name="latch"></param>
/// <returns></returns>
protected override void WriteLatch(ushort mask, ushort latch)
{
var handle = GetHandle();
int ret = CP210xRuntime.CP210xRT_WriteLatch(handle, mask, latch);
NativeMethods.CloseHandle(handle);
if (ret != SI_SUCCESS)
{
throw new Exception("call to write latch returned error: " + ret.ToString() + " on card: " + _name);
}
}
}
}

View File

@@ -0,0 +1,139 @@
// **********************************************************************************************************
// ECPDIOSiCp210xFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "ECPDIOSiCp210xFactory")]
public class ECPDIOSiCp210xFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public ECPDIOSiCp210xFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public ECPDIOSiCp210xFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new ECPDIOSiCp210x(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
else
return new ECPDIOSiCp210x(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1,927 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using SIUSBXP_DLL;
using System.Collections.Specialized;
using NLog;
using Raytheon.Common;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
/// <summary>
/// Class for controlling a Silicon Labs CP2108 UART GPIO device
/// </summary>
public class DIOSiUSBXp : IGeneralIO, IDisposable
{
#region PublicClassMembers
#endregion
#region PrivateClassMembers
private IntPtr _handle;
private uint _deviceNum;
private State _state;
private string _name;
private SelfTestResult _selfTestResult;
private object _syncObj = new Object();
private int _numChannelPerPort = 8;
private int _channelStartIndex = 0;
private int _numInputChannels;
private int _numOutputChannels;
private bool _shallWeInitializeOutput = false;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#endregion
#region PrivateClassFunctions
~DIOSiUSBXp()
{
Dispose(false);
}
/// <summary>
///
/// </summary>
private void CancelIo()
{
int ret = SIUSBXP.SI_CancelIo(_handle);
if (ret != 0)
{
throw new Exception("call to cancel IO returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
private void CancelIoEx()
{
int ret = SIUSBXP.SI_CancelIoEx(_handle, IntPtr.Zero);
if (ret != 0)
{
throw new Exception("call to cancel IO EX returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="numBytesInQueue"></param>
/// <param name="queueStatus"></param>
private void CheckRXQueue(ref uint numBytesInQueue, ref uint queueStatus)
{
int ret = SIUSBXP.SI_CheckRXQueue(_handle, ref numBytesInQueue, ref queueStatus);
if (ret != 0)
{
throw new Exception("call to check Rx Queue returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
private void Close()
{
int ret = SIUSBXP.SI_Close(_handle);
if (ret != 0)
{
throw new Exception("call to close returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="ioControlCode"></param>
/// <param name="inBuffer"></param>
/// <param name="bytesToRead"></param>
/// <param name="outBuffer"></param>
/// <param name="bytesToWrite"></param>
/// <param name="bytesSucceeded"></param>
/// <returns></returns>
private void DeviceIOControl(uint ioControlCode, ref byte[] inBuffer, uint bytesToRead, ref byte[] outBuffer, uint bytesToWrite, ref uint bytesSucceeded)
{
int ret = SIUSBXP.SI_DeviceIOControl(_handle, ioControlCode, inBuffer, bytesToRead, outBuffer, bytesToWrite, ref bytesSucceeded);
if (ret != 0)
{
throw new Exception("call to SI_DeviceIOControl returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
/// Dispose the object's resources
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
if (_state == State.Ready)
{
Close();
_state = State.Uninitialized;
}
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
/// <summary>
///
/// </summary>
private void FlushBuffers()
{
int ret = SIUSBXP.SI_FlushBuffers(_handle, 1, 1);
if (ret != 0)
{
throw new Exception("call to flush returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="product"></param>
/// <param name="length"></param>
/// <param name="convertToAscii"></param>
private void GetDeviceProductString(ref byte[] product, ref byte length, bool convertToAscii)
{
int ret = SIUSBXP.SI_GetDeviceProductString(_handle, product, ref length, convertToAscii);
if (ret != 0)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="highVersion"></param>
/// <param name="lowVersion"></param>
private void GetDLLVersion(ref uint highVersion, ref uint lowVersion)
{
int ret = SIUSBXP.SI_GetDLLVersion(ref highVersion, ref lowVersion);
if (ret != 0)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="highVersion"></param>
/// <param name="lowVersion"></param>
private void GetDriverVersion(ref uint highVersion, ref uint lowVersion)
{
int ret = SIUSBXP.SI_GetDriverVersion(ref highVersion, ref lowVersion);
if (ret != 0)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="LibVersion"></param>
private void GetInterfaceNumber(ref byte LibVersion)
{
int ret = SIUSBXP.SI_GetInterfaceNumber(_handle, ref LibVersion);
if (ret != 0)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="modemStatus"></param>
private void GetModemStatus(ref byte modemStatus)
{
int ret = SIUSBXP.SI_GetModemStatus(_handle, ref modemStatus);
if (ret != 0)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
private void GetNumDevices()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
/// <param name="libVersion"></param>
private void GetPartLibraryVersion(ref int libVersion)
{
int ret = SIUSBXP.SI_GetPartLibraryVersion(_handle, ref libVersion);
if (ret != 0)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="partNumber"></param>
private void GetPartNumber(ref byte partNumber)
{
int ret = SIUSBXP.SI_GetPartNumber(_handle, ref partNumber);
if (ret != 0)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
/// Can use as self-test
/// </summary>
/// <returns></returns>
private void GetProductString()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
/// <param name="readTimeoutMs"></param>
/// <param name="writeTimeoutMs"></param>
private void GetTimeouts(ref uint readTimeoutMs, ref uint writeTimeoutMs)
{
int ret = SIUSBXP.SI_GetTimeouts(ref readTimeoutMs, ref writeTimeoutMs);
if (ret != 0)
{
throw new Exception("call returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
private void Open()
{
int ret = SIUSBXP.SI_Open(_deviceNum, ref _handle);
if (ret != 0)
{
throw new Exception("call to open returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="buff"></param>
/// <param name="numBytesToRead"></param>
/// <returns></returns>
private uint Read(ref byte[] buff, uint numBytesToRead)
{
uint bytesRead = 0;
//uint bytesToReadUint = Convert.ToUInt32(bytesToRead);
int ret = SIUSBXP.SI_Read(_handle, buff, numBytesToRead, ref bytesRead, IntPtr.Zero);
if (ret != 0)
{
throw new Exception("call to read latch returned error: " + ret.ToString() + " on card: " + _name);
}
if (numBytesToRead != bytesRead)
{
throw new Exception("Commanded " + numBytesToRead + " bytes, received " + bytesRead + " bytes on card: " + _name);
}
return bytesRead;
}
/// <summary>
///
/// </summary>
/// <param name="latch"></param>
/// <returns></returns>
private void ReadLatch(ref byte latch)
{
int ret = SIUSBXP.SI_ReadLatch(_handle, ref latch);
if (ret != 0)
{
throw new Exception("call to read latch returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="baudDivisor"></param>
/// <returns></returns>
private void SetBaudDivisor(ushort baudDivisor)
{
int ret = SIUSBXP.SI_SetBaudDivisor(_handle, baudDivisor);
if (ret != 0)
{
throw new Exception("call to returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="baudRate"></param>
private void SetBaudRate(uint baudRate)
{
int ret = SIUSBXP.SI_SetBaudRate(_handle, baudRate);
if (ret != 0)
{
throw new Exception("call to returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
/// 0 or 1
/// </summary>
/// <param name="breakState"></param>
/// <returns></returns>
private void SetBreak(ushort breakState)
{
int ret = SIUSBXP.SI_SetBreak(_handle, breakState);
if (ret != 0)
{
throw new Exception("call to returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// CTS
/// SI_STATUS_INPUT = 0x00;
/// SI_HANDSHAKE_LINE = 0x01;
/// RTS
/// SI_HELD_INACTIVE = 0x00;
/// SI_HELD_ACTIVE = 0x01;
/// SI_FIRMWARE_CONTROLLED = 0x02;
/// SI_TRANSMIT_ACTIVE_SIGNAL = 0x03;
/// DTR
/// SI_HELD_INACTIVE = 0x00;
/// SI_HELD_ACTIVE = 0x01;
/// SI_FIRMWARE_CONTROLLED = 0x02;
/// DSR
/// SI_STATUS_INPUT = 0x00;
/// SI_HANDSHAKE_LINE = 0x01;
/// DCD
/// SI_STATUS_INPUT = 0x00;
/// SI_HANDSHAKE_LINE = 0x01;
/// FlowXonXoff
/// 0 or 1
/// </summary>
/// <returns></returns>
private void SetFlowControl(byte cts, byte rts, byte dtr, byte dsr, byte dcd, bool flowXOnOff)
{
int ret = SIUSBXP.SI_SetFlowControl(_handle, cts, rts, dtr, dsr, dcd, flowXOnOff);
if (ret != 0)
{
throw new Exception("call to returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
/// Set the line control
/// Bits 0-3: Number of stop bits
/// 0: 1 stop bit
/// 1: 1.5 stop bits
/// 2: 2 stop bits
/// Bits 4-7: Parity
/// 0: none
/// 1: Odd
/// 2: Even
/// 3: Mark
/// 4: Space
/// Bits 8-15: Number of bits per word
/// 5, 6, 7, or 8
/// </summary>
/// <returns></returns>
private void SetLineControl(ushort lineControl)
{
int ret = SIUSBXP.SI_SetLineControl(_handle, lineControl);
if (ret != 0)
{
throw new Exception("call to returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="readTimeoutMs"></param>
/// <param name="writeTimeoutMs"></param>
private void SetTimeout(uint readTimeoutMs, uint writeTimeoutMs)
{
int ret = SIUSBXP.SI_SetTimeouts(readTimeoutMs, writeTimeoutMs);
if (ret != 0)
{
throw new Exception("call to returned error: " + ret.ToString() + " on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="writeBuff"></param>
/// <param name="numBytesToWrite"></param>
private void Write(ref byte[] writeBuff, uint numBytesToWrite)
{
uint bytesWritten = 0;
//uint bytesToWriteUint = Convert.ToUInt32(numBytesToWrite);
int ret = SIUSBXP.SI_Write(_handle, writeBuff, numBytesToWrite, ref bytesWritten, IntPtr.Zero);
if (ret != 0)
{
throw new Exception("call to write latch returned error: " + ret.ToString() + " on card: " + _name);
}
if (numBytesToWrite != bytesWritten)
{
throw new Exception("Commanded " + numBytesToWrite + " bytes, wrote " + bytesWritten + " bytes on card: " + _name);
}
}
/// <summary>
///
/// </summary>
/// <param name="mask"></param>
/// <param name="latch"></param>
/// <returns></returns>
private void WriteLatch(byte mask, byte latch)
{
int ret = SIUSBXP.SI_WriteLatch(_handle, mask, latch);
if (ret != 0)
{
throw new Exception("call to write latch returned error: " + ret.ToString() + " on card: " + _name);
}
}
#endregion
#region PublicClassFunctions
/// <summary>
/// DIOSiUSBXp factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOSiUSBXp(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
if (!Path.IsPathRooted(dioModuleDefPath))
dioModuleDefPath = Path.GetFullPath(Path.Combine(assemblyFolder, dioModuleDefPath));
IConfigurationFile dioModuleConfig = new ConfigurationFile(dioModuleDefPath);
Boolean.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.SHALL_WE_DRIVE_OUTPUT_UPON_INITIALIZATION.ToString()), out _shallWeInitializeOutput);
UInt32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.DEVICE_NUMBER.ToString()), out _deviceNum);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_INPUT_CHANNELS.ToString()), out _numInputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_OUTPUT_CHANNELS.ToString()), out _numOutputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_CHANNELS_PER_PORT.ToString()), out _numChannelPerPort);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.CHANNEL_START_INDEX.ToString()), out _channelStartIndex);
if (!(_channelStartIndex == 0 || _channelStartIndex == 1))
{
throw new Exception($"The value for key {ConfigIni.CHANNEL_START_INDEX.ToString()} in section {Name} must be 0 or 1 in {dioModuleDefPath}");
}
List<string> outputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.OUTPUT_SIGNALS}");
List<string> intputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.INPUT_SIGNALS}");
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
string[] infoTokens = iniLine.Split('|');
if (infoTokens.Length != 2)
{
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} does not contain 2 tokens");
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
}
_handle = IntPtr.Zero;
_state = State.Uninitialized;
_selfTestResult = SelfTestResult.Unknown;
}
/// <summary>
///
/// </summary>
/// <param name="deviceName"></param>
/// <param name="deviceNum"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public DIOSiUSBXp(string deviceName, uint deviceNum)
{
_deviceNum = deviceNum;
_name = deviceName;
_handle = IntPtr.Zero;
_state = State.Uninitialized;
_selfTestResult = SelfTestResult.Unknown;
_logger = LogManager.GetCurrentClassLogger();
//@@@ Do we need to pass in more args to configure the DIO (Baud?)
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
//could use this to cancel IO and flush the buffers
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
byte arrSize = 255;
byte[] deviceStringArray = new byte[arrSize];
GetDeviceProductString(ref deviceStringArray, ref arrSize, true);
return "This is a Silicon Labs CP2108 device: " + deviceStringArray.ToString();
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
byte latchValue = 0;
ReadLatch(ref latchValue);
BitVector32 bits = new BitVector32(latchValue);
return (IODatatypes.BitState)(bits[bitIndex] ? 1 : 0);
}
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
//@@@ call the other setup functions..Baud? Flow? Timeout? Others?
Open();
_state = State.Ready;
}
else
{
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
/// Return list of signal names
/// </summary>
public List<string> GetSignalNames()
{
return new List<string>(_signalNameToChannelMap.Keys);
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
// card does not support self test
//throw new NotImplementedException("card does not support self test" + " on card " + _name);
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
Close();
Open();
}
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <param name="state"> high(open) or low(closed) </param>
///
public void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
byte mask = (byte)bitIndex;
if (state == IODatatypes.BitState.High)
{
WriteLatch(mask, 1);
}
else
{
WriteLatch(mask, 0);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void SetTristate(string signalName)
{
lock (_syncObj)
{
//@@@@ Is there a way to do this?
}
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
if (_state == State.Ready)
{
Close();
_state = State.Uninitialized;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <param name="frequencyInHz"></param>
/// <param name="dutyCylePercentage"></param>
public void StartClock(uint bit, double frequencyInHz, double dutyCylePercentage)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public void StopClock(uint bit)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
#endregion
}
}

View File

@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.DIOSiUSBXp</AssemblyName>
<RootNamespace>Raytheon.Instruments</RootNamespace>
<Product> implementation</Product>
<Description> implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
<PackageReference Include="Raytheon.Instruments.GeneralIO.Contracts" Version="1.7.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DIOSim\DIOSim.csproj" />
</ItemGroup>
<!-- Copy all *.dlls and *.pdb in the output folder to a temp folder -->
<Target Name="CopyFiles" AfterTargets="AfterBuild">
<ItemGroup>
<FILES_1 Include="$(OutDir)*.dll" />
<FILES_2 Include="$(OutDir)*.pdb" />
</ItemGroup>
<Copy SourceFiles="@(FILES_1)" DestinationFolder="$(HalTempFolder)" />
<Copy SourceFiles="@(FILES_2)" DestinationFolder="$(HalTempFolder)" />
</Target>
</Project>

View File

@@ -0,0 +1,139 @@
// **********************************************************************************************************
// DIOSiUSBXpFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOSiUSBXpFactory")]
public class DIOSiUSBXpFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public DIOSiUSBXpFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOSiUSBXpFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOSiUSBXp(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
else
return new DIOSiUSBXp(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1,274 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace SIUSBXP_DLL
{
public class SIUSBXP
{
static IntPtr zero = IntPtr.Zero;
// Return codes
public const byte SI_SUCCESS = 0x00;
public const byte SI_DEVICE_NOT_FOUND = 0xFF;
public const byte SI_INVALID_HANDLE = 0x01;
public const byte SI_READ_ERROR = 0x02;
public const byte SI_RX_QUEUE_NOT_READY = 0x03;
public const byte SI_WRITE_ERROR = 0x04;
public const byte SI_RESET_ERROR = 0x05;
public const byte SI_INVALID_PARAMETER = 0x06;
public const byte SI_INVALID_REQUEST_LENGTH = 0x07;
public const byte SI_DEVICE_IO_FAILED = 0x08;
public const byte SI_INVALID_BAUDRATE = 0x09;
public const byte SI_FUNCTION_NOT_SUPPORTED = 0x0a;
public const byte SI_GLOBAL_DATA_ERROR = 0x0b;
public const byte SI_SYSTEM_ERROR_CODE = 0x0c;
public const byte SI_READ_TIMED_OUT = 0x0d;
public const byte SI_WRITE_TIMED_OUT = 0x0e;
public const byte SI_IO_PENDING = 0x0f;
public const byte SI_NOTHING_TO_CANCEL = 0xa0;
// GetProductString() function flags
public const byte SI_RETURN_SERIAL_NUMBER = 0x00;
public const byte SI_RETURN_DESCRIPTION = 0x01;
public const byte SI_RETURN_LINK_NAME = 0x02;
public const byte SI_RETURN_VID = 0x03;
public const byte SI_RETURN_PID = 0x04;
// RX Queue status flags
public const byte SI_RX_NO_OVERRUN = 0x00;
public const byte SI_RX_EMPTY = 0x00;
public const byte SI_RX_OVERRUN = 0x01;
public const byte SI_RX_READY = 0x02;
// Buffer size limits
public const int SI_MAX_DEVICE_STRLEN = 256;
public const int SI_MAX_READ_SIZE = 4096 * 16;
public const int SI_MAX_WRITE_SIZE = 4096;
// Input and Output pin Characteristics
public const byte SI_HELD_INACTIVE = 0x00;
public const byte SI_HELD_ACTIVE = 0x01;
public const byte SI_FIRMWARE_CONTROLLED = 0x02;
public const byte SI_RECEIVE_FLOW_CONTROL = 0x02;
public const byte SI_TRANSMIT_ACTIVE_SIGNAL = 0x03;
public const byte SI_STATUS_INPUT = 0x00;
public const byte SI_HANDSHAKE_LINE = 0x01;
// Mask and Latch value bit definitions
public const int SI_GPIO_0 = 0x01;
public const int SI_GPIO_1 = 0x02;
public const int SI_GPIO_2 = 0x04;
public const int SI_GPIO_3 = 0x08;
public const int SI_GPIO_4 = 0x0010;
public const int SI_GPIO_5 = 0x0020;
public const int SI_GPIO_6 = 0x0040;
public const int SI_GPIO_7 = 0x0080;
public const int SI_GPIO_8 = 0x0100;
public const int SI_GPIO_9 = 0x0200;
public const int SI_GPIO_10 = 0x0400;
public const int SI_GPIO_11 = 0x0800;
public const int SI_GPIO_12 = 0x1000;
public const int SI_GPIO_13 = 0x2000;
public const int SI_GPIO_14 = 0x4000;
public const int SI_GPIO_15 = 0x8000;
// GetDeviceVersion() return codes
public const byte SI_USBXPRESS_EFM8 = 0x80;
public const byte SI_USBXPRESS_EFM32 = 0x81;
public const byte SI_CP2101_VERSION = 0x01;
public const byte SI_CP2102_VERSION = 0x02;
public const byte SI_CP2103_VERSION = 0x03;
public const byte SI_CP2104_VERSION = 0x04;
public const byte SI_CP2105_VERSION = 0x05;
public const byte SI_CP2108_VERSION = 0x08;
public const byte SI_CP2109_VERSION = 0x09;
public const byte SI_CP2102N_QFN28_VERSION = 0x20;
public const byte SI_CP2102N_QFN24_VERSION = 0x21;
public const byte SI_CP2102N_QFN20_VERSION = 0x22;
[DllImport("SiUSBXp.dll")]
public static extern int SI_GetNumDevices(
ref uint lpdwNumDevices
);
// Caller must set StringBuilder capacity to max possible
// returned string size before calling this function
[DllImport("SiUSBXp.dll")]
public static extern int SI_GetProductString(
uint dwDeviceNum,
StringBuilder lpvDeviceString,
uint dwFlags
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_Open(
uint dwDevice,
ref IntPtr cyHandle
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_Close(
IntPtr cyHandle
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_Read(
IntPtr cyHandle,
[Out] byte[] lpBuffer,
uint dwBytesToRead,
ref uint lpdwBytesReturned,
IntPtr o
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_Write(
IntPtr cyHandle,
[In] byte[] lpBuffer,
uint dwBytesToWrite,
ref uint lpdwBytesWritten,
IntPtr o
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_FlushBuffers(
IntPtr cyHandle,
byte FlushTransmit,
byte FlushReceive
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_SetTimeouts(
uint dwReadTimeoutInMs,
uint dwWriteTimeoutInMs
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_GetTimeouts(
ref uint lpdwReadTimeout,
ref uint lpdwWriteTimeout
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_CheckRXQueue(
IntPtr cyHandle,
ref uint lpdwNumBytesInQueue,
ref uint lpdwQueueStatus
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_SetBaudRate(
IntPtr cyHandle,
uint dwBaudRate
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_SetBaudDivisor(
IntPtr cyHandle,
ushort wBaudDivisor
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_SetLineControl(
IntPtr cyHandle,
ushort wLineControl
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_SetFlowControl(
IntPtr cyHandle,
byte bCTS_MaskCode,
byte bRTS_MaskCode,
byte bDTR_MaskCode,
byte bDSR_MaskCode,
byte bDCD_MaskCode,
bool bFlowXonXoff
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_GetModemStatus(
IntPtr cyHandle,
ref byte ModemStatus
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_SetBreak(
IntPtr cyHandle,
ushort wBreakState
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_ReadLatch(
IntPtr cyHandle,
ref byte lpbLatch
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_WriteLatch(
IntPtr cyHandle,
byte bMask,
byte bLatch
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_GetPartNumber(
IntPtr cyHandle,
ref byte lpbPartNum
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_DeviceIOControl(
IntPtr cyHandle,
uint dwIoControlCode,
[In] byte[] lpInBuffer,
uint dwBytesToRead,
[Out] byte[] lpOutBuffer,
uint dwBytesToWrite,
ref uint lpdwBytesSucceeded
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_GetPartLibraryVersion(
IntPtr cyHandle,
ref int pLibVersion
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_GetInterfaceNumber(
IntPtr cyHandle,
ref byte pLibVersion
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_GetDeviceProductString(
IntPtr cyHandle,
[Out] byte[] lpProduct,
ref byte lpbLength,
bool bConvertToASCII
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_GetDLLVersion(
ref uint HighVersion,
ref uint LowVersion
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_GetDriverVersion(
ref uint HighVersion,
ref uint LowVersion
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_CancelIo(
IntPtr cyHandle
);
[DllImport("SiUSBXp.dll")]
public static extern int SI_CancelIoEx(
IntPtr cyHandle,
IntPtr o
);
}
}

View File

@@ -0,0 +1,428 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using Raytheon.Common;
using NLog;
using System.IO;
using System.Reflection;
using System.Runtime.Remoting;
namespace Raytheon.Instruments
{
/// <summary>
/// A Simulated DIO class
/// </summary>
public class DIOSim : IGeneralIO
{
#region PrivateClassMembers
private string _name;
private SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
private const int _channelStartIndex = 0;
private int _numInputChannels;
private int _numOutputChannels;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
#endregion
#region PrivateClassFunctions
/// <summary>
/// The finalizer.
/// </summary>
~DIOSim()
{
Dispose(false);
}
/// <summary>
/// Dispose of this object.
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
// nothing to do here
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
#endregion
#region PublicClassFunctions
/// <summary>
/// DIOSim factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOSim(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
if (!Path.IsPathRooted(dioModuleDefPath))
dioModuleDefPath = Path.GetFullPath(Path.Combine(assemblyFolder, dioModuleDefPath));
IConfigurationFile dioModuleConfig = new ConfigurationFile(dioModuleDefPath);
Int32.TryParse(dioModuleConfig.ReadValue(Name, "NUM_OUTPUT_CHANNELS"), out _numOutputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, "NUM_INPUT_CHANNELS"), out _numInputChannels);
List<string> outputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.OUTPUT_SIGNALS}");
List<string> intputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.INPUT_SIGNALS}");
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
string[] infoTokens = iniLine.Split('|');
if (infoTokens.Length != 2)
{
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} does not contain 2 tokens");
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
}
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
}
/// <summary>
/// Constructor for DIO simulation.
/// </summary>
/// <param name="name"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public DIOSim(string name)
{
_name = name;
_logger = LogManager.GetCurrentClassLogger();
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
}
/// <summary>
/// Return list of signal names
/// </summary>
public List<string> GetSignalNames()
{
return new List<string>(_signalNameToChannelMap.Keys);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is a DIO Sim called " + _name;
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels} on card " + _name);
}
return IODatatypes.BitState.Low;
}
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
_state = State.Ready;
}
else
{
throw new Exception("DIOSim::Initialize() - expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
_selfTestResult = SelfTestResult.Pass;
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
}
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
/// <param name="channelNum"></param>
/// <param name="state"></param>
public void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels} on card " + _name);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void SetTristate(string signalName)
{
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
_state = State.Uninitialized;
}
}
#endregion
}
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.DIOSim</AssemblyName>
<Product>DIO Sim implementation</Product>
<Description>DIO Sim implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.1.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
<PackageReference Include="Raytheon.Instruments.GeneralIO.Contracts" Version="1.7.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,135 @@
// **********************************************************************************************************
// DIOSimFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOSimFactory")]
public class DIOSimFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public DIOSimFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOSimFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOSim(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOSim(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1,719 @@
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
/*Channels can operate in two modes. Static or dynamic.Static mode is sort of like have a register control the drive and expect states of a channel.
You load the register with the logic 1 or 0 that you want to drive or detect and then this is applied by to the UUT all at one time.
The 1 / 0 values are used to determine the high / low(VIH / VIL) from the drive side or the high / low expected(VOH / VOL) from the detector.
The channel is bidirectional.The various pin opcodes determine the whether you want to drive or detect or both.
IH or IL is drive only the detect is a don't care. OH or OL is detect only the drive is off. MH or ML is both drive and detect.
This later opcode is called monitor high/low. You might use this if you want to Monitor the drive to verify the signal is being output to the UUT.
In dynamic mode, the pin opcodes are loaded into a memory, the pattern memory, behind each channel. This is the dynamic pattern loading process.
A pattern controller is used to sequence the patterns out of the pattern memory and it has a instruction memory that is used to control this sequence of this pin opcodes
from the pattern memory.You can sequence patterns one after the other, repeat a pattern memory location several times, repeat a sequence of pattern memory locations
multiple times.The repeating pattern locations can be controlled by a count or a condition of the PASS/ FAIL test result of a pattern.The pattern controller also controls
whether a test should be associated with a pattern memory location. The are also pattern controller instruction halt that defines the last pattern of a sequence.
In dynamic mode you also have a timing sets that define the pattern time, when a channel will assert a high or low in that pattern time or when to observe the
detector in the pattern time.There is a memory for holding this information as well so that you can have different timing from one pattern to another.
After the memories have been loaded, operation of the pattern sequence is turned over to the pattern controller to run.
This starts applying the patterns under the pattern controller sequence instructions until a halt instruction is executed where it returns control back to the driver.
This is called dynamic pattern set execution or a dynamic burst.During the burst, another memory element is used to capture and record the pattern to pattern
pass fail information as well as what pin have failed.There are API functions to retrieve this information.*/
using Ivi.Driver;
using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using Teradyne.eDigital;
using Raytheon.Instruments.GeneralIO;
using NLog;
using Raytheon.Common;
using System.Xml.Linq;
namespace Raytheon.Instruments
{
/// <summary>
/// The EDigital 6020A 1_3_11 card
/// </summary>
public class DIOTeradyneEDigital6020A : IGeneralIO, IDisposable
{
#region PrivateClassMembers
private eDigital _dio;
private string _name;
private readonly string _dioAddress;
private Raytheon.Instruments.SelfTestResult _selfTestResult;
private State _state;
private readonly string _options;
private Dictionary<uint, IDynamic> _clocks;
private object _syncObj = new Object();
private int _numChannelPerPort = 8;
private int _channelStartIndex = 0;
private int _numInputChannels;
private int _numOutputChannels;
private bool _shallWeInitializeOutput = false;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#endregion
#region PrivateClassFunctions
/// <summary>
/// The finalizer.
/// </summary>
~DIOTeradyneEDigital6020A()
{
Dispose(false);
}
/// <summary>
/// Dispose of this object.
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
if (_state == State.Ready)
{
_dio.Utility.Reset();
_dio.Close();
_dio.Dispose();
_state = State.Uninitialized;
}
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
#endregion
#region PublicClassFunctions
/// <summary>
/// DIOTeradyneEDigital6020A factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOTeradyneEDigital6020A(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
if (!Path.IsPathRooted(dioModuleDefPath))
dioModuleDefPath = Path.GetFullPath(Path.Combine(assemblyFolder, dioModuleDefPath));
IConfigurationFile dioModuleConfig = new ConfigurationFile(dioModuleDefPath);
Boolean.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.SHALL_WE_DRIVE_OUTPUT_UPON_INITIALIZATION.ToString()), out _shallWeInitializeOutput);
_dioAddress = dioModuleConfig.ReadValue(Name, ConfigIni.DIO_ADDRESS.ToString());
_dioAddress = dioModuleConfig.ReadValue(Name, ConfigIni.DIO_OPTIONS.ToString());
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_INPUT_CHANNELS.ToString()), out _numInputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_OUTPUT_CHANNELS.ToString()), out _numOutputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_CHANNELS_PER_PORT.ToString()), out _numChannelPerPort);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.CHANNEL_START_INDEX.ToString()), out _channelStartIndex);
if (!(_channelStartIndex == 0 || _channelStartIndex == 1))
{
throw new Exception($"The value for key {ConfigIni.CHANNEL_START_INDEX.ToString()} in section {Name} must be 0 or 1 in {dioModuleDefPath}");
}
List<string> outputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.OUTPUT_SIGNALS}");
List<string> intputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.INPUT_SIGNALS}");
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
string[] infoTokens = iniLine.Split('|');
if (infoTokens.Length != 2)
{
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} does not contain 2 tokens");
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
}
_selfTestResult = Raytheon.Instruments.SelfTestResult.Unknown;
_state = State.Uninitialized;
_clocks = new Dictionary<uint, IDynamic>();
// set in Initialize()
_dio = null;
}
/// <summary>
///
/// </summary>
/// <param name="dioName"></param>
/// <param name="dioAddress"></param>
/// <param name="options"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public DIOTeradyneEDigital6020A(string dioName, string dioAddress, string options)
{
_name = dioName;
_dioAddress = dioAddress;
_options = options;
_selfTestResult = Raytheon.Instruments.SelfTestResult.Unknown;
_state = State.Uninitialized;
_clocks = new Dictionary<uint, IDynamic>();
_logger = LogManager.GetCurrentClassLogger();
// set in Initialize()
_dio = null;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is " + _name + " an EDigital 6020A static IO driver";
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
int mappedChannal = _dio.Pinmap.Find("CH" + bitIndex);
_dio.Pin.SetChannelMode(ChannelMode.Static, mappedChannal);
IStaticPattern pattern = _dio.Static.Pattern.SetPinOpcode(PinOpcode.IOX, mappedChannal);
pattern.Run();
return (IODatatypes.BitState)_dio.Static.FetchCapturedData(mappedChannal);
}
}
/// <summary>
///
/// </summary>
/// <param name="channelNo"></param>
/// <returns></returns>
/*public DioMeasurementInstruments.SignalState GetOutputSignalState(uint channelNo)
{
lock (_syncObj)
{
int mappedChannal = Pinmap.Channel((int)channelNo);
if (_outputPins.Contains((int)channelNo) == false)
{
throw new Exception("channel " + channelNo + " was not specified as an output channel at the time of construction");
}
// Monitor Low pin opcode specifies to drive and expect low.
IStaticPattern pattern = _dio.Static.Pattern.SetPinOpcode(PinOpcode.ML, mappedChannal);
// teradyne examples do not check the result, we wont either
Result res = pattern.Run();
/*if (res != Result.Pass)
{
throw new Exception("SetPinOpcode for channel: " + channelNo + " failed with result: " + res.ToString());
}*/
/*var testResult = _dio.Static.FetchResult();
if (testResult == Result.Pass)
{
return DioMeasurementInstruments.SignalState.LOW;
}
else
{
return DioMeasurementInstruments.SignalState.HIGH;
}
}
}*/
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
_dio = new eDigital(_dioAddress, false, true, _options);
// these probably are not needed
_dio.Utility.Reset();
_dio.Pinmap.Reset();
// enable the system
_dio.Instrument.SystemEnable = true;
_dio.Static.Delay = PrecisionTimeSpan.FromMicroseconds(100);
// set the channel modes
for (int channel= _channelStartIndex; channel < (_numInputChannels + _channelStartIndex); channel++)
{
int mappedChannal = _dio.Pinmap.Find("CH" + channel);
if (mappedChannal == -1)
{
throw new Exception("input channel " + channel.ToString() + " is not valid");
}
_dio.Pin.SetChannelMode(ChannelMode.Static, mappedChannal);
}
// set the channel modes
for (int channel = _channelStartIndex; channel < (_numOutputChannels + _channelStartIndex); channel++)
{
//tbd if this is needed
int mappedChannal = _dio.Pinmap.Find("CH" + channel);
if (mappedChannal == -1)
{
throw new Exception("output channel " + channel.ToString() + " is not valid");
}
_dio.Pin.SetChannelMode(ChannelMode.Static, mappedChannal);
}
if (_shallWeInitializeOutput)
{
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelMap)
{
if (item.Value.initialValue != -1)
{
SetBit(item.Key, (IODatatypes.BitState)item.Value.initialValue);
}
}
}
_state = State.Ready;
}
else
{
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
/// Return list of signal names
/// </summary>
public List<string> GetSignalNames()
{
return new List<string>(_signalNameToChannelMap.Keys);
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public Raytheon.Instruments.SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
Ivi.Driver.SelfTestResult res = _dio.Utility.SelfTest();
if (res.Code != 0)
{
_selfTestResult = Raytheon.Instruments.SelfTestResult.Fail;
throw new Exception("self test returned: " + res.Code + "," + res.Message + " on card " + _name);
}
_selfTestResult = Raytheon.Instruments.SelfTestResult.Pass;
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
public Raytheon.Instruments.SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
public void SetTristate(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + Name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
int mappedChannal = _dio.Pinmap.Find("CH" + bitIndex);
IStaticPattern pattern = _dio.Static.Pattern.SetPinOpcode(PinOpcode.IOX, mappedChannal);
Result res = _dio.Static.Pattern.Run();
//teradyne example does not check return value, we wont either
/*if (res != Result.Pass)
{
throw new Exception("SetPinOpcode for channel: " + channelNo + " to state " + state.ToString() + " failed with result: " + res.ToString());
}*/
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <param name="state"></param>
public void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
int mappedChannal = _dio.Pinmap.Find("CH" + bitIndex);
IStaticPattern pattern = _dio.Static.Pattern.SetPinOpcode((PinOpcode)((int)state+1), mappedChannal);
_dio.Static.Pattern.Run();
}
}
/// <summary>
/// Generate a free run clock
/// </summary>
/// <param name="bit">The channel index</param>
/// <param name="frequency">The frequency in Hz</param>
/// <param name="dutyCylePercentage">ex: .5 for 50% duty cycle</param>
public void StartClock(uint bit, double frequencyInHz, double dutyCylePercentage)
{
lock (_syncObj)
{
if (_clocks.ContainsKey(bit) == true)
{
throw new Exception("DIO " + _name + " already has a clock running on channel " + bit + ", must stop it first starting a new one");
}
int mappedChannal = _dio.Pinmap.Find("CH" + bit);
//set the pin to free run clock
double period = 1.0e6 / frequencyInHz; //period in Microsecond
Teradyne.eDigital.ITiming timing = _dio.Timing;
Teradyne.eDigital.IPin pin = _dio.Pin;
Teradyne.eDigital.IDynamic dynamic = _dio.Dynamic;
pin.SetDigitalConnect(RelayState.Closed, mappedChannal);
// Configure the channel attributes
pin.SetChannelMode(ChannelMode.Dynamic, mappedChannal);
pin.SetFormat(Format.ReturnToOne, mappedChannal);
pin.SetFreerun(true, mappedChannal);
//create tset and edgeset
timing.ConfigureClockReference(ClockReference.Internal, ClockEdgeSelect.Rising);
int edgeSet1 = timing.CreateEdgeSet();
var tset0 = timing.GetTimingSet(0);
tset0.ClockPeriod = PrecisionTimeSpan.FromMicroseconds(period);
tset0.SetDriveTiming(edgeSet1, PrecisionTimeSpan.FromMicroseconds(period * 0.25), PrecisionTimeSpan.FromMicroseconds(period * 0.75));
tset0.SetDetectStrobe(edgeSet1, PrecisionTimeSpan.FromMicroseconds(period * 0.5));
//assign phase to pin
pin.SetEdgeSet(edgeSet1, mappedChannal);
// Start of pattern
dynamic.BeginLoad(true);
// Pattern: 0
dynamic.Pattern.SetPinOpcode(PinOpcode.MH, mappedChannal)
.Modifiers.SetTimingSet(0)
.Modifiers.SetResultsCapture(false)
.End(TestInstruction.None);
// Drive low to start clock Repeat for 1000000 times
dynamic.Pattern.SetPinOpcode(PinOpcode.ML, mappedChannal)
.Modifiers.SetResultsCapture(false)
.End(TestInstruction.PassFail);
// End pattern
dynamic.Pattern.End(TestInstruction.PassFail);
dynamic.Pattern.Control.Halt().End(TestInstruction.PassFail);
dynamic.EndLoad();
dynamic.Timeout = PrecisionTimeSpan.MaxValue;
dynamic.ExpandLoops = true;
var testResult = dynamic.Run();
// hang onto the clock so we can stop it
_clocks[bit] = dynamic;
System.Threading.Thread.Sleep(10);
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void StopClock(uint bit)
{
lock (_syncObj)
{
if (_clocks.ContainsKey(bit) == false)
{
throw new Exception("DIO " + _name + " trying to stop clock on channel " + bit + ", that doesn't exist");
}
_clocks[bit].Execution.Stop();
_clocks.Remove(bit);
}
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
_dio.Utility.Reset();
_dio.Instrument.SystemEnable = true;
}
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
if (_state == State.Ready)
{
_dio.Utility.Reset();
_dio.Close();
_state = State.Uninitialized;
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<PlatformTarget>x86</PlatformTarget>
<AssemblyName>Raytheon.Instruments.DIOTeradyneEDigital6020A</AssemblyName>
<RootNamespace>Raytheon.Instruments</RootNamespace>
<Product>DIO Teradyne E Digital 6020A implementation</Product>
<Description>Digital IO Teradyne E Digital 6020A implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
<PackageReference Include="Raytheon.Instruments.GeneralIO.Contracts" Version="1.7.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DIOSim\DIOSim.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Ivi.Driver">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\COTS\IviFoundationSharedComponents_1.4.1\Ivi.Driver.dll</HintPath>
</Reference>
<Reference Include="Teradyne.eDigital.Fx40">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\COTS\Teradyne_EDigital_1_3_11\Teradyne.eDigital.Fx40.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,139 @@
// **********************************************************************************************************
// DIOTeradyneEDigital6020AFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOTeradyneEDigital6020AFactory")]
public class DIOTeradyneEDigital6020AFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public DIOTeradyneEDigital6020AFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOTeradyneEDigital6020AFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOTeradyneEDigital6020A(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
else
return new DIOTeradyneEDigital6020A(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}