Application Layer
=================

Since the Micro BLE Stack can support multiple functionalities (broadcaster,
observer, or connection monitor), it is up to the application layer to define
the behavior of the system. The following sections will discuss the TI provided
implementations of the monitor role.

  - ``micro_ble_cm.c`` : connection monitor application


.. _sec-cm-app-cc23xx:

Connection Monitor (CM) Application
-----------------------------------

The connection monitor application is built on top of the uGAP layer,
operating in the monitor role, and is responsible for implementing the high-level
connection tracking feature. This includes:

 1. Initializing connection parameters for a connection to monitor
 2. Performing the initial scan to find a connection event
 3. Scheduling subsequent scans to continue following the connection

The following sections will describe the above list in detail.


.. _sec-cm-init-cc23xx:

Initializing CM Session
^^^^^^^^^^^^^^^^^^^^^^^

In order to follow a connection, the CM needs to know the connection parameters
that were exchanged during the connection process between the central and
peripheral devices. These include:

  - Access address
  - Connection interval
  - Hop value
  - Next channel
  - Channel map
  - CRC initialization value

These parameters can be obtained from a |STACK| application by calling
the ``HCI_EXT_GetActiveConnInfoCmd`` command. Once they are obtained,
they should be shared (via an out of band mechanism such as UART, LIN, CAN etc)
with the CM device. The CM device then can use ``ubCM_startNewSession()`` to start the
initial scan.


.. _sec-cm-starting-monitoring-cc23xx:

Starting a Monitor Session
^^^^^^^^^^^^^^^^^^^^^^^^^^

In order to start tracking a connection, the connection monitor needs to
perform an initial scan with a long enough scan duration to catch a connection
event. This scan should be, at worst case, the connection interval times the
number of active channels in order to ensure the connection can be detected.

The logic trace below shows the initial scan of a connection monitor
and it was generated by enabling the RF observable pins on the
central and peripheral devices in the connection (RX/TX) as well as the
connection monitor (RX). For more information regarding the RF observable pins,
please refer to the :ref:`DEBUG_rf_output` section.

.. _cm-init-scan-cc23xx:
.. figure:: /u-stack/resources/cm-initial-scan.png

.. note ::
    For example, if the active channel map is channel 0, 1, 2, 3, 4, 5 and
    the hop number is 1. The next channel sent from peripheral is 2 and 
    connection interval is 7.5 ms. Then CM will stay at channel 2 for maximum
    45 ms(6 * 7.5).


.. _sec-cm-monitoring-connection-cc23xx:

Monitoring a Connection
^^^^^^^^^^^^^^^^^^^^^^^

Once a packet is received during the initial scan, the CM will set up
smaller scans based on the next expected event. Since it is now monitoring the
connection, it can calculate the channel and instant (adjusted for central and 
peripheral sleep clock accuracy (:term:`SCA`)) to listen for the next event.

The core of connection monitoring is based on

 - ``monitor_indicationCB`` : Invoked when a packet is received.
 - ``monitor_completeCB`` : Invoked when a scan window has completed.

 The logic trace below shows a CM actively tracking a connection:

.. _cm-conn:
.. figure:: /u-stack/resources/cm-conn.png

The sequence diagram below illustrates the whole process of how CM
starts monitoring the connection and reporting :term:`RSSI` to the application.

