Combines a working system to save force, acceleration and gyro data to an SD card in a MAX32630 with BLE_Heartrate taken from the mbed site.

Dependencies:   USBMSD_BD BMI160 HX711 max32630fthr USBDevice

Revision:
73:633b44bce5fc
Parent:
43:fb2855f7754b
Child:
80:caccea4da07b
--- 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;
 }
+