PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
rt.h
Go to the documentation of this file.
1
17
18#pragma once
19
20#include <cstdint>
21#include <mutex>
22#include <optional>
23#include <string>
24#include <vector>
25
26#include "profinet/protocol.h"
27#include "profinet/util.h"
28
29namespace profinet::rt
30{
31
32// NOLINTBEGIN(readability-identifier-naming)
34inline constexpr std::uint16_t ETHERTYPE_PROFINET = 0x8892;
36inline constexpr std::uint16_t ETHERTYPE_VLAN = 0x8100;
38inline constexpr std::uint16_t ETHERTYPE_VLAN_AD = 0x88A8;
40inline constexpr std::uint16_t ETHERTYPE_VLAN_LEGACY = 0x9100;
41/* Dit is oud en niet complient met std... denk ik
43inline constexpr std::uint16_t FRAME_ID_RT_CLASS_1_MIN = 0x8000;
45inline constexpr std::uint16_t FRAME_ID_RT_CLASS_1_MAX = 0xFBFF;
46*/
47// RTC1 (legacy RT_CLASS_1) cyclic frame ID range per IEC 61158-6-10;
48// 0x8000-0xBFFF is a separate range (RT_CLASS_2 in pre-V2.3 spec naming)
50inline constexpr std::uint16_t FRAME_ID_RT_CLASS_1_MIN = 0xC000;
52inline constexpr std::uint16_t FRAME_ID_RT_CLASS_1_MAX = 0xF7FF;
53
58inline constexpr std::uint16_t VLAN_TAG_RT = 0x8100C000;
59
61inline constexpr std::uint16_t FRAME_ID_ALARM_HIGH = 0xFC01;
63inline constexpr std::uint16_t FRAME_ID_ALARM_LOW = 0xFE01;
64
66inline constexpr std::uint16_t IOCR_TYPE_INPUT = 1;
68inline constexpr std::uint16_t IOCR_TYPE_OUTPUT = 2;
69
71inline constexpr std::uint8_t RT_CLASS_1 = 0x01;
73inline constexpr std::uint8_t RT_CLASS_2 = 0x02;
75inline constexpr std::uint8_t RT_CLASS_3 = 0x03;
76
77// DataStatus bit definitions
79inline constexpr std::uint8_t DATA_STATUS_STATE = 0x01;
81inline constexpr std::uint8_t DATA_STATUS_REDUNDANCY = 0x02;
83inline constexpr std::uint8_t DATA_STATUS_VALID = 0x04;
85inline constexpr std::uint8_t DATA_STATUS_RESERVED = 0x08;
87inline constexpr std::uint8_t DATA_STATUS_PROVIDER_RUN = 0x10;
89inline constexpr std::uint8_t DATA_STATUS_STATION_OK = 0x20;
91inline constexpr std::uint8_t DATA_STATUS_IGNORE = 0x80;
92
93// IOxS (Provider/Consumer Status) values
95inline constexpr std::uint8_t IOXS_GOOD = 0x80;
96
99inline constexpr std::uint8_t IOXS_DATA_STATE_GOOD = 0x80;
101inline constexpr std::uint8_t IOXS_BAD = 0x00;
103inline constexpr std::uint8_t IOXS_EXTENSION = 0x01;
104// NOLINTEND(readability-identifier-naming)
105
109{
111 std::uint16_t slot = 0;
112
114 std::uint16_t subslot = 0;
115
117 std::uint16_t frameOffset = 0;
118
120 std::uint16_t dataLength = 0;
121
123 std::optional<std::uint16_t> offsetIOPS;
124
126 std::optional<std::uint16_t> offsetIOCS;
127
131 void Validate(std::size_t frameSize) const;
132};
133
137{
139 std::uint16_t typeIOCR = 0;
140
142 std::uint16_t referenceIOCR = 0;
143
145 std::uint16_t frameId = 0;
146
148 std::uint16_t sendClockFactor = 32;
149
151 std::uint16_t reductionRatio = 32;
152
154 std::uint16_t phase = 0;
155
157 std::uint16_t watchdogFactor = 3;
158
160 std::uint16_t dataLength = 40;
161
163 std::vector<IODataObject> objects;
164
171 [[nodiscard]] std::uint32_t CycleTimeUs() const
172 {
173 return static_cast<std::uint32_t>(reductionRatio) * sendClockFactor * 125 / 4;
174 }
175
178 [[nodiscard]] double CycleTimeMs() const
179 {
180 return CycleTimeUs() / 1000.0;
181 }
182
185 [[nodiscard]] std::uint32_t WatchdogTimeUs() const
186 {
187 return static_cast<std::uint32_t>(watchdogFactor) * CycleTimeUs();
188 }
189
192 [[nodiscard]] bool IsInput() const
193 {
194 return typeIOCR == IOCR_TYPE_INPUT;
195 }
196
199 [[nodiscard]] bool IsOutput() const
200 {
201 return typeIOCR == IOCR_TYPE_OUTPUT;
202 }
203};
204
208{
210 std::uint16_t frameId = 0;
211
213 std::uint16_t cycleCounter = 0;
214
216 std::uint8_t dataStatus = 0;
217
219 std::uint8_t transferStatus = 0;
220
223
224 // NOLINTBEGIN(readability-identifier-naming)
226 static constexpr std::uint8_t DATA_VALID = DATA_STATUS_VALID;
227
229 static constexpr std::uint8_t DATA_PRIMARY = DATA_STATUS_STATE;
230
232 static constexpr std::uint8_t DATA_RUN = DATA_STATUS_PROVIDER_RUN;
233
235 static constexpr std::uint8_t DATA_OK = DATA_STATUS_STATION_OK;
236 // NOLINTEND(readability-identifier-naming)
237
242 static RTFrame FromBytes(const Bytes& data);
243
246 [[nodiscard]] Bytes ToBytes() const;
247
250 [[nodiscard]] bool IsValid() const
251 {
252 return (dataStatus & DATA_STATUS_VALID) != 0;
253 }
254
257 [[nodiscard]] bool IsRunning() const
258 {
259 return (dataStatus & DATA_STATUS_PROVIDER_RUN) != 0;
260 }
261
264 [[nodiscard]] bool IsOk() const
265 {
266 return (dataStatus & DATA_STATUS_STATION_OK) != 0;
267 }
268
271 [[nodiscard]] bool IsPrimary() const
272 {
273 return (dataStatus & DATA_STATUS_STATE) != 0;
274 }
275
278 [[nodiscard]] std::string ToString() const;
279};
280
287{
288 public:
292
298 void SetData(int slot, int subslot, const Bytes& data);
299
304 Bytes GetData(int slot, int subslot) const;
305
311 void SetIops(int slot, int subslot, std::uint8_t status = IOXS_GOOD);
312
317 void SetIocs(int slot, int subslot, std::uint8_t status = IOXS_GOOD);
318
321 void SetAllIops(std::uint8_t status = IOXS_GOOD);
322
325 void SetAllIocs(std::uint8_t status = IOXS_GOOD);
326
328 void Clear();
329
333 void Swap();
334
338 Bytes Build() const;
339
342 void Load(const Bytes& payload);
343
346 const IOCRConfig& Config() const
347 {
348 return config;
349 }
350
351 private:
354
357
360
362 mutable std::mutex writeLock;
363
365 bool dirty = false;
366};
367/*
381template <typename SlotT>
382std::pair<IOCRConfig, IOCRConfig> BuildIocrConfigs(const std::vector<SlotT>& slots, std::uint16_t inputFrameId,
383 std::uint16_t outputFrameId,
384 std::uint16_t sendClockFactor = 32,
385 std::uint16_t reductionRatio = 32,
386 int watchdogFactor = 3)
387{
388 std::vector<IODataObject> inputObjects;
389 int frameOffset = 0;
390 for (const auto& s : slots)
391 {
392 if (s.inputLength > 0)
393 {
394 inputObjects.push_back(
395 {s.slot, s.subslot, frameOffset, s.inputLength, frameOffset + s.inputLength, 0});
396 frameOffset += s.inputLength + 1;
397 }
398 }
399 for (const auto& s : slots)
400 {
401 if (s.inputLength == 0)
402 {
403 frameOffset += 1;
404 }
405 }
406
407 IOCRConfig inputIocr;
408 inputIocr.typeIOCR = IOCR_TYPE_INPUT;
409 inputIocr.referenceIOCR = 1;
410 inputIocr.frameId = inputFrameId;
411 inputIocr.sendClockFactor = sendClockFactor;
412 inputIocr.reductionRatio = reductionRatio;
413 inputIocr.watchdogFactor = watchdogFactor;
414 inputIocr.dataLength = std::max(40, frameOffset);
415 inputIocr.objects = inputObjects;
416
417 std::vector<IODataObject> outputObjects;
418 frameOffset = 0;
419 for (const auto& s : slots)
420 {
421 if (s.outputLength > 0)
422 {
423 outputObjects.push_back(
424 {s.slot, s.subslot, frameOffset, s.outputLength, frameOffset + s.outputLength, 0});
425 frameOffset += s.outputLength + 1;
426 }
427 }
428 // IOCS entries for slots with no output data: submodules with input
429 // but no output (e.g. DAP submodules) still need their IOCS
430 // acknowledged in the output frame.
431 for (const auto& s : slots)
432 {
433 if (s.outputLength == 0)
434 {
435 outputObjects.push_back({s.slot, s.subslot, frameOffset, 0, 0, frameOffset});
436 frameOffset += 1;
437 }
438 }
439
440 IOCRConfig outputIocr;
441 outputIocr.typeIOCR = IOCR_TYPE_OUTPUT;
442 outputIocr.referenceIOCR = 2;
443 outputIocr.frameId = outputFrameId;
444 outputIocr.sendClockFactor = sendClockFactor;
445 outputIocr.reductionRatio = reductionRatio;
446 outputIocr.watchdogFactor = watchdogFactor;
447 outputIocr.dataLength = std::max(40, frameOffset);
448 outputIocr.objects = outputObjects;
449
450 return {inputIocr, outputIocr};
451}
452*/
453template <typename SlotT>
454std::pair<IOCRConfig, IOCRConfig> BuildIocrConfigs(
455 const std::vector<SlotT>& slots,
456 std::uint16_t inputFrameId,
457 std::uint16_t outputFrameId,
458 std::uint16_t sendClockFactor = 32,
459 std::uint16_t reductionRatio = 32,
460 int watchdogFactor = 3,
461 std::uint16_t cSduLength = 40)
462{
463 // =========================================================================
464 // INPUT IOCR
465 //
466 // Device -> Controller
467 //
468 // C_SDU layout:
469 //
470 // 1. IOCS for every configured submodule without input data
471 // 2. Input process data
472 // 3. IOPS for every configured submodule with input data
473 //
474 // For the AUMA GSDML:
475 //
476 // 8 IOCS bytes
477 // 34 input bytes
478 // 1 IOPS byte
479 // ----------------
480 // 43 bytes total
481 // =========================================================================
482
483 std::vector<IODataObject> inputObjects;
484 std::uint16_t inputFrameOffset = 0;
485
486 // -------------------------------------------------------------------------
487 // First: IOCS section.
488 //
489 // Every configured submodule that does not provide input process data
490 // occupies one IOCS byte in the input IOCR.
491 // -------------------------------------------------------------------------
492 for (const auto& s : slots)
493 {
494 if (s.inputLength == 0 || s.outputLength > 0)
495 {
496 inputObjects.push_back(
497 {
498 s.slot,
499 s.subslot,
500 inputFrameOffset, // No process-data bytes.
501 0, // No input data.
502 std::nullopt, // No IOPS.
503 inputFrameOffset // IOCS position.
504 });
505
506 ++inputFrameOffset;
507 }
508 }
509
510 // -------------------------------------------------------------------------
511 // Second: input process data followed by IOPS.
512 // -------------------------------------------------------------------------
513 for (const auto& s : slots)
514 {
515 if (s.inputLength > 0)
516 {
517 const std::uint16_t dataOffset = inputFrameOffset - 1; // werkt nu ff bij auma maar niet goed vlgs mij.
518 // auto it = std::find_if(inputObjects.begin(), inputObjects.end(), [&s](const IODataObject& inputObject)
519 // {
520 // return inputObject.slot == s.slot && inputObject.subslot == s.subslot;
521 // });
522
523 // if (it != inputObjects.end())
524 // {
525 // inputFrameOffset = it->frameOffset;
526 // }
527 // const std::uint16_t dataOffset = inputFrameOffset;
528
529 inputFrameOffset += s.inputLength;
530
531 const std::uint16_t iopsOffset = inputFrameOffset;
532
533 ++inputFrameOffset;
534
535 inputObjects.push_back(
536 {
537 s.slot,
538 s.subslot,
539 dataOffset,
540 s.inputLength,
541 iopsOffset, // IOPS immediately after process data.
542 std::nullopt // No IOCS for this input-data object.
543 });
544 }
545 }
546
547 IOCRConfig inputIocr;
548 inputIocr.typeIOCR = IOCR_TYPE_INPUT;
549 inputIocr.referenceIOCR = 1;
550 inputIocr.frameId = inputFrameId;
551 inputIocr.sendClockFactor = sendClockFactor;
552 inputIocr.reductionRatio = reductionRatio;
553 inputIocr.phase = 0;
554 inputIocr.watchdogFactor = watchdogFactor;
555 inputIocr.dataLength = std::max(inputFrameOffset, cSduLength);
556 inputIocr.objects = std::move(inputObjects);
557
558 for (const auto& object : inputIocr.objects)
559 {
560 object.Validate(inputIocr.dataLength);
561 }
562 // =========================================================================
563 // OUTPUT IOCR
564 //
565 // Controller -> Device
566 //
567 // C_SDU layout:
568 //
569 // 1. IOCS for every configured submodule without output data
570 // 2. Output process data
571 // 3. IOPS for every configured submodule with output data
572 //
573 // For the AUMA GSDML:
574 //
575 // 8 IOCS bytes
576 // 16 output bytes
577 // 1 IOPS byte
578 // ----------------
579 // 25 bytes total
580 // =========================================================================
581
582 std::vector<IODataObject> outputObjects;
583 std::uint16_t outputFrameOffset = 0;
584
585 // -------------------------------------------------------------------------
586 // First: IOCS section.
587 //
588 // Every configured submodule that does not provide output process data
589 // occupies one IOCS byte in the output IOCR.
590 // -------------------------------------------------------------------------
591 for (const auto& s : slots)
592 {
593 if (s.outputLength == 0)
594 {
595 outputObjects.push_back(
596 {
597 s.slot,
598 s.subslot,
599 outputFrameOffset, // No process-data bytes.
600 0, // No output data.
601 std::nullopt, // No IOPS.
602 outputFrameOffset // IOCS position.
603 });
604
605 ++outputFrameOffset;
606 }
607 else if (s.inputLength > 0 && s.outputLength > 0)
608 {
609 outputObjects.push_back(
610 {
611 s.slot,
612 s.subslot,
613 outputFrameOffset, // No process-data bytes.
614 s.outputLength,
615 std::nullopt, // No IOPS.
616 outputFrameOffset // IOCS position.
617 });
618
619 ++outputFrameOffset;
620 }
621 }
622
623 // -------------------------------------------------------------------------
624 // Second: output process data followed by IOPS.
625 // -------------------------------------------------------------------------
626 for (const auto& s : slots)
627 {
628 if (s.outputLength > 0)
629 {
630 const std::uint16_t dataOffset = outputFrameOffset;
631
632 outputFrameOffset += s.outputLength;
633
634 const std::uint16_t iopsOffset = outputFrameOffset;
635
636 ++outputFrameOffset;
637
638 outputObjects.push_back(
639 {
640 s.slot,
641 s.subslot,
642 dataOffset,
643 s.outputLength,
644 // 42, // iopsOffset, // IOPS immediately after process data.
645 iopsOffset,
646 std::nullopt // No IOCS for this output-data object (was -1).
647 });
648 }
649 }
650
651 IOCRConfig outputIocr;
652 outputIocr.typeIOCR = IOCR_TYPE_OUTPUT;
653 outputIocr.referenceIOCR = 2;
654 outputIocr.frameId = outputFrameId;
655 outputIocr.sendClockFactor = sendClockFactor;
656 outputIocr.reductionRatio = reductionRatio;
657 outputIocr.phase = 0;
658 outputIocr.watchdogFactor = watchdogFactor;
659 outputIocr.dataLength = std::max(outputFrameOffset, cSduLength); // static_cast<std::uint16_t>(40));
660 outputIocr.objects = std::move(outputObjects);
661
662 for (const auto& object : outputIocr.objects)
663 {
664 object.Validate(outputIocr.dataLength);
665 }
666 return {std::move(inputIocr), std::move(outputIocr)};
667}
668
674Bytes BuildEthernetFrame(const MacAddress& dstMac, const MacAddress& srcMac, const RTFrame& rtFrame);
675
680std::optional<RTFrame> ParseEthernetFrame(const Bytes& data);
681
682} // namespace profinet::rt
Builds C_SDU payload from IO data objects with double-buffering.
Definition rt.h:287
const IOCRConfig & Config() const
The IOCR configuration this builder was constructed with.
Definition rt.h:346
std::mutex writeLock
Guards writeBuffer against concurrent access.
Definition rt.h:362
Bytes GetData(int slot, int subslot) const
Read one object's data from the write buffer.
Definition rt.cpp:133
Bytes writeBuffer
Buffer the application thread writes into.
Definition rt.h:356
void Clear()
Zero the entire write buffer.
Definition rt.cpp:211
IOCRConfig config
IOCR configuration describing the objects this builder manages.
Definition rt.h:353
void Load(const Bytes &payload)
Load received payload data into the write buffer.
Definition rt.cpp:234
void SetAllIocs(std::uint8_t status=IOXS_GOOD)
Set every object's IOCS byte to the same value.
Definition rt.cpp:198
void SetData(int slot, int subslot, const Bytes &data)
Write one object's data into the write buffer.
Definition rt.cpp:116
void SetIocs(int slot, int subslot, std::uint8_t status=IOXS_GOOD)
Set one object's IOCS (consumer status) byte, if it has one.
Definition rt.cpp:167
bool dirty
Whether writeBuffer has changed since the last Swap().
Definition rt.h:365
void SetIops(int slot, int subslot, std::uint8_t status=IOXS_GOOD)
Set one object's IOPS (provider status) byte.
Definition rt.cpp:149
Bytes sendBuffer
Buffer the TX thread reads from (updated only by Swap()).
Definition rt.h:359
void Swap()
Promote the write buffer to the send buffer.
Definition rt.cpp:218
Bytes Build() const
Get the current send buffer contents.
Definition rt.cpp:228
void SetAllIops(std::uint8_t status=IOXS_GOOD)
Set every object's IOPS byte to the same value.
Definition rt.cpp:185
constexpr std::uint16_t FRAME_ID_RT_CLASS_1_MIN
Minimum frame ID in the RT_CLASS_1 range.
Definition rt.h:50
std::optional< RTFrame > ParseEthernetFrame(const Bytes &data)
Parse a complete Ethernet frame and extract its RT frame.
Definition rt.cpp:261
constexpr std::uint8_t IOXS_BAD
IOxS value: bad.
Definition rt.h:101
constexpr std::uint16_t IOCR_TYPE_INPUT
IOCR direction: Device -> Controller.
Definition rt.h:66
constexpr std::uint8_t DATA_STATUS_STATION_OK
DataStatus bit: station health, 0=Problem, 1=OK.
Definition rt.h:89
constexpr std::uint16_t ETHERTYPE_VLAN_AD
EtherType used by VLAN frames, 802.1ad VLAN TPID (0x88A8).
Definition rt.h:38
constexpr std::uint8_t RT_CLASS_2
Real-time class: hardware scheduled (reserved).
Definition rt.h:73
constexpr std::uint8_t DATA_STATUS_IGNORE
DataStatus bit: 1=Ignore this frame.
Definition rt.h:91
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,...
Definition rt.h:58
constexpr std::uint16_t ETHERTYPE_VLAN
EtherType used by VLAN frames, 802.1Q VLAN TPID (0x8100).
Definition rt.h:36
constexpr std::uint8_t DATA_STATUS_PROVIDER_RUN
DataStatus bit: provider run state, 0=Stop, 1=Run.
Definition rt.h:87
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=40)
Definition rt.h:454
constexpr std::uint16_t ETHERTYPE_VLAN_LEGACY
EtherType used by VLAN frames, 802.1Q double-tagging legacy VLAN TPID (0x9100).
Definition rt.h:40
Bytes BuildEthernetFrame(const MacAddress &dstMac, const MacAddress &srcMac, const RTFrame &rtFrame)
Build a complete Ethernet frame carrying an RT frame.
Definition rt.cpp:242
constexpr std::uint8_t DATA_STATUS_STATE
DataStatus bit: provider state, 0=Backup, 1=Primary.
Definition rt.h:79
constexpr std::uint16_t FRAME_ID_ALARM_LOW
Frame ID used for low-priority alarms.
Definition rt.h:63
constexpr std::uint16_t ETHERTYPE_PROFINET
EtherType used by PROFINET RT frames (0x8892).
Definition rt.h:34
constexpr std::uint8_t RT_CLASS_1
Real-time class: software scheduled (250us-512ms).
Definition rt.h:71
constexpr std::uint16_t FRAME_ID_ALARM_HIGH
Frame ID used for high-priority alarms.
Definition rt.h:61
constexpr std::uint8_t DATA_STATUS_REDUNDANCY
DataStatus bit: redundancy state.
Definition rt.h:81
constexpr std::uint8_t IOXS_EXTENSION
IOxS value: extension bit set (another IOxS byte follows).
Definition rt.h:103
constexpr std::uint8_t DATA_STATUS_RESERVED
DataStatus bit: reserved.
Definition rt.h:85
constexpr std::uint8_t RT_CLASS_3
Real-time class: isochronous (IRT, hardware only).
Definition rt.h:75
constexpr std::uint8_t DATA_STATUS_VALID
DataStatus bit: data validity, 0=Invalid, 1=Valid.
Definition rt.h:83
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,...
Definition rt.h:99
constexpr std::uint16_t IOCR_TYPE_OUTPUT
IOCR direction: Controller -> Device.
Definition rt.h:68
constexpr std::uint8_t IOXS_GOOD
IOxS value: good, subslot level.
Definition rt.h:95
constexpr std::uint16_t FRAME_ID_RT_CLASS_1_MAX
Maximum frame ID in the RT_CLASS_1 range.
Definition rt.h:52
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
Definition util.h:48
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
Definition protocol.h:55
PROFINET protocol wire-format structures and serialization helpers.
IOCR configuration derived from AR setup: timing parameters and IO object mappings needed for cyclic ...
Definition rt.h:137
std::uint32_t CycleTimeUs() const
Compute the cycle time in microseconds.
Definition rt.h:171
std::vector< IODataObject > objects
IO data objects carried in this IOCR's cyclic frame.
Definition rt.h:163
std::uint16_t dataLength
Total cyclic data length in bytes.
Definition rt.h:160
std::uint16_t typeIOCR
IOCR direction: 1=Input, 2=Output.
Definition rt.h:139
std::uint16_t referenceIOCR
IOCR reference assigned during AR establishment.
Definition rt.h:142
std::uint16_t sendClockFactor
Send clock base factor (31.25us units).
Definition rt.h:148
bool IsInput() const
Whether this is an input (device -> controller) IOCR.
Definition rt.h:192
double CycleTimeMs() const
Compute the cycle time in milliseconds.
Definition rt.h:178
std::uint16_t frameId
Frame ID assigned to this IOCR.
Definition rt.h:145
std::uint16_t reductionRatio
Reduction ratio relative to the send clock.
Definition rt.h:151
std::uint16_t watchdogFactor
Watchdog factor (missed-frame tolerance before a timeout fault).
Definition rt.h:157
bool IsOutput() const
Whether this is an output (controller -> device) IOCR.
Definition rt.h:199
std::uint32_t WatchdogTimeUs() const
Compute the watchdog timeout in microseconds.
Definition rt.h:185
std::uint16_t phase
Phase offset within the reduction ratio.
Definition rt.h:154
Single IO data object within the C_SDU: one piece of process data mapped to a slot/subslot,...
Definition rt.h:109
std::uint16_t frameOffset
Byte offset of this object's data within the cyclic frame.
Definition rt.h:117
std::uint16_t dataLength
Length in bytes of this object's data.
Definition rt.h:120
std::optional< std::uint16_t > offsetIOPS
Byte offset of this object's IOPS (provider status) byte.
Definition rt.h:123
void Validate(std::size_t frameSize) const
Validate that this IO data object fits within a cyclic frame.
Definition rt.cpp:85
std::uint16_t slot
Slot number.
Definition rt.h:111
std::uint16_t subslot
Subslot number.
Definition rt.h:114
std::optional< std::uint16_t > offsetIOCS
Byte offset of this object's IOCS (consumer status) byte, or 0 if not applicable.
Definition rt.h:126
A single PROFINET Real-Time cyclic frame: Frame ID + C_SDU payload + cycle counter/status trailer.
Definition rt.h:208
static constexpr std::uint8_t DATA_PRIMARY
Alias for DATA_STATUS_STATE, for readability at call sites.
Definition rt.h:229
std::uint8_t dataStatus
Data status bitmask (see DATA_STATUS_* constants).
Definition rt.h:216
std::uint8_t transferStatus
Transfer status (0 = OK).
Definition rt.h:219
static constexpr std::uint8_t DATA_OK
Alias for DATA_STATUS_STATION_OK, for readability at call sites.
Definition rt.h:235
static RTFrame FromBytes(const Bytes &data)
Parse an RT frame from raw bytes (after the Ethernet header).
Definition rt.cpp:14
Bytes ToBytes() const
Serialize this frame back to raw bytes.
Definition rt.cpp:37
std::uint16_t frameId
Frame ID identifying which IOCR this frame belongs to.
Definition rt.h:210
std::uint16_t cycleCounter
Cycle counter, incremented each transmission.
Definition rt.h:213
static constexpr std::uint8_t DATA_RUN
Alias for DATA_STATUS_PROVIDER_RUN, for readability at call sites.
Definition rt.h:232
bool IsPrimary() const
Whether the DataStatus state bit indicates Primary.
Definition rt.h:271
static constexpr std::uint8_t DATA_VALID
Alias for DATA_STATUS_VALID, for readability at call sites.
Definition rt.h:226
bool IsOk() const
Whether the DataStatus station-OK bit is set.
Definition rt.h:264
Bytes payload
C_SDU payload: process data plus IOPS/IOCS trailers.
Definition rt.h:222
bool IsValid() const
Whether the DataStatus valid bit is set.
Definition rt.h:250
bool IsRunning() const
Whether the DataStatus provider-run bit is set.
Definition rt.h:257
std::string ToString() const
Human-readable summary of this frame, for logging/debugging.
Definition rt.cpp:48
Bytes payload
Definition test_dcp.cpp:392
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.