using System; using CP210xRuntime_DLL; using Raytheon.Common; using Raytheon.Instruments.GeneralIO; using Win_API; namespace Raytheon.Instruments { /// /// /// public class ECPDIOSiCp210x : DIOSiCp210x { private string _comPort = string.Empty; /// /// ECPDIOSiCp210x factory constructor /// /// /// public ECPDIOSiCp210x(string deviceName, IConfigurationManager configurationManager) : base(deviceName, configurationManager) { _comPort = _dioModuleConfig.ReadValue(Name, ConfigIni.COM_PORT.ToString()); } /// /// /// /// /// /// /// public ECPDIOSiCp210x(string deviceName, uint deviceNum) : base(deviceName, deviceNum) { } /// /// /// /// /// /// /// public ECPDIOSiCp210x(string deviceName, string comPort) : base(deviceName, 0) { _comPort = comPort; } /// /// /// /// public void SetComPort(string comPort) { _comPort = comPort; } /// /// /// /// 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}"); } } /// /// /// /// 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}"); } } /// /// /// /// /// public override IODatatypes.BitState GetBitState(string signalName) { lock (_syncObj) { if (!_signalNameToChannelInfoMap.ContainsKey(signalName)) throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name); if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex) { throw new Exception($"The input channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name); } int bitIndex = (int)_signalNameToChannelInfoMap[signalName].channelNumber - _channelStartIndex; ushort mask = (ushort)(0x1 << (int)bitIndex); var latch = ReadLatch(); return (IODatatypes.BitState)(latch & mask); } } /// /// /// /// /// public override void SetBit(string signalName, IODatatypes.BitState state) { lock (_syncObj) { if (!_signalNameToChannelInfoMap.ContainsKey(signalName)) throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name); if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex) { throw new Exception($"The output channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name); } int bitIndex = (int)_signalNameToChannelInfoMap[signalName].channelNumber - _channelStartIndex; ushort mask = (ushort)(0x1 << (int)bitIndex); if (state == IODatatypes.BitState.High) { WriteLatch(mask, mask); } else { WriteLatch(mask, 0); } } } /// /// /// /// /// /// 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); } } } }