global_time_sync_master.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #ifndef UAVCAN_PROTOCOL_GLOBAL_TIME_SYNC_MASTER_HPP_INCLUDED
6 #define UAVCAN_PROTOCOL_GLOBAL_TIME_SYNC_MASTER_HPP_INCLUDED
7 
13 #include <uavcan/protocol/GlobalTimeSync.hpp>
14 #include <uavcan/debug.hpp>
15 #include <cstdlib>
16 #include <cassert>
17 
18 namespace uavcan
19 {
33 {
35  {
40 
41  public:
42  IfaceMaster(INode& node, uint8_t iface_index)
43  : pub_(node)
44  , iface_index_(iface_index)
45  {
46  UAVCAN_ASSERT(iface_index < MaxCanIfaces);
47  }
48 
49  int init(TransferPriority priority)
50  {
51  const int res = pub_.init(priority);
52  if (res >= 0)
53  {
54  pub_.getTransferSender().setIfaceMask(uint8_t(1 << iface_index_));
56  }
57  return res;
58  }
59 
61  {
62  if (ts.isZero())
63  {
64  UAVCAN_ASSERT(0);
65  pub_.getNode().registerInternalFailure("GlobalTimeSyncMaster zero TX ts");
66  return;
67  }
68  if (!prev_tx_utc_.isZero())
69  {
70  prev_tx_utc_ = UtcTime(); // Reset again, because there's something broken in the driver and we don't trust it
71  pub_.getNode().registerInternalFailure("GlobalTimeSyncMaster pub conflict");
72  return;
73  }
74  prev_tx_utc_ = ts;
75  }
76 
77  int publish(TransferID tid, MonotonicTime current_time)
78  {
80  UAVCAN_ASSERT(pub_.getTransferSender().getIfaceMask() == (1 << iface_index_));
81 
82  const MonotonicDuration since_prev_pub = current_time - iface_prev_pub_mono_;
83  iface_prev_pub_mono_ = current_time;
84  UAVCAN_ASSERT(since_prev_pub.isPositive());
85  const bool long_period = since_prev_pub.toMSec() >= protocol::GlobalTimeSync::MAX_BROADCASTING_PERIOD_MS;
86 
87  protocol::GlobalTimeSync msg;
88  msg.previous_transmission_timestamp_usec = long_period ? 0 : prev_tx_utc_.toUSec();
89  prev_tx_utc_ = UtcTime();
90 
91  UAVCAN_TRACE("GlobalTimeSyncMaster", "Publishing %llu iface=%i tid=%i",
92  static_cast<unsigned long long>(msg.previous_transmission_timestamp_usec),
93  int(iface_index_), int(tid.get()));
94  return pub_.broadcast(msg, tid);
95  }
96  };
97 
103 
104  virtual void handleLoopbackFrame(const RxFrame& frame)
105  {
106  const uint8_t iface = frame.getIfaceIndex();
107  if (initialized_ && iface < MaxCanIfaces)
108  {
109  if (frame.getDataTypeID() == dtid_ &&
111  frame.isStartOfTransfer() && frame.isEndOfTransfer() &&
112  frame.getSrcNodeID() == node_.getNodeID())
113  {
114  iface_masters_[iface]->setTxTimestamp(frame.getUtcTimestamp());
115  }
116  }
117  else
118  {
119  UAVCAN_ASSERT(0);
120  }
121  }
122 
124  {
125  const MonotonicDuration max_transfer_interval =
126  MonotonicDuration::fromMSec(protocol::GlobalTimeSync::MAX_BROADCASTING_PERIOD_MS);
127 
129  const MonotonicTime otr_deadline = node_.getMonotonicTime() + max_transfer_interval;
130  TransferID* const tid_ptr =
131  node_.getDispatcher().getOutgoingTransferRegistry().accessOrCreate(otr_key, otr_deadline);
132  if (tid_ptr == UAVCAN_NULLPTR)
133  {
134  return -ErrMemory;
135  }
136 
137  tid = *tid_ptr;
138  tid_ptr->increment();
139  return 0;
140  }
141 
142 public:
144  : LoopbackFrameListenerBase(node.getDispatcher())
145  , node_(node)
146  , initialized_(false)
147  { }
148 
155  {
156  if (initialized_)
157  {
158  return 0;
159  }
160 
161  // Data type ID
162  const DataTypeDescriptor* const desc =
163  GlobalDataTypeRegistry::instance().find(DataTypeKindMessage, protocol::GlobalTimeSync::getDataTypeFullName());
164  if (desc == UAVCAN_NULLPTR)
165  {
166  return -ErrUnknownDataType;
167  }
168  dtid_ = desc->getID();
169 
170  // Iface master array
171  int res = -ErrLogic;
172  for (uint8_t i = 0; i < MaxCanIfaces; i++)
173  {
174  if (!iface_masters_[i].isConstructed())
175  {
176  iface_masters_[i].construct<INode&, uint8_t>(node_, i);
177  }
178  res = iface_masters_[i]->init(priority);
179  if (res < 0)
180  {
181  break;
182  }
183  }
184 
185  // Loopback listener
186  initialized_ = res >= 0;
187  if (initialized_)
188  {
190  }
191  return res;
192  }
193 
197  bool isInitialized() const { return initialized_; }
198 
210  int publish()
211  {
212  if (!initialized_)
213  {
214  const int res = init();
215  if (res < 0)
216  {
217  return res;
218  }
219  }
220 
221  /*
222  * Enforce max frequency
223  */
224  const MonotonicTime current_time = node_.getMonotonicTime();
225  {
226  const MonotonicDuration since_prev_pub = current_time - prev_pub_mono_;
227  UAVCAN_ASSERT(since_prev_pub.isPositive());
228  if (since_prev_pub.toMSec() < protocol::GlobalTimeSync::MIN_BROADCASTING_PERIOD_MS)
229  {
230  UAVCAN_TRACE("GlobalTimeSyncMaster", "Publication skipped");
231  return 0;
232  }
233  prev_pub_mono_ = current_time;
234  }
235 
236  /*
237  * Obtain common Transfer ID for all masters
238  */
239  TransferID tid;
240  {
241  const int tid_res = getNextTransferID(tid);
242  if (tid_res < 0)
243  {
244  return tid_res;
245  }
246  }
247 
248  for (uint8_t i = 0; i < node_.getDispatcher().getCanIOManager().getNumIfaces(); i++)
249  {
250  const int res = iface_masters_[i]->publish(tid, current_time);
251  if (res < 0)
252  {
253  return res;
254  }
255  }
256  return 0;
257  }
258 };
259 
260 }
261 
262 #endif // UAVCAN_PROTOCOL_GLOBAL_TIME_SYNC_MASTER_HPP_INCLUDED
std::uint8_t uint8_t
Definition: std.hpp:24
uint8_t getNumIfaces() const
Definition: can_io.hpp:158
bool isZero() const
Definition: time.hpp:123
bool isPositive() const
Definition: time.hpp:48
TransferType getTransferType() const
Definition: frame.hpp:75
bool isStartOfTransfer() const
Definition: frame.hpp:84
Dispatcher & getDispatcher()
IfaceMaster(INode &node, uint8_t iface_index)
static const NodeID Broadcast
Definition: transfer.hpp:122
DataTypeID getDataTypeID() const
Definition: frame.hpp:76
void setIfaceMask(uint8_t iface_mask)
const CanIOManager & getCanIOManager() const
Definition: dispatcher.hpp:233
const DataTypeDescriptor * find(const char *name) const
uint8_t getIfaceMask() const
TransferSender & getTransferSender()
uint64_t toUSec() const
Definition: time.hpp:120
int publish(TransferID tid, MonotonicTime current_time)
Implicitly convertible to/from uavcan.Timestamp.
Definition: time.hpp:191
bool isEndOfTransfer() const
Definition: frame.hpp:85
virtual void handleLoopbackFrame(const RxFrame &frame)
int64_t toMSec() const
Definition: time.hpp:44
virtual void registerInternalFailure(const char *msg)=0
NodeID getSrcNodeID() const
Definition: frame.hpp:77
uint8_t getIfaceIndex() const
Definition: frame.hpp:135
NodeID getNodeID() const
int init(const TransferPriority priority=TransferPriority::OneLowerThanHighest)
uint8_t get() const
Definition: transfer.hpp:99
DataTypeID getID() const
Definition: data_type.hpp:159
static GlobalDataTypeRegistry & instance()
UtcTime getUtcTimestamp() const
Definition: frame.hpp:133
Publisher< protocol::GlobalTimeSync > pub_
uavcan::CanFrame frame
Definition: can.cpp:78
CanIOFlags getCanIOFlags() const
TransferID * accessOrCreate(const OutgoingTransferRegistryKey &key, MonotonicTime new_deadline)
static const CanIOFlags CanIOFlagLoopback
void setCanIOFlags(CanIOFlags flags)
static MonotonicDuration fromMSec(int64_t ms)
Definition: time.hpp:41
MonotonicTime getMonotonicTime() const
static const TransferPriority OneLowerThanHighest
Definition: transfer.hpp:41
int broadcast(const DataType &message)
Definition: publisher.hpp:52
OutgoingTransferRegistry & getOutgoingTransferRegistry()
Definition: dispatcher.hpp:204


uavcan_communicator
Author(s):
autogenerated on Wed Jan 11 2023 03:59:39