Sic.Framework/SimulatorCore/IoProviders/SimulatorE84.cs

307 lines
12 KiB
C#

using Aitex.Core.RT.IOCore;
using Aitex.Core.Util;
namespace MECF.Framework.Simulator.Core.IoProviders
{
public enum E84Stage
{
WaitForStation,
IDLE,
TD0, //when CS_0 wait for VALID
TA1, //CS_0 and VALID wait for L_REQ(U_REQ)
TP1, //when TA1 and TR_REQ is set
TA2, //
TP2,
TP3,
TP4,
TA3,
TP5
}
public class SimulatorE84
{
#region sequence
/*
* for loading sequence:
* (1) Active set CS_0 *ON* then set VALID *ON* for valid confirm
* A:CS_0 *ON* VALID *ON*
* (2) Passive equipment set L_REQ *ON* if the load port is ready for loading operation / U_REQ for unload
* A:CS_0 *ON* VALID *ON*
* P:L_REQ *ON \\ U_REQ *ON*
* (3) After active equipment receive the L_REQ/U_REQ *ON* set TR_REQ *ON*
* A:TR_TRQ *ON* CS_0 *ON* VALID *ON*
* P:L_REQ *ON \\ U_REQ *ON*
* (4) After passive equipment turn the READY *ON*, active equipment BUSY set to *ON* and proceed handoff operation
* A:BUSY *ON* TR_TRQ *ON* CS_0 *ON* VALID *ON*
* P:READY *ON* L_REQ *ON \\ U_REQ *ON*
* (5) When passive equipment turns the L_REQ(U_REQ) signal *OFF* when carrier is done processing
* A:BUSY *ON* TR_TRQ *ON* CS_0 *ON* VALID *ON*
* P:READY *ON*
* (6) After finish the operation and the active equipment is out of conflict area,
* active equipment turns the BUSY signal *OFF*(make sure after the L_REQ(R_REQ) was *OFF*)
* A:TR_TRQ *ON* CS_0 *ON* VALID *ON*
* P:READY *ON*
* (7) After the BUSY *OFF*, active equipment set the TR_REQ signal *OFF*
* A:CS_0 *ON* VALID *ON*
* P:READY *ON*
* (8) When finish those above, active equipment set the COMPT *ON*
* A:COMPT *ON* CS_0 *ON* VALID *ON*
* P:READY *ON*
* (9) After COMPT *ON*, passive equipment should set the READY *OFF*
* A:COMPT *ON* CS_0 *ON* VALID *ON*
* P:
* (10) After READY *OFF*, active set the signal all off
* A:
* P:
*/
#endregion
private readonly string _loadPortName;
private PeriodicJob _thread;
public readonly bool IsFloor;
public bool IsLoading => Stage == E84Stage.TP2 && lReq;
public bool IsUnLoading => Stage == E84Stage.TP2 && uReq;
public string LoadPortName => _loadPortName;
public bool LReq => lReq;
public bool UReq => uReq;
public bool Ready => ready;
public bool HoAvbl => hoAvbl;
public bool ES => es;
public bool VA => va;
public bool VS0 => vs0;
public bool VS1 => vs1;
//inputs
private bool lReq;
private bool uReq;
private bool ready;
private bool hoAvbl;
private bool es;
private bool va;
private bool vs0;
private bool vs1;
private RD_TRIG _lReq = new RD_TRIG();
private RD_TRIG _uReq = new RD_TRIG();
private RD_TRIG _ready = new RD_TRIG();
private RD_TRIG _hoAvbl = new RD_TRIG();
private RD_TRIG _es = new RD_TRIG();
private RD_TRIG _va = new RD_TRIG();
private RD_TRIG _vs0 = new RD_TRIG();
private RD_TRIG _vs1 = new RD_TRIG();
//outputs
public bool ON => IO.DI[$"DI_{_loadPortName}_ON"].Value;
public bool VALID => IO.DI[$"DI_{_loadPortName}_VALID"].Value;
public bool CS_0 => IO.DI[$"DI_{_loadPortName}_CS_0"].Value;
public bool TR_REQ => IO.DI[$"DI_{_loadPortName}_TR_REQ"].Value;
public bool BUSY => IO.DI[$"DI_{_loadPortName}_BUSY"].Value;
public bool COMPT => IO.DI[$"DI_{_loadPortName}_COMPT"].Value;
public bool CONT => IO.DI[$"DI_{_loadPortName}_CONT"].Value;
public bool AM_AVBL => IO.DI[$"DI_{_loadPortName}_AM_AVBL"].Value;
public E84Stage Stage;
private readonly DeviceTimer _timerDelay = new DeviceTimer();
public SimulatorE84(string loadPortName, bool isFloor)
{
_loadPortName = loadPortName;
IsFloor = isFloor;
_thread = new PeriodicJob(50, OnMonitor, _loadPortName, true);
Stage = E84Stage.IDLE;
if (isFloor)
IO.DI[$"DI_{_loadPortName}_AM_AVBL"].Value = true;
_thread.Start();
}
//DO_LP1_L_REQ Load Request
//DO_LP1_U_REQ Unload Request
//DO_LP1_READY Ready Signal
//DO_LP1_HO_AVBL HandOff Available Always on
//DO_LP1_ES Emergency Stop Always on
//DO_LP1_VA Vehicle Arrive
//DO_LP1_VS_O Carrier Stage 0
//DO_LP1_VS_1 Carrier Stage 1
private bool OnMonitor()
{
//inputs
lReq = IO.DO[$"DO_{_loadPortName}_L_REQ"].Value;
uReq = IO.DO[$"DO_{_loadPortName}_U_REQ"].Value;
ready = IO.DO[$"DO_{_loadPortName}_READY"].Value;
hoAvbl = IO.DO[$"DO_{_loadPortName}_HO_AVBL"].Value;
es = IO.DO[$"DO_{_loadPortName}_ES"].Value;
va = IO.DO[$"DO_{_loadPortName}_VA"].Value;
vs0 = IO.DO[$"DO_{_loadPortName}_VS_O"].Value;
vs1 = IO.DO[$"DO_{_loadPortName}_VS_1"].Value;
_lReq.CLK = lReq;
_uReq.CLK = uReq;
_ready.CLK = ready;
_hoAvbl.CLK = hoAvbl;
_es.CLK = es;
_va.CLK = va;
_vs0.CLK = vs0;
_vs1.CLK = vs1;
//outputs
if (IsFloor)
{
if (_es.T || _hoAvbl.T)
{
Stage = E84Stage.WaitForStation;
IO.DI[$"DI_{_loadPortName}_CS_0"].Value = false;
IO.DI[$"DI_{_loadPortName}_VALID"].Value = false;
IO.DI[$"DI_{_loadPortName}_TR_REQ"].Value = false;
IO.DI[$"DI_{_loadPortName}_BUSY"].Value = false;
IO.DI[$"DI_{_loadPortName}_COMPT"].Value = false;
}
else if (_es.R || _hoAvbl.R)
{
Stage = E84Stage.IDLE;
}
switch(Stage)
{
case E84Stage.IDLE:
{
if ((lReq || uReq) && (vs0 || vs1))
Stage = E84Stage.TD0;
break;
}
case E84Stage.TD0:
{
if (va)
Stage = E84Stage.TA1;
break;
}
case E84Stage.TA1:
{
IO.DI[$"DI_{_loadPortName}_TR_REQ"].Value = true;
Stage = E84Stage.TA2;
break;
}
case E84Stage.TA2:
{
if (ready)
Stage = E84Stage.TP2;
break;
}
case E84Stage.TP2:
IO.DI[$"DI_{_loadPortName}_BUSY"].Value = true;
Stage = E84Stage.TP3;
break;
case E84Stage.TP3:
{
if (!uReq || !lReq)
Stage = E84Stage.TP4;
break;
}
case E84Stage.TP4:
IO.DI[$"DI_{_loadPortName}_BUSY"].Value = false;
IO.DI[$"DI_{_loadPortName}_TR_REQ"].Value = false;
IO.DI[$"DI_{_loadPortName}_COMPT"].Value = true;
Stage = E84Stage.TA3;
break;
case E84Stage.TA3:
{
if (!ready)
Stage = E84Stage.TP5;
break;
}
case E84Stage.TP5:
IO.DI[$"DI_{_loadPortName}_CS_0"].Value = false;
IO.DI[$"DI_{_loadPortName}_VALID"].Value = false;
IO.DI[$"DI_{_loadPortName}_COMPT"].Value = false;
Stage = E84Stage.IDLE;
break;
}
}
else
{
if (_es.T || _hoAvbl.T)
{
Stage = E84Stage.WaitForStation;
IO.DI[$"DI_{_loadPortName}_CS_0"].Value = false;
IO.DI[$"DI_{_loadPortName}_VALID"].Value = false;
IO.DI[$"DI_{_loadPortName}_TR_REQ"].Value = false;
IO.DI[$"DI_{_loadPortName}_BUSY"].Value = false;
IO.DI[$"DI_{_loadPortName}_COMPT"].Value = false;
}
else if (_es.R || _hoAvbl.R)
{
Stage = E84Stage.IDLE;
}
switch(Stage)
{
case E84Stage.IDLE:
{
IO.DI[$"DI_{_loadPortName}_CS_0"].Value = true;
Stage = E84Stage.TD0;
break;
}
case E84Stage.TD0:
{
IO.DI[$"DI_{_loadPortName}_VALID"].Value = true;
Stage = E84Stage.TA1;
break;
}
case E84Stage.TA1:
{
if (lReq || uReq)
Stage = E84Stage.TP1;
break;
}
case E84Stage.TP1:
IO.DI[$"DI_{_loadPortName}_TR_REQ"].Value = true;
Stage = E84Stage.TA2;
break;
case E84Stage.TA2:
{
if (ready)
Stage = E84Stage.TP2;
break;
}
case E84Stage.TP2:
IO.DI[$"DI_{_loadPortName}_BUSY"].Value = true;
Stage = E84Stage.TP3;
break;
case E84Stage.TP3:
{
if (!uReq || !lReq)
Stage = E84Stage.TP4;
break;
}
case E84Stage.TP4:
IO.DI[$"DI_{_loadPortName}_BUSY"].Value = false;
IO.DI[$"DI_{_loadPortName}_TR_REQ"].Value = false;
IO.DI[$"DI_{_loadPortName}_COMPT"].Value = true;
Stage = E84Stage.TA3;
break;
case E84Stage.TA3:
{
if (!ready)
Stage = E84Stage.TP5;
break;
}
case E84Stage.TP5:
IO.DI[$"DI_{_loadPortName}_CS_0"].Value = false;
IO.DI[$"DI_{_loadPortName}_VALID"].Value = false;
IO.DI[$"DI_{_loadPortName}_COMPT"].Value = false;
Stage = E84Stage.IDLE;
break;
}
}
return true;
}
}
}