.. _csa2:

Channel Selection Algorithm #2
------------------------------

Summary
^^^^^^^

Channel Selection Algorithm #2 (CSA #2) is a more complex and harder to track algorithm for
obtaining the channel index for the next connection event.  It is more effective at avoiding
interference and multi-path fading effects than Channel Selection Algorithm #1, especially in
high-throughput use cases.

See Volume 6, Part B, Section 4.5.8.2 of the |CORESPEC| for a \
detailed description of the algorithm.

Here are samples of what the algorithm would like over 100 events for 37 and 9 used channels:

.. _CSA2_example:
.. figure:: resources/CSA2.png
    :align: center

    Channel Selection Algorithm #2 Example

Default Configuration
^^^^^^^^^^^^^^^^^^^^^

The stack includes support for CSA #2 by default and it is also enabled by default. That is, as a
Central, the device will attempt to establish a connection using CSA #2 and, as a Peripheral, the device
will accept CSA #2 connections requests.  At a lower level, this means that, as a Central, the
device will send connection requests with the ChSel field set to 1 and, as a Peripheral, the device will
advertise with the ChSel field set to 1.

Whether or not CSA #2 is used for the connection depends on what is supported on the peer device.
The |CORESPEC| states that

   "If the initiator sent a CONNECT_IND PDU in response to an ADV_IND or AD_DIRECT_IND PDU and
   either or both device’s PDU had the ChSel field set to 0, then Channel Selection Algorithm
   #1 shall be used on the connection. Otherwise, Channel Selection Algorithm #2 shall be used."

See Volume 6, Part B, Section 4.5 of the |CORESPEC| for more details.

.. _csa2-disabling-procedure:

Disabling CSA #2
^^^^^^^^^^^^^^^^
For a detailed overview on disabling controller features, such as CSA #2, please
refer to the entirety of :ref:`sec-hci`.

CSA #2 may be disabled by clearing the respective supported features bit. First,
an HCI event handler must be registered to the stack. Then, use 
:ble_api:`HCI_LE_ReadLocalSupportedFeaturesCmd` to get the current set of local 
supported LE features.

After receiving the corresponding 
:ble_api:`HCI_LE_READ_LOCAL_SUPPORTED_FEATURES` event (see :ref:`sec-hci` for 
more details on how to receive events), clear the ``LL_FEATURE_CHAN_ALGO_2`` bit 
(bit 7 of byte 1) and update the modified features with 
:ble_api:`HCI_EXT_SetLocalSupportedFeaturesCmd` :

.. note::
   This must be done before advertising (for the Peripheral) or before 
   initiating (for the Central).

.. code-block:: c
   :linenos:

    case HCI_LE_READ_LOCAL_SUPPORTED_FEATURES:
    {
        uint8_t featSet[8];

        // get current feature set from received event (bytes 1-9 of
        // the returned data
        memcpy( featSet, &pMsg->pReturnParam[1], 8 );

        // clear the CSA#2 feature bit
        CLR_FEATURE_FLAG( featSet[1], LL_FEATURE_CHAN_ALGO_2 );

        // Update controller with modified features
        HCI_EXT_SetLocalSupportedFeaturesCmd( featSet );
    }
