mbed-os-examples / Mbed OS mbed-os-example-ble-HeartRate

Files at this revision

API Documentation at this revision

Comitter:
mbed_official
Date:
Mon Jan 14 10:45:44 2019 +0000
Parent:
72:584fc328cad6
Child:
74:74c41613796b
Commit message:
Merge pull request #208 from ARMmbed/mbed-os-5.11.0-oob

Mbed OS 5.11.0
.
Commit copied from https://github.com/ARMmbed/mbed-os-example-ble

Changed in this revision

mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
shields/TARGET_CORDIO_BLUENRG.lib Show annotated file Show diff for this revision Revisions of this file
source/main.cpp Show annotated file Show diff for this revision Revisions of this file
source/pretty_printer.h Show annotated file Show diff for this revision Revisions of this file
--- a/mbed-os.lib	Fri Dec 14 13:15:37 2018 +0000
+++ b/mbed-os.lib	Mon Jan 14 10:45:44 2019 +0000
@@ -1,1 +1,1 @@
-https://github.com/ARMmbed/mbed-os/#2fd0c5cfbd83fce62da6308f9d64c0ab64e1f0d6
+https://github.com/ARMmbed/mbed-os/#6a0a86538c0b9b2bfcc4583b1e2b7fea8f4e71e9
--- a/mbed_app.json	Fri Dec 14 13:15:37 2018 +0000
+++ b/mbed_app.json	Mon Jan 14 10:45:44 2019 +0000
@@ -11,6 +11,16 @@
         "DISCO_L475VG_IOT01A": {
             "target.features_add": ["BLE"],
             "target.extra_labels_add": ["CORDIO", "CORDIO_BLUENRG"]
+        },
+        "NRF52840_DK": {
+            "target.features_add": ["BLE"],
+            "target.extra_labels_add": ["CORDIO", "CORDIO_LL", "SOFTDEVICE_NONE", "NORDIC_CORDIO"],
+            "target.extra_labels_remove": ["SOFTDEVICE_COMMON", "SOFTDEVICE_S140_FULL", "NORDIC_SOFTDEVICE"]
+        },
+        "NRF52_DK": {
+            "target.features_add": ["BLE"],
+            "target.extra_labels_add": ["CORDIO", "CORDIO_LL", "SOFTDEVICE_NONE", "NORDIC_CORDIO"],
+            "target.extra_labels_remove": ["SOFTDEVICE_COMMON", "SOFTDEVICE_S132_FULL", "NORDIC_SOFTDEVICE"]
         }
     }
 }
--- a/shields/TARGET_CORDIO_BLUENRG.lib	Fri Dec 14 13:15:37 2018 +0000
+++ b/shields/TARGET_CORDIO_BLUENRG.lib	Mon Jan 14 10:45:44 2019 +0000
@@ -1,1 +1,1 @@
-https://github.com/ARMmbed/cordio-ble-x-nucleo-idb0xa1/#51f60dfea514e35e5aa13c8e24005ecadc24a9f5
+https://github.com/ARMmbed/cordio-ble-x-nucleo-idb0xa1/#811f3fea7aa8083c0bbf378e1b51a8b131d7efcc
--- a/source/main.cpp	Fri Dec 14 13:15:37 2018 +0000
+++ b/source/main.cpp	Mon Jan 14 10:45:44 2019 +0000
@@ -17,111 +17,157 @@
 #include <events/mbed_events.h>
 #include <mbed.h>
 #include "ble/BLE.h"
-#include "ble/Gap.h"
+#include "ble/gap/Gap.h"
 #include "ble/services/HeartRateService.h"
+#include "pretty_printer.h"
 
-DigitalOut led1(LED1, 1);
+const static char DEVICE_NAME[] = "Heartrate";
+
+static events::EventQueue event_queue(/* event count */ 16 * EVENTS_EVENT_SIZE);
 
