961 lines
32 KiB
C#
961 lines
32 KiB
C#
// UNCLASSIFIED
|
|
/*-------------------------------------------------------------------------
|
|
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
|
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
|
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
|
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
|
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
|
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
|
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
|
COMPANY.
|
|
|
|
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
|
GOVERNMENT.
|
|
|
|
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
|
-------------------------------------------------------------------------*/
|
|
|
|
using Raytheon.Common;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace BitMeasurementManagerLib
|
|
{
|
|
/// <summary>
|
|
/// This class implements a message that can be put on a communication interface
|
|
/// </summary>
|
|
public class BitConfigurableMessage
|
|
{
|
|
#region PublicClassMembers
|
|
public enum DataItemType
|
|
{
|
|
FLOAT,
|
|
UINT,
|
|
UINT_HEX,
|
|
USHORT_HEX,
|
|
USHORT,
|
|
BYTE_HEX,
|
|
BYTE_ARRAY_HEX,
|
|
DOUBLE,
|
|
ULONG,
|
|
ULONG_HEX,
|
|
BITS
|
|
}
|
|
#endregion
|
|
|
|
#region PrivateClassMembers
|
|
public List<IConfigurableDataItem> _dataItems;
|
|
public Dictionary<string, int> _byteArrayCount;
|
|
public Dictionary<string, int> _bitCount;
|
|
private string _messageName;
|
|
private uint _entireMsgLen;
|
|
private uint _messageId;
|
|
private uint _rspMessageId;
|
|
#endregion
|
|
|
|
#region PublicFuctions
|
|
|
|
/// <summary>
|
|
/// Copy constructor
|
|
/// </summary>
|
|
/// <param name="rhs">The object to copy</param>
|
|
public BitConfigurableMessage(BitConfigurableMessage rhs)
|
|
{
|
|
// copy over the basic types
|
|
_messageId = rhs._messageId;
|
|
_rspMessageId = rhs._rspMessageId;
|
|
_messageName = String.Copy(rhs._messageName);
|
|
|
|
// _entireMsgLen will get set when we add the data items
|
|
_entireMsgLen = 0;
|
|
|
|
// initialize the objects
|
|
_dataItems = new List<IConfigurableDataItem>();
|
|
_byteArrayCount = new Dictionary<string, int>();
|
|
_bitCount = new Dictionary<string, int>();
|
|
|
|
// copy the data items over
|
|
foreach (IConfigurableDataItem dataItem in rhs._dataItems)
|
|
{
|
|
AddDataItem(dataItem.GetDataItemName(), dataItem.GetDataItemType(), dataItem.GetNumDataItems(), dataItem.GetDefaultValueStr());
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="messageId"></param>
|
|
/// <param name="rspMessageId"></param>
|
|
/// <param name="messageName"></param>
|
|
public BitConfigurableMessage(uint messageId, uint rspMessageId, string messageName)
|
|
{
|
|
_messageId = messageId;
|
|
|
|
_rspMessageId = rspMessageId;
|
|
|
|
_messageName = messageName;
|
|
|
|
_entireMsgLen = 0;
|
|
|
|
_dataItems = new List<IConfigurableDataItem>();
|
|
|
|
_byteArrayCount = new Dictionary<string, int>();
|
|
|
|
_bitCount = new Dictionary<string, int>();
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public uint GetMessageId()
|
|
{
|
|
return _messageId;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public uint GetMessageRspId()
|
|
{
|
|
return _rspMessageId;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="dataItemName"></param>
|
|
/// <param name="dataItemType"></param>
|
|
/// <param name="numItems"></param>
|
|
/// <param name="defaultValue"></param>
|
|
public void AddDataItem(string dataItemName, DataItemType dataItemType, int numItems, string defaultValue)
|
|
{
|
|
if (numItems < 1)
|
|
{
|
|
throw new Exception("BitConfigurableMessage::AddDataItem() - numItems is not valid: " + numItems + ", data item name is: " + dataItemName);
|
|
}
|
|
|
|
if (numItems > 1 && (dataItemType != DataItemType.BYTE_ARRAY_HEX && dataItemType != DataItemType.BITS))
|
|
{
|
|
throw new Exception("BitConfigurableMessage::AddDataItem() - numItems greater than one only allowed for hex byte arrays and BITs: " + numItems + ", data item name is: " + dataItemName);
|
|
}
|
|
|
|
if (dataItemType == DataItemType.UINT)
|
|
{
|
|
uint value = Convert.ToUInt32(defaultValue);
|
|
BitConfigurableMessageDataItem<uint> dataItem = new BitConfigurableMessageDataItem<uint>(dataItemName, dataItemType, value, defaultValue, numItems);
|
|
_entireMsgLen += (uint)(4 * numItems);
|
|
_dataItems.Add(dataItem);
|
|
}
|
|
else if (dataItemType == DataItemType.UINT_HEX)
|
|
{
|
|
uint value = Convert.ToUInt32(defaultValue, 16);
|
|
BitConfigurableMessageDataItem<uint> dataItem = new BitConfigurableMessageDataItem<uint>(dataItemName, dataItemType, value, defaultValue, numItems);
|
|
_entireMsgLen += (uint)(4 * numItems);
|
|
_dataItems.Add(dataItem);
|
|
}
|
|
else if (dataItemType == DataItemType.FLOAT)
|
|
{
|
|
float value = (float)Convert.ToDouble(defaultValue);
|
|
BitConfigurableMessageDataItem<float> dataItem = new BitConfigurableMessageDataItem<float>(dataItemName, dataItemType, value, defaultValue, numItems);
|
|
_entireMsgLen += (uint)(4 * numItems);
|
|
_dataItems.Add(dataItem);
|
|
}
|
|
else if (dataItemType == DataItemType.USHORT)
|
|
{
|
|
ushort value = Convert.ToUInt16(defaultValue);
|
|
BitConfigurableMessageDataItem<ushort> dataItem = new BitConfigurableMessageDataItem<ushort>(dataItemName, dataItemType, value, defaultValue, numItems);
|
|
_entireMsgLen += (uint)(2 * numItems);
|
|
_dataItems.Add(dataItem);
|
|
}
|
|
else if (dataItemType == DataItemType.USHORT_HEX)
|
|
{
|
|
ushort value = Convert.ToUInt16(defaultValue, 16);
|
|
BitConfigurableMessageDataItem<ushort> dataItem = new BitConfigurableMessageDataItem<ushort>(dataItemName, dataItemType, value, defaultValue, numItems);
|
|
_entireMsgLen += (uint)(2 * numItems);
|
|
_dataItems.Add(dataItem);
|
|
}
|
|
else if (dataItemType == DataItemType.DOUBLE)
|
|
{
|
|
double value = Convert.ToDouble(defaultValue);
|
|
BitConfigurableMessageDataItem<double> dataItem = new BitConfigurableMessageDataItem<double>(dataItemName, dataItemType, value, defaultValue, numItems);
|
|
_entireMsgLen += (uint)(8 * numItems);
|
|
_dataItems.Add(dataItem);
|
|
}
|
|
else if (dataItemType == DataItemType.ULONG)
|
|
{
|
|
ulong value = Convert.ToUInt64(defaultValue);
|
|
BitConfigurableMessageDataItem<ulong> dataItem = new BitConfigurableMessageDataItem<ulong>(dataItemName, dataItemType, value, defaultValue, numItems);
|
|
_entireMsgLen += (uint)(8 * numItems);
|
|
_dataItems.Add(dataItem);
|
|
}
|
|
else if (dataItemType == DataItemType.ULONG_HEX)
|
|
{
|
|
ulong value = Convert.ToUInt64(defaultValue, 16);
|
|
BitConfigurableMessageDataItem<ulong> dataItem = new BitConfigurableMessageDataItem<ulong>(dataItemName, dataItemType, value, defaultValue, numItems);
|
|
_entireMsgLen += (uint)(8 * numItems);
|
|
_dataItems.Add(dataItem);
|
|
}
|
|
else if (dataItemType == DataItemType.BYTE_HEX)
|
|
{
|
|
byte value = Convert.ToByte(defaultValue, 16);
|
|
BitConfigurableMessageDataItem<byte> dataItem = new BitConfigurableMessageDataItem<byte>(dataItemName, dataItemType, value, defaultValue, numItems);
|
|
_entireMsgLen += (uint)(1 * numItems);
|
|
_dataItems.Add(dataItem);
|
|
}
|
|
else if (dataItemType == DataItemType.BITS)
|
|
{
|
|
if (numItems > 8)
|
|
{
|
|
throw new Exception("BitConfigurableMessage::AddDataItem() - trying to add bit field: " + dataItemName + " that has more than 8 bits, bit fields are required to be less than 8 bits at this time");
|
|
}
|
|
|
|
// query how many bit fields have been added
|
|
// use this later when updating the number of bytes in the message
|
|
int totalBitPrevCount = 0;
|
|
foreach (KeyValuePair<string, int> entry in _bitCount)
|
|
{
|
|
totalBitPrevCount += entry.Value;
|
|
}
|
|
|
|
|
|
//intention integer division
|
|
uint numBytesPrevAdded = (uint)(totalBitPrevCount / 8);
|
|
|
|
int totalBitPrevCountRemander = totalBitPrevCount % 8;
|
|
|
|
// if remander is not 0, bump up the byte count by 1
|
|
if (totalBitPrevCountRemander != 0)
|
|
{
|
|
numBytesPrevAdded++;
|
|
}
|
|
|
|
// convert value to a byte and create the data item
|
|
defaultValue = defaultValue.Replace("0b", "");
|
|
defaultValue = defaultValue.Replace("0B", "");
|
|
byte value = Convert.ToByte(defaultValue, 2);
|
|
BitConfigurableMessageDataItem<byte> dataItem = new BitConfigurableMessageDataItem<byte>(dataItemName, dataItemType, value, defaultValue, numItems);
|
|
_dataItems.Add(dataItem);
|
|
|
|
// store the number of bits for this items
|
|
_bitCount[dataItemName.ToUpper()] = numItems;
|
|
|
|
// now that we updated the bit fields, query how many bit fields there are
|
|
int totalBitCount = 0;
|
|
foreach (KeyValuePair<string, int> entry in _bitCount)
|
|
{
|
|
totalBitCount += entry.Value;
|
|
}
|
|
|
|
// intentional integer division
|
|
uint numBytesToAdd = (uint)(totalBitCount / 8);
|
|
int totalBitCountRemander = totalBitCount % 8;
|
|
|
|
// if remander is not 0, bump up the byte count by 1
|
|
if (totalBitCountRemander != 0)
|
|
{
|
|
numBytesToAdd++;
|
|
}
|
|
|
|
// increment the message length we crossed a byte boundary with the total number of bits
|
|
_entireMsgLen += numBytesToAdd - numBytesPrevAdded;
|
|
}
|
|
else if (dataItemType == DataItemType.BYTE_ARRAY_HEX)
|
|
{
|
|
byte value = Convert.ToByte(defaultValue, 16);
|
|
|
|
byte[] data = new byte[numItems];
|
|
|
|
for (int i = 0; i < numItems; i++)
|
|
{
|
|
data[i] = value;
|
|
}
|
|
|
|
BitConfigurableMessageDataItem<Array> dataItem = new BitConfigurableMessageDataItem<Array>(dataItemName, dataItemType, data, defaultValue, numItems);
|
|
|
|
_dataItems.Add(dataItem);
|
|
|
|
_entireMsgLen += (uint)(1 * numItems);
|
|
|
|
_byteArrayCount[dataItemName.ToUpper()] = numItems;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("BitConfigurableMessage::AddDataItem() - Unsupported data item type: " + dataItemType.ToString());
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="pData"></param>
|
|
public void Format(IntPtr pData)
|
|
{
|
|
IntPtr pDataLocation = pData;
|
|
|
|
// should we byte swap
|
|
bool shallWeSwap = BitMsgEndianControl.Instance().ShallWeSwap();
|
|
|
|
// format the data
|
|
List<IConfigurableDataItem> formattedData = _dataItems;
|
|
|
|
for (int i = 0; i < formattedData.Count; i++)
|
|
{
|
|
IConfigurableDataItem dataItem = _dataItems[i];
|
|
DataItemType itemType = dataItem.GetDataItemType();
|
|
string itemName = dataItem.GetDataItemName();
|
|
object itemValue = dataItem.Data;
|
|
|
|
int dataItemSize = 0;
|
|
|
|
if (itemValue is float)// if (itemType == DataItemType.FLOAT)
|
|
{
|
|
float data = (float)itemValue;
|
|
|
|
if (shallWeSwap == true)
|
|
{
|
|
itemValue = Util.Swap(data);
|
|
}
|
|
else
|
|
{
|
|
itemValue = data;
|
|
}
|
|
|
|
dataItemSize = 4;
|
|
|
|
//copy data from our data items, info the buffer
|
|
Marshal.StructureToPtr(itemValue, pDataLocation, true);
|
|
}
|
|
else if (itemValue is uint)
|
|
{
|
|
uint data = (uint)itemValue;
|
|
|
|
if (shallWeSwap == true)
|
|
{
|
|
itemValue = Util.Swap(data);
|
|
}
|
|
else
|
|
{
|
|
itemValue = data;
|
|
}
|
|
|
|
dataItemSize = 4;
|
|
|
|
//copy data from our data items, info the buffer
|
|
Marshal.StructureToPtr(itemValue, pDataLocation, true);
|
|
}
|
|
else if (itemValue is ushort)
|
|
{
|
|
ushort data = (ushort)itemValue;
|
|
|
|
if (shallWeSwap == true)
|
|
{
|
|
itemValue = Util.Swap(data);
|
|
}
|
|
else
|
|
{
|
|
itemValue = data;
|
|
}
|
|
|
|
dataItemSize = 2;
|
|
|
|
//copy data from our data items, info the buffer
|
|
Marshal.StructureToPtr(itemValue, pDataLocation, true);
|
|
}
|
|
else if (itemValue is byte)
|
|
{
|
|
// handle the case where we stored an array of BITS as a byte
|
|
if (itemType == DataItemType.BITS)
|
|
{
|
|
// grab the value of the first bit item
|
|
byte totalBitItemValue = (byte)itemValue;
|
|
|
|
// queue up the rest of the BITs to the next byte boundary
|
|
int totalBitsProcessed = dataItem.GetNumDataItems();
|
|
|
|
for (int j = i + 1; totalBitsProcessed < 8; j++)
|
|
{
|
|
// grab the next data items
|
|
IConfigurableDataItem bitDataItem = _dataItems[j];
|
|
DataItemType bitItemType = bitDataItem.GetDataItemType();
|
|
|
|
// the next item should be BITS
|
|
if (bitItemType != DataItemType.BITS)
|
|
{
|
|
throw new Exception("BitConfigurableMessage::Format() - Bit fields not consecutive out to byte boundary for msg ID: " + _messageId.ToString("X8"));
|
|
}
|
|
|
|
int bitItemNumBites = bitDataItem.GetNumDataItems();
|
|
byte bitItemValue = (byte)bitDataItem.Data;
|
|
uint mask = (uint)((1 << bitItemNumBites) - 1) << totalBitsProcessed;
|
|
|
|
// mask in the next bit value
|
|
byte valueToMaskIn = (byte)((bitItemValue << totalBitsProcessed) & mask);
|
|
totalBitItemValue = (byte)(totalBitItemValue | valueToMaskIn);
|
|
|
|
// increment the bit counter
|
|
totalBitsProcessed += bitItemNumBites;
|
|
|
|
// increment the outer loop counter since we just processed it
|
|
i++;
|
|
}
|
|
|
|
// double check that we are on a byte boundary
|
|
//int byteBoundaryRemainder = totalBitsProcessed % 8;
|
|
if (totalBitsProcessed != 8)
|
|
{
|
|
throw new Exception("BitConfigurableMessage::Format() - Bit fields not equal to 8 for msg ID: " + _messageId.ToString("X8"));
|
|
}
|
|
|
|
dataItemSize = 1;
|
|
|
|
// hold onto the total bit item value
|
|
itemValue = (byte)totalBitItemValue;
|
|
|
|
//copy data from our data items, info the buffer
|
|
Marshal.StructureToPtr(itemValue, pDataLocation, true);
|
|
}
|
|
else
|
|
{
|
|
itemValue = (byte)itemValue;
|
|
|
|
dataItemSize = 1;
|
|
|
|
//copy data from our data items, info the buffer
|
|
Marshal.StructureToPtr(itemValue, pDataLocation, true);
|
|
}
|
|
}
|
|
else if (itemValue is double)
|
|
{
|
|
itemValue = (double)itemValue;
|
|
|
|
dataItemSize = 8;
|
|
|
|
//copy data from our data items, info the buffer
|
|
Marshal.StructureToPtr(itemValue, pDataLocation, true);
|
|
}
|
|
else if (itemValue is ulong)
|
|
{
|
|
itemValue = (ulong)itemValue;
|
|
|
|
dataItemSize = 8;
|
|
|
|
//copy data from our data items, info the buffer
|
|
Marshal.StructureToPtr(itemValue, pDataLocation, true);
|
|
}
|
|
else if (itemValue is Array)
|
|
{
|
|
IEnumerable en = (IEnumerable)itemValue;
|
|
byte[] arrayTemp = en.OfType<byte>().ToArray();
|
|
dataItemSize = arrayTemp.Length;
|
|
Marshal.Copy(arrayTemp, 0, pDataLocation, dataItemSize);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("BitConfigurableMessage::Format() - Unsupported data item type: " + itemType.ToString());
|
|
}
|
|
|
|
// increment the pointer
|
|
pDataLocation = IntPtr.Add(pDataLocation, dataItemSize);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="dataItemName"></param>
|
|
/// <returns></returns>
|
|
public byte[] GetDataItemByName_ByteArray(string dataItemName)
|
|
{
|
|
for (int i = 0; i < _dataItems.Count; i++)
|
|
{
|
|
if (_dataItems[i].GetDataItemName().ToUpper() == dataItemName.ToUpper())
|
|
{
|
|
if (_dataItems[i].GetDataItemType() != DataItemType.BYTE_ARRAY_HEX)
|
|
{
|
|
throw new Exception("BitConfigurableMessage::GetDataItemByName_ByteArray() - item was not a byte array: " + dataItemName);
|
|
}
|
|
|
|
IEnumerable en = (IEnumerable)_dataItems[i].Data;
|
|
byte[] dataToReturn = en.OfType<byte>().ToArray();
|
|
return dataToReturn;
|
|
}
|
|
}
|
|
|
|
throw new Exception("BitConfigurableMessage::GetDataItemByName_ByteArray() - Could not find data item: " + dataItemName);
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="dataItemName"></param>
|
|
/// <returns></returns>
|
|
public T GetDataItemByName<T>(string dataItemName)
|
|
{
|
|
for (int i = 0; i < _dataItems.Count; i++)
|
|
{
|
|
if (_dataItems[i].GetDataItemName().ToUpper() == dataItemName.ToUpper())
|
|
{
|
|
T value = (T)Convert.ChangeType(_dataItems[i].Data, typeof(T));
|
|
return value;
|
|
}
|
|
}
|
|
|
|
throw new Exception("BitConfigurableMessage::GetDataItemByName() - Could not find data item: " + dataItemName);
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public uint GetEntireMsgLength()
|
|
{
|
|
return _entireMsgLen;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="pData"></param>
|
|
public void Parse(IntPtr pData)
|
|
{
|
|
// should we byte swap
|
|
bool shallWeSwap = BitMsgEndianControl.Instance().ShallWeSwap();
|
|
|
|
IntPtr pMsgDataPtr = pData;
|
|
|
|
for (int i = 0; i < _dataItems.Count; i++)
|
|
{
|
|
IConfigurableDataItem item = _dataItems[i];
|
|
|
|
object itemData = item.Data;
|
|
|
|
if (itemData is float)
|
|
{
|
|
float itemValue = 0;
|
|
|
|
unsafe
|
|
{
|
|
float* pFloatItem = (float*)pMsgDataPtr;
|
|
|
|
itemValue = *pFloatItem;
|
|
}
|
|
|
|
if (shallWeSwap == true)
|
|
{
|
|
itemValue = Util.Swap(itemValue);
|
|
}
|
|
|
|
item.Data = itemValue;
|
|
|
|
_dataItems[i] = item;
|
|
|
|
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 4);
|
|
}
|
|
else if (itemData is uint)
|
|
{
|
|
uint itemValue = 0;
|
|
|
|
unsafe
|
|
{
|
|
uint* pUInt32Item = (uint*)pMsgDataPtr;
|
|
|
|
itemValue = *pUInt32Item;
|
|
}
|
|
|
|
if (shallWeSwap == true)
|
|
{
|
|
itemValue = Util.Swap(itemValue);
|
|
}
|
|
|
|
item.Data = itemValue;
|
|
|
|
_dataItems[i] = item;
|
|
|
|
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 4);
|
|
}
|
|
else if (itemData is ushort)
|
|
{
|
|
ushort itemValue = 0;
|
|
|
|
unsafe
|
|
{
|
|
ushort* pUInt16Item = (ushort*)pMsgDataPtr;
|
|
|
|
itemValue = *pUInt16Item;
|
|
}
|
|
|
|
if (shallWeSwap == true)
|
|
{
|
|
itemValue = Util.Swap(itemValue);
|
|
}
|
|
|
|
item.Data = itemValue;
|
|
|
|
_dataItems[i] = item;
|
|
|
|
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 2);
|
|
}
|
|
else if (itemData is double)
|
|
{
|
|
double itemValue = 0;
|
|
|
|
unsafe
|
|
{
|
|
double* pDoubleItem = (double*)pMsgDataPtr;
|
|
|
|
itemValue = *pDoubleItem;
|
|
}
|
|
|
|
if (shallWeSwap == true)
|
|
{
|
|
itemValue = Util.Swap(itemValue);
|
|
}
|
|
|
|
item.Data = itemValue;
|
|
|
|
_dataItems[i] = item;
|
|
|
|
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 8);
|
|
}
|
|
else if (itemData is ulong)
|
|
{
|
|
ulong itemValue = 0;
|
|
|
|
unsafe
|
|
{
|
|
ulong* pUlongItem = (ulong*)pMsgDataPtr;
|
|
|
|
itemValue = *pUlongItem;
|
|
}
|
|
|
|
if (shallWeSwap == true)
|
|
{
|
|
itemValue = Util.Swap(itemValue);
|
|
}
|
|
|
|
item.Data = itemValue;
|
|
|
|
_dataItems[i] = item;
|
|
|
|
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 8);
|
|
}
|
|
else if (itemData is byte)
|
|
{
|
|
// handle the case where we are storing bit arrays as a byte
|
|
if (item.GetDataItemType() == DataItemType.BITS)
|
|
{
|
|
// grab the value of the first bit item
|
|
byte rawDataValue = 0;
|
|
|
|
// Grab the byte from the msg pointer
|
|
unsafe
|
|
{
|
|
byte* pUInt8Item = (byte*)pMsgDataPtr;
|
|
|
|
rawDataValue = *pUInt8Item;
|
|
}
|
|
|
|
// set the first data item
|
|
uint mask = (uint)((1 << item.GetNumDataItems()) - 1);
|
|
item.Data = (byte)(rawDataValue & mask);
|
|
_dataItems[i] = item;
|
|
int totalBitsProcessed = item.GetNumDataItems();
|
|
|
|
// set the rest of the data items
|
|
for (int j = i + 1; totalBitsProcessed < 8; j++)
|
|
{
|
|
IConfigurableDataItem bitDataItem = _dataItems[j];
|
|
|
|
DataItemType bitItemType = bitDataItem.GetDataItemType();
|
|
|
|
// the next item should be BITS
|
|
if (bitItemType != DataItemType.BITS)
|
|
{
|
|
throw new Exception("BitConfigurableMessage::Parse() - Bit fields not consecutive out to byte boundary for msg ID: " + _messageId.ToString("X8"));
|
|
}
|
|
|
|
// shift the data into the beggining of the byte and mask out the other bits
|
|
mask = (uint)((1 << bitDataItem.GetNumDataItems()) - 1);
|
|
bitDataItem.Data = (byte)((rawDataValue >> totalBitsProcessed) & mask);
|
|
_dataItems[j] = bitDataItem;
|
|
|
|
// increment the bit counter
|
|
totalBitsProcessed += bitDataItem.GetNumDataItems();
|
|
|
|
// increment the outer loop counter since we just processed it
|
|
i++;
|
|
}
|
|
|
|
// double check that we are on a byte boundary
|
|
//int byteBoundaryRemainder = totalBitsProcessed % 8;
|
|
if (totalBitsProcessed != 8)
|
|
{
|
|
throw new Exception("BitConfigurableMessage::Parse() - Bit fields not on byte boundary forequal to 8 msg ID: " + _messageId.ToString("X8"));
|
|
}
|
|
|
|
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 1);
|
|
}
|
|
else
|
|
{
|
|
byte itemValue = 0;
|
|
|
|
unsafe
|
|
{
|
|
byte* pUInt8Item = (byte*)pMsgDataPtr;
|
|
|
|
itemValue = *pUInt8Item;
|
|
}
|
|
|
|
item.Data = itemValue;
|
|
|
|
_dataItems[i] = item;
|
|
|
|
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 1);
|
|
}
|
|
}
|
|
else if (itemData is Array)
|
|
{
|
|
int numBytes = _byteArrayCount[item.GetDataItemName().ToUpper()];
|
|
byte[] data = new byte[numBytes];
|
|
|
|
unsafe
|
|
{
|
|
for (int byteCounter = 0; byteCounter < numBytes; byteCounter++)
|
|
{
|
|
byte* pUInt8Item = (byte*)pMsgDataPtr;
|
|
data[byteCounter] = *pUInt8Item;
|
|
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 1);
|
|
}
|
|
}
|
|
|
|
item.Data = data;
|
|
|
|
_dataItems[i] = item;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("BitConfigurableMessage::Parse() - Unsupported data item type: " + item.GetDataItemType().ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the params of the message.
|
|
/// This function will iterate over the list of params passed in and sequentially set the data items in the message starting at the data item at index 0
|
|
/// </summary>
|
|
/// <param name="messageParams">an array of params</param>
|
|
public void SetParams(params object[] messageParams)
|
|
{
|
|
if (messageParams.Length > _dataItems.Count)
|
|
{
|
|
throw new Exception("BitConfigurableMessage::SetParams() - number of supplied parameters: " + messageParams.Length.ToString() + ", is larger than the number of parameters in the definition file: " + _dataItems.Count.ToString());
|
|
}
|
|
|
|
for (int i = 0; i < messageParams.Length; i++)
|
|
{
|
|
IConfigurableDataItem item = _dataItems[i];
|
|
|
|
object itemData = item.Data;
|
|
|
|
if (itemData is uint)
|
|
{
|
|
item.Data = Convert.ToUInt32(messageParams[i]);
|
|
_dataItems[i] = item;
|
|
}
|
|
else if (itemData is float)
|
|
{
|
|
item.Data = Convert.ToDouble(messageParams[i]);
|
|
_dataItems[i] = item;
|
|
}
|
|
else if (itemData is ushort)
|
|
{
|
|
item.Data = Convert.ToUInt16(messageParams[i]);
|
|
_dataItems[i] = item;
|
|
}
|
|
else if (itemData is double)
|
|
{
|
|
item.Data = Convert.ToDouble(messageParams[i]);
|
|
_dataItems[i] = item;
|
|
}
|
|
else if (itemData is ulong)
|
|
{
|
|
item.Data = Convert.ToUInt64(messageParams[i]);
|
|
_dataItems[i] = item;
|
|
}
|
|
else if (itemData is byte)
|
|
{
|
|
item.Data = Convert.ToByte(messageParams[i]);
|
|
_dataItems[i] = item;
|
|
|
|
// doesnt matter if it is of types BITs or not, the configurable data item already knows
|
|
/*if (item.GetDataItemType() == DataItemType.BITS)
|
|
{
|
|
item.Data = Convert.ToByte(messageParams[i]);
|
|
_dataItems[i] = item;
|
|
}
|
|
else
|
|
{
|
|
item.Data = Convert.ToByte(messageParams[i]);
|
|
_dataItems[i] = item;
|
|
}*/
|
|
}
|
|
else if (itemData is Array)
|
|
{
|
|
// convert object to byte array
|
|
IEnumerable en = (IEnumerable)messageParams[i];
|
|
byte[] data = en.OfType<byte>().ToArray();
|
|
item.Data = data;
|
|
_dataItems[i] = item;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("BitConfigurableMessage::SetParams() - unknown type");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override string ToString()
|
|
{
|
|
string dataToReturn = "Description: " + _messageName + "\r\n";
|
|
dataToReturn += "Payload Data:\r\n";
|
|
|
|
for (int i = 0; i < _dataItems.Count; i++)
|
|
{
|
|
IConfigurableDataItem dataItem = _dataItems[i];
|
|
DataItemType itemType = dataItem.GetDataItemType();
|
|
string itemName = dataItem.GetDataItemName();
|
|
object itemValue = dataItem.Data;
|
|
|
|
if (itemValue is uint)
|
|
{
|
|
if (itemValue == null)
|
|
{
|
|
dataToReturn += " " + itemName + ":Not Set\r\n";
|
|
}
|
|
else
|
|
{
|
|
uint data = (uint)itemValue;
|
|
|
|
dataToReturn += " " + itemName + ":" + "0x" + data.ToString("X8") + "\r\n";
|
|
}
|
|
}
|
|
else if (itemValue is ushort)
|
|
{
|
|
if (itemValue == null)
|
|
{
|
|
dataToReturn += " " + itemName + ":Not Set\r\n";
|
|
}
|
|
else
|
|
{
|
|
ushort data = (ushort)itemValue;
|
|
|
|
dataToReturn += " " + itemName + ":" + "0x" + data.ToString("X4") + "\r\n";
|
|
}
|
|
}
|
|
else if (itemValue is double)
|
|
{
|
|
if (itemValue == null)
|
|
{
|
|
dataToReturn += " " + itemName + ":Not Set\r\n";
|
|
}
|
|
else
|
|
{
|
|
double data = (double)itemValue;
|
|
|
|
dataToReturn += " " + itemName + ":" + data + "\r\n";
|
|
}
|
|
}
|
|
else if (itemValue is ulong)
|
|
{
|
|
if (itemValue == null)
|
|
{
|
|
dataToReturn += " " + itemName + ":Not Set\r\n";
|
|
}
|
|
else
|
|
{
|
|
ulong data = (ulong)itemValue;
|
|
|
|
dataToReturn += " " + itemName + ":" + data + "\r\n";
|
|
}
|
|
}
|
|
else if (itemValue is byte)
|
|
{
|
|
if (itemValue == null)
|
|
{
|
|
dataToReturn += " " + itemName + ":Not Set\r\n";
|
|
}
|
|
else
|
|
{
|
|
if (itemType == DataItemType.BITS)
|
|
{
|
|
byte data = (byte)itemValue;
|
|
|
|
string binString = Convert.ToString(data, 2).PadLeft(dataItem.GetNumDataItems(), '0');
|
|
|
|
dataToReturn += " " + itemName + ":" + "0b" + binString + "\r\n";
|
|
}
|
|
else
|
|
{
|
|
byte data = (byte)itemValue;
|
|
|
|
dataToReturn += " " + itemName + ":" + "0x" + data.ToString("X2") + "\r\n";
|
|
}
|
|
}
|
|
}
|
|
else if (itemValue is Array)
|
|
{
|
|
string arrayDataStr = "";
|
|
|
|
if (itemValue == null)
|
|
{
|
|
arrayDataStr += " " + itemName + ":Not Set" + "\r\n";
|
|
}
|
|
else
|
|
{
|
|
IEnumerable en = (IEnumerable)itemValue;
|
|
byte[] arrayTemp = en.OfType<byte>().ToArray();
|
|
StringBuilder hex = new StringBuilder(arrayTemp.Length * 2);
|
|
foreach (byte b in arrayTemp)
|
|
hex.AppendFormat("{0:x2}", b);
|
|
|
|
arrayDataStr += " " + itemName + ":" + hex.ToString() + "\r\n";
|
|
}
|
|
|
|
dataToReturn += arrayDataStr;
|
|
}
|
|
else if (itemValue is float)
|
|
{
|
|
if (itemValue == null)
|
|
{
|
|
dataToReturn += " " + itemName + ":Not Set\r\n";
|
|
}
|
|
else
|
|
{
|
|
float data = (float)itemValue;
|
|
|
|
dataToReturn += " " + itemName + ":" + data + "\r\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dataToReturn += " " + itemName + ":" + "UNKNOWN TYPE:" + itemType + "\r\n";
|
|
}
|
|
}
|
|
|
|
return dataToReturn + "\r\n";
|
|
|
|
}
|
|
#endregion
|
|
}
|
|
} |