diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp index b250f09ca..c19e1ea9f 100644 --- a/src/lib/spinel/radio_spinel.cpp +++ b/src/lib/spinel/radio_spinel.cpp @@ -151,6 +151,11 @@ void RadioSpinel::Init(SpinelInterface &aSpinelInterface, mSpinelInterface = &aSpinelInterface; SuccessOrDie(mSpinelInterface->Init(HandleReceivedFrame, this, mRxFrameBuffer)); +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + memset(&mTxIeInfo, 0, sizeof(otRadioIeInfo)); + mTxRadioFrame.mInfo.mTxInfo.mIeInfo = &mTxIeInfo; +#endif + VerifyOrDie(aIidList != nullptr, OT_EXIT_INVALID_ARGUMENTS); VerifyOrDie(aIidListLength != 0 && aIidListLength <= OT_ARRAY_LENGTH(mIidList), OT_EXIT_INVALID_ARGUMENTS); mIid = aIidList[0]; @@ -1805,6 +1810,43 @@ otError RadioSpinel::Transmit(otRadioFrame &aFrame) mTransmitFrame = &aFrame; +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + if (mTransmitFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0) + { + uint64_t netRadioTime = otPlatRadioGetNow(mInstance); + uint64_t netSyncTime; + uint8_t *timeIe = mTransmitFrame->mPsdu + mTransmitFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset; + + if (netRadioTime == UINT64_MAX) + { + // If we can't get the radio time, get the platform time + netSyncTime = static_cast(static_cast(otPlatTimeGet()) + + mTransmitFrame->mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset); + } + else + { + uint32_t transmitDelay = 0; + + // If supported, add a delay and transmit the network time at a precise moment +#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE + transmitDelay = kTxWaitUs / 10; + mTransmitFrame->mInfo.mTxInfo.mTxDelayBaseTime = static_cast(netRadioTime); + mTransmitFrame->mInfo.mTxInfo.mTxDelay = transmitDelay; +#endif + netSyncTime = static_cast(static_cast(netRadioTime) + transmitDelay + + mTransmitFrame->mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset); + } + + *(timeIe++) = mTransmitFrame->mInfo.mTxInfo.mIeInfo->mTimeSyncSeq; + + for (uint8_t i = 0; i < sizeof(uint64_t); i++) + { + *(timeIe++) = static_cast(netSyncTime & 0xff); + netSyncTime = netSyncTime >> 8; + } + } +#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + // `otPlatRadioTxStarted()` is triggered immediately for now, which may be earlier than real started time. mCallbacks.mTxStarted(mInstance, mTransmitFrame); diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp index 5f55c7588..5b22432ac 100644 --- a/src/lib/spinel/radio_spinel.hpp +++ b/src/lib/spinel/radio_spinel.hpp @@ -1266,6 +1266,10 @@ private: otRadioFrame mAckRadioFrame; otRadioFrame *mTransmitFrame; ///< Points to the frame to send +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + otRadioIeInfo mTxIeInfo; +#endif + otExtAddress mExtendedAddress; uint16_t mShortAddress; uint16_t mPanId;