CMD_PROP_CS

The carrier sense command monitors the RF activity on a channel and decides, whether a channel is occupied or free. It can be used to implement a CSMA scheme where a TX command only executes when nothing else occupies the channel. Channel detection is based upon two criteria: RSSI measurement and Preamble Quality (PQ).

Execution

The RF channel can be in several states:

Invalid:This is the default state at CS start.
Idle:No signal was found.
Busy:A signal was detected (RSSI above threshold or correlation succeeded).

 scale 0.8

 [*] -> Invalid
 Invalid -> Idle
 Invalid -> Busy
 Idle --> Busy
 Idle -> Idle
 Busy -> Idle
 Busy -> Busy

 Idle --> [*]
 Busy --> [*]
 Invalid --> [*]

Figure 28. Channel states and possible transitions.

All possible transitions between these states are illustrated in Figure 28.. Carrier sense always starts in Invalid state. Depending on the measured RSSI or the preamble quality, the channel goes either into Idle or into Busy state. The operation ends or may continue depending on the configuration. In addition, a timeout may occur which ends the measurement process immediately. After that, a status code is written to the radio operation and an execution result is generated for the evaluation phase.

A detailed sequence description of the carrier sense execution phase is shown in Figure 29.. In total, four procedures run in parallel:

watchRssi():Optional. Constantly measures the RSSI value and updates the channel state.
watchCorr():Optional. Correlates the RF signal with the expected preamble sequence and updates the channel state. The preamble settings are configured via CMD_PROP_RADIO_SETUP or CMD_PROP_RADIO_DIV_SETUP.
watchChannelState():
 Watches and evaluates the channel state changes caused by watchRssi() or watchCorr().
waitForCsEndTrigger():
 Optional. Waits for an end trigger (timeout) and evaluates the channel state when triggered.

 scale 0.8

 :Execution started;
 :channelState = Invalid;]
 split
     if (cmd.csConf.bEnaRssi) then (1)
         :watchRssi();|
     else (0)
     endif
     end
 split again
     if (cmd.csConf.bEnaCorr) then (1)
         :watchCorr();|
     else (0)
     endif
     end
 split again
     :watchChannelState();|
 split again
     :waitForCsEndTrigger();|
 end split
 :Execution Finished;

 legend right
     Command parameters:
     - cmd.csConf.bEnaRssi
     - cmd.csConf.bEnaCorr
 endlegend

Figure 29. The execution phase of CMD_CS as a SDL diagram. Four procedures run in parallel.

 scale 0.8

 start
 :idleCount = 0;\nbusyCount = 0;\nrssiState = INVALID;]
 repeat
     :RSSI Sample available<
     note right
         See section 'Timing' below.
     end note
     :rssi = readRssi();]
     if (rssi < cmd.rssiThr) then (yes)
         :idleCount++;\nbusyCount = 0;]
         if (idleCount >= cmd.numRssiIdle) then (yes)
             :rssiState = IDLE;]
             :updateChannelState(rssiState);|
             :RSSI state changed>
         endif
     else (no)
         :busyCount++;\nidleCount = 0;]
         if (busyCount >= cmd.numRssiBusy) then (yes)
             :rssiState = BUSY;]
             :updateChannelState(rssiState);|
             :RSSI state changed>
         endif
     endif
 repeat while ()

 legend right
     Command parameters:
     - cmd.numRssiBusy
     - cmd.numRssiIdle
     - cmd.rssiThr
 endlegend

Figure 30. The watchRssi() function from Figure 29.. For each change of rssiState, the resulting state is updated ccording to Table 14..

 scale 0.8
 skinparam ranksep 120

 state "Corr INVALID" as invalid
 state "Corr IDLE" as idle
 state "Corr BUSY" as busy

 [*] -> invalid
 invalid --> idle : \n\n[no tops within cmd.CorrPeriod]
 idle --> invalid : [tops >= cmd.corrConfig.numCorrInv within corrPeriod]\n && [cmd.corrConfig.numCorrBusy > 0]
 invalid --> busy : \n[tops >= cmd.corrConfig.numCorrBusy\n within cmd.corrPeriod]
 idle --> busy : [tops >= cmd.corrConfig.numCorrInv within corrPeriod]\n && [cmd.corrConfig.numCorrBusy == 0]
 busy --> idle : [no tops within cmd.corrPeriod]

Figure 31. The watchCorr() function from Figure 29. as a state chart. For each state change, the correlation state is updated according to Table 14..

Both procedures, watchRssi() and watchCorr() result in an internal channel state that is one of INVALID, IDLE or BUSY. Depending on cmd.bEnaRssi and cmd.bEnaRssi only one or both functions are active. If only function is active, the resulting channel state is equal to the internal channel state. When both functions are active, the cmd.csConf.operation flag specifies, how the results from these functions are combined:

  • 0: The channel is BUSY if either watchRssi() OR watchCorr() indicate BUSY.
  • 1: The channel is BUSY if both watchRssi() AND watchCorr() indicate BUSY.

A complete mapping can be found in Table 14.. The resulting channel state is then fed into watchChannelState() (Figure 32.) and waitForCsEndTrigger() (Figure 33.).

