1655 lines
76 KiB
C#
1655 lines
76 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.IO.Ports;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Threading;
|
|||
|
|
using DTS.Common.Enums.DASFactory;
|
|||
|
|
using DTS.Common.Enums.Sensors;
|
|||
|
|
using DTS.Common.Interface.DASFactory;
|
|||
|
|
using DTS.Common.Interface.Connection;
|
|||
|
|
using DTS.Common.Interface.TestSetups;
|
|||
|
|
using DTS.Common.Utilities;
|
|||
|
|
using DTS.Common.Utilities.Logging;
|
|||
|
|
using DTS.Common.Utils;
|
|||
|
|
using DTS.DASLib.Command;
|
|||
|
|
using DTS.DASLib.Command.SLICE;
|
|||
|
|
using DTS.DASLib.Service.Interfaces;
|
|||
|
|
using DTS.Common.ICommunication;
|
|||
|
|
using DTS.Common.Interface.DASFactory.Download;
|
|||
|
|
using DTS.DASLib.Command.SLICE.DownloadCommands;
|
|||
|
|
using DTS.Common.Interface.StatusAndProgressBar;
|
|||
|
|
using DTS.Common.Constant.DASSpecific;
|
|||
|
|
using DTS.Common.Enums;
|
|||
|
|
using DTS.Common;
|
|||
|
|
using DTS.Common.Interface.DASFactory.Config;
|
|||
|
|
|
|||
|
|
namespace DTS.DASLib.Service
|
|||
|
|
{
|
|||
|
|
public class SLICE6AIR<T> : SLICE6_Base<T>, ITestDASOrder, IUARTDownload, IUARTDownloadActions, IAlignUDPToPPSAware
|
|||
|
|
where T : IConnection, new()
|
|||
|
|
{
|
|||
|
|
public bool AlignUDPToPPS { get; set; }
|
|||
|
|
public override bool SupportsADCSamplesPerPacket => true;
|
|||
|
|
public override bool SupportsRemoveLeapSeconds => true;
|
|||
|
|
protected override bool AdjustInputRange(AnalogInputDASChannel analog)
|
|||
|
|
{
|
|||
|
|
return analog.IEPEChannel;
|
|||
|
|
}
|
|||
|
|
protected override bool SupportsDiagnosticsMode => true;
|
|||
|
|
public override void SetIsStreamingSupported(bool supported)
|
|||
|
|
{
|
|||
|
|
IsStreamingSupported = true;
|
|||
|
|
}
|
|||
|
|
protected override void FirmwareVersionUpdated()
|
|||
|
|
{
|
|||
|
|
base.FirmwareVersionUpdated();
|
|||
|
|
if (DFConstantsAndEnums.IsSLICE6ERFirmware(FirmwareVersion))
|
|||
|
|
{
|
|||
|
|
IsEthernetRecorder = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private bool _IsEthernetRecorder = false;
|
|||
|
|
public bool IsEthernetRecorder
|
|||
|
|
{
|
|||
|
|
get => _IsEthernetRecorder;
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_IsEthernetRecorder = value;
|
|||
|
|
if (value)
|
|||
|
|
{
|
|||
|
|
SetEthernetRecorderProtocolMins();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private void SetEthernetRecorderProtocolMins()
|
|||
|
|
{
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryTiltSensorData] = byte.MaxValue;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InSliceTiltSensorADCPre] = byte.MaxValue;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordOnBoot] = byte.MaxValue;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.UDPAddressList] = SLICE6AIR.MULTIPLE_UDP_ADDRESSES_S6A_ETHERNETRECORDER;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override DASModule MakeConfigModuleFromInfoModule(InfoResult.Module infoModule)
|
|||
|
|
{
|
|||
|
|
//per LP we can make this simpler, S6A always supports 1/2,Full,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.UART == configModule.ModuleType())
|
|||
|
|
{
|
|||
|
|
var uartChannel = new UARTInputDASChannel(configModule, i);
|
|||
|
|
configModule.Channels[i] = uartChannel;
|
|||
|
|
}
|
|||
|
|
else if (DFConstantsAndEnums.ModuleType.StreamOut == configModule.ModuleType())
|
|||
|
|
{
|
|||
|
|
var streamOutChannel = new StreamOutputDASChannel(configModule, i);
|
|||
|
|
configModule.Channels[i] = streamOutChannel;
|
|||
|
|
}
|
|||
|
|
else if (DFConstantsAndEnums.ModuleType.StreamIn == configModule.ModuleType())
|
|||
|
|
{
|
|||
|
|
var streamInChannel = new StreamInputDASChannel(configModule, i);
|
|||
|
|
configModule.Channels[i] = streamInChannel;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
var channel = new AnalogInputDASChannel(configModule, i);
|
|||
|
|
|
|||
|
|
channel.SupportedBridges = new SensorConstants.BridgeType[]
|
|||
|
|
{
|
|||
|
|
SensorConstants.BridgeType.FullBridge,
|
|||
|
|
SensorConstants.BridgeType.HalfBridge, SensorConstants.BridgeType.IEPE
|
|||
|
|
};
|
|||
|
|
configModule.Channels[i] = channel;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return configModule;
|
|||
|
|
}
|
|||
|
|
private const byte DEVICE_STREAMING_ONLY = 1;
|
|||
|
|
protected override void AsyncAutoDetect(object o)
|
|||
|
|
{
|
|||
|
|
if (!(o is AutoDetectServiceAsyncInfo info))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (GetIsStreaming())
|
|||
|
|
{
|
|||
|
|
//if we are streaming avoid getting this information
|
|||
|
|
info.Success();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (null == DASInfo || null == DASInfo.Modules || 0 == DASInfo.Modules.Length
|
|||
|
|
|| null == ConfigData || 0 == ConfigData.Modules.Length)
|
|||
|
|
{
|
|||
|
|
info.Error($"no configuration on unit {SerialNumber}");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (DASInfo.Modules[0].IsProgrammable)
|
|||
|
|
{
|
|||
|
|
var channels = new List<SetStackChannelTypeConfiguration.ChannelTypes>();
|
|||
|
|
|
|||
|
|
foreach (var module in ConfigData.Modules)
|
|||
|
|
{
|
|||
|
|
foreach (var channel in module.Channels)
|
|||
|
|
{
|
|||
|
|
channels.Add(SetStackChannelTypeConfiguration.ChannelTypes.AUTO_DETECT);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var cmd = new SetStackChannelTypeConfiguration(this);
|
|||
|
|
cmd.SetValue(channels.ToArray());
|
|||
|
|
if (info.QueryConfiguration)
|
|||
|
|
{
|
|||
|
|
var query = new QueryStackSensorIDs(this);
|
|||
|
|
query.Exec();
|
|||
|
|
|
|||
|
|
var idx = 0;
|
|||
|
|
foreach (var m in ConfigData.Modules)
|
|||
|
|
{
|
|||
|
|
foreach (var c in m.Channels)
|
|||
|
|
{
|
|||
|
|
if (c is AnalogInputDASChannel)
|
|||
|
|
{
|
|||
|
|
switch (Convert.ToInt32(query.Types[idx]))
|
|||
|
|
{
|
|||
|
|
case (int)SetStackChannelTypeConfiguration.ChannelTypes.FORCE_IEPE:
|
|||
|
|
(c as AnalogInputDASChannel).IEPEChannel = true;
|
|||
|
|
break;
|
|||
|
|
case (int)SetStackChannelTypeConfiguration.ChannelTypes.FORCE_IEPE_LOW:
|
|||
|
|
(c as AnalogInputDASChannel).IEPEChannel = true;
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
(c as AnalogInputDASChannel).IEPEChannel = false;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var id = new EID(HexEncoding.ToString(query.IDs[idx]));
|
|||
|
|
if (id.IsValid() && !RunTestVariables.BypassEIDRead)
|
|||
|
|
{
|
|||
|
|
c.IDs = new EID[] { id };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
idx++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// FB15353 Is this device hardware configured for streaming only?
|
|||
|
|
var qsaDeviceStreamingOnly = new QuerySystemAttributeSLICE6AIR(this, QuerySystemAttribute.Default_IO_Timeout);
|
|||
|
|
qsaDeviceStreamingOnly.Key = AttributeTypes.SystemAttributesSLICE6AIR.S6A_DeviceStreamingOnly;
|
|||
|
|
qsaDeviceStreamingOnly.SyncExecute();
|
|||
|
|
//we made it, set results
|
|||
|
|
DASInfo.DeviceStreamingOnly = (DEVICE_STREAMING_ONLY == (byte)qsaDeviceStreamingOnly.Value);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("Problem getting Device Streaming only system attribute", ex);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
info.Success();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override double[] GetNominalRanges(SensorConstants.BridgeType bridgeType)
|
|||
|
|
{
|
|||
|
|
//FB15462 separate S6 gain limits from S6A
|
|||
|
|
switch (bridgeType)
|
|||
|
|
{
|
|||
|
|
case SensorConstants.BridgeType.IEPE:
|
|||
|
|
return WinUSBSlice.StaticDASS6AEIEPEInfo.NominalRanges;
|
|||
|
|
default:
|
|||
|
|
return WinUSBSlice.StaticDASBridgeInfo.NominalRanges;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#region protocol settings/overrides
|
|||
|
|
|
|||
|
|
private readonly Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte> SLICE6AIR_MinimumProtocols =
|
|||
|
|
new Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>();
|
|||
|
|
|
|||
|
|
protected override bool SupportsIEPECalSignal =>
|
|||
|
|
IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.IEPE);
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
private const int MIN_HW_REVISION_ETHERNET_RECORDER = 10;
|
|||
|
|
protected override void QueryHardwareRevisionPost()
|
|||
|
|
{
|
|||
|
|
if (_hardwareRevision >= MIN_HW_REVISION_ETHERNET_RECORDER)
|
|||
|
|
{
|
|||
|
|
IsEthernetRecorder = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
protected override void VerifyConfig(bool DoStrictCheck, ErrorCallback failedChallengeFunc)
|
|||
|
|
{
|
|||
|
|
if (IsEthernetRecorder)
|
|||
|
|
{
|
|||
|
|
//no verify needed
|
|||
|
|
}
|
|||
|
|
else { base.VerifyConfig(DoStrictCheck, failedChallengeFunc); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void InitMinProto()
|
|||
|
|
{
|
|||
|
|
// SLICE 6 AIR Protocol Limitations
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleAndHybridEvents] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleEvents] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArm] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmRepeatEnable] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetDefaultMIF] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FileData] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackSensors] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.TestCommunication] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackLowPowerMode] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetRealtimeSampleRate] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SLICE2_OneWireID] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareRevision] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareConfiguration] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventFaultFlags] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventArmAttempts] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryActualSampleRateImmediate] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageSysAttributes] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.DiagnosticsMode] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.LevelTrigger] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AttributeStoreBlocks] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryArmAndTriggerStatus_VoltageReadings] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MaxEvents] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmDiagnosticDelay] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelAutoArmDiagLevel] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FlashClear] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleSamplesRealtime] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseCalibrationDate] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.IgnoreShortedStartEvent] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ResetAttributeStore] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.DiangosShuntDAC] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageInsertion] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPTimestamp] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRecDelayInSecond] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryTiltSensorData] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InSliceTiltSensorADCPre] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRealtimeStream] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.UDPRealtimeStream] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ProgramStackChannels] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.IEPE] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelTypeConfiguration] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackSensors] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryClockSyncStatus] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetClockSyncConfig] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryUARTDownload] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.GetUARTSettings] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetUARTSettings] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetDSPFilterSettings] = SLICE6AIR.SET_DSP_FILTER_SETTINGS;
|
|||
|
|
//18090 Implement chapter 10 streaming while recording(in DTS format)
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordAndStreamSubSample] = SLICE6AIR.RECORD_AND_STREAM_SUBSAMPLE;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelBridgeACCouplerEnable] = SLICE6AIR.AC_COUPLER_ENABLE;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryMSP430Firmware] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
|
|||
|
|
//31747 Add-support-for-GPS-Time-leap-seconds
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RemoveLeapSeconds] = SLICE6AIR.REMOVE_LEAP_SECONDS_VER;
|
|||
|
|
//31754 expose-number-of-ADC-samples-in-UDP-packet
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ADCSamplesPerPacket] = SLICE6AIR.ADC_SAMPLES_PER_PACKET_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPDomainID] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ActiveRAM] = SLICE6AIR.MIN_PROTOCOL_VER;
|
|||
|
|
if (IsEthernetRecorder)
|
|||
|
|
{
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordOnBoot] = SLICE6AIR.RECORD_ON_BOOT_PROTOCOL_S6A_ETHERNETRECORDER;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmRecordDelay] = SLICE6AIR.AUTOARM_RECORD_DELAY_PROTOCOL_S6A_ETHERNETRECORDER;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordOnBoot] = SLICE6AIR.RECORD_ON_BOOT_PROTOCOL;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmRecordDelay] = SLICE6AIR.AUTOARM_RECORD_DELAY_PROTOCOL;
|
|||
|
|
}
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmRecordDelay] = SLICE6AIR.AUTOARM_RECORD_DELAY_PROTOCOL;
|
|||
|
|
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.UDPAlignOnPPS] = SLICE6AIR.UDPALIGNONPPS_PROTOCOL;
|
|||
|
|
MinimumProtocols = SLICE6AIR_MinimumProtocols;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
private void AsyncPrepareForArmNowOBRDDR(ArmPacket info)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var recordingMode = GetOBRDDREquivalentMode(ConfigData.Modules[0].RecordingMode, info.MaxNumberEvents);
|
|||
|
|
|
|||
|
|
var saa = new SetArmAttribute(this);
|
|||
|
|
saa.SetValue(AttributeTypes.ArmAndEventAttributes.SampleRate, ConfigData.Modules[0].SampleRateHz, true);
|
|||
|
|
saa.SyncExecute();
|
|||
|
|
|
|||
|
|
SetArmMode(recordingMode);
|
|||
|
|
|
|||
|
|
|
|||
|
|
saa = new SetArmAttribute(this);
|
|||
|
|
var postTriggerSamples = Convert.ToUInt64(ConfigData.Modules[0].PostTriggerSeconds *
|
|||
|
|
ConfigData.Modules[0].SampleRateHz);
|
|||
|
|
saa.SetValue(AttributeTypes.ArmAndEventAttributes.PostTriggerSamplesRequested, postTriggerSamples, true);
|
|||
|
|
saa.SyncExecute();
|
|||
|
|
|
|||
|
|
saa = new SetArmAttribute(this);
|
|||
|
|
var preTriggerSamples = 0UL;
|
|||
|
|
if (ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.CircularBuffer ||
|
|||
|
|
ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART ||
|
|||
|
|
ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.RAMActive ||
|
|||
|
|
ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.MultipleEventRAMActive)
|
|||
|
|
{
|
|||
|
|
preTriggerSamples =
|
|||
|
|
Convert.ToUInt64(Math.Abs(ConfigData.Modules[0].PreTriggerSeconds *
|
|||
|
|
ConfigData.Modules[0].SampleRateHz));
|
|||
|
|
}
|
|||
|
|
saa.SetValue(AttributeTypes.ArmAndEventAttributes.PreTriggerSamplesRequested, preTriggerSamples, true);
|
|||
|
|
saa.SyncExecute();
|
|||
|
|
|
|||
|
|
SetMaxEvents(info.MaxNumberEvents);
|
|||
|
|
|
|||
|
|
var ssa = new SetSystemAttributeSLICE6AIR(this);
|
|||
|
|
SetValueBasedOnProtocolVersion(ref ssa);
|
|||
|
|
ssa.SyncExecute();
|
|||
|
|
|
|||
|
|
//var ssaV = new SetSystemAttributeSLICE6DB(this);
|
|||
|
|
////input min, input max, battery min, battery max
|
|||
|
|
//var requirements = new[] { InputLowVoltage, InputHighVoltage, BatteryLowVoltage, BatteryHighVoltage };
|
|||
|
|
//ssaV.SetValue(AttributeTypes.SystemAttributesSLICE6DB.VoltageRequirements, requirements, true);
|
|||
|
|
//ssaV.SyncExecute();
|
|||
|
|
info.Success();
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log(ex);
|
|||
|
|
info.Error(ex.Message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
public override void Download(ServiceCallback callback, object userData)
|
|||
|
|
{
|
|||
|
|
if (IsEthernetRecorder)
|
|||
|
|
{
|
|||
|
|
var info = new SliceServiceAsyncInfo(callback, userData);
|
|||
|
|
LaunchAsyncWorker("Slice6A.DownloadOBRDDR", AsyncDownloadOBRDDDR, info);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
base.Download(callback, userData);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// returns true if the DAS supports DiagnosticsFactoryExcitation attribute,
|
|||
|
|
/// false otherwise
|
|||
|
|
/// <inheritdoc cref="Slice{T}"/>
|
|||
|
|
/// </summary>
|
|||
|
|
protected override bool SupportsDiagnosticsFactoryExcitation
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (IsTSRAIR()) { return false; }
|
|||
|
|
return base.SupportsDiagnosticsFactoryExcitation;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
public override bool IsSlice6Air()
|
|||
|
|
{
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
public override bool IsScheduleEventCountSupported()
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
private void AsyncDownloadOBRDDDR(object o)
|
|||
|
|
{
|
|||
|
|
var info = (SliceServiceAsyncInfo)o;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var queryEthernetEventInfo = new QueryEthernetEventInfo(this);
|
|||
|
|
queryEthernetEventInfo.EventID = WhatToDownload.EventNumber;
|
|||
|
|
queryEthernetEventInfo.SyncExecute();
|
|||
|
|
|
|||
|
|
if (0 == queryEthernetEventInfo.TotalByteCount)
|
|||
|
|
{
|
|||
|
|
var msg = $"No Ethernet Recorder data to download: {SerialNumber}";
|
|||
|
|
APILogger.Log(msg);
|
|||
|
|
info.Success();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var bytesToRead = queryEthernetEventInfo.TotalByteCount;//34844UL
|
|||
|
|
var curBytesRead = 0UL;
|
|||
|
|
while (curBytesRead < bytesToRead)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
var queryEthernetEventData = new QueryEthernetEventData(this);
|
|||
|
|
queryEthernetEventData.EventID = queryEthernetEventInfo.EventID;
|
|||
|
|
var requestSize = (bytesToRead - curBytesRead) < int.MaxValue ? (int)(bytesToRead - curBytesRead) : int.MaxValue;
|
|||
|
|
queryEthernetEventData.RequestByteCount = (uint)requestSize;
|
|||
|
|
queryEthernetEventData.StartDataOffsetBytes = curBytesRead;
|
|||
|
|
queryEthernetEventData.SyncExecute();
|
|||
|
|
var data = new byte[queryEthernetEventData.Data.Length];
|
|||
|
|
Array.Copy(queryEthernetEventData.Data, 0, data, 0, queryEthernetEventData.Data.Length);
|
|||
|
|
curBytesRead += (ulong)queryEthernetEventData.Data.Length;
|
|||
|
|
info.NewData(data);
|
|||
|
|
info.Progress(Convert.ToInt32(100D * curBytesRead / bytesToRead));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log(ex);
|
|||
|
|
info.Error(ex.Message);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
APILogger.Log($"Data successfully downloaded from {SerialNumber}");
|
|||
|
|
info.Progress(100);
|
|||
|
|
var config = GetConfigAttributes(this);
|
|||
|
|
config.SetEventDownloaded(WhatToDownload.EventNumber, 1);
|
|||
|
|
info.Success();
|
|||
|
|
}
|
|||
|
|
protected override void AsyncPrepareForArmNow(object asyncInfo)
|
|||
|
|
{
|
|||
|
|
if (!IsEthernetRecorder) { base.AsyncPrepareForArmNow(asyncInfo); }
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (!(asyncInfo is ArmPacket info)) { return; }
|
|||
|
|
|
|||
|
|
AsyncPrepareForArmNowOBRDDR(info);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// returns whether the unit supports 2V or not
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
protected override bool GetSupports2Volt()
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
/// <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;
|
|||
|
|
}
|
|||
|
|
protected override void PerformBridgeResistanceMeasurement(Common.Interface.DASFactory.Diagnostics.IDiagnosticActions[] ChannelActions, SliceServiceAsyncInfo info, ref Common.Interface.DASFactory.Diagnostics.IDiagnosticResult[] results)
|
|||
|
|
{
|
|||
|
|
//18927 Bridge resistance inaccurate due to channel config setting prior to measurement
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.ProgramStackChannels))
|
|||
|
|
{
|
|||
|
|
ReconfigureAccordingToConfig();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex) { APILogger.Log("Failed to force stack channel types", ex); }
|
|||
|
|
base.PerformBridgeResistanceMeasurement(ChannelActions, info, ref results);
|
|||
|
|
}
|
|||
|
|
#region configure overrides
|
|||
|
|
/// <summary>
|
|||
|
|
/// adjusts the requested input range to avoid certain gains if needed
|
|||
|
|
/// we are doing this for
|
|||
|
|
/// 15462 Limit SLICE 6 AIR gains as they are not functional with IEPE accel
|
|||
|
|
/// we manipulate the input range requested so we fall
|
|||
|
|
/// within acceptable gains
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="originalRange"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
protected override double AdjustInputRangeIfNeeded(double originalRange, bool bModified)
|
|||
|
|
{
|
|||
|
|
var gains = Enum.GetValues(typeof(GainCodesSLICE6IEPE)).Cast<GainCodesSLICE6IEPE>().ToList();
|
|||
|
|
gains.Sort(new GainSorterSLICE6IEPE());
|
|||
|
|
gains.Reverse();
|
|||
|
|
var lastAcceptableValue = double.NaN;
|
|||
|
|
//assume gains are in order from 1 to 1600, so find the first gain which is too restrictive and bounce back from that
|
|||
|
|
//so for instance, if someone selected a range of 700mV, we would start with G1, pass, go to G2, pass, go to G4, fail, so we would use
|
|||
|
|
//G2. Also note, while we know the min/max theoretical value foreach gain, when we request a range from the firmware we don't use that value
|
|||
|
|
//we use somewhere inbetween (the FirmwareInputRangemV) to increase the chances we get the gain we want...
|
|||
|
|
//note there are gains greater than 1600, but they are currently explicitly disabled by issue 10080
|
|||
|
|
foreach (var gain in gains)
|
|||
|
|
{
|
|||
|
|
if (GainDisabledAttribute.IsGainDisabled(gain))
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
var maxValue = MaxInputRangeAttribute.GetMaxInputRangemV(gain);
|
|||
|
|
if (originalRange < maxValue)
|
|||
|
|
{
|
|||
|
|
lastAcceptableValue = FirmwareInputRangeAttribute.GetFirmwareInputRangemV(gain);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return !double.IsNaN(lastAcceptableValue) ? lastAcceptableValue : originalRange;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// queries download information
|
|||
|
|
/// </summary>
|
|||
|
|
protected override void AsyncQueryDownload(object asyncInfo)
|
|||
|
|
{
|
|||
|
|
if (IsEthernetRecorder)
|
|||
|
|
{
|
|||
|
|
AsyncQueryDownloadDDR(asyncInfo);
|
|||
|
|
}
|
|||
|
|
else { base.AsyncQueryDownload(asyncInfo); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// handles quering download information but specifically for OBR-DDR
|
|||
|
|
/// most of it is copied from the base, but the DDR doesn't have the same
|
|||
|
|
/// amount of information available, and has some alternate info available
|
|||
|
|
/// </summary>
|
|||
|
|
private void AsyncQueryDownloadDDR(object asyncInfo)
|
|||
|
|
{
|
|||
|
|
var info = asyncInfo as QueryDownloadAsyncInfo;
|
|||
|
|
|
|||
|
|
// since we don't know exact how many XML attributes, modules or channels that's in the
|
|||
|
|
// configuration, we guess on the high end.
|
|||
|
|
// (44 per stored config + 4 + 3 per module + 3 per channel) * number of events
|
|||
|
|
// equals 44 + 4 + 30 + 90 = 168 per event
|
|||
|
|
const int StepsPerEvent = 168;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (info.EventIndex < 0) { RetrieveDASBootCount(); }
|
|||
|
|
var EventCount = new QueryTotalEventCount(this);
|
|||
|
|
EventCount.SyncExecute();
|
|||
|
|
|
|||
|
|
var config = GetConfigAttributes(this);
|
|||
|
|
|
|||
|
|
var progress = new QueryDownloadProgress(info, StepsPerEvent * EventCount.Count, 1);
|
|||
|
|
|
|||
|
|
// we'll also freshen up the cached event GUIDs
|
|||
|
|
// NOT IF WE ARE QUERYING A SPECIFIC GUID
|
|||
|
|
var eventGuids = new Guid[EventCount.Count];
|
|||
|
|
var faultFlags = new ushort[EventCount.Count];
|
|||
|
|
var faultFlagsEx = new ushort[EventCount.Count];
|
|||
|
|
var armAttempts = new byte[EventCount.Count];
|
|||
|
|
//each index in outer array belongs to event index, there are 4 extended fault ids for each event
|
|||
|
|
var extendedFaultIds = new List<uint[]>();
|
|||
|
|
var dlReport = new DownloadReport();
|
|||
|
|
|
|||
|
|
if (0 > info.EventIndex)
|
|||
|
|
{
|
|||
|
|
dlReport.Events = new DownloadReport.EventInfo[EventCount.Count];
|
|||
|
|
|
|||
|
|
var queryAutoArmError = new QuerySystemAttribute(this) { Key = AttributeTypes.SystemAttributes.AutoArmError };
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
queryAutoArmError.SyncExecute();
|
|||
|
|
AutoArmStatus = (DFConstantsAndEnums.CommandStatus)(Convert.ToInt32(queryAutoArmError.Value));
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log(ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
for (var eventIdx = 0; eventIdx < EventCount.Count; eventIdx++)
|
|||
|
|
{
|
|||
|
|
if (info.EventIndex >= 0 && eventIdx != info.EventIndex) { continue; }
|
|||
|
|
extendedFaultIds.Add(GetExtendedFaultFlags(eventIdx));
|
|||
|
|
|
|||
|
|
// Retrieved the stored configuration
|
|||
|
|
var storedConfigStr = config.RetrieveEventXMLConfig(eventIdx, progress, this); // I/O * n
|
|||
|
|
var triggerSampleNumber = 0UL;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
triggerSampleNumber = config.GetEventTriggerSampleNumber(eventIdx); // I/O
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log(ex);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// convert it from XML to object
|
|||
|
|
var storedConfig = ConfigurationData.DeserializeFromString(storedConfigStr);
|
|||
|
|
|
|||
|
|
// the object to store it all in
|
|||
|
|
var eventInfo = new DownloadReport.EventInfo();
|
|||
|
|
|
|||
|
|
// get the event level values
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
eventInfo.Description = config.GetEventDescription(eventIdx); // I/O
|
|||
|
|
if (null != ConfigData) { eventInfo.Description = ConfigData.Description; }
|
|||
|
|
}
|
|||
|
|
catch (Exception) { }
|
|||
|
|
progress.Step();
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
eventInfo.TestID = config.GetEventID(eventIdx, this).TrimEnd(new char[] { '\0' }); ; // I/O
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
eventInfo.TestID = string.Empty;
|
|||
|
|
APILogger.Log(ex);
|
|||
|
|
}
|
|||
|
|
progress.Step();
|
|||
|
|
eventInfo.EventNumber = eventIdx;
|
|||
|
|
progress.Step();
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
eventInfo.TestGUID = GetEventGuid(eventIdx);
|
|||
|
|
}
|
|||
|
|
catch (Exception) { eventInfo.TestGUID = Guid.NewGuid(); }
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
eventInfo.FaultFlags = config.GetEventFaultFlags(eventIdx);
|
|||
|
|
eventInfo.FaultFlagsEx = config.GetEventFaultFlagsEx(eventIdx);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("could not get fault flags", ex);
|
|||
|
|
}
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
eventInfo.ArmAttempts = config.GetEventArmAttempts(eventIdx);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("could not get arm attempts", ex);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
eventGuids[eventIdx] = eventInfo.TestGUID;
|
|||
|
|
faultFlags[eventIdx] = eventInfo.FaultFlags;
|
|||
|
|
faultFlagsEx[eventIdx] = eventInfo.FaultFlagsEx;
|
|||
|
|
armAttempts[eventIdx] = eventInfo.ArmAttempts;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var q = new QueryEthernetEventInfo(this);
|
|||
|
|
q.EventID = Convert.ToUInt16(eventIdx);
|
|||
|
|
q.SyncExecute();
|
|||
|
|
if (0 == q.TotalByteCount)
|
|||
|
|
{
|
|||
|
|
faultFlags[eventIdx] |= (ushort)DFConstantsAndEnums.FaultFlags.NO_DATA;
|
|||
|
|
eventInfo.FaultFlags |= (ushort)DFConstantsAndEnums.FaultFlags.NO_DATA;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("could not get EventTotalByteCount", ex);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
eventInfo.HasBeenDownloaded = config.EventHasBeenDownloaded(eventIdx, out uint flag); // I/O
|
|||
|
|
progress.Step();
|
|||
|
|
// take the module from the stored config
|
|||
|
|
var module = (DASModule)storedConfig.Modules[0];
|
|||
|
|
|
|||
|
|
//module.SampleRateHz = Convert.ToUInt32(actualSampleRate);
|
|||
|
|
//module.EmbeddedSampleRateHz = stackActualSampleRate;
|
|||
|
|
|
|||
|
|
/// <DesignNote topic="Level Trigger Configuration" author="PKXH">
|
|||
|
|
/// Amongst other things, the level trigger offset correction, if it exists, is getting applied
|
|||
|
|
/// to the module trigger sample numbers below. There shouldn't be any danger of this value being
|
|||
|
|
/// erroneously applied to outside "tweaking" since the only outside tweak should only ever happen
|
|||
|
|
/// if there was no trigger. Still I'm a little concerned that this value will still be invisibly
|
|||
|
|
/// applied to user-overridden trigger sample numbers. We could conceivably guard against this
|
|||
|
|
/// situation with an "original trigger sample number" concept, which we could then check against
|
|||
|
|
/// and not re-apply things like level trigger offset correction if the current value doesn't
|
|||
|
|
/// match it, implying it has been manually overridden.
|
|||
|
|
/// </DesignNote>
|
|||
|
|
|
|||
|
|
// now update the module with dynamic data
|
|||
|
|
module.OwningDAS = this;
|
|||
|
|
//module.NumberOfSamples = numberOfSamples;
|
|||
|
|
progress.Step();
|
|||
|
|
module.TriggerSampleNumbers = new ulong[1]; // only one so far
|
|||
|
|
//var phaseShift = GetPhaseShiftSamples(Convert.ToUInt32(1 + module.ModuleArrayIndex), Convert.ToDouble(actualSampleRate), Convert.ToUInt32(aafilter), triggerSampleNumber);
|
|||
|
|
|
|||
|
|
module.TriggerSampleNumbers[0] = triggerSampleNumber;
|
|||
|
|
eventInfo.WasTriggered = module.TriggerSampleNumbers[0] > 0;
|
|||
|
|
progress.Step();
|
|||
|
|
|
|||
|
|
|
|||
|
|
eventInfo.Modules = new DASModule[1];
|
|||
|
|
eventInfo.Modules[0] = module;
|
|||
|
|
|
|||
|
|
if (0 > info.EventIndex)
|
|||
|
|
{
|
|||
|
|
// store it in the object
|
|||
|
|
dlReport.Events[eventIdx] = eventInfo;
|
|||
|
|
}
|
|||
|
|
else { EventInfo.Events[eventIdx] = eventInfo; }
|
|||
|
|
}
|
|||
|
|
// now assigned the data to the public property
|
|||
|
|
if (0 > info.EventIndex)
|
|||
|
|
{
|
|||
|
|
SetEventInfo(dlReport);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SetEventFaultFlags(faultFlags);
|
|||
|
|
((IDownload)this)?.SetExtendedFaultFlags(extendedFaultIds.ToArray());
|
|||
|
|
SetEventGuids(eventGuids);
|
|||
|
|
SetEventArmAttemps(armAttempts);
|
|||
|
|
|
|||
|
|
info.Success();
|
|||
|
|
}
|
|||
|
|
catch (CanceledException)
|
|||
|
|
{
|
|||
|
|
info.Cancel();
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
info.Error(ex.Message, ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// the minimum version that supports TMATS interval attribute is 33 per LP
|
|||
|
|
/// http://manuscript.dts.local/f/cases/30460/S6-Air-attribute-145-interval-is-not-being-set-by-Datapro-because-of-protocol-version-41-ON-G0N5-FW
|
|||
|
|
/// </summary>
|
|||
|
|
protected override int MIN_PROTOCOL_TMATS_INTERVAL => 33;
|
|||
|
|
|
|||
|
|
void SetValueBasedOnProtocolVersion(ref SetSystemAttributeSLICE6AIR ssa)
|
|||
|
|
{
|
|||
|
|
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.UDPAddressList))
|
|||
|
|
{
|
|||
|
|
//43618 If new firmware is running, set the entire list of UDP addresses.
|
|||
|
|
ssa.SetValue(AttributeTypes.SystemAttributesSLICE6AIR.EthRecordingMcAddrList, ConfigData.UDPReceiveAddress, true);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
//43618 If old firmware is running, only set the first UDP address in the list, and notify the user.
|
|||
|
|
var firstAddress = ConfigData.UDPReceiveAddress;
|
|||
|
|
var indexOfFirstComma = ConfigData.UDPReceiveAddress.IndexOf(',');
|
|||
|
|
if (indexOfFirstComma != -1)
|
|||
|
|
{
|
|||
|
|
firstAddress = ConfigData.UDPReceiveAddress.Substring(0, indexOfFirstComma);
|
|||
|
|
}
|
|||
|
|
ssa.SetValue(AttributeTypes.SystemAttributesSLICE6AIR.EthRecordingMcAddrList, firstAddress, true);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <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();
|
|||
|
|
IncrementNumberOfTimesWritten();
|
|||
|
|
if (IsEthernetRecorder)
|
|||
|
|
{
|
|||
|
|
var ssa = new SetSystemAttributeSLICE6AIR(this);
|
|||
|
|
SetValueBasedOnProtocolVersion(ref ssa);
|
|||
|
|
ssa.SyncExecute();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
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 numUartChannels = DASInfo.Modules.Sum(mod => DFConstantsAndEnums.ModuleType.UART == mod.TypeOfModule ? mod.NumberOfChannels : 0);
|
|||
|
|
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, numUartChannels,
|
|||
|
|
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();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override ConfigAttributes GetConfigAttributes(ICommunication com)
|
|||
|
|
{
|
|||
|
|
return new SLICE6AIRConfigAttributes(com);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// SLICE6 config attributes, mostly inherits from SLICE.ConfigAttributes with some functionality removed
|
|||
|
|
/// </summary>
|
|||
|
|
protected class SLICE6AIRConfigAttributes : ConfigAttributes
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// I'm not aware of a purgeStaleData function in SLICE6/6AIR yet
|
|||
|
|
/// this may be unnecessary if the firmware is intelligent enough, and maybe this is legacy
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="das"></param>
|
|||
|
|
public override void PurgeStaleData(IDASCommunication das)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public SLICE6AIRConfigAttributes(ICommunication _com) : base(_com)
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#region CONFIG_XML
|
|||
|
|
|
|||
|
|
private readonly object _storeXMLConfigLock = new object();
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// SLICE6 stores the xml in flash using SetFileData. We compress the XML string, write the header,
|
|||
|
|
/// then write data 400 bytes at a time. For the header, we first write XML_STORE_MAGIC_BYTES followed
|
|||
|
|
/// by the length of the compressed XML in bytes.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="data"></param>
|
|||
|
|
/// <param name="info"></param>
|
|||
|
|
/// <param name="ProgressSteps"></param>
|
|||
|
|
public override void StoreXMLConfig(string data, FileStore fileStore)
|
|||
|
|
{
|
|||
|
|
lock (_storeXMLConfigLock)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrEmpty(data))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
// since this might contain multi byte characters, we need to convert it to a byte array first
|
|||
|
|
|
|||
|
|
var ByteArrayData = GetCompressedBytes(GetBytes(fileStore, data));
|
|||
|
|
|
|||
|
|
var fileid = (ushort)fileStore; //EventConfig ? Convert.ToUInt16(1) : Convert.ToUInt16(0);
|
|||
|
|
//Store Header - magic bytes and data length
|
|||
|
|
//Store Magic bytes
|
|||
|
|
var sfd = new SetFileData(com, 600000);
|
|||
|
|
sfd.StartByteCount = 0;
|
|||
|
|
sfd.FileID = fileid;
|
|||
|
|
sfd.Data = Constants.XML_STORE_MAGIC_BYTES;
|
|||
|
|
sfd.SyncExecute();
|
|||
|
|
|
|||
|
|
//Store Header - data length
|
|||
|
|
sfd.StartByteCount = (Constants.XML_HEADER_LENGTH / 2);
|
|||
|
|
sfd.FileID = fileid;
|
|||
|
|
sfd.Data = BitConverter.GetBytes((uint)ByteArrayData.Length);
|
|||
|
|
sfd.SyncExecute();
|
|||
|
|
|
|||
|
|
//purposely corrupt for testing purposes
|
|||
|
|
//if (EventConfig)
|
|||
|
|
//{
|
|||
|
|
// System.Random r = new Random(DateTime.Now.Second);
|
|||
|
|
// for (int i = 0; i < 100; i++)
|
|||
|
|
// {
|
|||
|
|
// int position = r.Next(0, ByteArrayData.Length - 1);
|
|||
|
|
// ByteArrayData[position] = Convert.ToByte(r.Next(0, 255));
|
|||
|
|
// }
|
|||
|
|
//}
|
|||
|
|
//Store Data
|
|||
|
|
for (uint i = 0; i < ByteArrayData.Length; i += (uint)sfd.MaximumFileStreamBytes)
|
|||
|
|
{
|
|||
|
|
long array_size = sfd.MaximumFileStreamBytes;
|
|||
|
|
if ((i + sfd.MaximumFileStreamBytes) > ByteArrayData.Length)
|
|||
|
|
{
|
|||
|
|
array_size = ByteArrayData.Length - i;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var dataToSend = new byte[array_size];
|
|||
|
|
Array.Copy(ByteArrayData, i, dataToSend, 0, array_size);
|
|||
|
|
sfd.Data = dataToSend;
|
|||
|
|
sfd.FileID = fileid;
|
|||
|
|
sfd.StartByteCount = i + Constants.XML_HEADER_LENGTH;
|
|||
|
|
sfd.SyncExecute();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ((FileStore.Diagnostic == fileStore) || (FileStore.Event == fileStore))
|
|||
|
|
{
|
|||
|
|
StoreXmlConfigPC(data);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// We retrieve the xml from SLICE 2 flash using QueryFileData. We read the header, then read data 400
|
|||
|
|
/// bytes at a time. For the header, we first read XML_STORE_MAGIC_BYTES followed by the length of the
|
|||
|
|
/// compressed XML in bytes. We then unzip the data and return the XML string.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public override string RetrieveXMLConfig(FileStore fileStore, IDASCommunication das)
|
|||
|
|
{
|
|||
|
|
lock (_storeXMLConfigLock)
|
|||
|
|
{
|
|||
|
|
var WholeStr = "";
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var allBytes = new List<byte>();
|
|||
|
|
allBytes.Clear();
|
|||
|
|
|
|||
|
|
//Get Header - magic bytes and data length
|
|||
|
|
//Get Magic bytes
|
|||
|
|
var qfd = new QueryFileData(com, 600000);
|
|||
|
|
var fileid = (ushort)fileStore;
|
|||
|
|
qfd.FileID = fileid;
|
|||
|
|
qfd.StartByteCount = 0;
|
|||
|
|
qfd.EndByteCount = (Constants.XML_HEADER_LENGTH / 2) - 1;
|
|||
|
|
if (das.GetIsStreaming())
|
|||
|
|
{
|
|||
|
|
//this is a big assumption here, when das is streaming we can't query it from the unit
|
|||
|
|
//but we might be able to from the pc ...
|
|||
|
|
//15949 S6A when streaming does a whole bunch of unnecessary queries
|
|||
|
|
if (FileStore.UserAttributes != fileStore)
|
|||
|
|
{
|
|||
|
|
//event config falls back to regular config, regular config falls back to pc file
|
|||
|
|
WholeStr = RetrieveXmlConfigPC();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
qfd.SyncExecute();
|
|||
|
|
if (qfd.Data.Length < 4)
|
|||
|
|
{
|
|||
|
|
return "";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (qfd.Data[0] == 0xFF && qfd.Data[1] == 0xFF && qfd.Data[2] == 0xFF &&
|
|||
|
|
qfd.Data[3] == 0xFF)
|
|||
|
|
{
|
|||
|
|
return "";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (BitConverter.ToUInt32(qfd.Data, 0) != BitConverter.ToUInt32(Constants.XML_STORE_MAGIC_BYTES, 0))
|
|||
|
|
{
|
|||
|
|
throw new InvalidDataException("Magic bytes not found");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//Get data length
|
|||
|
|
qfd.FileID = fileid;
|
|||
|
|
qfd.StartByteCount = (Constants.XML_HEADER_LENGTH / 2); //account for magic bytes
|
|||
|
|
qfd.EndByteCount = Constants.XML_HEADER_LENGTH - 1;
|
|||
|
|
qfd.SyncExecute();
|
|||
|
|
var ByteArrayDataLength = BitConverter.ToUInt32(qfd.Data, 0);
|
|||
|
|
if (Math.Pow(2, 21) < ByteArrayDataLength)
|
|||
|
|
{
|
|||
|
|
throw new InvalidDataException("data length is greater than store size");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//Get Data
|
|||
|
|
for (uint i = 0; i < ByteArrayDataLength; i += (uint)qfd.MaximumFileStreamBytes)
|
|||
|
|
{
|
|||
|
|
var array_size = (uint)qfd.MaximumFileStreamBytes;
|
|||
|
|
if ((i + qfd.MaximumFileStreamBytes) > ByteArrayDataLength)
|
|||
|
|
{
|
|||
|
|
array_size = ByteArrayDataLength - i;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
qfd.StartByteCount = Constants.XML_HEADER_LENGTH + i;
|
|||
|
|
qfd.EndByteCount = Constants.XML_HEADER_LENGTH - 1 + (i + array_size);
|
|||
|
|
qfd.FileID = fileid;
|
|||
|
|
qfd.SyncExecute();
|
|||
|
|
allBytes.InsertRange((int)i, qfd.Data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (allBytes.Count < 1)
|
|||
|
|
{
|
|||
|
|
// "Slice.RetrieveAttributes: Attributes are empty"
|
|||
|
|
throw new Exception("Attributes are empty");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Decopress data
|
|||
|
|
WholeStr = GetDecompressedString(allBytes.ToArray(), fileStore);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("failed to retrieve xml config - EventConfig: ", fileStore.ToString(), " error: ",
|
|||
|
|
ex);
|
|||
|
|
//if (!EventConfig)
|
|||
|
|
if (FileStore.UserAttributes != fileStore)
|
|||
|
|
{
|
|||
|
|
//event config falls back to regular config, regular config falls back to pc file
|
|||
|
|
WholeStr = RetrieveXmlConfigPC();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
APILogger.ConfLog(com.SerialNumber, "XML Config\n", Utils.PrettyPrint(WholeStr));
|
|||
|
|
}
|
|||
|
|
catch (Exception)
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return WholeStr;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void StoreXmlConfigPC(string data)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
const string dasConfigs = "DASConfigs";
|
|||
|
|
var fileName =
|
|||
|
|
Path.Combine(
|
|||
|
|
Path.Combine(
|
|||
|
|
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
|
|||
|
|
dasConfigs), string.Format("{0}.xml", com.SerialNumber));
|
|||
|
|
if (File.Exists(fileName))
|
|||
|
|
{
|
|||
|
|
File.Delete(fileName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
using (var file = File.CreateText(fileName))
|
|||
|
|
{
|
|||
|
|
file.Write(data);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log(ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Retrieve the XML string that was split and stored in the Arm attributes
|
|||
|
|
/// note that SLICE2 is apparently not going to store separate event configs,
|
|||
|
|
/// so we just grab the same one off the pc again
|
|||
|
|
/// [this is a bad idea as the event could be from earlier and the system config could have been
|
|||
|
|
/// changed after the use ran the test, and then reconfigured but wants to download the old test]
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="eventNum">The event number to get it from</param>
|
|||
|
|
/// <param name="progress"></param>
|
|||
|
|
/// <returns>The combined XML string</returns>
|
|||
|
|
public override string RetrieveEventXMLConfig(int eventNum, QueryDownloadProgress progress,
|
|||
|
|
IDASCommunication das)
|
|||
|
|
{
|
|||
|
|
lock (_storeXMLConfigLock)
|
|||
|
|
{
|
|||
|
|
var s = string.Empty;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
s = RetrieveXMLConfig(FileStore.Event, das);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("failed to retrieve event xml config for event ", eventNum, ex);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//fall back to whatever is on the live config
|
|||
|
|
if (string.IsNullOrEmpty(s))
|
|||
|
|
{
|
|||
|
|
APILogger.Log("failed to retrieve event xml config (it was empty) for event ", eventNum);
|
|||
|
|
s = RetrieveXMLConfig(FileStore.Diagnostic, das);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
protected override void SetArmAttribute(AttributeTypes.ArmAndEventAttributes key, DFConstantsAndEnums.RecordingMode value)
|
|||
|
|
{
|
|||
|
|
var mode = value;
|
|||
|
|
if (IsEthernetRecorder)
|
|||
|
|
{
|
|||
|
|
mode = GetOBRDDREquivalentMode(value, 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
base.SetArmAttribute(key, mode);
|
|||
|
|
}
|
|||
|
|
#region IClockSyncActions
|
|||
|
|
protected override void AsyncGetClockSyncStatus(object asyncInfo)
|
|||
|
|
{
|
|||
|
|
//S6A has a command for both profile and status fetch
|
|||
|
|
if (!(asyncInfo is GetClockSyncStatusPacket packet)) { return; }
|
|||
|
|
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.QueryClockSyncStatus))
|
|||
|
|
{
|
|||
|
|
packet.Info.Error("Get clock sync status not supported");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
var info = packet.Info;
|
|||
|
|
var bLocked = false;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
Lock();
|
|||
|
|
bLocked = true;
|
|||
|
|
var status = new QueryClockSyncStatus(this);
|
|||
|
|
status.SyncExecute();
|
|||
|
|
DASClockSyncProfile = status.ClockSyncProfile;
|
|||
|
|
DASClockSyncStatus = status.InputSyncStatus;
|
|||
|
|
DoRTCInUTCCheck();
|
|||
|
|
bLocked = false;
|
|||
|
|
Release();
|
|||
|
|
info.Success();
|
|||
|
|
}
|
|||
|
|
catch (CanceledException)
|
|||
|
|
{
|
|||
|
|
if (bLocked) { bLocked = false; Release(); }
|
|||
|
|
info.Cancel();
|
|||
|
|
}
|
|||
|
|
catch (CommandException ce)
|
|||
|
|
{
|
|||
|
|
if (bLocked) { Release(); bLocked = false; }
|
|||
|
|
straightFailures++;
|
|||
|
|
if (straightFailures > PERMITTED_FAILURES)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("GetClockSyncStatus error - has failed ", straightFailures, " times, giving up", ce);
|
|||
|
|
info.Error(ce.Message, ce);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (info.userData is ServiceBase.CallbackData cbData)
|
|||
|
|
{
|
|||
|
|
cbData.Target.DASClockSyncStatus = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
info.Success();
|
|||
|
|
APILogger.Log("GetClockSyncStatus error", ce);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
if (bLocked) { bLocked = false; Release(); }
|
|||
|
|
info.Error(ex.Message, ex);
|
|||
|
|
}
|
|||
|
|
finally { if (bLocked) { Release(); } }
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
public bool DownloadEthernetData { get; set; } = false;
|
|||
|
|
#region IUARTDownload
|
|||
|
|
public uint BaudRate { get; private set; }
|
|||
|
|
public uint DataBits { get; private set; }
|
|||
|
|
public StopBits StopBits { get; private set; }
|
|||
|
|
public Parity Parity { get; private set; }
|
|||
|
|
public Handshake FlowControl { get; private set; }
|
|||
|
|
public UartDataFormat DataFormat { get; private set; }
|
|||
|
|
public IUARTDownloadRequest WhatUARTToDownload { get; set; }
|
|||
|
|
public void SetWhatUARTToDownload(IUARTDownloadRequest request, bool bSetInDb = true)
|
|||
|
|
{
|
|||
|
|
UARTDownloadRequest.SetWhatToDownload(this, request, bSetInDb);
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region IUARTDownloadActions
|
|||
|
|
|
|||
|
|
public void UARTDownload(ServiceCallback callback, object userData)
|
|||
|
|
{
|
|||
|
|
var state = new SliceUARTDownloadState(callback, userData, WhatUARTToDownload);
|
|||
|
|
if (null == WhatUARTToDownload)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("UART download - what to download is null");
|
|||
|
|
state.Success();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
APILogger.Log("Starting UART Download ", WhatUARTToDownload.StartTimestamp,
|
|||
|
|
WhatUARTToDownload.EndTimestamp);
|
|||
|
|
|
|||
|
|
ulong totalDownloaded = 0, needed = WhatUARTToDownload.TotalByteCount;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
while (totalDownloaded < needed)
|
|||
|
|
{
|
|||
|
|
var getData = new QueryUARTEventData(this)
|
|||
|
|
{
|
|||
|
|
EventNumber = WhatUARTToDownload.EventNumber,
|
|||
|
|
LogCommands = false,
|
|||
|
|
RequestOffsetByteCount = totalDownloaded,
|
|||
|
|
RequestByteCount = needed - totalDownloaded < uint.MaxValue
|
|||
|
|
? (uint)(needed - totalDownloaded)
|
|||
|
|
: uint.MaxValue
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
getData.SyncExecute();
|
|||
|
|
if (null == getData.PayloadData)
|
|||
|
|
{
|
|||
|
|
Thread.Sleep(10);
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
state.NewData(new ServiceCallbackData.UARTNewData { DataOffset = getData.RequestOffsetByteCount, UARTData = getData.PayloadData });
|
|||
|
|
|
|||
|
|
var ratio = 100D * totalDownloaded / needed;
|
|||
|
|
if (ratio < 0)
|
|||
|
|
{
|
|||
|
|
ratio = 0;
|
|||
|
|
}
|
|||
|
|
else if (ratio > 100)
|
|||
|
|
{
|
|||
|
|
ratio = 100D;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
state.Progress(Convert.ToInt32(ratio));
|
|||
|
|
totalDownloaded += getData.PayloadByteCount;
|
|||
|
|
}
|
|||
|
|
state.Success();
|
|||
|
|
}
|
|||
|
|
catch (CanceledException)
|
|||
|
|
{
|
|||
|
|
state.Cancel();
|
|||
|
|
}
|
|||
|
|
catch (Exception e)
|
|||
|
|
{
|
|||
|
|
APILogger.LogException(e);
|
|||
|
|
state.Error(e.Message, e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Retrieve UART info about available events to download
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="callback">The function to call with information</param>
|
|||
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|||
|
|
void IUARTDownloadActions.QueryUARTDownload(ServiceCallback callback, object userData, int eventIndex, TDASServiceSetupInfo setupInfo)
|
|||
|
|
{
|
|||
|
|
var info = new QueryDownloadAsyncInfo(callback, userData, eventIndex);
|
|||
|
|
LaunchAsyncWorker("Slice.QueryUARTDownload", AsyncQueryUARTDownload, info);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected virtual void AsyncQueryUARTDownload(object asyncInfo)
|
|||
|
|
{
|
|||
|
|
if (!(asyncInfo is QueryDownloadAsyncInfo info)) { return; }
|
|||
|
|
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.QueryUARTDownload))
|
|||
|
|
{
|
|||
|
|
info.Error("Query UART download is not supported");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
var bLocked = false;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
Lock();
|
|||
|
|
bLocked = true;
|
|||
|
|
var status = new QueryUARTEventInfo(this) { EventNumber = (ushort)info.EventIndex };
|
|||
|
|
status.SyncExecute();
|
|||
|
|
|
|||
|
|
|
|||
|
|
bLocked = false;
|
|||
|
|
Release();
|
|||
|
|
info.Success();
|
|||
|
|
}
|
|||
|
|
catch (CanceledException)
|
|||
|
|
{
|
|||
|
|
if (bLocked) { bLocked = false; Release(); }
|
|||
|
|
info.Cancel();
|
|||
|
|
}
|
|||
|
|
catch (CommandException ce)
|
|||
|
|
{
|
|||
|
|
if (bLocked) { Release(); bLocked = false; }
|
|||
|
|
straightFailures++;
|
|||
|
|
if (straightFailures > PERMITTED_FAILURES)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("QueryUARTDownload error - has failed ", straightFailures, " times, giving up", ce);
|
|||
|
|
info.Error(ce.Message, ce);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (info.userData is ServiceBase.CallbackData cbData)
|
|||
|
|
{
|
|||
|
|
//cbData.Target.DASClockSyncStatus = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
info.Success();
|
|||
|
|
APILogger.Log("QueryUARTDownload error", ce);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
if (bLocked) { bLocked = false; Release(); }
|
|||
|
|
info.Error(ex.Message, ex);
|
|||
|
|
}
|
|||
|
|
finally { if (bLocked) { Release(); } }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void IUARTDownloadActions.GetUARTSettings(ServiceCallback callback, object userData)
|
|||
|
|
{
|
|||
|
|
var info = new SliceServiceAsyncInfo(callback, userData);
|
|||
|
|
LaunchAsyncWorker("Slice.GetUARTSettings", AsyncGetUARTSettings, info);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected virtual void AsyncGetUARTSettings(object asyncInfo)
|
|||
|
|
{
|
|||
|
|
if (!(asyncInfo is SliceServiceAsyncInfo info)) { return; }
|
|||
|
|
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.GetUARTSettings))
|
|||
|
|
{
|
|||
|
|
info.Error("Get UART settings is not supported");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
var bLocked = false;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
Lock();
|
|||
|
|
bLocked = true;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var qsaUARTSettings = new QuerySystemAttributeSLICE6AIR(this, QuerySystemAttribute.Default_IO_Timeout);
|
|||
|
|
qsaUARTSettings.Key = AttributeTypes.SystemAttributesSLICE6AIR.S6A_GpsCanUARTSettings;
|
|||
|
|
qsaUARTSettings.SyncExecute();
|
|||
|
|
//we made it, set results
|
|||
|
|
var uartSettings = (uint[])qsaUARTSettings.Value;
|
|||
|
|
|
|||
|
|
BaudRate = uartSettings[0];
|
|||
|
|
DataBits = uartSettings[1];
|
|||
|
|
StopBits = (StopBits)uartSettings[2];
|
|||
|
|
Parity = (Parity)uartSettings[3];
|
|||
|
|
FlowControl = (Handshake)uartSettings[4];
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("Problem getting UART settings", ex);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bLocked = false;
|
|||
|
|
Release();
|
|||
|
|
info.Success();
|
|||
|
|
}
|
|||
|
|
catch (CanceledException)
|
|||
|
|
{
|
|||
|
|
if (bLocked)
|
|||
|
|
{
|
|||
|
|
bLocked = false;
|
|||
|
|
Release();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
info.Cancel();
|
|||
|
|
}
|
|||
|
|
catch (CommandException ce)
|
|||
|
|
{
|
|||
|
|
if (bLocked)
|
|||
|
|
{
|
|||
|
|
Release();
|
|||
|
|
bLocked = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
straightFailures++;
|
|||
|
|
if (straightFailures > PERMITTED_FAILURES)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("GetUARTSettings error - has failed ", straightFailures, " times, giving up", ce);
|
|||
|
|
info.Error(ce.Message, ce);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
info.Success();
|
|||
|
|
APILogger.Log("GetUARTSettings error", ce);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
if (bLocked)
|
|||
|
|
{
|
|||
|
|
bLocked = false;
|
|||
|
|
Release();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
info.Error(ex.Message, ex);
|
|||
|
|
}
|
|||
|
|
finally
|
|||
|
|
{
|
|||
|
|
if (bLocked)
|
|||
|
|
{
|
|||
|
|
Release();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void IUARTDownloadActions.SetUARTSettings(ServiceCallback callback, object userData, uint baudRate, uint dataBits, uint stopBits, uint parity, uint flowControl)
|
|||
|
|
{
|
|||
|
|
var info = new SetUARTSettingsAsyncInfo(callback, userData, baudRate, dataBits, stopBits, parity, flowControl);
|
|||
|
|
LaunchAsyncWorker("Slice.SetUARTSettings", AsyncSetUARTSettings, info);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected virtual void AsyncSetUARTSettings(object asyncInfo)
|
|||
|
|
{
|
|||
|
|
if (!(asyncInfo is SetUARTSettingsAsyncInfo info)) { return; }
|
|||
|
|
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.SetUARTSettings))
|
|||
|
|
{
|
|||
|
|
info.Error("Set UART settings is not supported");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
var bLocked = false;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
Lock();
|
|||
|
|
bLocked = true;
|
|||
|
|
var value = new uint[] { info.BaudRate, info.DataBits, info.StopBits, info.Parity, info.FlowControl };
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var ssaUARTSettings =
|
|||
|
|
new SetSystemAttributeSLICE6AIR(this, SetSystemAttribute.Default_IO_Timeout);
|
|||
|
|
ssaUARTSettings.SetValue(AttributeTypes.SystemAttributesSLICE6AIR.S6A_GpsCanUARTSettings,
|
|||
|
|
value, true);
|
|||
|
|
ssaUARTSettings.SyncExecute();
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("Problem setting UART settings", ex);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bLocked = false;
|
|||
|
|
Release();
|
|||
|
|
info.Success();
|
|||
|
|
}
|
|||
|
|
catch (CanceledException)
|
|||
|
|
{
|
|||
|
|
if (bLocked)
|
|||
|
|
{
|
|||
|
|
bLocked = false;
|
|||
|
|
Release();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
info.Cancel();
|
|||
|
|
}
|
|||
|
|
catch (CommandException ce)
|
|||
|
|
{
|
|||
|
|
if (bLocked)
|
|||
|
|
{
|
|||
|
|
Release();
|
|||
|
|
bLocked = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
straightFailures++;
|
|||
|
|
if (straightFailures > PERMITTED_FAILURES)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("SetUARTSettings error - has failed ", straightFailures, " times, giving up", ce);
|
|||
|
|
info.Error(ce.Message, ce);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
info.Success();
|
|||
|
|
APILogger.Log("SetUARTSettings error", ce);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
if (bLocked)
|
|||
|
|
{
|
|||
|
|
bLocked = false;
|
|||
|
|
Release();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
info.Error(ex.Message, ex);
|
|||
|
|
}
|
|||
|
|
finally
|
|||
|
|
{
|
|||
|
|
if (bLocked)
|
|||
|
|
{
|
|||
|
|
Release();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
private DFConstantsAndEnums.RecordingMode GetOBRDDREquivalentMode(DFConstantsAndEnums.RecordingMode input,
|
|||
|
|
int numEvents)
|
|||
|
|
{
|
|||
|
|
switch (input)
|
|||
|
|
{
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.InvalidArmMode:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.ImmediateMode:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.HighPowerRecorderMode:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.LowPowerRecorderMode:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.ContinuousRecorderMode:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.AutoActiveMode:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.AerospaceWithMotion:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.S6A_DeviceStreamingOnly:
|
|||
|
|
APILogger.Log($"Invalid recording mode for OBR-DDR {input}");
|
|||
|
|
return input;
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.AutoCircularBufferMode:
|
|||
|
|
return DFConstantsAndEnums.RecordingMode.MultiEthernetUDPRecordingCircularMode;
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.AutoRecorderMode:
|
|||
|
|
return DFConstantsAndEnums.RecordingMode.MultiEthernetUDPRecordingRecorderMode;
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.CircularBuffer:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.a16_CircularBufferAndStreamSubSampleMode:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.MultipleEventRAMActive:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.RAMActive:
|
|||
|
|
return numEvents > 1
|
|||
|
|
? DFConstantsAndEnums.RecordingMode.MultiEthernetUDPRecordingCircularMode
|
|||
|
|
: DFConstantsAndEnums.RecordingMode.EthernetUDPRecordingCircularMode;
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.RecorderMode:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.a14_NormalRecorderAndStreamSubSampleMode:
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.RecorderModePlusUART:
|
|||
|
|
return numEvents > 1
|
|||
|
|
? DFConstantsAndEnums.RecordingMode.MultiEthernetUDPRecordingRecorderMode
|
|||
|
|
: DFConstantsAndEnums.RecordingMode.EthernetUDPRecordingRecorderMode;
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.HybridRecorderMode:
|
|||
|
|
return numEvents > 1
|
|||
|
|
? DFConstantsAndEnums.RecordingMode.MultiEthernetHybridRecorderMode
|
|||
|
|
: DFConstantsAndEnums.RecordingMode.EthernetHybridRecorderMode;
|
|||
|
|
case DFConstantsAndEnums.RecordingMode.MultiHybridRecorderMode:
|
|||
|
|
return DFConstantsAndEnums.RecordingMode.MultiEthernetHybridRecorderMode;
|
|||
|
|
default:
|
|||
|
|
APILogger.Log($"possible invalid recording mode for OBR-DDR {input}");
|
|||
|
|
return input;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// http://manuscript.dts.local/f/cases/16493/How-to-bypass-adjustable-HW-filter-for-Data-Collection-on-S6A
|
|||
|
|
// Loc, 11:44 AM S6A should have limit to 50K only.Anything< 50K will be with SCF. 50K and higher will be in by-pass mode.
|
|||
|
|
private uint _maxAAFilterRateHz = 0U;
|
|||
|
|
protected override uint MaxAAFilterRateHz
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (_maxAAFilterRateHz == 0)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
// FW added bandwidth to the MIF for S6A, lets use that.
|
|||
|
|
var qsa = new QuerySystemAttribute_BridgeSlice6(this)
|
|||
|
|
{
|
|||
|
|
Key = AttributeTypes.SystemAttributes_BridgeSlice6.Hardware_Analog_Bandwidth,
|
|||
|
|
DeviceID = 0x01 //per Loc we can always use 1 with slice6
|
|||
|
|
};
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
qsa.SyncExecute();
|
|||
|
|
_maxAAFilterRateHz = (uint)((float)qsa.Value * 1000F);
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
// Something went wrong. Set to default
|
|||
|
|
// This is the max SCF for the current S6A device family as of 9/28/2020
|
|||
|
|
_maxAAFilterRateHz = SLICE6AIR.MaxAAFilterRateHz;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return _maxAAFilterRateHz;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
protected override uint MaxSampleRateHz => IsEthernetRecorder ? SLICE6AIR.MaxSampleRateHz_OBRDDR : SLICE6AIR.MaxSampleRateHz;
|
|||
|
|
}
|
|||
|
|
}
|