Files
DP44/DataPRO/SLICECommands/.svn/pristine/4d/4dedeb470cf1a89d82dd081e9d6e1b687fe4f3df.svn-base
2026-04-17 14:55:32 -04:00

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