16 Commits
Author SHA1 Message Date
Thomas StoddardandKyle Schwarz 5ee450353b Bindings: Python: Add T1S members 2026-01-07 23:32:20 -05:00
Thomas StoddardandKyle Schwarz 516bca682c EthernetMessage: Add T1S symbol support 2026-01-07 16:34:34 -05:00
Jonathan SchwartzandKyle Schwarz 3f5150bef3 FirmIO: Fix instability and memory leak issues 2026-01-07 13:35:23 -05:00
Thomas StoddardandKyle Schwarz 2a2d55f20d Bindings: Python : Add baudrate and LIN mode methods 2026-01-07 10:51:25 -05:00
Thomas StoddardandKyle Schwarz 977677e3af Bindings: Add LiveData and LiveDataMessage support in Python bindings 2026-01-05 10:40:14 -05:00
Kyle Schwarz 000036f745 Driver: DXX: Update
Fixes D2XX HANDLE leak.
2025-12-19 22:30:14 -05:00
Kyle Schwarz be6a15c017 Device: Galaxy2: Update supported networks 2025-12-18 12:22:12 -05:00
Nicholas ZamoraandKyle Schwarz 5288385495 Driver: DXX: Update libredxx for FT260 support 2025-12-16 11:05:11 -05:00
Max Brombach d6d9fc16ef Device: Update chips for ValueCAN4_2EL bootloader 2025-12-10 19:47:23 +00:00
Kyle Schwarz dbab92b25c Bindings: Python: Migrate to smart_holder 2025-12-09 14:24:40 -05:00
Max Brombach 579160f6d4 Device: Fix Epsilon-XL bootloader pipeline and chip info 2025-12-08 21:16:14 +00:00
Emily Brooks 737d5ceb3b TransmitMessage: Mark timestamp as extended when using CAN FD 2025-12-05 13:53:26 -05:00
Emily Brooks 95521a5548 TransmitMessage: Add TX support for neoVI network 2025-12-05 10:53:53 -05:00
Emily BrooksandKyle Schwarz 16cd476c01 Network: neoVI: Add TX support 2025-12-03 14:43:35 -05:00
Thomas StoddardandKyle Schwarz d328d314b6 Bindings: Python: Update pybind11
Updates to 3.0.1 and switches to smart_holder & native_enum.
2025-11-24 11:56:09 -05:00
Bryant JonesandKyle Schwarz 7b5b94d980 Docs: Python: Add SPI example 2025-11-20 17:08:30 -05:00
51 changed files with 808 additions and 194 deletions
+3
View File
@@ -5,3 +5,6 @@ KERNEL=="ttyACM?", ATTRS{idVendor}=="093c", GROUP="users", MODE="0666"
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="093c", KERNEL=="ttyUSB*", \ ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="093c", KERNEL=="ttyUSB*", \
RUN+="/bin/sh -c 'echo $id:1.0>/sys/bus/usb/drivers/ftdi_sio/unbind'" RUN+="/bin/sh -c 'echo $id:1.0>/sys/bus/usb/drivers/ftdi_sio/unbind'"
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="093c", DRIVER=="usbhid", \
RUN+="/bin/sh -c 'echo $id:1.0>/sys/bus/usb/drivers/usbhid/unbind'"
+1 -1
View File
@@ -360,7 +360,7 @@ if(LIBICSNEO_ENABLE_DXX)
include(FetchContent) include(FetchContent)
FetchContent_Declare(libredxx FetchContent_Declare(libredxx
GIT_REPOSITORY https://github.com/Zeranoe/libredxx.git GIT_REPOSITORY https://github.com/Zeranoe/libredxx.git
GIT_TAG e1fe2bd6ba6079b17037379d78f3f18024b389d7 GIT_TAG c28c3f4e1c46f0e0fc119843eb73edd81d5bbb3d
) )
set(LIBREDXX_DISABLE_INSTALL ON) set(LIBREDXX_DISABLE_INSTALL ON)
FetchContent_MakeAvailable(libredxx) FetchContent_MakeAvailable(libredxx)
+3 -1
View File
@@ -9,7 +9,7 @@ else()
FetchContent_Declare( FetchContent_Declare(
pybind11 pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11.git GIT_REPOSITORY https://github.com/pybind/pybind11.git
GIT_TAG v2.13.6 GIT_TAG v3.0.1
) )
FetchContent_MakeAvailable(pybind11) FetchContent_MakeAvailable(pybind11)
endif() endif()
@@ -22,6 +22,7 @@ pybind11_add_module(icsneopy
icsneopy/device/devicetype.cpp icsneopy/device/devicetype.cpp
icsneopy/communication/network.cpp icsneopy/communication/network.cpp
icsneopy/communication/io.cpp icsneopy/communication/io.cpp
icsneopy/communication/livedata.cpp
icsneopy/communication/message/message.cpp icsneopy/communication/message/message.cpp
icsneopy/communication/message/canmessage.cpp icsneopy/communication/message/canmessage.cpp
icsneopy/communication/message/canerrormessage.cpp icsneopy/communication/message/canerrormessage.cpp
@@ -34,6 +35,7 @@ pybind11_add_module(icsneopy
icsneopy/communication/message/spimessage.cpp icsneopy/communication/message/spimessage.cpp
icsneopy/communication/message/scriptstatusmessage.cpp icsneopy/communication/message/scriptstatusmessage.cpp
icsneopy/communication/message/ethphymessage.cpp icsneopy/communication/message/ethphymessage.cpp
icsneopy/communication/message/livedatamessage.cpp
icsneopy/communication/message/callback/messagecallback.cpp icsneopy/communication/message/callback/messagecallback.cpp
icsneopy/communication/message/filter/messagefilter.cpp icsneopy/communication/message/filter/messagefilter.cpp
icsneopy/core/macseccfg.cpp icsneopy/core/macseccfg.cpp
+9 -6
View File
@@ -1,14 +1,15 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/api/event.h" #include "icsneo/api/event.h"
namespace icsneo { namespace icsneo {
void init_event(pybind11::module_& m) { void init_event(pybind11::module_& m) {
pybind11::class_<APIEvent, std::shared_ptr<APIEvent>> apiEvent(m, "APIEvent"); pybind11::classh<APIEvent> apiEvent(m, "APIEvent");
pybind11::enum_<APIEvent::Type>(apiEvent, "Type") pybind11::native_enum<APIEvent::Type>(apiEvent, "Type", "enum.IntEnum")
.value("Any", APIEvent::Type::Any) .value("Any", APIEvent::Type::Any)
.value("InvalidNeoDevice", APIEvent::Type::InvalidNeoDevice) .value("InvalidNeoDevice", APIEvent::Type::InvalidNeoDevice)
.value("RequiredParameterNull", APIEvent::Type::RequiredParameterNull) .value("RequiredParameterNull", APIEvent::Type::RequiredParameterNull)
@@ -132,13 +133,15 @@ void init_event(pybind11::module_& m) {
.value("DXXErrorArg", APIEvent::Type::DXXErrorArg) .value("DXXErrorArg", APIEvent::Type::DXXErrorArg)
.value("NoErrorFound", APIEvent::Type::NoErrorFound) .value("NoErrorFound", APIEvent::Type::NoErrorFound)
.value("TooManyEvents", APIEvent::Type::TooManyEvents) .value("TooManyEvents", APIEvent::Type::TooManyEvents)
.value("Unknown", APIEvent::Type::Unknown); .value("Unknown", APIEvent::Type::Unknown)
.finalize();
pybind11::enum_<APIEvent::Severity>(apiEvent, "Severity") pybind11::native_enum<APIEvent::Severity>(apiEvent, "Severity", "enum.IntEnum")
.value("Any", APIEvent::Severity::Any) .value("Any", APIEvent::Severity::Any)
.value("EventInfo", APIEvent::Severity::EventInfo) .value("EventInfo", APIEvent::Severity::EventInfo)
.value("EventWarning", APIEvent::Severity::EventWarning) .value("EventWarning", APIEvent::Severity::EventWarning)
.value("Error", APIEvent::Severity::Error); .value("Error", APIEvent::Severity::Error)
.finalize();
apiEvent apiEvent
.def("get_type", &APIEvent::getType) .def("get_type", &APIEvent::getType)
@@ -147,7 +150,7 @@ void init_event(pybind11::module_& m) {
.def("describe", &APIEvent::describe) .def("describe", &APIEvent::describe)
.def("__repr__", &APIEvent::describe); .def("__repr__", &APIEvent::describe);
pybind11::class_<EventFilter, std::shared_ptr<EventFilter>>(m, "EventFilter") pybind11::classh<EventFilter>(m, "EventFilter")
.def(pybind11::init()) .def(pybind11::init())
.def(pybind11::init<APIEvent::Type>()) .def(pybind11::init<APIEvent::Type>())
.def(pybind11::init<APIEvent::Severity>()) .def(pybind11::init<APIEvent::Severity>())
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_eventcallback(pybind11::module_& m) { void init_eventcallback(pybind11::module_& m) {
pybind11::class_<EventCallback>(m, "EventCallback") pybind11::classh<EventCallback>(m, "EventCallback")
.def(pybind11::init<EventCallback::fn_eventCallback, EventFilter>()) .def(pybind11::init<EventCallback::fn_eventCallback, EventFilter>())
.def(pybind11::init<EventCallback::fn_eventCallback>()); .def(pybind11::init<EventCallback::fn_eventCallback>());
} }
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_eventmanager(pybind11::module_& m) { void init_eventmanager(pybind11::module_& m) {
pybind11::class_<EventManager>(m, "EventManager") pybind11::classh<EventManager>(m, "EventManager")
.def_static("get_instance", &EventManager::GetInstance, pybind11::return_value_policy::reference) .def_static("get_instance", &EventManager::GetInstance, pybind11::return_value_policy::reference)
.def("add_event_callback", &EventManager::addEventCallback) .def("add_event_callback", &EventManager::addEventCallback)
.def("remove_event_callback", &EventManager::removeEventCallback) .def("remove_event_callback", &EventManager::removeEventCallback)
+1 -1
View File
@@ -9,7 +9,7 @@
namespace icsneo { namespace icsneo {
void init_version(pybind11::module_& m) { void init_version(pybind11::module_& m) {
pybind11::class_<neoversion_t>(m, "NeoVersion") pybind11::classh<neoversion_t>(m, "NeoVersion")
.def_readonly("major", &neoversion_t::major) .def_readonly("major", &neoversion_t::major)
.def_readonly("minor", &neoversion_t::minor) .def_readonly("minor", &neoversion_t::minor)
.def_readonly("patch", &neoversion_t::patch) .def_readonly("patch", &neoversion_t::patch)
@@ -0,0 +1,79 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/communication/livedata.h"
namespace icsneo {
void init_livedata(pybind11::module_& m) {
// LiveDataValue struct
pybind11::classh<LiveDataValue>(m, "LiveDataValue")
.def(pybind11::init<>())
.def_readwrite("value", &LiveDataValue::value);
// LiveDataArgument struct
pybind11::classh<LiveDataArgument>(m, "LiveDataArgument")
.def(pybind11::init<>())
.def_readwrite("object_type", &LiveDataArgument::objectType)
.def_readwrite("object_index", &LiveDataArgument::objectIndex)
.def_readwrite("signal_index", &LiveDataArgument::signalIndex)
.def_readwrite("value_type", &LiveDataArgument::valueType);
// LiveDataCommand enum
pybind11::native_enum<LiveDataCommand>(m, "LiveDataCommand", "enum.IntEnum")
.value("STATUS", LiveDataCommand::STATUS)
.value("SUBSCRIBE", LiveDataCommand::SUBSCRIBE)
.value("UNSUBSCRIBE", LiveDataCommand::UNSUBSCRIBE)
.value("RESPONSE", LiveDataCommand::RESPONSE)
.value("CLEAR_ALL", LiveDataCommand::CLEAR_ALL)
.value("SET_VALUE", LiveDataCommand::SET_VALUE)
.finalize();
// LiveDataStatus enum
pybind11::native_enum<LiveDataStatus>(m, "LiveDataStatus", "enum.IntEnum")
.value("SUCCESS", LiveDataStatus::SUCCESS)
.value("ERR_UNKNOWN_COMMAND", LiveDataStatus::ERR_UNKNOWN_COMMAND)
.value("ERR_HANDLE", LiveDataStatus::ERR_HANDLE)
.value("ERR_DUPLICATE", LiveDataStatus::ERR_DUPLICATE)
.value("ERR_FULL", LiveDataStatus::ERR_FULL)
.finalize();
// LiveDataObjectType enum
pybind11::enum_<LiveDataObjectType>(m, "LiveDataObjectType")
.value("MISC", LiveDataObjectType::MISC)
.value("SNA", LiveDataObjectType::SNA)
.export_values();
// LiveDataValueType enum
pybind11::native_enum<LiveDataValueType>(m, "LiveDataValueType", "enum.IntEnum")
.value("GPS_LATITUDE", LiveDataValueType::GPS_LATITUDE)
.value("GPS_LONGITUDE", LiveDataValueType::GPS_LONGITUDE)
.value("GPS_ALTITUDE", LiveDataValueType::GPS_ALTITUDE)
.value("GPS_SPEED", LiveDataValueType::GPS_SPEED)
.value("GPS_VALID", LiveDataValueType::GPS_VALID)
.value("GPS_ENABLE", LiveDataValueType::GPS_ENABLE)
.value("MANUAL_TRIGGER", LiveDataValueType::MANUAL_TRIGGER)
.value("TIME_SINCE_MSG", LiveDataValueType::TIME_SINCE_MSG)
.value("GPS_ACCURACY", LiveDataValueType::GPS_ACCURACY)
.value("GPS_BEARING", LiveDataValueType::GPS_BEARING)
.value("GPS_TIME", LiveDataValueType::GPS_TIME)
.value("GPS_TIME_VALID", LiveDataValueType::GPS_TIME_VALID)
.value("DAQ_ENABLE", LiveDataValueType::DAQ_ENABLE)
.finalize();
// LiveDataUtil namespace functions
m.def("get_new_handle", &LiveDataUtil::getNewHandle,
"Generate a new unique LiveData handle");
m.def("livedata_value_to_double", &LiveDataUtil::liveDataValueToDouble,
pybind11::arg("val"),
"Convert LiveDataValue to double (32.32 fixed-point to floating-point)");
m.def("livedata_double_to_value", &LiveDataUtil::liveDataDoubleToValue,
pybind11::arg("d"),
"Convert double to LiveDataValue (32.32 fixed-point format). Returns LiveDataValue or None on failure.");
}
} // namespace icsneo
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_messagecallback(pybind11::module_& m) { void init_messagecallback(pybind11::module_& m) {
pybind11::class_<MessageCallback, std::shared_ptr<MessageCallback>>(m, "MessageCallback") pybind11::classh<MessageCallback>(m, "MessageCallback")
.def(pybind11::init<MessageCallback::fn_messageCallback, std::shared_ptr<MessageFilter>>()); .def(pybind11::init<MessageCallback::fn_messageCallback, std::shared_ptr<MessageFilter>>());
} }
@@ -1,13 +1,14 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/communication/message/canerrormessage.h" #include "icsneo/communication/message/canerrormessage.h"
namespace icsneo { namespace icsneo {
void init_errorcodes(pybind11::module_& m) { void init_errorcodes(pybind11::module_& m) {
pybind11::enum_<CANErrorCode>(m, "CANErrorCode") pybind11::native_enum<CANErrorCode>(m, "CANErrorCode", "enum.IntEnum")
.value("NoError", CANErrorCode::NoError) .value("NoError", CANErrorCode::NoError)
.value("StuffError", CANErrorCode::StuffError) .value("StuffError", CANErrorCode::StuffError)
.value("FormError", CANErrorCode::FormError) .value("FormError", CANErrorCode::FormError)
@@ -15,12 +16,13 @@ void init_errorcodes(pybind11::module_& m) {
.value("Bit1Error", CANErrorCode::Bit1Error) .value("Bit1Error", CANErrorCode::Bit1Error)
.value("Bit0Error", CANErrorCode::Bit0Error) .value("Bit0Error", CANErrorCode::Bit0Error)
.value("CRCError", CANErrorCode::CRCError) .value("CRCError", CANErrorCode::CRCError)
.value("NoChange", CANErrorCode::NoChange); .value("NoChange", CANErrorCode::NoChange)
.finalize();
} }
void init_canerrormessage(pybind11::module_& m) { void init_canerrormessage(pybind11::module_& m) {
init_errorcodes(m); init_errorcodes(m);
pybind11::class_<CANErrorMessage, std::shared_ptr<CANErrorMessage>, Message>(m, "CANErrorMessage") pybind11::classh<CANErrorMessage, Message>(m, "CANErrorMessage")
.def_readonly("network", &CANErrorMessage::network) .def_readonly("network", &CANErrorMessage::network)
.def_readonly("transmitErrorCount", &CANErrorMessage::transmitErrorCount) .def_readonly("transmitErrorCount", &CANErrorMessage::transmitErrorCount)
.def_readonly("receiveErrorCount", &CANErrorMessage::receiveErrorCount) .def_readonly("receiveErrorCount", &CANErrorMessage::receiveErrorCount)
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_canmessage(pybind11::module_& m) { void init_canmessage(pybind11::module_& m) {
pybind11::class_<CANMessage, std::shared_ptr<CANMessage>, Frame>(m, "CANMessage") pybind11::classh<CANMessage, Frame>(m, "CANMessage")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("arbid", &CANMessage::arbid) .def_readwrite("arbid", &CANMessage::arbid)
.def_readwrite("dlcOnWire", &CANMessage::dlcOnWire) .def_readwrite("dlcOnWire", &CANMessage::dlcOnWire)
@@ -7,17 +7,28 @@
namespace icsneo { namespace icsneo {
void init_ethernetmessage(pybind11::module_& m) { void init_ethernetmessage(pybind11::module_& m) {
pybind11::class_<MACAddress>(m, "MACAddress") pybind11::classh<MACAddress>(m, "MACAddress")
.def("to_string", &MACAddress::toString) .def("to_string", &MACAddress::toString)
.def("__repr__", &MACAddress::toString); .def("__repr__", &MACAddress::toString);
pybind11::class_<EthernetMessage, std::shared_ptr<EthernetMessage>, Frame>(m, "EthernetMessage") pybind11::classh<EthernetMessage, Frame>(m, "EthernetMessage")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("preemptionEnabled", &EthernetMessage::preemptionEnabled) .def_readwrite("preemptionEnabled", &EthernetMessage::preemptionEnabled)
.def_readwrite("preemptionFlags", &EthernetMessage::preemptionFlags) .def_readwrite("preemptionFlags", &EthernetMessage::preemptionFlags)
.def_readwrite("fcs", &EthernetMessage::fcs) .def_readwrite("fcs", &EthernetMessage::fcs)
.def_readwrite("frameTooShort", &EthernetMessage::frameTooShort) .def_readwrite("frameTooShort", &EthernetMessage::frameTooShort)
.def_readwrite("noPadding", &EthernetMessage::noPadding) .def_readwrite("noPadding", &EthernetMessage::noPadding)
.def_readwrite("fcsVerified", &EthernetMessage::fcsVerified)
.def_readwrite("txAborted", &EthernetMessage::txAborted)
.def_readwrite("crcError", &EthernetMessage::crcError)
.def_readwrite("isT1S", &EthernetMessage::isT1S)
.def_readwrite("isT1SSymbol", &EthernetMessage::isT1SSymbol)
.def_readwrite("isT1SBurst", &EthernetMessage::isT1SBurst)
.def_readwrite("txCollision", &EthernetMessage::txCollision)
.def_readwrite("isT1SWake", &EthernetMessage::isT1SWake)
.def_readwrite("t1sNodeId", &EthernetMessage::t1sNodeId)
.def_readwrite("t1sBurstCount", &EthernetMessage::t1sBurstCount)
.def_readwrite("t1sSymbolType", &EthernetMessage::t1sSymbolType)
.def("get_destination_mac", &EthernetMessage::getDestinationMAC, pybind11::return_value_policy::reference) .def("get_destination_mac", &EthernetMessage::getDestinationMAC, pybind11::return_value_policy::reference)
.def("get_source_mac", &EthernetMessage::getSourceMAC, pybind11::return_value_policy::reference) .def("get_source_mac", &EthernetMessage::getSourceMAC, pybind11::return_value_policy::reference)
.def("get_ether_type", &EthernetMessage::getEtherType); .def("get_ether_type", &EthernetMessage::getEtherType);
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_ethernetstatusmessage(pybind11::module_& m) { void init_ethernetstatusmessage(pybind11::module_& m) {
pybind11::class_<EthernetStatusMessage, std::shared_ptr<EthernetStatusMessage>, Message> ethernetStatusMessage(m, "EthernetStatusMessage"); pybind11::classh<EthernetStatusMessage, Message> ethernetStatusMessage(m, "EthernetStatusMessage");
pybind11::enum_<EthernetStatusMessage::LinkSpeed>(ethernetStatusMessage, "LinkSpeed") pybind11::enum_<EthernetStatusMessage::LinkSpeed>(ethernetStatusMessage, "LinkSpeed")
.value("LinkSpeedAuto", EthernetStatusMessage::LinkSpeed::LinkSpeedAuto) .value("LinkSpeedAuto", EthernetStatusMessage::LinkSpeed::LinkSpeedAuto)
@@ -7,7 +7,17 @@
namespace icsneo { namespace icsneo {
void init_ethphymessage(pybind11::module_& m) { void init_ethphymessage(pybind11::module_& m) {
pybind11::class_<PhyMessage, std::shared_ptr<PhyMessage>>(m, "PhyMessage") pybind11::classh<Clause22Message>(m, "Clause22Message")
.def_readwrite("phyAddr", &Clause22Message::phyAddr)
.def_readwrite("page", &Clause22Message::page)
.def_readwrite("regAddr", &Clause22Message::regAddr)
.def_readwrite("regVal", &Clause22Message::regVal);
pybind11::classh<Clause45Message>(m, "Clause45Message")
.def_readwrite("port", &Clause45Message::port)
.def_readwrite("device", &Clause45Message::device)
.def_readwrite("regAddr", &Clause45Message::regAddr)
.def_readwrite("regVal", &Clause45Message::regVal);
pybind11::classh<PhyMessage>(m, "PhyMessage")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("Enabled", &PhyMessage::Enabled) .def_readwrite("Enabled", &PhyMessage::Enabled)
.def_readwrite("WriteEnable", &PhyMessage::WriteEnable) .def_readwrite("WriteEnable", &PhyMessage::WriteEnable)
@@ -16,19 +26,7 @@ void init_ethphymessage(pybind11::module_& m) {
.def_readwrite("BusIndex", &PhyMessage::BusIndex) .def_readwrite("BusIndex", &PhyMessage::BusIndex)
.def_readwrite("Clause22", &PhyMessage::Clause22) .def_readwrite("Clause22", &PhyMessage::Clause22)
.def_readwrite("Clause45", &PhyMessage::Clause45); .def_readwrite("Clause45", &PhyMessage::Clause45);
pybind11::class_<Clause22Message>(m, "Clause22Message") pybind11::classh<EthPhyMessage, Message>(m, "EthPhyMessage")
.def(pybind11::init())
.def_readwrite("phyAddr", &Clause22Message::phyAddr)
.def_readwrite("page", &Clause22Message::page)
.def_readwrite("regAddr", &Clause22Message::regAddr)
.def_readwrite("regVal", &Clause22Message::regVal);
pybind11::class_<Clause45Message>(m, "Clause45Message")
.def(pybind11::init())
.def_readwrite("port", &Clause45Message::port)
.def_readwrite("device", &Clause45Message::device)
.def_readwrite("regAddr", &Clause45Message::regAddr)
.def_readwrite("regVal", &Clause45Message::regVal);
pybind11::class_<EthPhyMessage, std::shared_ptr<EthPhyMessage>, Message>(m, "EthPhyMessage")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("messages", &EthPhyMessage::messages); .def_readwrite("messages", &EthPhyMessage::messages);
} }
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_messagefilter(pybind11::module_& m) { void init_messagefilter(pybind11::module_& m) {
pybind11::class_<MessageFilter, std::shared_ptr<MessageFilter>>(m, "MessageFilter") pybind11::classh<MessageFilter>(m, "MessageFilter")
.def(pybind11::init()) .def(pybind11::init())
.def(pybind11::init<Message::Type>()) .def(pybind11::init<Message::Type>())
.def(pybind11::init<Network::NetID>()); .def(pybind11::init<Network::NetID>());
@@ -7,40 +7,40 @@
namespace icsneo { namespace icsneo {
void init_gptpstatusmessage(pybind11::module_& m) { void init_gptpstatusmessage(pybind11::module_& m) {
pybind11::class_<GPTPStatus, std::shared_ptr<GPTPStatus>, Message> gptpStatus(m, "GPTPStatus"); pybind11::classh<GPTPStatus, Message> gptpStatus(m, "GPTPStatus");
pybind11::class_<GPTPStatus::Timestamp>(gptpStatus, "Timestamp") pybind11::classh<GPTPStatus::Timestamp>(gptpStatus, "Timestamp")
.def_readonly("seconds", &GPTPStatus::Timestamp::seconds) .def_readonly("seconds", &GPTPStatus::Timestamp::seconds)
.def_readonly("nanoseconds", &GPTPStatus::Timestamp::nanoseconds) .def_readonly("nanoseconds", &GPTPStatus::Timestamp::nanoseconds)
.def("to_seconds", &GPTPStatus::Timestamp::toSeconds, pybind11::call_guard<pybind11::gil_scoped_release>()); .def("to_seconds", &GPTPStatus::Timestamp::toSeconds, pybind11::call_guard<pybind11::gil_scoped_release>());
pybind11::class_<GPTPStatus::ScaledNanoSeconds>(gptpStatus, "ScaledNanoSeconds") pybind11::classh<GPTPStatus::ScaledNanoSeconds>(gptpStatus, "ScaledNanoSeconds")
.def_readonly("nanoseconds_msb", &GPTPStatus::ScaledNanoSeconds::nanosecondsMSB) .def_readonly("nanoseconds_msb", &GPTPStatus::ScaledNanoSeconds::nanosecondsMSB)
.def_readonly("nanoseconds_lsb", &GPTPStatus::ScaledNanoSeconds::nanosecondsLSB) .def_readonly("nanoseconds_lsb", &GPTPStatus::ScaledNanoSeconds::nanosecondsLSB)
.def_readonly("fractional_nanoseconds", &GPTPStatus::ScaledNanoSeconds::fractionalNanoseconds); .def_readonly("fractional_nanoseconds", &GPTPStatus::ScaledNanoSeconds::fractionalNanoseconds);
pybind11::class_<GPTPStatus::PortID>(gptpStatus, "PortID") pybind11::classh<GPTPStatus::PortID>(gptpStatus, "PortID")
.def_readonly("clock_identity", &GPTPStatus::PortID::clockIdentity) .def_readonly("clock_identity", &GPTPStatus::PortID::clockIdentity)
.def_readonly("port_number", &GPTPStatus::PortID::portNumber); .def_readonly("port_number", &GPTPStatus::PortID::portNumber);
pybind11::class_<GPTPStatus::ClockQuality>(gptpStatus, "ClockQuality") pybind11::classh<GPTPStatus::ClockQuality>(gptpStatus, "ClockQuality")
.def_readonly("clock_class", &GPTPStatus::ClockQuality::clockClass) .def_readonly("clock_class", &GPTPStatus::ClockQuality::clockClass)
.def_readonly("clock_accuracy", &GPTPStatus::ClockQuality::clockAccuracy) .def_readonly("clock_accuracy", &GPTPStatus::ClockQuality::clockAccuracy)
.def_readonly("offset_scaled_log_variance", &GPTPStatus::ClockQuality::offsetScaledLogVariance); .def_readonly("offset_scaled_log_variance", &GPTPStatus::ClockQuality::offsetScaledLogVariance);
pybind11::class_<GPTPStatus::SystemID>(gptpStatus, "SystemID") pybind11::classh<GPTPStatus::SystemID>(gptpStatus, "SystemID")
.def_readonly("priority1", &GPTPStatus::SystemID::priority1) .def_readonly("priority1", &GPTPStatus::SystemID::priority1)
.def_readonly("clock_quality", &GPTPStatus::SystemID::clockQuality) .def_readonly("clock_quality", &GPTPStatus::SystemID::clockQuality)
.def_readonly("priority2", &GPTPStatus::SystemID::priority2) .def_readonly("priority2", &GPTPStatus::SystemID::priority2)
.def_readonly("clock_id", &GPTPStatus::SystemID::clockID); .def_readonly("clock_id", &GPTPStatus::SystemID::clockID);
pybind11::class_<GPTPStatus::PriorityVector>(gptpStatus, "PriorityVector") pybind11::classh<GPTPStatus::PriorityVector>(gptpStatus, "PriorityVector")
.def_readonly("sys_id", &GPTPStatus::PriorityVector::sysID) .def_readonly("sys_id", &GPTPStatus::PriorityVector::sysID)
.def_readonly("steps_removed", &GPTPStatus::PriorityVector::stepsRemoved) .def_readonly("steps_removed", &GPTPStatus::PriorityVector::stepsRemoved)
.def_readonly("port_id", &GPTPStatus::PriorityVector::portID) .def_readonly("port_id", &GPTPStatus::PriorityVector::portID)
.def_readonly("port_number", &GPTPStatus::PriorityVector::portNumber); .def_readonly("port_number", &GPTPStatus::PriorityVector::portNumber);
pybind11::class_<GPTPStatus::ParentDS>(gptpStatus, "ParentDS") pybind11::classh<GPTPStatus::ParentDS>(gptpStatus, "ParentDS")
.def_readonly("parent_port_identity", &GPTPStatus::ParentDS::parentPortIdentity) .def_readonly("parent_port_identity", &GPTPStatus::ParentDS::parentPortIdentity)
.def_readonly("cumulative_rate_ratio", &GPTPStatus::ParentDS::cumulativeRateRatio) .def_readonly("cumulative_rate_ratio", &GPTPStatus::ParentDS::cumulativeRateRatio)
.def_readonly("grandmaster_identity", &GPTPStatus::ParentDS::grandmasterIdentity) .def_readonly("grandmaster_identity", &GPTPStatus::ParentDS::grandmasterIdentity)
@@ -50,7 +50,7 @@ void init_gptpstatusmessage(pybind11::module_& m) {
.def_readonly("gm_priority1", &GPTPStatus::ParentDS::gmPriority1) .def_readonly("gm_priority1", &GPTPStatus::ParentDS::gmPriority1)
.def_readonly("gm_priority2", &GPTPStatus::ParentDS::gmPriority2); .def_readonly("gm_priority2", &GPTPStatus::ParentDS::gmPriority2);
pybind11::class_<GPTPStatus::CurrentDS>(gptpStatus, "CurrentDS") pybind11::classh<GPTPStatus::CurrentDS>(gptpStatus, "CurrentDS")
.def_readonly("steps_removed", &GPTPStatus::CurrentDS::stepsRemoved) .def_readonly("steps_removed", &GPTPStatus::CurrentDS::stepsRemoved)
.def_readonly("offset_from_master", &GPTPStatus::CurrentDS::offsetFromMaster) .def_readonly("offset_from_master", &GPTPStatus::CurrentDS::offsetFromMaster)
.def_readonly("lastgm_phase_change", &GPTPStatus::CurrentDS::lastgmPhaseChange) .def_readonly("lastgm_phase_change", &GPTPStatus::CurrentDS::lastgmPhaseChange)
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_linmessage(pybind11::module_& m) { void init_linmessage(pybind11::module_& m) {
pybind11::class_<LINErrorFlags>(m, "LINErrorFlags") pybind11::classh<LINErrorFlags>(m, "LINErrorFlags")
.def_readwrite("ErrRxBreakOnly", &LINErrorFlags::ErrRxBreakOnly) .def_readwrite("ErrRxBreakOnly", &LINErrorFlags::ErrRxBreakOnly)
.def_readwrite("ErrRxBreakSyncOnly", &LINErrorFlags::ErrRxBreakSyncOnly) .def_readwrite("ErrRxBreakSyncOnly", &LINErrorFlags::ErrRxBreakSyncOnly)
.def_readwrite("ErrTxRxMismatch", &LINErrorFlags::ErrTxRxMismatch) .def_readwrite("ErrTxRxMismatch", &LINErrorFlags::ErrTxRxMismatch)
@@ -20,7 +20,7 @@ void init_linmessage(pybind11::module_& m) {
.def_readwrite("ErrFrameResponderData", &LINErrorFlags::ErrFrameResponderData) .def_readwrite("ErrFrameResponderData", &LINErrorFlags::ErrFrameResponderData)
.def_readwrite("ErrChecksumMatch", &LINErrorFlags::ErrChecksumMatch); .def_readwrite("ErrChecksumMatch", &LINErrorFlags::ErrChecksumMatch);
pybind11::class_<LINStatusFlags>(m, "LINStatusFlags") pybind11::classh<LINStatusFlags>(m, "LINStatusFlags")
.def_readwrite("TxChecksumEnhanced", &LINStatusFlags::TxChecksumEnhanced) .def_readwrite("TxChecksumEnhanced", &LINStatusFlags::TxChecksumEnhanced)
.def_readwrite("TxCommander", &LINStatusFlags::TxCommander) .def_readwrite("TxCommander", &LINStatusFlags::TxCommander)
.def_readwrite("TxResponder", &LINStatusFlags::TxResponder) .def_readwrite("TxResponder", &LINStatusFlags::TxResponder)
@@ -30,7 +30,7 @@ void init_linmessage(pybind11::module_& m) {
.def_readwrite("BusRecovered", &LINStatusFlags::BusRecovered) .def_readwrite("BusRecovered", &LINStatusFlags::BusRecovered)
.def_readwrite("BreakOnly", &LINStatusFlags::BreakOnly); .def_readwrite("BreakOnly", &LINStatusFlags::BreakOnly);
pybind11::class_<LINMessage, std::shared_ptr<LINMessage>, Frame> linMessage(m, "LINMessage"); pybind11::classh<LINMessage, Frame> linMessage(m, "LINMessage");
pybind11::enum_<LINMessage::Type>(linMessage, "Type") pybind11::enum_<LINMessage::Type>(linMessage, "Type")
.value("NOT_SET", LINMessage::Type::NOT_SET) .value("NOT_SET", LINMessage::Type::NOT_SET)
@@ -0,0 +1,50 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include <pybind11/chrono.h>
#include "icsneo/communication/message/livedatamessage.h"
namespace icsneo {
void init_livedatamessage(pybind11::module_& m) {
// LiveDataMessage base class
pybind11::classh<LiveDataMessage, RawMessage>(m, "LiveDataMessage")
.def(pybind11::init<>())
.def_readwrite("handle", &LiveDataMessage::handle)
.def_readwrite("cmd", &LiveDataMessage::cmd);
// LiveDataCommandMessage (for subscribe/unsubscribe)
pybind11::classh<LiveDataCommandMessage, LiveDataMessage>(m, "LiveDataCommandMessage")
.def(pybind11::init<>())
.def_readwrite("update_period", &LiveDataCommandMessage::updatePeriod)
.def_readwrite("expiration_time", &LiveDataCommandMessage::expirationTime)
.def_readwrite("args", &LiveDataCommandMessage::args)
.def("append_signal_arg", &LiveDataCommandMessage::appendSignalArg,
pybind11::arg("value_type"),
"Append a signal argument to the command message");
// LiveDataValueMessage (received values)
pybind11::classh<LiveDataValueMessage, LiveDataMessage>(m, "LiveDataValueMessage")
.def(pybind11::init<>())
.def_readwrite("num_args", &LiveDataValueMessage::numArgs)
.def_readwrite("values", &LiveDataValueMessage::values);
// LiveDataStatusMessage (status responses)
pybind11::classh<LiveDataStatusMessage, LiveDataMessage>(m, "LiveDataStatusMessage")
.def(pybind11::init<>())
.def_readwrite("requested_command", &LiveDataStatusMessage::requestedCommand)
.def_readwrite("status", &LiveDataStatusMessage::status);
// LiveDataSetValueMessage (for setting values)
pybind11::classh<LiveDataSetValueMessage, LiveDataMessage>(m, "LiveDataSetValueMessage")
.def(pybind11::init<>())
.def_readwrite("args", &LiveDataSetValueMessage::args)
.def_readwrite("values", &LiveDataSetValueMessage::values)
.def("append_set_value", &LiveDataSetValueMessage::appendSetValue,
pybind11::arg("value_type"),
pybind11::arg("value"),
"Append a value to set in the message");
}
} // namespace icsneo
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_mdiomessage(pybind11::module_& m) { void init_mdiomessage(pybind11::module_& m) {
pybind11::class_<MDIOMessage, std::shared_ptr<MDIOMessage>, Frame> mdioMessage(m, "MDIOMessage"); pybind11::classh<MDIOMessage, Frame> mdioMessage(m, "MDIOMessage");
pybind11::enum_<MDIOMessage::Clause>(mdioMessage, "Clause") pybind11::enum_<MDIOMessage::Clause>(mdioMessage, "Clause")
.value("Clause45", MDIOMessage::Clause::Clause45) .value("Clause45", MDIOMessage::Clause::Clause45)
.value("Clause22", MDIOMessage::Clause::Clause22); .value("Clause22", MDIOMessage::Clause::Clause22);
@@ -1,14 +1,16 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/communication/message/message.h" #include "icsneo/communication/message/message.h"
namespace icsneo { namespace icsneo {
void init_message(pybind11::module_& m) { void init_message(pybind11::module_& m) {
pybind11::class_<Message, std::shared_ptr<Message>> message(m, "Message"); // Using py::smart_holder for safer lifetime management
pybind11::enum_<Message::Type>(message, "Type") pybind11::classh<Message> message(m, "Message");
pybind11::native_enum<Message::Type>(message, "Type", "enum.IntEnum")
.value("Frame", Message::Type::Frame) .value("Frame", Message::Type::Frame)
.value("CANErrorCount", Message::Type::CANErrorCount) .value("CANErrorCount", Message::Type::CANErrorCount)
.value("CANError", Message::Type::CANError) .value("CANError", Message::Type::CANError)
@@ -34,17 +36,18 @@ void init_message(pybind11::module_& m) {
.value("TC10Status", Message::Type::TC10Status) .value("TC10Status", Message::Type::TC10Status)
.value("AppError", Message::Type::AppError) .value("AppError", Message::Type::AppError)
.value("GPTPStatus", Message::Type::GPTPStatus) .value("GPTPStatus", Message::Type::GPTPStatus)
.value("EthernetStatus", Message::Type::EthernetStatus); .value("EthernetStatus", Message::Type::EthernetStatus)
.finalize();
message.def(pybind11::init<Message::Type>()); message.def(pybind11::init<Message::Type>());
message.def_readonly("type", &Message::type); message.def_readonly("type", &Message::type);
message.def_readwrite("timestamp", &Message::timestamp); message.def_readwrite("timestamp", &Message::timestamp);
pybind11::class_<RawMessage, std::shared_ptr<RawMessage>, Message>(m, "RawMessage") pybind11::classh<RawMessage, Message>(m, "RawMessage")
.def_readwrite("network", &RawMessage::network) .def_readwrite("network", &RawMessage::network)
.def_readwrite("data", &RawMessage::data); .def_readwrite("data", &RawMessage::data);
pybind11::class_<Frame, std::shared_ptr<Frame>, RawMessage>(m, "Frame") pybind11::classh<Frame, RawMessage>(m, "Frame")
.def_readwrite("description", &Frame::description) .def_readwrite("description", &Frame::description)
.def_readwrite("transmitted", &Frame::transmitted) .def_readwrite("transmitted", &Frame::transmitted)
.def_readwrite("error", &Frame::error); .def_readwrite("error", &Frame::error);
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_scriptstatusmessage(pybind11::module_& m) { void init_scriptstatusmessage(pybind11::module_& m) {
pybind11::class_<ScriptStatusMessage, std::shared_ptr<ScriptStatusMessage>, Message>(m, "ScriptStatusMessage") pybind11::classh<ScriptStatusMessage, Message>(m, "ScriptStatusMessage")
.def_readonly("isEncrypted", &ScriptStatusMessage::isEncrypted) .def_readonly("isEncrypted", &ScriptStatusMessage::isEncrypted)
.def_readonly("isCoreminiRunning", &ScriptStatusMessage::isCoreminiRunning) .def_readonly("isCoreminiRunning", &ScriptStatusMessage::isCoreminiRunning)
.def_readonly("sectorOverflows", &ScriptStatusMessage::sectorOverflows) .def_readonly("sectorOverflows", &ScriptStatusMessage::sectorOverflows)
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_spimessage(pybind11::module_& m) { void init_spimessage(pybind11::module_& m) {
pybind11::class_<SPIMessage, std::shared_ptr<SPIMessage>, Frame> spiMessage(m, "SPIMessage"); pybind11::classh<SPIMessage, Frame> spiMessage(m, "SPIMessage");
pybind11::enum_<SPIMessage::Direction>(spiMessage, "Direction") pybind11::enum_<SPIMessage::Direction>(spiMessage, "Direction")
.value("Write", SPIMessage::Direction::Write) .value("Write", SPIMessage::Direction::Write)
.value("Read", SPIMessage::Direction::Read); .value("Read", SPIMessage::Direction::Read);
@@ -17,7 +17,7 @@ void init_tc10statusmessage(pybind11::module_& m) {
.value("SleepFailed", TC10SleepStatus::SleepFailed) .value("SleepFailed", TC10SleepStatus::SleepFailed)
.value("SleepAborted", TC10SleepStatus::SleepAborted); .value("SleepAborted", TC10SleepStatus::SleepAborted);
pybind11::class_<TC10StatusMessage, std::shared_ptr<TC10StatusMessage>, Message>(m, "TC10StatusMessage") pybind11::classh<TC10StatusMessage, Message>(m, "TC10StatusMessage")
.def_readonly("wakeStatus", &TC10StatusMessage::wakeStatus) .def_readonly("wakeStatus", &TC10StatusMessage::wakeStatus)
.def_readonly("sleepStatus", &TC10StatusMessage::sleepStatus); .def_readonly("sleepStatus", &TC10StatusMessage::sleepStatus);
} }
@@ -1,15 +1,16 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/communication/network.h" #include "icsneo/communication/network.h"
namespace icsneo { namespace icsneo {
void init_network(pybind11::module_& m) { void init_network(pybind11::module_& m) {
pybind11::class_<Network> network(m, "Network"); pybind11::classh<Network> network(m, "Network");
pybind11::enum_<Network::NetID>(network, "NetID") pybind11::native_enum<Network::NetID>(network, "NetID", "enum.IntEnum")
.value("Device", Network::NetID::Device) .value("Device", Network::NetID::Device)
.value("DWCAN_01", Network::NetID::DWCAN_01) .value("DWCAN_01", Network::NetID::DWCAN_01)
.value("DWCAN_08", Network::NetID::DWCAN_08) .value("DWCAN_08", Network::NetID::DWCAN_08)
@@ -166,9 +167,10 @@ void init_network(pybind11::module_& m) {
.value("LIN_15", Network::NetID::LIN_15) .value("LIN_15", Network::NetID::LIN_15)
.value("LIN_16", Network::NetID::LIN_16) .value("LIN_16", Network::NetID::LIN_16)
.value("Any", Network::NetID::Any) .value("Any", Network::NetID::Any)
.value("Invalid", Network::NetID::Invalid); .value("Invalid", Network::NetID::Invalid)
.finalize();
pybind11::enum_<Network::Type>(network, "Type") pybind11::native_enum<Network::Type>(network, "Type", "enum.Enum")
.value("Invalid", Network::Type::Invalid) .value("Invalid", Network::Type::Invalid)
.value("Internal", Network::Type::Internal) .value("Internal", Network::Type::Internal)
.value("CAN", Network::Type::CAN) .value("CAN", Network::Type::CAN)
@@ -185,7 +187,8 @@ void init_network(pybind11::module_& m) {
.value("MDIO", Network::Type::MDIO) .value("MDIO", Network::Type::MDIO)
.value("AutomotiveEthernet", Network::Type::AutomotiveEthernet) .value("AutomotiveEthernet", Network::Type::AutomotiveEthernet)
.value("Any", Network::Type::Any) .value("Any", Network::Type::Any)
.value("Other", Network::Type::Other); .value("Other", Network::Type::Other)
.finalize();
network network
.def(pybind11::init<Network::NetID>()) .def(pybind11::init<Network::NetID>())
+9 -9
View File
@@ -35,17 +35,17 @@ void init_macsecconfig(pybind11::module_ & m)
.value("GCM_AES_128_XPN", MACsecCipherSuite::GcmAes128Xpn) .value("GCM_AES_128_XPN", MACsecCipherSuite::GcmAes128Xpn)
.value("GCM_AES_256_XPN", MACsecCipherSuite::GcmAes256Xpn); .value("GCM_AES_256_XPN", MACsecCipherSuite::GcmAes256Xpn);
pybind11::class_<MACsecVLANTag, std::shared_ptr<MACsecVLANTag>>(m, "MACsecVLANTag") pybind11::classh<MACsecVLANTag>(m, "MACsecVLANTag")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("vid", &MACsecVLANTag::vid) .def_readwrite("vid", &MACsecVLANTag::vid)
.def_readwrite("pri_cfi", &MACsecVLANTag::priCfi); .def_readwrite("pri_cfi", &MACsecVLANTag::priCfi);
pybind11::class_<MACsecMPLSOuter, std::shared_ptr<MACsecMPLSOuter>>(m, "MACsecMPLSOuter") pybind11::classh<MACsecMPLSOuter>(m, "MACsecMPLSOuter")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("mpls_label", &MACsecMPLSOuter::mplsLabel) .def_readwrite("mpls_label", &MACsecMPLSOuter::mplsLabel)
.def_readwrite("exp", &MACsecMPLSOuter::exp); .def_readwrite("exp", &MACsecMPLSOuter::exp);
pybind11::class_<MACsecTci, std::shared_ptr<MACsecTci>>(m, "MACsecTci") pybind11::classh<MACsecTci>(m, "MACsecTci")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("es", &MACsecTci::es) .def_readwrite("es", &MACsecTci::es)
.def_readwrite("sc", &MACsecTci::sc) .def_readwrite("sc", &MACsecTci::sc)
@@ -53,7 +53,7 @@ void init_macsecconfig(pybind11::module_ & m)
.def_readwrite("e", &MACsecTci::e) .def_readwrite("e", &MACsecTci::e)
.def_readwrite("c", &MACsecTci::c); .def_readwrite("c", &MACsecTci::c);
pybind11::class_<MACsecRxRule, std::shared_ptr<MACsecRxRule>>(m, "MACsecRxRule") pybind11::classh<MACsecRxRule>(m, "MACsecRxRule")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("key_mac_da", &MACsecRxRule::keyMacDa) .def_readwrite("key_mac_da", &MACsecRxRule::keyMacDa)
.def_readwrite("mask_mac_da", &MACsecRxRule::maskMacDa) .def_readwrite("mask_mac_da", &MACsecRxRule::maskMacDa)
@@ -85,7 +85,7 @@ void init_macsecconfig(pybind11::module_ & m)
.def_readwrite("mask_express", &MACsecRxRule::maskExpress) .def_readwrite("mask_express", &MACsecRxRule::maskExpress)
.def_readwrite("is_mpls", &MACsecRxRule::isMpls); .def_readwrite("is_mpls", &MACsecRxRule::isMpls);
pybind11::class_<MACsecTxSecY, std::shared_ptr<MACsecTxSecY>>(m, "MACsecTxSecY") pybind11::classh<MACsecTxSecY>(m, "MACsecTxSecY")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("enable_control_port", &MACsecTxSecY::enableControlPort) .def_readwrite("enable_control_port", &MACsecTxSecY::enableControlPort)
.def_readwrite("cipher", &MACsecTxSecY::cipher) .def_readwrite("cipher", &MACsecTxSecY::cipher)
@@ -99,7 +99,7 @@ void init_macsecconfig(pybind11::module_ & m)
.def_readwrite("auxiliary_policy", &MACsecTxSecY::auxiliaryPolicy) .def_readwrite("auxiliary_policy", &MACsecTxSecY::auxiliaryPolicy)
.def_readwrite("sci", &MACsecTxSecY::sci); .def_readwrite("sci", &MACsecTxSecY::sci);
pybind11::class_<MACsecRxSecY, std::shared_ptr<MACsecRxSecY>>(m, "MACsecRxSecY") pybind11::classh<MACsecRxSecY>(m, "MACsecRxSecY")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("enable_control_port", &MACsecRxSecY::enableControlPort) .def_readwrite("enable_control_port", &MACsecRxSecY::enableControlPort)
.def_readwrite("frame_validation", &MACsecRxSecY::frameValidation) .def_readwrite("frame_validation", &MACsecRxSecY::frameValidation)
@@ -112,7 +112,7 @@ void init_macsecconfig(pybind11::module_ & m)
.def_readwrite("is_control_packet", &MACsecRxSecY::isControlPacket) .def_readwrite("is_control_packet", &MACsecRxSecY::isControlPacket)
.def_readwrite("sci", &MACsecRxSecY::sci); .def_readwrite("sci", &MACsecRxSecY::sci);
pybind11::class_<MACsecTxSa, std::shared_ptr<MACsecTxSa>>(m, "MACsecTxSa") pybind11::classh<MACsecTxSa>(m, "MACsecTxSa")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("sak", &MACsecTxSa::sak) .def_readwrite("sak", &MACsecTxSa::sak)
.def_readwrite("hash_key", &MACsecTxSa::hashKey) .def_readwrite("hash_key", &MACsecTxSa::hashKey)
@@ -121,7 +121,7 @@ void init_macsecconfig(pybind11::module_ & m)
.def_readwrite("next_pn", &MACsecTxSa::nextPn) .def_readwrite("next_pn", &MACsecTxSa::nextPn)
.def_readwrite("an", &MACsecTxSa::an); .def_readwrite("an", &MACsecTxSa::an);
pybind11::class_<MACsecRxSa, std::shared_ptr<MACsecRxSa>>(m, "MACsecRxSa") pybind11::classh<MACsecRxSa>(m, "MACsecRxSa")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("sak", &MACsecRxSa::sak) .def_readwrite("sak", &MACsecRxSa::sak)
.def_readwrite("hash_key", &MACsecRxSa::hashKey) .def_readwrite("hash_key", &MACsecRxSa::hashKey)
@@ -129,7 +129,7 @@ void init_macsecconfig(pybind11::module_ & m)
.def_readwrite("ssci", &MACsecRxSa::ssci) .def_readwrite("ssci", &MACsecRxSa::ssci)
.def_readwrite("next_pn", &MACsecRxSa::nextPn); .def_readwrite("next_pn", &MACsecRxSa::nextPn);
pybind11::class_<MACsecConfig, std::shared_ptr<MACsecConfig>>(m, "MACsecConfig") pybind11::classh<MACsecConfig>(m, "MACsecConfig")
.def(pybind11::init<icsneo::DeviceType>()) .def(pybind11::init<icsneo::DeviceType>())
.def("add_rx_secy", &MACsecConfig::addRxSecY, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("add_rx_secy", &MACsecConfig::addRxSecY, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("add_tx_secY", &MACsecConfig::addTxSecY, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("add_tx_secY", &MACsecConfig::addTxSecY, pybind11::call_guard<pybind11::gil_scoped_release>())
+4 -2
View File
@@ -1,13 +1,14 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/device/chipid.h" #include "icsneo/device/chipid.h"
namespace icsneo { namespace icsneo {
void init_chipid(pybind11::module_& m) { void init_chipid(pybind11::module_& m) {
pybind11::enum_<ChipID>(m, "ChipID") pybind11::native_enum<ChipID>(m, "ChipID", "enum.IntEnum")
.value("neoVIFIRE_MCHIP", ChipID::neoVIFIRE_MCHIP) .value("neoVIFIRE_MCHIP", ChipID::neoVIFIRE_MCHIP)
.value("neoVIFIRE_LCHIP", ChipID::neoVIFIRE_LCHIP) .value("neoVIFIRE_LCHIP", ChipID::neoVIFIRE_LCHIP)
.value("neoVIFIRE_UCHIP", ChipID::neoVIFIRE_UCHIP) .value("neoVIFIRE_UCHIP", ChipID::neoVIFIRE_UCHIP)
@@ -130,7 +131,8 @@ void init_chipid(pybind11::module_& m) {
.value("Connect_LINUX", ChipID::Connect_LINUX) .value("Connect_LINUX", ChipID::Connect_LINUX)
.value("RADGigastar2_ZYNQ", ChipID::RADGigastar2_ZYNQ) .value("RADGigastar2_ZYNQ", ChipID::RADGigastar2_ZYNQ)
.value("RADGemini_MCHIP", ChipID::RADGemini_MCHIP) .value("RADGemini_MCHIP", ChipID::RADGemini_MCHIP)
.value("Invalid", ChipID::Invalid); .value("Invalid", ChipID::Invalid)
.finalize();
} }
} // namespace icsneo } // namespace icsneo
+6 -1
View File
@@ -11,7 +11,7 @@
namespace icsneo { namespace icsneo {
void init_device(pybind11::module_& m) { void init_device(pybind11::module_& m) {
pybind11::class_<Device, std::shared_ptr<Device>>(m, "Device") pybind11::classh<Device>(m, "Device")
.def("__repr__", &Device::describe) .def("__repr__", &Device::describe)
.def("add_message_callback", &Device::addMessageCallback, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("add_message_callback", &Device::addMessageCallback, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("clear_script", &Device::clearScript, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("clear_script", &Device::clearScript, pybind11::call_guard<pybind11::gil_scoped_release>())
@@ -52,6 +52,11 @@ void init_device(pybind11::module_& m) {
.def("start_script", &Device::startScript, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("start_script", &Device::startScript, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("stop_script", &Device::stopScript, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("stop_script", &Device::stopScript, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("supports_tc10", &Device::supportsTC10) .def("supports_tc10", &Device::supportsTC10)
.def("supports_live_data", &Device::supportsLiveData)
.def("subscribe_live_data", &Device::subscribeLiveData, pybind11::arg("message"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("unsubscribe_live_data", &Device::unsubscribeLiveData, pybind11::arg("handle"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("clear_all_live_data", &Device::clearAllLiveData, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_value_live_data", &Device::setValueLiveData, pybind11::arg("message"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("transmit", pybind11::overload_cast<std::shared_ptr<Frame>>(&Device::transmit), pybind11::call_guard<pybind11::gil_scoped_release>()) .def("transmit", pybind11::overload_cast<std::shared_ptr<Frame>>(&Device::transmit), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("upload_coremini", [](Device& device, std::string& path, Disk::MemoryType memType) { std::ifstream ifs(path, std::ios::binary); return device.uploadCoremini(ifs, memType); }, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("upload_coremini", [](Device& device, std::string& path, Disk::MemoryType memType) { std::ifstream ifs(path, std::ios::binary); return device.uploadCoremini(ifs, memType); }, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("write_macsec_config", &Device::writeMACsecConfig, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("write_macsec_config", &Device::writeMACsecConfig, pybind11::call_guard<pybind11::gil_scoped_release>())
@@ -1,14 +1,15 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
namespace icsneo { namespace icsneo {
void init_devicetype(pybind11::module_& m) { void init_devicetype(pybind11::module_& m) {
pybind11::class_<DeviceType> deviceType(m, "DeviceType"); pybind11::classh<DeviceType> deviceType(m, "DeviceType");
pybind11::enum_<DeviceType::Enum>(deviceType, "Enum") pybind11::native_enum<DeviceType::Enum>(deviceType, "Enum", "enum.IntEnum")
.value("Unknown", DeviceType::Enum::Unknown) .value("Unknown", DeviceType::Enum::Unknown)
.value("BLUE", DeviceType::Enum::BLUE) .value("BLUE", DeviceType::Enum::BLUE)
.value("ECU_AVB", DeviceType::Enum::ECU_AVB) .value("ECU_AVB", DeviceType::Enum::ECU_AVB)
@@ -70,7 +71,8 @@ void init_devicetype(pybind11::module_& m) {
.value("RADGalaxy", DeviceType::Enum::RADGalaxy) .value("RADGalaxy", DeviceType::Enum::RADGalaxy)
.value("RADStar2", DeviceType::Enum::RADStar2) .value("RADStar2", DeviceType::Enum::RADStar2)
.value("VividCAN", DeviceType::Enum::VividCAN) .value("VividCAN", DeviceType::Enum::VividCAN)
.value("OBD2_SIM", DeviceType::Enum::OBD2_SIM); .value("OBD2_SIM", DeviceType::Enum::OBD2_SIM)
.finalize();
deviceType.def(pybind11::init<DeviceType::Enum>()); deviceType.def(pybind11::init<DeviceType::Enum>());
deviceType.def("get_device_type", &DeviceType::getDeviceType); deviceType.def("get_device_type", &DeviceType::getDeviceType);
deviceType.def("get_generic_product_name", &DeviceType::getGenericProductName); deviceType.def("get_generic_product_name", &DeviceType::getGenericProductName);
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_deviceextension(pybind11::module_& m) { void init_deviceextension(pybind11::module_& m) {
pybind11::class_<DeviceExtension, std::shared_ptr<DeviceExtension>>(m, "DeviceExtension") pybind11::classh<DeviceExtension>(m, "DeviceExtension")
.def("get_name", &DeviceExtension::getName); .def("get_name", &DeviceExtension::getName);
} }
@@ -16,7 +16,7 @@ struct DeviceSettingsNamespace {
}; };
void init_idevicesettings(pybind11::module_& m) { void init_idevicesettings(pybind11::module_& m) {
pybind11::class_<DeviceSettingsNamespace> settings(m, "Settings"); pybind11::classh<DeviceSettingsNamespace> settings(m, "Settings");
pybind11::enum_<DeviceSettingsNamespace::EthLinkMode>(settings, "EthernetLinkMode") pybind11::enum_<DeviceSettingsNamespace::EthLinkMode>(settings, "EthernetLinkMode")
.value("Auto", DeviceSettingsNamespace::EthLinkMode::AE_LINK_AUTO) .value("Auto", DeviceSettingsNamespace::EthLinkMode::AE_LINK_AUTO)
@@ -31,16 +31,49 @@ void init_idevicesettings(pybind11::module_& m) {
.value("Speed5G", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_5000) .value("Speed5G", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_5000)
.value("Speed10G", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_10000); .value("Speed10G", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_10000);
pybind11::class_<IDeviceSettings, std::shared_ptr<IDeviceSettings>>(m, "IDeviceSettings") pybind11::enum_<LINMode>(settings, "LINMode")
.value("Sleep", LINMode::SLEEP_MODE)
.value("Slow", LINMode::SLOW_MODE)
.value("Normal", LINMode::NORMAL_MODE)
.value("Fast", LINMode::FAST_MODE);
pybind11::classh<IDeviceSettings>(m, "IDeviceSettings")
.def("apply", &IDeviceSettings::apply, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("apply", &IDeviceSettings::apply, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("apply_defaults", &IDeviceSettings::applyDefaults, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("apply_defaults", &IDeviceSettings::applyDefaults, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("refresh", &IDeviceSettings::refresh, pybind11::call_guard<pybind11::gil_scoped_release>())
// Baudrate methods
.def("get_baudrate", &IDeviceSettings::getBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_baudrate", &IDeviceSettings::setBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_fd_baudrate", &IDeviceSettings::getFDBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_fd_baudrate", &IDeviceSettings::setFDBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
// Termination methods
.def("is_termination_supported", &IDeviceSettings::isTerminationSupportedFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("can_termination_be_enabled", &IDeviceSettings::canTerminationBeEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("is_termination_enabled", &IDeviceSettings::isTerminationEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_termination", &IDeviceSettings::setTerminationFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_termination_groups", &IDeviceSettings::getTerminationGroups, pybind11::call_guard<pybind11::gil_scoped_release>())
// LIN methods
.def("is_commander_resistor_enabled", &IDeviceSettings::isCommanderResistorEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_commander_resistor", &IDeviceSettings::setCommanderResistorFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_lin_mode", &IDeviceSettings::getLINModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_lin_mode", &IDeviceSettings::setLINModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_lin_commander_response_time", &IDeviceSettings::getLINCommanderResponseTimeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_lin_commander_response_time", &IDeviceSettings::setLINCommanderResponseTimeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
// Ethernet PHY methods
.def("get_phy_enable", &IDeviceSettings::getPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_phy_enable", &IDeviceSettings::getPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_phy_mode", &IDeviceSettings::getPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_phy_mode", &IDeviceSettings::getPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_phy_speed", &IDeviceSettings::getPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_phy_speed", &IDeviceSettings::getPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_phy_enable", &IDeviceSettings::setPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("set_phy_enable", &IDeviceSettings::setPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_phy_mode", &IDeviceSettings::setPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("set_phy_mode", &IDeviceSettings::setPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_phy_speed", &IDeviceSettings::setPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("set_phy_speed", &IDeviceSettings::setPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("refresh", &IDeviceSettings::refresh, pybind11::call_guard<pybind11::gil_scoped_release>());
// Status properties
.def_readonly("disabled", &IDeviceSettings::disabled)
.def_readonly("readonly", &IDeviceSettings::readonly);
} }
} // namespace icsneo } // namespace icsneo
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_versionreport(pybind11::module_& m) { void init_versionreport(pybind11::module_& m) {
pybind11::class_<VersionReport>(m, "VersionReport") pybind11::classh<VersionReport>(m, "VersionReport")
.def_readonly("id", &VersionReport::id) .def_readonly("id", &VersionReport::id)
.def_readonly("name", &VersionReport::name) .def_readonly("name", &VersionReport::name)
.def_readonly("major", &VersionReport::major) .def_readonly("major", &VersionReport::major)
+1 -1
View File
@@ -13,7 +13,7 @@ struct DiskNamespace {
}; };
void init_diskdriver(pybind11::module_& m) { void init_diskdriver(pybind11::module_& m) {
pybind11::class_<DiskNamespace> disk(m, "Disk"); pybind11::classh<DiskNamespace> disk(m, "Disk");
pybind11::enum_<Disk::Access>(disk, "Access") pybind11::enum_<Disk::Access>(disk, "Access")
.value("None", Disk::Access::None) .value("None", Disk::Access::None)
.value("EntireCard", Disk::Access::EntireCard) .value("EntireCard", Disk::Access::EntireCard)
+8 -8
View File
@@ -23,8 +23,8 @@ struct ClusterNamespace {
using SPPType = icsneo::FlexRay::Cluster::SPPType; using SPPType = icsneo::FlexRay::Cluster::SPPType;
}; };
void init_extension(pybind11::class_<FlexRayNamespace>& c) { void init_extension(pybind11::classh<FlexRayNamespace>& c) {
pybind11::class_<MessageBuffer, std::shared_ptr<MessageBuffer>>(c, "MessageBuffer") pybind11::classh<MessageBuffer>(c, "MessageBuffer")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("is_dynamic", &MessageBuffer::isDynamic) .def_readwrite("is_dynamic", &MessageBuffer::isDynamic)
.def_readwrite("is_sync", &MessageBuffer::isSync) .def_readwrite("is_sync", &MessageBuffer::isSync)
@@ -39,7 +39,7 @@ void init_extension(pybind11::class_<FlexRayNamespace>& c) {
.def_readwrite("cycle_repetition", &MessageBuffer::cycleRepetition) .def_readwrite("cycle_repetition", &MessageBuffer::cycleRepetition)
.def_readwrite("continuous_mode", &MessageBuffer::continuousMode); .def_readwrite("continuous_mode", &MessageBuffer::continuousMode);
auto controller = pybind11::class_<Controller, std::shared_ptr<Controller>>(c, "Controller") auto controller = pybind11::classh<Controller>(c, "Controller")
.def("get_network", &Controller::getNetwork) .def("get_network", &Controller::getNetwork)
.def("get_configuration", &Controller::getConfiguration) .def("get_configuration", &Controller::getConfiguration)
.def("set_configuration", &Controller::setConfiguration) .def("set_configuration", &Controller::setConfiguration)
@@ -59,7 +59,7 @@ void init_extension(pybind11::class_<FlexRayNamespace>& c) {
.def("freeze", &Controller::freeze) .def("freeze", &Controller::freeze)
.def("trigger_mts", &Controller::triggerMTS); .def("trigger_mts", &Controller::triggerMTS);
pybind11::class_<Controller::Configuration>(controller, "Configuration") pybind11::classh<Controller::Configuration>(controller, "Configuration")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("accept_startup_range_microticks", &Controller::Configuration::AcceptStartupRangeMicroticks) .def_readwrite("accept_startup_range_microticks", &Controller::Configuration::AcceptStartupRangeMicroticks)
.def_readwrite("allow_passive_to_active_cycle_pairs", &Controller::Configuration::AllowPassiveToActiveCyclePairs) .def_readwrite("allow_passive_to_active_cycle_pairs", &Controller::Configuration::AllowPassiveToActiveCyclePairs)
@@ -93,7 +93,7 @@ void init_extension(pybind11::class_<FlexRayNamespace>& c) {
.def_readwrite("wakeup_on_channel_b", &Controller::Configuration::WakeupOnChannelB); .def_readwrite("wakeup_on_channel_b", &Controller::Configuration::WakeupOnChannelB);
// Dummy class for cluster namespace // Dummy class for cluster namespace
pybind11::class_<ClusterNamespace> cluster(c, "Cluster"); pybind11::classh<ClusterNamespace> cluster(c, "Cluster");
pybind11::enum_<Cluster::SpeedType>(cluster, "SpeedType") pybind11::enum_<Cluster::SpeedType>(cluster, "SpeedType")
.value("FLEXRAY_BAUDRATE_10M", Cluster::SpeedType::FLEXRAY_BAUDRATE_10M) .value("FLEXRAY_BAUDRATE_10M", Cluster::SpeedType::FLEXRAY_BAUDRATE_10M)
@@ -107,7 +107,7 @@ void init_extension(pybind11::class_<FlexRayNamespace>& c) {
.value("FLEXRAY_SPP_6", Cluster::SPPType::FLEXRAY_SPP_6) .value("FLEXRAY_SPP_6", Cluster::SPPType::FLEXRAY_SPP_6)
.value("FLEXRAY_SPP_5_ALT", Cluster::SPPType::FLEXRAY_SPP_5_ALT); .value("FLEXRAY_SPP_5_ALT", Cluster::SPPType::FLEXRAY_SPP_5_ALT);
pybind11::class_<Cluster::Configuration>(cluster, "Configuration") pybind11::classh<Cluster::Configuration>(cluster, "Configuration")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("speed", &Cluster::Configuration::Speed) .def_readwrite("speed", &Cluster::Configuration::Speed)
.def_readwrite("strobe_point_position", &Cluster::Configuration::StrobePointPosition) .def_readwrite("strobe_point_position", &Cluster::Configuration::StrobePointPosition)
@@ -143,7 +143,7 @@ void init_extension(pybind11::class_<FlexRayNamespace>& c) {
} // namespace FlexRay } // namespace FlexRay
void init_flexraymessage(pybind11::module_& m) { void init_flexraymessage(pybind11::module_& m) {
pybind11::class_<FlexRayMessage, std::shared_ptr<FlexRayMessage>, Frame>(m, "FlexRayMessage") pybind11::classh<FlexRayMessage, Frame>(m, "FlexRayMessage")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("slotid", &FlexRayMessage::slotid) .def_readwrite("slotid", &FlexRayMessage::slotid)
.def_readwrite("tsslen", &FlexRayMessage::tsslen) .def_readwrite("tsslen", &FlexRayMessage::tsslen)
@@ -166,7 +166,7 @@ void init_flexraymessage(pybind11::module_& m) {
void init_flexray(pybind11::module_& m) { void init_flexray(pybind11::module_& m) {
// Dummy class to act as FlexRay namespace // Dummy class to act as FlexRay namespace
pybind11::class_<FlexRayNamespace> flexray(m, "FlexRay"); pybind11::classh<FlexRayNamespace> flexray(m, "FlexRay");
pybind11::enum_<FlexRayNamespace::Symbol>(flexray, "Symbol") pybind11::enum_<FlexRayNamespace::Symbol>(flexray, "Symbol")
.value("None", FlexRayNamespace::Symbol::None) .value("None", FlexRayNamespace::Symbol::None)
+4
View File
@@ -35,6 +35,8 @@ void init_version(pybind11::module_&);
void init_flexray(pybind11::module_& m); void init_flexray(pybind11::module_& m);
void init_idevicesettings(pybind11::module_&); void init_idevicesettings(pybind11::module_&);
void init_ethphymessage(pybind11::module_&); void init_ethphymessage(pybind11::module_&);
void init_livedata(pybind11::module_&);
void init_livedatamessage(pybind11::module_&);
PYBIND11_MODULE(icsneopy, m) { PYBIND11_MODULE(icsneopy, m) {
pybind11::options options; pybind11::options options;
@@ -48,6 +50,7 @@ PYBIND11_MODULE(icsneopy, m) {
init_devicetype(m); init_devicetype(m);
init_network(m); init_network(m);
init_io(m); init_io(m);
init_livedata(m);
init_message(m); init_message(m);
init_canmessage(m); init_canmessage(m);
init_canerrormessage(m); init_canerrormessage(m);
@@ -60,6 +63,7 @@ PYBIND11_MODULE(icsneopy, m) {
init_macsecconfig(m); init_macsecconfig(m);
init_scriptstatusmessage(m); init_scriptstatusmessage(m);
init_spimessage(m); init_spimessage(m);
init_livedatamessage(m);
init_messagefilter(m); init_messagefilter(m);
init_messagecallback(m); init_messagecallback(m);
init_diskdriver(m); init_diskdriver(m);
+1
View File
@@ -56,6 +56,7 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
break; break;
} }
case Network::Type::Internal:
case Network::Type::CAN: case Network::Type::CAN:
case Network::Type::SWCAN: case Network::Type::SWCAN:
case Network::Type::LSFTCAN: { case Network::Type::LSFTCAN: {
+6 -5
View File
@@ -19,7 +19,8 @@ double liveDataValueToDouble(const LiveDataValue& val) {
return val.value * liveDataFixedPointToDouble; return val.value * liveDataFixedPointToDouble;
} }
bool liveDataDoubleToValue(const double& dFloat, LiveDataValue& value) { std::optional<LiveDataValue> liveDataDoubleToValue(const double& dFloat) {
LiveDataValue value;
union { union {
struct struct
{ {
@@ -56,23 +57,23 @@ bool liveDataDoubleToValue(const double& dFloat, LiveDataValue& value) {
value.value = CminiFixedPt.ValueLarge; value.value = CminiFixedPt.ValueLarge;
if(dFloat == (double)0.0) if(dFloat == (double)0.0)
return true; return value;
//check if double can be stored as 32.32 //check if double can be stored as 32.32
// 0x1 0000 0000 0000 0000 * CM_FIXED_POINT_TO_DOUBLEVALUE = 0x1 0000 0000 // 0x1 0000 0000 0000 0000 * CM_FIXED_POINT_TO_DOUBLEVALUE = 0x1 0000 0000
if(dFloat > INT32_MAX_DOUBLE || dFloat < INT32_MIN_DOUBLE) { if(dFloat > INT32_MAX_DOUBLE || dFloat < INT32_MIN_DOUBLE) {
EventManager::GetInstance().add(APIEvent::Type::FixedPointOverflow, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::FixedPointOverflow, APIEvent::Severity::Error);
return false; return std::nullopt;
} }
// Use absolute value for minimum fixed point check // Use absolute value for minimum fixed point check
double absFloat = (dFloat < 0.0) ? -dFloat : dFloat; double absFloat = (dFloat < 0.0) ? -dFloat : dFloat;
if(absFloat < MIN_FIXED_POINT_DOUBLE) { if(absFloat < MIN_FIXED_POINT_DOUBLE) {
EventManager::GetInstance().add(APIEvent::Type::FixedPointPrecision, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::FixedPointPrecision, APIEvent::Severity::Error);
return false; return std::nullopt;
} }
return true; return value;
} }
} // namespace LiveDataUtil } // namespace LiveDataUtil
@@ -104,6 +104,7 @@ static std::vector<uint8_t> EncodeFromMessageCAN(std::shared_ptr<Frame> frame, c
canpacket->header.BRS = canmsg->baudrateSwitch ? 1 : 0; canpacket->header.BRS = canmsg->baudrateSwitch ? 1 : 0;
canpacket->header.ESI = canmsg->errorStateIndicator ? 1 : 0; canpacket->header.ESI = canmsg->errorStateIndicator ? 1 : 0;
canpacket->dlc.RTR = 0; canpacket->dlc.RTR = 0;
canpacket->timestamp.IsExtended = 1;
} else { } else {
canpacket->header.EDL = 0; canpacket->header.EDL = 0;
@@ -139,6 +140,7 @@ std::vector<uint8_t> TransmitMessage::EncodeFromMessage(std::shared_ptr<Frame> f
case Network::Type::AutomotiveEthernet: case Network::Type::AutomotiveEthernet:
result = EncodeFromMessageEthernet(frame, report); result = EncodeFromMessageEthernet(frame, report);
break; break;
case Network::Type::Internal:
case Network::Type::CAN: case Network::Type::CAN:
result = EncodeFromMessageCAN(frame, report); result = EncodeFromMessageCAN(frame, report);
break; break;
+21 -4
View File
@@ -1,5 +1,5 @@
#include "icsneo/communication/packet/ethernetpacket.h" #include "icsneo/communication/packet/ethernetpacket.h"
#include <algorithm> // for std::copy #include <algorithm>
#include <iostream> #include <iostream>
using namespace icsneo; using namespace icsneo;
@@ -10,16 +10,17 @@ std::shared_ptr<EthernetMessage> HardwareEthernetPacket::DecodeToMessage(const s
// Make sure we have enough to read the packet length first // Make sure we have enough to read the packet length first
if(bytestream.size() < sizeof(HardwareEthernetPacket)) if(bytestream.size() < sizeof(HardwareEthernetPacket))
return nullptr; return nullptr;
// packet->Length will also encompass the two uint16_t's at the end of the struct, make sure that at least they are here
if(packet->Length < 4)
return nullptr;
const size_t fcsSize = packet->header.FCS_AVAIL ? 4 : 0; const size_t fcsSize = packet->header.FCS_AVAIL ? 4 : 0;
// Ensure Length is sufficient for FCS extraction to avoid invalid iterator arithmetic
if(packet->Length < fcsSize)
return nullptr;
const size_t bytestreamExpectedSize = sizeof(HardwareEthernetPacket) + packet->Length; const size_t bytestreamExpectedSize = sizeof(HardwareEthernetPacket) + packet->Length;
const size_t bytestreamActualSize = bytestream.size(); const size_t bytestreamActualSize = bytestream.size();
if(bytestreamActualSize < bytestreamExpectedSize) if(bytestreamActualSize < bytestreamExpectedSize)
return nullptr; return nullptr;
auto messagePtr = std::make_shared<EthernetMessage>(); auto messagePtr = std::make_shared<EthernetMessage>();
EthernetMessage& message = *messagePtr; EthernetMessage& message = *messagePtr;
// Standard Ethernet fields
message.transmitted = packet->eid.TXMSG; message.transmitted = packet->eid.TXMSG;
if(message.transmitted) if(message.transmitted)
message.description = packet->stats; message.description = packet->stats;
@@ -27,12 +28,28 @@ std::shared_ptr<EthernetMessage> HardwareEthernetPacket::DecodeToMessage(const s
if(message.preemptionEnabled) if(message.preemptionEnabled)
message.preemptionFlags = (uint8_t)((rawWords[0] & 0x03F8) >> 4); message.preemptionFlags = (uint8_t)((rawWords[0] & 0x03F8) >> 4);
message.frameTooShort = packet->header.RUNT_FRAME; message.frameTooShort = packet->header.RUNT_FRAME;
message.noPadding = !packet->header.ENABLE_PADDING;
message.fcsVerified = packet->header.FCS_VERIFIED;
message.txAborted = packet->eid.TXAborted;
message.crcError = packet->header.CRC_ERROR;
if(message.frameTooShort) if(message.frameTooShort)
message.error = true; message.error = true;
// This timestamp is raw off the device (in timestampResolution increments) // This timestamp is raw off the device (in timestampResolution increments)
// Decoder will fix as it has information about the timestampResolution increments // Decoder will fix as it has information about the timestampResolution increments
message.timestamp = packet->timestamp.TS; message.timestamp = packet->timestamp.TS;
// Check if this is a T1S packet and populate T1S-specific fields
message.isT1S = packet->header.T1S_ETHERNET;
if(message.isT1S) {
message.isT1SSymbol = packet->eid.T1S_SYMBOL;
message.isT1SBurst = packet->eid.T1S_BURST;
message.txCollision = packet->t1s_status.TXCollision;
message.isT1SWake = packet->t1s_status.T1SWake;
message.t1sNodeId = packet->t1s_node.T1S_NODE_ID;
message.t1sBurstCount = packet->t1s_node.T1S_BURST_COUNT;
}
const std::vector<uint8_t>::const_iterator databegin = bytestream.begin() + sizeof(HardwareEthernetPacket); const std::vector<uint8_t>::const_iterator databegin = bytestream.begin() + sizeof(HardwareEthernetPacket);
const std::vector<uint8_t>::const_iterator dataend = databegin + packet->Length - fcsSize; const std::vector<uint8_t>::const_iterator dataend = databegin + packet->Length - fcsSize;
message.data.insert(message.data.begin(), databegin, dataend); message.data.insert(message.data.begin(), databegin, dataend);
+17
View File
@@ -27,6 +27,15 @@ Complete CAN Example
:language: python :language: python
LiveData Subscription and Monitoring
=====================================
:download:`Download example <../../examples/python/livedata/livedata_example.py>`
.. literalinclude:: ../../examples/python/livedata/livedata_example.py
:language: python
Transmit Ethernet frames on Ethernet 01 Transmit Ethernet frames on Ethernet 01
======================================== ========================================
@@ -74,3 +83,11 @@ Device Firmware/Chip Versions
.. literalinclude:: ../../examples/python/device/chip_versions.py .. literalinclude:: ../../examples/python/device/chip_versions.py
:language: python :language: python
SPI Example for 10BASE-T1S
=============================
:download:`Download example <../../examples/python/spi/spi_example.py>`
.. literalinclude:: ../../examples/python/spi/spi_example.py
:language: python
+31 -14
View File
@@ -29,7 +29,7 @@ int main() {
} }
std::cout << "OK" << std::endl; std::cout << "OK" << std::endl;
// Create a subscription message for the GPS signals // Create a subscription message for the GPS signals and TIME_SINCE_MSG
std::cout << "\tSending a live data subscribe command... "; std::cout << "\tSending a live data subscribe command... ";
auto msg = std::make_shared<icsneo::LiveDataCommandMessage>(); auto msg = std::make_shared<icsneo::LiveDataCommandMessage>();
msg->appendSignalArg(icsneo::LiveDataValueType::GPS_LATITUDE); msg->appendSignalArg(icsneo::LiveDataValueType::GPS_LATITUDE);
@@ -37,6 +37,7 @@ int main() {
msg->appendSignalArg(icsneo::LiveDataValueType::GPS_ACCURACY); msg->appendSignalArg(icsneo::LiveDataValueType::GPS_ACCURACY);
msg->appendSignalArg(icsneo::LiveDataValueType::DAQ_ENABLE); msg->appendSignalArg(icsneo::LiveDataValueType::DAQ_ENABLE);
msg->appendSignalArg(icsneo::LiveDataValueType::MANUAL_TRIGGER); msg->appendSignalArg(icsneo::LiveDataValueType::MANUAL_TRIGGER);
msg->appendSignalArg(icsneo::LiveDataValueType::TIME_SINCE_MSG);
msg->cmd = icsneo::LiveDataCommand::SUBSCRIBE; msg->cmd = icsneo::LiveDataCommand::SUBSCRIBE;
msg->handle = icsneo::LiveDataUtil::getNewHandle(); msg->handle = icsneo::LiveDataUtil::getNewHandle();
msg->updatePeriod = std::chrono::milliseconds(100); msg->updatePeriod = std::chrono::milliseconds(100);
@@ -44,6 +45,9 @@ int main() {
// Transmit the subscription message // Transmit the subscription message
ret = device->subscribeLiveData(msg); ret = device->subscribeLiveData(msg);
std::cout << (ret ? "OK" : "FAIL") << std::endl; std::cout << (ret ? "OK" : "FAIL") << std::endl;
if (!ret) {
std::cout << "\t\tError: " << icsneo::GetLastError() << std::endl;
}
// Register a handler that uses the data after it arrives every ~100ms // Register a handler that uses the data after it arrives every ~100ms
std::cout << "\tStreaming messages for 3 seconds... " << std::endl << std::endl; std::cout << "\tStreaming messages for 3 seconds... " << std::endl << std::endl;
@@ -53,19 +57,21 @@ int main() {
switch(ldMsg->cmd) { switch(ldMsg->cmd) {
case icsneo::LiveDataCommand::STATUS: { case icsneo::LiveDataCommand::STATUS: {
auto msg2 = std::dynamic_pointer_cast<icsneo::LiveDataStatusMessage>(message); auto msg2 = std::dynamic_pointer_cast<icsneo::LiveDataStatusMessage>(message);
std::cout << "[Handle] " << ldMsg->handle << std::endl; std::cout << "[STATUS Message]" << std::endl;
std::cout << "[Requested Command] " << msg2->requestedCommand << std::endl; std::cout << " Handle: " << ldMsg->handle << std::endl;
std::cout << "[Status] " << msg2->status << std::endl << std::endl; std::cout << " Requested Command: " << msg2->requestedCommand << std::endl;
std::cout << " Status: " << msg2->status << std::endl << std::endl;
break; break;
} }
case icsneo::LiveDataCommand::RESPONSE: { case icsneo::LiveDataCommand::RESPONSE: {
auto valueMsg = std::dynamic_pointer_cast<icsneo::LiveDataValueMessage>(message); auto valueMsg = std::dynamic_pointer_cast<icsneo::LiveDataValueMessage>(message);
if((valueMsg->handle == msg->handle) && (valueMsg->values.size() == msg->args.size())) if((valueMsg->handle == msg->handle) && (valueMsg->values.size() == msg->args.size()))
{ {
std::cout << "[Handle] " << msg->handle << std::endl; std::cout << "[Response Message]" << std::endl;
std::cout << "[Values] " << valueMsg->numArgs << std::endl; std::cout << " Handle: " << msg->handle << std::endl;
std::cout << " Number of Values: " << valueMsg->numArgs << std::endl;
for(uint32_t i = 0; i < valueMsg->numArgs; ++i) { for(uint32_t i = 0; i < valueMsg->numArgs; ++i) {
std::cout << "[" << msg->args[i]->valueType << "] "; std::cout << " [" << msg->args[i]->valueType << "] ";
auto scaledValue = icsneo::LiveDataUtil::liveDataValueToDouble(*valueMsg->values[i]); auto scaledValue = icsneo::LiveDataUtil::liveDataValueToDouble(*valueMsg->values[i]);
std::cout << scaledValue << std::endl; std::cout << scaledValue << std::endl;
} }
@@ -86,22 +92,33 @@ int main() {
setValMsg->cmd = icsneo::LiveDataCommand::SET_VALUE; setValMsg->cmd = icsneo::LiveDataCommand::SET_VALUE;
setValMsg->handle = msg->handle; setValMsg->handle = msg->handle;
// Convert the value format // Convert the value format
icsneo::LiveDataValue ldValueDAQEnable; auto ldValueDAQEnable = icsneo::LiveDataUtil::liveDataDoubleToValue(val / 3);
icsneo::LiveDataValue ldValueManTrig; auto ldValueManTrig = icsneo::LiveDataUtil::liveDataDoubleToValue(val);
if (!icsneo::LiveDataUtil::liveDataDoubleToValue(val / 3, ldValueDAQEnable) || auto ldValueTimeSinceMsg = icsneo::LiveDataUtil::liveDataDoubleToValue(val);
!icsneo::LiveDataUtil::liveDataDoubleToValue(val, ldValueManTrig)) { if (!ldValueDAQEnable || !ldValueManTrig || !ldValueTimeSinceMsg) {
std::cout << "\tError: Failed to convert values" << std::endl;
break; break;
} }
setValMsg->appendSetValue(icsneo::LiveDataValueType::DAQ_ENABLE, ldValueDAQEnable); setValMsg->appendSetValue(icsneo::LiveDataValueType::DAQ_ENABLE, *ldValueDAQEnable);
setValMsg->appendSetValue(icsneo::LiveDataValueType::MANUAL_TRIGGER, ldValueManTrig); setValMsg->appendSetValue(icsneo::LiveDataValueType::MANUAL_TRIGGER, *ldValueManTrig);
device->setValueLiveData(setValMsg); setValMsg->appendSetValue(icsneo::LiveDataValueType::TIME_SINCE_MSG, *ldValueTimeSinceMsg);
std::cout << "\tSetting values: DAQ_ENABLE=" << (val / 3)
<< ", MANUAL_TRIGGER=" << val
<< ", TIME_SINCE_MSG=" << val << std::endl;
if (!device->setValueLiveData(setValMsg)) {
std::cout << "\tError setting values: " << icsneo::GetLastError() << std::endl;
}
++val; ++val;
// Run handler for three seconds to observe the signal data // Run handler for three seconds to observe the signal data
std::this_thread::sleep_for(std::chrono::seconds(3)); std::this_thread::sleep_for(std::chrono::seconds(3));
} }
// Unsubscribe from the GPS signals and run handler for one more second // Unsubscribe from the GPS signals and run handler for one more second
// Unsubscription only requires a valid in-use handle, in this case from our previous subscription // Unsubscription only requires a valid in-use handle, in this case from our previous subscription
std::cout << "\tUnsubscribing... ";
ret = device->unsubscribeLiveData(msg->handle); ret = device->unsubscribeLiveData(msg->handle);
std::cout << (ret ? "OK" : "FAIL") << std::endl;
// The handler should no longer print values // The handler should no longer print values
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
device->removeMessageCallback(handler); device->removeMessageCallback(handler);
@@ -0,0 +1,130 @@
"""
LiveData subscription and monitoring example using icsneopy library.
"""
import icsneopy
import time
from datetime import timedelta
def livedata_example():
"""Subscribe to and monitor LiveData signals."""
devices = icsneopy.find_all_devices()
if not devices:
raise RuntimeError("No devices found")
device = devices[0]
print(f"Using device: {device}")
try:
if not device.open():
raise RuntimeError("Failed to open device")
if not device.go_online():
raise RuntimeError("Failed to go online")
device.enable_message_polling()
# Create subscription message
msg = icsneopy.LiveDataCommandMessage()
msg.handle = icsneopy.get_new_handle()
msg.cmd = icsneopy.LiveDataCommand.SUBSCRIBE
msg.update_period = timedelta(milliseconds=500)
msg.expiration_time = timedelta(milliseconds=0)
# Subscribe to various LiveData signals
msg.append_signal_arg(icsneopy.LiveDataValueType.GPS_LATITUDE)
msg.append_signal_arg(icsneopy.LiveDataValueType.GPS_LONGITUDE)
msg.append_signal_arg(icsneopy.LiveDataValueType.GPS_ACCURACY)
msg.append_signal_arg(icsneopy.LiveDataValueType.DAQ_ENABLE)
msg.append_signal_arg(icsneopy.LiveDataValueType.MANUAL_TRIGGER)
msg.append_signal_arg(icsneopy.LiveDataValueType.TIME_SINCE_MSG)
print("\nSubscribing to LiveData signals...")
if not device.subscribe_live_data(msg):
raise RuntimeError(f"Subscription failed: {icsneopy.get_last_error()}")
print("Subscription successful")
print("\nMonitoring LiveData for 5 seconds...")
response_count = 0
start_time = time.time()
while time.time() - start_time < 5:
result = device.get_messages()
messages = result[0] if isinstance(result, tuple) else result
for m in messages:
if isinstance(m, icsneopy.LiveDataStatusMessage):
if m.handle == msg.handle:
print(f"\n[Status] Command: {m.requested_command}, Status: {m.status}")
elif isinstance(m, icsneopy.LiveDataValueMessage):
if m.handle == msg.handle:
response_count += 1
print(f"\n[Response #{response_count}]")
signal_names = ["GPS_LAT", "GPS_LON", "GPS_ACC",
"DAQ_EN", "MAN_TRIG", "TIME_SINCE"]
for idx, val in enumerate(m.values):
value = icsneopy.livedata_value_to_double(val)
name = signal_names[idx] if idx < len(signal_names) else f"Signal_{idx}"
print(f" {name:12s}: {value:10.2f}")
time.sleep(0.1)
print(f"\nReceived {response_count} response messages")
# Demonstrate setting values
print("\nSetting custom values...")
set_msg = icsneopy.LiveDataSetValueMessage()
set_msg.handle = icsneopy.get_new_handle()
set_msg.cmd = icsneopy.LiveDataCommand.SET_VALUE
# Set DAQ_ENABLE
value = icsneopy.livedata_double_to_value(1.0)
if value:
set_msg.append_set_value(icsneopy.LiveDataValueType.DAQ_ENABLE, value)
# Set MANUAL_TRIGGER
value = icsneopy.livedata_double_to_value(1.0)
if value:
set_msg.append_set_value(icsneopy.LiveDataValueType.MANUAL_TRIGGER, value)
if device.set_value_live_data(set_msg):
print("Values set successfully")
time.sleep(0.5)
# Check the results
result = device.get_messages()
messages = result[0] if isinstance(result, tuple) else result
for m in messages:
if isinstance(m, icsneopy.LiveDataStatusMessage):
if m.handle == set_msg.handle:
print(f" Set status: {m.status}")
# Keep device awake by resetting TIME_SINCE_MSG
print("\nResetting TIME_SINCE_MSG to keep device awake...")
reset_msg = icsneopy.LiveDataSetValueMessage()
reset_msg.handle = icsneopy.get_new_handle()
reset_msg.cmd = icsneopy.LiveDataCommand.SET_VALUE
value = icsneopy.livedata_double_to_value(0.0)
if value:
reset_msg.append_set_value(icsneopy.LiveDataValueType.TIME_SINCE_MSG, value)
if device.set_value_live_data(reset_msg):
print("TIME_SINCE_MSG reset to 0")
# Unsubscribe
print("\nUnsubscribing...")
if device.unsubscribe_live_data(msg.handle):
print("Unsubscribed successfully")
finally:
device.close()
print("\nDevice closed")
if __name__ == "__main__":
livedata_example()
+134
View File
@@ -0,0 +1,134 @@
"""
Complete SPI example for 10BASE-T1S MACPHYs using icsneopy library.
Demonstrates device setup and SPI frame transmission/reception.
"""
import icsneopy
import time
def setup_device():
"""Initialize SPI device."""
devices = icsneopy.find_all_devices()
if not devices:
raise RuntimeError("No devices found")
device = devices[0]
print(f"Using device: {device}")
return device
def open_device(device):
"""Open device connection."""
try:
if not device.open():
raise RuntimeError("Failed to open device")
if not device.go_online():
device.close()
raise RuntimeError("Failed to go online")
print("Device initialized successfully")
return True
except Exception as e:
print(f"Device setup failed: {e}")
return False
def transmit_spi_frame(device, mms, addr, dir, write_data=None):
"""Transmit a SPI frame."""
frame = icsneopy.SPIMessage()
frame.network = icsneopy.Network(icsneopy.Network.NetID.SPI_01)
frame.direction = dir
frame.mms = mms
frame.address = addr
if dir == icsneopy.SPIMessage.Direction.Read:
frame.payload = [0] # single register
else:
frame.payload = [write_data]
success = device.transmit(frame)
if success:
print("Frame transmitted")
else:
print("Failed to transmit frame")
return success
def setup_spi_reception(device):
"""Configure SPI frame reception with callback."""
def frame_handler(frame):
access = (
"Write"
if frame.direction == icsneopy.SPIMessage.Direction.Write
else "Read"
)
print(
f"{access}, "
f"MMS: 0x{frame.mms:02X}, "
f"Register: 0x{frame.address:03X}, "
f"Data: {[hex(b) for b in frame.payload]}, "
f"Length: {len(frame.payload)}"
)
frame_filter = icsneopy.MessageFilter(icsneopy.Network.NetID.SPI_01)
callback = icsneopy.MessageCallback(frame_handler, frame_filter)
device.add_message_callback(callback)
print("SPI frame reception configured")
def cleanup_device(device):
"""Close device connection."""
if device:
device.close()
print("Device connection closed")
def main():
"""Complete SPI example with proper error handling."""
device = None
try:
# Setup device
device = setup_device()
# Open device
if not open_device(device):
raise RuntimeError("Failed to initialize device")
# Setup frame reception
setup_spi_reception(device)
# Read 10BASE-T1S MACPHY ID register
transmit_spi_frame(device, 0x0, 0x0001, icsneopy.SPIMessage.Direction.Read)
# Change 10BASE-T1S Test mode control
transmit_spi_frame(device, 0x3, 0x08FB, icsneopy.SPIMessage.Direction.Read)
transmit_spi_frame(
device, 0x3, 0x08FB, icsneopy.SPIMessage.Direction.Write, 0x6000
)
transmit_spi_frame(device, 0x3, 0x08FB, icsneopy.SPIMessage.Direction.Read)
time.sleep(0.1)
# Listen for responses
print("Listening for SPI frames for 5 seconds...")
time.sleep(5)
except Exception as e:
print(f"Error: {e}")
return 1
finally:
cleanup_device(device)
return 0
if __name__ == "__main__":
main()
+2 -1
View File
@@ -5,6 +5,7 @@
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <optional>
#include "icsneo/communication/command.h" #include "icsneo/communication/command.h"
#include "icsneo/api/eventmanager.h" #include "icsneo/api/eventmanager.h"
@@ -157,7 +158,7 @@ namespace LiveDataUtil
LiveDataHandle getNewHandle(); LiveDataHandle getNewHandle();
double liveDataValueToDouble(const LiveDataValue& val); double liveDataValueToDouble(const LiveDataValue& val);
bool liveDataDoubleToValue(const double& dFloat, LiveDataValue& value); std::optional<LiveDataValue> liveDataDoubleToValue(const double& dFloat);
static constexpr uint32_t LiveDataVersion = 1; static constexpr uint32_t LiveDataVersion = 1;
} // namespace LiveDataUtil } // namespace LiveDataUtil
@@ -4,17 +4,17 @@
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/communication/message/message.h" #include "icsneo/communication/message/message.h"
#include <string>
// Used for MACAddress.toString() only #include <vector>
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <cstring>
namespace icsneo { namespace icsneo {
struct MACAddress { struct MACAddress {
uint8_t data[6]; uint8_t data[6];
// Helpers
std::string toString() const { std::string toString() const {
std::stringstream ss; std::stringstream ss;
for(size_t i = 0; i < 6; i++) { for(size_t i = 0; i < 6; i++) {
@@ -33,11 +33,25 @@ struct MACAddress {
class EthernetMessage : public Frame { class EthernetMessage : public Frame {
public: public:
// Standard Ethernet fields
bool preemptionEnabled = false; bool preemptionEnabled = false;
uint8_t preemptionFlags = 0; uint8_t preemptionFlags = 0;
std::optional<uint32_t> fcs; std::optional<uint32_t> fcs;
bool frameTooShort = false; bool frameTooShort = false;
bool noPadding = false; bool noPadding = false;
bool fcsVerified = false;
bool txAborted = false;
bool crcError = false;
bool isT1S = false;
bool isT1SSymbol = false;
bool isT1SBurst = false;
bool txCollision = false;
bool isT1SWake = false;
uint8_t t1sNodeId = 0;
uint8_t t1sBurstCount = 0;
uint8_t t1sSymbolType = 0;
// Accessors // Accessors
const MACAddress& getDestinationMAC() const { return *(const MACAddress*)(data.data() + 0); } const MACAddress& getDestinationMAC() const { return *(const MACAddress*)(data.data() + 0); }
+2
View File
@@ -910,6 +910,8 @@ protected:
diskWriteDriver = std::unique_ptr<DiskWrite>(new DiskWrite()); diskWriteDriver = std::unique_ptr<DiskWrite>(new DiskWrite());
setupSupportedRXNetworks(supportedRXNetworks); setupSupportedRXNetworks(supportedRXNetworks);
setupSupportedTXNetworks(supportedTXNetworks); setupSupportedTXNetworks(supportedTXNetworks);
supportedRXNetworks.emplace_back(Network::NetID::Device);
supportedTXNetworks.emplace_back(Network::NetID::Device);
setupExtensions(); setupExtensions();
} }
@@ -35,7 +35,11 @@ public:
const std::vector<ChipInfo>& getChipInfo() const override { const std::vector<ChipInfo>& getChipInfo() const override {
static std::vector<ChipInfo> chips = { static std::vector<ChipInfo> chips = {
// We add both chips here because there is a mismatch between the id of the chip on the device
// and the chip that the bootloader extension expects. The device reports a RADProxima chip,
// but we use RADEpsilon firmware.
{ChipID::RADProxima_MCHIP, true, "MCHIP", "epsilon_mchip_ief", 0, FirmwareType::IEF}, {ChipID::RADProxima_MCHIP, true, "MCHIP", "epsilon_mchip_ief", 0, FirmwareType::IEF},
{ChipID::RADEpsilon_MCHIP, true, "MCHIP", "epsilon_mchip_ief", 0, FirmwareType::IEF}
}; };
return chips; return chips;
} }
@@ -43,7 +47,8 @@ public:
BootloaderPipeline getBootloader() override { BootloaderPipeline getBootloader() override {
return BootloaderPipeline() return BootloaderPipeline()
.add<EnterBootloaderPhase>() .add<EnterBootloaderPhase>()
.add<FlashPhase>(ChipID::RADProxima_MCHIP, BootloaderCommunication::RED) .add<FlashPhase>(ChipID::RADEpsilon_MCHIP, BootloaderCommunication::RED)
.add<EnterApplicationPhase>(ChipID::RADEpsilon_MCHIP)
.add<ReconnectPhase>(); .add<ReconnectPhase>();
} }
@@ -49,6 +49,10 @@ public:
Network::NetID::AE_10, Network::NetID::AE_10,
Network::NetID::AE_11, Network::NetID::AE_11,
Network::NetID::AE_12, Network::NetID::AE_12,
Network::NetID::AE_13,
Network::NetID::AE_14,
Network::NetID::AE_15,
Network::NetID::AE_16,
Network::NetID::ISO9141_01, Network::NetID::ISO9141_01,
Network::NetID::ISO9141_02, Network::NetID::ISO9141_02,
@@ -67,6 +67,7 @@ public:
const std::vector<ChipInfo>& getChipInfo() const override { const std::vector<ChipInfo>& getChipInfo() const override {
static std::vector<ChipInfo> chips = { static std::vector<ChipInfo> chips = {
{ChipID::ValueCAN4_2EL_MCHIP, true, "MCHIP", "vcan44_mchip_ief", 0, FirmwareType::IEF}, {ChipID::ValueCAN4_2EL_MCHIP, true, "MCHIP", "vcan44_mchip_ief", 0, FirmwareType::IEF},
{ChipID::ValueCAN4_4_MCHIP, true, "MCHIP", "vcan44_mchip_ief", 0, FirmwareType::IEF}
}; };
return chips; return chips;
} }
@@ -74,8 +75,8 @@ public:
BootloaderPipeline getBootloader() override { BootloaderPipeline getBootloader() override {
return BootloaderPipeline() return BootloaderPipeline()
.add<EnterBootloaderPhase>() .add<EnterBootloaderPhase>()
.add<FlashPhase>(ChipID::ValueCAN4_2EL_MCHIP, BootloaderCommunication::RED) .add<FlashPhase>(ChipID::ValueCAN4_4_MCHIP, BootloaderCommunication::RED)
.add<EnterApplicationPhase>(ChipID::ValueCAN4_2EL_MCHIP) .add<EnterApplicationPhase>(ChipID::ValueCAN4_4_MCHIP)
.add<WaitPhase>(std::chrono::milliseconds(3000)) .add<WaitPhase>(std::chrono::milliseconds(3000))
.add<ReconnectPhase>(); .add<ReconnectPhase>();
} }
+17 -5
View File
@@ -19,6 +19,9 @@ class FirmIO : public Driver {
public: public:
static void Find(std::vector<FoundDevice>& foundDevices); static void Find(std::vector<FoundDevice>& foundDevices);
FirmIO(const device_eventhandler_t& report) : Driver(report) {
writeQueueSize = 256;
}
using Driver::Driver; // Inherit constructor using Driver::Driver; // Inherit constructor
~FirmIO(); ~FirmIO();
bool open() override; bool open() override;
@@ -26,16 +29,16 @@ public:
bool close() override; bool close() override;
driver_finder_t getFinder() override { return FirmIO::Find; } driver_finder_t getFinder() override { return FirmIO::Find; }
// bool writeQueueFull() override;
// bool writeQueueAlmostFull() override;
bool writeInternal(const std::vector<uint8_t>& b) override;
private: private:
std::thread readThread, writeThread; std::thread readThread, writeThread;
void readTask(); void readTask();
void writeTask(); void writeTask();
bool writeQueueFull() override;
bool writeQueueAlmostFull() override;
bool writeInternal(const std::vector<uint8_t>& bytes) override;
struct DataInfo { struct DataInfo {
uint32_t type; uint32_t type;
uint32_t offset; uint32_t offset;
@@ -111,7 +114,11 @@ private:
bool free(uint8_t* addr); bool free(uint8_t* addr);
PhysicalAddress translate(uint8_t* addr) const; PhysicalAddress translate(uint8_t* addr) const;
private: uint32_t getUsedBlocks() const { return usedBlocks; }
size_t getTotalBlocks() const { return blocks.size(); }
bool isFull() const { return usedBlocks == blocks.size(); }
struct BlockInfo { struct BlockInfo {
enum class Status : uint32_t { enum class Status : uint32_t {
Free = 0, Free = 0,
@@ -121,6 +128,7 @@ private:
uint8_t* addr; uint8_t* addr;
}; };
private:
std::vector<BlockInfo> blocks; std::vector<BlockInfo> blocks;
std::atomic<uint32_t> usedBlocks; std::atomic<uint32_t> usedBlocks;
@@ -137,6 +145,10 @@ private:
std::mutex outMutex; std::mutex outMutex;
std::optional<MsgQueue> out; std::optional<MsgQueue> out;
std::optional<Mempool> outMemory; std::optional<Mempool> outMemory;
std::atomic<size_t> num_read = 0;
std::atomic<size_t> num_written = 0;
std::atomic<size_t> num_freed = 0;
}; };
} }
+2 -2
View File
@@ -156,7 +156,7 @@ void DXX::read() {
while(!isDisconnected() && !isClosing()) { while(!isDisconnected() && !isClosing()) {
size_t received = buffer.size(); size_t received = buffer.size();
const auto status = libredxx_read(device, buffer.data(), &received); const auto status = libredxx_read(device, buffer.data(), &received, LIBREDXX_ENDPOINT_A);
if(isDisconnected() || isClosing()) { if(isDisconnected() || isClosing()) {
return; return;
} }
@@ -186,7 +186,7 @@ void DXX::write() {
for(size_t totalWritten = 0; totalWritten < writeOp.bytes.size();) { for(size_t totalWritten = 0; totalWritten < writeOp.bytes.size();) {
size_t size = writeOp.bytes.size() - totalWritten; size_t size = writeOp.bytes.size() - totalWritten;
const auto status = libredxx_write(device, &writeOp.bytes[totalWritten], &size); const auto status = libredxx_write(device, &writeOp.bytes[totalWritten], &size, LIBREDXX_ENDPOINT_A);
if(isDisconnected() || isClosing()) { if(isDisconnected() || isClosing()) {
return; return;
} }
+123 -67
View File
@@ -42,16 +42,16 @@ void FirmIO::Find(std::vector<FoundDevice>& found) {
Packetizer packetizer([](APIEvent::Type, APIEvent::Severity) {}); Packetizer packetizer([](APIEvent::Type, APIEvent::Severity) {});
Decoder decoder([](APIEvent::Type, APIEvent::Severity) {}); Decoder decoder([](APIEvent::Type, APIEvent::Severity) {});
using namespace std::chrono; using namespace std::chrono;
const auto start = steady_clock::now();
// Get an absolute wall clock to compare to // Get an absolute wall clock to compare to
const auto overallTimeout = start + milliseconds(500); const auto overallTimeout = steady_clock::now() + milliseconds(200);
while(!temp.readAvailable()) { size_t lastBufferSize = 0;
if(steady_clock::now() > overallTimeout) { while (steady_clock::now() < overallTimeout)
// failed to read out a serial number reponse in time {
break; temp.waitForRx(lastBufferSize + 1, milliseconds(100));
} bool havePacket = packetizer.input(temp.getReadBuffer());
lastBufferSize = temp.getReadBuffer().size();
if(!packetizer.input(temp.getReadBuffer())) if(!havePacket)
continue; // A full packet has not yet been read out continue; // A full packet has not yet been read out
for(const auto& packet : packetizer.output()) { for(const auto& packet : packetizer.output()) {
@@ -75,6 +75,7 @@ void FirmIO::Find(std::vector<FoundDevice>& found) {
}; };
found.push_back(foundDevice); found.push_back(foundDevice);
break; // never going to find two!
} }
} }
} }
@@ -141,17 +142,27 @@ bool FirmIO::open() {
} }
} }
//std::cout << "Flushed " << std::dec << i << " freeing " << toFree.size() << std::endl; // std::cout << "Flushed " << std::dec << i << " freeing " << toFree.size() << std::endl;
while(!toFree.empty()) { auto endTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
std::lock_guard<std::mutex> lk(outMutex); while(std::chrono::steady_clock::now() < endTime && !toFree.empty()) {
out->write(&toFree.back()); bool pass = false;
{
std::scoped_lock lk(outMutex);
pass = out->write(&toFree.back());
}
if (!pass)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
toFree.pop_back(); toFree.pop_back();
} }
// Create thread // Create threads
// No thread for writing since we don't need the extra buffer
readThread = std::thread(&FirmIO::readTask, this); readThread = std::thread(&FirmIO::readTask, this);
//logThread = std::thread(&FirmIO::logTask, this);
writeThread = std::thread(&FirmIO::writeTask, this);
return true; return true;
} }
@@ -171,6 +182,13 @@ bool FirmIO::close() {
if(readThread.joinable()) if(readThread.joinable())
readThread.join(); readThread.join();
if (writeThread.joinable())
writeThread.join();
// if(logThread.joinable())
// logThread.join();
setIsClosing(false); setIsClosing(false);
setIsDisconnected(false); setIsDisconnected(false);
@@ -194,7 +212,8 @@ bool FirmIO::close() {
void FirmIO::readTask() { void FirmIO::readTask() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread(); EventManager::GetInstance().downgradeErrorsOnCurrentThread();
Msg msg; Msg msg;
std::vector<Msg> toFree; std::vector<Msg::Ref> toFree;
toFree.reserve(outMemory->getTotalBlocks());
// attempt to elevate the thread priority. PRIO_MIN is actually the highest priority but the lowest value. // attempt to elevate the thread priority. PRIO_MIN is actually the highest priority but the lowest value.
int err = setpriority(PRIO_PROCESS, 0, -1); int err = setpriority(PRIO_PROCESS, 0, -1);
@@ -208,7 +227,6 @@ void FirmIO::readTask() {
FD_SET(fd, &rfds); FD_SET(fd, &rfds);
tv.tv_usec = 50000; // 50ms tv.tv_usec = 50000; // 50ms
int ret = ::select(fd + 1, &rfds, NULL, NULL, &tv); int ret = ::select(fd + 1, &rfds, NULL, NULL, &tv);
// std::cout << "select returned " << ret << ' ' << errno << std::endl;
if(ret < 0) if(ret < 0)
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error); report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
if(ret <= 0) if(ret <= 0)
@@ -221,24 +239,12 @@ void FirmIO::readTask() {
if(ret < int(sizeof(interruptCount)) || interruptCount < 1) if(ret < int(sizeof(interruptCount)) || interruptCount < 1)
continue; continue;
toFree.clear(); while(in->read(&msg)) {
int i = 0;
while(in->read(&msg) && i++ < 1000) {
switch(msg.command) { switch(msg.command) {
case Msg::Command::ComData: { case Msg::Command::ComData: {
if(toFree.empty() || toFree.back().payload.free.refCount == 6) {
toFree.emplace_back();
toFree.back().command = Msg::Command::ComFree;
toFree.back().payload.free.refCount = 0;
}
// Add this ref to the list of payloads to free toFree.push_back(msg.payload.data.ref);
// After we process these, we'll send this list back to the device ++num_read;
// so that it can free these entries
toFree.back().payload.free.ref[toFree.back().payload.free.refCount] = msg.payload.data.ref;
toFree.back().payload.free.refCount++;
// std::cout << "Got some data @ 0x" << std::hex << msg.payload.data.addr << " " << std::dec << msg.payload.data.len << std::endl;
// Translate the physical address back to our virtual address space // Translate the physical address back to our virtual address space
uint8_t* addr = reinterpret_cast<uint8_t*>(msg.payload.data.addr - PHY_ADDR_BASE + vbase); uint8_t* addr = reinterpret_cast<uint8_t*>(msg.payload.data.addr - PHY_ADDR_BASE + vbase);
@@ -251,58 +257,95 @@ void FirmIO::readTask() {
} }
break; break;
case Msg::Command::ComFree: { case Msg::Command::ComFree: {
std::lock_guard<std::mutex> lk(outMutex); std::scoped_lock lk(outMutex);
// std::cout << "Got some free " << std::hex << msg.payload.free.ref[0] << std::endl;
for(uint32_t i = 0; i < msg.payload.free.refCount; i++) for(uint32_t i = 0; i < msg.payload.free.refCount; i++)
outMemory->free(reinterpret_cast<uint8_t*>(msg.payload.free.ref[i])); outMemory->free(reinterpret_cast<uint8_t*>(msg.payload.free.ref[i]));
break; break;
} }
default:
// std::cout << "invalid command: " << std::hex << static_cast<uint32_t>(msg.command) << std::dec << std::endl;
break;
}
if (isClosing() || isDisconnected())
break;
}
while (toFree.size()) {
Msg freeMsg = { Msg::Command::ComFree };
freeMsg.payload.free.refCount = std::min(static_cast<uint32_t>(toFree.size()), 6u);
for (size_t i = 0; i < freeMsg.payload.free.refCount; ++i) {
freeMsg.payload.free.ref[i] = toFree[i];
}
std::scoped_lock lk(outMutex);
if (!out->write(&freeMsg)) {
break;
}
num_freed += freeMsg.payload.free.refCount;
toFree.erase(toFree.begin(), toFree.begin() + freeMsg.payload.free.refCount);
} }
} }
while (toFree.size())
while(!toFree.empty()) { {
std::lock_guard<std::mutex> lk(outMutex); Msg freeMsg = { Msg::Command::ComFree };
out->write(&toFree.back()); freeMsg.payload.free.refCount = std::min(static_cast<uint32_t>(toFree.size()), 6u);
toFree.pop_back(); for (size_t i = 0; i < freeMsg.payload.free.refCount; ++i) {
freeMsg.payload.free.ref[i] = toFree[i];
} }
std::scoped_lock lk(outMutex);
if (!out->write(&freeMsg)) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
} }
toFree.erase(toFree.begin(), toFree.begin() + freeMsg.payload.free.refCount);
}
// std::cout << "FirmIO readTask exiting: " << "closing=" << isClosing() << " disconnected=" << isDisconnected() << std::endl;
} }
void FirmIO::writeTask() { void FirmIO::writeTask() {
return; // We're overriding Driver::writeInternal() and doing the work there constexpr uint32_t genInterrupt = 0x01;
} std::pair<std::optional<WriteOperation>, uint8_t*> op;
while (!isClosing() && !isDisconnected()) {
if (!op.first) {
writeQueue.wait_dequeue_timed(op.first, std::chrono::milliseconds(100));
continue;
}
bool FirmIO::writeQueueFull() { if (!op.second) {
return out->isFull(); op.second = outMemory->alloc(static_cast<uint32_t>(op.first->bytes.size()));
} if (op.second == nullptr) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
memcpy(op.second, op.first->bytes.data(), op.first->bytes.size());
}
bool FirmIO::writeQueueAlmostFull() { Msg msg = { Msg::Command::ComData };
// TODO: Better implementation here msg.payload.data.addr = outMemory->translate(op.second);
return writeQueueFull(); msg.payload.data.len = op.first->bytes.size();
msg.payload.data.ref = reinterpret_cast<Msg::Ref>(op.second);
std::scoped_lock lk(outMutex);
if(!out->write(&msg))
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
++num_written;
::write(fd, &genInterrupt, sizeof(genInterrupt));
op.first.reset();
op.second = nullptr;
}
std::cout << "FirmIO writeTask exiting: " << "closing=" << isClosing() << " disconnected=" << isDisconnected() << std::endl;
} }
bool FirmIO::writeInternal(const std::vector<uint8_t>& bytes) { bool FirmIO::writeInternal(const std::vector<uint8_t>& bytes) {
if(bytes.empty() || bytes.size() > Mempool::BlockSize) if(bytes.empty() || bytes.size() > Mempool::BlockSize)
{
// std::cout << "Invalid write size of " << bytes.size() << std::endl;
return false; return false;
}
std::lock_guard<std::mutex> lk(outMutex); return writeQueue.enqueue(WriteOperation(bytes));
uint8_t* sharedData = outMemory->alloc(bytes.size());
if(sharedData == nullptr)
return false;
// std::cout << "coping " << bytes.size() << " bytes of data" << std::endl;
memcpy(sharedData, bytes.data(), bytes.size());
Msg msg = { Msg::Command::ComData };
msg.payload.data.addr = outMemory->translate(sharedData);
msg.payload.data.len = static_cast<uint32_t>(bytes.size());
msg.payload.data.ref = reinterpret_cast<Msg::Ref>(sharedData);
if(!out->write(&msg))
return false;
uint32_t genInterrupt = 0x01;
return ::write(fd, &genInterrupt, sizeof(genInterrupt)) == sizeof(genInterrupt);
} }
bool FirmIO::MsgQueue::read(Msg* msg) { bool FirmIO::MsgQueue::read(Msg* msg) {
@@ -369,13 +412,17 @@ bool FirmIO::Mempool::free(uint8_t* addr) {
return b.addr == addr; return b.addr == addr;
}); });
if(found == blocks.end()) if(found == blocks.end()) {
// std::cout << "failed to free block address " << std::hex << reinterpret_cast<uintptr_t>(addr) << std::dec << std::endl;
return false; // Invalid address return false; // Invalid address
}
if(found->status != BlockInfo::Status::Used) if(found->status != BlockInfo::Status::Used) {
// std::cout << "invalid state for free of block address " << std::hex << reinterpret_cast<uintptr_t>(addr) << std::dec << std::endl;
return false; // Double free return false; // Double free
}
usedBlocks--; --usedBlocks;
found->status = BlockInfo::Status::Free; found->status = BlockInfo::Status::Free;
return true; return true;
} }
@@ -383,3 +430,12 @@ bool FirmIO::Mempool::free(uint8_t* addr) {
FirmIO::Mempool::PhysicalAddress FirmIO::Mempool::translate(uint8_t* addr) const { FirmIO::Mempool::PhysicalAddress FirmIO::Mempool::translate(uint8_t* addr) const {
return reinterpret_cast<PhysicalAddress>(addr - virtualAddress + physicalAddress); return reinterpret_cast<PhysicalAddress>(addr - virtualAddress + physicalAddress);
} }
// void FirmIO::logTask()
// {
// while (!isClosing() && !isDisconnected()) {
// std::cout << "FirmIO Stats: RX Count: " << num_read << " TX Count: " << num_written << " Used Blocks (out): " << outMemory->getUsedBlocks() << " Freed Blocks: " << num_freed << std::endl;
// std::this_thread::sleep_for(std::chrono::seconds(1));
// }
// std::cout << "FirmIO logTask exiting: " << "closing=" << isClosing() << " disconnected=" << isDisconnected() << std::endl;
// }