using DTS.Serialization.IRIGCH10.Enums; using DTS.Serialization.IRIGCH10.Packets; using System; using System.ComponentModel; using System.IO; namespace DTS.Serialization.IRIGCH10 { /// /// this is the interface that all datapackets implement, it defines how packets can be interacted with in general /// public interface IDataPacket { /// /// all chapter 10 packets have a packet header /// IPacketHeader PacketHeader { get; } /// /// computes the checksum for the datapacket data /// uint ComputeCheckSum(); /// /// returns all bytes for the packet /// /// byte[] GetBytes(); /// /// sets the Realtime Counter (10 MHZ) for the packet /// /// void SetRTC(long rtc); /// /// sets the DataVersion of the packet /// (part of the packet header) /// /// void SetDataVersion(DataTypeVersion version); /// /// sets the packet flags for the packet (part of packet header) /// /// /// /// /// /// /// //void SetPacketFlags(bool SecondaryHeaderPresent, // bool SecondaryHeaderTime, // bool RTCSyncerror, // bool DataOverflow, // SecondaryHeaderTimeFormat fmt, // DataCheckSumType checkSum //); /// /// sets the channel id for the packet (part of packet header) /// /// void SetChannelID(ushort channelID); /// /// sets the sequence number for the packet, /// in general should be increasing and flip back to 0 /// after max value /// /// void SetSequenceNumber(ushort seq); } /// /// this is the general base class all packets extend, it /// has common features like computing the checksum, setting the /// packet specific Channel Data Word, etc /// public abstract class AbstractDataPacket { protected int CommonHeaderWork(ushort channelId, byte dataVersion, byte sequenceNumber, long rtc, uint dataLength, int nanoseconds, int seconds) { PacketHeader.ChannelId = channelId; PacketHeader.DataVersion = dataVersion; PacketHeader.SequenceNum = sequenceNumber; PacketHeader.IPTSTimeSource = PacketHeader.SecondaryHeaderPresent; PacketHeader.RTCSyncError = false; PacketHeader.SecondaryHeaderTimeFormat = IRIGCH10.PacketHeader.SecondaryHeaderTimeFormats.IEEE1588; PacketHeader.DataOverflowError = false; PacketHeader.CheckSumPresence = IRIGCH10.PacketHeader.DataCheckSumPresences.NotPresent; PacketHeader.SetRTC(rtc); PacketHeader.DataLength = dataLength; PacketHeader.PacketLength = PacketHeader.DataLength + IRIGCH10.PacketHeader.PACKET_HEADER_LENGTH; if (PacketHeader.SecondaryHeaderPresent) { PacketHeader.PacketLength += SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH; } if (0 != PacketHeader.PacketLength % 4) { var pad = 4 - PacketHeader.PacketLength % 4; //pad out packet length to a multiple of 4 ... PacketHeader.PacketLength += pad; //_dataBytes = new byte[_dataBytes.Length + pad]; } _dataBytes = new byte[PacketHeader.PacketLength - IRIGCH10.PacketHeader.PACKET_HEADER_LENGTH]; var offset = 0; if (PacketHeader.SecondaryHeaderPresent) { var secondaryHeader = SecondaryTimeFormatHeader.GetBytes(nanoseconds, seconds); Buffer.BlockCopy(secondaryHeader, 0, _dataBytes, offset, secondaryHeader.Length); offset += secondaryHeader.Length; } var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord); Buffer.BlockCopy(channelSpecificDataWord, 0, _dataBytes, offset, channelSpecificDataWord.Length); offset += channelSpecificDataWord.Length; return offset; } private uint _ChannelSpecificDataWork = 0; [Browsable(false)] public uint ChannelSpecificDataWord { get => _ChannelSpecificDataWork; protected set => _ChannelSpecificDataWork = value; } [Browsable(false)] public IPacketHeader PacketHeader { get; protected set; } public uint ComputeCheckSum() { return Utils.Utils.GetCheckSum32(_dataBytes); } /// /// sets the sequence number for the packet /// /// public void SetSequenceNumber(ushort seq) { PacketHeader.SequenceNum = BitConverter.GetBytes(seq)[0]; } private long _rtc; /// /// returns the Realtime Counter (10Mhz) value for the packet /// /// public long GetRTC() { return _rtc; } /// /// sets the Realtime Counter (10Mhz) value for the packet /// /// public void SetRTC(long rtc) { _rtc = rtc; PacketHeader.SetRTC(rtc); } public const long BASE_RTC = 141989612500056L; /// /// returns all bytes for the packet /// is virtual so extending classes can define their own behavior as needed /// /// public virtual byte[] GetBytes() { using (var ms = new MemoryStream()) { using (var bw = new BinaryWriter(ms)) { bw.Write(PacketHeader.GetBytes()); bw.Write(_dataBytes); } return ms.ToArray(); } } public AbstractDataPacket(DataFileDataTypes dataType, bool secondaryHeaderPresent) { PacketHeader = new PacketHeader(dataType); PacketHeader.SecondaryHeaderPresent = secondaryHeaderPresent; } public AbstractDataPacket(byte[] bytes) { var header = new byte[24]; Buffer.BlockCopy(bytes, 0, header, 0, 24); PacketHeader = new PacketHeader(header); FromBytes(bytes); } protected virtual void FromBytes(byte[] bytes) { _dataBytes = new byte[PacketHeader.DataLength]; Buffer.BlockCopy(bytes, 24, _dataBytes, 0, _dataBytes.Length); } protected byte[] _dataBytes; public void SetDataVersion(DataTypeVersion version) { PacketHeader.SetDataVersion(version); } public void SetChannelID(ushort channelID) { PacketHeader.ChannelId = channelID; } } }