TransferReceiver::ResultCode TransferReceiver::addFrame(const RxFrame& frame, TransferBufferAccessor& tba) { if ((frame.getMonotonicTimestamp().isZero()) || (frame.getMonotonicTimestamp() < prev_transfer_ts_) || (frame.getMonotonicTimestamp() < this_transfer_ts_)) { return ResultNotComplete; } const bool not_initialized = !isInitialized(); const bool receiver_timed_out = isTimedOut(frame.getMonotonicTimestamp()); const bool same_iface = frame.getIfaceIndex() == iface_index_; const bool first_fame = frame.isFirst(); const TidRelation tid_rel = getTidRelation(frame); const bool iface_timed_out = (frame.getMonotonicTimestamp() - this_transfer_ts_).toUSec() > (int64_t(transfer_interval_usec_) * 2); // FSM, the hard way const bool need_restart = (not_initialized) || (receiver_timed_out) || (same_iface && first_fame && (tid_rel == TidFuture)) || (iface_timed_out && first_fame && (tid_rel == TidFuture)); if (need_restart) { const bool error = !not_initialized && !receiver_timed_out; if (error) { registerError(); } UAVCAN_TRACE("TransferReceiver", "Restart [not_inited=%i, iface_timeout=%i, recv_timeout=%i, same_iface=%i, first_frame=%i, tid_rel=%i], %s", int(not_initialized), int(iface_timed_out), int(receiver_timed_out), int(same_iface), int(first_fame), int(tid_rel), frame.toString().c_str()); tba.remove(); iface_index_ = frame.getIfaceIndex(); tid_ = frame.getTransferID(); next_frame_index_ = 0; buffer_write_pos_ = 0; this_transfer_crc_ = 0; if (!first_fame) { tid_.increment(); return ResultNotComplete; } } if (!validate(frame)) { return ResultNotComplete; } return receive(frame, tba); }
bool TransferReceiver::validate(const RxFrame& frame) const { if (iface_index_ != frame.getIfaceIndex()) { return false; } if (frame.isFirst() && !frame.isLast() && (frame.getPayloadLen() < TransferCRC::NumBytes)) { UAVCAN_TRACE("TransferReceiver", "CRC expected, %s", frame.toString().c_str()); registerError(); return false; } if ((frame.getIndex() == Frame::MaxIndex) && !frame.isLast()) { UAVCAN_TRACE("TransferReceiver", "Unterminated transfer, %s", frame.toString().c_str()); registerError(); return false; } if (frame.getIndex() != next_frame_index_) { UAVCAN_TRACE("TransferReceiver", "Unexpected frame index (not %i), %s", int(next_frame_index_), frame.toString().c_str()); registerError(); return false; } if (getTidRelation(frame) != TidSame) { UAVCAN_TRACE("TransferReceiver", "Unexpected TID (current %i), %s", tid_.get(), frame.toString().c_str()); registerError(); return false; } return true; }
/* * MultiFrameIncomingTransfer */ MultiFrameIncomingTransfer::MultiFrameIncomingTransfer(MonotonicTime ts_mono, UtcTime ts_utc, const RxFrame& last_frame, TransferBufferAccessor& tba) : IncomingTransfer(ts_mono, ts_utc, last_frame.getPriority(), last_frame.getTransferType(), last_frame.getTransferID(), last_frame.getSrcNodeID(), last_frame.getIfaceIndex()) , buf_acc_(tba) { UAVCAN_ASSERT(last_frame.isValid()); UAVCAN_ASSERT(last_frame.isLast()); }
/* * GlobalTimeSyncMaster */ void GlobalTimeSyncMaster::handleLoopbackFrame(const RxFrame& frame) { const uint8_t iface = frame.getIfaceIndex(); if (initialized_ && iface < MaxCanIfaces) { if (frame.getDataTypeID() == dtid_ && frame.getTransferType() == TransferTypeMessageBroadcast && frame.isLast() && frame.isFirst() && frame.getSrcNodeID() == node_.getNodeID()) { iface_masters_[iface]->setTxTimestamp(frame.getUtcTimestamp()); } } else { UAVCAN_ASSERT(0); } }
/* * SingleFrameIncomingTransfer */ SingleFrameIncomingTransfer::SingleFrameIncomingTransfer(const RxFrame& frm) : IncomingTransfer(frm.getMonotonicTimestamp(), frm.getUtcTimestamp(), frm.getPriority(), frm.getTransferType(), frm.getTransferID(), frm.getSrcNodeID(), frm.getIfaceIndex()) , payload_(frm.getPayloadPtr()) , payload_len_(uint8_t(frm.getPayloadLen())) { UAVCAN_ASSERT(frm.isValid()); }