NAV Navbar

CYW20819 BLE Find Me Profile – CE226123

This code example demonstrates the implementation of a simple BLE Immediate Alert Service (IAS)-based Find Me Profile (FMP) using the CYW20819 Bluetooth SoC, using ModusToolbox™ integrated development environment (IDE).

Requirements

Tool: ModusToolbox IDE 1.1 or later version

Programming Language: C

Associated Parts: CYW20819

Related Hardware: CYW920819EVB-02 Evaluation Kit

Overview

This design implements a BLE FMP that consists of an IAS. FMP and IAS are BLE standard Profile and Service respectively, as defined by the Bluetooth SIG. The design uses the two LEDs (red and yellow) on the CYW920819EVB-02 kit. The red LED (LED2) displays the following IAS alert levels: no alert (LED OFF), mild alert (LED blinking), and high alert (LED ON). The yellow LED (LED1) indicates whether the Peripheral device (CYW20819) is advertising (LED blinking), connected (LED ON), or disconnected (LED OFF).

An iOS/Android mobile device or a PC can act as the BLE Central device, which connects to the Peripheral device.

Hardware Setup

This example uses the kit’s default configuration. Refer to the kit guide, if required, to ensure the kit is configured correctly.

Software Setup

This code example consists of two parts: a locator and a target. For the locator, download and install the CySmart™ app for iOS or Android. You can also use the CySmart Host Emulation Tool Windows PC application if you have access to the CY5677 CySmart BLE 4.2 USB Dongle. You can also use other Android or iOS apps that support the IAS service.

Scan the following QR codes from your mobile phone to download the CySmart app.

iOS Android

Operation

Figure 1. Building and Programming the Application

Buiding and Programming the Application

Figure 2. Testing with the CySmart App on iOS

Figure 2. Testing with the CySmart App on iOS

Figure 3. Testing with the CySmart App on Android

Figure3

Figure 4. Log Messages on WICED PUART COM Port

Figure4

  1. Connect the kit to your PC using the provided USB cable.
  2. The USB Serial interface on the kit provides access to the two UART interfaces of the CYW20819 device – WICED HCI UART and WICED® Peripheral UART (PUART). The HCI UART is used only for downloading the application code in this code example and the PUART is for printing the Bluetooth stack and application trace messages. Use your favorite serial terminal application and connect to the PUART serial port. Configure the terminal application to access the serial port using the following settings:
  3. Baud rate: 115200 bps; Data: 8 bit; Parity: None; Stop: 1 bit; Flow control: None; New line for receive data: Line Feed(LF) or Auto setting
  4. Import the code example into a new or existing workspace. This involves the following steps.
    1. Follow the steps in KBA225201 to clone or download the CYW20819 code examples repository from Cypress GitHub portal.
    2. Once you have the repository on your local machine, the BLE Find Me profile code example is located in the repository folder at Code-Examples-BT-20819A1-1.0-for-ModusToolbox\CYW920819EVB-02\apps\demo\BLE_FindMe. Continue to follow the steps in KBA225201 to import this code example in ModusToolbox IDE with the following changes.
      1. Select the CYW920819EVB-02 evaluation kit in the Choose Target Hardware dialog.
      2. Select the modus.mk file of the BLE_FindMe code example during the Import step in the Starter Application dialog.

  5. Build and Program the application: In the project explorer, select the [App Name]_mainapp/ project. In the Quick Panel, scroll to the Launches section, and click the [App Name] Build + Program configuration as shown in Figure 1.
  6. Observe the yellow LED (LED1) starts blinking after the device starts advertising.
  7. To test using the CySmart mobile app, follow the steps below (see equivalent CySmart app screenshots in Figure 2 and Figure 3):
    1. Turn ON Bluetooth on your Android or iOS device.
    2. Launch the CySmart app.
    3. Press the reset switch on the CYW920819EVB-02 kit to start sending advertisements. The yellow LED (LED1) starts blinking to indicate that advertising has started. Advertising will stop after 90 seconds if a connection has not been established.
    4. Swipe down on the CySmart app home screen to start scanning for BLE Peripherals; your device (“Find Me Target”) appears in the CySmart app home screen. Select your device to establish a BLE connection. Once the connection is established, the yellow LED (LED1) changes from blinking state to always ON state.
    5. Select the 'Find Me' Profile from the carousel view.
    6. Select an Alert Level value on the Find Me Profile screen. Observe the state of the red LED (LED2) on the device changes based on the alert level.
    Figure 2 and Figure 3 show the steps for using CySmart App on iOS and Android respectively.

  8. Use the PUART serial port to view the Bluetooth stack and application trace messages in the terminal window as shown in Figure 4.

