246 lines
9.3 KiB
C#
246 lines
9.3 KiB
C#
///
|
|
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using System.Diagnostics;
|
|
using log4net;
|
|
using Dirichlet.Numerics;
|
|
using Common;
|
|
using System.Web.Routing;
|
|
|
|
namespace TBF.Rig.ControlBoard.Uni
|
|
{
|
|
public static class OutputMessage
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(OutputMessage));
|
|
|
|
public const int PayloadLen = 38;
|
|
|
|
|
|
static Action arguments = new Action();
|
|
///
|
|
static void FetchArguments(Action combinedAction)
|
|
{
|
|
foreach (var aId in (ActionID[])Enum.GetValues(typeof(ActionID)))
|
|
{
|
|
if ((combinedAction.ActionId & aId) != 0) arguments.SetArgs(combinedAction, aId);
|
|
}
|
|
}
|
|
|
|
|
|
public static string Caption()
|
|
{
|
|
// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
|
return " [. .. .. ..Cmd P1 P2 (pulses) (mass.p) xx (cfg) Xg (------- route -------) (DA2) RV Rpar1 Rpar2 St (DA1) PID x ST Div Sum ]";
|
|
}
|
|
|
|
public static byte[] GetMessage(Action action, short config, UInt128 bitsToInvert)
|
|
{
|
|
FetchArguments(action);
|
|
|
|
byte[] message = new byte[PayloadLen + 5]; /// headed 3 bytes, checksum 2 bytes
|
|
|
|
/// Header + message code (4 bytes)
|
|
message[0] = Const.STX;
|
|
message[1] = 1; /// Control board addres
|
|
message[2] = (byte)PayloadLen; /// Payload length
|
|
message[3] = (byte)' '; /// Message code
|
|
|
|
/// Command
|
|
message[4] = GetCommand(action);
|
|
message[5] = action.IsStart() ? GetStartParams(action) : action.IsStop() ? GetStopParams(action) : (byte)0;
|
|
message[6] = (byte)(((arguments.DivId <= 0) ? 0 : (arguments.DivId - 1)) + ((arguments.FlowMId > 7) ? arguments.FlowMId : 0) + (action.IsDelayedStart ? 128 : 0));
|
|
|
|
int totalPulsesCount = (arguments.TotalPulsesCount < 0) ? 0 : arguments.TotalPulsesCount;
|
|
message[7] = (byte)(totalPulsesCount & 0xFF);
|
|
message[8] = (byte)((totalPulsesCount >> 8) & 0xFF);
|
|
message[9] = (byte)((totalPulsesCount >> 16) & 0xFF);
|
|
|
|
int massPulsesCount = (arguments.MassPulsesCount < 0) ? 0 : arguments.MassPulsesCount;
|
|
message[10] = (byte)(massPulsesCount & 0xFF);
|
|
message[11] = (byte)((massPulsesCount >> 8) & 0xFF);
|
|
message[12] = (byte)((massPulsesCount >> 16) & 0xFF);
|
|
|
|
message[13] = 0;
|
|
|
|
message[14] = (byte)(config & 0xff);
|
|
message[15] = (byte)((config >> 8) & 0xff);
|
|
|
|
/// Route
|
|
UInt128 routeOut = arguments.Route ^ bitsToInvert;
|
|
message[16] = ((action.ActionId & ActionID.ChangeRoute) != 0) ? (byte)1 : (byte)0; /// Route change flag
|
|
message[17] = (byte)(routeOut & 0xFF); /// RV0 .. RV3
|
|
message[18] = (byte)((routeOut >> 8) & 0xFF); /// RV4 .. RV7
|
|
message[19] = (byte)((routeOut >> 16) & 0xFF);
|
|
message[20] = (byte)((routeOut >> 24) & 0xFF); /// Div1 .. Div5
|
|
message[21] = (byte)((routeOut >> 32) & 0xFF);
|
|
message[22] = (byte)((routeOut >> 40) & 0xFF); /// F
|
|
message[23] = (byte)((routeOut >> 48) & 0xFF); /// G
|
|
message[24] = (byte)((routeOut >> 56) & 0xFF); /// H
|
|
|
|
/// DA2
|
|
message[25] = 0;
|
|
message[26] = 0;
|
|
|
|
/// Regulation valve
|
|
message[27] = (action.RegVId < 0 || (action.RegVId == TBF.Rig.Uni.RegValveAnalog.RegValve.RVAnalogIdx && action.RegVMode == RegValveMode.TargetFrequency))
|
|
? (byte)0 : (byte)(action.RegVId | (int)action.RegVMode);
|
|
message[28] = (byte)(action.RVMovePar1 & 0xFF);
|
|
message[29] = (byte)((action.RVMovePar1 >> 8) & 0xFF);
|
|
message[30] = (byte)(action.RVMovePar2 & 0xFF);
|
|
message[31] = (byte)((action.RVMovePar2 >> 8) & 0xFF);
|
|
message[32] = GetRVStopParam(action);
|
|
|
|
/// DA1
|
|
message[33] = (byte)(arguments.InitDacVal & 0xFF);
|
|
message[34] = (byte)((arguments.InitDacVal >> 8) & 0xFF);
|
|
|
|
message[35] = (byte)Math.Max(1, Math.Min(255, arguments.PID)); /// PIDRV
|
|
message[36] = (byte)Math.Max(4, Math.Min(255, action.TolerRV)); /// TolerRV (4..20 mA reg.valve only)
|
|
message[37] = (byte)Math.Max(0, Math.Min(255, arguments.StabTime)); /// StabRV
|
|
message[38] = (byte)((arguments.DivThreshold >> 2) & 0xFF);
|
|
|
|
//---
|
|
message[39] = (byte)((action.RegulationMinStep << 4) & 0xFF); // ak 0 = koli kompatibilite, 1-6 = hodnoty prislusne pre spodnu saturaciu vypinacej periody casu
|
|
message[40] = (byte)((action.RegulationMinStep << 4) & 0xFF);
|
|
//---
|
|
/*int x = 0;
|
|
if (action.RegVId == 1 || action.RegVId == 2) x = 3;
|
|
else if (action.RegVId == 3 || action.RegVId == 4) x = 5;
|
|
else if (action.RegVId == 5 || action.RegVId == 5) x = 3;
|
|
message[39] = (byte)((x << 4) & 0xFF);
|
|
message[40] = (byte)((x << 4) & 0xFF);*/
|
|
/*//---
|
|
message[39] = 0x50; // ak 0 = koli kompatibilite, 1-6 = hodnoty prislusne pre spodnu saturaciu vypinacej periody casu
|
|
message[40] = 0x50;
|
|
//---*/
|
|
|
|
Debug.Assert(40 == PayloadLen + 2);
|
|
|
|
/// Checksum (2 bytes)
|
|
int checksum = 0;
|
|
for (int i = 1; i < PayloadLen + 3; i++) checksum += message[i];
|
|
message[PayloadLen + 3] = (byte)(checksum & 0xFF);
|
|
message[PayloadLen + 4] = (byte)((checksum >> 8) & 0xFF);
|
|
|
|
log.Info("");
|
|
|
|
return message;
|
|
}
|
|
|
|
|
|
static byte GetCommand(Action action)
|
|
{
|
|
if (action.StartStop == Command.DelayStartOrStop)
|
|
{
|
|
return (byte)Command.None;
|
|
}
|
|
else if (action.StartStop == Command.Start && action.IsProlonged)
|
|
{
|
|
return (byte)(Command.Start | Command.ProlongedFlag);
|
|
}
|
|
else
|
|
{
|
|
return (byte)action.StartStop;
|
|
}
|
|
}
|
|
|
|
static byte GetStartParams(Action action)
|
|
{
|
|
int param = (action.FlowMId <= 7) ? action.FlowMId : 0;
|
|
|
|
if (action.IsDivUsed) param |= (int)StartParam.DiverterStart;
|
|
if (action.IsSyncMethod) param |= (int)StartParam.SynchroMethod;
|
|
if (action.IsStartStop) param |= (int)StartParam.StartStopMethod;
|
|
|
|
return (byte)param;
|
|
}
|
|
|
|
static byte GetStopParams(Action action)
|
|
{
|
|
return (byte)StopDevs.All;
|
|
}
|
|
|
|
static byte GetRVStopParam(Action a)
|
|
{
|
|
if (a.IsStop() || (a.ActionId & ActionID.RegVlvStop) != 0)
|
|
{
|
|
return (byte)0x20;
|
|
}
|
|
|
|
else if ((a.ActionId & ActionID.SetFlow) != 0 && a.RegVId == TBF.Rig.Uni.RegValveAnalog.RegValve.RVAnalogIdx)
|
|
{
|
|
return (byte)0x42;
|
|
}
|
|
|
|
/*else
|
|
{
|
|
return (a.RegulationMinStep >= 0 || a.RegulationMinStep <= 6)?(byte)(a.RegulationMinStep << 4):(byte)(7<<4);
|
|
}*/
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
public enum Command : byte
|
|
{
|
|
None = 0, /// Request data only
|
|
Start = 1,
|
|
Stop = 2,
|
|
GetDiverterTransitionData = 4,
|
|
GetScopeAnalyzerData = 7,
|
|
ResetScopeAnalyzer = 8,
|
|
GetSwitchCounterData = 9,
|
|
///
|
|
ProlongedFlag = 0x10, /// Not a command of its own, a valid command is (byte)(Command.Start | Command.ProlongedFlag)
|
|
DelayStartOrStop = 255, /// Prevents other start or stop command, results in Command.None when creating a message
|
|
}
|
|
|
|
public enum StartParam : byte
|
|
{
|
|
EtalonMask = 0x07,
|
|
DiverterStart = 0x08,
|
|
SynchroMethod = 0x10,
|
|
DirectGateStart = 0x20, /// ???
|
|
StartStopMethod = 0x40,
|
|
CalibrationMode = 0x80,
|
|
}
|
|
|
|
public enum StopDevs : byte
|
|
{
|
|
None = 0,
|
|
Reference = 0x01, /// bit 0
|
|
Diverter = 0x02, /// bit 1
|
|
GatePulse = 0x08, /// bit 3
|
|
TimeMeasurement = 0x10, /// bit 4
|
|
BypassDevCoupled2Div = 0x20, /// bit 5
|
|
RegValveRegulation = 0x80, /// bit 7
|
|
All = 0x9B,
|
|
}
|
|
|
|
public enum ValveChgFlag : byte
|
|
{
|
|
DoNotChange = 0,
|
|
Change = 1,
|
|
SendPressureMeterAddresses = 2,
|
|
}
|
|
|
|
public enum RegValveMode : byte
|
|
{
|
|
None = 0,
|
|
TargetFrequency = 0x10, /// Low and high frequency limits (0..2000Hz,0..2200Hz) are specified
|
|
TargetPosition = 0x20, /// Low and high position (=DAC value) limits (0..100%) are specified
|
|
Stop = 0x30, /// Stop regulation
|
|
PulseWidth = 0x40, /// Pulse width 0.05 .. 2 sec. ... opening and closing (opening=0x40, closing=0xC0)
|
|
NegPulseWidth = 0x80, /// Pulse width 0.05 .. 2 sec. ... closing (closing=0xC0)
|
|
}
|
|
|
|
public enum RegValveState : byte
|
|
{
|
|
Idle = 0,
|
|
PwOrFreqRegul = 2,
|
|
DacValueRegul = 3,
|
|
}
|
|
}
|