-const static char     DEVICE_NAME[] = "HRM";
-static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE};
-
-static uint8_t hrmCounter = 100; // init HRM to 100bps
-static HeartRateService *hrServicePtr;
-
-static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
+class HeartrateDemo : ble::Gap::EventHandler {
+public:
+    HeartrateDemo(BLE &ble, events::EventQueue &event_queue) :
+        _ble(ble),
+        _event_queue(event_queue),
+        _led1(LED1, 1),
+        _connected(false),
+        _hr_uuid(GattService::UUID_HEART_RATE_SERVICE),
+        _hr_counter(100),
+        _hr_service(ble, _hr_counter, HeartRateService::LOCATION_FINGER),
+        _adv_data_builder(_adv_buffer) { }
 
-void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
-{
-    BLE::Instance().gap().startAdvertising(); // restart advertising
-}
+    void start() {
+        _ble.gap().setEventHandler(this);
+
+        _ble.init(this, &HeartrateDemo::on_init_complete);
+
+        _event_queue.call_every(500, this, &HeartrateDemo::blink);
+        _event_queue.call_every(1000, this, &HeartrateDemo::update_sensor_value);
+
+        _event_queue.dispatch_forever();
+    }
 
-void updateSensorValue() {
-    // Do blocking calls or whatever is necessary for sensor polling.
-    // In our case, we simply update the HRM measurement.
-    hrmCounter++;
+private:
+    /** Callback triggered when the ble initialization process has finished */
+    void on_init_complete(BLE::InitializationCompleteCallbackContext *params) {
+        if (params->error != BLE_ERROR_NONE) {
+            printf("Ble initialization failed.");
+            return;
+        }
 
-    //  100 <= HRM bps <=175
-    if (hrmCounter == 175) {
-        hrmCounter = 100;
+        print_mac_address();
+
+        start_advertising();
     }
 
-    hrServicePtr->updateHeartRate(hrmCounter);
-}
+    void start_advertising() {
+        /* Create advertising parameters and payload */
 
-void periodicCallback(void)
-{
-    led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
+        ble::AdvertisingParameters adv_parameters(
+            ble::advertising_type_t::CONNECTABLE_UNDIRECTED,
+            ble::adv_interval_t(ble::millisecond_t(1000))
+        );
 
-    if (BLE::Instance().getGapState().connected) {
-        eventQueue.call(updateSensorValue);
-    }
-}
+        _adv_data_builder.setFlags();
+        _adv_data_builder.setAppearance(ble::adv_data_appearance_t::GENERIC_HEART_RATE_SENSOR);
+        _adv_data_builder.setLocalServiceList(mbed::make_Span(&_hr_uuid, 1));
+        _adv_data_builder.setName(DEVICE_NAME);
 
-void onBleInitError(BLE &ble, ble_error_t error)
-{
-    (void)ble;
-    (void)error;
-   /* Initialization error handling should go here */
-}
+        /* Setup advertising */
+
+        ble_error_t error = _ble.gap().setAdvertisingParameters(
+            ble::LEGACY_ADVERTISING_HANDLE,
+            adv_parameters
+        );
 
-void printMacAddress()
-{
-    /* Print out device MAC address to the console*/
-    Gap::AddressType_t addr_type;
-    Gap::Address_t address;
-    BLE::Instance().gap().getAddress(&addr_type, address);
-    printf("DEVICE MAC ADDRESS: ");
-    for (int i = 5; i >= 1; i--){
-        printf("%02x:", address[i]);
-    }
-    printf("%02x\r\n", address[0]);
-}
+        if (error) {
+            printf("_ble.gap().setAdvertisingParameters() failed\r\n");
+            return;
+        }
+
+        error = _ble.gap().setAdvertisingPayload(
+            ble::LEGACY_ADVERTISING_HANDLE,
+            _adv_data_builder.getAdvertisingData()
+        );
 
-void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
-{
-    BLE&        ble   = params->ble;
-    ble_error_t error = params->error;
+        if (error) {
+            printf("_ble.gap().setAdvertisingPayload() failed\r\n");
+            return;
+        }
+
+        /* Start advertising */
 
-    if (error != BLE_ERROR_NONE) {
-        onBleInitError(ble, error);
-        return;
+        error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
+
+        if (error) {
+            printf("_ble.gap().startAdvertising() failed\r\n");
+            return;
+        }
     }
 
-    if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
-        return;
+    void update_sensor_value() {
+        if (_connected) {
+            // Do blocking calls or whatever is necessary for sensor polling.
+            // In our case, we simply update the HRM measurement.
+            _hr_counter++;
+
+            //  100 <= HRM bps <=175
+            if (_hr_counter == 175) {
+                _hr_counter = 100;
+            }
+
+            _hr_service.updateHeartRate(_hr_counter);
+        }
+    }
+
+    void blink(void) {
+        _led1 = !_led1;
     }
 
-    ble.gap().onDisconnection(disconnectionCallback);
+private:
+    /* Event handler */
 
-    /* Setup primary service. */
-    hrServicePtr = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
+    void onDisconnectionComplete(const ble::DisconnectionCompleteEvent&) {
+        _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
+        _connected = false;
+    }
+
+    virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event) {
+        if (event.getStatus() == BLE_ERROR_NONE) {
+            _connected = true;
+        }
+    }
 
-    /* Setup advertising. */
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
-    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
-    ble.gap().setAdvertisingInterval(1000); /* 1000ms */
-    ble.gap().startAdvertising();
+private:
+    BLE &_ble;
+    events::EventQueue &_event_queue;
+    DigitalOut _led1;
+
+    bool _connected;
+
+    UUID _hr_uuid;
 
-    printMacAddress();
-}
+    uint8_t _hr_counter;
+    HeartRateService _hr_service;
 
-void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
-    BLE &ble = BLE::Instance();
-    eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
+    uint8_t _adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
+    ble::AdvertisingDataBuilder _adv_data_builder;
+};
+
+/** Schedule processing of events from the BLE middleware in the event queue. */
+void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) {
+    event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents));
 }
 
 int main()
 {
-    eventQueue.call_every(500, periodicCallback);
+    BLE &ble = BLE::Instance();
+    ble.onEventsToProcess(schedule_ble_events);
 
-    BLE &ble = BLE::Instance();
-    ble.onEventsToProcess(scheduleBleEventsProcessing);
-    ble.init(bleInitComplete);
-
-    eventQueue.dispatch_forever();
+    HeartrateDemo demo(ble, event_queue);
+    demo.start();
 
     return 0;
 }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/pretty_printer.h	Mon Jan 14 10:45:44 2019 +0000
