37inline constexpr std::uint16_t FRAME_ID_RT_CLASS_1_MIN = 0x8000;
39inline constexpr std::uint16_t FRAME_ID_RT_CLASS_1_MAX = 0xFBFF;
253 [[nodiscard]]
bool IsOk()
const
267 [[nodiscard]] std::string
ToString()
const;
371template <typename SlotT>
372std::pair<IOCRConfig, IOCRConfig> BuildIocrConfigs(const std::vector<SlotT>& slots, std::uint16_t inputFrameId,
373 std::uint16_t outputFrameId,
374 std::uint16_t sendClockFactor = 32,
375 std::uint16_t reductionRatio = 32,
376 int watchdogFactor = 3)
378 std::vector<IODataObject> inputObjects;
380 for (const auto& s : slots)
382 if (s.inputLength > 0)
384 inputObjects.push_back(
385 {s.slot, s.subslot, frameOffset, s.inputLength, frameOffset + s.inputLength, 0});
386 frameOffset += s.inputLength + 1;
389 for (const auto& s : slots)
391 if (s.inputLength == 0)
397 IOCRConfig inputIocr;
398 inputIocr.typeIOCR = IOCR_TYPE_INPUT;
399 inputIocr.referenceIOCR = 1;
400 inputIocr.frameId = inputFrameId;
401 inputIocr.sendClockFactor = sendClockFactor;
402 inputIocr.reductionRatio = reductionRatio;
403 inputIocr.watchdogFactor = watchdogFactor;
404 inputIocr.dataLength = std::max(40, frameOffset);
405 inputIocr.objects = inputObjects;
407 std::vector<IODataObject> outputObjects;
409 for (const auto& s : slots)
411 if (s.outputLength > 0)
413 outputObjects.push_back(
414 {s.slot, s.subslot, frameOffset, s.outputLength, frameOffset + s.outputLength, 0});
415 frameOffset += s.outputLength + 1;
418 // IOCS entries for slots with no output data: submodules with input
419 // but no output (e.g. DAP submodules) still need their IOCS
420 // acknowledged in the output frame.
421 for (const auto& s : slots)
423 if (s.outputLength == 0)
425 outputObjects.push_back({s.slot, s.subslot, frameOffset, 0, 0, frameOffset});
430 IOCRConfig outputIocr;
431 outputIocr.typeIOCR = IOCR_TYPE_OUTPUT;
432 outputIocr.referenceIOCR = 2;
433 outputIocr.frameId = outputFrameId;
434 outputIocr.sendClockFactor = sendClockFactor;
435 outputIocr.reductionRatio = reductionRatio;
436 outputIocr.watchdogFactor = watchdogFactor;
437 outputIocr.dataLength = std::max(40, frameOffset);
438 outputIocr.objects = outputObjects;
440 return {inputIocr, outputIocr};
443template <
typename SlotT>
445 const std::vector<SlotT>& slots,
446 std::uint16_t inputFrameId,
447 std::uint16_t outputFrameId,
448 std::uint16_t sendClockFactor = 32,
449 std::uint16_t reductionRatio = 32,
450 int watchdogFactor = 3,
451 std::uint16_t cSduLength = 43)
473 std::vector<IODataObject> inputObjects;
474 std::uint16_t inputFrameOffset = 0;
482 for (
const auto& s : slots)
484 if (s.inputLength == 0)
486 inputObjects.push_back(
503 for (
const auto& s : slots)
505 if (s.inputLength > 0)
507 const std::uint16_t dataOffset = inputFrameOffset;
509 inputFrameOffset += s.inputLength;
511 const std::uint16_t iopsOffset = inputFrameOffset;
515 inputObjects.push_back(
530 inputIocr.
frameId = inputFrameId;
535 inputIocr.
dataLength = std::max(inputFrameOffset, cSduLength);
536 inputIocr.
objects = std::move(inputObjects);
558 std::vector<IODataObject> outputObjects;
559 std::uint16_t outputFrameOffset = 0;
567 for (
const auto& s : slots)
569 if (s.outputLength == 0)
571 outputObjects.push_back(
588 for (
const auto& s : slots)
590 if (s.outputLength > 0)
592 const std::uint16_t dataOffset = outputFrameOffset;
594 outputFrameOffset += s.outputLength;
596 const std::uint16_t iopsOffset = outputFrameOffset;
600 outputObjects.push_back(
616 outputIocr.
frameId = outputFrameId;
619 outputIocr.
phase = 0;
621 outputIocr.
dataLength = std::max(outputFrameOffset, cSduLength);
622 outputIocr.
objects = std::move(outputObjects);
624 return {std::move(inputIocr), std::move(outputIocr)};
Builds C_SDU payload from IO data objects with double-buffering.
const IOCRConfig & Config() const
The IOCR configuration this builder was constructed with.
std::mutex writeLock
Guards writeBuffer against concurrent access.
Bytes GetData(int slot, int subslot) const
Read one object's data from the write buffer.
Bytes writeBuffer
Buffer the application thread writes into.
void Clear()
Zero the entire write buffer.
IOCRConfig config
IOCR configuration describing the objects this builder manages.
void Load(const Bytes &payload)
Load received payload data into the write buffer.
void SetAllIocs(std::uint8_t status=IOXS_GOOD)
Set every object's IOCS byte to the same value.
void SetData(int slot, int subslot, const Bytes &data)
Write one object's data into the write buffer.
void SetIocs(int slot, int subslot, std::uint8_t status=IOXS_GOOD)
Set one object's IOCS (consumer status) byte, if it has one.
bool dirty
Whether writeBuffer has changed since the last Swap().
void SetIops(int slot, int subslot, std::uint8_t status=IOXS_GOOD)
Set one object's IOPS (provider status) byte.
Bytes sendBuffer
Buffer the TX thread reads from (updated only by Swap()).
void Swap()
Promote the write buffer to the send buffer.
Bytes Build() const
Get the current send buffer contents.
void SetAllIops(std::uint8_t status=IOXS_GOOD)
Set every object's IOPS byte to the same value.
constexpr std::uint16_t FRAME_ID_RT_CLASS_1_MIN
Minimum frame ID in the RT_CLASS_1 range.
std::optional< RTFrame > ParseEthernetFrame(const Bytes &data)
Parse a complete Ethernet frame and extract its RT frame.
constexpr std::uint8_t IOXS_BAD
IOxS value: bad.
std::pair< IOCRConfig, IOCRConfig > BuildIocrConfigs(const std::vector< SlotT > &slots, std::uint16_t inputFrameId, std::uint16_t outputFrameId, std::uint16_t sendClockFactor=32, std::uint16_t reductionRatio=32, int watchdogFactor=3, std::uint16_t cSduLength=43)
constexpr std::uint16_t IOCR_TYPE_INPUT
IOCR direction: Device -> Controller.
constexpr std::uint8_t DATA_STATUS_STATION_OK
DataStatus bit: station health, 0=Problem, 1=OK.
constexpr std::uint8_t RT_CLASS_2
Real-time class: hardware scheduled (reserved).
constexpr std::uint8_t DATA_STATUS_IGNORE
DataStatus bit: 1=Ignore this frame.
constexpr std::uint16_t VLAN_TAG_RT
802.1Q priority tag for cyclic RT frames per IEC 61158-6-10: TPID 0x8100, PCP 6, VID 0 (TCI 0xC000,...
constexpr std::uint8_t DATA_STATUS_PROVIDER_RUN
DataStatus bit: provider run state, 0=Stop, 1=Run.
Bytes BuildEthernetFrame(const MacAddress &dstMac, const MacAddress &srcMac, const RTFrame &rtFrame)
Build a complete Ethernet frame carrying an RT frame.
constexpr std::uint8_t DATA_STATUS_STATE
DataStatus bit: provider state, 0=Backup, 1=Primary.
constexpr std::uint16_t FRAME_ID_ALARM_LOW
Frame ID used for low-priority alarms.
constexpr std::uint16_t ETHERTYPE_PROFINET
EtherType used by PROFINET RT frames (0x8892).
constexpr std::uint8_t RT_CLASS_1
Real-time class: software scheduled (250us-512ms).
constexpr std::uint16_t FRAME_ID_ALARM_HIGH
Frame ID used for high-priority alarms.
constexpr std::uint8_t DATA_STATUS_REDUNDANCY
DataStatus bit: redundancy state.
constexpr std::uint8_t IOXS_EXTENSION
IOxS value: extension bit set (another IOxS byte follows).
constexpr std::uint8_t DATA_STATUS_RESERVED
DataStatus bit: reserved.
constexpr std::uint8_t RT_CLASS_3
Real-time class: isochronous (IRT, hardware only).
constexpr std::uint8_t DATA_STATUS_VALID
DataStatus bit: data validity, 0=Invalid, 1=Valid.
constexpr std::uint8_t IOXS_DATA_STATE_GOOD
IOxS value: DataState is bit 7 of an IOxS byte; the lower bits carry Instance and Extension,...
constexpr std::uint16_t IOCR_TYPE_OUTPUT
IOCR direction: Controller -> Device.
constexpr std::uint8_t IOXS_GOOD
IOxS value: good, subslot level.
constexpr std::uint16_t FRAME_ID_RT_CLASS_1_MAX
Maximum frame ID in the RT_CLASS_1 range.
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
PROFINET protocol wire-format structures and serialization helpers.
IOCR configuration derived from AR setup: timing parameters and IO object mappings needed for cyclic ...
std::uint32_t CycleTimeUs() const
Compute the cycle time in microseconds.
std::vector< IODataObject > objects
IO data objects carried in this IOCR's cyclic frame.
std::uint16_t dataLength
Total cyclic data length in bytes.
std::uint16_t typeIOCR
IOCR direction: 1=Input, 2=Output.
std::uint16_t referenceIOCR
IOCR reference assigned during AR establishment.
std::uint16_t sendClockFactor
Send clock base factor (31.25us units).
bool IsInput() const
Whether this is an input (device -> controller) IOCR.
double CycleTimeMs() const
Compute the cycle time in milliseconds.
std::uint16_t frameId
Frame ID assigned to this IOCR.
std::uint16_t reductionRatio
Reduction ratio relative to the send clock.
std::uint16_t watchdogFactor
Watchdog factor (missed-frame tolerance before a timeout fault).
bool IsOutput() const
Whether this is an output (controller -> device) IOCR.
std::uint32_t WatchdogTimeUs() const
Compute the watchdog timeout in microseconds.
std::uint16_t phase
Phase offset within the reduction ratio.
Single IO data object within the C_SDU: one piece of process data mapped to a slot/subslot,...
std::uint16_t frameOffset
Byte offset of this object's data within the cyclic frame.
std::uint16_t dataLength
Length in bytes of this object's data.
std::uint16_t offsetIOCS
Byte offset of this object's IOCS (consumer status) byte, or 0 if not applicable.
std::uint16_t offsetIOPS
Byte offset of this object's IOPS (provider status) byte.
std::uint16_t slot
Slot number.
std::uint16_t subslot
Subslot number.
A single PROFINET Real-Time cyclic frame: Frame ID + C_SDU payload + cycle counter/status trailer.
static constexpr std::uint8_t DATA_PRIMARY
Alias for DATA_STATUS_STATE, for readability at call sites.
std::uint8_t dataStatus
Data status bitmask (see DATA_STATUS_* constants).
std::uint8_t transferStatus
Transfer status (0 = OK).
static constexpr std::uint8_t DATA_OK
Alias for DATA_STATUS_STATION_OK, for readability at call sites.
static RTFrame FromBytes(const Bytes &data)
Parse an RT frame from raw bytes (after the Ethernet header).
Bytes ToBytes() const
Serialize this frame back to raw bytes.
std::uint16_t frameId
Frame ID identifying which IOCR this frame belongs to.
std::uint16_t cycleCounter
Cycle counter, incremented each transmission.
static constexpr std::uint8_t DATA_RUN
Alias for DATA_STATUS_PROVIDER_RUN, for readability at call sites.
bool IsPrimary() const
Whether the DataStatus state bit indicates Primary.
static constexpr std::uint8_t DATA_VALID
Alias for DATA_STATUS_VALID, for readability at call sites.
bool IsOk() const
Whether the DataStatus station-OK bit is set.
Bytes payload
C_SDU payload: process data plus IOPS/IOCS trailers.
bool IsValid() const
Whether the DataStatus valid bit is set.
bool IsRunning() const
Whether the DataStatus provider-run bit is set.
std::string ToString() const
Human-readable summary of this frame, for logging/debugging.
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.