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 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 void SetCSDWBit(int bit, bool value) { if (bit <0 || bit > 31) { return; } if (!value) { //and with all ones except for the bit in question ChannelSpecificDataWord &= ~(1u << bit); } else { //or with all 0s except for bit in question ChannelSpecificDataWord |= (1u << bit); } } protected bool GetCSDWBit(int bit) { if (bit < 0 || bit > 31) { return false; } return (ChannelSpecificDataWord & (1u << bit)) != 0; } 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[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(); } } protected AbstractDataPacket(DataFileDataTypes dataType, bool secondaryHeaderPresent) { PacketHeader = new PacketHeader(dataType); PacketHeader.SecondaryHeaderPresent = secondaryHeaderPresent; } protected AbstractDataPacket(byte[] bytes) { var header = new byte[24]; Buffer.BlockCopy(bytes, 0, header, 0, 24); PacketHeader = new PacketHeader(header); _dataBytes = new byte[PacketHeader.DataLength]; var length = _dataBytes.Length; var length2 = bytes.Length - 24; if (length2 < length) { length = length2; } Buffer.BlockCopy(bytes, 24, _dataBytes, 0, length); ChannelSpecificDataWord = BitConverter.ToUInt32(_dataBytes, 0); } protected byte[] _dataBytes; public void SetDataVersion(DataTypeVersion version) { PacketHeader.SetDataVersion(version); } public void SetChannelID(ushort channelID) { PacketHeader.ChannelId = channelID; } } }