This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,317 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace DTS.Serialization.DDAS
{
public class DDASChannel
{
private readonly DDASTest _parentTest;
private readonly Dictionary<DDASTest.Fields, string> _values = new Dictionary<DDASTest.Fields, string>();
public string GetValue(DDASTest.Fields field)
{
if (!_values.ContainsKey(field)) _values.Add(field, "#NOVALUE");
return _values[field];
}
public void SetValue(DDASTest.Fields field, string value)
{
_values[field] = value;
switch (field)
{
case DDASTest.Fields.DataType:
if (value == "Raw")
{
SetValue(DDASTest.Fields.EngineeringUnits, "ADC");
SetValue(DDASTest.Fields.DigitalFilterType, "");
var actualRange = _parentTest.ActualRangesADC[_channelIndex];
SetValue(DDASTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
FileName = Path.Combine(Path.Combine(_path, "DDAS"), "Raw");
FileName = Path.Combine(FileName, $"{_parentTest.Test.Id}_{ChannelNumber}.DDAS");
}
else if (value == "Processed")
{
SetValue(DDASTest.Fields.EngineeringUnits, _engineeringUnits);
SetValue(DDASTest.Fields.DigitalFilterType,
$"CFC {_parentTest.DataUnfilteredEU[_channelIndex].FilterDescription}/{_parentTest.DataUnfilteredEU[_channelIndex].FilterFrequencyHz}");
var actualRange = _parentTest.ActualRangesEUFiltered[_channelIndex];
SetValue(DDASTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
FileName = Path.Combine(Path.Combine(_path, "DDAS"), "Processed");
FileName = Path.Combine(FileName, $"{_parentTest.Test.Id}_{ChannelNumber}.DDAS");
}
else if (value == "Converted")
{
SetValue(DDASTest.Fields.EngineeringUnits, _engineeringUnits);
SetValue(DDASTest.Fields.DigitalFilterType, "");
var actualRange = _parentTest.ActualRangesEUUnfiltered[_channelIndex];
SetValue(DDASTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
FileName = Path.Combine(Path.Combine(_path, "DDAS"), "Converted");
FileName = Path.Combine(FileName, $"{_parentTest.Test.Id}_{ChannelNumber}.DDAS");
}
break;
}
}
private readonly string _engineeringUnits = "";
public string FileName { get; set; }
public void Serialize(TickEventHandler tickHandler)
{
if (!Directory.Exists(new FileInfo(FileName).Directory.FullName))
Directory.CreateDirectory(new FileInfo(FileName).Directory.FullName);
using (var bw = new BinaryWriter(System.IO.File.Open(FileName, FileMode.Create)))
{
// First write the "fileinfoblock"
//typedef struct tagFILEINFOBLOCK
//{
// UINT Size; // Block Size (including nSize)
// char FileTypeName[12]; // Software Type Name
// char FileTypeVers[12]; // File Version Name
// UINT FileTypeFlags; // File Type Flags
// // - Hardware Type in upper 16 bits
// // - File Type in lower 16 bits
// char CreatedByName[16]; // Created by T-number
// char UpdatedByName[16]; // Updated by T-number
//}FILEINFOBLOCK;
bw.Write((uint)0x40);
var fileType = "DDAS FlPt";
bw.Write(Encoding.ASCII.GetBytes(fileType.PadRight(12, '\0')));
var fileTypeVersion = "Ver 500";
bw.Write(Encoding.ASCII.GetBytes(fileTypeVersion.PadRight(12, '\0')));
bw.Write((uint)0);
bw.Write(
Encoding.ASCII.GetBytes(
_parentTest.Test.Id.Substring(0, Math.Min(16, _parentTest.Test.Id.Length)).PadRight(16, '\0')));
bw.Write(
Encoding.ASCII.GetBytes(
_parentTest.Test.Id.Substring(0, Math.Min(16, _parentTest.Test.Id.Length)).PadRight(16, '\0')));
// Now the test info
// typedef struct tagTESTINFO
// {
// unsigned long Size; // Block Size (including Size)
// unsigned long DeviceID; // DAQ device ID
// long ChannelNo; // Channel number (1-32)
// long SampleRate; // Samples per second
// long TotalSamples; // Total samples in data record
// long PreEventSamples; // Samples before event
// short ChanNumInSys; // Channel Number (1-128) in system (many devices)
// short NumPreCalPts; // Number of preCal points included with data
// short NumPostCalPts; // Number of preCal points included with data
// char TestCreation[TESTPATHSIZE]; // Test path and date
// char TimeAxisTitle[32]; // Time axis title
// byte SpareBytes[2]; // 2 bytes of spare (for 4 byte alignment)
//
// } TESTINFO;
var channel = _parentTest.Test.Channels[_channelIndex] as Test.Module.AnalogInputChannel;
bw.Write((uint)0xC0);
bw.Write((uint)(1 + channel.ParentModule.Number));
bw.Write((uint)(1 + _channelIndex));
bw.Write((uint)channel.ParentModule.SampleRateHz);
bw.Write((uint)channel.ParentModule.NumberOfSamples);
bw.Write((uint)(channel.ParentModule.PreTriggerSeconds * channel.ParentModule.SampleRateHz));
bw.Write((ushort)channel.Number);
bw.Write((ushort)0);
bw.Write((ushort)0);
var testPathAndDate = FileName + " " + channel.ParentModule.ParentTest.InceptionDate.ToLongDateString();
bw.Write(
Encoding.ASCII.GetBytes(
testPathAndDate.Substring(0, Math.Min(128, testPathAndDate.Length)).PadRight(128, '\0')));
var TimeLabel = "Time (msec)";
bw.Write(Encoding.ASCII.GetBytes(TimeLabel.PadRight(32, '\0')));
bw.Write((byte)0x00);
bw.Write((byte)0x00);
// Channel
//typedef struct tagCHANNEL
// {
// short Size; // Size of this object
// short Flags; // Channel Flags
// char Name[64]; // Channel Name
// char Sign[8]; // Sign +, -, or blank
// char Axis[8]; // X,Y,Z,FX,MX,AX,...
// float FilterFreq; // Channel Filter Class (in Hz)
// float SetGain; // Gain setting (1 - n)
// float ActGain; // Actual (measured?) gain setting.
// float Rcal; // Shunt cal resistance
// float Excitation; // Excitation Voltage (when programable)
// byte byteSpares[4]; // Spare bytes (was Cal Date)
// TRANSDUCER Transducer; // "Snapshot" of transducer values
// } CHANNEL;
bw.Write((ushort)0x1001);
bw.Write((ushort)0x0100);
var description =
Encoding.ASCII.GetBytes(
channel.Description.Substring(0, Math.Min(64, channel.Description.Length)).PadRight(64, '\0'));
bw.Write(description);
var polarity = "+";
if (channel.IsInverted)
polarity = "-";
bw.Write(Encoding.ASCII.GetBytes(polarity.PadRight(8, (char)0x00)));
const string empty = "";
bw.Write(Encoding.ASCII.GetBytes(empty.PadRight(8, (char)0x00)));
//ChannelFilter[] filterClasses = Enum.GetValues(typeof(ChannelFilter)).Cast<ChannelFilter>().ToArray();
//float effectiveCFCFrequency = 0;
//foreach(var f in filterClasses)
//{
// if((int)f == (int)_parentTest.DataUnfilteredEU[_channelIndex].FilterFrequencyHz)
// {
// var type = typeof(ChannelFilter);
// var memInfo = type.GetMember(f.ToString());
// var attributes = memInfo[0].GetCustomAttributes(typeof(CFCValueAttribute),
// false);
// effectiveCFCFrequency = (float)((CFCValueAttribute)attributes[0]).CFCValue;
// }
//}
//if (0 == effectiveCFCFrequency) { effectiveCFCFrequency = (float)_parentTest.DataUnfilteredEU[_channelIndex].FilterFrequencyHz; }
bw.Write(channel.ParentModule.AaFilterRateHz);
if (channel.ExpectedGainValid)
bw.Write((float)channel.ExpectedGain);
else
bw.Write((float)(2500.0 / channel.DesiredRange));
if (channel.MeasuredGainValid)
bw.Write((float)channel.MeasuredGain);
else if (channel.ExpectedGainValid)
bw.Write((float)channel.ExpectedGain);
else
bw.Write((float)1.0);
bw.Write((float)channel.BridgeResistanceOhms);
if (channel.MeasuredExcitationVoltageValid)
bw.Write((float)channel.MeasuredExcitationVoltage);
else
bw.Write((float)channel.ExcitationVoltage);
bw.Write((byte)0x00);
bw.Write((byte)0x00);
bw.Write((byte)0x00);
bw.Write((byte)0x00);
//typedef struct tagTRANSDUCER
//{
//char Mfr[32]; // Manufacturer
//char Model[32]; // Model
//char SN[32]; // Transducer Serial No
//char Type[16]; // Transducer Type (load cell, accel, etc)
//char EngUnits[16]; // Engineering Units (applies to Capacity,
// // Sensitivity, and EUCalValue
//float Capacity; // Max applied accel, force, displacement, etc
//float XdcrRactive; // Bridge arm resistance of active half
//float XdcrRinactive; // Bridge arm resistance of inactive half
//float Sensitivity; // Sensitivity in V/EU
//float EUCalValue; // Engineering unit cal value with Rcal
//float Rcal; // Cal Resistor in Ohms
//float Excitation; // Excitation Voltage (when specified)
//long CalDate; // Cal date as time_t (seconds since 1970)
// // (Good til 2038...shouldn't be an issue
// // for this developer).
// long Spare; // Spare long
//} TRANSDUCER;
var Manufacturer = "CHRYSLER";
bw.Write(
Encoding.ASCII.GetBytes(Manufacturer.Substring(0, Math.Min(32, Manufacturer.Length))
.PadRight(32, '\0')));
bw.Write(Encoding.ASCII.GetBytes(empty.PadRight(32, (char)0x00)));
bw.Write(
Encoding.ASCII.GetBytes(
channel.SerialNumber.Substring(0, Math.Min(32, channel.SerialNumber.Length)).PadRight(32, '\0')));
var SensorType = "UNKNOWN";
bw.Write(
Encoding.ASCII.GetBytes(SensorType.Substring(0, Math.Min(16, SensorType.Length)).PadRight(16, '\0')));
bw.Write(
Encoding.ASCII.GetBytes(
channel.EngineeringUnits.Substring(0, Math.Min(16, channel.EngineeringUnits.Length))
.PadRight(16, '\0')));
bw.Write((float)channel.DesiredRange);
bw.Write((float)0);
bw.Write((float)0);
bw.Write((float)(1000 * channel.Sensitivity));
bw.Write((float)0);
bw.Write((float)channel.BridgeResistanceOhms);
bw.Write((float)channel.ExcitationVoltage);
var Epoch = new DateTime(1971, 1, 1, 0, 0, 0);
bw.Write((int)(channel.LastCalibrationDate - Epoch).TotalSeconds);
var TransducerSpare = 0;
bw.Write(TransducerSpare);
var Spare = new byte[0x0230 - 0x0210];
bw.Write(Spare);
double percentageComplete = (float)_channelIndex / _parentTest.Channels.Length;
var weight = 1D / _parentTest.Channels.Length;
for (var i = 0; i < _parentTest.DataUnfilteredEU[_channelIndex].Data.Length; i++)
{
bw.Write((float)_parentTest.DataUnfilteredEU[_channelIndex].Data[i]);
if (0 == i % 1000)
{
var percent = 100D * (percentageComplete + i * weight / channel.ParentModule.NumberOfSamples);
tickHandler(this, percent);
}
}
}
}
private readonly int _channelIndex;
public int ChannelNumber => 1 + _channelIndex;
private readonly string _path;
public DDASChannel(DDASTest parentTest, int channelIndex, string path)
{
_path = path;
_parentTest = parentTest;
_channelIndex = channelIndex;
var aic = parentTest.Test.Channels[channelIndex] as Test.Module.AnalogInputChannel;
_engineeringUnits = aic.EngineeringUnits;
SetValue(DDASTest.Fields.EngineeringUnits, aic.EngineeringUnits);
SetValue(DDASTest.Fields.SensorMakeModelSerial, aic.SerialNumber);
SetValue(DDASTest.Fields.SensorLocation, aic.Description);
// double actualRange = _parentTest.ActualRangesEUFiltered[_channelIndex];
double actualRange = 0;
SetValue(DDASTest.Fields.BitResolution, (2D * actualRange / ushort.MaxValue).ToString());
//FB14282: Option to Flatten Export Folders
FileName = path;
var channel = _parentTest.Test.Channels[_channelIndex] as Test.Module.AnalogInputChannel;
// We need a list of bases in order to properly formulate the file name.
var moduleSerialNumbers = new List<string>();
foreach (var currentChannel in _parentTest.Test.Channels)
if (!moduleSerialNumbers.Contains(currentChannel.ParentModule.SerialNumber))
moduleSerialNumbers.Add(currentChannel.ParentModule.SerialNumber);
var baseIndex = moduleSerialNumbers.IndexOf(channel.ParentModule.SerialNumber);
// Another SLICE Specific short cut. To properly number the channels, we need to know how many channels per module. However, in the case
// of SLICE where a bridge only has one channel _assigned_, channel.ParentModule.NumberOfChannels is 1. AFAIK, in this context, there is
// no way other than assumption to know a bridge has three channels.
var numberOfChannelsPerModule = (channel.ParentModule.NumberOfChannels + 2) / 3 * 3;
FileName = Path.Combine(FileName, $"ch{1 + baseIndex:D2}{1 + channel.Number + numberOfChannelsPerModule * channel.ParentModule.Number:D2}.fpd");
}
}
}

View File

@@ -0,0 +1,120 @@
using DTS.Serialization.IRIGCH10.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
namespace DTS.Serialization.IRIGCH10
{
/// <summary>
/// this packet just points to specific time data packets as part of an indexing system
/// </summary>
public class RecorderIndexPacket : AbstractDataPacket, IDataPacket
{
//not confident on breaking out the individual properties of this dataword yet
//(root index, file size, presence of data header, etc, so just use a
//prefilled one for now ...
private readonly byte [] ChannelSpecificDataWord = new byte[] {0x8D, 0x02, 0x00, 0xE0};
private readonly byte [] RootPacketAddress = new byte [8];
public void SetRootPacketAddress(long address)
{
var bits = BitConverter.GetBytes(address);
Buffer.BlockCopy(bits, 0, RootPacketAddress, 0, bits.Length);
}
private List<RecordingIndex> _indices = new List<RecordingIndex>();
public DateTime GetDateTime()
{
return _indices.First().GetDateTime();
}
public int NumberOfEntries => _indices.Count;
public void AddRecordingIndex(RecordingIndex index)
{
_indices.Add(index);
}
public RecorderIndexPacket()
: base(DataFileDataTypes.ComputerGeneratedDataFormat3)
{
_CheckSum = new byte[4];
}
public override byte[] GetBytes()
{
//we just need to make sure data bytes is populated then we can let the base class do it's thing
_dataBytes = new byte[_indices.Count * RecordingIndex.SIZE + RootPacketAddress.Length +
ChannelSpecificDataWord.Length];
Buffer.BlockCopy(ChannelSpecificDataWord, 0, _dataBytes, 0, ChannelSpecificDataWord.Length);
Buffer.BlockCopy(RootPacketAddress, 0, _dataBytes, ChannelSpecificDataWord.Length, RootPacketAddress.Length);
var offset = ChannelSpecificDataWord.Length + RootPacketAddress.Length;
foreach (var index in _indices)
{
var bytes = index.GetBytes();
Buffer.BlockCopy(bytes, 0, _dataBytes, offset, bytes.Length);
offset += bytes.Length;
}
return base.GetBytes();
}
}
/// <summary>
/// here's a structure for the recording indicies in the recording index packet
/// </summary>
public class RecordingIndex
{
public const int SIZE = 8+8+2+1+1+8;
private byte [] RTC = new byte [8];
private byte [] TimeDate = new byte[8];
private DateTime _dt;
private readonly ushort ChannelId = ushort.MaxValue;
private readonly byte DataType = 0x11;
private readonly byte Reserved = 0x00;
private byte[] DataPacketOffset = new byte[8];
private void SetRTC(long rtc)
{
var bits = BitConverter.GetBytes(rtc);
Buffer.BlockCopy(bits, 0, RTC, 0, bits.Length);
}
private void SetDataPacketOffset(long offset)
{
var bits = BitConverter.GetBytes(offset);
Buffer.BlockCopy(bits, 0, DataPacketOffset, 0, bits.Length);
}
public DateTime GetDateTime(){ return _dt; }
private void SetDateTime(DateTime dt)
{
_dt = dt;
TimeDate[0] = Utils.Utils.GetBCDBytes(dt.Millisecond/10)[0];
TimeDate[1] = Utils.Utils.GetBCDBytes(dt.Second)[0];
TimeDate[2] = Utils.Utils.GetBCDBytes(dt.Minute)[0];
TimeDate[3] = Utils.Utils.GetBCDBytes(dt.Hour)[0];
TimeDate[4] = Utils.Utils.GetBCDBytes(dt.Day)[0];
TimeDate[5] = Utils.Utils.GetBCDBytes(dt.Month)[0];
TimeDate[6] = Utils.Utils.GetBCDBytes(dt.Year)[0];
TimeDate[7] = Utils.Utils.GetBCDBytes(dt.Year)[1];
}
public RecordingIndex(long rtc, long offset, DateTime dt)
{
SetDataPacketOffset(offset);
SetRTC(rtc);
SetDateTime(dt);
}
public byte[] GetBytes()
{
var data = new byte[8 + 8 + 2 + 1 + 1 + 8];
var curOffset = 0;
Buffer.BlockCopy(RTC, 0, data, 0, RTC.Length);
curOffset += RTC.Length;
Buffer.BlockCopy(TimeDate, 0, data, curOffset, TimeDate.Length);
curOffset += TimeDate.Length;
var bytes = BitConverter.GetBytes(ChannelId);
Buffer.BlockCopy(bytes, 0, data, curOffset, 2);
curOffset += 2;
data[curOffset++] = DataType;
data[curOffset++] = Reserved;
Buffer.BlockCopy(DataPacketOffset, 0, data, curOffset, DataPacketOffset.Length);
return data;
}
}
}