Experimental BLE project showing how IO can be made with an App over BLE. Pointer to matching App will be added when ready, initially this works with: - Android App [nRF-Master Control Panel], supports Write,Read,Notify - Android Project [BluetoothLeGatt]

Dependencies:   BLE_API mbed nRF51822

This is an experimental project for BLE (Bluetooth LE == Bluetooth Low Energy == Bluetooth Smart).

  • It supports general IO over BLE with Read/Notify/Write support.
  • It is compatible with FOTA using Android App "nRF Master Control Panel" (20150126)
  • IO supported by:
    • Custom Android App is in the WIKI under: Android-App, developed from Android Sample "BluetoothLeGatt"
    • Android App: nRF-MCP (Master Control Panel)
    • iOS App LightBlue.
    • General HRM, HTM, Battery and similar apps should be able to access the matching services.
  • It includes combinations of code from other projects, alternative code included can be tried by moving comments (, //)
  • 20150126 bleIO r25: It compiles for both "Nordic nRF51822" and "Nordic nRF51822 FOTA" platforms
  • 20150126 The matching bleIO App (in wiki) doesn't support FOTA yet, use Android App "nRF Master Control Panel"

Feedback and ideas greatly appreciated!!!

Committer:
prussell
Date:
Tue Dec 16 16:44:56 2014 +0000
Revision:
8:f187ba55aed2
Parent:
7:1097d012b01a
Child:
9:2d11beda333f
Changed Services to Handles, Updated Debug, OK.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
prussell 0:0217a862b047 1 //=========Header (PR)
prussell 0:0217a862b047 2 // blePRv04, Initial: 20141210 Paul Russell (mbed user: prussell = PR)
prussell 0:0217a862b047 3 // This sample includes code from several projects found on http://developer.mbed.org, including but not limited to:
prussell 0:0217a862b047 4 // - http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/
prussell 0:0217a862b047 5 // - https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LoopbackUART/
prussell 1:4a25d917fb6a 6 // - https://developer.mbed.org/users/takafuminaka/code/BLE_HTM_by_InTempSensr/
prussell 6:5b6fb35b4450 7 // - https://developer.mbed.org/users/garimagupta002/notebook/ble-uart-lcd-demo/ (Advertise UUID16+UUID128)
prussell 0:0217a862b047 8 // - miscellaneous adopted from more samples...
prussell 0:0217a862b047 9 // Reference:
prussell 0:0217a862b047 10 // - http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/
prussell 0:0217a862b047 11 // - Reference: http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/docs/tip/
prussell 0:0217a862b047 12 // - Reference: http://developer.mbed.org/teams/Bluetooth-Low-Energy/
prussell 0:0217a862b047 13 // Warnings:
prussell 0:0217a862b047 14 // - As of 20141210 it is necessary to use Android App [nRF-Master Control Panel] to ensure any previous connected
prussell 0:0217a862b047 15 // code on mkit is properly Disconnected before trying to connect other Android nRF Apps (nRFToolbox, nRF UART 2.0, etc.).
prussell 0:0217a862b047 16 // As UART device doesn't offer disconnect you may need to load a 3rf sample, then connect, then discoonect, to clear the link.
prussell 0:0217a862b047 17 // Notes:
prussell 0:0217a862b047 18 // - onDataSent() maybe only occuring when confirmed receive by phone, as onDataSent() didn't happen when phone moved out of range.
prussell 0:0217a862b047 19 // - onDisconnect(Reason:8) occured after ~20Tx with no onDataSent() after phone moved out of range, OnTimeout didn't occur at all.
prussell 0:0217a862b047 20 // ToDo: and ToCheck:
prussell 8:f187ba55aed2 21 // - Handle All return codes for all functions not void, including BLE not BLE_ERROR_NONE, as a minimum output some debug and log event in non-volatile memory for diagnostics.
prussell 0:0217a862b047 22 // - Re-check where voltatile needed
prussell 8:f187ba55aed2 23 // - Evaluate setting: IS_SRVC_CHANGED_CHARACT_PRESENT, see: https://devzone.nordicsemi.com/question/22751/nrftoobox-on-android-not-recognizing-changes-in-application-type-running-on-nordic-pcb/?answer=23097#post-id-23097
prussell 8:f187ba55aed2 24 //
prussell 0:0217a862b047 25 //==========End of PR's Header
prussell 0:0217a862b047 26
prussell 0:0217a862b047 27 //==========Historic Licencing from original imported sample from mbed website [BLE_HeartRate] ==========
prussell 0:0217a862b047 28 //From: http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/
prussell 0:0217a862b047 29 /* mbed Microcontroller Library
prussell 0:0217a862b047 30 * Copyright (c) 2006-2013 ARM Limited
prussell 0:0217a862b047 31 *
prussell 0:0217a862b047 32 * Licensed under the Apache License, Version 2.0 (the "License");
prussell 0:0217a862b047 33 * you may not use this file except in compliance with the License.
prussell 0:0217a862b047 34 * You may obtain a copy of the License at
prussell 0:0217a862b047 35 * http://www.apache.org/licenses/LICENSE-2.0
prussell 0:0217a862b047 36 * Unless required by applicable law or agreed to in writing, software
prussell 0:0217a862b047 37 * distributed under the License is distributed on an "AS IS" BASIS,
prussell 0:0217a862b047 38 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
prussell 0:0217a862b047 39 * See the License for the specific language governing permissions and
prussell 0:0217a862b047 40 * limitations under the License. */
prussell 0:0217a862b047 41 //==========end of Historic Licencing ==========
prussell 0:0217a862b047 42
prussell 0:0217a862b047 43
prussell 0:0217a862b047 44 //==========Compile Options==========
prussell 0:0217a862b047 45 #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/)
prussell 0:0217a862b047 46 #define UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL 0 //PR: Option to slow the connection intervsal possibly saving power (After Connected)
prussell 0:0217a862b047 47
prussell 0:0217a862b047 48 //==========Includes==========
prussell 0:0217a862b047 49 #include "mbed.h"
prussell 1:4a25d917fb6a 50 #include "BLEDevice.h" // BLE
prussell 1:4a25d917fb6a 51 #include "nrf_soc.h" // nRF Internal Temperature Sensor
prussell 0:0217a862b047 52
prussell 0:0217a862b047 53 //Services
prussell 0:0217a862b047 54 #include "BatteryService.h"
prussell 0:0217a862b047 55 #include "DeviceInformationService.h"
prussell 5:d36bbb315e31 56 #include "HealthThermometerService.h"
prussell 0:0217a862b047 57 #include "HeartRateService.h"
prussell 5:d36bbb315e31 58 #include "LinkLossService.h" //TODO: How support this?
prussell 8:f187ba55aed2 59 //#include "DFUService" //TODO: DFU and FOTA Support
prussell 0:0217a862b047 60 //#include "UARTService.h" //TODO: Add a UART Channel for streaming data like logs?
prussell 0:0217a862b047 61
prussell 0:0217a862b047 62 //==========Debug Console==========
prussell 0:0217a862b047 63 #if ENABLE_SerialUSB_DEBUG_CONSOLE
prussell 6:5b6fb35b4450 64 //Restart TeraTerm just before Pressing Reset on mbed, Default:9600-8N1(No Flow Control)
prussell 6:5b6fb35b4450 65 //Using default baud rate to avoid issues with DEBUG in a constructor being at wrong baud rate before main()
prussell 6:5b6fb35b4450 66 Serial debug_serial(USBTX, USBRX); //PR: DebugSerialOverMbedUSB
prussell 0:0217a862b047 67 #define DEBUG(...) { debug_serial.printf(__VA_ARGS__); }
prussell 0:0217a862b047 68 #else
prussell 6:5b6fb35b4450 69 #define DEBUG(...) //Do Nothing, DEBUG() lines are ignored
prussell 0:0217a862b047 70 #endif
prussell 0:0217a862b047 71
prussell 2:c77c2b06d604 72 //========== This Section is to Create Debug output showing variable prep before main() ==========
prussell 2:c77c2b06d604 73 bool u8_prep_dummy(void) {
prussell 6:5b6fb35b4450 74 DEBUG("\n\nBLE: ____Prep Memory____\n"); //May comment this out if none of the following Objects/Classes call initiator functions with debug
prussell 2:c77c2b06d604 75 return true;
prussell 2:c77c2b06d604 76 }
prussell 2:c77c2b06d604 77 const bool bPrep = u8_prep_dummy();
prussell 2:c77c2b06d604 78
prussell 0:0217a862b047 79 //==========LEDs==========
prussell 0:0217a862b047 80 //LEDs:
prussell 0:0217a862b047 81 //DigitalOut out_led1(LED1); //PR: Firmware heartbeat
prussell 0:0217a862b047 82 //DigitalOut out_led2(LED2); //PR: Firmware heartbeat
prussell 0:0217a862b047 83 PwmOut pwm_led1(LED1); //PR: Firmware Life Indicator
prussell 0:0217a862b047 84 PwmOut pwm_led2(LED2); //TODO: Controlled by App
prussell 0:0217a862b047 85 float f_led1level = 0.0; //Initial Brightness (Typically 0.0~0.5)
prussell 0:0217a862b047 86 float f_led2level = 0.0; //Initial Brightness (Typically 0.0~0.5)
prussell 0:0217a862b047 87
prussell 0:0217a862b047 88 //==========BLE==========
prussell 8:f187ba55aed2 89 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?
prussell 0:0217a862b047 90 BLEDevice ble;
prussell 8:f187ba55aed2 91 HealthThermometerService *pServiceHTM;
prussell 8:f187ba55aed2 92 BatteryService *pServiceBattery;
prussell 8:f187ba55aed2 93 HeartRateService *pServiceHRM;
prussell 8:f187ba55aed2 94 DeviceInformationService *pServiceDeviceInfo;
prussell 8:f187ba55aed2 95 LinkLossService *pServiceLinkLoss;
prussell 8:f187ba55aed2 96 //UARTService *pServiceUART;
prussell 8:f187ba55aed2 97 //pServiceUART->getTXCharacteristicHandle();
prussell 8:f187ba55aed2 98 //pServiceUART->getRXCharacteristicHandle();
prussell 8:f187ba55aed2 99 //ble.updateCharacteristicValue(pServiceUART->getRXCharacteristicHandle(), pData, uLen); // Tx to App
prussell 8:f187ba55aed2 100
prussell 3:a98203f84063 101
prussell 6:5b6fb35b4450 102 //==========UUID==========
prussell 6:5b6fb35b4450 103 //UUID16 List - Advertising these required by App nRF-Toolbox:HRM&HTM
prussell 6:5b6fb35b4450 104 // Keep list short so advertizing not too long.
prussell 0:0217a862b047 105 static const uint16_t uuid16_list[] = { //Service List (Pre-defined standard 16bit services)
prussell 4:976394791d7a 106 // *Order here doesn't affect order in nRF-MCP Discovery of Services
prussell 1:4a25d917fb6a 107 //BLE_UUID_GAP UUID_GENERIC_ACCESS //0x1800 //Included by Default, DeviceName, Appearance, PreferredConnectionParam
prussell 1:4a25d917fb6a 108 //BLE_UUID_GATT UUID_GENERIC ATTRIBUTE //0x1801 //Included by Default, ServiceChanged,
prussell 3:a98203f84063 109 GattService::UUID_HEALTH_THERMOMETER_SERVICE, //0x1809 //HTM (Might need to be first for nRF App)
prussell 1:4a25d917fb6a 110 GattService::UUID_HEART_RATE_SERVICE, //0x180D //HRM, BodyLocation, ControlPoint
prussell 7:1097d012b01a 111 GattService::UUID_DEVICE_INFORMATION_SERVICE, //0x180A //sManufacturer, sModelNumber, sSerialNumber, sHWver, sFWver, sSWver
prussell 7:1097d012b01a 112 GattService::UUID_BATTERY_SERVICE, //0x180F //BatteryLevel
prussell 7:1097d012b01a 113 GattService::UUID_LINK_LOSS_SERVICE, //0x1803 //LinkLoss
prussell 6:5b6fb35b4450 114
prussell 1:4a25d917fb6a 115 //x GattService::UUID_DFU, //0x1530 - See UARTServiceShortUUID in BLE_API:DFUService.cpp //
prussell 5:d36bbb315e31 116 //x GattService::UARTService, //0x0001~0x0003 - See DFUServiceShortUUID in BLE_API:UARTService.cpp //
prussell 1:4a25d917fb6a 117 //GattService::UUID_ALERT_NOTIFICATION_SERVICE, = 0x1811,
prussell 1:4a25d917fb6a 118 //GattService::UUID_CURRENT_TIME_SERVICE, = 0x1805,
prussell 1:4a25d917fb6a 119 //GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, = 0x1812,
prussell 6:5b6fb35b4450 120 //GattService::UUID_IMMEDIATE_ALERT_SERVICE, = 0x1802,
prussell 1:4a25d917fb6a 121 //GattService::UUID_PHONE_ALERT_STATUS_SERVICE, = 0x180E,
prussell 1:4a25d917fb6a 122 //GattService::UUID_REFERENCE_TIME_UPDATE_SERVICE, = 0x1806,
prussell 1:4a25d917fb6a 123 //GattService::UUID_SCAN_PARAMETERS_SERVICE, = 0x1813,
prussell 5:d36bbb315e31 124 };
prussell 5:d36bbb315e31 125
prussell 6:5b6fb35b4450 126 //UUID128 List(Only a single UUID128 can fit in advertising)
prussell 6:5b6fb35b4450 127 uint8_t puUUID128_Bluetooth_Base_Rev[16] = {0xFB,0x34,0x9B,0x5F,0x80,0, 0,0x80, 0,0x10, 0,0, 0x00,0x00, 0,0};//0000****-0000-1000-8000 00805F9B34FB, Base for UUID16
prussell 6:5b6fb35b4450 128 uint8_t puUUID128_BatteryService[16] = {0xFB,0x34,0x9B,0x5F,0x80,0, 0,0x80, 0,0x10, 0,0, 0x0F,0x18, 0,0};//0000****-0000-1000-8000 00805F9B34FB, ***=0x180F
prussell 5:d36bbb315e31 129
prussell 5:d36bbb315e31 130
prussell 6:5b6fb35b4450 131 /* //Adopted from sample code in header of BLE_API:UUID.cpp
prussell 6:5b6fb35b4450 132 // // Create a UUID16 (0x180F)
prussell 6:5b6fb35b4450 133 // uint8_t shortID[16] = { 0, 0, 0x0F, 0x18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
prussell 6:5b6fb35b4450 134 // UUID ble_uuid = UUID(shortID); // Will have: ble_uuid.type = UUID_TYPE_SHORT, ble_uuid.value = 0x180F
prussell 6:5b6fb35b4450 135 // // Create a UUID128
prussell 6:5b6fb35b4450 136 // uint8_t longID[16] = { 0x00,0x11,0x22,0x33, 0x44,0x55,0x66,0x77, 0x88,0x99,0xAA,0xBB, 0xCC,0xDD,0xEE,0xFF };
prussell 6:5b6fb35b4450 137 // UUID custom_uuid = UUID(longID);// Will have: custom_uuid.type=UUID_TYPE_LONG, custom_uuid.value=0x3322, custom_uuid.base=00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
prussell 6:5b6fb35b4450 138 */
prussell 5:d36bbb315e31 139
prussell 6:5b6fb35b4450 140 /* // The Nordic UART Service
prussell 5:d36bbb315e31 141 //static const uint8_t uart_base_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
prussell 5:d36bbb315e31 142 //static const uint8_t uart_tx_uuid[] = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
prussell 5:d36bbb315e31 143 //static const uint8_t uart_rx_uuid[] = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
prussell 6:5b6fb35b4450 144 //static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0, 0, 0x3D, 0x71};// = flip uart_base_uuid[]
prussell 6:5b6fb35b4450 145 //const uint16_t UUID16_UART_Serv = 0x0001;
prussell 6:5b6fb35b4450 146 //const uint16_t UUID16_UART_Tx = 0x0002;
prussell 6:5b6fb35b4450 147 //const uint16_t UUID16_UART_Rx = 0x0003;
prussell 6:5b6fb35b4450 148 //const uint8_t UUID128_UART_Serv[LENGTH_OF_LONG_UUID]={0x6E,0x40,(uint8_t)(UUID16_UART_Serv>>8),(uint8_t)(UUID16_UART_Serv&0xFF),0xB5,0xA3,0xF3,0x93,0xE0,0xA9,0xE5,0x0E,0x24,0xDC,0xCA,0x9E};
prussell 6:5b6fb35b4450 149 //const uint8_t UUID128_UART_Rev[LENGTH_OF_LONG_UUID]={0x9E,0xCA,0xDC,0x24,0x0E,0xE5,0xA9,0xE0,0x93,0xF3,0xA3,0xB5,(uint8_t)(UUID16_UART_Serv&0xFF),(uint8_t)(UUID16_UART_Serv>>8),0x40,0x6E};//Use with: INCOMPLETE_LIST_128BIT_SERVICE_IDS
prussell 6:5b6fb35b4450 150 */
prussell 1:4a25d917fb6a 151
prussell 6:5b6fb35b4450 152 //UUID Info:
prussell 5:d36bbb315e31 153 // 20141213 From https://developer.bluetooth.org/community/lists/community%20discussion/flat.aspx?rootfolder=/community/lists/community+discussion/16+bit+uuid+vs.+128+uuid&folderctid=0x01200200e2f0e56e3d53004dba96bdf0c357551f
prussell 5:d36bbb315e31 154 // 16bit UUID reserved 128bit base = 32 hex digits: 0000****-0000-1000-8000 00805F9B34FB (Careful to use unsigned to avoid negatives and overflows)
prussell 5:d36bbb315e31 155 // 32bit UUID reserved 128bit base = 32 hex digits: ********-0000-1000-8000 00805F9B34FB (Careful to use unsigned to avoid negatives and overflows)
prussell 5:d36bbb315e31 156 /* All the custom GATT based services and characteristics must use a 128 bit UUID.
prussell 5:d36bbb315e31 157 The Bluetooth_Base_UUID is: 00000000-0000-1000-8000 00805F9B34FB.
prussell 5:d36bbb315e31 158 All the 16-bit Attribute UUIDs defined in the adopted specifications use the above base.
prussell 5:d36bbb315e31 159 Generating a 128 bit UUID for custom profiles: For the 128 bit UUID, please refer to The ITU-T Rec. X.667.
prussell 5:d36bbb315e31 160 You can download a free copy of ITU-T Rec. X.667 from http://www.itu.int/ITU-T/studygroups/com17/oid/X.667-E.pdf.
prussell 5:d36bbb315e31 161 In addition if you go to http://www.itu.int/ITU-T/asn1/uuid.html, you can generate a unique 128-bit UUID.
prussell 5:d36bbb315e31 162 Latency: Refer to Core Spec V4.0, Vol 3, Part F - 3.3.1, which is "Ready by Type Request".
prussell 5:d36bbb315e31 163 If you look at the PDU, you have to send 2 bytes UUID for adopted profiles and 16 bytes UUID for custom profiles.
prussell 5:d36bbb315e31 164 There is additional 14 extra bytes over head for the custom profiles for "Ready By Type Request Method"
prussell 5:d36bbb315e31 165 Note: All attribute types are effectively compared as 128-bit UUIDs, even if a 16-bit UUID is provided in this request or defined for an attribute. (See Section 3.2.1.)
prussell 5:d36bbb315e31 166 A suggestive alternative will be to use a notification method, (see 3.4.7.1), where you don't need the 128 bit UUID or the indication method (see 3.4.7.2)
prussell 5:d36bbb315e31 167 */
prussell 4:976394791d7a 168
prussell 6:5b6fb35b4450 169 //========== UUID128 from readable strings based on URL (processed before main()) ==========
prussell 6:5b6fb35b4450 170 // UUID for released product may need to be properly generated, but for testing this can be convenient
prussell 6:5b6fb35b4450 171 // Adopted 20141214 from Nordic PUCK
prussell 6:5b6fb35b4450 172 uint8_t* puStrToUUID128(const char* pStr) {
prussell 6:5b6fb35b4450 173 static uint8_t pUUID[LENGTH_OF_LONG_UUID]; //Call only once before using
prussell 6:5b6fb35b4450 174 for(int i = 0; i < LENGTH_OF_LONG_UUID; i++) {
prussell 6:5b6fb35b4450 175 if( i < strlen(pStr) ){ pUUID[LENGTH_OF_LONG_UUID-i-1] = pStr[i];}
prussell 6:5b6fb35b4450 176 else { pUUID[LENGTH_OF_LONG_UUID-i-1] =' '; } //Pad end with space character (Or your choice of character such as 'u' or 'x' or NULL)
prussell 6:5b6fb35b4450 177 }
prussell 6:5b6fb35b4450 178 // (UUID128 byte order to match that displayed by App nRF-MCP)
prussell 6:5b6fb35b4450 179 DEBUG("UUID: Prep[%-16s] --> [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]\n",
prussell 6:5b6fb35b4450 180 pStr, pUUID[15],pUUID[14],pUUID[13],pUUID[12], pUUID[11],pUUID[10],pUUID[ 9],pUUID[ 8],
prussell 6:5b6fb35b4450 181 pUUID[ 7],pUUID[ 6],pUUID[ 5],pUUID[ 4], pUUID[ 3],pUUID[ 2],pUUID[ 1],pUUID[ 0] );
prussell 6:5b6fb35b4450 182 return pUUID; //Pointer to prepared UUID128
prussell 2:c77c2b06d604 183 }
prussell 6:5b6fb35b4450 184 // Strings to UUID128, test url: www.none.com: "0123456789ABCDEF" (16chars=32HexDigits=32nibbles)
prussell 6:5b6fb35b4450 185 //const char pc_com_none_servA[] = "com.none.servA";// Provide a short URL you own (in reverse to match Android naming style)
prussell 6:5b6fb35b4450 186 //const char pc_com_none_charA1[] = "com.none.charA1";
prussell 6:5b6fb35b4450 187 //const char pc_com_none_charA2[] = "com.none.charA2";
prussell 2:c77c2b06d604 188
prussell 0:0217a862b047 189 //==========Functions:Timer==========
prussell 0:0217a862b047 190 static volatile bool b_Ticker1 = false;//Volatile, don't optimize, changes under interrupt control
prussell 0:0217a862b047 191 void CallbackTicker1(void)
prussell 0:0217a862b047 192 {
prussell 0:0217a862b047 193 static uint32_t u32_Counter; // Counter for Debug Output
prussell 0:0217a862b047 194
prussell 0:0217a862b047 195 //pwm_led1 = !pwm_led1; /* Do blinky on LED1 while we're waiting for BLE events */
prussell 0:0217a862b047 196 f_led1level+=0.1; if (f_led1level>0.5){f_led1level = 0.1;}; pwm_led1=f_led1level;//PR: Ramp Blink
prussell 0:0217a862b047 197 DEBUG("\nBLEi: Ticker1(%u) ", ++u32_Counter);
prussell 0:0217a862b047 198 b_Ticker1 = true; //PR: Flag to handle Ticker1 Event in Main loop so interupts not blocked.
prussell 0:0217a862b047 199 }
prussell 0:0217a862b047 200
prussell 0:0217a862b047 201 //==========Functions:BLE==========
prussell 0:0217a862b047 202 void Callback_BLE_onTimeout(void)
prussell 0:0217a862b047 203 {
prussell 0:0217a862b047 204 DEBUG("\nBLEi: Callback_BLE_onTimeout()\n" );
prussell 0:0217a862b047 205 //PR: Haven't seen this, even when phone moved out of range and OnDisconnect(Reason0x08) occurs
prussell 0:0217a862b047 206
prussell 0:0217a862b047 207 //DEBUG("\nBLE:Callback_BLE_onTimeout(), Restarting Advertising\n" );
prussell 0:0217a862b047 208 //ble.startAdvertising();
prussell 0:0217a862b047 209 }
prussell 0:0217a862b047 210
prussell 0:0217a862b047 211 //void onDisconnection (Gap::DisconnectionEventCallback_t disconnectionCallback)
prussell 0:0217a862b047 212 void Callback_BLE_onDisconnect(Gap::Handle_t tHandle, Gap::DisconnectionReason_t eReason)
prussell 0:0217a862b047 213 {
prussell 0:0217a862b047 214 //PR: onDisconnect(Reason:8) occured after ~20Tx with no onDataSent() after phone moved out of range
prussell 0:0217a862b047 215
prussell 0:0217a862b047 216 // REMOTE_USER_TERMINATED_CONNECTION = 0x13 = 19,
prussell 0:0217a862b047 217 // LOCAL_HOST_TERMINATED_CONNECTION = 0x16 = 22,
prussell 0:0217a862b047 218 // CONN_INTERVAL_UNACCEPTABLE = 0x3B = 59,
prussell 0:0217a862b047 219 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
prussell 0:0217a862b047 220
prussell 0:0217a862b047 221 //DEBUG("Wait10sec...\n");wait(10.0); //PR: Optional to test effect on advertising
prussell 0:0217a862b047 222 ble.startAdvertising(); // restart advertising
prussell 0:0217a862b047 223 }
prussell 0:0217a862b047 224
prussell 0:0217a862b047 225 //inline void BLEDevice::onConnection(Gap::ConnectionEventCallback_t connectionCallback){ transport->getGap().setOnConnection(connectionCallback);}
prussell 0:0217a862b047 226 void Callback_BLE_onConnect(Gap::Handle_t tHandle, Gap::addr_type_t ePeerAddrType, const Gap::address_t c6PeerAddr, const Gap::ConnectionParams_t *params)
prussell 0:0217a862b047 227 {
prussell 0:0217a862b047 228 DEBUG("\nBLEi: Callback_BLE_Connect(Handle:%d, eType:%d, Add:%u ...)\n", tHandle, ePeerAddrType, c6PeerAddr);
prussell 0:0217a862b047 229
prussell 0:0217a862b047 230 #if UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL
prussell 0:0217a862b047 231 /* Updating connection parameters can be attempted only after a connection has been
prussell 0:0217a862b047 232 * established. Please note that the ble-Central is still the final arbiter for
prussell 0:0217a862b047 233 * the effective parameters; the peripheral can only hope that the request is
prussell 0:0217a862b047 234 * honored. Please also be mindful of the constraints that might be enforced by
prussell 0:0217a862b047 235 * the BLE stack on the underlying controller.*/
prussell 0:0217a862b047 236 #define MIN_CONN_INTERVAL 250 /**< Minimum connection interval (250 ms) */
prussell 0:0217a862b047 237 #define MAX_CONN_INTERVAL 350 /**< Maximum connection interval (350 ms). */
prussell 0:0217a862b047 238 #define CONN_SUP_TIMEOUT 6000 /**< Connection supervisory timeout (6 seconds). */
prussell 0:0217a862b047 239 #define SLAVE_LATENCY 4
prussell 0:0217a862b047 240
prussell 0:0217a862b047 241 Gap::ConnectionParams_t tGap_conn_params;
prussell 0:0217a862b047 242 tGap_conn_params.minConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(MIN_CONN_INTERVAL);
prussell 0:0217a862b047 243 tGap_conn_params.maxConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(MAX_CONN_INTERVAL);
prussell 0:0217a862b047 244 tGap_conn_params.connectionSupervisionTimeout = Gap::MSEC_TO_GAP_DURATION_UNITS(CONN_SUP_TIMEOUT);
prussell 0:0217a862b047 245 tGap_conn_params.slaveLatency = SLAVE_LATENCY;
prussell 0:0217a862b047 246 ble.updateConnectionParams(tHandle, &tGap_conn_params);
prussell 0:0217a862b047 247 #endif /* #if UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL */
prussell 0:0217a862b047 248 }
prussell 0:0217a862b047 249
prussell 0:0217a862b047 250 static volatile bool bSent = false; //Volatile, don't optimize, changes under interrupt control
prussell 0:0217a862b047 251 static volatile unsigned uSentBLE;
prussell 0:0217a862b047 252 void Callback_BLE_onDataSent(unsigned uSent){
prussell 0:0217a862b047 253 uSentBLE=uSent;
prussell 1:4a25d917fb6a 254 DEBUG("BLEi: SentI(%u)", uSent); //TODO: PR: Why uSent always "1", expected it to match sent bytes length
prussell 0:0217a862b047 255 bSent = true;
prussell 5:d36bbb315e31 256 //PR: App nRF-MCP doesn't cause onDataSent(), while App nRF-ToolBox:HRM does cause onDataSent()
prussell 0:0217a862b047 257 //PR: onDataSent() maybe only occuring when confirmed receive by phone, as onDataSent() didn't happen when phone moved out of range.
prussell 0:0217a862b047 258 }
prussell 0:0217a862b047 259
prussell 0:0217a862b047 260 void Callback_BLE_onDataWritten(const GattCharacteristicWriteCBParams *pParams)
prussell 0:0217a862b047 261 {
prussell 0:0217a862b047 262 // Callback_BLE_onDataWritten == This does occur when use nRF-MCP to save New Heart Rate Control Point (Ignored if incorrect length)
prussell 0:0217a862b047 263
prussell 0:0217a862b047 264 //Warning: *data may not be NULL terminated
prussell 0:0217a862b047 265 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);
prussell 8:f187ba55aed2 266
prussell 8:f187ba55aed2 267 //Triggered by BluetoothLEGatt sample changing Linkloss setting:
prussell 8:f187ba55aed2 268 //Alert=1: Debug=BLEi: Callback_BLE_onDataWritten(Handle:12, eOp:1, uOffset:0 uLen:1 Data0[0x01]=Data[]
prussell 8:f187ba55aed2 269 //Alert=2: Debug=BLEi: Callback_BLE_onDataWritten(Handle:12, eOp:1, uOffset:0 uLen:1 Data0[0x02]=Data[]
prussell 8:f187ba55aed2 270
prussell 8:f187ba55aed2 271 /* From mbed project BLE_LoopbackUART:
prussell 8:f187ba55aed2 272 if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) {
prussell 8:f187ba55aed2 273 uint16_t bytesRead = params->len;
prussell 8:f187ba55aed2 274 DEBUG("received %u bytes\n\r", bytesRead);
prussell 8:f187ba55aed2 275 ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead);
prussell 8:f187ba55aed2 276 }
prussell 8:f187ba55aed2 277 */
prussell 8:f187ba55aed2 278 //if(ble.getGapState().connected){ //Ensure BLE still connected
prussell 8:f187ba55aed2 279 // if(params->charHandle == ble.getTXCharacteristicHandle())
prussell 8:f187ba55aed2 280 // htmService.updateTemperature( update_htm() );
prussell 8:f187ba55aed2 281 // hrmService.updateHeartRate( update_hrm() );
prussell 8:f187ba55aed2 282 // battService.updateBatteryLevel( update_batt() );
prussell 8:f187ba55aed2 283
prussell 8:f187ba55aed2 284
prussell 8:f187ba55aed2 285 /* switch(pParams->op){
prussell 8:f187ba55aed2 286 case GATTS_CHAR_OP_INVALID:
prussell 8:f187ba55aed2 287 GATTS_CHAR_OP_WRITE_REQ
prussell 8:f187ba55aed2 288 GATTS_CHAR_OP_WRITE_CMD
prussell 8:f187ba55aed2 289 GATTS_CHAR_OP_SIGN_WRITE_CMD //< Signed Write Command
prussell 8:f187ba55aed2 290 GATTS_CHAR_OP_PREP_WRITE_REQ //< Prepare Write Request
prussell 8:f187ba55aed2 291 GATTS_CHAR_OP_EXEC_WRITE_REQ_CANCEL //< Execute Write Request: Cancel all prepared writes
prussell 8:f187ba55aed2 292 GATTS_CHAR_OP_EXEC_WRITE_REQ_NOW //< Execute Write Request: Immediately execute all prepared writes
prussell 8:f187ba55aed2 293 }
prussell 8:f187ba55aed2 294 */
prussell 8:f187ba55aed2 295
prussell 8:f187ba55aed2 296
prussell 8:f187ba55aed2 297
prussell 0:0217a862b047 298 }
prussell 0:0217a862b047 299
prussell 0:0217a862b047 300 void Callback_BLE_onUpdatesEnabled(Gap::Handle_t tHandle)
prussell 0:0217a862b047 301 {
prussell 0:0217a862b047 302 DEBUG("\nBLEi: Callback_BLE_onUpdates(Handle:%d)\r\n", tHandle);
prussell 0:0217a862b047 303 }
prussell 0:0217a862b047 304
prussell 5:d36bbb315e31 305 // Adopted 20141213 from http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LinkLoss/file/440ee5e8595f/main.cpp
prussell 5:d36bbb315e31 306 void Callback_BLE_onLinkLoss(LinkLossService::AlertLevel_t level)
prussell 5:d36bbb315e31 307 {
prussell 5:d36bbb315e31 308 printf("\nBLEi: Link loss alert[%d]\n", level);
prussell 5:d36bbb315e31 309 }
prussell 8:f187ba55aed2 310 //==========HRM==========
prussell 8:f187ba55aed2 311 //Adopted 2014Dec from http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/
prussell 8:f187ba55aed2 312 uint8_t update_hrm(void)//(bool bInit)
prussell 8:f187ba55aed2 313 {
prussell 8:f187ba55aed2 314 static uint8_t u8_hrm = 100;
prussell 8:f187ba55aed2 315 u8_hrm++;
prussell 8:f187ba55aed2 316 if (u8_hrm >= 175) {
prussell 8:f187ba55aed2 317 u8_hrm = 100;
prussell 8:f187ba55aed2 318 DEBUG("BLE: HRM Rollover175->100 ");
prussell 8:f187ba55aed2 319 }
prussell 8:f187ba55aed2 320 DEBUG("[HRM:%d]", u8_hrm);
prussell 8:f187ba55aed2 321 pServiceHRM->updateHeartRate( u8_hrm );// Update Characteristic so sent by BLE
prussell 8:f187ba55aed2 322 return(u8_hrm);
prussell 8:f187ba55aed2 323 }
prussell 8:f187ba55aed2 324 //==========HTM:Internal Temperature==========
prussell 8:f187ba55aed2 325 //Adopted 2014Dec from: https://developer.mbed.org/users/takafuminaka/code/BLE_HTM_by_InTempSensr/
prussell 8:f187ba55aed2 326 // Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.health_thermometer.xml
prussell 8:f187ba55aed2 327 // HTM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml
prussell 5:d36bbb315e31 328
prussell 8:f187ba55aed2 329 //****Although nRF-MCP displays float OK, the HTM Apps don't, its possible IEEE format required like in the original code:BLE_HTM_by_InTempSensr
prussell 8:f187ba55aed2 330 float update_htm(void)
prussell 8:f187ba55aed2 331 {
prussell 8:f187ba55aed2 332 //static float fTemperature = 0;//-123.456;
prussell 8:f187ba55aed2 333 int32_t i32_temp;
prussell 8:f187ba55aed2 334 sd_temp_get(&i32_temp); //Read the nRF Internal Temperature (Die in 0.25'C steps, Counting From TBD), TODO:Check Scaling
prussell 8:f187ba55aed2 335 float fTemperature = (float(i32_temp)/4.0) - 16.0; // Scale&Shift (0.25'C from -16'C?)
prussell 8:f187ba55aed2 336
prussell 8:f187ba55aed2 337 //{//Force to IEEE format to match needs of Apps like nRF-HTM and nRF-Toolbox:HTM
prussell 8:f187ba55aed2 338 // PR: Didn't work 20141213, might need 5byte style from BLE_HTM_by_InTempSensr if this is really necessary. OK in nRF-MCP for now.
prussell 8:f187ba55aed2 339 // uint8_t exponent = 0xFE; //exponent is -2
prussell 8:f187ba55aed2 340 // uint32_t mantissa = (uint32_t)(fTemperature*100);
prussell 8:f187ba55aed2 341 // uint32_t temp_ieee11073 = ((((uint32_t)exponent) << 24) | (mantissa)); //Note: Assumes Mantissa within 24bits
prussell 8:f187ba55aed2 342 // memcpy(((uint8_t*)&fTemperature)+1, (uint8_t*)&temp_ieee11073, 4); //Overwrite with IEEE format float
prussell 8:f187ba55aed2 343 //}
prussell 8:f187ba55aed2 344
prussell 8:f187ba55aed2 345 pServiceHTM->updateTemperature( fTemperature );// Update Characteristic so sent by BLE
prussell 8:f187ba55aed2 346 DEBUG("[HTMi:%d HTMf:%f]", i32_temp, fTemperature);
prussell 8:f187ba55aed2 347 return(fTemperature);
prussell 8:f187ba55aed2 348 }
prussell 8:f187ba55aed2 349 //==========Battery==========
prussell 8:f187ba55aed2 350 uint8_t update_batt(void)
prussell 8:f187ba55aed2 351 {
prussell 8:f187ba55aed2 352 static uint8_t u8_BattPercent=33; //Level: 0..100%
prussell 8:f187ba55aed2 353 u8_BattPercent <= 50 ? u8_BattPercent=100 : u8_BattPercent--; // Simulate Battery Decay
prussell 8:f187ba55aed2 354 pServiceBattery->updateBatteryLevel( u8_BattPercent ); // Update Characteristic so sent by BLE
prussell 8:f187ba55aed2 355 DEBUG("[BATT:%d%%]", u8_BattPercent);
prussell 8:f187ba55aed2 356 return(u8_BattPercent);
prussell 8:f187ba55aed2 357 }
prussell 0:0217a862b047 358 //==========main==========
prussell 0:0217a862b047 359 int main(void)
prussell 0:0217a862b047 360 {
prussell 0:0217a862b047 361 f_led1level = 1; pwm_led1 = f_led1level;//Start LED1=OnMax
prussell 0:0217a862b047 362 f_led2level = 1; pwm_led2 = f_led2level;//Start LED2=OnMax
prussell 6:5b6fb35b4450 363
prussell 6:5b6fb35b4450 364 //Restart TeraTerm just before Pressing Reset on mbed, 9600-8N1(No Flow Control)
prussell 6:5b6fb35b4450 365 DEBUG("\nBLE: ___%s___\n", pcDeviceName);
prussell 8:f187ba55aed2 366 DEBUG("BLE: Connect App for Data: nRF-MCP, nRF-Toolbox:HRM/HTM, Android Sample BluetoothLeGatt, etc.\n");
prussell 8:f187ba55aed2 367 DEBUG("BLE: BluetoothLeGatt: App->mbed: LinkLoss->AlertLevel(UpArrow)\n");
prussell 8:f187ba55aed2 368 DEBUG("BLE: BluetoothLeGatt: App->mbed: BatteryService->BatteryLevel(DownArrow)\n");
prussell 8:f187ba55aed2 369 DEBUG("BLE: BluetoothLeGatt: mbed->App: BatteryService->BatteryLevel->EnableNotify(ThreeDownArrows), Also App Acks the send=DEBUG('SentI')\n");
prussell 0:0217a862b047 370
prussell 0:0217a862b047 371 Ticker ticker1; //PR: Timer Object(Structure)
prussell 0:0217a862b047 372 ticker1.attach(CallbackTicker1, 2.0); //PR: Timer Handler, Float=PeriodSeconds
prussell 0:0217a862b047 373
prussell 3:a98203f84063 374 //BLE1: Setup BLE Service (and event actions) //TODO: Check for services declared before main() - Is that OK?
prussell 3:a98203f84063 375 DEBUG("BLE: Setup BLE\n");
prussell 0:0217a862b047 376 ble.init();
prussell 0:0217a862b047 377 ble.onDisconnection(Callback_BLE_onDisconnect);
prussell 0:0217a862b047 378 ble.onConnection(Callback_BLE_onConnect); //PR: Not required if no actions enabled, enabled now just for debug printf()
prussell 0:0217a862b047 379 ble.onDataSent(Callback_BLE_onDataSent);
prussell 0:0217a862b047 380 ble.onDataWritten(Callback_BLE_onDataWritten);
prussell 0:0217a862b047 381 ble.onTimeout(Callback_BLE_onTimeout);
prussell 0:0217a862b047 382 ble.onUpdatesEnabled(Callback_BLE_onUpdatesEnabled);
prussell 8:f187ba55aed2 383
prussell 8:f187ba55aed2 384 DEBUG("BLE: Handles:\n");
prussell 8:f187ba55aed2 385 //DEBUG(" Service: BLE: %d\n", ble.getHandle());
prussell 8:f187ba55aed2 386 //DEBUG(" Characteristic:BattLevel: %d\n", batteryLevelCharacteristic.getValueAttribute().getHandle());
prussell 8:f187ba55aed2 387 //DFUService
prussell 8:f187ba55aed2 388
prussell 8:f187ba55aed2 389
prussell 8:f187ba55aed2 390
prussell 0:0217a862b047 391
prussell 0:0217a862b047 392 //ble_error_t readCharacteristicValue ( uint16_t handle, uint8_t *const buffer, uint16_t *const lengthP )
prussell 0:0217a862b047 393 //ble_error_t updateCharacteristicValue (uint16_t handle, const uint8_t *value, uint16_t size, bool localOnly=false)
prussell 0:0217a862b047 394
prussell 4:976394791d7a 395 //UUID List by Services that are setup
prussell 6:5b6fb35b4450 396 //BLE2: Setup Services (with their initial values and options)
prussell 3:a98203f84063 397 DEBUG("BLE: Setup Services\n");
prussell 4:976394791d7a 398 // *Order here affects order in nRF-MCP Discovery of Services
prussell 8:f187ba55aed2 399 DeviceInformationService ServiceDeviceInfo(ble, "Maker", pcDeviceName, "sn1234", "hw00", "fw00", "sw00");//(BLEDevice), pcManufacturer, pcModelNumber, pcSerialNumber, pcHWver, pcFWver, pcSWver
prussell 8:f187ba55aed2 400 pServiceDeviceInfo = &ServiceDeviceInfo; DEBUG(" Handle Service DeviceInfo:%d\n", ServiceDeviceInfo);
prussell 8:f187ba55aed2 401 LinkLossService ServiceLinkLoss(ble, Callback_BLE_onLinkLoss, LinkLossService::HIGH_ALERT); //New20141213, TBD
prussell 8:f187ba55aed2 402 pServiceLinkLoss = &ServiceLinkLoss;
prussell 8:f187ba55aed2 403 BatteryService ServiceBattery(ble, 10);
prussell 8:f187ba55aed2 404 pServiceBattery = &ServiceBattery;
prussell 8:f187ba55aed2 405 HeartRateService ServiceHRM(ble, (uint8_t)111, HeartRateService::LOCATION_FINGER);
prussell 8:f187ba55aed2 406 pServiceHRM = &ServiceHRM;
prussell 8:f187ba55aed2 407 HealthThermometerService ServiceHTM(ble, 33.3, HealthThermometerService::LOCATION_EAR);
prussell 8:f187ba55aed2 408 pServiceHTM = &ServiceHTM;
prussell 8:f187ba55aed2 409 //UARTService ServiceUART(ble);
prussell 8:f187ba55aed2 410 // pServiceUART = &ServiceUART;
prussell 5:d36bbb315e31 411
prussell 3:a98203f84063 412 //BLE3: Setup advertising
prussell 6:5b6fb35b4450 413 // Note the Advertising payload is limited to 31bytes, so careful don't overflow this. Multiple UUID16's or a single UUID128 are possible in advertising.
prussell 6:5b6fb35b4450 414 // If there isn't enough space, then the accumulatepayload won't add that block to the advertising, it won't add a partial block.
prussell 3:a98203f84063 415 DEBUG("BLE: Setup Advertising\n");
prussell 6:5b6fb35b4450 416 ble.clearAdvertisingPayload(); //Prep
prussell 6:5b6fb35b4450 417 ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); //PR: Advertise 1sec (1Hz)
prussell 6:5b6fb35b4450 418 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //PR: TODO: To Study
prussell 6:5b6fb35b4450 419 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); //PR: BLE Only (Option:LE_LIMITED_DISCOVERABLE)
prussell 6:5b6fb35b4450 420 // Does "LE_GENERAL_DISCOVERABLE" affect whether UUID needs to be advertised to discover services?
prussell 6:5b6fb35b4450 421 //ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)UUID128_UART_Rev, sizeof(UUID128_UART_Rev)); //Single UUID128
prussell 6:5b6fb35b4450 422 //ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)puUUID128_BatteryService, sizeof(puUUID128_BatteryService)); //Single UUID128
prussell 6:5b6fb35b4450 423 //ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS, puStrToUUID128( pc_com_none_servA), LENGTH_OF_LONG_UUID); //Single UUID128
prussell 6:5b6fb35b4450 424 //ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // Multiple UUID16
prussell 6:5b6fb35b4450 425 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // Multiple UUID16
prussell 6:5b6fb35b4450 426 //ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);//PR: Add Appearance::HeartRate (HRM Connects without this)
prussell 6:5b6fb35b4450 427 //ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER); //PR: Add Appearance::Thermometer (HTM Connects without this, though float format still needs change)
prussell 6:5b6fb35b4450 428 // Add LocalName last so if Advertising too long will easily see as Name won't be available for the device.
prussell 6:5b6fb35b4450 429 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)pcDeviceName, sizeof(pcDeviceName)-1);//PR: LocalName (No NULL)
prussell 6:5b6fb35b4450 430 ble.startAdvertising();
prussell 3:a98203f84063 431
prussell 6:5b6fb35b4450 432 // Raw Advertizing max length 31bytes: 0x01020304050607080910111213141516171819202122232425262728293031
prussell 6:5b6fb35b4450 433 // Example Raw Advertising caught by App nRF-MCP: 0x020106070309180A180D180909626C655052763034
prussell 6:5b6fb35b4450 434 // = Len02 Type01 Value06 (Flags: BREDR_NOT_SUPPORTED, LE_GENERAL_DISCOVERABLE)
prussell 6:5b6fb35b4450 435 // = Len07 Type03 Values: 0918 0A18 0D18 (ListUUID16: 1809 180A 180D )
prussell 6:5b6fb35b4450 436 // = Len09 Type09 Values: 62 6C 65 50 52 76 30 34 (LocalName = "blePRv04")
prussell 5:d36bbb315e31 437
prussell 6:5b6fb35b4450 438 // Example Raw Advertising caught by App nRF-MCP: 0x02010611069ECADC240EE5A9E093F3A3B50100406E090209180A180D180F18 (==Max Length)
prussell 6:5b6fb35b4450 439 // = Len02 Type01 Value06 (Flags: BREDR_NOT_SUPPORTED, LE_GENERAL_DISCOVERABLE)
prussell 6:5b6fb35b4450 440 // = Len11 Type06 Value9ECADC240EE5A9E093F3A3B5_0100_406E (UUID128: NordicUART=0x0001)
prussell 6:5b6fb35b4450 441 // = Len09 Type02 Values:0918 0A18 0D18 0F18 (UUID16: 1809 180A 180D 180F)
prussell 6:5b6fb35b4450 442 // = LocalName field wasn't appended as insufficient space, so Device won't be named when scanning.
prussell 6:5b6fb35b4450 443
prussell 6:5b6fb35b4450 444 // Example Raw Advertising caught by App nRF-MCP: 0x0201061106FB349B5F80000080001000000F180000070209180A180D18
prussell 6:5b6fb35b4450 445 // = Len02 Type01 Value06 (Flags: BREDR_NOT_SUPPORTED, LE_GENERAL_DISCOVERABLE)
prussell 6:5b6fb35b4450 446 // = Len11 Type06 ValueFB349B5F8000008000100000_0F18_0000 (UUID128: BluetoothBattery=0x180F)
prussell 6:5b6fb35b4450 447 // = Len07 Type02 Value 0918 0A18 0D18 (UUID16: 1809 180A 180D )
prussell 6:5b6fb35b4450 448 // = LocalName field wasn't appended as insufficient space, so Device won't be named when scanning.
prussell 0:0217a862b047 449
prussell 0:0217a862b047 450 DEBUG("BLE: Main Loop\n");
prussell 0:0217a862b047 451 uint32_t u32_wakeevents=0, u32_wakelast=0; // Counter&Register for tracking Wake Events (to see monitor their Frequency)
prussell 0:0217a862b047 452 while (true) {
prussell 0:0217a862b047 453 if (b_Ticker1 && ble.getGapState().connected) { //If Ticker1 and Connected Update Data
prussell 0:0217a862b047 454 b_Ticker1 = false; // Clear flag for next Ticker1, see CallbackTicker1()
prussell 3:a98203f84063 455
prussell 3:a98203f84063 456 // Read Sensors, and update matching Service Characteristics (only if connected)
prussell 4:976394791d7a 457 // *Order here doesn't affect order in nRF-MCP Discovery of Services
prussell 6:5b6fb35b4450 458 //TBD: Maybe save power by not Tx unless enabled by App?
prussell 8:f187ba55aed2 459 // The Services are discovered if they were setup/started (They don't need update to be discovered)
prussell 8:f187ba55aed2 460 update_htm();
prussell 8:f187ba55aed2 461 update_hrm();
prussell 8:f187ba55aed2 462 update_batt();
prussell 8:f187ba55aed2 463
prussell 3:a98203f84063 464 DEBUG("BLE: Wakes:%u Delta:%d ", u32_wakeevents, u32_wakeevents-u32_wakelast); //For Evaluating Timing
prussell 3:a98203f84063 465 u32_wakelast = u32_wakeevents;
prussell 0:0217a862b047 466 } else if (b_Ticker1) {
prussell 0:0217a862b047 467 b_Ticker1 = false; // Clear flag for next Ticker1, see CallbackTicker1()
prussell 3:a98203f84063 468 DEBUG("BLE: Tick while unconnected ");
prussell 0:0217a862b047 469 } else if (bSent){
prussell 0:0217a862b047 470 bSent=false; //clear flag
prussell 3:a98203f84063 471 //DEBUG("BLE: Sent %ubytes ", uSentBLE);
prussell 0:0217a862b047 472 } else {
prussell 3:a98203f84063 473 //DEBUG("BLE: Wait for Event\n\r"); //x Debug output here causes unnecessary wakes resulting in endless awakes.
prussell 0:0217a862b047 474 ble.waitForEvent(); //PR: Wait for event - Yield control to BLE Stack and other events (Process ALL pending events before waiting again)
prussell 0:0217a862b047 475 f_led2level+=0.25; if (f_led2level>0.5){f_led2level = 0.0;}; pwm_led2=f_led2level;//PR: Ramp Blink
prussell 0:0217a862b047 476 u32_wakeevents++; //PR: Count events for frequency monitoring (20141207PR: nRF51822 mbed HRM = 50Hz)
prussell 0:0217a862b047 477 }
prussell 0:0217a862b047 478 }
prussell 0:0217a862b047 479 }
prussell 6:5b6fb35b4450 480 //========== end ==========