Communication: Add GPTPStatus
parent
c4ce803d62
commit
dc0f16b1d2
|
|
@ -246,6 +246,7 @@ set(SRC_FILES
|
|||
communication/message/linmessage.cpp
|
||||
communication/message/livedatamessage.cpp
|
||||
communication/message/tc10statusmessage.cpp
|
||||
communication/message/gptpstatusmessage.cpp
|
||||
communication/packet/flexraypacket.cpp
|
||||
communication/packet/canpacket.cpp
|
||||
communication/packet/a2bpacket.cpp
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ static constexpr const char* DISK_NOT_CONNECTED = "The program tried to access a
|
|||
static constexpr const char* UNEXPECTED_RESPONSE = "Received an unexpected or invalid response from the device.";
|
||||
static constexpr const char* LIN_SETTINGS_NOT_AVAILABLE = "LIN settings are not available for this device.";
|
||||
static constexpr const char* MODE_NOT_FOUND = "The mode was not found.";
|
||||
static constexpr const char* GPTP_NOT_SUPPORTED = "GPTP clock synchronization is not supported on this device.";
|
||||
|
||||
// Transport Errors
|
||||
static constexpr const char* FAILED_TO_READ = "A read operation failed.";
|
||||
|
|
@ -185,6 +186,7 @@ static constexpr const char* VSA_OTHER_ERROR = "Unknown error in VSA read API.";
|
|||
static constexpr const char* TOO_MANY_EVENTS = "Too many events have occurred. The list has been truncated.";
|
||||
static constexpr const char* UNKNOWN = "An unknown internal error occurred.";
|
||||
static constexpr const char* INVALID = "An invalid internal error occurred.";
|
||||
|
||||
const char* APIEvent::DescriptionForType(Type type) {
|
||||
switch(type) {
|
||||
// API Errors
|
||||
|
|
@ -345,6 +347,8 @@ const char* APIEvent::DescriptionForType(Type type) {
|
|||
return GETIFADDRS_ERROR;
|
||||
case Type::SendToError:
|
||||
return SEND_TO_ERROR;
|
||||
case Type::GPTPNotSupported:
|
||||
return GPTP_NOT_SUPPORTED;
|
||||
|
||||
// FTD3XX
|
||||
case Type::FTOK:
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ pybind11_add_module(icsneopy
|
|||
icsneopy/communication/message/linmessage.cpp
|
||||
icsneopy/communication/message/tc10statusmessage.cpp
|
||||
icsneopy/communication/message/mdiomessage.cpp
|
||||
icsneopy/communication/message/gptpstatusmessage.cpp
|
||||
icsneopy/communication/message/callback/messagecallback.cpp
|
||||
icsneopy/communication/message/filter/messagefilter.cpp
|
||||
icsneopy/device/device.cpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/gptpstatusmessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_gptpstatusmessage(pybind11::module_& m) {
|
||||
pybind11::class_<GPTPStatus, std::shared_ptr<GPTPStatus>, Message> gptpStatus(m, "GPTPStatus");
|
||||
|
||||
pybind11::class_<GPTPStatus::Timestamp>(gptpStatus, "Timestamp")
|
||||
.def_readonly("seconds", &GPTPStatus::Timestamp::seconds)
|
||||
.def_readonly("nanoseconds", &GPTPStatus::Timestamp::nanoseconds)
|
||||
.def("to_seconds", &GPTPStatus::Timestamp::toSeconds, pybind11::call_guard<pybind11::gil_scoped_release>());
|
||||
|
||||
pybind11::class_<GPTPStatus::ScaledNanoSeconds>(gptpStatus, "ScaledNanoSeconds")
|
||||
.def_readonly("nanosecondsMSB", &GPTPStatus::ScaledNanoSeconds::nanosecondsMSB)
|
||||
.def_readonly("nanosecondsLSB", &GPTPStatus::ScaledNanoSeconds::nanosecondsLSB)
|
||||
.def_readonly("fractionalNanoseconds", &GPTPStatus::ScaledNanoSeconds::fractionalNanoseconds);
|
||||
|
||||
pybind11::class_<GPTPStatus::PortID>(gptpStatus, "PortID")
|
||||
.def_readonly("clockIdentity", &GPTPStatus::PortID::clockIdentity)
|
||||
.def_readonly("portNumber", &GPTPStatus::PortID::portNumber);
|
||||
|
||||
pybind11::class_<GPTPStatus::ClockQuality>(gptpStatus, "ClockQuality")
|
||||
.def_readonly("clockClass", &GPTPStatus::ClockQuality::clockClass)
|
||||
.def_readonly("clockAccuracy", &GPTPStatus::ClockQuality::clockAccuracy)
|
||||
.def_readonly("offsetScaledLogVariance", &GPTPStatus::ClockQuality::offsetScaledLogVariance);
|
||||
|
||||
pybind11::class_<GPTPStatus::SystemID>(gptpStatus, "SystemID")
|
||||
.def_readonly("priority1", &GPTPStatus::SystemID::priority1)
|
||||
.def_readonly("clockQuality", &GPTPStatus::SystemID::clockQuality)
|
||||
.def_readonly("priority2", &GPTPStatus::SystemID::priority2)
|
||||
.def_readonly("clockID", &GPTPStatus::SystemID::clockID);
|
||||
|
||||
pybind11::class_<GPTPStatus::PriorityVector>(gptpStatus, "PriorityVector")
|
||||
.def_readonly("sysID", &GPTPStatus::PriorityVector::sysID)
|
||||
.def_readonly("stepsRemoved", &GPTPStatus::PriorityVector::stepsRemoved)
|
||||
.def_readonly("portID", &GPTPStatus::PriorityVector::portID)
|
||||
.def_readonly("portNumber", &GPTPStatus::PriorityVector::portNumber);
|
||||
|
||||
pybind11::class_<GPTPStatus::ParentDS>(gptpStatus, "ParentDS")
|
||||
.def_readonly("parentPortIdentity", &GPTPStatus::ParentDS::parentPortIdentity)
|
||||
.def_readonly("cumulativeRateRatio", &GPTPStatus::ParentDS::cumulativeRateRatio)
|
||||
.def_readonly("grandmasterIdentity", &GPTPStatus::ParentDS::grandmasterIdentity)
|
||||
.def_readonly("gmClockQualityClockClass", &GPTPStatus::ParentDS::gmClockQualityClockClass)
|
||||
.def_readonly("gmClockQualityClockAccuracy", &GPTPStatus::ParentDS::gmClockQualityClockAccuracy)
|
||||
.def_readonly("gmClockQualityOffsetScaledLogVariance", &GPTPStatus::ParentDS::gmClockQualityOffsetScaledLogVariance)
|
||||
.def_readonly("gmPriority1", &GPTPStatus::ParentDS::gmPriority1)
|
||||
.def_readonly("gmPriority2", &GPTPStatus::ParentDS::gmPriority2);
|
||||
|
||||
pybind11::class_<GPTPStatus::CurrentDS>(gptpStatus, "CurrentDS")
|
||||
.def_readonly("stepsRemoved", &GPTPStatus::CurrentDS::stepsRemoved)
|
||||
.def_readonly("offsetFromMaster", &GPTPStatus::CurrentDS::offsetFromMaster)
|
||||
.def_readonly("lastgmPhaseChange", &GPTPStatus::CurrentDS::lastgmPhaseChange)
|
||||
.def_readonly("lastgmFreqChange", &GPTPStatus::CurrentDS::lastgmFreqChange)
|
||||
.def_readonly("gmTimeBaseIndicator", &GPTPStatus::CurrentDS::gmTimeBaseIndicator)
|
||||
.def_readonly("gmChangeCount", &GPTPStatus::CurrentDS::gmChangeCount)
|
||||
.def_readonly("timeOfLastgmChangeEvent", &GPTPStatus::CurrentDS::timeOfLastgmChangeEvent)
|
||||
.def_readonly("timeOfLastgmPhaseChangeEvent", &GPTPStatus::CurrentDS::timeOfLastgmPhaseChangeEvent)
|
||||
.def_readonly("timeOfLastgmFreqChangeEvent", &GPTPStatus::CurrentDS::timeOfLastgmFreqChangeEvent);
|
||||
|
||||
gptpStatus.def_readonly("currentTime", &GPTPStatus::currentTime)
|
||||
.def_readonly("gmPriority", &GPTPStatus::gmPriority)
|
||||
.def_readonly("msOffsetNs", &GPTPStatus::msOffsetNs)
|
||||
.def_readonly("isSync", &GPTPStatus::isSync)
|
||||
.def_readonly("linkStatus", &GPTPStatus::linkStatus)
|
||||
.def_readonly("linkDelayNS", &GPTPStatus::linkDelayNS)
|
||||
.def_readonly("selectedRole", &GPTPStatus::selectedRole)
|
||||
.def_readonly("asCapable", &GPTPStatus::asCapable)
|
||||
.def_readonly("isSyntonized", &GPTPStatus::isSyntonized)
|
||||
.def_readonly("lastRXSyncTS", &GPTPStatus::lastRXSyncTS)
|
||||
.def_readonly("currentDS", &GPTPStatus::currentDS)
|
||||
.def_readonly("parentDS", &GPTPStatus::parentDS);
|
||||
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
|
@ -31,7 +31,8 @@ void init_message(pybind11::module_& m) {
|
|||
.value("LiveData", Message::Type::LiveData)
|
||||
.value("HardwareInfo", Message::Type::HardwareInfo)
|
||||
.value("TC10Status", Message::Type::TC10Status)
|
||||
.value("AppError", Message::Type::AppError);
|
||||
.value("AppError", Message::Type::AppError)
|
||||
.value("GPTPStatus", Message::Type::GPTPStatus);
|
||||
|
||||
message.def(pybind11::init<Message::Type>());
|
||||
message.def_readonly("type", &Message::type);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ void init_device(pybind11::module_& m) {
|
|||
.def("request_tc10_wake", &Device::requestTC10Wake, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("request_tc10_sleep", &Device::requestTC10Sleep, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_tc10_status", &Device::getTC10Status, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_gptp_status", &Device::getGPTPStatus, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("__repr__", &Device::describe);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ void init_canmessage(pybind11::module_&);
|
|||
void init_ethernetmessage(pybind11::module_&);
|
||||
void init_linmessage(pybind11::module_&);
|
||||
void init_tc10statusmessage(pybind11::module_&);
|
||||
void init_gptpstatusmessage(pybind11::module_&);
|
||||
void init_mdiomessage(pybind11::module_&);
|
||||
void init_device(pybind11::module_&);
|
||||
void init_messagefilter(pybind11::module_&);
|
||||
|
|
@ -36,6 +37,7 @@ PYBIND11_MODULE(icsneopy, m) {
|
|||
init_ethernetmessage(m);
|
||||
init_linmessage(m);
|
||||
init_tc10statusmessage(m);
|
||||
init_gptpstatusmessage(m);
|
||||
init_mdiomessage(m);
|
||||
init_messagefilter(m);
|
||||
init_messagecallback(m);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "icsneo/communication/message/diskdatamessage.h"
|
||||
#include "icsneo/communication/message/hardwareinfo.h"
|
||||
#include "icsneo/communication/message/tc10statusmessage.h"
|
||||
#include "icsneo/communication/message/gptpstatusmessage.h"
|
||||
#include "icsneo/communication/message/apperrormessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/device/device.h"
|
||||
|
|
@ -285,11 +286,11 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
|||
}
|
||||
case Network::NetID::ExtendedCommand: {
|
||||
|
||||
if(packet->data.size() < sizeof(ExtendedResponseMessage::PackedGenericResponse))
|
||||
if(packet->data.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
|
||||
break; // Handle as a raw message, might not be a generic response
|
||||
|
||||
const auto& resp = *reinterpret_cast<ExtendedResponseMessage::PackedGenericResponse*>(packet->data.data());
|
||||
switch(resp.header.command) {
|
||||
const auto& resp = *reinterpret_cast<ExtendedResponseMessage::ResponseHeader*>(packet->data.data());
|
||||
switch(resp.command) {
|
||||
case ExtendedCommand::GetComponentVersions:
|
||||
result = ComponentVersionPacket::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
|
|
@ -299,15 +300,23 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
|||
case ExtendedCommand::GenericBinaryInfo:
|
||||
result = GenericBinaryStatusPacket::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::GenericReturn:
|
||||
result = std::make_shared<ExtendedResponseMessage>(resp.command, resp.returnCode);
|
||||
case ExtendedCommand::GenericReturn: {
|
||||
if(packet->data.size() < sizeof(ExtendedResponseMessage::PackedGenericResponse))
|
||||
break;
|
||||
const auto& packedResp = *reinterpret_cast<ExtendedResponseMessage::PackedGenericResponse*>(packet->data.data());
|
||||
result = std::make_shared<ExtendedResponseMessage>(packedResp.command, packedResp.returnCode);
|
||||
return true;
|
||||
}
|
||||
case ExtendedCommand::LiveData:
|
||||
result = HardwareLiveDataPacket::DecodeToMessage(packet->data, report);
|
||||
return true;
|
||||
case ExtendedCommand::GetTC10Status:
|
||||
result = TC10StatusMessage::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::GetGPTPStatus: {
|
||||
result = GPTPStatus::DecodeToMessage(packet->data, report);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
// No defined handler, treat this as a RawMessage
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,219 @@
|
|||
#include <icsneo/communication/message/gptpstatusmessage.h>
|
||||
#include <icsneo/communication/message/extendedresponsemessage.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace icsneo {
|
||||
typedef double float64;
|
||||
typedef int64_t time_interval;
|
||||
typedef uint64_t _clock_identity;
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct port_identity {
|
||||
_clock_identity clock_identity;
|
||||
uint16_t port_number;
|
||||
};
|
||||
|
||||
struct _scaled_ns {
|
||||
int16_t nanoseconds_msb;
|
||||
int64_t nanoseconds_lsb;
|
||||
int16_t fractional_nanoseconds;
|
||||
};
|
||||
|
||||
struct _clock_quality {
|
||||
uint8_t clock_class;
|
||||
uint8_t clock_accuracy;
|
||||
uint16_t offset_scaled_log_variance;
|
||||
};
|
||||
|
||||
struct system_identity {
|
||||
uint8_t priority_1;
|
||||
struct _clock_quality clock_quality;
|
||||
uint8_t priority_2;
|
||||
_clock_identity clock_identity;
|
||||
};
|
||||
|
||||
struct _timestamp {
|
||||
uint16_t seconds_msb;
|
||||
uint32_t seconds_lsb;
|
||||
uint32_t nanoseconds;
|
||||
};
|
||||
|
||||
struct priority_vector {
|
||||
struct system_identity sysid;
|
||||
uint16_t steps_removed;
|
||||
struct port_identity portid;
|
||||
uint16_t port_number;
|
||||
};
|
||||
|
||||
|
||||
// IEEE 802.1AS-2020 14.3
|
||||
// This is a read-only data structure
|
||||
struct _current_ds {
|
||||
uint16_t steps_removed;
|
||||
time_interval offset_from_master;
|
||||
struct _scaled_ns last_gm_phase_change;
|
||||
float64 last_gm_freq_change;
|
||||
uint16_t gm_time_base_indicator;
|
||||
uint32_t gm_change_count;
|
||||
uint32_t time_of_last_gm_change_event;
|
||||
uint32_t time_of_last_gm_phase_change_event;
|
||||
uint32_t time_of_last_gm_freq_change_event;
|
||||
};
|
||||
|
||||
// IEEE 802.1AS-2020 14.4
|
||||
// This is a read-only data structure
|
||||
struct _parent_ds {
|
||||
struct port_identity parent_port_identity;
|
||||
int32_t cumulative_rate_ratio;
|
||||
_clock_identity grandmaster_identity;
|
||||
uint8_t gm_clock_quality_clock_class;
|
||||
uint8_t gm_clock_quality_clock_accuracy;
|
||||
uint16_t gm_clock_quality_offset_scaled_log_variance;
|
||||
uint8_t gm_priority1;
|
||||
uint8_t gm_priority2;
|
||||
};
|
||||
|
||||
struct _GPTPStatus
|
||||
{
|
||||
struct _timestamp current_time;
|
||||
struct priority_vector gm_priority;
|
||||
int64_t ms_offset_ns;
|
||||
uint8_t is_sync;
|
||||
uint8_t link_status;
|
||||
int64_t link_delay_ns;
|
||||
uint8_t selected_role;
|
||||
uint8_t as_capable;
|
||||
uint8_t is_syntonized;
|
||||
struct _timestamp last_rx_sync_ts; // t2 in IEEE 1588-2019 Figure-16
|
||||
struct _current_ds current_ds;
|
||||
struct _parent_ds parent_ds;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
static void SetField(GPTPStatus::Timestamp& output, const _timestamp& input) {
|
||||
output.seconds = ((uint64_t)(input.seconds_msb) << 32) | ((uint64_t)input.seconds_lsb);
|
||||
output.nanoseconds = input.nanoseconds;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::PortID& output, const port_identity& input) {
|
||||
output.clockIdentity = input.clock_identity;
|
||||
output.portNumber = input.port_number;
|
||||
}
|
||||
static void SetField(GPTPStatus::ClockQuality& output, const _clock_quality& input) {
|
||||
output.clockClass = input.clock_class;
|
||||
output.clockAccuracy = input.clock_accuracy;
|
||||
output.offsetScaledLogVariance = input.offset_scaled_log_variance;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::SystemID& output, const system_identity& input) {
|
||||
output.priority1 = input.priority_1;
|
||||
SetField(output.clockQuality, input.clock_quality);
|
||||
output.priority2 = input.priority_2;
|
||||
output.clockID = input.clock_identity;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::ScaledNanoSeconds& output, const _scaled_ns& input) {
|
||||
output.nanosecondsMSB = input.nanoseconds_msb;
|
||||
output.nanosecondsLSB = input.nanoseconds_lsb;
|
||||
output.fractionalNanoseconds = input.fractional_nanoseconds;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::PriorityVector& output, const priority_vector& input) {
|
||||
SetField(output.sysID, input.sysid);
|
||||
output.stepsRemoved = input.steps_removed;
|
||||
SetField(output.portID, input.portid);
|
||||
output.portNumber = input.port_number;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::CurrentDS& output, const _current_ds& input) {
|
||||
output.stepsRemoved = input.steps_removed;
|
||||
output.offsetFromMaster = input.offset_from_master;
|
||||
SetField(output.lastgmPhaseChange, input.last_gm_phase_change);
|
||||
output.lastgmFreqChange = input.last_gm_freq_change;
|
||||
output.gmTimeBaseIndicator = input.gm_time_base_indicator;
|
||||
output.gmChangeCount = input.gm_change_count;
|
||||
output.timeOfLastgmChangeEvent = input.time_of_last_gm_change_event;
|
||||
output.timeOfLastgmPhaseChangeEvent = input.time_of_last_gm_phase_change_event;
|
||||
output.timeOfLastgmFreqChangeEvent = input.time_of_last_gm_freq_change_event;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::ParentDS& output, const _parent_ds& input) {
|
||||
SetField(output.parentPortIdentity, input.parent_port_identity);
|
||||
output.cumulativeRateRatio = input.cumulative_rate_ratio;
|
||||
output.grandmasterIdentity = input.grandmaster_identity;
|
||||
output.gmClockQualityClockClass = input.gm_clock_quality_clock_class;
|
||||
output.gmClockQualityClockAccuracy = input.gm_clock_quality_clock_accuracy;
|
||||
output.gmClockQualityOffsetScaledLogVariance = input.gm_clock_quality_offset_scaled_log_variance;
|
||||
output.gmPriority1 = input.gm_priority1;
|
||||
output.gmPriority2 = input.gm_priority2;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(uint8_t& output, const uint8_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(uint16_t& output, const uint16_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(uint32_t& output, const uint32_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(uint64_t& output, const uint64_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(int8_t& output, const int8_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(int16_t& output, const int16_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(int32_t& output, const int32_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(int64_t& output, const int64_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
std::shared_ptr<GPTPStatus> GPTPStatus::DecodeToMessage(std::vector<uint8_t>& bytes, const device_eventhandler_t&) {
|
||||
|
||||
// The following does not lead to overflow since we only call this function if it has at least ResponseHeader length bytes
|
||||
std::shared_ptr<GPTPStatus> res = std::make_shared<GPTPStatus>();
|
||||
auto* header = reinterpret_cast<ExtendedResponseMessage::ResponseHeader*>(bytes.data());
|
||||
uint16_t length = header->length;
|
||||
_GPTPStatus* input = reinterpret_cast<_GPTPStatus*>(bytes.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
|
||||
|
||||
#define CheckLengthAndSet(output, input) if(length >= sizeof(decltype(input))) { \
|
||||
SetField(output, input); \
|
||||
length -= sizeof(decltype(input)); \
|
||||
} else {\
|
||||
memset(&output, 0, sizeof(decltype(output))); \
|
||||
length = 0; \
|
||||
res->shortFormat = true; \
|
||||
}
|
||||
|
||||
CheckLengthAndSet(res->currentTime, input->current_time);
|
||||
CheckLengthAndSet(res->gmPriority, input->gm_priority);
|
||||
CheckLengthAndSet(res->msOffsetNs, input->ms_offset_ns);
|
||||
CheckLengthAndSet(res->isSync, input->is_sync);
|
||||
CheckLengthAndSet(res->linkStatus, input->link_status);
|
||||
CheckLengthAndSet(res->linkDelayNS, input->link_delay_ns);
|
||||
CheckLengthAndSet(res->selectedRole, input->selected_role);
|
||||
CheckLengthAndSet(res->asCapable, input->as_capable);
|
||||
CheckLengthAndSet(res->isSyntonized, input->is_syntonized);
|
||||
CheckLengthAndSet(res->lastRXSyncTS, input->last_rx_sync_ts);
|
||||
CheckLengthAndSet(res->currentDS, input->current_ds);
|
||||
CheckLengthAndSet(res->parentDS, input->parent_ds);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3335,3 +3335,34 @@ std::optional<TC10StatusMessage> Device::getTC10Status(Network::NetID network) {
|
|||
|
||||
return *typed;
|
||||
}
|
||||
|
||||
std::optional<GPTPStatus> Device::getGPTPStatus(std::chrono::milliseconds timeout) {
|
||||
if(!supportsGPTP()) {
|
||||
report(APIEvent::Type::GPTPNotSupported, APIEvent::Severity::Error);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if(!isOpen()) {
|
||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::shared_ptr<Message> response = com->waitForMessageSync(
|
||||
[this](){
|
||||
return com->sendCommand(ExtendedCommand::GetGPTPStatus, {});
|
||||
},
|
||||
std::make_shared<MessageFilter>(Message::Type::GPTPStatus),
|
||||
timeout
|
||||
);
|
||||
|
||||
if(!response) {
|
||||
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
|
||||
return std::nullopt;
|
||||
}
|
||||
auto retMsg = std::static_pointer_cast<GPTPStatus>(response);
|
||||
if(!retMsg) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return *retMsg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ public:
|
|||
LINSettingsNotAvailable = 0x2053,
|
||||
ModeNotFound = 0x2054,
|
||||
AppErrorParsingFailed = 0x2055,
|
||||
GPTPNotSupported = 0x2056,
|
||||
|
||||
// Transport Events
|
||||
FailedToRead = 0x3000,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ enum class ExtendedCommand : uint16_t {
|
|||
StartDHCPServer = 0x0016,
|
||||
StopDHCPServer = 0x0017,
|
||||
GetSupportedFeatures = 0x0018,
|
||||
GetGPTPStatus = 0x0019,
|
||||
GetComponentVersions = 0x001A,
|
||||
Reboot = 0x001C,
|
||||
SetRootFSEntryFlags = 0x0027,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
#ifndef __GPTPSTATUSMESSAGE_H_
|
||||
#define __GPTPSTATUSMESSAGE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "icsneo/communication/message/message.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class GPTPStatus : public Message {
|
||||
public:
|
||||
typedef uint64_t TimeInterval;
|
||||
typedef uint64_t ClockID;
|
||||
|
||||
struct Timestamp {
|
||||
uint64_t seconds;
|
||||
uint32_t nanoseconds;
|
||||
|
||||
double toSeconds() const {
|
||||
static constexpr double billion = 1e9;
|
||||
return (double)seconds + ((double)nanoseconds) / billion;
|
||||
}
|
||||
};
|
||||
|
||||
struct ScaledNanoSeconds {
|
||||
int16_t nanosecondsMSB; // The most significant bits
|
||||
int64_t nanosecondsLSB; // The least significant bits
|
||||
int16_t fractionalNanoseconds; // Fractional part
|
||||
};
|
||||
|
||||
struct PortID {
|
||||
ClockID clockIdentity;
|
||||
uint16_t portNumber;
|
||||
};
|
||||
struct ClockQuality {
|
||||
uint8_t clockClass;
|
||||
uint8_t clockAccuracy;
|
||||
uint16_t offsetScaledLogVariance;
|
||||
};
|
||||
|
||||
struct SystemID {
|
||||
uint8_t priority1;
|
||||
ClockQuality clockQuality;
|
||||
uint8_t priority2;
|
||||
ClockID clockID;
|
||||
};
|
||||
|
||||
struct PriorityVector {
|
||||
SystemID sysID;
|
||||
uint16_t stepsRemoved;
|
||||
PortID portID;
|
||||
uint16_t portNumber;
|
||||
};
|
||||
|
||||
struct ParentDS {
|
||||
PortID parentPortIdentity;
|
||||
int32_t cumulativeRateRatio;
|
||||
ClockID grandmasterIdentity;
|
||||
uint8_t gmClockQualityClockClass;
|
||||
uint8_t gmClockQualityClockAccuracy;
|
||||
uint16_t gmClockQualityOffsetScaledLogVariance;
|
||||
uint8_t gmPriority1;
|
||||
uint8_t gmPriority2;
|
||||
};
|
||||
|
||||
struct CurrentDS {
|
||||
uint16_t stepsRemoved;
|
||||
TimeInterval offsetFromMaster;
|
||||
ScaledNanoSeconds lastgmPhaseChange;
|
||||
double lastgmFreqChange;
|
||||
uint16_t gmTimeBaseIndicator;
|
||||
uint32_t gmChangeCount;
|
||||
uint32_t timeOfLastgmChangeEvent;
|
||||
uint32_t timeOfLastgmPhaseChangeEvent;
|
||||
uint32_t timeOfLastgmFreqChangeEvent;
|
||||
};
|
||||
|
||||
GPTPStatus() : Message(Message::Type::GPTPStatus) {}
|
||||
static std::shared_ptr<GPTPStatus> DecodeToMessage(std::vector<uint8_t>& bytes, const device_eventhandler_t& report);
|
||||
|
||||
Timestamp currentTime;
|
||||
PriorityVector gmPriority;
|
||||
int64_t msOffsetNs;
|
||||
uint8_t isSync;
|
||||
uint8_t linkStatus;
|
||||
int64_t linkDelayNS;
|
||||
uint8_t selectedRole;
|
||||
uint8_t asCapable;
|
||||
uint8_t isSyntonized;
|
||||
Timestamp lastRXSyncTS; // t2 in IEEE 1588-2019 Figure-16
|
||||
CurrentDS currentDS;
|
||||
ParentDS parentDS;
|
||||
|
||||
bool shortFormat = false; // Set to true if the above variables weren't set (some firmware versions do not contain all the above variables)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -41,6 +41,7 @@ public:
|
|||
HardwareInfo = 0x8010,
|
||||
TC10Status = 0x8011,
|
||||
AppError = 0x8012,
|
||||
GPTPStatus = 0x8013
|
||||
};
|
||||
|
||||
Message(Type t) : type(t) {}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
#include "icsneo/disk/vsa/vsa.h"
|
||||
#include "icsneo/disk/vsa/vsaparser.h"
|
||||
#include "icsneo/communication/message/versionmessage.h"
|
||||
#include "icsneo/communication/message/gptpstatusmessage.h"
|
||||
|
||||
|
||||
#define ICSNEO_FINDABLE_DEVICE_BASE(className, type) \
|
||||
|
|
@ -728,11 +729,14 @@ public:
|
|||
|
||||
virtual bool supportsTC10() const { return false; }
|
||||
|
||||
virtual bool supportsGPTP() const { return false; }
|
||||
|
||||
bool requestTC10Wake(Network::NetID network);
|
||||
|
||||
bool requestTC10Sleep(Network::NetID network);
|
||||
|
||||
std::optional<TC10StatusMessage> getTC10Status(Network::NetID network);
|
||||
std::optional<GPTPStatus> getGPTPStatus(std::chrono::milliseconds timeout = std::chrono::milliseconds(100));
|
||||
|
||||
protected:
|
||||
bool online = false;
|
||||
|
|
|
|||
|
|
@ -444,20 +444,21 @@ typedef struct LOGGER_SETTINGS_t
|
|||
#define RAD_GPTP_NUM_PORTS 1 // 1 because only supported as gPTP endpoint
|
||||
typedef struct RAD_GPTP_SETTINGS_t
|
||||
{
|
||||
uint32_t neighborPropDelayThresh;//ns
|
||||
uint32_t sys_phc_sync_interval;//ns
|
||||
int8_t logPDelayReqInterval;// log2ms
|
||||
int8_t logSyncInterval;// log2ms
|
||||
int8_t logAnnounceInterval;// log2ms
|
||||
uint32_t neighborPropDelayThresh; //ns
|
||||
uint32_t sys_phc_sync_interval; //ns
|
||||
int8_t logPDelayReqInterval; // log2ms
|
||||
int8_t logSyncInterval; // log2ms
|
||||
int8_t logAnnounceInterval; // log2ms
|
||||
uint8_t profile;
|
||||
uint8_t priority1;
|
||||
uint8_t clockclass;
|
||||
uint8_t clockaccuracy;
|
||||
uint8_t priority2;
|
||||
uint16_t offset_scaled_log_variance;
|
||||
uint8_t gPTPportRole[RAD_GPTP_NUM_PORTS];
|
||||
uint8_t portEnable[RAD_GPTP_NUM_PORTS];
|
||||
uint8_t rsvd[16];
|
||||
uint8_t gptpPortRole;
|
||||
uint8_t gptpEnabledPort;
|
||||
uint8_t enableClockSyntonization;
|
||||
uint8_t rsvd[15];
|
||||
} RAD_GPTP_SETTINGS;//36 Bytes with RAD_GPTP_NUM_PORTS = 1
|
||||
#define RAD_GPTP_SETTINGS_SIZE 36
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ protected:
|
|||
|
||||
bool supportsLiveData() const override { return true; }
|
||||
|
||||
bool supportsGPTP() const override { return true; }
|
||||
|
||||
std::optional<MemoryAddress> getCoreminiStartAddressFlash() const override {
|
||||
return 33*1024*1024;
|
||||
}
|
||||
|
|
@ -90,6 +92,7 @@ protected:
|
|||
bool supportsEraseMemory() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ public:
|
|||
}
|
||||
|
||||
bool supportsComponentVersions() const override { return true; }
|
||||
bool supportsGPTP() const override { return true; }
|
||||
|
||||
protected:
|
||||
NeoVIRED2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ public:
|
|||
}
|
||||
|
||||
size_t getEthernetActivationLineCount() const override { return 1; }
|
||||
bool supportsGPTP() const override { return true; }
|
||||
|
||||
protected:
|
||||
RADA2B(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||
|
|
@ -77,6 +78,7 @@ protected:
|
|||
std::optional<MemoryAddress> getCoreminiStartAddressSD() const override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ public:
|
|||
}
|
||||
|
||||
bool getEthPhyRegControlSupported() const override { return true; }
|
||||
bool supportsGPTP() const override { return true; }
|
||||
|
||||
protected:
|
||||
using Device::Device;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public:
|
|||
bool getEthPhyRegControlSupported() const override { return true; }
|
||||
|
||||
bool supportsTC10() const override { return true; }
|
||||
bool supportsGPTP() const override { return true; }
|
||||
|
||||
protected:
|
||||
RADComet3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ public:
|
|||
}
|
||||
|
||||
size_t getEthernetActivationLineCount() const override { return 1; }
|
||||
bool supportsGPTP() const override { return true; }
|
||||
|
||||
protected:
|
||||
RADGalaxy(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ public:
|
|||
size_t getEthernetActivationLineCount() const override { return 1; }
|
||||
|
||||
bool supportsTC10() const override { return true; }
|
||||
bool supportsGPTP() const override { return true; }
|
||||
|
||||
protected:
|
||||
RADGalaxy2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public:
|
|||
|
||||
bool getEthPhyRegControlSupported() const override { return true; }
|
||||
bool supportsTC10() const override { return true; }
|
||||
bool supportsGPTP() const override { return true; }
|
||||
|
||||
protected:
|
||||
RADGigastar(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ namespace icsneo
|
|||
bool getEthPhyRegControlSupported() const override { return true; }
|
||||
|
||||
bool supportsTC10() const override { return true; }
|
||||
bool supportsGPTP() const override { return true; }
|
||||
|
||||
protected:
|
||||
RADGigastar2(neodevice_t neodevice, const driver_factory_t &makeDriver) : Device(neodevice)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ public:
|
|||
ICSNEO_FINDABLE_DEVICE(RADMars, DeviceType::RADMars, "GL");
|
||||
|
||||
size_t getEthernetActivationLineCount() const override { return 1; }
|
||||
bool supportsGPTP() const override { return true; }
|
||||
|
||||
protected:
|
||||
RADMars(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue