using System; using System.Collections.Generic; using System.Linq; using DTS.Common; using DTS.Common.Enums.DASFactory; using DTS.Common.ICommunication; namespace DTS.DASLib.Command.SLICE { public abstract class Ptp1588Commands : CommandBase { public enum PtpClockType { SlaveTransparentClock = 0, MasterTransparentClock = 1, BoundaryClock = 2, }; public enum PtpMode { Slave = 0, Master = 1, Auto = 2, }; public enum PtpDelayMechanism { Undefined = 0, E2E = 1, P2P = 2, }; public enum PtpSyncStatus { NotSynced = 0, Synced = 1, }; public enum PtpTimestampUnits { AutoTrigger = 1, Event = 3, AdcStart = 2, Pps = 5, }; protected enum Commands { Reserved = 0x00, SetMode = 0x01, GetMode = 0x02, SetOptions = 0x03, GetSyncStatus = 0x04, SetTime = 0x05, GetTime = 0x06, GetAutoTriggerTime = 0x07, SetAutoTriggerTime = 0x08, GetTimestamp = 0x09, SetTriggerTimestamping = 0x0A, SetAdcClockFrquency = 0x0B, RunClockAdjustmentCalibration = 0x0C, SetClockSyncConfig = 0x0d, GetClockSyncConfig = 0x0e, }; protected abstract Commands _Command { get; } protected Ptp1588Commands(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Type = CommandPacket.CommandType.Ptp1588; command.SetCommand((byte)_Command, _Command.ToString()); } protected Ptp1588Commands(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Type = CommandPacket.CommandType.Ptp1588; command.SetCommand((byte)_Command, _Command.ToString()); } public static string ToTimestampString(uint s, uint ns) { return $"{s}.{ns,9:000000000}"; } } public class Ptp1588SetMode : Ptp1588Commands { const int COMMAND_PAYLOAD_SIZE = 4; protected override Commands _Command => Commands.SetMode; private ushort _clock_type = 0; private ushort _delay_mechanism = 0; public void SetClockType(PtpClockType clockType) { _clock_type = (ushort)clockType; command.SetParameter(0, _clock_type); } public void SetDelayMechanism(PtpDelayMechanism delayMechanism) { _delay_mechanism = (ushort)delayMechanism; command.SetParameter(2, _delay_mechanism); } public Ptp1588SetMode(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[COMMAND_PAYLOAD_SIZE]; } public Ptp1588SetMode(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[COMMAND_PAYLOAD_SIZE]; } public override void CommandToString(ref List> list) { base.CommandToString(ref list); list.Add(new List() { $"Mode: {_clock_type} DelayMechanism: {_delay_mechanism}" }); } } public class Ptp1588GetMode : Ptp1588Commands { private const int COMMAND_PAYLOAD_SIZE = 4; protected override Commands _Command => Commands.GetMode; private ushort _clock_type = 0; private ushort _delay_mechanism = 0; public PtpClockType ClockType => (PtpClockType)_clock_type; public PtpDelayMechanism DelayMechanism => (PtpDelayMechanism)_delay_mechanism; public Ptp1588GetMode(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[COMMAND_PAYLOAD_SIZE]; } public Ptp1588GetMode(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[COMMAND_PAYLOAD_SIZE]; } protected override CommandReceiveAction WholePackage() { if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError) { response.GetParameter(0, out _clock_type); response.GetParameter(2, out _delay_mechanism); } return CommandReceiveAction.StopReceiving; } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List() { $"ClockType: {ClockType}" }); } } public class Ptp1588GetSyncStatus : Ptp1588Commands { protected override Commands _Command => Commands.GetSyncStatus; private int _ofm; private int _adj; public PtpSyncStatus SyncStatus { get; private set; } public int OFM => _ofm; public int FreqAdj => _adj; public Ptp1588GetSyncStatus(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[5]; } public Ptp1588GetSyncStatus(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[5]; } protected override CommandReceiveAction WholePackage() { if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError) { if (response.ParameterLength > 6) { response.GetParameter(0, out byte status); SyncStatus = (PtpSyncStatus)status; response.GetParameter(1, out _ofm); response.GetParameter(5, out _adj); } else { SyncStatus = PtpSyncStatus.NotSynced; } } return CommandReceiveAction.StopReceiving; } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List() { $"Status: {SyncStatus} OFM: {OFM} ns Adj: {FreqAdj}" }); } } public class Ptp1588SetTime : Ptp1588Commands { protected override Commands _Command => Commands.SetTime; private uint _s; private uint _ns; public void SetSeconds(uint seconds) { _s = seconds; command.SetParameter(0, _s); } public void SetNanoseconds(uint ns) { _ns = ns; command.SetParameter(4, _ns); } public Ptp1588SetTime(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[8]; } public Ptp1588SetTime(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[8]; } public override void CommandToString(ref List> list) { base.CommandToString(ref list); list.Add(new List() { $"Time: {_s}.{_ns,9:000000000}" }); } } public class Ptp1588GetTime : Ptp1588Commands { protected override Commands _Command => Commands.GetTime; private uint _s; private uint _ns; public uint Seconds => _s; public uint Nanoseconds => _ns; public string Timestamp => ToTimestampString(_s, _ns); public Ptp1588GetTime(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[8]; } public Ptp1588GetTime(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[8]; } protected override CommandReceiveAction WholePackage() { if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError) { response.GetParameter(0, out _s); response.GetParameter(4, out _ns); } return CommandReceiveAction.StopReceiving; } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List() { Timestamp }); } } public class Ptp1588SetAutoTriggerTime : Ptp1588Commands { protected override Commands _Command => Commands.SetAutoTriggerTime; private uint _s; private uint _ns; public void SetSeconds(uint seconds) { _s = seconds; command.SetParameter(0, _s); } public void SetNanoseconds(uint ns) { _ns = ns; command.SetParameter(4, _ns); } public Ptp1588SetAutoTriggerTime(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[8]; } public Ptp1588SetAutoTriggerTime(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[8]; } public override void CommandToString(ref List> list) { base.CommandToString(ref list); list.Add(new List() { $"Timestamp: {_s}.{_ns,9:000000000}" }); } } public class Ptp1588GetAutoTriggerTime : Ptp1588Commands { protected override Commands _Command => Commands.GetAutoTriggerTime; private uint _s; private uint _ns; public uint Seconds => _s; public uint Nanoseconds => _ns; public string Timestamp => ToTimestampString(_s, _ns); public Ptp1588GetAutoTriggerTime(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[8]; } public Ptp1588GetAutoTriggerTime(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[8]; } protected override CommandReceiveAction WholePackage() { if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError) { response.GetParameter(0, out _s); response.GetParameter(4, out _ns); } return CommandReceiveAction.StopReceiving; } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List() { Timestamp }); } } public class Ptp1588GetTimestamp : Ptp1588Commands { protected override Commands _Command => Commands.GetTimestamp; private byte _timestamp_unit; private uint _s; private uint _ns; private byte _timestamp_valid; public PtpTimestampUnits TimestampUnit { set { _timestamp_unit = (byte)value; command.SetParameter(0, _timestamp_unit); } } public uint Seconds => _s; public uint Nanoseconds => _ns; public bool IsValid => Convert.ToBoolean(_timestamp_valid); public string Timestamp => ToTimestampString(_s, _ns); public Ptp1588GetTimestamp(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[1]; } public Ptp1588GetTimestamp(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[1]; } protected override CommandReceiveAction WholePackage() { if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError) { response.GetParameter(0, out _timestamp_valid); response.GetParameter(1, out _s); response.GetParameter(5, out _ns); } return CommandReceiveAction.StopReceiving; } public override void CommandToString(ref List> list) { base.CommandToString(ref list); list.Add(new List() { $"Timestamp Unit: {_timestamp_unit}" }); } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List() { $"Timestamp: {Timestamp}" }); } } public class Ptp1588SetEnableTimestamping : Ptp1588Commands { protected override Commands _Command => Commands.SetTriggerTimestamping; private byte _enable; public void SetEnable(bool enable) { _enable = Convert.ToByte(enable); command.SetParameter(0, _enable); } public Ptp1588SetEnableTimestamping(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[1]; } public Ptp1588SetEnableTimestamping(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[1]; } public override void CommandToString(ref List> list) { base.CommandToString(ref list); list.Add(new List() { $"Enable: {_enable}" }); } } public class Ptp1588SetAdcClockFrequency : Ptp1588Commands { private const int COMMAND_PAYLOAD_SIZE = 4; protected override Commands _Command => Commands.SetAdcClockFrquency; private uint _requestedFrequency; private uint _actualFrequency; public uint RequestedFrequency { set { _requestedFrequency = value; command.SetParameter(0, _requestedFrequency); } } public Ptp1588SetAdcClockFrequency(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[COMMAND_PAYLOAD_SIZE]; } public Ptp1588SetAdcClockFrequency(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[COMMAND_PAYLOAD_SIZE]; } protected override CommandReceiveAction WholePackage() { if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError) { response.GetParameter(0, out _actualFrequency); } return CommandReceiveAction.StopReceiving; } public override void CommandToString(ref List> list) { base.CommandToString(ref list); list.Add(new List() { $"Requested Frequency: {_requestedFrequency}" }); } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List() { $"Actual Frequency: {_actualFrequency}" }); } } public class Ptp1588RunClockAdjustmentCalibration : Ptp1588Commands { private const int COMMAND_PAYLOAD_SIZE = 3; protected override Commands _Command => Commands.RunClockAdjustmentCalibration; private byte _saveAtribute = 0; private ushort _durationSeconds = 60; public void SetDuration(ushort duration) { _durationSeconds = duration; command.SetParameter(0, _durationSeconds); } public void SetSaveAttribute(bool b) { _saveAtribute = Convert.ToByte(b); command.SetParameter(2, _saveAtribute); } public Ptp1588RunClockAdjustmentCalibration(Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[COMMAND_PAYLOAD_SIZE]; } public Ptp1588RunClockAdjustmentCalibration(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[COMMAND_PAYLOAD_SIZE]; } public override void CommandToString(ref List> list) { base.CommandToString(ref list); list.Add(new List() { $"Duration: {_durationSeconds} Save Attribute {_saveAtribute}" }); } } public class QueryClockSyncStatus : Ptp1588Commands { protected override Commands _Command { get { return Commands.GetClockSyncConfig; } } private byte _inputstate; public byte InputState { get => _inputstate; } private byte _outputstate; public byte OutputState { get => _outputstate; } private byte _clockSyncProfile; private byte _syncstatus; public byte SyncStatus { get => _syncstatus; } public ClockSyncProfile ClockSyncProfile => (ClockSyncProfile)_clockSyncProfile; private readonly List _inputSources = new List(); public List InputSources => _inputSources; private readonly List _outputSources = new List(); public List OutputSources => _outputSources; public IDictionary InputSyncStatus { get; } = new Dictionary(); public QueryClockSyncStatus(Common.Interface.DASFactory.ICommunication sock) : base(sock) { MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.QueryClockSyncStatus); } protected override CommandReceiveAction WholePackage() { if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError && response.ParameterLength > 1) { response.GetParameter(0, out _clockSyncProfile); response.GetParameter(1, out _inputstate); response.GetParameter(2, out _outputstate); response.GetParameter(3, out _syncstatus); var sources = Enum.GetValues(typeof(InputClockSource)).Cast().ToList(); for (int i = 1; i < sources.Count; i++) { // use source as a mask on status to get the current state (same bit structure) InputSyncStatus.Add(sources[i], (_syncstatus & (byte)sources[i]) == (byte)sources[i]); } } return CommandReceiveAction.StopReceiving; } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List() { string.Format("Input source(s): {0}", string.Join(", ", InputSources.Select(source => source.ToString()))) }); lines.Add(new List() { string.Format("Output source(s): {0}", string.Join(", ", OutputSources.Select(source => source.ToString()))) }); lines.Add(new List() { string.Format("Input source synced: {0}", string.Join(", ", InputSyncStatus.Select(statuspair => statuspair.Key.ToString() + "-" + statuspair.Value.ToString()))) }); } } public class SetClockSyncConfig : Ptp1588Commands { protected override Commands _Command { get { return Commands.SetClockSyncConfig; } } public SetClockSyncConfig(Common.Interface.DASFactory.ICommunication sock) : base(sock) { MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.SetClockSyncConfig); } protected override CommandReceiveAction WholePackage() { return CommandReceiveAction.StopReceiving; } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List() { ResponseStatus == DFConstantsAndEnums.CommandStatus.StatusNoError ? "Set Clock Config Success" : "Set Clock Config Failure" }); } } }