Sic02-new/FrameworkLocal/RTCore/IoProviders/Mitsubishis/MCProtocol.cs

379 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace MECF.Framework.RT.Core.IoProviders
{
public partial class MCProtocol
{
////
///
///
/// Melsec Protocol QnA compatible 3E frame Constant and Message Format Definition
///
///
///
///
public const int CMD_BATCH_READ = 0x0401;
public const int CMD_BATCH_WRITE = 0x1401;
public const int CMD_RANDOM_READ = 0x0403;
public const int CMD_RANDOM_WRITE = 0x1402;
public const int SUB_CMD_WORD_UNITS = 0;
public const int SUB_CMD_BYTE_UNITS = 1;
public static readonly int JUNK_SIZE = Marshal.SizeOf(typeof(ushort)); // RESERVED
static public readonly int PLCDataSize = Marshal.SizeOf(typeof(ushort));
static public readonly int PLCDataBits = PLCDataSize * 8;
static public readonly int BufDataSize = Marshal.SizeOf(typeof(byte));
static public readonly int BufDataBits = BufDataSize * 8;
static public readonly int IntSize = Marshal.SizeOf(typeof(int));
static public readonly int IntBits = IntSize * 8;
static public readonly int ShortSize = Marshal.SizeOf(typeof(ushort));
// List of Commands and Functions for the QnA Compatible 3E Frame Device Memory Read/Write
// refer to manual 3-62
public const ushort MC_COMMAND_MULTIPLE_BATCH_READ = 0x0406;
public const ushort MC_COMMAND_MULTIPLE_BATCH_WRITE = 0x1406;
public const ushort MC_COMMAND_BATCH_READ = 0x0401;
public const ushort MC_COMMAND_BATCH_WRITE = 0x1401;
public const ushort MC_COMMAND_RANDOM_READ = 0x0403;
public const ushort MC_COMMAND_RANDOM_WRITE = 0x1402;
public const ushort MC_COMMAND_MONITOR_DATA_REGISTRATION = 0x0801;
public const ushort MC_COMMAND_MONITOR = 0x0802;
public const ushort MC_SUBCOMMAND_BIT_UNITS = 0x0001;
public const ushort MC_SUBCOMMAND_WORD_UNITS = 0x0000;
// List of Device code for QnACPU
// refer to manual 3-70
public const byte MC_DEVICE_CODE_INPUT_BIT = 0x9C;
public const byte MC_DEVICE_CODE_OUTPUT_BIT = 0x0D;
public const byte MC_DEVICE_CODE_INTERNAL_RELAY_BIT = 0x90;
public const byte MC_DEVICE_CODE_LATCH_RELAY_BIT = 0x92;
public const byte MC_DEVICE_CODE_ANNUNCIATOR_BIT = 0x93;
public const byte MC_DEVICE_CODE_EDGE_RELAY_BIT = 0x94;
public const byte MC_DEVICE_CODE_LINK_RELAY_BIT = 0xA0;
public const byte MC_DEVICE_CODE_DATA_REGISTER_WORD = 0xA8;
public const byte MC_DEVICE_CODE_LINK_REGISTER_WORD = 0xB4;
// refer to manual 3-4
public const ushort MC_SUBHEADER_COMMAND_MESSAGE = 0x0050;
public const ushort MC_SUBHEADER_RESPONSE_MESSAGE = 0x00D0;
// refer to manual 3-14
public const ushort MC_REQUEST_MODULE_IO_NUMBER = 0x03FF;
public const byte MC_REQUEST_MODULE_STATION_NUMBER = 0x00;
public static readonly ushort MC_CPU_MONITOR_TIMER = 0x0008; // Wait time (Unit: 250ms)
public const ushort MC_COMPLETE_CODE_SUCCESS = 0x0000;
// User Defined Constant
public static readonly ushort MC_NONE_DESIGNATE_DATA_LENGTH = 0x0000;
public static readonly int MC_SUBHEADER_SIZE = Marshal.SizeOf(MC_SUBHEADER_COMMAND_MESSAGE);
public static readonly int MC_QHEADER_COMMAND_SIZE = Marshal.SizeOf(typeof(MC_COMMAND_HEADER));
public static readonly int MC_QHEADER_RESPONSE_SIZE = Marshal.SizeOf(typeof(MC_RESPONSE_HEADER));
public static readonly int MC_BATCH_COMMAND_SIZE = Marshal.SizeOf(typeof(MC_BATCH_COMMAND));
//public static readonly int MC_POINT_BITS = sizeof(ushort) * 8;
//public const int MC_CA_WRITE_SIZE = 1024;
//public const int MC_COMMAND_DATA_SIZE = 1024;
//public const int MC_IO_BUFFER_LENGTH = 1024;
// Command Message Format
//[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
//public struct MC_DATA_FORMAT
//{
// public MC_HEADER mc_Header;
// public MC_APPLICATION_DATA mc_ApplicationData;
//};
//[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
//public struct MC_HEADER // Ethernet module adds and deletes the header
//{
//};
//[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
//public struct MC_APPLICATION_DATA
//{
// public MC_SUBHEADER mc_SubHeader;
// public MC_TEXT mc_Text;
//};
//[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
//public struct MC_SUBHEADER // 2 bytes (3E frame)
//{
// public enum SUBHEADER_TYPE : ushort
// {
// MC_COMMAND_MESSAGE = 0x0050,
// MC_RESPONSE_MESSAGE = 0x00D0
// };
// public SUBHEADER_TYPE mc_SubHeaderType;
//}
//[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
//public struct MC_TEXT // Text Command or Text Response
//{
//}
//public const byte MC_LOCAL_STATION_MCSocket_NUMBER = 0x00;
//public const byte MC_LOCAL_STATION_PC_NUMBER = 0xFF;
// refer to manual 3-7
//[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
//public struct MC_QHEADER_COMMAND
//{
// public byte nMCSocketNo;
// public byte nStationNo;
// public ushort nRequestIONumber;
// public byte nRequestStationNumber;
// public ushort nRequestDataLength;
// public ushort nCPUMonitorTimer;
//}
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MC_COMMAND_HEADER
{
public ushort ProtocolID; // MC_COMMAND_MESSAGE or MC_RESPONSE_MESSAGE
public byte NetworkID;
public byte StationID;
public ushort RequestIONumber;
public byte RequestStationNumber;
public ushort RequestDataLen;
public ushort CPUMonitorTimer;
};// MC_COMMAND_HEADER;
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MC_RESPONSE_HEADER
{
public ushort ProtocolId; //nSubheader
public byte NetworkId; //SocketNumber
public byte StationId;
public ushort RequestIoNumber;
public byte RequestStationNumber;
public ushort ResponseDataLen;
public ushort CompleteCode;
};
//[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
//public struct MC_QHEADER_RESPONSE
//{
// public ushort nSubHeader;
// public byte nMCSocketNo;
// public byte nStationNo;
// public ushort nRequestIONumber;
// public byte nRequestStationNumber;
// public ushort nResponseDataLength;
// public ushort nCompleteCode;
//}
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MC_BATCH_COMMAND
{
public ushort Command;
public ushort SubCommand;
public ushort HeadAddr;
public byte Reserved;
public byte DeviceCode;
public ushort DevicePoints;
}
//[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
//public struct MC_HEAD_DEVICE
//{
// public byte bLow;
// public byte bMid;
// public byte bHig;
// public int HeadDevice
// {
// get
// {
// return (bLow | bMid << sizeof(byte) | bHig << sizeof(byte) * 2);
// }
// set
// {
// bLow = (byte)(0x00 | value);
// bMid = (byte)(0x00 | value >> sizeof(byte));
// bHig = (byte)(0x00 | value >> sizeof(byte) * 2);
// }
// }
//}
//[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
//public struct MC_CA_RANDOM_WRITE_BIT
//{
// public ushort nCommand;
// public ushort nSubCommand;
// public byte nBitPoints;
// public DATA_RANDOM_WRITE_BIT[] data;
// [Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
// public struct DATA_RANDOM_WRITE_BIT
// {
// public ushort nHeadDeviceAddr;
// public byte nReserved;
// public byte nDeviceCode;
// public byte nSet;
// }
// byte[] ToByteArray() // can serialize with pointer type?
// {
// byte[] buffer = new byte[0];
// return buffer;
// }
//};
public static byte[] TransBoolArrayToByteData(bool[] value)
{
int length = (value.Length + 1) / 2;
byte[] buffer = new byte[length];
for (int i = 0; i < length; i++)
{
if (value[i * 2 + 0])
buffer[i] += 0x10;
if ((i * 2 + 1) < value.Length)
{
if (value[i * 2 + 1])
buffer[i] += 0x01;
}
}
return buffer;
}
public static bool[] TransByteDataToBoolArray(byte[] value, int offset, int size)
{
int count = size * 2;
bool[] result = new bool[count];
for (int i = 0; i < size; i++)
{
if ((value[i] & 0x10) == 0x10)
{
result[i * 2 + 0] = true;
}
if ((value[i] & 0x01) == 0x01)
{
result[i * 2 + 1] = true;
}
}
return result;
}
public static T ToStruct<T>(byte[] by) where T : struct
{
int objectSize = Marshal.SizeOf(typeof(T));
if (objectSize > by.Length) return default(T);
// Allocate some unmanaged memory.
IntPtr buffer = Marshal.AllocHGlobal(objectSize);
// Copy the read byte array (byte[]) into the unmanaged memory block.
Marshal.Copy(by, 0, buffer, objectSize);
// Push the memory into a new struct of type (T).
T returnStruct = (T)Marshal.PtrToStructure(buffer, typeof(T));
// Free the unmanaged memory block.
Marshal.FreeHGlobal(buffer);
return returnStruct;
}
public static object ToStruct(byte[] buffer, Type t)
{
int objectSize = Marshal.SizeOf(t);
if (objectSize > buffer.Length) return null;
// Allocate some unmanaged memory.
IntPtr buf = Marshal.AllocHGlobal(objectSize);
// Copy the read byte array (byte[]) into the unmanaged memory block.
Marshal.Copy(buffer, 0, buf, objectSize);
// Push the memory into a new struct of type (T).
object result = Marshal.PtrToStructure(buf, t);
// Free the unmanaged memory block.
Marshal.FreeHGlobal(buf);
return result;
}
public static byte[] Struct2Bytes(object o)
{
// create a new byte buffer the size of your struct
byte[] buffer = new byte[Marshal.SizeOf(o)];
// pin the buffer so we can copy data into it w/o GC collecting it
GCHandle bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
// copy the struct data into the buffer
Marshal.StructureToPtr(o, bufferHandle.AddrOfPinnedObject(), false);
// free the GC handle
bufferHandle.Free();
return buffer;
}
public static byte[] Ushort2Byte(ushort[] data)
{
int sizeofT1 = Marshal.SizeOf(typeof(ushort));
int sizeofT2 = Marshal.SizeOf(typeof(byte));
byte[] by = new byte[sizeofT1 * data.Length / sizeofT2];
for (int i = data.Length; i-- > 0;)
{
BitConverter.GetBytes(data[i]).CopyTo(by, i * 2);
}
return by;
}
public static byte[] Ushort2Byte(ushort[] data, int offset, int length)
{
int sizeofT1 = Marshal.SizeOf(typeof(ushort));
int sizeofT2 = Marshal.SizeOf(typeof(byte));
byte[] by = new byte[sizeofT1 * length / sizeofT2];
for (int i = offset+length; i-- > offset;)
{
var value = BitConverter.GetBytes(data[i]);
value.CopyTo(by, (i-offset) * 2);
}
return by;
}
public static ushort[] Byte2Ushort(byte[] data)
{
return Byte2Ushort(data, 0, data.Length);
}
public static ushort[] Byte2Ushort(byte[] data, int offset, int length)
{
System.Diagnostics.Debug.Assert(data.Length % 2 == 0);
int sizeofT1 = Marshal.SizeOf(typeof(byte));
int sizeofT2 = Marshal.SizeOf(typeof(ushort));
ushort[] us = new ushort[sizeofT1 * length / sizeofT2];
for (int i = 0; i < us.Length; i++)
{
us[i] = BitConverter.ToUInt16(data, offset + i * 2);
}
return us;
}
}
}