Design and Implementation

The ‘Find Me Locator’ (the BLE Central device) is a BLE GATT Client. The ‘Find Me Target’ (the Peripheral device) is a BLE GATT Server with the IAS implemented, as Figure 5 shows.

Figure 5. Find Me Profile (FMP) Application using CYW20819

Figure5

The BLE Find Me profile defines what happens when the locating Central device broadcasts a change in the alert level.

The Find Me locator performs service discovery using the 'GATT Discover All Primary Services' procedure. The BLE Service Characteristic discovery is done by the 'Discover All Characteristics of a Service' procedure. When the Find Me Locator wants to cause an alert on the Find Me Target, it writes an alert level in the Alert Level Characteristic of the IAS. When the Find Me Target receives an alert level, it indicates the level using the red LED: OFF for no alert, blinking for mild alert, and ON for high alert.

The application code and Bluetooth stack runs on the Arm® Cortex®-M4 core of the CYW20819 SoC. The important source files relevant for the user application level code for this code example are listed in Table 1.

Table 1. Important User-Application-Related Source Files

File Name Comments
main.c Contains the application_start() function which is the entry point for execution of the user application code after device startup.
app_bt_cfg.c, app_bt_cfg.h These files contain the runtime Bluetooth stack configuration parameters like device name, advertisement/ connection settings, etc. Note that the name that the device uses for advertising (“Find Me Target”) is defined in app_bt_cfg.c.
app_bt_event_handler.c, app_bt_event_handler.h These files contain the code for the Bluetooth stack event handler functions.
app_user_interface.c, app_user_interface.h These files contain the code for the application user interface (in this case, the LED) functionality.
cycfg_gatt_db.c, cycfg_gatt_db.h These files reside in the GeneratedSource folder under the application folder. They contain the GATT database information generated using the Bluetooth Configurator tool.

See AN225684 - Getting Started with CYW20819 application note to understand the firmware design for this code example.

Resources and Settings

This section explains the ModusToolbox resources and their configuration as used in this code example. Note that all the configuration explained in this section has already been done in the code example. The ModusToolbox IDE stores the configuration settings of the application in the design.modus file. This file is used by the graphical configurators, which generate the configuration firmware. This firmware is stored in the application’s GeneratedSource folder.

Figure 6 shows the Device Configurator settings highlighting the peripherals used for this code example. The Device Configurator is used to enable/configure the peripherals and the pins used in the application. To launch the Device Configurator, double-click the design.modus file or click on Configure Device in the Quick Panel. Any time you make a change in the Device Configurator, click File > Save to save the updated configuration.

Peripherals

The design uses the Bluetooth and PUART peripherals which are enabled under the Peripherals section as shown in Figure 6. Other chip peripherals that are applicable for using the kit are also enabled by default in Figure 6, but they are not used in this application.

Bluetooth Configurator

Figure 6. Device Configurator - Peripherals

Figure6

The Bluetooth Configurator is used for generating/modifying the BLE GATT database. To launch the Bluetooth Configurator from the Device Configurator window, click on the Bluetooth resource under the Peripherals section, and then click on the Launch Bluetooth Configurator shortcut under the Bluetooth-Parameters window (as shown in callouts A, B in Figure 6).

Figure 7. GATT Database View in BLE Configurator

Figure 7. GATT Database View in BLE Configurator

Figure 8. Adding Find Me Target Profile

Figure 8. Adding Find Me Target Profile

The Bluetooth Configurator for this code example is shown in Figure 7. Note that the Immediate Alert Service corresponding to the Find Me Target profile has been added in Figure 7. Figure 8 shows how the Find Me Target profile was added to create the GATT database shown in Figure 7. Click on GATT profile in the GATT database tree and follow the steps in Figure 8 to add the Find Me Target profile. Any time you make a change in the Bluetooth Configurator, ensure that you save the changes (click File > Save or click the Save icon).

Pins

Figure 9. Device Configurator - Pins

Figure 9. Device Configurator - Pins

The pins used in the application are enabled in the Pins section of the Device Configurator as shown in Figure 9. Other pins that are applicable for using the kit are also enabled by default in Figure 9, but they are not used in this application. Table 2 provides more information on the pins used in this application.

