@@ -137,18 +137,25 @@ bool SubMac::UpdateCsl(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShortAd
137137void SubMac::HandleCslTimer (Timer &aTimer) { aTimer.Get <SubMac>().HandleCslTimer (); }
138138
139139void 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
227242void 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
258292void SubMac::LogReceived (RxFrame *aFrame)
259293{
0 commit comments