241 lines
9.8 KiB
Plaintext
241 lines
9.8 KiB
Plaintext
|
|
using System;
|
||
|
|
using System.Collections;
|
||
|
|
using System.Linq;
|
||
|
|
|
||
|
|
namespace DTS.Serialization.IRIGCH10.Packets
|
||
|
|
{
|
||
|
|
public class AnalogDataFormat1Packet : AbstractDataPacket, IDataPacket
|
||
|
|
{
|
||
|
|
|
||
|
|
public DateTime LocalTimeOfFirstSample
|
||
|
|
{
|
||
|
|
get;
|
||
|
|
private set;
|
||
|
|
}
|
||
|
|
|
||
|
|
//bit 28
|
||
|
|
public bool Same
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var bits = new BitArray(channelSpecificDataWord);
|
||
|
|
return bits[28];
|
||
|
|
}
|
||
|
|
set
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var b = new BitArray(channelSpecificDataWord);
|
||
|
|
b[28] = value;
|
||
|
|
var ret = new byte[sizeof(uint)];
|
||
|
|
b.CopyTo(ret, 0);
|
||
|
|
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//bits 27-24
|
||
|
|
public int Factor
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var bits = new BitArray(channelSpecificDataWord);
|
||
|
|
return Utils.Utils.BitArrayToInt32(bits, 24, 27);
|
||
|
|
}
|
||
|
|
set
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var b = new BitArray(channelSpecificDataWord);
|
||
|
|
Utils.Utils.SetBits(b, (uint)value, 24, 27);
|
||
|
|
var ret = new byte[sizeof(uint)];
|
||
|
|
b.CopyTo(ret, 0);
|
||
|
|
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//bits 23-16
|
||
|
|
public int TotChan
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var bits = new BitArray(channelSpecificDataWord);
|
||
|
|
return Utils.Utils.BitArrayToInt32(bits, 16, 23);
|
||
|
|
}
|
||
|
|
set
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var b = new BitArray(channelSpecificDataWord);
|
||
|
|
Utils.Utils.SetBits(b, (uint)value, 16, 23);
|
||
|
|
var ret = new byte[sizeof(uint)];
|
||
|
|
b.CopyTo(ret, 0);
|
||
|
|
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//bits 15-8
|
||
|
|
public long Subchan
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var bits = new BitArray(channelSpecificDataWord);
|
||
|
|
return Utils.Utils.BitArrayToInt32(bits, 8, 15);
|
||
|
|
}
|
||
|
|
set
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var b = new BitArray(channelSpecificDataWord);
|
||
|
|
Utils.Utils.SetBits(b, (uint)value, 8, 15);
|
||
|
|
var ret = new byte[sizeof(uint)];
|
||
|
|
b.CopyTo(ret, 0);
|
||
|
|
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//bits 7-2
|
||
|
|
public long Length
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var bits = new BitArray(channelSpecificDataWord);
|
||
|
|
return Utils.Utils.BitArrayToInt32(bits, 2, 7);
|
||
|
|
}
|
||
|
|
set
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var b = new BitArray(channelSpecificDataWord);
|
||
|
|
Utils.Utils.SetBits(b, (uint)value, 2, 7);
|
||
|
|
var ret = new byte[sizeof(uint)];
|
||
|
|
b.CopyTo(ret, 0);
|
||
|
|
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public enum Modes
|
||
|
|
{
|
||
|
|
DataIsPacked,
|
||
|
|
DataIsUnpackedLSBPadded,
|
||
|
|
Reserved,
|
||
|
|
DataIsUnpackedMSBPadded
|
||
|
|
}
|
||
|
|
//bits 1-0
|
||
|
|
public Modes Mode
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var bits = new BitArray(channelSpecificDataWord);
|
||
|
|
var mode = Utils.Utils.BitArrayToInt32(bits, 0, 1);
|
||
|
|
switch (mode)
|
||
|
|
{
|
||
|
|
case 0: return Modes.DataIsPacked;
|
||
|
|
case 1: return Modes.DataIsUnpackedLSBPadded;
|
||
|
|
case 3: return Modes.DataIsUnpackedMSBPadded;
|
||
|
|
case 2:
|
||
|
|
default: return Modes.Reserved;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
set
|
||
|
|
{
|
||
|
|
var channelSpecificDataWord = BitConverter.GetBytes(ChannelSpecificDataWord);
|
||
|
|
var b = new BitArray(channelSpecificDataWord);
|
||
|
|
Utils.Utils.SetBits(b, (uint)value, 0, 1);
|
||
|
|
var ret = new byte[sizeof(uint)];
|
||
|
|
b.CopyTo(ret, 0);
|
||
|
|
ChannelSpecificDataWord = BitConverter.ToUInt32(ret, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public SampleData[] Samples = new SampleData[0];
|
||
|
|
public class SampleData
|
||
|
|
{
|
||
|
|
public short[] ChannelData { private set; get; }
|
||
|
|
protected SampleData() { }
|
||
|
|
public SampleData(short[] channels)
|
||
|
|
{
|
||
|
|
ChannelData = channels;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/// <summary>
|
||
|
|
/// it seems the EMC ch10 validation tool only supports CH10 106v5, so use this header value for the analog packet when in this mode
|
||
|
|
/// whether to include secondary time header or not
|
||
|
|
/// 33199 Add Time format 1 as an export option for CH 10 export
|
||
|
|
/// </summary>
|
||
|
|
private const byte DATA_VERSION_V105 = 0x01;
|
||
|
|
|
||
|
|
|
||
|
|
private const byte DATA_VERSION_DASSAULT = 0x06;
|
||
|
|
public AnalogDataFormat1Packet(int nanoseconds, int seconds,
|
||
|
|
Chapter10File.GetNextSampleDelegate getNextSample, int totalChannels, long channelLength, long rtc, long numSamples, long currentSample, byte sequenceNumber,
|
||
|
|
ushort channelId, bool includeSecondaryHeader) : base(Enums.DataFileDataTypes.AnalogDataFormat1, includeSecondaryHeader)
|
||
|
|
{
|
||
|
|
TotChan = totalChannels;
|
||
|
|
Subchan = 0;
|
||
|
|
Same = true;
|
||
|
|
Factor = 0;
|
||
|
|
Length = 16;
|
||
|
|
Mode = Modes.DataIsUnpackedMSBPadded;
|
||
|
|
|
||
|
|
var dataLength = Convert.ToUInt32(4 + sizeof(ushort) * totalChannels * numSamples); ;
|
||
|
|
var offset = CommonHeaderWork(channelId, includeSecondaryHeader ? DATA_VERSION_DASSAULT : DATA_VERSION_V105, sequenceNumber, rtc, dataLength, nanoseconds, seconds);
|
||
|
|
|
||
|
|
for (var sampleIdx = 0; sampleIdx < numSamples; sampleIdx++)
|
||
|
|
{
|
||
|
|
for (var chIdx = 0; chIdx < totalChannels; chIdx++)
|
||
|
|
{
|
||
|
|
var signed = getNextSample(chIdx);
|
||
|
|
var unsigned = (ushort)(((signed - 0x8000 & 0x00FF) << 8) | ((signed - 0x8000 >> 8) & 0x00FF));
|
||
|
|
var bytes = BitConverter.GetBytes(unsigned).Reverse().ToArray();
|
||
|
|
Buffer.BlockCopy(bytes, 0, _dataBytes, offset, 2);
|
||
|
|
offset += 2;
|
||
|
|
}
|
||
|
|
currentSample++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public AnalogDataFormat1Packet() : base(Enums.DataFileDataTypes.AnalogDataFormat1, true)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
public AnalogDataFormat1Packet(byte[] bytes) : base(bytes)
|
||
|
|
{
|
||
|
|
var offset = IRIGCH10.PacketHeader.PACKET_HEADER_LENGTH;
|
||
|
|
|
||
|
|
if (PacketHeader.SecondaryHeaderPresent)
|
||
|
|
{
|
||
|
|
var secondaryHeaderBytes = new byte[SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH];
|
||
|
|
Buffer.BlockCopy(bytes, offset,
|
||
|
|
secondaryHeaderBytes, 0, SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH);
|
||
|
|
var secondaryHeader = new SecondaryTimeFormatHeader(secondaryHeaderBytes);
|
||
|
|
LocalTimeOfFirstSample = secondaryHeader.LocalTime;
|
||
|
|
offset += SecondaryTimeFormatHeader.SECONDARY_TIME_HEADER_LENGTH;
|
||
|
|
}
|
||
|
|
|
||
|
|
ChannelSpecificDataWord = BitConverter.ToUInt32(bytes, offset);
|
||
|
|
offset += sizeof(uint);
|
||
|
|
var numChannels = TotChan;
|
||
|
|
var sizeOf1SampleForAllChannels = sizeof(ushort) * numChannels;
|
||
|
|
//There's a CSDW in the data section, then all ADC data. CSDW is uint, 4 bytes
|
||
|
|
var numSamples = (PacketHeader.DataLength - 4) / sizeOf1SampleForAllChannels;
|
||
|
|
|
||
|
|
Samples = new SampleData[numSamples];
|
||
|
|
for (var i = 0; i < Samples.Length; i++)
|
||
|
|
{
|
||
|
|
var channels = GetChannels(bytes, offset, numChannels);
|
||
|
|
Samples[i] = new SampleData(channels);
|
||
|
|
offset += sizeOf1SampleForAllChannels;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private short[] GetChannels(byte[] bytes, int sampleStart, int numChannels)
|
||
|
|
{
|
||
|
|
var ret = new short[numChannels];
|
||
|
|
for (var i = 0; i < numChannels; i++)
|
||
|
|
{
|
||
|
|
var unsignedBytes = new byte[2];
|
||
|
|
Buffer.BlockCopy(bytes, sampleStart + i * 2, unsignedBytes, 0, 2);
|
||
|
|
//we have to change the byte order here
|
||
|
|
var unsigned = BitConverter.ToUInt16(new[] { unsignedBytes[1], unsignedBytes[0] }, 0);
|
||
|
|
//go from unsigned to signed
|
||
|
|
var adc = (short)((((unsigned & 0x00FF) << 8) | ((unsigned >> 8) & 0x00FF)) + 0x8000);
|
||
|
|
ret[i] = adc;
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|