163 lines
6.9 KiB
Plaintext
163 lines
6.9 KiB
Plaintext
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
|
|
{
|
|
/// <summary>
|
|
/// this class was ported from FWTU RealtimeCommands, it appears almost verbatim to there
|
|
/// </summary>
|
|
public class UDPRealtimeByteConverter
|
|
{
|
|
public enum UDP_BYTE_INDEX
|
|
{
|
|
PKT_PATTERN = 0, // u16
|
|
CHANNEL_ID = 2, // u16
|
|
PKT_LEN = 4, // u32
|
|
DATA_LEN = 8, // u32
|
|
DATA_TYPE_VER = 12, // u8
|
|
SEQ_NUMBER = 13, // u8
|
|
PKT_FLAGS = 14, // u8
|
|
DATA_TYPE = 15, // u8
|
|
REL_TIME32 = 16, // u32 of 48
|
|
REL_TIME16 = 20, // u16
|
|
HDR_CRC16 = 22, // u16
|
|
PTP_U32_LSW = 24, // u32
|
|
PTP_U32_MSW = 28, // u32
|
|
RSV_U16 = 32, // u32
|
|
HDR2CRC16 = 34, // u16
|
|
CSDW = 36, // u32
|
|
DATA_START = 40, // data start address
|
|
}
|
|
|
|
// This is list of data type for UDP to support
|
|
public enum UDP_DATA_TYPE
|
|
{
|
|
// 0x21 for analog format 1. 0x01 = CGDP format 1 (setup record). 0x12 = Time Data, Format 2 (PTP time)
|
|
CGDP_TYPE = 0x01, // Setup XML record. 1. Setup Record, periodic message sent out.
|
|
TIME_DATA_PTP = 0x12, // Time data, format 2. Periodic message.
|
|
ANALOG_DATA_FORMAT_1 = 0x21, // Analog data format 3. Periodic message.
|
|
}
|
|
public ushort PacketPattern { get; private set; }
|
|
public ushort DataChannelID { get; private set; }
|
|
public uint PacketLength { get; private set; }
|
|
/// <summary>
|
|
/// careful if you use this, it's not the same as
|
|
/// RtData.Length ...
|
|
/// </summary>
|
|
public uint DataLength { get; private set; }
|
|
public byte DataTypeVersion { get; private set; }
|
|
public byte SequenceNumber { get; private set; }
|
|
public byte PacketFlags { get; private set; }
|
|
public byte DataType { get; private set; }
|
|
public uint RelativeTime32 { get; private set; }
|
|
public ushort RelativeTime16 { get; private set; }
|
|
public ushort HdrCrc16 { get; private set; }
|
|
public uint PtpTimeStampSec { get; private set; }
|
|
public uint PtpTimeStampNsec { get; private set; }
|
|
public uint Hdr2Crc16 { get; private set; }
|
|
public uint ChannelMask { get; private set; }
|
|
public ulong UdpSampleCount { get; private set; }
|
|
|
|
public ushort[] RtData { get; private set; }
|
|
|
|
public uint[] Channels { get; private set; }
|
|
public byte SequenceNumberPrev { get; private set; }
|
|
|
|
public UDPRealtimeByteConverter(byte[] bytes)
|
|
{
|
|
// TBD: Currently expect 36byte header. If simplified version with 24Byte,
|
|
// we have to account for the right offset. RTC will be used then.
|
|
PacketPattern = GetUShort(bytes, (int)UDP_BYTE_INDEX.PKT_PATTERN);
|
|
DataChannelID = GetUShort(bytes, (int)UDP_BYTE_INDEX.CHANNEL_ID);
|
|
PacketLength = GetUInt(bytes, (int)UDP_BYTE_INDEX.PKT_LEN);
|
|
DataLength = GetUInt(bytes, (int)UDP_BYTE_INDEX.DATA_LEN);
|
|
DataTypeVersion = GetByte(bytes, (int)UDP_BYTE_INDEX.DATA_TYPE_VER);
|
|
SequenceNumber = GetByte(bytes, (int)UDP_BYTE_INDEX.SEQ_NUMBER);
|
|
PacketFlags = GetByte(bytes, (int)UDP_BYTE_INDEX.PKT_FLAGS);
|
|
DataType = GetByte(bytes, (int)UDP_BYTE_INDEX.DATA_TYPE); // 0x21 for analog format 1. 0x01 = CGDP format 1 (setup record). 0x12 = Time Data, Format 2 (PTP time)
|
|
RelativeTime32 = GetUInt(bytes, (int)UDP_BYTE_INDEX.REL_TIME32);
|
|
RelativeTime16 = GetUShort(bytes, (int)UDP_BYTE_INDEX.REL_TIME16);
|
|
HdrCrc16 = GetUShort(bytes, (int)UDP_BYTE_INDEX.HDR_CRC16);
|
|
PtpTimeStampSec = GetUInt(bytes, (int)UDP_BYTE_INDEX.PTP_U32_MSW);
|
|
PtpTimeStampNsec = GetUInt(bytes, (int)UDP_BYTE_INDEX.PTP_U32_LSW);
|
|
Hdr2Crc16 = GetUShort(bytes, (int)UDP_BYTE_INDEX.HDR2CRC16);
|
|
|
|
if (DataType == (int)UDP_DATA_TYPE.ANALOG_DATA_FORMAT_1)
|
|
{
|
|
RtData = new ushort[(DataLength - 4) / 2]; // ushort[(bytes.Length - (int)UDP_BYTE_INDEX.DATA_START) / 2];
|
|
|
|
var mychannels = new List<uint>();
|
|
|
|
for (var i = 0; i < 6; i++) // var length = dataLength;
|
|
{
|
|
//if (ba.Get(i)) assume all 6 channels if UDP.
|
|
{
|
|
mychannels.Add(Convert.ToUInt32(i));
|
|
}
|
|
}
|
|
Channels = mychannels.ToArray();
|
|
UdpSampleCount = Convert.ToUInt64(RtData.Length / Channels.Length);
|
|
|
|
SequenceNumberPrev = SequenceNumber;
|
|
|
|
// TBD: check for pktFlag if the optional 2nd header is being used or not. If not,
|
|
// we can start the data from UDP_BYTE_INDEX.PTP_U32_LSW
|
|
for (var idx = 0; idx < RtData.Length; idx++)
|
|
{
|
|
RtData[idx] = GetRTUShort(bytes, (int)(UDP_BYTE_INDEX.DATA_START + idx * 2));
|
|
RtData[idx] ^= 0x8000;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// TBD for other packet types.
|
|
RtData = null;
|
|
}
|
|
}
|
|
|
|
|
|
private static ulong GetULong(byte[] bytes, int offset)
|
|
{
|
|
return (ulong)bytes[offset + 7] << 0 |
|
|
(ulong)bytes[offset + 6] << 8 |
|
|
(ulong)bytes[offset + 5] << 16 |
|
|
(ulong)bytes[offset + 4] << 24 |
|
|
(ulong)bytes[offset + 3] << 32 |
|
|
(ulong)bytes[offset + 2] << 40 |
|
|
(ulong)bytes[offset + 1] << 48 |
|
|
(ulong)bytes[offset + 0] << 56;
|
|
}
|
|
|
|
private static ushort GetUShort(byte[] bytes, int offset)
|
|
{
|
|
return (ushort)(bytes[offset + 1] |
|
|
bytes[offset + 0] << 8);
|
|
}
|
|
|
|
private static byte GetByte(byte[] bytes, int offset)
|
|
{
|
|
return bytes[offset];
|
|
}
|
|
private static uint GetUInt(byte[] bytes, int offset)
|
|
{
|
|
return (uint)bytes[offset + 3] << 0 |
|
|
(uint)bytes[offset + 2] << 8 |
|
|
(uint)bytes[offset + 1] << 16 |
|
|
(uint)bytes[offset + 0] << 24;
|
|
}
|
|
/// <summary>
|
|
/// data apparently has a different byte order than parameters, so we have to
|
|
/// rearrange byte order for parameters but not data.
|
|
/// </summary>
|
|
/// <param name="bytes"></param>
|
|
/// <param name="offset"></param>
|
|
/// <returns></returns>
|
|
private static ushort GetRTUShort(byte[] bytes, int offset)
|
|
{
|
|
return (ushort)(bytes[offset + 0] |
|
|
bytes[offset + 1] << 8);
|
|
}
|
|
|
|
}
|
|
}
|