Joe Finney / Mbed 2 deprecated BLETEST

Dependencies:   BLE_API BLE_HeartRate mbed nRF51822

Fork of BLE_HeartRate by Bluetooth Low Energy

Files at this revision

API Documentation at this revision

Comitter:
finneyj
Date:
Mon Nov 30 13:37:37 2015 +0000
Parent:
76:8b36a7c45cd2
Commit message:
Repro of BLE disconnect bug under pure mbed

Changed in this revision

BLE_API.lib Show annotated file Show diff for this revision Revisions of this file
BLE_HeartRate.lib Show annotated file Show diff for this revision Revisions of this file
MicroBitAccelerometerService.cpp Show annotated file Show diff for this revision Revisions of this file
MicroBitAccelerometerService.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
nRF51822.lib Show annotated file Show diff for this revision Revisions of this file
--- a/BLE_API.lib	Thu Nov 26 14:35:42 2015 +0000
+++ b/BLE_API.lib	Mon Nov 30 13:37:37 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#3cb4b0e44d8f
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#c6c50b28ccd2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BLE_HeartRate.lib	Mon Nov 30 13:37:37 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/#3a7d497a3e03
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MicroBitAccelerometerService.cpp	Mon Nov 30 13:37:37 2015 +0000
@@ -0,0 +1,76 @@
+/**
+  * Class definition for the custom MicroBit Accelerometer Service.
+  * Provides a BLE service to remotely read the state of the accelerometer, and configure its behaviour.
+  */
+  
+#include "mbed.h"
+#include "ble/BLE.h"
+#include "ble/UUID.h"
+#include "MicroBitAccelerometerService.h"
+
+GattAttribute::Handle_t accelerometerDataCharacteristicHandleGlobal;
+
+/**
+  * Constructor. 
+  * Create a representation of the AccelerometerService
+  * @param _ble The instance of a BLE device that we're running on.
+  */
+MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) : 
+        ble(_ble) 
+{
+    // Create the data structures that represent each of our characteristics in Soft Device.
+    GattCharacteristic *accelerometerDataCharacteristic = new GattCharacteristic(MicroBitAccelerometerServiceDataUUID, (uint8_t *)accelerometerDataCharacteristicBuffer, 0, 
+    sizeof(accelerometerDataCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
+
+    GattCharacteristic  *accelerometerPeriodCharacteristic = new GattCharacteristic(MicroBitAccelerometerServicePeriodUUID, (uint8_t *)&accelerometerPeriodCharacteristicBuffer, 0, 
+    sizeof(accelerometerPeriodCharacteristicBuffer), 
+    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
+
+    // Initialise our characteristic values.
+    accelerometerDataCharacteristicBuffer[0] = 0;
+    accelerometerDataCharacteristicBuffer[1] = 0;
+    accelerometerDataCharacteristicBuffer[2] = 0;
+    accelerometerPeriodCharacteristicBuffer = 0;
+
+    // Set default security requirements
+    accelerometerDataCharacteristic->requireSecurity(SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM);
+    accelerometerPeriodCharacteristic->requireSecurity(SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM);
+
+    GattCharacteristic *characteristics[] = {accelerometerDataCharacteristic, accelerometerPeriodCharacteristic};
+    GattService         service(MicroBitAccelerometerServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
+
+    ble.addService(service);
+
+    accelerometerDataCharacteristicHandle = accelerometerDataCharacteristic->getValueHandle();
+    accelerometerDataCharacteristicHandleGlobal = accelerometerDataCharacteristic->getValueHandle();
+    accelerometerPeriodCharacteristicHandle = accelerometerPeriodCharacteristic->getValueHandle();
+
+    ble.gattServer().write(accelerometerDataCharacteristicHandle,(uint8_t *)accelerometerDataCharacteristicBuffer, sizeof(accelerometerDataCharacteristicBuffer));
+    ble.gattServer().write(accelerometerPeriodCharacteristicHandle, (const uint8_t *)&accelerometerPeriodCharacteristicBuffer, sizeof(accelerometerPeriodCharacteristicBuffer));
+
+    ble.onDataWritten(this, &MicroBitAccelerometerService::onDataWritten);
+}
+
+/**
+  * Callback. Invoked when any of our attributes are written via BLE.
+  */
+void MicroBitAccelerometerService::onDataWritten(const GattWriteCallbackParams *params)
+{   
+    if (params->handle == accelerometerPeriodCharacteristicHandle && params->len >= sizeof(accelerometerPeriodCharacteristicBuffer))
+    {
+        accelerometerPeriodCharacteristicBuffer = *((uint16_t *)params->data);
+    }
+}
+
+const uint8_t  MicroBitAccelerometerServiceUUID[] = {
+    0xe9,0x5d,0x07,0x53,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
+};
+
+const uint8_t  MicroBitAccelerometerServiceDataUUID[] = {
+    0xe9,0x5d,0xca,0x4b,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
+};
+
+const uint8_t  MicroBitAccelerometerServicePeriodUUID[] = {
+    0xe9,0x5d,0xfb,0x24,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MicroBitAccelerometerService.h	Mon Nov 30 13:37:37 2015 +0000
@@ -0,0 +1,48 @@
+#ifndef MICROBIT_ACCELEROMETER_SERVICE_H
+#define MICROBIT_ACCELEROMETER_SERVICE_H
+
+extern GattAttribute::Handle_t accelerometerDataCharacteristicHandleGlobal;
+
+// UUIDs for our service and characteristics
+extern const uint8_t  MicroBitAccelerometerServiceUUID[];
+extern const uint8_t  MicroBitAccelerometerServiceDataUUID[];
+extern const uint8_t  MicroBitAccelerometerServicePeriodUUID[];
+
+
+/**
+  * Class definition for a MicroBit BLE Accelerometer Service.
+  * Provides access to live accelerometer data via BLE, and provides basic configuration options.
+  */
+class MicroBitAccelerometerService
+{                                    
+    public:
+    
+    /**
+      * Constructor. 
+      * Create a representation of the AccelerometerService
+      * @param _ble The instance of a BLE device that we're running on.
+      */
+    MicroBitAccelerometerService(BLEDevice &_ble);  
+    
+
+    private:
+
+    /**
+      * Callback. Invoked when any of our attributes are written via BLE.
+      */
+    void onDataWritten(const GattWriteCallbackParams *params);
+
+    // Bluetooth stack we're running on.
+    BLEDevice           &ble;
+
+    // memory for our 8 bit control characteristics.
+    uint16_t            accelerometerDataCharacteristicBuffer[3];
+    uint16_t            accelerometerPeriodCharacteristicBuffer;
+
+    // Handles to access each characteristic when they are held by Soft Device.
+    GattAttribute::Handle_t accelerometerDataCharacteristicHandle;
+    GattAttribute::Handle_t accelerometerPeriodCharacteristicHandle;
+};
+
+
+#endif
--- a/main.cpp	Thu Nov 26 14:35:42 2015 +0000
+++ b/main.cpp	Mon Nov 30 13:37:37 2015 +0000
@@ -16,21 +16,23 @@
 
 #include "mbed.h"
 #include "ble/BLE.h"
-#include "ble/services/HeartRateService.h"
-#include "ble/services/BatteryService.h"
 #include "ble/services/DeviceInformationService.h"
-
-DigitalOut led1(LED1);
+#include "MicroBitAccelerometerService.h"
+#include "nrf_soc.h"
 
-const static char     DEVICE_NAME[]        = "HRM1";
-static const uint16_t uuid16_list[]        = {GattService::UUID_HEART_RATE_SERVICE,
-                                              GattService::UUID_DEVICE_INFORMATION_SERVICE};
-static volatile bool  triggerSensorPolling = false;
+const char* DEVICE_NAME = "BBC micro:bit [zevug]";
+const char* MICROBIT_BLE_MANUFACTURER = "The Cast of W1A";
+const char* MICROBIT_BLE_MODEL = "BBC micro:bit";
+const char* MICROBIT_BLE_HARDWARE_VERSION = "1.0";
+const char* MICROBIT_BLE_FIRMWARE_VERSION = "BODGE";
+const char* MICROBIT_BLE_SOFTWARE_VERSION = "1.0";
 
-uint8_t hrmCounter = 100; // init HRM to 100bps
+#define MICROBIT_BLE_ENABLE_BONDING     true
+#define MICROBIT_BLE_REQUIRE_MITM       true
 
-HeartRateService         *hrService;
+MicroBitAccelerometerService *accelService;
 DeviceInformationService *deviceInfo;
+Serial pc(USBTX, USBRX);
 
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
 {
@@ -39,11 +41,23 @@
 
 void periodicCallback(void)
 {
-    led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
+    pc.printf(".");
+    wait_ms(3);
+}
 
-    /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
-     * heavy-weight sensor polling from the main thread. */
-    triggerSensorPolling = true;
+static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey)
+{
+    pc.printf("\nPASSKEY: ");
+    
+    for (int i = 0; i<SecurityManager::PASSKEY_LEN; i++)
+        pc.printf("%c", passkey[i]);
+
+    pc.printf("\n");
+}
+
+static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status)
+{
+    pc.printf("paring complete\n");
 }
 
 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
@@ -57,51 +71,98 @@
 
     ble.gap().onDisconnection(disconnectionCallback);
 
-    /* Setup primary service. */
-    hrService = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
+    // Setup our security requirements.
+    ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback);
+    ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
+    ble.securityManager().init(MICROBIT_BLE_ENABLE_BONDING, MICROBIT_BLE_REQUIRE_MITM, SecurityManager::IO_CAPS_DISPLAY_ONLY);
 
     /* Setup auxiliary service. */
-    deviceInfo = new DeviceInformationService(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
+    deviceInfo = new DeviceInformationService (ble, MICROBIT_BLE_MANUFACTURER, MICROBIT_BLE_MODEL, "SN1", MICROBIT_BLE_HARDWARE_VERSION, MICROBIT_BLE_FIRMWARE_VERSION, MICROBIT_BLE_SOFTWARE_VERSION);
+
+    /* Setup primary service. */
+    accelService = new MicroBitAccelerometerService(ble);
+
+    // Configure for high speed mode where possible.
+    Gap::ConnectionParams_t fast;
+    ble.getPreferredConnectionParams(&fast);
+    fast.minConnectionInterval = 8; // 10 ms
+    fast.maxConnectionInterval = 16; // 20 ms
+    fast.slaveLatency = 0;
+    ble.setPreferredConnectionParams(&fast);
 
     /* 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();
+    //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(200); /* 1000ms */
+    //ble.gap().startAdvertising();
+
+    // Setup advertising.
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, strlen(DEVICE_NAME));
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.setAdvertisingInterval(40);
+    ble.startAdvertising();  
 }
 
 int main(void)
 {
-    led1 = 1;
     Ticker ticker;
-    ticker.attach(periodicCallback, 1); // blink LED every second
+    
+    pc.baud(115200);
+    
+    ticker.attach(periodicCallback, 0.006); // 6ms
 
     BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
     ble.init(bleInitComplete);
 
     /* SpinWait for initialization to complete. This is necessary because the
      * BLE object is used in the main loop below. */
-    while (ble.hasInitialized()  == false) { /* spin loop */ }
+    while (ble.hasInitialized() == false) { /* spin loop */ }
+ 
+    // TEST
+ 
+    uint16_t i=0;
+    uint16_t accelerometerDataCharacteristicBuffer[3];
+
+    // Disable all the contents of the ISR.
+    //uBit.systemTicker.detach();
 
-    // infinite loop
-    while (1) {
-        // check for trigger from periodicCallback()
-        if (triggerSensorPolling && ble.getGapState().connected) {
-            triggerSensorPolling = false;
+    for (int irq = 0; irq < 23; irq++)
+        sd_nvic_SetPriority((IRQn_Type)irq, 3);
+    
+    while(1)
+    {   
+        /*
+        if (i % 500 == 0)
+        {
+            int sp = (int) __get_MSP();
+            uBit.serial.printf("MSP: 0x%.8x\n", sp);
 
-            // Do blocking calls or whatever is necessary for sensor polling.
-            // In our case, we simply update the HRM measurement.
-            hrmCounter++;
-            if (hrmCounter == 175) { //  100 <= HRM bps <=175
-                hrmCounter = 100;
+            uint32_t pm = __get_PRIMASK();
+            uBit.serial.printf("PG: 0x%.8x\n", pm);
+        
+            nrf_app_irq_priority_t pri;
+            
+            for (int irq = 0; irq <= 25; irq++)
+            {
+                sd_nvic_GetPriority((IRQn_Type)irq, &pri);
+                uBit.serial.printf("irq: %2d priority: %d\n", irq, pri);
             }
 
-            hrService->updateHeartRate(hrmCounter);
-        } else {
-            ble.waitForEvent(); // low power wait for event
+        }
+        */
+
+        wait_ms(20);
+        accelerometerDataCharacteristicBuffer[0] = i;
+        i++;
+        
+        if (ble.getGapState().connected)
+        {
+            ble.gattServer().write(accelerometerDataCharacteristicHandleGlobal,(uint8_t *)accelerometerDataCharacteristicBuffer, sizeof(accelerometerDataCharacteristicBuffer));
         }
     }
 }
+
--- a/mbed.bld	Thu Nov 26 14:35:42 2015 +0000
+++ b/mbed.bld	Mon Nov 30 13:37:37 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/9296ab0bfc11
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/165afa46840b
\ No newline at end of file
--- a/nRF51822.lib	Thu Nov 26 14:35:42 2015 +0000
+++ b/nRF51822.lib	Mon Nov 30 13:37:37 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#5de80a383c85
+http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#1762975cb3cb