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