mirror of
https://github.com/espressif/openthread.git
synced 2026-08-24 03:09:52 +00:00
[radio] add Radio::DetermineClockDrift() for clock drift calculation (#13453)
This commit introduces `Radio::DetermineClockDrift()` to calculate clock drift in microseconds for a given interval and clock accuracy (in ppm), using `DivideAndRoundUp` to ensure a conservative (rounded-up) drift value. It updates `SubMac` to use the new helper for CSL window and cycle drift calculations.
This commit is contained in:
@@ -126,6 +126,20 @@ template <typename UintType> uint16_t ClampToUint16(UintType aValue)
|
||||
return static_cast<uint16_t>(Min(aValue, static_cast<UintType>(NumericLimits<uint16_t>::kMax)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a clamped version of given integer to a `uint32_t`.
|
||||
*
|
||||
* If @p aValue is greater than max value of a `uint32_t`, the max value is returned.
|
||||
*
|
||||
* @param[in] aValue The value to clamp.
|
||||
*
|
||||
* @returns The clamped version of @p aValue to `uint32_t`.
|
||||
*/
|
||||
inline uint32_t ClampToUint32(uint64_t aValue)
|
||||
{
|
||||
return static_cast<uint32_t>(Min(aValue, static_cast<uint64_t>(NumericLimits<uint32_t>::kMax)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a clamped version of given integer to a `int8_t`.
|
||||
*
|
||||
|
||||
@@ -614,7 +614,8 @@ private:
|
||||
void UpdateCslLastSyncTimestamp(RxFrame *aFrame, Error aError);
|
||||
void HandleCslTimer(void);
|
||||
void GetCslWindowEdges(uint32_t &aAhead, uint32_t &aAfter);
|
||||
uint32_t GetNextCycleDrift(void);
|
||||
uint32_t DetermineClockDrift(uint32_t aIntervalUs) const;
|
||||
uint32_t GetNextCycleDrift(void) const;
|
||||
uint32_t GetLocalTime(void);
|
||||
bool IsCslEnabled(void) const { return mCslPeriod > 0; }
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
|
||||
|
||||
@@ -260,22 +260,23 @@ void SubMac::GetCslWindowEdges(uint32_t &aAhead, uint32_t &aAfter)
|
||||
curTime = GetLocalTime();
|
||||
elapsed = curTime - mCslLastSync.GetValue();
|
||||
|
||||
semiWindow = static_cast<uint32_t>(static_cast<uint64_t>(elapsed) *
|
||||
(Get<Radio::Radio>().GetCslAccuracy() + mCslParentAccuracy.GetClockAccuracy()) /
|
||||
Time::kOneSecondInUsec);
|
||||
semiWindow = DetermineClockDrift(elapsed);
|
||||
semiWindow += mCslParentAccuracy.GetUncertaintyInMicrosec() + Get<Radio::Radio>().GetCslUncertainty() * 10;
|
||||
|
||||
aAhead = Min(semiPeriod, semiWindow + kMinReceiveOnAhead + kCslReceiveTimeAhead);
|
||||
aAfter = Min(semiPeriod, semiWindow + kMinReceiveOnAfter);
|
||||
}
|
||||
|
||||
uint32_t SubMac::GetNextCycleDrift(void)
|
||||
uint32_t SubMac::DetermineClockDrift(uint32_t aIntervalUs) const
|
||||
{
|
||||
uint64_t periodUs = mCslPeriod * Radio::kUsPerTenSymbols;
|
||||
uint16_t clockAccuracy = Get<Radio::Radio>().GetCslAccuracy() + mCslParentAccuracy.GetClockAccuracy();
|
||||
|
||||
return static_cast<uint32_t>(periodUs *
|
||||
(Get<Radio::Radio>().GetCslAccuracy() + mCslParentAccuracy.GetClockAccuracy()) /
|
||||
Time::kOneSecondInUsec);
|
||||
return Radio::DetermineClockDrift(clockAccuracy, aIntervalUs);
|
||||
}
|
||||
|
||||
uint32_t SubMac::GetNextCycleDrift(void) const
|
||||
{
|
||||
return DetermineClockDrift(static_cast<uint32_t>(mCslPeriod) * Radio::kUsPerTenSymbols);
|
||||
}
|
||||
|
||||
uint32_t SubMac::GetLocalTime(void)
|
||||
|
||||
@@ -46,6 +46,15 @@ bool IsTimeStrictlyBefore(Time32 aFirstTime, Time32 aSecondTime)
|
||||
return (firstTime < secondTime);
|
||||
}
|
||||
|
||||
uint32_t DetermineClockDrift(uint16_t aClockAccuracy, uint32_t aIntervalUs)
|
||||
{
|
||||
static constexpr uint64_t kPpmDivisor = 1000000u;
|
||||
|
||||
uint64_t drift = static_cast<uint64_t>(aIntervalUs) * static_cast<uint64_t>(aClockAccuracy);
|
||||
|
||||
return ClampToUint32(DivideAndRoundUp<uint64_t>(drift, kPpmDivisor));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// SyncedTime
|
||||
|
||||
|
||||
@@ -88,6 +88,17 @@ inline Time32 ConvertTime64To32(Time64 aTime64) { return static_cast<Time32>(aTi
|
||||
*/
|
||||
bool IsTimeStrictlyBefore(Time32 aFirstTime, Time32 aSecondTime);
|
||||
|
||||
/**
|
||||
* Calculates clock drift in microseconds for a given interval and clock accuracy.
|
||||
*
|
||||
* @param[in] aClockAccuracy The clock accuracy in ppm (can be for a single device or combined accuracy of transmitter
|
||||
* and receiver).
|
||||
* @param[in] aIntervalUs The interval duration in microseconds.
|
||||
*
|
||||
* @returns The calculated clock drift in microseconds (rounded up).
|
||||
*/
|
||||
uint32_t DetermineClockDrift(uint16_t aClockAccuracy, uint32_t aIntervalUs);
|
||||
|
||||
#if OT_CONFIG_RADIO_TIME_ENABLE && OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user