Table 14. Truth table that combines the output of watchRssi() and watchCorr() depending on cmd.csConf.operation. The resulting channel state is used as input for watchChannelState() in Figure 32. and waitForCsEndTrigger() in Figure 33..
RSSI OR Correlation csConf.operation = 0 RSSI AND Correlation csConf.operation = 1
  Correlation state
RSSI State INVALID IDLE BUSY INVALID IDLE BUSY
INVALID INVALID INVALID BUSY INVALID IDLE INVALID
IDLE INVALID IDLE BUSY IDLE IDLE IDLE
BUSY BUSY BUSY BUSY INVALID IDLE BUSY

 scale 0.8

 start
 :finished = false;]
 repeat
     :channelState changed<
     :channelState = lookup(rssiState, corrState);|
     note right
         See lookup table above
     endnote
     if (channelState) then (Idle)
         if (cmd.csConf.idleOp) then (1)
             :finished = true;\nresult = FALSE;\ncmd.status = PROP_DONE_IDLE;]
         else (0)
         endif
     elseif (channelState) then (Busy)
         if (cmd.csConf.busyOp) then (1)
             :finished = true;\nresult = TRUE;\ncmd.status = PROP_DONE_BUSY;]
         else (0)
         endif
     else (Invalid)
     endif
 repeat while (finished?) is (false)
 stop

 legend right
     Command parameters:
     - cmd.csConf.busyOp
     - cmd.csConf.idleOp
 endlegend

Figure 32. The watchChannelState() function from Figure 29..

 scale 0.8

 start
 :csEndTrigger fired<
 if (channelState) then (Idle)
     :cmd.status = PROP_DONE_IDLE;\nresult = FALSE;]
 elseif (channelState) then (Busy)
     :cmd.status = PROP_DONE_BUSY;\nresult = TRUE;]
 else (Invalid)
     if (cmd.csConf.timeOutRes) then (1)
         :cmd.status = PROP_DONE_IDLETIMEOUT;\nresult = FALSE;]
     else (0)
         :cmd.status = PROP_DONE_BUSYTIMEOUT;\nresult = TRUE;]
     endif
 endif
 stop

 legend right
     Command parameters:
     - cmd.csConf.timeOutRes
 endlegend

Figure 33. The waitForCsEndTrigger() function from Figure 29. in an SDL diagram.

Timing

The CMD_PROP_CS provides two timing values:

  • cmd.csEndTime is the minimum execution time in RAT ticks, after which channel state evaluation is forced. Optional.
  • cmd.corrPeriod specifies the number of RAT ticks between each correlation evaluation.

How to chose a minimum value for cmd.csEndTime so that at least either cmd.numRssiIdle or cmd.numRssiBusy RSSI samples are measured before a final decision is forced? The following drawing illustrates the CS command execution phase.

../../_images/aafig-baabab8541a06985c3fc7c39aaa5973303f55b3e.png

After the obligatory parsing delay of approximatly 50 µs, command execution starts and the end trigger for cmd.csEndTime is armed. After a fixed time Rssi_0, the first RSSI sample is available and the RSSI available signal in Figure 30. is fired for the first time. Successive RSSI samples occur with a period Rssi_n. The execution may either end up due to channel state evaluation in Figure 32. or a timeout of cmd.csEndTime, but has an additional evaluation delay of 5 µs.

Please note, that the RSSI sample period might be affected by the Automatic Gain Correction (AGC) and the AGC is always enabled in RX mode. In case of a very strong signal, the AGC might increase the first sample period Rssi_1 up to 4 times. If the signal strength is changing very fast, the AGC re-adjusts every RSSI sample period. However, in reality it is safe to assume that only the first period Rssi_1 is delayed by the AGC. The value Rssi_0 in contrast, is not affected, but the value might be wrong if the signal strength is above -50 dBm. For CSMA applications, this is expected to be uncritical.

A minimum value for cmd.csEndTime can be estimated with formula (1).

(1)csEndTime_{\text{min}}^{\text{rssi}} =
     \begin{cases}
         Rssi_0 + Rssi_n \cdot cmd.numRssiIdle + \SI{5}{\us} \\
         Rssi_0 + Rssi_n \cdot cmd.numRssiBusy + \SI{5}{\us}
     \end{cases}

Table 15. provides measurement results for Rssi_0 and Rssi_n. Both depend on the configured RX bandwidth (cmd.rxBw), specified either in CMD_PROP_RADIO_SETUP or CMD_PROP_RADIO_DIV_SETUP.

Table 15. Timing watchRssi() and watchCorr()
RX bandwidth Value for rxBw First RSSI sample RSSI sample period
[kHz] CC13xx CC26xx Rssi_0 [µs] Rssi_n [µs]
45/55/66 32/33/34 n/a 348 136
88/110/130 35/36/37 1/2/3 214 68
180/220/260 38/39/40 4/5/6 149 34
350/430/530 41/42/43 7/8/9 114 17
700/870/1060 44/45/46 10/11/12 98 10
1410/1740/2120 47/48/49 13/14/15 89 10