diff --git a/bindings/python/icsneopy/device/idevicesettings.cpp b/bindings/python/icsneopy/device/idevicesettings.cpp index 7569cf0..3ab48e0 100644 --- a/bindings/python/icsneopy/device/idevicesettings.cpp +++ b/bindings/python/icsneopy/device/idevicesettings.cpp @@ -104,6 +104,18 @@ void init_idevicesettings(pybind11::module_& m) { .def("set_t1s_max_burst", &IDeviceSettings::setT1SMaxBurstFor, pybind11::call_guard()) .def("get_t1s_burst_timer", &IDeviceSettings::getT1SBurstTimerFor, pybind11::call_guard()) .def("set_t1s_burst_timer", &IDeviceSettings::setT1SBurstTimerFor, pybind11::call_guard()) + .def("get_t1s_local_id_alternate", &IDeviceSettings::getT1SLocalIDAlternateFor, pybind11::call_guard()) + .def("set_t1s_local_id_alternate", &IDeviceSettings::setT1SLocalIDAlternateFor, pybind11::call_guard()) + .def("is_t1s_termination_enabled", &IDeviceSettings::isT1STerminationEnabledFor, pybind11::call_guard()) + .def("set_t1s_termination", &IDeviceSettings::setT1STerminationFor, pybind11::call_guard()) + .def("is_t1s_bus_decoding_beacons_enabled", &IDeviceSettings::isT1SBusDecodingBeaconsEnabledFor, pybind11::call_guard()) + .def("set_t1s_bus_decoding_beacons", &IDeviceSettings::setT1SBusDecodingBeaconsFor, pybind11::call_guard()) + .def("is_t1s_bus_decoding_all_enabled", &IDeviceSettings::isT1SBusDecodingAllEnabledFor, pybind11::call_guard()) + .def("set_t1s_bus_decoding_all", &IDeviceSettings::setT1SBusDecodingAllFor, pybind11::call_guard()) + .def("get_t1s_multi_id_enable_mask", &IDeviceSettings::getT1SMultiIDEnableMaskFor, pybind11::call_guard()) + .def("set_t1s_multi_id_enable_mask", &IDeviceSettings::setT1SMultiIDEnableMaskFor, pybind11::call_guard()) + .def("get_t1s_multi_id", &IDeviceSettings::getT1SMultiIDFor, pybind11::call_guard()) + .def("set_t1s_multi_id", &IDeviceSettings::setT1SMultiIDFor, pybind11::call_guard()) .def("set_misc_io_analog_output_enabled", &IDeviceSettings::setMiscIOAnalogOutputEnabled, pybind11::call_guard()) .def("set_misc_io_analog_output", &IDeviceSettings::setMiscIOAnalogOutput, pybind11::call_guard()) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 54c9c67..20fde5e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -19,6 +19,7 @@ option(LIBICSNEO_BUILD_CPP_SPI_EXAMPLE "Build the SPI example." ON) 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_DISKFORMAT_EXAMPLE "Build the disk format example." ON) +option(LIBICSNEO_BUILD_CPP_T1S_EXAMPLE "Build the T1S example." ON) add_compile_options(${LIBICSNEO_COMPILER_WARNINGS}) @@ -105,3 +106,7 @@ endif() if(LIBICSNEO_BUILD_CPP_DISKFORMAT_EXAMPLE) add_subdirectory(cpp/diskformat) endif() + +if(LIBICSNEO_BUILD_CPP_T1S_EXAMPLE) + add_subdirectory(cpp/t1s) +endif() diff --git a/examples/cpp/t1s/CMakeLists.txt b/examples/cpp/t1s/CMakeLists.txt new file mode 100644 index 0000000..c74f9bb --- /dev/null +++ b/examples/cpp/t1s/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(libicsneocpp-t1s-settings src/T1SSettingsExample.cpp) +target_link_libraries(libicsneocpp-t1s-settings icsneocpp) + +add_executable(libicsneocpp-t1s-symbol-decoding src/T1SSymbolDecodingExample.cpp) +target_link_libraries(libicsneocpp-t1s-symbol-decoding icsneocpp) diff --git a/examples/cpp/t1s/src/T1SSettingsExample.cpp b/examples/cpp/t1s/src/T1SSettingsExample.cpp new file mode 100644 index 0000000..cd8b2ca --- /dev/null +++ b/examples/cpp/t1s/src/T1SSettingsExample.cpp @@ -0,0 +1,326 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "icsneo/icsneocpp.h" + +template +std::string optToString(const std::optional& opt) { + if (!opt.has_value()) + return "N/A"; + if constexpr (std::is_same_v) + return opt.value() ? "true" : "false"; + else + return std::to_string(opt.value()); +} + +bool getUserConfirmation(const std::string& prompt) { + std::string input; + std::cout << prompt << " (y/n): " << std::flush; + std::getline(std::cin, input); + if (!input.empty()) { + char c = std::tolower(input[0]); + return (c == 'y'); + } + return false; +} + +std::vector selectNetworks(const std::vector& availableNetworks) { + std::vector selectedNetworks; + + std::cout << "\n" << std::string(70, '=') << std::endl; + std::cout << "Select T1S Networks to Configure" << std::endl; + std::cout << std::string(70, '=') << std::endl; + + for (size_t i = 0; i < availableNetworks.size(); i++) { + std::cout << " [" << (i + 1) << "] " << icsneo::Network(availableNetworks[i]) << std::endl; + } + + std::cout << "\nEnter network numbers to configure (e.g., '1,3' or '1-3' or 'all'): " << std::flush; + std::string input; + std::getline(std::cin, input); + + if (input.empty()) + return selectedNetworks; + + std::transform(input.begin(), input.end(), input.begin(), ::tolower); + + if (input == "all") { + return availableNetworks; + } + + std::stringstream ss(input); + std::string token; + while (std::getline(ss, token, ',')) { + token.erase(0, token.find_first_not_of(" \t")); + token.erase(token.find_last_not_of(" \t") + 1); + + size_t dashPos = token.find('-'); + if (dashPos != std::string::npos) { + try { + int start = std::stoi(token.substr(0, dashPos)); + int end = std::stoi(token.substr(dashPos + 1)); + for (int i = start; i <= end; i++) { + if (i >= 1 && i <= (int)availableNetworks.size()) { + selectedNetworks.push_back(availableNetworks[i - 1]); + } + } + } catch (...) {} + } else { + try { + int num = std::stoi(token); + if (num >= 1 && num <= (int)availableNetworks.size()) { + selectedNetworks.push_back(availableNetworks[num - 1]); + } + } catch (...) {} + } + } + + return selectedNetworks; +} + +uint8_t getUint8Input(const std::string& prompt, uint8_t defaultValue) { + std::string input; + std::cout << prompt << " [" << (int)defaultValue << "]: " << std::flush; + std::getline(std::cin, input); + if (input.empty()) + return defaultValue; + try { + int val = std::stoi(input); + if (val >= 0 && val <= 255) + return static_cast(val); + } catch (...) {} + return defaultValue; +} + +uint16_t getUint16Input(const std::string& prompt, uint16_t defaultValue) { + std::string input; + std::cout << prompt << " [" << (int)defaultValue << "]: " << std::flush; + std::getline(std::cin, input); + if (input.empty()) + return defaultValue; + try { + int val = std::stoi(input); + if (val >= 0 && val <= 65535) + return static_cast(val); + } catch (...) {} + return defaultValue; +} + +void displayT1SSettings(const std::shared_ptr& device, icsneo::Network::NetID netId) { + std::cout << "\t" << icsneo::Network(netId) << " T1S Settings:" << std::endl; + + std::cout << "\t PLCA Enabled: " << optToString(device->settings->isT1SPLCAEnabledFor(netId)) << std::endl; + std::cout << "\t Local ID: " << optToString(device->settings->getT1SLocalIDFor(netId)) << std::endl; + std::cout << "\t Max Nodes: " << optToString(device->settings->getT1SMaxNodesFor(netId)) << std::endl; + std::cout << "\t TX Opp Timer: " << optToString(device->settings->getT1STxOppTimerFor(netId)) << std::endl; + std::cout << "\t Max Burst: " << optToString(device->settings->getT1SMaxBurstFor(netId)) << std::endl; + std::cout << "\t Burst Timer: " << optToString(device->settings->getT1SBurstTimerFor(netId)) << std::endl; + + auto termEnabled = device->settings->isT1STerminationEnabledFor(netId); + if (termEnabled.has_value()) + std::cout << "\t Termination: " << optToString(termEnabled) << std::endl; + + auto localIdAlt = device->settings->getT1SLocalIDAlternateFor(netId); + if (localIdAlt.has_value()) { + std::cout << "\t Local ID Alternate: " << optToString(localIdAlt) << std::endl; + std::cout << "\t Bus Dec Beacons: " << optToString(device->settings->isT1SBusDecodingBeaconsEnabledFor(netId)) << std::endl; + std::cout << "\t Bus Dec All: " << optToString(device->settings->isT1SBusDecodingAllEnabledFor(netId)) << std::endl; + + auto multiIdMask = device->settings->getT1SMultiIDEnableMaskFor(netId); + if (multiIdMask.has_value()) { + std::cout << "\t Multi-ID Mask: 0x" << std::hex << std::setw(2) << std::setfill('0') + << (int)multiIdMask.value() << std::dec << std::endl; + std::cout << "\t Multi-IDs: "; + for (uint8_t i = 0; i < 7; i++) { + if (i > 0) std::cout << ", "; + auto multiId = device->settings->getT1SMultiIDFor(netId, i); + std::cout << "[" << (int)i << "]=" << optToString(multiId); + } + std::cout << std::endl; + } + } + std::cout << std::endl; +} + +void configureT1SNetwork(std::shared_ptr& device, icsneo::Network::NetID netId) { + std::cout << "\n" << std::string(70, '=') << std::endl; + std::cout << "Configuring T1S Network: " << icsneo::Network(netId) << std::endl; + std::cout << std::string(70, '=') << std::endl; + + std::cout << "\n--- Basic PLCA Settings ---" << std::endl; + bool plcaEnabled = getUserConfirmation("Enable PLCA"); + device->settings->setT1SPLCAFor(netId, plcaEnabled); + + uint8_t localId = getUint8Input("Local ID (0-255)", 1); + device->settings->setT1SLocalIDFor(netId, localId); + + uint8_t maxNodes = getUint8Input("Max Nodes (0-255)", 8); + device->settings->setT1SMaxNodesFor(netId, maxNodes); + + uint8_t txOppTimer = getUint8Input("TX Opportunity Timer (0-255)", 20); + device->settings->setT1STxOppTimerFor(netId, txOppTimer); + + uint16_t maxBurst = getUint16Input("Max Burst (0-65535)", 128); + device->settings->setT1SMaxBurstFor(netId, maxBurst); + + uint16_t burstTimer = getUint16Input("Burst Timer (0-65535)", 64); + device->settings->setT1SBurstTimerFor(netId, burstTimer); + + if (device->settings->isT1STerminationEnabledFor(netId).has_value()) { + std::cout << "\n--- Termination Settings ---" << std::endl; + bool termEnabled = getUserConfirmation("Enable Termination"); + device->settings->setT1STerminationFor(netId, termEnabled); + } + + if (device->settings->getT1SLocalIDAlternateFor(netId).has_value()) { + std::cout << "\n--- Extended Settings ---" << std::endl; + uint8_t localIdAlt = getUint8Input("Local ID Alternate (0-255)", 0); + device->settings->setT1SLocalIDAlternateFor(netId, localIdAlt); + + bool busDecBeacons = getUserConfirmation("Enable Bus Decoding (Beacons)"); + device->settings->setT1SBusDecodingBeaconsFor(netId, busDecBeacons); + + bool busDecAll = getUserConfirmation("Enable Bus Decoding (All Symbols)"); + device->settings->setT1SBusDecodingAllFor(netId, busDecAll); + + if (getUserConfirmation("Configure Multi-ID settings?")) { + uint8_t multiIdMask = getUint8Input("Multi-ID Enable Mask (0x00-0xFF, hex)", 0x00); + device->settings->setT1SMultiIDEnableMaskFor(netId, multiIdMask); + + std::cout << "Configure Multi-IDs (7 slots):" << std::endl; + for (uint8_t i = 0; i < 7; i++) { + uint8_t multiId = getUint8Input(" Multi-ID [" + std::to_string(i) + "]", 0); + device->settings->setT1SMultiIDFor(netId, i, multiId); + } + } + } + + std::cout << "\n✓ Configuration complete for " << icsneo::Network(netId) << std::endl; +} + +int main() { + std::cout << "\n" << std::string(70, '=') << std::endl; + std::cout << "10BASE-T1S SETTINGS CONFIGURATION EXAMPLE" << std::endl; + std::cout << std::string(70, '=') << std::endl; + std::cout << "libicsneo " << icsneo::GetVersion() << std::endl; + std::cout << std::string(70, '=') << std::endl; + + std::cout << "\nFinding devices... " << std::flush; + auto devices = icsneo::FindAllDevices(); + std::cout << "OK, " << devices.size() << " device" << (devices.size() == 1 ? "" : "s") << " found" << std::endl; + + if (devices.empty()) { + std::cout << "No devices found!" << std::endl; + return 1; + } + + for(auto& device : devices) + std::cout << " " << device->describe() << std::endl; + + std::shared_ptr selectedDevice; + for(auto& device : devices) { + if (device->getType() == icsneo::DeviceType::RADComet3) { + selectedDevice = device; + break; + } + } + + if (!selectedDevice && !devices.empty()) + selectedDevice = devices[0]; + + if (!selectedDevice) { + std::cout << "No suitable device found!" << std::endl; + return 1; + } + + std::cout << "\nSelected device: " << selectedDevice->describe() << std::endl; + std::cout << "Serial: " << selectedDevice->getSerial() << std::endl; + + std::cout << "\nOpening device... " << std::flush; + if (!selectedDevice->open()) { + std::cout << "✗ Failed" << std::endl; + std::cout << icsneo::GetLastError() << std::endl; + return 1; + } + std::cout << "✓" << std::endl; + + std::vector candidateNetworks = { + icsneo::Network::NetID::AE_01, icsneo::Network::NetID::AE_02, + icsneo::Network::NetID::AE_03, icsneo::Network::NetID::AE_04, + icsneo::Network::NetID::AE_05, icsneo::Network::NetID::AE_06, + icsneo::Network::NetID::AE_07, icsneo::Network::NetID::AE_08, + icsneo::Network::NetID::AE_09, icsneo::Network::NetID::AE_10 + }; + + std::vector t1sNetworks; + for (auto netId : candidateNetworks) { + auto localId = selectedDevice->settings->getT1SLocalIDFor(netId); + if (localId.has_value()) + t1sNetworks.push_back(netId); + } + + if (t1sNetworks.empty()) { + std::cout << "No T1S networks found on this device" << std::endl; + selectedDevice->close(); + return 1; + } + + std::cout << "\nFound " << t1sNetworks.size() << " T1S network" + << (t1sNetworks.size() == 1 ? "" : "s") << ":" << std::endl; + for (size_t i = 0; i < t1sNetworks.size(); i++) + std::cout << " [" << (i + 1) << "] " << icsneo::Network(t1sNetworks[i]) << std::endl; + + std::cout << "\n" << std::string(70, '-') << std::endl; + std::cout << "Current T1S Settings:" << std::endl; + std::cout << std::string(70, '-') << std::endl; + for (auto netId : t1sNetworks) + displayT1SSettings(selectedDevice, netId); + + auto networksToConfig = selectNetworks(t1sNetworks); + + if (networksToConfig.empty()) { + std::cout << "\nNo networks selected for configuration." << std::endl; + std::cout << "Closing device... " << std::flush; + selectedDevice->close(); + std::cout << "✓" << std::endl; + return 0; + } + + std::cout << "\nConfiguring " << networksToConfig.size() << " network" + << (networksToConfig.size() == 1 ? "" : "s") << "..." << std::endl; + + for (auto netId : networksToConfig) + configureT1SNetwork(selectedDevice, netId); + + std::cout << "\n" << std::string(70, '=') << std::endl; + bool saveToEEPROM = getUserConfirmation("Save settings to EEPROM (permanent)?"); + std::cout << std::string(70, '=') << std::endl; + + std::cout << "\nApplying settings" << (saveToEEPROM ? " to EEPROM" : " temporarily") << "... " << std::flush; + bool success = selectedDevice->settings->apply(!saveToEEPROM); + if (!success) { + std::cout << "✗ Failed" << std::endl; + std::cout << icsneo::GetLastError() << std::endl; + selectedDevice->close(); + return 1; + } + std::cout << "✓" << std::endl; + + std::cout << "\n" << std::string(70, '-') << std::endl; + std::cout << "Updated T1S Settings:" << std::endl; + std::cout << std::string(70, '-') << std::endl; + for (auto netId : t1sNetworks) + displayT1SSettings(selectedDevice, netId); + + std::cout << "Closing device... " << std::flush; + selectedDevice->close(); + std::cout << "✓" << std::endl; + + return 0; +} diff --git a/examples/cpp/t1s/src/T1SSymbolDecodingExample.cpp b/examples/cpp/t1s/src/T1SSymbolDecodingExample.cpp new file mode 100644 index 0000000..0625617 --- /dev/null +++ b/examples/cpp/t1s/src/T1SSymbolDecodingExample.cpp @@ -0,0 +1,357 @@ +// 10BASE-T1S Symbol Decoding Example +// Demonstrates T1S bus symbol decoding and analysis + +#include +#include +#include +#include +#include +#include +#include + +#include "icsneo/icsneocpp.h" + +enum class T1SSymbol : uint8_t { + SSD = 0x04, + ESDOK = 0x07, + BEACON = 0x08, + ESD = 0x0D, + ESDERR = 0x11, + SYNC = 0x18, + ESDJAB = 0x19, + SILENCE = 0x1F +}; + +std::string getSymbolName(uint8_t value) { + switch(static_cast(value)) { + case T1SSymbol::SSD: return "SSD"; + case T1SSymbol::ESDOK: return "ESDOK"; + case T1SSymbol::BEACON: return "BEACON"; + case T1SSymbol::ESD: return "ESD"; + case T1SSymbol::ESDERR: return "ESDERR"; + case T1SSymbol::SYNC: return "SYNC"; + case T1SSymbol::ESDJAB: return "ESDJAB"; + case T1SSymbol::SILENCE: return "SILENCE"; + default: + if (value <= 0x0F) { + std::stringstream ss; + ss << "DATA(0x" << std::hex << std::uppercase << (int)value << ")"; + return ss.str(); + } + std::stringstream ss; + ss << "UNKNOWN(0x" << std::hex << std::uppercase << std::setw(2) + << std::setfill('0') << (int)value << std::setfill(' ') << ")"; + return ss.str(); + } +} + +struct T1SStatistics { + std::atomic symbolCount{0}; + std::atomic beaconCount{0}; + std::atomic wakeCount{0}; + std::atomic burstCount{0}; + std::atomic dataFrameCount{0}; + std::map symbolStats; + + void reset() { + symbolCount = 0; + beaconCount = 0; + wakeCount = 0; + burstCount = 0; + dataFrameCount = 0; + symbolStats.clear(); + } + + void print() const { + std::cout << std::setfill(' '); + + std::cout << "\n" << std::string(70, '=') << std::endl; + std::cout << "T1S SYMBOL DECODING STATISTICS" << std::endl; + std::cout << std::string(70, '=') << std::endl; + + std::cout << "Total Symbols: " << symbolCount << std::endl; + std::cout << "Total Beacons: " << beaconCount << std::endl; + std::cout << "Total Wake Signals: " << wakeCount << std::endl; + std::cout << "Total Bursts: " << burstCount << std::endl; + std::cout << "Total Data Frames: " << dataFrameCount << std::endl; + + if (!symbolStats.empty()) { + std::cout << "\n" << std::string(70, '-') << std::endl; + std::cout << "Symbol Type Breakdown:" << std::endl; + std::cout << std::string(70, '-') << std::endl; + std::vector> sortedStats( + symbolStats.begin(), symbolStats.end()); + std::sort(sortedStats.begin(), sortedStats.end(), + [](const auto& a, const auto& b) { return a.second > b.second; }); + + for (const auto& [name, count] : sortedStats) { + std::cout << " " << std::left << std::setw(20) << name + << std::right << std::setw(10) << count << std::endl; + } + } + std::cout << std::string(70, '=') << std::endl; + } +}; + +bool getUserConfirmation(const std::string& prompt) { + std::string input; + std::cout << prompt << " (y/n): " << std::flush; + std::getline(std::cin, input); + if (!input.empty()) { + char c = std::tolower(input[0]); + return (c == 'y'); + } + return false; +} + +bool configureT1SDecoding(std::shared_ptr& device, icsneo::Network::NetID network, + bool enableSymbols, bool enableBeacons) { + std::cout << "\nConfiguring T1S decoding on network " << icsneo::Network(network) << "..." << std::endl; + if (!device->settings->setT1SBusDecodingAllFor(network, enableSymbols)) { + std::cerr << " ✗ Failed to set T1S symbol decoding" << std::endl; + return false; + } + if (enableSymbols) { + std::cout << " ✓ Enabled decoding of all T1S symbols" << std::endl; + } else { + std::cout << " • T1S symbol decoding disabled" << std::endl; + } + + if (!device->settings->setT1SBusDecodingBeaconsFor(network, enableBeacons)) { + std::cerr << " ✗ Failed to set T1S beacon decoding" << std::endl; + return false; + } + if (enableBeacons) { + std::cout << " ✓ Enabled T1S beacon decoding" << std::endl; + } else { + std::cout << " • T1S beacon decoding disabled" << std::endl; + } + + if (!device->settings->apply(true)) { + std::cerr << " ✗ Failed to apply settings to device" << std::endl; + std::cerr << " " << icsneo::GetLastError() << std::endl; + return false; + } + std::cout << " ✓ Settings applied successfully" << std::endl; + + return true; +} + +void setupSymbolMonitoring(std::shared_ptr& device, + icsneo::Network::NetID network, + T1SStatistics& stats) { + + auto callback = std::make_shared( + icsneo::MessageFilter(network), + [&stats](std::shared_ptr message) { + if (message->type != icsneo::Message::Type::Frame) + return; + + auto frame = std::static_pointer_cast(message); + auto netType = frame->network.getType(); + if (netType != icsneo::Network::Type::Ethernet && netType != icsneo::Network::Type::AutomotiveEthernet) + return; + + auto ethMsg = std::static_pointer_cast(frame); + + if (!ethMsg->isT1S) + return; + + double timestamp_ms = ethMsg->timestamp / 1000000.0; + + if (ethMsg->isT1SSymbol) { + size_t numSymbols = ethMsg->data.size(); + + std::cout << std::fixed << std::setprecision(3) + << "[" << std::setw(12) << timestamp_ms << " ms] " + << "T1S Symbols"; + + if (numSymbols > 0) { + std::cout << " (" << numSymbols << " symbol" << (numSymbols > 1 ? "s" : "") << ")"; + } + std::cout << " | Node ID: " << (int)ethMsg->t1sNodeId << std::endl; + + for (size_t i = 0; i < numSymbols; i++) { + uint8_t symbolValue = ethMsg->data[i]; + std::string symbolName = getSymbolName(symbolValue); + + stats.symbolCount++; + stats.symbolStats[symbolName]++; + + if (symbolValue == static_cast(T1SSymbol::BEACON)) { + stats.beaconCount++; + } + + std::cout << " [" << i << "] " << std::left << std::setw(10) << symbolName << std::right + << " = 0x" << std::hex << std::uppercase << std::setw(2) + << std::setfill('0') << (int)symbolValue << std::setfill(' ') + << std::dec << std::endl; + } + + if (numSymbols == 0 && ethMsg->t1sSymbolType != 0) { + uint8_t symbolValue = ethMsg->t1sSymbolType; + std::string symbolName = getSymbolName(symbolValue); + + stats.symbolCount++; + stats.symbolStats[symbolName]++; + + if (symbolValue == static_cast(T1SSymbol::BEACON)) { + stats.beaconCount++; + } + + std::cout << " " << std::left << std::setw(10) << symbolName << std::right + << " = 0x" << std::hex << std::uppercase << std::setw(2) + << std::setfill('0') << (int)symbolValue << std::setfill(' ') + << std::dec << " (from t1sSymbolType field)" << std::endl; + } + } + else if (ethMsg->isT1SBurst) { + stats.burstCount++; + std::cout << std::fixed << std::setprecision(3) + << "[" << std::setw(12) << timestamp_ms << " ms] " + << "BURST | " + << "Node ID: " << (int)ethMsg->t1sNodeId << " | " + << "Burst Count: " << (int)ethMsg->t1sBurstCount << std::endl; + } + else if (ethMsg->isT1SWake) { + stats.wakeCount++; + std::cout << std::fixed << std::setprecision(3) + << "[" << std::setw(12) << timestamp_ms << " ms] " + << "WAKE signal detected | " + << "Node ID: " << (int)ethMsg->t1sNodeId << std::endl; + } + else { + stats.dataFrameCount++; + std::cout << std::fixed << std::setprecision(3) + << "[" << std::setw(12) << timestamp_ms << " ms] " + << "T1S Data Frame | " + << "Length: " << ethMsg->data.size() << " bytes | " + << "Node ID: " << (int)ethMsg->t1sNodeId << std::endl; + + if (!ethMsg->data.empty()) { + std::cout << " Data: "; + size_t preview_len = std::min(ethMsg->data.size(), size_t(16)); + for (size_t i = 0; i < preview_len; i++) { + std::cout << std::hex << std::uppercase << std::setw(2) + << std::setfill('0') << (int)ethMsg->data[i] << " "; + } + if (ethMsg->data.size() > 16) + std::cout << "..."; + std::cout << std::setfill(' ') << std::dec << std::endl; + } + } + } + ); + + device->addMessageCallback(callback); +} + +int main() { + const icsneo::Network::NetID MONITOR_NETWORK = icsneo::Network::NetID::AE_02; + const int MONITOR_DURATION_SECONDS = 30; + + std::cout << "\n" << std::string(70, '=') << std::endl; + std::cout << "10BASE-T1S SYMBOL DECODING EXAMPLE" << std::endl; + std::cout << std::string(70, '=') << std::endl; + std::cout << "libicsneo " << icsneo::GetVersion() << std::endl; + std::cout << std::string(70, '=') << std::endl; + + std::cout << "\nFinding devices... " << std::flush; + auto devices = icsneo::FindAllDevices(); + std::cout << "OK, " << devices.size() << " device" << (devices.size() == 1 ? "" : "s") << " found" << std::endl; + + if (devices.empty()) { + std::cerr << "No devices found!" << std::endl; + return 1; + } + + // List devices + for (const auto& device : devices) { + std::cout << " " << device->describe() << std::endl; + } + + std::shared_ptr device; + for (auto& dev : devices) { + if (dev->getType() == icsneo::DeviceType::RADComet3) { + device = dev; + break; + } + } + + if (!device && !devices.empty()) + device = devices[0]; + + if (!device) { + std::cerr << "No suitable device found!" << std::endl; + return 1; + } + + std::cout << "\nSelected device: " << device->describe() << std::endl; + std::cout << "Serial: " << device->getSerial() << std::endl; + + std::cout << "\n" << std::string(70, '-') << std::endl; + std::cout << "T1S DECODING CONFIGURATION" << std::endl; + std::cout << std::string(70, '-') << std::endl; + bool enableSymbols = getUserConfirmation("Enable T1S symbol decoding (all symbols)"); + bool enableBeacons = getUserConfirmation("Enable T1S beacon decoding"); + std::cout << std::string(70, '-') << std::endl; + + std::cout << "\nOpening device... " << std::flush; + if (!device->open()) { + std::cerr << "✗ Failed" << std::endl; + std::cerr << " " << icsneo::GetLastError() << std::endl; + return 1; + } + std::cout << "✓" << std::endl; + + std::cout << "Enabling message polling... " << std::flush; + if (!device->enableMessagePolling()) { + std::cerr << "✗ Failed" << std::endl; + std::cerr << " " << icsneo::GetLastError() << std::endl; + device->close(); + return 1; + } + device->setPollingMessageLimit(100000); + std::cout << "✓" << std::endl; + + if (!configureT1SDecoding(device, MONITOR_NETWORK, enableSymbols, enableBeacons)) { + device->close(); + return 1; + } + + std::cout << "Going online... " << std::flush; + if (!device->goOnline()) { + std::cerr << "✗ Failed" << std::endl; + std::cerr << " " << icsneo::GetLastError() << std::endl; + device->close(); + return 1; + } + std::cout << "✓" << std::endl; + + T1SStatistics stats; + setupSymbolMonitoring(device, MONITOR_NETWORK, stats); + + std::cout << "\n" << std::string(70, '-') << std::endl; + std::cout << "Monitoring T1S traffic for " << MONITOR_DURATION_SECONDS << " seconds..." << std::endl; + std::cout << std::string(70, '-') << std::endl; + + auto startTime = std::chrono::steady_clock::now(); + std::vector> messages; + messages.reserve(10000); + + while (std::chrono::steady_clock::now() - startTime < std::chrono::seconds(MONITOR_DURATION_SECONDS)) { + device->getMessages(messages); + messages.clear(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + + std::cout << "\n" << std::string(70, '-') << std::endl; + std::cout << "Closing device... " << std::flush; + device->close(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << "✓" << std::endl; + + stats.print(); + + return 0; +} diff --git a/examples/python/t1s/t1s_settings.py b/examples/python/t1s/t1s_settings.py new file mode 100644 index 0000000..28e5517 --- /dev/null +++ b/examples/python/t1s/t1s_settings.py @@ -0,0 +1,325 @@ +""" +10BASE-T1S Settings Configuration Example +Demonstrates interactive T1S network configuration +""" + +import icsneopy + + +def get_user_confirmation(prompt): + """Get yes/no confirmation from user.""" + response = input(f"{prompt} (y/n): ").strip().lower() + return response == 'y' + + +def select_networks(available_networks): + """Let user select which networks to configure.""" + print("\n" + "=" * 70) + print("Select T1S Networks to Configure") + print("=" * 70) + + for i, net_id in enumerate(available_networks, 1): + print(f" [{i}] {net_id}") + + response = input("\nEnter network numbers to configure (e.g., '1,3' or '1-3' or 'all'): ").strip().lower() + + if not response: + return [] + + if response == 'all': + return available_networks + + selected = [] + tokens = response.split(',') + + for token in tokens: + token = token.strip() + + if '-' in token: + try: + parts = token.split('-') + start = int(parts[0]) + end = int(parts[1]) + for i in range(start, end + 1): + if 1 <= i <= len(available_networks): + selected.append(available_networks[i - 1]) + except (ValueError, IndexError): + pass + else: + try: + num = int(token) + if 1 <= num <= len(available_networks): + selected.append(available_networks[num - 1]) + except ValueError: + pass + + return selected + + +def get_uint8_input(prompt, default_value): + """Get uint8 input from user with default.""" + response = input(f"{prompt} [{default_value}]: ").strip() + if not response: + return default_value + try: + val = int(response) + if 0 <= val <= 255: + return val + except ValueError: + pass + return default_value + + +def get_uint16_input(prompt, default_value): + """Get uint16 input from user with default.""" + response = input(f"{prompt} [{default_value}]: ").strip() + if not response: + return default_value + try: + val = int(response) + if 0 <= val <= 65535: + return val + except ValueError: + pass + return default_value + + +def opt_to_string(opt): + """Convert optional value to string for display.""" + if opt is None: + return "N/A" + if isinstance(opt, bool): + return "true" if opt else "false" + return str(opt) + + +def display_t1s_settings(device, network): + """Display T1S settings for a network.""" + print(f"\t{network} T1S Settings:") + + settings = device.get_settings() + if not settings: + print("\t Unable to read settings") + return + + print(f"\t PLCA Enabled: {opt_to_string(settings.get_t1s_plca_enabled(network))}") + print(f"\t Local ID: {opt_to_string(settings.get_t1s_local_id(network))}") + print(f"\t Max Nodes: {opt_to_string(settings.get_t1s_max_nodes(network))}") + print(f"\t TX Opp Timer: {opt_to_string(settings.get_t1s_tx_opp_timer(network))}") + print(f"\t Max Burst: {opt_to_string(settings.get_t1s_max_burst(network))}") + print(f"\t Burst Timer: {opt_to_string(settings.get_t1s_burst_timer(network))}") + + term_enabled = settings.get_t1s_termination_enabled(network) + if term_enabled is not None: + print(f"\t Termination: {opt_to_string(term_enabled)}") + + local_id_alt = settings.get_t1s_local_id_alternate(network) + if local_id_alt is not None: + print(f"\t Local ID Alternate: {opt_to_string(local_id_alt)}") + print(f"\t Bus Dec Beacons: {opt_to_string(settings.get_t1s_bus_decoding_beacons_enabled(network))}") + print(f"\t Bus Dec All: {opt_to_string(settings.get_t1s_bus_decoding_all_enabled(network))}") + + multi_id_mask = settings.get_t1s_multi_id_enable_mask(network) + if multi_id_mask is not None: + print(f"\t Multi-ID Mask: 0x{multi_id_mask:02X}") + print("\t Multi-IDs: ", end="") + multi_ids = [] + for i in range(7): + multi_id = settings.get_t1s_multi_id(network, i) + multi_ids.append(f"[{i}]={opt_to_string(multi_id)}") + print(", ".join(multi_ids)) + + print() + + +def configure_t1s_network(device, network): + """Interactively configure T1S settings for a network.""" + print("\n" + "=" * 70) + print(f"Configuring T1S Network: {network}") + print("=" * 70) + + settings = device.get_settings() + if not settings: + print("Unable to read settings") + return + + print("\n--- Basic PLCA Settings ---") + plca_enabled = get_user_confirmation("Enable PLCA") + settings.set_t1s_plca(network, plca_enabled) + + local_id = get_uint8_input("Local ID (0-255)", 1) + settings.set_t1s_local_id(network, local_id) + + max_nodes = get_uint8_input("Max Nodes (0-255)", 8) + settings.set_t1s_max_nodes(network, max_nodes) + + tx_opp_timer = get_uint8_input("TX Opportunity Timer (0-255)", 20) + settings.set_t1s_tx_opp_timer(network, tx_opp_timer) + + max_burst = get_uint16_input("Max Burst (0-65535)", 128) + settings.set_t1s_max_burst(network, max_burst) + + burst_timer = get_uint16_input("Burst Timer (0-65535)", 64) + settings.set_t1s_burst_timer(network, burst_timer) + + if settings.get_t1s_termination_enabled(network) is not None: + print("\n--- Termination Settings ---") + term_enabled = get_user_confirmation("Enable Termination") + settings.set_t1s_termination(network, term_enabled) + + if settings.get_t1s_local_id_alternate(network) is not None: + print("\n--- Extended Settings ---") + local_id_alt = get_uint8_input("Local ID Alternate (0-255)", 0) + settings.set_t1s_local_id_alternate(network, local_id_alt) + + bus_dec_beacons = get_user_confirmation("Enable Bus Decoding (Beacons)") + settings.set_t1s_bus_decoding_beacons(network, bus_dec_beacons) + + bus_dec_all = get_user_confirmation("Enable Bus Decoding (All Symbols)") + settings.set_t1s_bus_decoding_all(network, bus_dec_all) + + if get_user_confirmation("Configure Multi-ID settings?"): + multi_id_mask = get_uint8_input("Multi-ID Enable Mask (0x00-0xFF, hex)", 0x00) + settings.set_t1s_multi_id_enable_mask(network, multi_id_mask) + + print("Configure Multi-IDs (7 slots):") + for i in range(7): + multi_id = get_uint8_input(f" Multi-ID [{i}]", 0) + settings.set_t1s_multi_id(network, i, multi_id) + + if not device.set_settings(settings): + print("✗ Failed to update device settings") + else: + print(f"\n✓ Configuration complete for {network}") + + +def main(): + """Main T1S settings configuration example.""" + device = None + + try: + print("\n" + "=" * 70) + print("10BASE-T1S SETTINGS CONFIGURATION EXAMPLE") + print("=" * 70) + print(f"libicsneo {icsneopy.get_version()}") + print("=" * 70) + + print("\nFinding devices... ", end="", flush=True) + devices = icsneopy.find_all_devices() + print(f"OK, {len(devices)} device{'s' if len(devices) != 1 else ''} found") + + if not devices: + print("No devices found!") + return 1 + + for d in devices: + print(f" {d}") + + device = None + for d in devices: + if d.get_type() == icsneopy.DeviceType.RADComet3: + device = d + break + + if not device and devices: + device = devices[0] + + if not device: + print("No suitable device found!") + return 1 + + print(f"\nSelected device: {device}") + print(f"Serial: {device.get_serial()}") + + print("\nOpening device... ", end="", flush=True) + if not device.open(): + print("✗ Failed") + return 1 + print("✓") + + candidate_networks = [ + icsneopy.Network.NetID.AE_01, icsneopy.Network.NetID.AE_02, + icsneopy.Network.NetID.AE_03, icsneopy.Network.NetID.AE_04, + icsneopy.Network.NetID.AE_05, icsneopy.Network.NetID.AE_06, + icsneopy.Network.NetID.AE_07, icsneopy.Network.NetID.AE_08, + icsneopy.Network.NetID.AE_09, icsneopy.Network.NetID.AE_10 + ] + + settings = device.get_settings() + t1s_networks = [] + for net_id in candidate_networks: + local_id = settings.get_t1s_local_id(net_id) + if local_id is not None: + t1s_networks.append(net_id) + + if not t1s_networks: + print("No T1S networks found on this device") + device.close() + return 1 + + print(f"\nFound {len(t1s_networks)} T1S network{'s' if len(t1s_networks) != 1 else ''}:") + for i, net_id in enumerate(t1s_networks, 1): + print(f" [{i}] {net_id}") + + print("\n" + "-" * 70) + print("Current T1S Settings:") + print("-" * 70) + for net_id in t1s_networks: + display_t1s_settings(device, net_id) + + networks_to_config = select_networks(t1s_networks) + + if not networks_to_config: + print("\nNo networks selected for configuration.") + print("Closing device... ", end="", flush=True) + device.close() + print("✓") + return 0 + + print(f"\nConfiguring {len(networks_to_config)} network{'s' if len(networks_to_config) != 1 else ''}...") + + for net_id in networks_to_config: + configure_t1s_network(device, net_id) + + print("\n" + "=" * 70) + save_to_eeprom = get_user_confirmation("Save settings to EEPROM (permanent)?") + print("=" * 70) + + settings = device.get_settings() + print(f"\nApplying settings{' to EEPROM' if save_to_eeprom else ' temporarily'}... ", end="", flush=True) + success = settings.apply(not save_to_eeprom) + if not success: + print("✗ Failed") + device.close() + return 1 + print("✓") + + print("\n" + "-" * 70) + print("Updated T1S Settings:") + print("-" * 70) + for net_id in t1s_networks: + display_t1s_settings(device, net_id) + + print("Closing device... ", end="", flush=True) + device.close() + print("✓") + + except KeyboardInterrupt: + print("\n\nInterrupted by user") + return 1 + + except Exception as e: + print(f"\nError: {e}") + import traceback + traceback.print_exc() + return 1 + + finally: + if device and device.is_open(): + device.close() + + return 0 + + +if __name__ == "__main__": + exit(main()) diff --git a/examples/python/t1s/t1s_symbol_decoding.py b/examples/python/t1s/t1s_symbol_decoding.py new file mode 100644 index 0000000..2a1127d --- /dev/null +++ b/examples/python/t1s/t1s_symbol_decoding.py @@ -0,0 +1,282 @@ +""" +10BASE-T1S Symbol Decoding Example +Demonstrates T1S bus symbol decoding and analysis +""" + +import icsneopy +import time +from enum import IntEnum + + +class T1SSymbol(IntEnum): + """10BASE-T1S Symbol Types""" + SSD = 0x04 + ESDOK = 0x07 + BEACON = 0x08 + ESD = 0x0D + ESDERR = 0x11 + SYNC = 0x18 + ESDJAB = 0x19 + SILENCE = 0x1F + + @classmethod + def get_name(cls, value): + """Get human-readable name for symbol value.""" + try: + return cls(value).name + except ValueError: + if 0x00 <= value <= 0x0F: + return f"DATA(0x{value:X})" + return f"UNKNOWN(0x{value:02X})" + + +def get_user_confirmation(prompt): + """Get yes/no confirmation from user.""" + response = input(f"{prompt} (y/n): ").strip().lower() + return response == 'y' + + +def configure_t1s_decoding(device, network, enable_symbols, enable_beacons): + """Configure T1S bus decoding settings.""" + settings = device.get_settings() + if not settings: + raise RuntimeError("Failed to get device settings") + + print(f"\nConfiguring T1S decoding on network {network}...") + + if not settings.set_t1s_bus_decoding_all(network, enable_symbols): + raise RuntimeError("Failed to set T1S symbol decoding") + if enable_symbols: + print(" ✓ Enabled decoding of all T1S symbols") + else: + print(" • T1S symbol decoding disabled") + + if not settings.set_t1s_bus_decoding_beacons(network, enable_beacons): + raise RuntimeError("Failed to set T1S beacon decoding") + if enable_beacons: + print(" ✓ Enabled T1S beacon decoding") + else: + print(" • T1S beacon decoding disabled") + + if not device.set_settings(settings): + raise RuntimeError("Failed to apply settings to device") + print(" ✓ Settings applied successfully") + + +def setup_symbol_monitoring(device, network): + """Setup callback to monitor and decode T1S symbols.""" + state = { + 'symbol_count': 0, + 'beacon_count': 0, + 'wake_count': 0, + 'burst_count': 0, + 'symbol_stats': {}, + 'data_frame_count': 0 + } + + def symbol_handler(msg): + """Handle incoming T1S messages.""" + if not isinstance(msg, icsneopy.EthernetMessage): + return + + if not msg.isT1S: + return + + timestamp_ms = msg.timestamp / 1000000.0 + + if msg.isT1SSymbol: + num_symbols = len(msg.data) + + print(f"[{timestamp_ms:12.3f} ms] T1S Symbols", end="") + if num_symbols > 0: + print(f" ({num_symbols} symbol{'s' if num_symbols > 1 else ''})", end="") + print(f" | Node ID: {msg.t1sNodeId}") + + for i, symbol_value in enumerate(msg.data): + symbol_name = T1SSymbol.get_name(symbol_value) + + state['symbol_count'] += 1 + if symbol_name not in state['symbol_stats']: + state['symbol_stats'][symbol_name] = 0 + state['symbol_stats'][symbol_name] += 1 + + if symbol_value == T1SSymbol.BEACON: + state['beacon_count'] += 1 + + print(f" [{i}] {symbol_name:10s} = 0x{symbol_value:02X}") + + if num_symbols == 0 and msg.t1sSymbolType != 0: + symbol_value = msg.t1sSymbolType + symbol_name = T1SSymbol.get_name(symbol_value) + + state['symbol_count'] += 1 + if symbol_name not in state['symbol_stats']: + state['symbol_stats'][symbol_name] = 0 + state['symbol_stats'][symbol_name] += 1 + + if symbol_value == T1SSymbol.BEACON: + state['beacon_count'] += 1 + + print(f" {symbol_name:10s} = 0x{symbol_value:02X} (from t1sSymbolType field)") + + elif msg.isT1SBurst: + state['burst_count'] += 1 + print(f"[{timestamp_ms:12.3f} ms] BURST | " + f"Node ID: {msg.t1sNodeId} | " + f"Burst Count: {msg.t1sBurstCount}") + + elif msg.isT1SWake: + state['wake_count'] += 1 + print(f"[{timestamp_ms:12.3f} ms] WAKE signal detected | " + f"Node ID: {msg.t1sNodeId}") + + else: + state['data_frame_count'] += 1 + print(f"[{timestamp_ms:12.3f} ms] T1S Data Frame | " + f"Length: {len(msg.data)} bytes | " + f"Node ID: {msg.t1sNodeId}") + + if msg.data and len(msg.data) > 0: + preview = ' '.join([f"{b:02X}" for b in msg.data[:16]]) + if len(msg.data) > 16: + preview += " ..." + print(f" Data: {preview}") + + frame_filter = icsneopy.MessageFilter(network) + callback = icsneopy.MessageCallback(symbol_handler, frame_filter) + device.add_message_callback(callback) + + return state + + +def print_statistics(state): + """Print monitoring statistics.""" + print("\n" + "=" * 70) + print("T1S SYMBOL DECODING STATISTICS") + print("=" * 70) + print(f"Total Symbols: {state['symbol_count']}") + print(f"Total Beacons: {state['beacon_count']}") + print(f"Total Wake Signals: {state['wake_count']}") + print(f"Total Bursts: {state['burst_count']}") + print(f"Total Data Frames: {state['data_frame_count']}") + + if state['symbol_stats']: + print("\n" + "-" * 70) + print("Symbol Type Breakdown:") + print("-" * 70) + for symbol_name, count in sorted(state['symbol_stats'].items(), + key=lambda x: x[1], reverse=True): + print(f" {symbol_name:20s}{count:>10d}") + print("=" * 70) + + +def main(): + """Main T1S symbol decoding example.""" + device = None + + try: + MONITOR_NETWORK = icsneopy.Network.NetID.AE_02 + MONITOR_DURATION = 30 + + print("\n" + "=" * 70) + print("10BASE-T1S SYMBOL DECODING EXAMPLE") + print("=" * 70) + print(f"libicsneo {icsneopy.get_version()}") + print("=" * 70) + + print("\nFinding devices... ", end="", flush=True) + devices = icsneopy.find_all_devices() + print(f"OK, {len(devices)} device{'s' if len(devices) != 1 else ''} found") + + if not devices: + print("No devices found!") + return 1 + + for d in devices: + print(f" {d}") + + device = None + for d in devices: + if d.get_type() == icsneopy.DeviceType.RADComet3: + device = d + break + + if not device and devices: + device = devices[0] + + if not device: + print("No suitable device found!") + return 1 + + print(f"\nSelected device: {device}") + print(f"Serial: {device.get_serial()}") + + print("\n" + "-" * 70) + print("T1S DECODING CONFIGURATION") + print("-" * 70) + enable_symbols = get_user_confirmation("Enable T1S symbol decoding (all symbols)") + enable_beacons = get_user_confirmation("Enable T1S beacon decoding") + print("-" * 70) + + print("\nOpening device... ", end="", flush=True) + if not device.open(): + print("✗ Failed") + return 1 + print("✓") + + print("Enabling message polling... ", end="", flush=True) + if not device.enable_message_polling(): + print("✗ Failed") + device.close() + return 1 + device.set_polling_message_limit(100000) + print("✓") + + configure_t1s_decoding(device, MONITOR_NETWORK, enable_symbols, enable_beacons) + + print("Going online... ", end="", flush=True) + if not device.go_online(): + print("✗ Failed") + device.close() + return 1 + print("✓") + + state = setup_symbol_monitoring(device, MONITOR_NETWORK) + + print("\n" + "-" * 70) + print(f"Monitoring T1S traffic for {MONITOR_DURATION} seconds...") + print("-" * 70) + + start_time = time.time() + while time.time() - start_time < MONITOR_DURATION: + device.get_messages() + time.sleep(0.01) + + print("\n" + "-" * 70) + print("Closing device... ", end="", flush=True) + device.close() + time.sleep(0.1) + print("✓") + + print_statistics(state) + + except KeyboardInterrupt: + print("\n\nMonitoring interrupted by user") + if 'state' in locals(): + print_statistics(state) + + except Exception as e: + print(f"\nError: {e}") + import traceback + traceback.print_exc() + return 1 + + finally: + if device and device.is_open(): + device.close() + + return 0 + + +if __name__ == "__main__": + exit(main()) diff --git a/include/icsneo/device/idevicesettings.h b/include/icsneo/device/idevicesettings.h index 724f9f0..9f888c8 100644 --- a/include/icsneo/device/idevicesettings.h +++ b/include/icsneo/device/idevicesettings.h @@ -1194,6 +1194,77 @@ public: return false; } + virtual std::optional getT1SLocalIDAlternateFor(Network net) const { + (void)net; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return std::nullopt; + } + + virtual bool setT1SLocalIDAlternateFor(Network net, uint8_t id) { + (void)net; (void)id; + return false; + } + + virtual std::optional isT1STerminationEnabledFor(Network net) const { + (void)net; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return std::nullopt; + } + + virtual bool setT1STerminationFor(Network net, bool enable) { + (void)net; (void)enable; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return false; + } + + virtual std::optional isT1SBusDecodingBeaconsEnabledFor(Network net) const { + (void)net; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return std::nullopt; + } + + virtual bool setT1SBusDecodingBeaconsFor(Network net, bool enable) { + (void)net; (void)enable; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return false; + } + + virtual std::optional isT1SBusDecodingAllEnabledFor(Network net) const { + (void)net; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return std::nullopt; + } + + virtual bool setT1SBusDecodingAllFor(Network net, bool enable) { + (void)net; (void)enable; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return false; + } + + virtual std::optional getT1SMultiIDEnableMaskFor(Network net) const { + (void)net; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return std::nullopt; + } + + virtual bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) { + (void)net; (void)mask; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return false; + } + + virtual std::optional getT1SMultiIDFor(Network net, uint8_t index) const { + (void)net; (void)index; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return std::nullopt; + } + + virtual bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) { + (void)net; (void)index; (void)id; + report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); + return false; + } + virtual bool setMiscIOAnalogOutputEnabled(uint8_t pin, bool enabled); virtual bool setMiscIOAnalogOutput(uint8_t pin, MiscIOAnalogVoltage voltage); diff --git a/include/icsneo/device/tree/neovifire3t1slin/neovifire3t1slinsettings.h b/include/icsneo/device/tree/neovifire3t1slin/neovifire3t1slinsettings.h index 6840eae..14e630b 100644 --- a/include/icsneo/device/tree/neovifire3t1slin/neovifire3t1slinsettings.h +++ b/include/icsneo/device/tree/neovifire3t1slin/neovifire3t1slinsettings.h @@ -363,6 +363,109 @@ public: return true; } + std::optional getT1SLocalIDAlternateFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional(t1s->local_id_alternate); + } + + bool setT1SLocalIDAlternateFor(Network net, uint8_t id) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + t1s->local_id_alternate = id; + return true; + } + + std::optional isT1SBusDecodingBeaconsEnabledFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS) != 0); + } + + bool setT1SBusDecodingBeaconsFor(Network net, bool enable) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + if(enable) + t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS; + else + t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS; + + return true; + } + + std::optional isT1SBusDecodingAllEnabledFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL) != 0); + } + + bool setT1SBusDecodingAllFor(Network net, bool enable) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + if(enable) + t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL; + else + t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL; + + return true; + } + + std::optional getT1SMultiIDEnableMaskFor(Network net) const override { + const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return std::nullopt; + + return std::make_optional(t1sExt->enable_multi_id); + } + + bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) override { + ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return false; + + t1sExt->enable_multi_id = mask; + return true; + } + + std::optional getT1SMultiIDFor(Network net, uint8_t index) const override { + const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return std::nullopt; + + if(index >= 7) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return std::nullopt; + } + + return std::make_optional(t1sExt->multi_id[index]); + } + + bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) override { + ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return false; + + if(index >= 7) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return false; + } + + t1sExt->multi_id[index] = id; + return true; + } + private: const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const { auto cfg = getStructurePointer(); @@ -404,6 +507,46 @@ private: } } + const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const { + auto cfg = getStructurePointer(); + if(cfg == nullptr) + return nullptr; + + switch(net.getNetID()) { + case Network::NetID::AE_03: return &(cfg->t1s1Ext); + case Network::NetID::AE_04: return &(cfg->t1s2Ext); + case Network::NetID::AE_05: return &(cfg->t1s3Ext); + case Network::NetID::AE_06: return &(cfg->t1s4Ext); + case Network::NetID::AE_07: return &(cfg->t1s5Ext); + case Network::NetID::AE_08: return &(cfg->t1s6Ext); + case Network::NetID::AE_09: return &(cfg->t1s7Ext); + case Network::NetID::AE_10: return &(cfg->t1s8Ext); + default: + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return nullptr; + } + } + + ETHERNET10T1S_SETTINGS_EXT* getMutableT1SSettingsExtFor(Network net) { + auto cfg = getMutableStructurePointer(); + if(cfg == nullptr) + return nullptr; + + switch(net.getNetID()) { + case Network::NetID::AE_03: return &(cfg->t1s1Ext); + case Network::NetID::AE_04: return &(cfg->t1s2Ext); + case Network::NetID::AE_05: return &(cfg->t1s3Ext); + case Network::NetID::AE_06: return &(cfg->t1s4Ext); + case Network::NetID::AE_07: return &(cfg->t1s5Ext); + case Network::NetID::AE_08: return &(cfg->t1s6Ext); + case Network::NetID::AE_09: return &(cfg->t1s7Ext); + case Network::NetID::AE_10: return &(cfg->t1s8Ext); + default: + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return nullptr; + } + } + protected: ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override { auto cfg = getStructurePointer(); diff --git a/include/icsneo/device/tree/radcomet/radcometsettings.h b/include/icsneo/device/tree/radcomet/radcometsettings.h index 848fca4..c634c8a 100644 --- a/include/icsneo/device/tree/radcomet/radcometsettings.h +++ b/include/icsneo/device/tree/radcomet/radcometsettings.h @@ -223,6 +223,27 @@ public: return true; } + std::optional isT1STerminationEnabledFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_TERMINATION) != 0); + } + + bool setT1STerminationFor(Network net, bool enable) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + if(enable) + t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_TERMINATION; + else + t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_TERMINATION; + + return true; + } + private: const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const { auto cfg = getStructurePointer(); diff --git a/include/icsneo/device/tree/radcomet3/radcomet3settings.h b/include/icsneo/device/tree/radcomet3/radcomet3settings.h index 82809e3..9d98f98 100644 --- a/include/icsneo/device/tree/radcomet3/radcomet3settings.h +++ b/include/icsneo/device/tree/radcomet3/radcomet3settings.h @@ -258,6 +258,109 @@ public: return true; } + std::optional getT1SLocalIDAlternateFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional(t1s->local_id_alternate); + } + + bool setT1SLocalIDAlternateFor(Network net, uint8_t id) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + t1s->local_id_alternate = id; + return true; + } + + std::optional isT1SBusDecodingBeaconsEnabledFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS) != 0); + } + + bool setT1SBusDecodingBeaconsFor(Network net, bool enable) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + if(enable) + t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS; + else + t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS; + + return true; + } + + std::optional isT1SBusDecodingAllEnabledFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL) != 0); + } + + bool setT1SBusDecodingAllFor(Network net, bool enable) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + if(enable) + t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL; + else + t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL; + + return true; + } + + std::optional getT1SMultiIDEnableMaskFor(Network net) const override { + const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return std::nullopt; + + return std::make_optional(t1sExt->enable_multi_id); + } + + bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) override { + ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return false; + + t1sExt->enable_multi_id = mask; + return true; + } + + std::optional getT1SMultiIDFor(Network net, uint8_t index) const override { + const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return std::nullopt; + + if(index >= 7) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return std::nullopt; + } + + return std::make_optional(t1sExt->multi_id[index]); + } + + bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) override { + ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return false; + + if(index >= 7) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return false; + } + + t1sExt->multi_id[index] = id; + return true; + } + bool setPhyRoleFor(Network net, AELinkMode mode) override { if (mode != AE_LINK_AUTO && mode != AE_LINK_MASTER && mode != AE_LINK_SLAVE) { report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); @@ -571,6 +674,42 @@ private: return nullptr; } } + + const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const { + auto cfg = getStructurePointer(); + if(cfg == nullptr) + return nullptr; + + switch(net.getNetID()) { + case Network::NetID::AE_02: return &(cfg->t1s1Ext); + case Network::NetID::AE_03: return &(cfg->t1s2Ext); + case Network::NetID::AE_04: return &(cfg->t1s3Ext); + case Network::NetID::AE_05: return &(cfg->t1s4Ext); + case Network::NetID::AE_06: return &(cfg->t1s5Ext); + case Network::NetID::AE_07: return &(cfg->t1s6Ext); + default: + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return nullptr; + } + } + + ETHERNET10T1S_SETTINGS_EXT* getMutableT1SSettingsExtFor(Network net) { + auto cfg = getMutableStructurePointer(); + if(cfg == nullptr) + return nullptr; + + switch(net.getNetID()) { + case Network::NetID::AE_02: return &(cfg->t1s1Ext); + case Network::NetID::AE_03: return &(cfg->t1s2Ext); + case Network::NetID::AE_04: return &(cfg->t1s3Ext); + case Network::NetID::AE_05: return &(cfg->t1s4Ext); + case Network::NetID::AE_06: return &(cfg->t1s5Ext); + case Network::NetID::AE_07: return &(cfg->t1s6Ext); + default: + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return nullptr; + } + } }; } diff --git a/include/icsneo/device/tree/radgigastar2/radgigastar2settings.h b/include/icsneo/device/tree/radgigastar2/radgigastar2settings.h index 8039c1a..73393f9 100644 --- a/include/icsneo/device/tree/radgigastar2/radgigastar2settings.h +++ b/include/icsneo/device/tree/radgigastar2/radgigastar2settings.h @@ -355,6 +355,130 @@ namespace icsneo return true; } + std::optional getT1SLocalIDAlternateFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional(t1s->local_id_alternate); + } + + bool setT1SLocalIDAlternateFor(Network net, uint8_t id) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + t1s->local_id_alternate = id; + return true; + } + + std::optional isT1STerminationEnabledFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_TERMINATION) != 0); + } + + bool setT1STerminationFor(Network net, bool enable) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + if(enable) + t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_TERMINATION; + else + t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_TERMINATION; + + return true; + } + + std::optional isT1SBusDecodingBeaconsEnabledFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS) != 0); + } + + bool setT1SBusDecodingBeaconsFor(Network net, bool enable) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + if(enable) + t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS; + else + t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS; + + return true; + } + + std::optional isT1SBusDecodingAllEnabledFor(Network net) const override { + const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); + if(t1s == nullptr) + return std::nullopt; + + return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL) != 0); + } + + bool setT1SBusDecodingAllFor(Network net, bool enable) override { + ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); + if(t1s == nullptr) + return false; + + if(enable) + t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL; + else + t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL; + + return true; + } + + std::optional getT1SMultiIDEnableMaskFor(Network net) const override { + const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return std::nullopt; + + return std::make_optional(t1sExt->enable_multi_id); + } + + bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) override { + ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return false; + + t1sExt->enable_multi_id = mask; + return true; + } + + std::optional getT1SMultiIDFor(Network net, uint8_t index) const override { + const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return std::nullopt; + + if(index >= 7) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return std::nullopt; + } + + return std::make_optional(t1sExt->multi_id[index]); + } + + bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) override { + ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net); + if(t1sExt == nullptr) + return false; + + if(index >= 7) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return false; + } + + t1sExt->multi_id[index] = id; + return true; + } + private: const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const { auto cfg = getStructurePointer(); @@ -396,6 +520,46 @@ namespace icsneo } } + const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const { + auto cfg = getStructurePointer(); + if(cfg == nullptr) + return nullptr; + + switch(net.getNetID()) { + case Network::NetID::AE_03: return &(cfg->t1s1Ext); + case Network::NetID::AE_04: return &(cfg->t1s2Ext); + case Network::NetID::AE_05: return &(cfg->t1s3Ext); + case Network::NetID::AE_06: return &(cfg->t1s4Ext); + case Network::NetID::AE_07: return &(cfg->t1s5Ext); + case Network::NetID::AE_08: return &(cfg->t1s6Ext); + case Network::NetID::AE_09: return &(cfg->t1s7Ext); + case Network::NetID::AE_10: return &(cfg->t1s8Ext); + default: + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return nullptr; + } + } + + ETHERNET10T1S_SETTINGS_EXT* getMutableT1SSettingsExtFor(Network net) { + auto cfg = getMutableStructurePointer(); + if(cfg == nullptr) + return nullptr; + + switch(net.getNetID()) { + case Network::NetID::AE_03: return &(cfg->t1s1Ext); + case Network::NetID::AE_04: return &(cfg->t1s2Ext); + case Network::NetID::AE_05: return &(cfg->t1s3Ext); + case Network::NetID::AE_06: return &(cfg->t1s4Ext); + case Network::NetID::AE_07: return &(cfg->t1s5Ext); + case Network::NetID::AE_08: return &(cfg->t1s6Ext); + case Network::NetID::AE_09: return &(cfg->t1s7Ext); + case Network::NetID::AE_10: return &(cfg->t1s8Ext); + default: + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return nullptr; + } + } + protected: ICSNEO_UNALIGNED(const uint64_t *) getTerminationEnables() const override diff --git a/include/icsneo/device/tree/radmoont1s/radmoont1ssettings.h b/include/icsneo/device/tree/radmoont1s/radmoont1ssettings.h index 189d61e..7b31f82 100644 --- a/include/icsneo/device/tree/radmoont1s/radmoont1ssettings.h +++ b/include/icsneo/device/tree/radmoont1s/radmoont1ssettings.h @@ -210,10 +210,163 @@ private: return nullptr; } } + + std::optional getT1SLocalIDAlternateFor(Network net) const override { + auto cfg = getStructurePointer(); + if(cfg == nullptr) + return std::nullopt; + + if(net.getNetID() != Network::NetID::AE_01) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return std::nullopt; + } + + return std::make_optional(cfg->t1s.local_id_alternate); + } + + bool setT1SLocalIDAlternateFor(Network net, uint8_t id) override { + auto cfg = getMutableStructurePointer(); + if(cfg == nullptr) + return false; + + if(net.getNetID() != Network::NetID::AE_01) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return false; + } + + cfg->t1s.local_id_alternate = id; + return true; + } + + std::optional isT1SBusDecodingBeaconsEnabledFor(Network net) const override { + auto cfg = getStructurePointer(); + if(cfg == nullptr) + return std::nullopt; + + if(net.getNetID() != Network::NetID::AE_01) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return std::nullopt; + } + + return std::make_optional((cfg->t1s.flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS) != 0); + } + + bool setT1SBusDecodingBeaconsFor(Network net, bool enable) override { + auto cfg = getMutableStructurePointer(); + if(cfg == nullptr) + return false; + + if(net.getNetID() != Network::NetID::AE_01) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return false; + } + + if(enable) + cfg->t1s.flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS; + else + cfg->t1s.flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS; + + return true; + } + + std::optional isT1SBusDecodingAllEnabledFor(Network net) const override { + auto cfg = getStructurePointer(); + if(cfg == nullptr) + return std::nullopt; + + if(net.getNetID() != Network::NetID::AE_01) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return std::nullopt; + } + + return std::make_optional((cfg->t1s.flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL) != 0); + } + + bool setT1SBusDecodingAllFor(Network net, bool enable) override { + auto cfg = getMutableStructurePointer(); + if(cfg == nullptr) + return false; + + if(net.getNetID() != Network::NetID::AE_01) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return false; + } + + if(enable) + cfg->t1s.flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL; + else + cfg->t1s.flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL; + + return true; + } + + std::optional getT1SMultiIDEnableMaskFor(Network net) const override { + auto cfg = getStructurePointer(); + if(cfg == nullptr) + return std::nullopt; + + if(net.getNetID() != Network::NetID::AE_01) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return std::nullopt; + } + + return std::make_optional(cfg->t1sExt.enable_multi_id); + } + + bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) override { + auto cfg = getMutableStructurePointer(); + if(cfg == nullptr) + return false; + + if(net.getNetID() != Network::NetID::AE_01) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return false; + } + + cfg->t1sExt.enable_multi_id = mask; + return true; + } + + std::optional getT1SMultiIDFor(Network net, uint8_t index) const override { + auto cfg = getStructurePointer(); + if(cfg == nullptr) + return std::nullopt; + + if(net.getNetID() != Network::NetID::AE_01) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return std::nullopt; + } + + if(index >= 7) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return std::nullopt; + } + + return std::make_optional(cfg->t1sExt.multi_id[index]); + } + + bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) override { + auto cfg = getMutableStructurePointer(); + if(cfg == nullptr) + return false; + + if(net.getNetID() != Network::NetID::AE_01) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return false; + } + + if(index >= 7) { + report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); + return false; + } + + cfg->t1sExt.multi_id[index] = id; + return true; + } }; } #endif // __cplusplus -#endif // __RADMOONT1SSETTINGS_H_ +#endif // __RADMOONT1SSETTINGS_H_ \ No newline at end of file