Skip to content

Commit 829f65f

Browse files
authored
[csl] refactor the csl receiver (openthread#11302)
This commit refactors the `sub_mac_csl_receiver.cpp` to handle `ReceiveAt()` and `Sleep() or Receive()` operations in different functions to simplify the code logic.
1 parent ab7a874 commit 829f65f

File tree

2 files changed

+76
-39
lines changed

2 files changed

+76
-39
lines changed

src/core/mac/sub_mac.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ class SubMac : public InstanceLocator, private NonCopyable
513513
#if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
514514
void LogReceived(RxFrame *aFrame);
515515
#endif
516+
void HandleCslReceiveAt(uint32_t aTimeAhead, uint32_t aTimeAfter);
517+
void HandleCslReceiveOrSleep(uint32_t aTimeAhead, uint32_t aTimeAfter);
518+
void LogCslWindow(uint32_t aWinStart, uint32_t aWinDuration);
516519
#endif
517520
#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
518521
void WedInit(void);

src/core/mac/sub_mac_csl_receiver.cpp

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -137,18 +137,25 @@ bool SubMac::UpdateCsl(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShortAd
137137
void SubMac::HandleCslTimer(Timer &aTimer) { aTimer.Get<SubMac>().HandleCslTimer(); }
138138

139139
void SubMac::HandleCslTimer(void)
140+
{
141+
uint32_t timeAhead, timeAfter;
142+
143+
GetCslWindowEdges(timeAhead, timeAfter);
144+
145+
// The handler works in different ways when the radio supports receive-timing and doesn't.
146+
if (RadioSupportsReceiveTiming())
147+
{
148+
HandleCslReceiveAt(timeAhead, timeAfter);
149+
}
150+
else
151+
{
152+
HandleCslReceiveOrSleep(timeAhead, timeAfter);
153+
}
154+
}
155+
156+
void SubMac::HandleCslReceiveAt(uint32_t aTimeAhead, uint32_t aTimeAfter)
140157
{
141158
/*
142-
* CSL sample timing diagram
143-
* |<---------------------------------Sample--------------------------------->|<--------Sleep--------->|
144-
* | | |
145-
* |<--Ahead-->|<--UnCert-->|<--Drift-->|<--Drift-->|<--UnCert-->|<--MinWin-->| |
146-
* | | | | | | | |
147-
* ---|-----------|------------|-----------|-----------|------------|------------|----------//------------|---
148-
* -timeAhead CslPhase +timeAfter -timeAhead
149-
*
150-
* The handler works in different ways when the radio supports receive-timing and doesn't.
151-
*
152159
* When the radio supports receive-timing:
153160
* The handler will be called once per CSL period. When the handler is called, it will set the timer to
154161
* fire at the next CSL sample time and call `Radio::ReceiveAt` to start sampling for the current CSL period.
@@ -161,7 +168,32 @@ void SubMac::HandleCslTimer(void)
161168
* ^ ^
162169
* x-|------------|-------------------------------------x-|------------|---------------------------------------|
163170
* sample sleep sample sleep
164-
*
171+
*/
172+
uint32_t periodUs = mCslPeriod * kUsPerTenSymbols;
173+
uint32_t winStart;
174+
uint32_t winDuration;
175+
176+
mCslTimer.FireAt(mCslSampleTime - aTimeAhead + periodUs);
177+
aTimeAhead -= kCslReceiveTimeAhead;
178+
winStart = mCslSampleTime.GetValue() - aTimeAhead;
179+
winDuration = aTimeAhead + aTimeAfter;
180+
mCslSampleTime += periodUs;
181+
182+
Get<Radio>().UpdateCslSampleTime(mCslSampleTime.GetValue());
183+
184+
// Schedule reception window for any state except RX - so that CSL RX Window has lower priority
185+
// than scanning or RX after the data poll.
186+
if ((mState != kStateDisabled) && (mState != kStateReceive))
187+
{
188+
IgnoreError(Get<Radio>().ReceiveAt(mCslChannel, winStart, winDuration));
189+
}
190+
191+
LogCslWindow(winStart, winDuration);
192+
}
193+
194+
void SubMac::HandleCslReceiveOrSleep(uint32_t aTimeAhead, uint32_t aTimeAfter)
195+
{
196+
/*
165197
* When the radio doesn't support receive-timing:
166198
* The handler will be called twice per CSL period: at the beginning of sample and sleep. When the handler is
167199
* called, it will explicitly change the radio state due to the current state by calling `Radio::Receive` or
@@ -172,15 +204,11 @@ void SubMac::HandleCslTimer(void)
172204
* |------------|---------------------------------------|------------|---------------------------------------|
173205
* sample sleep sample sleep
174206
*/
175-
uint32_t periodUs = mCslPeriod * kUsPerTenSymbols;
176-
uint32_t timeAhead, timeAfter, winStart, winDuration;
177-
178-
GetCslWindowEdges(timeAhead, timeAfter);
179207

180208
if (mIsCslSampling)
181209
{
182210
mIsCslSampling = false;
183-
mCslTimer.FireAt(mCslSampleTime - timeAhead);
211+
mCslTimer.FireAt(mCslSampleTime - aTimeAhead);
184212
if (mState == kStateCslSample)
185213
{
186214
#if !OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
@@ -191,41 +219,38 @@ void SubMac::HandleCslTimer(void)
191219
}
192220
else
193221
{
194-
if (RadioSupportsReceiveTiming())
195-
{
196-
mCslTimer.FireAt(mCslSampleTime - timeAhead + periodUs);
197-
timeAhead -= kCslReceiveTimeAhead;
198-
winStart = mCslSampleTime.GetValue() - timeAhead;
199-
}
200-
else
201-
{
202-
mCslTimer.FireAt(mCslSampleTime + timeAfter);
203-
mIsCslSampling = true;
204-
winStart = ot::TimerMicro::GetNow().GetValue();
205-
}
206-
207-
winDuration = timeAhead + timeAfter;
222+
uint32_t periodUs = mCslPeriod * kUsPerTenSymbols;
223+
uint32_t winStart;
224+
uint32_t winDuration;
225+
226+
mCslTimer.FireAt(mCslSampleTime + aTimeAfter);
227+
mIsCslSampling = true;
228+
winStart = TimerMicro::GetNow().GetValue();
229+
winDuration = aTimeAhead + aTimeAfter;
208230
mCslSampleTime += periodUs;
209231

210232
Get<Radio>().UpdateCslSampleTime(mCslSampleTime.GetValue());
211-
212-
// Schedule reception window for any state except RX - so that CSL RX Window has lower priority
213-
// than scanning or RX after the data poll.
214-
if (RadioSupportsReceiveTiming() && (mState != kStateDisabled) && (mState != kStateReceive))
215-
{
216-
IgnoreError(Get<Radio>().ReceiveAt(mCslChannel, winStart, winDuration));
217-
}
218-
else if (mState == kStateCslSample)
233+
if (mState == kStateCslSample)
219234
{
220235
IgnoreError(Get<Radio>().Receive(mCslChannel));
221236
}
222237

223-
LogDebg("CSL window start %lu, duration %lu", ToUlong(winStart), ToUlong(winDuration));
238+
LogCslWindow(winStart, winDuration);
224239
}
225240
}
226241

227242
void SubMac::GetCslWindowEdges(uint32_t &aAhead, uint32_t &aAfter)
228243
{
244+
/*
245+
* CSL sample timing diagram
246+
* |<---------------------------------Sample--------------------------------->|<--------Sleep--------->|
247+
* | | |
248+
* |<--Ahead-->|<--UnCert-->|<--Drift-->|<--Drift-->|<--UnCert-->|<--MinWin-->| |
249+
* | | | | | | | |
250+
* ---|-----------|------------|-----------|-----------|------------|------------|----------//------------|---
251+
* -timeAhead CslPhase +timeAfter -timeAhead
252+
*
253+
*/
229254
uint32_t semiPeriod = mCslPeriod * kUsPerTenSymbols / 2;
230255
uint32_t curTime, elapsed, semiWindow;
231256

@@ -254,6 +279,15 @@ uint32_t SubMac::GetLocalTime(void)
254279
return now;
255280
}
256281

282+
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG)
283+
void SubMac::LogCslWindow(uint32_t aWinStart, uint32_t aWinDuration)
284+
{
285+
LogDebg("CSL window start %lu, duration %lu", ToUlong(aWinStart), ToUlong(aWinDuration));
286+
}
287+
#else
288+
void SubMac::LogCslWindow(uint32_t, uint32_t) {}
289+
#endif
290+
257291
#if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
258292
void SubMac::LogReceived(RxFrame *aFrame)
259293
{

0 commit comments

Comments
 (0)