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,355 @@
using DTS.Serialization.IRIGCh10.Attributes;
using DTS.Serialization.IRIGCH10.Enums;
using System;
using System.Collections;
using System.ComponentModel;
using System.IO;
using System.Linq;
namespace DTS.Serialization.IRIGCH10
{
/// <summary>
/// implements the packet header portion of a packet
/// </summary>
public class PacketHeader : IPacketHeader
{
/// <summary>
/// used to indicate the start of a packet, is defined to 0x25, 0xEB by chapter10.pdf
/// </summary>
public ushort PacketSyncPattern { get; set; } = BitConverter.ToUInt16(new byte[] { 0x25, 0xEB }, 0);
/// <summary>
/// this is just a shortcut to avoid calculating the ushort value for 0x25,0xEB
/// this is the ushort pattern expected for pattern sync
/// </summary>
public const ushort EXPECTED_SYNC_PATTERN = 60197;
/// <summary>
/// channel id, default to 0
/// </summary>
public ushort ChannelId { get; set; } = BitConverter.ToUInt16(new byte[] { 0x00, 0x00 }, 0);
/// <summary>
/// total length of the packet including header, data, and filler, and any checksums
/// </summary>
public uint PacketLength { get; set; } = 0;
/// <summary>
/// length of the data portion of the packet, so sans filler and checksums
/// </summary>
public uint DataLength { get; set; } = 0;
public byte DataVersion { get; set; } = 0;
public byte SequenceNum { get; set; } = 0;
[Browsable(false)]
public byte PacketFlags { get; private set; } = 0;
public bool SecondaryHeaderPresent
{
get
{
var b = new BitArray(new[] { PacketFlags });
return b.Get(7);
}
set
{
PacketFlags = SetBit(PacketFlags, 7, value);
}
}
public bool IPTSTimeSource
{
get
{
var b = new BitArray(new[] { PacketFlags });
return b.Get(6);
}
set
{
PacketFlags = SetBit(PacketFlags, 6, value);
}
}
public bool RTCSyncError
{
get
{
var b = new BitArray(new[] { PacketFlags });
return b.Get(5);
}
set
{
PacketFlags = SetBit(PacketFlags, 5, value);
}
}
public enum SecondaryHeaderTimeFormats
{
Chapter4 = 0,
IEEE1588 = 1,
ExtendedRelativeTimeCounter = 2,
Reserved = 3
}
public SecondaryHeaderTimeFormats SecondaryHeaderTimeFormat
{
get
{
var b = new BitArray(new[] { PacketFlags });
return (SecondaryHeaderTimeFormats)Utils.Utils.BitArrayToInt32(b, 2, 3);
}
set
{
var b = new BitArray(new[] { PacketFlags });
Utils.Utils.SetBits(b, (uint)value, 2, 3);
var ret = new byte[1];
b.CopyTo(ret, 0);
PacketFlags = ret[0];
}
}
public bool DataOverflowError
{
get
{
var b = new BitArray(new[] { PacketFlags });
return b.Get(4);
}
set
{
PacketFlags = SetBit(PacketFlags, 4, value);
}
}
private byte SetBit(byte input, int bit, bool bVal)
{
var b = new BitArray(new[] { input });
b.Set(bit, bVal);
var ret = new byte[1];
b.CopyTo(ret, 0);
return ret[0];
}
public enum DataCheckSumPresences
{
NotPresent = 0,
EightBit = 1,
SixteenBit = 2,
ThirtyTwoBit = 3
}
public DataCheckSumPresences CheckSumPresence
{
get
{
var b = new BitArray(new[] { PacketFlags });
return (DataCheckSumPresences)Utils.Utils.BitArrayToInt32(b, 0, 1);
}
set
{
var b = new BitArray(new[] { PacketFlags });
Utils.Utils.SetBits(b, (uint)value, 0, 1);
var ret = new byte[1];
b.CopyTo(ret, 0);
PacketFlags = ret[0];
}
}
[Browsable(false)]
public byte DataType { get; set; } = 0;
public DataFileDataTypes DataFileType
{
get
{
var all = Enum.GetValues(typeof(DataFileDataTypes)).Cast<DataFileDataTypes>().ToArray();
foreach (var datatype in all)
{
var b = PacketHeaderValueAttribute.GetPacketHeaderValue(datatype);
if (b == DataType) { return datatype; }
}
return DataFileDataTypes.ComputerGeneratedDataFormat0;
}
}
//10 MHz Relative Time Counter
[Browsable(false)]
public byte[] RTC { get; set; } = new byte[6];
public long RTCLong
{
get
{
var bytes = new byte[8];
Buffer.BlockCopy(RTC, 0, bytes, 0, 6);
return BitConverter.ToInt64(bytes, 0);
}
}
public ushort CheckSum { get; set; }
/// <summary>
/// the RealtimeCounter in the packet header is a 6 byte field
/// for convenience we'll use a long to interact with it
/// even though we are only using 6 bytes
/// </summary>
/// <param name="rtc"></param>
public void SetRTC(long rtc)
{
var bytes = GetRTCBytes(rtc);
Buffer.BlockCopy(bytes, 0, RTC, 0, RTC.Length);
}
private const int RTC_SIZE_BYTES = 6;
public static byte[] GetRTCBytes(long rtc)
{
var s = rtc.ToString("X");
var buffer = new byte[RTC_SIZE_BYTES];
for (int i = 0; i < RTC_SIZE_BYTES; i++)
{
string sVal = s.Substring(i * 2, 2);
var val = Convert.ToInt16(sVal, 16);
buffer[buffer.Length - 1 - i] = BitConverter.GetBytes(val)[0];
}
return buffer;
}
public PacketHeader(DataFileDataTypes dataType)
{
DataType = PacketHeaderValueAttribute.GetPacketHeaderValue(dataType);
}
public PacketHeader(byte[] bytes)
{
if (null == bytes) { throw new NullReferenceException("no bytes received"); }
if (PACKET_HEADER_LENGTH != bytes.Length) { throw new Exception($"Expected {PACKET_HEADER_LENGTH} bytes, received: {bytes.Length}"); }
PacketSyncPattern = BitConverter.ToUInt16(bytes, 0);
if (PacketSyncPattern != EXPECTED_SYNC_PATTERN)
{
System.Diagnostics.Trace.WriteLine("Expected sync pattern not found");
}
ChannelId = BitConverter.ToUInt16(bytes, 2);
PacketLength = BitConverter.ToUInt32(bytes, 4);
DataLength = BitConverter.ToUInt32(bytes, 8);
DataVersion = bytes[12];
SequenceNum = bytes[13];
PacketFlags = bytes[14];
DataType = bytes[15];
RTC = new byte[6];
Array.Copy(bytes, 16, RTC, 0, 6);
CheckSum = BitConverter.ToUInt16(bytes, 22);
var computedCRC = ComputeCheckSum();
if (CheckSum != computedCRC)
{
System.Diagnostics.Trace.WriteLine("Checksum doesn't match");
}
}
public byte[] GetBytes()
{
using (var sw = new MemoryStream())
{
using (var bw = new BinaryWriter(sw))
{
bw.Write(PacketSyncPattern);
bw.Write(ChannelId);
bw.Write(PacketLength);
bw.Write(DataLength);
bw.Write(DataVersion);
bw.Write(SequenceNum);
bw.Write(PacketFlags);
bw.Write(DataType);
bw.Write(RTC);
bw.Write(ComputeCheckSum());
}
return sw.ToArray();
}
}
public void SetDataVersion(DataTypeVersion version)
{
DataVersion = PacketHeaderValueAttribute.GetPacketHeaderValue(version);
}
public void SetPacketFlags(bool SecondaryHeaderPresent,
bool SecondaryHeaderTime,
bool RTCSyncerror,
bool DataOverflow,
SecondaryHeaderTimeFormat fmt,
DataCheckSumType checkSum
)
{
var bitArray = new BitArray(new[] { PacketFlags });
bitArray[7] = SecondaryHeaderPresent;
bitArray[6] = SecondaryHeaderTime;
bitArray[5] = RTCSyncerror;
bitArray[4] = DataOverflow;
var byteValue = new BitArray(new[] { PacketHeaderValueAttribute.GetPacketHeaderValue(fmt) });
bitArray[3] = byteValue[0];
bitArray[2] = byteValue[1];
byteValue = new BitArray(new[] { PacketHeaderValueAttribute.GetPacketHeaderValue(checkSum) });
bitArray[1] = byteValue[0];
bitArray[0] = byteValue[1];
var bytes = new byte[1];
bitArray.CopyTo(bytes, 0);
PacketFlags = bytes[0];
}
public ushort ComputeCheckSum()
{
byte[] bytesToCompute;
using (var ms = new MemoryStream())
{
using (var bw = new BinaryWriter(ms))
{
bw.Write(PacketSyncPattern);
bw.Write(ChannelId);
bw.Write(PacketLength);
bw.Write(DataLength);
bw.Write(DataVersion);
bw.Write(SequenceNum);
bw.Write(PacketFlags);
bw.Write(DataType);
bw.Write(RTC);
}
bytesToCompute = ms.ToArray();
}
return Utils.Utils.GetCheckSum16(bytesToCompute);
}
public const int PACKET_HEADER_LENGTH = 24;
}
public interface IPacketHeader
{
ushort PacketSyncPattern { get; set; }
ushort ChannelId { get; set; }
uint PacketLength { get; set; }
uint DataLength { get; set; }
byte DataVersion { get; set; }
byte SequenceNum { get; set; }
[Browsable(false)]
byte PacketFlags { get; }
bool SecondaryHeaderPresent { get; set; }
bool IPTSTimeSource { get; set; }
bool RTCSyncError { get; set; }
PacketHeader.SecondaryHeaderTimeFormats SecondaryHeaderTimeFormat { get; set; }
bool DataOverflowError { get; set; }
PacketHeader.DataCheckSumPresences CheckSumPresence { get; set; }
[Browsable(false)]
byte DataType { get; set; }
DataFileDataTypes DataFileType { get; }
[Browsable(false)]
byte[] RTC { get; set; }
long RTCLong { get; }
ushort CheckSum { get; set; }
void SetRTC(long rtc);
void SetDataVersion(DataTypeVersion version);
void SetPacketFlags(bool SecondaryHeaderPresent,
bool SecondaryHeaderTime,
bool RTCSyncerror,
bool DataOverflow,
SecondaryHeaderTimeFormat fmt,
DataCheckSumType checkSum
);
byte[] GetBytes();
ushort ComputeCheckSum();
}
}