@@ -0,0 +1,95 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2018 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <mbed.h>
+#include "ble/BLE.h"
+
+inline void print_error(ble_error_t error, const char* msg)
+{
+    printf("%s: ", msg);
+    switch(error) {
+        case BLE_ERROR_NONE:
+            printf("BLE_ERROR_NONE: No error");
+            break;
+        case BLE_ERROR_BUFFER_OVERFLOW:
+            printf("BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted");
+            break;
+        case BLE_ERROR_NOT_IMPLEMENTED:
+            printf("BLE_ERROR_NOT_IMPLEMENTED: Requested a feature that isn't yet implement or isn't supported by the target HW");
+            break;
+        case BLE_ERROR_PARAM_OUT_OF_RANGE:
+            printf("BLE_ERROR_PARAM_OUT_OF_RANGE: One of the supplied parameters is outside the valid range");
+            break;
+        case BLE_ERROR_INVALID_PARAM:
+            printf("BLE_ERROR_INVALID_PARAM: One of the supplied parameters is invalid");
+            break;
+        case BLE_STACK_BUSY:
+            printf("BLE_STACK_BUSY: The stack is busy");
+            break;
+        case BLE_ERROR_INVALID_STATE:
+            printf("BLE_ERROR_INVALID_STATE: Invalid state");
+            break;
+        case BLE_ERROR_NO_MEM:
+            printf("BLE_ERROR_NO_MEM: Out of Memory");
+            break;
+        case BLE_ERROR_OPERATION_NOT_PERMITTED:
+            printf("BLE_ERROR_OPERATION_NOT_PERMITTED");
+            break;
+        case BLE_ERROR_INITIALIZATION_INCOMPLETE:
+            printf("BLE_ERROR_INITIALIZATION_INCOMPLETE");
+            break;
+        case BLE_ERROR_ALREADY_INITIALIZED:
+            printf("BLE_ERROR_ALREADY_INITIALIZED");
+            break;
+        case BLE_ERROR_UNSPECIFIED:
+            printf("BLE_ERROR_UNSPECIFIED: Unknown error");
+            break;
+        case BLE_ERROR_INTERNAL_STACK_FAILURE:
+            printf("BLE_ERROR_INTERNAL_STACK_FAILURE: internal stack faillure");
+            break;
+    }
+    printf("\r\n");
+}
+
+/** print device address to the terminal */
+inline void print_address(const Gap::Address_t &addr)
+{
+    printf("%02x:%02x:%02x:%02x:%02x:%02x\r\n",
+           addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
+}
+
+inline void print_mac_address()
+{
+    /* Print out device MAC address to the console*/
+    Gap::AddressType_t addr_type;
+    Gap::Address_t address;
+    BLE::Instance().gap().getAddress(&addr_type, address);
+    printf("DEVICE MAC ADDRESS: ");
+    print_address(address);
+}
+
+inline const char* phy_to_string(Gap::Phy_t phy) {
+    switch(phy.value()) {
+        case Gap::Phy_t::LE_1M:
+            return "LE 1M";
+        case Gap::Phy_t::LE_2M:
+            return "LE 2M";
+        case Gap::Phy_t::LE_CODED:
+            return "LE coded";
+        default:
+            return "invalid PHY";
+    }
+}