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,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);
}
}
}