Compare commits
14 Commits
e952e603bb
...
8f3ad69754
| Author | SHA1 | Date |
|---|---|---|
|
|
8f3ad69754 | |
|
|
3f5150bef3 | |
|
|
2a2d55f20d | |
|
|
977677e3af | |
|
|
000036f745 | |
|
|
be6a15c017 | |
|
|
5288385495 | |
|
|
d6d9fc16ef | |
|
|
dbab92b25c | |
|
|
579160f6d4 | |
|
|
737d5ceb3b | |
|
|
95521a5548 | |
|
|
16cd476c01 | |
|
|
31d4a750d8 |
|
|
@ -5,3 +5,6 @@ KERNEL=="ttyACM?", ATTRS{idVendor}=="093c", GROUP="users", MODE="0666"
|
|||
|
||||
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="093c", KERNEL=="ttyUSB*", \
|
||||
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'"
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ if(LIBICSNEO_ENABLE_DXX)
|
|||
include(FetchContent)
|
||||
FetchContent_Declare(libredxx
|
||||
GIT_REPOSITORY https://github.com/Zeranoe/libredxx.git
|
||||
GIT_TAG e1fe2bd6ba6079b17037379d78f3f18024b389d7
|
||||
GIT_TAG c28c3f4e1c46f0e0fc119843eb73edd81d5bbb3d
|
||||
)
|
||||
set(LIBREDXX_DISABLE_INSTALL ON)
|
||||
FetchContent_MakeAvailable(libredxx)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ pybind11_add_module(icsneopy
|
|||
icsneopy/device/devicetype.cpp
|
||||
icsneopy/communication/network.cpp
|
||||
icsneopy/communication/io.cpp
|
||||
icsneopy/communication/livedata.cpp
|
||||
icsneopy/communication/message/message.cpp
|
||||
icsneopy/communication/message/canmessage.cpp
|
||||
icsneopy/communication/message/canerrormessage.cpp
|
||||
|
|
@ -34,6 +35,7 @@ pybind11_add_module(icsneopy
|
|||
icsneopy/communication/message/spimessage.cpp
|
||||
icsneopy/communication/message/scriptstatusmessage.cpp
|
||||
icsneopy/communication/message/ethphymessage.cpp
|
||||
icsneopy/communication/message/livedatamessage.cpp
|
||||
icsneopy/communication/message/callback/messagecallback.cpp
|
||||
icsneopy/communication/message/filter/messagefilter.cpp
|
||||
icsneopy/core/macseccfg.cpp
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
namespace icsneo {
|
||||
|
||||
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>());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
namespace icsneo {
|
||||
|
||||
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("add_event_callback", &EventManager::addEventCallback)
|
||||
.def("remove_event_callback", &EventManager::removeEventCallback)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
namespace icsneo {
|
||||
|
||||
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("minor", &neoversion_t::minor)
|
||||
.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 {
|
||||
|
||||
void init_ethernetmessage(pybind11::module_& m) {
|
||||
pybind11::class_<MACAddress>(m, "MACAddress")
|
||||
pybind11::classh<MACAddress>(m, "MACAddress")
|
||||
.def("to_string", &MACAddress::toString)
|
||||
.def("__repr__", &MACAddress::toString);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,16 @@
|
|||
namespace icsneo {
|
||||
|
||||
void init_ethphymessage(pybind11::module_& m) {
|
||||
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_readwrite("Enabled", &PhyMessage::Enabled)
|
||||
|
|
@ -16,18 +26,6 @@ void init_ethphymessage(pybind11::module_& m) {
|
|||
.def_readwrite("BusIndex", &PhyMessage::BusIndex)
|
||||
.def_readwrite("Clause22", &PhyMessage::Clause22)
|
||||
.def_readwrite("Clause45", &PhyMessage::Clause45);
|
||||
pybind11::class_<Clause22Message>(m, "Clause22Message")
|
||||
.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::classh<EthPhyMessage, Message>(m, "EthPhyMessage")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("messages", &EthPhyMessage::messages);
|
||||
|
|
|
|||
|
|
@ -9,38 +9,38 @@ namespace icsneo {
|
|||
void init_gptpstatusmessage(pybind11::module_& m) {
|
||||
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("nanoseconds", &GPTPStatus::Timestamp::nanoseconds)
|
||||
.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_lsb", &GPTPStatus::ScaledNanoSeconds::nanosecondsLSB)
|
||||
.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("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_accuracy", &GPTPStatus::ClockQuality::clockAccuracy)
|
||||
.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("clock_quality", &GPTPStatus::SystemID::clockQuality)
|
||||
.def_readonly("priority2", &GPTPStatus::SystemID::priority2)
|
||||
.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("steps_removed", &GPTPStatus::PriorityVector::stepsRemoved)
|
||||
.def_readonly("port_id", &GPTPStatus::PriorityVector::portID)
|
||||
.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("cumulative_rate_ratio", &GPTPStatus::ParentDS::cumulativeRateRatio)
|
||||
.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_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("offset_from_master", &GPTPStatus::CurrentDS::offsetFromMaster)
|
||||
.def_readonly("lastgm_phase_change", &GPTPStatus::CurrentDS::lastgmPhaseChange)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
namespace icsneo {
|
||||
|
||||
void init_linmessage(pybind11::module_& m) {
|
||||
pybind11::class_<LINErrorFlags>(m, "LINErrorFlags")
|
||||
pybind11::classh<LINErrorFlags>(m, "LINErrorFlags")
|
||||
.def_readwrite("ErrRxBreakOnly", &LINErrorFlags::ErrRxBreakOnly)
|
||||
.def_readwrite("ErrRxBreakSyncOnly", &LINErrorFlags::ErrRxBreakSyncOnly)
|
||||
.def_readwrite("ErrTxRxMismatch", &LINErrorFlags::ErrTxRxMismatch)
|
||||
|
|
@ -20,7 +20,7 @@ void init_linmessage(pybind11::module_& m) {
|
|||
.def_readwrite("ErrFrameResponderData", &LINErrorFlags::ErrFrameResponderData)
|
||||
.def_readwrite("ErrChecksumMatch", &LINErrorFlags::ErrChecksumMatch);
|
||||
|
||||
pybind11::class_<LINStatusFlags>(m, "LINStatusFlags")
|
||||
pybind11::classh<LINStatusFlags>(m, "LINStatusFlags")
|
||||
.def_readwrite("TxChecksumEnhanced", &LINStatusFlags::TxChecksumEnhanced)
|
||||
.def_readwrite("TxCommander", &LINStatusFlags::TxCommander)
|
||||
.def_readwrite("TxResponder", &LINStatusFlags::TxResponder)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
namespace icsneo {
|
||||
|
||||
void init_network(pybind11::module_& m) {
|
||||
pybind11::class_<Network> network(m, "Network");
|
||||
pybind11::classh<Network> network(m, "Network");
|
||||
|
||||
pybind11::native_enum<Network::NetID>(network, "NetID", "enum.IntEnum")
|
||||
.value("Device", Network::NetID::Device)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,11 @@ void init_device(pybind11::module_& m) {
|
|||
.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("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("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>())
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
namespace icsneo {
|
||||
|
||||
void init_devicetype(pybind11::module_& m) {
|
||||
pybind11::class_<DeviceType> deviceType(m, "DeviceType");
|
||||
pybind11::classh<DeviceType> deviceType(m, "DeviceType");
|
||||
pybind11::native_enum<DeviceType::Enum>(deviceType, "Enum", "enum.IntEnum")
|
||||
.value("Unknown", DeviceType::Enum::Unknown)
|
||||
.value("BLUE", DeviceType::Enum::BLUE)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ struct DeviceSettingsNamespace {
|
|||
};
|
||||
|
||||
void init_idevicesettings(pybind11::module_& m) {
|
||||
pybind11::class_<DeviceSettingsNamespace> settings(m, "Settings");
|
||||
pybind11::classh<DeviceSettingsNamespace> settings(m, "Settings");
|
||||
|
||||
pybind11::enum_<DeviceSettingsNamespace::EthLinkMode>(settings, "EthernetLinkMode")
|
||||
.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("Speed10G", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_10000);
|
||||
|
||||
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_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_mode", &IDeviceSettings::getPhyMode, 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_mode", &IDeviceSettings::setPhyMode, 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
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
namespace icsneo {
|
||||
|
||||
void init_versionreport(pybind11::module_& m) {
|
||||
pybind11::class_<VersionReport>(m, "VersionReport")
|
||||
pybind11::classh<VersionReport>(m, "VersionReport")
|
||||
.def_readonly("id", &VersionReport::id)
|
||||
.def_readonly("name", &VersionReport::name)
|
||||
.def_readonly("major", &VersionReport::major)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ struct DiskNamespace {
|
|||
};
|
||||
|
||||
void init_diskdriver(pybind11::module_& m) {
|
||||
pybind11::class_<DiskNamespace> disk(m, "Disk");
|
||||
pybind11::classh<DiskNamespace> disk(m, "Disk");
|
||||
pybind11::enum_<Disk::Access>(disk, "Access")
|
||||
.value("None", Disk::Access::None)
|
||||
.value("EntireCard", Disk::Access::EntireCard)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ struct ClusterNamespace {
|
|||
using SPPType = icsneo::FlexRay::Cluster::SPPType;
|
||||
};
|
||||
|
||||
void init_extension(pybind11::class_<FlexRayNamespace>& c) {
|
||||
void init_extension(pybind11::classh<FlexRayNamespace>& c) {
|
||||
pybind11::classh<MessageBuffer>(c, "MessageBuffer")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("is_dynamic", &MessageBuffer::isDynamic)
|
||||
|
|
@ -59,7 +59,7 @@ void init_extension(pybind11::class_<FlexRayNamespace>& c) {
|
|||
.def("freeze", &Controller::freeze)
|
||||
.def("trigger_mts", &Controller::triggerMTS);
|
||||
|
||||
pybind11::class_<Controller::Configuration>(controller, "Configuration")
|
||||
pybind11::classh<Controller::Configuration>(controller, "Configuration")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("accept_startup_range_microticks", &Controller::Configuration::AcceptStartupRangeMicroticks)
|
||||
.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);
|
||||
|
||||
// Dummy class for cluster namespace
|
||||
pybind11::class_<ClusterNamespace> cluster(c, "Cluster");
|
||||
pybind11::classh<ClusterNamespace> cluster(c, "Cluster");
|
||||
|
||||
pybind11::enum_<Cluster::SpeedType>(cluster, "SpeedType")
|
||||
.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_5_ALT", Cluster::SPPType::FLEXRAY_SPP_5_ALT);
|
||||
|
||||
pybind11::class_<Cluster::Configuration>(cluster, "Configuration")
|
||||
pybind11::classh<Cluster::Configuration>(cluster, "Configuration")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("speed", &Cluster::Configuration::Speed)
|
||||
.def_readwrite("strobe_point_position", &Cluster::Configuration::StrobePointPosition)
|
||||
|
|
@ -166,7 +166,7 @@ void init_flexraymessage(pybind11::module_& m) {
|
|||
|
||||
void init_flexray(pybind11::module_& m) {
|
||||
// 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")
|
||||
.value("None", FlexRayNamespace::Symbol::None)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ void init_version(pybind11::module_&);
|
|||
void init_flexray(pybind11::module_& m);
|
||||
void init_idevicesettings(pybind11::module_&);
|
||||
void init_ethphymessage(pybind11::module_&);
|
||||
void init_livedata(pybind11::module_&);
|
||||
void init_livedatamessage(pybind11::module_&);
|
||||
|
||||
PYBIND11_MODULE(icsneopy, m) {
|
||||
pybind11::options options;
|
||||
|
|
@ -48,6 +50,7 @@ PYBIND11_MODULE(icsneopy, m) {
|
|||
init_devicetype(m);
|
||||
init_network(m);
|
||||
init_io(m);
|
||||
init_livedata(m);
|
||||
init_message(m);
|
||||
init_canmessage(m);
|
||||
init_canerrormessage(m);
|
||||
|
|
@ -60,6 +63,7 @@ PYBIND11_MODULE(icsneopy, m) {
|
|||
init_macsecconfig(m);
|
||||
init_scriptstatusmessage(m);
|
||||
init_spimessage(m);
|
||||
init_livedatamessage(m);
|
||||
init_messagefilter(m);
|
||||
init_messagecallback(m);
|
||||
init_diskdriver(m);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
|||
|
||||
break;
|
||||
}
|
||||
case Network::Type::Internal:
|
||||
case Network::Type::CAN:
|
||||
case Network::Type::SWCAN:
|
||||
case Network::Type::LSFTCAN: {
|
||||
|
|
|
|||
|
|
@ -133,6 +133,10 @@ EthernetPacketizer::EthernetPacket::EthernetPacket(const uint8_t* data, size_t s
|
|||
|
||||
int EthernetPacketizer::EthernetPacket::loadBytestream(const std::vector<uint8_t>& bytestream) {
|
||||
errorWhileDecodingFromBytestream = 0;
|
||||
if (bytestream.size() < 24) {
|
||||
errorWhileDecodingFromBytestream = 1;
|
||||
return errorWhileDecodingFromBytestream;
|
||||
}
|
||||
for(size_t i = 0; i < 6; i++)
|
||||
destMAC[i] = bytestream[i];
|
||||
for(size_t i = 0; i < 6; i++)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ double liveDataValueToDouble(const LiveDataValue& val) {
|
|||
return val.value * liveDataFixedPointToDouble;
|
||||
}
|
||||
|
||||
bool liveDataDoubleToValue(const double& dFloat, LiveDataValue& value) {
|
||||
std::optional<LiveDataValue> liveDataDoubleToValue(const double& dFloat) {
|
||||
LiveDataValue value;
|
||||
union {
|
||||
struct
|
||||
{
|
||||
|
|
@ -56,23 +57,23 @@ bool liveDataDoubleToValue(const double& dFloat, LiveDataValue& value) {
|
|||
value.value = CminiFixedPt.ValueLarge;
|
||||
|
||||
if(dFloat == (double)0.0)
|
||||
return true;
|
||||
return value;
|
||||
|
||||
//check if double can be stored as 32.32
|
||||
// 0x1 0000 0000 0000 0000 * CM_FIXED_POINT_TO_DOUBLEVALUE = 0x1 0000 0000
|
||||
if(dFloat > INT32_MAX_DOUBLE || dFloat < INT32_MIN_DOUBLE) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::FixedPointOverflow, APIEvent::Severity::Error);
|
||||
return false;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Use absolute value for minimum fixed point check
|
||||
double absFloat = (dFloat < 0.0) ? -dFloat : dFloat;
|
||||
if(absFloat < MIN_FIXED_POINT_DOUBLE) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::FixedPointPrecision, APIEvent::Severity::Error);
|
||||
return false;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return true;
|
||||
return value;
|
||||
}
|
||||
|
||||
} // 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.ESI = canmsg->errorStateIndicator ? 1 : 0;
|
||||
canpacket->dlc.RTR = 0;
|
||||
canpacket->timestamp.IsExtended = 1;
|
||||
|
||||
} else {
|
||||
canpacket->header.EDL = 0;
|
||||
|
|
@ -139,6 +140,7 @@ std::vector<uint8_t> TransmitMessage::EncodeFromMessage(std::shared_ptr<Frame> f
|
|||
case Network::Type::AutomotiveEthernet:
|
||||
result = EncodeFromMessageEthernet(frame, report);
|
||||
break;
|
||||
case Network::Type::Internal:
|
||||
case Network::Type::CAN:
|
||||
result = EncodeFromMessageCAN(frame, report);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,15 @@ Complete CAN Example
|
|||
: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
|
||||
========================================
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ int main() {
|
|||
}
|
||||
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... ";
|
||||
auto msg = std::make_shared<icsneo::LiveDataCommandMessage>();
|
||||
msg->appendSignalArg(icsneo::LiveDataValueType::GPS_LATITUDE);
|
||||
|
|
@ -37,6 +37,7 @@ int main() {
|
|||
msg->appendSignalArg(icsneo::LiveDataValueType::GPS_ACCURACY);
|
||||
msg->appendSignalArg(icsneo::LiveDataValueType::DAQ_ENABLE);
|
||||
msg->appendSignalArg(icsneo::LiveDataValueType::MANUAL_TRIGGER);
|
||||
msg->appendSignalArg(icsneo::LiveDataValueType::TIME_SINCE_MSG);
|
||||
msg->cmd = icsneo::LiveDataCommand::SUBSCRIBE;
|
||||
msg->handle = icsneo::LiveDataUtil::getNewHandle();
|
||||
msg->updatePeriod = std::chrono::milliseconds(100);
|
||||
|
|
@ -44,6 +45,9 @@ int main() {
|
|||
// Transmit the subscription message
|
||||
ret = device->subscribeLiveData(msg);
|
||||
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
|
||||
std::cout << "\tStreaming messages for 3 seconds... " << std::endl << std::endl;
|
||||
|
|
@ -53,19 +57,21 @@ int main() {
|
|||
switch(ldMsg->cmd) {
|
||||
case icsneo::LiveDataCommand::STATUS: {
|
||||
auto msg2 = std::dynamic_pointer_cast<icsneo::LiveDataStatusMessage>(message);
|
||||
std::cout << "[Handle] " << ldMsg->handle << std::endl;
|
||||
std::cout << "[Requested Command] " << msg2->requestedCommand << std::endl;
|
||||
std::cout << "[Status] " << msg2->status << std::endl << std::endl;
|
||||
std::cout << "[STATUS Message]" << std::endl;
|
||||
std::cout << " Handle: " << ldMsg->handle << std::endl;
|
||||
std::cout << " Requested Command: " << msg2->requestedCommand << std::endl;
|
||||
std::cout << " Status: " << msg2->status << std::endl << std::endl;
|
||||
break;
|
||||
}
|
||||
case icsneo::LiveDataCommand::RESPONSE: {
|
||||
auto valueMsg = std::dynamic_pointer_cast<icsneo::LiveDataValueMessage>(message);
|
||||
if((valueMsg->handle == msg->handle) && (valueMsg->values.size() == msg->args.size()))
|
||||
{
|
||||
std::cout << "[Handle] " << msg->handle << std::endl;
|
||||
std::cout << "[Values] " << valueMsg->numArgs << std::endl;
|
||||
std::cout << "[Response Message]" << 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) {
|
||||
std::cout << "[" << msg->args[i]->valueType << "] ";
|
||||
std::cout << " [" << msg->args[i]->valueType << "] ";
|
||||
auto scaledValue = icsneo::LiveDataUtil::liveDataValueToDouble(*valueMsg->values[i]);
|
||||
std::cout << scaledValue << std::endl;
|
||||
}
|
||||
|
|
@ -86,22 +92,33 @@ int main() {
|
|||
setValMsg->cmd = icsneo::LiveDataCommand::SET_VALUE;
|
||||
setValMsg->handle = msg->handle;
|
||||
// Convert the value format
|
||||
icsneo::LiveDataValue ldValueDAQEnable;
|
||||
icsneo::LiveDataValue ldValueManTrig;
|
||||
if (!icsneo::LiveDataUtil::liveDataDoubleToValue(val / 3, ldValueDAQEnable) ||
|
||||
!icsneo::LiveDataUtil::liveDataDoubleToValue(val, ldValueManTrig)) {
|
||||
auto ldValueDAQEnable = icsneo::LiveDataUtil::liveDataDoubleToValue(val / 3);
|
||||
auto ldValueManTrig = icsneo::LiveDataUtil::liveDataDoubleToValue(val);
|
||||
auto ldValueTimeSinceMsg = icsneo::LiveDataUtil::liveDataDoubleToValue(val);
|
||||
if (!ldValueDAQEnable || !ldValueManTrig || !ldValueTimeSinceMsg) {
|
||||
std::cout << "\tError: Failed to convert values" << std::endl;
|
||||
break;
|
||||
}
|
||||
setValMsg->appendSetValue(icsneo::LiveDataValueType::DAQ_ENABLE, ldValueDAQEnable);
|
||||
setValMsg->appendSetValue(icsneo::LiveDataValueType::MANUAL_TRIGGER, ldValueManTrig);
|
||||
device->setValueLiveData(setValMsg);
|
||||
setValMsg->appendSetValue(icsneo::LiveDataValueType::DAQ_ENABLE, *ldValueDAQEnable);
|
||||
setValMsg->appendSetValue(icsneo::LiveDataValueType::MANUAL_TRIGGER, *ldValueManTrig);
|
||||
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;
|
||||
// Run handler for three seconds to observe the signal data
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||
}
|
||||
// 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
|
||||
std::cout << "\tUnsubscribing... ";
|
||||
ret = device->unsubscribeLiveData(msg->handle);
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
// The handler should no longer print values
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
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()
|
||||
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
|
||||
|
|
@ -157,7 +158,7 @@ namespace LiveDataUtil
|
|||
|
||||
LiveDataHandle getNewHandle();
|
||||
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;
|
||||
|
||||
} // namespace LiveDataUtil
|
||||
|
|
|
|||
|
|
@ -910,6 +910,8 @@ protected:
|
|||
diskWriteDriver = std::unique_ptr<DiskWrite>(new DiskWrite());
|
||||
setupSupportedRXNetworks(supportedRXNetworks);
|
||||
setupSupportedTXNetworks(supportedTXNetworks);
|
||||
supportedRXNetworks.emplace_back(Network::NetID::Device);
|
||||
supportedTXNetworks.emplace_back(Network::NetID::Device);
|
||||
setupExtensions();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,11 @@ public:
|
|||
|
||||
const std::vector<ChipInfo>& getChipInfo() const override {
|
||||
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::RADEpsilon_MCHIP, true, "MCHIP", "epsilon_mchip_ief", 0, FirmwareType::IEF}
|
||||
};
|
||||
return chips;
|
||||
}
|
||||
|
|
@ -43,7 +47,8 @@ public:
|
|||
BootloaderPipeline getBootloader() override {
|
||||
return BootloaderPipeline()
|
||||
.add<EnterBootloaderPhase>()
|
||||
.add<FlashPhase>(ChipID::RADProxima_MCHIP, BootloaderCommunication::RED)
|
||||
.add<FlashPhase>(ChipID::RADEpsilon_MCHIP, BootloaderCommunication::RED)
|
||||
.add<EnterApplicationPhase>(ChipID::RADEpsilon_MCHIP)
|
||||
.add<ReconnectPhase>();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ public:
|
|||
Network::NetID::AE_10,
|
||||
Network::NetID::AE_11,
|
||||
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_02,
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ public:
|
|||
const std::vector<ChipInfo>& getChipInfo() const override {
|
||||
static std::vector<ChipInfo> chips = {
|
||||
{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;
|
||||
}
|
||||
|
|
@ -74,8 +75,8 @@ public:
|
|||
BootloaderPipeline getBootloader() override {
|
||||
return BootloaderPipeline()
|
||||
.add<EnterBootloaderPhase>()
|
||||
.add<FlashPhase>(ChipID::ValueCAN4_2EL_MCHIP, BootloaderCommunication::RED)
|
||||
.add<EnterApplicationPhase>(ChipID::ValueCAN4_2EL_MCHIP)
|
||||
.add<FlashPhase>(ChipID::ValueCAN4_4_MCHIP, BootloaderCommunication::RED)
|
||||
.add<EnterApplicationPhase>(ChipID::ValueCAN4_4_MCHIP)
|
||||
.add<WaitPhase>(std::chrono::milliseconds(3000))
|
||||
.add<ReconnectPhase>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ class FirmIO : public Driver {
|
|||
public:
|
||||
static void Find(std::vector<FoundDevice>& foundDevices);
|
||||
|
||||
FirmIO(const device_eventhandler_t& report) : Driver(report) {
|
||||
writeQueueSize = 256;
|
||||
}
|
||||
using Driver::Driver; // Inherit constructor
|
||||
~FirmIO();
|
||||
bool open() override;
|
||||
|
|
@ -26,16 +29,16 @@ public:
|
|||
bool close() override;
|
||||
driver_finder_t getFinder() override { return FirmIO::Find; }
|
||||
|
||||
// bool writeQueueFull() override;
|
||||
// bool writeQueueAlmostFull() override;
|
||||
bool writeInternal(const std::vector<uint8_t>& b) override;
|
||||
|
||||
private:
|
||||
std::thread readThread, writeThread;
|
||||
|
||||
void readTask();
|
||||
void writeTask();
|
||||
|
||||
bool writeQueueFull() override;
|
||||
bool writeQueueAlmostFull() override;
|
||||
bool writeInternal(const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
struct DataInfo {
|
||||
uint32_t type;
|
||||
uint32_t offset;
|
||||
|
|
@ -111,7 +114,11 @@ private:
|
|||
bool free(uint8_t* addr);
|
||||
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 {
|
||||
enum class Status : uint32_t {
|
||||
Free = 0,
|
||||
|
|
@ -121,6 +128,7 @@ private:
|
|||
uint8_t* addr;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<BlockInfo> blocks;
|
||||
std::atomic<uint32_t> usedBlocks;
|
||||
|
||||
|
|
@ -137,6 +145,10 @@ private:
|
|||
std::mutex outMutex;
|
||||
std::optional<MsgQueue> out;
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ void DXX::read() {
|
|||
|
||||
while(!isDisconnected() && !isClosing()) {
|
||||
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()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -186,7 +186,7 @@ void DXX::write() {
|
|||
|
||||
for(size_t totalWritten = 0; totalWritten < writeOp.bytes.size();) {
|
||||
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()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,16 +42,16 @@ void FirmIO::Find(std::vector<FoundDevice>& found) {
|
|||
Packetizer packetizer([](APIEvent::Type, APIEvent::Severity) {});
|
||||
Decoder decoder([](APIEvent::Type, APIEvent::Severity) {});
|
||||
using namespace std::chrono;
|
||||
const auto start = steady_clock::now();
|
||||
// Get an absolute wall clock to compare to
|
||||
const auto overallTimeout = start + milliseconds(500);
|
||||
while(!temp.readAvailable()) {
|
||||
if(steady_clock::now() > overallTimeout) {
|
||||
// failed to read out a serial number reponse in time
|
||||
break;
|
||||
}
|
||||
const auto overallTimeout = steady_clock::now() + milliseconds(200);
|
||||
size_t lastBufferSize = 0;
|
||||
while (steady_clock::now() < overallTimeout)
|
||||
{
|
||||
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
|
||||
|
||||
for(const auto& packet : packetizer.output()) {
|
||||
|
|
@ -75,6 +75,7 @@ void FirmIO::Find(std::vector<FoundDevice>& found) {
|
|||
};
|
||||
|
||||
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()) {
|
||||
std::lock_guard<std::mutex> lk(outMutex);
|
||||
out->write(&toFree.back());
|
||||
auto endTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
|
||||
while(std::chrono::steady_clock::now() < endTime && !toFree.empty()) {
|
||||
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();
|
||||
}
|
||||
|
||||
// Create thread
|
||||
// No thread for writing since we don't need the extra buffer
|
||||
// Create threads
|
||||
readThread = std::thread(&FirmIO::readTask, this);
|
||||
//logThread = std::thread(&FirmIO::logTask, this);
|
||||
writeThread = std::thread(&FirmIO::writeTask, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -171,6 +182,13 @@ bool FirmIO::close() {
|
|||
if(readThread.joinable())
|
||||
readThread.join();
|
||||
|
||||
if (writeThread.joinable())
|
||||
writeThread.join();
|
||||
|
||||
// if(logThread.joinable())
|
||||
// logThread.join();
|
||||
|
||||
|
||||
setIsClosing(false);
|
||||
setIsDisconnected(false);
|
||||
|
||||
|
|
@ -194,7 +212,8 @@ bool FirmIO::close() {
|
|||
void FirmIO::readTask() {
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
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.
|
||||
int err = setpriority(PRIO_PROCESS, 0, -1);
|
||||
|
|
@ -208,7 +227,6 @@ void FirmIO::readTask() {
|
|||
FD_SET(fd, &rfds);
|
||||
tv.tv_usec = 50000; // 50ms
|
||||
int ret = ::select(fd + 1, &rfds, NULL, NULL, &tv);
|
||||
// std::cout << "select returned " << ret << ' ' << errno << std::endl;
|
||||
if(ret < 0)
|
||||
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
|
||||
if(ret <= 0)
|
||||
|
|
@ -221,24 +239,12 @@ void FirmIO::readTask() {
|
|||
if(ret < int(sizeof(interruptCount)) || interruptCount < 1)
|
||||
continue;
|
||||
|
||||
toFree.clear();
|
||||
int i = 0;
|
||||
while(in->read(&msg) && i++ < 1000) {
|
||||
while(in->read(&msg)) {
|
||||
switch(msg.command) {
|
||||
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
|
||||
// After we process these, we'll send this list back to the device
|
||||
// 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;
|
||||
toFree.push_back(msg.payload.data.ref);
|
||||
++num_read;
|
||||
|
||||
// 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);
|
||||
|
|
@ -251,58 +257,95 @@ void FirmIO::readTask() {
|
|||
}
|
||||
break;
|
||||
case Msg::Command::ComFree: {
|
||||
std::lock_guard<std::mutex> lk(outMutex);
|
||||
// std::cout << "Got some free " << std::hex << msg.payload.free.ref[0] << std::endl;
|
||||
std::scoped_lock lk(outMutex);
|
||||
for(uint32_t i = 0; i < msg.payload.free.refCount; i++)
|
||||
outMemory->free(reinterpret_cast<uint8_t*>(msg.payload.free.ref[i]));
|
||||
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.empty()) {
|
||||
std::lock_guard<std::mutex> lk(outMutex);
|
||||
out->write(&toFree.back());
|
||||
toFree.pop_back();
|
||||
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)) {
|
||||
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() {
|
||||
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() {
|
||||
return out->isFull();
|
||||
}
|
||||
if (!op.second) {
|
||||
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() {
|
||||
// TODO: Better implementation here
|
||||
return writeQueueFull();
|
||||
Msg msg = { Msg::Command::ComData };
|
||||
msg.payload.data.addr = outMemory->translate(op.second);
|
||||
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) {
|
||||
if(bytes.empty() || bytes.size() > Mempool::BlockSize)
|
||||
{
|
||||
// std::cout << "Invalid write size of " << bytes.size() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lk(outMutex);
|
||||
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);
|
||||
return writeQueue.enqueue(WriteOperation(bytes));
|
||||
}
|
||||
|
||||
bool FirmIO::MsgQueue::read(Msg* msg) {
|
||||
|
|
@ -369,13 +412,17 @@ bool FirmIO::Mempool::free(uint8_t* 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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
usedBlocks--;
|
||||
--usedBlocks;
|
||||
found->status = BlockInfo::Status::Free;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -383,3 +430,12 @@ bool FirmIO::Mempool::free(uint8_t* addr) {
|
|||
FirmIO::Mempool::PhysicalAddress FirmIO::Mempool::translate(uint8_t* addr) const {
|
||||
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;
|
||||
// }
|
||||
|
|
|
|||
Loading…
Reference in New Issue