View File

@@ -0,0 +1,193 @@
using IRIGCh10;
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace DTS.Serialization.IRIGCH10.TMATS.DataConversion
{
public enum TransducerInformation
{
[Description("DCN")] [MaxLength(32)] MeasurementName,
[Description("TRD1")] [MaxLength(32)] Type,
[Description("TRD2")] [MaxLength(32)] ModelNumber,
[Description("TRD3")] [MaxLength(32)] SerialNumber,
[Description("TRD4")] [MaxLength(2)] SecurityClassification,
[Description("TRD5")] [MaxLength(10)] OriginationDate,
[Description("TRD6")] [MaxLength(4)] RevisionNumber,
[MaxLength(32)] [Description("TRD7")] Orientation,
[MaxLength(24)] [Description("POC1")] PointOfContactName,
[MaxLength(48)] [Description("POC2")] PointOfContactAgency,
[MaxLength(48)] [Description("POC3")] PointOfContectAddress,
[MaxLength(20)] [Description("POC4")] PointOfContactTelephone,
}
public enum ClassificationTypes
{
[Description("U")] Unclassified,
[Description("C")] Confidential,
[Description("S")] Secret,
[Description("T")] TopSecret,
[Description("O")] Other
}
/// <summary>
/// this class handles the transducer information section of the TMAT packet (see chapter 9.pdf)
/// </summary>
public class TransducerInformationSection : TMATSSection<TransducerInformation>
{
public TransducerInformationSection(int number) : base(AttributeIdentifiers.DataConversionAttributes, number)
{
}
/// <summary>
/// GIVE THE MEASUREMENT NAME.
/// </summary>
public string MeasurementName
{
get => GetValue(TransducerInformation.MeasurementName);
set => SetValueWithLength(TransducerInformation.MeasurementName, value);
}
/// <summary>
/// TYPE OF SENSOR, IF APPROPRIATE
/// </summary>
public string Type
{
get => GetValue(TransducerInformation.Type);
set => SetValueWithLength(TransducerInformation.Type, value);
}
/// <summary>
/// IF APPROPRIATE
/// </summary>
public string ModelNumber
{
get => GetValue(TransducerInformation.ModelNumber);
set => SetValueWithLength(TransducerInformation.ModelNumber, value);
}
/// <summary>
/// IF APPLICABLE
/// </summary>
public string SerialNumber
{
get => GetValue(TransducerInformation.SerialNumber);
set => SetValueWithLength(TransducerInformation.SerialNumber, value);
}
/// <summary>
/// ENTER THE SECURITY CLASSIFICATION OF THIS MEASURAND.
/// </summary>
/// <param name="type"></param>
/// <param name="signalClassified"></param>
/// <param name="measurandClassified"></param>
public void SetSecurityClassification(ClassificationTypes type,
bool signalClassified, bool measurandClassified)
{
var val = DescriptionDecoder.GetDescription(type);
if (signalClassified && measurandClassified)
{
val = $"{val}B";
}
else if (signalClassified)
{
val = $"{val}R";
}
else if (measurandClassified)
{
val = $"{val}E";
}
SetValueWithLength(TransducerInformation.SecurityClassification, val);
}
/// <summary>
/// DATE OF ORIGINATION OF THIS DATA FILE. DD DAY MM MONTH
/// YYYY YEAR (MM-DD-YYYY)
/// </summary>
public DateTime? OriginationDate
{
get
{
var val = GetValue(TransducerInformation.OriginationDate);
if (string.IsNullOrWhiteSpace(val))
{
return null;
}
if (DateTime.TryParse(val, out var dt))
{
return dt;
}
return null;
}
set
{
if (null == value)
{
SetValueWithLength(TransducerInformation.OriginationDate, string.Empty);
}
else
{
var dt = (DateTime) value;
SetValueWithLength(TransducerInformation.OriginationDate,
$"{dt.Month:00}-{dt.Day:00}-{dt.Year:0000}");
}
}
}
/// <summary>
/// SPECIFY THE REVISION NUMBER OF THE DATA PROVIDED.
/// </summary>
public string RevisionNumber
{
get => GetValue(TransducerInformation.RevisionNumber);
set => SetValueWithLength(TransducerInformation.RevisionNumber, value);
}
/// <summary>
/// DESCRIBE THE PHYSICAL ORIENTATION OF THE SENSOR.
/// </summary>
public string Orientation
{
get => GetValue(TransducerInformation.Orientation);
set => SetValueWithLength(TransducerInformation.Orientation, value);
}
/// <summary>
/// POINT OF CONTACT WITH THE ORGANIZATION THAT PROVIDED THE CALIBRATION DATA
/// </summary>
public POC PointOfContact
{
get => new POC()
{
Name = GetValue(TransducerInformation.PointOfContactName),
Agency = GetValue(TransducerInformation.PointOfContactAgency),
Address = GetValue(TransducerInformation.PointOfContectAddress),
Telephone = GetValue(TransducerInformation.PointOfContectAddress)
};
set
{
SetValueWithLength(TransducerInformation.PointOfContactName, value.Name);
SetValueWithLength(TransducerInformation.PointOfContactAgency, value.Agency);
SetValueWithLength(TransducerInformation.PointOfContectAddress, value.Address);
SetValueWithLength(TransducerInformation.PointOfContactTelephone, value.Telephone);
}
}
}
/// <summary>
/// Point Of Contact structure
/// </summary>
public class POC
{
public string Name { get; set; }
public string Agency { get; set; }
public string Address { get; set; }
public string Telephone { get; set; }
public POC(string name, string agency, string address, string telephone)
{
Name = name;
Agency = agency;
Address = address;
Telephone = telephone;
}
public POC()
{
}
}
}