209 lines
11 KiB
C#
209 lines
11 KiB
C#
using System;
|
|
using DTS.Common.Constant;
|
|
using DTS.Common.Enums;
|
|
using DTS.Common.Enums.Sensors;
|
|
|
|
namespace DTS.Serialization.TDAS
|
|
{
|
|
public class TLFBin
|
|
{
|
|
public double AcquisitionRate { get; set; }
|
|
public int PreTriggerDataPoints { get; set; }
|
|
public int PostTriggerDataPoints { get; set; }
|
|
public int PreZeroLevel { get; set; }
|
|
public int PreCalLevel { get; set; }
|
|
public double SignalToNoiseRatio { get; set; }
|
|
public int PostZeroLevel { get; set; }
|
|
public int PostCalLevel { get; set; }
|
|
public double SuperSampleRate { get; set; }
|
|
|
|
public TLFBin(Test.Module.Channel channel, double superSampleRate)
|
|
{
|
|
SuperSampleRate = superSampleRate;
|
|
var aic = channel as Test.Module.AnalogInputChannel;
|
|
AcquisitionRate = aic.ParentModule.SampleRateHz;
|
|
var rate = Convert.ToInt32(Math.Ceiling(superSampleRate / AcquisitionRate));
|
|
PreTriggerDataPoints = Convert.ToInt32(rate * ((long)aic.ParentModule.TriggerSampleNumbers[0] - (long)aic.ParentModule.StartRecordSampleNumber));
|
|
PostTriggerDataPoints = Convert.ToInt32(rate * ((long)aic.ParentModule.NumberOfSamples - ((long)aic.ParentModule.TriggerSampleNumbers[0] - (long)aic.ParentModule.StartRecordSampleNumber)));
|
|
PreZeroLevel = Convert.ToInt32(aic.PreTestZeroLevelAdc);
|
|
PreCalLevel = Convert.ToInt32(.7D * short.MaxValue);//we could put in a constant value, but
|
|
//this makes it clear where the value is coming from
|
|
|
|
|
|
// Noise as a % of full scale is actually std dev noise as percent of full scale?
|
|
// so by dividing by the full scale (which is in ADC to avoid confusion) we should
|
|
// have std dev noise back, we don't infact have a precal value in slice, so
|
|
// maybe using 80% of the full range will give us something reasonable
|
|
// I used the min value since the equation producing noise as a percent of full scale
|
|
// is using 32768, which is actually - short.min;
|
|
var stddev = aic.NoiseAsPercentageOfFullScale / (-1D) * short.MinValue;
|
|
stddev /= 100D;
|
|
if (0 == stddev) { SignalToNoiseRatio = 0D; }
|
|
else
|
|
{
|
|
SignalToNoiseRatio = 20D * Math.Log10(-.8D * short.MinValue / stddev);
|
|
}
|
|
|
|
//@TODO - this information isn't currently available
|
|
//PostZeroLevel = Convert.ToInt32(aic.PreTestZeroLevelAdc);
|
|
PostZeroLevel = 0;
|
|
PostCalLevel = 0;
|
|
|
|
var excitationVoltage = 5D;
|
|
if ((!aic.IsSquibChannel) && (aic.Bridge != SensorConstants.BridgeType.DigitalInput))
|
|
{
|
|
try
|
|
{
|
|
excitationVoltage = aic.FactoryExcitationVoltage;
|
|
}
|
|
catch (Exception) { excitationVoltage = aic.MeasuredExcitationVoltage; }
|
|
}
|
|
//14251 - TDC export does not respect viewer data modifications for multiply
|
|
//ScaleFactorEU *= aic.Data.Multiplier;
|
|
}
|
|
public void Serialize(System.IO.BinaryWriter bw, Test.Module.Channel channel)
|
|
{
|
|
var aic = (Test.Module.AnalogInputChannel)channel;
|
|
var scaler = SliceRaw.File.Reader.GetDataScaler(aic);
|
|
|
|
//147662,112211
|
|
var rate = Convert.ToInt32(Math.Ceiling(SuperSampleRate / AcquisitionRate));
|
|
bw.Write(BitConverter.GetBytes(SuperSampleRate), 0, 8);
|
|
bw.Write(BitConverter.GetBytes(PreTriggerDataPoints), 0, 4);
|
|
bw.Write(BitConverter.GetBytes(PostTriggerDataPoints), 0, 4);
|
|
bw.Write(BitConverter.GetBytes(PreZeroLevel), 0, 4);
|
|
bw.Write(BitConverter.GetBytes(PreCalLevel), 0, 4);
|
|
bw.Write(BitConverter.GetBytes(SignalToNoiseRatio), 0, 8);
|
|
bw.Write(BitConverter.GetBytes(PostZeroLevel), 0, 4);
|
|
bw.Write(BitConverter.GetBytes(PostCalLevel), 0, 4);
|
|
bw.Write(BitConverter.GetBytes(Convert.ToInt32(scaler.GetDataZeroLevelADC())), 0, 4);
|
|
bw.Write(BitConverter.GetBytes(scaler.GetScaleFactorMv()), 0, 8);
|
|
if (!aic.LinearizationFormula.IsValid())
|
|
{
|
|
bw.Write(BitConverter.GetBytes(scaler.GetAdcToEuScalingFactor()), 0, 8);
|
|
}
|
|
else
|
|
{
|
|
bw.Write(BitConverter.GetBytes(aic.SensorCapacity / (ushort.MaxValue / 2.0)), 0, 8);
|
|
}
|
|
if (((Test.Module.AnalogInputChannel)channel).Bridge == SensorConstants.BridgeType.DigitalInput)
|
|
{
|
|
double breakPoint = DigitalInputs.ConstantCurrentBreakPoint;
|
|
if (aic.DigitalMode == DigitalInputModes.THL || aic.DigitalMode == DigitalInputModes.TLH)
|
|
{
|
|
breakPoint = DigitalInputs.VoltageInputBreakPoint;
|
|
}
|
|
|
|
for (ulong i = 0; i < channel.PersistentChannelInfo.NumberOfSamples; i++)
|
|
{
|
|
for (var step = 0; step < rate; step++)
|
|
{
|
|
var adc = channel.PersistentChannelInfo[i];
|
|
var increment = 0D;
|
|
if ((i + 1) < channel.PersistentChannelInfo.NumberOfSamples)
|
|
{
|
|
increment = (channel.PersistentChannelInfo[i + 1] - adc) / rate;
|
|
}
|
|
else
|
|
{
|
|
increment = (adc - channel.PersistentChannelInfo[i - 1]) / rate;
|
|
}
|
|
if ((adc + increment * step) > breakPoint)
|
|
{
|
|
switch (aic.DigitalMode)
|
|
{
|
|
case DigitalInputModes.CCNC:
|
|
bw.Write(BitConverter.GetBytes((short)aic.DigitalMultiplier.ActiveValue), 0, 2);
|
|
break;
|
|
case DigitalInputModes.CCNO:
|
|
bw.Write(BitConverter.GetBytes((short)aic.DigitalMultiplier.DefaultValue), 0, 2);
|
|
break;
|
|
case DigitalInputModes.THL:
|
|
bw.Write(BitConverter.GetBytes((short)aic.DigitalMultiplier.ActiveValue), 0, 2);
|
|
break;
|
|
case DigitalInputModes.TLH:
|
|
bw.Write(BitConverter.GetBytes((short)aic.DigitalMultiplier.DefaultValue), 0, 2);
|
|
break;
|
|
default:
|
|
bw.Write(BitConverter.GetBytes((short)aic.DigitalMultiplier.ActiveValue), 0, 2);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (aic.DigitalMode)
|
|
{
|
|
case DigitalInputModes.CCNC:
|
|
bw.Write(BitConverter.GetBytes((short)aic.DigitalMultiplier.DefaultValue), 0, 2);
|
|
break;
|
|
case DigitalInputModes.CCNO:
|
|
bw.Write(BitConverter.GetBytes((short)aic.DigitalMultiplier.ActiveValue), 0, 2);
|
|
break;
|
|
case DigitalInputModes.THL:
|
|
bw.Write(BitConverter.GetBytes((short)aic.DigitalMultiplier.DefaultValue), 0, 2);
|
|
break;
|
|
case DigitalInputModes.TLH:
|
|
bw.Write(BitConverter.GetBytes((short)aic.DigitalMultiplier.ActiveValue), 0, 2);
|
|
break;
|
|
default:
|
|
bw.Write(BitConverter.GetBytes((short)aic.DigitalMultiplier.DefaultValue), 0, 2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ulong i = 0; i < channel.PersistentChannelInfo.NumberOfSamples; i++)
|
|
{
|
|
var adc = channel.PersistentChannelInfo[i];
|
|
for (int step = 0; step < rate; step++)
|
|
{
|
|
var increment = 0D;
|
|
|
|
if ((i + 1) < channel.PersistentChannelInfo.NumberOfSamples)
|
|
{
|
|
increment = (channel.PersistentChannelInfo[i + 1] - adc) / rate;
|
|
|
|
}
|
|
else
|
|
{
|
|
increment = (adc - channel.PersistentChannelInfo[i - 1]) / rate;
|
|
}
|
|
//Use correct calculation for linear and non linear
|
|
//http://fogbugz/fogbugz/default.asp?10172
|
|
if (!aic.LinearizationFormula.IsValid())
|
|
{
|
|
bw.Write(BitConverter.GetBytes(Convert.ToInt16(adc + increment * step)), 0, 2);
|
|
}
|
|
else
|
|
{
|
|
//14496 TDAS export ALL failed
|
|
//newADC was underflowing in the below code that was causing an exception in 14496
|
|
//the sensor capacity was about 80mm, however there were some datapoints that were out of normal range
|
|
//(-250 or so EU), this appeared to be from a sig-gen ramp that went out of range for the IR-TRACC equation
|
|
//per CPB we now constrain newADC to short min/max and so the ADC rails in those spots.
|
|
var adcperEU = (ushort.MaxValue / 2.0) / aic.SensorCapacity;
|
|
var newADC = scaler.GetEU(adc) * adcperEU;
|
|
newADC += increment * step;
|
|
if (newADC < short.MinValue)
|
|
{
|
|
bw.Write(BitConverter.GetBytes(short.MinValue), 0, 2);
|
|
}
|
|
else if (newADC > short.MaxValue)
|
|
{
|
|
bw.Write(BitConverter.GetBytes(short.MaxValue), 0, 2);
|
|
}
|
|
else
|
|
{
|
|
bw.Write(BitConverter.GetBytes(Convert.ToInt16(newADC)), 0, 2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|