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:
Sun Dec 14 00:11:39 2014 +0000
Revision:
4:976394791d7a
Parent:
3:a98203f84063
Child:
5:d36bbb315e31
Updated comments

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 0:0217a862b047 7 // - miscellaneous adopted from more samples...
prussell 0:0217a862b047 8 // Reference:
prussell 0:0217a862b047 9 // - http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/
prussell 0:0217a862b047 10 // - Reference: http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/docs/tip/
prussell 0:0217a862b047 11 // - Reference: http://developer.mbed.org/teams/Bluetooth-Low-Energy/
prussell 0:0217a862b047 12 // Warnings:
prussell 0:0217a862b047 13 // - As of 20141210 it is necessary to use Android App [nRF-Master Control Panel] to ensure any previous connected
prussell 0:0217a862b047 14 // code on mkit is properly Disconnected before trying to connect other Android nRF Apps (nRFToolbox, nRF UART 2.0, etc.).
prussell 0:0217a862b047 15 // 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 16 // Notes:
prussell 0:0217a862b047 17 // - onDataSent() maybe only occuring when confirmed receive by phone, as onDataSent() didn't happen when phone moved out of range.
prussell 0:0217a862b047 18 // - onDisconnect(Reason:8) occured after ~20Tx with no onDataSent() after phone moved out of range, OnTimeout didn't occur at all.
prussell 0:0217a862b047 19 // ToDo: and ToCheck:
prussell 0:0217a862b047 20 // - Re-check where voltatile needed
prussell 0:0217a862b047 21 //==========End of PR's Header
prussell 0:0217a862b047 22
prussell 0:0217a862b047 23 //==========Historic Licencing from original imported sample from mbed website [BLE_HeartRate] ==========
prussell 0:0217a862b047 24 //From: http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/
prussell 0:0217a862b047 25 /* mbed Microcontroller Library
prussell 0:0217a862b047 26 * Copyright (c) 2006-2013 ARM Limited
prussell 0:0217a862b047 27 *
prussell 0:0217a862b047 28 * Licensed under the Apache License, Version 2.0 (the "License");
prussell 0:0217a862b047 29 * you may not use this file except in compliance with the License.
prussell 0:0217a862b047 30 * You may obtain a copy of the License at
prussell 0:0217a862b047 31 * http://www.apache.org/licenses/LICENSE-2.0
prussell 0:0217a862b047 32 * Unless required by applicable law or agreed to in writing, software
prussell 0:0217a862b047 33 * distributed under the License is distributed on an "AS IS" BASIS,
prussell 0:0217a862b047 34 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
prussell 0:0217a862b047 35 * See the License for the specific language governing permissions and
prussell 0:0217a862b047 36 * limitations under the License. */
prussell 0:0217a862b047 37 //==========end of Historic Licencing ==========
prussell 0:0217a862b047 38
prussell 0:0217a862b047 39
prussell 0:0217a862b047 40 //==========Compile Options==========
prussell 0:0217a862b047 41 #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 42 #define UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL 0 //PR: Option to slow the connection intervsal possibly saving power (After Connected)
prussell 0:0217a862b047 43
prussell 0:0217a862b047 44 //==========Includes==========
prussell 0:0217a862b047 45 #include "mbed.h"
prussell 1:4a25d917fb6a 46 #include "BLEDevice.h" // BLE
prussell 1:4a25d917fb6a 47 #include "nrf_soc.h" // nRF Internal Temperature Sensor
prussell 0:0217a862b047 48
prussell 0:0217a862b047 49 //Services
prussell 0:0217a862b047 50 #include "BatteryService.h"
prussell 0:0217a862b047 51 #include "DeviceInformationService.h"
prussell 0:0217a862b047 52 //#include "DFUService" //TODO: DFU and FOTA Support
prussell 1:4a25d917fb6a 53 #include "HealthThermometerService.h" //TODO: Temperature, #include "ble_hts.h"
prussell 0:0217a862b047 54 #include "HeartRateService.h"
prussell 0:0217a862b047 55 //#include "UARTService.h" //TODO: Add a UART Channel for streaming data like logs?
prussell 0:0217a862b047 56
prussell 0:0217a862b047 57 //==========Debug Console==========
prussell 0:0217a862b047 58 #if ENABLE_SerialUSB_DEBUG_CONSOLE
prussell 0:0217a862b047 59 Serial debug_serial(USBTX, USBRX); //PR: DebugSerialOverMbedUSB 9600-8N1N
prussell 0:0217a862b047 60 #define DEBUG(...) { debug_serial.printf(__VA_ARGS__); }
prussell 0:0217a862b047 61 #else
prussell 0:0217a862b047 62 #define DEBUG(...) //Do Nothing
prussell 0:0217a862b047 63 #endif
prussell 0:0217a862b047 64
prussell 2:c77c2b06d604 65 //========== This Section is to Create Debug output showing variable prep before main() ==========
prussell 2:c77c2b06d604 66 bool u8_prep_dummy(void) {
prussell 2:c77c2b06d604 67 DEBUG("\n\nBLE: ____Prep Memory____\n");
prussell 2:c77c2b06d604 68 return true;
prussell 2:c77c2b06d604 69 }
prussell 2:c77c2b06d604 70 const bool bPrep = u8_prep_dummy();
prussell 2:c77c2b06d604 71
prussell 0:0217a862b047 72 //==========LEDs==========
prussell 0:0217a862b047 73 //LEDs:
prussell 0:0217a862b047 74 //DigitalOut out_led1(LED1); //PR: Firmware heartbeat
prussell 0:0217a862b047 75 //DigitalOut out_led2(LED2); //PR: Firmware heartbeat
prussell 0:0217a862b047 76 PwmOut pwm_led1(LED1); //PR: Firmware Life Indicator
prussell 0:0217a862b047 77 PwmOut pwm_led2(LED2); //TODO: Controlled by App
prussell 0:0217a862b047 78 float f_led1level = 0.0; //Initial Brightness (Typically 0.0~0.5)
prussell 0:0217a862b047 79 float f_led2level = 0.0; //Initial Brightness (Typically 0.0~0.5)
prussell 0:0217a862b047 80
prussell 0:0217a862b047 81 //==========BLE==========
prussell 0:0217a862b047 82 BLEDevice ble;
prussell 0:0217a862b047 83 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 3:a98203f84063 84
prussell 3:a98203f84063 85 //UUID List by Advertised 16bit UUID list (PartA)
prussell 0:0217a862b047 86 static const uint16_t uuid16_list[] = { //Service List (Pre-defined standard 16bit services)
prussell 4:976394791d7a 87 // *Order here doesn't affect order in nRF-MCP Discovery of Services
prussell 1:4a25d917fb6a 88 //BLE_UUID_GAP UUID_GENERIC_ACCESS //0x1800 //Included by Default, DeviceName, Appearance, PreferredConnectionParam
prussell 1:4a25d917fb6a 89 //BLE_UUID_GATT UUID_GENERIC ATTRIBUTE //0x1801 //Included by Default, ServiceChanged,
prussell 3:a98203f84063 90 GattService::UUID_HEALTH_THERMOMETER_SERVICE, //0x1809 //HTM (Might need to be first for nRF App)
prussell 1:4a25d917fb6a 91 GattService::UUID_DEVICE_INFORMATION_SERVICE, //0x180A //sManufacturer, sModelNumber, sSerialNumber, sHWver, sFWver, sSWver
prussell 1:4a25d917fb6a 92 GattService::UUID_HEART_RATE_SERVICE, //0x180D //HRM, BodyLocation, ControlPoint
prussell 4:976394791d7a 93 GattService::UUID_BATTERY_SERVICE, //0x180F //BatteryLevel
prussell 3:a98203f84063 94 // GattService::UUID_HEALTH_THERMOMETER_SERVICE, //0x1809 //HTM
prussell 1:4a25d917fb6a 95 //x GattService::UUID_DFU, //0x1530 - See UARTServiceShortUUID in BLE_API:DFUService.cpp //
prussell 1:4a25d917fb6a 96 //x GattService::UARTService, //0x0001 - See DFUServiceShortUUID in BLE_API:UARTService.cpp //
prussell 1:4a25d917fb6a 97 //GattService::UUID_ALERT_NOTIFICATION_SERVICE, = 0x1811,
prussell 1:4a25d917fb6a 98 //GattService::UUID_CURRENT_TIME_SERVICE, = 0x1805,
prussell 1:4a25d917fb6a 99 //GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, = 0x1812,
prussell 1:4a25d917fb6a 100 //GattService::UUID_IMMEDIATE_ALERT_SERVICE, = 0x1802,
prussell 1:4a25d917fb6a 101 //GattService::UUID_LINK_LOSS_SERVICE, = 0x1803,
prussell 1:4a25d917fb6a 102 //GattService::UUID_PHONE_ALERT_STATUS_SERVICE, = 0x180E,
prussell 1:4a25d917fb6a 103 //GattService::UUID_REFERENCE_TIME_UPDATE_SERVICE, = 0x1806,
prussell 1:4a25d917fb6a 104 //GattService::UUID_SCAN_PARAMETERS_SERVICE, = 0x1813,
prussell 1:4a25d917fb6a 105 };
prussell 1:4a25d917fb6a 106
prussell 2:c77c2b06d604 107 //========== Prep UUID list (before main()) ==========
prussell 4:976394791d7a 108 // Adopted 2014Dec from http://developer.mbed.org/users/Bobty/code/BLE_ScoringDevice/
prussell 4:976394791d7a 109
prussell 4:976394791d7a 110 //TODO: Unfinished new code style from http://developer.mbed.org/users/Bobty/code/BLE_ScoringDevice/
prussell 4:976394791d7a 111
prussell 3:a98203f84063 112 //UUID List by Advertised 128bit UUID list (PartA, ToDo:)
prussell 2:c77c2b06d604 113 // Gatt characteristic and service UUIDs - Readable to UUID
prussell 2:c77c2b06d604 114 const UUID stringToUUID(const char* str) {
prussell 2:c77c2b06d604 115 uint8_t array[16] = {0x55,0x55,0x55,0x55, 0x55,0x55,0x55,0x55, 0x55,0x55,0x55,0x55, 0x55,0x55,0x55,0x55};//Prefill 'U' so fully specified even short string
prussell 2:c77c2b06d604 116 for(int i = 0; i < strlen(str); i++) { //Don't convert unspecified bytes past end of string
prussell 2:c77c2b06d604 117 array[i] = str[i];
prussell 2:c77c2b06d604 118 }
prussell 2:c77c2b06d604 119
prussell 2:c77c2b06d604 120 DEBUG("UUID: Prep[%16s] --> [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x] %c\n",
prussell 2:c77c2b06d604 121 str, array[0], array[1], array[2], array[3], array[4], array[5], array[6], array[7],
prussell 2:c77c2b06d604 122 array[8], array[9], array[10],array[11],array[12],array[13],array[14],array[15], array[15] );
prussell 2:c77c2b06d604 123
prussell 2:c77c2b06d604 124 return UUID(array);//TODO: Check if this array is safe or stack temporary??
prussell 2:c77c2b06d604 125 }
prussell 2:c77c2b06d604 126 //const UUID SCORING_GATT_SERVICE = stringToUUID("nod.score1.serv ");
prussell 2:c77c2b06d604 127 //const UUID THRESHOLD_GATT_CHARACTERISTIC = stringToUUID("nod.score1.thres");
prussell 2:c77c2b06d604 128 //const UUID DIVISOR_GATT_CHARACTERISTIC = stringToUUID("nod.score1.div ");
prussell 2:c77c2b06d604 129 //const UUID INTERVAL_US_GATT_CHARACTERISTIC = stringToUUID("nod.score1.intus");
prussell 2:c77c2b06d604 130 // Strings to hex UUID "0123456789ABCDEF"
prussell 2:c77c2b06d604 131 const UUID UUID_GATT_SERVICE_A = stringToUUID("com.test.servA");
prussell 2:c77c2b06d604 132 const UUID UUID_GATT_CHARACTERISTIC_A1 = stringToUUID("com.test.charA1");
prussell 2:c77c2b06d604 133 const UUID UUID_GATT_CHARACTERISTIC_A2 = stringToUUID("com.test.charA2");
prussell 2:c77c2b06d604 134 const UUID UUID_GATT_CHARACTERISTIC_SHORT = stringToUUID("com.short");
prussell 2:c77c2b06d604 135
prussell 0:0217a862b047 136 //==========Functions:Timer==========
prussell 0:0217a862b047 137 static volatile bool b_Ticker1 = false;//Volatile, don't optimize, changes under interrupt control
prussell 0:0217a862b047 138 void CallbackTicker1(void)
prussell 0:0217a862b047 139 {
prussell 0:0217a862b047 140 static uint32_t u32_Counter; // Counter for Debug Output
prussell 0:0217a862b047 141
prussell 0:0217a862b047 142 //pwm_led1 = !pwm_led1; /* Do blinky on LED1 while we're waiting for BLE events */
prussell 0:0217a862b047 143 f_led1level+=0.1; if (f_led1level>0.5){f_led1level = 0.1;}; pwm_led1=f_led1level;//PR: Ramp Blink
prussell 0:0217a862b047 144 DEBUG("\nBLEi: Ticker1(%u) ", ++u32_Counter);
prussell 0:0217a862b047 145 b_Ticker1 = true; //PR: Flag to handle Ticker1 Event in Main loop so interupts not blocked.
prussell 0:0217a862b047 146 }
prussell 0:0217a862b047 147
prussell 0:0217a862b047 148 //==========Functions:BLE==========
prussell 0:0217a862b047 149 void Callback_BLE_onTimeout(void)
prussell 0:0217a862b047 150 {
prussell 0:0217a862b047 151 DEBUG("\nBLEi: Callback_BLE_onTimeout()\n" );
prussell 0:0217a862b047 152 //PR: Haven't seen this, even when phone moved out of range and OnDisconnect(Reason0x08) occurs
prussell 0:0217a862b047 153
prussell 0:0217a862b047 154 //DEBUG("\nBLE:Callback_BLE_onTimeout(), Restarting Advertising\n" );
prussell 0:0217a862b047 155 //ble.startAdvertising();
prussell 0:0217a862b047 156 }
prussell 0:0217a862b047 157
prussell 0:0217a862b047 158 //void onDisconnection (Gap::DisconnectionEventCallback_t disconnectionCallback)
prussell 0:0217a862b047 159 void Callback_BLE_onDisconnect(Gap::Handle_t tHandle, Gap::DisconnectionReason_t eReason)
prussell 0:0217a862b047 160 {
prussell 0:0217a862b047 161 //PR: onDisconnect(Reason:8) occured after ~20Tx with no onDataSent() after phone moved out of range
prussell 0:0217a862b047 162
prussell 0:0217a862b047 163 // REMOTE_USER_TERMINATED_CONNECTION = 0x13 = 19,
prussell 0:0217a862b047 164 // LOCAL_HOST_TERMINATED_CONNECTION = 0x16 = 22,
prussell 0:0217a862b047 165 // CONN_INTERVAL_UNACCEPTABLE = 0x3B = 59,
prussell 0:0217a862b047 166 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 167
prussell 0:0217a862b047 168 //DEBUG("Wait10sec...\n");wait(10.0); //PR: Optional to test effect on advertising
prussell 0:0217a862b047 169 ble.startAdvertising(); // restart advertising
prussell 0:0217a862b047 170 }
prussell 0:0217a862b047 171
prussell 0:0217a862b047 172 //inline void BLEDevice::onConnection(Gap::ConnectionEventCallback_t connectionCallback){ transport->getGap().setOnConnection(connectionCallback);}
prussell 0:0217a862b047 173 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 174 {
prussell 0:0217a862b047 175 DEBUG("\nBLEi: Callback_BLE_Connect(Handle:%d, eType:%d, Add:%u ...)\n", tHandle, ePeerAddrType, c6PeerAddr);
prussell 0:0217a862b047 176
prussell 0:0217a862b047 177 #if UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL
prussell 0:0217a862b047 178 /* Updating connection parameters can be attempted only after a connection has been
prussell 0:0217a862b047 179 * established. Please note that the ble-Central is still the final arbiter for
prussell 0:0217a862b047 180 * the effective parameters; the peripheral can only hope that the request is
prussell 0:0217a862b047 181 * honored. Please also be mindful of the constraints that might be enforced by
prussell 0:0217a862b047 182 * the BLE stack on the underlying controller.*/
prussell 0:0217a862b047 183 #define MIN_CONN_INTERVAL 250 /**< Minimum connection interval (250 ms) */
prussell 0:0217a862b047 184 #define MAX_CONN_INTERVAL 350 /**< Maximum connection interval (350 ms). */
prussell 0:0217a862b047 185 #define CONN_SUP_TIMEOUT 6000 /**< Connection supervisory timeout (6 seconds). */
prussell 0:0217a862b047 186 #define SLAVE_LATENCY 4
prussell 0:0217a862b047 187
prussell 0:0217a862b047 188 Gap::ConnectionParams_t tGap_conn_params;
prussell 0:0217a862b047 189 tGap_conn_params.minConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(MIN_CONN_INTERVAL);
prussell 0:0217a862b047 190 tGap_conn_params.maxConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(MAX_CONN_INTERVAL);
prussell 0:0217a862b047 191 tGap_conn_params.connectionSupervisionTimeout = Gap::MSEC_TO_GAP_DURATION_UNITS(CONN_SUP_TIMEOUT);
prussell 0:0217a862b047 192 tGap_conn_params.slaveLatency = SLAVE_LATENCY;
prussell 0:0217a862b047 193 ble.updateConnectionParams(tHandle, &tGap_conn_params);
prussell 0:0217a862b047 194 #endif /* #if UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL */
prussell 0:0217a862b047 195 }
prussell 0:0217a862b047 196
prussell 0:0217a862b047 197 static volatile bool bSent = false; //Volatile, don't optimize, changes under interrupt control
prussell 0:0217a862b047 198 static volatile unsigned uSentBLE;
prussell 0:0217a862b047 199 void Callback_BLE_onDataSent(unsigned uSent){
prussell 0:0217a862b047 200 uSentBLE=uSent;
prussell 1:4a25d917fb6a 201 DEBUG("BLEi: SentI(%u)", uSent); //TODO: PR: Why uSent always "1", expected it to match sent bytes length
prussell 0:0217a862b047 202 bSent = true;
prussell 0:0217a862b047 203 //PR: onDataSent() maybe only occuring when confirmed receive by phone, as onDataSent() didn't happen when phone moved out of range.
prussell 0:0217a862b047 204 }
prussell 0:0217a862b047 205
prussell 0:0217a862b047 206 void Callback_BLE_onDataWritten(const GattCharacteristicWriteCBParams *pParams)
prussell 0:0217a862b047 207 {
prussell 0:0217a862b047 208 // Callback_BLE_onDataWritten == This does occur when use nRF-MCP to save New Heart Rate Control Point (Ignored if incorrect length)
prussell 0:0217a862b047 209
prussell 0:0217a862b047 210 //Warning: *data may not be NULL terminated
prussell 0:0217a862b047 211 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 0:0217a862b047 212 }
prussell 0:0217a862b047 213
prussell 0:0217a862b047 214 void Callback_BLE_onUpdatesEnabled(Gap::Handle_t tHandle)
prussell 0:0217a862b047 215 {
prussell 0:0217a862b047 216 DEBUG("\nBLEi: Callback_BLE_onUpdates(Handle:%d)\r\n", tHandle);
prussell 0:0217a862b047 217 }
prussell 0:0217a862b047 218
prussell 0:0217a862b047 219 //==========main==========
prussell 0:0217a862b047 220 int main(void)
prussell 0:0217a862b047 221 {
prussell 0:0217a862b047 222 f_led1level = 1; pwm_led1 = f_led1level;//Start LED1=OnMax
prussell 0:0217a862b047 223 f_led2level = 1; pwm_led2 = f_led2level;//Start LED2=OnMax
prussell 1:4a25d917fb6a 224 DEBUG("\nBLE: ___%s___\n", pcDeviceName); //Restart TeraTerm just before Pressing Reset on mbed
prussell 1:4a25d917fb6a 225 DEBUG("BLE: Connect App for Data: nRF-MCP, nRF-Toolbox:HRM, etc.\n");
prussell 0:0217a862b047 226
prussell 0:0217a862b047 227 Ticker ticker1; //PR: Timer Object(Structure)
prussell 0:0217a862b047 228 ticker1.attach(CallbackTicker1, 2.0); //PR: Timer Handler, Float=PeriodSeconds
prussell 0:0217a862b047 229
prussell 3:a98203f84063 230 //BLE1: Setup BLE Service (and event actions) //TODO: Check for services declared before main() - Is that OK?
prussell 3:a98203f84063 231 DEBUG("BLE: Setup BLE\n");
prussell 0:0217a862b047 232 ble.init();
prussell 0:0217a862b047 233 ble.onDisconnection(Callback_BLE_onDisconnect);
prussell 0:0217a862b047 234 ble.onConnection(Callback_BLE_onConnect); //PR: Not required if no actions enabled, enabled now just for debug printf()
prussell 0:0217a862b047 235 ble.onDataSent(Callback_BLE_onDataSent);
prussell 0:0217a862b047 236 ble.onDataWritten(Callback_BLE_onDataWritten);
prussell 0:0217a862b047 237 ble.onTimeout(Callback_BLE_onTimeout);
prussell 0:0217a862b047 238 ble.onUpdatesEnabled(Callback_BLE_onUpdatesEnabled);
prussell 0:0217a862b047 239
prussell 0:0217a862b047 240 //ble_error_t readCharacteristicValue ( uint16_t handle, uint8_t *const buffer, uint16_t *const lengthP )
prussell 0:0217a862b047 241 //ble_error_t updateCharacteristicValue (uint16_t handle, const uint8_t *value, uint16_t size, bool localOnly=false)
prussell 0:0217a862b047 242
prussell 4:976394791d7a 243 //UUID List by Services that are setup
prussell 3:a98203f84063 244 //BLE2: Setup Services
prussell 3:a98203f84063 245 DEBUG("BLE: Setup Services\n");
prussell 4:976394791d7a 246 // *Order here affects order in nRF-MCP Discovery of Services
prussell 3:a98203f84063 247 HealthThermometerService htmService(ble, 30.0, HealthThermometerService::LOCATION_EAR);
prussell 3:a98203f84063 248 BatteryService battService(ble, 11);//Declare the service for BLE:BATTERY
prussell 4:976394791d7a 249 HeartRateService hrmService(ble, (uint8_t)111, HeartRateService::LOCATION_FINGER);
prussell 4:976394791d7a 250 DeviceInformationService deviceInfo(ble, "Maker", pcDeviceName, "sn1234", "hw00", "fw00", "sw00");//(BLEDevice), pcManufacturer, pcModelNumber, pcSerialNumber, pcHWver, pcFWver, pcSWver
prussell 4:976394791d7a 251
prussell 3:a98203f84063 252 //BLE3: Setup advertising
prussell 3:a98203f84063 253 DEBUG("BLE: Setup Advertising\n");
prussell 0:0217a862b047 254 ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); //PR: Advertise 1sec (1Hz)
prussell 0:0217a862b047 255 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //PR: TODO
prussell 0:0217a862b047 256 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); //PR: BLE Only, Options(LE_GENERAL_DISCOVERABLE/LE_LIMITED_DISCOVERABLE)
prussell 3:a98203f84063 257
prussell 3:a98203f84063 258 //UUID List by Advertised 16bit UUID list (PartB)
prussell 0:0217a862b047 259 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); //PR: Might need to change for Custom Services/Characteristics
prussell 3:a98203f84063 260
prussell 3:a98203f84063 261 ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);//PR: Add Heart Rate
prussell 3:a98203f84063 262 ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER); //PR: Add Thermometer
prussell 0:0217a862b047 263 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)pcDeviceName, sizeof(pcDeviceName));//PR: Product?
prussell 3:a98203f84063 264 //Thermometer: ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
prussell 3:a98203f84063 265 //Thermometer: ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
prussell 0:0217a862b047 266 ble.startAdvertising();
prussell 0:0217a862b047 267
prussell 0:0217a862b047 268 DEBUG("BLE: Main Loop\n");
prussell 0:0217a862b047 269 uint32_t u32_wakeevents=0, u32_wakelast=0; // Counter&Register for tracking Wake Events (to see monitor their Frequency)
prussell 0:0217a862b047 270 while (true) {
prussell 0:0217a862b047 271 if (b_Ticker1 && ble.getGapState().connected) { //If Ticker1 and Connected Update Data
prussell 0:0217a862b047 272 b_Ticker1 = false; // Clear flag for next Ticker1, see CallbackTicker1()
prussell 3:a98203f84063 273
prussell 3:a98203f84063 274 // Read Sensors, and update matching Service Characteristics (only if connected)
prussell 4:976394791d7a 275 // *Order here doesn't affect order in nRF-MCP Discovery of Services
prussell 4:976394791d7a 276 float update_htm(void); //prototype
prussell 3:a98203f84063 277 uint8_t update_hrm(void); //prototype
prussell 3:a98203f84063 278 uint8_t update_batt(void);//prototype
prussell 4:976394791d7a 279 htmService.updateTemperature( update_htm() );
prussell 3:a98203f84063 280 hrmService.updateHeartRate( update_hrm() );
prussell 3:a98203f84063 281 battService.updateBatteryLevel( update_batt() );
prussell 3:a98203f84063 282
prussell 3:a98203f84063 283 DEBUG("BLE: Wakes:%u Delta:%d ", u32_wakeevents, u32_wakeevents-u32_wakelast); //For Evaluating Timing
prussell 3:a98203f84063 284 u32_wakelast = u32_wakeevents;
prussell 0:0217a862b047 285 } else if (b_Ticker1) {
prussell 0:0217a862b047 286 b_Ticker1 = false; // Clear flag for next Ticker1, see CallbackTicker1()
prussell 3:a98203f84063 287 DEBUG("BLE: Tick while unconnected ");
prussell 0:0217a862b047 288 } else if (bSent){
prussell 0:0217a862b047 289 bSent=false; //clear flag
prussell 3:a98203f84063 290 //DEBUG("BLE: Sent %ubytes ", uSentBLE);
prussell 0:0217a862b047 291 } else {
prussell 3:a98203f84063 292 //DEBUG("BLE: Wait for Event\n\r"); //x Debug output here causes unnecessary wakes resulting in endless awakes.
prussell 0:0217a862b047 293 ble.waitForEvent(); //PR: Wait for event - Yield control to BLE Stack and other events (Process ALL pending events before waiting again)
prussell 0:0217a862b047 294 f_led2level+=0.25; if (f_led2level>0.5){f_led2level = 0.0;}; pwm_led2=f_led2level;//PR: Ramp Blink
prussell 0:0217a862b047 295 u32_wakeevents++; //PR: Count events for frequency monitoring (20141207PR: nRF51822 mbed HRM = 50Hz)
prussell 0:0217a862b047 296 }
prussell 0:0217a862b047 297 }
prussell 0:0217a862b047 298 }
prussell 3:a98203f84063 299
prussell 3:a98203f84063 300 //==========HRM==========
prussell 3:a98203f84063 301 //Adopted 2014Dec from http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/
prussell 3:a98203f84063 302 uint8_t update_hrm(void)//(bool bInit)
prussell 3:a98203f84063 303 {
prussell 3:a98203f84063 304 static uint8_t u8_hrm = 100;
prussell 3:a98203f84063 305 u8_hrm++;
prussell 3:a98203f84063 306 if (u8_hrm >= 175) {
prussell 3:a98203f84063 307 u8_hrm = 100;
prussell 3:a98203f84063 308 DEBUG("BLE: HRM Rollover175->100 ");
prussell 3:a98203f84063 309 }
prussell 3:a98203f84063 310 DEBUG("[HRM:%d]", u8_hrm);
prussell 3:a98203f84063 311 return(u8_hrm);
prussell 3:a98203f84063 312 }
prussell 3:a98203f84063 313 //==========HTM:Internal Temperature==========
prussell 3:a98203f84063 314 //Adopted 2014Dec from: https://developer.mbed.org/users/takafuminaka/code/BLE_HTM_by_InTempSensr/
prussell 3:a98203f84063 315 // Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.health_thermometer.xml
prussell 3:a98203f84063 316 // HTM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml
prussell 3:a98203f84063 317
prussell 3:a98203f84063 318 //****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 3:a98203f84063 319 float update_htm(void)
prussell 3:a98203f84063 320 {
prussell 3:a98203f84063 321 //static float fTemperature = 0;//-123.456;
prussell 3:a98203f84063 322 int32_t i32_temp;
prussell 3:a98203f84063 323 sd_temp_get(&i32_temp); //Read the nRF Internal Temperature (Die in 0.25'C steps, Counting From TBD), TODO:Check Scaling
prussell 3:a98203f84063 324 float fTemperature = (float(i32_temp)/4.0) - 16.0; // Scale&Shift (0.25'C from -16'C?)
prussell 3:a98203f84063 325 DEBUG("[HTMi:%d HTMf:%f]", i32_temp, fTemperature);
prussell 4:976394791d7a 326
prussell 4:976394791d7a 327 //{//Force to IEEE format to match needs of Apps like nRF-HTM and nRF-Toolbox:HTM
prussell 4:976394791d7a 328 // PR: Didn't work 20141213, might need more of style from BLE_HTM_by_InTempSensr if this is really necessary. OK in nRF-MCP for now.
prussell 4:976394791d7a 329 // uint8_t exponent = 0xFE; //exponent is -2
prussell 4:976394791d7a 330 // uint32_t mantissa = (uint32_t)(fTemperature*100);
prussell 4:976394791d7a 331 // uint32_t temp_ieee11073 = ((((uint32_t)exponent) << 24) | (mantissa)); //Note: Assumes Mantissa within 24bits
prussell 4:976394791d7a 332 // memcpy(((uint8_t*)&fTemperature)+1, (uint8_t*)&temp_ieee11073, 4); //Overwrite with IEEE format float
prussell 4:976394791d7a 333 //}
prussell 4:976394791d7a 334
prussell 3:a98203f84063 335 return(fTemperature);
prussell 3:a98203f84063 336 }
prussell 3:a98203f84063 337 //==========Battery==========
prussell 3:a98203f84063 338 uint8_t update_batt(void)
prussell 3:a98203f84063 339 {
prussell 3:a98203f84063 340 static uint8_t u8_BattPercent=33; //Level: 0..100%
prussell 3:a98203f84063 341 u8_BattPercent <= 50 ? u8_BattPercent=100 : u8_BattPercent--; // Simulate Battery Decay
prussell 3:a98203f84063 342 DEBUG("[BATT:%d%%]", u8_BattPercent);
prussell 3:a98203f84063 343 return(u8_BattPercent);
prussell 3:a98203f84063 344 }
prussell 3:a98203f84063 345 //========== end ==========