2207 lines
103 KiB
Plaintext
2207 lines
103 KiB
Plaintext
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Text;
|
||
|
|
using System.Threading;
|
||
|
|
using DTS.Common.Utilities;
|
||
|
|
using DTS.Common.Utilities.Logging;
|
||
|
|
using DTS.DASLib.Command;
|
||
|
|
using DTS.Common.DAS.Concepts;
|
||
|
|
using DTS.Common.ICommunication;
|
||
|
|
using DTS.DASLib.Command.TDAS;
|
||
|
|
using DTS.Common.Interface.Connection;
|
||
|
|
using DTS.Common.Enums.DASFactory;
|
||
|
|
using DTS.Common.Interface.DASFactory.Config;
|
||
|
|
using DTS.Common.Interface.DASFactory;
|
||
|
|
|
||
|
|
namespace DTS.DASLib.Service
|
||
|
|
{
|
||
|
|
public partial class TDAS<T> : Communication<T>,
|
||
|
|
IDASCommunication,
|
||
|
|
IConfigurationActions,
|
||
|
|
IDiagnosticsActions,
|
||
|
|
ITriggerCheckActions,
|
||
|
|
IRealTimeActions,
|
||
|
|
IArmActions,
|
||
|
|
IDownloadActions where T : IConnection, new()
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// <inheritdoc cref="IConfiguration"/>
|
||
|
|
/// </summary>
|
||
|
|
public string TestDirectory { get; set; }
|
||
|
|
void IConfigurationActions.QueryTestSetup(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
void IConfigurationActions.StoreTestSetupXML(ServiceCallback callback, object userData, string testSetupXML)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// returns true if the unit is capable of reading arm status
|
||
|
|
/// 17800 Trigger status is "waiting" but PPRO has indeed triggered
|
||
|
|
/// </summary>
|
||
|
|
/// <returns></returns>
|
||
|
|
bool IDASCommunication.GetCanCheckArmStatus() { return true; }
|
||
|
|
void IDASCommunication.SetIsStreamingSupported(bool supported)
|
||
|
|
{
|
||
|
|
IsStreamingSupported = false;
|
||
|
|
}
|
||
|
|
void IDASCommunication.ReadFirstUseDate()
|
||
|
|
{
|
||
|
|
IsFirstUseDateSupported = false;
|
||
|
|
FirstUseDate = null;
|
||
|
|
}
|
||
|
|
public bool ConnectionCheck()
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var querySerialNumber = new QuerySerialNumber(this);
|
||
|
|
querySerialNumber.SyncExecute();
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
APILogger.Log(ex);
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
/// <summary>
|
||
|
|
/// discovers any connected devices
|
||
|
|
/// TDAS does support this currently
|
||
|
|
/// </summary>
|
||
|
|
public void QueryConnectedDevices()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
public int MaxModules { get; set; } = 4;
|
||
|
|
|
||
|
|
bool IArmActions.SupportsBackgroundFlashErase => IsG5();
|
||
|
|
private DateTime _backgroundFlashClearStart = DateTime.MinValue;
|
||
|
|
DateTime? IArmActions.BackgroundFlashEraseStartTime
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
if (DateTime.MinValue == _backgroundFlashClearStart) { return null; }
|
||
|
|
return _backgroundFlashClearStart;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
bool IArmActions.BackgroundFlashEraseStarted => null != (this as IArmActions).BackgroundFlashEraseStartTime;
|
||
|
|
|
||
|
|
void IArmActions.BeginBackgroundFlashErase(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
if (!(this as IArmActions).SupportsBackgroundFlashErase) { info.Success(); return; }
|
||
|
|
|
||
|
|
if (_backgroundFlashClearStart != DateTime.MinValue) { info.Success(); return; }//it's already been called ...
|
||
|
|
LaunchAsyncWorker("TDAS.BeginBackgroundFlashErase", AsyncBeginBackgroundFlashErase, info);
|
||
|
|
}
|
||
|
|
private void AsyncBeginBackgroundFlashErase(object o)
|
||
|
|
{
|
||
|
|
var info = o as TDASServiceAsyncInfo;
|
||
|
|
DoFlashErase(false);
|
||
|
|
_backgroundFlashClearStart = DateTime.Now;
|
||
|
|
info?.Success();
|
||
|
|
}
|
||
|
|
private void DoFlashErase(bool dummyArm)
|
||
|
|
{
|
||
|
|
if (!IsG5()) return;
|
||
|
|
if ((this as IArmActions).BackgroundFlashEraseStarted) return;
|
||
|
|
var rfc = new RackFlashClear(this);
|
||
|
|
|
||
|
|
rfc.SampleRate = Convert.ToDouble(ConfigData.Modules[0].SampleRateHz);
|
||
|
|
//didn't help at all :/
|
||
|
|
if (dummyArm)
|
||
|
|
{
|
||
|
|
rfc.RecordingTime = .1;
|
||
|
|
}
|
||
|
|
else { rfc.RecordingTime = ConfigData.Modules[0].PreTriggerSeconds + ConfigData.Modules[0].PostTriggerSeconds; }
|
||
|
|
|
||
|
|
rfc.SyncExecute();
|
||
|
|
}
|
||
|
|
void IArmActions.TurnOffT0Lights(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
|
||
|
|
LaunchAsyncWorker("TDAS.TurnOffT0Lights", AsyncTurnOffT0Lights, info);
|
||
|
|
}
|
||
|
|
private void AsyncTurnOffT0Lights(object o)
|
||
|
|
{
|
||
|
|
var info = o as TDASServiceAsyncInfo;
|
||
|
|
|
||
|
|
if (!IsG5())
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
//turn off lights
|
||
|
|
foreach (var mod in ConfigData.Modules)
|
||
|
|
{
|
||
|
|
if (mod.SerialNumber() == "EMPTY") continue;
|
||
|
|
var qsnb = new QuerySerialNumberBroadcast(this, mod.ModuleArrayIndex);
|
||
|
|
qsnb.SyncExecute();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info?.Error(ex.Message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
info?.Success();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SetDASDisplayOrder(int order) { throw new NotSupportedException("Not supported for TDAS"); }
|
||
|
|
public void SetChannelDisplayOrder(int[] order) { throw new NotSupportedException("Not supported for TDAS"); }
|
||
|
|
public int GetDASDisplayOrder() { return -1; }
|
||
|
|
public int[] GetChannelDisplayOrder() { return new[] { -1 }; }
|
||
|
|
public bool RequireDiagnosticRateMatchSampleRate() { return false; }
|
||
|
|
public DateTime SystemBaseTime => DateTime.MinValue;
|
||
|
|
public bool RangeBandwidthLimited => false;
|
||
|
|
public bool SupportsTimeSynchronization => false;
|
||
|
|
|
||
|
|
void IArmActions.ReadyForArming(ServiceCallback callback, object userData, Guid eventGuid, int armNowTimeout, bool testingMode,
|
||
|
|
int maxNumberEvents, bool dummyArm, bool sysMode)
|
||
|
|
{
|
||
|
|
var info = new ArmPacket(callback, userData, eventGuid, armNowTimeout);
|
||
|
|
info.DummyArm = dummyArm;
|
||
|
|
info.SysMode = sysMode;
|
||
|
|
LaunchAsyncWorker("TDAS.ReadyArming", AsyncReadyArming, info);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AsyncReadyArming(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = asyncInfo as ArmPacket;
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
// not needed, we will query it again when turning it on.
|
||
|
|
|
||
|
|
var bHasDigitalChannels = false;
|
||
|
|
SetupG5LevelTrigger setupLT = null;
|
||
|
|
|
||
|
|
//if a g5 has _only_ digital channels, we don't want to dummy arm it as the digital channels won't work properly
|
||
|
|
//this little bit detects if there are digital channels in play on this g5
|
||
|
|
if (IsG5())
|
||
|
|
{
|
||
|
|
foreach (var m in ConfigData.Modules)
|
||
|
|
{
|
||
|
|
foreach (var c in m.Channels)
|
||
|
|
{
|
||
|
|
if (!(c is AnalogInputDASChannel)) continue;
|
||
|
|
if (!(c as AnalogInputDASChannel).DigitalInputChannel || c.ConfigurationMode != DFConstantsAndEnums.ConfigMode.Normal) continue;
|
||
|
|
bHasDigitalChannels = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (bHasDigitalChannels) { break; }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
var bAllModulesDummyArmed = true;
|
||
|
|
for (var moduleIdx = 0; moduleIdx < DASInfo.Modules.Length; moduleIdx++)
|
||
|
|
{
|
||
|
|
if (DASInfo.Modules[moduleIdx].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
var dummyChannels = from c in ConfigData.Modules[moduleIdx].Channels
|
||
|
|
where c.ConfigurationMode == DFConstantsAndEnums.ConfigMode.DummyArm
|
||
|
|
select c;
|
||
|
|
|
||
|
|
if (DASInfo.Modules[moduleIdx].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
#region IsTom
|
||
|
|
|
||
|
|
if (IsTom((DASModule)ConfigData.Modules[moduleIdx]))
|
||
|
|
{
|
||
|
|
var bHasDoutsOnly = true;
|
||
|
|
foreach (var ch in ConfigData.Modules[moduleIdx].Channels)
|
||
|
|
{
|
||
|
|
if (ch is OutputTOMDigitalChannel)
|
||
|
|
{
|
||
|
|
//if we've gotten here then are sure there's no normal configured channels,
|
||
|
|
//so we just need to check that there's a digital channel
|
||
|
|
bHasDoutsOnly = false;
|
||
|
|
if (ch.ConfigurationMode != DFConstantsAndEnums.ConfigMode.Normal) continue;
|
||
|
|
bHasDoutsOnly = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (ch.ConfigurationMode != DFConstantsAndEnums.ConfigMode.Normal) continue;
|
||
|
|
bHasDoutsOnly = false;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
var sdl = new SetupTOMDASLoad(this);
|
||
|
|
if (null != dummyChannels && dummyChannels.Any() || info.DummyArm || bHasDoutsOnly)
|
||
|
|
{
|
||
|
|
sdl.IsDummyArm = true;
|
||
|
|
sdl.CollectData = null == dummyChannels || !dummyChannels.Any();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
bAllModulesDummyArmed = false;
|
||
|
|
}
|
||
|
|
sdl.TestConfig =
|
||
|
|
$"{info.EventGuid.ToString()}{SETUPDASREAD_SENTINEL}{ConfigData.Description}{SETUPDASREAD_SENTINEL}{ConfigData.Modules[moduleIdx].GetCRC32()}";
|
||
|
|
switch (ConfigData.Modules[moduleIdx].RecordingMode)
|
||
|
|
{
|
||
|
|
case DFConstantsAndEnums.RecordingMode.AutoCircularBufferMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.AutoRecorderMode:
|
||
|
|
throw new NotSupportedException("TOM does not support Auto Mode");
|
||
|
|
case DFConstantsAndEnums.RecordingMode.CircularBuffer:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.a16_CircularBufferAndStreamSubSampleMode:
|
||
|
|
sdl.ArmMode = SetupTOMDASLoad.ARMMode.WAIT;
|
||
|
|
break;
|
||
|
|
case DFConstantsAndEnums.RecordingMode.RecorderMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.RecorderModePlusUART:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.a14_NormalRecorderAndStreamSubSampleMode:
|
||
|
|
sdl.ArmMode = SetupTOMDASLoad.ARMMode.TAPE;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw new NotSupportedException(
|
||
|
|
"Mode not supported for TOM: " +
|
||
|
|
ConfigData.Modules[moduleIdx].RecordingMode.ToString());
|
||
|
|
}
|
||
|
|
double aaFilter = ConfigData.Modules[moduleIdx].AAFilterRateHz;
|
||
|
|
if (aaFilter > MaxAAFilterRateHz)
|
||
|
|
{
|
||
|
|
aaFilter = MaxAAFilterRateHz;
|
||
|
|
}
|
||
|
|
if (0 == aaFilter && IsG5())
|
||
|
|
{
|
||
|
|
aaFilter = MaxAAFilterRateHz;
|
||
|
|
}
|
||
|
|
|
||
|
|
sdl.SetHardwareAAFilter(Convert.ToInt32(aaFilter), MaxAAFilterRateHz);
|
||
|
|
sdl.ModuleIndex = ConfigData.Modules[moduleIdx].ModuleArrayIndex;
|
||
|
|
sdl.PostTriggerSeconds = ConfigData.Modules[moduleIdx].PostTriggerSeconds;
|
||
|
|
sdl.PreTriggerSeconds = ConfigData.Modules[moduleIdx].PreTriggerSeconds;
|
||
|
|
sdl.SampleRate = ConfigData.Modules[moduleIdx].SampleRateHz;
|
||
|
|
sdl.TestId = ConfigData.TestID;
|
||
|
|
sdl.TriggerType = SetupTOMDASLoad.TriggerTypes.BUS;
|
||
|
|
if (info.DummyArm)
|
||
|
|
{
|
||
|
|
sdl.IsDummyArm = true;
|
||
|
|
sdl.CollectData = null == dummyChannels || !dummyChannels.Any();
|
||
|
|
}
|
||
|
|
sdl.SyncExecute();
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion IsTom
|
||
|
|
|
||
|
|
else
|
||
|
|
{
|
||
|
|
var module = ConfigData.Modules[moduleIdx];
|
||
|
|
var levelTriggerMode = SetupDASLoad.TriggerModes.GT;
|
||
|
|
var levelTriggerEnabled = false;
|
||
|
|
|
||
|
|
//g5
|
||
|
|
var levelTriggerUpperThresholds = new List<short>();
|
||
|
|
var levelTriggerLowerThresholds = new List<short>();
|
||
|
|
|
||
|
|
var g5LTTypes = new List<SetupG5LevelTrigger.LevelTriggerTypes>();
|
||
|
|
var levelTriggerChannels = new List<int>();
|
||
|
|
// For SIM
|
||
|
|
var levelTriggerChannel = 0;
|
||
|
|
short levelTriggerUpperThreshold = 0;
|
||
|
|
short levelTriggerLowerThreshold = 0;
|
||
|
|
|
||
|
|
// configure the range for this bridge
|
||
|
|
for (var channelIdx = 0; channelIdx < module.Channels.Length; channelIdx++)
|
||
|
|
{
|
||
|
|
var g5LTType = SetupG5LevelTrigger.LevelTriggerTypes.OW;
|
||
|
|
var channel = module.Channels[channelIdx];
|
||
|
|
var dasChannelNumber =
|
||
|
|
DASInfo.MapModuleArrayIndexAndChannelNum2DASChannel(moduleIdx, channelIdx);
|
||
|
|
|
||
|
|
if (channel.ConfigurationMode != DFConstantsAndEnums.ConfigMode.Normal) continue;
|
||
|
|
bAllModulesDummyArmed = false;
|
||
|
|
var analog = channel as AnalogInputDASChannel;
|
||
|
|
|
||
|
|
if (analog.SensitivityMilliVoltsPerEU == 0) continue;
|
||
|
|
var levelTriggerOnThisChannel = false;
|
||
|
|
var unused = GetMvPerEu(analog);
|
||
|
|
|
||
|
|
//
|
||
|
|
// push level trigger settings out to hardware
|
||
|
|
//
|
||
|
|
|
||
|
|
// If this is level trigger, diagnostic results may be null. Need to cope.
|
||
|
|
var scalefactorMilliVoltsPerADC = analog.ScalefactorMilliVoltsPerADC;
|
||
|
|
var offsetRemovalADC = 0;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var diagnostics = analog.Diagnostics;
|
||
|
|
scalefactorMilliVoltsPerADC = diagnostics.ScalefactorMilliVoltsPerADC;
|
||
|
|
offsetRemovalADC = diagnostics.GetExpectedDataZeroLevelADC(analog.ZeroMethod);
|
||
|
|
}
|
||
|
|
catch (Exception)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
if (null != analog.TriggerBelowThresholdEu)
|
||
|
|
{
|
||
|
|
var invertScaleFactor = 1D;
|
||
|
|
if (analog.IsInverted)
|
||
|
|
{
|
||
|
|
invertScaleFactor = -1D;
|
||
|
|
}
|
||
|
|
|
||
|
|
levelTriggerOnThisChannel = true;
|
||
|
|
var bInvert = analog.IsInverted;
|
||
|
|
if (analog.ScalefactorMilliVoltsPerADC < 0)
|
||
|
|
{
|
||
|
|
bInvert = !bInvert;
|
||
|
|
}
|
||
|
|
if (analog.SensitivityMilliVoltsPerEU < 0)
|
||
|
|
{
|
||
|
|
bInvert = !bInvert;
|
||
|
|
}
|
||
|
|
if (bInvert)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
try
|
||
|
|
{
|
||
|
|
// Careful here... if remove offset is NOT active, and zero method is "none",
|
||
|
|
// then just send the level trigger as specified down to the hardware. Othewise,
|
||
|
|
// we'll need to apply the appropriate offset to it so it triggers as expected.
|
||
|
|
//
|
||
|
|
|
||
|
|
if (bInvert)
|
||
|
|
{
|
||
|
|
levelTriggerUpperThreshold =
|
||
|
|
(short)(invertScaleFactor * analog.TriggerBelowThresholdEu *
|
||
|
|
analog.SensitivityMilliVoltsPerEUNormalized /
|
||
|
|
scalefactorMilliVoltsPerADC
|
||
|
|
+ offsetRemovalADC);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
levelTriggerLowerThreshold =
|
||
|
|
(short)(invertScaleFactor * analog.TriggerBelowThresholdEu *
|
||
|
|
analog.SensitivityMilliVoltsPerEUNormalized /
|
||
|
|
scalefactorMilliVoltsPerADC
|
||
|
|
+ offsetRemovalADC);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (ApplicationException ex)
|
||
|
|
{
|
||
|
|
if (null != Exceptional
|
||
|
|
.ExtractFirstExceptionOfTypeFromExceptionTree<NoDiagnosticsAvailable>(ex))
|
||
|
|
levelTriggerLowerThreshold =
|
||
|
|
(short)(analog.TriggerBelowThresholdEu *
|
||
|
|
analog.SensitivityMilliVoltsPerEUNormalized /
|
||
|
|
scalefactorMilliVoltsPerADC);
|
||
|
|
else throw;
|
||
|
|
}
|
||
|
|
levelTriggerMode = SetupDASLoad.TriggerModes.LT;
|
||
|
|
g5LTType = SetupG5LevelTrigger.LevelTriggerTypes.LT;
|
||
|
|
if (bInvert)
|
||
|
|
{
|
||
|
|
//FLIP IT!
|
||
|
|
levelTriggerMode = SetupDASLoad.TriggerModes.GT;
|
||
|
|
g5LTType = SetupG5LevelTrigger.LevelTriggerTypes.GT;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (null != analog.TriggerAboveThresholdEu)
|
||
|
|
{
|
||
|
|
levelTriggerOnThisChannel = true;
|
||
|
|
var invertScaleFactor = 1D;
|
||
|
|
if (analog.IsInverted)
|
||
|
|
{
|
||
|
|
invertScaleFactor = -1D;
|
||
|
|
}
|
||
|
|
|
||
|
|
var bInvert = analog.IsInverted;
|
||
|
|
if (analog.ScalefactorMilliVoltsPerADC < 0)
|
||
|
|
{
|
||
|
|
bInvert = !bInvert;
|
||
|
|
}
|
||
|
|
if (analog.SensitivityMilliVoltsPerEU < 0)
|
||
|
|
{
|
||
|
|
bInvert = !bInvert;
|
||
|
|
}
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
//
|
||
|
|
// Careful here... if remove offset is NOT active, and zero method is "none",
|
||
|
|
// then just send the level trigger as specified down to the hardware. Othewise,
|
||
|
|
// we'll need to apply the appropriate offset to it so it triggers as expected.
|
||
|
|
//
|
||
|
|
|
||
|
|
if (bInvert)
|
||
|
|
{
|
||
|
|
levelTriggerLowerThreshold =
|
||
|
|
(short)(invertScaleFactor * analog.TriggerAboveThresholdEu *
|
||
|
|
analog.SensitivityMilliVoltsPerEUNormalized /
|
||
|
|
scalefactorMilliVoltsPerADC
|
||
|
|
+ offsetRemovalADC);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
levelTriggerUpperThreshold =
|
||
|
|
(short)(analog.TriggerAboveThresholdEu *
|
||
|
|
analog.SensitivityMilliVoltsPerEUNormalized /
|
||
|
|
scalefactorMilliVoltsPerADC
|
||
|
|
+ offsetRemovalADC);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (ApplicationException ex)
|
||
|
|
{
|
||
|
|
if (null != Exceptional
|
||
|
|
.ExtractFirstExceptionOfTypeFromExceptionTree<NoDiagnosticsAvailable>(ex))
|
||
|
|
levelTriggerUpperThreshold =
|
||
|
|
(short)(analog.TriggerAboveThresholdEu *
|
||
|
|
analog.SensitivityMilliVoltsPerEUNormalized /
|
||
|
|
scalefactorMilliVoltsPerADC);
|
||
|
|
else throw;
|
||
|
|
}
|
||
|
|
levelTriggerMode = SetupDASLoad.TriggerModes.GT;
|
||
|
|
g5LTType = SetupG5LevelTrigger.LevelTriggerTypes.GT;
|
||
|
|
if (bInvert)
|
||
|
|
{
|
||
|
|
//FLIP IT!
|
||
|
|
levelTriggerMode = SetupDASLoad.TriggerModes.LT;
|
||
|
|
g5LTType = SetupG5LevelTrigger.LevelTriggerTypes.LT;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
if (null != analog.TriggerAboveThresholdEu && null != analog.TriggerBelowThresholdEu)
|
||
|
|
{
|
||
|
|
switch (analog.LevelTriggerType)
|
||
|
|
{
|
||
|
|
case Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.GreaterThan:
|
||
|
|
break;
|
||
|
|
case Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.InsideWindow:
|
||
|
|
g5LTType = SetupG5LevelTrigger.LevelTriggerTypes.IW;
|
||
|
|
break;
|
||
|
|
case Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.LessThan:
|
||
|
|
break;
|
||
|
|
case Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.OutsideWindow:
|
||
|
|
g5LTType = SetupG5LevelTrigger.LevelTriggerTypes.OW;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!levelTriggerOnThisChannel) continue;
|
||
|
|
levelTriggerEnabled = true;
|
||
|
|
|
||
|
|
if (g5LTType == SetupG5LevelTrigger.LevelTriggerTypes.GT ||
|
||
|
|
g5LTType == SetupG5LevelTrigger.LevelTriggerTypes.LT)
|
||
|
|
{
|
||
|
|
levelTriggerChannel = channelIdx + 1;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// One based trigger channel
|
||
|
|
levelTriggerChannel = dasChannelNumber + 1;
|
||
|
|
}
|
||
|
|
if (!IsG5() || !levelTriggerEnabled) continue;
|
||
|
|
levelTriggerChannels.Add(levelTriggerChannel);
|
||
|
|
g5LTTypes.Add(g5LTType);
|
||
|
|
levelTriggerUpperThresholds.Add(levelTriggerUpperThreshold);
|
||
|
|
levelTriggerLowerThresholds.Add(levelTriggerLowerThreshold);
|
||
|
|
}
|
||
|
|
|
||
|
|
//ideally we would have a common base class between these and just one object here, but there's some work to do
|
||
|
|
//basically there's some 3 separate parameters or so separating the two.
|
||
|
|
var sdl = new SetupDASLoad(this);
|
||
|
|
var sdlDIM = new SetupDASLoadDIM(this);
|
||
|
|
|
||
|
|
if (null == dummyChannels || !dummyChannels.Any())
|
||
|
|
{
|
||
|
|
bAllModulesDummyArmed = false;
|
||
|
|
}
|
||
|
|
sdl.TestConfig =
|
||
|
|
$"{info.EventGuid.ToString()}{SETUPDASREAD_SENTINEL}{ConfigData.Description}{SETUPDASREAD_SENTINEL}{ConfigData.Modules[moduleIdx].GetCRC32()}";
|
||
|
|
sdlDIM.TestConfig = sdl.TestConfig;
|
||
|
|
|
||
|
|
sdl.ModuleIndex = DASInfo.Modules[moduleIdx].ModuleArrayIndex;
|
||
|
|
sdlDIM.ModuleIndex = sdl.ModuleIndex;
|
||
|
|
|
||
|
|
switch (ConfigData.Modules[moduleIdx].RecordingMode)
|
||
|
|
{
|
||
|
|
case DFConstantsAndEnums.RecordingMode.CircularBuffer:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.AutoCircularBufferMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.a16_CircularBufferAndStreamSubSampleMode:
|
||
|
|
sdl.ArmMode = SetupDASLoad.ARMMode.WAIT;
|
||
|
|
sdlDIM.ArmMode = SetupDASLoadDIM.ArmModes.WAIT;
|
||
|
|
break;
|
||
|
|
case DFConstantsAndEnums.RecordingMode.RecorderMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.a14_NormalRecorderAndStreamSubSampleMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.RecorderModePlusUART:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.AutoRecorderMode:
|
||
|
|
sdl.ArmMode = SetupDASLoad.ARMMode.TAPE;
|
||
|
|
sdlDIM.ArmMode = SetupDASLoadDIM.ArmModes.TAPE;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw new NotSupportedException(
|
||
|
|
"mode not supported for TDAS: " +
|
||
|
|
ConfigData.Modules[moduleIdx].RecordingMode.ToString());
|
||
|
|
}
|
||
|
|
|
||
|
|
var aaf = Convert.ToInt32(ConfigData.Modules[moduleIdx].AAFilterRateHz);
|
||
|
|
if (0 == aaf && IsG5())
|
||
|
|
{
|
||
|
|
aaf = Convert.ToInt32(MaxAAFilterRateHz);
|
||
|
|
}
|
||
|
|
sdl.SetHardwareAAFilter(aaf, MaxAAFilterRateHz);
|
||
|
|
|
||
|
|
sdl.PreTriggerSeconds = ConfigData.Modules[moduleIdx].PreTriggerSeconds;
|
||
|
|
sdlDIM.PreTriggerSeconds = sdl.PreTriggerSeconds;
|
||
|
|
|
||
|
|
sdl.PostTriggerSeconds = ConfigData.Modules[moduleIdx].PostTriggerSeconds;
|
||
|
|
sdlDIM.PostTriggerSeconds = ConfigData.Modules[moduleIdx].PostTriggerSeconds;
|
||
|
|
|
||
|
|
sdl.SampleRate = ConfigData.Modules[moduleIdx].SampleRateHz;
|
||
|
|
sdlDIM.SampleRate = sdl.SampleRate;
|
||
|
|
|
||
|
|
if (info.DummyArm || (null != dummyChannels && dummyChannels.Any()))
|
||
|
|
{
|
||
|
|
sdl.IsDummyArm = true;
|
||
|
|
sdlDIM.IsDummyArm = true;
|
||
|
|
sdl.CollectData = null == dummyChannels || !dummyChannels.Any();
|
||
|
|
sdlDIM.CollectData = sdl.CollectData;
|
||
|
|
}
|
||
|
|
|
||
|
|
sdl.TestId = ConfigData.TestID;
|
||
|
|
sdlDIM.TestId = ConfigData.TestID;
|
||
|
|
|
||
|
|
if (levelTriggerEnabled && !IsG5()) //G5 always uses HW for SetupDasLoad (use setup trig for lvl trigger)
|
||
|
|
{
|
||
|
|
sdl.TriggerType = SetupDASLoad.TriggerTypes.LV;
|
||
|
|
sdlDIM.TriggerType = SetupDASLoadDIM.TriggerTypes.LT;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
sdl.TriggerType = SetupDASLoad.TriggerTypes.HW;
|
||
|
|
sdlDIM.TriggerType = SetupDASLoadDIM.TriggerTypes.HW;
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (levelTriggerMode)
|
||
|
|
{
|
||
|
|
case SetupDASLoad.TriggerModes.GT:
|
||
|
|
sdl.TriggerLevelADC = levelTriggerUpperThreshold;
|
||
|
|
sdl.TriggerChannel = levelTriggerChannel;
|
||
|
|
sdlDIM.TriggerChannel = levelTriggerChannel;
|
||
|
|
sdl.TriggerMode = levelTriggerMode;
|
||
|
|
break;
|
||
|
|
case SetupDASLoad.TriggerModes.LT:
|
||
|
|
sdl.TriggerLevelADC = levelTriggerLowerThreshold;
|
||
|
|
sdl.TriggerChannel = levelTriggerChannel;
|
||
|
|
sdlDIM.TriggerChannel = levelTriggerChannel;
|
||
|
|
sdl.TriggerMode = levelTriggerMode;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
sdl.NumberOfTriggerSamples = 5;
|
||
|
|
sdlDIM.NumberOfTriggerSamples = 5;
|
||
|
|
|
||
|
|
if (DASInfo.Modules[moduleIdx].TypeOfModule == DFConstantsAndEnums.ModuleType.ProDIM &&
|
||
|
|
!IsG5())
|
||
|
|
{
|
||
|
|
sdlDIM.SyncExecute();
|
||
|
|
if (sdlDIM.IsErrored())
|
||
|
|
{
|
||
|
|
info.Error(sdlDIM.GetErrorString(), new Exception(sdlDIM.GetErrorString()));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (module.ModuleArrayIndex > 0 && IsG5())
|
||
|
|
{
|
||
|
|
//we only need to do the first module in a g5
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
sdl.SyncExecute();
|
||
|
|
if (sdl.IsErrored())
|
||
|
|
{
|
||
|
|
info.Error(sdl.GetErrorString(), new Exception(sdl.GetErrorString()));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (DASInfo.Modules[moduleIdx].TypeOfModule != DFConstantsAndEnums.ModuleType.G5Analog ||
|
||
|
|
!levelTriggerEnabled) continue;
|
||
|
|
|
||
|
|
for (var i = 0; i < g5LTTypes.Count; i++)
|
||
|
|
{
|
||
|
|
var g5LTType = g5LTTypes[i];
|
||
|
|
levelTriggerUpperThreshold = levelTriggerUpperThresholds[i];
|
||
|
|
levelTriggerLowerThreshold = levelTriggerLowerThresholds[i];
|
||
|
|
levelTriggerChannel = levelTriggerChannels[i];
|
||
|
|
|
||
|
|
setupLT = new SetupG5LevelTrigger(this);
|
||
|
|
setupLT.LevelTriggerType = g5LTType;
|
||
|
|
if (0 != levelTriggerLowerThreshold)
|
||
|
|
{
|
||
|
|
setupLT.TriggerLevelLowADC = levelTriggerLowerThreshold;
|
||
|
|
}
|
||
|
|
if (0 != levelTriggerUpperThreshold)
|
||
|
|
{
|
||
|
|
setupLT.TriggerLevelHighADC = levelTriggerUpperThreshold;
|
||
|
|
}
|
||
|
|
setupLT.TriggerChannel = levelTriggerChannel;
|
||
|
|
setupLT.NumberOfTriggerSamples = 5;
|
||
|
|
setupLT.SyncExecute();
|
||
|
|
if (setupLT.IsErrored())
|
||
|
|
{
|
||
|
|
info.Error(setupLT.GetErrorString(),
|
||
|
|
new Exception(setupLT.GetErrorString()));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
setupLT = null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
setupLT?.SyncExecute();
|
||
|
|
|
||
|
|
TurnOnExcitation();
|
||
|
|
|
||
|
|
var asl = new ArmSetupLoad(this);
|
||
|
|
if (bAllModulesDummyArmed) { asl.PostADWait = -1; }
|
||
|
|
else { asl.PostADWait = 5; }
|
||
|
|
|
||
|
|
switch (ConfigData.Modules[0].RecordingMode)
|
||
|
|
{
|
||
|
|
case DFConstantsAndEnums.RecordingMode.CircularBuffer:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.AutoCircularBufferMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.a16_CircularBufferAndStreamSubSampleMode:
|
||
|
|
asl.ArmMode = ArmSetupLoad.ArmModes.WAIT;
|
||
|
|
break;
|
||
|
|
case DFConstantsAndEnums.RecordingMode.RecorderMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.a14_NormalRecorderAndStreamSubSampleMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.RecorderModePlusUART:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.AutoRecorderMode:
|
||
|
|
asl.ArmMode = ArmSetupLoad.ArmModes.TAPE;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw new NotSupportedException("unsupported recording mode " + ConfigData.Modules[0].RecordingMode.ToString());
|
||
|
|
}
|
||
|
|
|
||
|
|
asl.RackArmMode = info.SysMode ? ArmSetupLoad.RackArmModes.SYS : ArmSetupLoad.RackArmModes.SOLO;
|
||
|
|
|
||
|
|
asl.PostTriggerSeconds = ConfigData.Modules[0].PostTriggerSeconds + ConfigData.Modules[0].PreTriggerSeconds;
|
||
|
|
|
||
|
|
asl.SampleRate = ConfigData.Modules[0].SampleRateHz;
|
||
|
|
asl.SyncExecute();
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
catch (CanceledException)
|
||
|
|
{
|
||
|
|
info.Cancel();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info.Error(ex.Message.Contains("invalid sample rate") ?
|
||
|
|
DFConstantsAndEnums.CommandStatus.StatusArmInvalidSampleRate.ToString() : ex.Message, ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool AutoArmed { get => false; set { } }
|
||
|
|
|
||
|
|
private class ArmPacket : TDASServiceAsyncInfo
|
||
|
|
{
|
||
|
|
public bool DummyArm { get; set; }
|
||
|
|
public Guid EventGuid { get; set; }
|
||
|
|
public int ArmNowTimeout { get; set; }
|
||
|
|
public bool SysMode { get; set; }
|
||
|
|
public ArmPacket(ServiceCallback cb, object ud, Guid eg, int armNowTimeout)
|
||
|
|
: base(cb, ud)
|
||
|
|
{
|
||
|
|
EventGuid = eg;
|
||
|
|
ArmNowTimeout = armNowTimeout;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/// <summary>
|
||
|
|
/// the UDP settings to broadcast auto arm status to on auto arm boot
|
||
|
|
/// 17583 Monitor Test UI
|
||
|
|
/// </summary>
|
||
|
|
public string AutoArmUDPSetting { get; set; } = "239.1.2.3:8504";
|
||
|
|
/// <summary>
|
||
|
|
/// Auto Arm a single DAS now (not supported for TDAS)
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="callback">The function to call with information</param>
|
||
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
||
|
|
/// <param name="eventGuid">A unique GUID that this event will be tagged
|
||
|
|
/// with</param>
|
||
|
|
void IArmActions.AutoArmNow(ServiceCallback callback, object userData, Guid eventGuid, int
|
||
|
|
armNowTimeout, bool testingMode, UInt32 diagnosticsDelayMs, int maxNumberEvents, bool repeatEnable, bool preserveDiagnostics)
|
||
|
|
{
|
||
|
|
throw new NotSupportedException("AutoArmNow not supported for TDAS");
|
||
|
|
}
|
||
|
|
|
||
|
|
#region FlashErase
|
||
|
|
|
||
|
|
private class FlashEraseInfo : TDASServiceAsyncInfo
|
||
|
|
{
|
||
|
|
public bool DummyArm { get; set; }
|
||
|
|
public FlashEraseInfo(ServiceCallback _callback, object _userData)
|
||
|
|
: base(_callback, _userData)
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void IArmActions.BeginFlashErase(ServiceCallback callback, object userData, bool DummyArm)
|
||
|
|
{
|
||
|
|
var info = new FlashEraseInfo(callback, userData);
|
||
|
|
info.DummyArm = DummyArm;
|
||
|
|
LaunchAsyncWorker("TDAS.BeginFlashErase", AsyncBeginFlashErase, info);
|
||
|
|
|
||
|
|
}
|
||
|
|
/// <summary>
|
||
|
|
/// returns whether this das is a G5
|
||
|
|
/// </summary>
|
||
|
|
/// <returns></returns>
|
||
|
|
private bool IsG5()
|
||
|
|
{
|
||
|
|
return SerialNumber.StartsWith("5M") || SerialNumber.StartsWith("PI");
|
||
|
|
}
|
||
|
|
|
||
|
|
public enum G5Modes
|
||
|
|
{
|
||
|
|
VDS,
|
||
|
|
//IPORT,
|
||
|
|
INDUMMY
|
||
|
|
}
|
||
|
|
|
||
|
|
public G5Modes G5Mode { get; set; } = G5Modes.VDS;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// returns whether a given module in a rack is a Time Output Module (TOM)
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="module"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
private static bool IsTom(IDASModule module)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (module.SerialNumber().ToLower().Contains("tom"))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception ex) { APILogger.Log("problem getting serial number", ex); }
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
/// <summary>
|
||
|
|
/// returns true if the module is a digital input module
|
||
|
|
/// </summary>
|
||
|
|
private static bool IsDIM(IDASModule module)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (module.SerialNumber().ToLower().Contains("dim"))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception ex) { APILogger.Log("problem getting serial number", ex); }
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
/// <summary>
|
||
|
|
/// returns whether a given module type is a Timed Output Module (TOM)
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="m"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
private static bool IsTom(DFConstantsAndEnums.ModuleType m)
|
||
|
|
{
|
||
|
|
switch (m)
|
||
|
|
{
|
||
|
|
case DFConstantsAndEnums.ModuleType.ProTOM: return true;
|
||
|
|
default: return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AsyncBeginFlashErase(object asyncInfo)
|
||
|
|
{
|
||
|
|
if (!(asyncInfo is FlashEraseInfo info)) { return; }
|
||
|
|
try
|
||
|
|
{
|
||
|
|
DoFlashErase(info.DummyArm);
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
catch (CanceledException)
|
||
|
|
{
|
||
|
|
info.Cancel();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info.Error(ex.Message, ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void IArmActions.QueryFlashEraseStatus(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
LaunchAsyncWorker("TDAS.QueryFlashEraseStatus", AsyncQueryFlashEraseStatus, info);
|
||
|
|
}
|
||
|
|
|
||
|
|
private const double EXPECTED_FLASHCLEAR_TIME = 3 * 60 * 1000;
|
||
|
|
|
||
|
|
private void AsyncQueryFlashEraseStatus(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = asyncInfo as TDASServiceAsyncInfo;
|
||
|
|
|
||
|
|
if (IsG5())
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
bool done = false;
|
||
|
|
DateTime start = DateTime.Now;
|
||
|
|
if ((this as IArmActions).BackgroundFlashEraseStarted)
|
||
|
|
{
|
||
|
|
start = (DateTime)(this as IArmActions).BackgroundFlashEraseStartTime;
|
||
|
|
}
|
||
|
|
while (false == done)
|
||
|
|
{
|
||
|
|
QueryFlashClear queryStatus = new QueryFlashClear(this);
|
||
|
|
queryStatus.SyncExecute();
|
||
|
|
|
||
|
|
var eraseStatus = new FlashEraseStatus();
|
||
|
|
eraseStatus.LastError = DFConstantsAndEnums.CommandStatus.StatusNoError;
|
||
|
|
if (queryStatus.Done)
|
||
|
|
{
|
||
|
|
_backgroundFlashClearStart = DateTime.MinValue;
|
||
|
|
eraseStatus.PercentComplete = 100F;
|
||
|
|
done = true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
done = false;
|
||
|
|
var percentDoneExpected = 100D * DateTime.Now.Subtract(start).TotalMilliseconds /
|
||
|
|
EXPECTED_FLASHCLEAR_TIME;
|
||
|
|
if (percentDoneExpected < 1)
|
||
|
|
{
|
||
|
|
percentDoneExpected = 1;
|
||
|
|
}
|
||
|
|
else if (percentDoneExpected > 100)
|
||
|
|
{
|
||
|
|
percentDoneExpected = 100;
|
||
|
|
}
|
||
|
|
eraseStatus.PercentComplete = Convert.ToSingle(percentDoneExpected);
|
||
|
|
}
|
||
|
|
|
||
|
|
DASFlashEraseStatus = eraseStatus;
|
||
|
|
|
||
|
|
if (eraseStatus.LastError != DFConstantsAndEnums.CommandStatus.StatusNoError)
|
||
|
|
{
|
||
|
|
info?.Progress(0);
|
||
|
|
info?.Error("Error while clearing flash: " + eraseStatus.LastError.ToString());
|
||
|
|
done = true;
|
||
|
|
}
|
||
|
|
else if (eraseStatus.PercentComplete < 100.0f)
|
||
|
|
{
|
||
|
|
info?.Progress((int)eraseStatus.PercentComplete);
|
||
|
|
Thread.Sleep(500);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_backgroundFlashClearStart = DateTime.MinValue;
|
||
|
|
info?.Progress(100);
|
||
|
|
info?.Success();
|
||
|
|
done = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (CanceledException)
|
||
|
|
{
|
||
|
|
info?.Cancel();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info?.Error(ex.Message, ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
info?.Progress(100);
|
||
|
|
info?.Success();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region ArmNow
|
||
|
|
internal bool _bExcitationOn = false;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// TDAS Excitation states On, Off, or Empty Slot.
|
||
|
|
/// If SIM Excitation is ON, it should not be turned ON again,
|
||
|
|
/// because FW does other tasks as well (offset removal).
|
||
|
|
/// </summary>
|
||
|
|
internal enum TdasExcitationState { On = 0, Off, EmptySlot };
|
||
|
|
|
||
|
|
public bool[] QueryTestPrepareStatus()
|
||
|
|
{
|
||
|
|
var ret = new bool[DASInfo.Modules.Length];
|
||
|
|
for (var i = 0; i < DASInfo.Modules.Length; i++)
|
||
|
|
{
|
||
|
|
if (DASInfo.Modules[i].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK) { ret[i] = true; continue; }
|
||
|
|
var qtp = new QueryTestPrepare(this);
|
||
|
|
qtp.ModuleIndex = DASInfo.Modules[i].ModuleArrayIndex;
|
||
|
|
qtp.SyncExecute();
|
||
|
|
ret[i] = qtp.On;
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
private List<TdasExcitationState> GetModulesExcitationState()
|
||
|
|
{
|
||
|
|
var excitationState = new List<TdasExcitationState>();
|
||
|
|
|
||
|
|
for (int i = 0; i < DASInfo.Modules.Length; i++)
|
||
|
|
{
|
||
|
|
if (DASInfo.Modules[i].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK)
|
||
|
|
{
|
||
|
|
excitationState.Add(TdasExcitationState.EmptySlot);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
QueryTestPrepare qtp = new QueryTestPrepare(this);
|
||
|
|
qtp.ModuleIndex = DASInfo.Modules[i].ModuleArrayIndex;
|
||
|
|
qtp.SyncExecute();
|
||
|
|
|
||
|
|
excitationState.Add(qtp.On ? TdasExcitationState.On : TdasExcitationState.Off);
|
||
|
|
}
|
||
|
|
|
||
|
|
return excitationState;
|
||
|
|
}
|
||
|
|
public void TurnOnExcitation()
|
||
|
|
{
|
||
|
|
//FB 16115 Undo part of the changes for FB 15873 causing the TestPrepare call in arm step
|
||
|
|
//Refactor the logic to get the excitation sate for modules in GetModulesExcitationSate method
|
||
|
|
var excitationStateForModules = GetModulesExcitationState();
|
||
|
|
|
||
|
|
//if there's any modules that are on then we don't need to turn on power
|
||
|
|
if (!excitationStateForModules.Exists(status => status == TdasExcitationState.On))
|
||
|
|
{
|
||
|
|
if (IsG5())
|
||
|
|
{
|
||
|
|
var tp = new TestPrepare(this);
|
||
|
|
tp.ModuleIndex = 0;
|
||
|
|
tp.On = true;
|
||
|
|
tp.SyncExecute();
|
||
|
|
}
|
||
|
|
for (var i = 0; i < DASInfo.Modules.Length; i++)
|
||
|
|
{
|
||
|
|
if (DASInfo.Modules[i].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK) { continue; }
|
||
|
|
var qsn = new QuerySerialNumberBroadcast(this, DASInfo.Modules[i].ModuleArrayIndex);
|
||
|
|
qsn.SyncExecute();
|
||
|
|
|
||
|
|
var tpb = new TestPrepareBroadcast(this, DASInfo.Modules[i].ModuleArrayIndex);
|
||
|
|
tpb.On = true;
|
||
|
|
tpb.SyncExecute();
|
||
|
|
Thread.Sleep(1000);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void TurnOffExcitation()
|
||
|
|
{
|
||
|
|
for (int i = 0; i < DASInfo.Modules.Length; i++)
|
||
|
|
{
|
||
|
|
if (DASInfo.Modules[i].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK) { continue; }
|
||
|
|
if (IsG5())
|
||
|
|
{
|
||
|
|
TestPrepare tp = new TestPrepare(this);
|
||
|
|
tp.ModuleIndex = 0;
|
||
|
|
tp.On = false;
|
||
|
|
tp.SyncExecute();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
var qsn = new QuerySerialNumberBroadcast(this, DASInfo.Modules[i].ModuleArrayIndex);
|
||
|
|
qsn.SyncExecute();
|
||
|
|
|
||
|
|
var tpb = new TestPrepareBroadcast(this, DASInfo.Modules[i].ModuleArrayIndex);
|
||
|
|
tpb.On = false;
|
||
|
|
ExcitationStatus = DFConstantsAndEnums.ExcitationStatus.Off;
|
||
|
|
tpb.SyncExecute();
|
||
|
|
Thread.Sleep(1000);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public void TurnOffExcitation(int moduleIdx)
|
||
|
|
{
|
||
|
|
if (DASInfo.Modules[moduleIdx].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK) { return; }
|
||
|
|
var tp = new TestPrepare(this);
|
||
|
|
tp.On = false;
|
||
|
|
tp.ModuleIndex = DASInfo.Modules[moduleIdx].ModuleArrayIndex;
|
||
|
|
tp.SyncExecute();
|
||
|
|
}
|
||
|
|
|
||
|
|
void IArmActions.ArmNow(ServiceCallback callback, object userData, Guid eventGuid,
|
||
|
|
int armNowTimeout, bool testingMode, int maxNumberEvents, bool SysMode)
|
||
|
|
{
|
||
|
|
var info = new ArmPacket(callback, userData, eventGuid, armNowTimeout);
|
||
|
|
info.SysMode = SysMode;
|
||
|
|
LaunchAsyncWorker("TDAS.ArmNow", new WaitCallback(AsyncArmNow), info);
|
||
|
|
}
|
||
|
|
|
||
|
|
void IArmActions.PrepareForArmNow(ServiceCallback callback, object userData, Guid eventGuid,
|
||
|
|
int armNowTimeout, bool testingMode, int maxNumberEvents, bool SysMode)
|
||
|
|
{
|
||
|
|
var info = new ArmPacket(callback, userData, eventGuid, armNowTimeout);
|
||
|
|
info.SysMode = SysMode;
|
||
|
|
LaunchAsyncWorker("TDAS.PrepareForArmNow", new WaitCallback(AsyncPrepareForArmNow), info);
|
||
|
|
}
|
||
|
|
void IArmActions.ReArm(ServiceCallback callback, object userData, bool autoArm, bool arm, bool repeatEnable)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
info.Error("NotSupported");
|
||
|
|
}
|
||
|
|
void IArmActions.PreparedArmNow(ServiceCallback callback, object userData, Guid eventGuid,
|
||
|
|
int armNowTimeout, bool checkoutMode, int maxNumberEvents, bool SysMode)
|
||
|
|
{
|
||
|
|
var info = new ArmPacket(callback, userData, eventGuid, armNowTimeout);
|
||
|
|
info.DummyArm = checkoutMode;
|
||
|
|
info.SysMode = SysMode;
|
||
|
|
LaunchAsyncWorker("TDAS.PreparedArmNow", new WaitCallback(AsyncPreparedArmNow), info);
|
||
|
|
}
|
||
|
|
|
||
|
|
private const char SETUPDASREAD_SENTINEL = (char)127;
|
||
|
|
private void AsyncArmNow(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = asyncInfo as ArmPacket;
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
StartRecord = false;
|
||
|
|
if (IsG5() && (G5Mode == G5Modes.VDS))
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var dockstat = new G5DockStat(this, true);
|
||
|
|
dockstat.SyncExecute();
|
||
|
|
if (dockstat.BatteryChargeLevel == G5DockStat.BatteryChargeStates.red /*|| dockstat.BatteryChargeLevel == Command.TDAS.G5DockStat.BatteryChargeStates.yellow*/)
|
||
|
|
{
|
||
|
|
info?.Error("BatteryLowVoltage");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception) { }
|
||
|
|
}
|
||
|
|
var ra = new RackArm(this);
|
||
|
|
ra.ArmState = RackArm.ArmStates.NOW;
|
||
|
|
ra.SyncExecute();
|
||
|
|
if (ra.IsErrored) { throw new Exception(string.Format("{0}:{1}", SerialNumber, ra.ResponseData)); }
|
||
|
|
info?.Success();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
QueryModules qm = new QueryModules(this);
|
||
|
|
qm.SyncExecute();
|
||
|
|
info.Error(ex.Message);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AsyncPrepareForArmNow(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = asyncInfo as ArmPacket;
|
||
|
|
|
||
|
|
info?.Success();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AsyncPreparedArmNow(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = asyncInfo as ArmPacket;
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var moduleIndexToArm = -1;
|
||
|
|
for (var i = 0; i < ConfigData.Modules.Length; i++)
|
||
|
|
{
|
||
|
|
if (DASInfo.Modules[i].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (moduleIndexToArm == -1)
|
||
|
|
{
|
||
|
|
moduleIndexToArm = DASInfo.Modules[i].ModuleArrayIndex;
|
||
|
|
}
|
||
|
|
|
||
|
|
//per rollin, this can add debug information if we call it before module arm
|
||
|
|
if (IsTom(DASInfo.Modules[i].TypeOfModule))
|
||
|
|
{
|
||
|
|
var gts = new GetTOMSwitch(this);
|
||
|
|
gts.ModuleIndex = DASInfo.Modules[i].ModuleArrayIndex;
|
||
|
|
gts.SyncExecute();
|
||
|
|
var dasModule = DASInfo.Modules[i];
|
||
|
|
var configModule = ConfigData.Modules[dasModule.ModuleArrayIndex];
|
||
|
|
if (!info.DummyArm)
|
||
|
|
{
|
||
|
|
var tsa = new TestSquibArray(this);
|
||
|
|
tsa.ModuleIndex = dasModule.ModuleArrayIndex;
|
||
|
|
tsa.SyncExecute();
|
||
|
|
for (var iCh = 0; iCh < 8; iCh += 2)
|
||
|
|
{
|
||
|
|
if (!(configModule.Channels[iCh] is OutputSquibChannel squib) ||
|
||
|
|
ConfigData.TestID == "TESTTRIG")
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
} // do not check the reistance being in range for the long Test Trigger check.
|
||
|
|
|
||
|
|
if (squib.ConfigurationMode == DFConstantsAndEnums.ConfigMode.Normal)
|
||
|
|
{
|
||
|
|
var resistance = tsa.ResistanceOhms[Convert.ToInt32(Math.Floor(iCh / 2D))];
|
||
|
|
if (resistance > squib.SquibToleranceHigh)
|
||
|
|
{
|
||
|
|
info.Error
|
||
|
|
(
|
||
|
|
string.Format("{0} High",
|
||
|
|
DFConstantsAndEnums.CommandStatus.StatusArmSquibResistanceFault
|
||
|
|
.ToString())
|
||
|
|
);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (resistance < squib.SquibToleranceLow)
|
||
|
|
{
|
||
|
|
info.Error
|
||
|
|
(
|
||
|
|
$"{DFConstantsAndEnums.CommandStatus.StatusArmSquibResistanceFault.ToString()} Low"
|
||
|
|
);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
var qsn = new QuerySerialNumberBroadcast(this, moduleIndexToArm);
|
||
|
|
qsn.SyncExecute();
|
||
|
|
|
||
|
|
var mArm = new ModuleArmBroadcast(this, moduleIndexToArm, IsG5());
|
||
|
|
mArm.SyncExecute();
|
||
|
|
if (!IsG5())
|
||
|
|
{
|
||
|
|
//17717 ModuleArmBroadcast must wait on G5
|
||
|
|
//the G5 is waiting on syncexecute above, racks are not
|
||
|
|
//to make sure the rack doesn't try to execute another command too quickly
|
||
|
|
//I introduced a delay here based on EFizer seeing a 1.5s delay happening
|
||
|
|
//the delay should be as long as the slowest fully configured module..
|
||
|
|
//2.5 to me seems a generous amount of time to allow
|
||
|
|
Thread.Sleep(2500);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (CanceledException)
|
||
|
|
{
|
||
|
|
info.Cancel();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
//17717 ModuleArmBroadcast must wait on G5
|
||
|
|
//the modulearmbroadcast for a g5 now processes the response
|
||
|
|
//and in turn can throw an exception, so I handle the new exception here and
|
||
|
|
//send an error back to the service
|
||
|
|
info.Error(ex.Message, ex);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (IsG5() && (G5Mode == G5Modes.VDS))
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var dockstat = new G5DockStat(this, true);
|
||
|
|
dockstat.SyncExecute();
|
||
|
|
if (dockstat.BatteryChargeLevel == G5DockStat.BatteryChargeStates.red /*|| dockstat.BatteryChargeLevel == Command.TDAS.G5DockStat.BatteryChargeStates.yellow*/)
|
||
|
|
{
|
||
|
|
info.Error("BatteryLowVoltage");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception) { }
|
||
|
|
}
|
||
|
|
|
||
|
|
var ra = new RackArm(this);
|
||
|
|
ra.ArmState = ConfigData.TestID == "TESTTRIG" ? RackArm.ArmStates.NOW_TEST : RackArm.ArmStates.NOW;
|
||
|
|
ra.SyncExecute();
|
||
|
|
if (ra.IsErrored) { throw new Exception(string.Format("{0}:{1}", SerialNumber, ra.ResponseData)); }
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
var qm = new QueryModules(this);
|
||
|
|
qm.SyncExecute();
|
||
|
|
info.Error(ex.Message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public const string SQUIB_RESISTANCE_TOOHIGH = "SQUIB resistance too high";
|
||
|
|
public const string SQUIB_RESISTANCE_TOOLOW = "SQUIB resistance too low";
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region EnableFaultChecking
|
||
|
|
|
||
|
|
void IArmActions.EnableFaultChecking(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
LaunchAsyncWorker("TDAS.EnableFaultChecking", new WaitCallback(AsyncEnableFaultChecking), info);
|
||
|
|
}
|
||
|
|
|
||
|
|
void IArmActions.CheckAlreadyLevelTriggered(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
LaunchAsyncWorker("TDAS.CheckAlreadyLevelTriggered", new WaitCallback(AsyncCheckAlreadyLevelTriggered), info);
|
||
|
|
}
|
||
|
|
private void AsyncCheckAlreadyLevelTriggered(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = asyncInfo as TDASServiceAsyncInfo;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
foreach (var m in ConfigData.Modules)
|
||
|
|
{
|
||
|
|
foreach (var ch in m.Channels)
|
||
|
|
{
|
||
|
|
if (ch is AnalogInputDASChannel)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var aCh = ch as AnalogInputDASChannel;
|
||
|
|
if (aCh.LevelTriggerType == Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.NONE
|
||
|
|
|| aCh.ConfigurationMode != DFConstantsAndEnums.ConfigMode.Normal)
|
||
|
|
{
|
||
|
|
aCh.AlreadyLevelTriggered = false;
|
||
|
|
aCh.MeasuredEULevelTriggerCheck = double.NaN;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
aCh.AlreadyLevelTriggered = false;
|
||
|
|
aCh.MeasuredEULevelTriggerCheck = double.NaN;
|
||
|
|
//SA
|
||
|
|
var sa = new SampleAverageWithFallback(this, m.ModuleArrayIndex);
|
||
|
|
sa.SyncExecute();
|
||
|
|
|
||
|
|
var adc = sa.ChannelValues[aCh.ModuleChannelNumber];
|
||
|
|
double scalefactorMilliVoltsPerADC = aCh.ScalefactorMilliVoltsPerADC;
|
||
|
|
int offsetRemovalADC = 0;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var diagnostics = aCh.Diagnostics;
|
||
|
|
scalefactorMilliVoltsPerADC = diagnostics.ScalefactorMilliVoltsPerADC;
|
||
|
|
offsetRemovalADC = diagnostics.GetExpectedDataZeroLevelADC(aCh.ZeroMethod);
|
||
|
|
}
|
||
|
|
catch (Exception) { }
|
||
|
|
//short dataZeroLevelADC = 0;
|
||
|
|
//if (null != aCh.DiagnosticInformation) { dataZeroLevelADC = aCh.DiagnosticInformation.GetExpectedDataZeroLevelADC(aCh.ZeroMethod); }
|
||
|
|
|
||
|
|
//var eu = (adc - dataZeroLevelADC) * scalefactorMilliVoltsPerADC / aCh.SensitivityMilliVoltsPerEUNormalized;
|
||
|
|
//if (aCh.IsInverted) { eu *= -1D; }
|
||
|
|
//aCh.MeasuredEULevelTriggerCheck = eu;
|
||
|
|
var ds = aCh.GetDataScaler();
|
||
|
|
var eu = ds.GetEU(adc);
|
||
|
|
aCh.MeasuredEULevelTriggerCheck = eu;
|
||
|
|
switch (aCh.LevelTriggerType)
|
||
|
|
{
|
||
|
|
case Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.GreaterThan:
|
||
|
|
{
|
||
|
|
double euThreshold = (double)aCh.TriggerAboveThresholdEu;
|
||
|
|
if (euThreshold < eu)
|
||
|
|
{
|
||
|
|
aCh.AlreadyLevelTriggered = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.InsideWindow:
|
||
|
|
{
|
||
|
|
double euThresholdLower = (double)aCh.TriggerBelowThresholdEu;
|
||
|
|
double euThresholdHigher = (double)aCh.TriggerAboveThresholdEu;
|
||
|
|
|
||
|
|
if (euThresholdLower <= eu && eu <= euThresholdHigher)
|
||
|
|
{
|
||
|
|
aCh.AlreadyLevelTriggered = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.LessThan:
|
||
|
|
{
|
||
|
|
double euThreshold = (double)aCh.TriggerBelowThresholdEu;
|
||
|
|
if (euThreshold > eu)
|
||
|
|
{
|
||
|
|
aCh.AlreadyLevelTriggered = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes.OutsideWindow:
|
||
|
|
{
|
||
|
|
double euThresholdLower = (double)aCh.TriggerBelowThresholdEu;
|
||
|
|
double euThresholdHigher = (double)aCh.TriggerAboveThresholdEu;
|
||
|
|
|
||
|
|
if (euThresholdLower > eu || eu > euThresholdHigher)
|
||
|
|
{
|
||
|
|
aCh.AlreadyLevelTriggered = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception ex2)
|
||
|
|
{
|
||
|
|
APILogger.Log(ex2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info.Error(ex.Message, ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/// <summary>
|
||
|
|
/// calls TA Prev/TA Curr to keep a record of rack state in logs
|
||
|
|
/// </summary>
|
||
|
|
private void DoTAPrevCurRFCheck(bool loopOnFaulted)
|
||
|
|
{
|
||
|
|
var ta = new TestAll(this);
|
||
|
|
ta.Mode = TestAllCommandString.Modes.PREV;
|
||
|
|
ta.SyncExecute();
|
||
|
|
|
||
|
|
ta = new TestAll(this);
|
||
|
|
ta.Mode = TestAllCommandString.Modes.CURR;
|
||
|
|
ta.SyncExecute();
|
||
|
|
int maxIterations = 10;
|
||
|
|
int i = 1;
|
||
|
|
while (loopOnFaulted && ta.RackFault == DFConstantsAndEnums.VoltageStatusColor.Red && i <= maxIterations)
|
||
|
|
{
|
||
|
|
APILogger.Log($"### TACURRLOOP {SerialNumber} Iteration {i} RF={ta.RackFault.ToString()}");
|
||
|
|
// Pause for 100ms
|
||
|
|
Thread.Sleep(100);
|
||
|
|
|
||
|
|
//Lets Check again
|
||
|
|
ta = new TestAll(this);
|
||
|
|
ta.Mode = TestAllCommandString.Modes.CURR;
|
||
|
|
ta.SyncExecute();
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
private void AsyncEnableFaultChecking(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = asyncInfo as TDASServiceAsyncInfo;
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (RecordingModeExtensions.IsARecorderMode(ConfigData.Modules[0].RecordingMode))
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
//15616Add additional debug information into TDAS arm sequence
|
||
|
|
DoTAPrevCurRFCheck(true);
|
||
|
|
var queryArmStat = new QueryArmStatus(this);
|
||
|
|
queryArmStat.SyncExecute();
|
||
|
|
var ra = new RackArm(this);
|
||
|
|
ra.ArmState = RackArm.ArmStates.RF;
|
||
|
|
ra.SyncExecute();
|
||
|
|
if (ra.IsErrored)
|
||
|
|
{
|
||
|
|
//execute TA PREV to get the state of latched switches,
|
||
|
|
//ARM RF Error will sometimes lead to disarming, so get it now before returning
|
||
|
|
//this is in reference to discoveries in TDC in ZenDesk id7153
|
||
|
|
//support.dtsweb.com/hc/requests/7153
|
||
|
|
//code in TDC was RJW 2004, presumably added for more debugging information.
|
||
|
|
DoTAPrevCurRFCheck(false);
|
||
|
|
throw new Exception(string.Format("{0}:{1}", SerialNumber, ra.ResponseData));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
//15616 Add additional debug information into TDAS arm sequence
|
||
|
|
queryArmStat = new QueryArmStatus(this);
|
||
|
|
queryArmStat.SyncExecute();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
catch (CanceledException)
|
||
|
|
{
|
||
|
|
info.Cancel();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info.Error(ex.Message, ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region Disarm
|
||
|
|
void IArmActions.DisAutoArm(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
throw new NotSupportedException("DisAutoArm not supported for TDAS");
|
||
|
|
}
|
||
|
|
void IArmActions.Disarm(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
LaunchAsyncWorker("TDAS.Disarm", new WaitCallback(AsyncDisarm), info);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AsyncDisarm(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = asyncInfo as TDASServiceAsyncInfo;
|
||
|
|
|
||
|
|
if (null != DASArmStatus && DASArmStatus.IsTriggered && DASArmStatus.IsRecording)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var stopNow = new ARMSTOP(this);
|
||
|
|
stopNow.SyncExecute();
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
catch (CanceledException)
|
||
|
|
{
|
||
|
|
info.Cancel();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info.Error(ex.Message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!IsG5())
|
||
|
|
{
|
||
|
|
//try to disarm any modules ...
|
||
|
|
//this doesn't work, it just hangs things.
|
||
|
|
/*foreach (var m in DASInfo.Modules)
|
||
|
|
{
|
||
|
|
if (m.TypeOfModule == InfoResult.Module.ModuleType.EMPTYBANK) { continue; }
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var armoff = new DTS.DASLib.Command.TDAS.ARMOFF(this);
|
||
|
|
armoff.ModuleIndex = m.ModuleArrayIndex;
|
||
|
|
armoff.SyncExecute();
|
||
|
|
}
|
||
|
|
catch (System.Exception ex)
|
||
|
|
{
|
||
|
|
APILogger.Log(ex);
|
||
|
|
}
|
||
|
|
}*/
|
||
|
|
}
|
||
|
|
try
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var armOff = new ARMOFF(this);
|
||
|
|
armOff.SyncExecute();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
APILogger.Log(ex);
|
||
|
|
}
|
||
|
|
//11326 Failed to arm in check trigger navi step
|
||
|
|
//see above issue for more details
|
||
|
|
//IMMEDIATELY turn back on all excitation
|
||
|
|
|
||
|
|
foreach (var module in ConfigData.Modules)
|
||
|
|
{
|
||
|
|
bool bAnalog = true;
|
||
|
|
if (IsG5() && module.ModuleArrayIndex > 3) { continue; }//skip digital banks
|
||
|
|
switch (DASInfo.Modules[module.ModuleArrayIndex].TypeOfModule)
|
||
|
|
{
|
||
|
|
case DFConstantsAndEnums.ModuleType.EMPTYBANK: continue;
|
||
|
|
case DFConstantsAndEnums.ModuleType.ProDIM: continue;
|
||
|
|
case DFConstantsAndEnums.ModuleType.G5Digital: continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
var setExcitation = new SetExcitation(this);
|
||
|
|
setExcitation.ModuleIndex = module.ModuleArrayIndex;
|
||
|
|
var channels = new List<int>();
|
||
|
|
var excitation = new List<int>();
|
||
|
|
|
||
|
|
foreach (var channel in module.Channels)
|
||
|
|
{
|
||
|
|
if (!channel.IsConfigured() || !bAnalog)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
if (!(channel is AnalogInputDASChannel aic))
|
||
|
|
{
|
||
|
|
bAnalog = false;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
switch (aic.Excitation)
|
||
|
|
{
|
||
|
|
case Common.Enums.ExcitationVoltageOptions.ExcitationVoltageOption.Volt10:
|
||
|
|
channels.Add(aic.ModuleChannelNumber);
|
||
|
|
excitation.Add(SetExcitation.SIM_TEN_VOLT);
|
||
|
|
break;
|
||
|
|
case Common.Enums.ExcitationVoltageOptions.ExcitationVoltageOption.Volt2:
|
||
|
|
channels.Add(aic.ModuleChannelNumber);
|
||
|
|
excitation.Add(IsG5() ? SetExcitation.G5_TWO_VOLT : SetExcitation.SIM_TWO_VOLT);
|
||
|
|
break;
|
||
|
|
case Common.Enums.ExcitationVoltageOptions.ExcitationVoltageOption.Volt5:
|
||
|
|
channels.Add(aic.ModuleChannelNumber);
|
||
|
|
if (IsG5())
|
||
|
|
{
|
||
|
|
excitation.Add(SetExcitation.G5_FIVE_VOLT);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
excitation.Add(SetExcitation.FIVE_VOLT);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (bAnalog && channels.Any())
|
||
|
|
{
|
||
|
|
setExcitation.Channels = channels.ToArray();
|
||
|
|
setExcitation.ExcitationModes = excitation.ToArray();
|
||
|
|
//setExcitation.SyncExecute();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
APILogger.Log(ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
info?.Success();
|
||
|
|
}
|
||
|
|
catch (CanceledException)
|
||
|
|
{
|
||
|
|
info?.Cancel();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info?.Error(ex.Message, ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region GetArmStatus
|
||
|
|
void IArmActions.GetAutoArmStatus(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
|
||
|
|
LaunchAsyncWorker("TDAS.GetAutoArmStatus", new WaitCallback(AsyncGetAutoArmStatus), info);
|
||
|
|
}
|
||
|
|
|
||
|
|
void IArmActions.GetArmStatus(ServiceCallback callback, object userData, uint inputVoltageCutoff, int maxTimeout)
|
||
|
|
{
|
||
|
|
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
|
||
|
|
LaunchAsyncWorker("TDAS.GetArmStatus", new WaitCallback(AsyncGetArmStatus), info);
|
||
|
|
}
|
||
|
|
void IArmActions.GetExtendedFaultIds(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
|
||
|
|
LaunchAsyncWorker("TDAS.GetExtendedFaultIds", new WaitCallback(TDASAsyncGetExtendedFaultIds), info);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void TDASAsyncGetExtendedFaultIds(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = (TDASServiceAsyncInfo)asyncInfo;
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
private DateTime recordTime = DateTime.MinValue;
|
||
|
|
private DateTime triggerTime = DateTime.MinValue;
|
||
|
|
private DateTime armedTime = DateTime.MinValue;
|
||
|
|
|
||
|
|
|
||
|
|
private volatile bool _bInFlashWrite = false;
|
||
|
|
private DateTime _timeOfFirstFlashWrite = DateTime.MinValue;
|
||
|
|
private static object FlashWriteTimeLock = new object();
|
||
|
|
private volatile bool _previousRackFault = false;
|
||
|
|
private volatile bool _previousModuleFault = false;
|
||
|
|
|
||
|
|
private void AsyncGetArmStatus(object asyncInfo)
|
||
|
|
{
|
||
|
|
TDASServiceAsyncInfo info = asyncInfo as TDASServiceAsyncInfo;
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (null == BaseInput)
|
||
|
|
{
|
||
|
|
//var ta = new Command.TDAS.TestAll(this);
|
||
|
|
//ta.SyncExecute();
|
||
|
|
BaseInput = new BaseInputValues
|
||
|
|
{
|
||
|
|
InputVoltageStatusColor = DFConstantsAndEnums.VoltageStatusColor.Off,
|
||
|
|
InputVoltageStatus = DFConstantsAndEnums.VoltageStatusColor.Off.ToString(),
|
||
|
|
StatusDisplayInput = String.Empty,
|
||
|
|
|
||
|
|
BatteryVoltageStatus = DFConstantsAndEnums.VoltageStatusColor.Off.ToString(),
|
||
|
|
BatteryVoltageStatusColor = DFConstantsAndEnums.VoltageStatusColor.Off,
|
||
|
|
StatusDisplayBattery = String.Empty
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception ex) { APILogger.Log(ex); }
|
||
|
|
try
|
||
|
|
{
|
||
|
|
QueryArmStatus arm = new QueryArmStatus(this);
|
||
|
|
arm.SyncExecute();
|
||
|
|
|
||
|
|
LEDS leds = null;
|
||
|
|
if (!IsG5() && arm.Status == QueryArmStatus.ARMStatus.DONE)
|
||
|
|
{
|
||
|
|
Thread.Sleep(1000); // let's hangout for a bit. This is moving too quickly after status done from armstatus is seen
|
||
|
|
leds = new LEDS(this);
|
||
|
|
leds.SyncExecute();
|
||
|
|
if (leds.CalFault == LEDS.FlagStatus.YellowOrYes)
|
||
|
|
{
|
||
|
|
arm.SetStatus(QueryArmStatus.ARMStatus.CAL);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (BaseInput != null)
|
||
|
|
{
|
||
|
|
bool bLowPower = arm.LowPower;
|
||
|
|
if (IsG5())
|
||
|
|
{
|
||
|
|
if (BaseInput.StatusDisplayBattery == TestAll.VoltageStatus.None.ToString())
|
||
|
|
{
|
||
|
|
if (BaseInput.StatusDisplayBattery == TestAll.VoltageStatus.None.ToString())/* no battery - display input */
|
||
|
|
{
|
||
|
|
BaseInput.InputVoltageStatus = bLowPower
|
||
|
|
? DFConstantsAndEnums.VoltageStatusColor.Red.ToString()
|
||
|
|
: DFConstantsAndEnums.VoltageStatusColor.Green.ToString();
|
||
|
|
BaseInput.InputVoltageStatusColor = bLowPower ? DFConstantsAndEnums.VoltageStatusColor.Red : DFConstantsAndEnums.VoltageStatusColor.Green;
|
||
|
|
BaseInput.StatusDisplayInput = bLowPower
|
||
|
|
? TestAll.VoltageStatus.Low.ToString()
|
||
|
|
: TestAll.VoltageStatus.Good.ToString();
|
||
|
|
|
||
|
|
BaseInput.BatteryVoltageStatus = String.Empty;
|
||
|
|
BaseInput.BatteryVoltageStatusColor = DFConstantsAndEnums.VoltageStatusColor.Off;
|
||
|
|
BaseInput.StatusDisplayBattery = TestAll.VoltageStatus.None.ToString();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
BaseInput.InputVoltageStatus = String.Empty;
|
||
|
|
BaseInput.InputVoltageStatusColor = DFConstantsAndEnums.VoltageStatusColor.Off;
|
||
|
|
BaseInput.StatusDisplayInput = TestAll.VoltageStatus.None.ToString();
|
||
|
|
|
||
|
|
BaseInput.BatteryVoltageStatus = bLowPower
|
||
|
|
? DFConstantsAndEnums.VoltageStatusColor.Red.ToString()
|
||
|
|
: DFConstantsAndEnums.VoltageStatusColor.Green.ToString();
|
||
|
|
BaseInput.BatteryVoltageStatusColor = bLowPower
|
||
|
|
? DFConstantsAndEnums.VoltageStatusColor.Red
|
||
|
|
: DFConstantsAndEnums.VoltageStatusColor.Green;
|
||
|
|
BaseInput.StatusDisplayBattery = bLowPower
|
||
|
|
? TestAll.VoltageStatus.Low.ToString()
|
||
|
|
: TestAll.VoltageStatus.Good.ToString();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
BaseInput.InputVoltageStatus = String.Empty;
|
||
|
|
BaseInput.InputVoltageStatusColor = DFConstantsAndEnums.VoltageStatusColor.Off;
|
||
|
|
BaseInput.StatusDisplayInput = "---";
|
||
|
|
|
||
|
|
BaseInput.StatusDisplayBattery = bLowPower
|
||
|
|
? DFConstantsAndEnums.VoltageStatusColor.Red.ToString()
|
||
|
|
: DFConstantsAndEnums.VoltageStatusColor.Green.ToString();
|
||
|
|
BaseInput.BatteryVoltageStatusColor = bLowPower
|
||
|
|
? DFConstantsAndEnums.VoltageStatusColor.Red
|
||
|
|
: DFConstantsAndEnums.VoltageStatusColor.Green;
|
||
|
|
BaseInput.BatteryVoltageStatus = bLowPower
|
||
|
|
? TestAll.VoltageStatus.Low.ToString()
|
||
|
|
: TestAll.VoltageStatus.Good.ToString();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
ArmStatus status = new ArmStatus();
|
||
|
|
status.IsRearming = false;
|
||
|
|
|
||
|
|
//there's a bit of a problem here, the das could be faulted, but if it's triggered we don't know, we need
|
||
|
|
|
||
|
|
if (arm.HardwareTrigger || arm.LevelTrigger)
|
||
|
|
{
|
||
|
|
if (null != DASArmStatus) { status.IsFaulted = DASArmStatus.IsFaulted; }
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
bool taQueried = false;
|
||
|
|
if (arm.ModuleFault)
|
||
|
|
{
|
||
|
|
if (_previousModuleFault)
|
||
|
|
{
|
||
|
|
TestAll ta = new TestAll(this);
|
||
|
|
ta.Mode = TestAllCommandString.Modes.PREV;
|
||
|
|
ta.SyncExecute();
|
||
|
|
|
||
|
|
ta = new TestAll(this);
|
||
|
|
ta.Mode = TestAllCommandString.Modes.CURR;
|
||
|
|
ta.SyncExecute();
|
||
|
|
taQueried = true;
|
||
|
|
status.IsFaulted = true;
|
||
|
|
}
|
||
|
|
_previousModuleFault = true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_previousModuleFault = false;
|
||
|
|
}
|
||
|
|
if (arm.RackFault)
|
||
|
|
{
|
||
|
|
if (!taQueried)
|
||
|
|
{
|
||
|
|
TestAll ta = new TestAll(this);
|
||
|
|
ta.Mode = TestAllCommandString.Modes.PREV;
|
||
|
|
ta.SyncExecute();
|
||
|
|
|
||
|
|
ta = new TestAll(this);
|
||
|
|
ta.Mode = TestAllCommandString.Modes.CURR;
|
||
|
|
ta.SyncExecute();
|
||
|
|
}
|
||
|
|
if (_previousRackFault)
|
||
|
|
{
|
||
|
|
status.IsFaulted = true;
|
||
|
|
}
|
||
|
|
_previousRackFault = true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_previousRackFault = false;
|
||
|
|
}
|
||
|
|
//status.IsFaulted = arm.ModuleFault || arm.RackFault;
|
||
|
|
}
|
||
|
|
status.IsInFlashWrite = false;
|
||
|
|
status.IsInPostTestDiagnostics = false;
|
||
|
|
switch (arm.Status)
|
||
|
|
{
|
||
|
|
case QueryArmStatus.ARMStatus.ARMED:
|
||
|
|
_bInFlashWrite = false;
|
||
|
|
if (null != ConfigData && null != ConfigData.Modules && ConfigData.Modules.Length > 0)
|
||
|
|
{
|
||
|
|
if (ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.CircularBuffer ||
|
||
|
|
ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART ||
|
||
|
|
ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.AutoCircularBufferMode ||
|
||
|
|
ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.a16_CircularBufferAndStreamSubSampleMode)
|
||
|
|
{
|
||
|
|
if (recordTime == DateTime.MinValue) { recordTime = DateTime.Now; }
|
||
|
|
}
|
||
|
|
else { recordTime = DateTime.MinValue; }
|
||
|
|
}
|
||
|
|
else { recordTime = DateTime.MinValue; }
|
||
|
|
triggerTime = DateTime.MinValue;
|
||
|
|
if (DateTime.MinValue == armedTime) { armedTime = DateTime.Now; }
|
||
|
|
status.IsArmed = true;
|
||
|
|
break;
|
||
|
|
case QueryArmStatus.ARMStatus.ARMING:
|
||
|
|
_bInFlashWrite = false;
|
||
|
|
recordTime = DateTime.MinValue;
|
||
|
|
triggerTime = DateTime.MinValue;
|
||
|
|
status.IsArmed = true;
|
||
|
|
// status.IsRearming = true;
|
||
|
|
status.HasBeenRecording = false;
|
||
|
|
break;
|
||
|
|
case QueryArmStatus.ARMStatus.DONE:
|
||
|
|
_bInFlashWrite = false;
|
||
|
|
status.IsArmed = false;
|
||
|
|
break;
|
||
|
|
case QueryArmStatus.ARMStatus.FLASH:
|
||
|
|
status.IsArmed = false;
|
||
|
|
break;
|
||
|
|
case QueryArmStatus.ARMStatus.FLASHWRITE:
|
||
|
|
status.IsArmed = false;
|
||
|
|
status.IsRecording = false;
|
||
|
|
status.IsInFlashWrite = true;
|
||
|
|
if (!_bInFlashWrite) { _bInFlashWrite = true; lock (FlashWriteTimeLock) { _timeOfFirstFlashWrite = DateTime.Now; } }
|
||
|
|
break;
|
||
|
|
case QueryArmStatus.ARMStatus.REC:
|
||
|
|
if (DateTime.MinValue == recordTime) { recordTime = DateTime.Now; }
|
||
|
|
status.IsArmed = true;
|
||
|
|
status.IsRecording = true;
|
||
|
|
|
||
|
|
status.HasBeenRecording = true;
|
||
|
|
break;
|
||
|
|
case QueryArmStatus.ARMStatus.TRIG:
|
||
|
|
armedTime = DateTime.MinValue;
|
||
|
|
if (DateTime.MinValue == triggerTime) { triggerTime = DateTime.Now; }
|
||
|
|
status.IsArmed = true;
|
||
|
|
status.IsTriggered = true;
|
||
|
|
status.IsRecording = true;
|
||
|
|
status.HasBeenRecording = true;
|
||
|
|
break;
|
||
|
|
case QueryArmStatus.ARMStatus.UNDEFINED:
|
||
|
|
status.IsArmed = false;
|
||
|
|
break;
|
||
|
|
case QueryArmStatus.ARMStatus.CAL:
|
||
|
|
status.IsArmed = true;
|
||
|
|
status.IsInPostTestDiagnostics = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (arm.StartRecord)
|
||
|
|
{
|
||
|
|
StartRecord = true;
|
||
|
|
}
|
||
|
|
else { StartRecord = false; }
|
||
|
|
|
||
|
|
if (arm.HardwareTrigger) { status.IsTriggered = true; }
|
||
|
|
else if (arm.LevelTrigger) { status.IsTriggered = true; }
|
||
|
|
if (arm.StartRecord && arm.Status != QueryArmStatus.ARMStatus.FLASHWRITE) { status.IsRecording = true; }
|
||
|
|
var faultMessage = new StringBuilder();
|
||
|
|
//took out TA below as TA should only be called after a fault
|
||
|
|
if (arm.ModuleFault && !arm.HardwareTrigger)
|
||
|
|
{
|
||
|
|
if (_previousModuleFault)
|
||
|
|
{
|
||
|
|
status.IsFaulted = true;
|
||
|
|
if (faultMessage.Length > 0) { faultMessage.Append(", "); }
|
||
|
|
faultMessage.Append("module fault");
|
||
|
|
}
|
||
|
|
_previousModuleFault = true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_previousModuleFault = false;
|
||
|
|
}
|
||
|
|
//took out TA below as TA should only be called after a fault
|
||
|
|
if (arm.RackFault && !(/*ta.TriggerFlag == Command.TDAS.TestAll.VoltageStatusColor.Red ||*/ arm.HardwareTrigger))
|
||
|
|
{
|
||
|
|
if (_previousRackFault)
|
||
|
|
{
|
||
|
|
status.IsFaulted = true;
|
||
|
|
if (faultMessage.Length > 0) { faultMessage.Append(", "); }
|
||
|
|
faultMessage.Append("rack fault");
|
||
|
|
}
|
||
|
|
_previousRackFault = true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_previousRackFault = false;
|
||
|
|
}
|
||
|
|
//took out TA below as TA should only be called after a fault
|
||
|
|
if (arm.LowPower /*|| ta.PrimaryPower == Command.TDAS.TestAll.VoltageStatusColor.Red*/)
|
||
|
|
{
|
||
|
|
status.IsFaulted = true;
|
||
|
|
if (faultMessage.Length > 0) { faultMessage.Append(", "); }
|
||
|
|
faultMessage.Append("low power");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (status.IsFaulted) { status.FaultMessage = faultMessage.ToString(); }
|
||
|
|
|
||
|
|
if (arm.Status == QueryArmStatus.ARMStatus.DONE)
|
||
|
|
{
|
||
|
|
status.IsRecording = false;
|
||
|
|
status.IsTriggered = false;
|
||
|
|
status.IsArmed = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (status.IsArmed)
|
||
|
|
{
|
||
|
|
ExcitationStatus = DFConstantsAndEnums.ExcitationStatus.On;
|
||
|
|
if (null == ConfigData)
|
||
|
|
{
|
||
|
|
ManualResetEvent finished = new ManualResetEvent(false);
|
||
|
|
|
||
|
|
(this as IConfigurationActions).QueryConfiguration(
|
||
|
|
delegate (ServiceCallbackData data)
|
||
|
|
{
|
||
|
|
switch (data.Status)
|
||
|
|
{
|
||
|
|
case ServiceCallbackData.CallbackStatus.Success:
|
||
|
|
case ServiceCallbackData.CallbackStatus.Failure:
|
||
|
|
case ServiceCallbackData.CallbackStatus.Canceled:
|
||
|
|
finished.Set();
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
}, null, 0, string.Empty, false);
|
||
|
|
|
||
|
|
while (false == finished.WaitOne(50)) { Thread.Sleep(10); }
|
||
|
|
}
|
||
|
|
|
||
|
|
if (null != ConfigData)
|
||
|
|
{
|
||
|
|
double timeRemaining = ConfigData.Modules[0].PreTriggerSeconds + ConfigData.Modules[0].PostTriggerSeconds;
|
||
|
|
status.CurrentSample = 0;
|
||
|
|
switch (ConfigData.Modules[0].RecordingMode)
|
||
|
|
{
|
||
|
|
case DFConstantsAndEnums.RecordingMode.CircularBuffer:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.AutoCircularBufferMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.a16_CircularBufferAndStreamSubSampleMode:
|
||
|
|
status.IsRecording = true;
|
||
|
|
status.HasBeenRecording = true;
|
||
|
|
//for circular buffer we only need to calculate if we've seen trigger
|
||
|
|
status.RecordingMode = Convert.ToInt32(ConfigData.Modules[0].RecordingMode);
|
||
|
|
if (DateTime.MinValue != triggerTime)
|
||
|
|
{
|
||
|
|
double secondsSpent = DateTime.Now.Subtract(triggerTime).TotalSeconds;
|
||
|
|
timeRemaining = Math.Max(0, ConfigData.Modules[0].PostTriggerSeconds - (DateTime.Now.Subtract(triggerTime)).TotalSeconds);
|
||
|
|
//timeRemaining = Math.Max(0, ConfigData.Modules[0].PostTriggerSeconds - secondsSpent);
|
||
|
|
status.CurrentSample = Convert.ToUInt64(ConfigData.Modules[0].SampleRateHz * ConfigData.Modules[0].PreTriggerSeconds
|
||
|
|
+ ConfigData.Modules[0].SampleRateHz * secondsSpent);
|
||
|
|
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (DateTime.MinValue == recordTime)
|
||
|
|
{
|
||
|
|
if (status.IsRecording) { recordTime = DateTime.Now; }
|
||
|
|
}
|
||
|
|
double secondsSpent = DateTime.Now.Subtract(recordTime).TotalSeconds;
|
||
|
|
//timeRemaining = Math.Max(0, ConfigData.Modules[0].PreTriggerSeconds - secondsSpent);
|
||
|
|
if (secondsSpent > ConfigData.Modules[0].PreTriggerSeconds)
|
||
|
|
{
|
||
|
|
timeRemaining = ConfigData.Modules[0].PostTriggerSeconds;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
//timeRemaining = ConfigData.Modules[0].PostTriggerSeconds - secondsSpent;
|
||
|
|
timeRemaining = ConfigData.Modules[0].PreTriggerSeconds - secondsSpent;
|
||
|
|
}
|
||
|
|
status.CurrentSample = Convert.ToUInt64(ConfigData.Modules[0].SampleRateHz * secondsSpent);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DFConstantsAndEnums.RecordingMode.RecorderMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.a14_NormalRecorderAndStreamSubSampleMode:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.RecorderModePlusUART:
|
||
|
|
case DFConstantsAndEnums.RecordingMode.AutoRecorderMode:
|
||
|
|
//for recorder mode we really only care about the total time spent
|
||
|
|
status.RecordingMode = Convert.ToInt32(ConfigData.Modules[0].RecordingMode);
|
||
|
|
if (DateTime.MinValue != recordTime)
|
||
|
|
{
|
||
|
|
double secondsSpent = DateTime.Now.Subtract(recordTime).TotalSeconds;
|
||
|
|
timeRemaining -= Math.Min(timeRemaining, secondsSpent);
|
||
|
|
status.CurrentSample = Convert.ToUInt64(secondsSpent * ConfigData.Modules[0].SampleRateHz);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw new NotSupportedException("unknown recording mode for tdas");
|
||
|
|
}
|
||
|
|
|
||
|
|
status.TotalSamples = Convert.ToUInt64((ConfigData.Modules[0].SampleRateHz * (ConfigData.Modules[0].PreTriggerSeconds + ConfigData.Modules[0].PostTriggerSeconds)));
|
||
|
|
status.SampleRate = ConfigData.Modules[0].SampleRateHz;
|
||
|
|
status.TimeRemainingSeconds = timeRemaining;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// In theory we should never get to this case.
|
||
|
|
// We need to reconstruct needed info without ConfigData
|
||
|
|
//also note, you're probably going to need a module index, which the code below isn't using? I'm going to leave the code in for now
|
||
|
|
SetupDASRead SDR = new SetupDASRead(this);
|
||
|
|
SDR.SyncExecute();
|
||
|
|
status.SampleRate = (uint)SDR.ActualSampleRate;
|
||
|
|
status.TotalSamples = Convert.ToUInt64((status.SampleRate * (SDR.PreTriggerTimeInSeconds + SDR.PostTriggerTimeInSeconds)));
|
||
|
|
if (SDR.ArmMode == SetupDASLoad.ARMMode.TAPE)
|
||
|
|
{
|
||
|
|
status.RecordingMode = Convert.ToInt32(DFConstantsAndEnums.RecordingMode.RecorderMode);
|
||
|
|
}
|
||
|
|
else if (SDR.ArmMode == SetupDASLoad.ARMMode.WAIT)
|
||
|
|
{
|
||
|
|
status.RecordingMode = Convert.ToInt32(DFConstantsAndEnums.RecordingMode.CircularBuffer);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
status.RecordingMode = Convert.ToInt32(DFConstantsAndEnums.RecordingMode.InvalidArmMode);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Don't have a way to know record time or trigger time, so need to assume the test hasn't started.
|
||
|
|
status.TimeRemainingSeconds = status.SampleRate * status.TotalSamples;
|
||
|
|
status.CurrentSample = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
status.SampleRate = 0;
|
||
|
|
status.TimeRemainingSeconds = 0;
|
||
|
|
status.TotalSamples = 0;
|
||
|
|
status.CurrentSample = 0;
|
||
|
|
status.RecordingMode = 0;
|
||
|
|
}
|
||
|
|
if (arm.Status == QueryArmStatus.ARMStatus.FLASHWRITE)
|
||
|
|
{
|
||
|
|
double timeRemaining = 0D;
|
||
|
|
lock (FlashWriteTimeLock)
|
||
|
|
{
|
||
|
|
timeRemaining = EXPECTED_FLASHWRITE_TIME - DateTime.Now.Subtract(_timeOfFirstFlashWrite).TotalSeconds;
|
||
|
|
if (timeRemaining > EXPECTED_FLASHWRITE_TIME) { timeRemaining = EXPECTED_FLASHWRITE_TIME; }
|
||
|
|
if (timeRemaining < 0) { timeRemaining = 0; }
|
||
|
|
}
|
||
|
|
|
||
|
|
status.TimeRemainingSeconds = timeRemaining;
|
||
|
|
|
||
|
|
double d = 100D * (EXPECTED_FLASHWRITE_TIME - timeRemaining) / EXPECTED_FLASHWRITE_TIME;
|
||
|
|
if (d < 0) { d = 1; }
|
||
|
|
if (d > 100) { d = 100; }
|
||
|
|
status.PercentComplete = d;
|
||
|
|
|
||
|
|
//System.Diagnostics.Trace.WriteLine("Time remaining: " + status.TimeRemainingSeconds.ToString() + " percentcomplete: " + status.PercentComplete.ToString());
|
||
|
|
}
|
||
|
|
|
||
|
|
if (arm.Status == QueryArmStatus.ARMStatus.UNDEFINED)
|
||
|
|
{
|
||
|
|
status.IsUndefined = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
status.EventNumber = 0;
|
||
|
|
|
||
|
|
// Now check power
|
||
|
|
if (IsG5() && G5Mode == G5Modes.VDS && false == status.IsRecording && false == status.IsInFlashWrite && false == status.IsUndefined)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
G5DockStat ds = new G5DockStat(this, true);
|
||
|
|
ds.SyncExecute();
|
||
|
|
status.BatteryMilliVolts = ds.BatteryMilliVolts;
|
||
|
|
}
|
||
|
|
catch (Exception) { /* tolerate failure in the case where it's not in a VDS */ }
|
||
|
|
|
||
|
|
//Command.TDAS.TestBattery tb = new Command.TDAS.TestBattery(this);
|
||
|
|
//tb.SyncExecute();
|
||
|
|
|
||
|
|
status.BatteryMilliVolts = null;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
SetDASArmStatus(status, true);
|
||
|
|
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
catch (CanceledException)
|
||
|
|
{
|
||
|
|
info.Cancel();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info.Error(ex.Message, ex);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
private const double EXPECTED_FLASHWRITE_TIME = 120;
|
||
|
|
private void AsyncGetAutoArmStatus(object asyncInfo)
|
||
|
|
{
|
||
|
|
TDASServiceAsyncInfo info = asyncInfo as TDASServiceAsyncInfo;
|
||
|
|
AutoArmStatus = DFConstantsAndEnums.CommandStatus.StatusUnimplemented;
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region EnterLowPowerMode
|
||
|
|
|
||
|
|
void IArmActions.EnterLowPowerMode(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
|
||
|
|
LaunchAsyncWorker("TDAS.EnterLowPowerMode", new WaitCallback(AsyncEnterLowPowerMode), info);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AsyncEnterLowPowerMode(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = asyncInfo as TDASServiceAsyncInfo;
|
||
|
|
DiagnosticsHasBeenRun = false;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
//clear any diagnostic results we have, they will be invalid after we go to low power
|
||
|
|
//16164 User can proceed past diag. without running on all channels
|
||
|
|
ClearChannelDiagnosticsResults();
|
||
|
|
TurnOffExcitation();
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
catch (CanceledException)
|
||
|
|
{
|
||
|
|
info.Cancel();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info.Error(ex.Message, ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region Start & Trigger
|
||
|
|
|
||
|
|
void IArmActions.StartRecord(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
|
||
|
|
LaunchAsyncWorker("TDAS.StartRecord", new WaitCallback(AsyncStartRecord), info);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AsyncStartRecord(object asyncInfo)
|
||
|
|
{
|
||
|
|
TDASServiceAsyncInfo info = asyncInfo as TDASServiceAsyncInfo;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
RackStartCommand rs = new RackStartCommand(this);
|
||
|
|
rs.SyncExecute();
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info.Error(ex.Message, ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void IArmActions.Trigger(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
LaunchAsyncWorker("TDAS.Trigger", new WaitCallback(AsyncTrigger), info);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
private void AsyncTrigger(object asyncInfo)
|
||
|
|
{
|
||
|
|
var info = asyncInfo as TDASServiceAsyncInfo;
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
RackTriggerCommand rtc = new RackTriggerCommand(
|
||
|
|
this);
|
||
|
|
rtc.SyncExecute();
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
info.Error(ex.Message, ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
public void PerformVoltageCheckTAOnly(ServiceCallback callback, object userData)
|
||
|
|
{
|
||
|
|
var info = new TDASServiceAsyncInfo(callback, userData);
|
||
|
|
LaunchAsyncWorker("TDAS.PerformVoltageCheckTAOnly", new WaitCallback(AsyncPerformVoltageCheckTAOnly), info);
|
||
|
|
}
|
||
|
|
private void AsyncPerformVoltageCheckTAOnly(object o)
|
||
|
|
{
|
||
|
|
TDASServiceAsyncInfo info = o as TDASServiceAsyncInfo;
|
||
|
|
info.Success();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|