Files
CMS-MTConn/MTC_Sim/SCMCncLib/thdNcEsaGvKvara.cs
T
Samuele E. Locatelli 4fc970e06a completata lettura allarmi
2016-06-03 10:10:38 +02:00

420 lines
16 KiB
C#

using System;
using System.Collections.Generic;
//using System.Windows.Threading;
using System.Threading;
using System.Runtime.InteropServices;
using System.Linq;
using System.Text;
using IniFiles;
namespace SCMCncLib
{
#region ESA_DATA_STRUCTURES
// public unsafe struct TS_REG
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct TS_REG
{
byte board;
byte iBaseReg;
UInt16 wType;
UInt32 iSharedId;
UInt32 iNum;
UInt32 iMax;
UInt32 iSiz;
UInt32 iOff;
UInt32 ChkSum;
}
#endregion
/// <summary>
/// Class for EsaGv Nc device
/// </summary>
public class thdNcEsaGvKvara : thdNcBase
{
private UInt16 ReadNumber;
private UInt16 WriteNumber;
private UInt16 VAreaByteSize;
private UInt16 ETKAreaByteSize;
private UInt16 AlarmByteSize;
private string SysLink = "";
private string DefCn = "";
private int iChannel;
private int iError;
private string StatusAddressName;
private TS_REG StatusAddress;
private string CommandsAddressName;
private TS_REG CommandsAddress;
private string VAreaAddressName;
private TS_REG VAreaAddress;
private string ETKAreaAddressName;
private TS_REG ETKAreaAddress;
/// <summary>
/// Memorie a 4 byte (32 bit)
/// </summary>
public UInt32[] PLC_MemoryRead;
public UInt32[] PLC_MemoryWrite;
/// <summary>
/// Area V: memoria temp di UINT di 4 byte (32 bit)
/// </summary>
public UInt32[] PLC_MemAreaV_tmp;
/// <summary>
/// Area ETK: memoria temp di UINT di 4 byte (32 bit)
/// </summary>
public UInt32[] PLC_MemAreaETK_tmp;
/// <summary>
/// Area Allarmi: memoria temp di UINT di 4 byte (32 bit)
/// </summary>
public UInt32[] PLC_MemAreaAlarm_tmp;
/// <summary>
/// memorie a 1 byte (8 bit) x area V (status e valori vari)
/// </summary>
public Byte[] PLC_MemoryAreaV;
/// <summary>
/// memorie a 1 byte (8 bit) x area ETK (status e valori vari)
/// </summary>
public Byte[] PLC_MemoryAreaETK;
/// <summary>
/// memorie a 1 byte (8 bit) x area Allarmi (V[300] - 256 bit)
/// </summary>
public Byte[] PLC_MemoryAreaAllarmi;
// esa constants
#region ESA_PLC_CONSTANTS
private const UInt32 MAX_PATH = 256;
#endregion
#region ESA_DLL_IMPORT_FUNCTIONS
[DllImport("KvCom3x", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "_ConvComunicationChannel@4")]
private static extern int ConvComunicationChannel([MarshalAs(UnmanagedType.LPStr)] string sChannelType);
[DllImport("KvCom3x", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "_init_board@8")]
private static extern int init_board([MarshalAs(UnmanagedType.LPStr)]string defcn_name, int ChannelType);
[DllImport("KvCom3x", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "_exit_board@0")]
private static extern int exit_board();
[DllImport("KvCom3x", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "_get_reg_by_name@8")]
private static extern int get_reg_by_name([MarshalAs(UnmanagedType.LPStr)]string name, ref TS_REG pReg);
[DllImport("KvCom3x", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "_read_regbuffer@16")]
private static extern int read_regbuffer(ref TS_REG pReg, UInt16 Offset, UInt16 Count, [MarshalAs(UnmanagedType.LPArray)] UInt32[] pDst);
//[DllImport("KvCom3x", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint="_read_regdword@12")]
//function read_regdword(pReg:LPTS_REG; Offset:WORD; dwpVal:LPDWORD);
[DllImport("KvCom3x", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "_write_regbuffer@16")]
private static extern int write_regbuffer(ref TS_REG pReg, UInt16 Offset, UInt16 Count, [MarshalAs(UnmanagedType.LPArray)] UInt32[] pSrc);
[DllImport("VKEnv", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern void ENVGetProfileString(
[MarshalAs(UnmanagedType.LPStr)] string AppName,
[MarshalAs(UnmanagedType.LPStr)] string KeyName,
[MarshalAs(UnmanagedType.LPStr)] string Default,
//[MarshalAs(UnmanagedType.LPArray)] byte[] ReturnedString,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder ReturnedString,
UInt32 nSize);
#endregion
/// <summary>
/// After calling this method the search path is:
/// 1 - The directory from which the application loaded
/// 2 - The directory specified by the lpPathName parameter
/// 3 - The system directory (The name of this directory is System32)
/// 4 - The 16-bit system directory (The name of this directory is System)
/// 5 - The Windows directory
/// 6 - The directories that are listed in the PATH environment variable
/// </summary>
/// <param name="lpPathName"></param>
/// <returns></returns>
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetDllDirectory(string lpPathName);
/// <summary>
/// Initializes a new instance of the <see cref="thdNcEsaGvKvara"/> class.
/// </summary>
/// <param name="fIni">The f ini.</param>
public thdNcEsaGvKvara(IniFile fIni) : base(fIni)
{
DeviceType = NC_DEVICE_TYPE.ESAGV_KVARA;
StringBuilder tempS = new StringBuilder(Convert.ToInt32(MAX_PATH));
// set executable path
SetDllDirectory(fIni.ReadString("NC", "SysExe", "C:\\KVARA\\EXE"));
// communication type
string defValue = fIni.ReadString("NC", "SysLink", "SIMULATO");
ENVGetProfileString("SYS", "LINK", defValue, tempS, MAX_PATH);
//bufferH.Free();
SysLink = tempS.ToString();
// communication channel
iChannel = ConvComunicationChannel(SysLink);
// definition path
defValue = fIni.ReadString("NC", "SysDefCn", "C:\\KVARA\\DISCOI");
ENVGetProfileString("SYS", "DEFCN", defValue, tempS, MAX_PATH);
DefCn = tempS.ToString() + "\\defcn";
//StrCat(DefCn, "\\defcn");
// !!! 2016.05.25 inutile forse? riguarda l'engine 3d...
//hack: metto fisso... OCCHIO son 4 byte x area SIM...
ReadNumber = 265;
WriteNumber = 265;
VAreaByteSize = 32;
ETKAreaByteSize = 32;
AlarmByteSize = 32;
#if false
// store read and write number of bytes
ReadNumber = Convert.ToUInt16(mwEngine.MemoryManager.NrByteToRead / 4);
if (mwEngine.MemoryManager.NrByteToRead != ReadNumber * 4) ReadNumber++;
WriteNumber = Convert.ToUInt16(mwEngine.MemoryManager.NrByteToWrite / 4);
if (mwEngine.MemoryManager.NrByteToWrite != WriteNumber * 4) WriteNumber++;
#endif
StatusAddressName = fIni.ReadString("NC", "StatusAddress", "SIMWRITE[0]");
CommandsAddressName = fIni.ReadString("NC", "CommandsAddress", "SIMREAD[0]");
VAreaAddressName= fIni.ReadString("NC", "VAreaAddress", "SIMREAD[0]");
/**************************************************
* Creazione buffers letture memoria
**************************************************/
// create read buffer 32bit
PLC_MemoryRead = new UInt32[ReadNumber];
// create write buffer 32bit
PLC_MemoryWrite = new UInt32[WriteNumber];
// creazione buffers a 32bit
PLC_MemAreaV_tmp = new UInt32[VAreaByteSize/4];
PLC_MemAreaETK_tmp = new UInt32[ETKAreaByteSize/4];
PLC_MemAreaAlarm_tmp = new UInt32[AlarmByteSize/4];
// creo array duali in bytes...
PLC_MemoryAreaV = new Byte[VAreaByteSize];
PLC_MemoryAreaETK = new Byte[ETKAreaByteSize];
PLC_MemoryAreaAllarmi = new Byte[AlarmByteSize];
if (!Connect())
Disconnect();
}
#if false
/// <summary>
/// Initializes a new instance of the <see cref="thdNcEsaGvKvara"/> class.
/// </summary>
/// <param name="e">The e.</param>
/// <param name="fIni">The f ini.</param>
/// <param name="form">The form.</param>
public thdNcEsaGvKvara(MWEngine e, IniFile fIni, XSimMainWindow form)
: base(e, fIni, form)
{
DeviceType = NC_DEVICE_TYPE.ESAGV_KVARA;
StringBuilder tempS = new StringBuilder(Convert.ToInt32(MAX_PATH));
//string buffer = " ";
//byte[] byteS = new UTF8Encoding().GetBytes(buffer);
//GCHandle bufferH = GCHandle.Alloc(byteS, GCHandleType.Pinned);
//IntPtr tempS = Marshal.UnsafeAddrOfPinnedArrayElement(byteS, 0);
//byte[] tempS = new byte[MAX_PATH];
// set executable path
SetDllDirectory(fIni.ReadString("NC", "SysExe", "C:\\KVARA\\EXE"));
// communication type
string defValue = fIni.ReadString("NC", "SysLink", "SIMULATO");
ENVGetProfileString("SYS", "LINK", defValue, tempS, MAX_PATH);
//bufferH.Free();
SysLink = tempS.ToString();
// communication channel
iChannel = ConvComunicationChannel(SysLink);
// definition path
defValue = fIni.ReadString("NC", "SysDefCn", "C:\\KVARA\\DISCOI");
ENVGetProfileString("SYS", "DEFCN", defValue, tempS, MAX_PATH);
DefCn = tempS.ToString() + "\\defcn";
//StrCat(DefCn, "\\defcn");
// store read and write number of bytes
ReadNumber = Convert.ToUInt16(mwEngine.MemoryManager.NrByteToRead / 4);
if (mwEngine.MemoryManager.NrByteToRead != ReadNumber * 4) ReadNumber++;
WriteNumber = Convert.ToUInt16(mwEngine.MemoryManager.NrByteToWrite / 4);
if (mwEngine.MemoryManager.NrByteToWrite != WriteNumber * 4) WriteNumber++;
StatusAddressName = fIni.ReadString("NC", "StatusAddress", "SIMWRITE[0]");
CommandsAddressName = fIni.ReadString("NC", "CommandsAddress", "SIMREAD[0]");
// create read buffer
PLC_MemoryRead = new UInt32[ReadNumber];
// create write buffer
PLC_MemoryWrite = new UInt32[WriteNumber];
if (!Connect())
Disconnect();
}
#endif // false
/// <summary>
/// Thread main execution
/// </summary>
public override void Execute()
{
while (!requestStop)
{
if (Connected)
{
// load data from NC
ReadBuffer();
// if requested make a pause
if (PlcDelay > 0)
Thread.Sleep(PlcDelay);
}
else if (!Connected)
{
// wait 5 sec and retry connection
Thread.Sleep(5000);
Connect();
}
else
Thread.Sleep(500);
}
if (Connected) Disconnect();
Finished = true;
}
#if false
/// <summary>
/// Thread main execution
/// </summary>
public override void Execute()
{
while (!requestStop)
{
if (Connected && mwEngine.ModelLoaded)
{
// load data from NC
ReadBuffer();
// write data to NC (if needed)
if (mwEngine.MemoryManager.CheckWriteRequest())
{
// copy memory to old before sending to device to avoid losing data
mwEngine.MemoryManager.NotifyWriteDone();
WriteBuffer();
}
// if requested make a pause
if (PlcDelay > 0)
Thread.Sleep(PlcDelay);
}
else if (!Connected && mwEngine.ModelLoaded)
{
// wait 5 sec and retry connection
Thread.Sleep(5000);
Connect();
}
else
Thread.Sleep(500);
}
if (Connected) Disconnect();
Finished = true;
}
#endif
/// <summary>
/// Reads the buffer.
/// </summary>
public void ReadBuffer()
{
// lettura buffer dal CN
iError = read_regbuffer(ref StatusAddress, 0, ReadNumber, PLC_MemoryRead);
// leggo da posizione memorie Vcome TS_REG
iError = read_regbuffer(ref VAreaAddress, 68, VAreaByteSize, PLC_MemAreaV_tmp);
// leggo da posizione memorie ETK TS_REG
iError = read_regbuffer(ref ETKAreaAddress, 68, ETKAreaByteSize, PLC_MemAreaETK_tmp);
// leggo da posizione memorie Vcome TS_REG
iError = read_regbuffer(ref VAreaAddress, 300, AlarmByteSize, PLC_MemAreaAlarm_tmp);
// copio in array a byte...
Buffer.BlockCopy(PLC_MemAreaV_tmp, 0, PLC_MemoryAreaV, 0, VAreaByteSize);
Buffer.BlockCopy(PLC_MemAreaETK_tmp, 0, PLC_MemoryAreaETK, 0, ETKAreaByteSize);
Buffer.BlockCopy(PLC_MemAreaAlarm_tmp, 0, PLC_MemoryAreaAllarmi, 0, AlarmByteSize);
}
/// <summary>
/// Writes the buffer.
/// </summary>
private void WriteBuffer()
{
#if false
System.Buffer.BlockCopy(mwEngine.MemoryManager.WriteMemory, 0, PLC_MemoryWrite, 0, mwEngine.MemoryManager.NrByteToWrite);
iError = write_regbuffer(ref CommandsAddress, 0, WriteNumber, PLC_MemoryWrite);
#endif
}
/// <summary>
/// Connects to device.
/// </summary>
/// <returns>True if connection is ok</returns>
public bool Connect()
{
// inizializzazione comunicazione
iError = init_board(DefCn, iChannel);
// inizializzo i registri di lettura e scrittura
if (iError == 0)
iError = get_reg_by_name(StatusAddressName, ref StatusAddress);
if (iError == 0)
iError = get_reg_by_name(CommandsAddressName, ref CommandsAddress);
if (iError == 0)
iError = get_reg_by_name(VAreaAddressName, ref VAreaAddress);
Connected = (iError == 0);
WriteConnectionStatus();
return Connected;
}
/// <summary>
/// Disconnects device.
/// </summary>
public void Disconnect()
{
iError = exit_board();
WriteConnectionStatus();
}
/// <summary>
/// Esa virtual Nc needs 2ms of multimedia timer to work in real time
/// </summary>
/// <returns></returns>
public bool CheckMultimediaTimer()
{
int minimumPeriod = TimePeriod.MinimumPeriod;
//int maximumPeriod = TimePeriod.MaximumPeriod;
return ((minimumPeriod <= 2) && (minimumPeriod > 0));
}
}
}