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;
}
}
}