Table 2. Pin Mapping Details

Pin Alias Purpose Settings
P26 LED2 Mapped to the red LED (LED2) on the kit. Indicates IAS Alert Level. See Figure 10
P27 LED1 Mapped to the yellow LED (LED1) on the kit. Indicates the Advertising/Connected state of the BLE peripheral device.
P32 PUART_TX Tx pin of PUART peripheral See Figure 11
P37 PUART_RX Rx pin of PUART peripheral See Figure 12

Figure 10. LED Pin Settings

#Figure10

Figure 11. PUART Tx Pin Settings

Figure 11. PUART Tx Pin Settings

Figure 12. PUART Rx Pin Settings

Figure 12. PUART Rx Pin Settings

Code Example

The BLE_FindMe app demonstrates the implementation of the BLE FindMe profile consisting of Immediate Alert Service (IAS). The application uses two LEDs, the first for indication of advertisement status and second for the IAS alert level.

BLE Initialization (main.c)

    /* Initialize Stack and Register Management Callback */
    wiced_bt_stack_init(app_bt_management_callback, &wiced_bt_cfg_settings, wiced_bt_cfg_buf_pools);

The function wiced_bt_stack_init() initializes the Bluetooth controller and stack, along with registering a callback for Bluetooth event notifications. The function return value is wiced_result_t, which will return WICED_BT_SUCCESS on successful initialization of the BT stack and WICED_BT_FAILED if some error occurs. The callback app_bt_management_callback is called to handle the BLE stack events. Based on these events, you will have to add code/call functions to take respective actions.

Main Loop (app_bt_event_handler.c)

wiced_result_t app_bt_management_callback(wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data)
{
switch (event)
    {
        case BTM_ENABLED_EVT:

            /* Bluetooth Controller and Host Stack Enabled */

            if (WICED_BT_SUCCESS == p_event_data->enabled.status)
            {
                /* Bluetooth is enabled */
                wiced_bt_dev_read_local_addr(bda);

                /* Perform application-specific initialization */
                ble_app_init();
            }

            break;

        case BTM_BLE_ADVERT_STATE_CHANGED_EVT:

            /* Advertisement State Changed */
            p_adv_mode = &p_event_data->ble_advert_state_changed;

            if (BTM_BLE_ADVERT_OFF == *p_adv_mode)
            {
                /* Advertisement Stopped */
                /* Check connection status after advertisement stops */
                if(bt_connection_id == 0)
                    app_bt_adv_conn_state = APP_BT_ADV_OFF_CONN_OFF;
                else
                    app_bt_adv_conn_state = APP_BT_ADV_OFF_CONN_ON;
            }
            else
            {
                /* Advertisement Started */
                app_bt_adv_conn_state = APP_BT_ADV_ON_CONN_OFF;
            }

            /* Update Advertisement LED to reflect the updated state */
            adv_led_update();

            break;

        default:
            WICED_BT_TRACE("Unhandled Bluetooth Management Event: 0x%x (%d)\n", event, event);
            break;
    }

    return status;
}

The BTM_ENABLED_EVT event is triggered once the BLE stack initialization is complete. After this event occurs, the main application will start executing by calling the function ble_app_init(). In ble_app_init, the device will start advertisement using the function wiced_bt_start_advertisements(BTM_BLE_ADVERT_UNDIRECTED_HIGH, 0, NULL). wiced_bt_gatt_register() is also called for registering the GATT events callback handler ble_app_gatt_event_handler(). TheBTM_BLE_ADVERT_STATE_CHANGED_EVT event is called when the advertisement state switching happens. For fast advertisement, you will see the return value as '3' indicating the BTM_BLE_ADVERT_UNDIRECTED_HIGH advertisement mode. Similarly, when advertisement stops, BTM_BLE_ADVERT_OFF mode will be called with the return value as '0'. To reflect the change in advertisement state, adv_led_update() function will be called and LED state will be updated.

GATT Event Handler (app_bt_event_handler.c)

static wiced_bt_gatt_status_t ble_app_gatt_event_handler(wiced_bt_gatt_evt_t event, wiced_bt_gatt_event_data_t *p_event_data)
{    
    switch ( event )
    {
        case GATT_CONNECTION_STATUS_EVT:
            status = ble_app_connect_callback( &p_event_data->connection_status );
            break;

        case GATT_ATTRIBUTE_REQUEST_EVT:
            p_attr_req = &p_event_data->attribute_request;
            status = ble_app_server_callback( p_attr_req->conn_id, p_attr_req->request_type, &p_attr_req->data );
            break;

        default:
            status = WICED_BT_GATT_SUCCESS;
            break;
    }

    return status;
}

