Files

282 lines
16 KiB
C#
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
using DTS.Common.Constant.DASSpecific;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Enums.Sensors;
using DTS.Common.ICommunication;
using DTS.Common.Interface.Connection;
using DTS.Common.Interface.DASFactory.Config;
using DTS.Common.Utilities.Logging;
using DTS.DASLib.Command.SLICE;
using System;
using System.Collections.Generic;
using System.Linq;
namespace DTS.DASLib.Service
{
public class SLICE6AIRBR<T> : SLICE6_Base<T>, IAlignUDPToPPSAware where T : IConnection, new()
{
public bool AlignUDPToPPS { get; set; }
public override bool SupportsRemoveLeapSeconds => true;
public override bool SupportsADCSamplesPerPacket => true;
protected override bool RequiresNon0QualificationSamples => true;
protected override byte[] GetRTChannelIndices(RealTimeAsyncPacket packet)
{
return new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
}
public override void SetIsStreamingSupported(bool supported)
{
IsStreamingSupported = true;
}
/// <summary>
/// the order of this DAS among multiple das
/// </summary>
public int DASIndex { get; set; } = -1;
public override void InitMinProto()
{
// SLICE 6.0 Protocol Limitations
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleAndHybridEvents] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleEvents] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArm] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmRepeatEnable] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetDefaultMIF] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FileData] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackSensors] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.TestCommunication] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackLowPowerMode] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetRealtimeSampleRate] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SLICE2_OneWireID] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareRevision] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareConfiguration] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventFaultFlags] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventArmAttempts] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryActualSampleRateImmediate] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageSysAttributes] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.LevelTrigger] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AttributeStoreBlocks] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryArmAndTriggerStatus_VoltageReadings] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MaxEvents] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmDiagnosticDelay] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelAutoArmDiagLevel] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FlashClear] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleSamplesRealtime] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseCalibrationDate] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.IgnoreShortedStartEvent] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ResetAttributeStore] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.DiangosShuntDAC] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageInsertion] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPTimestamp] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRecDelayInSecond] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryTiltSensorData] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InSliceTiltSensorADCPre] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRealtimeStream] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.UDPRealtimeStream] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.GenerateEvent] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPSyncStatus] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetClockSyncConfig] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetDSPFilterSettings] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPDomainID] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ActiveRAM] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordAndStreamSubSample] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RemoveLeapSeconds] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordOnBoot] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleAndHybridEvents] = SLICE6AIRBR.MIN_PROTOCOL_VER;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.UDPAlignOnPPS] = SLICE6AIRBR.UDPALIGNONPPS_PROTOCOL;
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ADCSamplesPerPacket] = SLICE6AIRBR.ADC_SAMPLES_PER_PACKET_VER;
MinimumProtocols = SLICE6AIR_BR_MinimumProtocols;
}
#region protocol settings/overrides
private readonly Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte> SLICE6AIR_BR_MinimumProtocols =
new Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>();
protected override int MIN_PROTOCOL_TMATS_INTERVAL => SLICE6AIRBR.MIN_PROTOCOL_VER;
private uint maxSampleRateHz = 0;
protected override uint MaxSampleRateHz
{
get
{
if (0 == maxSampleRateHz)
{
try
{
var qsa = new QuerySystemAttributeSLICE6(this)
{
Key = AttributeTypes.SystemAttributesSLICE6.MaximumSampleRate
};
qsa.SyncExecute();
maxSampleRateHz = (uint)qsa.Value;
}
catch (Exception ex)
{
APILogger.Log("Error getting S6A-BR max sample rate, returning 50K");
APILogger.LogException(ex);
return 50000;
}
}
return maxSampleRateHz;
}
}
#endregion
protected override DASModule MakeConfigModuleFromInfoModule(InfoResult.Module infoModule)
{
//per LP: can stream, no IEPE
var configModule = new DASModule(infoModule.ModuleArrayIndex, this);
configModule.Channels = new DASChannel[infoModule.NumberOfChannels];
for (var i = 0; i < infoModule.NumberOfChannels; i++)
{
if (DFConstantsAndEnums.ModuleType.StreamOut == configModule.ModuleType())
{
var streamOutChannel = new StreamOutputDASChannel(configModule, i);
configModule.Channels[i] = streamOutChannel;
}
else
{
var channel = new AnalogInputDASChannel(configModule, i);
channel.SupportedBridges = new SensorConstants.BridgeType[]
{
SensorConstants.BridgeType.FullBridge,
SensorConstants.BridgeType.HalfBridge,
};
configModule.Channels[i] = channel;
}
}
return configModule;
}
/// <summary>
/// we can probably simplify and take common items (slice6+slice1) out of this function, but for now
/// it's mostly a copy of SLICE1.AsyncConfigure
/// </summary>
/// <param name="configAsyncInfo"></param>
protected override void AsyncConfigure(object configAsyncInfo)
{
var info = configAsyncInfo as SliceConfigServiceAsyncInfo;
SetUDPAlignOnPPS();
SetRemoveSeconds();
if ((info.StreamADCPerPacket != null) && info.StreamADCPerPacket.ContainsKey(this))
{
SetADCSamplesPerPacket(info.StreamADCPerPacket[this]);
}
//12638 DAS does not record data in recorder mode during calibration ~ 40% of time.
//for SLICE6 we call reseteventlist here, prior to configuring and NOT before arming
ResetEventListPriorToConfigure();
int progressValue = 0;
bool bReleased = true;
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.ProgramStackChannels))
{
ReconfigureAccordingToConfig();
}
PresetSampleRate();
SetVoltageRequirements();
SetPolarity();
SetArmDisableShortCheck();
try
{
Lock();
bReleased = false;
// loop thru the modules (slices) and configure the non-UART channels
var numChannels = DASInfo.Modules.Sum(mod => mod.NumberOfChannels);
var numStreamingChannels = DASInfo.Modules.Sum(mod => DFConstantsAndEnums.ModuleType.StreamOut == mod.TypeOfModule ? mod.NumberOfChannels : 0);
var rangeArray = new float[numChannels];
//var IsHalfBridgeArray = new bool[numChannels];
var bridgeModeArray = new byte[numChannels];
var BridgeResistanceArray = new ushort[numChannels];
var IsACCoupledArray = new bool[numChannels];
//18294 Implement Bridge AC / DC coupling(fw update dependent)
var bridgeACCouplingArray = new bool[numChannels];
// level trigger values
var enableLowerLevelTriggerThreshold = new bool[numChannels];
var enableUpperLevelTriggerThreshold = new bool[numChannels];
var lowerLevelTriggerThreshold = new float[numChannels];
var upperLevelTriggerThreshold = new float[numChannels];
var qualificationSamples = new int[numChannels];
var diagnosticChannels = new List<byte>();
var bModified = false;
CommonConfigureWork(diagnosticChannels, qualificationSamples, ref bReleased,
info, bridgeModeArray, IsACCoupledArray, BridgeResistanceArray,
ref bModified, rangeArray, enableUpperLevelTriggerThreshold, upperLevelTriggerThreshold,
enableLowerLevelTriggerThreshold, lowerLevelTriggerThreshold, bridgeACCouplingArray);
if (bReleased) { return; }
// report progress
progressValue = 5;
info.Progress(progressValue);
StoreConfigAttributes(info, rangeArray, ref bReleased, ref progressValue, bridgeModeArray,
IsACCoupledArray, BridgeResistanceArray, enableLowerLevelTriggerThreshold, lowerLevelTriggerThreshold,
enableUpperLevelTriggerThreshold, upperLevelTriggerThreshold, qualificationSamples, numChannels,
out var config, bridgeACCouplingArray, 0, numStreamingChannels);
progressValue = 20;
info.Progress(progressValue);
RemainingConfigWork(ref progressValue, info, diagnosticChannels, config, ref bReleased, null, null, null);
}
catch (CanceledException)
{
if (!bReleased)
{
bReleased = true;
Release();
}
info.Cancel();
}
catch (Exception ex)
{
if (!bReleased)
{
bReleased = true;
Release();
}
info.Error(ex.Message, ex);
}
finally
{
if (!bReleased)
{
bReleased = true;
Release();
}
}
info.Progress(100);
info.Success();
}
/// <summary>
/// returns true if the device is known to be streaming
/// does not query device, just returns a flag if it has been set
/// </summary>
public override bool GetIsStreaming()
{
if (null == DASArmStatus) { return false; }
//18852 Cannot use Stop streaming / (Dis)Auto Arm button if one or more DAS is idle
//can't rely on just having received invalid mode, QATS will still have a status of realtime
//when streaming, so we'll use either for now.
return DASArmStatus.ReceivedInvalidModeDuringSetup || DASArmStatus.IsInRealtime;
}
}
}