368 lines
14 KiB
Plaintext
368 lines
14 KiB
Plaintext
using DTS.Serialization.IRIGCH10.Enums;
|
|
using System;
|
|
using System.Collections;
|
|
|
|
namespace DTS.Serialization.IRIGCH10
|
|
{
|
|
/// <summary>
|
|
/// implements the PCM/Pulse Control Modulation packet for CH 10
|
|
/// </summary>
|
|
public class PCMPacket : AbstractDataPacket, IDataPacket
|
|
{
|
|
private byte [] ChannelSpecificData;
|
|
|
|
public PCMPacket()
|
|
: base(DataFileDataTypes.PCMDataFormat1)
|
|
{
|
|
ChannelSpecificData = new byte[4];
|
|
_dataBytes = new byte[ChannelSpecificData.Length];
|
|
}
|
|
/// <summary>
|
|
/// Intra-Packet Header (IPH). (Bit 30) indicates if Intra-Packet Headers (IntraPacket Time Stamp and Intra-Packet Data Header) are inserted before each
|
|
/// minor frame. Intra-Packet Headers are only optional because of the mode
|
|
/// selection. This determines whether Intra-Packet Headers are included or
|
|
/// omitted.
|
|
/// false = Intra-Packet Headers are omitted for Throughput Mode.
|
|
/// true = Intra-Packet Headers are required for Packed Data and Unpacked Data
|
|
/// modes.
|
|
/// </summary>
|
|
public bool IntraPacketHeader
|
|
{
|
|
get
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
return bitArray[30];
|
|
}
|
|
set
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
bitArray[30] = value;
|
|
bitArray.CopyTo(ChannelSpecificData, 0);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Major Frame Indicator (MA). (Bit 29) indicates if the first word in the packet is
|
|
/// the beginning of a major frame. Not valid for Throughput Mode.
|
|
/// false = First word is not the beginning of a major frame.
|
|
/// true = First word is the beginning of a major frame.
|
|
/// </summary>
|
|
public bool MajorFrameIndicator
|
|
{
|
|
get
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
return bitArray[29];
|
|
}
|
|
set
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
bitArray[29] = value;
|
|
bitArray.CopyTo(ChannelSpecificData, 0);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Minor Frame Indicator (MI). (Bit 28) indicates if the first word in the packet is
|
|
/// the beginning of a minor frame. Not valid for Throughput Mode.
|
|
/// false = First word is not the beginning of a minor frame.
|
|
/// true = First word is the beginning of a minor frame.
|
|
/// </summary>
|
|
public bool MinorFrameIndicator
|
|
{
|
|
get
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
return bitArray[28];
|
|
}
|
|
set
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
bitArray[28] = value;
|
|
bitArray.CopyTo(ChannelSpecificData, 0);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicate Minor Frame Status
|
|
/// true = Minor Frame Lock
|
|
/// false = Minor Frame Check (after losing lock)
|
|
/// </summary>
|
|
public bool MinorFrameLockStatus
|
|
{
|
|
get
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
return bitArray[27] && bitArray[26];
|
|
}
|
|
set
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
bitArray[27] = true;
|
|
bitArray[26] = value;
|
|
bitArray.CopyTo(ChannelSpecificData, 0);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// true - Major Frame Lock
|
|
/// false - Major Frame Check (after losing Lock)
|
|
/// </summary>
|
|
public bool MajorFrameStatus
|
|
{
|
|
get
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
return bitArray[25] && bitArray[24];
|
|
}
|
|
set
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
|
|
bitArray[25] = true;
|
|
bitArray[24] = value;
|
|
|
|
bitArray.CopyTo(ChannelSpecificData, 0);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// true = 32Bit Alignment Mode
|
|
/// false = 16Bit Alignment Mode
|
|
/// </summary>
|
|
public bool AlignmentMode
|
|
{
|
|
get
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
return bitArray[21];
|
|
}
|
|
set
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
|
|
bitArray[21] = value;
|
|
|
|
bitArray.CopyTo(ChannelSpecificData, 0);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Throughput DataMode enabled or not
|
|
/// </summary>
|
|
public bool ThroughputDataMode
|
|
{
|
|
get
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
return bitArray[20];
|
|
}
|
|
set
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
bitArray[20] = value;
|
|
bitArray.CopyTo(ChannelSpecificData, 0);
|
|
}
|
|
}
|
|
|
|
public bool PackedData
|
|
{
|
|
get
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
return bitArray[19];
|
|
}
|
|
set
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
bitArray[19] = value;
|
|
bitArray.CopyTo(ChannelSpecificData, 0);
|
|
}
|
|
}
|
|
|
|
public bool UnpackedData
|
|
{
|
|
get
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
return bitArray[18];
|
|
}
|
|
set
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
bitArray[18] = value;
|
|
bitArray.CopyTo(ChannelSpecificData, 0);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// contains an 18-bit binary value
|
|
/// representing the Word offset into the major frame for the first data word in the
|
|
/// packet. Not valid for Packed or Throughput Mode.
|
|
/// </summary>
|
|
public byte[] SyncOffset
|
|
{
|
|
get
|
|
{
|
|
var output = new byte[2];
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
var bitArray2 = new BitArray(output);
|
|
for (int i = 0; i <= 17; i++)
|
|
{
|
|
bitArray2[i] = bitArray[i];
|
|
}
|
|
bitArray2.CopyTo(output, 0);
|
|
|
|
return output;
|
|
}
|
|
set
|
|
{
|
|
var bitArray = new BitArray(ChannelSpecificData);
|
|
var bitArray2 = new BitArray(value);
|
|
|
|
for (int i = 0; i <= 17; i++)
|
|
{
|
|
bitArray[i] = bitArray2[i];
|
|
}
|
|
bitArray.CopyTo(ChannelSpecificData, 0);
|
|
}
|
|
}
|
|
|
|
public readonly byte[] FrameSync = new byte[] { 0x90, 0xEB };
|
|
|
|
//private readonly byte[] FrameSync = new byte[] { 0x90, 0xEB, 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x90, 0xEB };
|
|
|
|
/// <summary>
|
|
/// adds data in unpacked 16 bit alignment into the data buffer, resizing as needed
|
|
/// </summary>
|
|
/// <param name="data"></param>
|
|
public void AddUnpacked16BitData(ushort[] data, long timeStamp, bool bFirst)
|
|
{
|
|
var intraPacketBytes = GetIntraPacketTimeStampBytes(timeStamp);
|
|
var intraHeaderBytes = GetIntraPacketHeader();
|
|
var insertSpot = 0;
|
|
|
|
//for some reason the spec seems to call out a different first order than all subsequent data sequences.
|
|
//the first sequence has a timestamp at the front, while all subsequent do not, but have a trailer timestamp.
|
|
if (bFirst)
|
|
{
|
|
var newBuffer = new byte[_dataBytes.Length + data.Length * 2 + FrameSync.Length + intraPacketBytes.Length + intraHeaderBytes.Length];
|
|
Buffer.BlockCopy(_dataBytes, 0, newBuffer, insertSpot, _dataBytes.Length);
|
|
insertSpot += _dataBytes.Length;
|
|
Buffer.BlockCopy(intraPacketBytes, 0, newBuffer, insertSpot, intraPacketBytes.Length);
|
|
insertSpot += intraPacketBytes.Length;
|
|
Buffer.BlockCopy(intraHeaderBytes, 0, newBuffer, insertSpot, intraHeaderBytes.Length);
|
|
insertSpot += intraHeaderBytes.Length;
|
|
Buffer.BlockCopy(FrameSync, 0, newBuffer, insertSpot, FrameSync.Length);
|
|
insertSpot += FrameSync.Length;
|
|
Buffer.BlockCopy(data, 0, newBuffer, insertSpot, data.Length * 2);
|
|
}
|
|
else
|
|
{
|
|
var newBuffer = new byte[_dataBytes.Length + data.Length * 2 + intraPacketBytes.Length + intraHeaderBytes.Length];
|
|
Buffer.BlockCopy(_dataBytes, 0, newBuffer, insertSpot, _dataBytes.Length);
|
|
insertSpot += _dataBytes.Length;
|
|
Buffer.BlockCopy(data, 0, newBuffer, insertSpot, data.Length * 2);
|
|
insertSpot += data.Length * 2;
|
|
Buffer.BlockCopy(intraPacketBytes, 0, newBuffer, insertSpot, intraPacketBytes.Length);
|
|
insertSpot += intraPacketBytes.Length;
|
|
Buffer.BlockCopy(intraHeaderBytes, 0, newBuffer, insertSpot, intraHeaderBytes.Length);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// adds data in unpacked 16 bit alignment into the data buffer, resizing as needed
|
|
/// </summary>
|
|
/// <param name="data"></param>
|
|
public void AddPacked16BitData(ushort[] data, long timeStamp, bool bFirst)
|
|
{
|
|
var intraPacketBytes = GetIntraPacketTimeStampBytes(timeStamp);
|
|
var intraHeaderBytes = GetIntraPacketHeader();
|
|
var insertSpot = 0;
|
|
|
|
//for some reason the spec seems to call out a different first order than all subsequent data sequences.
|
|
//the first sequence has a timestamp at the front, while all subsequent do not, but have a trailer timestamp.
|
|
if (bFirst)
|
|
{
|
|
var newBuffer = new byte[_dataBytes.Length + data.Length * 2 + FrameSync.Length + intraPacketBytes.Length + intraHeaderBytes.Length];
|
|
Buffer.BlockCopy(_dataBytes, 0, newBuffer, insertSpot, _dataBytes.Length);
|
|
insertSpot += _dataBytes.Length;
|
|
Buffer.BlockCopy(intraPacketBytes, 0, newBuffer, insertSpot, intraPacketBytes.Length);
|
|
insertSpot += intraPacketBytes.Length;
|
|
Buffer.BlockCopy(intraHeaderBytes, 0, newBuffer, insertSpot, intraHeaderBytes.Length);
|
|
insertSpot += intraHeaderBytes.Length;
|
|
Buffer.BlockCopy(FrameSync, 0, newBuffer, insertSpot, FrameSync.Length);
|
|
insertSpot += FrameSync.Length;
|
|
Buffer.BlockCopy(data, 0, newBuffer, insertSpot, data.Length * 2);
|
|
}
|
|
else
|
|
{
|
|
var newBuffer = new byte[_dataBytes.Length + data.Length * 2 + intraPacketBytes.Length + intraHeaderBytes.Length];
|
|
Buffer.BlockCopy(_dataBytes, 0, newBuffer, insertSpot, _dataBytes.Length);
|
|
insertSpot += _dataBytes.Length;
|
|
Buffer.BlockCopy(data, 0, newBuffer, insertSpot, data.Length * 2);
|
|
insertSpot += data.Length * 2;
|
|
Buffer.BlockCopy(intraPacketBytes, 0, newBuffer, insertSpot, intraPacketBytes.Length);
|
|
insertSpot += intraPacketBytes.Length;
|
|
Buffer.BlockCopy(intraHeaderBytes, 0, newBuffer, insertSpot, intraHeaderBytes.Length);
|
|
}
|
|
}
|
|
|
|
private byte [] GetIntraPacketHeader()
|
|
{
|
|
var array = new BitArray(new byte[2]);
|
|
//bits 15-14 minor frame status
|
|
//00,01 reserved
|
|
//10 minor frame check
|
|
//11 minor frame lock
|
|
|
|
//bits 13-12 major frame status
|
|
// 00 - major frame not locked
|
|
// 01 - reserved
|
|
// 10 major frame check
|
|
// 11 major frame lock
|
|
array.Set(15, true);
|
|
array.Set(14, true);
|
|
|
|
array.Set(12, true);
|
|
array.Set(13, true);
|
|
|
|
var output = new byte[2];
|
|
|
|
array.CopyTo(output, 0);
|
|
return output;
|
|
}
|
|
private byte [] GetIntraPacketTimeStampBytes(long timeStamp)
|
|
{
|
|
var output = new byte[8];
|
|
var stamp = IRIGCH10.PacketHeader.GetRTCBytes(timeStamp);
|
|
Buffer.BlockCopy(output, 0, stamp, 0, stamp.Length);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>
|
|
/// adds data in throughput mode to the packet, resizing the data buffer in the process
|
|
/// [throughput mode as opposed to a packed/or aligned mode]
|
|
/// </summary>
|
|
/// <param name="data"></param>
|
|
//public void AddThroughputData(ushort[] data)
|
|
//{
|
|
// var newBuffer = new byte[_dataBytes.Length + data.Length * 2 + FrameSync.Length];
|
|
// Buffer.BlockCopy(_dataBytes, 0, newBuffer, 0, _dataBytes.Length);
|
|
// Buffer.BlockCopy(FrameSync, 0, newBuffer, _dataBytes.Length, FrameSync.Length);
|
|
// Buffer.BlockCopy(data, 0, newBuffer, _dataBytes.Length + FrameSync.Length, data.Length * 2);
|
|
// _dataBytes = newBuffer;
|
|
//}
|
|
public override void ComputeCheckSum()
|
|
{
|
|
RefreshChannelSpecificDataInDataBytes();
|
|
base.ComputeCheckSum();
|
|
}
|
|
public override byte[] GetBytes()
|
|
{
|
|
RefreshChannelSpecificDataInDataBytes();
|
|
return base.GetBytes();
|
|
}
|
|
|
|
private void RefreshChannelSpecificDataInDataBytes()
|
|
{
|
|
//make sure ChannelSpecificData is set ...
|
|
Buffer.BlockCopy(ChannelSpecificData, 0, _dataBytes, 0, ChannelSpecificData.Length);
|
|
}
|
|
}
|
|
}
|