init
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user