Settings: Add GPTP
parent
2d0b0c63ed
commit
299766403f
|
|
@ -12,6 +12,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <chrono>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
@ -787,6 +788,43 @@ icsneoc2_error_t icsneoc2_device_tc10_status_get(const icsneoc2_device_t* device
|
||||||
return icsneoc2_error_success;
|
return icsneoc2_error_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_device_supports_gptp(const icsneoc2_device_t* device, bool* supported) {
|
||||||
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if(!supported) {
|
||||||
|
return icsneoc2_error_invalid_parameters;
|
||||||
|
}
|
||||||
|
*supported = device->device->supportsGPTP();
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_device_gptp_status_get(const icsneoc2_device_t* device, uint32_t timeout_ms, icsneoc2_gptp_status_t* status) {
|
||||||
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if(!status) {
|
||||||
|
return icsneoc2_error_invalid_parameters;
|
||||||
|
}
|
||||||
|
auto cpp_status = device->device->getGPTPStatus(std::chrono::milliseconds(timeout_ms));
|
||||||
|
if(!cpp_status.has_value()) {
|
||||||
|
return icsneoc2_error_get_settings_failure;
|
||||||
|
}
|
||||||
|
status->current_time_seconds = cpp_status->currentTime.seconds;
|
||||||
|
status->current_time_nanoseconds = cpp_status->currentTime.nanoseconds;
|
||||||
|
status->ms_offset_ns = cpp_status->msOffsetNs;
|
||||||
|
status->is_sync = cpp_status->isSync;
|
||||||
|
status->link_status = cpp_status->linkStatus;
|
||||||
|
status->link_delay_ns = cpp_status->linkDelayNS;
|
||||||
|
status->selected_role = cpp_status->selectedRole;
|
||||||
|
status->as_capable = cpp_status->asCapable;
|
||||||
|
status->is_syntonized = cpp_status->isSyntonized;
|
||||||
|
status->short_format = cpp_status->shortFormat;
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
|
||||||
icsneoc2_error_t icsneoc2_device_digital_io_get(const icsneoc2_device_t* device, icsneoc2_io_type_t type, uint32_t number, bool* value) {
|
icsneoc2_error_t icsneoc2_device_digital_io_get(const icsneoc2_device_t* device, icsneoc2_io_type_t type, uint32_t number, bool* value) {
|
||||||
auto res = icsneoc2_device_is_valid(device);
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
if(res != icsneoc2_error_success) {
|
if(res != icsneoc2_error_success) {
|
||||||
|
|
|
||||||
|
|
@ -892,3 +892,113 @@ icsneoc2_error_t icsneoc2_settings_readonly_get(icsneoc2_device_t* device, bool*
|
||||||
*value = device->device->settings->readonly;
|
*value = device->device->settings->readonly;
|
||||||
return icsneoc2_error_success;
|
return icsneoc2_error_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_profile_get(icsneoc2_device_t* device, icsneoc2_gptp_profile_t* value) {
|
||||||
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if(!value) {
|
||||||
|
return icsneoc2_error_invalid_parameters;
|
||||||
|
}
|
||||||
|
if(auto result = device->device->settings->getGPTPProfile(); result.has_value()) {
|
||||||
|
*value = static_cast<icsneoc2_gptp_profile_t>(result.value());
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
return icsneoc2_error_get_settings_failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_profile_set(icsneoc2_device_t* device, icsneoc2_gptp_profile_t value) {
|
||||||
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if(value >= icsneoc2_gptp_profile_maxsize) {
|
||||||
|
return icsneoc2_error_invalid_parameters;
|
||||||
|
}
|
||||||
|
if(!device->device->settings->setGPTPProfile(static_cast<RADGPTPProfile>(value))) {
|
||||||
|
return icsneoc2_error_set_settings_failure;
|
||||||
|
}
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_role_get(icsneoc2_device_t* device, icsneoc2_gptp_role_t* value) {
|
||||||
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if(!value) {
|
||||||
|
return icsneoc2_error_invalid_parameters;
|
||||||
|
}
|
||||||
|
if(auto result = device->device->settings->getGPTPRole(); result.has_value()) {
|
||||||
|
*value = static_cast<icsneoc2_gptp_role_t>(result.value());
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
return icsneoc2_error_get_settings_failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_role_set(icsneoc2_device_t* device, icsneoc2_gptp_role_t value) {
|
||||||
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if(value >= icsneoc2_gptp_role_maxsize) {
|
||||||
|
return icsneoc2_error_invalid_parameters;
|
||||||
|
}
|
||||||
|
if(!device->device->settings->setGPTPRole(static_cast<RADGPTPRole>(value))) {
|
||||||
|
return icsneoc2_error_set_settings_failure;
|
||||||
|
}
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_enabled_port_get(icsneoc2_device_t* device, uint8_t* value) {
|
||||||
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if(!value) {
|
||||||
|
return icsneoc2_error_invalid_parameters;
|
||||||
|
}
|
||||||
|
if(auto result = device->device->settings->getGPTPEnabledPort(); result.has_value()) {
|
||||||
|
*value = result.value();
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
return icsneoc2_error_get_settings_failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_enabled_port_set(icsneoc2_device_t* device, uint8_t value) {
|
||||||
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if(!device->device->settings->setGPTPEnabledPort(value)) {
|
||||||
|
return icsneoc2_error_set_settings_failure;
|
||||||
|
}
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_clock_syntonization_enabled_get(icsneoc2_device_t* device, bool* value) {
|
||||||
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if(!value) {
|
||||||
|
return icsneoc2_error_invalid_parameters;
|
||||||
|
}
|
||||||
|
if(auto result = device->device->settings->isGPTPClockSyntonizationEnabled(); result.has_value()) {
|
||||||
|
*value = result.value();
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
return icsneoc2_error_get_settings_failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_clock_syntonization_enabled_set(icsneoc2_device_t* device, bool value) {
|
||||||
|
auto res = icsneoc2_device_is_valid(device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if(!device->device->settings->setGPTPClockSyntonizationEnabled(value)) {
|
||||||
|
return icsneoc2_error_set_settings_failure;
|
||||||
|
}
|
||||||
|
return icsneoc2_error_success;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,16 @@ void init_idevicesettings(pybind11::module_& m) {
|
||||||
.value("Normal", LINMode::NORMAL_MODE)
|
.value("Normal", LINMode::NORMAL_MODE)
|
||||||
.value("Fast", LINMode::FAST_MODE);
|
.value("Fast", LINMode::FAST_MODE);
|
||||||
|
|
||||||
|
pybind11::enum_<RADGPTPProfile>(settings, "GPTPProfile")
|
||||||
|
.value("Standard", RADGPTPProfile::RAD_GPTP_PROFILE_STANDARD)
|
||||||
|
.value("Automotive", RADGPTPProfile::RAD_GPTP_PROFILE_AUTOMOTIVE);
|
||||||
|
|
||||||
|
pybind11::enum_<RADGPTPRole>(settings, "GPTPRole")
|
||||||
|
.value("Disabled", RADGPTPRole::RAD_GPTP_ROLE_DISABLED)
|
||||||
|
.value("Passive", RADGPTPRole::RAD_GPTP_ROLE_PASSIVE)
|
||||||
|
.value("Master", RADGPTPRole::RAD_GPTP_ROLE_MASTER)
|
||||||
|
.value("Slave", RADGPTPRole::RAD_GPTP_ROLE_SLAVE);
|
||||||
|
|
||||||
pybind11::enum_<MiscIOAnalogVoltage>(settings, "MiscIOAnalogVoltage")
|
pybind11::enum_<MiscIOAnalogVoltage>(settings, "MiscIOAnalogVoltage")
|
||||||
.value("V0", MiscIOAnalogVoltage::V0)
|
.value("V0", MiscIOAnalogVoltage::V0)
|
||||||
.value("V1", MiscIOAnalogVoltage::V1)
|
.value("V1", MiscIOAnalogVoltage::V1)
|
||||||
|
|
@ -123,6 +133,15 @@ void init_idevicesettings(pybind11::module_& m) {
|
||||||
// Performance blast
|
// Performance blast
|
||||||
.def("is_perf_test_enabled", &IDeviceSettings::isPerfTestEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
.def("is_perf_test_enabled", &IDeviceSettings::isPerfTestEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("set_perf_test_enable", &IDeviceSettings::setPerfTestEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
|
.def("set_perf_test_enable", &IDeviceSettings::setPerfTestEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
// gPTP methods
|
||||||
|
.def("get_gptp_profile", &IDeviceSettings::getGPTPProfile, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("set_gptp_profile", &IDeviceSettings::setGPTPProfile, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("get_gptp_role", &IDeviceSettings::getGPTPRole, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("set_gptp_role", &IDeviceSettings::setGPTPRole, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("get_gptp_enabled_port", &IDeviceSettings::getGPTPEnabledPort, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("set_gptp_enabled_port", &IDeviceSettings::setGPTPEnabledPort, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("is_gptp_clock_syntonization_enabled", &IDeviceSettings::isGPTPClockSyntonizationEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("set_gptp_clock_syntonization_enabled", &IDeviceSettings::setGPTPClockSyntonizationEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
|
||||||
// Status properties
|
// Status properties
|
||||||
.def_readonly("disabled", &IDeviceSettings::disabled)
|
.def_readonly("disabled", &IDeviceSettings::disabled)
|
||||||
|
|
|
||||||
|
|
@ -959,4 +959,79 @@ bool IDeviceSettings::setMiscIOAnalogOutput(uint8_t pin, MiscIOAnalogVoltage vol
|
||||||
(void)voltage;
|
(void)voltage;
|
||||||
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::Error);
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
std::optional<RADGPTPProfile> IDeviceSettings::getGPTPProfile() const {
|
||||||
|
const auto* gptp = getGPTPSettings();
|
||||||
|
if(!gptp) {
|
||||||
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return static_cast<RADGPTPProfile>(gptp->profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IDeviceSettings::setGPTPProfile(RADGPTPProfile profile) {
|
||||||
|
auto* gptp = getMutableGPTPSettings();
|
||||||
|
if(!gptp) {
|
||||||
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gptp->profile = static_cast<uint8_t>(profile);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<RADGPTPRole> IDeviceSettings::getGPTPRole() const {
|
||||||
|
const auto* gptp = getGPTPSettings();
|
||||||
|
if(!gptp) {
|
||||||
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return static_cast<RADGPTPRole>(gptp->gptpPortRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IDeviceSettings::setGPTPRole(RADGPTPRole role) {
|
||||||
|
auto* gptp = getMutableGPTPSettings();
|
||||||
|
if(!gptp) {
|
||||||
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gptp->gptpPortRole = static_cast<uint8_t>(role);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint8_t> IDeviceSettings::getGPTPEnabledPort() const {
|
||||||
|
const auto* gptp = getGPTPSettings();
|
||||||
|
if(!gptp) {
|
||||||
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return gptp->gptpEnabledPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IDeviceSettings::setGPTPEnabledPort(uint8_t port) {
|
||||||
|
auto* gptp = getMutableGPTPSettings();
|
||||||
|
if(!gptp) {
|
||||||
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gptp->gptpEnabledPort = port;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<bool> IDeviceSettings::isGPTPClockSyntonizationEnabled() const {
|
||||||
|
const auto* gptp = getGPTPSettings();
|
||||||
|
if(!gptp) {
|
||||||
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return gptp->enableClockSyntonization != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IDeviceSettings::setGPTPClockSyntonizationEnabled(bool enable) {
|
||||||
|
auto* gptp = getMutableGPTPSettings();
|
||||||
|
if(!gptp) {
|
||||||
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gptp->enableClockSyntonization = enable ? 1 : 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ option(LIBICSNEO_BUILD_C2_ETHERNET_TRANSMIT_EXAMPLE "Build the C2 ethernet trans
|
||||||
option(LIBICSNEO_BUILD_C2_ETHERNET_RECEIVE_EXAMPLE "Build the C2 ethernet receive example." ON)
|
option(LIBICSNEO_BUILD_C2_ETHERNET_RECEIVE_EXAMPLE "Build the C2 ethernet receive example." ON)
|
||||||
option(LIBICSNEO_BUILD_C2_T1S_LOOPBACK_EXAMPLE "Build the C2 RAD-Comet3 T1S loopback example." ON)
|
option(LIBICSNEO_BUILD_C2_T1S_LOOPBACK_EXAMPLE "Build the C2 RAD-Comet3 T1S loopback example." ON)
|
||||||
option(LIBICSNEO_BUILD_C2_TC10_EXAMPLE "Build the C2 TC10 example." ON)
|
option(LIBICSNEO_BUILD_C2_TC10_EXAMPLE "Build the C2 TC10 example." ON)
|
||||||
|
option(LIBICSNEO_BUILD_C2_GPTP_EXAMPLE "Build the C2 gPTP settings example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE "Build the simple C++ example." ON)
|
option(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE "Build the simple C++ example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_DEVICE_INFO_EXAMPLE "Build the C++ device info example." ON)
|
option(LIBICSNEO_BUILD_CPP_DEVICE_INFO_EXAMPLE "Build the C++ device info example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_INTERACTIVE_EXAMPLE "Build the command-line interactive C++ example." ON)
|
option(LIBICSNEO_BUILD_CPP_INTERACTIVE_EXAMPLE "Build the command-line interactive C++ example." ON)
|
||||||
|
|
@ -31,6 +32,7 @@ option(LIBICSNEO_BUILD_CPP_MUTEX_EXAMPLE "Build the NetworkMutex example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_ANALOG_OUT_EXAMPLE "Build the analog output example." ON)
|
option(LIBICSNEO_BUILD_CPP_ANALOG_OUT_EXAMPLE "Build the analog output example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_DISKFORMAT_EXAMPLE "Build the disk format example." ON)
|
option(LIBICSNEO_BUILD_CPP_DISKFORMAT_EXAMPLE "Build the disk format example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_T1S_EXAMPLE "Build the T1S example." ON)
|
option(LIBICSNEO_BUILD_CPP_T1S_EXAMPLE "Build the T1S example." ON)
|
||||||
|
option(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE "Build the C++ gPTP settings example." ON)
|
||||||
|
|
||||||
add_compile_options(${LIBICSNEO_COMPILER_WARNINGS})
|
add_compile_options(${LIBICSNEO_COMPILER_WARNINGS})
|
||||||
|
|
||||||
|
|
@ -98,6 +100,10 @@ if(LIBICSNEO_BUILD_C2_TC10_EXAMPLE)
|
||||||
add_subdirectory(c2/tc10)
|
add_subdirectory(c2/tc10)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(LIBICSNEO_BUILD_C2_GPTP_EXAMPLE)
|
||||||
|
add_subdirectory(c2/gptp)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE)
|
if(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE)
|
||||||
add_subdirectory(cpp/simple)
|
add_subdirectory(cpp/simple)
|
||||||
endif()
|
endif()
|
||||||
|
|
@ -165,3 +171,7 @@ endif()
|
||||||
if(LIBICSNEO_BUILD_CPP_T1S_EXAMPLE)
|
if(LIBICSNEO_BUILD_CPP_T1S_EXAMPLE)
|
||||||
add_subdirectory(cpp/t1s)
|
add_subdirectory(cpp/t1s)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE)
|
||||||
|
add_subdirectory(cpp/gptp)
|
||||||
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
add_executable(libicsneoc2-gptp-example src/main.c)
|
||||||
|
target_link_libraries(libicsneoc2-gptp-example icsneoc2-static)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_compile_definitions(libicsneoc2-gptp-example PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||||
|
endif()
|
||||||
|
|
@ -0,0 +1,330 @@
|
||||||
|
/*
|
||||||
|
* gPTP settings configurator example.
|
||||||
|
*
|
||||||
|
* Lists connected devices and their gPTP support, then lets the user
|
||||||
|
* configure the gPTP profile, role, port, and clock syntonization on any
|
||||||
|
* device that supports it. If --serial is omitted, the first available
|
||||||
|
* gPTP-capable device is used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <icsneo/icsneoc2.h>
|
||||||
|
#include <icsneo/icsneoc2settings.h>
|
||||||
|
#include <icsneo/icsneoc2messages.h>
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char* serial;
|
||||||
|
bool list;
|
||||||
|
} args_t;
|
||||||
|
|
||||||
|
/* Maps an icsneoc2_netid_t to its gPTP port index (0 = not a gPTP port). */
|
||||||
|
static uint8_t netid_to_gptp_port(icsneoc2_netid_t netid) {
|
||||||
|
switch(netid) {
|
||||||
|
case icsneoc2_netid_ae_01: return 1;
|
||||||
|
case icsneoc2_netid_ae_02: return 2;
|
||||||
|
case icsneoc2_netid_ae_03: return 3;
|
||||||
|
case icsneoc2_netid_ae_04: return 4;
|
||||||
|
case icsneoc2_netid_ae_05: return 5;
|
||||||
|
case icsneoc2_netid_ae_06: return 6;
|
||||||
|
case icsneoc2_netid_ae_07: return 7;
|
||||||
|
case icsneoc2_netid_ae_08: return 8;
|
||||||
|
case icsneoc2_netid_ae_09: return 9;
|
||||||
|
case icsneoc2_netid_ae_10: return 10;
|
||||||
|
case icsneoc2_netid_ae_11: return 11;
|
||||||
|
case icsneoc2_netid_ae_12: return 12;
|
||||||
|
case icsneoc2_netid_ethernet_01: return 13;
|
||||||
|
case icsneoc2_netid_ethernet_02: return 14;
|
||||||
|
case icsneoc2_netid_ethernet_03: return 15;
|
||||||
|
case icsneoc2_netid_ae_13: return 16;
|
||||||
|
case icsneoc2_netid_ae_14: return 17;
|
||||||
|
case icsneoc2_netid_ae_15: return 18;
|
||||||
|
case icsneoc2_netid_ae_16: return 19;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* gptp_profile_str(icsneoc2_gptp_profile_t p) {
|
||||||
|
switch(p) {
|
||||||
|
case icsneoc2_gptp_profile_standard: return "Standard";
|
||||||
|
case icsneoc2_gptp_profile_automotive: return "Automotive";
|
||||||
|
default: return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* gptp_role_str(icsneoc2_gptp_role_t r) {
|
||||||
|
switch(r) {
|
||||||
|
case icsneoc2_gptp_role_disabled: return "Disabled";
|
||||||
|
case icsneoc2_gptp_role_passive: return "Passive";
|
||||||
|
case icsneoc2_gptp_role_master: return "Master";
|
||||||
|
case icsneoc2_gptp_role_slave: return "Slave";
|
||||||
|
default: return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int print_error_code(const char* message, icsneoc2_error_t error) {
|
||||||
|
char error_str[64] = {0};
|
||||||
|
size_t error_str_len = sizeof(error_str);
|
||||||
|
icsneoc2_error_t res = icsneoc2_error_code_get(error, error_str, &error_str_len);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
fprintf(stderr, "%s: failed to get string for error code %u\n", message, error);
|
||||||
|
return (int)res;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "%s: \"%s\" (%u)\n", message, error_str, error);
|
||||||
|
return (int)error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_usage(const char* prog) {
|
||||||
|
printf("Usage:\n");
|
||||||
|
printf(" %s --list\n", prog);
|
||||||
|
printf(" %s [--serial SERIAL]\n", prog);
|
||||||
|
printf("\n");
|
||||||
|
printf(" --list List connected devices and their gPTP support.\n");
|
||||||
|
printf(" --serial SERIAL Serial number of the device to configure.\n");
|
||||||
|
printf(" -h, --help Show this message.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_args(int argc, char** argv, args_t* out) {
|
||||||
|
memset(out, 0, sizeof(*out));
|
||||||
|
for(int i = 1; i < argc; ++i) {
|
||||||
|
const char* a = argv[i];
|
||||||
|
if(strcmp(a, "-h") == 0 || strcmp(a, "--help") == 0) {
|
||||||
|
print_usage(argv[0]);
|
||||||
|
exit(0);
|
||||||
|
} else if(strcmp(a, "--list") == 0) {
|
||||||
|
out->list = true;
|
||||||
|
} else if(strcmp(a, "--serial") == 0) {
|
||||||
|
if(i + 1 >= argc) {
|
||||||
|
fprintf(stderr, "error: --serial requires a value\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
out->serial = argv[++i];
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "error: unknown argument '%s'\n", a);
|
||||||
|
print_usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static icsneoc2_device_info_t* find_device(icsneoc2_device_info_t* list, const char* serial) {
|
||||||
|
for(icsneoc2_device_info_t* cur = list; cur != NULL; cur = icsneoc2_device_info_next(cur)) {
|
||||||
|
if(serial == NULL)
|
||||||
|
return cur;
|
||||||
|
char dev_serial[64] = {0};
|
||||||
|
size_t dev_serial_len = sizeof(dev_serial);
|
||||||
|
if(icsneoc2_device_info_serial_get(cur, dev_serial, &dev_serial_len) != icsneoc2_error_success)
|
||||||
|
continue;
|
||||||
|
if(strcmp(dev_serial, serial) == 0)
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a list of available Ethernet/AE networks with their gPTP port indices.
|
||||||
|
* Returns the number of ports printed.
|
||||||
|
*/
|
||||||
|
static size_t print_gptp_ports(icsneoc2_device_t* device) {
|
||||||
|
icsneoc2_netid_t nets[128] = {0};
|
||||||
|
size_t count = sizeof(nets) / sizeof(nets[0]);
|
||||||
|
if(icsneoc2_device_supported_tx_networks_get(device, nets, &count) != icsneoc2_error_success)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size_t printed = 0;
|
||||||
|
for(size_t i = 0; i < count; ++i) {
|
||||||
|
uint8_t port = netid_to_gptp_port(nets[i]);
|
||||||
|
if(port == 0)
|
||||||
|
continue;
|
||||||
|
char name[64] = {0};
|
||||||
|
size_t name_len = sizeof(name);
|
||||||
|
icsneoc2_netid_name_get(nets[i], name, &name_len);
|
||||||
|
printf(" [%u] %s\n", (unsigned)port, name);
|
||||||
|
++printed;
|
||||||
|
}
|
||||||
|
return printed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int list_devices(icsneoc2_device_info_t* list) {
|
||||||
|
size_t index = 0;
|
||||||
|
for(icsneoc2_device_info_t* cur = list; cur != NULL; cur = icsneoc2_device_info_next(cur)) {
|
||||||
|
char serial[64] = {0};
|
||||||
|
size_t serial_len = sizeof(serial);
|
||||||
|
char description[256] = {0};
|
||||||
|
size_t description_len = sizeof(description);
|
||||||
|
icsneoc2_device_info_serial_get(cur, serial, &serial_len);
|
||||||
|
icsneoc2_device_info_description_get(cur, description, &description_len);
|
||||||
|
printf("[%zu] %s (%s)\n", index++, description, serial);
|
||||||
|
|
||||||
|
icsneoc2_device_t* device = NULL;
|
||||||
|
if(icsneoc2_device_create(cur, &device) != icsneoc2_error_success)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
icsneoc2_open_options_t opts = icsneoc2_open_options_default;
|
||||||
|
opts &= ~ICSNEOC2_OPEN_OPTIONS_SYNC_RTC;
|
||||||
|
opts &= ~ICSNEOC2_OPEN_OPTIONS_GO_ONLINE;
|
||||||
|
if(icsneoc2_device_open(device, opts) != icsneoc2_error_success) {
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool supported = false;
|
||||||
|
icsneoc2_device_supports_gptp(device, &supported);
|
||||||
|
printf(" gPTP supported: %s\n", supported ? "yes" : "no");
|
||||||
|
if(supported) {
|
||||||
|
printf(" gPTP ports:\n");
|
||||||
|
print_gptp_ports(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_device_close(device);
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_current_settings(icsneoc2_device_t* device) {
|
||||||
|
icsneoc2_gptp_profile_t profile = icsneoc2_gptp_profile_standard;
|
||||||
|
icsneoc2_gptp_role_t role = icsneoc2_gptp_role_disabled;
|
||||||
|
uint8_t port = 0;
|
||||||
|
bool clock_syntonization = false;
|
||||||
|
|
||||||
|
printf("\nCurrent gPTP settings:\n");
|
||||||
|
if(icsneoc2_settings_gptp_profile_get(device, &profile) == icsneoc2_error_success)
|
||||||
|
printf(" Profile: %s\n", gptp_profile_str(profile));
|
||||||
|
if(icsneoc2_settings_gptp_role_get(device, &role) == icsneoc2_error_success)
|
||||||
|
printf(" Role: %s\n", gptp_role_str(role));
|
||||||
|
if(icsneoc2_settings_gptp_enabled_port_get(device, &port) == icsneoc2_error_success)
|
||||||
|
printf(" Enabled port: %u%s\n", (unsigned)port, port == 0 ? " (disabled)" : "");
|
||||||
|
if(icsneoc2_settings_gptp_clock_syntonization_enabled_get(device, &clock_syntonization) == icsneoc2_error_success)
|
||||||
|
printf(" Clock syntonization: %s\n", clock_syntonization ? "enabled" : "disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
static long prompt_long(const char* prompt, long default_val, long min, long max) {
|
||||||
|
char buf[32] = {0};
|
||||||
|
printf("%s [%ld]: ", prompt, default_val);
|
||||||
|
fflush(stdout);
|
||||||
|
if(fgets(buf, sizeof(buf), stdin) == NULL || buf[0] == '\n')
|
||||||
|
return default_val;
|
||||||
|
char* end = NULL;
|
||||||
|
long val = strtol(buf, &end, 10);
|
||||||
|
if(end == buf || val < min || val > max) {
|
||||||
|
printf("Invalid input, using %ld.\n", default_val);
|
||||||
|
return default_val;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int configure_device(icsneoc2_device_t* device) {
|
||||||
|
icsneoc2_error_t res;
|
||||||
|
|
||||||
|
res = icsneoc2_settings_refresh(device);
|
||||||
|
if(res != icsneoc2_error_success)
|
||||||
|
return print_error_code("Failed to refresh settings", res);
|
||||||
|
|
||||||
|
print_current_settings(device);
|
||||||
|
|
||||||
|
printf("\nAvailable gPTP ports (0 = disabled):\n");
|
||||||
|
printf(" [0] Disabled\n");
|
||||||
|
print_gptp_ports(device);
|
||||||
|
|
||||||
|
printf("\nConfigure gPTP:\n");
|
||||||
|
|
||||||
|
long profile = prompt_long(" Profile (0=Standard, 1=Automotive)", 1, 0, 1);
|
||||||
|
res = icsneoc2_settings_gptp_profile_set(device, (icsneoc2_gptp_profile_t)profile);
|
||||||
|
if(res != icsneoc2_error_success)
|
||||||
|
return print_error_code("Failed to set profile", res);
|
||||||
|
|
||||||
|
long role = prompt_long(" Role (0=Disabled, 1=Passive, 2=Master, 3=Slave)", 3, 0, 3);
|
||||||
|
res = icsneoc2_settings_gptp_role_set(device, (icsneoc2_gptp_role_t)role);
|
||||||
|
if(res != icsneoc2_error_success)
|
||||||
|
return print_error_code("Failed to set role", res);
|
||||||
|
|
||||||
|
long port = prompt_long(" Enabled port index", 0, 0, 19);
|
||||||
|
res = icsneoc2_settings_gptp_enabled_port_set(device, (uint8_t)port);
|
||||||
|
if(res != icsneoc2_error_success)
|
||||||
|
return print_error_code("Failed to set enabled port", res);
|
||||||
|
|
||||||
|
long syntonization = prompt_long(" Clock syntonization (0=disabled, 1=enabled)", 0, 0, 1);
|
||||||
|
res = icsneoc2_settings_gptp_clock_syntonization_enabled_set(device, syntonization != 0);
|
||||||
|
if(res != icsneoc2_error_success)
|
||||||
|
return print_error_code("Failed to set clock syntonization", res);
|
||||||
|
|
||||||
|
printf("\nNote: icsneoc2_settings_apply() persists settings on the device.\n");
|
||||||
|
res = icsneoc2_settings_apply(device);
|
||||||
|
if(res != icsneoc2_error_success)
|
||||||
|
return print_error_code("Failed to apply settings", res);
|
||||||
|
|
||||||
|
printf("\nUpdated gPTP settings:\n");
|
||||||
|
print_current_settings(device);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
args_t args;
|
||||||
|
if(parse_args(argc, argv, &args) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
icsneoc2_device_info_t* found_devices = NULL;
|
||||||
|
icsneoc2_error_t res = icsneoc2_device_enumerate(0, &found_devices);
|
||||||
|
if(res != icsneoc2_error_success)
|
||||||
|
return print_error_code("Failed to enumerate devices", res);
|
||||||
|
if(found_devices == NULL) {
|
||||||
|
fprintf(stderr, "error: no devices found\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(args.list) {
|
||||||
|
int rc = list_devices(found_devices);
|
||||||
|
icsneoc2_enumeration_free(found_devices);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneoc2_device_info_t* info = find_device(found_devices, args.serial);
|
||||||
|
if(info == NULL) {
|
||||||
|
fprintf(stderr, "error: unable to find device %s\n", args.serial ? args.serial : "(any)");
|
||||||
|
icsneoc2_enumeration_free(found_devices);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char description[256] = {0};
|
||||||
|
size_t description_len = sizeof(description);
|
||||||
|
icsneoc2_device_info_description_get(info, description, &description_len);
|
||||||
|
|
||||||
|
icsneoc2_device_t* device = NULL;
|
||||||
|
res = icsneoc2_device_create(info, &device);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
icsneoc2_enumeration_free(found_devices);
|
||||||
|
return print_error_code("Failed to create device", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Opening %s\n", description);
|
||||||
|
res = icsneoc2_device_open(device, icsneoc2_open_options_default);
|
||||||
|
if(res != icsneoc2_error_success) {
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
icsneoc2_enumeration_free(found_devices);
|
||||||
|
return print_error_code("Failed to open device", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool supported = false;
|
||||||
|
icsneoc2_device_supports_gptp(device, &supported);
|
||||||
|
if(!supported) {
|
||||||
|
fprintf(stderr, "error: device does not support gPTP (%s)\n", description);
|
||||||
|
icsneoc2_device_close(device);
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
icsneoc2_enumeration_free(found_devices);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = configure_device(device);
|
||||||
|
|
||||||
|
printf("Closing %s\n", description);
|
||||||
|
icsneoc2_device_close(device);
|
||||||
|
icsneoc2_device_free(device);
|
||||||
|
icsneoc2_enumeration_free(found_devices);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
add_executable(libicsneocpp-gptp-settings src/GPTPSettingsExample.cpp)
|
||||||
|
target_link_libraries(libicsneocpp-gptp-settings icsneocpp)
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include "icsneo/icsneocpp.h"
|
||||||
|
|
||||||
|
/* Maps a Network::NetID to its gPTP port index (0 = not a gPTP port). */
|
||||||
|
static uint8_t netidToGPTPPort(icsneo::Network::NetID netid) {
|
||||||
|
using N = icsneo::Network::NetID;
|
||||||
|
switch(netid) {
|
||||||
|
case N::AE_01: return 1;
|
||||||
|
case N::AE_02: return 2;
|
||||||
|
case N::AE_03: return 3;
|
||||||
|
case N::AE_04: return 4;
|
||||||
|
case N::AE_05: return 5;
|
||||||
|
case N::AE_06: return 6;
|
||||||
|
case N::AE_07: return 7;
|
||||||
|
case N::AE_08: return 8;
|
||||||
|
case N::AE_09: return 9;
|
||||||
|
case N::AE_10: return 10;
|
||||||
|
case N::AE_11: return 11;
|
||||||
|
case N::AE_12: return 12;
|
||||||
|
case N::ETHERNET_01: return 13;
|
||||||
|
case N::ETHERNET_02: return 14;
|
||||||
|
case N::ETHERNET_03: return 15;
|
||||||
|
case N::AE_13: return 16;
|
||||||
|
case N::AE_14: return 17;
|
||||||
|
case N::AE_15: return 18;
|
||||||
|
case N::AE_16: return 19;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string gptpProfileStr(RADGPTPProfile p) {
|
||||||
|
switch(p) {
|
||||||
|
case RAD_GPTP_PROFILE_STANDARD: return "Standard";
|
||||||
|
case RAD_GPTP_PROFILE_AUTOMOTIVE: return "Automotive";
|
||||||
|
default: return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string gptpRoleStr(RADGPTPRole r) {
|
||||||
|
switch(r) {
|
||||||
|
case RAD_GPTP_ROLE_DISABLED: return "Disabled";
|
||||||
|
case RAD_GPTP_ROLE_PASSIVE: return "Passive";
|
||||||
|
case RAD_GPTP_ROLE_MASTER: return "Master";
|
||||||
|
case RAD_GPTP_ROLE_SLAVE: return "Slave";
|
||||||
|
default: return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static std::string optStr(const std::optional<T>& opt) {
|
||||||
|
if(!opt.has_value()) return "N/A";
|
||||||
|
if constexpr(std::is_same_v<T, bool>)
|
||||||
|
return opt.value() ? "enabled" : "disabled";
|
||||||
|
else
|
||||||
|
return std::to_string(static_cast<int>(opt.value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static long promptLong(const std::string& prompt, long defaultVal, long min, long max) {
|
||||||
|
std::cout << prompt << " [" << defaultVal << "]: " << std::flush;
|
||||||
|
std::string input;
|
||||||
|
std::getline(std::cin, input);
|
||||||
|
if(input.empty())
|
||||||
|
return defaultVal;
|
||||||
|
try {
|
||||||
|
long val = std::stol(input);
|
||||||
|
if(val >= min && val <= max)
|
||||||
|
return val;
|
||||||
|
} catch(...) {}
|
||||||
|
std::cout << "Invalid input, using " << defaultVal << ".\n";
|
||||||
|
return defaultVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printGPTPPorts(const std::shared_ptr<icsneo::Device>& device) {
|
||||||
|
for(const auto& net : device->getSupportedTXNetworks()) {
|
||||||
|
uint8_t port = netidToGPTPPort(net.getNetID());
|
||||||
|
if(port == 0) continue;
|
||||||
|
std::cout << " [" << (int)port << "] " << net << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printCurrentSettings(const std::shared_ptr<icsneo::Device>& device) {
|
||||||
|
std::cout << "\nCurrent gPTP settings:\n";
|
||||||
|
auto profile = device->settings->getGPTPProfile();
|
||||||
|
auto role = device->settings->getGPTPRole();
|
||||||
|
auto port = device->settings->getGPTPEnabledPort();
|
||||||
|
auto synton = device->settings->isGPTPClockSyntonizationEnabled();
|
||||||
|
|
||||||
|
if(profile.has_value())
|
||||||
|
std::cout << " Profile: " << gptpProfileStr(profile.value()) << "\n";
|
||||||
|
if(role.has_value())
|
||||||
|
std::cout << " Role: " << gptpRoleStr(role.value()) << "\n";
|
||||||
|
if(port.has_value())
|
||||||
|
std::cout << " Enabled port: " << (int)port.value() << (port.value() == 0 ? " (disabled)" : "") << "\n";
|
||||||
|
if(synton.has_value())
|
||||||
|
std::cout << " Clock syntonization: " << optStr(synton) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "Finding devices... " << std::flush;
|
||||||
|
auto devices = icsneo::FindAllDevices();
|
||||||
|
std::cout << devices.size() << " found\n";
|
||||||
|
|
||||||
|
if(devices.empty()) {
|
||||||
|
auto err = icsneo::GetLastError();
|
||||||
|
if(err.getType() != icsneo::APIEvent::Type::NoErrorFound)
|
||||||
|
std::cout << err << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<icsneo::Device>> gptp_devices;
|
||||||
|
for(auto& d : devices) {
|
||||||
|
if(d->supportsGPTP())
|
||||||
|
gptp_devices.push_back(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gptp_devices.empty()) {
|
||||||
|
std::cout << "No gPTP-capable devices found.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "\nAvailable gPTP-capable devices:\n";
|
||||||
|
for(size_t i = 0; i < gptp_devices.size(); ++i)
|
||||||
|
std::cout << " [" << (i + 1) << "] " << gptp_devices[i]->describe() << "\n";
|
||||||
|
|
||||||
|
long choice = promptLong("Select device", 1, 1, (long)gptp_devices.size());
|
||||||
|
auto device = gptp_devices[choice - 1];
|
||||||
|
|
||||||
|
std::cout << "\nOpening " << device->describe() << "... " << std::flush;
|
||||||
|
if(!device->open()) {
|
||||||
|
std::cout << "failed\n" << icsneo::GetLastError() << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::cout << "OK\n";
|
||||||
|
|
||||||
|
if(!device->settings->refresh()) {
|
||||||
|
std::cout << "Failed to refresh settings\n";
|
||||||
|
device->close();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printCurrentSettings(device);
|
||||||
|
|
||||||
|
std::cout << "\nAvailable gPTP ports (0 = disabled):\n";
|
||||||
|
std::cout << " [0] Disabled\n";
|
||||||
|
printGPTPPorts(device);
|
||||||
|
|
||||||
|
std::cout << "\nConfigure gPTP:\n";
|
||||||
|
|
||||||
|
long profile = promptLong(" Profile (0=Standard, 1=Automotive)", 1, 0, 1);
|
||||||
|
device->settings->setGPTPProfile(static_cast<RADGPTPProfile>(profile));
|
||||||
|
|
||||||
|
long role = promptLong(" Role (0=Disabled, 1=Passive, 2=Master, 3=Slave)", 3, 0, 3);
|
||||||
|
device->settings->setGPTPRole(static_cast<RADGPTPRole>(role));
|
||||||
|
|
||||||
|
long port = promptLong(" Enabled port index", 0, 0, 19);
|
||||||
|
device->settings->setGPTPEnabledPort(static_cast<uint8_t>(port));
|
||||||
|
|
||||||
|
long syntonization = promptLong(" Clock syntonization (0=disabled, 1=enabled)", 0, 0, 1);
|
||||||
|
device->settings->setGPTPClockSyntonizationEnabled(syntonization != 0);
|
||||||
|
|
||||||
|
long permanent = promptLong("\nSave to EEPROM? (0=temporary, 1=permanent)", 0, 0, 1);
|
||||||
|
if(!device->settings->apply(permanent == 0)) {
|
||||||
|
std::cout << "Failed to apply settings\n" << icsneo::GetLastError() << "\n";
|
||||||
|
device->close();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printCurrentSettings(device);
|
||||||
|
|
||||||
|
std::cout << "\nClosing " << device->describe() << "\n";
|
||||||
|
device->close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,151 @@
|
||||||
|
import icsneopy
|
||||||
|
|
||||||
|
GPTP_PORT_MAP = {
|
||||||
|
icsneopy.Network.NetID.AE_01: (1, "AE 01"),
|
||||||
|
icsneopy.Network.NetID.AE_02: (2, "AE 02"),
|
||||||
|
icsneopy.Network.NetID.AE_03: (3, "AE 03"),
|
||||||
|
icsneopy.Network.NetID.AE_04: (4, "AE 04"),
|
||||||
|
icsneopy.Network.NetID.AE_05: (5, "AE 05"),
|
||||||
|
icsneopy.Network.NetID.AE_06: (6, "AE 06"),
|
||||||
|
icsneopy.Network.NetID.AE_07: (7, "AE 07"),
|
||||||
|
icsneopy.Network.NetID.AE_08: (8, "AE 08"),
|
||||||
|
icsneopy.Network.NetID.AE_09: (9, "AE 09"),
|
||||||
|
icsneopy.Network.NetID.AE_10: (10, "AE 10"),
|
||||||
|
icsneopy.Network.NetID.AE_11: (11, "AE 11"),
|
||||||
|
icsneopy.Network.NetID.AE_12: (12, "AE 12"),
|
||||||
|
icsneopy.Network.NetID.ETHERNET_01: (13, "Ethernet 01"),
|
||||||
|
icsneopy.Network.NetID.ETHERNET_02: (14, "Ethernet 02"),
|
||||||
|
icsneopy.Network.NetID.ETHERNET_03: (15, "Ethernet 03"),
|
||||||
|
icsneopy.Network.NetID.AE_13: (16, "AE 13"),
|
||||||
|
icsneopy.Network.NetID.AE_14: (17, "AE 14"),
|
||||||
|
icsneopy.Network.NetID.AE_15: (18, "AE 15"),
|
||||||
|
icsneopy.Network.NetID.AE_16: (19, "AE 16"),
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILE_NAMES = {
|
||||||
|
icsneopy.Settings.GTPPProfile.Standard: "Standard",
|
||||||
|
icsneopy.Settings.GTPPProfile.Automotive: "Automotive",
|
||||||
|
}
|
||||||
|
|
||||||
|
ROLE_NAMES = {
|
||||||
|
icsneopy.Settings.GTPPRole.Disabled: "Disabled",
|
||||||
|
icsneopy.Settings.GTPPRole.Passive: "Passive",
|
||||||
|
icsneopy.Settings.GTPPRole.Master: "Master",
|
||||||
|
icsneopy.Settings.GTPPRole.Slave: "Slave",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_int(prompt, default, lo, hi):
|
||||||
|
try:
|
||||||
|
raw = input(f"{prompt} [{default}]: ").strip()
|
||||||
|
if not raw:
|
||||||
|
return default
|
||||||
|
val = int(raw)
|
||||||
|
if lo <= val <= hi:
|
||||||
|
return val
|
||||||
|
except (ValueError, EOFError):
|
||||||
|
pass
|
||||||
|
print(f"Invalid input, using {default}.")
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
def gptp_ports(device):
|
||||||
|
ports = []
|
||||||
|
for net in device.get_supported_tx_networks():
|
||||||
|
entry = GPTP_PORT_MAP.get(net.get_net_id())
|
||||||
|
if entry:
|
||||||
|
ports.append(entry)
|
||||||
|
return sorted(ports)
|
||||||
|
|
||||||
|
|
||||||
|
def print_settings(device):
|
||||||
|
s = device.settings
|
||||||
|
profile = s.get_gptp_profile()
|
||||||
|
role = s.get_gptp_role()
|
||||||
|
port = s.get_gptp_enabled_port()
|
||||||
|
synton = s.is_gptp_clock_syntonization_enabled()
|
||||||
|
|
||||||
|
print("\nCurrent gPTP settings:")
|
||||||
|
if profile is not None:
|
||||||
|
print(f" Profile: {PROFILE_NAMES.get(profile, profile)}")
|
||||||
|
if role is not None:
|
||||||
|
print(f" Role: {ROLE_NAMES.get(role, role)}")
|
||||||
|
if port is not None:
|
||||||
|
suffix = " (disabled)" if port == 0 else ""
|
||||||
|
print(f" Enabled port: {port}{suffix}")
|
||||||
|
if synton is not None:
|
||||||
|
print(f" Clock syntonization: {'enabled' if synton else 'disabled'}")
|
||||||
|
|
||||||
|
|
||||||
|
def configure(device):
|
||||||
|
if not device.settings.refresh():
|
||||||
|
print("error: failed to refresh settings")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print_settings(device)
|
||||||
|
|
||||||
|
ports = gptp_ports(device)
|
||||||
|
print("\nAvailable gPTP ports (0 = disabled):")
|
||||||
|
print(" [0] Disabled")
|
||||||
|
for idx, name in ports:
|
||||||
|
print(f" [{idx}] {name}")
|
||||||
|
|
||||||
|
print("\nConfigure gPTP:")
|
||||||
|
profile = prompt_int(" Profile (0=Standard, 1=Automotive)", 1, 0, 1)
|
||||||
|
role = prompt_int(" Role (0=Disabled, 1=Passive, 2=Master, 3=Slave)", 3, 0, 3)
|
||||||
|
port = prompt_int(" Enabled port index", 0, 0, 19)
|
||||||
|
synton = prompt_int(" Clock syntonization (0=disabled, 1=enabled)", 0, 0, 1)
|
||||||
|
permanent = prompt_int("\nSave to EEPROM? (0=temporary, 1=permanent)", 0, 0, 1)
|
||||||
|
|
||||||
|
s = device.settings
|
||||||
|
profile_enum = list(PROFILE_NAMES.keys())[profile]
|
||||||
|
role_enum = list(ROLE_NAMES.keys())[role]
|
||||||
|
|
||||||
|
s.set_gptp_profile(profile_enum)
|
||||||
|
s.set_gptp_role(role_enum)
|
||||||
|
s.set_gptp_enabled_port(port)
|
||||||
|
s.set_gptp_clock_syntonization_enabled(bool(synton))
|
||||||
|
|
||||||
|
if not s.apply(not permanent):
|
||||||
|
print("error: failed to apply settings")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print_settings(device)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
devices = icsneopy.find_all_devices()
|
||||||
|
if not devices:
|
||||||
|
print("error: no devices found")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
gptp_devices = [d for d in devices if d.settings.get_gptp_profile() is not None]
|
||||||
|
if not gptp_devices:
|
||||||
|
print("error: no gPTP-capable devices found")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print("Available gPTP-capable devices:")
|
||||||
|
for i, d in enumerate(gptp_devices, 1):
|
||||||
|
print(f" [{i}] {d}")
|
||||||
|
|
||||||
|
choice = prompt_int("Select device", 1, 1, len(gptp_devices))
|
||||||
|
device = gptp_devices[choice - 1]
|
||||||
|
|
||||||
|
print(f"\nOpening {device}... ", end="", flush=True)
|
||||||
|
if not device.open():
|
||||||
|
print("failed")
|
||||||
|
return 1
|
||||||
|
print("OK")
|
||||||
|
|
||||||
|
try:
|
||||||
|
ok = configure(device)
|
||||||
|
finally:
|
||||||
|
print(f"\nClosing {device}")
|
||||||
|
device.close()
|
||||||
|
|
||||||
|
return 0 if ok else 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
|
|
@ -613,6 +613,18 @@ enum : uint8_t
|
||||||
RESISTOR_OFF
|
RESISTOR_OFF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum RADGPTPProfile : icsneoc2_gptp_profile_t {
|
||||||
|
RAD_GPTP_PROFILE_STANDARD = icsneoc2_gptp_profile_standard,
|
||||||
|
RAD_GPTP_PROFILE_AUTOMOTIVE = icsneoc2_gptp_profile_automotive,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RADGPTPRole : icsneoc2_gptp_role_t {
|
||||||
|
RAD_GPTP_ROLE_DISABLED = icsneoc2_gptp_role_disabled,
|
||||||
|
RAD_GPTP_ROLE_PASSIVE = icsneoc2_gptp_role_passive,
|
||||||
|
RAD_GPTP_ROLE_MASTER = icsneoc2_gptp_role_master,
|
||||||
|
RAD_GPTP_ROLE_SLAVE = icsneoc2_gptp_role_slave,
|
||||||
|
};
|
||||||
|
|
||||||
/* Mode in LIN_SETTINGS */
|
/* Mode in LIN_SETTINGS */
|
||||||
enum LINMode
|
enum LINMode
|
||||||
{
|
{
|
||||||
|
|
@ -1278,6 +1290,18 @@ public:
|
||||||
virtual bool setMiscIOAnalogOutputEnabled(uint8_t pin, bool enabled);
|
virtual bool setMiscIOAnalogOutputEnabled(uint8_t pin, bool enabled);
|
||||||
virtual bool setMiscIOAnalogOutput(uint8_t pin, MiscIOAnalogVoltage voltage);
|
virtual bool setMiscIOAnalogOutput(uint8_t pin, MiscIOAnalogVoltage voltage);
|
||||||
|
|
||||||
|
// gPTP methods
|
||||||
|
std::optional<RADGPTPProfile> getGPTPProfile() const;
|
||||||
|
bool setGPTPProfile(RADGPTPProfile profile);
|
||||||
|
std::optional<RADGPTPRole> getGPTPRole() const;
|
||||||
|
bool setGPTPRole(RADGPTPRole role);
|
||||||
|
std::optional<uint8_t> getGPTPEnabledPort() const;
|
||||||
|
bool setGPTPEnabledPort(uint8_t port);
|
||||||
|
std::optional<bool> isGPTPClockSyntonizationEnabled() const;
|
||||||
|
bool setGPTPClockSyntonizationEnabled(bool enable);
|
||||||
|
virtual const RAD_GPTP_SETTINGS* getGPTPSettings() const { return nullptr; }
|
||||||
|
virtual RAD_GPTP_SETTINGS* getMutableGPTPSettings() { return nullptr; }
|
||||||
|
|
||||||
const void* getRawStructurePointer() const { return settingsInDeviceRAM.data(); }
|
const void* getRawStructurePointer() const { return settingsInDeviceRAM.data(); }
|
||||||
void* getMutableRawStructurePointer() { return settings.data(); }
|
void* getMutableRawStructurePointer() { return settings.data(); }
|
||||||
template<typename T> const T* getStructurePointer() const { return reinterpret_cast<const T*>(getRawStructurePointer()); }
|
template<typename T> const T* getStructurePointer() const { return reinterpret_cast<const T*>(getRawStructurePointer()); }
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,15 @@ public:
|
||||||
cfg->perf_en = !!enable;
|
cfg->perf_en = !!enable;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<neoviconnect_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<neoviconnect_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -422,6 +422,15 @@ protected:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &cfg->termination_enables;
|
return &cfg->termination_enables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<neovifire3_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<neovifire3_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,15 @@ protected:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &cfg->termination_enables;
|
return &cfg->termination_enables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<neovifire3flexray_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<neovifire3flexray_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -572,6 +572,15 @@ protected:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &cfg->termination_enables;
|
return &cfg->termination_enables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<neovifire3t1slin_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<neovifire3t1slin_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -320,6 +320,15 @@ protected:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &cfg->termination_enables;
|
return &cfg->termination_enables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<neovired2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<neovired2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -259,6 +259,15 @@ public:
|
||||||
cfg->perf_en = !!enable;
|
cfg->perf_en = !!enable;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -290,6 +290,15 @@ private:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<radcomet2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<radcomet2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -728,6 +728,15 @@ private:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<radcomet3_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<radcomet3_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -290,6 +290,15 @@ public:
|
||||||
cfg->perf_en = !!enable;
|
cfg->perf_en = !!enable;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<radgalaxy_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<radgalaxy_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,15 @@ public:
|
||||||
cfg->perf_en = !!enable;
|
cfg->perf_en = !!enable;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<radgalaxy2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<radgalaxy2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,15 @@ protected:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &cfg->termination_enables;
|
return &cfg->termination_enables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<radgigastar_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<radgigastar_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
||||||
|
|
@ -645,6 +645,14 @@ namespace icsneo
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &cfg->termination_enables;
|
return &cfg->termination_enables;
|
||||||
}
|
}
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<radgigastar2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<radgigastar2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,15 @@ static_assert(sizeof(radmoon2_settings_t) == 170, "RADMoon2 settings size mismat
|
||||||
class RADMoon2Settings : public IDeviceSettings {
|
class RADMoon2Settings : public IDeviceSettings {
|
||||||
public:
|
public:
|
||||||
RADMoon2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoon2_settings_t)) {}
|
RADMoon2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoon2_settings_t)) {}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<radmoon2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<radmoon2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -380,6 +380,15 @@ private:
|
||||||
cfg->t1sExt.multi_id[index] = id;
|
cfg->t1sExt.multi_id[index] = id;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<radmoont1s_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<radmoont1s_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,15 @@ public:
|
||||||
cfg->perf_en = !!enable;
|
cfg->perf_en = !!enable;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||||
|
auto cfg = getStructurePointer<radstar2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
|
RAD_GPTP_SETTINGS* getMutableGPTPSettings() override {
|
||||||
|
auto cfg = getMutableStructurePointer<radstar2_settings_t>();
|
||||||
|
return cfg ? &cfg->gPTP : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -581,6 +581,27 @@ icsneoc2_error_t icsneoc2_device_tc10_sleep_request(const icsneoc2_device_t* dev
|
||||||
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise.
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise.
|
||||||
*/
|
*/
|
||||||
icsneoc2_error_t icsneoc2_device_tc10_status_get(const icsneoc2_device_t* device, icsneoc2_netid_t netid, icsneoc2_tc10_sleep_status_t* sleep_status, icsneoc2_tc10_wake_status_t* wake_status);
|
icsneoc2_error_t icsneoc2_device_tc10_status_get(const icsneoc2_device_t* device, icsneoc2_netid_t netid, icsneoc2_tc10_sleep_status_t* sleep_status, icsneoc2_tc10_wake_status_t* wake_status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the device supports gPTP.
|
||||||
|
*
|
||||||
|
* @param[in] device The device to check against.
|
||||||
|
* @param[out] supported Pointer to a bool to copy the value into.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_device_supports_gptp(const icsneoc2_device_t* device, bool* supported);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current gPTP status from the device.
|
||||||
|
*
|
||||||
|
* @param[in] device The device to query.
|
||||||
|
* @param[in] timeout_ms Timeout in milliseconds to wait for the device response.
|
||||||
|
* @param[out] status Pointer to an icsneoc2_gptp_status_t to copy the status into.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters or icsneoc2_error_invalid_type otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_device_gptp_status_get(const icsneoc2_device_t* device, uint32_t timeout_ms, icsneoc2_gptp_status_t* status);
|
||||||
/**
|
/**
|
||||||
* Get the current state of a digital I/O pin.
|
* Get the current state of a digital I/O pin.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -676,6 +676,86 @@ icsneoc2_error_t icsneoc2_settings_disabled_get(icsneoc2_device_t* device, bool*
|
||||||
*/
|
*/
|
||||||
icsneoc2_error_t icsneoc2_settings_readonly_get(icsneoc2_device_t* device, bool* value);
|
icsneoc2_error_t icsneoc2_settings_readonly_get(icsneoc2_device_t* device, bool* value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the gPTP profile.
|
||||||
|
*
|
||||||
|
* @param[in] device The device to check.
|
||||||
|
* @param[out] value Pointer to store the gPTP profile.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_profile_get(icsneoc2_device_t* device, icsneoc2_gptp_profile_t* value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the gPTP profile.
|
||||||
|
*
|
||||||
|
* @param[in] device The device to configure.
|
||||||
|
* @param[in] value The gPTP profile to set.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters or icsneoc2_error_set_settings_failure otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_profile_set(icsneoc2_device_t* device, icsneoc2_gptp_profile_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the gPTP port role.
|
||||||
|
*
|
||||||
|
* @param[in] device The device to check.
|
||||||
|
* @param[out] value Pointer to store the gPTP port role.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_role_get(icsneoc2_device_t* device, icsneoc2_gptp_role_t* value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the gPTP port role.
|
||||||
|
*
|
||||||
|
* @param[in] device The device to configure.
|
||||||
|
* @param[in] value The gPTP port role to set.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters or icsneoc2_error_set_settings_failure otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_role_set(icsneoc2_device_t* device, icsneoc2_gptp_role_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the gPTP enabled port index. A value of 0 indicates gPTP is disabled.
|
||||||
|
*
|
||||||
|
* @param[in] device The device to check.
|
||||||
|
* @param[out] value Pointer to store the enabled port index.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_enabled_port_get(icsneoc2_device_t* device, uint8_t* value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the gPTP enabled port index. Set to 0 to disable gPTP.
|
||||||
|
*
|
||||||
|
* @param[in] device The device to configure.
|
||||||
|
* @param[in] value The port index to enable gPTP on, or 0 to disable.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters or icsneoc2_error_set_settings_failure otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_enabled_port_set(icsneoc2_device_t* device, uint8_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if gPTP clock syntonization is enabled.
|
||||||
|
*
|
||||||
|
* @param[in] device The device to check.
|
||||||
|
* @param[out] value Pointer to store the clock syntonization enable state.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_clock_syntonization_enabled_get(icsneoc2_device_t* device, bool* value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable gPTP clock syntonization.
|
||||||
|
*
|
||||||
|
* @param[in] device The device to configure.
|
||||||
|
* @param[in] value The clock syntonization enable state to set.
|
||||||
|
*
|
||||||
|
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters or icsneoc2_error_set_settings_failure otherwise.
|
||||||
|
*/
|
||||||
|
icsneoc2_error_t icsneoc2_settings_gptp_clock_syntonization_enabled_set(icsneoc2_device_t* device, bool value);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -352,6 +352,41 @@ typedef enum _icsneoc2_misc_io_analog_voltage_t {
|
||||||
|
|
||||||
typedef uint8_t icsneoc2_misc_io_analog_voltage_t;
|
typedef uint8_t icsneoc2_misc_io_analog_voltage_t;
|
||||||
|
|
||||||
|
typedef enum _icsneoc2_gptp_profile_t {
|
||||||
|
icsneoc2_gptp_profile_standard = 0, // IEEE 802.1AS standard profile
|
||||||
|
icsneoc2_gptp_profile_automotive = 1, // Automotive gPTP profile
|
||||||
|
|
||||||
|
// Must be last entry. Don't use as a gPTP profile.
|
||||||
|
icsneoc2_gptp_profile_maxsize
|
||||||
|
} _icsneoc2_gptp_profile_t;
|
||||||
|
|
||||||
|
typedef uint8_t icsneoc2_gptp_profile_t;
|
||||||
|
|
||||||
|
typedef enum _icsneoc2_gptp_role_t {
|
||||||
|
icsneoc2_gptp_role_disabled = 0, // gPTP disabled on this port
|
||||||
|
icsneoc2_gptp_role_passive = 1, // Passive role
|
||||||
|
icsneoc2_gptp_role_master = 2, // Master role
|
||||||
|
icsneoc2_gptp_role_slave = 3, // Slave role
|
||||||
|
|
||||||
|
// Must be last entry. Don't use as a gPTP role.
|
||||||
|
icsneoc2_gptp_role_maxsize
|
||||||
|
} _icsneoc2_gptp_role_t;
|
||||||
|
|
||||||
|
typedef uint8_t icsneoc2_gptp_role_t;
|
||||||
|
|
||||||
|
typedef struct icsneoc2_gptp_status_t {
|
||||||
|
uint64_t current_time_seconds; // Current PTP time (seconds portion)
|
||||||
|
uint32_t current_time_nanoseconds; // Current PTP time (nanoseconds portion)
|
||||||
|
int64_t ms_offset_ns; // Master-slave clock offset in nanoseconds
|
||||||
|
uint8_t is_sync; // Non-zero if the clock is synchronized
|
||||||
|
uint8_t link_status; // Non-zero if the link is up
|
||||||
|
int64_t link_delay_ns; // One-way propagation delay in nanoseconds
|
||||||
|
uint8_t selected_role; // Negotiated port role (see icsneoc2_gptp_role_t)
|
||||||
|
uint8_t as_capable; // Non-zero if the port is AS-capable (802.1AS)
|
||||||
|
uint8_t is_syntonized; // Non-zero if frequency is locked to grandmaster
|
||||||
|
uint8_t short_format; // Non-zero if firmware returned a partial response
|
||||||
|
} icsneoc2_gptp_status_t;
|
||||||
|
|
||||||
typedef struct icsneoc2_disk_details_t icsneoc2_disk_details_t;
|
typedef struct icsneoc2_disk_details_t icsneoc2_disk_details_t;
|
||||||
|
|
||||||
typedef enum _icsneoc2_disk_layout_t {
|
typedef enum _icsneoc2_disk_layout_t {
|
||||||
|
|
|
||||||
|
|
@ -299,6 +299,22 @@ TEST(icsneoc2, test_icsneoc2_error_invalid_parameters_and_invalid_device)
|
||||||
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_disabled_get(NULL, &placeholderBool));
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_disabled_get(NULL, &placeholderBool));
|
||||||
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_readonly_get(NULL, &placeholderBool));
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_readonly_get(NULL, &placeholderBool));
|
||||||
|
|
||||||
|
// gPTP settings NULL parameter checks
|
||||||
|
icsneoc2_gptp_profile_t placeholderGptpProfile = 0;
|
||||||
|
icsneoc2_gptp_role_t placeholderGptpRole = 0;
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_profile_get(NULL, &placeholderGptpProfile));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_profile_get(NULL, NULL));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_profile_set(NULL, placeholderGptpProfile));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_role_get(NULL, &placeholderGptpRole));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_role_get(NULL, NULL));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_role_set(NULL, placeholderGptpRole));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_enabled_port_get(NULL, &placeholderInteger8));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_enabled_port_get(NULL, NULL));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_enabled_port_set(NULL, 0));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_clock_syntonization_enabled_get(NULL, &placeholderBool));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_clock_syntonization_enabled_get(NULL, NULL));
|
||||||
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_gptp_clock_syntonization_enabled_set(NULL, false));
|
||||||
|
|
||||||
// Disk formatting functions
|
// Disk formatting functions
|
||||||
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_disk_count_get(NULL, &placeholderSizeT));
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_disk_count_get(NULL, &placeholderSizeT));
|
||||||
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_supports_disk_formatting(NULL, &placeholderBool));
|
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_supports_disk_formatting(NULL, &placeholderBool));
|
||||||
|
|
@ -1763,4 +1779,29 @@ TEST(icsneoc2, test_icsneoc2_eth_invalid_type)
|
||||||
ASSERT_EQ(icsneoc2_error_success, icsneoc2_message_free(can_msg));
|
ASSERT_EQ(icsneoc2_error_success, icsneoc2_message_free(can_msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(icsneoc2, test_gptp_enum_values)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(icsneoc2_gptp_profile_standard, 0);
|
||||||
|
ASSERT_EQ(icsneoc2_gptp_profile_automotive, 1);
|
||||||
|
ASSERT_EQ(sizeof(icsneoc2_gptp_profile_t), sizeof(uint8_t));
|
||||||
|
|
||||||
|
ASSERT_EQ(icsneoc2_gptp_role_disabled, 0);
|
||||||
|
ASSERT_EQ(icsneoc2_gptp_role_passive, 1);
|
||||||
|
ASSERT_EQ(icsneoc2_gptp_role_master, 2);
|
||||||
|
ASSERT_EQ(icsneoc2_gptp_role_slave, 3);
|
||||||
|
ASSERT_EQ(sizeof(icsneoc2_gptp_role_t), sizeof(uint8_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(icsneoc2, test_gptp_enum_alignment)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(RADGPTPProfile::RAD_GPTP_PROFILE_STANDARD, icsneoc2_gptp_profile_standard);
|
||||||
|
ASSERT_EQ(RADGPTPProfile::RAD_GPTP_PROFILE_AUTOMOTIVE, icsneoc2_gptp_profile_automotive);
|
||||||
|
ASSERT_EQ(sizeof(RADGPTPProfile), sizeof(icsneoc2_gptp_profile_t));
|
||||||
|
|
||||||
|
ASSERT_EQ(RADGPTPRole::RAD_GPTP_ROLE_DISABLED, icsneoc2_gptp_role_disabled);
|
||||||
|
ASSERT_EQ(RADGPTPRole::RAD_GPTP_ROLE_PASSIVE, icsneoc2_gptp_role_passive);
|
||||||
|
ASSERT_EQ(RADGPTPRole::RAD_GPTP_ROLE_MASTER, icsneoc2_gptp_role_master);
|
||||||
|
ASSERT_EQ(RADGPTPRole::RAD_GPTP_ROLE_SLAVE, icsneoc2_gptp_role_slave);
|
||||||
|
ASSERT_EQ(sizeof(RADGPTPRole), sizeof(icsneoc2_gptp_role_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue