190 lines
6.8 KiB
C#
190 lines
6.8 KiB
C#
///
|
|
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using System.Diagnostics;
|
|
using log4net;
|
|
using Dirichlet.Numerics;
|
|
|
|
namespace TBF.Rig.ControlBoard.Uni
|
|
{
|
|
public static class OutputMessage
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(OutputMessage));
|
|
|
|
public const int PayloadLen = 38;
|
|
public const byte MessageCode = (byte)' ';
|
|
|
|
public static byte[] GetMessage(Action action, short config)
|
|
{
|
|
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] = MessageCode;
|
|
|
|
/// Command
|
|
message[4] = GetCommand(action);
|
|
message[5] = action.IsStart() ? GetStartParams(action) : action.IsStop() ? GetStopParams(action) : (byte)0;
|
|
message[6] = (action.DivId <= 0) ? (byte)0 : (byte)(action.DivId - 1);
|
|
|
|
int totalPulsesCount = (action.TotalPulsesCount < 0) ? 0 : action.TotalPulsesCount;
|
|
message[7] = (byte)(totalPulsesCount & 0xFF);
|
|
message[8] = (byte)((totalPulsesCount >> 8) & 0xFF);
|
|
message[9] = (byte)((totalPulsesCount >> 16) & 0xFF);
|
|
|
|
int massPulsesCount = (action.MassPulsesCount < 0) ? 0 : action.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
|
|
message[16] = ((action.ActionId & ActionID.ChangeRoute) != 0) ? (byte)1 : (byte)0; /// Route change flag
|
|
message[17] = (byte)(action.Route & 0xFF);
|
|
message[18] = (byte)((action.Route >> 8) & 0xFF);
|
|
message[19] = (byte)((action.Route >> 16) & 0xFF);
|
|
message[20] = (byte)((action.Route >> 24) & 0xFF);
|
|
message[21] = (byte)((action.Route >> 32) & 0xFF);
|
|
message[22] = (byte)((action.Route >> 40) & 0xFF);
|
|
message[23] = (byte)((action.Route >> 48) & 0xFF);
|
|
message[24] = (byte)((action.Route >> 56) & 0xFF);
|
|
|
|
/// DA2
|
|
message[25] = 0;
|
|
message[26] = 0;
|
|
|
|
/// Regulation valve
|
|
message[27] = (action.RegVId < 0) ? (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] = 0; /// PrudParL
|
|
message[34] = 0; /// PrudParH
|
|
|
|
message[35] = (byte)Math.Max(1, Math.Min(255, action.PID)); /// PIDRV
|
|
message[36] = 0; // (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, action.StabTime)); /// StabRV
|
|
message[38] = 0x1A; // (byte)((action.DivThreshold >> 2) & 0xFF); /// HranAK
|
|
|
|
message[39] = 0;
|
|
message[40] = 0;
|
|
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);
|
|
|
|
return message;
|
|
}
|
|
|
|
|
|
static byte GetCommand(Action action)
|
|
{
|
|
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 & (int)StartParam.EtalonMask;
|
|
|
|
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 action)
|
|
{
|
|
if (action.IsStop()) return (byte)0x20;
|
|
if ((action.ActionId & ActionID.RegVlvStop) != 0) return (byte)0x20;
|
|
return (byte)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)
|
|
}
|
|
|
|
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,
|
|
}
|
|
}
|