Paul Russell / Mbed 2 deprecated bleIOv04_pr

Dependencies:   BLE_API mbed nRF51822

Files at this revision

API Documentation at this revision

Comitter:
prussell
Date:
Wed Dec 10 16:54:58 2014 +0000
Child:
1:4a25d917fb6a
Commit message:
Initial, Imported from PR's bleHRMv02

Changed in this revision

BLE_API.lib 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BLE_API.lib	Wed Dec 10 16:54:58 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#98f930d14515
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Dec 10 16:54:58 2014 +0000
@@ -0,0 +1,235 @@
+//=========Header (PR)
+// blePRv04, Initial: 20141210 Paul Russell (mbed user: prussell = PR)
+// This sample includes code from several projects found on http://developer.mbed.org, including but not limited to:
+//    - http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/
+//    - https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LoopbackUART/
+//    - miscellaneous adopted from more samples...
+// Reference:
+//    - http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/
+//    - Reference: http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/docs/tip/
+//    - Reference: http://developer.mbed.org/teams/Bluetooth-Low-Energy/
+// Warnings:
+//    - As of 20141210 it is necessary to use Android App [nRF-Master Control Panel] to ensure any previous connected 
+//      code on mkit is properly Disconnected before trying to connect other Android nRF Apps (nRFToolbox, nRF UART 2.0, etc.).
+//      As UART device doesn't offer disconnect you may need to load a 3rf sample, then connect, then discoonect, to clear the link.
+// Notes: 
+//    - onDataSent() maybe only occuring when confirmed receive by phone, as onDataSent() didn't happen when phone moved out of range.
+//    - onDisconnect(Reason:8) occured after ~20Tx with no onDataSent() after phone moved out of range, OnTimeout didn't occur at all.
+// ToDo: and ToCheck:
+//    - Re-check where voltatile needed
+//==========End of PR's Header
+
+//==========Historic Licencing from original imported sample from mbed website [BLE_HeartRate] ==========
+//From: http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 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. */
+//==========end of Historic Licencing ==========
+
+
+//==========Compile Options==========
+#define ENABLE_SerialUSB_DEBUG_CONSOLE                  1  //PR: Enable Debug on mbed's USB Serial Debug, Setup: Serial 9600,8,N,1,NoFlowControl (TeraTerm: http://en.sourceforge.jp/projects/ttssh2/releases/)
+#define UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL    0  //PR: Option to slow the connection intervsal possibly saving power (After Connected)
+
+//==========Includes==========
+#include "mbed.h"
+#include "BLEDevice.h"
+
+//Services
+#include "BatteryService.h"
+#include "DeviceInformationService.h"
+//#include "DFUService"                 //TODO: DFU and FOTA Support
+//#include "HealthThermometerService.h" //TODO: Temperature, #include "ble_hts.h"
+#include "HeartRateService.h"
+//#include "UARTService.h"              //TODO: Add a UART Channel for streaming data like logs?
+
+//==========Debug Console==========
+#if ENABLE_SerialUSB_DEBUG_CONSOLE
+    Serial  debug_serial(USBTX, USBRX); //PR: DebugSerialOverMbedUSB 9600-8N1N
+    #define DEBUG(...) { debug_serial.printf(__VA_ARGS__); }
+#else
+    #define DEBUG(...)            //Do Nothing
+#endif 
+
+//==========LEDs==========
+//LEDs:
+//DigitalOut  out_led1(LED1);             //PR: Firmware heartbeat
+//DigitalOut  out_led2(LED2);             //PR: Firmware heartbeat
+PwmOut      pwm_led1(LED1);             //PR: Firmware Life Indicator 
+PwmOut      pwm_led2(LED2);             //TODO: Controlled by App 
+float       f_led1level = 0.0;          //Initial Brightness (Typically 0.0~0.5)
+float       f_led2level = 0.0;          //Initial Brightness (Typically 0.0~0.5)
+
+//==========BLE==========
+BLEDevice   ble;
+const static char     pcDeviceName[]    = "blePRv04"; //PR: Why can App nRF-MCP modify this even though flagged as Const, maybe only temporary mod till App restarts?
+static const uint16_t uuid16_list[]     = { //Service List (Pre-defined standard 16bit services)
+    //BLE_UUID_GAP  UUID_GENERIC_ACCESS             //0x1800    //Included by Default, DeviceName, Appearance, PreferredConnectionParam
+    //BLE_UUID_GATT UUID_GENERIC ATTRIBUTE          //0x1801    //Included by Default, ServiceChanged, 
+    GattService::UUID_HEART_RATE_SERVICE,           //0x180D    //HRM, BosyLocation,ControlPoint
+    GattService::UUID_BATTERY_SERVICE,              //0x180F    //BatteryLevel
+    GattService::UUID_DEVICE_INFORMATION_SERVICE};  //0x180A    //sManufacturer, sModelNumber, sSerialNumber, sHWver, sFWver, sSWver
+
+//==========Functions:Timer==========
+static volatile bool  b_Ticker1 = false;//Volatile, don't optimize, changes under interrupt control
+void CallbackTicker1(void)
+{
+    static uint32_t    u32_Counter; // Counter for Debug Output
+
+    //pwm_led1 = !pwm_led1; /* Do blinky on LED1 while we're waiting for BLE events */
+    f_led1level+=0.1; if (f_led1level>0.5){f_led1level = 0.1;}; pwm_led1=f_led1level;//PR: Ramp Blink
+    DEBUG("\nBLEi: Ticker1(%u) ", ++u32_Counter);
+    b_Ticker1 = true;   //PR: Flag to handle Ticker1 Event in Main loop so interupts not blocked.
+}
+
+//==========Functions:BLE==========
+void Callback_BLE_onTimeout(void)
+{
+    DEBUG("\nBLEi: Callback_BLE_onTimeout()\n" );
+    //PR: Haven't seen this, even when phone moved out of range and OnDisconnect(Reason0x08) occurs
+  
+    //DEBUG("\nBLE:Callback_BLE_onTimeout(), Restarting Advertising\n" );
+    //ble.startAdvertising();
+}
+
+//void  onDisconnection (Gap::DisconnectionEventCallback_t disconnectionCallback) 
+void Callback_BLE_onDisconnect(Gap::Handle_t tHandle, Gap::DisconnectionReason_t eReason)
+{
+    //PR: onDisconnect(Reason:8) occured after ~20Tx with no onDataSent() after phone moved out of range
+
+    //   REMOTE_USER_TERMINATED_CONNECTION = 0x13 = 19,
+    //   LOCAL_HOST_TERMINATED_CONNECTION  = 0x16 = 22,
+    //   CONN_INTERVAL_UNACCEPTABLE        = 0x3B = 59,
+    DEBUG("\nBLEi: Callback_BLE_Disconnect(Handle:%d, eReason:0x%02x), Restarting Advertising\n",tHandle,eReason );//PR: Occurs properly when click disconnect in App nRFToolbox:HRM
+
+    //DEBUG("Wait10sec...\n");wait(10.0); //PR: Optional to test effect on advertising
+    ble.startAdvertising(); // restart advertising
+}
+
+//inline void BLEDevice::onConnection(Gap::ConnectionEventCallback_t connectionCallback){ transport->getGap().setOnConnection(connectionCallback);}
+void Callback_BLE_onConnect(Gap::Handle_t tHandle, Gap::addr_type_t ePeerAddrType, const Gap::address_t c6PeerAddr, const Gap::ConnectionParams_t *params)
+{
+    DEBUG("\nBLEi: Callback_BLE_Connect(Handle:%d, eType:%d, Add:%u ...)\n", tHandle, ePeerAddrType, c6PeerAddr);
+
+    #if UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL
+        /* Updating connection parameters can be attempted only after a connection has been
+         * established. Please note that the ble-Central is still the final arbiter for
+         * the effective parameters; the peripheral can only hope that the request is
+         * honored. Please also be mindful of the constraints that might be enforced by
+         * the BLE stack on the underlying controller.*/
+        #define MIN_CONN_INTERVAL 250  /**< Minimum connection interval (250 ms) */
+        #define MAX_CONN_INTERVAL 350  /**< Maximum connection interval (350 ms). */
+        #define CONN_SUP_TIMEOUT  6000 /**< Connection supervisory timeout (6 seconds). */
+        #define SLAVE_LATENCY     4
+
+        Gap::ConnectionParams_t tGap_conn_params;
+        tGap_conn_params.minConnectionInterval        = Gap::MSEC_TO_GAP_DURATION_UNITS(MIN_CONN_INTERVAL);
+        tGap_conn_params.maxConnectionInterval        = Gap::MSEC_TO_GAP_DURATION_UNITS(MAX_CONN_INTERVAL);
+        tGap_conn_params.connectionSupervisionTimeout = Gap::MSEC_TO_GAP_DURATION_UNITS(CONN_SUP_TIMEOUT);
+        tGap_conn_params.slaveLatency                 = SLAVE_LATENCY;
+        ble.updateConnectionParams(tHandle, &tGap_conn_params);
+    #endif /* #if UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL */
+}
+
+static volatile bool bSent = false; //Volatile, don't optimize, changes under interrupt control
+static volatile unsigned uSentBLE;
+void Callback_BLE_onDataSent(unsigned uSent){
+    uSentBLE=uSent;
+    DEBUG("BLEi: SentI %ubytes", uSent); //TODO: PR: Why uSent always "1", expected it to match sent bytes length
+    bSent = true;
+    //PR: onDataSent() maybe only occuring when confirmed receive by phone, as onDataSent() didn't happen when phone moved out of range.
+}
+
+void Callback_BLE_onDataWritten(const GattCharacteristicWriteCBParams *pParams)
+{
+    // Callback_BLE_onDataWritten == This does occur when use nRF-MCP to save New Heart Rate Control Point (Ignored if incorrect length)
+
+    //Warning: *data may not be NULL terminated
+    DEBUG("\nBLEi: Callback_BLE_onDataWritten(Handle:%d, eOp:%d, uOffset:%u uLen:%u Data0[0x%02x]=Data[%*s]\n", pParams->charHandle, pParams->op, pParams->offset, pParams->len, (char)(pParams->data[0]), pParams->len, pParams->data);
+}
+
+void Callback_BLE_onUpdatesEnabled(Gap::Handle_t tHandle)
+{
+    DEBUG("\nBLEi: Callback_BLE_onUpdates(Handle:%d)\r\n", tHandle);
+}
+
+//==========main==========
+int main(void)
+{
+    f_led1level = 1; pwm_led1 = f_led1level;//Start LED1=OnMax
+    f_led2level = 1; pwm_led2 = f_led2level;//Start LED2=OnMax
+    DEBUG("\nBLE:___%s___\nConnect App for Data: nRF-MCP, nRF-Toolbox:HRM, etc.\n", pcDeviceName); //Restart TeraTerm just before Pressing Reset on mbed
+
+    Ticker ticker1;                             //PR: Timer Object(Structure)
+    //ticker1.attach(CallbackTicker1, 1.0);       //PR: Timer Handler, Float=PeriodSeconds
+    ticker1.attach(CallbackTicker1, 2.0);       //PR: Timer Handler, Float=PeriodSeconds
+    //ticker1.attach(CallbackTicker1, 5.0);       //PR: Timer Handler, Float=PeriodSeconds
+
+    //Initialize BLE Service (and event actions)
+    ble.init();
+    ble.onDisconnection(Callback_BLE_onDisconnect);
+    ble.onConnection(Callback_BLE_onConnect); //PR: Not required if no actions enabled, enabled now just for debug printf()
+    ble.onDataSent(Callback_BLE_onDataSent);
+    ble.onDataWritten(Callback_BLE_onDataWritten);
+    ble.onTimeout(Callback_BLE_onTimeout);
+    ble.onUpdatesEnabled(Callback_BLE_onUpdatesEnabled);
+
+//ble_error_t readCharacteristicValue  ( uint16_t  handle,    uint8_t *const  buffer,    uint16_t *const  lengthP  ) 
+//ble_error_t  updateCharacteristicValue (uint16_t handle, const uint8_t *value, uint16_t size, bool localOnly=false) 
+
+    /* Setup primary service. */
+    uint8_t u8LoopCounter = 100;
+    HeartRateService hrService(ble, u8LoopCounter, HeartRateService::LOCATION_FINGER); //Start the service for BLE:HRM
+
+    /* Setup auxiliary services. */
+    BatteryService   battery(ble); //Start the service for BLE:Battery
+    DeviceInformationService deviceInfo(ble, "Maker", pcDeviceName, "sn1234", "hw00", "fw00", "sw00");//Start the service for BLE:DeviceInfo
+    //                              (BLEDevice), pcManufacturer, pcModelNumber, pcSerialNumber, pcHWver, pcFWver, pcSWver
+
+    /* Setup advertising. */
+    ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); //PR: Advertise 1sec (1Hz)
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //PR: TODO
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); //PR: BLE Only, Options(LE_GENERAL_DISCOVERABLE/LE_LIMITED_DISCOVERABLE)
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); //PR: Might need to change for Custom Services/Characteristics
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);//PR: TODO: Change to: UNKNOWN or custom
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)pcDeviceName, sizeof(pcDeviceName));//PR: Product?
+    ble.startAdvertising();
+
+    DEBUG("BLE: Main Loop\n");
+
+    uint32_t u32_wakeevents=0, u32_wakelast=0; // Counter&Register for tracking Wake Events (to see monitor their Frequency)
+    while (true) {
+        if (b_Ticker1 && ble.getGapState().connected) { //If Ticker1 and Connected Update Data
+            b_Ticker1 = false; // Clear flag for next Ticker1, see CallbackTicker1()
+
+            /* Handle sensor polling == Simulate Data */
+            u8LoopCounter++;
+            if (u8LoopCounter >= 175) {
+                u8LoopCounter = 100;
+                DEBUG("BLE: HRM Rollover175->100 ", u8LoopCounter);
+            }
+            DEBUG("BLE: HRM:%u, Wakes:%u Delta:%d ", u8LoopCounter, u32_wakeevents, u32_wakeevents-u32_wakelast); u32_wakelast=u32_wakeevents; 
+            hrService.updateHeartRate(u8LoopCounter);
+        } else if (b_Ticker1) {
+            b_Ticker1 = false; // Clear flag for next Ticker1, see CallbackTicker1()
+            DEBUG("BLE: Tick while unconnected ", u8LoopCounter);
+        } else if (bSent){
+            bSent=false; //clear flag
+            //DEBUG("BLE:Sent %ubytes ", uSentBLE);
+        } else {
+            //DEBUG("BLE:Wait for Event\n\r"); //x Debug output here causes unnecessary wakes resulting in endless awakes.    
+            ble.waitForEvent(); //PR: Wait for event - Yield control to BLE Stack and other events (Process ALL pending events before waiting again)
+            f_led2level+=0.25; if (f_led2level>0.5){f_led2level = 0.0;}; pwm_led2=f_led2level;//PR: Ramp Blink
+            u32_wakeevents++;   //PR: Count events for frequency monitoring (20141207PR: nRF51822 mbed HRM = 50Hz)
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Dec 10 16:54:58 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/4fc01daae5a5
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF51822.lib	Wed Dec 10 16:54:58 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#cdcc094ab166