The ble_app_gatt_event_handler() function is called after BT stack initialization to handle GATT events from the BT stack. The function returns the GATT status wiced_bt_gatt_status_t with different GATT codes. For example, WICED_BT_GATT_INVALID_HANDLE is returned with value '1' indicating an invalid handle. For the complete list of codes, see wiced_bt_gatt.h. The GATT_CONNECTION_STATUS_EVT event is triggered when the GATT connection status is changed. THe function ble_app_connect_callback() will be called to check the connection status with a particular connection ID. The GATT_ATTRIBUTE_REQUEST_EVT event is called when a GATT read event GATTS_REQ_TYPE_READ or a GATT write event GATTS_REQ_TYPE_WRITE occurs. These events are handled by function ble_app_server_callback(). ble_app_get_value() and ble_app_set_value() functions are called accordingly based on the requests type.

User Interface (app_user_interface.c)

This file contains two almost identical blocks of code, to control the Advertising State LED and the Alert Level indication LED. The only difference between the two blocks are the input states based on the which the OFF, ON, or Blinking states of the LEDs are decided.

void app_user_interface_init(void)
{
    wiced_init_timer(&adv_led_timer, adv_led_timer_cb, 0, WICED_MILLI_SECONDS_PERIODIC_TIMER);
    wiced_init_timer(&ias_led_timer, ias_led_timer_cb, 0, WICED_MILLI_SECONDS_PERIODIC_TIMER);
}

The app_user_interface_init() function initializes one timer to be used by the advertising state LED and another timer to be used by the IAS alert level LED. The wiced_init_timer() function uses a timer callback function adv_led_timer_cb(), which toggles the state of the adv LED to indicate the state of the advertising LED or toggles the state of the IAS LED to indicate the mid alert level.

adv_led_update()

void adv_led_update(void)
{
    wiced_stop_timer(&adv_led_timer);

    adv_timer_stopped_flag = WICED_TRUE;

    switch(app_bt_adv_conn_state)
    {
        case APP_BT_ADV_OFF_CONN_OFF:
            wiced_hal_gpio_set_pin_output(ADV_LED_GPIO, LED_OFF);
            break;

        case APP_BT_ADV_ON_CONN_OFF:
            wiced_start_timer(&adv_led_timer, ADV_LED_UPDATE_RATE_MS);
            adv_timer_stopped_flag = WICED_FALSE;
            break;

        case APP_BT_ADV_OFF_CONN_ON:
            wiced_hal_gpio_set_pin_output(ADV_LED_GPIO, LED_ON);
            break;

        default:
            /* LED OFF for unexpected states */
            wiced_hal_gpio_set_pin_output(ADV_LED_GPIO, LED_OFF);
            break;
    }
}

The timer is stopped using wiced_stop_timer() and the adv_timer_stopped_flag is set to prevent any pending timer callback to change the state of the LED. APP_BT_ADV_OFF_CONN_OFF event indicates that there is no advertisement or connection. The APP_BT_ADV_ON_CONN_OFF event indicates that the device is advertising but connection has not been established. The APP_BT_ADV_OFF_CONN_ON event indicates that a connection has been established with the peer device and it is in the connected state. Similarly, ias_led_update() is called for controlling the IAS LED depending on different alert levels received. The states for the IAS are IAS_ALERT_LEVEL_LOW, IAS_ALERT_LEVEL_MID and IAS_ALERT_LEVEL_HIGH.

User-Defined Callback Function

static void adv_led_timer_cb(uint32_t arg)
{
    if(!adv_timer_stopped_flag)
    {
        if(wiced_hal_gpio_get_pin_output(ADV_LED_GPIO) == LED_OFF)
        {
            wiced_hal_gpio_set_pin_output(ADV_LED_GPIO, LED_ON);
        }
        else
        {
            wiced_hal_gpio_set_pin_output(ADV_LED_GPIO, LED_OFF);
        }
    }
}

adv_led_timer_cb() is a user-defined callback function for toggling the LED state to indicate the advertising state of the device by blinking the LED. In a similar way, ias_led_timer_cb() is called for toggling IAS LED indicating a mid-level alert.