.. uml::
    :caption: Connection Monitor initialization and connection tracking
    :align: center

    @startuml
      
    participant CM as "Connection Monitor"
    participant Basic as "Basic BLE"
    participant Phone as "Phone"

    Basic <-- Phone: Connection Request
    == After connection has established ==
    CM <- Basic: Pass needed information to Connection Monitor

    rnote left
      Basic BLE device needs to pass access address,
      connection interval, channel map, 
      hop increment, CRC init, and next channel
      to Connection Monitor device.
    end note
  
    activate CM
      CM --> CM: Start scanning for packet at next channel
      Phone --> Basic: Send packet
      Basic --> Phone: Send packet
    ...
    ... Connection Monitor will stay at next channel for maximum\nCI * (Number of Active Channel) amount of time...
    ...
      Phone --> Basic: Send packet
      Basic --> Phone: Send packet
    deactivate CM
    
    Group If Connection Monitor Initial Scan Timeout\nScan Timeout = (CI * Number of Active Channels)
      CM --> CM: Back to Idle state
      CM -> Basic: Notify Basic BLE that sync failed
      Basic -> CM: Send over needed information to restart \nConnection Monitor
    end

    Group After Connection Monitor syncs up
    
    Phone --> Basic: Send packet

    activate CM

    CM --> CM: Scan packet sent from Phone and\nextract RSSI
    [<-CM : The RSSI value from Phone will be \nsent to monitor_indicationCB

    Basic --> Phone: Send packet
    CM --> CM: Scan packet sent from Basic BLE device \nand extract RSSI
    [<-CM : The RSSI value from Basic BLE device will \nbe sent to monitor_indicationCB
    CM --> CM: Finish one monitor event
    [<-CM : Send notification to monitor_completeCB \nto indicate one monitor event has finished 
    CM -> Basic: One monitor event success. \nSend RSSI, timeStamp and monitored channel to Basic BLE device
    Deactivate CM

    ...
    ... Change to next channel and Connection Monitor continues monitoring the connection...
    ...
    end
    @enduml

.. _sec-cm-loses-sync-cc23xx:

Lose Sync
^^^^^^^^^

The application layer can decide how many consecutive connection events the
CM is allowed to miss by setting ``BLE_CONSECUTIVE_MISSED_CONN_EVT_THRES``.

The CM keeps track of consecutive missed events (``consecutiveTimesMissed``)
and total missed events (``timesMissed``).
Those variables can be found under the ``ubCM_ConnInfo_t`` struct.

.. code-block:: c
  :caption: Connection Monitor Information
  :linenos:
  :emphasize-lines: 5,6
    
    typedef struct
    {
      uint8_t   sessionId;                             //! Number 1-255 assigned as they are created identifying each connection monitor session
      uint8_t   timesScanned;                          //! track count of recent events monitored to determine next priority CM session to avoid starvation
      uint8_t   timesMissed;                           //! missed count of recent events monitored
      uint8_t   consecutiveTimesMissed;                //! consecutive missed count of recent events monitored
      uint8_t   missedEvents;                          //! missed count of events since last monitoring session
      uint8_t   numEvents;                             //! how many connection events have passed since the last anchor point.
      uint32_t  accessAddr;                            //! return error code if failed to get conn info
      uint8_t   connRole;                              //! RTLS Coordinator BLE role (4 - Peripheral, 8- Central)
      uint16_t  connInterval;                          //! connection interval time, range 12 to 6400 in  625us increments (7.5ms to 4s)
      uint16_t  scanDuration;                          //! Required scan window to capture minimum of 1 packet from Central and Peripheral up to max possible packet size
      uint8_t   hopValue;                              //! Hop value for conn alg 1, integer range (5,16)
      uint16_t  combSCA;                               //! mSCA + cmSCA
      uint8_t   currentChan;                           //! current unmapped data channel
      uint8_t   lastUnmappedChannel;                   //! last used unmapped channel when received data packet from the central
      uint8_t   nextChan;                              //! next data channel
      uint8_t   numUsedChans;                          //! count of the number of usable data channels
      uint8_t   chanMap[CM_MAX_NUM_DATA_CHAN];         //! current channel map table that is in use for this connection
      uint8_t   rssiCentral;                           //! last Rssi value Central
      uint8_t   rssiPeripheral;                        //! last Rssi value Peripheral
      uint32_t  timeStampCentral;                      //! last timeStamp Central
      uint32_t  timeStampCentral2;                     //! last timeStamp Central
      uint32_t  timeStampPeripheral;                   //! last timeStamp Peripheral
      uint32_t  currentStartTime;                      //! Current anchor point
      uint32_t  nextStartTime;                         //! Record next planned scan anchor point to compare with competing CM sessions
      uint32_t  lastStartTime;                         //! Record last planned scan anchor point to compare with competing CM sessions
      uint32_t  timerDrift;                            //! Clock timer drift
      uint32_t  crcInit;                               //! crcInit value for this connection
      uint16_t  hostConnHandle;                        //! keep connHandle from host requests
      uint8_t   outOfSyncFlag;                         //! flag indicating that the CM session is trying to get in sync
      uint32_t  outOfSyncTimeStamp;                    //! timeStamp for trying to get in sync
    } ubCM_ConnInfo_t;

Once ``consecutiveTimesMissed`` is larger than ``BLE_CONSECUTIVE_MISSED_CONN_EVT_THRES``, 
the CM will terminate the monitor session and notify the 
host. The host can then restart the monitor session by going 
through :ref:`sec-cm-init-cc23xx`, :ref:`sec-cm-starting-monitoring-cc23xx`
and :ref:`sec-cm-monitoring-connection-cc23xx`. 

The sequence diagram below illustrates the whole process of how a CM
deals with losing sync.

.. uml::
    :caption: Connection Monitor loses sync
    :align: center

    @startuml

    participant CM as "Connection Monitor"
    participant Basic as "Basic BLE"
    participant Phone as "Phone"

    == BLE_CONSECUTIVE_MISSED_CONN_EVT_THRES = 30 ==
    == Connection Monitor syncs up ==
    Phone --> Basic: Send packet
    activate CM
    ...
    ... Assume Connection Monitor has been scanning \nbut missed 30 consecutive connection events.\n connInfo->consecutiveTimesMissed is now at 30...
    ...

    Basic --> Phone: Send packet

    Group If CM successfully monitors 31st connection event 

    Phone --> Basic: Send packet
    Basic --> Phone: Send packet
    
    CM --> CM: connInfo->consecutiveTimesMissed = 0

    CM --> CM: Finish one monitor event
    [<-CM : Send notification to monitor_completeCB \nto indicate one monitor event has finished 
    CM -> Basic: One monitor event success. \nSend RSSI, timeStamp and monitored channel \nto Basic BLE device

    end

    Group If CM misses 31st connection event 

    Phone --> Basic: Send packet
    Basic --> Phone: Send packet
    CM --> CM: connInfo->consecutiveTimesMissed ++
    deactivate CM
    
    CM --> CM: Change status to CM_FAILED_NOT_ACTIVE

    [<-CM: Send notification to monitor_completeCB \nto indicate the monitor session \nis no longer active
    CM --> CM: Terminate the monitor session by calling \nubCM_stop 
    CM-> Basic: Notify Basic BLE device that the monitor session is terminated

    CM --> CM: Back to Idle.
    Basic -> CM: Send over needed information to \nrestart monitoring session

    end

    @enduml

.. _sec-cm-update-connInfo-cc23xx:

Connection Information Update
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

A CM does not extract the payload information, it only measures the 
RSSI from the payload. Therefore, if there are control packets such as
a channel map update or other connection parameter updates
exchanged between the central and peripheral devices, the device that has a
wired connection to the CM needs to pass on the information so that the CM
can continue monitoring the connection.

Once the CM receives the new information, the application needs to call
``MicroCmApp_cmStartReq`` or ``RTLSPassive_cmStartReq`` which eventually 
calls ``ubCM_updateExt`` if the session already exists.

.. uml::
    :caption: Connection Monitor control packets update
    :align: center

    @startuml

    participant CM as "Connection Monitor"
    participant Basic as "Basic BLE"
    participant Phone as "Phone"
    
    activate CM

    == Connection Monitor syncs up ==
    Phone --> Basic: Send packet

    Basic --> Phone: Send packet

    group Channel Map Update 

    Phone --> Basic: Send channel map update packet
    Basic --> Phone: Send packet
    Basic -> CM: Send the updated channel map
    
    CM --> CM: Update the current monitor session \nwith new information by calling \nubCM_updateExt

    end

    Group Connection Parameters Update

    Phone --> Basic: Connection parameters update packet
    Basic --> Phone: Response to the connection \nparameters update packet
    Basic -> CM: Send the new connection parameters
    
    CM --> CM: Update the current monitor session \nwith new information by calling \nubCM_updateExt

    end
    
    CM --> CM: Stop monitoring current session and \ncontinue scanning until sync found/timeout

    @enduml

.. _sec-cm-multiple-connection-cc23xx:

Monitor Multiple Connections
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

A CM can monitor multiple connections even when all of the monitored
connections have different connection intervals. 

To determine which connection to monitor, after ending each monitor session,
the CM scheduler will sort all of the connections based on future start time.
Then the CM will do a timing conflict check on selected and sec connections.
If (conn1 start time + monitor/scan duration) > conn2 start time, then
the CM will consider that there is conflict between connection 1 and
connection 2.

The monitor/scan duration for each monitor session is determined by 
the following parameters:

 - Sleep Clock Accuracy (:term:`SCA`) for both central and peripheral devices.
 - The processing time for the radio core and the CM software.
 - Time needed to receive only one packet per central and periperal device using 
   1M Phy. No :term:`MD` in the same connection event.
   
   .. note::
     A CM is designed to extract :term:`RSSI` information for both the central
     and peripheral devices when they are in a connection. It does not extract
     payload information; therefore, there is no need to monitor more packets.

When there is a timing conflict among monitored connections, the CM will decide
which connection to monitor based on the following factors, in 
order of priorities from high to low:

 #. If one of the connections has larger connection interval, then the connection
    which the CM misses more monitored time will be scheduled.

    .. note::
      For example, if the next connection events for connection 1(CI = 100ms) 
      and connection 2(CI = 40ms, cmMissedEvent = 3) are in conflict, then CM will monitor
      connection 2 because connection 2 missed more monitored time (100 < 40*3).

 #. The connection with the higher ``cmMissedEvents``.
 #. The connection with the earlier start time.

The following diagram illustrates how a CM would handle a monitor
session conflict:

.. ditaa::
   :--no-separation:
   :--no-shadows:

                                          +-----------------------------------+
                                          | Does one of the connections       |
                                          | have a larger connection interval?|
                                          |   cCFF                            |
                                          +-----------------------------------+
                         Yes, conn1 has larger   |                  | No
                          connection interval    |                  |
                              /------------------/                  \-------------\
                              |                                                   |
                              |                                                   |
                              |                                                   |
                              v                                                   v
                    +--------------------------------------+          +---------------------------------+
                    | Is (Conn2 Interval x Conn2 MissedEvt)|          | Does one of the connections have|
                    | larger than Conn1 Interval?          |          | a higher missEvents count?      |
                    |   c0CC                               |          |  c0CC                           |
                    +--------------------------------------+          +---------------------------------+
                           |              |                                |                  |
                 Yes       |              | No                         Yes |                  | No
             /-------------/              |                      /---------/                  |           
             |                            |                      |                            |
             |                            |                      |                            |
             v                            v                      v                            v 
      +-------------+              +-------------+         +-------------------+       +---------------------+
      | Conn 2 will |              | Conn 1 will |         | Connection with   |       | Connection with     |
      | be scheduled|              | be scheduled|         | higher missEvents |       | earliest start time |
      | c189        |              | c189        |         | will be scheduled |       | will be scheduled   |
      +-------------+              +-------------+         | c189              |       | c189                |
                                                           +-------------------+       +---------------------+

.. _sec-cm-limitation-cc23xx:

Limitations
^^^^^^^^^^^

When requesting a new monitor session while CM has already been 
monitoring connection(s), the CM will process the request based
on the timing of when the request comes in.

 - If the request comes in when the CM is not monitoring 
   a connection, the request will be processed right away. This
   means that the CM will start scanning for a new connection immediately
   after receiving the request.
 - If the request comes in when the CM is monitoring a connection,
   the information of the new connection will be saved and processed
   once the current monitor session has ended.

The following diagram illustrates how the CM handles new monitor requests.

.. ditaa::
   :--no-separation:
   :--no-shadows:

                               +-------------------------+            
    +----------------+         | Is CM currently         |           +-------------------------+
    | New monitor    |         | monitoring a connection |   Yes     | Save the new connection |
    | session request|-------->| or scanning for a new   |---------->|       parameters        |  
    |  cCFF          |         | connection to monitor?  |           | c189                    |
    +----------------+         | c0CC                    |           +-------------------------+
                               +-------------------------+                                        
                                         |
                                         | No
                                         v
                               +-------------------------+
                               | Start scanning for the  |
                               |     new connection      |
                               | c189                    |
                               +-------------------------+
    
Due to the nature of how :ref:`sec-cm-starting-monitoring-cc23xx` works, 
the radio might still be scanning for the new connection when 
it is time to monitor existing connection(s). The CM will
prioritize scanning for new connection over monitoring existing connection(s).
Once the CM is able to track the new connection or scan timeout, it will
continue monitoring the existing connections.

That being said, if there are multiple new monitor session requests coming in,
then the CM will process all of the new monitor session requests before it
goes back to monitor the existing connections. 

In addition to the above limitations, the CM example also
has the following constraints:

- Connections must use LE Channel Selection Algorithm #1
- Connections must use LE 1M PHY
- Connections must exist on LE Data channels

.. warning::
    It is not recommended to call ``ubCM_stop`` or ``ubCM_start`` in the
    middle of a monitor session. Calling the aforementioned APIs while
    the radio is active might cause unexpected behavior.